mirror of
https://github.com/sockspls/badfish
synced 2025-05-02 01:29:36 +00:00
Cleanup and reorder in qsearch
This patch is a simplification / code normalisation in qsearch. Adds steps in comments the same way we have in search; Makes a separate "pruning" stage instead of heuristics randomly being spread over qsearch code; Reorders pruning heuristics from least taxing ones to more taxing ones; Removes repeated check for best value not being mated, instead uses 1 check - thus removes some lines of code. Moves prefetch and move setup after pruning - makes no sense to do them if move will actually get pruned. Passed non-regression test: https://tests.stockfishchess.org/tests/view/63dd2c5ff9a50a69252c1413 LLR: 2.95 (-2.94,2.94) <-1.75,0.25> Total: 113504 W: 29898 L: 29770 D: 53836 Ptnml(0-2): 287, 11861, 32327, 11991, 286 https://github.com/official-stockfish/Stockfish/pull/4382 Non-functional change.
This commit is contained in:
parent
d5817a5896
commit
8f843633db
1 changed files with 30 additions and 24 deletions
|
@ -1427,6 +1427,7 @@ moves_loop: // When in check, search starts here
|
|||
bool pvHit, givesCheck, capture;
|
||||
int moveCount;
|
||||
|
||||
// Step 1. Initialize node
|
||||
if (PvNode)
|
||||
{
|
||||
(ss+1)->pv = pv;
|
||||
|
@ -1438,7 +1439,7 @@ moves_loop: // When in check, search starts here
|
|||
ss->inCheck = pos.checkers();
|
||||
moveCount = 0;
|
||||
|
||||
// Check for an immediate draw or maximum ply reached
|
||||
// Step 2. Check for an immediate draw or maximum ply reached
|
||||
if ( pos.is_draw(ss->ply)
|
||||
|| ss->ply >= MAX_PLY)
|
||||
return (ss->ply >= MAX_PLY && !ss->inCheck) ? evaluate(pos) : VALUE_DRAW;
|
||||
|
@ -1450,13 +1451,14 @@ moves_loop: // When in check, search starts here
|
|||
// only two types of depth in TT: DEPTH_QS_CHECKS or DEPTH_QS_NO_CHECKS.
|
||||
ttDepth = ss->inCheck || depth >= DEPTH_QS_CHECKS ? DEPTH_QS_CHECKS
|
||||
: DEPTH_QS_NO_CHECKS;
|
||||
// Transposition table lookup
|
||||
// Step 3. Transposition table lookup
|
||||
posKey = pos.key();
|
||||
tte = TT.probe(posKey, ss->ttHit);
|
||||
ttValue = ss->ttHit ? value_from_tt(tte->value(), ss->ply, pos.rule50_count()) : VALUE_NONE;
|
||||
ttMove = ss->ttHit ? tte->move() : MOVE_NONE;
|
||||
pvHit = ss->ttHit && tte->is_pv();
|
||||
|
||||
// At non-PV nodes we check for an early TT cutoff
|
||||
if ( !PvNode
|
||||
&& ss->ttHit
|
||||
&& tte->depth() >= ttDepth
|
||||
|
@ -1464,7 +1466,7 @@ moves_loop: // When in check, search starts here
|
|||
&& (tte->bound() & (ttValue >= beta ? BOUND_LOWER : BOUND_UPPER)))
|
||||
return ttValue;
|
||||
|
||||
// Evaluate the position statically
|
||||
// Step 4. Static evaluation of the position
|
||||
if (ss->inCheck)
|
||||
{
|
||||
ss->staticEval = VALUE_NONE;
|
||||
|
@ -1522,7 +1524,8 @@ moves_loop: // When in check, search starts here
|
|||
|
||||
int quietCheckEvasions = 0;
|
||||
|
||||
// Loop through the moves until no moves remain or a beta cutoff occurs
|
||||
// Step 5. Loop through all pseudo-legal moves until no moves remain
|
||||
// or a beta cutoff occurs.
|
||||
while ((move = mp.next_move()) != MOVE_NONE)
|
||||
{
|
||||
assert(is_ok(move));
|
||||
|
@ -1536,9 +1539,11 @@ moves_loop: // When in check, search starts here
|
|||
|
||||
moveCount++;
|
||||
|
||||
// Step 6. Pruning.
|
||||
if (bestValue > VALUE_TB_LOSS_IN_MAX_PLY)
|
||||
{
|
||||
// Futility pruning and moveCount pruning (~10 Elo)
|
||||
if ( bestValue > VALUE_TB_LOSS_IN_MAX_PLY
|
||||
&& !givesCheck
|
||||
if ( !givesCheck
|
||||
&& to_sq(move) != prevSq
|
||||
&& futilityBase > -VALUE_KNOWN_WIN
|
||||
&& type_of(move) != PROMOTION)
|
||||
|
@ -1561,43 +1566,43 @@ moves_loop: // When in check, search starts here
|
|||
}
|
||||
}
|
||||
|
||||
// Do not search moves with bad enough SEE values (~5 Elo)
|
||||
if ( bestValue > VALUE_TB_LOSS_IN_MAX_PLY
|
||||
&& !pos.see_ge(move, Value(-108)))
|
||||
// We prune after 2nd quiet check evasion where being 'in check' is implicitly checked through the counter
|
||||
// and being a 'quiet' apart from being a tt move is assumed after an increment because captures are pushed ahead.
|
||||
if (quietCheckEvasions > 1)
|
||||
break;
|
||||
|
||||
// Continuation history based pruning (~3 Elo)
|
||||
if ( !capture
|
||||
&& (*contHist[0])[pos.moved_piece(move)][to_sq(move)] < 0
|
||||
&& (*contHist[1])[pos.moved_piece(move)][to_sq(move)] < 0)
|
||||
continue;
|
||||
|
||||
// Do not search moves with bad enough SEE values (~5 Elo)
|
||||
if (!pos.see_ge(move, Value(-108)))
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
// Speculative prefetch as early as possible
|
||||
prefetch(TT.first_entry(pos.key_after(move)));
|
||||
|
||||
// Update the current move
|
||||
ss->currentMove = move;
|
||||
ss->continuationHistory = &thisThread->continuationHistory[ss->inCheck]
|
||||
[capture]
|
||||
[pos.moved_piece(move)]
|
||||
[to_sq(move)];
|
||||
|
||||
// Continuation history based pruning (~3 Elo)
|
||||
if ( !capture
|
||||
&& bestValue > VALUE_TB_LOSS_IN_MAX_PLY
|
||||
&& (*contHist[0])[pos.moved_piece(move)][to_sq(move)] < 0
|
||||
&& (*contHist[1])[pos.moved_piece(move)][to_sq(move)] < 0)
|
||||
continue;
|
||||
|
||||
// We prune after 2nd quiet check evasion where being 'in check' is implicitly checked through the counter
|
||||
// and being a 'quiet' apart from being a tt move is assumed after an increment because captures are pushed ahead.
|
||||
if ( bestValue > VALUE_TB_LOSS_IN_MAX_PLY
|
||||
&& quietCheckEvasions > 1)
|
||||
break;
|
||||
|
||||
quietCheckEvasions += !capture && ss->inCheck;
|
||||
|
||||
// Make and search the move
|
||||
// Step 7. Make and search the move
|
||||
pos.do_move(move, st, givesCheck);
|
||||
value = -qsearch<nodeType>(pos, ss+1, -beta, -alpha, depth - 1);
|
||||
pos.undo_move(move);
|
||||
|
||||
assert(value > -VALUE_INFINITE && value < VALUE_INFINITE);
|
||||
|
||||
// Check for a new best move
|
||||
// Step 8. Check for a new best move
|
||||
if (value > bestValue)
|
||||
{
|
||||
bestValue = value;
|
||||
|
@ -1617,6 +1622,7 @@ moves_loop: // When in check, search starts here
|
|||
}
|
||||
}
|
||||
|
||||
// Step 9. Check for mate
|
||||
// All legal moves have been searched. A special case: if we're in check
|
||||
// and no legal moves were found, it is checkmate.
|
||||
if (ss->inCheck && bestValue == -VALUE_INFINITE)
|
||||
|
|
Loading…
Add table
Reference in a new issue