diff options
| author | Scott Gasch <[email protected]> | 2026-08-29 00:30:53 -0700 |
|---|---|---|
| committer | Scott Gasch <[email protected]> | 2026-08-29 00:30:53 -0700 |
| commit | 917bf1260ae217bdcbdbc11c2c37cdb5d3a8eae9 (patch) | |
| tree | 8013781f51e53eaf1fe3d4f45367e920d4c39786 /src/search.c | |
| parent | 366eebaf6b72fc6b56ea06a71f0276069a501dc7 (diff) | |
Switch to Crafty-style killer ordering; fix mvNullmoveRefutations type-mixing bug and add a quiet-refutation killer backfill.
Killer tiers now try both of this ply's own killers before either
ply-2-back one, matching Crafty's ordering. Two earlier attempts at
this same swap were reverted for regressing; this pass lands on top of
NumLeftoverMovesToSelect (more SelectBestWithHistory budget to reach
these lower-tier slots) and a real bug fix below, and beats interleaved
order head-to-head on solves, node count, and first-move beta cutoff
across the three curated suites.
The bug: mvNullmoveRefutations's empty-killer-slot backfill could only
ever contain a capturing move (TryNullmovePruning only wrote it inside
the capture-refutation branch), but IS_SAME_MOVE's mask includes the
pCaptured bits, so that backfilled value could never match a real
quiet candidate -- the backfill was silently dead code. Fixed by
recording genuinely quiet null-move refutations into a new, separate
mvNullmoveQuietRefutations array (kept separate so it can't clobber the
capture history mvNullmoveRefutations still needs for the
Botvinnik-Markoff same-piece-two-squares extension check) and
backfilling the regular killer table from that instead. The
check-evasion killer table intentionally does *not* get this backfill:
a null-move refutation can never legitimately be an escaping-check
move (null moves can't deliver check), so backfilling there risks
IS_SAME_MOVE cross-context false positives instead of the old
guaranteed-inert no-op.
Measured at sd10 across ecm_ringers/ecm_confident_quick/ecm_hard_quick
against head_reference (commit d11e973): 115/191 solves (vs. 116
baseline), 924.36M total nodes (vs. 933.23M), first-move beta cutoff
within 0.1-0.9 points of baseline on all three suites -- and clearly
better than the same fix under interleaved order (113/191 solves,
963.10M nodes), which loses to head_reference on every metric.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01EortUUkDVpsfrbqshBJYJg
Diffstat (limited to 'src/search.c')
| -rwxr-xr-x | src/search.c | 15 |
1 files changed, 7 insertions, 8 deletions
diff --git a/src/search.c b/src/search.c index b0bcafd..33cd09d 100755 --- a/src/search.c +++ b/src/search.c @@ -490,8 +490,8 @@ Search(IN SEARCHER_THREAD_CONTEXT *ctx, // mattering in practice. ASSERT(!uFutilityMargin); if ((FALSE == pi->fPvNode) && - (ctx->uPly >= 2) && (iOrigExtend == 0) && + (ctx->uPly >= 2) && (ctx->sPlyInfo[ctx->uPly - 2].iExtensionAmount <= 0)) { if ((uDepth > THREE_QUARTERS_PLY) && @@ -732,16 +732,16 @@ Search(IN SEARCHER_THREAD_CONTEXT *ctx, // this is the one thing that must never be true of a move // we skip outright. fThisMoveEFPPruned = FALSE; - if ((x != 0) && - (uLegalMoves > 1) && + if ((x != 0) && + (uLegalMoves > 1) && (uFutilityMargin) && (TRUE == fInLeftovers) && - (ComputeMoveScore(ctx, mv, (x - 1)) < uFutilityMargin) && (iExtend <= 0) && - (!IS_ESCAPING_CHECK(mv)) && + (!IS_ESCAPING_CHECK(mv)) && (!IS_CAPTURE_OR_PROMOTION(mv)) && - (!IS_CHECKING_MOVE(mv)) && - (!fThreat)) + (!IS_CHECKING_MOVE(mv)) && + (!fThreat) && + (ComputeMoveScore(ctx, mv, (x - 1)) < uFutilityMargin)) { ULONG uFHAttempts = 0; ULONG uFHPct = GetMoveFailHighPercentage(mv, &uFHAttempts); @@ -757,7 +757,6 @@ Search(IN SEARCHER_THREAD_CONTEXT *ctx, } if (TRUE == fThisMoveEFPPruned) { - ASSERT(!IS_CHECKING_MOVE(mv)); fAnyMoveEFPPruned = TRUE; UnmakeMove(ctx, mv); ASSERT(PositionsAreEquivalent(pos, &pi->sPosition)); |
