From 1e177058e0c87e372d6389223480487f7d9be118 Mon Sep 17 00:00:00 2001 From: mark rosenberg Date: Sat, 12 Sep 2026 00:41:44 -0400 Subject: [PATCH] Use new extension --- .../{decklist.txt => decklist.mgt} | 0 decks/reaper-king-no-more/decks/README.md | 2 +- decks/reaper-king-no-more/decks/aggro-hate/README.md | 4 ++-- .../decks/aggro-hate/{decklist.txt => decklist.mgt} | 0 .../reaper-king-no-more/decks/card-engine/README.md | 4 ++-- .../decks/card-engine/{decklist.txt => decklist.mgt} | 0 .../decks/commander-focus/README.md | 4 ++-- .../commander-focus/{decklist.txt => decklist.mgt} | 0 decks/reaper-king-no-more/decks/fast-ramp/README.md | 4 ++-- .../decks/fast-ramp/{decklist.txt => decklist.mgt} | 0 decks/reaper-king-no-more/decks/go-wide/README.md | 4 ++-- .../decks/go-wide/{decklist.txt => decklist.mgt} | 0 decks/reaper-king-no-more/decks/grindy/README.md | 4 ++-- .../decks/grindy/{decklist.txt => decklist.mgt} | 0 .../decks/heavy-removal/README.md | 4 ++-- .../heavy-removal/{decklist.txt => decklist.mgt} | 0 .../reaper-king-no-more/decks/lean-outlets/README.md | 4 ++-- .../lean-outlets/{decklist.txt => decklist.mgt} | 0 decks/reaper-king-no-more/decks/low-curve/README.md | 4 ++-- .../decks/low-curve/{decklist.txt => decklist.mgt} | 0 decks/reaper-king-no-more/decks/mikaeus/README.md | 4 ++-- .../decks/mikaeus/{decklist.txt => decklist.mgt} | 0 decks/reaper-king-no-more/decks/no-mikaeus/README.md | 4 ++-- .../decks/no-mikaeus/{decklist.txt => decklist.mgt} | 0 .../decks/opponent-facing/README.md | 4 ++-- .../opponent-facing/{decklist.txt => decklist.mgt} | 0 .../reaper-king-no-more/decks/proliferate/README.md | 4 ++-- .../decks/proliferate/{decklist.txt => decklist.mgt} | 0 decks/reaper-king-no-more/plan.md | 12 ++++++------ decks/reaper-king-no-more/sim_substitutions.yaml | 2 +- tools/ab_test.py | 2 +- tools/batch_run.py | 6 +++--- tools/bracket_check.py | 2 +- tools/card_stats.py | 2 +- tools/combos.py | 2 +- tools/compare.py | 6 +++--- tools/deckctx.py | 6 +++--- tools/forge_report.py | 4 ++-- tools/generate.py | 4 ++-- tools/make_variants.py | 4 ++-- tools/roles.py | 2 +- tools/run_forge.sh | 6 +++--- tools/to_dck.py | 8 ++++---- tools/variant.py | 8 ++++---- 44 files changed, 65 insertions(+), 65 deletions(-) rename decks/reaper-king-no-more/{decklist.txt => decklist.mgt} (100%) rename decks/reaper-king-no-more/decks/aggro-hate/{decklist.txt => decklist.mgt} (100%) rename decks/reaper-king-no-more/decks/card-engine/{decklist.txt => decklist.mgt} (100%) rename decks/reaper-king-no-more/decks/commander-focus/{decklist.txt => decklist.mgt} (100%) rename decks/reaper-king-no-more/decks/fast-ramp/{decklist.txt => decklist.mgt} (100%) rename decks/reaper-king-no-more/decks/go-wide/{decklist.txt => decklist.mgt} (100%) rename decks/reaper-king-no-more/decks/grindy/{decklist.txt => decklist.mgt} (100%) rename decks/reaper-king-no-more/decks/heavy-removal/{decklist.txt => decklist.mgt} (100%) rename decks/reaper-king-no-more/decks/lean-outlets/{decklist.txt => decklist.mgt} (100%) rename decks/reaper-king-no-more/decks/low-curve/{decklist.txt => decklist.mgt} (100%) rename decks/reaper-king-no-more/decks/mikaeus/{decklist.txt => decklist.mgt} (100%) rename decks/reaper-king-no-more/decks/no-mikaeus/{decklist.txt => decklist.mgt} (100%) rename decks/reaper-king-no-more/decks/opponent-facing/{decklist.txt => decklist.mgt} (100%) rename decks/reaper-king-no-more/decks/proliferate/{decklist.txt => decklist.mgt} (100%) diff --git a/decks/reaper-king-no-more/decklist.txt b/decks/reaper-king-no-more/decklist.mgt similarity index 100% rename from decks/reaper-king-no-more/decklist.txt rename to decks/reaper-king-no-more/decklist.mgt diff --git a/decks/reaper-king-no-more/decks/README.md b/decks/reaper-king-no-more/decks/README.md index 264941a..ca5f2f6 100644 --- a/decks/reaper-king-no-more/decks/README.md +++ b/decks/reaper-king-no-more/decks/README.md @@ -56,7 +56,7 @@ Each variant is a hypothesis: change a few cards, then measure what it does to l ``` decks// - decklist.txt the 100 cards, "N Card Name" per line + decklist.mgt 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: diff --git a/decks/reaper-king-no-more/decks/aggro-hate/README.md b/decks/reaper-king-no-more/decks/aggro-hate/README.md index 4fdd4c9..5b12244 100644 --- a/decks/reaper-king-no-more/decks/aggro-hate/README.md +++ b/decks/reaper-king-no-more/decks/aggro-hate/README.md @@ -3,13 +3,13 @@ _generated 2026-09-07 23:37Z by `tools/variant.py`_ - **bracket 3: PASS** (two-card vacuum combos: 0) -- 86 lines in `decklist.txt` +- 86 lines in `decklist.mgt` ## files | file | what it is | | --- | --- | -| `decklist.txt` | the deck, `N Card Name` per line | +| `decklist.mgt` | the deck, `N Card Name` per line | | `bracket.txt` | bracket-3 + house-rule check | | `combos.txt` | combos in the deck, and one card away | | `sim/` | Forge runs — `.log` raw, `.txt` report, `.json` data | diff --git a/decks/reaper-king-no-more/decks/aggro-hate/decklist.txt b/decks/reaper-king-no-more/decks/aggro-hate/decklist.mgt similarity index 100% rename from decks/reaper-king-no-more/decks/aggro-hate/decklist.txt rename to decks/reaper-king-no-more/decks/aggro-hate/decklist.mgt diff --git a/decks/reaper-king-no-more/decks/card-engine/README.md b/decks/reaper-king-no-more/decks/card-engine/README.md index 42cace8..39114b3 100644 --- a/decks/reaper-king-no-more/decks/card-engine/README.md +++ b/decks/reaper-king-no-more/decks/card-engine/README.md @@ -3,13 +3,13 @@ _generated 2026-09-07 23:37Z by `tools/variant.py`_ - **bracket 3: PASS** (two-card vacuum combos: 0) -- 86 lines in `decklist.txt` +- 86 lines in `decklist.mgt` ## files | file | what it is | | --- | --- | -| `decklist.txt` | the deck, `N Card Name` per line | +| `decklist.mgt` | the deck, `N Card Name` per line | | `bracket.txt` | bracket-3 + house-rule check | | `combos.txt` | combos in the deck, and one card away | | `sim/` | Forge runs — `.log` raw, `.txt` report, `.json` data | diff --git a/decks/reaper-king-no-more/decks/card-engine/decklist.txt b/decks/reaper-king-no-more/decks/card-engine/decklist.mgt similarity index 100% rename from decks/reaper-king-no-more/decks/card-engine/decklist.txt rename to decks/reaper-king-no-more/decks/card-engine/decklist.mgt diff --git a/decks/reaper-king-no-more/decks/commander-focus/README.md b/decks/reaper-king-no-more/decks/commander-focus/README.md index f54c8f4..34eb47e 100644 --- a/decks/reaper-king-no-more/decks/commander-focus/README.md +++ b/decks/reaper-king-no-more/decks/commander-focus/README.md @@ -3,13 +3,13 @@ _generated 2026-09-07 15:51Z by `tools/variant.py`_ - **bracket 3: PASS** (two-card vacuum combos: 0) -- 86 lines in `decklist.txt` +- 86 lines in `decklist.mgt` ## files | file | what it is | | --- | --- | -| `decklist.txt` | the deck, `N Card Name` per line | +| `decklist.mgt` | the deck, `N Card Name` per line | | `bracket.txt` | bracket-3 + house-rule check | | `combos.txt` | combos in the deck, and one card away | | `sim/` | Forge runs — `.log` raw, `.txt` report, `.json` data | diff --git a/decks/reaper-king-no-more/decks/commander-focus/decklist.txt b/decks/reaper-king-no-more/decks/commander-focus/decklist.mgt similarity index 100% rename from decks/reaper-king-no-more/decks/commander-focus/decklist.txt rename to decks/reaper-king-no-more/decks/commander-focus/decklist.mgt diff --git a/decks/reaper-king-no-more/decks/fast-ramp/README.md b/decks/reaper-king-no-more/decks/fast-ramp/README.md index 2dae2af..b919974 100644 --- a/decks/reaper-king-no-more/decks/fast-ramp/README.md +++ b/decks/reaper-king-no-more/decks/fast-ramp/README.md @@ -3,13 +3,13 @@ _generated 2026-09-08 02:07Z by `tools/variant.py`_ - **bracket 3: PASS** (two-card vacuum combos: 0) -- 86 lines in `decklist.txt` +- 86 lines in `decklist.mgt` ## files | file | what it is | | --- | --- | -| `decklist.txt` | the deck, `N Card Name` per line | +| `decklist.mgt` | the deck, `N Card Name` per line | | `bracket.txt` | bracket-3 + house-rule check | | `combos.txt` | combos in the deck, and one card away | | `sim/` | Forge runs — `.log` raw, `.txt` report, `.json` data | diff --git a/decks/reaper-king-no-more/decks/fast-ramp/decklist.txt b/decks/reaper-king-no-more/decks/fast-ramp/decklist.mgt similarity index 100% rename from decks/reaper-king-no-more/decks/fast-ramp/decklist.txt rename to decks/reaper-king-no-more/decks/fast-ramp/decklist.mgt diff --git a/decks/reaper-king-no-more/decks/go-wide/README.md b/decks/reaper-king-no-more/decks/go-wide/README.md index e171884..f4e5dfd 100644 --- a/decks/reaper-king-no-more/decks/go-wide/README.md +++ b/decks/reaper-king-no-more/decks/go-wide/README.md @@ -3,13 +3,13 @@ _generated 2026-09-07 23:37Z by `tools/variant.py`_ - **bracket 3: PASS** (two-card vacuum combos: 0) -- 86 lines in `decklist.txt` +- 86 lines in `decklist.mgt` ## files | file | what it is | | --- | --- | -| `decklist.txt` | the deck, `N Card Name` per line | +| `decklist.mgt` | the deck, `N Card Name` per line | | `bracket.txt` | bracket-3 + house-rule check | | `combos.txt` | combos in the deck, and one card away | | `sim/` | Forge runs — `.log` raw, `.txt` report, `.json` data | diff --git a/decks/reaper-king-no-more/decks/go-wide/decklist.txt b/decks/reaper-king-no-more/decks/go-wide/decklist.mgt similarity index 100% rename from decks/reaper-king-no-more/decks/go-wide/decklist.txt rename to decks/reaper-king-no-more/decks/go-wide/decklist.mgt diff --git a/decks/reaper-king-no-more/decks/grindy/README.md b/decks/reaper-king-no-more/decks/grindy/README.md index 54056cf..a7fb1f4 100644 --- a/decks/reaper-king-no-more/decks/grindy/README.md +++ b/decks/reaper-king-no-more/decks/grindy/README.md @@ -3,13 +3,13 @@ _generated 2026-09-07 23:38Z by `tools/variant.py`_ - **bracket 3: PASS** (two-card vacuum combos: 0) -- 86 lines in `decklist.txt` +- 86 lines in `decklist.mgt` ## files | file | what it is | | --- | --- | -| `decklist.txt` | the deck, `N Card Name` per line | +| `decklist.mgt` | the deck, `N Card Name` per line | | `bracket.txt` | bracket-3 + house-rule check | | `combos.txt` | combos in the deck, and one card away | | `sim/` | Forge runs — `.log` raw, `.txt` report, `.json` data | diff --git a/decks/reaper-king-no-more/decks/grindy/decklist.txt b/decks/reaper-king-no-more/decks/grindy/decklist.mgt similarity index 100% rename from decks/reaper-king-no-more/decks/grindy/decklist.txt rename to decks/reaper-king-no-more/decks/grindy/decklist.mgt diff --git a/decks/reaper-king-no-more/decks/heavy-removal/README.md b/decks/reaper-king-no-more/decks/heavy-removal/README.md index 5627f20..a15f5b4 100644 --- a/decks/reaper-king-no-more/decks/heavy-removal/README.md +++ b/decks/reaper-king-no-more/decks/heavy-removal/README.md @@ -3,13 +3,13 @@ _generated 2026-09-07 15:51Z by `tools/variant.py`_ - **bracket 3: PASS** (two-card vacuum combos: 0) -- 86 lines in `decklist.txt` +- 86 lines in `decklist.mgt` ## files | file | what it is | | --- | --- | -| `decklist.txt` | the deck, `N Card Name` per line | +| `decklist.mgt` | the deck, `N Card Name` per line | | `bracket.txt` | bracket-3 + house-rule check | | `combos.txt` | combos in the deck, and one card away | | `sim/` | Forge runs — `.log` raw, `.txt` report, `.json` data | diff --git a/decks/reaper-king-no-more/decks/heavy-removal/decklist.txt b/decks/reaper-king-no-more/decks/heavy-removal/decklist.mgt similarity index 100% rename from decks/reaper-king-no-more/decks/heavy-removal/decklist.txt rename to decks/reaper-king-no-more/decks/heavy-removal/decklist.mgt diff --git a/decks/reaper-king-no-more/decks/lean-outlets/README.md b/decks/reaper-king-no-more/decks/lean-outlets/README.md index 23b416e..8793a0d 100644 --- a/decks/reaper-king-no-more/decks/lean-outlets/README.md +++ b/decks/reaper-king-no-more/decks/lean-outlets/README.md @@ -3,13 +3,13 @@ _generated 2026-09-07 15:51Z by `tools/variant.py`_ - **bracket 3: PASS** (two-card vacuum combos: 0) -- 86 lines in `decklist.txt` +- 86 lines in `decklist.mgt` ## files | file | what it is | | --- | --- | -| `decklist.txt` | the deck, `N Card Name` per line | +| `decklist.mgt` | the deck, `N Card Name` per line | | `bracket.txt` | bracket-3 + house-rule check | | `combos.txt` | combos in the deck, and one card away | | `sim/` | Forge runs — `.log` raw, `.txt` report, `.json` data | diff --git a/decks/reaper-king-no-more/decks/lean-outlets/decklist.txt b/decks/reaper-king-no-more/decks/lean-outlets/decklist.mgt similarity index 100% rename from decks/reaper-king-no-more/decks/lean-outlets/decklist.txt rename to decks/reaper-king-no-more/decks/lean-outlets/decklist.mgt diff --git a/decks/reaper-king-no-more/decks/low-curve/README.md b/decks/reaper-king-no-more/decks/low-curve/README.md index 2eb48e8..6f339d4 100644 --- a/decks/reaper-king-no-more/decks/low-curve/README.md +++ b/decks/reaper-king-no-more/decks/low-curve/README.md @@ -3,13 +3,13 @@ _generated 2026-09-07 15:52Z by `tools/variant.py`_ - **bracket 3: PASS** (two-card vacuum combos: 0) -- 86 lines in `decklist.txt` +- 86 lines in `decklist.mgt` ## files | file | what it is | | --- | --- | -| `decklist.txt` | the deck, `N Card Name` per line | +| `decklist.mgt` | the deck, `N Card Name` per line | | `bracket.txt` | bracket-3 + house-rule check | | `combos.txt` | combos in the deck, and one card away | | `sim/` | Forge runs — `.log` raw, `.txt` report, `.json` data | diff --git a/decks/reaper-king-no-more/decks/low-curve/decklist.txt b/decks/reaper-king-no-more/decks/low-curve/decklist.mgt similarity index 100% rename from decks/reaper-king-no-more/decks/low-curve/decklist.txt rename to decks/reaper-king-no-more/decks/low-curve/decklist.mgt diff --git a/decks/reaper-king-no-more/decks/mikaeus/README.md b/decks/reaper-king-no-more/decks/mikaeus/README.md index f493fc4..f7518cd 100644 --- a/decks/reaper-king-no-more/decks/mikaeus/README.md +++ b/decks/reaper-king-no-more/decks/mikaeus/README.md @@ -3,13 +3,13 @@ _generated 2026-09-07 15:51Z by `tools/variant.py`_ - **bracket 3: FAIL** (two-card vacuum combos: 7) -- 86 lines in `decklist.txt` +- 86 lines in `decklist.mgt` ## files | file | what it is | | --- | --- | -| `decklist.txt` | the deck, `N Card Name` per line | +| `decklist.mgt` | the deck, `N Card Name` per line | | `bracket.txt` | bracket-3 + house-rule check | | `combos.txt` | combos in the deck, and one card away | | `sim/` | Forge runs — `.log` raw, `.txt` report, `.json` data | diff --git a/decks/reaper-king-no-more/decks/mikaeus/decklist.txt b/decks/reaper-king-no-more/decks/mikaeus/decklist.mgt similarity index 100% rename from decks/reaper-king-no-more/decks/mikaeus/decklist.txt rename to decks/reaper-king-no-more/decks/mikaeus/decklist.mgt diff --git a/decks/reaper-king-no-more/decks/no-mikaeus/README.md b/decks/reaper-king-no-more/decks/no-mikaeus/README.md index 75ad9ba..61b5bae 100644 --- a/decks/reaper-king-no-more/decks/no-mikaeus/README.md +++ b/decks/reaper-king-no-more/decks/no-mikaeus/README.md @@ -3,13 +3,13 @@ _generated 2026-09-07 15:56Z by `tools/variant.py`_ - **bracket 3: PASS** (two-card vacuum combos: 0) -- 86 lines in `decklist.txt` +- 86 lines in `decklist.mgt` ## files | file | what it is | | --- | --- | -| `decklist.txt` | the deck, `N Card Name` per line | +| `decklist.mgt` | the deck, `N Card Name` per line | | `bracket.txt` | bracket-3 + house-rule check | | `combos.txt` | combos in the deck, and one card away | | `sim/` | Forge runs — `.log` raw, `.txt` report, `.json` data | diff --git a/decks/reaper-king-no-more/decks/no-mikaeus/decklist.txt b/decks/reaper-king-no-more/decks/no-mikaeus/decklist.mgt similarity index 100% rename from decks/reaper-king-no-more/decks/no-mikaeus/decklist.txt rename to decks/reaper-king-no-more/decks/no-mikaeus/decklist.mgt diff --git a/decks/reaper-king-no-more/decks/opponent-facing/README.md b/decks/reaper-king-no-more/decks/opponent-facing/README.md index 4b1c159..f45f413 100644 --- a/decks/reaper-king-no-more/decks/opponent-facing/README.md +++ b/decks/reaper-king-no-more/decks/opponent-facing/README.md @@ -3,13 +3,13 @@ _generated 2026-09-07 23:37Z by `tools/variant.py`_ - **bracket 3: PASS** (two-card vacuum combos: 0) -- 86 lines in `decklist.txt` +- 86 lines in `decklist.mgt` ## files | file | what it is | | --- | --- | -| `decklist.txt` | the deck, `N Card Name` per line | +| `decklist.mgt` | the deck, `N Card Name` per line | | `bracket.txt` | bracket-3 + house-rule check | | `combos.txt` | combos in the deck, and one card away | | `sim/` | Forge runs — `.log` raw, `.txt` report, `.json` data | diff --git a/decks/reaper-king-no-more/decks/opponent-facing/decklist.txt b/decks/reaper-king-no-more/decks/opponent-facing/decklist.mgt similarity index 100% rename from decks/reaper-king-no-more/decks/opponent-facing/decklist.txt rename to decks/reaper-king-no-more/decks/opponent-facing/decklist.mgt diff --git a/decks/reaper-king-no-more/decks/proliferate/README.md b/decks/reaper-king-no-more/decks/proliferate/README.md index 098829a..172b5a9 100644 --- a/decks/reaper-king-no-more/decks/proliferate/README.md +++ b/decks/reaper-king-no-more/decks/proliferate/README.md @@ -3,13 +3,13 @@ _generated 2026-09-07 23:38Z by `tools/variant.py`_ - **bracket 3: PASS** (two-card vacuum combos: 0) -- 86 lines in `decklist.txt` +- 86 lines in `decklist.mgt` ## files | file | what it is | | --- | --- | -| `decklist.txt` | the deck, `N Card Name` per line | +| `decklist.mgt` | the deck, `N Card Name` per line | | `bracket.txt` | bracket-3 + house-rule check | | `combos.txt` | combos in the deck, and one card away | | `sim/` | Forge runs — `.log` raw, `.txt` report, `.json` data | diff --git a/decks/reaper-king-no-more/decks/proliferate/decklist.txt b/decks/reaper-king-no-more/decks/proliferate/decklist.mgt similarity index 100% rename from decks/reaper-king-no-more/decks/proliferate/decklist.txt rename to decks/reaper-king-no-more/decks/proliferate/decklist.mgt diff --git a/decks/reaper-king-no-more/plan.md b/decks/reaper-king-no-more/plan.md index 0e9fc00..4de277b 100644 --- a/decks/reaper-king-no-more/plan.md +++ b/decks/reaper-king-no-more/plan.md @@ -300,7 +300,7 @@ Card selection is offline and instant. Simulation is Forge, and it's the slow st ``` make data (once/per set) ──► data/*.jsonl, variants.json, AtomicCards.json │ - decklist.txt ─────────────────────────► │ blacklist.txt ──┐ + decklist.mgt ─────────────────────────► │ blacklist.txt ──┐ │ │ │ ├─► bracket_check.py ── game changers, MLD, vacuum combos, blacklist ──┐ ├─► combos.py ── included / almostIncluded (offline) ──────────┤ @@ -313,13 +313,13 @@ Card selection is offline and instant. Simulation is Forge, and it's the slow st Every simulation run writes a timestamped triple into `out/`: the full Forge `.log`, a human `.txt` report, and a `.json` artifact — and the report footer names -`decklist.txt`, the log, the JSON, and itself, so any number is traceable. +`decklist.mgt`, the log, the JSON, and itself, so any number is traceable. ## 4. Repo layout ``` reaper-king-no-more/ - decklist.txt # working deck, "1 Card Name" per line + decklist.mgt # working deck, "1 Card Name" per line blacklist.txt # cards I won't play, "Card Name | reason" plan.md data/ # ~1.2GB, all gitignored @@ -327,7 +327,7 @@ reaper-king-no-more/ variants.json AtomicCards.json embeddings.npz (generated) decks/ # RESULTS, one dir per archetype variant README.md - no-mikaeus/ # decklist.txt, bracket.txt, combos.txt, + no-mikaeus/ # decklist.mgt, bracket.txt, combos.txt, mikaeus/ # README.md, sim/.{log,txt,json} tools/ cards.py # shared index: oracle+tags+edhrec+combos+blacklist @@ -363,7 +363,7 @@ insists Commander decks live). 2. ~~`cards.py`~~ — **done.** oracle + 4,369 tags + edhrecRank + combos + blacklist. 3. ~~`bracket_check.py`~~ — **done and passing.** 4. ~~`embed.py` / `similar.py` / `similar_text.py`~~ — **done** (Layer B). -5. ~~Draft the 100~~ — **done**, `decklist.txt`. +5. ~~Draft the 100~~ — **done**, `decklist.mgt`. 6. ~~Forge installed + `to_dck.py` + `run_forge.sh` + `forge_report.py`~~ — **done.** 4-player pod vs precons, reproducible by seed. 7. Iterate on the list using Forge results + the offline combo/tag tools. @@ -375,7 +375,7 @@ with the real one is worse than having one. Forge is the simulator. (`goldfish.p and its `out/goldfish-*` runs are removed.) **Report convention** (every tool): a timestamped `.txt` human report plus a `.json` -artifact in `out/`, with the report footer naming `decklist.txt`, the raw log, the +artifact in `out/`, with the report footer naming `decklist.mgt`, the raw log, the JSON, and itself. ## 6. Deck skeleton to draft against diff --git a/decks/reaper-king-no-more/sim_substitutions.yaml b/decks/reaper-king-no-more/sim_substitutions.yaml index f0d812e..9474e3a 100644 --- a/decks/reaper-king-no-more/sim_substitutions.yaml +++ b/decks/reaper-king-no-more/sim_substitutions.yaml @@ -7,7 +7,7 @@ # correctly (the removal slot still does removal) even though the specific card # differs. # -# decklist.txt remains the source of truth. This map applies ONLY when building +# decklist.mgt remains the source of truth. This map applies ONLY when building # the .dck for simulation, and every substitution is recorded in the run's JSON # metadata and printed in reports. # diff --git a/tools/ab_test.py b/tools/ab_test.py index 60a9934..1f93069 100644 --- a/tools/ab_test.py +++ b/tools/ab_test.py @@ -53,7 +53,7 @@ def run_arm(ctx, label, variant, games, seed, profile, overlay, clock, workdir): tools_dir = os.path.dirname(os.path.abspath(__file__)) subprocess.run([sys.executable, os.path.join(tools_dir, "to_dck.py"), "--deck", ctx.dir, - os.path.join(ctx.dir, "decks", variant, "decklist.txt"), + os.path.join(ctx.dir, "decks", variant, "decklist.mgt"), "-o", os.path.join(dst, dck_name)], capture_output=True) import shutil as sh for p in POD: diff --git a/tools/batch_run.py b/tools/batch_run.py index c3d7cb9..43a3582 100644 --- a/tools/batch_run.py +++ b/tools/batch_run.py @@ -59,7 +59,7 @@ def variants(deck_root, only=None, resume=False): out = [] for name in sorted(os.listdir(os.path.join(deck_root, "decks"))): d = os.path.join(deck_root, "decks", name) - if not os.path.isdir(d) or not os.path.exists(os.path.join(d, "decklist.txt")): + if not os.path.isdir(d) or not os.path.exists(os.path.join(d, "decklist.mgt")): continue if only and name not in only: continue @@ -122,7 +122,7 @@ def run_variant(ctx, name, games, seed, wid, pod_idx): # build this variant's .dck into the worker's own profile r = subprocess.run([sys.executable, os.path.join(TOOLS_ROOT, "tools", "to_dck.py"), "--deck", deck_root, - os.path.join(vdir, "decklist.txt"), + os.path.join(vdir, "decklist.mgt"), "-o", os.path.join(dst, dck_name)], capture_output=True, text=True) if r.returncode != 0: @@ -160,7 +160,7 @@ def run_variant(ctx, name, games, seed, wid, pod_idx): subprocess.run([sys.executable, os.path.join(TOOLS_ROOT, "tools", "forge_report.py"), out + ".log", out + ".json", out + ".txt", str(games), str(seed), - os.path.join(vdir, "decklist.txt"), ctx.forge_metadata_name()], + os.path.join(vdir, "decklist.mgt"), ctx.forge_metadata_name()], capture_output=True) # Stamp the run config so tuned and stock arms are never silently compared. diff --git a/tools/bracket_check.py b/tools/bracket_check.py index a9f46fe..75a4e06 100644 --- a/tools/bracket_check.py +++ b/tools/bracket_check.py @@ -2,7 +2,7 @@ """Check a decklist against Commander Bracket 3 + our house rules. python3 tools/bracket_check.py --deck decks/reaper-king-no-more - python3 tools/bracket_check.py --deck decks/reaper-king-no-more decks/reaper-king-no-more/decks/no-mikaeus/decklist.txt + python3 tools/bracket_check.py --deck decks/reaper-king-no-more decks/reaper-king-no-more/decks/no-mikaeus/decklist.mgt Enforces: * <= 3 Game Changers (official) diff --git a/tools/card_stats.py b/tools/card_stats.py index ce56d8d..6dfc66d 100644 --- a/tools/card_stats.py +++ b/tools/card_stats.py @@ -103,7 +103,7 @@ def main(): # only cards actually in our decklist db = DB(blacklist_path=ctx.blacklist_path) variant_dir = os.path.dirname(os.path.dirname(log)) - deck_file = os.path.join(variant_dir, "decklist.txt") + deck_file = os.path.join(variant_dir, "decklist.mgt") commander, deck = load_decklist(deck_file) deck_set = set(deck) | {commander} diff --git a/tools/combos.py b/tools/combos.py index ce24b6f..3075507 100644 --- a/tools/combos.py +++ b/tools/combos.py @@ -4,7 +4,7 @@ against the local variants.json. No API calls. python3 tools/combos.py --deck decks/reaper-king-no-more python3 tools/combos.py --deck decks/reaper-king-no-more --almost 30 - python3 tools/combos.py --deck decks/reaper-king-no-more --deck-file some/decklist.txt + python3 tools/combos.py --deck decks/reaper-king-no-more --deck-file some/decklist.mgt """ import sys, os, json sys.path.insert(0, os.path.dirname(__file__)) diff --git a/tools/compare.py b/tools/compare.py index a7bccbe..8913208 100644 --- a/tools/compare.py +++ b/tools/compare.py @@ -23,7 +23,7 @@ def variant_order(ctx): except ImportError: pass rest = sorted(os.path.basename(os.path.dirname(p)) - for p in glob.glob(ctx.path("decks", "*", "decklist.txt")) + for p in glob.glob(ctx.path("decks", "*", "decklist.mgt")) if os.path.basename(os.path.dirname(p)) not in hand) return hand + rest @@ -46,7 +46,7 @@ def main(): rows = [] for name in order: vdir = os.path.join(DECKS, name) - deck_f = os.path.join(vdir, "decklist.txt") + deck_f = os.path.join(vdir, "decklist.mgt") if not os.path.exists(deck_f): continue cmd, deck = load_decklist(deck_f) @@ -107,7 +107,7 @@ def main(): slug = ctx.slug L += ["## layout", "", "```", "decks//", - " decklist.txt the 100 cards, \"N Card Name\" per line", + " decklist.mgt 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:", diff --git a/tools/deckctx.py b/tools/deckctx.py index ce407e4..965dac5 100644 --- a/tools/deckctx.py +++ b/tools/deckctx.py @@ -17,7 +17,7 @@ Resolution order for the deck directory: from deckctx import DeckContext ctx = DeckContext.from_args() # pops --deck out of sys.argv - ctx.path("decklist.txt") # -> decks//decklist.txt + ctx.path("decklist.mgt") # -> decks//decklist.mgt ctx.commander # -> "The Reaper, King No More" ctx.identity # -> frozenset("BRG"), from the DB ctx.slug # -> "reaper-king-no-more" @@ -30,7 +30,7 @@ ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) def _looks_like_deck_dir(d): return os.path.exists(os.path.join(d, "config.yaml")) or \ - os.path.exists(os.path.join(d, "decklist.txt")) + os.path.exists(os.path.join(d, "decklist.mgt")) def resolve_deck_dir(argv=None, pop=True): @@ -103,7 +103,7 @@ class DeckContext: @property def decklist_path(self): return self.config.get("decklist") and self.path(self.config["decklist"]) \ - or self.path("decklist.txt") + or self.path("decklist.mgt") @property def blacklist_path(self): diff --git a/tools/forge_report.py b/tools/forge_report.py index e27ff21..e025d39 100644 --- a/tools/forge_report.py +++ b/tools/forge_report.py @@ -104,7 +104,7 @@ def parse(log_path): return games -def report(games, n_req, seed, log, jsonp, txtp, deck_path="decklist.txt", +def report(games, n_req, seed, log, jsonp, txtp, deck_path="decklist.mgt", tally=None, tally_total=0, timeouts=0): L, add = [], lambda s: L.append(s) # prefer the authoritative Match Result tally over per-game lines @@ -209,7 +209,7 @@ def main(): log, jsonp, txtp = sys.argv[1], sys.argv[2], sys.argv[3] n_req = sys.argv[4] if len(sys.argv) > 4 else "?" seed = sys.argv[5] if len(sys.argv) > 5 else "?" - deck_path = sys.argv[6] if len(sys.argv) > 6 else "decklist.txt" + deck_path = sys.argv[6] if len(sys.argv) > 6 else "decklist.mgt" ours_name = sys.argv[7] if len(sys.argv) > 7 else deck_name_for(deck_path) if ours_name: OURS = ours_name diff --git a/tools/generate.py b/tools/generate.py index 3fd6361..e2e4588 100644 --- a/tools/generate.py +++ b/tools/generate.py @@ -159,7 +159,7 @@ def main(): only = args[args.index("--only") + 1] if "--only" in args else None stats = args[args.index("--from-stats") + 1] if "--from-stats" in args else None base_path = args[args.index("--base") + 1] if "--base" in args else \ - ctx.path(ctx.config.get("generate_base", "decks/no-mikaeus/decklist.txt")) + ctx.path(ctx.config.get("generate_base", "decks/no-mikaeus/decklist.mgt")) recipes = load_recipes(ctx) if "--list" in args: @@ -203,7 +203,7 @@ def main(): body = [f"1 {n}" for n in sorted(set(res["deck"]) - {"Swamp", "Forest", "Mountain"})] basics = [f"{Counter(res['deck'])[b]} {b}" for b in ("Swamp", "Forest", "Mountain") if Counter(res["deck"])[b]] - open(os.path.join(vdir, "decklist.txt"), "w").write( + open(os.path.join(vdir, "decklist.mgt"), "w").write( "\n".join(header + body + basics) + "\n") print(f"{name:18} ok -{len(res['cuts'])} +{len(res['adds'])}") print(f"{'':18} cut: {', '.join(res['cuts'][:4])}{'...' if len(res['cuts'])>4 else ''}") diff --git a/tools/make_variants.py b/tools/make_variants.py index 930d1c9..a19f339 100644 --- a/tools/make_variants.py +++ b/tools/make_variants.py @@ -53,7 +53,7 @@ def main(): from cards import DB db = DB(blacklist_path=ctx.blacklist_path) commander = ctx.commander - base_path = ctx.path("decks", "no-mikaeus", "decklist.txt") + base_path = ctx.path("decks", "no-mikaeus", "decklist.mgt") if not os.path.exists(base_path): base_path = ctx.decklist_path base = load(base_path) @@ -87,7 +87,7 @@ def main(): os.makedirs(vdir, exist_ok=True) header = [f"# {name}", f"# {why}", "", "# Commander", f"1 {commander}", "", "# Main"] - open(os.path.join(vdir, "decklist.txt"), "w").write( + open(os.path.join(vdir, "decklist.mgt"), "w").write( "\n".join(header + lines) + "\n") flags = [] diff --git a/tools/roles.py b/tools/roles.py index c3d551b..520aa34 100644 --- a/tools/roles.py +++ b/tools/roles.py @@ -6,7 +6,7 @@ allocation. This module defines the roles (as verified Scryfall Tagger slugs plu oracle-text fallbacks) and can classify any card or score a whole decklist. python3 tools/roles.py --deck decks/reaper-king-no-more - python3 tools/roles.py --deck decks/reaper-king-no-more decks/reaper-king-no-more/decks/fast-ramp/decklist.txt + python3 tools/roles.py --deck decks/reaper-king-no-more decks/reaper-king-no-more/decks/fast-ramp/decklist.mgt """ import sys, os sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) diff --git a/tools/run_forge.sh b/tools/run_forge.sh index a1061dd..22a9c82 100755 --- a/tools/run_forge.sh +++ b/tools/run_forge.sh @@ -22,7 +22,7 @@ STAMP="$(date -u +%Y%m%dT%H%M%SZ)" VDIR="$DECK_DIR/decks/$VARIANT" OUT="$VDIR/sim/$STAMP" -[ -f "$VDIR/decklist.txt" ] || { echo "no decklist: $VDIR/decklist.txt" >&2; exit 1; } +[ -f "$VDIR/decklist.mgt" ] || { echo "no decklist: $VDIR/decklist.mgt" >&2; exit 1; } mkdir -p "$VDIR/sim" OPPONENTS=( @@ -33,7 +33,7 @@ OPPONENTS=( # .dck filename and [metadata] Name= are derived from the deck (slug / # config.yaml `name:`), never hardcoded -- ask to_dck.py what it wrote. -DCK_NAME="$(python3 "$TOOLS/to_dck.py" --deck "$DECK_DIR" "$VDIR/decklist.txt" \ +DCK_NAME="$(python3 "$TOOLS/to_dck.py" --deck "$DECK_DIR" "$VDIR/decklist.mgt" \ -o "$FORGE_DECKS/$(basename "$DECK_DIR").dck" | sed -n 's/^wrote \(.*\) (.*/\1/p')" DCK_NAME="$(basename "$DCK_NAME")" @@ -48,4 +48,4 @@ echo "[$VARIANT] $GAMES games, 4-player Commander pod, seed $SEED" | stdbuf -oL grep -E "^Game Result:" || true python3 "$TOOLS/forge_report.py" "$OUT.log" "$OUT.json" "$OUT.txt" \ - "$GAMES" "$SEED" "$VDIR/decklist.txt" + "$GAMES" "$SEED" "$VDIR/decklist.mgt" diff --git a/tools/to_dck.py b/tools/to_dck.py index 374bc06..67e70f4 100644 --- a/tools/to_dck.py +++ b/tools/to_dck.py @@ -1,8 +1,8 @@ #!/usr/bin/env python3 -"""Convert decklist.txt -> Forge .dck format. +"""Convert decklist.mgt -> Forge .dck format. python3 tools/to_dck.py --deck decks/reaper-king-no-more - python3 tools/to_dck.py --deck decks/reaper-king-no-more [decklist.txt] [-o ~/forge/decks/.dck] + python3 tools/to_dck.py --deck decks/reaper-king-no-more [decklist.mgt] [-o ~/forge/decks/.dck] Forge sections are [Commander], [Main], [Sideboard] (verified in DeckSection.java). Card names must match Forge's own database, so this validates against @@ -70,7 +70,7 @@ def main(): args = [a for a in sys.argv[1:]] out = args[args.index("-o") + 1] if "-o" in args else \ os.path.join(FORGE, "decks", ctx.dck_filename()) - src = next((a for a in args if a.endswith(".txt")), ctx.decklist_path) + src = next((a for a in args if a.endswith(".mgt")), ctx.decklist_path) commander, deck = load_decklist(src) @@ -107,7 +107,7 @@ def main(): print(f"!! {len(missing)} card(s) Forge does not recognise:", file=sys.stderr) for m in missing: print(f" {m}", file=sys.stderr) - print(" (fix the name in decklist.txt, or Forge will drop it)\n", file=sys.stderr) + print(" (fix the name in decklist.mgt, or Forge will drop it)\n", file=sys.stderr) else: print("warning: could not read Forge's card list; skipping validation", file=sys.stderr) diff --git a/tools/variant.py b/tools/variant.py index 6f1dc32..2ca48e7 100644 --- a/tools/variant.py +++ b/tools/variant.py @@ -7,7 +7,7 @@ Each variant directory ends up self-contained: /decks// - decklist.txt the 100 cards + decklist.mgt the 100 cards bracket.txt bracket-3 + house-rule check combos.txt combos in the deck, and one card away sim/ Forge runs: .{log,txt,json} @@ -38,7 +38,7 @@ def main(): tools = os.path.join(TOOLS_ROOT, "tools") vdir = ctx.path("decks", name) - deck = os.path.join(vdir, "decklist.txt") + deck = os.path.join(vdir, "decklist.mgt") if not os.path.exists(deck): sys.exit(f"no decklist at {deck}") os.makedirs(os.path.join(vdir, "sim"), exist_ok=True) @@ -90,13 +90,13 @@ def main(): f"_generated {stamp} by `tools/variant.py`_", "", f"- **bracket 3: {verdict}** (two-card vacuum combos: {vac})", - f"- {n_deck} lines in `decklist.txt`", + f"- {n_deck} lines in `decklist.mgt`", "", "## files", "", "| file | what it is |", "| --- | --- |", - "| `decklist.txt` | the deck, `N Card Name` per line |", + "| `decklist.mgt` | the deck, `N Card Name` per line |", "| `bracket.txt` | bracket-3 + house-rule check |", "| `combos.txt` | combos in the deck, and one card away |", "| `sim/` | Forge runs — `.log` raw, `.txt` report, `.json` data |",