# mtg A generic toolkit for building, testing, and simulating Magic: The Gathering Commander decks — evidenced by real games played in a real rules engine ([Forge](https://github.com/Card-Forge/forge)), not vibes. Give it four things about a deck — a commander, a card pool, a blacklist of cards you refuse to play, and a few constraints (bracket, land count, role budget) — and it derives everything else from offline card databases: color identity, legality, Game Changers, Scryfall Tagger tags (so it knows what a "sac outlet" or "drain payoff" *is*), and the Commander Spellbook combo database (108k+ combos). It can then generate deck variants as falsifiable hypotheses, check them against Commander Bracket rules and house rules, and simulate them in Forge to get card-level and deck-level statistics — cast rate, win-rate contribution, synergy pairs — instead of guesses. See `docs/howto.md` for the full methodology: what you supply, how pool size and game count determine whether results mean anything, how the Forge AI's weaknesses get worked around, and how to read the output honestly. ## Layout ``` mtg/ tools/ generic engine — works on ANY deck given its config.yaml mtg single dispatcher: tools/mtg decks/ [args...] deckctx.py resolves --deck / $MTG_DECK, loads config.yaml cards.py shared index: oracle + tags + edhrecRank + combos + blacklist bracket_check.py Bracket 3 + house-rule check (game changers, MLD, vacuum combos) combos.py offline combo finder (included / one-card-away) roles.py role classification + budget profile generate.py role-budget variant generator (recipes in /variants.yaml) make_variants.py hand-curated cut/add variant generator (same file) to_dck.py decklist -> Forge .dck batch_run.py / run_forge.sh / ab_test.py Forge simulation, in bulk or A/B forge_report.py / card_stats.py / power.py turn Forge logs into reports compare.py rebuilds a deck's decks/README.md summary table similar.py / similar_text.py / embed.py semantic "cards like this" search fetch_data.py downloads the shared bulk data below decks/ reaper-king-no-more/ one deck: data + config, the reference example config.yaml commander, pool, constraints, role budget, protected cards decklist.txt the 100 cards blacklist.txt cards you refuse to play, with reasons variants.yaml variant hypotheses (role-budget recipes + hand-curated cut/add) plan.md / README.md this deck's own design notes forge-overrides/ AI tuning for cards Forge's default AI can't pilot sim_substitutions.yaml simulation-only stand-ins for AI-unpilotable cards decks// RESULTS: one dir per archetype variant (generated) data/ gitignored, ~1.2GB — Scryfall/MTGJSON/Spellbook bulk downloads. Shared across every deck: this is Commander-format-wide data, not deck-specific. One copy at the repo root. out/ gitignored scratch output docs/howto.md the full methodology (pool size, game count, AI tuning, caveats) ``` ## Quickstart ```bash # one-time, shared across all decks python3 tools/fetch_data.py # ~1.2GB: Scryfall, MTGJSON, Spellbook python3 tools/embed.py # -> data/embeddings.npz # install Forge 2.0.14 to ~/forge (needs Java 17+) # check the reference deck python3 tools/bracket_check.py --deck decks/reaper-king-no-more python3 tools/combos.py --deck decks/reaper-king-no-more python3 tools/roles.py --deck decks/reaper-king-no-more # or via the single dispatcher tools/mtg decks/reaper-king-no-more bracket_check tools/mtg decks/reaper-king-no-more variant no-mikaeus --sim 24 ``` To add a new deck: copy the shape of `decks/reaper-king-no-more/` (at minimum `config.yaml`, `decklist.txt`, `blacklist.txt`), point `--deck` at it, and every tool in `tools/` works on it immediately — nothing in `tools/` is hardcoded to a specific commander, color identity, or deck name. See `docs/howto.md` for what each config field does and why, and `decks/reaper-king-no-more/plan.md` / `README.md` for a worked example of building one deck end to end.