From 3051a0828b17268183916b12671ce3819f66141a Mon Sep 17 00:00:00 2001 From: Nick Date: Sat, 10 Oct 2026 23:36:07 -0500 Subject: [PATCH] Add guarded qsearch delta pruning --- src/search.cpp | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/search.cpp b/src/search.cpp index f491d7f..e861304 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -17,6 +17,7 @@ namespace ironphoenix { namespace { constexpr int LMP_HISTORY_THRESHOLD = 2'000; + constexpr int DELTA_MARGIN = 200; IRONPHOENIX_FORCE_INLINE Bitboard teamOccupancy(const Position& pos, Color c) noexcept { const Color partner = static_cast(static_cast(c) ^ 2u); @@ -281,10 +282,12 @@ namespace ironphoenix { } int bestScore = -INF; + int staticEval = -INF; Move bestMove{}; if (!inCheckNode) { - bestScore = evaluate(pos); + staticEval = evaluate(pos); + bestScore = staticEval; if (bestScore >= beta) { tt_.store(pos.key(), 0, bestScore, TTBound::Lower, Move{}, pvNode, ply); @@ -319,6 +322,31 @@ namespace ironphoenix { const bool terminalKingCapture = isTerminalKingCapture(pos, move); const bool givesCheckMove = !terminalKingCapture && pos.givesCheck(move); + const bool normalWindow = alpha > -MATE_THRESHOLD && beta < MATE_THRESHOLD; + + // Delta pruning: in quiet qsearch positions, skip a non-checking + // capture when even the captured material plus a safety margin cannot + // raise alpha. Promotions and terminal king captures are never pruned. + // Keep PV qsearch exact and avoid all mate-window applications. + if (!pvNode + && !inCheckNode + && normalWindow + && move.isCapture() + && !move.isPromotion() + && !terminalKingCapture + && !givesCheckMove) { + Piece captured = move.captured(); + if (!isPiece(captured)) { + const Square capSq = pos.capturedSquare(move, us); + if (capSq != SQ_NONE) + captured = pos.pieceAt(capSq); + } + + if (isPiece(captured) + && staticEval + pieceValue(captured) + DELTA_MARGIN <= alpha) { + continue; + } + } int score = -INF; bool legal = true;