The .mtgr format
Version: 0.3.0 (pre-1.0: any minor version may break compatibility)
Comprehensive Rules baseline: effective 2026-09-25, https://media.wizards.com/2026/downloads/MagicCompRules 20260925.txt
PGN baseline: "Standard: Portable Game Notation Specification and Implementation Guide" (Steven J. Edwards, 1994), https://www.saremba.de/chessgml/standards/pgn/pgn-complete.htm
1. Introduction
1.1 Purpose
.mtgr is a plain-text format for recording games of Magic: The Gathering. It plays the role for Magic that PGN plays for chess. A program that watches a game (a writer) produces a .mtgr file, and any program that understands this document (a parser) can read it, replay it, and check it.
A .mtgr file records:
- who played, when, where, and the result (tags, section 4);
- every object seen in the game, with an instance ID (section 6);
- every event, in order, with its cause, the choices made, and the costs paid (sections 7 to 9);
- the full game state at the start of the game and of every turn (keyframes, section 10);
- the full stack whenever a player receives priority with objects on it (section 9.9);
- optional annotations and alternative lines (sections 11 and 12).
For a one-page list of every keyword with an example, see the keyword reference. It is not normative.
1.2 Conformance language
The key words MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY are to be interpreted as described in RFC 2119 and RFC 8174 when, and only when, they appear in all capitals.
A writer is a program that produces .mtgr files. A parser is a program that reads them. A conforming file satisfies every MUST in this document.
1.3 One canonical format
There is exactly one format, equivalent to PGN's export format (PGN section 3.2). Every lexical detail is fixed, so the same game written by two conforming writers is identical byte for byte (PGN section 3.2.1). Writers MUST produce the canonical format. Parsers MAY reject anything that is not canonical. See decisions/0013-canonical-format.md.
1.4 Rules terms
Zones, phases, steps, priority, the stack, abilities, costs, and other game terms have their meaning from the Comprehensive Rules (CR). Where this document cites a rule, it gives the rule number from the CR baseline above. The reasoning behind each part of the format is in the numbered decision records in decisions/.
1.5 Point of view
Every game is recorded from one player's seat, named by the Perspective tag. Information hidden from that player is hidden in the file (CR 400.2). Every object still has an instance ID, so hidden cards can be counted, moved, and later identified. See decisions/0001-point-of-view.md.
2. Lexical rules
See decisions/0015-lexical-rules.md.
- A file is UTF-8 without a byte-order mark, in Unicode Normalization Form C. A file that is not NFC is invalid.
- Lines end with LF (U+000A) only. The file ends with LF.
- There is no line length limit. Lines are never wrapped.
- Tabs and other control characters are not allowed anywhere except LF at the end of a line.
- Tokens on a line are separated by exactly one space (U+0020). Indentation (section 5.2) is the only place several spaces appear in a row, outside strings and comments.
- Strings are enclosed in double quotes. Inside a string,
\"is a double quote,\\is a backslash, and\nis a line break. No other escape exists, and a backslash followed by any other character is invalid. Strings have no length limit. - Card names, ability text, player names, and all other free text are always strings, never bare words.
- Integers are written in decimal without leading zeros (
0,7,20) and without a sign. - Keywords (verbs, zone names, step names, and so on) are lowercase ASCII and are defined in this document. A keyword that is not defined here, and is not an extension (section 13), makes the file invalid.
3. File structure
A file holds one or more games. Each game is:
- a tag section: one tag per line (section 4);
- one empty line;
- the game body: one or more body lines (sections 5 to 12);
- the result line: the game's result marker (
1-0,0-1,1/2-1/2, or*) alone on a line, equal to itsResulttag (PGN section 8.2.6).
Consecutive games are separated by exactly one empty line. Empty lines appear nowhere else. A line whose first character is % is an escape line (PGN section 6): parsers MUST ignore it, and it may appear anywhere except inside the tag section.
The game is the unit. There is no match header: games of the same match share a Match tag value. See decisions/0012-file-structure-and-tag-roster.md.
4. Tags
4.1 Syntax
A tag is [Name "value"] alone on a line, left justified, with a single space between name and value (PGN section 8.1). Tag names consist of ASCII letters, digits, and underscore, and begin with an uppercase letter. No tag name appears twice in a game. Tag values are strings (section 2).
4.2 Required tags
Every game has these tags, in this order, before any other tag:
| Tag | Value |
|---|---|
Mtgr | Format version of this game, for example "0.3.0". |
Event | Event name, for example "Modern League". "?" if unknown. |
Site | Where the game was played: a client such as "MTGO" or "Arena", or a venue for paper Magic. "?" if unknown. |
Date | Start date, YYYY.MM.DD, with ? for each unknown digit. For online sites, the UTC date. |
Round | Tournament round, for example "3" or "3.1". "-" where rounds do not apply; "?" if unknown. |
Player1 | First player in the match's seat order. Fixed for the whole match. |
Player2 | Second player in the match's seat order. |
Result | "1-0" (Player1 won), "0-1" (Player2 won), "1/2-1/2" (draw), or "*" (unfinished, abandoned, or unknown). |
Format | Game format, for example "Modern". "?" if unknown. |
Match | Identifier shared by every game of the same match. Any string. |
Game | Game number within the match, starting at "1". |
Perspective | The player whose seat the game is recorded from. MUST equal Player1 or Player2. |
Player1 and Player2 MUST differ. Seat order does not change between games of a match; who plays first is recorded in the body (section 9.1).
4.3 Optional core tags
These tags MAY follow the required tags. Each is omitted when unknown.
| Tag | Value |
|---|---|
Annotator | Who added annotations (PGN section 9.9.1). |
Player1Archetype | Archetype of Player1's deck, as commonly named in the format, for example "Izzet Murktide" (section 4.6). |
Player2Archetype | Archetype of Player2's deck (section 4.6). |
Recorder | Name and version of the writer that produced the game, for example "MtgoReplay 0.1.0 (MTGOSDK 1.8.1.20261028)". |
RoundTime | Round time limit in seconds, for a match played under a round timer (section 10.4). |
Termination | Why the game ended (section 4.4). |
TimeControl | Per-player clock as in PGN section 9.6.1, for example "1500" for 25 minutes each with no increment. |
UTCDate | Start date in UTC, YYYY.MM.DD. |
UTCTime | Start time in UTC, HH:MM:SS. |
4.4 Termination values
| Value | Meaning | Basis |
|---|---|---|
"life total" | A player lost with 0 or less life. | CR 104.3b, 704.5a |
"empty library" | A player lost by drawing from an empty library. | CR 104.3c, 704.5b |
"poison" | A player lost with ten or more poison counters. | CR 104.3d |
"concession" | A player conceded. | CR 104.3a |
"card effect" | An effect made a player win or lose. | CR 104.2b, 104.3e |
"draw" | The game was a draw under the game rules. | CR 104.4 |
"time forfeit" | A player's clock ran out. | PGN 9.8.1 |
"rules infraction" | A player was penalised with a game loss. | PGN 9.8.1 |
"adjudication" | A judge or the site decided the result. | PGN 9.8.1 |
"disconnect" | A player was disconnected and lost. | source |
"abandoned" | The game was abandoned. | PGN 9.8.1 |
"unterminated" | The game did not end. | PGN 9.8.1 |
4.5 Tag order
After the required tags, every other tag (optional core tags and extension tags) appears in ASCII order of tag name.
4.6 Archetypes
Player1Archetype and Player2Archetype classify each player's deck by archetype, the way PGN's Opening tag classifies a chess game by opening (PGN section 9.3.1). There is no registry of names; the value is the name commonly used in the format.
An archetype is a classification, not game data. It MAY be set by the writer, by the player, or later by another tool, and it MAY be set for the opponent from the cards they revealed. A reader MUST NOT derive game state from it. When no classification is known, the tag is omitted. Each player's archetype SHOULD be the same in every game of a match: sideboarding changes a deck (CR 100.4) without making it a different archetype. This is a classification convention, not a rule; in Limited a player may rebuild their deck between games (CR 100.4b), and a tool may then classify each game separately.
The archetype is not the deck block's name (section 10.5), which is the perspective player's own label for their list. See decisions/0028-archetypes.md.
5. Body lines
5.1 Line shape
Every body line has this shape:
TIME SP INDENT STATEMENT [SP CAUSE [SP REPLACEMENT]...] [SP NAG]* [SP BRACE-COMMENT] [SP LINE-COMMENT]- TIME is the elapsed time since the game started,
M:SSorM:SS.fwith one to three fraction digits (for example0:41,12:05,1:52.374). Minutes have no upper limit and no leading zero. Writers SHOULD use the same precision for every line of a game. Inside a variation, TIME is-(section 12). TIME is informational: line order is the authoritative order of events, and parsers MUST NOT reorder lines by time. Time never decreases from one main-line body line to the next. - INDENT is two spaces per nesting level (section 5.2), possibly empty.
- STATEMENT is one of the statements defined in sections 6 to 12.
- CAUSE and REPLACEMENT are defined in section 8.
- NAG, BRACE-COMMENT, and LINE-COMMENT are annotations (section 11).
Stack entries and keyframe entries also carry TIME, equal to the time of the line they belong to.
5.2 Nesting
Indentation shows structure. Each line's level is one more than its parent's.
| Level | Lines |
|---|---|
| 0 | deck, pregame, turn |
| 1 | deck entries; keyframe; step lines; events inside pregame |
| 2 | keyframe entries; events inside a step |
| +1 | stack under a priority line |
| +2 | stack entries |
Events inside pregame sit at level 1; events inside a step sit at level 2. A stack line is one level deeper than its priority line, and its entries one level deeper again.
5.3 Body order
A game body is, in order:
- one
deckblock (section 10.5); - one
pregameblock (section 9.1); - one
turnblock per turn, in order (section 9.2).
The game ends with the last body line; the result line follows.
A recording that starts late, or loses track of the game, writes incomplete (section 9.8). Turns after an incomplete line MAY be missing: the next turn line resumes the record. Before that turn's keyframe, new lines MAY introduce objects directly in the zones where the keyframe shows them.
6. Objects
6.1 Instance IDs
Every object seen in the game has an instance ID: # followed by a positive integer without leading zeros. IDs are assigned in increasing order of first appearance, starting at #1 for each game, and are never reused within a game. See decisions/0002-card-identity.md and decisions/0003-ability-identity.md.
An ID lasts as long as the object can be tracked, which is longer than the CR's notion of an object (CR 400.7): a card keeps its ID from hand to stack to battlefield to graveyard. An ID ends when:
- the object's library is shuffled (every tracked object in that library loses its ID, CR 701.24a);
- an
untrackedline ends it (section 7.3), because the object can no longer be told apart from others; - the object ceases to exist (
cease, section 7.3).
A card that becomes trackable again gets a new ID with a new new line.
6.2 Untracked library cards
A card in a library that cannot be told apart from the other cards in that library has no ID. Each library holds a number of untracked cards plus any tracked objects. The total is the library's size (CR 401.3), recorded in keyframes. A new line with in library takes one card out of the untracked pool and gives it an ID.
At the start of the game every card in every library is untracked.
6.3 Object references
An object is referred to by its ID, followed by its name when it has a known name:
#7 "Ugin's Labyrinth"
#16- A card, token, or copy whose name is known MUST be written with its name. A hidden card, and any ability, MUST be written without one.
- The name is the object's current name as recorded in
neworidentify. The ID is authoritative. A name that does not match the object's recorded name makes the file invalid.
6.4 Names and printings
A card name is the card's English Oracle name (CR 201.2, 108.1), written exactly, including accented letters. Multi-faced cards use every face name separated by //. Writers MUST convert source spellings that differ from Oracle (for example Æther Vial to Aether Vial).
A printing is a set code and a collector number, both strings: print "MH3" "233". Writers SHOULD include it whenever the source knows it.
A source ID is a source prefix, a colon, and the source's own identifier: src mtgo:126485. Source IDs are optional and the file must be meaningful without them. Prefixes are listed in section 13.2.
6.5 Introducing objects: new
Every object is introduced by a new line at the point it is first seen, before any other line refers to it.
| Statement | Introduces |
|---|---|
new card ID NAME owner PLAYER in ZONE [POSITION] [print SET NUMBER] [src SOURCEID]... | A card whose name is known. |
new hidden ID owner PLAYER in ZONE [POSITION] | A card whose name is hidden from the perspective player. |
new token ID NAME owner PLAYER in ZONE [ENTERING] CAUSE | A token (CR 111.1). Its owner is the player who created it (CR 111.2). |
new copy ID of OBJREF NAME owner PLAYER in ZONE CAUSE | A copy of a card or spell (CR 707.2, 707.10). A copy of a spell has the original's choices (section 7.2). |
new copy ID of ID controller PLAYER in stack CAUSE | A copy of an activated or triggered ability (CR 707.10). It has the original's text and choices. |
new ability ID KIND of OBJREF TEXT controller PLAYER [in stack] [from ID] | An activated, triggered, loyalty, or mana ability (CR 113.1c, 405.1). from ID names the effect a delayed triggered ability came from (section 9.10). |
new effect ID of OBJREF TEXT controller PLAYER CAUSE | A lasting effect (section 9.10). |
new emblem ID TEXT owner PLAYER CAUSE | An emblem in the command zone (CR 114.1, 114.2). |
ZONEis a zone keyword (section 6.7).in librarytakes a card from the untracked pool (section 6.2).POSITION(top Norbottom N, counted from that end,1being the end card) says which card, when known: Impulse's four cards aretop 1totop 4.new cardis used whenever the perspective player knows the name by the time the object leaves the zone it is introduced in: a card they search for, or the top card of a library exiled face up.new hiddenis used only for cards whose name stays hidden.ENTERINGis the same as for moves to the battlefield (section 7.1):[face NAME] [tapped] [attacking PLAYER|OBJREF] [pt PT].KINDisactivated,triggered,loyalty, ormana(CR 113.3b, 113.3c, 605.1a, 606.1).of OBJREFnames the ability's source.TEXTis the ability's rules text as the source reports it, as a string, or?when the source does not report it. Writers MUST include the text when the source provides it and MUST NOT reconstruct it from an external database and present it as reported.- A triggered, activated, or loyalty ability is written
in stack: thenewline is the ability being put on the stack (CR 602.2a, 603.3). A mana ability has noinclause: it never goes on the stack (CR 605.3b) and its line is its activation. - A card in a hand, library, or graveyard is in its owner's zone (CR 400.3). A permanent's controller is its owner until a
controlline changes it.
6.6 Hidden objects and identify
A hidden object is written by ID only. When its name becomes known to the perspective player, an identify line binds the name to the ID:
OBJREF identify NAME [print SET NUMBER] [src SOURCEID]...A name becomes known when the card is revealed (CR 701.20a) or moves to a public zone (CR 400.2). The identify line comes immediately before the first line that needs the name. identify is only valid on a hidden object, and only once.
When a source cannot say which hidden card in a player's hand an event involves (for example which unknown card in the opponent's hand was played), the writer MUST use the lowest-numbered hidden object in that hand. Such hidden objects are interchangeable, and parsers MUST NOT treat the choice as information. This does not apply to libraries, where tracked cards have positions (CR 400.5): an unknown card leaving a library is a new object taken from the untracked pool.
6.7 Zones
| Keyword | Zone | Owned by |
|---|---|---|
library | library | each player (CR 400.1) |
hand | hand | each player |
graveyard | graveyard | each player |
battlefield | battlefield | shared |
stack | stack | shared |
exile | exile | shared |
command | command zone | shared |
ante | ante | shared |
outside STRING | outside the game (not a zone, CR 400.11), with a label saying where. A card in a player's sideboard (CR 100.4), including a companion, is outside "sideboard". | n/a |
7. Object statements
An object statement starts with an object reference: OBJREF VERB ARGUMENTS [CAUSE].
7.1 Moving
| Statement | Meaning | Cause |
|---|---|---|
play from ZONE [face NAME] [tapped] [pt PT] | The controller plays a land (special action, CR 116.2a, 305.1). It moves to the battlefield. | none |
cast from ZONE [face NAME | fused] | The controller casts the card: it moves to the stack (CR 601.2a). fused casts both halves of a split card with fuse (CR 702.102a). | see below |
move ZONE -> ZONE [as ACTION] [top | bottom] [ENTERING] [with ID] | The object moves between zones. ENTERING is [face NAME] [tapped] [attacking PLAYER|OBJREF] [pt PT], only on moves to the battlefield. | required |
casthas a cause only when the card is cast while another spell or ability is resolving and allows it, such as cascade, discover, or suspend's last time counter (CR 117.2e):by ID, naming that spell or ability. A card cast as a player's own action, including with flashback or from plot, has no cause.as ACTIONnames the keyword action that moved it, when there was one:draw(CR 121.1),discard,sacrifice,destroy,mill.toporbottomgives the position in a library. A move to a library without a position puts the object at an unknown position. When several cards are put on the bottom together in a random order (cascade, CR 702.85a), each is amove ... -> library bottomline, but the order of the lines is not their order: their positions among those bottom cards are unknown, and keyframes give them no position.tappedrecords that a permanent enters the battlefield tapped: a land whose "As this land enters" payment was declined (CR 614.1c), a land that always enters tapped (CR 614.1d), or a token created tapped (CR 110.5b). Entering tapped is part of how the permanent enters, so it is not a separatetapline: the permanent never "becomes tapped".attacking PLAYER|OBJREFrecords that a creature is put onto the battlefield attacking that player, planeswalker, or battle (CR 508.4), for example a token "tapped and attacking" or a creature put in with ninjutsu. It is not anattackline: such creatures never "attacked".face NAMEsays which face or half of a multi-faced card is used: the half of a split card being cast (CR 709.3), an Adventure (CR 715.3), the face of a modal double-faced card being cast (CR 712.11b) or played as a land (CR 712.12), or the face a double-faced permanent enters with. The object's name stays the full card name. On acastlinefaceis always written for a card cast as one face or half. A permanent's front face is the first part of its name, and a permanent entering or showing its front face is written withoutface:faceonplay,move,new, and keyframe entries names a face other than the front.pt PTgives the power and toughness a creature enters with (section 7.5). A permanent that enters with counters ("enters with a +1/+1 counter", CR 122.6) has acountersline straight after its move, caused by the object that gave them; its enteringptalready includes them, so noptline follows.with IDrecords that an exiled card is "exiled with" that object, for linked abilities (CR 406.6, 607.2a). The link ends when either object leaves the zone it was in, because it becomes a new object (CR 400.7, 607.2a). Bouncing and replaying Ugin's Labyrinth breaks its link to the card it exiled. One exception: cards exiled to pay a permanent spell's cost stay linked to the permanent the spell becomes (CR 607.2q), so cards Murktide Regent delved staywithit on the battlefield.
Replacement effects. When a replacement effect changes how an event happens and involves a choice or a payment ("As this land enters, you may pay 2 life", CR 614.1c, 614.12), the choice and payment lines come immediately before the line for the event they change:
0:44 #1 "Watery Grave" choose option "pay 2 life"
0:44 "PlayerA" life 20 -> 18 by #1
0:44 #1 "Watery Grave" play from hand7.2 Choices and targets
Choices are separate lines on the object they belong to, in the order the rules make them: modes and costs (CR 601.2b), then targets (CR 601.2c), then other choices. See decisions/0005-choices-and-costs.md.
Targeting and choosing are different. target records a target (CR 115.1), and only targets are affected by hexproof, ward, and other abilities that care about targeting (CR 702.11b, 702.21a). choose object and choose player record an object or player chosen without targeting, usually as the spell or ability resolves (CR 115.10), for example a vote (CR 701.38a).
Who chose. A choice is made by the controller of the object it belongs to unless its line ends with by PLAYER, naming the player who made it. by PLAYER MUST be written when someone other than the controller makes the choice: an opponent deciding whether to pay a ward cost, or each player's vote. It MUST NOT be written when the controller chose. No other cause is written on a choice line.
Copies. A copy of a spell or ability has the original's recorded choices, in the same order (CR 707.10): its modes, costs, X, targets, and every other choice. None of them is written again. When the copy's controller may choose new targets (CR 707.10c), target lines straight after the copy's new line are the copy's targets: they replace every copied target, so they list all of the copy's targets, changed or not. With no target line there, the copy keeps the original's targets. See decisions/0038-copies-of-spells-and-repeated-costs.md.
A choice that belongs to no spell or ability, such as which legendary permanent to keep (CR 704.5j) or which replacement effect to apply first (CR 616.1), is a player statement: PLAYER choose CHOICE CAUSE, with a required rule cause, for example "PlayerA" choose object #5 "Ragavan, Nimble Pilferer" by rule:sba.
| Statement | Meaning | Cause |
|---|---|---|
choose mode TEXT | A mode of a modal spell or ability, quoted as the source reports it (CR 700.2). | chooser |
choose cost TEXT | An additional or alternative cost the player chose to pay, by name, for example "kicker" (CR 118.8, 118.9). A cost paid more than once, such as replicate or multikicker, is one line per payment (CR 702.56a, 702.33c). Casting a spell without paying its mana cost is the alternative cost "without paying its mana cost" (CR 118.9). | chooser |
choose x INTEGER | The value of X (CR 107.3). | chooser |
choose symbol SYMBOL PAYMENT | How a hybrid or Phyrexian mana symbol in the cost will be paid (CR 601.2b): a nonhybrid symbol, or life for a Phyrexian symbol paid with 2 life. One line per symbol, in the order of the cost. | chooser |
choose color COLOR | A color: white, blue, black, red, or green (CR 105.1). | chooser |
choose option TEXT | A choice offered in words, such as a "may" instruction, quoted as the source reports it. | chooser |
choose object OBJREF | An object chosen without targeting. | chooser |
choose player PLAYER | A player chosen without targeting. | chooser |
choose number INTEGER | A number. | chooser |
choose name NAME | A card name. | chooser |
choose type TEXT | A card type, subtype, or other characteristic. | chooser |
choose hidden | A choice was made, but its value is hidden from the perspective player. | chooser |
target OBJREF|PLAYER [amount INTEGER] | A target, with the amount when an effect is divided (CR 601.2c, 601.2d). | none |
7.3 Other object events
| Statement | Meaning | Cause |
|---|---|---|
tap | The permanent becomes tapped. | required |
untap | The permanent becomes untapped. | required |
attach OBJREF | The object becomes attached to another. | required |
unattach | The object becomes unattached. | required |
control PLAYER | The object's controller changes. | required |
counters TEXT INTEGER -> INTEGER | The number of counters of a kind changes, for example counters "+1/+1" 0 -> 2. | required |
pt PTVALUE -> PTVALUE | The creature's power and toughness change (section 7.5). | required |
damage OBJREF|PLAYER INTEGER [prevented] | The object deals damage. Damage that is partly prevented is written with the amount actually dealt and replacement ID (section 8). Damage that is completely prevented is written with the amount that would have been dealt, prevented, and replacement ID: it was never dealt (CR 615.6). | required |
attack PLAYER|OBJREF | The creature is declared as an attacker (CR 508.1). Declaring it taps it (CR 508.1f), written as a separate tap by rule:declare-attackers line, except for creatures with vigilance (CR 702.20b). | none |
block OBJREF | The creature is declared as a blocker of that attacker (CR 509.1). | none |
reveal | The object is revealed (CR 701.20a). A hidden object is identified first. | required |
look PLAYER | The player looks at the object (CR 701.20e). If the perspective player looks at a hidden object, it is identified first. | required |
identify NAME ... | See section 6.6. | none |
untracked | The object can no longer be told apart from other cards in its zone. Its ID ends. | none |
transform | The double-faced permanent turns over to its other face (CR 701.27a). | required |
become-copy OBJREF | The object becomes a copy of another (CR 707.2). Its name becomes the copied object's name, written after the OBJREF. For an object that enters as a copy (CR 707.5), the line comes before the move onto the battlefield. When the object leaves the battlefield it becomes a new object and the copy effect no longer applies (CR 400.7): the move line uses the copied name, and lines after it use the card's own name. | required |
special ACTION | The player takes a special action with this card (CR 116.2): companion (116.2g), suspend (116.2f), or plot (116.2k). Its costs are by cost:ID of this card, and its effects by ID. | none |
goad | The creature becomes goaded by the controller of the cause (CR 701.15a, 701.15b). | required |
end-goad PLAYER | The creature stops being goaded by that player, as that player's next turn begins (CR 701.15a). | required |
cease | The object ceases to exist: an ability after it leaves the stack (CR 608.2n); a token outside the battlefield (CR 111.7); a copy of a spell or card outside the zones it can exist in (CR 704.5e, 707.10a); an effect when its duration ends (section 9.10). Its ID ends. | required |
7.4 Leaving the stack
| Statement | Meaning | Cause |
|---|---|---|
resolve | The top object of the stack begins to resolve (CR 405.5, 608.2). Lines caused by its effects follow. | none |
fizzle | The object does not resolve because every target is illegal (CR 608.2b). The cause, when the source knows it, is the object whose effect made the targets illegal, for example by #9 for a Veil of Summer that gave the target player hexproof. | optional |
countered | The object is countered (CR 701.6a). | required |
Every object that leaves the stack does so with exactly one explicit line:
- a card or a copy of a card moves with
move stack -> ZONE: to the battlefield for a permanent spell (CR 608.3a), to its owner's graveyard for an instant or sorcery (CR 608.2n) or a countered spell (CR 701.6a), or wherever an effect puts it; - an ability ceases to exist with
cease.
A triggered ability that is removed from the stack because no legal choice can be made for it (CR 603.3d) or no mode is chosen (CR 700.2b) is written cease by rule:no-choice straight after its new line. One whose intervening "if" clause is false as it resolves (CR 608.2a) is written resolve, then cease by rule:intervening-if.
A copy of a permanent spell becomes a token as it resolves (CR 608.3f). It keeps its ID, and from then on it is a token.
An effect that does nothing writes no line. For example, ward's "counter that spell unless that player pays" does nothing to a spell that can't be countered (CR 101.2): the ward ability resolves and ceases, and the spell stays on the stack with no countered line.
After resolve that line has cause by rule:resolve (or by rule:intervening-if); after fizzle, by rule:fizzle; after countered, the same cause as the countered line. An object that resolves or fizzles MUST be the top object of the stack (CR 608.1). A countered object can be anywhere on the stack: a counterspell resolves from the top and counters an object below it (CR 701.6a).
7.5 Power and toughness
Power and toughness are recorded as state, like life totals: what the object's power and toughness are, not how the rules arrived at them. Writers record what the source reports, so they do not need a rules engine. See decisions/0027-power-and-toughness.md.
PTis power, a slash, and toughness, each an integer that may be negative:2/1,0/0,-1/1(CR 208.1).PTVALUEis aPT,nonefor a permanent that is not a creature (CR 208.3), or?when the source does not report it.- Entering. A creature that enters the battlefield, by any statement, MUST have
pt PTon that line:move stack -> battlefield pt 2/1 by rule:resolve,new token ... pt 4/4 by #61. This includes creature tokens, which have no card to look up. - Changes. Every change to a creature's power or toughness MUST be written as
OBJREF pt OLD -> NEW CAUSEstraight after the event that caused it, whatever the cause: a spell or ability ("gets -1/-0 until end of turn"), counters (CR 122.1a), a static ability starting or stopping to apply (an anthem entering), or a characteristic-defining ability (Tarmogoyf, CR 604.3). The cause is the object whose effect or ability changed it. Several simultaneous changes to one creature are one line. - Becoming or stopping being a creature. A permanent that becomes a creature (Mutavault, a crewed Vehicle) is written
pt none -> 2/2; one that stops is writtenpt 2/2 -> none. - End of turn. "Until end of turn" changes end in the cleanup step (CR 514.2), written
pt 5/5 -> 2/2 by rule:cleanup. A creature that leaves the battlefield becomes a new object (CR 400.7), so its power and toughness need no line. - Combat damage. A creature assigns combat damage equal to its power (CR 510.1a), so a parser can compare
damagelines with the recorded power.
7.6 Cost changes
Effects can increase or reduce the cost of a spell or ability, or set it outright (Trinisphere: "each spell that would cost less than three mana to cast costs three mana to cast"). Each such effect that changes the mana component of the total cost (CR 601.2f) is written as a line on the spell or ability:
OBJREF cost OLD -> NEW CAUSE0:44 #2 "Thoughtseize" cast from hand
0:44 #2 "Thoughtseize" target "PlayerB"
0:44 #2 "Thoughtseize" cost {B} -> {1}{B} by #30
0:44 #2 "Thoughtseize" cost {1}{B} -> {2}{B} by #31
0:44 "PlayerA" pay {U}{B}{B} by cost:#2- Where. After the spell's or ability's choices and targets, and before any mana abilities activated while it is being cast and its
paylines (CR 601.2g, 601.2h), one line per effect in the order the effects were applied (CR 601.2f): cost increases, then cost reductions in the order the player chose, then effects that apply to the total cost, such as Trinisphere. OLDis the cost before that effect: for the first line, the mana cost or alternative cost plus any additional costs chosen (CR 601.2b, 601.2f), which is{0}for a spell cast without paying its mana cost (CR 118.9d), even one with no mana cost at all (CR 118.6a); for each later line, the previous line'sNEW.NEWis the cost after it.- The cause is the object whose ability changed the cost, for example a permanent with a static ability such as Thalia, Guardian of Thraben (#30) or Trinisphere (#31).
- No change, no line. A spell whose cost no effect changes has no
costline; itspaylines are the whole record. COSTis written in cost notation (CR 107.4): the generic amount as one number first (omitted when it is zero, unless the whole cost is{0}), then the other symbols in the order{W}{U}{B}{R}{G}{C}{S}. Hybrid and Phyrexian symbols never appear: the player announces how each will be paid before the total cost is determined (CR 601.2b), soOLDalready has the announced symbols, and Phyrexian symbols announced as 2 life are left out of it (their life is paid with the cost, as alifelineby cost:ID). Seedecisions/0033-hybrid-and-phyrexian-mana.md.{X}is never written: X is replaced by its chosen value (CR 107.3). A cost reduced to nothing is{0}(CR 118.7).- Paying without mana. Delve, convoke, and improvise pay part of the total cost by exiling cards or tapping permanents instead of spending mana (CR 702.66a, 702.51a, 702.126a). They are not cost changes and have no
costline (CR 702.66b, 702.51b, 702.126b). Each card or permanent used is a line causedby cost:ID, written after the mana abilities and before thepayline:#9 "Fatal Push" move graveyard -> exile with #6 by cost:#6,#12 "Llanowar Elves" tap by cost:#20. The cards exiled, the permanents tapped, and the mana paid together make up the lastNEW(or the cost, when there is nocostline). Seedecisions/0034-delve-convoke-and-improvise.md. - Changes to the non-mana parts of a cost (life, sacrifices, discards) are not yet covered (section 15).
See decisions/0031-cost-changes.md.
8. Causes
A cause ends a statement and says why it happened. See decisions/0004-causality.md.
| Cause | Meaning |
|---|---|
by ID | The effect of that spell, ability, or permanent (including static and replacement effects, CR 609.1, 614.1). |
by cost:ID | Done to pay a cost of that spell or ability (CR 601.2f to 601.2h), including "unless" payments made as it resolves (CR 118.12a), or of a special action taken with that card (CR 116.2). |
by PLAYER | The player's own action, where no other verb records it. On a choice line, the player who made the choice (section 7.2). |
by rule:NAME | A game rule (table below). |
by source:NAME | An event from the game client, outside the CR: clock (a clock ran out) or disconnect. |
by ? | The cause is unknown. |
Replacement effects. When a replacement effect changes an event (CR 614.1a, 614.6), the event's line keeps its original cause and adds replacement ID after it, naming the object whose replacement effect applied. The line shows the event as it actually happened. For example, a card that Thoughtseize makes PlayerB discard while PlayerA controls Leyline of the Void is exiled instead of going to the graveyard:
0:53 #10 "Ragavan, Nimble Pilferer" move hand -> exile as discard by #18 replacement #15The card is still discarded (CR 701.9a describes the discard, and CR 614.6 says only the modified event happens), so as discard stays. When more than one replacement effect applies, each gets its own replacement ID, in the order they were applied (CR 616.1). Prevention effects (CR 615.1) are written the same way. Choices and payments for a replacement effect ("As this land enters, you may pay 2 life") are written as in section 7.1, not with replacement.
A statement whose Cause column says "required" MUST have a cause; by ? satisfies this. "Optional" means a cause MAY be written. "None" means a cause MUST NOT be written. "Chooser" means the rule in section 7.2: by PLAYER only, when someone other than the controller chose.
Rule causes:
| Name | Rule |
|---|---|
opening-hand | Each player draws their starting hand (CR 103.5). |
mulligan | A mulligan's shuffle, draw, and cards put on the bottom (CR 103.5). |
untap | The untap step's untap (CR 502.3). |
draw | The draw step's draw (CR 504.1). |
combat-damage | Combat damage (CR 510.2). |
cleanup | Cleanup step actions (CR 514.1, 514.2). |
sba | A state-based action (CR 704.3). |
empty-pool | Unspent mana lost as a mana pool empties (CR 106.4). |
resolve | A spell or ability leaving the stack as it finishes resolving (CR 608.2n, 608.3a), and an Aura spell becoming attached as it resolves (CR 608.3c). |
fizzle | A spell or ability leaving the stack because its targets are illegal (CR 608.2b). |
no-choice | A triggered ability removed from the stack because no legal choice can be made or no mode is chosen (CR 603.3d, 700.2b). |
intervening-if | A triggered ability removed as it resolves because its intervening "if" clause is false (CR 608.2a). |
declare-attackers | Attacking creatures becoming tapped (CR 508.1f). |
lore | Lore counters put on Sagas as the precombat main phase begins (CR 703.4f). |
replacement-order | The affected player choosing which replacement effect to apply (CR 616.1). |
duration | An effect ending because its stated duration is over (CR 611.2a). |
delayed-trigger | A delayed triggered ability ending because it has triggered and triggers only once (CR 603.7b). |
day-night | The game becoming day or night in the untap step (CR 731.2). |
9. Player and game statements
A player statement starts with the player's name as a string: PLAYER VERB ARGUMENTS [CAUSE]. The name MUST equal Player1 or Player2.
9.1 Pregame
pregame (level 0) opens the pregame block. Its first child is a keyframe (section 10). Then, in order (CR 103.1 to 103.6):
| Statement | Meaning | Cause |
|---|---|---|
PLAYER roll [dINTEGER] INTEGER | The player rolls a die with the given result, to decide who chooses the starting player (CR 103.1). The number of sides is written when known, for example roll d20 15. | none |
PLAYER choose first PLAYER | The player chooses who takes the first turn (CR 103.1). | none |
PLAYER mulligan | The player declares a mulligan (CR 103.5). | none |
PLAYER keep | The player keeps their hand (CR 103.5). | none |
Revealing a companion (CR 103.2b) comes after the starting player is chosen and before the opening hands are drawn. The card is introduced outside the game in its owner's sideboard, then revealed, caused by its own companion ability:
0:12 new card #1 "Lurrus of the Dream-Den" owner "PlayerA" in outside "sideboard"
0:12 #1 "Lurrus of the Dream-Den" reveal by #1The starting player's companion comes first, then each other player's in turn order. A player who reveals no companion writes no line. The card stays outside the game (CR 103.2b) and is listed in keyframes as a companion (section 10.3) until it is put into the game. See decisions/0029-companions.md.
The opening hands are drawn with new and move library -> hand as draw by rule:opening-hand lines. A mulligan is written as the player's hand moving to the library (by rule:mulligan), the shuffle, the new hand drawn, and the cards put on the bottom, in that order (CR 103.5).
Opening hand actions (CR 103.6) come after every player has kept: the starting player's first, then each other player's in turn order. They use ordinary statements, caused by the card that allows them:
- beginning the game with a card on the battlefield (CR 103.6a) is a move from hand to battlefield, for example
#4 "Leyline of the Void" move hand -> battlefield by #4; - revealing a card from the opening hand (CR 103.6b) is a
reveal, for example#5 "Chancellor of the Annex" reveal by #5. If revealing it creates a delayed triggered ability ("If you do, at the beginning of your first upkeep, ..."), anew effectline follows (section 9.10); - anything else the card does is written the same way. Counters a permanent is given as it enters are a
countersline straight after its move (CR 122.6).
A card that is not used this way writes no line. Cards that act during the mulligan process, such as Serum Powder, are written with ordinary moves and draws caused by that card, at the point they are used.
9.2 Turns, phases, and steps
turn INTEGER PLAYER (level 0) opens a turn and names the active player. Its first child is a keyframe (section 10). Then one line per step or main phase that occurs, in order (CR 500.1):
untap upkeep draw precombat-main beginning-of-combat declare-attackers
declare-blockers combat-damage end-of-combat postcombat-main end cleanupEvery step and main phase that occurs MUST be written, even if nothing happens in it. A skipped step is not written: for example the starting player's first draw step (CR 103.8a), and the declare blockers and combat damage steps when no creatures attack (CR 508.8). A second combat damage step for first strike (CR 510.4) is a second combat-damage line. Extra phases and steps added by effects (CR 500.8) are written where they occur, with the same keywords.
Turn-based actions that change the game are written in their step with a rule cause: untapping (rule:untap), the draw (rule:draw), lore counters (rule:lore), attackers becoming tapped (rule:declare-attackers), combat damage (rule:combat-damage), and cleanup (rule:cleanup).
9.3 Priority
| Statement | Meaning | Cause |
|---|---|---|
PLAYER priority [clock PLAYER TIME PLAYER TIME] | The player receives priority (CR 117.3). | none |
PLAYER pass | The player passes priority (CR 117.3d). | none |
When the stack is not empty, every time a player receives priority and every pass MUST be written. When the stack is empty, they MAY be written. The optional clock gives the time left on each player's clock, Player1 first (section 10.4). A player who activates a mana ability keeps priority (CR 405.6c), so no new priority line follows it.
See decisions/0007-stack-and-priority.md.
9.4 Mana
| Statement | Meaning | Cause |
|---|---|---|
PLAYER add MANA [restriction TEXT] | Mana is added to the player's mana pool (CR 106.3, 106.4), with any spending restriction (CR 106.6). | required |
PLAYER pay MANA | Mana is spent from the pool, with cause by cost:ID (CR 601.2h). | required |
PLAYER lose-mana MANA | Unspent mana is lost as the pool empties (CR 106.4). Written only when there was unspent mana. | required |
MANA is one or more mana symbols, one per mana, in the order {W}{U}{B}{R}{G}{C}: for example {C}{C}{C}{C}{C}{G} is written {G}{C}{C}{C}{C}{C}. Only the six types of mana are used (CR 106.1b). Generic numbers such as {5} are a cost notation (CR 107.4b), not a type of mana, and are never written in MANA; costs use their own notation (section 7.6). See decisions/0006-mana.md.
9.5 Life and counters
| Statement | Meaning | Cause |
|---|---|---|
PLAYER life INTEGER -> INTEGER | The life total changes (CR 119.3). | required |
PLAYER poison INTEGER -> INTEGER | Poison counters change. | required |
PLAYER counters TEXT INTEGER -> INTEGER | Other player counters, for example "energy". | required |
Every result of damage (CR 120.3) is written straight after the damage line, with the same cause, for example by rule:combat-damage or by #31:
- life lost (CR 120.3a): a
lifeline; - poison counters from infect or toxic (CR 120.3b, 120.3g): a
poisonline; - loyalty counters removed from a planeswalker (CR 120.3c) and defense counters removed from a battle (CR 120.3h): a
countersline on the permanent; - -1/-1 counters from wither or infect (CR 120.3d): a
counters "-1/-1"line, then theptline (section 7.5); - life gained from lifelink (CR 120.3f): a
lifeline for the source's controller.
Damage marked on a creature (CR 120.3e) needs no other line: the damage line records it, and it is removed in the cleanup step (CR 514.2), before the next keyframe.
Life totals below zero are written with a leading - (for example life 2 -> -1); this is the only place a sign appears.
9.6 Library actions
| Statement | Meaning | Cause |
|---|---|---|
PLAYER search ZONE [PLAYER] | The player searches a zone (CR 701.23a). The second player names whose library, hand, or graveyard it is, when it is not the searcher's own. | required |
PLAYER shuffle | The player's library is shuffled (CR 701.24a). Every tracked object in it loses its ID. | required |
9.7 End of the game
| Statement | Meaning | Cause |
|---|---|---|
PLAYER concede | The player concedes (CR 104.3a). | none |
PLAYER lose | The player loses the game (CR 104.3). | required |
PLAYER win | The player wins the game (CR 104.2). | required |
game-draw | The game is a draw (CR 104.4). | required |
9.8 Incompleteness
incomplete TEXT may appear wherever an event may appear. It means events between this line and the next keyframe may be missing, for the reason given. Checks that compare the replayed state with the file are suspended until the next keyframe, which then replaces the replayed state; if no keyframe follows, until the end of the game (section 14.4). See CONTRIBUTING.md, design principle 5.
A recorder that misses events MUST write incomplete, and MUST NOT invent events to fill the gap. A source that has no clock data is not incomplete.
9.9 Stack snapshots
A stack line under a priority line lists the whole stack, top first, one entry per line:
ID NAME [face NAME | fused] controller PLAYER [CHOICE]... (spell)
ID KIND of OBJREF TEXT controller PLAYER [CHOICE]... (ability)CHOICE repeats the object's recorded choices in order, each as it was written after choose or as target ...: for example cost "kicker", mode "...", x 3, target #17 "Urza's Tower", hidden. A hidden spell is written with its ID and no name. A split card half or an Adventure being cast shows its face; a fused split spell shows fused.
A stack line MUST follow every priority line written while the stack is not empty, and MUST NOT follow one while it is empty.
9.10 Lasting effects and designations
Some effects outlive the spell or ability that created them. A keyframe has to show them, or it is not the full game state. See decisions/0026-lasting-effects.md.
Effects. A new effect line records, as the spell or ability that creates it resolves:
- every delayed triggered ability (CR 603.7a), such as dash's "return it to its owner's hand at the beginning of the next end step", or Tamiyo, Seasoned Scholar's "until your next turn, whenever a creature attacks you...";
- every continuous effect from a resolving spell or ability whose duration can last past the current turn's cleanup step (CR 611.2a): "until your next turn", "for as long as", or no stated duration.
new effect ID of OBJREF TEXT controller PLAYER CAUSEof OBJREF is the effect's source (CR 603.7d, 603.7e), TEXT its text as the source reports it, and the cause the spell or ability that created it. Effects that end by the cleanup step ("until end of turn", "this turn") are not recorded as effects: they never reach a keyframe, and their results are recorded as events (damage dealt, attacks made, and power and toughness changes, section 7.5).
A delayed triggered ability can also be created by a static ability that lets a player take an action (CR 603.7a), such as revealing Chancellor of the Annex or Devourer of Destiny from an opening hand. Its new effect line comes straight after the action. Its source is the card with that static ability, and its controller is that card's controller when the action was taken (CR 603.7g), which for a card in a hand is its owner (CR 108.4a). Its cause is that card: new effect #22 of #16 "Chancellor of the Annex" "..." controller "PlayerA" by #16. See decisions/0030-delayed-triggers-from-actions.md.
A reflexive triggered ability ("when you do", CR 603.12) is created and triggers during the same resolution, so it never reaches a keyframe. It has no new effect line, and its new ability line has no from.
When a delayed triggered ability triggers, its new ability line ends with from ID, naming the effect. An effect ends with cease: by rule:delayed-trigger when a delayed trigger that triggers only once has triggered (CR 603.7b), or by rule:duration when its duration is over (CR 611.2a). An effect lasting "until your next turn" ends as that turn begins: its cease is the first line of that turn's untap step, and that turn's keyframe still lists it.
Designations.
- Goaded (CR 701.15):
OBJREF goad CAUSEandOBJREF end-goad PLAYER by rule:duration, as the goading player's next turn begins (first line of the untap step). - Day and night (CR 731): the game statements
day CAUSEandnight CAUSE. The game starts with neither (CR 731.1). In the untap step the cause isrule:day-night(CR 731.2); a daybound permanent entering when it is neither makes it day, caused by that permanent (CR 702.145d). - Emblems (CR 114):
new emblem ID TEXT owner PLAYER CAUSEputs an emblem into the command zone.
10. Keyframes and decklists
10.1 When
A keyframe line (level 1) is the first child of pregame and of every turn. It records the full game state at that point, before any of the turn's untap step actions (CR 502.1). See decisions/0008-keyframes.md.
A turn always begins with an empty stack (CR 500.2), so keyframes have no stack. Mana pools normally empty between steps (CR 106.4); mana that an effect keeps in a pool across turns is not yet covered (section 15).
10.2 Player entries
One per player, Player1 first:
player PLAYER life INTEGER poison INTEGER library INTEGER [counters TEXT INTEGER]... [clock TIME]If the game is day or night (CR 731.1), the player entries are followed by a day or night line.
library is the library's total size (CR 401.3), tracked and untracked. counters entries, here and in object entries, list each kind with a count above zero once, in Unicode code point order of TEXT. clock is the time left on the player's clock, when the source has one.
10.3 Object entries
One per tracked object in a zone, and one per lasting effect, in increasing ID order:
ID [NAME] ZONE [PLAYER] [face NAME] [pt PTVALUE] [tapped] [attached ID] [with ID] [adventure PLAYER] [companion] [goaded PLAYER]... [counters TEXT INTEGER]... [top INTEGER | bottom INTEGER] [emblem TEXT]
ID effect of OBJREF TEXT controller PLAYERPLAYERis written forlibrary,hand,graveyard, andoutside(the owner), forbattlefield(the controller), and for an emblem incommand(its owner), and not otherwise.face NAMEgives the face up of a double-faced permanent when it is not the front face (section 7.1).pt PTVALUEis written for every creature on the battlefield, and for nothing else.adventure PLAYERmarks a card in exile "on an adventure" (CR 715.3d), naming the player who may play it: whoever controlled the Adventure spell, who is not always its owner.companionmarks a card revealed as its owner's companion (CR 103.2b, section 9.1) that is still outside the game.goaded PLAYERis written once per player who goaded the creature (CR 701.15c),Player1first.- Each lasting effect (section 9.10) still in force has an
effectentry. top Nandbottom Ngive a library position counted from that end,1being the end card. They are omitted when the position is unknown.- Mana abilities, objects outside the game other than companions, and objects whose ID has ended are not listed.
10.4 Clocks
Clocks are optional and recorded only when the source has them. See decisions/0009-timestamps-and-clocks.md.
- Per-player clocks (MTGO, Arena): the
TimeControltag gives the limit. Each keyframe player entry and eachpriorityline MAY give the time left. - Round timer (paper events and some online events): the
RoundTimetag gives the limit, and each keyframe MAY end withround-clock TIME, the round time left.
10.5 Decklists
The body starts with the perspective player's decklist for this game (CR 100.4):
deck PLAYER [name TEXT]
main INTEGER NAME
side INTEGER NAMEmain entries come first, then side entries, each sorted by name in Unicode code point order, one entry per distinct name. When the decklist is unknown, the block is the single line deck PLAYER [name TEXT] unknown, which is a defined incompleteness. The opponent's decklist is hidden and is not recorded. Sideboarding is inferred by comparing the decklists of consecutive games. See decisions/0010-multi-game-matches.md.
11. Annotations
Annotations follow PGN sections 5 and 8.2.4. They never change game data: removing them leaves the same game. See decisions/0011-extensions-and-annotations.md.
- NAGs:
$followed by an integer from 0 to 255. NAGs 1 to 6 are PGN's move glyphs:$1good (!),$2poor (?),$3very good (!!),$4very poor (??),$5speculative (!?),$6questionable (?!). Because.mtgrhas only the export format, the traditional suffixes are always written as NAGs (PGN section 8.2.3.8). - Brace comments:
{to the next}on the same line. Brace comments do not nest and cannot contain}. - Line comments:
;to the end of the line.
Annotations go at the end of a body line, after the cause, in the order NAGs, brace comment, line comment. Comments are UTF-8 text and are not escaped.
12. Variations
A variation is an alternative to the line it follows (PGN section 8.2.5). See decisions/0014-variations.md.
- INDENT (
- INDENT ...alternative lines...
- INDENT )- The opening
(line has the same indent as the line it is an alternative to, and comes immediately after that line (and its stack entries). Lines inside are written as if they replaced that line and the lines after it, one level deeper. - Every line inside a variation, including the brackets, has TIME
-. - Variations may nest. A parser that does not support variations MAY skip from a
(line to its matching)line by counting bracket lines, without reading the lines between. - Objects that exist only in a variation get hypothetical IDs
#h1,#h2, and so on, scoped to that variation and the variations nested inside it. - Variations never change the game. Keyframes, stack snapshots, and checks apply only to the main line, and the format does not check that a variation is legal.
13. Extensions
13.1 Rules
- Extension tags are named
PREFIX_Name, for exampleMTGO_Version. - Extension statements are body lines whose statement starts with
PREFIX_name, followed by strings, integers, and keywords. - Parsers MUST ignore extension tags and statements they do not understand, and MUST reject unknown core tags, keywords, and statements.
- Removing every extension leaves a valid file describing the same game.
13.2 Prefix registry
| Tag prefix | Source ID prefix | Owner |
|---|---|---|
MTGO_ | mtgo: | Magic: The Gathering Online data |
ARENA_ | arena: | MTG Arena data |
MYMTGO_ | mymtgo: | MyMTGO |
MTGREPLAY_ | mtgreplay: | mtgreplay.app |
New prefixes are added through CONTRIBUTING.md.
14. Validation
This section defines how to decide whether a file is valid. A validator is a program that applies these checks; this document does not provide one. Every check below can be decided from the file alone, without a rules engine or a card database: the format records every change to the game state as a line, so a validator only has to apply those lines in order (section 14.3). See decisions/0037-validation.md.
A validator reports each failure with the line number and the check number below. Conformance fixtures are in conformance/.
14.1 Checks
A file is invalid if any of these fail. Checks marked † compare the replayed state with what the file says, and are suspended by incomplete (section 14.4).
- Lexical rules (section 2), file structure (section 3), and tag rules (section 4) hold, and every line matches the grammar (section 16) at the nesting level its parent allows (section 5.2).
- Each game's result line equals its
Resulttag. - Every ID is introduced by exactly one
newline before it is used, IDs increase by one in order of introduction, and no line refers to an ID that has ended. - Every name next to an ID matches the object's recorded name; hidden objects and abilities have none (section 6.3).
- Causes appear exactly where required (section 8), and every
by IDandby cost:IDrefers to a known object. - A
stacksnapshot equals the replayed stack (section 14.6). † - A keyframe equals the replayed state (section 14.5). †
- An object that resolves or fizzles is on top of the stack, and a countered object is on the stack. †
- A
move,play, orcastline's source zone is the object's current zone. † - Every
OLDvalue equals the replayed value: inlife,poison, and playercounterslines, in objectcountersandptlines, and incostlines, where each line'sOLDafter the first equals the previous line'sNEWfor the same object. † - A
payorlose-manaline spends only mana in the player's pool, and every mana pool is empty when a step, phase, or keyframe line is reached (unspent mana is lost with alose-manaline first, CR 106.4). † tapapplies only to an untapped permanent, anduntaponly to a tapped one. †- A move out of a library
as draworas milltakes the top card: if a tracked object is known to be the top card of that library, it is the object moved. † - A
stackline follows apriorityline if and only if the replayed stack is not empty (section 9.9). † identifyapplies only to a hidden object, at most once (section 6.6).- After the line that ends the game (
concede,lose,win, orgame-draw), only extension statements follow in that game. TheResulttag agrees with it: the other player wins after aconcedeorlose, that player wins after awin, andgame-drawis1/2-1/2. A game with no such line ends with anincompleteline; itsResultmay still be known from the source. - Variation brackets balance, and hypothetical IDs (
#h1) appear only inside variations (section 12).
14.2 Replay state
Replaying a game starts from the pregame keyframe and applies each main-line body line in order. The state is:
- For the game: the turn number and active player, day or night (or neither), and the stack, an ordered list of IDs, top first.
- For each player: life, poison counters, other player counters, the size of their library, and their mana pool, a multiset of the six types of mana.
- For each object: its kind (card, hidden card, token, copy, ability, effect, or emblem), name or none, owner, controller, zone (with the label for
outside), and whether its ID has ended. Then, as they apply: library position (top N,bottom N, or unknown), tapped, face, power and toughness, counters, the object it is attached to, the object it is exiledwith, the player who may play it from an adventure, whether it is a revealed companion, the players who goaded it, and the choices recorded for it since it was last put on the stack (or since it was created, for an ability or a copy).
A library holds tracked objects and an untracked pool (section 6.2). Its size counts both. A tracked object's position is counted from the top or the bottom, or is unknown:
- When an object with a known position leaves a library, positions counted from the same end that were beyond it move one closer. When an object with an unknown position leaves, every other position in that library becomes unknown, except that a move
as draworas milltakes the top card (check 13). - When an object is put on the top or bottom, positions counted from that end move one further away. When it is put in at an unknown position, every other position in that library becomes unknown.
- Cards put on the bottom together in a random order (section 7.1) all get unknown positions.
Clock values are not part of the state and are not compared.
14.3 Statement effects
Only these lines change the state. Every other line (choose first, roll, mulligan, keep, pass, reveal except as below, look, damage, attack, block, special, search, resolve, fizzle, countered, priority, step lines, deck blocks, annotations, and extensions) leaves it unchanged. Lines are applied exactly as written: resolve moves nothing, damage changes no life total, and so on, because the lines that follow record those changes.
| Line | Effect |
|---|---|
new card, new hidden, new token, new copy, new emblem | Creates the object in the zone given, owned and controlled by the owner given, with its name (none for a hidden card) and any position or ENTERING values. A copy of a spell put on the stack gets the original's recorded choices. In a library it is taken from the untracked pool, so the library's size does not change; the pool must not be empty. |
new ability | Creates an ability with its controller. With in stack, it is put on top of the stack. A mana ability is in no zone. A copy of an ability (new copy ID of ID) is put on top of the stack with the original's text and recorded choices. |
new effect | Creates a lasting effect with its source, text, and controller. |
play, cast, move | Moves the object from its zone to the new zone (the stack for cast, the battlefield for play), on top of the stack or at the library position given. Leaving a zone clears its tapped status, face, power and toughness, counters, attachments, goads, adventure and companion marks, and any with link to or from it, except that a card exiled with a permanent spell stays linked when that spell moves to the battlefield (CR 607.2q). The new zone sets the ENTERING values, face (or fused on the stack), and with. A library's size goes down by one when an object leaves it and up by one when an object enters it. |
choose, target | Appends the choice to the object's recorded choices. The first target line straight after a copy's new line first removes the targets the copy was given (section 7.2). |
tap, untap | Sets or clears tapped. |
attach OBJREF, unattach | Sets or clears the object it is attached to. |
control PLAYER | Sets the controller. |
counters TEXT OLD -> NEW (object or player) | Sets that kind of counter to NEW. A count of 0 is the same as none. |
pt OLD -> NEW | Sets power and toughness. |
life, poison | Sets the player's life or poison counters. |
add, pay, lose-mana | Adds mana to, or removes it from, the player's pool. |
identify NAME | Sets the hidden object's name. |
transform | Sets the face to the other part of the object's name: names are FRONT // BACK. A face equal to the front is the same as no face. |
become-copy OBJREF | Sets the name to the copied object's name until the object leaves the battlefield, when it returns to the card's own name (section 7.3). |
goad, end-goad PLAYER | Adds the cause's controller to, or removes the player from, the players who goaded it. |
shuffle | Ends the ID of every tracked object in that player's library. The size does not change. |
untracked, cease | Ends the ID. An object on the stack is removed from it; in a library, the card joins the untracked pool. |
day, night | Sets day or night. |
turn N PLAYER | Sets the turn number and active player. |
Two marks are set by a sequence of lines, not by one line:
- Adventure. A card cast with
facenaming the second part of its name ("Bonecrusher Giant // Stomp"castface "Stomp") that then moves from the stack to exileby rule:resolveis on an adventure; the player who may play it is the spell's controller (CR 715.3d). - Companion. A card in
outside "sideboard"that is revealed in the pregame, caused by itself, is a revealed companion (section 9.1).
14.4 Incompleteness
After an incomplete line, the checks marked † are suspended until the next keyframe; if no keyframe follows, until the end of the game. The other checks still apply, and lines are still applied to the state where they can be.
At the next keyframe, the replayed state is replaced by the keyframe: every object it lists takes the values it gives, and every live object it does not list ends, except abilities and objects outside the game. Every ID it lists must already have been introduced. The † checks resume from there.
14.5 Comparing keyframes
A keyframe equals the replayed state when all of these hold at the keyframe line:
- The stack is empty and every mana pool is empty.
- Each player entry's life, poison, library size, and counters equal the replayed values.
clockis not compared. dayornightappears exactly when the replayed game is day or night.- The object entries are exactly the live objects in these places, each once, in increasing ID order: every zone except the stack (tracked library objects included);
outsideonly for revealed companions; and every live effect. Abilities and the untracked pool are never listed. - Each entry's fields equal the object's replayed values: name, zone, the
PLAYERfield (section 10.3), face, power and toughness (for every creature on the battlefield, and only those), tapped, attached,with, adventure, companion, goads, counters, position (written exactly when it is known), and an emblem's or effect's text, source, and controller.
The keyframe at the start of the pregame sets the starting state: the players' life, poison, and library sizes, and no objects.
14.6 Comparing stack snapshots
A stack snapshot equals the replayed stack when it lists the same objects in the same order, top first, and each entry's name, face or fused, controller, and choices equal the object's replayed values. The choices are the object's recorded choices, in the order they were written (section 9.9).
14.7 What validation does not check
Some requirements on writers cannot be checked from the file alone, because they depend on what happened in the game or on the rules of Magic. A valid file can still break them:
- that every event was recorded (writers MUST write
incompletewhen they miss events, section 9.8); - that causes are the right ones, and that choices and costs are the ones made;
- that the game was played legally: that spells could be cast, targets were legal, steps that occurred were all written (section 9.2), and so on;
- that card names are Oracle names and ability texts are as the source reported them.
A validator MAY check these using a rules engine or a card database. Such checks are outside this specification, and a file that fails them is still valid .mtgr.
15. Not yet covered
These situations have no defined encoding yet. A writer that meets one MUST write incomplete with a reason and resynchronise at the next keyframe. Each needs a real recorded game and a decision record before it is added (CONTRIBUTING.md, no speculative features).
- Face-down permanents and spells (morph, manifest, disguise, foretell) beyond
new hidden. - Converting, melding, and other face changes besides transforming.
- Multiplayer games (more than two players).
- Dungeons, the initiative, the monarch, and designations other than goaded, day, and night.
- Continuous effects from static abilities, other than their effect on power and toughness (section 7.5) and on mana costs (section 7.6). Their results are recorded as events.
- Effects that change the non-mana parts of a cost.
- Mana that stays in a pool across steps or turns.
- Special actions other than playing a land,
companion,suspend, andplot. - Rooms: the unlocked designations and unlocking a door (CR 709.5, 116.2m).
- Casting a card with alternative characteristics or another face up: Omens (CR 720.3), disturb and other "cast transformed" permissions (CR 712.11a), and prototype (CR 718.3).
- Mutating and merged permanents (CR 702.140, 730).
- Speed (CR 702.179), and triggered abilities that have no source, such as the speed and rad counter triggers (CR 702.179d, 728.1).
- Delayed triggered abilities created by a replacement effect (CR 603.7f), such as rebound.
- Phasing.
- Spectator and omniscient perspectives.
16. Grammar
ABNF (RFC 5234). Core rules ALPHA, DIGIT, DQUOTE, SP, and LF are as in RFC 5234. UCHAR is any Unicode scalar value except control characters.
file = game *(LF game)
game = 1*tag-line LF body result-line
tag-line = "[" tag-name SP string "]" LF
tag-name = %x41-5A *(ALPHA / DIGIT / "_")
result-line = result LF
result = "1-0" / "0-1" / "1/2-1/2" / "*"
body = 1*(body-line / escape-line)
escape-line = "%" *UCHAR LF
body-line = time SP indent statement [SP cause *(SP replacement)] *(SP nag)
[SP brace-comment] [SP line-comment] LF
/ "-" SP indent ("(" / ")") LF
time = (minutes ":" seconds ["." 1*3DIGIT]) / "-"
minutes = "0" / (%x31-39 *DIGIT)
seconds = %x30-35 DIGIT
indent = *(" ")
statement = structural / new-stmt / object-stmt / player-stmt
/ keyframe-entry / stack-entry / deck-entry / ext-stmt
structural = "pregame" / "keyframe" / "stack"
/ "turn" SP int SP player
/ step
/ "deck" SP player [SP "name" SP string] [SP "unknown"]
/ "incomplete" SP string
/ "game-draw"
/ "day" / "night"
step = "untap" / "upkeep" / "draw" / "precombat-main"
/ "beginning-of-combat" / "declare-attackers"
/ "declare-blockers" / "combat-damage" / "end-of-combat"
/ "postcombat-main" / "end" / "cleanup"
new-stmt = "new" SP ( "card" SP id SP name SP owner SP in-zone [SP position]
[SP "print" SP string SP string] *(SP src)
/ "hidden" SP id SP owner SP in-zone [SP position]
/ "token" SP id SP name SP owner SP in-zone entering
/ "copy" SP id SP "of" SP objref SP name SP owner SP in-zone
/ "copy" SP id SP "of" SP id SP "controller" SP player
SP "in" SP "stack"
/ "ability" SP id SP kind SP "of" SP objref SP text
SP "controller" SP player [SP "in" SP "stack"]
[SP "from" SP id]
/ "effect" SP id SP "of" SP objref SP text
SP "controller" SP player
/ "emblem" SP id SP text SP owner )
position = ("top" / "bottom") SP int
entering = [SP "face" SP name] [SP "tapped"]
[SP "attacking" SP (player / objref)] [SP "pt" SP pt]
pt = sint "/" sint
ptvalue = pt / "none" / "?"
owner = "owner" SP player
in-zone = "in" SP zone
kind = "activated" / "triggered" / "loyalty" / "mana"
src = "src" SP src-id
src-id = 1*(%x61-7A) ":" 1*(ALPHA / DIGIT / "-" / "_" / ".")
object-stmt = objref SP object-verb
object-verb = "play" SP "from" SP zone [SP "face" SP name] [SP "tapped"]
[SP "pt" SP pt]
/ "cast" SP "from" SP zone [SP ("face" SP name / "fused")]
/ "move" SP zone SP "->" SP zone [SP "as" SP action]
[SP ("top" / "bottom")] entering [SP "with" SP id]
/ "choose" SP choice
/ "target" SP (objref / player) [SP "amount" SP int]
/ "tap" / "untap" / "unattach" / "reveal" / "untracked" / "cease"
/ "transform" / "goad" / "end-goad" SP player
/ "look" SP player
/ "become-copy" SP objref
/ "special" SP ("companion" / "suspend" / "plot")
/ "attach" SP objref
/ "control" SP player
/ "counters" SP string SP int SP "->" SP int
/ "pt" SP ptvalue SP "->" SP ptvalue
/ "cost" SP cost SP "->" SP cost
/ "damage" SP (objref / player) SP int [SP "prevented"]
/ "attack" SP (player / objref)
/ "block" SP objref
/ "identify" SP name [SP "print" SP string SP string] *(SP src)
/ "resolve" / "fizzle" / "countered"
action = "draw" / "discard" / "sacrifice" / "destroy" / "mill"
choice = "mode" SP string / "cost" SP string / "x" SP int
/ "symbol" SP split-symbol SP ("life" / "{" (color-sym / "C" / "2") "}")
/ "color" SP color / "option" SP string / "object" SP objref
/ "player" SP player / "number" SP int / "name" SP name
/ "type" SP string / "hidden"
color = "white" / "blue" / "black" / "red" / "green"
player-stmt = player SP player-verb
player-verb = "roll" [SP "d" int] SP int
/ "choose" SP "first" SP player
/ "choose" SP choice
/ "mulligan" / "keep" / "pass" / "concede" / "lose" / "win"
/ "shuffle" / "search" SP zone [SP player]
/ "priority" [SP "clock" SP player SP time SP player SP time]
/ "add" SP mana [SP "restriction" SP string]
/ "pay" SP mana / "lose-mana" SP mana
/ "life" SP sint SP "->" SP sint
/ "poison" SP int SP "->" SP int
/ "counters" SP string SP int SP "->" SP int
keyframe-entry = "player" SP player SP "life" SP sint SP "poison" SP int
SP "library" SP int *(SP "counters" SP string SP int)
[SP "clock" SP time]
/ "round-clock" SP time
/ "day" / "night"
/ objref SP zone [SP player] [SP "face" SP name]
[SP "pt" SP ptvalue] [SP "tapped"]
[SP "attached" SP id] [SP "with" SP id] [SP "adventure" SP player]
[SP "companion"]
*(SP "goaded" SP player) *(SP "counters" SP string SP int)
[SP position] [SP "emblem" SP text]
/ id SP "effect" SP "of" SP objref SP text SP "controller" SP player
stack-entry = id [SP name] [SP ("face" SP name / "fused")] SP "controller" SP player
*(SP snap-choice)
/ id SP kind SP "of" SP objref SP text SP "controller" SP player
*(SP snap-choice)
snap-choice = choice / "target" SP (objref / player) [SP "amount" SP int]
deck-entry = ("main" / "side") SP int SP name
ext-stmt = ext-prefix "_" 1*(ALPHA / DIGIT / "_") *(SP (string / int / 1*(%x61-7A / "-")))
ext-prefix = 1*(%x41-5A)
cause = "by" SP ( id / "cost:" id / player / "rule:" rule-name
/ "source:" ("clock" / "disconnect") / "?" )
replacement = "replacement" SP id
rule-name = "opening-hand" / "mulligan" / "untap" / "draw" / "combat-damage"
/ "cleanup" / "sba" / "empty-pool" / "resolve" / "fizzle"
/ "no-choice" / "intervening-if" / "declare-attackers" / "lore"
/ "replacement-order" / "duration" / "delayed-trigger" / "day-night"
objref = id [SP name]
id = "#" ["h"] %x31-39 *DIGIT
player = string
name = string
text = string / "?"
zone = "library" / "hand" / "graveyard" / "battlefield" / "stack"
/ "exile" / "command" / "ante" / "outside" SP string
mana = 1*("{" ("W" / "U" / "B" / "R" / "G" / "C") "}")
cost = "{0}" / "{" nzint "}" *("{" cost-sym "}") / 1*("{" cost-sym "}")
nzint = %x31-39 *DIGIT
cost-sym = color-sym / "C" / "S"
split-symbol = "{" ( color-sym "/" color-sym ; hybrid, CR 107.4
/ ("2" / "C") "/" color-sym ; monocolored hybrid
/ color-sym "/" "P" ; Phyrexian
/ color-sym "/" color-sym "/" "P" ; hybrid Phyrexian
) "}"
color-sym = "W" / "U" / "B" / "R" / "G"
int = "0" / (%x31-39 *DIGIT)
sint = ["-"] int
string = DQUOTE *(schar / "\" (DQUOTE / "\" / "n")) DQUOTE
schar = <any UCHAR except DQUOTE and "\">
nag = "$" int ; 0 to 255
brace-comment = "{" *<any UCHAR except "}"> "}"
line-comment = ";" *UCHARThe grammar defines each line on its own. Which statements may appear where (section 5.2), which causes each statement needs (sections 7 to 9), and the checks in section 14 are part of the format as well.