Magic: The Gathering is a classic trading card game, with millions of players playing every day. It's a game with fantastic depth, built with systems allowing players to play in unexpected and exciting ways. In Commander, one of the most popular formats, four players fight in a free for all with 100 card decks, each of which has no repeating cards (with the notable exception of basic lands). To someone unfamiliar with Magic, this might sound like an outrageous amount of information; with up to 400 different cards between all the players, how could they possibly be expected to understand how to play? Are they supposed to simply memorize the over 27,000 Magic cards in existence? What sort of maniac would want to play a game like that?
Fortunately, Magic's cards are designed with strict parameters and formatting, allowing players to get at least a general idea of what a card does with only a glance. This formatting can be transcribed to JavaScript's classes, allowing us to describe the structure of a card, and demonstrate how each card can be read and interpreted. Following is what a top level "Card" class might look like. (For the sake of simplicity, we will ignore cards which cannot be included in a deck)
class Card {
constructor() {
this.name = "Card Name";
this.type = null;
this.subTypes = [];
this.manaCost = null;
this.colors = null;
this.rulesText = "";
this.loreText = "";
this.keyWords = [];
this.abilities = [];
}
}
This is the basic structure which all Magic: The Gathering cards will follow. Not every one of those fields will be filled on every card, but those are all the attributes which are common to all types of cards. Each type can be understood as a subclass of the "Card" class. For example, we can transcribe one of the simplest card types in the game; the Land Type.
class Land extends Card {
constructor(name, subTypes, colors, abilities) {
super();
this.name = name;
this.type = "Land";
this.subTypes = subTypes
this.colors = colors;
this.abilities = abilities;
}
}
The systems of Magic apply many more rules, abilities, and conditions to each card, but this Land class allows us to create a simple Land Card. If we wanted to recreate the Plains Basic Land, we would call our Land Class as follows:
const Plains = new Land(
"Plains", // card name
["Basic", "Plains"], // types
["White"], // color identity
["Tap: Add 1 White mana"] // ability
)
/*
The resulting Card should look something like this:
{
name: "Plains",
type: "Land",
subTypes: [ "Basic", "Plains" ],
colors: [ "White" ],
rulesText = "",
loreText = "",
keyWords = [],
abilities = [ "Tap: Add 1 White mana" ],
}
*/
This newly constructed card provides us with some essential information about how it interacts with the game. This information is usually put in the same position on every card. Basic Lands are actually one of the rare examples of a card where it is common for the abilities to not be explicitly printed on the card. This is because of a rule Wizards of the Coast added that tied the ability to tap for mana to the "Basic" typing. So let's try a non-basic Land; Tranquil Expanse.
On this card, we can identify several attributes which neatly fit within our class. We have the name ("Tranquil Expanse"), the type ("Land"), some rules text ("This land enters the battlefield tapped"), an ability ("Tap: Add 1 Green or White mana"), and some lore text ("Despite the chaos ..."). Notably this card is lacking subtypes, which is common for non-basic Lands.
Another type of card is the Creature card. Creatures are among the most iconic and versatile card types in Magic: The Gathering. They represent characters, monsters, and entities that enter the battlefield and can attack your opponents or defend against their creatures. Just like Lands, Creature cards follow a predictable structure that we can extend from our base Card class.
Let’s define what a Creature subclass might look like in JavaScript:
class Creature extends Card {
constructor(name, manaCost, colors, subTypes, power, toughness, rulesText, keyWords, abilities, loreText) {
super();
this.name = name;
this.type = "Creature";
this.subTypes = subTypes;
this.manaCost = manaCost;
this.colors = colors;
this.power = power;
this.toughness = toughness;
this.rulesText = rulesText;
this.keyWords = keyWords;
this.abilities = abilities;
this.loreText = loreText;
}
}
This class can be used to describe most creatures in the game. We can use the card Savannah Lions for example;
const SavannahLions = new Creature(
"Savannah Lions",
"W", // W = 1 white mana
["White"],
["Cat"],
2, // power
1, // toughness
"", // no special rules
[], // no keywords
[], // no abilities
"Once they ruled the savannah. Now they scrabble for territory at the fringes of civilization."
);
In Magic, even a simple creature like Savannah Lions follows the same consistent card structure. This makes it easier for players to understand new cards. As a rule of thumb, creatures always have power and toughness, and often have keywords like "Flying", "Trample", or "First Strike"—shortcuts for specific abilities defined by the rules of the game.
If you want to learn more about the anatomy of Magic cards, this is a great source from Wizards itself.
Top comments (0)