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


// $Id: game.h,v 1.17 1995/12/11 21:09:35 daveg Exp $

#ifndef __GAME_H__
#define __GAME_H__

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

class board;
class player;
class move;

class game : public web_node {

public:

    // Overview: Dispatches data between two players and a board to
    // arbitrate a game state.  Note: once a player is assigned an
    // index, this index will remain associated with the player for
    // the rest of the game.

    // This is a heap abstraction.


    // Constructors and destructors:

    game ( board *b, player *p1, player *p2, string uri, string image_uri, bool player1_is_default);
    // Requires: p1 and p2 be players capable of playing the game
    // represented by board b, board b not be used in previous calls
    // to game::game, player p1 and p2 not be used in any other game,
    // board b not be modified by using code after this is constructed
    // Effects: Initializes a new game to be played on board b,
    // between player p1 and player p2.  If player1_is_default is
    // true, requests using the mandentory web protocol wil go to
    // player1, else they go to player 2.  The uri parameter is the
    // base URI to this game used to construct anchors in generated
    // HTML; it should end with a trailing slash. The image_uri
    // parameter is the base URI for images and static texts; it should
    // also end with a trailing slash.


    virtual ~game();
    // Effects: frees state associated with a game.  It is not
    // necessarey for game to be destructed, but if it is destructed,
    // associated state will be freed.  Requires: the players and
    // board associated with the game not be used after the game is
    // destructed.  In addition, no generators returned by the move
    // history mechanism, nor moves queried from the history mechanism
    // can be used after the game is destructed.

    // possible results of applying a move:
    enum move_result {
	ok,			// move accepted and board updated
	game_already_done,	// The move is invalid because one of the players has already won the game.
	move_invalid} ;		// Move invalid; possible penalty applied
    

    // Movement history:
    int number_moves() const;
    // Eeffects: Returns the number of moves made so far in this game.  Initially this is zero.

    generator <move *> *move_history() const;
    // Effects: Returns a generator that produces the previous moves
    // in the game in order, starting from the initial move.
    // Requires: no moves be made while this generator is in use.

    bool get_move(int number, move *&m) const;
    // Effects: If 0 <= number < moves(), returns true and assigns the
    // numberth move from the move history to m.  Else, returns false
    // without modifying m.
    // Modifies: m

    // Observers for players and board
    int players() const {return 2;}
    // Effects: returns the number of players in the game.

     player *get_player(int num) const;
    // Checks: 0 <= num < players()
    // Effects: returns a pointer to the numth player.
    int player_index(const player *p) const;
    // Effects: returns the index of player in the game, or -1 if the player
    // is not a player of this.
    
    const board * get_board() const;
    // Effects: returns the board this game is using.

    move_result apply (move &m, int player_num);
    // Checks: 0 <= player_num < players()
    // Modifies: this, p1, p2, board
    // Effects: Checks with board to see if m is a valid move; if so,
    // m is applied to board as a move submitted by p and players are notified.  Returns a
    // result indicating successful application of the move, or a
    // reason for failure.
    //   In no event shall m be assumed to exist
    // beyond the call to apply.

    void state_changed();
    // Modifies: this
    // Effects: tell all players that the state of the game has
    // changed and that all assumptions should be rechecked; check to
    // see if a winner is present.This method should only be called by
    // board.

    virtual http_response *get(string request, extensions *ext);
    // Modifies: this, p1, p2, board
    // Effects: Dispatches the request according to the protocol
    // described in the Design Document in section \tex{\ref{p:game}}
    // The request will be handled by game, or passed off to
    // p1, p2, or board.

    
    int winner() const;
    // Effects:  Returns the player who won the game, or -1 if the game is still in progress or -2 if a tie was declared.

    void forfeit (int player_num);
// Checks: 0 <= player_num < players()
    // Modifies: this
    // Checks: player_num is a player of this game and has not yet been
    // declared winner of this game.
    // Effects: player_num forfeits the game;
    // the other player wins.

    void message(string m);
// Modifies: this
    // Effects: causes a message to be displayed during the next update.
    // Multiple old messages may be displayed; if message is called more times
    // than slots exist in the message history, old messages are lost.  If
    // message is called more than once between updates, messages may be lost.

    
    http_response *display (extensions *ext, int player_num) const;
    // Checks: 0 <= player_num < players()
    // Effects: Returns the current state of the game, including the
    // state of each player and the board as viewed from player
    // player_num's point of view.  If extensions is non-null,the
    // extra headers associated with the web request this update is a
    // response to should be included in extensions.  These requests
    // may be used to determine capabilities of the requester.
    // Requires: The state of the game not be changed until the
    // request is sent.
    
    string uri() const;
    // Effects: returns the uri to the game, ending with a trailing slash.
string uri_with_move() const;
    // Effects: returns the URI including the move number, as used in most requests in the game protocol.  This includes a trailing slash.

    string image_base() const;
    // Effects: returns the base URI to images including a trailing slash.

    http_response *ref_game(extensions *ext);
    // Effects: returns a valid representation of the current refereed game.

    http_response *game::ref_display(extensions *ext);
    // Effects: returns a valid representation of the current refereed game.
    
private:

   game();
    void operator = (const game &);
    // Disable unwanted operators/constructors

    player *p1, *p2;
    board *b;
    string my_uri,image_uri;
    bool p1_is_def;		// Do protocol requests without an explicit player go to p1?

    array <move *> history;
    int win;
    // Abstraction function: A game represents a controlled
    // interaction between two players, a board and a move history.
    // p1 and p2 are pointers to the players, b is a pointer to the
    // board.  The move history, stores in history, is the ordered set
    // of moves played so far.  In addition, win stores the index of
    // the player who has won the game, or -1 if the game is still in
    // progress.

    // Rep invarient: p1, p2, and b satisfy their rep invarient -1 <=
    // win < players().

    
};

inline player *game::get_player (int num ) const {
    check((0 <= num) && (num < players()), "out of bounds");
    return (num==0)?p1:p2;
}


inline const board *game::get_board() const {return b;}

inline string game::uri() const {return my_uri;}

inline string game::image_base() const {return image_uri;}



#endif // __GAME_H__

