this post was submitted on 20 Oct 2025
3 points (100.0% liked)

MTG

2357 readers
1 users here now

Magic: the Gathering discussion

General discussion, questions, and media related to Magic: the Gathering that doesn't fit within a more specific community. Our equivalent of /r/magicTCG!

Type [[Card name]] in your posts and comments and CardBot will reply with a link to the card! More info here.

founded 2 years ago
MODERATORS
 

Hi everyone, I’m trying to build decks for a custom format using this card pool (f:standard tix<=0.1 usd<=1). I have a deck here: deck link.

I know legality is ultimately whatever rules you define for a custom format, but I’m looking for a practical way to check a deck automatically against a specific pool, rather than checking each card one by one. For reference, Penny Dreadful has a deck legality checker. I’m wondering if there’s something similar for generic card pools, or if manual checking is the only option.

Is there an easy way to check if the deck is legal for this pool and identify any cards that aren’t allowed? Also, I’d love tips or strategies for making deckbuilding simple in a custom format like this. Thanks!

you are viewing a single comment's thread
view the rest of the comments
[–] counterspell@mtgzone.com 1 points 2 months ago

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()