summaryrefslogtreecommitdiff
path: root/src/search.c
diff options
context:
space:
mode:
authorScott Gasch <[email protected]>2026-08-29 00:30:53 -0700
committerScott Gasch <[email protected]>2026-08-29 00:30:53 -0700
commit917bf1260ae217bdcbdbc11c2c37cdb5d3a8eae9 (patch)
tree8013781f51e53eaf1fe3d4f45367e920d4c39786 /src/search.c
parent366eebaf6b72fc6b56ea06a71f0276069a501dc7 (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-xsrc/search.c15
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));