Skip to content

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.

  1. A file is UTF-8 without a byte-order mark, in Unicode Normalization Form C. A file that is not NFC is invalid.
  2. Lines end with LF (U+000A) only. The file ends with LF.
  3. There is no line length limit. Lines are never wrapped.
  4. Tabs and other control characters are not allowed anywhere except LF at the end of a line.
  5. 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.
  6. Strings are enclosed in double quotes. Inside a string, \" is a double quote, \\ is a backslash, and \n is a line break. No other escape exists, and a backslash followed by any other character is invalid. Strings have no length limit.
  7. Card names, ability text, player names, and all other free text are always strings, never bare words.
  8. Integers are written in decimal without leading zeros (0, 7, 20) and without a sign.
  9. 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:

  1. a tag section: one tag per line (section 4);
  2. one empty line;
  3. the game body: one or more body lines (sections 5 to 12);
  4. the result line: the game's result marker (1-0, 0-1, 1/2-1/2, or *) alone on a line, equal to its Result tag (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:

TagValue
MtgrFormat version of this game, for example "0.3.0".
EventEvent name, for example "Modern League". "?" if unknown.
SiteWhere the game was played: a client such as "MTGO" or "Arena", or a venue for paper Magic. "?" if unknown.
DateStart date, YYYY.MM.DD, with ? for each unknown digit. For online sites, the UTC date.
RoundTournament round, for example "3" or "3.1". "-" where rounds do not apply; "?" if unknown.
Player1First player in the match's seat order. Fixed for the whole match.
Player2Second 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).
FormatGame format, for example "Modern". "?" if unknown.
MatchIdentifier shared by every game of the same match. Any string.
GameGame number within the match, starting at "1".
PerspectiveThe 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.

TagValue
AnnotatorWho added annotations (PGN section 9.9.1).
Player1ArchetypeArchetype of Player1's deck, as commonly named in the format, for example "Izzet Murktide" (section 4.6).
Player2ArchetypeArchetype of Player2's deck (section 4.6).
RecorderName and version of the writer that produced the game, for example "MtgoReplay 0.1.0 (MTGOSDK 1.8.1.20261028)".
RoundTimeRound time limit in seconds, for a match played under a round timer (section 10.4).
TerminationWhy the game ended (section 4.4).
TimeControlPer-player clock as in PGN section 9.6.1, for example "1500" for 25 minutes each with no increment.
UTCDateStart date in UTC, YYYY.MM.DD.
UTCTimeStart time in UTC, HH:MM:SS.

4.4 Termination values ​

ValueMeaningBasis
"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:SS or M:SS.f with one to three fraction digits (for example 0: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.

LevelLines
0deck, pregame, turn
1deck entries; keyframe; step lines; events inside pregame
2keyframe entries; events inside a step
+1stack under a priority line
+2stack 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:

  1. one deck block (section 10.5);
  2. one pregame block (section 9.1);
  3. one turn block 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 untracked line 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 new or identify. 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.

StatementIntroduces
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] CAUSEA 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 CAUSEA 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 CAUSEA 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 CAUSEA lasting effect (section 9.10).
new emblem ID TEXT owner PLAYER CAUSEAn emblem in the command zone (CR 114.1, 114.2).
  • ZONE is a zone keyword (section 6.7). in library takes a card from the untracked pool (section 6.2). POSITION (top N or bottom N, counted from that end, 1 being the end card) says which card, when known: Impulse's four cards are top 1 to top 4.
  • new card is 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 hidden is used only for cards whose name stays hidden.
  • ENTERING is the same as for moves to the battlefield (section 7.1): [face NAME] [tapped] [attacking PLAYER|OBJREF] [pt PT].
  • KIND is activated, triggered, loyalty, or mana (CR 113.3b, 113.3c, 605.1a, 606.1).
  • of OBJREF names the ability's source.
  • TEXT is 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: the new line is the ability being put on the stack (CR 602.2a, 603.3). A mana ability has no in clause: 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 control line 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 ​

