r/ComputerChess • u/Macimoar • 9h ago
Nemesis: an engine that models one specific human (Maia-2 + a per-player model) and plays the move most likely to beat them
Enable HLS to view with audio, or disable this notification
I built an engine with a different objective. Instead of the objectively best move, it plays the move with the best expected result against one specific player, using a model of how that player actually chooses moves.
How it works
- The player model: a conditional-logit model over the legal moves, fitted per player on their imported Lichess or Chess. com games. Its features include Maia-2’s log-probability for the move, Stockfish’s eval loss, and style features: material grabbing, checks, king safety, development, how often the player repeats their own repertoire, and time pressure. The weights are regularised towards a Maia-2-based prior, so a player with few games falls back to “a typical human at your rating”.
- Maia-2: converted to ONNX and run on onnxruntime, so no PyTorch is needed. The rapid and blitz models are downloaded on first use.
- Move choice: Stockfish supplies the candidate moves and evals. For each candidate, the player model predicts the reply distribution, and Nemesis scores the expected outcome against that distribution. A risk dial sets how far it may stray from the objectively best move to set traps.
- Time controls: separate profiles per time control, kept only if they predict that time control’s held-out games better than the main profile.
- Also: it runs as a UCI engine, so it works in any GUI, and there’s a web app with an explain-everything commentary mode.
Results on my own games (I’m about 900 on Chess. com, 93 games, newest quarter held out):
| Predicting my exact move | Top-1 |
|---|---|
| Stockfish’s top move | 25% |
| Maia-2 alone, at my rating | 47% |
| Nemesis’s personal model | 49% (top-3: 78%) |
To be clear, Maia-2 does most of the work on top-1; the personal layer adds a couple of points. The more interesting test is whether exploiting the model pays off. Over 16 games against it, Nemesis set 59 traps and I fell for 14 (24%), against an 18% mistake rate (losing a pawn or more) on my other moves. On synthetic players with known habits it also beat plain Stockfish at the same depth: it finished off a “grabber” bot in 16.8 moves on average against Stockfish’s 22.6. That’s a simulation, though, not real people.
Caveats: one real player is a tiny sample, the trap rate comes from only 59 traps, and the synthetic benchmarks only show that it can exploit a known habit.
It’s free and open source (MIT), runs locally, and has downloads for Windows, Mac and Linux: https://github.com/macimoar/nemesis
Built as a one-person project with a lot of help from an AI coding assistant. I’d especially welcome thoughts on the method: better ways to measure whether exploitation works, features worth adding, or prior work I should be comparing against.

