summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/board_representation/MIGRATION.md26
-rwxr-xr-xsrc/command.c132
2 files changed, 150 insertions, 8 deletions
diff --git a/src/board_representation/MIGRATION.md b/src/board_representation/MIGRATION.md
index 313c74d..c6673ce 100644
--- a/src/board_representation/MIGRATION.md
+++ b/src/board_representation/MIGRATION.md
@@ -15,12 +15,13 @@ inline as a note rather than deleted, so a future session designing
the separate migration doesn't have to rediscover it from git history.
**Status: sections 1-3 (`bbPieces`/`bbPawns`-backed
-`_WhoAttacksSquareBB`/`_GetAttacksBB`), section 4 items 1-3 and 5, and
-section 6 (the `GETATTACKS_BITBOARD` toggle) all implemented, verified,
-and committed -- including a whole-engine `sd10` check across all three
-curated suites showing zero solve-count regression and +8.38%
-aggregate NPS. Only `match_play.py` (section 4 item 6 / section 7)
-remains unmet before full retirement of the old mailbox
+`_WhoAttacksSquareBB`/`_GetAttacksBB`), all of section 4, and section 6
+(the `GETATTACKS_BITBOARD` toggle) implemented, verified, and
+committed -- including a whole-engine `sd10` check across all three
+curated suites (zero solve-count regression, +8.38% aggregate NPS) and
+a `seescores` SEE-value diff across all 747 captures in those suites
+(byte-identical, zero diff). Only `match_play.py` (section 4 item 6 /
+section 7) remains unmet before full retirement of the old mailbox
implementation, deliberately deferred for now. Section 5's whole-engine
item and section 7's remaining items are otherwise done; section 8 not
started.** See the per-section status notes below for specifics.
@@ -461,7 +462,18 @@ sequence.
ECM/random positions, run once per `GetAttacksBB` toggle state,
diffed. Catches any behavioral drift `TestGetAttacks`'s raw-list
comparison might miss once results feed into `_MinLegalPiece`'s
- exchange simulation. Not started.
+ exchange simulation. **DONE.** `seescores <filename>` (`command.c`,
+ registered alongside `script`/`sd`) reads `setboard` lines from an
+ EPD file (the same convention `tests/ecm*.ep_` already use),
+ generates legal moves per position, and prints `(FEN, SAN move, SEE
+ value)` for every capture. Run against all three curated suites (747
+ captures total: 51 + 351 + 345), once per binary from section 4 item
+ 5's same-commit asm-vs-`GETATTACKS_BITBOARD=1` A/B build -- output
+ **byte-identical, zero diff**, on all three. Confirms `_GetAttacksBB`
+ is correct not just at the attacker-list level (`TestGetAttacks`)
+ but all the way through `SEE()`/`_MinLegalPiece`'s exchange
+ simulation to the final score every move-ordering decision actually
+ uses.
5. **Full-suite behavioral check is mandatory here, not optional** --
this is the one place this migration is *riskier* than the Eval
constant work: `GetAttacks` feeds move ordering and pruning decisions
diff --git a/src/command.c b/src/command.c
index a3361af..37686ed 100755
--- a/src/command.c
+++ b/src/command.c
@@ -1844,6 +1844,130 @@ COMMAND(SEECommand)
}
+COMMAND(SeeScoresCommand)
+/**
+
+Routine description:
+
+ board_representation/MIGRATION.md section 4 item 4: for every
+ position in <filename> (lines starting with "setboard ", the same
+ EPD convention the 'script' command's suite files use -- see
+ tests/ecm*.ep_), compute SEE() for every legal capture and print
+ (FEN, SAN move, SEE value) triples in generation order. Meant to
+ be run once per GetAttacksBB toggle state and diffed -- catches
+ any behavioral drift TestGetAttacks's attacker-*list* comparison
+ can't see, since that test only checks GetAttacks's raw output,
+ not what SEE()/_MinLegalPiece's exchange simulation does with it
+ downstream.
+
+ Usage:
+
+ seescores <required filename>
+
+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 (unused --
+ this command sets its own position per line of the file)
+
+Return value:
+
+ void
+
+**/
+{
+ FILE *pFile;
+ static CHAR szLine[SMALL_STRING_LEN_CHAR];
+ SEARCHER_THREAD_CONTEXT *ctx;
+ CHAR *szFen;
+ CHAR *p;
+ MOVE mv;
+ ULONG u;
+ ULONG uPositions = 0;
+ ULONG uCaptures = 0;
+
+ if (argc < 2)
+ {
+ Trace("Usage: seescores <required-filename>\n");
+ return;
+ }
+ if (FALSE == SystemDoesFileExist(argv[1]))
+ {
+ Trace("Error (file doesn't exist): %s\n", argv[1]);
+ return;
+ }
+ pFile = fopen(argv[1], "rb");
+ if (NULL == pFile)
+ {
+ Trace("Error (can't open file): %s\n", argv[1]);
+ return;
+ }
+ ctx = SystemAllocateMemory(sizeof(SEARCHER_THREAD_CONTEXT));
+ if (NULL == ctx)
+ {
+ fclose(pFile);
+ return;
+ }
+
+ while (fgets(szLine, ARRAY_LENGTH(szLine), pFile))
+ {
+ if (STRNCMPI(szLine, "setboard", 8))
+ {
+ continue;
+ }
+ szFen = szLine + 8;
+ while (' ' == *szFen)
+ {
+ szFen++;
+ }
+ p = strchr(szFen, '\r');
+ if (NULL != p) *p = '\0';
+ p = strchr(szFen, '\n');
+ if (NULL != p) *p = '\0';
+
+ if (FALSE == FenToPosition(&(ctx->sPosition), szFen))
+ {
+ Trace("SEESCORES: skipping malformed FEN: %s\n", szFen);
+ continue;
+ }
+ uPositions++;
+
+ mv.uMove = 0;
+ GenerateMoves(ctx, mv,
+ (InCheck(&(ctx->sPosition), ctx->sPosition.uToMove) ?
+ GENERATE_ESCAPES : GENERATE_ALL_MOVES));
+ ASSERT(ctx->uPly == 0);
+ for (u = ctx->sMoveStack.uBegin[0];
+ u < ctx->sMoveStack.uEnd[0];
+ u++)
+ {
+ mv = ctx->sMoveStack.mvf[u].mv;
+ if (!mv.pCaptured)
+ {
+ continue;
+ }
+ if (MakeMove(ctx, mv))
+ {
+ UnmakeMove(ctx, mv);
+ Trace("SEESCORES %s | %s | %d\n",
+ szFen,
+ MoveToSan(mv, &(ctx->sPosition)),
+ SEE(&(ctx->sPosition), mv));
+ uCaptures++;
+ }
+ }
+ }
+ fclose(pFile);
+ SystemFreeMemory(ctx);
+ Trace("SEESCORES: %u position(s), %u capture(s) scored.\n",
+ uPositions, uCaptures);
+}
+
+
COMMAND(TestCommand)
/**
@@ -2404,11 +2528,17 @@ COMMAND_PARSER_ENTRY g_ParserTable[] =
FALSE,
"Run a script" },
{ "sd",
- SearchDepthCommand,
+ SearchDepthCommand,
TRUE,
FALSE,
TRUE,
"Set engine maximum search depth" },
+ { "seescores",
+ SeeScoresCommand,
+ FALSE,
+ FALSE,
+ FALSE,
+ "Dump SEE() for every legal capture in a batch of EPD positions" },
{ "set",
SetCommand,
TRUE,