summaryrefslogtreecommitdiff
path: root/src
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 /src
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]>
Diffstat (limited to 'src')
-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