match.cpp (4748B)
1 #include "match.hpp" 2 #include "logger.hpp" 3 #include "repetition.hpp" 4 #include "timer.hpp" 5 #include "utils_ui.hpp" 6 #include <algorithm> 7 8 uint16_t Match::id_t = 0; 9 Match::~Match() { logger::log(std::format("Match {}: destroyed", id), logger::Debug); } 10 Match::Match(Engine &white, Engine &black) : engines({&white, &black}) { 11 logger::log(std::format("Match {}: created", id), logger::Debug); 12 } 13 14 Game Match::play(Settings swhite, Settings sblack, const std::string &fen = Game::startPosition) { 15 const std::string position = "position " + (fen == Game::startPosition ? "startpos" : "fen " + fen); 16 17 repetition::Table rtable; 18 Board board(fen); 19 Move move; 20 21 logger::log(std::format("Match {}: Play a game between {}(white) and {}(black)", id, 22 engines[0]->get_name(), engines[1]->get_name())); 23 Game game(id, engines[0]->get_name(), engines[1]->get_name(), fen); 24 25 engines[0]->send("ucinewgame"); 26 engines[1]->send("ucinewgame"); 27 28 Color turn = board.get_side(); 29 while (true) { 30 const MoveList list = MoveList(board, false, true); 31 if (!list.size()) { 32 game.set_winner(other(turn)); 33 break; 34 } 35 36 Engine *engine = engines[turn]; 37 engine->send(std::format("{} moves {}", position, game.get_moves())); 38 engine->send(get_go(swhite, sblack, turn)); 39 40 std::string response; 41 42 uint64_t time_start = timer::get_ms(); 43 while (true) { 44 response = engine->receive(); 45 if (response.starts_with("bestmove")) break; 46 } 47 uint64_t time_passed = timer::get_ms() - time_start; 48 49 std::string move_str = response.substr(9); 50 if ((move = parse_move(list, move_str)) == Move() || !move.make(board)) { 51 logger::log(std::format("Match {}: {} illegal {}", id, to_string(turn), (std::string)move)); 52 game.set_terminate(Game::Illegal); 53 game.set_winner(other(turn)); 54 break; 55 } 56 57 if (rtable.is_repetition(board.get_hash())) { 58 logger::log(std::format("Match {}: {} repetition", id, to_string(turn))); 59 game.set_terminate(Game::Repetition); 60 game.set_draw(true); 61 break; 62 } 63 64 rtable.push_hash(board.get_hash()); 65 if (!move.is_repeatable()) rtable.push_null(); 66 game.play(move); 67 68 if ((turn == WHITE ? swhite.time : sblack.time) <= time_passed) { 69 logger::log(std::format("Match {}: {} timeout", id, to_string(turn))); 70 game.set_terminate(Game::Timeout); 71 game.set_winner(other(turn)); 72 break; 73 } 74 75 if (turn == WHITE && !swhite.depth) swhite.time -= time_passed; 76 if (turn == BLACK && !sblack.depth) sblack.time -= time_passed; 77 78 logger::log(std::format("Match {}: wtime: {}, btime: {}", id, swhite.time, sblack.time), 79 logger::Debug); 80 81 turn = other(turn); 82 } 83 84 if (!game.is_draw()) { 85 logger::log(std::format("Match {}: winner is {}", id, to_string(game.get_winner()))); 86 } else { 87 logger::log(std::format("Match {}: ended in a draw", id)); 88 } 89 90 std::swap(engines[0], engines[1]); 91 return game; 92 } 93 94 std::string Match::get_go(Settings &swhite, Settings &sblack, Color side) { 95 std::string go = "go"; 96 if (side == WHITE && swhite.depth) go += " depth " + std::to_string(swhite.depth); 97 else { 98 if (side == WHITE && swhite.togo) go += " movestogo " + std::to_string(swhite.togo); 99 if (!sblack.depth && swhite.time) go += " wtime " + std::to_string(swhite.time); 100 if (swhite.inc) go += " winc " + std::to_string(swhite.inc); 101 if (swhite.movetime) go += " movetime " + std::to_string(swhite.movetime); 102 } 103 104 if (side == BLACK && sblack.depth) go += " depth " + std::to_string(sblack.depth); 105 else { 106 if (side == BLACK && sblack.togo) go += " movestogo " + std::to_string(sblack.togo); 107 if (!swhite.depth && sblack.time) go += " btime " + std::to_string(sblack.time); 108 if (sblack.inc) go += " binc " + std::to_string(sblack.inc); 109 if (swhite.movetime) go += " movetime " + std::to_string(sblack.movetime); 110 } 111 112 return go; 113 } 114 115 Move Match::parse_move(const MoveList &list, const std::string &move_string) { 116 const Square source = from_coordinates(move_string.substr(0, 2)); 117 const Square target = from_coordinates(move_string.substr(2, 2)); 118 119 for (int i = 0; i < list.size(); i++) { 120 const Move crnt = list[i]; 121 if (crnt.source() != source || crnt.target() != target) continue; 122 if (move_string[4] && tolower(piece::get_code(crnt.promoted())) != move_string[4]) continue; 123 return crnt; 124 } 125 return {}; 126 }