summaryrefslogtreecommitdiff
path: root/src/CLAUDE.md
diff options
context:
space:
mode:
authorScott Gasch <[email protected]>2026-10-15 11:26:31 -0700
committerScott Gasch <[email protected]>2026-10-15 11:26:31 -0700
commit53b380c658f828c4c0e096be2763e6b012c23abd (patch)
tree3e6b6a8ce608674d8fa33e6e9632d4d37290a301 /src/CLAUDE.md
parentef2c2f667c4fc2c0303f56ea487183916f82fb67 (diff)
Docs moved around.
Diffstat (limited to 'src/CLAUDE.md')
-rw-r--r--src/CLAUDE.md74
1 files changed, 21 insertions, 53 deletions
diff --git a/src/CLAUDE.md b/src/CLAUDE.md
index 0bfc028..f2bbd37 100644
--- a/src/CLAUDE.md
+++ b/src/CLAUDE.md
@@ -1,6 +1,6 @@
# typhoon chess engine
-A chess engine by Scott Gasch ([email protected]), originally started 2004.
+A chess engine by Scott Gasch ([email protected]), originally started 2000.
Previously named "monsoon" -- any old references to that name mean this same
codebase. Speaks the xboard/WinBoard protocol. FreeBSD host, 64-bit.
@@ -26,7 +26,13 @@ exist here (no `gcc`, and the resulting `.o` files are architecture-mismatched
against everything else). **Don't use build.sh as-is.** Build directly with:
```sh
-gmake -j5 GENETIC=1 PERF_COUNTERS=1 MP=1 SIXTYFOUR=1
+gmake release PERF_COUNTERS=1 MP=1
+```
+
+or
+
+```sh
+gmake debug PERF_COUNTERS=1 MP=1
```
This uses `clang`/`clang++` (already the GNUmakefile default) and produces a
@@ -79,50 +85,6 @@ invariants) fast; the suite workflow measures whether a change is actually
directory isn't left with a `TEST`/`DEBUG`-flavored binary as a side
effect of running it. ~20s end to end on this box.
-**Two real bugs found and fixed by exercising this session's changes
-through the smoke test, both pre-existing and unrelated to the session's
-actual move-ordering work:**
-1. **A killer-table backfill collision** (`dynamic.c`'s `_NewKillerMove`,
- from a previous session's `917bf12`): when slot `[1]` was empty after
- the shift, it backfilled unconditionally from
- `mvNullmoveQuietRefutations[uPly]` with no check that the backfilled
- move differed from the move just placed in slot `[0]` -- if they
- coincided, both slots ended up holding the identical move, tripping
- `_NewKillerMove`'s own `!IS_SAME_MOVE(mvKiller[uPly][0], mvKiller[uPly][1])`
- invariant. Silent (a wasted killer slot, not a crash) in a release
- build, since `ASSERT` compiles to nothing there -- only visible once a
- `DEBUG` build actually got exercised. Fixed by skipping the backfill
- when it would collide.
-2. **Two `ASSERT(iBestScore > -NMATE)` calls in `QSearch()`** (`search.c`)
- encoded an invariant that isn't actually guaranteed: at a very early
- (full-width) root iteration, or after aspiration-window widening
- following repeated fail-highs, an ancestor frame's `iAlpha`/`iBeta` can
- itself already be more extreme than `-NMATE` (e.g. `-32767`) with no
- mate anywhere in the line. Once that's true, a legitimately-computed
- fail-low placeholder (`iBestScore = iAlpha`, used to deny a stand-pat
- credit when material looks unavoidably in trouble) or a genuine
- fail-high (`iScore >= iBeta`) can land in mate-magnitude territory
- purely as a window artifact -- there's no value that can simultaneously
- satisfy `iBestScore <= iAlpha` (required to preserve fail-low semantics)
- and `iBestScore > -NMATE` once `iAlpha` itself is past that threshold,
- so the assert was demanding something structurally impossible, not
- catching a real bug. Removed both. This exposure (a non-mate score
- numerically resembling one) already existed in every release build
- before this, since `ASSERT` is a no-op there -- checked `hash.c`'s
- storage path specifically and confirmed it already treats any value
- `<= -NMATE` as a sound, if loose, upper bound regardless of origin
- (clamped to exactly `-NMATE` on store, never marked `HASH_FLAG_EXACT`,
- so the `ADJUST_MATE_IN_N` ply-distance readjustment -- which only fires
- for `HASH_FLAG_EXACT` entries -- never misapplies to it); a full audit
- of every other `NMATE`/`MATED_SCORE` consumer (root.c's mate-in-N
- display being the obvious remaining one) hasn't been done.
-
-Also fixed while chasing these: batch-mode's exit code was `exit(-1)`
-(`command.c`, truncates to `255` as an 8-bit status), indistinguishable
-from a real crash's nonzero exit -- changed to `exit(0)` so a clean batch
-run and a crash are actually distinguishable by exit status, which is what
-`debug_smoke_test.sh` relies on.
-
**On not making this an automatic git pre-commit hook**: deliberately not
wired up that way. Two concrns pushed toward manual-by-default: (1) each
full gate is a `gmake clean` + rebuild, real time on every commit even for
@@ -150,6 +112,8 @@ an xboard-protocol REPL on stdin/stdout. Key commands used during development:
- `evaldna dump` / `evaldna read <file>` / `evaldna write <file>` -- the
eval-constant import/export system (`g_EvalDNA` in eval.c). `evaldna` alone
(no subcommand) just prints usage -- you need `evaldna dump` explicitly.
+- `dump eval` -- in a EVAL_DUMP=1 build (see GNUMakefile), will output each
+ individual eval term at the previously evaluated position.
- `sd <n>` / `st <n>` -- fixed depth vs. fixed time search limits.
- `go` -- search and play one move for whichever side is on move, then stop
(when paired with `force` after). Repeated `go`/`force` cycles correctly
@@ -216,13 +180,6 @@ touch); for large 6-man files it's a weaker guarantee -- a `ready`
whether this matters in practice; if deep-probe latency spikes show up
in profiling, this is the first place to look.
-**Not yet done, a natural follow-up**: root-time warm-up -- proactively
-touching (probing) WDL tables for material signatures reachable within a
-few plies of likely trades from the root position, before the main
-search starts, so `ready[WDL]` is already true for most of what the deep
-search will actually encounter rather than depending on an earlier
-shallow-ply probe in the *same* search to have warmed it first.
-
**Also worth knowing**: `ProbeEGTB` wraps the actual `tb_probe_wdl` call
in a single process-wide spinlock (`g_uEgtbLock`, `probe.c`). Increasing
probe frequency deep in the tree (now possible via the above) increases
@@ -484,6 +441,17 @@ bake-in-if-better, repeatable indefinitely against a growing game pool.
large improvement it first looked like. Always diff ECM numbers taken at
the same `sd` depth.
+## Running the engine in batch workloads
+
+Sometimes you will want to run the engine in a --batch --command
+'whatever' mode to do background batch processing. When you do, run
+with --cpus=1 and --hash=8m if you don't have a reason not to. The
+--hash argument is because every `setboard <fen>` command memsets the
+hash table to 0 so a default (256m) hash table will add latency to the
+workflow. With --cpus=1, you can run up to 16 instances of the engine
+on this 24 core machine and still leave enough cycles for normal
+operating while the chess work continues in the background.
+
## Dynamic move ordering experiments (2026-08-29)
A single long session that redesigned how quiet ("leftover", i.e.