diff --git a/.gitignore b/.gitignore index 39a0d76c168..d60de4860ca 100644 --- a/.gitignore +++ b/.gitignore @@ -91,6 +91,7 @@ Mage.Verify/AllCards.json.zip Mage.Verify/AllSets.json.zip Mage.Verify/AllCards.json Mage.Verify/AllSets.json +/db releases Utils/author.txt diff --git a/Mage.Client/pom.xml b/Mage.Client/pom.xml index 7a5a733b2c1..35baf24109c 100644 --- a/Mage.Client/pom.xml +++ b/Mage.Client/pom.xml @@ -158,11 +158,11 @@ 1.7 - - org.ocpsoft.prettytime - prettytime - 3.2.7.Final - + + org.ocpsoft.prettytime + prettytime + 3.2.7.Final + diff --git a/Mage.Client/serverlist.txt b/Mage.Client/serverlist.txt deleted file mode 100644 index caecdb8ac02..00000000000 --- a/Mage.Client/serverlist.txt +++ /dev/null @@ -1,6 +0,0 @@ -XMage.de 1 (Europe/Germany) fast :xmage.de:17171 -old xmage.de (Europe/Germany) :185.3.232.200:17171 -XMage Players MTG:xmageplayersmtg.ddns.net:17171 -XMage.tahiti :xmage.tahiti.one:443 -Seedds Server (Asia) :115.29.203.80:17171 -localhost -> connect to your local server (must be started):localhost:17171 diff --git a/Mage.Client/src/main/java/mage/client/cards/DragCardGrid.java b/Mage.Client/src/main/java/mage/client/cards/DragCardGrid.java index 7ca2057605b..3d388ad9260 100644 --- a/Mage.Client/src/main/java/mage/client/cards/DragCardGrid.java +++ b/Mage.Client/src/main/java/mage/client/cards/DragCardGrid.java @@ -1,5 +1,15 @@ package mage.client.cards; +import java.awt.*; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import javax.swing.*; import mage.cards.Card; import mage.cards.MageCard; import mage.cards.decks.DeckCardInfo; @@ -20,17 +30,6 @@ import mage.view.CardsView; import org.apache.log4j.Logger; import org.mage.card.arcane.CardRenderer; -import javax.swing.*; -import java.awt.*; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - /** * Created by StravantUser on 2016-09-20. */ @@ -1408,13 +1407,13 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg while (regexMatcher.find()) { String val = regexMatcher.group(1); int colorless_val = Integer.parseInt(val); - + int total_c_pip = 0; - if (pips.get("#c}") != null) { + if (pips.get("#c}") != null) { total_c_pip = pips.get("#c}"); } pips.put("#c}", colorless_val + total_c_pip); - + int cmc_pip_value = 0; if (pips_at_cmcs.get(cmc + "##c}") != null) { cmc_pip_value = pips_at_cmcs.get(cmc + "##c}"); @@ -2032,6 +2031,9 @@ public class DragCardGrid extends JPanel implements DragCardSource, DragCardTarg } private int getCardWidth() { + if (GUISizeHelper.editorCardDimension == null) { + return 200; + } return (int) (GUISizeHelper.editorCardDimension.width * cardSizeMod); } diff --git a/Mage.Client/src/main/java/mage/client/deck/generator/DeckGenerator.java b/Mage.Client/src/main/java/mage/client/deck/generator/DeckGenerator.java index 88c94f17118..ab7e7b07743 100644 --- a/Mage.Client/src/main/java/mage/client/deck/generator/DeckGenerator.java +++ b/Mage.Client/src/main/java/mage/client/deck/generator/DeckGenerator.java @@ -1,4 +1,3 @@ - package mage.client.deck.generator; import java.util.ArrayList; @@ -7,6 +6,7 @@ import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; + import mage.cards.Card; import mage.cards.decks.Deck; import mage.cards.repository.CardCriteria; @@ -123,9 +123,9 @@ public final class DeckGenerator { * non-creatures, lands (including non-basic). Fixes the deck, adjusting for * size and color of the cards retrieved. * - * @param deckSize how big the deck is to generate. + * @param deckSize how big the deck is to generate. * @param allowedColors which colors are allowed in the deck. - * @param setsToUse which sets to use to retrieve cards for this deck. + * @param setsToUse which sets to use to retrieve cards for this deck. * @return the final deck to use. */ private static Deck generateDeck(int deckSize, List allowedColors, List setsToUse) { @@ -180,9 +180,9 @@ public final class DeckGenerator { * non-creatures are retrieved separately to ensure the deck contains a * reasonable mix of both. * - * @param criteria the criteria to search for in the database. + * @param criteria the criteria to search for in the database. * @param spellCount the number of spells that match the criteria needed in - * the deck. + * the deck. */ private static void generateSpells(CardCriteria criteria, int spellCount) { List cardPool = CardRepository.instance.findCards(criteria); @@ -233,7 +233,7 @@ public final class DeckGenerator { * in this deck. Usually the lands will be well balanced relative to the * color of cards. * - * @param criteria the criteria of the lands to search for in the database. + * @param criteria the criteria of the lands to search for in the database. * @param landsCount the amount of lands required for this deck. * @param basicLands information about the basic lands from the sets used. */ @@ -310,10 +310,10 @@ public final class DeckGenerator { * filled. * * @param landsNeeded how many remaining lands are needed. - * @param percentage the percentage needed for each color in the final deck. - * @param count how many of each color can be produced by non-basic lands. - * @param basicLands list of information about basic lands from the - * database. + * @param percentage the percentage needed for each color in the final deck. + * @param count how many of each color can be produced by non-basic lands. + * @param basicLands list of information about basic lands from the + * database. */ private static void addBasicLands(int landsNeeded, Map percentage, Map count, Map> basicLands) { @@ -360,15 +360,14 @@ public final class DeckGenerator { /** * Return a random basic land of the chosen color. * - * @param color the color the basic land should produce. + * @param color the color the basic land should produce. * @param basicLands list of information about basic lands from the - * database. + * database. * @return a single basic land that produces the color needed. */ private static Card getBasicLand(ColoredManaSymbol color, Map> basicLands) { String landName = DeckGeneratorPool.getBasicLandName(color.toString()); List basicLandsInfo = basicLands.get(landName); - return basicLandsInfo.get(RandomUtil.nextInt(basicLandsInfo.size() - 1)).getMockCard().copy(); + return basicLandsInfo.get(RandomUtil.nextInt(basicLandsInfo.size())).getMockCard().copy(); } - } diff --git a/Mage.Client/src/main/java/mage/client/deckeditor/CardSelector.java b/Mage.Client/src/main/java/mage/client/deckeditor/CardSelector.java index 413b087ebde..7935854a1ba 100644 --- a/Mage.Client/src/main/java/mage/client/deckeditor/CardSelector.java +++ b/Mage.Client/src/main/java/mage/client/deckeditor/CardSelector.java @@ -1,6 +1,4 @@ - - - /* +/* * CardSelector.java * * Created on Feb 18, 2010, 2:49:03 PM diff --git a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPane.java b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPane.java index 477c1cff45b..a61e879b1af 100644 --- a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPane.java +++ b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPane.java @@ -1,6 +1,4 @@ - - - /* +/* * DeckEditorPane.java * * Created on Dec 17, 2009, 9:21:42 AM @@ -98,14 +96,13 @@ public class DeckEditorPane extends MagePane { this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(container, javax.swing.GroupLayout.DEFAULT_SIZE, 885, Short.MAX_VALUE) + .addComponent(container, javax.swing.GroupLayout.DEFAULT_SIZE, 885, Short.MAX_VALUE) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(container, javax.swing.GroupLayout.DEFAULT_SIZE, 626, Short.MAX_VALUE) + .addComponent(container, javax.swing.GroupLayout.DEFAULT_SIZE, 626, Short.MAX_VALUE) ); - } public DeckEditorPanel getPanel() { diff --git a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.form b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.form index 5065dfbe631..27c3526d491 100644 --- a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.form +++ b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.form @@ -192,6 +192,15 @@ + + + + + + + + + @@ -210,7 +219,7 @@ - + diff --git a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java index 971e45679b8..182be367ebd 100644 --- a/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java +++ b/Mage.Client/src/main/java/mage/client/deckeditor/DeckEditorPanel.java @@ -1,6 +1,14 @@ - package mage.client.deckeditor; +import java.awt.*; +import java.awt.event.*; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.*; +import java.util.concurrent.*; +import javax.swing.*; +import javax.swing.filechooser.FileFilter; import mage.cards.Card; import mage.cards.Sets; import mage.cards.decks.Deck; @@ -29,18 +37,6 @@ import mage.view.CardView; import mage.view.SimpleCardView; import org.apache.log4j.Logger; -import javax.swing.*; -import javax.swing.Timer; -import javax.swing.filechooser.FileFilter; -import java.awt.*; -import java.awt.event.*; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.*; -import java.util.List; -import java.util.concurrent.*; - /** * @author BetaSteward_at_googlemail.com */ @@ -55,7 +51,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { private UUID tableId; private DeckEditorMode mode; private int timeout; - private Timer countdown; + private javax.swing.Timer countdown; private UpdateDeckTask updateDeckTask; private int timeToSubmit = -1; @@ -75,7 +71,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { jPanel1.setOpaque(false); jSplitPane1.setOpaque(false); restoreDividerLocationsAndDeckAreaSettings(); - countdown = new Timer(1000, + countdown = new javax.swing.Timer(1000, e -> { if (--timeout > 0) { setTimeout(timeout); @@ -209,7 +205,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { this.btnGenDeck.setVisible(false); this.btnImport.setVisible(false); this.btnLoad.setVisible(false); - this.btnNew.setVisible(false); + this.btnNew.setVisible(false); this.btnSubmit.setVisible(false); this.btnSubmitTimer.setVisible(false); this.cardSelector.loadCards(this.bigCard); @@ -456,7 +452,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { CardView cardView = (CardView) event.getSource(); int numberToSet = event.getNumber(); int cardsFound = 0; - List toDelete = new ArrayList<>(); + java.util.List toDelete = new ArrayList<>(); for (Card card : cards) { if (card.getName().equals(cardView.getName()) && Objects.equals(card.getCardNumber(), cardView.getCardNumber()) @@ -689,7 +685,6 @@ public class DeckEditorPanel extends javax.swing.JPanel { btnGenDeck.setText("Generate"); btnGenDeck.setName("btnGenDeck"); btnGenDeck.addActionListener(evt -> btnGenDeckActionPerformed(evt)); - txtTimeRemaining.setEditable(false); txtTimeRemaining.setForeground(java.awt.Color.red); txtTimeRemaining.setHorizontalAlignment(javax.swing.JTextField.CENTER); @@ -699,89 +694,89 @@ public class DeckEditorPanel extends javax.swing.JPanel { jPanel1.setLayout(jPanel1Layout); jPanel1Layout.setHorizontalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - /*.addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createSequentialGroup() + .addGroup(jPanel1Layout.createSequentialGroup() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + /*.addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel1Layout.createSequentialGroup() .addContainerGap() .addComponent(jLayeredPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 256, Short.MAX_VALUE))*/ - .addGroup(jPanel1Layout.createSequentialGroup() - .addGap(6, 6, 6) - .addComponent(lblDeckName) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(txtDeckName, javax.swing.GroupLayout.DEFAULT_SIZE, 189, Short.MAX_VALUE)) - .addComponent(cardInfoPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(bigCard, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGroup(jPanel1Layout.createSequentialGroup() - .addContainerGap() - .addComponent(btnSave) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnLoad) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnNew) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(btnExit)) - .addGroup(jPanel1Layout.createSequentialGroup() - .addContainerGap() - .addComponent(btnImport) - .addContainerGap() - .addComponent(btnGenDeck) - .addContainerGap() - .addComponent(btnAddLand) - .addContainerGap() - .addComponent(btnSubmit) - .addContainerGap() - .addComponent(btnSubmitTimer)) - .addGroup(jPanel1Layout.createSequentialGroup() - .addContainerGap() - .addComponent(txtTimeRemaining)) - ) - .addContainerGap())); + .addGroup(jPanel1Layout.createSequentialGroup() + .addGap(6, 6, 6) + .addComponent(lblDeckName) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(txtDeckName, javax.swing.GroupLayout.DEFAULT_SIZE, 189, Short.MAX_VALUE)) + .addComponent(cardInfoPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(bigCard, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addComponent(btnSave) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnLoad) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnNew) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(btnExit)) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addComponent(btnImport) + .addContainerGap() + .addComponent(btnGenDeck) + .addContainerGap() + .addComponent(btnAddLand) + .addContainerGap() + .addComponent(btnSubmit) + .addContainerGap() + .addComponent(btnSubmitTimer)) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addComponent(txtTimeRemaining)) + ) + .addContainerGap())); jPanel1Layout.setVerticalGroup( jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(jPanel1Layout.createSequentialGroup() - .addContainerGap() - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(txtDeckName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblDeckName)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(btnSave) - .addComponent(btnLoad) - .addComponent(btnNew) - .addComponent(btnExit)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(btnImport) - .addComponent(btnGenDeck) - .addComponent(btnAddLand) - .addComponent(btnSubmit) - .addComponent(btnSubmitTimer)) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(txtTimeRemaining)) - //.addComponent(jLayeredPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 60, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, isShowCardInfo ? 30 : 159, Short.MAX_VALUE) - .addComponent(cardInfoPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 104, Short.MAX_VALUE) - .addComponent(bigCard, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))); + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(txtDeckName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblDeckName)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(btnSave) + .addComponent(btnLoad) + .addComponent(btnNew) + .addComponent(btnExit)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(btnImport) + .addComponent(btnGenDeck) + .addComponent(btnAddLand) + .addComponent(btnSubmit) + .addComponent(btnSubmitTimer)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(txtTimeRemaining)) + //.addComponent(jLayeredPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 60, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, isShowCardInfo ? 30 : 159, Short.MAX_VALUE) + .addComponent(cardInfoPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 104, Short.MAX_VALUE) + .addComponent(bigCard, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 261, javax.swing.GroupLayout.PREFERRED_SIZE) - .addGap(0, 0, 0) - .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 604, Short.MAX_VALUE))); + .addGroup(layout.createSequentialGroup() + .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 261, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(jSplitPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 604, Short.MAX_VALUE))); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) - .addComponent(jSplitPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 615, Short.MAX_VALUE)); + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jSplitPane1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 615, Short.MAX_VALUE)); } - private void processAndShowImportErrors(StringBuilder errorMessages){ + private void processAndShowImportErrors(StringBuilder errorMessages) { // show up errors list - if (errorMessages.length() > 0){ + if (errorMessages.length() > 0) { String mes = "Founded problems with deck: \n\n" + errorMessages.toString(); JOptionPane.showMessageDialog(MageFrame.getDesktop(), mes.substring(0, Math.min(1000, mes.length())), "Errors while loading deck", JOptionPane.WARNING_MESSAGE); } @@ -813,7 +808,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { } catch (GameException e1) { JOptionPane.showMessageDialog(MageFrame.getDesktop(), e1.getMessage(), "Error loading deck", JOptionPane.ERROR_MESSAGE); - }finally { + } finally { MageFrame.getDesktop().setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); } } @@ -845,7 +840,7 @@ public class DeckEditorPanel extends javax.swing.JPanel { } } catch (GameException e1) { JOptionPane.showMessageDialog(MageFrame.getDesktop(), e1.getMessage(), "Error loading deck", JOptionPane.ERROR_MESSAGE); - }finally { + } finally { MageFrame.getDesktop().setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); } } @@ -1063,7 +1058,6 @@ public class DeckEditorPanel extends javax.swing.JPanel { } refreshDeck(); } - // Variables declaration - do not modify//GEN-BEGIN:variables private mage.client.cards.BigCard bigCard; private javax.swing.JButton btnExit; diff --git a/Mage.Client/src/main/java/mage/client/deckeditor/DeckImportFromClipboardDialog.java b/Mage.Client/src/main/java/mage/client/deckeditor/DeckImportFromClipboardDialog.java index eef1987dfaa..32f63c8d187 100644 --- a/Mage.Client/src/main/java/mage/client/deckeditor/DeckImportFromClipboardDialog.java +++ b/Mage.Client/src/main/java/mage/client/deckeditor/DeckImportFromClipboardDialog.java @@ -3,15 +3,28 @@ package mage.client.deckeditor; import mage.util.StreamUtils; import java.awt.*; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.event.*; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; +import java.util.Optional; + import javax.swing.*; public class DeckImportFromClipboardDialog extends JDialog { + private static final String FORMAT_TEXT = + "// Example:\n" + + "//1 Library of Congress\n" + + "//1 Cryptic Gateway\n" + + "//1 Azami, Lady of Scrolls\n" + + "// NB: This is slow as, and will lock your screen :)\n" + + "\n" + + "// Your current clipboard:\n"; + private JPanel contentPane; private JButton buttonOK; private JButton buttonCancel; @@ -21,6 +34,9 @@ public class DeckImportFromClipboardDialog extends JDialog { public DeckImportFromClipboardDialog() { initComponents(); + + onRefreshClipboard(); + setContentPane(contentPane); setModal(true); getRootPane().setDefaultButton(buttonOK); @@ -40,6 +56,15 @@ public class DeckImportFromClipboardDialog extends JDialog { contentPane.registerKeyboardAction(e -> onCancel(), KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT); } + private Optional getClipboardStringData() { + try { + return Optional.of((String)Toolkit.getDefaultToolkit().getSystemClipboard().getData(DataFlavor.stringFlavor)); + } catch (HeadlessException | UnsupportedFlavorException | IOException e) { + //e.printStackTrace(); + } + return Optional.empty(); + } + private void onOK() { BufferedWriter bw = null; try { @@ -60,6 +85,10 @@ public class DeckImportFromClipboardDialog extends JDialog { dispose(); } + private void onRefreshClipboard() { + txtDeckList.setText(FORMAT_TEXT + getClipboardStringData().orElse("")); + } + public String getTmpPath() { return tmpPath; } @@ -143,7 +172,7 @@ public class DeckImportFromClipboardDialog extends JDialog { txtDeckList.setMinimumSize(new Dimension(250, 400)); txtDeckList.setPreferredSize(new Dimension(550, 400)); - txtDeckList.setText("// Example:\n//1 Library of Congress\n//1 Cryptic Gateway\n//1 Azami, Lady of Scrolls\n// NB: This is slow as, and will lock your screen :)"); + txtDeckList.setText(FORMAT_TEXT); JScrollPane txtScrollableDeckList = new JScrollPane(txtDeckList); panel3.add(txtScrollableDeckList, new GridBagConstraints(0, 0, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, diff --git a/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.form b/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.form index 5b74e76cbf5..c1ef452cc22 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.form +++ b/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.form @@ -340,8 +340,8 @@ - - + + diff --git a/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java b/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java index 120c35e2c03..10e188e3336 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java @@ -270,8 +270,8 @@ public class ConnectDialog extends MageDialog { }); btnFind3.setIcon(new javax.swing.ImageIcon(getClass().getResource("/flags/us.png"))); // NOI18N - btnFind3.setText("W"); - btnFind3.setToolTipText("Connect to vaporservermtg.com (USA)"); + btnFind3.setText("P"); + btnFind3.setToolTipText("Connect to mtg.powersofwar.com (USA)"); btnFind3.setActionCommand("connectXmageus"); btnFind3.setAlignmentY(0.0F); btnFind3.setMargin(new java.awt.Insets(2, 2, 2, 2)); @@ -688,7 +688,7 @@ public class ConnectDialog extends MageDialog { }//GEN-LAST:event_btnFind2findPublicServerActionPerformed private void connectXmageus(java.awt.event.ActionEvent evt) { - String serverAddress = "vapormtgserver.com"; + String serverAddress = "mtg.powersofwar.com"; this.txtServer.setText(serverAddress); this.txtPort.setText("17171"); // Update userName and password according to the chosen server. diff --git a/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.java b/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.java index 0e3121f61d9..c47059ed798 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/NewTableDialog.java @@ -51,6 +51,7 @@ public class NewTableDialog extends MageDialog { this.spnNumWins.setModel(new SpinnerNumberModel(1, 1, 5, 1)); this.spnFreeMulligans.setModel(new SpinnerNumberModel(0, 0, 5, 1)); this.spnQuitRatio.setModel(new SpinnerNumberModel(100, 0, 100, 5)); + this.spnMinimumRating.setModel(new SpinnerNumberModel(0, 0, 3000, 10)); this.spnEdhPowerLevel.setModel(new SpinnerNumberModel(100, 0, 100, 5)); MageFrame.getUI().addButton(MageComponents.NEW_TABLE_OK_BUTTON, btnOK); } @@ -102,8 +103,10 @@ public class NewTableDialog extends MageDialog { btnPreviousConfiguration2 = new javax.swing.JButton(); btnCancel = new javax.swing.JButton(); lblQuitRatio = new javax.swing.JLabel(); + lblMinimumRating = new javax.swing.JLabel(); lblEdhPowerLevel = new javax.swing.JLabel(); spnQuitRatio = new javax.swing.JSpinner(); + spnMinimumRating = new javax.swing.JSpinner(); spnEdhPowerLevel = new javax.swing.JSpinner(); setTitle("New Table"); @@ -186,9 +189,11 @@ public class NewTableDialog extends MageDialog { btnCancel.addActionListener(evt -> btnCancelActionPerformed(evt)); lblQuitRatio.setText("Allowed quit %"); + lblMinimumRating.setText("Minimum rating"); lblEdhPowerLevel.setText("EDH power level"); spnQuitRatio.setToolTipText("Players with quit % more than this value can't join this table"); + spnMinimumRating.setToolTipText("Players with rating less than this value can't join this table"); spnEdhPowerLevel.setToolTipText("Players with decks with a higher power level can't join this table"); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); @@ -239,9 +244,10 @@ public class NewTableDialog extends MageDialog { .addComponent(lblQuitRatio) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(spnQuitRatio, javax.swing.GroupLayout.PREFERRED_SIZE, 60, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblEdhPowerLevel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(lblMinimumRating) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(spnEdhPowerLevel, javax.swing.GroupLayout.PREFERRED_SIZE, 60, javax.swing.GroupLayout.PREFERRED_SIZE)))) + .addComponent(spnMinimumRating, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE)))) .addComponent(jLabel1, javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jLabel2, javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() @@ -270,7 +276,11 @@ public class NewTableDialog extends MageDialog { .addGap(18, 18, 18) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(lblNumWins) - .addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(lblEdhPowerLevel) + .addComponent(spnEdhPowerLevel, javax.swing.GroupLayout.PREFERRED_SIZE, 60, javax.swing.GroupLayout.PREFERRED_SIZE))) .addComponent(jSeparator2) .addComponent(player1Panel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(pnlOtherPlayers, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) @@ -297,14 +307,13 @@ public class NewTableDialog extends MageDialog { .addComponent(cbTimeLimit, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) - .addComponent(cbDeckType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(lbDeckType) + .addComponent(cbDeckType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(chkRated) .addComponent(lblQuitRatio) - .addComponent(chkRated) .addComponent(spnQuitRatio, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(lblEdhPowerLevel) - .addComponent(chkRated) - .addComponent(spnEdhPowerLevel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(lblMinimumRating) + .addComponent(spnMinimumRating, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) @@ -326,6 +335,7 @@ public class NewTableDialog extends MageDialog { .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(lblSkillLevel) .addComponent(lblNumWins) + .addComponent(lblEdhPowerLevel) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(lblRange) .addComponent(lblAttack))) @@ -334,7 +344,8 @@ public class NewTableDialog extends MageDialog { .addComponent(cbRange, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(cbAttackOption, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(cbSkillLevel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) - .addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))) + .addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(spnEdhPowerLevel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) @@ -394,6 +405,7 @@ public class NewTableDialog extends MageDialog { options.setFreeMulligans((Integer) this.spnFreeMulligans.getValue()); options.setPassword(this.txtPassword.getText()); options.setQuitRatio((Integer) this.spnQuitRatio.getValue()); + options.setMinimumRating((Integer) this.spnMinimumRating.getValue()); options.setEdhPowerLevel((Integer) this.spnEdhPowerLevel.getValue()); String serverAddress = SessionHandler.getSession().getServerHostname().orElseGet(() -> ""); options.setBannedUsers(IgnoreList.ignoreList(serverAddress)); @@ -695,6 +707,7 @@ public class NewTableDialog extends MageDialog { } this.spnQuitRatio.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_QUIT_RATIO, "100"))); + this.spnMinimumRating.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TABLE_MINIMUM_RATING + versionStr, "0"))); this.spnEdhPowerLevel.setValue(0); } @@ -729,6 +742,7 @@ public class NewTableDialog extends MageDialog { PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_SPECTATORS_ALLOWED + versionStr, options.isSpectatorsAllowed() ? "Yes" : "No"); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_PLANECHASE + versionStr, options.isPlaneChase() ? "Yes" : "No"); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_QUIT_RATIO + versionStr, Integer.toString(options.getQuitRatio())); + PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TABLE_MINIMUM_RATING + versionStr, Integer.toString(options.getMinimumRating())); StringBuilder playerTypesString = new StringBuilder(); for (Object player : players) { if (playerTypesString.length() > 0) { @@ -770,6 +784,7 @@ public class NewTableDialog extends MageDialog { private javax.swing.JLabel lblNumWins; private javax.swing.JLabel lblPassword; private javax.swing.JLabel lblQuitRatio; + private javax.swing.JLabel lblMinimumRating; private javax.swing.JLabel lblEdhPowerLevel; private javax.swing.JLabel lblRange; private javax.swing.JLabel lblSkillLevel; @@ -779,6 +794,7 @@ public class NewTableDialog extends MageDialog { private javax.swing.JSpinner spnNumPlayers; private javax.swing.JSpinner spnNumWins; private javax.swing.JSpinner spnQuitRatio; + private javax.swing.JSpinner spnMinimumRating; private javax.swing.JSpinner spnEdhPowerLevel; private javax.swing.JTextField txtName; private javax.swing.JTextField txtPassword; diff --git a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java index f5f2961f513..fef9bdab407 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/NewTournamentDialog.java @@ -24,6 +24,7 @@ import mage.cards.repository.ExpansionRepository; import mage.client.MageFrame; import mage.client.SessionHandler; import mage.client.table.TournamentPlayerPanel; +import mage.client.util.IgnoreList; import mage.client.util.gui.FastSearchUtil; import mage.constants.MatchTimeLimit; import mage.constants.MultiplayerAttackOption; @@ -74,6 +75,7 @@ public class NewTournamentDialog extends MageDialog { this.spnConstructTime.setModel(new SpinnerNumberModel(10, CONSTRUCTION_TIME_MIN, CONSTRUCTION_TIME_MAX, 2)); this.spnNumRounds.setModel(new SpinnerNumberModel(2, 2, 10, 1)); this.spnQuitRatio.setModel(new SpinnerNumberModel(100, 0, 100, 5)); + this.spnMinimumRating.setModel(new SpinnerNumberModel(0, 0, 3000, 10)); } public void showDialog(UUID roomId) { @@ -164,6 +166,8 @@ public class NewTournamentDialog extends MageDialog { pnlRandomPacks = new javax.swing.JPanel(); lblQuitRatio = new javax.swing.JLabel(); spnQuitRatio = new javax.swing.JSpinner(); + lblMinimumRating = new javax.swing.JLabel(); + spnMinimumRating = new javax.swing.JSpinner(); setTitle("New Tournament"); @@ -314,8 +318,10 @@ public class NewTournamentDialog extends MageDialog { pnlRandomPacks.setLayout(new javax.swing.BoxLayout(pnlRandomPacks, javax.swing.BoxLayout.Y_AXIS)); lblQuitRatio.setText("Allowed quit %:"); + lblMinimumRating.setText("Minimum rating:"); spnQuitRatio.setToolTipText("Players with quit % more than this value can't join this table"); + spnMinimumRating.setToolTipText("Players with rating less than this value can't join this table"); spnNumSeats.setToolTipText("The number of seats for each duel. If more than 2, will set number of wins to 1"); spnNumPlayers.setToolTipText("The total number of players who will draft"); @@ -385,11 +391,15 @@ public class NewTournamentDialog extends MageDialog { .addComponent(lblNumWins) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(lblQuitRatio) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(spnQuitRatio, javax.swing.GroupLayout.PREFERRED_SIZE, 60, javax.swing.GroupLayout.PREFERRED_SIZE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(lblMinimumRating) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(spnMinimumRating, javax.swing.GroupLayout.PREFERRED_SIZE, 80, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addComponent(chkRated)) .addComponent(cbTournamentType, javax.swing.GroupLayout.PREFERRED_SIZE, 290, javax.swing.GroupLayout.PREFERRED_SIZE))) .addGroup(layout.createSequentialGroup() @@ -443,6 +453,8 @@ public class NewTournamentDialog extends MageDialog { .addComponent(spnNumWins, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(lblQuitRatio) .addComponent(spnQuitRatio, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(lblMinimumRating) + .addComponent(spnMinimumRating, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(chkRated)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) @@ -521,6 +533,7 @@ public class NewTournamentDialog extends MageDialog { tOptions.setWatchingAllowed(cbAllowSpectators.isSelected()); tOptions.setPlaneChase(cbPlaneChase.isSelected()); tOptions.setQuitRatio((Integer) spnQuitRatio.getValue()); + tOptions.setMinimumRating((Integer) spnMinimumRating.getValue()); for (TournamentPlayerPanel player : players) { tOptions.getPlayerTypes().add((PlayerType) player.getPlayerType().getSelectedItem()); } @@ -595,6 +608,9 @@ public class NewTournamentDialog extends MageDialog { tOptions.getMatchOptions().setLimited(false); } + String serverAddress = SessionHandler.getSession().getServerHostname().orElseGet(() -> ""); + tOptions.getMatchOptions().setBannedUsers(IgnoreList.ignoreList(serverAddress)); + tOptions.getMatchOptions().setMatchTimeLimit((MatchTimeLimit) this.cbTimeLimit.getSelectedItem()); tOptions.getMatchOptions().setSkillLevel((SkillLevel) this.cbSkillLevel.getSelectedItem()); tOptions.getMatchOptions().setWinsNeeded((Integer) this.spnNumWins.getValue()); @@ -1061,6 +1077,7 @@ public class NewTournamentDialog extends MageDialog { this.spnFreeMulligans.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TOURNAMENT_NUMBER_OF_FREE_MULLIGANS + versionStr, "0"))); this.spnNumWins.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TOURNAMENT_NUMBER_OF_WINS + versionStr, "2"))); this.spnQuitRatio.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TOURNAMENT_QUIT_RATIO + versionStr, "100"))); + this.spnMinimumRating.setValue(Integer.parseInt(PreferencesDialog.getCachedValue(PreferencesDialog.KEY_NEW_TOURNAMENT_MINIMUM_RATING + versionStr, "0"))); TournamentTypeView tournamentType = (TournamentTypeView) cbTournamentType.getSelectedItem(); activatePanelElements(tournamentType); @@ -1146,6 +1163,7 @@ public class NewTournamentDialog extends MageDialog { PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TOURNAMENT_NUMBER_OF_FREE_MULLIGANS + versionStr, Integer.toString(tOptions.getMatchOptions().getFreeMulligans())); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TOURNAMENT_NUMBER_OF_WINS + versionStr, Integer.toString(tOptions.getMatchOptions().getWinsNeeded())); PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TOURNAMENT_QUIT_RATIO + versionStr, Integer.toString(tOptions.getQuitRatio())); + PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TOURNAMENT_MINIMUM_RATING + versionStr, Integer.toString(tOptions.getMinimumRating())); if (tOptions.getTournamentType().startsWith("Sealed")) { PreferencesDialog.saveValue(PreferencesDialog.KEY_NEW_TOURNAMENT_PACKS_SEALED + versionStr, tOptions.getLimitedOptions().getSetCodes().toString()); @@ -1217,6 +1235,7 @@ public class NewTournamentDialog extends MageDialog { private javax.swing.JLabel lblPassword; private javax.swing.JLabel lblPlayer1; private javax.swing.JLabel lblQuitRatio; + private javax.swing.JLabel lblMinimumRating; private javax.swing.JLabel lblTournamentType; private mage.client.table.NewPlayerPanel player1Panel; private javax.swing.JPanel pnlDraftOptions; @@ -1231,6 +1250,7 @@ public class NewTournamentDialog extends MageDialog { private javax.swing.JSpinner spnNumRounds; private javax.swing.JSpinner spnNumWins; private javax.swing.JSpinner spnQuitRatio; + private javax.swing.JSpinner spnMinimumRating; private javax.swing.JTextField txtName; private javax.swing.JTextField txtPassword; private org.jdesktop.beansbinding.BindingGroup bindingGroup; diff --git a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java index 4d595a005a8..5826d2c85b3 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java @@ -222,6 +222,7 @@ public class PreferencesDialog extends javax.swing.JDialog { public static final String KEY_NEW_TABLE_NUMBER_PLAYERS = "newTableNumberPlayers"; public static final String KEY_NEW_TABLE_PLAYER_TYPES = "newTablePlayerTypes"; public static final String KEY_NEW_TABLE_QUIT_RATIO = "newTableQuitRatio"; + public static final String KEY_NEW_TABLE_MINIMUM_RATING = "newTableMinimumRating"; public static final String KEY_NEW_TABLE_RATED = "newTableRated"; // pref setting for new tournament dialog @@ -243,6 +244,7 @@ public class PreferencesDialog extends javax.swing.JDialog { public static final String KEY_NEW_TOURNAMENT_ALLOW_ROLLBACKS = "newTournamentAllowRollbacks"; public static final String KEY_NEW_TOURNAMENT_DECK_FILE = "newTournamentDeckFile"; public static final String KEY_NEW_TOURNAMENT_QUIT_RATIO = "newTournamentQuitRatio"; + public static final String KEY_NEW_TOURNAMENT_MINIMUM_RATING = "newTournamentMinimumRating"; public static final String KEY_NEW_TOURNAMENT_RATED = "newTournamentRated"; // pref setting for deck generator diff --git a/Mage.Client/src/main/java/mage/client/plugins/impl/Plugins.java b/Mage.Client/src/main/java/mage/client/plugins/impl/Plugins.java index d9f1fef14ff..1731b0b656d 100644 --- a/Mage.Client/src/main/java/mage/client/plugins/impl/Plugins.java +++ b/Mage.Client/src/main/java/mage/client/plugins/impl/Plugins.java @@ -26,6 +26,8 @@ import mage.view.CardView; import mage.view.PermanentView; import net.xeoh.plugins.base.PluginManager; import net.xeoh.plugins.base.impl.PluginManagerFactory; +import net.xeoh.plugins.base.util.uri.ClassURI; + import org.apache.log4j.Logger; import org.mage.plugins.card.CardPluginImpl; import static org.mage.plugins.card.utils.CardImageUtils.getImagesDir; @@ -46,13 +48,15 @@ public enum Plugins implements MagePlugins { @Override public void loadPlugins() { - LOGGER.info("Loading plugins..."); pm = PluginManagerFactory.createPluginManager(); pm.addPluginsFrom(new File(PLUGINS_DIRECTORY + File.separator).toURI()); - this.cardPlugin = new CardPluginImpl(); + pm.addPluginsFrom(new ClassURI(CardPluginImpl.class).toURI()); + pm.addPluginsFrom(new ClassURI(ThemePluginImpl.class).toURI()); + + this.cardPlugin = pm.getPlugin(CardPlugin.class); this.counterPlugin = pm.getPlugin(CounterPlugin.class); - this.themePlugin = new ThemePluginImpl(); + this.themePlugin = pm.getPlugin(ThemePlugin.class); LOGGER.info("Done."); } diff --git a/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java b/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java index f71b1225915..f3bc3dc5d20 100644 --- a/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java +++ b/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java @@ -214,7 +214,7 @@ public class CallbackClientImpl implements CallbackClient { case GAME_CHOOSE_ABILITY: { GamePanel panel = MageFrame.getGame(callback.getObjectId()); if (panel != null) { - appendJsonEvent("GAME_CHOOSE_PILE", callback.getObjectId(), callback.getData()); + appendJsonEvent("GAME_CHOOSE_ABILITY", callback.getObjectId(), callback.getData()); panel.pickAbility((AbilityPickerView) callback.getData()); } break; diff --git a/Mage.Client/src/main/java/mage/client/table/TablesPanel.java b/Mage.Client/src/main/java/mage/client/table/TablesPanel.java index d28badf2f79..59963ff2999 100644 --- a/Mage.Client/src/main/java/mage/client/table/TablesPanel.java +++ b/Mage.Client/src/main/java/mage/client/table/TablesPanel.java @@ -1,163 +1,193 @@ - - /* - * TablesPanel.java - * - * Created on 15-Dec-2009, 10:54:01 PM - */ -package mage.client.table; + * TablesPanel.java + * + * Created on 15-Dec-2009, 10:54:01 PM + */ + package mage.client.table; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.beans.PropertyVetoException; -import java.io.File; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.*; -import java.util.concurrent.CancellationException; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import javax.swing.*; -import javax.swing.table.AbstractTableModel; -import javax.swing.table.DefaultTableCellRenderer; -import javax.swing.table.TableCellRenderer; -import mage.cards.decks.importer.DeckImporterUtil; -import mage.client.MageFrame; -import mage.client.SessionHandler; -import mage.client.chat.ChatPanelBasic; -import mage.client.components.MageComponents; -import mage.client.dialog.*; -import static mage.client.dialog.PreferencesDialog.KEY_TABLES_COLUMNS_ORDER; -import static mage.client.dialog.PreferencesDialog.KEY_TABLES_COLUMNS_WIDTH; -import static mage.client.dialog.PreferencesDialog.KEY_TABLES_FILTER_SETTINGS; -import static mage.client.dialog.PreferencesDialog.KEY_TABLES_DIVIDER_LOCATION_1; -import static mage.client.dialog.PreferencesDialog.KEY_TABLES_DIVIDER_LOCATION_2; -import static mage.client.dialog.PreferencesDialog.KEY_TABLES_DIVIDER_LOCATION_3; -import mage.client.util.ButtonColumn; -import mage.client.util.GUISizeHelper; -import mage.client.util.IgnoreList; -import mage.client.util.MageTableRowSorter; -import mage.client.util.URLHandler; -import mage.client.util.gui.GuiDisplayUtil; -import mage.client.util.gui.TableUtil; -import mage.constants.*; -import mage.game.match.MatchOptions; -import mage.players.PlayerType; -import mage.remote.MageRemoteException; -import mage.view.MatchView; -import mage.view.RoomUsersView; -import mage.view.TableView; -import mage.view.UserRequestMessage; -import org.apache.log4j.Logger; -import org.ocpsoft.prettytime.Duration; -import org.ocpsoft.prettytime.PrettyTime; -import org.ocpsoft.prettytime.units.JustNow; + import mage.cards.decks.importer.DeckImporterUtil; + import mage.client.MageFrame; + import mage.client.SessionHandler; + import mage.client.chat.ChatPanelBasic; + import mage.client.components.MageComponents; + import mage.client.dialog.*; + import mage.client.util.*; + import mage.client.util.gui.GuiDisplayUtil; + import mage.client.util.gui.TableUtil; + import mage.constants.*; + import mage.game.match.MatchOptions; + import mage.players.PlayerType; + import mage.remote.MageRemoteException; + import mage.view.MatchView; + import mage.view.RoomUsersView; + import mage.view.TableView; + import mage.view.UserRequestMessage; + import org.apache.log4j.Logger; + import org.mage.card.arcane.CardRendererUtils; + import org.ocpsoft.prettytime.Duration; + import org.ocpsoft.prettytime.PrettyTime; + import org.ocpsoft.prettytime.units.JustNow; -/** - * - * @author BetaSteward_at_googlemail.com - */ -public class TablesPanel extends javax.swing.JPanel { + import javax.swing.*; + import javax.swing.border.EmptyBorder; + import javax.swing.table.AbstractTableModel; + import javax.swing.table.DefaultTableCellRenderer; + import javax.swing.table.TableCellRenderer; + import java.awt.*; + import java.awt.event.ActionEvent; + import java.awt.event.MouseAdapter; + import java.awt.event.MouseEvent; + import java.beans.PropertyVetoException; + import java.io.File; + import java.text.DateFormat; + import java.text.SimpleDateFormat; + import java.util.*; + import java.util.concurrent.CancellationException; + import java.util.concurrent.ExecutionException; + import java.util.concurrent.Executors; + import java.util.concurrent.TimeUnit; - private static final Logger LOGGER = Logger.getLogger(TablesPanel.class); - private static final int[] DEFAULT_COLUMNS_WIDTH = {35, 150, 120, 180, 80, 120, 80, 60, 40, 40, 60}; + import static mage.client.dialog.PreferencesDialog.*; - private final TableTableModel tableModel; - private final MatchesTableModel matchesModel; - private UUID roomId; - private UpdateTablesTask updateTablesTask; - private UpdatePlayersTask updatePlayersTask; - private UpdateMatchesTask updateMatchesTask; - private JoinTableDialog joinTableDialog; - private NewTableDialog newTableDialog; - private NewTournamentDialog newTournamentDialog; - private final GameChooser gameChooser; - private java.util.List messages; - private int currentMessage; - private final MageTableRowSorter activeTablesSorter; - private final MageTableRowSorter completedTablesSorter; + /** + * @author BetaSteward_at_googlemail.com + */ + public class TablesPanel extends javax.swing.JPanel { - private final ButtonColumn actionButton1; - private final ButtonColumn actionButton2; + private static final Logger LOGGER = Logger.getLogger(TablesPanel.class); + private static final int[] DEFAULT_COLUMNS_WIDTH = {35, 150, 120, 180, 80, 120, 80, 60, 40, 40, 60}; - final JToggleButton[] filterButtons; + private final TableTableModel tableModel; + private final MatchesTableModel matchesModel; + private UUID roomId; + private UpdateTablesTask updateTablesTask; + private UpdatePlayersTask updatePlayersTask; + private UpdateMatchesTask updateMatchesTask; + private JoinTableDialog joinTableDialog; + private NewTableDialog newTableDialog; + private NewTournamentDialog newTournamentDialog; + private final GameChooser gameChooser; + private java.util.List messages; + private int currentMessage; + private final MageTableRowSorter activeTablesSorter; + private final MageTableRowSorter completedTablesSorter; - // time formater - private PrettyTime timeFormater = new PrettyTime(); + private final ButtonColumn actionButton1; + private final ButtonColumn actionButton2; - // time ago renderer - TableCellRenderer timeAgoCellRenderer = new DefaultTableCellRenderer() { - @Override - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); - Date d = (Date) value; - label.setText(timeFormater.format(d)); - return label; - } - }; + final JToggleButton[] filterButtons; - // duration renderer - TableCellRenderer durationCellRenderer = new DefaultTableCellRenderer() { - @Override - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); - Long ms = (Long) value; + // time formater + private PrettyTime timeFormater = new PrettyTime(); - if (ms != 0) { - Duration dur = timeFormater.approximateDuration(new Date(ms)); - label.setText((timeFormater.formatDuration(dur))); - } else { - label.setText(""); - } - return label; - } - }; + // time ago renderer + TableCellRenderer timeAgoCellRenderer = new DefaultTableCellRenderer() { + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + Date d = (Date) value; + label.setText(timeFormater.format(d)); + return label; + } + }; - // datetime render - TableCellRenderer datetimeCellRenderer = new DefaultTableCellRenderer() { - DateFormat datetimeFormater = new SimpleDateFormat("HH:mm:ss"); + // duration renderer + TableCellRenderer durationCellRenderer = new DefaultTableCellRenderer() { + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + Long ms = (Long) value; - @Override - public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { - JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); - Date d = (Date) value; - if (d != null) { - label.setText(datetimeFormater.format(d)); - } else { - label.setText(""); - } + if (ms != 0) { + Duration dur = timeFormater.approximateDuration(new Date(ms)); + label.setText((timeFormater.formatDuration(dur))); + } else { + label.setText(""); + } + return label; + } + }; - return label; - } - }; + // datetime render + TableCellRenderer datetimeCellRenderer = new DefaultTableCellRenderer() { + DateFormat datetimeFormater = new SimpleDateFormat("HH:mm:ss"); - /** - * Creates new form TablesPanel - */ - public TablesPanel() { + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + Date d = (Date) value; + if (d != null) { + label.setText(datetimeFormater.format(d)); + } else { + label.setText(""); + } - tableModel = new TableTableModel(); - matchesModel = new MatchesTableModel(); - gameChooser = new GameChooser(); + return label; + } + }; - initComponents(); - // tableModel.setSession(session); + // skill renderer + TableCellRenderer skillCellRenderer = new DefaultTableCellRenderer() { - // formater - timeFormater.setLocale(Locale.ENGLISH); - JustNow jn = timeFormater.getUnit(JustNow.class); - jn.setMaxQuantity(1000L * 30L); // 30 seconds gap (show "just now" from 0 to 30 secs) + // base panel to render + private JPanel renderPanel = new JPanel(); + private ImageIcon skillIcon = new ImageIcon(this.getClass().getResource("/info/yellow_star_16.png")); - // 1. TABLE CURRENT - tableTables.createDefaultColumnsFromModel(); - activeTablesSorter = new MageTableRowSorter(tableModel); - tableTables.setRowSorter(activeTablesSorter); + @Override + public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { + + // get table text cell settings + DefaultTableCellRenderer baseRenderer = (DefaultTableCellRenderer) table.getDefaultRenderer(String.class); + JLabel baseComp = (JLabel) baseRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + String skillCode = baseComp.getText(); + + // apply settings to render panel from parent + renderPanel.setOpaque(baseComp.isOpaque()); + renderPanel.setForeground(CardRendererUtils.copyColor(baseComp.getForeground())); + renderPanel.setBackground(CardRendererUtils.copyColor(baseComp.getBackground())); + renderPanel.setBorder(baseComp.getBorder()); + + // create each skill symbol as child label + renderPanel.removeAll(); + renderPanel.setLayout(new BoxLayout(renderPanel, BoxLayout.X_AXIS)); + for (char skillSymbol : skillCode.toCharArray()) { + JLabel symbolLabel = new JLabel(); + symbolLabel.setBorder(new EmptyBorder(0, 3, 0, 0)); + symbolLabel.setIcon(skillIcon); + renderPanel.add(symbolLabel); + } + + return renderPanel; + } + }; + + /** + * Creates new form TablesPanel + */ + public TablesPanel() { + + tableModel = new TableTableModel(); + matchesModel = new MatchesTableModel(); + gameChooser = new GameChooser(); + + initComponents(); + // tableModel.setSession(session); + + // formater + timeFormater.setLocale(Locale.ENGLISH); + JustNow jn = timeFormater.getUnit(JustNow.class); + jn.setMaxQuantity(1000L * 30L); // 30 seconds gap (show "just now" from 0 to 30 secs) + + // 1. TABLE CURRENT + tableTables.createDefaultColumnsFromModel(); + activeTablesSorter = new MageTableRowSorter(tableModel); + tableTables.setRowSorter(activeTablesSorter); + + // time ago + tableTables.getColumnModel().getColumn(TableTableModel.COLUMN_CREATED).setCellRenderer(timeAgoCellRenderer); + // skill level + tableTables.getColumnModel().getColumn(TableTableModel.COLUMN_SKILL).setCellRenderer(skillCellRenderer); - // time ago - tableTables.getColumnModel().getColumn(TableTableModel.COLUMN_CREATED).setCellRenderer(timeAgoCellRenderer); /* date sorter (not need, default is good - see getColumnClass) activeTablesSorter.setComparator(TableTableModel.COLUMN_CREATED, new Comparator() { @Override @@ -166,6 +196,7 @@ public class TablesPanel extends javax.swing.JPanel { } });*/ + // default sort by created date (last games from above) ArrayList list = new ArrayList(); list.add(new RowSorter.SortKey(TableTableModel.COLUMN_CREATED, SortOrder.DESCENDING)); @@ -322,17 +353,22 @@ public class TablesPanel extends javax.swing.JPanel { addTableDoubleClickListener(tableCompleted, closedTableAction); } - private void addTableDoubleClickListener(JTable table, Action action) { - table.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - int row = table.rowAtPoint(e.getPoint()); - if (e.getClickCount() == 2 && row != -1) { - action.actionPerformed(new ActionEvent(e.getSource(), e.getID(), "" + row)); - } - } - }); - } + private void addTableDoubleClickListener(JTable table, Action action) { + table.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.getClickCount() == 2) { + int selRow = table.getSelectedRow(); + if (selRow != -1) { + int dataRow = table.convertRowIndexToModel(selRow); + if (dataRow != -1) { + action.actionPerformed(new ActionEvent(e.getSource(), e.getID(), "" + dataRow)); + } + } + } + } + }); + } public void cleanUp() { saveGuiSettings(); @@ -620,15 +656,16 @@ public class TablesPanel extends javax.swing.JPanel { formatFilterList.add(RowFilter.regexFilter("^Momir Basic|^Constructed - Pauper|^Constructed - Frontier|^Constructed - Extended|^Constructed - Eternal|^Constructed - Historical|^Constructed - Super|^Constructed - Freeform|^Australian Highlander|^Canadian Highlander|^Constructed - Old", TableTableModel.COLUMN_DECK_TYPE)); } + // skill java.util.List> skillFilterList = new ArrayList<>(); if (btnSkillBeginner.isSelected()) { - skillFilterList.add(RowFilter.regexFilter(SkillLevel.BEGINNER.toString(), TableTableModel.COLUMN_SKILL)); + skillFilterList.add(RowFilter.regexFilter(this.tableModel.getSkillLevelAsCode(SkillLevel.BEGINNER, true), TableTableModel.COLUMN_SKILL)); } - if (btnSkillCasual.isSelected()) { - skillFilterList.add(RowFilter.regexFilter(SkillLevel.CASUAL.toString(), TableTableModel.COLUMN_SKILL)); + if (btnSkillCasual.isSelected()) { + skillFilterList.add(RowFilter.regexFilter(this.tableModel.getSkillLevelAsCode(SkillLevel.CASUAL, true), TableTableModel.COLUMN_SKILL)); } if (btnSkillSerious.isSelected()) { - skillFilterList.add(RowFilter.regexFilter(SkillLevel.SERIOUS.toString(), TableTableModel.COLUMN_SKILL)); + skillFilterList.add(RowFilter.regexFilter(this.tableModel.getSkillLevelAsCode(SkillLevel.SERIOUS, true), TableTableModel.COLUMN_SKILL)); } String ratedMark = TableTableModel.RATED_VALUE_YES; @@ -1221,6 +1258,7 @@ public class TablesPanel extends javax.swing.JPanel { options.setSkillLevel(SkillLevel.CASUAL); options.setRollbackTurnsAllowed(true); options.setQuitRatio(100); + options.setMinimumRating(0); String serverAddress = SessionHandler.getSession().getServerHostname().orElseGet(() -> ""); options.setBannedUsers(IgnoreList.ignoreList(serverAddress)); table = SessionHandler.createTable(roomId, options); @@ -1335,14 +1373,15 @@ class TableTableModel extends AbstractTableModel { public static final int COLUMN_SKILL = 8; public static final int COLUMN_RATING = 9; public static final int COLUMN_QUIT_RATIO = 10; - public static final int ACTION_COLUMN = 11; // column the action is located (starting with 0) + public static final int COLUMN_MINIMUM_RATING = 11; + public static final int ACTION_COLUMN = 12; // column the action is located (starting with 0) public static final String RATED_VALUE_YES = "YES"; public static final String RATED_VALUE_NO = ""; public static final String PASSWORD_VALUE_YES = "YES"; - private final String[] columnNames = new String[]{"M/T", "Deck Type", "Owner / Players", "Game Type", "Info", "Status", "Password", "Created / Started", "Skill Level", "Rating", "Quit %", "Action"}; + private final String[] columnNames = new String[]{"M/T", "Deck Type", "Owner / Players", "Game Type", "Info", "Status", "Password", "Created / Started", "Skill Level", "Rated", "Quit %", "Min Rating", "Action"}; private TableView[] tables = new TableView[0]; @@ -1354,6 +1393,31 @@ class TableTableModel extends AbstractTableModel { this.fireTableDataChanged(); } + public String getSkillLevelAsCode(SkillLevel skill, boolean asRegExp) { + String res; + switch (skill) { + case BEGINNER: + res = "*"; + break; + case CASUAL: + res = "**"; + break; + case SERIOUS: + res = "***"; + break; + default: + res = ""; + break; + } + + // regexp format for search table rows + if (asRegExp) { + res = String.format("^%s$", res.replace("*", "\\*")); + } + + return res; + } + @Override public int getRowCount() { return tables.length; @@ -1384,12 +1448,14 @@ class TableTableModel extends AbstractTableModel { case 7: return tables[arg0].getCreateTime(); // use cell render, not format here case 8: - return tables[arg0].getSkillLevel(); + return this.getSkillLevelAsCode(tables[arg0].getSkillLevel(), false); case 9: return tables[arg0].isRated() ? RATED_VALUE_YES : RATED_VALUE_NO; case 10: return tables[arg0].getQuitRatio(); case 11: + return tables[arg0].getMinimumRating(); + case 12: switch (tables[arg0].getTableState()) { case WAITING: @@ -1419,14 +1485,14 @@ class TableTableModel extends AbstractTableModel { default: return ""; } - case 12: - return tables[arg0].isTournament(); case 13: + return tables[arg0].isTournament(); + case 14: if (!tables[arg0].getGames().isEmpty()) { return tables[arg0].getGames().get(0); } return null; - case 14: + case 15: return tables[arg0].getTableId(); } return ""; diff --git a/Mage.Client/src/main/java/mage/client/util/Config.java b/Mage.Client/src/main/java/mage/client/util/Config.java index 466f2ad08c4..459ee469b99 100644 --- a/Mage.Client/src/main/java/mage/client/util/Config.java +++ b/Mage.Client/src/main/java/mage/client/util/Config.java @@ -1,4 +1,3 @@ - package mage.client.util; import java.io.File; @@ -33,38 +32,41 @@ public final class Config { static { Properties p = new Properties(); - try(FileInputStream fis =new FileInputStream(new File("config/config.properties"))) { + boolean fileFound = true; + try (FileInputStream fis = new FileInputStream(new File("config/config.properties"))) { p.load(fis); } catch (IOException ex) { - logger.fatal("Config error ", ex); + fileFound = false; } - serverName = p.getProperty("server-name"); - port = Integer.parseInt(p.getProperty("port")); - remoteServer = p.getProperty("remote-server"); - cardScalingFactor = Double.valueOf(p.getProperty("card-scaling-factor")); - cardScalingFactorEnlarged = Double.valueOf(p.getProperty("card-scaling-factor-enlarged")); - handScalingFactor = Double.valueOf(p.getProperty("hand-scaling-factor")); - defaultGameType = p.getProperty("default-game-type", "Human"); - defaultDeckPath = p.getProperty("default-deck-path"); - defaultOtherPlayerIndex = p.getProperty("default-other-player-index"); - defaultComputerName = p.getProperty("default-computer-name"); + if (fileFound) { + serverName = p.getProperty("server-name"); + port = Integer.parseInt(p.getProperty("port")); + remoteServer = p.getProperty("remote-server"); + cardScalingFactor = Double.valueOf(p.getProperty("card-scaling-factor")); + cardScalingFactorEnlarged = Double.valueOf(p.getProperty("card-scaling-factor-enlarged")); + handScalingFactor = Double.valueOf(p.getProperty("hand-scaling-factor")); + defaultGameType = p.getProperty("default-game-type", "Human"); + defaultDeckPath = p.getProperty("default-deck-path"); + defaultOtherPlayerIndex = p.getProperty("default-other-player-index"); + defaultComputerName = p.getProperty("default-computer-name"); - dimensions = new CardDimensions(cardScalingFactor); - dimensionsEnlarged = new CardDimensions(cardScalingFactorEnlarged); -// activate instead this part, to run the UI editor for some panels without error -// serverName = "localhost"; -// port = 17171; -// remoteServer = "mage-server"; -// cardScalingFactor = 0.4; -// cardScalingFactorEnlarged = 0.5; -// handScalingFactor = 1.3; -// defaultGameType = p.getProperty("default-game-type", "Human"); -// defaultDeckPath = ""; -// defaultOtherPlayerIndex = "1"; -// defaultComputerName = "Computer"; -// -// dimensions = new CardDimensions(cardScalingFactor); -// dimensionsEnlarged = new CardDimensions(cardScalingFactorEnlarged); + dimensions = new CardDimensions(cardScalingFactor); + dimensionsEnlarged = new CardDimensions(cardScalingFactorEnlarged); + } else { // Take some default valies for netbeans design view + serverName = "localhost"; + port = 17171; + remoteServer = "mage-server"; + cardScalingFactor = 0.4; + cardScalingFactorEnlarged = 0.5; + handScalingFactor = 1.3; + defaultGameType = p.getProperty("default-game-type", "Human"); + defaultDeckPath = ""; + defaultOtherPlayerIndex = "1"; + defaultComputerName = "AI Computer"; + + dimensions = new CardDimensions(cardScalingFactor); + dimensionsEnlarged = new CardDimensions(cardScalingFactorEnlarged); + } } diff --git a/Mage.Client/src/main/java/mage/client/util/IgnoreList.java b/Mage.Client/src/main/java/mage/client/util/IgnoreList.java index 89906031fa7..3fbabab31d9 100644 --- a/Mage.Client/src/main/java/mage/client/util/IgnoreList.java +++ b/Mage.Client/src/main/java/mage/client/util/IgnoreList.java @@ -9,8 +9,8 @@ import mage.view.ChatMessage; public final class IgnoreList { - private static final String USAGE = "
\\ignore - shows current ignore list on this server." - + "
\\ignore [username] - add a username to your ignore list on this server." + private static final String USAGE = "
\\ignore - shows your ignore list on this server." + + "
\\ignore [username] - add username to ignore list (they won't be able to chat or join to your game)." + "
\\unignore [username] - remove a username from your ignore list on this server.
"; public static final int MAX_IGNORE_LIST_SIZE = 50; diff --git a/Mage.Client/src/main/java/mage/client/util/sets/ConstructedFormats.java b/Mage.Client/src/main/java/mage/client/util/sets/ConstructedFormats.java index 93efaaafba4..ad1351b7f89 100644 --- a/Mage.Client/src/main/java/mage/client/util/sets/ConstructedFormats.java +++ b/Mage.Client/src/main/java/mage/client/util/sets/ConstructedFormats.java @@ -9,6 +9,8 @@ import java.util.Map; import mage.cards.repository.ExpansionInfo; import mage.cards.repository.ExpansionRepository; import mage.constants.SetType; +import static mage.constants.SetType.EXPANSION; +import static mage.constants.SetType.SUPPLEMENTAL; import mage.deck.Standard; /** @@ -64,6 +66,13 @@ public final class ConstructedFormats { underlyingSetCodesPerFormat.put(CUSTOM, new ArrayList<>()); final Map expansionInfo = new HashMap<>(); formats.clear(); // prevent NPE on sorting if this is not the first try + + // Because this is also called in Netbeans Design view, but the object does not exist in that case, + // we have to return here to prevent exception in design view. (Does not hurt at design time) + if (!ExpansionRepository.instance.instanceInitialized) { + return; + } + for (ExpansionInfo set : ExpansionRepository.instance.getAll()) { expansionInfo.put(set.getName(), set); formats.add(set.getName()); diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/CardRendererUtils.java b/Mage.Client/src/main/java/org/mage/card/arcane/CardRendererUtils.java index 3702f176cb2..f32c08e972d 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/CardRendererUtils.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/CardRendererUtils.java @@ -1,8 +1,3 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ package org.mage.card.arcane; import java.awt.*; @@ -63,26 +58,26 @@ public final class CardRendererUtils { int plus_b = (int) ((255 - b) / 2); return new Color(r + plus_r, - g + plus_g, - b + plus_b, - alpha); + g + plus_g, + b + plus_b, + alpha); } - + public static Color abitdarker(Color c) { int r = c.getRed(); int g = c.getGreen(); int b = c.getBlue(); int alpha = c.getAlpha(); - int plus_r = (int) (Math.min (255 - r, r) / 2); - int plus_g = (int) (Math.min (255 - g, g) / 2); - int plus_b = (int) (Math.min (255 - b, b) / 2); + int plus_r = (int) (Math.min(255 - r, r) / 2); + int plus_g = (int) (Math.min(255 - g, g) / 2); + int plus_b = (int) (Math.min(255 - b, b) / 2); return new Color(r - plus_r, - g - plus_g, - b - plus_b, - alpha); - } + g - plus_g, + b - plus_b, + alpha); + } // Draw a rounded box with a 2-pixel border // Used on various card parts. @@ -192,4 +187,12 @@ public final class CardRendererUtils { .replaceAll("", "") .replaceAll("", ""); } + + public static Color copyColor(Color color) { + if (color != null) { + return new Color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()); + } else { + return null; + } + } } diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/ManaSymbolsCellRenderer.java b/Mage.Client/src/main/java/org/mage/card/arcane/ManaSymbolsCellRenderer.java index 46a0e3f1c2c..bd9731ec6a4 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/ManaSymbolsCellRenderer.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/ManaSymbolsCellRenderer.java @@ -9,10 +9,13 @@ import java.awt.*; import java.awt.image.BufferedImage; import java.util.StringTokenizer; +/** + * @author JayDi85 + */ public final class ManaSymbolsCellRenderer extends DefaultTableCellRenderer { // base panel to render - private JPanel manaPanel = new JPanel(); + private JPanel renderPanel = new JPanel(); @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, @@ -20,47 +23,47 @@ public final class ManaSymbolsCellRenderer extends DefaultTableCellRenderer { // get table text cell settings DefaultTableCellRenderer baseRenderer = (DefaultTableCellRenderer) table.getDefaultRenderer(String.class); - JLabel baseLabel = (JLabel)baseRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); + JLabel baseComp = (JLabel) baseRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); // apply settings to mana panel from parent - manaPanel.setOpaque(baseLabel.isOpaque()); - manaPanel.setForeground(baseLabel.getForeground()); - manaPanel.setBackground(baseLabel.getBackground()); + renderPanel.setOpaque(baseComp.isOpaque()); + renderPanel.setForeground(CardRendererUtils.copyColor(baseComp.getForeground())); + renderPanel.setBackground(CardRendererUtils.copyColor(baseComp.getBackground())); + renderPanel.setBorder(baseComp.getBorder()); // icons size with margin int symbolWidth = GUISizeHelper.symbolTableSize; int symbolHorizontalMargin = 2; // create each mana symbol as child label - String manaCost = (String)value; - manaPanel.removeAll(); - manaPanel.setLayout(new BoxLayout(manaPanel, BoxLayout.X_AXIS)); - if(manaCost != null){ + String manaCost = (String) value; + renderPanel.removeAll(); + renderPanel.setLayout(new BoxLayout(renderPanel, BoxLayout.X_AXIS)); + if (manaCost != null) { StringTokenizer tok = new StringTokenizer(manaCost, " "); while (tok.hasMoreTokens()) { String symbol = tok.nextToken(); JLabel symbolLabel = new JLabel(); //symbolLabel.setBorder(new LineBorder(new Color(150, 150, 150))); // debug - symbolLabel.setBorder(new EmptyBorder(0, symbolHorizontalMargin,0, 0)); + symbolLabel.setBorder(new EmptyBorder(0, symbolHorizontalMargin, 0, 0)); BufferedImage image = ManaSymbols.getSizedManaSymbol(symbol, symbolWidth); - if (image != null){ + if (image != null) { // icon symbolLabel.setIcon(new ImageIcon(image)); - }else - { + } else { // text symbolLabel.setText("{" + symbol + "}"); - symbolLabel.setOpaque(baseLabel.isOpaque()); - symbolLabel.setForeground(baseLabel.getForeground()); - symbolLabel.setBackground(baseLabel.getBackground()); + symbolLabel.setOpaque(baseComp.isOpaque()); + symbolLabel.setForeground(baseComp.getForeground()); + symbolLabel.setBackground(baseComp.getBackground()); } - manaPanel.add(symbolLabel); + renderPanel.add(symbolLabel); } } - return manaPanel; + return renderPanel; } } diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSource.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSource.java index 7f2bc5825f2..fa6dc551c34 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSource.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/ScryfallImageSource.java @@ -231,11 +231,15 @@ public enum ScryfallImageSource implements CardImageSource { supportedSets.add("GS1"); supportedSets.add("GRN"); supportedSets.add("GK1"); + supportedSets.add("GNT"); + supportedSets.add("UMA"); + supportedSets.add("PUMA"); // supportedSets.add("EURO"); supportedSets.add("GPX"); supportedSets.add("ATH"); supportedSets.add("GRC"); + supportedSets.add("ANA"); } @Override @@ -246,7 +250,9 @@ public enum ScryfallImageSource implements CardImageSource { String localizedCode = languageAliases.getOrDefault(preferredLanguage, defaultCode); // loc example: https://api.scryfall.com/cards/xln/121/ru?format=image - // TODO: do not use API at all? It's can help with scryfall request limits (1 request instead 2) + // WARNING, some cards haven't direct images and uses random GUID: + // As example: Raging Ravine - https://scryfall.com/card/uma/249/raging-ravine + // https://img.scryfall.com/cards/large/front/5/4/54f41726-e0bb-4154-a2db-4b68b50f5032.jpg String baseUrl = null; String alternativeUrl = null; @@ -268,12 +274,19 @@ public enum ScryfallImageSource implements CardImageSource { } } - // special card number like "103a" already compatible + // special card number like "103a" and "U123" already compatible if (baseUrl == null && card.isCollectorIdWithStr()) { - baseUrl = "https://img.scryfall.com/cards/large/" + localizedCode + "/" + formatSetName(card.getSet()) + "/" - + card.getCollectorId() + ".jpg"; - alternativeUrl = "https://img.scryfall.com/cards/large/" + defaultCode + "/" + formatSetName(card.getSet()) + "/" - + card.getCollectorId() + ".jpg"; + // WARNING, after 2018 it's not compatible and some new sets have GUID files instead card numbers + // TODO: replace card number links to API calls (need test with lands, alternative images and double faces), replace not working images by direct links + if (card.getCollectorId().startsWith("U")) { + // fix for Ultimate Box Topper (PUMA) -- need to use API + // ignored and go to API call at the end + } else { + baseUrl = "https://img.scryfall.com/cards/large/" + localizedCode + "/" + formatSetName(card.getSet()) + "/" + + card.getCollectorId() + ".jpg"; + alternativeUrl = "https://img.scryfall.com/cards/large/" + defaultCode + "/" + formatSetName(card.getSet()) + "/" + + card.getCollectorId() + ".jpg"; + } } // double faced cards do not supports by API (need direct link for img) diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/images/ImageCache.java b/Mage.Client/src/main/java/org/mage/plugins/card/images/ImageCache.java index ffe80ecdf55..2edf005832f 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/images/ImageCache.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/images/ImageCache.java @@ -409,6 +409,7 @@ public final class ImageCache { // legitimate, happens when a card has no image return null; } catch (ComputationException ex) { + // too low memory if (ex.getCause() instanceof NullPointerException) { return null; } diff --git a/Mage.Client/src/main/resources/card-pictures-tok.txt b/Mage.Client/src/main/resources/card-pictures-tok.txt index 05988555120..d6fb91a0d8c 100644 --- a/Mage.Client/src/main/resources/card-pictures-tok.txt +++ b/Mage.Client/src/main/resources/card-pictures-tok.txt @@ -105,6 +105,8 @@ |Generate|PLANE:PCA|Plane - Truga Jungle|||TrugaJunglePlane| |Generate|PLANE:PCA|Plane - Turri Island|||TurriIslandPlane| |Generate|PLANE:PCA|Plane - Undercity Reaches|||UndercityReachesPlane| +|Generate|TOK:ANA|Goblin|||GoblinToken| +|Generate|TOK:ANA|Spirit|||SpiritWhiteToken| |Generate|TOK:PCA|Eldrazi|||EldraziAnnihilatorToken| |Generate|TOK:10E|Ape|||PongifyApeToken| |Generate|TOK:10E|Dragon|||DragonToken2| diff --git a/Mage.Client/src/main/resources/info/yellow_star_16.png b/Mage.Client/src/main/resources/info/yellow_star_16.png new file mode 100644 index 00000000000..849916980af Binary files /dev/null and b/Mage.Client/src/main/resources/info/yellow_star_16.png differ diff --git a/Mage.Client/src/main/resources/info/yellow_star_24.png b/Mage.Client/src/main/resources/info/yellow_star_24.png new file mode 100644 index 00000000000..41d21f49db2 Binary files /dev/null and b/Mage.Client/src/main/resources/info/yellow_star_24.png differ diff --git a/Mage.Client/src/main/resources/info/yellow_star_32.png b/Mage.Client/src/main/resources/info/yellow_star_32.png new file mode 100644 index 00000000000..029025a9a9e Binary files /dev/null and b/Mage.Client/src/main/resources/info/yellow_star_32.png differ diff --git a/Mage.Common/src/main/java/mage/utils/properties/PropertiesUtil.java b/Mage.Common/src/main/java/mage/utils/properties/PropertiesUtil.java index 0a220e12fdf..17fe10e05b1 100644 --- a/Mage.Common/src/main/java/mage/utils/properties/PropertiesUtil.java +++ b/Mage.Common/src/main/java/mage/utils/properties/PropertiesUtil.java @@ -21,7 +21,11 @@ public final class PropertiesUtil { static { try (InputStream in = PropertiesUtil.class.getResourceAsStream("/xmage.properties")) { - properties.load(in); + if(in != null) { + properties.load(in); + } else { + logger.warn("No xmage.properties were found"); + } } catch (FileNotFoundException fnfe) { logger.warn("No xmage.properties were found on classpath"); } catch (IOException e) { diff --git a/Mage.Common/src/main/java/mage/view/TableView.java b/Mage.Common/src/main/java/mage/view/TableView.java index c3d748c3446..948c7717bf1 100644 --- a/Mage.Common/src/main/java/mage/view/TableView.java +++ b/Mage.Common/src/main/java/mage/view/TableView.java @@ -36,6 +36,7 @@ public class TableView implements Serializable { private List seats = new ArrayList<>(); private List games = new ArrayList<>(); private final String quitRatio; + private final String minimumRating; private final boolean limited; private final boolean rated; private final boolean passworded; @@ -111,6 +112,7 @@ public class TableView implements Serializable { this.additionalInfo = addInfo.toString(); this.skillLevel = table.getMatch().getOptions().getSkillLevel(); this.quitRatio = Integer.toString(table.getMatch().getOptions().getQuitRatio()); + this.minimumRating = Integer.toString(table.getMatch().getOptions().getMinimumRating()); this.limited = table.getMatch().getOptions().isLimited(); this.rated = table.getMatch().getOptions().isRated(); this.passworded = !table.getMatch().getOptions().getPassword().isEmpty(); @@ -159,6 +161,7 @@ public class TableView implements Serializable { this.deckType = table.getDeckType() + ' ' + table.getTournament().getBoosterInfo() + (tableNameInfo != null ? tableNameInfo : ""); this.skillLevel = table.getTournament().getOptions().getMatchOptions().getSkillLevel(); this.quitRatio = Integer.toString(table.getTournament().getOptions().getQuitRatio()); + this.minimumRating = Integer.toString(table.getTournament().getOptions().getMinimumRating()); this.limited = table.getTournament().getOptions().getMatchOptions().isLimited(); this.rated = table.getTournament().getOptions().getMatchOptions().isRated(); this.passworded = !table.getTournament().getOptions().getPassword().isEmpty(); @@ -223,9 +226,9 @@ public class TableView implements Serializable { return skillLevel; } - public String getQuitRatio() { - return quitRatio; - } + public String getQuitRatio() { return quitRatio; } + + public String getMinimumRating() { return minimumRating; } public boolean isLimited() { return limited; diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/AusHighlander.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/AusHighlander.java index 112563f76d0..ed5a331ce34 100644 --- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/AusHighlander.java +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/AusHighlander.java @@ -1,15 +1,15 @@ package mage.deck; -import java.util.HashMap; -import java.util.Map; import mage.cards.ExpansionSet; import mage.cards.Sets; import mage.cards.decks.Constructed; import mage.cards.decks.Deck; import mage.constants.SetType; +import java.util.HashMap; +import java.util.Map; + /** - * * @author spjspj */ public class AusHighlander extends Constructed { @@ -36,9 +36,9 @@ public class AusHighlander extends Constructed { pointMap.put("Dig Through Time", 2); pointMap.put("Library of Alexandria", 2); pointMap.put("Mana Crypt", 2); + pointMap.put("Mind Twist", 2); pointMap.put("Mystical Tutor", 2); pointMap.put("Protean Hulk", 2); - pointMap.put("Skullclamp", 2); pointMap.put("Strip Mine", 2); pointMap.put("Tolarian Academy", 2); pointMap.put("Treasure Cruise", 2); @@ -61,12 +61,12 @@ public class AusHighlander extends Constructed { pointMap.put("Mana Vault", 1); pointMap.put("Memory Jar", 1); pointMap.put("Merchant Scroll", 1); - pointMap.put("Mind Twist", 1); pointMap.put("Mishra’s Workshop", 1); pointMap.put("Natural Order", 1); pointMap.put("Oath of Druids", 1); pointMap.put("Personal Tutor", 1); pointMap.put("Sensei’s Divining Top", 1); + pointMap.put("Skullclamp", 1); pointMap.put("Snapcaster Mage", 1); pointMap.put("Stoneforge Mystic", 1); pointMap.put("Survival of the Fittest", 1); diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/CanadianHighlander.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/CanadianHighlander.java index 23f5c57f2fd..da4955be6ab 100644 --- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/CanadianHighlander.java +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/CanadianHighlander.java @@ -1,15 +1,15 @@ package mage.deck; -import java.util.HashMap; -import java.util.Map; import mage.cards.ExpansionSet; import mage.cards.Sets; import mage.cards.decks.Constructed; import mage.cards.decks.Deck; import mage.constants.SetType; +import java.util.HashMap; +import java.util.Map; + /** - * * @author spjspj */ public class CanadianHighlander extends Constructed { @@ -19,7 +19,7 @@ public class CanadianHighlander extends Constructed { static { pointMap.put("Ancestral Recall", 7); pointMap.put("Balance", 1); - pointMap.put("Birthing Pod", 3); + pointMap.put("Birthing Pod", 2); pointMap.put("Black Lotus", 7); pointMap.put("Demonic Tutor", 3); pointMap.put("Dig Through Time", 1); @@ -27,7 +27,6 @@ public class CanadianHighlander extends Constructed { pointMap.put("Fastbond", 1); pointMap.put("Flash", 7); pointMap.put("Gifts Ungiven", 2); - pointMap.put("Hermit Druid", 1); pointMap.put("Imperial Seal", 1); pointMap.put("Intuition", 1); pointMap.put("Library of Alexandria", 1); @@ -46,6 +45,7 @@ public class CanadianHighlander extends Constructed { pointMap.put("Personal Tutor", 1); pointMap.put("Protean Hulk", 3); pointMap.put("Sol Ring", 3); + pointMap.put("Spellseeker", 1); pointMap.put("Stoneforge Mystic", 1); pointMap.put("Strip Mine", 2); pointMap.put("Summoner's Pact", 2); diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Standard.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Standard.java index 2e2098244a1..e5f19747e3f 100644 --- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Standard.java +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/Standard.java @@ -1,19 +1,13 @@ package mage.deck; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collections; -import java.util.Comparator; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.List; import mage.cards.ExpansionSet; import mage.cards.Sets; import mage.cards.decks.Constructed; import mage.constants.SetType; +import java.util.*; + /** - * * @author BetaSteward_at_googlemail.com */ public class Standard extends Constructed { @@ -23,13 +17,7 @@ public class Standard extends Constructed { setCodes.addAll(makeLegalSets()); - banned.add("Attune with Aether"); // since 2018-01-15 - banned.add("Aetherworks Marvel"); - banned.add("Felidar Guardian"); banned.add("Rampaging Ferocidon"); // since 2018-01-15 - banned.add("Ramunap Ruins"); // since 2018-01-15 - banned.add("Rogue Refiner"); // since 2018-01-15 - banned.add("Smuggler's Copter"); } private static boolean isFallSet(ExpansionSet set) { diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java index 8362963995a..3625c367692 100644 --- a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/ComputerPlayer.java @@ -861,6 +861,19 @@ public class ComputerPlayer extends PlayerImpl implements Player { } return target.isChosen(); } + + if (target.getOriginalTarget() instanceof TargetCardInGraveyardOrBattlefield) { + List cards = new ArrayList<>(); + for (Player player : game.getPlayers().values()) { + cards.addAll(player.getGraveyard().getCards(game)); + cards.addAll(game.getBattlefield().getAllActivePermanents(new FilterPermanent(), player.getId(), game)); + } + Card card = pickTarget(cards, outcome, target, source, game); + if (card != null) { + target.addTarget(card.getId(), source, game); + return true; + } + } throw new IllegalStateException("Target wasn't handled. class:" + target.getClass().toString()); } //end of chooseTarget method @@ -2074,14 +2087,14 @@ public class ComputerPlayer extends PlayerImpl implements Player { int maxScore = RateCard.rateCard(bestCard, chosenColors); int pickedCardRate = RateCard.getCardRating(bestCard); - if (pickedCardRate <= 3) { + if (pickedCardRate <= 30) { // if card is bad // try to counter pick without any color restriction Card counterPick = pickBestCard(cards, null); int counterPickScore = RateCard.getCardRating(counterPick); // card is really good // take it! - if (counterPickScore >= 8) { + if (counterPickScore >= 80) { bestCard = counterPick; maxScore = RateCard.rateCard(bestCard, chosenColors); } diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/utils/RateCard.java b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/utils/RateCard.java index 5197c335365..b31894e48ca 100644 --- a/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/utils/RateCard.java +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/java/mage/player/ai/utils/RateCard.java @@ -7,13 +7,25 @@ import mage.cards.Card; import mage.constants.ColoredManaSymbol; import mage.constants.Outcome; import mage.target.Target; -import mage.target.common.TargetAnyTarget; import mage.target.common.TargetCreaturePermanent; import org.apache.log4j.Logger; import java.io.InputStream; import java.util.*; +import mage.abilities.Mode; +import mage.abilities.effects.common.DamageWithPowerTargetEffect; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.ExileTargetEffect; +import mage.abilities.effects.common.ExileUntilSourceLeavesEffect; +import mage.abilities.effects.common.FightTargetsEffect; +import mage.abilities.effects.common.continuous.BoostEnchantedEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.constants.Rarity; import mage.constants.SubType; +import mage.target.TargetPermanent; +import mage.target.common.TargetAttackingCreature; +import mage.target.common.TargetAttackingOrBlockingCreature; +import mage.target.common.TargetPlayerOrPlaneswalker; /** * Class responsible for reading ratings from resources and rating given cards. @@ -24,14 +36,22 @@ import mage.constants.SubType; public final class RateCard { private static Map ratings; + private static List setsWithRatingsToBeLoaded; private static final Map rated = new HashMap<>(); - private static Integer min = Integer.MAX_VALUE, max = 0; /** * Rating that is given for new cards. * Ratings are in [1,10] range, so setting it high will make new cards appear more often. + * nowadays, cards that are more rare are more powerful, lets trust that and play the shiny cards. + * */ - private static final int DEFAULT_NOT_RATED_CARD_RATING = 4; + private static final int DEFAULT_NOT_RATED_CARD_RATING = 40; + private static final int DEFAULT_NOT_RATED_UNCOMMON_RATING = 60; + private static final int DEFAULT_NOT_RATED_RARE_RATING = 75; + private static final int DEFAULT_NOT_RATED_MYTHIC_RATING = 90; + + private static String RATINGS_DIR = "/ratings/"; + private static String RATINGS_SET_LIST = RATINGS_DIR + "setsWithRatings.csv"; private static final Logger log = Logger.getLogger(RateCard.class); @@ -53,7 +73,6 @@ public final class RateCard { public static int rateCard(Card card, List allowedColors) { if (allowedColors == null && rated.containsKey(card.getName())) { int rate = rated.get(card.getName()); -// log.info(card.getName() + " rate: " + rate); return rate; } int type; @@ -70,7 +89,7 @@ public final class RateCard { } else { type = 6; } - int score = 10 * getCardRating(card) + 2 * type + getManaCostScore(card, allowedColors) + int score = getCardRating(card) + 2 * type + getManaCostScore(card, allowedColors) + 40 * isRemoval(card); if (allowedColors == null) rated.put(card.getName(), score); @@ -78,37 +97,64 @@ public final class RateCard { } private static int isRemoval(Card card) { - if (card.getSubtype(null).contains(SubType.AURA) || card.isInstant() || card.isSorcery()) { + if (card.isEnchantment() || card.isInstant() || card.isSorcery()) { for (Ability ability : card.getAbilities()) { - for (Effect effect : ability.getEffects()) { - if (effect.getOutcome() == Outcome.Removal) { - log.debug("Found removal: " + card.getName()); + for (Effect effect : ability.getEffects()) { + if (isEffectRemoval(card, ability, effect) == 1){ return 1; } - if (effect.getOutcome() == Outcome.Damage) { - if (effect instanceof DamageTargetEffect) { - DamageTargetEffect damageEffect = (DamageTargetEffect) effect; - if (damageEffect.getAmount() > 1) { - for (Target target : ability.getTargets()) { - if (target instanceof TargetCreaturePermanent || target instanceof TargetAnyTarget) { - log.debug("Found damage dealer: " + card.getName()); - return 1; - } - } - } - } - } - if (effect.getOutcome() == Outcome.DestroyPermanent) { - for (Target target : ability.getTargets()) { - if (target instanceof TargetCreaturePermanent) { - log.debug("Found destroyer: " + card.getName()); - return 1; - } + } + for (Mode mode: ability.getModes().values() ){ + for (Effect effect: mode.getEffects()){ + if (isEffectRemoval(card, ability, effect) == 1){ + return 1; } } } } + + } + return 0; + } + + private static int isEffectRemoval(Card card, Ability ability, Effect effect){ + if (effect.getOutcome() == Outcome.Removal) { + log.debug("Found removal: " + card.getName()); + return 1; + } + //static List removalEffects =[BoostTargetEffect,BoostEnchantedEffect] + if (effect instanceof BoostTargetEffect || effect instanceof BoostEnchantedEffect){ + String text = effect.getText(null); + if (text.contains("/-")){ + // toughness reducer, aka removal + return 1; + } + } + if (effect instanceof FightTargetsEffect || effect instanceof DamageWithPowerTargetEffect){ + return 1; + } + if (effect.getOutcome() == Outcome.Damage || effect instanceof DamageTargetEffect) { + for (Target target : ability.getTargets()) { + if (!(target instanceof TargetPlayerOrPlaneswalker)){ + log.debug("Found damage dealer: " + card.getName()); + return 1; + } + } + } + if (effect.getOutcome() == Outcome.DestroyPermanent || + effect instanceof DestroyTargetEffect || + effect instanceof ExileTargetEffect || + effect instanceof ExileUntilSourceLeavesEffect) { + for (Target target : ability.getTargets()) { + if (target instanceof TargetCreaturePermanent || + target instanceof TargetAttackingCreature || + target instanceof TargetAttackingOrBlockingCreature || + target instanceof TargetPermanent) { + log.debug("Found destroyer/exiler: " + card.getName()); + return 1; + } + } } return 0; } @@ -117,32 +163,72 @@ public final class RateCard { * Return rating of the card. * * @param card Card to rate. - * @return Rating number from [1;10]. + * @return Rating number from [1:100]. */ public static int getCardRating(Card card) { - if (ratings == null) { - readRatings(); + readRatingSetList(); + String exp = card.getExpansionSetCode().toLowerCase(); + readRatings(exp); + + if (ratings != null && ratings.containsKey(card.getName())) { + return ratings.get(card.getName()); } - if (ratings.containsKey(card.getName())) { - int r = ratings.get(card.getName()); - // normalize to [1..10] - float f = 10.0f * (r - min) / (max - min); - return (int) Math.round(f); + + Rarity r = card.getRarity(); + if (Rarity.COMMON == r){ + return DEFAULT_NOT_RATED_CARD_RATING; + }else if (Rarity.UNCOMMON == r){ + return DEFAULT_NOT_RATED_UNCOMMON_RATING; + }else if (Rarity.RARE == r){ + return DEFAULT_NOT_RATED_RARE_RATING; + }else if (Rarity.MYTHIC == r){ + return DEFAULT_NOT_RATED_MYTHIC_RATING; } return DEFAULT_NOT_RATED_CARD_RATING; } - + /** - * Reads ratings from resources. + * reads the list of sets that have ratings csv files + * populates the setsWithRatingsToBeLoaded */ - private synchronized static void readRatings() { - if (ratings == null) { - ratings = new HashMap<>(); - readFromFile("/m13.csv"); + private synchronized static void readRatingSetList(){ + try { + if (setsWithRatingsToBeLoaded == null){ + setsWithRatingsToBeLoaded = new LinkedList<>(); + InputStream is = RateCard.class.getResourceAsStream(RATINGS_SET_LIST); + Scanner scanner = new Scanner(is); + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + if (!line.substring(0,1).equals("#")){ + setsWithRatingsToBeLoaded.add(line); + } + } + } + }catch (Exception e) { + log.info("failed to read ratings set list file: " + RATINGS_SET_LIST ); + e.printStackTrace(); } } - - private static void readFromFile(String path) { + + /** + * Reads ratings from resources and loads them into ratings map + */ + private synchronized static void readRatings(String expCode) { + if (ratings == null) { + ratings = new HashMap<>(); + } + if (setsWithRatingsToBeLoaded.contains(expCode)){ + log.info("reading draftbot ratings for the set" + expCode); + readFromFile(RATINGS_DIR + expCode + ".csv"); + setsWithRatingsToBeLoaded.remove(expCode); + } + } + /** + * reads ratings from the file + */ + private synchronized static void readFromFile(String path) { + Integer min = Integer.MAX_VALUE, max = 0; + Map thisFileRatings = new HashMap<>(); try { InputStream is = RateCard.class.getResourceAsStream(path); Scanner scanner = new Scanner(is); @@ -158,21 +244,32 @@ public final class RateCard { if (rating < min) { min = rating; } - ratings.put(name, rating); + thisFileRatings.put(name, rating); + } + } + // normalize for the file to [1..100] + for (String name: thisFileRatings.keySet()){ + int r = thisFileRatings.get(name); + int newrating = (int)(100.0f * (r - min) / (max - min)); + if (!ratings.containsKey(name) || + (ratings.containsKey(name) && newrating > ratings.get(name)) ){ + ratings.put(name, newrating); } } } catch (Exception e) { + log.info("failed to read ratings file: " + path ); e.printStackTrace(); - ratings.clear(); // no rating available on exception } } private static final int SINGLE_PENALTY[] = {0, 1, 1, 3, 6, 9}; + private static final int MULTICOLOR_BONUS = 15; /** * Get manacost score. * Depends on chosen colors. Returns negative score for those cards that doesn't fit allowed colors. * If allowed colors are not chosen, then score based on converted cost is returned with penalty for heavy colored cards. + * gives bonus to multicolor cards that fit within allowed colors and if allowed colors is <5 * * * @param card @@ -215,9 +312,14 @@ public final class RateCard { } if (maxSingleCount > 5) maxSingleCount = 5; - return 2 * converted + 3 * (10 - SINGLE_PENALTY[maxSingleCount]/*-DOUBLE_PENALTY[doubleCount]*/); - } + int rate = 2 * converted + 3 * (10 - SINGLE_PENALTY[maxSingleCount]); + if( singleCount.size() > 1 && singleCount.size() < 5){ + rate += MULTICOLOR_BONUS; + } + return rate; + } + /** * Determines whether mana symbol is color. * diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings.txt b/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings.txt deleted file mode 100644 index 6ccb175ffb4..00000000000 --- a/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings.txt +++ /dev/null @@ -1,1214 +0,0 @@ -1569 : Day of Judgment -1548 : Garruk Wildspeaker -1547 : Sword of Vengeance -1544 : Baneslayer Angel -1533 : Kargan Dragonlord -1526 : Frost Titan -1523 : Wurmcoil Engine -1522 : Ob Nixilis, the Fallen -1520 : Chandra Nalaar -1516 : Gideon Jura -1516 : Primeval Titan -1513 : Ajani Goldmane -1512 : Basilisk Collar -1511 : Vampire Nighthawk -1511 : Skithiryx, the Blight Dragon -1509 : Serra Angel -1508 : Koth of the Hammer -1507 : Jace, the Mind Sculptor -1507 : Avenger of Zendikar -1506 : Vengevine -1505 : Nissa Revane -1502 : Student of Warfare -1501 : Jace Beleren -1500 : Iona, Shield of Emeria -1500 : Glimmerpost -1500 : Transcendent Master -1500 : Guul Draz Assassin -1500 : Kozilek, Butcher of Truth -1500 : Omnath, Locus of Mana -1500 : Abyssal Persecutor -1500 : Dragonmaster Outcast -1500 : Kazuul, Tyrant of the Cliffs -1500 : Anowon, the Ruin Sage -1500 : Platinum Angel -1499 : Eldrazi Conscription -1499 : Drana, Kalastria Bloodchief -1499 : Conquering Manticore -1498 : Mul Daya Channelers -1498 : Lord of Shatterskull Pass -1498 : Admonition Angel -1498 : Archon of Redemption -1498 : Inferno Titan -1497 : Sorin Markov -1497 : Sword of Body and Mind -1496 : Terra Stomper -1496 : Carnifex Demon -1496 : Deathless Angel -1495 : Linvala, Keeper of Silence -1492 : Bloodghast -1492 : Steel Hellkite -1491 : Obsidian Fireheart -1489 : Guul Draz Specter -1489 : Kazandu Tuskcaller -1488 : Emrakul, the Aeons Torn -1488 : Coralhelm Commander -1488 : Wrexial, the Risen Deep -1487 : Nirkana Revenant -1486 : Scalding Tarn -1486 : Sphinx of Jwar Isle -1486 : Khalni Hydra -1485 : Felidar Sovereign -1485 : Halo Hunter -1485 : Sarkhan the Mad -1485 : Consume the Meek -1484 : Rampaging Baloths -1484 : Gigantiform -1483 : Consuming Vapors -1482 : It That Betrays -1481 : Eldrazi Monument -1481 : All Is Dust -1480 : Kalitas, Bloodchief of Ghet -1480 : Mimic Vat -1480 : Pestilence Demon -1480 : Stirring Wildwood -1480 : Mind Control -1479 : Comet Storm -1477 : Creeping Tar Pit -1476 : Harabaz Druid -1475 : Geth, Lord of the Vault -1475 : Pelakka Wurm -1473 : Lorthos, the Tidemaker -1473 : Elspeth Tirel -1473 : Grave Titan -1472 : Celestial Colonnade -1471 : Bear Umbra -1471 : Triskelion -1469 : Turntimber Ranger -1468 : Terastodon -1466 : Kazuul Warlord -1465 : Sphinx of Magosi -1464 : Luminarch Ascension -1464 : Lighthouse Chronologist -1464 : Stone Idol Trap -1464 : Chain Reaction -1463 : Sunblast Angel -1463 : Spawnsire of Ulamog -1463 : Royal Assassin -1462 : Misty Rainforest -1461 : Jwari Shapeshifter -1460 : Hellcarver Demon -1459 : Hellkite Charger -1459 : Rite of Replication -1458 : Eternity Vessel -1458 : Bala Ged Thief -1458 : Kalastria Highborn -1458 : Fireball -1456 : Precursor Golem -1456 : Venser, the Sojourner -1456 : Joraga Treespeaker -1456 : Wolfbriar Elemental -1456 : Mitotic Slime -1455 : Journey to Nowhere -1454 : Strata Scythe -1452 : Awakening Zone -1452 : Magmaw -1452 : Gaea's Revenge -1449 : Ezuri's Brigade -1448 : Strength of the Tajuru -1448 : Nantuko Shade -1446 : Ratchet Bomb -1445 : Sun Titan -1444 : Hand of the Praetors -1443 : Lotus Cobra -1441 : Nim Deathmantle -1440 : Arid Mesa -1439 : Scute Mob -1439 : Mystifying Maze -1437 : Argentum Armor -1436 : Chimeric Mass -1434 : Magma Phoenix -1433 : Chandra Ablaze -1433 : Scars of Mirrodin -1433 : Rise of the Eldrazi -1433 : Brittle Effigy -1432 : Blade of the Bloodchief -1432 : Oracle of Mul Daya -1432 : Kuldotha Phoenix -1432 : Mordant Dragon -1431 : Myr Battlesphere -1431 : Skinrender -1431 : Argent Sphinx -1431 : Talus Paladin -1430 : Vengeful Archon -1428 : Cunning Sparkmage -1426 : Celestial Mantle -1425 : Roil Elemental -1425 : Malakir Bloodwitch -1425 : Contagion Clasp -1424 : Trusty Machete -1424 : Sea Gate Loremaster -1424 : World Queller -1423 : Burst Lightning -1423 : Agadeem Occultist -1422 : Raging Ravine -1422 : Fauna Shaman -1421 : Valakut, the Molten Pinnacle -1421 : Seer's Sundial -1420 : Butcher of Malakir -1415 : Novablast Wurm -1414 : Liliana Vess -1413 : Marsh Flats -1412 : Obstinate Baloth -1412 : Condemn -1409 : Emeria Angel -1408 : Sphinx of Lost Truths -1408 : Goliath Sphinx -1407 : Kazandu Blademaster -1407 : Verdant Catacombs -1406 : Grasp of Darkness -1406 : Marshal's Anthem -1404 : Platinum Emperion -1404 : Doom Blade -1404 : Lightning Bolt -1403 : Grappling Hook -1403 : Ulamog, the Infinite Gyre -1402 : Conundrum Sphinx -1400 : Momentous Fall -1400 : Protean Hydra -1399 : Ancient Hellkite -1398 : Flame Slash -1396 : Kabira Evangel -1396 : Pacifism -1395 : Gelatinous Genesis -1394 : Arc Trail -1393 : Joraga Warcaller -1392 : Lavaclaw Reaches -1392 : Lodestone Golem -1390 : Liege of the Tangle -1389 : Grand Architect -1386 : Trigon of Corruption -1386 : Angelic Arbiter -1383 : True Conviction -1383 : Mox Opal -1383 : Spikeshot Elder -1380 : Devout Lightcaster -1379 : Gatekeeper of Malakir -1378 : Gigantomancer -1377 : Shepherd of the Lost -1375 : Bloodchief Ascension -1375 : Darksteel Axe -1375 : Livewire Lash -1372 : Hoarding Dragon -1368 : Darksteel Juggernaut -1367 : Conqueror's Pledge -1367 : Arrest -1367 : Pyroclasm -1364 : Galvanic Blast -1363 : Lux Cannon -1362 : Echo Mage -1361 : Quicksilver Gargantuan -1360 : Razor Hippogriff -1360 : Volition Reins -1360 : Rage Nimbus -1360 : Tuktuk the Explorer -1357 : Putrefax -1353 : Prototype Portal -1353 : Disaster Radius -1353 : Prodigal Pyromancer -1352 : Staggershock -1352 : Brimstone Mage -1351 : Punishing Fire -1348 : Rapacious One -1346 : Golem Artisan -1345 : Air Servant -1343 : Goblin Guide -1342 : Overwhelming Stampede -1342 : Cudgel Troll -1336 : Emeria, the Sky Ruin -1335 : Stoneforge Mystic -1334 : Engulfing Slagwurm -1333 : Kemba, Kha Regent -1332 : Etched Champion -1324 : Beastmaster Ascension -1324 : Warren Instigator -1315 : Plated Geopede -1315 : Kabira Vindicator -1315 : Chandra's Outrage -1313 : Oxidda Scrapmelter -1312 : Hideous End -1312 : Hedron Matrix -1312 : Blinding Mage -1311 : Slice in Twain -1311 : Knight Exemplar -1309 : Reassembling Skeleton -1308 : Embersmith -1308 : Hellion Eruption -1305 : Dispense Justice -1304 : Turn to Slag -1304 : Boar Umbra -1302 : Ulamog's Crusher -1299 : Artisan of Kozilek -1297 : Hada Freeblade -1296 : Eye of Ugin -1296 : Death's Shadow -1295 : Marsh Casualties -1295 : Kor Skyfisher -1294 : Summoning Trap -1293 : Smother -1292 : Howling Banshee -1290 : Domestication -1290 : Urge to Feed -1289 : Lightkeeper of Emeria -1287 : Demon of Death's Gate -1286 : Sylvok Replica -1286 : Vendetta -1284 : Broodwarden -1282 : Shatter -1281 : Asceticism -1280 : Assassinate -1279 : Cyclops Gladiator -1276 : Nomads' Assembly -1276 : Knight of Cliffhaven -1275 : Bestial Menace -1272 : Myrsmith -1272 : Necrotic Ooze -1272 : Aether Adept -1270 : Living Tsunami -1267 : Beastbreaker of Bala Ged -1264 : Adventuring Gear -1264 : Revoke Existence -1263 : Vampire Hexmage -1262 : Heavy Arbalest -1261 : Pathrazer of Ulamog -1260 : Disfigure -1258 : Forked Bolt -1258 : Stormfront Pegasus -1256 : Birds of Paradise -1253 : Nirkana Cutthroat -1253 : Voyager Drake -1251 : Heat Ray -1250 : Rust Tick -1250 : Crystal Ball -1248 : Windrider Eel -1245 : Acid Web Spider -1243 : Enclave Cryptologist -1238 : Myr Propagator -1238 : Kozilek's Predator -1237 : Vapor Snare -1236 : Steppe Lynx -1236 : Tempered Steel -1235 : Terminate -1234 : Palladium Myr -1234 : Tomb Hex -1234 : Garruk's Packleader -1233 : Electropotence -1231 : Black Knight -1230 : Narcolepsy -1229 : Acidic Slime -1226 : Oblivion Ring -1223 : Cystbearer -1221 : Rusted Relic -1221 : Azure Drake -1220 : Venerated Teacher -1220 : Splinter Twin -1220 : Searing Blaze -1219 : Tideforce Elemental -1218 : Trinket Mage -1218 : Whispersilk Cloak -1216 : Hada Spy Patrol -1216 : Jace's Ingenuity -1215 : Kor Aeronaut -1214 : Cerebral Eruption -1214 : Nest Invader -1214 : Water Servant -1213 : World at War -1212 : Bladetusk Boar -1211 : Traitorous Instinct -1210 : Plague Stinger -1210 : Ondu Giant -1210 : Cloud Crusader -1209 : Honor of the Pure -1207 : Barrage Ogre -1207 : Wall of Omens -1207 : Path to Exile -1206 : Umara Raptor -1206 : Mana Leak -1205 : Overgrown Battlement -1205 : Caustic Crawler -1205 : Behemoth Sledge -1203 : Growth Spasm -1202 : Bellowing Tanglewurm -1200 : Flesh Allergy -1199 : Cloud Elemental -1198 : Darkslick Drake -1198 : Quag Sickness -1197 : Myr Galvanizer -1195 : Barbed Battlegear -1195 : Assault Griffin -1193 : Foresee -1192 : Induce Despair -1192 : Greater Basilisk -1191 : Bloodhusk Ritualist -1189 : Leatherback Baloth -1188 : Kor Spiritdancer -1188 : Rise from the Grave -1187 : Kor Hookmaster -1187 : Sleep -1185 : Grafted Exoskeleton -1185 : Skywatcher Adept -1183 : Glimmerpoint Stag -1182 : Kuldotha Forgemaster -1182 : Mortician Beetle -1181 : Eldrazi Temple -1180 : Harrow -1178 : Ezuri, Renegade Leader -1175 : Hammer of Ruin -1172 : Contagious Nim -1169 : Cultivate -1168 : Mindbreak Trap -1168 : Pitfall Trap -1168 : Inferno Trap -1167 : Turntimber Basilisk -1167 : Ember Hauler -1166 : Martial Coup -1164 : Perilous Myr -1163 : Iona's Judgment -1163 : Child of Night -1161 : Painsmith -1161 : Ogre's Cleaver -1161 : Finest Hour -1160 : Myr Reservoir -1160 : Duskdale Wurm -1160 : Elspeth, Knight-Errant -1159 : Garruk's Companion -1158 : Horizon Drake -1157 : Emrakul's Hatcher -1157 : Jagwasp Swarm -1156 : Thought Gorger -1156 : Guard Gomazoa -1156 : Last Kiss -1155 : Thada Adel, Acquisitor -1154 : Quest for the Gravelord -1154 : Destructive Force -1154 : Armored Ascension -1153 : Trigon of Rage -1153 : Join the Ranks -1153 : Sylvan Ranger -1152 : Merfolk Seastalkers -1152 : Merfolk Skyscout -1152 : Kor Firewalker -1151 : Elvish Archdruid -1149 : Sadistic Sacrament -1149 : Glint Hawk -1148 : Predatory Urge -1148 : Liliana's Specter -1148 : Woolly Thoctar -1147 : Stonework Puma -1146 : Archive Trap -1146 : Wild Griffin -1146 : Llanowar Elves -1145 : Necrogen Scudder -1144 : Armament Master -1143 : Keening Stone -1141 : Blazing Torch -1141 : Dawnglare Invoker -1140 : Torch Slinger -1140 : Geyser Glider -1140 : Fire Servant -1138 : Heartstabber Mosquito -1138 : Caravan Escort -1138 : Wildheart Invoker -1137 : Welkin Tern -1137 : Squadron Hawk -1137 : Maelstrom Pulse -1136 : Throne of Geth -1136 : Bloodbraid Elf -1135 : Glint Hawk Idol -1135 : Trigon of Infestation -1135 : Clone -1135 : Putrid Leech -1134 : Giant Scorpion -1134 : Ajani Vengeant -1133 : Grazing Gladehart -1132 : Cosi's Trickster -1131 : Juggernaut -1130 : Hedron Crab -1130 : Into the Roil -1130 : Ichor Rats -1130 : Ogre Geargrabber -1129 : Lightning Helix -1128 : Oust -1127 : Act of Treason -1126 : Arrow Volley Trap -1126 : Vedalken Certarch -1126 : Deathforge Shaman -1126 : Bituminous Blast -1125 : Training Grounds -1124 : Mark of Mutiny -1124 : Knight of the White Orchid -1123 : Tumble Magnet -1121 : Lumengrid Drake -1121 : Necropede -1121 : Yavimaya Wurm -1120 : Noble Hierarch -1119 : River Boa -1119 : Scrapdiver Serpent -1119 : Renegade Doppelganger -1119 : Tajuru Preserver -1119 : White Knight -1119 : Vengeful Rebirth -1118 : Mindslaver -1118 : Genesis Wave -1118 : Frostwind Invoker -1118 : Ranger of Eos -1118 : Sarkhan Vol -1117 : Corrupt -1117 : Chandra's Spitfire -1116 : Bonds of Quicksilver -1115 : Surrakar Marauder -1114 : Explorer's Scope -1114 : Ice Cage -1114 : Steel Overseer -1114 : Earthquake -1113 : Vines of Vastwood -1113 : Strider Harness -1113 : Snapping Drake -1112 : Drake Umbra -1112 : Warlord's Axe -1111 : Sphinx of the Steel Wind -1110 : Hand of Emrakul -1109 : Aether Figment -1109 : Hagra Diabolist -1109 : Murasa Pyromancer -1107 : Apex Hawks -1107 : Dead Reckoning -1104 : Guul Draz Vampire -1104 : Overrun -1104 : Battlegrace Angel -1103 : Elvish Visionary -1102 : Goblin Ruinblaster -1102 : Smite -1099 : Graypelt Hunter -1099 : Rhox War Monk -1099 : Stun Sniper -1098 : Khalni Heart Expedition -1098 : Aven Squire -1097 : Greenweaver Druid -1097 : Broodmate Dragon -1096 : Goblin Bushwhacker -1096 : Riddlesmith -1096 : Steady Progress -1096 : Blight Mamba -1096 : Pawn of Ulamog -1094 : Spined Wurm -1094 : Glacial Fortress -1094 : Master of the Wild Hunt -1091 : Blood Seeker -1091 : Carapace Forger -1090 : Highland Berserker -1090 : Phylactery Lich -1089 : Skeletal Wurm -1089 : Refraction Trap -1089 : Tattered Drake -1087 : Tainted Strike -1087 : Lorescale Coatl -1087 : Sprouting Thrinax -1086 : Arbor Elf -1085 : Frontier Guide -1085 : Sign in Blood -1084 : Mammoth Umbra -1084 : Rakka Mar -1083 : Air Elemental -1082 : Madrush Cyclops -1080 : Preordain -1080 : Ant Queen -1080 : Fiery Fall -1078 : Ichorclaw Myr -1076 : Gomazoa -1076 : Horizon Spellbomb -1076 : War Priest of Thune -1076 : Scroll Thief -1075 : Might of Oaks -1074 : Hellfire Mongrel -1074 : Kor Cartographer -1074 : Kor Sanctifiers -1074 : Champion's Drake -1074 : Darklit Gargoyle -1074 : Knight of the Reliquary -1073 : Fledgling Griffin -1072 : Goblin Shortcutter -1072 : Infiltration Lens -1072 : Indomitable Archangel -1071 : Bogardan Hellkite -1071 : Kathari Remnant -1070 : See Beyond -1070 : Ethersworn Adjudicator -1069 : Deny Reality -1069 : Vampire Aristocrat -1069 : Ethercaste Knight -1068 : Bladed Pinions -1068 : Kemba's Skyguard -1068 : AEther Figment -1067 : Tajuru Archer -1067 : Tuktuk Grunts -1067 : Stoic Rebuttal -1067 : Auriok Edgewright -1067 : Great Sable Stag -1066 : Tangle Angler -1066 : Barony Vampire -1066 : Druid of the Anima -1065 : Court Archers -1064 : Mold Shambler -1064 : Feast of Blood -1064 : Ondu Cleric -1064 : Deadly Recluse -1064 : Thornling -1063 : Paralyzing Grasp -1063 : Aura Gnarlid -1062 : Zektar Shrine Expedition -1062 : Blood Tribute -1062 : Bleak Coven Vampires -1061 : Rafiq of the Many -1061 : Nulltread Gargantuan -1060 : Baloth Cage Trap -1060 : Loam Lion -1060 : Stormtide Leviathan -1060 : Ball Lightning -1059 : Spawning Breath -1059 : Shoreline Salvager -1059 : Jenara, Asura of War -1058 : Halt Order -1058 : Stabbing Pain -1056 : Courier's Capsule -1056 : Shock -1055 : Khalni Gem -1055 : Disperse -1055 : Sigiled Paladin -1054 : Timbermaw Larva -1054 : Puncturing Light -1054 : Canopy Cover -1053 : Windborne Charge -1053 : Lightmine Field -1053 : Reverberate -1052 : Crypt Ripper -1052 : Looming Shade -1051 : Spire Barrage -1051 : Cadaver Imp -1050 : Summoner's Bane -1050 : Perimeter Captain -1049 : Makindi Griffin -1048 : Lullmage Mentor -1048 : Primal Bellow -1048 : Surrakar Spellblade -1048 : Awakener Druid -1048 : Conquerors Pledge -1047 : Mind Sludge -1047 : Neurok Replica -1047 : Neurok Invisimancer -1047 : Trigon of Thought -1047 : Kitesail -1047 : Wild Nacatl -1046 : Reckless Scholar -1046 : Sky Ruin Drake -1046 : Grindclock -1046 : Explore -1045 : Nissa's Chosen -1045 : Flameborn Hellion -1045 : Ghalma's Warden -1045 : Berserkers of Blood Ridge -1045 : Goblin Outlander -1044 : Virulent Swipe -1044 : Time of Heroes -1044 : Nightwing Shade -1044 : Scarland Thrinax -1043 : Time Warp -1043 : Rhox Pikemaster -1042 : Zendikar -1042 : Lavaball Trap -1042 : Magma Rift -1042 : Snake Umbra -1042 : Giant Spider -1041 : Shatterskull Giant -1041 : Cliff Threader -1041 : Sea Gate Oracle -1041 : Nemesis Trap -1041 : Rootbound Crag -1040 : Auriok Sunchaser -1040 : Corpse Cur -1040 : Sacred Wolf -1040 : Beacon Behemoth -1040 : Hell's Thunder -1039 : Bloodhall Ooze -1039 : Winged Coatl -1038 : Regress -1038 : Tuktuk Scrapper -1038 : Ruthless Cullblade -1038 : Captivating Vampire -1038 : Mind Spring -1038 : Emerald Oryx -1038 : Steward of Valeron -1037 : Devastating Summons -1037 : Calcite Snapper -1037 : Blightning -1037 : Cloudheath Drake -1036 : Recurring Insight -1036 : Hellspark Elemental -1036 : Rhox Brute -1035 : Saberclaw Golem -1034 : Reality Spasm -1034 : Drowned Catacomb -1034 : Dragonskull Summit -1034 : Sigil of the Empty Throne -1033 : Tower of Calamities -1033 : Bojuka Brigand -1033 : Time Reversal -1032 : Bramblesnap -1032 : Groundswell -1032 : Treasure Hunt -1032 : Kathari Screecher -1031 : Vampire Lacerator -1031 : Daggerback Basilisk -1030 : Prey's Vengeance -1030 : Augury Owl -1030 : Fling -1029 : Blackcleave Goblin -1029 : Wall of Frost -1029 : Brave the Elements -1027 : Pyromancer Ascension -1027 : Grixis Slavedriver -1026 : Soulsurge Elemental -1026 : Putrefy -1025 : Makindi Shieldmate -1025 : Abuna Acolyte -1024 : Alpha Tyrannax -1023 : Quest for the Gemblades -1023 : Wind Zendikon -1023 : Mist Leopard -1023 : Esper Cormorants -1022 : Expedition Map -1022 : Dread Drone -1022 : Everflowing Chalice -1022 : Prized Unicorn -1022 : Griffin Sentinel -1022 : Skyknight Legionnaire -1022 : Ardent Plea -1021 : Nightguard Patrol -1020 : Giant Growth -1020 : Dregscape Zombie -1019 : Nacatl Outlander -1019 : Molten-Tail Masticore -1017 : Repel the Darkness -1017 : Gravitational Shift -1017 : Bloodthrone Vampire -1016 : Whiplash Trap -1016 : Bloodshot Trainee -1016 : Guard Duty -1016 : Akoum Battlesinger -1016 : Sejiri Merfolk -1016 : Gravedigger -1015 : Hyena Umbra -1014 : Æther Figment -1013 : Umbra Mystic -1013 : Akoum Boulderfoot -1012 : Crypt of Agadeem -1012 : Mnemonic Wall -1012 : Plummet -1012 : Watchwolf -1011 : Vastwood Gorger -1011 : Moriok Replica -1011 : Sky-Eel School -1011 : Zombie Outlander -1011 : Incurable Ogre -1010 : Emerge Unscathed -1010 : Runeclaw Bear -1010 : Vectis Silencers -1009 : Kor Duelist -1009 : Wall of Denial -1008 : Inexorable Tide -1007 : Chrome Steed -1007 : Survival Cache -1007 : Pilgrim's Eye -1006 : Jaddi Lifestrider -1006 : Vastwood Animist -1006 : Sigil of Distinction -1006 : Yoked Plowbeast -1005 : Sighted-Caste Sorcerer -1004 : Bala Ged Scorpion -1004 : Halimar Excavator -1004 : Sunpetal Grove -1004 : Stone Golem -1003 : Jwar Isle Refuge -1003 : Vectis Agents -1003 : Gold Myr -1002 : Mysteries of the Deep -1002 : Negate -1002 : Pestilent Kathari -1001 : Halimar Depths -1001 : Glass Golem -1000 : Lust for War -1000 : Realms Uncharted -1000 : Affa Guard Hound -1000 : Roc Egg -999 : Ajani's Pridemate -998 : Aether Tradewinds -998 : Weakness -997 : Eel Umbra -997 : Drudge Skeletons -995 : Vulshok Replica -995 : Ferrovore -995 : Molten Frame -995 : Jungle Weaver -994 : Akoum Refuge -994 : Wind Drake -993 : AEther Adept -992 : Cobra Trap -992 : Summit Apes -992 : Cylian Elf -992 : Talon Trooper -991 : Colossal Might -990 : Vulshok Heartstoker -990 : Warmonger's Chariot -990 : Silvercoat Lion -989 : Sunspear Shikari -988 : Slavering Nulls -986 : Spidersilk Net -986 : Unstable Footing -986 : Razorfield Thresher -986 : Gnarlid Pack -986 : Votary of the Conclave -986 : Zephyr Sprite -985 : Grappler Spider -985 : Grayscaled Gharial -984 : Snapsail Glider -984 : Goblin Chieftain -983 : Soul's Majesty -983 : Hellkite Overlord -982 : Diabolic Tutor -982 : Soul Warden -982 : Akrasan Squire -982 : Wildfield Borderpost -981 : Graypelt Refuge -980 : Sejiri Refuge -980 : Instill Infection -980 : Spider Umbra -980 : Celestial Purge -980 : Bone Saw -980 : Dispeller's Capsule -979 : Teetering Peaks -979 : Soliton -979 : Scepter of Insight -978 : Kazandu Refuge -978 : Valakut Fireboar -978 : Warpath Ghoul -977 : Filigree Angel -977 : Fume Spitter -976 : Inquisition of Kozilek -975 : Traumatize -975 : Tukatongue Thallid -975 : Aerie Mystics -974 : Savage Silhouette -974 : Kiln Fiend -973 : Rhox Bodyguard -972 : Vulshok Berserker -972 : Obelisk of Jund -971 : Marsh Threader -970 : Vampire's Bite -970 : Narrow Escape -970 : Wrap in Flames -970 : Diminish -970 : Cavern Thoctar -970 : Filigree Sages -969 : Stomper Cub -969 : Bazaar Trader -969 : Manic Vandal -969 : Scepter of Dominance -968 : Lavafume Invoker -968 : Font of Mythos -968 : Outrider of Jhess -968 : Undead Leotau -967 : Moriok Reaver -967 : Sporecap Spider -967 : Spell Contortion -967 : Arc Runner -967 : Firewild Borderpost -967 : Jhessian Lookout -966 : Brindle Boar -965 : Serra Ascendant -965 : Veinfire Borderpost -964 : Magosi, the Waterveil -964 : Deprive -964 : Lava Axe -962 : Thrummingbird -962 : Ezuri's Archers -962 : Copper Myr -962 : Lone Missionary -962 : Quest for Renewal -962 : Permafrost Trap -962 : Dimir Signet -962 : Etherium Abomination -962 : Glory of Warfare -961 : Hagra Crocodile -961 : Iron Myr -961 : Ikiral Outrider -961 : Null Champion -961 : Dreg Reaver -961 : Valeron Outlander -960 : Might of the Masses -960 : Golgari Signet -959 : Carrion Call -959 : Salvage Scout -958 : Ior Ruin Expedition -958 : Horned Turtle -957 : Molder Beast -957 : Halimar Wavewatch -956 : Molten Ravager -956 : Origin Spellbomb -956 : Goblin Roughrider -956 : Shiv's Embrace -955 : Alpha Tyrranax -954 : Vent Sentinel -954 : Gloomhunter -954 : Rampant Growth -953 : Kor Outfitter -953 : Needlebite Trap -953 : Wing Puncture -953 : Amulet of Vigor -952 : Obelisk of Naya -951 : Lifesmith -951 : Kranioceros -950 : Grim Discovery -950 : Kelinore Bat -950 : Quenchable Fire -949 : Slaughter Cry -949 : Merfolk Sovereign -948 : Seascape Aerialist -948 : Bant Battlemage -948 : Mistvein Borderpost -946 : Wall of Tanglecord -946 : Brood Birthing -946 : Guardians of Akrasa -945 : Joraga Bard -945 : Hedron Rover -944 : Goblin War Paint -944 : Exsanguinate -943 : Slingbow Trap -942 : Gloryscale Viashino -942 : Goblin Mountaineer -941 : Escaped Null -941 : Inspired Charge -941 : Terramorphic Expanse -941 : Temple Bell -941 : Excommunicate -941 : Onyx Goblet -940 : Culling Dais -940 : Elite Vanguard -939 : Kraken Hatchling -938 : Marble Chalice -937 : Quag Vampires -936 : Trailblazer's Boots -936 : Necrotic Plague -934 : Leyline of Vitality -933 : Wall of Bone -933 : Disorient -932 : Merfolk Wayfinder -932 : Withstand Death -931 : Distortion Strike -931 : Claws of Valakut -931 : Deathmark -930 : Soulbound Guardians -930 : Valiant Guard -930 : Spellbreaker Behemoth -930 : Vedalken Outlander -929 : Prophetic Prism -928 : Soul Stair Expedition -928 : Quest for Ula's Temple -926 : Cancel -926 : Ruinous Minotaur -926 : Psychic Miasma -924 : Skitter of Lizards -923 : Soul Parry -923 : Quest for the Nihil Stone -922 : Sylvok Lifestaff -922 : Pennon Blade -921 : Tempest Owl -921 : Combust -920 : Archmage Ascension -920 : Hedron Scrabbler -920 : Lagac Lizard -920 : Enclave Elite -920 : Obelisk of Grixis -919 : Selesnya Signet -918 : Scythe Tiger -918 : Flight Spellbomb -918 : Ruin Ghost -917 : Lay Bare -917 : Bog Wraith -917 : Acolyte of Xathrid -916 : Wall of Faith -914 : Surrakar Banisher -914 : Dread Statuary -914 : Obelisk of Esper -913 : Screeching Silcaw -913 : Furnace Celebration -913 : Snapping Creeper -912 : Battle Hurda -911 : Nether Horror -911 : Howling Mine -910 : Obelisk of Bant -910 : Knotvine Mystic -909 : Seismic Shudder -908 : Copperline Gorge -908 : Suffer the Past -907 : Corrupted Zendikon -907 : Oakenform -907 : Fieldmist Borderpost -906 : Dreamstone Hedron -905 : Fusion Elemental -904 : Terra Eternal -904 : Infantry Veteran -904 : Boros Signet -903 : Dreadwing -902 : Twitch -901 : Surreal Memoir -900 : Dross Hopper -900 : Quicksand -900 : Khalni Garden -899 : Earth Servant -899 : Constricting Tendrils -898 : Quest for Pure Flame -898 : Kabira Crossroads -898 : Leonin Arbiter -898 : Blackcleave Cliffs -897 : Ricochet Trap -897 : Gargoyle Sentinel -896 : Vastwood Zendikon -894 : Spreading Seas -894 : Seize the Initiative -894 : Seachrome Coast -894 : Baneful Omen -893 : Explosive Revelation -892 : Razorverge Thicket -891 : Roofstalker Wight -889 : Redirect -888 : Selective Memory -887 : Silver Myr -886 : Grotag Thrasher -886 : Sejiri Steppe -886 : Unsummon -884 : Shoal Serpent -884 : Darkslick Shores -884 : Semblance Anvil -882 : Goblin Arsonist -881 : Mind Rot -881 : Rotting Legion -880 : Crusher Zendikon -880 : Angel's Mercy -879 : Spell Pierce -879 : Corrupted Harvester -879 : Leaden Myr -878 : Alluring Siren -877 : Quest for the Holy Relic -877 : Cast Through Time -877 : Angelsong -876 : Shieldmate's Blessing -876 : Bold Defense -876 : Noble Vestige -876 : Tanglesap -876 : Scrib Nibblers -875 : Soaring Seacliff -875 : Landbind Ritual -874 : Nimbus Wings -874 : Pulse Tracker -874 : Canyon Minotaur -873 : Eland Umbra -872 : Zendikar Farguide -872 : Tunnel Ignus -872 : Goblin Piker -871 : Mighty Leap -870 : Luminous Wake -870 : Ogre Sentry -870 : Glory Seeker -868 : Quest for Ancient Secrets -868 : Turntimber Grove -868 : Brink of Disaster -868 : Kitesail Apprentice -867 : Auriok Replica -866 : Guardian Zendikon -865 : Relic Crush -865 : Fiery Hellhound -864 : Lethargy Trap -864 : Zof Shade -863 : Mire Blight -863 : Vector Asp -863 : Naturalize -863 : Silence -863 : Flashfreeze -860 : Dormant Gomazoa -860 : Leaf Arrow -859 : Call to Mind -859 : Inkwell Leviathan -858 : Caller of Gales -858 : Trapmaker's Snare -858 : Carnage Altar -858 : Memnite -858 : Nature's Claim -856 : Scoria Elemental -856 : Mass Polymorph -856 : Coral Merfolk -855 : Dark Tutelage -854 : Dissipation Field -853 : Kuldotha Rebirth -852 : Pillarfield Ox -851 : Irresistible Prey -848 : Shrivel -847 : Runeflare Trap -847 : Mindless Null -847 : Disentomb -846 : Veteran's Reflexes -845 : Cosi's Ravager -844 : Smoldering Spires -844 : Relentless Rats -842 : Piranha Marsh -842 : Oxidda Daredevil -842 : Thunder Strike -840 : Evolving Wilds -840 : Goblin Tunneler -840 : Viscera Seer -840 : Solemn Offering -838 : Rest for the Weary -838 : Palace Guard -836 : Nema Siltlurker -836 : Skittering Invasion -835 : Bog Tatters -835 : Siege Mastodon -833 : Plated Seastrider -833 : Volcanic Strength -833 : Kraken's Eye -832 : Copperhorn Scout -831 : Safe Passage -830 : Harmless Assault -830 : Armored Cancrix -829 : Bull Rush -828 : Harbor Serpent -828 : Merfolk Spy -827 : Leyline of Anticipation -827 : Unholy Strength -825 : Assault Strobe -821 : Holy Strength -821 : Jinxed Idol -819 : Beast Hunt -817 : Merfolk Observer -817 : Leyline of the Void -816 : Bog Raiders -816 : Goblin Balloon Brigade -816 : Phantom Beast -815 : Duress -814 : Repay In Kind -814 : Primal Cocoon -813 : Clone Shell -812 : Twisted Image -812 : Painful Quandary -812 : Haze Frog -810 : Panic Spellbomb -810 : Blunt the Assault -810 : Mire's Toll -808 : Necrogen Censer -808 : Curse of Wizardry -807 : Ravenous Trap -807 : Shared Discovery -806 : Desecrated Earth -806 : Accorder's Shield -806 : Venser's Journal -806 : Leyline of Punishment -805 : Turn Aside -805 : Fleeting Distraction -804 : Demolish -803 : Raid Bombardment -803 : Maritime Guard -803 : Wall of Vines -801 : Roiling Terrain -800 : Jace's Erasure -797 : Phantasmal Abomination -797 : Bojuka Bog -796 : Perish the Thought -796 : Demystify -793 : Sunspring Expedition -792 : Blistergrub -792 : Death Cultist -792 : Crab Umbra -790 : Caravan Hurda -790 : Ancient Stirrings -790 : Gravity Well -790 : Nature's Spiral -786 : Goblin Gaveleer -786 : Molten Psyche -786 : Dispel -785 : Ajani's Mantra -783 : Memoricide -782 : Razor Boomerang -782 : Feral Contest -780 : Hornet Sting -778 : Shape Anew -778 : Walking Atlas -777 : Jwari Scuttler -777 : Dragon's Claw -776 : Demon's Horn -775 : Leyline of Sanctity -775 : Tireless Missionaries -774 : Fulgent Distraction -774 : Loxodon Wayfarer -773 : Unified Will -764 : Trapfinder's Trick -763 : Trigon of Mending -758 : Quest for the Goblin Lord -756 : Pyretic Ritual -755 : Relic Putrescence -754 : Liquimetal Coating -750 : Darksteel Myr -750 : Nihil Spellbomb -750 : Goldenglow Moth -747 : Rumbling Aftershocks -745 : Fog -743 : Tome Scour -741 : Bloodcrazed Goblin -739 : Golem Foundry -739 : Viridian Revel -739 : Elixir of Immortality -739 : Wild Evocation -734 : Haunting Echoes -732 : Contaminated Ground -732 : Blood Tithe -726 : Enatu Golem -724 : Aura Finesse -723 : Back to Nature -721 : Demonic Appetite -715 : Vault Skyward -712 : Nighthaze -710 : Autumn's Veil -703 : Melt Terrain -702 : Reinforced Bulwark -696 : Vigil for the Lost -693 : Dryad's Favor -692 : Golden Urn -688 : Fissure Vent -686 : Living Destiny -684 : Ornithopter -679 : Echo Circlet -678 : Runed Servitor -669 : Hunters' Feast -650 : Liliana's Caress -644 : Not Of This World -640 : Golem's Heart -633 : Swamp -633 : Mountain -615 : Whitesun's Passage -612 : Sorcerer's Strongbox -604 : Incite -588 : Forest -586 : Voltaic Key -577 : Plains -574 : Island -572 : Tectonic Edge -554 : Angel's Feather -535 : Wurm's Tooth diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/aer.csv b/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/aer.csv new file mode 100644 index 00000000000..8801646b1ab --- /dev/null +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/aer.csv @@ -0,0 +1,184 @@ +Ajani Unyielding:40114 +Herald of Anguish:39905 +Rishkar, Peema Renegade:39137 +Aethersphere Harvester:38827 +Heart of Kiran:37403 +Yahenni’s Expertise:37199 +Tezzeret the Schemer:34694 +Solemn Recruit:34338 +Untethered Express:33419 +Battle at the Bridge:33072 +Yahenni, Undying Partisan:32377 +Fatal Push:32126 +Sram’s Expertise:32076 +Walking Ballista:31052 +Baral’s Expertise:30879 +Freejam Regent:30870 +Glint-Sleeve Siphoner:30022 +Ridgescale Tusker:30018 +Quicksmith Spy:29214 +Scrapper Champion:29176 +Aethertide Whale:28976 +Daring Demolition:28538 +Gifted Aetherborn:28163 +Quicksmith Rebel:27792 +Hungry Flames:27737 +Thopter Arrest:27574 +Exquisite Archangel:27415 +Kari Zev, Skyship Raider:27188 +Aetherwind Basker:26371 +Treasure Keeper:26283 +Greenbelt Rampager:26185 +Vengeful Rebel:25902 +Aethergeode Miner:25711 +Rishkar’s Expertise:25327 +Lightning Runner:25297 +Shock:25129 +Caught in the Brights:24815 +Lifecrafter’s Bestiary:24466 +Midnight Entourage:23732 +Sram, Senior Edificer:23386 +Metallic Mimic:23383 +Maulfist Revolutionary:23093 +Greenwheel Liberator:21817 +Chandra’s Revolution:21713 +Maverick Thopterist:21685 +Airdrop Aeronauts:21061 +Narnam Renegade:20406 +Winding Constrictor:20174 +Scrap Trawler:20001 +Monstrous Onslaught:19528 +Wind-Kin Raiders:19507 +Deadeye Harpooner:19305 +Skyship Plunderer:18967 +Aether Poisoner:18617 +Cruel Finality:18352 +Release the Gremlins:18286 +Aether Chaser:17813 +Rogue Refiner:17646 +Reckless Racer:17299 +Dawnfeather Eagle:17238 +Felidar Guardian:17122 +Prey Upon:16986 +Spire Patrol:16942 +Druid of the Cowl:16941 +Aetherstream Leopard:16826 +Reverse Engineer:15858 +Daredevil Dragster:15795 +Shielded Aether Thief:15596 +Scrounging Bandar:14827 +Lifecraft Cavalry:14821 +Pacification Array:14672 +Renegade Rallier:14442 +Trophy Mage:14084 +Enraged Giant:13989 +Foundry Hornet:13907 +Call for Unity:13832 +Renegade Wheelsmith:13717 +Peacewalker Colossus:13604 +Sweatworks Brawler:13229 +Aether Swooper:13171 +Outland Boar:13074 +Restoration Specialist:12713 +Perilous Predicament:12702 +Aeronaut Admiral:12409 +Tezzeret’s Touch:12281 +Oath of Ajani:11663 +Bastion Inventor:11485 +Weldfast Engineer:11309 +Countless Gears Renegade:11144 +Mechanized Production:10887 +Hinterland Drake:10667 +Consulate Crackdown:10549 +Renegade Map:10115 +Peema Aether-Seer:9906 +Unbridled Growth:9661 +Lifecraft Awakening:9620 +Baral, Chief of Compliance:9382 +Merchant’s Dockhand:9033 +Barricade Breaker:8635 +Lifecrafter’s Gift:8248 +Hidden Herbalists:8012 +Mobile Garrison:7976 +Aether Herder:7964 +Disallow:7550 +Kari Zev’s Expertise:7472 +Cogwork Assembler:7463 +Heroic Intervention:6922 +Hidden Stockpile:6732 +Illusionist’s Stratagem:6678 +Leave in the Dust:6675 +Ghirapur Osprey:6597 +Decommission:6354 +Ice Over:6297 +Night Market Aeronaut:6198 +Gremlin Infestation:6195 +Spire of Industry:6181 +Audacious Infiltrator:6084 +Sly Requisitioner:5718 +Alley Strangler:5595 +Silkweaver Elite:5574 +Aid from the Cowl:5463 +Highspire Infusion:5402 +Frontline Rebel:5350 +Invigorated Rampage:5268 +Defiant Salvager:5211 +Watchful Automaton:5147 +Siege Modification:5142 +Inspiring Statuary:4932 +Embraal Gear-Smasher:4847 +Deft Dismissal:4727 +Shipwreck Moray:4645 +Metallic Rebuke:4618 +Dispersal Technician:4389 +Resourceful Return:4325 +Efficient Construction:4108 +Welder Automaton:4076 +Aether Inspector:3989 +Ravenous Intruder:3963 +Ironclad Revolutionary:3930 +Implement of Ferocity:3720 +Alley Evasion:3712 +Hope of Ghirapur:3699 +Aerial Modification:3671 +Gonti’s Aether Heart:3295 +Foundry Assembler:3292 +Fen Hauler:3265 +Natural Obsolescence:3262 +Destructive Tampering:3239 +Implement of Examination:3217 +Irontread Crusher:3097 +Filigree Crawler:3020 +Servo Schematic:3006 +Verdant Automaton:2979 +Reservoir Walker:2918 +Whir of Invention:2916 +Paradox Engine:2714 +Salvage Scuttler:2677 +Augmenting Automaton:2636 +Fourth Bridge Prowler:2448 +Conviction:2411 +Lathnu Sailback:2352 +Planar Bridge:2348 +Night Market Guard:2244 +Bastion Enforcer:2236 +Precise Strike:2179 +Universal Solvent:2128 +Implement of Malice:2089 +Crackdown Construct:1926 +Dark Intimations:1876 +Pia’s Revolution:1850 +Renegade’s Getaway:1472 +Aegis Automaton:1355 +Consulate Dreadnought:1255 +Indomitable Creativity:1206 +Negate:1016 +Consulate Turret:1014 +Implement of Combustion:806 +Take into Custody:678 +Implement of Improvement:624 +Wrangle:543 +Ornithopter:177 +Gonti’s Machinations:167 +Prizefighter Construct:123 +Secret Salvage:77 \ No newline at end of file diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/akh.csv b/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/akh.csv new file mode 100644 index 00000000000..168d2671cc7 --- /dev/null +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/akh.csv @@ -0,0 +1,249 @@ +Angel of Sanctions:1638 +Glorybringer:1590 +Oketra the True:1512 +Rhonas the Indomitable:1456 +Gideon of the Trials:1445 +Hazoret the Fervent:1404 +Liliana, Death’s Majesty:1370 +Archfiend of Ifnir:1346 +Cast Out:1331 +Curator of Mysteries:1329 +Regal Caracal:1324 +Glyph Keeper:1312 +Cut /// Ribbons:1310 +Dusk /// Dawn:1266 +Vizier of Many Faces:1252 +Never /// Return:1251 +Vizier of the Menagerie:1243 +Heart-Piercer Manticore:1220 +Liliana’s Mastery:1216 +Trial of Zeal:1195 +Samut, Voice of Dissent:1190 +Nissa, Steward of Elements:1174 +Magma Spray:1157 +Honored Hydra:1132 +Sweltering Suns:1126 +Glory-Bound Initiate:1125 +Lord of the Accursed:1119 +Ahn-Crop Crasher:1115 +Insult /// Injury:1113 +Champion of Rhonas:1096 +Plague Belcher:1095 +Angler Drake:1091 +Cartouche of Strength:1089 +Electrify:1083 +Combat Celebrant:1079 +Compulsory Rest:1073 +Crocodile of the Crossing:1061 +Gust Walker:1058 +Scaled Behemoth:1055 +Decimator Beetle:1050 +Bone Picker:1048 +Drake Haven:1042 +Mouth /// Feed:1039 +Channeler Initiate:1038 +Deem Worthy:1031 +Bontu the Glorified:1022 +Trial of Solidarity:1018 +Final Reward:1013 +Stir the Sands:1010 +Hapatra, Vizier of Poisons:1009 +Start /// Finish:1005 +Trial of Strength:1002 +Emberhorn Minotaur:999 +Prepare /// Fight:998 +Baleful Ammit:997 +Cartouche of Knowledge:989 +Cruel Reality:989 +Sandwurm Convergence:973 +Prowling Serpopard:965 +Trial of Ambition:962 +Devoted Crop-Mate:959 +Oketra’s Attendant:955 +Commit /// Memory:952 +Neheb, the Worthy:952 +Aven Wind Guide:944 +Bloodrage Brawler:944 +Fan Bearer:936 +Dread Wanderer:930 +Temmet, Vizier of Naktamun:924 +Oketra’s Monument:921 +Edifice of Authority:919 +Cartouche of Ambition:918 +Wayward Servant:905 +Lay Claim:903 +Splendid Agony:896 +Tah-Crop Elite:894 +Kefnet the Mindful:884 +Gravedigger:871 +Harsh Mentor:864 +Soulstinger:863 +Exemplar of Strength:862 +Cartouche of Zeal:861 +Defiant Greatmaw:846 +Enigma Drake:846 +Cartouche of Solidarity:840 +Labyrinth Guardian:836 +Vizier of Deferment:835 +Naga Vitalist:834 +Pull from Tomorrow:832 +Rags /// Riches:832 +Khenra Charioteer:829 +Hooded Brawler:828 +Horror of the Broken Lands:815 +Trueheart Duelist:815 +Honored Crop-Captain:813 +Bitterblade Warrior:812 +Shefet Monitor:808 +Heaven /// Earth:807 +Seraph of the Suns:805 +Nef-Crop Entangler:803 +Greater Sandwurm:802 +Ruthless Sniper:799 +Cursed Minotaur:798 +Rhet-Crop Spearmaster:796 +Soul-Scar Mage:796 +Trial of Knowledge:787 +Trueheart Twins:785 +Battlefield Scavenger:784 +Aven Initiate:782 +Wasteland Scorpion:778 +Impeccable Timing:774 +Essence Scatter:773 +Open into Wonder:769 +Unwavering Initiate:767 +Warfire Javelineer:765 +Manticore of the Gauntlet:762 +Binding Mummy:760 +Approach of the Second Sun:758 +Ahn-Crop Champion:757 +Synchronized Strike:756 +Winged Shepherd:747 +Ornery Kudu:742 +Cryptic Serpent:741 +Shimmerscale Drake:739 +Hieroglyphic Illumination:737 +Censor:733 +Illusory Wrappings:731 +Watchful Naga:731 +Vizier of Tumbling Sands:724 +Minotaur Sureshot:720 +Rhonas’s Monument:719 +Galestrike:718 +Merciless Javelineer:718 +Bounty of the Luxa:712 +Aven Mindcensor:708 +Naga Oracle:705 +Thresher Lizard:692 +Quarry Hauler:689 +Irrigated Farmland:688 +Pathmaker Initiate:681 +Shadowstorm Vizier:678 +Grim Strider:676 +Flameblade Adept:674 +Sheltered Thicket:672 +Destined /// Lead:668 +Wander in Death:668 +Weaver of Currents:663 +Blighted Bat:651 +Nest of Scarabs:648 +Oracle’s Vault:646 +Canyon Slough:643 +Evolving Wilds:640 +Colossapede:638 +Sacred Cat:637 +Doomed Dissenter:635 +Fetid Pools:628 +Festering Mummy:616 +Onward /// Victory:615 +Throne of the God-Pharaoh:613 +Anointed Procession:608 +Gift of Paradise:602 +Anointer Priest:599 +Consuming Fervor:595 +Limits of Solidarity:594 +Spring /// Mind:593 +Desert Cerodon:592 +Sparring Mummy:592 +River Serpent:584 +Seeker of Insight:582 +Shed Weakness:582 +Gideon’s Intervention:580 +Slither Blade:580 +Tah-Crop Skirmisher:580 +Initiate’s Companion:570 +Pitiless Vizier:567 +Scattered Groves:563 +Supernatural Stamina:563 +Vizier of Remedies:563 +Hekma Sentinels:562 +Bloodlust Inciter:559 +Pouncing Cheetah:559 +Winds of Rebuke:550 +Cancel:540 +Painful Lesson:536 +Mighty Leap:535 +Pyramid of the Pantheon:535 +Reduce /// Rubble:533 +Brute Strength:530 +Floodwaters:530 +Faith of the Devoted:529 +Manglehorn:529 +Miasmic Mummy:522 +Fling:519 +Oashra Cultivator:512 +In Oketra’s Name:510 +Forsake the Worldly:506 +Supply Caravan:505 +Time to Reflect:505 +Decision Paralysis:504 +Giant Spider:504 +Hapatra’s Mark:500 +Nimble-Blade Khenra:499 +Harvest Season:497 +Failure /// Comply:496 +Zenith Seeker:494 +Those Who Serve:491 +Bontu’s Monument:488 +As Foretold:487 +Tormenting Voice:487 +Hazoret’s Monument:485 +New Perspectives:484 +Pursue Glory:478 +Unburden:476 +Djeru’s Resolve:469 +Spidery Grasp:468 +Kefnet’s Monument:466 +Lay Bare the Heart:464 +Scribe of the Mindful:463 +Honed Khopesh:450 +Stinging Shot:443 +Trespasser’s Curse:431 +Blazing Volley:430 +Watchers of the Dead:415 +Sixth Sense:413 +Dune Beetle:386 +Cradle of the Accursed:382 +Glorious End:380 +Sacred Excavation:379 +Grasping Dunes:372 +Shadow of the Grave:370 +Cascading Cataracts:357 +Hyena Pack:356 +Benefaction of Rhonas:354 +Dissenter’s Deliverance:353 +Painted Bluffs:348 +Renewed Faith:337 +Hazoret’s Favor:305 +Violent Impact:284 +Haze of Pollen:277 +Scarab Feast:268 +Compelling Argument:265 +Embalmer’s Tools:260 +Luxa River Shrine:213 +By Force:201 +Ancient Crab:198 +Sunscorched Desert:186 +Dispossess:109 +Protection of the Hekma:108 +Gate to the Afterlife 95 \ No newline at end of file diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/dom.csv b/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/dom.csv new file mode 100644 index 00000000000..b14997dc930 --- /dev/null +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/dom.csv @@ -0,0 +1,249 @@ +Lyra Dawnbringer:2375 +Karn, Scion of Urza:2372 +Shalai, Voice of Plenty:2234 +Teferi, Hero of Dominaria:2215 +Verix Bladewing:2207 +Aryel, Knight of Windgrace:2166 +Multani, Yavimaya’s Avatar:2150 +History of Benalia:2123 +Siege-Gang Commander:2091 +In Bolas’s Clutches:2047 +Josu Vess, Lich Knight:2044 +Cast Down:2025 +Demonlord Belzenlok:2016 +Eviscerate:2010 +Serra Angel:2000 +Slimefoot, the Stowaway:1995 +Seal Away:1985 +Tatyova, Benthic Druid:1981 +Zahid, Djinn of the Lamp:1971 +Darigaaz Reincarnated:1959 +Weatherlight:1952 +Phyrexian Scriptures:1951 +Forebear’s Blade:1928 +Adeliz, the Cinder Wind:1919 +The Eldest Reborn:1919 +Teshar, Ancestor’s Apostle:1913 +Territorial Allosaurus:1896 +Danitha Capashen, Paragon:1895 +Muldrotha, the Gravetide:1881 +Fight with Fire:1879 +Shivan Fire:1879 +Helm of the Host:1876 +Knight of Grace:1863 +Vicious Offering:1859 +Pegasus Courser:1856 +Icy Manipulator:1849 +Benalish Marshal:1837 +Untamed Kavu:1836 +Goblin Chainwhirler:1834 +Raff Capashen, Ship’s Mage:1834 +Blessed Light:1833 +Rite of Belzenlok:1827 +Naru Meha, Master Wizard:1824 +Grand Warlord Radha:1817 +Two-Headed Giant:1817 +Llanowar Elves:1815 +Shanna, Sisay’s Legacy:1814 +Steel Leaf Champion:1811 +Song of Freyalise:1807 +Settle the Score:1804 +Time of Ice:1804 +Grunn, the Lonely King:1793 +Knight of Malice:1786 +Arvad the Cursed:1783 +Jhoira, Weatherlight Captain:1780 +Saproling Migration:1780 +Wizard’s Lightning:1779 +Tempest Djinn:1777 +Urgoros, the Empty One:1773 +Cloudreader Sphinx:1769 +Baloth Gorger:1768 +Skittering Surveyor:1765 +Baird, Steward of Argive:1762 +Blackblade Reforged:1760 +Hallar, the Firefletcher:1760 +On Serra’s Wings:1753 +Evra, Halcyon Witness:1748 +Traxos, Scourge of Kroog:1746 +Blink of an Eye:1742 +Triumph of Gerrard:1725 +Deep Freeze:1723 +Kazarov, Sengir Pureblood:1718 +Tiana, Ship’s Caretaker:1712 +Merfolk Trickster:1709 +Squee, the Immortal:1708 +Valduk, Keeper of the Flame:1708 +Kwende, Pride of Femeref:1707 +Whisper, Blood Liturgist:1707 +Academy Drake:1705 +Jaya Ballard:1704 +Gideon’s Reproach:1703 +Warcry Phoenix:1703 +Sporecrown Thallid:1698 +Yavimaya Sapherd:1692 +Rona, Disciple of Gix:1686 +Wizard’s Retort:1684 +Elfhame Druid:1683 +Fiery Intervention:1682 +Torgaar, Famine Incarnate:1682 +Yawgmoth’s Vile Offering:1677 +Deathbloom Thallid:1665 +Fungal Infection:1662 +Daring Archaeologist:1658 +Cold-Water Snapper:1656 +Thorn Elemental:1656 +Call the Cavalry:1649 +Sylvan Awakening:1648 +Jaya’s Immolating Inferno:1646 +Verdant Force:1642 +Fungal Plots:1636 +Spore Swarm:1635 +Divination:1629 +Syncopate:1626 +Marwyn, the Nurturer:1625 +Sergeant-at-Arms:1625 +Garna, the Bloodflame:1624 +Ghitu Chronicler:1622 +Tetsuko Umezawa, Fugitive:1612 +Dread Shade:1602 +Stronghold Confessor:1601 +Academy Journeymage:1599 +Chainer’s Torment:1593 +Thallid Omnivore:1592 +Thallid Soothsayer:1592 +Jousting Lance:1587 +Firefist Adept:1581 +Goblin Barrage:1580 +Naban, Dean of Iteration:1579 +Caligo Skin-Witch:1577 +Karn’s Temporal Sundering:1577 +Keldon Overseer:1574 +Dauntless Bodyguard:1572 +Opt:1572 +Ghitu Journeymage:1570 +The Mending of Dominaria:1568 +The Mirari Conjecture:1568 +Wild Onslaught:1567 +Haphazard Bombardment:1566 +Skizzik:1565 +Mammoth Spider:1558 +Serra Disciple:1558 +Clifftop Retreat:1557 +Aven Sentry:1556 +Mishra’s Self-Replicator:1552 +Ancient Animus:1550 +D’Avenant Trapper:1550 +Gilded Lotus:1549 +Jhoira’s Familiar:1548 +Champion of the Flame:1547 +Ghitu Lavarunner:1547 +Woodland Cemetery:1543 +Keldon Raider:1541 +Grow from the Ashes:1536 +Radiating Lightning:1536 +Sanctum Spirit:1533 +Windgrace Acolyte:1532 +Urza’s Ruinous Blast:1531 +Sulfur Falls:1527 +The Antiquities War:1522 +Adamant Will:1519 +Goblin Warchief:1518 +Adventurous Impulse:1516 +Mesa Unicorn:1512 +Bloodtallow Candle:1510 +Hinterland Harbor:1509 +Lingering Phantom:1506 +Short Sword:1499 +Llanowar Scout:1495 +Juggernaut:1493 +Frenzied Rage:1490 +Slinn Voda, the Rising Deep:1489 +Dub:1484 +Cabal Paladin:1482 +Gift of Growth:1482 +Dark Bargain:1481 +Benalish Honor Guard:1480 +Isolated Chapel:1473 +Kamahl’s Druidic Vow:1472 +Memorial to Glory:1469 +Sentinel of the Pearl Trident:1466 +Krosan Druid:1465 +Guardians of Koilos:1457 +Llanowar Envoy:1455 +Pardic Wanderer:1450 +Soul Salvage:1449 +The Flame of Keld:1448 +Arcane Flight:1445 +Divest:1444 +Feral Abomination:1441 +Artificer’s Assistant:1439 +Memorial to Unity:1439 +Yargle, Glutton of Urborg:1436 +Sparring Construct:1431 +Mox Amber:1429 +Weight of Memory:1426 +Precognition Field:1424 +The First Eruption:1420 +Invoke the Divine:1414 +Unwind:1413 +Primordial Wurm:1409 +Bloodstone Goblin:1408 +Vodalian Arcanist:1401 +Cabal Stronghold:1400 +Urza’s Tome:1393 +Lich’s Mastery:1390 +Primevals’ Glorious Rebirth:1390 +Run Amok:1390 +Gaea’s Protector:1382 +Pierce the Sky:1382 +Relic Runner:1381 +Jodah, Archmage Eternal:1378 +Excavation Elephant:1377 +Knight of New Benalia:1377 +Aesthir Glider:1376 +Befuddle:1375 +Homarid Explorer:1372 +Memorial to Folly:1371 +Howling Golem:1369 +Voltaic Servant:1369 +Nature’s Spiral:1368 +Sorcerer’s Wand:1366 +Corrosive Ooze:1360 +Broken Bond:1357 +Curator’s Ward:1355 +Tolarian Scholar:1354 +Memorial to Genius:1349 +Rampaging Cyclops:1347 +Warlord’s Fury:1328 +Fervent Strike:1321 +Demonic Vigor:1320 +Keldon Warcaller:1319 +Arbor Armament:1314 +Final Parting:1313 +Diligent Excavator:1312 +Navigator’s Compass:1308 +Charge:1307 +Amaranthine Wall:1305 +Cabal Evangel:1305 +Fire Elemental:1304 +Shield of the Realm:1304 +Oath of Teferi:1300 +Tragic Poet:1283 +Blessing of Belzenlok:1272 +Board the Weatherlight:1258 +Thran Temporal Gateway:1256 +Drudge Sentinel:1248 +Orcish Vandal:1247 +Skirk Prospector:1246 +Zhalfirin Void:1239 +Sage of Lat-Nam:1232 +Rescue:1225 +Gaea’s Blessing:1218 +Healing Grace:1200 +Rat Colony:1191 +Powerstone Shard:1162 +Seismic Shift:1152 +Damping Sphere:1133 +Fall of the Thran:1104 +Memorial to War:1089 \ No newline at end of file diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/grn.csv b/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/grn.csv new file mode 100644 index 00000000000..b8ec1234861 --- /dev/null +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/grn.csv @@ -0,0 +1,259 @@ +Doom Whisperer:2332 +Aurelia, Exemplar of Justice:2258 +Vraska, Golgari Queen:2211 +Ral, Izzet Viceroy:2196 +Dream Eater:2180 +Thief of Sanity:2164 +Assassin's Trophy:2153 +Trostani Discordant:2141 +Beast Whisperer:2102 +Nullhide Ferox:2102 +Legion Warboss:2100 +March of the Multitudes:2094 +Conclave Tribunal:2092 +Niv-Mizzet, Parun:2088 +Light of the Legion:2073 +Price of Fame:2036 +Etrata, the Silencer:2019 +Venerated Loxodon:2017 +Justice Strike:2016 +Tajic, Legion's Edge:2005 +Underrealm Lich:1985 +Pelt Collector:1984 +Izoni, Thousand-Eyed:1977 +Find // Finality:1976 +Lazav, the Multifarious:1973 +Nightveil Sprite:1968 +Midnight Reaper:1964 +Lava Coil:1963 +Watcher in the Mist:1961 +Response // Resurgence:1958 +Knight of Autumn:1950 +Dimir Spybug:1948 +Integrity // Intervention:1945 +Nightveil Predator:1943 +Emmara, Soul of the Accord:1942 +Luminous Bonds:1932 +Artful Takedown:1923 +Ritual of Soot:1914 +Blood Operative:1903 +Conclave Cavalier:1902 +Truefire Captain:1902 +Runaway Steam-Kin:1901 +Murmuring Mystic:1899 +Arclight Phoenix:1894 +Risk Factor:1893 +Boros Challenger:1887 +Dead Weight:1887 +Bounty of Might:1886 +Connive // Concoct:1886 +Status // Statue:1885 +Deadly Visit:1878 +Deafening Clarion:1878 +Roc Charger:1864 +Kraul Harpooner:1839 +Citywatch Sphinx:1837 +Assure // Assemble:1836 +Expansion // Explosion:1836 +Capture Sphere:1834 +Thoughtbound Phantasm:1832 +Crackling Drake:1830 +Dawn of Hope:1827 +Disinformation Campaign:1826 +House Guildmage:1824 +Quasiduplicate:1816 +Sunhome Stalwart:1815 +Skyknight Legionnaire:1805 +Darkblade Agent:1788 +Plaguecrafter:1786 +Goblin Cratermaker:1773 +Affectionate Indrik:1772 +Whisper Agent:1771 +Notion Rain:1761 +Ledev Champion:1757 +Charnel Troll:1751 +Thought Erasure:1750 +Golgari Findbroker:1749 +Chemister's Insight:1743 +Goblin Banneret:1737 +Swiftblade Vindicator:1736 +Command the Storm:1728 +Camaraderie:1726 +Wee Dragonauts:1723 +District Guide:1722 +Hypothesizzle:1715 +League Guildmage:1712 +Direct Current:1711 +Experimental Frenzy:1711 +Discovery // Dispersal:1708 +Rampaging Monument:1705 +Rosemane Centaur:1698 +Inescapable Blaze:1693 +Watery Grave:1687 +Legion Guildmage:1680 +Chamber Sentry:1674 +Inspiring Unicorn:1671 +Ionize:1669 +Flower // Flourish:1663 +Divine Visitation:1656 +Dimir Informant:1653 +Healer's Hawk:1651 +Conclave Guildmage:1648 +Sinister Sabotage:1647 +Parhelion Patrol:1640 +Ochran Assassin:1639 +Goblin Electromancer:1634 +Glowspore Shaman:1631 +Siege Wurm:1629 +Wojek Bodyguard:1629 +Hellkite Whelp:1626 +Hired Poisoner:1625 +Unexplained Disappearance:1625 +Overgrown Tomb:1624 +Prey Upon:1624 +Pitiless Gorgon:1622 +Flight of Equenauts:1621 +Hatchery Spider:1621 +Temple Garden:1621 +Beacon Bolt:1620 +Citywide Bust:1615 +Bounty Agent:1613 +Piston-Fist Cyclops:1605 +Steam Vents:1600 +Erratic Cyclops:1582 +Swarm Guildmage:1582 +Sacred Foundry:1581 +Mission Briefing:1580 +Muse Drake:1574 +Arboretum Elemental:1572 +Worldsoul Colossus:1572 +Skyline Scout:1569 +Smelt-Ward Minotaur:1568 +Burglar Rat:1561 +Whispering Snitch:1560 +Fresh-Faced Recruit:1555 +Necrotic Wound:1554 +Electrostatic Field:1541 +Disdainful Stroke:1534 +Gruesome Menagerie:1534 +Sprouting Renewal:1534 +Sonic Assault:1533 +Sure Strike:1527 +Severed Strands:1522 +Beamsplitter Mage:1521 +Chromatic Lantern:1516 +Ledev Guardian:1510 +Radical Idea:1502 +Pilfering Imp:1500 +Vernadi Shieldmate:1497 +Ornery Goblin:1495 +Gatekeeper Gargoyle:1489 +Barging Sergeant:1484 +Blade Instructor:1483 +Rhizome Lurcher:1481 +Invert // Invent:1477 +Ironshell Beetle:1477 +Generous Stray:1474 +Demotion:1469 +Might of the Masses:1468 +Molderhulk:1467 +Selective Snare:1466 +Hammer Dropper:1463 +Swathcutter Giant:1462 +Firemind's Research:1460 +Devkarin Dissident:1459 +Mnemonic Betrayal:1459 +Vigorspore Wurm:1459 +Haazda Marshal:1457 +Lotleth Giant:1455 +Righteous Blow:1451 +Fire Urchin:1446 +Gird for Battle:1441 +Kraul Swarm:1437 +Veiled Shade:1437 +Centaur Peacemaker:1434 +Golgari Raiders:1434 +Passwall Adept:1434 +Sworn Companions:1434 +Erstwhile Trooper:1432 +Hunted Witness:1431 +Kraul Foragers:1431 +Collar the Culprit:1427 +Mausoleum Secrets:1424 +Take Heart:1424 +Dazzling Lights:1419 +Rubblebelt Boar:1418 +Sumala Woodshaper:1418 +Intrusive Packbeast:1416 +Loxodon Restorer:1415 +Omnispell Adept:1415 +Spinal Centipede:1415 +Glaive of the Guildpact:1414 +Vivid Revival:1410 +Douser of Lights:1409 +Devious Cover-Up:1404 +Chance for Glory:1402 +Child of Night:1402 +Enhanced Surveillance:1399 +Hitchclaw Recluse:1398 +Mephitic Vapors:1395 +Circuitous Route:1389 +Cosmotronic Wave:1389 +Leapfrog:1379 +Goblin Locksmith:1377 +Guildmages' Forum:1370 +Guild Summit:1368 +Bartizan Bats:1367 +Undercity Uprising:1363 +Thousand-Year Storm:1355 +Drowned Secrets:1349 +Boros Guildgate :1345 +Grappling Sundew:1344 +Boros Guildgate :1343 +Tenth District Guard:1342 +Izzet Guildgate :1338 +Crushing Canopy:1335 +Portcullis Vine:1333 +Undercity Necrolisk:1332 +Dimir Guildgate :1331 +Barrier of Bones:1327 +Wild Ceratok:1327 +Izzet Guildgate :1326 +Gravitic Punch:1320 +Silent Dart:1310 +Wary Okapi:1309 +Pack's Favor:1307 +Garrison Sergeant:1303 +Vedalken Mesmerist:1303 +Golgari Guildgate :1295 +Golgari Guildgate :1286 +Dimir Guildgate :1280 +Maniacal Rage:1280 +Selesnya Guildgate :1280 +Urban Utopia:1278 +Wall of Mist:1273 +Maximize Altitude:1268 +Join Shields:1267 +Selesnya Guildgate :1266 +Book Devourer:1263 +Wishcoin Crab:1262 +Narcomoeba:1257 +Crush Contraband:1248 +Gateway Plaza:1248 +Fearless Halberdier:1246 +Torch Courier:1242 +Candlelight Vigil:1241 +Moodmark Painter:1230 +Creeping Chill:1218 +Izzet Locket:1217 +Dimir Locket:1202 +Maximize Velocity:1200 +Unmoored Ego:1184 +Never Happened:1175 +Golgari Locket:1173 +Selesnya Locket:1154 +Boros Locket:1128 +Street Riot:1110 +Vicious Rumors:1101 +Pause for Reflection:1089 +Wand of Vertebrae:1073 \ No newline at end of file diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/hou.csv b/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/hou.csv new file mode 100644 index 00000000000..5687f1f849e --- /dev/null +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/hou.csv @@ -0,0 +1,184 @@ +The Scarab God:2272 +Angel of Condemnation:2079 +The Locust God:2077 +The Scorpion God:2048 +Pride Sovereign:2046 +Crested Sunmare:1996 +Nicol Bolas, God-Pharaoh:1965 +Majestic Myriarch:1915 +Neheb, the Eternal:1906 +Hour of Devastation:1901 +Adorned Pouncer:1889 +Ammit Eternal:1881 +Samut, the Tested:1874 +Razaketh, the Foulblooded:1856 +Grind // Dust:1855 +Resilient Khenra:1832 +Sand Strangler:1822 +Ramunap Hydra:1818 +Abrade:1816 +Desert’s Hold:1813 +Champion of Wits:1810 +Bontu’s Last Reckoning:1807 +Nimble Obstructionist:1796 +Chaos Maw:1788 +Sifter Wurm:1783 +Unesh, Criosphinx Sovereign:1776 +Hour of Glory:1771 +River Hoopoe:1769 +Ominous Sphinx:1754 +Torment of Hailfire:1754 +Open Fire:1751 +Torment of Venom:1743 +Dreamstealer:1740 +Struggle // Survive:1737 +Burning-Fist Minotaur:1734 +Ambuscade:1732 +God-Pharaoh’s Gift:1731 +Accursed Horde:1729 +Doomfall:1727 +Earthshaker Khenra:1716 +Aerial Guide:1711 +Khenra Scrapper:1709 +Oketra’s Avenger:1691 +Bloodwater Entity:1689 +Rhonas’s Last Stand:1686 +Angel of the God-Pharaoh:1685 +Tenacious Hunter:1685 +Hour of Promise:1684 +Eternal of Harsh Truths:1680 +Fervent Paincaster:1677 +Lethal Sting:1673 +Vizier of the Anointed:1673 +Wildfire Eternal:1671 +Puncturing Blow:1668 +Sandblast:1668 +Sunscourge Champion:1661 +Spellweaver Eternal:1656 +Vizier of the True:1656 +Banewhip Punisher:1652 +Kefnet’s Last Word:1652 +Merciless Eternal:1648 +Vile Manifestation:1647 +Bitterbow Sharpshooters:1646 +Driven // Despair:1643 +Supreme Will:1638 +Hour of Revelation:1637 +Torment of Scarabs:1637 +Oasis Ritualist:1636 +Farm // Market:1628 +Unraveling Mummy:1628 +Obelisk Spider:1617 +Mirage Mirror:1615 +Manticore Eternal:1613 +Resolute Survivors:1610 +Ruin Rat:1610 +Overwhelming Splendor:1608 +Unconventional Tactics:1608 +Hour of Eternity:1606 +Devotee of Strength:1605 +Sinuous Striker:1604 +Sunset Pyramid:1602 +Riddleform:1600 +Solitary Camel:1600 +Harrier Naga:1598 +Steward of Solidarity:1597 +Sidewinder Naga:1595 +Dauntless Aven:1591 +Feral Prowler:1591 +Thorned Moloch:1586 +Striped Riverwinder:1584 +Frontline Devastator:1580 +Appeal // Authority:1578 +Aven of Enduring Hope:1577 +Mummy Paramount:1571 +Uncage the Menagerie:1570 +Consign // Oblivion:1564 +Hollow One:1561 +Aven Reedstalker:1560 +Rhonas’s Stalwart:1559 +Unsummon:1557 +Desert of the Glorified:1556 +Manalith:1555 +Hope Tender:1551 +Granitic Titan:1550 +Ifnir Deadlands:1550 +Blur of Blades:1547 +Marauding Boneslasher:1547 +Shefet Dunes:1547 +Claim // Fame:1545 +Magmaroth:1545 +Beneath the Sands:1543 +Ramunap Excavator:1542 +Desert of the Mindful:1541 +Khenra Eternal:1541 +Reason // Believe:1541 +Rampaging Hippo:1540 +Unquenchable Thirst:1539 +Razaketh’s Rite:1537 +Saving Grace:1532 +Steadfast Sentinel:1531 +Wall of Forgotten Pharaohs:1531 +Imminent Doom:1530 +Defiant Khenra:1526 +Cunning Survivor:1525 +Ramunap Ruins:1525 +Hashep Oasis:1524 +Overcome:1523 +Abandoned Sarcophagus:1514 +Carrion Screecher:1514 +Firebrand Archer:1510 +Frilled Sandwalla:1507 +Hazoret’s Undying Fury:1505 +Inferno Jet:1499 +Crypt of the Eternals:1496 +Gift of Strength:1495 +Kindled Fury:1493 +Ipnu Rivulet:1492 +Act of Heroism:1491 +Without Weakness:1489 +Desert of the Indomitable:1487 +Fraying Sanity:1485 +Hostile Desert:1484 +Traveler’s Amulet:1482 +God-Pharaoh’s Faithful:1477 +Desert of the Fervent:1476 +Apocalypse Demon:1474 +Wretched Camel:1472 +Dagger of the Worthy:1468 +Refuse // Cooperate:1468 +Quarry Beetle:1464 +Countervailing Winds:1460 +Gilded Cerodon:1455 +Djeru, With Eyes Open:1450 +Strategic Planning:1450 +Tragic Lesson:1449 +Scrounger of Souls:1447 +Dune Diviner:1438 +Desert of the True:1436 +Chandra’s Defeat:1433 +Proven Combatant:1430 +Survivors’ Encampment:1427 +Djeru’s Renunciation:1425 +Disposal Mummy:1422 +Imaginary Threats:1418 +Moaning Wall:1416 +Dutiful Servants:1403 +Oketra’s Last Mercy:1403 +Crash Through:1400 +Lurching Rotbeast:1397 +Swarm Intelligence:1397 +Life Goes On:1395 +Grisly Survivor:1388 +Dunes of the Dead:1381 +Jace’s Defeat:1369 +Endless Sands:1367 +Seer of the Last Tomorrow:1360 +Graven Abomination:1352 +Gideon’s Defeat:1346 +Liliana’s Defeat:1345 +Leave // Chance:1324 +Solemnity:1265 +Scavenger Grounds:1256 +Crook of Condemnation:1228 +Nissa’s Defeat:1185 \ No newline at end of file diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/ima.csv b/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/ima.csv new file mode 100644 index 00000000000..d9afedab23a --- /dev/null +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/ima.csv @@ -0,0 +1,249 @@ +Consecrated Sphinx:2182 +Ancestral Vision:2144 +Archangel of Thune:2141 +Elesh Norn, Grand Cenobite:2135 +Mana Drain:2124 +Urabrask the Hidden:2107 +Sheoldred, Whispering One:2106 +Swords to Plowshares:2106 +Primeval Titan:2103 +Ob Nixilis, the Fallen:2081 +Doom Blade:2064 +Rampaging Baloths:2056 +Thundermaw Hellkite:2053 +Restoration Angel:2044 +Keiga, the Tide Star:2042 +Avacyn, Angel of Hope:2029 +Kiki-Jiki, Mirror Breaker:2024 +Kokusho, the Evening Star:2020 +Cryptic Command:2012 +Supreme Verdict:2002 +Genesis Hydra:2001 +Fireball:2000 +Emeria Angel:1992 +Austere Command:1969 +Blood Baron of Vizkopa:1968 +Lotus Cobra:1955 +Sphinx of Uthuun:1927 +Yosei, the Morning Star:1924 +Rift Bolt:1912 +Scourge of Valkas:1909 +Bogardan Hellkite:1907 +Ryusei, the Falling Star:1907 +Spiritmonger:1900 +Vorinclex, Voice of Hunger:1897 +Indulgent Tormentor:1888 +Heroes’ Bane:1885 +Jugan, the Rising Star:1877 +Simic Sky Swallower:1874 +Serra Angel:1873 +Grisly Spectacle:1865 +Rune-Scarred Demon:1864 +Channel:1861 +Hypersonic Dragon:1856 +Lightning Helix:1856 +Teferi, Mage of Zhalfir:1854 +Knight of the Reliquary:1848 +Thran Dynamo:1848 +Thoughtseize:1839 +Anger of the Gods:1836 +Savageborn Hydra:1829 +Charmbreaker Devils:1828 +Staggershock:1824 +Malfegor:1812 +Palladium Myr:1808 +Draconic Roar:1796 +Ulcerate:1795 +Heat Ray:1794 +Mahamoti Djinn:1793 +Hoarding Dragon:1786 +Corpsejack Menace:1783 +Abyssal Persecutor:1774 +Firemane Angel:1771 +Curse of Predation:1766 +Electrolyze:1754 +Reave Soul:1754 +Oblivion Stone:1744 +Overgrown Battlement:1738 +Claustrophobia:1736 +Obstinate Baloth:1732 +Blizzard Specter:1724 +Pillar of Flame:1724 +Wall of Roots:1723 +Undercity Troll:1721 +Cephalid Broker:1717 +Abzan Battle Priest:1716 +Abzan Falconer:1698 +Mind Stone:1697 +Illusory Ambusher:1691 +Fog Bank:1690 +Mana Leak:1689 +Genesis Wave:1686 +Condescend:1685 +Rosheen Meanderer:1682 +Aether Vial:1681 +Wing Shards:1680 +Bladewing the Risen:1677 +Vizkopa Guildmage:1671 +Aetherize:1669 +Bloodghast:1667 +Horizon Canopy:1662 +Noxious Dragon:1661 +Seeker of the Way:1657 +Azorius Charm:1650 +Topan Freeblade:1650 +Ajani’s Pridemate:1649 +Guttersnipe:1648 +Orzhov Basilica:1648 +Necropotence:1645 +Prodigal Pyromancer:1641 +Monastery Swiftspear:1639 +Phantom Monster:1637 +Search for Tomorrow:1637 +Phyrexian Rager:1630 +Frost Lynx:1624 +Carven Caryatid:1621 +Hunt the Weak:1621 +Izzet Boilerworks:1620 +Blinding Mage:1616 +Amass the Components:1610 +Iona’s Judgment:1605 +Repeal:1602 +Serra Ascendant:1601 +Star Compass:1600 +Kiln Fiend:1597 +Simic Growth Chamber:1596 +Auriok Champion:1592 +Illusory Angel:1588 +Day of the Dragons:1587 +Jungle Barrier:1586 +Rakdos Carnarium:1586 +Dimir Aqueduct:1575 +Golgari Rot Farm:1572 +Jin-Gitaxias, Core Augur:1570 +Bladewing’s Thrall:1562 +Mnemonic Wall:1562 +Ainok Bond-Kin:1561 +Crowned Ceratok:1556 +Jhessian Thief:1555 +Boros Garrison:1551 +Selesnya Sanctuary:1551 +Grove of the Burnwillows:1547 +Chronicler of Heroes:1546 +Glimpse the Unthinkable:1543 +Manakin:1537 +Riverwheel Aerialists:1531 +Guardian Idol:1525 +Assault Formation:1520 +Graven Cairns:1520 +Mer-Ek Nightblade:1519 +Stalwart Aven:1518 +Netcaster Spider:1516 +Angelic Accord:1514 +Doomed Traveler:1514 +Thrill-Kill Assassin:1514 +Distortion Strike:1511 +Azorius Chancery:1509 +Skywise Teachings:1503 +Borderland Marauder:1497 +Sustainer of the Realm:1495 +Furnace Whelp:1494 +Sultai Flayer:1493 +Ivy Elemental:1490 +Darksteel Axe:1487 +Gruul Turf:1486 +Path of Bravery:1485 +Wight of Precinct Six:1480 +Dissolve:1477 +Doorkeeper:1476 +Evolving Wilds:1472 +Keldon Halberdier:1468 +Foul-Tongue Invocation:1465 +Durkwood Baloth:1462 +Nantuko Shaman:1462 +Vent Sentinel:1461 +Scion of Ugin:1460 +Splatter Thug:1459 +Mishra’s Bauble:1458 +Child of Night:1454 +Ojutai’s Breath:1454 +Night of Souls’ Betrayal:1449 +Greater Basilisk:1448 +Butcher’s Glee:1446 +Surreal Memoir:1443 +Magus of the Moon:1438 +Battle-Rattle Shaman:1435 +Guard Duty:1429 +Sandstone Oracle:1426 +Enlarge:1425 +Jace’s Phantasm:1425 +Pristine Talisman:1424 +Duskdale Wurm:1423 +Elusive Spellfist:1423 +Dragon Egg:1421 +Flusterstorm:1421 +Kolaghan Monument:1415 +Balustrade Spy:1410 +Dragon Bell Monk:1407 +Student of Ojutai:1407 +Dragon Tempest:1406 +Angel of Mercy:1405 +Dragonloft Idol:1395 +Sanguine Bond:1394 +Dead Reveler:1393 +Wrench Mind:1393 +Diminish:1392 +Wildsize:1392 +Windfall:1392 +Guided Strike:1391 +Survival Cache:1391 +Lord of the Pit:1390 +Nimbus Maze:1390 +Rakdos Drake:1384 +Phantom Tiger:1381 +River of Tears:1381 +Moonglove Extract:1380 +Timberland Guide:1378 +Trepanation Blade:1378 +Burrenton Forge-Tender:1376 +Virulent Swipe:1376 +Hunting Pack:1367 +Fury Charm:1364 +Infantry Veteran:1360 +Coordinated Assault:1356 +Jaddi Offshoot:1353 +Inspiring Call:1350 +Shriekgeist:1349 +Thought Scour:1345 +Pentarch Ward:1344 +Bogbrew Witch:1343 +Tavern Swindler:1342 +Prey’s Vengeance:1341 +Serum Powder:1340 +Rotfeaster Maggot:1338 +Emerge Unscathed:1322 +Lead the Stampede:1322 +Bala Ged Scorpion:1321 +Dragonlord’s Servant:1321 +Great Teacher’s Decree:1313 +Eternal Thirst:1312 +Hammerhand:1302 +Haunting Hymn:1301 +Festering Newt:1287 +Tormenting Voice:1286 +Earth Elemental:1278 +Benevolent Ancestor:1264 +Trumpet Blast:1253 +Bewilder:1252 +Mark of Mutiny:1245 +Crucible of Fire:1242 +Bubbling Cauldron:1241 +Duress:1236 +Lure:1228 +Mindcrank:1225 +Radiant Fountain:1224 +Disenchant:1215 +Runed Servitor:1213 +Aerial Predation:1196 +Shimmering Grotto:1163 +Nature’s Claim:1137 \ No newline at end of file diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/kld.csv b/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/kld.csv new file mode 100644 index 00000000000..b477e4f3600 --- /dev/null +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/kld.csv @@ -0,0 +1,274 @@ +Sword of Feast and Famine:100 +Chandra, Torch of Defiance:99 +Skysovereign, Consul Flagship:98 +Noxious Gearhulk:97 +Sword of Fire and Ice:96 +Angel of Invention:95 +Verdurous Gearhulk:94 +Demon of Dark Schemes:94 +Sol Ring:93 +Cataclysmic Gearhulk:92 +Torrential Gearhulk:92 +Nissa, Vital Force:91 +Hangarback Walker:90 +Gonti, Lord of Luxury:90 +Steel Overseer:89 +Skyship Stalker:89 +Pia Nalaar:88 +Sword of Light and Shadow:88 +Smuggler's Copter:87 +Confiscation Coup:87 +Combustible Gearhulk:86 +Oviya Pashiri, Sage Lifecrafte:86 +Mana Crypt:86 +Solemn Simulacrum:85 +Mana Vault:85 +Harnessed Lightning:84 +Aetherstorm Roc:84 +Cultivator's Caravan:84 +Fairgrounds Warden:83 +Rashmi, Eternities Crafter:83 +Dovin Baan:83 +Aerial Responder:82 +Saheeli's Artistry:82 +Bristling Hydra:82 +Master Trinketeer:81 +Welding Sparks:81 +Cultivator of Blades:81 +Aethersquall Ancient:80 +Longtusk Cub:80 +Unlicensed Disintegration:80 +Snare Thopter:79 +Fleetwheel Cruiser:79 +Depala, Pilot Exemplar:79 +Multiform Wonder:79 +Cloudblazer:78 +Filigree Familiar:78 +Gauntlet of Power:78 +Skywhaler's Shot:78 +Renegade Freighter:77 +Fumigate:77 +Chromatic Lantern:77 +Champion's Helm:77 +Revoke Privileges:76 +Peema Outrider:76 +Arborback Stomper:76 +Architect of the Untamed:76 +Tidy Conclusion:75 +Servant of the Conduit:75 +Aetherborn Marauder:75 +Essence Extraction:75 +Saheeli Rai:74 +Chief of the Foundry:74 +Syndicate Trafficker:74 +Lathnu Hellion:74 +Bomat Bazaar Barge:73 +Visionary Augmenter:73 +Foundry Inspector:73 +Wispweaver Angel:73 +Gearshift Ace:73 +Mox Opal:72 +Key to the City:72 +Furious Reprisal:72 +Captured by the Consulate:72 +Scrapheap Scrounger:71 +Aethertorch Renegade:71 +Die Young:71 +Whirler Virtuoso:71 +Animation Module:71 +Æther Vial:70 +Marionette Master:70 +Nature's Way:70 +Chandra's Pyrohelix:70 +Long-Finned Skywhale:70 +Aether Meltdown:69 +Restoration Gearsmith:69 +Empyreal Voyager:69 +Ovalchase Daredevil:69 +Thriving Rhino:69 +Hunt the Weak:68 +Veteran Motorist:68 +Voltaic Brawler:68 +Lightning Greaves:68 +Dynavolt Tower:68 +Scroll Rack:67 +Padeem, Consul of Innovation:67 +Shrewd Negotiation:67 +Propeller Pioneer:67 +Kambal, Consul of Allocation:67 +Malfunction:66 +Brazen Scourge:66 +Chrome Mox:66 +Ballista Charger:66 +Sculpting Steel:66 +Glint-Sleeve Artisan:66 +Gearseeker Serpent:65 +Glint-Nest Crane:65 +Armorcraft Judge:65 +Thriving Grubs:65 +Sky Skiff:65 +Speedway Fanatic:64 +Riparian Tiger:64 +Underhanded Designs:64 +Kujar Seedsculptor:64 +Maulfist Doorbuster:64 +Subtle Strike:64 +Mind's Eye:63 +Impeccable Timing:63 +Spontaneous Artist:63 +Foundry Screecher:63 +Elegant Edgecrafters:63 +Weaponcraft Enthusiast:62 +Contraband Kingpin:62 +Consul's Shieldguard:62 +Glimmer of Genius:62 +Eliminate the Competition:62 +Metalwork Colossus:62 +Aetherworks Marvel:61 +Aviary Mechanic:61 +Aether Hub:61 +Fateful Showdown:61 +Prophetic Prism:61 +Experimental Aviator:60 +Metallurgic Summonings:60 +Aether Theorist:60 +Rings of Brighthearth:60 +Toolcraft Exemplar:60 +Attune with Aether:60 +Thriving Ibex:59 +Narnam Cobra:59 +Quicksmith Genius:59 +Fabrication Module:59 +Lotus Petal:59 +Thriving Rats:58 +Insidious Will:58 +Embraal Bruiser:58 +Maulfist Squad:58 +Dhund Operative:58 +Cloudstone Curio:58 +Salivating Gremlins:57 +Janjeet Sentry:57 +Static Orb:57 +Era of Innovation:57 +Fairgrounds Trumpeter:57 +Wind Drake:56 +Lawless Broker:56 +Ovalchase Dragster:56 +Fragmentize:56 +Blossoming Defense:56 +Built to Last:56 +Territorial Gorger:55 +Skyswirl Harrier:55 +Rush of Vitality:55 +Wild Wanderer:55 +Deadlock Trap:55 +Spireside Infiltrator:54 +Durable Handicraft:54 +Prakhata Pillar-Bug:54 +Dukhara Peafowl:54 +Sage of Shaila's Claim:54 +Incendiary Sabotage:54 +Weldfast Monitor:53 +Trusty Companion:53 +Iron League Steed:53 +Spark of Creativity:53 +Self-Assembler:53 +Make Obsolete:52 +Select for Inspection:52 +Live Fast:52 +Ambitious Aetherborn:52 +Thriving Turtle:52 +Nimble Innovator:51 +Eager Construct:51 +Servo Exhibition:51 +Appetite for the Unnatural:51 +Midnight Oil:51 +Eddytrail Hawk:50 +Æther Tradewinds:50 +Reckless Fireweaver:50 +Weldfast Wingsmith:50 +Ghirapur Guide:50 +Electrostatic Pummeler:49 +Painter's Servant:49 +Bastion Mastodon:49 +Highspire Artisan:49 +Cathartic Reunion:49 +Wayward Giant:48 +Acrobatic Maneuver:48 +Crucible of Worlds:48 +Built to Smash:48 +Prakhata Club Security:47 +Vedalken Blademaster:47 +Panharmonicon:47 +Decoction Module:47 +Inventor's Apprentice:47 +Fretwork Colony:46 +Hightide Hermit:46 +Spirebluff Canal:46 +Botanical Sanctum:46 +Blooming Marsh:45 +Whirlermaker:45 +Concealed Courtyard:45 +Wildest Dreams:45 +Tezzeret's Ambition:44 +Ninth Bridge Patrol:44 +Metalspinner's Puzzleknot:44 +Inspiring Vantage:44 +Ruinous Gremlin:43 +Inventors' Fair:43 +Herald of the Fair:43 +Hazardous Conditions:43 +Glassblower's Puzzleknot:42 +Hijack:42 +Engineered Might:42 +Bomat Courier:42 +Night Market Lookout:41 +Inventor's Goggles:41 +Cowl Prowler:41 +Dukhara Scavenger:41 +Ornamental Courage:40 +Fortuitous Find:40 +Demolition Stomper:40 +Cogworker's Puzzleknot:39 +Creeping Mold:39 +Aradara Express:39 +Minister of Inquiries:38 +Harsh Scrutiny:38 +Accomplished Automaton:38 +Woodweaver's Puzzleknot:37 +Failed Inspection:37 +Diabolic Tutor:37 +Consulate Skygate:36 +Refurbish:36 +Disappearing Act:36 +Pressure Point:35 +Authority of the Consuls:35 +Workshop Assistant:34 +Inspired Charge:34 +Take Down:34 +Renegade Tactics:33 +Larger Than Life:33 +Revolutionary Rebuff:32 +Ceremonious Rejection:32 +Torch Gauntlet:31 +Fireforger's Puzzleknot:31 +Morbid Curiosity:30 +Ghirapur Orrery:30 +Paradoxical Outcome:29 +Curio Vendor:28 +Aetherflux Reservoir:28 +Start Your Engines:27 +Terror of the Fairgrounds:26 +Demolish:26 +Wily Bandar:25 +Consulate Surveillance:24 +Giant Spectacle:23 +Mind Rot:22 +Lost Legacy:21 +Commencement of Festivities:20 +Sequestered Stash:18 +Madcap Experiment:16 +Tasseled Dromedary:14 +Dramatic Reversal:11 +Perpetual Timepiece:6 +Dubious Challenge:0 \ No newline at end of file diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/m13.csv b/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/m13.csv similarity index 100% rename from Mage.Server.Plugins/Mage.Player.AI/src/main/resources/m13.csv rename to Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/m13.csv diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/m19.csv b/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/m19.csv new file mode 100644 index 00000000000..82164b0866a --- /dev/null +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/m19.csv @@ -0,0 +1,260 @@ +Resplendent Angel:2323 +Tezzeret, Artifice Master:2297 +Ajani, Adversary of Tyrants:2268 +Vivien Reid:2257 +Nicol Bolas, the Ravager:2210 +Bone Dragon:2163 +Demanding Dragon:2122 +Murder:2118 +Banefire:2116 +Lathliss, Dragon Queen:2111 +Djinn of Wishes:2092 +Isareth the Awakener:2083 +Demon of Catastrophes:2078 +Leonin Warleader:2036 +Hieromancer's Cage:2031 +Lightning Strike:2030 +Goreclaw, Terror of Qal Sisma:1990 +Angel of the Dawn:1965 +Vine Mare:1962 +Cleansing Nova:1957 +Luminous Bonds:1957 +Hungering Hydra:1956 +Pelakka Wurm:1948 +Palladia-Mors, the Ruiner:1940 +Thorn Lieutenant:1931 +Rabid Bite:1929 +Dismissive Pyromancer:1919 +Lena, Selfless Champion:1914 +Herald of Faith:1911 +Sigiled Sword of Valeron:1906 +Vaevictis Asmadi, the Dire:1898 +Lich's Caress:1895 +Graveyard Marshal:1885 +Pegasus Courser:1878 +Chromium, the Mutable:1875 +Volcanic Dragon:1869 +Mentor of the Meek:1866 +Vampire Sovereign:1860 +Valiant Knight:1855 +Poison-Tip Archer:1851 +Spit Flame:1851 +Windreader Sphinx:1846 +Death Baron:1844 +Skyrider Patrol:1844 +Shock:1841 +Regal Bloodlord:1840 +Ajani's Pridemate:1836 +Psychic Symbiont:1833 +Liliana, Untouched by Death:1825 +Exclusion Mage:1824 +Star-Crowned Stag:1823 +Sleep:1817 +Heroic Reinforcements:1805 +Patient Rebuilding:1804 +Druid of the Cowl:1790 +Horizon Scholar:1784 +Skymarch Bloodletter:1777 +Sarkhan, Fireblood:1776 +Runic Armasaur:1774 +Prodigious Growth:1773 +Take Vengeance:1772 +Aven Wind Mage:1770 +Dryad Greenseeker:1761 +Electrify:1751 +Sarkhan's Unsealing:1743 +Plague Mare:1739 +Gallant Cavalry:1736 +Mystic Archaeologist:1724 +Draconic Disciple:1723 +Essence Scatter:1723 +Vigilant Baloth:1719 +Skeleton Archer:1717 +Arcades, the Strategist:1715 +Militia Bugler:1715 +Departed Deckhand:1713 +Fell Specter:1708 +Strangling Spores:1703 +Bristling Boar:1699 +Snapping Drake:1693 +Enigma Drake:1692 +Knightly Valor:1692 +Gravedigger:1690 +Sai, Master Thopterist:1688 +Aviation Pioneer:1685 +Skyscanner:1683 +Shield Mare:1680 +Meteor Golem:1674 +Sparktongue Dragon:1673 +Brawl-Bash Ogre:1667 +Remorseful Cleric:1666 +Sift:1663 +Fiery Finish:1654 +Transmogrifying Wand:1653 +Aerial Engineer:1649 +Cavalry Drillmaster:1648 +Ghastbark Twins:1645 +Reclamation Sage:1640 +Ajani's Last Stand:1637 +Metamorphic Alteration:1634 +Mirror Image:1633 +Omenspeaker:1633 +Vivien's Invocation:1633 +Dark-Dweller Oracle:1630 +Boggart Brute:1628 +Dwindle:1625 +Goblin Trashmaster:1625 +Make a Stand:1624 +Liliana's Contract:1623 +Giant Spider:1622 +Open the Graves:1621 +Colossal Dreadmaw:1616 +Divination:1615 +Goblin Instigator:1614 +Supreme Phantom:1613 +Chaos Wand:1605 +Rhox Oracle:1603 +Elvish Rejuvenator:1602 +Skilled Animator:1600 +Leonin Vanguard:1597 +Declare Dominance:1596 +Reassembling Skeleton:1595 +Daggerback Basilisk:1591 +Bone to Ash:1585 +Rise from the Grave:1585 +Gift of Paradise:1582 +Titanic Growth:1582 +Arcane Encyclopedia:1581 +Switcheroo:1581 +Doomed Dissenter:1579 +Gigantosaurus:1579 +Siegebreaker Giant:1577 +Child of Night:1575 +Surge Mare:1575 +Cancel:1561 +Volley Veteran:1560 +Epicure of Blood:1559 +Vampire Neonate:1555 +Guttersnipe:1554 +Aethershield Artificer:1553 +Rogue's Gloves:1553 +Macabre Waltz:1550 +Hired Blade:1548 +Salvager of Secrets:1545 +Diamond Mare:1543 +Blood Divination:1542 +Nightmare's Thirst:1542 +Gargoyle Sentinel:1539 +Act of Treason:1538 +Lightning Mare:1534 +Abnormal Endurance:1531 +Inspired Charge:1531 +Gearsmith Guardian:1527 +Dragon Egg:1521 +Anticipate:1519 +Viashino Pyromancer:1519 +Rustwing Falcon:1514 +Two-Headed Zombie:1513 +Blanchwood Armor:1511 +Hostile Minotaur:1510 +Druid of Horns:1508 +Marauder's Axe:1508 +Diregraf Ghoul:1507 +Havoc Devils:1506 +Satyr Enchanter:1505 +Centaur Courser:1502 +Plummet:1497 +Disperse:1494 +Sure Strike:1494 +Inferno Hellion:1491 +Novice Knight:1491 +Oakenform:1483 +Knight of the Tusk:1482 +Fountain of Renewal:1477 +Ravenous Harpy:1474 +Knight's Pledge:1469 +Thornhide Wolves:1463 +Dragon's Hoard:1461 +Daybreak Chaplain:1459 +Ghirapur Guide:1457 +Greenwood Sentinel:1456 +Recollect:1455 +Goblin Motivator:1452 +Talons of Wildwood:1449 +Colossal Majesty:1447 +Gearsmith Prodigy:1441 +Scholar of Stars:1439 +Ajani's Welcome:1433 +Mighty Leap:1432 +Naturalize:1431 +Trusty Packbeast:1431 +Dwarven Priest:1426 +Uncomfortable Chill:1423 +Oreskos Swiftclaw:1422 +Psychic Corrosion:1421 +Loxodon Line Breaker:1419 +Aether Tunnel:1404 +Frilled Sea Serpent:1403 +Infernal Scarring:1403 +Phylactery Lich:1398 +Mind Rot:1396 +Explosive Apparatus:1395 +Amulet of Safekeeping:1390 +Duress:1390 +Magistrate's Scepter:1388 +Suspicious Bookcase:1388 +Invoke the Divine:1385 +Manalith:1384 +Onakke Ogre:1384 +Tormenting Voice:1384 +One with the Machine:1378 +Meandering River:1374 +Lava Axe:1369 +Stone Quarry:1369 +Thud:1368 +Field Creeper:1367 +Rupture Spire:1366 +Elvish Clancaller:1365 +Wall of Mist:1363 +Suncleanser:1357 +Highland Game:1352 +Walking Corpse:1352 +Fire Elemental:1351 +Tectonic Rift:1348 +Totally Lost:1348 +Woodland Stream:1346 +Trumpet Blast:1339 +Millstone:1329 +Crash Through:1327 +Bogstomper:1326 +Aegis of the Heavens:1323 +Forsaken Sanctuary:1323 +Apex of Power:1307 +Tranquil Expanse:1304 +Cinder Barrens:1296 +Infernal Reckoning:1294 +Revitalize:1293 +Wall of Vines:1292 +Detection Tower:1283 +Timber Gorge:1282 +Submerged Boneyard:1277 +Mistcaller:1273 +Ghostform:1272 +Catalyst Elemental:1268 +Omniscience:1267 +Tolarian Scholar:1267 +Stitcher's Supplier:1263 +Desecrated Tomb:1258 +Scapeshift:1251 +Sovereign's Bite:1250 +Highland Lake:1245 +Infectious Horror:1241 +Doublecast:1240 +Fraying Omnipotence:1220 +Crucible of Worlds:1209 +Root Snare:1201 +Smelt:1199 +Reliquary Tower:1197 +Foul Orchard:1190 +Isolate:1139 +Alpine Moon:1068 \ No newline at end of file diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/mm3.csv b/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/mm3.csv new file mode 100644 index 00000000000..3d175cd059c --- /dev/null +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/mm3.csv @@ -0,0 +1,249 @@ +Jace, the Mind Sculptor:2196 +Master of the Wild Hunt:2148 +Lightning Bolt:2107 +Swords to Plowshares:2060 +Vendilion Clique:2058 +Ravenous Chupacabra:2057 +Courser of Kruphix:1981 +Reef Worm:1962 +Vindicate:1961 +Pillory of the Sleepless:1926 +Akroma, Angel of Fury:1923 +Gisela, Blade of Goldnight:1918 +Akroma, Angel of Wrath:1913 +Animar, Soul of Elements:1902 +Murder:1900 +Ruric Thar, the Unbowed:1896 +Protean Hulk:1894 +Pacifism:1888 +Akroma’s Vengeance:1885 +Murder of Crows:1885 +Phyrexian Obliterator:1882 +Rancor:1864 +Vesuvan Shapeshifter:1858 +Niv-Mizzet, the Firemind:1854 +Shadowmage Infiltrator:1854 +Fiend Hunter:1844 +Pernicious Deed:1841 +Thalia, Guardian of Thraben:1829 +Living Death:1827 +Man-o’-War:1827 +Elvish Piper:1825 +Imperial Recruiter:1810 +Sundering Titan:1806 +Decree of Justice:1803 +Prossh, Skyraider of Kher:1803 +Cloudblazer:1798 +Laquatus’s Champion:1795 +Darien, King of Kjeldor:1787 +Grenzo, Dungeon Warden:1787 +Pyroclasm:1787 +Brion Stoutarm:1786 +Utopia Sprawl:1785 +Counterspell:1772 +Coalition Relic:1765 +Disfigure:1755 +Kongming, “Sleeping Dragon”:1752 +Spikeshot Goblin:1752 +Blightning:1750 +Arbor Elf:1748 +Bident of Thassa:1743 +Hell’s Caretaker:1739 +Cultivate:1728 +Kindle:1726 +Luminarch Ascension:1719 +Fallen Angel:1718 +Krosan Tusker:1718 +Promise of Bunrei:1713 +Squadron Hawk:1712 +Mystic Snake:1711 +Horseshoe Crab:1707 +Ensnaring Bridge:1706 +Lorescale Coatl:1702 +Nicol Bolas:1702 +Boros Charm:1701 +Treasure Keeper:1701 +Undead Gladiator:1699 +Baloth Null:1698 +Chandra’s Outrage:1691 +Notion Thief:1691 +Merfolk Looter:1689 +Willbender:1689 +Azusa, Lost but Seeking:1686 +Quicksilver Dagger:1686 +Armageddon:1683 +Dusk Legion Zealot:1678 +Zombify:1678 +Urbis Protector:1676 +Rishadan Port:1673 +Blue Sun’s Zenith:1672 +Mesmeric Fiend:1669 +Chalice of the Void:1668 +Zulaport Cutthroat:1662 +Epic Confrontation:1658 +Exclude:1658 +Eidolon of the Great Revel:1655 +Nyx-Fleece Ram:1653 +Diabolic Edict:1651 +Brainstorm:1648 +Magus of the Wheel:1648 +Zada, Hedron Grinder:1645 +Court Hussar:1638 +Sift:1638 +Iwamori of the Open Fist:1637 +Twisted Abomination:1633 +Izzet Chemister:1632 +Ire Shaman:1629 +Kavu Predator:1628 +Street Wraith:1628 +Dauntless Cathar:1625 +Cloudshift:1622 +Mystic of the Hidden Way:1622 +Summoner’s Pact:1622 +Ball Lightning:1621 +Skeletonize:1620 +Ruthless Ripper:1614 +Hordeling Outburst:1609 +Path of Peace:1609 +Loyal Sentry:1607 +Eladamri’s Call:1606 +Mishra’s Factory:1604 +Ash Barrens:1602 +Griffin Protector:1591 +Myriad Landscape:1588 +Hanna, Ship’s Navigator:1586 +Flash:1585 +Prophetic Prism:1585 +Unearth:1584 +Enthralling Victor:1583 +Freed from the Real:1581 +Fathom Seer:1578 +Sai of the Shinobi:1578 +Ancient Craving:1577 +Bloodhunter Bat:1577 +Invigorate:1576 +Watchwolf:1575 +Mogg Flunkies:1571 +Vessel of Nascency:1571 +Whitemane Lion:1571 +Swiftfoot Boots:1570 +Plague Wind:1569 +Perilous Myr:1568 +Karona’s Zealot:1567 +Geist of the Moors:1563 +Jalira, Master Polymorphist:1563 +Cascade Bluffs:1560 +Elvish Aberration:1560 +Kavu Climber:1555 +Thresher Lizard:1555 +Horror of the Broken Lands:1551 +Ainok Survivalist:1549 +Genju of the Falls:1549 +Frenzied Goblin:1547 +Pyre Hound:1545 +Stangg:1544 +Twilight Mire:1544 +Broodhatch Nantuko:1542 +Kor Firewalker:1542 +Ratcatcher:1542 +Presence of Gond:1541 +Noble Templar:1539 +Brine Elemental:1537 +Death’s-Head Buzzard:1537 +Fierce Empath:1537 +Timberpack Wolf:1537 +Skirk Commando:1536 +Ghost Ship:1535 +Ember Weaver:1533 +Pact of Negation:1531 +Shoreline Ranger:1531 +Woolly Loxodon:1526 +Curiosity:1525 +Gods Willing:1523 +Deadly Designs:1521 +Phyrexian Ghoul:1519 +Giant Growth:1518 +Fortune Thief:1517 +Genju of the Spires:1517 +Angelic Page:1516 +Nettle Sentinel:1516 +Wildheart Invoker:1514 +Ambassador Oak:1513 +Nezumi Cutthroat:1511 +Knight of the Skyward Eye:1510 +Dark Ritual:1509 +Supernatural Stamina:1509 +Flooded Grove:1503 +Ordeal of Heliod:1503 +Fetid Heath:1500 +Accumulated Knowledge:1498 +Balduvian Horde:1497 +Vampire Lacerator:1491 +Chartooth Cougar:1487 +Lunarch Mantle:1487 +Pendelhaven:1487 +Doomsday:1486 +Colossal Dreadmaw:1485 +Krosan Colossus:1483 +Retraction Helix:1473 +Arcane Denial:1472 +Quicksand:1472 +Fencing Ace:1470 +Goblin War Drums:1467 +Self-Assembler:1463 +Rugged Prairie:1461 +Caustic Tar:1459 +Erg Raiders:1458 +Simian Spirit Guide:1458 +Regrowth:1454 +Mikokoro, Center of the Sea:1450 +Returned Phalanx:1449 +Cursecatcher:1445 +Tree of Redemption:1445 +Soulbright Flamekin:1444 +Primal Clay:1443 +Uncaged Fury:1443 +Will-o’-the-Wisp:1443 +Browbeat:1434 +Heavy Arbalest:1430 +Echoing Courage:1429 +Blood Moon:1425 +Choking Tethers:1424 +Stampede Driver:1422 +Crimson Mage:1421 +Relentless Rats:1421 +Living Wish:1420 +Totally Lost:1418 +Humble Defector:1417 +Ihsan’s Shade:1417 +Zoetic Cavern:1412 +Act of Treason:1405 +Savannah Lions:1404 +Coralhelm Guide:1398 +Trumpet Blast:1397 +Twisted Image:1397 +Dragon’s Eye Savants:1392 +Blue Elemental Blast:1385 +Ancient Stirrings:1377 +Phantasmal Bear:1374 +Rest in Peace:1373 +Dirge of Dread:1372 +Red Elemental Blast:1361 +Triskaidekaphobia:1361 +Cinder Storm:1352 +Auramancer:1346 +Haunted Fengraf:1343 +Strionic Resonator:1342 +Act of Heroism:1341 +Borrowing 100,000 Arrows:1338 +Jackal Pup:1337 +Valor in Akros:1337 +Nihil Spellbomb:1316 +Assembly-Worker:1301 +Pillage:1300 +Disenchant:1271 +Renewed Faith:1250 +Plummet:1238 +Congregate:1218 +Lull:1212 +Conflux:1208 \ No newline at end of file diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/rix.csv b/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/rix.csv new file mode 100644 index 00000000000..4d561540870 --- /dev/null +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/rix.csv @@ -0,0 +1,191 @@ +Rekindling Phoenix:2418 +Tetzimoc, Primal Death:2401 +Ravenous Chupacabra:2290 +Twilight Prophet:2282 +Etali, Primal Storm:2192 +Angrath, the Flame-Chained:2180 +The Immortal Sun:2168 +Profane Procession:2155 +Jadelight Ranger:2143 +Ghalta, Primal Hunger:2131 +Tendershoot Dryad:2121 +Bishop of Binding:2103 +Kumena, Tyrant of Orazca:2098 +Dire Fleet Poisoner:2094 +Trapjaw Tyrant:2087 +Bombard:2052 +Moment of Craving:2039 +Huatli, Radiant Champion:2029 +Hadana’s Climb:2019 +Reaver Ambush:2001 +Warkite Marauder:2001 +Champion of Dusk:2000 +Baffling End:1990 +Luminous Bonds:1970 +Impale:1966 +Golden Demise:1946 +Journey to Eternity:1941 +Crested Herdcaller:1936 +Azor, the Lawbringer:1914 +Thrashing Brontodon:1908 +Raging Regisaur:1902 +Zacama, Primal Calamity:1901 +Legion Lieutenant:1898 +Deeproot Elite:1893 +Sadistic Skymarcher:1893 +Needletooth Raptor:1889 +Elenda, the Dusk Rose:1888 +Dire Fleet Daredevil:1883 +Merfolk Mistbinder:1881 +Hunt the Weak:1839 +Forerunner of the Legion:1828 +Zetalpa, Primal Dawn:1820 +Golden Guardian:1819 +Radiant Destiny:1816 +Vona’s Hunger:1798 +Polyraptor:1793 +Tilonalli’s Summoner:1792 +Swift Warden:1774 +Slaughter the Strong:1767 +Protean Raider:1764 +Waterknot:1762 +Seafloor Oracle:1761 +Forerunner of the Empire:1760 +Divine Verdict:1759 +Reckless Rage:1758 +Dusk Legion Zealot:1755 +Squire’s Devotion:1754 +Temple Altisaur:1753 +Forerunner of the Heralds:1749 +Deadeye Brawler:1748 +Nezahal, Primal Tide:1742 +Captain’s Hook:1722 +Curious Obsession:1720 +Charging Tuskodon:1717 +Azor’s Gateway:1706 +Dire Fleet Neckbreaker:1703 +Wayward Swordtooth:1699 +Resplendent Griffin:1698 +Jungle Creeper:1693 +Siegehorn Ceratops:1690 +Kitesail Corsair:1689 +Martyr of Dusk:1689 +Exultant Skymarcher:1686 +Sailor of Means:1683 +Silvergill Adept:1680 +Atzocan Seer:1675 +Jungleborn Pioneer:1674 +Path of Discovery:1669 +Skymarcher Aspirant:1667 +Siren Reaver:1661 +Paladin of Atonement:1655 +Forerunner of the Coalition:1652 +Mutiny:1648 +Storm Fleet Sprinter:1638 +Relentless Raptor:1634 +Everdawn Champion:1625 +Goblin Trailblazer:1622 +Storm Fleet Swashbuckler:1606 +Spire Winder:1600 +Strength of the Pack:1594 +Secrets of the Golden City:1593 +Mausoleum Harpy:1586 +Slippery Scoundrel:1585 +Colossal Dreadmaw:1584 +Knight of the Stampede:1584 +Dusk Charger:1579 +Expel from Orazca:1578 +Oathsworn Vampire:1578 +Overgrown Armasaur:1576 +Daring Buccaneer:1562 +Deadeye Rig-Hauler:1557 +Sun-Crested Pterodon:1557 +Soul of the Rapids:1549 +Cherished Hatchling:1547 +Crashing Tide:1538 +Recover:1538 +Arch of Orazca:1537 +Majestic Heliopterus:1531 +Sanguine Glorifier:1525 +Form of the Dinosaur:1523 +Pride of Conquerors:1523 +Famished Paladin:1516 +Moment of Triumph:1515 +Silverclad Ferocidons:1511 +Frilled Deathspitter:1509 +Kumena’s Awakening:1505 +Snubhorn Sentry:1504 +Voracious Vampire:1504 +Fathom Fleet Boarder:1501 +Buccaneer’s Bravado:1492 +Thunderherd Migration:1487 +Legion Conquistador:1483 +See Red:1481 +Riverwise Augur:1478 +Cacophodon:1477 +Tomb Robber:1475 +Giltgrove Stalker:1472 +Swaggering Corsair:1472 +Evolving Wilds:1463 +Dinosaur Hunter:1461 +World Shaper:1452 +Path of Mettle:1447 +Hardy Veteran:1446 +Mist-Cloaked Herald:1443 +Fanatical Firebrand:1442 +Jadecraft Artisan:1440 +Stampeding Horncrest:1439 +Admiral’s Order:1436 +Timestream Navigator:1433 +Brazen Freebooter:1427 +Imperial Ceratops:1415 +Aggressive Urge:1413 +Traveler’s Amulet:1412 +Grasping Scoundrel:1403 +Jade Bearer:1384 +Aquatic Incursion:1375 +Shake the Foundations:1374 +Vampire Revenant:1368 +Orazca Raptor:1363 +Sun Sentinel:1362 +Hornswoggle:1350 +Mastermind’s Acquisition:1344 +Raptor Companion:1340 +Sea Legs:1332 +Sun-Collared Raptor:1322 +Tilonalli’s Crown:1318 +Gleaming Barrier:1307 +Enter the Unknown:1301 +Storm the Vault:1297 +Crafty Cutpurse:1291 +Pitiless Plunderer:1288 +Forsaken Sanctuary:1281 +Pirate’s Pillage:1274 +Arterial Flow:1255 +Woodland Stream:1246 +Orazca Frillback:1244 +Dead Man’s Chest:1233 +River Darter:1233 +Naturalize:1224 +Cleansing Ray:1203 +Highland Lake:1199 +Strider Harness:1198 +Negate:1195 +Stone Quarry:1192 +Dark Inquiry:1187 +Release to the Wind:1165 +Plummet:1160 +Foul Orchard:1146 +Orazca Relic:1123 +Flood of Recollection:1121 +Canal Monitor:1094 +Blazing Hope:1069 +Brass’s Bounty:1064 +Sworn Guardian:1060 +Blood Sun:1059 +Gruesome Fate:1036 +Awakened Amalgam:1017 +Induced Amnesia:1003 +Silent Gravestone:968 +Sphinx’s Decree:961 +Shatter:907 \ No newline at end of file diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/setsWithRatings.csv b/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/setsWithRatings.csv new file mode 100644 index 00000000000..172ed6537e2 --- /dev/null +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/setsWithRatings.csv @@ -0,0 +1,19 @@ +# this file specifies which sets have set files. +# each line must be exactly the 3 letter expansion code. this corresponds to a csv resource file in the same directory +# The .csv files have a strict format: +# each line must be: +# cardname : integer rating +# each set's ratings are post-processed to have a normalized score [1..100], so the files don't need to have the same rating system. +# I created the first few files with draftaholicsanonymous but you can use any integer rating system you want +grn +m19 +dom +rix +xln +hou +akh +aer +kld +mm3 +ima +m13 \ No newline at end of file diff --git a/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/xln.csv b/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/xln.csv new file mode 100644 index 00000000000..3e92060d88e --- /dev/null +++ b/Mage.Server.Plugins/Mage.Player.AI/src/main/resources/ratings/xln.csv @@ -0,0 +1,259 @@ +Vraska, Relic Seeker:2381 +Hostage Taker:2336 +Carnage Tyrant:2332 +Regisaur Alpha:2276 +Ripjaw Raptor:2228 +Captivating Crew:2225 +Vraska’s Contempt:2214 +Vona, Butcher of Magan:2192 +Huatli, Warrior Poet:2173 +Repeating Barrage:2144 +Charging Monstrosaur:2133 +Lightning Strike:2122 +Walk the Plank:2096 +Ixalan’s Binding:2083 +Burning Sun’s Avatar:2068 +Mavren Fein, Dusk Apostle:2061 +Settle the Wreckage:2057 +Waker of the Wilds:2033 +Kinjalli’s Sunwing:2032 +Sanctum Seeker:2003 +Rampaging Ferocidon:2000 +Legion’s Landing:1999 +Territorial Hammerskull:1990 +Dreamcaller Siren:1983 +Bishop of Rebirth:1975 +Vanquish the Weak:1969 +River’s Rebuke:1967 +Fathom Fleet Captain:1950 +Imperial Aerosaur:1939 +Drover of the Mighty:1932 +Deathgorge Scavenger:1917 +Snapping Sailback:1916 +Shapers of Nature:1913 +Entrancing Melody:1911 +Contract Killing:1910 +Adanto Vanguard:1901 +Air Elemental:1901 +Dire Fleet Ravager:1889 +Merfolk Branchwalker:1889 +Jace, Cunning Castaway:1881 +Savage Stomp:1878 +Kitesail Freebooter:1877 +Raging Swordtooth:1858 +Ruin Raider:1856 +Vance’s Blasting Cannons:1854 +Unfriendly Fire:1844 +Captain Lannery Storm:1843 +Pious Interdiction:1842 +Firecannon Blast:1837 +Ranging Raptors:1835 +Treasure Map:1832 +Sky Terror:1824 +Vanquisher’s Banner:1823 +Watertrap Weaver:1811 +Pirate’s Cutlass:1806 +Emperor’s Vanguard:1805 +Storm Fleet Aerialist:1805 +Tempest Caller:1798 +Daring Saboteur:1795 +Search for Azcanta:1794 +Rowdy Crew:1793 +Seekers’ Squire:1777 +Skulduggery:1773 +Glorifier of Dusk:1757 +Siren Lookout:1757 +One With the Wind:1754 +Admiral Beckett Brass:1752 +Bishop of the Bloodstained:1752 +Wanted Scoundrels:1750 +Pounce:1748 +Jade Guardian:1740 +Vineshaper Mystic:1740 +Skymarch Bloodletter:1739 +Gishath, Sun’s Avatar:1733 +Call to the Feast:1730 +Paladin of the Bloodstained:1729 +Emissary of Sunrise:1725 +Otepec Huntmaster:1719 +Thundering Spineback:1710 +Tishana’s Wayfinder:1707 +Fiery Cannonade:1697 +Verdant Sun’s Avatar:1692 +Dark Nourishment:1682 +Deadeye Tracker:1679 +Siren Stormtamer:1679 +Chart a Course:1674 +Dire Fleet Captain:1673 +Inspiring Cleric:1671 +Bishop’s Soldier:1669 +Deathless Ancient:1669 +Deeproot Warrior:1669 +Tilonalli’s Knight:1669 +Deadeye Plunderers:1664 +Conqueror’s Galleon:1657 +Bright Reprisal:1654 +Shining Aerosaur:1654 +Raptor Hatchling:1653 +Wakening Sun’s Avatar:1651 +Fell Flagship:1649 +Herald of Secret Streams:1645 +Headstrong Brute:1643 +Fathom Fleet Firebrand:1641 +Colossal Dreadmaw:1637 +Vicious Conquistador:1636 +Bloodcrazed Paladin:1635 +Bellowing Aegisaur:1629 +Tishana, Voice of Thunder:1628 +Kopala, Warden of Waves:1626 +New Horizons:1624 +Deadeye Tormentor:1621 +Marauding Looter:1621 +Kumena’s Speaker:1619 +Vampire’s Zeal:1618 +Duskborne Skymarcher:1616 +Ixalli’s Diviner:1616 +Ravenous Daggertooth:1615 +Angrath’s Marauders:1613 +Perilous Voyage:1613 +Slash of Talons:1613 +Shaper Apprentice:1612 +Wildgrowth Walker:1609 +Storm Fleet Spy:1607 +Sailor of Means:1605 +Bonded Horncrest:1600 +Grazing Whiptail:1597 +Thaumatic Compass:1596 +Thrash of Raptors:1594 +Legion’s Judgment:1591 +Queen’s Commission:1590 +Deeproot Champion:1587 +Steadfast Armasaur:1581 +River Heralds’ Boon:1579 +Rigging Runner:1575 +Goring Ceratops:1572 +Skittering Heartstopper:1572 +Storm Fleet Arsonist:1571 +Dire Fleet Hoarder:1569 +Commune with Dinosaurs:1566 +Atzocan Archer:1562 +River Sneak:1562 +Skyblade of the Legion:1560 +Run Aground:1558 +Anointed Deacon:1557 +Pterodon Knight:1557 +Mark of the Vampire:1555 +Fathom Fleet Cutthroat:1552 +Prosperous Pirates:1549 +Shipwreck Looter:1546 +Arguel’s Blood Fast:1536 +Wind Strider:1535 +Legion Conquistador:1533 +Depths of Desire:1531 +Ruthless Knave:1531 +Sunbird’s Invocation:1531 +Growing Rites of Itlimoc:1525 +Lookout’s Dispersal:1525 +Lightning-Rig Crew:1517 +Sure Strike:1517 +Boneyard Parley:1515 +Dusk Legion Dreadnought:1515 +Priest of the Wakening Sun:1514 +Brazen Buccaneers:1513 +Star of Extinction:1513 +Raptor Companion:1511 +Rallying Roar:1505 +Heartless Pillage:1501 +Sleek Schooner:1500 +Fleet Swallower:1498 +Ixalli’s Keeper:1497 +Dive Down:1496 +Sheltering Light:1492 +Sun-Crowned Hunters:1483 +Cobbled Wings:1474 +Dire Fleet Interloper:1473 +Lurking Chupacabra:1465 +Storm Fleet Pyromancer:1463 +Dowsing Dagger:1456 +Shadowed Caravel:1455 +Spike-Tailed Ceratops:1455 +Kinjalli’s Caller:1454 +Deeproot Waters:1452 +Rootbound Crag:1451 +Verdant Rebirth:1451 +Storm Sculptor:1448 +Frenzied Raptor:1446 +Opt:1440 +Jungle Delver:1438 +Sword-Point Diplomacy:1438 +Nest Robber:1436 +Tilonalli’s Skinshifter:1434 +Siren’s Ruse:1433 +Crushing Canopy:1431 +Dinosaur Stampede:1429 +Overflowing Insight:1425 +Swashbuckling:1418 +Crash the Ramparts:1413 +Sunpetal Grove:1412 +Favorable Winds:1406 +Shapers’ Sanctuary:1406 +Queen’s Bay Soldier:1405 +Deadeye Quartermaster:1401 +Queen’s Agent:1397 +Dual Shot:1396 +Pirate’s Prize:1394 +March of the Drowned:1387 +Blossom Dryad:1385 +Drowned Catacomb:1383 +Tocatli Honor Guard:1373 +Dragonskull Summit:1372 +Raiders’ Wake:1371 +Spell Swindle:1368 +Sunrise Seeker:1361 +Desperate Castaways:1342 +Prying Blade:1338 +Sorcerous Spyglass:1334 +Blight Keeper:1330 +Costly Plunder:1310 +Primal Amulet:1306 +Unclaimed Territory:1306 +Fire Shrine Keeper:1301 +Imperial Lancer:1297 +Belligerent Brontodon:1296 +Emergent Growth:1293 +Wily Goblin:1293 +Cancel:1287 +Duress:1286 +Old-Growth Dryads:1282 +Navigator’s Ruin:1273 +Glacial Fortress:1262 +Trove of Temptation:1259 +Pillar of Origins:1252 +Hijack:1236 +Rile:1234 +Revel in Riches:1232 +Headwater Sentries:1225 +Grim Captain’s Call:1214 +Elaborate Firecannon:1209 +Looming Altisaur:1206 +Encampment Keeper:1199 +Slice in Twain:1198 +Spell Pierce:1186 +Makeshift Munitions:1183 +Rummaging Goblin:1182 +Axis of Mortality:1179 +Unknown Shores:1173 +Shore Keeper:1172 +Ancient Brontodon:1165 +Sanguine Sacrament:1162 +Arcane Adaptation:1151 +Ashes of the Abhorrent:1135 +Ritual of Rejuvenation:1102 +Field of Ruin:1097 +Hierophant’s Chalice:1077 +Gilded Sentinel:1035 +Blinding Fog:1033 +Demystify:1023 +Sentinel Totem:998 +Demolish:994 +Spreading Rot:935 \ No newline at end of file diff --git a/Mage.Server/pom.xml b/Mage.Server/pom.xml index ef2b5d1b81a..91d840c5a8c 100644 --- a/Mage.Server/pom.xml +++ b/Mage.Server/pom.xml @@ -22,8 +22,8 @@ org.apache.commons commons-lang3 - 3.3.2 - + 3.8.1 + ${project.groupId} mage-common @@ -76,16 +76,16 @@ ${project.version} runtime - + ${project.groupId} mage-game-brawlduel ${project.version} runtime - + org.apache.commons commons-compress - 1.16.1 + 1.18 @@ -194,58 +194,58 @@ org.apache.shiro shiro-core - 1.2.4 + 1.4.0 jar com.google.api-client google-api-client - 1.21.0 + 1.25.0 jar com.google.apis google-api-services-gmail - v1-rev35-1.21.0 + v1-rev82-1.23.0 jar com.google.oauth-client google-oauth-client-java6 - 1.19.0 + 1.25.0 jar com.google.oauth-client google-oauth-client-jetty - 1.19.0 + 1.25.0 jar javax.mail mail - 1.4.2 + 1.4.7 jar com.sun.jersey jersey-core - 1.19 + 1.19.4 com.sun.jersey jersey-client - 1.19 + 1.19.4 com.sun.jersey.contribs jersey-multipart - 1.19 + 1.19.4 org.xerial sqlite-jdbc - 3.7.2 + 3.25.2 @@ -254,7 +254,7 @@ org.jvnet.jaxb2.maven2 maven-jaxb2-plugin - 0.12.3 + 0.14.0 mage.server.util.config ./src/main/xml-resources/jaxb/Config/ @@ -320,7 +320,7 @@ - + mage-server diff --git a/Mage.Server/src/main/java/mage/server/ChatManager.java b/Mage.Server/src/main/java/mage/server/ChatManager.java index 4841a766437..7ef083002ae 100644 --- a/Mage.Server/src/main/java/mage/server/ChatManager.java +++ b/Mage.Server/src/main/java/mage/server/ChatManager.java @@ -172,8 +172,8 @@ public enum ChatManager { + "
\\whisper or \\w [player name] [text] - whisper to the player with the given name" + "
\\card Card Name - Print oracle text for card" + "
[Card Name] - Show a highlighted card name" - + "
\\ignore - shows current ignore list on this server." - + "
\\ignore [username] - add a username to your ignore list on this server." + + "
\\ignore - shows your ignore list on this server." + + "
\\ignore [username] - add username to ignore list (they won't be able to chat or join to your game)." + "
\\unignore [username] - remove a username from your ignore list on this server."; final Pattern getCardTextPattern = Pattern.compile("^.card *(.*)"); diff --git a/Mage.Server/src/main/java/mage/server/MageServerImpl.java b/Mage.Server/src/main/java/mage/server/MageServerImpl.java index 899f113519b..97d84c1a28b 100644 --- a/Mage.Server/src/main/java/mage/server/MageServerImpl.java +++ b/Mage.Server/src/main/java/mage/server/MageServerImpl.java @@ -227,6 +227,20 @@ public class MageServerImpl implements MageServer { user.showUserMessage("Create tournament", message); throw new MageException("No message"); } + // check if the user satisfies the minimumRating requirement. + int minimumRating = options.getMinimumRating(); + int userRating; + if (options.getMatchOptions().isLimited()) { + userRating = user.getUserData().getLimitedRating(); + } else { + userRating = user.getUserData().getConstructedRating(); + } + if (userRating < minimumRating) { + String message = new StringBuilder("Your rating ").append(userRating) + .append(" is lower than the table requirement ").append(minimumRating).toString(); + user.showUserMessage("Create tournament", message); + throw new MageException("No message"); + } Optional room = GamesRoomManager.instance.getRoom(roomId); if (!room.isPresent()) { @@ -1386,7 +1400,19 @@ public class MageServerImpl implements MageServer { user.showUserMessage("Create table", "Your quit ratio " + user.getMatchQuitRatio() + "% is higher than the table requirement " + quitRatio + '%'); throw new MageException("No message"); } - + // check if the user satisfies the minimumRating requirement. + int minimumRating = options.getMinimumRating(); + int userRating; + if (options.isLimited()) { + userRating = user.getUserData().getLimitedRating(); + } else { + userRating = user.getUserData().getConstructedRating(); + } + if (userRating < minimumRating) { + String message = new StringBuilder("Your rating ").append(userRating).append(" is lower than the table requirement ").append(minimumRating).toString(); + user.showUserMessage("Create table", message); + throw new MageException("No message"); + } Optional room = GamesRoomManager.instance.getRoom(roomId); if (room.isPresent()) { TableView table = room.get().createTable(userId, options); diff --git a/Mage.Server/src/main/java/mage/server/TableController.java b/Mage.Server/src/main/java/mage/server/TableController.java index 1f4d9808cd3..a3f993cf415 100644 --- a/Mage.Server/src/main/java/mage/server/TableController.java +++ b/Mage.Server/src/main/java/mage/server/TableController.java @@ -172,6 +172,21 @@ public class TableController { return false; } + // Check minimum rating. + int minimumRating = table.getTournament().getOptions().getMinimumRating(); + int userRating; + if (table.getTournament().getOptions().getMatchOptions().isLimited()) { + userRating = user.getUserData().getLimitedRating(); + } else { + userRating = user.getUserData().getConstructedRating(); + } + if (userRating < minimumRating) { + String message = new StringBuilder("Your rating ").append(userRating) + .append(" is lower than the table requirement ").append(minimumRating).toString(); + user.showUserMessage("Join Table", message); + return false; + } + Optional playerOptional = createPlayer(name, seat.getPlayerType(), skill); if (playerOptional.isPresent()) { Player player = playerOptional.get(); @@ -272,6 +287,21 @@ public class TableController { return false; } + // Check minimum rating. + int minimumRating = table.getMatch().getOptions().getMinimumRating(); + int userRating; + if (table.getMatch().getOptions().isLimited()) { + userRating = user.getUserData().getLimitedRating(); + } else { + userRating = user.getUserData().getConstructedRating(); + } + if (userRating < minimumRating) { + String message = new StringBuilder("Your rating ").append(userRating) + .append(" is lower than the table requirement ").append(minimumRating).toString(); + user.showUserMessage("Join Table", message); + return false; + } + // Check power level for table (currently only used for EDH/Commander table) int edhPowerLevel = table.getMatch().getOptions().getEdhPowerLevel(); if (edhPowerLevel > 0 && table.getValidator().getName().toLowerCase(Locale.ENGLISH).equals("commander")) { diff --git a/Mage.Sets/src/mage/cards/a/AdroitHateflayer.java b/Mage.Sets/src/mage/cards/a/AdroitHateflayer.java index e51f259f632..dcf0a7f023a 100644 --- a/Mage.Sets/src/mage/cards/a/AdroitHateflayer.java +++ b/Mage.Sets/src/mage/cards/a/AdroitHateflayer.java @@ -1,10 +1,9 @@ - package mage.cards.a; import java.util.UUID; import mage.MageInt; import mage.abilities.common.AttacksTriggeredAbility; -import mage.abilities.effects.common.LoseLifeOpponentsEffect; +import mage.abilities.effects.common.LoseLifeAllPlayersEffect; import mage.abilities.keyword.MenaceAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -18,7 +17,7 @@ import mage.constants.SubType; public final class AdroitHateflayer extends CardImpl { public AdroitHateflayer(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{U}{B}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{U}{B}{R}"); this.subtype.add(SubType.NAUTOLAN); this.subtype.add(SubType.SITH); this.power = new MageInt(3); @@ -26,9 +25,9 @@ public final class AdroitHateflayer extends CardImpl { // Menace this.addAbility(new MenaceAbility()); - - // Whenever Adroit Hateflayer attacks, each opponent loses 2 life. - this.addAbility(new AttacksTriggeredAbility(new LoseLifeOpponentsEffect(2), false)); + + // Whenever Adroit Hateflayer attacks, each player loses 2 life. + this.addAbility(new AttacksTriggeredAbility(new LoseLifeAllPlayersEffect(2), false)); } public AdroitHateflayer(final AdroitHateflayer card) { diff --git a/Mage.Sets/src/mage/cards/a/AdventurersGuildhouse.java b/Mage.Sets/src/mage/cards/a/AdventurersGuildhouse.java new file mode 100644 index 00000000000..f52a02aa307 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AdventurersGuildhouse.java @@ -0,0 +1,47 @@ + +package mage.cards.a; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.keyword.BandsWithOtherAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SuperType; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.filter.predicate.mageobject.SupertypePredicate; + +/** + * + * @author L_J + */ +public final class AdventurersGuildhouse extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Green legendary creatures"); + + static { + filter.add(new ColorPredicate(ObjectColor.GREEN)); + filter.add(new SupertypePredicate(SuperType.LEGENDARY)); + } + + public AdventurersGuildhouse(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + // Green legendary creatures you control have "bands with other legendary creatures." + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledEffect(new BandsWithOtherAbility(SuperType.LEGENDARY), Duration.WhileOnBattlefield, filter))); + } + + public AdventurersGuildhouse(final AdventurersGuildhouse card) { + super(card); + } + + @Override + public AdventurersGuildhouse copy() { + return new AdventurersGuildhouse(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/AminatouTheFateShifter.java b/Mage.Sets/src/mage/cards/a/AminatouTheFateShifter.java index 8067fc0183c..23a6897b4b9 100644 --- a/Mage.Sets/src/mage/cards/a/AminatouTheFateShifter.java +++ b/Mage.Sets/src/mage/cards/a/AminatouTheFateShifter.java @@ -44,7 +44,7 @@ public class AminatouTheFateShifter extends CardImpl { } public AminatouTheFateShifter(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.PLANESWALKER},"{W}{U}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{W}{U}{B}"); this.addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.AMINATOU); @@ -56,7 +56,7 @@ public class AminatouTheFateShifter extends CardImpl { // -1: Exile another target permanent you own, then return it to the battlefield under your control. ability = new LoyaltyAbility(new ExileTargetForSourceEffect(), -1); - ability.addEffect(new ReturnToBattlefieldUnderYourControlTargetEffect()); + ability.addEffect(new ReturnToBattlefieldUnderYourControlTargetEffect(true)); ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); @@ -68,6 +68,7 @@ public class AminatouTheFateShifter extends CardImpl { // Aminatou, the Fateshifter can be your commander. this.addAbility(CanBeYourCommanderAbility.getInstance()); } + public AminatouTheFateShifter(final AminatouTheFateShifter card) { super(card); } @@ -79,6 +80,7 @@ public class AminatouTheFateShifter extends CardImpl { } class AminatouPlusEffect extends OneShotEffect { + public AminatouPlusEffect() { super(Outcome.DrawCard); staticText = "draw a card, then put a card from your hand on top of your library"; @@ -118,10 +120,11 @@ class AminatouPlusEffect extends OneShotEffect { } class AminatouUltimateEffect extends OneShotEffect { - public AminatouUltimateEffect (){ + + public AminatouUltimateEffect() { super(Outcome.Benefit); - staticText = "Choose left or right. Each player gains control of all nonland permanents other than Aminatou," + - " the Fateshifter controlled by the next player in the chosen direction."; + staticText = "Choose left or right. Each player gains control of all nonland permanents other than Aminatou," + + " the Fateshifter controlled by the next player in the chosen direction."; } public AminatouUltimateEffect(final AminatouUltimateEffect effect) { @@ -129,7 +132,9 @@ class AminatouUltimateEffect extends OneShotEffect { } @Override - public AminatouUltimateEffect copy(){return new AminatouUltimateEffect(this);} + public AminatouUltimateEffect copy() { + return new AminatouUltimateEffect(this); + } @Override public boolean apply(Game game, Ability source) { @@ -154,7 +159,7 @@ class AminatouUltimateEffect extends OneShotEffect { return false; } // skip players out of range - if (!game.getState().getPlayersInRange(controller.getId(), game).contains(nextPlayer)){ + if (!game.getState().getPlayersInRange(controller.getId(), game).contains(nextPlayer)) { continue; } // save first next player to check for iteration stop @@ -164,7 +169,7 @@ class AminatouUltimateEffect extends OneShotEffect { FilterNonlandPermanent nextPlayerNonlandPermanentsFilter = new FilterNonlandPermanent(); nextPlayerNonlandPermanentsFilter.add(new ControllerIdPredicate(nextPlayer)); for (Permanent permanent : game.getBattlefield().getAllActivePermanents(nextPlayerNonlandPermanentsFilter, game)) { - if (permanent.getId().equals(source.getSourceId())){ + if (permanent.getId().equals(source.getSourceId())) { continue; } ContinuousEffect effect = new GainControlTargetEffect(Duration.EndOfGame, currentPlayer); @@ -188,4 +193,3 @@ class AminatouUltimateEffect extends OneShotEffect { return nextPlayerId; } } - diff --git a/Mage.Sets/src/mage/cards/a/AmphibiousKavu.java b/Mage.Sets/src/mage/cards/a/AmphibiousKavu.java new file mode 100644 index 00000000000..95480164864 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AmphibiousKavu.java @@ -0,0 +1,48 @@ + +package mage.cards.a; + +import java.util.UUID; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.common.BlocksOrBecomesBlockedByOneOrMoreTriggeredAbility; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.ColorPredicate; + +/** + * + * @author L_J + */ +public final class AmphibiousKavu extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("blue and/or black creatures"); + + static { + filter.add(Predicates.or(new ColorPredicate(ObjectColor.BLUE), new ColorPredicate(ObjectColor.BLACK))); + } + + public AmphibiousKavu(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}"); + this.subtype.add(SubType.KAVU); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Whenever Amphibious Kavu blocks or becomes blocked by one or more blue and/or black creatures, Amphibious Kavu gets +3/+3 until end of turn. + this.addAbility(new BlocksOrBecomesBlockedByOneOrMoreTriggeredAbility(new BoostSourceEffect(3, 3, Duration.EndOfTurn), filter, false)); + } + + public AmphibiousKavu(final AmphibiousKavu card) { + super(card); + } + + @Override + public AmphibiousKavu copy() { + return new AmphibiousKavu(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/AngelOfSerenity.java b/Mage.Sets/src/mage/cards/a/AngelOfSerenity.java index b34df8718c7..4dfb63bbc40 100644 --- a/Mage.Sets/src/mage/cards/a/AngelOfSerenity.java +++ b/Mage.Sets/src/mage/cards/a/AngelOfSerenity.java @@ -1,43 +1,34 @@ - package mage.cards.a; import java.util.UUID; import mage.MageInt; -import mage.MageObject; import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.LeavesBattlefieldTriggeredAbility; -import mage.abilities.common.ZoneChangeTriggeredAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ExileTargetForSourceEffect; import mage.abilities.effects.common.ReturnFromExileForSourceEffect; import mage.abilities.keyword.FlyingAbility; -import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.SubType; import mage.constants.Zone; -import mage.filter.FilterCard; import mage.filter.common.FilterCreatureCard; -import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.permanent.AnotherPredicate; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; -import mage.players.Player; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardIdPredicate; import mage.target.Target; -import mage.target.common.TargetCardInGraveyard; -import mage.target.common.TargetCreaturePermanent; -import mage.util.CardUtil; +import mage.target.common.TargetCardInGraveyardOrBattlefield; /** * * @author LevelX2 */ public final class AngelOfSerenity extends CardImpl { + + private static final String rule = "you may exile up to three other target creatures from the battlefield and/or creature cards from graveyards."; public AngelOfSerenity(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{W}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}{W}{W}"); this.subtype.add(SubType.ANGEL); this.power = new MageInt(5); @@ -47,7 +38,12 @@ public final class AngelOfSerenity extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // When Angel of Serenity enters the battlefield, you may exile up to three other target creatures from the battlefield and/or creature cards from graveyards. - this.addAbility(new AngelOfSerenityTriggeredAbility()); + FilterCreatureCard filter = new FilterCreatureCard("creatures from the battlefield and/or a graveyard"); + filter.add(Predicates.not(new CardIdPredicate(this.getId()))); + Ability ability = new EntersBattlefieldTriggeredAbility(new ExileTargetForSourceEffect().setText(rule), true); + Target target = new TargetCardInGraveyardOrBattlefield(0, 3, filter); + ability.addTarget(target); + this.addAbility(ability); // When Angel of Serenity leaves the battlefield, return the exiled cards to their owners' hands. this.addAbility(new LeavesBattlefieldTriggeredAbility(new ReturnFromExileForSourceEffect(Zone.HAND, false, true), false)); @@ -62,92 +58,3 @@ public final class AngelOfSerenity extends CardImpl { return new AngelOfSerenity(this); } } - -class AngelOfSerenityTriggeredAbility extends ZoneChangeTriggeredAbility { - - public AngelOfSerenityTriggeredAbility() { - super(Zone.BATTLEFIELD, new AngelOfSerenityEnterEffect(), "When {this} enters the battlefield, ", true); - } - - public AngelOfSerenityTriggeredAbility(AngelOfSerenityTriggeredAbility ability) { - super(ability); - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (super.checkTrigger(event, game)) { - getTargets().clear(); - FilterCreaturePermanent filter = new FilterCreaturePermanent("up to three other target creatures"); - filter.add(new AnotherPredicate()); - TargetCreaturePermanent target1 = new TargetCreaturePermanent(0, 3, filter, false); - game.getPlayer(getControllerId()).chooseTarget(Outcome.Exile, target1, this, game); - if (!target1.getTargets().isEmpty()) { - getTargets().add(target1); - - } - int leftTargets = 3 - target1.getTargets().size(); - if (leftTargets > 0) { - FilterCard filter2 = new FilterCreatureCard("up to " + leftTargets + " target creature card" + (leftTargets > 1 ? "s" : "") + " from graveyards"); - TargetCardInGraveyard target2 = new TargetCardInGraveyard(0, leftTargets, filter2); - game.getPlayer(getControllerId()).chooseTarget(Outcome.Exile, target2, this, game); - if (!target2.getTargets().isEmpty()) { - getTargets().add(target2); - } - } - return true; - } - return false; - } - - @Override - public AngelOfSerenityTriggeredAbility copy() { - return new AngelOfSerenityTriggeredAbility(this); - } - -} - -class AngelOfSerenityEnterEffect extends OneShotEffect { - - public AngelOfSerenityEnterEffect() { - super(Outcome.ReturnToHand); - this.staticText = "you may exile up to three other target creatures from the battlefield and/or creature cards from graveyards"; - } - - public AngelOfSerenityEnterEffect(final AngelOfSerenityEnterEffect effect) { - super(effect); - } - - @Override - public AngelOfSerenityEnterEffect copy() { - return new AngelOfSerenityEnterEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - boolean result = true; - Player controller = game.getPlayer(source.getControllerId()); - MageObject sourceObject = game.getObject(source.getSourceId()); - if (controller != null && sourceObject != null && !source.getTargets().isEmpty()) { - UUID exileZoneId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()); - for (Target target : source.getTargets()) { - if (target instanceof TargetCreaturePermanent) { - for (UUID permanentId : target.getTargets()) { - Permanent permanent = game.getPermanent(permanentId); - if (permanent != null) { - result |= controller.moveCardToExileWithInfo(permanent, exileZoneId, sourceObject.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true); - } - } - - } else if (target instanceof TargetCardInGraveyard) { - for (UUID cardId : target.getTargets()) { - Card card = game.getCard(cardId); - if (card != null) { - result |= controller.moveCardToExileWithInfo(card, exileZoneId, sourceObject.getIdName(), source.getSourceId(), game, Zone.GRAVEYARD, true); - } - } - } - } - } - return result; - } -} diff --git a/Mage.Sets/src/mage/cards/a/AngelicReward.java b/Mage.Sets/src/mage/cards/a/AngelicReward.java new file mode 100644 index 00000000000..dce1309e721 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AngelicReward.java @@ -0,0 +1,53 @@ +package mage.cards.a; + +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTappedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continuous.BoostEnchantedEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.TotemArmorAbility; +import mage.abilities.mana.AnyColorManaAbility; +import mage.abilities.mana.WhiteManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author JayDi85 + */ + +public final class AngelicReward extends CardImpl { + + public AngelicReward(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}{W}"); + this.subtype.add(SubType.AURA); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // Enchanted creature gets +3/+3 and has flying. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(3, 3, Duration.WhileOnBattlefield))); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(FlyingAbility.getInstance(), AttachmentType.AURA))); + } + + public AngelicReward(final AngelicReward card) { + super(card); + } + + @Override + public AngelicReward copy() { + return new AngelicReward(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/AngelsTomb.java b/Mage.Sets/src/mage/cards/a/AngelsTomb.java index 6cd8c0e5ad9..9eec7a62863 100644 --- a/Mage.Sets/src/mage/cards/a/AngelsTomb.java +++ b/Mage.Sets/src/mage/cards/a/AngelsTomb.java @@ -1,10 +1,8 @@ package mage.cards.a; -import java.util.UUID; - -import mage.MageInt; -import mage.abilities.common.CreatureEntersBattlefieldTriggeredAbility; +import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; @@ -12,10 +10,12 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.game.permanent.token.TokenImpl; -import mage.game.permanent.token.Token; +import mage.constants.Zone; +import mage.filter.StaticFilters; import mage.game.permanent.token.custom.CreatureToken; +import java.util.UUID; + /** * @author Loki */ @@ -25,12 +25,18 @@ public final class AngelsTomb extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); // Whenever a creature enters the battlefield under your control, you may have Angel's Tomb become a 3/3 white Angel artifact creature with flying until end of turn. - this.addAbility(new CreatureEntersBattlefieldTriggeredAbility(new BecomesCreatureSourceEffect( - new CreatureToken(3, 3, "3/3 white Angel artifact creature with flying") - .withColor("W") - .withSubType(SubType.ANGEL) - .withAbility(FlyingAbility.getInstance()), - "", Duration.EndOfTurn), true)); + Effect effect = new BecomesCreatureSourceEffect(new CreatureToken(3, 3, "3/3 white Angel artifact creature with flying") + .withColor("W") + .withSubType(SubType.ANGEL) + .withAbility(FlyingAbility.getInstance()), + "", Duration.EndOfTurn) + .setText("have {this} become a 3/3 white Angel artifact creature with flying until end of turn"); + this.addAbility(new EntersBattlefieldControlledTriggeredAbility( + Zone.BATTLEFIELD, + effect, + StaticFilters.FILTER_PERMANENT_CREATURE_A, + true) + ); } public AngelsTomb(final AngelsTomb card) { diff --git a/Mage.Sets/src/mage/cards/a/Antagonism.java b/Mage.Sets/src/mage/cards/a/Antagonism.java new file mode 100644 index 00000000000..2bde3ac7b29 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/Antagonism.java @@ -0,0 +1,64 @@ +package mage.cards.a; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfEndStepTriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetController; +import mage.game.Game; +import mage.watchers.common.BloodthirstWatcher; + +/** + * + * @author jeffwadsworth + */ +public final class Antagonism extends CardImpl { + + private static final String rule = "{this} deals 2 damage to that player unless one of his or her opponents was dealt damage this turn"; + + public Antagonism(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}"); + + // At the beginning of each player's end step, Antagonism deals 2 damage to that player unless one of his or her opponents was dealt damage this turn. + this.addAbility(new BeginningOfEndStepTriggeredAbility(new ConditionalOneShotEffect(new DamageTargetEffect(2), + new OpponentWasNotDealtDamageCondition(), rule), TargetController.ANY, false)); + + } + + public Antagonism(final Antagonism card) { + super(card); + } + + @Override + public Antagonism copy() { + return new Antagonism(this); + } +} + +class OpponentWasNotDealtDamageCondition implements Condition { + + public OpponentWasNotDealtDamageCondition() { + } + + @Override + public boolean apply(Game game, Ability source) { + UUID activePlayer = game.getState().getActivePlayerId(); + if (activePlayer != null) { + BloodthirstWatcher watcher = (BloodthirstWatcher) game.getState().getWatchers().get(BloodthirstWatcher.class.getSimpleName(), activePlayer); + if (watcher != null) { + return !watcher.conditionMet(); + } + } + return false; + } + + @Override + public String toString() { + return "if an opponent was dealt damage this turn"; + } +} diff --git a/Mage.Sets/src/mage/cards/a/ArcheryTraining.java b/Mage.Sets/src/mage/cards/a/ArcheryTraining.java new file mode 100644 index 00000000000..f70caaa22c9 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/ArcheryTraining.java @@ -0,0 +1,67 @@ +package mage.cards.a; + +import java.util.UUID; +import mage.constants.SubType; +import mage.target.common.TargetCreaturePermanent; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.dynamicvalue.common.CountersSourceCount; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.constants.Outcome; +import mage.target.TargetPermanent; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AttachmentType; +import mage.constants.CardType; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.target.common.TargetAttackingOrBlockingCreature; + +/** + * + * @author jeffwadsworth + */ +public final class ArcheryTraining extends CardImpl { + + private static final String rule = "This creature deals X damage to target attacking or blocking creature, where X is the number of arrow counters on {this}."; + + public ArcheryTraining(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{W}"); + + this.subtype.add(SubType.AURA); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // At the beginning of your upkeep, you may put an arrow counter on Archery Training. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, + new AddCountersSourceEffect(CounterType.ARROW.createInstance(), true), TargetController.YOU, true)); + + // Enchanted creature has "{tap}: This creature deals X damage to target attacking or blocking creature, where X is the number of arrow counters on Archery Training." + Ability gainedAbility = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(new CountersSourceCount(CounterType.ARROW)).setText(rule), new TapSourceCost()); + gainedAbility.addTarget(new TargetAttackingOrBlockingCreature()); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(gainedAbility, AttachmentType.AURA))); + + } + + public ArcheryTraining(final ArcheryTraining card) { + super(card); + } + + @Override + public ArcheryTraining copy() { + return new ArcheryTraining(this); + } +} diff --git a/Mage.Sets/src/mage/cards/a/ArixmethesSlumberingIsle.java b/Mage.Sets/src/mage/cards/a/ArixmethesSlumberingIsle.java index 3c6578b392a..615f5d7e243 100644 --- a/Mage.Sets/src/mage/cards/a/ArixmethesSlumberingIsle.java +++ b/Mage.Sets/src/mage/cards/a/ArixmethesSlumberingIsle.java @@ -28,7 +28,6 @@ import mage.constants.SubType; import mage.constants.SuperType; import mage.constants.Zone; import mage.counters.CounterType; -import mage.filter.FilterSpell; import mage.game.Game; import mage.game.permanent.Permanent; @@ -38,8 +37,6 @@ import mage.game.permanent.Permanent; */ public final class ArixmethesSlumberingIsle extends CardImpl { - private static final FilterSpell filter = new FilterSpell("a spell"); - public ArixmethesSlumberingIsle(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{U}"); diff --git a/Mage.Sets/src/mage/cards/a/AvatarOfGrowth.java b/Mage.Sets/src/mage/cards/a/AvatarOfGrowth.java new file mode 100644 index 00000000000..41cb4670036 --- /dev/null +++ b/Mage.Sets/src/mage/cards/a/AvatarOfGrowth.java @@ -0,0 +1,93 @@ +package mage.cards.a; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.cost.SpellCostReductionSourceForOpponentsEffect; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCardInLibrary; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class AvatarOfGrowth extends CardImpl { + + public AvatarOfGrowth(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}{G}"); + this.subtype.add(SubType.ELEMENTAL); + this.subtype.add(SubType.AVATAR); + + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // This spell costs {1} less to cast for each opponent you have. + this.addAbility(new SimpleStaticAbility(Zone.ALL, new SpellCostReductionSourceForOpponentsEffect("This spell costs {1} less to cast for each opponent you have"))); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // When Avatar of Growth enters the battlefield, each player searches their library for up to two basic land cards, puts them onto the battlefield, then shuffles their library. + this.addAbility(new EntersBattlefieldTriggeredAbility(new AvatarOfGrowthSearchEffect())); + } + + public AvatarOfGrowth(final AvatarOfGrowth card) { + super(card); + } + + @Override + public AvatarOfGrowth copy() { + return new AvatarOfGrowth(this); + } +} + +class AvatarOfGrowthSearchEffect extends OneShotEffect { + + public AvatarOfGrowthSearchEffect() { + super(Outcome.Detriment); + this.staticText = "each player searches their library for up to two basic land cards, puts them onto the battlefield, then shuffles their libarary"; + } + + public AvatarOfGrowthSearchEffect(final AvatarOfGrowthSearchEffect effect) { + super(effect); + } + + @Override + public AvatarOfGrowthSearchEffect copy() { + return new AvatarOfGrowthSearchEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null) { + TargetCardInLibrary target = new TargetCardInLibrary(0, 2, StaticFilters.FILTER_CARD_BASIC_LAND); + if (player.searchLibrary(target, game)) { + if (!target.getTargets().isEmpty()) { + player.moveCards(new CardsImpl(target.getTargets()), Zone.BATTLEFIELD, source, game); + } + } + player.shuffleLibrary(source, game); + } + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/b/BeamsplitterMage.java b/Mage.Sets/src/mage/cards/b/BeamsplitterMage.java index 0cd6c16ea0b..30853e7e8b7 100644 --- a/Mage.Sets/src/mage/cards/b/BeamsplitterMage.java +++ b/Mage.Sets/src/mage/cards/b/BeamsplitterMage.java @@ -1,19 +1,19 @@ package mage.cards.b; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.OneShotEffect; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; +import mage.constants.SubType; import mage.constants.Zone; import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; @@ -23,8 +23,9 @@ import mage.target.Target; import mage.target.TargetPermanent; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class BeamsplitterMage extends CardImpl { @@ -156,7 +157,7 @@ class BeamsplitterMageEffect extends OneShotEffect { if (usedTarget == null) { return false; } - FilterPermanent filter = new BeamsplitterMageFilter(usedTarget, source.getSourceId()); + FilterPermanent filter = new BeamsplitterMageFilter(usedTarget, source.getSourceId(), source.getControllerId()); Target target1 = new TargetPermanent(filter); target1.setNotTarget(true); if (controller.choose(outcome, target1, source.getSourceId(), game)) { @@ -199,10 +200,11 @@ class BeamsplitterMageFilter extends FilterControlledPermanent { private final Target target; private final UUID notId; - public BeamsplitterMageFilter(Target target, UUID notId) { + public BeamsplitterMageFilter(Target target, UUID notId, UUID controllerId) { super("creature this spell could target"); this.target = target; this.notId = notId; + this.add(new ControllerIdPredicate(controllerId)); } public BeamsplitterMageFilter(final BeamsplitterMageFilter filter) { diff --git a/Mage.Sets/src/mage/cards/b/BeckonApparition.java b/Mage.Sets/src/mage/cards/b/BeckonApparition.java index 9df22c5d0ba..523332f22d7 100644 --- a/Mage.Sets/src/mage/cards/b/BeckonApparition.java +++ b/Mage.Sets/src/mage/cards/b/BeckonApparition.java @@ -1,7 +1,6 @@ package mage.cards.b; -import java.util.UUID; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.ExileTargetEffect; import mage.cards.CardImpl; @@ -10,6 +9,8 @@ import mage.constants.CardType; import mage.game.permanent.token.BeckonApparitionToken; import mage.target.common.TargetCardInGraveyard; +import java.util.UUID; + /** * @author Loki */ @@ -18,6 +19,7 @@ public final class BeckonApparition extends CardImpl { public BeckonApparition(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W/B}"); + // Exile target card from a graveyard. Create a 1/1 white and black Spirit creature token with flying. this.getSpellAbility().addEffect(new ExileTargetEffect()); this.getSpellAbility().addTarget(new TargetCardInGraveyard()); this.getSpellAbility().addEffect(new CreateTokenEffect(new BeckonApparitionToken(), 1)); diff --git a/Mage.Sets/src/mage/cards/b/BendOrBreak.java b/Mage.Sets/src/mage/cards/b/BendOrBreak.java new file mode 100644 index 00000000000..e7bdfa74f98 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BendOrBreak.java @@ -0,0 +1,199 @@ + +package mage.cards.b; + +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.stream.Collectors; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.filter.FilterPlayer; +import mage.filter.common.FilterControlledLandPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.other.PlayerIdPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.players.PlayerList; +import mage.target.Target; +import mage.target.TargetPermanent; +import mage.target.TargetPlayer; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author LevelX2 & L_J + */ +public final class BendOrBreak extends CardImpl { + + public BendOrBreak(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{R}"); + + // Each player separates all nontoken lands they control into two piles. For each player, one of their piles is chosen by one of their opponents of their choice. Destroy all lands in the chosen piles. Tap all lands in the other piles. + this.getSpellAbility().addEffect(new BendOrBreakEffect()); + } + + public BendOrBreak(final BendOrBreak card) { + super(card); + } + + @Override + public BendOrBreak copy() { + return new BendOrBreak(this); + } +} + +class BendOrBreakEffect extends OneShotEffect { + + + public BendOrBreakEffect() { + super(Outcome.DestroyPermanent); + this.staticText = "Each player separates all nontoken lands they control into two piles. For each player, one of their piles is chosen by one of their opponents of their choice. Destroy all lands in the chosen piles. Tap all lands in the other piles"; + } + + public BendOrBreakEffect(final BendOrBreakEffect effect) { + super(effect); + } + + @Override + public BendOrBreakEffect copy() { + return new BendOrBreakEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + + // Map of players and their piles + Map>> playerPermanents = new LinkedHashMap<>(); + + PlayerList playerList = game.getState().getPlayerList().copy(); + while (!playerList.get().equals(source.getControllerId()) && controller.canRespond()) { + playerList.getNext(); + } + Player currentPlayer = game.getPlayer(playerList.get()); + Player nextPlayer; + UUID firstNextPlayer = null; + + while (!getNextPlayerInDirection(true, playerList, game).equals(firstNextPlayer) && controller.canRespond()) { + nextPlayer = game.getPlayer(playerList.get()); + if (nextPlayer == null) { + return false; + } + if (firstNextPlayer == null) { + firstNextPlayer = nextPlayer.getId(); + } + if (!nextPlayer.canRespond()) { + continue; + } + // Each player separates all nontoken lands they control into two piles + if (currentPlayer != null && game.getState().getPlayersInRange(controller.getId(), game).contains(currentPlayer.getId())) { + List firstPile = new ArrayList<>(); + List secondPile = new ArrayList<>(); + FilterControlledLandPermanent filter = new FilterControlledLandPermanent("lands you control to assign to the first pile (lands not chosen will be assigned to the second pile)"); + TargetPermanent target = new TargetControlledPermanent(0, Integer.MAX_VALUE, filter, true); + if (target.canChoose(source.getSourceId(), currentPlayer.getId(), game)) { + if (currentPlayer.chooseTarget(Outcome.Neutral, target, source, game)) { + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, currentPlayer.getId(), game)) { + if (target.getTargets().contains(permanent.getId())) { + firstPile.add(permanent); + } else { + secondPile.add(permanent); + } + } + } + + StringBuilder sb = new StringBuilder("First pile of ").append(currentPlayer.getLogName()).append(": "); + sb.append(firstPile.stream().map(Permanent::getLogName).collect(Collectors.joining(", "))); + + game.informPlayers(sb.toString()); + + sb = new StringBuilder("Second pile of ").append(currentPlayer.getLogName()).append(": "); + sb.append(secondPile.stream().map(Permanent::getLogName).collect(Collectors.joining(", "))); + + game.informPlayers(sb.toString()); + } + List> playerPiles = new ArrayList<>(); + playerPiles.add(firstPile); + playerPiles.add(secondPile); + playerPermanents.put(currentPlayer.getId(), playerPiles); + } + currentPlayer = nextPlayer; + } + + // For each player, one of their piles is chosen by one of their opponents of their choice + for (Map.Entry>> playerPiles : playerPermanents.entrySet()) { + Player player = game.getPlayer(playerPiles.getKey()); + if (player != null) { + FilterPlayer filter = new FilterPlayer("opponent"); + List opponentPredicates = new ArrayList<>(); + for (UUID opponentId : game.getOpponents(player.getId())) { + opponentPredicates.add(new PlayerIdPredicate(opponentId)); + } + filter.add(Predicates.or(opponentPredicates)); + Target target = new TargetPlayer(1, 1, true, filter); + target.setTargetController(player.getId()); + target.setAbilityController(source.getControllerId()); + if (player.chooseTarget(outcome, target, source, game)) { + Player chosenOpponent = game.getPlayer(target.getFirstTarget()); + if (chosenOpponent != null) { + List firstPile = playerPiles.getValue().get(0); + List secondPile = playerPiles.getValue().get(1); + game.informPlayers(player.getLogName() + " chose " + chosenOpponent.getLogName() + " to choose his pile"); + if (chosenOpponent.choosePile(outcome, "Piles of " + player.getName(), firstPile, secondPile, game)) { + List> lists = playerPiles.getValue(); + lists.clear(); + lists.add(firstPile); + lists.add(secondPile); + game.informPlayers(player.getLogName() + " will have their first pile destroyed"); + } else { + List> lists = playerPiles.getValue(); + lists.clear(); + lists.add(secondPile); + lists.add(firstPile); + game.informPlayers(player.getLogName() + " will have their second pile destroyed"); + } + } + } + } + } + // Destroy all lands in the chosen piles. Tap all lands in the other piles + for (Map.Entry>> playerPiles : playerPermanents.entrySet()) { + Player player = game.getPlayer(playerPiles.getKey()); + if (player != null) { + List pileToSac = playerPiles.getValue().get(0); + List pileToTap = playerPiles.getValue().get(1); + for (Permanent permanent : pileToSac) { + if (permanent != null) { + permanent.destroy(source.getSourceId(), game, false); + } + } + for (Permanent permanent : pileToTap) { + if (permanent != null) { + permanent.tap(game); + } + } + } + } + return true; + } + return false; + } + + private UUID getNextPlayerInDirection(boolean left, PlayerList playerList, Game game) { + UUID nextPlayerId; + if (left) { + nextPlayerId = playerList.getNext(); + } else { + nextPlayerId = playerList.getPrevious(); + } + return nextPlayerId; + } +} diff --git a/Mage.Sets/src/mage/cards/b/BetrothedOfFire.java b/Mage.Sets/src/mage/cards/b/BetrothedOfFire.java new file mode 100644 index 00000000000..95fbfb8440f --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BetrothedOfFire.java @@ -0,0 +1,71 @@ +package mage.cards.b; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeAttachedCost; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.effects.common.continuous.BoostEnchantedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.TargetPermanent; +import mage.target.common.TargetControlledPermanent; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class BetrothedOfFire extends CardImpl { + + private static final FilterControlledPermanent filter = new FilterControlledCreaturePermanent("an untapped creature"); + + static { + filter.add(Predicates.not(new TappedPredicate())); + } + + public BetrothedOfFire(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}"); + + this.subtype.add(SubType.AURA); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // Sacrifice an untapped creature: Enchanted creature gets +2/+0 until end of turn. + this.addAbility(new SimpleActivatedAbility( + new BoostEnchantedEffect(2, 0, Duration.EndOfTurn), + new SacrificeTargetCost(new TargetControlledPermanent(filter)) + )); + + // Sacrifice enchanted creature: Creatures you control get +2/+0 until end of turn. + this.addAbility(new SimpleActivatedAbility( + new BoostControlledEffect(2, 0, Duration.EndOfTurn), + new SacrificeAttachedCost() + )); + } + + public BetrothedOfFire(final BetrothedOfFire card) { + super(card); + } + + @Override + public BetrothedOfFire copy() { + return new BetrothedOfFire(this); + } +} diff --git a/Mage.Sets/src/mage/cards/b/BlindingAngel.java b/Mage.Sets/src/mage/cards/b/BlindingAngel.java index c75b26c07e6..f7f25c29ab0 100644 --- a/Mage.Sets/src/mage/cards/b/BlindingAngel.java +++ b/Mage.Sets/src/mage/cards/b/BlindingAngel.java @@ -1,14 +1,14 @@ - package mage.cards.b; import java.util.UUID; import mage.MageInt; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; -import mage.abilities.effects.common.SkipNextCombatEffect; +import mage.abilities.effects.common.SkipCombatStepEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.Duration; import mage.constants.SubType; /** @@ -16,26 +16,28 @@ import mage.constants.SubType; * @author Plopman */ public final class BlindingAngel extends CardImpl { - + public BlindingAngel(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}"); this.subtype.add(SubType.ANGEL); - + this.power = new MageInt(2); this.toughness = new MageInt(4); // Flying this.addAbility(FlyingAbility.getInstance()); - // Whenever Blinding Angel deals combat damage to a player, that player skips their next combat phase. - this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new SkipNextCombatEffect(), false, true)); - } + // Whenever Blinding Angel deals combat damage to a player, that player skips their next combat phase. + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new SkipCombatStepEffect(Duration.OneUse).setText("that player skips their next combat phase."), false, true)); + + } + public BlindingAngel(final BlindingAngel card) { super(card); } - + @Override public BlindingAngel copy() { return new BlindingAngel(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/b/BlindingRadiance.java b/Mage.Sets/src/mage/cards/b/BlindingRadiance.java new file mode 100644 index 00000000000..2ef6ef3039e --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BlindingRadiance.java @@ -0,0 +1,40 @@ +package mage.cards.b; + +import mage.abilities.effects.common.TapAllEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.common.FilterOpponentsCreaturePermanent; +import mage.filter.predicate.mageobject.ToughnessPredicate; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class BlindingRadiance extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterOpponentsCreaturePermanent("creatures your opponents control with toughness 2 or less"); + static { + filter.add(new ToughnessPredicate(ComparisonType.FEWER_THAN, 3)); + } + + public BlindingRadiance(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{W}"); + + // Tap all creatures your opponents control with toughness 2 or less. + TapAllEffect effect = new TapAllEffect(filter); + this.getSpellAbility().addEffect(effect); + } + + public BlindingRadiance(final BlindingRadiance card) { + super(card); + } + + @Override + public BlindingRadiance copy() { + return new BlindingRadiance(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/b/BoarUmbra.java b/Mage.Sets/src/mage/cards/b/BoarUmbra.java index c161a7a1ca4..5e40bb1e6ad 100644 --- a/Mage.Sets/src/mage/cards/b/BoarUmbra.java +++ b/Mage.Sets/src/mage/cards/b/BoarUmbra.java @@ -31,8 +31,11 @@ public final class BoarUmbra extends CardImpl { this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); Ability ability = new EnchantAbility(auraTarget.getTargetName()); this.addAbility(ability); + // Enchanted creature gets +3/+3. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(3, 3, Duration.WhileOnBattlefield))); + + // Totem armor this.addAbility(new TotemArmorAbility()); } diff --git a/Mage.Sets/src/mage/cards/b/BrilliantUltimatum.java b/Mage.Sets/src/mage/cards/b/BrilliantUltimatum.java index c9bad9c5c71..4dc433e7c1e 100644 --- a/Mage.Sets/src/mage/cards/b/BrilliantUltimatum.java +++ b/Mage.Sets/src/mage/cards/b/BrilliantUltimatum.java @@ -1,4 +1,3 @@ - package mage.cards.b; import java.util.ArrayList; @@ -111,6 +110,7 @@ class BrilliantUltimatumEffect extends OneShotEffect { TargetCard targetExiledCard = new TargetCard(Zone.EXILED, new FilterCard()); if (controller.chooseTarget(Outcome.PlayForFree, selectedPile, targetExiledCard, source, game)) { Card card = selectedPile.get(targetExiledCard.getFirstTarget(), game); + controller.canPlayLand(); if (controller.playCard(card, game, true, true, new MageObjectReference(source.getSourceObject(game), game))) { selectedPileCards.remove(card); selectedPile.remove(card); diff --git a/Mage.Sets/src/mage/cards/b/BronzeHorse.java b/Mage.Sets/src/mage/cards/b/BronzeHorse.java new file mode 100644 index 00000000000..28180cf2bb4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BronzeHorse.java @@ -0,0 +1,91 @@ + +package mage.cards.b; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalReplacementEffect; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.PreventAllDamageToSourceEffect; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.stack.Spell; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.permanent.AnotherPredicate; +import mage.target.Target; + +/** + * + * @author L_J + */ +public final class BronzeHorse extends CardImpl { + + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); + + static { + filter.add(new AnotherPredicate()); + } + + public BronzeHorse(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT, CardType.CREATURE},"{7}"); + this.subtype.add(SubType.HORSE); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // Trample + this.addAbility(TrampleAbility.getInstance()); + + // As long as you control another creature, prevent all damage that would be dealt to Bronze Horse by spells that target it. + Effect effect = new ConditionalReplacementEffect(new PreventDamageToSourceBySpellsThatTargetIt(), new PermanentsOnTheBattlefieldCondition(filter)); + effect.setText("As long as you control another creature, prevent all damage that would be dealt to {this} by spells that target it."); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); + } + + public BronzeHorse(final BronzeHorse card) { + super(card); + } + + @Override + public BronzeHorse copy() { + return new BronzeHorse(this); + } +} + +class PreventDamageToSourceBySpellsThatTargetIt extends PreventAllDamageToSourceEffect { + + public PreventDamageToSourceBySpellsThatTargetIt() { + super(Duration.WhileOnBattlefield); + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (super.applies(event, source, game)) { + if (event.getTargetId().equals(source.getSourceId())) { + Spell spell = game.getStack().getSpell(event.getSourceId()); + if (spell != null) { + for (UUID modeId : spell.getStackAbility().getModes().getSelectedModes()) { + Mode mode = spell.getStackAbility().getModes().get(modeId); + for (Target target : mode.getTargets()) { + for (UUID targetId : target.getTargets()) { + if (targetId.equals(source.getSourceId())) { + return true; + } + } + } + } + } + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/c/CanalDredger.java b/Mage.Sets/src/mage/cards/c/CanalDredger.java new file mode 100644 index 00000000000..d1a8d2b7bbe --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CanalDredger.java @@ -0,0 +1,52 @@ + +package mage.cards.c; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.InfoEffect; +import mage.abilities.effects.common.PutOnLibraryTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.target.common.TargetCardInYourGraveyard; + +/** + * + * @author L_J + */ +public final class CanalDredger extends CardImpl { + + public CanalDredger(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{4}"); + this.subtype.add(SubType.CONSTRUCT); + this.power = new MageInt(1); + this.toughness = new MageInt(5); + + // TODO: Draft specific abilities not implemented + // Draft Canal Dredger face up. + this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("Draft Canal Dredger face up."))); + + // Each player passes the last card from each booster pack to a player who drafted a card named Canal Dredger. + this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("Each player passes the last card from each booster pack to a player who drafted a card named Canal Dredger."))); + + // {T}: Put target card from your graveyard on the bottom of your library. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PutOnLibraryTargetEffect(false), new TapSourceCost()); + ability.addTarget(new TargetCardInYourGraveyard()); + this.addAbility(ability); + } + + public CanalDredger(final CanalDredger card) { + super(card); + } + + @Override + public CanalDredger copy() { + return new CanalDredger(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/CatharsCrusade.java b/Mage.Sets/src/mage/cards/c/CatharsCrusade.java index bfb4f678fbd..59a6ce427ef 100644 --- a/Mage.Sets/src/mage/cards/c/CatharsCrusade.java +++ b/Mage.Sets/src/mage/cards/c/CatharsCrusade.java @@ -1,27 +1,34 @@ package mage.cards.c; -import java.util.UUID; -import mage.abilities.common.CreatureEntersBattlefieldTriggeredAbility; +import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; import mage.abilities.effects.common.counter.AddCountersAllEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.Zone; import mage.counters.CounterType; +import mage.filter.StaticFilters; import mage.filter.common.FilterControlledCreaturePermanent; +import java.util.UUID; + /** - * * @author Loki */ public final class CatharsCrusade extends CardImpl { public CatharsCrusade(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}{W}"); // Whenever a creature enters the battlefield under your control, put a +1/+1 counter on each creature you control. - this.addAbility(new CreatureEntersBattlefieldTriggeredAbility(new AddCountersAllEffect(CounterType.P1P1.createInstance(), new FilterControlledCreaturePermanent()))); + this.addAbility(new EntersBattlefieldControlledTriggeredAbility( + Zone.BATTLEFIELD, + new AddCountersAllEffect(CounterType.P1P1.createInstance(), new FilterControlledCreaturePermanent()), + StaticFilters.FILTER_PERMANENT_CREATURE_A, + false) + ); } public CatharsCrusade(final CatharsCrusade card) { diff --git a/Mage.Sets/src/mage/cards/c/CathedralOfSerra.java b/Mage.Sets/src/mage/cards/c/CathedralOfSerra.java new file mode 100644 index 00000000000..b5702899891 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CathedralOfSerra.java @@ -0,0 +1,47 @@ + +package mage.cards.c; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.keyword.BandsWithOtherAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SuperType; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.filter.predicate.mageobject.SupertypePredicate; + +/** + * + * @author L_J + */ +public final class CathedralOfSerra extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("White legendary creatures"); + + static { + filter.add(new ColorPredicate(ObjectColor.WHITE)); + filter.add(new SupertypePredicate(SuperType.LEGENDARY)); + } + + public CathedralOfSerra(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + // White legendary creatures you control have "bands with other legendary creatures." + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledEffect(new BandsWithOtherAbility(SuperType.LEGENDARY), Duration.WhileOnBattlefield, filter))); + } + + public CathedralOfSerra(final CathedralOfSerra card) { + super(card); + } + + @Override + public CathedralOfSerra copy() { + return new CathedralOfSerra(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/CelestialDawn.java b/Mage.Sets/src/mage/cards/c/CelestialDawn.java index 787eaf39cc2..babf9c8d241 100644 --- a/Mage.Sets/src/mage/cards/c/CelestialDawn.java +++ b/Mage.Sets/src/mage/cards/c/CelestialDawn.java @@ -135,7 +135,7 @@ class CelestialDawnToWhiteEffect extends ContinuousEffectImpl { // Command for (CommandObject commandObject : game.getState().getCommand()) { if (commandObject instanceof Commander) { - if (commandObject.getControllerId().equals(controller.getId())) { + if (commandObject.isControlledBy(controller.getId())) { setColor(commandObject.getColor(game), game); } } diff --git a/Mage.Sets/src/mage/cards/c/ChanceForGlory.java b/Mage.Sets/src/mage/cards/c/ChanceForGlory.java index ab8c37fb8aa..dff4e834e24 100644 --- a/Mage.Sets/src/mage/cards/c/ChanceForGlory.java +++ b/Mage.Sets/src/mage/cards/c/ChanceForGlory.java @@ -1,16 +1,17 @@ package mage.cards.c; -import java.util.UUID; -import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.effects.common.continuous.GainAbilityAllEffect; import mage.abilities.effects.common.turn.AddExtraTurnControllerEffect; import mage.abilities.keyword.IndestructibleAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; +import mage.filter.StaticFilters; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class ChanceForGlory extends CardImpl { @@ -19,9 +20,10 @@ public final class ChanceForGlory extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{R}{W}"); // Creatures you control gain indestructible. Take an extra turn after this one. At the beginning of that turn's end step, you lose the game. - this.getSpellAbility().addEffect(new GainAbilityControlledEffect( - IndestructibleAbility.getInstance(), Duration.EndOfGame - ).setText("Creatures you control gain indestructible")); + this.getSpellAbility().addEffect(new GainAbilityAllEffect( + IndestructibleAbility.getInstance(), Duration.EndOfGame, + StaticFilters.FILTER_CONTROLLED_CREATURES + ).setText("Creatures you control gain indestructible.")); this.getSpellAbility().addEffect(new AddExtraTurnControllerEffect(true)); } diff --git a/Mage.Sets/src/mage/cards/c/ClearTheLand.java b/Mage.Sets/src/mage/cards/c/ClearTheLand.java new file mode 100644 index 00000000000..abb2b345579 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/ClearTheLand.java @@ -0,0 +1,92 @@ +package mage.cards.c; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.game.Game; +import mage.players.Library; +import mage.players.Player; + +/** + * + * @author davidmfritz + */ +public final class ClearTheLand extends CardImpl { + + public ClearTheLand(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{G}"); + + + // Each player reveals the top five cards of his or her library, puts all land cards revealed this way onto the battlefield tapped, and exiles the rest. + getSpellAbility().addEffect(new ClearTheLandEffect()); + } + + public ClearTheLand(final ClearTheLand card) { + super(card); + } + + @Override + public ClearTheLand copy() { + return new ClearTheLand(this); + } +} + +class ClearTheLandEffect extends OneShotEffect { + + public ClearTheLandEffect() { + super(Outcome.Benefit); + this.staticText = "Each player reveals the top five cards of his or her library, puts all land cards revealed this way onto the battlefield tapped, and exiles the rest."; + } + + public ClearTheLandEffect(final ClearTheLandEffect effect) { + super(effect); + } + + @Override + public ClearTheLandEffect copy() { + return new ClearTheLandEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + + boolean tapped = true; + + Player controller = game.getPlayer(source.getControllerId()); + + if (controller != null) { + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null) { + Library library = player.getLibrary(); + Cards cardsToReveal = new CardsImpl(); + cardsToReveal.addAll(library.getTopCards(game, 5)); + if (!cardsToReveal.isEmpty()) { + player.revealCards(source, "Revealed cards for " + player.getName(), cardsToReveal, game); + Cards cardsToPutOnBattlefield = new CardsImpl(); + Cards cardsToExile = new CardsImpl(); + for (Card card : cardsToReveal.getCards(game)) { + if (card.isLand()) { + cardsToPutOnBattlefield.add(card); + } else { + cardsToExile.add(card); + } + } + player.moveCards(cardsToPutOnBattlefield.getCards(game), Zone.BATTLEFIELD, source, game, tapped, false, true, null); + player.moveCards(cardsToExile.getCards(game), Zone.EXILED, source, game); + } + } + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/c/CoffinPurge.java b/Mage.Sets/src/mage/cards/c/CoffinPurge.java index 34d26d9c913..200d6a4a9c9 100644 --- a/Mage.Sets/src/mage/cards/c/CoffinPurge.java +++ b/Mage.Sets/src/mage/cards/c/CoffinPurge.java @@ -1,7 +1,6 @@ package mage.cards.c; -import java.util.UUID; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.keyword.FlashbackAbility; @@ -11,21 +10,21 @@ import mage.constants.CardType; import mage.constants.TimingRule; import mage.target.common.TargetCardInGraveyard; +import java.util.UUID; + /** - * * @author cbt33, jonubuu (Withered Wretch) */ public final class CoffinPurge extends CardImpl { public CoffinPurge(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{B}"); - + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}"); // Exile target card from a graveyard. - this.getSpellAbility().addEffect(new ExileTargetEffect()); this.getSpellAbility().addTarget(new TargetCardInGraveyard()); + // Flashback {B} this.addAbility(new FlashbackAbility(new ManaCostsImpl("{B}"), TimingRule.INSTANT)); } diff --git a/Mage.Sets/src/mage/cards/c/ConfrontTheAssault.java b/Mage.Sets/src/mage/cards/c/ConfrontTheAssault.java new file mode 100644 index 00000000000..985bc5f919a --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/ConfrontTheAssault.java @@ -0,0 +1,45 @@ +package mage.cards.c; + +import mage.abilities.Ability; +import mage.abilities.common.CastOnlyDuringPhaseStepSourceAbility; +import mage.abilities.condition.common.AttackedThisStepCondition; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.PhaseStep; +import mage.constants.TurnPhase; +import mage.game.permanent.token.SpiritWhiteToken; +import mage.watchers.common.PlayerAttackedStepWatcher; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class ConfrontTheAssault extends CardImpl { + + public ConfrontTheAssault(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{W}"); + + // Cast this spell only if a creature is attacking you. + Ability ability = new CastOnlyDuringPhaseStepSourceAbility( + TurnPhase.COMBAT, PhaseStep.DECLARE_ATTACKERS, AttackedThisStepCondition.instance, + "Cast this spell only if a creature is attacking you." + ); + ability.addWatcher(new PlayerAttackedStepWatcher()); + this.addAbility(ability); + + // Create three 1/1 white Spirit creature tokens with flying. + this.getSpellAbility().addEffect(new CreateTokenEffect(new SpiritWhiteToken("ANA"), 3)); + } + + public ConfrontTheAssault(final ConfrontTheAssault card) { + super(card); + } + + @Override + public ConfrontTheAssault copy() { + return new ConfrontTheAssault(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/c/CoverOfWinter.java b/Mage.Sets/src/mage/cards/c/CoverOfWinter.java index 5497f041bb2..7d9fdfa4264 100644 --- a/Mage.Sets/src/mage/cards/c/CoverOfWinter.java +++ b/Mage.Sets/src/mage/cards/c/CoverOfWinter.java @@ -88,7 +88,7 @@ class CoverOfWinterEffect extends PreventionEffectImpl { if (event.getType() == GameEvent.EventType.DAMAGE_CREATURE) { Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent != null && permanent.getControllerId().equals(source.getControllerId())) { + if (permanent != null && permanent.isControlledBy(source.getControllerId())) { return super.applies(event, source, game); } } diff --git a/Mage.Sets/src/mage/cards/c/CrabUmbra.java b/Mage.Sets/src/mage/cards/c/CrabUmbra.java index 86f5d56cf78..da173d83406 100644 --- a/Mage.Sets/src/mage/cards/c/CrabUmbra.java +++ b/Mage.Sets/src/mage/cards/c/CrabUmbra.java @@ -2,6 +2,7 @@ package mage.cards.c; import java.util.UUID; + import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; @@ -19,13 +20,12 @@ import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** - * * @author Loki */ public final class CrabUmbra extends CardImpl { public CrabUmbra(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{U}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{U}"); this.subtype.add(SubType.AURA); @@ -35,8 +35,11 @@ public final class CrabUmbra extends CardImpl { this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); Ability ability = new EnchantAbility(auraTarget.getTargetName()); this.addAbility(ability); + // {2}{U}: Untap enchanted creature. this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new UntapEnchantedEffect(), new ManaCostsImpl("{2}{U}"))); + + // Totem armor this.addAbility(new TotemArmorAbility()); } diff --git a/Mage.Sets/src/mage/cards/c/Cremate.java b/Mage.Sets/src/mage/cards/c/Cremate.java index a5e061094ad..62c465e34f1 100644 --- a/Mage.Sets/src/mage/cards/c/Cremate.java +++ b/Mage.Sets/src/mage/cards/c/Cremate.java @@ -1,7 +1,6 @@ package mage.cards.c; -import java.util.UUID; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.ExileTargetEffect; import mage.cards.CardImpl; @@ -9,17 +8,21 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.target.common.TargetCardInGraveyard; +import java.util.UUID; + /** - * * @author Loki */ public final class Cremate extends CardImpl { public Cremate(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{B}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}"); + // Exile target card from a graveyard. this.getSpellAbility().addEffect(new ExileTargetEffect()); this.getSpellAbility().addTarget(new TargetCardInGraveyard()); + + // Draw a card. this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1)); } diff --git a/Mage.Sets/src/mage/cards/c/CruelCut.java b/Mage.Sets/src/mage/cards/c/CruelCut.java new file mode 100644 index 00000000000..267732f89f2 --- /dev/null +++ b/Mage.Sets/src/mage/cards/c/CruelCut.java @@ -0,0 +1,42 @@ +package mage.cards.c; + +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.PowerPredicate; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author JayDi85 + */ + +public final class CruelCut extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with power 2 or less"); + + static { + filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, 3)); + } + + public CruelCut(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{B}"); + + // Destroy target creature with power 2 or less. + this.getSpellAbility().addEffect(new DestroyTargetEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + } + + public CruelCut(final CruelCut card) { + super(card); + } + + @Override + public CruelCut copy() { + return new CruelCut(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/CyclopeanTomb.java b/Mage.Sets/src/mage/cards/c/CyclopeanTomb.java index 77e7787f930..b37803bd255 100644 --- a/Mage.Sets/src/mage/cards/c/CyclopeanTomb.java +++ b/Mage.Sets/src/mage/cards/c/CyclopeanTomb.java @@ -1,6 +1,9 @@ - package mage.cards.c; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; @@ -31,11 +34,6 @@ import mage.target.common.TargetLandPermanent; import mage.target.targetpointer.FixedTarget; import mage.watchers.Watcher; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; - /** * * @author MTGfan @@ -123,7 +121,6 @@ class CyclopeanTombCreateTriggeredEffect extends OneShotEffect { if (controller != null) { Permanent tomb = game.getPermanentOrLKIBattlefield(source.getSourceId()); // we need to set the correct source object DelayedTriggeredAbility ability = new AtTheBeginOfYourNextUpkeepDelayedTriggeredAbility(new CyclopeanTombEffect(), Duration.EndOfGame, false); - ability.setSourceObject(tomb, game); ability.setControllerId(source.getControllerId()); ability.setSourceId(source.getSourceId()); game.addDelayedTriggeredAbility(ability); diff --git a/Mage.Sets/src/mage/cards/d/DealBroker.java b/Mage.Sets/src/mage/cards/d/DealBroker.java new file mode 100644 index 00000000000..432f5836934 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DealBroker.java @@ -0,0 +1,50 @@ + +package mage.cards.d; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.DrawDiscardControllerEffect; +import mage.abilities.effects.common.InfoEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Zone; + +/** + * + * @author L_J + */ +public final class DealBroker extends CardImpl { + + public DealBroker(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT, CardType.CREATURE},"{3}"); + this.subtype.add(SubType.CONSTRUCT); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // TODO: Draft specific abilities not implemented + // Draft Deal Broker face up. + this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("Draft Deal Broker face up."))); + + // Immediately after the draft, you may reveal a card in your card pool. Each other player may offer you one card in their card pool in exchange. You may accept any one offer. + this.addAbility(new SimpleStaticAbility(Zone.ALL, new InfoEffect("Immediately after the draft, you may reveal a card in your card pool. " + + "Each other player may offer you one card in their card pool in exchange. You may accept any one offer."))); + + // {T}: Draw a card, then discard a card. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new DrawDiscardControllerEffect(), new TapSourceCost())); + } + + public DealBroker(final DealBroker card) { + super(card); + } + + @Override + public DealBroker copy() { + return new DealBroker(this); + } + +} diff --git a/Mage.Sets/src/mage/cards/d/DeathOrGlory.java b/Mage.Sets/src/mage/cards/d/DeathOrGlory.java new file mode 100644 index 00000000000..1417f0bd850 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DeathOrGlory.java @@ -0,0 +1,129 @@ + +package mage.cards.d; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.cards.Cards; +import mage.cards.CardsImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.common.FilterCreatureCard; +import mage.game.Game; +import mage.players.Player; +import mage.target.Target; +import mage.target.TargetCard; +import mage.target.common.TargetOpponent; + +/** + * + * @author L_J + */ +public final class DeathOrGlory extends CardImpl { + + public DeathOrGlory(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{W}"); + + // Separate all creature cards in your graveyard into two piles. Exile the pile of an opponent’s choice and return the other to the battlefield. + this.getSpellAbility().addEffect(new DeathOrGloryEffect()); + } + + public DeathOrGlory(final DeathOrGlory card) { + super(card); + } + + @Override + public DeathOrGlory copy() { + return new DeathOrGlory(this); + } +} + +class DeathOrGloryEffect extends OneShotEffect { + + DeathOrGloryEffect() { + super(Outcome.Benefit); + this.staticText = "Separate all creature cards in your graveyard into two piles. Exile the pile of an opponent’s choice and return the other to the battlefield"; + } + + DeathOrGloryEffect(final DeathOrGloryEffect effect) { + super(effect); + } + + @Override + public DeathOrGloryEffect copy() { + return new DeathOrGloryEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Cards cards = new CardsImpl(); + cards.addAll(controller.getGraveyard().getCards(new FilterCreatureCard(), game)); + if (!cards.isEmpty()) { + TargetCard targetCards = new TargetCard(0, cards.size(), Zone.EXILED, new FilterCard("cards to put in the first pile")); + List pile1 = new ArrayList<>(); + if (controller.choose(Outcome.Neutral, cards, targetCards, game)) { + List targets = targetCards.getTargets(); + for (UUID targetId : targets) { + Card card = cards.get(targetId, game); + if (card != null) { + pile1.add(card); + cards.remove(card); + } + } + } + List pile2 = new ArrayList<>(); + pile2.addAll(cards.getCards(game)); + + StringBuilder sb = new StringBuilder("First pile of ").append(controller.getLogName()).append(": "); + sb.append(pile1.stream().map(Card::getLogName).collect(Collectors.joining(", "))); + game.informPlayers(sb.toString()); + + sb = new StringBuilder("Second pile of ").append(controller.getLogName()).append(": "); + sb.append(pile2.stream().map(Card::getLogName).collect(Collectors.joining(", "))); + game.informPlayers(sb.toString()); + + Set opponents = game.getOpponents(source.getControllerId()); + if (!opponents.isEmpty()) { + Player opponent = game.getPlayer(opponents.iterator().next()); + if (opponents.size() > 1) { + Target targetOpponent = new TargetOpponent(true); + if (controller.chooseTarget(Outcome.Neutral, targetOpponent, source, game)) { + opponent = game.getPlayer(targetOpponent.getFirstTarget()); + game.informPlayers(controller.getLogName() + " chose " + opponent.getLogName() + " to choose his pile"); + } + } + if (opponent != null) { + boolean choice = opponent.choosePile(outcome, "Choose a pile to put onto the battlefield.", pile1, pile2, game); + + Zone pile1Zone = Zone.EXILED; + Zone pile2Zone = Zone.BATTLEFIELD; + if (choice) { + pile1Zone = Zone.BATTLEFIELD; + pile2Zone = Zone.EXILED; + } + Set pile1Set = new HashSet<>(); + Set pile2Set = new HashSet<>(); + pile1Set.addAll(pile1); + pile2Set.addAll(pile2); + controller.moveCards(pile1Set, pile1Zone, source, game, false, false, false, null); + controller.moveCards(pile2Set, pile2Zone, source, game, false, false, false, null); + } + } + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/d/DecoctionModule.java b/Mage.Sets/src/mage/cards/d/DecoctionModule.java index 95b4a39c128..c870592f426 100644 --- a/Mage.Sets/src/mage/cards/d/DecoctionModule.java +++ b/Mage.Sets/src/mage/cards/d/DecoctionModule.java @@ -1,9 +1,8 @@ package mage.cards.d; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.common.CreatureEntersBattlefieldTriggeredAbility; +import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; @@ -13,19 +12,26 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Zone; +import mage.filter.StaticFilters; import mage.target.common.TargetControlledCreaturePermanent; +import java.util.UUID; + /** - * * @author emerald000 */ public final class DecoctionModule extends CardImpl { public DecoctionModule(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{2}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); // Whenever a creature enters the battlefield under your control, you get {E}. - this.addAbility(new CreatureEntersBattlefieldTriggeredAbility(new GetEnergyCountersControllerEffect(1))); + this.addAbility(new EntersBattlefieldControlledTriggeredAbility( + Zone.BATTLEFIELD, + new GetEnergyCountersControllerEffect(1), + StaticFilters.FILTER_PERMANENT_CREATURE_A, + false) + ); // {4}, {T}: Return target creature you control to its owner's hand. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ReturnToHandTargetEffect(), new GenericManaCost(4)); diff --git a/Mage.Sets/src/mage/cards/d/Disappear.java b/Mage.Sets/src/mage/cards/d/Disappear.java new file mode 100644 index 00000000000..43b6fa78a8a --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/Disappear.java @@ -0,0 +1,87 @@ +package mage.cards.d; + +import java.util.UUID; +import mage.constants.SubType; +import mage.target.common.TargetCreaturePermanent; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.AttachEffect; +import mage.constants.Outcome; +import mage.target.TargetPermanent; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author jeffwadsworth + */ +public final class Disappear extends CardImpl { + + public Disappear(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}{U}"); + + this.subtype.add(SubType.AURA); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // {U}: Return enchanted creature and Disappear to their owners' hands. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new DisappearEffect(), new ManaCostsImpl("{U}"))); + + } + + public Disappear(final Disappear card) { + super(card); + } + + @Override + public Disappear copy() { + return new Disappear(this); + } +} + +class DisappearEffect extends OneShotEffect { + + public DisappearEffect() { + super(Outcome.ReturnToHand); + staticText = "Return enchanted creature and {this} to their owners' hands"; + } + + public DisappearEffect(final DisappearEffect effect) { + super(effect); + } + + @Override + public DisappearEffect copy() { + return new DisappearEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent aura = (Permanent) game.getPermanentOrLKIBattlefield(source.getSourceId()); + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null + && aura != null + && aura.getAttachedTo() != null) { + Permanent enchantedCreature = game.getPermanent(aura.getAttachedTo()); + controller.moveCards(aura, Zone.HAND, source, game); + if (enchantedCreature != null) { + controller.moveCards(enchantedCreature, Zone.HAND, source, game); + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/d/DiscordantDirge.java b/Mage.Sets/src/mage/cards/d/DiscordantDirge.java new file mode 100644 index 00000000000..cab74cb9870 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DiscordantDirge.java @@ -0,0 +1,99 @@ +package mage.cards.d; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.FilterCard; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetCard; +import mage.target.common.TargetOpponent; + +/** + * + * @author jeffwadsworth + */ +public final class DiscordantDirge extends CardImpl { + + private static final String rule = "Look at target opponent's hand and choose up to X cards from it, where X is the number of verse counters on {this}. That player discards those cards.."; + + public DiscordantDirge(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{B}{B}"); + + // At the beginning of your upkeep, you may put a verse counter on Discordant Dirge. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, + new AddCountersSourceEffect(CounterType.VERSE.createInstance(), true), TargetController.YOU, true)); + + // {B}, Sacrifice Discordant Dirge: Look at target opponent's hand and choose up to X cards from it, where X is the number of verse counters on Discordant Dirge. That player discards those cards. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, + new DiscordantDirgeEffect(), + new ManaCostsImpl("{B}")); + ability.addCost(new SacrificeSourceCost()); + ability.addTarget(new TargetOpponent()); + this.addAbility(ability); + } + + public DiscordantDirge(final DiscordantDirge card) { + super(card); + } + + @Override + public DiscordantDirge copy() { + return new DiscordantDirge(this); + } +} + +class DiscordantDirgeEffect extends OneShotEffect { + + public DiscordantDirgeEffect() { + super(Outcome.Benefit); + staticText = "Look at target opponent's hand and choose up to X cards from it, where X is the number of verse counters on {this}. That player discards those card."; + } + + public DiscordantDirgeEffect(final DiscordantDirgeEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent discordantDirge = game.getPermanentOrLKIBattlefield(source.getSourceId()); + if (discordantDirge != null) { + int verseCounters = discordantDirge.getCounters(game).getCount(CounterType.VERSE); + Player targetOpponent = game.getPlayer(source.getFirstTarget()); + Player controller = game.getPlayer(source.getControllerId()); + if (targetOpponent != null + && controller != null) { + controller.lookAtCards(targetOpponent.getName() + " hand", targetOpponent.getHand(), game); + TargetCard target = new TargetCard(0, verseCounters, Zone.HAND, new FilterCard()); + target.setNotTarget(true); + if (controller.choose(Outcome.Benefit, targetOpponent.getHand(), target, game)) { + target.getTargets().stream().map((targetCardId) -> game.getCard(targetCardId)).filter((card) -> (card != null + && targetOpponent.getHand().contains(card.getId()))).forEachOrdered((card) -> { + targetOpponent.discard(card, source, game); + }); + return true; + } + } + } + return false; + } + + @Override + public DiscordantDirgeEffect copy() { + return new DiscordantDirgeEffect(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DominariasJudgment.java b/Mage.Sets/src/mage/cards/d/DominariasJudgment.java new file mode 100644 index 00000000000..9da85644107 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DominariasJudgment.java @@ -0,0 +1,63 @@ + +package mage.cards.d; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.keyword.ProtectionAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.StaticFilters; +import mage.filter.common.FilterLandPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; + +/** + * + * @author L_J + */ +public final class DominariasJudgment extends CardImpl { + + private static final FilterLandPermanent filterPlains = new FilterLandPermanent("Plains"); + private static final FilterLandPermanent filterIsland = new FilterLandPermanent("Island"); + private static final FilterLandPermanent filterSwamp = new FilterLandPermanent("Swamp"); + private static final FilterLandPermanent filterMountain = new FilterLandPermanent("Mountain"); + private static final FilterLandPermanent filterForest = new FilterLandPermanent("Forest"); + + static { + filterPlains.add(new SubtypePredicate(SubType.PLAINS)); + filterIsland.add(new SubtypePredicate(SubType.ISLAND)); + filterSwamp.add(new SubtypePredicate(SubType.SWAMP)); + filterMountain.add(new SubtypePredicate(SubType.MOUNTAIN)); + filterForest.add(new SubtypePredicate(SubType.FOREST)); + } + + public DominariasJudgment(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{W}"); + + // Until end of turn, creatures you control gain protection from white if you control a Plains, from blue if you control an Island, from black if you control a Swamp, from red if you control a Mountain, and from green if you control a Forest. + this.getSpellAbility().addEffect(new ConditionalContinuousEffect(new GainAbilityControlledEffect(ProtectionAbility.from(ObjectColor.WHITE), Duration.EndOfTurn, + StaticFilters.FILTER_PERMANENT_CREATURE, false), new PermanentsOnTheBattlefieldCondition(filterPlains),"Until end of turn, creatures you control gain protection from white if you control a Plains,")); + this.getSpellAbility().addEffect(new ConditionalContinuousEffect(new GainAbilityControlledEffect(ProtectionAbility.from(ObjectColor.BLUE), Duration.EndOfTurn, + StaticFilters.FILTER_PERMANENT_CREATURE, false), new PermanentsOnTheBattlefieldCondition(filterIsland)," from blue if you control an Island,")); + this.getSpellAbility().addEffect(new ConditionalContinuousEffect(new GainAbilityControlledEffect(ProtectionAbility.from(ObjectColor.BLACK), Duration.EndOfTurn, + StaticFilters.FILTER_PERMANENT_CREATURE, false), new PermanentsOnTheBattlefieldCondition(filterSwamp)," from black if you control a Swamp,")); + this.getSpellAbility().addEffect(new ConditionalContinuousEffect(new GainAbilityControlledEffect(ProtectionAbility.from(ObjectColor.RED), Duration.EndOfTurn, + StaticFilters.FILTER_PERMANENT_CREATURE, false), new PermanentsOnTheBattlefieldCondition(filterMountain)," from red if you control a Mountain,")); + this.getSpellAbility().addEffect(new ConditionalContinuousEffect(new GainAbilityControlledEffect(ProtectionAbility.from(ObjectColor.GREEN), Duration.EndOfTurn, + StaticFilters.FILTER_PERMANENT_CREATURE, false), new PermanentsOnTheBattlefieldCondition(filterForest)," and from green if you control a Forest")); + } + + public DominariasJudgment(final DominariasJudgment card) { + super(card); + } + + @Override + public DominariasJudgment copy() { + return new DominariasJudgment(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DrakeUmbra.java b/Mage.Sets/src/mage/cards/d/DrakeUmbra.java index 299d7b07373..8a124d093f0 100644 --- a/Mage.Sets/src/mage/cards/d/DrakeUmbra.java +++ b/Mage.Sets/src/mage/cards/d/DrakeUmbra.java @@ -2,6 +2,7 @@ package mage.cards.d; import java.util.UUID; + import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.AttachEffect; @@ -17,13 +18,12 @@ import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** - * * @author Loki */ public final class DrakeUmbra extends CardImpl { public DrakeUmbra(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{4}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{U}"); this.subtype.add(SubType.AURA); @@ -33,9 +33,12 @@ public final class DrakeUmbra extends CardImpl { this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); Ability ability = new EnchantAbility(auraTarget.getTargetName()); this.addAbility(ability); + // Enchanted creature gets +3/+3 and has flying. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(3, 3, Duration.WhileOnBattlefield))); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(FlyingAbility.getInstance(), AttachmentType.AURA))); + + // Totem armor this.addAbility(new TotemArmorAbility()); } diff --git a/Mage.Sets/src/mage/cards/d/Duplicity.java b/Mage.Sets/src/mage/cards/d/Duplicity.java new file mode 100644 index 00000000000..ec2655933c0 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/Duplicity.java @@ -0,0 +1,200 @@ +package mage.cards.d; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.BeginningOfYourEndStepTriggeredAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.discard.DiscardControllerEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.players.Player; +import mage.util.CardUtil; + +/** + * + * @author jeffwadsworth + */ +public final class Duplicity extends CardImpl { + + public Duplicity(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{U}"); + + // When Duplicity enters the battlefield, exile the top five cards of your library face down. + this.addAbility(new EntersBattlefieldTriggeredAbility(new DuplicityEffect(), false)); + + // At the beginning of your upkeep, you may exile all cards from your hand face down. If you do, put all other cards you own exiled with Duplicity into your hand. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new DuplicityExileHandEffect(), TargetController.YOU, true)); + + // At the beginning of your end step, discard a card. + this.addAbility(new BeginningOfYourEndStepTriggeredAbility(new DiscardControllerEffect(1), false)); + + // When you lose control of Duplicity, put all cards exiled with Duplicity into their owner's graveyard. + this.addAbility(new LoseControlDuplicity()); + + } + + public Duplicity(final Duplicity card) { + super(card); + } + + @Override + public Duplicity copy() { + return new Duplicity(this); + } +} + +class DuplicityEffect extends OneShotEffect { + + public DuplicityEffect() { + super(Outcome.Exile); + staticText = "exile the top five cards of your library face down"; + } + + public DuplicityEffect(final DuplicityEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = game.getObject(source.getSourceId()); + if (controller != null + && sourceObject != null) { + if (controller.getLibrary().hasCards()) { + UUID exileId = CardUtil.getCardExileZoneId(game, source); + Set cardsToExile = controller.getLibrary().getTopCards(game, 5); + for (Card card : cardsToExile) { + controller.moveCardsToExile(card, source, game, true, exileId, sourceObject.getName()); + card.setFaceDown(true, game); + } + } + return true; + } + return false; + } + + @Override + public DuplicityEffect copy() { + return new DuplicityEffect(this); + } +} + +class DuplicityExileHandEffect extends OneShotEffect { + + public DuplicityExileHandEffect() { + super(Outcome.Exile); + staticText = "you may exile all cards from your hand face down. If you do, put all other cards you own exiled with {this} into your hand"; + } + + public DuplicityExileHandEffect(final DuplicityExileHandEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = game.getObject(source.getSourceId()); + if (controller != null + && sourceObject != null) { + if (!controller.getHand().isEmpty()) { + UUID exileId = CardUtil.getCardExileZoneId(game, source); + Set cardsFromHandToExile = controller.getHand().getCards(game); + for (Card card : cardsFromHandToExile) { + controller.moveCardsToExile(card, source, game, true, exileId, sourceObject.getName()); + card.setFaceDown(true, game); + } + Set cardsInExile = game.getExile().getExileZone(exileId).getCards(game); + Set cardsToReturnToHandFromExile = new HashSet<>(); + for (Card card : cardsInExile) { + if (!cardsFromHandToExile.contains(card)) { + cardsToReturnToHandFromExile.add(card); + } + } + controller.moveCards(cardsToReturnToHandFromExile, Zone.HAND, source, game); + } + return true; + } + return false; + } + + @Override + public DuplicityExileHandEffect copy() { + return new DuplicityExileHandEffect(this); + } +} + +class LoseControlDuplicity extends DelayedTriggeredAbility { + + public LoseControlDuplicity() { + super(new PutExiledCardsInOwnersGraveyard(), Duration.EndOfGame, false); + } + + public LoseControlDuplicity(final LoseControlDuplicity ability) { + super(ability); + } + + @Override + public LoseControlDuplicity copy() { + return new LoseControlDuplicity(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.LOST_CONTROL; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return event.getPlayerId().equals(controllerId); + } + + @Override + public String getRule() { + return "When you lose control of {this}, put all cards exiled with {this} into their owner's graveyard."; + } +} + +class PutExiledCardsInOwnersGraveyard extends OneShotEffect { + + public PutExiledCardsInOwnersGraveyard() { + super(Outcome.Neutral); + staticText = " put all cards exiled with {this} into their owner's graveyard."; + } + + public PutExiledCardsInOwnersGraveyard(final PutExiledCardsInOwnersGraveyard effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = game.getObject(source.getSourceId()); + if (controller != null + && sourceObject != null) { + UUID exileId = CardUtil.getCardExileZoneId(game, source); + Set cardsInExile = game.getExile().getExileZone(exileId).getCards(game); + controller.moveCardsToGraveyardWithInfo(cardsInExile, source, game, Zone.EXILED); + return true; + } + return false; + } + + @Override + public PutExiledCardsInOwnersGraveyard copy() { + return new PutExiledCardsInOwnersGraveyard(this); + } +} diff --git a/Mage.Sets/src/mage/cards/e/EarthSurge.java b/Mage.Sets/src/mage/cards/e/EarthSurge.java index 4f82004c4c9..6992e2695a5 100644 --- a/Mage.Sets/src/mage/cards/e/EarthSurge.java +++ b/Mage.Sets/src/mage/cards/e/EarthSurge.java @@ -4,7 +4,7 @@ package mage.cards.e; import java.util.UUID; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.Effect; -import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.effects.common.continuous.BoostAllEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; @@ -29,7 +29,7 @@ public final class EarthSurge extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{G}"); //Each land gets +2/+2 as long as it's a creature. - Effect effect = new BoostControlledEffect(2, 2, Duration.WhileOnBattlefield, filter, true); + Effect effect = new BoostAllEffect(2, 2, Duration.WhileOnBattlefield, filter, true); effect.setText("Each land gets +2/+2 as long as it\'s a creature"); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); } diff --git a/Mage.Sets/src/mage/cards/e/EelUmbra.java b/Mage.Sets/src/mage/cards/e/EelUmbra.java index d0d69cce3d4..7438c420299 100644 --- a/Mage.Sets/src/mage/cards/e/EelUmbra.java +++ b/Mage.Sets/src/mage/cards/e/EelUmbra.java @@ -2,6 +2,7 @@ package mage.cards.e; import java.util.UUID; + import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.AttachEffect; @@ -20,25 +21,28 @@ import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** - * * @author Loki */ public final class EelUmbra extends CardImpl { public EelUmbra(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}"); this.subtype.add(SubType.AURA); - + // Flash this.addAbility(FlashAbility.getInstance()); + // Enchant creature TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); Ability ability = new EnchantAbility(auraTarget.getTargetName()); this.addAbility(ability); + // Enchanted creature gets +1/+1. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(1, 1, Duration.WhileOnBattlefield))); + + // Totem armor this.addAbility(new TotemArmorAbility()); } diff --git a/Mage.Sets/src/mage/cards/e/ElandUmbra.java b/Mage.Sets/src/mage/cards/e/ElandUmbra.java index 86a2c8be49d..1cbee9cbfa3 100644 --- a/Mage.Sets/src/mage/cards/e/ElandUmbra.java +++ b/Mage.Sets/src/mage/cards/e/ElandUmbra.java @@ -2,6 +2,7 @@ package mage.cards.e; import java.util.UUID; + import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.AttachEffect; @@ -19,24 +20,25 @@ import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** - * * @author Loki */ public final class ElandUmbra extends CardImpl { public ElandUmbra(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}"); this.subtype.add(SubType.AURA); - // Enchant creature TargetPermanent auraTarget = new TargetCreaturePermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); Ability ability = new EnchantAbility(auraTarget.getTargetName()); this.addAbility(ability); + // Enchanted creature gets +0/+4. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(0, 4, Duration.WhileOnBattlefield))); + + // Totem armor this.addAbility(new TotemArmorAbility()); } diff --git a/Mage.Sets/src/mage/cards/e/ElderSpawn.java b/Mage.Sets/src/mage/cards/e/ElderSpawn.java new file mode 100644 index 00000000000..1d65526cdcb --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/ElderSpawn.java @@ -0,0 +1,102 @@ + +package mage.cards.e; + +import java.util.UUID; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SimpleEvasionAbility; +import mage.abilities.costs.common.SacrificeTargetCost; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.combat.CantBeBlockedByCreaturesSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author L_J + */ +public final class ElderSpawn extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("red creatures"); + + static { + filter.add(new ColorPredicate(ObjectColor.RED)); + } + + public ElderSpawn(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}{U}{U}"); + this.subtype.add(SubType.SPAWN); + this.power = new MageInt(6); + this.toughness = new MageInt(6); + + // At the beginning of your upkeep, unless you sacrifice an Island, sacrifice Elder Spawn and it deals 6 damage to you. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new ElderSpawnEffect(), TargetController.YOU, false)); + + // Elder Spawn can't be blocked by red creatures. + this.addAbility(new SimpleEvasionAbility(new CantBeBlockedByCreaturesSourceEffect(filter, Duration.WhileOnBattlefield))); + } + + public ElderSpawn(final ElderSpawn card) { + super(card); + } + + @Override + public ElderSpawn copy() { + return new ElderSpawn(this); + } +} + +class ElderSpawnEffect extends OneShotEffect { + + private static final FilterControlledPermanent filter = new FilterControlledPermanent("an Island"); + static { + filter.add(new SubtypePredicate(SubType.ISLAND)); + } + + public ElderSpawnEffect() { + super(Outcome.Sacrifice); + staticText = "unless you sacrifice an Island, sacrifice {this} and it deals 6 damage to you"; + } + + public ElderSpawnEffect(final ElderSpawnEffect effect) { + super(effect); + } + + @Override + public ElderSpawnEffect copy() { + return new ElderSpawnEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); + if (controller != null && sourcePermanent != null) { + TargetControlledPermanent target = new TargetControlledPermanent(1, 1, filter, true); + SacrificeTargetCost cost = new SacrificeTargetCost(target); + if (!controller.chooseUse(Outcome.AIDontUseIt, "Do you wish to sacrifice an Island?", source, game) + || !cost.canPay(source, source.getSourceId(), source.getControllerId(), game) + || !cost.pay(source, game, source.getSourceId(), source.getControllerId(), true)) { + sourcePermanent.sacrifice(source.getSourceId(), game); + controller.damage(6, sourcePermanent.getId(), game, false, true); + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/e/EmissaryOfGrudges.java b/Mage.Sets/src/mage/cards/e/EmissaryOfGrudges.java index 9bd4c2fa1f3..0f1f1141c2e 100644 --- a/Mage.Sets/src/mage/cards/e/EmissaryOfGrudges.java +++ b/Mage.Sets/src/mage/cards/e/EmissaryOfGrudges.java @@ -94,11 +94,11 @@ class EmissaryOfGrudgesEffect extends OneShotEffect { Mode mode = stackObject.getStackAbility().getModes().get(modeId); for (Target target : mode.getTargets()) { for (UUID targetId : target.getTargets()) { - if (source.getControllerId().equals(targetId)) { + if (source.isControlledBy(targetId)) { targetsYouOrAPermanentYouControl = true; } Permanent permanent = game.getPermanent(targetId); - if (permanent != null && source.getControllerId().equals(permanent.getControllerId())) { + if (permanent != null && source.isControlledBy(permanent.getControllerId())) { targetsYouOrAPermanentYouControl = true; } } diff --git a/Mage.Sets/src/mage/cards/e/EmptyCityRuse.java b/Mage.Sets/src/mage/cards/e/EmptyCityRuse.java index 020899fc0ea..8e1ff3e4178 100644 --- a/Mage.Sets/src/mage/cards/e/EmptyCityRuse.java +++ b/Mage.Sets/src/mage/cards/e/EmptyCityRuse.java @@ -1,11 +1,11 @@ - package mage.cards.e; import java.util.UUID; -import mage.abilities.effects.common.SkipNextCombatEffect; +import mage.abilities.effects.common.SkipCombatStepEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.Duration; import mage.target.common.TargetOpponent; /** @@ -15,10 +15,10 @@ import mage.target.common.TargetOpponent; public final class EmptyCityRuse extends CardImpl { public EmptyCityRuse(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{W}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{W}"); // Target opponent skips all combat phases of their next turn. - this.getSpellAbility().addEffect(new SkipNextCombatEffect()); + this.getSpellAbility().addEffect(new SkipCombatStepEffect(Duration.UntilYourNextTurn).setText("Target opponent skips all combat phases of their next turn.")); this.getSpellAbility().addTarget(new TargetOpponent()); } @@ -30,4 +30,4 @@ public final class EmptyCityRuse extends CardImpl { public EmptyCityRuse copy() { return new EmptyCityRuse(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/e/EnchantedBeing.java b/Mage.Sets/src/mage/cards/e/EnchantedBeing.java new file mode 100644 index 00000000000..0843ff51f8a --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EnchantedBeing.java @@ -0,0 +1,79 @@ + +package mage.cards.e; + +import java.util.UUID; +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.PreventAllDamageToSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; + +/** + * + * @author L_J + */ +public final class EnchantedBeing extends CardImpl { + + public EnchantedBeing(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}{W}"); + this.subtype.add(SubType.HUMAN); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Prevent all damage that would be dealt to Enchanted Being by enchanted creatures. + Effect effect = new PreventDamageToSourceByEnchantedCreatures(); + effect.setText("Prevent all damage that would be dealt to {this} by enchanted creatures."); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); + } + + public EnchantedBeing(final EnchantedBeing card) { + super(card); + } + + @Override + public EnchantedBeing copy() { + return new EnchantedBeing(this); + } +} + +class PreventDamageToSourceByEnchantedCreatures extends PreventAllDamageToSourceEffect { + + public PreventDamageToSourceByEnchantedCreatures() { + super(Duration.WhileOnBattlefield); + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (super.applies(event, source, game)) { + if (isEnchantedCreature(game.getObject(event.getSourceId()), game)) { + if (event.getTargetId().equals(source.getSourceId())) { + return true; + } + } + } + return false; + } + + public boolean isEnchantedCreature(MageObject input, Game game) { + if (input == null || input.isCreature()) { + return false; + } + for (UUID attachmentId : ((Permanent) input).getAttachments()) { + Permanent attachment = game.getPermanent(attachmentId); + if (attachment != null && attachment.isEnchantment()) { + return true; + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/e/EnchantmentAlteration.java b/Mage.Sets/src/mage/cards/e/EnchantmentAlteration.java new file mode 100644 index 00000000000..c0594751a62 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EnchantmentAlteration.java @@ -0,0 +1,145 @@ +package mage.cards.e; + +import java.util.UUID; +import mage.MageItem; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.AttachmentAttachedToCardTypePredicate; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.stack.StackObject; +import mage.players.Player; +import mage.target.Target; +import mage.target.TargetPermanent; + +/** + * + * @author jeffwadsworth + */ +public final class EnchantmentAlteration extends CardImpl { + + private static final FilterPermanent filter = new FilterPermanent("aura attached to a creature or land"); + private static final FilterPermanent filter2 = new FilterPermanent("another target permanent that shares that type of creature or land"); + + static { + filter.add(new SubtypePredicate(SubType.AURA)); + filter.add(Predicates.or(new AttachmentAttachedToCardTypePredicate(CardType.CREATURE), + new AttachmentAttachedToCardTypePredicate(CardType.LAND))); + filter2.add(new SharesEnchantedCardTypePredicate()); + // another target permanent is handled in this predicate + } + + public EnchantmentAlteration(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}"); + + // Attach target Aura attached to a creature or land to another permanent of that type. + this.getSpellAbility().addEffect(new EnchantmentAlterationEffect()); + TargetPermanent targetAura = new TargetPermanent(filter); + this.getSpellAbility().addTarget(targetAura); + + TargetPermanent targetCreatureOrLandThatSharesTheEnchantedCardType = new TargetPermanent(filter2); + this.getSpellAbility().addTarget(targetCreatureOrLandThatSharesTheEnchantedCardType); + + } + + public EnchantmentAlteration(final EnchantmentAlteration card) { + super(card); + } + + @Override + public EnchantmentAlteration copy() { + return new EnchantmentAlteration(this); + } + +} + +class SharesEnchantedCardTypePredicate implements ObjectSourcePlayerPredicate> { + + @Override + public boolean apply(ObjectSourcePlayer input, Game game) { + StackObject source = game.getStack().getStackObject(input.getSourceId()); + Permanent auraIsAttachedToThisPermanent = null; + Permanent newPermanentToAttachAuraTo; + if (source != null) { + if (source.getStackAbility().getTargets().isEmpty() + || source.getStackAbility().getTargets().get(0).getTargets().isEmpty()) { + return true; + } + Permanent auraPermanent = game.getPermanent( + source.getStackAbility().getTargets().get(0).getTargets().get(0)); // targeted aura enchanting land or creature + if (auraPermanent != null) { + auraIsAttachedToThisPermanent = game.getPermanent(auraPermanent.getAttachedTo()); + } + if (auraIsAttachedToThisPermanent == null) { // the original permanent the aura is attached to + return false; + } + newPermanentToAttachAuraTo = game.getPermanent(input.getObject().getId()); // the new target creature or land to enchant + if (newPermanentToAttachAuraTo == auraIsAttachedToThisPermanent) { + return false; // must be another permanent + } + if (auraIsAttachedToThisPermanent.isCreature() + && newPermanentToAttachAuraTo.isCreature()) { + return true; + } + if (auraIsAttachedToThisPermanent.isLand() + && newPermanentToAttachAuraTo.isLand()) { + return true; + } + return false; + } + return true; + } + +} + +class EnchantmentAlterationEffect extends OneShotEffect { + + public EnchantmentAlterationEffect() { + super(Outcome.BoostCreature); + this.staticText = "Attach target Aura attached to a creature or land to another permanent of that type"; + } + + public EnchantmentAlterationEffect(final EnchantmentAlterationEffect effect) { + super(effect); + } + + @Override + public EnchantmentAlterationEffect copy() { + return new EnchantmentAlterationEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Permanent aura = game.getPermanent(source.getFirstTarget()); + Permanent permanentToBeAttachedTo = game.getPermanent(source.getTargets().get(1).getFirstTarget()); + if (aura != null + && permanentToBeAttachedTo != null) { + Permanent oldPermanent = game.getPermanent(aura.getAttachedTo()); + if (oldPermanent != null + && !oldPermanent.equals(permanentToBeAttachedTo)) { + Target auraTarget = aura.getSpellAbility().getTargets().get(0); + if (!auraTarget.canTarget(permanentToBeAttachedTo.getId(), game)) { + game.informPlayers(aura.getLogName() + " was not attched to " + permanentToBeAttachedTo.getLogName() + " because it's no legal target for the aura"); + } else if (oldPermanent.removeAttachment(aura.getId(), game)) { + game.informPlayers(aura.getLogName() + " was unattached from " + oldPermanent.getLogName() + " and attached to " + permanentToBeAttachedTo.getLogName()); + permanentToBeAttachedTo.addAttachment(aura.getId(), game); + } + } + } + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/e/EtrataTheSilencer.java b/Mage.Sets/src/mage/cards/e/EtrataTheSilencer.java index 9ced4088310..fbbef138a62 100644 --- a/Mage.Sets/src/mage/cards/e/EtrataTheSilencer.java +++ b/Mage.Sets/src/mage/cards/e/EtrataTheSilencer.java @@ -144,14 +144,18 @@ class EtrataTheSilencerEffect extends OneShotEffect { card.addCounters(CounterType.HIT.createInstance(), source, game); } int cardsFound = 0; - for (Card exiledCard : game.getExile().getAllCards(game)) { - if (exiledCard.getCounters(game).getCount(CounterType.HIT) >= 1 && exiledCard.getOwnerId().equals(player.getId())) { - cardsFound++; - } - } + cardsFound = game.getExile().getAllCards(game).stream().filter((exiledCard) -> (exiledCard.getCounters(game).getCount(CounterType.HIT) >= 1 + && exiledCard.getOwnerId().equals(player.getId()))).map((_item) -> 1).reduce(cardsFound, Integer::sum); if (cardsFound > 2) { player.lost(game); } - return new ShuffleIntoLibrarySourceEffect().apply(game, source); + Permanent etrataTheSilencer = game.getPermanent(source.getSourceId()); + if (etrataTheSilencer != null) { + if (etrataTheSilencer.isPhasedIn()) { + return new ShuffleIntoLibrarySourceEffect().apply(game, source); + } + } + controller.shuffleLibrary(source, game); + return true; } } diff --git a/Mage.Sets/src/mage/cards/f/FalsePeace.java b/Mage.Sets/src/mage/cards/f/FalsePeace.java index 026dae7c19a..55bfe14023c 100644 --- a/Mage.Sets/src/mage/cards/f/FalsePeace.java +++ b/Mage.Sets/src/mage/cards/f/FalsePeace.java @@ -1,11 +1,11 @@ - package mage.cards.f; import java.util.UUID; -import mage.abilities.effects.common.SkipNextCombatEffect; +import mage.abilities.effects.common.SkipCombatStepEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.Duration; import mage.target.TargetPlayer; /** @@ -13,19 +13,19 @@ import mage.target.TargetPlayer; * @author escplan9 (Derek Monturo - dmontur1 at gmail dot com) */ public final class FalsePeace extends CardImpl { - + public FalsePeace(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{W}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{W}"); // Target player skips all combat phases of their next turn. - this.getSpellAbility().addEffect(new SkipNextCombatEffect()); + this.getSpellAbility().addEffect(new SkipCombatStepEffect(Duration.UntilYourNextTurn).setText("Target player skips all combat phases of their next turn.")); this.getSpellAbility().addTarget(new TargetPlayer()); } - + public FalsePeace(final FalsePeace card) { super(card); } - + @Override public FalsePeace copy() { return new FalsePeace(this); diff --git a/Mage.Sets/src/mage/cards/f/Fatigue.java b/Mage.Sets/src/mage/cards/f/Fatigue.java new file mode 100644 index 00000000000..8f3ae9784b2 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/Fatigue.java @@ -0,0 +1,36 @@ +package mage.cards.f; + +import java.util.UUID; +import mage.abilities.effects.common.SkipNextDrawStepTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.target.TargetPlayer; + +/** + * + * @author jeffwadsworth + */ +public final class Fatigue extends CardImpl { + + private static final String rule = "Target player skips his or her next draw step."; + + public Fatigue(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{U}"); + + + // Target player skips his or her next draw step. + this.getSpellAbility().addEffect(new SkipNextDrawStepTargetEffect().setText(rule)); + this.getSpellAbility().addTarget(new TargetPlayer()); + + } + + public Fatigue(final Fatigue card) { + super(card); + } + + @Override + public Fatigue copy() { + return new Fatigue(this); + } +} diff --git a/Mage.Sets/src/mage/cards/f/FendOff.java b/Mage.Sets/src/mage/cards/f/FendOff.java new file mode 100644 index 00000000000..045d166fe7d --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FendOff.java @@ -0,0 +1,41 @@ +package mage.cards.f; + +import java.util.UUID; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.PreventDamageByTargetEffect; +import mage.abilities.keyword.CyclingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author jeffwadsworth + */ +public final class FendOff extends CardImpl { + + private static final String rule = "Prevent all combat damage that would be dealt by target creature this turn."; + + public FendOff(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}"); + + // Prevent all combat damage that would be dealt by target creature this turn. + this.getSpellAbility().addEffect(new PreventDamageByTargetEffect(Duration.EndOfTurn, true).setText(rule)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + + // Cycling {2} + this.addAbility(new CyclingAbility(new ManaCostsImpl("{2}"))); + + } + + public FendOff(final FendOff card) { + super(card); + } + + @Override + public FendOff copy() { + return new FendOff(this); + } +} diff --git a/Mage.Sets/src/mage/cards/f/FeralRoar.java b/Mage.Sets/src/mage/cards/f/FeralRoar.java new file mode 100644 index 00000000000..46598d12af4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FeralRoar.java @@ -0,0 +1,33 @@ +package mage.cards.f; + +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class FeralRoar extends CardImpl { + + public FeralRoar(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{G}"); + + // Target creature gets +4/+4 until end of turn. + this.getSpellAbility().addEffect(new BoostTargetEffect(4, 4, Duration.EndOfTurn)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + } + + public FeralRoar(final FeralRoar card) { + super(card); + } + + @Override + public FeralRoar copy() { + return new FeralRoar(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/f/FightOrFlight.java b/Mage.Sets/src/mage/cards/f/FightOrFlight.java new file mode 100644 index 00000000000..69e34a94fdb --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FightOrFlight.java @@ -0,0 +1,109 @@ + +package mage.cards.f; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfCombatTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.RestrictionEffect; +import mage.abilities.effects.common.combat.CantAttackTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.filter.StaticFilters; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author LevelX2 & L_J + */ +public final class FightOrFlight extends CardImpl { + + public FightOrFlight(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{W}"); + + // At the beginning of combat on each opponent’s turn, separate all creatures that player controls into two piles. Only creatures in the pile of their choice can attack this turn. + this.addAbility(new BeginningOfCombatTriggeredAbility(new FightOrFlightEffect(), TargetController.OPPONENT, false)); + } + + public FightOrFlight(final FightOrFlight card) { + super(card); + } + + @Override + public FightOrFlight copy() { + return new FightOrFlight(this); + } +} + +class FightOrFlightEffect extends OneShotEffect { + + public FightOrFlightEffect() { + super(Outcome.Detriment); + this.staticText = "separate all creatures that player controls into two piles. Only creatures in the pile of their choice can attack this turn"; + } + + public FightOrFlightEffect(final FightOrFlightEffect effect) { + super(effect); + } + + @Override + public FightOrFlightEffect copy() { + return new FightOrFlightEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + Player targetPlayer = game.getPlayer(game.getCombat().getAttackingPlayerId()); + if (player != null && targetPlayer != null) { + int count = game.getBattlefield().countAll(StaticFilters.FILTER_PERMANENT_CREATURES, targetPlayer.getId(), game); + TargetCreaturePermanent creatures = new TargetCreaturePermanent(0, count, new FilterCreaturePermanent("creatures to put in the first pile"), true); + List pile1 = new ArrayList<>(); + creatures.setRequired(false); + if (player.choose(Outcome.Neutral, creatures, source.getSourceId(), game)) { + List targets = creatures.getTargets(); + for (UUID targetId : targets) { + Permanent p = game.getPermanent(targetId); + if (p != null) { + pile1.add(p); + } + } + } + List pile2 = new ArrayList<>(); + for (Permanent p : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, targetPlayer.getId(), game)) { + if (!pile1.contains(p)) { + pile2.add(p); + } + } + + boolean choice = targetPlayer.choosePile(outcome, "Choose which pile can attack this turn.", pile1, pile2, game); + List chosenPile = choice ? pile2 : pile1; + List otherPile = choice ? pile1 : pile2; + for (Permanent permanent : chosenPile) { + if (permanent != null) { + RestrictionEffect effect = new CantAttackTargetEffect(Duration.EndOfTurn); + effect.setText(""); + effect.setTargetPointer(new FixedTarget(permanent.getId())); + game.addEffect(effect, source); + } + } + StringBuilder sb = new StringBuilder("Creatures that can attack this turn: "); + sb.append(otherPile.stream().map(Permanent::getLogName).collect(Collectors.joining(", "))); + game.informPlayers(sb.toString()); + return true; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/f/Flickerform.java b/Mage.Sets/src/mage/cards/f/Flickerform.java index 550ae27ce61..0f0ef9da3e1 100644 --- a/Mage.Sets/src/mage/cards/f/Flickerform.java +++ b/Mage.Sets/src/mage/cards/f/Flickerform.java @@ -156,39 +156,44 @@ class FlickerformReturnEffect extends OneShotEffect { } ExileZone exileZone = game.getExile().getExileZone(exileZoneId); Card enchantedCard = exileZone.get(enchantedCardId, game); + //skip if exiled card is missing if (enchantedCard != null) { - controller.moveCards(enchantedCard, Zone.BATTLEFIELD, source, game); - Permanent newPermanent = game.getPermanent(enchantedCardId); - if (newPermanent != null) { - Set toBattlefieldAttached = new HashSet(); - for (Card enchantment : exileZone.getCards(game)) { - if (filterAura.match(enchantment, game)) { - boolean canTarget = false; - for (Target target : enchantment.getSpellAbility().getTargets()) { - Filter filter = target.getFilter(); - if (filter.match(newPermanent, game)) { - canTarget = true; - break; + Player owner = game.getPlayer(enchantedCard.getOwnerId()); + //skip if card's owner is missing + if (owner != null) { + owner.moveCards(enchantedCard, Zone.BATTLEFIELD, source, game); + Permanent newPermanent = game.getPermanent(enchantedCardId); + if (newPermanent != null) { + Set toBattlefieldAttached = new HashSet(); + for (Card enchantment : exileZone.getCards(game)) { + if (filterAura.match(enchantment, game)) { + boolean canTarget = false; + for (Target target : enchantment.getSpellAbility().getTargets()) { + Filter filter = target.getFilter(); + if (filter.match(newPermanent, game)) { + canTarget = true; + break; + } + } + if (!canTarget) { + // Aura stays exiled + continue; + } + game.getState().setValue("attachTo:" + enchantment.getId(), newPermanent); + } + toBattlefieldAttached.add(enchantment); + } + if (!toBattlefieldAttached.isEmpty()) { + controller.moveCards(toBattlefieldAttached, Zone.BATTLEFIELD, source, game); + for (Card card : toBattlefieldAttached) { + if (game.getState().getZone(card.getId()) == Zone.BATTLEFIELD) { + newPermanent.addAttachment(card.getId(), game); } } - if (!canTarget) { - // Aura stays exiled - continue; - } - game.getState().setValue("attachTo:" + enchantment.getId(), newPermanent); - } - toBattlefieldAttached.add(enchantment); - } - if (!toBattlefieldAttached.isEmpty()) { - controller.moveCards(toBattlefieldAttached, Zone.BATTLEFIELD, source, game); - for (Card card : toBattlefieldAttached) { - if (game.getState().getZone(card.getId()) == Zone.BATTLEFIELD) { - newPermanent.addAttachment(card.getId(), game); - } } } + return true; } - return true; } return false; } diff --git a/Mage.Sets/src/mage/cards/f/ForerunnerOfTheEmpire.java b/Mage.Sets/src/mage/cards/f/ForerunnerOfTheEmpire.java index a2789bf5555..a33e5bfc1bb 100644 --- a/Mage.Sets/src/mage/cards/f/ForerunnerOfTheEmpire.java +++ b/Mage.Sets/src/mage/cards/f/ForerunnerOfTheEmpire.java @@ -1,23 +1,26 @@ package mage.cards.f; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.CreatureEntersBattlefieldTriggeredAbility; +import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.effects.common.DamageAllEffect; import mage.abilities.effects.common.search.SearchLibraryPutOnLibraryEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.TargetController; +import mage.constants.Zone; import mage.filter.common.FilterBySubtypeCard; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerPredicate; import mage.target.common.TargetCardInLibrary; +import java.util.UUID; + /** - * * @author JayDi85 */ public final class ForerunnerOfTheEmpire extends CardImpl { @@ -49,12 +52,11 @@ public final class ForerunnerOfTheEmpire extends CardImpl { ); // Whenever a Dinosaur enters the battlefield under your control, you may have Forerunner of the Empire deal 1 damage to each creature. - Ability ability = new CreatureEntersBattlefieldTriggeredAbility( + Ability ability = new EntersBattlefieldControlledTriggeredAbility( Zone.BATTLEFIELD, new DamageAllEffect(1, new FilterCreaturePermanent()).setText("have {this} deal 1 damage to each creature"), filterAnyDinosaur, - true, - false); + true); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/f/ForethoughtAmulet.java b/Mage.Sets/src/mage/cards/f/ForethoughtAmulet.java new file mode 100644 index 00000000000..f6eff9d8ff1 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/ForethoughtAmulet.java @@ -0,0 +1,91 @@ + +package mage.cards.f; + +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.SacrificeSourceUnlessPaysEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent; + +/** + * + * @author L_J + */ +public final class ForethoughtAmulet extends CardImpl { + + public ForethoughtAmulet(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{5}"); + + // At the beginning of your upkeep, sacrifice Forethought Amulet unless you pay {3}. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new SacrificeSourceUnlessPaysEffect(new GenericManaCost(3)), TargetController.YOU, false)); + + // If an instant or sorcery source would deal 3 or more damage to you, it deals 2 damage to you instead. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ForethoughtAmuletEffect())); + } + + public ForethoughtAmulet(final ForethoughtAmulet card) { + super(card); + } + + @Override + public ForethoughtAmulet copy() { + return new ForethoughtAmulet(this); + } +} + +class ForethoughtAmuletEffect extends ReplacementEffectImpl { + + public ForethoughtAmuletEffect() { + super(Duration.WhileOnBattlefield, Outcome.Neutral); + staticText = "If an instant or sorcery source would deal 3 or more damage to you, it deals 2 damage to you instead"; + } + + public ForethoughtAmuletEffect(final ForethoughtAmuletEffect effect) { + super(effect); + } + + @Override + public ForethoughtAmuletEffect copy() { + return new ForethoughtAmuletEffect(this); + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGE_PLAYER; + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (event.getAmount() >= 3) { + MageObject object = game.getObject(event.getSourceId()); + return object != null && (object.isInstant() || object.isSorcery()); + } + return false; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + if (event.getTargetId().equals(source.getControllerId())) { + event.setAmount(2); + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/g/GhostQuarter.java b/Mage.Sets/src/mage/cards/g/GhostQuarter.java index b84b4a3ba4d..66a20c6860e 100644 --- a/Mage.Sets/src/mage/cards/g/GhostQuarter.java +++ b/Mage.Sets/src/mage/cards/g/GhostQuarter.java @@ -1,4 +1,3 @@ - package mage.cards.g; import java.util.UUID; @@ -16,7 +15,6 @@ import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Zone; import mage.filter.StaticFilters; -import mage.filter.common.FilterBasicLandCard; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; @@ -30,7 +28,7 @@ import mage.target.common.TargetLandPermanent; public final class GhostQuarter extends CardImpl { public GhostQuarter(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.LAND},""); + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); // {T}: Add {C}. this.addAbility(new ColorlessManaAbility()); diff --git a/Mage.Sets/src/mage/cards/g/GiantOyster.java b/Mage.Sets/src/mage/cards/g/GiantOyster.java index 05617d00dca..53e103906b8 100644 --- a/Mage.Sets/src/mage/cards/g/GiantOyster.java +++ b/Mage.Sets/src/mage/cards/g/GiantOyster.java @@ -1,5 +1,6 @@ package mage.cards.g; +import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.DelayedTriggeredAbility; @@ -27,8 +28,6 @@ import mage.players.Player; import mage.target.common.TargetCreaturePermanent; import mage.target.targetpointer.FixedTarget; -import java.util.UUID; - /** * * @author noahg @@ -43,7 +42,7 @@ public final class GiantOyster extends CardImpl { public GiantOyster(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}{U}"); - + this.subtype.add(SubType.OYSTER); this.power = new MageInt(0); this.toughness = new MageInt(3); @@ -111,7 +110,6 @@ class GiantOysterCreateDelayedTriggerEffects extends OneShotEffect { Effect addCountersEffect = new AddCountersTargetEffect(CounterType.M1M1.createInstance(1)); addCountersEffect.setTargetPointer(getTargetPointer().getFixedTarget(game, source)); DelayedTriggeredAbility drawStepAbility = new AtTheBeginOfYourNextDrawStepDelayedTriggeredAbility(addCountersEffect, Duration.Custom, false); - drawStepAbility.setSourceObject(oyster, game); drawStepAbility.setControllerId(source.getControllerId()); UUID drawStepAbilityUUID = game.addDelayedTriggeredAbility(drawStepAbility, source); @@ -161,4 +159,4 @@ class GiantOysterLeaveUntapDelayedTriggeredAbility extends DelayedTriggeredAbili public String getRule() { return "When {this} leaves the battlefield or becomes untapped, remove all -1/-1 counters from the creature."; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/g/GoblinBruiser.java b/Mage.Sets/src/mage/cards/g/GoblinBruiser.java new file mode 100644 index 00000000000..ab4b7acfe0c --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GoblinBruiser.java @@ -0,0 +1,33 @@ +package mage.cards.g; + +import mage.MageInt; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class GoblinBruiser extends CardImpl { + + public GoblinBruiser(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}{R}"); + this.subtype.add(SubType.GOBLIN); + this.subtype.add(SubType.WARRIOR); + + this.power = new MageInt(3); + this.toughness = new MageInt(3); + } + + public GoblinBruiser(final GoblinBruiser card) { + super(card); + } + + @Override + public GoblinBruiser copy() { + return new GoblinBruiser(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GoblinGangLeader.java b/Mage.Sets/src/mage/cards/g/GoblinGangLeader.java new file mode 100644 index 00000000000..db0e80fc8bd --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GoblinGangLeader.java @@ -0,0 +1,39 @@ +package mage.cards.g; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.game.permanent.token.GoblinToken; + +import java.util.UUID; + +/** + * + * @author JayDi85 + */ +public final class GoblinGangLeader extends CardImpl { + + public GoblinGangLeader(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{R}{R}"); + this.subtype.add(SubType.GOBLIN, SubType.WARRIOR); + + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // When Goblin Gang Leader enters the battlefield, create two 1/1 red Goblin creature tokens. + this.addAbility(new EntersBattlefieldTriggeredAbility(new CreateTokenEffect(new GoblinToken("ANA"), 2))); + } + + public GoblinGangLeader(final GoblinGangLeader card) { + super(card); + } + + @Override + public GoblinGangLeader copy() { + return new GoblinGangLeader(this); + } +} diff --git a/Mage.Sets/src/mage/cards/g/GoblinGoliath.java b/Mage.Sets/src/mage/cards/g/GoblinGoliath.java new file mode 100644 index 00000000000..b8ac5dc92cf --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GoblinGoliath.java @@ -0,0 +1,105 @@ +package mage.cards.g; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.common.OpponentsCount; +import mage.abilities.effects.Effect; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.token.GoblinToken; +import mage.util.CardUtil; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class GoblinGoliath extends CardImpl { + + public GoblinGoliath(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}{R}"); + this.subtype.add(SubType.GOBLIN); + this.subtype.add(SubType.MUTANT); + + this.power = new MageInt(5); + this.toughness = new MageInt(4); + + // When Goblin Goliath enters the battlefield, create a number of 1/1 red Goblin creature tokens equal to the number of opponents you have. + Effect effect = new CreateTokenEffect(new GoblinToken(), new OpponentsCount()); + effect.setText("create a number of 1/1 red Goblin creature tokens equal to the number of opponents you have"); + this.addAbility(new EntersBattlefieldTriggeredAbility(effect)); + + // {3}{R}, {T}: If a source you control would deal damage to an opponent this turn, it deals double that damage to that player instead. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GoblinGoliathDamageEffect(), new ManaCostsImpl("{3}{R}")); + ability.addCost(new TapSourceCost()); + this.addAbility(ability); + } + + public GoblinGoliath(final GoblinGoliath card) { + super(card); + } + + @Override + public GoblinGoliath copy() { + return new GoblinGoliath(this); + } +} + +class GoblinGoliathDamageEffect extends ReplacementEffectImpl { + + public GoblinGoliathDamageEffect() { + super(Duration.EndOfTurn, Outcome.Damage); + staticText = "If a source you control would deal damage to an opponent this turn, it deals double that damage to that player instead."; + } + + public GoblinGoliathDamageEffect(final GoblinGoliathDamageEffect effect) { + super(effect); + } + + @Override + public GoblinGoliathDamageEffect copy() { + return new GoblinGoliathDamageEffect(this); + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGE_PLAYER; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + UUID sourceControllerID = source.getControllerId(); + UUID damageControllerID = game.getControllerId(event.getSourceId()); + UUID damageTargetID = event.getTargetId(); + if (sourceControllerID != null && damageControllerID != null && damageTargetID != null) { + // our damage + if (damageControllerID.equals(sourceControllerID)) { + // to opponent only + if (game.getOpponents(sourceControllerID).contains(damageTargetID)) { + return true; + } + } + } + return false; + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + event.setAmount(CardUtil.addWithOverflowCheck(event.getAmount(), event.getAmount())); + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/g/GoblinMachinist.java b/Mage.Sets/src/mage/cards/g/GoblinMachinist.java index 2e217d109bf..8ff675b00e9 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinMachinist.java +++ b/Mage.Sets/src/mage/cards/g/GoblinMachinist.java @@ -77,9 +77,9 @@ class GoblinMachinistEffect extends OneShotEffect { break; } } - controller.revealCards(source, cards, game); - controller.putCardsOnBottomOfLibrary(cards, game, source, true); } + controller.revealCards(source, cards, game); + controller.putCardsOnBottomOfLibrary(cards, game, source, true); return true; } return false; diff --git a/Mage.Sets/src/mage/cards/g/GripOfChaos.java b/Mage.Sets/src/mage/cards/g/GripOfChaos.java index 3cbd36bc980..479a74548de 100644 --- a/Mage.Sets/src/mage/cards/g/GripOfChaos.java +++ b/Mage.Sets/src/mage/cards/g/GripOfChaos.java @@ -126,7 +126,10 @@ class GripOfChaosEffect extends OneShotEffect { Mode mode = stackObject.getStackAbility().getModes().get(modeId); for (Target target : mode.getTargets()) { UUID oldTargetId = target.getFirstTarget(); - Set possibleTargets = target.possibleTargets(stackObject.getSourceId(), stackObject.getControllerId(), game); + Set possibleTargets = target.possibleTargets(stackObject.getId(), stackObject.getControllerId(), game); + if (possibleTargets.contains(stackObject.getId())) { // The stackObject can't target itself + possibleTargets.remove(stackObject.getId()); + } if (!possibleTargets.isEmpty()) { int i = 0; int rnd = RandomUtil.nextInt(possibleTargets.size()); diff --git a/Mage.Sets/src/mage/cards/g/GuardDogs.java b/Mage.Sets/src/mage/cards/g/GuardDogs.java new file mode 100644 index 00000000000..6101684b23b --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GuardDogs.java @@ -0,0 +1,100 @@ + +package mage.cards.g; + +import java.util.UUID; +import mage.MageInt; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.PreventionEffectImpl; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.target.common.TargetCreaturePermanent; +import mage.target.common.TargetControlledPermanent; + +/** + * + * @author L_J + */ +public final class GuardDogs extends CardImpl { + + public GuardDogs(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}"); + this.subtype.add(SubType.HOUND); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // {2}{W}, {T}: Choose a permanent you control. Prevent all combat damage target creature would deal this turn if it shares a color with that permanent. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new GuardDogsEffect(), new ManaCostsImpl("{2}{W}")); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public GuardDogs(final GuardDogs card) { + super(card); + } + + @Override + public GuardDogs copy() { + return new GuardDogs(this); + } +} + +class GuardDogsEffect extends PreventionEffectImpl { + + private TargetControlledPermanent controlledTarget; + + public GuardDogsEffect() { + super(Duration.EndOfTurn, Integer.MAX_VALUE, true); + this.staticText = "Choose a permanent you control. Prevent all combat damage target creature would deal this turn if it shares a color with that permanent"; + } + + public GuardDogsEffect(final GuardDogsEffect effect) { + super(effect); + } + + + @Override + public void init(Ability source, Game game) { + this.controlledTarget = new TargetControlledPermanent(); + this.controlledTarget.setNotTarget(true); + this.controlledTarget.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), game); + super.init(source, game); + } + + + @Override + public GuardDogsEffect copy() { + return new GuardDogsEffect(this); + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (!this.used && super.applies(event, source, game)) { + MageObject mageObject = game.getObject(event.getSourceId()); + if (mageObject != null + && controlledTarget.getFirstTarget() != null) { + Permanent permanent = game.getPermanentOrLKIBattlefield(controlledTarget.getFirstTarget()); + Permanent targetPermanent = game.getPermanentOrLKIBattlefield(this.getTargetPointer().getFirst(game, source)); + if (permanent != null + && targetPermanent != null + && this.getTargetPointer().getTargets(game, source).contains(event.getSourceId()) + && permanent.getColor(game).shares(targetPermanent.getColor(game))) { + return true; + } + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/h/HiddenPredators.java b/Mage.Sets/src/mage/cards/h/HiddenPredators.java new file mode 100644 index 00000000000..88f532926e3 --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/HiddenPredators.java @@ -0,0 +1,134 @@ +package mage.cards.h; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.StateTriggeredAbility; +import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.PowerPredicate; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.token.TokenImpl; + +/** + * + * @author jeffwadsworth + */ +public final class HiddenPredators extends CardImpl { + + public HiddenPredators(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{G}"); + + // When an opponent controls a creature with power 4 or greater, if Hidden Predators is an enchantment, Hidden Predators becomes a 4/4 Beast creature. + this.addAbility(new HiddenPredatorsStateTriggeredAbility()); + } + + public HiddenPredators(final HiddenPredators card) { + super(card); + } + + @Override + public HiddenPredators copy() { + return new HiddenPredators(this); + } +} + +class HiddenPredatorsStateTriggeredAbility extends StateTriggeredAbility { + + private final static FilterCreaturePermanent filter = new FilterCreaturePermanent(); + + static { + filter.add(new ControllerPredicate(TargetController.OPPONENT)); + filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 3)); + } + + public HiddenPredatorsStateTriggeredAbility() { + super(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(new HiddenPredatorsToken(), "", Duration.Custom, true, false)); + } + + public HiddenPredatorsStateTriggeredAbility(final HiddenPredatorsStateTriggeredAbility ability) { + super(ability); + } + + @Override + public HiddenPredatorsStateTriggeredAbility copy() { + return new HiddenPredatorsStateTriggeredAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + return !game.getBattlefield().getAllActivePermanents(filter, game).isEmpty(); + } + + @Override + public boolean checkInterveningIfClause(Game game) { + if (getSourcePermanentIfItStillExists(game) != null) { + return getSourcePermanentIfItStillExists(game).isEnchantment(); + } + return false; + } + + @Override + public boolean canTrigger(Game game) { + //20100716 - 603.8 + Boolean triggered = (Boolean) game.getState().getValue(getSourceId().toString() + "triggered"); + if (triggered == null) { + triggered = Boolean.FALSE; + } + return !triggered; + } + + @Override + public void trigger(Game game, UUID controllerId) { + //20100716 - 603.8 + game.getState().setValue(this.getSourceId().toString() + "triggered", Boolean.TRUE); + super.trigger(game, controllerId); + } + + @Override + public boolean resolve(Game game) { + //20100716 - 603.8 + boolean result = super.resolve(game); + game.getState().setValue(this.getSourceId().toString() + "triggered", Boolean.FALSE); + return result; + } + + @Override + public void counter(Game game) { + game.getState().setValue(this.getSourceId().toString() + "triggered", Boolean.FALSE); + } + + @Override + public String getRule() { + return new StringBuilder("When an opponent controls a creature with 4 or greater power, if {this} is an enchantment, ").append(super.getRule()).toString(); + } + +} + +class HiddenPredatorsToken extends TokenImpl { + + public HiddenPredatorsToken() { + super("Beast", "4/4 Beast creature"); + cardType.add(CardType.CREATURE); + subtype.add(SubType.BEAST); + power = new MageInt(4); + toughness = new MageInt(4); + } + + public HiddenPredatorsToken(final HiddenPredatorsToken token) { + super(token); + } + + public HiddenPredatorsToken copy() { + return new HiddenPredatorsToken(this); + } +} diff --git a/Mage.Sets/src/mage/cards/h/HiddenStag.java b/Mage.Sets/src/mage/cards/h/HiddenStag.java new file mode 100644 index 00000000000..6083cbaf307 --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/HiddenStag.java @@ -0,0 +1,73 @@ +package mage.cards.h; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.TriggeredAbility; +import mage.abilities.common.ControllerPlaysLandTriggeredAbility; +import mage.abilities.common.OpponentPlaysLandTriggeredAbility; +import mage.abilities.condition.common.SourceMatchesFilterCondition; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; +import mage.abilities.effects.common.continuous.BecomesEnchantmentSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.StaticFilters; +import mage.game.permanent.token.TokenImpl; + +/** + * + * @author jeffwadsworth + */ +public final class HiddenStag extends CardImpl { + + public HiddenStag(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}"); + + // Whenever an opponent plays a land, if Hidden Stag is an enchantment, Hidden Stag becomes a 3/2 Elk Beast creature. + Effect effect = new BecomesCreatureSourceEffect(new ElkBeastToken(), "", Duration.WhileOnBattlefield, true, false); + TriggeredAbility ability = new OpponentPlaysLandTriggeredAbility(Zone.BATTLEFIELD, effect, false); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_ENCHANTMENT_PERMANENT), + "Whenever an opponent plays a land, if Hidden Stag is an enchantment, Hidden Stag becomes a 3/2 Elk Beast creature.")); + + // Whenever you play a land, if Hidden Stag is a creature, Hidden Stag becomes an enchantment. + Effect effect2 = new BecomesEnchantmentSourceEffect(); + TriggeredAbility ability2 = new ControllerPlaysLandTriggeredAbility(Zone.BATTLEFIELD, effect2, false); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability2, new SourceMatchesFilterCondition(StaticFilters.FILTER_PERMANENT_CREATURE), + "Whenever you play a land, if Hidden Stag is a creature, Hidden Stag becomes an enchantment.")); + + } + + public HiddenStag(final HiddenStag card) { + super(card); + } + + @Override + public HiddenStag copy() { + return new HiddenStag(this); + } +} + +class ElkBeastToken extends TokenImpl { + + public ElkBeastToken() { + super("Elk Beast", "3/2 Elk Beast creature"); + cardType.add(CardType.CREATURE); + subtype.add(SubType.ELK); + subtype.add(SubType.BEAST); + power = new MageInt(3); + toughness = new MageInt(2); + } + + public ElkBeastToken(final ElkBeastToken token) { + super(token); + } + + public ElkBeastToken copy() { + return new ElkBeastToken(this); + } +} diff --git a/Mage.Sets/src/mage/cards/i/Icequake.java b/Mage.Sets/src/mage/cards/i/Icequake.java index cad1b47cd1d..70399b40e7d 100644 --- a/Mage.Sets/src/mage/cards/i/Icequake.java +++ b/Mage.Sets/src/mage/cards/i/Icequake.java @@ -59,14 +59,16 @@ class IcequakeEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); - if (permanent != null && controller != null) { - permanent.destroy(source.getSourceId(), game, false); - if (permanent.isSnow()) { - controller.damage(1, source.getSourceId(), game, false, true); + if (permanent != null) { + Player controller = game.getPlayer(permanent.getControllerId()); + if(controller != null) { + permanent.destroy(source.getSourceId(), game, false); + if (permanent.isSnow()) { + controller.damage(1, source.getSourceId(), game, false, true); + } + return true; } - return true; } return false; } diff --git a/Mage.Sets/src/mage/cards/i/Incendiary.java b/Mage.Sets/src/mage/cards/i/Incendiary.java new file mode 100644 index 00000000000..f5987a4793c --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/Incendiary.java @@ -0,0 +1,65 @@ +package mage.cards.i; + +import java.util.UUID; +import mage.constants.SubType; +import mage.target.common.TargetCreaturePermanent; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.DiesAttachedTriggeredAbility; +import mage.abilities.dynamicvalue.common.CountersSourceCount; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.constants.Outcome; +import mage.target.TargetPermanent; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.target.common.TargetCreatureOrPlayer; + +/** + * + * @author jeffwadsworth + */ +public final class Incendiary extends CardImpl { + + private static final String rule = "{this} deals X damage to any target, where X is the number of fuse counters on {this}."; + + public Incendiary(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{R}"); + + this.subtype.add(SubType.AURA); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // At the beginning of your upkeep, you may put a fuse counter on Incendiary. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, + new AddCountersSourceEffect(CounterType.FUSE.createInstance(), true), TargetController.YOU, true)); + + // When enchanted creature dies, Incendiary deals X damage to any target, where X is the number of fuse counters on Incendiary. + Effect effect = new DamageTargetEffect(new CountersSourceCount(CounterType.FUSE)).setText(rule); + Ability ability2 = new DiesAttachedTriggeredAbility(effect, "enchanted creature"); + ability.addTarget(new TargetCreatureOrPlayer()); + this.addAbility(ability2); + + } + + public Incendiary(final Incendiary card) { + super(card); + } + + @Override + public Incendiary copy() { + return new Incendiary(this); + } +} diff --git a/Mage.Sets/src/mage/cards/i/InspiredSphinx.java b/Mage.Sets/src/mage/cards/i/InspiredSphinx.java new file mode 100644 index 00000000000..f3e793d77e6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/InspiredSphinx.java @@ -0,0 +1,51 @@ +package mage.cards.i; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.common.OpponentsCount; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.game.permanent.token.ThopterColorlessToken; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class InspiredSphinx extends CardImpl { + + public InspiredSphinx(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{U}{U}"); + this.subtype.add(SubType.SPHINX); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // When Inspired Sphinx enters the battlefield, draw cards equal to the number of opponents you have. + this.addAbility(new EntersBattlefieldTriggeredAbility( + new DrawCardSourceControllerEffect(new OpponentsCount()).setText("draw cards equal to the number of opponents you have") + )); + + // {3}{U}: Create a colorless 1/1 Thopter artifact creature token with flying. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new ThopterColorlessToken()), new ManaCostsImpl<>("{3}{U}"))); + } + + public InspiredSphinx(final InspiredSphinx card) { + super(card); + } + + @Override + public InspiredSphinx copy() { + return new InspiredSphinx(this); + } +} diff --git a/Mage.Sets/src/mage/cards/i/InspiringCommander.java b/Mage.Sets/src/mage/cards/i/InspiringCommander.java new file mode 100644 index 00000000000..ad50beeafcd --- /dev/null +++ b/Mage.Sets/src/mage/cards/i/InspiringCommander.java @@ -0,0 +1,59 @@ +package mage.cards.i; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.mageobject.PowerPredicate; +import mage.filter.predicate.permanent.AnotherPredicate; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class InspiringCommander extends CardImpl { + + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("another creature with power 2 or less"); + + static { + filter.add(new AnotherPredicate()); + filter.add(new PowerPredicate(ComparisonType.FEWER_THAN, 3)); + } + + public InspiringCommander(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}{W}"); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.SOLDIER); + + this.power = new MageInt(1); + this.toughness = new MageInt(4); + + // Whenever another creature with power 2 or less enters the battlefield under your control, you gain 1 life and draw a card. + Effect effect1 = new GainLifeEffect(1); + Effect effect2 = new DrawCardSourceControllerEffect(1); + Ability ability = new EntersBattlefieldControlledTriggeredAbility( + Zone.BATTLEFIELD, effect1, filter, false); + ability.addEffect(effect2.setText("and draw a card")); + this.addAbility(ability); + } + + public InspiringCommander(final InspiringCommander card) { + super(card); + } + + @Override + public InspiringCommander copy() { + return new InspiringCommander(this); + } +} diff --git a/Mage.Sets/src/mage/cards/j/JaceArchitectOfThought.java b/Mage.Sets/src/mage/cards/j/JaceArchitectOfThought.java index 125d144b15d..fbf022f466b 100644 --- a/Mage.Sets/src/mage/cards/j/JaceArchitectOfThought.java +++ b/Mage.Sets/src/mage/cards/j/JaceArchitectOfThought.java @@ -2,6 +2,8 @@ package mage.cards.j; import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; import java.util.Set; import java.util.UUID; import mage.MageObjectReference; @@ -24,7 +26,10 @@ import mage.constants.SubType; import mage.constants.SuperType; import mage.constants.Zone; import mage.filter.FilterCard; +import mage.filter.FilterPlayer; import mage.filter.common.FilterNonlandCard; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.other.PlayerIdPredicate; import mage.game.ExileZone; import mage.game.Game; import mage.game.events.GameEvent; @@ -32,6 +37,7 @@ import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetCard; +import mage.target.TargetPlayer; import mage.target.common.TargetCardInExile; import mage.target.common.TargetCardInLibrary; import mage.target.common.TargetOpponent; @@ -239,28 +245,61 @@ class JaceArchitectOfThoughtEffect3 extends OneShotEffect { if (controller == null || sourcePermanent == null) { return false; } - if(controller.chooseUse(Outcome.Benefit, "Look at all players' libraries before card select?", null, game)) { + if (controller.chooseUse(Outcome.Benefit, "Look at all players' libraries before card select?", null, game)) { game.informPlayers(controller.getLogName() + " is looking at all players' libraries."); controller.lookAtAllLibraries(source, game); } - for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { - Player player = game.getPlayer(playerId); - String playerName = new StringBuilder(player.getLogName()).append("'s").toString(); - if (source.isControlledBy(player.getId())) { - playerName = "your"; + List playerList = new ArrayList<>(); + playerList.addAll(game.getState().getPlayersInRange(controller.getId(), game)); + Set checkList = new HashSet<>(); + while (!playerList.isEmpty()) { + FilterPlayer filter = new FilterPlayer(); + List playerPredicates = new ArrayList<>(); + for (UUID playerId : playerList) { + playerPredicates.add(new PlayerIdPredicate(playerId)); } - - TargetCardInLibrary target = new TargetCardInLibrary(new FilterNonlandCard(new StringBuilder("nonland card from ").append(playerName).append(" library").toString())); - if (controller.searchLibrary(target, game, playerId)) { - UUID targetId = target.getFirstTarget(); - Card card = player.getLibrary().remove(targetId, game); - if (card != null) { - controller.moveCardToExileWithInfo(card, CardUtil.getCardExileZoneId(game, source), sourcePermanent.getIdName(), source.getSourceId(), game, Zone.LIBRARY, true); + filter.add(Predicates.or(playerPredicates)); + TargetPlayer targetPlayer = new TargetPlayer(1, 1, true, filter); + targetPlayer.setRequired(!checkList.containsAll(playerList)); + if (controller.chooseTarget(outcome, targetPlayer, source, game)) { + UUID playerId = targetPlayer.getFirstTarget(); + Player player = game.getPlayer(playerId); + if (player != null) { + String playerName = new StringBuilder(player.getLogName()).append("'s").toString(); + if (source.isControlledBy(player.getId())) { + playerName = "your"; + } + TargetCardInLibrary target = new TargetCardInLibrary(new FilterNonlandCard(new StringBuilder("nonland card from ").append(playerName).append(" library").toString())); + if (controller.searchLibrary(target, game, playerId, !checkList.contains(playerId))) { + checkList.add(playerId); + UUID targetId = target.getFirstTarget(); + Card card = player.getLibrary().remove(targetId, game); + if (card != null) { + controller.moveCardToExileWithInfo(card, CardUtil.getCardExileZoneId(game, source), sourcePermanent.getIdName(), source.getSourceId(), game, Zone.LIBRARY, true); + playerList.remove(playerId); + } + } else { + playerList.remove(playerId); + } + } else { + playerList.remove(playerId); + } + } else { + break; + } + for (UUID playerId : playerList) { + Player player = game.getPlayer(playerId); + if (player == null || !player.canRespond()) { + playerList.remove(player); } } - player.shuffleLibrary(source, game); } - + for (UUID playerId : checkList) { + Player player = game.getPlayer(playerId); + if (player != null) { + player.shuffleLibrary(source, game); + } + } ExileZone jaceExileZone = game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source)); if (jaceExileZone == null) { return true; diff --git a/Mage.Sets/src/mage/cards/j/JusticeStrike.java b/Mage.Sets/src/mage/cards/j/JusticeStrike.java index db01871ddb1..f992cd7c4a2 100644 --- a/Mage.Sets/src/mage/cards/j/JusticeStrike.java +++ b/Mage.Sets/src/mage/cards/j/JusticeStrike.java @@ -38,7 +38,7 @@ public final class JusticeStrike extends CardImpl { class JusticeStrikeEffect extends OneShotEffect { public JusticeStrikeEffect() { - super(Outcome.Benefit); + super(Outcome.Damage); this.staticText = "Target creature deals damage to itself equal to its power."; } diff --git a/Mage.Sets/src/mage/cards/k/KarametraGodOfHarvests.java b/Mage.Sets/src/mage/cards/k/KarametraGodOfHarvests.java index 2325c45a863..6ccd4c9f3b1 100644 --- a/Mage.Sets/src/mage/cards/k/KarametraGodOfHarvests.java +++ b/Mage.Sets/src/mage/cards/k/KarametraGodOfHarvests.java @@ -25,7 +25,7 @@ import mage.target.common.TargetCardInLibrary; */ public final class KarametraGodOfHarvests extends CardImpl { - private static final FilterCard filter = new FilterCard("a Forest or Plains card"); + private static final FilterCard filter = new FilterCard("Forest or Plains card"); static { filter.add(Predicates.or( diff --git a/Mage.Sets/src/mage/cards/k/KryShield.java b/Mage.Sets/src/mage/cards/k/KryShield.java new file mode 100644 index 00000000000..8fc55fc5dc4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/k/KryShield.java @@ -0,0 +1,49 @@ + +package mage.cards.k; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.dynamicvalue.common.TargetConvertedManaCost; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.PreventDamageByTargetEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.target.common.TargetControlledCreaturePermanent; + +/** + * + * @author L_J + */ +public final class KryShield extends CardImpl { + + public KryShield(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{2}"); + + // {2}, {T}: Prevent all damage that would be dealt this turn by target creature you control. That creature gets +0/+X until end of turn, where X is its converted mana cost. + Effect effect = new PreventDamageByTargetEffect(Duration.EndOfTurn); + effect.setText("Prevent all damage that would be dealt this turn by target creature you control"); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new GenericManaCost(2)); + ability.addEffect(new BoostTargetEffect(new StaticValue(0), new TargetConvertedManaCost(), Duration.EndOfTurn, true) + .setText("That creature gets +0/+X until end of turn, where X is its converted mana cost")); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetControlledCreaturePermanent()); + this.addAbility(ability); + } + + public KryShield(final KryShield card) { + super(card); + } + + @Override + public KryShield copy() { + return new KryShield(this); + } +} diff --git a/Mage.Sets/src/mage/cards/l/LeylineOfVitality.java b/Mage.Sets/src/mage/cards/l/LeylineOfVitality.java index 42be613481e..8808969cecd 100644 --- a/Mage.Sets/src/mage/cards/l/LeylineOfVitality.java +++ b/Mage.Sets/src/mage/cards/l/LeylineOfVitality.java @@ -1,8 +1,7 @@ package mage.cards.l; -import java.util.UUID; -import mage.abilities.common.CreatureEntersBattlefieldTriggeredAbility; +import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.continuous.BoostControlledEffect; @@ -14,8 +13,9 @@ import mage.constants.Duration; import mage.constants.Zone; import mage.filter.StaticFilters; +import java.util.UUID; + /** - * * @author BetaSteward_at_googlemail.com */ public final class LeylineOfVitality extends CardImpl { @@ -23,10 +23,19 @@ public final class LeylineOfVitality extends CardImpl { public LeylineOfVitality(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}{G}"); + // If Leyline of Vitality is in your opening hand, you may begin the game with it on the battlefield. this.addAbility(LeylineAbility.getInstance()); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostControlledEffect(0, 1, Duration.WhileOnBattlefield, StaticFilters.FILTER_PERMANENT_CREATURE, false))); - this.addAbility(new CreatureEntersBattlefieldTriggeredAbility(new GainLifeEffect(1), true)); + // Creatures you control get +0/+1. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostControlledEffect(0, 1, Duration.WhileOnBattlefield, StaticFilters.FILTER_PERMANENT_CREATURES, false))); + + // Whenever a creature enters the battlefield under your control, you may gain 1 life. + this.addAbility(new EntersBattlefieldControlledTriggeredAbility( + Zone.BATTLEFIELD, + new GainLifeEffect(1), + StaticFilters.FILTER_PERMANENT_CREATURE_A, + true) + ); } public LeylineOfVitality(final LeylineOfVitality card) { diff --git a/Mage.Sets/src/mage/cards/l/LurkingJackals.java b/Mage.Sets/src/mage/cards/l/LurkingJackals.java new file mode 100644 index 00000000000..4822bb2c2de --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LurkingJackals.java @@ -0,0 +1,130 @@ +package mage.cards.l; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.StateTriggeredAbility; +import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.token.TokenImpl; + +/** + * + * @author jeffwadsworth + */ +public final class LurkingJackals extends CardImpl { + + public LurkingJackals(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{B}"); + + // When an opponent has 10 or less life, if Lurking Jackals is an enchantment, it becomes a 3/2 Hound creature. + this.addAbility(new LurkingJackalsStateTriggeredAbility()); + } + + public LurkingJackals(final LurkingJackals card) { + super(card); + } + + @Override + public LurkingJackals copy() { + return new LurkingJackals(this); + } +} + +class LurkingJackalsStateTriggeredAbility extends StateTriggeredAbility { + + public LurkingJackalsStateTriggeredAbility() { + super(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(new LurkingJackalsToken(), "", Duration.Custom, true, false)); + } + + public LurkingJackalsStateTriggeredAbility(final LurkingJackalsStateTriggeredAbility ability) { + super(ability); + } + + @Override + public LurkingJackalsStateTriggeredAbility copy() { + return new LurkingJackalsStateTriggeredAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (game.getOpponents(getControllerId()) != null) { + for (UUID opponentId : game.getOpponents(getControllerId())) { + if (game.getPlayer(opponentId).getLife() <= 10) { + return true; + } + } + } + return false; + } + + @Override + public boolean checkInterveningIfClause(Game game) { + if (getSourcePermanentIfItStillExists(game) != null) { + return getSourcePermanentIfItStillExists(game).isEnchantment(); + } + return false; + } + + @Override + public boolean canTrigger(Game game) { + //20100716 - 603.8 + Boolean triggered = (Boolean) game.getState().getValue(getSourceId().toString() + "triggered"); + if (triggered == null) { + triggered = Boolean.FALSE; + } + return !triggered; + } + + @Override + public void trigger(Game game, UUID controllerId) { + //20100716 - 603.8 + game.getState().setValue(this.getSourceId().toString() + "triggered", Boolean.TRUE); + super.trigger(game, controllerId); + } + + @Override + public boolean resolve(Game game) { + //20100716 - 603.8 + boolean result = super.resolve(game); + game.getState().setValue(this.getSourceId().toString() + "triggered", Boolean.FALSE); + return result; + } + + @Override + public void counter(Game game) { + game.getState().setValue(this.getSourceId().toString() + "triggered", Boolean.FALSE); + } + + @Override + public String getRule() { + return new StringBuilder("When an opponent has 10 or less life, if {this} is an enchantment, ").append(super.getRule()).toString(); + } + +} + +class LurkingJackalsToken extends TokenImpl { + + public LurkingJackalsToken() { + super("Hound", "3/2 Hound creature"); + cardType.add(CardType.CREATURE); + subtype.add(SubType.HOUND); + power = new MageInt(3); + toughness = new MageInt(2); + } + + public LurkingJackalsToken(final LurkingJackalsToken token) { + super(token); + } + + @Override + public LurkingJackalsToken copy() { + return new LurkingJackalsToken(this); + } +} diff --git a/Mage.Sets/src/mage/cards/l/LurkingSkirge.java b/Mage.Sets/src/mage/cards/l/LurkingSkirge.java new file mode 100644 index 00000000000..8829e559b74 --- /dev/null +++ b/Mage.Sets/src/mage/cards/l/LurkingSkirge.java @@ -0,0 +1,71 @@ +package mage.cards.l; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.TriggeredAbility; +import mage.abilities.common.PutIntoGraveFromBattlefieldAllTriggeredAbility; +import mage.abilities.condition.common.SourceMatchesFilterCondition; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.TargetController; +import mage.filter.StaticFilters; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.other.OwnerPredicate; +import mage.game.permanent.token.TokenImpl; + +/** + * + * @author jeffwadsworth + */ +public final class LurkingSkirge extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); + + static { + filter.add(new OwnerPredicate(TargetController.OPPONENT)); + } + + public LurkingSkirge(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}"); + + // When a creature is put into an opponent's graveyard from the battlefield, if Lurking Skirge is an enchantment, Lurking Skirge becomes a 3/2 Imp creature with flying. + TriggeredAbility ability = new PutIntoGraveFromBattlefieldAllTriggeredAbility(new BecomesCreatureSourceEffect(new LurkingSkirgeToken(), "", Duration.WhileOnBattlefield, true, false), false, filter, false); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_ENCHANTMENT_PERMANENT), + "When a creature is put into an opponent's graveyard from the battlefield, if {this} is an enchantment, {this} becomes a 3/2 Imp creature with flying.")); + } + + public LurkingSkirge(final LurkingSkirge card) { + super(card); + } + + @Override + public LurkingSkirge copy() { + return new LurkingSkirge(this); + } +} + +class LurkingSkirgeToken extends TokenImpl { + + public LurkingSkirgeToken() { + super("Imp", "3/2 Imp with flying."); + cardType.add(CardType.CREATURE); + subtype.add(SubType.IMP); + power = new MageInt(3); + toughness = new MageInt(2); + this.addAbility(FlyingAbility.getInstance()); + } + + public LurkingSkirgeToken(final LurkingSkirgeToken token) { + super(token); + } + + public LurkingSkirgeToken copy() { + return new LurkingSkirgeToken(this); + } +} diff --git a/Mage.Sets/src/mage/cards/m/Machinate.java b/Mage.Sets/src/mage/cards/m/Machinate.java index dbb2094a560..b1039219f02 100644 --- a/Mage.Sets/src/mage/cards/m/Machinate.java +++ b/Mage.Sets/src/mage/cards/m/Machinate.java @@ -30,7 +30,9 @@ public final class Machinate extends CardImpl { // Look at the top X cards of your library, where X is the number of artifacts you control. Put one of those cards into your hand and the rest on the bottom of your library in any order. DynamicValue artifactsOnControl = new PermanentsOnBattlefieldCount(filter); - this.getSpellAbility().addEffect(new LookLibraryAndPickControllerEffect(artifactsOnControl, false, new StaticValue(1), new FilterCard(), Zone.LIBRARY, false, false)); + LookLibraryAndPickControllerEffect effect = new LookLibraryAndPickControllerEffect(artifactsOnControl, false, new StaticValue(1), new FilterCard(), Zone.LIBRARY, false, false); + effect.setText("Look at the top X cards of your library, where X is the number of artifacts you control. Put one of those cards into your hand and the rest on the bottom of your library in any order."); + this.getSpellAbility().addEffect(effect); } public Machinate(final Machinate card) { diff --git a/Mage.Sets/src/mage/cards/m/MammothUmbra.java b/Mage.Sets/src/mage/cards/m/MammothUmbra.java index 4b67b0e72c8..17343666429 100644 --- a/Mage.Sets/src/mage/cards/m/MammothUmbra.java +++ b/Mage.Sets/src/mage/cards/m/MammothUmbra.java @@ -2,6 +2,7 @@ package mage.cards.m; import java.util.UUID; + import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.AttachEffect; @@ -17,13 +18,12 @@ import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; /** - * * @author Loki */ public final class MammothUmbra extends CardImpl { public MammothUmbra(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{4}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{W}"); this.subtype.add(SubType.AURA); @@ -33,9 +33,12 @@ public final class MammothUmbra extends CardImpl { this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); Ability ability = new EnchantAbility(auraTarget.getTargetName()); this.addAbility(ability); + // Enchanted creature gets +3/+3 and has vigilance. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(3, 3, Duration.WhileOnBattlefield))); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(VigilanceAbility.getInstance(), AttachmentType.AURA))); + + // Totem armor this.addAbility(new TotemArmorAbility()); } diff --git a/Mage.Sets/src/mage/cards/m/MasterOfTheHunt.java b/Mage.Sets/src/mage/cards/m/MasterOfTheHunt.java new file mode 100644 index 00000000000..32ea8a44b57 --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MasterOfTheHunt.java @@ -0,0 +1,40 @@ + +package mage.cards.m; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.game.permanent.token.WolvesOfTheHuntToken; + +/** + * @author L_J + */ +public final class MasterOfTheHunt extends CardImpl { + + public MasterOfTheHunt(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{G}{G}"); + this.subtype.add(SubType.HUMAN); + this.power = new MageInt(2); + this.toughness = new MageInt(2); + + // Create a 1/1 green Wolf creature token named Wolves of the Hunt. It has “bands with other creatures named Wolves of the Hunt.” + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new CreateTokenEffect(new WolvesOfTheHuntToken()), new ManaCostsImpl("{2}{G}{G}"))); + } + + public MasterOfTheHunt(final MasterOfTheHunt card) { + super(card); + } + + @Override + public MasterOfTheHunt copy() { + return new MasterOfTheHunt(this); + } + +} diff --git a/Mage.Sets/src/mage/cards/m/MetathranElite.java b/Mage.Sets/src/mage/cards/m/MetathranElite.java new file mode 100644 index 00000000000..cfeed06ccfe --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MetathranElite.java @@ -0,0 +1,47 @@ +package mage.cards.m; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.EnchantedSourceCondition; +import mage.abilities.decorator.ConditionalRestrictionEffect; +import mage.abilities.effects.common.combat.CantBeBlockedSourceEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; + +/** + * + * @author jeffwadsworth + */ +public final class MetathranElite extends CardImpl { + + private static final String rule = "{this} is unblockable as long as it's enchanted."; + + public MetathranElite(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{U}"); + + this.subtype.add(SubType.METATHRAN); + this.subtype.add(SubType.SOLDIER); + this.power = new MageInt(2); + this.toughness = new MageInt(3); + + // Metathran Elite is unblockable as long as it's enchanted. + ConditionalRestrictionEffect effect = new ConditionalRestrictionEffect( + new CantBeBlockedSourceEffect(), new EnchantedSourceCondition()); + effect.setText(rule); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); + + } + + public MetathranElite(final MetathranElite card) { + super(card); + } + + @Override + public MetathranElite copy() { + return new MetathranElite(this); + } +} diff --git a/Mage.Sets/src/mage/cards/m/MilitantAngel.java b/Mage.Sets/src/mage/cards/m/MilitantAngel.java new file mode 100644 index 00000000000..790f1e62c17 --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MilitantAngel.java @@ -0,0 +1,49 @@ +package mage.cards.m; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.dynamicvalue.common.AttackedThisTurnOpponentsCount; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.LifelinkAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.game.permanent.token.KnightToken; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class MilitantAngel extends CardImpl { + + public MilitantAngel(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}{W}"); + this.subtype.add(SubType.ANGEL); + this.power = new MageInt(3); + this.toughness = new MageInt(4); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + + // Lifelink + this.addAbility(LifelinkAbility.getInstance()); + + // When Militant Angel enters the battlefield, create a number of 2/2 white Knight creature tokens with vigilance equal to the number of opponents you attacked this turn. + Effect effect = new CreateTokenEffect(new KnightToken(), new AttackedThisTurnOpponentsCount()); + effect.setText("create a number of 2/2 white Knight creature tokens with vigilance equal to the number of opponents you attacked this turn"); + this.addAbility(new EntersBattlefieldTriggeredAbility(effect)); + } + + public MilitantAngel(final MilitantAngel card) { + super(card); + } + + @Override + public MilitantAngel copy() { + return new MilitantAngel(this); + } +} diff --git a/Mage.Sets/src/mage/cards/m/MindBomb.java b/Mage.Sets/src/mage/cards/m/MindBomb.java index 56a35ad408a..26b08552837 100644 --- a/Mage.Sets/src/mage/cards/m/MindBomb.java +++ b/Mage.Sets/src/mage/cards/m/MindBomb.java @@ -1,17 +1,10 @@ package mage.cards.m; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; -import mage.cards.Card; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.cards.CardsImpl; +import mage.cards.*; import mage.constants.CardType; import mage.constants.Outcome; import mage.filter.FilterCard; @@ -20,8 +13,11 @@ import mage.players.Player; import mage.target.Target; import mage.target.common.TargetDiscard; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + /** - * * @author TheElk801 */ public final class MindBomb extends CardImpl { @@ -67,6 +63,7 @@ class MindBombEffect extends OneShotEffect { if (controller != null && sourceObject != null) { Map cardsToDiscard = new HashMap<>(); + // choose for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { Player player = game.getPlayer(playerId); if (player != null) { @@ -77,6 +74,8 @@ class MindBombEffect extends OneShotEffect { cardsToDiscard.put(playerId, cards); } } + + // discard for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { Player player = game.getPlayer(playerId); if (player != null) { @@ -91,31 +90,17 @@ class MindBombEffect extends OneShotEffect { } } } + + // damage for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { Player player = game.getPlayer(playerId); if (player != null) { Cards cardsPlayer = cardsToDiscard.get(playerId); - if (cardsPlayer != null && !cardsPlayer.isEmpty()) { + if (cardsPlayer != null) { player.damage(3 - cardsPlayer.size(), source.getId(), game, false, true); } } } - // reveal the searched lands, put in hands, and shuffle -// for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { -// Player player = game.getPlayer(playerId); -// if (player != null) { -// Cards cardsPlayer = cardsToReveal.get(playerId); -// if (cardsPlayer != null) { -// for (UUID cardId : cardsPlayer) { -// Cards cards = new CardsImpl(game.getCard(cardId)); -// Card card = game.getCard(cardId); -// player.revealCards(sourceObject.getIdName() + " (" + player.getName() + ')', cards, game); -// player.moveCards(card, Zone.HAND, source, game); -// player.shuffleLibrary(source, game); -// } -// } -// } -// } return true; } return false; diff --git a/Mage.Sets/src/mage/cards/m/MirrorwoodTreefolk.java b/Mage.Sets/src/mage/cards/m/MirrorwoodTreefolk.java new file mode 100644 index 00000000000..c648d36d5a0 --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MirrorwoodTreefolk.java @@ -0,0 +1,95 @@ + +package mage.cards.m; + +import java.util.UUID; +import mage.MageInt; +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.RedirectionEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.target.common.TargetAnyTarget; + +/** + * + * @author LevelX2 & L_J + */ +public final class MirrorwoodTreefolk extends CardImpl { + + public MirrorwoodTreefolk(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}"); + this.subtype.add(SubType.TREEFOLK); + this.power = new MageInt(2); + this.toughness = new MageInt(4); + + // {2}{R}{W}: The next time damage would be dealt to Mirrorwood Treefolk this turn, that damage is dealt to any target instead. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new MirrorwoodTreefolkEffect(), new ManaCostsImpl("{2}{R}{W}")); + ability.addTarget(new TargetAnyTarget()); + this.addAbility(ability); + } + + public MirrorwoodTreefolk(final MirrorwoodTreefolk card) { + super(card); + } + + @Override + public MirrorwoodTreefolk copy() { + return new MirrorwoodTreefolk(this); + } +} + +class MirrorwoodTreefolkEffect extends RedirectionEffect { + + protected MageObjectReference redirectToObject; + + public MirrorwoodTreefolkEffect() { + super(Duration.EndOfTurn, Integer.MAX_VALUE, UsageType.ONE_USAGE_ABSOLUTE); + staticText = "The next time damage would be dealt to {this} this turn, that damage is dealt to any target instead"; + } + + public MirrorwoodTreefolkEffect(final MirrorwoodTreefolkEffect effect) { + super(effect); + this.redirectToObject = effect.redirectToObject; + } + + @Override + public MirrorwoodTreefolkEffect copy() { + return new MirrorwoodTreefolkEffect(this); + } + + @Override + public void init(Ability source, Game game) { + super.init(source, game); + redirectToObject = new MageObjectReference(source.getTargets().get(0).getFirstTarget(), game); + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGE_CREATURE; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (event.getTargetId().equals(source.getSourceId())) { + if (redirectToObject.equals(new MageObjectReference(source.getTargets().get(0).getFirstTarget(), game))) { + redirectTarget = source.getTargets().get(0); + return true; + } + } + return false; + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + +} diff --git a/Mage.Sets/src/mage/cards/m/MissionBriefing.java b/Mage.Sets/src/mage/cards/m/MissionBriefing.java index ecd3f55643f..29642c0d632 100644 --- a/Mage.Sets/src/mage/cards/m/MissionBriefing.java +++ b/Mage.Sets/src/mage/cards/m/MissionBriefing.java @@ -13,7 +13,6 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.Zone; -import mage.filter.FilterCard; import mage.filter.common.FilterInstantOrSorceryCard; import mage.game.Game; import mage.game.events.GameEvent; @@ -48,14 +47,12 @@ public final class MissionBriefing extends CardImpl { class MissionBriefingEffect extends OneShotEffect { - public static final FilterCard filter = new FilterInstantOrSorceryCard("instant or sorcery card from your graveyard"); - public MissionBriefingEffect() { super(Outcome.Benefit); this.staticText = "Surveil 2, then choose an instant or sorcery card " + "in your graveyard. You may cast that card this turn. " + "If that card would be put into your graveyard this turn, " - + "exile it instead."; + + "exile it instead"; } public MissionBriefingEffect(final MissionBriefingEffect effect) { @@ -74,9 +71,10 @@ class MissionBriefingEffect extends OneShotEffect { return false; } player.surveil(2, source, game); - Target target = new TargetCardInYourGraveyard(filter); + Target target = new TargetCardInYourGraveyard( + new FilterInstantOrSorceryCard("instant or sorcery card from your graveyard")); if (!player.choose(outcome, target, source.getSourceId(), game)) { - return false; + return true; } Card card = game.getCard(target.getFirstTarget()); if (card != null) { diff --git a/Mage.Sets/src/mage/cards/m/Mistfolk.java b/Mage.Sets/src/mage/cards/m/Mistfolk.java new file mode 100644 index 00000000000..497feb0ec5a --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/Mistfolk.java @@ -0,0 +1,83 @@ +package mage.cards.m; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.Mode; +import mage.abilities.SpellAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.CounterTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.FilterSpell; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.stack.Spell; +import mage.target.Target; +import mage.target.TargetSpell; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class Mistfolk extends CardImpl { + + private static final FilterSpell filter = new FilterSpell("spell that this creature"); + + static { + filter.add(MistfolkPredicate.instance); + } + + public Mistfolk(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{U}{U}"); + + this.subtype.add(SubType.ILLUSION); + this.power = new MageInt(1); + this.toughness = new MageInt(2); + + // {U}: Counter target spell that targets Mistfolk. + Ability ability = new SimpleActivatedAbility( + new CounterTargetEffect() + .setText("counter target spell that targets {this}"), + new ManaCostsImpl("{U}") + ); + ability.addTarget(new TargetSpell(filter)); + this.addAbility(ability); + } + + public Mistfolk(final Mistfolk card) { + super(card); + } + + @Override + public Mistfolk copy() { + return new Mistfolk(this); + } +} + +enum MistfolkPredicate implements ObjectSourcePlayerPredicate> { + instance; + + @Override + public boolean apply(ObjectSourcePlayer input, Game game) { + Permanent sourceObject = game.getPermanent(input.getSourceId()); + if (sourceObject == null || input.getObject() == null) { + return false; + } + for (SpellAbility spellAbility : input.getObject().getSpellAbilities()) { + for (Mode mode : spellAbility.getModes().values()) { + for (Target target : spellAbility.getTargets()) { + if (target.getTargets().contains(input.getSourceId())) { + return true; + } + } + } + } + return false; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/m/MistveilPlains.java b/Mage.Sets/src/mage/cards/m/MistveilPlains.java index f564de722b7..35d71a44877 100644 --- a/Mage.Sets/src/mage/cards/m/MistveilPlains.java +++ b/Mage.Sets/src/mage/cards/m/MistveilPlains.java @@ -1,6 +1,6 @@ - package mage.cards.m; +import java.util.UUID; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.common.ActivateIfConditionActivatedAbility; @@ -20,8 +20,6 @@ import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCardInYourGraveyard; -import java.util.UUID; - /** * @author LevelX2 */ @@ -86,8 +84,8 @@ class MistveilPlainsGraveyardToLibraryEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Card card = game.getCard(source.getFirstTarget()); Player player = game.getPlayer(source.getControllerId()); - if (card == null || player == null || - game.getState().getZone(card.getId()) == Zone.GRAVEYARD) { + if (card == null || player == null + || game.getState().getZone(card.getId()) != Zone.GRAVEYARD) { return false; } return player.putCardsOnBottomOfLibrary(card, game, source, false); diff --git a/Mage.Sets/src/mage/cards/m/MnemonicBetrayal.java b/Mage.Sets/src/mage/cards/m/MnemonicBetrayal.java index 019527dd74f..ab23ae3bd35 100644 --- a/Mage.Sets/src/mage/cards/m/MnemonicBetrayal.java +++ b/Mage.Sets/src/mage/cards/m/MnemonicBetrayal.java @@ -10,10 +10,11 @@ import mage.constants.*; import mage.game.Game; import mage.game.events.GameEvent; import mage.players.Player; - import java.util.HashMap; import java.util.Map; import java.util.UUID; +import mage.abilities.effects.AsThoughManaEffect; +import mage.players.ManaPoolItem; /** * @author TheElk801 @@ -69,17 +70,18 @@ class MnemonicBetrayalExileEffect extends OneShotEffect { } Cards cards = new CardsImpl(); Map cardMap = new HashMap(); - for (UUID playerId : game.getOpponents(source.getControllerId())) { - Player player = game.getPlayer(playerId); - if (player != null) { - cards.addAll(player.getGraveyard()); - } - } - for (Card card : cards.getCards(game)) { + game.getOpponents(source.getControllerId()).stream().map((playerId) -> game.getPlayer(playerId)).filter((player) -> (player != null)).forEachOrdered((player) -> { + cards.addAll(player.getGraveyard()); + }); + cards.getCards(game).stream().map((card) -> { cardMap.put(card.getId(), card.getZoneChangeCounter(game)); + return card; + }).map((card) -> { game.addEffect(new MnemonicBetrayalCastFromExileEffect(card, game), source); + return card; + }).forEachOrdered((card) -> { game.addEffect(new MnemonicBetrayalAnyColorEffect(card, game), source); - } + }); controller.moveCardsToExile(cards.getCards(game), source, game, true, source.getSourceId(), source.getSourceObjectIfItStillExists(game).getName()); game.addDelayedTriggeredAbility(new MnemonicBetrayalDelayedTriggeredAbility(cards, cardMap), source); return true; @@ -125,7 +127,7 @@ class MnemonicBetrayalCastFromExileEffect extends AsThoughEffectImpl { } } -class MnemonicBetrayalAnyColorEffect extends AsThoughEffectImpl { +class MnemonicBetrayalAnyColorEffect extends AsThoughEffectImpl implements AsThoughManaEffect { private final Card card; private final int zoneCounter; @@ -154,13 +156,21 @@ class MnemonicBetrayalAnyColorEffect extends AsThoughEffectImpl { @Override public boolean applies(UUID objectId, Ability source, UUID affectedControllerId, Game game) { - if (card.getZoneChangeCounter(game) != zoneCounter) { - this.discard(); - return false; + if (objectId.equals(card.getId()) + && card.getZoneChangeCounter(game) <= zoneCounter + 1 + && affectedControllerId.equals(source.getControllerId())) { + return true; + } else { + if (objectId.equals(card.getId())) { + this.discard(); + } } - return objectId.equals(card.getId()) - && card.getZoneChangeCounter(game) == zoneCounter - && affectedControllerId.equals(source.getControllerId()); + return false; + } + + @Override + public ManaType getAsThoughManaType(ManaType manaType, ManaPoolItem mana, UUID affectedControllerId, Ability source, Game game) { + return mana.getFirstAvailable(); } } @@ -240,12 +250,10 @@ class MnemonicBetrayalReturnEffect extends OneShotEffect { return false; } Cards cardsToReturn = new CardsImpl(); - for (Card card : cards.getCards(game)) { - if (game.getState().getZone(card.getId()) == Zone.EXILED - && card.getZoneChangeCounter(game) == cardMap.getOrDefault(card.getId(), -5) + 1) { - cardsToReturn.add(card); - } - } + cards.getCards(game).stream().filter((card) -> (game.getState().getZone(card.getId()) == Zone.EXILED + && card.getZoneChangeCounter(game) == cardMap.getOrDefault(card.getId(), -5) + 1)).forEachOrdered((card) -> { + cardsToReturn.add(card); + }); return player.moveCards(cardsToReturn, Zone.GRAVEYARD, source, game); } } diff --git a/Mage.Sets/src/mage/cards/m/MobMentality.java b/Mage.Sets/src/mage/cards/m/MobMentality.java new file mode 100644 index 00000000000..e00596f1a3f --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MobMentality.java @@ -0,0 +1,111 @@ +package mage.cards.m; + +import mage.abilities.Ability; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.dynamicvalue.common.AttackingCreatureCount; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; +import mage.target.targetpointer.FixedTarget; + +import java.util.UUID; + +/** + * @author TheElk801 + */ +public final class MobMentality extends CardImpl { + + public MobMentality(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{R}"); + + this.subtype.add(SubType.AURA); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // Enchanted creature has trample. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(TrampleAbility.getInstance(), AttachmentType.AURA))); + + // Whenever all non-Wall creatures you control attack, enchanted creature gets +X/+0 until end of turn, where X is the number of attacking creatures. + this.addAbility(new MobMentalityTriggeredAbility()); + } + + public MobMentality(final MobMentality card) { + super(card); + } + + @Override + public MobMentality copy() { + return new MobMentality(this); + } +} + +class MobMentalityTriggeredAbility extends TriggeredAbilityImpl { + MobMentalityTriggeredAbility() { + super(Zone.BATTLEFIELD, new BoostTargetEffect(new AttackingCreatureCount(), new StaticValue(0), Duration.EndOfTurn, true)); + } + + private MobMentalityTriggeredAbility(final MobMentalityTriggeredAbility ability) { + super(ability); + } + + @Override + public MobMentalityTriggeredAbility copy() { + return new MobMentalityTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DECLARED_ATTACKERS; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (!game.getCombat().getAttackingPlayerId().equals(getControllerId())) { + return false; + } + Permanent aura = game.getPermanent(getSourceId()); + if (aura == null) { + return false; + } + Permanent creature = game.getPermanent(aura.getAttachedTo()); + if (creature == null) { + return false; + } + for (Effect effect : getEffects()) { + effect.setTargetPointer(new FixedTarget(creature, game)); + } + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(getControllerId())) { + if (permanent.isCreature() + && !permanent.hasSubtype(SubType.WALL, game) + && !permanent.isAttacking()) { + return false; + } + } + return true; + } + + @Override + public String getRule() { + return "Whenever all non-Wall creatures you control attack, " + + "enchanted creature gets +X/+0 until end of turn, " + + "where X is the number of attacking creatures."; + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/m/MomentOfSilence.java b/Mage.Sets/src/mage/cards/m/MomentOfSilence.java index 50e275a7ed0..6607ae3528b 100644 --- a/Mage.Sets/src/mage/cards/m/MomentOfSilence.java +++ b/Mage.Sets/src/mage/cards/m/MomentOfSilence.java @@ -1,11 +1,11 @@ - package mage.cards.m; import java.util.UUID; -import mage.abilities.effects.common.SkipNextCombatEffect; +import mage.abilities.effects.common.SkipCombatStepEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.Duration; import mage.target.TargetPlayer; /** @@ -13,19 +13,19 @@ import mage.target.TargetPlayer; * @author escplan9 (Derek Monturo - dmontur1 at gmail dot com) */ public final class MomentOfSilence extends CardImpl { - + public MomentOfSilence(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{W}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}"); // Target player skips their next combat phase this turn. - this.getSpellAbility().addEffect(new SkipNextCombatEffect()); + this.getSpellAbility().addEffect(new SkipCombatStepEffect(Duration.EndOfTurn).setText("Target player skips their next combat this turn")); this.getSpellAbility().addTarget(new TargetPlayer()); } - + public MomentOfSilence(final MomentOfSilence card) { super(card); } - + @Override public MomentOfSilence copy() { return new MomentOfSilence(this); diff --git a/Mage.Sets/src/mage/cards/m/MountainStronghold.java b/Mage.Sets/src/mage/cards/m/MountainStronghold.java new file mode 100644 index 00000000000..64775cba115 --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MountainStronghold.java @@ -0,0 +1,47 @@ + +package mage.cards.m; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.keyword.BandsWithOtherAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SuperType; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.filter.predicate.mageobject.SupertypePredicate; + +/** + * + * @author L_J + */ +public final class MountainStronghold extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Red legendary creatures"); + + static { + filter.add(new ColorPredicate(ObjectColor.RED)); + filter.add(new SupertypePredicate(SuperType.LEGENDARY)); + } + + public MountainStronghold(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + // Red legendary creatures you control have "bands with other legendary creatures." + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledEffect(new BandsWithOtherAbility(SuperType.LEGENDARY), Duration.WhileOnBattlefield, filter))); + } + + public MountainStronghold(final MountainStronghold card) { + super(card); + } + + @Override + public MountainStronghold copy() { + return new MountainStronghold(this); + } +} diff --git a/Mage.Sets/src/mage/cards/n/NimblePilferer.java b/Mage.Sets/src/mage/cards/n/NimblePilferer.java new file mode 100644 index 00000000000..bbd383b6642 --- /dev/null +++ b/Mage.Sets/src/mage/cards/n/NimblePilferer.java @@ -0,0 +1,36 @@ +package mage.cards.n; + +import mage.MageInt; +import mage.abilities.keyword.FlashAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class NimblePilferer extends CardImpl { + + public NimblePilferer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); + this.subtype.add(SubType.HUMAN); + this.subtype.add(SubType.ROGUE); + + this.power = new MageInt(2); + this.toughness = new MageInt(1); + + this.addAbility(FlashAbility.getInstance()); + } + + public NimblePilferer(final NimblePilferer card) { + super(card); + } + + @Override + public NimblePilferer copy() { + return new NimblePilferer(this); + } +} diff --git a/Mage.Sets/src/mage/cards/n/NoxiousRevival.java b/Mage.Sets/src/mage/cards/n/NoxiousRevival.java index 64d5e54525b..5a8ee8c05e7 100644 --- a/Mage.Sets/src/mage/cards/n/NoxiousRevival.java +++ b/Mage.Sets/src/mage/cards/n/NoxiousRevival.java @@ -2,27 +2,28 @@ package mage.cards.n; -import java.util.UUID; import mage.abilities.effects.common.PutOnLibraryTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.target.common.TargetCardInGraveyard; +import java.util.UUID; + /** - * * @author Loki */ public final class NoxiousRevival extends CardImpl { - public NoxiousRevival (UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{G/P}"); + public NoxiousRevival(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{G/P}"); + // Put target card from a graveyard on top of its owner’s library. this.getSpellAbility().addEffect(new PutOnLibraryTargetEffect(true)); this.getSpellAbility().addTarget(new TargetCardInGraveyard()); } - public NoxiousRevival (final NoxiousRevival card) { + public NoxiousRevival(final NoxiousRevival card) { super(card); } diff --git a/Mage.Sets/src/mage/cards/n/NoxiousVapors.java b/Mage.Sets/src/mage/cards/n/NoxiousVapors.java new file mode 100644 index 00000000000..1e67b13521e --- /dev/null +++ b/Mage.Sets/src/mage/cards/n/NoxiousVapors.java @@ -0,0 +1,109 @@ + +package mage.cards.n; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.filter.FilterCard; +import mage.filter.common.FilterNonlandCard; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCardInHand; + +/** + * + * @author L_J + */ +public final class NoxiousVapors extends CardImpl { + + public NoxiousVapors(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{B}{B}"); + + // Each player reveals their hand, chooses one card of each color from it, then discards all other nonland cards. + this.getSpellAbility().addEffect(new NoxiousVaporsEffect()); + + } + + public NoxiousVapors(final NoxiousVapors card) { + super(card); + } + + @Override + public NoxiousVapors copy() { + return new NoxiousVapors(this); + } +} + +class NoxiousVaporsEffect extends OneShotEffect { + + private static final FilterNonlandCard filter = new FilterNonlandCard(); + + public NoxiousVaporsEffect() { + super(Outcome.Benefit); + this.staticText = "Each player reveals their hand, chooses one card of each color from it, then discards all other nonland cards"; + } + + public NoxiousVaporsEffect(final NoxiousVaporsEffect effect) { + super(effect); + } + + @Override + public NoxiousVaporsEffect copy() { + return new NoxiousVaporsEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null) { + player.revealCards(player.getName() + "'s hand", player.getHand(), game); + } + } + + for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { + Player player = game.getPlayer(playerId); + if (player != null) { + Set chosenCards = new HashSet<>(); + chooseCardForColor(ObjectColor.WHITE, chosenCards, player, game, source); + chooseCardForColor(ObjectColor.BLUE, chosenCards, player, game, source); + chooseCardForColor(ObjectColor.BLACK, chosenCards, player, game, source); + chooseCardForColor(ObjectColor.RED, chosenCards, player, game, source); + chooseCardForColor(ObjectColor.GREEN, chosenCards, player, game, source); + + Set cards = player.getHand().getCards(game); + for (Card card : cards) { + if (card != null && !chosenCards.contains(card) && filter.match(card, game)) { + player.discard(card, source, game); + } + } + } + } + return true; + } + return false; + } + + private void chooseCardForColor(ObjectColor color, Set chosenCards, Player player, Game game, Ability source) { + FilterCard filter = new FilterCard(); + filter.add(new ColorPredicate(color)); + TargetCardInHand target = new TargetCardInHand(filter); + if (player.choose(Outcome.Benefit, target, source.getSourceId(), game)) { + Card card = game.getCard(target.getFirstTarget()); + if (card != null) { + chosenCards.add(card); + } + } + } +} diff --git a/Mage.Sets/src/mage/cards/o/OgrePainbringer.java b/Mage.Sets/src/mage/cards/o/OgrePainbringer.java new file mode 100644 index 00000000000..6a51e5b6502 --- /dev/null +++ b/Mage.Sets/src/mage/cards/o/OgrePainbringer.java @@ -0,0 +1,38 @@ +package mage.cards.o; + +import mage.MageInt; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.DamagePlayersEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.TargetController; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class OgrePainbringer extends CardImpl { + + public OgrePainbringer(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{R}"); + this.subtype.add(SubType.OGRE); + + this.power = new MageInt(7); + this.toughness = new MageInt(3); + + // When Ogre Painbringer enters the battlefield, it deals 3 damage to each player. + this.addAbility(new EntersBattlefieldTriggeredAbility(new DamagePlayersEffect(3, TargetController.ANY, "it"))); + } + + public OgrePainbringer(final OgrePainbringer card) { + super(card); + } + + @Override + public OgrePainbringer copy() { + return new OgrePainbringer(this); + } +} diff --git a/Mage.Sets/src/mage/cards/o/OldFogey.java b/Mage.Sets/src/mage/cards/o/OldFogey.java new file mode 100644 index 00000000000..4dd4ed481a2 --- /dev/null +++ b/Mage.Sets/src/mage/cards/o/OldFogey.java @@ -0,0 +1,75 @@ + +package mage.cards.o; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.keyword.BandsWithOtherAbility; +import mage.abilities.keyword.CumulativeUpkeepAbility; +import mage.abilities.keyword.EchoAbility; +import mage.abilities.keyword.FadingAbility; +import mage.abilities.keyword.FlankingAbility; +import mage.abilities.keyword.LandwalkAbility; +import mage.abilities.keyword.PhasingAbility; +import mage.abilities.keyword.ProtectionAbility; +import mage.abilities.keyword.RampageAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.FilterCard; +import mage.filter.common.FilterLandPermanent; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.filter.predicate.mageobject.SupertypePredicate; + +/** + * + * @author L_J + */ +public final class OldFogey extends CardImpl { + + private static final FilterCard filter = new FilterCard("Homarids"); + private static final FilterLandPermanent filter2 = new FilterLandPermanent("snow-covered plains"); + + static { + filter.add(new SubtypePredicate(SubType.HOMARID)); + filter2.add(new SupertypePredicate(SuperType.SNOW)); + filter2.add(new SubtypePredicate(SubType.PLAINS)); + } + + public OldFogey(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{G}{G}"); + this.subtype.add(SubType.DINOSAUR); + this.power = new MageInt(7); + this.toughness = new MageInt(7); + + // Phasing + this.addAbility(PhasingAbility.getInstance()); + // Cumulative upkeep {1} + this.addAbility(new CumulativeUpkeepAbility(new ManaCostsImpl("{1}"))); + // Echo {G}{G} + this.addAbility(new EchoAbility("{G}{G}")); + // Fading 3 + this.addAbility(new FadingAbility(3, this)); + // Bands with other Dinosaurs + this.addAbility(new BandsWithOtherAbility(SubType.DINOSAUR)); + // Protection from Homarids + this.addAbility(new ProtectionAbility(filter)); + // Snow-covered plainswalk + this.addAbility(new LandwalkAbility(filter2)); + // Flanking + this.addAbility(new FlankingAbility()); + // Rampage 2 + this.addAbility(new RampageAbility(2)); + } + + public OldFogey(final OldFogey card) { + super(card); + } + + @Override + public OldFogey copy() { + return new OldFogey(this); + } +} diff --git a/Mage.Sets/src/mage/cards/o/OpalAcrolith.java b/Mage.Sets/src/mage/cards/o/OpalAcrolith.java new file mode 100644 index 00000000000..235bf3a3620 --- /dev/null +++ b/Mage.Sets/src/mage/cards/o/OpalAcrolith.java @@ -0,0 +1,77 @@ +package mage.cards.o; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.TriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.common.SpellCastOpponentTriggeredAbility; +import mage.abilities.condition.common.SourceMatchesFilterCondition; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; +import mage.abilities.effects.common.continuous.BecomesEnchantmentSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.FilterSpell; +import mage.filter.StaticFilters; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.permanent.token.TokenImpl; + +/** + * + * @author jeffwadsworth + */ +public final class OpalAcrolith extends CardImpl { + + private static final FilterSpell filter = new FilterSpell("creature spell"); + + static { + filter.add(new CardTypePredicate(CardType.CREATURE)); + } + + public OpalAcrolith(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}"); + + // Whenever an opponent casts a creature spell, if Opal Acrolith is an enchantment, Opal Acrolith becomes a 2/4 Soldier creature. + TriggeredAbility ability = new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect(new OpalAcrolithToken(), "", Duration.WhileOnBattlefield, true, false), + filter, false); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_ENCHANTMENT_PERMANENT), + "Whenever an opponent casts a creature spell, if Opal Acrolith is an enchantment, Opal Acrolith becomes a 2/4 Soldier creature.")); + + // {0}: Opal Acrolith becomes an enchantment. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BecomesEnchantmentSourceEffect(), new ManaCostsImpl("{0}"))); + + } + + public OpalAcrolith(final OpalAcrolith card) { + super(card); + } + + @Override + public OpalAcrolith copy() { + return new OpalAcrolith(this); + } +} + +class OpalAcrolithToken extends TokenImpl { + + public OpalAcrolithToken() { + super("Soldier", "2/4 Soldier creature"); + cardType.add(CardType.CREATURE); + subtype.add(SubType.SOLDIER); + power = new MageInt(2); + toughness = new MageInt(4); + } + + public OpalAcrolithToken(final OpalAcrolithToken token) { + super(token); + } + + public OpalAcrolithToken copy() { + return new OpalAcrolithToken(this); + } +} diff --git a/Mage.Sets/src/mage/cards/o/OpalAvenger.java b/Mage.Sets/src/mage/cards/o/OpalAvenger.java new file mode 100644 index 00000000000..cc28e074245 --- /dev/null +++ b/Mage.Sets/src/mage/cards/o/OpalAvenger.java @@ -0,0 +1,126 @@ +package mage.cards.o; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.StateTriggeredAbility; +import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.token.TokenImpl; + +/** + * + * @author jeffwadsworth + */ +public final class OpalAvenger extends CardImpl { + + public OpalAvenger(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}"); + + // When you have 10 or less life, if Opal Avenger is an enchantment, Opal Avenger becomes a 3/5 Soldier creature. + this.addAbility(new OpalAvengerStateTriggeredAbility()); + } + + public OpalAvenger(final OpalAvenger card) { + super(card); + } + + @Override + public OpalAvenger copy() { + return new OpalAvenger(this); + } +} + +class OpalAvengerStateTriggeredAbility extends StateTriggeredAbility { + + public OpalAvengerStateTriggeredAbility() { + super(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(new OpalAvengerToken(), "", Duration.Custom, true, false)); + } + + public OpalAvengerStateTriggeredAbility(final OpalAvengerStateTriggeredAbility ability) { + super(ability); + } + + @Override + public OpalAvengerStateTriggeredAbility copy() { + return new OpalAvengerStateTriggeredAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (game.getState().getPlayer(getControllerId()) != null) { + return game.getState().getPlayer(getControllerId()).getLife() <= 10; + } + return false; + } + + @Override + public boolean checkInterveningIfClause(Game game) { + if (getSourcePermanentIfItStillExists(game) != null) { + return getSourcePermanentIfItStillExists(game).isEnchantment(); + } + return false; + } + + @Override + public boolean canTrigger(Game game) { + //20100716 - 603.8 + Boolean triggered = (Boolean) game.getState().getValue(getSourceId().toString() + "triggered"); + if (triggered == null) { + triggered = Boolean.FALSE; + } + return !triggered; + } + + @Override + public void trigger(Game game, UUID controllerId) { + //20100716 - 603.8 + game.getState().setValue(this.getSourceId().toString() + "triggered", Boolean.TRUE); + super.trigger(game, controllerId); + } + + @Override + public boolean resolve(Game game) { + //20100716 - 603.8 + boolean result = super.resolve(game); + game.getState().setValue(this.getSourceId().toString() + "triggered", Boolean.FALSE); + return result; + } + + @Override + public void counter(Game game) { + game.getState().setValue(this.getSourceId().toString() + "triggered", Boolean.FALSE); + } + + @Override + public String getRule() { + return new StringBuilder("When you have 10 or less life, if {this} is an enchantment, ").append(super.getRule()).toString(); + } + +} + +class OpalAvengerToken extends TokenImpl { + + public OpalAvengerToken() { + super("Soldier", "3/5 Soldier creature"); + cardType.add(CardType.CREATURE); + subtype.add(SubType.SOLDIER); + power = new MageInt(3); + toughness = new MageInt(5); + } + + public OpalAvengerToken(final OpalAvengerToken token) { + super(token); + } + + @Override + public OpalAvengerToken copy() { + return new OpalAvengerToken(this); + } +} diff --git a/Mage.Sets/src/mage/cards/o/OpalTitan.java b/Mage.Sets/src/mage/cards/o/OpalTitan.java new file mode 100644 index 00000000000..1f215472b72 --- /dev/null +++ b/Mage.Sets/src/mage/cards/o/OpalTitan.java @@ -0,0 +1,145 @@ +package mage.cards.o; + +import java.util.UUID; +import mage.MageObjectReference; +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbility; +import mage.abilities.common.SpellCastOpponentTriggeredAbility; +import mage.abilities.condition.common.SourceMatchesFilterCondition; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.common.continuous.SourceEffect; +import mage.abilities.keyword.ProtectionAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.DependencyType; +import mage.constants.Duration; +import mage.constants.Layer; +import static mage.constants.Layer.AbilityAddingRemovingEffects_6; +import static mage.constants.Layer.PTChangingEffects_7; +import static mage.constants.Layer.TypeChangingEffects_4; +import mage.constants.Outcome; +import mage.constants.SetTargetPointer; +import mage.constants.SubLayer; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.FilterSpell; +import mage.filter.StaticFilters; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.stack.Spell; + +/** + * + * @author jeffwadsworth + */ +public final class OpalTitan extends CardImpl { + + private static final FilterSpell filter = new FilterSpell("creature spell"); + + static { + filter.add(new CardTypePredicate(CardType.CREATURE)); + } + + public OpalTitan(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{W}{W}"); + + // When an opponent casts a creature spell, if Opal Titan is an enchantment, Opal Titan becomes a 4/4 Giant creature with protection from each of that spell's colors. + TriggeredAbility ability = new SpellCastOpponentTriggeredAbility(Zone.BATTLEFIELD, new OpalTitanBecomesCreatureEffect(), + filter, false, SetTargetPointer.SPELL); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_ENCHANTMENT_PERMANENT), + "When an opponent casts a creature spell, if Opal Titan is an enchantment, Opal Titan becomes a 4/4 Giant creature with protection from each of that spell's colors.")); + + } + + public OpalTitan(final OpalTitan card) { + super(card); + } + + @Override + public OpalTitan copy() { + return new OpalTitan(this); + } +} + +class OpalTitanBecomesCreatureEffect extends ContinuousEffectImpl implements SourceEffect { + + public OpalTitanBecomesCreatureEffect() { + super(Duration.WhileOnBattlefield, Outcome.BecomeCreature); + staticText = "{this} becomes a 4/4 Giant creature with protection from each of that spell's colors."; + this.addDependencyType(DependencyType.BecomeCreature); + } + + public OpalTitanBecomesCreatureEffect(final OpalTitanBecomesCreatureEffect effect) { + super(effect); + } + + @Override + public OpalTitanBecomesCreatureEffect copy() { + return new OpalTitanBecomesCreatureEffect(this); + } + + @Override + public void init(Ability source, Game game) { + super.init(source, game); + affectedObjectList.add(new MageObjectReference(source.getSourceId(), game)); + Spell creatureSpellCast = game.getSpell(targetPointer.getFirst(game, source)); + if (creatureSpellCast != null + && creatureSpellCast.getColor(game).hasColor()) { + game.getState().setValue("opalTitanColor" + source.getSourceId(), creatureSpellCast.getColor(game)); + } + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + Permanent permanent = affectedObjectList.get(0).getPermanent(game); + if (permanent != null) { + switch (layer) { + case TypeChangingEffects_4: + if (sublayer == SubLayer.NA) { + permanent.getCardType().clear(); + permanent.addCardType(CardType.CREATURE); + permanent.getSubtype(game).add(SubType.GIANT); + } + break; + case AbilityAddingRemovingEffects_6: + if (sublayer == SubLayer.NA) { + if (((ObjectColor) game.getState().getValue("opalTitanColor" + source.getSourceId())) != null) { + for (ObjectColor color : ((ObjectColor) game.getState().getValue("opalTitanColor" + source.getSourceId())).getColors()) { + if (!permanent.getAbilities().contains(ProtectionAbility.from(color))) { + permanent.addAbility(ProtectionAbility.from(color)); + } + } + } + } + break; + case PTChangingEffects_7: + if ((sublayer == SubLayer.CharacteristicDefining_7a) + || (sublayer == SubLayer.SetPT_7b)) { + permanent.getPower().setValue(4); + permanent.getToughness().setValue(4); + } + break; + } + return true; + } + this.discard(); + return false; + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } + + @Override + public boolean hasLayer(Layer layer) { + return layer == Layer.PTChangingEffects_7 + || layer == Layer.AbilityAddingRemovingEffects_6 + || layer == Layer.TypeChangingEffects_4; + } + +} diff --git a/Mage.Sets/src/mage/cards/o/OuterRimSlaver.java b/Mage.Sets/src/mage/cards/o/OuterRimSlaver.java index 98ea2f4b723..438ca1a7292 100644 --- a/Mage.Sets/src/mage/cards/o/OuterRimSlaver.java +++ b/Mage.Sets/src/mage/cards/o/OuterRimSlaver.java @@ -1,4 +1,3 @@ - package mage.cards.o; import java.util.UUID; @@ -30,12 +29,13 @@ public final class OuterRimSlaver extends CardImpl { this.toughness = new MageInt(3); // When Outer Rim Slaver enters the battlefield, you may put a bounty counter on target creature. If you do, another target creature fights that creature - Ability ability = new EntersBattlefieldTriggeredAbility(new AddCountersTargetEffect(CounterType.BOUNTY.createInstance()), true); - ability.addEffect(new FightTargetsEffect("another target creature fights that creature")); - TargetCreaturePermanent target = new TargetCreaturePermanent(); + Ability ability = new EntersBattlefieldTriggeredAbility(new AddCountersTargetEffect(CounterType.BOUNTY.createInstance()) + .setText("you may put a bounty counter on target creature"), true); + ability.addEffect(new FightTargetsEffect("If you do, another target creature fights that creature")); + TargetCreaturePermanent target = new TargetCreaturePermanent(new FilterCreaturePermanent("creature to put a bounty counter on it")); target.setTargetTag(1); ability.addTarget(target); - FilterCreaturePermanent filter = new FilterCreaturePermanent(); + FilterCreaturePermanent filter = new FilterCreaturePermanent("another creature to fight that creature that gets the bounty counter"); filter.add(new AnotherTargetPredicate(2)); TargetCreaturePermanent target2 = new TargetCreaturePermanent(filter); target2.setTargetTag(2); diff --git a/Mage.Sets/src/mage/cards/o/Outmaneuver.java b/Mage.Sets/src/mage/cards/o/Outmaneuver.java new file mode 100644 index 00000000000..3a604f97782 --- /dev/null +++ b/Mage.Sets/src/mage/cards/o/Outmaneuver.java @@ -0,0 +1,96 @@ +package mage.cards.o; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.SpellAbility; +import mage.abilities.effects.AsThoughEffectImpl; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AsThoughEffectType; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.BlockedPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author jeffwadsworth + */ +public final class Outmaneuver extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); + + static { + filter.add(new BlockedPredicate()); + } + + public Outmaneuver(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{R}"); + + // X target blocked creatures assign their combat damage this turn as though they weren't blocked. + this.getSpellAbility().addEffect(new OutmaneuverEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + + } + + public Outmaneuver(final Outmaneuver card) { + super(card); + } + + @Override + public Outmaneuver copy() { + return new Outmaneuver(this); + } + + @Override + public void adjustTargets(Ability ability, Game game) { + if (ability instanceof SpellAbility) { + ability.getTargets().clear(); + int numberOfTargets = ability.getManaCostsToPay().getX(); + numberOfTargets = Math.min(game.getBattlefield().getAllActivePermanents(filter, + ability.getControllerId(), game).size(), numberOfTargets); + ability.addTarget(new TargetCreaturePermanent(numberOfTargets, + numberOfTargets, filter, false)); + } + } +} + +class OutmaneuverEffect extends AsThoughEffectImpl { + + public OutmaneuverEffect() { + super(AsThoughEffectType.DAMAGE_NOT_BLOCKED, Duration.EndOfTurn, Outcome.Damage); + this.staticText = "X target blocked creatures assign their combat damage this turn as though they weren't blocked."; + } + + public OutmaneuverEffect(OutmaneuverEffect effect) { + super(effect); + } + + @Override + public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { + Permanent blockedCreature = game.getPermanent(sourceId); + if (blockedCreature != null) { + Player controller = game.getPlayer(blockedCreature.getControllerId()); + if (controller != null) { + return controller.chooseUse(Outcome.Damage, "Do you wish to assign combat damage for " + + blockedCreature.getLogName() + " as though it weren't blocked?", source, game); + } + } + return false; + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public OutmaneuverEffect copy() { + return new OutmaneuverEffect(this); + } +} diff --git a/Mage.Sets/src/mage/cards/p/PemminsAura.java b/Mage.Sets/src/mage/cards/p/PemminsAura.java index 89139bc99de..4cd260a1acf 100644 --- a/Mage.Sets/src/mage/cards/p/PemminsAura.java +++ b/Mage.Sets/src/mage/cards/p/PemminsAura.java @@ -1,7 +1,6 @@ package mage.cards.p; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; @@ -17,20 +16,16 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.choices.Choice; import mage.choices.ChoiceImpl; -import mage.constants.AttachmentType; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.SubType; -import mage.constants.Zone; +import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetPermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class PemminsAura extends CardImpl { @@ -94,21 +89,28 @@ class PemminsAuraBoostEnchantedEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); Permanent enchantment = game.getPermanent(source.getSourceId()); - Permanent creature = game.getPermanent(enchantment.getAttachedTo()); - if (controller != null && creature != null) { - Choice choice = new ChoiceImpl(true); - choice.setMessage("Select how to boost"); - choice.getChoices().add(CHOICE_1); - choice.getChoices().add(CHOICE_2); - if (controller.choose(outcome, choice, game)) { - if (choice.getChoice().equals(CHOICE_1)) { - game.addEffect(new BoostEnchantedEffect(+1, -1, Duration.EndOfTurn), source); - } else { - game.addEffect(new BoostEnchantedEffect(-1, +1, Duration.EndOfTurn), source); - } - return true; - } + if (controller == null || enchantment == null) { + return false; } + + Permanent creature = game.getPermanent(enchantment.getAttachedTo()); + if (creature == null) { + return false; + } + + Choice choice = new ChoiceImpl(true); + choice.setMessage("Select how to boost"); + choice.getChoices().add(CHOICE_1); + choice.getChoices().add(CHOICE_2); + if (controller.choose(outcome, choice, game)) { + if (choice.getChoice().equals(CHOICE_1)) { + game.addEffect(new BoostEnchantedEffect(+1, -1, Duration.EndOfTurn), source); + } else { + game.addEffect(new BoostEnchantedEffect(-1, +1, Duration.EndOfTurn), source); + } + return true; + } + return false; } } diff --git a/Mage.Sets/src/mage/cards/p/PermeatingMass.java b/Mage.Sets/src/mage/cards/p/PermeatingMass.java index 58a7466de34..286739e23c1 100644 --- a/Mage.Sets/src/mage/cards/p/PermeatingMass.java +++ b/Mage.Sets/src/mage/cards/p/PermeatingMass.java @@ -1,4 +1,3 @@ - package mage.cards.p; import java.util.UUID; @@ -9,9 +8,9 @@ import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; import mage.constants.Outcome; +import mage.constants.SubType; import mage.game.Game; import mage.game.permanent.Permanent; import mage.util.functions.EmptyApplyToPermanent; @@ -23,7 +22,7 @@ import mage.util.functions.EmptyApplyToPermanent; public final class PermeatingMass extends CardImpl { public PermeatingMass(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}"); this.subtype.add(SubType.SPIRIT); this.power = new MageInt(1); this.toughness = new MageInt(3); @@ -62,7 +61,7 @@ class PermeatingMassEffect extends OneShotEffect { public boolean apply(Game game, Ability ability) { Permanent copyTo = game.getPermanentOrLKIBattlefield(getTargetPointer().getFirst(game, ability)); if (copyTo != null) { - Permanent copyFrom = (Permanent) ability.getSourceObject(game); + Permanent copyFrom = ability.getSourcePermanentOrLKI(game); if (copyFrom != null) { game.copyPermanent(Duration.Custom, copyFrom, copyTo.getId(), ability, new EmptyApplyToPermanent()); } diff --git a/Mage.Sets/src/mage/cards/p/Portcullis.java b/Mage.Sets/src/mage/cards/p/Portcullis.java index c238942678d..5a5f9ae6006 100644 --- a/Mage.Sets/src/mage/cards/p/Portcullis.java +++ b/Mage.Sets/src/mage/cards/p/Portcullis.java @@ -2,24 +2,30 @@ package mage.cards.p; import java.util.UUID; import mage.abilities.Ability; +import mage.abilities.DelayedTriggeredAbility; import mage.abilities.TriggeredAbility; import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; -import mage.abilities.common.LeavesBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.ReturnFromExileForSourceEffect; +import mage.abilities.effects.common.ReturnToBattlefieldUnderOwnerControlTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.SetTargetPointer; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.game.events.ZoneChangeEvent; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.targetpointer.FixedTarget; import mage.util.CardUtil; /** @@ -34,14 +40,14 @@ public final class Portcullis extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); // Whenever a creature enters the battlefield, if there are two or more other creatures on the battlefield, exile that creature. - String rule = "Whenever a creature enters the battlefield, if there are two or more other creatures on the battlefield, exile that creature"; - TriggeredAbility ability = new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new PortcullisExileEffect(), filter, false, SetTargetPointer.PERMANENT, rule); - MoreThanXCreaturesOnBFCondition condition = new MoreThanXCreaturesOnBFCondition(2); - this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, condition, rule)); - // Return that card to the battlefield under its owner's control when Portcullis leaves the battlefield. - Ability ability2 = new LeavesBattlefieldTriggeredAbility(new ReturnFromExileForSourceEffect(Zone.BATTLEFIELD), false); - this.addAbility(ability2); + String rule = "Whenever a creature enters the battlefield, if there are two or more other creatures on the battlefield, exile that creature."; + String rule2 = " Return that card to the battlefield under its owner's control when {this} leaves the battlefield."; + TriggeredAbility ability = new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new PortcullisExileEffect(), + filter, false, SetTargetPointer.PERMANENT, rule); + MoreThanXCreaturesOnBFCondition condition = new MoreThanXCreaturesOnBFCondition(2); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, condition, rule + rule2)); + } public Portcullis(final Portcullis card) { @@ -74,8 +80,8 @@ class MoreThanXCreaturesOnBFCondition implements Condition { class PortcullisExileEffect extends OneShotEffect { public PortcullisExileEffect() { - super(Outcome.Neutral); - this.staticText = "Whenever a creature enters the battlefield, if there are two or more other creatures on the battlefield, exile that creature."; + super(Outcome.Exile); + this.staticText = "Whenever a creature enters the battlefield, if there are two or more other creatures on the battlefield, exile that creature"; } public PortcullisExileEffect(final PortcullisExileEffect effect) { @@ -89,20 +95,58 @@ class PortcullisExileEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent creature = game.getPermanent(targetPointer.getFirst(game, source)); - - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent == null) { - permanent = (Permanent) game.getLastKnownInformation(source.getSourceId(), Zone.BATTLEFIELD); + Permanent creatureToExile = game.getPermanent(getTargetPointer().getFirst(game, source)); + Permanent portcullis = game.getPermanent(source.getSourceId()); + Player controller = game.getPlayer(source.getControllerId()); + if (portcullis != null + && creatureToExile != null + && controller != null) { + UUID exileZoneId = CardUtil.getExileZoneId(game, creatureToExile.getId(), creatureToExile.getZoneChangeCounter(game)); + controller.moveCardsToExile(creatureToExile, source, game, true, exileZoneId, portcullis.getName()); + FixedTarget fixedTarget = new FixedTarget(portcullis, game); + Effect returnEffect = new ReturnToBattlefieldUnderOwnerControlTargetEffect(); + returnEffect.setTargetPointer(new FixedTarget(creatureToExile.getId(), game.getState().getZoneChangeCounter(creatureToExile.getId()))); + DelayedTriggeredAbility delayedAbility = new PortcullisReturnToBattlefieldTriggeredAbility(fixedTarget, returnEffect); + game.addDelayedTriggeredAbility(delayedAbility, source); } - if (permanent != null && creature != null) { - Player controller = game.getPlayer(creature.getControllerId()); - Zone currentZone = game.getState().getZone(creature.getId()); - if (currentZone == Zone.BATTLEFIELD) { - controller.moveCardsToExile(creature, source, game, true, CardUtil.getCardExileZoneId(game, source), permanent.getIdName()); - return true; - } + return true; + } +} + +class PortcullisReturnToBattlefieldTriggeredAbility extends DelayedTriggeredAbility { + + protected FixedTarget fixedTarget; + + public PortcullisReturnToBattlefieldTriggeredAbility(FixedTarget fixedTarget, Effect effect) { + super(effect, Duration.OneUse); + this.fixedTarget = fixedTarget; + } + + public PortcullisReturnToBattlefieldTriggeredAbility(final PortcullisReturnToBattlefieldTriggeredAbility ability) { + super(ability); + this.fixedTarget = ability.fixedTarget; + } + + @Override + public PortcullisReturnToBattlefieldTriggeredAbility copy() { + return new PortcullisReturnToBattlefieldTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == EventType.ZONE_CHANGE; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + if (((ZoneChangeEvent) event).getFromZone().match(Zone.BATTLEFIELD)) { + return (fixedTarget.getTarget().equals(event.getTargetId())); } return false; } + + @Override + public String getRule() { + return "Return this card to the battlefield under its owner's control when Portcullis leaves the battlefield."; + } } diff --git a/Mage.Sets/src/mage/cards/p/PowerTaint.java b/Mage.Sets/src/mage/cards/p/PowerTaint.java new file mode 100644 index 00000000000..c985eabd112 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PowerTaint.java @@ -0,0 +1,61 @@ +package mage.cards.p; + +import java.util.UUID; +import mage.constants.SubType; +import mage.target.common.TargetEnchantmentPermanent; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.effects.common.AttachEffect; +import mage.constants.Outcome; +import mage.target.TargetPermanent; +import mage.abilities.keyword.EnchantAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DoUnlessTargetPlayerOrTargetsControllerPaysEffect; +import mage.abilities.effects.common.LoseLifeTargetEffect; +import mage.abilities.keyword.CyclingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetController; +import mage.constants.Zone; + +/** + * + * @author jeffwadsworth + */ +public final class PowerTaint extends CardImpl { + + public PowerTaint(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}"); + + this.subtype.add(SubType.AURA); + + // Enchant enchantment + TargetPermanent auraTarget = new TargetEnchantmentPermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.Detriment)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // At the beginning of the upkeep of enchanted enchantment's controller, that player loses 2 life unless he or she pays {2}. + Effect effect = new DoUnlessTargetPlayerOrTargetsControllerPaysEffect(new LoseLifeTargetEffect(2), + new ManaCostsImpl("{2}"), "that player loses 2 life unless he or she pays {2}"); + this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, effect, + TargetController.CONTROLLER_ATTACHED_TO, false, true, + "At the beginning of the upkeep of enchanted enchantment's controller, ")); + + // Cycling {2} + this.addAbility(new CyclingAbility(new ManaCostsImpl("{2}"))); + + } + + public PowerTaint(final PowerTaint card) { + super(card); + } + + @Override + public PowerTaint copy() { + return new PowerTaint(this); + } +} diff --git a/Mage.Sets/src/mage/cards/p/PredatoryFocus.java b/Mage.Sets/src/mage/cards/p/PredatoryFocus.java index 807f5249596..46311e34e0d 100644 --- a/Mage.Sets/src/mage/cards/p/PredatoryFocus.java +++ b/Mage.Sets/src/mage/cards/p/PredatoryFocus.java @@ -1,12 +1,8 @@ package mage.cards.p; import java.util.UUID; - -import mage.MageObject; import mage.abilities.Ability; -import mage.abilities.effects.AsThoughEffect; import mage.abilities.effects.AsThoughEffectImpl; -import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.AsThoughEffectType; @@ -24,7 +20,6 @@ public final class PredatoryFocus extends CardImpl { public PredatoryFocus(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{G}{G}"); - // You may have creatures you control assign their combat damage this turn as though they weren't blocked. this.getSpellAbility().addEffect(new PredatoryFocusEffect()); @@ -58,10 +53,10 @@ class PredatoryFocusEffect extends AsThoughEffectImpl { super.init(source, game); Player controller = game.getPlayer(source.getControllerId()); String sourceName = source.getSourceObject(game).getLogName(); - choseUse = controller.chooseUse(Outcome.Damage, "Have creatures you control deal combat damage this turn" + - " as though they weren't blocked?", source, game); - game.informPlayers(choseUse ? controller.getName()+" chose to use "+sourceName+"'s effect" : - controller.getName()+" chose not to use "+sourceName+"'s effect."); + choseUse = controller.chooseUse(Outcome.Damage, "Have creatures you control deal combat damage this turn" + + " as though they weren't blocked?", source, game); + game.informPlayers(choseUse ? controller.getName() + " chose to use " + sourceName + "'s effect" + : controller.getName() + " chose not to use " + sourceName + "'s effect."); } @Override @@ -78,4 +73,4 @@ class PredatoryFocusEffect extends AsThoughEffectImpl { public PredatoryFocusEffect copy() { return new PredatoryFocusEffect(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/p/PrivateResearch.java b/Mage.Sets/src/mage/cards/p/PrivateResearch.java new file mode 100644 index 00000000000..bef10ca1c29 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PrivateResearch.java @@ -0,0 +1,60 @@ +package mage.cards.p; + +import java.util.UUID; +import mage.constants.SubType; +import mage.target.common.TargetCreaturePermanent; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.DiesAttachedTriggeredAbility; +import mage.abilities.dynamicvalue.common.CountersSourceCount; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.constants.Outcome; +import mage.target.TargetPermanent; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; + +/** + * + * @author jeffwadsworth + */ +public final class PrivateResearch extends CardImpl { + + private static final String rule = "draw a card for each page counter on {this}."; + + public PrivateResearch(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{U}"); + + this.subtype.add(SubType.AURA); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // At the beginning of your upkeep, you may put a page counter on Private Research. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, + new AddCountersSourceEffect(CounterType.PAGE.createInstance(), true), TargetController.YOU, true)); + + // When enchanted creature dies, draw a card for each page counter on Private Research. + this.addAbility(new DiesAttachedTriggeredAbility(new DrawCardSourceControllerEffect(new CountersSourceCount(CounterType.PAGE)).setText(rule), "enchanted creature")); + + } + + public PrivateResearch(final PrivateResearch card) { + super(card); + } + + @Override + public PrivateResearch copy() { + return new PrivateResearch(this); + } +} diff --git a/Mage.Sets/src/mage/cards/p/PulseOfLlanowar.java b/Mage.Sets/src/mage/cards/p/PulseOfLlanowar.java new file mode 100644 index 00000000000..e4ae658497b --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PulseOfLlanowar.java @@ -0,0 +1,98 @@ + +package mage.cards.p; + +import java.util.UUID; +import mage.MageObject; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.abilities.effects.mana.AddManaOfAnyColorEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SuperType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.SupertypePredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.game.events.ManaEvent; +import mage.game.permanent.Permanent; + +/** + * + * @author L_J + */ +public final class PulseOfLlanowar extends CardImpl { + + public PulseOfLlanowar(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{G}"); + + // If a basic land you control is tapped for mana, it produces mana of a color of your choice instead of any other type. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PulseOfLlanowarReplacementEffect())); + } + + public PulseOfLlanowar(final PulseOfLlanowar card) { + super(card); + } + + @Override + public PulseOfLlanowar copy() { + return new PulseOfLlanowar(this); + } +} + +class PulseOfLlanowarReplacementEffect extends ReplacementEffectImpl { + + private static final FilterControlledPermanent filter = new FilterControlledPermanent(); + static { + filter.add(new SupertypePredicate(SuperType.BASIC)); + } + + PulseOfLlanowarReplacementEffect() { + super(Duration.WhileOnBattlefield, Outcome.Neutral); + staticText = "If a basic land you control is tapped for mana, it produces mana of a color of your choice instead of any other type"; + } + + PulseOfLlanowarReplacementEffect(final PulseOfLlanowarReplacementEffect effect) { + super(effect); + } + + @Override + public PulseOfLlanowarReplacementEffect copy() { + return new PulseOfLlanowarReplacementEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + ManaEvent manaEvent = (ManaEvent) event; + Mana mana = manaEvent.getMana(); + new AddManaOfAnyColorEffect(mana.count()).apply(game,source); + mana.setToMana(new Mana(0,0,0,0,0,0,0,0)); + return true; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.TAPPED_FOR_MANA; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + MageObject mageObject = game.getObject(event.getSourceId()); + if (mageObject != null && mageObject.isLand()) { + Permanent land = game.getPermanent(event.getSourceId()); + return land != null && filter.match(land, game); + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/r/RevenantPatriarch.java b/Mage.Sets/src/mage/cards/r/RevenantPatriarch.java index 50b1fd07e85..e770b5d4397 100644 --- a/Mage.Sets/src/mage/cards/r/RevenantPatriarch.java +++ b/Mage.Sets/src/mage/cards/r/RevenantPatriarch.java @@ -1,4 +1,3 @@ - package mage.cards.r; import java.util.UUID; @@ -8,12 +7,13 @@ import mage.abilities.common.CantBlockAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.common.ManaWasSpentCondition; import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.effects.common.SkipNextCombatEffect; +import mage.abilities.effects.common.SkipCombatStepEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.ColoredManaSymbol; +import mage.constants.Duration; import mage.target.TargetPlayer; import mage.watchers.common.ManaSpentToCastWatcher; @@ -22,26 +22,26 @@ import mage.watchers.common.ManaSpentToCastWatcher; * @author ilcartographer */ public final class RevenantPatriarch extends CardImpl { - + public RevenantPatriarch(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{B}"); this.subtype.add(SubType.SPIRIT); this.power = new MageInt(4); this.toughness = new MageInt(3); // When Revenant Patriarch enters the battlefield, if {W} was spent to cast it, target player skips their next combat phase. - TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new SkipNextCombatEffect(), false); + TriggeredAbility ability = new EntersBattlefieldTriggeredAbility(new SkipCombatStepEffect(Duration.OneUse).setText("target player skips their next combat phase."), false); ability.addTarget(new TargetPlayer()); this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new ManaWasSpentCondition(ColoredManaSymbol.W), "if {W} was spent to cast it, target player skips their next combat phase."), new ManaSpentToCastWatcher()); // Revenant Patriarch can't block. this.addAbility(new CantBlockAbility()); } - + public RevenantPatriarch(final RevenantPatriarch card) { super(card); } - + @Override public RevenantPatriarch copy() { return new RevenantPatriarch(this); diff --git a/Mage.Sets/src/mage/cards/r/Reverberation.java b/Mage.Sets/src/mage/cards/r/Reverberation.java new file mode 100644 index 00000000000..0a0768ae700 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/Reverberation.java @@ -0,0 +1,105 @@ + +package mage.cards.r; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.filter.FilterSpell; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.game.Game; +import mage.game.events.DamageEvent; +import mage.game.events.GameEvent; +import mage.game.stack.Spell; +import mage.players.Player; +import mage.target.TargetSpell; + +/** + * + * @author L_J + */ +public final class Reverberation extends CardImpl { + + private static final FilterSpell filter = new FilterSpell("sorcery spell"); + + static { + filter.add(new CardTypePredicate(CardType.SORCERY)); + } + + public Reverberation(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}{U}"); + + // All damage that would be dealt this turn by target sorcery spell is dealt to that spell’s controller instead. + this.getSpellAbility().addEffect(new ReverberationEffect()); + this.getSpellAbility().addTarget(new TargetSpell(filter)); + } + + public Reverberation(final Reverberation card) { + super(card); + } + + @Override + public Reverberation copy() { + return new Reverberation(this); + } +} + +class ReverberationEffect extends ReplacementEffectImpl { + + public ReverberationEffect() { + super(Duration.EndOfTurn, Outcome.RedirectDamage); + staticText = "All damage that would be dealt this turn by target sorcery spell is dealt to that spell’s controller instead"; + } + + public ReverberationEffect(final ReverberationEffect effect) { + super(effect); + } + + @Override + public ReverberationEffect copy() { + return new ReverberationEffect(this); + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGE_CREATURE || + event.getType() == GameEvent.EventType.DAMAGE_PLANESWALKER || + event.getType() == GameEvent.EventType.DAMAGE_PLAYER; + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + Player controller = game.getPlayer(source.getControllerId()); + DamageEvent damageEvent = (DamageEvent) event; + if (controller != null) { + Spell targetSpell = game.getStack().getSpell(source.getFirstTarget()); + if (targetSpell != null) { + Player targetsController = game.getPlayer(targetSpell.getControllerId()); + if (targetsController != null) { + targetsController.damage(damageEvent.getAmount(), damageEvent.getSourceId(), game, damageEvent.isCombatDamage(), damageEvent.isPreventable(), damageEvent.getAppliedEffects()); + return true; + } + } + } + return false; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + DamageEvent damageEvent = (DamageEvent) event; + Spell targetSpell = game.getStack().getSpell(source.getFirstTarget()); + if (targetSpell != null) { + return damageEvent.getAmount() > 0; + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/r/RiversFavor.java b/Mage.Sets/src/mage/cards/r/RiversFavor.java new file mode 100644 index 00000000000..523500e1ed2 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RiversFavor.java @@ -0,0 +1,47 @@ +package mage.cards.r; + +import mage.abilities.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.continuous.BoostEnchantedEffect; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.target.TargetPermanent; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class RiversFavor extends CardImpl { + + public RiversFavor(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{U}"); + this.subtype.add(SubType.AURA); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // Enchanted creature gets +1/+1. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEnchantedEffect(1, 1))); + } + + public RiversFavor(final RiversFavor card) { + super(card); + } + + @Override + public RiversFavor copy() { + return new RiversFavor(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/r/RotHulk.java b/Mage.Sets/src/mage/cards/r/RotHulk.java new file mode 100644 index 00000000000..152f27ddcac --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RotHulk.java @@ -0,0 +1,72 @@ +package mage.cards.r; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.dynamicvalue.common.OpponentsCount; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; +import mage.abilities.keyword.MenaceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.game.Game; +import mage.target.common.TargetCardInYourGraveyard; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class RotHulk extends CardImpl { + + private static final FilterCard filterZombie = new FilterCard("Zombie cards from your graveyard"); + + static { + filterZombie.add(new SubtypePredicate(SubType.ZOMBIE)); + } + + private final UUID entersBattlefieldAbilityID; + + public RotHulk(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{B}{B}"); + this.subtype.add(SubType.ZOMBIE); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Menace + this.addAbility(new MenaceAbility(false)); + + // When Rot Hulk enters the battlefield, return up to X target Zombie cards from your graveyard to the battlefield, where X is the number of opponents you have. + Effect effect = new ReturnFromGraveyardToBattlefieldTargetEffect(); + effect.setText("return up to X target Zombie cards from your graveyard to the battlefield, where X is the number of opponents you have."); + Ability ability = new EntersBattlefieldTriggeredAbility(effect); + ability.addTarget(new TargetCardInYourGraveyard()); + entersBattlefieldAbilityID = ability.getOriginalId(); // adjust targets + this.addAbility(ability); + } + + @Override + public void adjustTargets(Ability ability, Game game) { + if (ability.getOriginalId().equals(entersBattlefieldAbilityID)) { + // up to X target Zombie cards from your graveyard + // X is the number of opponents you have. + ability.getTargets().clear(); + int numbTargets = new OpponentsCount().calculate(game, ability, null); + ability.addTarget(new TargetCardInYourGraveyard(0, numbTargets, filterZombie)); + } + } + + public RotHulk(final RotHulk card) { + super(card); + this.entersBattlefieldAbilityID = card.entersBattlefieldAbilityID; + } + + @Override + public RotHulk copy() { + return new RotHulk(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SamiteMinistration.java b/Mage.Sets/src/mage/cards/s/SamiteMinistration.java new file mode 100644 index 00000000000..5035bafdaa2 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SamiteMinistration.java @@ -0,0 +1,90 @@ + +package mage.cards.s; + +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.effects.PreventionEffectData; +import mage.abilities.effects.PreventionEffectImpl; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.players.Player; +import mage.target.TargetSource; + +/** + * + * @author L_J + */ +public final class SamiteMinistration extends CardImpl { + + public SamiteMinistration(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}"); + + // Prevent all damage that would be dealt to you this turn by a source of your choice. Whenever damage from a black or red source is prevented this way this turn, you gain that much life. + this.getSpellAbility().addEffect(new SamiteMinistrationEffect()); + } + + public SamiteMinistration(final SamiteMinistration card) { + super(card); + } + + @Override + public SamiteMinistration copy() { + return new SamiteMinistration(this); + } + +} + +class SamiteMinistrationEffect extends PreventionEffectImpl { + + private final TargetSource targetSource; + + public SamiteMinistrationEffect() { + super(Duration.EndOfTurn, Integer.MAX_VALUE, false); + this.staticText = "Prevent all damage that would be dealt to you this turn by a source of your choice. Whenever damage from a black or red source is prevented this way this turn, you gain that much life"; + this.targetSource = new TargetSource(); + } + + public SamiteMinistrationEffect(final SamiteMinistrationEffect effect) { + super(effect); + this.targetSource = effect.targetSource.copy(); + } + + @Override + public SamiteMinistrationEffect copy() { + return new SamiteMinistrationEffect(this); + } + + @Override + public void init(Ability source, Game game) { + this.targetSource.choose(Outcome.PreventDamage, source.getControllerId(), source.getSourceId(), game); + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + PreventionEffectData preventionData = preventDamageAction(event, source, game); + MageObject sourceObject = game.getObject(event.getSourceId()); + if (sourceObject.getColor(game).isBlack() || sourceObject.getColor(game).isRed()) { + Player player = game.getPlayer(source.getControllerId()); + if (player != null) { + player.gainLife(preventionData.getPreventedDamage(), game, source); + } + } + return false; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + if (super.applies(event, source, game)) { + if (event.getTargetId().equals(source.getControllerId()) && event.getSourceId().equals(targetSource.getFirstTarget())) { + return true; + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/s/SavageSummoning.java b/Mage.Sets/src/mage/cards/s/SavageSummoning.java index 2d19dea4fb8..df81be34d65 100644 --- a/Mage.Sets/src/mage/cards/s/SavageSummoning.java +++ b/Mage.Sets/src/mage/cards/s/SavageSummoning.java @@ -100,7 +100,7 @@ class SavageSummoningAsThoughEffect extends AsThoughEffectImpl { MageObject mageObject = game.getBaseObject(objectId); if (mageObject instanceof Commander) { Commander commander = (Commander) mageObject; - if (commander.isCreature() && commander.getControllerId().equals(source.getControllerId())) { + if (commander.isCreature() && commander.isControlledBy(source.getControllerId())) { return true; } } else if (mageObject instanceof Card) { diff --git a/Mage.Sets/src/mage/cards/s/ScepterOfEmpires.java b/Mage.Sets/src/mage/cards/s/ScepterOfEmpires.java index 5907583effb..8455a23f8b2 100644 --- a/Mage.Sets/src/mage/cards/s/ScepterOfEmpires.java +++ b/Mage.Sets/src/mage/cards/s/ScepterOfEmpires.java @@ -5,7 +5,6 @@ import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -25,8 +24,7 @@ public final class ScepterOfEmpires extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); // {tap}: Scepter of Empires deals 1 damage to target player. It deals 3 damage to that player instead if you control artifacts named Crown of Empires and Throne of Empires. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ScepterOfEmpiresEffect(), new GenericManaCost(0)); - ability.addCost(new TapSourceCost()); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ScepterOfEmpiresEffect(), new TapSourceCost()); ability.addTarget(new TargetPlayerOrPlaneswalker()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/ScryingGlass.java b/Mage.Sets/src/mage/cards/s/ScryingGlass.java new file mode 100644 index 00000000000..8f53b6f0333 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/ScryingGlass.java @@ -0,0 +1,87 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.choices.ChoiceColor; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetOpponent; + +/** + * + * @author jeffwadsworth + */ +public final class ScryingGlass extends CardImpl { + + public ScryingGlass(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); + + // {3}, {tap}: Choose a number greater than 0 and a color. Target opponent reveals his or her hand. If that opponent reveals exactly the chosen number of cards of the chosen color, you draw a card. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ScryingGlassEffect(), new ManaCostsImpl("{3}")); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetOpponent()); + this.addAbility(ability); + + } + + public ScryingGlass(final ScryingGlass card) { + super(card); + } + + @Override + public ScryingGlass copy() { + return new ScryingGlass(this); + } +} + +class ScryingGlassEffect extends OneShotEffect { + + public ScryingGlassEffect() { + super(Outcome.Neutral); + staticText = "Choose a number greater than 0 and a color. Target opponent reveals his or her hand. If that opponent reveals exactly the chosen number of cards of the chosen color, you draw a card"; + } + + public ScryingGlassEffect(final ScryingGlassEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + Player targetOpponent = game.getPlayer(source.getFirstTarget()); + ChoiceColor color = new ChoiceColor(); + int amount = 0; + if (controller != null + && targetOpponent != null) { + amount = controller.getAmount(1, Integer.MAX_VALUE, "Choose a number", game); + controller.choose(Outcome.Discard, color, game); + FilterCard filter = new FilterCard(); + filter.add(new ColorPredicate(color.getColor())); + targetOpponent.revealCards(source, targetOpponent.getHand(), game); + if (targetOpponent.getHand().count(filter, game) == amount) { + game.informPlayers(controller.getName() + " has chosen the exact number and color of the revealed cards from " + targetOpponent.getName() + "'s hand. They draw a card."); + controller.drawCards(1, game); + return true; + } else { + game.informPlayers(controller.getName() + " has chosen incorrectly and will not draw a card."); + } + } + return false; + } + + @Override + public ScryingGlassEffect copy() { + return new ScryingGlassEffect(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SeafarersQuay.java b/Mage.Sets/src/mage/cards/s/SeafarersQuay.java new file mode 100644 index 00000000000..ce62ca00404 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SeafarersQuay.java @@ -0,0 +1,47 @@ + +package mage.cards.s; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.keyword.BandsWithOtherAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SuperType; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.filter.predicate.mageobject.SupertypePredicate; + +/** + * + * @author L_J + */ +public final class SeafarersQuay extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Blue legendary creatures"); + + static { + filter.add(new ColorPredicate(ObjectColor.BLUE)); + filter.add(new SupertypePredicate(SuperType.LEGENDARY)); + } + + public SeafarersQuay(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + // Blue legendary creatures you control have "bands with other legendary creatures." + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledEffect(new BandsWithOtherAbility(SuperType.LEGENDARY), Duration.WhileOnBattlefield, filter))); + } + + public SeafarersQuay(final SeafarersQuay card) { + super(card); + } + + @Override + public SeafarersQuay copy() { + return new SeafarersQuay(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SerrasHymn.java b/Mage.Sets/src/mage/cards/s/SerrasHymn.java new file mode 100644 index 00000000000..5d7b9be30b8 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SerrasHymn.java @@ -0,0 +1,55 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.SacrificeSourceCost; +import mage.abilities.dynamicvalue.common.CountersSourceCount; +import mage.abilities.effects.common.PreventDamageToTargetMultiAmountEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.target.common.TargetAnyTargetAmount; + +/** + * + * @author jeffwadsworth + */ +public final class SerrasHymn extends CardImpl { + + private static final String rule = "Prevent the next X damage that would be dealt this turn to any number of target creatures and/or players, divided as you choose, where X is the number of verse counters on {this}."; + + public SerrasHymn(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{W}"); + + // At the beginning of your upkeep, you may put a verse counter on Serra's Hymn. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(Zone.BATTLEFIELD, + new AddCountersSourceEffect(CounterType.VERSE.createInstance(), true), TargetController.YOU, true)); + + // Sacrifice Serra's Hymn: Prevent the next X damage that would be dealt this turn to any number of target creatures and/or players, divided as you choose, where X is the number of verse counters on Serra's Hymn. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, + new PreventDamageToTargetMultiAmountEffect( + Duration.EndOfTurn, + 1, false, true, // the integer 1 is ignored due to the dynamic number being set + new CountersSourceCount(CounterType.VERSE)).setText(rule), + new SacrificeSourceCost()); + ability.addTarget(new TargetAnyTargetAmount(new CountersSourceCount(CounterType.VERSE))); + this.addAbility(ability); + + } + + public SerrasHymn(final SerrasHymn card) { + super(card); + } + + @Override + public SerrasHymn copy() { + return new SerrasHymn(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/Shadowfeed.java b/Mage.Sets/src/mage/cards/s/Shadowfeed.java index 8e615530b73..bd0c8400ff6 100644 --- a/Mage.Sets/src/mage/cards/s/Shadowfeed.java +++ b/Mage.Sets/src/mage/cards/s/Shadowfeed.java @@ -1,7 +1,6 @@ package mage.cards.s; -import java.util.UUID; import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.effects.common.GainLifeEffect; import mage.cards.CardImpl; @@ -9,19 +8,20 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.target.common.TargetCardInGraveyard; +import java.util.UUID; + /** - * * @author North */ public final class Shadowfeed extends CardImpl { public Shadowfeed(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{B}"); - + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}"); // Exile target card from a graveyard. this.getSpellAbility().addEffect(new ExileTargetEffect()); this.getSpellAbility().addTarget(new TargetCardInGraveyard()); + // You gain 3 life. this.getSpellAbility().addEffect(new GainLifeEffect(3)); } diff --git a/Mage.Sets/src/mage/cards/s/ShelkinBrownie.java b/Mage.Sets/src/mage/cards/s/ShelkinBrownie.java new file mode 100644 index 00000000000..0d5f206ecf6 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/ShelkinBrownie.java @@ -0,0 +1,45 @@ + +package mage.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.effects.common.continuous.LoseAbilityTargetEffect; +import mage.abilities.keyword.BandsWithOtherAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author L_J + */ +public final class ShelkinBrownie extends CardImpl { + + public ShelkinBrownie(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{G}"); + this.subtype.add(SubType.OUPHE); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // {T}: Target creature loses all "bands with other" abilities until end of turn. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new LoseAbilityTargetEffect(new BandsWithOtherAbility(), Duration.EndOfTurn), new TapSourceCost()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public ShelkinBrownie(final ShelkinBrownie card) { + super(card); + } + + @Override + public ShelkinBrownie copy() { + return new ShelkinBrownie(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/ShorecomberCrab.java b/Mage.Sets/src/mage/cards/s/ShorecomberCrab.java new file mode 100644 index 00000000000..03dee68e491 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/ShorecomberCrab.java @@ -0,0 +1,32 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class ShorecomberCrab extends CardImpl { + + public ShorecomberCrab(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{U}"); + this.subtype.add(SubType.CRAB); + + this.power = new MageInt(0); + this.toughness = new MageInt(4); + } + + public ShorecomberCrab(final ShorecomberCrab card) { + super(card); + } + + @Override + public ShorecomberCrab copy() { + return new ShorecomberCrab(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/ShrineKeeper.java b/Mage.Sets/src/mage/cards/s/ShrineKeeper.java new file mode 100644 index 00000000000..67682826d72 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/ShrineKeeper.java @@ -0,0 +1,32 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class ShrineKeeper extends CardImpl { + + public ShrineKeeper(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{W}"); + this.subtype.add(SubType.HUMAN, SubType.CLERIC); + + this.power = new MageInt(2); + this.toughness = new MageInt(2); + } + + public ShrineKeeper(final ShrineKeeper card) { + super(card); + } + + @Override + public ShrineKeeper copy() { + return new ShrineKeeper(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SinsOfThePast.java b/Mage.Sets/src/mage/cards/s/SinsOfThePast.java index 013b5780d71..8e86dc46890 100644 --- a/Mage.Sets/src/mage/cards/s/SinsOfThePast.java +++ b/Mage.Sets/src/mage/cards/s/SinsOfThePast.java @@ -1,7 +1,6 @@ package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.ContinuousEffect; @@ -11,32 +10,29 @@ import mage.abilities.effects.common.ExileSourceEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.AsThoughEffectType; -import mage.constants.CardType; -import mage.constants.Duration; -import mage.constants.Outcome; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.common.FilterInstantOrSorceryCard; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; import mage.players.Player; -import mage.target.common.TargetCardInGraveyard; +import mage.target.common.TargetCardInYourGraveyard; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** - * * @author emerald000 */ public final class SinsOfThePast extends CardImpl { public SinsOfThePast(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{4}{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{B}{B}"); // Until end of turn, you may cast target instant or sorcery card from your graveyard without paying its mana cost. If that card would be put into your graveyard this turn, exile it instead. Exile Sins of the Past. this.getSpellAbility().addEffect(new SinsOfThePastEffect()); this.getSpellAbility().addEffect(new ExileSourceEffect()); - this.getSpellAbility().addTarget(new TargetCardInGraveyard(new FilterInstantOrSorceryCard())); + this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(new FilterInstantOrSorceryCard())); } public SinsOfThePast(final SinsOfThePast card) { diff --git a/Mage.Sets/src/mage/cards/s/SosukesSummons.java b/Mage.Sets/src/mage/cards/s/SosukesSummons.java index e5ea61eb3b7..b3afeaf79fb 100644 --- a/Mage.Sets/src/mage/cards/s/SosukesSummons.java +++ b/Mage.Sets/src/mage/cards/s/SosukesSummons.java @@ -1,8 +1,7 @@ package mage.cards.s; -import java.util.UUID; -import mage.abilities.common.CreatureEntersBattlefieldTriggeredAbility; +import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.ReturnSourceFromGraveyardToHandEffect; import mage.cards.CardImpl; @@ -16,30 +15,34 @@ import mage.filter.predicate.mageobject.SubtypePredicate; import mage.filter.predicate.permanent.TokenPredicate; import mage.game.permanent.token.SnakeToken; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class SosukesSummons extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nontoken Snake"); + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("a nontoken Snake"); static { - filter.add(new SubtypePredicate(SubType.SNAKE)); - filter.add(Predicates.not(new TokenPredicate())); + filter.add(new SubtypePredicate(SubType.SNAKE)); + filter.add(Predicates.not(new TokenPredicate())); } public SosukesSummons(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{G}"); // Create two 1/1 green Snake creature tokens. this.getSpellAbility().addEffect(new CreateTokenEffect(new SnakeToken(), 2)); // Whenever a nontoken Snake enters the battlefield under your control, you may return Sosuke's Summons from your graveyard to your hand. - this.addAbility(new CreatureEntersBattlefieldTriggeredAbility(Zone.GRAVEYARD, new ReturnSourceFromGraveyardToHandEffect(), filter, true, false)); - - + this.addAbility(new EntersBattlefieldControlledTriggeredAbility( + Zone.GRAVEYARD, + new ReturnSourceFromGraveyardToHandEffect(), + filter, + true) + ); } public SosukesSummons(final SosukesSummons card) { diff --git a/Mage.Sets/src/mage/cards/s/SoulSculptor.java b/Mage.Sets/src/mage/cards/s/SoulSculptor.java new file mode 100644 index 00000000000..f82ccd16f1b --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SoulSculptor.java @@ -0,0 +1,149 @@ +package mage.cards.s; + +import java.util.UUID; +import mage.MageInt; +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.Condition; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.DependencyType; +import mage.constants.Duration; +import mage.constants.Layer; +import static mage.constants.Layer.TypeChangingEffects_4; +import mage.constants.Outcome; +import mage.constants.SubLayer; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.stack.StackObject; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author jeffwadsworth + */ +public final class SoulSculptor extends CardImpl { + + final String rule = "Target creature becomes an enchantment and loses all abilities until a player casts a creature spell."; + + public SoulSculptor(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); + + this.subtype.add(SubType.HUMAN); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // {1}{W}, {tap}: Target creature becomes an enchantment and loses all abilities until a player casts a creature spell. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect(new SoulSculptorEffect(), SoulSculptorCondition.instance, rule), new ManaCostsImpl("{1}{W}")); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + + } + + public SoulSculptor(final SoulSculptor card) { + super(card); + } + + @Override + public SoulSculptor copy() { + return new SoulSculptor(this); + } +} + +class SoulSculptorEffect extends ContinuousEffectImpl { + + public SoulSculptorEffect() { + super(Duration.Custom, Outcome.LoseAbility); + staticText = "target becomes an Enchantment and loses all abilites"; + dependencyTypes.add(DependencyType.EnchantmentAddingRemoving); + dependencyTypes.add(DependencyType.AddingAbility); + + } + + public SoulSculptorEffect(final SoulSculptorEffect effect) { + super(effect); + } + + @Override + public SoulSculptorEffect copy() { + return new SoulSculptorEffect(this); + } + + @Override + public void init(Ability source, Game game) { + super.init(source, game); + Permanent targetPermanent = game.getPermanent(source.getFirstTarget()); + if (targetPermanent != null) { + affectedObjectList.add(new MageObjectReference(targetPermanent, game)); + } + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + Permanent permanent = affectedObjectList.get(0).getPermanent(game); + if (permanent != null) { + switch (layer) { + case TypeChangingEffects_4: + if (sublayer == SubLayer.NA) { + permanent.getCardType().clear(); + permanent.getSubtype(game).clear(); + if (!permanent.getCardType().contains(CardType.ENCHANTMENT)) { + permanent.getCardType().add(CardType.ENCHANTMENT); + } + } + break; + case AbilityAddingRemovingEffects_6: + if (sublayer == SubLayer.NA) { + permanent.getAbilities().clear(); + } + break; + } + return true; + } + this.discard(); + return false; + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } + + @Override + public boolean hasLayer(Layer layer) { + return Layer.TypeChangingEffects_4 == layer + || Layer.AbilityAddingRemovingEffects_6 == layer; + } + +} + +enum SoulSculptorCondition implements Condition { + + instance; + + @Override + public boolean apply(Game game, Ability source) { + if (!game.getStack().isEmpty()) { + StackObject stackObject = game.getStack().getFirst(); + if (stackObject != null) { + return !stackObject.getCardType().contains(CardType.CREATURE); + } + } + return true; + } + + @Override + public String toString() { + return "creature spell cast"; + } + +} diff --git a/Mage.Sets/src/mage/cards/s/SoulStrings.java b/Mage.Sets/src/mage/cards/s/SoulStrings.java new file mode 100644 index 00000000000..4dc5d880609 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SoulStrings.java @@ -0,0 +1,39 @@ +package mage.cards.s; + +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DoUnlessAnyPlayerPaysEffect; +import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.common.FilterCreatureCard; +import mage.target.common.TargetCardInYourGraveyard; + +import java.util.UUID; +import mage.abilities.dynamicvalue.common.ManacostVariableValue; + +/** + * @author jmharmon + */ + +public final class SoulStrings extends CardImpl { + + public SoulStrings(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{B}"); + + // Return two target creature cards from your graveyard to your hand unless any player pays {X}. + Effect effect = new DoUnlessAnyPlayerPaysEffect( + new ReturnFromGraveyardToHandTargetEffect(), new ManacostVariableValue()); + this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(2, new FilterCreatureCard("creature cards from your graveyard"))); + } + + public SoulStrings(final SoulStrings card) { + super(card); + } + + @Override + public SoulStrings copy() { + return new SoulStrings(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SoulhunterRakshasa.java b/Mage.Sets/src/mage/cards/s/SoulhunterRakshasa.java new file mode 100644 index 00000000000..dba46f380ce --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SoulhunterRakshasa.java @@ -0,0 +1,45 @@ +package mage.cards.s; + +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.CantBlockAbility; +import mage.abilities.common.EntersBattlefieldTriggeredAbility; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.target.common.TargetOpponentOrPlaneswalker; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class SoulhunterRakshasa extends CardImpl { + + public SoulhunterRakshasa(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}"); + this.subtype.add(SubType.CAT, SubType.DEMON); + + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // Soulhunter Rakshasa can’t block. + this.addAbility(new CantBlockAbility()); + + // When Soulhunter Rakshasa enters the battlefield, it deals 5 damage to target opponent. + Ability ability = new EntersBattlefieldTriggeredAbility(new DamageTargetEffect(5, "it"), false); + ability.addTarget(new TargetOpponentOrPlaneswalker()); + this.addAbility(ability); + } + + public SoulhunterRakshasa(final SoulhunterRakshasa card) { + super(card); + } + + @Override + public SoulhunterRakshasa copy() { + return new SoulhunterRakshasa(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SpellContortion.java b/Mage.Sets/src/mage/cards/s/SpellContortion.java index 208f327bd2e..aab49c9ab4f 100644 --- a/Mage.Sets/src/mage/cards/s/SpellContortion.java +++ b/Mage.Sets/src/mage/cards/s/SpellContortion.java @@ -4,6 +4,7 @@ package mage.cards.s; import java.util.ArrayList; import java.util.List; import java.util.UUID; + import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.dynamicvalue.common.MultikickerCount; import mage.abilities.effects.common.CounterUnlessPaysEffect; @@ -15,23 +16,21 @@ import mage.constants.CardType; import mage.target.TargetSpell; /** - * * @author jeffwadsworth */ public final class SpellContortion extends CardImpl { public SpellContortion(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{U}"); // Multikicker {1}{U} this.addAbility(new MultikickerAbility("{1}{U}")); - + // Counter target spell unless its controller pays {2}. Draw a card for each time Spell Contortion was kicked. this.getSpellAbility().addEffect(new CounterUnlessPaysEffect(new GenericManaCost(2))); this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(new MultikickerCount())); this.getSpellAbility().addTarget(new TargetSpell()); - } public SpellContortion(final SpellContortion card) { @@ -42,11 +41,4 @@ public final class SpellContortion extends CardImpl { public SpellContortion copy() { return new SpellContortion(this); } - - @Override - public List getRules() { - List rules = new ArrayList<>(); - rules.add("Counter target spell unless its controller pays {2}. Draw a card for each time Spell Contortion was kicked."); - return rules; - } } diff --git a/Mage.Sets/src/mage/cards/s/StadiumVendors.java b/Mage.Sets/src/mage/cards/s/StadiumVendors.java index 04ebe8dad82..c95788ca696 100644 --- a/Mage.Sets/src/mage/cards/s/StadiumVendors.java +++ b/Mage.Sets/src/mage/cards/s/StadiumVendors.java @@ -1,4 +1,3 @@ - package mage.cards.s; import java.util.UUID; @@ -65,21 +64,22 @@ class StadiumVendorsEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getSourceId()); + Player controller = game.getPlayer(source.getControllerId()); if (controller == null) { return false; } TargetPlayer target = new TargetPlayer(1, 1, true); - if (!controller.choose(Outcome.Benefit, target, source.getSourceId(), game)) { - return false; + if (controller.choose(Outcome.Benefit, target, source.getSourceId(), game)) { + Player player = game.getPlayer(target.getFirstTarget()); + ChoiceColor colorChoice = new ChoiceColor(true); + if (player == null + || !player.choose(Outcome.Benefit, colorChoice, game)) { + return false; + } + Effect effect = new AddManaToManaPoolTargetControllerEffect(colorChoice.getMana(2), "that player's"); + effect.setTargetPointer(new FixedTarget(player.getId(), game)); + return effect.apply(game, source); } - Player player = game.getPlayer(target.getFirstTarget()); - ChoiceColor colorChoice = new ChoiceColor(true); - if (player == null || !player.choose(Outcome.Benefit, colorChoice, game)) { - return false; - } - Effect effect = new AddManaToManaPoolTargetControllerEffect(colorChoice.getMana(2), "that player's"); - effect.setTargetPointer(new FixedTarget(player.getId(), game)); - return effect.apply(game, source); + return false; } } diff --git a/Mage.Sets/src/mage/cards/s/StandOrFall.java b/Mage.Sets/src/mage/cards/s/StandOrFall.java new file mode 100644 index 00000000000..8bdbcefd8fa --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/StandOrFall.java @@ -0,0 +1,133 @@ + +package mage.cards.s; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfCombatTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.RestrictionEffect; +import mage.abilities.effects.common.combat.CantBlockTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.filter.StaticFilters; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCreaturePermanent; +import mage.target.common.TargetOpponent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author LevelX2 & L_J + */ +public final class StandOrFall extends CardImpl { + + public StandOrFall(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{R}"); + + // At the beginning of combat on your turn, separate all creatures defending player controls into two piles. Only creatures in the pile of that player’s choice can block this turn. + this.addAbility(new BeginningOfCombatTriggeredAbility(new StandOrFallEffect(), TargetController.YOU, false)); + } + + public StandOrFall(final StandOrFall card) { + super(card); + } + + @Override + public StandOrFall copy() { + return new StandOrFall(this); + } +} + +class StandOrFallEffect extends OneShotEffect { + + public StandOrFallEffect() { + super(Outcome.Detriment); + this.staticText = "separate all creatures defending player controls into two piles. Only creatures in the pile of that player’s choice can block this turn"; + } + + public StandOrFallEffect(final StandOrFallEffect effect) { + super(effect); + } + + @Override + public StandOrFallEffect copy() { + return new StandOrFallEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + // 802.2. As the combat phase starts, the attacking player doesn’t choose an opponent to become the defending player. + // Instead, all the attacking player’s opponents are defending players during the combat phase. + // + // 802.2a Any rule, object, or effect that refers to a “defending player” refers to one specific defending player, not to all of the defending players. + // If an ability of an attacking creature refers to a defending player, or a spell or ability refers to both an attacking creature and a defending player, + // then unless otherwise specified, the defending player it’s referring to is the player that creature was attacking at the time it became an attacking + // creature that combat, or the controller of the planeswalker that creature was attacking at the time it became an attacking creature that combat. If a spell or ability + // could apply to multiple attacking creatures, the appropriate defending player is individually determined for each of those attacking creatures. + // If there are multiple defending players that could be chosen, the controller of the spell or ability chooses one. + // + // https://www.mtgsalvation.com/forums/magic-fundamentals/magic-rulings/756140-stand-or-fall-mechanics + Player player = game.getPlayer(source.getControllerId()); + Set opponents = game.getOpponents(source.getControllerId()); + if (!opponents.isEmpty()) { + Player targetPlayer = game.getPlayer(opponents.iterator().next()); + if (opponents.size() > 1) { + TargetOpponent targetOpponent = new TargetOpponent(true); + if (player.chooseTarget(Outcome.Neutral, targetOpponent, source, game)) { + targetPlayer = game.getPlayer(targetOpponent.getFirstTarget()); + game.informPlayers(player.getLogName() + " chose " + targetPlayer.getLogName() + " as the defending player"); + } + } + + if (player != null && targetPlayer != null) { + int count = game.getBattlefield().countAll(StaticFilters.FILTER_PERMANENT_CREATURES, targetPlayer.getId(), game); + TargetCreaturePermanent creatures = new TargetCreaturePermanent(0, count, new FilterCreaturePermanent("creatures to put in the first pile"), true); + List pile1 = new ArrayList<>(); + creatures.setRequired(false); + if (player.choose(Outcome.Neutral, creatures, source.getSourceId(), game)) { + List targets = creatures.getTargets(); + for (UUID targetId : targets) { + Permanent p = game.getPermanent(targetId); + if (p != null) { + pile1.add(p); + } + } + } + List pile2 = new ArrayList<>(); + for (Permanent p : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, targetPlayer.getId(), game)) { + if (!pile1.contains(p)) { + pile2.add(p); + } + } + + boolean choice = targetPlayer.choosePile(outcome, "Choose which pile can block this turn.", pile1, pile2, game); + List chosenPile = choice ? pile2 : pile1; + List otherPile = choice ? pile1 : pile2; + for (Permanent permanent : chosenPile) { + if (permanent != null) { + RestrictionEffect effect = new CantBlockTargetEffect(Duration.EndOfTurn); + effect.setText(""); + effect.setTargetPointer(new FixedTarget(permanent.getId())); + game.addEffect(effect, source); + } + } + StringBuilder sb = new StringBuilder("Creatures that can block this turn: "); + sb.append(otherPile.stream().map(Permanent::getLogName).collect(Collectors.joining(", "))); + game.informPlayers(sb.toString()); + return true; + } + } + return false; + } +} diff --git a/Mage.Sets/src/mage/cards/s/StonehornDignitary.java b/Mage.Sets/src/mage/cards/s/StonehornDignitary.java index 3f92110a139..0443f4f16db 100644 --- a/Mage.Sets/src/mage/cards/s/StonehornDignitary.java +++ b/Mage.Sets/src/mage/cards/s/StonehornDignitary.java @@ -1,14 +1,14 @@ - package mage.cards.s; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.effects.common.SkipNextCombatEffect; +import mage.abilities.effects.common.SkipCombatStepEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.Duration; import mage.constants.SubType; import mage.target.common.TargetOpponent; @@ -17,27 +17,27 @@ import mage.target.common.TargetOpponent; * @author nantuko */ public final class StonehornDignitary extends CardImpl { - + public StonehornDignitary(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{W}"); this.subtype.add(SubType.RHINO); this.subtype.add(SubType.SOLDIER); - + this.power = new MageInt(1); this.toughness = new MageInt(4); // When Stonehorn Dignitary enters the battlefield, target opponent skips their next combat phase. - Ability ability = new EntersBattlefieldTriggeredAbility(new SkipNextCombatEffect()); + Ability ability = new EntersBattlefieldTriggeredAbility(new SkipCombatStepEffect(Duration.OneUse).setText("target opponent skips their next combat phase.")); ability.addTarget(new TargetOpponent()); this.addAbility(ability); } - + public StonehornDignitary(final StonehornDignitary card) { super(card); } - + @Override public StonehornDignitary copy() { return new StonehornDignitary(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/s/Subdue.java b/Mage.Sets/src/mage/cards/s/Subdue.java new file mode 100644 index 00000000000..63ac77351e7 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/Subdue.java @@ -0,0 +1,39 @@ + +package mage.cards.s; + +import java.util.UUID; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.dynamicvalue.common.TargetConvertedManaCost; +import mage.abilities.effects.common.PreventDamageByTargetEffect; +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author L_J + */ +public final class Subdue extends CardImpl { + + public Subdue(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{G}"); + + // Prevent all combat damage that would be dealt by target creature this turn. That creature gets +0/+X until end of turn, where X is its converted mana cost. + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + this.getSpellAbility().addEffect(new PreventDamageByTargetEffect(Duration.EndOfTurn, true)); + this.getSpellAbility().addEffect(new BoostTargetEffect(new StaticValue(0), new TargetConvertedManaCost(), Duration.EndOfTurn, true) + .setText("That creature gets +0/+X until end of turn, where X is its converted mana cost")); + } + + public Subdue(final Subdue card) { + super(card); + } + + @Override + public Subdue copy() { + return new Subdue(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SylvanLibrary.java b/Mage.Sets/src/mage/cards/s/SylvanLibrary.java index 97a7e02a0bb..751a5ab5444 100644 --- a/Mage.Sets/src/mage/cards/s/SylvanLibrary.java +++ b/Mage.Sets/src/mage/cards/s/SylvanLibrary.java @@ -1,4 +1,3 @@ - package mage.cards.s; import java.util.HashMap; @@ -106,7 +105,7 @@ class SylvanLibraryEffect extends OneShotEffect { } } } - controller.putCardsOnTopOfLibrary(cardsPutBack, game, source, false); + controller.putCardsOnTopOfLibrary(cardsPutBack, game, source, true); } } return true; diff --git a/Mage.Sets/src/mage/cards/t/TacticalAdvantage.java b/Mage.Sets/src/mage/cards/t/TacticalAdvantage.java new file mode 100644 index 00000000000..52774236e1d --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TacticalAdvantage.java @@ -0,0 +1,51 @@ +package mage.cards.t; + +import mage.abilities.effects.common.continuous.BoostTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.TargetController; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.BlockedPredicate; +import mage.filter.predicate.permanent.BlockingPredicate; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.target.common.TargetCreaturePermanent; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class TacticalAdvantage extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("blocking or blocked creature you control"); + + static { + filter.add( + Predicates.or( + new BlockingPredicate(), + new BlockedPredicate() + + )); + filter.add(new ControllerPredicate(TargetController.YOU)); + } + + public TacticalAdvantage(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}"); + + // Target blocking or blocked creature you control gets +2/+2 until end of turn. + this.getSpellAbility().addEffect(new BoostTargetEffect(2, 2, Duration.EndOfTurn)); + this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + } + + public TacticalAdvantage(final TacticalAdvantage card) { + super(card); + } + + @Override + public TacticalAdvantage copy() { + return new TacticalAdvantage(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TemurWarShaman.java b/Mage.Sets/src/mage/cards/t/TemurWarShaman.java index c95e2f82798..96577ada39b 100644 --- a/Mage.Sets/src/mage/cards/t/TemurWarShaman.java +++ b/Mage.Sets/src/mage/cards/t/TemurWarShaman.java @@ -14,6 +14,7 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Outcome; import mage.constants.TargetController; +import mage.constants.Zone; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.ControllerPredicate; @@ -62,7 +63,7 @@ public final class TemurWarShaman extends CardImpl { class TemurWarShamanTriggeredAbility extends TurnedFaceUpAllTriggeredAbility { public TemurWarShamanTriggeredAbility() { - super(new TemurWarShamanFightEffect(), new FilterControlledCreaturePermanent(), true); + super(Zone.BATTLEFIELD, new TemurWarShamanFightEffect(), new FilterControlledCreaturePermanent(), true, true); } public TemurWarShamanTriggeredAbility(final TemurWarShamanTriggeredAbility ability) { diff --git a/Mage.Sets/src/mage/cards/t/TheEldestReborn.java b/Mage.Sets/src/mage/cards/t/TheEldestReborn.java index 666e52d657f..c8120d042e3 100644 --- a/Mage.Sets/src/mage/cards/t/TheEldestReborn.java +++ b/Mage.Sets/src/mage/cards/t/TheEldestReborn.java @@ -1,4 +1,3 @@ - package mage.cards.t; import java.util.UUID; @@ -13,7 +12,6 @@ import mage.constants.SagaChapter; import mage.constants.SubType; import mage.constants.TargetController; import mage.filter.FilterCard; -import mage.filter.StaticFilters; import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CardTypePredicate; @@ -35,11 +33,12 @@ public final class TheEldestReborn extends CardImpl { } private static final FilterControlledPermanent filterSacrifice = new FilterControlledPermanent("creature or planeswalker"); + static { filterSacrifice.add(Predicates.or( - new CardTypePredicate(CardType.CREATURE), - new CardTypePredicate(CardType.PLANESWALKER) - )); + new CardTypePredicate(CardType.CREATURE), + new CardTypePredicate(CardType.PLANESWALKER) + )); } diff --git a/Mage.Sets/src/mage/cards/t/TitanicPelagosaur.java b/Mage.Sets/src/mage/cards/t/TitanicPelagosaur.java new file mode 100644 index 00000000000..221dfc89455 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TitanicPelagosaur.java @@ -0,0 +1,32 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class TitanicPelagosaur extends CardImpl { + + public TitanicPelagosaur(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}{U}"); + this.subtype.add(SubType.DINOSAUR); + + this.power = new MageInt(4); + this.toughness = new MageInt(6); + } + + public TitanicPelagosaur(final TitanicPelagosaur card) { + super(card); + } + + @Override + public TitanicPelagosaur copy() { + return new TitanicPelagosaur(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/Tolaria.java b/Mage.Sets/src/mage/cards/t/Tolaria.java new file mode 100644 index 00000000000..24543958cab --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/Tolaria.java @@ -0,0 +1,52 @@ + +package mage.cards.t; + +import java.util.UUID; +import mage.abilities.ActivatedAbilityImpl; +import mage.abilities.condition.common.IsStepCondition; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.decorator.ConditionalActivatedAbility; +import mage.abilities.effects.common.continuous.LoseAbilityTargetEffect; +import mage.abilities.keyword.BandingAbility; +import mage.abilities.keyword.BandsWithOtherAbility; +import mage.abilities.mana.BlueManaAbility; +import mage.constants.SuperType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.PhaseStep; +import mage.constants.Zone; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author L_J + */ +public final class Tolaria extends CardImpl { + + public Tolaria(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + this.addSuperType(SuperType.LEGENDARY); + + // {T}: Add {U}. + this.addAbility(new BlueManaAbility()); + + // {T}: Target creature loses banding and all "bands with other" abilities until end of turn. Activate this ability only during any upkeep step. + ActivatedAbilityImpl ability = new ConditionalActivatedAbility(Zone.BATTLEFIELD, + new LoseAbilityTargetEffect(BandingAbility.getInstance(), Duration.EndOfTurn), new TapSourceCost(), new IsStepCondition(PhaseStep.UPKEEP, false), + "{T}: Target creature loses banding and all \"bands with other\" abilities until end of turn. Activate this ability only during any upkeep step."); + ability.addEffect(new LoseAbilityTargetEffect(new BandsWithOtherAbility(), Duration.EndOfTurn)); + ability.addTarget(new TargetCreaturePermanent()); + this.addAbility(ability); + } + + public Tolaria(final Tolaria card) { + super(card); + } + + @Override + public Tolaria copy() { + return new Tolaria(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TreetopWarden.java b/Mage.Sets/src/mage/cards/t/TreetopWarden.java new file mode 100644 index 00000000000..2b4b7d2b304 --- /dev/null +++ b/Mage.Sets/src/mage/cards/t/TreetopWarden.java @@ -0,0 +1,32 @@ +package mage.cards.t; + +import mage.MageInt; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class TreetopWarden extends CardImpl { + + public TreetopWarden(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); + this.subtype.add(SubType.ELF, SubType.WARRIOR); + + this.power = new MageInt(2); + this.toughness = new MageInt(2); + } + + public TreetopWarden(final TreetopWarden card) { + super(card); + } + + @Override + public TreetopWarden copy() { + return new TreetopWarden(this); + } +} diff --git a/Mage.Sets/src/mage/cards/u/UnholyCitadel.java b/Mage.Sets/src/mage/cards/u/UnholyCitadel.java new file mode 100644 index 00000000000..7153b14a32e --- /dev/null +++ b/Mage.Sets/src/mage/cards/u/UnholyCitadel.java @@ -0,0 +1,47 @@ + +package mage.cards.u; + +import java.util.UUID; +import mage.ObjectColor; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; +import mage.abilities.keyword.BandsWithOtherAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SuperType; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.ColorPredicate; +import mage.filter.predicate.mageobject.SupertypePredicate; + +/** + * + * @author L_J + */ +public final class UnholyCitadel extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Black legendary creatures"); + + static { + filter.add(new ColorPredicate(ObjectColor.BLACK)); + filter.add(new SupertypePredicate(SuperType.LEGENDARY)); + } + + public UnholyCitadel(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.LAND}, ""); + + // Black legendary creatures you control have "bands with other legendary creatures." + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledEffect(new BandsWithOtherAbility(SuperType.LEGENDARY), Duration.WhileOnBattlefield, filter))); + } + + public UnholyCitadel(final UnholyCitadel card) { + super(card); + } + + @Override + public UnholyCitadel copy() { + return new UnholyCitadel(this); + } +} diff --git a/Mage.Sets/src/mage/cards/v/ValorInAkros.java b/Mage.Sets/src/mage/cards/v/ValorInAkros.java index 851ff2e66ab..3f778cba22b 100644 --- a/Mage.Sets/src/mage/cards/v/ValorInAkros.java +++ b/Mage.Sets/src/mage/cards/v/ValorInAkros.java @@ -1,25 +1,32 @@ package mage.cards.v; -import java.util.UUID; -import mage.abilities.common.CreatureEntersBattlefieldTriggeredAbility; +import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.StaticFilters; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class ValorInAkros extends CardImpl { public ValorInAkros(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}"); // Whenever a creature enters the battlefield under your control, creatures you control get +1/+1 until end of turn. - this.addAbility(new CreatureEntersBattlefieldTriggeredAbility(new BoostControlledEffect(1,1,Duration.EndOfTurn))); + this.addAbility(new EntersBattlefieldControlledTriggeredAbility( + Zone.BATTLEFIELD, + new BoostControlledEffect(1, 1, Duration.EndOfTurn), + StaticFilters.FILTER_PERMANENT_CREATURE_A, + false) + ); } public ValorInAkros(final ValorInAkros card) { diff --git a/Mage.Sets/src/mage/cards/v/VeilOfBirds.java b/Mage.Sets/src/mage/cards/v/VeilOfBirds.java new file mode 100644 index 00000000000..53e476fca42 --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VeilOfBirds.java @@ -0,0 +1,66 @@ +package mage.cards.v; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.TriggeredAbility; +import mage.abilities.common.SpellCastOpponentTriggeredAbility; +import mage.abilities.condition.common.SourceMatchesFilterCondition; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.filter.FilterSpell; +import mage.filter.StaticFilters; +import mage.game.permanent.token.TokenImpl; + +/** + * + * @author jeffwadsworth + */ +public final class VeilOfBirds extends CardImpl { + + private static final FilterSpell filter = new FilterSpell(); + + public VeilOfBirds(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{U}"); + + // When an opponent casts a spell, if Veil of Birds is an enchantment, Veil of Birds becomes a 1/1 Bird creature with flying. + TriggeredAbility ability = new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect(new VeilOfBirdsToken(), "", Duration.WhileOnBattlefield, true, false), + filter, false); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_ENCHANTMENT_PERMANENT), + "Whenever an opponent casts a spell, if Veil of Birds is an enchantment, Veil of Birds becomes a 1/1 Bird creature with flying.")); + } + + public VeilOfBirds(final VeilOfBirds card) { + super(card); + } + + @Override + public VeilOfBirds copy() { + return new VeilOfBirds(this); + } +} + +class VeilOfBirdsToken extends TokenImpl { + + public VeilOfBirdsToken() { + super("Bird", "1/1 creature with flying"); + cardType.add(CardType.CREATURE); + subtype.add(SubType.BIRD); + power = new MageInt(1); + toughness = new MageInt(1); + this.addAbility(FlyingAbility.getInstance()); + } + + public VeilOfBirdsToken(final VeilOfBirdsToken token) { + super(token); + } + + public VeilOfBirdsToken copy() { + return new VeilOfBirdsToken(this); + } +} diff --git a/Mage.Sets/src/mage/cards/v/VeiledApparition.java b/Mage.Sets/src/mage/cards/v/VeiledApparition.java new file mode 100644 index 00000000000..2bf24f13390 --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VeiledApparition.java @@ -0,0 +1,74 @@ +package mage.cards.v; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbility; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.SpellCastOpponentTriggeredAbility; +import mage.abilities.condition.common.SourceMatchesFilterCondition; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.effects.common.DoUnlessControllerPaysEffect; +import mage.abilities.effects.common.SacrificeSourceEffect; +import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.TargetController; +import mage.filter.FilterSpell; +import mage.filter.StaticFilters; +import mage.game.permanent.token.TokenImpl; + +/** + * + * @author jeffwadsworth + */ +public final class VeiledApparition extends CardImpl { + + private static final FilterSpell filter = new FilterSpell(); + + public VeiledApparition(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}"); + + + // When an opponent casts a spell, if Veiled Apparition is an enchantment, Veiled Apparition becomes a 3/3 Illusion creature with flying and "At the beginning of your upkeep, sacrifice Veiled Apparition unless you pay {1}{U}." + TriggeredAbility ability = new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect(new VeilApparitionToken(), "", Duration.WhileOnBattlefield, true, false), + filter, false); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_ENCHANTMENT_PERMANENT), + "Whenever an opponent casts a spell, if Veiled Apparition is an enchantment, Veiled Apparition becomes a 3/3 Illusion creature with flying and \"At the beginning of your upkeep, sacrifice Veiled Apparition unless you pay {1}{U}.")); + + } + + public VeiledApparition(final VeiledApparition card) { + super(card); + } + + @Override + public VeiledApparition copy() { + return new VeiledApparition(this); + } +} + +class VeilApparitionToken extends TokenImpl { + + public VeilApparitionToken() { + super("Illusion", "3/3 Illusion creature with flying and \"At the beginning of your upkeep, sacrifice Veiled Apparition unless you pay {1}{U}."); + cardType.add(CardType.CREATURE); + subtype.add(SubType.ILLUSION); + power = new MageInt(3); + toughness = new MageInt(3); + Ability ability = new BeginningOfUpkeepTriggeredAbility(new DoUnlessControllerPaysEffect(new SacrificeSourceEffect(), new ManaCostsImpl("{1}{U}")), TargetController.YOU, false); + this.addAbility(ability); + } + + public VeilApparitionToken(final VeilApparitionToken token) { + super(token); + } + + public VeilApparitionToken copy() { + return new VeilApparitionToken(this); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/v/VeiledCrocodile.java b/Mage.Sets/src/mage/cards/v/VeiledCrocodile.java new file mode 100644 index 00000000000..860795598af --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VeiledCrocodile.java @@ -0,0 +1,130 @@ +package mage.cards.v; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.StateTriggeredAbility; +import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.token.TokenImpl; +import mage.players.Player; + +/** + * + * @author jeffwadsworth + */ +public final class VeiledCrocodile extends CardImpl { + + public VeiledCrocodile(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); + + // When a player has no cards in hand, if Veiled Crocodile is an enchantment, Veiled Crocodile becomes a 4/4 Crocodile creature. + this.addAbility(new VeiledCrocodileStateTriggeredAbility()); + } + + public VeiledCrocodile(final VeiledCrocodile card) { + super(card); + } + + @Override + public VeiledCrocodile copy() { + return new VeiledCrocodile(this); + } +} + +class VeiledCrocodileStateTriggeredAbility extends StateTriggeredAbility { + + public VeiledCrocodileStateTriggeredAbility() { + super(Zone.BATTLEFIELD, new BecomesCreatureSourceEffect(new VeilCrocodileToken(), "", Duration.Custom, true, false)); + } + + public VeiledCrocodileStateTriggeredAbility(final VeiledCrocodileStateTriggeredAbility ability) { + super(ability); + } + + @Override + public VeiledCrocodileStateTriggeredAbility copy() { + return new VeiledCrocodileStateTriggeredAbility(this); + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + for (UUID playerId : game.getState().getPlayersInRange(controllerId, game)) { + Player player = game.getPlayer(playerId); + if (player != null + && player.getHand().isEmpty()) { + return true; + } + } + return false; + } + + @Override + public boolean checkInterveningIfClause(Game game) { + if (getSourcePermanentIfItStillExists(game) != null) { + return getSourcePermanentIfItStillExists(game).isEnchantment(); + } + return false; + } + + @Override + public boolean canTrigger(Game game) { + //20100716 - 603.8 + Boolean triggered = (Boolean) game.getState().getValue(getSourceId().toString() + "triggered"); + if (triggered == null) { + triggered = Boolean.FALSE; + } + return !triggered; + } + + @Override + public void trigger(Game game, UUID controllerId) { + //20100716 - 603.8 + game.getState().setValue(this.getSourceId().toString() + "triggered", Boolean.TRUE); + super.trigger(game, controllerId); + } + + @Override + public boolean resolve(Game game) { + //20100716 - 603.8 + boolean result = super.resolve(game); + game.getState().setValue(this.getSourceId().toString() + "triggered", Boolean.FALSE); + return result; + } + + @Override + public void counter(Game game) { + game.getState().setValue(this.getSourceId().toString() + "triggered", Boolean.FALSE); + } + + @Override + public String getRule() { + return new StringBuilder("When a player has no cards in hand, if {this} is an enchantment, ").append(super.getRule()).toString(); + } + +} + +class VeilCrocodileToken extends TokenImpl { + + public VeilCrocodileToken() { + super("Crocodile", "4/4 Crocodile creature"); + cardType.add(CardType.CREATURE); + subtype.add(SubType.CROCODILE); + power = new MageInt(4); + toughness = new MageInt(4); + } + + public VeilCrocodileToken(final VeilCrocodileToken token) { + super(token); + } + + public VeilCrocodileToken copy() { + return new VeilCrocodileToken(this); + } +} diff --git a/Mage.Sets/src/mage/cards/v/VeiledSentry.java b/Mage.Sets/src/mage/cards/v/VeiledSentry.java new file mode 100644 index 00000000000..3c6ce6f61e4 --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VeiledSentry.java @@ -0,0 +1,115 @@ +package mage.cards.v; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.TriggeredAbility; +import mage.abilities.common.SpellCastOpponentTriggeredAbility; +import mage.abilities.condition.common.SourceMatchesFilterCondition; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Layer; +import static mage.constants.Layer.PTChangingEffects_7; +import static mage.constants.Layer.TypeChangingEffects_4; +import mage.constants.Outcome; +import mage.constants.SetTargetPointer; +import mage.constants.SubLayer; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.FilterSpell; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.game.stack.Spell; + +/** + * + * @author jeffwadsworth + */ +public final class VeiledSentry extends CardImpl { + + public VeiledSentry(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{U}"); + + // When an opponent casts a spell, if Veiled Sentry is an enchantment, Veiled Sentry becomes an Illusion creature with power and toughness each equal to that spell's converted mana cost. + TriggeredAbility ability = new SpellCastOpponentTriggeredAbility(Zone.BATTLEFIELD, new VeiledSentryEffect(), new FilterSpell(), false, SetTargetPointer.SPELL); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_ENCHANTMENT_PERMANENT), + "Whenever an opponent casts a spell, if Veiled Sentry is an enchantment, Veil Sentry becomes an Illusion creature with power and toughness equal to that spell's converted mana cost.")); + + } + + public VeiledSentry(final VeiledSentry card) { + super(card); + } + + @Override + public VeiledSentry copy() { + return new VeiledSentry(this); + } +} + +class VeiledSentryEffect extends ContinuousEffectImpl { + + public VeiledSentryEffect() { + super(Duration.Custom, Outcome.BecomeCreature); + staticText = "{this} becomes an Illusion creature with power and toughness equal to that spell's converted mana cost"; + } + + public VeiledSentryEffect(final VeiledSentryEffect effect) { + super(effect); + } + + @Override + public VeiledSentryEffect copy() { + return new VeiledSentryEffect(this); + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + Permanent veiledSentry = game.getPermanent(source.getSourceId()); + Spell spellCast = game.getSpell(targetPointer.getFirst(game, source)); + if (spellCast != null) { + game.getState().setValue(source + "cmcSpell", spellCast.getConvertedManaCost()); + } + if (veiledSentry == null) { + return false; + } + switch (layer) { + case TypeChangingEffects_4: + if (sublayer == SubLayer.NA) { + veiledSentry.getCardType().clear(); + if (!veiledSentry.isCreature()) { + veiledSentry.addCardType(CardType.CREATURE); + } + if (!veiledSentry.getSubtype(game).contains(SubType.ILLUSION)) { + veiledSentry.getSubtype(game).add(SubType.ILLUSION); + } + } + break; + + case PTChangingEffects_7: + if (game.getState().getValue(source + "cmcSpell") != null) { + int cmc = (int) game.getState().getValue(source + "cmcSpell"); + if (sublayer == SubLayer.SetPT_7b) { + veiledSentry.addPower(cmc); + veiledSentry.addToughness(cmc); + } + } + } + return true; + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } + + @Override + public boolean hasLayer(Layer layer) { + return layer == Layer.PTChangingEffects_7 + || layer == Layer.TypeChangingEffects_4; + } +} diff --git a/Mage.Sets/src/mage/cards/v/VeiledSerpent.java b/Mage.Sets/src/mage/cards/v/VeiledSerpent.java new file mode 100644 index 00000000000..216133ebfda --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VeiledSerpent.java @@ -0,0 +1,75 @@ +package mage.cards.v; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.TriggeredAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.common.SpellCastOpponentTriggeredAbility; +import mage.abilities.condition.common.SourceMatchesFilterCondition; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; +import mage.abilities.effects.common.combat.CantAttackUnlessDefenderControllsPermanent; +import mage.abilities.effects.common.continuous.BecomesCreatureSourceEffect; +import mage.abilities.keyword.CyclingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.FilterSpell; +import mage.filter.StaticFilters; +import mage.filter.common.FilterLandPermanent; +import mage.game.permanent.token.TokenImpl; + +/** + * + * @author jeffwadsworth + */ +public final class VeiledSerpent extends CardImpl { + + public VeiledSerpent(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{U}"); + + // When an opponent casts a spell, if Veiled Serpent is an enchantment, Veiled Serpent becomes a 4/4 Serpent creature that can't attack unless defending player controls an Island. + TriggeredAbility ability = new SpellCastOpponentTriggeredAbility(new BecomesCreatureSourceEffect(new VeiledSerpentToken(), "", Duration.WhileOnBattlefield, true, false), + new FilterSpell(), false); + this.addAbility(new ConditionalInterveningIfTriggeredAbility(ability, new SourceMatchesFilterCondition(StaticFilters.FILTER_ENCHANTMENT_PERMANENT), + "Whenever an opponent casts a spell, if Veiled Serpent is an enchantment, Veiled Serpent becomes a 4/4 Serpent creature that can't attack unless defending player controls an Island.")); + + // Cycling {2} + this.addAbility(new CyclingAbility(new ManaCostsImpl("{2}"))); + + } + + public VeiledSerpent(final VeiledSerpent card) { + super(card); + } + + @Override + public VeiledSerpent copy() { + return new VeiledSerpent(this); + } +} + +class VeiledSerpentToken extends TokenImpl { + + public VeiledSerpentToken() { + super("Serpent", "4/4 Serpent creature"); + cardType.add(CardType.CREATURE); + subtype.add(SubType.SERPENT); + power = new MageInt(4); + toughness = new MageInt(4); + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, + new CantAttackUnlessDefenderControllsPermanent( + new FilterLandPermanent(SubType.ISLAND, "an Island")))); + } + + public VeiledSerpentToken(final VeiledSerpentToken token) { + super(token); + } + + public VeiledSerpentToken copy() { + return new VeiledSerpentToken(this); + } +} diff --git a/Mage.Sets/src/mage/cards/v/VenomousFangs.java b/Mage.Sets/src/mage/cards/v/VenomousFangs.java new file mode 100644 index 00000000000..1be68f955f2 --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VenomousFangs.java @@ -0,0 +1,48 @@ +package mage.cards.v; + +import java.util.UUID; +import mage.constants.SubType; +import mage.target.common.TargetCreaturePermanent; +import mage.abilities.Ability; +import mage.abilities.common.DealsDamageToACreatureAttachedTriggeredAbility; +import mage.abilities.effects.common.AttachEffect; +import mage.abilities.effects.common.DestroyTargetEffect; +import mage.constants.Outcome; +import mage.target.TargetPermanent; +import mage.abilities.keyword.EnchantAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; + +/** + * + * @author jeffwadsworth + */ +public final class VenomousFangs extends CardImpl { + + public VenomousFangs(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{G}"); + + this.subtype.add(SubType.AURA); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // Whenever enchanted creature deals damage to a creature, destroy the other creature. + this.addAbility(new DealsDamageToACreatureAttachedTriggeredAbility(new DestroyTargetEffect(), false, "enchanted creature", false, true)); + + } + + public VenomousFangs(final VenomousFangs card) { + super(card); + } + + @Override + public VenomousFangs copy() { + return new VenomousFangs(this); + } +} diff --git a/Mage.Sets/src/mage/cards/v/ViashinoBey.java b/Mage.Sets/src/mage/cards/v/ViashinoBey.java new file mode 100644 index 00000000000..d3471e16e40 --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/ViashinoBey.java @@ -0,0 +1,94 @@ +package mage.cards.v; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.AttacksTriggeredAbility; +import mage.abilities.effects.OneShotEffect; +import mage.constants.SubType; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.TargetController; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.ControllerPredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetOpponent; + +/** + * + * @author jeffwadsworth + */ +public final class ViashinoBey extends CardImpl { + + private static final String rule = "If {this} attacks, all creatures you control attack if able."; + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); + + static { + filter.add(new ControllerPredicate(TargetController.YOU)); + } + + public ViashinoBey(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}{R}"); + + this.subtype.add(SubType.VIASHINO); + this.power = new MageInt(4); + this.toughness = new MageInt(3); + + // If Viashino Bey attacks, all creatures you control attack if able. + this.addAbility(new AttacksTriggeredAbility(new ViashinoBeyEffect(), false, rule)); + + } + + public ViashinoBey(final ViashinoBey card) { + super(card); + } + + @Override + public ViashinoBey copy() { + return new ViashinoBey(this); + } +} + +class ViashinoBeyEffect extends OneShotEffect { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); + + static { + filter.add(new ControllerPredicate(TargetController.YOU)); + } + + public ViashinoBeyEffect() { + super(Outcome.Benefit); + } + + public ViashinoBeyEffect(final ViashinoBeyEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + TargetOpponent targetDefender = new TargetOpponent(); + if (controller != null) { + game.getBattlefield().getAllActivePermanents(CardType.CREATURE).stream().filter((permanent) -> (filter.match(permanent, source.getSourceId(), source.getControllerId(), game))).forEachOrdered((permanent) -> { + if (game.getOpponents(controller.getId()).size() > 1) { + controller.choose(outcome.Benefit, targetDefender, source.getSourceId(), game); + } else { + targetDefender.add(game.getOpponents(controller.getId()).iterator().next(), game); + } + if (permanent.canAttack(targetDefender.getFirstTarget(), game)) { + controller.declareAttacker(permanent.getId(), targetDefender.getFirstTarget(), game, false); + } + }); + } + return false; + } + + @Override + public ViashinoBeyEffect copy() { + return new ViashinoBeyEffect(this); + } +} diff --git a/Mage.Sets/src/mage/cards/v/VigilanteJustice.java b/Mage.Sets/src/mage/cards/v/VigilanteJustice.java index e99e223b5f0..791642147ba 100644 --- a/Mage.Sets/src/mage/cards/v/VigilanteJustice.java +++ b/Mage.Sets/src/mage/cards/v/VigilanteJustice.java @@ -1,9 +1,8 @@ package mage.cards.v; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.common.CreatureEntersBattlefieldTriggeredAbility; +import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -14,24 +13,30 @@ import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.SubtypePredicate; import mage.target.common.TargetAnyTarget; +import java.util.UUID; + /** - * * @author Loki */ public final class VigilanteJustice extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("Human"); + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("a Human"); static { - filter.add(new SubtypePredicate(SubType.HUMAN)); + filter.add(new SubtypePredicate(SubType.HUMAN)); } public VigilanteJustice(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}"); // Whenever a Human enters the battlefield under your control, Vigilante Justice deals 1 damage to any target. - Ability ability = new CreatureEntersBattlefieldTriggeredAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), filter, false, false); + Ability ability = new EntersBattlefieldControlledTriggeredAbility( + Zone.BATTLEFIELD, + new DamageTargetEffect(1), + filter, + false + ); ability.addTarget(new TargetAnyTarget()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/v/VigorousCharge.java b/Mage.Sets/src/mage/cards/v/VigorousCharge.java new file mode 100644 index 00000000000..fccee6d9cb2 --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VigorousCharge.java @@ -0,0 +1,95 @@ + +package mage.cards.v; + +import java.util.UUID; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.condition.LockedInCondition; +import mage.abilities.condition.common.KickedCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; +import mage.abilities.keyword.KickerAbility; +import mage.abilities.keyword.TrampleAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.DamagedEvent; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author LevelX2 & L_J + */ +public final class VigorousCharge extends CardImpl { + + private static final String staticText = "Whenever that creature deals combat damage this turn, if this spell was kicked, you gain life equal to that damage"; + + public VigorousCharge(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{G}"); + + // Kicker {W} (You may pay an additional {W} as you cast this spell.) + this.addAbility(new KickerAbility("{W}")); + // Target creature gains trample until end of turn. + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); + this.getSpellAbility().addEffect(new GainAbilityTargetEffect(TrampleAbility.getInstance(), Duration.EndOfTurn)); + // Whenever that creature deals combat damage this turn, if this spell was kicked, you gain life equal to that damage. + this.getSpellAbility().addEffect(new ConditionalContinuousEffect(new GainAbilityTargetEffect(new VigorousChargeTriggeredAbility(), Duration.EndOfTurn), + new LockedInCondition(KickedCondition.instance), staticText)); + + } + + public VigorousCharge(final VigorousCharge card) { + super(card); + } + + @Override + public VigorousCharge copy() { + return new VigorousCharge(this); + } +} + +class VigorousChargeTriggeredAbility extends TriggeredAbilityImpl { + + public VigorousChargeTriggeredAbility() { + super(Zone.BATTLEFIELD, null); + } + + public VigorousChargeTriggeredAbility(final VigorousChargeTriggeredAbility ability) { + super(ability); + } + + @Override + public VigorousChargeTriggeredAbility copy() { + return new VigorousChargeTriggeredAbility(this); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == EventType.DAMAGED_CREATURE + || event.getType() == EventType.DAMAGED_PLAYER + || event.getType() == EventType.DAMAGED_PLANESWALKER; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + DamagedEvent damageEvent = (DamagedEvent) event; + if (damageEvent.isCombatDamage()) { + if (event.getSourceId().equals(this.sourceId)) { + this.getEffects().clear(); + this.getEffects().add(new GainLifeEffect(damageEvent.getAmount())); + return true; + } + } + return false; + } + + @Override + public String getRule() { + return "Whenever {this} deals combat damage, you gain that much life."; + } +} diff --git a/Mage.Sets/src/mage/cards/w/WallOfTombstones.java b/Mage.Sets/src/mage/cards/w/WallOfTombstones.java new file mode 100644 index 00000000000..16abfc19f7c --- /dev/null +++ b/Mage.Sets/src/mage/cards/w/WallOfTombstones.java @@ -0,0 +1,77 @@ + +package mage.cards.w; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.dynamicvalue.common.StaticValue; +import mage.abilities.dynamicvalue.common.CardsInControllerGraveyardCount; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.SetToughnessSourceEffect; +import mage.abilities.keyword.DefenderAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.SubLayer; +import mage.constants.TargetController; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.util.CardUtil; + +/** + * + * @author L_J + */ +public final class WallOfTombstones extends CardImpl { + + public WallOfTombstones(UUID ownerId, CardSetInfo setInfo) { + super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}"); + this.subtype.add(SubType.WALL); + this.power = new MageInt(0); + this.toughness = new MageInt(1); + + // Defender + this.addAbility(DefenderAbility.getInstance()); + + // At the beginning of your upkeep, change Wall of Tombstones’s base toughness to 1 plus the number of creature cards in your graveyard. + this.addAbility(new BeginningOfUpkeepTriggeredAbility(new WallOfTombstonesEffect(), TargetController.YOU, false)); + + } + + public WallOfTombstones(final WallOfTombstones card) { + super(card); + } + + @Override + public WallOfTombstones copy() { + return new WallOfTombstones(this); + } +} + +class WallOfTombstonesEffect extends OneShotEffect { + + public WallOfTombstonesEffect() { + super(Outcome.Detriment); + this.staticText = "change {this}’s base toughness to 1 plus the number of creature cards in your graveyard"; + } + + public WallOfTombstonesEffect(final WallOfTombstonesEffect effect) { + super(effect); + } + + @Override + public WallOfTombstonesEffect copy() { + return new WallOfTombstonesEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + int newToughness = CardUtil.addWithOverflowCheck(1, new CardsInControllerGraveyardCount(StaticFilters.FILTER_CARD_CREATURE).calculate(game, source, this)); + game.addEffect(new SetToughnessSourceEffect(new StaticValue(newToughness), Duration.Custom, SubLayer.SetPT_7b), source); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/w/WarleadersHelix.java b/Mage.Sets/src/mage/cards/w/WarleadersHelix.java index 77b2feb5dd6..769228823d0 100644 --- a/Mage.Sets/src/mage/cards/w/WarleadersHelix.java +++ b/Mage.Sets/src/mage/cards/w/WarleadersHelix.java @@ -4,6 +4,7 @@ package mage.cards.w; import java.util.ArrayList; import java.util.List; import java.util.UUID; + import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.GainLifeEffect; import mage.cards.CardImpl; @@ -12,18 +13,16 @@ import mage.constants.CardType; import mage.target.common.TargetAnyTarget; /** - * * @author jeffwadsworth */ public final class WarleadersHelix extends CardImpl { public WarleadersHelix(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{R}{W}"); - + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R}{W}"); // Warleader's Helix deals 4 damage to any target and you gain 4 life. this.getSpellAbility().addEffect(new DamageTargetEffect(4)); - this.getSpellAbility().addEffect(new GainLifeEffect(4)); + this.getSpellAbility().addEffect(new GainLifeEffect(4).setText("and you gain 4 life")); this.getSpellAbility().addTarget(new TargetAnyTarget()); } @@ -35,11 +34,4 @@ public final class WarleadersHelix extends CardImpl { public WarleadersHelix copy() { return new WarleadersHelix(this); } - - @Override - public List getRules() { - List rules = new ArrayList<>(); - rules.add("Warleader's Helix deals 4 damage to any target and you gain 4 life."); - return rules; - } } diff --git a/Mage.Sets/src/mage/cards/w/WarsToll.java b/Mage.Sets/src/mage/cards/w/WarsToll.java index 01972bac1a8..3f103a26978 100644 --- a/Mage.Sets/src/mage/cards/w/WarsToll.java +++ b/Mage.Sets/src/mage/cards/w/WarsToll.java @@ -1,4 +1,3 @@ - package mage.cards.w; import java.util.UUID; @@ -103,7 +102,9 @@ class WarsTollEffect extends OneShotEffect { filterOpponentCreatures.add(new ControllerIdPredicate(opponent.getId())); game.getBattlefield().getAllActivePermanents(CardType.CREATURE).stream().filter((permanent) -> (filterOpponentCreatures.match(permanent, source.getSourceId(), source.getControllerId(), game))).forEachOrdered((permanent) -> { //TODO: allow the player to choose between a planeswalker and player - opponent.declareAttacker(permanent.getId(), source.getControllerId(), game, false); + if (permanent.canAttack(source.getControllerId(), game)) { + opponent.declareAttacker(permanent.getId(), source.getControllerId(), game, false); + } }); return true; } diff --git a/Mage.Sets/src/mage/cards/w/WhisperingSnitch.java b/Mage.Sets/src/mage/cards/w/WhisperingSnitch.java index c28daf08416..6d88e9d1af0 100644 --- a/Mage.Sets/src/mage/cards/w/WhisperingSnitch.java +++ b/Mage.Sets/src/mage/cards/w/WhisperingSnitch.java @@ -7,10 +7,10 @@ import mage.MageInt; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.common.DamagePlayersEffect; import mage.abilities.effects.common.GainLifeEffect; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.SubType; import mage.constants.TargetController; import mage.constants.WatcherScope; import mage.constants.Zone; @@ -65,8 +65,11 @@ class WhisperingSnitchTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { - WhisperingSnitchWatcher watcher = (WhisperingSnitchWatcher) game.getState().getWatchers().get(WhisperingSnitchWatcher.class.getSimpleName()); - return watcher != null && watcher.getTimesSurveiled(getControllerId()) == 1; + if (event.getPlayerId().equals(getControllerId())) { + WhisperingSnitchWatcher watcher = (WhisperingSnitchWatcher) game.getState().getWatchers().get(WhisperingSnitchWatcher.class.getSimpleName()); + return watcher != null && watcher.getTimesSurveiled(getControllerId()) == 1; + } + return false; } @Override diff --git a/Mage.Sets/src/mage/cards/w/WildwoodRebirth.java b/Mage.Sets/src/mage/cards/w/WildwoodRebirth.java index 3ce85f81a31..106fe3c6bc6 100644 --- a/Mage.Sets/src/mage/cards/w/WildwoodRebirth.java +++ b/Mage.Sets/src/mage/cards/w/WildwoodRebirth.java @@ -1,16 +1,16 @@ package mage.cards.w; -import java.util.UUID; import mage.abilities.effects.common.ReturnFromGraveyardToHandTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.StaticFilters; -import mage.target.common.TargetCardInGraveyard; +import mage.target.common.TargetCardInYourGraveyard; + +import java.util.UUID; /** - * * @author Plopman */ public final class WildwoodRebirth extends CardImpl { @@ -20,7 +20,7 @@ public final class WildwoodRebirth extends CardImpl { // Return target creature card from your graveyard to your hand. this.getSpellAbility().addEffect(new ReturnFromGraveyardToHandTargetEffect()); - this.getSpellAbility().addTarget(new TargetCardInGraveyard(StaticFilters.FILTER_CARD_CREATURE_YOUR_GRAVEYARD)); + this.getSpellAbility().addTarget(new TargetCardInYourGraveyard()); } public WildwoodRebirth(final WildwoodRebirth card) { diff --git a/Mage.Sets/src/mage/cards/w/WordOfCommand.java b/Mage.Sets/src/mage/cards/w/WordOfCommand.java index a73cc01035b..ad06e245df4 100644 --- a/Mage.Sets/src/mage/cards/w/WordOfCommand.java +++ b/Mage.Sets/src/mage/cards/w/WordOfCommand.java @@ -1,4 +1,3 @@ - package mage.cards.w; import java.util.UUID; @@ -14,8 +13,8 @@ import mage.abilities.effects.RestrictionEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.CardType; import mage.constants.AsThoughEffectType; +import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.Zone; @@ -37,7 +36,7 @@ import mage.target.targetpointer.FixedTarget; public final class WordOfCommand extends CardImpl { public WordOfCommand(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}{B}"); // Look at target opponent's hand and choose a card from it. You control that player until Word of Command finishes resolving. The player plays that card if able. While doing so, the player can activate mana abilities only if they're from lands that player controls and only if mana they produce is spent to activate other mana abilities of lands the player controls and/or to play that card. If the chosen card is cast as a spell, you control the player while that spell is resolving. this.getSpellAbility().addEffect(new WordOfCommandEffect()); @@ -58,7 +57,7 @@ class WordOfCommandEffect extends OneShotEffect { public WordOfCommandEffect() { super(Outcome.GainControl); - this.staticText = "Look at target opponent's hand and choose a card from it. You control that player until Word of Command finishes resolving. The player plays that card if able. While doing so, the player can activate mana abilities only if they're from lands that player controls and only if mana they produce is spent to activate other mana abilities of lands the player controls and/or to play that card. If the chosen card is cast as a spell, you control the player while that spell is resolving"; + this.staticText = "Look at target opponent's hand and choose a card from it. You control that player until {this} finishes resolving. The player plays that card if able. While doing so, the player can activate mana abilities only if they're from lands that player controls and only if mana they produce is spent to activate other mana abilities of lands the player controls and/or to play that card. If the chosen card is cast as a spell, you control the player while that spell is resolving"; } public WordOfCommandEffect(final WordOfCommandEffect effect) { diff --git a/Mage.Sets/src/mage/cards/z/ZephyrGull.java b/Mage.Sets/src/mage/cards/z/ZephyrGull.java new file mode 100644 index 00000000000..5b246992051 --- /dev/null +++ b/Mage.Sets/src/mage/cards/z/ZephyrGull.java @@ -0,0 +1,36 @@ +package mage.cards.z; + +import mage.MageInt; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SubType; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public final class ZephyrGull extends CardImpl { + + public ZephyrGull(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{U}"); + this.subtype.add(SubType.BIRD); + + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Flying + this.addAbility(FlyingAbility.getInstance()); + } + + public ZephyrGull(final ZephyrGull card) { + super(card); + } + + @Override + public ZephyrGull copy() { + return new ZephyrGull(this); + } +} diff --git a/Mage.Sets/src/mage/sets/ArenaNewPlayerExperience.java b/Mage.Sets/src/mage/sets/ArenaNewPlayerExperience.java new file mode 100644 index 00000000000..aaad1327f93 --- /dev/null +++ b/Mage.Sets/src/mage/sets/ArenaNewPlayerExperience.java @@ -0,0 +1,63 @@ +package mage.sets; + +import mage.cards.ExpansionSet; +import mage.constants.Rarity; +import mage.constants.SetType; + +/** + * @author JayDi85 + */ +public final class ArenaNewPlayerExperience extends ExpansionSet { + + private static final ArenaNewPlayerExperience instance = new ArenaNewPlayerExperience(); + + public static ArenaNewPlayerExperience getInstance() { + return instance; + } + + private ArenaNewPlayerExperience() { + super("Arena New Player Experience", "ANA", ExpansionSet.buildDate(2018, 7, 29), SetType.MAGIC_ONLINE); + this.hasBoosters = false; + this.hasBasicLands = false; + + cards.add(new SetCardInfo("Altar's Reap", 24, Rarity.COMMON, mage.cards.a.AltarsReap.class)); + cards.add(new SetCardInfo("Ambition's Cost", 25, Rarity.UNCOMMON, mage.cards.a.AmbitionsCost.class)); + cards.add(new SetCardInfo("Angelic Reward", 1, Rarity.UNCOMMON, mage.cards.a.AngelicReward.class)); + cards.add(new SetCardInfo("Blinding Radiance", 2, Rarity.UNCOMMON, mage.cards.b.BlindingRadiance.class)); + cards.add(new SetCardInfo("Chaos Maw", 36, Rarity.RARE, mage.cards.c.ChaosMaw.class)); + cards.add(new SetCardInfo("Confront the Assault", 3, Rarity.UNCOMMON, mage.cards.c.ConfrontTheAssault.class)); + cards.add(new SetCardInfo("Cruel Cut", 26, Rarity.COMMON, mage.cards.c.CruelCut.class)); + cards.add(new SetCardInfo("Divination", 14, Rarity.COMMON, mage.cards.d.Divination.class)); + cards.add(new SetCardInfo("Doublecast", 37, Rarity.UNCOMMON, mage.cards.d.Doublecast.class)); + cards.add(new SetCardInfo("Feral Roar", 46, Rarity.COMMON, mage.cards.f.FeralRoar.class)); + cards.add(new SetCardInfo("Goblin Bruiser", 39, Rarity.UNCOMMON, mage.cards.g.GoblinBruiser.class)); + cards.add(new SetCardInfo("Goblin Gang Leader", 40, Rarity.UNCOMMON, mage.cards.g.GoblinGangLeader.class)); + cards.add(new SetCardInfo("Goblin Grenade", 41, Rarity.UNCOMMON, mage.cards.g.GoblinGrenade.class)); + cards.add(new SetCardInfo("Inspiring Commander", 5, Rarity.RARE, mage.cards.i.InspiringCommander.class)); + cards.add(new SetCardInfo("Knight's Pledge", 6, Rarity.COMMON, mage.cards.k.KnightsPledge.class)); + cards.add(new SetCardInfo("Loxodon Line Breaker", 7, Rarity.COMMON, mage.cards.l.LoxodonLineBreaker.class)); + cards.add(new SetCardInfo("Miasmic Mummy", 29, Rarity.COMMON, mage.cards.m.MiasmicMummy.class)); + cards.add(new SetCardInfo("Nimble Pilferer", 31, Rarity.COMMON, mage.cards.n.NimblePilferer.class)); + cards.add(new SetCardInfo("Ogre Painbringer", 42, Rarity.RARE, mage.cards.o.OgrePainbringer.class)); + cards.add(new SetCardInfo("Overflowing Insight", 16, Rarity.MYTHIC, mage.cards.o.OverflowingInsight.class)); + cards.add(new SetCardInfo("Raging Goblin", 43, Rarity.COMMON, mage.cards.r.RagingGoblin.class)); + cards.add(new SetCardInfo("Renegade Demon", 33, Rarity.COMMON, mage.cards.r.RenegadeDemon.class)); + cards.add(new SetCardInfo("Rise from the Grave", 34, Rarity.UNCOMMON, mage.cards.r.RiseFromTheGrave.class)); + cards.add(new SetCardInfo("River's Favor", 17, Rarity.COMMON, mage.cards.r.RiversFavor.class)); + cards.add(new SetCardInfo("Rumbling Baloth", 47, Rarity.COMMON, mage.cards.r.RumblingBaloth.class)); + cards.add(new SetCardInfo("Sanctuary Cat", 8, Rarity.COMMON, mage.cards.s.SanctuaryCat.class)); + cards.add(new SetCardInfo("Seismic Rupture", 44, Rarity.UNCOMMON, mage.cards.s.SeismicRupture.class)); + cards.add(new SetCardInfo("Serra Angel", 9, Rarity.UNCOMMON, mage.cards.s.SerraAngel.class)); + cards.add(new SetCardInfo("Shorecomber Crab", 18, Rarity.COMMON, mage.cards.s.ShorecomberCrab.class)); + cards.add(new SetCardInfo("Shrine Keeper", 10, Rarity.COMMON, mage.cards.s.ShrineKeeper.class)); + cards.add(new SetCardInfo("Soulhunter Rakshasa", 35, Rarity.RARE, mage.cards.s.SoulhunterRakshasa.class)); + cards.add(new SetCardInfo("Spiritual Guardian", 11, Rarity.COMMON, mage.cards.s.SpiritualGuardian.class)); + cards.add(new SetCardInfo("Tactical Advantage", 12, Rarity.COMMON, mage.cards.t.TacticalAdvantage.class)); + cards.add(new SetCardInfo("Take Vengeance", 13, Rarity.COMMON, mage.cards.t.TakeVengeance.class)); + cards.add(new SetCardInfo("Titanic Pelagosaur", 19, Rarity.UNCOMMON, mage.cards.t.TitanicPelagosaur.class)); + cards.add(new SetCardInfo("Treetop Warden", 48, Rarity.COMMON, mage.cards.t.TreetopWarden.class)); + cards.add(new SetCardInfo("Volcanic Dragon", 45, Rarity.UNCOMMON, mage.cards.v.VolcanicDragon.class)); + cards.add(new SetCardInfo("Waterknot", 22, Rarity.COMMON, mage.cards.w.Waterknot.class)); + cards.add(new SetCardInfo("Zephyr Gull", 23, Rarity.COMMON, mage.cards.z.ZephyrGull.class)); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/Chronicles.java b/Mage.Sets/src/mage/sets/Chronicles.java index 03cde6e56d1..66a72016426 100644 --- a/Mage.Sets/src/mage/sets/Chronicles.java +++ b/Mage.Sets/src/mage/sets/Chronicles.java @@ -1,147 +1,149 @@ -package mage.sets; - -import mage.cards.ExpansionSet; -import mage.constants.Rarity; -import mage.constants.SetType; - -/** - * - * @author LevelX2 - */ -public final class Chronicles extends ExpansionSet { - - private static final Chronicles instance = new Chronicles(); - - public static Chronicles getInstance() { - return instance; - } - - private Chronicles() { - super("Chronicles", "CHR", ExpansionSet.buildDate(1995, 6, 1), SetType.SUPPLEMENTAL); - this.blockName = "Reprint"; - this.hasBasicLands = false; - this.hasBoosters = true; - this.numBoosterLands = 0; - this.numBoosterCommon = 9; - this.numBoosterUncommon = 2; - this.numBoosterRare = 1; - this.ratioBoosterMythic = 0; - cards.add(new SetCardInfo("Abu Ja'far", 57, Rarity.UNCOMMON, mage.cards.a.AbuJafar.class)); - cards.add(new SetCardInfo("Active Volcano", 43, Rarity.COMMON, mage.cards.a.ActiveVolcano.class)); - cards.add(new SetCardInfo("Akron Legionnaire", 58, Rarity.RARE, mage.cards.a.AkronLegionnaire.class)); - cards.add(new SetCardInfo("Aladdin", 44, Rarity.UNCOMMON, mage.cards.a.Aladdin.class)); - cards.add(new SetCardInfo("Angelic Voices", 59, Rarity.RARE, mage.cards.a.AngelicVoices.class)); - cards.add(new SetCardInfo("Arcades Sabboth", 106, Rarity.RARE, mage.cards.a.ArcadesSabboth.class)); - cards.add(new SetCardInfo("Arena of the Ancients", 71, Rarity.RARE, mage.cards.a.ArenaOfTheAncients.class)); - cards.add(new SetCardInfo("Argothian Pixies", 29, Rarity.COMMON, mage.cards.a.ArgothianPixies.class)); - cards.add(new SetCardInfo("Ashnod's Altar", 72, Rarity.COMMON, mage.cards.a.AshnodsAltar.class)); - cards.add(new SetCardInfo("Ashnod's Transmogrant", 73, Rarity.COMMON, mage.cards.a.AshnodsTransmogrant.class)); - cards.add(new SetCardInfo("Axelrod Gunnarson", 107, Rarity.RARE, mage.cards.a.AxelrodGunnarson.class)); - cards.add(new SetCardInfo("Ayesha Tanaka", 108, Rarity.RARE, mage.cards.a.AyeshaTanaka.class)); - cards.add(new SetCardInfo("Azure Drake", 15, Rarity.UNCOMMON, mage.cards.a.AzureDrake.class)); - cards.add(new SetCardInfo("Banshee", 1, Rarity.UNCOMMON, mage.cards.b.Banshee.class)); - cards.add(new SetCardInfo("Barl's Cage", 74, Rarity.RARE, mage.cards.b.BarlsCage.class)); - cards.add(new SetCardInfo("Beasts of Bogardan", 45, Rarity.UNCOMMON, mage.cards.b.BeastsOfBogardan.class)); - cards.add(new SetCardInfo("Blood Moon", 46, Rarity.RARE, mage.cards.b.BloodMoon.class)); - cards.add(new SetCardInfo("Blood of the Martyr", 60, Rarity.UNCOMMON, mage.cards.b.BloodOfTheMartyr.class)); - cards.add(new SetCardInfo("Bog Rats", 2, Rarity.COMMON, mage.cards.b.BogRats.class)); - cards.add(new SetCardInfo("Book of Rass", 75, Rarity.RARE, mage.cards.b.BookOfRass.class)); - cards.add(new SetCardInfo("Boomerang", 16, Rarity.COMMON, mage.cards.b.Boomerang.class)); - cards.add(new SetCardInfo("Cat Warriors", 30, Rarity.COMMON, mage.cards.c.CatWarriors.class)); - cards.add(new SetCardInfo("Chromium", 109, Rarity.RARE, mage.cards.c.Chromium.class)); - cards.add(new SetCardInfo("City of Brass", 92, Rarity.RARE, mage.cards.c.CityOfBrass.class)); - cards.add(new SetCardInfo("Concordant Crossroads", 32, Rarity.RARE, mage.cards.c.ConcordantCrossroads.class)); - cards.add(new SetCardInfo("Craw Giant", 33, Rarity.UNCOMMON, mage.cards.c.CrawGiant.class)); - cards.add(new SetCardInfo("Cuombajj Witches", 3, Rarity.COMMON, mage.cards.c.CuombajjWitches.class)); - cards.add(new SetCardInfo("Cyclone", 34, Rarity.RARE, mage.cards.c.Cyclone.class)); - cards.add(new SetCardInfo("Dakkon Blackblade", 110, Rarity.RARE, mage.cards.d.DakkonBlackblade.class)); - cards.add(new SetCardInfo("Dance of Many", 17, Rarity.RARE, mage.cards.d.DanceOfMany.class)); - cards.add(new SetCardInfo("Dandan", 18, Rarity.COMMON, mage.cards.d.Dandan.class)); - cards.add(new SetCardInfo("D'Avenant Archer", 61, Rarity.COMMON, mage.cards.d.DAvenantArcher.class)); - cards.add(new SetCardInfo("Divine Offering", 62, Rarity.COMMON, mage.cards.d.DivineOffering.class)); - cards.add(new SetCardInfo("Emerald Dragonfly", 35, Rarity.COMMON, mage.cards.e.EmeraldDragonfly.class)); - cards.add(new SetCardInfo("Erhnam Djinn", 36, Rarity.UNCOMMON, mage.cards.e.ErhnamDjinn.class)); - cards.add(new SetCardInfo("Fallen Angel", 4, Rarity.UNCOMMON, mage.cards.f.FallenAngel.class)); - cards.add(new SetCardInfo("Feldon's Cane", 77, Rarity.COMMON, mage.cards.f.FeldonsCane.class)); - cards.add(new SetCardInfo("Fire Drake", 47, Rarity.UNCOMMON, mage.cards.f.FireDrake.class)); - cards.add(new SetCardInfo("Fishliver Oil", 20, Rarity.COMMON, mage.cards.f.FishliverOil.class)); - cards.add(new SetCardInfo("Flash Flood", 21, Rarity.COMMON, mage.cards.f.FlashFlood.class)); - cards.add(new SetCardInfo("Fountain of Youth", 78, Rarity.COMMON, mage.cards.f.FountainOfYouth.class)); - cards.add(new SetCardInfo("Gabriel Angelfire", 111, Rarity.RARE, mage.cards.g.GabrielAngelfire.class)); - cards.add(new SetCardInfo("Gauntlets of Chaos", 79, Rarity.RARE, mage.cards.g.GauntletsOfChaos.class)); - cards.add(new SetCardInfo("Ghazban Ogre", 37, Rarity.COMMON, mage.cards.g.GhazbanOgre.class)); - cards.add(new SetCardInfo("Goblin Artisans", 48, Rarity.UNCOMMON, mage.cards.g.GoblinArtisans.class)); - cards.add(new SetCardInfo("Goblin Digging Team", 49, Rarity.COMMON, mage.cards.g.GoblinDiggingTeam.class)); - cards.add(new SetCardInfo("Goblin Shrine", 50, Rarity.COMMON, mage.cards.g.GoblinShrine.class)); - cards.add(new SetCardInfo("Goblins of the Flarg", 51, Rarity.COMMON, mage.cards.g.GoblinsOfTheFlarg.class)); - cards.add(new SetCardInfo("Hasran Ogress", 6, Rarity.COMMON, mage.cards.h.HasranOgress.class)); - cards.add(new SetCardInfo("Hell's Caretaker", 7, Rarity.RARE, mage.cards.h.HellsCaretaker.class)); - cards.add(new SetCardInfo("Horn of Deafening", 80, Rarity.RARE, mage.cards.h.HornOfDeafening.class)); - cards.add(new SetCardInfo("Indestructible Aura", 63, Rarity.COMMON, mage.cards.i.IndestructibleAura.class)); - cards.add(new SetCardInfo("Ivory Guardians", 64, Rarity.UNCOMMON, mage.cards.i.IvoryGuardians.class)); - cards.add(new SetCardInfo("Jalum Tome", 81, Rarity.RARE, mage.cards.j.JalumTome.class)); - cards.add(new SetCardInfo("Johan", 112, Rarity.RARE, mage.cards.j.Johan.class)); - cards.add(new SetCardInfo("Juxtapose", 22, Rarity.RARE, mage.cards.j.Juxtapose.class)); - cards.add(new SetCardInfo("Keepers of the Faith", 65, Rarity.COMMON, mage.cards.k.KeepersOfTheFaith.class)); - cards.add(new SetCardInfo("Kei Takahashi", 113, Rarity.UNCOMMON, mage.cards.k.KeiTakahashi.class)); - cards.add(new SetCardInfo("Land's Edge", 52, Rarity.RARE, mage.cards.l.LandsEdge.class)); - cards.add(new SetCardInfo("Living Armor", 83, Rarity.COMMON, mage.cards.l.LivingArmor.class)); - cards.add(new SetCardInfo("Marhault Elsdragon", 114, Rarity.UNCOMMON, mage.cards.m.MarhaultElsdragon.class)); - cards.add(new SetCardInfo("Metamorphosis", 38, Rarity.COMMON, mage.cards.m.Metamorphosis.class)); - cards.add(new SetCardInfo("Mountain Yeti", 53, Rarity.COMMON, mage.cards.m.MountainYeti.class)); - cards.add(new SetCardInfo("Nebuchadnezzar", 115, Rarity.RARE, mage.cards.n.Nebuchadnezzar.class)); - cards.add(new SetCardInfo("Nicol Bolas", 116, Rarity.RARE, mage.cards.n.NicolBolas.class)); - cards.add(new SetCardInfo("Obelisk of Undoing", 84, Rarity.RARE, mage.cards.o.ObeliskOfUndoing.class)); - cards.add(new SetCardInfo("Palladia-Mors", 117, Rarity.RARE, mage.cards.p.PalladiaMors.class)); - cards.add(new SetCardInfo("Petra Sphinx", 66, Rarity.RARE, mage.cards.p.PetraSphinx.class)); - cards.add(new SetCardInfo("Primordial Ooze", 54, Rarity.UNCOMMON, mage.cards.p.PrimordialOoze.class)); - cards.add(new SetCardInfo("Rabid Wombat", 39, Rarity.UNCOMMON, mage.cards.r.RabidWombat.class)); - cards.add(new SetCardInfo("Rakalite", 85, Rarity.RARE, mage.cards.r.Rakalite.class)); - cards.add(new SetCardInfo("Recall", 24, Rarity.UNCOMMON, mage.cards.r.Recall.class)); - cards.add(new SetCardInfo("Remove Soul", 25, Rarity.COMMON, mage.cards.r.RemoveSoul.class)); - cards.add(new SetCardInfo("Repentant Blacksmith", 67, Rarity.COMMON, mage.cards.r.RepentantBlacksmith.class)); - cards.add(new SetCardInfo("Revelation", 40, Rarity.RARE, mage.cards.r.Revelation.class)); - cards.add(new SetCardInfo("Rubinia Soulsinger", 118, Rarity.RARE, mage.cards.r.RubiniaSoulsinger.class)); - cards.add(new SetCardInfo("Runesword", 86, Rarity.COMMON, mage.cards.r.Runesword.class)); - cards.add(new SetCardInfo("Safe Haven", 93, Rarity.RARE, mage.cards.s.SafeHaven.class)); - cards.add(new SetCardInfo("Scavenger Folk", 41, Rarity.COMMON, mage.cards.s.ScavengerFolk.class)); - cards.add(new SetCardInfo("Sentinel", 87, Rarity.RARE, mage.cards.s.Sentinel.class)); - cards.add(new SetCardInfo("Serpent Generator", 88, Rarity.RARE, mage.cards.s.SerpentGenerator.class)); - cards.add(new SetCardInfo("Shield Wall", 68, Rarity.UNCOMMON, mage.cards.s.ShieldWall.class)); - cards.add(new SetCardInfo("Shimian Night Stalker", 8, Rarity.UNCOMMON, mage.cards.s.ShimianNightStalker.class)); - cards.add(new SetCardInfo("Sivitri Scarzam", 119, Rarity.UNCOMMON, mage.cards.s.SivitriScarzam.class)); - cards.add(new SetCardInfo("Sol'kanar the Swamp King", 120, Rarity.RARE, mage.cards.s.SolkanarTheSwampKing.class)); - cards.add(new SetCardInfo("Stangg", 121, Rarity.RARE, mage.cards.s.Stangg.class)); - cards.add(new SetCardInfo("Storm Seeker", 42, Rarity.UNCOMMON, mage.cards.s.StormSeeker.class)); - cards.add(new SetCardInfo("Teleport", 26, Rarity.RARE, mage.cards.t.Teleport.class)); - cards.add(new SetCardInfo("The Fallen", 10, Rarity.UNCOMMON, mage.cards.t.TheFallen.class)); - cards.add(new SetCardInfo("The Wretched", 11, Rarity.RARE, mage.cards.t.TheWretched.class)); - cards.add(new SetCardInfo("Tobias Andrion", 122, Rarity.UNCOMMON, mage.cards.t.TobiasAndrion.class)); - cards.add(new SetCardInfo("Tormod's Crypt", 89, Rarity.COMMON, mage.cards.t.TormodsCrypt.class)); - cards.add(new SetCardInfo("Tor Wauki", 123, Rarity.UNCOMMON, mage.cards.t.TorWauki.class)); - cards.add(new SetCardInfo("Transmutation", 12, Rarity.COMMON, mage.cards.t.Transmutation.class)); - cards.add(new SetCardInfo("Triassic Egg", 90, Rarity.RARE, mage.cards.t.TriassicEgg.class)); - cards.add(new SetCardInfo("Urza's Mine", 94, Rarity.UNCOMMON, mage.cards.u.UrzasMine.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Urza's Mine", 95, Rarity.UNCOMMON, mage.cards.u.UrzasMine.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Urza's Mine", 96, Rarity.UNCOMMON, mage.cards.u.UrzasMine.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Urza's Mine", 97, Rarity.UNCOMMON, mage.cards.u.UrzasMine.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Urza's Power Plant", 98, Rarity.UNCOMMON, mage.cards.u.UrzasPowerPlant.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Urza's Power Plant", 99, Rarity.UNCOMMON, mage.cards.u.UrzasPowerPlant.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Urza's Power Plant", 100, Rarity.UNCOMMON, mage.cards.u.UrzasPowerPlant.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Urza's Power Plant", 101, Rarity.UNCOMMON, mage.cards.u.UrzasPowerPlant.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Urza's Tower", 102, Rarity.UNCOMMON, mage.cards.u.UrzasTower.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Urza's Tower", 103, Rarity.UNCOMMON, mage.cards.u.UrzasTower.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Urza's Tower", 104, Rarity.UNCOMMON, mage.cards.u.UrzasTower.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Urza's Tower", 105, Rarity.UNCOMMON, mage.cards.u.UrzasTower.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Vaevictis Asmadi", 124, Rarity.RARE, mage.cards.v.VaevictisAsmadi.class)); - cards.add(new SetCardInfo("Wall of Heat", 55, Rarity.COMMON, mage.cards.w.WallOfHeat.class)); - cards.add(new SetCardInfo("Wall of Opposition", 56, Rarity.UNCOMMON, mage.cards.w.WallOfOpposition.class)); - cards.add(new SetCardInfo("Wall of Vapor", 27, Rarity.COMMON, mage.cards.w.WallOfVapor.class)); - cards.add(new SetCardInfo("Wall of Wonder", 28, Rarity.UNCOMMON, mage.cards.w.WallOfWonder.class)); - cards.add(new SetCardInfo("War Elephant", 69, Rarity.COMMON, mage.cards.w.WarElephant.class)); - cards.add(new SetCardInfo("Witch Hunter", 70, Rarity.UNCOMMON, mage.cards.w.WitchHunter.class)); - cards.add(new SetCardInfo("Xira Arien", 125, Rarity.RARE, mage.cards.x.XiraArien.class)); - cards.add(new SetCardInfo("Yawgmoth Demon", 14, Rarity.RARE, mage.cards.y.YawgmothDemon.class)); - } - -} +package mage.sets; + +import mage.cards.ExpansionSet; +import mage.constants.Rarity; +import mage.constants.SetType; + +/** + * + * @author LevelX2 + */ +public final class Chronicles extends ExpansionSet { + + private static final Chronicles instance = new Chronicles(); + + public static Chronicles getInstance() { + return instance; + } + + private Chronicles() { + super("Chronicles", "CHR", ExpansionSet.buildDate(1995, 6, 1), SetType.SUPPLEMENTAL); + this.blockName = "Reprint"; + this.hasBasicLands = false; + this.hasBoosters = true; + this.numBoosterLands = 0; + this.numBoosterCommon = 9; + this.numBoosterUncommon = 2; + this.numBoosterRare = 1; + this.ratioBoosterMythic = 0; + cards.add(new SetCardInfo("Abu Ja'far", 57, Rarity.UNCOMMON, mage.cards.a.AbuJafar.class)); + cards.add(new SetCardInfo("Active Volcano", 43, Rarity.COMMON, mage.cards.a.ActiveVolcano.class)); + cards.add(new SetCardInfo("Akron Legionnaire", 58, Rarity.RARE, mage.cards.a.AkronLegionnaire.class)); + cards.add(new SetCardInfo("Aladdin", 44, Rarity.UNCOMMON, mage.cards.a.Aladdin.class)); + cards.add(new SetCardInfo("Angelic Voices", 59, Rarity.RARE, mage.cards.a.AngelicVoices.class)); + cards.add(new SetCardInfo("Arcades Sabboth", 106, Rarity.RARE, mage.cards.a.ArcadesSabboth.class)); + cards.add(new SetCardInfo("Arena of the Ancients", 71, Rarity.RARE, mage.cards.a.ArenaOfTheAncients.class)); + cards.add(new SetCardInfo("Argothian Pixies", 29, Rarity.COMMON, mage.cards.a.ArgothianPixies.class)); + cards.add(new SetCardInfo("Ashnod's Altar", 72, Rarity.COMMON, mage.cards.a.AshnodsAltar.class)); + cards.add(new SetCardInfo("Ashnod's Transmogrant", 73, Rarity.COMMON, mage.cards.a.AshnodsTransmogrant.class)); + cards.add(new SetCardInfo("Axelrod Gunnarson", 107, Rarity.RARE, mage.cards.a.AxelrodGunnarson.class)); + cards.add(new SetCardInfo("Ayesha Tanaka", 108, Rarity.RARE, mage.cards.a.AyeshaTanaka.class)); + cards.add(new SetCardInfo("Azure Drake", 15, Rarity.UNCOMMON, mage.cards.a.AzureDrake.class)); + cards.add(new SetCardInfo("Banshee", 1, Rarity.UNCOMMON, mage.cards.b.Banshee.class)); + cards.add(new SetCardInfo("Barl's Cage", 74, Rarity.RARE, mage.cards.b.BarlsCage.class)); + cards.add(new SetCardInfo("Beasts of Bogardan", 45, Rarity.UNCOMMON, mage.cards.b.BeastsOfBogardan.class)); + cards.add(new SetCardInfo("Blood Moon", 46, Rarity.RARE, mage.cards.b.BloodMoon.class)); + cards.add(new SetCardInfo("Blood of the Martyr", 60, Rarity.UNCOMMON, mage.cards.b.BloodOfTheMartyr.class)); + cards.add(new SetCardInfo("Bog Rats", 2, Rarity.COMMON, mage.cards.b.BogRats.class)); + cards.add(new SetCardInfo("Book of Rass", 75, Rarity.RARE, mage.cards.b.BookOfRass.class)); + cards.add(new SetCardInfo("Boomerang", 16, Rarity.COMMON, mage.cards.b.Boomerang.class)); + cards.add(new SetCardInfo("Bronze Horse", 76, Rarity.RARE, mage.cards.b.BronzeHorse.class)); + cards.add(new SetCardInfo("Cat Warriors", 30, Rarity.COMMON, mage.cards.c.CatWarriors.class)); + cards.add(new SetCardInfo("Chromium", 109, Rarity.RARE, mage.cards.c.Chromium.class)); + cards.add(new SetCardInfo("City of Brass", 92, Rarity.RARE, mage.cards.c.CityOfBrass.class)); + cards.add(new SetCardInfo("Concordant Crossroads", 32, Rarity.RARE, mage.cards.c.ConcordantCrossroads.class)); + cards.add(new SetCardInfo("Craw Giant", 33, Rarity.UNCOMMON, mage.cards.c.CrawGiant.class)); + cards.add(new SetCardInfo("Cuombajj Witches", 3, Rarity.COMMON, mage.cards.c.CuombajjWitches.class)); + cards.add(new SetCardInfo("Cyclone", 34, Rarity.RARE, mage.cards.c.Cyclone.class)); + cards.add(new SetCardInfo("Dakkon Blackblade", 110, Rarity.RARE, mage.cards.d.DakkonBlackblade.class)); + cards.add(new SetCardInfo("Dance of Many", 17, Rarity.RARE, mage.cards.d.DanceOfMany.class)); + cards.add(new SetCardInfo("Dandan", 18, Rarity.COMMON, mage.cards.d.Dandan.class)); + cards.add(new SetCardInfo("D'Avenant Archer", 61, Rarity.COMMON, mage.cards.d.DAvenantArcher.class)); + cards.add(new SetCardInfo("Divine Offering", 62, Rarity.COMMON, mage.cards.d.DivineOffering.class)); + cards.add(new SetCardInfo("Emerald Dragonfly", 35, Rarity.COMMON, mage.cards.e.EmeraldDragonfly.class)); + cards.add(new SetCardInfo("Enchantment Alteration", 19, Rarity.UNCOMMON, mage.cards.e.EnchantmentAlteration.class)); + cards.add(new SetCardInfo("Erhnam Djinn", 36, Rarity.UNCOMMON, mage.cards.e.ErhnamDjinn.class)); + cards.add(new SetCardInfo("Fallen Angel", 4, Rarity.UNCOMMON, mage.cards.f.FallenAngel.class)); + cards.add(new SetCardInfo("Feldon's Cane", 77, Rarity.COMMON, mage.cards.f.FeldonsCane.class)); + cards.add(new SetCardInfo("Fire Drake", 47, Rarity.UNCOMMON, mage.cards.f.FireDrake.class)); + cards.add(new SetCardInfo("Fishliver Oil", 20, Rarity.COMMON, mage.cards.f.FishliverOil.class)); + cards.add(new SetCardInfo("Flash Flood", 21, Rarity.COMMON, mage.cards.f.FlashFlood.class)); + cards.add(new SetCardInfo("Fountain of Youth", 78, Rarity.COMMON, mage.cards.f.FountainOfYouth.class)); + cards.add(new SetCardInfo("Gabriel Angelfire", 111, Rarity.RARE, mage.cards.g.GabrielAngelfire.class)); + cards.add(new SetCardInfo("Gauntlets of Chaos", 79, Rarity.RARE, mage.cards.g.GauntletsOfChaos.class)); + cards.add(new SetCardInfo("Ghazban Ogre", 37, Rarity.COMMON, mage.cards.g.GhazbanOgre.class)); + cards.add(new SetCardInfo("Goblin Artisans", 48, Rarity.UNCOMMON, mage.cards.g.GoblinArtisans.class)); + cards.add(new SetCardInfo("Goblin Digging Team", 49, Rarity.COMMON, mage.cards.g.GoblinDiggingTeam.class)); + cards.add(new SetCardInfo("Goblin Shrine", 50, Rarity.COMMON, mage.cards.g.GoblinShrine.class)); + cards.add(new SetCardInfo("Goblins of the Flarg", 51, Rarity.COMMON, mage.cards.g.GoblinsOfTheFlarg.class)); + cards.add(new SetCardInfo("Hasran Ogress", 6, Rarity.COMMON, mage.cards.h.HasranOgress.class)); + cards.add(new SetCardInfo("Hell's Caretaker", 7, Rarity.RARE, mage.cards.h.HellsCaretaker.class)); + cards.add(new SetCardInfo("Horn of Deafening", 80, Rarity.RARE, mage.cards.h.HornOfDeafening.class)); + cards.add(new SetCardInfo("Indestructible Aura", 63, Rarity.COMMON, mage.cards.i.IndestructibleAura.class)); + cards.add(new SetCardInfo("Ivory Guardians", 64, Rarity.UNCOMMON, mage.cards.i.IvoryGuardians.class)); + cards.add(new SetCardInfo("Jalum Tome", 81, Rarity.RARE, mage.cards.j.JalumTome.class)); + cards.add(new SetCardInfo("Johan", 112, Rarity.RARE, mage.cards.j.Johan.class)); + cards.add(new SetCardInfo("Juxtapose", 22, Rarity.RARE, mage.cards.j.Juxtapose.class)); + cards.add(new SetCardInfo("Keepers of the Faith", 65, Rarity.COMMON, mage.cards.k.KeepersOfTheFaith.class)); + cards.add(new SetCardInfo("Kei Takahashi", 113, Rarity.UNCOMMON, mage.cards.k.KeiTakahashi.class)); + cards.add(new SetCardInfo("Land's Edge", 52, Rarity.RARE, mage.cards.l.LandsEdge.class)); + cards.add(new SetCardInfo("Living Armor", 83, Rarity.COMMON, mage.cards.l.LivingArmor.class)); + cards.add(new SetCardInfo("Marhault Elsdragon", 114, Rarity.UNCOMMON, mage.cards.m.MarhaultElsdragon.class)); + cards.add(new SetCardInfo("Metamorphosis", 38, Rarity.COMMON, mage.cards.m.Metamorphosis.class)); + cards.add(new SetCardInfo("Mountain Yeti", 53, Rarity.COMMON, mage.cards.m.MountainYeti.class)); + cards.add(new SetCardInfo("Nebuchadnezzar", 115, Rarity.RARE, mage.cards.n.Nebuchadnezzar.class)); + cards.add(new SetCardInfo("Nicol Bolas", 116, Rarity.RARE, mage.cards.n.NicolBolas.class)); + cards.add(new SetCardInfo("Obelisk of Undoing", 84, Rarity.RARE, mage.cards.o.ObeliskOfUndoing.class)); + cards.add(new SetCardInfo("Palladia-Mors", 117, Rarity.RARE, mage.cards.p.PalladiaMors.class)); + cards.add(new SetCardInfo("Petra Sphinx", 66, Rarity.RARE, mage.cards.p.PetraSphinx.class)); + cards.add(new SetCardInfo("Primordial Ooze", 54, Rarity.UNCOMMON, mage.cards.p.PrimordialOoze.class)); + cards.add(new SetCardInfo("Rabid Wombat", 39, Rarity.UNCOMMON, mage.cards.r.RabidWombat.class)); + cards.add(new SetCardInfo("Rakalite", 85, Rarity.RARE, mage.cards.r.Rakalite.class)); + cards.add(new SetCardInfo("Recall", 24, Rarity.UNCOMMON, mage.cards.r.Recall.class)); + cards.add(new SetCardInfo("Remove Soul", 25, Rarity.COMMON, mage.cards.r.RemoveSoul.class)); + cards.add(new SetCardInfo("Repentant Blacksmith", 67, Rarity.COMMON, mage.cards.r.RepentantBlacksmith.class)); + cards.add(new SetCardInfo("Revelation", 40, Rarity.RARE, mage.cards.r.Revelation.class)); + cards.add(new SetCardInfo("Rubinia Soulsinger", 118, Rarity.RARE, mage.cards.r.RubiniaSoulsinger.class)); + cards.add(new SetCardInfo("Runesword", 86, Rarity.COMMON, mage.cards.r.Runesword.class)); + cards.add(new SetCardInfo("Safe Haven", 93, Rarity.RARE, mage.cards.s.SafeHaven.class)); + cards.add(new SetCardInfo("Scavenger Folk", 41, Rarity.COMMON, mage.cards.s.ScavengerFolk.class)); + cards.add(new SetCardInfo("Sentinel", 87, Rarity.RARE, mage.cards.s.Sentinel.class)); + cards.add(new SetCardInfo("Serpent Generator", 88, Rarity.RARE, mage.cards.s.SerpentGenerator.class)); + cards.add(new SetCardInfo("Shield Wall", 68, Rarity.UNCOMMON, mage.cards.s.ShieldWall.class)); + cards.add(new SetCardInfo("Shimian Night Stalker", 8, Rarity.UNCOMMON, mage.cards.s.ShimianNightStalker.class)); + cards.add(new SetCardInfo("Sivitri Scarzam", 119, Rarity.UNCOMMON, mage.cards.s.SivitriScarzam.class)); + cards.add(new SetCardInfo("Sol'kanar the Swamp King", 120, Rarity.RARE, mage.cards.s.SolkanarTheSwampKing.class)); + cards.add(new SetCardInfo("Stangg", 121, Rarity.RARE, mage.cards.s.Stangg.class)); + cards.add(new SetCardInfo("Storm Seeker", 42, Rarity.UNCOMMON, mage.cards.s.StormSeeker.class)); + cards.add(new SetCardInfo("Teleport", 26, Rarity.RARE, mage.cards.t.Teleport.class)); + cards.add(new SetCardInfo("The Fallen", 10, Rarity.UNCOMMON, mage.cards.t.TheFallen.class)); + cards.add(new SetCardInfo("The Wretched", 11, Rarity.RARE, mage.cards.t.TheWretched.class)); + cards.add(new SetCardInfo("Tobias Andrion", 122, Rarity.UNCOMMON, mage.cards.t.TobiasAndrion.class)); + cards.add(new SetCardInfo("Tormod's Crypt", 89, Rarity.COMMON, mage.cards.t.TormodsCrypt.class)); + cards.add(new SetCardInfo("Tor Wauki", 123, Rarity.UNCOMMON, mage.cards.t.TorWauki.class)); + cards.add(new SetCardInfo("Transmutation", 12, Rarity.COMMON, mage.cards.t.Transmutation.class)); + cards.add(new SetCardInfo("Triassic Egg", 90, Rarity.RARE, mage.cards.t.TriassicEgg.class)); + cards.add(new SetCardInfo("Urza's Mine", 94, Rarity.UNCOMMON, mage.cards.u.UrzasMine.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Urza's Mine", 95, Rarity.UNCOMMON, mage.cards.u.UrzasMine.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Urza's Mine", 96, Rarity.UNCOMMON, mage.cards.u.UrzasMine.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Urza's Mine", 97, Rarity.UNCOMMON, mage.cards.u.UrzasMine.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Urza's Power Plant", 98, Rarity.UNCOMMON, mage.cards.u.UrzasPowerPlant.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Urza's Power Plant", 99, Rarity.UNCOMMON, mage.cards.u.UrzasPowerPlant.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Urza's Power Plant", 100, Rarity.UNCOMMON, mage.cards.u.UrzasPowerPlant.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Urza's Power Plant", 101, Rarity.UNCOMMON, mage.cards.u.UrzasPowerPlant.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Urza's Tower", 102, Rarity.UNCOMMON, mage.cards.u.UrzasTower.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Urza's Tower", 103, Rarity.UNCOMMON, mage.cards.u.UrzasTower.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Urza's Tower", 104, Rarity.UNCOMMON, mage.cards.u.UrzasTower.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Urza's Tower", 105, Rarity.UNCOMMON, mage.cards.u.UrzasTower.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Vaevictis Asmadi", 124, Rarity.RARE, mage.cards.v.VaevictisAsmadi.class)); + cards.add(new SetCardInfo("Wall of Heat", 55, Rarity.COMMON, mage.cards.w.WallOfHeat.class)); + cards.add(new SetCardInfo("Wall of Opposition", 56, Rarity.UNCOMMON, mage.cards.w.WallOfOpposition.class)); + cards.add(new SetCardInfo("Wall of Vapor", 27, Rarity.COMMON, mage.cards.w.WallOfVapor.class)); + cards.add(new SetCardInfo("Wall of Wonder", 28, Rarity.UNCOMMON, mage.cards.w.WallOfWonder.class)); + cards.add(new SetCardInfo("War Elephant", 69, Rarity.COMMON, mage.cards.w.WarElephant.class)); + cards.add(new SetCardInfo("Witch Hunter", 70, Rarity.UNCOMMON, mage.cards.w.WitchHunter.class)); + cards.add(new SetCardInfo("Xira Arien", 125, Rarity.RARE, mage.cards.x.XiraArien.class)); + cards.add(new SetCardInfo("Yawgmoth Demon", 14, Rarity.RARE, mage.cards.y.YawgmothDemon.class)); + } + +} diff --git a/Mage.Sets/src/mage/sets/Conspiracy.java b/Mage.Sets/src/mage/sets/Conspiracy.java index 3e561263f15..bc992d21361 100644 --- a/Mage.Sets/src/mage/sets/Conspiracy.java +++ b/Mage.Sets/src/mage/sets/Conspiracy.java @@ -43,6 +43,7 @@ public final class Conspiracy extends ExpansionSet { cards.add(new SetCardInfo("Brainstorm", 91, Rarity.COMMON, mage.cards.b.Brainstorm.class)); cards.add(new SetCardInfo("Breakthrough", 92, Rarity.UNCOMMON, mage.cards.b.Breakthrough.class)); cards.add(new SetCardInfo("Brimstone Volley", 138, Rarity.COMMON, mage.cards.b.BrimstoneVolley.class)); + cards.add(new SetCardInfo("Canal Dredger", 55, Rarity.RARE, mage.cards.c.CanalDredger.class)); cards.add(new SetCardInfo("Charging Rhino", 159, Rarity.COMMON, mage.cards.c.ChargingRhino.class)); cards.add(new SetCardInfo("Chartooth Cougar", 139, Rarity.COMMON, mage.cards.c.ChartoothCougar.class)); cards.add(new SetCardInfo("Cinder Wall", 140, Rarity.COMMON, mage.cards.c.CinderWall.class)); @@ -57,6 +58,7 @@ public final class Conspiracy extends ExpansionSet { cards.add(new SetCardInfo("Custodi Squire", 18, Rarity.COMMON, mage.cards.c.CustodiSquire.class)); cards.add(new SetCardInfo("Dack Fayden", 42, Rarity.MYTHIC, mage.cards.d.DackFayden.class)); cards.add(new SetCardInfo("Dack's Duplicate", 43, Rarity.RARE, mage.cards.d.DacksDuplicate.class)); + cards.add(new SetCardInfo("Deal Broker", 61, Rarity.RARE, mage.cards.d.DealBroker.class)); cards.add(new SetCardInfo("Deathforge Shaman", 141, Rarity.UNCOMMON, mage.cards.d.DeathforgeShaman.class)); cards.add(new SetCardInfo("Deathreap Ritual", 44, Rarity.UNCOMMON, mage.cards.d.DeathreapRitual.class)); cards.add(new SetCardInfo("Deathrender", 197, Rarity.RARE, mage.cards.d.Deathrender.class)); diff --git a/Mage.Sets/src/mage/sets/GameNight.java b/Mage.Sets/src/mage/sets/GameNight.java new file mode 100644 index 00000000000..84631bf8ac7 --- /dev/null +++ b/Mage.Sets/src/mage/sets/GameNight.java @@ -0,0 +1,91 @@ +package mage.sets; + +import mage.cards.ExpansionSet; +import mage.constants.Rarity; +import mage.constants.SetType; + +/** + * @author JayDi85 + */ +public final class GameNight extends ExpansionSet { + + private static final GameNight instance = new GameNight(); + + public static GameNight getInstance() { + return instance; + } + + private GameNight() { + super("Game Night", "GNT", ExpansionSet.buildDate(2018, 11, 16), SetType.SUPPLEMENTAL); + this.hasBasicLands = true; + + cards.add(new SetCardInfo("Advanced Stitchwing", 18, Rarity.UNCOMMON, mage.cards.a.AdvancedStitchwing.class)); + cards.add(new SetCardInfo("Aerial Responder", 6, Rarity.UNCOMMON, mage.cards.a.AerialResponder.class)); + cards.add(new SetCardInfo("Air Elemental", 19, Rarity.UNCOMMON, mage.cards.a.AirElemental.class)); + cards.add(new SetCardInfo("Always Watching", 7, Rarity.RARE, mage.cards.a.AlwaysWatching.class)); + cards.add(new SetCardInfo("Avatar of Growth", 5, Rarity.MYTHIC, mage.cards.a.AvatarOfGrowth.class)); + cards.add(new SetCardInfo("Benalish Marshal", 8, Rarity.RARE, mage.cards.b.BenalishMarshal.class)); + cards.add(new SetCardInfo("Bombard", 37, Rarity.COMMON, mage.cards.b.Bombard.class)); + cards.add(new SetCardInfo("Bone Splinters", 27, Rarity.COMMON, mage.cards.b.BoneSplinters.class)); + cards.add(new SetCardInfo("Bright Reprisal", 9, Rarity.UNCOMMON, mage.cards.b.BrightReprisal.class)); + cards.add(new SetCardInfo("Call the Cavalry", 10, Rarity.COMMON, mage.cards.c.CallTheCavalry.class)); + cards.add(new SetCardInfo("Captivating Crew", 38, Rarity.RARE, mage.cards.c.CaptivatingCrew.class)); + cards.add(new SetCardInfo("Claustrophobia", 20, Rarity.COMMON, mage.cards.c.Claustrophobia.class)); + cards.add(new SetCardInfo("Cruel Revival", 28, Rarity.UNCOMMON, mage.cards.c.CruelRevival.class)); + cards.add(new SetCardInfo("Dragon Fodder", 39, Rarity.COMMON, mage.cards.d.DragonFodder.class)); + cards.add(new SetCardInfo("Eager Construct", 51, Rarity.COMMON, mage.cards.e.EagerConstruct.class)); + cards.add(new SetCardInfo("Everdawn Champion", 11, Rarity.UNCOMMON, mage.cards.e.EverdawnChampion.class)); + cards.add(new SetCardInfo("Fan Bearer", 12, Rarity.COMMON, mage.cards.f.FanBearer.class)); + cards.add(new SetCardInfo("Favorable Winds", 21, Rarity.UNCOMMON, mage.cards.f.FavorableWinds.class)); + cards.add(new SetCardInfo("Filigree Familiar", 52, Rarity.UNCOMMON, mage.cards.f.FiligreeFamiliar.class)); + cards.add(new SetCardInfo("Fleshbag Marauder", 29, Rarity.UNCOMMON, mage.cards.f.FleshbagMarauder.class)); + cards.add(new SetCardInfo("Forest", 67, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Forest", 68, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Ghalta, Primal Hunger", 44, Rarity.RARE, mage.cards.g.GhaltaPrimalHunger.class)); + cards.add(new SetCardInfo("Goblin Goliath", 4, Rarity.MYTHIC, mage.cards.g.GoblinGoliath.class)); + cards.add(new SetCardInfo("Gruesome Fate", 30, Rarity.COMMON, mage.cards.g.GruesomeFate.class)); + cards.add(new SetCardInfo("Howling Golem", 53, Rarity.UNCOMMON, mage.cards.h.HowlingGolem.class)); + cards.add(new SetCardInfo("Hydrolash", 22, Rarity.UNCOMMON, mage.cards.h.Hydrolash.class)); + cards.add(new SetCardInfo("Inspired Charge", 13, Rarity.COMMON, mage.cards.i.InspiredCharge.class)); + cards.add(new SetCardInfo("Inspired Sphinx", 2, Rarity.MYTHIC, mage.cards.i.InspiredSphinx.class)); + cards.add(new SetCardInfo("Inspiring Captain", 14, Rarity.COMMON, mage.cards.i.InspiringCaptain.class)); + cards.add(new SetCardInfo("Island", 61, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Island", 62, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Jungle Delver", 45, Rarity.COMMON, mage.cards.j.JungleDelver.class)); + cards.add(new SetCardInfo("Languish", 31, Rarity.RARE, mage.cards.l.Languish.class)); + cards.add(new SetCardInfo("Liliana's Mastery", 32, Rarity.RARE, mage.cards.l.LilianasMastery.class)); + cards.add(new SetCardInfo("Llanowar Elves", 46, Rarity.COMMON, mage.cards.l.LlanowarElves.class)); + cards.add(new SetCardInfo("Lord of the Accursed", 33, Rarity.UNCOMMON, mage.cards.l.LordOfTheAccursed.class)); + cards.add(new SetCardInfo("Manalith", 54, Rarity.COMMON, mage.cards.m.Manalith.class)); + cards.add(new SetCardInfo("Mesa Unicorn", 15, Rarity.COMMON, mage.cards.m.MesaUnicorn.class)); + cards.add(new SetCardInfo("Militant Angel", 1, Rarity.MYTHIC, mage.cards.m.MilitantAngel.class)); + cards.add(new SetCardInfo("Mountain", 65, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mountain", 66, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Nissa's Revelation", 47, Rarity.RARE, mage.cards.n.NissasRevelation.class)); + cards.add(new SetCardInfo("Overcome", 48, Rarity.UNCOMMON, mage.cards.o.Overcome.class)); + cards.add(new SetCardInfo("Pilgrim's Eye", 55, Rarity.UNCOMMON, mage.cards.p.PilgrimsEye.class)); + cards.add(new SetCardInfo("Plains", 59, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Plains", 60, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Reckless Scholar", 23, Rarity.UNCOMMON, mage.cards.r.RecklessScholar.class)); + cards.add(new SetCardInfo("Rhonas's Monument", 56, Rarity.UNCOMMON, mage.cards.r.RhonassMonument.class)); + cards.add(new SetCardInfo("Rolling Thunder", 40, Rarity.UNCOMMON, mage.cards.r.RollingThunder.class)); + cards.add(new SetCardInfo("Rot Hulk", 3, Rarity.MYTHIC, mage.cards.r.RotHulk.class)); + cards.add(new SetCardInfo("Seek the Wilds", 49, Rarity.COMMON, mage.cards.s.SeekTheWilds.class)); + cards.add(new SetCardInfo("Seismic Elemental", 41, Rarity.UNCOMMON, mage.cards.s.SeismicElemental.class)); + cards.add(new SetCardInfo("Serra Angel", 16, Rarity.UNCOMMON, mage.cards.s.SerraAngel.class)); + cards.add(new SetCardInfo("Siege-Gang Commander", 42, Rarity.RARE, mage.cards.s.SiegeGangCommander.class)); + cards.add(new SetCardInfo("Snare Thopter", 57, Rarity.UNCOMMON, mage.cards.s.SnareThopter.class)); + cards.add(new SetCardInfo("Soulblade Djinn", 24, Rarity.RARE, mage.cards.s.SoulbladeDjinn.class)); + cards.add(new SetCardInfo("Subjugator Angel", 17, Rarity.UNCOMMON, mage.cards.s.SubjugatorAngel.class)); + cards.add(new SetCardInfo("Swamp", 63, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Swamp", 64, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Tattered Mummy", 34, Rarity.COMMON, mage.cards.t.TatteredMummy.class)); + cards.add(new SetCardInfo("Thallid Soothsayer", 35, Rarity.UNCOMMON, mage.cards.t.ThallidSoothsayer.class)); + cards.add(new SetCardInfo("Thrashing Brontodon", 50, Rarity.UNCOMMON, mage.cards.t.ThrashingBrontodon.class)); + cards.add(new SetCardInfo("Tormenting Voice", 43, Rarity.COMMON, mage.cards.t.TormentingVoice.class)); + cards.add(new SetCardInfo("Welder Automaton", 58, Rarity.COMMON, mage.cards.w.WelderAutomaton.class)); + cards.add(new SetCardInfo("Whirler Rogue", 25, Rarity.UNCOMMON, mage.cards.w.WhirlerRogue.class)); + cards.add(new SetCardInfo("Zahid, Djinn of the Lamp", 26, Rarity.RARE, mage.cards.z.ZahidDjinnOfTheLamp.class)); + cards.add(new SetCardInfo("Zulaport Cutthroat", 36, Rarity.UNCOMMON, mage.cards.z.ZulaportCutthroat.class)); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/IceAge.java b/Mage.Sets/src/mage/sets/IceAge.java index fc2e781f9c6..2112294e3b5 100644 --- a/Mage.Sets/src/mage/sets/IceAge.java +++ b/Mage.Sets/src/mage/sets/IceAge.java @@ -215,6 +215,7 @@ public final class IceAge extends ExpansionSet { cards.add(new SetCardInfo("Mind Warp", 148, Rarity.UNCOMMON, mage.cards.m.MindWarp.class)); cards.add(new SetCardInfo("Minion of Leshrac", 150, Rarity.RARE, mage.cards.m.MinionOfLeshrac.class)); cards.add(new SetCardInfo("Minion of Tevesh Szat", 151, Rarity.RARE, mage.cards.m.MinionOfTeveshSzat.class)); + cards.add(new SetCardInfo("Mistfolk", 84, Rarity.COMMON, mage.cards.m.Mistfolk.class)); cards.add(new SetCardInfo("Mole Worms", 152, Rarity.UNCOMMON, mage.cards.m.MoleWorms.class)); cards.add(new SetCardInfo("Monsoon", 298, Rarity.RARE, mage.cards.m.Monsoon.class)); cards.add(new SetCardInfo("Moor Fiend", 153, Rarity.COMMON, mage.cards.m.MoorFiend.class)); diff --git a/Mage.Sets/src/mage/sets/Invasion.java b/Mage.Sets/src/mage/sets/Invasion.java index 7aef568c5aa..beb5c28697f 100644 --- a/Mage.Sets/src/mage/sets/Invasion.java +++ b/Mage.Sets/src/mage/sets/Invasion.java @@ -55,6 +55,7 @@ public final class Invasion extends ExpansionSet { cards.add(new SetCardInfo("Benalish Heralds", 6, Rarity.UNCOMMON, mage.cards.b.BenalishHeralds.class)); cards.add(new SetCardInfo("Benalish Lancer", 7, Rarity.COMMON, mage.cards.b.BenalishLancer.class)); cards.add(new SetCardInfo("Benalish Trapper", 8, Rarity.COMMON, mage.cards.b.BenalishTrapper.class)); + cards.add(new SetCardInfo("Bend or Break", 137, Rarity.RARE, mage.cards.b.BendOrBreak.class)); cards.add(new SetCardInfo("Bind", 182, Rarity.RARE, mage.cards.b.Bind.class)); cards.add(new SetCardInfo("Blazing Specter", 236, Rarity.RARE, mage.cards.b.BlazingSpecter.class)); cards.add(new SetCardInfo("Blinding Light", 9, Rarity.UNCOMMON, mage.cards.b.BlindingLight.class)); @@ -88,6 +89,7 @@ public final class Invasion extends ExpansionSet { cards.add(new SetCardInfo("Darigaaz's Attendant", 301, Rarity.UNCOMMON, mage.cards.d.DarigaazsAttendant.class)); cards.add(new SetCardInfo("Darigaaz, the Igniter", 243, Rarity.RARE, mage.cards.d.DarigaazTheIgniter.class)); cards.add(new SetCardInfo("Defiling Tears", 99, Rarity.UNCOMMON, mage.cards.d.DefilingTears.class)); + cards.add(new SetCardInfo("Death or Glory", 13, Rarity.RARE, mage.cards.d.DeathOrGlory.class)); cards.add(new SetCardInfo("Desperate Research", 100, Rarity.RARE, mage.cards.d.DesperateResearch.class)); cards.add(new SetCardInfo("Devouring Strossus", 101, Rarity.RARE, mage.cards.d.DevouringStrossus.class)); cards.add(new SetCardInfo("Dismantling Blow", 14, Rarity.COMMON, mage.cards.d.DismantlingBlow.class)); @@ -113,6 +115,7 @@ public final class Invasion extends ExpansionSet { cards.add(new SetCardInfo("Fact or Fiction", 57, Rarity.UNCOMMON, mage.cards.f.FactOrFiction.class)); cards.add(new SetCardInfo("Faerie Squadron", 58, Rarity.COMMON, mage.cards.f.FaerieSquadron.class)); cards.add(new SetCardInfo("Fertile Ground", 188, Rarity.COMMON, mage.cards.f.FertileGround.class)); + cards.add(new SetCardInfo("Fight or Flight", 16, Rarity.RARE, mage.cards.f.FightOrFlight.class)); cards.add(new SetCardInfo("Firebrand Ranger", 143, Rarity.UNCOMMON, mage.cards.f.FirebrandRanger.class)); cards.add(new SetCardInfo("Firescreamer", 106, Rarity.COMMON, mage.cards.f.Firescreamer.class)); cards.add(new SetCardInfo("Fires of Yavimaya", 246, Rarity.UNCOMMON, mage.cards.f.FiresOfYavimaya.class)); @@ -217,6 +220,7 @@ public final class Invasion extends ExpansionSet { cards.add(new SetCardInfo("Prohibit", 67, Rarity.COMMON, mage.cards.p.Prohibit.class)); cards.add(new SetCardInfo("Protective Sphere", 26, Rarity.COMMON, mage.cards.p.ProtectiveSphere.class)); cards.add(new SetCardInfo("Psychic Battle", 68, Rarity.RARE, mage.cards.p.PsychicBattle.class)); + cards.add(new SetCardInfo("Pulse of Llanowar", 202, Rarity.UNCOMMON, mage.cards.p.PulseOfLlanowar.class)); cards.add(new SetCardInfo("Pure Reflection", 27, Rarity.RARE, mage.cards.p.PureReflection.class)); cards.add(new SetCardInfo("Pyre Zombie", 261, Rarity.RARE, mage.cards.p.PyreZombie.class)); cards.add(new SetCardInfo("Quirion Elves", 203, Rarity.COMMON, mage.cards.q.QuirionElves.class)); @@ -250,6 +254,7 @@ public final class Invasion extends ExpansionSet { cards.add(new SetCardInfo("Sabertooth Nishoba", 268, Rarity.RARE, mage.cards.s.SabertoothNishoba.class)); cards.add(new SetCardInfo("Salt Marsh", 326, Rarity.UNCOMMON, mage.cards.s.SaltMarsh.class)); cards.add(new SetCardInfo("Samite Archer", 269, Rarity.UNCOMMON, mage.cards.s.SamiteArcher.class)); + cards.add(new SetCardInfo("Samite Ministration", 36, Rarity.UNCOMMON, mage.cards.s.SamiteMinistration.class)); cards.add(new SetCardInfo("Sapphire Leech", 71, Rarity.RARE, mage.cards.s.SapphireLeech.class)); cards.add(new SetCardInfo("Saproling Infestation", 208, Rarity.RARE, mage.cards.s.SaprolingInfestation.class)); cards.add(new SetCardInfo("Saproling Symbiosis", 209, Rarity.RARE, mage.cards.s.SaprolingSymbiosis.class)); @@ -286,6 +291,7 @@ public final class Invasion extends ExpansionSet { cards.add(new SetCardInfo("Spreading Plague", 125, Rarity.RARE, mage.cards.s.SpreadingPlague.class)); cards.add(new SetCardInfo("Stalking Assassin", 277, Rarity.RARE, mage.cards.s.StalkingAssassin.class)); cards.add(new SetCardInfo("Stand // Deliver", 292, Rarity.UNCOMMON, mage.cards.s.StandDeliver.class)); + cards.add(new SetCardInfo("Stand or Fall", 171, Rarity.RARE, mage.cards.s.StandOrFall.class)); cards.add(new SetCardInfo("Sterling Grove", 278, Rarity.UNCOMMON, mage.cards.s.SterlingGrove.class)); cards.add(new SetCardInfo("Stormscape Apprentice", 75, Rarity.COMMON, mage.cards.s.StormscapeApprentice.class)); cards.add(new SetCardInfo("Stormscape Master", 76, Rarity.RARE, mage.cards.s.StormscapeMaster.class)); @@ -346,6 +352,7 @@ public final class Invasion extends ExpansionSet { cards.add(new SetCardInfo("Verduran Emissary", 221, Rarity.UNCOMMON, mage.cards.v.VerduranEmissary.class)); cards.add(new SetCardInfo("Viashino Grappler", 179, Rarity.COMMON, mage.cards.v.ViashinoGrappler.class)); cards.add(new SetCardInfo("Vicious Kavu", 284, Rarity.UNCOMMON, mage.cards.v.ViciousKavu.class)); + cards.add(new SetCardInfo("Vigorous Charge", 222, Rarity.COMMON, mage.cards.v.VigorousCharge.class)); cards.add(new SetCardInfo("Vile Consumption", 285, Rarity.RARE, mage.cards.v.VileConsumption.class)); cards.add(new SetCardInfo("Vodalian Hypnotist", 84, Rarity.UNCOMMON, mage.cards.v.VodalianHypnotist.class)); cards.add(new SetCardInfo("Vodalian Merchant", 85, Rarity.COMMON, mage.cards.v.VodalianMerchant.class)); diff --git a/Mage.Sets/src/mage/sets/Legends.java b/Mage.Sets/src/mage/sets/Legends.java index 987bc827ddd..134bb3b75cb 100644 --- a/Mage.Sets/src/mage/sets/Legends.java +++ b/Mage.Sets/src/mage/sets/Legends.java @@ -1,295 +1,312 @@ -package mage.sets; - -import mage.cards.ExpansionSet; -import mage.constants.Rarity; -import mage.constants.SetType; - -/** - * - * @author North - */ -public final class Legends extends ExpansionSet { - - private static final Legends instance = new Legends(); - - public static Legends getInstance() { - return instance; - } - - private Legends() { - super("Legends", "LEG", ExpansionSet.buildDate(1994, 6, 1), SetType.EXPANSION); - this.hasBasicLands = false; - this.hasBoosters = true; - this.numBoosterLands = 0; - this.numBoosterCommon = 11; - this.numBoosterUncommon = 3; - this.numBoosterRare = 1; - this.ratioBoosterMythic = 0; - cards.add(new SetCardInfo("Abomination", 87, Rarity.UNCOMMON, mage.cards.a.Abomination.class)); - cards.add(new SetCardInfo("Acid Rain", 44, Rarity.RARE, mage.cards.a.AcidRain.class)); - cards.add(new SetCardInfo("Active Volcano", 130, Rarity.COMMON, mage.cards.a.ActiveVolcano.class)); - cards.add(new SetCardInfo("Adun Oakenshield", 216, Rarity.RARE, mage.cards.a.AdunOakenshield.class)); - cards.add(new SetCardInfo("Aerathi Berserker", 131, Rarity.UNCOMMON, mage.cards.a.AerathiBerserker.class)); - cards.add(new SetCardInfo("Aisling Leprechaun", 173, Rarity.COMMON, mage.cards.a.AislingLeprechaun.class)); - cards.add(new SetCardInfo("Akron Legionnaire", 1, Rarity.RARE, mage.cards.a.AkronLegionnaire.class)); - cards.add(new SetCardInfo("Al-abara's Carpet", 271, Rarity.RARE, mage.cards.a.AlAbarasCarpet.class)); - cards.add(new SetCardInfo("Alabaster Potion", 2, Rarity.COMMON, mage.cards.a.AlabasterPotion.class)); - cards.add(new SetCardInfo("Alchor's Tomb", 272, Rarity.RARE, mage.cards.a.AlchorsTomb.class)); - cards.add(new SetCardInfo("All Hallow's Eve", 88, Rarity.RARE, mage.cards.a.AllHallowsEve.class)); - cards.add(new SetCardInfo("Amrou Kithkin", 3, Rarity.COMMON, mage.cards.a.AmrouKithkin.class)); - cards.add(new SetCardInfo("Angelic Voices", 4, Rarity.RARE, mage.cards.a.AngelicVoices.class)); - cards.add(new SetCardInfo("Angus Mackenzie", 217, Rarity.RARE, mage.cards.a.AngusMackenzie.class)); - cards.add(new SetCardInfo("Anti-Magic Aura", 45, Rarity.COMMON, mage.cards.a.AntiMagicAura.class)); - cards.add(new SetCardInfo("Arboria", 174, Rarity.UNCOMMON, mage.cards.a.Arboria.class)); - cards.add(new SetCardInfo("Arcades Sabboth", 218, Rarity.RARE, mage.cards.a.ArcadesSabboth.class)); - cards.add(new SetCardInfo("Arena of the Ancients", 273, Rarity.RARE, mage.cards.a.ArenaOfTheAncients.class)); - cards.add(new SetCardInfo("Avoid Fate", 175, Rarity.COMMON, mage.cards.a.AvoidFate.class)); - cards.add(new SetCardInfo("Axelrod Gunnarson", 219, Rarity.RARE, mage.cards.a.AxelrodGunnarson.class)); - cards.add(new SetCardInfo("Ayesha Tanaka", 220, Rarity.RARE, mage.cards.a.AyeshaTanaka.class)); - cards.add(new SetCardInfo("Azure Drake", 46, Rarity.UNCOMMON, mage.cards.a.AzureDrake.class)); - cards.add(new SetCardInfo("Backfire", 47, Rarity.UNCOMMON, mage.cards.b.Backfire.class)); - cards.add(new SetCardInfo("Barbary Apes", 176, Rarity.COMMON, mage.cards.b.BarbaryApes.class)); - cards.add(new SetCardInfo("Barktooth Warbeard", 221, Rarity.UNCOMMON, mage.cards.b.BarktoothWarbeard.class)); - cards.add(new SetCardInfo("Bartel Runeaxe", 222, Rarity.RARE, mage.cards.b.BartelRuneaxe.class)); - cards.add(new SetCardInfo("Beasts of Bogardan", 133, Rarity.UNCOMMON, mage.cards.b.BeastsOfBogardan.class)); - cards.add(new SetCardInfo("Black Mana Battery", 274, Rarity.UNCOMMON, mage.cards.b.BlackManaBattery.class)); - cards.add(new SetCardInfo("Blight", 89, Rarity.UNCOMMON, mage.cards.b.Blight.class)); - cards.add(new SetCardInfo("Blood Lust", 135, Rarity.UNCOMMON, mage.cards.b.BloodLust.class)); - cards.add(new SetCardInfo("Blue Mana Battery", 275, Rarity.UNCOMMON, mage.cards.b.BlueManaBattery.class)); - cards.add(new SetCardInfo("Boomerang", 48, Rarity.COMMON, mage.cards.b.Boomerang.class)); - cards.add(new SetCardInfo("Boris Devilboon", 223, Rarity.RARE, mage.cards.b.BorisDevilboon.class)); - cards.add(new SetCardInfo("Carrion Ants", 90, Rarity.RARE, mage.cards.c.CarrionAnts.class)); - cards.add(new SetCardInfo("Cat Warriors", 177, Rarity.COMMON, mage.cards.c.CatWarriors.class)); - cards.add(new SetCardInfo("Caverns of Despair", 136, Rarity.RARE, mage.cards.c.CavernsOfDespair.class)); - cards.add(new SetCardInfo("Chain Lightning", 137, Rarity.COMMON, mage.cards.c.ChainLightning.class)); - cards.add(new SetCardInfo("Chains of Mephistopheles", 91, Rarity.RARE, mage.cards.c.ChainsOfMephistopheles.class)); - cards.add(new SetCardInfo("Chromium", 224, Rarity.RARE, mage.cards.c.Chromium.class)); - cards.add(new SetCardInfo("Cleanse", 5, Rarity.RARE, mage.cards.c.Cleanse.class)); - cards.add(new SetCardInfo("Clergy of the Holy Nimbus", 6, Rarity.COMMON, mage.cards.c.ClergyOfTheHolyNimbus.class)); - cards.add(new SetCardInfo("Concordant Crossroads", 179, Rarity.RARE, mage.cards.c.ConcordantCrossroads.class)); - cards.add(new SetCardInfo("Cosmic Horror", 92, Rarity.RARE, mage.cards.c.CosmicHorror.class)); - cards.add(new SetCardInfo("Craw Giant", 180, Rarity.UNCOMMON, mage.cards.c.CrawGiant.class)); - cards.add(new SetCardInfo("Crevasse", 138, Rarity.UNCOMMON, mage.cards.c.Crevasse.class)); - cards.add(new SetCardInfo("Crimson Kobolds", 139, Rarity.COMMON, mage.cards.c.CrimsonKobolds.class)); - cards.add(new SetCardInfo("Crimson Manticore", 140, Rarity.RARE, mage.cards.c.CrimsonManticore.class)); - cards.add(new SetCardInfo("Crookshank Kobolds", 141, Rarity.COMMON, mage.cards.c.CrookshankKobolds.class)); - cards.add(new SetCardInfo("Cyclopean Mummy", 93, Rarity.COMMON, mage.cards.c.CyclopeanMummy.class)); - cards.add(new SetCardInfo("D'Avenant Archer", 7, Rarity.COMMON, mage.cards.d.DAvenantArcher.class)); - cards.add(new SetCardInfo("Dakkon Blackblade", 225, Rarity.RARE, mage.cards.d.DakkonBlackblade.class)); - cards.add(new SetCardInfo("Darkness", 94, Rarity.COMMON, mage.cards.d.Darkness.class)); - cards.add(new SetCardInfo("Deadfall", 181, Rarity.UNCOMMON, mage.cards.d.Deadfall.class)); - cards.add(new SetCardInfo("Demonic Torment", 95, Rarity.UNCOMMON, mage.cards.d.DemonicTorment.class)); - cards.add(new SetCardInfo("Devouring Deep", 50, Rarity.COMMON, mage.cards.d.DevouringDeep.class)); - cards.add(new SetCardInfo("Disharmony", 142, Rarity.RARE, mage.cards.d.Disharmony.class)); - cards.add(new SetCardInfo("Divine Intervention", 8, Rarity.RARE, mage.cards.d.DivineIntervention.class)); - cards.add(new SetCardInfo("Divine Offering", 9, Rarity.COMMON, mage.cards.d.DivineOffering.class)); - cards.add(new SetCardInfo("Divine Transformation", 10, Rarity.RARE, mage.cards.d.DivineTransformation.class)); - cards.add(new SetCardInfo("Dream Coat", 51, Rarity.UNCOMMON, mage.cards.d.DreamCoat.class)); - cards.add(new SetCardInfo("Durkwood Boars", 182, Rarity.COMMON, mage.cards.d.DurkwoodBoars.class)); - cards.add(new SetCardInfo("Dwarven Song", 143, Rarity.UNCOMMON, mage.cards.d.DwarvenSong.class)); - cards.add(new SetCardInfo("Elder Land Wurm", 11, Rarity.RARE, mage.cards.e.ElderLandWurm.class)); - cards.add(new SetCardInfo("Elven Riders", 183, Rarity.RARE, mage.cards.e.ElvenRiders.class)); - cards.add(new SetCardInfo("Emerald Dragonfly", 184, Rarity.COMMON, mage.cards.e.EmeraldDragonfly.class)); - cards.add(new SetCardInfo("Energy Tap", 54, Rarity.COMMON, mage.cards.e.EnergyTap.class)); - cards.add(new SetCardInfo("Eternal Warrior", 144, Rarity.UNCOMMON, mage.cards.e.EternalWarrior.class)); - cards.add(new SetCardInfo("Eureka", 185, Rarity.RARE, mage.cards.e.Eureka.class)); - cards.add(new SetCardInfo("Evil Eye of Orms-by-Gore", 96, Rarity.UNCOMMON, mage.cards.e.EvilEyeOfOrmsByGore.class)); - cards.add(new SetCardInfo("Fallen Angel", 97, Rarity.UNCOMMON, mage.cards.f.FallenAngel.class)); - cards.add(new SetCardInfo("Field of Dreams", 55, Rarity.RARE, mage.cards.f.FieldOfDreams.class)); - cards.add(new SetCardInfo("Fire Sprites", 186, Rarity.COMMON, mage.cards.f.FireSprites.class)); - cards.add(new SetCardInfo("Flash Counter", 56, Rarity.COMMON, mage.cards.f.FlashCounter.class)); - cards.add(new SetCardInfo("Flash Flood", 57, Rarity.COMMON, mage.cards.f.FlashFlood.class)); - cards.add(new SetCardInfo("Floral Spuzzem", 187, Rarity.UNCOMMON, mage.cards.f.FloralSpuzzem.class)); - cards.add(new SetCardInfo("Force Spike", 58, Rarity.COMMON, mage.cards.f.ForceSpike.class)); - cards.add(new SetCardInfo("Fortified Area", 14, Rarity.UNCOMMON, mage.cards.f.FortifiedArea.class)); - cards.add(new SetCardInfo("Frost Giant", 148, Rarity.UNCOMMON, mage.cards.f.FrostGiant.class)); - cards.add(new SetCardInfo("Gabriel Angelfire", 226, Rarity.RARE, mage.cards.g.GabrielAngelfire.class)); - cards.add(new SetCardInfo("Gaseous Form", 59, Rarity.COMMON, mage.cards.g.GaseousForm.class)); - cards.add(new SetCardInfo("Gauntlets of Chaos", 278, Rarity.RARE, mage.cards.g.GauntletsOfChaos.class)); - cards.add(new SetCardInfo("Ghosts of the Damned", 98, Rarity.COMMON, mage.cards.g.GhostsOfTheDamned.class)); - cards.add(new SetCardInfo("Giant Strength", 149, Rarity.COMMON, mage.cards.g.GiantStrength.class)); - cards.add(new SetCardInfo("Giant Turtle", 188, Rarity.COMMON, mage.cards.g.GiantTurtle.class)); - cards.add(new SetCardInfo("Glyph of Destruction", 150, Rarity.COMMON, mage.cards.g.GlyphOfDestruction.class)); - cards.add(new SetCardInfo("Glyph of Doom", 100, Rarity.COMMON, mage.cards.g.GlyphOfDoom.class)); - cards.add(new SetCardInfo("Glyph of Life", 15, Rarity.COMMON, mage.cards.g.GlyphOfLife.class)); - cards.add(new SetCardInfo("Gosta Dirk", 227, Rarity.RARE, mage.cards.g.GostaDirk.class)); - cards.add(new SetCardInfo("Gravity Sphere", 151, Rarity.RARE, mage.cards.g.GravitySphere.class)); - cards.add(new SetCardInfo("Great Defender", 16, Rarity.UNCOMMON, mage.cards.g.GreatDefender.class)); - cards.add(new SetCardInfo("Great Wall", 17, Rarity.UNCOMMON, mage.cards.g.GreatWall.class)); - cards.add(new SetCardInfo("Greater Realm of Preservation", 18, Rarity.UNCOMMON, mage.cards.g.GreaterRealmOfPreservation.class)); - cards.add(new SetCardInfo("Greed", 101, Rarity.RARE, mage.cards.g.Greed.class)); - cards.add(new SetCardInfo("Green Mana Battery", 279, Rarity.UNCOMMON, mage.cards.g.GreenManaBattery.class)); - cards.add(new SetCardInfo("Gwendlyn Di Corci", 228, Rarity.RARE, mage.cards.g.GwendlynDiCorci.class)); - cards.add(new SetCardInfo("Halfdane", 229, Rarity.RARE, mage.cards.h.Halfdane.class)); - cards.add(new SetCardInfo("Hammerheim", 302, Rarity.UNCOMMON, mage.cards.h.Hammerheim.class)); - cards.add(new SetCardInfo("Hazezon Tamar", 230, Rarity.RARE, mage.cards.h.HazezonTamar.class)); - cards.add(new SetCardInfo("Headless Horseman", 102, Rarity.COMMON, mage.cards.h.HeadlessHorseman.class)); - cards.add(new SetCardInfo("Heaven's Gate", 19, Rarity.UNCOMMON, mage.cards.h.HeavensGate.class)); - cards.add(new SetCardInfo("Hell Swarm", 103, Rarity.COMMON, mage.cards.h.HellSwarm.class)); - cards.add(new SetCardInfo("Hell's Caretaker", 104, Rarity.RARE, mage.cards.h.HellsCaretaker.class)); - cards.add(new SetCardInfo("Hellfire", 105, Rarity.RARE, mage.cards.h.Hellfire.class)); - cards.add(new SetCardInfo("Holy Day", 20, Rarity.COMMON, mage.cards.h.HolyDay.class)); - cards.add(new SetCardInfo("Horn of Deafening", 280, Rarity.RARE, mage.cards.h.HornOfDeafening.class)); - cards.add(new SetCardInfo("Hornet Cobra", 190, Rarity.COMMON, mage.cards.h.HornetCobra.class)); - cards.add(new SetCardInfo("Horror of Horrors", 106, Rarity.UNCOMMON, mage.cards.h.HorrorOfHorrors.class)); - cards.add(new SetCardInfo("Hunding Gjornersen", 231, Rarity.UNCOMMON, mage.cards.h.HundingGjornersen.class)); - cards.add(new SetCardInfo("Hyperion Blacksmith", 152, Rarity.UNCOMMON, mage.cards.h.HyperionBlacksmith.class)); - cards.add(new SetCardInfo("Immolation", 153, Rarity.COMMON, mage.cards.i.Immolation.class)); - cards.add(new SetCardInfo("Imprison", 107, Rarity.RARE, mage.cards.i.Imprison.class)); - cards.add(new SetCardInfo("In the Eye of Chaos", 61, Rarity.RARE, mage.cards.i.InTheEyeOfChaos.class)); - cards.add(new SetCardInfo("Indestructible Aura", 21, Rarity.COMMON, mage.cards.i.IndestructibleAura.class)); - cards.add(new SetCardInfo("Infernal Medusa", 108, Rarity.UNCOMMON, mage.cards.i.InfernalMedusa.class)); - cards.add(new SetCardInfo("Invoke Prejudice", 62, Rarity.RARE, mage.cards.i.InvokePrejudice.class)); - cards.add(new SetCardInfo("Ivory Guardians", 23, Rarity.UNCOMMON, mage.cards.i.IvoryGuardians.class)); - cards.add(new SetCardInfo("Jacques le Vert", 232, Rarity.RARE, mage.cards.j.JacquesLeVert.class)); - cards.add(new SetCardInfo("Jasmine Boreal", 233, Rarity.UNCOMMON, mage.cards.j.JasmineBoreal.class)); - cards.add(new SetCardInfo("Jedit Ojanen", 234, Rarity.UNCOMMON, mage.cards.j.JeditOjanen.class)); - cards.add(new SetCardInfo("Jerrard of the Closed Fist", 235, Rarity.UNCOMMON, mage.cards.j.JerrardOfTheClosedFist.class)); - cards.add(new SetCardInfo("Johan", 236, Rarity.RARE, mage.cards.j.Johan.class)); - cards.add(new SetCardInfo("Jovial Evil", 109, Rarity.RARE, mage.cards.j.JovialEvil.class)); - cards.add(new SetCardInfo("Juxtapose", 63, Rarity.RARE, mage.cards.j.Juxtapose.class)); - cards.add(new SetCardInfo("Karakas", 303, Rarity.UNCOMMON, mage.cards.k.Karakas.class)); - cards.add(new SetCardInfo("Kasimir the Lone Wolf", 237, Rarity.UNCOMMON, mage.cards.k.KasimirTheLoneWolf.class)); - cards.add(new SetCardInfo("Keepers of the Faith", 24, Rarity.COMMON, mage.cards.k.KeepersOfTheFaith.class)); - cards.add(new SetCardInfo("Kei Takahashi", 238, Rarity.RARE, mage.cards.k.KeiTakahashi.class)); - cards.add(new SetCardInfo("Killer Bees", 192, Rarity.RARE, mage.cards.k.KillerBees.class)); - cards.add(new SetCardInfo("Kismet", 25, Rarity.UNCOMMON, mage.cards.k.Kismet.class)); - cards.add(new SetCardInfo("Kobold Drill Sergeant", 154, Rarity.UNCOMMON, mage.cards.k.KoboldDrillSergeant.class)); - cards.add(new SetCardInfo("Kobold Overlord", 155, Rarity.RARE, mage.cards.k.KoboldOverlord.class)); - cards.add(new SetCardInfo("Kobold Taskmaster", 156, Rarity.UNCOMMON, mage.cards.k.KoboldTaskmaster.class)); - cards.add(new SetCardInfo("Kobolds of Kher Keep", 157, Rarity.COMMON, mage.cards.k.KoboldsOfKherKeep.class)); - cards.add(new SetCardInfo("Lady Caleria", 239, Rarity.RARE, mage.cards.l.LadyCaleria.class)); - cards.add(new SetCardInfo("Lady Evangela", 240, Rarity.RARE, mage.cards.l.LadyEvangela.class)); - cards.add(new SetCardInfo("Lady Orca", 241, Rarity.UNCOMMON, mage.cards.l.LadyOrca.class)); - cards.add(new SetCardInfo("Land Equilibrium", 64, Rarity.RARE, mage.cards.l.LandEquilibrium.class)); - cards.add(new SetCardInfo("Land Tax", 26, Rarity.UNCOMMON, mage.cards.l.LandTax.class)); - cards.add(new SetCardInfo("Land's Edge", 158, Rarity.RARE, mage.cards.l.LandsEdge.class)); - cards.add(new SetCardInfo("Life Chisel", 283, Rarity.UNCOMMON, mage.cards.l.LifeChisel.class)); - cards.add(new SetCardInfo("Lifeblood", 27, Rarity.RARE, mage.cards.l.Lifeblood.class)); - cards.add(new SetCardInfo("Living Plane", 193, Rarity.RARE, mage.cards.l.LivingPlane.class)); - cards.add(new SetCardInfo("Livonya Silone", 242, Rarity.RARE, mage.cards.l.LivonyaSilone.class)); - cards.add(new SetCardInfo("Lord Magnus", 243, Rarity.UNCOMMON, mage.cards.l.LordMagnus.class)); - cards.add(new SetCardInfo("Lost Soul", 111, Rarity.COMMON, mage.cards.l.LostSoul.class)); - cards.add(new SetCardInfo("Mana Drain", 65, Rarity.UNCOMMON, mage.cards.m.ManaDrain.class)); - cards.add(new SetCardInfo("Mana Matrix", 285, Rarity.RARE, mage.cards.m.ManaMatrix.class)); - cards.add(new SetCardInfo("Marble Priest", 286, Rarity.UNCOMMON, mage.cards.m.MarblePriest.class)); - cards.add(new SetCardInfo("Marhault Elsdragon", 244, Rarity.UNCOMMON, mage.cards.m.MarhaultElsdragon.class)); - cards.add(new SetCardInfo("Mirror Universe", 287, Rarity.RARE, mage.cards.m.MirrorUniverse.class)); - cards.add(new SetCardInfo("Moat", 28, Rarity.RARE, mage.cards.m.Moat.class)); - cards.add(new SetCardInfo("Mold Demon", 112, Rarity.RARE, mage.cards.m.MoldDemon.class)); - cards.add(new SetCardInfo("Moss Monster", 195, Rarity.COMMON, mage.cards.m.MossMonster.class)); - cards.add(new SetCardInfo("Mountain Yeti", 159, Rarity.UNCOMMON, mage.cards.m.MountainYeti.class)); - cards.add(new SetCardInfo("Nebuchadnezzar", 245, Rarity.RARE, mage.cards.n.Nebuchadnezzar.class)); - cards.add(new SetCardInfo("Nether Void", 113, Rarity.RARE, mage.cards.n.NetherVoid.class)); - cards.add(new SetCardInfo("Nicol Bolas", 246, Rarity.RARE, mage.cards.n.NicolBolas.class)); - cards.add(new SetCardInfo("Nova Pentacle", 289, Rarity.RARE, mage.cards.n.NovaPentacle.class)); - cards.add(new SetCardInfo("Osai Vultures", 29, Rarity.COMMON, mage.cards.o.OsaiVultures.class)); - cards.add(new SetCardInfo("Palladia-Mors", 247, Rarity.RARE, mage.cards.p.PalladiaMors.class)); - cards.add(new SetCardInfo("Part Water", 66, Rarity.UNCOMMON, mage.cards.p.PartWater.class)); - cards.add(new SetCardInfo("Pavel Maliki", 248, Rarity.UNCOMMON, mage.cards.p.PavelMaliki.class)); - cards.add(new SetCardInfo("Pendelhaven", 305, Rarity.UNCOMMON, mage.cards.p.Pendelhaven.class)); - cards.add(new SetCardInfo("Petra Sphinx", 30, Rarity.RARE, mage.cards.p.PetraSphinx.class)); - cards.add(new SetCardInfo("Pit Scorpion", 114, Rarity.COMMON, mage.cards.p.PitScorpion.class)); - cards.add(new SetCardInfo("Pixie Queen", 196, Rarity.RARE, mage.cards.p.PixieQueen.class)); - cards.add(new SetCardInfo("Planar Gate", 290, Rarity.RARE, mage.cards.p.PlanarGate.class)); - cards.add(new SetCardInfo("Pradesh Gypsies", 197, Rarity.UNCOMMON, mage.cards.p.PradeshGypsies.class)); - cards.add(new SetCardInfo("Presence of the Master", 31, Rarity.UNCOMMON, mage.cards.p.PresenceOfTheMaster.class)); - cards.add(new SetCardInfo("Primordial Ooze", 160, Rarity.UNCOMMON, mage.cards.p.PrimordialOoze.class)); - cards.add(new SetCardInfo("Princess Lucrezia", 249, Rarity.UNCOMMON, mage.cards.p.PrincessLucrezia.class)); - cards.add(new SetCardInfo("Psionic Entity", 67, Rarity.RARE, mage.cards.p.PsionicEntity.class)); - cards.add(new SetCardInfo("Psychic Purge", 68, Rarity.COMMON, mage.cards.p.PsychicPurge.class)); - cards.add(new SetCardInfo("Pyrotechnics", 161, Rarity.COMMON, mage.cards.p.Pyrotechnics.class)); - cards.add(new SetCardInfo("Quagmire", 115, Rarity.UNCOMMON, mage.cards.q.Quagmire.class)); - cards.add(new SetCardInfo("Rabid Wombat", 198, Rarity.UNCOMMON, mage.cards.r.RabidWombat.class)); - cards.add(new SetCardInfo("Radjan Spirit", 199, Rarity.UNCOMMON, mage.cards.r.RadjanSpirit.class)); - cards.add(new SetCardInfo("Raging Bull", 163, Rarity.COMMON, mage.cards.r.RagingBull.class)); - cards.add(new SetCardInfo("Ragnar", 250, Rarity.RARE, mage.cards.r.Ragnar.class)); - cards.add(new SetCardInfo("Ramirez DePietro", 251, Rarity.UNCOMMON, mage.cards.r.RamirezDePietro.class)); - cards.add(new SetCardInfo("Ramses Overdark", 252, Rarity.RARE, mage.cards.r.RamsesOverdark.class)); - cards.add(new SetCardInfo("Rasputin Dreamweaver", 253, Rarity.RARE, mage.cards.r.RasputinDreamweaver.class)); - cards.add(new SetCardInfo("Recall", 70, Rarity.RARE, mage.cards.r.Recall.class)); - cards.add(new SetCardInfo("Red Mana Battery", 291, Rarity.UNCOMMON, mage.cards.r.RedManaBattery.class)); - cards.add(new SetCardInfo("Reincarnation", 201, Rarity.UNCOMMON, mage.cards.r.Reincarnation.class)); - cards.add(new SetCardInfo("Relic Barrier", 292, Rarity.UNCOMMON, mage.cards.r.RelicBarrier.class)); - cards.add(new SetCardInfo("Relic Bind", 71, Rarity.UNCOMMON, mage.cards.r.RelicBind.class)); - cards.add(new SetCardInfo("Remove Enchantments", 33, Rarity.COMMON, mage.cards.r.RemoveEnchantments.class)); - cards.add(new SetCardInfo("Remove Soul", 72, Rarity.COMMON, mage.cards.r.RemoveSoul.class)); - cards.add(new SetCardInfo("Reset", 73, Rarity.UNCOMMON, mage.cards.r.Reset.class)); - cards.add(new SetCardInfo("Revelation", 202, Rarity.RARE, mage.cards.r.Revelation.class)); - cards.add(new SetCardInfo("Righteous Avengers", 34, Rarity.UNCOMMON, mage.cards.r.RighteousAvengers.class)); - cards.add(new SetCardInfo("Ring of Immortals", 293, Rarity.RARE, mage.cards.r.RingOfImmortals.class)); - cards.add(new SetCardInfo("Riven Turnbull", 254, Rarity.UNCOMMON, mage.cards.r.RivenTurnbull.class)); - cards.add(new SetCardInfo("Rohgahh of Kher Keep", 255, Rarity.RARE, mage.cards.r.RohgahhOfKherKeep.class)); - cards.add(new SetCardInfo("Rubinia Soulsinger", 256, Rarity.RARE, mage.cards.r.RubiniaSoulsinger.class)); - cards.add(new SetCardInfo("Rust", 203, Rarity.COMMON, mage.cards.r.Rust.class)); - cards.add(new SetCardInfo("Sea Kings' Blessing", 75, Rarity.UNCOMMON, mage.cards.s.SeaKingsBlessing.class)); - cards.add(new SetCardInfo("Seeker", 35, Rarity.UNCOMMON, mage.cards.s.Seeker.class)); - cards.add(new SetCardInfo("Segovian Leviathan", 76, Rarity.UNCOMMON, mage.cards.s.SegovianLeviathan.class)); - cards.add(new SetCardInfo("Sentinel", 294, Rarity.RARE, mage.cards.s.Sentinel.class)); - cards.add(new SetCardInfo("Serpent Generator", 295, Rarity.RARE, mage.cards.s.SerpentGenerator.class)); - cards.add(new SetCardInfo("Shield Wall", 36, Rarity.UNCOMMON, mage.cards.s.ShieldWall.class)); - cards.add(new SetCardInfo("Shimian Night Stalker", 116, Rarity.UNCOMMON, mage.cards.s.ShimianNightStalker.class)); - cards.add(new SetCardInfo("Sir Shandlar of Eberyn", 257, Rarity.UNCOMMON, mage.cards.s.SirShandlarOfEberyn.class)); - cards.add(new SetCardInfo("Sivitri Scarzam", 258, Rarity.UNCOMMON, mage.cards.s.SivitriScarzam.class)); - cards.add(new SetCardInfo("Sol'kanar the Swamp King", 259, Rarity.RARE, mage.cards.s.SolkanarTheSwampKing.class)); - cards.add(new SetCardInfo("Spectral Cloak", 78, Rarity.UNCOMMON, mage.cards.s.SpectralCloak.class)); - cards.add(new SetCardInfo("Spinal Villain", 164, Rarity.RARE, mage.cards.s.SpinalVillain.class)); - cards.add(new SetCardInfo("Spirit Link", 37, Rarity.UNCOMMON, mage.cards.s.SpiritLink.class)); - cards.add(new SetCardInfo("Spirit Shackle", 117, Rarity.COMMON, mage.cards.s.SpiritShackle.class)); - cards.add(new SetCardInfo("Spiritual Sanctuary", 38, Rarity.RARE, mage.cards.s.SpiritualSanctuary.class)); - cards.add(new SetCardInfo("Stangg", 260, Rarity.RARE, mage.cards.s.Stangg.class)); - cards.add(new SetCardInfo("Storm Seeker", 205, Rarity.UNCOMMON, mage.cards.s.StormSeeker.class)); - cards.add(new SetCardInfo("Storm World", 165, Rarity.RARE, mage.cards.s.StormWorld.class)); - cards.add(new SetCardInfo("Sunastian Falconer", 261, Rarity.UNCOMMON, mage.cards.s.SunastianFalconer.class)); - cards.add(new SetCardInfo("Sword of the Ages", 296, Rarity.RARE, mage.cards.s.SwordOfTheAges.class)); - cards.add(new SetCardInfo("Sylvan Library", 207, Rarity.UNCOMMON, mage.cards.s.SylvanLibrary.class)); - cards.add(new SetCardInfo("Sylvan Paradise", 208, Rarity.UNCOMMON, mage.cards.s.SylvanParadise.class)); - cards.add(new SetCardInfo("Syphon Soul", 118, Rarity.COMMON, mage.cards.s.SyphonSoul.class)); - cards.add(new SetCardInfo("Telekinesis", 79, Rarity.RARE, mage.cards.t.Telekinesis.class)); - cards.add(new SetCardInfo("Teleport", 80, Rarity.RARE, mage.cards.t.Teleport.class)); - cards.add(new SetCardInfo("Tetsuo Umezawa", 262, Rarity.RARE, mage.cards.t.TetsuoUmezawa.class)); - cards.add(new SetCardInfo("The Abyss", 120, Rarity.RARE, mage.cards.t.TheAbyss.class)); - cards.add(new SetCardInfo("The Brute", 167, Rarity.COMMON, mage.cards.t.TheBrute.class)); - cards.add(new SetCardInfo("The Lady of the Mountain", 263, Rarity.UNCOMMON, mage.cards.t.TheLadyOfTheMountain.class)); - cards.add(new SetCardInfo("The Tabernacle at Pendrell Vale", 307, Rarity.RARE, mage.cards.t.TheTabernacleAtPendrellVale.class)); - cards.add(new SetCardInfo("The Wretched", 121, Rarity.RARE, mage.cards.t.TheWretched.class)); - cards.add(new SetCardInfo("Thunder Spirit", 39, Rarity.RARE, mage.cards.t.ThunderSpirit.class)); - cards.add(new SetCardInfo("Time Elemental", 81, Rarity.RARE, mage.cards.t.TimeElemental.class)); - cards.add(new SetCardInfo("Tobias Andrion", 264, Rarity.UNCOMMON, mage.cards.t.TobiasAndrion.class)); - cards.add(new SetCardInfo("Tor Wauki", 265, Rarity.UNCOMMON, mage.cards.t.TorWauki.class)); - cards.add(new SetCardInfo("Torsten Von Ursus", 266, Rarity.UNCOMMON, mage.cards.t.TorstenVonUrsus.class)); - cards.add(new SetCardInfo("Touch of Darkness", 122, Rarity.UNCOMMON, mage.cards.t.TouchOfDarkness.class)); - cards.add(new SetCardInfo("Transmutation", 123, Rarity.COMMON, mage.cards.t.Transmutation.class)); - cards.add(new SetCardInfo("Triassic Egg", 297, Rarity.RARE, mage.cards.t.TriassicEgg.class)); - cards.add(new SetCardInfo("Tuknir Deathlock", 267, Rarity.RARE, mage.cards.t.TuknirDeathlock.class)); - cards.add(new SetCardInfo("Tundra Wolves", 40, Rarity.COMMON, mage.cards.t.TundraWolves.class)); - cards.add(new SetCardInfo("Typhoon", 209, Rarity.RARE, mage.cards.t.Typhoon.class)); - cards.add(new SetCardInfo("Undertow", 82, Rarity.UNCOMMON, mage.cards.u.Undertow.class)); - cards.add(new SetCardInfo("Underworld Dreams", 124, Rarity.UNCOMMON, mage.cards.u.UnderworldDreams.class)); - cards.add(new SetCardInfo("Untamed Wilds", 210, Rarity.UNCOMMON, mage.cards.u.UntamedWilds.class)); - cards.add(new SetCardInfo("Ur-Drago", 268, Rarity.RARE, mage.cards.u.UrDrago.class)); - cards.add(new SetCardInfo("Urborg", 310, Rarity.UNCOMMON, mage.cards.u.Urborg.class)); - cards.add(new SetCardInfo("Vaevictis Asmadi", 269, Rarity.RARE, mage.cards.v.VaevictisAsmadi.class)); - cards.add(new SetCardInfo("Vampire Bats", 125, Rarity.COMMON, mage.cards.v.VampireBats.class)); - cards.add(new SetCardInfo("Visions", 41, Rarity.UNCOMMON, mage.cards.v.Visions.class)); - cards.add(new SetCardInfo("Walking Dead", 126, Rarity.COMMON, mage.cards.w.WalkingDead.class)); - cards.add(new SetCardInfo("Wall of Caltrops", 42, Rarity.COMMON, mage.cards.w.WallOfCaltrops.class)); - cards.add(new SetCardInfo("Wall of Dust", 168, Rarity.UNCOMMON, mage.cards.w.WallOfDust.class)); - cards.add(new SetCardInfo("Wall of Earth", 169, Rarity.COMMON, mage.cards.w.WallOfEarth.class)); - cards.add(new SetCardInfo("Wall of Heat", 170, Rarity.COMMON, mage.cards.w.WallOfHeat.class)); - cards.add(new SetCardInfo("Wall of Light", 43, Rarity.UNCOMMON, mage.cards.w.WallOfLight.class)); - cards.add(new SetCardInfo("Wall of Opposition", 171, Rarity.RARE, mage.cards.w.WallOfOpposition.class)); - cards.add(new SetCardInfo("Wall of Putrid Flesh", 127, Rarity.UNCOMMON, mage.cards.w.WallOfPutridFlesh.class)); - cards.add(new SetCardInfo("Wall of Vapor", 84, Rarity.COMMON, mage.cards.w.WallOfVapor.class)); - cards.add(new SetCardInfo("Wall of Wonder", 85, Rarity.UNCOMMON, mage.cards.w.WallOfWonder.class)); - cards.add(new SetCardInfo("Whirling Dervish", 211, Rarity.UNCOMMON, mage.cards.w.WhirlingDervish.class)); - cards.add(new SetCardInfo("White Mana Battery", 299, Rarity.UNCOMMON, mage.cards.w.WhiteManaBattery.class)); - cards.add(new SetCardInfo("Willow Satyr", 212, Rarity.RARE, mage.cards.w.WillowSatyr.class)); - cards.add(new SetCardInfo("Winds of Change", 172, Rarity.UNCOMMON, mage.cards.w.WindsOfChange.class)); - cards.add(new SetCardInfo("Winter Blast", 213, Rarity.RARE, mage.cards.w.WinterBlast.class)); - cards.add(new SetCardInfo("Wolverine Pack", 214, Rarity.COMMON, mage.cards.w.WolverinePack.class)); - cards.add(new SetCardInfo("Wood Elemental", 215, Rarity.RARE, mage.cards.w.WoodElemental.class)); - cards.add(new SetCardInfo("Xira Arien", 270, Rarity.RARE, mage.cards.x.XiraArien.class)); - cards.add(new SetCardInfo("Zephyr Falcon", 86, Rarity.COMMON, mage.cards.z.ZephyrFalcon.class)); - } -} +package mage.sets; + +import mage.cards.ExpansionSet; +import mage.constants.Rarity; +import mage.constants.SetType; + +/** + * + * @author North + */ +public final class Legends extends ExpansionSet { + + private static final Legends instance = new Legends(); + + public static Legends getInstance() { + return instance; + } + + private Legends() { + super("Legends", "LEG", ExpansionSet.buildDate(1994, 6, 1), SetType.EXPANSION); + this.hasBasicLands = false; + this.hasBoosters = true; + this.numBoosterLands = 0; + this.numBoosterCommon = 11; + this.numBoosterUncommon = 3; + this.numBoosterRare = 1; + this.ratioBoosterMythic = 0; + cards.add(new SetCardInfo("Abomination", 87, Rarity.UNCOMMON, mage.cards.a.Abomination.class)); + cards.add(new SetCardInfo("Acid Rain", 44, Rarity.RARE, mage.cards.a.AcidRain.class)); + cards.add(new SetCardInfo("Active Volcano", 130, Rarity.COMMON, mage.cards.a.ActiveVolcano.class)); + cards.add(new SetCardInfo("Adun Oakenshield", 216, Rarity.RARE, mage.cards.a.AdunOakenshield.class)); + cards.add(new SetCardInfo("Adventurers' Guildhouse", 300, Rarity.UNCOMMON, mage.cards.a.AdventurersGuildhouse.class)); + cards.add(new SetCardInfo("Aerathi Berserker", 131, Rarity.UNCOMMON, mage.cards.a.AerathiBerserker.class)); + cards.add(new SetCardInfo("Aisling Leprechaun", 173, Rarity.COMMON, mage.cards.a.AislingLeprechaun.class)); + cards.add(new SetCardInfo("Akron Legionnaire", 1, Rarity.RARE, mage.cards.a.AkronLegionnaire.class)); + cards.add(new SetCardInfo("Al-abara's Carpet", 271, Rarity.RARE, mage.cards.a.AlAbarasCarpet.class)); + cards.add(new SetCardInfo("Alabaster Potion", 2, Rarity.COMMON, mage.cards.a.AlabasterPotion.class)); + cards.add(new SetCardInfo("Alchor's Tomb", 272, Rarity.RARE, mage.cards.a.AlchorsTomb.class)); + cards.add(new SetCardInfo("All Hallow's Eve", 88, Rarity.RARE, mage.cards.a.AllHallowsEve.class)); + cards.add(new SetCardInfo("Amrou Kithkin", 3, Rarity.COMMON, mage.cards.a.AmrouKithkin.class)); + cards.add(new SetCardInfo("Angelic Voices", 4, Rarity.RARE, mage.cards.a.AngelicVoices.class)); + cards.add(new SetCardInfo("Angus Mackenzie", 217, Rarity.RARE, mage.cards.a.AngusMackenzie.class)); + cards.add(new SetCardInfo("Anti-Magic Aura", 45, Rarity.COMMON, mage.cards.a.AntiMagicAura.class)); + cards.add(new SetCardInfo("Arboria", 174, Rarity.UNCOMMON, mage.cards.a.Arboria.class)); + cards.add(new SetCardInfo("Arcades Sabboth", 218, Rarity.RARE, mage.cards.a.ArcadesSabboth.class)); + cards.add(new SetCardInfo("Arena of the Ancients", 273, Rarity.RARE, mage.cards.a.ArenaOfTheAncients.class)); + cards.add(new SetCardInfo("Avoid Fate", 175, Rarity.COMMON, mage.cards.a.AvoidFate.class)); + cards.add(new SetCardInfo("Axelrod Gunnarson", 219, Rarity.RARE, mage.cards.a.AxelrodGunnarson.class)); + cards.add(new SetCardInfo("Ayesha Tanaka", 220, Rarity.RARE, mage.cards.a.AyeshaTanaka.class)); + cards.add(new SetCardInfo("Azure Drake", 46, Rarity.UNCOMMON, mage.cards.a.AzureDrake.class)); + cards.add(new SetCardInfo("Backfire", 47, Rarity.UNCOMMON, mage.cards.b.Backfire.class)); + cards.add(new SetCardInfo("Barbary Apes", 176, Rarity.COMMON, mage.cards.b.BarbaryApes.class)); + cards.add(new SetCardInfo("Barktooth Warbeard", 221, Rarity.UNCOMMON, mage.cards.b.BarktoothWarbeard.class)); + cards.add(new SetCardInfo("Bartel Runeaxe", 222, Rarity.RARE, mage.cards.b.BartelRuneaxe.class)); + cards.add(new SetCardInfo("Beasts of Bogardan", 133, Rarity.UNCOMMON, mage.cards.b.BeastsOfBogardan.class)); + cards.add(new SetCardInfo("Black Mana Battery", 274, Rarity.UNCOMMON, mage.cards.b.BlackManaBattery.class)); + cards.add(new SetCardInfo("Blight", 89, Rarity.UNCOMMON, mage.cards.b.Blight.class)); + cards.add(new SetCardInfo("Blood Lust", 135, Rarity.UNCOMMON, mage.cards.b.BloodLust.class)); + cards.add(new SetCardInfo("Blue Mana Battery", 275, Rarity.UNCOMMON, mage.cards.b.BlueManaBattery.class)); + cards.add(new SetCardInfo("Boomerang", 48, Rarity.COMMON, mage.cards.b.Boomerang.class)); + cards.add(new SetCardInfo("Boris Devilboon", 223, Rarity.RARE, mage.cards.b.BorisDevilboon.class)); + cards.add(new SetCardInfo("Bronze Horse", 276, Rarity.RARE, mage.cards.b.BronzeHorse.class)); + cards.add(new SetCardInfo("Carrion Ants", 90, Rarity.RARE, mage.cards.c.CarrionAnts.class)); + cards.add(new SetCardInfo("Cat Warriors", 177, Rarity.COMMON, mage.cards.c.CatWarriors.class)); + cards.add(new SetCardInfo("Cathedral of Serra", 301, Rarity.UNCOMMON, mage.cards.c.CathedralOfSerra.class)); + cards.add(new SetCardInfo("Caverns of Despair", 136, Rarity.RARE, mage.cards.c.CavernsOfDespair.class)); + cards.add(new SetCardInfo("Chain Lightning", 137, Rarity.COMMON, mage.cards.c.ChainLightning.class)); + cards.add(new SetCardInfo("Chains of Mephistopheles", 91, Rarity.RARE, mage.cards.c.ChainsOfMephistopheles.class)); + cards.add(new SetCardInfo("Chromium", 224, Rarity.RARE, mage.cards.c.Chromium.class)); + cards.add(new SetCardInfo("Cleanse", 5, Rarity.RARE, mage.cards.c.Cleanse.class)); + cards.add(new SetCardInfo("Clergy of the Holy Nimbus", 6, Rarity.COMMON, mage.cards.c.ClergyOfTheHolyNimbus.class)); + cards.add(new SetCardInfo("Concordant Crossroads", 179, Rarity.RARE, mage.cards.c.ConcordantCrossroads.class)); + cards.add(new SetCardInfo("Cosmic Horror", 92, Rarity.RARE, mage.cards.c.CosmicHorror.class)); + cards.add(new SetCardInfo("Craw Giant", 180, Rarity.UNCOMMON, mage.cards.c.CrawGiant.class)); + cards.add(new SetCardInfo("Crevasse", 138, Rarity.UNCOMMON, mage.cards.c.Crevasse.class)); + cards.add(new SetCardInfo("Crimson Kobolds", 139, Rarity.COMMON, mage.cards.c.CrimsonKobolds.class)); + cards.add(new SetCardInfo("Crimson Manticore", 140, Rarity.RARE, mage.cards.c.CrimsonManticore.class)); + cards.add(new SetCardInfo("Crookshank Kobolds", 141, Rarity.COMMON, mage.cards.c.CrookshankKobolds.class)); + cards.add(new SetCardInfo("Cyclopean Mummy", 93, Rarity.COMMON, mage.cards.c.CyclopeanMummy.class)); + cards.add(new SetCardInfo("D'Avenant Archer", 7, Rarity.COMMON, mage.cards.d.DAvenantArcher.class)); + cards.add(new SetCardInfo("Dakkon Blackblade", 225, Rarity.RARE, mage.cards.d.DakkonBlackblade.class)); + cards.add(new SetCardInfo("Darkness", 94, Rarity.COMMON, mage.cards.d.Darkness.class)); + cards.add(new SetCardInfo("Deadfall", 181, Rarity.UNCOMMON, mage.cards.d.Deadfall.class)); + cards.add(new SetCardInfo("Demonic Torment", 95, Rarity.UNCOMMON, mage.cards.d.DemonicTorment.class)); + cards.add(new SetCardInfo("Devouring Deep", 50, Rarity.COMMON, mage.cards.d.DevouringDeep.class)); + cards.add(new SetCardInfo("Disharmony", 142, Rarity.RARE, mage.cards.d.Disharmony.class)); + cards.add(new SetCardInfo("Divine Intervention", 8, Rarity.RARE, mage.cards.d.DivineIntervention.class)); + cards.add(new SetCardInfo("Divine Offering", 9, Rarity.COMMON, mage.cards.d.DivineOffering.class)); + cards.add(new SetCardInfo("Divine Transformation", 10, Rarity.RARE, mage.cards.d.DivineTransformation.class)); + cards.add(new SetCardInfo("Dream Coat", 51, Rarity.UNCOMMON, mage.cards.d.DreamCoat.class)); + cards.add(new SetCardInfo("Durkwood Boars", 182, Rarity.COMMON, mage.cards.d.DurkwoodBoars.class)); + cards.add(new SetCardInfo("Dwarven Song", 143, Rarity.UNCOMMON, mage.cards.d.DwarvenSong.class)); + cards.add(new SetCardInfo("Elder Land Wurm", 11, Rarity.RARE, mage.cards.e.ElderLandWurm.class)); + cards.add(new SetCardInfo("Elder Spawn", 52, Rarity.RARE, mage.cards.e.ElderSpawn.class)); + cards.add(new SetCardInfo("Elven Riders", 183, Rarity.RARE, mage.cards.e.ElvenRiders.class)); + cards.add(new SetCardInfo("Emerald Dragonfly", 184, Rarity.COMMON, mage.cards.e.EmeraldDragonfly.class)); + cards.add(new SetCardInfo("Enchanted Being", 12, Rarity.COMMON, mage.cards.e.EnchantedBeing.class)); + cards.add(new SetCardInfo("Enchantment Alteration", 53, Rarity.COMMON, mage.cards.e.EnchantmentAlteration.class)); + cards.add(new SetCardInfo("Energy Tap", 54, Rarity.COMMON, mage.cards.e.EnergyTap.class)); + cards.add(new SetCardInfo("Eternal Warrior", 144, Rarity.UNCOMMON, mage.cards.e.EternalWarrior.class)); + cards.add(new SetCardInfo("Eureka", 185, Rarity.RARE, mage.cards.e.Eureka.class)); + cards.add(new SetCardInfo("Evil Eye of Orms-by-Gore", 96, Rarity.UNCOMMON, mage.cards.e.EvilEyeOfOrmsByGore.class)); + cards.add(new SetCardInfo("Fallen Angel", 97, Rarity.UNCOMMON, mage.cards.f.FallenAngel.class)); + cards.add(new SetCardInfo("Field of Dreams", 55, Rarity.RARE, mage.cards.f.FieldOfDreams.class)); + cards.add(new SetCardInfo("Fire Sprites", 186, Rarity.COMMON, mage.cards.f.FireSprites.class)); + cards.add(new SetCardInfo("Flash Counter", 56, Rarity.COMMON, mage.cards.f.FlashCounter.class)); + cards.add(new SetCardInfo("Flash Flood", 57, Rarity.COMMON, mage.cards.f.FlashFlood.class)); + cards.add(new SetCardInfo("Floral Spuzzem", 187, Rarity.UNCOMMON, mage.cards.f.FloralSpuzzem.class)); + cards.add(new SetCardInfo("Force Spike", 58, Rarity.COMMON, mage.cards.f.ForceSpike.class)); + cards.add(new SetCardInfo("Forethought Amulet", 277, Rarity.RARE, mage.cards.f.ForethoughtAmulet.class)); + cards.add(new SetCardInfo("Fortified Area", 14, Rarity.UNCOMMON, mage.cards.f.FortifiedArea.class)); + cards.add(new SetCardInfo("Frost Giant", 148, Rarity.UNCOMMON, mage.cards.f.FrostGiant.class)); + cards.add(new SetCardInfo("Gabriel Angelfire", 226, Rarity.RARE, mage.cards.g.GabrielAngelfire.class)); + cards.add(new SetCardInfo("Gaseous Form", 59, Rarity.COMMON, mage.cards.g.GaseousForm.class)); + cards.add(new SetCardInfo("Gauntlets of Chaos", 278, Rarity.RARE, mage.cards.g.GauntletsOfChaos.class)); + cards.add(new SetCardInfo("Ghosts of the Damned", 98, Rarity.COMMON, mage.cards.g.GhostsOfTheDamned.class)); + cards.add(new SetCardInfo("Giant Strength", 149, Rarity.COMMON, mage.cards.g.GiantStrength.class)); + cards.add(new SetCardInfo("Giant Turtle", 188, Rarity.COMMON, mage.cards.g.GiantTurtle.class)); + cards.add(new SetCardInfo("Glyph of Destruction", 150, Rarity.COMMON, mage.cards.g.GlyphOfDestruction.class)); + cards.add(new SetCardInfo("Glyph of Doom", 100, Rarity.COMMON, mage.cards.g.GlyphOfDoom.class)); + cards.add(new SetCardInfo("Glyph of Life", 15, Rarity.COMMON, mage.cards.g.GlyphOfLife.class)); + cards.add(new SetCardInfo("Gosta Dirk", 227, Rarity.RARE, mage.cards.g.GostaDirk.class)); + cards.add(new SetCardInfo("Gravity Sphere", 151, Rarity.RARE, mage.cards.g.GravitySphere.class)); + cards.add(new SetCardInfo("Great Defender", 16, Rarity.UNCOMMON, mage.cards.g.GreatDefender.class)); + cards.add(new SetCardInfo("Great Wall", 17, Rarity.UNCOMMON, mage.cards.g.GreatWall.class)); + cards.add(new SetCardInfo("Greater Realm of Preservation", 18, Rarity.UNCOMMON, mage.cards.g.GreaterRealmOfPreservation.class)); + cards.add(new SetCardInfo("Greed", 101, Rarity.RARE, mage.cards.g.Greed.class)); + cards.add(new SetCardInfo("Green Mana Battery", 279, Rarity.UNCOMMON, mage.cards.g.GreenManaBattery.class)); + cards.add(new SetCardInfo("Gwendlyn Di Corci", 228, Rarity.RARE, mage.cards.g.GwendlynDiCorci.class)); + cards.add(new SetCardInfo("Halfdane", 229, Rarity.RARE, mage.cards.h.Halfdane.class)); + cards.add(new SetCardInfo("Hammerheim", 302, Rarity.UNCOMMON, mage.cards.h.Hammerheim.class)); + cards.add(new SetCardInfo("Hazezon Tamar", 230, Rarity.RARE, mage.cards.h.HazezonTamar.class)); + cards.add(new SetCardInfo("Headless Horseman", 102, Rarity.COMMON, mage.cards.h.HeadlessHorseman.class)); + cards.add(new SetCardInfo("Heaven's Gate", 19, Rarity.UNCOMMON, mage.cards.h.HeavensGate.class)); + cards.add(new SetCardInfo("Hell Swarm", 103, Rarity.COMMON, mage.cards.h.HellSwarm.class)); + cards.add(new SetCardInfo("Hell's Caretaker", 104, Rarity.RARE, mage.cards.h.HellsCaretaker.class)); + cards.add(new SetCardInfo("Hellfire", 105, Rarity.RARE, mage.cards.h.Hellfire.class)); + cards.add(new SetCardInfo("Holy Day", 20, Rarity.COMMON, mage.cards.h.HolyDay.class)); + cards.add(new SetCardInfo("Horn of Deafening", 280, Rarity.RARE, mage.cards.h.HornOfDeafening.class)); + cards.add(new SetCardInfo("Hornet Cobra", 190, Rarity.COMMON, mage.cards.h.HornetCobra.class)); + cards.add(new SetCardInfo("Horror of Horrors", 106, Rarity.UNCOMMON, mage.cards.h.HorrorOfHorrors.class)); + cards.add(new SetCardInfo("Hunding Gjornersen", 231, Rarity.UNCOMMON, mage.cards.h.HundingGjornersen.class)); + cards.add(new SetCardInfo("Hyperion Blacksmith", 152, Rarity.UNCOMMON, mage.cards.h.HyperionBlacksmith.class)); + cards.add(new SetCardInfo("Immolation", 153, Rarity.COMMON, mage.cards.i.Immolation.class)); + cards.add(new SetCardInfo("Imprison", 107, Rarity.RARE, mage.cards.i.Imprison.class)); + cards.add(new SetCardInfo("In the Eye of Chaos", 61, Rarity.RARE, mage.cards.i.InTheEyeOfChaos.class)); + cards.add(new SetCardInfo("Indestructible Aura", 21, Rarity.COMMON, mage.cards.i.IndestructibleAura.class)); + cards.add(new SetCardInfo("Infernal Medusa", 108, Rarity.UNCOMMON, mage.cards.i.InfernalMedusa.class)); + cards.add(new SetCardInfo("Invoke Prejudice", 62, Rarity.RARE, mage.cards.i.InvokePrejudice.class)); + cards.add(new SetCardInfo("Ivory Guardians", 23, Rarity.UNCOMMON, mage.cards.i.IvoryGuardians.class)); + cards.add(new SetCardInfo("Jacques le Vert", 232, Rarity.RARE, mage.cards.j.JacquesLeVert.class)); + cards.add(new SetCardInfo("Jasmine Boreal", 233, Rarity.UNCOMMON, mage.cards.j.JasmineBoreal.class)); + cards.add(new SetCardInfo("Jedit Ojanen", 234, Rarity.UNCOMMON, mage.cards.j.JeditOjanen.class)); + cards.add(new SetCardInfo("Jerrard of the Closed Fist", 235, Rarity.UNCOMMON, mage.cards.j.JerrardOfTheClosedFist.class)); + cards.add(new SetCardInfo("Johan", 236, Rarity.RARE, mage.cards.j.Johan.class)); + cards.add(new SetCardInfo("Jovial Evil", 109, Rarity.RARE, mage.cards.j.JovialEvil.class)); + cards.add(new SetCardInfo("Juxtapose", 63, Rarity.RARE, mage.cards.j.Juxtapose.class)); + cards.add(new SetCardInfo("Karakas", 303, Rarity.UNCOMMON, mage.cards.k.Karakas.class)); + cards.add(new SetCardInfo("Kasimir the Lone Wolf", 237, Rarity.UNCOMMON, mage.cards.k.KasimirTheLoneWolf.class)); + cards.add(new SetCardInfo("Keepers of the Faith", 24, Rarity.COMMON, mage.cards.k.KeepersOfTheFaith.class)); + cards.add(new SetCardInfo("Kei Takahashi", 238, Rarity.RARE, mage.cards.k.KeiTakahashi.class)); + cards.add(new SetCardInfo("Killer Bees", 192, Rarity.RARE, mage.cards.k.KillerBees.class)); + cards.add(new SetCardInfo("Kismet", 25, Rarity.UNCOMMON, mage.cards.k.Kismet.class)); + cards.add(new SetCardInfo("Kobold Drill Sergeant", 154, Rarity.UNCOMMON, mage.cards.k.KoboldDrillSergeant.class)); + cards.add(new SetCardInfo("Kobold Overlord", 155, Rarity.RARE, mage.cards.k.KoboldOverlord.class)); + cards.add(new SetCardInfo("Kobold Taskmaster", 156, Rarity.UNCOMMON, mage.cards.k.KoboldTaskmaster.class)); + cards.add(new SetCardInfo("Kobolds of Kher Keep", 157, Rarity.COMMON, mage.cards.k.KoboldsOfKherKeep.class)); + cards.add(new SetCardInfo("Kry Shield", 282, Rarity.UNCOMMON, mage.cards.k.KryShield.class)); + cards.add(new SetCardInfo("Lady Caleria", 239, Rarity.RARE, mage.cards.l.LadyCaleria.class)); + cards.add(new SetCardInfo("Lady Evangela", 240, Rarity.RARE, mage.cards.l.LadyEvangela.class)); + cards.add(new SetCardInfo("Lady Orca", 241, Rarity.UNCOMMON, mage.cards.l.LadyOrca.class)); + cards.add(new SetCardInfo("Land Equilibrium", 64, Rarity.RARE, mage.cards.l.LandEquilibrium.class)); + cards.add(new SetCardInfo("Land Tax", 26, Rarity.UNCOMMON, mage.cards.l.LandTax.class)); + cards.add(new SetCardInfo("Land's Edge", 158, Rarity.RARE, mage.cards.l.LandsEdge.class)); + cards.add(new SetCardInfo("Life Chisel", 283, Rarity.UNCOMMON, mage.cards.l.LifeChisel.class)); + cards.add(new SetCardInfo("Lifeblood", 27, Rarity.RARE, mage.cards.l.Lifeblood.class)); + cards.add(new SetCardInfo("Living Plane", 193, Rarity.RARE, mage.cards.l.LivingPlane.class)); + cards.add(new SetCardInfo("Livonya Silone", 242, Rarity.RARE, mage.cards.l.LivonyaSilone.class)); + cards.add(new SetCardInfo("Lord Magnus", 243, Rarity.UNCOMMON, mage.cards.l.LordMagnus.class)); + cards.add(new SetCardInfo("Lost Soul", 111, Rarity.COMMON, mage.cards.l.LostSoul.class)); + cards.add(new SetCardInfo("Mana Drain", 65, Rarity.UNCOMMON, mage.cards.m.ManaDrain.class)); + cards.add(new SetCardInfo("Mana Matrix", 285, Rarity.RARE, mage.cards.m.ManaMatrix.class)); + cards.add(new SetCardInfo("Marble Priest", 286, Rarity.UNCOMMON, mage.cards.m.MarblePriest.class)); + cards.add(new SetCardInfo("Marhault Elsdragon", 244, Rarity.UNCOMMON, mage.cards.m.MarhaultElsdragon.class)); + cards.add(new SetCardInfo("Master of the Hunt", 194, Rarity.RARE, mage.cards.m.MasterOfTheHunt.class)); + cards.add(new SetCardInfo("Mirror Universe", 287, Rarity.RARE, mage.cards.m.MirrorUniverse.class)); + cards.add(new SetCardInfo("Moat", 28, Rarity.RARE, mage.cards.m.Moat.class)); + cards.add(new SetCardInfo("Mold Demon", 112, Rarity.RARE, mage.cards.m.MoldDemon.class)); + cards.add(new SetCardInfo("Moss Monster", 195, Rarity.COMMON, mage.cards.m.MossMonster.class)); + cards.add(new SetCardInfo("Mountain Stronghold", 304, Rarity.UNCOMMON, mage.cards.m.MountainStronghold.class)); + cards.add(new SetCardInfo("Mountain Yeti", 159, Rarity.UNCOMMON, mage.cards.m.MountainYeti.class)); + cards.add(new SetCardInfo("Nebuchadnezzar", 245, Rarity.RARE, mage.cards.n.Nebuchadnezzar.class)); + cards.add(new SetCardInfo("Nether Void", 113, Rarity.RARE, mage.cards.n.NetherVoid.class)); + cards.add(new SetCardInfo("Nicol Bolas", 246, Rarity.RARE, mage.cards.n.NicolBolas.class)); + cards.add(new SetCardInfo("Nova Pentacle", 289, Rarity.RARE, mage.cards.n.NovaPentacle.class)); + cards.add(new SetCardInfo("Osai Vultures", 29, Rarity.COMMON, mage.cards.o.OsaiVultures.class)); + cards.add(new SetCardInfo("Palladia-Mors", 247, Rarity.RARE, mage.cards.p.PalladiaMors.class)); + cards.add(new SetCardInfo("Part Water", 66, Rarity.UNCOMMON, mage.cards.p.PartWater.class)); + cards.add(new SetCardInfo("Pavel Maliki", 248, Rarity.UNCOMMON, mage.cards.p.PavelMaliki.class)); + cards.add(new SetCardInfo("Pendelhaven", 305, Rarity.UNCOMMON, mage.cards.p.Pendelhaven.class)); + cards.add(new SetCardInfo("Petra Sphinx", 30, Rarity.RARE, mage.cards.p.PetraSphinx.class)); + cards.add(new SetCardInfo("Pit Scorpion", 114, Rarity.COMMON, mage.cards.p.PitScorpion.class)); + cards.add(new SetCardInfo("Pixie Queen", 196, Rarity.RARE, mage.cards.p.PixieQueen.class)); + cards.add(new SetCardInfo("Planar Gate", 290, Rarity.RARE, mage.cards.p.PlanarGate.class)); + cards.add(new SetCardInfo("Pradesh Gypsies", 197, Rarity.UNCOMMON, mage.cards.p.PradeshGypsies.class)); + cards.add(new SetCardInfo("Presence of the Master", 31, Rarity.UNCOMMON, mage.cards.p.PresenceOfTheMaster.class)); + cards.add(new SetCardInfo("Primordial Ooze", 160, Rarity.UNCOMMON, mage.cards.p.PrimordialOoze.class)); + cards.add(new SetCardInfo("Princess Lucrezia", 249, Rarity.UNCOMMON, mage.cards.p.PrincessLucrezia.class)); + cards.add(new SetCardInfo("Psionic Entity", 67, Rarity.RARE, mage.cards.p.PsionicEntity.class)); + cards.add(new SetCardInfo("Psychic Purge", 68, Rarity.COMMON, mage.cards.p.PsychicPurge.class)); + cards.add(new SetCardInfo("Pyrotechnics", 161, Rarity.COMMON, mage.cards.p.Pyrotechnics.class)); + cards.add(new SetCardInfo("Quagmire", 115, Rarity.UNCOMMON, mage.cards.q.Quagmire.class)); + cards.add(new SetCardInfo("Rabid Wombat", 198, Rarity.UNCOMMON, mage.cards.r.RabidWombat.class)); + cards.add(new SetCardInfo("Radjan Spirit", 199, Rarity.UNCOMMON, mage.cards.r.RadjanSpirit.class)); + cards.add(new SetCardInfo("Raging Bull", 163, Rarity.COMMON, mage.cards.r.RagingBull.class)); + cards.add(new SetCardInfo("Ragnar", 250, Rarity.RARE, mage.cards.r.Ragnar.class)); + cards.add(new SetCardInfo("Ramirez DePietro", 251, Rarity.UNCOMMON, mage.cards.r.RamirezDePietro.class)); + cards.add(new SetCardInfo("Ramses Overdark", 252, Rarity.RARE, mage.cards.r.RamsesOverdark.class)); + cards.add(new SetCardInfo("Rasputin Dreamweaver", 253, Rarity.RARE, mage.cards.r.RasputinDreamweaver.class)); + cards.add(new SetCardInfo("Recall", 70, Rarity.RARE, mage.cards.r.Recall.class)); + cards.add(new SetCardInfo("Red Mana Battery", 291, Rarity.UNCOMMON, mage.cards.r.RedManaBattery.class)); + cards.add(new SetCardInfo("Reincarnation", 201, Rarity.UNCOMMON, mage.cards.r.Reincarnation.class)); + cards.add(new SetCardInfo("Relic Barrier", 292, Rarity.UNCOMMON, mage.cards.r.RelicBarrier.class)); + cards.add(new SetCardInfo("Relic Bind", 71, Rarity.UNCOMMON, mage.cards.r.RelicBind.class)); + cards.add(new SetCardInfo("Remove Enchantments", 33, Rarity.COMMON, mage.cards.r.RemoveEnchantments.class)); + cards.add(new SetCardInfo("Remove Soul", 72, Rarity.COMMON, mage.cards.r.RemoveSoul.class)); + cards.add(new SetCardInfo("Reset", 73, Rarity.UNCOMMON, mage.cards.r.Reset.class)); + cards.add(new SetCardInfo("Revelation", 202, Rarity.RARE, mage.cards.r.Revelation.class)); + cards.add(new SetCardInfo("Reverberation", 74, Rarity.RARE, mage.cards.r.Reverberation.class)); + cards.add(new SetCardInfo("Righteous Avengers", 34, Rarity.UNCOMMON, mage.cards.r.RighteousAvengers.class)); + cards.add(new SetCardInfo("Ring of Immortals", 293, Rarity.RARE, mage.cards.r.RingOfImmortals.class)); + cards.add(new SetCardInfo("Riven Turnbull", 254, Rarity.UNCOMMON, mage.cards.r.RivenTurnbull.class)); + cards.add(new SetCardInfo("Rohgahh of Kher Keep", 255, Rarity.RARE, mage.cards.r.RohgahhOfKherKeep.class)); + cards.add(new SetCardInfo("Rubinia Soulsinger", 256, Rarity.RARE, mage.cards.r.RubiniaSoulsinger.class)); + cards.add(new SetCardInfo("Rust", 203, Rarity.COMMON, mage.cards.r.Rust.class)); + cards.add(new SetCardInfo("Sea Kings' Blessing", 75, Rarity.UNCOMMON, mage.cards.s.SeaKingsBlessing.class)); + cards.add(new SetCardInfo("Seafarer's Quay", 306, Rarity.UNCOMMON, mage.cards.s.SeafarersQuay.class)); + cards.add(new SetCardInfo("Seeker", 35, Rarity.UNCOMMON, mage.cards.s.Seeker.class)); + cards.add(new SetCardInfo("Segovian Leviathan", 76, Rarity.UNCOMMON, mage.cards.s.SegovianLeviathan.class)); + cards.add(new SetCardInfo("Sentinel", 294, Rarity.RARE, mage.cards.s.Sentinel.class)); + cards.add(new SetCardInfo("Serpent Generator", 295, Rarity.RARE, mage.cards.s.SerpentGenerator.class)); + cards.add(new SetCardInfo("Shelkin Brownie", 204, Rarity.COMMON, mage.cards.s.ShelkinBrownie.class)); + cards.add(new SetCardInfo("Shield Wall", 36, Rarity.UNCOMMON, mage.cards.s.ShieldWall.class)); + cards.add(new SetCardInfo("Shimian Night Stalker", 116, Rarity.UNCOMMON, mage.cards.s.ShimianNightStalker.class)); + cards.add(new SetCardInfo("Sir Shandlar of Eberyn", 257, Rarity.UNCOMMON, mage.cards.s.SirShandlarOfEberyn.class)); + cards.add(new SetCardInfo("Sivitri Scarzam", 258, Rarity.UNCOMMON, mage.cards.s.SivitriScarzam.class)); + cards.add(new SetCardInfo("Sol'kanar the Swamp King", 259, Rarity.RARE, mage.cards.s.SolkanarTheSwampKing.class)); + cards.add(new SetCardInfo("Spectral Cloak", 78, Rarity.UNCOMMON, mage.cards.s.SpectralCloak.class)); + cards.add(new SetCardInfo("Spinal Villain", 164, Rarity.RARE, mage.cards.s.SpinalVillain.class)); + cards.add(new SetCardInfo("Spirit Link", 37, Rarity.UNCOMMON, mage.cards.s.SpiritLink.class)); + cards.add(new SetCardInfo("Spirit Shackle", 117, Rarity.COMMON, mage.cards.s.SpiritShackle.class)); + cards.add(new SetCardInfo("Spiritual Sanctuary", 38, Rarity.RARE, mage.cards.s.SpiritualSanctuary.class)); + cards.add(new SetCardInfo("Stangg", 260, Rarity.RARE, mage.cards.s.Stangg.class)); + cards.add(new SetCardInfo("Storm Seeker", 205, Rarity.UNCOMMON, mage.cards.s.StormSeeker.class)); + cards.add(new SetCardInfo("Storm World", 165, Rarity.RARE, mage.cards.s.StormWorld.class)); + cards.add(new SetCardInfo("Subdue", 206, Rarity.COMMON, mage.cards.s.Subdue.class)); + cards.add(new SetCardInfo("Sunastian Falconer", 261, Rarity.UNCOMMON, mage.cards.s.SunastianFalconer.class)); + cards.add(new SetCardInfo("Sword of the Ages", 296, Rarity.RARE, mage.cards.s.SwordOfTheAges.class)); + cards.add(new SetCardInfo("Sylvan Library", 207, Rarity.UNCOMMON, mage.cards.s.SylvanLibrary.class)); + cards.add(new SetCardInfo("Sylvan Paradise", 208, Rarity.UNCOMMON, mage.cards.s.SylvanParadise.class)); + cards.add(new SetCardInfo("Syphon Soul", 118, Rarity.COMMON, mage.cards.s.SyphonSoul.class)); + cards.add(new SetCardInfo("Telekinesis", 79, Rarity.RARE, mage.cards.t.Telekinesis.class)); + cards.add(new SetCardInfo("Teleport", 80, Rarity.RARE, mage.cards.t.Teleport.class)); + cards.add(new SetCardInfo("Tetsuo Umezawa", 262, Rarity.RARE, mage.cards.t.TetsuoUmezawa.class)); + cards.add(new SetCardInfo("The Abyss", 120, Rarity.RARE, mage.cards.t.TheAbyss.class)); + cards.add(new SetCardInfo("The Brute", 167, Rarity.COMMON, mage.cards.t.TheBrute.class)); + cards.add(new SetCardInfo("The Lady of the Mountain", 263, Rarity.UNCOMMON, mage.cards.t.TheLadyOfTheMountain.class)); + cards.add(new SetCardInfo("The Tabernacle at Pendrell Vale", 307, Rarity.RARE, mage.cards.t.TheTabernacleAtPendrellVale.class)); + cards.add(new SetCardInfo("The Wretched", 121, Rarity.RARE, mage.cards.t.TheWretched.class)); + cards.add(new SetCardInfo("Thunder Spirit", 39, Rarity.RARE, mage.cards.t.ThunderSpirit.class)); + cards.add(new SetCardInfo("Time Elemental", 81, Rarity.RARE, mage.cards.t.TimeElemental.class)); + cards.add(new SetCardInfo("Tobias Andrion", 264, Rarity.UNCOMMON, mage.cards.t.TobiasAndrion.class)); + cards.add(new SetCardInfo("Tolaria", 308, Rarity.UNCOMMON, mage.cards.t.Tolaria.class)); + cards.add(new SetCardInfo("Tor Wauki", 265, Rarity.UNCOMMON, mage.cards.t.TorWauki.class)); + cards.add(new SetCardInfo("Torsten Von Ursus", 266, Rarity.UNCOMMON, mage.cards.t.TorstenVonUrsus.class)); + cards.add(new SetCardInfo("Touch of Darkness", 122, Rarity.UNCOMMON, mage.cards.t.TouchOfDarkness.class)); + cards.add(new SetCardInfo("Transmutation", 123, Rarity.COMMON, mage.cards.t.Transmutation.class)); + cards.add(new SetCardInfo("Triassic Egg", 297, Rarity.RARE, mage.cards.t.TriassicEgg.class)); + cards.add(new SetCardInfo("Tuknir Deathlock", 267, Rarity.RARE, mage.cards.t.TuknirDeathlock.class)); + cards.add(new SetCardInfo("Tundra Wolves", 40, Rarity.COMMON, mage.cards.t.TundraWolves.class)); + cards.add(new SetCardInfo("Typhoon", 209, Rarity.RARE, mage.cards.t.Typhoon.class)); + cards.add(new SetCardInfo("Undertow", 82, Rarity.UNCOMMON, mage.cards.u.Undertow.class)); + cards.add(new SetCardInfo("Unholy Citadel", 309, Rarity.UNCOMMON, mage.cards.u.UnholyCitadel.class)); + cards.add(new SetCardInfo("Underworld Dreams", 124, Rarity.UNCOMMON, mage.cards.u.UnderworldDreams.class)); + cards.add(new SetCardInfo("Untamed Wilds", 210, Rarity.UNCOMMON, mage.cards.u.UntamedWilds.class)); + cards.add(new SetCardInfo("Ur-Drago", 268, Rarity.RARE, mage.cards.u.UrDrago.class)); + cards.add(new SetCardInfo("Urborg", 310, Rarity.UNCOMMON, mage.cards.u.Urborg.class)); + cards.add(new SetCardInfo("Vaevictis Asmadi", 269, Rarity.RARE, mage.cards.v.VaevictisAsmadi.class)); + cards.add(new SetCardInfo("Vampire Bats", 125, Rarity.COMMON, mage.cards.v.VampireBats.class)); + cards.add(new SetCardInfo("Visions", 41, Rarity.UNCOMMON, mage.cards.v.Visions.class)); + cards.add(new SetCardInfo("Walking Dead", 126, Rarity.COMMON, mage.cards.w.WalkingDead.class)); + cards.add(new SetCardInfo("Wall of Caltrops", 42, Rarity.COMMON, mage.cards.w.WallOfCaltrops.class)); + cards.add(new SetCardInfo("Wall of Dust", 168, Rarity.UNCOMMON, mage.cards.w.WallOfDust.class)); + cards.add(new SetCardInfo("Wall of Earth", 169, Rarity.COMMON, mage.cards.w.WallOfEarth.class)); + cards.add(new SetCardInfo("Wall of Heat", 170, Rarity.COMMON, mage.cards.w.WallOfHeat.class)); + cards.add(new SetCardInfo("Wall of Light", 43, Rarity.UNCOMMON, mage.cards.w.WallOfLight.class)); + cards.add(new SetCardInfo("Wall of Opposition", 171, Rarity.RARE, mage.cards.w.WallOfOpposition.class)); + cards.add(new SetCardInfo("Wall of Putrid Flesh", 127, Rarity.UNCOMMON, mage.cards.w.WallOfPutridFlesh.class)); + cards.add(new SetCardInfo("Wall of Tombstones", 129, Rarity.UNCOMMON, mage.cards.w.WallOfTombstones.class)); + cards.add(new SetCardInfo("Wall of Vapor", 84, Rarity.COMMON, mage.cards.w.WallOfVapor.class)); + cards.add(new SetCardInfo("Wall of Wonder", 85, Rarity.UNCOMMON, mage.cards.w.WallOfWonder.class)); + cards.add(new SetCardInfo("Whirling Dervish", 211, Rarity.UNCOMMON, mage.cards.w.WhirlingDervish.class)); + cards.add(new SetCardInfo("White Mana Battery", 299, Rarity.UNCOMMON, mage.cards.w.WhiteManaBattery.class)); + cards.add(new SetCardInfo("Willow Satyr", 212, Rarity.RARE, mage.cards.w.WillowSatyr.class)); + cards.add(new SetCardInfo("Winds of Change", 172, Rarity.UNCOMMON, mage.cards.w.WindsOfChange.class)); + cards.add(new SetCardInfo("Winter Blast", 213, Rarity.RARE, mage.cards.w.WinterBlast.class)); + cards.add(new SetCardInfo("Wolverine Pack", 214, Rarity.COMMON, mage.cards.w.WolverinePack.class)); + cards.add(new SetCardInfo("Wood Elemental", 215, Rarity.RARE, mage.cards.w.WoodElemental.class)); + cards.add(new SetCardInfo("Xira Arien", 270, Rarity.RARE, mage.cards.x.XiraArien.class)); + cards.add(new SetCardInfo("Zephyr Falcon", 86, Rarity.COMMON, mage.cards.z.ZephyrFalcon.class)); + } +} diff --git a/Mage.Sets/src/mage/sets/MercadianMasques.java b/Mage.Sets/src/mage/sets/MercadianMasques.java index a1110e968cd..aa70db5e8a7 100644 --- a/Mage.Sets/src/mage/sets/MercadianMasques.java +++ b/Mage.Sets/src/mage/sets/MercadianMasques.java @@ -75,6 +75,7 @@ public final class MercadianMasques extends ExpansionSet { cards.add(new SetCardInfo("Cho-Manno, Revolutionary", 11, Rarity.RARE, mage.cards.c.ChoMannoRevolutionary.class)); cards.add(new SetCardInfo("Cho-Manno's Blessing", 12, Rarity.COMMON, mage.cards.c.ChoMannosBlessing.class)); cards.add(new SetCardInfo("Cinder Elemental", 183, Rarity.UNCOMMON, mage.cards.c.CinderElemental.class)); + cards.add(new SetCardInfo("Clear the Land", 235, Rarity.RARE, mage.cards.c.ClearTheLand.class)); cards.add(new SetCardInfo("Close Quarters", 184, Rarity.UNCOMMON, mage.cards.c.CloseQuarters.class)); cards.add(new SetCardInfo("Cloud Sprite", 67, Rarity.COMMON, mage.cards.c.CloudSprite.class)); cards.add(new SetCardInfo("Coastal Piracy", 68, Rarity.UNCOMMON, mage.cards.c.CoastalPiracy.class)); diff --git a/Mage.Sets/src/mage/sets/Planeshift.java b/Mage.Sets/src/mage/sets/Planeshift.java index 57a70190de4..206dd194b31 100644 --- a/Mage.Sets/src/mage/sets/Planeshift.java +++ b/Mage.Sets/src/mage/sets/Planeshift.java @@ -30,6 +30,7 @@ public final class Planeshift extends ExpansionSet { cards.add(new SetCardInfo("Allied Strategies", 20, Rarity.UNCOMMON, mage.cards.a.AlliedStrategies.class)); cards.add(new SetCardInfo("Alpha Kavu", 77, Rarity.UNCOMMON, mage.cards.a.AlphaKavu.class)); + cards.add(new SetCardInfo("Amphibious Kavu", 78, Rarity.COMMON, mage.cards.a.AmphibiousKavu.class)); cards.add(new SetCardInfo("Ancient Spider", 96, Rarity.RARE, mage.cards.a.AncientSpider.class)); cards.add(new SetCardInfo("Arctic Merfolk", 21, Rarity.COMMON, mage.cards.a.ArcticMerfolk.class)); cards.add(new SetCardInfo("Aura Blast", 1, Rarity.COMMON, mage.cards.a.AuraBlast.class)); @@ -50,6 +51,7 @@ public final class Planeshift extends ExpansionSet { cards.add(new SetCardInfo("Destructive Flow", 102, Rarity.RARE, mage.cards.d.DestructiveFlow.class)); cards.add(new SetCardInfo("Diabolic Intent", 42, Rarity.RARE, mage.cards.d.DiabolicIntent.class)); cards.add(new SetCardInfo("Disciple of Kangee", 3, Rarity.COMMON, mage.cards.d.DiscipleOfKangee.class)); + cards.add(new SetCardInfo("Dominaria's Judgment", 4, Rarity.RARE, mage.cards.d.DominariasJudgment.class)); cards.add(new SetCardInfo("Doomsday Specter", 103, Rarity.RARE, mage.cards.d.DoomsdaySpecter.class)); cards.add(new SetCardInfo("Draco", 131, Rarity.RARE, mage.cards.d.Draco.class)); cards.add(new SetCardInfo("Dralnu's Crusade", 104, Rarity.RARE, mage.cards.d.DralnusCrusade.class)); @@ -71,6 +73,7 @@ public final class Planeshift extends ExpansionSet { cards.add(new SetCardInfo("Gainsay", 26, Rarity.UNCOMMON, mage.cards.g.Gainsay.class)); cards.add(new SetCardInfo("Gerrard's Command", 109, Rarity.COMMON, mage.cards.g.GerrardsCommand.class)); cards.add(new SetCardInfo("Goblin Game", 61, Rarity.RARE, mage.cards.g.GoblinGame.class)); + cards.add(new SetCardInfo("Guard Dogs", 5, Rarity.UNCOMMON, mage.cards.g.GuardDogs.class)); cards.add(new SetCardInfo("Heroic Defiance", 6, Rarity.COMMON, mage.cards.h.HeroicDefiance.class)); cards.add(new SetCardInfo("Hobble", 7, Rarity.COMMON, mage.cards.h.Hobble.class)); cards.add(new SetCardInfo("Honorable Scout", 8, Rarity.COMMON, mage.cards.h.HonorableScout.class)); @@ -95,6 +98,7 @@ public final class Planeshift extends ExpansionSet { cards.add(new SetCardInfo("Meddling Mage", 116, Rarity.RARE, mage.cards.m.MeddlingMage.class)); cards.add(new SetCardInfo("Meteor Crater", 140, Rarity.RARE, mage.cards.m.MeteorCrater.class)); cards.add(new SetCardInfo("Mire Kavu", 67, Rarity.COMMON, mage.cards.m.MireKavu.class)); + cards.add(new SetCardInfo("Mirrorwood Treefolk", 83, Rarity.UNCOMMON, mage.cards.m.MirrorwoodTreefolk.class)); cards.add(new SetCardInfo("Mogg Jailer", 68, Rarity.UNCOMMON, mage.cards.m.MoggJailer.class)); cards.add(new SetCardInfo("Mogg Sentry", 69, Rarity.RARE, mage.cards.m.MoggSentry.class)); cards.add(new SetCardInfo("Morgue Toad", 46, Rarity.COMMON, mage.cards.m.MorgueToad.class)); @@ -103,6 +107,7 @@ public final class Planeshift extends ExpansionSet { cards.add(new SetCardInfo("Nemata, Grove Guardian", 85, Rarity.RARE, mage.cards.n.NemataGroveGuardian.class)); cards.add(new SetCardInfo("Nightscape Battlemage", 47, Rarity.UNCOMMON, mage.cards.n.NightscapeBattlemage.class)); cards.add(new SetCardInfo("Nightscape Familiar", 48, Rarity.COMMON, mage.cards.n.NightscapeFamiliar.class)); + cards.add(new SetCardInfo("Noxious Vapors", 49, Rarity.UNCOMMON, mage.cards.n.NoxiousVapors.class)); cards.add(new SetCardInfo("Orim's Chant", 11, Rarity.RARE, mage.cards.o.OrimsChant.class)); cards.add(new SetCardInfo("Phyrexian Bloodstock", 50, Rarity.COMMON, mage.cards.p.PhyrexianBloodstock.class)); cards.add(new SetCardInfo("Phyrexian Scuta", 51, Rarity.RARE, mage.cards.p.PhyrexianScuta.class)); diff --git a/Mage.Sets/src/mage/sets/Prophecy.java b/Mage.Sets/src/mage/sets/Prophecy.java index 428e91c8763..66b0ea67afb 100644 --- a/Mage.Sets/src/mage/sets/Prophecy.java +++ b/Mage.Sets/src/mage/sets/Prophecy.java @@ -136,6 +136,7 @@ public final class Prophecy extends ExpansionSet { cards.add(new SetCardInfo("Silt Crawler", 123, Rarity.COMMON, mage.cards.s.SiltCrawler.class)); cards.add(new SetCardInfo("Snag", 124, Rarity.UNCOMMON, mage.cards.s.Snag.class)); cards.add(new SetCardInfo("Soul Charmer", 24, Rarity.COMMON, mage.cards.s.SoulCharmer.class)); + cards.add(new SetCardInfo("Soul Strings", 78, Rarity.COMMON, mage.cards.s.SoulStrings.class)); cards.add(new SetCardInfo("Spiketail Drake", 48, Rarity.UNCOMMON, mage.cards.s.SpiketailDrake.class)); cards.add(new SetCardInfo("Spiketail Hatchling", 49, Rarity.COMMON, mage.cards.s.SpiketailHatchling.class)); cards.add(new SetCardInfo("Spitting Spider", 125, Rarity.UNCOMMON, mage.cards.s.SpittingSpider.class)); diff --git a/Mage.Sets/src/mage/sets/Tempest.java b/Mage.Sets/src/mage/sets/Tempest.java index 5269f4c17c7..e1ec411d32e 100644 --- a/Mage.Sets/src/mage/sets/Tempest.java +++ b/Mage.Sets/src/mage/sets/Tempest.java @@ -1,368 +1,369 @@ -package mage.sets; - -import mage.cards.ExpansionSet; -import mage.constants.Rarity; -import mage.constants.SetType; - -public final class Tempest extends ExpansionSet { - - private static final Tempest instance = new Tempest(); - - public static Tempest getInstance() { - return instance; - } - - private Tempest() { - super("Tempest", "TMP", ExpansionSet.buildDate(1997, 10, 1), SetType.EXPANSION); - this.blockName = "Tempest"; - this.hasBoosters = true; - this.numBoosterLands = 0; - this.numBoosterCommon = 11; - this.numBoosterUncommon = 3; - this.numBoosterRare = 1; - this.ratioBoosterMythic = 0; - cards.add(new SetCardInfo("Abandon Hope", 107, Rarity.UNCOMMON, mage.cards.a.AbandonHope.class)); - cards.add(new SetCardInfo("Advance Scout", 1, Rarity.COMMON, mage.cards.a.AdvanceScout.class)); - cards.add(new SetCardInfo("Aftershock", 160, Rarity.COMMON, mage.cards.a.Aftershock.class)); - cards.add(new SetCardInfo("Altar of Dementia", 276, Rarity.RARE, mage.cards.a.AltarOfDementia.class)); - cards.add(new SetCardInfo("Aluren", 213, Rarity.RARE, mage.cards.a.Aluren.class)); - cards.add(new SetCardInfo("Ancient Runes", 161, Rarity.UNCOMMON, mage.cards.a.AncientRunes.class)); - cards.add(new SetCardInfo("Ancient Tomb", 315, Rarity.UNCOMMON, mage.cards.a.AncientTomb.class)); - cards.add(new SetCardInfo("Angelic Protector", 2, Rarity.UNCOMMON, mage.cards.a.AngelicProtector.class)); - cards.add(new SetCardInfo("Anoint", 3, Rarity.COMMON, mage.cards.a.Anoint.class)); - cards.add(new SetCardInfo("Apes of Rath", 214, Rarity.UNCOMMON, mage.cards.a.ApesOfRath.class)); - cards.add(new SetCardInfo("Apocalypse", 162, Rarity.RARE, mage.cards.a.Apocalypse.class)); - cards.add(new SetCardInfo("Armor Sliver", 4, Rarity.UNCOMMON, mage.cards.a.ArmorSliver.class)); - cards.add(new SetCardInfo("Armored Pegasus", 5, Rarity.COMMON, mage.cards.a.ArmoredPegasus.class)); - cards.add(new SetCardInfo("Auratog", 6, Rarity.RARE, mage.cards.a.Auratog.class)); - cards.add(new SetCardInfo("Avenging Angel", 7, Rarity.RARE, mage.cards.a.AvengingAngel.class)); - cards.add(new SetCardInfo("Barbed Sliver", 163, Rarity.UNCOMMON, mage.cards.b.BarbedSliver.class)); - cards.add(new SetCardInfo("Bayou Dragonfly", 215, Rarity.COMMON, mage.cards.b.BayouDragonfly.class)); - cards.add(new SetCardInfo("Bellowing Fiend", 108, Rarity.RARE, mage.cards.b.BellowingFiend.class)); - cards.add(new SetCardInfo("Benthic Behemoth", 54, Rarity.RARE, mage.cards.b.BenthicBehemoth.class)); - cards.add(new SetCardInfo("Blood Frenzy", 164, Rarity.COMMON, mage.cards.b.BloodFrenzy.class)); - cards.add(new SetCardInfo("Blood Pet", 109, Rarity.COMMON, mage.cards.b.BloodPet.class)); - cards.add(new SetCardInfo("Boil", 165, Rarity.UNCOMMON, mage.cards.b.Boil.class)); - cards.add(new SetCardInfo("Booby Trap", 277, Rarity.RARE, mage.cards.b.BoobyTrap.class)); - cards.add(new SetCardInfo("Bottle Gnomes", 278, Rarity.UNCOMMON, mage.cards.b.BottleGnomes.class)); - cards.add(new SetCardInfo("Bounty Hunter", 110, Rarity.RARE, mage.cards.b.BountyHunter.class)); - cards.add(new SetCardInfo("Broken Fall", 216, Rarity.COMMON, mage.cards.b.BrokenFall.class)); - cards.add(new SetCardInfo("Caldera Lake", 316, Rarity.RARE, mage.cards.c.CalderaLake.class)); - cards.add(new SetCardInfo("Canopy Spider", 217, Rarity.COMMON, mage.cards.c.CanopySpider.class)); - cards.add(new SetCardInfo("Canyon Drake", 166, Rarity.RARE, mage.cards.c.CanyonDrake.class)); - cards.add(new SetCardInfo("Canyon Wildcat", 167, Rarity.COMMON, mage.cards.c.CanyonWildcat.class)); - cards.add(new SetCardInfo("Capsize", 55, Rarity.COMMON, mage.cards.c.Capsize.class)); - cards.add(new SetCardInfo("Carrionette", 111, Rarity.RARE, mage.cards.c.Carrionette.class)); - cards.add(new SetCardInfo("Chaotic Goo", 168, Rarity.RARE, mage.cards.c.ChaoticGoo.class)); - cards.add(new SetCardInfo("Charging Rhino", 218, Rarity.UNCOMMON, mage.cards.c.ChargingRhino.class)); - cards.add(new SetCardInfo("Chill", 56, Rarity.UNCOMMON, mage.cards.c.Chill.class)); - cards.add(new SetCardInfo("Choke", 219, Rarity.UNCOMMON, mage.cards.c.Choke.class)); - cards.add(new SetCardInfo("Cinder Marsh", 317, Rarity.UNCOMMON, mage.cards.c.CinderMarsh.class)); - cards.add(new SetCardInfo("Circle of Protection: Black", 8, Rarity.COMMON, mage.cards.c.CircleOfProtectionBlack.class)); - cards.add(new SetCardInfo("Circle of Protection: Blue", 9, Rarity.COMMON, mage.cards.c.CircleOfProtectionBlue.class)); - cards.add(new SetCardInfo("Circle of Protection: Green", 10, Rarity.COMMON, mage.cards.c.CircleOfProtectionGreen.class)); - cards.add(new SetCardInfo("Circle of Protection: Red", 11, Rarity.COMMON, mage.cards.c.CircleOfProtectionRed.class)); - cards.add(new SetCardInfo("Circle of Protection: Shadow", 12, Rarity.COMMON, mage.cards.c.CircleOfProtectionShadow.class)); - cards.add(new SetCardInfo("Circle of Protection: White", 13, Rarity.COMMON, mage.cards.c.CircleOfProtectionWhite.class)); - cards.add(new SetCardInfo("Clergy en-Vec", 14, Rarity.COMMON, mage.cards.c.ClergyEnVec.class)); - cards.add(new SetCardInfo("Clot Sliver", 112, Rarity.COMMON, mage.cards.c.ClotSliver.class)); - cards.add(new SetCardInfo("Cloudchaser Eagle", 15, Rarity.COMMON, mage.cards.c.CloudchaserEagle.class)); - cards.add(new SetCardInfo("Coercion", 113, Rarity.COMMON, mage.cards.c.Coercion.class)); - cards.add(new SetCardInfo("Coffin Queen", 114, Rarity.RARE, mage.cards.c.CoffinQueen.class)); - cards.add(new SetCardInfo("Coiled Tinviper", 279, Rarity.COMMON, mage.cards.c.CoiledTinviper.class)); - cards.add(new SetCardInfo("Cold Storage", 280, Rarity.RARE, mage.cards.c.ColdStorage.class)); - cards.add(new SetCardInfo("Commander Greven il-Vec", 115, Rarity.RARE, mage.cards.c.CommanderGrevenIlVec.class)); - cards.add(new SetCardInfo("Corpse Dance", 116, Rarity.RARE, mage.cards.c.CorpseDance.class)); - cards.add(new SetCardInfo("Counterspell", 57, Rarity.COMMON, mage.cards.c.Counterspell.class)); - cards.add(new SetCardInfo("Crazed Armodon", 220, Rarity.RARE, mage.cards.c.CrazedArmodon.class)); - cards.add(new SetCardInfo("Crown of Flames", 169, Rarity.COMMON, mage.cards.c.CrownOfFlames.class)); - cards.add(new SetCardInfo("Cursed Scroll", 281, Rarity.RARE, mage.cards.c.CursedScroll.class)); - cards.add(new SetCardInfo("Dark Banishing", 117, Rarity.COMMON, mage.cards.d.DarkBanishing.class)); - cards.add(new SetCardInfo("Dark Ritual", 118, Rarity.COMMON, mage.cards.d.DarkRitual.class)); - cards.add(new SetCardInfo("Darkling Stalker", 119, Rarity.COMMON, mage.cards.d.DarklingStalker.class)); - cards.add(new SetCardInfo("Dauthi Embrace", 120, Rarity.UNCOMMON, mage.cards.d.DauthiEmbrace.class)); - cards.add(new SetCardInfo("Dauthi Ghoul", 121, Rarity.UNCOMMON, mage.cards.d.DauthiGhoul.class)); - cards.add(new SetCardInfo("Dauthi Horror", 122, Rarity.COMMON, mage.cards.d.DauthiHorror.class)); - cards.add(new SetCardInfo("Dauthi Marauder", 123, Rarity.COMMON, mage.cards.d.DauthiMarauder.class)); - cards.add(new SetCardInfo("Dauthi Mercenary", 124, Rarity.UNCOMMON, mage.cards.d.DauthiMercenary.class)); - cards.add(new SetCardInfo("Dauthi Mindripper", 125, Rarity.UNCOMMON, mage.cards.d.DauthiMindripper.class)); - cards.add(new SetCardInfo("Dauthi Slayer", 126, Rarity.COMMON, mage.cards.d.DauthiSlayer.class)); - cards.add(new SetCardInfo("Deadshot", 170, Rarity.RARE, mage.cards.d.Deadshot.class)); - cards.add(new SetCardInfo("Death Pits of Rath", 127, Rarity.RARE, mage.cards.d.DeathPitsOfRath.class)); - cards.add(new SetCardInfo("Diabolic Edict", 128, Rarity.COMMON, mage.cards.d.DiabolicEdict.class)); - cards.add(new SetCardInfo("Dirtcowl Wurm", 221, Rarity.RARE, mage.cards.d.DirtcowlWurm.class)); - cards.add(new SetCardInfo("Disenchant", 16, Rarity.COMMON, mage.cards.d.Disenchant.class)); - cards.add(new SetCardInfo("Dismiss", 58, Rarity.UNCOMMON, mage.cards.d.Dismiss.class)); - cards.add(new SetCardInfo("Disturbed Burial", 129, Rarity.COMMON, mage.cards.d.DisturbedBurial.class)); - cards.add(new SetCardInfo("Dracoplasm", 266, Rarity.RARE, mage.cards.d.Dracoplasm.class)); - cards.add(new SetCardInfo("Dread of Night", 130, Rarity.UNCOMMON, mage.cards.d.DreadOfNight.class)); - cards.add(new SetCardInfo("Dream Cache", 59, Rarity.COMMON, mage.cards.d.DreamCache.class)); - cards.add(new SetCardInfo("Dregs of Sorrow", 131, Rarity.RARE, mage.cards.d.DregsOfSorrow.class)); - cards.add(new SetCardInfo("Earthcraft", 222, Rarity.RARE, mage.cards.e.Earthcraft.class)); - cards.add(new SetCardInfo("Echo Chamber", 282, Rarity.RARE, mage.cards.e.EchoChamber.class)); - cards.add(new SetCardInfo("Eladamri's Vineyard", 223, Rarity.RARE, mage.cards.e.EladamrisVineyard.class)); - cards.add(new SetCardInfo("Eladamri, Lord of Leaves", 224, Rarity.RARE, mage.cards.e.EladamriLordOfLeaves.class)); - cards.add(new SetCardInfo("Elite Javelineer", 17, Rarity.COMMON, mage.cards.e.EliteJavelineer.class)); - cards.add(new SetCardInfo("Elven Warhounds", 225, Rarity.RARE, mage.cards.e.ElvenWarhounds.class)); - cards.add(new SetCardInfo("Elvish Fury", 226, Rarity.COMMON, mage.cards.e.ElvishFury.class)); - cards.add(new SetCardInfo("Emerald Medallion", 283, Rarity.RARE, mage.cards.e.EmeraldMedallion.class)); - cards.add(new SetCardInfo("Emmessi Tome", 284, Rarity.RARE, mage.cards.e.EmmessiTome.class)); - cards.add(new SetCardInfo("Endless Scream", 132, Rarity.COMMON, mage.cards.e.EndlessScream.class)); - cards.add(new SetCardInfo("Energizer", 285, Rarity.RARE, mage.cards.e.Energizer.class)); - cards.add(new SetCardInfo("Enfeeblement", 133, Rarity.COMMON, mage.cards.e.Enfeeblement.class)); - cards.add(new SetCardInfo("Enraging Licid", 171, Rarity.UNCOMMON, mage.cards.e.EnragingLicid.class)); - cards.add(new SetCardInfo("Essence Bottle", 286, Rarity.UNCOMMON, mage.cards.e.EssenceBottle.class)); - cards.add(new SetCardInfo("Evincar's Justice", 134, Rarity.COMMON, mage.cards.e.EvincarsJustice.class)); - cards.add(new SetCardInfo("Excavator", 287, Rarity.UNCOMMON, mage.cards.e.Excavator.class)); - cards.add(new SetCardInfo("Extinction", 135, Rarity.RARE, mage.cards.e.Extinction.class)); - cards.add(new SetCardInfo("Fevered Convulsions", 136, Rarity.RARE, mage.cards.f.FeveredConvulsions.class)); - cards.add(new SetCardInfo("Field of Souls", 18, Rarity.RARE, mage.cards.f.FieldOfSouls.class)); - cards.add(new SetCardInfo("Fighting Drake", 63, Rarity.UNCOMMON, mage.cards.f.FightingDrake.class)); - cards.add(new SetCardInfo("Firefly", 172, Rarity.UNCOMMON, mage.cards.f.Firefly.class)); - cards.add(new SetCardInfo("Fireslinger", 173, Rarity.COMMON, mage.cards.f.Fireslinger.class)); - cards.add(new SetCardInfo("Flailing Drake", 227, Rarity.UNCOMMON, mage.cards.f.FlailingDrake.class)); - cards.add(new SetCardInfo("Flickering Ward", 19, Rarity.UNCOMMON, mage.cards.f.FlickeringWard.class)); - cards.add(new SetCardInfo("Flowstone Giant", 174, Rarity.COMMON, mage.cards.f.FlowstoneGiant.class)); - cards.add(new SetCardInfo("Flowstone Salamander", 175, Rarity.UNCOMMON, mage.cards.f.FlowstoneSalamander.class)); - cards.add(new SetCardInfo("Flowstone Sculpture", 288, Rarity.RARE, mage.cards.f.FlowstoneSculpture.class)); - cards.add(new SetCardInfo("Flowstone Wyvern", 176, Rarity.RARE, mage.cards.f.FlowstoneWyvern.class)); - cards.add(new SetCardInfo("Fool's Tome", 289, Rarity.RARE, mage.cards.f.FoolsTome.class)); - cards.add(new SetCardInfo("Forest", 347, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Forest", 348, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Forest", 349, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Forest", 350, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Frog Tongue", 228, Rarity.COMMON, mage.cards.f.FrogTongue.class)); - cards.add(new SetCardInfo("Fugitive Druid", 229, Rarity.RARE, mage.cards.f.FugitiveDruid.class)); - cards.add(new SetCardInfo("Furnace of Rath", 177, Rarity.RARE, mage.cards.f.FurnaceOfRath.class)); - cards.add(new SetCardInfo("Fylamarid", 64, Rarity.UNCOMMON, mage.cards.f.Fylamarid.class)); - cards.add(new SetCardInfo("Gallantry", 20, Rarity.UNCOMMON, mage.cards.g.Gallantry.class)); - cards.add(new SetCardInfo("Gaseous Form", 65, Rarity.COMMON, mage.cards.g.GaseousForm.class)); - cards.add(new SetCardInfo("Gerrard's Battle Cry", 21, Rarity.RARE, mage.cards.g.GerrardsBattleCry.class)); - cards.add(new SetCardInfo("Ghost Town", 318, Rarity.UNCOMMON, mage.cards.g.GhostTown.class)); - cards.add(new SetCardInfo("Giant Crab", 66, Rarity.COMMON, mage.cards.g.GiantCrab.class)); - cards.add(new SetCardInfo("Giant Strength", 178, Rarity.COMMON, mage.cards.g.GiantStrength.class)); - cards.add(new SetCardInfo("Goblin Bombardment", 179, Rarity.UNCOMMON, mage.cards.g.GoblinBombardment.class)); - cards.add(new SetCardInfo("Gravedigger", 137, Rarity.COMMON, mage.cards.g.Gravedigger.class)); - cards.add(new SetCardInfo("Grindstone", 290, Rarity.RARE, mage.cards.g.Grindstone.class)); - cards.add(new SetCardInfo("Hand to Hand", 180, Rarity.RARE, mage.cards.h.HandToHand.class)); - cards.add(new SetCardInfo("Hanna's Custody", 22, Rarity.RARE, mage.cards.h.HannasCustody.class)); - cards.add(new SetCardInfo("Harrow", 230, Rarity.UNCOMMON, mage.cards.h.Harrow.class)); - cards.add(new SetCardInfo("Havoc", 181, Rarity.UNCOMMON, mage.cards.h.Havoc.class)); - cards.add(new SetCardInfo("Heart Sliver", 182, Rarity.COMMON, mage.cards.h.HeartSliver.class)); - cards.add(new SetCardInfo("Heartwood Dryad", 231, Rarity.COMMON, mage.cards.h.HeartwoodDryad.class)); - cards.add(new SetCardInfo("Heartwood Giant", 232, Rarity.RARE, mage.cards.h.HeartwoodGiant.class)); - cards.add(new SetCardInfo("Heartwood Treefolk", 233, Rarity.UNCOMMON, mage.cards.h.HeartwoodTreefolk.class)); - cards.add(new SetCardInfo("Helm of Possession", 291, Rarity.RARE, mage.cards.h.HelmOfPossession.class)); - cards.add(new SetCardInfo("Hero's Resolve", 23, Rarity.COMMON, mage.cards.h.HerosResolve.class)); - cards.add(new SetCardInfo("Horned Sliver", 234, Rarity.UNCOMMON, mage.cards.h.HornedSliver.class)); - cards.add(new SetCardInfo("Horned Turtle", 67, Rarity.COMMON, mage.cards.h.HornedTurtle.class)); - cards.add(new SetCardInfo("Humility", 24, Rarity.RARE, mage.cards.h.Humility.class)); - cards.add(new SetCardInfo("Imps' Taunt", 138, Rarity.UNCOMMON, mage.cards.i.ImpsTaunt.class)); - cards.add(new SetCardInfo("Insight", 68, Rarity.UNCOMMON, mage.cards.i.Insight.class)); - cards.add(new SetCardInfo("Interdict", 69, Rarity.UNCOMMON, mage.cards.i.Interdict.class)); - cards.add(new SetCardInfo("Intuition", 70, Rarity.RARE, mage.cards.i.Intuition.class)); - cards.add(new SetCardInfo("Invulnerability", 25, Rarity.UNCOMMON, mage.cards.i.Invulnerability.class)); - cards.add(new SetCardInfo("Island", 335, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Island", 336, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Island", 337, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Island", 338, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Jackal Pup", 183, Rarity.UNCOMMON, mage.cards.j.JackalPup.class)); - cards.add(new SetCardInfo("Jet Medallion", 292, Rarity.RARE, mage.cards.j.JetMedallion.class)); - cards.add(new SetCardInfo("Jinxed Idol", 293, Rarity.RARE, mage.cards.j.JinxedIdol.class)); - cards.add(new SetCardInfo("Kezzerdrix", 139, Rarity.RARE, mage.cards.k.Kezzerdrix.class)); - cards.add(new SetCardInfo("Kindle", 184, Rarity.COMMON, mage.cards.k.Kindle.class)); - cards.add(new SetCardInfo("Knight of Dawn", 26, Rarity.UNCOMMON, mage.cards.k.KnightOfDawn.class)); - cards.add(new SetCardInfo("Knight of Dusk", 140, Rarity.UNCOMMON, mage.cards.k.KnightOfDusk.class)); - cards.add(new SetCardInfo("Krakilin", 235, Rarity.UNCOMMON, mage.cards.k.Krakilin.class)); - cards.add(new SetCardInfo("Leeching Licid", 141, Rarity.UNCOMMON, mage.cards.l.LeechingLicid.class)); - cards.add(new SetCardInfo("Legacy's Allure", 71, Rarity.UNCOMMON, mage.cards.l.LegacysAllure.class)); - cards.add(new SetCardInfo("Legerdemain", 72, Rarity.UNCOMMON, mage.cards.l.Legerdemain.class)); - cards.add(new SetCardInfo("Light of Day", 27, Rarity.UNCOMMON, mage.cards.l.LightOfDay.class)); - cards.add(new SetCardInfo("Lightning Blast", 185, Rarity.COMMON, mage.cards.l.LightningBlast.class)); - cards.add(new SetCardInfo("Lightning Elemental", 186, Rarity.COMMON, mage.cards.l.LightningElemental.class)); - cards.add(new SetCardInfo("Living Death", 142, Rarity.RARE, mage.cards.l.LivingDeath.class)); - cards.add(new SetCardInfo("Lobotomy", 267, Rarity.UNCOMMON, mage.cards.l.Lobotomy.class)); - cards.add(new SetCardInfo("Lotus Petal", 294, Rarity.COMMON, mage.cards.l.LotusPetal.class)); - cards.add(new SetCardInfo("Lowland Giant", 187, Rarity.COMMON, mage.cards.l.LowlandGiant.class)); - cards.add(new SetCardInfo("Maddening Imp", 143, Rarity.RARE, mage.cards.m.MaddeningImp.class)); - cards.add(new SetCardInfo("Magmasaur", 188, Rarity.RARE, mage.cards.m.Magmasaur.class)); - cards.add(new SetCardInfo("Mana Severance", 73, Rarity.RARE, mage.cards.m.ManaSeverance.class)); - cards.add(new SetCardInfo("Manakin", 296, Rarity.COMMON, mage.cards.m.Manakin.class)); - cards.add(new SetCardInfo("Manta Riders", 74, Rarity.COMMON, mage.cards.m.MantaRiders.class)); - cards.add(new SetCardInfo("Marble Titan", 28, Rarity.RARE, mage.cards.m.MarbleTitan.class)); - cards.add(new SetCardInfo("Marsh Lurker", 144, Rarity.COMMON, mage.cards.m.MarshLurker.class)); - cards.add(new SetCardInfo("Master Decoy", 29, Rarity.COMMON, mage.cards.m.MasterDecoy.class)); - cards.add(new SetCardInfo("Mawcor", 75, Rarity.RARE, mage.cards.m.Mawcor.class)); - cards.add(new SetCardInfo("Maze of Shadows", 319, Rarity.UNCOMMON, mage.cards.m.MazeOfShadows.class)); - cards.add(new SetCardInfo("Meditate", 76, Rarity.RARE, mage.cards.m.Meditate.class)); - cards.add(new SetCardInfo("Metallic Sliver", 297, Rarity.COMMON, mage.cards.m.MetallicSliver.class)); - cards.add(new SetCardInfo("Mindwhip Sliver", 145, Rarity.UNCOMMON, mage.cards.m.MindwhipSliver.class)); - cards.add(new SetCardInfo("Minion of the Wastes", 146, Rarity.RARE, mage.cards.m.MinionOfTheWastes.class)); - cards.add(new SetCardInfo("Mirri's Guile", 236, Rarity.RARE, mage.cards.m.MirrisGuile.class)); - cards.add(new SetCardInfo("Mnemonic Sliver", 77, Rarity.UNCOMMON, mage.cards.m.MnemonicSliver.class)); - cards.add(new SetCardInfo("Mogg Cannon", 298, Rarity.UNCOMMON, mage.cards.m.MoggCannon.class)); - cards.add(new SetCardInfo("Mogg Conscripts", 189, Rarity.COMMON, mage.cards.m.MoggConscripts.class)); - cards.add(new SetCardInfo("Mogg Fanatic", 190, Rarity.COMMON, mage.cards.m.MoggFanatic.class)); - cards.add(new SetCardInfo("Mogg Hollows", 320, Rarity.UNCOMMON, mage.cards.m.MoggHollows.class)); - cards.add(new SetCardInfo("Mogg Raider", 191, Rarity.COMMON, mage.cards.m.MoggRaider.class)); - cards.add(new SetCardInfo("Mogg Squad", 192, Rarity.UNCOMMON, mage.cards.m.MoggSquad.class)); - cards.add(new SetCardInfo("Mongrel Pack", 237, Rarity.RARE, mage.cards.m.MongrelPack.class)); - cards.add(new SetCardInfo("Mountain", 343, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Mountain", 344, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Mountain", 345, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Mountain", 346, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Mounted Archers", 30, Rarity.COMMON, mage.cards.m.MountedArchers.class)); - cards.add(new SetCardInfo("Muscle Sliver", 238, Rarity.COMMON, mage.cards.m.MuscleSliver.class)); - cards.add(new SetCardInfo("Natural Spring", 239, Rarity.COMMON, mage.cards.n.NaturalSpring.class)); - cards.add(new SetCardInfo("Nature's Revolt", 240, Rarity.RARE, mage.cards.n.NaturesRevolt.class)); - cards.add(new SetCardInfo("Needle Storm", 241, Rarity.UNCOMMON, mage.cards.n.NeedleStorm.class)); - cards.add(new SetCardInfo("Nurturing Licid", 242, Rarity.UNCOMMON, mage.cards.n.NurturingLicid.class)); - cards.add(new SetCardInfo("Opportunist", 194, Rarity.UNCOMMON, mage.cards.o.Opportunist.class)); - cards.add(new SetCardInfo("Oracle en-Vec", 31, Rarity.RARE, mage.cards.o.OracleEnVec.class)); - cards.add(new SetCardInfo("Orim's Prayer", 32, Rarity.UNCOMMON, mage.cards.o.OrimsPrayer.class)); - cards.add(new SetCardInfo("Orim, Samite Healer", 33, Rarity.RARE, mage.cards.o.OrimSamiteHealer.class)); - cards.add(new SetCardInfo("Overrun", 243, Rarity.UNCOMMON, mage.cards.o.Overrun.class)); - cards.add(new SetCardInfo("Pacifism", 34, Rarity.COMMON, mage.cards.p.Pacifism.class)); - cards.add(new SetCardInfo("Pallimud", 195, Rarity.RARE, mage.cards.p.Pallimud.class)); - cards.add(new SetCardInfo("Patchwork Gnomes", 299, Rarity.UNCOMMON, mage.cards.p.PatchworkGnomes.class)); - cards.add(new SetCardInfo("Pearl Medallion", 300, Rarity.RARE, mage.cards.p.PearlMedallion.class)); - cards.add(new SetCardInfo("Pegasus Refuge", 35, Rarity.RARE, mage.cards.p.PegasusRefuge.class)); - cards.add(new SetCardInfo("Perish", 147, Rarity.UNCOMMON, mage.cards.p.Perish.class)); - cards.add(new SetCardInfo("Phyrexian Grimoire", 301, Rarity.RARE, mage.cards.p.PhyrexianGrimoire.class)); - cards.add(new SetCardInfo("Phyrexian Hulk", 302, Rarity.UNCOMMON, mage.cards.p.PhyrexianHulk.class)); - cards.add(new SetCardInfo("Pincher Beetles", 244, Rarity.COMMON, mage.cards.p.PincherBeetles.class)); - cards.add(new SetCardInfo("Pine Barrens", 321, Rarity.RARE, mage.cards.p.PineBarrens.class)); - cards.add(new SetCardInfo("Pit Imp", 148, Rarity.COMMON, mage.cards.p.PitImp.class)); - cards.add(new SetCardInfo("Plains", 331, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Plains", 332, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Plains", 333, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Plains", 334, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Power Sink", 78, Rarity.COMMON, mage.cards.p.PowerSink.class)); - cards.add(new SetCardInfo("Precognition", 79, Rarity.RARE, mage.cards.p.Precognition.class)); - cards.add(new SetCardInfo("Propaganda", 80, Rarity.UNCOMMON, mage.cards.p.Propaganda.class)); - cards.add(new SetCardInfo("Puppet Strings", 304, Rarity.UNCOMMON, mage.cards.p.PuppetStrings.class)); - cards.add(new SetCardInfo("Quickening Licid", 36, Rarity.UNCOMMON, mage.cards.q.QuickeningLicid.class)); - cards.add(new SetCardInfo("Rain of Tears", 149, Rarity.UNCOMMON, mage.cards.r.RainOfTears.class)); - cards.add(new SetCardInfo("Rampant Growth", 245, Rarity.COMMON, mage.cards.r.RampantGrowth.class)); - cards.add(new SetCardInfo("Ranger en-Vec", 268, Rarity.UNCOMMON, mage.cards.r.RangerEnVec.class)); - cards.add(new SetCardInfo("Rathi Dragon", 196, Rarity.RARE, mage.cards.r.RathiDragon.class)); - cards.add(new SetCardInfo("Rats of Rath", 150, Rarity.COMMON, mage.cards.r.RatsOfRath.class)); - cards.add(new SetCardInfo("Reality Anchor", 246, Rarity.COMMON, mage.cards.r.RealityAnchor.class)); - cards.add(new SetCardInfo("Reanimate", 151, Rarity.UNCOMMON, mage.cards.r.Reanimate.class)); - cards.add(new SetCardInfo("Reap", 247, Rarity.UNCOMMON, mage.cards.r.Reap.class)); - cards.add(new SetCardInfo("Reckless Spite", 152, Rarity.UNCOMMON, mage.cards.r.RecklessSpite.class)); - cards.add(new SetCardInfo("Recycle", 248, Rarity.RARE, mage.cards.r.Recycle.class)); - cards.add(new SetCardInfo("Reflecting Pool", 322, Rarity.RARE, mage.cards.r.ReflectingPool.class)); - cards.add(new SetCardInfo("Renegade Warlord", 197, Rarity.UNCOMMON, mage.cards.r.RenegadeWarlord.class)); - cards.add(new SetCardInfo("Repentance", 37, Rarity.UNCOMMON, mage.cards.r.Repentance.class)); - cards.add(new SetCardInfo("Respite", 249, Rarity.COMMON, mage.cards.r.Respite.class)); - cards.add(new SetCardInfo("Rolling Thunder", 198, Rarity.COMMON, mage.cards.r.RollingThunder.class)); - cards.add(new SetCardInfo("Root Maze", 250, Rarity.RARE, mage.cards.r.RootMaze.class)); - cards.add(new SetCardInfo("Rootbreaker Wurm", 251, Rarity.COMMON, mage.cards.r.RootbreakerWurm.class)); - cards.add(new SetCardInfo("Rootwalla", 252, Rarity.COMMON, mage.cards.r.Rootwalla.class)); - cards.add(new SetCardInfo("Rootwater Depths", 323, Rarity.UNCOMMON, mage.cards.r.RootwaterDepths.class)); - cards.add(new SetCardInfo("Rootwater Diver", 81, Rarity.UNCOMMON, mage.cards.r.RootwaterDiver.class)); - cards.add(new SetCardInfo("Rootwater Hunter", 82, Rarity.COMMON, mage.cards.r.RootwaterHunter.class)); - cards.add(new SetCardInfo("Rootwater Matriarch", 83, Rarity.RARE, mage.cards.r.RootwaterMatriarch.class)); - cards.add(new SetCardInfo("Rootwater Shaman", 84, Rarity.RARE, mage.cards.r.RootwaterShaman.class)); - cards.add(new SetCardInfo("Ruby Medallion", 305, Rarity.RARE, mage.cards.r.RubyMedallion.class)); - cards.add(new SetCardInfo("Sacred Guide", 38, Rarity.RARE, mage.cards.s.SacredGuide.class)); - cards.add(new SetCardInfo("Sadistic Glee", 153, Rarity.COMMON, mage.cards.s.SadisticGlee.class)); - cards.add(new SetCardInfo("Safeguard", 39, Rarity.RARE, mage.cards.s.Safeguard.class)); - cards.add(new SetCardInfo("Salt Flats", 324, Rarity.RARE, mage.cards.s.SaltFlats.class)); - cards.add(new SetCardInfo("Sandstone Warrior", 199, Rarity.COMMON, mage.cards.s.SandstoneWarrior.class)); - cards.add(new SetCardInfo("Sapphire Medallion", 306, Rarity.RARE, mage.cards.s.SapphireMedallion.class)); - cards.add(new SetCardInfo("Sarcomancy", 154, Rarity.RARE, mage.cards.s.Sarcomancy.class)); - cards.add(new SetCardInfo("Scabland", 325, Rarity.RARE, mage.cards.s.Scabland.class)); - cards.add(new SetCardInfo("Scalding Tongs", 307, Rarity.RARE, mage.cards.s.ScaldingTongs.class)); - cards.add(new SetCardInfo("Scorched Earth", 200, Rarity.RARE, mage.cards.s.ScorchedEarth.class)); - cards.add(new SetCardInfo("Scragnoth", 253, Rarity.UNCOMMON, mage.cards.s.Scragnoth.class)); - cards.add(new SetCardInfo("Screeching Harpy", 155, Rarity.UNCOMMON, mage.cards.s.ScreechingHarpy.class)); - cards.add(new SetCardInfo("Scroll Rack", 308, Rarity.RARE, mage.cards.s.ScrollRack.class)); - cards.add(new SetCardInfo("Sea Monster", 85, Rarity.COMMON, mage.cards.s.SeaMonster.class)); - cards.add(new SetCardInfo("Searing Touch", 201, Rarity.UNCOMMON, mage.cards.s.SearingTouch.class)); - cards.add(new SetCardInfo("Seeker of Skybreak", 254, Rarity.COMMON, mage.cards.s.SeekerOfSkybreak.class)); - cards.add(new SetCardInfo("Segmented Wurm", 269, Rarity.UNCOMMON, mage.cards.s.SegmentedWurm.class)); - cards.add(new SetCardInfo("Selenia, Dark Angel", 270, Rarity.RARE, mage.cards.s.SeleniaDarkAngel.class)); - cards.add(new SetCardInfo("Serene Offering", 40, Rarity.UNCOMMON, mage.cards.s.SereneOffering.class)); - cards.add(new SetCardInfo("Servant of Volrath", 156, Rarity.COMMON, mage.cards.s.ServantOfVolrath.class)); - cards.add(new SetCardInfo("Shadow Rift", 86, Rarity.COMMON, mage.cards.s.ShadowRift.class)); - cards.add(new SetCardInfo("Shadowstorm", 202, Rarity.UNCOMMON, mage.cards.s.Shadowstorm.class)); - cards.add(new SetCardInfo("Shatter", 203, Rarity.COMMON, mage.cards.s.Shatter.class)); - cards.add(new SetCardInfo("Shimmering Wings", 87, Rarity.COMMON, mage.cards.s.ShimmeringWings.class)); - cards.add(new SetCardInfo("Shocker", 204, Rarity.RARE, mage.cards.s.Shocker.class)); - cards.add(new SetCardInfo("Sky Spirit", 271, Rarity.UNCOMMON, mage.cards.s.SkySpirit.class)); - cards.add(new SetCardInfo("Skyshroud Condor", 88, Rarity.UNCOMMON, mage.cards.s.SkyshroudCondor.class)); - cards.add(new SetCardInfo("Skyshroud Elf", 255, Rarity.COMMON, mage.cards.s.SkyshroudElf.class)); - cards.add(new SetCardInfo("Skyshroud Forest", 326, Rarity.RARE, mage.cards.s.SkyshroudForest.class)); - cards.add(new SetCardInfo("Skyshroud Ranger", 256, Rarity.COMMON, mage.cards.s.SkyshroudRanger.class)); - cards.add(new SetCardInfo("Skyshroud Troll", 257, Rarity.COMMON, mage.cards.s.SkyshroudTroll.class)); - cards.add(new SetCardInfo("Skyshroud Vampire", 157, Rarity.UNCOMMON, mage.cards.s.SkyshroudVampire.class)); - cards.add(new SetCardInfo("Soltari Crusader", 41, Rarity.UNCOMMON, mage.cards.s.SoltariCrusader.class)); - cards.add(new SetCardInfo("Soltari Emissary", 42, Rarity.RARE, mage.cards.s.SoltariEmissary.class)); - cards.add(new SetCardInfo("Soltari Foot Soldier", 43, Rarity.COMMON, mage.cards.s.SoltariFootSoldier.class)); - cards.add(new SetCardInfo("Soltari Guerrillas", 272, Rarity.RARE, mage.cards.s.SoltariGuerrillas.class)); - cards.add(new SetCardInfo("Soltari Lancer", 44, Rarity.COMMON, mage.cards.s.SoltariLancer.class)); - cards.add(new SetCardInfo("Soltari Monk", 45, Rarity.UNCOMMON, mage.cards.s.SoltariMonk.class)); - cards.add(new SetCardInfo("Soltari Priest", 46, Rarity.UNCOMMON, mage.cards.s.SoltariPriest.class)); - cards.add(new SetCardInfo("Soltari Trooper", 47, Rarity.COMMON, mage.cards.s.SoltariTrooper.class)); - cards.add(new SetCardInfo("Souldrinker", 158, Rarity.UNCOMMON, mage.cards.s.Souldrinker.class)); - cards.add(new SetCardInfo("Spell Blast", 89, Rarity.COMMON, mage.cards.s.SpellBlast.class)); - cards.add(new SetCardInfo("Spike Drone", 258, Rarity.COMMON, mage.cards.s.SpikeDrone.class)); - cards.add(new SetCardInfo("Spinal Graft", 159, Rarity.COMMON, mage.cards.s.SpinalGraft.class)); - cards.add(new SetCardInfo("Spirit Mirror", 48, Rarity.RARE, mage.cards.s.SpiritMirror.class)); - cards.add(new SetCardInfo("Spontaneous Combustion", 273, Rarity.UNCOMMON, mage.cards.s.SpontaneousCombustion.class)); - cards.add(new SetCardInfo("Squee's Toy", 309, Rarity.COMMON, mage.cards.s.SqueesToy.class)); - cards.add(new SetCardInfo("Stalking Stones", 327, Rarity.UNCOMMON, mage.cards.s.StalkingStones.class)); - cards.add(new SetCardInfo("Starke of Rath", 205, Rarity.RARE, mage.cards.s.StarkeOfRath.class)); - cards.add(new SetCardInfo("Static Orb", 310, Rarity.RARE, mage.cards.s.StaticOrb.class)); - cards.add(new SetCardInfo("Staunch Defenders", 49, Rarity.UNCOMMON, mage.cards.s.StaunchDefenders.class)); - cards.add(new SetCardInfo("Steal Enchantment", 90, Rarity.UNCOMMON, mage.cards.s.StealEnchantment.class)); - cards.add(new SetCardInfo("Stinging Licid", 91, Rarity.UNCOMMON, mage.cards.s.StingingLicid.class)); - cards.add(new SetCardInfo("Stone Rain", 206, Rarity.COMMON, mage.cards.s.StoneRain.class)); - cards.add(new SetCardInfo("Storm Front", 259, Rarity.UNCOMMON, mage.cards.s.StormFront.class)); - cards.add(new SetCardInfo("Stun", 207, Rarity.COMMON, mage.cards.s.Stun.class)); - cards.add(new SetCardInfo("Sudden Impact", 208, Rarity.UNCOMMON, mage.cards.s.SuddenImpact.class)); - cards.add(new SetCardInfo("Swamp", 339, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Swamp", 340, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Swamp", 341, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Swamp", 342, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Tahngarth's Rage", 209, Rarity.UNCOMMON, mage.cards.t.TahngarthsRage.class)); - cards.add(new SetCardInfo("Talon Sliver", 50, Rarity.COMMON, mage.cards.t.TalonSliver.class)); - cards.add(new SetCardInfo("Telethopter", 311, Rarity.UNCOMMON, mage.cards.t.Telethopter.class)); - cards.add(new SetCardInfo("Thalakos Dreamsower", 92, Rarity.UNCOMMON, mage.cards.t.ThalakosDreamsower.class)); - cards.add(new SetCardInfo("Thalakos Lowlands", 328, Rarity.UNCOMMON, mage.cards.t.ThalakosLowlands.class)); - cards.add(new SetCardInfo("Thalakos Mistfolk", 93, Rarity.COMMON, mage.cards.t.ThalakosMistfolk.class)); - cards.add(new SetCardInfo("Thalakos Seer", 94, Rarity.COMMON, mage.cards.t.ThalakosSeer.class)); - cards.add(new SetCardInfo("Thalakos Sentry", 95, Rarity.COMMON, mage.cards.t.ThalakosSentry.class)); - cards.add(new SetCardInfo("Thumbscrews", 312, Rarity.RARE, mage.cards.t.Thumbscrews.class)); - cards.add(new SetCardInfo("Time Ebb", 96, Rarity.COMMON, mage.cards.t.TimeEbb.class)); - cards.add(new SetCardInfo("Time Warp", 97, Rarity.RARE, mage.cards.t.TimeWarp.class)); - cards.add(new SetCardInfo("Tooth and Claw", 210, Rarity.RARE, mage.cards.t.ToothAndClaw.class)); - cards.add(new SetCardInfo("Torture Chamber", 313, Rarity.RARE, mage.cards.t.TortureChamber.class)); - cards.add(new SetCardInfo("Tradewind Rider", 98, Rarity.RARE, mage.cards.t.TradewindRider.class)); - cards.add(new SetCardInfo("Trained Armodon", 260, Rarity.COMMON, mage.cards.t.TrainedArmodon.class)); - cards.add(new SetCardInfo("Tranquility", 261, Rarity.COMMON, mage.cards.t.Tranquility.class)); - cards.add(new SetCardInfo("Trumpeting Armodon", 262, Rarity.UNCOMMON, mage.cards.t.TrumpetingArmodon.class)); - cards.add(new SetCardInfo("Twitch", 99, Rarity.COMMON, mage.cards.t.Twitch.class)); - cards.add(new SetCardInfo("Unstable Shapeshifter", 100, Rarity.RARE, mage.cards.u.UnstableShapeshifter.class)); - cards.add(new SetCardInfo("Vec Townships", 329, Rarity.UNCOMMON, mage.cards.v.VecTownships.class)); - cards.add(new SetCardInfo("Verdant Force", 263, Rarity.RARE, mage.cards.v.VerdantForce.class)); - cards.add(new SetCardInfo("Verdigris", 264, Rarity.UNCOMMON, mage.cards.v.Verdigris.class)); - cards.add(new SetCardInfo("Vhati il-Dal", 274, Rarity.RARE, mage.cards.v.VhatiIlDal.class)); - cards.add(new SetCardInfo("Volrath's Curse", 101, Rarity.COMMON, mage.cards.v.VolrathsCurse.class)); - cards.add(new SetCardInfo("Wall of Diffusion", 211, Rarity.COMMON, mage.cards.w.WallOfDiffusion.class)); - cards.add(new SetCardInfo("Warmth", 51, Rarity.UNCOMMON, mage.cards.w.Warmth.class)); - cards.add(new SetCardInfo("Wasteland", 330, Rarity.UNCOMMON, mage.cards.w.Wasteland.class)); - cards.add(new SetCardInfo("Watchdog", 314, Rarity.UNCOMMON, mage.cards.w.Watchdog.class)); - cards.add(new SetCardInfo("Whispers of the Muse", 103, Rarity.UNCOMMON, mage.cards.w.WhispersOfTheMuse.class)); - cards.add(new SetCardInfo("Wild Wurm", 212, Rarity.UNCOMMON, mage.cards.w.WildWurm.class)); - cards.add(new SetCardInfo("Wind Dancer", 104, Rarity.UNCOMMON, mage.cards.w.WindDancer.class)); - cards.add(new SetCardInfo("Wind Drake", 105, Rarity.COMMON, mage.cards.w.WindDrake.class)); - cards.add(new SetCardInfo("Winds of Rath", 52, Rarity.RARE, mage.cards.w.WindsOfRath.class)); - cards.add(new SetCardInfo("Winged Sliver", 106, Rarity.COMMON, mage.cards.w.WingedSliver.class)); - cards.add(new SetCardInfo("Winter's Grasp", 265, Rarity.UNCOMMON, mage.cards.w.WintersGrasp.class)); - cards.add(new SetCardInfo("Wood Sage", 275, Rarity.RARE, mage.cards.w.WoodSage.class)); - cards.add(new SetCardInfo("Worthy Cause", 53, Rarity.UNCOMMON, mage.cards.w.WorthyCause.class)); - } -} +package mage.sets; + +import mage.cards.ExpansionSet; +import mage.constants.Rarity; +import mage.constants.SetType; + +public final class Tempest extends ExpansionSet { + + private static final Tempest instance = new Tempest(); + + public static Tempest getInstance() { + return instance; + } + + private Tempest() { + super("Tempest", "TMP", ExpansionSet.buildDate(1997, 10, 1), SetType.EXPANSION); + this.blockName = "Tempest"; + this.hasBoosters = true; + this.numBoosterLands = 0; + this.numBoosterCommon = 11; + this.numBoosterUncommon = 3; + this.numBoosterRare = 1; + this.ratioBoosterMythic = 0; + cards.add(new SetCardInfo("Abandon Hope", 107, Rarity.UNCOMMON, mage.cards.a.AbandonHope.class)); + cards.add(new SetCardInfo("Advance Scout", 1, Rarity.COMMON, mage.cards.a.AdvanceScout.class)); + cards.add(new SetCardInfo("Aftershock", 160, Rarity.COMMON, mage.cards.a.Aftershock.class)); + cards.add(new SetCardInfo("Altar of Dementia", 276, Rarity.RARE, mage.cards.a.AltarOfDementia.class)); + cards.add(new SetCardInfo("Aluren", 213, Rarity.RARE, mage.cards.a.Aluren.class)); + cards.add(new SetCardInfo("Ancient Runes", 161, Rarity.UNCOMMON, mage.cards.a.AncientRunes.class)); + cards.add(new SetCardInfo("Ancient Tomb", 315, Rarity.UNCOMMON, mage.cards.a.AncientTomb.class)); + cards.add(new SetCardInfo("Angelic Protector", 2, Rarity.UNCOMMON, mage.cards.a.AngelicProtector.class)); + cards.add(new SetCardInfo("Anoint", 3, Rarity.COMMON, mage.cards.a.Anoint.class)); + cards.add(new SetCardInfo("Apes of Rath", 214, Rarity.UNCOMMON, mage.cards.a.ApesOfRath.class)); + cards.add(new SetCardInfo("Apocalypse", 162, Rarity.RARE, mage.cards.a.Apocalypse.class)); + cards.add(new SetCardInfo("Armor Sliver", 4, Rarity.UNCOMMON, mage.cards.a.ArmorSliver.class)); + cards.add(new SetCardInfo("Armored Pegasus", 5, Rarity.COMMON, mage.cards.a.ArmoredPegasus.class)); + cards.add(new SetCardInfo("Auratog", 6, Rarity.RARE, mage.cards.a.Auratog.class)); + cards.add(new SetCardInfo("Avenging Angel", 7, Rarity.RARE, mage.cards.a.AvengingAngel.class)); + cards.add(new SetCardInfo("Barbed Sliver", 163, Rarity.UNCOMMON, mage.cards.b.BarbedSliver.class)); + cards.add(new SetCardInfo("Bayou Dragonfly", 215, Rarity.COMMON, mage.cards.b.BayouDragonfly.class)); + cards.add(new SetCardInfo("Bellowing Fiend", 108, Rarity.RARE, mage.cards.b.BellowingFiend.class)); + cards.add(new SetCardInfo("Benthic Behemoth", 54, Rarity.RARE, mage.cards.b.BenthicBehemoth.class)); + cards.add(new SetCardInfo("Blood Frenzy", 164, Rarity.COMMON, mage.cards.b.BloodFrenzy.class)); + cards.add(new SetCardInfo("Blood Pet", 109, Rarity.COMMON, mage.cards.b.BloodPet.class)); + cards.add(new SetCardInfo("Boil", 165, Rarity.UNCOMMON, mage.cards.b.Boil.class)); + cards.add(new SetCardInfo("Booby Trap", 277, Rarity.RARE, mage.cards.b.BoobyTrap.class)); + cards.add(new SetCardInfo("Bottle Gnomes", 278, Rarity.UNCOMMON, mage.cards.b.BottleGnomes.class)); + cards.add(new SetCardInfo("Bounty Hunter", 110, Rarity.RARE, mage.cards.b.BountyHunter.class)); + cards.add(new SetCardInfo("Broken Fall", 216, Rarity.COMMON, mage.cards.b.BrokenFall.class)); + cards.add(new SetCardInfo("Caldera Lake", 316, Rarity.RARE, mage.cards.c.CalderaLake.class)); + cards.add(new SetCardInfo("Canopy Spider", 217, Rarity.COMMON, mage.cards.c.CanopySpider.class)); + cards.add(new SetCardInfo("Canyon Drake", 166, Rarity.RARE, mage.cards.c.CanyonDrake.class)); + cards.add(new SetCardInfo("Canyon Wildcat", 167, Rarity.COMMON, mage.cards.c.CanyonWildcat.class)); + cards.add(new SetCardInfo("Capsize", 55, Rarity.COMMON, mage.cards.c.Capsize.class)); + cards.add(new SetCardInfo("Carrionette", 111, Rarity.RARE, mage.cards.c.Carrionette.class)); + cards.add(new SetCardInfo("Chaotic Goo", 168, Rarity.RARE, mage.cards.c.ChaoticGoo.class)); + cards.add(new SetCardInfo("Charging Rhino", 218, Rarity.UNCOMMON, mage.cards.c.ChargingRhino.class)); + cards.add(new SetCardInfo("Chill", 56, Rarity.UNCOMMON, mage.cards.c.Chill.class)); + cards.add(new SetCardInfo("Choke", 219, Rarity.UNCOMMON, mage.cards.c.Choke.class)); + cards.add(new SetCardInfo("Cinder Marsh", 317, Rarity.UNCOMMON, mage.cards.c.CinderMarsh.class)); + cards.add(new SetCardInfo("Circle of Protection: Black", 8, Rarity.COMMON, mage.cards.c.CircleOfProtectionBlack.class)); + cards.add(new SetCardInfo("Circle of Protection: Blue", 9, Rarity.COMMON, mage.cards.c.CircleOfProtectionBlue.class)); + cards.add(new SetCardInfo("Circle of Protection: Green", 10, Rarity.COMMON, mage.cards.c.CircleOfProtectionGreen.class)); + cards.add(new SetCardInfo("Circle of Protection: Red", 11, Rarity.COMMON, mage.cards.c.CircleOfProtectionRed.class)); + cards.add(new SetCardInfo("Circle of Protection: Shadow", 12, Rarity.COMMON, mage.cards.c.CircleOfProtectionShadow.class)); + cards.add(new SetCardInfo("Circle of Protection: White", 13, Rarity.COMMON, mage.cards.c.CircleOfProtectionWhite.class)); + cards.add(new SetCardInfo("Clergy en-Vec", 14, Rarity.COMMON, mage.cards.c.ClergyEnVec.class)); + cards.add(new SetCardInfo("Clot Sliver", 112, Rarity.COMMON, mage.cards.c.ClotSliver.class)); + cards.add(new SetCardInfo("Cloudchaser Eagle", 15, Rarity.COMMON, mage.cards.c.CloudchaserEagle.class)); + cards.add(new SetCardInfo("Coercion", 113, Rarity.COMMON, mage.cards.c.Coercion.class)); + cards.add(new SetCardInfo("Coffin Queen", 114, Rarity.RARE, mage.cards.c.CoffinQueen.class)); + cards.add(new SetCardInfo("Coiled Tinviper", 279, Rarity.COMMON, mage.cards.c.CoiledTinviper.class)); + cards.add(new SetCardInfo("Cold Storage", 280, Rarity.RARE, mage.cards.c.ColdStorage.class)); + cards.add(new SetCardInfo("Commander Greven il-Vec", 115, Rarity.RARE, mage.cards.c.CommanderGrevenIlVec.class)); + cards.add(new SetCardInfo("Corpse Dance", 116, Rarity.RARE, mage.cards.c.CorpseDance.class)); + cards.add(new SetCardInfo("Counterspell", 57, Rarity.COMMON, mage.cards.c.Counterspell.class)); + cards.add(new SetCardInfo("Crazed Armodon", 220, Rarity.RARE, mage.cards.c.CrazedArmodon.class)); + cards.add(new SetCardInfo("Crown of Flames", 169, Rarity.COMMON, mage.cards.c.CrownOfFlames.class)); + cards.add(new SetCardInfo("Cursed Scroll", 281, Rarity.RARE, mage.cards.c.CursedScroll.class)); + cards.add(new SetCardInfo("Dark Banishing", 117, Rarity.COMMON, mage.cards.d.DarkBanishing.class)); + cards.add(new SetCardInfo("Dark Ritual", 118, Rarity.COMMON, mage.cards.d.DarkRitual.class)); + cards.add(new SetCardInfo("Darkling Stalker", 119, Rarity.COMMON, mage.cards.d.DarklingStalker.class)); + cards.add(new SetCardInfo("Dauthi Embrace", 120, Rarity.UNCOMMON, mage.cards.d.DauthiEmbrace.class)); + cards.add(new SetCardInfo("Dauthi Ghoul", 121, Rarity.UNCOMMON, mage.cards.d.DauthiGhoul.class)); + cards.add(new SetCardInfo("Dauthi Horror", 122, Rarity.COMMON, mage.cards.d.DauthiHorror.class)); + cards.add(new SetCardInfo("Dauthi Marauder", 123, Rarity.COMMON, mage.cards.d.DauthiMarauder.class)); + cards.add(new SetCardInfo("Dauthi Mercenary", 124, Rarity.UNCOMMON, mage.cards.d.DauthiMercenary.class)); + cards.add(new SetCardInfo("Dauthi Mindripper", 125, Rarity.UNCOMMON, mage.cards.d.DauthiMindripper.class)); + cards.add(new SetCardInfo("Dauthi Slayer", 126, Rarity.COMMON, mage.cards.d.DauthiSlayer.class)); + cards.add(new SetCardInfo("Deadshot", 170, Rarity.RARE, mage.cards.d.Deadshot.class)); + cards.add(new SetCardInfo("Death Pits of Rath", 127, Rarity.RARE, mage.cards.d.DeathPitsOfRath.class)); + cards.add(new SetCardInfo("Diabolic Edict", 128, Rarity.COMMON, mage.cards.d.DiabolicEdict.class)); + cards.add(new SetCardInfo("Dirtcowl Wurm", 221, Rarity.RARE, mage.cards.d.DirtcowlWurm.class)); + cards.add(new SetCardInfo("Disenchant", 16, Rarity.COMMON, mage.cards.d.Disenchant.class)); + cards.add(new SetCardInfo("Dismiss", 58, Rarity.UNCOMMON, mage.cards.d.Dismiss.class)); + cards.add(new SetCardInfo("Disturbed Burial", 129, Rarity.COMMON, mage.cards.d.DisturbedBurial.class)); + cards.add(new SetCardInfo("Dracoplasm", 266, Rarity.RARE, mage.cards.d.Dracoplasm.class)); + cards.add(new SetCardInfo("Dread of Night", 130, Rarity.UNCOMMON, mage.cards.d.DreadOfNight.class)); + cards.add(new SetCardInfo("Dream Cache", 59, Rarity.COMMON, mage.cards.d.DreamCache.class)); + cards.add(new SetCardInfo("Dregs of Sorrow", 131, Rarity.RARE, mage.cards.d.DregsOfSorrow.class)); + cards.add(new SetCardInfo("Duplicity", 60, Rarity.RARE, mage.cards.d.Duplicity.class)); + cards.add(new SetCardInfo("Earthcraft", 222, Rarity.RARE, mage.cards.e.Earthcraft.class)); + cards.add(new SetCardInfo("Echo Chamber", 282, Rarity.RARE, mage.cards.e.EchoChamber.class)); + cards.add(new SetCardInfo("Eladamri's Vineyard", 223, Rarity.RARE, mage.cards.e.EladamrisVineyard.class)); + cards.add(new SetCardInfo("Eladamri, Lord of Leaves", 224, Rarity.RARE, mage.cards.e.EladamriLordOfLeaves.class)); + cards.add(new SetCardInfo("Elite Javelineer", 17, Rarity.COMMON, mage.cards.e.EliteJavelineer.class)); + cards.add(new SetCardInfo("Elven Warhounds", 225, Rarity.RARE, mage.cards.e.ElvenWarhounds.class)); + cards.add(new SetCardInfo("Elvish Fury", 226, Rarity.COMMON, mage.cards.e.ElvishFury.class)); + cards.add(new SetCardInfo("Emerald Medallion", 283, Rarity.RARE, mage.cards.e.EmeraldMedallion.class)); + cards.add(new SetCardInfo("Emmessi Tome", 284, Rarity.RARE, mage.cards.e.EmmessiTome.class)); + cards.add(new SetCardInfo("Endless Scream", 132, Rarity.COMMON, mage.cards.e.EndlessScream.class)); + cards.add(new SetCardInfo("Energizer", 285, Rarity.RARE, mage.cards.e.Energizer.class)); + cards.add(new SetCardInfo("Enfeeblement", 133, Rarity.COMMON, mage.cards.e.Enfeeblement.class)); + cards.add(new SetCardInfo("Enraging Licid", 171, Rarity.UNCOMMON, mage.cards.e.EnragingLicid.class)); + cards.add(new SetCardInfo("Essence Bottle", 286, Rarity.UNCOMMON, mage.cards.e.EssenceBottle.class)); + cards.add(new SetCardInfo("Evincar's Justice", 134, Rarity.COMMON, mage.cards.e.EvincarsJustice.class)); + cards.add(new SetCardInfo("Excavator", 287, Rarity.UNCOMMON, mage.cards.e.Excavator.class)); + cards.add(new SetCardInfo("Extinction", 135, Rarity.RARE, mage.cards.e.Extinction.class)); + cards.add(new SetCardInfo("Fevered Convulsions", 136, Rarity.RARE, mage.cards.f.FeveredConvulsions.class)); + cards.add(new SetCardInfo("Field of Souls", 18, Rarity.RARE, mage.cards.f.FieldOfSouls.class)); + cards.add(new SetCardInfo("Fighting Drake", 63, Rarity.UNCOMMON, mage.cards.f.FightingDrake.class)); + cards.add(new SetCardInfo("Firefly", 172, Rarity.UNCOMMON, mage.cards.f.Firefly.class)); + cards.add(new SetCardInfo("Fireslinger", 173, Rarity.COMMON, mage.cards.f.Fireslinger.class)); + cards.add(new SetCardInfo("Flailing Drake", 227, Rarity.UNCOMMON, mage.cards.f.FlailingDrake.class)); + cards.add(new SetCardInfo("Flickering Ward", 19, Rarity.UNCOMMON, mage.cards.f.FlickeringWard.class)); + cards.add(new SetCardInfo("Flowstone Giant", 174, Rarity.COMMON, mage.cards.f.FlowstoneGiant.class)); + cards.add(new SetCardInfo("Flowstone Salamander", 175, Rarity.UNCOMMON, mage.cards.f.FlowstoneSalamander.class)); + cards.add(new SetCardInfo("Flowstone Sculpture", 288, Rarity.RARE, mage.cards.f.FlowstoneSculpture.class)); + cards.add(new SetCardInfo("Flowstone Wyvern", 176, Rarity.RARE, mage.cards.f.FlowstoneWyvern.class)); + cards.add(new SetCardInfo("Fool's Tome", 289, Rarity.RARE, mage.cards.f.FoolsTome.class)); + cards.add(new SetCardInfo("Forest", 347, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Forest", 348, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Forest", 349, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Forest", 350, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Frog Tongue", 228, Rarity.COMMON, mage.cards.f.FrogTongue.class)); + cards.add(new SetCardInfo("Fugitive Druid", 229, Rarity.RARE, mage.cards.f.FugitiveDruid.class)); + cards.add(new SetCardInfo("Furnace of Rath", 177, Rarity.RARE, mage.cards.f.FurnaceOfRath.class)); + cards.add(new SetCardInfo("Fylamarid", 64, Rarity.UNCOMMON, mage.cards.f.Fylamarid.class)); + cards.add(new SetCardInfo("Gallantry", 20, Rarity.UNCOMMON, mage.cards.g.Gallantry.class)); + cards.add(new SetCardInfo("Gaseous Form", 65, Rarity.COMMON, mage.cards.g.GaseousForm.class)); + cards.add(new SetCardInfo("Gerrard's Battle Cry", 21, Rarity.RARE, mage.cards.g.GerrardsBattleCry.class)); + cards.add(new SetCardInfo("Ghost Town", 318, Rarity.UNCOMMON, mage.cards.g.GhostTown.class)); + cards.add(new SetCardInfo("Giant Crab", 66, Rarity.COMMON, mage.cards.g.GiantCrab.class)); + cards.add(new SetCardInfo("Giant Strength", 178, Rarity.COMMON, mage.cards.g.GiantStrength.class)); + cards.add(new SetCardInfo("Goblin Bombardment", 179, Rarity.UNCOMMON, mage.cards.g.GoblinBombardment.class)); + cards.add(new SetCardInfo("Gravedigger", 137, Rarity.COMMON, mage.cards.g.Gravedigger.class)); + cards.add(new SetCardInfo("Grindstone", 290, Rarity.RARE, mage.cards.g.Grindstone.class)); + cards.add(new SetCardInfo("Hand to Hand", 180, Rarity.RARE, mage.cards.h.HandToHand.class)); + cards.add(new SetCardInfo("Hanna's Custody", 22, Rarity.RARE, mage.cards.h.HannasCustody.class)); + cards.add(new SetCardInfo("Harrow", 230, Rarity.UNCOMMON, mage.cards.h.Harrow.class)); + cards.add(new SetCardInfo("Havoc", 181, Rarity.UNCOMMON, mage.cards.h.Havoc.class)); + cards.add(new SetCardInfo("Heart Sliver", 182, Rarity.COMMON, mage.cards.h.HeartSliver.class)); + cards.add(new SetCardInfo("Heartwood Dryad", 231, Rarity.COMMON, mage.cards.h.HeartwoodDryad.class)); + cards.add(new SetCardInfo("Heartwood Giant", 232, Rarity.RARE, mage.cards.h.HeartwoodGiant.class)); + cards.add(new SetCardInfo("Heartwood Treefolk", 233, Rarity.UNCOMMON, mage.cards.h.HeartwoodTreefolk.class)); + cards.add(new SetCardInfo("Helm of Possession", 291, Rarity.RARE, mage.cards.h.HelmOfPossession.class)); + cards.add(new SetCardInfo("Hero's Resolve", 23, Rarity.COMMON, mage.cards.h.HerosResolve.class)); + cards.add(new SetCardInfo("Horned Sliver", 234, Rarity.UNCOMMON, mage.cards.h.HornedSliver.class)); + cards.add(new SetCardInfo("Horned Turtle", 67, Rarity.COMMON, mage.cards.h.HornedTurtle.class)); + cards.add(new SetCardInfo("Humility", 24, Rarity.RARE, mage.cards.h.Humility.class)); + cards.add(new SetCardInfo("Imps' Taunt", 138, Rarity.UNCOMMON, mage.cards.i.ImpsTaunt.class)); + cards.add(new SetCardInfo("Insight", 68, Rarity.UNCOMMON, mage.cards.i.Insight.class)); + cards.add(new SetCardInfo("Interdict", 69, Rarity.UNCOMMON, mage.cards.i.Interdict.class)); + cards.add(new SetCardInfo("Intuition", 70, Rarity.RARE, mage.cards.i.Intuition.class)); + cards.add(new SetCardInfo("Invulnerability", 25, Rarity.UNCOMMON, mage.cards.i.Invulnerability.class)); + cards.add(new SetCardInfo("Island", 335, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Island", 336, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Island", 337, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Island", 338, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Jackal Pup", 183, Rarity.UNCOMMON, mage.cards.j.JackalPup.class)); + cards.add(new SetCardInfo("Jet Medallion", 292, Rarity.RARE, mage.cards.j.JetMedallion.class)); + cards.add(new SetCardInfo("Jinxed Idol", 293, Rarity.RARE, mage.cards.j.JinxedIdol.class)); + cards.add(new SetCardInfo("Kezzerdrix", 139, Rarity.RARE, mage.cards.k.Kezzerdrix.class)); + cards.add(new SetCardInfo("Kindle", 184, Rarity.COMMON, mage.cards.k.Kindle.class)); + cards.add(new SetCardInfo("Knight of Dawn", 26, Rarity.UNCOMMON, mage.cards.k.KnightOfDawn.class)); + cards.add(new SetCardInfo("Knight of Dusk", 140, Rarity.UNCOMMON, mage.cards.k.KnightOfDusk.class)); + cards.add(new SetCardInfo("Krakilin", 235, Rarity.UNCOMMON, mage.cards.k.Krakilin.class)); + cards.add(new SetCardInfo("Leeching Licid", 141, Rarity.UNCOMMON, mage.cards.l.LeechingLicid.class)); + cards.add(new SetCardInfo("Legacy's Allure", 71, Rarity.UNCOMMON, mage.cards.l.LegacysAllure.class)); + cards.add(new SetCardInfo("Legerdemain", 72, Rarity.UNCOMMON, mage.cards.l.Legerdemain.class)); + cards.add(new SetCardInfo("Light of Day", 27, Rarity.UNCOMMON, mage.cards.l.LightOfDay.class)); + cards.add(new SetCardInfo("Lightning Blast", 185, Rarity.COMMON, mage.cards.l.LightningBlast.class)); + cards.add(new SetCardInfo("Lightning Elemental", 186, Rarity.COMMON, mage.cards.l.LightningElemental.class)); + cards.add(new SetCardInfo("Living Death", 142, Rarity.RARE, mage.cards.l.LivingDeath.class)); + cards.add(new SetCardInfo("Lobotomy", 267, Rarity.UNCOMMON, mage.cards.l.Lobotomy.class)); + cards.add(new SetCardInfo("Lotus Petal", 294, Rarity.COMMON, mage.cards.l.LotusPetal.class)); + cards.add(new SetCardInfo("Lowland Giant", 187, Rarity.COMMON, mage.cards.l.LowlandGiant.class)); + cards.add(new SetCardInfo("Maddening Imp", 143, Rarity.RARE, mage.cards.m.MaddeningImp.class)); + cards.add(new SetCardInfo("Magmasaur", 188, Rarity.RARE, mage.cards.m.Magmasaur.class)); + cards.add(new SetCardInfo("Mana Severance", 73, Rarity.RARE, mage.cards.m.ManaSeverance.class)); + cards.add(new SetCardInfo("Manakin", 296, Rarity.COMMON, mage.cards.m.Manakin.class)); + cards.add(new SetCardInfo("Manta Riders", 74, Rarity.COMMON, mage.cards.m.MantaRiders.class)); + cards.add(new SetCardInfo("Marble Titan", 28, Rarity.RARE, mage.cards.m.MarbleTitan.class)); + cards.add(new SetCardInfo("Marsh Lurker", 144, Rarity.COMMON, mage.cards.m.MarshLurker.class)); + cards.add(new SetCardInfo("Master Decoy", 29, Rarity.COMMON, mage.cards.m.MasterDecoy.class)); + cards.add(new SetCardInfo("Mawcor", 75, Rarity.RARE, mage.cards.m.Mawcor.class)); + cards.add(new SetCardInfo("Maze of Shadows", 319, Rarity.UNCOMMON, mage.cards.m.MazeOfShadows.class)); + cards.add(new SetCardInfo("Meditate", 76, Rarity.RARE, mage.cards.m.Meditate.class)); + cards.add(new SetCardInfo("Metallic Sliver", 297, Rarity.COMMON, mage.cards.m.MetallicSliver.class)); + cards.add(new SetCardInfo("Mindwhip Sliver", 145, Rarity.UNCOMMON, mage.cards.m.MindwhipSliver.class)); + cards.add(new SetCardInfo("Minion of the Wastes", 146, Rarity.RARE, mage.cards.m.MinionOfTheWastes.class)); + cards.add(new SetCardInfo("Mirri's Guile", 236, Rarity.RARE, mage.cards.m.MirrisGuile.class)); + cards.add(new SetCardInfo("Mnemonic Sliver", 77, Rarity.UNCOMMON, mage.cards.m.MnemonicSliver.class)); + cards.add(new SetCardInfo("Mogg Cannon", 298, Rarity.UNCOMMON, mage.cards.m.MoggCannon.class)); + cards.add(new SetCardInfo("Mogg Conscripts", 189, Rarity.COMMON, mage.cards.m.MoggConscripts.class)); + cards.add(new SetCardInfo("Mogg Fanatic", 190, Rarity.COMMON, mage.cards.m.MoggFanatic.class)); + cards.add(new SetCardInfo("Mogg Hollows", 320, Rarity.UNCOMMON, mage.cards.m.MoggHollows.class)); + cards.add(new SetCardInfo("Mogg Raider", 191, Rarity.COMMON, mage.cards.m.MoggRaider.class)); + cards.add(new SetCardInfo("Mogg Squad", 192, Rarity.UNCOMMON, mage.cards.m.MoggSquad.class)); + cards.add(new SetCardInfo("Mongrel Pack", 237, Rarity.RARE, mage.cards.m.MongrelPack.class)); + cards.add(new SetCardInfo("Mountain", 343, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mountain", 344, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mountain", 345, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mountain", 346, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mounted Archers", 30, Rarity.COMMON, mage.cards.m.MountedArchers.class)); + cards.add(new SetCardInfo("Muscle Sliver", 238, Rarity.COMMON, mage.cards.m.MuscleSliver.class)); + cards.add(new SetCardInfo("Natural Spring", 239, Rarity.COMMON, mage.cards.n.NaturalSpring.class)); + cards.add(new SetCardInfo("Nature's Revolt", 240, Rarity.RARE, mage.cards.n.NaturesRevolt.class)); + cards.add(new SetCardInfo("Needle Storm", 241, Rarity.UNCOMMON, mage.cards.n.NeedleStorm.class)); + cards.add(new SetCardInfo("Nurturing Licid", 242, Rarity.UNCOMMON, mage.cards.n.NurturingLicid.class)); + cards.add(new SetCardInfo("Opportunist", 194, Rarity.UNCOMMON, mage.cards.o.Opportunist.class)); + cards.add(new SetCardInfo("Oracle en-Vec", 31, Rarity.RARE, mage.cards.o.OracleEnVec.class)); + cards.add(new SetCardInfo("Orim's Prayer", 32, Rarity.UNCOMMON, mage.cards.o.OrimsPrayer.class)); + cards.add(new SetCardInfo("Orim, Samite Healer", 33, Rarity.RARE, mage.cards.o.OrimSamiteHealer.class)); + cards.add(new SetCardInfo("Overrun", 243, Rarity.UNCOMMON, mage.cards.o.Overrun.class)); + cards.add(new SetCardInfo("Pacifism", 34, Rarity.COMMON, mage.cards.p.Pacifism.class)); + cards.add(new SetCardInfo("Pallimud", 195, Rarity.RARE, mage.cards.p.Pallimud.class)); + cards.add(new SetCardInfo("Patchwork Gnomes", 299, Rarity.UNCOMMON, mage.cards.p.PatchworkGnomes.class)); + cards.add(new SetCardInfo("Pearl Medallion", 300, Rarity.RARE, mage.cards.p.PearlMedallion.class)); + cards.add(new SetCardInfo("Pegasus Refuge", 35, Rarity.RARE, mage.cards.p.PegasusRefuge.class)); + cards.add(new SetCardInfo("Perish", 147, Rarity.UNCOMMON, mage.cards.p.Perish.class)); + cards.add(new SetCardInfo("Phyrexian Grimoire", 301, Rarity.RARE, mage.cards.p.PhyrexianGrimoire.class)); + cards.add(new SetCardInfo("Phyrexian Hulk", 302, Rarity.UNCOMMON, mage.cards.p.PhyrexianHulk.class)); + cards.add(new SetCardInfo("Pincher Beetles", 244, Rarity.COMMON, mage.cards.p.PincherBeetles.class)); + cards.add(new SetCardInfo("Pine Barrens", 321, Rarity.RARE, mage.cards.p.PineBarrens.class)); + cards.add(new SetCardInfo("Pit Imp", 148, Rarity.COMMON, mage.cards.p.PitImp.class)); + cards.add(new SetCardInfo("Plains", 331, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Plains", 332, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Plains", 333, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Plains", 334, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Power Sink", 78, Rarity.COMMON, mage.cards.p.PowerSink.class)); + cards.add(new SetCardInfo("Precognition", 79, Rarity.RARE, mage.cards.p.Precognition.class)); + cards.add(new SetCardInfo("Propaganda", 80, Rarity.UNCOMMON, mage.cards.p.Propaganda.class)); + cards.add(new SetCardInfo("Puppet Strings", 304, Rarity.UNCOMMON, mage.cards.p.PuppetStrings.class)); + cards.add(new SetCardInfo("Quickening Licid", 36, Rarity.UNCOMMON, mage.cards.q.QuickeningLicid.class)); + cards.add(new SetCardInfo("Rain of Tears", 149, Rarity.UNCOMMON, mage.cards.r.RainOfTears.class)); + cards.add(new SetCardInfo("Rampant Growth", 245, Rarity.COMMON, mage.cards.r.RampantGrowth.class)); + cards.add(new SetCardInfo("Ranger en-Vec", 268, Rarity.UNCOMMON, mage.cards.r.RangerEnVec.class)); + cards.add(new SetCardInfo("Rathi Dragon", 196, Rarity.RARE, mage.cards.r.RathiDragon.class)); + cards.add(new SetCardInfo("Rats of Rath", 150, Rarity.COMMON, mage.cards.r.RatsOfRath.class)); + cards.add(new SetCardInfo("Reality Anchor", 246, Rarity.COMMON, mage.cards.r.RealityAnchor.class)); + cards.add(new SetCardInfo("Reanimate", 151, Rarity.UNCOMMON, mage.cards.r.Reanimate.class)); + cards.add(new SetCardInfo("Reap", 247, Rarity.UNCOMMON, mage.cards.r.Reap.class)); + cards.add(new SetCardInfo("Reckless Spite", 152, Rarity.UNCOMMON, mage.cards.r.RecklessSpite.class)); + cards.add(new SetCardInfo("Recycle", 248, Rarity.RARE, mage.cards.r.Recycle.class)); + cards.add(new SetCardInfo("Reflecting Pool", 322, Rarity.RARE, mage.cards.r.ReflectingPool.class)); + cards.add(new SetCardInfo("Renegade Warlord", 197, Rarity.UNCOMMON, mage.cards.r.RenegadeWarlord.class)); + cards.add(new SetCardInfo("Repentance", 37, Rarity.UNCOMMON, mage.cards.r.Repentance.class)); + cards.add(new SetCardInfo("Respite", 249, Rarity.COMMON, mage.cards.r.Respite.class)); + cards.add(new SetCardInfo("Rolling Thunder", 198, Rarity.COMMON, mage.cards.r.RollingThunder.class)); + cards.add(new SetCardInfo("Root Maze", 250, Rarity.RARE, mage.cards.r.RootMaze.class)); + cards.add(new SetCardInfo("Rootbreaker Wurm", 251, Rarity.COMMON, mage.cards.r.RootbreakerWurm.class)); + cards.add(new SetCardInfo("Rootwalla", 252, Rarity.COMMON, mage.cards.r.Rootwalla.class)); + cards.add(new SetCardInfo("Rootwater Depths", 323, Rarity.UNCOMMON, mage.cards.r.RootwaterDepths.class)); + cards.add(new SetCardInfo("Rootwater Diver", 81, Rarity.UNCOMMON, mage.cards.r.RootwaterDiver.class)); + cards.add(new SetCardInfo("Rootwater Hunter", 82, Rarity.COMMON, mage.cards.r.RootwaterHunter.class)); + cards.add(new SetCardInfo("Rootwater Matriarch", 83, Rarity.RARE, mage.cards.r.RootwaterMatriarch.class)); + cards.add(new SetCardInfo("Rootwater Shaman", 84, Rarity.RARE, mage.cards.r.RootwaterShaman.class)); + cards.add(new SetCardInfo("Ruby Medallion", 305, Rarity.RARE, mage.cards.r.RubyMedallion.class)); + cards.add(new SetCardInfo("Sacred Guide", 38, Rarity.RARE, mage.cards.s.SacredGuide.class)); + cards.add(new SetCardInfo("Sadistic Glee", 153, Rarity.COMMON, mage.cards.s.SadisticGlee.class)); + cards.add(new SetCardInfo("Safeguard", 39, Rarity.RARE, mage.cards.s.Safeguard.class)); + cards.add(new SetCardInfo("Salt Flats", 324, Rarity.RARE, mage.cards.s.SaltFlats.class)); + cards.add(new SetCardInfo("Sandstone Warrior", 199, Rarity.COMMON, mage.cards.s.SandstoneWarrior.class)); + cards.add(new SetCardInfo("Sapphire Medallion", 306, Rarity.RARE, mage.cards.s.SapphireMedallion.class)); + cards.add(new SetCardInfo("Sarcomancy", 154, Rarity.RARE, mage.cards.s.Sarcomancy.class)); + cards.add(new SetCardInfo("Scabland", 325, Rarity.RARE, mage.cards.s.Scabland.class)); + cards.add(new SetCardInfo("Scalding Tongs", 307, Rarity.RARE, mage.cards.s.ScaldingTongs.class)); + cards.add(new SetCardInfo("Scorched Earth", 200, Rarity.RARE, mage.cards.s.ScorchedEarth.class)); + cards.add(new SetCardInfo("Scragnoth", 253, Rarity.UNCOMMON, mage.cards.s.Scragnoth.class)); + cards.add(new SetCardInfo("Screeching Harpy", 155, Rarity.UNCOMMON, mage.cards.s.ScreechingHarpy.class)); + cards.add(new SetCardInfo("Scroll Rack", 308, Rarity.RARE, mage.cards.s.ScrollRack.class)); + cards.add(new SetCardInfo("Sea Monster", 85, Rarity.COMMON, mage.cards.s.SeaMonster.class)); + cards.add(new SetCardInfo("Searing Touch", 201, Rarity.UNCOMMON, mage.cards.s.SearingTouch.class)); + cards.add(new SetCardInfo("Seeker of Skybreak", 254, Rarity.COMMON, mage.cards.s.SeekerOfSkybreak.class)); + cards.add(new SetCardInfo("Segmented Wurm", 269, Rarity.UNCOMMON, mage.cards.s.SegmentedWurm.class)); + cards.add(new SetCardInfo("Selenia, Dark Angel", 270, Rarity.RARE, mage.cards.s.SeleniaDarkAngel.class)); + cards.add(new SetCardInfo("Serene Offering", 40, Rarity.UNCOMMON, mage.cards.s.SereneOffering.class)); + cards.add(new SetCardInfo("Servant of Volrath", 156, Rarity.COMMON, mage.cards.s.ServantOfVolrath.class)); + cards.add(new SetCardInfo("Shadow Rift", 86, Rarity.COMMON, mage.cards.s.ShadowRift.class)); + cards.add(new SetCardInfo("Shadowstorm", 202, Rarity.UNCOMMON, mage.cards.s.Shadowstorm.class)); + cards.add(new SetCardInfo("Shatter", 203, Rarity.COMMON, mage.cards.s.Shatter.class)); + cards.add(new SetCardInfo("Shimmering Wings", 87, Rarity.COMMON, mage.cards.s.ShimmeringWings.class)); + cards.add(new SetCardInfo("Shocker", 204, Rarity.RARE, mage.cards.s.Shocker.class)); + cards.add(new SetCardInfo("Sky Spirit", 271, Rarity.UNCOMMON, mage.cards.s.SkySpirit.class)); + cards.add(new SetCardInfo("Skyshroud Condor", 88, Rarity.UNCOMMON, mage.cards.s.SkyshroudCondor.class)); + cards.add(new SetCardInfo("Skyshroud Elf", 255, Rarity.COMMON, mage.cards.s.SkyshroudElf.class)); + cards.add(new SetCardInfo("Skyshroud Forest", 326, Rarity.RARE, mage.cards.s.SkyshroudForest.class)); + cards.add(new SetCardInfo("Skyshroud Ranger", 256, Rarity.COMMON, mage.cards.s.SkyshroudRanger.class)); + cards.add(new SetCardInfo("Skyshroud Troll", 257, Rarity.COMMON, mage.cards.s.SkyshroudTroll.class)); + cards.add(new SetCardInfo("Skyshroud Vampire", 157, Rarity.UNCOMMON, mage.cards.s.SkyshroudVampire.class)); + cards.add(new SetCardInfo("Soltari Crusader", 41, Rarity.UNCOMMON, mage.cards.s.SoltariCrusader.class)); + cards.add(new SetCardInfo("Soltari Emissary", 42, Rarity.RARE, mage.cards.s.SoltariEmissary.class)); + cards.add(new SetCardInfo("Soltari Foot Soldier", 43, Rarity.COMMON, mage.cards.s.SoltariFootSoldier.class)); + cards.add(new SetCardInfo("Soltari Guerrillas", 272, Rarity.RARE, mage.cards.s.SoltariGuerrillas.class)); + cards.add(new SetCardInfo("Soltari Lancer", 44, Rarity.COMMON, mage.cards.s.SoltariLancer.class)); + cards.add(new SetCardInfo("Soltari Monk", 45, Rarity.UNCOMMON, mage.cards.s.SoltariMonk.class)); + cards.add(new SetCardInfo("Soltari Priest", 46, Rarity.UNCOMMON, mage.cards.s.SoltariPriest.class)); + cards.add(new SetCardInfo("Soltari Trooper", 47, Rarity.COMMON, mage.cards.s.SoltariTrooper.class)); + cards.add(new SetCardInfo("Souldrinker", 158, Rarity.UNCOMMON, mage.cards.s.Souldrinker.class)); + cards.add(new SetCardInfo("Spell Blast", 89, Rarity.COMMON, mage.cards.s.SpellBlast.class)); + cards.add(new SetCardInfo("Spike Drone", 258, Rarity.COMMON, mage.cards.s.SpikeDrone.class)); + cards.add(new SetCardInfo("Spinal Graft", 159, Rarity.COMMON, mage.cards.s.SpinalGraft.class)); + cards.add(new SetCardInfo("Spirit Mirror", 48, Rarity.RARE, mage.cards.s.SpiritMirror.class)); + cards.add(new SetCardInfo("Spontaneous Combustion", 273, Rarity.UNCOMMON, mage.cards.s.SpontaneousCombustion.class)); + cards.add(new SetCardInfo("Squee's Toy", 309, Rarity.COMMON, mage.cards.s.SqueesToy.class)); + cards.add(new SetCardInfo("Stalking Stones", 327, Rarity.UNCOMMON, mage.cards.s.StalkingStones.class)); + cards.add(new SetCardInfo("Starke of Rath", 205, Rarity.RARE, mage.cards.s.StarkeOfRath.class)); + cards.add(new SetCardInfo("Static Orb", 310, Rarity.RARE, mage.cards.s.StaticOrb.class)); + cards.add(new SetCardInfo("Staunch Defenders", 49, Rarity.UNCOMMON, mage.cards.s.StaunchDefenders.class)); + cards.add(new SetCardInfo("Steal Enchantment", 90, Rarity.UNCOMMON, mage.cards.s.StealEnchantment.class)); + cards.add(new SetCardInfo("Stinging Licid", 91, Rarity.UNCOMMON, mage.cards.s.StingingLicid.class)); + cards.add(new SetCardInfo("Stone Rain", 206, Rarity.COMMON, mage.cards.s.StoneRain.class)); + cards.add(new SetCardInfo("Storm Front", 259, Rarity.UNCOMMON, mage.cards.s.StormFront.class)); + cards.add(new SetCardInfo("Stun", 207, Rarity.COMMON, mage.cards.s.Stun.class)); + cards.add(new SetCardInfo("Sudden Impact", 208, Rarity.UNCOMMON, mage.cards.s.SuddenImpact.class)); + cards.add(new SetCardInfo("Swamp", 339, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Swamp", 340, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Swamp", 341, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Swamp", 342, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Tahngarth's Rage", 209, Rarity.UNCOMMON, mage.cards.t.TahngarthsRage.class)); + cards.add(new SetCardInfo("Talon Sliver", 50, Rarity.COMMON, mage.cards.t.TalonSliver.class)); + cards.add(new SetCardInfo("Telethopter", 311, Rarity.UNCOMMON, mage.cards.t.Telethopter.class)); + cards.add(new SetCardInfo("Thalakos Dreamsower", 92, Rarity.UNCOMMON, mage.cards.t.ThalakosDreamsower.class)); + cards.add(new SetCardInfo("Thalakos Lowlands", 328, Rarity.UNCOMMON, mage.cards.t.ThalakosLowlands.class)); + cards.add(new SetCardInfo("Thalakos Mistfolk", 93, Rarity.COMMON, mage.cards.t.ThalakosMistfolk.class)); + cards.add(new SetCardInfo("Thalakos Seer", 94, Rarity.COMMON, mage.cards.t.ThalakosSeer.class)); + cards.add(new SetCardInfo("Thalakos Sentry", 95, Rarity.COMMON, mage.cards.t.ThalakosSentry.class)); + cards.add(new SetCardInfo("Thumbscrews", 312, Rarity.RARE, mage.cards.t.Thumbscrews.class)); + cards.add(new SetCardInfo("Time Ebb", 96, Rarity.COMMON, mage.cards.t.TimeEbb.class)); + cards.add(new SetCardInfo("Time Warp", 97, Rarity.RARE, mage.cards.t.TimeWarp.class)); + cards.add(new SetCardInfo("Tooth and Claw", 210, Rarity.RARE, mage.cards.t.ToothAndClaw.class)); + cards.add(new SetCardInfo("Torture Chamber", 313, Rarity.RARE, mage.cards.t.TortureChamber.class)); + cards.add(new SetCardInfo("Tradewind Rider", 98, Rarity.RARE, mage.cards.t.TradewindRider.class)); + cards.add(new SetCardInfo("Trained Armodon", 260, Rarity.COMMON, mage.cards.t.TrainedArmodon.class)); + cards.add(new SetCardInfo("Tranquility", 261, Rarity.COMMON, mage.cards.t.Tranquility.class)); + cards.add(new SetCardInfo("Trumpeting Armodon", 262, Rarity.UNCOMMON, mage.cards.t.TrumpetingArmodon.class)); + cards.add(new SetCardInfo("Twitch", 99, Rarity.COMMON, mage.cards.t.Twitch.class)); + cards.add(new SetCardInfo("Unstable Shapeshifter", 100, Rarity.RARE, mage.cards.u.UnstableShapeshifter.class)); + cards.add(new SetCardInfo("Vec Townships", 329, Rarity.UNCOMMON, mage.cards.v.VecTownships.class)); + cards.add(new SetCardInfo("Verdant Force", 263, Rarity.RARE, mage.cards.v.VerdantForce.class)); + cards.add(new SetCardInfo("Verdigris", 264, Rarity.UNCOMMON, mage.cards.v.Verdigris.class)); + cards.add(new SetCardInfo("Vhati il-Dal", 274, Rarity.RARE, mage.cards.v.VhatiIlDal.class)); + cards.add(new SetCardInfo("Volrath's Curse", 101, Rarity.COMMON, mage.cards.v.VolrathsCurse.class)); + cards.add(new SetCardInfo("Wall of Diffusion", 211, Rarity.COMMON, mage.cards.w.WallOfDiffusion.class)); + cards.add(new SetCardInfo("Warmth", 51, Rarity.UNCOMMON, mage.cards.w.Warmth.class)); + cards.add(new SetCardInfo("Wasteland", 330, Rarity.UNCOMMON, mage.cards.w.Wasteland.class)); + cards.add(new SetCardInfo("Watchdog", 314, Rarity.UNCOMMON, mage.cards.w.Watchdog.class)); + cards.add(new SetCardInfo("Whispers of the Muse", 103, Rarity.UNCOMMON, mage.cards.w.WhispersOfTheMuse.class)); + cards.add(new SetCardInfo("Wild Wurm", 212, Rarity.UNCOMMON, mage.cards.w.WildWurm.class)); + cards.add(new SetCardInfo("Wind Dancer", 104, Rarity.UNCOMMON, mage.cards.w.WindDancer.class)); + cards.add(new SetCardInfo("Wind Drake", 105, Rarity.COMMON, mage.cards.w.WindDrake.class)); + cards.add(new SetCardInfo("Winds of Rath", 52, Rarity.RARE, mage.cards.w.WindsOfRath.class)); + cards.add(new SetCardInfo("Winged Sliver", 106, Rarity.COMMON, mage.cards.w.WingedSliver.class)); + cards.add(new SetCardInfo("Winter's Grasp", 265, Rarity.UNCOMMON, mage.cards.w.WintersGrasp.class)); + cards.add(new SetCardInfo("Wood Sage", 275, Rarity.RARE, mage.cards.w.WoodSage.class)); + cards.add(new SetCardInfo("Worthy Cause", 53, Rarity.UNCOMMON, mage.cards.w.WorthyCause.class)); + } +} diff --git a/Mage.Sets/src/mage/sets/UltimateBoxTopperPromos.java b/Mage.Sets/src/mage/sets/UltimateBoxTopperPromos.java new file mode 100644 index 00000000000..26eb20d5717 --- /dev/null +++ b/Mage.Sets/src/mage/sets/UltimateBoxTopperPromos.java @@ -0,0 +1,65 @@ + +package mage.sets; + +import mage.cards.ExpansionSet; +import mage.constants.Rarity; +import mage.constants.SetType; + +/** + * @author JayDi85 + */ +public final class UltimateBoxTopperPromos extends ExpansionSet { + + private static final UltimateBoxTopperPromos instance = new UltimateBoxTopperPromos(); + + public static UltimateBoxTopperPromos getInstance() { + return instance; + } + + private UltimateBoxTopperPromos() { + super("Ultimate Box Topper Promos", "PUMA", ExpansionSet.buildDate(2018, 12, 7), SetType.PROMOTIONAL); + this.hasBasicLands = false; + this.hasBoosters = false; + + cards.add(new SetCardInfo("Ancient Tomb", "U31", Rarity.MYTHIC, mage.cards.a.AncientTomb.class)); + cards.add(new SetCardInfo("Balefire Dragon", "U14", Rarity.MYTHIC, mage.cards.b.BalefireDragon.class)); + cards.add(new SetCardInfo("Bitterblossom", "U7", Rarity.MYTHIC, mage.cards.b.Bitterblossom.class)); + cards.add(new SetCardInfo("Cavern of Souls", "U32", Rarity.MYTHIC, mage.cards.c.CavernOfSouls.class)); + cards.add(new SetCardInfo("Celestial Colonnade", "U33", Rarity.MYTHIC, mage.cards.c.CelestialColonnade.class)); + cards.add(new SetCardInfo("Creeping Tar Pit", "U34", Rarity.MYTHIC, mage.cards.c.CreepingTarPit.class)); + cards.add(new SetCardInfo("Dark Depths", "U35", Rarity.MYTHIC, mage.cards.d.DarkDepths.class)); + cards.add(new SetCardInfo("Demonic Tutor", "U8", Rarity.MYTHIC, mage.cards.d.DemonicTutor.class)); + cards.add(new SetCardInfo("Emrakul, the Aeons Torn", "U1", Rarity.MYTHIC, mage.cards.e.EmrakulTheAeonsTorn.class)); + cards.add(new SetCardInfo("Engineered Explosives", "U28", Rarity.MYTHIC, mage.cards.e.EngineeredExplosives.class)); + cards.add(new SetCardInfo("Eternal Witness", "U16", Rarity.MYTHIC, mage.cards.e.EternalWitness.class)); + cards.add(new SetCardInfo("Fulminator Mage", "U26", Rarity.MYTHIC, mage.cards.f.FulminatorMage.class)); + cards.add(new SetCardInfo("Gaddock Teeg", "U21", Rarity.MYTHIC, mage.cards.g.GaddockTeeg.class)); + cards.add(new SetCardInfo("Goryo's Vengeance", "U9", Rarity.MYTHIC, mage.cards.g.GoryosVengeance.class)); + cards.add(new SetCardInfo("Karakas", "U36", Rarity.MYTHIC, mage.cards.k.Karakas.class)); + cards.add(new SetCardInfo("Karn Liberated", "U02", Rarity.MYTHIC, mage.cards.k.KarnLiberated.class)); + cards.add(new SetCardInfo("Kitchen Finks", "U27", Rarity.MYTHIC, mage.cards.k.KitchenFinks.class)); + cards.add(new SetCardInfo("Kozilek, Butcher of Truth", "U03", Rarity.MYTHIC, mage.cards.k.KozilekButcherOfTruth.class)); + cards.add(new SetCardInfo("Lavaclaw Reaches", "U37", Rarity.MYTHIC, mage.cards.l.LavaclawReaches.class)); + cards.add(new SetCardInfo("Leovold, Emissary of Trest", "U22", Rarity.MYTHIC, mage.cards.l.LeovoldEmissaryOfTrest.class)); + cards.add(new SetCardInfo("Life from the Loam", "U17", Rarity.MYTHIC, mage.cards.l.LifeFromTheLoam.class)); + cards.add(new SetCardInfo("Liliana of the Veil", "U10", Rarity.MYTHIC, mage.cards.l.LilianaOfTheVeil.class)); + cards.add(new SetCardInfo("Lord of Extinction", "U23", Rarity.MYTHIC, mage.cards.l.LordOfExtinction.class)); + cards.add(new SetCardInfo("Maelstrom Pulse", "U24", Rarity.MYTHIC, mage.cards.m.MaelstromPulse.class)); + cards.add(new SetCardInfo("Mana Vault", "U29", Rarity.MYTHIC, mage.cards.m.ManaVault.class)); + cards.add(new SetCardInfo("Mikaeus, the Unhallowed", "U11", Rarity.MYTHIC, mage.cards.m.MikaeusTheUnhallowed.class)); + cards.add(new SetCardInfo("Noble Hierarch", "U18", Rarity.MYTHIC, mage.cards.n.NobleHierarch.class)); + cards.add(new SetCardInfo("Platinum Emperion", "U30", Rarity.MYTHIC, mage.cards.p.PlatinumEmperion.class)); + cards.add(new SetCardInfo("Raging Ravine", "U38", Rarity.MYTHIC, mage.cards.r.RagingRavine.class)); + cards.add(new SetCardInfo("Reanimate", "U12", Rarity.MYTHIC, mage.cards.r.Reanimate.class)); + cards.add(new SetCardInfo("Sigarda, Host of Herons", "U25", Rarity.MYTHIC, mage.cards.s.SigardaHostOfHerons.class)); + cards.add(new SetCardInfo("Snapcaster Mage", "U5", Rarity.MYTHIC, mage.cards.s.SnapcasterMage.class)); + cards.add(new SetCardInfo("Stirring Wildwood", "U39", Rarity.MYTHIC, mage.cards.s.StirringWildwood.class)); + cards.add(new SetCardInfo("Tarmogoyf", "U19", Rarity.MYTHIC, mage.cards.t.Tarmogoyf.class)); + cards.add(new SetCardInfo("Tasigur, the Golden Fang", "U13", Rarity.MYTHIC, mage.cards.t.TasigurTheGoldenFang.class)); + cards.add(new SetCardInfo("Temporal Manipulation", "U6", Rarity.MYTHIC, mage.cards.t.TemporalManipulation.class)); + cards.add(new SetCardInfo("Through the Breach", "U15", Rarity.MYTHIC, mage.cards.t.ThroughTheBreach.class)); + cards.add(new SetCardInfo("Ulamog, the Infinite Gyre", "U4", Rarity.MYTHIC, mage.cards.u.UlamogTheInfiniteGyre.class)); + cards.add(new SetCardInfo("Urborg, Tomb of Yawgmoth", "U40", Rarity.MYTHIC, mage.cards.u.UrborgTombOfYawgmoth.class)); + cards.add(new SetCardInfo("Vengevine", "U20", Rarity.MYTHIC, mage.cards.v.Vengevine.class)); + } +} diff --git a/Mage.Sets/src/mage/sets/UltimateMasters.java b/Mage.Sets/src/mage/sets/UltimateMasters.java new file mode 100644 index 00000000000..7e39b5da524 --- /dev/null +++ b/Mage.Sets/src/mage/sets/UltimateMasters.java @@ -0,0 +1,284 @@ +package mage.sets; + +import mage.cards.ExpansionSet; +import mage.constants.Rarity; +import mage.constants.SetType; + +/** + * @author JayDi85 + */ +public final class UltimateMasters extends ExpansionSet { + + private static final UltimateMasters instance = new UltimateMasters(); + + public static UltimateMasters getInstance() { + return instance; + } + + private UltimateMasters() { + super("Ultimate Masters", "UMA", ExpansionSet.buildDate(2018, 12, 7), SetType.SUPPLEMENTAL); + this.blockName = "Reprint"; + this.hasBasicLands = false; + this.hasBoosters = true; + this.numBoosterLands = 0; + this.numBoosterCommon = 11; + this.numBoosterUncommon = 3; + this.numBoosterRare = 1; + this.ratioBoosterMythic = 8; + + cards.add(new SetCardInfo("Aethersnipe", 44, Rarity.COMMON, mage.cards.a.Aethersnipe.class)); + cards.add(new SetCardInfo("Akroan Crusader", 121, Rarity.COMMON, mage.cards.a.AkroanCrusader.class)); + cards.add(new SetCardInfo("All Is Dust", 1, Rarity.RARE, mage.cards.a.AllIsDust.class)); + cards.add(new SetCardInfo("Ancestor's Chosen", 9, Rarity.UNCOMMON, mage.cards.a.AncestorsChosen.class)); + cards.add(new SetCardInfo("Ancient Tomb", 236, Rarity.RARE, mage.cards.a.AncientTomb.class)); + cards.add(new SetCardInfo("Angel of Despair", 196, Rarity.UNCOMMON, mage.cards.a.AngelOfDespair.class)); + cards.add(new SetCardInfo("Angelic Renewal", 10, Rarity.COMMON, mage.cards.a.AngelicRenewal.class)); + cards.add(new SetCardInfo("Anger", 122, Rarity.UNCOMMON, mage.cards.a.Anger.class)); + cards.add(new SetCardInfo("Appetite for Brains", 83, Rarity.UNCOMMON, mage.cards.a.AppetiteForBrains.class)); + cards.add(new SetCardInfo("Apprentice Necromancer", 84, Rarity.UNCOMMON, mage.cards.a.ApprenticeNecromancer.class)); + cards.add(new SetCardInfo("Archaeomancer", 45, Rarity.COMMON, mage.cards.a.Archaeomancer.class)); + cards.add(new SetCardInfo("Arena Athlete", 123, Rarity.COMMON, mage.cards.a.ArenaAthlete.class)); + cards.add(new SetCardInfo("Artisan of Kozilek", 2, Rarity.UNCOMMON, mage.cards.a.ArtisanOfKozilek.class)); + cards.add(new SetCardInfo("Back to Basics", 46, Rarity.RARE, mage.cards.b.BackToBasics.class)); + cards.add(new SetCardInfo("Balefire Dragon", 124, Rarity.MYTHIC, mage.cards.b.BalefireDragon.class)); + cards.add(new SetCardInfo("Basking Rootwalla", 156, Rarity.COMMON, mage.cards.b.BaskingRootwalla.class)); + cards.add(new SetCardInfo("Beckon Apparition", 211, Rarity.COMMON, mage.cards.b.BeckonApparition.class)); + cards.add(new SetCardInfo("Become Immense", 157, Rarity.UNCOMMON, mage.cards.b.BecomeImmense.class)); + cards.add(new SetCardInfo("Bitterblossom", 85, Rarity.MYTHIC, mage.cards.b.Bitterblossom.class)); + cards.add(new SetCardInfo("Blast of Genius", 197, Rarity.UNCOMMON, mage.cards.b.BlastOfGenius.class)); + cards.add(new SetCardInfo("Bloodflow Connoisseur", 86, Rarity.COMMON, mage.cards.b.BloodflowConnoisseur.class)); + cards.add(new SetCardInfo("Boar Umbra", 158, Rarity.UNCOMMON, mage.cards.b.BoarUmbra.class)); + cards.add(new SetCardInfo("Boneyard Wurm", 159, Rarity.UNCOMMON, mage.cards.b.BoneyardWurm.class)); + cards.add(new SetCardInfo("Brawn", 160, Rarity.UNCOMMON, mage.cards.b.Brawn.class)); + cards.add(new SetCardInfo("Brazen Scourge", 125, Rarity.UNCOMMON, mage.cards.b.BrazenScourge.class)); + cards.add(new SetCardInfo("Bridge from Below", 87, Rarity.RARE, mage.cards.b.BridgeFromBelow.class)); + cards.add(new SetCardInfo("Buried Alive", 88, Rarity.UNCOMMON, mage.cards.b.BuriedAlive.class)); + cards.add(new SetCardInfo("Canker Abomination", 212, Rarity.COMMON, mage.cards.c.CankerAbomination.class)); + cards.add(new SetCardInfo("Cathodion", 226, Rarity.COMMON, mage.cards.c.Cathodion.class)); + cards.add(new SetCardInfo("Cavern of Souls", 237, Rarity.MYTHIC, mage.cards.c.CavernOfSouls.class)); + cards.add(new SetCardInfo("Celestial Colonnade", 238, Rarity.RARE, mage.cards.c.CelestialColonnade.class)); + cards.add(new SetCardInfo("Chainer's Edict", 89, Rarity.UNCOMMON, mage.cards.c.ChainersEdict.class)); + cards.add(new SetCardInfo("Circular Logic", 47, Rarity.UNCOMMON, mage.cards.c.CircularLogic.class)); + cards.add(new SetCardInfo("Conflagrate", 126, Rarity.UNCOMMON, mage.cards.c.Conflagrate.class)); + cards.add(new SetCardInfo("Containment Priest", 11, Rarity.RARE, mage.cards.c.ContainmentPriest.class)); + cards.add(new SetCardInfo("Conviction", 12, Rarity.COMMON, mage.cards.c.Conviction.class)); + cards.add(new SetCardInfo("Countersquall", 198, Rarity.UNCOMMON, mage.cards.c.Countersquall.class)); + cards.add(new SetCardInfo("Creeping Tar Pit", 239, Rarity.RARE, mage.cards.c.CreepingTarPit.class)); + cards.add(new SetCardInfo("Crow of Dark Tidings", 90, Rarity.COMMON, mage.cards.c.CrowOfDarkTidings.class)); + cards.add(new SetCardInfo("Crushing Canopy", 161, Rarity.COMMON, mage.cards.c.CrushingCanopy.class)); + cards.add(new SetCardInfo("Dakmor Salvage", 240, Rarity.UNCOMMON, mage.cards.d.DakmorSalvage.class)); + cards.add(new SetCardInfo("Dark Dabbling", 91, Rarity.COMMON, mage.cards.d.DarkDabbling.class)); + cards.add(new SetCardInfo("Dark Depths", 241, Rarity.MYTHIC, mage.cards.d.DarkDepths.class)); + cards.add(new SetCardInfo("Dawn Charm", 13, Rarity.UNCOMMON, mage.cards.d.DawnCharm.class)); + cards.add(new SetCardInfo("Daybreak Coronet", 14, Rarity.RARE, mage.cards.d.DaybreakCoronet.class)); + cards.add(new SetCardInfo("Death Denied", 92, Rarity.COMMON, mage.cards.d.DeathDenied.class)); + cards.add(new SetCardInfo("Defy Gravity", 48, Rarity.COMMON, mage.cards.d.DefyGravity.class)); + cards.add(new SetCardInfo("Demonic Tutor", 93, Rarity.RARE, mage.cards.d.DemonicTutor.class)); + cards.add(new SetCardInfo("Deranged Assistant", 49, Rarity.COMMON, mage.cards.d.DerangedAssistant.class)); + cards.add(new SetCardInfo("Desolate Lighthouse", 242, Rarity.RARE, mage.cards.d.DesolateLighthouse.class)); + cards.add(new SetCardInfo("Desperate Ritual", 127, Rarity.UNCOMMON, mage.cards.d.DesperateRitual.class)); + cards.add(new SetCardInfo("Devoted Druid", 162, Rarity.UNCOMMON, mage.cards.d.DevotedDruid.class)); + cards.add(new SetCardInfo("Dig Through Time", 50, Rarity.RARE, mage.cards.d.DigThroughTime.class)); + cards.add(new SetCardInfo("Dimir Guildmage", 213, Rarity.COMMON, mage.cards.d.DimirGuildmage.class)); + cards.add(new SetCardInfo("Disrupting Shoal", 51, Rarity.RARE, mage.cards.d.DisruptingShoal.class)); + cards.add(new SetCardInfo("Double Cleave", 214, Rarity.COMMON, mage.cards.d.DoubleCleave.class)); + cards.add(new SetCardInfo("Dreamscape Artist", 52, Rarity.UNCOMMON, mage.cards.d.DreamscapeArtist.class)); + cards.add(new SetCardInfo("Eel Umbra", 53, Rarity.COMMON, mage.cards.e.EelUmbra.class)); + cards.add(new SetCardInfo("Eldrazi Conscription", 3, Rarity.RARE, mage.cards.e.EldraziConscription.class)); + cards.add(new SetCardInfo("Emancipation Angel", 15, Rarity.UNCOMMON, mage.cards.e.EmancipationAngel.class)); + cards.add(new SetCardInfo("Emrakul, the Aeons Torn", 4, Rarity.MYTHIC, mage.cards.e.EmrakulTheAeonsTorn.class)); + cards.add(new SetCardInfo("Engineered Explosives", 227, Rarity.RARE, mage.cards.e.EngineeredExplosives.class)); + cards.add(new SetCardInfo("Entomb", 94, Rarity.RARE, mage.cards.e.Entomb.class)); + cards.add(new SetCardInfo("Eternal Witness", 163, Rarity.UNCOMMON, mage.cards.e.EternalWitness.class)); + cards.add(new SetCardInfo("Faith's Fetters", 16, Rarity.COMMON, mage.cards.f.FaithsFetters.class)); + cards.add(new SetCardInfo("Faithless Looting", 128, Rarity.COMMON, mage.cards.f.FaithlessLooting.class)); + cards.add(new SetCardInfo("Fauna Shaman", 164, Rarity.RARE, mage.cards.f.FaunaShaman.class)); + cards.add(new SetCardInfo("Fecundity", 165, Rarity.UNCOMMON, mage.cards.f.Fecundity.class)); + cards.add(new SetCardInfo("Fiend Hunter", 17, Rarity.UNCOMMON, mage.cards.f.FiendHunter.class)); + cards.add(new SetCardInfo("Fiery Temper", 129, Rarity.COMMON, mage.cards.f.FieryTemper.class)); + cards.add(new SetCardInfo("Fire // Ice", 225, Rarity.COMMON, mage.cards.f.FireIce.class)); + cards.add(new SetCardInfo("Firewing Phoenix", 130, Rarity.UNCOMMON, mage.cards.f.FirewingPhoenix.class)); + cards.add(new SetCardInfo("Flagstones of Trokair", 243, Rarity.RARE, mage.cards.f.FlagstonesOfTrokair.class)); + cards.add(new SetCardInfo("Flight of Fancy", 54, Rarity.COMMON, mage.cards.f.FlightOfFancy.class)); + cards.add(new SetCardInfo("Foil", 55, Rarity.COMMON, mage.cards.f.Foil.class)); + cards.add(new SetCardInfo("Forbidden Alchemy", 56, Rarity.UNCOMMON, mage.cards.f.ForbiddenAlchemy.class)); + cards.add(new SetCardInfo("Frantic Search", 57, Rarity.COMMON, mage.cards.f.FranticSearch.class)); + cards.add(new SetCardInfo("Fulminator Mage", 215, Rarity.RARE, mage.cards.f.FulminatorMage.class)); + cards.add(new SetCardInfo("Fume Spitter", 95, Rarity.COMMON, mage.cards.f.FumeSpitter.class)); + cards.add(new SetCardInfo("Furnace Celebration", 131, Rarity.UNCOMMON, mage.cards.f.FurnaceCelebration.class)); + cards.add(new SetCardInfo("Gaddock Teeg", 199, Rarity.RARE, mage.cards.g.GaddockTeeg.class)); + cards.add(new SetCardInfo("Gamble", 132, Rarity.RARE, mage.cards.g.Gamble.class)); + cards.add(new SetCardInfo("Garna, the Bloodflame", 200, Rarity.UNCOMMON, mage.cards.g.GarnaTheBloodflame.class)); + cards.add(new SetCardInfo("Generator Servant", 133, Rarity.COMMON, mage.cards.g.GeneratorServant.class)); + cards.add(new SetCardInfo("Ghoulcaller's Accomplice", 96, Rarity.COMMON, mage.cards.g.GhoulcallersAccomplice.class)); + cards.add(new SetCardInfo("Ghoulsteed", 97, Rarity.UNCOMMON, mage.cards.g.Ghoulsteed.class)); + cards.add(new SetCardInfo("Glen Elendra Archmage", 58, Rarity.RARE, mage.cards.g.GlenElendraArchmage.class)); + cards.add(new SetCardInfo("Gods Willing", 18, Rarity.COMMON, mage.cards.g.GodsWilling.class)); + cards.add(new SetCardInfo("Golgari Brownscale", 166, Rarity.COMMON, mage.cards.g.GolgariBrownscale.class)); + cards.add(new SetCardInfo("Golgari Charm", 201, Rarity.UNCOMMON, mage.cards.g.GolgariCharm.class)); + cards.add(new SetCardInfo("Golgari Grave-Troll", 167, Rarity.RARE, mage.cards.g.GolgariGraveTroll.class)); + cards.add(new SetCardInfo("Golgari Thug", 98, Rarity.UNCOMMON, mage.cards.g.GolgariThug.class)); + cards.add(new SetCardInfo("Goryo's Vengeance", 99, Rarity.RARE, mage.cards.g.GoryosVengeance.class)); + cards.add(new SetCardInfo("Grave Scrabbler", 100, Rarity.COMMON, mage.cards.g.GraveScrabbler.class)); + cards.add(new SetCardInfo("Grave Strength", 101, Rarity.UNCOMMON, mage.cards.g.GraveStrength.class)); + cards.add(new SetCardInfo("Groundskeeper", 168, Rarity.COMMON, mage.cards.g.Groundskeeper.class)); + cards.add(new SetCardInfo("Gurmag Angler", 102, Rarity.COMMON, mage.cards.g.GurmagAngler.class)); + cards.add(new SetCardInfo("Heap Doll", 228, Rarity.UNCOMMON, mage.cards.h.HeapDoll.class)); + cards.add(new SetCardInfo("Heliod's Pilgrim", 19, Rarity.COMMON, mage.cards.h.HeliodsPilgrim.class)); + cards.add(new SetCardInfo("Hero of Iroas", 20, Rarity.UNCOMMON, mage.cards.h.HeroOfIroas.class)); + cards.add(new SetCardInfo("Hero of Leina Tower", 169, Rarity.UNCOMMON, mage.cards.h.HeroOfLeinaTower.class)); + cards.add(new SetCardInfo("Hissing Iguanar", 134, Rarity.COMMON, mage.cards.h.HissingIguanar.class)); + cards.add(new SetCardInfo("Hooting Mandrills", 170, Rarity.COMMON, mage.cards.h.HootingMandrills.class)); + cards.add(new SetCardInfo("Hyena Umbra", 21, Rarity.COMMON, mage.cards.h.HyenaUmbra.class)); + cards.add(new SetCardInfo("Icatian Crier", 22, Rarity.COMMON, mage.cards.i.IcatianCrier.class)); + cards.add(new SetCardInfo("Ingot Chewer", 135, Rarity.COMMON, mage.cards.i.IngotChewer.class)); + cards.add(new SetCardInfo("Iridescent Drake", 59, Rarity.UNCOMMON, mage.cards.i.IridescentDrake.class)); + cards.add(new SetCardInfo("Just the Wind", 60, Rarity.COMMON, mage.cards.j.JustTheWind.class)); + cards.add(new SetCardInfo("Karakas", 244, Rarity.MYTHIC, mage.cards.k.Karakas.class)); + cards.add(new SetCardInfo("Karn Liberated", 5, Rarity.MYTHIC, mage.cards.k.KarnLiberated.class)); + cards.add(new SetCardInfo("Kitchen Finks", 216, Rarity.UNCOMMON, mage.cards.k.KitchenFinks.class)); + cards.add(new SetCardInfo("Kodama's Reach", 171, Rarity.COMMON, mage.cards.k.KodamasReach.class)); + cards.add(new SetCardInfo("Kozilek, Butcher of Truth", 6, Rarity.MYTHIC, mage.cards.k.KozilekButcherOfTruth.class)); + cards.add(new SetCardInfo("Laboratory Maniac", 61, Rarity.UNCOMMON, mage.cards.l.LaboratoryManiac.class)); + cards.add(new SetCardInfo("Last Gasp", 103, Rarity.COMMON, mage.cards.l.LastGasp.class)); + cards.add(new SetCardInfo("Lava Spike", 136, Rarity.UNCOMMON, mage.cards.l.LavaSpike.class)); + cards.add(new SetCardInfo("Lavaclaw Reaches", 245, Rarity.RARE, mage.cards.l.LavaclawReaches.class)); + cards.add(new SetCardInfo("Leovold, Emissary of Trest", 202, Rarity.MYTHIC, mage.cards.l.LeovoldEmissaryOfTrest.class)); + cards.add(new SetCardInfo("Life from the Loam", 172, Rarity.RARE, mage.cards.l.LifeFromTheLoam.class)); + cards.add(new SetCardInfo("Liliana of the Veil", 104, Rarity.MYTHIC, mage.cards.l.LilianaOfTheVeil.class)); + cards.add(new SetCardInfo("Living Lore", 62, Rarity.UNCOMMON, mage.cards.l.LivingLore.class)); + cards.add(new SetCardInfo("Lord of Extinction", 203, Rarity.MYTHIC, mage.cards.l.LordOfExtinction.class)); + cards.add(new SetCardInfo("Lotus-Eye Mystics", 23, Rarity.COMMON, mage.cards.l.LotusEyeMystics.class)); + cards.add(new SetCardInfo("Mad Prophet", 137, Rarity.COMMON, mage.cards.m.MadProphet.class)); + cards.add(new SetCardInfo("Maelstrom Pulse", 204, Rarity.RARE, mage.cards.m.MaelstromPulse.class)); + cards.add(new SetCardInfo("Mage-Ring Network", 246, Rarity.UNCOMMON, mage.cards.m.MageRingNetwork.class)); + cards.add(new SetCardInfo("Magmaw", 138, Rarity.UNCOMMON, mage.cards.m.Magmaw.class)); + cards.add(new SetCardInfo("Magus of the Bazaar", 63, Rarity.RARE, mage.cards.m.MagusOfTheBazaar.class)); + cards.add(new SetCardInfo("Mahamoti Djinn", 64, Rarity.UNCOMMON, mage.cards.m.MahamotiDjinn.class)); + cards.add(new SetCardInfo("Malevolent Whispers", 139, Rarity.UNCOMMON, mage.cards.m.MalevolentWhispers.class)); + cards.add(new SetCardInfo("Mammoth Umbra", 24, Rarity.COMMON, mage.cards.m.MammothUmbra.class)); + cards.add(new SetCardInfo("Mana Vault", 229, Rarity.MYTHIC, mage.cards.m.ManaVault.class)); + cards.add(new SetCardInfo("Marang River Prowler", 65, Rarity.UNCOMMON, mage.cards.m.MarangRiverProwler.class)); + cards.add(new SetCardInfo("Mark of the Vampire", 105, Rarity.COMMON, mage.cards.m.MarkOfTheVampire.class)); + cards.add(new SetCardInfo("Martyr of Sands", 25, Rarity.COMMON, mage.cards.m.MartyrOfSands.class)); + cards.add(new SetCardInfo("Mikaeus, the Unhallowed", 106, Rarity.MYTHIC, mage.cards.m.MikaeusTheUnhallowed.class)); + cards.add(new SetCardInfo("Miming Slime", 173, Rarity.COMMON, mage.cards.m.MimingSlime.class)); + cards.add(new SetCardInfo("Miraculous Recovery", 26, Rarity.UNCOMMON, mage.cards.m.MiraculousRecovery.class)); + cards.add(new SetCardInfo("Mistveil Plains", 247, Rarity.UNCOMMON, mage.cards.m.MistveilPlains.class)); + cards.add(new SetCardInfo("Moan of the Unhallowed", 107, Rarity.COMMON, mage.cards.m.MoanOfTheUnhallowed.class)); + cards.add(new SetCardInfo("Molten Birth", 140, Rarity.COMMON, mage.cards.m.MoltenBirth.class)); + cards.add(new SetCardInfo("Murderous Redcap", 217, Rarity.UNCOMMON, mage.cards.m.MurderousRedcap.class)); + cards.add(new SetCardInfo("Myr Servitor", 230, Rarity.COMMON, mage.cards.m.MyrServitor.class)); + cards.add(new SetCardInfo("Mystic Retrieval", 66, Rarity.UNCOMMON, mage.cards.m.MysticRetrieval.class)); + cards.add(new SetCardInfo("Nightbird's Clutches", 141, Rarity.COMMON, mage.cards.n.NightbirdsClutches.class)); + cards.add(new SetCardInfo("Noble Hierarch", 174, Rarity.RARE, mage.cards.n.NobleHierarch.class)); + cards.add(new SetCardInfo("Nourishing Shoal", 175, Rarity.RARE, mage.cards.n.NourishingShoal.class)); + cards.add(new SetCardInfo("Offalsnout", 108, Rarity.COMMON, mage.cards.o.Offalsnout.class)); + cards.add(new SetCardInfo("Olivia's Dragoon", 109, Rarity.COMMON, mage.cards.o.OliviasDragoon.class)); + cards.add(new SetCardInfo("Patchwork Gnomes", 231, Rarity.COMMON, mage.cards.p.PatchworkGnomes.class)); + cards.add(new SetCardInfo("Pattern of Rebirth", 176, Rarity.RARE, mage.cards.p.PatternOfRebirth.class)); + cards.add(new SetCardInfo("Penumbra Wurm", 177, Rarity.UNCOMMON, mage.cards.p.PenumbraWurm.class)); + cards.add(new SetCardInfo("Phalanx Leader", 27, Rarity.UNCOMMON, mage.cards.p.PhalanxLeader.class)); + cards.add(new SetCardInfo("Phyrexian Altar", 232, Rarity.RARE, mage.cards.p.PhyrexianAltar.class)); + cards.add(new SetCardInfo("Phyrexian Tower", 248, Rarity.RARE, mage.cards.p.PhyrexianTower.class)); + cards.add(new SetCardInfo("Platinum Emperion", 233, Rarity.MYTHIC, mage.cards.p.PlatinumEmperion.class)); + cards.add(new SetCardInfo("Plumeveil", 218, Rarity.UNCOMMON, mage.cards.p.Plumeveil.class)); + cards.add(new SetCardInfo("Prey Upon", 178, Rarity.COMMON, mage.cards.p.PreyUpon.class)); + cards.add(new SetCardInfo("Prismatic Lens", 234, Rarity.UNCOMMON, mage.cards.p.PrismaticLens.class)); + cards.add(new SetCardInfo("Pulse of Murasa", 179, Rarity.COMMON, mage.cards.p.PulseOfMurasa.class)); + cards.add(new SetCardInfo("Raging Ravine", 249, Rarity.RARE, mage.cards.r.RagingRavine.class)); + cards.add(new SetCardInfo("Raid Bombardment", 142, Rarity.COMMON, mage.cards.r.RaidBombardment.class)); + cards.add(new SetCardInfo("Rakdos Shred-Freak", 219, Rarity.COMMON, mage.cards.r.RakdosShredFreak.class)); + cards.add(new SetCardInfo("Rally the Peasants", 28, Rarity.UNCOMMON, mage.cards.r.RallyThePeasants.class)); + cards.add(new SetCardInfo("Reanimate", 110, Rarity.RARE, mage.cards.r.Reanimate.class)); + cards.add(new SetCardInfo("Reckless Charge", 143, Rarity.COMMON, mage.cards.r.RecklessCharge.class)); + cards.add(new SetCardInfo("Reckless Wurm", 144, Rarity.COMMON, mage.cards.r.RecklessWurm.class)); + cards.add(new SetCardInfo("Repel the Darkness", 29, Rarity.COMMON, mage.cards.r.RepelTheDarkness.class)); + cards.add(new SetCardInfo("Resurrection", 30, Rarity.COMMON, mage.cards.r.Resurrection.class)); + cards.add(new SetCardInfo("Reveillark", 31, Rarity.RARE, mage.cards.r.Reveillark.class)); + cards.add(new SetCardInfo("Reviving Vapors", 205, Rarity.UNCOMMON, mage.cards.r.RevivingVapors.class)); + cards.add(new SetCardInfo("Reya Dawnbringer", 32, Rarity.RARE, mage.cards.r.ReyaDawnbringer.class)); + cards.add(new SetCardInfo("Rise from the Tides", 67, Rarity.UNCOMMON, mage.cards.r.RiseFromTheTides.class)); + cards.add(new SetCardInfo("Rogue's Passage", 250, Rarity.UNCOMMON, mage.cards.r.RoguesPassage.class)); + cards.add(new SetCardInfo("Rolling Temblor", 145, Rarity.UNCOMMON, mage.cards.r.RollingTemblor.class)); + cards.add(new SetCardInfo("Ronom Unicorn", 33, Rarity.COMMON, mage.cards.r.RonomUnicorn.class)); + cards.add(new SetCardInfo("Rune Snag", 68, Rarity.COMMON, mage.cards.r.RuneSnag.class)); + cards.add(new SetCardInfo("Runed Halo", 34, Rarity.RARE, mage.cards.r.RunedHalo.class)); + cards.add(new SetCardInfo("Safehold Elite", 220, Rarity.COMMON, mage.cards.s.SafeholdElite.class)); + cards.add(new SetCardInfo("Sanitarium Skeleton", 111, Rarity.COMMON, mage.cards.s.SanitariumSkeleton.class)); + cards.add(new SetCardInfo("Satyr Wayfinder", 180, Rarity.COMMON, mage.cards.s.SatyrWayfinder.class)); + cards.add(new SetCardInfo("Scuzzback Marauders", 221, Rarity.COMMON, mage.cards.s.ScuzzbackMarauders.class)); + cards.add(new SetCardInfo("Seismic Assault", 146, Rarity.RARE, mage.cards.s.SeismicAssault.class)); + cards.add(new SetCardInfo("Seize the Day", 147, Rarity.RARE, mage.cards.s.SeizeTheDay.class)); + cards.add(new SetCardInfo("Shed Weakness", 181, Rarity.COMMON, mage.cards.s.ShedWeakness.class)); + cards.add(new SetCardInfo("Shielding Plax", 222, Rarity.COMMON, mage.cards.s.ShieldingPlax.class)); + cards.add(new SetCardInfo("Shirei, Shizo's Caretaker", 112, Rarity.UNCOMMON, mage.cards.s.ShireiShizosCaretaker.class)); + cards.add(new SetCardInfo("Shriekmaw", 113, Rarity.UNCOMMON, mage.cards.s.Shriekmaw.class)); + cards.add(new SetCardInfo("Sigarda, Host of Herons", 206, Rarity.MYTHIC, mage.cards.s.SigardaHostOfHerons.class)); + cards.add(new SetCardInfo("Sigil of the New Dawn", 35, Rarity.UNCOMMON, mage.cards.s.SigilOfTheNewDawn.class)); + cards.add(new SetCardInfo("Skyspear Cavalry", 36, Rarity.COMMON, mage.cards.s.SkyspearCavalry.class)); + cards.add(new SetCardInfo("Skywing Aven", 69, Rarity.COMMON, mage.cards.s.SkywingAven.class)); + cards.add(new SetCardInfo("Sleight of Hand", 70, Rarity.UNCOMMON, mage.cards.s.SleightOfHand.class)); + cards.add(new SetCardInfo("Slippery Bogle", 223, Rarity.UNCOMMON, mage.cards.s.SlipperyBogle.class)); + cards.add(new SetCardInfo("Slum Reaper", 114, Rarity.COMMON, mage.cards.s.SlumReaper.class)); + cards.add(new SetCardInfo("Snake Umbra", 182, Rarity.UNCOMMON, mage.cards.s.SnakeUmbra.class)); + cards.add(new SetCardInfo("Snapcaster Mage", 71, Rarity.MYTHIC, mage.cards.s.SnapcasterMage.class)); + cards.add(new SetCardInfo("Songs of the Damned", 115, Rarity.UNCOMMON, mage.cards.s.SongsOfTheDamned.class)); + cards.add(new SetCardInfo("Soul's Fire", 148, Rarity.COMMON, mage.cards.s.SoulsFire.class)); + cards.add(new SetCardInfo("Sovereigns of Lost Alara", 207, Rarity.RARE, mage.cards.s.SovereignsOfLostAlara.class)); + cards.add(new SetCardInfo("Sparkspitter", 149, Rarity.COMMON, mage.cards.s.Sparkspitter.class)); + cards.add(new SetCardInfo("Spider Spawning", 183, Rarity.UNCOMMON, mage.cards.s.SpiderSpawning.class)); + cards.add(new SetCardInfo("Spider Umbra", 184, Rarity.COMMON, mage.cards.s.SpiderUmbra.class)); + cards.add(new SetCardInfo("Spirit Cairn", 37, Rarity.UNCOMMON, mage.cards.s.SpiritCairn.class)); + cards.add(new SetCardInfo("Spoils of the Vault", 116, Rarity.RARE, mage.cards.s.SpoilsOfTheVault.class)); + cards.add(new SetCardInfo("Squee, Goblin Nabob", 150, Rarity.RARE, mage.cards.s.SqueeGoblinNabob.class)); + cards.add(new SetCardInfo("Staunch-Hearted Warrior", 185, Rarity.COMMON, mage.cards.s.StaunchHeartedWarrior.class)); + cards.add(new SetCardInfo("Stingerfling Spider", 186, Rarity.UNCOMMON, mage.cards.s.StingerflingSpider.class)); + cards.add(new SetCardInfo("Stirring Wildwood", 251, Rarity.RARE, mage.cards.s.StirringWildwood.class)); + cards.add(new SetCardInfo("Stitched Drake", 72, Rarity.COMMON, mage.cards.s.StitchedDrake.class)); + cards.add(new SetCardInfo("Stitcher's Apprentice", 73, Rarity.COMMON, mage.cards.s.StitchersApprentice.class)); + cards.add(new SetCardInfo("Stream of Consciousness", 74, Rarity.UNCOMMON, mage.cards.s.StreamOfConsciousness.class)); + cards.add(new SetCardInfo("Sublime Archangel", 38, Rarity.RARE, mage.cards.s.SublimeArchangel.class)); + cards.add(new SetCardInfo("Sultai Skullkeeper", 75, Rarity.COMMON, mage.cards.s.SultaiSkullkeeper.class)); + cards.add(new SetCardInfo("Swift Reckoning", 39, Rarity.UNCOMMON, mage.cards.s.SwiftReckoning.class)); + cards.add(new SetCardInfo("Talrand, Sky Summoner", 76, Rarity.RARE, mage.cards.t.TalrandSkySummoner.class)); + cards.add(new SetCardInfo("Tarmogoyf", 187, Rarity.MYTHIC, mage.cards.t.Tarmogoyf.class)); + cards.add(new SetCardInfo("Tasigur, the Golden Fang", 117, Rarity.RARE, mage.cards.t.TasigurTheGoldenFang.class)); + cards.add(new SetCardInfo("Temporal Manipulation", 77, Rarity.MYTHIC, mage.cards.t.TemporalManipulation.class)); + cards.add(new SetCardInfo("Terramorphic Expanse", 252, Rarity.COMMON, mage.cards.t.TerramorphicExpanse.class)); + cards.add(new SetCardInfo("Tethmos High Priest", 40, Rarity.COMMON, mage.cards.t.TethmosHighPriest.class)); + cards.add(new SetCardInfo("Thermo-Alchemist", 151, Rarity.COMMON, mage.cards.t.ThermoAlchemist.class)); + cards.add(new SetCardInfo("Thespian's Stage", 253, Rarity.RARE, mage.cards.t.ThespiansStage.class)); + cards.add(new SetCardInfo("Think Twice", 78, Rarity.COMMON, mage.cards.t.ThinkTwice.class)); + cards.add(new SetCardInfo("Through the Breach", 152, Rarity.RARE, mage.cards.t.ThroughTheBreach.class)); + cards.add(new SetCardInfo("Travel Preparations", 188, Rarity.UNCOMMON, mage.cards.t.TravelPreparations.class)); + cards.add(new SetCardInfo("Treasure Cruise", 79, Rarity.COMMON, mage.cards.t.TreasureCruise.class)); + cards.add(new SetCardInfo("Turn to Mist", 224, Rarity.COMMON, mage.cards.t.TurnToMist.class)); + cards.add(new SetCardInfo("Twins of Maurer Estate", 118, Rarity.COMMON, mage.cards.t.TwinsOfMaurerEstate.class)); + cards.add(new SetCardInfo("Ulamog's Crusher", 8, Rarity.COMMON, mage.cards.u.UlamogsCrusher.class)); + cards.add(new SetCardInfo("Ulamog, the Infinite Gyre", 7, Rarity.MYTHIC, mage.cards.u.UlamogTheInfiniteGyre.class)); + cards.add(new SetCardInfo("Unburial Rites", 119, Rarity.UNCOMMON, mage.cards.u.UnburialRites.class)); + cards.add(new SetCardInfo("Undying Rage", 153, Rarity.COMMON, mage.cards.u.UndyingRage.class)); + cards.add(new SetCardInfo("Unholy Hunger", 120, Rarity.COMMON, mage.cards.u.UnholyHunger.class)); + cards.add(new SetCardInfo("Unstable Mutation", 80, Rarity.UNCOMMON, mage.cards.u.UnstableMutation.class)); + cards.add(new SetCardInfo("Urban Evolution", 208, Rarity.UNCOMMON, mage.cards.u.UrbanEvolution.class)); + cards.add(new SetCardInfo("Urborg, Tomb of Yawgmoth", 254, Rarity.RARE, mage.cards.u.UrborgTombOfYawgmoth.class)); + cards.add(new SetCardInfo("Vengeful Rebirth", 209, Rarity.UNCOMMON, mage.cards.v.VengefulRebirth.class)); + cards.add(new SetCardInfo("Vengevine", 189, Rarity.MYTHIC, mage.cards.v.Vengevine.class)); + cards.add(new SetCardInfo("Verdant Eidolon", 190, Rarity.COMMON, mage.cards.v.VerdantEidolon.class)); + cards.add(new SetCardInfo("Vessel of Endless Rest", 235, Rarity.COMMON, mage.cards.v.VesselOfEndlessRest.class)); + cards.add(new SetCardInfo("Vexing Devil", 154, Rarity.RARE, mage.cards.v.VexingDevil.class)); + cards.add(new SetCardInfo("Visions of Beyond", 81, Rarity.RARE, mage.cards.v.VisionsOfBeyond.class)); + cards.add(new SetCardInfo("Walker of the Grove", 191, Rarity.COMMON, mage.cards.w.WalkerOfTheGrove.class)); + cards.add(new SetCardInfo("Wall of Reverence", 41, Rarity.RARE, mage.cards.w.WallOfReverence.class)); + cards.add(new SetCardInfo("Wandering Champion", 42, Rarity.COMMON, mage.cards.w.WanderingChampion.class)); + cards.add(new SetCardInfo("Warleader's Helix", 210, Rarity.UNCOMMON, mage.cards.w.WarleadersHelix.class)); + cards.add(new SetCardInfo("Whirlwind Adept", 82, Rarity.COMMON, mage.cards.w.WhirlwindAdept.class)); + cards.add(new SetCardInfo("Wickerbough Elder", 192, Rarity.COMMON, mage.cards.w.WickerboughElder.class)); + cards.add(new SetCardInfo("Wild Hunger", 193, Rarity.UNCOMMON, mage.cards.w.WildHunger.class)); + cards.add(new SetCardInfo("Wild Mongrel", 194, Rarity.COMMON, mage.cards.w.WildMongrel.class)); + cards.add(new SetCardInfo("Wingsteed Rider", 43, Rarity.COMMON, mage.cards.w.WingsteedRider.class)); + cards.add(new SetCardInfo("Woodfall Primus", 195, Rarity.RARE, mage.cards.w.WoodfallPrimus.class)); + cards.add(new SetCardInfo("Young Pyromancer", 155, Rarity.UNCOMMON, mage.cards.y.YoungPyromancer.class)); + } +} diff --git a/Mage.Sets/src/mage/sets/Unhinged.java b/Mage.Sets/src/mage/sets/Unhinged.java index 9a927bad34b..bc8b3730532 100644 --- a/Mage.Sets/src/mage/sets/Unhinged.java +++ b/Mage.Sets/src/mage/sets/Unhinged.java @@ -39,6 +39,7 @@ public final class Unhinged extends ExpansionSet { cards.add(new SetCardInfo("Mountain", 139, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(FrameStyle.UNH_FULL_ART_BASIC, false))); cards.add(new SetCardInfo("Mox Lotus", 124, Rarity.RARE, mage.cards.m.MoxLotus.class)); cards.add(new SetCardInfo("Now I Know My ABC's", 41, Rarity.RARE, mage.cards.n.NowIKnowMyABCs.class)); + cards.add(new SetCardInfo("Old Fogey", 106, Rarity.RARE, mage.cards.o.OldFogey.class)); cards.add(new SetCardInfo("Plains", 136, Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(FrameStyle.UNH_FULL_ART_BASIC, false))); cards.add(new SetCardInfo("Rare-B-Gone", 119, Rarity.RARE, mage.cards.r.RareBGone.class)); cards.add(new SetCardInfo("Six-y Beast", 89, Rarity.UNCOMMON, mage.cards.s.SixyBeast.class)); diff --git a/Mage.Sets/src/mage/sets/UrzasDestiny.java b/Mage.Sets/src/mage/sets/UrzasDestiny.java index 17e0fd38ed1..aae8ca309c2 100644 --- a/Mage.Sets/src/mage/sets/UrzasDestiny.java +++ b/Mage.Sets/src/mage/sets/UrzasDestiny.java @@ -1,166 +1,175 @@ - -package mage.sets; - -import mage.cards.ExpansionSet; -import mage.constants.Rarity; -import mage.constants.SetType; - -/** - * - * @author Backfir3 - */ -public final class UrzasDestiny extends ExpansionSet { - - private static final UrzasDestiny instance = new UrzasDestiny(); - - public static UrzasDestiny getInstance() { - return instance; - } - - private UrzasDestiny() { - super("Urza's Destiny", "UDS", ExpansionSet.buildDate(1999, 6, 7), SetType.EXPANSION); - this.blockName = "Urza"; - this.parentSet = UrzasSaga.getInstance(); - this.hasBasicLands = false; - this.hasBoosters = true; - this.numBoosterLands = 0; - this.numBoosterCommon = 11; - this.numBoosterUncommon = 3; - this.numBoosterRare = 1; - this.ratioBoosterMythic = 0; - cards.add(new SetCardInfo("Academy Rector", 1, Rarity.RARE, mage.cards.a.AcademyRector.class)); - cards.add(new SetCardInfo("Aether Sting", 76, Rarity.UNCOMMON, mage.cards.a.AetherSting.class)); - cards.add(new SetCardInfo("Ancient Silverback", 101, Rarity.RARE, mage.cards.a.AncientSilverback.class)); - cards.add(new SetCardInfo("Apprentice Necromancer", 51, Rarity.RARE, mage.cards.a.ApprenticeNecromancer.class)); - cards.add(new SetCardInfo("Attrition", 52, Rarity.RARE, mage.cards.a.Attrition.class)); - cards.add(new SetCardInfo("Aura Thief", 26, Rarity.RARE, mage.cards.a.AuraThief.class)); - cards.add(new SetCardInfo("Blizzard Elemental", 27, Rarity.RARE, mage.cards.b.BlizzardElemental.class)); - cards.add(new SetCardInfo("Bloodshot Cyclops", 77, Rarity.RARE, mage.cards.b.BloodshotCyclops.class)); - cards.add(new SetCardInfo("Body Snatcher", 53, Rarity.RARE, mage.cards.b.BodySnatcher.class)); - cards.add(new SetCardInfo("Braidwood Cup", 126, Rarity.UNCOMMON, mage.cards.b.BraidwoodCup.class)); - cards.add(new SetCardInfo("Braidwood Sextant", 127, Rarity.UNCOMMON, mage.cards.b.BraidwoodSextant.class)); - cards.add(new SetCardInfo("Brass Secretary", 128, Rarity.UNCOMMON, mage.cards.b.BrassSecretary.class)); - cards.add(new SetCardInfo("Brine Seer", 28, Rarity.UNCOMMON, mage.cards.b.BrineSeer.class)); - cards.add(new SetCardInfo("Bubbling Beebles", 29, Rarity.COMMON, mage.cards.b.BubblingBeebles.class)); - cards.add(new SetCardInfo("Bubbling Muck", 54, Rarity.COMMON, mage.cards.b.BubblingMuck.class)); - cards.add(new SetCardInfo("Caltrops", 129, Rarity.UNCOMMON, mage.cards.c.Caltrops.class)); - cards.add(new SetCardInfo("Capashen Knight", 3, Rarity.COMMON, mage.cards.c.CapashenKnight.class)); - cards.add(new SetCardInfo("Capashen Standard", 4, Rarity.COMMON, mage.cards.c.CapashenStandard.class)); - cards.add(new SetCardInfo("Capashen Templar", 5, Rarity.COMMON, mage.cards.c.CapashenTemplar.class)); - cards.add(new SetCardInfo("Carnival of Souls", 55, Rarity.RARE, mage.cards.c.CarnivalOfSouls.class)); - cards.add(new SetCardInfo("Chime of Night", 56, Rarity.COMMON, mage.cards.c.ChimeOfNight.class)); - cards.add(new SetCardInfo("Cinder Seer", 78, Rarity.UNCOMMON, mage.cards.c.CinderSeer.class)); - cards.add(new SetCardInfo("Colos Yearling", 79, Rarity.COMMON, mage.cards.c.ColosYearling.class)); - cards.add(new SetCardInfo("Compost", 102, Rarity.UNCOMMON, mage.cards.c.Compost.class)); - cards.add(new SetCardInfo("Covetous Dragon", 80, Rarity.RARE, mage.cards.c.CovetousDragon.class)); - cards.add(new SetCardInfo("Disease Carriers", 57, Rarity.COMMON, mage.cards.d.DiseaseCarriers.class)); - cards.add(new SetCardInfo("Donate", 31, Rarity.RARE, mage.cards.d.Donate.class)); - cards.add(new SetCardInfo("Dying Wail", 58, Rarity.COMMON, mage.cards.d.DyingWail.class)); - cards.add(new SetCardInfo("Elvish Lookout", 103, Rarity.COMMON, mage.cards.e.ElvishLookout.class)); - cards.add(new SetCardInfo("Elvish Piper", 104, Rarity.RARE, mage.cards.e.ElvishPiper.class)); - cards.add(new SetCardInfo("Emperor Crocodile", 105, Rarity.RARE, mage.cards.e.EmperorCrocodile.class)); - cards.add(new SetCardInfo("Encroach", 59, Rarity.UNCOMMON, mage.cards.e.Encroach.class)); - cards.add(new SetCardInfo("Eradicate", 60, Rarity.UNCOMMON, mage.cards.e.Eradicate.class)); - cards.add(new SetCardInfo("Extruder", 130, Rarity.UNCOMMON, mage.cards.e.Extruder.class)); - cards.add(new SetCardInfo("False Prophet", 6, Rarity.RARE, mage.cards.f.FalseProphet.class)); - cards.add(new SetCardInfo("Festering Wound", 61, Rarity.UNCOMMON, mage.cards.f.FesteringWound.class)); - cards.add(new SetCardInfo("Field Surgeon", 8, Rarity.COMMON, mage.cards.f.FieldSurgeon.class)); - cards.add(new SetCardInfo("Flame Jet", 81, Rarity.COMMON, mage.cards.f.FlameJet.class)); - cards.add(new SetCardInfo("Fledgling Osprey", 33, Rarity.COMMON, mage.cards.f.FledglingOsprey.class)); - cards.add(new SetCardInfo("Flicker", 9, Rarity.RARE, mage.cards.f.Flicker.class)); - cards.add(new SetCardInfo("Fodder Cannon", 131, Rarity.UNCOMMON, mage.cards.f.FodderCannon.class)); - cards.add(new SetCardInfo("Gamekeeper", 106, Rarity.UNCOMMON, mage.cards.g.Gamekeeper.class)); - cards.add(new SetCardInfo("Goblin Berserker", 82, Rarity.UNCOMMON, mage.cards.g.GoblinBerserker.class)); - cards.add(new SetCardInfo("Goblin Festival", 83, Rarity.RARE, mage.cards.g.GoblinFestival.class)); - cards.add(new SetCardInfo("Goblin Gardener", 84, Rarity.COMMON, mage.cards.g.GoblinGardener.class)); - cards.add(new SetCardInfo("Goblin Marshal", 85, Rarity.RARE, mage.cards.g.GoblinMarshal.class)); - cards.add(new SetCardInfo("Goblin Masons", 86, Rarity.COMMON, mage.cards.g.GoblinMasons.class)); - cards.add(new SetCardInfo("Goliath Beetle", 107, Rarity.COMMON, mage.cards.g.GoliathBeetle.class)); - cards.add(new SetCardInfo("Heart Warden", 108, Rarity.COMMON, mage.cards.h.HeartWarden.class)); - cards.add(new SetCardInfo("Hulking Ogre", 87, Rarity.COMMON, mage.cards.h.HulkingOgre.class)); - cards.add(new SetCardInfo("Hunting Moa", 109, Rarity.UNCOMMON, mage.cards.h.HuntingMoa.class)); - cards.add(new SetCardInfo("Illuminated Wings", 34, Rarity.COMMON, mage.cards.i.IlluminatedWings.class)); - cards.add(new SetCardInfo("Impatience", 88, Rarity.RARE, mage.cards.i.Impatience.class)); - cards.add(new SetCardInfo("Iridescent Drake", 35, Rarity.UNCOMMON, mage.cards.i.IridescentDrake.class)); - cards.add(new SetCardInfo("Ivy Seer", 110, Rarity.UNCOMMON, mage.cards.i.IvySeer.class)); - cards.add(new SetCardInfo("Jasmine Seer", 10, Rarity.UNCOMMON, mage.cards.j.JasmineSeer.class)); - cards.add(new SetCardInfo("Junk Diver", 132, Rarity.RARE, mage.cards.j.JunkDiver.class)); - cards.add(new SetCardInfo("Keldon Champion", 90, Rarity.UNCOMMON, mage.cards.k.KeldonChampion.class)); - cards.add(new SetCardInfo("Keldon Vandals", 91, Rarity.COMMON, mage.cards.k.KeldonVandals.class)); - cards.add(new SetCardInfo("Kingfisher", 36, Rarity.COMMON, mage.cards.k.Kingfisher.class)); - cards.add(new SetCardInfo("Landslide", 92, Rarity.UNCOMMON, mage.cards.l.Landslide.class)); - cards.add(new SetCardInfo("Magnify", 111, Rarity.COMMON, mage.cards.m.Magnify.class)); - cards.add(new SetCardInfo("Mantis Engine", 133, Rarity.UNCOMMON, mage.cards.m.MantisEngine.class)); - cards.add(new SetCardInfo("Marker Beetles", 112, Rarity.COMMON, mage.cards.m.MarkerBeetles.class)); - cards.add(new SetCardInfo("Mark of Fury", 93, Rarity.COMMON, mage.cards.m.MarkOfFury.class)); - cards.add(new SetCardInfo("Mask of Law and Grace", 11, Rarity.COMMON, mage.cards.m.MaskOfLawAndGrace.class)); - cards.add(new SetCardInfo("Master Healer", 12, Rarity.RARE, mage.cards.m.MasterHealer.class)); - cards.add(new SetCardInfo("Masticore", 134, Rarity.RARE, mage.cards.m.Masticore.class)); - cards.add(new SetCardInfo("Mental Discipline", 37, Rarity.COMMON, mage.cards.m.MentalDiscipline.class)); - cards.add(new SetCardInfo("Metalworker", 135, Rarity.RARE, mage.cards.m.Metalworker.class)); - cards.add(new SetCardInfo("Metathran Soldier", 39, Rarity.COMMON, mage.cards.m.MetathranSoldier.class)); - cards.add(new SetCardInfo("Momentum", 113, Rarity.UNCOMMON, mage.cards.m.Momentum.class)); - cards.add(new SetCardInfo("Multani's Decree", 114, Rarity.COMMON, mage.cards.m.MultanisDecree.class)); - cards.add(new SetCardInfo("Nightshade Seer", 63, Rarity.UNCOMMON, mage.cards.n.NightshadeSeer.class)); - cards.add(new SetCardInfo("Opalescence", 13, Rarity.RARE, mage.cards.o.Opalescence.class)); - cards.add(new SetCardInfo("Opposition", 40, Rarity.RARE, mage.cards.o.Opposition.class)); - cards.add(new SetCardInfo("Pattern of Rebirth", 115, Rarity.RARE, mage.cards.p.PatternOfRebirth.class)); - cards.add(new SetCardInfo("Phyrexian Monitor", 64, Rarity.COMMON, mage.cards.p.PhyrexianMonitor.class)); - cards.add(new SetCardInfo("Phyrexian Negator", 65, Rarity.RARE, mage.cards.p.PhyrexianNegator.class)); - cards.add(new SetCardInfo("Plague Dogs", 66, Rarity.UNCOMMON, mage.cards.p.PlagueDogs.class)); - cards.add(new SetCardInfo("Plated Spider", 116, Rarity.COMMON, mage.cards.p.PlatedSpider.class)); - cards.add(new SetCardInfo("Plow Under", 117, Rarity.RARE, mage.cards.p.PlowUnder.class)); - cards.add(new SetCardInfo("Powder Keg", 136, Rarity.RARE, mage.cards.p.PowderKeg.class)); - cards.add(new SetCardInfo("Quash", 42, Rarity.UNCOMMON, mage.cards.q.Quash.class)); - cards.add(new SetCardInfo("Rapid Decay", 67, Rarity.RARE, mage.cards.r.RapidDecay.class)); - cards.add(new SetCardInfo("Ravenous Rats", 68, Rarity.COMMON, mage.cards.r.RavenousRats.class)); - cards.add(new SetCardInfo("Rayne, Academy Chancellor", 43, Rarity.RARE, mage.cards.r.RayneAcademyChancellor.class)); - cards.add(new SetCardInfo("Reckless Abandon", 94, Rarity.COMMON, mage.cards.r.RecklessAbandon.class)); - cards.add(new SetCardInfo("Reliquary Monk", 14, Rarity.COMMON, mage.cards.r.ReliquaryMonk.class)); - cards.add(new SetCardInfo("Repercussion", 95, Rarity.RARE, mage.cards.r.Repercussion.class)); - cards.add(new SetCardInfo("Replenish", 15, Rarity.RARE, mage.cards.r.Replenish.class)); - cards.add(new SetCardInfo("Rescue", 44, Rarity.COMMON, mage.cards.r.Rescue.class)); - cards.add(new SetCardInfo("Rofellos's Gift", 119, Rarity.COMMON, mage.cards.r.RofellossGift.class)); - cards.add(new SetCardInfo("Rofellos, Llanowar Emissary", 118, Rarity.RARE, mage.cards.r.RofellosLlanowarEmissary.class)); - cards.add(new SetCardInfo("Sanctimony", 16, Rarity.UNCOMMON, mage.cards.s.Sanctimony.class)); - cards.add(new SetCardInfo("Scent of Brine", 45, Rarity.COMMON, mage.cards.s.ScentOfBrine.class)); - cards.add(new SetCardInfo("Scent of Cinder", 96, Rarity.COMMON, mage.cards.s.ScentOfCinder.class)); - cards.add(new SetCardInfo("Scent of Ivy", 120, Rarity.COMMON, mage.cards.s.ScentOfIvy.class)); - cards.add(new SetCardInfo("Scent of Jasmine", 17, Rarity.COMMON, mage.cards.s.ScentOfJasmine.class)); - cards.add(new SetCardInfo("Scent of Nightshade", 69, Rarity.COMMON, mage.cards.s.ScentOfNightshade.class)); - cards.add(new SetCardInfo("Scour", 18, Rarity.UNCOMMON, mage.cards.s.Scour.class)); - cards.add(new SetCardInfo("Serra Advocate", 19, Rarity.UNCOMMON, mage.cards.s.SerraAdvocate.class)); - cards.add(new SetCardInfo("Sigil of Sleep", 46, Rarity.COMMON, mage.cards.s.SigilOfSleep.class)); - cards.add(new SetCardInfo("Skittering Horror", 70, Rarity.COMMON, mage.cards.s.SkitteringHorror.class)); - cards.add(new SetCardInfo("Slinking Skirge", 71, Rarity.COMMON, mage.cards.s.SlinkingSkirge.class)); - cards.add(new SetCardInfo("Solidarity", 20, Rarity.COMMON, mage.cards.s.Solidarity.class)); - cards.add(new SetCardInfo("Soul Feast", 72, Rarity.UNCOMMON, mage.cards.s.SoulFeast.class)); - cards.add(new SetCardInfo("Sowing Salt", 97, Rarity.UNCOMMON, mage.cards.s.SowingSalt.class)); - cards.add(new SetCardInfo("Splinter", 121, Rarity.UNCOMMON, mage.cards.s.Splinter.class)); - cards.add(new SetCardInfo("Squirming Mass", 73, Rarity.COMMON, mage.cards.s.SquirmingMass.class)); - cards.add(new SetCardInfo("Storage Matrix", 138, Rarity.RARE, mage.cards.s.StorageMatrix.class)); - cards.add(new SetCardInfo("Taunting Elf", 122, Rarity.COMMON, mage.cards.t.TauntingElf.class)); - cards.add(new SetCardInfo("Telepathic Spies", 47, Rarity.COMMON, mage.cards.t.TelepathicSpies.class)); - cards.add(new SetCardInfo("Temporal Adept", 48, Rarity.RARE, mage.cards.t.TemporalAdept.class)); - cards.add(new SetCardInfo("Tethered Griffin", 21, Rarity.RARE, mage.cards.t.TetheredGriffin.class)); - cards.add(new SetCardInfo("Thieving Magpie", 49, Rarity.UNCOMMON, mage.cards.t.ThievingMagpie.class)); - cards.add(new SetCardInfo("Thorn Elemental", 123, Rarity.RARE, mage.cards.t.ThornElemental.class)); - cards.add(new SetCardInfo("Thran Dynamo", 139, Rarity.UNCOMMON, mage.cards.t.ThranDynamo.class)); - cards.add(new SetCardInfo("Thran Foundry", 140, Rarity.UNCOMMON, mage.cards.t.ThranFoundry.class)); - cards.add(new SetCardInfo("Thran Golem", 141, Rarity.RARE, mage.cards.t.ThranGolem.class)); - cards.add(new SetCardInfo("Tormented Angel", 22, Rarity.COMMON, mage.cards.t.TormentedAngel.class)); - cards.add(new SetCardInfo("Treachery", 50, Rarity.RARE, mage.cards.t.Treachery.class)); - cards.add(new SetCardInfo("Trumpet Blast", 98, Rarity.COMMON, mage.cards.t.TrumpetBlast.class)); - cards.add(new SetCardInfo("Twisted Experiment", 74, Rarity.COMMON, mage.cards.t.TwistedExperiment.class)); - cards.add(new SetCardInfo("Urza's Incubator", 142, Rarity.RARE, mage.cards.u.UrzasIncubator.class)); - cards.add(new SetCardInfo("Voice of Duty", 23, Rarity.UNCOMMON, mage.cards.v.VoiceOfDuty.class)); - cards.add(new SetCardInfo("Voice of Reason", 24, Rarity.UNCOMMON, mage.cards.v.VoiceOfReason.class)); - cards.add(new SetCardInfo("Wake of Destruction", 99, Rarity.RARE, mage.cards.w.WakeOfDestruction.class)); - cards.add(new SetCardInfo("Wall of Glare", 25, Rarity.COMMON, mage.cards.w.WallOfGlare.class)); - cards.add(new SetCardInfo("Wild Colos", 100, Rarity.COMMON, mage.cards.w.WildColos.class)); - cards.add(new SetCardInfo("Yavimaya Elder", 124, Rarity.COMMON, mage.cards.y.YavimayaElder.class)); - cards.add(new SetCardInfo("Yavimaya Enchantress", 125, Rarity.UNCOMMON, mage.cards.y.YavimayaEnchantress.class)); - cards.add(new SetCardInfo("Yavimaya Hollow", 143, Rarity.RARE, mage.cards.y.YavimayaHollow.class)); - cards.add(new SetCardInfo("Yawgmoth's Bargain", 75, Rarity.RARE, mage.cards.y.YawgmothsBargain.class)); - } -} + +package mage.sets; + +import mage.cards.ExpansionSet; +import mage.constants.Rarity; +import mage.constants.SetType; + +/** + * + * @author Backfir3 + */ +public final class UrzasDestiny extends ExpansionSet { + + private static final UrzasDestiny instance = new UrzasDestiny(); + + public static UrzasDestiny getInstance() { + return instance; + } + + private UrzasDestiny() { + super("Urza's Destiny", "UDS", ExpansionSet.buildDate(1999, 6, 7), SetType.EXPANSION); + this.blockName = "Urza"; + this.parentSet = UrzasSaga.getInstance(); + this.hasBasicLands = false; + this.hasBoosters = true; + this.numBoosterLands = 0; + this.numBoosterCommon = 11; + this.numBoosterUncommon = 3; + this.numBoosterRare = 1; + this.ratioBoosterMythic = 0; + cards.add(new SetCardInfo("Academy Rector", 1, Rarity.RARE, mage.cards.a.AcademyRector.class)); + cards.add(new SetCardInfo("Aether Sting", 76, Rarity.UNCOMMON, mage.cards.a.AetherSting.class)); + cards.add(new SetCardInfo("Ancient Silverback", 101, Rarity.RARE, mage.cards.a.AncientSilverback.class)); + cards.add(new SetCardInfo("Apprentice Necromancer", 51, Rarity.RARE, mage.cards.a.ApprenticeNecromancer.class)); + cards.add(new SetCardInfo("Archery Training", 2, Rarity.UNCOMMON, mage.cards.a.ArcheryTraining.class)); + cards.add(new SetCardInfo("Attrition", 52, Rarity.RARE, mage.cards.a.Attrition.class)); + cards.add(new SetCardInfo("Aura Thief", 26, Rarity.RARE, mage.cards.a.AuraThief.class)); + cards.add(new SetCardInfo("Blizzard Elemental", 27, Rarity.RARE, mage.cards.b.BlizzardElemental.class)); + cards.add(new SetCardInfo("Bloodshot Cyclops", 77, Rarity.RARE, mage.cards.b.BloodshotCyclops.class)); + cards.add(new SetCardInfo("Body Snatcher", 53, Rarity.RARE, mage.cards.b.BodySnatcher.class)); + cards.add(new SetCardInfo("Braidwood Cup", 126, Rarity.UNCOMMON, mage.cards.b.BraidwoodCup.class)); + cards.add(new SetCardInfo("Braidwood Sextant", 127, Rarity.UNCOMMON, mage.cards.b.BraidwoodSextant.class)); + cards.add(new SetCardInfo("Brass Secretary", 128, Rarity.UNCOMMON, mage.cards.b.BrassSecretary.class)); + cards.add(new SetCardInfo("Brine Seer", 28, Rarity.UNCOMMON, mage.cards.b.BrineSeer.class)); + cards.add(new SetCardInfo("Bubbling Beebles", 29, Rarity.COMMON, mage.cards.b.BubblingBeebles.class)); + cards.add(new SetCardInfo("Bubbling Muck", 54, Rarity.COMMON, mage.cards.b.BubblingMuck.class)); + cards.add(new SetCardInfo("Caltrops", 129, Rarity.UNCOMMON, mage.cards.c.Caltrops.class)); + cards.add(new SetCardInfo("Capashen Knight", 3, Rarity.COMMON, mage.cards.c.CapashenKnight.class)); + cards.add(new SetCardInfo("Capashen Standard", 4, Rarity.COMMON, mage.cards.c.CapashenStandard.class)); + cards.add(new SetCardInfo("Capashen Templar", 5, Rarity.COMMON, mage.cards.c.CapashenTemplar.class)); + cards.add(new SetCardInfo("Carnival of Souls", 55, Rarity.RARE, mage.cards.c.CarnivalOfSouls.class)); + cards.add(new SetCardInfo("Chime of Night", 56, Rarity.COMMON, mage.cards.c.ChimeOfNight.class)); + cards.add(new SetCardInfo("Cinder Seer", 78, Rarity.UNCOMMON, mage.cards.c.CinderSeer.class)); + cards.add(new SetCardInfo("Colos Yearling", 79, Rarity.COMMON, mage.cards.c.ColosYearling.class)); + cards.add(new SetCardInfo("Compost", 102, Rarity.UNCOMMON, mage.cards.c.Compost.class)); + cards.add(new SetCardInfo("Covetous Dragon", 80, Rarity.RARE, mage.cards.c.CovetousDragon.class)); + cards.add(new SetCardInfo("Disappear", 30, Rarity.UNCOMMON, mage.cards.d.Disappear.class)); + cards.add(new SetCardInfo("Disease Carriers", 57, Rarity.COMMON, mage.cards.d.DiseaseCarriers.class)); + cards.add(new SetCardInfo("Donate", 31, Rarity.RARE, mage.cards.d.Donate.class)); + cards.add(new SetCardInfo("Dying Wail", 58, Rarity.COMMON, mage.cards.d.DyingWail.class)); + cards.add(new SetCardInfo("Elvish Lookout", 103, Rarity.COMMON, mage.cards.e.ElvishLookout.class)); + cards.add(new SetCardInfo("Elvish Piper", 104, Rarity.RARE, mage.cards.e.ElvishPiper.class)); + cards.add(new SetCardInfo("Emperor Crocodile", 105, Rarity.RARE, mage.cards.e.EmperorCrocodile.class)); + cards.add(new SetCardInfo("Encroach", 59, Rarity.UNCOMMON, mage.cards.e.Encroach.class)); + cards.add(new SetCardInfo("Eradicate", 60, Rarity.UNCOMMON, mage.cards.e.Eradicate.class)); + cards.add(new SetCardInfo("Extruder", 130, Rarity.UNCOMMON, mage.cards.e.Extruder.class)); + cards.add(new SetCardInfo("False Prophet", 6, Rarity.RARE, mage.cards.f.FalseProphet.class)); + cards.add(new SetCardInfo("Fatigue", 32, Rarity.COMMON, mage.cards.f.Fatigue.class)); + cards.add(new SetCardInfo("Fend Off", 7, Rarity.COMMON, mage.cards.f.FendOff.class)); + cards.add(new SetCardInfo("Festering Wound", 61, Rarity.UNCOMMON, mage.cards.f.FesteringWound.class)); + cards.add(new SetCardInfo("Field Surgeon", 8, Rarity.COMMON, mage.cards.f.FieldSurgeon.class)); + cards.add(new SetCardInfo("Flame Jet", 81, Rarity.COMMON, mage.cards.f.FlameJet.class)); + cards.add(new SetCardInfo("Fledgling Osprey", 33, Rarity.COMMON, mage.cards.f.FledglingOsprey.class)); + cards.add(new SetCardInfo("Flicker", 9, Rarity.RARE, mage.cards.f.Flicker.class)); + cards.add(new SetCardInfo("Fodder Cannon", 131, Rarity.UNCOMMON, mage.cards.f.FodderCannon.class)); + cards.add(new SetCardInfo("Gamekeeper", 106, Rarity.UNCOMMON, mage.cards.g.Gamekeeper.class)); + cards.add(new SetCardInfo("Goblin Berserker", 82, Rarity.UNCOMMON, mage.cards.g.GoblinBerserker.class)); + cards.add(new SetCardInfo("Goblin Festival", 83, Rarity.RARE, mage.cards.g.GoblinFestival.class)); + cards.add(new SetCardInfo("Goblin Gardener", 84, Rarity.COMMON, mage.cards.g.GoblinGardener.class)); + cards.add(new SetCardInfo("Goblin Marshal", 85, Rarity.RARE, mage.cards.g.GoblinMarshal.class)); + cards.add(new SetCardInfo("Goblin Masons", 86, Rarity.COMMON, mage.cards.g.GoblinMasons.class)); + cards.add(new SetCardInfo("Goliath Beetle", 107, Rarity.COMMON, mage.cards.g.GoliathBeetle.class)); + cards.add(new SetCardInfo("Heart Warden", 108, Rarity.COMMON, mage.cards.h.HeartWarden.class)); + cards.add(new SetCardInfo("Hulking Ogre", 87, Rarity.COMMON, mage.cards.h.HulkingOgre.class)); + cards.add(new SetCardInfo("Hunting Moa", 109, Rarity.UNCOMMON, mage.cards.h.HuntingMoa.class)); + cards.add(new SetCardInfo("Illuminated Wings", 34, Rarity.COMMON, mage.cards.i.IlluminatedWings.class)); + cards.add(new SetCardInfo("Impatience", 88, Rarity.RARE, mage.cards.i.Impatience.class)); + cards.add(new SetCardInfo("Incendiary", 89, Rarity.UNCOMMON, mage.cards.i.Incendiary.class)); + cards.add(new SetCardInfo("Iridescent Drake", 35, Rarity.UNCOMMON, mage.cards.i.IridescentDrake.class)); + cards.add(new SetCardInfo("Ivy Seer", 110, Rarity.UNCOMMON, mage.cards.i.IvySeer.class)); + cards.add(new SetCardInfo("Jasmine Seer", 10, Rarity.UNCOMMON, mage.cards.j.JasmineSeer.class)); + cards.add(new SetCardInfo("Junk Diver", 132, Rarity.RARE, mage.cards.j.JunkDiver.class)); + cards.add(new SetCardInfo("Keldon Champion", 90, Rarity.UNCOMMON, mage.cards.k.KeldonChampion.class)); + cards.add(new SetCardInfo("Keldon Vandals", 91, Rarity.COMMON, mage.cards.k.KeldonVandals.class)); + cards.add(new SetCardInfo("Kingfisher", 36, Rarity.COMMON, mage.cards.k.Kingfisher.class)); + cards.add(new SetCardInfo("Landslide", 92, Rarity.UNCOMMON, mage.cards.l.Landslide.class)); + cards.add(new SetCardInfo("Lurking Jackals", 62, Rarity.UNCOMMON, mage.cards.l.LurkingJackals.class)); + cards.add(new SetCardInfo("Magnify", 111, Rarity.COMMON, mage.cards.m.Magnify.class)); + cards.add(new SetCardInfo("Mantis Engine", 133, Rarity.UNCOMMON, mage.cards.m.MantisEngine.class)); + cards.add(new SetCardInfo("Marker Beetles", 112, Rarity.COMMON, mage.cards.m.MarkerBeetles.class)); + cards.add(new SetCardInfo("Mark of Fury", 93, Rarity.COMMON, mage.cards.m.MarkOfFury.class)); + cards.add(new SetCardInfo("Mask of Law and Grace", 11, Rarity.COMMON, mage.cards.m.MaskOfLawAndGrace.class)); + cards.add(new SetCardInfo("Master Healer", 12, Rarity.RARE, mage.cards.m.MasterHealer.class)); + cards.add(new SetCardInfo("Masticore", 134, Rarity.RARE, mage.cards.m.Masticore.class)); + cards.add(new SetCardInfo("Mental Discipline", 37, Rarity.COMMON, mage.cards.m.MentalDiscipline.class)); + cards.add(new SetCardInfo("Metalworker", 135, Rarity.RARE, mage.cards.m.Metalworker.class)); + cards.add(new SetCardInfo("Metathran Elite", 38, Rarity.UNCOMMON, mage.cards.m.MetathranElite.class)); + cards.add(new SetCardInfo("Metathran Soldier", 39, Rarity.COMMON, mage.cards.m.MetathranSoldier.class)); + cards.add(new SetCardInfo("Momentum", 113, Rarity.UNCOMMON, mage.cards.m.Momentum.class)); + cards.add(new SetCardInfo("Multani's Decree", 114, Rarity.COMMON, mage.cards.m.MultanisDecree.class)); + cards.add(new SetCardInfo("Nightshade Seer", 63, Rarity.UNCOMMON, mage.cards.n.NightshadeSeer.class)); + cards.add(new SetCardInfo("Opalescence", 13, Rarity.RARE, mage.cards.o.Opalescence.class)); + cards.add(new SetCardInfo("Opposition", 40, Rarity.RARE, mage.cards.o.Opposition.class)); + cards.add(new SetCardInfo("Pattern of Rebirth", 115, Rarity.RARE, mage.cards.p.PatternOfRebirth.class)); + cards.add(new SetCardInfo("Phyrexian Monitor", 64, Rarity.COMMON, mage.cards.p.PhyrexianMonitor.class)); + cards.add(new SetCardInfo("Phyrexian Negator", 65, Rarity.RARE, mage.cards.p.PhyrexianNegator.class)); + cards.add(new SetCardInfo("Plague Dogs", 66, Rarity.UNCOMMON, mage.cards.p.PlagueDogs.class)); + cards.add(new SetCardInfo("Plated Spider", 116, Rarity.COMMON, mage.cards.p.PlatedSpider.class)); + cards.add(new SetCardInfo("Plow Under", 117, Rarity.RARE, mage.cards.p.PlowUnder.class)); + cards.add(new SetCardInfo("Powder Keg", 136, Rarity.RARE, mage.cards.p.PowderKeg.class)); + cards.add(new SetCardInfo("Private Research", 41, Rarity.UNCOMMON, mage.cards.p.PrivateResearch.class)); + cards.add(new SetCardInfo("Quash", 42, Rarity.UNCOMMON, mage.cards.q.Quash.class)); + cards.add(new SetCardInfo("Rapid Decay", 67, Rarity.RARE, mage.cards.r.RapidDecay.class)); + cards.add(new SetCardInfo("Ravenous Rats", 68, Rarity.COMMON, mage.cards.r.RavenousRats.class)); + cards.add(new SetCardInfo("Rayne, Academy Chancellor", 43, Rarity.RARE, mage.cards.r.RayneAcademyChancellor.class)); + cards.add(new SetCardInfo("Reckless Abandon", 94, Rarity.COMMON, mage.cards.r.RecklessAbandon.class)); + cards.add(new SetCardInfo("Reliquary Monk", 14, Rarity.COMMON, mage.cards.r.ReliquaryMonk.class)); + cards.add(new SetCardInfo("Repercussion", 95, Rarity.RARE, mage.cards.r.Repercussion.class)); + cards.add(new SetCardInfo("Replenish", 15, Rarity.RARE, mage.cards.r.Replenish.class)); + cards.add(new SetCardInfo("Rescue", 44, Rarity.COMMON, mage.cards.r.Rescue.class)); + cards.add(new SetCardInfo("Rofellos's Gift", 119, Rarity.COMMON, mage.cards.r.RofellossGift.class)); + cards.add(new SetCardInfo("Rofellos, Llanowar Emissary", 118, Rarity.RARE, mage.cards.r.RofellosLlanowarEmissary.class)); + cards.add(new SetCardInfo("Sanctimony", 16, Rarity.UNCOMMON, mage.cards.s.Sanctimony.class)); + cards.add(new SetCardInfo("Scent of Brine", 45, Rarity.COMMON, mage.cards.s.ScentOfBrine.class)); + cards.add(new SetCardInfo("Scent of Cinder", 96, Rarity.COMMON, mage.cards.s.ScentOfCinder.class)); + cards.add(new SetCardInfo("Scent of Ivy", 120, Rarity.COMMON, mage.cards.s.ScentOfIvy.class)); + cards.add(new SetCardInfo("Scent of Jasmine", 17, Rarity.COMMON, mage.cards.s.ScentOfJasmine.class)); + cards.add(new SetCardInfo("Scent of Nightshade", 69, Rarity.COMMON, mage.cards.s.ScentOfNightshade.class)); + cards.add(new SetCardInfo("Scour", 18, Rarity.UNCOMMON, mage.cards.s.Scour.class)); + cards.add(new SetCardInfo("Scrying Glass", 137, Rarity.RARE, mage.cards.s.ScryingGlass.class)); + cards.add(new SetCardInfo("Serra Advocate", 19, Rarity.UNCOMMON, mage.cards.s.SerraAdvocate.class)); + cards.add(new SetCardInfo("Sigil of Sleep", 46, Rarity.COMMON, mage.cards.s.SigilOfSleep.class)); + cards.add(new SetCardInfo("Skittering Horror", 70, Rarity.COMMON, mage.cards.s.SkitteringHorror.class)); + cards.add(new SetCardInfo("Slinking Skirge", 71, Rarity.COMMON, mage.cards.s.SlinkingSkirge.class)); + cards.add(new SetCardInfo("Solidarity", 20, Rarity.COMMON, mage.cards.s.Solidarity.class)); + cards.add(new SetCardInfo("Soul Feast", 72, Rarity.UNCOMMON, mage.cards.s.SoulFeast.class)); + cards.add(new SetCardInfo("Sowing Salt", 97, Rarity.UNCOMMON, mage.cards.s.SowingSalt.class)); + cards.add(new SetCardInfo("Splinter", 121, Rarity.UNCOMMON, mage.cards.s.Splinter.class)); + cards.add(new SetCardInfo("Squirming Mass", 73, Rarity.COMMON, mage.cards.s.SquirmingMass.class)); + cards.add(new SetCardInfo("Storage Matrix", 138, Rarity.RARE, mage.cards.s.StorageMatrix.class)); + cards.add(new SetCardInfo("Taunting Elf", 122, Rarity.COMMON, mage.cards.t.TauntingElf.class)); + cards.add(new SetCardInfo("Telepathic Spies", 47, Rarity.COMMON, mage.cards.t.TelepathicSpies.class)); + cards.add(new SetCardInfo("Temporal Adept", 48, Rarity.RARE, mage.cards.t.TemporalAdept.class)); + cards.add(new SetCardInfo("Tethered Griffin", 21, Rarity.RARE, mage.cards.t.TetheredGriffin.class)); + cards.add(new SetCardInfo("Thieving Magpie", 49, Rarity.UNCOMMON, mage.cards.t.ThievingMagpie.class)); + cards.add(new SetCardInfo("Thorn Elemental", 123, Rarity.RARE, mage.cards.t.ThornElemental.class)); + cards.add(new SetCardInfo("Thran Dynamo", 139, Rarity.UNCOMMON, mage.cards.t.ThranDynamo.class)); + cards.add(new SetCardInfo("Thran Foundry", 140, Rarity.UNCOMMON, mage.cards.t.ThranFoundry.class)); + cards.add(new SetCardInfo("Thran Golem", 141, Rarity.RARE, mage.cards.t.ThranGolem.class)); + cards.add(new SetCardInfo("Tormented Angel", 22, Rarity.COMMON, mage.cards.t.TormentedAngel.class)); + cards.add(new SetCardInfo("Treachery", 50, Rarity.RARE, mage.cards.t.Treachery.class)); + cards.add(new SetCardInfo("Trumpet Blast", 98, Rarity.COMMON, mage.cards.t.TrumpetBlast.class)); + cards.add(new SetCardInfo("Twisted Experiment", 74, Rarity.COMMON, mage.cards.t.TwistedExperiment.class)); + cards.add(new SetCardInfo("Urza's Incubator", 142, Rarity.RARE, mage.cards.u.UrzasIncubator.class)); + cards.add(new SetCardInfo("Voice of Duty", 23, Rarity.UNCOMMON, mage.cards.v.VoiceOfDuty.class)); + cards.add(new SetCardInfo("Voice of Reason", 24, Rarity.UNCOMMON, mage.cards.v.VoiceOfReason.class)); + cards.add(new SetCardInfo("Wake of Destruction", 99, Rarity.RARE, mage.cards.w.WakeOfDestruction.class)); + cards.add(new SetCardInfo("Wall of Glare", 25, Rarity.COMMON, mage.cards.w.WallOfGlare.class)); + cards.add(new SetCardInfo("Wild Colos", 100, Rarity.COMMON, mage.cards.w.WildColos.class)); + cards.add(new SetCardInfo("Yavimaya Elder", 124, Rarity.COMMON, mage.cards.y.YavimayaElder.class)); + cards.add(new SetCardInfo("Yavimaya Enchantress", 125, Rarity.UNCOMMON, mage.cards.y.YavimayaEnchantress.class)); + cards.add(new SetCardInfo("Yavimaya Hollow", 143, Rarity.RARE, mage.cards.y.YavimayaHollow.class)); + cards.add(new SetCardInfo("Yawgmoth's Bargain", 75, Rarity.RARE, mage.cards.y.YawgmothsBargain.class)); + } +} diff --git a/Mage.Sets/src/mage/sets/UrzasLegacy.java b/Mage.Sets/src/mage/sets/UrzasLegacy.java index eaa00b8c3cd..431d2eb3f80 100644 --- a/Mage.Sets/src/mage/sets/UrzasLegacy.java +++ b/Mage.Sets/src/mage/sets/UrzasLegacy.java @@ -1,172 +1,175 @@ - -package mage.sets; - -import mage.cards.ExpansionSet; -import mage.constants.Rarity; -import mage.constants.SetType; - -/** - * - * @author noxx - */ -public final class UrzasLegacy extends ExpansionSet { - - private static final UrzasLegacy instance = new UrzasLegacy(); - - public static UrzasLegacy getInstance() { - return instance; - } - - private UrzasLegacy() { - super("Urza's Legacy", "ULG", ExpansionSet.buildDate(1999, 2, 15), SetType.EXPANSION); - this.blockName = "Urza"; - this.parentSet = UrzasSaga.getInstance(); - this.hasBasicLands = false; - this.hasBoosters = true; - this.numBoosterLands = 0; - this.numBoosterCommon = 11; - this.numBoosterUncommon = 3; - this.numBoosterRare = 1; - this.ratioBoosterMythic = 0; - cards.add(new SetCardInfo("About Face", 73, Rarity.COMMON, mage.cards.a.AboutFace.class)); - cards.add(new SetCardInfo("Angel's Trumpet", 121, Rarity.UNCOMMON, mage.cards.a.AngelsTrumpet.class)); - cards.add(new SetCardInfo("Angelic Curator", 1, Rarity.COMMON, mage.cards.a.AngelicCurator.class)); - cards.add(new SetCardInfo("Anthroplasm", 25, Rarity.RARE, mage.cards.a.Anthroplasm.class)); - cards.add(new SetCardInfo("Archivist", 26, Rarity.RARE, mage.cards.a.Archivist.class)); - cards.add(new SetCardInfo("Aura Flux", 27, Rarity.COMMON, mage.cards.a.AuraFlux.class)); - cards.add(new SetCardInfo("Avalanche Riders", 74, Rarity.UNCOMMON, mage.cards.a.AvalancheRiders.class)); - cards.add(new SetCardInfo("Beast of Burden", 122, Rarity.RARE, mage.cards.b.BeastOfBurden.class)); - cards.add(new SetCardInfo("Blessed Reversal", 2, Rarity.RARE, mage.cards.b.BlessedReversal.class)); - cards.add(new SetCardInfo("Bloated Toad", 97, Rarity.UNCOMMON, mage.cards.b.BloatedToad.class)); - cards.add(new SetCardInfo("Bone Shredder", 49, Rarity.UNCOMMON, mage.cards.b.BoneShredder.class)); - cards.add(new SetCardInfo("Bouncing Beebles", 28, Rarity.COMMON, mage.cards.b.BouncingBeebles.class)); - cards.add(new SetCardInfo("Brink of Madness", 50, Rarity.RARE, mage.cards.b.BrinkOfMadness.class)); - cards.add(new SetCardInfo("Burst of Energy", 3, Rarity.COMMON, mage.cards.b.BurstOfEnergy.class)); - cards.add(new SetCardInfo("Cessation", 4, Rarity.COMMON, mage.cards.c.Cessation.class)); - cards.add(new SetCardInfo("Cloud of Faeries", 29, Rarity.COMMON, mage.cards.c.CloudOfFaeries.class)); - cards.add(new SetCardInfo("Crawlspace", 123, Rarity.RARE, mage.cards.c.Crawlspace.class)); - cards.add(new SetCardInfo("Crop Rotation", 98, Rarity.COMMON, mage.cards.c.CropRotation.class)); - cards.add(new SetCardInfo("Damping Engine", 124, Rarity.RARE, mage.cards.d.DampingEngine.class)); - cards.add(new SetCardInfo("Darkwatch Elves", 99, Rarity.UNCOMMON, mage.cards.d.DarkwatchElves.class)); - cards.add(new SetCardInfo("Defender of Chaos", 75, Rarity.COMMON, mage.cards.d.DefenderOfChaos.class)); - cards.add(new SetCardInfo("Defender of Law", 5, Rarity.COMMON, mage.cards.d.DefenderOfLaw.class)); - cards.add(new SetCardInfo("Defense Grid", 125, Rarity.RARE, mage.cards.d.DefenseGrid.class)); - cards.add(new SetCardInfo("Defense of the Heart", 100, Rarity.RARE, mage.cards.d.DefenseOfTheHeart.class)); - cards.add(new SetCardInfo("Delusions of Mediocrity", 30, Rarity.RARE, mage.cards.d.DelusionsOfMediocrity.class)); - cards.add(new SetCardInfo("Deranged Hermit", 101, Rarity.RARE, mage.cards.d.DerangedHermit.class)); - cards.add(new SetCardInfo("Devout Harpist", 6, Rarity.COMMON, mage.cards.d.DevoutHarpist.class)); - cards.add(new SetCardInfo("Engineered Plague", 51, Rarity.UNCOMMON, mage.cards.e.EngineeredPlague.class)); - cards.add(new SetCardInfo("Erase", 7, Rarity.COMMON, mage.cards.e.Erase.class)); - cards.add(new SetCardInfo("Eviscerator", 52, Rarity.RARE, mage.cards.e.Eviscerator.class)); - cards.add(new SetCardInfo("Expendable Troops", 8, Rarity.COMMON, mage.cards.e.ExpendableTroops.class)); - cards.add(new SetCardInfo("Faerie Conclave", 139, Rarity.UNCOMMON, mage.cards.f.FaerieConclave.class)); - cards.add(new SetCardInfo("Fleeting Image", 31, Rarity.RARE, mage.cards.f.FleetingImage.class)); - cards.add(new SetCardInfo("Fog of Gnats", 53, Rarity.COMMON, mage.cards.f.FogOfGnats.class)); - cards.add(new SetCardInfo("Forbidding Watchtower", 140, Rarity.UNCOMMON, mage.cards.f.ForbiddingWatchtower.class)); - cards.add(new SetCardInfo("Frantic Search", 32, Rarity.COMMON, mage.cards.f.FranticSearch.class)); - cards.add(new SetCardInfo("Gang of Elk", 102, Rarity.UNCOMMON, mage.cards.g.GangOfElk.class)); - cards.add(new SetCardInfo("Ghitu Encampment", 141, Rarity.UNCOMMON, mage.cards.g.GhituEncampment.class)); - cards.add(new SetCardInfo("Ghitu Fire-Eater", 76, Rarity.UNCOMMON, mage.cards.g.GhituFireEater.class)); - cards.add(new SetCardInfo("Ghitu Slinger", 77, Rarity.COMMON, mage.cards.g.GhituSlinger.class)); - cards.add(new SetCardInfo("Ghitu War Cry", 78, Rarity.UNCOMMON, mage.cards.g.GhituWarCry.class)); - cards.add(new SetCardInfo("Giant Cockroach", 54, Rarity.COMMON, mage.cards.g.GiantCockroach.class)); - cards.add(new SetCardInfo("Goblin Medics", 79, Rarity.COMMON, mage.cards.g.GoblinMedics.class)); - cards.add(new SetCardInfo("Goblin Welder", 80, Rarity.RARE, mage.cards.g.GoblinWelder.class)); - cards.add(new SetCardInfo("Granite Grip", 81, Rarity.COMMON, mage.cards.g.GraniteGrip.class)); - cards.add(new SetCardInfo("Grim Monolith", 126, Rarity.RARE, mage.cards.g.GrimMonolith.class)); - cards.add(new SetCardInfo("Harmonic Convergence", 103, Rarity.UNCOMMON, mage.cards.h.HarmonicConvergence.class)); - cards.add(new SetCardInfo("Hidden Gibbons", 104, Rarity.RARE, mage.cards.h.HiddenGibbons.class)); - cards.add(new SetCardInfo("Hope and Glory", 9, Rarity.UNCOMMON, mage.cards.h.HopeAndGlory.class)); - cards.add(new SetCardInfo("Impending Disaster", 82, Rarity.RARE, mage.cards.i.ImpendingDisaster.class)); - cards.add(new SetCardInfo("Intervene", 33, Rarity.COMMON, mage.cards.i.Intervene.class)); - cards.add(new SetCardInfo("Iron Maiden", 127, Rarity.RARE, mage.cards.i.IronMaiden.class)); - cards.add(new SetCardInfo("Iron Will", 10, Rarity.COMMON, mage.cards.i.IronWill.class)); - cards.add(new SetCardInfo("Jhoira's Toolbox", 128, Rarity.UNCOMMON, mage.cards.j.JhoirasToolbox.class)); - cards.add(new SetCardInfo("Karmic Guide", 11, Rarity.RARE, mage.cards.k.KarmicGuide.class)); - cards.add(new SetCardInfo("King Crab", 34, Rarity.UNCOMMON, mage.cards.k.KingCrab.class)); - cards.add(new SetCardInfo("Knighthood", 12, Rarity.UNCOMMON, mage.cards.k.Knighthood.class)); - cards.add(new SetCardInfo("Last-Ditch Effort", 83, Rarity.UNCOMMON, mage.cards.l.LastDitchEffort.class)); - cards.add(new SetCardInfo("Lava Axe", 84, Rarity.COMMON, mage.cards.l.LavaAxe.class)); - cards.add(new SetCardInfo("Levitation", 35, Rarity.UNCOMMON, mage.cards.l.Levitation.class)); - cards.add(new SetCardInfo("Lone Wolf", 105, Rarity.UNCOMMON, mage.cards.l.LoneWolf.class)); - cards.add(new SetCardInfo("Martyr's Cause", 13, Rarity.UNCOMMON, mage.cards.m.MartyrsCause.class)); - cards.add(new SetCardInfo("Memory Jar", 129, Rarity.RARE, mage.cards.m.MemoryJar.class)); - cards.add(new SetCardInfo("Might of Oaks", 106, Rarity.RARE, mage.cards.m.MightOfOaks.class)); - cards.add(new SetCardInfo("Miscalculation", 36, Rarity.COMMON, mage.cards.m.Miscalculation.class)); - cards.add(new SetCardInfo("Molten Hydra", 85, Rarity.RARE, mage.cards.m.MoltenHydra.class)); - cards.add(new SetCardInfo("Mother of Runes", 14, Rarity.UNCOMMON, mage.cards.m.MotherOfRunes.class)); - cards.add(new SetCardInfo("Multani's Acolyte", 108, Rarity.COMMON, mage.cards.m.MultanisAcolyte.class)); - cards.add(new SetCardInfo("Multani's Presence", 109, Rarity.UNCOMMON, mage.cards.m.MultanisPresence.class)); - cards.add(new SetCardInfo("Multani, Maro-Sorcerer", 107, Rarity.RARE, mage.cards.m.MultaniMaroSorcerer.class)); - cards.add(new SetCardInfo("No Mercy", 56, Rarity.RARE, mage.cards.n.NoMercy.class)); - cards.add(new SetCardInfo("Opal Champion", 16, Rarity.COMMON, mage.cards.o.OpalChampion.class)); - cards.add(new SetCardInfo("Opportunity", 37, Rarity.UNCOMMON, mage.cards.o.Opportunity.class)); - cards.add(new SetCardInfo("Ostracize", 57, Rarity.COMMON, mage.cards.o.Ostracize.class)); - cards.add(new SetCardInfo("Palinchron", 38, Rarity.RARE, mage.cards.p.Palinchron.class)); - cards.add(new SetCardInfo("Parch", 86, Rarity.COMMON, mage.cards.p.Parch.class)); - cards.add(new SetCardInfo("Peace and Quiet", 17, Rarity.UNCOMMON, mage.cards.p.PeaceAndQuiet.class)); - cards.add(new SetCardInfo("Phyrexian Broodlings", 58, Rarity.COMMON, mage.cards.p.PhyrexianBroodlings.class)); - cards.add(new SetCardInfo("Phyrexian Debaser", 59, Rarity.COMMON, mage.cards.p.PhyrexianDebaser.class)); - cards.add(new SetCardInfo("Phyrexian Defiler", 60, Rarity.UNCOMMON, mage.cards.p.PhyrexianDefiler.class)); - cards.add(new SetCardInfo("Phyrexian Denouncer", 61, Rarity.COMMON, mage.cards.p.PhyrexianDenouncer.class)); - cards.add(new SetCardInfo("Phyrexian Plaguelord", 62, Rarity.RARE, mage.cards.p.PhyrexianPlaguelord.class)); - cards.add(new SetCardInfo("Phyrexian Reclamation", 63, Rarity.UNCOMMON, mage.cards.p.PhyrexianReclamation.class)); - cards.add(new SetCardInfo("Plague Beetle", 64, Rarity.COMMON, mage.cards.p.PlagueBeetle.class)); - cards.add(new SetCardInfo("Planar Collapse", 18, Rarity.RARE, mage.cards.p.PlanarCollapse.class)); - cards.add(new SetCardInfo("Purify", 19, Rarity.RARE, mage.cards.p.Purify.class)); - cards.add(new SetCardInfo("Pygmy Pyrosaur", 87, Rarity.COMMON, mage.cards.p.PygmyPyrosaur.class)); - cards.add(new SetCardInfo("Pyromancy", 88, Rarity.RARE, mage.cards.p.Pyromancy.class)); - cards.add(new SetCardInfo("Quicksilver Amulet", 130, Rarity.RARE, mage.cards.q.QuicksilverAmulet.class)); - cards.add(new SetCardInfo("Rack and Ruin", 89, Rarity.UNCOMMON, mage.cards.r.RackAndRuin.class)); - cards.add(new SetCardInfo("Radiant's Dragoons", 21, Rarity.UNCOMMON, mage.cards.r.RadiantsDragoons.class)); - cards.add(new SetCardInfo("Radiant's Judgment", 22, Rarity.COMMON, mage.cards.r.RadiantsJudgment.class)); - cards.add(new SetCardInfo("Radiant, Archangel", 20, Rarity.RARE, mage.cards.r.RadiantArchangel.class)); - cards.add(new SetCardInfo("Rancor", 110, Rarity.COMMON, mage.cards.r.Rancor.class)); - cards.add(new SetCardInfo("Rank and File", 65, Rarity.UNCOMMON, mage.cards.r.RankAndFile.class)); - cards.add(new SetCardInfo("Raven Familiar", 39, Rarity.UNCOMMON, mage.cards.r.RavenFamiliar.class)); - cards.add(new SetCardInfo("Rebuild", 40, Rarity.UNCOMMON, mage.cards.r.Rebuild.class)); - cards.add(new SetCardInfo("Repopulate", 111, Rarity.COMMON, mage.cards.r.Repopulate.class)); - cards.add(new SetCardInfo("Ring of Gix", 131, Rarity.RARE, mage.cards.r.RingOfGix.class)); - cards.add(new SetCardInfo("Rivalry", 90, Rarity.RARE, mage.cards.r.Rivalry.class)); - cards.add(new SetCardInfo("Scrapheap", 132, Rarity.RARE, mage.cards.s.Scrapheap.class)); - cards.add(new SetCardInfo("Second Chance", 41, Rarity.RARE, mage.cards.s.SecondChance.class)); - cards.add(new SetCardInfo("Shivan Phoenix", 91, Rarity.RARE, mage.cards.s.ShivanPhoenix.class)); - cards.add(new SetCardInfo("Sick and Tired", 66, Rarity.COMMON, mage.cards.s.SickAndTired.class)); - cards.add(new SetCardInfo("Silk Net", 112, Rarity.COMMON, mage.cards.s.SilkNet.class)); - cards.add(new SetCardInfo("Simian Grunts", 113, Rarity.COMMON, mage.cards.s.SimianGrunts.class)); - cards.add(new SetCardInfo("Sleeper's Guile", 67, Rarity.COMMON, mage.cards.s.SleepersGuile.class)); - cards.add(new SetCardInfo("Slow Motion", 42, Rarity.COMMON, mage.cards.s.SlowMotion.class)); - cards.add(new SetCardInfo("Sluggishness", 92, Rarity.COMMON, mage.cards.s.Sluggishness.class)); - cards.add(new SetCardInfo("Snap", 43, Rarity.COMMON, mage.cards.s.Snap.class)); - cards.add(new SetCardInfo("Spawning Pool", 142, Rarity.UNCOMMON, mage.cards.s.SpawningPool.class)); - cards.add(new SetCardInfo("Subversion", 68, Rarity.RARE, mage.cards.s.Subversion.class)); - cards.add(new SetCardInfo("Sustainer of the Realm", 23, Rarity.UNCOMMON, mage.cards.s.SustainerOfTheRealm.class)); - cards.add(new SetCardInfo("Swat", 69, Rarity.COMMON, mage.cards.s.Swat.class)); - cards.add(new SetCardInfo("Tethered Skirge", 70, Rarity.UNCOMMON, mage.cards.t.TetheredSkirge.class)); - cards.add(new SetCardInfo("Thornwind Faeries", 44, Rarity.COMMON, mage.cards.t.ThornwindFaeries.class)); - cards.add(new SetCardInfo("Thran Lens", 133, Rarity.RARE, mage.cards.t.ThranLens.class)); - cards.add(new SetCardInfo("Thran War Machine", 134, Rarity.UNCOMMON, mage.cards.t.ThranWarMachine.class)); - cards.add(new SetCardInfo("Thran Weaponry", 135, Rarity.RARE, mage.cards.t.ThranWeaponry.class)); - cards.add(new SetCardInfo("Ticking Gnomes", 136, Rarity.UNCOMMON, mage.cards.t.TickingGnomes.class)); - cards.add(new SetCardInfo("Tinker", 45, Rarity.UNCOMMON, mage.cards.t.Tinker.class)); - cards.add(new SetCardInfo("Tragic Poet", 24, Rarity.COMMON, mage.cards.t.TragicPoet.class)); - cards.add(new SetCardInfo("Treacherous Link", 71, Rarity.UNCOMMON, mage.cards.t.TreacherousLink.class)); - cards.add(new SetCardInfo("Treefolk Mystic", 114, Rarity.COMMON, mage.cards.t.TreefolkMystic.class)); - cards.add(new SetCardInfo("Treetop Village", 143, Rarity.UNCOMMON, mage.cards.t.TreetopVillage.class)); - cards.add(new SetCardInfo("Unearth", 72, Rarity.COMMON, mage.cards.u.Unearth.class)); - cards.add(new SetCardInfo("Urza's Blueprints", 137, Rarity.RARE, mage.cards.u.UrzasBlueprints.class)); - cards.add(new SetCardInfo("Viashino Cutthroat", 94, Rarity.UNCOMMON, mage.cards.v.ViashinoCutthroat.class)); - cards.add(new SetCardInfo("Viashino Heretic", 95, Rarity.UNCOMMON, mage.cards.v.ViashinoHeretic.class)); - cards.add(new SetCardInfo("Viashino Sandscout", 96, Rarity.COMMON, mage.cards.v.ViashinoSandscout.class)); - cards.add(new SetCardInfo("Vigilant Drake", 46, Rarity.COMMON, mage.cards.v.VigilantDrake.class)); - cards.add(new SetCardInfo("Walking Sponge", 47, Rarity.UNCOMMON, mage.cards.w.WalkingSponge.class)); - cards.add(new SetCardInfo("Weatherseed Elf", 115, Rarity.COMMON, mage.cards.w.WeatherseedElf.class)); - cards.add(new SetCardInfo("Weatherseed Faeries", 48, Rarity.COMMON, mage.cards.w.WeatherseedFaeries.class)); - cards.add(new SetCardInfo("Weatherseed Treefolk", 116, Rarity.RARE, mage.cards.w.WeatherseedTreefolk.class)); - cards.add(new SetCardInfo("Wheel of Torture", 138, Rarity.RARE, mage.cards.w.WheelOfTorture.class)); - cards.add(new SetCardInfo("Wing Snare", 117, Rarity.UNCOMMON, mage.cards.w.WingSnare.class)); - cards.add(new SetCardInfo("Yavimaya Granger", 118, Rarity.COMMON, mage.cards.y.YavimayaGranger.class)); - cards.add(new SetCardInfo("Yavimaya Scion", 119, Rarity.COMMON, mage.cards.y.YavimayaScion.class)); - cards.add(new SetCardInfo("Yavimaya Wurm", 120, Rarity.COMMON, mage.cards.y.YavimayaWurm.class)); - } -} + +package mage.sets; + +import mage.cards.ExpansionSet; +import mage.constants.Rarity; +import mage.constants.SetType; + +/** + * + * @author noxx + */ +public final class UrzasLegacy extends ExpansionSet { + + private static final UrzasLegacy instance = new UrzasLegacy(); + + public static UrzasLegacy getInstance() { + return instance; + } + + private UrzasLegacy() { + super("Urza's Legacy", "ULG", ExpansionSet.buildDate(1999, 2, 15), SetType.EXPANSION); + this.blockName = "Urza"; + this.parentSet = UrzasSaga.getInstance(); + this.hasBasicLands = false; + this.hasBoosters = true; + this.numBoosterLands = 0; + this.numBoosterCommon = 11; + this.numBoosterUncommon = 3; + this.numBoosterRare = 1; + this.ratioBoosterMythic = 0; + cards.add(new SetCardInfo("About Face", 73, Rarity.COMMON, mage.cards.a.AboutFace.class)); + cards.add(new SetCardInfo("Angel's Trumpet", 121, Rarity.UNCOMMON, mage.cards.a.AngelsTrumpet.class)); + cards.add(new SetCardInfo("Angelic Curator", 1, Rarity.COMMON, mage.cards.a.AngelicCurator.class)); + cards.add(new SetCardInfo("Anthroplasm", 25, Rarity.RARE, mage.cards.a.Anthroplasm.class)); + cards.add(new SetCardInfo("Archivist", 26, Rarity.RARE, mage.cards.a.Archivist.class)); + cards.add(new SetCardInfo("Aura Flux", 27, Rarity.COMMON, mage.cards.a.AuraFlux.class)); + cards.add(new SetCardInfo("Avalanche Riders", 74, Rarity.UNCOMMON, mage.cards.a.AvalancheRiders.class)); + cards.add(new SetCardInfo("Beast of Burden", 122, Rarity.RARE, mage.cards.b.BeastOfBurden.class)); + cards.add(new SetCardInfo("Blessed Reversal", 2, Rarity.RARE, mage.cards.b.BlessedReversal.class)); + cards.add(new SetCardInfo("Bloated Toad", 97, Rarity.UNCOMMON, mage.cards.b.BloatedToad.class)); + cards.add(new SetCardInfo("Bone Shredder", 49, Rarity.UNCOMMON, mage.cards.b.BoneShredder.class)); + cards.add(new SetCardInfo("Bouncing Beebles", 28, Rarity.COMMON, mage.cards.b.BouncingBeebles.class)); + cards.add(new SetCardInfo("Brink of Madness", 50, Rarity.RARE, mage.cards.b.BrinkOfMadness.class)); + cards.add(new SetCardInfo("Burst of Energy", 3, Rarity.COMMON, mage.cards.b.BurstOfEnergy.class)); + cards.add(new SetCardInfo("Cessation", 4, Rarity.COMMON, mage.cards.c.Cessation.class)); + cards.add(new SetCardInfo("Cloud of Faeries", 29, Rarity.COMMON, mage.cards.c.CloudOfFaeries.class)); + cards.add(new SetCardInfo("Crawlspace", 123, Rarity.RARE, mage.cards.c.Crawlspace.class)); + cards.add(new SetCardInfo("Crop Rotation", 98, Rarity.COMMON, mage.cards.c.CropRotation.class)); + cards.add(new SetCardInfo("Damping Engine", 124, Rarity.RARE, mage.cards.d.DampingEngine.class)); + cards.add(new SetCardInfo("Darkwatch Elves", 99, Rarity.UNCOMMON, mage.cards.d.DarkwatchElves.class)); + cards.add(new SetCardInfo("Defender of Chaos", 75, Rarity.COMMON, mage.cards.d.DefenderOfChaos.class)); + cards.add(new SetCardInfo("Defender of Law", 5, Rarity.COMMON, mage.cards.d.DefenderOfLaw.class)); + cards.add(new SetCardInfo("Defense Grid", 125, Rarity.RARE, mage.cards.d.DefenseGrid.class)); + cards.add(new SetCardInfo("Defense of the Heart", 100, Rarity.RARE, mage.cards.d.DefenseOfTheHeart.class)); + cards.add(new SetCardInfo("Delusions of Mediocrity", 30, Rarity.RARE, mage.cards.d.DelusionsOfMediocrity.class)); + cards.add(new SetCardInfo("Deranged Hermit", 101, Rarity.RARE, mage.cards.d.DerangedHermit.class)); + cards.add(new SetCardInfo("Devout Harpist", 6, Rarity.COMMON, mage.cards.d.DevoutHarpist.class)); + cards.add(new SetCardInfo("Engineered Plague", 51, Rarity.UNCOMMON, mage.cards.e.EngineeredPlague.class)); + cards.add(new SetCardInfo("Erase", 7, Rarity.COMMON, mage.cards.e.Erase.class)); + cards.add(new SetCardInfo("Eviscerator", 52, Rarity.RARE, mage.cards.e.Eviscerator.class)); + cards.add(new SetCardInfo("Expendable Troops", 8, Rarity.COMMON, mage.cards.e.ExpendableTroops.class)); + cards.add(new SetCardInfo("Faerie Conclave", 139, Rarity.UNCOMMON, mage.cards.f.FaerieConclave.class)); + cards.add(new SetCardInfo("Fleeting Image", 31, Rarity.RARE, mage.cards.f.FleetingImage.class)); + cards.add(new SetCardInfo("Fog of Gnats", 53, Rarity.COMMON, mage.cards.f.FogOfGnats.class)); + cards.add(new SetCardInfo("Forbidding Watchtower", 140, Rarity.UNCOMMON, mage.cards.f.ForbiddingWatchtower.class)); + cards.add(new SetCardInfo("Frantic Search", 32, Rarity.COMMON, mage.cards.f.FranticSearch.class)); + cards.add(new SetCardInfo("Gang of Elk", 102, Rarity.UNCOMMON, mage.cards.g.GangOfElk.class)); + cards.add(new SetCardInfo("Ghitu Encampment", 141, Rarity.UNCOMMON, mage.cards.g.GhituEncampment.class)); + cards.add(new SetCardInfo("Ghitu Fire-Eater", 76, Rarity.UNCOMMON, mage.cards.g.GhituFireEater.class)); + cards.add(new SetCardInfo("Ghitu Slinger", 77, Rarity.COMMON, mage.cards.g.GhituSlinger.class)); + cards.add(new SetCardInfo("Ghitu War Cry", 78, Rarity.UNCOMMON, mage.cards.g.GhituWarCry.class)); + cards.add(new SetCardInfo("Giant Cockroach", 54, Rarity.COMMON, mage.cards.g.GiantCockroach.class)); + cards.add(new SetCardInfo("Goblin Medics", 79, Rarity.COMMON, mage.cards.g.GoblinMedics.class)); + cards.add(new SetCardInfo("Goblin Welder", 80, Rarity.RARE, mage.cards.g.GoblinWelder.class)); + cards.add(new SetCardInfo("Granite Grip", 81, Rarity.COMMON, mage.cards.g.GraniteGrip.class)); + cards.add(new SetCardInfo("Grim Monolith", 126, Rarity.RARE, mage.cards.g.GrimMonolith.class)); + cards.add(new SetCardInfo("Harmonic Convergence", 103, Rarity.UNCOMMON, mage.cards.h.HarmonicConvergence.class)); + cards.add(new SetCardInfo("Hidden Gibbons", 104, Rarity.RARE, mage.cards.h.HiddenGibbons.class)); + cards.add(new SetCardInfo("Hope and Glory", 9, Rarity.UNCOMMON, mage.cards.h.HopeAndGlory.class)); + cards.add(new SetCardInfo("Impending Disaster", 82, Rarity.RARE, mage.cards.i.ImpendingDisaster.class)); + cards.add(new SetCardInfo("Intervene", 33, Rarity.COMMON, mage.cards.i.Intervene.class)); + cards.add(new SetCardInfo("Iron Maiden", 127, Rarity.RARE, mage.cards.i.IronMaiden.class)); + cards.add(new SetCardInfo("Iron Will", 10, Rarity.COMMON, mage.cards.i.IronWill.class)); + cards.add(new SetCardInfo("Jhoira's Toolbox", 128, Rarity.UNCOMMON, mage.cards.j.JhoirasToolbox.class)); + cards.add(new SetCardInfo("Karmic Guide", 11, Rarity.RARE, mage.cards.k.KarmicGuide.class)); + cards.add(new SetCardInfo("King Crab", 34, Rarity.UNCOMMON, mage.cards.k.KingCrab.class)); + cards.add(new SetCardInfo("Knighthood", 12, Rarity.UNCOMMON, mage.cards.k.Knighthood.class)); + cards.add(new SetCardInfo("Last-Ditch Effort", 83, Rarity.UNCOMMON, mage.cards.l.LastDitchEffort.class)); + cards.add(new SetCardInfo("Lava Axe", 84, Rarity.COMMON, mage.cards.l.LavaAxe.class)); + cards.add(new SetCardInfo("Levitation", 35, Rarity.UNCOMMON, mage.cards.l.Levitation.class)); + cards.add(new SetCardInfo("Lone Wolf", 105, Rarity.UNCOMMON, mage.cards.l.LoneWolf.class)); + cards.add(new SetCardInfo("Lurking Skirge", 55, Rarity.RARE, mage.cards.l.LurkingSkirge.class)); + cards.add(new SetCardInfo("Martyr's Cause", 13, Rarity.UNCOMMON, mage.cards.m.MartyrsCause.class)); + cards.add(new SetCardInfo("Memory Jar", 129, Rarity.RARE, mage.cards.m.MemoryJar.class)); + cards.add(new SetCardInfo("Might of Oaks", 106, Rarity.RARE, mage.cards.m.MightOfOaks.class)); + cards.add(new SetCardInfo("Miscalculation", 36, Rarity.COMMON, mage.cards.m.Miscalculation.class)); + cards.add(new SetCardInfo("Molten Hydra", 85, Rarity.RARE, mage.cards.m.MoltenHydra.class)); + cards.add(new SetCardInfo("Mother of Runes", 14, Rarity.UNCOMMON, mage.cards.m.MotherOfRunes.class)); + cards.add(new SetCardInfo("Multani's Acolyte", 108, Rarity.COMMON, mage.cards.m.MultanisAcolyte.class)); + cards.add(new SetCardInfo("Multani's Presence", 109, Rarity.UNCOMMON, mage.cards.m.MultanisPresence.class)); + cards.add(new SetCardInfo("Multani, Maro-Sorcerer", 107, Rarity.RARE, mage.cards.m.MultaniMaroSorcerer.class)); + cards.add(new SetCardInfo("No Mercy", 56, Rarity.RARE, mage.cards.n.NoMercy.class)); + cards.add(new SetCardInfo("Opal Avenger", 15, Rarity.RARE, mage.cards.o.OpalAvenger.class)); + cards.add(new SetCardInfo("Opal Champion", 16, Rarity.COMMON, mage.cards.o.OpalChampion.class)); + cards.add(new SetCardInfo("Opportunity", 37, Rarity.UNCOMMON, mage.cards.o.Opportunity.class)); + cards.add(new SetCardInfo("Ostracize", 57, Rarity.COMMON, mage.cards.o.Ostracize.class)); + cards.add(new SetCardInfo("Palinchron", 38, Rarity.RARE, mage.cards.p.Palinchron.class)); + cards.add(new SetCardInfo("Parch", 86, Rarity.COMMON, mage.cards.p.Parch.class)); + cards.add(new SetCardInfo("Peace and Quiet", 17, Rarity.UNCOMMON, mage.cards.p.PeaceAndQuiet.class)); + cards.add(new SetCardInfo("Phyrexian Broodlings", 58, Rarity.COMMON, mage.cards.p.PhyrexianBroodlings.class)); + cards.add(new SetCardInfo("Phyrexian Debaser", 59, Rarity.COMMON, mage.cards.p.PhyrexianDebaser.class)); + cards.add(new SetCardInfo("Phyrexian Defiler", 60, Rarity.UNCOMMON, mage.cards.p.PhyrexianDefiler.class)); + cards.add(new SetCardInfo("Phyrexian Denouncer", 61, Rarity.COMMON, mage.cards.p.PhyrexianDenouncer.class)); + cards.add(new SetCardInfo("Phyrexian Plaguelord", 62, Rarity.RARE, mage.cards.p.PhyrexianPlaguelord.class)); + cards.add(new SetCardInfo("Phyrexian Reclamation", 63, Rarity.UNCOMMON, mage.cards.p.PhyrexianReclamation.class)); + cards.add(new SetCardInfo("Plague Beetle", 64, Rarity.COMMON, mage.cards.p.PlagueBeetle.class)); + cards.add(new SetCardInfo("Planar Collapse", 18, Rarity.RARE, mage.cards.p.PlanarCollapse.class)); + cards.add(new SetCardInfo("Purify", 19, Rarity.RARE, mage.cards.p.Purify.class)); + cards.add(new SetCardInfo("Pygmy Pyrosaur", 87, Rarity.COMMON, mage.cards.p.PygmyPyrosaur.class)); + cards.add(new SetCardInfo("Pyromancy", 88, Rarity.RARE, mage.cards.p.Pyromancy.class)); + cards.add(new SetCardInfo("Quicksilver Amulet", 130, Rarity.RARE, mage.cards.q.QuicksilverAmulet.class)); + cards.add(new SetCardInfo("Rack and Ruin", 89, Rarity.UNCOMMON, mage.cards.r.RackAndRuin.class)); + cards.add(new SetCardInfo("Radiant's Dragoons", 21, Rarity.UNCOMMON, mage.cards.r.RadiantsDragoons.class)); + cards.add(new SetCardInfo("Radiant's Judgment", 22, Rarity.COMMON, mage.cards.r.RadiantsJudgment.class)); + cards.add(new SetCardInfo("Radiant, Archangel", 20, Rarity.RARE, mage.cards.r.RadiantArchangel.class)); + cards.add(new SetCardInfo("Rancor", 110, Rarity.COMMON, mage.cards.r.Rancor.class)); + cards.add(new SetCardInfo("Rank and File", 65, Rarity.UNCOMMON, mage.cards.r.RankAndFile.class)); + cards.add(new SetCardInfo("Raven Familiar", 39, Rarity.UNCOMMON, mage.cards.r.RavenFamiliar.class)); + cards.add(new SetCardInfo("Rebuild", 40, Rarity.UNCOMMON, mage.cards.r.Rebuild.class)); + cards.add(new SetCardInfo("Repopulate", 111, Rarity.COMMON, mage.cards.r.Repopulate.class)); + cards.add(new SetCardInfo("Ring of Gix", 131, Rarity.RARE, mage.cards.r.RingOfGix.class)); + cards.add(new SetCardInfo("Rivalry", 90, Rarity.RARE, mage.cards.r.Rivalry.class)); + cards.add(new SetCardInfo("Scrapheap", 132, Rarity.RARE, mage.cards.s.Scrapheap.class)); + cards.add(new SetCardInfo("Second Chance", 41, Rarity.RARE, mage.cards.s.SecondChance.class)); + cards.add(new SetCardInfo("Shivan Phoenix", 91, Rarity.RARE, mage.cards.s.ShivanPhoenix.class)); + cards.add(new SetCardInfo("Sick and Tired", 66, Rarity.COMMON, mage.cards.s.SickAndTired.class)); + cards.add(new SetCardInfo("Silk Net", 112, Rarity.COMMON, mage.cards.s.SilkNet.class)); + cards.add(new SetCardInfo("Simian Grunts", 113, Rarity.COMMON, mage.cards.s.SimianGrunts.class)); + cards.add(new SetCardInfo("Sleeper's Guile", 67, Rarity.COMMON, mage.cards.s.SleepersGuile.class)); + cards.add(new SetCardInfo("Slow Motion", 42, Rarity.COMMON, mage.cards.s.SlowMotion.class)); + cards.add(new SetCardInfo("Sluggishness", 92, Rarity.COMMON, mage.cards.s.Sluggishness.class)); + cards.add(new SetCardInfo("Snap", 43, Rarity.COMMON, mage.cards.s.Snap.class)); + cards.add(new SetCardInfo("Spawning Pool", 142, Rarity.UNCOMMON, mage.cards.s.SpawningPool.class)); + cards.add(new SetCardInfo("Subversion", 68, Rarity.RARE, mage.cards.s.Subversion.class)); + cards.add(new SetCardInfo("Sustainer of the Realm", 23, Rarity.UNCOMMON, mage.cards.s.SustainerOfTheRealm.class)); + cards.add(new SetCardInfo("Swat", 69, Rarity.COMMON, mage.cards.s.Swat.class)); + cards.add(new SetCardInfo("Tethered Skirge", 70, Rarity.UNCOMMON, mage.cards.t.TetheredSkirge.class)); + cards.add(new SetCardInfo("Thornwind Faeries", 44, Rarity.COMMON, mage.cards.t.ThornwindFaeries.class)); + cards.add(new SetCardInfo("Thran Lens", 133, Rarity.RARE, mage.cards.t.ThranLens.class)); + cards.add(new SetCardInfo("Thran War Machine", 134, Rarity.UNCOMMON, mage.cards.t.ThranWarMachine.class)); + cards.add(new SetCardInfo("Thran Weaponry", 135, Rarity.RARE, mage.cards.t.ThranWeaponry.class)); + cards.add(new SetCardInfo("Ticking Gnomes", 136, Rarity.UNCOMMON, mage.cards.t.TickingGnomes.class)); + cards.add(new SetCardInfo("Tinker", 45, Rarity.UNCOMMON, mage.cards.t.Tinker.class)); + cards.add(new SetCardInfo("Tragic Poet", 24, Rarity.COMMON, mage.cards.t.TragicPoet.class)); + cards.add(new SetCardInfo("Treacherous Link", 71, Rarity.UNCOMMON, mage.cards.t.TreacherousLink.class)); + cards.add(new SetCardInfo("Treefolk Mystic", 114, Rarity.COMMON, mage.cards.t.TreefolkMystic.class)); + cards.add(new SetCardInfo("Treetop Village", 143, Rarity.UNCOMMON, mage.cards.t.TreetopVillage.class)); + cards.add(new SetCardInfo("Unearth", 72, Rarity.COMMON, mage.cards.u.Unearth.class)); + cards.add(new SetCardInfo("Urza's Blueprints", 137, Rarity.RARE, mage.cards.u.UrzasBlueprints.class)); + cards.add(new SetCardInfo("Viashino Bey", 93, Rarity.COMMON, mage.cards.v.ViashinoBey.class)); + cards.add(new SetCardInfo("Viashino Cutthroat", 94, Rarity.UNCOMMON, mage.cards.v.ViashinoCutthroat.class)); + cards.add(new SetCardInfo("Viashino Heretic", 95, Rarity.UNCOMMON, mage.cards.v.ViashinoHeretic.class)); + cards.add(new SetCardInfo("Viashino Sandscout", 96, Rarity.COMMON, mage.cards.v.ViashinoSandscout.class)); + cards.add(new SetCardInfo("Vigilant Drake", 46, Rarity.COMMON, mage.cards.v.VigilantDrake.class)); + cards.add(new SetCardInfo("Walking Sponge", 47, Rarity.UNCOMMON, mage.cards.w.WalkingSponge.class)); + cards.add(new SetCardInfo("Weatherseed Elf", 115, Rarity.COMMON, mage.cards.w.WeatherseedElf.class)); + cards.add(new SetCardInfo("Weatherseed Faeries", 48, Rarity.COMMON, mage.cards.w.WeatherseedFaeries.class)); + cards.add(new SetCardInfo("Weatherseed Treefolk", 116, Rarity.RARE, mage.cards.w.WeatherseedTreefolk.class)); + cards.add(new SetCardInfo("Wheel of Torture", 138, Rarity.RARE, mage.cards.w.WheelOfTorture.class)); + cards.add(new SetCardInfo("Wing Snare", 117, Rarity.UNCOMMON, mage.cards.w.WingSnare.class)); + cards.add(new SetCardInfo("Yavimaya Granger", 118, Rarity.COMMON, mage.cards.y.YavimayaGranger.class)); + cards.add(new SetCardInfo("Yavimaya Scion", 119, Rarity.COMMON, mage.cards.y.YavimayaScion.class)); + cards.add(new SetCardInfo("Yavimaya Wurm", 120, Rarity.COMMON, mage.cards.y.YavimayaWurm.class)); + } +} diff --git a/Mage.Sets/src/mage/sets/UrzasSaga.java b/Mage.Sets/src/mage/sets/UrzasSaga.java index 161a5e42ca6..ab0632ed8ec 100644 --- a/Mage.Sets/src/mage/sets/UrzasSaga.java +++ b/Mage.Sets/src/mage/sets/UrzasSaga.java @@ -1,362 +1,379 @@ -package mage.sets; - -import mage.cards.ExpansionSet; -import mage.constants.Rarity; -import mage.constants.SetType; - -/** - * - * @author Backfir3 - */ -public final class UrzasSaga extends ExpansionSet { - - private static final UrzasSaga instance = new UrzasSaga(); - - public static UrzasSaga getInstance() { - return instance; - } - - private UrzasSaga() { - super("Urza's Saga", "USG", ExpansionSet.buildDate(1998, 10, 12), SetType.EXPANSION); - this.blockName = "Urza"; - this.hasBoosters = true; - this.numBoosterLands = 0; - this.numBoosterCommon = 11; - this.numBoosterUncommon = 3; - this.numBoosterRare = 1; - this.ratioBoosterMythic = 0; - cards.add(new SetCardInfo("Absolute Grace", 1, Rarity.UNCOMMON, mage.cards.a.AbsoluteGrace.class)); - cards.add(new SetCardInfo("Absolute Law", 2, Rarity.UNCOMMON, mage.cards.a.AbsoluteLaw.class)); - cards.add(new SetCardInfo("Abundance", 229, Rarity.RARE, mage.cards.a.Abundance.class)); - cards.add(new SetCardInfo("Abyssal Horror", 115, Rarity.RARE, mage.cards.a.AbyssalHorror.class)); - cards.add(new SetCardInfo("Academy Researchers", 58, Rarity.UNCOMMON, mage.cards.a.AcademyResearchers.class)); - cards.add(new SetCardInfo("Acidic Soil", 172, Rarity.UNCOMMON, mage.cards.a.AcidicSoil.class)); - cards.add(new SetCardInfo("Acridian", 230, Rarity.COMMON, mage.cards.a.Acridian.class)); - cards.add(new SetCardInfo("Albino Troll", 231, Rarity.UNCOMMON, mage.cards.a.AlbinoTroll.class)); - cards.add(new SetCardInfo("Anaconda", 232, Rarity.UNCOMMON, mage.cards.a.Anaconda.class)); - cards.add(new SetCardInfo("Angelic Chorus", 3, Rarity.RARE, mage.cards.a.AngelicChorus.class)); - cards.add(new SetCardInfo("Angelic Page", 4, Rarity.COMMON, mage.cards.a.AngelicPage.class)); - cards.add(new SetCardInfo("Annul", 59, Rarity.COMMON, mage.cards.a.Annul.class)); - cards.add(new SetCardInfo("Arcane Laboratory", 60, Rarity.UNCOMMON, mage.cards.a.ArcaneLaboratory.class)); - cards.add(new SetCardInfo("Arc Lightning", 174, Rarity.COMMON, mage.cards.a.ArcLightning.class)); - cards.add(new SetCardInfo("Argothian Elder", 233, Rarity.UNCOMMON, mage.cards.a.ArgothianElder.class)); - cards.add(new SetCardInfo("Argothian Enchantress", 234, Rarity.RARE, mage.cards.a.ArgothianEnchantress.class)); - cards.add(new SetCardInfo("Argothian Swine", 235, Rarity.COMMON, mage.cards.a.ArgothianSwine.class)); - cards.add(new SetCardInfo("Argothian Wurm", 236, Rarity.RARE, mage.cards.a.ArgothianWurm.class)); - cards.add(new SetCardInfo("Attunement", 61, Rarity.RARE, mage.cards.a.Attunement.class)); - cards.add(new SetCardInfo("Back to Basics", 62, Rarity.RARE, mage.cards.b.BackToBasics.class)); - cards.add(new SetCardInfo("Barrin, Master Wizard", 63, Rarity.RARE, mage.cards.b.BarrinMasterWizard.class)); - cards.add(new SetCardInfo("Barrin's Codex", 286, Rarity.RARE, mage.cards.b.BarrinsCodex.class)); - cards.add(new SetCardInfo("Bedlam", 175, Rarity.RARE, mage.cards.b.Bedlam.class)); - cards.add(new SetCardInfo("Befoul", 116, Rarity.COMMON, mage.cards.b.Befoul.class)); - cards.add(new SetCardInfo("Bereavement", 117, Rarity.UNCOMMON, mage.cards.b.Bereavement.class)); - cards.add(new SetCardInfo("Blanchwood Armor", 237, Rarity.UNCOMMON, mage.cards.b.BlanchwoodArmor.class)); - cards.add(new SetCardInfo("Blanchwood Treefolk", 238, Rarity.COMMON, mage.cards.b.BlanchwoodTreefolk.class)); - cards.add(new SetCardInfo("Blasted Landscape", 319, Rarity.UNCOMMON, mage.cards.b.BlastedLandscape.class)); - cards.add(new SetCardInfo("Blood Vassal", 118, Rarity.COMMON, mage.cards.b.BloodVassal.class)); - cards.add(new SetCardInfo("Bog Raiders", 119, Rarity.COMMON, mage.cards.b.BogRaiders.class)); - cards.add(new SetCardInfo("Brand", 176, Rarity.RARE, mage.cards.b.Brand.class)); - cards.add(new SetCardInfo("Bravado", 177, Rarity.COMMON, mage.cards.b.Bravado.class)); - cards.add(new SetCardInfo("Breach", 120, Rarity.COMMON, mage.cards.b.Breach.class)); - cards.add(new SetCardInfo("Brilliant Halo", 5, Rarity.COMMON, mage.cards.b.BrilliantHalo.class)); - cards.add(new SetCardInfo("Bull Hippo", 239, Rarity.UNCOMMON, mage.cards.b.BullHippo.class)); - cards.add(new SetCardInfo("Bulwark", 178, Rarity.RARE, mage.cards.b.Bulwark.class)); - cards.add(new SetCardInfo("Cackling Fiend", 121, Rarity.COMMON, mage.cards.c.CacklingFiend.class)); - cards.add(new SetCardInfo("Carpet of Flowers", 240, Rarity.UNCOMMON, mage.cards.c.CarpetOfFlowers.class)); - cards.add(new SetCardInfo("Carrion Beetles", 122, Rarity.COMMON, mage.cards.c.CarrionBeetles.class)); - cards.add(new SetCardInfo("Catalog", 64, Rarity.COMMON, mage.cards.c.Catalog.class)); - cards.add(new SetCardInfo("Catastrophe", 6, Rarity.RARE, mage.cards.c.Catastrophe.class)); - cards.add(new SetCardInfo("Cathodion", 287, Rarity.UNCOMMON, mage.cards.c.Cathodion.class)); - cards.add(new SetCardInfo("Cave Tiger", 241, Rarity.COMMON, mage.cards.c.CaveTiger.class)); - cards.add(new SetCardInfo("Child of Gaea", 242, Rarity.RARE, mage.cards.c.ChildOfGaea.class)); - cards.add(new SetCardInfo("Chimeric Staff", 288, Rarity.RARE, mage.cards.c.ChimericStaff.class)); - cards.add(new SetCardInfo("Citanul Centaurs", 243, Rarity.RARE, mage.cards.c.CitanulCentaurs.class)); - cards.add(new SetCardInfo("Citanul Flute", 289, Rarity.RARE, mage.cards.c.CitanulFlute.class)); - cards.add(new SetCardInfo("Citanul Hierophants", 244, Rarity.RARE, mage.cards.c.CitanulHierophants.class)); - cards.add(new SetCardInfo("Claws of Gix", 290, Rarity.UNCOMMON, mage.cards.c.ClawsOfGix.class)); - cards.add(new SetCardInfo("Clear", 7, Rarity.UNCOMMON, mage.cards.c.Clear.class)); - cards.add(new SetCardInfo("Cloak of Mists", 65, Rarity.COMMON, mage.cards.c.CloakOfMists.class)); - cards.add(new SetCardInfo("Confiscate", 66, Rarity.UNCOMMON, mage.cards.c.Confiscate.class)); - cards.add(new SetCardInfo("Congregate", 8, Rarity.COMMON, mage.cards.c.Congregate.class)); - cards.add(new SetCardInfo("Contamination", 123, Rarity.RARE, mage.cards.c.Contamination.class)); - cards.add(new SetCardInfo("Copper Gnomes", 291, Rarity.RARE, mage.cards.c.CopperGnomes.class)); - cards.add(new SetCardInfo("Coral Merfolk", 67, Rarity.COMMON, mage.cards.c.CoralMerfolk.class)); - cards.add(new SetCardInfo("Corrupt", 124, Rarity.COMMON, mage.cards.c.Corrupt.class)); - cards.add(new SetCardInfo("Cradle Guard", 245, Rarity.UNCOMMON, mage.cards.c.CradleGuard.class)); - cards.add(new SetCardInfo("Crater Hellion", 179, Rarity.RARE, mage.cards.c.CraterHellion.class)); - cards.add(new SetCardInfo("Crazed Skirge", 125, Rarity.UNCOMMON, mage.cards.c.CrazedSkirge.class)); - cards.add(new SetCardInfo("Crosswinds", 246, Rarity.UNCOMMON, mage.cards.c.Crosswinds.class)); - cards.add(new SetCardInfo("Crystal Chimes", 292, Rarity.UNCOMMON, mage.cards.c.CrystalChimes.class)); - cards.add(new SetCardInfo("Curfew", 68, Rarity.COMMON, mage.cards.c.Curfew.class)); - cards.add(new SetCardInfo("Darkest Hour", 128, Rarity.RARE, mage.cards.d.DarkestHour.class)); - cards.add(new SetCardInfo("Dark Hatchling", 126, Rarity.RARE, mage.cards.d.DarkHatchling.class)); - cards.add(new SetCardInfo("Dark Ritual", 127, Rarity.COMMON, mage.cards.d.DarkRitual.class)); - cards.add(new SetCardInfo("Defensive Formation", 9, Rarity.UNCOMMON, mage.cards.d.DefensiveFormation.class)); - cards.add(new SetCardInfo("Despondency", 129, Rarity.COMMON, mage.cards.d.Despondency.class)); - cards.add(new SetCardInfo("Destructive Urge", 180, Rarity.UNCOMMON, mage.cards.d.DestructiveUrge.class)); - cards.add(new SetCardInfo("Diabolic Servitude", 130, Rarity.UNCOMMON, mage.cards.d.DiabolicServitude.class)); - cards.add(new SetCardInfo("Disciple of Grace", 10, Rarity.COMMON, mage.cards.d.DiscipleOfGrace.class)); - cards.add(new SetCardInfo("Disciple of Law", 11, Rarity.COMMON, mage.cards.d.DiscipleOfLaw.class)); - cards.add(new SetCardInfo("Disenchant", 12, Rarity.COMMON, mage.cards.d.Disenchant.class)); - cards.add(new SetCardInfo("Disorder", 181, Rarity.UNCOMMON, mage.cards.d.Disorder.class)); - cards.add(new SetCardInfo("Disruptive Student", 69, Rarity.COMMON, mage.cards.d.DisruptiveStudent.class)); - cards.add(new SetCardInfo("Douse", 70, Rarity.UNCOMMON, mage.cards.d.Douse.class)); - cards.add(new SetCardInfo("Dragon Blood", 293, Rarity.UNCOMMON, mage.cards.d.DragonBlood.class)); - cards.add(new SetCardInfo("Drifting Djinn", 71, Rarity.RARE, mage.cards.d.DriftingDjinn.class)); - cards.add(new SetCardInfo("Drifting Meadow", 320, Rarity.COMMON, mage.cards.d.DriftingMeadow.class)); - cards.add(new SetCardInfo("Dromosaur", 182, Rarity.COMMON, mage.cards.d.Dromosaur.class)); - cards.add(new SetCardInfo("Duress", 132, Rarity.COMMON, mage.cards.d.Duress.class)); - cards.add(new SetCardInfo("Eastern Paladin", 133, Rarity.RARE, mage.cards.e.EasternPaladin.class)); - cards.add(new SetCardInfo("Electryte", 183, Rarity.RARE, mage.cards.e.Electryte.class)); - cards.add(new SetCardInfo("Elite Archers", 13, Rarity.RARE, mage.cards.e.EliteArchers.class)); - cards.add(new SetCardInfo("Elvish Herder", 247, Rarity.COMMON, mage.cards.e.ElvishHerder.class)); - cards.add(new SetCardInfo("Elvish Lyrist", 248, Rarity.COMMON, mage.cards.e.ElvishLyrist.class)); - cards.add(new SetCardInfo("Endless Wurm", 249, Rarity.RARE, mage.cards.e.EndlessWurm.class)); - cards.add(new SetCardInfo("Endoskeleton", 294, Rarity.UNCOMMON, mage.cards.e.Endoskeleton.class)); - cards.add(new SetCardInfo("Energy Field", 73, Rarity.RARE, mage.cards.e.EnergyField.class)); - cards.add(new SetCardInfo("Exhaustion", 74, Rarity.UNCOMMON, mage.cards.e.Exhaustion.class)); - cards.add(new SetCardInfo("Exhume", 134, Rarity.COMMON, mage.cards.e.Exhume.class)); - cards.add(new SetCardInfo("Exploration", 250, Rarity.RARE, mage.cards.e.Exploration.class)); - cards.add(new SetCardInfo("Expunge", 135, Rarity.COMMON, mage.cards.e.Expunge.class)); - cards.add(new SetCardInfo("Faith Healer", 14, Rarity.RARE, mage.cards.f.FaithHealer.class)); - cards.add(new SetCardInfo("Falter", 184, Rarity.COMMON, mage.cards.f.Falter.class)); - cards.add(new SetCardInfo("Fault Line", 185, Rarity.RARE, mage.cards.f.FaultLine.class)); - cards.add(new SetCardInfo("Fecundity", 251, Rarity.UNCOMMON, mage.cards.f.Fecundity.class)); - cards.add(new SetCardInfo("Fertile Ground", 252, Rarity.COMMON, mage.cards.f.FertileGround.class)); - cards.add(new SetCardInfo("Fiery Mantle", 186, Rarity.COMMON, mage.cards.f.FieryMantle.class)); - cards.add(new SetCardInfo("Fire Ants", 187, Rarity.UNCOMMON, mage.cards.f.FireAnts.class)); - cards.add(new SetCardInfo("Flesh Reaver", 136, Rarity.UNCOMMON, mage.cards.f.FleshReaver.class)); - cards.add(new SetCardInfo("Fluctuator", 295, Rarity.RARE, mage.cards.f.Fluctuator.class)); - cards.add(new SetCardInfo("Fog Bank", 75, Rarity.UNCOMMON, mage.cards.f.FogBank.class)); - cards.add(new SetCardInfo("Forest", 347, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Forest", 348, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Forest", 349, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Forest", 350, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Fortitude", 253, Rarity.COMMON, mage.cards.f.Fortitude.class)); - cards.add(new SetCardInfo("Gaea's Bounty", 254, Rarity.COMMON, mage.cards.g.GaeasBounty.class)); - cards.add(new SetCardInfo("Gaea's Cradle", 321, Rarity.RARE, mage.cards.g.GaeasCradle.class)); - cards.add(new SetCardInfo("Gaea's Embrace", 255, Rarity.UNCOMMON, mage.cards.g.GaeasEmbrace.class)); - cards.add(new SetCardInfo("Gamble", 188, Rarity.RARE, mage.cards.g.Gamble.class)); - cards.add(new SetCardInfo("Gilded Drake", 76, Rarity.RARE, mage.cards.g.GildedDrake.class)); - cards.add(new SetCardInfo("Glorious Anthem", 15, Rarity.RARE, mage.cards.g.GloriousAnthem.class)); - cards.add(new SetCardInfo("Goblin Cadets", 189, Rarity.UNCOMMON, mage.cards.g.GoblinCadets.class)); - cards.add(new SetCardInfo("Goblin Lackey", 190, Rarity.UNCOMMON, mage.cards.g.GoblinLackey.class)); - cards.add(new SetCardInfo("Goblin Matron", 191, Rarity.COMMON, mage.cards.g.GoblinMatron.class)); - cards.add(new SetCardInfo("Goblin Offensive", 192, Rarity.UNCOMMON, mage.cards.g.GoblinOffensive.class)); - cards.add(new SetCardInfo("Goblin Patrol", 193, Rarity.COMMON, mage.cards.g.GoblinPatrol.class)); - cards.add(new SetCardInfo("Goblin Raider", 194, Rarity.COMMON, mage.cards.g.GoblinRaider.class)); - cards.add(new SetCardInfo("Goblin Spelunkers", 195, Rarity.COMMON, mage.cards.g.GoblinSpelunkers.class)); - cards.add(new SetCardInfo("Goblin War Buggy", 196, Rarity.COMMON, mage.cards.g.GoblinWarBuggy.class)); - cards.add(new SetCardInfo("Gorilla Warrior", 256, Rarity.COMMON, mage.cards.g.GorillaWarrior.class)); - cards.add(new SetCardInfo("Grafted Skullcap", 296, Rarity.RARE, mage.cards.g.GraftedSkullcap.class)); - cards.add(new SetCardInfo("Greater Good", 257, Rarity.RARE, mage.cards.g.GreaterGood.class)); - cards.add(new SetCardInfo("Great Whale", 77, Rarity.RARE, mage.cards.g.GreatWhale.class)); - cards.add(new SetCardInfo("Greener Pastures", 258, Rarity.RARE, mage.cards.g.GreenerPastures.class)); - cards.add(new SetCardInfo("Guma", 197, Rarity.UNCOMMON, mage.cards.g.Guma.class)); - cards.add(new SetCardInfo("Hawkeater Moth", 259, Rarity.UNCOMMON, mage.cards.h.HawkeaterMoth.class)); - cards.add(new SetCardInfo("Headlong Rush", 198, Rarity.COMMON, mage.cards.h.HeadlongRush.class)); - cards.add(new SetCardInfo("Healing Salve", 16, Rarity.COMMON, mage.cards.h.HealingSalve.class)); - cards.add(new SetCardInfo("Heat Ray", 199, Rarity.COMMON, mage.cards.h.HeatRay.class)); - cards.add(new SetCardInfo("Herald of Serra", 17, Rarity.RARE, mage.cards.h.HeraldOfSerra.class)); - cards.add(new SetCardInfo("Hermetic Study", 78, Rarity.COMMON, mage.cards.h.HermeticStudy.class)); - cards.add(new SetCardInfo("Hibernation", 79, Rarity.UNCOMMON, mage.cards.h.Hibernation.class)); - cards.add(new SetCardInfo("Hidden Ancients", 260, Rarity.UNCOMMON, mage.cards.h.HiddenAncients.class)); - cards.add(new SetCardInfo("Hidden Guerrillas", 261, Rarity.UNCOMMON, mage.cards.h.HiddenGuerrillas.class)); - cards.add(new SetCardInfo("Hidden Herd", 262, Rarity.RARE, mage.cards.h.HiddenHerd.class)); - cards.add(new SetCardInfo("Hidden Spider", 264, Rarity.COMMON, mage.cards.h.HiddenSpider.class)); - cards.add(new SetCardInfo("Hollow Dogs", 137, Rarity.COMMON, mage.cards.h.HollowDogs.class)); - cards.add(new SetCardInfo("Hopping Automaton", 297, Rarity.UNCOMMON, mage.cards.h.HoppingAutomaton.class)); - cards.add(new SetCardInfo("Horseshoe Crab", 80, Rarity.COMMON, mage.cards.h.HorseshoeCrab.class)); - cards.add(new SetCardInfo("Humble", 18, Rarity.UNCOMMON, mage.cards.h.Humble.class)); - cards.add(new SetCardInfo("Hush", 266, Rarity.COMMON, mage.cards.h.Hush.class)); - cards.add(new SetCardInfo("Ill-Gotten Gains", 138, Rarity.RARE, mage.cards.i.IllGottenGains.class)); - cards.add(new SetCardInfo("Imaginary Pet", 81, Rarity.RARE, mage.cards.i.ImaginaryPet.class)); - cards.add(new SetCardInfo("Intrepid Hero", 19, Rarity.RARE, mage.cards.i.IntrepidHero.class)); - cards.add(new SetCardInfo("Island", 335, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Island", 336, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Island", 337, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Island", 338, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Jagged Lightning", 200, Rarity.UNCOMMON, mage.cards.j.JaggedLightning.class)); - cards.add(new SetCardInfo("Karn, Silver Golem", 298, Rarity.RARE, mage.cards.k.KarnSilverGolem.class)); - cards.add(new SetCardInfo("Launch", 82, Rarity.COMMON, mage.cards.l.Launch.class)); - cards.add(new SetCardInfo("Lay Waste", 201, Rarity.COMMON, mage.cards.l.LayWaste.class)); - cards.add(new SetCardInfo("Lifeline", 299, Rarity.RARE, mage.cards.l.Lifeline.class)); - cards.add(new SetCardInfo("Lightning Dragon", 202, Rarity.RARE, mage.cards.l.LightningDragon.class)); - cards.add(new SetCardInfo("Lilting Refrain", 83, Rarity.UNCOMMON, mage.cards.l.LiltingRefrain.class)); - cards.add(new SetCardInfo("Lingering Mirage", 84, Rarity.UNCOMMON, mage.cards.l.LingeringMirage.class)); - cards.add(new SetCardInfo("Looming Shade", 139, Rarity.COMMON, mage.cards.l.LoomingShade.class)); - cards.add(new SetCardInfo("Lotus Blossom", 300, Rarity.RARE, mage.cards.l.LotusBlossom.class)); - cards.add(new SetCardInfo("Lull", 267, Rarity.COMMON, mage.cards.l.Lull.class)); - cards.add(new SetCardInfo("Lurking Evil", 140, Rarity.RARE, mage.cards.l.LurkingEvil.class)); - cards.add(new SetCardInfo("Mana Leech", 141, Rarity.UNCOMMON, mage.cards.m.ManaLeech.class)); - cards.add(new SetCardInfo("Meltdown", 203, Rarity.UNCOMMON, mage.cards.m.Meltdown.class)); - cards.add(new SetCardInfo("Metrognome", 301, Rarity.RARE, mage.cards.m.Metrognome.class)); - cards.add(new SetCardInfo("Midsummer Revel", 268, Rarity.RARE, mage.cards.m.MidsummerRevel.class)); - cards.add(new SetCardInfo("Mishra's Helix", 302, Rarity.RARE, mage.cards.m.MishrasHelix.class)); - cards.add(new SetCardInfo("Mobile Fort", 303, Rarity.UNCOMMON, mage.cards.m.MobileFort.class)); - cards.add(new SetCardInfo("Monk Idealist", 20, Rarity.UNCOMMON, mage.cards.m.MonkIdealist.class)); - cards.add(new SetCardInfo("Monk Realist", 21, Rarity.COMMON, mage.cards.m.MonkRealist.class)); - cards.add(new SetCardInfo("Morphling", 85, Rarity.RARE, mage.cards.m.Morphling.class)); - cards.add(new SetCardInfo("Mountain", 343, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Mountain", 344, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Mountain", 345, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Mountain", 346, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("No Rest for the Wicked", 142, Rarity.UNCOMMON, mage.cards.n.NoRestForTheWicked.class)); - cards.add(new SetCardInfo("Noetic Scales", 304, Rarity.RARE, mage.cards.n.NoeticScales.class)); - cards.add(new SetCardInfo("Okk", 204, Rarity.RARE, mage.cards.o.Okk.class)); - cards.add(new SetCardInfo("Opal Archangel", 23, Rarity.RARE, mage.cards.o.OpalArchangel.class)); - cards.add(new SetCardInfo("Opal Caryatid", 24, Rarity.COMMON, mage.cards.o.OpalCaryatid.class)); - cards.add(new SetCardInfo("Opal Gargoyle", 25, Rarity.COMMON, mage.cards.o.OpalGargoyle.class)); - cards.add(new SetCardInfo("Oppression", 143, Rarity.RARE, mage.cards.o.Oppression.class)); - cards.add(new SetCardInfo("Order of Yawgmoth", 144, Rarity.UNCOMMON, mage.cards.o.OrderOfYawgmoth.class)); - cards.add(new SetCardInfo("Pacifism", 27, Rarity.COMMON, mage.cards.p.Pacifism.class)); - cards.add(new SetCardInfo("Parasitic Bond", 145, Rarity.UNCOMMON, mage.cards.p.ParasiticBond.class)); - cards.add(new SetCardInfo("Pariah", 28, Rarity.RARE, mage.cards.p.Pariah.class)); - cards.add(new SetCardInfo("Path of Peace", 29, Rarity.COMMON, mage.cards.p.PathOfPeace.class)); - cards.add(new SetCardInfo("Pegasus Charger", 30, Rarity.COMMON, mage.cards.p.PegasusCharger.class)); - cards.add(new SetCardInfo("Pendrell Drake", 86, Rarity.COMMON, mage.cards.p.PendrellDrake.class)); - cards.add(new SetCardInfo("Pendrell Flux", 87, Rarity.COMMON, mage.cards.p.PendrellFlux.class)); - cards.add(new SetCardInfo("Peregrine Drake", 88, Rarity.UNCOMMON, mage.cards.p.PeregrineDrake.class)); - cards.add(new SetCardInfo("Persecute", 146, Rarity.RARE, mage.cards.p.Persecute.class)); - cards.add(new SetCardInfo("Pestilence", 147, Rarity.COMMON, mage.cards.p.Pestilence.class)); - cards.add(new SetCardInfo("Phyrexian Colossus", 305, Rarity.RARE, mage.cards.p.PhyrexianColossus.class)); - cards.add(new SetCardInfo("Phyrexian Ghoul", 148, Rarity.COMMON, mage.cards.p.PhyrexianGhoul.class)); - cards.add(new SetCardInfo("Phyrexian Processor", 306, Rarity.RARE, mage.cards.p.PhyrexianProcessor.class)); - cards.add(new SetCardInfo("Phyrexian Tower", 322, Rarity.RARE, mage.cards.p.PhyrexianTower.class)); - cards.add(new SetCardInfo("Pit Trap", 307, Rarity.UNCOMMON, mage.cards.p.PitTrap.class)); - cards.add(new SetCardInfo("Plains", 331, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Plains", 332, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Plains", 333, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Plains", 334, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Planar Birth", 31, Rarity.RARE, mage.cards.p.PlanarBirth.class)); - cards.add(new SetCardInfo("Planar Void", 149, Rarity.UNCOMMON, mage.cards.p.PlanarVoid.class)); - cards.add(new SetCardInfo("Polluted Mire", 323, Rarity.COMMON, mage.cards.p.PollutedMire.class)); - cards.add(new SetCardInfo("Pouncing Jaguar", 269, Rarity.COMMON, mage.cards.p.PouncingJaguar.class)); - cards.add(new SetCardInfo("Power Sink", 89, Rarity.COMMON, mage.cards.p.PowerSink.class)); - cards.add(new SetCardInfo("Presence of the Master", 32, Rarity.UNCOMMON, mage.cards.p.PresenceOfTheMaster.class)); - cards.add(new SetCardInfo("Priest of Gix", 150, Rarity.UNCOMMON, mage.cards.p.PriestOfGix.class)); - cards.add(new SetCardInfo("Priest of Titania", 270, Rarity.COMMON, mage.cards.p.PriestOfTitania.class)); - cards.add(new SetCardInfo("Purging Scythe", 308, Rarity.RARE, mage.cards.p.PurgingScythe.class)); - cards.add(new SetCardInfo("Rain of Filth", 151, Rarity.UNCOMMON, mage.cards.r.RainOfFilth.class)); - cards.add(new SetCardInfo("Rain of Salt", 206, Rarity.UNCOMMON, mage.cards.r.RainOfSalt.class)); - cards.add(new SetCardInfo("Ravenous Skirge", 152, Rarity.COMMON, mage.cards.r.RavenousSkirge.class)); - cards.add(new SetCardInfo("Raze", 207, Rarity.COMMON, mage.cards.r.Raze.class)); - cards.add(new SetCardInfo("Recantation", 91, Rarity.RARE, mage.cards.r.Recantation.class)); - cards.add(new SetCardInfo("Reclusive Wight", 153, Rarity.UNCOMMON, mage.cards.r.ReclusiveWight.class)); - cards.add(new SetCardInfo("Redeem", 33, Rarity.UNCOMMON, mage.cards.r.Redeem.class)); - cards.add(new SetCardInfo("Reflexes", 208, Rarity.COMMON, mage.cards.r.Reflexes.class)); - cards.add(new SetCardInfo("Rejuvenate", 271, Rarity.COMMON, mage.cards.r.Rejuvenate.class)); - cards.add(new SetCardInfo("Remembrance", 34, Rarity.RARE, mage.cards.r.Remembrance.class)); - cards.add(new SetCardInfo("Remote Isle", 324, Rarity.COMMON, mage.cards.r.RemoteIsle.class)); - cards.add(new SetCardInfo("Reprocess", 154, Rarity.RARE, mage.cards.r.Reprocess.class)); - cards.add(new SetCardInfo("Rescind", 92, Rarity.COMMON, mage.cards.r.Rescind.class)); - cards.add(new SetCardInfo("Retaliation", 272, Rarity.UNCOMMON, mage.cards.r.Retaliation.class)); - cards.add(new SetCardInfo("Retromancer", 209, Rarity.COMMON, mage.cards.r.Retromancer.class)); - cards.add(new SetCardInfo("Rewind", 93, Rarity.COMMON, mage.cards.r.Rewind.class)); - cards.add(new SetCardInfo("Rumbling Crescendo", 210, Rarity.RARE, mage.cards.r.RumblingCrescendo.class)); - cards.add(new SetCardInfo("Rune of Protection: Artifacts", 35, Rarity.UNCOMMON, mage.cards.r.RuneOfProtectionArtifacts.class)); - cards.add(new SetCardInfo("Rune of Protection: Black", 36, Rarity.COMMON, mage.cards.r.RuneOfProtectionBlack.class)); - cards.add(new SetCardInfo("Rune of Protection: Blue", 37, Rarity.COMMON, mage.cards.r.RuneOfProtectionBlue.class)); - cards.add(new SetCardInfo("Rune of Protection: Green", 38, Rarity.COMMON, mage.cards.r.RuneOfProtectionGreen.class)); - cards.add(new SetCardInfo("Rune of Protection: Lands", 39, Rarity.RARE, mage.cards.r.RuneOfProtectionLands.class)); - cards.add(new SetCardInfo("Rune of Protection: Red", 40, Rarity.COMMON, mage.cards.r.RuneOfProtectionRed.class)); - cards.add(new SetCardInfo("Rune of Protection: White", 41, Rarity.COMMON, mage.cards.r.RuneOfProtectionWhite.class)); - cards.add(new SetCardInfo("Sanctum Custodian", 42, Rarity.COMMON, mage.cards.s.SanctumCustodian.class)); - cards.add(new SetCardInfo("Sanctum Guardian", 43, Rarity.UNCOMMON, mage.cards.s.SanctumGuardian.class)); - cards.add(new SetCardInfo("Sandbar Merfolk", 94, Rarity.COMMON, mage.cards.s.SandbarMerfolk.class)); - cards.add(new SetCardInfo("Sandbar Serpent", 95, Rarity.UNCOMMON, mage.cards.s.SandbarSerpent.class)); - cards.add(new SetCardInfo("Sanguine Guard", 155, Rarity.UNCOMMON, mage.cards.s.SanguineGuard.class)); - cards.add(new SetCardInfo("Scald", 211, Rarity.UNCOMMON, mage.cards.s.Scald.class)); - cards.add(new SetCardInfo("Scoria Wurm", 212, Rarity.RARE, mage.cards.s.ScoriaWurm.class)); - cards.add(new SetCardInfo("Scrap", 213, Rarity.COMMON, mage.cards.s.Scrap.class)); - cards.add(new SetCardInfo("Seasoned Marshal", 44, Rarity.UNCOMMON, mage.cards.s.SeasonedMarshal.class)); - cards.add(new SetCardInfo("Serra Avatar", 45, Rarity.RARE, mage.cards.s.SerraAvatar.class)); - cards.add(new SetCardInfo("Serra's Embrace", 47, Rarity.UNCOMMON, mage.cards.s.SerrasEmbrace.class)); - cards.add(new SetCardInfo("Serra's Liturgy", 49, Rarity.RARE, mage.cards.s.SerrasLiturgy.class)); - cards.add(new SetCardInfo("Serra's Sanctum", 325, Rarity.RARE, mage.cards.s.SerrasSanctum.class)); - cards.add(new SetCardInfo("Serra Zealot", 46, Rarity.COMMON, mage.cards.s.SerraZealot.class)); - cards.add(new SetCardInfo("Shimmering Barrier", 50, Rarity.UNCOMMON, mage.cards.s.ShimmeringBarrier.class)); - cards.add(new SetCardInfo("Shivan Gorge", 326, Rarity.RARE, mage.cards.s.ShivanGorge.class)); - cards.add(new SetCardInfo("Shivan Hellkite", 214, Rarity.RARE, mage.cards.s.ShivanHellkite.class)); - cards.add(new SetCardInfo("Shivan Raptor", 215, Rarity.UNCOMMON, mage.cards.s.ShivanRaptor.class)); - cards.add(new SetCardInfo("Shiv's Embrace", 216, Rarity.UNCOMMON, mage.cards.s.ShivsEmbrace.class)); - cards.add(new SetCardInfo("Show and Tell", 96, Rarity.RARE, mage.cards.s.ShowAndTell.class)); - cards.add(new SetCardInfo("Shower of Sparks", 217, Rarity.COMMON, mage.cards.s.ShowerOfSparks.class)); - cards.add(new SetCardInfo("Sicken", 156, Rarity.COMMON, mage.cards.s.Sicken.class)); - cards.add(new SetCardInfo("Silent Attendant", 51, Rarity.COMMON, mage.cards.s.SilentAttendant.class)); - cards.add(new SetCardInfo("Skirge Familiar", 157, Rarity.UNCOMMON, mage.cards.s.SkirgeFamiliar.class)); - cards.add(new SetCardInfo("Skittering Skirge", 158, Rarity.COMMON, mage.cards.s.SkitteringSkirge.class)); - cards.add(new SetCardInfo("Sleeper Agent", 159, Rarity.RARE, mage.cards.s.SleeperAgent.class)); - cards.add(new SetCardInfo("Slippery Karst", 327, Rarity.COMMON, mage.cards.s.SlipperyKarst.class)); - cards.add(new SetCardInfo("Smokestack", 309, Rarity.RARE, mage.cards.s.Smokestack.class)); - cards.add(new SetCardInfo("Smoldering Crater", 328, Rarity.COMMON, mage.cards.s.SmolderingCrater.class)); - cards.add(new SetCardInfo("Sneak Attack", 218, Rarity.RARE, mage.cards.s.SneakAttack.class)); - cards.add(new SetCardInfo("Somnophore", 97, Rarity.RARE, mage.cards.s.Somnophore.class)); - cards.add(new SetCardInfo("Songstitcher", 52, Rarity.UNCOMMON, mage.cards.s.Songstitcher.class)); - cards.add(new SetCardInfo("Spined Fluke", 160, Rarity.UNCOMMON, mage.cards.s.SpinedFluke.class)); - cards.add(new SetCardInfo("Spire Owl", 98, Rarity.COMMON, mage.cards.s.SpireOwl.class)); - cards.add(new SetCardInfo("Sporogenesis", 273, Rarity.RARE, mage.cards.s.Sporogenesis.class)); - cards.add(new SetCardInfo("Spreading Algae", 274, Rarity.UNCOMMON, mage.cards.s.SpreadingAlgae.class)); - cards.add(new SetCardInfo("Steam Blast", 219, Rarity.UNCOMMON, mage.cards.s.SteamBlast.class)); - cards.add(new SetCardInfo("Stern Proctor", 99, Rarity.UNCOMMON, mage.cards.s.SternProctor.class)); - cards.add(new SetCardInfo("Stroke of Genius", 100, Rarity.RARE, mage.cards.s.StrokeOfGenius.class)); - cards.add(new SetCardInfo("Sulfuric Vapors", 220, Rarity.RARE, mage.cards.s.SulfuricVapors.class)); - cards.add(new SetCardInfo("Sunder", 101, Rarity.RARE, mage.cards.s.Sunder.class)); - cards.add(new SetCardInfo("Swamp", 339, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Swamp", 340, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Swamp", 341, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Swamp", 342, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); - cards.add(new SetCardInfo("Symbiosis", 275, Rarity.COMMON, mage.cards.s.Symbiosis.class)); - cards.add(new SetCardInfo("Tainted Aether", 161, Rarity.RARE, mage.cards.t.TaintedAether.class)); - cards.add(new SetCardInfo("Telepathy", 102, Rarity.UNCOMMON, mage.cards.t.Telepathy.class)); - cards.add(new SetCardInfo("Temporal Aperture", 310, Rarity.RARE, mage.cards.t.TemporalAperture.class)); - cards.add(new SetCardInfo("Thran Quarry", 329, Rarity.RARE, mage.cards.t.ThranQuarry.class)); - cards.add(new SetCardInfo("Thran Turbine", 311, Rarity.UNCOMMON, mage.cards.t.ThranTurbine.class)); - cards.add(new SetCardInfo("Thundering Giant", 221, Rarity.UNCOMMON, mage.cards.t.ThunderingGiant.class)); - cards.add(new SetCardInfo("Time Spiral", 103, Rarity.RARE, mage.cards.t.TimeSpiral.class)); - cards.add(new SetCardInfo("Titania's Boon", 276, Rarity.UNCOMMON, mage.cards.t.TitaniasBoon.class)); - cards.add(new SetCardInfo("Titania's Chosen", 277, Rarity.UNCOMMON, mage.cards.t.TitaniasChosen.class)); - cards.add(new SetCardInfo("Tolarian Academy", 330, Rarity.RARE, mage.cards.t.TolarianAcademy.class)); - cards.add(new SetCardInfo("Tolarian Winds", 104, Rarity.COMMON, mage.cards.t.TolarianWinds.class)); - cards.add(new SetCardInfo("Torch Song", 222, Rarity.UNCOMMON, mage.cards.t.TorchSong.class)); - cards.add(new SetCardInfo("Treefolk Seedlings", 278, Rarity.UNCOMMON, mage.cards.t.TreefolkSeedlings.class)); - cards.add(new SetCardInfo("Treetop Rangers", 279, Rarity.COMMON, mage.cards.t.TreetopRangers.class)); - cards.add(new SetCardInfo("Turnabout", 105, Rarity.UNCOMMON, mage.cards.t.Turnabout.class)); - cards.add(new SetCardInfo("Umbilicus", 312, Rarity.RARE, mage.cards.u.Umbilicus.class)); - cards.add(new SetCardInfo("Unnerve", 162, Rarity.COMMON, mage.cards.u.Unnerve.class)); - cards.add(new SetCardInfo("Unworthy Dead", 163, Rarity.COMMON, mage.cards.u.UnworthyDead.class)); - cards.add(new SetCardInfo("Urza's Armor", 313, Rarity.UNCOMMON, mage.cards.u.UrzasArmor.class)); - cards.add(new SetCardInfo("Vampiric Embrace", 164, Rarity.UNCOMMON, mage.cards.v.VampiricEmbrace.class)); - cards.add(new SetCardInfo("Vebulid", 165, Rarity.RARE, mage.cards.v.Vebulid.class)); - cards.add(new SetCardInfo("Vernal Bloom", 281, Rarity.RARE, mage.cards.v.VernalBloom.class)); - cards.add(new SetCardInfo("Viashino Outrider", 223, Rarity.COMMON, mage.cards.v.ViashinoOutrider.class)); - cards.add(new SetCardInfo("Viashino Runner", 224, Rarity.COMMON, mage.cards.v.ViashinoRunner.class)); - cards.add(new SetCardInfo("Viashino Sandswimmer", 225, Rarity.RARE, mage.cards.v.ViashinoSandswimmer.class)); - cards.add(new SetCardInfo("Viashino Weaponsmith", 226, Rarity.COMMON, mage.cards.v.ViashinoWeaponsmith.class)); - cards.add(new SetCardInfo("Victimize", 166, Rarity.UNCOMMON, mage.cards.v.Victimize.class)); - cards.add(new SetCardInfo("Vile Requiem", 167, Rarity.UNCOMMON, mage.cards.v.VileRequiem.class)); - cards.add(new SetCardInfo("Voice of Grace", 54, Rarity.UNCOMMON, mage.cards.v.VoiceOfGrace.class)); - cards.add(new SetCardInfo("Voice of Law", 55, Rarity.UNCOMMON, mage.cards.v.VoiceOfLaw.class)); - cards.add(new SetCardInfo("Voltaic Key", 314, Rarity.UNCOMMON, mage.cards.v.VoltaicKey.class)); - cards.add(new SetCardInfo("Vug Lizard", 227, Rarity.UNCOMMON, mage.cards.v.VugLizard.class)); - cards.add(new SetCardInfo("War Dance", 282, Rarity.UNCOMMON, mage.cards.w.WarDance.class)); - cards.add(new SetCardInfo("Wall of Junk", 315, Rarity.UNCOMMON, mage.cards.w.WallOfJunk.class)); - cards.add(new SetCardInfo("Waylay", 56, Rarity.UNCOMMON, mage.cards.w.Waylay.class)); - cards.add(new SetCardInfo("Western Paladin", 168, Rarity.RARE, mage.cards.w.WesternPaladin.class)); - cards.add(new SetCardInfo("Whetstone", 316, Rarity.RARE, mage.cards.w.Whetstone.class)); - cards.add(new SetCardInfo("Whirlwind", 283, Rarity.RARE, mage.cards.w.Whirlwind.class)); - cards.add(new SetCardInfo("Wild Dogs", 284, Rarity.COMMON, mage.cards.w.WildDogs.class)); - cards.add(new SetCardInfo("Wildfire", 228, Rarity.RARE, mage.cards.w.Wildfire.class)); - cards.add(new SetCardInfo("Windfall", 111, Rarity.UNCOMMON, mage.cards.w.Windfall.class)); - cards.add(new SetCardInfo("Winding Wurm", 285, Rarity.COMMON, mage.cards.w.WindingWurm.class)); - cards.add(new SetCardInfo("Wirecat", 317, Rarity.UNCOMMON, mage.cards.w.Wirecat.class)); - cards.add(new SetCardInfo("Witch Engine", 169, Rarity.RARE, mage.cards.w.WitchEngine.class)); - cards.add(new SetCardInfo("Wizard Mentor", 112, Rarity.COMMON, mage.cards.w.WizardMentor.class)); - cards.add(new SetCardInfo("Worn Powerstone", 318, Rarity.UNCOMMON, mage.cards.w.WornPowerstone.class)); - cards.add(new SetCardInfo("Worship", 57, Rarity.RARE, mage.cards.w.Worship.class)); - cards.add(new SetCardInfo("Yawgmoth's Edict", 170, Rarity.UNCOMMON, mage.cards.y.YawgmothsEdict.class)); - cards.add(new SetCardInfo("Yawgmoth's Will", 171, Rarity.RARE, mage.cards.y.YawgmothsWill.class)); - cards.add(new SetCardInfo("Zephid", 113, Rarity.RARE, mage.cards.z.Zephid.class)); - cards.add(new SetCardInfo("Zephid's Embrace", 114, Rarity.UNCOMMON, mage.cards.z.ZephidsEmbrace.class)); - } -} +package mage.sets; + +import mage.cards.ExpansionSet; +import mage.constants.Rarity; +import mage.constants.SetType; + +/** + * + * @author Backfir3 + */ +public final class UrzasSaga extends ExpansionSet { + + private static final UrzasSaga instance = new UrzasSaga(); + + public static UrzasSaga getInstance() { + return instance; + } + + private UrzasSaga() { + super("Urza's Saga", "USG", ExpansionSet.buildDate(1998, 10, 12), SetType.EXPANSION); + this.blockName = "Urza"; + this.hasBoosters = true; + this.numBoosterLands = 0; + this.numBoosterCommon = 11; + this.numBoosterUncommon = 3; + this.numBoosterRare = 1; + this.ratioBoosterMythic = 0; + cards.add(new SetCardInfo("Absolute Grace", 1, Rarity.UNCOMMON, mage.cards.a.AbsoluteGrace.class)); + cards.add(new SetCardInfo("Absolute Law", 2, Rarity.UNCOMMON, mage.cards.a.AbsoluteLaw.class)); + cards.add(new SetCardInfo("Abundance", 229, Rarity.RARE, mage.cards.a.Abundance.class)); + cards.add(new SetCardInfo("Abyssal Horror", 115, Rarity.RARE, mage.cards.a.AbyssalHorror.class)); + cards.add(new SetCardInfo("Academy Researchers", 58, Rarity.UNCOMMON, mage.cards.a.AcademyResearchers.class)); + cards.add(new SetCardInfo("Acidic Soil", 172, Rarity.UNCOMMON, mage.cards.a.AcidicSoil.class)); + cards.add(new SetCardInfo("Acridian", 230, Rarity.COMMON, mage.cards.a.Acridian.class)); + cards.add(new SetCardInfo("Albino Troll", 231, Rarity.UNCOMMON, mage.cards.a.AlbinoTroll.class)); + cards.add(new SetCardInfo("Anaconda", 232, Rarity.UNCOMMON, mage.cards.a.Anaconda.class)); + cards.add(new SetCardInfo("Angelic Chorus", 3, Rarity.RARE, mage.cards.a.AngelicChorus.class)); + cards.add(new SetCardInfo("Angelic Page", 4, Rarity.COMMON, mage.cards.a.AngelicPage.class)); + cards.add(new SetCardInfo("Annul", 59, Rarity.COMMON, mage.cards.a.Annul.class)); + cards.add(new SetCardInfo("Antagonism", 173, Rarity.RARE, mage.cards.a.Antagonism.class)); + cards.add(new SetCardInfo("Arcane Laboratory", 60, Rarity.UNCOMMON, mage.cards.a.ArcaneLaboratory.class)); + cards.add(new SetCardInfo("Arc Lightning", 174, Rarity.COMMON, mage.cards.a.ArcLightning.class)); + cards.add(new SetCardInfo("Argothian Elder", 233, Rarity.UNCOMMON, mage.cards.a.ArgothianElder.class)); + cards.add(new SetCardInfo("Argothian Enchantress", 234, Rarity.RARE, mage.cards.a.ArgothianEnchantress.class)); + cards.add(new SetCardInfo("Argothian Swine", 235, Rarity.COMMON, mage.cards.a.ArgothianSwine.class)); + cards.add(new SetCardInfo("Argothian Wurm", 236, Rarity.RARE, mage.cards.a.ArgothianWurm.class)); + cards.add(new SetCardInfo("Attunement", 61, Rarity.RARE, mage.cards.a.Attunement.class)); + cards.add(new SetCardInfo("Back to Basics", 62, Rarity.RARE, mage.cards.b.BackToBasics.class)); + cards.add(new SetCardInfo("Barrin, Master Wizard", 63, Rarity.RARE, mage.cards.b.BarrinMasterWizard.class)); + cards.add(new SetCardInfo("Barrin's Codex", 286, Rarity.RARE, mage.cards.b.BarrinsCodex.class)); + cards.add(new SetCardInfo("Bedlam", 175, Rarity.RARE, mage.cards.b.Bedlam.class)); + cards.add(new SetCardInfo("Befoul", 116, Rarity.COMMON, mage.cards.b.Befoul.class)); + cards.add(new SetCardInfo("Bereavement", 117, Rarity.UNCOMMON, mage.cards.b.Bereavement.class)); + cards.add(new SetCardInfo("Blanchwood Armor", 237, Rarity.UNCOMMON, mage.cards.b.BlanchwoodArmor.class)); + cards.add(new SetCardInfo("Blanchwood Treefolk", 238, Rarity.COMMON, mage.cards.b.BlanchwoodTreefolk.class)); + cards.add(new SetCardInfo("Blasted Landscape", 319, Rarity.UNCOMMON, mage.cards.b.BlastedLandscape.class)); + cards.add(new SetCardInfo("Blood Vassal", 118, Rarity.COMMON, mage.cards.b.BloodVassal.class)); + cards.add(new SetCardInfo("Bog Raiders", 119, Rarity.COMMON, mage.cards.b.BogRaiders.class)); + cards.add(new SetCardInfo("Brand", 176, Rarity.RARE, mage.cards.b.Brand.class)); + cards.add(new SetCardInfo("Bravado", 177, Rarity.COMMON, mage.cards.b.Bravado.class)); + cards.add(new SetCardInfo("Breach", 120, Rarity.COMMON, mage.cards.b.Breach.class)); + cards.add(new SetCardInfo("Brilliant Halo", 5, Rarity.COMMON, mage.cards.b.BrilliantHalo.class)); + cards.add(new SetCardInfo("Bull Hippo", 239, Rarity.UNCOMMON, mage.cards.b.BullHippo.class)); + cards.add(new SetCardInfo("Bulwark", 178, Rarity.RARE, mage.cards.b.Bulwark.class)); + cards.add(new SetCardInfo("Cackling Fiend", 121, Rarity.COMMON, mage.cards.c.CacklingFiend.class)); + cards.add(new SetCardInfo("Carpet of Flowers", 240, Rarity.UNCOMMON, mage.cards.c.CarpetOfFlowers.class)); + cards.add(new SetCardInfo("Carrion Beetles", 122, Rarity.COMMON, mage.cards.c.CarrionBeetles.class)); + cards.add(new SetCardInfo("Catalog", 64, Rarity.COMMON, mage.cards.c.Catalog.class)); + cards.add(new SetCardInfo("Catastrophe", 6, Rarity.RARE, mage.cards.c.Catastrophe.class)); + cards.add(new SetCardInfo("Cathodion", 287, Rarity.UNCOMMON, mage.cards.c.Cathodion.class)); + cards.add(new SetCardInfo("Cave Tiger", 241, Rarity.COMMON, mage.cards.c.CaveTiger.class)); + cards.add(new SetCardInfo("Child of Gaea", 242, Rarity.RARE, mage.cards.c.ChildOfGaea.class)); + cards.add(new SetCardInfo("Chimeric Staff", 288, Rarity.RARE, mage.cards.c.ChimericStaff.class)); + cards.add(new SetCardInfo("Citanul Centaurs", 243, Rarity.RARE, mage.cards.c.CitanulCentaurs.class)); + cards.add(new SetCardInfo("Citanul Flute", 289, Rarity.RARE, mage.cards.c.CitanulFlute.class)); + cards.add(new SetCardInfo("Citanul Hierophants", 244, Rarity.RARE, mage.cards.c.CitanulHierophants.class)); + cards.add(new SetCardInfo("Claws of Gix", 290, Rarity.UNCOMMON, mage.cards.c.ClawsOfGix.class)); + cards.add(new SetCardInfo("Clear", 7, Rarity.UNCOMMON, mage.cards.c.Clear.class)); + cards.add(new SetCardInfo("Cloak of Mists", 65, Rarity.COMMON, mage.cards.c.CloakOfMists.class)); + cards.add(new SetCardInfo("Confiscate", 66, Rarity.UNCOMMON, mage.cards.c.Confiscate.class)); + cards.add(new SetCardInfo("Congregate", 8, Rarity.COMMON, mage.cards.c.Congregate.class)); + cards.add(new SetCardInfo("Contamination", 123, Rarity.RARE, mage.cards.c.Contamination.class)); + cards.add(new SetCardInfo("Copper Gnomes", 291, Rarity.RARE, mage.cards.c.CopperGnomes.class)); + cards.add(new SetCardInfo("Coral Merfolk", 67, Rarity.COMMON, mage.cards.c.CoralMerfolk.class)); + cards.add(new SetCardInfo("Corrupt", 124, Rarity.COMMON, mage.cards.c.Corrupt.class)); + cards.add(new SetCardInfo("Cradle Guard", 245, Rarity.UNCOMMON, mage.cards.c.CradleGuard.class)); + cards.add(new SetCardInfo("Crater Hellion", 179, Rarity.RARE, mage.cards.c.CraterHellion.class)); + cards.add(new SetCardInfo("Crazed Skirge", 125, Rarity.UNCOMMON, mage.cards.c.CrazedSkirge.class)); + cards.add(new SetCardInfo("Crosswinds", 246, Rarity.UNCOMMON, mage.cards.c.Crosswinds.class)); + cards.add(new SetCardInfo("Crystal Chimes", 292, Rarity.UNCOMMON, mage.cards.c.CrystalChimes.class)); + cards.add(new SetCardInfo("Curfew", 68, Rarity.COMMON, mage.cards.c.Curfew.class)); + cards.add(new SetCardInfo("Darkest Hour", 128, Rarity.RARE, mage.cards.d.DarkestHour.class)); + cards.add(new SetCardInfo("Dark Hatchling", 126, Rarity.RARE, mage.cards.d.DarkHatchling.class)); + cards.add(new SetCardInfo("Dark Ritual", 127, Rarity.COMMON, mage.cards.d.DarkRitual.class)); + cards.add(new SetCardInfo("Defensive Formation", 9, Rarity.UNCOMMON, mage.cards.d.DefensiveFormation.class)); + cards.add(new SetCardInfo("Despondency", 129, Rarity.COMMON, mage.cards.d.Despondency.class)); + cards.add(new SetCardInfo("Destructive Urge", 180, Rarity.UNCOMMON, mage.cards.d.DestructiveUrge.class)); + cards.add(new SetCardInfo("Diabolic Servitude", 130, Rarity.UNCOMMON, mage.cards.d.DiabolicServitude.class)); + cards.add(new SetCardInfo("Disciple of Grace", 10, Rarity.COMMON, mage.cards.d.DiscipleOfGrace.class)); + cards.add(new SetCardInfo("Disciple of Law", 11, Rarity.COMMON, mage.cards.d.DiscipleOfLaw.class)); + cards.add(new SetCardInfo("Discordant Dirge", 131, Rarity.RARE, mage.cards.d.DiscordantDirge.class)); + cards.add(new SetCardInfo("Disenchant", 12, Rarity.COMMON, mage.cards.d.Disenchant.class)); + cards.add(new SetCardInfo("Disorder", 181, Rarity.UNCOMMON, mage.cards.d.Disorder.class)); + cards.add(new SetCardInfo("Disruptive Student", 69, Rarity.COMMON, mage.cards.d.DisruptiveStudent.class)); + cards.add(new SetCardInfo("Douse", 70, Rarity.UNCOMMON, mage.cards.d.Douse.class)); + cards.add(new SetCardInfo("Dragon Blood", 293, Rarity.UNCOMMON, mage.cards.d.DragonBlood.class)); + cards.add(new SetCardInfo("Drifting Djinn", 71, Rarity.RARE, mage.cards.d.DriftingDjinn.class)); + cards.add(new SetCardInfo("Drifting Meadow", 320, Rarity.COMMON, mage.cards.d.DriftingMeadow.class)); + cards.add(new SetCardInfo("Dromosaur", 182, Rarity.COMMON, mage.cards.d.Dromosaur.class)); + cards.add(new SetCardInfo("Duress", 132, Rarity.COMMON, mage.cards.d.Duress.class)); + cards.add(new SetCardInfo("Eastern Paladin", 133, Rarity.RARE, mage.cards.e.EasternPaladin.class)); + cards.add(new SetCardInfo("Electryte", 183, Rarity.RARE, mage.cards.e.Electryte.class)); + cards.add(new SetCardInfo("Elite Archers", 13, Rarity.RARE, mage.cards.e.EliteArchers.class)); + cards.add(new SetCardInfo("Elvish Herder", 247, Rarity.COMMON, mage.cards.e.ElvishHerder.class)); + cards.add(new SetCardInfo("Elvish Lyrist", 248, Rarity.COMMON, mage.cards.e.ElvishLyrist.class)); + cards.add(new SetCardInfo("Enchantment Alteration", 72, Rarity.UNCOMMON, mage.cards.e.EnchantmentAlteration.class)); + cards.add(new SetCardInfo("Endless Wurm", 249, Rarity.RARE, mage.cards.e.EndlessWurm.class)); + cards.add(new SetCardInfo("Endoskeleton", 294, Rarity.UNCOMMON, mage.cards.e.Endoskeleton.class)); + cards.add(new SetCardInfo("Energy Field", 73, Rarity.RARE, mage.cards.e.EnergyField.class)); + cards.add(new SetCardInfo("Exhaustion", 74, Rarity.UNCOMMON, mage.cards.e.Exhaustion.class)); + cards.add(new SetCardInfo("Exhume", 134, Rarity.COMMON, mage.cards.e.Exhume.class)); + cards.add(new SetCardInfo("Exploration", 250, Rarity.RARE, mage.cards.e.Exploration.class)); + cards.add(new SetCardInfo("Expunge", 135, Rarity.COMMON, mage.cards.e.Expunge.class)); + cards.add(new SetCardInfo("Faith Healer", 14, Rarity.RARE, mage.cards.f.FaithHealer.class)); + cards.add(new SetCardInfo("Falter", 184, Rarity.COMMON, mage.cards.f.Falter.class)); + cards.add(new SetCardInfo("Fault Line", 185, Rarity.RARE, mage.cards.f.FaultLine.class)); + cards.add(new SetCardInfo("Fecundity", 251, Rarity.UNCOMMON, mage.cards.f.Fecundity.class)); + cards.add(new SetCardInfo("Fertile Ground", 252, Rarity.COMMON, mage.cards.f.FertileGround.class)); + cards.add(new SetCardInfo("Fiery Mantle", 186, Rarity.COMMON, mage.cards.f.FieryMantle.class)); + cards.add(new SetCardInfo("Fire Ants", 187, Rarity.UNCOMMON, mage.cards.f.FireAnts.class)); + cards.add(new SetCardInfo("Flesh Reaver", 136, Rarity.UNCOMMON, mage.cards.f.FleshReaver.class)); + cards.add(new SetCardInfo("Fluctuator", 295, Rarity.RARE, mage.cards.f.Fluctuator.class)); + cards.add(new SetCardInfo("Fog Bank", 75, Rarity.UNCOMMON, mage.cards.f.FogBank.class)); + cards.add(new SetCardInfo("Forest", 347, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Forest", 348, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Forest", 349, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Forest", 350, Rarity.LAND, mage.cards.basiclands.Forest.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Fortitude", 253, Rarity.COMMON, mage.cards.f.Fortitude.class)); + cards.add(new SetCardInfo("Gaea's Bounty", 254, Rarity.COMMON, mage.cards.g.GaeasBounty.class)); + cards.add(new SetCardInfo("Gaea's Cradle", 321, Rarity.RARE, mage.cards.g.GaeasCradle.class)); + cards.add(new SetCardInfo("Gaea's Embrace", 255, Rarity.UNCOMMON, mage.cards.g.GaeasEmbrace.class)); + cards.add(new SetCardInfo("Gamble", 188, Rarity.RARE, mage.cards.g.Gamble.class)); + cards.add(new SetCardInfo("Gilded Drake", 76, Rarity.RARE, mage.cards.g.GildedDrake.class)); + cards.add(new SetCardInfo("Glorious Anthem", 15, Rarity.RARE, mage.cards.g.GloriousAnthem.class)); + cards.add(new SetCardInfo("Goblin Cadets", 189, Rarity.UNCOMMON, mage.cards.g.GoblinCadets.class)); + cards.add(new SetCardInfo("Goblin Lackey", 190, Rarity.UNCOMMON, mage.cards.g.GoblinLackey.class)); + cards.add(new SetCardInfo("Goblin Matron", 191, Rarity.COMMON, mage.cards.g.GoblinMatron.class)); + cards.add(new SetCardInfo("Goblin Offensive", 192, Rarity.UNCOMMON, mage.cards.g.GoblinOffensive.class)); + cards.add(new SetCardInfo("Goblin Patrol", 193, Rarity.COMMON, mage.cards.g.GoblinPatrol.class)); + cards.add(new SetCardInfo("Goblin Raider", 194, Rarity.COMMON, mage.cards.g.GoblinRaider.class)); + cards.add(new SetCardInfo("Goblin Spelunkers", 195, Rarity.COMMON, mage.cards.g.GoblinSpelunkers.class)); + cards.add(new SetCardInfo("Goblin War Buggy", 196, Rarity.COMMON, mage.cards.g.GoblinWarBuggy.class)); + cards.add(new SetCardInfo("Gorilla Warrior", 256, Rarity.COMMON, mage.cards.g.GorillaWarrior.class)); + cards.add(new SetCardInfo("Grafted Skullcap", 296, Rarity.RARE, mage.cards.g.GraftedSkullcap.class)); + cards.add(new SetCardInfo("Greater Good", 257, Rarity.RARE, mage.cards.g.GreaterGood.class)); + cards.add(new SetCardInfo("Great Whale", 77, Rarity.RARE, mage.cards.g.GreatWhale.class)); + cards.add(new SetCardInfo("Greener Pastures", 258, Rarity.RARE, mage.cards.g.GreenerPastures.class)); + cards.add(new SetCardInfo("Guma", 197, Rarity.UNCOMMON, mage.cards.g.Guma.class)); + cards.add(new SetCardInfo("Hawkeater Moth", 259, Rarity.UNCOMMON, mage.cards.h.HawkeaterMoth.class)); + cards.add(new SetCardInfo("Headlong Rush", 198, Rarity.COMMON, mage.cards.h.HeadlongRush.class)); + cards.add(new SetCardInfo("Healing Salve", 16, Rarity.COMMON, mage.cards.h.HealingSalve.class)); + cards.add(new SetCardInfo("Heat Ray", 199, Rarity.COMMON, mage.cards.h.HeatRay.class)); + cards.add(new SetCardInfo("Herald of Serra", 17, Rarity.RARE, mage.cards.h.HeraldOfSerra.class)); + cards.add(new SetCardInfo("Hermetic Study", 78, Rarity.COMMON, mage.cards.h.HermeticStudy.class)); + cards.add(new SetCardInfo("Hibernation", 79, Rarity.UNCOMMON, mage.cards.h.Hibernation.class)); + cards.add(new SetCardInfo("Hidden Ancients", 260, Rarity.UNCOMMON, mage.cards.h.HiddenAncients.class)); + cards.add(new SetCardInfo("Hidden Guerrillas", 261, Rarity.UNCOMMON, mage.cards.h.HiddenGuerrillas.class)); + cards.add(new SetCardInfo("Hidden Herd", 262, Rarity.RARE, mage.cards.h.HiddenHerd.class)); + cards.add(new SetCardInfo("Hidden Predators", 263, Rarity.RARE, mage.cards.h.HiddenPredators.class)); + cards.add(new SetCardInfo("Hidden Spider", 264, Rarity.COMMON, mage.cards.h.HiddenSpider.class)); + cards.add(new SetCardInfo("Hidden Stag", 265, Rarity.RARE, mage.cards.h.HiddenStag.class)); + cards.add(new SetCardInfo("Hollow Dogs", 137, Rarity.COMMON, mage.cards.h.HollowDogs.class)); + cards.add(new SetCardInfo("Hopping Automaton", 297, Rarity.UNCOMMON, mage.cards.h.HoppingAutomaton.class)); + cards.add(new SetCardInfo("Horseshoe Crab", 80, Rarity.COMMON, mage.cards.h.HorseshoeCrab.class)); + cards.add(new SetCardInfo("Humble", 18, Rarity.UNCOMMON, mage.cards.h.Humble.class)); + cards.add(new SetCardInfo("Hush", 266, Rarity.COMMON, mage.cards.h.Hush.class)); + cards.add(new SetCardInfo("Ill-Gotten Gains", 138, Rarity.RARE, mage.cards.i.IllGottenGains.class)); + cards.add(new SetCardInfo("Imaginary Pet", 81, Rarity.RARE, mage.cards.i.ImaginaryPet.class)); + cards.add(new SetCardInfo("Intrepid Hero", 19, Rarity.RARE, mage.cards.i.IntrepidHero.class)); + cards.add(new SetCardInfo("Island", 335, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Island", 336, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Island", 337, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Island", 338, Rarity.LAND, mage.cards.basiclands.Island.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Jagged Lightning", 200, Rarity.UNCOMMON, mage.cards.j.JaggedLightning.class)); + cards.add(new SetCardInfo("Karn, Silver Golem", 298, Rarity.RARE, mage.cards.k.KarnSilverGolem.class)); + cards.add(new SetCardInfo("Launch", 82, Rarity.COMMON, mage.cards.l.Launch.class)); + cards.add(new SetCardInfo("Lay Waste", 201, Rarity.COMMON, mage.cards.l.LayWaste.class)); + cards.add(new SetCardInfo("Lifeline", 299, Rarity.RARE, mage.cards.l.Lifeline.class)); + cards.add(new SetCardInfo("Lightning Dragon", 202, Rarity.RARE, mage.cards.l.LightningDragon.class)); + cards.add(new SetCardInfo("Lilting Refrain", 83, Rarity.UNCOMMON, mage.cards.l.LiltingRefrain.class)); + cards.add(new SetCardInfo("Lingering Mirage", 84, Rarity.UNCOMMON, mage.cards.l.LingeringMirage.class)); + cards.add(new SetCardInfo("Looming Shade", 139, Rarity.COMMON, mage.cards.l.LoomingShade.class)); + cards.add(new SetCardInfo("Lotus Blossom", 300, Rarity.RARE, mage.cards.l.LotusBlossom.class)); + cards.add(new SetCardInfo("Lull", 267, Rarity.COMMON, mage.cards.l.Lull.class)); + cards.add(new SetCardInfo("Lurking Evil", 140, Rarity.RARE, mage.cards.l.LurkingEvil.class)); + cards.add(new SetCardInfo("Mana Leech", 141, Rarity.UNCOMMON, mage.cards.m.ManaLeech.class)); + cards.add(new SetCardInfo("Meltdown", 203, Rarity.UNCOMMON, mage.cards.m.Meltdown.class)); + cards.add(new SetCardInfo("Metrognome", 301, Rarity.RARE, mage.cards.m.Metrognome.class)); + cards.add(new SetCardInfo("Midsummer Revel", 268, Rarity.RARE, mage.cards.m.MidsummerRevel.class)); + cards.add(new SetCardInfo("Mishra's Helix", 302, Rarity.RARE, mage.cards.m.MishrasHelix.class)); + cards.add(new SetCardInfo("Mobile Fort", 303, Rarity.UNCOMMON, mage.cards.m.MobileFort.class)); + cards.add(new SetCardInfo("Monk Idealist", 20, Rarity.UNCOMMON, mage.cards.m.MonkIdealist.class)); + cards.add(new SetCardInfo("Monk Realist", 21, Rarity.COMMON, mage.cards.m.MonkRealist.class)); + cards.add(new SetCardInfo("Morphling", 85, Rarity.RARE, mage.cards.m.Morphling.class)); + cards.add(new SetCardInfo("Mountain", 343, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mountain", 344, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mountain", 345, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Mountain", 346, Rarity.LAND, mage.cards.basiclands.Mountain.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("No Rest for the Wicked", 142, Rarity.UNCOMMON, mage.cards.n.NoRestForTheWicked.class)); + cards.add(new SetCardInfo("Noetic Scales", 304, Rarity.RARE, mage.cards.n.NoeticScales.class)); + cards.add(new SetCardInfo("Okk", 204, Rarity.RARE, mage.cards.o.Okk.class)); + cards.add(new SetCardInfo("Opal Acrolith", 22, Rarity.UNCOMMON, mage.cards.o.OpalAcrolith.class)); + cards.add(new SetCardInfo("Opal Archangel", 23, Rarity.RARE, mage.cards.o.OpalArchangel.class)); + cards.add(new SetCardInfo("Opal Caryatid", 24, Rarity.COMMON, mage.cards.o.OpalCaryatid.class)); + cards.add(new SetCardInfo("Opal Gargoyle", 25, Rarity.COMMON, mage.cards.o.OpalGargoyle.class)); + cards.add(new SetCardInfo("Opal Titan", 26, Rarity.RARE, mage.cards.o.OpalTitan.class)); + cards.add(new SetCardInfo("Oppression", 143, Rarity.RARE, mage.cards.o.Oppression.class)); + cards.add(new SetCardInfo("Order of Yawgmoth", 144, Rarity.UNCOMMON, mage.cards.o.OrderOfYawgmoth.class)); + cards.add(new SetCardInfo("Outmaneuver", 205, Rarity.UNCOMMON, mage.cards.o.Outmaneuver.class)); + cards.add(new SetCardInfo("Pacifism", 27, Rarity.COMMON, mage.cards.p.Pacifism.class)); + cards.add(new SetCardInfo("Parasitic Bond", 145, Rarity.UNCOMMON, mage.cards.p.ParasiticBond.class)); + cards.add(new SetCardInfo("Pariah", 28, Rarity.RARE, mage.cards.p.Pariah.class)); + cards.add(new SetCardInfo("Path of Peace", 29, Rarity.COMMON, mage.cards.p.PathOfPeace.class)); + cards.add(new SetCardInfo("Pegasus Charger", 30, Rarity.COMMON, mage.cards.p.PegasusCharger.class)); + cards.add(new SetCardInfo("Pendrell Drake", 86, Rarity.COMMON, mage.cards.p.PendrellDrake.class)); + cards.add(new SetCardInfo("Pendrell Flux", 87, Rarity.COMMON, mage.cards.p.PendrellFlux.class)); + cards.add(new SetCardInfo("Peregrine Drake", 88, Rarity.UNCOMMON, mage.cards.p.PeregrineDrake.class)); + cards.add(new SetCardInfo("Persecute", 146, Rarity.RARE, mage.cards.p.Persecute.class)); + cards.add(new SetCardInfo("Pestilence", 147, Rarity.COMMON, mage.cards.p.Pestilence.class)); + cards.add(new SetCardInfo("Phyrexian Colossus", 305, Rarity.RARE, mage.cards.p.PhyrexianColossus.class)); + cards.add(new SetCardInfo("Phyrexian Ghoul", 148, Rarity.COMMON, mage.cards.p.PhyrexianGhoul.class)); + cards.add(new SetCardInfo("Phyrexian Processor", 306, Rarity.RARE, mage.cards.p.PhyrexianProcessor.class)); + cards.add(new SetCardInfo("Phyrexian Tower", 322, Rarity.RARE, mage.cards.p.PhyrexianTower.class)); + cards.add(new SetCardInfo("Pit Trap", 307, Rarity.UNCOMMON, mage.cards.p.PitTrap.class)); + cards.add(new SetCardInfo("Plains", 331, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Plains", 332, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Plains", 333, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Plains", 334, Rarity.LAND, mage.cards.basiclands.Plains.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Planar Birth", 31, Rarity.RARE, mage.cards.p.PlanarBirth.class)); + cards.add(new SetCardInfo("Planar Void", 149, Rarity.UNCOMMON, mage.cards.p.PlanarVoid.class)); + cards.add(new SetCardInfo("Polluted Mire", 323, Rarity.COMMON, mage.cards.p.PollutedMire.class)); + cards.add(new SetCardInfo("Pouncing Jaguar", 269, Rarity.COMMON, mage.cards.p.PouncingJaguar.class)); + cards.add(new SetCardInfo("Power Sink", 89, Rarity.COMMON, mage.cards.p.PowerSink.class)); + cards.add(new SetCardInfo("Power Taint", 90, Rarity.COMMON, mage.cards.p.PowerTaint.class)); + cards.add(new SetCardInfo("Presence of the Master", 32, Rarity.UNCOMMON, mage.cards.p.PresenceOfTheMaster.class)); + cards.add(new SetCardInfo("Priest of Gix", 150, Rarity.UNCOMMON, mage.cards.p.PriestOfGix.class)); + cards.add(new SetCardInfo("Priest of Titania", 270, Rarity.COMMON, mage.cards.p.PriestOfTitania.class)); + cards.add(new SetCardInfo("Purging Scythe", 308, Rarity.RARE, mage.cards.p.PurgingScythe.class)); + cards.add(new SetCardInfo("Rain of Filth", 151, Rarity.UNCOMMON, mage.cards.r.RainOfFilth.class)); + cards.add(new SetCardInfo("Rain of Salt", 206, Rarity.UNCOMMON, mage.cards.r.RainOfSalt.class)); + cards.add(new SetCardInfo("Ravenous Skirge", 152, Rarity.COMMON, mage.cards.r.RavenousSkirge.class)); + cards.add(new SetCardInfo("Raze", 207, Rarity.COMMON, mage.cards.r.Raze.class)); + cards.add(new SetCardInfo("Recantation", 91, Rarity.RARE, mage.cards.r.Recantation.class)); + cards.add(new SetCardInfo("Reclusive Wight", 153, Rarity.UNCOMMON, mage.cards.r.ReclusiveWight.class)); + cards.add(new SetCardInfo("Redeem", 33, Rarity.UNCOMMON, mage.cards.r.Redeem.class)); + cards.add(new SetCardInfo("Reflexes", 208, Rarity.COMMON, mage.cards.r.Reflexes.class)); + cards.add(new SetCardInfo("Rejuvenate", 271, Rarity.COMMON, mage.cards.r.Rejuvenate.class)); + cards.add(new SetCardInfo("Remembrance", 34, Rarity.RARE, mage.cards.r.Remembrance.class)); + cards.add(new SetCardInfo("Remote Isle", 324, Rarity.COMMON, mage.cards.r.RemoteIsle.class)); + cards.add(new SetCardInfo("Reprocess", 154, Rarity.RARE, mage.cards.r.Reprocess.class)); + cards.add(new SetCardInfo("Rescind", 92, Rarity.COMMON, mage.cards.r.Rescind.class)); + cards.add(new SetCardInfo("Retaliation", 272, Rarity.UNCOMMON, mage.cards.r.Retaliation.class)); + cards.add(new SetCardInfo("Retromancer", 209, Rarity.COMMON, mage.cards.r.Retromancer.class)); + cards.add(new SetCardInfo("Rewind", 93, Rarity.COMMON, mage.cards.r.Rewind.class)); + cards.add(new SetCardInfo("Rumbling Crescendo", 210, Rarity.RARE, mage.cards.r.RumblingCrescendo.class)); + cards.add(new SetCardInfo("Rune of Protection: Artifacts", 35, Rarity.UNCOMMON, mage.cards.r.RuneOfProtectionArtifacts.class)); + cards.add(new SetCardInfo("Rune of Protection: Black", 36, Rarity.COMMON, mage.cards.r.RuneOfProtectionBlack.class)); + cards.add(new SetCardInfo("Rune of Protection: Blue", 37, Rarity.COMMON, mage.cards.r.RuneOfProtectionBlue.class)); + cards.add(new SetCardInfo("Rune of Protection: Green", 38, Rarity.COMMON, mage.cards.r.RuneOfProtectionGreen.class)); + cards.add(new SetCardInfo("Rune of Protection: Lands", 39, Rarity.RARE, mage.cards.r.RuneOfProtectionLands.class)); + cards.add(new SetCardInfo("Rune of Protection: Red", 40, Rarity.COMMON, mage.cards.r.RuneOfProtectionRed.class)); + cards.add(new SetCardInfo("Rune of Protection: White", 41, Rarity.COMMON, mage.cards.r.RuneOfProtectionWhite.class)); + cards.add(new SetCardInfo("Sanctum Custodian", 42, Rarity.COMMON, mage.cards.s.SanctumCustodian.class)); + cards.add(new SetCardInfo("Sanctum Guardian", 43, Rarity.UNCOMMON, mage.cards.s.SanctumGuardian.class)); + cards.add(new SetCardInfo("Sandbar Merfolk", 94, Rarity.COMMON, mage.cards.s.SandbarMerfolk.class)); + cards.add(new SetCardInfo("Sandbar Serpent", 95, Rarity.UNCOMMON, mage.cards.s.SandbarSerpent.class)); + cards.add(new SetCardInfo("Sanguine Guard", 155, Rarity.UNCOMMON, mage.cards.s.SanguineGuard.class)); + cards.add(new SetCardInfo("Scald", 211, Rarity.UNCOMMON, mage.cards.s.Scald.class)); + cards.add(new SetCardInfo("Scoria Wurm", 212, Rarity.RARE, mage.cards.s.ScoriaWurm.class)); + cards.add(new SetCardInfo("Scrap", 213, Rarity.COMMON, mage.cards.s.Scrap.class)); + cards.add(new SetCardInfo("Seasoned Marshal", 44, Rarity.UNCOMMON, mage.cards.s.SeasonedMarshal.class)); + cards.add(new SetCardInfo("Serra Avatar", 45, Rarity.RARE, mage.cards.s.SerraAvatar.class)); + cards.add(new SetCardInfo("Serra's Embrace", 47, Rarity.UNCOMMON, mage.cards.s.SerrasEmbrace.class)); + cards.add(new SetCardInfo("Serra's Hymn", 48, Rarity.UNCOMMON, mage.cards.s.SerrasHymn.class)); + cards.add(new SetCardInfo("Serra's Liturgy", 49, Rarity.RARE, mage.cards.s.SerrasLiturgy.class)); + cards.add(new SetCardInfo("Serra's Sanctum", 325, Rarity.RARE, mage.cards.s.SerrasSanctum.class)); + cards.add(new SetCardInfo("Serra Zealot", 46, Rarity.COMMON, mage.cards.s.SerraZealot.class)); + cards.add(new SetCardInfo("Shimmering Barrier", 50, Rarity.UNCOMMON, mage.cards.s.ShimmeringBarrier.class)); + cards.add(new SetCardInfo("Shivan Gorge", 326, Rarity.RARE, mage.cards.s.ShivanGorge.class)); + cards.add(new SetCardInfo("Shivan Hellkite", 214, Rarity.RARE, mage.cards.s.ShivanHellkite.class)); + cards.add(new SetCardInfo("Shivan Raptor", 215, Rarity.UNCOMMON, mage.cards.s.ShivanRaptor.class)); + cards.add(new SetCardInfo("Shiv's Embrace", 216, Rarity.UNCOMMON, mage.cards.s.ShivsEmbrace.class)); + cards.add(new SetCardInfo("Show and Tell", 96, Rarity.RARE, mage.cards.s.ShowAndTell.class)); + cards.add(new SetCardInfo("Shower of Sparks", 217, Rarity.COMMON, mage.cards.s.ShowerOfSparks.class)); + cards.add(new SetCardInfo("Sicken", 156, Rarity.COMMON, mage.cards.s.Sicken.class)); + cards.add(new SetCardInfo("Silent Attendant", 51, Rarity.COMMON, mage.cards.s.SilentAttendant.class)); + cards.add(new SetCardInfo("Skirge Familiar", 157, Rarity.UNCOMMON, mage.cards.s.SkirgeFamiliar.class)); + cards.add(new SetCardInfo("Skittering Skirge", 158, Rarity.COMMON, mage.cards.s.SkitteringSkirge.class)); + cards.add(new SetCardInfo("Sleeper Agent", 159, Rarity.RARE, mage.cards.s.SleeperAgent.class)); + cards.add(new SetCardInfo("Slippery Karst", 327, Rarity.COMMON, mage.cards.s.SlipperyKarst.class)); + cards.add(new SetCardInfo("Smokestack", 309, Rarity.RARE, mage.cards.s.Smokestack.class)); + cards.add(new SetCardInfo("Smoldering Crater", 328, Rarity.COMMON, mage.cards.s.SmolderingCrater.class)); + cards.add(new SetCardInfo("Sneak Attack", 218, Rarity.RARE, mage.cards.s.SneakAttack.class)); + cards.add(new SetCardInfo("Somnophore", 97, Rarity.RARE, mage.cards.s.Somnophore.class)); + cards.add(new SetCardInfo("Songstitcher", 52, Rarity.UNCOMMON, mage.cards.s.Songstitcher.class)); + cards.add(new SetCardInfo("Soul Sculptor", 53, Rarity.RARE, mage.cards.s.SoulSculptor.class)); + cards.add(new SetCardInfo("Spined Fluke", 160, Rarity.UNCOMMON, mage.cards.s.SpinedFluke.class)); + cards.add(new SetCardInfo("Spire Owl", 98, Rarity.COMMON, mage.cards.s.SpireOwl.class)); + cards.add(new SetCardInfo("Sporogenesis", 273, Rarity.RARE, mage.cards.s.Sporogenesis.class)); + cards.add(new SetCardInfo("Spreading Algae", 274, Rarity.UNCOMMON, mage.cards.s.SpreadingAlgae.class)); + cards.add(new SetCardInfo("Steam Blast", 219, Rarity.UNCOMMON, mage.cards.s.SteamBlast.class)); + cards.add(new SetCardInfo("Stern Proctor", 99, Rarity.UNCOMMON, mage.cards.s.SternProctor.class)); + cards.add(new SetCardInfo("Stroke of Genius", 100, Rarity.RARE, mage.cards.s.StrokeOfGenius.class)); + cards.add(new SetCardInfo("Sulfuric Vapors", 220, Rarity.RARE, mage.cards.s.SulfuricVapors.class)); + cards.add(new SetCardInfo("Sunder", 101, Rarity.RARE, mage.cards.s.Sunder.class)); + cards.add(new SetCardInfo("Swamp", 339, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Swamp", 340, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Swamp", 341, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Swamp", 342, Rarity.LAND, mage.cards.basiclands.Swamp.class, NON_FULL_USE_VARIOUS)); + cards.add(new SetCardInfo("Symbiosis", 275, Rarity.COMMON, mage.cards.s.Symbiosis.class)); + cards.add(new SetCardInfo("Tainted Aether", 161, Rarity.RARE, mage.cards.t.TaintedAether.class)); + cards.add(new SetCardInfo("Telepathy", 102, Rarity.UNCOMMON, mage.cards.t.Telepathy.class)); + cards.add(new SetCardInfo("Temporal Aperture", 310, Rarity.RARE, mage.cards.t.TemporalAperture.class)); + cards.add(new SetCardInfo("Thran Quarry", 329, Rarity.RARE, mage.cards.t.ThranQuarry.class)); + cards.add(new SetCardInfo("Thran Turbine", 311, Rarity.UNCOMMON, mage.cards.t.ThranTurbine.class)); + cards.add(new SetCardInfo("Thundering Giant", 221, Rarity.UNCOMMON, mage.cards.t.ThunderingGiant.class)); + cards.add(new SetCardInfo("Time Spiral", 103, Rarity.RARE, mage.cards.t.TimeSpiral.class)); + cards.add(new SetCardInfo("Titania's Boon", 276, Rarity.UNCOMMON, mage.cards.t.TitaniasBoon.class)); + cards.add(new SetCardInfo("Titania's Chosen", 277, Rarity.UNCOMMON, mage.cards.t.TitaniasChosen.class)); + cards.add(new SetCardInfo("Tolarian Academy", 330, Rarity.RARE, mage.cards.t.TolarianAcademy.class)); + cards.add(new SetCardInfo("Tolarian Winds", 104, Rarity.COMMON, mage.cards.t.TolarianWinds.class)); + cards.add(new SetCardInfo("Torch Song", 222, Rarity.UNCOMMON, mage.cards.t.TorchSong.class)); + cards.add(new SetCardInfo("Treefolk Seedlings", 278, Rarity.UNCOMMON, mage.cards.t.TreefolkSeedlings.class)); + cards.add(new SetCardInfo("Treetop Rangers", 279, Rarity.COMMON, mage.cards.t.TreetopRangers.class)); + cards.add(new SetCardInfo("Turnabout", 105, Rarity.UNCOMMON, mage.cards.t.Turnabout.class)); + cards.add(new SetCardInfo("Umbilicus", 312, Rarity.RARE, mage.cards.u.Umbilicus.class)); + cards.add(new SetCardInfo("Unnerve", 162, Rarity.COMMON, mage.cards.u.Unnerve.class)); + cards.add(new SetCardInfo("Unworthy Dead", 163, Rarity.COMMON, mage.cards.u.UnworthyDead.class)); + cards.add(new SetCardInfo("Urza's Armor", 313, Rarity.UNCOMMON, mage.cards.u.UrzasArmor.class)); + cards.add(new SetCardInfo("Vampiric Embrace", 164, Rarity.UNCOMMON, mage.cards.v.VampiricEmbrace.class)); + cards.add(new SetCardInfo("Vebulid", 165, Rarity.RARE, mage.cards.v.Vebulid.class)); + cards.add(new SetCardInfo("Veil of Birds", 106, Rarity.COMMON, mage.cards.v.VeilOfBirds.class)); + cards.add(new SetCardInfo("Veiled Apparition", 107, Rarity.UNCOMMON, mage.cards.v.VeiledApparition.class)); + cards.add(new SetCardInfo("Veiled Crocodile", 108, Rarity.RARE, mage.cards.v.VeiledCrocodile.class)); + cards.add(new SetCardInfo("Veiled Sentry", 109, Rarity.UNCOMMON, mage.cards.v.VeiledSentry.class)); + cards.add(new SetCardInfo("Veiled Serpent", 110, Rarity.COMMON, mage.cards.v.VeiledSerpent.class)); + cards.add(new SetCardInfo("Venomous Fangs", 280, Rarity.COMMON, mage.cards.v.VenomousFangs.class)); + cards.add(new SetCardInfo("Vernal Bloom", 281, Rarity.RARE, mage.cards.v.VernalBloom.class)); + cards.add(new SetCardInfo("Viashino Outrider", 223, Rarity.COMMON, mage.cards.v.ViashinoOutrider.class)); + cards.add(new SetCardInfo("Viashino Runner", 224, Rarity.COMMON, mage.cards.v.ViashinoRunner.class)); + cards.add(new SetCardInfo("Viashino Sandswimmer", 225, Rarity.RARE, mage.cards.v.ViashinoSandswimmer.class)); + cards.add(new SetCardInfo("Viashino Weaponsmith", 226, Rarity.COMMON, mage.cards.v.ViashinoWeaponsmith.class)); + cards.add(new SetCardInfo("Victimize", 166, Rarity.UNCOMMON, mage.cards.v.Victimize.class)); + cards.add(new SetCardInfo("Vile Requiem", 167, Rarity.UNCOMMON, mage.cards.v.VileRequiem.class)); + cards.add(new SetCardInfo("Voice of Grace", 54, Rarity.UNCOMMON, mage.cards.v.VoiceOfGrace.class)); + cards.add(new SetCardInfo("Voice of Law", 55, Rarity.UNCOMMON, mage.cards.v.VoiceOfLaw.class)); + cards.add(new SetCardInfo("Voltaic Key", 314, Rarity.UNCOMMON, mage.cards.v.VoltaicKey.class)); + cards.add(new SetCardInfo("Vug Lizard", 227, Rarity.UNCOMMON, mage.cards.v.VugLizard.class)); + cards.add(new SetCardInfo("War Dance", 282, Rarity.UNCOMMON, mage.cards.w.WarDance.class)); + cards.add(new SetCardInfo("Wall of Junk", 315, Rarity.UNCOMMON, mage.cards.w.WallOfJunk.class)); + cards.add(new SetCardInfo("Waylay", 56, Rarity.UNCOMMON, mage.cards.w.Waylay.class)); + cards.add(new SetCardInfo("Western Paladin", 168, Rarity.RARE, mage.cards.w.WesternPaladin.class)); + cards.add(new SetCardInfo("Whetstone", 316, Rarity.RARE, mage.cards.w.Whetstone.class)); + cards.add(new SetCardInfo("Whirlwind", 283, Rarity.RARE, mage.cards.w.Whirlwind.class)); + cards.add(new SetCardInfo("Wild Dogs", 284, Rarity.COMMON, mage.cards.w.WildDogs.class)); + cards.add(new SetCardInfo("Wildfire", 228, Rarity.RARE, mage.cards.w.Wildfire.class)); + cards.add(new SetCardInfo("Windfall", 111, Rarity.UNCOMMON, mage.cards.w.Windfall.class)); + cards.add(new SetCardInfo("Winding Wurm", 285, Rarity.COMMON, mage.cards.w.WindingWurm.class)); + cards.add(new SetCardInfo("Wirecat", 317, Rarity.UNCOMMON, mage.cards.w.Wirecat.class)); + cards.add(new SetCardInfo("Witch Engine", 169, Rarity.RARE, mage.cards.w.WitchEngine.class)); + cards.add(new SetCardInfo("Wizard Mentor", 112, Rarity.COMMON, mage.cards.w.WizardMentor.class)); + cards.add(new SetCardInfo("Worn Powerstone", 318, Rarity.UNCOMMON, mage.cards.w.WornPowerstone.class)); + cards.add(new SetCardInfo("Worship", 57, Rarity.RARE, mage.cards.w.Worship.class)); + cards.add(new SetCardInfo("Yawgmoth's Edict", 170, Rarity.UNCOMMON, mage.cards.y.YawgmothsEdict.class)); + cards.add(new SetCardInfo("Yawgmoth's Will", 171, Rarity.RARE, mage.cards.y.YawgmothsWill.class)); + cards.add(new SetCardInfo("Zephid", 113, Rarity.RARE, mage.cards.z.Zephid.class)); + cards.add(new SetCardInfo("Zephid's Embrace", 114, Rarity.UNCOMMON, mage.cards.z.ZephidsEmbrace.class)); + } +} diff --git a/Mage.Sets/src/mage/sets/Visions.java b/Mage.Sets/src/mage/sets/Visions.java index ea27845253c..eaf27a65d39 100644 --- a/Mage.Sets/src/mage/sets/Visions.java +++ b/Mage.Sets/src/mage/sets/Visions.java @@ -105,6 +105,7 @@ public final class Visions extends ExpansionSet { cards.add(new SetCardInfo("Magma Mine", 149, Rarity.UNCOMMON, mage.cards.m.MagmaMine.class)); cards.add(new SetCardInfo("Man-o'-War", 37, Rarity.COMMON, mage.cards.m.ManOWar.class)); cards.add(new SetCardInfo("Miraculous Recovery", 13, Rarity.UNCOMMON, mage.cards.m.MiraculousRecovery.class)); + cards.add(new SetCardInfo("Mob Mentality", 88, Rarity.UNCOMMON, mage.cards.m.MobMentality.class)); cards.add(new SetCardInfo("Mortal Wound", 113, Rarity.COMMON, mage.cards.m.MortalWound.class)); cards.add(new SetCardInfo("Mundungu", 132, Rarity.UNCOMMON, mage.cards.m.Mundungu.class)); cards.add(new SetCardInfo("Mystic Veil", 38, Rarity.COMMON, mage.cards.m.MysticVeil.class)); diff --git a/Mage.Sets/src/mage/sets/Weatherlight.java b/Mage.Sets/src/mage/sets/Weatherlight.java index 01abb9f2b1b..88f32d096d1 100644 --- a/Mage.Sets/src/mage/sets/Weatherlight.java +++ b/Mage.Sets/src/mage/sets/Weatherlight.java @@ -49,6 +49,7 @@ public final class Weatherlight extends ExpansionSet { cards.add(new SetCardInfo("Benalish Infantry", 8, Rarity.COMMON, mage.cards.b.BenalishInfantry.class)); cards.add(new SetCardInfo("Benalish Knight", 9, Rarity.COMMON, mage.cards.b.BenalishKnight.class)); cards.add(new SetCardInfo("Benalish Missionary", 10, Rarity.COMMON, mage.cards.b.BenalishMissionary.class)); + cards.add(new SetCardInfo("Betrothed of Fire", 89, Rarity.COMMON, mage.cards.b.BetrothedOfFire.class)); cards.add(new SetCardInfo("Bloodrock Cyclops", 90, Rarity.COMMON, mage.cards.b.BloodrockCyclops.class)); cards.add(new SetCardInfo("Blossoming Wreath", 120, Rarity.COMMON, mage.cards.b.BlossomingWreath.class)); cards.add(new SetCardInfo("Bogardan Firefiend", 91, Rarity.COMMON, mage.cards.b.BogardanFirefiend.class)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/damage/SpitefulShadowsTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/damage/SpitefulShadowsTest.java index 42628bca6c2..4eaffcbd2b7 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/damage/SpitefulShadowsTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/damage/SpitefulShadowsTest.java @@ -39,9 +39,11 @@ public class SpitefulShadowsTest extends CardTestPlayerBase { @Test public void testCard1() { - addCard(Zone.BATTLEFIELD, playerA, "Craw Wurm"); + addCard(Zone.BATTLEFIELD, playerA, "Craw Wurm"); // Creature 6/4 addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2); addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2); + // Enchant creature + // Whenever enchanted creature is dealt damage, it deals that much damage to its controller. addCard(Zone.HAND, playerA, "Spiteful Shadows"); addCard(Zone.HAND, playerA, "Lightning Bolt"); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/exile/FiendHunterTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/exile/FiendHunterTest.java index 705a274c36d..e7aa5a62bd6 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/exile/FiendHunterTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/exile/FiendHunterTest.java @@ -1,4 +1,3 @@ - package org.mage.test.cards.abilities.oneshot.exile; import mage.constants.PhaseStep; @@ -70,10 +69,9 @@ public class FiendHunterTest extends CardTestPlayerBase { execute(); assertExileCount("Silvercoat Lion", 1); - assertPermanentCount(playerB, "Primeval Titan", 1); - assertPermanentCount(playerA, "Fiend Hunter", 1); assertPermanentCount(playerA, "Restoration Angel", 1); + assertPermanentCount(playerB, "Primeval Titan", 1); } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/LimitedCountedActivationsTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/LimitedCountedActivationsTest.java index 7901a6d153b..74b14b0b2f9 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/LimitedCountedActivationsTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/other/LimitedCountedActivationsTest.java @@ -1,179 +1,180 @@ - -package org.mage.test.cards.abilities.other; - -import mage.constants.PhaseStep; -import mage.constants.Zone; -import org.junit.Test; -import org.mage.test.serverside.base.CardTestPlayerBase; - -/** - * - * @author LevelX2 - */ -public class LimitedCountedActivationsTest extends CardTestPlayerBase { - - /** - * Tests usage of ActivationInfo class - */ - @Test - public void testDragonWhelpActivatedThreeTimes() { - addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3); - // Flying - // {R}: Dragon Whelp gets +1/+0 until end of turn. If this ability has been activated four or more times this turn, sacrifice Dragon Whelp at the beginning of the next end step. - addCard(Zone.BATTLEFIELD, playerA, "Dragon Whelp", 1); // 3/3 - - activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); - activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); - activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); - - attack(1, playerA, "Dragon Whelp"); - - setStopAt(2, PhaseStep.UPKEEP); - execute(); - - assertPermanentCount(playerA, "Dragon Whelp", 1); - - assertLife(playerA, 20); - assertLife(playerB, 15); - } - - @Test - public void testDragonWhelpActivatedFourTimes() { - addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4); - // Flying - // {R}: Dragon Whelp gets +1/+0 until end of turn. If this ability has been activated four or more times this turn, sacrifice Dragon Whelp at the beginning of the next end step. - addCard(Zone.BATTLEFIELD, playerA, "Dragon Whelp", 1); // 3/3 - - activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); - activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); - activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); - activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); - - attack(1, playerA, "Dragon Whelp"); - - setStopAt(2, PhaseStep.UPKEEP); - execute(); - - assertPermanentCount(playerA, "Dragon Whelp", 0); - assertGraveyardCount(playerA, "Dragon Whelp", 1); - - assertLife(playerA, 20); - assertLife(playerB, 14); - } - - @Test - public void testDragonWhelpActivatedFiveTimes() { - addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5); - // Flying - // {R}: Dragon Whelp gets +1/+0 until end of turn. If this ability has been activated four or more times this turn, sacrifice Dragon Whelp at the beginning of the next end step. - addCard(Zone.BATTLEFIELD, playerA, "Dragon Whelp", 1); // 3/3 - - activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); - activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); - activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); - activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); - activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); - - attack(1, playerA, "Dragon Whelp"); - - setStopAt(2, PhaseStep.UPKEEP); - execute(); - - assertPermanentCount(playerA, "Dragon Whelp", 0); - assertGraveyardCount(playerA, "Dragon Whelp", 1); - - assertLife(playerA, 20); - assertLife(playerB, 13); - } - - @Test - public void testDragonWhelpTwoObjects() { - addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5); - addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1); - // Flying - // {R}: Dragon Whelp gets +1/+0 until end of turn. If this ability has been activated four or more times this turn, sacrifice Dragon Whelp at the beginning of the next end step. - addCard(Zone.BATTLEFIELD, playerA, "Dragon Whelp", 1); // 3/3 - // Put target creature card from a graveyard onto the battlefield under your control. You lose life equal to its converted mana cost. - addCard(Zone.HAND, playerA, "Reanimate", 1); - // Target creature gains haste until end of turn. - addCard(Zone.HAND, playerA, "Unnatural Speed", 1); - - addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2); - // Destroy target nonartifact, nonblack creature. It can't be regenerated. - addCard(Zone.HAND, playerB, "Terror", 1); // {1}{B} - - activateAbility(1, PhaseStep.UPKEEP, playerA, "{R}: "); - - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Terror", "Dragon Whelp"); - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reanimate", "Dragon Whelp"); - castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Unnatural Speed", "Dragon Whelp"); - - activateAbility(1, PhaseStep.DECLARE_ATTACKERS, playerA, "{R}: "); - activateAbility(1, PhaseStep.DECLARE_ATTACKERS, playerA, "{R}: "); - activateAbility(1, PhaseStep.DECLARE_ATTACKERS, playerA, "{R}: "); - - attack(1, playerA, "Dragon Whelp"); - - setStopAt(2, PhaseStep.UPKEEP); - execute(); - - assertGraveyardCount(playerA, "Unnatural Speed", 1); - assertGraveyardCount(playerA, "Reanimate", 1); - - assertGraveyardCount(playerB, "Terror", 1); - - assertPermanentCount(playerA, "Dragon Whelp", 1); - assertPowerToughness(playerA, "Dragon Whelp", 2, 3); - assertGraveyardCount(playerA, "Dragon Whelp", 0); - - assertLife(playerA, 16); - assertLife(playerB, 15); - } - - @Test - public void testDragonWhelpDontSacrificeNewObject() { - addCard(Zone.BATTLEFIELD, playerA, "Mountain", 8); - addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1); - // Flying - // {R}: Dragon Whelp gets +1/+0 until end of turn. If this ability has been activated four or more times this turn, sacrifice Dragon Whelp at the beginning of the next end step. - addCard(Zone.BATTLEFIELD, playerA, "Dragon Whelp", 1); // 3/3 - // Put target creature card from a graveyard onto the battlefield under your control. You lose life equal to its converted mana cost. - addCard(Zone.HAND, playerA, "Reanimate", 1); - // Target creature gains haste until end of turn. - addCard(Zone.HAND, playerA, "Unnatural Speed", 1); - - addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2); - // Destroy target nonartifact, nonblack creature. It can't be regenerated. - addCard(Zone.HAND, playerB, "Terror", 1); // {1}{B} - - activateAbility(1, PhaseStep.UPKEEP, playerA, "{R}: "); - activateAbility(1, PhaseStep.UPKEEP, playerA, "{R}: "); - activateAbility(1, PhaseStep.UPKEEP, playerA, "{R}: "); - activateAbility(1, PhaseStep.UPKEEP, playerA, "{R}: "); - - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Terror", "Dragon Whelp"); - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reanimate", "Dragon Whelp"); - castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Unnatural Speed", "Dragon Whelp"); - - activateAbility(1, PhaseStep.DECLARE_ATTACKERS, playerA, "{R}: "); - activateAbility(1, PhaseStep.DECLARE_ATTACKERS, playerA, "{R}: "); - activateAbility(1, PhaseStep.DECLARE_ATTACKERS, playerA, "{R}: "); - - attack(1, playerA, "Dragon Whelp"); - - setStopAt(2, PhaseStep.UPKEEP); - execute(); - - assertGraveyardCount(playerA, "Unnatural Speed", 1); - assertGraveyardCount(playerA, "Reanimate", 1); - - assertGraveyardCount(playerB, "Terror", 1); - - assertPermanentCount(playerA, "Dragon Whelp", 1); - assertPowerToughness(playerA, "Dragon Whelp", 2, 3); - assertGraveyardCount(playerA, "Dragon Whelp", 0); - - assertLife(playerA, 16); - assertLife(playerB, 15); - } -} +package org.mage.test.cards.abilities.other; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class LimitedCountedActivationsTest extends CardTestPlayerBase { + + /** + * Tests usage of ActivationInfo class + */ + @Test + public void testDragonWhelpActivatedThreeTimes() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3); + // Flying + // {R}: Dragon Whelp gets +1/+0 until end of turn. If this ability has been activated four or more times this turn, sacrifice Dragon Whelp at the beginning of the next end step. + addCard(Zone.BATTLEFIELD, playerA, "Dragon Whelp", 1); // 3/3 + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); + + attack(1, playerA, "Dragon Whelp"); + + setStopAt(2, PhaseStep.UPKEEP); + execute(); + + assertPermanentCount(playerA, "Dragon Whelp", 1); + + assertLife(playerA, 20); + assertLife(playerB, 15); + } + + @Test + public void testDragonWhelpActivatedFourTimes() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4); + // Flying + // {R}: Dragon Whelp gets +1/+0 until end of turn. If this ability has been activated four or more times this turn, sacrifice Dragon Whelp at the beginning of the next end step. + addCard(Zone.BATTLEFIELD, playerA, "Dragon Whelp", 1); // 3/3 + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); + + attack(1, playerA, "Dragon Whelp"); + + setStopAt(2, PhaseStep.UPKEEP); + execute(); + + assertPermanentCount(playerA, "Dragon Whelp", 0); + assertGraveyardCount(playerA, "Dragon Whelp", 1); + + assertLife(playerA, 20); + assertLife(playerB, 14); + } + + @Test + public void testDragonWhelpActivatedFiveTimes() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5); + // Flying + // {R}: Dragon Whelp gets +1/+0 until end of turn. If this ability has been activated four or more times this turn, sacrifice Dragon Whelp at the beginning of the next end step. + addCard(Zone.BATTLEFIELD, playerA, "Dragon Whelp", 1); // 3/3 + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{R}: "); + + attack(1, playerA, "Dragon Whelp"); + + setStopAt(2, PhaseStep.UPKEEP); + execute(); + + assertPermanentCount(playerA, "Dragon Whelp", 0); + assertGraveyardCount(playerA, "Dragon Whelp", 1); + + assertLife(playerA, 20); + assertLife(playerB, 13); + } + + @Test + public void testDragonWhelpTwoObjects() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1); + // Flying + // {R}: Dragon Whelp gets +1/+0 until end of turn. If this ability has been activated four or more times this turn, sacrifice Dragon Whelp at the beginning of the next end step. + addCard(Zone.BATTLEFIELD, playerA, "Dragon Whelp", 1); // 3/3 + // Put target creature card from a graveyard onto the battlefield under your control. You lose life equal to its converted mana cost. + addCard(Zone.HAND, playerA, "Reanimate", 1); + // Target creature gains haste until end of turn. + addCard(Zone.HAND, playerA, "Unnatural Speed", 1); + + addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2); + // Destroy target nonartifact, nonblack creature. It can't be regenerated. + addCard(Zone.HAND, playerB, "Terror", 1); // {1}{B} + + activateAbility(1, PhaseStep.UPKEEP, playerA, "{R}: "); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Terror", "Dragon Whelp"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reanimate", "Dragon Whelp"); + castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Unnatural Speed", "Dragon Whelp"); + + activateAbility(1, PhaseStep.DECLARE_ATTACKERS, playerA, "{R}: "); + activateAbility(1, PhaseStep.DECLARE_ATTACKERS, playerA, "{R}: "); + activateAbility(1, PhaseStep.DECLARE_ATTACKERS, playerA, "{R}: "); + + attack(1, playerA, "Dragon Whelp"); + + setStopAt(2, PhaseStep.UPKEEP); + execute(); + + assertGraveyardCount(playerA, "Unnatural Speed", 1); + assertGraveyardCount(playerA, "Reanimate", 1); + + assertGraveyardCount(playerB, "Terror", 1); + + assertPermanentCount(playerA, "Dragon Whelp", 1); + assertPowerToughness(playerA, "Dragon Whelp", 2, 3); + assertGraveyardCount(playerA, "Dragon Whelp", 0); + + assertLife(playerA, 16); + assertLife(playerB, 15); + } + + @Test + public void testDragonWhelpDontSacrificeNewObject() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 8); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1); + // Flying + // {R}: Dragon Whelp gets +1/+0 until end of turn. If this ability has been activated four or more times this turn, sacrifice Dragon Whelp at the beginning of the next end step. + addCard(Zone.BATTLEFIELD, playerA, "Dragon Whelp", 1); // 3/3 + // Put target creature card from a graveyard onto the battlefield under your control. You lose life equal to its converted mana cost. + addCard(Zone.HAND, playerA, "Reanimate", 1); + // Target creature gains haste until end of turn. + addCard(Zone.HAND, playerA, "Unnatural Speed", 1); + + addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2); + // Destroy target nonartifact, nonblack creature. It can't be regenerated. + addCard(Zone.HAND, playerB, "Terror", 1); // {1}{B} + + activateAbility(1, PhaseStep.UPKEEP, playerA, "{R}: "); + activateAbility(1, PhaseStep.UPKEEP, playerA, "{R}: "); + activateAbility(1, PhaseStep.UPKEEP, playerA, "{R}: "); + activateAbility(1, PhaseStep.UPKEEP, playerA, "{R}: "); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Terror", "Dragon Whelp"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reanimate", "Dragon Whelp"); + castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Unnatural Speed", "Dragon Whelp"); + + activateAbility(1, PhaseStep.DECLARE_ATTACKERS, playerA, "{R}: "); + activateAbility(1, PhaseStep.DECLARE_ATTACKERS, playerA, "{R}: "); + activateAbility(1, PhaseStep.DECLARE_ATTACKERS, playerA, "{R}: "); + + attack(1, playerA, "Dragon Whelp"); + + setStopAt(2, PhaseStep.UPKEEP); + execute(); + + assertGraveyardCount(playerA, "Unnatural Speed", 1); + assertGraveyardCount(playerA, "Reanimate", 1); + + assertGraveyardCount(playerB, "Terror", 1); + + assertLife(playerA, 16); + assertLife(playerB, 15); + + assertGraveyardCount(playerA, "Dragon Whelp", 0); + + assertPermanentCount(playerA, "Dragon Whelp", 1); + assertPowerToughness(playerA, "Dragon Whelp", 2, 3); + + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/conditional/IcequakeTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/conditional/IcequakeTest.java new file mode 100644 index 00000000000..f3db7d63796 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/conditional/IcequakeTest.java @@ -0,0 +1,25 @@ +package org.mage.test.cards.conditional; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +public class IcequakeTest extends CardTestPlayerBase { + + @Test + public void testIcequakeOnSnowLand(){ + + addCard(Zone.BATTLEFIELD, playerB, "Snow-Covered Plains"); + addCard(Zone.BATTLEFIELD, playerA, "Swamp",10); + addCard(Zone.HAND, playerA, "Icequake"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN,playerA, "Icequake", "Snow-Covered Plains"); + + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertLife(playerA, 20); + assertLife(playerB, 19); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/GoblinGoliathTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/GoblinGoliathTest.java new file mode 100644 index 00000000000..b3151c95351 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/GoblinGoliathTest.java @@ -0,0 +1,47 @@ +package org.mage.test.cards.continuous; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author JayDi85 + */ +public class GoblinGoliathTest extends CardTestPlayerBase { + + @Test + public void test_DoubleDamage() { + // test double damage on creature (no), on yourself (no) and on opponent (yes) by bold damage + + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 20); + // {3}{R}, {T}: If a source you control would deal damage to an opponent this turn, it deals double that damage to that player instead. + addCard(Zone.BATTLEFIELD, playerA, "Goblin Goliath"); + addCard(Zone.HAND, playerA, "Lightning Bolt", 4); // 3 damage + addCard(Zone.BATTLEFIELD, playerB, "Barktooth Warbeard"); // 6/5 + + // normal damage without ability + castSpell(1, PhaseStep.UPKEEP, playerA, "Lightning Bolt", playerB); + checkLife("normal damage to opponent", 1, PhaseStep.PRECOMBAT_MAIN, playerB, 20 - 3); + + // activate double damage + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{3}{R}"); + // cast bolt to player (2x damage) + castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Lightning Bolt", playerB); + checkLife("double damage to opponent", 1, PhaseStep.END_COMBAT, playerB, 20 - 3 - 3 * 2); + // cast bolt to creature (1x damage) + castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Lightning Bolt", "Barktooth Warbeard"); + checkPermanentCount("normal damage to creature", 1, PhaseStep.END_COMBAT, playerB, "Barktooth Warbeard", 1); + // cast bolt to yourself (1x damage) + castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Lightning Bolt", playerA); + checkLife("normal damage to yourself", 1, PhaseStep.END_COMBAT, playerA, 20 - 3); + + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertGraveyardCount(playerA, "Lightning Bolt", 4); + assertLife(playerA, 20 - 3); + assertLife(playerB, 20 - 3 - 3 * 2); + assertGraveyardCount(playerB, "Barktooth Warbeard", 0); + } +} \ No newline at end of file diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/facedown/SummonersEggTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/facedown/SummonersEggTest.java index e9354e7a8d5..ab984d69d8b 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/facedown/SummonersEggTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/facedown/SummonersEggTest.java @@ -27,17 +27,16 @@ public class SummonersEggTest extends CardTestPlayerBase { @Test public void testSummonersEggImprint() { addCard(Zone.HAND, playerA, "Summoner's Egg"); - addCard(Zone.HAND, playerA, "Sejiri Merfolk"); + addCard(Zone.HAND, playerA, "Maritime Guard"); addCard(Zone.HAND, playerA, "Goblin Roughrider"); addCard(Zone.BATTLEFIELD, playerA, "Island", 4); - - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Summoner's Egg"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Summoner's Egg"); setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); - + assertHandCount(playerA, 1); - assertHandCount(playerA, "Sejiri Merfolk", 1); + assertHandCount(playerA, "Maritime Guard", 1); assertHandCount(playerA, "Goblin Roughrider", 0); assertExileCount("Goblin Roughrider", 1); @@ -53,7 +52,7 @@ public class SummonersEggTest extends CardTestPlayerBase { @Test public void testSummonersEggDies() { addCard(Zone.HAND, playerA, "Summoner's Egg"); - addCard(Zone.HAND, playerA, "Sejiri Merfolk"); + addCard(Zone.HAND, playerA, "Maritime Guard"); addCard(Zone.HAND, playerA, "Goblin Roughrider"); addCard(Zone.BATTLEFIELD, playerA, "Island", 4); addCard(Zone.HAND, playerB, "Char"); @@ -67,7 +66,7 @@ public class SummonersEggTest extends CardTestPlayerBase { execute(); assertHandCount(playerA, 1); - assertHandCount(playerA, "Sejiri Merfolk", 1); + assertHandCount(playerA, "Maritime Guard", 1); assertHandCount(playerA, "Goblin Roughrider", 0); assertGraveyardCount(playerA, "Summoner's Egg", 1); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/mana/HarvestMageTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/mana/HarvestMageTest.java new file mode 100644 index 00000000000..ac39080b792 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/mana/HarvestMageTest.java @@ -0,0 +1,35 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.mage.test.cards.mana; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class HarvestMageTest extends CardTestPlayerBase { + + @Test + public void testOneInstance() { + addCard(Zone.BATTLEFIELD, playerA, "Forest", 1); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); + + // {G}, {T}, Discard a card: Until end of turn, if you tap a land for mana, it produces one mana of a color of your choice instead of any other type and amount. + addCard(Zone.HAND, playerA, "Harvest Mage", 1); // Creature 1/1 {G} + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Harvest Mage"); + + activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{G}, {T}, Discard a card: Until end of turn"); + setStopAt(3, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertPermanentCount(playerA, "Harvest Mage", 1); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/redirect/GlarecasterTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/redirect/GlarecasterTest.java new file mode 100644 index 00000000000..817761420f2 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/redirect/GlarecasterTest.java @@ -0,0 +1,48 @@ +package org.mage.test.cards.replacement.redirect; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class GlarecasterTest extends CardTestPlayerBase { + + /** + * I can activate Glarecaster's redirection ability, immediately cast two + * Lightning Bolts on it and both get redirected towards the chosen target. + * If I pass until the next step and cast another Bolt on it, it's not being + * redirected anymore. + * + */ + @Test + public void testTwoTimesInstantSpellDamage() { + addCard(Zone.HAND, playerA, "Lightning Bolt", 2); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2); + + // Flying + // {5}{W}: The next time damage would be dealt to Glarecaster and/or you this turn, that damage is dealt to any target instead. + addCard(Zone.BATTLEFIELD, playerB, "Glarecaster"); // Creature 3/3 + addCard(Zone.BATTLEFIELD, playerB, "Plains", 6); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{5}{W}: The next time damage would be dealt to", playerA); + + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", playerB); + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", "Glarecaster"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertGraveyardCount(playerA, "Lightning Bolt", 2); + + assertPermanentCount(playerB, "Glarecaster", 1); + + assertLife(playerA, 17); + assertLife(playerB, 17); + + } + +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/soi/PrizedAmalgamTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/soi/PrizedAmalgamTest.java index 0cd8182c34f..807859f205b 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/soi/PrizedAmalgamTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/soi/PrizedAmalgamTest.java @@ -26,8 +26,7 @@ public class PrizedAmalgamTest extends CardTestPlayerBase { addCard(Zone.GRAVEYARD, playerA, "Prized Amalgam", 1); addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1); - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reanimate"); - addTarget(playerA, "Bronze Sable"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reanimate", "Bronze Sable"); setStopAt(1, PhaseStep.END_TURN); execute(); @@ -72,8 +71,7 @@ public class PrizedAmalgamTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3); addCard(Zone.GRAVEYARD, playerB, "Prized Amalgam", 1); - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reanimate"); - addTarget(playerA, "Hill Giant"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reanimate", "Hill Giant"); setStopAt(1, PhaseStep.END_TURN); execute(); @@ -95,8 +93,7 @@ public class PrizedAmalgamTest extends CardTestPlayerBase { // Whenever a creature enters the battlefield, if it entered from your graveyard or you cast it from your graveyard, return Prized Amalgam from your graveyard to the battlefield tapped at the beginning of the next end step. addCard(Zone.GRAVEYARD, playerB, "Prized Amalgam", 1); - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Necromantic Summons"); - addTarget(playerA, "Merfolk Looter"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Necromantic Summons", "Merfolk Looter"); setStopAt(1, PhaseStep.END_TURN); execute(); diff --git a/Mage.Tests/src/test/java/org/mage/test/load/LoadTest.java b/Mage.Tests/src/test/java/org/mage/test/load/LoadTest.java index afe179f7c7d..636305a79df 100644 --- a/Mage.Tests/src/test/java/org/mage/test/load/LoadTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/load/LoadTest.java @@ -10,6 +10,7 @@ import mage.cards.decks.DeckCardInfo; import mage.cards.decks.DeckCardLists; import mage.cards.repository.CardInfo; import mage.cards.repository.CardRepository; +import mage.cards.repository.CardScanner; import mage.constants.*; import mage.game.match.MatchOptions; import mage.player.ai.ComputerPlayer; @@ -21,9 +22,7 @@ import mage.remote.SessionImpl; import mage.util.RandomUtil; import mage.view.*; import org.apache.log4j.Logger; -import org.junit.Assert; -import org.junit.Ignore; -import org.junit.Test; +import org.junit.*; /** * Intended to test Mage server under different load patterns. @@ -45,6 +44,12 @@ public class LoadTest { private static final String TEST_PROXY_TYPE = "None"; private static final String TEST_USER_NAME = "user"; + @BeforeClass + public static void initDatabase() { + // recreate missing cards db + CardScanner.scan(); + } + @Test public void test_CreateRandomDeck() { diff --git a/Mage.Tests/src/test/java/org/mage/test/multiplayer/BlatantThieveryTest.java b/Mage.Tests/src/test/java/org/mage/test/multiplayer/BlatantThieveryTest.java index a5447b94b15..049e958347b 100644 --- a/Mage.Tests/src/test/java/org/mage/test/multiplayer/BlatantThieveryTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/multiplayer/BlatantThieveryTest.java @@ -52,6 +52,7 @@ public class BlatantThieveryTest extends CardTestMultiPlayerBase { setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); + assertGraveyardCount(playerA, "Blatant Thievery", 1); assertPermanentCount(playerA, "Silvercoat Lion", 1); assertPermanentCount(playerA, "Walking Corpse", 1); assertPermanentCount(playerA, "Pillarfield Ox", 1); diff --git a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java index 8c22e36169e..e6bf95d3973 100644 --- a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java +++ b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java @@ -1,5 +1,9 @@ package org.mage.test.player; +import java.io.Serializable; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import mage.MageObject; import mage.MageObjectReference; import mage.ObjectColor; @@ -46,14 +50,9 @@ import mage.players.Player; import mage.players.net.UserData; import mage.target.*; import mage.target.common.*; +import org.apache.log4j.Logger; import org.junit.Assert; import org.junit.Ignore; - -import java.io.Serializable; -import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - import static org.mage.test.serverside.base.impl.CardTestPlayerAPIImpl.*; /** @@ -64,6 +63,8 @@ import static org.mage.test.serverside.base.impl.CardTestPlayerAPIImpl.*; @Ignore public class TestPlayer implements Player { + private static final Logger logger = Logger.getLogger(TestPlayer.class); + private int maxCallsWithoutAction = 100; private int foundNoAction = 0; private boolean AIPlayer; @@ -128,7 +129,7 @@ public class TestPlayer implements Player { /** * @param maxCallsWithoutAction max number of priority passes a player may - * have for this test (default = 100) + * have for this test (default = 100) */ public void setMaxCallsWithoutAction(int maxCallsWithoutAction) { this.maxCallsWithoutAction = maxCallsWithoutAction; @@ -524,6 +525,13 @@ public class TestPlayer implements Player { checkProccessed = true; } + // check PT: life + if (params[0].equals(CHECK_COMMAND_LIFE) && params.length == 2) { + assertLife(action, game, computerPlayer, Integer.parseInt(params[1])); + actions.remove(action); + checkProccessed = true; + } + // check ability: card name, ability class, must have if (params[0].equals(CHECK_COMMAND_ABILITY) && params.length == 4) { assertAbility(action, game, computerPlayer, params[1], params[2], Boolean.parseBoolean(params[3])); @@ -538,6 +546,13 @@ public class TestPlayer implements Player { checkProccessed = true; } + // check exile count: card name, count + if (params[0].equals(CHECK_COMMAND_EXILE_COUNT) && params.length == 3) { + assertExileCount(action, game, computerPlayer, params[1], Integer.parseInt(params[2])); + actions.remove(action); + checkProccessed = true; + } + // check hand count: count if (params[0].equals(CHECK_COMMAND_HAND_COUNT) && params.length == 2) { assertHandCount(action, game, computerPlayer, Integer.parseInt(params[1])); @@ -610,6 +625,11 @@ public class TestPlayer implements Player { Toughness, perm.getToughness().getValue()); } + private void assertLife(PlayerAction action, Game game, Player player, int Life) { + Assert.assertEquals(action.getActionName() + " - " + player.getName() + " have wrong life: " + player.getLife() + " <> " + Life, + Life, player.getLife()); + } + private void assertAbility(PlayerAction action, Game game, Player player, String permanentName, String abilityClass, boolean mustHave) { Permanent perm = findPermanentWithAssert(action, game, player, permanentName); @@ -639,6 +659,17 @@ public class TestPlayer implements Player { Assert.assertEquals(action.getActionName() + " - permanent " + permanentName + " must exists in " + count + " instances", count, foundedCount); } + private void assertExileCount(PlayerAction action, Game game, Player player, String permanentName, int count) { + int foundedCount = 0; + for (Card card : game.getExile().getAllCards(game)) { + if (card.getName().equals(permanentName) && card.isOwnedBy(player.getId())) { + foundedCount++; + } + } + + Assert.assertEquals(action.getActionName() + " - card " + permanentName + " must exists in exile zone with " + count + " instances", count, foundedCount); + } + private void assertHandCount(PlayerAction action, Game game, Player player, int count) { Assert.assertEquals(action.getActionName() + " - hand must contain " + count, count, player.getHand().size()); } @@ -773,7 +804,7 @@ public class TestPlayer implements Player { // Loop through players and validate can attack/block this turn UUID defenderId = null; //List - for (Iterator it = actions.iterator(); it.hasNext(); ) { + for (Iterator it = actions.iterator(); it.hasNext();) { PlayerAction action = it.next(); if (action.getTurnNum() == game.getTurnNum() && action.getAction().startsWith("attack:")) { String command = action.getAction(); @@ -1092,6 +1123,7 @@ public class TestPlayer implements Player { } } } + return computerPlayer.choose(outcome, target, sourceId, game, options); } @@ -1102,6 +1134,62 @@ public class TestPlayer implements Player { if (target.getTargetController() != null && target.getAbilityController() != null) { abilityControllerId = target.getAbilityController(); } + if (target instanceof TargetCardInGraveyardOrBattlefield) { + boolean removeTargetDefinition = false; + Filter filter = target.getFilter(); + for (String targetDefinition : targets) { + String[] targetList = targetDefinition.split("\\^"); + boolean targetFound = false; + for (String targetName : targetList) { + boolean originOnly = false; + boolean copyOnly = false; + if (targetName.endsWith("]")) { + if (targetName.endsWith("[no copy]")) { + originOnly = true; + targetName = targetName.substring(0, targetName.length() - 9); + } + if (targetName.endsWith("[only copy]")) { + copyOnly = true; + targetName = targetName.substring(0, targetName.length() - 11); + } + } + for (Permanent permanent : game.getBattlefield().getAllActivePermanents()) { + if (permanent.getName().equals(targetName) || (permanent.getName() + '-' + permanent.getExpansionSetCode()).equals(targetName)) { + if (filter.match(permanent, game) && target.canTarget(abilityControllerId, permanent.getId(), source, game) && !target.getTargets().contains(permanent.getId())) { + if ((permanent.isCopy() && !originOnly) || (!permanent.isCopy() && !copyOnly)) { + target.add(permanent.getId(), game); + targetFound = true; + break; + } + } + } + } + if (!targetFound) { + for (UUID playerId : game.getState().getPlayersInRange(this.getId(), game)) { + Player player = game.getPlayer(playerId); + for (Card card : player.getGraveyard().getCards(((TargetCardInGraveyardOrBattlefield) target).getFilter(), game)) { + if (card.getName().equals(targetName) || (card.getName() + '-' + card.getExpansionSetCode()).equals(targetName)) { + if (((TargetCardInYourGraveyard) target).canTarget(abilityControllerId, card.getId(), source, game) && !target.getTargets().contains(card.getId())) { + target.add(card.getId(), game); + targetFound = true; + break; + } + } + } + } + } + if (targetFound) { + targetFound = false; + removeTargetDefinition = true; + } + + } + if (removeTargetDefinition) { + targets.remove(targetDefinition); + return true; + } + } + } if (target instanceof TargetPlayer || target instanceof TargetAnyTarget || target instanceof TargetCreatureOrPlayer @@ -1269,7 +1357,10 @@ public class TestPlayer implements Player { } @Override - public boolean chooseTarget(Outcome outcome, Cards cards, TargetCard target, Ability source, Game game) { + public boolean chooseTarget(Outcome outcome, Cards cards, + TargetCard target, Ability source, + Game game + ) { if (!targets.isEmpty()) { for (String targetDefinition : targets) { String[] targetList = targetDefinition.split("\\^"); @@ -1293,7 +1384,8 @@ public class TestPlayer implements Player { } @Override - public TriggeredAbility chooseTriggeredAbility(List abilities, Game game) { + public TriggeredAbility chooseTriggeredAbility(List abilities, Game game + ) { if (!choices.isEmpty()) { for (TriggeredAbility ability : abilities) { if (ability.toString().startsWith(choices.get(0))) { @@ -1306,12 +1398,18 @@ public class TestPlayer implements Player { } @Override - public boolean chooseUse(Outcome outcome, String message, Ability source, Game game) { + public boolean chooseUse(Outcome outcome, String message, + Ability source, Game game + ) { return this.chooseUse(outcome, message, null, null, null, source, game); } @Override - public boolean chooseUse(Outcome outcome, String message, String secondMessage, String trueText, String falseText, Ability source, Game game) { + public boolean chooseUse(Outcome outcome, String message, + String secondMessage, String trueText, + String falseText, Ability source, + Game game + ) { if (message.equals("Scry 1?")) { return false; } @@ -1329,7 +1427,9 @@ public class TestPlayer implements Player { } @Override - public int announceXMana(int min, int max, String message, Game game, Ability ability) { + public int announceXMana(int min, int max, String message, + Game game, Ability ability + ) { if (!choices.isEmpty()) { for (String choice : choices) { if (choice.startsWith("X=")) { @@ -1343,7 +1443,10 @@ public class TestPlayer implements Player { } @Override - public int announceXCost(int min, int max, String message, Game game, Ability ability, VariableCost variablCost) { + public int announceXCost(int min, int max, String message, + Game game, Ability ability, + VariableCost variablCost + ) { if (!choices.isEmpty()) { if (choices.get(0).startsWith("X=")) { int xValue = Integer.parseInt(choices.get(0).substring(2)); @@ -1355,7 +1458,9 @@ public class TestPlayer implements Player { } @Override - public int getAmount(int min, int max, String message, Game game) { + public int getAmount(int min, int max, String message, + Game game + ) { if (!choices.isEmpty()) { if (choices.get(0).startsWith("X=")) { int xValue = Integer.parseInt(choices.get(0).substring(2)); @@ -1367,12 +1472,14 @@ public class TestPlayer implements Player { } @Override - public void addAbility(Ability ability) { + public void addAbility(Ability ability + ) { computerPlayer.addAbility(ability); } @Override - public boolean activateAbility(ActivatedAbility ability, Game game) { + public boolean activateAbility(ActivatedAbility ability, Game game + ) { return computerPlayer.activateAbility(ability, game); } @@ -1392,12 +1499,14 @@ public class TestPlayer implements Player { } @Override - public void won(Game game) { + public void won(Game game + ) { computerPlayer.won(game); } @Override - public void restore(Player player) { + public void restore(Player player + ) { this.modesSet.clear(); this.modesSet.addAll(((TestPlayer) player).modesSet); this.actions.clear(); @@ -1410,18 +1519,21 @@ public class TestPlayer implements Player { } @Override - public void useDeck(Deck deck, Game game) { + public void useDeck(Deck deck, Game game + ) { computerPlayer.useDeck(deck, game); } @Override - public void init(Game game) { + public void init(Game game + ) { initialTurns = 0; computerPlayer.init(game); } @Override - public void init(Game game, boolean testMode) { + public void init(Game game, boolean testMode + ) { initialTurns = 0; computerPlayer.init(game, testMode); } @@ -1437,12 +1549,14 @@ public class TestPlayer implements Player { } @Override - public void otherPlayerLeftGame(Game game) { + public void otherPlayerLeftGame(Game game + ) { computerPlayer.otherPlayerLeftGame(game); } @Override - public void beginTurn(Game game) { + public void beginTurn(Game game + ) { checkLegalMovesThisTurn(game); computerPlayer.beginTurn(game); } @@ -1463,12 +1577,14 @@ public class TestPlayer implements Player { } @Override - public void controlPlayersTurn(Game game, UUID playerId) { + public void controlPlayersTurn(Game game, UUID playerId + ) { computerPlayer.controlPlayersTurn(game, playerId); } @Override - public void setTurnControlledBy(UUID playerId) { + public void setTurnControlledBy(UUID playerId + ) { computerPlayer.setTurnControlledBy(playerId); } @@ -1488,77 +1604,98 @@ public class TestPlayer implements Player { } @Override - public void setGameUnderYourControl(boolean value) { + public void setGameUnderYourControl(boolean value + ) { computerPlayer.setGameUnderYourControl(value); } @Override - public void setGameUnderYourControl(boolean value, boolean fullRestore) { + public void setGameUnderYourControl(boolean value, boolean fullRestore + ) { computerPlayer.setGameUnderYourControl(value, fullRestore); } @Override - public void endOfTurn(Game game) { + public void endOfTurn(Game game + ) { computerPlayer.endOfTurn(game); } @Override - public boolean canBeTargetedBy(MageObject source, UUID sourceControllerId, Game game) { + public boolean canBeTargetedBy(MageObject source, UUID sourceControllerId, + Game game + ) { return computerPlayer.canBeTargetedBy(source, sourceControllerId, game); } @Override - public boolean hasProtectionFrom(MageObject source, Game game) { + public boolean hasProtectionFrom(MageObject source, Game game + ) { return computerPlayer.hasProtectionFrom(source, game); } @Override - public int drawCards(int num, Game game) { + public int drawCards(int num, Game game + ) { return computerPlayer.drawCards(num, game); } @Override - public int drawCards(int num, Game game, List appliedEffects) { + public int drawCards(int num, Game game, + List appliedEffects + ) { return computerPlayer.drawCards(num, game, appliedEffects); } @Override - public void discardToMax(Game game) { + public void discardToMax(Game game + ) { computerPlayer.discardToMax(game); } @Override - public boolean putInHand(Card card, Game game) { + public boolean putInHand(Card card, Game game + ) { return computerPlayer.putInHand(card, game); } @Override - public boolean removeFromHand(Card card, Game game) { + public boolean removeFromHand(Card card, Game game + ) { return computerPlayer.removeFromHand(card, game); } @Override - public boolean removeFromLibrary(Card card, Game game) { + public boolean removeFromLibrary(Card card, Game game + ) { return computerPlayer.removeFromLibrary(card, game); } @Override - public void discard(int amount, Ability source, Game game) { + public void discard(int amount, Ability source, + Game game + ) { computerPlayer.discard(amount, source, game); } @Override - public Card discardOne(boolean random, Ability source, Game game) { + public Card discardOne(boolean random, Ability source, + Game game + ) { return computerPlayer.discardOne(random, source, game); } @Override - public Cards discard(int amount, boolean random, Ability source, Game game) { + public Cards discard(int amount, boolean random, Ability source, + Game game + ) { return computerPlayer.discard(amount, random, source, game); } @Override - public boolean discard(Card card, Ability source, Game game) { + public boolean discard(Card card, Ability source, + Game game + ) { return computerPlayer.discard(card, source, game); } @@ -1568,52 +1705,67 @@ public class TestPlayer implements Player { } @Override - public boolean addAttachment(UUID permanentId, Game game) { + public boolean addAttachment(UUID permanentId, Game game + ) { return computerPlayer.addAttachment(permanentId, game); } @Override - public boolean removeAttachment(Permanent attachment, Game game) { + public boolean removeAttachment(Permanent attachment, Game game + ) { return computerPlayer.removeAttachment(attachment, game); } @Override - public boolean removeFromBattlefield(Permanent permanent, Game game) { + public boolean removeFromBattlefield(Permanent permanent, Game game + ) { return computerPlayer.removeFromBattlefield(permanent, game); } @Override - public boolean putInGraveyard(Card card, Game game) { + public boolean putInGraveyard(Card card, Game game + ) { return computerPlayer.putInGraveyard(card, game); } @Override - public boolean removeFromGraveyard(Card card, Game game) { + public boolean removeFromGraveyard(Card card, Game game + ) { return computerPlayer.removeFromGraveyard(card, game); } @Override - public boolean putCardsOnBottomOfLibrary(Card card, Game game, Ability source, boolean anyOrder) { + public boolean putCardsOnBottomOfLibrary(Card card, Game game, + Ability source, boolean anyOrder + ) { return computerPlayer.putCardsOnBottomOfLibrary(card, game, source, anyOrder); } @Override - public boolean putCardsOnBottomOfLibrary(Cards cards, Game game, Ability source, boolean anyOrder) { + public boolean putCardsOnBottomOfLibrary(Cards cards, Game game, + Ability source, boolean anyOrder + ) { return computerPlayer.putCardsOnBottomOfLibrary(cards, game, source, anyOrder); } @Override - public boolean putCardOnTopXOfLibrary(Card card, Game game, Ability source, int xFromTheTop) { + public boolean putCardOnTopXOfLibrary(Card card, Game game, + Ability source, int xFromTheTop + ) { return computerPlayer.putCardOnTopXOfLibrary(card, game, source, xFromTheTop); } @Override - public boolean putCardsOnTopOfLibrary(Cards cards, Game game, Ability source, boolean anyOrder) { + public boolean putCardsOnTopOfLibrary(Cards cards, Game game, + Ability source, boolean anyOrder + ) { return computerPlayer.putCardsOnTopOfLibrary(cards, game, source, anyOrder); } @Override - public void setCastSourceIdWithAlternateMana(UUID sourceId, ManaCosts manaCosts, Costs costs) { + public void setCastSourceIdWithAlternateMana(UUID sourceId, ManaCosts manaCosts, + Costs costs + ) { computerPlayer.setCastSourceIdWithAlternateMana(sourceId, manaCosts, costs); } @@ -1638,27 +1790,36 @@ public class TestPlayer implements Player { } @Override - public boolean cast(SpellAbility ability, Game game, boolean noMana, MageObjectReference reference) { + public boolean cast(SpellAbility ability, Game game, + boolean noMana, MageObjectReference reference + ) { return computerPlayer.cast(ability, game, noMana, reference); } @Override - public boolean playCard(Card card, Game game, boolean noMana, boolean ignoreTiming, MageObjectReference reference) { + public boolean playCard(Card card, Game game, + boolean noMana, boolean ignoreTiming, MageObjectReference reference + ) { return computerPlayer.playCard(card, game, noMana, ignoreTiming, reference); } @Override - public boolean playLand(Card card, Game game, boolean ignoreTiming) { + public boolean playLand(Card card, Game game, + boolean ignoreTiming + ) { return computerPlayer.playLand(card, game, ignoreTiming); } @Override - public boolean triggerAbility(TriggeredAbility source, Game game) { + public boolean triggerAbility(TriggeredAbility source, Game game + ) { return computerPlayer.triggerAbility(source, game); } @Override - public LinkedHashMap getUseableActivatedAbilities(MageObject object, Zone zone, Game game) { + public LinkedHashMap getUseableActivatedAbilities(MageObject object, Zone zone, + Game game + ) { return computerPlayer.getUseableActivatedAbilities(object, zone, game); } @@ -1673,57 +1834,77 @@ public class TestPlayer implements Player { } @Override - public void shuffleLibrary(Ability source, Game game) { + public void shuffleLibrary(Ability source, Game game + ) { computerPlayer.shuffleLibrary(source, game); } @Override - public void revealCards(Ability source, Cards cards, Game game) { + public void revealCards(Ability source, Cards cards, + Game game + ) { computerPlayer.revealCards(source, cards, game); } @Override - public void revealCards(String name, Cards cards, Game game) { + public void revealCards(String name, Cards cards, + Game game + ) { computerPlayer.revealCards(name, cards, game); } @Override - public void revealCards(Ability source, String name, Cards cards, Game game) { + public void revealCards(Ability source, String name, + Cards cards, Game game + ) { computerPlayer.revealCards(name, cards, game); } @Override - public void revealCards(String name, Cards cards, Game game, boolean postToLog) { + public void revealCards(String name, Cards cards, + Game game, boolean postToLog + ) { computerPlayer.revealCards(name, cards, game, postToLog); } @Override - public void revealCards(Ability source, String name, Cards cards, Game game, boolean postToLog) { + public void revealCards(Ability source, String name, + Cards cards, Game game, + boolean postToLog + ) { computerPlayer.revealCards(name, cards, game, postToLog); } @Override - public void lookAtCards(String name, Cards cards, Game game) { + public void lookAtCards(String name, Cards cards, + Game game + ) { computerPlayer.lookAtCards(name, cards, game); } @Override - public void lookAtCards(Ability source, String name, Cards cards, Game game) { + public void lookAtCards(Ability source, String name, + Cards cards, Game game + ) { computerPlayer.lookAtCards(source, name, cards, game); } @Override - public void lookAtCards(String name, Card card, Game game) { + public void lookAtCards(String name, Card card, + Game game + ) { computerPlayer.lookAtCards(name, card, game); } @Override - public void phasing(Game game) { + public void phasing(Game game + ) { computerPlayer.phasing(game); } @Override - public void untap(Game game) { + public void untap(Game game + ) { computerPlayer.untap(game); } @@ -1778,22 +1959,28 @@ public class TestPlayer implements Player { } @Override - public void initLife(int life) { + public void initLife(int life + ) { computerPlayer.initLife(life); } @Override - public void setLife(int life, Game game, UUID sourceId) { + public void setLife(int life, Game game, + UUID sourceId + ) { computerPlayer.setLife(life, game, sourceId); } @Override - public void setLife(int life, Game game, Ability source) { + public void setLife(int life, Game game, + Ability source + ) { computerPlayer.setLife(life, game, source); } @Override - public void setLifeTotalCanChange(boolean lifeTotalCanChange) { + public void setLifeTotalCanChange(boolean lifeTotalCanChange + ) { computerPlayer.setLifeTotalCanChange(lifeTotalCanChange); } @@ -1813,12 +2000,15 @@ public class TestPlayer implements Player { } @Override - public void setCanLoseLife(boolean canLoseLife) { + public void setCanLoseLife(boolean canLoseLife + ) { computerPlayer.setCanLoseLife(canLoseLife); } @Override - public int loseLife(int amount, Game game, boolean atCombat) { + public int loseLife(int amount, Game game, + boolean atCombat + ) { return computerPlayer.loseLife(amount, game, atCombat); } @@ -1828,37 +2018,49 @@ public class TestPlayer implements Player { } @Override - public void setCanGainLife(boolean canGainLife) { + public void setCanGainLife(boolean canGainLife + ) { computerPlayer.setCanGainLife(canGainLife); } @Override - public int gainLife(int amount, Game game, Ability source) { + public int gainLife(int amount, Game game, + Ability source + ) { return computerPlayer.gainLife(amount, game, source); } @Override - public int gainLife(int amount, Game game, UUID sourceId) { + public int gainLife(int amount, Game game, + UUID sourceId + ) { return computerPlayer.gainLife(amount, game, sourceId); } @Override - public int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable) { + public int damage(int damage, UUID sourceId, + Game game, boolean combatDamage, boolean preventable + ) { return computerPlayer.damage(damage, sourceId, game, combatDamage, preventable); } @Override - public int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable, List appliedEffects) { + public int damage(int damage, UUID sourceId, + Game game, boolean combatDamage, boolean preventable, List appliedEffects + ) { return computerPlayer.damage(damage, sourceId, game, combatDamage, preventable, appliedEffects); } @Override - public boolean addCounters(Counter counter, Game game) { + public boolean addCounters(Counter counter, Game game + ) { return computerPlayer.addCounters(counter, game); } @Override - public void removeCounters(String name, int amount, Ability source, Game game) { + public void removeCounters(String name, int amount, Ability source, + Game game + ) { computerPlayer.removeCounters(name, amount, source, game); } @@ -1873,7 +2075,8 @@ public class TestPlayer implements Player { } @Override - public void setLandsPerTurn(int landsPerTurn) { + public void setLandsPerTurn(int landsPerTurn + ) { computerPlayer.setLandsPerTurn(landsPerTurn); } @@ -1883,7 +2086,8 @@ public class TestPlayer implements Player { } @Override - public void setLoyaltyUsePerTurn(int loyaltyUsePerTurn) { + public void setLoyaltyUsePerTurn(int loyaltyUsePerTurn + ) { computerPlayer.setLoyaltyUsePerTurn(loyaltyUsePerTurn); } @@ -1893,12 +2097,14 @@ public class TestPlayer implements Player { } @Override - public void setMaxHandSize(int maxHandSize) { + public void setMaxHandSize(int maxHandSize + ) { computerPlayer.setMaxHandSize(maxHandSize); } @Override - public void setMaxAttackedBy(int maxAttackedBy) { + public void setMaxAttackedBy(int maxAttackedBy + ) { computerPlayer.setMaxAttackedBy(maxAttackedBy); } @@ -1908,27 +2114,32 @@ public class TestPlayer implements Player { } @Override - public void setResponseString(String responseString) { + public void setResponseString(String responseString + ) { computerPlayer.setResponseString(responseString); } @Override - public void setResponseManaType(UUID manaTypePlayerId, ManaType responseManaType) { + public void setResponseManaType(UUID manaTypePlayerId, ManaType responseManaType + ) { computerPlayer.setResponseManaType(manaTypePlayerId, responseManaType); } @Override - public void setResponseUUID(UUID responseUUID) { + public void setResponseUUID(UUID responseUUID + ) { computerPlayer.setResponseUUID(responseUUID); } @Override - public void setResponseBoolean(Boolean responseBoolean) { + public void setResponseBoolean(Boolean responseBoolean + ) { computerPlayer.setResponseBoolean(responseBoolean); } @Override - public void setResponseInteger(Integer responseInteger) { + public void setResponseInteger(Integer responseInteger + ) { computerPlayer.setResponseInteger(responseInteger); } @@ -1938,7 +2149,8 @@ public class TestPlayer implements Player { } @Override - public void pass(Game game) { + public void pass(Game game + ) { computerPlayer.pass(game); } @@ -1958,27 +2170,33 @@ public class TestPlayer implements Player { } @Override - public void quit(Game game) { + public void quit(Game game + ) { computerPlayer.quit(game); } @Override - public void timerTimeout(Game game) { + public void timerTimeout(Game game + ) { computerPlayer.timerTimeout(game); } @Override - public void idleTimeout(Game game) { + public void idleTimeout(Game game + ) { computerPlayer.idleTimeout(game); } @Override - public void concede(Game game) { + public void concede(Game game + ) { computerPlayer.concede(game); } @Override - public void sendPlayerAction(mage.constants.PlayerAction playerAction, Game game, Object data) { + public void sendPlayerAction(mage.constants.PlayerAction playerAction, Game game, + Object data + ) { computerPlayer.sendPlayerAction(playerAction, game, data); } @@ -1993,7 +2211,8 @@ public class TestPlayer implements Player { } @Override - public void lost(Game game) { + public void lost(Game game + ) { computerPlayer.lost(game); } @@ -2003,17 +2222,20 @@ public class TestPlayer implements Player { } @Override - public void drew(Game game) { + public void drew(Game game + ) { computerPlayer.drew(game); } @Override - public void lostForced(Game game) { + public void lostForced(Game game + ) { computerPlayer.lostForced(game); } @Override - public boolean canLose(Game game) { + public boolean canLose(Game game + ) { return computerPlayer.canLose(game); } @@ -2038,37 +2260,51 @@ public class TestPlayer implements Player { } @Override - public void declareAttacker(UUID attackerId, UUID defenderId, Game game, boolean allowUndo) { + public void declareAttacker(UUID attackerId, UUID defenderId, + Game game, boolean allowUndo + ) { computerPlayer.declareAttacker(attackerId, defenderId, game, allowUndo); } @Override - public void declareBlocker(UUID defenderId, UUID blockerId, UUID attackerId, Game game) { + public void declareBlocker(UUID defenderId, UUID blockerId, + UUID attackerId, Game game + ) { computerPlayer.declareBlocker(defenderId, blockerId, attackerId, game); } @Override - public void declareBlocker(UUID defenderId, UUID blockerId, UUID attackerId, Game game, boolean allowUndo) { + public void declareBlocker(UUID defenderId, UUID blockerId, + UUID attackerId, Game game, + boolean allowUndo + ) { computerPlayer.declareBlocker(defenderId, blockerId, attackerId, game, allowUndo); } @Override - public boolean searchLibrary(TargetCardInLibrary target, Game game) { + public boolean searchLibrary(TargetCardInLibrary target, Game game + ) { return computerPlayer.searchLibrary(target, game); } @Override - public boolean searchLibrary(TargetCardInLibrary target, Game game, boolean triggerEvents) { + public boolean searchLibrary(TargetCardInLibrary target, Game game, + boolean triggerEvents + ) { return computerPlayer.searchLibrary(target, game, triggerEvents); } @Override - public boolean searchLibrary(TargetCardInLibrary target, Game game, UUID targetPlayerId) { + public boolean searchLibrary(TargetCardInLibrary target, Game game, + UUID targetPlayerId + ) { return computerPlayer.searchLibrary(target, game, targetPlayerId); } @Override - public boolean searchLibrary(TargetCardInLibrary target, Game game, UUID targetPlayerId, boolean triggerEvents) { + public boolean searchLibrary(TargetCardInLibrary target, Game game, + UUID targetPlayerId, boolean triggerEvents + ) { return computerPlayer.searchLibrary(target, game, targetPlayerId, triggerEvents); } @@ -2083,37 +2319,45 @@ public class TestPlayer implements Player { } @Override - public boolean flipCoin(Game game, ArrayList appliedEffects) { + public boolean flipCoin(Game game, ArrayList appliedEffects + ) { return computerPlayer.flipCoin(game, appliedEffects); } @Override - public int rollDice(Game game, int numSides) { + public int rollDice(Game game, int numSides + ) { return computerPlayer.rollDice(game, numSides); } @Override - public int rollDice(Game game, ArrayList appliedEffects, int numSides) { + public int rollDice(Game game, ArrayList appliedEffects, + int numSides + ) { return computerPlayer.rollDice(game, appliedEffects, numSides); } @Override - public List getAvailableAttackers(Game game) { + public List getAvailableAttackers(Game game + ) { return computerPlayer.getAvailableAttackers(game); } @Override - public List getAvailableAttackers(UUID defenderId, Game game) { + public List getAvailableAttackers(UUID defenderId, Game game + ) { return computerPlayer.getAvailableAttackers(defenderId, game); } @Override - public List getAvailableBlockers(Game game) { + public List getAvailableBlockers(Game game + ) { return computerPlayer.getAvailableBlockers(game); } @Override - public ManaOptions getManaAvailable(Game game) { + public ManaOptions getManaAvailable(Game game + ) { return computerPlayer.getManaAvailable(game); } @@ -2466,7 +2710,7 @@ public class TestPlayer implements Player { @Override public boolean choose(Outcome outcome, Target target, - UUID sourceId, Game game + UUID sourceId, Game game ) { // needed to call here the TestPlayer because it's overwitten return choose(outcome, target, sourceId, game, null); @@ -2474,7 +2718,7 @@ public class TestPlayer implements Player { @Override public boolean choose(Outcome outcome, Cards cards, - TargetCard target, Game game + TargetCard target, Game game ) { if (!choices.isEmpty()) { for (String choose2 : choices) { @@ -2506,7 +2750,7 @@ public class TestPlayer implements Player { @Override public boolean chooseTargetAmount(Outcome outcome, TargetAmount target, - Ability source, Game game + Ability source, Game game ) { return computerPlayer.chooseTargetAmount(outcome, target, source, game); } @@ -2519,15 +2763,15 @@ public class TestPlayer implements Player { @Override public boolean choosePile(Outcome outcome, String message, - List pile1, List pile2, - Game game + List pile1, List pile2, + Game game ) { return computerPlayer.choosePile(outcome, message, pile1, pile2, game); } @Override public boolean playMana(Ability ability, ManaCost unpaid, - String promptText, Game game + String promptText, Game game ) { groupsForTargetHandling = null; return computerPlayer.playMana(ability, unpaid, promptText, game); @@ -2541,15 +2785,15 @@ public class TestPlayer implements Player { @Override public UUID chooseBlockerOrder(List blockers, CombatGroup combatGroup, - List blockerOrder, Game game + List blockerOrder, Game game ) { return computerPlayer.chooseBlockerOrder(blockers, combatGroup, blockerOrder, game); } @Override public void assignDamage(int damage, List targets, - String singleTargetName, UUID sourceId, - Game game + String singleTargetName, UUID sourceId, + Game game ) { computerPlayer.assignDamage(damage, targets, singleTargetName, sourceId, game); } @@ -2568,14 +2812,14 @@ public class TestPlayer implements Player { @Override public void pickCard(List cards, Deck deck, - Draft draft + Draft draft ) { computerPlayer.pickCard(cards, deck, draft); } @Override public boolean scry(int value, Ability source, - Game game + Game game ) { // Don't scry at the start of the game. if (game.getTurnNum() == 1 && game.getStep() == null) { @@ -2586,44 +2830,44 @@ public class TestPlayer implements Player { @Override public boolean surveil(int value, Ability source, - Game game + Game game ) { return computerPlayer.surveil(value, source, game); } @Override public boolean moveCards(Card card, Zone toZone, - Ability source, Game game + Ability source, Game game ) { return computerPlayer.moveCards(card, toZone, source, game); } @Override public boolean moveCards(Card card, Zone toZone, - Ability source, Game game, - boolean tapped, boolean faceDown, boolean byOwner, List appliedEffects + Ability source, Game game, + boolean tapped, boolean faceDown, boolean byOwner, List appliedEffects ) { return computerPlayer.moveCards(card, toZone, source, game, tapped, faceDown, byOwner, appliedEffects); } @Override public boolean moveCards(Cards cards, Zone toZone, - Ability source, Game game + Ability source, Game game ) { return computerPlayer.moveCards(cards, toZone, source, game); } @Override public boolean moveCards(Set cards, Zone toZone, - Ability source, Game game + Ability source, Game game ) { return computerPlayer.moveCards(cards, toZone, source, game); } @Override public boolean moveCards(Set cards, Zone toZone, - Ability source, Game game, - boolean tapped, boolean faceDown, boolean byOwner, List appliedEffects + Ability source, Game game, + boolean tapped, boolean faceDown, boolean byOwner, List appliedEffects ) { return computerPlayer.moveCards(cards, toZone, source, game, tapped, faceDown, byOwner, appliedEffects); } diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestPlayerBase.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestPlayerBase.java index 37da99ab428..b514cc68b4d 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestPlayerBase.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestPlayerBase.java @@ -10,6 +10,8 @@ import java.util.Scanner; import java.util.regex.Matcher; import java.util.regex.Pattern; import mage.cards.Card; +import mage.cards.decks.Deck; +import mage.cards.decks.DeckCardLists; import mage.cards.repository.CardInfo; import mage.cards.repository.CardRepository; import mage.constants.PhaseStep; @@ -54,6 +56,8 @@ public abstract class MageTestPlayerBase { protected Map> commands = new HashMap<>(); + protected static Map loadedDeckCardLists = new HashMap<>(); // test decks buffer + protected TestPlayer playerA; protected TestPlayer playerB; protected TestPlayer playerC; diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java index bf2a95d8702..b858d8609b5 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java @@ -1,11 +1,11 @@ package org.mage.test.serverside.base.impl; -import mage.MageInt; import mage.Mana; import mage.ObjectColor; import mage.abilities.Ability; import mage.cards.Card; import mage.cards.decks.Deck; +import mage.cards.decks.DeckCardLists; import mage.cards.decks.importer.DeckImporterUtil; import mage.cards.repository.CardInfo; import mage.cards.repository.CardRepository; @@ -49,8 +49,10 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement public static final String NO_TARGET = "NO_TARGET"; public static final String CHECK_COMMAND_PT = "PT"; + public static final String CHECK_COMMAND_LIFE = "LIFE"; public static final String CHECK_COMMAND_ABILITY = "ABILITY"; public static final String CHECK_COMMAND_PERMANENT_COUNT = "PERMANENT_COUNT"; + public static final String CHECK_COMMAND_EXILE_COUNT = "EXILE_COUNT"; public static final String CHECK_COMMAND_HAND_COUNT = "HAND_COUNT"; public static final String CHECK_COMMAND_COLOR = "COLOR"; public static final String CHECK_COMMAND_SUBTYPE = "SUBTYPE"; @@ -64,7 +66,6 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement protected String deckNameD; protected enum ExpectedType { - TURN_NUMBER, RESULT, LIFE, @@ -165,12 +166,21 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement protected TestPlayer createPlayer(Game game, TestPlayer player, String name, String deckName) throws GameException { player = createNewPlayer(name, game.getRangeOfInfluence()); player.setTestMode(true); + logger.debug("Loading deck..."); - Deck deck = Deck.load(DeckImporterUtil.importDeck(deckName), false, false); + DeckCardLists list; + if (loadedDeckCardLists.containsKey(deckName)) { + list = loadedDeckCardLists.get(deckName); + } else { + list = DeckImporterUtil.importDeck(deckName); + loadedDeckCardLists.put(deckName, list); + } + Deck deck = Deck.load(list, false, false); logger.debug("Done!"); if (deck.getCards().size() < 40) { throw new IllegalArgumentException("Couldn't load deck, deck size=" + deck.getCards().size()); } + game.loadCards(deck.getCards(), player.getId()); game.loadCards(deck.getSideboard(), player.getId()); game.addPlayer(player, deck); @@ -240,6 +250,10 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement check(checkName, turnNum, step, player, CHECK_COMMAND_PT, permanentName, power.toString(), toughness.toString()); } + public void checkLife(String checkName, int turnNum, PhaseStep step, TestPlayer player, Integer life) { + check(checkName, turnNum, step, player, CHECK_COMMAND_LIFE, life.toString()); + } + public void checkAbility(String checkName, int turnNum, PhaseStep step, TestPlayer player, String permanentName, Class abilityClass, Boolean mustHave) { check(checkName, turnNum, step, player, CHECK_COMMAND_ABILITY, permanentName, abilityClass.getName(), mustHave.toString()); } @@ -248,6 +262,10 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement check(checkName, turnNum, step, player, CHECK_COMMAND_PERMANENT_COUNT, permanentName, count.toString()); } + public void checkExileCount(String checkName, int turnNum, PhaseStep step, TestPlayer player, String permanentName, Integer count) { + check(checkName, turnNum, step, player, CHECK_COMMAND_EXILE_COUNT, permanentName, count.toString()); + } + public void checkHandCount(String checkName, int turnNum, PhaseStep step, TestPlayer player, Integer count) { check(checkName, turnNum, step, player, CHECK_COMMAND_HAND_COUNT, count.toString()); } diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/deck/DeckValidatorTest.java b/Mage.Tests/src/test/java/org/mage/test/serverside/deck/DeckValidatorTest.java index e472754c2a9..3feddbd4eba 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/deck/DeckValidatorTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/deck/DeckValidatorTest.java @@ -59,13 +59,9 @@ public class DeckValidatorTest extends MageTestBase { } @Test - public void testStandardValid() { + public void testStandardDeckCardsAmountValid() { ArrayList deck = new ArrayList<>(); - - deck.add(new CardNameAmount("MPS-AKH", 28, 4)); // Rhonas the Indomitable - deck.add(new CardNameAmount("Built to Smash", 4)); - deck.add(new CardNameAmount("Heroic Intervention", 4)); - deck.add(new CardNameAmount("Mountain", 48)); + deck.add(new CardNameAmount("Mountain", 60)); DeckValidator validator = new Standard(); boolean validationSuccessful = testDeckValid(validator, deck); @@ -73,13 +69,9 @@ public class DeckValidatorTest extends MageTestBase { } @Test - public void testStandardNotValid() { + public void testStandardDeckCardsAmountNotValid() { ArrayList deck = new ArrayList<>(); - - deck.add(new CardNameAmount("MPS-AKH", 28, 4)); // Rhonas the Indomitable - deck.add(new CardNameAmount("Built to Smash", 4)); - deck.add(new CardNameAmount("Heroic Intervention", 4)); - deck.add(new CardNameAmount("Mountain", 47)); + deck.add(new CardNameAmount("Mountain", 59)); ArrayList sideboard = new ArrayList<>(); sideboard.add(new CardNameAmount("Mountain", 16)); diff --git a/Mage.Verify/pom.xml b/Mage.Verify/pom.xml index 90c41da8661..cb1f3be8672 100644 --- a/Mage.Verify/pom.xml +++ b/Mage.Verify/pom.xml @@ -32,7 +32,7 @@ com.fasterxml.jackson.core jackson-databind - 2.6.3 + 2.9.7 @@ -67,7 +67,7 @@ org.apache.maven.plugins maven-compiler-plugin - diff --git a/Mage.Verify/src/main/java/mage/verify/Booster.java b/Mage.Verify/src/main/java/mage/verify/Booster.java new file mode 100644 index 00000000000..161dcfff1d2 --- /dev/null +++ b/Mage.Verify/src/main/java/mage/verify/Booster.java @@ -0,0 +1,8 @@ +package mage.verify; + +public class Booster { + + public Booster(String mythic){ + + } +} diff --git a/Mage.Verify/src/main/java/mage/verify/ForeignData.java b/Mage.Verify/src/main/java/mage/verify/ForeignData.java new file mode 100644 index 00000000000..e410fb24d73 --- /dev/null +++ b/Mage.Verify/src/main/java/mage/verify/ForeignData.java @@ -0,0 +1,12 @@ +package mage.verify; + +public class ForeignData { + + + public String language; + public String name; + public String type; + public String text; + public String flavorText; + public String multiverseId; +} diff --git a/Mage.Verify/src/main/java/mage/verify/JsonCard.java b/Mage.Verify/src/main/java/mage/verify/JsonCard.java index a17d1a7b6bb..c7a0c49a4b5 100644 --- a/Mage.Verify/src/main/java/mage/verify/JsonCard.java +++ b/Mage.Verify/src/main/java/mage/verify/JsonCard.java @@ -3,10 +3,23 @@ package mage.verify; import java.util.List; class JsonCard { + public String uuid; + public String convertedManaCost; + public List foreignData; + public boolean isReserved; + public String side; + public Legality legalities; + public List printings; + public List rulings; + public List colorIndicator; public String layout; public String name; public List names; // flip cards public String manaCost; + public boolean hasFoil; + public boolean hasNonFoil; + public String multiverseId; + public String frameVersion; public int cmc; public List colors; public List colorIdentity; @@ -22,6 +35,10 @@ class JsonCard { public boolean starter; // only available in boxed sets and not in boosters public int hand; // vanguard public int life; // vanguard + public String originalText; + public String originalType; + public String flavorText; + public boolean isOnlineOnly; // only available in AllSets.json public String artist; @@ -37,4 +54,6 @@ class JsonCard { public String border; public String watermark; public boolean timeshifted; + public String borderColor; + public boolean isOversized; } diff --git a/Mage.Verify/src/main/java/mage/verify/JsonSet.java b/Mage.Verify/src/main/java/mage/verify/JsonSet.java index 831721937fd..466ebbfb630 100644 --- a/Mage.Verify/src/main/java/mage/verify/JsonSet.java +++ b/Mage.Verify/src/main/java/mage/verify/JsonSet.java @@ -1,5 +1,7 @@ package mage.verify; +import com.fasterxml.jackson.annotation.JsonIgnore; + import java.util.List; import java.util.Map; @@ -21,4 +23,14 @@ class JsonSet { public String mkm_id; public String mkm_name; public Map translations; + public int baseSetSize; + @JsonIgnore + public List boosterV3; + public String borderColor; + public Meta meta; + public String mtgoCode; + public List tokens; + public int totalSetSize; + public boolean isOnlineOnly; + public boolean isFoilOnly; } diff --git a/Mage.Verify/src/main/java/mage/verify/Legality.java b/Mage.Verify/src/main/java/mage/verify/Legality.java new file mode 100644 index 00000000000..925bc2189e7 --- /dev/null +++ b/Mage.Verify/src/main/java/mage/verify/Legality.java @@ -0,0 +1,19 @@ +package mage.verify; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class Legality { + @JsonProperty("1v1") + public String oneVersusOne; + public String commander; + public String duel; + public String legacy; + public String penny; + public String vintage; +public String frontier; +public String modern; +public String pauper; +public String brawl; +public String future; +public String standard; +} diff --git a/Mage.Verify/src/main/java/mage/verify/Meta.java b/Mage.Verify/src/main/java/mage/verify/Meta.java new file mode 100644 index 00000000000..4a93171da0d --- /dev/null +++ b/Mage.Verify/src/main/java/mage/verify/Meta.java @@ -0,0 +1,6 @@ +package mage.verify; + +public class Meta { + public String date; + public String version; +} diff --git a/Mage.Verify/src/main/java/mage/verify/MtgJson.java b/Mage.Verify/src/main/java/mage/verify/MtgJson.java index 1919f8db0f8..4301ac0b6cb 100644 --- a/Mage.Verify/src/main/java/mage/verify/MtgJson.java +++ b/Mage.Verify/src/main/java/mage/verify/MtgJson.java @@ -12,8 +12,7 @@ import java.net.URL; import java.nio.file.Files; import java.nio.file.StandardCopyOption; import java.text.Normalizer; -import java.util.HashMap; -import java.util.Map; +import java.util.*; import java.util.zip.ZipInputStream; public final class MtgJson { @@ -61,6 +60,16 @@ public final class MtgJson { static { try { cards = loadAllCards(); + List oldKeys = new ArrayList<>(); + Map newKeys = new HashMap<>(); + for (String key : cards.keySet()) { + if (key.contains("(")) { + newKeys.put(key.replaceAll("\\(.*\\)", "").trim(), cards.get(key)); + oldKeys.add(key); + } + } + cards.putAll(newKeys); + cards.keySet().removeAll(oldKeys); addAliases(cards); } catch (IOException e) { throw new RuntimeException(e); @@ -95,7 +104,7 @@ public final class MtgJson { if (stream == null) { File file = new File(filename); if (!file.exists()) { - InputStream download = new URL("http://mtgjson.com/json/" + filename).openStream(); + InputStream download = new URL("http://mtgjson.com/v4/json/" + filename).openStream(); Files.copy(download, file.toPath(), StandardCopyOption.REPLACE_EXISTING); System.out.println("Downloaded " + filename + " to " + file.getAbsolutePath()); } else { @@ -133,6 +142,7 @@ public final class MtgJson { name = name.replace("'", "\""); // for Kongming, "Sleeping Dragon" & Pang Tong, "Young Phoenix" ref = reference.get(name); } + return ref; } diff --git a/Mage.Verify/src/main/java/mage/verify/Ruling.java b/Mage.Verify/src/main/java/mage/verify/Ruling.java new file mode 100644 index 00000000000..5bcb036329c --- /dev/null +++ b/Mage.Verify/src/main/java/mage/verify/Ruling.java @@ -0,0 +1,6 @@ +package mage.verify; + +public class Ruling { + public String text; + public String date; +} diff --git a/Mage.Verify/src/main/java/mage/verify/Token.java b/Mage.Verify/src/main/java/mage/verify/Token.java new file mode 100644 index 00000000000..c99ed0abc25 --- /dev/null +++ b/Mage.Verify/src/main/java/mage/verify/Token.java @@ -0,0 +1,19 @@ +package mage.verify; + +import java.util.List; + +public class Token { + public String artist; + public String borderColor; + public List colorIdentity; + public List colors; + public String name; + public String number; + public String power; + public String toughness; + public List reverseRelated; + public String text; + public String type; + public String uuid; + public String watermark; +} diff --git a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java index 34869ff85bd..fb16264f15f 100644 --- a/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java +++ b/Mage.Verify/src/test/java/mage/verify/VerifyCardDataTest.java @@ -1,15 +1,16 @@ package mage.verify; import mage.ObjectColor; +import mage.abilities.keyword.DevoidAbility; +import mage.abilities.keyword.MultikickerAbility; import mage.cards.*; import mage.cards.basiclands.BasicLand; import mage.constants.CardType; -import mage.constants.Constants; import mage.constants.Rarity; +import mage.constants.SubType; import mage.constants.SuperType; import mage.game.permanent.token.Token; import mage.game.permanent.token.TokenImpl; -import mage.util.CardUtil; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; @@ -230,7 +231,7 @@ public class VerifyCardDataTest { // replace codes for aliases String searchSet = MtgJson.mtgJsonToXMageCodes.getOrDefault(refSet.code, refSet.code); - ExpansionSet mageSet = Sets.findSet(searchSet); + ExpansionSet mageSet = Sets.findSet(searchSet.toUpperCase()); if (mageSet == null) { totalMissingSets = totalMissingSets + 1; totalMissingCards = totalMissingCards + refSet.cards.size(); @@ -381,9 +382,9 @@ public class VerifyCardDataTest { // check for (ExpansionSet.SetCardInfo card : set.getSetCardInfo()) { boolean cardHaveDoubleName = (doubleNames.getOrDefault(card.getName(), 0) > 1); - boolean cardHaveVariousSetting = card.getGraphicInfo() == null ? false : card.getGraphicInfo().getUsesVariousArt(); + boolean cardHaveVariousSetting = card.getGraphicInfo() != null && card.getGraphicInfo().getUsesVariousArt(); - if(cardHaveDoubleName && !cardHaveVariousSetting) { + if (cardHaveDoubleName && !cardHaveVariousSetting) { errorsList.add("error, founded double card names, but UsesVariousArt is not true: " + set.getCode() + " - " + set.getName() + " - " + card.getName() + " - " + card.getCardNumber()); } } @@ -567,17 +568,22 @@ public class VerifyCardDataTest { return; } - Collection expected = ref.colors; - ObjectColor color = card.getColor(null); - if (expected == null) { - expected = Collections.emptyList(); + Set expected = new HashSet<>(); + if (ref.colors != null) { + expected.addAll(ref.colors); } + if(card.isFlipCard()){ + expected.addAll(ref.colorIdentity); + } + + ObjectColor color = card.getColor(null); + if (expected.size() != color.getColorCount() - || (color.isBlack() && !expected.contains("Black")) - || (color.isBlue() && !expected.contains("Blue")) - || (color.isGreen() && !expected.contains("Green")) - || (color.isRed() && !expected.contains("Red")) - || (color.isWhite() && !expected.contains("White"))) { + || (color.isBlack() && !expected.contains("B")) + || (color.isBlue() && !expected.contains("U")) + || (color.isGreen() && !expected.contains("G")) + || (color.isRed() && !expected.contains("R")) + || (color.isWhite() && !expected.contains("W"))) { fail(card, "colors", color + " != " + expected); } } @@ -599,7 +605,7 @@ public class VerifyCardDataTest { } } - if (!eqSet(card.getSubtype(null).stream().map(p -> p.toString()).collect(Collectors.toSet()), expected)) { + if (!eqSet(card.getSubtype(null).stream().map(SubType::toString).collect(Collectors.toSet()), expected)) { fail(card, "subtypes", card.getSubtype(null) + " != " + expected); } } @@ -625,7 +631,12 @@ public class VerifyCardDataTest { return; } - // spells have only 1 abilities + // special check: kicker ability must be in rules + if (card.getAbilities().containsClass(MultikickerAbility.class) && card.getRules().stream().noneMatch(rule -> rule.contains("Multikicker"))) { + fail(card, "abilities", "card have Multikicker ability, but missing it in rules text"); + } + + // spells have only 1 ability if (card.isSorcery() || card.isInstant()) { return; } @@ -690,7 +701,7 @@ public class VerifyCardDataTest { String expected = ref.manaCost; String cost = join(card.getManaCost().getSymbols()); - if (cost != null && cost.isEmpty()) { + if (cost.isEmpty()) { cost = null; } if (cost != null) { diff --git a/Mage/pom.xml b/Mage/pom.xml index d7881372f8b..5666f64aff8 100644 --- a/Mage/pom.xml +++ b/Mage/pom.xml @@ -38,7 +38,7 @@ com.google.protobuf protobuf-java - ${protobuf.version} + 3.6.0 @@ -55,68 +55,31 @@ - - + - org.apache.maven.plugins - maven-dependency-plugin - ${maven-dependency-plugin.version} + com.github.os72 + protoc-jar-maven-plugin + 3.6.0.1 - copy-protoc - generate-sources - - copy - - - - - com.google.protobuf - protoc - ${protobuf.version} - ${os.detected.classifier} - exe - true - ${project.build.directory} - - - - - - - - - org.apache.maven.plugins - maven-antrun-plugin - ${maven-antrun-plugin.version} - - - exec-protoc - generate-sources - - - - - - - - - - - - - - - - - - - - - - - run - + generate-sources + + run + + + + com.google.protobuf:protoc:3.0.0 + + ${project.basedir}/src/main/proto + + + + java + none + ${project.build.directory}/generated-sources + + + @@ -124,7 +87,7 @@ org.codehaus.mojo build-helper-maven-plugin - ${build-helper-maven-plugin.version} + 1.12 add-classes @@ -139,20 +102,16 @@ - + + + + + mage - - - - - kr.motd.maven - os-maven-plugin - ${os-maven-plugin.version} - - + @@ -160,14 +119,6 @@ ${project.basedir}/src/main/proto ${project.build.directory}/generated-sources - - - 1.9.1 - 1.8 - 2.10 - 2.4.2 - 1.4.1.Final - 3.0.0-beta-1 diff --git a/Mage/src/main/java/mage/abilities/Ability.java b/Mage/src/main/java/mage/abilities/Ability.java index 9701e1a140a..4ef44edad6f 100644 --- a/Mage/src/main/java/mage/abilities/Ability.java +++ b/Mage/src/main/java/mage/abilities/Ability.java @@ -479,16 +479,7 @@ public interface Ability extends Controllable, Serializable { boolean activateAlternateOrAdditionalCosts(MageObject sourceObject, boolean noMana, Player controller, Game game); /** - * Sets the object that actually existed while a ability triggerd or an - * ability was activated. - * - * @param mageObject - * @param game - */ - void setSourceObject(MageObject mageObject, Game game); - - /** - * Returns the object that actually existed while a ability triggerd or an + * Returns the object that actually existed while a ability triggered or an * ability was activated. If not set yet, the current object will be * retrieved from the game. * @@ -497,6 +488,8 @@ public interface Ability extends Controllable, Serializable { */ MageObject getSourceObject(Game game); + void setSourceObjectZoneChangeCounter(int zoneChangeCounter); + int getSourceObjectZoneChangeCounter(); /** @@ -520,6 +513,8 @@ public interface Ability extends Controllable, Serializable { */ Permanent getSourcePermanentIfItStillExists(Game game); + Permanent getSourcePermanentOrLKI(Game game); + String getTargetDescription(Targets targets, Game game); void setCanFizzle(boolean canFizzle); diff --git a/Mage/src/main/java/mage/abilities/AbilityImpl.java b/Mage/src/main/java/mage/abilities/AbilityImpl.java index 6047e079694..481658c5078 100644 --- a/Mage/src/main/java/mage/abilities/AbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/AbilityImpl.java @@ -5,7 +5,6 @@ import java.util.Iterator; import java.util.List; import java.util.UUID; import mage.MageObject; -import mage.MageObjectReference; import mage.Mana; import mage.abilities.costs.*; import mage.abilities.costs.common.PayLifeCost; @@ -15,8 +14,8 @@ import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.Effect; import mage.abilities.effects.Effects; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.mana.DynamicManaEffect; import mage.abilities.effects.common.ManaEffect; +import mage.abilities.effects.mana.DynamicManaEffect; import mage.abilities.mana.ActivatedManaAbilityImpl; import mage.cards.Card; import mage.cards.SplitCard; @@ -67,7 +66,6 @@ public abstract class AbilityImpl implements Ability { protected boolean costModificationActive = true; protected boolean activated = false; protected boolean worksFaceDown = false; - protected MageObject sourceObject; protected int sourceObjectZoneChangeCounter; protected List watchers = new ArrayList<>(); protected List subAbilities = null; @@ -116,7 +114,6 @@ public abstract class AbilityImpl implements Ability { this.costModificationActive = ability.costModificationActive; this.worksFaceDown = ability.worksFaceDown; this.abilityWord = ability.abilityWord; - this.sourceObject = ability.sourceObject; this.sourceObjectZoneChangeCounter = ability.sourceObjectZoneChangeCounter; this.canFizzle = ability.canFizzle; this.targetAdjuster = ability.targetAdjuster; @@ -131,8 +128,6 @@ public abstract class AbilityImpl implements Ability { public void newId() { if (!(this instanceof MageSingleton)) { this.id = UUID.randomUUID(); -// this.sourceObject = null; -// this.sourceObjectZoneChangeCounter = -1; } getEffects().newId(); } @@ -226,8 +221,10 @@ public abstract class AbilityImpl implements Ability { return false; } - getSourceObject(game); - + MageObject sourceObject = getSourceObject(game); + if (getSourceObjectZoneChangeCounter() == 0) { + setSourceObjectZoneChangeCounter(game.getState().getZoneChangeCounter(getSourceId())); + } if (controller.isTestMode()) { if (!controller.addTargets(this, game)) { return false; @@ -1160,58 +1157,44 @@ public abstract class AbilityImpl implements Ability { @Override public MageObject getSourceObject(Game game) { - if (sourceObject == null) { - setSourceObject(null, game); - if (sourceObject == null) { - logger.warn("Source object could not be retrieved: " + this.getRule()); - } - } - return sourceObject; + return game.getObject(getSourceId()); } @Override public MageObject getSourceObjectIfItStillExists(Game game) { - MageObject currentObject = game.getObject(getSourceId()); - if (currentObject != null) { - if (sourceObject == null) { - setSourceObject(currentObject, game); - } - MageObjectReference mor = new MageObjectReference(currentObject, game); - if (mor.getZoneChangeCounter() == getSourceObjectZoneChangeCounter()) { - // source object has meanwhile not changed zone - return currentObject; - } + if (getSourceObjectZoneChangeCounter() == 0 + || getSourceObjectZoneChangeCounter() == game.getState().getZoneChangeCounter(getSourceId())) { + return game.getObject(getSourceId()); } return null; } @Override public Permanent getSourcePermanentIfItStillExists(Game game) { - if (sourceObject == null || !sourceObject.getId().equals(getSourceId())) { - setSourceObject(game.getObject(getSourceId()), game); - } - if (sourceObject instanceof Permanent) { - if (game.getState().getZoneChangeCounter(getSourceId()) == getSourceObjectZoneChangeCounter()) { - return (Permanent) sourceObject; - } + MageObject mageObject = getSourceObjectIfItStillExists(game); + if (mageObject instanceof Permanent) { + return (Permanent) mageObject; } return null; } @Override - public int getSourceObjectZoneChangeCounter() { - return sourceObjectZoneChangeCounter; + public Permanent getSourcePermanentOrLKI(Game game) { + if (getSourceObjectZoneChangeCounter() == 0 + || getSourceObjectZoneChangeCounter() == game.getState().getZoneChangeCounter(getSourceId())) { + return game.getPermanent(getSourceId()); + } + return (Permanent) game.getLastKnownInformation(getSourceId(), Zone.BATTLEFIELD, getSourceObjectZoneChangeCounter()); } @Override - public void setSourceObject(MageObject sourceObject, Game game) { - if (sourceObject == null) { - this.sourceObject = game.getObject(sourceId); - this.sourceObjectZoneChangeCounter = game.getState().getZoneChangeCounter(sourceId); - } else { - this.sourceObject = sourceObject; - this.sourceObjectZoneChangeCounter = this.sourceObject.getZoneChangeCounter(game); - } + public void setSourceObjectZoneChangeCounter(int sourceObjectZoneChangeCounter) { + this.sourceObjectZoneChangeCounter = sourceObjectZoneChangeCounter; + } + + @Override + public int getSourceObjectZoneChangeCounter() { + return sourceObjectZoneChangeCounter; } @Override diff --git a/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java b/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java index 6b48461d8f7..21fac77d7aa 100644 --- a/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/ActivatedAbilityImpl.java @@ -219,9 +219,9 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa } else { MageObject mageObject = game.getObject(this.sourceId); if (mageObject instanceof Emblem) { - return ((Emblem) mageObject).getControllerId().equals(playerId); + return ((Emblem) mageObject).isControlledBy(playerId); } else if (mageObject instanceof Plane) { - return ((Plane) mageObject).getControllerId().equals(playerId); + return ((Plane) mageObject).isControlledBy(playerId); } else if (game.getState().getZone(this.sourceId) != Zone.BATTLEFIELD) { return ((Card) mageObject).isOwnedBy(playerId); } diff --git a/Mage/src/main/java/mage/abilities/PlayLandAbility.java b/Mage/src/main/java/mage/abilities/PlayLandAbility.java index 939f28e328e..4fc440012e3 100644 --- a/Mage/src/main/java/mage/abilities/PlayLandAbility.java +++ b/Mage/src/main/java/mage/abilities/PlayLandAbility.java @@ -1,4 +1,3 @@ - package mage.abilities; import java.util.UUID; @@ -31,7 +30,10 @@ public class PlayLandAbility extends ActivatedAbilityImpl { return ActivationStatus.getFalse(); } //20091005 - 114.2a - return new ActivationStatus(game.isActivePlayer(playerId) && game.getPlayer(playerId).canPlayLand() && game.canPlaySorcery(playerId), permittingObject); + return new ActivationStatus(game.isActivePlayer(playerId) + && game.getPlayer(playerId).canPlayLand() + && game.canPlaySorcery(playerId), + permittingObject); } @Override diff --git a/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java b/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java index e341ee74be2..55e5bfb9c2f 100644 --- a/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/TriggeredAbilityImpl.java @@ -1,4 +1,3 @@ - package mage.abilities; import java.util.Locale; @@ -45,9 +44,6 @@ public abstract class TriggeredAbilityImpl extends AbilityImpl implements Trigge @Override public void trigger(Game game, UUID controllerId) { //20091005 - 603.4 - if (!(this instanceof DelayedTriggeredAbility)) { - setSourceObject(null, game); - } if (checkInterveningIfClause(game)) { game.addTriggeredAbility(this); } diff --git a/Mage/src/main/java/mage/abilities/common/ControllerPlaysLandTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/ControllerPlaysLandTriggeredAbility.java new file mode 100644 index 00000000000..252203870dc --- /dev/null +++ b/Mage/src/main/java/mage/abilities/common/ControllerPlaysLandTriggeredAbility.java @@ -0,0 +1,50 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package mage.abilities.common; + +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.game.permanent.Permanent; + +/** + * + * @author jeffwadsworth + */ +public class ControllerPlaysLandTriggeredAbility extends TriggeredAbilityImpl { + + public ControllerPlaysLandTriggeredAbility(Zone zone, Effect effect, Boolean optional) { + super(zone, effect, optional); + } + + public ControllerPlaysLandTriggeredAbility(ControllerPlaysLandTriggeredAbility ability) { + super(ability); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == EventType.LAND_PLAYED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Permanent land = game.getPermanent(event.getTargetId()); + return land.getControllerId().equals(controllerId); + } + + @Override + public ControllerPlaysLandTriggeredAbility copy() { + return new ControllerPlaysLandTriggeredAbility(this); + } + + @Override + public String getRule() { + return "Whenever you play a land, "; + } +} diff --git a/Mage/src/main/java/mage/abilities/common/CreatureEntersBattlefieldTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/CreatureEntersBattlefieldTriggeredAbility.java deleted file mode 100644 index ba3e9555d74..00000000000 --- a/Mage/src/main/java/mage/abilities/common/CreatureEntersBattlefieldTriggeredAbility.java +++ /dev/null @@ -1,123 +0,0 @@ - -package mage.abilities.common; - -import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.effects.Effect; -import mage.constants.Zone; -import mage.filter.common.FilterCreaturePermanent; -import mage.game.Game; -import mage.game.events.EntersTheBattlefieldEvent; -import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; -import mage.game.permanent.Permanent; -import mage.target.Target; -import mage.target.TargetPlayer; -import mage.target.common.TargetCreaturePermanent; - -/** - * - * @author North - */ -public class CreatureEntersBattlefieldTriggeredAbility extends TriggeredAbilityImpl { - - private boolean opponentController; - protected FilterCreaturePermanent filter = new FilterCreaturePermanent(); - - /** - * optional = false
- * opponentController = false - * - * @param effect - */ - public CreatureEntersBattlefieldTriggeredAbility(Effect effect) { - this(effect, false, false); - } - - /** - * opponentController = false - * - * @param effect - * @param optional - */ - public CreatureEntersBattlefieldTriggeredAbility(Effect effect, boolean optional) { - this(effect, optional, false); - } - - /** - * - * @param effect - * @param optional - * @param opponentController - */ - public CreatureEntersBattlefieldTriggeredAbility(Effect effect, boolean optional, boolean opponentController) { - this(Zone.BATTLEFIELD, effect, optional, opponentController); - - } - - /** - * @param zone - * @param effect - * @param optional - * @param opponentController - */ - public CreatureEntersBattlefieldTriggeredAbility(Zone zone, Effect effect, boolean optional, boolean opponentController) { - this(zone, effect, null, optional, opponentController); - } - - /** - * @param zone - * @param effect - * @param filter filter the triggering creatures - * @param optional - * @param opponentController - */ - public CreatureEntersBattlefieldTriggeredAbility(Zone zone, Effect effect, FilterCreaturePermanent filter, boolean optional, boolean opponentController) { - super(zone, effect, optional); - this.opponentController = opponentController; - if (filter != null) { - this.filter = filter; - } - } - - public CreatureEntersBattlefieldTriggeredAbility(CreatureEntersBattlefieldTriggeredAbility ability) { - super(ability); - this.opponentController = ability.opponentController; - this.filter = ability.filter; - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == EventType.ENTERS_THE_BATTLEFIELD; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - Permanent permanent = ((EntersTheBattlefieldEvent) event).getTarget(); - if (filter.match(permanent, sourceId, controllerId, game) - && (permanent.isControlledBy(this.controllerId) ^ opponentController)) { - if (!this.getTargets().isEmpty()) { - Target target = this.getTargets().get(0); - if (target instanceof TargetPlayer) { - target.add(permanent.getControllerId(), game); - } - if (target instanceof TargetCreaturePermanent) { - target.add(event.getTargetId(), game); - } - } - return true; - } - return false; - } - - @Override - public String getRule() { - return "Whenever a " + filter.getMessage() + " enters the battlefield under " - + (opponentController ? "an opponent's control, " : "your control, ") - + super.getRule(); - } - - @Override - public CreatureEntersBattlefieldTriggeredAbility copy() { - return new CreatureEntersBattlefieldTriggeredAbility(this); - } -} diff --git a/Mage/src/main/java/mage/abilities/common/DealsDamageToAPlayerAllTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/DealsDamageToAPlayerAllTriggeredAbility.java index 0b0a41eaa61..4c662d195c8 100644 --- a/Mage/src/main/java/mage/abilities/common/DealsDamageToAPlayerAllTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/DealsDamageToAPlayerAllTriggeredAbility.java @@ -13,7 +13,6 @@ import mage.game.permanent.Permanent; import mage.target.targetpointer.FixedTarget; /** - * * @author LevelX2 */ public class DealsDamageToAPlayerAllTriggeredAbility extends TriggeredAbilityImpl { @@ -28,7 +27,11 @@ public class DealsDamageToAPlayerAllTriggeredAbility extends TriggeredAbilityImp } public DealsDamageToAPlayerAllTriggeredAbility(Effect effect, FilterPermanent filter, boolean optional, SetTargetPointer setTargetPointer, boolean onlyCombat, boolean affectsDefendingPlayer) { - super(Zone.BATTLEFIELD, effect, optional); + this(Zone.BATTLEFIELD, effect, filter, optional, setTargetPointer, onlyCombat, affectsDefendingPlayer); + } + + public DealsDamageToAPlayerAllTriggeredAbility(Zone zone, Effect effect, FilterPermanent filter, boolean optional, SetTargetPointer setTargetPointer, boolean onlyCombat, boolean affectsDefendingPlayer) { + super(zone, effect, optional); this.setTargetPointer = setTargetPointer; this.filter = filter; this.onlyCombat = onlyCombat; @@ -57,27 +60,25 @@ public class DealsDamageToAPlayerAllTriggeredAbility extends TriggeredAbilityImp public boolean checkTrigger(GameEvent event, Game game) { if (!onlyCombat || ((DamagedPlayerEvent) event).isCombatDamage()) { Permanent permanent = game.getPermanent(event.getSourceId()); - if (permanent != null) { - if (filter.match(permanent, getSourceId(), getControllerId(), game)) { - for (Effect effect : this.getEffects()) { - effect.setValue("damage", event.getAmount()); - effect.setValue("sourceId", event.getSourceId()); - if (affectsDefendingPlayer) { - effect.setTargetPointer(new FixedTarget(event.getTargetId())); - continue; - } - switch (setTargetPointer) { - case PLAYER: - effect.setTargetPointer(new FixedTarget(permanent.getControllerId())); - break; - case PERMANENT: - effect.setTargetPointer(new FixedTarget(permanent.getId(), permanent.getZoneChangeCounter(game))); - break; - } - + if (permanent != null && filter.match(permanent, getSourceId(), getControllerId(), game)) { + for (Effect effect : this.getEffects()) { + effect.setValue("damage", event.getAmount()); + effect.setValue("sourceId", event.getSourceId()); + if (affectsDefendingPlayer) { + effect.setTargetPointer(new FixedTarget(event.getTargetId())); + continue; } - return true; + switch (setTargetPointer) { + case PLAYER: + effect.setTargetPointer(new FixedTarget(permanent.getControllerId())); + break; + case PERMANENT: + effect.setTargetPointer(new FixedTarget(permanent.getId(), permanent.getZoneChangeCounter(game))); + break; + } + } + return true; } } return false; diff --git a/Mage/src/main/java/mage/abilities/common/OpponentPlaysLandTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/OpponentPlaysLandTriggeredAbility.java new file mode 100644 index 00000000000..7249b6679e4 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/common/OpponentPlaysLandTriggeredAbility.java @@ -0,0 +1,49 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package mage.abilities.common; + +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.constants.Zone; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; + +/** + * + * @author jeffwadsworth + */ +public class OpponentPlaysLandTriggeredAbility extends TriggeredAbilityImpl { + + public OpponentPlaysLandTriggeredAbility(Zone zone, Effect effect, Boolean optional) { + super(zone, effect, optional); + } + + public OpponentPlaysLandTriggeredAbility(OpponentPlaysLandTriggeredAbility ability) { + super(ability); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.LAND_PLAYED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Permanent land = game.getPermanent(event.getTargetId()); + return game.getOpponents(controllerId).contains(land.getControllerId()); + } + + @Override + public OpponentPlaysLandTriggeredAbility copy() { + return new OpponentPlaysLandTriggeredAbility(this); + } + + @Override + public String getRule() { + return "Whenever an opponent plays a land, "; + } +} diff --git a/Mage/src/main/java/mage/abilities/common/SagaAbility.java b/Mage/src/main/java/mage/abilities/common/SagaAbility.java index 954ed8930d6..624221c13ef 100644 --- a/Mage/src/main/java/mage/abilities/common/SagaAbility.java +++ b/Mage/src/main/java/mage/abilities/common/SagaAbility.java @@ -1,4 +1,3 @@ - package mage.abilities.common; import mage.abilities.Ability; @@ -138,7 +137,8 @@ class ChapterTriggeredAbility extends TriggeredAbilityImpl { if (event.getTargetId().equals(getSourceId()) && event.getData().equals(CounterType.LORE.getName())) { int amountAdded = event.getAmount(); int loreCounters = amountAdded; - Permanent sourceSaga = game.getPermanentOrLKIBattlefield(getSourceId()); + //Permanent sourceSaga = game.getPermanentOrLKIBattlefield(getSourceId()); BUG #5393 + Permanent sourceSaga = game.getPermanent(getSourceId()); if (sourceSaga == null) { sourceSaga = game.getPermanentEntering(getSourceId()); } diff --git a/Mage/src/main/java/mage/abilities/common/delayed/OnLeaveReturnExiledToBattlefieldAbility.java b/Mage/src/main/java/mage/abilities/common/delayed/OnLeaveReturnExiledToBattlefieldAbility.java index c7c465dd247..8ec64e77600 100644 --- a/Mage/src/main/java/mage/abilities/common/delayed/OnLeaveReturnExiledToBattlefieldAbility.java +++ b/Mage/src/main/java/mage/abilities/common/delayed/OnLeaveReturnExiledToBattlefieldAbility.java @@ -1,4 +1,3 @@ - package mage.abilities.common.delayed; import java.util.LinkedHashSet; diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/AttackedThisTurnOpponentsCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/AttackedThisTurnOpponentsCount.java new file mode 100644 index 00000000000..69a12d8c92a --- /dev/null +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/AttackedThisTurnOpponentsCount.java @@ -0,0 +1,44 @@ + +package mage.abilities.dynamicvalue.common; + +import mage.abilities.Ability; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.Effect; +import mage.game.Game; +import mage.watchers.common.PlayersAttackedThisTurnWatcher; + +import java.util.UUID; + +/** + * @author JayDi85 + */ +public class AttackedThisTurnOpponentsCount implements DynamicValue { + + @Override + public int calculate(Game game, Ability sourceAbility, Effect effect) { + return this.calculate(game, sourceAbility.getControllerId()); + } + + public int calculate(Game game, UUID controllerId) { + PlayersAttackedThisTurnWatcher watcher = (PlayersAttackedThisTurnWatcher) game.getState().getWatchers().get(PlayersAttackedThisTurnWatcher.class.getSimpleName()); + if (watcher != null) { + return watcher.getAttackedOpponentsCount(controllerId); + } + return 0; + } + + @Override + public AttackedThisTurnOpponentsCount copy() { + return new AttackedThisTurnOpponentsCount(); + } + + @Override + public String toString() { + return "1"; + } + + @Override + public String getMessage() { + return "the number of opponents you attacked this turn"; + } +} diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/OpponentsCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/OpponentsCount.java new file mode 100644 index 00000000000..2435bb53add --- /dev/null +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/OpponentsCount.java @@ -0,0 +1,32 @@ +package mage.abilities.dynamicvalue.common; + +import mage.abilities.Ability; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.Effect; +import mage.game.Game; + +/** + * @author JayDi85 + */ +public class OpponentsCount implements DynamicValue { + + @Override + public int calculate(Game game, Ability sourceAbility, Effect effect) { + return game.getOpponents(sourceAbility.getControllerId()).size(); + } + + @Override + public OpponentsCount copy() { + return new OpponentsCount(); + } + + @Override + public String getMessage() { + return "number of opponents you have"; + } + + @Override + public String toString() { + return "1"; + } +} \ No newline at end of file diff --git a/Mage/src/main/java/mage/abilities/effects/RedirectionEffect.java b/Mage/src/main/java/mage/abilities/effects/RedirectionEffect.java index afea25b950a..262d7ab3bee 100644 --- a/Mage/src/main/java/mage/abilities/effects/RedirectionEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/RedirectionEffect.java @@ -1,4 +1,3 @@ - package mage.abilities.effects; import mage.MageObject; @@ -47,6 +46,7 @@ public abstract class RedirectionEffect extends ReplacementEffectImpl { this.redirectTarget = effect.redirectTarget; this.amountToRedirect = effect.amountToRedirect; this.usageType = effect.usageType; + this.applyEffectsCounter = effect.applyEffectsCounter; } @Override @@ -80,6 +80,7 @@ public abstract class RedirectionEffect extends ReplacementEffectImpl { if (applyEffectsCounter > 0) { if (applyEffectsCounter < game.getState().getApplyEffectsCounter()) { this.discard(); + return false; } } else { applyEffectsCounter = game.getState().getApplyEffectsCounter(); diff --git a/Mage/src/main/java/mage/abilities/effects/common/CopyPermanentEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CopyPermanentEffect.java index d74258916fa..c8aeb347db7 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CopyPermanentEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CopyPermanentEffect.java @@ -1,12 +1,12 @@ package mage.abilities.effects.common; -import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.SpellAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; +import mage.abilities.keyword.EnchantAbility; import mage.constants.Outcome; import mage.constants.SubType; import mage.filter.FilterPermanent; @@ -20,8 +20,9 @@ import mage.target.TargetPermanent; import mage.util.functions.ApplyToPermanent; import mage.util.functions.EmptyApplyToPermanent; +import java.util.UUID; + /** - * * @author BetaSteward_at_googlemail.com */ public class CopyPermanentEffect extends OneShotEffect { @@ -59,7 +60,9 @@ public class CopyPermanentEffect extends OneShotEffect { super(effect); this.filter = effect.filter.copy(); this.applier = effect.applier; - this.bluePrintPermanent = effect.bluePrintPermanent; + if (effect.bluePrintPermanent != null) { + this.bluePrintPermanent = effect.bluePrintPermanent.copy(); + } this.useTargetOfAbility = effect.useTargetOfAbility; } @@ -84,42 +87,70 @@ public class CopyPermanentEffect extends OneShotEffect { } if (copyFromPermanent != null) { bluePrintPermanent = game.copyPermanent(copyFromPermanent, sourcePermanent.getId(), source, applier); - - //if object is a copy of an aura, it needs to attach - if (bluePrintPermanent.hasSubtype(SubType.AURA, game)){ + if (bluePrintPermanent == null) { + return false; + } + + // if object is a copy of an aura, it needs to attach again for new target + if (bluePrintPermanent.hasSubtype(SubType.AURA, game)) { //copied from mage.cards.c.CopyEnchantment.java - Target target = bluePrintPermanent.getSpellAbility().getTargets().get(0); + + // permanent can be attached (Estrid's Mask) or enchant (Utopia Sprawl) + // TODO: fix Animate Dead -- it's can't be copied (can't retarget) Outcome auraOutcome = Outcome.BoostCreature; + Target auraTarget = null; + + // attach - search effect in spell ability (example: cast Utopia Sprawl, cast Estrid's Invocation on it) for (Ability ability : bluePrintPermanent.getAbilities()) { if (ability instanceof SpellAbility) { for (Effect effect : ability.getEffects()) { if (effect instanceof AttachEffect) { - auraOutcome = effect.getOutcome(); + if (bluePrintPermanent.getSpellAbility().getTargets().size() > 0) { + auraTarget = bluePrintPermanent.getSpellAbility().getTargets().get(0); + auraOutcome = effect.getOutcome(); + } } } } } - - /*if this is a copy of a copy, the copy's target has been - *copied and needs to be cleared - */ - { - UUID targetId = target.getFirstTarget(); - if(targetId != null) - target.remove(targetId); + + // enchant - search in all abilities (example: cast Estrid's Invocation on enchanted creature by Estrid, the Masked second ability, cast Estrid's Invocation on it) + if (auraTarget == null) { + for (Ability ability : bluePrintPermanent.getAbilities()) { + if (ability instanceof EnchantAbility) { + if (ability.getTargets().size() > 0) { // Animate Dead don't have targets + auraTarget = ability.getTargets().get(0); + for (Effect effect : ability.getEffects()) { + // first outcome + auraOutcome = effect.getOutcome(); + } + } + } + } } - - target.setNotTarget(true); - if (controller.choose(auraOutcome, target, source.getSourceId(), game)) { - UUID targetId = target.getFirstTarget(); - Permanent targetPermanent = game.getPermanent(targetId); - Player targetPlayer = game.getPlayer(targetId); - if (targetPermanent != null) { - targetPermanent.addAttachment(sourcePermanent.getId(), game); - } else if (targetPlayer != null) { - targetPlayer.addAttachment(sourcePermanent.getId(), game); - } else { - return false; + + /* if this is a copy of a copy, the copy's target has been + * copied and needs to be cleared + */ + if (auraTarget != null) { + // clear selected target + if (auraTarget.getFirstTarget() != null) { + auraTarget.remove(auraTarget.getFirstTarget()); + } + + // select new target + auraTarget.setNotTarget(true); + if (controller.choose(auraOutcome, auraTarget, source.getSourceId(), game)) { + UUID targetId = auraTarget.getFirstTarget(); + Permanent targetPermanent = game.getPermanent(targetId); + Player targetPlayer = game.getPlayer(targetId); + if (targetPermanent != null) { + targetPermanent.addAttachment(sourcePermanent.getId(), game); + } else if (targetPlayer != null) { + targetPlayer.addAttachment(sourcePermanent.getId(), game); + } else { + return false; + } } } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/DoUnlessAnyPlayerPaysEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DoUnlessAnyPlayerPaysEffect.java index 4c2208e00c6..8368248a156 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DoUnlessAnyPlayerPaysEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DoUnlessAnyPlayerPaysEffect.java @@ -1,4 +1,3 @@ - package mage.abilities.effects.common; import java.util.UUID; @@ -6,6 +5,8 @@ import mage.MageObject; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.costs.Cost; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.Effect; import mage.abilities.effects.Effects; @@ -22,15 +23,22 @@ import mage.util.CardUtil; public class DoUnlessAnyPlayerPaysEffect extends OneShotEffect { protected Effects executingEffects = new Effects(); - private final Cost cost; + protected Cost cost; private String chooseUseText; + protected DynamicValue genericMana; + + public DoUnlessAnyPlayerPaysEffect(Effect effect, DynamicValue genericMana) { + super(Outcome.Detriment); + this.genericMana = genericMana; + this.executingEffects.add(effect); + } public DoUnlessAnyPlayerPaysEffect(Effect effect, Cost cost) { this(effect, cost, null); } public DoUnlessAnyPlayerPaysEffect(Effect effect, Cost cost, String chooseUseText) { - super(Outcome.Benefit); + super(Outcome.Neutral); this.executingEffects.add(effect); this.cost = cost; this.chooseUseText = chooseUseText; @@ -38,8 +46,13 @@ public class DoUnlessAnyPlayerPaysEffect extends OneShotEffect { public DoUnlessAnyPlayerPaysEffect(final DoUnlessAnyPlayerPaysEffect effect) { super(effect); + if (effect.cost != null) { + this.cost = effect.cost.copy(); + } + if (effect.genericMana != null) { + this.genericMana = effect.genericMana.copy(); + } this.executingEffects = effect.executingEffects.copy(); - this.cost = effect.cost.copy(); this.chooseUseText = effect.chooseUseText; } @@ -51,11 +64,18 @@ public class DoUnlessAnyPlayerPaysEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); MageObject sourceObject = game.getObject(source.getSourceId()); - if (controller != null && sourceObject != null) { + Cost costToPay; + if (controller != null + && sourceObject != null) { + if (cost != null) { + costToPay = cost.copy(); + } else { + costToPay = new GenericManaCost(genericMana.calculate(game, source, this)); + } String message; if (chooseUseText == null) { String effectText = executingEffects.getText(source.getModes().getMode()); - message = "Pay " + cost.getText() + " to prevent (" + effectText.substring(0, effectText.length() - 1) + ")?"; + message = "Pay " + costToPay.getText() + " to prevent (" + effectText.substring(0, effectText.length() - 1) + ")?"; } else { message = chooseUseText; } @@ -65,9 +85,10 @@ public class DoUnlessAnyPlayerPaysEffect extends OneShotEffect { // check if any player is willing to pay for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { Player player = game.getPlayer(playerId); - if (player != null && cost.canPay(source, source.getSourceId(), player.getId(), game) && player.chooseUse(Outcome.Detriment, message, source, game)) { - cost.clearPaid(); - if (cost.pay(source, game, source.getSourceId(), player.getId(), false, null)) { + if (player != null + && costToPay.canPay(source, source.getSourceId(), player.getId(), game) && player.chooseUse(Outcome.Detriment, message, source, game)) { + costToPay.clearPaid(); + if (costToPay.pay(source, game, source.getSourceId(), player.getId(), false, null)) { if (!game.isSimulation()) { game.informPlayers(player.getLogName() + " pays the cost to prevent the effect"); } @@ -100,8 +121,18 @@ public class DoUnlessAnyPlayerPaysEffect extends OneShotEffect { if (!staticText.isEmpty()) { return staticText; } + StringBuilder sb = new StringBuilder(); + if (cost != null) { + sb.append(cost.getText()); + } else { + sb.append("{X}"); + } + if (genericMana != null && !genericMana.getMessage().isEmpty()) { + sb.append(", where X is "); + sb.append(genericMana.getMessage()); + } String effectsText = executingEffects.getText(mode); - return effectsText.substring(0, effectsText.length() - 1) + " unless any player pays " + cost.getText(); + return effectsText.substring(0, effectsText.length() - 1) + " unless any player pays " + sb.toString(); } @Override diff --git a/Mage/src/main/java/mage/abilities/effects/common/DontUntapInControllersUntapStepEnchantedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DontUntapInControllersUntapStepEnchantedEffect.java index 9371f56249b..c0e7b28f54b 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DontUntapInControllersUntapStepEnchantedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DontUntapInControllersUntapStepEnchantedEffect.java @@ -19,7 +19,7 @@ public class DontUntapInControllersUntapStepEnchantedEffect extends ContinuousRu } public DontUntapInControllersUntapStepEnchantedEffect(String description) { - super(Duration.WhileOnBattlefield, Outcome.Detriment, false, true); + super(Duration.WhileOnBattlefield, Outcome.Removal, false, true); staticText = "Enchanted " + description + " doesn't untap during its controller's untap step"; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/DrawCardSourceControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DrawCardSourceControllerEffect.java index b2e79fcd0ef..ce8822a9d1e 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DrawCardSourceControllerEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DrawCardSourceControllerEffect.java @@ -3,6 +3,7 @@ package mage.abilities.effects.common; import mage.abilities.Ability; import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.MultikickerCount; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.OneShotEffect; @@ -51,7 +52,7 @@ public class DrawCardSourceControllerEffect extends OneShotEffect { private void setText() { StringBuilder sb = new StringBuilder(); boolean oneCard = (amount instanceof StaticValue && amount.calculate(null, null, this) == 1) - || amount instanceof PermanentsOnBattlefieldCount || amount.toString().equals("1"); + || amount instanceof PermanentsOnBattlefieldCount || amount.toString().equals("1") || amount.toString().equals("a"); sb.append("draw ").append(oneCard ? "a" : CardUtil.numberToText(amount.toString())).append(" card"); if (!oneCard) { sb.append('s'); diff --git a/Mage/src/main/java/mage/abilities/effects/common/ExileAndGainLifeEqualPowerTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ExileAndGainLifeEqualPowerTargetEffect.java index 8126896e216..efa3ecd82d8 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/ExileAndGainLifeEqualPowerTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/ExileAndGainLifeEqualPowerTargetEffect.java @@ -14,7 +14,7 @@ import mage.players.Player; public class ExileAndGainLifeEqualPowerTargetEffect extends OneShotEffect { public ExileAndGainLifeEqualPowerTargetEffect() { - super(Outcome.GainLife); + super(Outcome.Removal); staticText = "Exile target creature. Its controller gains life equal to its power"; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/ExileUntilSourceLeavesEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ExileUntilSourceLeavesEffect.java index 496096af91c..bd541042375 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/ExileUntilSourceLeavesEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/ExileUntilSourceLeavesEffect.java @@ -19,7 +19,7 @@ import mage.util.CardUtil; public class ExileUntilSourceLeavesEffect extends OneShotEffect { public ExileUntilSourceLeavesEffect(String targetName) { - super(Outcome.Benefit); + super(Outcome.Removal); this.staticText = "exile target " + targetName + " an opponent controls until {this} leaves the battlefield"; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/FightTargetsEffect.java b/Mage/src/main/java/mage/abilities/effects/common/FightTargetsEffect.java index c0fd2f1ca51..db8b80f874c 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/FightTargetsEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/FightTargetsEffect.java @@ -1,6 +1,6 @@ - package mage.abilities.effects.common; +import java.util.UUID; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.effects.OneShotEffect; @@ -32,35 +32,58 @@ public class FightTargetsEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Card card = game.getCard(source.getSourceId()); if (card != null) { - // only if both targets are legal the effect will be applied - if (source.getTargets().get(0).isLegal(source, game) && source.getTargets().get(1).isLegal(source, game)) { - Permanent creature1 = game.getPermanent(source.getTargets().get(0).getFirstTarget()); - Permanent creature2 = game.getPermanent(source.getTargets().get(1).getFirstTarget()); - // 20110930 - 701.10 - if (creature1 != null && creature2 != null) { - if (creature1.isCreature() && creature2.isCreature()) { - return creature1.fight(creature2, source, game); - } + UUID target1Id = null; + UUID target2Id = null; + // first target is in target pointer, second target is a normal target + if (source.getTargets().size() < 2) { + if (!source.getTargets().get(0).isLegal(source, game)) { + return false; + } + target1Id = getTargetPointer().getFirst(game, source); + target2Id = source.getTargets().getFirstTarget(); + if (target1Id == target2Id) { + return false; + } + // two normal targets available, only if both targets are legal the effect will be applied + } else if (source.getTargets().get(0).isLegal(source, game) && source.getTargets().get(1).isLegal(source, game)) { + target1Id = source.getTargets().get(0).getFirstTarget(); + target2Id = source.getTargets().get(1).getFirstTarget(); + } + Permanent creature1 = game.getPermanent(target1Id); + Permanent creature2 = game.getPermanent(target2Id); + // 20110930 - 701.10 + if (creature1 != null && creature2 != null) { + if (creature1.isCreature() && creature2.isCreature()) { + return creature1.fight(creature2, source, game); } } - if (!game.isSimulation()) { - game.informPlayers(card.getName() + " has been fizzled."); - } + } + if (!game.isSimulation()) { + game.informPlayers(card.getName() + " has been fizzled."); } return false; } @Override - public FightTargetsEffect copy() { + public FightTargetsEffect + copy() { return new FightTargetsEffect(this); + } @Override - public String getText(Mode mode) { - if (staticText != null && !staticText.isEmpty()) { + public String + getText(Mode mode + ) { + if (staticText + != null && !staticText + .isEmpty()) { return staticText; + } - return "Target " + mode.getTargets().get(0).getTargetName() + " fights another target " + mode.getTargets().get(1).getTargetName(); + return "Target " + mode + .getTargets().get(0).getTargetName() + " fights another target " + mode + .getTargets().get(1).getTargetName(); } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/PreventDamageToTargetMultiAmountEffect.java b/Mage/src/main/java/mage/abilities/effects/common/PreventDamageToTargetMultiAmountEffect.java index b72b54d01cf..0e832aeac6e 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/PreventDamageToTargetMultiAmountEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/PreventDamageToTargetMultiAmountEffect.java @@ -6,6 +6,7 @@ import java.util.UUID; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.Mode; +import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.PreventionEffectImpl; import mage.constants.Duration; import mage.game.Game; @@ -27,6 +28,10 @@ public class PreventDamageToTargetMultiAmountEffect extends PreventionEffectImpl super(duration, amount, false); } + public PreventDamageToTargetMultiAmountEffect(Duration duration, int amount, boolean onlyCombat, boolean consumable, DynamicValue dynamicValue) { + super(duration, amount, onlyCombat, consumable, dynamicValue); + } + public PreventDamageToTargetMultiAmountEffect(final PreventDamageToTargetMultiAmountEffect effect) { super(effect); } @@ -100,12 +105,15 @@ public class PreventDamageToTargetMultiAmountEffect extends PreventionEffectImpl @Override public String getText(Mode mode) { StringBuilder sb = new StringBuilder(); - sb.append("prevent the next ").append(amountToPrevent).append(" damage that would be dealt "); - if (duration == Duration.EndOfTurn) { - sb.append("this turn "); + if (staticText.isEmpty()) { + sb.append("prevent the next ").append(amountToPrevent).append(" damage that would be dealt "); + if (duration == Duration.EndOfTurn) { + sb.append("this turn "); + } + sb.append("to any number of targets, divided as you choose"); + return sb.toString(); } - sb.append("to any number of targets, divided as you choose"); - return sb.toString(); + return staticText; } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/SacrificeSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/SacrificeSourceEffect.java index b4e9339de44..806acf2a7ed 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/SacrificeSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/SacrificeSourceEffect.java @@ -1,13 +1,12 @@ - package mage.abilities.effects.common; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.constants.Outcome; +import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.game.stack.Spell; /** * @@ -34,11 +33,9 @@ public class SacrificeSourceEffect extends OneShotEffect { MageObject sourceObject = source.getSourceObjectIfItStillExists(game); if (sourceObject == null) { // Check if the effect was installed by the spell the source was cast by (e.g. Necromancy), if not don't sacrifice the permanent - if (source.getSourceObject(game) instanceof Spell) { + if (game.getState().getZone(source.getSourceId()).equals(Zone.BATTLEFIELD) + && source.getSourceObjectZoneChangeCounter() + 1 == game.getState().getZoneChangeCounter(source.getSourceId())) { sourceObject = game.getPermanent(source.getSourceId()); - if (sourceObject != null && sourceObject.getZoneChangeCounter(game) > source.getSourceObjectZoneChangeCounter() + 1) { - return false; - } } } if (sourceObject instanceof Permanent) { diff --git a/Mage/src/main/java/mage/abilities/effects/common/SkipCombatStepEffect.java b/Mage/src/main/java/mage/abilities/effects/common/SkipCombatStepEffect.java new file mode 100644 index 00000000000..4d72fe19fd0 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/SkipCombatStepEffect.java @@ -0,0 +1,55 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package mage.abilities.effects.common; + +import mage.abilities.Ability; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.game.Game; +import mage.game.events.GameEvent; + +/** + * + * @author jeffwadsworth + */ + +public class SkipCombatStepEffect extends ReplacementEffectImpl { + + public SkipCombatStepEffect(Duration duration) { + super(duration, Outcome.Detriment); + staticText = "that player skips their next combat phase"; + } + + public SkipCombatStepEffect(final SkipCombatStepEffect effect) { + super(effect); + } + + @Override + public SkipCombatStepEffect copy() { + return new SkipCombatStepEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + return true; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.COMBAT_PHASE; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + return event.getPlayerId().equals(targetPointer.getFirst(game, source)); + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/SkipNextDrawStepTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/SkipNextDrawStepTargetEffect.java new file mode 100644 index 00000000000..2f1ba7d187e --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/SkipNextDrawStepTargetEffect.java @@ -0,0 +1,55 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package mage.abilities.effects.common; + +import mage.abilities.Ability; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.game.Game; +import mage.game.events.GameEvent; + +/** + * + * @author jeffwadsworth + */ + +public class SkipNextDrawStepTargetEffect extends ReplacementEffectImpl { + + public SkipNextDrawStepTargetEffect() { + super(Duration.OneUse, Outcome.Detriment); + staticText = "Target player skips his or her next draw step"; + } + + public SkipNextDrawStepTargetEffect(final SkipNextDrawStepTargetEffect effect) { + super(effect); + } + + @Override + public SkipNextDrawStepTargetEffect copy() { + return new SkipNextDrawStepTargetEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + return true; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DRAW_STEP; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + return event.getPlayerId().equals(source.getFirstTarget()); + } +} \ No newline at end of file diff --git a/Mage/src/main/java/mage/abilities/effects/common/combat/CantAttackBlockAttachedEffect.java b/Mage/src/main/java/mage/abilities/effects/common/combat/CantAttackBlockAttachedEffect.java index 082c2a96324..9a026d3a93b 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/combat/CantAttackBlockAttachedEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/combat/CantAttackBlockAttachedEffect.java @@ -5,6 +5,7 @@ import mage.constants.AttachmentType; import mage.constants.Duration; import mage.abilities.Ability; import mage.abilities.effects.RestrictionEffect; +import mage.constants.Outcome; import mage.game.Game; import mage.game.permanent.Permanent; @@ -14,7 +15,7 @@ import mage.game.permanent.Permanent; public class CantAttackBlockAttachedEffect extends RestrictionEffect { public CantAttackBlockAttachedEffect(AttachmentType attachmentType) { - super(Duration.WhileOnBattlefield); + super(Duration.WhileOnBattlefield, Outcome.Removal); this.staticText = attachmentType.verb() + " creature can't attack or block"; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesEnchantmentSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesEnchantmentSourceEffect.java new file mode 100644 index 00000000000..e16f3d033af --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesEnchantmentSourceEffect.java @@ -0,0 +1,79 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package mage.abilities.effects.common.continuous; + +import mage.MageObjectReference; +import mage.abilities.Ability; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.constants.CardType; +import mage.constants.DependencyType; +import mage.constants.Duration; +import mage.constants.Layer; +import mage.constants.Outcome; +import mage.constants.SubLayer; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * + * @author jeffwadsworth + */ +public class BecomesEnchantmentSourceEffect extends ContinuousEffectImpl implements SourceEffect { + + public BecomesEnchantmentSourceEffect() { + super(Duration.Custom, Outcome.AddAbility); + staticText = "{this} becomes an Enchantment"; + dependencyTypes.add(DependencyType.EnchantmentAddingRemoving); + + } + + public BecomesEnchantmentSourceEffect(final BecomesEnchantmentSourceEffect effect) { + super(effect); + } + + @Override + public BecomesEnchantmentSourceEffect copy() { + return new BecomesEnchantmentSourceEffect(this); + } + + @Override + public void init(Ability source, Game game) { + super.init(source, game); + affectedObjectList.add(new MageObjectReference(source.getSourceId(), game)); + } + + @Override + public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { + Permanent permanent = affectedObjectList.get(0).getPermanent(game); + if (permanent != null) { + switch (layer) { + case TypeChangingEffects_4: + if (sublayer == SubLayer.NA) { + permanent.getCardType().clear(); + permanent.getSubtype(game).clear(); + if (!permanent.getCardType().contains(CardType.ENCHANTMENT)) { + permanent.getCardType().add(CardType.ENCHANTMENT); + } + } + break; + } + return true; + } + this.discard(); + return false; + } + + @Override + public boolean apply(Game game, Ability source) { + return false; + } + + @Override + public boolean hasLayer(Layer layer) { + return Layer.TypeChangingEffects_4 == layer; + } + +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/cost/SpellCostReductionSourceForOpponentsEffect.java b/Mage/src/main/java/mage/abilities/effects/common/cost/SpellCostReductionSourceForOpponentsEffect.java new file mode 100644 index 00000000000..4391755fa38 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/cost/SpellCostReductionSourceForOpponentsEffect.java @@ -0,0 +1,52 @@ +package mage.abilities.effects.common.cost; + +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.SpellAbility; +import mage.constants.CostModificationType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.game.Game; + +public class SpellCostReductionSourceForOpponentsEffect extends CostModificationEffectImpl { + + public SpellCostReductionSourceForOpponentsEffect() { + this("undaunted (This spell costs {1} less to cast for each opponent.)"); + } + + public SpellCostReductionSourceForOpponentsEffect(String newStaticText) { + super(Duration.Custom, Outcome.Benefit, CostModificationType.REDUCE_COST); + staticText = newStaticText; + } + + public SpellCostReductionSourceForOpponentsEffect(final SpellCostReductionSourceForOpponentsEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source, Ability abilityToModify) { + SpellAbility spellAbility = (SpellAbility) abilityToModify; + Mana mana = spellAbility.getManaCostsToPay().getMana(); + if (mana.getGeneric() > 0) { + int count = game.getOpponents(source.getControllerId()).size(); + int newCount = mana.getGeneric() - count; + if (newCount < 0) { + newCount = 0; + } + mana.setGeneric(newCount); + spellAbility.getManaCostsToPay().load(mana.toString()); + return true; + } + return false; + } + + @Override + public boolean applies(Ability abilityToModify, Ability source, Game game) { + return abilityToModify instanceof SpellAbility && abilityToModify.getSourceId().equals(source.getSourceId()); + } + + @Override + public SpellCostReductionSourceForOpponentsEffect copy() { + return new SpellCostReductionSourceForOpponentsEffect(this); + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/counter/RemoveCounterSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/counter/RemoveCounterSourceEffect.java index 4cd077f158b..6345058e2f5 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/counter/RemoveCounterSourceEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/counter/RemoveCounterSourceEffect.java @@ -1,4 +1,3 @@ - package mage.abilities.effects.common.counter; import mage.abilities.Ability; diff --git a/Mage/src/main/java/mage/abilities/keyword/BandsWithOtherAbility.java b/Mage/src/main/java/mage/abilities/keyword/BandsWithOtherAbility.java new file mode 100644 index 00000000000..528cc744df2 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/keyword/BandsWithOtherAbility.java @@ -0,0 +1,79 @@ + +package mage.abilities.keyword; + +import mage.abilities.StaticAbility; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.constants.Zone; + +/** + * + * @author L_J + */ +public class BandsWithOtherAbility extends StaticAbility { + + private SubType subtype; + private SuperType supertype; + private String bandingName; + + public BandsWithOtherAbility() { + this(null, null, null); + } + + public BandsWithOtherAbility(SubType subtype) { + this(subtype, null, null); + } + + public BandsWithOtherAbility(SuperType supertype) { + this(null, supertype, null); + } + + public BandsWithOtherAbility(String bandingName) { + this(null, null, bandingName); + } + + public BandsWithOtherAbility(SubType subtype, SuperType supertype, String bandingName) { + super(Zone.ALL, null); + this.subtype = subtype; + this.supertype = supertype; + this.bandingName = bandingName; + } + + public BandsWithOtherAbility(BandsWithOtherAbility ability) { + super(ability); + this.subtype = ability.subtype; + this.supertype = ability.supertype; + this.bandingName = ability.bandingName; + } + + @Override + public BandsWithOtherAbility copy() { + return new BandsWithOtherAbility(this); + } + + public SubType getSubtype() { + return subtype; + } + + public SuperType getSupertype() { + return supertype; + } + + public String getName() { + return bandingName; + } + + @Override + public String getRule() { + StringBuilder sb = new StringBuilder("bands with other"); + if (subtype != null) { + return sb.append(' ').append(subtype.getDescription()).append('s').toString(); + } else if (supertype != null) { + return sb.append(' ').append(supertype.toString()).append(" creatures").toString(); + } else if (bandingName != null) { + return sb.append(" creatures named ").append(bandingName).toString(); + } + return "all \"" + sb.toString() + "\" abilities"; + } + +} diff --git a/Mage/src/main/java/mage/abilities/keyword/MentorAbility.java b/Mage/src/main/java/mage/abilities/keyword/MentorAbility.java index bd579657dac..85f700357ff 100644 --- a/Mage/src/main/java/mage/abilities/keyword/MentorAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/MentorAbility.java @@ -13,7 +13,6 @@ import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; /** - * * @author TheElk801 */ public class MentorAbility extends AttacksTriggeredAbility { @@ -22,7 +21,7 @@ public class MentorAbility extends AttacksTriggeredAbility { static { filter.add(new AttackingPredicate()); - filter.add(new MentorAbilityPredicate()); + filter.add(MentorAbilityPredicate.instance); } public MentorAbility() { @@ -46,7 +45,8 @@ public class MentorAbility extends AttacksTriggeredAbility { } -class MentorAbilityPredicate implements ObjectSourcePlayerPredicate> { +enum MentorAbilityPredicate implements ObjectSourcePlayerPredicate> { + instance; @Override public boolean apply(ObjectSourcePlayer input, Game game) { diff --git a/Mage/src/main/java/mage/abilities/keyword/NinjutsuAbility.java b/Mage/src/main/java/mage/abilities/keyword/NinjutsuAbility.java index 5737f0b50b0..ce728b1f75f 100644 --- a/Mage/src/main/java/mage/abilities/keyword/NinjutsuAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/NinjutsuAbility.java @@ -199,8 +199,8 @@ class RevealNinjutsuCardCost extends CostImpl { for (CommandObject coj : game.getState().getCommand()) { if (coj != null && coj.getId().equals(ability.getSourceId())) { card = game.getCard(ability.getSourceId()); + break; } - break; } } if (card != null) { diff --git a/Mage/src/main/java/mage/abilities/keyword/UndauntedAbility.java b/Mage/src/main/java/mage/abilities/keyword/UndauntedAbility.java index 857d47133bb..52061608d3a 100644 --- a/Mage/src/main/java/mage/abilities/keyword/UndauntedAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/UndauntedAbility.java @@ -5,25 +5,17 @@ */ package mage.abilities.keyword; -import mage.Mana; -import mage.abilities.Ability; -import mage.abilities.SpellAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.common.cost.CostModificationEffectImpl; -import mage.constants.CostModificationType; -import mage.constants.Duration; -import mage.constants.Outcome; +import mage.abilities.effects.common.cost.SpellCostReductionSourceForOpponentsEffect; import mage.constants.Zone; -import mage.game.Game; /** - * * @author LevelX2 */ public class UndauntedAbility extends SimpleStaticAbility { public UndauntedAbility() { - super(Zone.ALL, new UndauntedEffect()); + super(Zone.ALL, new SpellCostReductionSourceForOpponentsEffect("undaunted (This spell costs {1} less to cast for each opponent.)")); setRuleAtTheTop(true); } @@ -36,43 +28,4 @@ public class UndauntedAbility extends SimpleStaticAbility { return new UndauntedAbility(this); } -} - -class UndauntedEffect extends CostModificationEffectImpl { - - public UndauntedEffect() { - super(Duration.Custom, Outcome.Benefit, CostModificationType.REDUCE_COST); - staticText = "undaunted (This spell costs {1} less to cast for each opponent.)"; - } - - public UndauntedEffect(final UndauntedEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source, Ability abilityToModify) { - SpellAbility spellAbility = (SpellAbility) abilityToModify; - Mana mana = spellAbility.getManaCostsToPay().getMana(); - if (mana.getGeneric() > 0) { - int count = game.getOpponents(source.getControllerId()).size(); - int newCount = mana.getGeneric() - count; - if (newCount < 0) { - newCount = 0; - } - mana.setGeneric(newCount); - spellAbility.getManaCostsToPay().load(mana.toString()); - return true; - } - return false; - } - - @Override - public boolean applies(Ability abilityToModify, Ability source, Game game) { - return abilityToModify instanceof SpellAbility && abilityToModify.getSourceId().equals(source.getSourceId()); - } - - @Override - public UndauntedEffect copy() { - return new UndauntedEffect(this); - } -} +} \ No newline at end of file diff --git a/Mage/src/main/java/mage/abilities/meta/OrTriggeredAbility.java b/Mage/src/main/java/mage/abilities/meta/OrTriggeredAbility.java index ebd11af1fb6..1f0723298d2 100644 --- a/Mage/src/main/java/mage/abilities/meta/OrTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/meta/OrTriggeredAbility.java @@ -1,6 +1,5 @@ package mage.abilities.meta; -import mage.MageObject; import mage.abilities.TriggeredAbility; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.Effect; @@ -14,9 +13,12 @@ import java.util.List; import java.util.UUID; /** - * A triggered ability that combines several others and triggers whenever one or more of them would. The abilities - * passed in should have null as their effect, and should have their own targets set if necessary. All other information - * will be passed in from changes to this Ability. Note: this does NOT work with abilities that have intervening if clauses. + * A triggered ability that combines several others and triggers whenever one or + * more of them would. The abilities passed in should have null as their effect, + * and should have their own targets set if necessary. All other information + * will be passed in from changes to this Ability. Note: this does NOT work with + * abilities that have intervening if clauses. + * * @author noahg */ public class OrTriggeredAbility extends TriggeredAbilityImpl { @@ -43,18 +45,17 @@ public class OrTriggeredAbility extends TriggeredAbilityImpl { public OrTriggeredAbility(OrTriggeredAbility ability) { super(ability); this.triggeredAbilities = new TriggeredAbility[ability.triggeredAbilities.length]; - for (int i = 0; i < this.triggeredAbilities.length; i++){ + for (int i = 0; i < this.triggeredAbilities.length; i++) { this.triggeredAbilities[i] = ability.triggeredAbilities[i].copy(); } this.triggeringAbilities = new ArrayList<>(ability.triggeringAbilities); this.ruleTrigger = ability.ruleTrigger; } - @Override public boolean checkEventType(GameEvent event, Game game) { for (TriggeredAbility ability : triggeredAbilities) { - if (ability.checkEventType(event, game)){ + if (ability.checkEventType(event, game)) { System.out.println("Correct event type (" + event.getType() + ")"); return true; } @@ -101,7 +102,6 @@ public class OrTriggeredAbility extends TriggeredAbilityImpl { return sb.toString() + super.getRule(); } - @Override public void setControllerId(UUID controllerId) { super.setControllerId(controllerId); @@ -126,11 +126,4 @@ public class OrTriggeredAbility extends TriggeredAbilityImpl { } } - @Override - public void setSourceObject(MageObject sourceObject, Game game) { - super.setSourceObject(sourceObject, game); - for (TriggeredAbility ability : triggeredAbilities) { - ability.setSourceObject(sourceObject, game); - } - } } diff --git a/Mage/src/main/java/mage/cards/decks/importer/DeckImporterUtil.java b/Mage/src/main/java/mage/cards/decks/importer/DeckImporterUtil.java index a0e90dc5261..0384a17f44c 100644 --- a/Mage/src/main/java/mage/cards/decks/importer/DeckImporterUtil.java +++ b/Mage/src/main/java/mage/cards/decks/importer/DeckImporterUtil.java @@ -39,7 +39,9 @@ public final class DeckImporterUtil { } public static DeckImporter getDeckImporter(String file) { - if (file.toLowerCase(Locale.ENGLISH).endsWith("dec")) { + if (file == null) { + return null; + } if (file.toLowerCase(Locale.ENGLISH).endsWith("dec")) { return new DecDeckImporter(); } else if (file.toLowerCase(Locale.ENGLISH).endsWith("mwdeck")) { return new MWSDeckImporter(); diff --git a/Mage/src/main/java/mage/cards/repository/ExpansionRepository.java b/Mage/src/main/java/mage/cards/repository/ExpansionRepository.java index 4ed44d2966a..b36b5cc9e90 100644 --- a/Mage/src/main/java/mage/cards/repository/ExpansionRepository.java +++ b/Mage/src/main/java/mage/cards/repository/ExpansionRepository.java @@ -33,6 +33,8 @@ public enum ExpansionRepository { private Dao expansionDao; + public boolean instanceInitialized = false; + ExpansionRepository() { File file = new File("db"); if (!file.exists()) { @@ -48,9 +50,11 @@ public enum ExpansionRepository { TableUtils.createTableIfNotExists(connectionSource, ExpansionInfo.class); expansionDao = DaoManager.createDao(connectionSource, ExpansionInfo.class); + instanceInitialized = true; } catch (SQLException ex) { ex.printStackTrace(); } + } public void add(ExpansionInfo expansion) { diff --git a/Mage/src/main/java/mage/counters/CounterType.java b/Mage/src/main/java/mage/counters/CounterType.java index fd2eb779126..a5ce8b6a603 100644 --- a/Mage/src/main/java/mage/counters/CounterType.java +++ b/Mage/src/main/java/mage/counters/CounterType.java @@ -9,6 +9,7 @@ public enum CounterType { AGE("age"), AIM("aim"), + ARROW("arrow"), ARROWHEAD("arrowhead"), AWAKENING("awakening"), BLAZE("blaze"), diff --git a/Mage/src/main/java/mage/filter/StaticFilters.java b/Mage/src/main/java/mage/filter/StaticFilters.java index 0fcf903c4c3..4226afe8767 100644 --- a/Mage/src/main/java/mage/filter/StaticFilters.java +++ b/Mage/src/main/java/mage/filter/StaticFilters.java @@ -23,7 +23,7 @@ import mage.filter.predicate.permanent.TokenPredicate; /** * A class that holds Filter objects that may not be modified without copying * before. This prevents the creation of thousands of filter objects. - * + *

* Because the filters are used application wide they may not be modified. * NEVER!!!!! But it's possible, so be careful! * @@ -42,6 +42,7 @@ public final class StaticFilters { static { FILTER_ENCHANTMENT_PERMANENT.setLockedFilter(true); } + public static final FilterCard FILTER_CARD = new FilterCard("card"); static { @@ -119,6 +120,7 @@ public final class StaticFilters { static { FILTER_CARD_NON_LAND.setLockedFilter(true); } + public static final FilterNonlandCard FILTER_CARD_A_NON_LAND = new FilterNonlandCard("a nonland card"); static { @@ -154,11 +156,13 @@ public final class StaticFilters { static { FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT.setLockedFilter(true); } + public static final FilterCreaturePermanent FILTER_ARTIFACT_CREATURE_PERMANENT = new FilterArtifactCreaturePermanent(); static { FILTER_ARTIFACT_CREATURE_PERMANENT.setLockedFilter(true); } + public static final FilterPermanent FILTER_PERMANENT_ARTIFACT_OR_CREATURE = new FilterPermanent("artifact or creature"); static { @@ -168,6 +172,7 @@ public final class StaticFilters { )); FILTER_PERMANENT_ARTIFACT_OR_CREATURE.setLockedFilter(true); } + public static final FilterPermanent FILTER_PERMANENT_ARTIFACT_CREATURE_OR_ENCHANTMENT = new FilterPermanent("artifact, creature, or enchantment"); static { @@ -178,6 +183,7 @@ public final class StaticFilters { )); FILTER_PERMANENT_ARTIFACT_CREATURE_OR_ENCHANTMENT.setLockedFilter(true); } + public static final FilterPermanent FILTER_PERMANENT_ARTIFACT_CREATURE_ENCHANTMENT_OR_LAND = new FilterPermanent("artifact, creature, enchantment, or land"); static { @@ -195,16 +201,19 @@ public final class StaticFilters { static { FILTER_CONTROLLED_PERMANENT.setLockedFilter(true); } + public static final FilterControlledPermanent FILTER_CONTROLLED_PERMANENT_ARTIFACT = new FilterControlledArtifactPermanent(); static { FILTER_CONTROLLED_PERMANENT_ARTIFACT.setLockedFilter(true); } + public static final FilterControlledPermanent FILTER_CONTROLLED_PERMANENT_ARTIFACT_AN = new FilterControlledArtifactPermanent("an artifact"); static { FILTER_CONTROLLED_PERMANENT_ARTIFACT_AN.setLockedFilter(true); } + public static final FilterControlledPermanent FILTER_CONTROLLED_PERMANENT_ARTIFACT_OR_CREATURE = new FilterControlledPermanent("artifact or creature you control"); static { @@ -214,6 +223,7 @@ public final class StaticFilters { )); FILTER_CONTROLLED_PERMANENT_ARTIFACT_OR_CREATURE.setLockedFilter(true); } + public static final FilterControlledPermanent FILTER_CONTROLLED_PERMANENT_LAND = new FilterControlledLandPermanent(); static { @@ -232,12 +242,14 @@ public final class StaticFilters { FILTER_OPPONENTS_PERMANENT.add(new ControllerPredicate(TargetController.OPPONENT)); FILTER_OPPONENTS_PERMANENT.setLockedFilter(true); } + public static final FilterCreaturePermanent FILTER_OPPONENTS_PERMANENT_CREATURE = new FilterCreaturePermanent("creature an opponent controls"); static { FILTER_OPPONENTS_PERMANENT_CREATURE.add(new ControllerPredicate(TargetController.OPPONENT)); FILTER_OPPONENTS_PERMANENT_CREATURE.setLockedFilter(true); } + public static final FilterPermanent FILTER_OPPONENTS_PERMANENT_ARTIFACT = new FilterPermanent("artifact an opponent controls"); static { @@ -245,6 +257,7 @@ public final class StaticFilters { FILTER_OPPONENTS_PERMANENT_ARTIFACT.add(new CardTypePredicate(CardType.ARTIFACT)); FILTER_OPPONENTS_PERMANENT_ARTIFACT.setLockedFilter(true); } + public static final FilterPermanent FILTER_OPPONENTS_PERMANENT_ARTIFACT_OR_CREATURE = new FilterPermanent("artifact or creature an opponent controls"); static { @@ -280,12 +293,14 @@ public final class StaticFilters { static { FILTER_CONTROLLED_A_CREATURE.setLockedFilter(true); } + public static final FilterControlledCreaturePermanent FILTER_CONTROLLED_ANOTHER_CREATURE = new FilterControlledCreaturePermanent("another creature"); static { FILTER_CONTROLLED_ANOTHER_CREATURE.add(new AnotherPredicate()); FILTER_CONTROLLED_ANOTHER_CREATURE.setLockedFilter(true); } + public static final FilterControlledPermanent FILTER_CONTROLLED_PERMANENT_NON_LAND = new FilterControlledPermanent("nonland permanent"); static { @@ -294,6 +309,7 @@ public final class StaticFilters { ); FILTER_CONTROLLED_PERMANENT_NON_LAND.setLockedFilter(true); } + public static final FilterLandPermanent FILTER_LAND = new FilterLandPermanent(); static { @@ -331,6 +347,12 @@ public final class StaticFilters { FILTER_PERMANENT_CREATURE.setLockedFilter(true); } + public static final FilterCreaturePermanent FILTER_PERMANENT_CREATURE_A = new FilterCreaturePermanent("a creature"); + + static { + FILTER_PERMANENT_CREATURE_A.setLockedFilter(true); + } + public static final FilterPermanent FILTER_PERMANENT_CREATURE_OR_PLANESWALKER_A = new FilterPermanent("a creature or planeswalker"); static { @@ -344,33 +366,39 @@ public final class StaticFilters { static { FILTER_PERMANENT_A_CREATURE.setLockedFilter(true); } + public static final FilterCreaturePermanent FILTER_PERMANENT_CREATURE_CONTROLLED = new FilterCreaturePermanent("creature you control"); static { FILTER_PERMANENT_CREATURE_CONTROLLED.add(new ControllerPredicate(TargetController.YOU)); FILTER_PERMANENT_CREATURE_CONTROLLED.setLockedFilter(true); } + public static final FilterCreaturePermanent FILTER_PERMANENT_CREATURES = new FilterCreaturePermanent("creatures"); static { FILTER_PERMANENT_CREATURES.setLockedFilter(true); } + public static final FilterCreaturePermanent FILTER_PERMANENT_CREATURES_CONTROLLED = new FilterCreaturePermanent("creatures you control"); static { FILTER_PERMANENT_CREATURES_CONTROLLED.add(new ControllerPredicate(TargetController.YOU)); FILTER_PERMANENT_CREATURES_CONTROLLED.setLockedFilter(true); } + public static final FilterCreaturePermanent FILTER_PERMANENT_CREATURE_GOBLINS = new FilterCreaturePermanent(SubType.GOBLIN, "Goblin creatures"); static { FILTER_PERMANENT_CREATURE_GOBLINS.setLockedFilter(true); } + public static final FilterCreaturePermanent FILTER_PERMANENT_CREATURE_SLIVERS = new FilterCreaturePermanent(SubType.SLIVER, "all Sliver creatures"); static { FILTER_PERMANENT_CREATURE_SLIVERS.setLockedFilter(true); } + public static final FilterPlaneswalkerPermanent FILTER_PERMANENT_PLANESWALKER = new FilterPlaneswalkerPermanent(); static { @@ -388,12 +416,14 @@ public final class StaticFilters { static { FILTER_PERMANENTS_NON_LAND.setLockedFilter(true); } + public static final FilterStackObject FILTER_SPELL_OR_ABILITY_OPPONENTS = new FilterStackObject("spell or ability and opponent controls"); static { FILTER_SPELL_OR_ABILITY_OPPONENTS.add(new ControllerPredicate(TargetController.OPPONENT)); FILTER_SPELL_OR_ABILITY_OPPONENTS.setLockedFilter(true); } + public static final FilterStackObject FILTER_SPELL_OR_ABILITY = new FilterStackObject(); static { @@ -405,11 +435,13 @@ public final class StaticFilters { static { FILTER_SPELL_A_CREATURE.setLockedFilter(true); } + public static final FilterCreatureSpell FILTER_SPELL_CREATURE = new FilterCreatureSpell("creature spell"); static { FILTER_SPELL_CREATURE.setLockedFilter(true); } + public static final FilterSpell FILTER_SPELL_NON_CREATURE = (FilterSpell) new FilterSpell("noncreature spell").add(Predicates.not(new CardTypePredicate(CardType.CREATURE))); static { @@ -444,6 +476,7 @@ public final class StaticFilters { )); FILTER_SPELL_AN_INSTANT_OR_SORCERY.setLockedFilter(true); } + public static final FilterSpell FILTER_SPELL_INSTANT_OR_SORCERY = new FilterSpell("instant or sorcery spell"); static { @@ -463,6 +496,7 @@ public final class StaticFilters { )); FILTER_SPELLS_INSTANT_OR_SORCERY.setLockedFilter(true); } + public static final FilterCreaturePermanent FILTER_CREATURE_TOKENS = new FilterCreaturePermanent("creature tokens"); static { @@ -484,6 +518,7 @@ public final class StaticFilters { FILTER_PERMANENT_AURA.add(new SubtypePredicate(SubType.AURA)); FILTER_PERMANENT_AURA.setLockedFilter(true); } + public static final FilterPermanent FILTER_PERMANENT_EQUIPMENT = new FilterPermanent(); static { @@ -491,6 +526,7 @@ public final class StaticFilters { FILTER_PERMANENT_EQUIPMENT.add(new SubtypePredicate(SubType.EQUIPMENT)); FILTER_PERMANENT_EQUIPMENT.setLockedFilter(true); } + public static final FilterPermanent FILTER_PERMANENT_FORTIFICATION = new FilterPermanent(); static { @@ -498,6 +534,7 @@ public final class StaticFilters { FILTER_PERMANENT_FORTIFICATION.add(new SubtypePredicate(SubType.FORTIFICATION)); FILTER_PERMANENT_FORTIFICATION.setLockedFilter(true); } + public static final FilterPermanent FILTER_PERMANENT_LEGENDARY = new FilterPermanent(); static { diff --git a/Mage/src/main/java/mage/game/Controllable.java b/Mage/src/main/java/mage/game/Controllable.java index 025b8f3720d..ac7507e5082 100644 --- a/Mage/src/main/java/mage/game/Controllable.java +++ b/Mage/src/main/java/mage/game/Controllable.java @@ -12,6 +12,9 @@ public interface Controllable { UUID getId(); default boolean isControlledBy(UUID controllerID){ + if(getControllerId() == null){ + return false; + } return getControllerId().equals(controllerID); } } diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index e745c75e129..c0fa488e204 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -1026,6 +1026,7 @@ public abstract class GameImpl implements Game, Serializable { watchers.add(new BlockedAttackerWatcher()); watchers.add(new DamageDoneWatcher()); watchers.add(new PlanarRollWatcher()); + watchers.add(new PlayersAttackedThisTurnWatcher()); //20100716 - 103.5 for (UUID playerId : state.getPlayerList(startingPlayerId)) { @@ -1527,7 +1528,7 @@ public abstract class GameImpl implements Game, Serializable { @Override public void addEffect(ContinuousEffect continuousEffect, Ability source) { Ability newAbility = source.copy(); - newAbility.setSourceObject(null, this); // Update the source object to the currently existing Object + newAbility.setSourceObjectZoneChangeCounter(getState().getZoneChangeCounter(source.getSourceId())); ContinuousEffect newEffect = continuousEffect.copy(); newEffect.newId(); @@ -1698,11 +1699,17 @@ public abstract class GameImpl implements Game, Serializable { if (ability instanceof TriggeredManaAbility || ability instanceof DelayedTriggeredManaAbility) { // 20110715 - 605.4 Ability manaAbiltiy = ability.copy(); + if (manaAbiltiy.getSourceObjectZoneChangeCounter() == 0) { + manaAbiltiy.setSourceObjectZoneChangeCounter(getState().getZoneChangeCounter(ability.getSourceId())); + } manaAbiltiy.activate(this, false); manaAbiltiy.resolve(this); } else { TriggeredAbility newAbility = ability.copy(); newAbility.newId(); + if (newAbility.getSourceObjectZoneChangeCounter() == 0) { + newAbility.setSourceObjectZoneChangeCounter(getState().getZoneChangeCounter(ability.getSourceId())); + } state.addTriggeredAbility(newAbility); } } @@ -1711,10 +1718,10 @@ public abstract class GameImpl implements Game, Serializable { public UUID addDelayedTriggeredAbility(DelayedTriggeredAbility delayedAbility, Ability source) { delayedAbility.setSourceId(source.getSourceId()); delayedAbility.setControllerId(source.getControllerId()); - delayedAbility.setSourceObject(source.getSourceObject(this), this); // return addDelayedTriggeredAbility(delayedAbility); DelayedTriggeredAbility newAbility = delayedAbility.copy(); newAbility.newId(); + newAbility.setSourceObjectZoneChangeCounter(getState().getZoneChangeCounter(source.getSourceId())); newAbility.initOnAdding(this); // ability.init is called as the ability triggeres not now. // If a FixedTarget pointer is already set from the effect setting up this delayed ability @@ -2594,7 +2601,7 @@ public abstract class GameImpl implements Game, Serializable { boolean addPlaneAgain = false; for (Iterator it = this.getState().getCommand().iterator(); it.hasNext();) { CommandObject obj = it.next(); - if (obj.getControllerId().equals(playerId)) { + if (obj.isControlledBy(playerId)) { if (obj instanceof Emblem) { ((Emblem) obj).discardEffects();// This may not be the best fix but it works } diff --git a/Mage/src/main/java/mage/game/combat/Combat.java b/Mage/src/main/java/mage/game/combat/Combat.java index 5b56d49347c..08157890e1f 100644 --- a/Mage/src/main/java/mage/game/combat/Combat.java +++ b/Mage/src/main/java/mage/game/combat/Combat.java @@ -1,4 +1,3 @@ - package mage.game.combat; import mage.MageObject; @@ -6,6 +5,7 @@ import mage.abilities.Ability; import mage.abilities.effects.RequirementEffect; import mage.abilities.effects.RestrictionEffect; import mage.abilities.keyword.BandingAbility; +import mage.abilities.keyword.BandsWithOtherAbility; import mage.abilities.keyword.VigilanceAbility; import mage.abilities.keyword.special.JohanVigilanceAbility; import mage.constants.Outcome; @@ -14,8 +14,12 @@ import mage.filter.StaticFilters; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterCreatureForCombatBlock; import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicate; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.filter.predicate.mageobject.NamePredicate; +import mage.filter.predicate.mageobject.SubtypePredicate; +import mage.filter.predicate.mageobject.SupertypePredicate; import mage.filter.predicate.permanent.AttackingSameNotBandedPredicate; import mage.filter.predicate.permanent.PermanentIdPredicate; import mage.game.Game; @@ -103,8 +107,8 @@ public class Combat implements Serializable, Copyable { } /** - * Get all possible defender (players and plainwalkers) That does not mean - * neccessarly mean that they are really attacked + * Get all possible defender (players and planeswalkers) That does not mean + * necessarily mean that they are really attacked * * @return */ @@ -246,11 +250,14 @@ public class Combat implements Serializable, Copyable { game.getCombat().checkAttackRequirements(player, game); boolean firstTime = true; do { - if (!firstTime || !game.getPlayer(game.getActivePlayerId()).getAvailableAttackers(game).isEmpty()) { + if (!firstTime + || !game.getPlayer(game.getActivePlayerId()).getAvailableAttackers(game).isEmpty()) { player.selectAttackers(game, attackingPlayerId); } firstTime = false; - if (game.isPaused() || game.checkIfGameIsOver() || game.executingRollback()) { + if (game.isPaused() + || game.checkIfGameIsOver() + || game.executingRollback()) { return; } // because of possible undo during declare attackers it's neccassary to call here the methods with "game.getCombat()." to get the current combat object!!! @@ -293,53 +300,115 @@ public class Combat implements Serializable, Copyable { Permanent attacker = game.getPermanent(creatureId); if (attacker != null && player != null) { CombatGroup combatGroup = findGroup(attacker.getId()); - if (combatGroup != null && attacker.getAbilities().containsKey(BandingAbility.getInstance().getId()) && attacker.getBandedCards().isEmpty() && getAttackers().size() > 1) { - boolean isBanded = false; - FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("attacking creature to band with " + attacker.getLogName()); - filter.add(Predicates.not(new PermanentIdPredicate(creatureId))); - filter.add(new AttackingSameNotBandedPredicate(combatGroup.getDefenderId())); // creature that isn't already banded, and is attacking the same player or planeswalker - while (player.canRespond()) { - TargetControlledPermanent target = new TargetControlledPermanent(1, 1, filter, true); - target.setRequired(false); - if (!target.canChoose(attackingPlayerId, game) - || game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DECLARING_ATTACKERS, attackingPlayerId, attackingPlayerId)) - || !player.chooseUse(Outcome.Benefit, "Do you wish to " + (isBanded ? "band " + attacker.getLogName() + " with another " : "form a band with " + attacker.getLogName() + " and an ") + "attacking creature?", null, game)) { - break; - } - if (target.choose(Outcome.Benefit, attackingPlayerId, null, game)) { - isBanded = true; - for (UUID targetId : target.getTargets()) { - Permanent permanent = game.getPermanent(targetId); - if (permanent != null) { - - for (UUID bandedId : attacker.getBandedCards()) { - permanent.addBandedCard(bandedId); - Permanent banded = game.getPermanent(bandedId); - if (banded != null) { - banded.addBandedCard(targetId); - } - } - permanent.addBandedCard(creatureId); - attacker.addBandedCard(targetId); - if (!permanent.getAbilities().containsKey(BandingAbility.getInstance().getId())) { - filter.add(new AbilityPredicate(BandingAbility.class)); - } - } - - } + if (combatGroup != null && attacker.getBandedCards().isEmpty() && getAttackers().size() > 1) { + boolean canBand = attacker.getAbilities().containsKey(BandingAbility.getInstance().getId()); + List bandsWithOther = new ArrayList<>(); + for (Ability ability : attacker.getAbilities()) { + if (ability.getClass().equals(BandsWithOtherAbility.class)) { + bandsWithOther.add(ability); } } - if (isBanded) { - StringBuilder sb = new StringBuilder(player.getLogName()).append(" formed a band with ").append((attacker.getBandedCards().size() + 1) + " creatures: "); - sb.append(attacker.getLogName()); - for (UUID id : attacker.getBandedCards()) { - sb.append(", "); - Permanent permanent = game.getPermanent(id); - if (permanent != null) { - sb.append(permanent.getLogName()); + boolean canBandWithOther = !bandsWithOther.isEmpty(); + if (canBand || canBandWithOther) { + boolean isBanded = false; + FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("attacking creature to band with " + attacker.getLogName()); + filter.add(Predicates.not(new PermanentIdPredicate(creatureId))); + filter.add(new AttackingSameNotBandedPredicate(combatGroup.getDefenderId())); // creature that isn't already banded, and is attacking the same player or planeswalker + List> predicates = new ArrayList<>(); + if (!canBand && canBandWithOther) { + for (Ability ab : bandsWithOther) { + BandsWithOtherAbility ability = (BandsWithOtherAbility) ab; + if (ability.getSubtype() != null) { + predicates.add(new SubtypePredicate(ability.getSubtype())); + } + if (ability.getSupertype() != null) { + predicates.add(new SupertypePredicate(ability.getSupertype())); + } + if (ability.getName() != null) { + predicates.add(new NamePredicate(ability.getName())); + } + } + filter.add(Predicates.or(predicates)); + } + while (player.canRespond()) { + TargetControlledPermanent target = new TargetControlledPermanent(1, 1, filter, true); + target.setRequired(false); + canBand &= target.canChoose(attackingPlayerId, game); + canBandWithOther &= target.canChoose(attackingPlayerId, game); + if (game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.DECLARING_ATTACKERS, attackingPlayerId, attackingPlayerId)) + || (!canBand && !canBandWithOther) + || !player.chooseUse(Outcome.Benefit, "Do you wish to " + (isBanded ? "band " + attacker.getLogName() + " with another " : "form a band with " + attacker.getLogName() + " and an ") + "attacking creature?", null, game)) { + break; + } + + if (canBand && canBandWithOther) { + if (player.chooseUse(Outcome.Detriment, "Choose type of banding ability to apply:", attacker.getLogName(), "Banding", "Bands with other", null, game)) { + canBandWithOther = false; + } else { + canBand = false; + for (Ability ab : bandsWithOther) { + BandsWithOtherAbility ability = (BandsWithOtherAbility) ab; + if (ability.getSubtype() != null) { + predicates.add(new SubtypePredicate(ability.getSubtype())); + } + if (ability.getSupertype() != null) { + predicates.add(new SupertypePredicate(ability.getSupertype())); + } + if (ability.getName() != null) { + predicates.add(new NamePredicate(ability.getName())); + } + } + filter.add(Predicates.or(predicates)); + } + } + + if (target.choose(Outcome.Benefit, attackingPlayerId, null, game)) { + isBanded = true; + for (UUID targetId : target.getTargets()) { + Permanent permanent = game.getPermanent(targetId); + if (permanent != null) { + + for (UUID bandedId : attacker.getBandedCards()) { + permanent.addBandedCard(bandedId); + Permanent banded = game.getPermanent(bandedId); + if (banded != null) { + banded.addBandedCard(targetId); + } + } + permanent.addBandedCard(creatureId); + attacker.addBandedCard(targetId); + if (canBand) { + if (!permanent.getAbilities().containsKey(BandingAbility.getInstance().getId())) { + filter.add(new AbilityPredicate(BandingAbility.class)); + canBandWithOther = false; + } + } else if (canBandWithOther) { + List> newPredicates = new ArrayList<>(); + for (Predicate predicate : predicates) { + if (predicate.apply(permanent, game)) { + newPredicates.add(predicate); + } + } + filter.add(Predicates.or(newPredicates)); + canBand = false; + } + } + + } } } - game.informPlayers(sb.toString()); + if (isBanded) { + StringBuilder sb = new StringBuilder(player.getLogName()).append(" formed a band with ").append((attacker.getBandedCards().size() + 1) + " creatures: "); + sb.append(attacker.getLogName()); + for (UUID id : attacker.getBandedCards()) { + sb.append(", "); + Permanent permanent = game.getPermanent(id); + if (permanent != null) { + sb.append(permanent.getLogName()); + } + } + game.informPlayers(sb.toString()); + } } } } @@ -387,11 +456,16 @@ public class Combat implements Serializable, Copyable { if (defenders.size() == 1) { player.declareAttacker(creature.getId(), defenders.iterator().next(), game, false); } else { - TargetDefender target = new TargetDefender(defenders, creature.getId()); - target.setRequired(true); - target.setTargetName("planeswalker or player for " + creature.getLogName() + " to attack"); - if (player.chooseTarget(Outcome.Damage, target, null, game)) { - player.declareAttacker(creature.getId(), target.getFirstTarget(), game, false); + if (!player.isHuman()) { // computer only for multiple defenders + player.declareAttacker(creature.getId(), defenders.iterator().next(), game, false); + } else { // human players only for multiple defenders + TargetDefender target = new TargetDefender(defenders, creature.getId()); + target.setRequired(true); + target.setTargetName("planeswalker or player for " + creature.getLogName() + " to attack"); + if (player.chooseTarget(Outcome.Damage, target, null, game)) { + System.out.println("The player " + player.getName() + " declares an attacker here. " + creature.getName()); + player.declareAttacker(creature.getId(), target.getFirstTarget(), game, false); + } } } } else { @@ -483,7 +557,7 @@ public class Combat implements Serializable, Copyable { * Handle the blocker selection process * * @param blockController player that controlls how to block, if null the - * defender is the controller + * defender is the controller * @param game */ public void selectBlockers(Player blockController, Game game) { @@ -1275,10 +1349,10 @@ public class Combat implements Serializable, Copyable { if (defenderAttackedBy.size() >= defendingPlayer.getMaxAttackedBy()) { Player attackingPlayer = game.getPlayer(game.getControllerId(attackerId)); if (attackingPlayer != null && !game.isSimulation()) { - game.informPlayer(attackingPlayer, "No more than " + - CardUtil.numberToText(defendingPlayer.getMaxAttackedBy()) + - " creatures can attack " + - defendingPlayer.getLogName()); + game.informPlayer(attackingPlayer, "No more than " + + CardUtil.numberToText(defendingPlayer.getMaxAttackedBy()) + + " creatures can attack " + + defendingPlayer.getLogName()); } return false; } @@ -1308,7 +1382,7 @@ public class Combat implements Serializable, Copyable { * @param playerId * @param game * @param solveBanding check whether also add creatures banded with - * attackerId + * attackerId */ public void addBlockingGroup(UUID blockerId, UUID attackerId, UUID playerId, Game game, boolean solveBanding) { Permanent blocker = game.getPermanent(blockerId); diff --git a/Mage/src/main/java/mage/game/combat/CombatGroup.java b/Mage/src/main/java/mage/game/combat/CombatGroup.java index e357b6df977..be2f139af66 100644 --- a/Mage/src/main/java/mage/game/combat/CombatGroup.java +++ b/Mage/src/main/java/mage/game/combat/CombatGroup.java @@ -5,10 +5,12 @@ import java.io.Serializable; import java.util.*; import java.util.stream.Stream; +import mage.abilities.Ability; import mage.abilities.common.ControllerAssignCombatDamageToBlockersAbility; import mage.abilities.common.ControllerDivideCombatDamageAbility; import mage.abilities.common.DamageAsThoughNotBlockedAbility; import mage.abilities.keyword.BandingAbility; +import mage.abilities.keyword.BandsWithOtherAbility; import mage.abilities.keyword.CantBlockAloneAbility; import mage.abilities.keyword.DeathtouchAbility; import mage.abilities.keyword.DoubleStrikeAbility; @@ -110,6 +112,56 @@ public class CombatGroup implements Serializable, Copyable { return perm.getAbilities().containsKey(BandingAbility.getInstance().getId()); } + private boolean appliesBandsWithOther(List creatureIds, Game game) { + for (UUID creatureId : creatureIds) { + Permanent perm = game.getPermanent(creatureId); + if (perm != null && perm.getBandedCards() != null) { + for (Ability ab : perm.getAbilities()) { + if (ab.getClass().equals(BandsWithOtherAbility.class)) { + BandsWithOtherAbility ability = (BandsWithOtherAbility) ab; + if (ability.getSubtype() != null) { + if (perm.hasSubtype(ability.getSubtype(), game)) { + for (UUID bandedId : creatureIds) { + if (!bandedId.equals(creatureId)) { + Permanent banded = game.getPermanent(bandedId); + if (banded != null && banded.hasSubtype(ability.getSubtype(), game)) { + return true; + } + } + } + } + } + if (ability.getSupertype() != null) { + if (perm.getSuperType().contains(ability.getSupertype())) { + for (UUID bandedId : creatureIds) { + if (!bandedId.equals(creatureId)) { + Permanent banded = game.getPermanent(bandedId); + if (banded != null && banded.getSuperType().contains(ability.getSupertype())) { + return true; + } + } + } + } + } + if (ability.getName() != null) { + if (perm.getName().equals(ability.getName())) { + for (UUID bandedId : creatureIds) { + if (!bandedId.equals(creatureId)) { + Permanent banded = game.getPermanent(bandedId); + if (banded != null && banded.getName().equals(ability.getName())) { + return true; + } + } + } + } + } + } + } + } + } + return false; + } + public void assignDamageToBlockers(boolean first, Game game) { if (!attackers.isEmpty() && (!first || hasFirstOrDoubleStrike(game))) { Permanent attacker = game.getPermanent(attackers.get(0)); @@ -837,6 +889,9 @@ public class CombatGroup implements Serializable, Copyable { } } } + if (appliesBandsWithOther(attackers, game)) { // 702.21k - both a [quality] creature with “bands with other [quality]” and another [quality] creature (...) + return true; + } return false; } @@ -855,6 +910,9 @@ public class CombatGroup implements Serializable, Copyable { } } } + if (appliesBandsWithOther(blockers, game)) { // 702.21j - both a [quality] creature with “bands with other [quality]” and another [quality] creature (...) + return true; + } for (Permanent defensiveFormation : game.getBattlefield().getAllActivePermanents(defendingPlayerId)) { if (defensiveFormation.getAbilities().containsKey(ControllerAssignCombatDamageToBlockersAbility.getInstance().getId())) { return true; diff --git a/Mage/src/main/java/mage/game/command/CommandObject.java b/Mage/src/main/java/mage/game/command/CommandObject.java index b537d823ea6..2a376c6b3f0 100644 --- a/Mage/src/main/java/mage/game/command/CommandObject.java +++ b/Mage/src/main/java/mage/game/command/CommandObject.java @@ -3,17 +3,16 @@ package mage.game.command; import java.util.UUID; import mage.MageObject; +import mage.game.Controllable; /** * * @author Viserion, nantuko */ -public interface CommandObject extends MageObject { +public interface CommandObject extends MageObject, Controllable { UUID getSourceId(); - UUID getControllerId(); - void assignNewId(); MageObject getSourceObject(); diff --git a/Mage/src/main/java/mage/game/command/Emblem.java b/Mage/src/main/java/mage/game/command/Emblem.java index 898a5aeb562..d95cfb659d6 100644 --- a/Mage/src/main/java/mage/game/command/Emblem.java +++ b/Mage/src/main/java/mage/game/command/Emblem.java @@ -1,4 +1,3 @@ - package mage.game.command; import java.util.EnumSet; diff --git a/Mage/src/main/java/mage/game/command/Plane.java b/Mage/src/main/java/mage/game/command/Plane.java index b6a3768c298..ae34edade03 100644 --- a/Mage/src/main/java/mage/game/command/Plane.java +++ b/Mage/src/main/java/mage/game/command/Plane.java @@ -1,7 +1,5 @@ - package mage.game.command; -import static java.lang.Math.log; import java.lang.reflect.Constructor; import java.util.EnumSet; import java.util.List; @@ -289,7 +287,7 @@ public class Plane implements CommandObject { if (plane instanceof Plane) { return (Plane) plane; } - } catch (Exception ex) { + } catch (Exception ex) { } return null; } diff --git a/Mage/src/main/java/mage/game/command/emblems/VraskaGolgariQueenEmblem.java b/Mage/src/main/java/mage/game/command/emblems/VraskaGolgariQueenEmblem.java index f7c2fac333c..018943ecaba 100644 --- a/Mage/src/main/java/mage/game/command/emblems/VraskaGolgariQueenEmblem.java +++ b/Mage/src/main/java/mage/game/command/emblems/VraskaGolgariQueenEmblem.java @@ -3,11 +3,11 @@ package mage.game.command.emblems; import mage.abilities.common.DealsDamageToAPlayerAllTriggeredAbility; import mage.abilities.effects.common.LoseGameTargetPlayerEffect; import mage.constants.SetTargetPointer; +import mage.constants.Zone; import mage.filter.StaticFilters; import mage.game.command.Emblem; /** - * * @author TheElk801 */ public final class VraskaGolgariQueenEmblem extends Emblem { @@ -17,9 +17,9 @@ public final class VraskaGolgariQueenEmblem extends Emblem { this.setName("Emblem Vraska"); this.setExpansionSetCodeForImage("GRN"); this.getAbilities().add(new DealsDamageToAPlayerAllTriggeredAbility( - new LoseGameTargetPlayerEffect(), + Zone.COMMAND, new LoseGameTargetPlayerEffect(), StaticFilters.FILTER_CONTROLLED_A_CREATURE, - false, SetTargetPointer.PLAYER, true + false, SetTargetPointer.NONE, true, true )); } } diff --git a/Mage/src/main/java/mage/game/draft/DraftImpl.java b/Mage/src/main/java/mage/game/draft/DraftImpl.java index 35efc144316..5ef5a2330ea 100644 --- a/Mage/src/main/java/mage/game/draft/DraftImpl.java +++ b/Mage/src/main/java/mage/game/draft/DraftImpl.java @@ -147,7 +147,8 @@ public abstract class DraftImpl implements Draft { @Override public void autoPick(UUID playerId) { - this.addPick(playerId, players.get(playerId).getBooster().get(0).getId(), null); + List booster = players.get(playerId).getBooster(); + this.addPick(playerId, booster.get(booster.size()-1).getId(), null); } protected void passLeft() { diff --git a/Mage/src/main/java/mage/game/match/MatchOptions.java b/Mage/src/main/java/mage/game/match/MatchOptions.java index 02e6808416c..47ad873e631 100644 --- a/Mage/src/main/java/mage/game/match/MatchOptions.java +++ b/Mage/src/main/java/mage/game/match/MatchOptions.java @@ -37,6 +37,7 @@ public class MatchOptions implements Serializable { protected boolean spectatorsAllowed; protected boolean planeChase; protected int quitRatio; + protected int minimumRating; protected int edhPowerLevel; protected boolean rated; protected int numSeatsForMatch; @@ -205,6 +206,10 @@ public class MatchOptions implements Serializable { this.quitRatio = quitRatio; } + public int getMinimumRating() { return minimumRating; } + + public void setMinimumRating(int minimumRating) { this.minimumRating = minimumRating; } + public int getEdhPowerLevel() { return edhPowerLevel; } diff --git a/Mage/src/main/java/mage/game/permanent/token/GoblinToken.java b/Mage/src/main/java/mage/game/permanent/token/GoblinToken.java index e59b7f70df4..79a3a2236db 100644 --- a/Mage/src/main/java/mage/game/permanent/token/GoblinToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/GoblinToken.java @@ -20,7 +20,7 @@ public final class GoblinToken extends TokenImpl { static { tokenImageSets.addAll(Arrays.asList("10E", "ALA", "SOM", "M10", "NPH", "M13", "RTR", "MMA", "M15", "C14", "KTK", "EVG", "DTK", "ORI", "DDG", "DDN", "DD3EVG", "MM2", - "MM3", "EMA", "C16", "DOM")); + "MM3", "EMA", "C16", "DOM", "ANA")); } public GoblinToken(boolean withHaste) { diff --git a/Mage/src/main/java/mage/game/permanent/token/MaskToken.java b/Mage/src/main/java/mage/game/permanent/token/MaskToken.java index 662ee9e0603..fd1619f9955 100644 --- a/Mage/src/main/java/mage/game/permanent/token/MaskToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/MaskToken.java @@ -10,7 +10,6 @@ import mage.constants.SubType; import mage.target.TargetPermanent; /** - * * @author TheElk801 */ public final class MaskToken extends TokenImpl { @@ -18,8 +17,8 @@ public final class MaskToken extends TokenImpl { public MaskToken() { super( "Mask", "white Aura enchantment token named Mask " - + "attached to another target permanent. " - + "The token has enchant permanent and totem armor." + + "attached to another target permanent. " + + "The token has enchant permanent and totem armor." ); cardType.add(CardType.ENCHANTMENT); color.setWhite(true); @@ -31,6 +30,7 @@ public final class MaskToken extends TokenImpl { ability.addEffect(new AttachEffect(Outcome.BoostCreature)); this.addAbility(ability); + // Totem armor this.addAbility(new TotemArmorAbility()); } diff --git a/Mage/src/main/java/mage/game/permanent/token/SpiritWhiteToken.java b/Mage/src/main/java/mage/game/permanent/token/SpiritWhiteToken.java index 5b856ddedad..64668eb42a2 100644 --- a/Mage/src/main/java/mage/game/permanent/token/SpiritWhiteToken.java +++ b/Mage/src/main/java/mage/game/permanent/token/SpiritWhiteToken.java @@ -17,7 +17,7 @@ public final class SpiritWhiteToken extends TokenImpl { final static private List tokenImageSets = new ArrayList<>(); static { - tokenImageSets.addAll(Arrays.asList("AVR", "C14", "CNS", "DDC", "DDK", "FRF", "ISD", "KTK", "M15", "MM2", "SHM", "SOI", "EMA", "C16", "MM3", "CMA", "E01")); + tokenImageSets.addAll(Arrays.asList("AVR", "C14", "CNS", "DDC", "DDK", "FRF", "ISD", "KTK", "M15", "MM2", "SHM", "SOI", "EMA", "C16", "MM3", "CMA", "E01", "ANA")); } public SpiritWhiteToken() { diff --git a/Mage/src/main/java/mage/game/permanent/token/WolvesOfTheHuntToken.java b/Mage/src/main/java/mage/game/permanent/token/WolvesOfTheHuntToken.java new file mode 100644 index 00000000000..af156cd597b --- /dev/null +++ b/Mage/src/main/java/mage/game/permanent/token/WolvesOfTheHuntToken.java @@ -0,0 +1,32 @@ + +package mage.game.permanent.token; + +import mage.constants.CardType; +import mage.constants.SubType; +import mage.MageInt; +import mage.abilities.keyword.BandsWithOtherAbility; + +/** + * + * @author L_J + */ +public final class WolvesOfTheHuntToken extends TokenImpl { + + public WolvesOfTheHuntToken() { + super("Wolves of the Hunt", "1/1 green Wolf creature token named Wolves of the Hunt"); + cardType.add(CardType.CREATURE); + subtype.add(SubType.WOLF); + color.setGreen(true); + power = new MageInt(1); + toughness = new MageInt(1); + this.addAbility(new BandsWithOtherAbility("Wolves of the Hunt")); + } + + public WolvesOfTheHuntToken(final WolvesOfTheHuntToken token) { + super(token); + } + + public WolvesOfTheHuntToken copy() { + return new WolvesOfTheHuntToken(this); + } +} diff --git a/Mage/src/main/java/mage/game/stack/StackAbility.java b/Mage/src/main/java/mage/game/stack/StackAbility.java index 4c7259ed7d8..02546c99c23 100644 --- a/Mage/src/main/java/mage/game/stack/StackAbility.java +++ b/Mage/src/main/java/mage/game/stack/StackAbility.java @@ -518,14 +518,19 @@ public class StackAbility extends StackObjImpl implements Ability { return this.ability.getSourcePermanentIfItStillExists(game); } + @Override + public void setSourceObjectZoneChangeCounter(int zoneChangeCounter) { + ability.setSourceObjectZoneChangeCounter(zoneChangeCounter); + } + @Override public int getSourceObjectZoneChangeCounter() { return ability.getSourceObjectZoneChangeCounter(); } @Override - public void setSourceObject(MageObject sourceObject, Game game) { - throw new UnsupportedOperationException("Not supported."); + public Permanent getSourcePermanentOrLKI(Game game) { + return ability.getSourcePermanentOrLKI(game); } @Override diff --git a/Mage/src/main/java/mage/game/tournament/TournamentOptions.java b/Mage/src/main/java/mage/game/tournament/TournamentOptions.java index 2b042d19a1d..c81294ce3ee 100644 --- a/Mage/src/main/java/mage/game/tournament/TournamentOptions.java +++ b/Mage/src/main/java/mage/game/tournament/TournamentOptions.java @@ -24,6 +24,7 @@ public class TournamentOptions implements Serializable { protected int numberRounds; protected String password; protected int quitRatio; + protected int minimumRating; public TournamentOptions(String name, String matchType, int numSeats) { this.name = name; @@ -98,4 +99,8 @@ public class TournamentOptions implements Serializable { public void setQuitRatio(int quitRatio) { this.quitRatio = quitRatio; } + + public int getMinimumRating() { return minimumRating; } + + public void setMinimumRating(int minimumRating) { this.minimumRating = minimumRating; } } diff --git a/Mage/src/main/java/mage/players/Player.java b/Mage/src/main/java/mage/players/Player.java index ec86ad550c1..dab98647ec4 100644 --- a/Mage/src/main/java/mage/players/Player.java +++ b/Mage/src/main/java/mage/players/Player.java @@ -1,5 +1,7 @@ package mage.players; +import java.io.Serializable; +import java.util.*; import mage.MageItem; import mage.MageObject; import mage.MageObjectReference; @@ -37,9 +39,6 @@ import mage.target.TargetCard; import mage.target.common.TargetCardInLibrary; import mage.util.Copyable; -import java.io.Serializable; -import java.util.*; - /** * @author BetaSteward_at_googlemail.com */ @@ -74,7 +73,7 @@ public interface Player extends MageItem, Copyable { void setLife(int life, Game game, UUID sourceId); /** - * @param amount amount of life loss + * @param amount amount of life loss * @param game * @param atCombat was the source combat damage * @return @@ -345,7 +344,7 @@ public interface Player extends MageItem, Copyable { * @param target * @param game * @param targetPlayerId player whose library will be searched - * @param triggerEvents whether searching will trigger any game events + * @param triggerEvents whether searching will trigger any game events * @return true if search was successful */ boolean searchLibrary(TargetCardInLibrary target, Game game, UUID targetPlayerId, boolean triggerEvents); @@ -364,22 +363,23 @@ public interface Player extends MageItem, Copyable { /** * Plays a card if possible * - * @param card the card that can be cast + * @param card the card that can be cast * @param game - * @param noMana if it's a spell i can be cast without paying mana + * @param noMana if it's a spell i can be cast without paying mana * @param ignoreTiming if it's cast during the resolution of another spell - * no sorcery or play land timing restriction are checked. For a land it has - * to be the turn of the player playing that card. + * no sorcery or play land timing restriction are checked. For a land it has + * to be the turn of the player playing that card. + * @param reference mage object that allows to play the card * @return */ boolean playCard(Card card, Game game, boolean noMana, boolean ignoreTiming, MageObjectReference reference); /** - * @param card the land card to play + * @param card the land card to play * @param game * @param ignoreTiming false - it won't be checked if the stack is empty and - * you are able to play a Sorcery. It's still checked, if you are able to - * play a land concerning the numner of lands you already played. + * you are able to play a Sorcery. It's still checked, if you are able to + * play a land concerning the number of lands you already played. * @return */ boolean playLand(Card card, Game game, boolean ignoreTiming); @@ -525,11 +525,11 @@ public interface Player extends MageItem, Copyable { /** * Moves the cards from cards to the bottom of the players library. * - * @param cards - list of cards that have to be moved - * @param game - game + * @param cards - list of cards that have to be moved + * @param game - game * @param anyOrder - true if player can determine the order of the cards - * else random order - * @param source - source ability + * else random order + * @param source - source ability * @return */ boolean putCardsOnBottomOfLibrary(Cards cards, Game game, Ability source, boolean anyOrder); @@ -550,10 +550,10 @@ public interface Player extends MageItem, Copyable { /** * Moves the cards from cards to the top of players library. * - * @param cards - list of cards that have to be moved - * @param game - game + * @param cards - list of cards that have to be moved + * @param game - game * @param anyOrder - true if player can determine the order of the cards - * @param source - source ability + * @param source - source ability * @return */ boolean putCardsOnTopOfLibrary(Cards cards, Game game, Ability source, boolean anyOrder); @@ -579,8 +579,8 @@ public interface Player extends MageItem, Copyable { /** * Choose the order in which blockers get damage assigned to * - * @param blockers list of blockers where to choose the next one from - * @param combatGroup the concerning combat group + * @param blockers list of blockers where to choose the next one from + * @param combatGroup the concerning combat group * @param blockerOrder the already set order of blockers * @param game * @return blocker next to add to the blocker order @@ -719,11 +719,11 @@ public interface Player extends MageItem, Copyable { * @param toZone * @param source * @param game - * @param tapped the cards are tapped on the battlefield - * @param faceDown the cards are face down in the to zone - * @param byOwner the card is moved (or put onto battlefield) by the owner - * of the card and if target zone is battlefield controls the permanent - * (instead of the controller of the source) + * @param tapped the cards are tapped on the battlefield + * @param faceDown the cards are face down in the to zone + * @param byOwner the card is moved (or put onto battlefield) by the owner + * of the card and if target zone is battlefield controls the permanent + * (instead of the controller of the source) * @param appliedEffects * @return */ @@ -759,7 +759,7 @@ public interface Player extends MageItem, Copyable { * list of applied effects is not saved * * @param card - * @param exileId exile zone id (optional) + * @param exileId exile zone id (optional) * @param exileName name of exile zone (optional) * @param sourceId * @param game @@ -801,7 +801,7 @@ public interface Player extends MageItem, Copyable { * @param sourceId * @param game * @param fromZone if null, this info isn't postet - * @param toTop to the top of the library else to the bottom + * @param toTop to the top of the library else to the bottom * @param withName show the card name in the log * @return */ @@ -826,10 +826,10 @@ public interface Player extends MageItem, Copyable { * without mana (null) or the mana set to manaCosts instead of its normal * mana costs. * - * @param sourceId the source that can be cast without mana + * @param sourceId the source that can be cast without mana * @param manaCosts alternate ManaCost, null if it can be cast without mana - * cost - * @param costs alternate other costs you need to pay + * cost + * @param costs alternate other costs you need to pay */ void setCastSourceIdWithAlternateMana(UUID sourceId, ManaCosts manaCosts, Costs costs); diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index 53053fb0466..9e93659dbf1 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -1041,15 +1041,15 @@ public abstract class PlayerImpl implements Player, Serializable { } @Override - public boolean cast(SpellAbility ability, Game game, boolean noMana, MageObjectReference permittingObject) { - if (game == null || ability == null) { + public boolean cast(SpellAbility originalAbility, Game game, boolean noMana, MageObjectReference permittingObject) { + if (game == null || originalAbility == null) { return false; } // Use ability copy to avoid problems with targets and costs on recast (issue https://github.com/magefree/mage/issues/5189). - ability = ability.copy(); - + SpellAbility ability = originalAbility.copy(); ability.setControllerId(getId()); + ability.setSourceObjectZoneChangeCounter(game.getState().getZoneChangeCounter(ability.getSourceId())); if (ability.getSpellAbilityType() != SpellAbilityType.BASE) { ability = chooseSpellAbilityForCast(ability, game, noMana); if (ability == null) { @@ -1073,6 +1073,8 @@ public abstract class PlayerImpl implements Player, Serializable { logger.error("Got no spell from stack. ability: " + ability.getRule()); return false; } + // Update the zcc to the stack + ability.setSourceObjectZoneChangeCounter(game.getState().getZoneChangeCounter(ability.getSourceId())); // some effects set sourceId to cast without paying mana costs or other costs if (ability.getSourceId().equals(getCastSourceIdWithAlternateMana())) { Ability spellAbility = spell.getSpellAbility(); @@ -1143,8 +1145,14 @@ public abstract class PlayerImpl implements Player, Serializable { } //20091005 - 114.2a ActivationStatus activationStatus = playLandAbility.canActivate(this.playerId, game); - if (!ignoreTiming && !activationStatus.canActivate()) { - return false; + if (ignoreTiming) { + if (!canPlayLand()) { + return false; // ignore timing does not mean that more lands than normal can be played + } + } else { + if (!activationStatus.canActivate()) { + return false; + } } //20091005 - 305.1 @@ -2364,7 +2372,9 @@ public abstract class PlayerImpl implements Player, Serializable { setStoredBookmark(game.bookmarkState()); // makes it possible to UNDO a declared attacker with costs from e.g. Propaganda } Permanent attacker = game.getPermanent(attackerId); - if (attacker != null && attacker.canAttack(defenderId, game) && attacker.isControlledBy(playerId)) { + if (attacker != null + && attacker.canAttack(defenderId, game) + && attacker.isControlledBy(playerId)) { if (!game.getCombat().declareAttacker(attackerId, defenderId, playerId, game)) { game.undo(playerId); } @@ -2463,13 +2473,14 @@ public abstract class PlayerImpl implements Player, Serializable { for (UUID targetId : newTarget.getTargets()) { target.add(targetId, game); } - if (triggerEvents) { - game.fireEvent(GameEvent.getEvent(GameEvent.EventType.LIBRARY_SEARCHED, targetPlayerId, playerId)); - } + } else if (targetPlayerId.equals(playerId) && handleLibraryCastableCards(library, game, targetPlayerId)) { // for handling Panglacial Wurm newTarget.clearChosen(); continue; } + if (triggerEvents) { + game.fireEvent(GameEvent.getEvent(GameEvent.EventType.LIBRARY_SEARCHED, targetPlayerId, playerId)); + } break; } while (true); return true; diff --git a/Mage/src/main/java/mage/target/common/TargetDefender.java b/Mage/src/main/java/mage/target/common/TargetDefender.java index 3d48481d59a..863c419b28a 100644 --- a/Mage/src/main/java/mage/target/common/TargetDefender.java +++ b/Mage/src/main/java/mage/target/common/TargetDefender.java @@ -68,7 +68,8 @@ public class TargetDefender extends TargetImpl { } } for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_PLANESWALKER, sourceControllerId, game)) { - if ((notTarget || permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) + if ((notTarget + || permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) && filter.match(permanent, game)) { count++; if (count >= this.minNumberOfTargets) { @@ -84,7 +85,8 @@ public class TargetDefender extends TargetImpl { int count = 0; for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) { Player player = game.getPlayer(playerId); - if (player != null && filter.match(player, game)) { + if (player != null + && filter.match(player, game)) { count++; if (count >= this.minNumberOfTargets) { return true; @@ -109,13 +111,15 @@ public class TargetDefender extends TargetImpl { for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) { Player player = game.getPlayer(playerId); if (player != null - && (notTarget || player.canBeTargetedBy(targetSource, sourceControllerId, game)) + && (notTarget + || player.canBeTargetedBy(targetSource, sourceControllerId, game)) && filter.match(player, game)) { possibleTargets.add(playerId); } } for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_PLANESWALKER, sourceControllerId, game)) { - if ((notTarget || permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) + if ((notTarget + || permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) && filter.match(permanent, game)) { possibleTargets.add(permanent.getId()); } @@ -128,7 +132,8 @@ public class TargetDefender extends TargetImpl { Set possibleTargets = new HashSet<>(); for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) { Player player = game.getPlayer(playerId); - if (player != null && filter.match(player, game)) { + if (player != null + && filter.match(player, game)) { possibleTargets.add(playerId); } } @@ -162,7 +167,8 @@ public class TargetDefender extends TargetImpl { return filter.match(player, game); } Permanent permanent = game.getPermanent(id); - return permanent != null && filter.match(permanent, game); + return permanent != null + && filter.match(permanent, game); } @Override @@ -170,7 +176,8 @@ public class TargetDefender extends TargetImpl { Player player = game.getPlayer(id); MageObject targetSource = game.getObject(attackerId); if (player != null) { - return (notTarget || player.canBeTargetedBy(targetSource, (source == null ? null : source.getControllerId()), game)) + return (notTarget + || player.canBeTargetedBy(targetSource, (source == null ? null : source.getControllerId()), game)) && filter.match(player, game); } Permanent permanent = game.getPermanent(id); // planeswalker @@ -180,7 +187,8 @@ public class TargetDefender extends TargetImpl { if (source != null) { controllerId = source.getControllerId(); } - return (notTarget || permanent.canBeTargetedBy(targetSource, controllerId, game)) + return (notTarget + || permanent.canBeTargetedBy(targetSource, controllerId, game)) && filter.match(permanent, game); } return false; diff --git a/Mage/src/main/java/mage/util/CardUtil.java b/Mage/src/main/java/mage/util/CardUtil.java index ac9a02f558f..53da40ceef7 100644 --- a/Mage/src/main/java/mage/util/CardUtil.java +++ b/Mage/src/main/java/mage/util/CardUtil.java @@ -362,7 +362,7 @@ public final class CardUtil { /** * Parse card number as int (support base [123] and alternative numbers - * [123b]). + * [123b], [U123]). * * @param cardNumber origin card number * @return int @@ -373,10 +373,15 @@ public final class CardUtil { throw new IllegalArgumentException("Card number is empty."); } - if (Character.isDigit(cardNumber.charAt(cardNumber.length() - 1))) { - return Integer.parseInt(cardNumber); - } else { + if (!Character.isDigit(cardNumber.charAt(0))) { + // U123 + return Integer.parseInt(cardNumber.substring(1, cardNumber.length())); + } else if (!Character.isDigit(cardNumber.charAt(cardNumber.length() - 1))) { + // 123b return Integer.parseInt(cardNumber.substring(0, cardNumber.length() - 1)); + } else { + // 123 + return Integer.parseInt(cardNumber); } } diff --git a/Mage/src/main/java/mage/util/ClassScanner.java b/Mage/src/main/java/mage/util/ClassScanner.java index 46609ea4baf..47972fe400b 100644 --- a/Mage/src/main/java/mage/util/ClassScanner.java +++ b/Mage/src/main/java/mage/util/ClassScanner.java @@ -33,8 +33,8 @@ public final class ClassScanner { if(classLoader == null) classLoader = Thread.currentThread().getContextClassLoader(); assert classLoader != null; - HashMap dirs = new HashMap<>(); - TreeSet jars = new TreeSet<>(); + Map dirs = new HashMap<>(); + Set jars = new TreeSet<>(); for (String packageName : packages) { String path = packageName.replace('.', '/'); Enumeration resources = classLoader.getResources(path); @@ -51,8 +51,8 @@ public final class ClassScanner { } } - for (String filePath : dirs.keySet()) { - cards.addAll(findClasses(classLoader, new File(filePath), dirs.get(filePath), type)); + for (Map.Entry dir : dirs.entrySet()) { + cards.addAll(findClasses(classLoader, new File(dir.getKey()), dir.getValue(), type)); } for (String filePath : jars) { @@ -66,7 +66,7 @@ public final class ClassScanner { private static List findClasses(ClassLoader classLoader, File directory, String packageName, Class type) { List cards = new ArrayList<>(); - if (!directory.exists()) return cards; + if (directory == null || !directory.exists()) return cards; for (File file : directory.listFiles()) { if (file.getName().endsWith(".class")) { diff --git a/Mage/src/main/java/mage/watchers/common/PlayersAttackedThisTurnWatcher.java b/Mage/src/main/java/mage/watchers/common/PlayersAttackedThisTurnWatcher.java new file mode 100644 index 00000000000..0099fb12672 --- /dev/null +++ b/Mage/src/main/java/mage/watchers/common/PlayersAttackedThisTurnWatcher.java @@ -0,0 +1,91 @@ +package mage.watchers.common; + +import mage.constants.WatcherScope; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.players.PlayerList; +import mage.watchers.Watcher; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +/** + * @author JayDi85 + */ +public class PlayersAttackedThisTurnWatcher extends Watcher { + + // how many players or opponents each player attacked this turn + private final Map playersAttackedThisTurn = new HashMap<>(); + private final Map opponentsAttackedThisTurn = new HashMap<>(); + + public PlayersAttackedThisTurnWatcher() { + super(PlayersAttackedThisTurnWatcher.class.getSimpleName(), WatcherScope.GAME); + } + + public PlayersAttackedThisTurnWatcher(final PlayersAttackedThisTurnWatcher watcher) { + super(watcher); + + for (Map.Entry entry : watcher.playersAttackedThisTurn.entrySet()) { + this.playersAttackedThisTurn.put(entry.getKey(), entry.getValue()); + } + + for (Map.Entry entry : watcher.opponentsAttackedThisTurn.entrySet()) { + this.opponentsAttackedThisTurn.put(entry.getKey(), entry.getValue()); + } + } + + @Override + public PlayersAttackedThisTurnWatcher copy() { + return new PlayersAttackedThisTurnWatcher(this); + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() == GameEvent.EventType.BEGINNING_PHASE_PRE) { + playersAttackedThisTurn.clear(); + opponentsAttackedThisTurn.clear(); + } + + if (event.getType() == GameEvent.EventType.ATTACKER_DECLARED) { + + // players + PlayerList playersAttacked = playersAttackedThisTurn.get(event.getPlayerId()); + if (playersAttacked == null) { + playersAttacked = new PlayerList(); + } + UUID playerDefender = game.getCombat().getDefendingPlayerId(event.getSourceId(), game); + if (playerDefender != null) { + playersAttacked.add(playerDefender); + } + playersAttackedThisTurn.put(event.getPlayerId(), playersAttacked); + + // opponents + PlayerList opponentsAttacked = opponentsAttackedThisTurn.get(event.getPlayerId()); + if (opponentsAttacked == null) { + opponentsAttacked = new PlayerList(); + } + UUID opponentDefender = game.getCombat().getDefendingPlayerId(event.getSourceId(), game); + if (opponentDefender != null && game.getOpponents(event.getPlayerId()).contains(opponentDefender)) { + opponentsAttacked.add(opponentDefender); + } + opponentsAttackedThisTurn.put(event.getPlayerId(), opponentsAttacked); + } + } + + public int getAttackedPlayersCount(UUID playerID) { + PlayerList defendersList = playersAttackedThisTurn.getOrDefault(playerID, null); + if (defendersList != null) { + return defendersList.size(); + } + return 0; + } + + public int getAttackedOpponentsCount(UUID playerID) { + PlayerList defendersList = opponentsAttackedThisTurn.getOrDefault(playerID, null); + if (defendersList != null) { + return defendersList.size(); + } + return 0; + } +} diff --git a/pom.xml b/pom.xml index 39d6abf21b4..62c3c3a0d9a 100644 --- a/pom.xml +++ b/pom.xml @@ -103,7 +103,7 @@ org.slf4j slf4j-log4j12 - 1.7.19 + 1.7.25