KeywordZoneOwned by
librarylibraryeach player (CR 400.1)
handhandeach player
graveyardgraveyardeach player
battlefieldbattlefieldshared
stackstackshared
exileexileshared
commandcommand zoneshared
anteanteshared
outside STRINGoutside 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 ​

StatementMeaningCause
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
  • cast has 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 ACTION names the keyword action that moved it, when there was one: draw (CR 121.1), discard, sacrifice, destroy, mill.
  • top or bottom gives 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 a move ... -> library bottom line, but the order of the lines is not their order: their positions among those bottom cards are unknown, and keyframes give them no position.
  • tapped records 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 separate tap line: the permanent never "becomes tapped".
  • attacking PLAYER|OBJREF records 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 an attack line: such creatures never "attacked".
  • face NAME says 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 a cast line face is 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 without face: face on play, move, new, and keyframe entries names a face other than the front.
  • pt PT gives 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 a counters line straight after its move, caused by the object that gave them; its entering pt already includes them, so no pt line follows.
  • with ID records 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 stay with it 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:

mtgr
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 hand

7.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.

StatementMeaningCause
choose mode TEXTA mode of a modal spell or ability, quoted as the source reports it (CR 700.2).chooser
choose cost TEXTAn 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 INTEGERThe value of X (CR 107.3).chooser
choose symbol SYMBOL PAYMENTHow 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 COLORA color: white, blue, black, red, or green (CR 105.1).chooser
choose option TEXTA choice offered in words, such as a "may" instruction, quoted as the source reports it.chooser
choose object OBJREFAn object chosen without targeting.chooser
choose player PLAYERA player chosen without targeting.chooser
choose number INTEGERA number.chooser
choose name NAMEA card name.chooser
choose type TEXTA card type, subtype, or other characteristic.chooser
choose hiddenA 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 ​

StatementMeaningCause
tapThe permanent becomes tapped.required
untapThe permanent becomes untapped.required
attach OBJREFThe object becomes attached to another.required
unattachThe object becomes unattached.required
control PLAYERThe object's controller changes.required
counters TEXT INTEGER -> INTEGERThe number of counters of a kind changes, for example counters "+1/+1" 0 -> 2.required
pt PTVALUE -> PTVALUEThe 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|OBJREFThe 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 OBJREFThe creature is declared as a blocker of that attacker (CR 509.1).none
revealThe object is revealed (CR 701.20a). A hidden object is identified first.required
look PLAYERThe 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
untrackedThe object can no longer be told apart from other cards in its zone. Its ID ends.none
transformThe double-faced permanent turns over to its other face (CR 701.27a).required
become-copy OBJREFThe 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 ACTIONThe 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
goadThe creature becomes goaded by the controller of the cause (CR 701.15a, 701.15b).required
end-goad PLAYERThe creature stops being goaded by that player, as that player's next turn begins (CR 701.15a).required
ceaseThe 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 ​

StatementMeaningCause
resolveThe top object of the stack begins to resolve (CR 405.5, 608.2). Lines caused by its effects follow.none
fizzleThe 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
counteredThe 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.

  • PT is power, a slash, and toughness, each an integer that may be negative: 2/1, 0/0, -1/1 (CR 208.1). PTVALUE is a PT, none for 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 PT on 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 CAUSE straight 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 written pt 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 damage lines 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 CAUSE
mtgr
0: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 pay lines (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.
  • OLD is 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's NEW. NEW is 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 cost line; its pay lines are the whole record.
  • COST is 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), so OLD already has the announced symbols, and Phyrexian symbols announced as 2 life are left out of it (their life is paid with the cost, as a life line by cost:ID). See decisions/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 cost line (CR 702.66b, 702.51b, 702.126b). Each card or permanent used is a line caused by cost:ID, written after the mana abilities and before the pay line: #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 last NEW (or the cost, when there is no cost line). See decisions/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.

