This is TableView.m in view mode; [Download] [Up]
#import "TableView.h" #import "crapswraps.h" #import "props.h" @implementation TableView - initializePropositions { int i; window = [dealer table]; for(i=0; i<MAX_PLAYERS; i++) { bets[i].amount = 0; bets[i].odds = 0; bets[i].isOn = YES; } if((displayFont = [Font newFont:"Helvetica" size:8 matrix:NX_IDENTITYMATRIX]) == nil) NXRunAlertPanel("Font Error", "Unable to find font", "Okay", NULL, NULL); puckFont = [Font newFont:"Times-Roman" size:10 matrix:NX_IDENTITYMATRIX]; for(i=0; i<MAX_PLAYERS; i++) { chip[i].textColor = (i+1<(MAX_PLAYERS/2)) ? NX_BLACK : NX_WHITE; chip[i].chipColor = NX_WHITE - NX_WHITE/((float)MAX_PLAYERS/((float)i+1.0)); } return self; } - initializeChipPlacement { int i, numPlayers; float width = NX_WIDTH(&bounds), section, center; numPlayers = [dealer numPlayers]; section = (width)/numPlayers; center = section/2; for(i=0; i<numPlayers; i++) { chip[i].r = 10.0; chip[i].x = (section*i)+center; chip[i].y = chip[i].r + 2.0; } return self; } - setTag:(int)aTag { tag = aTag; return self; } - setTrackingRectForWindow:aWindow { NXRect aRect; //window = aWindow; [self getFrame:&aRect]; [superview convertRect:&aRect toView:nil]; [window setTrackingRect:&aRect inside:NO owner:self tag:tag left:NO right:NO]; return self; } - (int)tag { return tag; } /*********************** * Betting Methods * ***********************/ - bet:(int)units forPlayer:player num:(int)playerNum { int point = [dealer point]; char buf[256]; if(player == nil) return nil; // Things player can't bet on directly... if((tag == COME_FOUR || tag == COME_FIVE || tag == COME_SIX || tag == COME_EIGHT || tag == COME_NINE || tag == COME_TEN || tag == DONT_COME_FOUR || tag == DONT_COME_FIVE || tag == DONT_COME_SIX || tag == DONT_COME_EIGHT || tag == DONT_COME_NINE || tag == DONT_COME_TEN)) { [dealer playSound:WARNSOUND]; sprintf(buf, "Can't bet on %s directly...", prop[tag].name); [dealer say:buf]; return self; } // Do not allow a bet on PASS or DONT_PASS if point has been established. if(point != 0 && (tag == PASS || tag == DONT_PASS)) { [dealer playSound:WARNSOUND]; sprintf(buf, "Can't bet on %s after the point has been established...", prop[tag].name); [dealer say:buf]; return nil; } // use default bet if user wants if(units == DEFAULT) units = (prop[tag].cost > [dealer tableMin]) ? prop[tag].cost : [dealer tableMin]; // special case HORN if(tag == HORN) units = prop[tag].cost * [dealer tableMin]; // if this bet is more than the player has in chips, or if units would put // the bet above the table maximum, do not allow it. if(units > [player amountInBank]) { [dealer playSound:WARNSOUND]; sprintf(buf, "Can't bet more than you have!"); [dealer say:buf]; return nil; } if(((units+bets[playerNum].amount+bets[playerNum].odds) > [dealer tableMax])) { [dealer playSound:WARNSOUND]; sprintf(buf, "Betting $%d on %s would put your bet over the table max!", units, prop[tag].name); [dealer say:buf]; return nil; } [dealer playSound:CHIPSOUND]; // add units to bet, subtract from players bank bets[playerNum].amount += units; bets[playerNum].isOn = YES; [player addToBank:-units]; [self displayFromOpaqueAncestor:&bounds :1 :YES]; sprintf(buf, "House accepts %s's $%d bet on %s.", [player playerName], bets[playerNum].amount, prop[tag].name); [dealer say:buf]; return self; } - removeBet:(int)units forPlayer:player num:(int)playerNum { int point = [dealer point]; char buf[256]; if(player == nil) return nil; // Things player can't bet on directly... if((tag == COME_FOUR || tag == COME_FIVE || tag == COME_SIX || tag == COME_EIGHT || tag == COME_NINE || tag == COME_TEN || tag == DONT_COME_FOUR || tag == DONT_COME_FIVE || tag == DONT_COME_SIX || tag == DONT_COME_EIGHT || tag == DONT_COME_NINE || tag == DONT_COME_TEN)) { [dealer playSound:WARNSOUND]; sprintf(buf, "Can't bet on %s directly...", prop[tag].name); [dealer say:buf]; return nil; } // do not allow a player to remove a PASS, DONT_PASS, COME, or DONT_COME bet once // point has been established. if(point != 0 && (tag == PASS || tag == DONT_PASS)) { [dealer playSound:WARNSOUND]; sprintf(buf, "Can't remove %s bets after the point has been established!", prop[tag].name); [dealer say:buf]; return nil; } else if(tag >= COME_FOUR && tag <= COME_TEN) { [dealer playSound:WARNSOUND]; sprintf(buf, "Can't remove %s bets after the point has been established!", prop[tag].name); [dealer say:buf]; return nil; } else if(tag >= DONT_COME_FOUR && tag <= DONT_COME_TEN) { [dealer playSound:WARNSOUND]; sprintf(buf, "Can't remove %s bets after the point has been established!", prop[tag].name); [dealer say:buf]; return nil; } if(units == DEFAULT) units = bets[playerNum].amount; // dont allow a player to subtract more than he has bet if(units > bets[playerNum].amount) { [dealer playSound:WARNSOUND]; sprintf(buf, "Can't remove more than you've bet!"); [dealer say:buf]; return nil; } [dealer playSound:CHIPSOUND]; // subtract units from bet, add that amount to player's bank. bets[playerNum].amount -= units; [player addToBank:units]; [self displayFromOpaqueAncestor:&bounds :1 :YES]; return self; } - layOdds:(int)units forPlayer:player num:(int)playerNum { int point = [dealer point]; char buf[256]; if(player == nil) return nil; // only allow odds on props that allow odds, and only on PASS and DONT_PASS after // point has been established. if(!prop[tag].allowsOdds) { [dealer playSound:WARNSOUND]; sprintf(buf, "Odds bets aren't allowed on %s!", prop[tag].name); [dealer say:buf]; return nil; } if(point == 0 && (tag == PASS || tag == DONT_PASS)) { [dealer playSound:WARNSOUND]; sprintf(buf, "Can't buy odds on %s before the point has been established!", prop[tag].name); [dealer say:buf]; return nil; } if(units == DEFAULT) units = bets[playerNum].amount; // dont allow any more odds if units is greater than players bank, or if // adding units to odds would make the bet greater than table max. if(units > [player amountInBank] || bets[playerNum].amount == 0 ) { [dealer playSound:WARNSOUND]; [dealer say:"You don't have enough money for that bet!"]; return nil; } if(((units+bets[playerNum].amount+bets[playerNum].odds) > [dealer tableMax])) { [dealer playSound:WARNSOUND]; sprintf(buf, "Laying odds on %s now would put your bet over the table max!", prop[tag].name); [dealer say:buf]; return nil; } // don't allow more than [dealer tableOdds] times odds if(((bets[playerNum].odds+units) / bets[playerNum].amount) > [dealer tableOdds]) { [dealer playSound:WARNSOUND]; sprintf(buf, "Can't have more than %dX odds on bets!", [dealer tableOdds]); [dealer say:buf]; return nil; } [dealer playSound:CHIPSOUND]; // add odds to bet, subtract amount from bank. bets[playerNum].odds += units; bets[playerNum].isOn = YES; [player addToBank:-units]; [self displayFromOpaqueAncestor:&bounds :1 :YES]; return self; } - removeOdds:(int)units forPlayer:player num:(int)playerNum { char buf[256]; if(player == nil) return nil; if(units == DEFAULT) units = bets[playerNum].odds; // don't allow removal of more odds than player has bet if(units > bets[playerNum].odds) { [dealer playSound:WARNSOUND]; sprintf(buf, "Can't remove more odds than you've bet!"); [dealer say:buf]; return nil; } [dealer playSound:CHIPSOUND]; bets[playerNum].odds -= units; [player addToBank:units]; [self displayFromOpaqueAncestor:&bounds :1 :YES]; return self; } /************************************** * Manipulating Bets * **************************************/ - payOutForRoll:(int)roll { int player, amount=0, odds=0, profit=0, cost=0; for(player = 0; player < MAX_PLAYERS; player++) { if(bets[player].amount > 0 && bets[player].isOn) { if(tag == FIELD && (roll == 2 || roll == 12)) // special case FIELD { amount = 2 * prop[tag].payoff * (int) (bets[player].amount / prop[tag].cost); } else { amount = prop[tag].payoff * (int) (bets[player].amount / prop[tag].cost); } amount = amount + (int)(bets[player].amount % prop[tag].cost); amount = amount + bets[player].amount; // special case HORN. Payout is 1/4 the bet times the payout for TWO // THREE, ELEVEN, or TWELVE, depending on what is rolled. if(tag == HORN) { switch(roll) { case 2: amount = prop[TWO].payoff * (int) (bets[player].amount/4/prop[TWO].cost); amount = amount + (int)((bets[player].amount/4) % prop[TWO].cost); break; case 3: amount = prop[THREE].payoff * (int) (bets[player].amount/4/prop[THREE].cost); amount = amount + (int)((bets[player].amount/4) % prop[THREE].cost); break; case 11: amount = prop[ELEVEN].payoff * (int) (bets[player].amount/4/prop[ELEVEN].cost); amount = amount + (int)((bets[player].amount/4) % prop[ELEVEN].cost); break; case 12: amount = prop[TWELVE].payoff * (int) (bets[player].amount/4/prop[TWELVE].cost); amount = amount + (int)((bets[player].amount/4) % prop[TWELVE].cost); break; } amount = amount + (bets[player].amount/4); } // get odds for roll if needed if(prop[tag].allowsOdds && bets[player].odds > 0) { switch(tag) { case PASS: [dealer trueOdds:&profit for:&cost forRoll:roll]; break; case COME_FOUR: [dealer trueOdds:&profit for:&cost forRoll:roll]; break; case COME_FIVE: [dealer trueOdds:&profit for:&cost forRoll:roll]; break; case COME_SIX: [dealer trueOdds:&profit for:&cost forRoll:roll]; break; case COME_EIGHT: [dealer trueOdds:&profit for:&cost forRoll:roll]; break; case COME_NINE: [dealer trueOdds:&profit for:&cost forRoll:roll]; break; case COME_TEN: [dealer trueOdds:&profit for:&cost forRoll:roll]; break; // odds on the DONTs are opposite case DONT_PASS: [dealer trueOdds:&profit for:&cost forRoll:-[dealer point]]; break; case DONT_COME_FOUR: [dealer trueOdds:&profit for:&cost forRoll:-4]; break; case DONT_COME_FIVE: [dealer trueOdds:&profit for:&cost forRoll:-5]; break; case DONT_COME_SIX: [dealer trueOdds:&profit for:&cost forRoll:-6]; break; case DONT_COME_EIGHT: [dealer trueOdds:&profit for:&cost forRoll:-8]; break; case DONT_COME_NINE: [dealer trueOdds:&profit for:&cost forRoll:-9]; break; case DONT_COME_TEN: [dealer trueOdds:&profit for:&cost forRoll:-10]; break; } odds = profit * (int)(bets[player].odds / cost); odds = odds + (int)(bets[player].odds % cost); odds = odds + bets[player].odds; bets[player].odds = 0; } bets[player].amount = amount + odds; } } [self displayFromOpaqueAncestor:&bounds :1 :YES]; return self; } - clearBets { int i; for(i=0; i<MAX_PLAYERS; i++) { if(bets[i].isOn) { bets[i].amount = 0; bets[i].odds = 0; } } [self displayFromOpaqueAncestor:&bounds :1 :YES]; return self; } - getBetsFrom:otherView { int i; for(i=0; i<MAX_PLAYERS; i++) { [otherView getBet:&bets[i].amount odds:&bets[i].odds forPlayer:i]; [otherView setBet:0 odds:0 forPlayer:i]; } [self displayFromOpaqueAncestor:&bounds :1 :YES]; return self; } - addBetsFrom:otherView { int i, bet, odds; for(i=0; i<MAX_PLAYERS; i++) { [otherView getBet:&bet odds:&odds forPlayer:i]; [otherView setBet:0 odds:0 forPlayer:i]; bets[i].amount = bets[i].amount + bet; bets[i].odds = bets[i].odds + odds; } [self displayFromOpaqueAncestor:&bounds :1 :YES]; return self; } - getBet:(int *)bet odds:(int *)odds forPlayer:(int)playerNum { *bet = bets[playerNum].amount; *odds = bets[playerNum].odds; return self; } - setBet:(int)bet odds:(int)odds forPlayer:(int)playerNum { bets[playerNum].amount = bet; bets[playerNum].odds = odds; [self displayFromOpaqueAncestor:&bounds :1 :YES]; return self; } - switchBetOnOffForPlayer:(int) playerNum { if(bets[playerNum].isOn == NO) bets[playerNum].isOn = YES; else bets[playerNum].isOn = NO; [self displayFromOpaqueAncestor:&bounds :1 :YES]; return self; } - tradeBetsWith:otherView { int i, bet, odds; for(i=0; i<MAX_PLAYERS; i++) { [otherView getBet:&bet odds:&odds forPlayer:i]; [otherView setBet:bets[i].amount odds:bets[i].odds forPlayer:i]; bets[i].amount = bet; bets[i].odds = odds; } [self displayFromOpaqueAncestor:&bounds :1 :YES]; return self; } - drawSelf:(const NXRect *)rects :(int)rectCount { int i; float width; char bet[20]; int point = [dealer point]; BOOL doPuckSound = NO; // draw puck if needed if((point==4 && tag==COME_FOUR) || (point==5 && tag==COME_FIVE) || (point==6 && tag==COME_SIX) || (point==8 && tag==COME_EIGHT) || (point==9 && tag==COME_NINE) || (point==10 && tag==COME_TEN)) { [puckFont set]; drawChip(NX_WIDTH(&bounds)/2, NX_HEIGHT(&bounds)/2+15, 15.0, NX_BLACK); width = [displayFont getWidthOf:"Point"]; drawText("Point", NX_WIDTH(&bounds)/2-(width/2)-2, NX_HEIGHT(&bounds)/2+12, NX_WHITE); // play sound if we this is the first time we draw the puck if(!drawingPuck) { //[dealer playSound:PUCKSOUND]; doPuckSound = YES; drawingPuck = YES; } } else drawingPuck = NO; for(i=0; i<MAX_PLAYERS; i++) { if(bets[i].amount>0) { [displayFont set]; drawChip(chip[i].x, chip[i].y, chip[i].r, chip[i].chipColor); if(bets[i].isOn) sprintf(bet, "%d", bets[i].amount); else sprintf(bet, "OFF"); width = [displayFont getWidthOf:bet]; drawText(bet, chip[i].x-(width/2), chip[i].y-4, chip[i].textColor); if(bets[i].odds > 0) { drawChip(chip[i].x, chip[i].y+4, chip[i].r, chip[i].chipColor); if(bets[i].isOn) sprintf(bet, "%d", bets[i].amount+bets[i].odds); else sprintf(bet, "OFF"); width = [displayFont getWidthOf:bet]; drawText(bet, chip[i].x-(width/2), chip[i].y, chip[i].textColor); } } } if(doPuckSound) [dealer playSound:PUCKSOUND]; return self; } - (BOOL)acceptsFirstMouse { return YES; } - mouseDown:(NXEvent *)theEvent /* * player has moused down in our view, indicating that they wish to bet here. * * if no key is down -- Bet * if shift is down -- remove bet * if alternate key is down - lay odds * if alternate+shift is down -- remove odds * if control+shift -- turn off/on */ { id player = [dealer currentPlayer]; if(theEvent->flags & NX_ALTERNATEMASK) { if(theEvent->flags & NX_SHIFTMASK) [self removeOdds:[player selectedChip] forPlayer:player num:[player tag]]; else [self layOdds:[player selectedChip] forPlayer:player num:[player tag]]; } else if(theEvent->flags & NX_SHIFTMASK) { [self removeBet:[player selectedChip] forPlayer:player num:[player tag]]; } else if(theEvent->flags & NX_CONTROLMASK) { [self switchBetOnOffForPlayer:[player tag]]; } else { [self bet:[player selectedChip] forPlayer:player num:[player tag]]; } return self; } - mouseEntered:(NXEvent *)theEvent { [dealer mouseEnteredView:tag]; return self; } - mouseExited:(NXEvent *)theEvent { return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.