summaryrefslogtreecommitdiff
path: root/src/command.c
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/command.c
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/command.c')
-rw-r--r--src/command.c109
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,