From 57bb4d1aec903b5336aa06d1b0de4d016a403043 Mon Sep 17 00:00:00 2001 From: Peter Elliott Date: Sat, 19 Jun 2021 14:49:53 -0600 Subject: [PATCH] LibChess: Only save hash of board state for repetition checking This more than doubles the number of nodes that MCTS can search for a given time limit, and greatly reduces memory usage. --- Userland/Libraries/LibChess/Chess.cpp | 12 +++++------- Userland/Libraries/LibChess/Chess.h | 7 ++++--- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Userland/Libraries/LibChess/Chess.cpp b/Userland/Libraries/LibChess/Chess.cpp index 981db187159..d173b78c830 100644 --- a/Userland/Libraries/LibChess/Chess.cpp +++ b/Userland/Libraries/LibChess/Chess.cpp @@ -579,14 +579,12 @@ bool Board::apply_move(const Move& move, Color color) bool Board::apply_illegal_move(const Move& move, Color color) { - Board clone = *this; - clone.m_previous_states = {}; - clone.m_moves = {}; + auto state = Traits::hash(*this); auto state_count = 0; - if (m_previous_states.contains(clone)) - state_count = m_previous_states.get(clone).value(); + if (m_previous_states.contains(state)) + state_count = m_previous_states.get(state).value(); - m_previous_states.set(clone, state_count + 1); + m_previous_states.set(state, state_count + 1); m_moves.append(move); m_turn = opposing_color(color); @@ -758,7 +756,7 @@ Board::Result Board::game_result() const if (m_moves_since_capture == 50 * 2) return Result::FiftyMoveRule; - auto repeats = m_previous_states.get(*this); + auto repeats = m_previous_states.get(Traits::hash(*this)); if (repeats.has_value()) { if (repeats.value() == 3) return Result::ThreeFoldRepetition; diff --git a/Userland/Libraries/LibChess/Chess.h b/Userland/Libraries/LibChess/Chess.h index ac227ea2878..9ad01408aee 100644 --- a/Userland/Libraries/LibChess/Chess.h +++ b/Userland/Libraries/LibChess/Chess.h @@ -172,7 +172,8 @@ private: bool m_black_can_castle_kingside { true }; bool m_black_can_castle_queenside { true }; - HashMap m_previous_states; + // We trust that hash collisions will not happen to save lots of memory and time. + HashMap m_previous_states; Vector m_moves; friend struct Traits; }; @@ -276,7 +277,7 @@ void Board::generate_moves(Callback callback, Color color) const template<> struct AK::Traits : public GenericTraits { - static unsigned hash(Chess::Piece piece) + static unsigned hash(const Chess::Piece& piece) { return pair_int_hash(static_cast(piece.color), static_cast(piece.type)); } @@ -284,7 +285,7 @@ struct AK::Traits : public GenericTraits { template<> struct AK::Traits : public GenericTraits { - static unsigned hash(Chess::Board chess) + static unsigned hash(const Chess::Board chess) { unsigned hash = 0; hash = pair_int_hash(hash, static_cast(chess.m_white_can_castle_queenside));