This is Pyramid.m in view mode; [Download] [Up]
/* indent:4 tabsize:8 font:fixed-width */ #import "Pyramid.h" #import "PyramidPrefs.h" #import "DiscardCardPileDelegate.h" #import "GameCardPileDelegate.h" #import "StockCardPileDelegate.h" #import "WasteCardPileDelegate.h" #import "localstrings.h" @implementation Pyramid /*--------------------------------------------------------------------------- | | - startGame: | | returns: (id) self | |---------------------------------------------------------------------------- | | Start a new game. Get confirmation from the user before aborting a | game in progress. | \----------------------------------------------------------------------------*/ - startGame:sender { if (gameInProgress) [self determineScore]; [super startGame:sender]; return [self setupGame:YES]; } /*--------------------------------------------------------------------------- | | - restartGame: | | returns: (id) self | |---------------------------------------------------------------------------- | | Restart the game in progress. | \----------------------------------------------------------------------------*/ - restartGame:sender { if (gameInProgress) [self determineScore]; [super restartGame:sender]; return [self setupGame:NO]; } /*--------------------------------------------------------------------------- | | - setupGame:(BOOL)redeal | | returns: (id) self | |---------------------------------------------------------------------------- | | Setup a new game. If "redeal" is true, deal a new deck, otherwise | use the same cards as the previous game. | \----------------------------------------------------------------------------*/ - setupGame:(BOOL)redeal { int pileIndex; id stockCardPile = [stockCardPileView cardPile]; [gameWindow disableFlushWindow]; [self setDealCount:1]; pyramidEmpty = NO; //---------------------------------------------------------------- // Sync pile id's with current game window and set // preferences and delegates //---------------------------------------------------------------- gameCardPiles[0] = gamePileView1; gameCardPiles[1] = gamePileView2; gameCardPiles[2] = gamePileView3; gameCardPiles[3] = gamePileView4; gameCardPiles[4] = gamePileView5; gameCardPiles[5] = gamePileView6; gameCardPiles[6] = gamePileView7; gameCardPiles[7] = gamePileView8; gameCardPiles[8] = gamePileView9; gameCardPiles[9] = gamePileView10; gameCardPiles[10] = gamePileView11; gameCardPiles[11] = gamePileView12; gameCardPiles[12] = gamePileView13; gameCardPiles[13] = gamePileView14; gameCardPiles[14] = gamePileView15; gameCardPiles[15] = gamePileView16; gameCardPiles[16] = gamePileView17; gameCardPiles[17] = gamePileView18; gameCardPiles[18] = gamePileView19; gameCardPiles[19] = gamePileView20; gameCardPiles[20] = gamePileView21; gameCardPiles[21] = gamePileView22; gameCardPiles[22] = gamePileView23; gameCardPiles[23] = gamePileView24; gameCardPiles[24] = gamePileView25; gameCardPiles[25] = gamePileView26; gameCardPiles[26] = gamePileView27; gameCardPiles[27] = gamePileView28; [stockCardPileView setBackgroundColor:desktopColor]; [stockCardPileView setCardSize:cardSize]; [stockCardPileView setDelegate:stockDelegate]; [wasteCardPileView setBackgroundColor:desktopColor]; [wasteCardPileView setCardSize:cardSize]; [wasteCardPileView setDelegate:wasteDelegate]; [discardCardPileViewL setBackgroundColor:desktopColor]; [discardCardPileViewL setCardSize:cardSize]; [discardCardPileViewL setDelegate:discardDelegate]; [discardCardPileViewR setBackgroundColor:desktopColor]; [discardCardPileViewR setCardSize:cardSize]; [discardCardPileViewR setDelegate:discardDelegate]; [stockDelegate setDiscardLeft:discardCardPileViewL discardRight:discardCardPileViewR waste:wasteCardPileView]; [gameDelegate setDiscardLeft:discardCardPileViewL discardRight:discardCardPileViewR]; [wasteDelegate setDiscardLeft:discardCardPileViewL discardRight:discardCardPileViewR]; [gameWindow display]; [gameWindow reenableFlushWindow]; [gameWindow flushWindow]; /*----------------------------------------------------------------------- * Initialize the stockCardPileView to have a shuffled deck. *---------------------------------------------------------------------*/ [stockCardPile freeCards]; if (redeal) { [[stockCardPile addDeck] shuffle]; // make a copy of the CardPile for restart option if (!prevDeck) { prevDeck = [[CardPile allocFromZone:[self zone]] initForCardSize:cardSize]; } else { [prevDeck freeCards]; [prevDeck setCardSize:cardSize]; } [prevDeck addCopyOfPile:stockCardPile]; } else { if (prevDeck) { // copy the saved deck back to the game deck [prevDeck setCardSize:cardSize]; [stockCardPile addCopyOfPile:prevDeck]; } else { // this shouldn't happen, but just in case... [[[stockCardPile freeCards] addDeck] shuffle]; } } /*----------------------------------------------------------------------- * Initialize the other piles as empty. *---------------------------------------------------------------------*/ [[wasteCardPileView cardPile] freeCards]; [[discardCardPileViewL cardPile] freeCards]; [[discardCardPileViewR cardPile] freeCards]; [wasteCardPileView display]; [discardCardPileViewL display]; [discardCardPileViewR display]; /*----------------------------------------------------------------------- * Remove the remaining gameCardPileViews from the view * hierarchy so they can be put back in correct order. * As cards are removed from the Pyramid during game play, the * Pyramid cardPileViews are removed from the view hierarchy to * allow access to the piles underneath. *---------------------------------------------------------------------*/ for (pileIndex = 0; pileIndex < 28; pileIndex++) { if ([gameCardPiles[pileIndex] superview]) [gameCardPiles[pileIndex] removeFromSuperview]; } /*----------------------------------------------------------------------- * Set the attributes of the pyramid cardpiles *---------------------------------------------------------------------*/ for (pileIndex = 0; pileIndex < 28; pileIndex++) { [gameCardPiles[pileIndex] setDelegate:gameDelegate]; [gameCardPiles[pileIndex] setBackgroundColor:desktopColor]; [gameCardPiles[pileIndex] setCardSize:cardSize]; [gameCardPiles[pileIndex] setDelegate:gameDelegate]; [gameCardPiles[pileIndex] setDrawOutline:NO]; [gameCardPiles[pileIndex] resetBacking:self]; if (pileIndex > 0) [gameCardPiles[pileIndex] setCoversOthers:YES]; } /*----------------------------------------------------------------------- * Initialize and deal cards to the 28 "game piles" *---------------------------------------------------------------------*/ for (pileIndex = 0; pileIndex < 28; pileIndex++) { id userPile, tempCard; /*------------------------------------------------------------------- * Reinsert the game pile view in the proper hierachy. * The views are unlinked during game play. *-----------------------------------------------------------------*/ [[stockCardPileView superview] addSubview:gameCardPiles[pileIndex]]; /*------------------------------------------------------------------- * Deal the cards. *-----------------------------------------------------------------*/ userPile = [gameCardPiles[pileIndex] cardPile]; [userPile freeCards]; tempCard = [stockCardPile cardAt:CS_TOP]; [stockCardPile removeCard:tempCard]; [userPile insertCard:tempCard at:CS_TOP]; [[userPile cardAt:CS_TOP] flip]; } /*----------------------------------------------------------------------- * Update all views, then display the window. *---------------------------------------------------------------------*/ [gameWindow display]; [gameWindow makeKeyAndOrderFront:self]; return self; } /*--------------------------------------------------------------------------- | | - endGame:sender | | returns: (id) self | |---------------------------------------------------------------------------- | | End the game in progress. Discard the game window. | \----------------------------------------------------------------------------*/ - endGame:sender { if (gameInProgress) { [self determineScore]; gameInProgress = NO; } // close the game window [super endGame:sender]; return self; } /*--------------------------------------------------------------------------- | | - win | | returns: (id) self | |---------------------------------------------------------------------------- | | Called when the game has been won. This is where you can insert fancy | winning routines, or just call the default (boring) routine. | \----------------------------------------------------------------------------*/ - win { [super win]; // replace this with something wonderful return self; } /*--------------------------------------------------------------------------- | | - checkForWin | | returns: (id) self | |---------------------------------------------------------------------------- | | Called to check the state of the game. Always override (unless your | game is impossible to win). This is ugly because it handles winning | and keeping track of the score. | \----------------------------------------------------------------------------*/ - checkForWin { int i, j; int total; id viewList = [[gameWindow contentView] subviews]; BOOL didMatch; total = [viewList count]; /*----------------------------------------------------------------------- * * Points for clearing the pyramid... * *---------------------------------------------------------------------*/ for (j = 0, didMatch = NO; j < total && !pyramidEmpty && !didMatch; j++) { id theView = [viewList objectAt:j]; for (i = 0; i < 28 && !didMatch; i++) { if (theView == gameCardPiles[i]) didMatch = YES; } } if (!didMatch && !pyramidEmpty) { switch ([self dealCount]) { case 1: [prefs setPyramidScore:[prefs pyramidScore] + 50]; break; case 2: [prefs setPyramidScore:[prefs pyramidScore] + 35]; break; case 3: [prefs setPyramidScore:[prefs pyramidScore] + 20]; break; default: break; } pyramidEmpty = YES; } /*----------------------------------------------------------------------- * * Cleared everything; you win. * *---------------------------------------------------------------------*/ if ([[discardCardPileViewL cardPile] cardCount] + [[discardCardPileViewR cardPile] cardCount] == 52) { [self win]; gameInProgress = NO; return self; } /*----------------------------------------------------------------------- * * If the stock pile is empty and we have used both redeals AND the * pyramid is empty, then it's time to count the remaining cards. * *---------------------------------------------------------------------*/ if (pyramidEmpty && [[stockCardPileView cardPile] cardCount] == 0 && [self dealCount] == 3) { [self determineScore]; gameInProgress = NO; return self; } gameInProgress = YES; return self; } /*--------------------------------------------------------------------------- | | - (int)dealCount | | returns: (int) the number of deals so far (1, 2, 3, ...) | |---------------------------------------------------------------------------- | | The deal count is incremented everytime the deck is flipped. | \----------------------------------------------------------------------------*/ - (int)dealCount { return dealCount; } /*--------------------------------------------------------------------------- | | - setDealCount:(int)count | | returns: (id) self | |---------------------------------------------------------------------------- | | Set the deal count. This is the number of passes through the stock. \----------------------------------------------------------------------------*/ - setDealCount:(int)count { dealCount = count; return self; } /*--------------------------------------------------------------------------- | | - incDealCount | | returns: (id) self | |---------------------------------------------------------------------------- | | Add one to the deal count. | \----------------------------------------------------------------------------*/ - incDealCount { dealCount++; return self; } /*--------------------------------------------------------------------------- | | - determineScore | | returns: (id) self | |---------------------------------------------------------------------------- | | Subtract the remaining cards from the current score. | \----------------------------------------------------------------------------*/ - determineScore { int i; int total = 0; for (i = 0; i < 28; i++) { total += [[gameCardPiles[i] cardPile] cardCount]; } total += [[stockCardPileView cardPile] cardCount]; total += [[wasteCardPileView cardPile] cardCount]; [prefs setPyramidScore:[prefs pyramidScore] - total]; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.