2020-08-20 20:04:08 -03:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2020, the SerenityOS developers.
|
|
|
|
|
*
|
2021-04-22 05:24:48 -03:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
2020-08-20 20:04:08 -03:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "ChessEngine.h"
|
|
|
|
|
#include "MCTSTree.h"
|
2021-05-14 12:27:38 -03:00
|
|
|
#include <AK/Random.h>
|
2020-08-20 20:04:08 -03:00
|
|
|
#include <LibCore/ElapsedTimer.h>
|
|
|
|
|
|
|
|
|
|
using namespace Chess::UCI;
|
|
|
|
|
|
|
|
|
|
void ChessEngine::handle_uci()
|
|
|
|
|
{
|
2022-07-11 14:32:29 -03:00
|
|
|
send_command(IdCommand(IdCommand::Type::Name, "ChessEngine"sv));
|
|
|
|
|
send_command(IdCommand(IdCommand::Type::Author, "the SerenityOS developers"sv));
|
2020-08-20 20:04:08 -03:00
|
|
|
send_command(UCIOkCommand());
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-01 14:58:27 -03:00
|
|
|
void ChessEngine::handle_position(PositionCommand const& command)
|
2020-08-20 20:04:08 -03:00
|
|
|
{
|
|
|
|
|
// FIXME: Implement fen board position.
|
2021-02-23 16:42:32 -03:00
|
|
|
VERIFY(!command.fen().has_value());
|
2020-08-20 20:04:08 -03:00
|
|
|
m_board = Chess::Board();
|
|
|
|
|
for (auto& move : command.moves()) {
|
2021-02-23 16:42:32 -03:00
|
|
|
VERIFY(m_board.apply_move(move));
|
2020-08-20 20:04:08 -03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-01 14:58:27 -03:00
|
|
|
void ChessEngine::handle_go(GoCommand const& command)
|
2020-08-20 20:04:08 -03:00
|
|
|
{
|
|
|
|
|
// FIXME: A better algorithm than naive mcts.
|
|
|
|
|
// FIXME: Add different ways to terminate search.
|
2021-02-23 16:42:32 -03:00
|
|
|
VERIFY(command.movetime.has_value());
|
2020-08-20 20:04:08 -03:00
|
|
|
|
2021-05-14 12:27:38 -03:00
|
|
|
srand(get_random<u32>());
|
2020-08-20 20:04:08 -03:00
|
|
|
|
2021-09-12 12:51:13 -03:00
|
|
|
auto elapsed_time = Core::ElapsedTimer::start_new();
|
2020-08-20 20:04:08 -03:00
|
|
|
|
2022-08-14 11:39:32 -03:00
|
|
|
auto mcts = [this]() -> MCTSTree {
|
|
|
|
|
if (!m_last_tree.has_value())
|
|
|
|
|
return { m_board };
|
|
|
|
|
auto x = m_last_tree.value().child_with_move(m_board.last_move().value());
|
|
|
|
|
if (x.has_value())
|
|
|
|
|
return move(x.value());
|
|
|
|
|
return { m_board };
|
|
|
|
|
}();
|
2020-08-20 20:04:08 -03:00
|
|
|
|
|
|
|
|
int rounds = 0;
|
|
|
|
|
while (elapsed_time.elapsed() <= command.movetime.value()) {
|
|
|
|
|
mcts.do_round();
|
|
|
|
|
++rounds;
|
|
|
|
|
}
|
2021-01-17 14:17:00 -03:00
|
|
|
dbgln("MCTS finished {} rounds.", rounds);
|
|
|
|
|
dbgln("MCTS evaluation {}", mcts.expected_value());
|
2022-08-14 11:39:32 -03:00
|
|
|
auto& best_node = mcts.best_node();
|
|
|
|
|
auto const& best_move = best_node.last_move();
|
2021-01-17 14:17:00 -03:00
|
|
|
dbgln("MCTS best move {}", best_move.to_long_algebraic());
|
2020-08-20 20:04:08 -03:00
|
|
|
send_command(BestMoveCommand(best_move));
|
2022-08-14 11:39:32 -03:00
|
|
|
|
|
|
|
|
m_last_tree = move(best_node);
|
2020-08-20 20:04:08 -03:00
|
|
|
}
|