a research devlog · est. 2026 · solo build

INSCRYPTION· KCM · AI

An RL agent for Kaycee's Mod, in build. Validated Rust simulator complete and surfacing actionable play patterns; warm-start training data generated; agent training next. The most transferable artefact so far: a framework for parallel agentic workflows.

Phase 1.6 — L6a four-boss validationPhase 1.8 warm-start training run · complete$0 / $80spent / cap
Algorithm
AlphaZero-style IS-MCTS + distilled neural network, fine-tuned with PPO self-play
Simulator
Rust + PyO3 bindings, validated against the live game via a BepInEx bridge mod

About the game

Why Inscryption — and specifically Kaycee's Mod — is the target.

Inscryption (2021) is a roguelike deck-building card game by Daniel Mullins Games, published by Devolver Digital. It won Game of the Year at the 2022 Game Developers Choice Awards and the Seumas McNally Grand Prize at the Independent Games Festival, selling over a million copies in its first three months.

The game presents itself as found footage — a mysterious floppy disk containing a tabletop card game played against a shadowy figure named Leshy in a dimly lit cabin. Act 1 is a self-contained roguelike: build a deck of creatures, navigate a procedurally generated map, and fight through three bosses before a climactic encounter with Leshy himself.

I.aHow the card game works — grid, scale, blood, bones, sigils

Combat takes place on a 3×4 grid — four slots per side. The goal is to tip a weighing scale by five damage points in your favour. Cards attack the opposing slot every turn; excess damage carries over to the scale.

Resource costs

  • Blood. Sacrifice your own creatures to pay the blood cost of a new card. A Squirrel (0/2, no abilities) is always free fodder.
  • Bones. Generated when your creatures die. Bone-cost cards reward aggressive play and death loops.

Sigils

Each card carries one or more sigils — passive or triggered abilities. Examples: Flying (only blocked by Reach), Bifurcated Strike (attacks two slots), Touch of Death (kills any card in one hit), Unkillable (returns to hand on death). Act 1 has 48 distinct sigils; their interactions — totems, evolved cards, cardmod stacks — are where most of the strategic depth lives.

I.bRun structure — branching map, candles, node types

Between combats players navigate a branching map across three regions. Death costs a candle; you start with two lives.

  • Combat. Standard encounter.
  • Card reward. Choose one of three cards to add to your deck.
  • Campfire. Upgrade a card's ATK or HP. Repeated attempts risk failure.
  • Trader / Trapper. Trade pelts (earned from kills) for cards.
  • Shop. Buy or sell cards and single-use items (Hammer, Pliers, Scissors).
  • Mycologists. Merge two cards into one.
  • Totem builder. Attach a sigil to an entire creature tribe for the rest of the run.
I.cKaycee's Mod — the scope target

Kaycee's Mod (KCM) is an official post-release expansion bundled free with Inscryption, named after the game's lead programmer. It strips away the metafictional narrative of Act 1 and turns the card game into a pure roguelike challenge mode — the game as a game, not as a horror story.

What KCM adds

  • Challenge modifiers. Unlocked progressively. Single Candle, Tipped Scales, No Hammer, Brutal Hunt, Bones Bummer, Boss Tougher, and more — stackable, with a difficulty score.
  • Full Act 1 card pool. All cards available in the reward pool, including rare/powerful cards uncommon in a single Act 1 playthrough.
  • All four bosses. Prospector, Angler, Trapper/Trader, and a multi-phase final encounter with Leshy (Moon card and starvation overrides).
  • Consistent rules. Unlike Act 1, narrative events do not override game logic. KCM is deterministic.

KCM with all challenges active simultaneously, full card pool, all four bosses, is the scope target for this project.

I.dWhy Inscryption is a strong research platform

Decompilable, auditable rules

Inscryption is a Unity game shipped with C# managed code. Game logic lives in Assembly-CSharp.dll and decompiles cleanly with ilspycmd / dnSpy. For this project, 2,098 classes were decompiled and 12 key behaviour classes were read in full. The simulator is built from the source of truth — not reverse-engineered from gameplay observations. Every hardcoded exception, every sigil-interaction edge case, every boss AI decision is documented with a DLL citation. That fidelity is unusual in game-AI research and eliminates an entire class of simulator bugs.

