This is Human.m in view mode; [Download] [Up]
//
// $Id: Human.m,v 1.3 1997/10/31 03:38:30 nygard Exp $
//
//
// This file is a part of Empire, a game of exploration and conquest.
// Copyright (C) 1996 Steve Nygard
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// You may contact the author by:
// e-mail: nygard@telusplanet.net
//
#import "Empire.h"
RCSID ("$Id: Human.m,v 1.3 1997/10/31 03:38:30 nygard Exp $");
#import "Human.h"
#import "Brain.h"
#import "City.h"
#import "CombatEvent.h"
#import "DistributedGameManager.h"
#import "EmInspectorManager.h"
#import "Map.h"
#import "MapPathView.h"
#import "Unit.h"
#import "WorldMapController.h"
#import "HState.h"
#import "HCombatReportState.h"
#import "HDirectionState.h"
#import "HEscortShipState.h"
#import "HFlightPathState.h"
#import "HIdleState.h"
#import "HInitialState.h"
#import "HMoveState.h"
#import "HMoveToState.h"
#import "HPatrolToState.h"
#import "HProductionState.h"
#import "HSetFlightPathState.h"
#import "HSurveyState.h"
#import "HGameOverState.h"
//======================================================================
@implementation Human
- (void) awakeFromNib
{
NSString *imagePath;
NSImage *image;
imagePath = [[NSBundle mainBundle] pathForImageResource:@"mwi_map.tiff"];
NSAssert (imagePath != nil, @"Couldn't find mwi_map.tiff");
image = [[[NSImage alloc] initWithContentsOfFile:imagePath] autorelease];
NSAssert (image != nil, @"Couldn't load mwi_map.tiff");
[playerWindow setMiniwindowImage:image];
[self retain]; // Released when window closed
}
//----------------------------------------------------------------------
- initWithName:(NSString *)aName number:(Player)number world:(Map *)aMap
capital:(City *)capitalCity withEfficiencies:(int)pe:(int)ce
gameManager:(GameManager *)theGameManager
{
EMMapLocation cityLocation;
NSRect frameRect;
BOOL loaded;
[super initWithName:aName
number:number
world:aMap
capital:capitalCity
withEfficiencies:pe:ce
gameManager:theGameManager];
loaded = [NSBundle loadNibNamed:@"Human.nib" owner:self];
NSAssert (loaded == YES, @"Could not load Human.nib");
frameRect = [playerWindow frame];
frameRect.origin.x += number * 24;
frameRect.origin.y -= number * 24;
[playerWindow setFrameOrigin:frameRect.origin];
[mapView setMap:map];
cityLocation = [capitalCity cityLocation];
[mapView positionCursorAtLocation:cityLocation];
[mapView centerScreenAroundCursor];
[playerWindow makeFirstResponder:mapView];
[playerWindow setTitle:[NSString stringWithFormat:@"Player %d - %@", number, aName]];
[mapView useDefaultCursor];
[mapView setCursorEnabled:YES];
[turnNumberTextfield setIntValue:0];
//[playerWindow setFrame:frameRect display:YES];
[playerWindow orderFront:nil];
state = nil;
savedStateKey = nil;
selectedUnit = nil;
worldMapController = nil;
selectedCity = nil;
combatEvents = [[NSMutableArray array] retain];
savedMap = nil;
stateGroup = [[NSMutableDictionary dictionary] retain];
[stateGroup setObject:[[[HCombatReportState alloc] initWithGameManager:gameManager] autorelease] forKey:HS_COMBAT_REPORT];
[stateGroup setObject:[[[HDirectionState alloc] initWithGameManager:gameManager] autorelease] forKey:HS_DIRECTION];
[stateGroup setObject:[[[HEscortShipState alloc] initWithGameManager:gameManager] autorelease] forKey:HS_ESCORT_SHIP];
[stateGroup setObject:[[[HFlightPathState alloc] initWithGameManager:gameManager] autorelease] forKey:HS_FLIGHT_PATH];
[stateGroup setObject:[[[HIdleState alloc] initWithGameManager:gameManager] autorelease] forKey:HS_IDLE];
[stateGroup setObject:[[[HInitialState alloc] initWithGameManager:gameManager] autorelease] forKey:HS_INITIAL];
[stateGroup setObject:[[[HMoveState alloc] initWithGameManager:gameManager] autorelease] forKey:HS_MOVE];
[stateGroup setObject:[[[HMoveToState alloc] initWithGameManager:gameManager] autorelease] forKey:HS_MOVE_TO];
[stateGroup setObject:[[[HPatrolToState alloc] initWithGameManager:gameManager] autorelease] forKey:HS_PATROL_TO];
[stateGroup setObject:[[[HProductionState alloc] initWithGameManager:gameManager] autorelease] forKey:HS_PRODUCTION];
[stateGroup setObject:[[[HSetFlightPathState alloc] initWithGameManager:gameManager] autorelease] forKey:HS_SET_FLIGHT_PATH];
[stateGroup setObject:[[[HSurveyState alloc] initWithGameManager:gameManager] autorelease] forKey:HS_SURVEY];
[stateGroup setObject:[[[HGameOverState alloc] initWithGameManager:gameManager] autorelease] forKey:HS_GAME_OVER];
[self changeState:HS_IDLE];
return self;
}
//----------------------------------------------------------------------
- (void) dealloc
{
SNRelease (worldMapController);
SNRelease (savedStateKey);
SNRelease (stateGroup);
SNRelease (combatEvents);
SNRelease (savedMap);
[super dealloc];
}
//======================================================================
// Turn phases
//======================================================================
- (void) yourTurn:(int)turn
{
[map detach:self];
[super yourTurn:turn];
selectedUnit = nil;
[turnNumberTextfield setIntValue:turn];
if ([playerWindow isVisible] == YES)
[playerWindow makeKeyAndOrderFront:self];
if (state != nil)
[state beginTurn:self];
}
//======================================================================
// Interface Management
//======================================================================
- (void) continue:sender
{
if (state != nil)
[state continue:self];
}
//----------------------------------------------------------------------
- (void) endTurn:sender
{
if (state != nil)
[state endTurn:self];
[combatEvents removeAllObjects];
SNRelease (savedMap);
savedMap = [map copyWithZone:[self zone]];
[map attach:self];
}
//----------------------------------------------------------------------
- (void) enableContinueButton:(BOOL)flag
{
if (flag == NO && [playerWindow firstResponder] == continueButton)
[playerWindow makeFirstResponder:endTurnButton];
[continueButton setEnabled:flag];
}
//----------------------------------------------------------------------
- (void) enableEndTurnButton:(BOOL)flag
{
[endTurnButton setEnabled:flag];
if (flag == NO && [playerWindow firstResponder] == endTurnButton)
[playerWindow makeFirstResponder:mapView];
//[playerWindow makeFirstResponder:continueButton];
}
//----------------------------------------------------------------------
// Hmm. Always default to NO, and if super returns NO, run through our checks?
- (BOOL) validateMenuItem:(NSMenuItem *)menuCell
{
SEL action = [menuCell action];
BOOL valid = NO;
if (action == @selector (showCrystalBall:)
|| action == @selector (toggleBerserk:)
|| action == @selector (stopGame:))
{
valid = [super validateMenuItem:menuCell];
}
else if (action == @selector (showWarReport:))
{
valid = gameOver == NO;
}
else if (action == @selector (showWorldMap:)
|| action == @selector (showShipReport:))
{
valid = YES;
}
else if (action == @selector (resignFromGame:))
{
valid = YES;
}
else if (state != nil)
{
valid = [state validateMenuItem:self:menuCell];
}
return valid;
}
//----------------------------------------------------------------------
- (void) clickActiveButton
{
if ([endTurnButton isEnabled] == YES)
[endTurnButton performClick:nil];
else if ([continueButton isEnabled] == YES)
[continueButton performClick:nil];
}
//----------------------------------------------------------------------
- (void) setStatusLine:(NSString *)text
{
if (text != nil)
[statusTextfield setStringValue:text];
}
//----------------------------------------------------------------------
- (void) selectThing:object
{
[[EmInspectorManager instance] player:playerNumber selectThing:object];
}
//----------------------------------------------------------------------
- (void) selectUnit:(Unit *)aUnit
{
selectedUnit = aUnit;
}
//----------------------------------------------------------------------
- (MapView *) mapView
{
return mapView;
}
//======================================================================-
// Commands
//======================================================================-
- (void) moveMode:sender
{
if (state != nil)
[state moveMode:self];
}
//----------------------------------------------------------------------
- (void) surveyMode:sender
{
if (state != nil)
[state surveyMode:self];
}
//----------------------------------------------------------------------
- (void) groupMode:sender
{
if (state != nil)
[state groupMode:self];
}
//----------------------------------------------------------------------
- (void) wait:sender
{
if (state != nil && selectedUnit != nil)
[state wait:self unit:selectedUnit];
}
//----------------------------------------------------------------------
- (void) flightPaths:sender
{
if (state != nil)
[state flightPathMode:self];
}
//----------------------------------------------------------------------
- (void) activateUnit:sender
{
if (state != nil && selectedUnit != nil)
[state activate:self unit:selectedUnit];
}
//----------------------------------------------------------------------
- (void) centerScreen:sender
{
if (state != nil)
[state centerScreen:self mapView:mapView];
}
//----------------------------------------------------------------------
- (void) centerCursor:sender
{
if (state != nil)
[state centerCursor:self mapView:mapView];
}
//----------------------------------------------------------------------
- (void) centerSelected:sender
{
if (state != nil)
[state centerSelected:self mapView:mapView];
}
//======================================================================
// End of game Reports
//======================================================================
- (void) showFinalCombinedMap:sender
{
if (state != nil)
[state showFinalMap:self forPlayer:p_neutral];
}
//----------------------------------------------------------------------
- (void) showFinalPlayer1Map:sender
{
if (state != nil)
[state showFinalMap:self forPlayer:p_player1];
}
//----------------------------------------------------------------------
- (void) showFinalPlayer2Map:sender
{
if (state != nil)
[state showFinalMap:self forPlayer:p_player2];
}
//----------------------------------------------------------------------
- (void) showFinalPlayer3Map:sender
{
if (state != nil)
[state showFinalMap:self forPlayer:p_player3];
}
//----------------------------------------------------------------------
- (void) showFinalMapForPlayer:(Player)number
{
if (finalMaps[number] == nil)
return;
if (number == p_neutral)
[statusTextfield setStringValue:@"Final Combined Map"];
else
[statusTextfield setStringValue:[NSString stringWithFormat:@"Final Player %d Map", number]];
// main and world maps...
[mapView setMap:finalMaps[number]];
if (worldMapController != nil)
{
[worldMapController setMap:finalMaps[number]];
}
}
//======================================================================-
// Orders
//======================================================================-
- (void) goDirection:sender
{
if (state != nil)
[state goDirection:self];
}
//----------------------------------------------------------------------
- (void) goHome:sender
{
if (state != nil && selectedUnit != nil)
[state goHome:self unit:selectedUnit];
}
//----------------------------------------------------------------------
- (void) goRandom:sender
{
if (state != nil && selectedUnit != nil)
[state goRandom:self unit:selectedUnit];
}
//----------------------------------------------------------------------
- (void) moveTo:sender
{
if (state != nil)
[state moveTo:self];
}
//----------------------------------------------------------------------
- (void) patrolTo:sender
{
if (state != nil)
[state patrolTo:self];
}
//----------------------------------------------------------------------
- (void) escortShip:sender
{
if (state != nil)
[state escortShip:self];
}
//----------------------------------------------------------------------
- (void) explore:sender
{
if (state != nil && selectedUnit != nil)
[state explore:self unit:selectedUnit];
}
//----------------------------------------------------------------------
- (void) sentry:sender
{
if (state != nil && selectedUnit != nil)
[state sentry:self unit:selectedUnit];
}
//----------------------------------------------------------------------
- (void) clearOrders:sender
{
if (state != nil)
{
if (selectedUnit != nil)
{
[state activate:self unit:selectedUnit];
//[state clearOrders:self unit:selectedUnit];
}
else
{
City *city = [self cityAtLocation:[mapView cursorLocation]];
[state clearOrders:self city:city];
}
}
}
//----------------------------------------------------------------------
- (void) loadShip:sender
{
if (state != nil && selectedUnit != nil)
[state loadShip:self unit:selectedUnit];
}
//----------------------------------------------------------------------
- (void) unloadShip:sender
{
if (state != nil && selectedUnit != nil)
[state unloadShip:self unit:selectedUnit];
}
//----------------------------------------------------------------------
- (void) skipMove:sender
{
if (state != nil && selectedUnit != nil)
[state skipMove:self unit:selectedUnit];
}
//----------------------------------------------------------------------
- (void) resignFromGame:sender
{
NSAssert (gameOver == NO, @"The game is already over.");
// Confirm..
[self resign];
}
//======================================================================
// Reports
//======================================================================
- (void) showCombatReport:sender
{
if (state != nil)
[state combatReport:self];
}
//----------------------------------------------------------------------
- (void) showProductionMap:sender
{
if (state != nil)
[state productionMap:self];
}
//----------------------------------------------------------------------
- (void) showShipReport:sender
{
[gameManager showShipReport:sender forPlayer:self];
}
//----------------------------------------------------------------------
// We need the game manager to have a world, so that we can get the
// worldCityCount for the war report even after the game is over.
//----------------------------------------------------------------------
- (void) showWarReport:sender
{
NSAssert (gameOver == NO, @"The game is over.");
[gameManager showWarReport:sender forPlayer:self];
}
//----------------------------------------------------------------------
- (void) showWorldMap:sender
{
if (worldMapController == nil)
{
worldMapController = [[WorldMapController alloc] init];
[worldMapController setMap:map];
[worldMapController setDelegate:self];
[worldMapController setTitle:[NSString stringWithFormat:@"Player %d World Map", playerNumber] autosaveFrame:YES];
}
[worldMapController showPanel];
}
//======================================================================
// MapView delegate
//======================================================================
- (void) mouseDown:(unsigned int)modifierFlags atLocation:(EMMapLocation)target
{
if (state != nil)
[state mouseDown:self:modifierFlags atLocation:target];
}
//----------------------------------------------------------------------
- (void) mouseUp:(unsigned int)modifierFlags atLocation:(EMMapLocation)target
{
if (state != nil)
[state mouseUp:self:modifierFlags atLocation:target];
}
//----------------------------------------------------------------------
- (void) rightMouseDown:(unsigned int)modifierFlags atLocation:(EMMapLocation)target
{
if (state != nil)
[state rightMouseDown:self:modifierFlags atLocation:target];
}
//----------------------------------------------------------------------
- (void) rightMouseUp:(unsigned int)modifierFlags atLocation:(EMMapLocation)target
{
if (state != nil)
[state rightMouseUp:self:modifierFlags atLocation:target];
}
//----------------------------------------------------------------------
- (void) keyDown:(NSEvent *)theEvent
{
if (state != nil)
[state keyDown:self:theEvent];
}
//======================================================================
// Window Delegate
//======================================================================
- (BOOL) windowShouldClose:sender
{
BOOL shouldClose = YES;
int result;
// This may also be the delegate of the world map window.
// Only if still connected, running...
if (sender == playerWindow && gameOver == NO)
{
result = NSRunAlertPanel (@"Exit Game", @"Closing this window will end the game for player %d.",
@"Keep playing", @"Exit game", nil, playerNumber);
shouldClose = result == NSAlertAlternateReturn;
if (shouldClose == YES)
{
// Notify game manager...
[self resignFromGame:nil];
}
}
return shouldClose;
}
//----------------------------------------------------------------------
- (void) windowWillClose:(NSNotification *)aNotification
{
NSWindow *window;
window = [aNotification object];
if (window == playerWindow)
{
[self autorelease]; // Important for timing.
}
}
//======================================================================
// End of player
//======================================================================
- (void) gameStopped:(int)activePlayers
{
[super gameStopped:activePlayers];
[self changeState:HS_GAME_OVER];
[self setStatusLine:@"The game has been stopped."];
}
//----------------------------------------------------------------------
// Returns YES to continue playing, NO to stop game.
// Does this block (whirling disk) the server?
//----------------------------------------------------------------------
- (BOOL) playerHasWon:(int)activePlayers
{
BOOL keepPlaying = YES;
int result;
result = NSRunAlertPanel (@"Game Over", @"Player %d has won.", @"End Game", @"Continue Moving", nil, playerNumber);
if (result == NSAlertDefaultReturn)
{
[super playerHasWon:activePlayers];
[self changeState:HS_GAME_OVER];
[self setStatusLine:@"You win."];
keepPlaying = NO;
}
return keepPlaying;
}
//----------------------------------------------------------------------
- (void) playerHasLost:(int)activePlayers
{
[super playerHasLost:activePlayers];
[self changeState:HS_GAME_OVER];
[self setStatusLine:@"All your cities have been captured."];
}
//----------------------------------------------------------------------
- (void) playerHasResigned:(int)activePlayers
{
[super playerHasResigned:activePlayers];
[self changeState:HS_GAME_OVER];
[self setStatusLine:@"You have resigned from the game."];
}
//======================================================================
// HState Management
//======================================================================
- (void) changeState:(NSString *)newStateName
{
HState *newState;
newState = [stateGroup objectForKey:newStateName];
NSAssert1 (newState != nil, @"Couldn't find state '%@' in group.", newStateName);
if (state != nil)
[state stateExited:self];
state = newState;
[modeTextfield setStringValue:[state stateName]];
[state stateEntered:self];
}
//----------------------------------------------------------------------
- (void) saveState
{
// We can only save one state at a time.
NSAssert (savedStateKey == nil, @"Saved state not nil.");
savedStateKey = [[state stateKey] retain];
}
//----------------------------------------------------------------------
- (void) restoreState
{
NSAssert (savedStateKey != nil, @"Saved state is nil");
[self changeState:savedStateKey];
SNRelease (savedStateKey);
}
//======================================================================
// HState Access
//======================================================================
- (City *) selectedCity
{
return selectedCity;
}
//----------------------------------------------------------------------
- (void) selectCity:(City *)city
{
selectedCity = city;
}
//----------------------------------------------------------------------
- (Map *) finalMapForPlayer:(Player)number
{
return finalMaps[number];
}
//======================================================================
// Combat Report
//======================================================================
- (Map *) savedMap
{
return savedMap;
}
//----------------------------------------------------------------------
- (NSArray *) combatEvents
{
return combatEvents;
}
//======================================================================
// Map Delegate
//======================================================================
//----------------------------------------------------------------------
// The methods record combat events. They are only observed while
// other players are playing their turns.
//----------------------------------------------------------------------
- (void) refreshLocation:(EMMapLocation)target
{
[combatEvents addObject:[CombatEvent updateAtLocation:target ofMap:map]];
}
//----------------------------------------------------------------------
- (void) refresh3x3Location:(EMMapLocation)target
{
[combatEvents addObject:[CombatEvent update3x3AroundLocation:target ofMap:map]];
}
//----------------------------------------------------------------------
- (void) strippedIconsOfPlayer:(Player)number
{
[combatEvents addObject:[CombatEvent stripIconsOfPlayer:number]];
}
//======================================================================
// Other
//======================================================================
- (void) showExplosions:(int)count atLocation:(EMMapLocation)target
{
[super showExplosions:count atLocation:target];
[mapView showExplosions:count atLocation:target];
}
//======================================================================
// Subclass Notifications
//======================================================================
- (void) selectedUnitTriedToMove:(MoveResult)moveResult
{
[super selectedUnitTriedToMove:moveResult];
if (moveResult == mr_moved || moveResult == mr_victory)
{
[mapView setCursorEnabled:NO];
[mapView positionCursorAtLocation:[selectedUnit unitLocation]];
[mapView setCursorEnabled:YES];
}
else if (moveResult == mr_destroyed)
{
[mapView setCursorEnabled:NO];
}
else if (moveResult == mr_blocked)
{
[mapView setFastCursor:YES];
}
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.