00001 //---------------------------------------------------------------------------- 00002 /** @file GoGame.h 00003 GoGame class, play and replay moves in a game tree. */ 00004 //---------------------------------------------------------------------------- 00005 00006 #ifndef GO_GAME_H 00007 #define GO_GAME_H 00008 00009 #include <string> 00010 #include "GoBoard.h" 00011 #include "GoBoardUpdater.h" 00012 #include "GoBoardUtil.h" 00013 #include "GoTimeSettings.h" 00014 #include "SgNode.h" 00015 #include "SgPoint.h" 00016 #include "SgTimeRecord.h" 00017 00018 class SgSearchStatistics; 00019 00020 //---------------------------------------------------------------------------- 00021 00022 /** Game state and move history including variations. 00023 Contains a game tree, a pointer to a current node, a board and information 00024 of the time left. The current node is always a valid node of the tree and 00025 the board and time records reflect the game state at the current node. 00026 @todo Remove non-const function Time() and decouple time measurement from 00027 tracking the time left at a node. This class should not have to deal with 00028 time measurement, instead add a time parameter to AddMove() that informs 00029 the game about the time that needs to be subtracted from the time left. 00030 @todo Also ensure in GoGame that the time settings and time left records 00031 always reflect the state at the current node. This should be implemented 00032 in GoBoardUpdater::Update(), which is used by GoGame. */ 00033 class GoGame 00034 { 00035 public: 00036 /** Create a game record for replaying games on the given board. */ 00037 explicit GoGame(int boardSize = GO_DEFAULT_SIZE); 00038 00039 ~GoGame(); 00040 00041 /** Init from an existing game tree. 00042 Takes the ownership of the tree. */ 00043 void Init(SgNode* root); 00044 00045 /** Delete the old game record and start with a fresh one. 00046 Init the board with the given parameters, and create a root node 00047 to start with. */ 00048 void Init(int size, const GoRules& rules); 00049 00050 /** Get the board associated with this game record. */ 00051 const GoBoard& Board() const; 00052 00053 /** Return the root of this tree. */ 00054 const SgNode& Root() const; 00055 00056 const GoTimeSettings& TimeSettings() const; 00057 00058 /** Set handicap stones at explicitely given points. 00059 If the current node alread has children, a new child is created with 00060 the handicap setup (and made the current node), otherwise the 00061 handicap stones are added to the current node. 00062 @pre Board is empty */ 00063 void PlaceHandicap(const SgVector<SgPoint>& stones); 00064 00065 /** Set up a position on the board. 00066 Creates a new child node of the current node and adds the appropriate 00067 AB, AW and AE properties to change the board position to the 00068 position defined by the given stone lists. Makes the new child node 00069 the current node. */ 00070 void SetupPosition(const SgBWArray<SgPointSet>& stones); 00071 00072 /** Add move to the game record and make it the current node. 00073 Add move as the next move at the current position. 00074 If a node with that move already exists, then don't add a new one. 00075 Return the node with that move. 00076 Also add any statistics from 'stat' and time left to that node. */ 00077 void AddMove(SgMove move, SgBlackWhite player, 00078 const SgSearchStatistics* stat = 0, 00079 bool makeMainVariation = true); 00080 00081 /** Add a comment to the current node. */ 00082 void AddComment(const std::string& comment); 00083 00084 /** Add a comment to any node. */ 00085 void AddComment(const SgNode& node, const std::string& comment); 00086 00087 /** Add a node with a comment that a player resigned. 00088 For informational purposes only, the resign node will not be made 00089 the current node. */ 00090 const SgNode& AddResignNode(SgBlackWhite player); 00091 00092 /** Append a node as a new child to the current node. 00093 @param child The new child. The ownership is transfered. The user is 00094 responsible that the subtree is consistent and contains no lines with 00095 illegal moves with respect to the position at the current node. */ 00096 void AppendChild(SgNode* child); 00097 00098 /** Play to the given node. 00099 @c dest must be in this tree, or 0. 00100 Also updates the clock. */ 00101 void GoToNode(const SgNode* dest); 00102 00103 /** Play to the next node in the given direction. */ 00104 void GoInDirection(SgNode::Direction dir); 00105 00106 /** Return whether there is a next node in the given direction. */ 00107 bool CanGoInDirection(SgNode::Direction dir) const; 00108 00109 /** Set the current player. 00110 Same meaning as the SGF property PL. */ 00111 void SetToPlay(SgBlackWhite toPlay); 00112 00113 /** Return whether the game is finished. */ 00114 bool EndOfGame() const; 00115 00116 /** Deprecated. 00117 Non-const access to time left records will be removed in the future 00118 because its part of the class invariants of this class that they 00119 reflect the state corresponding to the current node. */ 00120 SgTimeRecord& Time(); 00121 00122 /** The time left in the game at the current position. */ 00123 const SgTimeRecord& Time() const; 00124 00125 /** Return the current position in the tree. 00126 @todo changed from protected to public because of getting 00127 the current time left. */ 00128 const SgNode* CurrentNode() const; 00129 00130 /** Return the move of the current node. 00131 Return NullMove if no current move. */ 00132 SgMove CurrentMove() const; 00133 00134 /** Get the number of moves since root or last node with setup 00135 properties. */ 00136 int CurrentMoveNumber() const; 00137 00138 00139 /** @name Query or change game info properties */ 00140 // @{ 00141 00142 /** Set komi property in the root node and delete all komi properties 00143 in the tree. */ 00144 void SetKomiGlobal(GoKomi komi); 00145 00146 /** Set time settings properties in the root node and delete all such 00147 properties in the rest of the tree. 00148 @param timeSettings 00149 @param overhead See SgTimeRecord */ 00150 void SetTimeSettingsGlobal(const GoTimeSettings& timeSettings, 00151 double overhead = 0); 00152 00153 /** Get the player name. 00154 Searches to nearest game info node on the path to the root node that 00155 has a player property. Returns an empty string if unknown. */ 00156 std::string GetPlayerName(SgBlackWhite player) const; 00157 00158 /** Set the player name at root node or most recent node with this 00159 property. */ 00160 void UpdatePlayerName(SgBlackWhite player, const std::string& name); 00161 00162 /** Set the date at root node or most recent node with this property. */ 00163 void UpdateDate(const std::string& date); 00164 00165 /** Get the game result. 00166 Searches to nearest game info node on the path to the root node that 00167 has a result property. Returns an empty string if unknown. */ 00168 std::string GetResult() const; 00169 00170 /** Set the result at root node or most recent node with this property. */ 00171 void UpdateResult(const std::string& result); 00172 00173 /** Get the game name. 00174 Searches to nearest game info node on the path to the root node that 00175 has a game name property. Returns an empty string if unknown. */ 00176 std::string GetGameName() const; 00177 00178 /** Set the game name at root node or most recent node with this 00179 property. */ 00180 void UpdateGameName(const std::string& name); 00181 00182 void SetRulesGlobal(const GoRules& rules); 00183 00184 // @} // name 00185 00186 private: 00187 GoBoard m_board; 00188 00189 /** The root node of the current tree. */ 00190 SgNode* m_root; 00191 00192 /** The position in the current tree. */ 00193 SgNode* m_current; 00194 00195 GoBoardUpdater m_updater; 00196 00197 GoTimeSettings m_timeSettings; 00198 00199 /** A record of the clock settings and time left. */ 00200 SgTimeRecord m_time; 00201 00202 /** Moves inserted into a line of play instead of added at the end. */ 00203 int m_numMovesToInsert; 00204 00205 /** Not implemented. */ 00206 GoGame(const GoGame&); 00207 00208 /** Not implemented. */ 00209 GoGame& operator=(const GoGame&); 00210 00211 std::string GetGameInfoStringProp(SgPropID id) const; 00212 00213 void InitHandicap(const GoRules& rules, SgNode* root); 00214 00215 SgNode* NonConstNodePtr(const SgNode* node) const; 00216 00217 SgNode& NonConstNodeRef(const SgNode& node) const; 00218 00219 void UpdateGameInfoStringProp(SgPropID id, const std::string& value); 00220 }; 00221 00222 inline void GoGame::AddComment(const std::string& comment) 00223 { 00224 m_current->AddComment(comment); 00225 } 00226 00227 inline const GoBoard& GoGame::Board() const 00228 { 00229 return m_board; 00230 } 00231 00232 inline const SgNode& GoGame::Root() const 00233 { 00234 return *m_root; 00235 } 00236 00237 inline SgTimeRecord& GoGame::Time() 00238 { 00239 return m_time; 00240 } 00241 00242 inline const SgTimeRecord& GoGame::Time() const 00243 { 00244 return m_time; 00245 } 00246 00247 inline const GoTimeSettings& GoGame::TimeSettings() const 00248 { 00249 return m_timeSettings; 00250 } 00251 00252 inline const SgNode* GoGame::CurrentNode() const 00253 { 00254 return m_current; 00255 } 00256 00257 //---------------------------------------------------------------------------- 00258 00259 /** Utility functions for GoGame. */ 00260 namespace GoGameUtil 00261 { 00262 /** Goto last node in main variation before move number. 00263 This function can be used for implementing the loadsgf GTP command. 00264 @param game (current node must be root) 00265 @param moveNumber move number (-1 means goto last node in main 00266 variation) 00267 @return false if moveNumber greater than moves in main variation */ 00268 bool GotoBeforeMove(GoGame* game, int moveNumber); 00269 } 00270 00271 //---------------------------------------------------------------------------- 00272 00273 #endif // GO_GAME_H 00274