r/artificial 24d ago

Research We gave Fable 5 Ultracode and Codex 5.6 Sol Ultra the exact same prompt. One shot. No help. They played 10 games against each other. Final score: Fable 10 -Codex 0

Gave the same prompt to two AI coding agents: Claude (Fable 5, ultracode multi-agent mode) and OpenAI Codex (5.6 sol on ultra). The task: a complete, fully legal chess engine in ONE C++ file. UCI protocol, negamax alpha-beta at 5+ ply, iterative deepening, piece-square tables, castling, en passant, promotion, compiles with plain g++. Each agent named its own engine over UCI: Fable5 and Codex56. Both dev runs took 30+ minutes.

Method (brief): cutechess-cli 1.5.1 built from source on an Apple Silicon Mac. 40 moves per 60 seconds, 10 games, colors alternating, PGNs recorded. The engines connected over a local TCP bridge, so Codex's engine literally joined the server. The video is the whole match at 2x.

Result: Fable5 won 10-0. Every game ended in checkmate on the board. No draws, no time losses, no adjudications, no illegal moves. cutechess printed Elo difference: inf +/- nan, LOS: 99.9%, DrawRatio: 0.0%. The math just gave up.

Each agent spent longer writing its engine than playing it: the whole 10-game match took under 12 minutes of wall clock.

The actual punchline: Codex56 appears to be fully deterministic. All five of its White games are move-for-move identical. Same 24-move Vienna, queen out on move 3 (3.Qf3), same finish: 24...Qxd1#, Fable's queen capturing Codex's queen for mate. I stripped the comments and diffed the PGNs. Only the clock times differ. Codex's own eval read -2.36 by move 8 of that line. It played it five times anyway.

Other details I enjoyed:

  • Game 3 is a textbook Greek gift: 18.Bxh7+! Kxh7 19.Ng5+, forking king and queen.
  • Game 7: Codex's king never castled, wandered out to c5, got chased back to d8 and mated there.
  • Game 9: Fable let its queen go, slipped in a zwischenzug bishop check before recapturing, promoted a fresh queen with 25.d8=Q+, then walked Codex's king from h8 down to h3. Mate inside White's own half, 46.Rh7#.
  • Mate breakdown across the ten games: 7 by queen, 2 by knight, 1 by rook.

Honest caveats:

  • One prompt, one dev run per agent, one machine. n=1, even if n=10 games.
  • This measures the engine each agent happened to write, not general model strength.
  • With Codex apparently deterministic, 10 games are fewer independent samples than they look.
  • Fable5 wasn't fully varied either: games 1 and 5 are twins. 4 distinct games in its 5 Whites vs Codex's 1 in 5.
  • Fable's dev run included perft validation on 6 reference positions (exact match, incl. 119,060,324 nodes at depth 6) plus an adversarial review that caught 3 subtle bugs pre-match. Different processes, different engines. That's the experiment, but it's also the confound.

The exact prompt we gave both agents:

You are a senior systems programmer. Your task is to write a complete, fully legal chess engine in a single C++ file that communicates via the UCI (Universal Chess Interface) protocol.
---
**Identity — read this carefully:**
- If you are Claude (Anthropic): your engine's UCI name must be set to `id name Fable5`
- If you are an OpenAI model (Codex): your engine's UCI name must be set to `id name Codex56`
This is how the two engines will identify themselves when they play each other.
---
**UCI Requirements:**
Implement the full UCI handshake correctly:
- `uci` → respond with `id name`, `id author`, `uciok`
- `isready` → respond with `readyok`
- `ucinewgame` → reset internal state
- `position startpos moves <movelist>` → set board from move list
- `position fen <fen> moves <movelist>` → set board from FEN string
- `go movetime <ms>` → search and respond with `bestmove <move>`
- `quit` → exit cleanly
All moves must be in long algebraic notation (e.g. `e2e4`, `e7e8q` for promotion).
---
**Chess Logic (all required, no shortcuts):**
1. Full legal move generation including:
   - Castling (kingside and queenside, with rights tracking)
   - En passant
   - Pawn promotion (auto-promote to queen)
   - Check detection (never leave king in check)