Active modding community

Inscryption has a large, technically capable modding community centred on InscryptionAPI — a BepInEx-based framework that exposes hooks into the game's event loop. This project uses the same infrastructure: a BepInEx validation mod reads live game state mid-run, exports it to JSON, and is used to verify that the Rust simulator produces identical results to the real game. CommunicationMod served as the template for the validation bridge.

Tractable complexity at the right scale

Not too simple — 126 cards, 48 sigils, stochastic draws, branching map, multi-phase bosses, 10+ challenge combinations, and tightly coupled deck-building / combat decisions. No known AI plays it at strong human level. Not too expensive — a full run simulates in milliseconds on laptop CPU; MCTS data generation needs zero cloud spend, GPU fine-tuning is estimated at $30–50 total. Coupled decisions — the key unsolved problem in Inscryption is that card-reward and combat decisions are bidirectionally coupled. Slay-the-Spire RL work reportedly failed to discover this coupling when treating the two separately. This project models them jointly via MCTS over full runs with a single shared-trunk neural network.

The approach

MCTS over full runs as the data engine; a small distilled NN as the policy; PPO self-play as the polish.

I'm building this because nobody has done it. There's no published RL agent for Kaycee's Mod, and the game's coupling of meta-game and combat decisions broke the only large-budget Slay-the-Spire attempt I'm aware of.

The wager: MCTS over full runs on a laptop CPU is free; it generates clean training signal that handles the coupling correctly. Distill into a small NN, fine-tune with PPO self-play on a single spot GPU. Total budget cap: $80.

Goal isn't "a bot that wins." Goal is novel play patterns and calibrated coaching — a tool that says "play Wolf in slot 2, opponent queues Stoat opposite, scale tips +2" and is right 70% of the time when it says 70%.

Algorithm
AlphaZero-style

IS-MCTS over full runs — deck-building and combat as one decision space — distilled into a small shared-trunk NN, then fine-tuned with PPO self-play.

Simulator
Rust + PyO3

Built from the decompiled DLL, not from gameplay observation. A BepInEx bridge mod validates Rust against the live game on every level transition.

Budget
$80 hard cap

$0 through Phase 3 (laptop CPU). $30–50 of GPU spot time for PPO. $2–10 for warm-start LLM calls. Buffer covers overruns.

Project phases

Six phases · $0 → $80 · roughly twenty weeks. Click any phase for detail; click a sub-phase for its key work and acceptance gate.

P0
Phase 0

Mechanics Audit & Architecture

$0complete · 2026-04-20L0complete

Establish ground-truth rule documentation and lock irreversible architecture decisions before any code is written.

Detail · key work, gate, outputs
Hardware
Laptop
Outputs
  • docs/rule-reference.md — 1,247 lines, 48 sigils with DLL citations
  • docs/MECHANICS-AUDIT.md, MECHANICS-COVERAGE-MATRIX.md, MECHANICS-VALIDATION-SUMMARY.md
  • docs/TRAINING-ARCHITECTURE-DECISIONS.md (8 ADRs)
  • sim/ (L0 simulator scaffold)
Phase gate. L0 acceptance ≥ 80%. BepInEx bridge validated vs live game. All [VERIFY] markers in rule-reference.md resolved.
Sub-phases
Phase 0.1DLL Decompilationcomplete

Full decompile of Assembly-CSharp.dll (2,098 classes) via ilspycmd. Grep passes for hardcoded exceptions, persistent state mutations, KCM-specific code paths.

Phase 0.2Mechanics Coverage Auditcomplete

Systematic audit of all 52 sigils (48 documented with DLL citations; 4 data-driven). 23 hardcoded exceptions identified and mapped to simulator rules.

Phase 0.3Architecture Decision Recordscomplete

Lock irreversible decisions: simulator language (Rust), algorithm (IS-MCTS), card encoding (feature-vector only), policy structure (hierarchical), warm-start strategy, GPU provisioning.

Phase 0.4L0 Simulatorcomplete

Fixed deck, scripted opponent, ~8 sigils, PyO3 bindings. Prove the Rust/PyO3 stack before full implementation.

P1
Phase 1

