From 9e995e7c39a83ae9b5ba86f3346e0281744bf773 Mon Sep 17 00:00:00 2001 From: Scott Gasch Date: Sat, 5 Sep 2026 21:52:40 -0700 Subject: King-safety recalibration, lazy-eval material floor, eval hot-path trimming Recalibrate iKingSwingP90 against the bitboard-rewritten CountKingSafetyDefects (~1.28B samples via new CALIBRATE_POSITIONAL/ CALIBRATE_BASE_MARGIN/CALIBRATE_MARGIN_SAFETY diagnostic build flags, board_representation/EVAL.md section 9). Add LAZY_EVAL_MIN_MATERIAL: measured the regular lazy exit's real swing exceeding its own assumed margin 20.6% of the time in near-bare-king endgames (vs <=0.36% elsewhere) -- skip lazy eval entirely below that material floor. Double the stale search.c/searchsup.c CountKingSafetyDefects extension thresholds as a stopgap pending their own recalibration. Eval hot-path trimming (measured via EVAL_TIME, ~1759 -> ~1386 avg cycles/eval on a representative middlegame position): - Pull _GetFileStormDefects out of EstimatePositionalScore's hot path (cost more than the "cheap cached lookup" it was assumed to be, running on ~90% of all Eval() calls). - Add pos->bbOccupiedSide[2], incrementally maintained alongside bbOccupied, so _BuildFriendlySideBB is a field read instead of a 6-term OR. - Switch CoorFromBitBoardRank8ToRank1/Rank1ToRank8 to the existing static-inline FastFirstBit/FastLastBit (same bsf/bsr instruction, no call/ret overhead). - Defer EvalPasserRaces' uRacerDist/fDontCountMeOut past its no-passer early return. - Remove the mailbox-era "max mobility in a row" term from _EvalBishop/_EvalRook (no bitboard-mobility equivalent need for it). - Simplify _EvalBishopPairs and rook file-openness/passer bonuses to flat DNA-tunable constants instead of distance/pawn-count-scaled tables, rook file-openness now a branchless bitboard-indexed lookup. - Remove pos->cPiece (write-only, no reader anywhere). - Collapse WHITE/BLACK mirror-branches (castle-rights block, rook-trapped-in-corner) to color-indexed constants. - Close the PAWN_BIT..KING_BIT gap (bits 7-3 -> bits 4-0), removing the bvPattern >>= 3 before its KING_COUNTER_BY_ATTACK_PATTERN lookup. This also fixes a real bug introduced earlier this session when _WhoControlsSquareFast was converted to read these constants directly: g_SwapTable is only [32][32], but the old bit values (up to 0xF8) indexed far out of bounds on any attacked square -- data.c's InitializeSwapTable was always built assuming the bits 0-4 range this change now actually produces. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01XxmVi2sTMwpPp4i6WYFjan --- src/root.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'src/root.c') diff --git a/src/root.c b/src/root.c index 0ab42f7..d7113c0 100755 --- a/src/root.c +++ b/src/root.c @@ -460,6 +460,19 @@ Return value: ASSERT(d); n = (double)(ctx->sCounters.pawnhash.u64Hits); Trace("Pawn hash hitrate: %5.3f percent.\n", (n/d) * 100.0); + // EXPERIMENTAL, measurement-only -- see eval.c's Eval() / + // rgKingSafetyHashProbe. + d = (double)(ctx->sCounters.kingsafetyhash.u64Probes) + 1; + ASSERT(d); + n = (double)(ctx->sCounters.kingsafetyhash.u64Hits); + Trace("[EXPERIMENTAL] King safety hash: %5.3f%% hitrate, " + "avg %.1f cyc hit / %.1f cyc miss (%" COMPILER_LONGLONG_UNSIGNED_FORMAT + " probes)\n", + (n/d) * 100.0, + (n > 0 ? (double)ctx->sCounters.kingsafetyhash.u64CyclesHit / n : 0.0), + ((d - 1 - n) > 0 ? + (double)ctx->sCounters.kingsafetyhash.u64CyclesMiss / (d - 1 - n) : 0.0), + ctx->sCounters.kingsafetyhash.u64Probes); n = (double)(ctx->sCounters.tree.u64NullMoveSuccess); d = (double)(ctx->sCounters.tree.u64NullMoves) + 1; ASSERT(d); @@ -614,6 +627,22 @@ Return value: Trace(" attack-table pop: %5.1f%% unaccounted: %5.1f%%\n", (u64Total ? (100.0 * (double)u64AttackPop / (double)u64Total) : 0.0), (u64Total ? (100.0 * (double)u64Unaccounted / (double)u64Total) : 0.0)); + { + UINT64 u64LazyDecision = ctx->sCounters.tree.u64CyclesEvalLazyDecision; + UINT64 u64CKSD = ctx->sCounters.tree.u64CyclesEvalCountKingSafetyDefects; + UINT64 u64Storm = ctx->sCounters.tree.u64CyclesEvalFileStormDefects; + UINT64 u64PreLazyRest = (u64PreLazyOther >= u64LazyDecision) ? + (u64PreLazyOther - u64LazyDecision) : 0; + Trace(" -- of which, pre-lazy breakdown --\n"); + Trace(" material/passers/badtrades/bishoppairs: %5.1f%%\n", + (u64Total ? (100.0 * (double)u64PreLazyRest / (double)u64Total) : 0.0)); + Trace(" lazy gate + EstimatePositionalScore: %5.1f%% " + "(of which CountKingSafetyDefects: %5.1f%%, " + "_GetFileStormDefects: %5.1f%%)\n", + (u64Total ? (100.0 * (double)u64LazyDecision / (double)u64Total) : 0.0), + (u64Total ? (100.0 * (double)u64CKSD / (double)u64Total) : 0.0), + (u64Total ? (100.0 * (double)u64Storm / (double)u64Total) : 0.0)); + } { UINT64 u64PHits = ctx->sCounters.tree.u64CountEvalPawnsHit; UINT64 u64PMisses = ctx->sCounters.tree.u64CountEvalPawnsMiss; -- cgit v1.3