diff --git a/README.md b/README.md index 512ece1..60c67fc 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,7 @@ IronPhoenix includes a modern alpha-beta search stack designed specifically for - History-based move ordering - Static Exchange Evaluation (SEE) - Late Move Reductions (LMR) +- Late Move Pruning (LMP) - Search pruning and reductions - Iterative deepening - Principal variation reporting diff --git a/src/search.cpp b/src/search.cpp index c47792f..93ff16e 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -16,6 +16,8 @@ namespace ironphoenix { namespace { + constexpr int LMP_HISTORY_THRESHOLD = 2'000; + IRONPHOENIX_FORCE_INLINE Bitboard teamOccupancy(const Position& pos, Color c) noexcept { const Color partner = static_cast(static_cast(c) ^ 2u); return pos.occupancy(c) | pos.occupancy(partner); @@ -441,6 +443,21 @@ namespace ironphoenix { const int mateWindow = !(alpha > -MATE_THRESHOLD && beta < MATE_THRESHOLD) && !terminalKingCapture; + // Late Move Pruning (LMP): at non-PV nodes, stop spending search + // effort on late quiet moves unless history says the move is + // promising. Checks, TT moves, promotions/captures, and mate-window + // searches are never pruned here. This intentionally has no depth cap. + if (!pvNode + && !inCheckNode + && legalMoves >= 3 + depth * depth + && quiet + && move != ttMove + && !givesCheckMove + && !mateWindow + && lmrHistoryScore < LMP_HISTORY_THRESHOLD) { + continue; + } + if (!pvNode && !inCheckNode && depth <= tuning.seePruneMaxDepth