Bullet chess: Jev picks from the legal moves
1. What Jev decides
Which legal move to play. chess.js generates the legal moves in SAN; they become the options of one choice question with empty descriptions. The state is the FEN, the side to move, and the last six moves. The opponent is a random mover by default, or any gateway chat model asked for one SAN move with a 10 s budget. Each side has one minute; Jev's clock runs down by its measured call time.
2. The questions
The question and limits, from the top of chess.mjs. This is the block a reviewer must read; the rest of the file is plumbing.
// ---- Review these. Everything else is plumbing. ----
const QUESTION = { type: "choice", instructions: "Which move is best for the side to move?" }; // criteria: one option per legal move (SAN), empty description
const HISTORY = 6; // last N moves shown to Jev
const CLOCK_MS = 60_000; // bullet: one minute per side
const MAX_PLIES = 200; // ponytail: hard stop, scored as a draw
const MODEL_BUDGET_MS = 10_000; // the chat opponent's time per move; a late or illegal answer plays a random move
3. What the page shows
A board drawn on a canvas with Unicode pieces, two clocks with Jev's in orange, a card with Jev's last decision (the move, how many legal moves it chose from, the call time, the confidence) and the top five candidates as bars, and the move list with Jev's moves in orange. A form picks Jev's colour and the opponent.
4. Run it
node --env-file=.env chess/chess.mjs # http://localhost:3003
node --env-file=.env chess/chess.mjs --check # 10 games vs random
node --env-file=.env chess/chess.mjs --check --games 1
5. The check, verbatim
game 1: Jev white, 200 plies, draw (200 plies), $0.0024
game 2: Jev black, 20 plies, black wins by checkmate, $0.0002
game 3: Jev white, 200 plies, draw (200 plies), $0.0022
game 4: Jev black, 166 plies, draw, $0.0018
game 5: Jev white, 67 plies, white wins by checkmate, $0.0009
game 6: Jev black, 36 plies, black wins by checkmate, $0.0005
game 7: Jev white, 167 plies, draw, $0.0020
game 8: Jev black, 62 plies, black wins by checkmate, $0.0008
game 9: Jev white, 23 plies, white wins by checkmate, $0.0003
game 10: Jev black, 200 plies, draw (200 plies), $0.0022
Jev won or drew 10/10; 572 Jev moves, mean 465 ms per move, $0.0133 total
The first single game, before the ten: Jev white, 37 plies, white wins by checkmate, 19 Jev moves at a mean of 723 ms, $0.0005.
The first ten-game attempt died in game 2 on a gateway 503 that outlived the SDK's retries. The error, cut to its first line:
RetryError [AI_RetryError]: Failed after 3 attempts. Last error: GatewayInternalServerError: Service temporarily unavailable. Please try again shortly.
The second single game died on the SDK itself:
InvalidResponseDataError [AI_InvalidResponseDataError]: Question "move" did not select a highest-probability option.
data: { move: { type: 'choice', choice: 'Nc4', probabilities: { ..., Nc4: 0.13, Ne4: 0.14, ... } } }
6. Findings
- Jev never played an illegal move. It cannot: the options are the legal moves, so the schema does the legality. This is what "zero hallucination" means here.
- Five checkmates and five draws against random moves. Two draws were the 200-ply cap; two were real (repetition or insufficient material). Jev finds mates but does not always convert a won position.
- The rounding tie. Jev's probabilities are rounded to two decimals. When the chosen move shows 0.13 and another shows 0.14,
ai7.0.107 throwsAI_InvalidResponseDataError. With 20 to 40 near-equal moves this happens often.lib.mjscatches it and takes the answers from the error'sdatafield; the confidence and cost of that call are lost. - The 503 bursts. The gateway answered 503 three times within 6 s during game 2 of the first check.
lib.mjsnow waits 3, 6, 12, and 24 s and tries again before giving up. - Mean time per move over 572 moves: 465 ms. Over one game earlier in the session: 723 ms. Over an HTTP smoke test at black: about 340 ms. The clock on the page shows whichever it is.
- Not measured: a game against a chat model. The page accepts a gateway model id in the opponent field and gives it 10 s per move; a late or illegal answer plays a random move and is marked in the move list.
7. Cost and latency
About 30 legal moves per position, under 1,000 input tokens: $0.00004 per move. A game: $0.0002 to $0.0024.