From 0fd0915e2d514528f60043a63c868e18349b1e71 Mon Sep 17 00:00:00 2001 From: Nick Date: Fri, 9 Oct 2026 13:06:35 -0500 Subject: [PATCH 1/3] Add history-aware Late Move Pruning --- src/search.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/search.cpp b/src/search.cpp index 393c9b7..c634e40 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -22,6 +22,9 @@ namespace ironphoenix { constexpr int SEE_PRUNE_MARGIN_PER_DEPTH = 80; constexpr int QSEARCH_SEE_THRESHOLD = -50; + constexpr int LMP_MAX_DEPTH = 4; + 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); @@ -444,6 +447,22 @@ namespace ironphoenix { const int mateWindow = !(alpha > -MATE_THRESHOLD && beta < MATE_THRESHOLD) && !terminalKingCapture; + // Late Move Pruning (LMP): at shallow 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. + if (!pvNode + && !inCheckNode + && depth <= LMP_MAX_DEPTH + && legalMoves >= 3 + depth * depth + && quiet + && move != ttMove + && !givesCheckMove + && !mateWindow + && lmrHistoryScore < LMP_HISTORY_THRESHOLD) { + continue; + } + if (!pvNode && !inCheckNode && depth <= SEE_PRUNE_MAX_DEPTH From ebc25aade81281a8c8395e0c49bc49675ec574b7 Mon Sep 17 00:00:00 2001 From: Nick Date: Fri, 9 Oct 2026 13:09:21 -0500 Subject: [PATCH 2/3] Remove LMP depth limit --- src/search.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index c634e40..ee7ac6c 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -22,7 +22,6 @@ namespace ironphoenix { constexpr int SEE_PRUNE_MARGIN_PER_DEPTH = 80; constexpr int QSEARCH_SEE_THRESHOLD = -50; - constexpr int LMP_MAX_DEPTH = 4; constexpr int LMP_HISTORY_THRESHOLD = 2'000; IRONPHOENIX_FORCE_INLINE Bitboard teamOccupancy(const Position& pos, Color c) noexcept { @@ -447,13 +446,12 @@ namespace ironphoenix { const int mateWindow = !(alpha > -MATE_THRESHOLD && beta < MATE_THRESHOLD) && !terminalKingCapture; - // Late Move Pruning (LMP): at shallow non-PV nodes, stop spending - // search effort on late quiet moves unless history says the move is + // 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. + // searches are never pruned here. This intentionally has no depth cap. if (!pvNode && !inCheckNode - && depth <= LMP_MAX_DEPTH && legalMoves >= 3 + depth * depth && quiet && move != ttMove From c62b8e598970879449ef785eff40ee590995e5fc Mon Sep 17 00:00:00 2001 From: Nick Date: Fri, 9 Oct 2026 16:11:59 -0500 Subject: [PATCH 3/3] Add Late Move Pruning (LMP) to features list --- README.md | 1 + 1 file changed, 1 insertion(+) 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