Simulator — L1 → L6b

$06–10 weeks totalL1 → L6bin progress

Complete, bridge-validated Rust simulator from L1 through L6b — full Kaycee's Mod with all challenges active.

Detail · key work, gate, outputs
Hardware
Laptop
Outputs
  • sim/kcm-sim/src/ (complete Rust simulator)
  • sim/kcm-sim/src/card_registry.json (126 cards)
  • acceptance gate scripts (l1_acceptance_gate.py, l4_acceptance_gate.py, l6b_acceptance_gate.py)
Phase gate. All Phase 1.7 sim-completeness criteria met (see L6b gate). Hard block on Phase 2.
Sub-phases
Phase 1.1L1Single combat with draws1–2 weekscomplete

Real deck draws, heuristic opponent, 6 new sigils — makes isolated combat stochastic and meaningful.

Key work
  • init_l1_game() and draw_phase()
  • Heuristic opponent
  • Sigils: SharpQuills, LooseTail, Unkillable, Strafe, Sniper, CorpseEater
  • l1_acceptance_gate.py
Gate. All Rust unit tests pass; each L1 sigil has passing test; greedy 30–80% win rate vs heuristic; bridge ≥ 5 live states; throughput ≥ 200 eps/sec; L0 regression ≥ 80%.
Phase 1.2L2Multi-fight runs1–2 weekscomplete

Persistent deck state, candle/lives system, side deck — models a complete multi-fight run.

Key work
  • RunState struct (deck, candles, bones, items, seed)
  • Combat-chain persistence
  • CardModificationInfo stack
  • Side deck (unlimited Squirrel)
  • Starvation mechanic
  • 2 → 1 → 0 candle death sequence
Gate. Greedy agent completes 10-fight run > 50% of attempts.
Phase 1.3L3Card rewards & linear progression~1 weekcomplete

Deck growth via card rewards and evolution — enables a complete linear run.

Key work
  • CardChoiceNode (3 cards from pool, pick 1)
  • Full card-registry.json for reward-eligible cards
  • Evolve mechanic (Stoat → Stinkbug)
  • Ice Cube spawn on death
  • Linear run skeleton (fight → reward → fight)
Gate. Agent completes L3 linear run end-to-end without crash.
Phase 1.4aL4aBranching map · combat nodes~1 weekcomplete

Seeded map generation with branching node selection — run-path decisions become real.

Key work
  • Map generation (3 regions × ~14 nodes, branching, seeded RNG)
  • ChooseMapNode action type
  • completed_nodes BitSet on RunState
  • Node traversal state machine
Gate. Agent navigates map to each region's boss node without crash.
Phase 1.4bL4bNon-combat nodes~1 weekcomplete

Campfire, shop, and trader nodes with full decision surfaces.

Key work
  • CampfireNode (ATK/HP upgrade with failure risk)
  • ShopNode (buy/sell cards and items)
  • TraderNode (pelt trading for cards)
  • ActivateItem action in combat
Gate. Agent can reach each boss node via map and enter combat from each node type.
Phase 1.4cL4cMeta systems · bones, items, totems~1 weekcomplete

Bones economy, usable items in combat, totem builder node — largest action-space expansion in Phase 1.

Key work
  • Combat items: Hammer, Pliers, Scissors, Moose Antlers, Steak Dagger, remainder
  • Totem builder node (tribe + sigil → whole-run buff)
  • Bones wiring across run scope
Gate. Agent can navigate map, activate items in combat, and reach each boss.
Phase 1.5aL5aCore card subset · ~30 cards, ~10 sigils~4–5 dayscomplete

Validate the full pipeline with a representative card subset before full-pool complexity.

Key work
  • Mycologists merge node
  • Bone Lord node
  • Totem builder functional with subset
  • Hardcoded exceptions for subset cards
Gate. 5,000 random-action runs without crash.
Phase 1.5bL5bFull card pool · 126 cards, 48 sigils1–2 weekscomplete

All 126 cards and all 48 sigils implemented, tested, and interaction-validated.

Key work
  • Full card_registry.json loaded
  • All 48 sigils with unit tests
  • Stat icons: Ant count, Hand size, Bell proximity, Bones held, Mirror
  • Hardcoded exceptions: Daus slot pattern, HydraEgg transform, Ijiraq repulsive, Shapeshifter, Cat counter
  • All 27 CardModificationInfo fields handled
