spire-mentor

A fast, bit-exact Slay the Spire 2 engine in Rust, and an AI that plays it

spire-mentor reimplements Slay the Spire 2 from scratch, checks itself against the game's own code after every action, and runs fast enough to search thousands of futures per decision, with a run-level AI on top. Two front ends show that AI thinking: a browser workbench and a mod for the real game.

The browser workbench in the act-3 boss fight (Ironclad vs the Queen, floor 45): the best card, Dominate+, carries a 95% win badge, and the machine-reasoning panel ranks every legal move by value and visits.
The browser workbench in the act-3 boss fight: the search marks the best card with its win chance, and the machine-reasoning panel ranks every legal move.

Overview

Six pieces, each usable on its own:

Engine

Rust, deterministic, the whole game: five characters, ~580 cards, ~300 relics, three acts. Built for speed (1.3 M actions a second on one core, 31 M on a 24-core server; about 1,500× the shipped game's throughput per core), checked against the game's own code after every action, and usable from Python.

Parity harness

Runs the game's own assembly headless and checks the engine against it after every single action, plus a fuzzer that hunts for divergences.

Run AI

Chance-node MCTS for fights (it never sees the draw order); a PPO-trained transformer per character for every other decision. Ironclad wins 90% at A0 and 39% at A9; Defect 22% at A10.

Workbench

The game in your browser, on any platform: rewind and branch, an AI coach, autobattle, post-run blunder review, the MCTS tree, state import from the real game, and SimLab.

Spire Mentor

A mod that puts the AI inside the real game as a coach, an autopilot and a rewind button.

Extraction & wiki

just import-game decompiles your copy and extracts data, art and sound; a generator builds a static wiki.

The engine

sts2-rs re-implements the game's rules in Rust, pinned to game build v0.107.1. It is not an approximation: the random number generator is a hand port of .NET's System.Random (the 56-element subtractive generator the game uses), and every RNG stream is consumed in the game's order. A seed yields the same map, the same card rewards, the same shuffles and the same monster rolls as the real game.

Content implemented in the engine
KindCountNotes
Characters5Ironclad, Silent, Defect, Regent, Necrobinder
Cards580card ids incl. colorless, status and curse cards
Relics297
Potions63
Powers272
Monsters121with their intent state machines
Events69incl. the Ancients
Acts34 act models (act 1 rolls Overgrowth or Underdocks)

Performance

Full benchmarks → one core against the whole machine, the shipped game compared five ways, search and training speed, the hardware, and two other Slay the Spire 2 simulators.

MeasurementResult
Random-play fights per second, one core59,400
Engine actions per second, same fights, one core1.30 M (766 ns each)
The same on the whole machine (24 cores, 48 threads)1.41 M fights/s
31.0 M actions/s
Against the shipped game run headless, best measured throughput1,500× per core
2,430× whole machine
Against the shipped game, CPU time per action2,970× (2,250× its game thread)
Against the previous engine (12 Oct 2026), same fights2.25×
Against two other simulators, same random-play fights, one core3.13× faster than sansb
sts2core 1.56× faster
Browser hint's search, 1,000 simulations13.7 ms native
18.4 ms WASM in Chromium
Browser hint at its default 2,000 simulations, WASM in Chromium39.9 ms
Advisor's search on an Act-1 boss, 8,000 simulations275 ms on 1 thread
39.6 ms on 8
A typical PPO training iteration (Ironclad, 960 games)208 s (609 s before)
150 in ~9 h

Measured on 14 October 2026 on one AMD EPYC 7443P server (24 cores, 48 threads, Linux) on a quiet host; plain release builds, except the training row, which uses the profile-guided build training runs on; medians of interleaved runs. The fights are random play: Ironclad's starter deck and Burning Blood against each of the 22 Act-1 Overgrowth encounters in turn, 22.0 actions per fight on average (an action is a card play or an end of turn). One core means one process on one physical core with its second hardware thread idle. The shipped game is its own assembly run headless by the project's harness on the same fights. One game process spends most of its time asleep in the harness's 1 ms polling, so the fair comparison runs many game processes at once, the best counts measured: 16 on one core, 192 on the machine. Earlier versions of this page said 23,000×: that was the wall time of one cold game process per fight, a different measurement, explained on the benchmarks page. Both other simulators are combat only. sansb/sts2-sim (game build v0.111.0) is certified against checksums the real game writes, and its review solver searches the true state by design; the 3.13× has our relic switched off, as Burning Blood is inert there. lain-wood/sts2core is effectively Ironclad only, with partial content and its own RNG, and its live solver is given the true draw-pile order. The comparison is random play, with no search involved (details). Method: 2026-10-14-benchmarks.md.

Workspace

A cargo workspace of twelve crates: sts2-core (state, hooks, damage, powers, RNG), sts2-content (every card, relic, potion, monster and event), sts2-mcts, sts2-runai (run arena, seed panels, policy/value nets with ONNX inference), sts2-cli (REPL, replays, sweeps), sts2-wire, sts2-py (PyO3 bindings), sts2-bench, sts2-workbench + sts2-workbench-wasm, and helpers. 7,000+ Rust tests, plus a cargo-fuzz target on the combat step.

Parity with the game

Claims of accuracy are cheap, so the project checks them mechanically. The game's own C# assembly, taken from your copy, is IL-patched and run headless with Godot stubbed out. The engine and that oracle then play the same seed with the same actions, in lockstep:

seed + actions
game's C# assembly
headless oracle
Rust engine
sts2-rs
compare after every action:
HP, block, energy, powers · ordered draw/discard/exhaust piles · hand costs · relics · monster state
first divergence → bucketed (draw order, hand cost, …)
  • Fuzzed combat parity on seeds covering every card (base and upgraded), every card against every arena, pairwise hook interactions and 30-turn fights; the full tier runs 5,000 seeds. In the last full sweeps Ironclad was clean on all 6,104 fights (June 2026) and the other four characters on 99.4–99.8% of about 5,750 each (July 2026), with a known tail still open.
  • Whole-run parity 1,232 of 1,250 runs clean (July 2026; five characters at Ascensions 0, 2, 5, 8 and 10): map generation, event pools, rewards, shops and the run state carried between acts. The runs use a random policy, so most end in Act 1.
  • No full sweep has run since July 2026, and the engine has changed since. Checks against fights recorded from the real game, with the game's own checksums, are planned but not done.
  • Freshness gates refuse to compare against a stale engine build or a stale oracle: a source hash is compiled into the Python extension and checked at load.
  • The browser build is held to the same standard: 46 recorded scenarios, 8,454 requests, zero divergences between the WASM workbench and the Python one.

Details: parity-suite.md.

The AI

Fights: chance-node MCTS

Every combat decision is an MCTS search over the engine: 8,000 simulations per decision in the real game and the published win rates, 1,000 (4,000 at bosses) in training gates. Draws and monster rolls are chance nodes, not clairvoyance; leaves are scored by a 216-feature evaluation.

Everything else: PPO

Paths, card rewards, removals, upgrades, transforms, enchantments, events, shops, rest sites and relic choices come from a transformer policy per character, trained with PPO by self-play over full runs in the simulator and served from Rust through ONNX.

Read more: How the AI plays (search, hidden information, the network) and How it's trained (PPO, compute, the promotion gate, what didn't work).

