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: 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
Kind
Count
Notes
Characters
5
Ironclad, Silent, Defect, Regent, Necrobinder
Cards
580
card ids incl. colorless, status and curse cards
Relics
297
Potions
63
Powers
272
Monsters
121
with their intent state machines
Events
69
incl. the Ancients
Acts
3
4 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.
Measurement
Result
Random-play fights per second, one core
59,400
Engine actions per second, same fights, one core
1.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 throughput
1,500× per core 2,430× whole machine
Against the shipped game, CPU time per action
2,970× (2,250× its game thread)
Against the previous engine (12 Oct 2026), same fights
2.25×
Against two other simulators, same random-play fights, one core
3.13× faster than sansb sts2core 1.56× faster
Browser hint's search, 1,000 simulations
13.7 ms native 18.4 ms WASM in Chromium
Browser hint at its default 2,000 simulations, WASM in Chromium
39.9 ms
Advisor's search on an Act-1 boss, 8,000 simulations
275 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:
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.
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
Character
Win rate
Promotion gate (vs previous champion)
Defect
76.1%
+5.5 pp, p = 2e-6
Ironclad
74.9%
+5.2 pp, p = 1e-6
Silent
59.9%
+5.6 pp, p = 7e-7, all 11 ascension levels up
Regent
53.8%
+4.6 pp, p = 1e-4
Necrobinder
51.7%
+6.8 pp, p = 6e-10, all 11 levels up
Win rate (%) by ascension level, current champions, simulator
Character
A0
A1
A2
A3
A4
A5
A6
A7
A8
A9
A10
Mean
Defect
93
90
92
89
90.5
85
87.5
79
70
39.2
22
76.1%
Ironclad
89.5
95
92.5
90
86.5
85
86
79
70
39
11
74.9%
Silent
78.5
80
77
74
67.5
64
65.5
68
55.5
20
9
59.9%
Regent
67.5
77.5
73
72
66
59.5
60
51
43.5
15.6
6.2
53.8%
Necrobinder
66.5
73
73
68.5
62.5
59.5
52.5
49
44.5
13.8
5.6
51.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.
Character
Wins
Win rate
95% CI
Ironclad
13 / 40
32.5%
20–48%
Silent
11 / 40
27.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.
A hint 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 MCTS search tree for that position, as an outline: the most-visited line expanded through chance nodes (the possible draws), with visits, Q values and predicted outcomes.The live regret coach flags a move as you make it: Shrug It Off (87%) instead of drinking Beetle Juice (98%).The act-1 map with the planned route to the boss and the run policy ranking the next room.A card reward: each pick with its effect on the deck and a rollout act-win rate; the run policy's own pick probabilities below.The opening Neow event: act-win rate over rollouts for every option.The shop with an act-win estimate under every card, potion and relic.After a rewind: the run tree forks at a card reward, and both branches stay playable.Deck analysis: damage, block and velocity profile with warnings (“energy-limited”, “deck clogged with basics”).Watch the AI play: the PPO champion and MCTS playing a Silent run live, here at the act-1 boss.…and winning it: 45 floors, 29 cards, 15 relics, with the replay one click away.The replay viewer: scrub any recorded run step by step and “play from here”.Post-combat regret review: every decision re-searched, the costliest plays listed first.Run review: the outlook-score curve over a whole run, with the turning points and a re-check for each.SimLab: build any combat position by hand, then search it in the browser.A SimLab study: damage-taken distributions of four strategies over 30 seeds each.Start a run: any character, seed and ascension, played yourself or by the AI.
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.
Combat advice in the real game: MCTS ranks every legal move,
shows the principal line and estimates the chance to win the fight.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
Key
Action
F1
Help panel: mode, keys, file locations
F3
Action log
F4
Advisor overlay on/off
F6
AI takes this one decision
F7
AI plays until you stop it
F8
Advisor mode on/off
F9 / F10
Game speed − / +
Ctrl+Z
Undo to the start of the combat turn
Ctrl+Shift+Z
Restart 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).
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.py
just import-game: every game-derived input from your install