Gate. All 48 sigil unit tests pass; 5,000 random-action full runs without crash.
Phase 1.6L6aAll four bosses1–2 weeksin progress

All four boss encounters with phase transitions and boss-specific AI. Currently validating.

Key work
  • Prospector — Phase 1 standard; Phase 2 PickAxe + Pelt reward
  • Angler — Phase 1 standard; Phase 2 BaitBucket + Hook theft
  • Trapper/Trader — Phase 1 standard; Phase 2 trader mid-fight
  • Leshy — Phase 1 standard; Phase 2 Death card; Phase 3 Moon + starvation
  • Boss AI scripted per phase
  • Integration tests for all boss phase transitions
Gate. Greedy agent completes a full L6a run (all bosses) > 20% of attempts; bridge ≥ 5 live states per boss phase.
Runs in parallel with Phase 1.8.
Phase 1.7L6bChallenge modifiers — full KCM~1 weekfuture

Full challenge modifier system — all KCM challenges active simultaneously. This is the hard block on Phase 2.

Key work
  • ChallengeFlags bitmask on RunState
  • Per-challenge implementations: Tipped Scales, Single Candle, No Hammer, No Sniper, Brutal Hunt, Tougher Hunt, Bones Bummer, Boss Tougher, Limited Lives, remainder
  • apply_challenges() PyO3 binding
  • 20 curated challenge combination tests
  • Zobrist state hashing
  • Throughput verification ≥ 100 full runs/sec
Hard block on Phase 2 — all of the following must pass:
  • All challenges active; greedy runs complete without crash
  • All 48 sigil unit tests pass
  • Bridge round-trip ≥ 20 distinct live states
  • Full-run determinism: 1,000/1,000 same-seed runs produce identical outcomes
  • Heuristic vs heuristic at L6b: win rate 30–70%
  • All prior acceptance gates pass (L0, L1, L4, L6b)
  • All boss phases end-to-end
  • 20 curated challenge combinations tested
  • Throughput ≥ 100 full runs/sec
  • 10,000 random-action fuzz: zero panics, zero infinite loops
P1.8
Phase 1.8 · optional · parallel: 1.6, 2

Warm-Start Behavioural Cloning

$2–103–5 days · run completeL6bcomplete

Pre-generate an initial policy baseline via cheap LLM API to reduce Phase 2 MCTS warm-up time. The training run is complete.

Detail · key work, gate, outputs
Hardware
Laptop + OpenRouter API
Acceptance gate. Cheap-model policy accuracy > 40% on held-out states (baseline greedy ~30%); value MSE < 0.20; dataset importable into Phase 2.
Outputs
  • guard.py with resolve_provider() routing to OpenRouter (Mistral/Llama, ~$0.14 / 1M tokens)
  • Synthetic rollout pipeline (random/greedy games → LLM action ranking → soft distribution)
  • Dataset target: 500k positions minimum / 5M positions primary
P2
Phase 2

MCTS Data Generation

$02–4 weeks of overnight runsL6bfuture

Generate a large dataset of (game state, action distribution, win probability) triples via pure MCTS on laptop CPU.

Detail · key work, gate, outputs
Hardware
Laptop CPU (rayon, 4–8 threads)
Prerequisite
All Phase 1.7 / L6b sim-completeness criteria.
Acceptance gate. MCTS (200 sims) beats greedy 70%+ in 500 combat episodes; full-run win rate > 25% over 500 runs; value estimates calibrated.
Configuration
Rollout policy
heuristic-greedy
Sims / move
200–800
Selection
PUCT + progressive widening
Transposition table
Zobrist hashing
IS determinization k
5
Data targets
TierPositionsTimeline
minimum viable1M1–2 nights
primary target10M1–2 weeks
extended (only if value head struggles)50M+extended
P3
Phase 3

Distillation — small NN from MCTS labels

$0–153–5 daysL6bfuture

Train a small neural network to approximate the MCTS action distribution and win probability.