Run-AI champions: simulator win rate, mean over Ascension 0–10
CharacterWin ratePromotion gate (vs previous champion)
Defect76.1%+5.5 pp, p = 2e-6
Ironclad74.9%+5.2 pp, p = 1e-6
Silent59.9%+5.6 pp, p = 7e-7, all 11 ascension levels up
Regent53.8%+4.6 pp, p = 1e-4
Necrobinder51.7%+6.8 pp, p = 6e-10, all 11 levels up
Win rate (%) by ascension level, current champions, simulator
CharacterA0A1A2A3A4A5A6A7A8A9A10Mean
Defect9390928990.58587.5797039.22276.1%
Ironclad89.59592.59086.585867970391174.9%
Silent78.580777467.56465.56855.520959.9%
Regent67.577.573726659.5605143.515.66.253.8%
Necrobinder66.5737368.562.559.552.54944.513.85.651.7%

One fresh seed panel for all five champions, measured October 2026: 200 runs per cell at A0–A8 and 500 at A9–A10, the same seeds for every character, Act 1 rolled between Overgrowth and Underdocks. Combat search is honest (it does not see the draw pile order) at 8,000 simulations per decision, boss fights included, the advisor's budget. A cell's 95% interval is roughly ±6 pp in the middle of the range and ±2–4 pp at A9–A10. The cliff lines up with the game's own steps: A9 (Deadly Enemies) makes every enemy hit harder, and A10 (Double Boss) adds a second boss fight at the end of the run. Full write-up: docs/experiments/2026-10-11-release-winrates.md.

