| Name | Modified | Size | Downloads / Week |
|---|---|---|---|
| Parent folder | |||
| sunfish-4k.packed | 2026-08-11 | 3.3 kB | |
| sunfish-2026-py3-none-any.whl | 2026-08-11 | 51.8 kB | |
| sunfish-2026.tar.gz | 2026-08-11 | 94.0 kB | |
| README.md | 2026-08-11 | 5.6 kB | |
| sunfish v2026 source code.tar.gz | 2026-08-11 | 2.5 MB | |
| sunfish v2026 source code.zip | 2026-08-11 | 2.5 MB | |
| Totals: 6 Items | 5.2 MB | 0 | |
Changelog
sunfish 2026
The first PyPI release. Three years of work since sunfish 2023, in four stories: the search was formally verified and got simpler for it, two families of production bugs were found and fixed, the engine became a proper package, and a strong NNUE sibling grew up next to it.
The engine (142 clean lines, ~3.3KB packed)
- The search's promises are now theorems. The
bound()docstring states the full contract — the fail-soft bracket, the exact promises (king-gone, capturable-node sentinel, verified mate/stalemate values, the fail-hightp_movewitness) — and every clause maps to a machine-checked theorem informal/(Lean 4, zero sorries, no Mathlib). The correctness layer carries no chess assumptions; zugzwang can cost accuracy, never table consistency. - Null-move fail-highs are verified before they may cut: a real
king capture is substituted when one exists, and a mate-band claim is
settled by one probe at the band boundary — where a fail-soft report
is decisive in both directions. The chess assumption this replaced
("you cannot be in zugzwang while delivering forced mate") is false
(witness:
8/6p1/6R1/k7/2K5/8/8/8 w), which is why it had to be computed rather than assumed. - Mate/stalemate detection is verify-on-suspicion: when no searched move proves legal, every generated move is checked with a board predicate, and verified terminals return their exact values (0 / −MATE_LOWER) at every depth ≥ 1 — in both fail directions. Trusting search scores as legality evidence is provably unsound; three historical "score implies legality" assumptions were refuted on real boards and their fixes are regression-tested.
- Late Move Reductions were removed after measurement showed the honest variant is worth exactly 0.00 ± 34 Elo — the historical variant's entire edge was its unsound bound propagation (the transposition-table crossing is machine-checked). The move loop is full-width again, and the docstring is provable as written.
MATE_LOWERmargin repair: the king-value margin now covers the largest army a kingless side can field (K − 13Q); the old margin provably leaked.- The MTD-bi driver brackets the full window band, converges in a proven ≤ 15 probes per depth, and only commits a best move from a completed depth (see bug fixes below).
Production bug fixes (found by auditing the lichess bot's games)
- The killer-eviction race:
tp_move's FIFO eviction could age out the current search root mid-search once the table churned past capacity; a deep fail-low probe then stored whatever capture sorted first, and a timeout played it. Three queen/piece giveaways in 145 production games. Fixed: eviction never removes the search root. - The dive-window family: a mid-depth stop could answer from a fail-high obtained at an absurd probe window (including a ponderhit variant). Fixed: both UCI loops promote a candidate move only when its depth's bracket converges — with the one sound exception proven and kept (the first probe of the next depth, which runs at the converged bracket's midpoint).
position fenhandling (#156): an installed engine that cannot find its real UCI interface now says so and stops, rather than silently playing on with a reduced one.- Long-TC time overruns: deadlines are enforced inside the search (checked every 2048 nodes), not just between iterations.
Packaging and interfaces
pip install sunfish && sunfishstarts the terminal play interface;sunfish-uciis the engine for GUIs and tournament managers. Published to PyPI via trusted publishing; releases are tag-driven and smoke-test the wheel end-to-end, including on Windows.sunfish_ui/ships in the wheel: the full UCI interface (pondering, Hash, spec-completegoparsing, FEN positions) and the fancy terminal board.- Repository reorganized:
docs/,formal/,sunfish_ui/,tests/,tools/— with build scripts, deploy configs, and test data filed under their owners.
Verification and testing infrastructure
formal/: the Lean development — the core fail-soft contract, the layered null-move specs, the killer-table lifecycle theorem, liveness results (mate-in-k completeness, driver convergence, no false mates, and the win/loss/no-mate classification theorem) — plus a CI drift guard that hashes every audited code region and ratchets stale citations. A paper draft lives informal/paper/.docs/TESTING.md: the tournament methodology, each rule with the confident wrong number that created it. Decision-grade matches run at 30+1 minimum with a book that covers the round count.- The test suite grew the terminal bench (148 Stockfish-validated mate/stalemate positions), transposition-consistency witnesses, and deterministic regressions for both production bug families.
The NNUE sibling (in review, nnue_4k/)
A packed big-integer NNUE engine — the whole accumulator and evaluation head live in one Python int (SWAR lanes, modular horizontal sums, king buckets) with training and verification toolchains. Currently measured around +200 Elo over classic at 30+1, aimed at the TCEC 4k division and a lichess bot of its own. Lands in the next release.
sunfish 2023
The classic 131-line engine: MTD-bi search, piece-square tables, null-move pruning, quiescence via the value filter, futility pruning, and the king-capture convention. See git history.