counterspell

joined 2 years ago
 

I noticed that Commander Legends: Battle for Baldur’s Gate was the last big release with a wide language range, and since then most sets have been printed in fewer languages. Does anyone know why Wizards started scaling back on localization after CLB?

 

For MTG (like everything else on the internet) it feels like the old forums are dead, replaced by a dozen different Discord servers where you’re lucky to get a rushed answer before your message gets swept away and forgotten. So what are good deckbuilding communities nowadays?

I’m currently building some nostalgia Commander decks based on decks I used to play when I started playing Magic.

Honestly, I’ve found better deckbuilding advice in old forum posts than on most Discords I’ve tried. Curious what places people use now for thoughtful feedback and discussion.

[–] counterspell@mtgzone.com 1 points 1 month ago* (last edited 1 month ago)

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.

[–] counterspell@mtgzone.com 5 points 1 month ago* (last edited 1 month ago)
  • 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.
[–] counterspell@mtgzone.com 6 points 1 month ago (1 children)

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.

 

If you enjoy playing alternative MTG formats like Penny Dreadful, Heirloom, Pauper, Tribal Apocalypse, or Pre‑modern on Magic: The Gathering Online, check out Gatherling. It’s built for player‑run tournaments and has impressive stats: over 74,000 unique decks and 218,000+ matches logged.

It features:

  • A full deck‑search function and meta overview.
  • Event listings for many niche formats.
  • Profiles, ratings, and participation history.
  • Direct login via Discord or local credentials.

Useful Discord communities for each format:

Some of these servers may be inactive, but they’re still worth checking out.

Related tools:

[–] counterspell@mtgzone.com 1 points 2 months ago* (last edited 2 months ago)

MTG Deck Legality Web Checker

A simple web tool for validating Magic: The Gathering decklists in a custom format.


Inspiration

This project was inspired by several sources:

  • Badaro's Validator GitHub, a simple web tool for checking card lists in "nostalgia" Magic the Gathering formats: https://badaro.github.io/validator
  • Penny Dreadful, an unofficial, budget-friendly MTG Constructed format where only cards costing 0.02 tix or less are legal. Decks are 60 cards with a 15-card sideboard, promoting creative play with inexpensive cards.
  • Heirloom Constructed, a fan-created format combining Legacy-style interactions with price caps. Cards are legal based on current prices, with different caps for mythics, rares, uncommons, and commons. The format rotates weekly after new Standard set releases, providing a dynamic but affordable competitive environment.

Features

  • Automatic setup: Downloads Oracle bulk-data from Scryfall and builds legality files on first run.
  • Custom format validation: Checks decks for banned or out-of-format cards.
  • Browser interface: Paste a decklist, click Validate, and view results instantly.

Installation

It is recommended to use a virtual environment to keep dependencies isolated.

1. Clone the Repository

git clone https://git.disroot.org/hirrolot19/mtg-legality-checker.git
cd mtg-legality-checker

2. Create and Activate a Virtual Environment

python -m venv venv
source venv/bin/activate

3. Install Dependencies

pip install -r requirements.txt

Running the App

From the project root (with the virtual environment activated):

python app.py

Then open your browser and navigate to:

http://127.0.0.1:5000/

First Run Behavior

On first launch, the app will:

  1. Download Scryfall’s Oracle card data.
  2. Filter legal cards for the custom format based on a Scryfall query. Default query is f:standard usd<=1 tix<=0.1
  3. Convert the filtered data into a validation JSON file.

This process may take a few minutes.
Once complete, cached files are stored persistently for future sessions.


Using the Web Checker

  1. Paste your decklist into the text box.
  2. Click Validate.
  3. The app displays any cards that are banned or not legal in the format.

Decklist Rules

  • One card per line.
  • Quantities accepted (4 Lightning Bolt, 2x Opt).
  • Comments start with #.
  • “Deck” or “Sideboard” headers ignored.

Advanced Usage

For detailed information about the supporting scripts and command-line tools, see tools/README.md.

 

Hello,

I’ve built a set of Python scripts to create a custom Magic: The Gathering legality checker using Scryfall and Moxfield. It fetches a card pool, converts Moxfield CSVs to JSON, and validates decks against that pool.

Right now, I'd have to update the format manually every few months. I host my repo on Forgejo, but I’m not sure if it supports GitHub-style workflow automation.

What’s the best way to automate this update process? Should I use a cron job, or are there other alternatives I should consider for a Forgejo-hosted repo?

I don’t have much experience with CI/CD or scheduled automation, so any guidance or examples would be greatly appreciated.

Thanks!

8
submitted 2 months ago* (last edited 1 month ago) by counterspell@mtgzone.com to c/mtg@mtgzone.com
 

Hey everyone!

I just finished building a web tool to help validate Magic: The Gathering decklists in any custom format. It fetches card data from Scryfall, checks for banned or illegal cards, and gives instant feedback right in your browser.

It’s perfect for experimenting with niche formats, casual play, or even building decks for some existing formats like Standard Penny Dreadful, 2015 Modern, Classic Legacy, Pre Fire Modern, Pre Horizons Modern, Pre Modern. It can also integrate with Moxfield for deck building.

Check it out here: https://git.disroot.org/hirrolot19/mtg-legality-checker

I’d love to hear your thoughts, suggestions, or ideas for improving it. Hope it helps deckbuilders and casual players alike!

