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.