mtg/decks/reaper-king-no-more/decks/README.md
mark rosenberg d4a8a587f0 Restructure into a multi-deck engine; generalize tools/ off Jund/Reaper hardcodes
Migrates the reaper-king-no-more proof of concept into decks/reaper-king-no-more/
as the first deck under a shared tools/ engine, so the repo can hold many
Commander decks instead of one implicit one.

- tools/deckctx.py: new shared DeckContext, resolves --deck / $MTG_DECK / cwd,
  loads a deck's config.yaml, and derives color identity from the commander's
  own card data (never a hardcoded color combination).
- cards.py: drop the JUND=frozenset("BRG") constant; jund_legal() renamed to
  identity_legal(card, identity); DB() takes an explicit blacklist_path since
  the blacklist is per-deck, not shared.
- combos.py, roles.py, similar.py, similar_text.py, bracket_check.py: take
  --deck, use the deck's real identity instead of Jund/BRG.
- power.py, card_stats.py, forge_report.py: OURS deck-name constant now comes
  from the deck's config (name: / commander), matched via DeckContext instead
  of hardcoded "Reaper King No More".
- to_dck.py, batch_run.py, ab_test.py: .dck filename and [metadata] Name= are
  derived from the deck (slug / config name), not a hardcoded "reaper.dck".
- generate.py: RECIPES and make_variants.py's VARIANTS (deck-specific
  hypotheses) moved out of Python into decks/reaper-king-no-more/variants.yaml;
  protected cards now come from config.yaml's protected: list instead of a
  hardcoded set.
- New tools/mtg dispatcher: `tools/mtg decks/<name> <tool> [args...]` runs any
  tool against any deck without cd-ing into its directory.
- data/ (Scryfall/MTGJSON/Spellbook bulk, ~1.2GB, gitignored) and embeddings.npz
  move to the repo root as shared, commander-format-wide data.
- docs/howto.md: moved from the deck dir (it documents the tool, not the deck)
  and updated its example commands to the real generalized CLI.
- README.md: rewritten to describe the multi-deck repo and point at
  decks/reaper-king-no-more as the reference example.

Verified after the change: bracket_check, combos, and roles against
reaper-king-no-more reproduce the exact PASS/11-combos/role-profile numbers
from before the move; generate.py --list now loads recipes from YAML;
make_variants.py reproduces all 7 hand-curated variants including the
mikaeus FAIL control case; to_dck.py derives the right Name= and filename;
variant.py and compare.py reproduce decks/README.md's original numbers
exactly. The original POC at ~/mtg/reaper-king-no-more is untouched.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QPKgLYpMR8szWNFXyK1XNu
2026-09-12 00:37:42 -04:00

3.9 KiB

decks/

Forge simulation results and deck analysis, one directory per archetype variant.

Each variant is a hypothesis: change a few cards, then measure what it does to legality, combo density, and win rate. Every file here is generated — see regenerating below.

variants

variant bracket 3 vacuum combos combos sac outlets cmdr synergy lands avg MV Forge win rate
no-mikaeus/ ⭐ PASS 0 11 8 6 36 3.02 29% (24g)
fast-ramp/ PASS 0 11 8 6 36 2.84 33% (6g)
lean-outlets/ PASS 0 10 5 7 36 2.97 —
commander-focus/ PASS 0 7 7 10 36 3.03 —
heavy-removal/ PASS 0 7 8 8 36 2.95 —
low-curve/ PASS 0 11 8 9 36 2.67 —
mikaeus/ FAIL 7 39 8 6 36 3.08 —
aggro-hate/ PASS 0 9 6 5 36 3.03 50% (2g)
card-engine/ PASS 0 10 8 6 36 2.97 —
go-wide/ PASS 0 10 8 6 36 2.97 0% (2g)
grindy/ PASS 0 9 6 5 36 2.92 100% (1g)
opponent-facing/ PASS 0 9 5 10 36 2.92 —
proliferate/ PASS 0 10 5 5 36 3.08 —

⭐ = current baseline

the hypotheses

no-mikaeus — Baseline. Aristocrats + -1/-1, every combo needs board state.

fast-ramp — fast-ramp

lean-outlets — The deck runs 8 sac outlets and probably needs ~5. Cut 3 for interaction and card advantage -- does consistency actually drop?

commander-focus — The commander only steals from OPPONENTS' creatures, but the deck's -1/-1 engine mostly counters our own. Push counters onto their board.

heavy-removal — Bracket 3 pods interact. Trade combo redundancy for removal and see whether surviving longer beats assembling faster.

low-curve — Avg MV is 3.02 and the engine lands ~T6. Cut the top of the curve entirely -- does the deck come online sooner and win more?

mikaeus — Does the highest-leverage combo card (28 combos) stay legal? Expected FAIL: goes infinite with every sac outlet.

aggro-hate — aggro-hate

card-engine — card-engine

go-wide — go-wide

grindy — grindy

opponent-facing — opponent-facing

proliferate — proliferate

layout

decks/<variant>/
  decklist.txt     the 100 cards, "N Card Name" per line
  bracket.txt      bracket-3 + house-rule check
  combos.txt       combos already in the deck, and one card away
  sim/             Forge runs, one triple per batch:
    <stamp>.log      raw Forge output, every game
    <stamp>.txt      human-readable report
    <stamp>.json     machine-readable results
  README.md        generated summary

regenerating

python3 tools/make_variants.py       # rebuild every decklist from the spec
python3 tools/variant.py <name>      # analysis for one variant (~10s)
python3 tools/variant.py <name> --sim 24   # + 24 Forge games (~25 min)
python3 tools/compare.py             # rebuild this file

The decklists are generated from tools/make_variants.py, which holds each variant as a cut/add list against the baseline. Change the baseline and every variant follows. Analysis files are rewritten each run; sim runs are additive, so batches accumulate and stay comparable.

reading the win rates

Forge's AI is heuristic and weak at combo decks by its own documentation. Ours is a combo deck, so the AI under-plays it. Treat win rates as a floor and as evidence the deck functions and its cards interact — not as a power rating. Random baseline in a 4-player pod is 25%. Opponents are stock Commander precons (roughly bracket 2).