diff options
| author | Scott Gasch <[email protected]> | 2026-09-13 23:18:07 -0700 |
|---|---|---|
| committer | Scott Gasch <[email protected]> | 2026-09-13 23:18:07 -0700 |
| commit | 4ff9170fd96e3da049c747bf5215e908a94ff145 (patch) | |
| tree | 6c8e6f846b42518d84357bb3b83014feddc83202 /src/chess.h | |
| parent | 78d1889fe38db1fd45b58509c8b3bd535ce691b7 (diff) | |
Add king-safety mate-mining regression pipeline; retune file-storm/
queen-proximity king-safety weights and add a back-flight bonus from it.
Mines real human-game checkmates and matched sound-draw controls
(eval_tune/mine_king_mates.py, shard_mine.py, extract_king_features.py,
match_controls.py, train_king_safety_model.py), then fits a logistic
regression against _EvalKing's raw per-defect breakdown (engine-side
support: chess.h's KING_DEFECT_DUMP_INFO, eval.c's KING_DEFECT_DUMP
instrumentation, command.c's evalkingdump command, all gated behind the
KING_DEFECT_DUMP=1 build flag) to see which defects actually predict
getting mated. See eval_tune/king_safety_data/HANDOFF.md for the full
methodology and findings.
Two rounds of retuning landed from this data so far, both validated via
sd10 curated-suite comparison plus per-position Crafty corroboration
(tests/ECM.md) and gated self-play:
- KingFileDefects/KingStormingPawnDefects (_ComputeFileStormDefects)
bumped ~1.75-2x relative to the rest of the ring-scan defects -- the
regression's most dominant, most stable tier-1 predictors, previously
weighted the same as every other hand-picked defect.
- KING_QUEEN_PROXIMITY_DANGER rescaled from -8/count to -32/count, and
a new KING_BACK_FLIGHT_BONUS (+1/square) term added for empty,
unattacked ring squares on the side of the king away from the
attacker -- a real, non-collinear protective signal the current
EmptyUnattackedSquare table didn't credit at all. Both calibrated by
unstandardizing the regression's coefficients and anchoring against
KING_MISSING_ONE_CASTLE_OPTION's already-live -23 value (same
direct-EVAL_TERM unit family).
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01P9EDZVcqu6E2bNRm4zDrTf
Diffstat (limited to 'src/chess.h')
| -rwxr-xr-x | src/chess.h | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/src/chess.h b/src/chess.h index 2681701..df59626 100755 --- a/src/chess.h +++ b/src/chess.h @@ -1367,6 +1367,70 @@ typedef struct _KING_SAFETY_HASH_ENTRY } KING_SAFETY_HASH_ENTRY; +#ifdef KING_DEFECT_DUMP +// Ring-slot indexing matches KingSafetyDeltas' order in eval.c exactly +// (-17,-16,-15,-1,+1,+15,+16,+17): slots 0-7, no bucketing -- kept at +// full per-square resolution rather than collapsed into front/side/back, +// since the direct in-front square (delta +-16) and the two front- +// diagonal squares (+-15/+-17) are genuinely different attack geometries +// (e.g. a same-file rook vs. a diagonal bishop) that a bucket would +// conflate. Sample size (tens of thousands of mined positions) has no +// trouble supporting this many features. +#define KING_RING_NUM_SLOTS 8 + +#define KING_RING_PAWN 0 +#define KING_RING_MINOR 1 +#define KING_RING_ROOK 2 +#define KING_RING_QUEEN 3 +#define KING_RING_NUM_PIECE_TYPES 4 + +// Raw, per-defect, per-square breakdown of _EvalKing's ring-square scan, +// filled in (only under this build flag) instead of/alongside the normal +// collapse into one scalar uCounter -- feeds a per-defect regression +// against real mate outcomes instead of trusting the hand-picked weights +// already baked into KING_SAFETY_BY_COUNTER / KING_COUNTER_BY_ATTACK_PATTERN. +// See CLAUDE.md's king-safety discussion. +typedef struct _KING_DEFECT_DUMP_INFO +{ + // [slot][piece type]: 1 if this ring square is attacked or x-rayed by + // this piece type, same bits _EvalKing's own bvAttack/bvXray already + // compute per square -- just retained per-slot instead of OR'd + // together into one whole-ring bvPattern. + FLAG fAttackedByPieceType[KING_RING_NUM_SLOTS][KING_RING_NUM_PIECE_TYPES]; + // [slot]: off-board squares (near an edge/corner) leave all four FALSE. + FLAG fOnBoard[KING_RING_NUM_SLOTS]; + FLAG fAttackedUndefended[KING_RING_NUM_SLOTS]; + FLAG fAttackedDefended[KING_RING_NUM_SLOTS]; + FLAG fXrayedUnattacked[KING_RING_NUM_SLOTS]; + FLAG fEmptyFlight[KING_RING_NUM_SLOTS]; + ULONG uFileStormDefects; + // Split-out sub-components of uFileStormDefects, from two already- + // separate hand-picked tables (KingFileDefects / KingStormingPawnDefects) + // -- kept apart so a regression can weigh "open/half-open file near + // the king" independently from "how far an enemy pawn has advanced up + // that file", rather than only ever seeing their pre-summed total. + ULONG uFileStormOpenFile; + ULONG uFileStormStormingPawn; + ULONG uQueenNearKing; + ULONG uInitialCounterByLocation; + ULONG uCounterTotal; // final uCounter, pre-clamp + ULONG uSafetyTableValue; // KING_SAFETY_BY_COUNTER[MINU(uCounterTotal,41)] + // Attacker's (xColor's) army strength -- pos->uArmyScaler[xColor], + // the exact index REDUCED_MATERIAL_DOWN_SCALER itself uses to scale + // the final king-safety score. Captured so training can control for + // it directly (a defect pattern under a weak attacker converts to + // mate far less often than the identical pattern under a full + // attacking army, regardless of what the raw defect counts say) -- + // see CLAUDE.md's king-safety discussion. + ULONG uAttackerArmyScaler; + FLAG fCastled; + ULONG uMinorsAtHome; + FLAG fMissingCastleShort; + FLAG fMissingCastleLong; +} +KING_DEFECT_DUMP_INFO; +#endif + #define NUM_SPLIT_PTRS_IN_CONTEXT (8) // @@ -1450,6 +1514,9 @@ typedef struct _SEARCHER_THREAD_CONTEXT // rejected), so there's no risk of runaway nested diagnosis. FLAG fDiagUnprunedSubtree; #endif +#ifdef KING_DEFECT_DUMP + KING_DEFECT_DUMP_INFO sKingDefectDump[2]; // filled by _EvalKing, indexed by color +#endif CHAR szLastPV[SMALL_STRING_LEN_CHAR]; } SEARCHER_THREAD_CONTEXT; |
