summaryrefslogtreecommitdiff
path: root/src/searchsup.c
diff options
context:
space:
mode:
authorScott Gasch <[email protected]>2026-08-25 14:03:46 -0700
committerScott Gasch <[email protected]>2026-08-25 14:03:46 -0700
commitba803fe406ee2470aa461578f530d292380ec241 (patch)
treec083e1f88e1e8c978084b34b9b315c3eec682e32 /src/searchsup.c
parent29d73f4dd59554a349aa8e86e5ea65f28c912ec9 (diff)
Add LMR with PV-adjacency guard (v7), verified against saved binary
Late Move Reductions using a depth x movecount table (Ethereal-style formula), gated off PV nodes and the ply directly below a PV node (PLY_INFO.fIsPVNode), with magnitude-aware re-search on fail-high. Verified node-for-node identical to the previously tested-good v7 binary on a canary position (sd 10) after reconstructing from a ZFS snapshot of search.c/root.c/split.c taken just before that binary was built. Co-Authored-By: Claude Sonnet 5 <[email protected]>
Diffstat (limited to 'src/searchsup.c')
-rw-r--r--src/searchsup.c62
1 files changed, 60 insertions, 2 deletions
diff --git a/src/searchsup.c b/src/searchsup.c
index 9e842d4..7af1a18 100644
--- a/src/searchsup.c
+++ b/src/searchsup.c
@@ -18,6 +18,7 @@ Revision History:
**/
+#include <math.h>
#include "chess.h"
extern SCORE g_iRootScore[2];
@@ -224,7 +225,8 @@ Return value:
ASSERT((uMoveNum > 0) || (uLegalMoves == 0));
if ((uRemainingDepth >= TWO_PLY) &&
(iBeta == (iAlpha + 1)) &&
- (uLegalMoves > 5) &&
+ (FALSE == ctx->sPlyInfo[ctx->uPly - 1].fIsPVNode) &&
+ (uLegalMoves > 3) &&
(0 == iExtend) &&
// (iRoughEval + ComputeMoveScore(ctx, mv, uMoveNum - 1) + 200 < iAlpha) &&
(!IS_ESCAPING_CHECK(mv)) &&
@@ -244,10 +246,66 @@ Return value:
}
+#define LMR_TABLE_MAX_DEPTH 32
+#define LMR_TABLE_MAX_MOVES 63
+
+static INT g_iLMRTable[LMR_TABLE_MAX_DEPTH + 1][LMR_TABLE_MAX_MOVES + 1];
+
+void
+InitializeLMRTable(void)
+{
+ ULONG d, m;
+ double r;
+
+ g_iLMRTable[0][0] = 0;
+ for (d = 0; d <= LMR_TABLE_MAX_DEPTH; d++)
+ {
+ for (m = 0; m <= LMR_TABLE_MAX_MOVES; m++)
+ {
+ if ((d < 1) || (m < 1))
+ {
+ g_iLMRTable[d][m] = 0;
+ continue;
+ }
+ r = 0.7844 + (log((double)d) * log((double)m) / 2.4696);
+ if (r < 0.0) r = 0.0;
+ g_iLMRTable[d][m] = (INT)((r * ONE_PLY) + 0.5);
+ }
+ }
+}
+
+
+INT
+ExtraReduction(IN ULONG uRemainingDepth,
+ IN ULONG uMoveNum,
+ IN ULONG uFailHighPct)
+{
+ INT iExtra;
+ ULONG d = uRemainingDepth / ONE_PLY;
+ ULONG m = uMoveNum;
+
+ if (d > LMR_TABLE_MAX_DEPTH) d = LMR_TABLE_MAX_DEPTH;
+ if (m > LMR_TABLE_MAX_MOVES) m = LMR_TABLE_MAX_MOVES;
+ iExtra = g_iLMRTable[d][m];
+
+ if (uFailHighPct == 0)
+ {
+ iExtra += QUARTER_PLY;
+ }
+
+ if ((INT)uRemainingDepth - ONE_PLY - iExtra < TWO_PLY)
+ {
+ iExtra = MAX((INT)uRemainingDepth - ONE_PLY - TWO_PLY, 0);
+ }
+ ASSERT(iExtra >= 0);
+ return(iExtra);
+}
+
+
SCORE
ComputeMoveScore(IN SEARCHER_THREAD_CONTEXT *ctx,
IN MOVE mv,
- IN ULONG uMoveNum)
+ IN ULONG uMoveNum)
{
SCORE iMoveScore = (PIECE_VALUE(mv.pCaptured) +
PIECE_VALUE(mv.pPromoted));