summaryrefslogtreecommitdiff
path: root/src/docs/TREEDUMP_FORMAT.md
diff options
context:
space:
mode:
authorScott Gasch <[email protected]>2026-10-24 09:07:03 -0700
committerScott Gasch <[email protected]>2026-10-24 09:07:03 -0700
commit5f901d737b17c5f99b6e456d6c0c7d5e3c093dc4 (patch)
tree6601dadbd36c8f45991c5dd821a3dbb2059baafe /src/docs/TREEDUMP_FORMAT.md
parent69525eb2f42ea9cca8255f6cc3b85e6b1312fd05 (diff)
More aggressive move reductions; Wilson bound overrides static signal when available
SPRT playtest (2000 games, sd/depth matched): -535 =875 +590, score=0.514, llr=+1.04 (floated around +1.0 the whole run, never went negative) toward H1=+2.94. Not a confirmed win, but searches meaningfully deeper (avg depth 14.35 vs 13.50, EBF 3.131 vs 3.305) at no measurable strength cost -- worth banking and continuing to accumulate games against. Co-Authored-By: Claude Sonnet 5 <[email protected]>
Diffstat (limited to 'src/docs/TREEDUMP_FORMAT.md')
-rw-r--r--src/docs/TREEDUMP_FORMAT.md95
1 files changed, 95 insertions, 0 deletions
diff --git a/src/docs/TREEDUMP_FORMAT.md b/src/docs/TREEDUMP_FORMAT.md
index ecc4325..47d1a82 100644
--- a/src/docs/TREEDUMP_FORMAT.md
+++ b/src/docs/TREEDUMP_FORMAT.md
@@ -66,6 +66,101 @@ redirecting from a real tty) never hits this, which is why it's easy
to not reproduce it while debugging interactively and then hit it
again the next time a script pipes input in.
+**Future-work idea, not yet built**: a small purpose-written xboard<->UCI
+driver (distinct from `stockfish_xboard`, which hardcodes
+`/usr/local/bin/stockfish` via PolyGlot for `match_play.py`'s xboard-only
+engine pool, not this instrumented source build) would let this
+TREEDUMP-build Stockfish be driven with the same `--batch --command`-style
+invocation already used for typhoon and Crafty, sidestepping the
+stdin-race gotcha entirely rather than working around it with `sleep`.
+Worth doing if this three-engine TREEDUMP comparison becomes a repeated
+workflow rather than a one-off batch.
+
+## Building a third engine: Crafty
+
+Crafty (`~/programming/chess/crafty-25.2`) also speaks this format now
+(added 2026-10-23), giving a third data point alongside typhoon and
+Stockfish -- useful specifically because Crafty's HCE is much "dumber"
+than typhoon's NNUE, so if Crafty's pruning/reduction magnitudes still
+line up with Stockfish's despite the weaker eval, that's a stronger
+signal that the magnitude is calibration-driven (an engine-independent
+"right amount") rather than an artifact of how strong the eval backing
+the search happens to be.
+
+Crafty compiles everything into one translation unit (`crafty.c`
+`#include`s every other `.c` file), so the `TREEDUMP` instrumentation
+lives directly in `search.c` (new `TDOpen`/`TDClose`/`TDMove`/`TDResult`
+functions, prototyped in `chess.h` behind `#if defined(TREEDUMP)`) rather
+than needing a new source file. `main.c` opens `treedump.log` at process
+start and registers `TDClose` via `atexit()` so it's closed on every exit
+path, not just a clean `quit`.
+
+Build (single-threaded, matching typhoon's and Stockfish's TREEDUMP
+convention -- `search.c`'s path-reconstruction helper assumes Crafty's
+single-TREE-struct-per-thread model, where `tree->curmv[1..ply]` holds
+every move played so far in *this* recursion; that invariant only holds
+cleanly with one thread):
+
+```sh
+cd ~/programming/chess/crafty-25.2
+rm -f *.o crafty
+gmake target=UNIX CC=clang opt='-DSYZYGY -DCPUS=1 -DTREEDUMP' \
+ CFLAGS='-Wall -Wno-array-bounds -pipe -O3 -mpopcnt' \
+ LDFLAGS='-lstdc++ -lm' crafty-make
+```
+
+(`-j` can be dropped or kept; `crafty.o` depends on `*.c *.h` as one
+glob so there's no partial-rebuild hazard the way Stockfish's
+`EXTRACXXFLAGS` has -- no `touch` trick needed here. Rebuild the normal
+multi-threaded profile afterward the same way the other two engines'
+TREEDUMP builds get reverted: `rm -f *.o crafty && gmake target=UNIX
+CC=clang opt='-DSYZYGY -DTEST -DCPUS=4' CFLAGS='-Wall -Wno-array-bounds
+-pipe -O3 -mpopcnt -pthread' LDFLAGS='-pthread -lstdc++ -lm'
+crafty-make` -- note the `-pthread` CFLAGS/LDFLAGS are required once
+`CPUS` > 1, the TREEDUMP/`CPUS=1` build doesn't need them.)
+
+Crafty speaks xboard natively (no PolyGlot/UCI adapter needed, unlike
+driving it through `stockfish_xboard`-style tooling), so it can be
+driven the same way as typhoon's own `--batch --command` invocations:
+
+```sh
+(printf 'force\nsetboard <FEN>\nsd 6\ngo\nquit\n'; sleep 2) | ./crafty
+```
+
+Hold stdin open past the search the same way Stockfish needs (see the
+gotcha below) -- not yet confirmed whether Crafty has the identical
+race, but cheap to guard against unconditionally rather than
+re-discover it.
+
+**Mapped `act=` values**: `FP-QUIET` (Crafty's `FP_margin[]` futility
+check -- note this is a **raw-material** check,
+`MaterialSTM(wtm) + FP_margin[depth] <= alpha`, not a full static-eval
+call the way typhoon's/Stockfish's futility-flavored checks are, so
+don't read "FP-QUIET volume" as directly comparable cost between
+engines even where the tag matches), `LMP` (pure move-count/depth
+threshold, no evidence gate at all -- matches the `search.c` comment
+block this investigation started from), `NMP` (null-move probe, `r`
+left `0.00` same convention as typhoon), `FULL`/`LMR`/`EXT` (the main
+move loop, after Crafty's own `reduce`/`extend` locals are resolved).
+Crafty has no ProbCut and no IID-as-a-traced-decision (IID's recursive
+call reuses the *same* ply rather than descending one, so it doesn't fit
+the path model and isn't traced).
+
+**A Crafty-specific wrinkle worth remembering when reading a diff**:
+Crafty's own `search.c` comment on this block (the one this
+investigation started from) says forward pruning here "simply avoid[s]
+searching this move at all, and skip[s] to the next move" -- but
+functionally this is a `break`, not a `continue`: once FP or LMP fires on
+one move, every *remaining* move at that node is abandoned too, not just
+the one move. typhoon's and Stockfish's LMP-equivalents are evaluated
+move-by-move (a `continue`, not a `break`) -- a given late move being
+pruned doesn't prevent trying a later move that might not be. Don't read
+Crafty's `act=LMP`/`act=FP-QUIET` *count* at a node as "N moves pruned
+out of the move list" the way you might for the other two engines; it
+usually means "the move list ended early starting here," which has a
+different effect on tree shape (and EBF) than an equal count of
+individually-pruned moves scattered across a wider move list.
+
## Why path-keyed, not node-numbered
Internal node counters are meaningless across two different engines --