Detail · key work, gate, outputs
Hardware
Laptop or modest GPU
Acceptance gate. Value MSE < 0.05; policy top-1 accuracy > 50%; live win rate vs heuristic > 30%; if not met after 5 epochs return to Phase 2.
NN architecture
Input
~500–800 floats
Trunk
3-layer MLP or small transformer, ~300K–500K parameters
Policy head
softmax over legal actions
Value head
scalar win probability
Encoding
feature-vector only — attack/health/cost/sigil bitmask/tribe one-hot · never card-ID lookup
Training
Loss
CE(policy) + MSE(value)
Optimiser
Adam · lr 1e-3 cosine decay
Batch size
512–2,048
P4
Phase 4

Self-Play Fine-Tuning · PPO

$30–502–3 days wall-clockL6bfuture

Improve the distilled model via PPO self-play to discover patterns beyond heuristic-rollout MCTS.

Detail · key work, gate, outputs
Hardware
GPU spot · Vast.ai / RunPod RTX 4090 (~$0.35/hr)
Cost cap
$80 total including buffer
Algorithm
PPO + past-checkpoint opponent pool + entropy bonus 0.01 + 128-unit LSTM
Acceptance gate. Win rate > 60% vs heuristic at L6b over 500 eval runs; OR $80 budget cap; OR 3 consecutive plateau evaluations.
Curriculum
StageConfigurationConditionTarget
4.1L6a (no challenges)baselinewin rate > 30%
4.2+Tipped Scalesafter 4.1 gatewin rate > 25%
4.3+Single Candleafter 4.2 gatewin rate > 20%
4.4All challenges (L6b)after 4.3 gatebudget exhausted or plateau
Operational
Checkpoint interval
15 min
Eval interval
1 hr
Eval episodes
500
P5
Phase 5

Inference & Coaching Deployment

$0~1 weekL6bfuture

Deploy trained agent as an in-game coaching tool with real-time win probability, best-move suggestions, and on-demand deep analysis.

Detail · key work, gate, outputs
Hardware
Laptop
Integration
BepInEx bridge mod → JSON export → Python inference script → CLI or HUD injection.
Acceptance gate. Win probability calibrated within ±10% of actual win rate on 200 held-out live positions; deep analysis latency < 5s on laptop.
Inference modes
ModeMechanismLatency
Real-time overlayNN value head< 10 ms
Best-move suggestionNN policy top-3< 100 ms
Deep analysisMCTS · 200–800 sims1–5 s
CounterfactualNN value on hypothetical< 100 ms
LLM explanation layer (MCTS trace → natural language) — out of scope but architecturally enabled.

Scope ladder · L0 → L6b

Each rung is its own acceptance gate. Lit candles are passed; the flickering candle is L6a — currently validating.

L0
Single combat · fixed deck
P0
L1
Real draws · heuristic opponent
P1.1
L2
Multi-fight runs · candles · side deck
P1.2
L3
Card rewards · evolve · Ice Cube
P1.3
L4a
Branching map · combat nodes
P1.4a
L4b
Campfire · shop · trader
P1.4b
L4c
Bones · items · totems
P1.4c
L5a
~30 cards · ~10 sigils subset
P1.5a
L5b
Full pool · 126 cards · 48 sigils
P1.5b
L6a
All four bosses · multi-phase
P1.6
L6b
All challenges stacked
P1.7
L0
Single combat · fixed deckPhase 0
Gate. 100% win-rate · 100/100 episodes
complete
L1
Real draws · heuristic opponentPhase 1.1
Gate. Greedy 30–80% vs heuristic
complete
L2
Multi-fight runs · candles · side deckPhase 1.2
Gate. 10-fight run > 50%
complete
L3
Card rewards · evolve · Ice CubePhase 1.3
Gate. Linear run end-to-end
complete
L4a
Branching map · combat nodesPhase 1.4a
Gate. Reach each region's boss
complete
L4b
Campfire · shop · traderPhase 1.4b
Gate. Each node type → combat
complete
L4c
Bones · items · totemsPhase 1.4c
Gate. Items active in combat
complete
L5a
~30 cards · ~10 sigils subsetPhase 1.5a
Gate. 5k random-action runs · no crash
complete
L5b
Full pool · 126 cards · 48 sigilsPhase 1.5b
Gate. All sigil tests · 5k fuzz
complete
L6a
All four bosses · multi-phasePhase 1.6
Gate. Greedy full run > 20%
in progress
L6b
All challenges stackedPhase 1.7
Gate. Calibrated 30–70% h-vs-h · hard block on Phase 2
future

