00001 //---------------------------------------------------------------------------- 00002 /** @file GoGame.h 00003 GoGameRecord class, play and replay moves in a game tree. 00004 00005 GoGame implements the GoGameRecord class, which provides functions for 00006 playing and replaying moves in a game tree. 00007 Derived from it is the GoGame class, which allows two Player objects 00008 to play a game against each other. 00009 */ 00010 //---------------------------------------------------------------------------- 00011 00012 #ifndef GO_GAME_H 00013 #define GO_GAME_H 00014 00015 #include <string> 00016 #include "GoBoard.h" 00017 #include "GoBoardUpdater.h" 00018 #include "GoBoardUtil.h" 00019 #include "SgNode.h" 00020 #include "SgPoint.h" 00021 #include "SgTimeRecord.h" 00022 00023 class GoPlayer; 00024 class GoPlayerMove; 00025 class SgSearchStatistics; 00026 00027 //---------------------------------------------------------------------------- 00028 00029 /** Game stored as a tree of moves. 00030 @note What is wrong with this class? It exposes non-const access to its 00031 data members and therefore cannot guarantee the integrity of its state. In 00032 the future, this class should only provide read access to the board, tree, 00033 and current node pointer. All modifications to and navigation in the tree 00034 should only be possible through member functions of this class, such that 00035 it can guarantee that its invariants are met (i.e. the board position 00036 always belongs to the current node and the current node always points to a 00037 valid node in the tree). 00038 */ 00039 class GoGameRecord 00040 { 00041 public: 00042 /** Create a game record for replaying games on the given board. */ 00043 explicit GoGameRecord(GoBoard& board); 00044 00045 virtual ~GoGameRecord(); 00046 00047 /** Delete the old game record and start with a fresh one. 00048 If 'root' is 0, create a root node to start with, 00049 otherwise use the game tree passed in 'root'. 00050 If 'fTakeOwnership', the game record will delete this tree when 00051 it's destroyed, otherwise the client is reponsible 00052 for deleting the tree. 00053 @todo AR: change comment 00054 */ 00055 virtual void InitFromRoot(SgNode* root, bool fTakeOwnership); 00056 00057 /** Delete the old game record and start with a fresh one. 00058 Init the board with the given parameters, and create a root node 00059 to start with. 00060 */ 00061 virtual void Init(int size, const GoRules& rules); 00062 00063 /** Hook for subclasses. 00064 Default implementation does nothing. 00065 */ 00066 virtual void OnGoToNode(SgNode* dest); 00067 00068 /** Override to initialize other boards in derived classes. 00069 @see GoBoard 00070 */ 00071 virtual void OnInitBoard(int size, const GoRules& rules); 00072 00073 virtual void OnInitHandicap(const GoRules& rules, SgNode* root); 00074 00075 /** Get the board associated with this game record. */ 00076 const GoBoard& Board() const; 00077 00078 /** Return the root of this tree. */ 00079 SgNode& Root() const; 00080 00081 /** Add move to the game record. 00082 Add move as the next move at the current position. 00083 If a node with that move already exists, then don't add a new one. 00084 Return the node with that move. 00085 Also add any statistics from 'stat' and time left to that node. 00086 */ 00087 SgNode* AddMove(SgMove move, SgBlackWhite player, 00088 const SgSearchStatistics* stat = 0); 00089 00090 /** Add a node with a comment that a player resigned. 00091 For informational purposes only, the resign node will not be made 00092 the current node. 00093 */ 00094 SgNode* AddResignNode(SgBlackWhite player); 00095 00096 /** Play to the given node. 00097 @c dest must be in this tree, or 0. 00098 Also updates the clock. 00099 */ 00100 void GoToNode(SgNode* dest); 00101 00102 /** Play to the next node in the given direction. */ 00103 void GoInDirection(SgNode::Direction dir); 00104 00105 /** Return whether there is a next node in the given direction. */ 00106 bool CanGoInDirection(SgNode::Direction dir) const; 00107 00108 /** Set the current player. */ 00109 void SetToPlay(SgBlackWhite player); 00110 00111 /** Return whether the game is finished. */ 00112 bool EndOfGame() const; 00113 00114 /** Get the name of the given player. 00115 Return the blank string if unknown. 00116 Override to get information from an ongoing game rather than fron the 00117 game record. 00118 */ 00119 virtual std::string GetPlayerName(SgBlackWhite player) const; 00120 00121 /** Return the current score (black minus white). 00122 @todo: in what units? 00123 Return true if there's a score recorded in the tree, otherwise false. 00124 Override to return information about the score from a player. 00125 */ 00126 virtual bool GetScore(int* score) const; 00127 00128 /** The time left in the game at the current position. */ 00129 SgTimeRecord& Time(); 00130 00131 /** The time left in the game at the current position. */ 00132 const SgTimeRecord& Time() const; 00133 00134 /** Return the current position in the tree. 00135 @todo changed from protected to public because of getting 00136 the current time left. 00137 */ 00138 SgNode* CurrentNode(); 00139 00140 /** Return the current position in the tree. 00141 @todo changed from protected to public because of getting 00142 the current time left. 00143 */ 00144 const SgNode* CurrentNode() const; 00145 00146 /** Whether this game record owns the game tree. */ 00147 bool OwnsTree() const; 00148 00149 bool CanDeleteCurrentNode() const; 00150 00151 /** Return the move of the current node. 00152 Return NullMove if no current move. 00153 */ 00154 SgMove CurrentMove() const; 00155 00156 /** Get the number of moves since root or last node with setup 00157 properties. 00158 */ 00159 int CurrentMoveNumber() const; 00160 00161 private: 00162 /** The position in the current tree. */ 00163 SgNode* m_current; 00164 00165 GoBoard& m_board; 00166 00167 GoBoardUpdater m_updater; 00168 00169 /** A record of the clock settings and time left. */ 00170 SgTimeRecord m_time; 00171 00172 /** Whether this game record owns the game tree. */ 00173 bool m_ownsTree; 00174 00175 /** Comment display. */ 00176 SgNode* m_oldCommentNode; 00177 00178 /** Moves inserted into a line of play instead of added at the end. */ 00179 int m_numMovesToInsert; 00180 00181 /** Not implemented. */ 00182 GoGameRecord(const GoGameRecord&); 00183 00184 /** Not implemented. */ 00185 GoGameRecord& operator=(const GoGameRecord&); 00186 00187 /** Delete the tree and initialize the state associated with the position 00188 in the tree. 00189 */ 00190 void DeleteTreeAndInitState(); 00191 }; 00192 00193 inline const GoBoard& GoGameRecord::Board() const 00194 { 00195 return m_board; 00196 } 00197 00198 inline SgNode& GoGameRecord::Root() const 00199 { 00200 SG_ASSERT(m_current); 00201 return *m_current->Root(); 00202 } 00203 00204 inline SgTimeRecord& GoGameRecord::Time() 00205 { 00206 return m_time; 00207 } 00208 00209 inline const SgTimeRecord& GoGameRecord::Time() const 00210 { 00211 return m_time; 00212 } 00213 00214 inline SgNode* GoGameRecord::CurrentNode() 00215 { 00216 return m_current; 00217 } 00218 00219 inline const SgNode* GoGameRecord::CurrentNode() const 00220 { 00221 return m_current; 00222 } 00223 00224 inline bool GoGameRecord::OwnsTree() const 00225 { 00226 return m_ownsTree; 00227 } 00228 00229 //---------------------------------------------------------------------------- 00230 00231 /** Utility functions for GoGameRecord. */ 00232 namespace GoGameUtil 00233 { 00234 /** Goto last node in main variation before move number. 00235 This function can be used for implementing the loadsgf GTP command. 00236 @param game (current node must be root) 00237 @param moveNumber move number (-1 means goto last node in main 00238 variation) 00239 @return false if moveNumber greater than moves in main variation 00240 */ 00241 bool GotoBeforeMove(GoGameRecord* game, int moveNumber); 00242 } 00243 00244 //---------------------------------------------------------------------------- 00245 00246 /** Game record played between two players. 00247 A GoGame object handles the synchronization between the players 00248 and the board they're playing on, and keeps track of the time. 00249 */ 00250 class GoGame 00251 : public GoGameRecord 00252 { 00253 public: 00254 explicit GoGame(GoBoard& board); 00255 00256 virtual ~GoGame(); 00257 00258 /** Needed to avoid hiding of inherited virtual function by the 00259 other variants of GoGame::Init. 00260 */ 00261 virtual void InitFromRoot(SgNode* root, bool fTakeOwnership) 00262 { 00263 GoGameRecord::InitFromRoot(root, fTakeOwnership); 00264 } 00265 00266 /** Needed to avoid hiding of inherited virtual function by the 00267 other variants of GoGame::Init. 00268 */ 00269 void Init(int size, const GoRules& rules); 00270 00271 void Init(SgNode* root, bool fTakeOwnership, bool fDeletePlayers); 00272 00273 void Init(int size, const GoRules& rules, bool fDeletePlayers); 00274 00275 void OnGoToNode(SgNode* dest); 00276 00277 /** Turn the clock on or off. 00278 Call this method instead of Time().TurnClockOn 00279 so that computer player is started and stopped appropriately. 00280 */ 00281 void TurnClockOn(bool turnOn); 00282 00283 /** Return whether the clock is running (not stopped or suspended). */ 00284 bool ClockIsRunning() const { return Time().ClockIsRunning(); } 00285 00286 /** Set the player 'color' to the player algorithm 'player'. 00287 The old player of that color is stopped and deleted, and the new 00288 player is initialized to the current board state. 00289 A 0 player means user interaction. 00290 */ 00291 void SetPlayer(SgBlackWhite color, GoPlayer* player); 00292 00293 /** Delete the player 'color' (set it to interactive input). 00294 @note If black and white point to the same player, delete will be 00295 called only once, but both players will be set to null. 00296 */ 00297 void DeletePlayer(SgBlackWhite color); 00298 00299 /** Whether the human move at 'move' can be played at this point. 00300 The move must be legal, and either it's a human player to play 00301 or the clock is inactive. 00302 */ 00303 bool CanPlayHumanMove(SgMove move, SgBlackWhite player) const; 00304 00305 /** Adds a move to the game record and tells all other players to update 00306 their boards. 00307 Returns whether the move was added to the game record. 00308 @todo AR: to be replaced by HumanPlayer. 00309 */ 00310 bool PlayHumanMove(SgMove move, SgBlackWhite player); 00311 00312 void PlayComputerMove(const GoPlayerMove* playerMove); 00313 00314 GoPlayer* Player(SgBlackWhite player); 00315 00316 /** Compute and play one move using the given player. */ 00317 GoPlayerMove PlayOneMove(SgBlackWhite playerColor); 00318 00319 private: 00320 /** Black and white player. */ 00321 SgBWArray<GoPlayer*> m_player; 00322 00323 /** Not implemented. */ 00324 GoGame(const GoGame&); 00325 00326 /** Not implemented. */ 00327 GoGame& operator=(const GoGame&); 00328 00329 void UpdatePlayer(SgBlackWhite color); 00330 00331 void UpdatePlayers(); 00332 }; 00333 00334 inline GoPlayer* GoGame::Player(SgBlackWhite player) 00335 { 00336 return m_player[player]; 00337 } 00338 00339 //---------------------------------------------------------------------------- 00340 00341 #endif // GO_GAME_H 00342