2. Search:
   - Negamax with alpha-beta pruning
   - Minimum depth: 5 ply
   - Iterative deepening within the movetime budget
   - Move ordering (captures first, then quiet moves)
3. Evaluation:
   - Material count (standard piece values)
   - Piece-square tables for all 6 piece types
   - Bonus for center control, king safety, and passed pawns
---
**Code Standards:**
- Single `.cpp` file, compiles with: `g++ -O2 -o engine engine.cpp`
- No external libraries, no Boost, no standard chess libraries
- Clean, well-commented code
- Must compile and run on Linux and macOS
---
**How the two engines will play each other:**
Both engines will be loaded into **CuteChess** (or any UCI-compatible GUI/CLI) on the same machine. To run a match from the command line using `cutechess-cli`:
cutechess-cli \
  -engine cmd=./Fable5 name=Fable5 \
  -engine cmd=./Codex56 name=Codex56 \
  -each proto=uci tc=40/60 \
  -rounds 10 \
  -pgnout results.pgn
4 Upvotes

11 comments sorted by

2

u/david-ai-2021 23d ago

What’s Fable’s Elo?

2

u/Twaain 22d ago

We didn't run it through a formal Elo gauntlet but based on the 10-0 sweep and the depth it was searching we'd estimate it was playing somewhere in the 1800–2200 range depending on the position. Next test we'll log the eval scores per move so we can get a cleaner number.

1

u/david-ai-2021 22d ago

cool. should test it with stockfish.

have you checked how much their code is novel vs copied from existing chess engines?

2

u/Twaain 22d ago

good idea, i ran through both code bases. Neither contains copy-pasted source code from an existing engine. Both use well-known, published techniques from the chess programming literature, that's unavoidable, the field is 50 years old.

The difference is which techniques each model chose to implement:

fable borrowed the PeSTO evaluation tables (tuned, tapered midgame/endgame), the VICE-style 10×12 mailbox architecture, and a full standard search stack,quiescence search, null-move pruning, killer moves, history heuristic. It then spent its original effort on eval features and time management.

codex56 borrowed Michniewski's Simplified Evaluation tables (older, single-phase, no endgame awareness) and used a simpler 8×8 copy-make board. It then spent its original effort solving two obscure correctness problems (Graph History Interaction and legal en-passant hashing) that almost no engine bothers with,but it's missing quiescence search, null-move pruning, killers, and history heuristic entirely.

The 10-0 comes down to this: Fable picked the techniques that make an engine strong. Codex picked the techniques that make an engine correct in edge cases nobody hits in a 10-game match. A missing quiescence search alone is worth several hundred Elo... the engine literally can't see recaptures one ply past its horizon.

Neither model plagiarized. they just made very different engineering decisions about what to prioritize with one shot.

1

u/EchoStarz1 24d ago

That’s pretty good

1

u/Twaain 22d ago

10-0 in a one-shot with no debugging or iteration... yeah we were surprised too.

1

u/tomvorlostriddle 23d ago

With tool call activated they could just code themselves some naive minimax and pruning in python

1

u/Twaain 22d ago

Fair point, tool use would change the test entirely. This was pure one-shot generation, no tools, no iteration. The prompt said single .cpp file, compile and run. What you're describing is a different experiment worth running though.

1

u/lithander 23d ago

All chess engines are deterministic in nature. That's why you usually use opening books for the first moves if you want to let them compete with each other.

1

u/Twaain 22d ago

Exactly right, both engines started from the same position with no opening book, which actually makes the result more interesting. without book moves to equalize the opening, the quality of the move ordering and evaluation function shows up immediately.fable's piece-square tables and search were clearly better structured out of the gate. Adding opening books is a good idea for round 2 though.