Architecture

Sim ↔ MCTS ↔ Distill ↔ Self-play. The bridge mod keeps the simulator honest; warm-start BC seeds the policy.

validaterolloutslabelsdistillseedwarm-startfine-tunerolloutsdeployBepInEx BridgeValidationBridge.dllRust Simulatorkcm-sim · PyO3Warm-Start BCOpenRouter LLMIS-MCTSPUCT · k=5Position Dataset(state, π, v)Shared-Trunk NNpolicy + valueSelf-Play PPOPPO · LSTMCoaching HUD<10ms · NN forward

Acceptance gates

Every level has a gate. The L6b composite gate is the hard block on Phase 2.

L0
L0 acceptance
100/100 eps · 24 turns deterministic · ~410 eps/sec
passing
L1
L1 acceptance
Loose Tail · Strafe · Sniper · 30–80% win-rate band hit
passing
L2
L2 acceptance
10-fight greedy run > 50%
passing
L3
L3 acceptance
Linear run end-to-end · no crash
passing
L4
L4 acceptance (a/b/c)
Map + non-combat + items integrated
passing
L5
L5 acceptance (a/b)
All 48 sigil tests pass · 5k fuzz clean
passing
BR
BepInEx bridge round-trip
≥ 5 live states / boss phase under L6a · in progress
in progress
L6a
L6a acceptance
All 4 bosses · greedy full run > 20% target
in progress
WARM
Warm-Start BC dataset
Training run complete · accuracy > 40% on held-out · value MSE < 0.20
passing
FUZZ
10k random-action fuzz
L6b gate · zero panics · zero infinite loops
todo
ZOB
Zobrist state hashing
Required for MCTS transposition · L6b gate
todo
DET
Full-run determinism
1,000/1,000 same-seed identical outcomes · L6b gate
todo

Mechanics coverage

47 of 48 sigils implemented and unit-tested. Audited line-by-line against Assembly-CSharp.dll.

Combat
14 of 14 implemented
100%
Bifurcated Strike · Trifurcated · Sharp Quills · Sniper · Mighty Leap
Spawn
7 of 7 implemented
100%
Loose Tail · Bone King · Hoarder · Many Lives · Fledgling
Stat icons
5 of 5 implemented
100%
Ant count · Hand size · Bell prox. · Bones held · Mirror
Tribe
6 of 6 implemented
100%
Bee · Avian · Reptile · Canine · Insect
Hardcoded
6 of 7 implemented
86%
Hodag · Ijiraq · HydraEgg · Daus · Shapeshifter
Passive
9 of 9 implemented
100%
Buff Neighbours · Cultist · Flying · Reach · Worthy Sacrifice

Budget

Hard cap $80. Spent so far: $0. Most of the budget is reserved for a single GPU spot run during PPO self-play.

Cloud spend · running total$0 / $80
Phase 0 — Mechanics audit
$0–$0
Phase 1 — Simulator (1.1 → 1.7)
$0–$0
Phase 1.8 — Warm-start BC
$2–$10
Phase 2 — MCTS data gen
$0–$0
Phase 3 — Distillation
$0–$15
Phase 4 — Self-play PPO (GPU)
$30–$50
Phase 5 — Coaching
$0–$0
Buffer
$5–$15

Up next & references

Active work this week and the documents this devlog draws from.

Up next · this week
  • Leshy phase 3 — Moon + starvation override boss/leshy.rs · 2d
  • Bridge round-trip · Prospector P2 (PickAxe) ValidationBridge · 1d
  • Bridge round-trip · Angler P2 (Hook theft) ValidationBridge · 0.5d
  • L6a integration tests — all phase transitions tests/l6a_bosses.rs · 2d
  • Gate script — l6a_acceptance_gate.py scripts/ · 1d
Inscryption KCM AI · devlog · last updated 2026-05-09 · github.com/4abandoment/inscryption-kcm-ai