Serenity Operating System
at master 64 lines 1.8 kB view raw
1/* 2 * Copyright (c) 2020, the SerenityOS developers. 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include "ChessEngine.h" 8#include "MCTSTree.h" 9#include <AK/Random.h> 10#include <LibCore/DeprecatedFile.h> 11#include <LibCore/ElapsedTimer.h> 12 13using namespace Chess::UCI; 14 15void ChessEngine::handle_uci() 16{ 17 send_command(IdCommand(IdCommand::Type::Name, "ChessEngine"sv)); 18 send_command(IdCommand(IdCommand::Type::Author, "the SerenityOS developers"sv)); 19 send_command(UCIOkCommand()); 20} 21 22void ChessEngine::handle_position(PositionCommand const& command) 23{ 24 // FIXME: Implement fen board position. 25 VERIFY(!command.fen().has_value()); 26 m_board = Chess::Board(); 27 for (auto& move : command.moves()) { 28 VERIFY(m_board.apply_move(move)); 29 } 30} 31 32void ChessEngine::handle_go(GoCommand const& command) 33{ 34 // FIXME: A better algorithm than naive mcts. 35 // FIXME: Add different ways to terminate search. 36 VERIFY(command.movetime.has_value()); 37 38 srand(get_random<u32>()); 39 40 auto elapsed_time = Core::ElapsedTimer::start_new(); 41 42 auto mcts = [this]() -> MCTSTree { 43 if (!m_last_tree.has_value()) 44 return { m_board }; 45 auto x = m_last_tree.value().child_with_move(m_board.last_move().value()); 46 if (x.has_value()) 47 return move(x.value()); 48 return { m_board }; 49 }(); 50 51 int rounds = 0; 52 while (elapsed_time.elapsed() <= command.movetime.value()) { 53 mcts.do_round(); 54 ++rounds; 55 } 56 dbgln("MCTS finished {} rounds.", rounds); 57 dbgln("MCTS evaluation {}", mcts.expected_value()); 58 auto& best_node = mcts.best_node(); 59 auto const& best_move = best_node.last_move(); 60 dbgln("MCTS best move {}", best_move.to_long_algebraic()); 61 send_command(BestMoveCommand(best_move)); 62 63 m_last_tree = move(best_node); 64}