summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorScott Gasch <[email protected]>2026-08-28 20:41:48 -0700
committerScott Gasch <[email protected]>2026-08-28 20:41:48 -0700
commit1509b3e593258690cbe3eee761a54f105111fc72 (patch)
tree9c8d87425b2004952a7aa31bc89ec1112cff4f9f /src
parent74f91d7379d8055678dd5c58e7223a228d8a03b0 (diff)
Rewire GetMoveFailHighPercentage: index by (cFrom, cTo, pMoved) instead
of (cFrom, cTo, color), and expose sample size. MOVE_TO_INDEX (used elsewhere for the counter-move table) folds any two moves with the same from/to/color into one fail-high bucket -- e.g. a king shuffle and a queen sac to the same square/color shared a slot. New MOVE_TO_FH_INDEX uses the low 20 bits of mv.uMove (cFrom+cTo+pMoved), which already encodes color in pMoved's low bit, so this is strictly more granular for free. Table grown 0x20000 -> 0x100000 entries to match. Also adds an optional ULONG *puAttempts out-param so future callers can weight by sample confidence instead of trusting a percentage computed from as few as one observation. GetLMRReduction (proto-LMR, live at HEAD) is the only real consumer right now; verified against head_reference at sd10 across ecm_ringers/ecm_confident_quick/ecm_hard_quick: net +2 solves (88 vs 87 on confident_quick, 18 vs 17 on hard_quick), node counts flat within noise (-1.5%/+1.4%/+0.5%).
Diffstat (limited to 'src')
-rwxr-xr-xsrc/chess.h2
-rwxr-xr-xsrc/dynamic.c24
-rw-r--r--src/searchsup.c2
3 files changed, 20 insertions, 8 deletions
diff --git a/src/chess.h b/src/chess.h
index 3a78b2b..9722414 100755
--- a/src/chess.h
+++ b/src/chess.h
@@ -2782,7 +2782,7 @@ TestBitboards(void);
extern ULONG g_HistoryCounters[14][128];
ULONG
-GetMoveFailHighPercentage(MOVE mv);
+GetMoveFailHighPercentage(MOVE mv, ULONG *puAttempts);
void
UpdateDynamicMoveOrdering(SEARCHER_THREAD_CONTEXT *ctx,
diff --git a/src/dynamic.c b/src/dynamic.c
index 33a673c..c6e86e3 100755
--- a/src/dynamic.c
+++ b/src/dynamic.c
@@ -44,7 +44,14 @@ extern double log(double);
ULONG g_HistoryCounters[14][128];
SCORE g_iLMRQuietReduction[MAX_PLY_PER_SEARCH + 1][LMR_TABLE_MAX_MOVES + 1];
-#define FH_STATS_TABLE_SIZE (0x20000)
+
+// Keyed by (cFrom, cTo, pMoved) -- the low 20 bits of mv.uMove -- rather
+// than MOVE_TO_INDEX's (cFrom, cTo, color) so that e.g. a king shuffle
+// and a queen sac to the same square/color aren't folded into the same
+// fail-high bucket. pMoved's low bit is already the color, so this
+// subsumes MOVE_TO_INDEX's color term for free.
+#define MOVE_TO_FH_INDEX(mv) ((mv).uMove & 0xFFFFF)
+#define FH_STATS_TABLE_SIZE (0x100000)
typedef struct _FH_STATS
{
@@ -197,7 +204,7 @@ Return value:
**/
{
- ULONG u = MOVE_TO_INDEX(mv);
+ ULONG u = MOVE_TO_FH_INDEX(mv);
ULONG v = g_FailHighs[u].uWholeThing;
ASSERT(DYN_IS_LOCKED);
@@ -233,7 +240,7 @@ Return value:
**/
{
- ULONG u = MOVE_TO_INDEX(mv);
+ ULONG u = MOVE_TO_FH_INDEX(mv);
ASSERT(DYN_IS_LOCKED);
if (g_FailHighs[u].u16Attempts == 0xFFFF)
@@ -827,8 +834,8 @@ Return value:
-ULONG
-GetMoveFailHighPercentage(IN MOVE mv)
+ULONG
+GetMoveFailHighPercentage(IN MOVE mv, OUT ULONG *puAttempts)
/**
Routine description:
@@ -839,6 +846,10 @@ Routine description:
Parameters:
MOVE mv
+ ULONG *puAttempts : optional (may be NULL) -- receives the number of
+ observations the percentage is based on, so callers can weight
+ by sample confidence instead of trusting a percentage computed
+ from as few as one attempt.
Return value:
@@ -846,11 +857,12 @@ Return value:
**/
{
- ULONG u = MOVE_TO_INDEX(mv);
+ ULONG u = MOVE_TO_FH_INDEX(mv);
ULONG n, d;
n = g_FailHighs[u].u16FailHighs;
d = g_FailHighs[u].u16Attempts;
+ if (puAttempts) *puAttempts = d;
if (d == 0)
{
return(0);
diff --git a/src/searchsup.c b/src/searchsup.c
index b532d9a..5673bbe 100644
--- a/src/searchsup.c
+++ b/src/searchsup.c
@@ -227,7 +227,7 @@ Return value:
((ctx->uPly < 3) ||
(!IS_SAME_MOVE(mv, ctx->mvKiller[ctx->uPly-3][0]) &&
!IS_SAME_MOVE(mv, ctx->mvKiller[ctx->uPly-3][1]))) &&
- (GetMoveFailHighPercentage(mv) <= 10))
+ (GetMoveFailHighPercentage(mv, NULL) <= 10))
{
ASSERT(!InCheck(&ctx->sPosition, ctx->sPosition.uToMove));
return(-ONE_PLY);