diff --git a/src/thinking.cc b/src/thinking.cc index ced717b..4009036 100644 --- a/src/thinking.cc +++ b/src/thinking.cc @@ -191,3 +191,18 @@ void Thinking::Ponderhit() { sleep_condition_.notify_one(); } + +void Thinking::SetMateInfo(Node& node, std::vector sfen_moves) { + for (size_t i = 0, n = sfen_moves.size(); i < n; ++i) { + Move move = Move::FromSfen(sfen_moves[i], node); + Score eval = node.Evaluate(); + Score score = i % 2 == 0 ? score_mate_in(n - i) : score_mated_in(n - i); + + // 読み筋の局面の詰み情報を置換表に格納する + shared_data_.hash_table.Save(node.key(), move, score, (kMaxPly - 1) * kOnePly, kBoundExact, eval, true); + //SYNCED_PRINTF("i=%d, move=%s, eval=%d, score=%d\n", i, move.ToSfen().c_str(), eval, score); + + // 局面を進める + node.MakeMove(move); + } +} diff --git a/src/thinking.h b/src/thinking.h index a42b12d..cffe6ce 100644 --- a/src/thinking.h +++ b/src/thinking.h @@ -89,6 +89,11 @@ class Thinking { */ void Ponderhit(); + /** + * 読み筋の局面の詰み情報をエンジンに伝えます. + */ + void SetMateInfo(Node& node, std::vector sfen_moves); + private: const UsiOptions& usi_options_; std::mutex mutex_; diff --git a/src/usi.cc b/src/usi.cc index f8b0260..cd3e421 100644 --- a/src/usi.cc +++ b/src/usi.cc @@ -37,7 +37,7 @@ namespace { -const auto kProgramName = "Gikou 2"; +const auto kProgramName = "Gikou 2 MateInfo 20170514"; const auto kAuthorName = "Yosuke Demura"; /** @@ -81,6 +81,8 @@ class CommandQueue { std::condition_variable sleep_condition_; }; +void SetRootNode(std::istream& input, Node* const node); + void ReceiveCommands(CommandQueue* const queue, Thinking* const thinking) { assert(queue != nullptr); assert(thinking != nullptr); @@ -123,6 +125,41 @@ void ReceiveCommands(CommandQueue* const queue, Thinking* const thinking) { // 到着してしまい、stop/ponderhitコマンドが機能しないおそれがあるため。 } else if (type == "go") { thinking->ResetSignals(); + + // mateinfoコマンド対応 + // ・SimpleGougiShogiの合議タイプ「詰探索エンジンとの合議(読み筋の局面も詰探索)」で使用する。 + // ・過去にGUI側に送った読み筋の局面について詰探索エンジンが詰みを見つけた場合、GUI側から以下のようなコマンドが送られてくる。 + // 「mateinfo position sfen(読み筋の局面)checkmate(詰みまでの指し手)」 + // (例)「mateinfo position sfen ln1g1g1n1/2s1k4/p1ppp3p/5ppR1/P8/2P1LKP2/3PPP2P/5+rS2/L5sNL b BGSN2Pbg2p 1 checkmate 5f5c+ 5b5c N*6e 5c4b S*4c 4b5a G*4b 4a4b 4c4b+ 5a4b 2d2b+ S*3b G*5c 4b4a B*5b 6a5b 5c5b 4a5b 2b3b L*4b S*5c 5b6a G*6b」 + // ・相手玉の詰みを見つけた場合だけではなく、自玉の詰みを見つけた場合もあるので注意。 + // ・mateinfoコマンドの利用方法の一例として、この実装では置換表にmateの評価値を登録してみる。 + } else if (type == "mateinfo") { + std::size_t found_sfen = command.find(" sfen "); + std::size_t found_checkmate = command.find(" checkmate "); + + if (found_sfen != std::string::npos && found_checkmate != std::string::npos) { + // (例)「sfen ln1g1g1n1/2s1k4/p1ppp3p/5ppR1/P8/2P1LKP2/3PPP2P/5+rS2/L5sNL b BGSN2Pbg2p 1」 + std::string sfen = command.substr(found_sfen + 1, found_checkmate - found_sfen - 1); + // (例)「5f5c+ 5b5c N*6e 5c4b S*4c 4b5a G*4b 4a4b 4c4b+ 5a4b 2d2b+ S*3b G*5c 4b4a B*5b 6a5b 5c5b 4a5b 2b3b L*4b S*5c 5b6a G*6b」 + std::string moves = command.substr(found_checkmate + std::string(" checkmate ").length()); + + std::istringstream is_sfen(sfen); + std::istringstream is_moves(moves); + + // 局面をセット + Node node(Position::CreateStartPosition()); + SetRootNode(is_sfen, &node); + + // 詰みまでの指し手 + std::vector sfen_moves; + for (std::string sfen_move; is_moves >> sfen_move;) { + sfen_moves.push_back(sfen_move); + } + + // 読み筋の局面の詰み情報をエンジンに伝える + thinking->SetMateInfo(node, sfen_moves); + continue; + } } // コマンドをキューに保存する