00001 //---------------------------------------------------------------------------- 00002 /** @file GoGtpEngine.h 00003 GtpEngine with GoBoard, GoPlayer and GoGame. */ 00004 //---------------------------------------------------------------------------- 00005 00006 #ifndef GO_GTPENGINE_H 00007 #define GO_GTPENGINE_H 00008 00009 #include <sstream> 00010 #include <boost/filesystem/path.hpp> 00011 #include <boost/scoped_ptr.hpp> 00012 #include "GoBoard.h" 00013 #include "GoBook.h" 00014 #include "GoAutoBook.h" 00015 #include "GoGame.h" 00016 #include "GoPlayer.h" 00017 #include "GoStaticLadder.h" 00018 #include "GoTimeSettings.h" 00019 #include "GtpEngine.h" 00020 #include "SgGtpCommands.h" 00021 #include "SgPointArray.h" 00022 #include "SgMpiSynchronizer.h" 00023 00024 //---------------------------------------------------------------------------- 00025 00026 /** GtpEngine with GoBoard, GoPlayer and GoGame. 00027 @see gogtpenginecommands */ 00028 class GoGtpEngine 00029 : public GtpEngine 00030 { 00031 public: 00032 /** @page gogtpenginecommands GoGtpEngine Commands 00033 - @link CmdAllLegal() @c all_legal @endlink 00034 - @link CmdAllMoveValues() @c all_move_values @endlink 00035 - @link CmdBoardSize() @c boardsize @endlink 00036 - @link CmdClearBoard() @c clear_board @endlink 00037 - @link CmdFinalScore() @c final_score @endlink 00038 - @link CmdFixedHandicap() @c fixed_handicap @endlink 00039 - @link CmdGenMove() @c genmove @endlink 00040 - @link CmdGetKomi() @c get_komi @endlink 00041 - @link CmdGGUndo() @c gg-undo @endlink 00042 - @link CmdBoard() @c go_board @endlink 00043 - @link CmdClock() @c go_clock @endlink 00044 - @link CmdParam() @c go_param @endlink 00045 - @link CmdParamRules() @c go_param_rules @endlink 00046 - @link CmdParamTimecontrol() @c go_param_timecontrol @endlink 00047 - @link CmdPlayerBoard() @c go_player_board @endlink 00048 - @link CmdPointNumbers() @c go_point_numbers @endlink 00049 - @link CmdPointInfo() @c go_point_info @endlink 00050 - @link CmdRules() @c go_rules @endlink 00051 - @link CmdSentinelFile() @c go_sentinel_file @endlink 00052 - @link CmdSetInfo() @c go_set_info @endlink 00053 - @link CmdAnalyzeCommands() @c gogui-analyze_commands @endlink 00054 - @link CmdInterrupt() @c gogui-interrupt @endlink 00055 - @link CmdPlaySequence() @c gogui-play_sequence @endlink 00056 - @link CmdSetup() @c gogui-setup @endlink 00057 - @link CmdSetupPlayer() @c gogui-setup_player @endlink 00058 - @link CmdIsLegal() @c is_legal @endlink 00059 - @link CmdGameOver() @c cgos-gameover @endlink 00060 - @link CmdGenMoveCleanup() @c kgs-genmove_cleanup @endlink 00061 - @link CmdKgsTimeSettings() @c kgs-time_settings @endlink 00062 - @link CmdKomi() @c komi @endlink 00063 - @link CmdListStones() @c list_stones @endlink 00064 - @link CmdLoadSgf() @c loadsgf @endlink 00065 - @link CmdName() @c name @endlink 00066 - @link CmdPlaceFreeHandicap() @c place_free_handicap @endlink 00067 - @link CmdPlay() @c play @endlink 00068 - @link CmdRegGenMove() @c reg_genmove @endlink 00069 - @link CmdRegGenMoveToPlay() @c reg_genmove_toplay @endlink 00070 - @link CmdSaveSgf() @c savesgf @endlink 00071 - @link CmdSetFreeHandicap() @c set_free_handicap @endlink 00072 - @link CmdShowBoard() @c showboard @endlink 00073 - @link CmdTimeLastMove() @c time_last_move @endlink 00074 - @link CmdTimeLeft() @c time_left @endlink 00075 - @link CmdTimeSettings() @c time_settings @endlink 00076 - @link CmdUndo() @c undo @endlink */ 00077 /** @name Command Callbacks */ 00078 // @{ 00079 // The callback functions are documented in the cpp file 00080 virtual void CmdAllLegal(GtpCommand&); 00081 virtual void CmdAllMoveValues(GtpCommand&); 00082 virtual void CmdAnalyzeCommands(GtpCommand&); 00083 virtual void CmdBoard(GtpCommand&); 00084 virtual void CmdBoardSize(GtpCommand&); 00085 virtual void CmdClearBoard(GtpCommand&); 00086 virtual void CmdClock(GtpCommand&); 00087 virtual void CmdFinalScore(GtpCommand&); 00088 virtual void CmdFixedHandicap(GtpCommand&); 00089 virtual void CmdGameOver(GtpCommand&); 00090 virtual void CmdGenMove(GtpCommand&); 00091 virtual void CmdGenMoveCleanup(GtpCommand&); 00092 virtual void CmdGetKomi(GtpCommand&); 00093 virtual void CmdGGUndo(GtpCommand&); 00094 virtual void CmdInterrupt(GtpCommand&); 00095 virtual void CmdIsLegal(GtpCommand&); 00096 virtual void CmdKgsTimeSettings(GtpCommand& cmd); 00097 virtual void CmdKomi(GtpCommand&); 00098 virtual void CmdListStones(GtpCommand&); 00099 virtual void CmdLoadSgf(GtpCommand&); 00100 virtual void CmdName(GtpCommand&); 00101 virtual void CmdParam(GtpCommand&); 00102 virtual void CmdParamRules(GtpCommand&); 00103 virtual void CmdParamTimecontrol(GtpCommand&); 00104 virtual void CmdPlaceFreeHandicap(GtpCommand&); 00105 virtual void CmdPlay(GtpCommand&); 00106 virtual void CmdPlayerBoard(GtpCommand&); 00107 virtual void CmdPlaySequence(GtpCommand&); 00108 virtual void CmdPointNumbers(GtpCommand&); 00109 virtual void CmdPointInfo(GtpCommand&); 00110 virtual void CmdQuit(GtpCommand& cmd); 00111 virtual void CmdRegGenMove(GtpCommand&); 00112 virtual void CmdRegGenMoveToPlay(GtpCommand&); 00113 virtual void CmdRules(GtpCommand&); 00114 virtual void CmdSaveSgf(GtpCommand&); 00115 virtual void CmdSentinelFile(GtpCommand&); 00116 virtual void CmdSetFreeHandicap(GtpCommand&); 00117 virtual void CmdSetInfo(GtpCommand&); 00118 virtual void CmdSetup(GtpCommand&); 00119 virtual void CmdSetupPlayer(GtpCommand&); 00120 virtual void CmdShowBoard(GtpCommand&); 00121 virtual void CmdTimeLastMove(GtpCommand&); 00122 virtual void CmdTimeLeft(GtpCommand&); 00123 virtual void CmdTimeSettings(GtpCommand&); 00124 virtual void CmdUndo(GtpCommand&); 00125 // @} // @name 00126 00127 /** Constructor. 00128 @param fixedBoardSize Initial and only allowed size of the board. 00129 0 means startup with GO_DEFAULT_SIZE and allow to change board size 00130 @param programPath File path to the executable. Needed for 00131 SgGtpCommands::CmdDebugger 00132 @param noPlayer Indicate that the subclass will not set a player 00133 with SetPlayer(). Useful for GTP engines that cannot play moves 00134 (e.g. TsumeGo solvers) This causes player-specific GTP commands, 00135 like @c reg_genmove) not to be registered. 00136 @param noHandicap Don't register handicap commands (useful, to 00137 avoid accepting handicap games on KGS) */ 00138 GoGtpEngine(int fixedBoardSize = 0, const char* programPath = 0, 00139 bool noPlayer = false, bool noHandicap = false); 00140 00141 ~GoGtpEngine(); 00142 00143 GoBook& Book(); 00144 00145 const GoGame& Game() const; 00146 00147 const GoBoard& Board() const; 00148 00149 /** Set player. 00150 Takes ownership of player. */ 00151 void SetPlayer(GoPlayer* player); 00152 00153 /** Throws GtpFailure if no player set. */ 00154 GoPlayer& Player() const; 00155 00156 /** Write game and player boards. */ 00157 void DumpState(std::ostream& out) const; 00158 00159 /** Automatically save game after each move. 00160 @param prefix Filename prefix; game number and file extension sgf 00161 will be added. */ 00162 void SetAutoSave(const std::string& prefix); 00163 00164 /** File to save statistics. 00165 An empty string means that the statistics will not be saved (default 00166 behavior). 00167 @see CreateStatisticsSlots() */ 00168 void SetStatisticsFile(const std::string& fileName); 00169 00170 /** Automatically write board to SgDebug() after changes. 00171 Default is false. */ 00172 void SetAutoShowBoard(bool showBoard); 00173 00174 /** Write everything written to SgDebug() during a genmove command to the 00175 comment in the new game node. 00176 During a genmove command, SgDebug() will be redirected to a string 00177 stream. After the move generation, SgDebug() will be reset to its old 00178 value and the string will be written to SgDebug(), as well as added 00179 as a comment to the new game node. 00180 Default is false. */ 00181 void SetDebugToComment(bool debugToComment); 00182 00183 /** Set maximum number of clear_board commands. 00184 -1 means no limit (default). 00185 After the limit is reached, the clear_board command will fail. 00186 This limit can be used to limit the game loop of the Computer 00187 bot interface to the Kiseido Go server http://kgs.kiseido.com. */ 00188 void SetMaxClearBoard(int n); 00189 00190 /** Set named rules. 00191 @param namedRules Named rules. 00192 @exception SgException on unknown rules. 00193 @see GoRules::SetNamedRules */ 00194 void SetNamedRules(const std::string& namedRules); 00195 00196 /** See TimeLimit() */ 00197 void SetTimeLimit(double timeLimit); 00198 00199 /** Time limit in seconds for move generation and other commands. */ 00200 double TimeLimit(); 00201 00202 #if GTPENGINE_PONDER 00203 /** Implementation of GtpEngine::Ponder() 00204 Calls GoPlayer::Ponder() if a player is set. */ 00205 void Ponder(); 00206 00207 /** Implementation of GtpEngine::StopPonder() 00208 Calls SgSetUserAbort() */ 00209 void StopPonder(); 00210 00211 /** Implementation of GtpEngine::InitPonder() 00212 Calls SgSetUserAbort(false) */ 00213 void InitPonder(); 00214 #endif // GTPENGINE_PONDER 00215 00216 #if GTPENGINE_INTERRUPT 00217 /** Implementation of GtpEngine::Interrupt(). 00218 Calls SgSetUserAbort() */ 00219 void Interrupt(); 00220 #endif // GTPENGINE_INTERRUPT 00221 00222 void SetMpiSynchronizer(const SgMpiSynchronizerHandle &m_handle); 00223 00224 SgMpiSynchronizerHandle MpiSynchronizer(); 00225 00226 const SgMpiSynchronizerHandle MpiSynchronizer() const; 00227 00228 protected: 00229 /** Current player. 00230 The player can be exchanged at runtime. It is null, if no player is 00231 set. This member is accessible by subclasses of GoGtpEngine to allow 00232 them to register external classes, which handle player specific GTP 00233 commands. These external classes can be constructed with a reference 00234 to this pointer, such that they can access the player they need. They 00235 have to check first, that the current player is the expected one. */ 00236 GoPlayer* m_player; 00237 00238 boost::scoped_ptr<GoAutoBook> m_autoBook; 00239 00240 /** Hook function to be executed before each command. 00241 Resets user abort flag. Lengthy functions should poll SgUserAbort but 00242 should not reset the user abort flag themselves. 00243 Also flushes SgDebug() (see comment at BeforeWritingResponse()). */ 00244 void BeforeHandleCommand(); 00245 00246 /** Hook function to be executed before the response of a command is 00247 written. 00248 Flushes SgDebug(). */ 00249 void BeforeWritingResponse(); 00250 00251 void BoardChanged(); 00252 00253 void CheckLegal(std::string message, SgBlackWhite color, SgPoint move, 00254 bool checkOnlyOccupied); 00255 00256 void CheckMaxClearBoard(); 00257 00258 void CheckMoveStackOverflow() const; 00259 00260 SgPoint GenMove(SgBlackWhite color, bool ignoreClock); 00261 00262 /** Write integer array response to command. 00263 Elements with the value numeric_limits<int>::min() are considered to 00264 have no defined value and are written as "" for compatibility with 00265 GoGui. */ 00266 void RespondNumberArray(GtpCommand& cmd, const SgPointArray<int>& array, 00267 int scale); 00268 00269 void Init(int size); 00270 00271 /** Play a move in game and goto new node. 00272 @throws GtpFailure If move stack overflow or illegal move. */ 00273 void Play(SgBlackWhite color, SgPoint move); 00274 00275 /** @name Statistics file */ 00276 // @{ 00277 00278 /** Create additional slots for the statistics file. 00279 This function will be called whenever a new player is set in 00280 GoGtpEngine. The default implementation returns an empty list. 00281 @return A list of slot headers. A header may not contain tabs. The 00282 following headers are already used by GoGtpEngine: 00283 GAME, MOVE, BOOK, TIME. 00284 In GenMove(), AddPlayStatistics() will be called, in which the 00285 subclass should use AddStatistics() to fill in the values. Only 00286 defined slots may be used. Slots that are not filled in will get the 00287 value '-' 00288 @see SetStatisticsFile() */ 00289 virtual std::vector<std::string> CreateStatisticsSlots(); 00290 00291 /** Add statistics for the last generated move. 00292 See CreateStatisticsSlots(). Default implementation does nothing. */ 00293 virtual void AddPlayStatistics(); 00294 00295 /** See CreateStatisticsSlots() */ 00296 void AddStatistics(const std::string& key, const std::string& value); 00297 00298 /** See CreateStatisticsSlots() */ 00299 template<typename T> 00300 void AddStatistics(const std::string& key, const T& value); 00301 00302 // @} 00303 00304 00305 SgBlackWhite BlackWhiteArg(const GtpCommand& cmd, 00306 std::size_t number) const; 00307 00308 SgEmptyBlackWhite EmptyBlackWhiteArg(const GtpCommand& cmd, 00309 std::size_t number) const; 00310 00311 SgPoint EmptyPointArg(const GtpCommand& cmd, std::size_t number) const; 00312 00313 SgPoint MoveArg(const GtpCommand& cmd, std::size_t number) const; 00314 00315 /** Check that number of arguments is one and get point argument. */ 00316 SgPoint PointArg(const GtpCommand& cmd) const; 00317 00318 SgPoint PointArg(const GtpCommand& cmd, std::size_t number) const; 00319 00320 SgVector<SgPoint> PointListArg(const GtpCommand& cmd, 00321 std::size_t number) const; 00322 00323 SgVector<SgPoint> PointListArg(const GtpCommand& cmd) const; 00324 00325 SgPoint StoneArg(const GtpCommand& cmd, std::size_t number) const; 00326 00327 void RulesChanged(); 00328 00329 private: 00330 bool m_noPlayer; 00331 00332 /** Accept illegal ko or suicide moves in CmdPlay() */ 00333 bool m_acceptIllegal; 00334 00335 /** See SetAutoSave() */ 00336 bool m_autoSave; 00337 00338 /** See SetAutoShowBoard() */ 00339 bool m_autoShowBoard; 00340 00341 /** See SetDebugToComment() */ 00342 bool m_debugToComment; 00343 00344 bool m_useBook; 00345 00346 /** Flag set to false if pondering in current position would be a waste 00347 of CPU time. 00348 This flag is set to false if the game has not really started yet 00349 (current position is an empty board or still in the opening book) or 00350 is already finished (two passes, resign or the game result was just 00351 set with <tt>go_set_info result</tt>). */ 00352 bool m_isPonderPosition; 00353 00354 int m_fixedBoardSize; 00355 00356 /** Maximum number of clear_board commands. 00357 -1, if no limit. 00358 @see SetMaxClearBoard() */ 00359 int m_maxClearBoard; 00360 00361 /** Number of clear_board commands. 00362 @see SetMaxClearBoard() */ 00363 int m_numberClearBoard; 00364 00365 double m_timeLastMove; 00366 00367 /** See GoGtpEngine::CmdTimeLimit */ 00368 double m_timeLimit; 00369 00370 /** Operator overhead time for time settings. */ 00371 double m_overhead; 00372 00373 /** Time settings for game. */ 00374 GoTimeSettings m_timeSettings; 00375 00376 /** Default rules. 00377 Will be used whenever a new game is started. */ 00378 GoRules m_defaultRules; 00379 00380 /** Order dependency: destruct m_game before m_board */ 00381 GoGame m_game; 00382 00383 SgGtpCommands m_sgCommands; 00384 00385 GoBook m_book; 00386 00387 GoBookCommands m_bookCommands; 00388 00389 std::string m_autoSaveFileName; 00390 00391 std::string m_autoSavePrefix; 00392 00393 /** See CmdSentinelFile() */ 00394 boost::filesystem::path m_sentinelFile; 00395 00396 std::string m_statisticsFile; 00397 00398 /** See CreateStatisticsSlots() */ 00399 std::vector<std::string> m_statisticsSlots; 00400 00401 /** See CreateStatisticsSlots() */ 00402 std::vector<std::string> m_statisticsValues; 00403 00404 SgMpiSynchronizerHandle m_mpiSynchronizer; 00405 00406 void ApplyTimeSettings(); 00407 00408 void AutoSave() const; 00409 00410 void CheckBoardEmpty() const; 00411 00412 void CreateAutoSaveFileName(); 00413 00414 void GameFinished(); 00415 00416 SgPoint GenBookMove(SgBlackWhite toPlay); 00417 00418 void InitStatistics(); 00419 00420 void PlaceHandicap(const SgVector<SgPoint>& stones); 00421 00422 void SaveGame(const std::string& fileName) const; 00423 00424 void SaveStatistics(); 00425 00426 void StartStatistics(); 00427 00428 void Undo(int n); 00429 00430 static void WriteBoardInfo(GtpCommand& cmd, const GoBoard& bd); 00431 }; 00432 00433 template<typename T> 00434 void GoGtpEngine::AddStatistics(const std::string& key, const T& value) 00435 { 00436 std::ostringstream s; 00437 s << value; 00438 AddStatistics(key, s.str()); 00439 } 00440 00441 inline const GoBoard& GoGtpEngine::Board() const 00442 { 00443 return m_game.Board(); 00444 } 00445 00446 inline GoBook& GoGtpEngine::Book() 00447 { 00448 return m_book; 00449 } 00450 00451 inline const GoGame& GoGtpEngine::Game() const 00452 { 00453 return m_game; 00454 } 00455 00456 inline void GoGtpEngine::SetDebugToComment(bool debugToComment) 00457 { 00458 m_debugToComment = debugToComment; 00459 } 00460 00461 inline void GoGtpEngine::SetMaxClearBoard(int n) 00462 { 00463 m_maxClearBoard = n; 00464 } 00465 00466 inline void GoGtpEngine::SetTimeLimit(double timeLimit) 00467 { 00468 m_timeLimit = timeLimit; 00469 } 00470 00471 inline double GoGtpEngine::TimeLimit() 00472 { 00473 return m_timeLimit; 00474 } 00475 00476 //---------------------------------------------------------------------------- 00477 00478 /** Assertion handler that can be registered with SgRegisterAssertionHandler. 00479 Calls GoBoardUtil::DumpBoard with the engine's board. */ 00480 class GoGtpAssertionHandler 00481 : public SgAssertionHandler 00482 { 00483 public: 00484 GoGtpAssertionHandler(const GoGtpEngine& engine); 00485 00486 void Run(); 00487 00488 private: 00489 const GoGtpEngine& m_engine; 00490 }; 00491 00492 //---------------------------------------------------------------------------- 00493 00494 #endif // GO_GTPENGINE_H