This is Mover.m in view mode; [Download] [Up]
// Mover.m // Part of Risk by Mike Ferris #import "Mover.h" #import "GameSetup.h" #import "ArmyView.h" #import "MapView.h" #import "Country.h" #import "ComputerLogic.h" #import "ComputerPlayer.h" #import "DiceInspector.h" #import <stdlib.h> #import <strings.h> #import <objc/List.h> #import <appkit/Panel.h> #import <appkit/View.h> #import <appkit/TextField.h> #import <appkit/NXColorWell.h> #import <appkit/publicWraps.h> #import <appkit/nextstd.h> #import <appkit/Application.h> #import "CardManager.h" @implementation Mover + initialize { if (self == [Mover class]) { [self setVersion:1]; } return self; } - appDidInit:sender { int i; diceInspector = nil; gameInProgress=NO; initPlaceArmiesNum=-1; fortifyRule = FR_NIL; currentPhaseView=nil; currentPhase=P_NIL; placeArmiesSubphase=SP_INITIAL; phaseResults=PR_NIL; currentPlayer=-1; currentTurn=0; currentPlayerGetsCard=NO; currentCountry=nil; attackFromCountry=nil; attackToCountry=nil; defaultAttackFrom=nil; for (i=0;i<6;i++) { attackOption[i]=AP_ONCE; attackNum[i]=3; initPlaceArmies[i]=0; } [phaseComputerMove removeFromSuperview]; [phasePlaceArmies removeFromSuperview]; [phaseAttack removeFromSuperview]; [phaseFortify removeFromSuperview]; [phaseChooseCountries removeFromSuperview]; [colorWell setEnabled:NO]; [colorWell setColor:NX_COLORWHITE]; [colorWell display]; return self; } - startNewGame { gameInProgress=YES; initPlaceArmiesNum=[theGameSetup initialArmyPlacement]; fortifyRule = [theGameSetup fortifyRule]; [theMapView makeAllCountriesUnoccupied]; currentPhase=P_NIL; currentPlayer=-1; [theCardManager reset]; [self continuePlay]; return self; } - settingsChanged { initPlaceArmiesNum=[theGameSetup initialArmyPlacement]; fortifyRule = [theGameSetup fortifyRule]; [theMapView display]; [nameTextField setStringValue:[theGameSetup nameOfPlayer:currentPlayer]]; [colorWell setColor:[theGameSetup colorOfPlayer:currentPlayer]]; [colorWell display]; [statusView display]; return self; } - endGame:(int)winner { NXRunAlertPanel("Victory", "Winner was %s.", "OK", NULL, NULL, [theGameSetup nameOfPlayer:winner]); gameInProgress=NO; currentCountry=nil; [theMapView setSelectedCountry:currentCountry]; // flush the control panel view [self continuePlay]; [controlPanel display]; return self; } - countryClick:country num:(int)n event:(NXEvent *)e // dispatch function for events where the player has clicked in a country. // determines what phase of which players turn it is, and dispatches the // event accordingly. { if (gameInProgress) { switch (currentPhase) { case P_NIL: currentCountry=nil; [theMapView setSelectedCountry:currentCountry]; break; case P_CHOOSECOUNTRIES: [self chooseCountry:country num:n]; break; case P_PLACEARMIES: [self placeArmiesInCountry:country num:n event:e]; break; case P_ATTACK: if ([country player]==currentPlayer) { [self attackFrom:country num:n]; } else { [self attackTo:country num:n event:e]; } break; case P_FORTIFY: if ([country player]==currentPlayer) { [self fortifyFrom:country num:n]; } break; default: break; } } else { currentCountry=nil; [theMapView setSelectedCountry:currentCountry]; } return self; } - placeArmiesInCountry:country num:(int)n event:(NXEvent *)e { int armiesToPlace=1; BOOL doit=NO; if (e->flags & NX_SHIFTMASK) { if ([placeArmyView armiesLeft]<5) { armiesToPlace=[placeArmyView armiesLeft]; } else { armiesToPlace=5; } } if (e->flags & NX_COMMANDMASK) { armiesToPlace=[placeArmyView armiesLeft]; } switch (placeArmiesSubphase) { case SP_INITIAL: case SP_BEGINTURN: if ([country player] == currentPlayer) { currentCountry=nil; defaultAttackFrom=country; doit=YES; } else { doit=NO; } break; case SP_ATTACK: if ((country==attackFromCountry) || (country==attackToCountry)) { doit=YES; } else { doit=NO; } break; case SP_FORTIFY: // make this canFortifyTo:country doit = [self canFortifyTo:country]; break; } if (doit) { [country addArmies:armiesToPlace]; if (placeArmiesSubphase==SP_FORTIFY) { [country addUnmovableArmies:armiesToPlace forTurn:currentTurn]; } [placeArmyView decreaseArmiesLeftBy:armiesToPlace]; if (initPlaceArmies[currentPlayer] > 0) { [placeArmyInitTextField setIntValue: [placeArmyInitTextField intValue] - armiesToPlace]; } [theMapView displayCountry:country]; [theMapView setSelectedCountry:currentCountry]; if ([placeArmyView armiesLeft]<=0) { [self continuePlay]; } } else { [theMapView setSelectedCountry:currentCountry]; NXBeep(); } return self; } - attackFrom:country num:(int)n { // if the clicked country has enough armies to attack, let em. if ([country armies]>1) { currentCountry = attackFromCountry = country; [attackCountry setStringValue:[currentCountry name]]; } else { NXBeep(); } [theMapView setSelectedCountry:currentCountry]; return self; } - attackTo:country num:(int)n event:(NXEvent *)e { BOOL conq, moveAll = NO; id fc = currentCountry; id tc = country; int aArmies = [fc armies]; int aPlayer = [fc player]; int dPlayer = [tc player]; int oldAttackOption=attackOption[currentPlayer]; if (e->flags & NX_SHIFTMASK) { moveAll = YES; } if (e->flags & NX_COMMANDMASK) { attackOption[currentPlayer]=AP_ONCE; } if (([country isNeighborTo:[currentCountry idNum]]) && ([country player] != currentPlayer)) { // do the attack from currentCountry to country attackToCountry=tc; conq = [self attackFrom:fc to:tc]; if (conq) { defaultAttackFrom=country; aArmies = [fc armies]; [fc setPlayer:aPlayer andArmies:1]; if (moveAll) { [tc setPlayer:aPlayer andArmies:aArmies-1]; [fc setPlayer:aPlayer andArmies:1]; [placeArmyView setArmiesLeft:0]; } else { if (aArmies > 3) { [tc setPlayer:aPlayer andArmies:3]; [placeArmyView setArmiesLeft:aArmies-4]; } else { [tc setPlayer:aPlayer andArmies:aArmies-1]; [placeArmyView setArmiesLeft:0]; } } [theMapView displayCountry:fc]; [theMapView displayCountry:tc]; // now check to see if defending player still exists if (![theMapView playerOccupiesCountries:dPlayer]) { // dPlayer is out of game [theGameSetup playerConquered:dPlayer]; if ([theMapView doesPlayerWin:aPlayer]) { [self endGame:aPlayer]; } else { [theCardManager player:aPlayer takesCardsOf:dPlayer]; } } if (gameInProgress) { currentCountry = nil; [theMapView setSelectedCountry:currentCountry]; phaseResults=PR_A_VICTORY; placeArmiesSubphase=SP_ATTACK; [self continuePlay]; } } else { if ([fc armies]<=1) { currentCountry=nil; } } } else { NXBeep(); } attackOption[currentPlayer]=oldAttackOption; [theMapView setSelectedCountry:currentCountry]; return self; } - (BOOL)attackFrom:fc to:tc // calls attackOnceFrom: to: according to the attackOption setting // it can call it just once or it can call it repeatedly until a certain // condition is met. { int i; BOOL conquered, cont; switch (attackOption[currentPlayer]) { case AP_ONCE: conquered = [self attackOnceFrom:fc to:tc]; break; case AP_MULTIPLE: cont=YES; conquered=NO; for (i=[attackSlider intValue];(i>0) && (cont);i--) { conquered=[self attackOnceFrom:fc to:tc]; // if the battle was won don't keep going or // if the attacker can't attack anymore stop if ((conquered) || ([fc armies]<2)) { cont=NO; } } break; case AP_UNTILLEFT: cont=YES; conquered = NO; i=[attackSlider intValue]; while (cont) { conquered = [self attackOnceFrom:fc to:tc]; if ((conquered) || ([fc armies]<=i)) { cont=NO; } } break; case AP_UNTILCANT: cont=YES; conquered = NO; while (cont) { conquered = [self attackOnceFrom:fc to:tc]; if ((conquered) || ([fc armies]<2)) { cont=NO; } } break; default: conquered = NO; break; } return conquered; } - (BOOL)attackOnceFrom:fc to:tc // this method makes one attack from fc to tc. // it subtracts the required armies from fc and tc and redisplays // changing phase and setting the new current country are the caller's // responsibility. // returns whether fc conquered tc. { int aDice[3], dDice[2]; int aNumDice, dNumDice; int aArmies = [fc armies]; int dArmies = [tc armies]; int aLoses=0, dLoses=0; int i, numCompares; // first figure out how many dice to roll if (aArmies>3) { aNumDice=3; } else { aNumDice=aArmies-1; } if (dArmies>1) { dNumDice=2; } else { dNumDice=1; } numCompares = MIN(aNumDice, dNumDice); // now get numbers for the dice. the arrays come back sorted. [computerLogic rollDiceAttacker:aDice :aNumDice defender:dDice :dNumDice]; // show the dice if needed if ((diceInspector != nil) && ([diceInspector panelOnScreen])) { [diceInspector setFromCountry:[fc name] toCountry:[tc name] fromArmies:aArmies toArmies:dArmies attackerRolling:aNumDice attackerUsing:numCompares attackerDie1:aDice[0] attackerDie2:aDice[1] attackerDie3:aDice[2] defenderRolling:dNumDice defenderUsing:numCompares attackerDie1:dDice[0] attackerDie2:dDice[1]]; } // figure out how many countries each side loses for (i=0;i<numCompares;i++) { if (aDice[i]>dDice[i]) { // attacker wins this roll dLoses++; } else { // defender wins this roll aLoses++; } } // aLoses and dLoses are set to the number of armies each is to lose // first get rid of attackers lost armies if (aLoses != 0) { [fc subArmies:aLoses]; [theMapView displayCountry:fc]; } if (dLoses!=0) { [tc subArmies:dLoses]; [theMapView displayCountry:tc]; } if ([theGameSetup strategyOfPlayer:[tc player]] == S_COMPUTER) { // notify the computer player that it has been affronted so // it can retaliate later [[theGameSetup computerPlayerForPlayer:[tc player]] youWereAttacked:tc by:[fc player]]; } // now see if the defender lost if (dLoses >= dArmies) { // country is conquered currentPlayerGetsCard=YES; if ([theGameSetup strategyOfPlayer:[tc player]] == S_COMPUTER) { // notify the computer player that it has lost a country so // it can retaliate later [[theGameSetup computerPlayerForPlayer:[tc player]] youLostCountry:tc to:[fc player]]; } return YES; } else { return NO; } } - endTurn:sender { if (gameInProgress) { phaseResults=PR_ENDTURN; currentCountry=nil; defaultAttackFrom=nil; [theMapView setSelectedCountry:currentCountry]; [self perform:@selector(continuePlay:) with:self afterDelay:5 cancelPrevious:YES]; } return self; } - fortify:sender { if (gameInProgress) { phaseResults=PR_A_FORTIFY; currentTurn+=1; currentCountry=nil; [theMapView setSelectedCountry:currentCountry]; [self perform:@selector(continuePlay:) with:self afterDelay:5 cancelPrevious:YES]; } return self; } - fortifyFrom:country num:(int)n { int numToPlace; numToPlace = [country movableArmiesForTurn:currentTurn]; if (numToPlace > 0) { currentCountry=country; attackFromCountry = country; attackToCountry=nil; phaseResults = PR_F_PLACE; placeArmiesSubphase = SP_FORTIFY; [country subArmies:numToPlace]; [placeArmyView setArmiesLeft:numToPlace]; [theMapView displayCountry:country]; [theMapView setSelectedCountry:currentCountry]; [self continuePlay]; } return self; } - (BOOL)canFortifyTo:country // this function returns yes if the player can fortify to the country // in question from the attackFromCountry. It also keeps track of // attackToCountry so it can tell. { // we can always fortify back into the country we're fortifying out of if (country == attackFromCountry) { return YES; } // you can never fortify into somebody else's country if ([country player]!=currentPlayer) { return NO; } switch(fortifyRule) { case FR_ONE_ONE_N: // any neighbor, but just one if ((attackToCountry == nil) && ([country isNeighborTo:[attackFromCountry idNum]])) { attackToCountry = country; } return (country == attackToCountry); break; case FR_ONE_MANY_N: case FR_MANY_MANY_N: // any neighbor is ok return [country isNeighborTo:[attackFromCountry idNum]]; break; case FR_MANY_MANY_C: return [country isConnectedTo:[attackFromCountry idNum] withMapList:[theMapView countryList] alreadyTried:NULL]; break; default: return NO; } return NO; } - chooseCountry:country num:(int)n { if ([country player] == -1) { [country setPlayer:currentPlayer andArmies:1]; currentCountry=nil; [theMapView setSelectedCountry:currentCountry]; [self continuePlay]; } else { currentCountry=nil; [theMapView setSelectedCountry:currentCountry]; NXBeep(); } return self; } - continuePlay:sender // cover for following method { return [self continuePlay]; } - continuePlay // upon entry to this function it is assumed that the caller has completed // the current phase. // specifically it is assumed that if the current phase is attack or // fortify, that phaseResults and placeArmySubphase are set accurately, and // if the results are either PR_A_VICTORY or PR_F_PLACE that placeArmyView // has been set to display the proper number of armies to be placed. // also upon entry currentCountry is expected to be // accurate. { id theCP; int anum, cnum; [self goNextPhase]; switch (currentPhase) { case P_CHOOSECOUNTRIES: if ([theGameSetup countryDistribution] == CO_RANDOM) { [computerLogic randomCountries:self]; [theMapView display]; [self goNextPhase]; } break; default: break; } while (([theGameSetup strategyOfPlayer:currentPlayer] == S_COMPUTER) && (gameInProgress)) { theCP = [theGameSetup computerPlayerForPlayer:currentPlayer]; // it's a computerplayer switch (currentPhase) { case P_CHOOSECOUNTRIES: [theCP yourChooseCountry]; break; case P_PLACEARMIES: if (placeArmiesSubphase == SP_INITIAL) { if (initPlaceArmiesNum > initPlaceArmies[currentPlayer]) { [theCP yourInitialPlaceArmies: initPlaceArmies[currentPlayer]]; } else { [theCP yourInitialPlaceArmies:initPlaceArmiesNum]; } } else if (placeArmiesSubphase == SP_BEGINTURN) { anum = [theMapView armiesForPlayer:currentPlayer]; cnum = [theCardManager numCardsForPlayer:currentPlayer]; [theCP yourTurnWithArmies:anum andCards:cnum]; currentPhase = P_FORTIFY; phaseResults = PR_ENDTURN; } [placeArmyView setArmiesLeft:0]; break; default: break; } if (NXUserAborted()) { int result; // the user pressed command-. while we were in a computer // player. Ask if we should abort the game. result=NXRunAlertPanel("Interrupt", "You pressed command-. " "Do you wish to abort the game in progress?", "Yes", "No", NULL); if (result == NX_ALERTDEFAULT) { gameInProgress = NO; } NXResetUserAbort(); } [self goNextPhase]; } return self; } - goNextPhase // this function should be called exclusively from continuePlay { int i, pl=-1, ph=-1; switch (currentPhase) { case P_NIL: pl=0; while ([theGameSetup strategyOfPlayer:pl] ==S_NOTPLAYING) { pl=(pl+1)%6; } ph=P_CHOOSECOUNTRIES; break; case P_CHOOSECOUNTRIES: if ([theMapView countriesAreUnoccupied]) { ph=currentPhase; pl=(currentPlayer+1)%6; while ([theGameSetup strategyOfPlayer:pl] ==S_NOTPLAYING) { pl=(pl+1)%6; } } else { pl=0; while ([theGameSetup strategyOfPlayer:pl] ==S_NOTPLAYING) { pl=(pl+1)%6; } ph=P_PLACEARMIES; placeArmiesSubphase=SP_INITIAL; [placeArmyView setArmiesLeft:initPlaceArmiesNum]; for (i=0;i<6;i++) { initPlaceArmies[i] = [theGameSetup initialPlaceArmiesForPlayer:i]; } [placeArmyInitStatText setTextGray:NX_BLACK]; [placeArmyInitTextField setTextGray:NX_BLACK]; [placeArmyInitTextField setIntValue:initPlaceArmies[pl]]; } break; case P_PLACEARMIES: switch (placeArmiesSubphase) { case SP_INITIAL: if (initPlaceArmiesNum > initPlaceArmies[currentPlayer]) { initPlaceArmies[currentPlayer] -= initPlaceArmies[currentPlayer]; } else { initPlaceArmies[currentPlayer] -= initPlaceArmiesNum; } pl=(currentPlayer+1)%6; while ([theGameSetup strategyOfPlayer:pl] ==S_NOTPLAYING) { pl=(pl+1)%6; } if (initPlaceArmies[pl] > 0) { [placeArmyInitTextField setIntValue:initPlaceArmies[pl]]; ph=P_PLACEARMIES; if (initPlaceArmiesNum > initPlaceArmies[pl]) { [placeArmyView setArmiesLeft:initPlaceArmies[pl]]; } else { [placeArmyView setArmiesLeft:initPlaceArmiesNum]; } } else { [placeArmyInitStatText setTextGray:NX_DKGRAY]; [placeArmyInitTextField setTextGray:NX_DKGRAY]; [placeArmyInitTextField setStringValue:"--"]; ph=P_PLACEARMIES; placeArmiesSubphase=SP_BEGINTURN; [placeArmyView setArmiesLeft: [theMapView armiesForPlayer:pl]]; } break; case SP_BEGINTURN: ph=P_ATTACK; pl=currentPlayer; if (defaultAttackFrom != nil) { if ([defaultAttackFrom armies] > 1) { [self attackFrom:defaultAttackFrom num:[defaultAttackFrom idNum]]; } } break; case SP_ATTACK: // it is possible that we vanquished an opponent, so // check how many cards we have pl=currentPlayer; if ([theCardManager numCardsForPlayer:pl] > 4) { ph=P_PLACEARMIES; placeArmiesSubphase=SP_BEGINTURN; } else { ph=P_ATTACK; if (defaultAttackFrom != nil) { if ([defaultAttackFrom armies] > 1) { [self attackFrom:defaultAttackFrom num:[defaultAttackFrom idNum]]; } } } break; case SP_FORTIFY: currentCountry=nil; [theMapView setSelectedCountry:currentCountry]; if ((fortifyRule == FR_ONE_ONE_N) || (fortifyRule == FR_ONE_MANY_N)) { if (currentPlayerGetsCard) { [theCardManager playerDrawsCard:currentPlayer]; } currentPlayerGetsCard=NO; ph=P_PLACEARMIES; placeArmiesSubphase=SP_BEGINTURN; pl=(currentPlayer+1)%6; while ([theGameSetup strategyOfPlayer:pl]== S_NOTPLAYING) { pl=(pl+1)%6; } [placeArmyView setArmiesLeft:[theMapView armiesForPlayer:pl]]; } else { ph=P_FORTIFY; pl=currentPlayer; } break; } break; case P_ATTACK: switch (phaseResults) { case PR_A_VICTORY: // check to see if we have to turn in cards pl=currentPlayer; if (([theCardManager numCardsForPlayer:pl] > 4) && ([placeArmyView armiesLeft]==0)) { ph=P_PLACEARMIES; placeArmiesSubphase=SP_BEGINTURN; } else { if ([placeArmyView armiesLeft]>0) { ph=P_PLACEARMIES; placeArmiesSubphase=SP_ATTACK; } else { ph=P_ATTACK; if (defaultAttackFrom != nil) { if ([defaultAttackFrom armies] > 1) { [self attackFrom:defaultAttackFrom num:[defaultAttackFrom idNum]]; } } } } break; case PR_A_FORTIFY: if (currentPlayerGetsCard) { [theCardManager playerDrawsCard:currentPlayer]; } currentPlayerGetsCard=NO; ph=P_FORTIFY; pl=currentPlayer; break; case PR_ENDTURN: if (currentPlayerGetsCard) { [theCardManager playerDrawsCard:currentPlayer]; } currentPlayerGetsCard=NO; ph=P_PLACEARMIES; placeArmiesSubphase=SP_BEGINTURN; pl=(currentPlayer+1)%6; while ([theGameSetup strategyOfPlayer:pl]==S_NOTPLAYING) { pl=(pl+1)%6; } [placeArmyView setArmiesLeft:[theMapView armiesForPlayer:pl]]; break; } break; case P_FORTIFY: switch (phaseResults) { case PR_F_PLACE: ph=P_PLACEARMIES; pl=currentPlayer; placeArmiesSubphase=SP_FORTIFY; break; case PR_ENDTURN: if (currentPlayerGetsCard) { [theCardManager playerDrawsCard:currentPlayer]; } currentPlayerGetsCard=NO; ph=P_PLACEARMIES; placeArmiesSubphase=SP_BEGINTURN; pl=(currentPlayer+1)%6; while ([theGameSetup strategyOfPlayer:pl]==S_NOTPLAYING) { pl=(pl+1)%6; } [placeArmyView setArmiesLeft:[theMapView armiesForPlayer:pl]]; break; } break; default: break; } if (!gameInProgress) ph=P_NIL; [self phaseChange:ph forPlayer:pl]; [statusView display]; return self; } - phaseChange:(int)phaseNum forPlayer:(int)playerNum { id view=nil; int strat = [theGameSetup strategyOfPlayer:playerNum]; id pHand = [theCardManager playersHand:playerNum]; int cardArmies; if ((currentPlayer==playerNum) && (phaseNum==P_ATTACK)) { [attackTextField setIntValue:attackNum[playerNum]]; [attackSlider setIntValue:attackNum[playerNum]]; switch (attackOption[currentPlayer]) { case AP_ONCE: [attackPopupButton setTitle:APN_ONCE]; [attackTextField setEnabled:NO]; [attackSlider setEnabled:NO]; break; case AP_MULTIPLE: [attackPopupButton setTitle:APN_MULTIPLE]; [attackTextField setEnabled:YES]; [attackSlider setEnabled:YES]; break; case AP_UNTILLEFT: [attackPopupButton setTitle:APN_UNTILLEFT]; [attackTextField setEnabled:YES]; [attackSlider setEnabled:YES]; break; case AP_UNTILCANT: [attackPopupButton setTitle:APN_UNTILCANT]; [attackTextField setEnabled:NO]; [attackSlider setEnabled:NO]; break; default: break; } } currentPhase=phaseNum; currentPlayer=playerNum; [statusView display]; [controlPanel disableDisplay]; if (currentPhaseView!=nil) { [currentPhaseView removeFromSuperview]; } if (strat==S_COMPUTER) { view=phaseComputerMove; [nameTextField setStringValue: [theGameSetup nameOfPlayer:playerNum]]; [colorWell setColor:[theGameSetup colorOfPlayer:playerNum]]; [colorWell display]; [phaseTextField setStringValue:"Computer Move"]; [infoTextField setStringValue:"The computer player named above is " "moving, please wait."]; } else { switch (phaseNum) { case P_NIL: view=nil; [nameTextField setStringValue:""]; [colorWell setColor:NX_COLORWHITE]; [colorWell display]; [phaseTextField setStringValue:""]; [infoTextField setStringValue:""]; break; case P_PLACEARMIES: view=phasePlaceArmies; [nameTextField setStringValue: [theGameSetup nameOfPlayer:playerNum]]; [colorWell setColor:[theGameSetup colorOfPlayer:playerNum]]; [colorWell display]; [phaseTextField setStringValue:"Place Armies"]; switch (placeArmiesSubphase) { case SP_INITIAL: [placeArmyTurnInButton setEnabled:NO]; [placeArmyReviewButton setEnabled:NO]; [infoTextField setStringValue:"The game begins by " "players taking turns placing their initial " "armies a few at a time."]; break; case SP_BEGINTURN: if (([pHand count]>4) && (strat!=S_COMPUTER)) { cardArmies = [theCardManager runCardPanel:YES forPlayer:currentPlayer]; [placeArmyView increaseArmiesLeftBy:cardArmies]; } if ([theCardManager canPlayerPlay:currentPlayer]) { [placeArmyTurnInButton setEnabled:YES]; } else { [placeArmyTurnInButton setEnabled:NO]; } if ([pHand count] > 0) { [placeArmyReviewButton setEnabled:YES]; } else { [placeArmyReviewButton setEnabled:NO]; } [infoTextField setStringValue:"Begin your turn by " "placing new armies and possibly turning in " "cards."]; break; case SP_ATTACK: [placeArmyTurnInButton setEnabled:NO]; if ([pHand count] > 0) { [placeArmyReviewButton setEnabled:YES]; } else { [placeArmyReviewButton setEnabled:NO]; } [infoTextField setStringValue:"You have conquered " "a country. Now place the available armies" "in either the attacking or the conquered " "countries."]; break; case SP_FORTIFY: [placeArmyTurnInButton setEnabled:NO]; if ([pHand count] > 0) { [placeArmyReviewButton setEnabled:YES]; } else { [placeArmyReviewButton setEnabled:NO]; } [infoTextField setStringValue:"Fortify the armies " "into the source country or any neighboring " "countries you control."]; break; default: break; } break; case P_ATTACK: view=phaseAttack; [nameTextField setStringValue: [theGameSetup nameOfPlayer:playerNum]]; [colorWell setColor:[theGameSetup colorOfPlayer:playerNum]]; [colorWell display]; [phaseTextField setStringValue:"Attack"]; [infoTextField setStringValue:"Attack opponent's countries " "which border on your own countries."]; if ([pHand count] > 0) { [attackReviewButton setEnabled:YES]; } else { [attackReviewButton setEnabled:NO]; } break; case P_FORTIFY: view=phaseFortify; [nameTextField setStringValue: [theGameSetup nameOfPlayer:playerNum]]; [colorWell setColor:[theGameSetup colorOfPlayer:playerNum]]; [colorWell display]; [phaseTextField setStringValue:"Fortify Position"]; [infoTextField setStringValue:"Fortify your position at the " "end of your move by shifting armies."]; if ([pHand count] > 0) { [fortifyReviewButton setEnabled:YES]; } else { [fortifyReviewButton setEnabled:NO]; } break; case P_CHOOSECOUNTRIES: view=phaseChooseCountries; [nameTextField setStringValue: [theGameSetup nameOfPlayer:playerNum]]; [colorWell setColor:[theGameSetup colorOfPlayer:playerNum]]; [colorWell display]; [phaseTextField setStringValue:"Choose Countries"]; [infoTextField setStringValue:"Before play begins, take turns " "choosing the countries on the board."]; break; default: break; } } if (view!=nil) { [[controlPanel contentView] addSubview:view]; [view moveTo:281:8]; [view display]; } currentPhaseView=view; [controlPanel reenableDisplay]; [controlPanel displayIfNeeded]; return self; } - attackPopupAction:sender { attackOption[currentPlayer]=[[sender selectedCell] tag]; switch (attackOption[currentPlayer]) { case AP_ONCE: case AP_UNTILCANT: [attackTextField setEnabled:NO]; [attackSlider setEnabled:NO]; break; case AP_MULTIPLE: case AP_UNTILLEFT: [attackTextField setEnabled:YES]; [attackSlider setEnabled:YES]; break; } return self; } - attackSliderAction:sender { attackNum[currentPlayer]=[sender intValue]; [attackTextField takeIntValueFrom:sender]; return self; } - turnInCardsAction:sender { int numArmies; if (gameInProgress) { numArmies=[theCardManager runCardPanel:YES forPlayer:currentPlayer]; [placeArmyView increaseArmiesLeftBy:numArmies]; [statusView display]; } return self; } - reviewCardsAction:sender { int numArmies; if (gameInProgress) { numArmies=[theCardManager runCardPanel:NO forPlayer:currentPlayer]; } return self; } - (BOOL)isGameInProgress { return gameInProgress; } - setGameInProgress:(BOOL)flag { gameInProgress=flag; return self; } - (int)currentPlayer { return currentPlayer; } - displayStatusView { [statusView display]; return self; } - setDiceInspector:anObject { diceInspector = anObject; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.