This is HSurveyState.m in view mode; [Download] [Up]
//
// $Id: HSurveyState.m,v 1.3 1997/10/31 03:38:28 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: HSurveyState.m,v 1.3 1997/10/31 03:38:28 nygard Exp $");
#import "HSurveyState.h"
#import "City.h"
#import "GameManager.h"
#import "HCombatReportState.h"
#import "HDirectionState.h"
#import "HEscortShipState.h"
#import "HFlightPathState.h"
#import "HIdleState.h"
#import "HMoveState.h"
#import "HMoveToState.h"
#import "HPatrolToState.h"
#import "HProductionState.h"
#import "Human.h"
#import "Map.h"
#import "MapView.h"
#import "Unit.h"
#import "../Orders.subproj/Orders.h"
//======================================================================
// This state gives the user another chance to change commands of
// units before the turn ends. The user can give them orders which will
// be executed on the next turn.
//======================================================================
@implementation HSurveyState
- initWithGameManager:(GameManager *)theGameManager
{
[super initWithGameManager:theGameManager];
draggingFromUnit = NO;
return self;
}
//======================================================================
// Subclass responsibilities
//======================================================================
- (NSString *) stateName
{
return @"Survey";
}
//----------------------------------------------------------------------
- (NSString *) stateKey
{
return HS_SURVEY;
}
//----------------------------------------------------------------------
- (void) stateEntered:(Human *)context
{
MapView *mapView = [context mapView];
EMMapLocation cursorLocation;
draggingFromUnit = NO;
[mapView enableCompressedEvents:YES];
[mapView useDefaultCursor];
[mapView setFastCursor:NO];
[mapView setCursorEnabled:YES];
[context setStatusLine:@""];
// Disable both buttons
[context enableContinueButton:NO];
if ([context nextUnitAwaitingMovement] == nil) // clears selected unit..
{
[context enableEndTurnButton:YES];
if ([gameManager isBerserk] == YES)
{
[self endTurn:context];
}
else
{
cursorLocation = [mapView cursorLocation];
[self selectThing:context atLocation:cursorLocation andInspect:YES];
}
}
else
{
[context enableEndTurnButton:NO];
//[context selectUnit:[context nextUnit]];
cursorLocation = [mapView cursorLocation];
[self selectThing:context atLocation:cursorLocation andInspect:YES];
[context setStatusLine:[[context selectedUnit] statusLine]];
}
}
//----------------------------------------------------------------------
- (void) endTurn:(Human *)context
{
// Should this be executed when we enter the idle state?
// I don't think so -- we "enter" the idle state upon startup, but
// don't want to execute this code.
[context turnDone];
[context changeState:HS_IDLE];
}
//----------------------------------------------------------------------
- (void) combatReport:(Human *)context
{
[context saveState];
[context changeState:HS_COMBAT_REPORT];
}
//----------------------------------------------------------------------
// This is a bit unusual: You can select nothing, drag over a unit, and
// it will enter the MoveTo state...
- (void) mouseDown:(Human *)context:(unsigned int)modifierFlags atLocation:(EMMapLocation)target
{
Map *map = [context map];
MapToken mapToken = [map tokenAtLocation:target];
Unit *unit;
EMMapLocation unitLocation;
Player player;
Icon icon;
BOOL explored;
[[context mapView] positionCursorAtLocation:target];
//[context selectUnit:nil];
EMMapTokenComponents (mapToken, NULL, &player, &icon, &explored);
if (draggingFromUnit == NO
&& player == [context playerNumber]
&& icon != i_none
&& explored == YES)
{
unit = [context unitWithType:EMConvertIconToUnitType (icon) atLocation:target];
if (unit != nil)
{
[context selectUnit:unit];
[context setStatusLine:[unit statusLine]];
draggingFromUnit = YES;
}
}
else
{
[context setStatusLine:[NSString stringWithFormat:@"Loc: %d,%d", target.row, target.column]];
unit = [context selectedUnit];
unitLocation = [unit unitLocation];
if (draggingFromUnit == YES && unit != nil && (target.row != unitLocation.row || target.column != unitLocation.column))
{
[context saveState];
if ((modifierFlags & NSControlKeyMask) != 0)
[context changeState:HS_PATROL_TO];
else
[context changeState:HS_MOVE_TO];
}
}
}
//----------------------------------------------------------------------
- (void) mouseUp:(Human *)context:(unsigned int)modifierFlags atLocation:(EMMapLocation)target
{
[self selectThing:context atLocation:target andInspect:YES];
draggingFromUnit = NO;
}
//----------------------------------------------------------------------
- (void) rightMouseUp:(Human *)context:(unsigned int)modifierFlags atLocation:(EMMapLocation)target
{
[self moveMode:context];
}
//----------------------------------------------------------------------
- (void) keyDown:(Human *)context:(NSEvent *)theEvent
{
NSString *eventCharacters = [theEvent characters];
unichar uc = [eventCharacters characterAtIndex:0];
// I'm going to assume that this is okay, because the alternatives
// seem worse.
switch (uc)
{
case '5':
case 'c':
case 'C':
[context centerScreen:nil];
break;
case 'd':
case 'D':
[context goDirection:nil];
break;
case 'e':
case 'E':
[context escortShip:nil];
break;
case 'h':
case 'H':
[context goHome:nil];
break;
case 'l':
case 'L':
[context loadShip:nil];
break;
case 'm':
case 'M':
[self moveMode:context];
break;
case 'o':
case 'O':
// Can clear orders for city too.
//[context activateUnit:nil];
[context clearOrders:nil];
break;
case 'p':
case 'P':
[self patrolTo:context];
break;
case 'r':
case 'R':
[context goRandom:nil];
break;
case 'S':
case 's':
[context sentry:nil];
break;
case 't':
case 'T':
[context moveTo:nil];
break;
case 'u':
case 'U':
[context unloadShip:nil];
break;
case 'x':
case 'X':
[context explore:nil];
break;
case 3: // This is the Enter key on the number pad... at least, on my machine.
[context clickActiveButton];
break;
default:
[super keyDown:context:theEvent];
break;
}
}
//======================================================================
// Commands
//======================================================================
- (void) moveMode:(Human *)context
{
if ([context nextUnitAwaitingMovement] != nil)
[context changeState:HS_MOVE];
}
//----------------------------------------------------------------------
- (void) flightPathMode:(Human *)context
{
[context saveState];
[context changeState:HS_FLIGHT_PATH];
}
//----------------------------------------------------------------------
- (void) activate:(Human *)context unit:(Unit *)aUnit
{
[self clearOrders:context unit:aUnit];
[context activateThisUnit:aUnit];
[self moveMode:context];
}
//----------------------------------------------------------------------
- (void) centerScreen:(Human *)context mapView:(MapView *)mapView
{
[mapView centerScreenAroundCursor];
}
//----------------------------------------------------------------------
- (void) productionMap:(Human *)context
{
[context saveState];
[context changeState:HS_PRODUCTION];
}
//======================================================================
// Orders
//======================================================================
- (void) goDirection:(Human *)context
{
[context saveState];
[context changeState:HS_DIRECTION];
}
//----------------------------------------------------------------------
- (void) goHome:(Human *)context unit:(Unit *)aUnit
{
City *target_city;
// Find nearest city.
target_city = [context ourCityNearestToLocation:[aUnit unitLocation]];
if (target_city != nil)
{
Order *order;
// Set orders to move to that coordinate.
order = [[[OShortestMoveTo alloc] initForUnit:aUnit
moveToLocation:[target_city cityLocation]
onMap:[context map]] autorelease];
[aUnit setOrder:order];
[context setStatusLine:[aUnit statusLine]];
}
}
//----------------------------------------------------------------------
- (void) goRandom:(Human *)context unit:(Unit *)aUnit
{
[aUnit setOrder:[[[ORandom alloc] initForUnit:aUnit] autorelease]];
[context setStatusLine:[aUnit statusLine]];
}
//----------------------------------------------------------------------
- (void) escortShip:(Human *)context
{
[context saveState];
[context changeState:HS_ESCORT_SHIP];
}
//----------------------------------------------------------------------
- (void) moveTo:(Human *)context
{
[context saveState];
[context changeState:HS_MOVE_TO];
}
//----------------------------------------------------------------------
- (void) patrolTo:(Human *)context
{
[context saveState];
[context changeState:HS_PATROL_TO];
}
//----------------------------------------------------------------------
- (void) explore:(Human *)context unit:(Unit *)unit
{
[unit setOrder:[[[OExplore alloc] initForUnit:unit explore:[context map]] autorelease]];
[self continueWithContext:context];
}
//----------------------------------------------------------------------
- (void) sentry:(Human *)context unit:(Unit *)aUnit
{
[aUnit setOrder:[[[OSentry alloc] initForUnit:aUnit] autorelease]];
[context setStatusLine:[aUnit statusLine]];
}
//----------------------------------------------------------------------
- (void) clearOrders:(Human *)context unit:(Unit *)aUnit
{
[aUnit setOrder:nil];
[context setStatusLine:[aUnit statusLine]];
}
//----------------------------------------------------------------------
// Clear orders, but don't activate units (i.e. do not put in the
// units awaiting movement list, even if they can move.)
//----------------------------------------------------------------------
- (void) clearOrders:(Human *)context city:(City *)aCity
{
NSEnumerator *unitEnumerator = [[aCity cityUnits] objectEnumerator];
int count = 0;
Unit *unit;
while (unit = [unitEnumerator nextObject])
{
count++;
[unit setOrder:nil];
}
[context setStatusLine:[NSString stringWithFormat:@"Orders cleared for %d unit%@.", count, (count == 1) ? @"" : @"s"]];
}
//----------------------------------------------------------------------
- (void) loadShip:(Human *)context unit:(Unit *)aUnit
{
UnitType unitType = [aUnit unitType];
if (unitType == u_transport || unitType == u_carrier)
{
[aUnit setOrder:[[[OLoadShip alloc] initForUnit:aUnit] autorelease]];
// May lead to inconsistency -- continueWithContext...
//[context activateThisUnit:aUnit];
[self continueWithContext:context];
}
}
//----------------------------------------------------------------------
- (void) unloadShip:(Human *)context unit:(Unit *)aUnit
{
#if NYC
[aUnit unloadShip];
[context wait:nil];
#endif
}
//----------------------------------------------------------------------
- (void) skipMove:(Human *)context unit:(Unit *)aUnit
{
[aUnit skipMove];
[context setStatusLine:[aUnit statusLine]];
}
//======================================================================
// Interface Management
//======================================================================
- (BOOL) validateMenuItem:(Human *)context:(NSMenuItem *)menuCell
{
SEL action = [menuCell action];
BOOL valid = NO;
//Unit *unit = [context selectedUnit];
// Commands
if (action == @selector (moveMode:))
{
//valid = ([context selectedUnit] == nil) ? NO : YES;
valid = YES;
}
else if (action == @selector (surveyMode:))
{
valid = NO;
}
else if (action == @selector (groupMode:))
{
valid = NO;
}
else if (action == @selector (wait:))
{
valid = NO;
}
else if (action == @selector (flightPaths:))
{
valid = YES;
}
else if (action == @selector (activateUnit:))
{
//printf ("selectedUnit: %p\n", [context selectedUnit]);
//valid = ([context selectedUnit] != nil && [[context selectedUnit] currentRange] > 0) ? YES : NO;
valid = YES;
}
else if (action == @selector (centerScreen:)
|| action == @selector (centerCursor:))
{
//valid = [[context mapView] cursorEnabled];
valid = YES;
}
else if (action == @selector (showProductionMap:)
|| action == @selector (showCombatReport:))
{
valid = YES;
}
// Orders
else if (action == @selector (goDirection:)
|| action == @selector (goHome:)
|| action == @selector (goRandom:) // Not for fighter
|| action == @selector (moveTo:)
|| action == @selector (escortShip:) // Only if ship
|| action == @selector (sentry:) // Not for fighter not in city/carrier
|| action == @selector (clearOrders:) // Only if city or unit w/ order
|| action == @selector (loadShip:) // Only ship
|| action == @selector (unloadShip:) // Only ship
|| action == @selector (skipMove:) // Only if has movement left
|| action == @selector (explore:)
)
{
//valid = ([context selectedUnit] == nil) ? NO : YES;
valid = YES;
}
else if (action == @selector (patrolTo:) )
{
//valid = (unit != nil && ([unit unitType] != u_fighter || [unit isOnBoardShip] == YES || [unit isInCity] == YES));
valid = YES;
}
return valid;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.