//
// $Id: Order.m,v 1.1 1997/10/28 05:11:48 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: Order.m,v 1.1 1997/10/28 05:11:48 nygard Exp $");

#import "Order.h"

#import "MapView.h"

//======================================================================
//
// An Order provides a unit with guidance to carry out a higher level
// command that may have a duration of several game turns.  Currently,
// it is used mainly by the Human player to help reduce the tedious
// micro-management of units.
//
// A higher level object, while determining the strategy for the player,
// may decide that a particular unit should move to a given location.
// It can then give that unit an order to move to that location.  The
// order is then responsible for making the tactical decisions to
// accomplish this goal.
//
//======================================================================

#define Order_VERSION 1

@implementation Order

+ (void) initialize
{
    if (self == [Order class])
    {
        [self setVersion:Order_VERSION];
    }
}

//----------------------------------------------------------------------
//
// Each order needs to know the unit that it is assigned to.  The unit
// may be nil.  This is used, for example, with fligh paths, where the
// flight path is represented by an Order without a unit.  When a unit
// is assigned to a flight path, the order is copied and the unit for
// the order is then set.
//
//----------------------------------------------------------------------

- initForUnit:(Unit *)aUnit
{
    [super init];

    // The unit owns the order.
    unit = aUnit;
    blockedCount = 0;

    return self;
}

//----------------------------------------------------------------------

- (void) dealloc
{
    [super dealloc];
}

//----------------------------------------------------------------------
//
// Notify the order that it was able to move without being blocked.
//
//----------------------------------------------------------------------

- (void) unblocked
{
    blockedCount = 0;
}

//----------------------------------------------------------------------
//
// Some orders will have state that needs to be recalculated if it has
// been blocked and a different move is done by the user...
//
// Normally the state is set during initialization.  However, if the
// unit is set later, the order will also have to be reset to do this
// initialization.
//
//----------------------------------------------------------------------

- (void) reset
{
}

//----------------------------------------------------------------------
//
// For display on the status line of the Human player.
//
//----------------------------------------------------------------------

- (NSString *) orderText
{
    return @">Order<";
}

//----------------------------------------------------------------------
//
// Allows the order to do stuff before it has a chance to move.
//
//----------------------------------------------------------------------

- (void) aboutToMove
{
}

//----------------------------------------------------------------------
//
// An Order decides on a direction to move each time the unit has a
// chance to move.  Returning d_none means that it couldn't move,
// for example, if it was blocked.
//
//----------------------------------------------------------------------

- (Direction) nextMove
{
    return d_none;
}

//----------------------------------------------------------------------
//
// If the order was blocked on the previous try (nextMove returned d_none),
// it is asked whether it wants to try again.  This returns whether
// the unit should try moving again (in this turn).
//
// The blockedCount instance variable can be incremented to keep track
// of the number of retries, so that the order can give up eventually.
//
//----------------------------------------------------------------------

- (BOOL) wasBlocked
{
    return NO;
}

//----------------------------------------------------------------------
//
// Does this order represent a sentried state?  If so, the Human player
// will silently skip over the unit during a turn.  This is also used
// to determine the icon of a sentried army.
//
//----------------------------------------------------------------------

- (BOOL) isSentried
{
    return NO;
}

//----------------------------------------------------------------------
//
// Used by OMoveTo when it reaches the destination, so that the orders
// can be cleared.
//
//----------------------------------------------------------------------

- (BOOL) isOrderComplete
{
    return NO;
}

//----------------------------------------------------------------------
//
// Some orders represent a path that needs to be shown in some views
// for the Human player.  For example, flight paths are shown on top
// of the map when setting or clearing flight paths.
//
//----------------------------------------------------------------------

- (PathSegment *) pathInMapView:(MapView *)mapView
{
    return nil;
}

//----------------------------------------------------------------------
//
// For flight paths, we just have an order without a unit, so we need
// to set the unit after the flight path is copied.
//
//----------------------------------------------------------------------

- (void) setUnit:(Unit *)aUnit
{
    unit = aUnit;

    [self reset];
}

//----------------------------------------------------------------------
//
// Orders that deal with the loading of units may want to know when a
// unit does enter, so they can determine whether this order is complete.
//
//----------------------------------------------------------------------

- (void) unitDidEnter:(Unit *)aUnit
{
}

@end
