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.