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/command.c | |
| 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/command.c')
| -rw-r--r-- | src/command.c | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/src/command.c b/src/command.c index e6bf9fc..1696690 100644 --- a/src/command.c +++ b/src/command.c @@ -547,6 +547,107 @@ Return value: } +#ifdef KING_DEFECT_DUMP +COMMAND(EvalKingDumpCommand) +/** + +Routine description: + + This function implements the 'evalkingdump' engine command, only + built under KING_DEFECT_DUMP. Runs a full static eval (same + persistent-context pattern as EvalCommand) then prints one + space-separated key=value line per side with _EvalKing's raw, + per-defect breakdown (chess.h's KING_DEFECT_DUMP_INFO) instead of + the single collapsed score -- feeds an offline regression against + real mate outcomes. See CLAUDE.md's king-safety discussion. + + Usage: + + evalkingdump + +Parameters: + + The COMMAND macro hides four arguments from the input parser: + + CHAR *szInput : the full line of input + ULONG argc : number of argument chunks + CHAR *argv[] : array of ptrs to each argument chunk + POSITION *pos : a POSITION pointer to operate on + +Return value: + + void + +**/ +{ + static SEARCHER_THREAD_CONTEXT *ctx = NULL; + static ULONG uLastSeenDnaGeneration = (ULONG)-1; + static const CHAR *szPieceName[KING_RING_NUM_PIECE_TYPES] = + { "pawn", "minor", "rook", "queen" }; + ULONG uColor; + ULONG uSlot, uPieceType; + KING_DEFECT_DUMP_INFO *p; + + if (NULL == ctx) + { + ctx = SystemAllocateMemory(sizeof(SEARCHER_THREAD_CONTEXT)); + if (NULL == ctx) + { + Trace("Out of memory.\n"); + return; + } + InitializeSearcherContext(pos, ctx); + uLastSeenDnaGeneration = g_uDnaGeneration; + } + else if (uLastSeenDnaGeneration != g_uDnaGeneration) + { + InitializeSearcherContext(pos, ctx); + uLastSeenDnaGeneration = g_uDnaGeneration; + } + else + { + ReInitializeSearcherContext(pos, ctx); + } + (void)Eval(ctx, -INFINITY, +INFINITY, NULL); + + for (uColor = 0; uColor < 2; uColor++) + { + p = &ctx->sKingDefectDump[uColor]; + Trace("KINGDEFECTDUMP color=%s", COLOR_NAME(uColor)); + for (uSlot = 0; uSlot < KING_RING_NUM_SLOTS; uSlot++) + { + if (!p->fOnBoard[uSlot]) + { + Trace(" sq%u_offboard=1", uSlot); + continue; + } + for (uPieceType = 0; uPieceType < KING_RING_NUM_PIECE_TYPES; uPieceType++) + { + Trace(" sq%u_atk_%s=%u", + uSlot, szPieceName[uPieceType], + p->fAttackedByPieceType[uSlot][uPieceType]); + } + Trace(" sq%u_undef=%u sq%u_def=%u sq%u_xray=%u sq%u_flight=%u", + uSlot, p->fAttackedUndefended[uSlot], + uSlot, p->fAttackedDefended[uSlot], + uSlot, p->fXrayedUnattacked[uSlot], + uSlot, p->fEmptyFlight[uSlot]); + } + Trace(" filestorm=%u filestormopenfile=%u filestormpawn=%u " + "queenproximity=%u initloc=%u countertotal=%u " + "safetyvalue=%u attackerarmyscaler=%u castled=%u minorsathome=%u " + "misscastleshort=%u misscastlelong=%u\n", + p->uFileStormDefects, p->uFileStormOpenFile, p->uFileStormStormingPawn, + p->uQueenNearKing, + p->uInitialCounterByLocation, p->uCounterTotal, + p->uSafetyTableValue, p->uAttackerArmyScaler, + p->fCastled, p->uMinorsAtHome, + p->fMissingCastleShort, p->fMissingCastleLong); + } +} +#endif + + COMMAND(QSearchCommand) /** @@ -2454,6 +2555,14 @@ COMMAND_PARSER_ENTRY g_ParserTable[] = FALSE, FALSE, "Run a static eval" }, +#ifdef KING_DEFECT_DUMP + { "evalkingdump", + EvalKingDumpCommand, + FALSE, + FALSE, + FALSE, + "Dump _EvalKing's raw per-defect breakdown for both sides" }, +#endif { "evaldna", EvalDnaCommand, FALSE, |