[–] 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()
[–] counterspell@mtgzone.com 1 points 2 months ago* (last edited 2 months ago) (2 children)

I exported the Standard Penny collection from Moxfield to JSON using a Python script:

import csv
import json

input_csv = 'moxfield_haves_2025-10-21-1123Z.csv'
output_json = 'standard_penny.json'

sets = set()
cards = []

with open(input_csv, newline='', encoding='utf-8') as csvfile:
    reader = csv.DictReader(csvfile)
    for row in reader:
        name = row.get('Name')
        edition = row.get('Edition')
        if name:
            cards.append(name)
        if edition:
            sets.add(edition.upper())

sets = sorted(list(sets))

output_data = {
    "sets": sets,
    "cards": cards
}

with open(output_json, 'w', encoding='utf-8') as jsonfile:
    json.dump(output_data, jsonfile, indent=2)

print(f"JSON saved to {output_json}")

I saved the JSON file as validator/formats/standardpenny.json and added it to the validator’s config:

{ "name": "Standard Penny", "key": "standardpenny", "datafile":"formats/standardpenny.json" },

Then I tried to validate this deck exported as Plain Text from Moxfield and got the error.

[–] counterspell@mtgzone.com 1 points 2 months ago (3 children)

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.

[–] counterspell@mtgzone.com 2 points 2 months ago

No, it's just for reference.

[–] counterspell@mtgzone.com 1 points 2 months ago* (last edited 1 month ago)

Seems simple enough, so I'm going to try and make one myself. Here's the idea I have so far:

  1. User selects a default format or uploads a JSON list of legal cards.
  2. User pastes decklist text or uploads deck JSON.
  3. Script compares deck entries with legal list.
  4. Output = list of illegal cards.
 
[–] counterspell@mtgzone.com 1 points 2 months ago

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

 

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!

[–] counterspell@mtgzone.com 1 points 2 months ago

✅ This will create a fully Moxfield-compatible CSV with all cards from a Scryfall search.

import requests
import csv
import time

QUERY = "f:standard f:penny usd<=1"
BASE_URL = "https://api.scryfall.com/cards/search"
PARAMS = {
    "q": QUERY,
    "unique": "cards",
    "format": "json"
}

OUTPUT_FILE = "moxfield_import.csv"

FIELDNAMES = [
    "Count",
    "Tradelist Count",
    "Name",
    "Edition",
    "Condition",
    "Language",
    "Foil",
    "Tags",
    "Last Modified",
    "Collector Number",
    "Alter",
    "Proxy",
    "Purchase Price"
]

def fetch_all_cards():
    url = BASE_URL
    params = PARAMS.copy()
    while True:
        resp = requests.get(url, params=params)
        resp.raise_for_status()
        data = resp.json()
        for card in data.get("data", []):
            yield card
        if not data.get("has_more"):
            break
        url = data["next_page"]
        params = None
        time.sleep(0.2)

def write_cards_to_csv(filename):
    with open(filename, "w", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=FIELDNAMES)
        writer.writeheader()
        for card in fetch_all_cards():
            row = {
                "Count": 1,
                "Tradelist Count": "",
                "Name": card.get("name"),
                "Edition": card.get("set"),
                "Condition": "",
                "Language": card.get("lang"),
                "Foil": "Yes" if card.get("foil") else "No",
                "Tags": "",
                "Last Modified": "",
                "Collector Number": card.get("collector_number"),
                "Alter": "",
                "Proxy": "",
                "Purchase Price": ""
            }
            writer.writerow(row)

if __name__ == "__main__":
    write_cards_to_csv(OUTPUT_FILE)
    print(f"Saved all cards to {OUTPUT_FILE}")
[–] counterspell@mtgzone.com 2 points 2 months ago* (last edited 2 months ago)

My first try was using this script:
Query Scryfall + dump card names out for easy import into Moxfield

❯ python scryfall_search.py -q "f:standard f:penny usd<=1" --output-as-file "$HOME/desktop/out.csv"
Running Scryfall search on f:standard f:penny usd<=1 legal:commander
Found 1,197 total matches!

But when I tried importing the output csv in Moxfield, I got a bunch of No card name found on line x errors.

 

I want to play a custom MTG format where the card pool is defined by a Scryfall search and updated twice a year. For example, my search might be f:standard f:penny usd<=1.

How can I export, share, and import the list of legal cards with other people so that we can all check card legality and use a deck builder with the same pool of cards?

 

I personally use cockatrice, there's almost always a game available

MTGO and MTGA are the official clients (MTGA only has brawl. MTGO has commander but is also not particularly budget friendly). There are also unofficial ones like cockatrice, untap.in, xmage, forge (with some of these, you might be able to play commander, with others not). Many also play commander via webcam using https://spelltable.wizards.com/

source

I've been playing some Magic recently on Forge and considering rejoining my local game store (LGS). However, it seems like the company is pushing Commander a lot, and the most recommended way to play it is through Cockatrice. Nevermind, I'll keep playing on Forge, and maybe I'll try Cockatrice. I'm just not excited about playing a format where "Bobsponge" is a thing. It makes me wonder, what are they even doing with this game?

5
3x Core Set 2012 Draft on XMage (media.discordapp.net)
submitted 2 years ago* (last edited 2 years ago) by counterspell@mtgzone.com to c/digital@mtgzone.com
view more: next ›