Jelajahi Sumber

ChessEngine: Use reduced Board objects in MCTSTree

Monte-Carlo methods are known to intensively create nodes and in our
case each leaf of the tree stores a board. However, for this use case,
we don't need a full board object that also contains game information.

This patch adds a `clone_cleared()` method that return a clone without
game information and uses it when constructing the tree.
It allows the ChessEngine much more possibility before getting out of
memory.
Lucas CHOLLET 3 tahun lalu
induk
melakukan
351fc0cce2

+ 10 - 0
Userland/Libraries/LibChess/Chess.cpp

@@ -259,6 +259,16 @@ Board::Board()
     set_piece(Square("h8"), { Color::Black, Type::Rook });
 }
 
+Board Board::clone_without_history() const
+{
+    // Note: When used in the MCTSTree, the board doesn't need to have all information about previous states.
+    // It spares a huge amount of memory.
+    auto result = *this;
+    result.m_moves.clear();
+    result.m_previous_states.clear();
+    return result;
+}
+
 String Board::to_fen() const
 {
     StringBuilder builder;

+ 1 - 0
Userland/Libraries/LibChess/Chess.h

@@ -117,6 +117,7 @@ struct Move {
 class Board {
 public:
     Board();
+    Board clone_without_history() const;
 
     Piece get_piece(Square const&) const;
     Piece set_piece(Square const&, Piece const&);

+ 4 - 4
Userland/Services/ChessEngine/MCTSTree.cpp

@@ -39,10 +39,10 @@ MCTSTree& MCTSTree::expand()
     VERIFY(!expanded() || m_children.size() == 0);
 
     if (!m_moves_generated) {
-        m_board->generate_moves([&](Chess::Move move) {
-            Chess::Board clone = *m_board;
-            clone.apply_move(move);
-            m_children.append(make<MCTSTree>(clone, this));
+        m_board->generate_moves([&](Chess::Move chess_move) {
+            auto clone = m_board->clone_without_history();
+            clone.apply_move(chess_move);
+            m_children.append(make<MCTSTree>(move(clone), this));
             return IterationDecision::Continue;
         });
         m_moves_generated = true;