CauseMeaning
by IDThe effect of that spell, ability, or permanent (including static and replacement effects, CR 609.1, 614.1).
by cost:IDDone 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 PLAYERThe 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:NAMEA game rule (table below).
by source:NAMEAn 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:

mtgr
0:53     #10 "Ragavan, Nimble Pilferer" move hand -> exile as discard by #18 replacement #15

The 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:

NameRule
opening-handEach player draws their starting hand (CR 103.5).
mulliganA mulligan's shuffle, draw, and cards put on the bottom (CR 103.5).
untapThe untap step's untap (CR 502.3).
drawThe draw step's draw (CR 504.1).
combat-damageCombat damage (CR 510.2).
cleanupCleanup step actions (CR 514.1, 514.2).
sbaA state-based action (CR 704.3).
empty-poolUnspent mana lost as a mana pool empties (CR 106.4).
resolveA 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).
fizzleA spell or ability leaving the stack because its targets are illegal (CR 608.2b).
no-choiceA triggered ability removed from the stack because no legal choice can be made or no mode is chosen (CR 603.3d, 700.2b).
intervening-ifA triggered ability removed as it resolves because its intervening "if" clause is false (CR 608.2a).
declare-attackersAttacking creatures becoming tapped (CR 508.1f).
loreLore counters put on Sagas as the precombat main phase begins (CR 703.4f).
replacement-orderThe affected player choosing which replacement effect to apply (CR 616.1).
durationAn effect ending because its stated duration is over (CR 611.2a).
delayed-triggerA delayed triggered ability ending because it has triggered and triggers only once (CR 603.7b).
day-nightThe 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):

StatementMeaningCause
PLAYER roll [dINTEGER] INTEGERThe 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 PLAYERThe player chooses who takes the first turn (CR 103.1).none
PLAYER mulliganThe player declares a mulligan (CR 103.5).none
PLAYER keepThe 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:

mtgr
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 #1

The 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, ..."), a new effect line follows (section 9.10);
  • anything else the card does is written the same way. Counters a permanent is given as it enters are a counters line 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  cleanup

Every 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 ​

StatementMeaningCause
PLAYER priority [clock PLAYER TIME PLAYER TIME]The player receives priority (CR 117.3).none
PLAYER passThe 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 ​

StatementMeaningCause
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 MANAMana is spent from the pool, with cause by cost:ID (CR 601.2h).required
PLAYER lose-mana MANAUnspent 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 ​

StatementMeaningCause
PLAYER life INTEGER -> INTEGERThe life total changes (CR 119.3).required
PLAYER poison INTEGER -> INTEGERPoison counters change.required
PLAYER counters TEXT INTEGER -> INTEGEROther 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 life line;
  • poison counters from infect or toxic (CR 120.3b, 120.3g): a poison line;
  • loyalty counters removed from a planeswalker (CR 120.3c) and defense counters removed from a battle (CR 120.3h): a counters line on the permanent;
  • -1/-1 counters from wither or infect (CR 120.3d): a counters "-1/-1" line, then the pt line (section 7.5);
  • life gained from lifelink (CR 120.3f): a life line 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 ​

StatementMeaningCause
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 shuffleThe player's library is shuffled (CR 701.24a). Every tracked object in it loses its ID.required

9.7 End of the game ​

StatementMeaningCause
PLAYER concedeThe player concedes (CR 104.3a).none
PLAYER loseThe player loses the game (CR 104.3).required
PLAYER winThe player wins the game (CR 104.2).required
game-drawThe 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 CAUSE

