This is RiskPlayer.m in view mode; [Download] [Up]
//
// This file is a part of Risk by Mike Ferris.
//
#import "Risk.h"
RCSID ("$Id: RiskPlayer.m,v 1.7 1997/12/15 21:09:43 nygard Exp $");
#import "RiskPlayer.h"
#import "RiskGameManager.h"
#import "Country.h"
#import "RiskWorld.h"
#import "SNRandom.h"
#import "RiskCard.h"
#import "CardSet.h"
//======================================================================
// The RiskPlayer is the base class for all players, both human and
// computer. It has generally useful methods, and defines methods
// the subclasses must implement to provide behavior for distinct
// parts of game play.
//======================================================================
#define RiskPlayer_VERSION 1
@implementation RiskPlayer
+ (void) load
{
//NSLog (@"RiskPlayer.");
}
//----------------------------------------------------------------------
+ (void) initialize
{
if (self == [RiskPlayer class])
{
[self setVersion:RiskPlayer_VERSION];
}
}
//----------------------------------------------------------------------
// Initializes a newly allocated RiskPlayer with the given name and
// number. The controlling game manager is also saved so that the
// player can access it during the game.
//----------------------------------------------------------------------
- initWithPlayerName:(NSString *)aName number:(Player)number gameManager:(RiskGameManager *)aManager
{
if ([super init] == nil)
return nil;
playerName = [aName retain];
playerNumber = number;
playerCards = [[NSMutableArray array] retain];
gameManager = [aManager retain];
attackMethod = AttackOnce;
attackMethodValue = 1;
consoleWindow = nil;
consoleMessageText = nil;
continueButton = nil;
pauseForContinueButton = nil;
playerToolMenu = nil;
rng = [[SNRandom instance] retain];
return self;
}
//----------------------------------------------------------------------
- (void) dealloc
{
SNRelease (playerName);
SNRelease (gameManager);
SNRelease (playerCards);
SNRelease (rng);
if (consoleWindow != nil)
{
// What happens to a window that is already closed when it gets this message?
[consoleWindow setReleasedWhenClosed:YES];
[continueButton setEnabled:NO];
[pauseForContinueButton setEnabled:NO];
}
[super dealloc];
}
//----------------------------------------------------------------------
- (NSString *) playerName
{
return playerName;
}
//----------------------------------------------------------------------
- (Player) playerNumber
{
return playerNumber;
}
//----------------------------------------------------------------------
- (NSArray *) playerCards
{
return playerCards;
}
//----------------------------------------------------------------------
// Returns the Player N menu under the Tool menu for this player. This
// allows players easy access for adding new menu items. Each player
// always starts out with one menu item to display the Console window.
//----------------------------------------------------------------------
- (NSMenu *) playerToolMenu
{
return playerToolMenu;
}
//----------------------------------------------------------------------
- (void) setPlayerToolMenu:(NSMenu *)theMenu
{
playerToolMenu = theMenu;
}
//----------------------------------------------------------------------
// Return the default attack method. This is used mostly by the Human
// player.
//----------------------------------------------------------------------
- (AttackMethod) attackMethod
{
return attackMethod;
}
//----------------------------------------------------------------------
// Change the default attack method. This is used mostly by the Human
// player.
//----------------------------------------------------------------------
- (void) setAttackMethod:(AttackMethod)newMethod
{
attackMethod = newMethod;
}
//----------------------------------------------------------------------
// Return the value associated with the default attack method. This is
// used mostly by the Human player.
//----------------------------------------------------------------------
- (int) attackMethodValue
{
return attackMethodValue;
}
//----------------------------------------------------------------------
// Set the value associated with the default attack method. This is
// used mostly by the Human player.
//----------------------------------------------------------------------
- (void) setAttackMethodValue:(int)newValue
{
attackMethodValue = newValue;
}
//----------------------------------------------------------------------
- (void) addCardToHand:(RiskCard *)newCard
{
[playerCards addObject:newCard];
}
//----------------------------------------------------------------------
- (void) removeCardFromHand:(RiskCard *)aCard
{
[playerCards removeObject:aCard];
}
//----------------------------------------------------------------------
- (SNRandom *) rng
{
return rng;
}
//----------------------------------------------------------------------
// The player should call this function at the end of certain phases in
// order to continue game play. This is required, as interactive
// players normally aren't finished the current phase when these
// functions return. This is required for the following methods:
//
// -placeInitialArmies:
// -placeArmies:
// -attackPhase
// -moveAttackingArmies:between::
// -fortifyPhase:
// -placeFortifyingArmies:fromCountry:
//
//----------------------------------------------------------------------
- (void) turnDone
{
[gameManager endTurn];
}
//----------------------------------------------------------------------
- (void) mouseDown:(NSEvent *)theEvent inCountry:(Country *)aCountry
{
}
//----------------------------------------------------------------------
- (void) mouseUp:(NSEvent *)theEvent inCountry:(Country *)aCountry
{
}
//----------------------------------------------------------------------
- (void) windowWillClose:(NSNotification *)aNotification
{
// Stop pausing if we close the window, otherwise we're stuck!
if ([aNotification object] == consoleWindow && [pauseForContinueButton state] == 1)
{
[NSApp stopModal];
[pauseForContinueButton setState:0];
[continueButton setEnabled:NO];
}
}
//======================================================================
// General methods for players
//======================================================================
- (NSSet *) ourCountries
{
return [[gameManager world] countriesForPlayer:playerNumber];
}
//----------------------------------------------------------------------
// Returns a set of countries from the source set that satisfy all the
// given options. The options are the bitwise OR of the OPT_ constants
// that are defined in RiskPlayer.h.
//
// Note that not all combinations make send. For example, no country
// can be occupied by both player three and player four.
//----------------------------------------------------------------------
- (NSSet *) countriesWithAllOptions:(int)options from:(NSSet *)source
{
NSEnumerator *countryEnumerator;
NSMutableSet *resultingSet;
Country *country;
Player number;
int troopCount, movableTroopCount;
BOOL hasEnemyNeighbors;
resultingSet = [NSMutableSet set];
countryEnumerator = [source objectEnumerator];
while (country = [countryEnumerator nextObject])
{
number = [country playerNumber];
troopCount = [country troopCount];
movableTroopCount = [country movableTroopCount];
hasEnemyNeighbors = [country hasEnemyNeighbors];
if (((options & OPT_PLAYER_NONE) && number != 0)
|| ((options & OPT_PLAYER_ONE) && number != 1)
|| ((options & OPT_PLAYER_TWO) && number != 2)
|| ((options & OPT_PLAYER_THREE) && number != 3)
|| ((options & OPT_PLAYER_FOUR) && number != 4)
|| ((options & OPT_PLAYER_FIVE) && number != 5)
|| ((options & OPT_PLAYER_SIX) && number != 6)
|| ((options & OPT_THIS_PLAYER) && number != playerNumber)
|| ((options & OPT_WITH_TROOPS) && troopCount < 1)
|| ((options & OPT_WITHOUT_TROOPS) && troopCount > 0)
|| ((options & OPT_WITH_MOVABLE_TROOPS) && movableTroopCount < 1)
|| ((options & OPT_WITHOUT_MOVABLE_TROOPS) && movableTroopCount > 0)
|| ((options & OPT_WITH_ENEMY_NEIGHBORS) && hasEnemyNeighbors == NO)
|| ((options & OPT_WITHOUT_ENEMY_NEIGHBORS) && hasEnemyNeighbors == YES))
{
continue;
}
[resultingSet addObject:country];
}
return resultingSet;
}
//----------------------------------------------------------------------
// Returns a set of countries from the source set that satisfy any of
// the given options. The options are the bitwise OR of the OPT_
// constants that are defined in RiskPlayer.h.
//----------------------------------------------------------------------
- (NSSet *) countriesWithAnyOptions:(int)options from:(NSSet *)source
{
NSEnumerator *countryEnumerator;
NSMutableSet *resultingSet;
Country *country;
Player number;
int troopCount, movableTroopCount;
BOOL hasEnemyNeighbors;
resultingSet = [NSMutableSet set];
countryEnumerator = [source objectEnumerator];
while (country = [countryEnumerator nextObject])
{
number = [country playerNumber];
troopCount = [country troopCount];
movableTroopCount = [country movableTroopCount];
hasEnemyNeighbors = [country hasEnemyNeighbors];
if (((options & OPT_PLAYER_NONE) && number == 0)
|| ((options & OPT_PLAYER_ONE) && number == 1)
|| ((options & OPT_PLAYER_TWO) && number == 2)
|| ((options & OPT_PLAYER_THREE) && number == 3)
|| ((options & OPT_PLAYER_FOUR) && number == 4)
|| ((options & OPT_PLAYER_FIVE) && number == 5)
|| ((options & OPT_PLAYER_SIX) && number == 6)
|| ((options & OPT_THIS_PLAYER) && number == playerNumber)
|| ((options & OPT_WITH_TROOPS) && troopCount > 0)
|| ((options & OPT_WITHOUT_TROOPS) && troopCount < 1)
|| ((options & OPT_WITH_MOVABLE_TROOPS) && movableTroopCount > 0)
|| ((options & OPT_WITHOUT_MOVABLE_TROOPS) && movableTroopCount < 1)
|| ((options & OPT_WITH_ENEMY_NEIGHBORS) && hasEnemyNeighbors == YES)
|| ((options & OPT_WITHOUT_ENEMY_NEIGHBORS) && hasEnemyNeighbors == NO))
{
[resultingSet addObject:country];
}
}
return resultingSet;
}
//----------------------------------------------------------------------
// Returns YES if any of the countries from the source set satisfies
// all of the given options. The options are the bitwise OR of the
// OPT_ constants that are defined in RiskPlayer.h.
//
// Note that not all combinations make send. For example, no country
// can be occupied by both player three and player four.
//----------------------------------------------------------------------
- (BOOL) hasCountriesWithAllOptions:(int)options from:(NSSet *)source
{
NSEnumerator *countryEnumerator;
Country *country;
BOOL flag;
Player number;
int troopCount, movableTroopCount;
BOOL hasEnemyNeighbors;
flag = NO;
countryEnumerator = [source objectEnumerator];
while (country = [countryEnumerator nextObject])
{
number = [country playerNumber];
troopCount = [country troopCount];
movableTroopCount = [country movableTroopCount];
hasEnemyNeighbors = [country hasEnemyNeighbors];
if (((options & OPT_PLAYER_NONE) && number != 0)
|| ((options & OPT_PLAYER_ONE) && number != 1)
|| ((options & OPT_PLAYER_TWO) && number != 2)
|| ((options & OPT_PLAYER_THREE) && number != 3)
|| ((options & OPT_PLAYER_FOUR) && number != 4)
|| ((options & OPT_PLAYER_FIVE) && number != 5)
|| ((options & OPT_PLAYER_SIX) && number != 6)
|| ((options & OPT_THIS_PLAYER) && number != playerNumber)
|| ((options & OPT_WITH_TROOPS) && troopCount < 1)
|| ((options & OPT_WITHOUT_TROOPS) && troopCount > 0)
|| ((options & OPT_WITH_MOVABLE_TROOPS) && movableTroopCount < 1)
|| ((options & OPT_WITHOUT_MOVABLE_TROOPS) && movableTroopCount > 0)
|| ((options & OPT_WITH_ENEMY_NEIGHBORS) && hasEnemyNeighbors == NO)
|| ((options & OPT_WITHOUT_ENEMY_NEIGHBORS) && hasEnemyNeighbors == YES))
{
continue;
}
flag = YES;
break;
}
return flag;
}
//----------------------------------------------------------------------
// Returns YES if any of the countries from the source set satisfies
// any of the given options. The options are the bitwise OR of the
// OPT_ constants that are defined in RiskPlayer.h.
//----------------------------------------------------------------------
- (BOOL) hasCountriesWithAnyOptions:(int)options from:(NSSet *)source
{
NSEnumerator *countryEnumerator;
Country *country;
BOOL flag;
Player number;
int troopCount, movableTroopCount;
BOOL hasEnemyNeighbors;
flag = NO;
countryEnumerator = [source objectEnumerator];
while (country = [countryEnumerator nextObject])
{
number = [country playerNumber];
troopCount = [country troopCount];
movableTroopCount = [country movableTroopCount];
hasEnemyNeighbors = [country hasEnemyNeighbors];
if (((options & OPT_PLAYER_NONE) && number == 0)
|| ((options & OPT_PLAYER_ONE) && number == 1)
|| ((options & OPT_PLAYER_TWO) && number == 2)
|| ((options & OPT_PLAYER_THREE) && number == 3)
|| ((options & OPT_PLAYER_FOUR) && number == 4)
|| ((options & OPT_PLAYER_FIVE) && number == 5)
|| ((options & OPT_PLAYER_SIX) && number == 6)
|| ((options & OPT_THIS_PLAYER) && number == playerNumber)
|| ((options & OPT_WITH_TROOPS) && troopCount > 0)
|| ((options & OPT_WITHOUT_TROOPS) && troopCount < 1)
|| ((options & OPT_WITH_MOVABLE_TROOPS) && movableTroopCount > 0)
|| ((options & OPT_WITHOUT_MOVABLE_TROOPS) && movableTroopCount < 1)
|| ((options & OPT_WITH_ENEMY_NEIGHBORS) && hasEnemyNeighbors == YES)
|| ((options & OPT_WITHOUT_ENEMY_NEIGHBORS) && hasEnemyNeighbors == NO))
{
flag = YES;
break;
}
}
return flag;
}
//----------------------------------------------------------------------
// Returns a set of countries from the source set that are also in the
// named continent.
//----------------------------------------------------------------------
- (NSSet *) chooseCountriesInContinentNamed:(NSString *)continentName from:(NSSet *)source
{
NSEnumerator *countryEnumerator;
NSMutableSet *resultingSet;
Country *country;
resultingSet = [NSMutableSet set];
countryEnumerator = [source objectEnumerator];
while (country = [countryEnumerator nextObject])
{
if ([[country continentName] isEqualToString:continentName] == YES)
[resultingSet addObject:country];
}
return resultingSet;
}
//----------------------------------------------------------------------
// Returns a set of countries from the source set, ensuring that none
// are in the named continent.
//----------------------------------------------------------------------
- (NSSet *) removeCountriesInContinentNamed:(NSString *)continentName from:(NSSet *)source
{
NSEnumerator *countryEnumerator;
NSMutableSet *resultingSet;
Country *country;
resultingSet = [NSMutableSet set];
countryEnumerator = [source objectEnumerator];
while (country = [countryEnumerator nextObject])
{
if ([[country continentName] isEqualToString:continentName] == NO)
[resultingSet addObject:country];
}
return resultingSet;
}
//======================================================================
// Card set methods
//======================================================================
//----------------------------------------------------------------------
// Returns a set of all the valid card sets from this player's hand.
//----------------------------------------------------------------------
- (NSSet *) allOurCardSets
{
NSMutableSet *allCardSets;
int i, j, k;
int count;
RiskCard *card1, *card2, *card3;
CardSet *cardSet;
count = [playerCards count];
allCardSets = [NSMutableSet set];
for (i = 0; i < count; i++)
{
card1 = [playerCards objectAtIndex:i];
for (j = i + 1; j < count; j++)
{
card2 = [playerCards objectAtIndex:j];
for (k = j + 1; k < count; k++)
{
card3 = [playerCards objectAtIndex:k];
cardSet = [CardSet cardSet:card1:card2:card3];
if (cardSet != nil)
[allCardSets addObject:cardSet];
}
}
}
return allCardSets;
}
//----------------------------------------------------------------------
// Returns the best set to turn in. To determine which of all possible
// sets is best, this method looks for the set:
// 1) with the least jokers in it, and
// 2) with the most countries that this player occupies
// It does not take into account things like the proximity of the
// countries to the action or anything amorphous like that.
//----------------------------------------------------------------------
- (CardSet *) bestSet
{
CardSet *bestSet;
NSSet *allSets;
NSEnumerator *cardSetEnumerator;
CardSet *cardSet;
bestSet = nil;
allSets = [self allOurCardSets];
cardSetEnumerator = [allSets objectEnumerator];
while (cardSet = [cardSetEnumerator nextObject])
{
if (compareCardSetValues (cardSet, bestSet, (void *)playerNumber) == NSOrderedAscending)
bestSet = cardSet;
}
return bestSet;
}
//----------------------------------------------------------------------
// Returns YES if this player has at least one valid card set.
//----------------------------------------------------------------------
- (BOOL) canTurnInCardSet
{
int i, j, k;
int count;
RiskCard *card1, *card2, *card3;
BOOL hasValidSet;
hasValidSet = NO;
count = [playerCards count];
for (i = 0; hasValidSet == NO && i < count; i++)
{
card1 = [playerCards objectAtIndex:i];
for (j = i + 1; hasValidSet == NO && j < count; j++)
{
card2 = [playerCards objectAtIndex:j];
for (k = j + 1; k < count; k++)
{
card3 = [playerCards objectAtIndex:k];
if ([CardSet isValidCardSet:card1:card2:card3] == YES)
{
hasValidSet = YES;
break;
}
}
}
}
return hasValidSet;
}
//======================================================================
// Console
//======================================================================
- (void) showConsolePanel:sender
{
NSString *nibFile;
BOOL loaded;
if (consoleWindow == nil)
{
nibFile = @"PlayerConsole.nib";
loaded = [NSBundle loadNibNamed:nibFile owner:self];
NSAssert1 (loaded == YES, @"Could not load %@.", nibFile);
[consoleWindow setTitle:[NSString stringWithFormat:@"Player %d Console", playerNumber]];
}
[consoleWindow orderFront:self];
}
//----------------------------------------------------------------------
// Appends a formatted string to the console window, if it is visible.
// Subclasses can use this to show debugging information.
//----------------------------------------------------------------------
- (void) logMessage:(NSString *)format, ...
{
NSRange selected;
NSMutableString *str;
va_list ap;
if (consoleMessageText != nil)
{
va_start(ap, format);
str = [[[NSMutableString alloc] initWithFormat:format arguments:ap] autorelease];
[str appendString:@"\n"];
va_end(ap);
[consoleMessageText selectAll:nil];
selected = [consoleMessageText selectedRange];
selected.location = selected.length;
selected.length = 0;
[consoleMessageText setSelectedRange:selected];
[consoleMessageText replaceCharactersInRange:selected withString:str];
[consoleMessageText scrollRangeToVisible:selected];
if ([pauseForContinueButton state] == 1)
[self waitForContinue];
}
}
//----------------------------------------------------------------------
- (void) waitForContinue
{
[consoleWindow orderFront:self];
[NSApp runModalForWindow:consoleWindow];
}
//----------------------------------------------------------------------
- (void) continueAction:sender
{
[NSApp stopModal];
}
//----------------------------------------------------------------------
- (void) pauseCheckAction:sender
{
[NSApp stopModal];
if ([sender state] == 1)
{
[continueButton setEnabled:YES];
}
else
{
[continueButton setEnabled:NO];
}
}
//======================================================================
// Subclass Responsibilities
//======================================================================
//----------------------------------------------------------------------
// Returns YES if this is an interactive player that will use the
// shared panels to direct movement. Human's implementation returns
// YES; only subclasses that want to use the shared panels and refine
// the interactive behavior should override this method to return YES.
//----------------------------------------------------------------------
- (BOOL) isInteractive
{
return NO;
}
//----------------------------------------------------------------------
// Card management
//----------------------------------------------------------------------
//----------------------------------------------------------------------
// Notifies the player at the beginning of a turn that it has at least
// one card set that may be turned in. This allows computer players to
// turn in cards before they get the -placeArmies: message. If the
// player has more than four cards, -mustTurnInCards is called instead.
//----------------------------------------------------------------------
- (void) mayTurnInCards
{
}
//----------------------------------------------------------------------
// Notifies the player at the beginning of a turn that it must turn in
// card sets. This happens when the player has more than four cards.
// If a player still doesn't turn in cards, some cards will
// automatically be turned in before continuing.
//----------------------------------------------------------------------
- (void) mustTurnInCards
{
}
//----------------------------------------------------------------------
// Notifies the player about the number of extra armies that were
// awarded as a result of turning in a card set. This is useful for
// the Human player to allow it to update the number of armies left to
// place, since it turns in cards after receiving the -placeArmies:
// message.
//----------------------------------------------------------------------
- (void) didTurnInCards:(int)extraArmyCount
{
}
//----------------------------------------------------------------------
// Initial game phases
//----------------------------------------------------------------------
//----------------------------------------------------------------------
// Notifies the player that the players will begin choosing countries.
// Currently, this is called before *any* player has chosen a country.
//----------------------------------------------------------------------
- (void) willBeginChoosingCountries
{
}
//----------------------------------------------------------------------
// The player should choose a single unoccupied country by calling
// RiskGameManager -player:choseCountry:.
//----------------------------------------------------------------------
- (void) chooseCountry
{
NSArray *unoccupiedCountries;
Country *country;
unoccupiedCountries = [gameManager unoccupiedCountries];
country = [unoccupiedCountries objectAtIndex:[[self rng] randomNumberModulo:[unoccupiedCountries count]]];
[gameManager player:self choseCountry:country];
// Possible to choose more than one country...
[self turnDone];
}
//----------------------------------------------------------------------
// Notifies the player that all of the countries have been chosen.
//----------------------------------------------------------------------
- (void) willEndChoosingCountries
{
}
//----------------------------------------------------------------------
// Notifies the player that the players will begin placing the initial
// armies. Currently, this is called before *any* player has placed
// initial armies.
//----------------------------------------------------------------------
- (void) willBeginPlacingInitialArmies
{
}
//----------------------------------------------------------------------
// The player should place 'count' armies among any of their countries
// by calling RiskGameManager -player:placesArmies:inCountry:, and then
// call self -turnDone.
//----------------------------------------------------------------------
- (void) placeInitialArmies:(int)count
{
[self turnDone];
}
//----------------------------------------------------------------------
// Notifies the player that all of the players have finished placing
// their initial armies.
//----------------------------------------------------------------------
- (void) willEndPlacingInitialArmies
{
}
//----------------------------------------------------------------------
// Notifies the player that they have lost the game.
//----------------------------------------------------------------------
- (void) youLostGame
{
//NSLog (@"(%d) %@ has lost the game.", playerNumber, playerName);
}
//----------------------------------------------------------------------
// Notifies the player that they have won the game.
//----------------------------------------------------------------------
- (void) youWonGame
{
//NSLog (@"(%d) %@ has won the game.", playerNumber, playerName);
}
//----------------------------------------------------------------------
// Regular turn phases
//----------------------------------------------------------------------
//----------------------------------------------------------------------
// Notifies the player that their turn will begin.
//----------------------------------------------------------------------
- (void) willBeginTurn
{
}
//----------------------------------------------------------------------
// Notifies the player that they should place 'count' armies among any
// of their countries by calling
// RiskGameManager -player:placesArmies:inCountry:, and then call
// self -turnDone.
//----------------------------------------------------------------------
- (void) placeArmies:(int)count
{
[self turnDone];
}
//----------------------------------------------------------------------
// Notifies the player that they may attack other players. When done,
// it should call self -turnDone.
//----------------------------------------------------------------------
- (void) attackPhase
{
[self turnDone];
}
//----------------------------------------------------------------------
// Notifies the player that they should distribute 'count' armies
// between the source and destination countries. This is the result of
// a successful attack. The minimum number of armies have already been
// moved into the destination country. When done, it should call
// self -turnDone.
//----------------------------------------------------------------------
- (void) moveAttackingArmies:(int)count between:(Country *)source:(Country *)destination
{
[self turnDone];
}
//----------------------------------------------------------------------
// Notifies the player that they may fortify armies under the given
// 'fortifyRule'. The player may call -turnDone to skip fortification,
// or call RiskGameManager -fortifyArmiesFrom: to specify the source
// country for fortification. If multiple sources are allowed, this
// method will be called again, otherwise the game will automatically
// proceed to the next phase.
//----------------------------------------------------------------------
// Call either -turnDone or -fortifyArmiesFrom:
- (void) fortifyPhase:(FortifyRule)fortifyRule
{
[self turnDone];
}
//----------------------------------------------------------------------
// Notifies the player that they should place 'count' fortifying armies
// from the source country by calling
// RiskGameManager -player:placesArmies:inCountry:, and then call
// self -turnDone. The current fortify rule will determine the valid
// destination countries. Armies that are not placed will be lost.
//----------------------------------------------------------------------
- (void) placeFortifyingArmies:(int)count fromCountry:(Country *)source
{
[self turnDone];
}
//----------------------------------------------------------------------
// Notifies the player that their turn has ended.
//----------------------------------------------------------------------
- (void) willEndTurn
{
}
//======================================================================
// Inform computer players of important events that happed during other
// players turns.
//======================================================================
//----------------------------------------------------------------------
// Notifies this player that player 'number' attacked one of this
// players countries, attackedCountry. An advanced computer player
// could use this information, for example, to bias future attacks
// against the most antagonistic player.
//----------------------------------------------------------------------
- (void) playerNumber:(Player)number attackedCountry:(Country *)attackedCountry
{
}
//----------------------------------------------------------------------
// Notifies this player that player 'number' captured one of this
// players cuntries, capturedCountry. An advanced computer player
// could use this information, for example, to bias future attacks
// against the most antagonistic player.
//----------------------------------------------------------------------
- (void) playerNumber:(Player)number capturedCountry:(Country *)capturedCountry
{
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.