summaryrefslogtreecommitdiff
path: root/src/stockfish_xboard
blob: 91765adb4b1799b811876a89a4574e57bc695b8c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#!/usr/bin/env bash
#
# stockfish_xboard -- thin wrapper so match_play.py's Engine class (which
# always spawns its path with hardcoded TYPHOON flags, "--hash 256m --cpus 1
# --logfile -" -- see match_play.py's engine_args) can drive Stockfish
# instead. Stockfish speaks UCI, not xboard, so this execs it through
# PolyGlot (the UCI<->xboard adapter already installed on this box,
# /usr/local/bin/polyglot) and deliberately DISCARDS every argument it's
# called with -- match_play.py's hardcoded typhoon-style flags are
# meaningless (and would error) if passed to polyglot/Stockfish directly.
#
# Same "ignore whatever the caller passes, always do the right thing"
# pattern as the NNUE_WEIGHTS shim in eval_tune/test_vs_head.sh.
#
# Verified manually (2026-10-17): PolyGlot's xboard handshake (feature
# negotiation ending "feature done=1") and a real "setboard ...; st 2; go"
# round-trip both work correctly when driven by a persistent subprocess
# that keeps stdin open (exactly how Engine class drives it) -- a one-shot
# shell pipe (`printf ... | polyglot`) does NOT work, stdin EOFs before
# Stockfish finishes thinking and no "move ..." line is ever printed. Do
# not "simplify" this to a plain pipe when debugging.
#
# Override the Stockfish binary/dir via env vars if needed:
#   STOCKFISH_BIN   defaults to "stockfish" (resolved via PATH, i.e.
#                   /usr/local/bin/stockfish on this box)
#   STOCKFISH_DIR   defaults to /usr/local/bin (polyglot's -ed)
#   SYZYGY_PATH     defaults to /zscratch/egtb (same dir typhoon's own
#                   --egtbpath default points at, see main.c). Stockfish 19's
#                   tbprobe.cpp is itself Fathom-derived, so it reads the
#                   exact same .rtbw/.rtbz files typhoon does -- no separate
#                   Stockfish-format tablebase or conversion needed.
#                   Verified 2026-10-18: `setoption name SyzygyPath value
#                   /zscratch/egtb` against a bare stockfish UCI session logs
#                   "info string Found 510 WDL and 510 DTZ tablebase files
#                   (up to 6-man)." PolyGlot forwards this through via its
#                   `-uci SyzygyPath=...` flag (any `-uci name=value` is
#                   passed straight to the engine as a UCI setoption at
#                   startup, before the xboard-side handshake). Set to ""
#                   to disable TB probing entirely.
SYZYGY_PATH="${SYZYGY_PATH:-/zscratch/egtb}"
#
# 2026-10-17: wrapped with `stdbuf -oL` -- when PolyGlot's stdout isn't
# a tty (true here: match_play.py spawns it via subprocess.Popen with a
# pipe), C stdio defaults to full block buffering instead of line
# buffering, so xboard protocol lines (including "move ...") can sit
# unflushed in PolyGlot's own buffer while match_play.py's readline()
# blocks waiting for them -- looks exactly like an I/O-bound engine
# from the outside (low measured CPU, long wall-clock per move, idle
# machine) even though the actual Stockfish search finished promptly.
# Same class of bug as this session's own repeated Python stdout-
# buffering gotchas, just at the C-stdio layer instead. `stdbuf -oL`
# forces line buffering regardless of tty status.

set -e

STOCKFISH_BIN="${STOCKFISH_BIN:-stockfish}"
STOCKFISH_DIR="${STOCKFISH_DIR:-/usr/local/bin}"

if [ -n "$SYZYGY_PATH" ]; then
    exec stdbuf -oL polyglot -noini -ec "$STOCKFISH_BIN" -ed "$STOCKFISH_DIR" \
        -uci "SyzygyPath=$SYZYGY_PATH"
else
    exec stdbuf -oL polyglot -noini -ec "$STOCKFISH_BIN" -ed "$STOCKFISH_DIR"
fi