Every champion is promoted on a pre-registered gate: 200 seeds × 11 ascension levels = 2,200 paired runs against the incumbent, McNemar test, seed-clustered error check, and a guard that no single level may regress by more than 5 pp. Promotion records and provenance live next to the nets in sts2-pycli/data/ppo/.

In the real game

Driven through the Spire Mentor mod against the actual SlayTheSpire2.exe, random seeds, no cheats, 40 runs each at Ascension 8, with 8,000 simulations per combat decision. These runs used the champions deployed in August 2026; the current ones, above, have not been measured in the real game yet.

CharacterWinsWin rate95% CI
Ironclad13 / 4032.5%20–48%
Silent11 / 4027.5%16–43%

Browser workbench

The engine compiled to WebAssembly, running in a Web Worker behind a React UI styled after the game. No server: saves live in IndexedDB and the site installs as an offline app. Without the game it runs with the real card text and placeholder art; just import-game fills in the real art and sound from your copy.

What you can do

  • Play any character, seed and ascension yourself, or let the PPO champion play a whole run while you watch, then take over at any point.
  • Rewind and branch any decision; the run tree keeps every fork, with named saves.
  • Ask the AI: combat hint, the full MCTS search tree, rankings for card rewards, shops, events and rest sites, "play best". The live coach flags a weak move the moment you make it.
  • Autobattle: play Slay the Spire 2 as an autobattler. You make the run-level decisions (paths, cards, shops, events) and the AI fights every combat; each stop shows what changed since the last one.
  • Review a finished run to find its biggest blunders: regret per decision and win-probability-added over the whole run.
  • SimLab: a "what if" lab for a single fight. Set up any combat (character, deck, HP, relics, potions, enemies, ascension) and see the legal moves and what the search thinks of each. Replay the fight many times to see the spread of outcomes, so you can test a card, a relic or a line of play without reaching that spot in a real run.
  • Lab tools: replay viewer, MCTS-runs browser, deck analysis, and state import: paste a position copied from the live game and analyse it in the browser.

Run it: just workbench-local builds the site into sts2-pycli/web/dist and serves it on http://127.0.0.1:4173. With real art the build contains the game's images and sound, extracted from your copy for your own use, so please run it locally and don't host it publicly. Architecture: browser-workbench.md.

Spire Mentor: the AI inside the real game

A C# mod for Slay the Spire 2 that connects the running game to the AI stack over a local TCP socket. Installed but idle, it leaves the game vanilla. The advisor backend is launched by the mod and ships as a self-contained executable.

Play with it: subscribe on the Steam Workshop (Windows; Steam installs BaseLib with it). The workbench comes bundled and follows your run in the browser.

