#!/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