From d4627759ff425b6c34ab7026aba1ad9978c3f1fa Mon Sep 17 00:00:00 2001 From: mstembera Date: Sat, 6 Jan 2024 19:29:27 -0800 Subject: [PATCH] Introduce BAD_QUIET movepicker stage Split quiets into good and bad as we do with captures. When we find the first quiet move below a certain threshold that has been sorted we consider all subsequent quiets bad. Inspired by @locutus2 idea to skip bad captures. --- src/movepick.cpp | 45 +++++++++++++++++++++++++++++++++++++++------ src/movepick.h | 10 +++++----- 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/src/movepick.cpp b/src/movepick.cpp index b19f406fb..fa9b93adf 100644 --- a/src/movepick.cpp +++ b/src/movepick.cpp @@ -37,8 +37,9 @@ enum Stages { GOOD_CAPTURE, REFUTATION, QUIET_INIT, - QUIET, + GOOD_QUIET, BAD_CAPTURE, + BAD_QUIET, // generate evasion moves EVASION_TT, @@ -247,6 +248,8 @@ Move MovePicker::select(Pred filter) { // moves left, picking the move with the highest score from a list of generated moves. Move MovePicker::next_move(bool skipQuiets) { + auto quiet_threshold = [](Depth d) { return -3330 * d; }; + top: switch (stage) { @@ -299,20 +302,34 @@ Move MovePicker::next_move(bool skipQuiets) { if (!skipQuiets) { cur = endBadCaptures; - endMoves = generate(pos, cur); + endMoves = beginBadQuiets = endBadQuiets = generate(pos, cur); score(); - partial_insertion_sort(cur, endMoves, -3330 * depth); + partial_insertion_sort(cur, endMoves, quiet_threshold(depth)); } ++stage; [[fallthrough]]; - case QUIET : + case GOOD_QUIET : if (!skipQuiets && select([&]() { return *cur != refutations[0] && *cur != refutations[1] && *cur != refutations[2]; })) - return *(cur - 1); + { + Move tmp = *(cur - 1); + if ((cur - 1)->value < -7500 && (cur - 1)->value > quiet_threshold(depth)) + { + // Remaining quiets are bad + beginBadQuiets = cur; + + // Prepare the pointers to loop over the bad captures + cur = moves; + endMoves = endBadCaptures; + + ++stage; + } + return tmp; + } // Prepare the pointers to loop over the bad captures cur = moves; @@ -322,7 +339,23 @@ Move MovePicker::next_move(bool skipQuiets) { [[fallthrough]]; case BAD_CAPTURE : - return select([]() { return true; }); + if (select([]() { return true; })) + return *(cur - 1); + + // Prepare the pointers to loop over the bad quiets + cur = beginBadQuiets; + endMoves = endBadQuiets; + + ++stage; + [[fallthrough]]; + + case BAD_QUIET : + if (!skipQuiets) + return select([&]() { + return *cur != refutations[0] && *cur != refutations[1] && *cur != refutations[2]; + }); + + return Move::none(); case EVASION_INIT : cur = moves; diff --git a/src/movepick.h b/src/movepick.h index d6298d48d..d5c95616c 100644 --- a/src/movepick.h +++ b/src/movepick.h @@ -188,11 +188,11 @@ class MovePicker { const PieceToHistory** continuationHistory; const PawnHistory* pawnHistory; Move ttMove; - ExtMove refutations[3], *cur, *endMoves, *endBadCaptures; - int stage; - int threshold; - Depth depth; - ExtMove moves[MAX_MOVES]; + ExtMove refutations[3], *cur, *endMoves, *endBadCaptures, *beginBadQuiets, *endBadQuiets; + int stage; + int threshold; + Depth depth; + ExtMove moves[MAX_MOVES]; }; } // namespace Stockfish