diff options
| author | Scott Gasch <[email protected]> | 2026-10-15 11:26:31 -0700 |
|---|---|---|
| committer | Scott Gasch <[email protected]> | 2026-10-15 11:26:31 -0700 |
| commit | 53b380c658f828c4c0e096be2763e6b012c23abd (patch) | |
| tree | 3e6b6a8ce608674d8fa33e6e9632d4d37290a301 /src/CLAUDE.md | |
| parent | ef2c2f667c4fc2c0303f56ea487183916f82fb67 (diff) | |
Docs moved around.
Diffstat (limited to 'src/CLAUDE.md')
| -rw-r--r-- | src/CLAUDE.md | 74 |
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. |