The real game with the Spire Mentor advisor panel: Taunt on Haunted Ship ranked first at +0.85 with 87% of 1,000 simulations, estimated win 92%
Combat advice in the real game: MCTS ranks every legal move, shows the principal line and estimates the chance to win the fight.
The real game's map with the advisor panel recommending the right-hand unknown room at 73% over a monster room at 27%
Route advice on the map: the run policy prefers the unknown room (73%) and the route is drawn over the map.
The AI beating Ironclad at Ascension 9 in the real game, through the Spire Mentor mod. The advisor panel at the top left shows the search's ranking of each move.

Advisor

You play. Ranked moves with MCTS statistics and the principal line, card-reward and shop scores, map routes, a win estimate.

AI turns & autopilot

Let the AI take one decision or play until you stop it; autopilot plays whole runs unattended and never falls back to random play.

Rewind

Every room is snapshotted with its RNG state. Undo a turn, restart a room, or go back to any earlier room, bit-exact.

Workbench link

Open the current state in the workbench, browse the live game's tree, and rewind the real game from the page.

Controls
KeyAction
F1Help panel: mode, keys, file locations
F3Action log
F4Advisor overlay on/off
F6AI takes this one decision
F7AI plays until you stop it
F8Advisor mode on/off
F9 / F10Game speed − / +
Ctrl+ZUndo to the start of the combat turn
Ctrl+Shift+ZRestart the room

Every key is also on the in-game toolbar, and the settings live on a mod-configuration page in the main menu.

Install

Players: subscribe on the Steam Workshop. To build it yourself: Windows, the game at v0.107.1, the .NET 9 SDK and BaseLib in the game's mods/ folder. Then cd spire-mentor-mod && dotnet build builds the mod and installs it into mods/SpireMentor/. Configuration, the console commands and the wire protocol are in spire-mentor-mod/README.md and PROTOCOL.md.

Getting started

Three tiers; each needs a little more than the last.

1 · Engine only

No game needed. Rust 1.96, cargo-nextest, just 1.38+.

just rs-check
just rs-test        # cargo nextest run --workspace
just rs-doc-test

2 · Parity oracle

Adds your game install, the .NET 9 SDK and uv.

just import-game "/path/to/Slay the Spire 2" --tier oracle
cd sts2-pycli && uv sync --dev
just build-cs && uv run pytest tests

3 · Workbench with real art

Adds ilspycmd, Node 20+, the wasm32-unknown-unknown target and wasm-bindgen-cli 0.2.120.

just import-game "/path/to/Slay the Spire 2"
just workbench-local   # → http://127.0.0.1:4173

Use cargo nextest, never bare cargo test: tests rely on per-process isolation. Full prerequisites: bring-your-own-game.md; Windows: the engine tier runs from PowerShell, the rest under WSL2 (BUILDING-WINDOWS.md).

Repository map

PathWhat it is
sts2-rs/Rust: engine, content, MCTS, run-AI, CLI, PyO3 bindings, workbench engine (WASM)
sts2-pycli/Python, C# and TypeScript: the headless C# oracle, parity suite, PPO training, the workbench web app, the real-game advisor, an MCP server so an LLM can play
spire-mentor-mod/C#: the Spire Mentor mod
sts2-wiki/Python / Astro: decompile, extract, generate a static wiki
scripts/import_game.pyjust import-game: every game-derived input from your install
docs/Reference docs, ADRs, this site (docs/site/)

Start with ARCHITECTURE.md, then CONTRIBUTING.md. Training a run policy? Read the champion training playbook first.

Game content & legal

Slay the Spire 2 is © Mega Crit. This project is not affiliated with or endorsed by Mega Crit. The repository carries the game's text and extracted data so the engine, the AI and the workbench work out of the box, but no art, audio, game assemblies or decompiled code. The tooling extracts those from a copy of the game you own, into git-ignored paths. The screenshots on this page show the game's art.

The original work is MIT-licensed. sts2-pycli began as a fork of wuhao21/sts2-cli; Spire Mentor started as a port of zhiyue's STS2BridgeMod from zhiyue/sts2-rl-agent. See NOTICE and PROVENANCE.md.