This is RedDog.m in view mode; [Download] [Up]
#import "RedDog.h" #import "../NEXTVegas/CardSet.subproj/cardset.h" #define RD_DRAWPAUSE 200000 #define RD_LONGPAUSE 999999 #define RD_LEFTPILE 1 #define RD_RIGHTPILE 3 #define RD_MIDDLEPILE 2 #define RD_DECKPILE 0 #define RD_WINNER 1 #define RD_LOSER 0 #define RD_BEFOREDEAL 2 #define RD_BEFORETHIRD 3 #define RD_NAMEFORDEFAULTS "NVRedDog" @implementation RedDog /*************************************************************************************** * Module Methods * ***************************************************************************************/ + initialize { static NXDefaultsVector ourDefaults = { {"numDecks", "8"}, {NULL, NULL} }; NXRegisterDefaults(RD_NAMEFORDEFAULTS, ourDefaults); return self; } - awakeFromNib /* Sent to every object instantiated in a nib file. A good place to perform some initialization... */ { // This may take a while, so lets inform the user [self say:"Pre-Drawing Cards..."]; NXPing(); [Card drawCardImages]; pile1 = [pileView1 cardPile]; pile2 = [pileView2 cardPile]; pile3 = [pileView3 cardPile]; deckPile = [deckView cardPile]; //[[[deckView setCoversOthers:YES] setCardSize:CS_SMALL] setDrawOutline:NO]; [deckView setUseShoe:YES]; [[[pileView1 setCoversOthers:YES] setCardSize:CS_SMALL] setDrawOutline:NO]; [[[pileView2 setCoversOthers:YES] setCardSize:CS_SMALL] setDrawOutline:NO]; [[[pileView3 setCoversOthers:YES] setCardSize:CS_SMALL] setDrawOutline:NO]; [[[[[betView setNumCols:MAX_PLAYERS] setNumRows:1] positionChips] setEnabled:YES] setSoundEnabled:YES]; handStatus = RD_BEFOREDEAL; [self revertPreferences:self]; [self checkDeck]; won = 0; lost = 0; return self; } - (BOOL)anyBetsTooLowOrHigh { int i; char buf[512]; for(i=0; i<MAX_PLAYERS; i++) { if([betView amountAtRow:0 col:i] && [betView amountAtRow:0 col:i] < [self tableMin]) { sprintf(buf, "%s, your bet is below the table minimum!", [[PBoss() playerAt:i] playerName]); [PBoss() playSound:NV_WARNSOUND]; [self say:buf]; return YES; } if([betView amountAtRow:0 col:i] && [betView amountAtRow:0 col:i] > [self tableMax]) { sprintf(buf, "%s, your bet is above the table maximum!", [[PBoss() playerAt:i] playerName]); [PBoss() playSound:NV_WARNSOUND]; [self say:buf]; return YES; } } return NO; } - deal:sender { if(handStatus == RD_BEFOREDEAL) { [self dealFirstTwo]; } else if(handStatus == RD_BEFORETHIRD) { [self dealThird]; } return self; } - dealFirstTwo { int i; // Make sure wager is above table min, and below table max if([self anyBetsTooLowOrHigh]) return self; [dealButton setEnabled:NO]; for(i=0; i<MAX_PLAYERS; i++) doubledAlready[i] = NO; [self checkDeck]; [self dealCardToPile:RD_LEFTPILE]; [self dealCardToPile:RD_RIGHTPILE]; [self setPayoff]; if(spread == 0) // two cards are the same { [self say:"The two cards are the same, dealing third card...."]; NXPing(); usleep(RD_LONGPAUSE); return [self dealThird]; } else if(spread == 1) // two cards are consecutive { [self say:"The two cards are the consecutive, dealing again...."]; NXPing(); usleep(RD_LONGPAUSE); return [self dealFirstTwo]; } [self say:"You can double your bet now, if you wish. Press 'Continue' when ready..."]; handStatus = RD_BEFORETHIRD; [dealButton setTitle:"Continue"]; [self enableDealButtonIfNecessary]; return self; } - dealThird { [dealButton setEnabled:NO]; [self dealCardToPile:RD_MIDDLEPILE]; usleep(RD_LONGPAUSE); [self checkHand]; [self say:"New game... Place your bets!"]; handStatus = RD_BEFOREDEAL; [dealButton setTitle:"Deal"]; [self enableDealButtonIfNecessary]; return self; } - dealCardToPile:(int)pileNum { id card, pile=deckPile, view=deckView; switch(pileNum) { case RD_LEFTPILE: pile = pile1; view = pileView1; break; case RD_RIGHTPILE: pile = pile3; view = pileView3; break; case RD_MIDDLEPILE: pile = pile2; view = pileView2; break; default: return nil; } card = [deckPile cardAt:CS_TOP]; [card setFaceUp:YES]; [pile addCard:card]; [deckPile removeCard:card]; [deckView display]; [view display]; NXPing(); [PBoss() playSound:NV_CARDSOUND]; usleep(RD_DRAWPAUSE); return self; } - checkDeck { [pile1 empty]; [pile2 empty]; [pile3 empty]; [pileView1 display]; [pileView2 display]; [pileView3 display]; if([deckPile cardCount] < 4) { [self newDeck:self]; } return self; } - checkHand { if([[pile1 cardAt:CS_TOP] userValue] < [[pile2 cardAt:CS_TOP] userValue] && [[pile2 cardAt:CS_TOP] userValue] < [[pile3 cardAt:CS_TOP] userValue]) { handStatus = RD_WINNER; } else if([[pile1 cardAt:CS_TOP] userValue] > [[pile2 cardAt:CS_TOP] userValue] && [[pile2 cardAt:CS_TOP] userValue] > [[pile3 cardAt:CS_TOP] userValue]) { handStatus = RD_WINNER; } else if([[pile1 cardAt:CS_TOP] userValue] == [[pile2 cardAt:CS_TOP] userValue] && [[pile2 cardAt:CS_TOP] userValue] == [[pile3 cardAt:CS_TOP] userValue]) { handStatus = RD_WINNER; } else { handStatus = RD_LOSER; } if(handStatus == RD_WINNER) { [self say:"Hand Wins! Paying Line Bets!"]; NXPing(); [betView payBets]; [wonText setIntValue:++won]; } else { [self say:"Hand Loses! Clearing Line Bets!"]; NXPing(); [betView clearBets]; [lostText setIntValue:++lost]; } [PBoss() playSound:NV_CHIPSOUND]; NXPing(); usleep(RD_LONGPAUSE); return self; } - enableDealButtonIfNecessary { int i; BOOL shouldEnable = NO; for(i=0; i<MAX_PLAYERS; i++) { if([betView amountAtRow:0 col:i]) shouldEnable = YES; } if(shouldEnable) [dealButton setEnabled:YES]; else [dealButton setEnabled:NO]; return self; } - newDeck:sender { id theMatrix; int numDecks; theMatrix = [[deckPrefButton target] itemList]; numDecks = [[theMatrix selectedCell] tag]; if(numDecks == 0) numDecks = 1; [self newDeck:numDecks forView:deckView]; [self setUserValueForPile:deckPile aceHigh:YES]; return self; } - setPayoff { spread = abs([[pile1 cardAt:CS_TOP] userValue] - [[pile3 cardAt:CS_TOP] userValue]); switch(spread) { case 0: [betView setPayoff:15 cost:1]; break; case 1: return nil; case 2: [betView setPayoff:7 cost:1]; break; case 3: [betView setPayoff:5 cost:1]; break; case 4: [betView setPayoff:3 cost:1]; break; case 5: [betView setPayoff:2 cost:1]; break; default: [betView setPayoff:1 cost:1]; break; } return self; } /*************************************************************************************** * Inspector And Rules Methods * ***************************************************************************************/ - (BOOL)hasRules /* NO if the module does not have a Rules Window, YES if it does. The default method returns NO. */ { return YES; } - inspectorWillBeRemoved:sender /* Sent when this module's inspector is about to be replace with another one. */ { return self; } - inspectorWasInstalled:sender /* Sent just after this module's inspector has been installed. */ { return self; } /*************************************************************************************** * Player Methods * ***************************************************************************************/ - (int)collectAllBetsForPlayer:(int)playerNum { int total = 0; if(handStatus != RD_BEFORETHIRD) { total = [betView collectBetAtRow:0 col:playerNum]; [betView display]; [self enableDealButtonIfNecessary]; } return total; } - playerDidBet:aPlayer { return self; } - 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. */ { return self; } - playerDidJoin:player { return self; } - (BOOL)playerWillClose:aPlayer /* * Should return YES if it is okay to close this player, NO if it is not. The * default implementation returns YES. */ { if(RD_BEFORETHIRD) return NO; return YES; } - (BOOL)playerWillJoin:sender { return YES; } /*************************************************************************************** * Table Methods * ***************************************************************************************/ - view:aView wasLoadedOnTable:tableObject { table = tableObject; [self say:"Welcome to Red Dog! Place Your Bets!"]; return self; } - revertPreferences:sender { int numDecks = atoi(NXGetDefaultValue(RD_NAMEFORDEFAULTS, "numDecks")); [self selectCellWithTag:numDecks forPopUpButton:deckPrefButton]; return self; } - setPreferences:sender { static NXDefaultsVector newDefaults = { {"numDecks", "8"}, {NULL, NULL} }; int numDecks = [[[[deckPrefButton target] itemList] selectedCell] tag]; newDefaults[0].value = alloca(256); sprintf(newDefaults[0].value, "%d", numDecks); NXWriteDefaults(RD_NAMEFORDEFAULTS, newDefaults); 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. */ { [self setPreferences:self]; return self; } @end @implementation RedDog(BetViewDelegate) - player:aPlayer willBet:(int)betType onView:sender { int amount, prevAmount, tag = [aPlayer tag]; char buf[128]; if(aPlayer != nil) { amount = [aPlayer selectedChip]; prevAmount = [sender amountAtRow:0 col:tag]; switch(betType) { case NV_BET: if(amount == DEFAULT) { amount = [self tableMin]; } if(handStatus == RD_BEFORETHIRD) { if(doubledAlready[tag]) return nil; amount = [betView amountAtRow:0 col:tag]; } if(amount > [aPlayer amountInBank]) { NXBeep(); [self say:"You can't wager more than you have!"]; return nil; } if(prevAmount+amount > [self tableMax]) { NXBeep(); [self say:"That bet would put you over the table max!"]; return nil; } [sender bet:amount atRow:0 col:tag]; [aPlayer removeChip:amount]; sprintf(buf, "Dealer accepts %s's $%d wager.", [aPlayer playerName], prevAmount+amount); [self say:buf]; if(handStatus == RD_BEFORETHIRD) doubledAlready[tag] = YES; break; case NV_REMOVEBET: if(handStatus == RD_BEFORETHIRD) return nil; if(prevAmount == 0) return nil; if(amount == DEFAULT) amount = prevAmount; if(amount > prevAmount) { amount = prevAmount; } [sender removeBet:amount atRow:0 col:tag]; [aPlayer addChip:amount]; if(prevAmount-amount > 0) { sprintf(buf, "Dealer accepts %s's $%d.", [aPlayer playerName], prevAmount-amount); } else sprintf(buf, "Player %s removed his wager", [aPlayer playerName]); [self say:buf]; break; case NV_REMOVEOTHER: if(handStatus == RD_BEFORETHIRD) return nil; if(prevAmount == 0) return nil; amount = prevAmount; [sender removeBet:amount atRow:0 col:tag]; [aPlayer addChip:amount]; if(prevAmount-amount > 0) { sprintf(buf, "Dealer accepts %s's $%d.", [aPlayer playerName], prevAmount-amount); } else sprintf(buf, "Player %s removed his wager", [aPlayer playerName]); [self say:buf]; break; default: NXBeep(); [self say:"That action is not allowed in this game..."]; break; } } [self enableDealButtonIfNecessary]; return self; } - (BOOL)playerWillDragChipAtRow:(int)row andCol:(int)col fromView:sender { // dont allow players to drag chips when game is in progress if(handStatus == RD_BEFORETHIRD) return NO; else return YES; } - playerDraggedChipAtRow:(int)row andCol:(int)col fromView:sender { [self enableDealButtonIfNecessary]; return self; } - (BOOL)playerWillDropChipAtRow:(int *)row andCol:(int *)col InView:sender; { // dont allow players to drag chips when game is in progress if(handStatus == RD_BEFORETHIRD) return NO; else return YES; } - playerDroppedChipAtRow:(int)row andCol:(int)col inView:sender { [self enableDealButtonIfNecessary]; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.