From: Fabian Fichter Date: Sun, 29 Nov 2020 20:25:22 +0000 (+0100) Subject: Cache legal capture state X-Git-Url: http://winboard.nl/cgi-bin?a=commitdiff_plain;h=4346adf9c14fb5da699dfda094064a4dbc8c51a0;p=fairystockfish.git Cache legal capture state Speed-up for variants with mandatory captures. giveaway STC LLR: 2.94 (-2.94,2.94) [0.00,10.00] Total: 1873 W: 743 L: 637 D: 493 http://www.variantfishtest.org:6543/tests/view/5fc2239d6e23db221d9e9423 losers STC LLR: 2.95 (-2.94,2.94) [0.00,10.00] Total: 1194 W: 577 L: 469 D: 148 http://www.variantfishtest.org:6543/tests/view/5fc223af6e23db221d9e9426 No functional change. --- diff --git a/src/position.cpp b/src/position.cpp index 3cebafe..5c747c4 100644 --- a/src/position.cpp +++ b/src/position.cpp @@ -504,6 +504,7 @@ void Position::set_check_info(StateInfo* si) const { si->checkSquares[KING] = 0; si->shak = si->checkersBB & (byTypeBB[KNIGHT] | byTypeBB[ROOK] | byTypeBB[BERS]); si->bikjang = var->bikjangRule && ksq != SQ_NONE ? bool(attacks_bb(sideToMove, ROOK, ksq, pieces()) & pieces(sideToMove, KING)) : false; + si->legalCapture = NO_VALUE; } @@ -842,20 +843,30 @@ bool Position::legal(Move m) const { return false; // Illegal quiet moves - if (must_capture() && !capture(m)) + if (must_capture() && !capture(m) && st->legalCapture != VALUE_FALSE) { + // Check for cached value + if (st->legalCapture == VALUE_TRUE) + return false; if (checkers()) { for (const auto& mevasion : MoveList(*this)) if (capture(mevasion) && legal(mevasion)) + { + st->legalCapture = VALUE_TRUE; return false; + } } else { for (const auto& mcap : MoveList(*this)) if (capture(mcap) && legal(mcap)) + { + st->legalCapture = VALUE_TRUE; return false; + } } + st->legalCapture = VALUE_FALSE; } // Illegal non-drop moves diff --git a/src/position.h b/src/position.h index 6e4dc48..e57c31c 100644 --- a/src/position.h +++ b/src/position.h @@ -29,6 +29,7 @@ #include "evaluate.h" #include "types.h" #include "variant.h" +#include "movegen.h" #include "nnue/nnue_accumulator.h" @@ -62,6 +63,7 @@ struct StateInfo { Bitboard pinners[COLOR_NB]; Bitboard checkSquares[PIECE_TYPE_NB]; Bitboard flippedPieces; + OptBool legalCapture; bool capturedpromoted; bool shak; bool bikjang; @@ -134,6 +136,7 @@ public: bool checking_permitted() const; bool drop_checks() const; bool must_capture() const; + bool has_capture() const; bool must_drop() const; bool piece_drops() const; bool drop_loop() const; @@ -492,6 +495,10 @@ inline bool Position::must_capture() const { return var->mustCapture; } +inline bool Position::has_capture() const { + return st->legalCapture == VALUE_TRUE || (st->legalCapture == NO_VALUE && MoveList(*this).size()); +} + inline bool Position::must_drop() const { assert(var != nullptr); return var->mustDrop; diff --git a/src/search.cpp b/src/search.cpp index ee7eb04..094dbe1 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -895,7 +895,7 @@ namespace { : ss->staticEval > (ss-2)->staticEval; // Skip early pruning in case of mandatory capture - if (pos.must_capture() && MoveList(pos).size()) + if (pos.must_capture() && pos.has_capture()) goto moves_loop; // Step 8. Futility pruning: child node (~50 Elo) @@ -1250,7 +1250,7 @@ moves_loop: // When in check, search starts from here || ss->staticEval + PieceValue[EG][pos.captured_piece()] <= alpha || cutNode || thisThread->ttHitAverage < 427 * TtHitAverageResolution * TtHitAverageWindow / 1024) - && !(pos.must_capture() && (givesCheck || MoveList(pos).size()))) + && !(pos.must_capture() && (givesCheck || pos.has_capture()))) { Depth r = reduction(improving, depth, moveCount); diff --git a/src/types.h b/src/types.h index bdb4a7c..e71536e 100644 --- a/src/types.h +++ b/src/types.h @@ -294,6 +294,10 @@ enum EnclosingRule { NO_ENCLOSING, REVERSI, ATAXX }; +enum OptBool { + NO_VALUE, VALUE_FALSE, VALUE_TRUE +}; + enum Phase { PHASE_ENDGAME, PHASE_MIDGAME = 128,