This is Klondike.m in view mode; [Download] [Up]
#import "Klondike.h" #import "DrawPileDelegate.h" #import "GamePileDelegate.h" #import "SuitPileDelegate.h" #import "DiscardPileDelegate.h" #define KL_BETAMOUNT 52 #define KL_CARDVALUE 5 #define KL_NAMEFORPREFS "NVKlondike" @implementation Klondike /*************************************************************************************** * Module Methods * ***************************************************************************************/ + initialize { static NXDefaultsVector ourDefaults = { {"numToDraw", "3"}, {NULL, NULL} }; NXRegisterDefaults(KL_NAMEFORPREFS, ourDefaults); return self; } - awakeFromNib /* Sent to every object instantiated in a nib file. A good place to perform some initialization... */ { int i; // This may take a while, so lets inform the user [self say:"Pre-Drawing Cards..."]; NXPing(); [Card drawCardImages]; [self say:"Setting up preferences..."]; NXPing(); [self revertPreferences:self]; [self say:"Initializing Table..."]; NXPing(); [self enableDealButton]; [amountBetText setIntValue:KL_BETAMOUNT]; [amountWonText setIntValue:0]; [totalWonText setIntValue:0]; bank = 0; gameCardPileViews[0] = gamePileView1; gameCardPileViews[1] = gamePileView2; gameCardPileViews[2] = gamePileView3; gameCardPileViews[3] = gamePileView4; gameCardPileViews[4] = gamePileView5; gameCardPileViews[5] = gamePileView6; gameCardPileViews[6] = gamePileView7; suitCardPileViews[0] = suitPileView1; suitCardPileViews[1] = suitPileView2; suitCardPileViews[2] = suitPileView3; suitCardPileViews[3] = suitPileView4; for(i=0; i<4; i++) { [[[suitCardPileViews[i] setCoversOthers:YES] setDrawOutline:NO] resetBacking:self]; } for(i=0; i<7; i++) { [[[gameCardPileViews[i] setCoversOthers:YES] setDrawOutline:NO] resetBacking:self]; } [[[drawPileView setCoversOthers:YES] setDrawOutline:NO] resetBacking:self]; [[[discardPileView setCoversOthers:YES] setDrawOutline:NO] resetBacking:self]; gameInProgress = NO; [self say:""]; return self; } /*--------------------------------------------------------------------------- | | - startGame: | | returns: (id) self | |---------------------------------------------------------------------------- | | Start a new game. | \----------------------------------------------------------------------------*/ - startGame:sender { return [self setupGame:YES]; } /*--------------------------------------------------------------------------- | | - restartGame: | | returns: (id) self | |---------------------------------------------------------------------------- | | Restart the game in progress (i.e. don't shuffle the cards). | \----------------------------------------------------------------------------*/ - 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, cardIndex , i; id suitCardPiles[4]; id gameCardPiles[7]; id drawCardPile; int numToDraw = [[drawPref selectedCell] tag]; int amountToBet; char buf[128]; gameInProgress = YES; [suitPileDelegate setEnabled:YES]; [drawPileDelegate setEnabled:YES]; [gamePileDelegate setEnabled:YES]; [discardPileDelegate setEnabled:YES]; sprintf(buf, "New 'Draw %s' game...", (numToDraw == 1) ? "One" : "Three"); [self say:buf]; bank = [totalWonText intValue]; amountToBet = bank - KL_BETAMOUNT; [amountBetText setIntValue:KL_BETAMOUNT]; [amountWonText setIntValue:0]; if(bank >= KL_BETAMOUNT) { bank -= KL_BETAMOUNT; } else if(bank > 0) { amountToBet = KL_BETAMOUNT - bank; bank = 0; [[PBoss() currentPlayer] removeChip:amountToBet]; } else { [[PBoss() currentPlayer] removeChip:KL_BETAMOUNT]; } [totalWonText setIntValue:bank]; if(numToDraw == KL_DRAWONE) //[[drawPileDelegate setMaxPasses:KL_MINPASS] setDrawCardCount:numToDraw]; [[drawPileDelegate setMaxPasses:numToDraw] setDrawCardCount:numToDraw]; else [[drawPileDelegate setMaxPasses:numToDraw] setDrawCardCount:numToDraw]; //[[drawPileDelegate setMaxPasses:KL_INFINITEPASS] setDrawCardCount:numToDraw]; [discardPileDelegate setDrawCardCount:numToDraw]; //---------------------------------------------------------------- // Sync pile id's with current game window and set // preferences and delegates //---------------------------------------------------------------- suitCardPiles[0] = suitPileView1; suitCardPiles[1] = suitPileView2; suitCardPiles[2] = suitPileView3; suitCardPiles[3] = suitPileView4; for (i = 0; i < 4; i++) { // [suitCardPiles[i] setBackgroundColor:desktopColor]; [suitCardPiles[i] setCardSize:CS_SMALL]; } gameCardPiles[0] = gamePileView1; gameCardPiles[1] = gamePileView2; gameCardPiles[2] = gamePileView3; gameCardPiles[3] = gamePileView4; gameCardPiles[4] = gamePileView5; gameCardPiles[5] = gamePileView6; gameCardPiles[6] = gamePileView7; for (i = 0; i < 7; i++) { //[gameCardPiles[i] setBackgroundColor:desktopColor]; [gameCardPiles[i] setCardSize:CS_SMALL]; } [gamePileDelegate setSuitCardPileViews:suitCardPiles]; //[drawPileView setBackgroundColor:desktopColor]; [drawPileView setCardSize:CS_SMALL]; drawCardPile = [drawPileView cardPile]; [drawPileDelegate setDiscardCardPileView:discardPileView]; //[discardPileView setBackgroundColor:desktopColor]; [discardPileView setCardSize:CS_SMALL]; //[discardPileView setDelegate:discardPileDelegate]; [discardPileDelegate setSuitCardPileViews:suitCardPiles]; //----------------------------------------------------------------------- // Empty the recycle pile //----------------------------------------------------------------------- [recycleCardPile freeCards]; //----------------------------------------------------------------------- // Initialize the drawPileView to have a shuffled // deck //----------------------------------------------------------------------- [drawCardPile freeCards]; if (redeal) { [[drawCardPile addDeck] shuffle]; // make a copy of the CardPile for restart option if (!prevDeck) { prevDeck = [[CardPile allocFromZone:[self zone]] initForCardSize:CS_SMALL]; } else { [prevDeck freeCards]; [prevDeck setCardSize:CS_SMALL]; } [prevDeck addCopyOfPile:drawCardPile]; } else { if (prevDeck) { // copy the saved deck back to the game deck [prevDeck setCardSize:CS_SMALL]; [drawCardPile addCopyOfPile:prevDeck]; } else { // this shouldn't happen, but just in case... [[[drawCardPile freeCards] addDeck] shuffle]; } } //---------------------------------------------------------------------- // Initialize the discardPileView as empty //---------------------------------------------------------------------- [[discardPileView cardPile] freeCards]; [discardPileView display]; //----------------------------------------------------------------------- // Initialize the four "suit piles" as empty //----------------------------------------------------------------------- for (pileIndex = 0; pileIndex < 4; pileIndex++) { [[suitCardPiles[pileIndex] cardPile] freeCards]; [suitCardPiles[pileIndex] display]; } //----------------------------------------------------------------------- // Initialize and deal cards to the seven "user piles" //----------------------------------------------------------------------- for (pileIndex = 0; pileIndex < 7; pileIndex++) { id userPile = [gameCardPiles[pileIndex] cardPile]; [userPile freeCards]; [gameCardPiles[pileIndex] display]; } for (pileIndex = 0; pileIndex < 7; pileIndex++) { id userPile = [gameCardPiles[pileIndex] cardPile]; for (cardIndex = 0; cardIndex <= pileIndex; cardIndex++) { id tempCard = [drawCardPile cardAt:CS_TOP]; [drawCardPile removeCard:tempCard]; [userPile insertCard:tempCard at:CS_TOP]; [gameCardPiles[pileIndex] display]; } [[userPile cardAt:CS_TOP] flip]; [gameCardPiles[pileIndex] display]; //[PBoss() playSound:NV_CARDSOUND]; //NXPing(); } //----------------------------------------------------------------------- // Draw the remaining cards on the // drawPileView //----------------------------------------------------------------------- [drawPileView display]; return self; } /*--------------------------------------------------------------------------- | | - checkForWin | | returns: (id) self | |---------------------------------------------------------------------------- | | Called to check the state of the game. | \----------------------------------------------------------------------------*/ - checkForWin { int collected = [self totalCollected]; int won = (collected * KL_CARDVALUE); [amountWonText setIntValue:collected]; //if(won > [amountBetText intValue]) [totalWonText setIntValue:won+bank]; if ([[suitPileView1 cardPile] cardCount] + [[suitPileView2 cardPile] cardCount] + [[suitPileView3 cardPile] cardCount] + [[suitPileView4 cardPile] cardCount] == 52) { [self win]; } return self; } - win { [self say:"Winner!!!"]; [PBoss() playSound:NV_WINSOUND]; [suitPileDelegate setEnabled:NO]; [drawPileDelegate setEnabled:NO]; [gamePileDelegate setEnabled:NO]; [discardPileDelegate setEnabled:NO]; return self; } - enableDealButton { if([PBoss() currentPlayer]) [dealButton setEnabled:YES]; else [dealButton setEnabled:NO]; return self; } - (int)totalCollected /* Returns the total of all the cards in all the suit piles */ { int amount = [[suitPileView1 cardPile] cardCount] + [[suitPileView2 cardPile] cardCount] + [[suitPileView3 cardPile] cardCount] + [[suitPileView4 cardPile] cardCount]; return amount; } - endGame { //NXRunAlertPanel("Klondike", "The Game Is Over.", "Okay", NULL, NULL); [self say:"End of Game. Keep playing until you collect, or press 'New Deal' to start over."]; gameInProgress = NO; return self; } - findHomeFor:cardPile fromPileView:aCardPileView /* * First searches the suit piles to see if the card can go their, then searches * the game piles. If it finds a home, it returns the view that the card can be * moved to. */ { int i; for (i=0;i<4;i++) { [[suitCardPileViews[i] delegate] setDoubleClickCheck]; if ([[suitCardPileViews[i] delegate] canAcceptPile:cardPile from:aCardPileView in:suitCardPileViews[i]]) { return suitCardPileViews[i]; } } for(i=0; i<7; i++) { if([[gameCardPileViews[i] delegate] canAcceptPile:cardPile from:aCardPileView in:gameCardPileViews[i]] && gameCardPileViews[i] != aCardPileView) { return gameCardPileViews[i]; } } return nil; } /*************************************************************************************** * Inspector And Rules Methods * ***************************************************************************************/ - (BOOL)hasRules { return YES; } - revertPreferences:sender { int numToDraw = atoi(NXGetDefaultValue(KL_NAMEFORPREFS, "numToDraw")); [drawPref selectCellWithTag:numToDraw]; return self; } - setPreferences:sender { static NXDefaultsVector newDefaults = { {"numToDraw", "3"}, {NULL, NULL} }; int numToDraw = [[drawPref selectedCell] tag]; newDefaults[0].value = alloca(256); sprintf(newDefaults[0].value, "%d", numToDraw); NXWriteDefaults(KL_NAMEFORPREFS, newDefaults); return self; } /*************************************************************************************** * Player Methods * ***************************************************************************************/ - (int)collectAllBetsForPlayer:(int)playerNum { int amountWon = [totalWonText intValue]; if(gameInProgress) { [self endGame]; [suitPileDelegate setEnabled:NO]; [drawPileDelegate setEnabled:NO]; [gamePileDelegate setEnabled:NO]; [discardPileDelegate setEnabled:NO]; } [self say:"Game Over. Press 'New Deal' to start a new game."]; if(amountWon > 0) { [totalWonText setIntValue:0]; [amountWonText setIntValue:0]; bank = 0; return amountWon; } return 0; } - playerDidClose:aPlayer /* * Sent after a player has closed and is no longer part of the game. No messages * should be sent to aPlayer. This method should just do some internal cleanup * if necessary. */ { [self enableDealButton]; return self; } - playerDidJoin:player { [self enableDealButton]; return self; } /*************************************************************************************** * Table Methods * ***************************************************************************************/ - view:aView wasLoadedOnTable:tableObject { table = tableObject; [self say:"Welcome to Klondike!!! Press 'New Deal' to start a new game."]; return self; } /*************************************************************************************** * Other Misc. Methods * ***************************************************************************************/ - finishSessionAndClose /* This message is sent when a new game is being loaded. If there is any clean up to do, this is where to do it. */ { return self; } @end @implementation Klondike(BetViewDelegate) - player:aPlayer willBet:(int)betType onView:aBetView { return self; } - (BOOL)playerWillDragChipAtRow:(int)row andCol:(int)col fromView:sender /* Sent by a BetView when a player wishes to drag a chip pile. Overwrite this method to return YES if your module will allow drag and drop. */ { return NO; } - playerDraggedChipAtRow:(int)row andCol:(int)col fromView:sender /* Sent by a BetView after a player drags a chip pile. */ { return self; } - (BOOL)playerWillDropChipAtRow:(int *)row andCol:(int *)col InView:sender /* Sent by a BetView when a player wants to drop a chip pile on it. Over write this method to return YES if your module allows drag and drop. */ { return NO; } - playerDroppedChipAtRow:(int)row andCol:(int)col inView:sender /* Sent by a BetView when a player drops a chip on it. Overwrite this method to add the pile to the betview. Check out the blackjack module to see how this is done. */ { return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.