of 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 CAUSE and OBJREF 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 CAUSE and night CAUSE. The game starts with neither (CR 731.1). In the untap step the cause is rule: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 CAUSE puts 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 PLAYER
  • PLAYER is written for library, hand, graveyard, and outside (the owner), for battlefield (the controller), and for an emblem in command (its owner), and not otherwise.
  • face NAME gives the face up of a double-faced permanent when it is not the front face (section 7.1).
  • pt PTVALUE is written for every creature on the battlefield, and for nothing else.
  • adventure PLAYER marks 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.
  • companion marks a card revealed as its owner's companion (CR 103.2b, section 9.1) that is still outside the game.
  • goaded PLAYER is written once per player who goaded the creature (CR 701.15c), Player1 first.
  • Each lasting effect (section 9.10) still in force has an effect entry.
  • top N and bottom N give a library position counted from that end, 1 being 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 TimeControl tag gives the limit. Each keyframe player entry and each priority line MAY give the time left.
  • Round timer (paper events and some online events): the RoundTime tag gives the limit, and each keyframe MAY end with round-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 NAME

main 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: $1 good (!), $2 poor (?), $3 very good (!!), $4 very poor (??), $5 speculative (!?), $6 questionable (?!). Because .mtgr has 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 example MTGO_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 prefixSource ID prefixOwner
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).

  1. 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).
  2. Each game's result line equals its Result tag.
  3. Every ID is introduced by exactly one new line before it is used, IDs increase by one in order of introduction, and no line refers to an ID that has ended.
  4. Every name next to an ID matches the object's recorded name; hidden objects and abilities have none (section 6.3).
  5. Causes appear exactly where required (section 8), and every by ID and by cost:ID refers to a known object.
  6. A stack snapshot equals the replayed stack (section 14.6). †
  7. A keyframe equals the replayed state (section 14.5). †
  8. An object that resolves or fizzles is on top of the stack, and a countered object is on the stack. †
  9. A move, play, or cast line's source zone is the object's current zone. †
  10. Every OLD value equals the replayed value: in life, poison, and player counters lines, in object counters and pt lines, and in cost lines, where each line's OLD after the first equals the previous line's NEW for the same object. †
  11. A pay or lose-mana line 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 a lose-mana line first, CR 106.4). †
  12. tap applies only to an untapped permanent, and untap only to a tapped one. †
  13. A move out of a library as draw or as mill takes the top card: if a tracked object is known to be the top card of that library, it is the object moved. †
  14. A stack line follows a priority line if and only if the replayed stack is not empty (section 9.9). †
  15. identify applies only to a hidden object, at most once (section 6.6).
  16. After the line that ends the game (concede, lose, win, or game-draw), only extension statements follow in that game. The Result tag agrees with it: the other player wins after a concede or lose, that player wins after a win, and game-draw is 1/2-1/2. A game with no such line ends with an incomplete line; its Result may still be known from the source.
  17. 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 exiled with, 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 draw or as mill takes 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.

LineEffect
new card, new hidden, new token, new copy, new emblemCreates 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 abilityCreates 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 effectCreates a lasting effect with its source, text, and controller.
play, cast, moveMoves 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, targetAppends 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, untapSets or clears tapped.
attach OBJREF, unattachSets or clears the object it is attached to.
control PLAYERSets 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 -> NEWSets power and toughness.
life, poisonSets the player's life or poison counters.
add, pay, lose-manaAdds mana to, or removes it from, the player's pool.
identify NAMESets the hidden object's name.
transformSets 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 OBJREFSets 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 PLAYERAdds the cause's controller to, or removes the player from, the players who goaded it.
shuffleEnds the ID of every tracked object in that player's library. The size does not change.
untracked, ceaseEnds the ID. An object on the stack is removed from it; in a library, the card joins the untracked pool.
day, nightSets day or night.
turn N PLAYERSets the turn number and active player.

Two marks are set by a sequence of lines, not by one line:

  • Adventure. A card cast with face naming the second part of its name ("Bonecrusher Giant // Stomp" cast face "Stomp") that then moves from the stack to exile by rule:resolve is 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. clock is not compared.
  • day or night appears 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); outside only 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 PLAYER field (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 incomplete when 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, and plot.
  • 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.

text
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    = ";" *UCHAR

The 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.