Headless Disney Lorcana TCG analytics engine. Simulates thousands of games to produce deck analytics, win rates, and card performance data.
Not a human-playable simulator — built for quantitative deck analysis.
# Prerequisites: Node >=20, pnpm >=9
pnpm install
# Run all tests
pnpm test
# Start the UI
pnpm dev # http://localhost:5173All commands run from the repo root. Deck files live in decks/, query files in sims/.
pnpm analyze -- --deck ./decks/set-001-ruby-amethyst-deck.txt --bot greedy --iterations 1000Runs the deck against itself and prints win rate, average game length, and per-card performance stats.
pnpm compare -- --deck1 ./decks/set-001-ruby-amethyst-deck.txt --deck2 ./decks/goldfish-deck.txt --bot greedy --iterations 500pnpm compare -- --deck1 ./decks/set-001-ruby-amethyst-deck.txt --deck2 ./decks/goldfish-deck.txt --bot greedy --iterations 500The goldfish deck is 60 uninkable cards — the opponent can never ink or play anything and just passes every turn.
# One-shot: simulate + query
pnpm query -- --sim sims/set-001-ruby-amethyst/sim.json --questions sims/set-001-ruby-amethyst/turn3-questions.json
# Save results for later
pnpm query -- --sim sims/set-001-ruby-amethyst/sim.json --questions sims/set-001-ruby-amethyst/turn3-questions.json --save results/ruby-amethyst.json
# Re-query saved results instantly
pnpm query -- --questions sims/set-001-ruby-amethyst/turn3-questions.json --results results/ruby-amethyst.jsonAsk condition-based questions like "how often is Magic Broom played on T2, and what's the win rate when it happens?" See docs/QUERY_SYSTEM.md for the full condition language.
All commands that run simulations support --save ./path.json to persist results for later querying:
pnpm analyze -- --deck ./decks/set-001-ruby-amethyst-deck.txt --bot greedy --iterations 5000 --save results/ruby-amethyst.json
pnpm query -- --questions sims/set-001-ruby-amethyst/turn3-questions.json --results results/ruby-amethyst.json| Name | Style |
|---|---|
random |
Uniformly random legal action (baseline) |
greedy |
Fixed priority: quest > favorable challenge > play card > ink > pass |
rl |
Trained neural network policy — requires --policy <path> |
Plain text, one entry per line. Lines starting with # or // are comments.
4 HeiHei - Boat Snack
4 Stitch - New Dog
4 Simba - Protective Cub
# This is a comment
4 Minnie Mouse - Beloved Princess
Card names must match the Lorcast card database (case-insensitive). Use the full
Name - Title format.
pnpm devOpens at http://localhost:5173. Five screens:
| Screen | What it does |
|---|---|
| Deck Input | Paste a decklist, validate it, load the sample deck |
| Composition | Cost curve, ink colors, inkable probability by turn, card types |
| Simulate | Mirror match simulation with card performance breakdown |
| Compare | Two-deck head-to-head matchup |
| Weight Explorer | Tune bot weight sliders, compare against preset strategies |
All simulations run in-browser — no server needed.
packages/
engine/ Pure game rules. No UI, no bot logic.
simulator/ Game loop + bots. Imports engine only.
analytics/ Aggregation + composition. Imports engine + simulator.
cli/ Terminal commands. Imports analytics only.
ui/ React + Vite. Imports analytics only.
decks/ Sample decklists (.txt)
sims/ Query sim configs + question files (.json)
Set 1 (The First Chapter): 216 cards total, 106 fully implemented, 110 stubs. Stub cards are playable as vanilla characters — their named abilities just don't trigger yet. Keyword-only cards (Rush, Evasive, Bodyguard, etc.) work correctly.
pnpm test # all packages (engine: 49 pass + 5 todo, simulator: 3, analytics: 15)
pnpm test:watch # engine TDD mode
pnpm typecheck # known errors in cli (missing @types/node) only