summaryrefslogtreecommitdiff
path: root/src/chess.h
diff options
context:
space:
mode:
authorScott Gasch <[email protected]>2026-09-13 23:18:07 -0700
committerScott Gasch <[email protected]>2026-09-13 23:18:07 -0700
commit4ff9170fd96e3da049c747bf5215e908a94ff145 (patch)
tree6c8e6f846b42518d84357bb3b83014feddc83202 /src/chess.h
parent78d1889fe38db1fd45b58509c8b3bd535ce691b7 (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-xsrc/chess.h67
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;