// This is -*- c++ -*- code


// $Id: board.h,v 1.28 1995/12/11 08:21:06 daveg Exp $


#ifndef __BOARD_H__ 
#define __BOARD_H__

#include <6170.h>
#include <limits.h>
#include <typeinfo.h>
#include <ps5/web_node.h>

#include "game.h"
#include "move_generator.h"

class move;

class board: public web_node {
  // Overview: This class represents the abstract interface of a
  // game board required by the game and player abstractions.
  
  // This is a heap abstraction
  
public:
// Constructors and destructors:

  board();
  // Effects:  Constructs a board that is not associated with any game.
  
  virtual ~board();
  // Effects: Frees any resources associated with the board.
  // Because garbage collection is performed, calling this
  // destructor is not strictly necessary, but if it is known that a
  // board wil not be needed, destroying it may avoid heap
  // fragmentation.

  virtual bool is_associated() const;
  // Effects: Returns true if this board is associated with a game.


    virtual bool is_legal_move(move &m, int player_num) const = 0 ;
  // Checks: 0 <= player_num < players()
  // Effects: return true if m is a move compatible with this type
  // of board and player player_num (from game) applying m to this board in the current
  // state would be legal, else return false. If this is not
  // associated with a game, the return value is undefined, but this
  // shall remain in a well-defined state.  This method does not
  // expect m to exist after the call.
  
    virtual game::move_result  apply(move &m, int player_num) = 0;
    // Checks: 0 <= player_num < players()
    // Modifies: this
  // Effects: applies m to this if possible, or
  // returns a failure reason.  The applicability of m shall be
  // defined by the rules of the game this implements and the
  // current state of this.  If is_legal_move(m, p) is true, then m
  // must be applicable If m is
  // applied, returns ok In no event shall m be assumed to exist
  // beyond the call to apply.  Apply will not call any non-const
  // methods of game.  It is illegal to return game_already_done.
  

  virtual bool unapply(move &m, int player_num) = 0;
  // Checks: 0 <= player_num < players()
  // Modifies: this
  // Requires: m is the last move that was applied to this by player player_num
  // Effects: Reverts this to the state before m was applied if
  // possible, returning true, else returns false.  The behavior is
  // undefined if m isn't the most-recent move applied to this,
  // although after m is unapplied, the move applied before m is
  // most recent.  I.E.  If a series of moves is applied then
  // unapplied, unapply must either unapply the move, modifying
  // this, or return false, leaving this unchanged.  However, if a
  // move three moves back is unapplied, the behavior is completely
  // undefined.  Unapply_move will not call any non-const methods of
  // game.   Unapply must return true and successfully a move just after a call to apply.
  // I.E.  It must be possible to write a machine player that examines the
  // effect of applying moves then unapplies them if the results are not desirable.
  
  virtual int winner() = 0;
  // Modifies: this
  // Effects: Checks to see if the game has been won.  If so,
  // returns the player who won the game, else returns -1.  If the game is a draw, returns -2.
  // Note that
  // successful unapplication can revert this to -1.
  // Requires: There must be
  // no valid moves for any players if winner() is non-null.
  

  virtual http_response *get(string request, extensions *extras) = 0;
  // Modifies: this, and possibly players and games associated with
  // this
  // Effects: Processes a web request as defined by the
  // protocol for the game this implements.  Requests defined in
  // Section \tex{\ref{p:board}} must be implemented. If a move is returned
  // by the request, game::apply shall be called; in no other
  // event shall an object outside of this be modified.  If the
  // request is not supported, an error is returned.  It is always
  // an error to make a web request of a board not associated with a
  // particular game.
  
  virtual void display(extensions *ext, ostream &body, int player_num) const = 0;
  // Checks: 0 <= player_num < players()
  // Effects: returns an html representation of this from the point of 
  // view of player_num.  The headers
  // in extensions (if extensions is non-null) can be used to
  // determine the capabilities of the web client.
  
  virtual bool valid_move_available( int player_num) const = 0;
  // Checks: 0 <= player_num < players()
  // Effects: returns true if player p has any current legal moves,
  // returns true, else returns false.


  virtual  move_generator * valid_moves(int player_num) const = 0 ;
// Checks: 0 <= player_num < players()
  // Effects: returns a generator that returns in arbitrary order
  // the valid moves for player p at this point; if p cannot
  // currently move, then the generator will initially be empty.
  // The generator returns valid moves only once.
  // Requires: the generator not be used after apply is used, the generator be deleted
  // when no longer needed.
  
  // Type for static evaluator values:
  typedef long value;
  const value infinity = LONG_MAX;

  virtual value eval_move_delta (int p_pov, move &, int p_mover) const = 0;
  // Checks: 0 <= p_pov, p_mover < players()
  // Effects: returns the change in value from p_pov's point of view,
  // after the given move was applied by player p_mover.
 
  
  virtual value evaluate( int player1) const = 0;
    // Checks: 0 <= player_num < players()
  // Effects: returns a static evaluation of the currentate.  A value
  // of 0 indicates that player p is tied with other players or not
  // involved in the game represented by board.  A positive value
  // indicates that player p is ahead of other players--the more
  // positive the value, the farther ahead player p is.  A negative
  // value indicates that p is behind other players; the more
  // negative the value, the farther behind.  Ideally, the values
  // will be scaled such that winning the game results in
  // approximately the largest value representable in value, but this
  // is not required.


  virtual board * clone() const = 0 ;
  // Effects: Returns a cloned board of this.  (See design document
  // for implications of cloning).
  // Implementation-comment:  To implement this method, see the protected method clone_part.
    
  bool is_clone() const;
  // Effects: returns true if this is a clone else false.
    
  virtual long suggest_time(long time_left) const = 0;
    // Effects: Returns an amount of time appropriate to spend on a
    // move during this turn.
  
  virtual void * force (typeinfo_t &t) = 0;

  virtual const void *force(typeinfo_t &type) const;
    

protected:
  virtual void associate( game *g);
  // Modifies: this 
  // Effects: Associates this with a particular game.
  // This method should only be called by game::game or overiding methods in subclasses, and never by
  // using code.  A board that is not associated with a particular
  // game can be used, but no web requests can be sent to it.
  // Associate will not call any non-const methods of game.
  
friend game::game(board *b, player *p1, player *p2, string uri, 
		  string image_base, bool player1_is_default);
  //friendship-extent: game::game is a friend of board so it can
  //call board::associate.  game::game shall not access other
  //private or protected methods or state of board.

    game * get_game() const;
    // Effects: returns a pointer to game so that web requests and
    // other methods of board and subtypes of board can find the game this is
    //  associated with.  If this is not associated, returns null.

    void clone_part (board &b) const;
    // Effects Copies state into b from this as appropriate for a
    // clone of b.  To implement clone, construct the right board,
// then call the clone_part of the implementing subclass.
        // Modifies: b

    
private:
  void operator = (const board &);
  board(const board &);
  
  // Abstraction function: The only permanent state at this level of
  // the class hierarchy is the association with a particular game; g
  // contains a pointer to this game.  In addition, i_am_clone returns
  // true if and only if the clone method was used to prduce this.
  
  // Rep invariant: If g is non-null, g->get_board() == this
  game *g;
    bool i_am_clone;
};

inline bool board::is_associated()const  {return g != 0;}

inline game * board::get_game() const {return g;};

inline bool board::is_clone() const {return i_am_clone;}

#endif
