mirror of
https://github.com/sockspls/badfish
synced 2025-05-01 17:19:36 +00:00
Introduce ProbCut for check evasions
The idea of this patch can be described as follows: if we are in check and the transposition table move is a capture that returns a value far above beta, we can assume that the opponent just blundered a piece by giving check, and we return the transposition table value. This is similar to the usual probCut logic for quiet moves, but with a different threshold. Passed STC LLR: 2.94 (-2.94,2.94) {-0.25,1.25} Total: 33440 W: 3056 L: 2891 D: 27493 Ptnml(0-2): 110, 2338, 11672, 2477, 123 https://tests.stockfishchess.org/tests/view/602cd1087f517a561bc49bda Passed LTC LLR: 2.98 (-2.94,2.94) {0.25,1.25} Total: 10072 W: 401 L: 309 D: 9362 Ptnml(0-2): 2, 288, 4365, 378, 3 https://tests.stockfishchess.org/tests/view/602ceea57f517a561bc49bf0 The committed version has an additional fix to never return unproven wins in the tablebase range or the mate range. This fix passed tests for non- regression at STC and LTC: STC: LLR: 2.93 (-2.94,2.94) {-1.25,0.25} Total: 26240 W: 2354 L: 2280 D: 21606 Ptnml(0-2): 85, 1763, 9372, 1793, 107 https://tests.stockfishchess.org/tests/view/602d86a87f517a561bc49c7a LTC: LLR: 2.95 (-2.94,2.94) {-0.75,0.25} Total: 35304 W: 1299 L: 1256 D: 32749 Ptnml(0-2): 14, 1095, 15395, 1130, 18 https://tests.stockfishchess.org/tests/view/602d98d17f517a561bc49c83 Closes https://github.com/official-stockfish/Stockfish/pull/3362 Bench: 3830215
This commit is contained in:
parent
6294db7514
commit
7c30091a92
1 changed files with 26 additions and 10 deletions
|
@ -969,6 +969,23 @@ namespace {
|
||||||
|
|
||||||
moves_loop: // When in check, search starts from here
|
moves_loop: // When in check, search starts from here
|
||||||
|
|
||||||
|
ttCapture = ttMove && pos.capture_or_promotion(ttMove);
|
||||||
|
|
||||||
|
// Step 11. A small Probcut idea, when we are in check
|
||||||
|
probCutBeta = beta + 400;
|
||||||
|
if ( ss->inCheck
|
||||||
|
&& !PvNode
|
||||||
|
&& depth >= 4
|
||||||
|
&& ttCapture
|
||||||
|
&& (tte->bound() & BOUND_LOWER)
|
||||||
|
&& tte->depth() >= depth - 3
|
||||||
|
&& ttValue >= probCutBeta
|
||||||
|
&& abs(ttValue) <= VALUE_KNOWN_WIN
|
||||||
|
&& abs(beta) <= VALUE_KNOWN_WIN
|
||||||
|
)
|
||||||
|
return probCutBeta;
|
||||||
|
|
||||||
|
|
||||||
const PieceToHistory* contHist[] = { (ss-1)->continuationHistory, (ss-2)->continuationHistory,
|
const PieceToHistory* contHist[] = { (ss-1)->continuationHistory, (ss-2)->continuationHistory,
|
||||||
nullptr , (ss-4)->continuationHistory,
|
nullptr , (ss-4)->continuationHistory,
|
||||||
nullptr , (ss-6)->continuationHistory };
|
nullptr , (ss-6)->continuationHistory };
|
||||||
|
@ -985,12 +1002,11 @@ moves_loop: // When in check, search starts from here
|
||||||
|
|
||||||
value = bestValue;
|
value = bestValue;
|
||||||
singularQuietLMR = moveCountPruning = false;
|
singularQuietLMR = moveCountPruning = false;
|
||||||
ttCapture = ttMove && pos.capture_or_promotion(ttMove);
|
|
||||||
|
|
||||||
// Mark this node as being searched
|
// Mark this node as being searched
|
||||||
ThreadHolding th(thisThread, posKey, ss->ply);
|
ThreadHolding th(thisThread, posKey, ss->ply);
|
||||||
|
|
||||||
// Step 11. Loop through all pseudo-legal moves until no moves remain
|
// Step 12. Loop through all pseudo-legal moves until no moves remain
|
||||||
// or a beta cutoff occurs.
|
// or a beta cutoff occurs.
|
||||||
while ((move = mp.next_move(moveCountPruning)) != MOVE_NONE)
|
while ((move = mp.next_move(moveCountPruning)) != MOVE_NONE)
|
||||||
{
|
{
|
||||||
|
@ -1036,7 +1052,7 @@ moves_loop: // When in check, search starts from here
|
||||||
// Calculate new depth for this move
|
// Calculate new depth for this move
|
||||||
newDepth = depth - 1;
|
newDepth = depth - 1;
|
||||||
|
|
||||||
// Step 12. Pruning at shallow depth (~200 Elo)
|
// Step 13. Pruning at shallow depth (~200 Elo)
|
||||||
if ( !rootNode
|
if ( !rootNode
|
||||||
&& pos.non_pawn_material(us)
|
&& pos.non_pawn_material(us)
|
||||||
&& bestValue > VALUE_TB_LOSS_IN_MAX_PLY)
|
&& bestValue > VALUE_TB_LOSS_IN_MAX_PLY)
|
||||||
|
@ -1084,7 +1100,7 @@ moves_loop: // When in check, search starts from here
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 13. Extensions (~75 Elo)
|
// Step 14. Extensions (~75 Elo)
|
||||||
|
|
||||||
// Singular extension search (~70 Elo). If all moves but one fail low on a
|
// Singular extension search (~70 Elo). If all moves but one fail low on a
|
||||||
// search of (alpha-s, beta-s), and just one fails high on (alpha, beta),
|
// search of (alpha-s, beta-s), and just one fails high on (alpha, beta),
|
||||||
|
@ -1156,10 +1172,10 @@ moves_loop: // When in check, search starts from here
|
||||||
[movedPiece]
|
[movedPiece]
|
||||||
[to_sq(move)];
|
[to_sq(move)];
|
||||||
|
|
||||||
// Step 14. Make the move
|
// Step 15. Make the move
|
||||||
pos.do_move(move, st, givesCheck);
|
pos.do_move(move, st, givesCheck);
|
||||||
|
|
||||||
// Step 15. Reduced depth search (LMR, ~200 Elo). If the move fails high it will be
|
// Step 16. Reduced depth search (LMR, ~200 Elo). If the move fails high it will be
|
||||||
// re-searched at full depth.
|
// re-searched at full depth.
|
||||||
if ( depth >= 3
|
if ( depth >= 3
|
||||||
&& moveCount > 1 + 2 * rootNode
|
&& moveCount > 1 + 2 * rootNode
|
||||||
|
@ -1266,7 +1282,7 @@ moves_loop: // When in check, search starts from here
|
||||||
didLMR = false;
|
didLMR = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 16. Full depth search when LMR is skipped or fails high
|
// Step 17. Full depth search when LMR is skipped or fails high
|
||||||
if (doFullDepthSearch)
|
if (doFullDepthSearch)
|
||||||
{
|
{
|
||||||
value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, newDepth, !cutNode);
|
value = -search<NonPV>(pos, ss+1, -(alpha+1), -alpha, newDepth, !cutNode);
|
||||||
|
@ -1293,12 +1309,12 @@ moves_loop: // When in check, search starts from here
|
||||||
std::min(maxNextDepth, newDepth), false);
|
std::min(maxNextDepth, newDepth), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 17. Undo move
|
// Step 18. Undo move
|
||||||
pos.undo_move(move);
|
pos.undo_move(move);
|
||||||
|
|
||||||
assert(value > -VALUE_INFINITE && value < VALUE_INFINITE);
|
assert(value > -VALUE_INFINITE && value < VALUE_INFINITE);
|
||||||
|
|
||||||
// Step 18. Check for a new best move
|
// Step 19. Check for a new best move
|
||||||
// Finished searching the move. If a stop occurred, the return value of
|
// Finished searching the move. If a stop occurred, the return value of
|
||||||
// the search cannot be trusted, and we return immediately without
|
// the search cannot be trusted, and we return immediately without
|
||||||
// updating best move, PV and TT.
|
// updating best move, PV and TT.
|
||||||
|
@ -1375,7 +1391,7 @@ moves_loop: // When in check, search starts from here
|
||||||
return VALUE_DRAW;
|
return VALUE_DRAW;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Step 19. Check for mate and stalemate
|
// Step 20. Check for mate and stalemate
|
||||||
// All legal moves have been searched and if there are no legal moves, it
|
// All legal moves have been searched and if there are no legal moves, it
|
||||||
// must be a mate or a stalemate. If we are in a singular extension search then
|
// must be a mate or a stalemate. If we are in a singular extension search then
|
||||||
// return a fail low score.
|
// return a fail low score.
|
||||||
|
|
Loading…
Add table
Reference in a new issue