This tool isn’t really needed given that there are multiple websites, where you can upload your collection and your deck, and they will tell you exactly which cards in the deck are missing from your collection.
For example:
Archidekt — collection tracker + deck builder
Moxfield — modern deck builder with collection support
Deckstats — deck-building + collection management
Deckbox — collection manager that shows missing cards for a deck
ManaBox — app for collection tracking + deck building
MTGGoldfish — has features to input your collection and compare against decks
Untapped.gg — for MTG Arena, tells you which decks you can build given your collection
So while a custom format legality checker is neat, if your goal is simply “which cards do I lack in this deck given my collection”, one of those sites will do just fine.
Commander with low power brackets, no tutors, no infinite combos, and mostly budget decks.
Cube Draft.
Playing precons against the computer using Forge. I copy the names of the precons from a block, then play them against each other using a bit of randomization:
import itertools, random
decks = ["Deck A", "Deck B", "Deck C", ...]
matchups = list(itertools.combinations(decks, 2))
random.shuffle(matchups)
for i, (deck1, deck2) in enumerate(matchups, 1):
print(f"Match {i}: {deck1} vs {deck2}")
Aside from the usual Theme Decks, some of the most interesting precons are Duel Decks, Pro Tour Collector Sets, Salvat 2005 and 2011, and Commander decks. You can find a full list of precon decks here.
Penny Dreadful on MTGO when I want constructed but cheap play.
I've played a bunch of Draft and Standard on MTG Arena but I didn't really enjoy it that much. It felt like a chore doing the dailies and just caring about getting the four wins per day.
I really used to like classic cards like Serra Angel and Shivan Dragon and I don't know exactly when they became so bad, but I couldn't even consider playing them now in most formats.
I believe Throne of Eldraine in 2019 was the set where power creep started accelerating most.
I've managed to write another script that seems to work:
import json
import re
def load_legal_cards(json_file):
"""
Load legal cards from a JSON file with structure:
{ "sets": [], "cards": [], "banned": [] }
"""
with open(json_file, 'r', encoding='utf-8') as f:
data = json.load(f)
legal_cards = [card.lower() for card in data.get('cards', [])]
banned_cards = [card.lower() for card in data.get('banned', [])] if 'banned' in data else []
return legal_cards, banned_cards
def clean_line(line):
"""
Remove quantities, set info, markers, and whitespace
Skip lines that are section headers like 'Deck', 'Sideboard'
"""
line = re.sub(r'^\d+\s*x?\s*', '', line) # "2 " or "2x "
line = re.sub(r'\(.*?\)', '', line) # "(SET)"
line = re.sub(r'\*\w+\*', '', line) # "*F*"
line = line.strip()
if re.match(r'^(deck|sideboard)\s*:?\s*$', line, re.IGNORECASE):
return None
return line if line else None
def validate_deck(deck_file, legal_cards, banned_cards):
"""
Returns a list of illegal cards
"""
illegal_cards = []
with open(deck_file, 'r', encoding='utf-8') as f:
lines = f.readlines()
for line in lines:
card_name = clean_line(line)
if not card_name or card_name.startswith("#"):
continue # skip empty or comment lines
card_lower = card_name.lower()
if card_lower in banned_cards or card_lower not in legal_cards:
illegal_cards.append(card_name)
return illegal_cards
def main():
legal_cards_file = 'legal_cards.json' # JSON with "cards" and optional "banned"
decklist_file = 'decklist.txt' # Your decklist input
legal_cards, banned_cards = load_legal_cards(legal_cards_file)
illegal_cards = validate_deck(decklist_file, legal_cards, banned_cards)
if illegal_cards:
print("Illegal cards:")
for card in illegal_cards:
print(card)
if __name__ == "__main__":
main()
When I try to validate a deck, I only see the message “Loading data, please wait…” and nothing happens. So I’m not sure if it’s a problem with my JSON export, the file path, or the validator itself.
I’m not aware of a single tool, but you could ensure the deck is standard legal in any normal deck building tool, then additionally check it against the Penny Dreadful deck checker - if it passes both, it should be legal in your format (assuming I understand what you’re doing correctly.)
Edit: Nevermind, I see you’re limiting it to $1, not $0.01, despite borrowing the name. Penny Dreadful checker won’t work.
Yeah Penny Dreadful uses tix<=0.02 and this uses both tix<=0.1 and usd<=1
The list needs to be static. How can you create decks for a format that is constantly changing? What I need is a way to share a consistent list of legal cards so that everyone can search within the same list, rather than each person having a different version.
You can either go here https://mtg.wtf/deck
Or the same data is also exported to mtgjson if you want it in JSON format https://mtgjson.com/
The same data is also available in a few other export formats.
Source data for it is in https://github.com/taw/magic-preconstructed-decks with source URLs for every deck (some of these expired by now
and you'd need to go to the Web Archive - WotC redesigns its website every few years, killing old URLs).
Inferring exact set and collector number based on all available information is done algorithmically.
Everything should have correct names, quantities, and set codes.
A few cards won't have correct collector numbers. The list of cards which are generally expected to not have exact collector number:
"Plains",
"Island",
"Swamp",
"Mountain",
"Forest",
"Wastes",
"Azorius Guildgate",
"Boros Guildgate",
"Dimir Guildgate",
"Golgari Guildgate",
"Gruul Guildgate",
"Izzet Guildgate",
"Orzhov Guildgate",
"Rakdos Guildgate",
"Selesnya Guildgate",
"Simic Guildgate"
For everything else, the algorithm is exact as far as we know. Anything the algorithm can't detect automatically it flags, and we resolve it manually.
In case it matters, collector numbers are Gatherer-style not Scryfall-style (so DFCs are 123a / 123b, not 123 etc.). This only really affects cards with multiple parts.
You can download the .txt file for each decklist from MTGGoldfish by clicking on the "Download > Exact Card Versions (Tabletop)" button. However, please note that these files may not be compatible with Xmage due to differences in formatting. Nonetheless, creating a conversion script should not be too difficult.
analyze_deck_colors - reports colors of the deck according to correct algorithm [ http://t-a-w.blogspot.com/2013/03/simple-and-correct-algorithm-for.html ]
clean_up_decklist - clean up manually created decklist
cod2dck - convert Cockatrice's .cod to XMage's .dck
cod2txt - convert Cockatrice's .cod to .txt format
txt2cod - convert plaintext deck formats to Cockatrice's cod
txt2dck - convert plaintext deck format to XMage
txt2txt - convert plaintext deck format to plaintext deck format (i.e. normalize the decklist)
url2cod - download decklists from URL and convert to .cod (a few popular websites supported)
url2dck - download decklists from URL and convert to XMage .dck format
url2txt - download decklists from URL and convert to .txt format
data management
These are used to generate data in data/, you probably won't need to run them yourself
generate_colors_tsv_mtgjson - generate data/colors.tsv from mtgjson's AllSets-x.json (recommended)
generate_colors_tsv_cockatrice - generate data/colors.tsv from cockatrice's cards.xml (use mtgjson instead)
Open a terminal or command prompt on your computer. On Windows, you can do this by pressing the Windows key and typing "cmd" and then pressing Enter.
Navigate to the folder where the decks_v2.json file and the migrate_decks.py file are located. You can do this by typing cd followed by the path to the folder, such as cd C:\Users\YourName\Downloads\magic-preconstructed-decks-master.
Type python migrate_decks.py and press Enter to run the Python script.
Wait for the script to finish running. It will create a .dck file for each deck in the decks_v2.json file, with the desired structure.
Note: If you don't have Python installed on your computer, you can download it from the official website: https://www.python.org/downloads/. Choose the latest version for your operating system and follow the installation instructions.
decks.json has traditional cards + sideboard structure, with commanders reusing sideboard.
decks_v2.json has cards + sideboard + commander structure. You should use this one.
Data format
Data file i a JSON array, with every element representing one deck.
Fields for each deck:
name - deck name
type - deck type
set_code - mtgjson set code
set_name - set name
release_date - deck release date (many decks are released much after their set)
cards - list of cards in the deck's mainboard
sideboard - list of cards in the deck's sideboard
commander - any commanders deck has (can be multiple for partners)
Each card is:
name - card name
set_code - mtgjson set card is from (decks often have cards from multiple sets)
number - card collector number
foil - is this a foil version
count - how many of given card
mtgjson_uuid - mtgjson uuid
multiverseid - Gatherer multiverseid of card if cards is on Gatherer (optional field)
Data Limitations
All precons ever released by Wizards of the Coast should be present, and decklists should always contain right cards, with correct number and foiling, and mainboard/sideboard/commander status.
Source decklists generally do not say which printing (set and card number) each card is from, so we need to use heuristics to figure that out.
We use a script to infer most likely set for each card based on some heuristics, and as far as I know, it always matches perfectly.
That just leaves situation where there are multiple printings of same card in same set.
If some of the printings are special (full art basics, Jumpstart basics, showcase frames etc.), these have been manually chosen to match every product.
If you see any errors for anything mentioned above, please report them, so they can be fixed.
That just leaves the case of multiple non-special printings of same card in same set - most commonly basic lands.
In such case one of them is chosen arbitrarily, even though in reality a core set deck with 16 Forests would likely have 4 of each Forest in that core set, not 16 of one of them.
Feel free to create issue with data on exact priting if you want, but realistically we'll never get them all, and it's not something most people care about much.
This tool isn’t really needed given that there are multiple websites, where you can upload your collection and your deck, and they will tell you exactly which cards in the deck are missing from your collection.
For example:
So while a custom format legality checker is neat, if your goal is simply “which cards do I lack in this deck given my collection”, one of those sites will do just fine.
Commander with low power brackets, no tutors, no infinite combos, and mostly budget decks.
Cube Draft.
Playing precons against the computer using Forge. I copy the names of the precons from a block, then play them against each other using a bit of randomization:
I really used to like classic cards like Serra Angel and Shivan Dragon and I don't know exactly when they became so bad, but I couldn't even consider playing them now in most formats.
I believe Throne of Eldraine in 2019 was the set where power creep started accelerating most.
I've managed to write another script that seems to work:
I exported the Standard Penny collection from Moxfield to JSON using a Python script:
I saved the JSON file as
validator/formats/standardpenny.jsonand added it to the validator’s config:Then I tried to validate this deck exported as Plain Text from Moxfield and got the error.
When I try to validate a deck, I only see the message “Loading data, please wait…” and nothing happens. So I’m not sure if it’s a problem with my JSON export, the file path, or the validator itself.
No, it's just for reference.
Seems simple enough, so I'm going to try and make one myself. Here's the idea I have so far:
Yeah Penny Dreadful uses tix<=0.02 and this uses both tix<=0.1 and usd<=1
✅ This will create a fully Moxfield-compatible CSV with all cards from a Scryfall search.
My first try was using this script:
Query Scryfall + dump card names out for easy import into Moxfield
But when I tried importing the output csv in Moxfield, I got a bunch of
No card name found on line xerrors.The list needs to be static. How can you create decks for a format that is constantly changing? What I need is a way to share a consistent list of legal cards so that everyone can search within the same list, rather than each person having a different version.
Are you answering to the right post?
Forge not only has all the decks with their original printings but also has the capability to play against the AI.
You can download the .txt file for each decklist from MTGGoldfish by clicking on the "Download > Exact Card Versions (Tabletop)" button. However, please note that these files may not be compatible with Xmage due to differences in formatting. Nonetheless, creating a conversion script should not be too difficult.
https://github.com/taw/mtg
Here are step-by-step instructions to migrate
decks_v2.jsonto.dckfiles with the desired structure, assuming no prior knowledge of the command line:migrate_decks.py.decks_v2.jsonfile and themigrate_decks.pyfile are located. You can do this by typingcdfollowed by the path to the folder, such ascd C:\Users\YourName\Downloads\magic-preconstructed-decks-master.python migrate_decks.pyand press Enter to run the Python script..dckfile for each deck in thedecks_v2.jsonfile, with the desired structure.Note: If you don't have Python installed on your computer, you can download it from the official website: https://www.python.org/downloads/. Choose the latest version for your operating system and follow the installation instructions.
https://github.com/taw/magic-preconstructed-decks-data