diff --git a/forge-gui-desktop/src/main/java/forge/deckchooser/FDeckChooser.java b/forge-gui-desktop/src/main/java/forge/deckchooser/FDeckChooser.java index 11897b53557..e625ea3ba12 100644 --- a/forge-gui-desktop/src/main/java/forge/deckchooser/FDeckChooser.java +++ b/forge-gui-desktop/src/main/java/forge/deckchooser/FDeckChooser.java @@ -92,7 +92,7 @@ public FDeckChooser(final CDetailPicture cDetailPicture, final boolean forAi, Ga isForCommander = forCommander; final UiCommand cmdViewDeck = () -> { if (selectedDeckType != DeckType.COLOR_DECK && selectedDeckType != DeckType.THEME_DECK) { - FDeckViewer.show(getDeck()); + FDeckViewer.show(getDeck(), gameType.getDeckFormat() == DeckFormat.Commander); } }; lstDecks.setItemActivateCommand(cmdViewDeck); @@ -234,7 +234,10 @@ private void updateNetDecks() { if (netDeckCategory != null) { decksComboBox.setText(netDeckCategory.getDeckType()); } - updateDecks(DeckProxy.getNetDecks(netDeckCategory), ItemManagerConfig.NET_DECKS); + final ItemManagerConfig config = selectedDeckType == DeckType.NET_COMMANDER_DECK + ? ItemManagerConfig.NET_COMMANDER_DECKS + : ItemManagerConfig.NET_DECKS; + updateDecks(DeckProxy.getNetDecks(netDeckCategory), config); } private void updateNetArchiveStandardDecks() { diff --git a/forge-gui-desktop/src/main/java/forge/deckchooser/FDeckViewer.java b/forge-gui-desktop/src/main/java/forge/deckchooser/FDeckViewer.java index e5d52f7bc55..ca6808e6c56 100644 --- a/forge-gui-desktop/src/main/java/forge/deckchooser/FDeckViewer.java +++ b/forge-gui-desktop/src/main/java/forge/deckchooser/FDeckViewer.java @@ -13,6 +13,7 @@ import forge.itemmanager.ItemManagerConfig; import forge.itemmanager.ItemManagerContainer; import forge.itemmanager.ItemManagerModel; +import forge.itemmanager.views.CommanderBracketDeckView; import forge.itemmanager.views.ImageView; import forge.localinstance.properties.ForgePreferences; import forge.model.FModel; @@ -52,17 +53,27 @@ public class FDeckViewer extends FDialog { private boolean isDisplayAlt = false; public static void show(final Deck deck) { + show(deck, false); + } + + public static void show(final Deck deck, final boolean showCommanderBracket) { if (deck == null) { return; } - final FDeckViewer deckViewer = new FDeckViewer(deck); + final FDeckViewer deckViewer = new FDeckViewer(deck, showCommanderBracket); deckViewer.setVisible(true); deckViewer.dispose(); } - private FDeckViewer(final Deck deck0) { + private FDeckViewer(final Deck deck0, final boolean showCommanderBracket) { this.deck = deck0; this.setTitle(deck.getName()); this.cardManager = new CardManager(null, false, false, false) { + { + if (showCommanderBracket) { + addView(new CommanderBracketDeckView(this, getModel(), FDeckViewer.this.deck)); + } + } + @Override //show hovered card in Image View in dialog instead of main Detail/Picture panes protected ImageView createImageView(final ItemManagerModel model0) { return new ImageView(this, model0, false) { diff --git a/forge-gui-desktop/src/main/java/forge/itemmanager/DeckManager.java b/forge-gui-desktop/src/main/java/forge/itemmanager/DeckManager.java index 94e7597325b..1a16c4e1377 100644 --- a/forge-gui-desktop/src/main/java/forge/itemmanager/DeckManager.java +++ b/forge-gui-desktop/src/main/java/forge/itemmanager/DeckManager.java @@ -13,12 +13,14 @@ import javax.swing.JTable; import forge.itemmanager.filters.*; +import forge.itemmanager.views.CommanderBracketView; import forge.localinstance.properties.ForgePreferences; import org.apache.commons.lang3.StringUtils; import forge.Singletons; import forge.deck.Deck; import forge.deck.DeckBase; +import forge.deck.DeckFormat; import forge.deck.DeckProxy; import forge.deck.io.DeckPreferences; import forge.game.GameFormat; @@ -72,6 +74,10 @@ public DeckManager(final GameType gt, final CDetailPicture cDetailPicture) { super(DeckProxy.class, cDetailPicture, true, false); this.gameType = gt; + if (gt.getDeckFormat() == DeckFormat.Commander) { + this.addView(new CommanderBracketView(this)); + } + this.addSelectionListener(e -> { if (cmdSelect != null) { cmdSelect.run(); @@ -86,6 +92,11 @@ public GameType getGameType() { return gameType; } + @Override + public ItemManagerModel getModel() { + return super.getModel(); + } + @Override public void setup(final ItemManagerConfig config0) { final boolean wasStringOnly = (this.getConfig() == ItemManagerConfig.STRING_ONLY); diff --git a/forge-gui-desktop/src/main/java/forge/itemmanager/ItemManager.java b/forge-gui-desktop/src/main/java/forge/itemmanager/ItemManager.java index c454877b03c..5d6b80f2565 100644 --- a/forge-gui-desktop/src/main/java/forge/itemmanager/ItemManager.java +++ b/forge-gui-desktop/src/main/java/forge/itemmanager/ItemManager.java @@ -139,10 +139,21 @@ protected ItemManager(final Class genericType0, final CDetailPicture cDetailP this.currentView = this.listView; } + protected void addView(final ItemView view) { + if (this.initialized) { + throw new IllegalStateException("Views must be added before ItemManager initialization"); + } + this.views.add(view); + } + protected ImageView createImageView(final ItemManagerModel model0) { return new ImageView<>(this, model0, this.showRanking); } + protected ItemManagerModel getModel() { + return this.model; + } + public final CDetailPicture getCDetailPicture() { return cDetailPicture; } diff --git a/forge-gui-desktop/src/main/java/forge/itemmanager/views/CommanderBracketDeckView.java b/forge-gui-desktop/src/main/java/forge/itemmanager/views/CommanderBracketDeckView.java new file mode 100644 index 00000000000..50b34489756 --- /dev/null +++ b/forge-gui-desktop/src/main/java/forge/itemmanager/views/CommanderBracketDeckView.java @@ -0,0 +1,23 @@ +package forge.itemmanager.views; + +import forge.deck.CommanderBracketCalculator; +import forge.deck.Deck; +import forge.item.PaperCard; +import forge.itemmanager.CardManager; +import forge.itemmanager.ItemManagerModel; + +@SuppressWarnings("serial") +public final class CommanderBracketDeckView extends CommanderBracketTextView { + private final Deck deck; + + public CommanderBracketDeckView(final CardManager itemManager0, final ItemManagerModel model0, final Deck deck0) { + super(itemManager0, model0); + this.deck = deck0; + updateText(); + } + + @Override + protected String getText() { + return deck.getName() + "\n\n" + CommanderBracketCalculator.getExplanation(deck); + } +} diff --git a/forge-gui-desktop/src/main/java/forge/itemmanager/views/CommanderBracketTextView.java b/forge-gui-desktop/src/main/java/forge/itemmanager/views/CommanderBracketTextView.java new file mode 100644 index 00000000000..75ce6d1af11 --- /dev/null +++ b/forge-gui-desktop/src/main/java/forge/itemmanager/views/CommanderBracketTextView.java @@ -0,0 +1,170 @@ +package forge.itemmanager.views; + +import forge.item.InventoryItem; +import forge.itemmanager.ColumnDef; +import forge.itemmanager.ItemManager; +import forge.itemmanager.ItemManagerConfig; +import forge.itemmanager.ItemManagerModel; +import forge.localinstance.skin.FSkinProp; +import forge.toolbox.FLabel; +import forge.toolbox.FPanel; +import forge.toolbox.FSkin; + +import javax.swing.JComponent; +import javax.swing.JTextArea; +import javax.swing.JViewport; +import javax.swing.border.EmptyBorder; +import java.awt.BorderLayout; +import java.awt.Font; +import java.awt.Point; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +@SuppressWarnings("serial") +abstract class CommanderBracketTextView extends ItemView { + private final FPanel panel = new FPanel(new BorderLayout()); + private final JTextArea textArea = new JTextArea(); + private int selectedIndex = -1; + + CommanderBracketTextView(final ItemManager itemManager0, final ItemManagerModel model0) { + super(itemManager0, model0); + this.panel.setBackgroundTexture(FSkin.getIcon(FSkinProp.BG_TEXTURE)); + this.panel.setBorderToggle(false); + this.textArea.setEditable(false); + this.textArea.setLineWrap(true); + this.textArea.setWrapStyleWord(true); + this.textArea.setOpaque(false); + this.textArea.setFont(FSkin.getFont(13).getBaseFont()); + this.textArea.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT).getColor()); + this.textArea.setCaretColor(FSkin.getColor(FSkin.Colors.CLR_TEXT).getColor()); + this.textArea.setBorder(new EmptyBorder(8, 8, 8, 8)); + this.panel.add(textArea, BorderLayout.CENTER); + this.getButton().setBorder(new EmptyBorder(4, 0, 0, 0)); + this.getPnlOptions().setVisible(false); + } + + @Override + public JComponent getComponent() { + return panel; + } + + @Override + public void setup(final ItemManagerConfig config, final Map colOverrides) { + } + + @Override + public void setAllowMultipleSelections(final boolean allowMultipleSelections) { + } + + @Override + public T getItemAtIndex(final int index) { + final List> items = model.getOrderedList(); + if (index < 0 || index >= items.size()) { + return null; + } + return items.get(index).getKey(); + } + + @Override + public int getIndexOfItem(final T item) { + final List> items = model.getOrderedList(); + for (int i = 0; i < items.size(); i++) { + if (items.get(i).getKey().equals(item)) { + return i; + } + } + return -1; + } + + @Override + public int getSelectedIndex() { + return selectedIndex; + } + + @Override + public Iterable getSelectedIndices() { + return selectedIndex < 0 ? Collections.emptyList() : Collections.singletonList(selectedIndex); + } + + @Override + public void selectAll() { + } + + @Override + public int getCount() { + return model.getOrderedList().size(); + } + + @Override + public int getSelectionCount() { + return selectedIndex < 0 ? 0 : 1; + } + + @Override + public int getIndexAtPoint(final Point p) { + return selectedIndex; + } + + @Override + protected FSkin.SkinImage getIcon() { + return null; + } + + @Override + protected String getButtonText() { + return "B"; + } + + @Override + protected void configureTextButton(final FLabel.Builder buttonBuilder) { + buttonBuilder.fontStyle(Font.BOLD).fontSize(18); + } + + @Override + protected String getCaption() { + return localizer.getMessage("lblBracketView"); + } + + @Override + protected void onSetSelectedIndex(final int index) { + selectedIndex = index; + updateText(); + onSelectionChange(); + } + + @Override + protected void onSetSelectedIndices(final Iterable indices) { + final List indexList = new ArrayList<>(); + for (final Integer index : indices) { + indexList.add(index); + } + selectedIndex = indexList.isEmpty() ? -1 : indexList.get(0); + updateText(); + onSelectionChange(); + } + + @Override + protected void onScrollSelectionIntoView(final JViewport viewport) { + } + + @Override + protected void onResize() { + } + + @Override + protected void onRefresh() { + if (selectedIndex >= getCount()) { + selectedIndex = getCount() - 1; + } + updateText(); + } + + protected final void updateText() { + textArea.setText(getText()); + textArea.setCaretPosition(0); + } + + protected abstract String getText(); +} diff --git a/forge-gui-desktop/src/main/java/forge/itemmanager/views/CommanderBracketView.java b/forge-gui-desktop/src/main/java/forge/itemmanager/views/CommanderBracketView.java new file mode 100644 index 00000000000..05d377b28ba --- /dev/null +++ b/forge-gui-desktop/src/main/java/forge/itemmanager/views/CommanderBracketView.java @@ -0,0 +1,26 @@ +package forge.itemmanager.views; + +import forge.deck.CommanderBracketCalculator; +import forge.deck.DeckProxy; +import forge.itemmanager.DeckManager; +import forge.itemmanager.ItemManagerModel; + +@SuppressWarnings("serial") +public final class CommanderBracketView extends CommanderBracketTextView { + public CommanderBracketView(final DeckManager itemManager0) { + super(itemManager0, getModel(itemManager0)); + } + + private static ItemManagerModel getModel(final DeckManager itemManager) { + return itemManager.getModel(); + } + + @Override + protected String getText() { + final DeckProxy deck = getSelectedItem(); + if (deck == null) { + return localizer.getMessage("lblCommanderBracketSelectDeck"); + } + return deck.getName() + "\n\n" + CommanderBracketCalculator.getExplanation(deck.getDeck()); + } +} diff --git a/forge-gui-desktop/src/main/java/forge/itemmanager/views/ItemView.java b/forge-gui-desktop/src/main/java/forge/itemmanager/views/ItemView.java index 7412066bcab..1eafd389b2b 100644 --- a/forge-gui-desktop/src/main/java/forge/itemmanager/views/ItemView.java +++ b/forge-gui-desktop/src/main/java/forge/itemmanager/views/ItemView.java @@ -85,13 +85,27 @@ protected void processMouseWheelEvent(final MouseWheelEvent e) { this.pnlOptions.setOpaque(false); this.pnlOptions.setBorder(new FSkin.MatteSkinBorder(1, 0, 0, 0, BORDER_COLOR)); this.scroller.setBorder(new FSkin.LineSkinBorder(BORDER_COLOR)); - this.button = new FLabel.Builder() + final String buttonText = getButtonText(); + final FLabel.Builder buttonBuilder = new FLabel.Builder() .hoverable() .selectable(true) - .icon(getIcon()) - .iconScaleAuto(false) .tooltip(getCaption()) - .build(); + .text(buttonText); + final SkinImage icon = getIcon(); + if (icon == null) { + buttonBuilder.fontAlign(SwingConstants.CENTER); + configureTextButton(buttonBuilder); + } + else { + buttonBuilder.icon(icon).iconScaleAuto(false); + } + this.button = buttonBuilder.build(); + if (buttonText != null) { + this.button.setHorizontalAlignment(SwingConstants.CENTER); + this.button.setVerticalAlignment(SwingConstants.CENTER); + this.button.setHorizontalTextPosition(SwingConstants.CENTER); + this.button.setVerticalTextPosition(SwingConstants.CENTER); + } this.uniqueCardsOnlyChkBox = new FCheckBox(localizer.getMessage("lblUniqueCardsOnly"), this.itemManager.getWantUnique()); @@ -341,6 +355,11 @@ public String toString() { public abstract int getSelectionCount(); public abstract int getIndexAtPoint(Point p); protected abstract SkinImage getIcon(); + protected String getButtonText() { + return null; + } + protected void configureTextButton(final FLabel.Builder buttonBuilder) { + } protected abstract String getCaption(); protected abstract void onSetSelectedIndex(int index); protected abstract void onSetSelectedIndices(Iterable indices); diff --git a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CAllDecks.java b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CAllDecks.java index 83c2f0b714a..467db702ff8 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CAllDecks.java +++ b/forge-gui-desktop/src/main/java/forge/screens/deckeditor/controllers/CAllDecks.java @@ -1,6 +1,7 @@ package forge.screens.deckeditor.controllers; import forge.deck.DeckBase; +import forge.deck.DeckFormat; import forge.deck.DeckProxy; import forge.gui.framework.ICDoc; import forge.item.InventoryItem; @@ -51,7 +52,10 @@ public static void refreshDeckManager(DeckManager dm, Iterable deckLi } public static void updateDeckManager(DeckManager dm){ - dm.setup(ItemManagerConfig.CONSTRUCTED_DECKS); + final ItemManagerConfig config = dm.getGameType().getDeckFormat() == DeckFormat.Commander + ? ItemManagerConfig.COMMANDER_DECKS + : ItemManagerConfig.CONSTRUCTED_DECKS; + dm.setup(config); if (dm.getSelectedIndex() == 0) { // This may be default and so requiring potential update! ACEditorBase editorCtrl = diff --git a/forge-gui-desktop/src/test/java/forge/deck/CommanderBracketDataTest.java b/forge-gui-desktop/src/test/java/forge/deck/CommanderBracketDataTest.java new file mode 100644 index 00000000000..08392d49308 --- /dev/null +++ b/forge-gui-desktop/src/test/java/forge/deck/CommanderBracketDataTest.java @@ -0,0 +1,136 @@ +package forge.deck; + +import forge.GuiDesktop; +import forge.gui.GuiBase; +import forge.localinstance.properties.ForgeConstants; +import forge.util.FileUtil; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.stream.Stream; + +import static org.testng.Assert.fail; + +public class CommanderBracketDataTest { + private static final String NAME_PREFIX = "Name:"; + private static final String FLAVOR_NAME_PREFIX = "FlavorName:"; + + @BeforeClass + public void setUp() { + GuiBase.setInterface(new GuiDesktop()); + } + + @Test + public void bracketCardNamesResolveInDatabase() { + final Set cardNames = getCardDatabaseNames(); + final Map> unknownCards = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + + for (final String filename : List.of( + ForgeConstants.COMMANDER_BRACKET_GAMECHANGERS_FILE, + ForgeConstants.COMMANDER_BRACKET_MASS_LAND_DENIAL_FILE, + ForgeConstants.COMMANDER_BRACKET_EXTRA_TURNS_FILE, + ForgeConstants.COMMANDER_BRACKET_CHAINED_EXTRA_TURNS_FILE)) { + validateFile(cardNames, filename, false, unknownCards); + } + validateFile(cardNames, ForgeConstants.COMMANDER_BRACKET_COMBOS_FILE, true, unknownCards); + + if (!unknownCards.isEmpty()) { + fail("Commander bracket list contains " + unknownCards.size() + + " unknown card name(s):\n" + formatUnknownCards(unknownCards)); + } + } + + private static Set getCardDatabaseNames() { + final Set cardNames = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); + try (Stream paths = Files.walk(Path.of(ForgeConstants.CARD_DATA_DIR))) { + paths.filter(path -> path.toString().endsWith(".txt")) + .forEach(path -> readCardName(path, cardNames)); + } catch (final IOException e) { + fail("Could not read card database names from " + ForgeConstants.CARD_DATA_DIR, e); + } + return cardNames; + } + + private static void readCardName(final Path path, final Set cardNames) { + final List faceNames = new ArrayList<>(); + for (final String line : FileUtil.readFile(path.toString())) { + if (line.startsWith(NAME_PREFIX)) { + final String cardName = line.substring(NAME_PREFIX.length()).trim(); + cardNames.add(cardName); + faceNames.add(cardName); + } + else if (line.contains(FLAVOR_NAME_PREFIX)) { + cardNames.add(line.substring(line.indexOf(FLAVOR_NAME_PREFIX) + FLAVOR_NAME_PREFIX.length()).trim()); + } + } + if (faceNames.size() > 1) { + cardNames.add(String.join(" // ", faceNames)); + } + } + + private static void validateFile(final Set cardNames, final String filename, final boolean comboFile, + final Map> unknownCards) { + int lineNumber = 0; + for (final String line : FileUtil.readFile(filename)) { + lineNumber++; + final String data = stripComment(line).trim(); + if (data.isEmpty()) { + continue; + } + + if (!comboFile) { + validateCardName(cardNames, filename, lineNumber, data, unknownCards); + continue; + } + + final String[] parts = data.split("\\s*\\|\\s*"); + if (parts.length < 3) { + addUnknownCard(unknownCards, data, filename, lineNumber, "fewer than 3 columns"); + continue; + } + validateCardName(cardNames, filename, lineNumber, parts[1].trim(), unknownCards); + validateCardName(cardNames, filename, lineNumber, parts[2].trim(), unknownCards); + } + } + + private static void validateCardName(final Set cardNames, final String filename, final int lineNumber, + final String cardName, final Map> unknownCards) { + if (!cardNames.contains(cardName)) { + addUnknownCard(unknownCards, cardName, filename, lineNumber, null); + } + } + + private static void addUnknownCard(final Map> unknownCards, final String cardName, + final String filename, final int lineNumber, final String note) { + String location = filename + ":" + lineNumber; + if (note != null) { + location += " (" + note + ")"; + } + unknownCards.computeIfAbsent(cardName, key -> new ArrayList<>()).add(location); + } + + private static String formatUnknownCards(final Map> unknownCards) { + final StringBuilder errors = new StringBuilder(); + for (final Map.Entry> entry : unknownCards.entrySet()) { + errors.append(entry.getKey()) + .append(" at ") + .append(String.join(", ", entry.getValue())) + .append("\n"); + } + return errors.toString(); + } + + private static String stripComment(final String line) { + final int commentIndex = line.indexOf('#'); + return commentIndex < 0 ? line : line.substring(0, commentIndex); + } +} diff --git a/forge-gui/res/languages/de-DE.properties b/forge-gui/res/languages/de-DE.properties index 3f15694de7c..4cd3cb386c3 100644 --- a/forge-gui/res/languages/de-DE.properties +++ b/forge-gui/res/languages/de-DE.properties @@ -3561,4 +3561,26 @@ lblRepair=Reparieren lblDataMigrationMsg=Datenmigration abgeschlossen!\nBitte überprüfen Sie Ihr Inventar und Ihre Ausrüstung.\nBitte erstellen Sie an dieser Stelle eine Sicherungskopie Ihrer Spielstände, da der aktuelle Spielstand noch nicht überschrieben wird, wenn Sie im Menü „Szene“ den Punkt „Daten“ -> „Sicherungskopie“ verwenden. #AdventureDeckEditor.java lblRemoveUnsupportedCard=Verwijder niet-ondersteunde kaart -lblRemoveAllUnsupportedCards=Nicht unterstützte Karten wurden aus Ihrem Inventar entfernt. \ No newline at end of file +lblRemoveAllUnsupportedCards=Nicht unterstützte Karten wurden aus Ihrem Inventar entfernt. +lblBracket=Gruppe +ttCommanderBracket=Vorgeschlagene Mindest-Einstufungsgruppe für Commander +lblBracketView=Gruppenansicht +lblCommanderBracketMinimum=Commander-Mindestgruppe: {0} +lblCommanderBracketSelectDeck=Wählen Sie ein Commander-Deck aus, um die Gruppenerklärung anzuzeigen. +lblCommanderBracketGameChangers=Game Changers +lblCommanderBracketMassLandDenial=Massenlandverweigerung +lblCommanderBracketExtraTurns=Extrazüge +lblCommanderBracketChainedExtraTurns=Verkettete Extrazüge +lblCommanderBracketTwoCardCombos=2-Karten-Kombos +lblCommanderBracketLateGame=Spätes Spiel +lblCommanderBracketEarlyGame=Frühes Spiel +lblCommanderBracketReasonGameChangersFour=4 oder mehr Game Changers machen das Deck mindestens zu Gruppe 4. +lblCommanderBracketReasonGameChangersOne=1 bis 3 Game Changers machen das Deck mindestens zu Gruppe 3. +lblCommanderBracketReasonMassLandDenial=Massenlandverweigerung macht das Deck mindestens zu Gruppe 4. +lblCommanderBracketReasonChainedExtraTurn=Verkettete Extrazug-Karten machen das Deck mindestens zu Gruppe 4. +lblCommanderBracketReasonExtraTurnsFour=4 oder mehr Extrazug-Karten machen das Deck mindestens zu Gruppe 4. +lblCommanderBracketReasonExtraTurnsThree=3 oder mehr Extrazug-Karten machen das Deck mindestens zu Gruppe 3. +lblCommanderBracketReasonExtraTurnsTwo=2 Extrazug-Karten machen das Deck mindestens zu Gruppe 2. +lblCommanderBracketReasonExtraTurnsFew=Weniger als 2 Extrazug-Karten erhöhen die Gruppe nicht. +lblCommanderBracketReasonLateGameCombo=2-Karten-Kombos im späten Spiel machen das Deck mindestens zu Gruppe 3. +lblCommanderBracketReasonEarlyGameCombo=2-Karten-Kombos im frühen Spiel machen das Deck mindestens zu Gruppe 4. diff --git a/forge-gui/res/languages/en-US.properties b/forge-gui/res/languages/en-US.properties index c7e95e5b03f..ab6987aee98 100644 --- a/forge-gui/res/languages/en-US.properties +++ b/forge-gui/res/languages/en-US.properties @@ -3459,4 +3459,25 @@ lblRemoveUnsupportedCard=Remove unsupported card lblRemoveAllUnsupportedCards=Unsupported cards have been removed from your inventory. lbldisableCrackedItems=Disable the possibility of your items breaking after losing a boss fight. lblusepricelist=Use the (currently experimental) price generation based on a set cardlist. - +lblBracket=Bracket +ttCommanderBracket=Suggested minimum Commander bracket +lblBracketView=Bracket View +lblCommanderBracketMinimum=Minimum Commander Bracket: {0} +lblCommanderBracketSelectDeck=Select a Commander deck to see its bracket explanation. +lblCommanderBracketGameChangers=Game Changers +lblCommanderBracketMassLandDenial=Mass Land Denial +lblCommanderBracketExtraTurns=Extra Turns +lblCommanderBracketChainedExtraTurns=Chained Extra Turns +lblCommanderBracketTwoCardCombos=2-card Combos +lblCommanderBracketLateGame=Late Game +lblCommanderBracketEarlyGame=Early Game +lblCommanderBracketReasonGameChangersFour=4 or more Game Changers make the deck at least Bracket 4. +lblCommanderBracketReasonGameChangersOne=1 to 3 Game Changers make the deck at least Bracket 3. +lblCommanderBracketReasonMassLandDenial=Mass Land Denial makes the deck at least Bracket 4. +lblCommanderBracketReasonChainedExtraTurn=Chained Extra Turn cards make the deck at least Bracket 4. +lblCommanderBracketReasonExtraTurnsFour=4 or more Extra Turn cards make the deck at least Bracket 4. +lblCommanderBracketReasonExtraTurnsThree=3 or more Extra Turn cards make the deck at least Bracket 3. +lblCommanderBracketReasonExtraTurnsTwo=2 Extra Turn cards make the deck at least Bracket 2. +lblCommanderBracketReasonExtraTurnsFew=Fewer than 2 Extra Turn cards do not raise the bracket. +lblCommanderBracketReasonLateGameCombo=Late Game 2-card combos make the deck at least Bracket 3. +lblCommanderBracketReasonEarlyGameCombo=Early Game 2-card combos make the deck at least Bracket 4. diff --git a/forge-gui/res/languages/es-ES.properties b/forge-gui/res/languages/es-ES.properties index 03762cc9d0b..505bb70742c 100644 --- a/forge-gui/res/languages/es-ES.properties +++ b/forge-gui/res/languages/es-ES.properties @@ -3542,4 +3542,26 @@ lblRepair=Reparar lblDataMigrationMsg=¡Migración de datos completada!\nPor favor revise su inventario y equipos.\nPor favor, haz una copia de seguridad de tus partidas guardadas en este punto, ya que la partida guardada real aún no se sobrescribe al usar Datos -> Copia de seguridad en la Escena del menú. #AdventureDeckEditor.java lblRemoveUnsupportedCard=Quitar tarjeta incompatible -lblRemoveAllUnsupportedCards=Las tarjetas no compatibles se han eliminado de tu inventario. \ No newline at end of file +lblRemoveAllUnsupportedCards=Las tarjetas no compatibles se han eliminado de tu inventario. +lblBracket=Grupo +ttCommanderBracket=Grupo mínimo sugerido para Commander +lblBracketView=Vista de grupo +lblCommanderBracketMinimum=Grupo mínimo de Commander: {0} +lblCommanderBracketSelectDeck=Selecciona un mazo de Commander para ver la explicación del grupo. +lblCommanderBracketGameChangers=Cartas decisivas +lblCommanderBracketMassLandDenial=Neutralización masiva de tierras +lblCommanderBracketExtraTurns=Turnos adicionales +lblCommanderBracketChainedExtraTurns=Turnos adicionales encadenados +lblCommanderBracketTwoCardCombos=Combos con 2 cartas +lblCommanderBracketLateGame=Final del juego +lblCommanderBracketEarlyGame=Principio del juego +lblCommanderBracketReasonGameChangersFour=4 o más cartas decisivas hacen que el mazo sea al menos del grupo 4. +lblCommanderBracketReasonGameChangersOne=De 1 a 3 cartas decisivas hacen que el mazo sea al menos del grupo 3. +lblCommanderBracketReasonMassLandDenial=La neutralización masiva de tierras hace que el mazo sea al menos del grupo 4. +lblCommanderBracketReasonChainedExtraTurn=Las cartas que encadenan turnos adicionales hacen que el mazo sea al menos del grupo 4. +lblCommanderBracketReasonExtraTurnsFour=4 o más cartas de turnos adicionales hacen que el mazo sea al menos del grupo 4. +lblCommanderBracketReasonExtraTurnsThree=3 o más cartas de turnos adicionales hacen que el mazo sea al menos del grupo 3. +lblCommanderBracketReasonExtraTurnsTwo=2 cartas de turnos adicionales hacen que el mazo sea al menos del grupo 2. +lblCommanderBracketReasonExtraTurnsFew=Menos de 2 cartas de turnos adicionales no aumentan el grupo. +lblCommanderBracketReasonLateGameCombo=Los combos con 2 cartas al final del juego hacen que el mazo sea al menos del grupo 3. +lblCommanderBracketReasonEarlyGameCombo=Los combos con 2 cartas al principio del juego hacen que el mazo sea al menos del grupo 4. diff --git a/forge-gui/res/languages/fr-FR.properties b/forge-gui/res/languages/fr-FR.properties index 1e2c0faba3f..e6d86b95709 100644 --- a/forge-gui/res/languages/fr-FR.properties +++ b/forge-gui/res/languages/fr-FR.properties @@ -3543,4 +3543,26 @@ lblRepair=Réparation lblDataMigrationMsg=Migration des données terminée!\nVeuillez vérifier votre inventaire et vos équipements.\nVeuillez effectuer une sauvegarde de vos sauvegardes à ce stade, car la sauvegarde réelle n'est pas encore écrasée en utilisant Données -> Sauvegarde dans le menu Scène. #AdventureDeckEditor.java lblRemoveUnsupportedCard=Supprimer la carte non prise en charge -lblRemoveAllUnsupportedCards=Les cartes non prises en charge ont été supprimées de votre inventaire. \ No newline at end of file +lblRemoveAllUnsupportedCards=Les cartes non prises en charge ont été supprimées de votre inventaire. +lblBracket=Catégorie +ttCommanderBracket=Catégorie minimum suggérée pour Commander +lblBracketView=Vue des catégories +lblCommanderBracketMinimum=Catégorie Commander minimum : {0} +lblCommanderBracketSelectDeck=Sélectionnez un deck Commander pour voir l’explication de la catégorie. +lblCommanderBracketGameChangers=Cartes à impact +lblCommanderBracketMassLandDenial=Refus de terrains massif +lblCommanderBracketExtraTurns=Tours supplémentaires +lblCommanderBracketChainedExtraTurns=Tours supplémentaires enchaînés +lblCommanderBracketTwoCardCombos=Combos à 2 cartes +lblCommanderBracketLateGame=Fin de partie +lblCommanderBracketEarlyGame=Début de partie +lblCommanderBracketReasonGameChangersFour=4 Cartes à impact ou plus placent le deck au moins en catégorie 4. +lblCommanderBracketReasonGameChangersOne=1 à 3 Cartes à impact placent le deck au moins en catégorie 3. +lblCommanderBracketReasonMassLandDenial=Le refus de terrains massif place le deck au moins en catégorie 4. +lblCommanderBracketReasonChainedExtraTurn=Les cartes qui enchaînent les tours supplémentaires placent le deck au moins en catégorie 4. +lblCommanderBracketReasonExtraTurnsFour=4 cartes de tours supplémentaires ou plus placent le deck au moins en catégorie 4. +lblCommanderBracketReasonExtraTurnsThree=3 cartes de tours supplémentaires ou plus placent le deck au moins en catégorie 3. +lblCommanderBracketReasonExtraTurnsTwo=2 cartes de tours supplémentaires placent le deck au moins en catégorie 2. +lblCommanderBracketReasonExtraTurnsFew=Moins de 2 cartes de tours supplémentaires ne modifient pas la catégorie. +lblCommanderBracketReasonLateGameCombo=Les combos à 2 cartes de fin de partie placent le deck au moins en catégorie 3. +lblCommanderBracketReasonEarlyGameCombo=Les combos à 2 cartes de début de partie placent le deck au moins en catégorie 4. diff --git a/forge-gui/res/languages/it-IT.properties b/forge-gui/res/languages/it-IT.properties index dbefaf842f0..fae525ace19 100644 --- a/forge-gui/res/languages/it-IT.properties +++ b/forge-gui/res/languages/it-IT.properties @@ -3541,4 +3541,26 @@ lblRepair=Riparazione lblDataMigrationMsg=Migrazione dati completata!\nControlla il tuo inventario e le tue attrezzature.\nA questo punto, esegui un backup dei tuoi salvataggi, poiché il salvataggio effettivo non è ancora stato sovrascritto, utilizzando Dati -> Backup nel menu Scena. #AdventureDeckEditor.java lblRemoveUnsupportedCard=Rimuovi la carta non supportata -lblRemoveAllUnsupportedCards=Le carte non supportate sono state rimosse dal tuo inventario. \ No newline at end of file +lblRemoveAllUnsupportedCards=Le carte non supportate sono state rimosse dal tuo inventario. +lblBracket=Fascia +ttCommanderBracket=Fascia minima suggerita per Commander +lblBracketView=Vista fasce +lblCommanderBracketMinimum=Fascia Commander minima: {0} +lblCommanderBracketSelectDeck=Seleziona un mazzo Commander per vedere la spiegazione della fascia. +lblCommanderBracketGameChangers=Game Changer +lblCommanderBracketMassLandDenial=Negazione di massa delle terre +lblCommanderBracketExtraTurns=Turni extra +lblCommanderBracketChainedExtraTurns=Turni extra concatenati +lblCommanderBracketTwoCardCombos=Combo da 2 carte +lblCommanderBracketLateGame=Fase avanzata +lblCommanderBracketEarlyGame=Fase iniziale +lblCommanderBracketReasonGameChangersFour=4 o più Game Changer rendono il mazzo almeno di fascia 4. +lblCommanderBracketReasonGameChangersOne=Da 1 a 3 Game Changer rendono il mazzo almeno di fascia 3. +lblCommanderBracketReasonMassLandDenial=La negazione di massa delle terre rende il mazzo almeno di fascia 4. +lblCommanderBracketReasonChainedExtraTurn=Le carte che concatenano turni extra rendono il mazzo almeno di fascia 4. +lblCommanderBracketReasonExtraTurnsFour=4 o più carte di turni extra rendono il mazzo almeno di fascia 4. +lblCommanderBracketReasonExtraTurnsThree=3 o più carte di turni extra rendono il mazzo almeno di fascia 3. +lblCommanderBracketReasonExtraTurnsTwo=2 carte di turni extra rendono il mazzo almeno di fascia 2. +lblCommanderBracketReasonExtraTurnsFew=Meno di 2 carte di turni extra non aumentano la fascia. +lblCommanderBracketReasonLateGameCombo=Le combo da 2 carte in fase avanzata rendono il mazzo almeno di fascia 3. +lblCommanderBracketReasonEarlyGameCombo=Le combo da 2 carte in fase iniziale rendono il mazzo almeno di fascia 4. diff --git a/forge-gui/res/languages/ja-JP.properties b/forge-gui/res/languages/ja-JP.properties index 6452f0bea3f..92510c77c30 100644 --- a/forge-gui/res/languages/ja-JP.properties +++ b/forge-gui/res/languages/ja-JP.properties @@ -3537,4 +3537,26 @@ lblRepair=修理 lblDataMigrationMsg=データ移行が完了しました!\nインベントリと装備を確認してください。\n実際の保存はまだメニューシーンの「データ」->「バックアップ」を使用して上書きされていないため、この時点で保存のバックアップを作成してください。 #AdventureDeckEditor.java lblRemoveUnsupportedCard=サポートされていないカードを削除する -lblRemoveAllUnsupportedCards=サポートされていないカードはインベントリから削除されました。 \ No newline at end of file +lblRemoveAllUnsupportedCards=サポートされていないカードはインベントリから削除されました。 +lblBracket=ブラケット +ttCommanderBracket=統率者の推奨最低ブラケット +lblBracketView=ブラケット表示 +lblCommanderBracketMinimum=統率者戦の最低ブラケット: {0} +lblCommanderBracketSelectDeck=統率者デッキを選択すると、ブラケットの説明が表示されます。 +lblCommanderBracketGameChangers=ゲームチェンジャー +lblCommanderBracketMassLandDenial=大量土地妨害 +lblCommanderBracketExtraTurns=追加ターン +lblCommanderBracketChainedExtraTurns=連続追加ターン +lblCommanderBracketTwoCardCombos=2枚コンボ +lblCommanderBracketLateGame=終盤 +lblCommanderBracketEarlyGame=序盤 +lblCommanderBracketReasonGameChangersFour=ゲームチェンジャーが4枚以上あるため、このデッキは少なくともブラケット4です。 +lblCommanderBracketReasonGameChangersOne=ゲームチェンジャーが1~3枚あるため、このデッキは少なくともブラケット3です。 +lblCommanderBracketReasonMassLandDenial=大量土地妨害があるため、このデッキは少なくともブラケット4です。 +lblCommanderBracketReasonChainedExtraTurn=連続追加ターン・カードがあるため、このデッキは少なくともブラケット4です。 +lblCommanderBracketReasonExtraTurnsFour=追加ターン・カードが4枚以上あるため、このデッキは少なくともブラケット4です。 +lblCommanderBracketReasonExtraTurnsThree=追加ターン・カードが3枚以上あるため、このデッキは少なくともブラケット3です。 +lblCommanderBracketReasonExtraTurnsTwo=追加ターン・カードが2枚あるため、このデッキは少なくともブラケット2です。 +lblCommanderBracketReasonExtraTurnsFew=追加ターン・カードが2枚未満のため、ブラケットは上がりません。 +lblCommanderBracketReasonLateGameCombo=終盤の2枚コンボがあるため、このデッキは少なくともブラケット3です。 +lblCommanderBracketReasonEarlyGameCombo=序盤の2枚コンボがあるため、このデッキは少なくともブラケット4です。 diff --git a/forge-gui/res/languages/ko-KR.properties b/forge-gui/res/languages/ko-KR.properties index 5fd53df5968..26c783a840f 100644 --- a/forge-gui/res/languages/ko-KR.properties +++ b/forge-gui/res/languages/ko-KR.properties @@ -3323,4 +3323,26 @@ lblRepair=수리 lblDataMigrationMsg=데이터 마이그레이션이 완료되었습니다!\n인벤토리와 장비를 확인하세요.\n실제 저장 데이터는 아직 메뉴 화면의 ‘데이터’ -> '백업'을 사용하여 덮어쓰지 않았으므로, 이 시점에서 저장 백업을 생성하세요. #AdventureDeckEditor.java lblRemoveUnsupportedCard=지원되지 않는 카드 제거 -lblRemoveAllUnsupportedCards=지원되지 않는 카드가 인벤토리에서 제거되었습니다. \ No newline at end of file +lblRemoveAllUnsupportedCards=지원되지 않는 카드가 인벤토리에서 제거되었습니다. +lblBracket=브래킷 +ttCommanderBracket=추천 최소 커맨더 브래킷 +lblBracketView=브래킷 보기 +lblCommanderBracketMinimum=커맨더 최소 브래킷: {0} +lblCommanderBracketSelectDeck=브래킷 설명을 보려면 커맨더 덱을 선택하세요. +lblCommanderBracketGameChangers=게임 체인저 +lblCommanderBracketMassLandDenial=대량 대지 방해 +lblCommanderBracketExtraTurns=추가 턴 +lblCommanderBracketChainedExtraTurns=연쇄 추가 턴 +lblCommanderBracketTwoCardCombos=2장 콤보 +lblCommanderBracketLateGame=후반 +lblCommanderBracketEarlyGame=초반 +lblCommanderBracketReasonGameChangersFour=게임 체인저가 4장 이상이면 이 덱은 최소 브래킷 4입니다. +lblCommanderBracketReasonGameChangersOne=게임 체인저가 1~3장이면 이 덱은 최소 브래킷 3입니다. +lblCommanderBracketReasonMassLandDenial=대량 대지 방해가 있으면 이 덱은 최소 브래킷 4입니다. +lblCommanderBracketReasonChainedExtraTurn=연쇄 추가 턴 카드는 이 덱을 최소 브래킷 4로 만듭니다. +lblCommanderBracketReasonExtraTurnsFour=추가 턴 카드가 4장 이상이면 이 덱은 최소 브래킷 4입니다. +lblCommanderBracketReasonExtraTurnsThree=추가 턴 카드가 3장 이상이면 이 덱은 최소 브래킷 3입니다. +lblCommanderBracketReasonExtraTurnsTwo=추가 턴 카드가 2장이면 이 덱은 최소 브래킷 2입니다. +lblCommanderBracketReasonExtraTurnsFew=추가 턴 카드가 2장 미만이면 브래킷이 올라가지 않습니다. +lblCommanderBracketReasonLateGameCombo=후반 2장 콤보는 이 덱을 최소 브래킷 3으로 만듭니다. +lblCommanderBracketReasonEarlyGameCombo=초반 2장 콤보는 이 덱을 최소 브래킷 4로 만듭니다. diff --git a/forge-gui/res/languages/pt-BR.properties b/forge-gui/res/languages/pt-BR.properties index fd9eec4ba4c..7b8f451c5b4 100644 --- a/forge-gui/res/languages/pt-BR.properties +++ b/forge-gui/res/languages/pt-BR.properties @@ -3626,4 +3626,26 @@ lblRepair=Reparar lblDataMigrationMsg=Migração de dados concluída!\nVerifique seu inventário e equipamentos.\nPor favor, faça um backup dos seus arquivos salvos neste momento, já que o arquivo salvo atual ainda não foi sobrescrito usando Dados -> Backup na Cena do Menu. #AdventureDeckEditor.java lblRemoveUnsupportedCard=Remover cartão não suportado -lblRemoveAllUnsupportedCards=Cartas não suportadas foram removidas do seu inventário. \ No newline at end of file +lblRemoveAllUnsupportedCards=Cartas não suportadas foram removidas do seu inventário. +lblBracket=Grupo +ttCommanderBracket=Grupo mínimo sugerido para Commander +lblBracketView=Visão de grupo +lblCommanderBracketMinimum=Grupo mínimo de Commander: {0} +lblCommanderBracketSelectDeck=Selecione um deck de Commander para ver a explicação do grupo. +lblCommanderBracketGameChangers=Cards decisivos +lblCommanderBracketMassLandDenial=Negação massiva de terrenos +lblCommanderBracketExtraTurns=Turnos extras +lblCommanderBracketChainedExtraTurns=Turnos extras encadeados +lblCommanderBracketTwoCardCombos=Combos de 2 cards +lblCommanderBracketLateGame=Fim de jogo +lblCommanderBracketEarlyGame=Início de jogo +lblCommanderBracketReasonGameChangersFour=4 ou mais cards decisivos tornam o deck pelo menos do grupo 4. +lblCommanderBracketReasonGameChangersOne=De 1 a 3 cards decisivos tornam o deck pelo menos do grupo 3. +lblCommanderBracketReasonMassLandDenial=Negação massiva de terrenos torna o deck pelo menos do grupo 4. +lblCommanderBracketReasonChainedExtraTurn=Cards que encadeiam turnos extras tornam o deck pelo menos do grupo 4. +lblCommanderBracketReasonExtraTurnsFour=4 ou mais cards de turnos extras tornam o deck pelo menos do grupo 4. +lblCommanderBracketReasonExtraTurnsThree=3 ou mais cards de turnos extras tornam o deck pelo menos do grupo 3. +lblCommanderBracketReasonExtraTurnsTwo=2 cards de turnos extras tornam o deck pelo menos do grupo 2. +lblCommanderBracketReasonExtraTurnsFew=Menos de 2 cards de turnos extras não aumentam o grupo. +lblCommanderBracketReasonLateGameCombo=Combos de 2 cards no fim de jogo tornam o deck pelo menos do grupo 3. +lblCommanderBracketReasonEarlyGameCombo=Combos de 2 cards no início de jogo tornam o deck pelo menos do grupo 4. diff --git a/forge-gui/res/languages/zh-CN.properties b/forge-gui/res/languages/zh-CN.properties index dd8947ba8e6..6ebaf5fccf9 100644 --- a/forge-gui/res/languages/zh-CN.properties +++ b/forge-gui/res/languages/zh-CN.properties @@ -3529,3 +3529,25 @@ lblDataMigrationMsg=数据迁移完成!\n请检查您的库存和设备。此 #AdventureDeckEditor.java lblRemoveUnsupportedCard=移除不受支持的卡 lblRemoveAllUnsupportedCards=不受支持的卡已从您的库存中移除。 +lblBracket=分级 +ttCommanderBracket=建议的指挥官最低分级 +lblBracketView=分级视图 +lblCommanderBracketMinimum=指挥官最低分级:{0} +lblCommanderBracketSelectDeck=选择一个指挥官套牌以查看分级说明。 +lblCommanderBracketGameChangers=游戏改变者 +lblCommanderBracketMassLandDenial=大规模地阻 +lblCommanderBracketExtraTurns=额外回合 +lblCommanderBracketChainedExtraTurns=连续额外回合 +lblCommanderBracketTwoCardCombos=2张牌组合技 +lblCommanderBracketLateGame=后期 +lblCommanderBracketEarlyGame=前期 +lblCommanderBracketReasonGameChangersFour=4张或更多游戏改变者会使该套牌至少为第4级。 +lblCommanderBracketReasonGameChangersOne=1到3张游戏改变者会使该套牌至少为第3级。 +lblCommanderBracketReasonMassLandDenial=大规模地阻会使该套牌至少为第4级。 +lblCommanderBracketReasonChainedExtraTurn=连续额外回合牌会使该套牌至少为第4级。 +lblCommanderBracketReasonExtraTurnsFour=4张或更多额外回合牌会使该套牌至少为第4级。 +lblCommanderBracketReasonExtraTurnsThree=3张或更多额外回合牌会使该套牌至少为第3级。 +lblCommanderBracketReasonExtraTurnsTwo=2张额外回合牌会使该套牌至少为第2级。 +lblCommanderBracketReasonExtraTurnsFew=少于2张额外回合牌不会提高分级。 +lblCommanderBracketReasonLateGameCombo=后期2张牌组合技会使该套牌至少为第3级。 +lblCommanderBracketReasonEarlyGameCombo=前期2张牌组合技会使该套牌至少为第4级。 diff --git a/forge-gui/res/lists/chained-extra-turns.txt b/forge-gui/res/lists/chained-extra-turns.txt new file mode 100644 index 00000000000..2e5867f6436 --- /dev/null +++ b/forge-gui/res/lists/chained-extra-turns.txt @@ -0,0 +1,12 @@ +Time Warp +Temporal Manipulation +Walk the Aeons +Capture of Jingzhou +Expropriate +Time Stretch +Nexus of Fate +Timestream Navigator +Sage of Hours +Lighthouse Chronologist +Time Sieve +Magosi, the Waterveil diff --git a/forge-gui/res/lists/commander-bracket-combos.txt b/forge-gui/res/lists/commander-bracket-combos.txt new file mode 100644 index 00000000000..921edec3d16 --- /dev/null +++ b/forge-gui/res/lists/commander-bracket-combos.txt @@ -0,0 +1,2176 @@ +late_game | Sheoldred, the Apocalypse | Peer into the Abyss +late_game | Niv-Mizzet, Visionary | Niv-Mizzet, Parun +late_game | Niv-Mizzet, Parun | Ophidian Eye +late_game | Tidespout Tyrant | Sol Ring +late_game | Peer into the Abyss | Underworld Dreams +late_game | Jeska's Will | Reiterate +late_game | Aurelia, the Warleader | Helm of the Host +late_game | Psychosis Crawler | Peer into the Abyss +late_game | Mana Geyser | Reiterate +late_game | Vraska, Betrayal's Sting | Vorinclex, Monstrous Raider +late_game | Dragon Tempest | Ancient Gold Dragon +late_game | Ancient Copper Dragon | Aggravated Assault +late_game | Polyraptor | Marauding Raptor +late_game | Approach of the Second Sun | Mystical Tutor +late_game | Teferi, Temporal Archmage | The Chain Veil +late_game | Old Gnawbone | Hellkite Charger +late_game | Aggravated Assault | Old Gnawbone +late_game | The World Tree | Maskwood Nexus +late_game | Niv-Mizzet, Visionary | Niv-Mizzet, the Firemind +late_game | Riverchurn Monument | Maddening Cacophony +late_game | Bruvac the Grandiloquent | Terisian Mindbreaker +late_game | Approach of the Second Sun | Reprieve +late_game | Bruvac the Grandiloquent | Fleet Swallower +late_game | Duskmantle Guildmage | Maddening Cacophony +late_game | Peer into the Abyss | Bloodletter of Aclazotz +late_game | Bumi, Unleashed | Ashaya, Soul of the Wild +late_game | Tidespout Tyrant | Mana Vault +late_game | Brass's Bounty | Revel in Riches +late_game | Orthion, Hero of Lavabrink | Terror of the Peaks +late_game | Cybermen Squadron | Blightsteel Colossus +late_game | Fleet Swallower | Fraying Sanity +late_game | Riverchurn Monument | Jidoor, Aristocratic Capital +late_game | Archetype of Imagination | Stormtide Leviathan +late_game | Maze's End | Reshape the Earth +late_game | Tidespout Tyrant | Mox Opal +late_game | Doppelgang | Eternal Witness +late_game | Exquisite Blood | Defiant Bloodlord +late_game | Kefka, Court Mage | Psychosis Crawler +late_game | Enter the Infinite | Thassa's Oracle +late_game | Jace, Wielder of Mysteries | Enter the Infinite +late_game | Drogskol Reaver | Queza, Augur of Agonies +late_game | Cavern-Hoard Dragon | Aggravated Assault +late_game | Approach of the Second Sun | Narset's Reversal +late_game | Astral Dragon | Cursed Mirror +late_game | Riverchurn Monument | Cut Your Losses +late_game | Bootleggers' Stash | Revel in Riches +late_game | Biovisionary | Rite of Replication +late_game | Tidespout Tyrant | Grim Monolith +late_game | Toxrill, the Corrosive | Maha, Its Feathers Night +late_game | Ayara, First of Locthwain | Plague of Vermin +late_game | Kefka, Court Mage | Niv-Mizzet, Parun +late_game | Approach of the Second Sun | Solve the Equation +late_game | Brine Elemental | Vesuvan Shapeshifter +late_game | Mikaeus, the Unhallowed | Triskelion +late_game | Riverchurn Monument | Singularity Rupture +late_game | Approach of the Second Sun | Demonic Tutor +late_game | Vito, Thorn of the Dusk Rose | Shard of the Nightbringer +late_game | Shard of the Nightbringer | Sanguine Bond +late_game | Jumbo Cactuar | Selvala, Heart of the Wilds +late_game | Enter the Infinite | Psychosis Crawler +late_game | Peer into the Abyss | Teferi's Ageless Insight +late_game | Approach of the Second Sun | Scroll Rack +late_game | There and Back Again | Clockspinning +late_game | Rionya, Fire Dancer | Terror of the Peaks +late_game | Bloodthirsty Conqueror | Defiant Bloodlord +late_game | Be'lakor, the Dark Master | Rite of Replication +late_game | The World Tree | Purphoros, God of the Forge +late_game | Brass's Bounty | Reiterate +late_game | Scourge of the Throne | Helm of the Host +late_game | Palinchron | Deadeye Navigator +late_game | Vizkopa Guildmage | Revival // Revenge +late_game | Hellkite Charger | Sozin's Comet +late_game | Mindslaver | Academy Ruins +late_game | Emry, Lurker of the Loch | Mindslaver +late_game | Astarion, the Decadent | Blood Tribute +late_game | Approach of the Second Sun | Vampiric Tutor +late_game | Drogskol Reaver | Shabraz, the Skyshark +late_game | Maddening Cacophony | Keening Stone +late_game | Vizkopa Guildmage | Beacon of Immortality +late_game | Realmbreaker, the Invasion Tree | Maskwood Nexus +late_game | James, Wandering Dad | Mechanized Production +late_game | Demonic Pact | Blim, Comedic Genius +late_game | Leyline of the Guildpact | Coalition Victory +late_game | Toralf, God of Fury | Star of Extinction +late_game | Riverchurn Monument | Fleet Swallower +late_game | Heartless Hidetsugu | Wound Reflection +late_game | The Reaver Cleaver | Hellkite Charger +late_game | Havoc Festival | Wound Reflection +late_game | Orthion, Hero of Lavabrink | Fanatic of Mogis +late_game | Drogskol Reaver | Sheoldred, the Apocalypse +late_game | Traumatize | Keening Stone +late_game | Toph, the First Metalbender | Mindslaver +late_game | Approach of the Second Sun | Personal Tutor +late_game | The World Tree | Arcane Adaptation +late_game | Mirkwood Bats | Plague of Vermin +late_game | Polyraptor | Warstorm Surge +late_game | Brass's Bounty | Mechanized Production +late_game | Terra, Magical Adept | Yenna, Redtooth Regent +late_game | The World Tree | Rukarumel, Biologist +late_game | Blightsteel Colossus | Chandra's Ignition +late_game | Dualcaster Mage | Sublime Epiphany +late_game | Magistrate's Scepter | Clock of Omens +late_game | Solemnity | Decree of Silence +late_game | Heartless Hidetsugu | Angrath's Marauders +late_game | Cut Your Losses | Keening Stone +late_game | Terror of the Peaks | Rite of Replication +late_game | Devastating Onslaught | Terror of the Peaks +late_game | Storm Herd | Cathars' Crusade +late_game | Fleet Swallower | Keening Stone +late_game | Avacyn, Angel of Hope | Worldslayer +late_game | Zedruu the Greathearted | Transcendence +late_game | Gisela, Blade of Goldnight | Heartless Hidetsugu +late_game | Kefka, Court Mage | Magmakin Artillerist +late_game | Avacyn, Angel of Hope | Nevinyrral's Disk +late_game | Terisian Mindbreaker | Keening Stone +late_game | Doppelgang | Biovisionary +late_game | Chandra's Ignition | Jumbo Cactuar +late_game | Kefka, Court Mage | Glint-Horn Buccaneer +late_game | The Locust God | Sage of the Falls +late_game | Abdel Adrian, Gorion's Ward | Deadeye Navigator +late_game | The World Tree | Leyline of Transformation +late_game | Dawnsire, Sunstar Dreadnought | Brash Taunter +late_game | Turnabout | Reiterate +late_game | Blightsteel Colossus | Blade of Selves +late_game | Myrkul, Lord of Bones | Barrenton Medic +late_game | Maha, Its Feathers Night | Elesh Norn, Grand Cenobite +late_game | Approach of the Second Sun | Diabolic Tutor +late_game | Brion Stoutarm | Serra Avatar +late_game | Venser, Shaper Savant | Approach of the Second Sun +late_game | Hellkite Charger | Sword of Feast and Famine +late_game | Kefka, Court Mage | Niv-Mizzet, the Firemind +late_game | Doomsday Excruciator | Breach the Multiverse +late_game | Gray Merchant of Asphodel | Rite of Replication +late_game | Astral Dragon | Machine God's Effigy +late_game | Tivit, Seller of Secrets | Deadeye Navigator +late_game | Bootleggers' Stash | Mechanized Production +late_game | Aetheric Amplifier | Magistrate's Scepter +late_game | Palinchron | Phantasmal Image +late_game | Twenty-Toed Toad | Enter the Infinite +late_game | Doomsday Excruciator | Maddening Cacophony +late_game | Baral's Expertise | Dualcaster Mage +late_game | Jarad, Golgari Lich Lord | Jumbo Cactuar +late_game | Hellkite Charger | Zuko, Firebending Master +late_game | Great Whale | Deadeye Navigator +late_game | Arabella, Abandoned Doll | Storm Herd +late_game | Unstoppable Slasher | Archfiend of Despair +late_game | Nyxbloom Ancient | Rite of Replication +late_game | Filigree Sages | Chromatic Orrery +late_game | Orthion, Hero of Lavabrink | Gray Merchant of Asphodel +late_game | Zacama, Primal Calamity | Temur Sabertooth +late_game | Peer into the Abyss | Folio of Fancies +late_game | Shard of the Nightbringer | Wound Reflection +late_game | Scourge of Valkas | Rite of Replication +late_game | Heartless Hidetsugu | Archfiend of Despair +late_game | Mind Over Matter | Azami, Lady of Scrolls +late_game | Doomsday Excruciator | Fractured Sanity +late_game | Neera, Wild Mage | Displacer Kitten +late_game | Anzrag, the Quake-Mole | Last Night Together +late_game | Approach of the Second Sun | Remand +late_game | Approach of the Second Sun | Necropotence +late_game | Palinchron | Nyxbloom Ancient +late_game | Muldrotha, the Gravetide | Mindslaver +late_game | The Enigma Jewel | Basalt Monolith +late_game | Enter the Infinite | Psychic Corrosion +late_game | Biovisionary | Aggressive Biomancy +late_game | Scourge of the Skyclaves | Archfiend of Despair +late_game | Teferi's Protection | Obliterate +late_game | Magistrate's Scepter | Viral Drake +late_game | Elesh Norn, Grand Cenobite | Nature's Revolt +late_game | Swarm Intelligence | Reiterate +late_game | Triskaidekaphile | Stroke of Genius +late_game | Shard of the Nightbringer | Archfiend of Despair +late_game | Mind Over Matter | Arcanis the Omnipotent +late_game | Miirym, Sentinel Wyrm | Worldgorger Dragon +late_game | Spiteful Sliver | Star of Extinction +late_game | Bladewing the Risen | Cursed Mirror +late_game | Grievous Wound | Archfiend of Despair +late_game | The World Tree | Conspiracy +late_game | Inner Fire | Reiterate +late_game | Hellkite Charger | Nature's Will +late_game | Rionya, Fire Dancer | Bloodthirster +late_game | Bladewing the Risen | Saw in Half +late_game | Bruvac the Grandiloquent | Lord Xander, the Collector +late_game | Flameshadow Conjuring | Worldgorger Dragon +late_game | Realmbreaker, the Invasion Tree | Arcane Adaptation +late_game | Devastating Onslaught | Exalted Sunborn +late_game | Jace's Archivist | Mind Over Matter +late_game | Grievous Wound | Warlock Class +late_game | Naru Meha, Master Wizard | Sublime Epiphany +late_game | Esoteric Duplicator | Mindslaver +late_game | Approach of the Second Sun | Demonic Consultation +late_game | Teferi's Protection | Worldfire +late_game | Animar, Soul of Elements | Palinchron +late_game | Avacyn, Angel of Hope | Magus of the Disk +late_game | Polyraptor | Aether Flash +late_game | Dawnsire, Sunstar Dreadnought | Screaming Nemesis +late_game | Scourge of the Skyclaves | Wound Reflection +late_game | Unstoppable Slasher | Warlock Class +late_game | Havoc Festival | Archfiend of Despair +late_game | Avatar of Woe | Thornbite Staff +late_game | Storm Herd | Molten Gatekeeper +late_game | The Enigma Jewel | Aphetto Alchemist +late_game | Varragoth, Bloodsky Sire | Nexus of Fate +late_game | Approach of the Second Sun | Wheel of Fortune +late_game | Sword of the Paruns | Howlsquad Heavy +late_game | Lord Xander, the Collector | Fraying Sanity +late_game | Brago, King Eternal | Aurelia, the Warleader +late_game | Storm Herd | Agate Instigator +late_game | Mind Over Matter | Chromatic Orrery +late_game | Lulu, Stern Guardian | Magistrate's Scepter +late_game | Avacyn, Angel of Hope | Obliterate +late_game | Feast of Sanity | Peer into the Abyss +late_game | Staff of Domination | Kydele, Chosen of Kruphix +late_game | Rukarumel, Biologist | Realmbreaker, the Invasion Tree +late_game | Phage the Untouchable | Fractured Identity +late_game | Astarion, the Decadent | Peer into the Abyss +late_game | Zacama, Primal Calamity | Sanctum of Eternity +late_game | Kratos, Stoic Father | Sage of Hours +late_game | Scytheclaw | Wound Reflection +late_game | Doppelgang | Archaeomancer +late_game | Spawnsire of Ulamog | Ashnod's Altar +late_game | Storm Herd | Warleader's Call +late_game | Scourge of Valkas | Orthion, Hero of Lavabrink +late_game | Astarion, the Decadent | Fraying Omnipotence +late_game | Fraying Omnipotence | Warlock Class +late_game | Bladewing the Risen | Deceptive Frostkite +late_game | Maha, Its Feathers Night | Pestilence Demon +late_game | Altar of Dementia | Jumbo Cactuar +late_game | Fraying Omnipotence | Archfiend of Despair +late_game | Approach of the Second Sun | Unsubstantiate +late_game | Storm Herd | Purphoros, God of the Forge +late_game | Peer into the Abyss | Vnwxt, Verbose Host +late_game | Ilharg, the Raze-Boar | Medomai the Ageless +late_game | Inalla, Archmage Ritualist | Wanderwine Prophets +late_game | Palinchron | Emiel the Blessed +late_game | Virtus the Veiled | Archfiend of Despair +late_game | Palinchron | Elesh Norn, Mother of Machines +late_game | Grab the Reins | Serra Avatar +late_game | Approach of the Second Sun | Tainted Pact +late_game | Aggravated Assault | The Legend of Kyoshi +late_game | Super State | Tainted Strike +late_game | Sphinx of the Second Sun | Aggravated Assault +late_game | Dawnsire, Sunstar Dreadnought | Spitemare +late_game | Old Gnawbone | Mechanized Production +late_game | Dawnsire, Sunstar Dreadnought | Donna Noble +late_game | Storm Herd | Witty Roastmaster +late_game | Rionya, Fire Dancer | Scourge of the Throne +late_game | Ruthless Technomancer | Jumbo Cactuar +late_game | Naru Meha, Master Wizard | Three Steps Ahead +late_game | Filigree Sages | Empowered Autogenerator +late_game | Soulfire Grand Master | Mana Geyser +late_game | Fury Storm | Professor Onyx +late_game | Kefka, Court Mage | Starving Revenant +late_game | Panoptic Mirror | Expropriate +late_game | Baral's Expertise | Naru Meha, Master Wizard +late_game | Requiem Monolith | Dawnsire, Sunstar Dreadnought +late_game | Noctis, Heir Apparent | Vorpal Sword +late_game | Virtus the Veiled | Warlock Class +late_game | Polyraptor | Blasting Station +late_game | Twenty-Toed Toad | Peer into the Abyss +late_game | Deathbringer Thoctar | Vorpal Sword +late_game | Drogskol Reaver | Horizon Chimera +late_game | Reality Spasm | Reiterate +late_game | Éomer, Marshal of Rohan | Legion Loyalty +late_game | Vilis, Broker of Blood | Curse of Fool's Wisdom +late_game | Transcendence | Platinum Angel +late_game | Najeela, the Blade-Blossom | Old Gnawbone +late_game | Proteus Staff | Nexus of Fate +late_game | Palinchron | Extraplanar Lens +late_game | Rakdos, the Muscle | Doomsday Excruciator +late_game | Dawnsire, Sunstar Dreadnought | Wrathful Raptors +late_game | Scourge of the Skyclaves | Warlock Class +late_game | Deathbringer Thoctar | Archetype of Finality +late_game | Spawnsire of Ulamog | Mondrak, Glory Dominus +late_game | Chandra's Ignition | Serra Avatar +late_game | Yarok, the Desecrated | Palinchron +late_game | Palinchron | Caged Sun +late_game | Panoptic Mirror | Nexus of Fate +late_game | Dovescape | Guile +late_game | Scytheclaw | Warlock Class +late_game | Beacon of Immortality | False Cure +late_game | Windswift Slice | Jumbo Cactuar +late_game | Mindslaver | Prototype Portal +late_game | Realmbreaker, the Invasion Tree | Conspiracy +late_game | Toralf, God of Fury | Dawnsire, Sunstar Dreadnought +late_game | Lich | Repay in Kind +late_game | The War Doctor | Dance with Calamity +late_game | Shard of the Nightbringer | Warlock Class +late_game | Dawnsire, Sunstar Dreadnought | Barbed Servitor +late_game | Approach of the Second Sun | Drawn from Dreams +late_game | Aphelia, Viper Whisperer | Warlock Class +late_game | Doomsday Excruciator | Thassa's Oracle +late_game | Teferi, Mage of Zhalfir | Omen Machine +late_game | Tombstone Stairwell | Vein Ripper +late_game | Shadow of the Second Sun | Aggravated Assault +late_game | Be'lakor, the Dark Master | Orthion, Hero of Lavabrink +late_game | Astarion, the Decadent | Scourge of the Skyclaves +late_game | Magistrate's Scepter | Merfolk Skydiver +late_game | Worldfire | Outpost Siege +late_game | Chandra's Ignition | Soul of Eternity +late_game | Drafna, Founder of Lat-Nam | Ugin's Nexus +late_game | Dualcaster Mage | Doppelgang +late_game | Gogo, Master of Mimicry | Magistrate's Scepter +late_game | Dance with Calamity | Laboratory Maniac +late_game | Barren Glory | Renounce +late_game | Mayael's Aria | Colossification +late_game | Myr Matrix | Mana Echoes +late_game | Azor, the Lawbringer | Deadeye Navigator +late_game | Dualcaster Mage | Blue Sun's Twilight +late_game | Impostor Syndrome | Aurelia, the Warleader +late_game | Super State | Triumph of the Hordes +late_game | Mutagen Man, Living Ooze | Mechanized Production +late_game | Mirage Phalanx | Bloodthirster +late_game | Starfall Invocation | Dualcaster Mage +late_game | Deathbringer Thoctar | Quietus Spike +late_game | Niv-Mizzet, Parun | Snake Umbra +late_game | Doomsday Excruciator | One Ring to Rule Them All +late_game | Magus of the Coffers | Sword of the Paruns +late_game | Aggravated Assault | Shriekwood Devourer +late_game | Demonic Pact | Zedruu the Greathearted +late_game | Samut, the Driving Force | Sprout Swarm +late_game | Near-Death Experience | Doom Whisperer +late_game | Panoptic Mirror | Temporal Mastery +late_game | Aggravated Assault | Primal Adversary +late_game | Transcendence | Lich's Mastery +late_game | Doppelgang | Pinnacle Monk +late_game | The Enigma Jewel | Grim Monolith +late_game | Alpharael, Stonechosen | Archfiend of Despair +late_game | Palinchron | Eldrazi Displacer +late_game | Spawnsire of Ulamog | Ojer Taq, Deepest Foundation +late_game | Great Whale | Emiel the Blessed +late_game | Phyrexian Altar | Nevinyrral, Urborg Tyrant +late_game | Plague of Vermin | Corpse Knight +late_game | Mayael's Aria | Chameleon Colossus +late_game | Panoptic Mirror | Time Stretch +late_game | Shredder, Shadow Master | Archfiend of Despair +late_game | Shabraz, the Skyshark | Lich's Mastery +late_game | Dawnsire, Sunstar Dreadnought | Wrathful Red Dragon +late_game | Worldgorger Dragon | Worldfire +late_game | Alpharael, Stonechosen | Warlock Class +late_game | Necromantic Selection | Dualcaster Mage +late_game | Varragoth, Bloodsky Sire | Beacon of Tomorrows +late_game | Panoptic Mirror | Rise of the Eldrazi +late_game | Leveler | Nexus of Fate +late_game | Ulamog's Dreadsire | Intruder Alarm +late_game | Niv-Mizzet, the Firemind | Helm of the Ghastlord +late_game | Endless Detour | Approach of the Second Sun +late_game | Archmage Ascension | Nexus of Fate +late_game | Feldon of the Third Path | Timestream Navigator +late_game | Massacre Wurm | Natural Affinity +late_game | Niv-Mizzet, Parun | Helm of the Ghastlord +late_game | Palinchron | Mana Reflection +late_game | Shared Trauma | Doomsday Excruciator +late_game | Soulfire Grand Master | Time Warp +late_game | Kiki-Jiki, Mirror Breaker | Double Major +late_game | Dualcaster Mage | Stolen Identity +late_game | Palinchron | Zendikar Resurgent +late_game | Ezio Auditore da Firenze | Magister Sphinx +late_game | Myojin of Cryptic Dreams | Kiora's Dambreaker +late_game | Heartless Hidetsugu | Warlock Class +late_game | Reset | Reiterate +late_game | Doubling Cube | Capsize +late_game | Elesh Norn, Grand Cenobite | Godhead of Awe +late_game | Lord Xander, the Collector | Keening Stone +late_game | Blitzwing, Cruel Tormentor | Scourge of the Skyclaves +late_game | Worldslayer | Soul of New Phyrexia +late_game | Riverchurn Monument | Lord Xander, the Collector +late_game | Mind Over Matter | Niv-Mizzet, the Firemind +late_game | Eye of the Storm | Lavinia, Azorius Renegade +late_game | Approach of the Second Sun | Failure // Comply +late_game | Timestream Navigator | Planar Bridge +late_game | Baral's Expertise | Lutri, the Spellchaser +late_game | Morality Shift | Mortal Combat +late_game | Cavern-Hoard Dragon | Time Sieve +late_game | Spawnsire of Ulamog | Pitiless Plunderer +late_game | Tameshi, Reality Architect | Mindslaver +late_game | Monk Gyatso | Zacama, Primal Calamity +late_game | Mind Over Matter | Otherworld Atlas +late_game | Barren Glory | Decree of Annihilation +late_game | Radiant Performer | Door to Nothingness +late_game | Hermit Druid | Nexus of Fate +late_game | Nivix Guildmage | Brass's Bounty +late_game | Peer into the Abyss | Thought Reflection +late_game | Shredder, Shadow Master | Warlock Class +late_game | Palinchron | Riku of Two Reflections +late_game | Great Whale | Lilysplash Mentor +late_game | Lich | Soul Conduit +late_game | Nexus of Fate | Thought Lash +late_game | Panoptic Mirror | Beacon of Tomorrows +late_game | Heartless Hidetsugu | Goblin Goliath +late_game | The Last Agni Kai | Jumbo Cactuar +late_game | Spawnsire of Ulamog | Primal Vigor +late_game | Lich | Axis of Mortality +late_game | Dance with Calamity | Jace, Wielder of Mysteries +late_game | Dualcaster Mage | Ember Island Production +late_game | Archmage Ascension | Beacon of Tomorrows +late_game | Cogwork Assembler | Powerstone Shard +late_game | Jarad, Golgari Lich Lord | Hatred +late_game | Stormtide Leviathan | Choke +late_game | Storm Herd | Weftstalker Ardent +late_game | Vish Kal, Blood Arbiter | Mikaeus, the Unhallowed +late_game | Duke Ulder Ravengard | Blightsteel Colossus +late_game | Approach of the Second Sun | Farsight Ritual +late_game | Dance with Calamity | Thassa's Oracle +late_game | Ayara, Widow of the Realm | Breath of Fury +late_game | Storm Herd | General Kreat, the Boltbringer +late_game | Nivix Guildmage | Turnabout +late_game | Wanderwine Prophets | Maskwood Nexus +late_game | Palinchron | Mirari's Wake +late_game | Panoptic Mirror | Temporal Trespass +late_game | Dualcaster Mage | Will of the Temur +late_game | There and Back Again | Vitu-Ghazi Guildmage +late_game | Astral Dragon | Dance of Many +late_game | Myojin of Cryptic Dreams | Huatli's Raptor +late_game | Spawnsire of Ulamog | Elspeth, Storm Slayer +late_game | Aphelia, Viper Whisperer | Archfiend of Despair +late_game | Proteus Staff | Beacon of Tomorrows +late_game | Omnath, Locus of Rage | Mirrorform +late_game | Medomai the Ageless | Phantom Steed +late_game | Food Chain | Thrasta, Tempest's Roar +late_game | Panoptic Mirror | Alrund's Epiphany +late_game | Dismiss into Dream | Goblin Sharpshooter +late_game | Sharuum the Hegemon | Phantasmal Image +late_game | Filigree Sages | Doubling Cube +late_game | Polyraptor | Where Ancients Tread +late_game | Drogskol Reaver | Feast of Sanity +late_game | Storm King's Thunder | Prologue to Phyresis +late_game | Great Whale | Eldrazi Displacer +late_game | Minion Reflector | Worldgorger Dragon +late_game | Elite Arcanist | Nexus of Fate +late_game | Doppelgang | Greenwarden of Murasa +late_game | Magister Sphinx | Archfiend of Despair +late_game | Mind Over Matter | Selvala, Explorer Returned +late_game | Ad Nauseam | Platinum Emperion +late_game | Bearer of the Heavens | Gift of Immortality +late_game | Mayael's Aria | Tyvar, the Pummeler +late_game | Starfall Invocation | Naru Meha, Master Wizard +late_game | Body of Research | Season of Gathering +late_game | Sword of the Paruns | Cradle Clearcutter +late_game | Volo, Guide to Monsters | Palinchron +late_game | Agatha of the Vile Cauldron | Spawnsire of Ulamog +late_game | Kiki-Jiki, Mirror Breaker | Ratadrabik of Urborg +late_game | Marina Vendrell's Grimoire | Starving Revenant +late_game | Zinnia, Valley's Voice | Palinchron +late_game | Myojin of Cryptic Dreams | Eagle of Deliverance +late_game | Naru Meha, Master Wizard | Stolen Identity +late_game | Palinchron | Reflections of Littjara +late_game | Myojin of Cryptic Dreams | Bloom Hulk +late_game | Azor, the Lawbringer | Helm of the Host +late_game | Uyo, Silent Prophet | Doppelgang +late_game | Myojin of Cryptic Dreams | Biovisionary +late_game | Second Chance | Hanna, Ship's Navigator +late_game | Spawnsire of Ulamog | Illusionist's Bracers +late_game | Dark Leo & Shredder | Archfiend of Despair +late_game | Avatar Aang | Sprout Swarm +late_game | Avatar Aang | Recruit the Worthy +late_game | Doppelgang | Reiterate +late_game | Divine Intervention | Vampire Hexmage +late_game | Another Round | Naru Meha, Master Wizard +late_game | Naru Meha, Master Wizard | Doppelgang +late_game | Mirror Room // Fractured Realm | Palinchron +late_game | Charmbreaker Devils | Temporal Manipulation +late_game | Timestream Navigator | The Fire Crystal +late_game | Spawnsire of Ulamog | Training Grounds +late_game | Myojin of Cryptic Dreams | Dramatist's Puppet +late_game | Leveler | Beacon of Tomorrows +late_game | Biorhythm | Damnation +late_game | Spawnsire of Ulamog | Exalted Sunborn +late_game | Anzrag, the Quake-Mole | Darksteel Mutation +late_game | Doppelgang | Kairi, the Swirling Sky +late_game | Aggravated Assault | Rude Awakening +late_game | Archon of Emeria | Eye of the Storm +late_game | Bearer of the Heavens | Worldgorger Dragon +late_game | Lethal Vapors | Avacyn, Angel of Hope +late_game | Sage of Hours | Clockspinning +late_game | Obscura Interceptor | Approach of the Second Sun +late_game | Go-Shintai of Life's Origin | Second Chance +late_game | Aether Syphon | Peer into the Abyss +late_game | Infested Thrinax | Jumbo Cactuar +late_game | Soulless Jailer | Eye of the Storm +late_game | Spawnsire of Ulamog | Mana Echoes +late_game | Myojin of Cryptic Dreams | Proud Pack-Rhino +late_game | Marina Vendrell's Grimoire | Feast of Sanity +late_game | Tasigur, the Golden Fang | Mindslaver +late_game | Naru Meha, Master Wizard | Saheeli's Artistry +late_game | Bladewing the Risen | Phantasmal Image +late_game | Form of the Dragon | Sandwurm Convergence +late_game | Avatar Aang | Haze of Rage +late_game | Dualcaster Mage | Self-Reflection +late_game | Orthion, Hero of Lavabrink | Biovisionary +late_game | Astral Dragon | Oblivion Ring +late_game | Near-Death Experience | Ethereal Champion +late_game | Sekki, Seasons' Guide | Warstorm Surge +late_game | Enduring Scalelord | Helm of the Host +late_game | Mayael's Aria | Serra Avatar +late_game | The Master, Formed Anew | Palinchron +late_game | Bladewing the Risen | Glasspool Mimic +late_game | Avatar Aang | Lab Rats +late_game | Zacama, Primal Calamity | Stormfront Riders +late_game | Form of the Dragon | Axis of Mortality +late_game | Soulfire Grand Master | Temporal Manipulation +late_game | Storm Herd | Epic Struggle +late_game | Charmbreaker Devils | Walk the Aeons +late_game | Olivia's Attendants | Mechanized Production +late_game | Mayael's Aria | Colossus of Akros +late_game | Divine Intervention | Hex Parasite +late_game | Biorhythm | Austere Command +late_game | Balancing Act | Perch Protection +late_game | Thousand-Year Storm | Sprout Swarm +late_game | Worldfire | Nekusar, the Mindrazer +late_game | Morophon, the Boundless | Grinning Ignus +late_game | Heartless Hidetsugu | Vizkopa Guildmage +late_game | Planar Portal | Beacon of Tomorrows +late_game | Body of Research | Chandra's Ignition +late_game | Worldfire | Mogis, God of Slaughter +late_game | Charmbreaker Devils | Capture of Jingzhou +late_game | Moat | Sandwurm Convergence +late_game | Thousand-Year Storm | Spelljack +late_game | Eye of the Storm | Vexing Bauble +late_game | Magus of the Moat | Sandwurm Convergence +late_game | Naru Meha, Master Wizard | Will of the Temur +late_game | Divine Intervention | Clockspinning +late_game | Eye of the Storm | Spellshift +late_game | Havi, the All-Father | Moritte of the Frost +late_game | Volcano Hellion | Vito, Thorn of the Dusk Rose +late_game | Approach of the Second Sun | Plunge into Darkness +late_game | Astral Dragon | Parallax Wave +late_game | Bladewing the Risen | Heat Shimmer +late_game | The Legend of Kyoshi | Freed from the Real +late_game | Planar Portal | Nexus of Fate +late_game | Soulfire Grand Master | Brass's Bounty +late_game | Sekki, Seasons' Guide | Terror of the Peaks +late_game | Naru Meha, Master Wizard | Self-Reflection +late_game | Reins of Power | Echo Mage +late_game | Biorhythm | Wrath of God +late_game | Sway of the Stars | Syr Konrad, the Grim +late_game | Naru Meha, Master Wizard | Ember Island Production +late_game | Drogskol Reaver | Curse of Fool's Wisdom +late_game | Chrome Dome | Powerstone Shard +late_game | Avatar Aang | Seething Anger +late_game | Storm Herd | Slash, Reptile Rampager +late_game | Astral Dragon | Journey to Nowhere +late_game | Worldfire | Kroxa, Titan of Death's Hunger +late_game | Eye of the Storm | Void Mirror +late_game | Myojin of Cryptic Dreams | Gulping Scraptrap +late_game | Dino DNA | Palinchron +late_game | Soulfire Grand Master | Walk the Aeons +late_game | Conqueror's Galleon | Time Warp +late_game | Doppelgang | Ardent Elementalist +late_game | Mischievous Quanar | Turnabout +late_game | Dino DNA | Great Whale +late_game | Soulfire Grand Master | Capture of Jingzhou +late_game | Bladewing the Risen | Omni-Changeling +late_game | The Legend of Kyoshi | Body of Research +late_game | Earthcraft | Spawning Grounds +late_game | Palinchron | Flameshadow Conjuring +late_game | Mystic Decree | Stormtide Leviathan +late_game | Koh, the Face Stealer | Bloodthirster +late_game | Naru Meha, Master Wizard | Devastating Onslaught +late_game | Volrath, the Shapestealer | Patron of the Orochi +late_game | Opalescence | Day of the Dragons +late_game | Marneus Calgar | The Locust God +late_game | Chandra's Ignition | Enduring Angel +late_game | Mayael's Aria | Soul of Eternity +late_game | Biorhythm | Nevinyrral's Disk +late_game | Storm King's Thunder | Infectious Inquiry +late_game | Day of the Dragons | Starfield of Nyx +late_game | Radiant Performer | Confiscate +late_game | Ad Nauseam | Perch Protection +late_game | Divine Intervention | Resourceful Defense +late_game | Settle Beyond Reality | Dualcaster Mage +late_game | Eirdu, Carrier of Dawn | Workhorse +late_game | Toxrill, the Corrosive | Godhead of Awe +late_game | Nexus of Fate | Divining Witch +late_game | Storm King's Thunder | Vraska's Fall +late_game | Body of Research | Soul's Fire +late_game | Archetype of Imagination | Form of the Dragon +late_game | The Legend of Kyoshi | Pemmin's Aura +late_game | Conqueror's Galleon | Time Stretch +late_game | Molten Echoes | Supreme Exemplar +late_game | Bladewing the Risen | Clone +late_game | Memory Vessel | Doomsday Excruciator +late_game | Mind Over Matter | Quicksilver Dagger +late_game | Part the Waterveil | Radiate +late_game | Biorhythm | Supreme Verdict +late_game | Koh, the Face Stealer | Port Razer +late_game | Bladewing the Risen | Clever Impersonator +late_game | Mayael's Aria | Body of Research +late_game | Conqueror's Galleon | Temporal Manipulation +late_game | Timestream Navigator | Planar Portal +late_game | Form of the Dragon | Soul Conduit +late_game | Crystalline Crawler | Evolution Vat +late_game | Magister Sphinx | Hidetsugu's Second Rite +late_game | Storm King's Thunder | Infectious Bite +late_game | Riku of Two Reflections | Worldgorger Dragon +late_game | Intruder Alarm | Godsire +late_game | Conqueror's Galleon | Walk the Aeons +late_game | Mirror-Mad Phantasm | Progenitor Mimic +late_game | Jon Irenicus, Shattered One | Slipstream Serpent +late_game | Mayael's Aria | Enduring Angel +late_game | Bladewing the Risen | Dack's Duplicate +late_game | Conqueror's Galleon | Turnabout +late_game | Divine Intervention | Render Inert +late_game | Jon Irenicus, Shattered One | Island Fish Jasconius +late_game | Brion Stoutarm | Enduring Angel +late_game | The Enigma Jewel | Seeker of Skybreak +late_game | Wanderwine Prophets | Followed Footsteps +late_game | Karrthus, Tyrant of Jund | Splinter Twin +late_game | Aggravated Assault | Jolrael, Empress of Beasts +late_game | Marneus Calgar | Mana Echoes +late_game | Jon Irenicus, Shattered One | Marjhan +late_game | Jarad, Golgari Lich Lord | Serra Avatar +late_game | Bog Serpent | Assault Suit +late_game | Magar of the Magic Strings | Time Stretch +late_game | Rakdos Joins Up | Moritte of the Frost +late_game | Kefka, Court Mage | Queza, Augur of Agonies +late_game | Spawnsire of Ulamog | Kaya, Geist Hunter +late_game | Mind Over Matter | Urza's Blueprints +late_game | Olivia's Attendants | Time Sieve +late_game | Avacyn, Angel of Hope | Worms of the Earth +late_game | Jarad, Golgari Lich Lord | Soul of Eternity +late_game | Biorhythm | Damn +late_game | Lich's Mastery | Horizon Chimera +late_game | Bruce Banner | Power of Fire +late_game | Conqueror's Galleon | Capture of Jingzhou +late_game | Avacyn, Angel of Hope | Aether Storm +late_game | Possessed Portal | Ant Queen +late_game | Phyrexian Devourer | Nexus of Fate +late_game | Phyrexian Devourer | Assault Suit +late_game | Aphelia, Viper Whisperer | Astarion, the Decadent +late_game | Palinchron | Minion Reflector +late_game | Bruce Banner | Lavamancer's Skill +late_game | Medomai the Ageless | Koh, the Face Stealer +late_game | Enduring Scalelord | Kiki-Jiki, Mirror Breaker +late_game | Storm King's Thunder | Phyresis Outbreak +late_game | Ith, High Arcanist | Unctus, Grand Metatect +late_game | Sharuum the Hegemon | Sakashima's Protege +late_game | The One Ring | Time Elemental +late_game | Hermit Druid | Beacon of Tomorrows +late_game | Bladewing the Risen | Mirror Image +late_game | Cogwork Assembler | Mana Echoes +late_game | Jumbo Cactuar | Fire Lord Ozai +late_game | Conqueror's Galleon | Rude Awakening +late_game | Mayael's Aria | Loxodon Lifechanter +late_game | Tolsimir Wolfblood | Thornbite Staff +late_game | Bladewing the Risen | Naga Fleshcrafter +late_game | Mirror-Mad Phantasm | Blue Sun's Twilight +late_game | Approach of the Second Sun | Spellscorn Coven +late_game | Peer into the Abyss | Eruth, Tormented Prophet +late_game | Minsc & Boo, Timeless Heroes | Serra Avatar +late_game | Catapult Fodder | Soul of Eternity +late_game | Mind Over Matter | Staff of Eden, Vault's Key +late_game | Bladewing the Risen | Evil Twin +late_game | Xathrid Demon | Serra Avatar +late_game | Xathrid Demon | Soul of Eternity +late_game | Assault Suit | Slipstream Serpent +late_game | Sekki, Seasons' Guide | Pandemonium +late_game | Invasion of Fiora | Divine Intervention +late_game | Assault Suit | Island Fish Jasconius +late_game | Shabraz, the Skyshark | Lich +late_game | Biorhythm | Cleansing Nova +late_game | Fire Nation Archers | Mana Echoes +late_game | Goblin Sharpshooter | Overwhelming Splendor +late_game | The Legend of Kyoshi | Gauntlets of Light +late_game | Worldfire | Vela the Night-Clad +late_game | Doppelgang | Possessed Skaab +late_game | Mischievous Quanar | Brass's Bounty +late_game | Huatli, Radiant Champion | The Locust God +late_game | Conqueror's Galleon | Reset +late_game | Phyrexian Devourer | Beacon of Tomorrows +late_game | Body of Research | Thud +late_game | Timestream Navigator | Phyrexian Devourer +late_game | Bladewing the Risen | Necroduality +late_game | Myrkul, Lord of Bones | Astral Dragon +late_game | Dualcaster Mage | Invasion of Alara +late_game | Divine Intervention | Cemetery Desecrator +late_game | Mind Over Matter | Lu Su, Wu Advisor +late_game | Sharuum the Hegemon | Infinite Reflection +late_game | Nivix Guildmage | Channel the Suns +late_game | Mayael's Aria | Rootwire Amalgam +late_game | Radiant Performer | Lay Claim +late_game | Xathrid Demon | Enduring Angel +late_game | Palinchron | Molten Echoes +late_game | The Legend of Kyoshi | Seedcradle Witch +late_game | Mayael's Aria | Targ Nar, Demon-Fang Gnoll +late_game | Enduring Scalelord | Cackling Counterpart +late_game | Mirror-Mad Phantasm | Omni-Changeling +late_game | Charnelhoard Wurm | Time Warp +late_game | Radiant Performer | Volition Reins +late_game | Mind Over Matter | Sea Gate Loremaster +late_game | Casey & Raph, Hotheads | Deadeye Navigator +late_game | Curse of Marit Lage | Stormtide Leviathan +late_game | The Locust God | Beck // Call +late_game | Mischievous Quanar | Rude Awakening +late_game | Mirrodin Besieged | Morality Shift +late_game | Dismiss into Dream | Deathbringer Thoctar +late_game | Bladewing the Risen | Vizier of Many Faces +late_game | Mirror-Mad Phantasm | Vesuvan Doppelganger +late_game | Enduring Scalelord | Quasiduplicate +late_game | Doppelgang | Vampire Charmseeker +late_game | Mirror-Mad Phantasm | Unstable Shapeshifter +late_game | Charnelhoard Wurm | Capture of Jingzhou +late_game | Body of Research | Grab the Reins +late_game | Worldfire | Marath, Will of the Wild +late_game | Worms of the Earth | Aegis Angel +late_game | Charnelhoard Wurm | Walk the Aeons +late_game | Charnelhoard Wurm | Temporal Manipulation +late_game | Azor, the Lawbringer | Delina, Wild Mage +late_game | Worms of the Earth | Indestructibility +late_game | Atemsis, All-Seeing | Weird Harvest +late_game | Biorhythm | Magus of the Disk +late_game | High Alert | The Legend of Kyoshi +late_game | Bladewing the Risen | Undercover Operative +late_game | Mirror-Mad Phantasm | Legion Loyalty +late_game | One Ring to Rule Them All | Body of Research +late_game | The Legend of Kyoshi | Crab Umbra +late_game | Bladewing the Risen | Vesuvan Shapeshifter +late_game | Bladewing the Risen | Mercurial Pretender +late_game | Mind Over Matter | Ocular Halo +late_game | Shadowheart, Dark Justiciar | Body of Research +late_game | Mayael's Aria | Casey Jones, Asphalt Hooligan +late_game | The Legend of Kyoshi | Singing Bell Strike +late_game | Bladewing the Risen | Synth Infiltrator +late_game | Azor, the Lawbringer | Rionya, Fire Dancer +late_game | Super-Skrull | Mayael's Aria +late_game | Body of Research | Doom Weaver +early_game | Demonic Consultation | Thassa's Oracle +early_game | Exquisite Blood | Sanguine Bond +early_game | Tainted Pact | Thassa's Oracle +early_game | Exquisite Blood | Vito, Thorn of the Dusk Rose +early_game | Dramatic Reversal | Isochron Scepter +early_game | Bloodthirsty Conqueror | Vito, Thorn of the Dusk Rose +early_game | Dualcaster Mage | Twinflame +early_game | Gravecrawler | Phyrexian Altar +early_game | Niv-Mizzet, Parun | Curiosity +early_game | Bloodthirsty Conqueror | Sanguine Bond +early_game | Exquisite Blood | Enduring Tenacity +early_game | Chatterfang, Squirrel General | Pitiless Plunderer +early_game | Bloodchief Ascension | Mindcrank +early_game | Basalt Monolith | Forsaken Monument +early_game | Exquisite Blood | Marauding Blight-Priest +early_game | Peregrin Took | Nuka-Cola Vending Machine +early_game | Aetherflux Reservoir | Exquisite Blood +early_game | Dualcaster Mage | Molten Duplication +early_game | Bruvac the Grandiloquent | Maddening Cacophony +early_game | Bloodthirsty Conqueror | Enduring Tenacity +early_game | Rings of Brighthearth | Basalt Monolith +early_game | Walking Ballista | Heliod, Sun-Crowned +early_game | The Gitrog Monster | Dakmor Salvage +early_game | Kinnan, Bonder Prodigy | Basalt Monolith +early_game | Orcish Bowmasters | Peer into the Abyss +early_game | Peregrine Drake | Deadeye Navigator +early_game | Bloodthirsty Conqueror | Marauding Blight-Priest +early_game | The Reaver Cleaver | Aggravated Assault +early_game | Squee, the Immortal | Food Chain +early_game | Blasphemous Act | Repercussion +early_game | Peregrin Took | Experimental Confectioner +early_game | Niv-Mizzet, Parun | Tandem Lookout +early_game | Sword of Feast and Famine | Aggravated Assault +early_game | Blowfly Infestation | Nest of Scarabs +early_game | Dualcaster Mage | Saw in Half +early_game | Aetherflux Reservoir | Bloodthirsty Conqueror +early_game | Kiki-Jiki, Mirror Breaker | Zealous Conscripts +early_game | Staff of Domination | Marwyn, the Nurturer +early_game | Maddening Cacophony | Fraying Sanity +early_game | Dualcaster Mage | Heat Shimmer +early_game | Blowfly Infestation | Hapatra, Vizier of Poisons +early_game | Ashaya, Soul of the Wild | Quirion Ranger +early_game | Niv-Mizzet, the Firemind | Curiosity +early_game | The Gitrog Monster | The Necrobloom +early_game | Scurry Oak | Ivy Lane Denizen +early_game | Godo, Bandit Warlord | Helm of the Host +early_game | Staff of Domination | Circle of Dreams Druid +early_game | Combat Celebrant | Helm of the Host +early_game | Exquisite Blood | Starscape Cleric +early_game | Bruvac the Grandiloquent | Traumatize +early_game | Basalt Monolith | Forensic Gadgeteer +early_game | Kaalia of the Vast | Master of Cruelties +early_game | Malcolm, Keen-Eyed Navigator | Glint-Horn Buccaneer +early_game | Dualcaster Mage | Electroduplicate +early_game | Karn, the Great Creator | Mycosynth Lattice +early_game | Ondu Spiritdancer | Secret Arcade // Dusty Parlor +early_game | Professor Onyx | Chain of Smog +early_game | Basking Broodscale | Rosie Cotton of South Lane +early_game | Neheb, the Eternal | Aggravated Assault +early_game | Toralf, God of Fury | Blasphemous Act +early_game | Chain of Smog | Witherbloom Apprentice +early_game | Bruvac the Grandiloquent | Cut Your Losses +early_game | Mycosynth Lattice | Vandalblast +early_game | Solphim, Mayhem Dominus | Heartless Hidetsugu +early_game | Bloom Tender | Freed from the Real +early_game | Eternal Scourge | Food Chain +early_game | Staff of Domination | Selvala, Heart of the Wilds +early_game | Umbral Mantle | Priest of Titania +early_game | Combat Celebrant | Kiki-Jiki, Mirror Breaker +early_game | Duskmantle Guildmage | Mindcrank +early_game | Rosie Cotton of South Lane | Scurry Oak +early_game | Devoted Druid | Swift Reconfiguration +early_game | Savage Ventmaw | Aggravated Assault +early_game | Bloodthirsty Conqueror | Starscape Cleric +early_game | Satya, Aetherflux Genius | Lightning Runner +early_game | Cut Your Losses | Fraying Sanity +early_game | Vito, Thorn of the Dusk Rose | Blood Tribute +early_game | Abdel Adrian, Gorion's Ward | Animate Dead +early_game | Beacon of Immortality | Sanguine Bond +early_game | Umbral Mantle | Elvish Archdruid +early_game | Umbral Mantle | Marwyn, the Nurturer +early_game | Glacial Chasm | Icetill Explorer +early_game | Cultivator Colossus | Abundance +early_game | Ghostly Flicker | Dualcaster Mage +early_game | Aggravated Assault | Selvala, Heart of the Wilds +early_game | Ratadrabik of Urborg | Boromir, Warden of the Tower +early_game | Glint-Horn Buccaneer | Curiosity +early_game | Hazel's Brewmaster | Devoted Druid +early_game | Secret Arcade // Dusty Parlor | Ghostly Dancers +early_game | Kiki-Jiki, Mirror Breaker | Helm of the Host +early_game | Animate Dead | Worldgorger Dragon +early_game | High Perfect Morcant | Flourishing Defenses +early_game | Tivit, Seller of Secrets | Time Sieve +early_game | Razorkin Needlehead | Peer into the Abyss +early_game | Goblin Sharpshooter | Basilisk Collar +early_game | Basalt Monolith | Nyxbloom Ancient +early_game | Exquisite Blood | Cliffhaven Vampire +early_game | Food Chain | Misthollow Griffin +early_game | Niv-Mizzet, the Firemind | Ophidian Eye +early_game | Demonic Consultation | Laboratory Maniac +early_game | Ghostly Flicker | Naru Meha, Master Wizard +early_game | Kiki-Jiki, Mirror Breaker | Felidar Guardian +early_game | Doomsday | Thassa's Oracle +early_game | The Jolly Balloon Man | Village Bell-Ringer +early_game | Kiki-Jiki, Mirror Breaker | Village Bell-Ringer +early_game | Machine God's Effigy | Devoted Druid +early_game | Vivi Ornitier | Quicksilver Elemental +early_game | Rionya, Fire Dancer | Combat Celebrant +early_game | Umbral Mantle | Selvala, Heart of the Wilds +early_game | Exquisite Blood | Vizkopa Guildmage +early_game | Herd Baloth | Ivy Lane Denizen +early_game | Ancestral Statue | Animar, Soul of Elements +early_game | Niv-Mizzet, the Firemind | Tandem Lookout +early_game | Stuffy Doll | Pariah's Shield +early_game | Secret Arcade // Dusty Parlor | Archon of Sun's Grace +early_game | Unstoppable Slasher | Bloodletter of Aclazotz +early_game | Exquisite Blood | Dina, Soul Steeper +early_game | Abdel Adrian, Gorion's Ward | Necromancy +early_game | Blazing Sunsteel | Brash Taunter +early_game | Bloom Tender | Pemmin's Aura +early_game | Stuffy Doll | Pariah +early_game | Toph, the First Metalbender | The Stasis Coffin +early_game | Aggravated Assault | Nature's Will +early_game | Walking Ballista | Mikaeus, the Unhallowed +early_game | Incubation Druid | Freed from the Real +early_game | Springheart Nantuko | Nissa, Who Shakes the World +early_game | Kudo, King Among Bears | Elesh Norn, Grand Cenobite +early_game | Anti-Venom, Horrifying Healer | With Great Power . . . +early_game | Animar, Soul of Elements | Hullbreaker Horror +early_game | Basking Broodscale | Cathars' Crusade +early_game | Najeela, the Blade-Blossom | Derevi, Empyrial Tactician +early_game | Bloodletter of Aclazotz | Blood Tribute +early_game | Painter's Servant | Grindstone +early_game | Power Artifact | Basalt Monolith +early_game | Bruvac the Grandiloquent | Singularity Rupture +early_game | Hermit Druid | Thassa's Oracle +early_game | Kiki-Jiki, Mirror Breaker | Delina, Wild Mage +early_game | Pyromancer's Goggles | Return the Favor +early_game | Zirda, the Dawnwaker | Basalt Monolith +early_game | Chandra's Incinerator | Repercussion +early_game | Tainted Pact | Laboratory Maniac +early_game | Chulane, Teller of Tales | Intruder Alarm +early_game | Staff of Domination | Metalworker +early_game | All Will Be One | The Red Terror +early_game | Maha, Its Feathers Night | Kaervek, the Spiteful +early_game | Basalt Monolith | Mesmeric Orb +early_game | Pili-Pala | Grand Architect +early_game | Power Artifact | Grim Monolith +early_game | Essence Flux | Dualcaster Mage +early_game | Ob Nixilis, Captive Kingpin | All Will Be One +early_game | Guilty Conscience | Phyrexian Vindicator +early_game | Sporemound | Life and Limb +early_game | Faeburrow Elder | Freed from the Real +early_game | Port Razer | Helm of the Host +early_game | Leonin Relic-Warder | Animate Dead +early_game | Peregrine Drake | Emiel the Blessed +early_game | Demonic Consultation | Jace, Wielder of Mysteries +early_game | Heartless Hidetsugu | Twinflame Tyrant +early_game | Sanctum Weaver | Freed from the Real +early_game | Phyrexian Metamorph | Felidar Guardian +early_game | Necromancy | Worldgorger Dragon +early_game | Sedgemoor Witch | Chain of Smog +early_game | Scurry Oak | Cathars' Crusade +early_game | Selvala, Heart of the Wilds | Freed from the Real +early_game | Fathom Mage | Wizard Class +early_game | Grim Monolith | Nyxbloom Ancient +early_game | Rosie Cotton of South Lane | Herd Baloth +early_game | Acererak the Archlich | Rooftop Storm +early_game | Maha, Its Feathers Night | Night of Souls' Betrayal +early_game | Tree of Perdition | Bloodletter of Aclazotz +early_game | Glint-Horn Buccaneer | Tandem Lookout +early_game | Exquisite Blood | Epicure of Blood +early_game | Wanderwine Prophets | Deeproot Pilgrimage +early_game | Marrow-Gnawer | Thornbite Staff +early_game | Kami of Whispered Hopes | Freed from the Real +early_game | Leveler | Thassa's Oracle +early_game | Umbral Mantle | Wirewood Channeler +early_game | Najeela, the Blade-Blossom | Faeburrow Elder +early_game | Glint-Horn Buccaneer | Ophidian Eye +early_game | Narset, Parter of Veils | Teferi's Puzzle Box +early_game | Abdel Adrian, Gorion's Ward | Dance of the Dead +early_game | Bloodthirsty Conqueror | Cliffhaven Vampire +early_game | Kitsa, Otterball Elite | Dramatic Reversal +early_game | Secret Arcade // Dusty Parlor | Gremlin Tamer +early_game | Kodama of the East Tree | Meloku the Clouded Mirror +early_game | Zaxara, the Exemplary | Freed from the Real +early_game | Eldrazi Displacer | Brood Monitor +early_game | Staff of Domination | Karametra's Acolyte +early_game | Incubation Druid | Pemmin's Aura +early_game | Birgi, God of Storytelling | Grinning Ignus +early_game | Maralen of the Mornsong | Opposition Agent +early_game | Riverchurn Monument | Terisian Mindbreaker +early_game | Stasis | Smothering Tithe +early_game | Delina, Wild Mage | Port Razer +early_game | Leveler | Laboratory Maniac +early_game | Unstoppable Slasher | Wound Reflection +early_game | Sliver Queen | Basal Sliver +early_game | All Will Be One | Everlasting Torment +early_game | Murderous Redcap | Gev, Scaled Scorch +early_game | Lion's Eye Diamond | Auriok Salvagers +early_game | Tayam, Luminous Enigma | Devoted Druid +early_game | Ephemerate | Dualcaster Mage +early_game | Officious Interrogation | Mechanized Production +early_game | Breath of Fury | Loyal Apprentice +early_game | Shalai and Hallar | The Red Terror +early_game | Grievous Wound | Wound Reflection +early_game | Illusionist's Bracers | Aphetto Alchemist +early_game | Sharuum the Hegemon | Phyrexian Metamorph +early_game | Tainted Pact | Jace, Wielder of Mysteries +early_game | Earthcraft | Squirrel Nest +early_game | Ad Nauseam | Teferi's Protection +early_game | Peregrine Drake | Eldrazi Displacer +early_game | Peregrine Drake | Lilysplash Mentor +early_game | Staff of Domination | Kami of Whispered Hopes +early_game | Hermit Druid | Laboratory Maniac +early_game | Fortune Teller's Talent | Sensei's Divining Top +early_game | Najeela, the Blade-Blossom | Druids' Repository +early_game | Basking Broodscale | Mazirek, Kraul Death Priest +early_game | Body of Knowledge | Niv-Mizzet, Parun +early_game | Dance of the Dead | Worldgorger Dragon +early_game | Mikaeus, the Unhallowed | Devoted Druid +early_game | Staff of Domination | Gyre Sage +early_game | Emrakul's Hatcher | Eldrazi Displacer +early_game | Thopter Assembly | Time Sieve +early_game | Umbral Mantle | Fanatic of Rhonas +early_game | Frenetic Efreet | Tavern Scoundrel +early_game | Sliver Queen | Mana Echoes +early_game | Intruder Alarm | Shrieking Drake +early_game | Bloodthirsty Conqueror | Vizkopa Guildmage +early_game | Triskelion | Heliod, Sun-Crowned +early_game | Kiki-Jiki, Mirror Breaker | Coercive Recruiter +early_game | Wedding Ring | Consecrated Sphinx +early_game | Mind Over Matter | The One Ring +early_game | Selvala, Heart of the Wilds | Pemmin's Aura +early_game | Bloodthirsty Conqueror | Dina, Soul Steeper +early_game | Mechanized Production | Masterful Replication +early_game | Sanctum Weaver | Pemmin's Aura +early_game | Kiki-Jiki, Mirror Breaker | Restoration Angel +early_game | Frenetic Efreet | Chance Encounter +early_game | Essence Flux | Naru Meha, Master Wizard +early_game | Herd Baloth | Cathars' Crusade +early_game | Umbral Mantle | Karametra's Acolyte +early_game | Kiki-Jiki, Mirror Breaker | Port Razer +early_game | Solemnity | Nine Lives +early_game | Notion Thief | Teferi's Puzzle Box +early_game | Zaxara, the Exemplary | Pemmin's Aura +early_game | Maha, Its Feathers Night | Pestilence +early_game | Displace | Dualcaster Mage +early_game | Sheoldred, the Apocalypse | Lich's Mastery +early_game | Edgar, King of Figaro | Squee's Revenge +early_game | Leveler | Jace, Wielder of Mysteries +early_game | Terra, Magical Adept | Estrid's Invocation +early_game | Neheb, Dreadhorde Champion | Aggravated Assault +early_game | Drannith Magistrate | Knowledge Pool +early_game | Ashaya, Soul of the Wild | Argothian Elder +early_game | Body of Knowledge | Niv-Mizzet, the Firemind +early_game | Enchanted Evening | Archon of Sun's Grace +early_game | Spike Feeder | Heliod, Sun-Crowned +early_game | Heartless Hidetsugu | Fiendish Duo +early_game | Myrkul, Lord of Bones | Devoted Druid +early_game | Cloudshift | Dualcaster Mage +early_game | Siona, Captain of the Pyleas | Shielded by Faith +early_game | Goblin Sharpshooter | Gorgon's Head +early_game | Kami of Whispered Hopes | Pemmin's Aura +early_game | Gilraen, Dúnedain Protector | Village Bell-Ringer +early_game | Storm-Kiln Artist | Chain of Smog +early_game | Lavinia, Azorius Renegade | Knowledge Pool +early_game | Tyvar, the Pummeler | Devoted Druid +early_game | Dualcaster Mage | Rite of Replication +early_game | Rousing Refrain | Rift Elemental +early_game | Bristly Bill, Spine Sower | Devoted Druid +early_game | Terra, Magical Adept | The Apprentice's Folly +early_game | Overkill | Jaws of Defeat +early_game | Umbral Mantle | Kami of Whispered Hopes +early_game | Najeela, the Blade-Blossom | Grim Hireling +early_game | Sword of the Paruns | Priest of Titania +early_game | Staff of Domination | Howlsquad Heavy +early_game | Kiki-Jiki, Mirror Breaker | Fear of Missing Out +early_game | Glasspool Mimic | Felidar Guardian +early_game | Phenax, God of Deception | Eater of the Dead +early_game | Bloodthirsty Conqueror | Epicure of Blood +early_game | Pyromancer's Goggles | Flare of Duplication +early_game | Brallin, Skyshark Rider | Curiosity +early_game | Pramikon, Sky Rampart | Spark Double +early_game | Devoted Druid | Vizier of Remedies +early_game | Dramatic Reversal | Lithoform Engine +early_game | Leonin Relic-Warder | Necromancy +early_game | Najeela, the Blade-Blossom | Nature's Will +early_game | Splinter Twin | Zealous Conscripts +early_game | Faeburrow Elder | Pemmin's Aura +early_game | Bloodletter of Aclazotz | Revival // Revenge +early_game | Ondu Spiritdancer | Enchanted Evening +early_game | Hermit Druid | Jace, Wielder of Mysteries +early_game | Bloodletter of Aclazotz | Quietus Spike +early_game | Fury Storm | Archmage Emeritus +early_game | Shalai and Hallar | Heliod, Sun-Crowned +early_game | Underworld Breach | Path of the Pyromancer +early_game | Unctus, Grand Metatect | Freed from the Real +early_game | Leonin Relic-Warder | Dance of the Dead +early_game | Spike Feeder | Archangel of Thune +early_game | Magmakin Artillerist | Curiosity +early_game | Combat Celebrant | Splinter Twin +early_game | Sage of Hours | Ezuri, Claw of Progress +early_game | Combat Celebrant | Mirage Phalanx +early_game | Murderous Redcap | First Day of Class +early_game | Dualcaster Mage | Devastating Onslaught +early_game | Tainted Sigil | Aetherflux Reservoir +early_game | Sword of the Paruns | Marwyn, the Nurturer +early_game | Seeker of Skybreak | Illusionist's Bracers +early_game | Queza, Augur of Agonies | Lich's Mastery +early_game | Guilty Conscience | Brash Taunter +early_game | Goblin Welder | Thornbite Staff +early_game | Enchanted Evening | Aura Thief +early_game | Cryptcaller Chariot | Kindred Discovery +early_game | Unctus, Grand Metatect | Aphetto Alchemist +early_game | Murderous Redcap | Metallic Mimic +early_game | Aluren | Cloudstone Curio +early_game | Spike Feeder | Cleric Class +early_game | Breath of Fury | Legion Warboss +early_game | Stuffy Doll | With Great Power . . . +early_game | The Locust God | Kindred Discovery +early_game | Tree of Perdition | Soul Immolation +early_game | Helm of Obedience | Rest in Peace +early_game | Zirda, the Dawnwaker | Grim Monolith +early_game | Aluren | Shrieking Drake +early_game | Reverberate | Dual Strike +early_game | Hellkite Charger | Bear Umbra +early_game | Thassa's Oracle | Thought Lash +early_game | Body of Research | Simic Ascendancy +early_game | Arixmethes, Slumbering Isle | Freed from the Real +early_game | Fraying Omnipotence | Wound Reflection +early_game | The Jolly Balloon Man | Coercive Recruiter +early_game | Teferi, Time Raveler | Knowledge Pool +early_game | Umbral Mantle | Howlsquad Heavy +early_game | Satya, Aetherflux Genius | Port Razer +early_game | Umbral Mantle | Gyre Sage +early_game | Marina Vendrell's Grimoire | Queza, Augur of Agonies +early_game | Replication Technique | Doubling Season +early_game | Metalworker | Voltaic Construct +early_game | Blazing Sunsteel | Wrathful Raptors +early_game | Sword of the Paruns | Selvala, Heart of the Wilds +early_game | Staff of Domination | Faeburrow Elder +early_game | Gogo, Master of Mimicry | Unstoppable Plan +early_game | Bloodletter of Aclazotz | Fraying Omnipotence +early_game | Archon of Emeria | Knowledge Pool +early_game | Vigean Graftmage | Incubation Druid +early_game | Blur | Naru Meha, Master Wizard +early_game | Murderous Redcap | Grumgully, the Generous +early_game | Bruvac the Grandiloquent | Kitsune's Technique +early_game | Alania, Divergent Storm | Reverberate +early_game | Sword of the Paruns | Circle of Dreams Druid +early_game | Fear of Missing Out | Helm of the Host +early_game | Replication Technique | Parallel Lives +early_game | Energy Field | Rest in Peace +early_game | Tarrian's Soulcleaver | Basking Broodscale +early_game | Peer into the Abyss | Psychic Corrosion +early_game | Benthic Biomancer | Wizard Class +early_game | Rionya, Fire Dancer | Port Razer +early_game | Scurry Oak | Coat of Arms +early_game | Mornsong Aria | Opposition Agent +early_game | Kiki-Jiki, Mirror Breaker | Hyrax Tower Scout +early_game | Drafna, Founder of Lat-Nam | The One Ring +early_game | Laboratory Maniac | Thought Lash +early_game | Dualcaster Mage | Three Steps Ahead +early_game | Dualcaster Mage | Irenicus's Vile Duplication +early_game | Freed from the Real | Gyre Engineer +early_game | Food Chain | Prossh, Skyraider of Kher +early_game | Palinchron | High Tide +early_game | Bristly Bill, Spine Sower | Crystalline Crawler +early_game | Basalt Monolith | Mana Reflection +early_game | Devoted Druid | Luxior, Giada's Gift +early_game | Bloodletter of Aclazotz | Scourge of the Skyclaves +early_game | Paradigm Shift | Thassa's Oracle +early_game | Knowledge Pool | Rule of Law +early_game | Kiki-Jiki, Mirror Breaker | Breath of Fury +early_game | Midnight Guard | Presence of Gond +early_game | Jarad, Golgari Lich Lord | Wall of Blood +early_game | River Song | Timestream Navigator +early_game | Sakashima of a Thousand Faces | Felidar Guardian +early_game | Alesha, Who Smiles at Death | Master of Cruelties +early_game | Illusionist's Stratagem | Naru Meha, Master Wizard +early_game | Breath of Fury | Rionya, Fire Dancer +early_game | Blur | Dualcaster Mage +early_game | Staff of Domination | Sanctum Weaver +early_game | Sanctum Weaver | Gauntlets of Light +early_game | Murderous Redcap | Rhythm of the Wild +early_game | Palinchron | Panharmonicon +early_game | Aphelia, Viper Whisperer | Wound Reflection +early_game | Breath of Fury | Helm of the Host +early_game | Umbral Mantle | Viridian Joiner +early_game | Breath of Fury | Urabrask's Forge +early_game | Aetheric Amplifier | Teferi, Master of Time +early_game | Ashaya, Soul of the Wild | Ley Weaver +early_game | Famished Paladin | Resplendent Mentor +early_game | Fiendlash | Ill-Tempered Loner +early_game | Virtus the Veiled | Wound Reflection +early_game | Najeela, the Blade-Blossom | Bear Umbra +early_game | All Will Be One | War Elemental +early_game | Bloodletter of Aclazotz | Virtus the Veiled +early_game | Shalai and Hallar | War Elemental +early_game | Éomer, Marshal of Rohan | Blade of Selves +early_game | Jace, Wielder of Mysteries | Thought Lash +early_game | Najeela, the Blade-Blossom | Sword of Feast and Famine +early_game | Lavinia, Azorius Renegade | Omen Machine +early_game | Calamity, Galloping Inferno | Port Razer +early_game | Sharuum the Hegemon | Hashaton, Scarab's Fist +early_game | Dualcaster Mage | Cackling Counterpart +early_game | Breath of Fury | Goblin Rabblemaster +early_game | Fury Storm | Ral, Storm Conduit +early_game | Fury Storm | Sedgemoor Witch +early_game | Sword of the Paruns | Wirewood Channeler +early_game | Uba Mask | Drannith Magistrate +early_game | Caduceus, Staff of Hermes | Pariah's Shield +early_game | Deafening Silence | Knowledge Pool +early_game | Intruder Alarm | Imperious Perfect +early_game | Kiki-Jiki, Mirror Breaker | Deceiver Exarch +early_game | Saheeli Rai | Felidar Guardian +early_game | Kami of Whispered Hopes | Vigean Graftmage +early_game | Helm of Obedience | Dauthi Voidwalker +early_game | Terra, Magical Adept | Spark Double +early_game | Vorel of the Hull Clade | Magistrate's Scepter +early_game | Turntimber Ranger | Maskwood Nexus +early_game | Basking Broodscale | Blade of the Bloodchief +early_game | Arixmethes, Slumbering Isle | Pemmin's Aura +early_game | Splinter Twin | Village Bell-Ringer +early_game | Transcendence | Fractured Identity +early_game | Riverchurn Monument | Kitsune's Technique +early_game | Unstoppable Slasher | Astarion, the Decadent +early_game | Kiki-Jiki, Mirror Breaker | Pestermite +early_game | Paradigm Shift | Laboratory Maniac +early_game | Badgermole Cub | Freed from the Real +early_game | Redshift, Rocketeer Chief | Umbral Mantle +early_game | Fable of the Mirror-Breaker | Village Bell-Ringer +early_game | Helm of Obedience | Leyline of the Void +early_game | Mind Over Matter | Temple Bell +early_game | Goro-Goro and Satoru | Breath of Fury +early_game | Exquisite Blood | South Wind Avatar +early_game | Planar Incision | Dualcaster Mage +early_game | Ad Nauseam | Phyrexian Unlife +early_game | Glacial Chasm | Solemnity +early_game | Tree of Perdition | Astarion, the Decadent +early_game | Goblin Sharpshooter | Gorgon Flail +early_game | Rune-Tail, Kitsune Ascendant | Pariah +early_game | Caesar, Legion's Emperor | Breath of Fury +early_game | Delaying Shield | Solemnity +early_game | Omen Machine | Drannith Magistrate +early_game | Unstoppable Plan | Strionic Resonator +early_game | Ouroboroid | Sage of Hours +early_game | Ghired, Mirror of the Wilds | Midnight Guard +early_game | Terra, Magical Adept | Mirrormade +early_game | Dualcaster Mage | Quasiduplicate +early_game | Exalted Flamer of Tzeentch | Time Warp +early_game | Aphelia, Viper Whisperer | Bloodletter of Aclazotz +early_game | Wick, the Whorled Mind | Conspiracy +early_game | Divining Witch | Thassa's Oracle +early_game | Pemmin's Aura | Gyre Engineer +early_game | Ghired, Mirror of the Wilds | Village Bell-Ringer +early_game | Brallin, Skyshark Rider | Ophidian Eye +early_game | Isengard Unleashed | Heartless Hidetsugu +early_game | Zethi, Arcane Blademaster | Teferi's Protection +early_game | Murderous Redcap | Uncivil Unrest +early_game | Teferi, Temporal Archmage | Lithoform Engine +early_game | Mana Reflection | Pemmin's Aura +early_game | Astarion, the Decadent | Quietus Spike +early_game | Naru Meha, Master Wizard | Twinflame +early_game | Sliver Queen | Ashnod's Altar +early_game | Stasis | Unstoppable Plan +early_game | Archmage Emeritus | Chain of Smog +early_game | Knowledge Pool | Eidolon of Rhetoric +early_game | Kiki-Jiki, Mirror Breaker | Spark Double +early_game | Haldir, Lórien Lieutenant | Devoted Druid +early_game | Flicker | Dualcaster Mage +early_game | Soulfire Grand Master | Jeska's Will +early_game | Piper Wright, Publick Reporter | Time Sieve +early_game | Ephemerate | Naru Meha, Master Wizard +early_game | Brallin, Skyshark Rider | Tandem Lookout +early_game | Web of Inertia | Rest in Peace +early_game | Soulless Jailer | Knowledge Pool +early_game | Twitching Doll | Freed from the Real +early_game | Enchanted Evening | Ghostly Dancers +early_game | Teferi, Mage of Zhalfir | Knowledge Pool +early_game | Terra, Magical Adept | Copy Enchantment +early_game | Kederekt Leviathan | Animate Dead +early_game | Shredder, Shadow Master | Bloodletter of Aclazotz +early_game | Sword of the Paruns | Karametra's Acolyte +early_game | Deathbringer Thoctar | Basilisk Collar +early_game | Bloodthirsty Conqueror | South Wind Avatar +early_game | Unstoppable Plan | Lithoform Engine +early_game | Maester Seymour | Sage of Hours +early_game | Avatar Aang | Searing Touch +early_game | Vexing Bauble | Knowledge Pool +early_game | Glint-Horn Buccaneer | Keen Sense +early_game | Breath of Fury | Lagomos, Hand of Hatred +early_game | Goblin Sharpshooter | Quietus Spike +early_game | Kiki-Jiki, Mirror Breaker | Corridor Monitor +early_game | Ad Nauseam | Platinum Angel +early_game | Kiki-Jiki, Mirror Breaker | Worldgorger Dragon +early_game | Redshift, Rocketeer Chief | Aggravated Assault +early_game | Long Feng, Grand Secretariat | Basking Broodscale +early_game | Port Razer | Splinter Twin +early_game | Paradigm Shift | Jace, Wielder of Mysteries +early_game | Doomsday Excruciator | Phenax, God of Deception +early_game | Argothian Elder | Maze of Ith +early_game | Teferi, Who Slows the Sunset | The Peregrine Dynamo +early_game | Wirewood Symbiote | Maskwood Nexus +early_game | Goblin Sharpshooter | Splinter Twin +early_game | Delaying Shield | Phyrexian Unlife +early_game | Screams from Within | Warehouse Tabby +early_game | Clone | Felidar Guardian +early_game | Port Razer | Mirage Phalanx +early_game | Staff of Domination | Arbor Adherent +early_game | Teferi, Time Raveler | Omen Machine +early_game | Marina Vendrell's Grimoire | Sheoldred, the Apocalypse +early_game | Spike Feeder | Light of Promise +early_game | Intruder Alarm | Presence of Gond +early_game | Lyla, Holographic Assistant | Fathom Mage +early_game | Wedding Ring | Psychic Possession +early_game | Krosan Restorer | Ashaya, Soul of the Wild +early_game | Port Razer | Brago, King Eternal +early_game | Enchanted Evening | Opalescence +early_game | Parallax Wave | Felidar Guardian +early_game | Secret Arcade // Dusty Parlor | Ajani's Chosen +early_game | Boromir, Warden of the Tower | Knowledge Pool +early_game | Mycosynth Lattice | Anzrag's Rampage +early_game | Staff of Domination | Heronblade Elite +early_game | Dina, Essence Brewer | Jumbo Cactuar +early_game | The Watcher in the Water | Kindred Discovery +early_game | Rionya, Fire Dancer | Godo, Bandit Warlord +early_game | Enchanted Evening | Ajani's Chosen +early_game | Shredder, Shadow Master | Wound Reflection +early_game | Marina Vendrell's Grimoire | Shabraz, the Skyshark +early_game | Llawan, Cephalid Empress | Painter's Servant +early_game | Divining Witch | Laboratory Maniac +early_game | Redshift, Rocketeer Chief | Sword of the Paruns +early_game | Loyal Retainers | Saffi Eriksdotter +early_game | Dualcaster Mage | Kindle the Inner Flame +early_game | Opalescence | Parallax Wave +early_game | Magmakin Artillerist | Ophidian Eye +early_game | Heartless Hidetsugu | Grafted Exoskeleton +early_game | Near-Death Experience | Wall of Blood +early_game | Kiki-Jiki, Mirror Breaker | Auton Soldier +early_game | Blazing Sunsteel | Barbed Servitor +early_game | Illusionist's Stratagem | Dualcaster Mage +early_game | Badgermole Cub | Pemmin's Aura +early_game | Timestream Navigator | Helm of the Host +early_game | Brago, King Eternal | Peter Parker's Camera +early_game | Splinter Twin | Coercive Recruiter +early_game | Enduring Renewal | Ashnod's Altar +early_game | Alpharael, Stonechosen | Bloodletter of Aclazotz +early_game | Intruder Alarm | Dream Stalker +early_game | Medomai the Ageless | Satoru Umezawa +early_game | Saheeli, the Sun's Brilliance | Combat Celebrant +early_game | Aurelia, the Warleader | Rionya, Fire Dancer +early_game | Ad Nauseam | Flare of Fortitude +early_game | Goblin Sharpshooter | Maha, Its Feathers Night +early_game | Terrasymbiosis | Body of Research +early_game | Protean Thaumaturge | Ondu Spiritdancer +early_game | Duke Ulder Ravengard | Éomer, Marshal of Rohan +early_game | Intruder Alarm | Kiki-Jiki, Mirror Breaker +early_game | Panoptic Mirror | Time Warp +early_game | Basking Broodscale | Sadistic Glee +early_game | Alena, Kessig Trapper | Aggravated Assault +early_game | Staff of Domination | Brigid, Clachan's Heart +early_game | Mind Over Matter | Kwain, Itinerant Meddler +early_game | Azor, the Lawbringer | Soulherder +early_game | Alania, Divergent Storm | Twincast +early_game | Guilty Conscience | Donna Noble +early_game | Teysa, Orzhov Scion | Painter's Servant +early_game | Soulless Jailer | Omen Machine +early_game | Splinter Twin | Deceiver Exarch +early_game | The Reaver Cleaver | Time Sieve +early_game | Possibility Storm | Drannith Magistrate +early_game | Duke Ulder Ravengard | Port Razer +early_game | Flicker of Fate | Dualcaster Mage +early_game | Umbral Mantle | Heronblade Elite +early_game | Jorn, God of Winter | Stasis +early_game | Bloodletter of Aclazotz | Scytheclaw +early_game | Kiki-Jiki, Mirror Breaker | Irenicus's Vile Duplication +early_game | Saheeli, the Sun's Brilliance | Intruder Alarm +early_game | Omen Hawker | Pemmin's Aura +early_game | Vexing Bauble | Possibility Storm +early_game | Ley Weaver | Maze of Ith +early_game | All Will Be One | Quest for Pure Flame +early_game | Time Sieve | Inquisitor Eisenhorn +early_game | Splinter Twin | Pestermite +early_game | Molten Echoes | Changeling Berserker +early_game | Umbral Mantle | Metalworker +early_game | Nath of the Gilt-Leaf | Sadistic Hypnotist +early_game | Worldgorger Dragon | Molten Echoes +early_game | Heartless Hidetsugu | Curse of Bloodletting +early_game | Enchanted Evening | Gremlin Tamer +early_game | Sword of the Paruns | Kami of Whispered Hopes +early_game | Elite Arcanist | Dramatic Reversal +early_game | Living Plane | Elesh Norn, Grand Cenobite +early_game | Teferi's Protection | Spellbinder +early_game | Niv-Mizzet, Parun | Keen Sense +early_game | The One Ring | Meticulous Excavation +early_game | Twitching Doll | Pemmin's Aura +early_game | Undercover Operative | Felidar Guardian +early_game | Ancestral Statue | Rakdos, Lord of Riots +early_game | Bruce Banner | Caltrops +early_game | Charismatic Conqueror | Silverquill Lecturer +early_game | Vexing Bauble | Omen Machine +early_game | Sneak Attack | Palinchron +early_game | Cephalid Illusionist | Nomads en-Kor +early_game | Sword of the Paruns | Bloom Tender +early_game | Mirror of Fate | Thassa's Oracle +early_game | Exalted Flamer of Tzeentch | Temporal Manipulation +early_game | Casey Jones, Back Alley Brute | Ob Nixilis, Captive Kingpin +early_game | Umbral Mantle | Cradle Clearcutter +early_game | Freed from the Real | Krosan Restorer +early_game | Goblin Welder | Sewer-veillance Cam +early_game | Sandstorm Crasher | Combat Celebrant +early_game | Arcane Laboratory | Knowledge Pool +early_game | March of the Machines | Mycosynth Lattice +early_game | Umbral Mantle | Sanctum Weaver +early_game | Leveler | Fractured Identity +early_game | Breath of Fury | Daring Piracy +early_game | Scrollshift | Dualcaster Mage +early_game | Magus of the Coffers | Staff of Domination +early_game | Jace, Cunning Castaway | Doubling Season +early_game | Basking Broodscale | Ghost Lantern +early_game | Lonis, Genetics Expert | Extruder +early_game | Biovisionary | Augmenter Pugilist +early_game | Vigor | Pariah's Shield +early_game | Transcendence | Angel's Grace +early_game | Naru Meha, Master Wizard | Irenicus's Vile Duplication +early_game | Momentary Blink | Dualcaster Mage +early_game | Najeela, the Blade-Blossom | The Reaver Cleaver +early_game | Lyla, Holographic Assistant | Benthic Biomancer +early_game | Dualcaster Mage | Quantum Misalignment +early_game | Breath of Fury | Siege-Gang Lieutenant +early_game | Naru Meha, Master Wizard | Saw in Half +early_game | Vigean Graftmage | Bloom Tender +early_game | Panoptic Mirror | Temporal Manipulation +early_game | Heartless Hidetsugu | Tainted Strike +early_game | Saheeli, the Sun's Brilliance | Timestream Navigator +early_game | Aggravated Assault | Sylvan Awakening +early_game | Replication Technique | Anointed Procession +early_game | Food Chain | Aeve, Progenitor Ooze +early_game | Kederekt Leviathan | Necromancy +early_game | Freed from the Real | Ley Weaver +early_game | Freed from the Real | Argothian Elder +early_game | Dawnsire, Sunstar Dreadnought | Mogg Maniac +early_game | Enduring Renewal | Phyrexian Altar +early_game | Shaun, Father of Synths | Aurelia, the Warleader +early_game | Ral, Storm Conduit | Chain of Smog +early_game | Enchanted Evening | Calming Verse +early_game | Spellbinder | Savage Beating +early_game | Crackdown Construct | Puresteel Paladin +early_game | Lonis, Genetics Expert | Yotian Dissident +early_game | The Archimandrite | Beacon of Immortality +early_game | Intruder Alarm | Krenko, Mob Boss +early_game | Axebane Guardian | Freed from the Real +early_game | Sharuum the Hegemon | Machine God's Effigy +early_game | Acrobatic Maneuver | Dualcaster Mage +early_game | Emiel the Blessed | Brood Monitor +early_game | Lonis, Genetics Expert | Rosie Cotton of South Lane +early_game | Old Gnawbone | Time Sieve +early_game | Iname, Death Aspect | Mortal Combat +early_game | Sword of the Paruns | Gyre Sage +early_game | Kiki-Jiki, Mirror Breaker | Fatestitcher +early_game | All Will Be One | Soul-Scar Mage +early_game | Near-Death Experience | Necropotence +early_game | Aluren | Fleetfoot Panther +early_game | Assault Suit | Bronze Bombshell +early_game | Heartless Hidetsugu | Phyresis +early_game | Fear of Missing Out | Splinter Twin +early_game | Acererak the Archlich | Aluren +early_game | Ghired, Mirror of the Wilds | Sunstrike Legionnaire +early_game | Maze of Ith | Krosan Restorer +early_game | Basking Broodscale | Necrosynthesis +early_game | Vhal, Candlekeep Researcher | Staff of Domination +early_game | Breath of Fury | Splinter Twin +early_game | Chrome Dome | Metalworker +early_game | Timestream Navigator | Extravagant Replication +early_game | Donatello, the Brains | Basking Broodscale +early_game | Merieke Ri Berit | Intruder Alarm +early_game | Jace, Wielder of Mysteries | Mirror of Fate +early_game | Sage of the Maze | Freed from the Real +early_game | Vigean Graftmage | Faeburrow Elder +early_game | Ancestral Statue | Sami, Wildcat Captain +early_game | Jegantha, the Wellspring | Freed from the Real +early_game | Bigger on the Inside | Staff of Domination +early_game | Screams from Within | Knight of Doves +early_game | Murderous Redcap | Cathars' Crusade +early_game | Kiki-Jiki, Mirror Breaker | Timestream Navigator +early_game | Torgaar, Famine Incarnate | Bloodletter of Aclazotz +early_game | Belisarius Cawl | Intruder Alarm +early_game | Divining Witch | Jace, Wielder of Mysteries +early_game | Selenia, Dark Angel | Near-Death Experience +early_game | Pemmin's Aura | Argothian Elder +early_game | Ivy Lane Denizen | Aerie Ouphes +early_game | Pemmin's Aura | Ley Weaver +early_game | Pili-Pala | Careful Cultivation +early_game | Eloise, Nephalia Sleuth | March of the Machines +early_game | Grim Monolith | Mana Reflection +early_game | Arcane Adaptation | Turntimber Ranger +early_game | Marvin, Murderous Mimic | Splinter Twin +early_game | Naru Meha, Master Wizard | Molten Duplication +early_game | Panoptic Mirror | Capture of Jingzhou +early_game | Drannith Magistrate | Urabrask, Heretic Praetor +early_game | Zur's Weirding | Bloodchief Ascension +early_game | Sasaya, Orochi Ascendant | Wakeroot Elemental +early_game | Naru Meha, Master Wizard | Cackling Counterpart +early_game | Mycosynth Lattice | Hurkyl's Recall +early_game | Naru Meha, Master Wizard | Quasiduplicate +early_game | Dualcaster Mage | Replication Technique +early_game | Dualcaster Mage | Mythos of Illuna +early_game | Cephalid Illusionist | Shuko +early_game | Linvala, Keeper of Silence | Living Plane +early_game | Aerie Ouphes | Rhythm of the Wild +early_game | Void Mirror | Possibility Storm +early_game | Goblin Welder | Intruder Alarm +early_game | Jace, Cunning Castaway | Vorinclex, Monstrous Raider +early_game | Gogo, Master of Mimicry | Magosi, the Waterveil +early_game | Sword of the Paruns | Viridian Joiner +early_game | Myrel, Shield of Argive | Time Sieve +early_game | Kiki-Jiki, Mirror Breaker | Hazel's Brewmaster +early_game | Staff of Domination | Accomplished Alchemist +early_game | Dualcaster Mage | Relm's Sketching +early_game | Pemmin's Aura | Krosan Restorer +early_game | Staff of Domination | Alena, Kessig Trapper +early_game | Felidar Guardian | Machine God's Effigy +early_game | Pitiless Plunderer | March of the Machines +early_game | Possibility Storm | Rule of Law +early_game | Rasputin Dreamweaver | Eldrazi Displacer +early_game | Mardu Siegebreaker | Port Razer +early_game | Treasonous Ogre | Greven, Predator Captain +early_game | Patrol Signaler | Earthcraft +early_game | Near-Death Experience | Blood Celebrant +early_game | Enduring Angel | Vizkopa Guildmage +early_game | Midnight Guard | Splinter Twin +early_game | Spike Feeder | Sunbond +early_game | Goldspan Dragon | Crown of Flames +early_game | Bloom Tender | High Alert +early_game | Walking Ballista | Enduring Renewal +early_game | Exalted Flamer of Tzeentch | Capture of Jingzhou +early_game | Demonic Consultation | Timestream Navigator +early_game | Palinchron | Lilysplash Mentor +early_game | Sanctum Weaver | Crab Umbra +early_game | Possibility Storm | Archon of Emeria +early_game | Jarad, Golgari Lich Lord | Phyrexian Devourer +early_game | Casey Jones, Back Alley Brute | The Red Terror +early_game | Sharuum the Hegemon | Clever Impersonator +early_game | Balancing Act | Teferi's Protection +early_game | Deathbringer Thoctar | Gift of Doom +early_game | Visara the Dreadful | Thornbite Staff +early_game | Tidewater Minion | Illusionist's Bracers +early_game | Eirdu, Carrier of Dawn | Triskelion +early_game | Mycosynth Lattice | Collector Ouphe +early_game | Void Mirror | Knowledge Pool +early_game | Toph, the First Metalbender | Caged Sun +early_game | Sage of the Maze | Pemmin's Aura +early_game | Linvala, Keeper of Silence | Nature's Revolt +early_game | Deafening Silence | Possibility Storm +early_game | Chain Stasis | Bloom Tender +early_game | Mycosynth Golem | Ancestral Statue +early_game | Molten Echoes | Felidar Guardian +early_game | Walking Ballista | The Destined White Mage +early_game | Eidolon of Rhetoric | Possibility Storm +early_game | Boromir, Warden of the Tower | Possibility Storm +early_game | Another Round | Dualcaster Mage +early_game | Felidar Guardian | Flameshadow Conjuring +early_game | Mana Severance | Goblin Charbelcher +early_game | Necrotic Ooze | Kiki-Jiki, Mirror Breaker +early_game | Beifong's Bounty Hunters | Pawn of Ulamog +early_game | Bootleggers' Stash | Time Sieve +early_game | Splinter Twin | Hyrax Tower Scout +early_game | Kiki-Jiki, Mirror Breaker | Quantum Misalignment +early_game | Naru Meha, Master Wizard | Heat Shimmer +early_game | Faeburrow Elder | High Alert +early_game | Marrow-Gnawer | Intruder Alarm +early_game | Sedraxis Alchemist | Rooftop Storm +early_game | Aggravated Assault | Kamahl's Will +early_game | Murderous Redcap | The Great Henge +early_game | Kiki-Jiki, Mirror Breaker | Vizier of Tumbling Sands +early_game | Flicker of Fate | Naru Meha, Master Wizard +early_game | The Twelfth Doctor | Increasing Vengeance +early_game | Kiki-Jiki, Mirror Breaker | Kiora's Follower +early_game | Orthion, Hero of Lavabrink | Timestream Navigator +early_game | Teferi's Protection | Apocalypse +early_game | Chain Stasis | Faeburrow Elder +early_game | Splinter Twin | Intruder Alarm +early_game | Aurelia, the Warleader | The Neutrinos +early_game | Heidar, Rimewind Master | Stasis +early_game | Phyrexian Devourer | Thassa's Oracle +early_game | Blitzwing, Cruel Tormentor | Fraying Omnipotence +early_game | Young Necromancer | Altar of Dementia +early_game | Auton Soldier | Felidar Guardian +early_game | Shrieking Drake | Oltec Matterweaver +early_game | Dualcaster Mage | Saheeli's Artistry +early_game | Molten Echoes | Wanderwine Prophets +early_game | Naru Meha, Master Wizard | Electroduplicate +early_game | Unctus, Grand Metatect | Tidewater Minion +early_game | Mardu Siegebreaker | Felidar Guardian +early_game | Bruce Banner | Legolas's Quick Reflexes +early_game | Niv-Mizzet, the Firemind | Keen Sense +early_game | Double Major | Vadrok, Apex of Thunder +early_game | Umbral Mantle | Alena, Kessig Trapper +early_game | Molten Echoes | Lightning Crafter +early_game | Boros Reckoner | Take Up the Shield +early_game | Soulless Jailer | Possibility Storm +early_game | Mystic Barrier | Mirrormade +early_game | Kiki-Jiki, Mirror Breaker | Great Oak Guardian +early_game | Biovisionary | Mirrorform +early_game | Urban Daggertooth | Walking Ballista +early_game | Kederekt Leviathan | Dance of the Dead +early_game | Marneus Calgar | The Watcher in the Water +early_game | Intruder Alarm | Torpor Orb +early_game | Biovisionary | March from Velis Vel +early_game | Palinchron | Gauntlet of Power +early_game | Sharuum the Hegemon | Copy Artifact +early_game | Alania, Divergent Storm | Fork +early_game | Emiel the Blessed | Workhorse +early_game | Kiki-Jiki, Mirror Breaker | Sparring Mummy +early_game | Release to the Wind | Naru Meha, Master Wizard +early_game | Saheeli, Radiant Creator | Saheeli Rai +early_game | Celestial Convergence | Solemnity +early_game | Null Rod | Mycosynth Lattice +early_game | Transcendence | Cloudsteel Kirin +early_game | Pili-Pala | Bigger on the Inside +early_game | Vedalken Mastermind | Stasis +early_game | Lavinia, Azorius Renegade | Possibility Storm +early_game | Hapatra, Vizier of Poisons | Host of the Hereafter +early_game | Release to the Wind | Dualcaster Mage +early_game | Brallin, Skyshark Rider | Keen Sense +early_game | Mardu Siegebreaker | Éomer, Marshal of Rohan +early_game | Slip On the Ring | Dualcaster Mage +early_game | Astarion, the Decadent | Virtus the Veiled +early_game | Maralen of the Mornsong | Stranglehold +early_game | Imodane, the Pyrohammer | Fire Covenant +early_game | Forsaken City | Stasis +early_game | Timestream Navigator | The Temporal Anchor +early_game | Teferi, Time Raveler | Possibility Storm +early_game | Vadrok, Apex of Thunder | Chef's Kiss +early_game | Seedcradle Witch | Selvala, Heart of the Wilds +early_game | Axebane Guardian | Pemmin's Aura +early_game | Sword of the Paruns | Arbor Adherent +early_game | Vigean Graftmage | Krosan Restorer +early_game | Mystic Barrier | Estrid's Invocation +early_game | Aluren | Cavern Harpy +early_game | Tooth and Claw | Parallel Lives +early_game | Mycosynth Lattice | Broadcast Takeover +early_game | Wrath of Marit Lage | Painter's Servant +early_game | Charmbreaker Devils | Time Warp +early_game | Shilgengar, Sire of Famine | Stridehangar Automaton +early_game | Dualcaster Mage | Mirage Mockery +early_game | Laboratory Maniac | Phyrexian Devourer +early_game | Omen Machine | Void Mirror +early_game | Hexavus | Devoted Druid +early_game | Transcendence | Gideon of the Trials +early_game | Sheoldred, the Apocalypse | Lich +early_game | Emrakul's Hatcher | Emiel the Blessed +early_game | Xerex Strobe-Knight | Intruder Alarm +early_game | Insight Engine | Mind Over Matter +early_game | Molten Echoes | Changeling Titan +early_game | Niv-Mizzet, the Firemind | Snake Umbra +early_game | Basking Broodscale | Battle of Hoover Dam +early_game | Tooth and Claw | Doubling Season +early_game | Sword of the Paruns | Bighorner Rancher +early_game | Tooth and Claw | Anointed Procession +early_game | Urban Daggertooth | Triskelion +early_game | Jon Irenicus, Shattered One | Bronze Bombshell +early_game | Ad Nauseam | Lich +early_game | Spitemare | Angelfire Ignition +early_game | Maha, Its Feathers Night | Pyrohemia +early_game | Jace, Cunning Castaway | Innkeeper's Talent +early_game | Dualcaster Mage | Fated Infatuation +early_game | Mirror-Mad Phantasm | Spark Double +early_game | Edea, Possessed Sorceress | Breath of Fury +early_game | Hell's Caretaker | Thornbite Staff +early_game | The Watcher in the Water | Sage of the Falls +early_game | Elemental Mastery | Midnight Guard +early_game | Nexus of Fate | Spellbinder +early_game | Staff of Domination | Mona Lisa, Science Geek +early_game | Fable of the Mirror-Breaker | Timestream Navigator +early_game | Sandstorm Crasher | Port Razer +early_game | Stasis | Eon Hub +early_game | Triskaidekaphile | Ad Nauseam +early_game | Kiki-Jiki, Mirror Breaker | Icewind Stalwart +early_game | Ad Nauseam | Cloudsteel Kirin +early_game | Marvin, Murderous Mimic | Grinning Ignus +early_game | Ghired, Mirror of the Wilds | Hyrax Tower Scout +early_game | Redshift, Rocketeer Chief | Freed from the Real +early_game | Naru Meha, Master Wizard | Quantum Misalignment +early_game | Ad Nauseam | Gideon of the Trials +early_game | Umbral Mantle | Mona Lisa, Science Geek +early_game | The Jolly Balloon Man | Intruder Alarm +early_game | Sunstrike Legionnaire | Splinter Twin +early_game | Greater Good | Body of Research +early_game | Consulate Crackdown | Mycosynth Lattice +early_game | Intruder Alarm | Thraben Doomsayer +early_game | Murderous Redcap | Renata, Called to the Hunt +early_game | Sheoldred, the Apocalypse | Nefarious Lich +early_game | Alpharael, Stonechosen | Astarion, the Decadent +early_game | Tooth and Claw | Mondrak, Glory Dominus +early_game | Composite Golem | Nim Deathmantle +early_game | Naru Meha, Master Wizard | Replication Technique +early_game | Kiki-Jiki, Mirror Breaker | Seeker of Skybreak +early_game | Rionya, Fire Dancer | Akki Battle Squad +early_game | Drannith Magistrate | Eye of the Storm +early_game | Breath of Fury | Rootha, Mastering the Moment +early_game | Sword of the Paruns | Alena, Kessig Trapper +early_game | The One Ring | Vedalken Mastermind +early_game | Stony Silence | Mycosynth Lattice +early_game | Naru Meha, Master Wizard | Relm's Sketching +early_game | Kiki-Jiki, Mirror Breaker | Aphetto Alchemist +early_game | Panoptic Mirror | Karn's Temporal Sundering +early_game | Kiki-Jiki, Mirror Breaker | Everquill Phoenix +early_game | Bladewing the Risen | Phyrexian Metamorph +early_game | Mikaeus, the Unhallowed | Cinderhaze Wretch +early_game | Splinter Twin | Corridor Monitor +early_game | Archetype of Imagination | Moat +early_game | Filigree Sages | Nyx Lotus +early_game | Crackdown Construct | Shuko +early_game | Mighty Mutanimals | Basking Broodscale +early_game | Mornsong Aria | Stranglehold +early_game | Sunstrike Legionnaire | Presence of Gond +early_game | Teferi, Mage of Zhalfir | Possibility Storm +# Last Voyage of the _____ has edition metadata but no card script. +# early_game | Abdel Adrian, Gorion's Ward | Last Voyage of the _____ +early_game | Tooth and Claw | Primal Vigor +early_game | All Will Be One | Talon of Pain +early_game | Staff of Domination | Deathbloom Ritualist +early_game | Filigree Sages | Timeless Lotus +early_game | Bloodline Keeper | Intruder Alarm +early_game | Sword of the Paruns | Brigid, Clachan's Heart +early_game | Sharuum the Hegemon | Glasspool Mimic +early_game | Murderous Redcap | Solemnity +early_game | Cradle Clearcutter | Voltaic Construct +early_game | Magmakin Artillerist | Keen Sense +early_game | Queza, Augur of Agonies | Nefarious Lich +early_game | Timestream Navigator | Progenitor Mimic +early_game | Magmakin Artillerist | Snake Umbra +early_game | Selvala, Eager Trailblazer | Freed from the Real +early_game | Teferi's Puzzle Box | Spirit of the Labyrinth +early_game | Brigid, Clachan's Heart | Gauntlets of Light +early_game | Kami of Whispered Hopes | Crab Umbra +early_game | Light of Day | Painter's Servant +early_game | Amalia Benavides Aguirre | Wildgrowth Walker +early_game | Night of Souls' Betrayal | Humility +early_game | Sword of the Paruns | Heronblade Elite +early_game | Chain of Smog | Witherbloom Pledgemage +early_game | Kiki-Jiki, Mirror Breaker | Kelpie Guide +early_game | Aggravated Assault | Mona Lisa, Science Geek +early_game | Jace, Wielder of Mysteries | Phyrexian Devourer +early_game | Intruder Alarm | Hushbringer +early_game | Mirror-Mad Phantasm | Mirage Mirror +early_game | Swift Reconfiguration | Barrenton Medic +early_game | Scrollshift | Naru Meha, Master Wizard +early_game | Oathkeeper, Takeno's Daisho | Ashnod's Altar +early_game | Bloodletter of Aclazotz | Ebonblade Reaper +early_game | Possibility Storm | Arcane Laboratory +early_game | Tooth and Claw | Ojer Taq, Deepest Foundation +early_game | Cornered Market | Spy Kit +early_game | Dualcaster Mage | Croaking Counterpart +early_game | Light of Day | Darkest Hour +early_game | Conspiracy | Turntimber Ranger +early_game | Panoptic Mirror | Walk the Aeons +early_game | Sword of the Paruns | Accomplished Alchemist +early_game | Mind Over Matter | Archivist +early_game | Ghired, Mirror of the Wilds | Battered Golem +early_game | Breath of Fury | Harried Dronesmith +early_game | Lord of the Forsaken | Cut // Ribbons +early_game | Battered Golem | Splinter Twin +early_game | Oath of Druids | Jace, Wielder of Mysteries +early_game | Lethal Vapors | Pithing Needle +early_game | Island Sanctuary | Mystic Decree +early_game | Massacre Wurm | Nature's Revolt +early_game | Sword of the Paruns | Metalworker +early_game | Mighty Mutanimals | Scurry Oak +early_game | Harbinger of the Seas | Choke +early_game | Jon Irenicus, Shattered One | Phylactery Lich +early_game | Vodalian Wave-Knight | Benthic Biomancer +early_game | Kate Stewart | Soultether Golem +early_game | Kiki-Jiki, Mirror Breaker | Cloudpiercer +early_game | Casey Jones, Back Alley Brute | Heliod, Sun-Crowned +early_game | Timestream Navigator | Endless Evil +early_game | Acrobatic Maneuver | Naru Meha, Master Wizard +early_game | Hyalopterous Lemure | Jaws of Defeat +early_game | Sandstorm Crasher | Aurelia, the Warleader +# early_game | Last Voyage of the _____ | Worldgorger Dragon +early_game | Kiki-Jiki, Mirror Breaker | Gemrazer +early_game | Chain of Smog | Deekah, Fractal Theorist +early_game | Mephidross Vampire | Triskelion +early_game | Timestream Navigator | Mirrorhall Mimic +early_game | Charismatic Conqueror | Fractured Identity +early_game | Queza, Augur of Agonies | Lich +early_game | Exalted Flamer of Tzeentch | Walk the Aeons +early_game | Dual Casting | Traitorous Greed +early_game | Kiki-Jiki, Mirror Breaker | Bounding Krasis +early_game | Murderous Redcap | Master Chef +early_game | Marina Vendrell's Grimoire | Horizon Chimera +early_game | Strionic Resonator | Sands of Time +early_game | Panoptic Mirror | Part the Waterveil +early_game | Aggravated Assault | Natural Affinity +early_game | Fury Storm | Witherbloom Apprentice +early_game | Triskelion | Spider-Man, Peter Parker +early_game | Stormsplitter | Sprout Swarm +early_game | Aluren | Grinning Ignus +early_game | Jaws of Defeat | Viscid Lemures +early_game | Marrow-Gnawer | Faces of the Past +early_game | Ad Nauseam | Soul Echo +early_game | Hangarback Walker | Enduring Renewal +early_game | Wheel of Misfortune | Intervention Pact +early_game | Wirewood Symbiote | Arcane Adaptation +early_game | Ugin's Nexus | Masterful Replication +early_game | Massacre Wurm | Living Plane +early_game | Ashaya, Soul of the Wild | Realm Razer +early_game | Tooth and Claw | Elspeth, Storm Slayer +early_game | Sacred Guide | Thassa's Oracle +early_game | Jan Jansen, Chaos Crafter | Intruder Alarm +early_game | Drannith Magistrate | Shared Fate +early_game | Heartless Hidetsugu | Glistening Oil +early_game | The Watcher in the Water | Greater Good +early_game | Enduring Scalelord | Altered Ego +early_game | Saheeli, Radiant Creator | Timestream Navigator +early_game | King Macar, the Gold-Cursed | Aura of Dominion +early_game | Mindslaver | Mages' Contest +early_game | Ghired, Mirror of the Wilds | Great Oak Guardian +early_game | Goldspan Dragon | Flickering Ward +early_game | Timestream Navigator | Followed Footsteps +early_game | Drana and Linvala | Living Plane +early_game | Drana and Linvala | Nature's Revolt +early_game | Niv-Mizzet, Parun | Swans of Bryn Argoll +early_game | Splinter Twin | Dominating Vampire +early_game | Mystic Barrier | Clever Impersonator +early_game | Vampire Hexmage | Celestial Convergence +early_game | Devoted Druid | One with the Stars +early_game | Aggravated Assault | Nature's Revolt +early_game | Beifong's Bounty Hunters | Sifter of Skulls +early_game | Selvala, Heart of the Wilds | Crab Umbra +early_game | Naru Meha, Master Wizard | Mirage Mockery +early_game | Kiki-Jiki, Mirror Breaker | Breaching Hippocamp +early_game | Mirror-Mad Phantasm | Mirrorhall Mimic +early_game | Phantom Steed | Port Razer +early_game | Ethereal Absolution | Humility +early_game | Splinter Twin | Sparring Mummy +early_game | Kiki-Jiki, Mirror Breaker | Wispweaver Angel +early_game | Wispweaver Angel | Cursed Mirror +early_game | Mighty Mutanimals | Herd Baloth +early_game | Selvala, Eager Trailblazer | Pemmin's Aura +early_game | Volcano Hellion | Whip of Erebos +early_game | Intruder Alarm | Kazandu Tuskcaller +early_game | Accomplished Alchemist | Pemmin's Aura +early_game | Jon Irenicus, Shattered One | Seasinger +early_game | Blood Pet | Enduring Renewal +early_game | Wake Thrasher | Aphetto Alchemist +early_game | Pitiless Plunderer | Titania's Song +early_game | Against All Odds | Dualcaster Mage +early_game | Redshift, Rocketeer Chief | Pemmin's Aura +early_game | All Will Be One | Phyrexian Devourer +early_game | Selvala, Heart of the Wilds | Gauntlets of Light +early_game | Vigor | With Great Power . . . +early_game | Soul's Grace | Jumbo Cactuar +early_game | Xenograft | Turntimber Ranger +early_game | Kiki-Jiki, Mirror Breaker | Dreamtail Heron +early_game | Shalai and Hallar | Phyrexian Devourer +early_game | Sanctum Weaver | Thassa's Ire +early_game | Mind Over Matter | Idol of Oblivion +early_game | Satoru Umezawa | Master of Cruelties +early_game | Murderous Redcap | Arwen, Weaver of Hope +early_game | Niv-Mizzet, the Firemind | Swans of Bryn Argoll +early_game | Avatar Aang | Mystic Speculation +early_game | Clever Impersonator | Wispweaver Angel +early_game | Living Plane | Doomwake Giant +early_game | Satya, Aetherflux Genius | Breath of Fury +early_game | Kiki-Jiki, Mirror Breaker | Pouncing Shoreshark +early_game | Stonecoil Serpent | Enduring Renewal +early_game | Murderous Redcap | Tromell, Seymour's Butler +early_game | Lithoform Engine | Sands of Time +early_game | Arcane Laboratory | Eye of the Storm +early_game | Umbral Mantle | Deathbloom Ritualist +early_game | Tooth and Claw | Chatterfang, Squirrel General +early_game | Aggravated Assault | Life // Death +early_game | Tameshi, Reality Architect | Second Chance +early_game | Intruder Alarm | Hell's Caretaker +early_game | Selvala, Explorer Returned | Tolarian Kraken +early_game | Ertha Jo, Frontier Mentor | Aphetto Alchemist +early_game | Triskelion | The Destined White Mage +early_game | Sprouting Phytohydra | Aether Flash +early_game | Jon Irenicus, Shattered One | Manta Ray +early_game | Felidar Guardian | Portcullis +early_game | Retrofitter Foundry | Mana Echoes +early_game | Intruder Alarm | Elemental Mastery +early_game | Halana and Alena, Partners | Sage of Hours +early_game | Sharuum the Hegemon | Evil Twin +early_game | Hulking Metamorph | Felidar Guardian +early_game | Jenova, Ancient Calamity | Sage of Hours +early_game | Tooth and Claw | Queen Allenal of Ruadach +early_game | Sharuum the Hegemon | Vizier of Many Faces +early_game | Mona Lisa, Science Geek | Freed from the Real +early_game | Farmstead Gleaner | Bigger on the Inside +early_game | Ghired, Mirror of the Wilds | Sparring Mummy +early_game | Harabaz Druid | Pemmin's Aura +early_game | Jon Irenicus, Shattered One | Lurebound Scarecrow +early_game | Living Plane | Humility +early_game | Kiki-Jiki, Mirror Breaker | Glowstone Recluse +early_game | Eirdu, Carrier of Dawn | Arcbound Worker +early_game | Leonin Relic-Warder | Enchanted Evening +early_game | Aluren | Horned Kavu +early_game | Eirdu, Carrier of Dawn | Arcbound Javelineer +early_game | Kitsa, Otterball Elite | To Arms! +early_game | Heidar, Rimewind Master | The One Ring +early_game | Splinter Twin | Bounding Krasis +early_game | Murderous Redcap | Bloodspore Thrinax +early_game | Meneldor, Swift Savior | Aurelia, the Warleader +early_game | Earthcraft | Grinning Ignus +early_game | Resourceful Defense | Delaying Shield +early_game | Chain of Smog | Leonin Lightscribe +early_game | Intruder Alarm | Steward of Solidarity +early_game | Swans of Bryn Argoll | Chain of Plasma +early_game | Timestream Navigator | Grenzo, Dungeon Warden +early_game | Kami of Whispered Hopes | Gauntlets of Light +early_game | Celestial Convergence | Hex Parasite +early_game | Stasis | Time Elemental +early_game | Pramikon, Sky Rampart | Auton Soldier +early_game | Gogo, Mysterious Mime | Ioreth of the Healing House +early_game | Sword of the Paruns | Rainveil Rejuvenator +early_game | The Jolly Balloon Man | Great Oak Guardian +early_game | Maralen of the Mornsong | Mindlock Orb +early_game | Mycosynth Lattice | Clarion Conqueror +early_game | Enduring Renewal | Skirk Prospector +early_game | Enduring Renewal | Omarthis, Ghostfire Initiate +early_game | Eirdu, Carrier of Dawn | Arcbound Mouser +early_game | Umbral Mantle | Harabaz Druid +early_game | Kiki-Jiki, Mirror Breaker | Trumpeting Gnarr +early_game | Spike Feeder | The Destined White Mage +early_game | Sakashima of a Thousand Faces | Wispweaver Angel +early_game | Time Sieve | Ria Ivor, Bane of Bladehold +early_game | All Will Be One | Night Dealings +early_game | Morophon, the Boundless | Shrieking Drake +early_game | Sunstrike Legionnaire | Elemental Mastery +early_game | Mephidross Vampire | Walking Ballista +early_game | Pramikon, Sky Rampart | Chameleon, Master of Disguise +early_game | Tezzeret, Master of the Bridge | Ancestral Statue +early_game | Sprout Swarm | Mana Echoes +early_game | Oasis Ritualist | Freed from the Real +early_game | Avatar Aang | Change of Heart +early_game | Enduring Renewal | Marketback Walker +early_game | Vivi Ornitier | Emiel the Blessed +early_game | Rakdos Joins Up | Clever Impersonator +early_game | The One Ring | Tradewind Rider +early_game | Cephalid Illusionist | Shaman en-Kor +early_game | Kiki-Jiki, Mirror Breaker | Insatiable Hemophage +early_game | Kirol, Attentive First-Year | Brago, King Eternal +early_game | Heartless Hidetsugu | Triumph of the Hordes +early_game | Mishra, Eminent One | Breath of Fury +early_game | Kiki-Jiki, Mirror Breaker | Dirge Bat +early_game | Orthion, Hero of Lavabrink | Great Oak Guardian +early_game | Crackdown Construct | Wandering Fumarole +early_game | Cephalid Aristocrat | Shuko +early_game | Splinter Twin | Great Oak Guardian +early_game | Gremlin Tamer | Screams from Within +early_game | Moritte of the Frost | Aerie Ouphes +early_game | Assault Suit | Dandân +early_game | Kiki-Jiki, Mirror Breaker | Dominating Vampire +early_game | Shalai and Hallar | The Destined White Mage +early_game | Splinter Twin | Breaching Hippocamp +early_game | Murderous Redcap | Good-Fortune Unicorn +early_game | Cryptcaller Chariot | Greater Good +early_game | Intruder Alarm | Nemata, Grove Guardian +early_game | Sage of the Falls | Cryptcaller Chariot +early_game | All Will Be One | Body of Research +early_game | Sprouting Phytohydra | Goblin Bombardment +early_game | Sharuum the Hegemon | Body Double +early_game | Jon Irenicus, Shattered One | Vodalian Knights +early_game | Horobi, Death's Wail | Baldin, Century Herdmaster +early_game | Sword of the Paruns | Mona Lisa, Science Geek +early_game | Eirdu, Carrier of Dawn | Arcbound Ravager +early_game | Lurebound Scarecrow | Assault Suit +early_game | Sharuum the Hegemon | Stunt Double +early_game | Endless One | Enduring Renewal +early_game | Mona Lisa, Science Geek | Pemmin's Aura +early_game | All-Out Assault | Appa, Loyal Sky Bison +early_game | Guardian Beast | Nevinyrral's Disk +early_game | The Watcher in the Water | Dire Undercurrents +early_game | Unctus, Grand Metatect | Norritt +early_game | Mirror-Mad Phantasm | Flesh Duplicate +early_game | Kiki-Jiki, Mirror Breaker | Chittering Harvester +early_game | Shifting Wall | Enduring Renewal +early_game | Mikaeus, the Unhallowed | Barrenton Medic +early_game | Oasis Ritualist | Pemmin's Aura +early_game | Jon Irenicus, Shattered One | Skeleton Ship +early_game | Seasinger | Assault Suit +early_game | Transcendence | Sulfuric Vortex +early_game | Delina, Wild Mage | Medomai the Ageless +early_game | Aggravated Assault | Living Plane +early_game | Palinchron | Dictate of Karametra +early_game | Helm of Obedience | Wheel of Sun and Moon +early_game | Living Plane | Ethereal Absolution +early_game | Dissection Tools | One with the Kami +early_game | Wirewood Symbiote | Conspiracy +early_game | Assault Suit | Manta Ray +early_game | Arena of the Ancients | Leyline of Singularity +early_game | Mornsong Aria | Mindlock Orb +early_game | Awakening | Sands of Time +early_game | Sword of the Paruns | Deathbloom Ritualist +early_game | Shilgengar, Sire of Famine | Chatterfang, Squirrel General +early_game | Mesmeric Orb | Tidewater Minion +early_game | Kiki-Jiki, Mirror Breaker | Cavern Whisperer +early_game | Cryptic Trilobite | Enduring Renewal +early_game | Vesuvan Shapeshifter | Felidar Guardian +early_game | Ghired, Mirror of the Wilds | Intruder Alarm +early_game | Lethal Vapors | Phyrexian Revoker +early_game | Sprouting Phytohydra | Blasting Station +early_game | Kiki-Jiki, Mirror Breaker | Mindleecher +early_game | Aether Storm | Pithing Needle +early_game | Hangar Scrounger | Seeker of Skybreak +early_game | Robaran Mercenaries | Kiki-Jiki, Mirror Breaker +early_game | Intruder Alarm | Speaker of the Heavens +early_game | Joo Dee, One of Many | Intruder Alarm +early_game | Jon Irenicus, Shattered One | Pirate Ship +early_game | Kiki-Jiki, Mirror Breaker | Huntmaster Liger +early_game | Jon Irenicus, Shattered One | Merchant Ship +early_game | Pentavus | Mana Echoes +early_game | Stormfront Riders | Cryptic Gateway +early_game | Kami of Whispered Hopes | High Alert +early_game | Enduring Renewal | Thermopod +early_game | Godhead of Awe | Ethereal Absolution +early_game | Tooth and Claw | Quina, Qu Gourmet +early_game | Reckless Barbarian | Enduring Renewal +early_game | Irma, Part-Time Mutant | Akki Battle Squad +early_game | Mayael's Aria | Wall of Blood +early_game | Heronblade Elite | Crab Umbra +early_game | Deathbringer Thoctar | Heliod, Sun-Crowned +early_game | Splinter Twin | Derevi, Empyrial Tactician +early_game | Leonin Relic-Warder | Dance of Many +early_game | Wheel of Misfortune | Hallow +early_game | Magus of the Moat | Mystic Decree +early_game | Phyrexian Marauder | Enduring Renewal +early_game | Celestial Convergence | Aether Snap +early_game | Mirror-Mad Phantasm | Sakashima's Will +early_game | Cephalid Illusionist | Reconnaissance +early_game | Mirror Image | Wispweaver Angel +early_game | Intruder Alarm | Hushwing Gryff +early_game | Heartless Hidetsugu | Corrupted Conscience +early_game | Jon Irenicus, Shattered One | Giant Shark +early_game | Kiki-Jiki, Mirror Breaker | Glamermite +early_game | Kamahl, Pit Fighter | Scythe of the Wretched +early_game | Transcendence | Rain of Gore +early_game | Biovisionary | Devastating Onslaught +early_game | Temporal Adept | Stasis +early_game | Tamanoa | Aetherflux Reservoir +early_game | Enduring Angel | Mirrorhall Mimic +early_game | Deathbringer Thoctar | Horobi, Death's Wail +early_game | Voice of the Woods | Intruder Alarm +early_game | Jon Irenicus, Shattered One | Sea Serpent +early_game | Tooth and Claw | Kaya, Geist Hunter +early_game | Lonis, Genetics Expert | Builder's Talent +early_game | Mirror-Mad Phantasm | See Double +early_game | Murderous Redcap | Warden of the Grove +early_game | Mayael's Aria | Malignus +early_game | Turnabout | Mirror Sheen +early_game | Felidar Guardian | Dual Nature +early_game | Mind Over Matter | Oracle's Insight +early_game | Kiki-Jiki, Mirror Breaker | Sky Hussar +early_game | Murderous Redcap | Thunderous Velocipede +early_game | Murderous Redcap | Railway Brawler +early_game | Assault Suit | Vodalian Knights +early_game | Deathbloom Ritualist | Freed from the Real +early_game | Goblin Sharpshooter | Living Plane +early_game | Chameleon, Master of Disguise | Wispweaver Angel +early_game | Jackal Pup | Pariah's Shield +early_game | Maha, Its Feathers Night | Crovax, Ascendant Hero +early_game | Assault Suit | Kukemssa Serpent +early_game | The Locust God | Dire Undercurrents +early_game | Arbor Adherent | Crab Umbra +early_game | Carnage, Crimson Chaos | Flesh Duplicate +early_game | Murderous Redcap | Surrak and Goreclaw +early_game | Altered Ego | Wispweaver Angel +early_game | Reset | Nivix Guildmage +early_game | Elite Arcanist | Vitalize +early_game | Ertha Jo, Frontier Mentor | Seeker of Skybreak +early_game | Felhide Spiritbinder | Ondu Spiritdancer +early_game | Shabraz, the Skyshark | Nefarious Lich +early_game | Cephalid Illusionist | Warrior en-Kor +early_game | Accomplished Alchemist | Crab Umbra +early_game | Murderous Redcap | Master Biomancer +early_game | Elemental Mastery | Black Carriage +early_game | Transcendence | Forsaken Wastes +early_game | Rakka Mar | Intruder Alarm +early_game | Ashaya, Soul of the Wild | Wormfang Newt +early_game | Gravity Sphere | Moat +early_game | Slimefoot, the Stowaway | Mana Echoes +early_game | Ranar the Ever-Watchful | Portcullis +early_game | Murderous Redcap | Bioengineered Future +early_game | Pirate Ship | Assault Suit +early_game | Eirdu, Carrier of Dawn | Arcbound Crusher +early_game | Eye of Singularity | Faerie Artisans +early_game | Bruce Banner | Hermetic Study +early_game | Aluren | Silver Drake +early_game | Splinter Twin | Glamermite +early_game | Changeling Titan | Dual Nature +early_game | Celestial Convergence | Thief of Blood +early_game | The One Ring | Tolarian Sentinel +early_game | Crackleburr | Cryptolith Rite +early_game | Najeela, the Blade-Blossom | Shriekwood Devourer +early_game | Lethal Vapors | Sorcerous Spyglass +early_game | Jon Irenicus, Shattered One | Ronom Serpent +early_game | Magar of the Magic Strings | Time Warp +early_game | Skeleton Ship | Assault Suit +early_game | Grimgrin, Corpse-Born | Elemental Mastery +early_game | Tawnos, Urza's Apprentice | Sands of Time +early_game | Sacred Guide | Jace, Wielder of Mysteries +early_game | Bruce Banner | Psionic Gift +early_game | Aether Flash | Nature's Revolt +early_game | Godhead of Awe | Night of Souls' Betrayal +early_game | Sharuum the Hegemon | Mirror of the Forebears +early_game | Intruder Alarm | Tolsimir Wolfblood +early_game | Reset | Izzet Guildmage +early_game | Captain of the Mists | Splinter Twin +early_game | Ob Nixilis, Captive Kingpin | Shalai and Hallar +early_game | Deathbloom Ritualist | Pemmin's Aura +early_game | Lord of the Forsaken | Near-Death Experience +early_game | Cadaverous Bloom | Well of Knowledge +early_game | Intruder Alarm | Selesnya Evangel +early_game | Casey Jones, Back Alley Brute | The Destined White Mage +early_game | Lethal Vapors | Indestructibility +early_game | Sword of the Paruns | Harabaz Druid +early_game | Aether Storm | Phyrexian Revoker +early_game | Intruder Alarm | Tocatli Honor Guard +early_game | Najeela, the Blade-Blossom | Hoard Hauler +early_game | Elemental Mastery | Altar Golem +early_game | Intruder Alarm | Puppet Conjurer +early_game | Fiend Hunter | Dual Nature +early_game | The Jolly Balloon Man | Sky Hussar +early_game | Mirror-Mad Phantasm | Moritte of the Frost +early_game | Freed from the Real | Mul Daya Channelers +early_game | Angel of Jubilation | Aether Storm +early_game | Assault Suit | Sea Serpent +early_game | Assault Suit | Merchant Ship +early_game | The Locust God | Rite of Harmony +early_game | Molten Echoes | Wispweaver Angel +early_game | Metamorphic Alteration | Mirror-Mad Phantasm +early_game | Garruk Relentless | Moritte of the Frost +early_game | Selvala, Heart of the Wilds | Singing Bell Strike +early_game | Deepwood Ghoul | Greven, Predator Captain +early_game | Aether Flash | Living Plane +early_game | Redshift, Rocketeer Chief | Seedcradle Witch +early_game | Filigree Sages | Prismatic Geoscope +early_game | Harbinger of the Seas | Curse of Marit Lage +early_game | Aether Storm | Sorcerous Spyglass +early_game | Chain of Smog | Silverquill Apprentice +early_game | Soulfire Grand Master | Reset +early_game | Cephalid Illusionist | Outrider en-Kor +early_game | Kami of Whispered Hopes | Singing Bell Strike +early_game | Elite Arcanist | Call to Glory +early_game | Stasis | Generous Plunderer +early_game | Intruder Alarm | Drana's Chosen +early_game | Wirewood Channeler | Crab Umbra +early_game | Mayael's Aria | Hatred +early_game | Godhead of Awe | Kaervek, the Spiteful +early_game | Gravity Sphere | Island Sanctuary +early_game | Sharuum the Hegemon | Vesuvan Shapeshifter +early_game | Kiki-Jiki, Mirror Breaker | Tidewater Minion +early_game | Ceaseless Searblades | Lavaclaw Reaches +early_game | Cephalid Illusionist | Grafted Wargear +early_game | Mikaeus, the Unhallowed | Canker Abomination +early_game | Mirror-Mad Phantasm | Vesuvan Shapeshifter +early_game | Teysa, Orzhov Scion | Mind Bend +early_game | Teysa, Orzhov Scion | Crystal Spray +early_game | Machine God's Effigy | Barrenton Medic +early_game | Medomai the Ageless | The Neutrinos +early_game | Marwyn, the Nurturer | Singing Bell Strike +early_game | Rasputin Dreamweaver | Emiel the Blessed +early_game | Casey Jones, Back Alley Brute | Phyrexian Devourer +early_game | Magar of the Magic Strings | Capture of Jingzhou +early_game | Assault Suit | Ronom Serpent +early_game | Tooth and Claw | Adrix and Nev, Twincasters +early_game | Carnage, Crimson Chaos | Deceptive Frostkite +early_game | Firedrinker Satyr | Pariah +early_game | Splinter Twin | Sky Hussar +early_game | Kitsa, Otterball Elite | Rally of Wings +early_game | Mona Lisa, Science Geek | Seedcradle Witch +early_game | Assault Suit | Gorilla Pack +early_game | Volcano Hellion | Sorin, Vengeful Bloodlord +early_game | Magar of the Magic Strings | Temporal Manipulation +early_game | Splinter Twin | Faces of the Past +early_game | Akki Battle Squad | The Neutrinos +early_game | Shilgengar, Sire of Famine | Quina, Qu Gourmet +early_game | Boros Reckoner | Rush of Vitality +early_game | Mirror-Mad Phantasm | Twinflame +early_game | Mirror-Mad Phantasm | Mirror of the Forebears +early_game | Ith, High Arcanist | Mesmeric Orb +early_game | Gravity Sphere | Magus of the Moat +early_game | Weaver of Blossoms | Freed from the Real +early_game | Mayael's Aria | Evra, Halcyon Witness +early_game | Murderous Redcap | Zameck Guildmage +early_game | Mind Over Matter | Talas Researcher +early_game | Enduring Angel | Ludevic, Necrogenius +early_game | Adarkar Valkyrie | Teardrop Kami +early_game | Aluren | Lava Zombie +early_game | Crackdown Construct | Soltari Guerrillas +early_game | Intruder Alarm | Flamewright +early_game | Faceless Butcher | Dual Nature +early_game | Jon Irenicus, Shattered One | Barbarian Outcast +early_game | Kiki-Jiki, Mirror Breaker | Teardrop Kami +early_game | Cephalid Aristocrat | Shaman en-Kor +early_game | Mirror-Mad Phantasm | Mercurial Pretender +early_game | Feast of Sanity | Ripjaw Raptor +early_game | Soltari Guerrillas | Willbreaker +early_game | Grimgrin, Corpse-Born | Presence of Gond +early_game | Mirror-Mad Phantasm | Molten Duplication +early_game | Mirror-Mad Phantasm | Shameless Charlatan +early_game | Hangar Scrounger | Aphetto Alchemist +early_game | Crackdown Construct | Mist Dragon +early_game | Jon Irenicus, Shattered One | Tethered Griffin +early_game | Jon Irenicus, Shattered One | Gorilla Pack +early_game | Black Carriage | Presence of Gond +early_game | Godhead of Awe | Ascendant Evincar +early_game | Saffi Eriksdotter | Crypt Champion +# early_game | Kederekt Leviathan | Last Voyage of the _____ +early_game | Ertha Jo, Frontier Mentor | Tidewater Minion +early_game | Kiki-Jiki, Mirror Breaker | Janjeet Sentry +early_game | Mayael's Aria | Willowdusk, Essence Seer +early_game | Goblin Sharpshooter | Godhead of Awe +early_game | Ghave, Guru of Spores | Mana Echoes +early_game | Soliton | Bigger on the Inside +early_game | General Leo Cristophe | Phantasmal Image +early_game | Ghired, Mirror of the Wilds | Deceiver Exarch +early_game | Godhead of Awe | Aether Flash +early_game | Jodah's Codex | Mind Over Matter +early_game | Horobi, Death's Wail | Soltari Guerrillas +early_game | Crypt Champion | Glasspool Mimic +early_game | Murderous Redcap | Cayth, Famed Mechanist +early_game | Intruder Alarm | Jungle Patrol +early_game | Jon Irenicus, Shattered One | Covetous Dragon +early_game | Wild Cantor | Enduring Renewal +early_game | Splinter Twin | Teardrop Kami +early_game | Murderous Redcap | Combine Guildmage +early_game | Synth Infiltrator | Wispweaver Angel +early_game | Shilgengar, Sire of Famine | Jinnie Fay, Jetmir's Second +early_game | Black Carriage | Splinter Twin +early_game | Molten Echoes | Unstoppable Ash +early_game | Ghired, Mirror of the Wilds | Grimgrin, Corpse-Born +early_game | Cephalid Aristocrat | Spirit en-Kor +early_game | Enchanted Evening | Chishiro, the Shattered Blade +early_game | Eirdu, Carrier of Dawn | Zabaz, the Glimmerwasp +early_game | Mind Over Matter | Magus of the Library +early_game | Shadowcloak Vampire | Greven, Predator Captain +early_game | Thermopod | Dargo, the Shipwrecker +early_game | Phyrexian Altar | Dargo, the Shipwrecker +early_game | Vivi Ornitier | Volrath, the Shapestealer +early_game | Mayael's Aria | Minion of the Wastes +early_game | Crypt Champion | Phantasmal Image +early_game | Intruder Alarm | Jund Battlemage +early_game | Molten Echoes | Thoughtweft Trio +early_game | Crackdown Construct | Blinking Spirit diff --git a/forge-gui/res/lists/extra-turns.txt b/forge-gui/res/lists/extra-turns.txt new file mode 100644 index 00000000000..a767a862cde --- /dev/null +++ b/forge-gui/res/lists/extra-turns.txt @@ -0,0 +1,57 @@ +Alchemist's Gambit +Alrund's Epiphany +Beacon of Tomorrows +Capture of Jingzhou +Chance for Glory +Emrakul, the Aeons Torn +Emrakul, the Promised End +Eon Frolicker +Expropriate +Final Fortune +Gonti's Aether Heart +Ichormoon Gauntlet +Karn's Temporal Sundering +Last Chance +Lighthouse Chronologist +Lost Isle Calling +Magistrate's Scepter +Magosi, the Waterveil +Medomai the Ageless +Mu Yanling +Nexus of Fate +Notorious Throng +Part the Waterveil +Perch Protection +# Phone a Friend has edition metadata but no card script. +Piece It Together +Plea for Power +Ral Zarek +Regenerations Restored +Rise of the Eldrazi +Sage of Hours +Savor the Moment +Search the City +Second Chance +Seedtime +Stitch in Time +Teferi, Master of Time +Teferi, Timebender +Temporal Extortion +Temporal Manipulation +Temporal Mastery +Temporal Trespass +The Legend of Kuruk // Avatar Kuruk +Time Sieve +Timesifter +Timestream Navigator +Time Stretch +Time Vault +Time Walk +Time Warp +Twice Upon a Time // Unlikely Meeting +Ugin's Nexus +Ultimecia, Time Sorceress // Ultimecia, Omnipotent +Walk the Aeons +Wanderwine Prophets +Warrior's Oath +Wormfang Manta diff --git a/forge-gui/res/lists/gamechangers.txt b/forge-gui/res/lists/gamechangers.txt new file mode 100644 index 00000000000..e3c2d9dea6b --- /dev/null +++ b/forge-gui/res/lists/gamechangers.txt @@ -0,0 +1,53 @@ +Ad Nauseam +Ancient Tomb +Aura Shards +Biorhythm +Bolas's Citadel +Braids, Cabal Minion +Chrome Mox +Coalition Victory +Consecrated Sphinx +Crop Rotation +Cyclonic Rift +Demonic Tutor +Drannith Magistrate +Enlightened Tutor +Farewell +Field of the Dead +Fierce Guardianship +Force of Will +Gaea's Cradle +Gamble +Gifts Ungiven +Glacial Chasm +Grand Arbiter Augustin IV +Grim Monolith +Humility +Imperial Seal +Intuition +Jeska's Will +Lion's Eye Diamond +Mana Vault +Mishra's Workshop +Mox Diamond +Mystical Tutor +Narset, Parter of Veils +Natural Order +Necropotence +Notion Thief +Opposition Agent +Orcish Bowmasters +Panoptic Mirror +Rhystic Study +Seedborn Muse +Serra's Sanctum +Smothering Tithe +Survival of the Fittest +Teferi's Protection +Tergrid, God of Fright // Tergrid's Lantern +Thassa's Oracle +The One Ring +The Tabernacle at Pendrell Vale +Underworld Breach +Vampiric Tutor +Worldly Tutor diff --git a/forge-gui/res/lists/mass-land-denial.txt b/forge-gui/res/lists/mass-land-denial.txt new file mode 100644 index 00000000000..0bf0a54b842 --- /dev/null +++ b/forge-gui/res/lists/mass-land-denial.txt @@ -0,0 +1,117 @@ +Acid Rain +Ajani Vengeant +Apocalypse +Armageddon +Avalanche +Back to Basics +Balance +Balancing Act +Bearer of the Heavens +Bend or Break +Blood Moon +Boil +Boiling Seas +Boom // Bust +Break the Ice +Burning Sands +Cataclysm +Catastrophe +Chaos Moon +Choke +Cleansing +Contamination +Conversion +Curse of Marit Lage +Curse of the Cabal +Damping Sphere +Death Cloud +Decree of Annihilation +Demonic Hordes +Desolation +Desolation Angel +Destructive Flow +Devastating Dreams +Devastation +Dimensional Breach +Dovin Baan +Drought +Earthlink +Epicenter +Equipoise +Fall of the Thran +Flashfires +Gideon, Champion of Justice +Gilt-Leaf Archdruid +Glaciers +Global Ruin +Hall of Gemstone +Harbinger of the Seas +Hokori, Dust Drinker +Illusionary Terrain +Impending Disaster +Infernal Darkness +Jokulhaups +Keldon Firebombers +Kudzu +Land Equilibrium +Liliana of the Veil +Liliana, Dreadhorde General +Limited Resources +Magus of the Balance +Magus of the Moon +Mana Breach +Mana Vortex +Mist of Stagnation +Myojin of Infinite Rage +Naked Singularity +Nature's Wrath +Numot, the Devastator +Obliterate +Omen of Fire +Once More with Feeling +Overburden +Pox +Price of Glory +Quicksilver Fountain +Raiding Party +Ravages of War +Razia's Purification +Razing Snidd +Reality Twist +Realm Razer +Restore Balance +Rising Waters +Ritual of Subdual +Ruination +Rumbling Crescendo +Shivan Harvest +Soulscour +Spelltithe Enforcer +Spreading Algae +Stasis +Static Orb +Stench of Evil +Stoneshaker Shaman +Storm Cauldron +Strategy, Schmategy +Sunder +Tainted Aether +Tangle Wire +Tectonic Break +Temporal Distortion +Thieves' Auction +Thoughts of Ruin +Trinisphere +Tsabo's Web +Tsunami +Upheaval +Urza's Sylex +Vorinclex, Voice of Hunger +Whims of the Fates +Wildfire +Winter Moon +Winter Orb +Winter's Night +Worldfire +Worldpurge +Worldslayer diff --git a/forge-gui/src/main/java/forge/deck/CommanderBracketCalculator.java b/forge-gui/src/main/java/forge/deck/CommanderBracketCalculator.java new file mode 100644 index 00000000000..52a23af7d7e --- /dev/null +++ b/forge-gui/src/main/java/forge/deck/CommanderBracketCalculator.java @@ -0,0 +1,279 @@ +package forge.deck; + +import forge.item.PaperCard; +import forge.localinstance.properties.ForgeConstants; +import forge.util.FileUtil; +import forge.util.Localizer; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.Map.Entry; + +public final class CommanderBracketCalculator { + private static final String LATE_GAME = "late_game"; + private static final String EARLY_GAME = "early_game"; + + private static final Data DATA = new Data(); + + private CommanderBracketCalculator() { + } + + public static Result calculate(final Deck deck) { + if (deck == null) { + return Result.empty(); + } + + final Set deckCards = getDeckCardNames(deck); + final List gamechangers = DATA.findCards(deckCards, DATA.gamechangers); + final List massLandDenial = DATA.findCards(deckCards, DATA.massLandDenial); + final List extraTurns = DATA.findCards(deckCards, DATA.extraTurns); + final List chainedExtraTurns = DATA.findCards(deckCards, DATA.chainedExtraTurns); + final List lateGameCombos = DATA.findCombos(deckCards, LATE_GAME); + final List earlyGameCombos = DATA.findCombos(deckCards, EARLY_GAME); + + int bracket = 1; + if (!massLandDenial.isEmpty()) { + bracket = Math.max(bracket, 4); + } + if (!chainedExtraTurns.isEmpty()) { + bracket = Math.max(bracket, 4); + } + if (extraTurns.size() >= 4) { + bracket = Math.max(bracket, 4); + } + else if (extraTurns.size() >= 3) { + bracket = Math.max(bracket, 3); + } + else if (extraTurns.size() >= 2) { + bracket = Math.max(bracket, 2); + } + if (gamechangers.size() >= 4) { + bracket = Math.max(bracket, 4); + } + else if (!gamechangers.isEmpty()) { + bracket = Math.max(bracket, 3); + } + if (!lateGameCombos.isEmpty()) { + bracket = Math.max(bracket, 3); + } + if (!earlyGameCombos.isEmpty()) { + bracket = Math.max(bracket, 4); + } + + return new Result(bracket, gamechangers, massLandDenial, extraTurns, chainedExtraTurns, lateGameCombos, earlyGameCombos); + } + + public static int getBracket(final Deck deck) { + return calculate(deck).getBracket(); + } + + public static String getDisplayBracket(final Deck deck) { + return String.valueOf(getBracket(deck)); + } + + public static String getExplanation(final Deck deck) { + return calculate(deck).toExplanation(); + } + + private static Set getDeckCardNames(final Deck deck) { + final Set result = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); + for (final Entry cardEntry : deck.getAllCardsInASinglePool()) { + result.addAll(cardEntry.getKey().getAllSearchableNames()); + } + return result; + } + + private static String normalize(final String text) { + return text.trim().toLowerCase(Locale.ROOT); + } + + private static final class Data { + private final Map gamechangers = readCardList(ForgeConstants.COMMANDER_BRACKET_GAMECHANGERS_FILE); + private final Map massLandDenial = readCardList(ForgeConstants.COMMANDER_BRACKET_MASS_LAND_DENIAL_FILE); + private final Map extraTurns = readCardList(ForgeConstants.COMMANDER_BRACKET_EXTRA_TURNS_FILE); + private final Map chainedExtraTurns = readCardList(ForgeConstants.COMMANDER_BRACKET_CHAINED_EXTRA_TURNS_FILE); + private final List combos = readCombos(); + + private List findCards(final Set deckCards, final Map source) { + final List result = new ArrayList<>(); + for (final String cardName : deckCards) { + final String match = source.get(normalize(cardName)); + if (match != null) { + result.add(match); + } + } + Collections.sort(result); + return result; + } + + private List findCombos(final Set deckCards, final String category) { + final List result = new ArrayList<>(); + for (final Combo combo : combos) { + if (category.equalsIgnoreCase(combo.category) + && deckCards.contains(combo.card1) + && deckCards.contains(combo.card2)) { + result.add(combo); + } + } + result.sort((a, b) -> a.toString().compareToIgnoreCase(b.toString())); + return result; + } + + private static Map readCardList(final String filename) { + final Map result = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + for (final String line : FileUtil.readFile(filename)) { + final String cardName = stripComment(line).trim(); + if (!cardName.isEmpty()) { + result.put(normalize(cardName), cardName); + } + } + return result; + } + + private static List readCombos() { + final List result = new ArrayList<>(); + for (final String line : FileUtil.readFile(ForgeConstants.COMMANDER_BRACKET_COMBOS_FILE)) { + final String comboLine = stripComment(line).trim(); + if (comboLine.isEmpty()) { + continue; + } + final String[] parts = comboLine.split("\\s*\\|\\s*"); + if (parts.length >= 3) { + result.add(new Combo(parts[0].trim(), parts[1].trim(), parts[2].trim())); + } + } + return result; + } + + private static String stripComment(final String line) { + final int commentIndex = line.indexOf('#'); + return commentIndex < 0 ? line : line.substring(0, commentIndex); + } + } + + public static final class Combo { + private final String category; + private final String card1; + private final String card2; + + private Combo(final String category, final String card1, final String card2) { + this.category = category; + this.card1 = card1; + this.card2 = card2; + } + + public String getCategory() { + return category; + } + + public String getCard1() { + return card1; + } + + public String getCard2() { + return card2; + } + + @Override + public String toString() { + return card1 + " + " + card2; + } + } + + public static final class Result { + private final int bracket; + private final List gamechangers; + private final List massLandDenial; + private final List extraTurns; + private final List chainedExtraTurns; + private final List lateGameCombos; + private final List earlyGameCombos; + + private Result(final int bracket, final List gamechangers, final List massLandDenial, + final List extraTurns, final List chainedExtraTurns, + final List lateGameCombos, final List earlyGameCombos) { + this.bracket = bracket; + this.gamechangers = gamechangers; + this.massLandDenial = massLandDenial; + this.extraTurns = extraTurns; + this.chainedExtraTurns = chainedExtraTurns; + this.lateGameCombos = lateGameCombos; + this.earlyGameCombos = earlyGameCombos; + } + + private static Result empty() { + return new Result(1, Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), + Collections.emptyList(), Collections.emptyList(), Collections.emptyList()); + } + + public int getBracket() { + return bracket; + } + + public String toExplanation() { + final Localizer localizer = Localizer.getInstance(); + final StringBuilder sb = new StringBuilder(); + sb.append(localizer.getMessage("lblCommanderBracketMinimum", bracket)).append("\n\n"); + appendCards(sb, localizer, localizer.getMessage("lblCommanderBracketGameChangers"), gamechangers, + gamechangers.size() >= 4 ? localizer.getMessage("lblCommanderBracketReasonGameChangersFour") + : !gamechangers.isEmpty() ? localizer.getMessage("lblCommanderBracketReasonGameChangersOne") + : null); + appendCards(sb, localizer, localizer.getMessage("lblCommanderBracketMassLandDenial"), massLandDenial, + massLandDenial.isEmpty() ? null : localizer.getMessage("lblCommanderBracketReasonMassLandDenial")); + appendCards(sb, localizer, localizer.getMessage("lblCommanderBracketExtraTurns"), extraTurns, + extraTurns.size() >= 4 ? localizer.getMessage("lblCommanderBracketReasonExtraTurnsFour") + : extraTurns.size() >= 3 ? localizer.getMessage("lblCommanderBracketReasonExtraTurnsThree") + : extraTurns.size() >= 2 ? localizer.getMessage("lblCommanderBracketReasonExtraTurnsTwo") + : extraTurns.isEmpty() ? null : localizer.getMessage("lblCommanderBracketReasonExtraTurnsFew")); + appendCards(sb, localizer, localizer.getMessage("lblCommanderBracketChainedExtraTurns"), chainedExtraTurns, + chainedExtraTurns.isEmpty() ? null : localizer.getMessage("lblCommanderBracketReasonChainedExtraTurn")); + appendCombos(sb, localizer, lateGameCombos, earlyGameCombos); + return sb.toString(); + } + + private static void appendCards(final StringBuilder sb, final Localizer localizer, + final String title, final List cards, final String reason) { + sb.append(title).append("\n"); + if (cards.isEmpty()) { + sb.append(" ").append(localizer.getMessage("lblNone")).append("\n"); + } + else { + for (final String card : cards) { + sb.append(" ").append(card).append("\n"); + } + } + if (reason != null) { + sb.append(" ").append(reason).append("\n"); + } + sb.append("\n"); + } + + private static void appendCombos(final StringBuilder sb, final Localizer localizer, + final List lateGameCombos, final List earlyGameCombos) { + sb.append(localizer.getMessage("lblCommanderBracketTwoCardCombos")).append("\n"); + if (lateGameCombos.isEmpty() && earlyGameCombos.isEmpty()) { + sb.append(" ").append(localizer.getMessage("lblNone")).append("\n"); + } + else { + for (final Combo combo : lateGameCombos) { + sb.append(" ").append(localizer.getMessage("lblCommanderBracketLateGame")).append(": ").append(combo).append("\n"); + } + for (final Combo combo : earlyGameCombos) { + sb.append(" ").append(localizer.getMessage("lblCommanderBracketEarlyGame")).append(": ").append(combo).append("\n"); + } + if (!lateGameCombos.isEmpty()) { + sb.append(" ").append(localizer.getMessage("lblCommanderBracketReasonLateGameCombo")).append("\n"); + } + if (!earlyGameCombos.isEmpty()) { + sb.append(" ").append(localizer.getMessage("lblCommanderBracketReasonEarlyGameCombo")).append("\n"); + } + } + } + } +} diff --git a/forge-gui/src/main/java/forge/itemmanager/ColumnDef.java b/forge-gui/src/main/java/forge/itemmanager/ColumnDef.java index d8e692c89c0..98643785c03 100644 --- a/forge-gui/src/main/java/forge/itemmanager/ColumnDef.java +++ b/forge-gui/src/main/java/forge/itemmanager/ColumnDef.java @@ -41,6 +41,8 @@ import java.util.Set; import java.util.function.Function; +import forge.deck.CommanderBracketCalculator; + public enum ColumnDef { /** * The column containing the inventory item name. @@ -312,6 +314,15 @@ public enum ColumnDef { DECK_AI("lblAI", "lblAIStatus", 38, true, SortState.DESC, from -> toDeck(from.getKey()).getAI().inMainDeck, from -> toDeck(from.getKey()).getAI()), + DECK_BRACKET("lblBracket", "ttCommanderBracket", 55, true, SortState.ASC, + from -> { + DeckProxy deck = toDeck(from.getKey()); + return deck == null ? 1 : CommanderBracketCalculator.getBracket(deck.getDeck()); + }, + from -> { + DeckProxy deck = toDeck(from.getKey()); + return deck == null ? "" : CommanderBracketCalculator.getDisplayBracket(deck.getDeck()); + }), /** * The main library size column. */ diff --git a/forge-gui/src/main/java/forge/itemmanager/ItemManagerConfig.java b/forge-gui/src/main/java/forge/itemmanager/ItemManagerConfig.java index 8fd6740bfb3..c8720d9fd7d 100644 --- a/forge-gui/src/main/java/forge/itemmanager/ItemManagerConfig.java +++ b/forge-gui/src/main/java/forge/itemmanager/ItemManagerConfig.java @@ -89,7 +89,7 @@ public enum ItemManagerConfig { GroupDef.DEFAULT, ColumnDef.CMC, 4, 1), CONSTRUCTED_DECKS(SColumnUtil.getDecksDefaultColumns(true, true), false, false, false, null, null, 3, 0), - COMMANDER_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false, + COMMANDER_DECKS(SColumnUtil.getDecksDefaultColumns(true, false, true), false, false, false, null, null, 3, 0), PLANAR_DECKS(SColumnUtil.getDecksDefaultColumns(true, false), false, false, false, null, null, 3, 0), @@ -111,6 +111,8 @@ public enum ItemManagerConfig { null, null, 3, 0), NET_DECKS(SColumnUtil.getDecksDefaultColumns(false, false), false, false, false, null, null, 3, 0), + NET_COMMANDER_DECKS(SColumnUtil.getDecksDefaultColumns(false, false, true), false, false, false, + null, null, 3, 0), NET_ARCHIVE_STANDARD_DECKS(SColumnUtil.getDecksDefaultColumns(false, false), false, false, false, null, null, 3, 0), NET_ARCHIVE_PIONEER_DECKS(SColumnUtil.getDecksDefaultColumns(false, false), false, false, false, diff --git a/forge-gui/src/main/java/forge/itemmanager/SColumnUtil.java b/forge-gui/src/main/java/forge/itemmanager/SColumnUtil.java index 0ae2e4a250e..0ee881974b5 100644 --- a/forge-gui/src/main/java/forge/itemmanager/SColumnUtil.java +++ b/forge-gui/src/main/java/forge/itemmanager/SColumnUtil.java @@ -236,6 +236,10 @@ public static Map getConquestCommandersDefaultColum } public static Map getDecksDefaultColumns(boolean allowEdit, boolean includeFolder) { + return getDecksDefaultColumns(allowEdit, includeFolder, false); + } + + public static Map getDecksDefaultColumns(boolean allowEdit, boolean includeFolder, boolean includeBracket) { List colDefs = new ArrayList<>(); colDefs.add(ColumnDef.DECK_FAVORITE); if (allowEdit) { @@ -248,6 +252,9 @@ public static Map getDecksDefaultColumns(boolean al colDefs.add(ColumnDef.DECK_COLOR); colDefs.add(ColumnDef.DECK_FORMAT); colDefs.add(ColumnDef.DECK_EDITION); + if (includeBracket) { + colDefs.add(ColumnDef.DECK_BRACKET); + } colDefs.add(ColumnDef.DECK_MAIN); colDefs.add(ColumnDef.DECK_SIDE); colDefs.add(ColumnDef.DECK_AI); diff --git a/forge-gui/src/main/java/forge/localinstance/properties/ForgeConstants.java b/forge-gui/src/main/java/forge/localinstance/properties/ForgeConstants.java index ed7e1f0d6f4..33a60340afd 100644 --- a/forge-gui/src/main/java/forge/localinstance/properties/ForgeConstants.java +++ b/forge-gui/src/main/java/forge/localinstance/properties/ForgeConstants.java @@ -74,6 +74,11 @@ public final class ForgeConstants { public static final String NET_ARCHIVE_LEGACY_DECKS_LIST_FILE = LISTS_DIR + "net-decks-archive-legacy.txt"; public static final String NET_ARCHIVE_VINTAGE_DECKS_LIST_FILE = LISTS_DIR + "net-decks-archive-vintage.txt"; public static final String NET_ARCHIVE_BLOCK_DECKS_LIST_FILE = LISTS_DIR + "net-decks-archive-block.txt"; + public static final String COMMANDER_BRACKET_COMBOS_FILE = LISTS_DIR + "commander-bracket-combos.txt"; + public static final String COMMANDER_BRACKET_GAMECHANGERS_FILE = LISTS_DIR + "gamechangers.txt"; + public static final String COMMANDER_BRACKET_MASS_LAND_DENIAL_FILE = LISTS_DIR + "mass-land-denial.txt"; + public static final String COMMANDER_BRACKET_EXTRA_TURNS_FILE = LISTS_DIR + "extra-turns.txt"; + public static final String COMMANDER_BRACKET_CHAINED_EXTRA_TURNS_FILE = LISTS_DIR + "chained-extra-turns.txt"; public static final String ADVENTURE_BOOSTER_PRICE_FILE = ADVENTURE_COMMON_LIST_DIR + "adventure-booster-price.txt"; public static final String CHANGES_FILE = ASSETS_DIR + "README.txt"; diff --git a/forge-gui/tools/scrape_bracket_details.py b/forge-gui/tools/scrape_bracket_details.py new file mode 100644 index 00000000000..c455d7a90e5 --- /dev/null +++ b/forge-gui/tools/scrape_bracket_details.py @@ -0,0 +1,246 @@ +#!/usr/bin/env python3 +"""Scrape Commander bracket detail lists. + +Outputs four headerless text files: +- commander-bracket-combos.txt: category | card_1 | card_2 +- gamechangers.txt: one card name per line +- mass-land-denial.txt: one card name per line +- extra-turns.txt: one card name per line +""" + +from __future__ import annotations + +import argparse +import html.parser +import json +import sys +import time +import urllib.error +import urllib.parse +import urllib.request +from pathlib import Path +from typing import Any, Iterable + + +EDHREC_BASE_URL = "https://edhrec.com" +EDHREC_JSON_BASE_URL = "https://json-cloudflare.edhrec.com/pages" +SCRYFALL_SEARCH_API = "https://api.scryfall.com/cards/search" + +COMBO_SOURCES = { + "late_game": "https://edhrec.com/combos/late-game-2-card-combos", + "early_game": "https://edhrec.com/combos/early-game-2-card-combos", +} +SCRYFALL_LISTS = { + "gamechangers.txt": "is:gamechanger", + "mass-land-denial.txt": "otag:mass-land-denial", + "extra-turns.txt": "oracletag:extra-turn", +} + + +class NextDataParser(html.parser.HTMLParser): + """Extract the JSON payload from Next.js' __NEXT_DATA__ script tag.""" + + def __init__(self) -> None: + super().__init__() + self._in_next_data = False + self._chunks: list[str] = [] + + def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None: + attrs_by_name = dict(attrs) + if tag == "script" and attrs_by_name.get("id") == "__NEXT_DATA__": + self._in_next_data = True + + def handle_endtag(self, tag: str) -> None: + if tag == "script" and self._in_next_data: + self._in_next_data = False + + def handle_data(self, data: str) -> None: + if self._in_next_data: + self._chunks.append(data) + + @property + def data(self) -> str: + return "".join(self._chunks).strip() + + +def fetch_text(url: str, accept: str, timeout: int = 30) -> str: + request = urllib.request.Request( + url, + headers={ + "Accept": accept, + "User-Agent": "Mozilla/5.0 commander-bracket-scraper/1.0", + }, + ) + try: + with urllib.request.urlopen(request, timeout=timeout) as response: + return response.read().decode("utf-8") + except urllib.error.HTTPError as exc: + body = exc.read().decode("utf-8", errors="replace") + raise RuntimeError(f"HTTP {exc.code} while fetching {url}: {body[:250]}") from exc + except urllib.error.URLError as exc: + raise RuntimeError(f"Could not fetch {url}: {exc.reason}") from exc + + +def fetch_json(url: str) -> dict[str, Any]: + return json.loads(fetch_text(url, accept="application/json")) + + +def parse_initial_payload(html: str) -> dict[str, Any]: + parser = NextDataParser() + parser.feed(html) + if not parser.data: + raise RuntimeError("Could not find __NEXT_DATA__ JSON in the EDHREC page.") + return json.loads(parser.data) + + +def walk_json(value: Any) -> Iterable[Any]: + yield value + if isinstance(value, dict): + for child in value.values(): + yield from walk_json(child) + elif isinstance(value, list): + for child in value: + yield from walk_json(child) + + +def find_combo_entries(payload: Any) -> list[dict[str, Any]]: + entries: list[dict[str, Any]] = [] + for value in walk_json(payload): + if isinstance(value, dict) and {"cardviews", "combo", "href"}.issubset(value): + entries.append(value) + return entries + + +def find_more_path(payload: Any) -> str | None: + for value in walk_json(payload): + if isinstance(value, dict) and isinstance(value.get("more"), str): + return value["more"] + return None + + +def edhrec_more_url(path: str) -> str: + return urllib.parse.urljoin(f"{EDHREC_JSON_BASE_URL}/", path) + + +def combo_row(category: str, entry: dict[str, Any]) -> tuple[str, str, str]: + card_names = [ + card.get("name", "").strip() + for card in entry.get("cardviews") or [] + if isinstance(card, dict) and card.get("name") + ] + card_1 = card_names[0] if len(card_names) > 0 else "" + card_2 = card_names[1] if len(card_names) > 1 else "" + return category, card_1, card_2 + + +def scrape_combo_source( + category: str, source_url: str, delay_seconds: float +) -> list[tuple[str, str, str]]: + print(f"Fetching {category}: {source_url}", file=sys.stderr) + payload = parse_initial_payload( + fetch_text(source_url, accept="text/html,application/json") + ) + rows = [combo_row(category, entry) for entry in find_combo_entries(payload)] + seen_more_paths: set[str] = set() + next_path = find_more_path(payload) + + while next_path: + if next_path in seen_more_paths: + raise RuntimeError(f"Pagination loop detected at {next_path}") + seen_more_paths.add(next_path) + if delay_seconds > 0: + time.sleep(delay_seconds) + + page_url = edhrec_more_url(next_path) + print(f"Fetching {category}: {page_url}", file=sys.stderr) + payload = fetch_json(page_url) + rows.extend(combo_row(category, entry) for entry in find_combo_entries(payload)) + next_path = find_more_path(payload) + + return rows + + +def scrape_combos(delay_seconds: float) -> list[tuple[str, str, str]]: + rows: list[tuple[str, str, str]] = [] + for category, source_url in COMBO_SOURCES.items(): + rows.extend(scrape_combo_source(category, source_url, delay_seconds)) + return rows + + +def scryfall_search_url(query: str) -> str: + return f"{SCRYFALL_SEARCH_API}?{urllib.parse.urlencode({'q': query, 'unique': 'cards'})}" + + +def scrape_scryfall_cards(query: str, delay_seconds: float) -> list[str]: + names: list[str] = [] + seen_names: set[str] = set() + next_url: str | None = scryfall_search_url(query) + + while next_url: + print(f"Fetching: {next_url}", file=sys.stderr) + payload = fetch_json(next_url) + for card in payload.get("data", []): + name = card.get("name", "").strip() + if name and name not in seen_names: + names.append(name) + seen_names.add(name) + + next_url = payload.get("next_page") if payload.get("has_more") else None + if next_url and delay_seconds > 0: + time.sleep(delay_seconds) + + return names + + +def write_combo_file(path: Path, rows: list[tuple[str, str, str]]) -> None: + with path.open("w", encoding="utf-8", newline="") as file: + for category, card_1, card_2 in rows: + file.write(f"{category} | {card_1} | {card_2}\n") + + +def write_card_file(path: Path, card_names: list[str]) -> None: + with path.open("w", encoding="utf-8", newline="") as file: + for name in card_names: + file.write(f"{name}\n") + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser( + description="Scrape Commander bracket combo and card detail lists." + ) + parser.add_argument( + "-o", + "--output-dir", + default=".", + help="Directory for output text files. Default: current directory.", + ) + parser.add_argument( + "--delay", + type=float, + default=0.5, + help="Seconds to wait between paginated requests. Default: 0.5", + ) + return parser.parse_args() + + +def main() -> int: + args = parse_args() + output_dir = Path(args.output_dir) + output_dir.mkdir(parents=True, exist_ok=True) + + combo_rows = scrape_combos(args.delay) + combo_path = output_dir / "commander-bracket-combos.txt" + write_combo_file(combo_path, combo_rows) + print(f"Wrote {len(combo_rows)} combos to {combo_path}") + + for filename, query in SCRYFALL_LISTS.items(): + card_names = scrape_scryfall_cards(query, args.delay) + output_path = output_dir / filename + write_card_file(output_path, card_names) + print(f"Wrote {len(card_names)} cards to {output_path}") + + return 0 + + +if __name__ == "__main__": + raise SystemExit(main())