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