summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Gasch <[email protected]>2026-10-14 11:16:06 -0700
committerScott Gasch <[email protected]>2026-10-14 11:16:06 -0700
commit3845a082df2fd0d1bd059dd4c22c922067be826a (patch)
tree01f7059b7d1d7e7f0495a281512a6ac1610a280b
parent3d54c2cc82366040f00d5901f80dbe4e9d7bfe10 (diff)
Remove dead EFP references left over from its removal
EFP (extended futility pruning) was removed from Search()'s move loop in favor of LMP's joint FH% table, but several comments, a dead counter (u64EFPPruned, never incremented anywhere), and two unused defines (EFP_FH_MIN_SAMPLES/EFP_FH_PRUNE_THRESHOLD_PCT_THOUSANDTHS) were left behind claiming EFP still gates something. Clean these up: - Delete u64EFPPruned (COUNTERS and g_Options) and its dead reader/writer in root.c. - Delete the two unused EFP_FH_* defines in search.c, and the stale fAnyMoveEFPPruned comment describing a branch that no longer skips a store. - Fix dangling prose references to EFP in generate.c, chess.h, searchsup.c, and testsearch.c that describe present-tense behavior EFP no longer participates in, preserving the historical rationale where it's still relevant (e.g. why EstimateHangingMaterialCp can return a negative value). Deliberately left alone (flagged for a separate decision, not a clear delete): script.c's still-live JOINT_EXTRA_VERIFY calibration labels ("EFP tier1/tier2"), search.c's _PostReduceDepthBucketEfpAligned (same live mechanism, name only), searchsup.c's LMP_BASE_MOVENUM/ LMP_PER_PLY_MOVENUM dead macros (kept pending a real floor/ceiling decision), and PLY_INFO.iPositional[2] (now write-only, but removing it touches Eval()'s call signature everywhere). Comment/dead-code only, no logic touched. Co-Authored-By: Claude Sonnet 5 <[email protected]>
-rwxr-xr-xsrc/chess.h15
-rw-r--r--src/generate.c2
-rw-r--r--src/root.c6
-rw-r--r--src/search.c15
-rw-r--r--src/searchsup.c24
-rw-r--r--src/testsearch.c4
6 files changed, 24 insertions, 42 deletions
diff --git a/src/chess.h b/src/chess.h
index 94c9db4..36b90e3 100755
--- a/src/chess.h
+++ b/src/chess.h
@@ -1268,10 +1268,6 @@ typedef struct _COUNTERS
// leftover pool near the leaves. Counts every move this was
// applied to.
UINT64 u64LMPPruned;
- // 2026-10-05: extended futility pruning (EFP, search.c) -- same
- // shape as u64LMPPruned above, for the other overt-skip (not
- // reduction) mechanism in the move loop.
- UINT64 u64EFPPruned;
// 2026-10-05: null-move R-factor breakdown -- which whole-ply R
// SelectNullmoveRFactor chose, and how often the null-move
// search at that R actually failed high. Indexed by R/ONE_PLY,
@@ -1709,9 +1705,11 @@ typedef struct _PLY_INFO
// -- e.g. a cleaner cross-ply "improving" signal that corrects for
// a tier switch (super-lazy vs full) between the two Eval() calls
// being compared, instead of just diffing raw iEval values. Not
- // yet consumed that way anywhere; currently only the search.c EFP
- // gate (VALUE_KNIGHT/VALUE_ROOK margins) reads this, for the
- // node-it-was-computed-at only.
+ // yet consumed that way anywhere; its one reader (search.c's EFP
+ // gate, VALUE_KNIGHT/VALUE_ROOK margins) was removed along with
+ // EFP, so this is currently write-only -- flagged, not deleted,
+ // since removing it means touching Eval()'s piPositional parameter
+ // at every call site, a bigger change than this cleanup pass.
SCORE iPositional[2];
INT iExtensionAmount;
FLAG fInCheck;
@@ -2077,7 +2075,6 @@ typedef struct _GAME_OPTIONS
UINT64 u64JointExtraTries[JOINT_EXTRA_TIER_COUNT];
UINT64 u64JointExtraResearch[JOINT_EXTRA_TIER_COUNT];
UINT64 u64LMPPruned;
- UINT64 u64EFPPruned;
UINT64 u64NullMoveTriesByR[NULL_R_BUCKETS];
UINT64 u64NullMoveSuccessByR[NULL_R_BUCKETS];
#ifdef PRUNE_VERIFY
@@ -2953,7 +2950,7 @@ TestMakeUnmakeMove(void);
// Countermove-match tier bonus, placed above GOOD_MOVE (see
// generate.c's _ScoreAllMoves quiet-move branch) so a *sufficiently
// evidenced* match (see COUNTERMOVE_EVIDENCE_THRESHOLD) escapes
-// "leftover" classification -- and the fIsLeftoverMove-gated EFP check --
+// "leftover" classification -- and the fIsLeftoverMove-gated LMP check --
// entirely, becoming its own tier alongside killers. Conservatively
// placed below both ply-2 killer slots (FOURTH_KILLER/THIRD_KILLER):
// the contested-node A/B harness never found clean evidence a
diff --git a/src/generate.c b/src/generate.c
index d202384..569face 100644
--- a/src/generate.c
+++ b/src/generate.c
@@ -4655,7 +4655,7 @@ Routine description:
comments for why the promotion is evidence-gated rather than
automatic on a bare match.
6. GOOD_MOVE boundary. Below this, "leftover" (see search.c's
- fIsLeftoverMove) -- eligible for EFP pruning, but every leftover
+ fIsLeftoverMove) -- eligible for LMP pruning, but every leftover
is still fully ranked via SelectBestWithHistory (movesup.c); the
old NumLeftoverMovesToSelect depth-indexed selection budget was
retired once evidence showed the leftover pool has real,
diff --git a/src/root.c b/src/root.c
index f95bc2f..3ec1a9d 100644
--- a/src/root.c
+++ b/src/root.c
@@ -469,9 +469,8 @@ Return value:
Trace("Null move cutoff rate: %5.3f percent.\n",
((n / d) * 100.0));
#ifdef PERF_COUNTERS
- Trace("Overt move skips: LMP=%llu EFP=%llu moves.\n",
- ctx->sCounters.tree.u64LMPPruned,
- ctx->sCounters.tree.u64EFPPruned);
+ Trace("Overt move skips: LMP=%llu moves.\n",
+ ctx->sCounters.tree.u64LMPPruned);
{
ULONG uR;
UINT64 u64TotalTries = 0;
@@ -1594,7 +1593,6 @@ Return value:
memcpy(g_Options.u64JointExtraResearch, ctx->sCounters.tree.u64JointExtraResearch,
sizeof(g_Options.u64JointExtraResearch));
g_Options.u64LMPPruned = ctx->sCounters.tree.u64LMPPruned;
- g_Options.u64EFPPruned = ctx->sCounters.tree.u64EFPPruned;
memcpy(g_Options.u64NullMoveTriesByR, ctx->sCounters.tree.u64NullMoveTriesByR,
sizeof(g_Options.u64NullMoveTriesByR));
memcpy(g_Options.u64NullMoveSuccessByR, ctx->sCounters.tree.u64NullMoveSuccessByR,
diff --git a/src/search.c b/src/search.c
index 3abb44b..d0d67b9 100644
--- a/src/search.c
+++ b/src/search.c
@@ -75,15 +75,6 @@ extern FLAG g_fCanSplit[MAX_PLY_PER_SEARCH];
#define PREPARE_TO_TRY_MOVES (2)
#define TRY_GENERATED_MOVES (3)
-// EFP's fail-high-history exemption: below EFP_FH_MIN_SAMPLES
-// observations, GetMoveFailHighPctThousandths's result isn't trusted
-// enough to override the static-eval-based decision either way.
-// THOUSANDTHS, not whole percent, since 2026-10-02's rename -- 100
-// thousandths == 10%, unchanged in effect from the old whole-percent
-// EFP_FH_PRUNE_THRESHOLD of 10.
-#define EFP_FH_MIN_SAMPLES (5)
-#define EFP_FH_PRUNE_THRESHOLD_PCT_THOUSANDTHS (10000) // 10%
-
// 2026-10-13: "skip trying null-move at all" on the iEval <= iAlpha
// side (alpha-side table, EV-neutral -- the real move loop still runs
// and finds the correct score either way; we only forgo the cheap
@@ -1848,12 +1839,6 @@ Search(IN SEARCHER_THREAD_CONTEXT *ctx,
// --Ed Schroder
StoreUpperBound(pos, iBestScore, uDepth, fThreat);
}
- // else: fail-low (iAlpha == iInitialAlpha) AND fAnyMoveEFPPruned --
- // no sound bound in either direction to store (the skipped move
- // could have raised the true value above iBestScore, so it's not a
- // valid upper bound; there's no mvBest to offer as a lower bound
- // either, since nothing beat alpha). Store nothing rather than
- // cache an unsound result.
end:
ASSERT(IS_VALID_SCORE(iBeta));
diff --git a/src/searchsup.c b/src/searchsup.c
index a048d39..d94dbb4 100644
--- a/src/searchsup.c
+++ b/src/searchsup.c
@@ -281,9 +281,11 @@ Return value:
sign in that case rather than clamping it away -- IID's shallow
search genuinely knows more than a static material exchange
does, and a caller folding this value directly into a margin
- calculation (EFP, search.c) WANTS "this move turned out to
- actually be good" to look like the opposite of "hung", not like
- "hung = 0" -- see search.c's EFP comment. Callers that need a
+ calculation WANTS "this move turned out to actually be good" to
+ look like the opposite of "hung", not like "hung = 0" (this
+ historically mattered for EFP's margin check, search.c, now
+ removed -- the reasoning is preserved here in case a future
+ direct-margin consumer reappears). Callers that need a
true cp-loss-or-zero reading instead (the "dumb" axis feeding
the joint FH table) must go through HangCpBucket, which clamps
exactly this case to bucket 0 rather than asserting it away.
@@ -795,8 +797,8 @@ Routine description:
2026-10-04: hoisted out of Search()'s move loop (search.c), where
this had grown into an inline block setting fPruneReduceEligible
plus two more exemption checks (killer-adjacency, countermove
- match) immediately below it -- EFP, LMP and LMR all gate on the
- combined result. Pulled into one function so the "is this move
+ match) immediately below it -- EFP (since removed), LMP and LMR all
+ gated on the combined result. Pulled into one function so the "is this move
even a candidate for pruning/reduction" question has a single,
named answer instead of three co-located but separately-maintained
checks.
@@ -860,7 +862,7 @@ Parameters:
Return value:
FLAG : TRUE iff mv is eligible to be considered for pruning or
- reduction (EFP/LMP/LMR still each apply their own further checks
+ reduction (LMP/LMR still each apply their own further checks
on top of this).
**/
@@ -1081,7 +1083,7 @@ Routine description:
for a move either of those would have exempted. Takes the FH-table
lookups (uFHAttempts, uFHPctThousandths, uPredictedFH) as inputs
rather than recomputing them -- search.c's move loop already looks
- them up once per move for LMP/LMR/EFP to share.
+ them up once per move for LMP/LMR to share.
2026-10-13: corrected from an earlier version of this comment that
claimed four checks including a move-number floor and a depth
@@ -1141,8 +1143,8 @@ Return value:
FLAG : TRUE iff mv should be pruned outright (skipped, not merely
reduced). Live, not audit-only: search.c's move loop actually
- `continue`s past mv when this returns TRUE (the same final check
- that consumes fThisMoveEFPPruned), after INCrementing
+ `continue`s past mv when this returns TRUE (the check that
+ consumes fThisMoveLMPPruned), after INCrementing
u64LMPPruned for the script-summary "late-move pruning (overt
skip, not reduction)" line under PERF_COUNTERS.
@@ -1325,8 +1327,8 @@ ComputeMoveScore(IN SEARCHER_THREAD_CONTEXT *ctx,
ASSERT(IS_SAME_MOVE(mv, ctx->sMoveStack.mvf[uMoveNum].mv));
ASSERT(ctx->uPly > 0);
- // Every current caller (search.c's EFP check, and
- // ComputeMoveExtension's two ComputeMoveScore() call sites) only
+ // Every current caller (EstimateHangingMaterialCp above, and
+ // ComputeMoveExtension's own call site below) only
// reaches here after MakeMove(ctx, mv) has already succeeded, so
// ctx->uPly is always the *child's* ply here -- uMoveNum indexes
// the parent's move list, i.e. ctx->uPly - 1, not ctx->uPly. That's
diff --git a/src/testsearch.c b/src/testsearch.c
index afd2733..8c67819 100644
--- a/src/testsearch.c
+++ b/src/testsearch.c
@@ -154,7 +154,7 @@ TestSearch(void)
// MaintainDynamicMoveOrdering does) still leaves real accumulated
// evidence behind. Search is not a pure function of (position, depth)
// in the presence of that evidence: a move's own GetMoveFailHighPct
-// Thousandths reading (feeding GetLMRReduction/ShouldLatePrune/EFP)
+// Thousandths reading (feeding GetLMRReduction/ShouldLatePrune)
// depends on it, and it accumulates LIVE during a search as sibling/
// cousin nodes are visited -- so two calls that visit nodes in a
// different order (which a warm vs. cold hash table, by design, makes
@@ -198,7 +198,7 @@ _FixedDepthSearchScore(SEARCHER_THREAD_CONTEXT *ctx,
// *transparent* (changes performance, never the answer) and that this
// is checkable by comparing scores across searches that visit
// different subsets of the tree -- does not hold in this engine and
-// cannot be patched into holding. EFP/LMR pruning decisions depend on
+// cannot be patched into holding. LMP/LMR pruning decisions depend on
// GLOBAL, LIVE-ACCUMULATING evidence tables (g_HistoryCounters,
// g_ContinuationHistory, g_FailHighs) that update as a side effect of
// actually VISITING a node, not as a side effect of that node's final