Verified SEE pruning for capturing and checking moves.

Patch analyzes field after SEE exchanges concluded with a recapture by
the opponent:
if opponent Queen/Rook/King results under attack after the exchanges, we
consider the move sharp and don't prune it.

Important note:
By accident I forgot to adjust 'occupied' when the king takes part in
the exchanges.
As result of this a move is considered sharp too, when opponent king
apparently can evade check by recapturing.
Surprisingly this seems contribute to patch's strength.

STC:
https://tests.stockfishchess.org/tests/view/640b16132644b62c33947397
LLR: 2.96 (-2.94,2.94) <0.00,2.00>
Total: 116400 W: 31239 L: 30817 D: 54344
Ptnml(0-2): 350, 12742, 31618, 13116, 374

LTC:
https://tests.stockfishchess.org/tests/view/640c88092644b62c3394c1c5
LLR: 2.95 (-2.94,2.94) <0.50,2.50>
Total: 177600 W: 47988 L: 47421 D: 82191
Ptnml(0-2): 62, 16905, 54317, 17436, 80

closes https://github.com/official-stockfish/Stockfish/pull/4453

bench: 5012145
This commit is contained in:
pb00067
2023-03-20 08:56:44 +01:00
committed by Joost VandeVondele
parent 02e4697055
commit 24b37e4586
5 changed files with 37 additions and 17 deletions

View File

@@ -1019,9 +1019,27 @@ moves_loop: // When in check, search starts here
+ captureHistory[movedPiece][to_sq(move)][type_of(pos.piece_on(to_sq(move)))] / 7 < alpha)
continue;
Bitboard occupied;
// SEE based pruning (~11 Elo)
if (!pos.see_ge(move, Value(-206) * depth))
continue;
if (!pos.see_ge(move, occupied, Value(-206) * depth))
{
if (depth < 2 - capture)
continue;
// don't prune move if a heavy enemy piece (KQR) is under attack after the exchanges
Bitboard leftEnemies = (pos.pieces(~us, QUEEN, ROOK) | pos.pieces(~us, KING)) & occupied;
Bitboard attacks = 0;
occupied |= to_sq(move);
while (leftEnemies && !attacks)
{
Square sq = pop_lsb(leftEnemies);
attacks |= pos.attackers_to(sq, occupied) & pos.pieces(us) & occupied;
// exclude Queen/Rook(s) which were already threatened before SEE
if (attacks && (sq != pos.square<KING>(~us) && (pos.attackers_to(sq, pos.pieces()) & pos.pieces(us))))
attacks = 0;
}
if (!attacks)
continue;
}
}
else
{
@@ -1047,8 +1065,9 @@ moves_loop: // When in check, search starts here
lmrDepth = std::max(lmrDepth, 0);
Bitboard occupied;
// Prune moves with negative SEE (~4 Elo)
if (!pos.see_ge(move, Value(-24 * lmrDepth * lmrDepth - 15 * lmrDepth)))
if (!pos.see_ge(move, occupied, Value(-24 * lmrDepth * lmrDepth - 15 * lmrDepth)))
continue;
}
}
@@ -1533,6 +1552,7 @@ moves_loop: // When in check, search starts here
prevSq);
int quietCheckEvasions = 0;
Bitboard occupied;
// Step 5. Loop through all pseudo-legal moves until no moves remain
// or a beta cutoff occurs.
@@ -1569,7 +1589,7 @@ moves_loop: // When in check, search starts here
continue;
}
if (futilityBase <= alpha && !pos.see_ge(move, VALUE_ZERO + 1))
if (futilityBase <= alpha && !pos.see_ge(move, occupied, VALUE_ZERO + 1))
{
bestValue = std::max(bestValue, futilityBase);
continue;
@@ -1588,7 +1608,7 @@ moves_loop: // When in check, search starts here
continue;
// Do not search moves with bad enough SEE values (~5 Elo)
if (!pos.see_ge(move, Value(-110)))
if (!pos.see_ge(move, occupied, Value(-110)))
continue;
}