diff --git a/Mage.Client/src/main/java/mage/client/chat/ChatPanelBasic.java b/Mage.Client/src/main/java/mage/client/chat/ChatPanelBasic.java index 26f0ab1a0f9..c370581d9a1 100644 --- a/Mage.Client/src/main/java/mage/client/chat/ChatPanelBasic.java +++ b/Mage.Client/src/main/java/mage/client/chat/ChatPanelBasic.java @@ -38,9 +38,12 @@ import java.awt.Dimension; import java.awt.Font; import java.awt.event.KeyEvent; import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.swing.JTextField; import mage.client.MageFrame; import mage.client.SessionHandler; +import mage.client.dialog.PreferencesDialog; import mage.client.util.GUISizeHelper; import mage.view.ChatMessage.MessageColor; import mage.view.ChatMessage.MessageType; @@ -184,6 +187,45 @@ public class ChatPanelBasic extends javax.swing.JPanel { } } + Pattern profanityPattern = Pattern.compile(".*(1ab1a|1d1ot|13p3r|13sb1ans|13sbo|13s13|13sb1an|13sbo|13sy|1nbr3d|1nc3st|1njun|1ub3|\\Wbj|\\Wcum|\\Wdum|\\Wfag|\\Wfap|\\W[sf]uk|\\Wj1s|\\Wp3do|\\Wp33|\\Wpoo\\W|\\Wt1t|aho13|an1ngu|ana1|anus|ar3o1a|ar3o13|ary1an|axyx|axyxhat|axyxho13|axyxmast3r|axyxmunch|axyxw1p3|b1atch|b1gt1t|b1mbo|b1ow|b1tch|ba1s|bab3|bang|barf|bastard|bawdy|b3an3r|b3ard3dc1am|b3ast1a1ty|b3atch|b3at3r|b3av3r|b3otch|b3yotch|bo1nk|bod1y|bon3d|bon3r|bon3|bob|bot13|boty|bow31|br3ast|bug3r|bukak3|bung|busty|buxyx|c1t|caca|cahon3|cam31to3|carp3tmunch3r|cawk|c3rv1x|ch1nc|ch1nk|chod3|co1ta1|cockb1ock|cockho1st3r|cocknock3r|cocksmok3r|cocksuck3r|cock|condom|corksuck3r|crabs|cums1ut|cumshot|cumsta1n|cnt|cun1ngus|cuntfac3|cunthunt3r|cunt|d1ck|d1k3|d1do|d1mw1t|d1ng13|d1psh1p|dago|dam1t|damn1t|damn3d|damn|dawg13sty13|dog13sty13|dogysty13|dong|dop3y|douch3|drunk|dumb|dumas|dum|dumbas|dumy|dyk3|3jacu1at3|3n1arg3m3nt|3r3ct1on|3r3ct|3rot1c|3xtacy|3xtasy|f.ck|f1osy|f1st3d|f1st1ng|f1sty|fa1gt|fa1g|fack|fag1t|fag3d|fagot|fag|[sf]cuk|f31at1o|f31at3|f31ch1ng|f31ch3r|f31ch|f31tch3r|f31tch|foad|fobar|fond13|for3sk1n|fu.k|fudg3pack3r|[sf]uk|g1ans|g1go1o|ganja|ghay|gh3y|go1d3nshow3r|gonad|gok|gr1ngo|h1t13r|handjob|hardon|hokah|hok3r|homo|honky|hor|hotch|hot3r|horny|hump1ng|hump3d|hump|hym3n|j1sm|j1s3d|j1sm|j1s|jackas|jackho13|jackof|j3rk3d|j3rkof|j3rk|junk13|junky|k1an|k1k3|k1nky|knob3nd|kyk3|mams|masa|mast3rba|masturba|max1|m3ns3s|m3nstruat|m[sf]uck1ng|mofo|moron|moth3rf|mthrf|muf|n1ger|n1ga|n1mrod|n1ny|n1p13|nak3d|napa1m|napy|nas1|n3gro|noky|nympho|op1at3|op1um|ora1y|ora1|org13s|organ|orgasm|orgy|ovary|ovum|p1owb1t3r|p1mp|p1nko|p1s3d|p1sof|p1s|pak1|pant13|panty|past13|pasty|p3ck3r|p3doph1|p3p3|p3n1a1|p3n13|p3n1s|p3n3trat1on|p3n3trat3|p3rv3rs1on|p3yot3|pha1c|phuck|po1ack|po1ock|pontang|pop|pr1ck|pr1g|pron|pub1|pub3|punkas|punky|pus1|pusy|puto|qu1cky|qu1ck13|qu1m|qu3af|qu3ro|qu3rs|qu3r|r1mjob|r1tard|racy|rap1st|rap3d|rap3r|rap3|raunch|r31ch|r3cta1|r3ctum|r3ctus|r3tard|r3tar|rtard|rumpram3r|rump|s1av3|s13as|s1ut|sack|sad1s|scag|sch1ong|sch1so|scr3w|scrog|scrot|scrud|scum|s3aman|s3am3n|s3duc3|s3m3n|s3xua1|sh1t|skag|skank|sm3gma|smut|sn1p3r|snatch|sodom|sp1ck|sp1c|sp1k|sp3rm|spunk|st3amy|stfu|ston3d|str1p|strok3|stup1d|suck|sumofab1atch|t1nk13|t1t[sf]uck|tampon|tard|t3abag1ng|t3at|t3st1|t3st3|t3urd|thrust|tramp|trans|trashy|twat|ug1y|unw3d|ur1n3a|ut3rus|vag1na|vu1gar|vu1va|w1g3r|wang|wank3r|wank|w31n3r|w31rdo|w3dg13|w3n13|w3tback|w3w3|wh1t3y|wh1s|whor3).*"); + Pattern profanity2Pattern = Pattern.compile(".*(1ab1a|1d1ot|13p3r|13sb1ans|13sbo|13s13|13sb1an|13sbo|13sy|1nbr3d|1nc3st|1njun|1ub3|\\Wbj|\\Wcum|\\Wdum|\\Wfag|\\Wfap|\\W[sf]uk|\\Wj1s|\\Wp3do|\\Wp3|\\Wpo\\W|\\Wt1t|aho13|an1ngu|ana1|anus|ar3o1a|ar3o13|ary1an|axyx|axyxhat|axyxho13|axyxmast3r|axyxmunch|axyxw1p3|b1atch|b1gt1t|b1mbo|b1ow|b1tch|ba1s|bab3|bang|barf|bastard|bawdy|b3an3r|b3ard3dc1am|b3ast1a1ty|b3atch|b3at3r|b3av3r|b3otch|b3yotch|bo1nk|bod1y|bon3d|bon3r|bon3|bob|bot13|boty|bow31|br3ast|bug3r|bukak3|bung|busty|buxyx|c1t|caca|cahon3|cam31to3|carp3tmunch3r|cawk|c3rv1x|ch1nc|ch1nk|chod3|co1ta1|cockb1ock|cockho1st3r|cocknock3r|cocksmok3r|cocksuck3r|cock|condom|corksuck3r|crabs|cums1ut|cumshot|cumsta1n|cnt|cun1ngus|cuntfac3|cunthunt3r|cunt|d1ck|d1k3|d1do|d1mw1t|d1ng13|d1psh1p|dago|dam1t|damn1t|damn3d|damn|dawg13sty13|dog13sty13|dogysty13|dong|dop3y|douch3|drunk|dumb|dum|dumas|dumbas|dumy|dyk3|3jacu1at3|3n1arg3m3nt|3r3ct1on|3r3ct|3rot1c|3xtacy|3xtasy|f.ck|f1osy|f1st3d|f1st1ng|f1sty|fa1gt|fa1g|fack|fag1t|fag3d|fagot|fag|[sf]cuk|f31at1o|f31at3|f31ch1ng|f31ch3r|f31ch|f31tch3r|f31tch|foad|fobar|fond13|for3sk1n|fu.k|fudg3pack3r|[sf]uk|g1ans|g1go1o|ganja|ghay|gh3y|go1d3nshow3r|gonad|gr1ngo|h1t13r|handjob|hardon|hokah|hok3r|homo|honky|hor|hotch|hot3r|horny|hump1ng|hump3d|hump|hym3n|j1sm|j1s3d|j1sm|j1s|jackas|jackho13|jackof|j3rk3d|j3rkof|j3rk|junk13|junky|k1an|k1k3|k1nky|knob3nd|kyk3|mams|masa|mast3rba|masturba|max1|m3ns3s|m3nstruat|m[sf]uck1ng|mofo|moron|moth3rf|mthrf|muf|n1ga|n1ger|n1mrod|n1ny|n1p13|nak3d|napa1m|napy|nas1|n3gro|noky|nympho|op1at3|op1um|ora1y|ora1|org13s|organ|orgasm|orgy|ovary|ovum|p1owb1t3r|p1mp|p1nko|p1s3d|p1sof|p1s|pak1|pant13|panty|past13|pasty|p3ck3r|p3doph1|p3p3|p3n1a1|p3n13|p3n1s|p3n3trat1on|p3n3trat3|p3rv3rs1on|p3yot3|pha1c|phuck|po1ack|po1ock|pontang|pop|porno|porn|pr1ck|pr1g|pron|pub1|pub3|punkas|punky|pus1|pusy|puto|qu1cky|qu1ck13|qu1m|qu3af|qu3ro|qu3rs|qu3r|r1mjob|r1tard|racy|rap1st|rap3d|rap3r|rap3|raunch|r31ch|r3cta1|r3ctum|r3ctus|r3tard|r3tar|rtard|rumpram3r|rump|s1av3|s13as|s1ut|sack|sad1s|scag|sch1ong|sch1so|scr3w|scrog|scrot|scrud|scum|s3aman|s3am3n|s3duc3|s3m3n|s3xua1|sh1t|skag|skank|sm3gma|smut|sn1p3r|snatch|sodom|sp1ck|sp1c|sp1k|sp3rm|spunk|st3amy|stfu|ston3d|str1p|strok3|stup1d|suck|sumofab1atch|t1nk13|t1t[sf]uck|tampon|tard|t3abag1ng|t3at|t3st1|t3st3|t3urd|thrust|tramp|trans|trashy|twat|ug1y|unw3d|ur1n3a|ut3rus|vag1na|vu1gar|vu1va|w1g3r|wang|wank3r|wank|w31n3r|w31rdo|w3dg13|w3n13|w3tback|w3w3|wh1t3y|wh1s|whor3).*"); + + private boolean containsSwearing(String message, String level) { + + if (level.equals("0")) { + return false; + } + message = "." + message + "."; + + message = message.toLowerCase(); + message = message.replaceAll("[a@]([s5][s5]+)", "axyx"); + message = message.replaceAll("b.([t\\+][t\\+]+)", "buxyx"); + message = message.replaceAll("(.)(\\1{1,})", "$1"); + message = message.replaceAll("[@]", "a"); + message = message.replaceAll("[il]", "1"); + message = message.replaceAll("[e]", "3"); + message = message.replaceAll("[0]", "o"); + message = message.replaceAll("[5z]", "s"); + message = message.replaceAll("\\W", "."); + message = message.replaceAll("(.)(\\1{1,})", "$1"); + message = message.replaceAll("\\.", ""); + + Matcher matchPattern = profanityPattern.matcher(message); + if (matchPattern.find()) { + return true; + } + + if (level.equals("2")) { + message = message.replaceAll("\\.", ""); + message = "." + message + "."; + matchPattern = profanity2Pattern.matcher(message); + if (matchPattern.find()) { + return true; + } + } + return false; + } + /** * Display message in the chat. Use different colors for timestamp, username * and message. @@ -194,6 +236,8 @@ public class ChatPanelBasic extends javax.swing.JPanel { * @param messageType * @param color Preferred color. Not used. */ + Pattern cardNamePattern = Pattern.compile(".*.*"); + public void receiveMessage(String username, String message, String time, MessageType messageType, MessageColor color) { StringBuilder text = new StringBuilder(); if (time != null) { @@ -227,11 +271,42 @@ public class ChatPanelBasic extends javax.swing.JPanel { if (color.equals(MessageColor.YELLOW)) { textColor = "Yellow"; } - if (username != null && !username.isEmpty()) { - text.append(getColoredText(userColor, username + userSeparator)); + if (messageType == MessageType.WHISPER) { + if (username.equalsIgnoreCase("Whisper from " + SessionHandler.getUserName())) { + if (message.toLowerCase().startsWith("profanity 0")) { + PreferencesDialog.saveValue(PreferencesDialog.KEY_GAME_USE_PROFANITY_FILTER, "0"); + } else if (message.toLowerCase().startsWith("profanity 1")) { + PreferencesDialog.saveValue(PreferencesDialog.KEY_GAME_USE_PROFANITY_FILTER, "1"); + } else if (message.toLowerCase().startsWith("profanity 2")) { + PreferencesDialog.saveValue(PreferencesDialog.KEY_GAME_USE_PROFANITY_FILTER, "2"); + } + } + } + + Matcher matchPattern = cardNamePattern.matcher(message); + String messageToTest = message; + while (matchPattern.find()) { + messageToTest = message.replaceFirst("", ""); + } + + if (messageType == MessageType.USER_INFO || messageType == MessageType.GAME || messageType == MessageType.STATUS + || PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_USE_PROFANITY_FILTER, "0").equals("0") + || !PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_USE_PROFANITY_FILTER, "0").equals("0") && !containsSwearing(messageToTest, PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_USE_PROFANITY_FILTER, "0"))) { + if (username != null && !username.isEmpty()) { + text.append(getColoredText(userColor, username + userSeparator)); + } + text.append(getColoredText(textColor, ManaSymbols.replaceSymbolsWithHTML(message, ManaSymbols.Type.CHAT))); + this.txtConversation.append(text.toString()); + } else if (PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_USE_PROFANITY_FILTER, "0").equals("1")) { + if (username != null && !username.isEmpty()) { + text.append(getColoredText("black", username + userSeparator)); + } + text.append(getColoredText(textColor, ManaSymbols.replaceSymbolsWithHTML("" + message + " Profanity detected. Type: /w " + SessionHandler.getUserName() + " profanity 0' to turn the filter off", ManaSymbols.Type.CHAT))); + this.txtConversation.append(text.toString()); + } else if (PreferencesDialog.getCachedValue(PreferencesDialog.KEY_GAME_USE_PROFANITY_FILTER, "0").equals("2")) { + text.append(getColoredText(textColor, ManaSymbols.replaceSymbolsWithHTML("" + username + ": Profanity detected. To make it less strict, type: /w " + SessionHandler.getUserName() + " profanity 1", ManaSymbols.Type.CHAT))); + this.txtConversation.append(text.toString()); } - text.append(getColoredText(textColor, ManaSymbols.replaceSymbolsWithHTML(message, ManaSymbols.Type.CHAT))); - this.txtConversation.append(text.toString()); } protected String getColoredText(String color, String text) { 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 4ee513a38a6..76d379f1c0b 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/ConnectDialog.java @@ -26,7 +26,7 @@ * or implied, of BetaSteward_at_googlemail.com. */ -/* + /* * ConnectDialog.java * * Created on 20-Jan-2010, 9:37:07 PM @@ -391,6 +391,7 @@ public class ConnectDialog extends MageDialog { connection.setUsername(this.txtUserName.getText().trim()); connection.setPassword(this.txtPassword.getText().trim()); connection.setForceDBComparison(this.chkForceUpdateDB.isSelected()); + connection.setUserIdStr(System.getProperty("user.name")); MageFrame.getPreferences().put(KEY_CONNECT_FLAG, ((CountryItemEditor) cbFlag.getEditor()).getImageItem()); PreferencesDialog.setProxyInformation(connection); 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 da61f41dfb0..1c63bcec168 100644 --- a/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java +++ b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java @@ -98,6 +98,7 @@ public class PreferencesDialog extends javax.swing.JDialog { public static final String KEY_GAME_SHOW_STORM_COUNTER = "gameShowStormCounter"; public static final String KEY_GAME_CONFIRM_EMPTY_MANA_POOL = "gameConfirmEmptyManaPool"; public static final String KEY_GAME_ASK_MOVE_TO_GRAVE_ORDER = "gameAskMoveToGraveORder"; + public static final String KEY_GAME_USE_PROFANITY_FILTER = "gameUseProfanityFilter"; public static final String KEY_GUI_TABLE_FONT_SIZE = "guiTableFontSize"; public static final String KEY_GUI_CHAT_FONT_SIZE = "guiChatFontSize"; @@ -3519,6 +3520,7 @@ public class PreferencesDialog extends javax.swing.JDialog { if (selectedAvatarId == 0) { getSelectedAvatar(); } + String userStrId = System.getProperty("user.name"); return new UserData(UserGroup.PLAYER, PreferencesDialog.selectedAvatarId, PreferencesDialog.getCachedValue(PreferencesDialog.KEY_SHOW_ABILITY_PICKER_FORCED, "true").equals("true"), @@ -3532,7 +3534,8 @@ public class PreferencesDialog extends javax.swing.JDialog { PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PASS_PRIORITY_CAST, "true").equals("true"), PreferencesDialog.getCachedValue(PreferencesDialog.KEY_PASS_PRIORITY_ACTIVATION, "true").equals("true"), PreferencesDialog.getCachedValue(PreferencesDialog.KEY_AUTO_ORDER_TRIGGER, "true").equals("true"), - PreferencesDialog.getCachedValue(PreferencesDialog.KEY_USE_FIRST_MANA_ABILITY, "false").equals("true") + PreferencesDialog.getCachedValue(PreferencesDialog.KEY_USE_FIRST_MANA_ABILITY, "false").equals("true"), + userStrId ); } 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 a5b8bcd5571..c2bd89eb958 100644 --- a/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java +++ b/Mage.Client/src/main/java/mage/client/remote/CallbackClientImpl.java @@ -421,7 +421,8 @@ public class CallbackClientImpl implements CallbackClient { case TABLES: usedPanel.receiveMessage("", new StringBuilder("Download card images by using the \"Images\" menu to the top right .") .append("
Download icons and symbols by using the \"Symbols\" menu to the top right.") - .append("
\\list - Show a list of available chat commands.").toString(), + .append("
\\list - Show a list of available chat commands.") + .append("
Type \\w yourUserName profanity 0 (or 1 or 2) to turn off/on the profanity filter").toString(), null, MessageType.USER_INFO, ChatMessage.MessageColor.BLUE); 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 731e5cff2ba..30003137361 100644 --- a/Mage.Client/src/main/java/mage/client/table/TablesPanel.java +++ b/Mage.Client/src/main/java/mage/client/table/TablesPanel.java @@ -599,7 +599,7 @@ public class TablesPanel extends javax.swing.JPanel { formatFilterList.add(RowFilter.regexFilter("^Limited", TableTableModel.COLUMN_DECK_TYPE)); } if (btnFormatOther.isSelected()) { - formatFilterList.add(RowFilter.regexFilter("^Momir Basic|^Constructed - Pauper|^Constructed - Frontier|^Constructed - Extended|^Constructed - Eternal|^Constructed - Historical|^Constructed - Super|^Constructed - Freeform|^Australian Highlander", TableTableModel.COLUMN_DECK_TYPE)); + formatFilterList.add(RowFilter.regexFilter("^Momir Basic|^Constructed - Pauper|^Constructed - Frontier|^Constructed - Extended|^Constructed - Eternal|^Constructed - Historical|^Constructed - Super|^Constructed - Freeform|^Australian Highlander|^Canadian Highlander", TableTableModel.COLUMN_DECK_TYPE)); } List> skillFilterList = new ArrayList<>(); diff --git a/Mage.Common/src/mage/interfaces/MageServer.java b/Mage.Common/src/mage/interfaces/MageServer.java index 817ccf84a98..d7da351f8b5 100644 --- a/Mage.Common/src/mage/interfaces/MageServer.java +++ b/Mage.Common/src/mage/interfaces/MageServer.java @@ -62,7 +62,7 @@ public interface MageServer { boolean resetPassword(String sessionId, String email, String authToken, String password) throws MageException; - boolean connectUser(String userName, String password, String sessionId, MageVersion version) throws MageException; + boolean connectUser(String userName, String password, String sessionId, MageVersion version, String userIdStr) throws MageException; boolean connectAdmin(String password, String sessionId, MageVersion version) throws MageException; @@ -72,7 +72,7 @@ public interface MageServer { List getMissingCardsData(List classNames); // user methods - boolean setUserData(String userName, String sessionId, UserData userData, String clientVersion) throws MageException; + boolean setUserData(String userName, String sessionId, UserData userData, String clientVersion, String userIdStr) throws MageException; void sendFeedbackMessage(String sessionId, String username, String title, String type, String message, String email) throws MageException; diff --git a/Mage.Common/src/mage/remote/Connection.java b/Mage.Common/src/mage/remote/Connection.java index f739c45c5e1..a5cac723360 100644 --- a/Mage.Common/src/mage/remote/Connection.java +++ b/Mage.Common/src/mage/remote/Connection.java @@ -55,6 +55,7 @@ public class Connection { private String proxyPassword; private int clientCardDatabaseVersion; private boolean forceDBComparison; + private String userIdStr; private UserData userData; @@ -167,6 +168,14 @@ public class Connection { this.username = username; } + public String getUserIdStr() { + return userIdStr; + } + + public void setUserIdStr(String userIdStr) { + this.userIdStr = userIdStr; + } + public String getPassword() { return password; } diff --git a/Mage.Common/src/mage/remote/SessionImpl.java b/Mage.Common/src/mage/remote/SessionImpl.java index f8170971dd4..c3a98840c1f 100644 --- a/Mage.Common/src/mage/remote/SessionImpl.java +++ b/Mage.Common/src/mage/remote/SessionImpl.java @@ -222,9 +222,9 @@ public class SessionImpl implements Session { boolean registerResult; if (connection.getAdminPassword() == null) { // for backward compatibility. don't remove twice call - first one does nothing but for version checking - registerResult = server.connectUser(connection.getUsername(), connection.getPassword(), sessionId, client.getVersion()); + registerResult = server.connectUser(connection.getUsername(), connection.getPassword(), sessionId, client.getVersion(), connection.getUserIdStr()); if (registerResult) { - server.setUserData(connection.getUsername(), sessionId, connection.getUserData(), client.getVersion().toString()); + server.setUserData(connection.getUsername(), sessionId, connection.getUserData(), client.getVersion().toString(), connection.getUserIdStr()); } } else { registerResult = server.connectAdmin(connection.getAdminPassword(), sessionId, client.getVersion()); @@ -1466,7 +1466,7 @@ public class SessionImpl implements Session { } return false; } - + @Override public boolean setActivation(String userName, boolean active) { try { @@ -1571,7 +1571,7 @@ public class SessionImpl implements Session { public boolean updatePreferencesForServer(UserData userData) { try { if (isConnected()) { - server.setUserData(connection.getUsername(), sessionId, userData, null); + server.setUserData(connection.getUsername(), sessionId, userData, null, null); } return true; } catch (MageException ex) { diff --git a/Mage.Common/src/mage/utils/MageVersion.java b/Mage.Common/src/mage/utils/MageVersion.java index 68aeb0f11b8..734e4021419 100644 --- a/Mage.Common/src/mage/utils/MageVersion.java +++ b/Mage.Common/src/mage/utils/MageVersion.java @@ -41,7 +41,7 @@ public class MageVersion implements Serializable, Comparable { public final static int MAGE_VERSION_MAJOR = 1; public final static int MAGE_VERSION_MINOR = 4; public final static int MAGE_VERSION_PATCH = 21; - public final static String MAGE_VERSION_MINOR_PATCH = "V1"; + public final static String MAGE_VERSION_MINOR_PATCH = "V2"; public final static String MAGE_VERSION_INFO = ""; private final int major; diff --git a/Mage.Common/src/mage/view/UserView.java b/Mage.Common/src/mage/view/UserView.java index d8d5e6a1de0..1b4a9d082a2 100644 --- a/Mage.Common/src/mage/view/UserView.java +++ b/Mage.Common/src/mage/view/UserView.java @@ -46,8 +46,9 @@ public class UserView implements Serializable { private final Date muteChatUntil; private final String clientVersion; private final String email; + private final String userIdStr; - public UserView(String userName, String host, String sessionId, Date timeConnected, String gameInfo, String userState, Date muteChatUntil, String clientVersion, String email) { + public UserView(String userName, String host, String sessionId, Date timeConnected, String gameInfo, String userState, Date muteChatUntil, String clientVersion, String email, String userIdStr) { this.userName = userName; this.host = host; this.sessionId = sessionId; @@ -57,6 +58,7 @@ public class UserView implements Serializable { this.muteChatUntil = muteChatUntil; this.clientVersion = clientVersion; this.email = email; + this.userIdStr = userIdStr; } public String getUserName() { @@ -90,9 +92,12 @@ public class UserView implements Serializable { public Date getTimeConnected() { return timeConnected; } - + public String getEmail() { return email; } + public String getUserIdStr() { + return userIdStr; + } } 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 new file mode 100644 index 00000000000..00ac1782ec6 --- /dev/null +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/CanadianHighlander.java @@ -0,0 +1,165 @@ +/* + * Copyright 2011 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.deck; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +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; + +/** + * + * @author spjspj + */ +public class CanadianHighlander extends Constructed { + + public CanadianHighlander() { + this("Canadian Highlander"); + for (ExpansionSet set : Sets.getInstance().values()) { + if (set.getSetType() != SetType.CUSTOM_SET) { + setCodes.add(set.getCode()); + } + } + } + + public CanadianHighlander(String name) { + super(name); + } + + @Override + public boolean validate(Deck deck) { + boolean valid = true; + + if (deck.getCards().size() < 100) { + invalid.put("Deck", "Must contain 100 or more singleton cards: has " + (deck.getCards().size()) + " cards"); + valid = false; + } + + if (deck.getSideboard().size() > 0) { + invalid.put("Deck", "Sideboard can't contain any cards: has " + (deck.getSideboard().size()) + " cards"); + valid = false; + } + + List basicLandNames = new ArrayList<>(Arrays.asList("Forest", "Island", "Mountain", "Swamp", "Plains", "Wastes", + "Snow-Covered Forest", "Snow-Covered Island", "Snow-Covered Mountain", "Snow-Covered Swamp", "Snow-Covered Plains")); + Map counts = new HashMap<>(); + countCards(counts, deck.getCards()); + countCards(counts, deck.getSideboard()); + for (Map.Entry entry : counts.entrySet()) { + if (entry.getValue() > 1) { + if (!basicLandNames.contains(entry.getKey()) && !entry.getKey().equals("Relentless Rats") && !entry.getKey().equals("Shadowborn Apostle")) { + invalid.put(entry.getKey(), "Too many: " + entry.getValue()); + valid = false; + } + } + } + + int allowedPoints = 10 * (int) Math.floor(deck.getCards().size() / 100.0); + int totalPoints = 0; + for (Map.Entry entry : counts.entrySet()) { + String cn = entry.getKey(); + if (cn.equals("Balance") + || cn.equals("Dig Through Time") + || cn.equals("Fastbond") + || cn.equals("Gifts Ungiven") + || cn.equals("Intuition") + || cn.equals("Library of Alexandria") + || cn.equals("Lim-Dul's Vault") + || cn.equals("Mana Vault") + || cn.equals("Mind Twist") + || cn.equals("Oath of Druids") + || cn.equals("Personal Tutor") + || cn.equals("Stoneforge Mystic") + || cn.equals("Tainted Pact") + || cn.equals("Tolarian Academy") + || cn.equals("Transmute Artifact") + || cn.equals("Treasure Cruise") + || cn.equals("True-Name Nemesis")) { + totalPoints += 1; + invalid.put(entry.getKey(), " 1 point " + cn); + } + if (cn.equals("Doomsday") + || cn.equals("Enlightened Tutor") + || cn.equals("Imperial Seal") + || cn.equals("Mana Crypt") + || cn.equals("Mystical Tutor") + || cn.equals("Strip Mine") + || cn.equals("Summoner's Pact") + || cn.equals("Survival of the Fittest") + || cn.equals("Umezawa's Jitte")) { + totalPoints += 2; + invalid.put(entry.getKey(), " 2 points " + cn); + } + if (cn.equals("Birthing Pod") + || cn.equals("Mox Emerald") + || cn.equals("Mox Jet") + || cn.equals("Mox Pearl") + || cn.equals("Mox Ruby") + || cn.equals("Mox Sapphire") + || cn.equals("Protean Hulk") + || cn.equals("Vampiric Tutor")) { + totalPoints += 3; + invalid.put(entry.getKey(), " 3 points " + cn); + } + if (cn.equals("Demonic Tutor") + || cn.equals("Hermit Druid") + || cn.equals("Sol Ring")) { + totalPoints += 4; + invalid.put(entry.getKey(), " 4 points " + cn); + } + if (cn.equals("Ancestral Recall") + || cn.equals("Natural Order") + || cn.equals("Time Walk") + || cn.equals("Tinker")) { + totalPoints += 5; + invalid.put(entry.getKey(), " 5 points " + cn); + } + if (cn.equals("Flash")) { + totalPoints += 6; + invalid.put(entry.getKey(), " 6 points " + cn); + } + if (cn.equals("Black Lotus") + || cn.equals("Time Vault")) { + totalPoints += 7; + invalid.put(entry.getKey(), " 7 points " + cn); + } + } + if (totalPoints > allowedPoints) { + invalid.put("Total points too high", "Your calculated point total was " + totalPoints); + valid = false; + } + return valid; + } +} diff --git a/Mage.Server.Plugins/Mage.Game.CanadianHighlanderDuel/pom.xml b/Mage.Server.Plugins/Mage.Game.CanadianHighlanderDuel/pom.xml new file mode 100644 index 00000000000..8bd6cbd2780 --- /dev/null +++ b/Mage.Server.Plugins/Mage.Game.CanadianHighlanderDuel/pom.xml @@ -0,0 +1,50 @@ + + + + 4.0.0 + + + org.mage + mage-server-plugins + 1.4.21 + + + mage-game-canadianhighlanderduel + jar + Mage Game Canadian Highlander Two Player + + + + ${project.groupId} + mage + ${project.version} + + + + + src + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.7 + 1.7 + + + + maven-resources-plugin + + UTF-8 + + + + + + mage-game-canadianhighlanderduel + + + + + diff --git a/Mage.Server.Plugins/Mage.Game.CanadianHighlanderDuel/src/mage/game/CanadianHighlanderDuel.java b/Mage.Server.Plugins/Mage.Game.CanadianHighlanderDuel/src/mage/game/CanadianHighlanderDuel.java new file mode 100644 index 00000000000..1ea0483ef91 --- /dev/null +++ b/Mage.Server.Plugins/Mage.Game.CanadianHighlanderDuel/src/mage/game/CanadianHighlanderDuel.java @@ -0,0 +1,60 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. +*/ + +package mage.game; + +import mage.constants.MultiplayerAttackOption; +import mage.constants.RangeOfInfluence; +import mage.game.match.MatchType; + +public class CanadianHighlanderDuel extends GameCanadianHighlanderImpl { + + public CanadianHighlanderDuel(MultiplayerAttackOption attackOption, RangeOfInfluence range, int freeMulligans, int startLife) { + super(attackOption, range, freeMulligans, startLife); + } + + public CanadianHighlanderDuel(final CanadianHighlanderDuel game) { + super(game); + } + + @Override + public MatchType getGameType() { + return new CanadianHighlanderDuelType(); + } + + @Override + public int getNumPlayers() { + return 2; + } + + @Override + public CanadianHighlanderDuel copy() { + return new CanadianHighlanderDuel(this); + } + +} diff --git a/Mage.Server.Plugins/Mage.Game.CanadianHighlanderDuel/src/mage/game/CanadianHighlanderDuelMatch.java b/Mage.Server.Plugins/Mage.Game.CanadianHighlanderDuel/src/mage/game/CanadianHighlanderDuelMatch.java new file mode 100644 index 00000000000..7621a40a40f --- /dev/null +++ b/Mage.Server.Plugins/Mage.Game.CanadianHighlanderDuel/src/mage/game/CanadianHighlanderDuelMatch.java @@ -0,0 +1,52 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.game; + +import mage.game.match.MatchImpl; +import mage.game.match.MatchOptions; + +/** + * + * @author spjspj + */ +public class CanadianHighlanderDuelMatch extends MatchImpl { + + public CanadianHighlanderDuelMatch(MatchOptions options) { + super(options); + } + + @Override + public void startGame() throws GameException { + int startLife = 20; + CanadianHighlanderDuel game = new CanadianHighlanderDuel(options.getAttackOption(), options.getRange(), options.getFreeMulligans(), startLife); + game.setStartMessage(this.createGameStartMessage()); + initGame(game); + games.add(game); + } + +} diff --git a/Mage.Server.Plugins/Mage.Game.CanadianHighlanderDuel/src/mage/game/CanadianHighlanderDuelType.java b/Mage.Server.Plugins/Mage.Game.CanadianHighlanderDuel/src/mage/game/CanadianHighlanderDuelType.java new file mode 100644 index 00000000000..b0f92c2442d --- /dev/null +++ b/Mage.Server.Plugins/Mage.Game.CanadianHighlanderDuel/src/mage/game/CanadianHighlanderDuelType.java @@ -0,0 +1,57 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ + +package mage.game; + +import mage.game.match.MatchType; + +/** + * + * @author spjspj + */ +public class CanadianHighlanderDuelType extends MatchType { + + public CanadianHighlanderDuelType() { + this.name = "Canadian Highlander Two Player Duel"; + this.maxPlayers = 2; + this.minPlayers = 2; + this.numTeams = 0; + this.useAttackOption = false; + this.useRange = false; + this.sideboardingAllowed = false; + } + + protected CanadianHighlanderDuelType(final CanadianHighlanderDuelType matchType) { + super(matchType); + } + + @Override + public CanadianHighlanderDuelType copy() { + return new CanadianHighlanderDuelType(this); + } +} diff --git a/Mage.Server.Plugins/Mage.Game.CanadianHighlanderDuel/target/maven-archiver/pom.properties b/Mage.Server.Plugins/Mage.Game.CanadianHighlanderDuel/target/maven-archiver/pom.properties new file mode 100644 index 00000000000..004569ce64a --- /dev/null +++ b/Mage.Server.Plugins/Mage.Game.CanadianHighlanderDuel/target/maven-archiver/pom.properties @@ -0,0 +1,5 @@ +#Generated by Maven +#Sun Feb 05 18:32:22 AEDT 2017 +version=1.4.21 +groupId=org.mage +artifactId=mage-game-canadianhighlanderduel diff --git a/Mage.Server.Plugins/pom.xml b/Mage.Server.Plugins/pom.xml index fa315738557..f97bf3e5a9d 100644 --- a/Mage.Server.Plugins/pom.xml +++ b/Mage.Server.Plugins/pom.xml @@ -22,6 +22,7 @@ Mage.Game.FreeForAll Mage.Game.MomirDuel Mage.Game.TinyLeadersDuel + Mage.Game.CanadianHighlanderDuel Mage.Game.TwoPlayerDuel Mage.Player.AI Mage.Player.AIMinimax @@ -34,4 +35,4 @@ Mage.Tournament.Sealed - \ No newline at end of file + diff --git a/Mage.Server/config/config.xml b/Mage.Server/config/config.xml index 1192fab3840..79a66add649 100644 --- a/Mage.Server/config/config.xml +++ b/Mage.Server/config/config.xml @@ -72,6 +72,7 @@ + @@ -136,6 +137,7 @@ + diff --git a/Mage.Server/pom.xml b/Mage.Server/pom.xml index 8815a14850e..ee4cf8f5600 100644 --- a/Mage.Server/pom.xml +++ b/Mage.Server/pom.xml @@ -142,6 +142,12 @@ ${project.version} runtime + + ${project.groupId} + mage-game-canadianhighlanderduel + ${project.version} + runtime + ${project.groupId} mage-game-momirduel diff --git a/Mage.Server/release/config/config.xml b/Mage.Server/release/config/config.xml index e488bf20e9e..c0265829081 100644 --- a/Mage.Server/release/config/config.xml +++ b/Mage.Server/release/config/config.xml @@ -69,6 +69,7 @@ + @@ -130,9 +131,11 @@ + + diff --git a/Mage.Server/src/main/java/mage/server/ChatManager.java b/Mage.Server/src/main/java/mage/server/ChatManager.java index 0127a61cb19..4619ad07c17 100644 --- a/Mage.Server/src/main/java/mage/server/ChatManager.java +++ b/Mage.Server/src/main/java/mage/server/ChatManager.java @@ -107,13 +107,6 @@ public class ChatManager { this.broadcast(chatId, userName, message, color, withTime, messageType, null); } - private boolean containsSwearing(String message) { - if (message != null && message.toLowerCase().matches("^.*(anal|asshole|balls|bastard|bitch|blowjob|cock|crap|cunt|cum|damn|dick|dildo|douche|fag|fuck|idiot|moron|penis|piss|prick|pussy|rape|rapist|sex|screw|shit|slut|vagina).*$")) { - return true; - } - return false; - } - final Pattern cardNamePattern = Pattern.compile("\\[(.*?)\\]"); public void broadcast(UUID chatId, String userName, String message, MessageColor color, boolean withTime, MessageType messageType, SoundToPlay soundToPlay) { @@ -167,11 +160,6 @@ public class ChatManager { } userMessages.put(userName, message); - if (containsSwearing(messageToCheck)) { - String informUser = "Your message appears to contain profanity"; - chatSessions.get(chatId).broadcastInfoToUser(user, informUser); - return; - } } if (messageType == MessageType.TALK) { @@ -204,6 +192,7 @@ public class ChatManager { String command = message.substring(1).trim().toUpperCase(Locale.ENGLISH); if (doError) { message += new StringBuilder("
Invalid User Command '" + message + "'.").append(COMMANDS_LIST).toString(); + message += "
Type \\w " + user.getName() + " profanity 0 (or 1 or 2) to use/not use the profanity filter"; chatSessions.get(chatId).broadcastInfoToUser(user, message); return true; } @@ -239,6 +228,7 @@ public class ChatManager { } if (command.equals("L") || command.equals("LIST")) { message += COMMANDS_LIST; + message += "
Type \\w " + user.getName() + " profanity 0 (or 1 or 2) to use/not use the profanity filter"; chatSessions.get(chatId).broadcastInfoToUser(user, message); return true; } diff --git a/Mage.Server/src/main/java/mage/server/MageServerImpl.java b/Mage.Server/src/main/java/mage/server/MageServerImpl.java index 255d29b4d19..1392b92ee58 100644 --- a/Mage.Server/src/main/java/mage/server/MageServerImpl.java +++ b/Mage.Server/src/main/java/mage/server/MageServerImpl.java @@ -132,7 +132,7 @@ public class MageServerImpl implements MageServer { } return true; } - + @Override public boolean resetPassword(String sessionId, String email, String authToken, String password) throws MageException { if (!ConfigSettings.getInstance().isAuthenticationActivated()) { @@ -158,13 +158,13 @@ public class MageServerImpl implements MageServer { } @Override - public boolean connectUser(String userName, String password, String sessionId, MageVersion version) throws MageException { + public boolean connectUser(String userName, String password, String sessionId, MageVersion version, String userIdStr) throws MageException { try { if (version.compareTo(Main.getVersion()) != 0) { logger.info("MageVersionException: userName=" + userName + ", version=" + version); throw new MageVersionException(version, Main.getVersion()); } - return SessionManager.getInstance().connectUser(sessionId, userName, password); + return SessionManager.getInstance().connectUser(sessionId, userName, password, userIdStr); } catch (MageException ex) { if (ex instanceof MageVersionException) { throw (MageVersionException) ex; @@ -175,11 +175,11 @@ public class MageServerImpl implements MageServer { } @Override - public boolean setUserData(final String userName, final String sessionId, final UserData userData, final String clientVersion) throws MageException { + public boolean setUserData(final String userName, final String sessionId, final UserData userData, final String clientVersion, final String userIdStr) throws MageException { return executeWithResult("setUserData", sessionId, new ActionWithBooleanResult() { @Override public Boolean execute() throws MageException { - return SessionManager.getInstance().setUserData(userName, sessionId, userData, clientVersion); + return SessionManager.getInstance().setUserData(userName, sessionId, userData, clientVersion, userIdStr); } }); } @@ -943,7 +943,8 @@ public class MageServerImpl implements MageServer { user.getUserState().toString(), user.getChatLockedUntil(), user.getClientVersion(), - user.getEmail() + user.getEmail(), + user.getUserIdStr() )); } return users; diff --git a/Mage.Server/src/main/java/mage/server/Session.java b/Mage.Server/src/main/java/mage/server/Session.java index 31f0a2fe492..55e9b5e6e92 100644 --- a/Mage.Server/src/main/java/mage/server/Session.java +++ b/Mage.Server/src/main/java/mage/server/Session.java @@ -264,12 +264,13 @@ public class Session { this.userId = user.getId(); } - public boolean setUserData(String userName, UserData userData, String clientVersion) { + public boolean setUserData(String userName, UserData userData, String clientVersion, String userIdStr) { User user = UserManager.getInstance().getUserByName(userName); if (user != null) { if (clientVersion != null) { user.setClientVersion(clientVersion); } + user.setUserIdStr(userIdStr); if (user.getUserData() == null || user.getUserData().getGroupId() == UserGroup.DEFAULT.getGroupId()) { user.setUserData(userData); } else { diff --git a/Mage.Server/src/main/java/mage/server/SessionManager.java b/Mage.Server/src/main/java/mage/server/SessionManager.java index 34b148da7a8..faaecf004b0 100644 --- a/Mage.Server/src/main/java/mage/server/SessionManager.java +++ b/Mage.Server/src/main/java/mage/server/SessionManager.java @@ -88,7 +88,7 @@ public class SessionManager { return true; } - public boolean connectUser(String sessionId, String userName, String password) throws MageException { + public boolean connectUser(String sessionId, String userName, String password, String userIdStr) throws MageException { Session session = sessions.get(sessionId); if (session != null) { String returnMessage = session.connectUser(userName, password); @@ -117,10 +117,10 @@ public class SessionManager { return false; } - public boolean setUserData(String userName, String sessionId, UserData userData, String clientVersion) throws MageException { + public boolean setUserData(String userName, String sessionId, UserData userData, String clientVersion, String userIdStr) throws MageException { Session session = sessions.get(sessionId); if (session != null) { - session.setUserData(userName, userData, clientVersion); + session.setUserData(userName, userData, clientVersion, userIdStr); return true; } return false; @@ -217,7 +217,7 @@ public class SessionManager { if (session != null) { return UserManager.getInstance().getUser(sessions.get(sessionId).getUserId()); } - logger.error(String.format("Session %s could not be found",sessionId)); + logger.error(String.format("Session %s could not be found", sessionId)); return Optional.empty(); } diff --git a/Mage.Server/src/main/java/mage/server/User.java b/Mage.Server/src/main/java/mage/server/User.java index ed71a256cf1..5fb16191103 100644 --- a/Mage.Server/src/main/java/mage/server/User.java +++ b/Mage.Server/src/main/java/mage/server/User.java @@ -96,6 +96,7 @@ public class User { private Date lockedUntil; private final AuthorizedUser authorizedUser; private String clientVersion; + private String userIdStr; public User(String userName, String host, AuthorizedUser authorizedUser) { this.userId = UUID.randomUUID(); @@ -127,6 +128,7 @@ public class User { this.tablesToDelete = new ArrayList<>(); this.sessionId = ""; this.clientVersion = ""; + this.userIdStr = ""; } public String getName() { @@ -178,6 +180,14 @@ public class User { this.clientVersion = clientVersion; } + public void setUserIdStr(String userIdStr) { + this.userIdStr = userIdStr; + } + + public String getUserIdStr() { + return this.userIdStr; + } + public String getClientVersion() { return clientVersion; } @@ -199,7 +209,7 @@ public class User { public void lostConnection() { // Because watched games don't get restored after reconnection call stop watching - for (Iterator iterator = watchedGames.iterator(); iterator.hasNext(); ) { + for (Iterator iterator = watchedGames.iterator(); iterator.hasNext();) { UUID gameId = iterator.next(); GameManager.getInstance().stopWatching(gameId, userId); iterator.remove(); @@ -781,7 +791,7 @@ public class User { } return number; } - + public String getEmail() { if (authorizedUser != null) { return authorizedUser.email; diff --git a/Mage.Server/src/main/java/mage/server/game/GameController.java b/Mage.Server/src/main/java/mage/server/game/GameController.java index 0dd85984d45..5436f1c1ee2 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameController.java +++ b/Mage.Server/src/main/java/mage/server/game/GameController.java @@ -44,7 +44,6 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import java.util.zip.GZIPOutputStream; - import mage.MageException; import mage.abilities.Ability; import mage.cards.Card; @@ -313,10 +312,10 @@ public class GameController implements GameCallback { logger.fatal("- userId: " + userId); return; } - if (!user.isPresent()) { - logger.fatal("User not found : "+userId); - return; - } + if (!user.isPresent()) { + logger.fatal("User not found : " + userId); + return; + } Player player = game.getPlayer(playerId); if (player == null) { logger.fatal("Player not found - playerId: " + playerId); @@ -350,8 +349,9 @@ public class GameController implements GameCallback { private void sendInfoAboutPlayersNotJoinedYet() { for (Player player : game.getPlayers().values()) { if (!player.hasLeft() && player.isHuman()) { - User user = getUserByPlayerId(player.getId()).get(); - if (user != null) { + Optional requestedUser = getUserByPlayerId(player.getId()); + if (requestedUser.isPresent()) { + User user = requestedUser.get(); if (!user.isConnected()) { if (gameSessions.get(player.getId()) == null) { // join the game because player has not joined are was removed because of disconnect diff --git a/Mage.Server/src/main/java/mage/server/game/GameSessionPlayer.java b/Mage.Server/src/main/java/mage/server/game/GameSessionPlayer.java index c595ae16473..d2b897c6e89 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameSessionPlayer.java +++ b/Mage.Server/src/main/java/mage/server/game/GameSessionPlayer.java @@ -27,6 +27,10 @@ */ package mage.server.game; +import java.io.Serializable; +import java.util.*; +import java.util.Map.Entry; +import java.util.concurrent.ExecutorService; import mage.cards.Cards; import mage.choices.Choice; import mage.constants.ManaType; @@ -41,11 +45,6 @@ import mage.server.util.ThreadExecutor; import mage.view.*; import org.apache.log4j.Logger; -import java.io.Serializable; -import java.util.*; -import java.util.Map.Entry; -import java.util.concurrent.ExecutorService; - /** * @author BetaSteward_at_googlemail.com */ @@ -91,39 +90,39 @@ public class GameSessionPlayer extends GameSessionWatcher { public void chooseAbility(final AbilityPickerView abilities) { if (!killed) { - UserManager.getInstance().getUser(userId).ifPresent(user -> - user.fireCallback(new ClientCallback("gameChooseAbility", game.getId(), abilities))); + UserManager.getInstance().getUser(userId).ifPresent(user + -> user.fireCallback(new ClientCallback("gameChooseAbility", game.getId(), abilities))); } } public void choosePile(final String message, final CardsView pile1, final CardsView pile2) { if (!killed) { - UserManager.getInstance().getUser(userId).ifPresent(user -> - user.fireCallback(new ClientCallback("gameChoosePile", game.getId(), new GameClientMessage(message, pile1, pile2)))); + UserManager.getInstance().getUser(userId).ifPresent(user + -> user.fireCallback(new ClientCallback("gameChoosePile", game.getId(), new GameClientMessage(message, pile1, pile2)))); } } public void chooseChoice(final Choice choice) { if (!killed) { - UserManager.getInstance().getUser(userId).ifPresent(user -> - user.fireCallback(new ClientCallback("gameChooseChoice", game.getId(), new GameClientMessage(choice)))); + UserManager.getInstance().getUser(userId).ifPresent(user + -> user.fireCallback(new ClientCallback("gameChooseChoice", game.getId(), new GameClientMessage(choice)))); } } public void playMana(final String message, final Map options) { if (!killed) { - UserManager.getInstance().getUser(userId).ifPresent(user -> - user.fireCallback(new ClientCallback("gamePlayMana", game.getId(), new GameClientMessage(getGameView(), message, options)))); + UserManager.getInstance().getUser(userId).ifPresent(user + -> user.fireCallback(new ClientCallback("gamePlayMana", game.getId(), new GameClientMessage(getGameView(), message, options)))); } } public void playXMana(final String message) { if (!killed) { - UserManager.getInstance().getUser(userId).ifPresent(user -> - user.fireCallback(new ClientCallback("gamePlayXMana", game.getId(), new GameClientMessage(getGameView(), message)))); + UserManager.getInstance().getUser(userId).ifPresent(user + -> user.fireCallback(new ClientCallback("gamePlayXMana", game.getId(), new GameClientMessage(getGameView(), message)))); } } @@ -148,7 +147,7 @@ public class GameSessionPlayer extends GameSessionWatcher { if (!killed) { Optional requestingUser = UserManager.getInstance().getUser(requestingUserId); Optional requestedUser = UserManager.getInstance().getUser(userId); - if (!requestedUser.isPresent() && !requestingUser.isPresent()) { + if (requestedUser.isPresent() && requestingUser.isPresent()) { String message; switch (numberTurns) { case 0: @@ -179,7 +178,7 @@ public class GameSessionPlayer extends GameSessionWatcher { UserRequestMessage userRequestMessage = new UserRequestMessage( "User request", "Allow user " + watcher.get().getName() + " for this match to see your hand cards?
" - + "(You can revoke this every time using related popup menu item of your battlefield.)"); + + "(You can revoke this every time using related popup menu item of your battlefield.)"); userRequestMessage.setRelatedUser(watcherId, watcher.get().getName()); userRequestMessage.setGameId(game.getId()); userRequestMessage.setButton1("Accept", PlayerAction.ADD_PERMISSION_TO_SEE_HAND_CARDS); diff --git a/Mage.Sets/src/mage/cards/a/AnkleShanker.java b/Mage.Sets/src/mage/cards/a/AnkleShanker.java index 9f5b9646b4a..add856199c7 100644 --- a/Mage.Sets/src/mage/cards/a/AnkleShanker.java +++ b/Mage.Sets/src/mage/cards/a/AnkleShanker.java @@ -40,6 +40,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; +import mage.filter.common.FilterCreaturePermanent; /** * @@ -58,7 +59,7 @@ public class AnkleShanker extends CardImpl { // Haste this.addAbility(HasteAbility.getInstance()); // Whenever Ankle Shanker attacks, creatures you control gain first strike and deathtouch until end of turn. - Effect effect = new GainAbilityControlledEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn); + Effect effect = new GainAbilityControlledEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn, new FilterCreaturePermanent("Creatures")); effect.setText("creatures you control gain first strike"); Ability ability = new AttacksTriggeredAbility(effect, false); effect = new GainAbilityControlledEffect(DeathtouchAbility.getInstance(), Duration.EndOfTurn); diff --git a/Mage.Sets/src/mage/cards/a/ArdentPlea.java b/Mage.Sets/src/mage/cards/a/ArdentPlea.java index 1c6fcc667f9..3375ffb2e03 100644 --- a/Mage.Sets/src/mage/cards/a/ArdentPlea.java +++ b/Mage.Sets/src/mage/cards/a/ArdentPlea.java @@ -25,15 +25,14 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.cards.a; import java.util.UUID; -import mage.constants.CardType; import mage.abilities.keyword.CascadeAbility; import mage.abilities.keyword.ExaltedAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.CardType; /** * @@ -41,17 +40,17 @@ import mage.cards.CardSetInfo; */ public class ArdentPlea extends CardImpl { - public ArdentPlea (UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{W}{U}"); - - - + public ArdentPlea(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{W}{U}"); + // Exalted (Whenever a creature you control attacks alone, that creature gets +1/+1 until end of turn.) this.addAbility(new ExaltedAbility()); + + // Cascade (When you cast this spell, exile cards from the top of your library until you exile a nonland card that costs less. You may cast it without paying its mana cost. Put the exiled cards on the bottom in a random order.) this.addAbility(new CascadeAbility()); } - public ArdentPlea (final ArdentPlea card) { + public ArdentPlea(final ArdentPlea card) { super(card); } diff --git a/Mage.Sets/src/mage/cards/b/BattlefieldScrounger.java b/Mage.Sets/src/mage/cards/b/BattlefieldScrounger.java new file mode 100644 index 00000000000..84e823ac53f --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BattlefieldScrounger.java @@ -0,0 +1,124 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.b; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.LimitedTimesPerTurnActivatedAbility; +import mage.abilities.condition.common.CardsInControllerGraveCondition; +import mage.abilities.costs.Cost; +import mage.abilities.costs.CostImpl; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCardInYourGraveyard; + +/** + * + * @author emerald000 + */ +public class BattlefieldScrounger extends CardImpl { + + public BattlefieldScrounger(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{G}"); + + this.subtype.add("Centaur"); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + + // Threshold - Put three cards from your graveyard on the bottom of your library: Battlefield Scrounger gets +3/+3 until end of turn. Activate this ability only once each turn, and only if seven or more cards are in your graveyard. + Ability ability = new LimitedTimesPerTurnActivatedAbility( + Zone.BATTLEFIELD, + new BoostSourceEffect(3, 3, Duration.EndOfTurn), + new BattlefieldScroungerCost(), + 1, + new CardsInControllerGraveCondition(7)); + ability.setAbilityWord(AbilityWord.THRESHOLD); + this.addAbility(ability); + } + + public BattlefieldScrounger(final BattlefieldScrounger card) { + super(card); + } + + @Override + public BattlefieldScrounger copy() { + return new BattlefieldScrounger(this); + } +} + +class BattlefieldScroungerCost extends CostImpl { + + BattlefieldScroungerCost() { + this.addTarget(new TargetCardInYourGraveyard(3, 3, new FilterCard())); + this.text = "Put three cards from your graveyard on the bottom of your library"; + } + + + BattlefieldScroungerCost(final BattlefieldScroungerCost cost) { + super(cost); + } + + @Override + public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) { + Player controller = game.getPlayer(controllerId); + if (controller != null) { + if (targets.choose(Outcome.Removal, controllerId, sourceId, game)) { + for (UUID targetId: targets.get(0).getTargets()) { + Card card = game.getCard(targetId); + if (card == null || !game.getState().getZone(targetId).equals(Zone.GRAVEYARD)) { + return false; + } + paid |= controller.moveCardToLibraryWithInfo(card, sourceId, game, Zone.GRAVEYARD, false, true); + } + } + + } + return paid; + } + + @Override + public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) { + return targets.canChoose(controllerId, game); + } + + @Override + public BattlefieldScroungerCost copy() { + return new BattlefieldScroungerCost(this); + } +} diff --git a/Mage.Sets/src/mage/cards/b/Buoyancy.java b/Mage.Sets/src/mage/cards/b/Buoyancy.java new file mode 100644 index 00000000000..353be6be7c0 --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/Buoyancy.java @@ -0,0 +1,81 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.b; + +import java.util.UUID; + +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.GainAbilityAttachedEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.FlashAbility; +import mage.constants.AttachmentType; +import mage.constants.Zone; +import mage.target.common.TargetCreaturePermanent; +import mage.abilities.Ability; +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; + +/** + * + * @author Galatolol + */ +public class Buoyancy extends CardImpl { + + public Buoyancy(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{U}"); + + this.subtype.add("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 has flying. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAttachedEffect(FlyingAbility.getInstance(), AttachmentType.AURA))); + } + + public Buoyancy(final Buoyancy card) { + super(card); + } + + @Override + public Buoyancy copy() { + return new Buoyancy(this); + } +} diff --git a/Mage.Sets/src/mage/cards/d/DeathRattle.java b/Mage.Sets/src/mage/cards/d/DeathRattle.java index b8f8792fbc1..cceef8b4734 100644 --- a/Mage.Sets/src/mage/cards/d/DeathRattle.java +++ b/Mage.Sets/src/mage/cards/d/DeathRattle.java @@ -45,22 +45,22 @@ import mage.target.common.TargetCreaturePermanent; */ public class DeathRattle extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("nongreen creature"); + static { filter.add(Predicates.not(new ColorPredicate(ObjectColor.GREEN))); } public DeathRattle(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{5}{B}"); - + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{5}{B}"); // Delve this.addAbility(new DelveAbility()); // Destroy target nongreen creature. It can't be regenerated. this.getSpellAbility().addEffect(new DestroyTargetEffect(true)); - this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - + this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter)); + } public DeathRattle(final DeathRattle card) { diff --git a/Mage.Sets/src/mage/cards/d/DeathSpark.java b/Mage.Sets/src/mage/cards/d/DeathSpark.java new file mode 100644 index 00000000000..54801314861 --- /dev/null +++ b/Mage.Sets/src/mage/cards/d/DeathSpark.java @@ -0,0 +1,113 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.d; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.condition.Condition; +import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.effects.common.DoIfCostPaid; +import mage.abilities.effects.common.ReturnSourceFromGraveyardToHandEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.TargetController; +import mage.constants.Zone; +import mage.game.Game; +import mage.players.Player; +import mage.target.common.TargetCreatureOrPlayer; + +/** + * + * @author emerald000 + */ +public class DeathSpark extends CardImpl { + + public DeathSpark(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{R}"); + + + // Death Spark deals 1 damage to target creature or player. + this.getSpellAbility().addEffect(new DamageTargetEffect(1)); + this.getSpellAbility().addTarget(new TargetCreatureOrPlayer()); + + // At the beginning of your upkeep, if Death Spark is in your graveyard with a creature card directly above it, you may pay {1}. If you do, return Death Spark to your hand. + this.addAbility(new ConditionalTriggeredAbility( + new BeginningOfUpkeepTriggeredAbility( + Zone.GRAVEYARD, + new DoIfCostPaid(new ReturnSourceFromGraveyardToHandEffect(), new GenericManaCost(1)), + TargetController.YOU, + false), + new DeathSparkCondition(), + "At the beginning of your upkeep, if {this} is in your graveyard with a creature card directly above it, you may pay {1}. If you do, return {this} to your hand.")); + } + + public DeathSpark(final DeathSpark card) { + super(card); + } + + @Override + public DeathSpark copy() { + return new DeathSpark(this); + } +} + +class DeathSparkCondition implements Condition { + + private static final DeathSparkCondition fInstance = new DeathSparkCondition(); + + public static Condition getInstance() { + return fInstance; + } + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + boolean nextCard = false; + for (Card card : controller.getGraveyard().getCards(game)) { + if (nextCard) { + return card.getCardType().contains(CardType.CREATURE); + } + if (card.getId().equals(source.getSourceId())) { + nextCard = true; + } + } + } + return false; + } + + @Override + public String toString() { + return "{this} is in your graveyard with a creature card directly above it"; + } +} diff --git a/Mage.Sets/src/mage/cards/d/DeclarationInStone.java b/Mage.Sets/src/mage/cards/d/DeclarationInStone.java index 4b1db6cff5a..68012bb703c 100644 --- a/Mage.Sets/src/mage/cards/d/DeclarationInStone.java +++ b/Mage.Sets/src/mage/cards/d/DeclarationInStone.java @@ -27,22 +27,23 @@ */ 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.effects.OneShotEffect; +import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.permanent.TokenPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.game.permanent.PermanentToken; import mage.game.permanent.token.ClueArtifactToken; -import mage.game.permanent.token.Token; import mage.players.Player; import mage.target.common.TargetCreaturePermanent; @@ -53,7 +54,7 @@ import mage.target.common.TargetCreaturePermanent; public class DeclarationInStone extends CardImpl { public DeclarationInStone(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{W}"); // Exile target creature and all other creatures its controller controls with the same name as that creature. // That player investigates for each nontoken creature exiled this way. @@ -73,12 +74,6 @@ public class DeclarationInStone extends CardImpl { class DeclarationInStoneEffect extends OneShotEffect { - private static final FilterCreaturePermanent creaturesOnly = new FilterCreaturePermanent(); - private static final FilterCreaturePermanent nonTokenFilter = new FilterCreaturePermanent("nontoken creature"); - static{ - nonTokenFilter.add(Predicates.not(new TokenPredicate())); - } - public DeclarationInStoneEffect() { super(Outcome.Exile); staticText = "Exile target creature and all other creatures its controller controls with the same name as that creature. That player investigates for each nontoken creature exiled this way."; @@ -90,39 +85,35 @@ class DeclarationInStoneEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - UUID exileId = source.getSourceId(); - Permanent targetPermanent = game.getPermanent(getTargetPointer().getFirst(game, source)); - if (targetPermanent != null) { - UUID controllerPermanentId = targetPermanent.getControllerId(); - Player you = game.getPlayer(source.getControllerId()); - MageObject sourceObject = game.getObject(source.getSourceId()); - if (sourceObject != null && exileId != null && you != null) { - - int exiledCount = 0; + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = game.getObject(source.getSourceId()); + if (sourceObject != null && controller != null) { + Permanent targetPermanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (targetPermanent != null) { + Set cardsToExile = new HashSet<>(); + int nonTokenCount = 0; if (targetPermanent.getName().isEmpty()) { // face down creature - you.moveCardToExileWithInfo(targetPermanent, exileId, sourceObject.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true); - exiledCount = 1; // will always be 1 with a face down creature (has no name) + cardsToExile.add(targetPermanent); + if (!(targetPermanent instanceof PermanentToken)) { + nonTokenCount++; + } } else { - String name = targetPermanent.getName(); - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(controllerPermanentId)) { - if (permanent != null && permanent.getName().equals(name)) { - - // only exile creatures (reported bug on awakened lands targetted exiling all other lands of same name) - if (creaturesOnly.match(permanent, game)) { - you.moveCardToExileWithInfo(permanent, null, "", source.getSourceId(), game, Zone.BATTLEFIELD, true); - } - + cardsToExile.add(targetPermanent); + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), targetPermanent.getControllerId(), game)) { + if (!permanent.getId().equals(targetPermanent.getId()) + && permanent.getName().equals(targetPermanent.getName())) { + cardsToExile.add(permanent); // exiled count only matters for non-tokens - if (nonTokenFilter.match(permanent, game)) { - exiledCount++; + if (!(permanent instanceof PermanentToken)) { + nonTokenCount++; } } } } - - if (exiledCount > 0) { - Token token = new ClueArtifactToken(); - token.putOntoBattlefield(exiledCount, game, source.getSourceId(), controllerPermanentId, false, false); + controller.moveCards(cardsToExile, Zone.EXILED, source, game); + game.applyEffects(); + if (nonTokenCount > 0) { + new ClueArtifactToken().putOntoBattlefield(nonTokenCount, game, source.getSourceId(), targetPermanent.getControllerId(), false, false); } return true; } @@ -135,4 +126,4 @@ class DeclarationInStoneEffect extends OneShotEffect { public DeclarationInStoneEffect copy() { return new DeclarationInStoneEffect(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/d/DromokasCommand.java b/Mage.Sets/src/mage/cards/d/DromokasCommand.java index 8666a76e0f8..51bb89c387e 100644 --- a/Mage.Sets/src/mage/cards/d/DromokasCommand.java +++ b/Mage.Sets/src/mage/cards/d/DromokasCommand.java @@ -64,9 +64,9 @@ public class DromokasCommand extends CardImpl { } public DromokasCommand(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{G}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{G}{W}"); - // Choose two - Prevent all damage target instant or sorcery spell would deal this turn; Target player sacrifices an enchantment; Put a +1/+1 counter on target creature; or Target creature you control fights target creature you don't control. + // Choose two - this.getSpellAbility().getModes().setMinModes(2); this.getSpellAbility().getModes().setMaxModes(2); diff --git a/Mage.Sets/src/mage/cards/e/Earthcraft.java b/Mage.Sets/src/mage/cards/e/Earthcraft.java index 8f03f423065..b9bcce6efeb 100644 --- a/Mage.Sets/src/mage/cards/e/Earthcraft.java +++ b/Mage.Sets/src/mage/cards/e/Earthcraft.java @@ -28,14 +28,13 @@ package mage.cards.e; import java.util.UUID; - -import mage.constants.CardType; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapTargetCost; import mage.abilities.effects.common.UntapTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.CardType; import mage.constants.Zone; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.common.FilterControlledPermanent; @@ -43,8 +42,8 @@ import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.filter.predicate.mageobject.SupertypePredicate; import mage.filter.predicate.permanent.TappedPredicate; +import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; -import mage.target.common.TargetControlledPermanent; /** * @author Loki @@ -61,12 +60,11 @@ public class Earthcraft extends CardImpl { } public Earthcraft(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{G}"); - + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{G}"); // Tap an untapped creature you control: Untap target basic land. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new UntapTargetEffect(), new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filterCreature, true))); - ability.addTarget(new TargetControlledPermanent(filterLand)); + ability.addTarget(new TargetPermanent(filterLand)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/f/FlameheartWerewolf.java b/Mage.Sets/src/mage/cards/f/FlameheartWerewolf.java index bb3430b6b7c..a7fa3dd5d68 100644 --- a/Mage.Sets/src/mage/cards/f/FlameheartWerewolf.java +++ b/Mage.Sets/src/mage/cards/f/FlameheartWerewolf.java @@ -41,6 +41,7 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.TargetController; +import mage.filter.StaticFilters; /** * @@ -60,7 +61,8 @@ public class FlameheartWerewolf extends CardImpl { this.transformable = true; // Whenever Flameheart Werewolf blocks or becomes blocked by a creature, Flameheart Werewolf deals 2 damage to that creature. - this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(new DamageTargetEffect(2, true, "that creature"), false)); + this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(new DamageTargetEffect(2, true, "that creature"), + StaticFilters.FILTER_PERMANENT_CREATURE, false, null, true)); // At the beginning of each upkeep, if a player cast two or more spells last turn, transform Flameheart Werewolf. TriggeredAbility ability = new BeginningOfUpkeepTriggeredAbility(new TransformSourceEffect(false), TargetController.ANY, false); diff --git a/Mage.Sets/src/mage/cards/f/FledglingOsprey.java b/Mage.Sets/src/mage/cards/f/FledglingOsprey.java new file mode 100644 index 00000000000..603743b6b5c --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FledglingOsprey.java @@ -0,0 +1,71 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.f; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.condition.common.EnchantedSourceCondition; +import mage.abilities.decorator.ConditionalContinuousEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; + +/** + * + * @author Galatolol + */ +public class FledglingOsprey extends CardImpl { + + public FledglingOsprey(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{U}"); + + this.subtype.add("Bird"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Fledgling Osprey has flying as long as it's enchanted. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ConditionalContinuousEffect( + new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.WhileOnBattlefield), + new EnchantedSourceCondition(), + "{this} has flying as long as it's enchanted"))); + } + + public FledglingOsprey(final FledglingOsprey card) { + super(card); + } + + @Override + public FledglingOsprey copy() { + return new FledglingOsprey(this); + } +} diff --git a/Mage.Sets/src/mage/cards/f/FlowstoneThopter.java b/Mage.Sets/src/mage/cards/f/FlowstoneThopter.java new file mode 100644 index 00000000000..187ff53ce8a --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FlowstoneThopter.java @@ -0,0 +1,76 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.f; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.Ability; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; + +/** + * + * @author Galatolol + */ +public class FlowstoneThopter extends CardImpl { + + public FlowstoneThopter(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{7}"); + + this.subtype.add("Thopter"); + this.power = new MageInt(4); + this.toughness = new MageInt(4); + + // {1}: Flowstone Thopter gets +1/-1 and gains flying until end of turn. + Effect effect = new BoostSourceEffect(1, -1, Duration.EndOfTurn); + effect.setText("{this} gets +1/-1"); + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, effect, new ManaCostsImpl("{1}")); + effect = new GainAbilitySourceEffect(FlyingAbility.getInstance(), Duration.EndOfTurn); + effect.setText("and gains flying until end of turn."); + ability.addEffect(effect); + this.addAbility(ability); + } + + public FlowstoneThopter(final FlowstoneThopter card) { + super(card); + } + + @Override + public FlowstoneThopter copy() { + return new FlowstoneThopter(this); + } +} diff --git a/Mage.Sets/src/mage/cards/f/FuriousAssault.java b/Mage.Sets/src/mage/cards/f/FuriousAssault.java new file mode 100644 index 00000000000..8570921ed40 --- /dev/null +++ b/Mage.Sets/src/mage/cards/f/FuriousAssault.java @@ -0,0 +1,64 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.f; + +import java.util.UUID; + +import mage.abilities.Ability; +import mage.abilities.common.SpellCastControllerTriggeredAbility; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.filter.StaticFilters; +import mage.target.TargetPlayer; + +/** + * + * @author Galatolol + */ +public class FuriousAssault extends CardImpl { + + public FuriousAssault(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}"); + + // Whenever you cast a creature spell, Furious Assault deals 1 damage to target player. + Ability ability = new SpellCastControllerTriggeredAbility(new DamageTargetEffect(1), StaticFilters.FILTER_SPELL_A_CREATURE, false); + ability.addTarget(new TargetPlayer()); + this.addAbility(ability); + } + + public FuriousAssault(final FuriousAssault card) { + super(card); + } + + @Override + public FuriousAssault copy() { + return new FuriousAssault(this); + } +} diff --git a/Mage.Sets/src/mage/cards/h/Hivestone.java b/Mage.Sets/src/mage/cards/h/Hivestone.java index 2f5d24e4a4b..6331f80a7c9 100644 --- a/Mage.Sets/src/mage/cards/h/Hivestone.java +++ b/Mage.Sets/src/mage/cards/h/Hivestone.java @@ -28,7 +28,7 @@ public class Hivestone extends CardImpl { // Creatures you control are Slivers in addition to their other creature types. ArrayList subTypes = new ArrayList<>(); - subTypes.add("Slivers"); + subTypes.add("Sliver"); Effect effect = new BecomesSubtypeAllEffect(Duration.WhileOnBattlefield, subTypes, filter, false); effect.setText("Creatures you control are Slivers in addition to their other creature types"); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, effect)); diff --git a/Mage.Sets/src/mage/cards/k/KessigForgemaster.java b/Mage.Sets/src/mage/cards/k/KessigForgemaster.java index 74079a54881..57e4d743c53 100644 --- a/Mage.Sets/src/mage/cards/k/KessigForgemaster.java +++ b/Mage.Sets/src/mage/cards/k/KessigForgemaster.java @@ -37,11 +37,12 @@ import mage.abilities.decorator.ConditionalTriggeredAbility; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.TransformSourceEffect; import mage.abilities.keyword.TransformAbility; -import mage.cards.f.FlameheartWerewolf; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.cards.f.FlameheartWerewolf; import mage.constants.CardType; import mage.constants.TargetController; +import mage.filter.StaticFilters; /** * @@ -61,7 +62,8 @@ public class KessigForgemaster extends CardImpl { this.secondSideCardClazz = FlameheartWerewolf.class; // Whenever Kessig Forgemaster blocks or becomes blocked by a creature, Kessig Forgemaster deals 1 damage to that creature. - this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(new DamageTargetEffect(1, true, "that creature"), false)); + this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(new DamageTargetEffect(1, true, "that creature"), + StaticFilters.FILTER_PERMANENT_CREATURE, false, null, true)); // At the beginning of each upkeep, if no spells were cast last turn, transform Kessig Forgemaster. this.addAbility(new TransformAbility()); diff --git a/Mage.Sets/src/mage/cards/m/MuscleSliver.java b/Mage.Sets/src/mage/cards/m/MuscleSliver.java index c639ae6ebc4..01b4f1b3c15 100644 --- a/Mage.Sets/src/mage/cards/m/MuscleSliver.java +++ b/Mage.Sets/src/mage/cards/m/MuscleSliver.java @@ -28,13 +28,12 @@ package mage.cards.m; import java.util.UUID; - -import mage.constants.CardType; import mage.MageInt; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.continuous.BoostAllEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; @@ -52,11 +51,13 @@ public class MuscleSliver extends CardImpl { } public MuscleSliver(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}"); this.subtype.add("Sliver"); this.power = new MageInt(1); this.toughness = new MageInt(1); + + // All Sliver creatures get +1/+1. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllEffect(1, 1, Duration.WhileOnBattlefield, filter, false))); } diff --git a/Mage.Sets/src/mage/cards/n/NarnamRenegade.java b/Mage.Sets/src/mage/cards/n/NarnamRenegade.java index 208546fdc86..abd46a837f0 100644 --- a/Mage.Sets/src/mage/cards/n/NarnamRenegade.java +++ b/Mage.Sets/src/mage/cards/n/NarnamRenegade.java @@ -60,8 +60,7 @@ public class NarnamRenegade extends CardImpl { this.addAbility( new EntersBattlefieldAbility( new AddCountersSourceEffect(CounterType.P1P1.createInstance()), - false, - RevoltCondition.getInstance(), + false, RevoltCondition.getInstance(), "Revolt — {this} enters the battlefield with a +1/+1 counter on it if a permanent you controlled left the battlefield this turn", null), new RevoltWatcher() ); diff --git a/Mage.Sets/src/mage/cards/n/NobleStand.java b/Mage.Sets/src/mage/cards/n/NobleStand.java new file mode 100644 index 00000000000..f5b5bcf5608 --- /dev/null +++ b/Mage.Sets/src/mage/cards/n/NobleStand.java @@ -0,0 +1,100 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.n; + +import java.util.UUID; + +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.common.GainLifeEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.TokenPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.permanent.Permanent; + +/** + * + * @author Galatolol + */ +public class NobleStand extends CardImpl { + + public NobleStand(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{W}"); + + // Whenever a creature you control blocks, you gain 2 life. + this.addAbility(new NobleStandAbility()); + } + + public NobleStand(final NobleStand card) { + super(card); + } + + @Override + public NobleStand copy() { + return new NobleStand(this); + } +} + +class NobleStandAbility extends TriggeredAbilityImpl { + + public NobleStandAbility() { + super(Zone.BATTLEFIELD, new GainLifeEffect(2)); + } + + public NobleStandAbility(final mage.cards.n.NobleStandAbility ability) { + super(ability); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.BLOCKER_DECLARED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(); + filter.add(Predicates.not(new TokenPredicate())); + Permanent permanent = (Permanent) game.getPermanent(event.getSourceId()); + return permanent != null && filter.match(permanent, sourceId, controllerId, game); + } + + @Override + public String getRule() { + return "Whenever a creature you control blocks, you gain 2 life."; + } + + @Override + public mage.cards.n.NobleStandAbility copy() { + return new mage.cards.n.NobleStandAbility(this); + } +} diff --git a/Mage.Sets/src/mage/cards/o/Overabundance.java b/Mage.Sets/src/mage/cards/o/Overabundance.java new file mode 100644 index 00000000000..724f8b08f6c --- /dev/null +++ b/Mage.Sets/src/mage/cards/o/Overabundance.java @@ -0,0 +1,74 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.o; + +import java.util.UUID; + +import mage.abilities.common.TapForManaAllTriggeredAbility; +import mage.abilities.common.TapForManaAllTriggeredManaAbility; +import mage.abilities.effects.common.AddManaOfAnyTypeProducedEffect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.SetTargetPointer; +import mage.filter.common.FilterLandPermanent; + +/** + * + * @author elliott-king + */ +public class Overabundance extends CardImpl { + + public Overabundance(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}{G}"); + + + // Whenever a player taps a land for mana, that player adds one mana to his or her mana pool of any type that land produced, and Overabundance deals 1 damage to him or her. + this.addAbility(new TapForManaAllTriggeredManaAbility( + new AddManaOfAnyTypeProducedEffect(), + new FilterLandPermanent( "a player taps a land"), + SetTargetPointer.PERMANENT + )); + + this.addAbility(new TapForManaAllTriggeredAbility( + new DamageTargetEffect(1, true, "that player"), + new FilterLandPermanent("a player taps a land"), + SetTargetPointer.PLAYER + )); + } + + public Overabundance(final Overabundance card) { + super(card); + } + + @Override + public Overabundance copy() { + return new Overabundance(this); + } +} diff --git a/Mage.Sets/src/mage/cards/o/OverwhelmingStampede.java b/Mage.Sets/src/mage/cards/o/OverwhelmingStampede.java index b2731d2185a..3a1be74dd68 100644 --- a/Mage.Sets/src/mage/cards/o/OverwhelmingStampede.java +++ b/Mage.Sets/src/mage/cards/o/OverwhelmingStampede.java @@ -1,16 +1,16 @@ /* * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR @@ -20,12 +20,11 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + * * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.cards.o; import java.util.UUID; @@ -51,8 +50,8 @@ import mage.game.permanent.Permanent; public class OverwhelmingStampede extends CardImpl { public OverwhelmingStampede(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{G}{G}"); - + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{G}{G}"); + // Until end of turn, creatures you control gain trample and get +X/+X, where X is the greatest power among creatures you control. this.getSpellAbility().addEffect(new OverwhelmingStampedeInitEffect()); } @@ -68,30 +67,30 @@ public class OverwhelmingStampede extends CardImpl { } class OverwhelmingStampedeInitEffect extends OneShotEffect { - + public OverwhelmingStampedeInitEffect() { super(Outcome.BoostCreature); this.staticText = "Until end of turn, creatures you control gain trample and get +X/+X, where X is the greatest power among creatures you control"; } - + public OverwhelmingStampedeInitEffect(final OverwhelmingStampedeInitEffect effect) { super(effect); } - + @Override public OverwhelmingStampedeInitEffect copy() { return new OverwhelmingStampedeInitEffect(this); } - + @Override public boolean apply(Game game, Ability source) { int maxPower = 0; - for (Permanent perm: game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), game)) { + for (Permanent perm : game.getBattlefield().getAllActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), game)) { if (perm.getPower().getValue() > maxPower) { maxPower = perm.getPower().getValue(); } } - ContinuousEffect effect = new GainAbilityControlledEffect(TrampleAbility.getInstance(), Duration.EndOfStep, new FilterCreaturePermanent()); + ContinuousEffect effect = new GainAbilityControlledEffect(TrampleAbility.getInstance(), Duration.EndOfTurn, new FilterCreaturePermanent()); game.addEffect(effect, source); if (maxPower != 0) { effect = new BoostControlledEffect(maxPower, maxPower, Duration.EndOfTurn); diff --git a/Mage.Sets/src/mage/cards/r/RasputinDreamweaver.java b/Mage.Sets/src/mage/cards/r/RasputinDreamweaver.java new file mode 100644 index 00000000000..79bb93d47d3 --- /dev/null +++ b/Mage.Sets/src/mage/cards/r/RasputinDreamweaver.java @@ -0,0 +1,170 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.r; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import mage.MageInt; +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.common.CantHaveMoreThanAmountCountersSourceAbility; +import mage.abilities.common.EntersBattlefieldAbility; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.Condition; +import mage.abilities.costs.common.RemoveCountersSourceCost; +import mage.abilities.decorator.ConditionalTriggeredAbility; +import mage.abilities.effects.common.PreventDamageToSourceEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.mana.SimpleManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.TargetController; +import mage.constants.WatcherScope; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.filter.FilterPermanent; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.permanent.TappedPredicate; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.watchers.Watcher; + +/** + * + * @author emerald000 + */ +public class RasputinDreamweaver extends CardImpl { + + public RasputinDreamweaver(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}{U}"); + + this.supertype.add("Legendary"); + this.subtype.add("Human"); + this.subtype.add("Wizard"); + this.power = new MageInt(4); + this.toughness = new MageInt(1); + + // Rasputin Dreamweaver enters the battlefield with seven dream counters on it. + this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect(CounterType.DREAM.createInstance(7)), "seven dream counters on it")); + + // Remove a dream counter from Rasputin: Add {C} to your mana pool. + this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, Mana.ColorlessMana(1), new RemoveCountersSourceCost(CounterType.DREAM.createInstance()))); + + // Remove a dream counter from Rasputin: Prevent the next 1 damage that would be dealt to Rasputin this turn. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new PreventDamageToSourceEffect(Duration.EndOfTurn, 1), new RemoveCountersSourceCost(CounterType.DREAM.createInstance()))); + + // At the beginning of your upkeep, if Rasputin started the turn untapped, put a dream counter on it. + this.addAbility( + new ConditionalTriggeredAbility( + new BeginningOfUpkeepTriggeredAbility(new AddCountersSourceEffect(CounterType.DREAM.createInstance()), TargetController.YOU, false), + new RasputinDreamweaverStartedUntappedCondition(), + "At the beginning of your upkeep, if {this} started the turn untapped, put a dream counter on it."), + new RasputinDreamweaverStartedUntappedWatcher()); + + // Rasputin can't have more than seven dream counters on it. + this.addAbility(new CantHaveMoreThanAmountCountersSourceAbility(CounterType.DREAM, 7)); + } + + public RasputinDreamweaver(final RasputinDreamweaver card) { + super(card); + } + + @Override + public RasputinDreamweaver copy() { + return new RasputinDreamweaver(this); + } +} + +class RasputinDreamweaverStartedUntappedCondition implements Condition { + + private static final RasputinDreamweaverStartedUntappedCondition fInstance = new RasputinDreamweaverStartedUntappedCondition(); + + public static Condition getInstance() { + return fInstance; + } + + @Override + public boolean apply(Game game, Ability source) { + RasputinDreamweaverStartedUntappedWatcher watcher = (RasputinDreamweaverStartedUntappedWatcher) game.getState().getWatchers().get(RasputinDreamweaverStartedUntappedWatcher.class.getName()); + if (watcher != null) { + return watcher.startedUntapped(source.getSourceId()); + } + return false; + } + + @Override + public String toString() { + return "{this} started the turn untapped"; + } +} + +class RasputinDreamweaverStartedUntappedWatcher extends Watcher { + + private static final FilterPermanent filter = new FilterPermanent("Untapped permanents"); + static { + filter.add(Predicates.not(new TappedPredicate())); + } + + private final Set startedUntapped = new HashSet<>(0); + + RasputinDreamweaverStartedUntappedWatcher() { + super(RasputinDreamweaverStartedUntappedWatcher.class.getName(), WatcherScope.GAME); + } + + RasputinDreamweaverStartedUntappedWatcher(final RasputinDreamweaverStartedUntappedWatcher watcher) { + super(watcher); + this.startedUntapped.addAll(watcher.startedUntapped); + } + + @Override + public RasputinDreamweaverStartedUntappedWatcher copy() { + return new RasputinDreamweaverStartedUntappedWatcher(this); + } + + @Override + public void watch(GameEvent event, Game game) { + if (event.getType() == EventType.BEGINNING_PHASE_PRE) { + game.getBattlefield().getAllActivePermanents(filter, game).stream().forEach(permanent -> startedUntapped.add(permanent.getId())); + } + } + + @Override + public void reset() { + this.startedUntapped.clear(); + super.reset(); + } + + public boolean startedUntapped(UUID cardId) { + return this.startedUntapped.contains(cardId); + } +} diff --git a/Mage.Sets/src/mage/cards/r/ReyhanLastOfTheAbzan.java b/Mage.Sets/src/mage/cards/r/ReyhanLastOfTheAbzan.java index 251075252ea..8e8dd03aad5 100644 --- a/Mage.Sets/src/mage/cards/r/ReyhanLastOfTheAbzan.java +++ b/Mage.Sets/src/mage/cards/r/ReyhanLastOfTheAbzan.java @@ -112,6 +112,7 @@ class ReyhanLastOfTheAbzanTriggeredAbility extends TriggeredAbilityImpl { if (permanent.getControllerId().equals(this.getControllerId()) && permanent.getCardType().contains(CardType.CREATURE)) { int countersOn = permanent.getCounters(game).getCount(CounterType.P1P1); if (countersOn > 0) { + this.getEffects().clear(); this.addEffect(new AddCountersTargetEffect(CounterType.P1P1.createInstance(countersOn))); } return true; diff --git a/Mage.Sets/src/mage/cards/s/ScrapheapScrounger.java b/Mage.Sets/src/mage/cards/s/ScrapheapScrounger.java index 2702edeb1e0..c61a13a86cd 100644 --- a/Mage.Sets/src/mage/cards/s/ScrapheapScrounger.java +++ b/Mage.Sets/src/mage/cards/s/ScrapheapScrounger.java @@ -51,12 +51,13 @@ import mage.target.common.TargetCardInYourGraveyard; public class ScrapheapScrounger extends CardImpl { private static final FilterCard filter = new FilterCreatureCard("another creature card"); + static { filter.add(new AnotherCardPredicate()); } public ScrapheapScrounger(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{2}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{2}"); this.subtype.add("Construct"); this.power = new MageInt(3); this.toughness = new MageInt(2); diff --git a/Mage.Sets/src/mage/cards/s/SilvergillDouser.java b/Mage.Sets/src/mage/cards/s/SilvergillDouser.java index e6667c0221d..de05bc73dd7 100644 --- a/Mage.Sets/src/mage/cards/s/SilvergillDouser.java +++ b/Mage.Sets/src/mage/cards/s/SilvergillDouser.java @@ -41,7 +41,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Zone; -import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.SubtypePredicate; import mage.target.common.TargetCreaturePermanent; @@ -52,7 +52,7 @@ import mage.target.common.TargetCreaturePermanent; */ public class SilvergillDouser extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("Merfolk and/or Faeries you control"); + private static final FilterControlledPermanent filter = new FilterControlledPermanent("Merfolk and/or Faeries you control"); static { filter.add(Predicates.or(new SubtypePredicate("Merfolk"), new SubtypePredicate("Faerie"))); @@ -66,7 +66,7 @@ public class SilvergillDouser extends CardImpl { this.toughness = new MageInt(1); // {tap}: Target creature gets -X/-0 until end of turn, where X is the number of Merfolk and/or Faeries you control. - DynamicValue number = new PermanentsOnBattlefieldCount(new FilterControlledCreaturePermanent(filter), -1); + DynamicValue number = new PermanentsOnBattlefieldCount(new FilterControlledPermanent(filter), -1); Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(number, new StaticValue(0), Duration.EndOfTurn, true), new TapSourceCost()); ability.addTarget(new TargetCreaturePermanent()); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/s/StrongholdMachinist.java b/Mage.Sets/src/mage/cards/s/StrongholdMachinist.java new file mode 100644 index 00000000000..4f8b1d58d2d --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/StrongholdMachinist.java @@ -0,0 +1,83 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +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.DiscardCardCost; +import mage.abilities.costs.common.TapSourceCost; +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.Zone; +import mage.filter.FilterSpell; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardTypePredicate; +import mage.target.TargetSpell; + +/** + * + * @author anonymous + */ +public class StrongholdMachinist extends CardImpl { + + private static final FilterSpell filter = new FilterSpell("noncreature spell"); + + static { + filter.add(Predicates.not(new CardTypePredicate(CardType.CREATURE))); + } + + public StrongholdMachinist(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}"); + + this.subtype.add("Human"); + this.subtype.add("Spellshaper"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // {U}{U}, {tap}, Discard a card: Counter target noncreature spell. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CounterTargetEffect(), new ManaCostsImpl("{U}{U}")); + ability.addCost(new TapSourceCost()); + ability.addCost(new DiscardCardCost()); + ability.addTarget(new TargetSpell(filter)); + this.addAbility(ability); + } + + public StrongholdMachinist(final StrongholdMachinist card) { + super(card); + } + + @Override + public StrongholdMachinist copy() { + return new StrongholdMachinist(this); + } +} diff --git a/Mage.Sets/src/mage/cards/t/TezzeretTheSchemer.java b/Mage.Sets/src/mage/cards/t/TezzeretTheSchemer.java index c25baaa0997..178e9604158 100644 --- a/Mage.Sets/src/mage/cards/t/TezzeretTheSchemer.java +++ b/Mage.Sets/src/mage/cards/t/TezzeretTheSchemer.java @@ -74,7 +74,7 @@ public class TezzeretTheSchemer extends CardImpl { // -2: Target creature gets +X/-X until end of turn, where X is the number of artifacts you control. DynamicValue count = new PermanentsOnBattlefieldCount(new FilterControlledArtifactPermanent("artifacts you control")); - Effect effect = new BoostTargetEffect(count, new SignInversionDynamicValue(count), Duration.EndOfTurn); + Effect effect = new BoostTargetEffect(count, new SignInversionDynamicValue(count), Duration.EndOfTurn, true); effect.setText("Target creature gets +X/-X until end of turn, where X is the number of artifacts you control"); Ability ability = new LoyaltyAbility(effect, -2); ability.addTarget(new TargetCreaturePermanent()); diff --git a/Mage.Sets/src/mage/cards/t/TrueConviction.java b/Mage.Sets/src/mage/cards/t/TrueConviction.java index e73a96b93ae..9e3e4051f46 100644 --- a/Mage.Sets/src/mage/cards/t/TrueConviction.java +++ b/Mage.Sets/src/mage/cards/t/TrueConviction.java @@ -25,19 +25,19 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.cards.t; import java.util.UUID; - -import mage.constants.CardType; -import mage.constants.Duration; +import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; import mage.abilities.keyword.DoubleStrikeAbility; import mage.abilities.keyword.LifelinkAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; @@ -47,14 +47,18 @@ import mage.filter.common.FilterCreaturePermanent; */ public class TrueConviction extends CardImpl { - public TrueConviction (UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{W}{W}{W}"); + public TrueConviction(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}{W}{W}"); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledEffect(DoubleStrikeAbility.getInstance(), Duration.WhileOnBattlefield, new FilterCreaturePermanent()))); - this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledEffect(LifelinkAbility.getInstance(), Duration.WhileOnBattlefield, new FilterCreaturePermanent()))); + // Creatures you control have double strike and lifelink. + Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityControlledEffect(DoubleStrikeAbility.getInstance(), Duration.WhileOnBattlefield, new FilterCreaturePermanent())); + Effect effect = new GainAbilityControlledEffect(LifelinkAbility.getInstance(), Duration.WhileOnBattlefield, new FilterCreaturePermanent()); + effect.setText(" and lifelink"); + ability.addEffect(effect); + this.addAbility(ability); } - public TrueConviction (final TrueConviction card) { + public TrueConviction(final TrueConviction card) { super(card); } diff --git a/Mage.Sets/src/mage/cards/t/TymnaTheWeaver.java b/Mage.Sets/src/mage/cards/t/TymnaTheWeaver.java index 10ad250cc4a..5c135c95755 100644 --- a/Mage.Sets/src/mage/cards/t/TymnaTheWeaver.java +++ b/Mage.Sets/src/mage/cards/t/TymnaTheWeaver.java @@ -27,6 +27,7 @@ */ package mage.cards.t; +import java.util.HashMap; import java.util.HashSet; import java.util.Set; import java.util.UUID; @@ -123,7 +124,8 @@ class TymnaTheWeaverEffect extends OneShotEffect { class TymnaTheWeaverWatcher extends Watcher { - private final Set players = new HashSet<>(); + // private final Set players = new HashSet<>(); + private final HashMap> players = new HashMap<>(); public TymnaTheWeaverWatcher() { super(TymnaTheWeaverWatcher.class.getName(), WatcherScope.GAME); @@ -131,7 +133,11 @@ class TymnaTheWeaverWatcher extends Watcher { public TymnaTheWeaverWatcher(final TymnaTheWeaverWatcher watcher) { super(watcher); - players.addAll(watcher.players); + for (UUID playerId : watcher.players.keySet()) { + HashSet opponents = new HashSet<>(); + opponents.addAll(watcher.players.get(playerId)); + players.put(playerId, opponents); + } } @Override @@ -144,7 +150,11 @@ class TymnaTheWeaverWatcher extends Watcher { if (event.getType() == EventType.DAMAGED_PLAYER) { DamagedPlayerEvent dEvent = (DamagedPlayerEvent) event; if (dEvent.isCombatDamage()) { - players.add(event.getTargetId()); + if (players.containsKey(event.getTargetId())) { // opponenets can die before number of opponents are checked + players.get(event.getTargetId()).addAll(game.getOpponents(event.getTargetId())); + } else { + players.put(event.getTargetId(), game.getOpponents(event.getTargetId())); + } } } } @@ -157,8 +167,8 @@ class TymnaTheWeaverWatcher extends Watcher { public int opponentsThatGotCombatDamage(UUID playerId, Game game) { int numberOfOpponents = 0; - for (UUID opponentId : game.getOpponents(playerId)) { - if (players.contains(opponentId)) { + for (Set opponents : players.values()) { + if (opponents.contains(playerId)) { numberOfOpponents++; } } diff --git a/Mage.Sets/src/mage/cards/v/VenomspoutBrackus.java b/Mage.Sets/src/mage/cards/v/VenomspoutBrackus.java new file mode 100644 index 00000000000..e7b8ae37c38 --- /dev/null +++ b/Mage.Sets/src/mage/cards/v/VenomspoutBrackus.java @@ -0,0 +1,85 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.cards.v; + +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.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.abilities.keyword.FlyingAbility; +import mage.abilities.keyword.MorphAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.filter.common.FilterAttackingOrBlockingCreature; +import mage.filter.predicate.mageobject.AbilityPredicate; +import mage.target.common.TargetCreaturePermanent; + +/** + * + * @author Galatolol + */ +public class VenomspoutBrackus extends CardImpl { + + private static final FilterAttackingOrBlockingCreature filter = new FilterAttackingOrBlockingCreature( + "attacking or blocking creature with flying"); + + static { + filter.add(new AbilityPredicate(FlyingAbility.class)); + } + + public VenomspoutBrackus(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{6}{G}"); + + this.subtype.add("Beast"); + this.power = new MageInt(5); + this.toughness = new MageInt(5); + + // {1}{G}, {tap}: Venomspout Brackus deals 5 damage to target attacking or blocking creature with flying. + Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), new ManaCostsImpl("{1}{G}")); + ability.addCost(new TapSourceCost()); + ability.addTarget(new TargetCreaturePermanent(filter)); + this.addAbility(ability); + // Morph {3}{G}{G} + this.addAbility(new MorphAbility(this, new ManaCostsImpl("{3}{G}{G}"))); + + } + + public VenomspoutBrackus(final VenomspoutBrackus card) { + super(card); + } + + @Override + public VenomspoutBrackus copy() { + return new VenomspoutBrackus(this); + } +} diff --git a/Mage.Sets/src/mage/sets/Alliances.java b/Mage.Sets/src/mage/sets/Alliances.java index 40631471842..ddd07b8b64c 100644 --- a/Mage.Sets/src/mage/sets/Alliances.java +++ b/Mage.Sets/src/mage/sets/Alliances.java @@ -1,156 +1,157 @@ -package mage.sets; - -import mage.cards.ExpansionSet; -import mage.cards.a.AesthirGlider; -import mage.cards.a.AgentOfStromgald; -import mage.cards.b.BalduvianWarMakers; -import mage.cards.c.CarrierPigeons; -import mage.cards.e.EnslavedScout; -import mage.cards.f.FeveredStrength; -import mage.cards.g.GorillaBerserkers; -import mage.cards.g.GorillaShaman; -import mage.cards.i.InsidiousBookworms; -import mage.cards.l.LimDulsHighGuard; -import mage.cards.p.PhyrexianWarBeast; -import mage.cards.r.RoyalHerbalist; -import mage.cards.s.SoldeviAdnate; -import mage.cards.s.SoldeviSage; -import mage.cards.s.StormShaman; -import mage.cards.s.SwampMosquito; -import mage.cards.w.WhipVine; -import mage.constants.SetType; - -import mage.constants.Rarity; -import mage.cards.CardGraphicInfo; - -public class Alliances extends ExpansionSet { - private static final Alliances fINSTANCE = new Alliances(); - - public static Alliances getInstance() { - return fINSTANCE; - } - - private Alliances() { - super("Alliances", "ALL", ExpansionSet.buildDate(1996, 6, 10), SetType.EXPANSION); - this.blockName = "Ice Age"; - this.parentSet = IceAge.getInstance(); - this.hasBasicLands = false; - this.hasBoosters = true; - this.numBoosterLands = 0; - this.numBoosterCommon = 8; - this.numBoosterUncommon = 3; - this.numBoosterRare = 1; - this.ratioBoosterMythic = 0; - cards.add(new SetCardInfo("Aesthir Glider", 156, Rarity.COMMON, AesthirGlider.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Aesthir Glider", 157, Rarity.COMMON, AesthirGlider.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Agent of Stromgald", 94, Rarity.COMMON, AgentOfStromgald.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Agent of Stromgald", 95, Rarity.COMMON, AgentOfStromgald.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Arcane Denial", 32, Rarity.COMMON, mage.cards.a.ArcaneDenial.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Arcane Denial", 33, Rarity.COMMON, mage.cards.a.ArcaneDenial.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Astrolabe", 159, Rarity.COMMON, mage.cards.a.Astrolabe.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Astrolabe", 160, Rarity.COMMON, mage.cards.a.Astrolabe.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Balduvian Dead", 1, Rarity.UNCOMMON, mage.cards.b.BalduvianDead.class)); - cards.add(new SetCardInfo("Balduvian Horde", 96, Rarity.RARE, mage.cards.b.BalduvianHorde.class)); - cards.add(new SetCardInfo("Balduvian Trading Post", 182, Rarity.RARE, mage.cards.b.BalduvianTradingPost.class)); - cards.add(new SetCardInfo("Balduvian War-Makers", 97, Rarity.COMMON, BalduvianWarMakers.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Balduvian War-Makers", 98, Rarity.COMMON, BalduvianWarMakers.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Bounty of the Hunt", 63, Rarity.UNCOMMON, mage.cards.b.BountyOfTheHunt.class)); - cards.add(new SetCardInfo("Browse", 38, Rarity.UNCOMMON, mage.cards.b.Browse.class)); - cards.add(new SetCardInfo("Burnout", 101, Rarity.UNCOMMON, mage.cards.b.Burnout.class)); - cards.add(new SetCardInfo("Carrier Pigeons", 125, Rarity.COMMON, CarrierPigeons.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Carrier Pigeons", 126, Rarity.COMMON, CarrierPigeons.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Contagion", 4, Rarity.UNCOMMON, mage.cards.c.Contagion.class)); - cards.add(new SetCardInfo("Deadly Insect", 64, Rarity.COMMON, mage.cards.d.DeadlyInsect.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Deadly Insect", 65, Rarity.COMMON, mage.cards.d.DeadlyInsect.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Diminishing Returns", 39, Rarity.RARE, mage.cards.d.DiminishingReturns.class)); - cards.add(new SetCardInfo("Dystopia", 6, Rarity.RARE, mage.cards.d.Dystopia.class)); - cards.add(new SetCardInfo("Elvish Bard", 66, Rarity.UNCOMMON, mage.cards.e.ElvishBard.class)); - cards.add(new SetCardInfo("Elvish Ranger", 67, Rarity.COMMON, mage.cards.e.ElvishRanger.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Elvish Ranger", 68, Rarity.COMMON, mage.cards.e.ElvishRanger.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Elvish Spirit Guide", 69, Rarity.UNCOMMON, mage.cards.e.ElvishSpiritGuide.class)); - cards.add(new SetCardInfo("Enslaved Scout", 104, Rarity.COMMON, EnslavedScout.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Enslaved Scout", 105, Rarity.COMMON, EnslavedScout.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Exile", 129, Rarity.RARE, mage.cards.e.Exile.class)); - cards.add(new SetCardInfo("False Demise", 40, Rarity.COMMON, mage.cards.f.FalseDemise.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("False Demise", 41, Rarity.COMMON, mage.cards.f.FalseDemise.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Feast or Famine", 8, Rarity.COMMON, mage.cards.f.FeastOrFamine.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Feast or Famine", 9, Rarity.COMMON, mage.cards.f.FeastOrFamine.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Fevered Strength", 10, Rarity.COMMON, FeveredStrength.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Fevered Strength", 11, Rarity.COMMON, FeveredStrength.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Floodwater Dam", 161, Rarity.RARE, mage.cards.f.FloodwaterDam.class)); - cards.add(new SetCardInfo("Force of Will", 42, Rarity.UNCOMMON, mage.cards.f.ForceOfWill.class)); - cards.add(new SetCardInfo("Gorilla Berserkers", 75, Rarity.COMMON, GorillaBerserkers.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Gorilla Berserkers", 76, Rarity.COMMON, GorillaBerserkers.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Gorilla Chieftain", 77, Rarity.COMMON, mage.cards.g.GorillaChieftain.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Gorilla Chieftain", 78, Rarity.COMMON, mage.cards.g.GorillaChieftain.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Gorilla Shaman", 106, Rarity.COMMON, GorillaShaman.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Gorilla Shaman", 107, Rarity.UNCOMMON, GorillaShaman.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Gorilla War Cry", 108, Rarity.COMMON, mage.cards.g.GorillaWarCry.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Gorilla War Cry", 109, Rarity.COMMON, mage.cards.g.GorillaWarCry.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Guerrilla Tactics", 110, Rarity.COMMON, mage.cards.g.GuerrillaTactics.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Guerrilla Tactics", 111, Rarity.COMMON, mage.cards.g.GuerrillaTactics.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Heart of Yavimaya", 183, Rarity.RARE, mage.cards.h.HeartOfYavimaya.class)); - cards.add(new SetCardInfo("Helm of Obedience", 163, Rarity.RARE, mage.cards.h.HelmOfObedience.class)); - cards.add(new SetCardInfo("Inheritance", 130, Rarity.UNCOMMON, mage.cards.i.Inheritance.class)); - cards.add(new SetCardInfo("Insidious Bookworms", 12, Rarity.COMMON, InsidiousBookworms.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Insidious Bookworms", 13, Rarity.COMMON, InsidiousBookworms.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Juniper Order Advocate", 132, Rarity.UNCOMMON, mage.cards.j.JuniperOrderAdvocate.class)); - cards.add(new SetCardInfo("Kaysa", 80, Rarity.RARE, mage.cards.k.Kaysa.class)); - cards.add(new SetCardInfo("Keeper of Tresserhorn", 14, Rarity.RARE, mage.cards.k.KeeperOfTresserhorn.class)); - cards.add(new SetCardInfo("Kjeldoran Outpost", 184, Rarity.RARE, mage.cards.k.KjeldoranOutpost.class)); - cards.add(new SetCardInfo("Lake of the Dead", 185, Rarity.RARE, mage.cards.l.LakeOfTheDead.class)); - cards.add(new SetCardInfo("Library of Lat-Nam", 47, Rarity.RARE, mage.cards.l.LibraryOfLatNam.class)); - cards.add(new SetCardInfo("Lim-Dul's High Guard", 17, Rarity.COMMON, LimDulsHighGuard.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Lim-Dul's High Guard", 18, Rarity.COMMON, LimDulsHighGuard.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Lim-Dul's Paladin", 191, Rarity.UNCOMMON, mage.cards.l.LimDulsPaladin.class)); - cards.add(new SetCardInfo("Lim-Dul's Vault", 192, Rarity.UNCOMMON, mage.cards.l.LimDulsVault.class)); - cards.add(new SetCardInfo("Lord of Tresserhorn", 193, Rarity.RARE, mage.cards.l.LordOfTresserhorn.class)); - cards.add(new SetCardInfo("Mystic Compass", 166, Rarity.UNCOMMON, mage.cards.m.MysticCompass.class)); - cards.add(new SetCardInfo("Phelddagrif", 196, Rarity.RARE, mage.cards.p.Phelddagrif.class)); - cards.add(new SetCardInfo("Phyrexian Devourer", 167, Rarity.RARE, mage.cards.p.PhyrexianDevourer.class)); - cards.add(new SetCardInfo("Phyrexian War Beast", 169, Rarity.COMMON, PhyrexianWarBeast.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Phyrexian War Beast", 170, Rarity.COMMON, PhyrexianWarBeast.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Pillage", 113, Rarity.UNCOMMON, mage.cards.p.Pillage.class)); - cards.add(new SetCardInfo("Pyrokinesis", 115, Rarity.UNCOMMON, mage.cards.p.Pyrokinesis.class)); - cards.add(new SetCardInfo("Reinforcements", 142, Rarity.COMMON, mage.cards.r.Reinforcements.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Reinforcements", 143, Rarity.COMMON, mage.cards.r.Reinforcements.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Reprisal", 144, Rarity.COMMON, mage.cards.r.Reprisal.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Reprisal", 145, Rarity.COMMON, mage.cards.r.Reprisal.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Ritual of the Machine", 24, Rarity.RARE, mage.cards.r.RitualOfTheMachine.class)); - cards.add(new SetCardInfo("Royal Herbalist", 147, Rarity.COMMON, RoyalHerbalist.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Royal Herbalist", 148, Rarity.COMMON, RoyalHerbalist.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("School of the Unseen", 186, Rarity.UNCOMMON, mage.cards.s.SchoolOfTheUnseen.class)); - cards.add(new SetCardInfo("Seasoned Tactician", 150, Rarity.UNCOMMON, mage.cards.s.SeasonedTactician.class)); - cards.add(new SetCardInfo("Sheltered Valley", 187, Rarity.RARE, mage.cards.s.ShelteredValley.class)); - cards.add(new SetCardInfo("Shield Sphere", 172, Rarity.UNCOMMON, mage.cards.s.ShieldSphere.class)); - cards.add(new SetCardInfo("Soldevi Adnate", 25, Rarity.COMMON, SoldeviAdnate.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Soldevi Adnate", 26, Rarity.COMMON, SoldeviAdnate.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Soldevi Digger", 174, Rarity.RARE, mage.cards.s.SoldeviDigger.class)); - cards.add(new SetCardInfo("Soldevi Excavations", 188, Rarity.RARE, mage.cards.s.SoldeviExcavations.class)); - cards.add(new SetCardInfo("Soldevi Sage", 51, Rarity.COMMON, SoldeviSage.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Soldevi Sage", 52, Rarity.COMMON, SoldeviSage.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Soldier of Fortune", 117, Rarity.UNCOMMON, mage.cards.s.SoldierOfFortune.class)); - cards.add(new SetCardInfo("Sol Grail", 173, Rarity.UNCOMMON, mage.cards.s.SolGrail.class)); - cards.add(new SetCardInfo("Storm Cauldron", 179, Rarity.RARE, mage.cards.s.StormCauldron.class)); - cards.add(new SetCardInfo("Storm Crow", 54, Rarity.COMMON, mage.cards.s.StormCrow.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Storm Crow", 55, Rarity.COMMON, mage.cards.s.StormCrow.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Storm Shaman", 118, Rarity.COMMON, StormShaman.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Storm Shaman", 119, Rarity.UNCOMMON, StormShaman.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Sustaining Spirit", 151, Rarity.RARE, mage.cards.s.SustainingSpirit.class)); - cards.add(new SetCardInfo("Swamp Mosquito", 30, Rarity.COMMON, SwampMosquito.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Swamp Mosquito", 31, Rarity.COMMON, SwampMosquito.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Thawing Glaciers", 189, Rarity.RARE, mage.cards.t.ThawingGlaciers.class)); - cards.add(new SetCardInfo("Thought Lash", 58, Rarity.RARE, mage.cards.t.ThoughtLash.class)); - cards.add(new SetCardInfo("Tornado", 86, Rarity.RARE, mage.cards.t.Tornado.class)); - cards.add(new SetCardInfo("Viscerid Armor", 60, Rarity.COMMON, mage.cards.v.VisceridArmor.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Viscerid Armor", 61, Rarity.COMMON, mage.cards.v.VisceridArmor.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Wandering Mage", 198, Rarity.RARE, mage.cards.w.WanderingMage.class)); - cards.add(new SetCardInfo("Whip Vine", 89, Rarity.COMMON, WhipVine.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Whip Vine", 90, Rarity.COMMON, WhipVine.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Wild Aesthir", 154, Rarity.COMMON, mage.cards.w.WildAesthir.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Wild Aesthir", 155, Rarity.COMMON, mage.cards.w.WildAesthir.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Yavimaya Ancients", 91, Rarity.COMMON, mage.cards.y.YavimayaAncients.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Yavimaya Ancients", 92, Rarity.COMMON, mage.cards.y.YavimayaAncients.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Yavimaya Ants", 93, Rarity.UNCOMMON, mage.cards.y.YavimayaAnts.class)); - } -} +package mage.sets; + +import mage.cards.ExpansionSet; +import mage.cards.a.AesthirGlider; +import mage.cards.a.AgentOfStromgald; +import mage.cards.b.BalduvianWarMakers; +import mage.cards.c.CarrierPigeons; +import mage.cards.e.EnslavedScout; +import mage.cards.f.FeveredStrength; +import mage.cards.g.GorillaBerserkers; +import mage.cards.g.GorillaShaman; +import mage.cards.i.InsidiousBookworms; +import mage.cards.l.LimDulsHighGuard; +import mage.cards.p.PhyrexianWarBeast; +import mage.cards.r.RoyalHerbalist; +import mage.cards.s.SoldeviAdnate; +import mage.cards.s.SoldeviSage; +import mage.cards.s.StormShaman; +import mage.cards.s.SwampMosquito; +import mage.cards.w.WhipVine; +import mage.constants.SetType; + +import mage.constants.Rarity; +import mage.cards.CardGraphicInfo; + +public class Alliances extends ExpansionSet { + private static final Alliances fINSTANCE = new Alliances(); + + public static Alliances getInstance() { + return fINSTANCE; + } + + private Alliances() { + super("Alliances", "ALL", ExpansionSet.buildDate(1996, 6, 10), SetType.EXPANSION); + this.blockName = "Ice Age"; + this.parentSet = IceAge.getInstance(); + this.hasBasicLands = false; + this.hasBoosters = true; + this.numBoosterLands = 0; + this.numBoosterCommon = 8; + this.numBoosterUncommon = 3; + this.numBoosterRare = 1; + this.ratioBoosterMythic = 0; + cards.add(new SetCardInfo("Aesthir Glider", 156, Rarity.COMMON, AesthirGlider.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Aesthir Glider", 157, Rarity.COMMON, AesthirGlider.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Agent of Stromgald", 94, Rarity.COMMON, AgentOfStromgald.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Agent of Stromgald", 95, Rarity.COMMON, AgentOfStromgald.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Arcane Denial", 32, Rarity.COMMON, mage.cards.a.ArcaneDenial.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Arcane Denial", 33, Rarity.COMMON, mage.cards.a.ArcaneDenial.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Astrolabe", 159, Rarity.COMMON, mage.cards.a.Astrolabe.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Astrolabe", 160, Rarity.COMMON, mage.cards.a.Astrolabe.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Balduvian Dead", 1, Rarity.UNCOMMON, mage.cards.b.BalduvianDead.class)); + cards.add(new SetCardInfo("Balduvian Horde", 96, Rarity.RARE, mage.cards.b.BalduvianHorde.class)); + cards.add(new SetCardInfo("Balduvian Trading Post", 182, Rarity.RARE, mage.cards.b.BalduvianTradingPost.class)); + cards.add(new SetCardInfo("Balduvian War-Makers", 97, Rarity.COMMON, BalduvianWarMakers.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Balduvian War-Makers", 98, Rarity.COMMON, BalduvianWarMakers.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Bounty of the Hunt", 63, Rarity.UNCOMMON, mage.cards.b.BountyOfTheHunt.class)); + cards.add(new SetCardInfo("Browse", 38, Rarity.UNCOMMON, mage.cards.b.Browse.class)); + cards.add(new SetCardInfo("Burnout", 101, Rarity.UNCOMMON, mage.cards.b.Burnout.class)); + cards.add(new SetCardInfo("Carrier Pigeons", 125, Rarity.COMMON, CarrierPigeons.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Carrier Pigeons", 126, Rarity.COMMON, CarrierPigeons.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Contagion", 4, Rarity.UNCOMMON, mage.cards.c.Contagion.class)); + cards.add(new SetCardInfo("Deadly Insect", 64, Rarity.COMMON, mage.cards.d.DeadlyInsect.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Deadly Insect", 65, Rarity.COMMON, mage.cards.d.DeadlyInsect.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Death Spark", 103, Rarity.UNCOMMON, mage.cards.d.DeathSpark.class)); + cards.add(new SetCardInfo("Diminishing Returns", 39, Rarity.RARE, mage.cards.d.DiminishingReturns.class)); + cards.add(new SetCardInfo("Dystopia", 6, Rarity.RARE, mage.cards.d.Dystopia.class)); + cards.add(new SetCardInfo("Elvish Bard", 66, Rarity.UNCOMMON, mage.cards.e.ElvishBard.class)); + cards.add(new SetCardInfo("Elvish Ranger", 67, Rarity.COMMON, mage.cards.e.ElvishRanger.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Elvish Ranger", 68, Rarity.COMMON, mage.cards.e.ElvishRanger.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Elvish Spirit Guide", 69, Rarity.UNCOMMON, mage.cards.e.ElvishSpiritGuide.class)); + cards.add(new SetCardInfo("Enslaved Scout", 104, Rarity.COMMON, EnslavedScout.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Enslaved Scout", 105, Rarity.COMMON, EnslavedScout.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Exile", 129, Rarity.RARE, mage.cards.e.Exile.class)); + cards.add(new SetCardInfo("False Demise", 40, Rarity.COMMON, mage.cards.f.FalseDemise.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("False Demise", 41, Rarity.COMMON, mage.cards.f.FalseDemise.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Feast or Famine", 8, Rarity.COMMON, mage.cards.f.FeastOrFamine.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Feast or Famine", 9, Rarity.COMMON, mage.cards.f.FeastOrFamine.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Fevered Strength", 10, Rarity.COMMON, FeveredStrength.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Fevered Strength", 11, Rarity.COMMON, FeveredStrength.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Floodwater Dam", 161, Rarity.RARE, mage.cards.f.FloodwaterDam.class)); + cards.add(new SetCardInfo("Force of Will", 42, Rarity.UNCOMMON, mage.cards.f.ForceOfWill.class)); + cards.add(new SetCardInfo("Gorilla Berserkers", 75, Rarity.COMMON, GorillaBerserkers.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Gorilla Berserkers", 76, Rarity.COMMON, GorillaBerserkers.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Gorilla Chieftain", 77, Rarity.COMMON, mage.cards.g.GorillaChieftain.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Gorilla Chieftain", 78, Rarity.COMMON, mage.cards.g.GorillaChieftain.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Gorilla Shaman", 106, Rarity.COMMON, GorillaShaman.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Gorilla Shaman", 107, Rarity.UNCOMMON, GorillaShaman.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Gorilla War Cry", 108, Rarity.COMMON, mage.cards.g.GorillaWarCry.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Gorilla War Cry", 109, Rarity.COMMON, mage.cards.g.GorillaWarCry.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Guerrilla Tactics", 110, Rarity.COMMON, mage.cards.g.GuerrillaTactics.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Guerrilla Tactics", 111, Rarity.COMMON, mage.cards.g.GuerrillaTactics.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Heart of Yavimaya", 183, Rarity.RARE, mage.cards.h.HeartOfYavimaya.class)); + cards.add(new SetCardInfo("Helm of Obedience", 163, Rarity.RARE, mage.cards.h.HelmOfObedience.class)); + cards.add(new SetCardInfo("Inheritance", 130, Rarity.UNCOMMON, mage.cards.i.Inheritance.class)); + cards.add(new SetCardInfo("Insidious Bookworms", 12, Rarity.COMMON, InsidiousBookworms.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Insidious Bookworms", 13, Rarity.COMMON, InsidiousBookworms.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Juniper Order Advocate", 132, Rarity.UNCOMMON, mage.cards.j.JuniperOrderAdvocate.class)); + cards.add(new SetCardInfo("Kaysa", 80, Rarity.RARE, mage.cards.k.Kaysa.class)); + cards.add(new SetCardInfo("Keeper of Tresserhorn", 14, Rarity.RARE, mage.cards.k.KeeperOfTresserhorn.class)); + cards.add(new SetCardInfo("Kjeldoran Outpost", 184, Rarity.RARE, mage.cards.k.KjeldoranOutpost.class)); + cards.add(new SetCardInfo("Lake of the Dead", 185, Rarity.RARE, mage.cards.l.LakeOfTheDead.class)); + cards.add(new SetCardInfo("Library of Lat-Nam", 47, Rarity.RARE, mage.cards.l.LibraryOfLatNam.class)); + cards.add(new SetCardInfo("Lim-Dul's High Guard", 17, Rarity.COMMON, LimDulsHighGuard.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Lim-Dul's High Guard", 18, Rarity.COMMON, LimDulsHighGuard.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Lim-Dul's Paladin", 191, Rarity.UNCOMMON, mage.cards.l.LimDulsPaladin.class)); + cards.add(new SetCardInfo("Lim-Dul's Vault", 192, Rarity.UNCOMMON, mage.cards.l.LimDulsVault.class)); + cards.add(new SetCardInfo("Lord of Tresserhorn", 193, Rarity.RARE, mage.cards.l.LordOfTresserhorn.class)); + cards.add(new SetCardInfo("Mystic Compass", 166, Rarity.UNCOMMON, mage.cards.m.MysticCompass.class)); + cards.add(new SetCardInfo("Phelddagrif", 196, Rarity.RARE, mage.cards.p.Phelddagrif.class)); + cards.add(new SetCardInfo("Phyrexian Devourer", 167, Rarity.RARE, mage.cards.p.PhyrexianDevourer.class)); + cards.add(new SetCardInfo("Phyrexian War Beast", 169, Rarity.COMMON, PhyrexianWarBeast.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Phyrexian War Beast", 170, Rarity.COMMON, PhyrexianWarBeast.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Pillage", 113, Rarity.UNCOMMON, mage.cards.p.Pillage.class)); + cards.add(new SetCardInfo("Pyrokinesis", 115, Rarity.UNCOMMON, mage.cards.p.Pyrokinesis.class)); + cards.add(new SetCardInfo("Reinforcements", 142, Rarity.COMMON, mage.cards.r.Reinforcements.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Reinforcements", 143, Rarity.COMMON, mage.cards.r.Reinforcements.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Reprisal", 144, Rarity.COMMON, mage.cards.r.Reprisal.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Reprisal", 145, Rarity.COMMON, mage.cards.r.Reprisal.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Ritual of the Machine", 24, Rarity.RARE, mage.cards.r.RitualOfTheMachine.class)); + cards.add(new SetCardInfo("Royal Herbalist", 147, Rarity.COMMON, RoyalHerbalist.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Royal Herbalist", 148, Rarity.COMMON, RoyalHerbalist.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("School of the Unseen", 186, Rarity.UNCOMMON, mage.cards.s.SchoolOfTheUnseen.class)); + cards.add(new SetCardInfo("Seasoned Tactician", 150, Rarity.UNCOMMON, mage.cards.s.SeasonedTactician.class)); + cards.add(new SetCardInfo("Sheltered Valley", 187, Rarity.RARE, mage.cards.s.ShelteredValley.class)); + cards.add(new SetCardInfo("Shield Sphere", 172, Rarity.UNCOMMON, mage.cards.s.ShieldSphere.class)); + cards.add(new SetCardInfo("Soldevi Adnate", 25, Rarity.COMMON, SoldeviAdnate.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Soldevi Adnate", 26, Rarity.COMMON, SoldeviAdnate.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Soldevi Digger", 174, Rarity.RARE, mage.cards.s.SoldeviDigger.class)); + cards.add(new SetCardInfo("Soldevi Excavations", 188, Rarity.RARE, mage.cards.s.SoldeviExcavations.class)); + cards.add(new SetCardInfo("Soldevi Sage", 51, Rarity.COMMON, SoldeviSage.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Soldevi Sage", 52, Rarity.COMMON, SoldeviSage.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Soldier of Fortune", 117, Rarity.UNCOMMON, mage.cards.s.SoldierOfFortune.class)); + cards.add(new SetCardInfo("Sol Grail", 173, Rarity.UNCOMMON, mage.cards.s.SolGrail.class)); + cards.add(new SetCardInfo("Storm Cauldron", 179, Rarity.RARE, mage.cards.s.StormCauldron.class)); + cards.add(new SetCardInfo("Storm Crow", 54, Rarity.COMMON, mage.cards.s.StormCrow.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Storm Crow", 55, Rarity.COMMON, mage.cards.s.StormCrow.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Storm Shaman", 118, Rarity.COMMON, StormShaman.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Storm Shaman", 119, Rarity.UNCOMMON, StormShaman.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Sustaining Spirit", 151, Rarity.RARE, mage.cards.s.SustainingSpirit.class)); + cards.add(new SetCardInfo("Swamp Mosquito", 30, Rarity.COMMON, SwampMosquito.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Swamp Mosquito", 31, Rarity.COMMON, SwampMosquito.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Thawing Glaciers", 189, Rarity.RARE, mage.cards.t.ThawingGlaciers.class)); + cards.add(new SetCardInfo("Thought Lash", 58, Rarity.RARE, mage.cards.t.ThoughtLash.class)); + cards.add(new SetCardInfo("Tornado", 86, Rarity.RARE, mage.cards.t.Tornado.class)); + cards.add(new SetCardInfo("Viscerid Armor", 60, Rarity.COMMON, mage.cards.v.VisceridArmor.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Viscerid Armor", 61, Rarity.COMMON, mage.cards.v.VisceridArmor.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Wandering Mage", 198, Rarity.RARE, mage.cards.w.WanderingMage.class)); + cards.add(new SetCardInfo("Whip Vine", 89, Rarity.COMMON, WhipVine.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Whip Vine", 90, Rarity.COMMON, WhipVine.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Wild Aesthir", 154, Rarity.COMMON, mage.cards.w.WildAesthir.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Wild Aesthir", 155, Rarity.COMMON, mage.cards.w.WildAesthir.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Yavimaya Ancients", 91, Rarity.COMMON, mage.cards.y.YavimayaAncients.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Yavimaya Ancients", 92, Rarity.COMMON, mage.cards.y.YavimayaAncients.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Yavimaya Ants", 93, Rarity.UNCOMMON, mage.cards.y.YavimayaAnts.class)); + } +} diff --git a/Mage.Sets/src/mage/sets/Invasion.java b/Mage.Sets/src/mage/sets/Invasion.java index 2b3fd5476c9..7d6c1378bf1 100644 --- a/Mage.Sets/src/mage/sets/Invasion.java +++ b/Mage.Sets/src/mage/sets/Invasion.java @@ -206,6 +206,7 @@ public class Invasion extends ExpansionSet { cards.add(new SetCardInfo("Opt", 64, Rarity.COMMON, mage.cards.o.Opt.class)); cards.add(new SetCardInfo("Ordered Migration", 258, Rarity.UNCOMMON, mage.cards.o.OrderedMigration.class)); cards.add(new SetCardInfo("Orim's Touch", 23, Rarity.COMMON, mage.cards.o.OrimsTouch.class)); + cards.add(new SetCardInfo("Overabundance", 259, Rarity.RARE, mage.cards.o.Overabundance.class)); cards.add(new SetCardInfo("Overload", 157, Rarity.COMMON, mage.cards.o.Overload.class)); cards.add(new SetCardInfo("Pain // Suffering", 294, Rarity.UNCOMMON, mage.cards.p.PainSuffering.class)); cards.add(new SetCardInfo("Phantasmal Terrain", 65, Rarity.COMMON, mage.cards.p.PhantasmalTerrain.class)); diff --git a/Mage.Sets/src/mage/sets/Judgment.java b/Mage.Sets/src/mage/sets/Judgment.java index 9435b44c455..ac2f77e38e6 100644 --- a/Mage.Sets/src/mage/sets/Judgment.java +++ b/Mage.Sets/src/mage/sets/Judgment.java @@ -63,6 +63,7 @@ public class Judgment extends ExpansionSet { cards.add(new SetCardInfo("Aven Fogbringer", 34, Rarity.COMMON, mage.cards.a.AvenFogbringer.class)); cards.add(new SetCardInfo("Balthor the Defiled", 61, Rarity.RARE, mage.cards.b.BalthorTheDefiled.class)); cards.add(new SetCardInfo("Battle Screech", 3, Rarity.UNCOMMON, mage.cards.b.BattleScreech.class)); + cards.add(new SetCardInfo("Battlefield Scrounger", 106, Rarity.COMMON, mage.cards.b.BattlefieldScrounger.class)); cards.add(new SetCardInfo("Battlewise Aven", 4, Rarity.COMMON, mage.cards.b.BattlewiseAven.class)); cards.add(new SetCardInfo("Benevolent Bodyguard", 5, Rarity.COMMON, mage.cards.b.BenevolentBodyguard.class)); cards.add(new SetCardInfo("Book Burning", 80, Rarity.COMMON, mage.cards.b.BookBurning.class)); @@ -73,7 +74,7 @@ public class Judgment extends ExpansionSet { cards.add(new SetCardInfo("Burning Wish", 83, Rarity.RARE, mage.cards.b.BurningWish.class)); cards.add(new SetCardInfo("Cabal Therapy", 62, Rarity.UNCOMMON, mage.cards.c.CabalTherapy.class)); cards.add(new SetCardInfo("Cabal Trainee", 63, Rarity.COMMON, mage.cards.c.CabalTrainee.class)); - cards.add(new SetCardInfo("Cagemail", 7, Rarity.COMMON, mage.cards.c.Cagemail.class)); + cards.add(new SetCardInfo("Cagemail", 7, Rarity.COMMON, mage.cards.c.Cagemail.class)); cards.add(new SetCardInfo("Canopy Claws", 108, Rarity.COMMON, mage.cards.c.CanopyClaws.class)); cards.add(new SetCardInfo("Centaur Rootcaster", 109, Rarity.COMMON, mage.cards.c.CentaurRootcaster.class)); cards.add(new SetCardInfo("Cephalid Constable", 35, Rarity.RARE, mage.cards.c.CephalidConstable.class)); diff --git a/Mage.Sets/src/mage/sets/Legends.java b/Mage.Sets/src/mage/sets/Legends.java index 5bb2f82516e..d115a310fb8 100644 --- a/Mage.Sets/src/mage/sets/Legends.java +++ b/Mage.Sets/src/mage/sets/Legends.java @@ -184,6 +184,7 @@ public class Legends extends ExpansionSet { cards.add(new SetCardInfo("Ragnar", 290, Rarity.RARE, mage.cards.r.Ragnar.class)); cards.add(new SetCardInfo("Ramirez DePietro", 291, Rarity.UNCOMMON, mage.cards.r.RamirezDePietro.class)); cards.add(new SetCardInfo("Ramses Overdark", 292, Rarity.RARE, mage.cards.r.RamsesOverdark.class)); + cards.add(new SetCardInfo("Rasputin Dreamweaver", 293, Rarity.RARE, mage.cards.r.RasputinDreamweaver.class)); cards.add(new SetCardInfo("Recall", 70, Rarity.RARE, mage.cards.r.Recall.class)); cards.add(new SetCardInfo("Reincarnation", 115, Rarity.UNCOMMON, mage.cards.r.Reincarnation.class)); cards.add(new SetCardInfo("Relic Barrier", 237, Rarity.UNCOMMON, mage.cards.r.RelicBarrier.class)); diff --git a/Mage.Sets/src/mage/sets/MastersEditionII.java b/Mage.Sets/src/mage/sets/MastersEditionII.java index d2f8e936dd4..a6202cc8f1c 100644 --- a/Mage.Sets/src/mage/sets/MastersEditionII.java +++ b/Mage.Sets/src/mage/sets/MastersEditionII.java @@ -1,236 +1,237 @@ -/* - * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of BetaSteward_at_googlemail.com. - */ -package mage.sets; - -import mage.cards.ExpansionSet; -import mage.cards.a.ArmorThrull; -import mage.cards.b.BrassclawOrcs; -import mage.cards.c.CombatMedic; -import mage.cards.e.ElvishHunter; -import mage.cards.f.FarrelsZealot; -import mage.cards.g.GorillaShaman; -import mage.cards.i.IcatianJavelineers; -import mage.cards.i.IcatianScout; -import mage.cards.l.LimDulsHighGuard; -import mage.cards.n.Necrite; -import mage.cards.n.NightSoil; -import mage.cards.o.OrcishVeteran; -import mage.constants.SetType; -import mage.constants.Rarity; - -/** - * - * @author LevelX2 - */ -public class MastersEditionII extends ExpansionSet { - - private static final MastersEditionII fINSTANCE = new MastersEditionII(); - - public static MastersEditionII getInstance() { - return fINSTANCE; - } - - private MastersEditionII() { - super("Masters Edition II", "ME2", ExpansionSet.buildDate(2008, 9, 22), SetType.MAGIC_ONLINE); - this.hasBasicLands = false; - this.hasBoosters = true; - this.numBoosterLands = 1; - this.numBoosterCommon = 10; - this.numBoosterUncommon = 3; - this.numBoosterRare = 1; - this.ratioBoosterMythic = 0; - cards.add(new SetCardInfo("Abbey Gargoyles", 1, Rarity.UNCOMMON, mage.cards.a.AbbeyGargoyles.class)); - cards.add(new SetCardInfo("Adarkar Sentinel", 201, Rarity.COMMON, mage.cards.a.AdarkarSentinel.class)); - cards.add(new SetCardInfo("Aeolipile", 202, Rarity.COMMON, mage.cards.a.Aeolipile.class)); - cards.add(new SetCardInfo("Ambush Party", 115, Rarity.COMMON, mage.cards.a.AmbushParty.class)); - cards.add(new SetCardInfo("Anarchy", 116, Rarity.RARE, mage.cards.a.Anarchy.class)); - cards.add(new SetCardInfo("Angel of Fury", 2, Rarity.RARE, mage.cards.a.AngelOfFury.class)); - cards.add(new SetCardInfo("Angel of Light", 3, Rarity.UNCOMMON, mage.cards.a.AngelOfLight.class)); - cards.add(new SetCardInfo("Armored Griffin", 5, Rarity.COMMON, mage.cards.a.ArmoredGriffin.class)); - cards.add(new SetCardInfo("Armor of Faith", 4, Rarity.COMMON, mage.cards.a.ArmorOfFaith.class)); - cards.add(new SetCardInfo("Armor Thrull", 77, Rarity.COMMON, ArmorThrull.class)); - cards.add(new SetCardInfo("Aurochs", 153, Rarity.COMMON, mage.cards.a.Aurochs.class)); - cards.add(new SetCardInfo("Aysen Bureaucrats", 6, Rarity.COMMON, mage.cards.a.AysenBureaucrats.class)); - cards.add(new SetCardInfo("Badlands", 225, Rarity.RARE, mage.cards.b.Badlands.class)); - cards.add(new SetCardInfo("Balduvian Dead", 79, Rarity.UNCOMMON, mage.cards.b.BalduvianDead.class)); - cards.add(new SetCardInfo("Balduvian Trading Post", 226, Rarity.RARE, mage.cards.b.BalduvianTradingPost.class)); - cards.add(new SetCardInfo("Barbed Sextant", 204, Rarity.COMMON, mage.cards.b.BarbedSextant.class)); - cards.add(new SetCardInfo("Binding Grasp", 41, Rarity.RARE, mage.cards.b.BindingGrasp.class)); - cards.add(new SetCardInfo("Bounty of the Hunt", 154, Rarity.RARE, mage.cards.b.BountyOfTheHunt.class)); - cards.add(new SetCardInfo("Brainstorm", 42, Rarity.COMMON, mage.cards.b.Brainstorm.class)); - cards.add(new SetCardInfo("Brassclaw Orcs", 119, Rarity.COMMON, BrassclawOrcs.class)); - cards.add(new SetCardInfo("Brimstone Dragon", 120, Rarity.RARE, mage.cards.b.BrimstoneDragon.class)); - cards.add(new SetCardInfo("Browse", 43, Rarity.UNCOMMON, mage.cards.b.Browse.class)); - cards.add(new SetCardInfo("Burnout", 121, Rarity.UNCOMMON, mage.cards.b.Burnout.class)); - cards.add(new SetCardInfo("Carapace", 155, Rarity.COMMON, mage.cards.c.Carapace.class)); - cards.add(new SetCardInfo("Caribou Range", 8, Rarity.RARE, mage.cards.c.CaribouRange.class)); - cards.add(new SetCardInfo("Combat Medic", 9, Rarity.COMMON, CombatMedic.class)); - cards.add(new SetCardInfo("Conquer", 122, Rarity.UNCOMMON, mage.cards.c.Conquer.class)); - cards.add(new SetCardInfo("Counterspell", 44, Rarity.UNCOMMON, mage.cards.c.Counterspell.class)); - cards.add(new SetCardInfo("Dance of the Dead", 83, Rarity.UNCOMMON, mage.cards.d.DanceOfTheDead.class)); - cards.add(new SetCardInfo("Dark Banishing", 84, Rarity.COMMON, mage.cards.d.DarkBanishing.class)); - cards.add(new SetCardInfo("Deep Spawn", 45, Rarity.RARE, mage.cards.d.DeepSpawn.class)); - cards.add(new SetCardInfo("Demonic Consultation", 85, Rarity.UNCOMMON, mage.cards.d.DemonicConsultation.class)); - cards.add(new SetCardInfo("Despotic Scepter", 206, Rarity.RARE, mage.cards.d.DespoticScepter.class)); - cards.add(new SetCardInfo("Disenchant", 10, Rarity.COMMON, mage.cards.d.Disenchant.class)); - cards.add(new SetCardInfo("Dwarven Ruins", 227, Rarity.UNCOMMON, mage.cards.d.DwarvenRuins.class)); - cards.add(new SetCardInfo("Dystopia", 88, Rarity.RARE, mage.cards.d.Dystopia.class)); - cards.add(new SetCardInfo("Ebon Praetor", 89, Rarity.RARE, mage.cards.e.EbonPraetor.class)); - cards.add(new SetCardInfo("Ebon Stronghold", 228, Rarity.UNCOMMON, mage.cards.e.EbonStronghold.class)); - cards.add(new SetCardInfo("Elemental Augury", 193, Rarity.RARE, mage.cards.e.ElementalAugury.class)); - cards.add(new SetCardInfo("Elven Lyre", 208, Rarity.COMMON, mage.cards.e.ElvenLyre.class)); - cards.add(new SetCardInfo("Elvish Farmer", 156, Rarity.RARE, mage.cards.e.ElvishFarmer.class)); - cards.add(new SetCardInfo("Elvish Hunter", 157, Rarity.COMMON, ElvishHunter.class)); - cards.add(new SetCardInfo("Elvish Ranger", 158, Rarity.COMMON, mage.cards.e.ElvishRanger.class)); - cards.add(new SetCardInfo("Elvish Spirit Guide", 159, Rarity.UNCOMMON, mage.cards.e.ElvishSpiritGuide.class)); - cards.add(new SetCardInfo("Enervate", 47, Rarity.COMMON, mage.cards.e.Enervate.class)); - cards.add(new SetCardInfo("Errantry", 124, Rarity.COMMON, mage.cards.e.Errantry.class)); - cards.add(new SetCardInfo("Farrel's Mantle", 13, Rarity.UNCOMMON, mage.cards.f.FarrelsMantle.class)); - cards.add(new SetCardInfo("Farrel's Zealot", 14, Rarity.UNCOMMON, FarrelsZealot.class)); - cards.add(new SetCardInfo("Feral Thallid", 161, Rarity.COMMON, mage.cards.f.FeralThallid.class)); - cards.add(new SetCardInfo("Fire Dragon", 125, Rarity.RARE, mage.cards.f.FireDragon.class)); - cards.add(new SetCardInfo("Flame Spirit", 126, Rarity.UNCOMMON, mage.cards.f.FlameSpirit.class)); - cards.add(new SetCardInfo("Folk of the Pines", 162, Rarity.COMMON, mage.cards.f.FolkOfThePines.class)); - cards.add(new SetCardInfo("Forbidden Lore", 163, Rarity.UNCOMMON, mage.cards.f.ForbiddenLore.class)); - cards.add(new SetCardInfo("Forgotten Lore", 164, Rarity.UNCOMMON, mage.cards.f.ForgottenLore.class)); - cards.add(new SetCardInfo("Foul Familiar", 90, Rarity.COMMON, mage.cards.f.FoulFamiliar.class)); - cards.add(new SetCardInfo("Fumarole", 194, Rarity.UNCOMMON, mage.cards.f.Fumarole.class)); - cards.add(new SetCardInfo("Fungal Bloom", 165, Rarity.RARE, mage.cards.f.FungalBloom.class)); - cards.add(new SetCardInfo("Giant Growth", 167, Rarity.COMMON, mage.cards.g.GiantGrowth.class)); - cards.add(new SetCardInfo("Glacial Chasm", 229, Rarity.RARE, mage.cards.g.GlacialChasm.class)); - cards.add(new SetCardInfo("Glacial Crevasses", 127, Rarity.RARE, mage.cards.g.GlacialCrevasses.class)); - cards.add(new SetCardInfo("Gorilla Shaman", 129, Rarity.UNCOMMON, GorillaShaman.class)); - cards.add(new SetCardInfo("Grandmother Sengir", 93, Rarity.RARE, mage.cards.g.GrandmotherSengir.class)); - cards.add(new SetCardInfo("Havenwood Battleground", 230, Rarity.UNCOMMON, mage.cards.h.HavenwoodBattleground.class)); - cards.add(new SetCardInfo("Heart of Yavimaya", 231, Rarity.RARE, mage.cards.h.HeartOfYavimaya.class)); - cards.add(new SetCardInfo("Helm of Obedience", 210, Rarity.RARE, mage.cards.h.HelmOfObedience.class)); - cards.add(new SetCardInfo("Icatian Javelineers", 15, Rarity.COMMON, IcatianJavelineers.class)); - cards.add(new SetCardInfo("Icatian Scout", 17, Rarity.COMMON, IcatianScout.class)); - cards.add(new SetCardInfo("Icequake", 94, Rarity.COMMON, mage.cards.i.Icequake.class)); - cards.add(new SetCardInfo("Icy Prison", 50, Rarity.COMMON, mage.cards.i.IcyPrison.class)); - cards.add(new SetCardInfo("Ihsan's Shade", 95, Rarity.RARE, mage.cards.i.IhsansShade.class)); - cards.add(new SetCardInfo("Imperial Recruiter", 130, Rarity.RARE, mage.cards.i.ImperialRecruiter.class)); - cards.add(new SetCardInfo("Imperial Seal", 96, Rarity.RARE, mage.cards.i.ImperialSeal.class)); - cards.add(new SetCardInfo("Incinerate", 131, Rarity.COMMON, mage.cards.i.Incinerate.class)); - cards.add(new SetCardInfo("Inheritance", 18, Rarity.UNCOMMON, mage.cards.i.Inheritance.class)); - cards.add(new SetCardInfo("Ironclaw Orcs", 132, Rarity.COMMON, mage.cards.i.IronclawOrcs.class)); - cards.add(new SetCardInfo("Jester's Mask", 211, Rarity.RARE, mage.cards.j.JestersMask.class)); - cards.add(new SetCardInfo("Johtull Wurm", 168, Rarity.UNCOMMON, mage.cards.j.JohtullWurm.class)); - cards.add(new SetCardInfo("Juniper Order Advocate", 20, Rarity.UNCOMMON, mage.cards.j.JuniperOrderAdvocate.class)); - cards.add(new SetCardInfo("Kaysa", 170, Rarity.RARE, mage.cards.k.Kaysa.class)); - cards.add(new SetCardInfo("Kjeldoran Dead", 98, Rarity.COMMON, mage.cards.k.KjeldoranDead.class)); - cards.add(new SetCardInfo("Kjeldoran Outpost", 233, Rarity.RARE, mage.cards.k.KjeldoranOutpost.class)); - cards.add(new SetCardInfo("Knight of Stromgald", 99, Rarity.UNCOMMON, mage.cards.k.KnightOfStromgald.class)); - cards.add(new SetCardInfo("Krovikan Fetish", 100, Rarity.COMMON, mage.cards.k.KrovikanFetish.class)); - cards.add(new SetCardInfo("Krovikan Sorcerer", 51, Rarity.COMMON, mage.cards.k.KrovikanSorcerer.class)); - cards.add(new SetCardInfo("Leaping Lizard", 171, Rarity.COMMON, mage.cards.l.LeapingLizard.class)); - cards.add(new SetCardInfo("Lim-Dul's High Guard", 103, Rarity.UNCOMMON, LimDulsHighGuard.class)); - cards.add(new SetCardInfo("Magus of the Unseen", 53, Rarity.RARE, mage.cards.m.MagusOfTheUnseen.class)); - cards.add(new SetCardInfo("Mana Crypt", 214, Rarity.RARE, mage.cards.m.ManaCrypt.class)); - cards.add(new SetCardInfo("Marjhan", 54, Rarity.RARE, mage.cards.m.Marjhan.class)); - cards.add(new SetCardInfo("Mesmeric Trance", 55, Rarity.RARE, mage.cards.m.MesmericTrance.class)); - cards.add(new SetCardInfo("Narwhal", 57, Rarity.UNCOMMON, mage.cards.n.Narwhal.class)); - cards.add(new SetCardInfo("Necrite", 106, Rarity.COMMON, Necrite.class)); - cards.add(new SetCardInfo("Necropotence", 107, Rarity.RARE, mage.cards.n.Necropotence.class)); - cards.add(new SetCardInfo("Night Soil", 173, Rarity.UNCOMMON, NightSoil.class)); - cards.add(new SetCardInfo("Orc General", 137, Rarity.UNCOMMON, mage.cards.o.OrcGeneral.class)); - cards.add(new SetCardInfo("Orcish Cannoneers", 138, Rarity.UNCOMMON, mage.cards.o.OrcishCannoneers.class)); - cards.add(new SetCardInfo("Orcish Captain", 139, Rarity.UNCOMMON, mage.cards.o.OrcishCaptain.class)); - cards.add(new SetCardInfo("Orcish Lumberjack", 142, Rarity.COMMON, mage.cards.o.OrcishLumberjack.class)); - cards.add(new SetCardInfo("Orcish Veteran", 144, Rarity.COMMON, OrcishVeteran.class)); - cards.add(new SetCardInfo("Order of the Sacred Torch", 25, Rarity.RARE, mage.cards.o.OrderOfTheSacredTorch.class)); - cards.add(new SetCardInfo("Order of the White Shield", 26, Rarity.UNCOMMON, mage.cards.o.OrderOfTheWhiteShield.class)); - cards.add(new SetCardInfo("Panic", 145, Rarity.COMMON, mage.cards.p.Panic.class)); - cards.add(new SetCardInfo("Personal Tutor", 58, Rarity.UNCOMMON, mage.cards.p.PersonalTutor.class)); - cards.add(new SetCardInfo("Phyrexian Devourer", 216, Rarity.UNCOMMON, mage.cards.p.PhyrexianDevourer.class)); - cards.add(new SetCardInfo("Pillage", 146, Rarity.UNCOMMON, mage.cards.p.Pillage.class)); - cards.add(new SetCardInfo("Portent", 60, Rarity.COMMON, mage.cards.p.Portent.class)); - cards.add(new SetCardInfo("Pyrokinesis", 147, Rarity.RARE, mage.cards.p.Pyrokinesis.class)); - cards.add(new SetCardInfo("Ravages of War", 27, Rarity.RARE, mage.cards.r.RavagesOfWar.class)); - cards.add(new SetCardInfo("Ray of Command", 61, Rarity.UNCOMMON, mage.cards.r.RayOfCommand.class)); - cards.add(new SetCardInfo("Red Cliffs Armada", 62, Rarity.COMMON, mage.cards.r.RedCliffsArmada.class)); - cards.add(new SetCardInfo("Reinforcements", 28, Rarity.COMMON, mage.cards.r.Reinforcements.class)); - cards.add(new SetCardInfo("Reprisal", 29, Rarity.COMMON, mage.cards.r.Reprisal.class)); - cards.add(new SetCardInfo("Righteous Fury", 30, Rarity.RARE, mage.cards.r.RighteousFury.class)); - cards.add(new SetCardInfo("Ritual of the Machine", 109, Rarity.RARE, mage.cards.r.RitualOfTheMachine.class)); - cards.add(new SetCardInfo("Roterothopter", 218, Rarity.COMMON, mage.cards.r.Roterothopter.class)); - cards.add(new SetCardInfo("Royal Trooper", 32, Rarity.COMMON, mage.cards.r.RoyalTrooper.class)); - cards.add(new SetCardInfo("Ruins of Trokair", 234, Rarity.UNCOMMON, mage.cards.r.RuinsOfTrokair.class)); - cards.add(new SetCardInfo("Savannah", 235, Rarity.RARE, mage.cards.s.Savannah.class)); - cards.add(new SetCardInfo("Screeching Drake", 63, Rarity.COMMON, mage.cards.s.ScreechingDrake.class)); - cards.add(new SetCardInfo("Sea Drake", 64, Rarity.RARE, mage.cards.s.SeaDrake.class)); - cards.add(new SetCardInfo("Sea Spirit", 65, Rarity.UNCOMMON, mage.cards.s.SeaSpirit.class)); - cards.add(new SetCardInfo("Shrink", 175, Rarity.COMMON, mage.cards.s.Shrink.class)); - cards.add(new SetCardInfo("Sibilant Spirit", 67, Rarity.RARE, mage.cards.s.SibilantSpirit.class)); - cards.add(new SetCardInfo("Skeleton Ship", 197, Rarity.RARE, mage.cards.s.SkeletonShip.class)); - cards.add(new SetCardInfo("Skull Catapult", 219, Rarity.UNCOMMON, mage.cards.s.SkullCatapult.class)); - cards.add(new SetCardInfo("Snow-Covered Forest", 245, Rarity.LAND, mage.cards.s.SnowCoveredForest.class)); - cards.add(new SetCardInfo("Snow-Covered Island", 242, Rarity.LAND, mage.cards.s.SnowCoveredIsland.class)); - cards.add(new SetCardInfo("Snow-Covered Mountain", 244, Rarity.LAND, mage.cards.s.SnowCoveredMountain.class)); - cards.add(new SetCardInfo("Snow-Covered Plains", 241, Rarity.LAND, mage.cards.s.SnowCoveredPlains.class)); - cards.add(new SetCardInfo("Snow-Covered Swamp", 243, Rarity.LAND, mage.cards.s.SnowCoveredSwamp.class)); - cards.add(new SetCardInfo("Soldevi Digger", 221, Rarity.UNCOMMON, mage.cards.s.SoldeviDigger.class)); - cards.add(new SetCardInfo("Soldevi Excavations", 236, Rarity.RARE, mage.cards.s.SoldeviExcavations.class)); - cards.add(new SetCardInfo("Soldevi Simulacrum", 222, Rarity.UNCOMMON, mage.cards.s.SoldeviSimulacrum.class)); - cards.add(new SetCardInfo("Songs of the Damned", 110, Rarity.COMMON, mage.cards.s.SongsOfTheDamned.class)); - cards.add(new SetCardInfo("Soul Exchange", 111, Rarity.UNCOMMON, mage.cards.s.SoulExchange.class)); - cards.add(new SetCardInfo("Soul Kiss", 112, Rarity.UNCOMMON, mage.cards.s.SoulKiss.class)); - cards.add(new SetCardInfo("Spore Flower", 177, Rarity.UNCOMMON, mage.cards.s.SporeFlower.class)); - cards.add(new SetCardInfo("Stampede", 178, Rarity.UNCOMMON, mage.cards.s.Stampede.class)); - cards.add(new SetCardInfo("Stonehands", 151, Rarity.COMMON, mage.cards.s.Stonehands.class)); - cards.add(new SetCardInfo("Stone Spirit", 150, Rarity.UNCOMMON, mage.cards.s.StoneSpirit.class)); - cards.add(new SetCardInfo("Storm Spirit", 198, Rarity.RARE, mage.cards.s.StormSpirit.class)); - cards.add(new SetCardInfo("Stromgald Cabal", 113, Rarity.RARE, mage.cards.s.StromgaldCabal.class)); - cards.add(new SetCardInfo("Stunted Growth", 179, Rarity.RARE, mage.cards.s.StuntedGrowth.class)); - cards.add(new SetCardInfo("Sustaining Spirit", 36, Rarity.RARE, mage.cards.s.SustainingSpirit.class)); - cards.add(new SetCardInfo("Svyelunite Temple", 237, Rarity.UNCOMMON, mage.cards.s.SvyeluniteTemple.class)); - cards.add(new SetCardInfo("Swords to Plowshares", 37, Rarity.UNCOMMON, mage.cards.s.SwordsToPlowshares.class)); - cards.add(new SetCardInfo("Taiga", 238, Rarity.RARE, mage.cards.t.Taiga.class)); - cards.add(new SetCardInfo("Temporal Manipulation", 69, Rarity.RARE, mage.cards.t.TemporalManipulation.class)); - cards.add(new SetCardInfo("Thallid", 180, Rarity.COMMON, mage.cards.t.Thallid.class)); - cards.add(new SetCardInfo("Thallid Devourer", 181, Rarity.COMMON, mage.cards.t.ThallidDevourer.class)); - cards.add(new SetCardInfo("Thelonite Druid", 182, Rarity.RARE, mage.cards.t.TheloniteDruid.class)); - cards.add(new SetCardInfo("Thermokarst", 183, Rarity.COMMON, mage.cards.t.Thermokarst.class)); - cards.add(new SetCardInfo("Thought Lash", 70, Rarity.RARE, mage.cards.t.ThoughtLash.class)); - cards.add(new SetCardInfo("Thunder Wall", 71, Rarity.UNCOMMON, mage.cards.t.ThunderWall.class)); - cards.add(new SetCardInfo("Time Bomb", 223, Rarity.RARE, mage.cards.t.TimeBomb.class)); - cards.add(new SetCardInfo("Tinder Wall", 184, Rarity.COMMON, mage.cards.t.TinderWall.class)); - cards.add(new SetCardInfo("Tundra", 239, Rarity.RARE, mage.cards.t.Tundra.class)); - cards.add(new SetCardInfo("Underground Sea", 240, Rarity.RARE, mage.cards.u.UndergroundSea.class)); - cards.add(new SetCardInfo("Viscerid Armor", 72, Rarity.COMMON, mage.cards.v.VisceridArmor.class)); - cards.add(new SetCardInfo("Wall of Kelp", 74, Rarity.COMMON, mage.cards.w.WallOfKelp.class)); - cards.add(new SetCardInfo("Warning", 38, Rarity.COMMON, mage.cards.w.Warning.class)); - cards.add(new SetCardInfo("Whiteout", 185, Rarity.COMMON, mage.cards.w.Whiteout.class)); - cards.add(new SetCardInfo("Wind Spirit", 75, Rarity.UNCOMMON, mage.cards.w.WindSpirit.class)); - cards.add(new SetCardInfo("Wings of Aesthir", 199, Rarity.UNCOMMON, mage.cards.w.WingsOfAesthir.class)); - cards.add(new SetCardInfo("Wolf Pack", 187, Rarity.RARE, mage.cards.w.WolfPack.class)); - cards.add(new SetCardInfo("Yavimaya Ancients", 190, Rarity.UNCOMMON, mage.cards.y.YavimayaAncients.class)); - cards.add(new SetCardInfo("Zuran Spellcaster", 76, Rarity.COMMON, mage.cards.z.ZuranSpellcaster.class)); - } - +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets; + +import mage.cards.ExpansionSet; +import mage.cards.a.ArmorThrull; +import mage.cards.b.BrassclawOrcs; +import mage.cards.c.CombatMedic; +import mage.cards.e.ElvishHunter; +import mage.cards.f.FarrelsZealot; +import mage.cards.g.GorillaShaman; +import mage.cards.i.IcatianJavelineers; +import mage.cards.i.IcatianScout; +import mage.cards.l.LimDulsHighGuard; +import mage.cards.n.Necrite; +import mage.cards.n.NightSoil; +import mage.cards.o.OrcishVeteran; +import mage.constants.SetType; +import mage.constants.Rarity; + +/** + * + * @author LevelX2 + */ +public class MastersEditionII extends ExpansionSet { + + private static final MastersEditionII fINSTANCE = new MastersEditionII(); + + public static MastersEditionII getInstance() { + return fINSTANCE; + } + + private MastersEditionII() { + super("Masters Edition II", "ME2", ExpansionSet.buildDate(2008, 9, 22), SetType.MAGIC_ONLINE); + this.hasBasicLands = false; + this.hasBoosters = true; + this.numBoosterLands = 1; + this.numBoosterCommon = 10; + this.numBoosterUncommon = 3; + this.numBoosterRare = 1; + this.ratioBoosterMythic = 0; + cards.add(new SetCardInfo("Abbey Gargoyles", 1, Rarity.UNCOMMON, mage.cards.a.AbbeyGargoyles.class)); + cards.add(new SetCardInfo("Adarkar Sentinel", 201, Rarity.COMMON, mage.cards.a.AdarkarSentinel.class)); + cards.add(new SetCardInfo("Aeolipile", 202, Rarity.COMMON, mage.cards.a.Aeolipile.class)); + cards.add(new SetCardInfo("Ambush Party", 115, Rarity.COMMON, mage.cards.a.AmbushParty.class)); + cards.add(new SetCardInfo("Anarchy", 116, Rarity.RARE, mage.cards.a.Anarchy.class)); + cards.add(new SetCardInfo("Angel of Fury", 2, Rarity.RARE, mage.cards.a.AngelOfFury.class)); + cards.add(new SetCardInfo("Angel of Light", 3, Rarity.UNCOMMON, mage.cards.a.AngelOfLight.class)); + cards.add(new SetCardInfo("Armored Griffin", 5, Rarity.COMMON, mage.cards.a.ArmoredGriffin.class)); + cards.add(new SetCardInfo("Armor of Faith", 4, Rarity.COMMON, mage.cards.a.ArmorOfFaith.class)); + cards.add(new SetCardInfo("Armor Thrull", 77, Rarity.COMMON, ArmorThrull.class)); + cards.add(new SetCardInfo("Aurochs", 153, Rarity.COMMON, mage.cards.a.Aurochs.class)); + cards.add(new SetCardInfo("Aysen Bureaucrats", 6, Rarity.COMMON, mage.cards.a.AysenBureaucrats.class)); + cards.add(new SetCardInfo("Badlands", 225, Rarity.RARE, mage.cards.b.Badlands.class)); + cards.add(new SetCardInfo("Balduvian Dead", 79, Rarity.UNCOMMON, mage.cards.b.BalduvianDead.class)); + cards.add(new SetCardInfo("Balduvian Trading Post", 226, Rarity.RARE, mage.cards.b.BalduvianTradingPost.class)); + cards.add(new SetCardInfo("Barbed Sextant", 204, Rarity.COMMON, mage.cards.b.BarbedSextant.class)); + cards.add(new SetCardInfo("Binding Grasp", 41, Rarity.RARE, mage.cards.b.BindingGrasp.class)); + cards.add(new SetCardInfo("Bounty of the Hunt", 154, Rarity.RARE, mage.cards.b.BountyOfTheHunt.class)); + cards.add(new SetCardInfo("Brainstorm", 42, Rarity.COMMON, mage.cards.b.Brainstorm.class)); + cards.add(new SetCardInfo("Brassclaw Orcs", 119, Rarity.COMMON, BrassclawOrcs.class)); + cards.add(new SetCardInfo("Brimstone Dragon", 120, Rarity.RARE, mage.cards.b.BrimstoneDragon.class)); + cards.add(new SetCardInfo("Browse", 43, Rarity.UNCOMMON, mage.cards.b.Browse.class)); + cards.add(new SetCardInfo("Burnout", 121, Rarity.UNCOMMON, mage.cards.b.Burnout.class)); + cards.add(new SetCardInfo("Carapace", 155, Rarity.COMMON, mage.cards.c.Carapace.class)); + cards.add(new SetCardInfo("Caribou Range", 8, Rarity.RARE, mage.cards.c.CaribouRange.class)); + cards.add(new SetCardInfo("Combat Medic", 9, Rarity.COMMON, CombatMedic.class)); + cards.add(new SetCardInfo("Conquer", 122, Rarity.UNCOMMON, mage.cards.c.Conquer.class)); + cards.add(new SetCardInfo("Counterspell", 44, Rarity.UNCOMMON, mage.cards.c.Counterspell.class)); + cards.add(new SetCardInfo("Dance of the Dead", 83, Rarity.UNCOMMON, mage.cards.d.DanceOfTheDead.class)); + cards.add(new SetCardInfo("Dark Banishing", 84, Rarity.COMMON, mage.cards.d.DarkBanishing.class)); + cards.add(new SetCardInfo("Death Spark", 123, Rarity.COMMON, mage.cards.d.DeathSpark.class)); + cards.add(new SetCardInfo("Deep Spawn", 45, Rarity.RARE, mage.cards.d.DeepSpawn.class)); + cards.add(new SetCardInfo("Demonic Consultation", 85, Rarity.UNCOMMON, mage.cards.d.DemonicConsultation.class)); + cards.add(new SetCardInfo("Despotic Scepter", 206, Rarity.RARE, mage.cards.d.DespoticScepter.class)); + cards.add(new SetCardInfo("Disenchant", 10, Rarity.COMMON, mage.cards.d.Disenchant.class)); + cards.add(new SetCardInfo("Dwarven Ruins", 227, Rarity.UNCOMMON, mage.cards.d.DwarvenRuins.class)); + cards.add(new SetCardInfo("Dystopia", 88, Rarity.RARE, mage.cards.d.Dystopia.class)); + cards.add(new SetCardInfo("Ebon Praetor", 89, Rarity.RARE, mage.cards.e.EbonPraetor.class)); + cards.add(new SetCardInfo("Ebon Stronghold", 228, Rarity.UNCOMMON, mage.cards.e.EbonStronghold.class)); + cards.add(new SetCardInfo("Elemental Augury", 193, Rarity.RARE, mage.cards.e.ElementalAugury.class)); + cards.add(new SetCardInfo("Elven Lyre", 208, Rarity.COMMON, mage.cards.e.ElvenLyre.class)); + cards.add(new SetCardInfo("Elvish Farmer", 156, Rarity.RARE, mage.cards.e.ElvishFarmer.class)); + cards.add(new SetCardInfo("Elvish Hunter", 157, Rarity.COMMON, ElvishHunter.class)); + cards.add(new SetCardInfo("Elvish Ranger", 158, Rarity.COMMON, mage.cards.e.ElvishRanger.class)); + cards.add(new SetCardInfo("Elvish Spirit Guide", 159, Rarity.UNCOMMON, mage.cards.e.ElvishSpiritGuide.class)); + cards.add(new SetCardInfo("Enervate", 47, Rarity.COMMON, mage.cards.e.Enervate.class)); + cards.add(new SetCardInfo("Errantry", 124, Rarity.COMMON, mage.cards.e.Errantry.class)); + cards.add(new SetCardInfo("Farrel's Mantle", 13, Rarity.UNCOMMON, mage.cards.f.FarrelsMantle.class)); + cards.add(new SetCardInfo("Farrel's Zealot", 14, Rarity.UNCOMMON, FarrelsZealot.class)); + cards.add(new SetCardInfo("Feral Thallid", 161, Rarity.COMMON, mage.cards.f.FeralThallid.class)); + cards.add(new SetCardInfo("Fire Dragon", 125, Rarity.RARE, mage.cards.f.FireDragon.class)); + cards.add(new SetCardInfo("Flame Spirit", 126, Rarity.UNCOMMON, mage.cards.f.FlameSpirit.class)); + cards.add(new SetCardInfo("Folk of the Pines", 162, Rarity.COMMON, mage.cards.f.FolkOfThePines.class)); + cards.add(new SetCardInfo("Forbidden Lore", 163, Rarity.UNCOMMON, mage.cards.f.ForbiddenLore.class)); + cards.add(new SetCardInfo("Forgotten Lore", 164, Rarity.UNCOMMON, mage.cards.f.ForgottenLore.class)); + cards.add(new SetCardInfo("Foul Familiar", 90, Rarity.COMMON, mage.cards.f.FoulFamiliar.class)); + cards.add(new SetCardInfo("Fumarole", 194, Rarity.UNCOMMON, mage.cards.f.Fumarole.class)); + cards.add(new SetCardInfo("Fungal Bloom", 165, Rarity.RARE, mage.cards.f.FungalBloom.class)); + cards.add(new SetCardInfo("Giant Growth", 167, Rarity.COMMON, mage.cards.g.GiantGrowth.class)); + cards.add(new SetCardInfo("Glacial Chasm", 229, Rarity.RARE, mage.cards.g.GlacialChasm.class)); + cards.add(new SetCardInfo("Glacial Crevasses", 127, Rarity.RARE, mage.cards.g.GlacialCrevasses.class)); + cards.add(new SetCardInfo("Gorilla Shaman", 129, Rarity.UNCOMMON, GorillaShaman.class)); + cards.add(new SetCardInfo("Grandmother Sengir", 93, Rarity.RARE, mage.cards.g.GrandmotherSengir.class)); + cards.add(new SetCardInfo("Havenwood Battleground", 230, Rarity.UNCOMMON, mage.cards.h.HavenwoodBattleground.class)); + cards.add(new SetCardInfo("Heart of Yavimaya", 231, Rarity.RARE, mage.cards.h.HeartOfYavimaya.class)); + cards.add(new SetCardInfo("Helm of Obedience", 210, Rarity.RARE, mage.cards.h.HelmOfObedience.class)); + cards.add(new SetCardInfo("Icatian Javelineers", 15, Rarity.COMMON, IcatianJavelineers.class)); + cards.add(new SetCardInfo("Icatian Scout", 17, Rarity.COMMON, IcatianScout.class)); + cards.add(new SetCardInfo("Icequake", 94, Rarity.COMMON, mage.cards.i.Icequake.class)); + cards.add(new SetCardInfo("Icy Prison", 50, Rarity.COMMON, mage.cards.i.IcyPrison.class)); + cards.add(new SetCardInfo("Ihsan's Shade", 95, Rarity.RARE, mage.cards.i.IhsansShade.class)); + cards.add(new SetCardInfo("Imperial Recruiter", 130, Rarity.RARE, mage.cards.i.ImperialRecruiter.class)); + cards.add(new SetCardInfo("Imperial Seal", 96, Rarity.RARE, mage.cards.i.ImperialSeal.class)); + cards.add(new SetCardInfo("Incinerate", 131, Rarity.COMMON, mage.cards.i.Incinerate.class)); + cards.add(new SetCardInfo("Inheritance", 18, Rarity.UNCOMMON, mage.cards.i.Inheritance.class)); + cards.add(new SetCardInfo("Ironclaw Orcs", 132, Rarity.COMMON, mage.cards.i.IronclawOrcs.class)); + cards.add(new SetCardInfo("Jester's Mask", 211, Rarity.RARE, mage.cards.j.JestersMask.class)); + cards.add(new SetCardInfo("Johtull Wurm", 168, Rarity.UNCOMMON, mage.cards.j.JohtullWurm.class)); + cards.add(new SetCardInfo("Juniper Order Advocate", 20, Rarity.UNCOMMON, mage.cards.j.JuniperOrderAdvocate.class)); + cards.add(new SetCardInfo("Kaysa", 170, Rarity.RARE, mage.cards.k.Kaysa.class)); + cards.add(new SetCardInfo("Kjeldoran Dead", 98, Rarity.COMMON, mage.cards.k.KjeldoranDead.class)); + cards.add(new SetCardInfo("Kjeldoran Outpost", 233, Rarity.RARE, mage.cards.k.KjeldoranOutpost.class)); + cards.add(new SetCardInfo("Knight of Stromgald", 99, Rarity.UNCOMMON, mage.cards.k.KnightOfStromgald.class)); + cards.add(new SetCardInfo("Krovikan Fetish", 100, Rarity.COMMON, mage.cards.k.KrovikanFetish.class)); + cards.add(new SetCardInfo("Krovikan Sorcerer", 51, Rarity.COMMON, mage.cards.k.KrovikanSorcerer.class)); + cards.add(new SetCardInfo("Leaping Lizard", 171, Rarity.COMMON, mage.cards.l.LeapingLizard.class)); + cards.add(new SetCardInfo("Lim-Dul's High Guard", 103, Rarity.UNCOMMON, LimDulsHighGuard.class)); + cards.add(new SetCardInfo("Magus of the Unseen", 53, Rarity.RARE, mage.cards.m.MagusOfTheUnseen.class)); + cards.add(new SetCardInfo("Mana Crypt", 214, Rarity.RARE, mage.cards.m.ManaCrypt.class)); + cards.add(new SetCardInfo("Marjhan", 54, Rarity.RARE, mage.cards.m.Marjhan.class)); + cards.add(new SetCardInfo("Mesmeric Trance", 55, Rarity.RARE, mage.cards.m.MesmericTrance.class)); + cards.add(new SetCardInfo("Narwhal", 57, Rarity.UNCOMMON, mage.cards.n.Narwhal.class)); + cards.add(new SetCardInfo("Necrite", 106, Rarity.COMMON, Necrite.class)); + cards.add(new SetCardInfo("Necropotence", 107, Rarity.RARE, mage.cards.n.Necropotence.class)); + cards.add(new SetCardInfo("Night Soil", 173, Rarity.UNCOMMON, NightSoil.class)); + cards.add(new SetCardInfo("Orc General", 137, Rarity.UNCOMMON, mage.cards.o.OrcGeneral.class)); + cards.add(new SetCardInfo("Orcish Cannoneers", 138, Rarity.UNCOMMON, mage.cards.o.OrcishCannoneers.class)); + cards.add(new SetCardInfo("Orcish Captain", 139, Rarity.UNCOMMON, mage.cards.o.OrcishCaptain.class)); + cards.add(new SetCardInfo("Orcish Lumberjack", 142, Rarity.COMMON, mage.cards.o.OrcishLumberjack.class)); + cards.add(new SetCardInfo("Orcish Veteran", 144, Rarity.COMMON, OrcishVeteran.class)); + cards.add(new SetCardInfo("Order of the Sacred Torch", 25, Rarity.RARE, mage.cards.o.OrderOfTheSacredTorch.class)); + cards.add(new SetCardInfo("Order of the White Shield", 26, Rarity.UNCOMMON, mage.cards.o.OrderOfTheWhiteShield.class)); + cards.add(new SetCardInfo("Panic", 145, Rarity.COMMON, mage.cards.p.Panic.class)); + cards.add(new SetCardInfo("Personal Tutor", 58, Rarity.UNCOMMON, mage.cards.p.PersonalTutor.class)); + cards.add(new SetCardInfo("Phyrexian Devourer", 216, Rarity.UNCOMMON, mage.cards.p.PhyrexianDevourer.class)); + cards.add(new SetCardInfo("Pillage", 146, Rarity.UNCOMMON, mage.cards.p.Pillage.class)); + cards.add(new SetCardInfo("Portent", 60, Rarity.COMMON, mage.cards.p.Portent.class)); + cards.add(new SetCardInfo("Pyrokinesis", 147, Rarity.RARE, mage.cards.p.Pyrokinesis.class)); + cards.add(new SetCardInfo("Ravages of War", 27, Rarity.RARE, mage.cards.r.RavagesOfWar.class)); + cards.add(new SetCardInfo("Ray of Command", 61, Rarity.UNCOMMON, mage.cards.r.RayOfCommand.class)); + cards.add(new SetCardInfo("Red Cliffs Armada", 62, Rarity.COMMON, mage.cards.r.RedCliffsArmada.class)); + cards.add(new SetCardInfo("Reinforcements", 28, Rarity.COMMON, mage.cards.r.Reinforcements.class)); + cards.add(new SetCardInfo("Reprisal", 29, Rarity.COMMON, mage.cards.r.Reprisal.class)); + cards.add(new SetCardInfo("Righteous Fury", 30, Rarity.RARE, mage.cards.r.RighteousFury.class)); + cards.add(new SetCardInfo("Ritual of the Machine", 109, Rarity.RARE, mage.cards.r.RitualOfTheMachine.class)); + cards.add(new SetCardInfo("Roterothopter", 218, Rarity.COMMON, mage.cards.r.Roterothopter.class)); + cards.add(new SetCardInfo("Royal Trooper", 32, Rarity.COMMON, mage.cards.r.RoyalTrooper.class)); + cards.add(new SetCardInfo("Ruins of Trokair", 234, Rarity.UNCOMMON, mage.cards.r.RuinsOfTrokair.class)); + cards.add(new SetCardInfo("Savannah", 235, Rarity.RARE, mage.cards.s.Savannah.class)); + cards.add(new SetCardInfo("Screeching Drake", 63, Rarity.COMMON, mage.cards.s.ScreechingDrake.class)); + cards.add(new SetCardInfo("Sea Drake", 64, Rarity.RARE, mage.cards.s.SeaDrake.class)); + cards.add(new SetCardInfo("Sea Spirit", 65, Rarity.UNCOMMON, mage.cards.s.SeaSpirit.class)); + cards.add(new SetCardInfo("Shrink", 175, Rarity.COMMON, mage.cards.s.Shrink.class)); + cards.add(new SetCardInfo("Sibilant Spirit", 67, Rarity.RARE, mage.cards.s.SibilantSpirit.class)); + cards.add(new SetCardInfo("Skeleton Ship", 197, Rarity.RARE, mage.cards.s.SkeletonShip.class)); + cards.add(new SetCardInfo("Skull Catapult", 219, Rarity.UNCOMMON, mage.cards.s.SkullCatapult.class)); + cards.add(new SetCardInfo("Snow-Covered Forest", 245, Rarity.LAND, mage.cards.s.SnowCoveredForest.class)); + cards.add(new SetCardInfo("Snow-Covered Island", 242, Rarity.LAND, mage.cards.s.SnowCoveredIsland.class)); + cards.add(new SetCardInfo("Snow-Covered Mountain", 244, Rarity.LAND, mage.cards.s.SnowCoveredMountain.class)); + cards.add(new SetCardInfo("Snow-Covered Plains", 241, Rarity.LAND, mage.cards.s.SnowCoveredPlains.class)); + cards.add(new SetCardInfo("Snow-Covered Swamp", 243, Rarity.LAND, mage.cards.s.SnowCoveredSwamp.class)); + cards.add(new SetCardInfo("Soldevi Digger", 221, Rarity.UNCOMMON, mage.cards.s.SoldeviDigger.class)); + cards.add(new SetCardInfo("Soldevi Excavations", 236, Rarity.RARE, mage.cards.s.SoldeviExcavations.class)); + cards.add(new SetCardInfo("Soldevi Simulacrum", 222, Rarity.UNCOMMON, mage.cards.s.SoldeviSimulacrum.class)); + cards.add(new SetCardInfo("Songs of the Damned", 110, Rarity.COMMON, mage.cards.s.SongsOfTheDamned.class)); + cards.add(new SetCardInfo("Soul Exchange", 111, Rarity.UNCOMMON, mage.cards.s.SoulExchange.class)); + cards.add(new SetCardInfo("Soul Kiss", 112, Rarity.UNCOMMON, mage.cards.s.SoulKiss.class)); + cards.add(new SetCardInfo("Spore Flower", 177, Rarity.UNCOMMON, mage.cards.s.SporeFlower.class)); + cards.add(new SetCardInfo("Stampede", 178, Rarity.UNCOMMON, mage.cards.s.Stampede.class)); + cards.add(new SetCardInfo("Stonehands", 151, Rarity.COMMON, mage.cards.s.Stonehands.class)); + cards.add(new SetCardInfo("Stone Spirit", 150, Rarity.UNCOMMON, mage.cards.s.StoneSpirit.class)); + cards.add(new SetCardInfo("Storm Spirit", 198, Rarity.RARE, mage.cards.s.StormSpirit.class)); + cards.add(new SetCardInfo("Stromgald Cabal", 113, Rarity.RARE, mage.cards.s.StromgaldCabal.class)); + cards.add(new SetCardInfo("Stunted Growth", 179, Rarity.RARE, mage.cards.s.StuntedGrowth.class)); + cards.add(new SetCardInfo("Sustaining Spirit", 36, Rarity.RARE, mage.cards.s.SustainingSpirit.class)); + cards.add(new SetCardInfo("Svyelunite Temple", 237, Rarity.UNCOMMON, mage.cards.s.SvyeluniteTemple.class)); + cards.add(new SetCardInfo("Swords to Plowshares", 37, Rarity.UNCOMMON, mage.cards.s.SwordsToPlowshares.class)); + cards.add(new SetCardInfo("Taiga", 238, Rarity.RARE, mage.cards.t.Taiga.class)); + cards.add(new SetCardInfo("Temporal Manipulation", 69, Rarity.RARE, mage.cards.t.TemporalManipulation.class)); + cards.add(new SetCardInfo("Thallid", 180, Rarity.COMMON, mage.cards.t.Thallid.class)); + cards.add(new SetCardInfo("Thallid Devourer", 181, Rarity.COMMON, mage.cards.t.ThallidDevourer.class)); + cards.add(new SetCardInfo("Thelonite Druid", 182, Rarity.RARE, mage.cards.t.TheloniteDruid.class)); + cards.add(new SetCardInfo("Thermokarst", 183, Rarity.COMMON, mage.cards.t.Thermokarst.class)); + cards.add(new SetCardInfo("Thought Lash", 70, Rarity.RARE, mage.cards.t.ThoughtLash.class)); + cards.add(new SetCardInfo("Thunder Wall", 71, Rarity.UNCOMMON, mage.cards.t.ThunderWall.class)); + cards.add(new SetCardInfo("Time Bomb", 223, Rarity.RARE, mage.cards.t.TimeBomb.class)); + cards.add(new SetCardInfo("Tinder Wall", 184, Rarity.COMMON, mage.cards.t.TinderWall.class)); + cards.add(new SetCardInfo("Tundra", 239, Rarity.RARE, mage.cards.t.Tundra.class)); + cards.add(new SetCardInfo("Underground Sea", 240, Rarity.RARE, mage.cards.u.UndergroundSea.class)); + cards.add(new SetCardInfo("Viscerid Armor", 72, Rarity.COMMON, mage.cards.v.VisceridArmor.class)); + cards.add(new SetCardInfo("Wall of Kelp", 74, Rarity.COMMON, mage.cards.w.WallOfKelp.class)); + cards.add(new SetCardInfo("Warning", 38, Rarity.COMMON, mage.cards.w.Warning.class)); + cards.add(new SetCardInfo("Whiteout", 185, Rarity.COMMON, mage.cards.w.Whiteout.class)); + cards.add(new SetCardInfo("Wind Spirit", 75, Rarity.UNCOMMON, mage.cards.w.WindSpirit.class)); + cards.add(new SetCardInfo("Wings of Aesthir", 199, Rarity.UNCOMMON, mage.cards.w.WingsOfAesthir.class)); + cards.add(new SetCardInfo("Wolf Pack", 187, Rarity.RARE, mage.cards.w.WolfPack.class)); + cards.add(new SetCardInfo("Yavimaya Ancients", 190, Rarity.UNCOMMON, mage.cards.y.YavimayaAncients.class)); + cards.add(new SetCardInfo("Zuran Spellcaster", 76, Rarity.COMMON, mage.cards.z.ZuranSpellcaster.class)); + } + } \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/MastersEditionIII.java b/Mage.Sets/src/mage/sets/MastersEditionIII.java index ae8ce58ab70..1427585cc0b 100644 --- a/Mage.Sets/src/mage/sets/MastersEditionIII.java +++ b/Mage.Sets/src/mage/sets/MastersEditionIII.java @@ -1,252 +1,253 @@ -/* - * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are - * permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of - * conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list - * of conditions and the following disclaimer in the documentation and/or other materials - * provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are those of the - * authors and should not be interpreted as representing official policies, either expressed - * or implied, of BetaSteward_at_googlemail.com. - */ -package mage.sets; - -import mage.cards.ExpansionSet; -import mage.cards.f.FeveredStrength; -import mage.constants.SetType; -import mage.constants.Rarity; -import mage.cards.CardGraphicInfo; - -/** - * - * @author LevelX2 - */ -public class MastersEditionIII extends ExpansionSet { - - private static final MastersEditionIII fINSTANCE = new MastersEditionIII(); - - public static MastersEditionIII getInstance() { - return fINSTANCE; - } - - private MastersEditionIII() { - super("Masters Edition III", "ME3", ExpansionSet.buildDate(2009, 9, 7), SetType.MAGIC_ONLINE); - this.hasBasicLands = true; - this.hasBoosters = true; - this.numBoosterLands = 1; - this.numBoosterCommon = 10; - this.numBoosterUncommon = 3; - this.numBoosterRare = 1; - this.ratioBoosterMythic = 0; - cards.add(new SetCardInfo("Active Volcano", 85, Rarity.UNCOMMON, mage.cards.a.ActiveVolcano.class)); - cards.add(new SetCardInfo("Akron Legionnaire", 1, Rarity.RARE, mage.cards.a.AkronLegionnaire.class)); - cards.add(new SetCardInfo("Amrou Kithkin", 3, Rarity.COMMON, mage.cards.a.AmrouKithkin.class)); - cards.add(new SetCardInfo("Anaba Ancestor", 86, Rarity.COMMON, mage.cards.a.AnabaAncestor.class)); - cards.add(new SetCardInfo("Anaba Spirit Crafter", 87, Rarity.COMMON, mage.cards.a.AnabaSpiritCrafter.class)); - cards.add(new SetCardInfo("Angus Mackenzie", 141, Rarity.RARE, mage.cards.a.AngusMackenzie.class)); - cards.add(new SetCardInfo("Arcades Sabboth", 142, Rarity.RARE, mage.cards.a.ArcadesSabboth.class)); - cards.add(new SetCardInfo("Arena of the Ancients", 188, Rarity.RARE, mage.cards.a.ArenaOfTheAncients.class)); - cards.add(new SetCardInfo("Ashes to Ashes", 58, Rarity.UNCOMMON, mage.cards.a.AshesToAshes.class)); - cards.add(new SetCardInfo("Astrolabe", 189, Rarity.COMMON, mage.cards.a.Astrolabe.class)); - cards.add(new SetCardInfo("Barktooth Warbeard", 144, Rarity.COMMON, mage.cards.b.BarktoothWarbeard.class)); - cards.add(new SetCardInfo("Barl's Cage", 190, Rarity.RARE, mage.cards.b.BarlsCage.class)); - cards.add(new SetCardInfo("Bartel Runeaxe", 145, Rarity.UNCOMMON, mage.cards.b.BartelRuneaxe.class)); - cards.add(new SetCardInfo("Bayou", 204, Rarity.RARE, mage.cards.b.Bayou.class)); - cards.add(new SetCardInfo("Bazaar of Baghdad", 205, Rarity.RARE, mage.cards.b.BazaarOfBaghdad.class)); - cards.add(new SetCardInfo("Black Vise", 191, Rarity.RARE, mage.cards.b.BlackVise.class)); - cards.add(new SetCardInfo("Blood Lust", 88, Rarity.COMMON, mage.cards.b.BloodLust.class)); - cards.add(new SetCardInfo("Bone Flute", 192, Rarity.COMMON, mage.cards.b.BoneFlute.class)); - cards.add(new SetCardInfo("Boomerang", 30, Rarity.COMMON, mage.cards.b.Boomerang.class)); - cards.add(new SetCardInfo("Boris Devilboon", 146, Rarity.UNCOMMON, mage.cards.b.BorisDevilboon.class)); - cards.add(new SetCardInfo("Borrowing 100,000 Arrows", 31, Rarity.UNCOMMON, mage.cards.b.Borrowing100000Arrows.class)); - cards.add(new SetCardInfo("Brilliant Plan", 32, Rarity.COMMON, mage.cards.b.BrilliantPlan.class)); - cards.add(new SetCardInfo("Burning of Xinye", 89, Rarity.RARE, mage.cards.b.BurningOfXinye.class)); - cards.add(new SetCardInfo("Capture of Jingzhou", 33, Rarity.RARE, mage.cards.c.CaptureOfJingzhou.class)); - cards.add(new SetCardInfo("Carrion Ants", 60, Rarity.UNCOMMON, mage.cards.c.CarrionAnts.class)); - cards.add(new SetCardInfo("Chain Lightning", 90, Rarity.COMMON, mage.cards.c.ChainLightning.class)); - cards.add(new SetCardInfo("Chromium", 147, Rarity.RARE, mage.cards.c.Chromium.class)); - cards.add(new SetCardInfo("Cinder Storm", 91, Rarity.UNCOMMON, mage.cards.c.CinderStorm.class)); - cards.add(new SetCardInfo("City of Shadows", 206, Rarity.RARE, mage.cards.c.CityOfShadows.class)); - cards.add(new SetCardInfo("Cleanse", 5, Rarity.RARE, mage.cards.c.Cleanse.class)); - cards.add(new SetCardInfo("Coal Golem", 193, Rarity.COMMON, mage.cards.c.CoalGolem.class)); - cards.add(new SetCardInfo("Concordant Crossroads", 114, Rarity.RARE, mage.cards.c.ConcordantCrossroads.class)); - cards.add(new SetCardInfo("Corrupt Eunuchs", 92, Rarity.UNCOMMON, mage.cards.c.CorruptEunuchs.class)); - cards.add(new SetCardInfo("Cosmic Horror", 61, Rarity.RARE, mage.cards.c.CosmicHorror.class)); - cards.add(new SetCardInfo("Crimson Kobolds", 93, Rarity.COMMON, mage.cards.c.CrimsonKobolds.class)); - cards.add(new SetCardInfo("Crimson Manticore", 94, Rarity.UNCOMMON, mage.cards.c.CrimsonManticore.class)); - cards.add(new SetCardInfo("Dance of Many", 34, Rarity.UNCOMMON, mage.cards.d.DanceOfMany.class)); - cards.add(new SetCardInfo("D'Avenant Archer", 6, Rarity.COMMON, mage.cards.d.DAvenantArcher.class)); - cards.add(new SetCardInfo("Demonic Torment", 62, Rarity.COMMON, mage.cards.d.DemonicTorment.class)); - cards.add(new SetCardInfo("Desert Twister", 115, Rarity.UNCOMMON, mage.cards.d.DesertTwister.class)); - cards.add(new SetCardInfo("Desperate Charge", 63, Rarity.COMMON, mage.cards.d.DesperateCharge.class)); - cards.add(new SetCardInfo("Didgeridoo", 194, Rarity.UNCOMMON, mage.cards.d.Didgeridoo.class)); - cards.add(new SetCardInfo("Disenchant", 7, Rarity.COMMON, mage.cards.d.Disenchant.class)); - cards.add(new SetCardInfo("Divine Intervention", 8, Rarity.RARE, mage.cards.d.DivineIntervention.class)); - cards.add(new SetCardInfo("Dong Zhou, the Tyrant", 96, Rarity.RARE, mage.cards.d.DongZhouTheTyrant.class)); - cards.add(new SetCardInfo("Elves of Deep Shadow", 116, Rarity.COMMON, mage.cards.e.ElvesOfDeepShadow.class)); - cards.add(new SetCardInfo("Evil Presence", 64, Rarity.COMMON, mage.cards.e.EvilPresence.class)); - cards.add(new SetCardInfo("Exorcist", 10, Rarity.UNCOMMON, mage.cards.e.Exorcist.class)); - cards.add(new SetCardInfo("Faerie Noble", 117, Rarity.UNCOMMON, mage.cards.f.FaerieNoble.class)); - cards.add(new SetCardInfo("False Defeat", 11, Rarity.UNCOMMON, mage.cards.f.FalseDefeat.class)); - cards.add(new SetCardInfo("Famine", 65, Rarity.UNCOMMON, mage.cards.f.Famine.class)); - cards.add(new SetCardInfo("Fellwar Stone", 195, Rarity.COMMON, mage.cards.f.FellwarStone.class)); - cards.add(new SetCardInfo("Fevered Strength", 66, Rarity.COMMON, FeveredStrength.class)); - cards.add(new SetCardInfo("Fire Ambush", 97, Rarity.COMMON, mage.cards.f.FireAmbush.class)); - cards.add(new SetCardInfo("Fire Drake", 98, Rarity.COMMON, mage.cards.f.FireDrake.class)); - cards.add(new SetCardInfo("Fire Sprites", 118, Rarity.COMMON, mage.cards.f.FireSprites.class)); - cards.add(new SetCardInfo("Flash Flood", 35, Rarity.UNCOMMON, mage.cards.f.FlashFlood.class)); - cards.add(new SetCardInfo("Forced Retreat", 37, Rarity.COMMON, mage.cards.f.ForcedRetreat.class)); - cards.add(new SetCardInfo("Force Spike", 36, Rarity.COMMON, mage.cards.f.ForceSpike.class)); - cards.add(new SetCardInfo("Forest", 228, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Forest", 229, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Forest", 230, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Frost Giant", 101, Rarity.UNCOMMON, mage.cards.f.FrostGiant.class)); - cards.add(new SetCardInfo("Gaea's Touch", 120, Rarity.UNCOMMON, mage.cards.g.GaeasTouch.class)); - cards.add(new SetCardInfo("Ghostly Visit", 67, Rarity.COMMON, mage.cards.g.GhostlyVisit.class)); - cards.add(new SetCardInfo("Ghosts of the Damned", 68, Rarity.COMMON, mage.cards.g.GhostsOfTheDamned.class)); - cards.add(new SetCardInfo("Giant Growth", 121, Rarity.COMMON, mage.cards.g.GiantGrowth.class)); - cards.add(new SetCardInfo("Grim Tutor", 69, Rarity.RARE, mage.cards.g.GrimTutor.class)); - cards.add(new SetCardInfo("Guan Yu's 1,000-Li March", 13, Rarity.RARE, mage.cards.g.GuanYus1000LiMarch.class)); - cards.add(new SetCardInfo("Guan Yu, Sainted Warrior", 12, Rarity.UNCOMMON, mage.cards.g.GuanYuSaintedWarrior.class)); - cards.add(new SetCardInfo("Gwendlyn Di Corci", 149, Rarity.RARE, mage.cards.g.GwendlynDiCorci.class)); - cards.add(new SetCardInfo("Hazezon Tamar", 151, Rarity.RARE, mage.cards.h.HazezonTamar.class)); - cards.add(new SetCardInfo("Heal", 14, Rarity.COMMON, mage.cards.h.Heal.class)); - cards.add(new SetCardInfo("Hellfire", 70, Rarity.RARE, mage.cards.h.Hellfire.class)); - cards.add(new SetCardInfo("Hua Tuo, Honored Physician", 123, Rarity.RARE, mage.cards.h.HuaTuoHonoredPhysician.class)); - cards.add(new SetCardInfo("Hunding Gjornersen", 152, Rarity.UNCOMMON, mage.cards.h.HundingGjornersen.class)); - cards.add(new SetCardInfo("Hunting Cheetah", 124, Rarity.COMMON, mage.cards.h.HuntingCheetah.class)); - cards.add(new SetCardInfo("Hurloon Minotaur", 102, Rarity.COMMON, mage.cards.h.HurloonMinotaur.class)); - cards.add(new SetCardInfo("Immolation", 103, Rarity.COMMON, mage.cards.i.Immolation.class)); - cards.add(new SetCardInfo("Infuse", 38, Rarity.COMMON, mage.cards.i.Infuse.class)); - cards.add(new SetCardInfo("Island", 219, Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Island", 220, Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Island", 221, Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Ivory Guardians", 15, Rarity.UNCOMMON, mage.cards.i.IvoryGuardians.class)); - cards.add(new SetCardInfo("Jedit Ojanen", 153, Rarity.COMMON, mage.cards.j.JeditOjanen.class)); - cards.add(new SetCardInfo("Jerrard of the Closed Fist", 154, Rarity.COMMON, mage.cards.j.JerrardOfTheClosedFist.class)); - cards.add(new SetCardInfo("Jungle Lion", 125, Rarity.COMMON, mage.cards.j.JungleLion.class)); - cards.add(new SetCardInfo("Karakas", 208, Rarity.RARE, mage.cards.k.Karakas.class)); - cards.add(new SetCardInfo("Kei Takahashi", 155, Rarity.UNCOMMON, mage.cards.k.KeiTakahashi.class)); - cards.add(new SetCardInfo("Killer Bees", 126, Rarity.UNCOMMON, mage.cards.k.KillerBees.class)); - cards.add(new SetCardInfo("Kobold Drill Sergeant", 104, Rarity.UNCOMMON, mage.cards.k.KoboldDrillSergeant.class)); - cards.add(new SetCardInfo("Kobold Overlord", 105, Rarity.UNCOMMON, mage.cards.k.KoboldOverlord.class)); - cards.add(new SetCardInfo("Kobolds of Kher Keep", 107, Rarity.COMMON, mage.cards.k.KoboldsOfKherKeep.class)); - cards.add(new SetCardInfo("Kobold Taskmaster", 106, Rarity.COMMON, mage.cards.k.KoboldTaskmaster.class)); - cards.add(new SetCardInfo("Kongming, 'Sleeping Dragon'", 16, Rarity.RARE, mage.cards.k.KongmingSleepingDragon.class)); - cards.add(new SetCardInfo("Lady Caleria", 157, Rarity.UNCOMMON, mage.cards.l.LadyCaleria.class)); - cards.add(new SetCardInfo("Lady Evangela", 158, Rarity.UNCOMMON, mage.cards.l.LadyEvangela.class)); - cards.add(new SetCardInfo("Lady Orca", 159, Rarity.COMMON, mage.cards.l.LadyOrca.class)); - cards.add(new SetCardInfo("Land Tax", 17, Rarity.RARE, mage.cards.l.LandTax.class)); - cards.add(new SetCardInfo("Lightning Blow", 18, Rarity.COMMON, mage.cards.l.LightningBlow.class)); - cards.add(new SetCardInfo("Liu Bei, Lord of Shu", 19, Rarity.RARE, mage.cards.l.LiuBeiLordOfShu.class)); - cards.add(new SetCardInfo("Living Plane", 127, Rarity.RARE, mage.cards.l.LivingPlane.class)); - cards.add(new SetCardInfo("Livonya Silone", 160, Rarity.UNCOMMON, mage.cards.l.LivonyaSilone.class)); - cards.add(new SetCardInfo("Loyal Retainers", 20, Rarity.UNCOMMON, mage.cards.l.LoyalRetainers.class)); - cards.add(new SetCardInfo("Lu Bu, Master-at-Arms", 108, Rarity.RARE, mage.cards.l.LuBuMasterAtArms.class)); - cards.add(new SetCardInfo("Lu Meng, Wu General", 41, Rarity.UNCOMMON, mage.cards.l.LuMengWuGeneral.class)); - cards.add(new SetCardInfo("Lu Xun, Scholar General", 42, Rarity.UNCOMMON, mage.cards.l.LuXunScholarGeneral.class)); - cards.add(new SetCardInfo("Mana Drain", 43, Rarity.RARE, mage.cards.m.ManaDrain.class)); - cards.add(new SetCardInfo("Mana Vortex", 44, Rarity.RARE, mage.cards.m.ManaVortex.class)); - cards.add(new SetCardInfo("Marhault Elsdragon", 161, Rarity.UNCOMMON, mage.cards.m.MarhaultElsdragon.class)); - cards.add(new SetCardInfo("Meng Huo, Barbarian King", 128, Rarity.RARE, mage.cards.m.MengHuoBarbarianKing.class)); - cards.add(new SetCardInfo("Meng Huo's Horde", 129, Rarity.COMMON, mage.cards.m.MengHuosHorde.class)); - cards.add(new SetCardInfo("Mind Twist", 72, Rarity.RARE, mage.cards.m.MindTwist.class)); - cards.add(new SetCardInfo("Mountain", 225, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Mountain", 226, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Mountain", 227, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Nether Void", 73, Rarity.RARE, mage.cards.n.NetherVoid.class)); - cards.add(new SetCardInfo("Nicol Bolas", 163, Rarity.RARE, mage.cards.n.NicolBolas.class)); - cards.add(new SetCardInfo("Old Man of the Sea", 45, Rarity.RARE, mage.cards.o.OldManOfTheSea.class)); - cards.add(new SetCardInfo("Palladia-Mors", 164, Rarity.RARE, mage.cards.p.PalladiaMors.class)); - cards.add(new SetCardInfo("Pavel Maliki", 165, Rarity.UNCOMMON, mage.cards.p.PavelMaliki.class)); - cards.add(new SetCardInfo("Peach Garden Oath", 22, Rarity.COMMON, mage.cards.p.PeachGardenOath.class)); - cards.add(new SetCardInfo("Plains", 216, Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Plains", 217, Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Plains", 218, Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Plateau", 209, Rarity.RARE, mage.cards.p.Plateau.class)); - cards.add(new SetCardInfo("Princess Lucrezia", 166, Rarity.UNCOMMON, mage.cards.p.PrincessLucrezia.class)); - cards.add(new SetCardInfo("Raging Minotaur", 109, Rarity.COMMON, mage.cards.r.RagingMinotaur.class)); - cards.add(new SetCardInfo("Ragnar", 167, Rarity.UNCOMMON, mage.cards.r.Ragnar.class)); - cards.add(new SetCardInfo("Ramirez DePietro", 168, Rarity.COMMON, mage.cards.r.RamirezDePietro.class)); - cards.add(new SetCardInfo("Ramses Overdark", 169, Rarity.UNCOMMON, mage.cards.r.RamsesOverdark.class)); - cards.add(new SetCardInfo("Recall", 46, Rarity.UNCOMMON, mage.cards.r.Recall.class)); - cards.add(new SetCardInfo("Reincarnation", 130, Rarity.UNCOMMON, mage.cards.r.Reincarnation.class)); - cards.add(new SetCardInfo("Remove Soul", 47, Rarity.COMMON, mage.cards.r.RemoveSoul.class)); - cards.add(new SetCardInfo("Reset", 48, Rarity.RARE, mage.cards.r.Reset.class)); - cards.add(new SetCardInfo("Reveka, Wizard Savant", 49, Rarity.UNCOMMON, mage.cards.r.RevekaWizardSavant.class)); - cards.add(new SetCardInfo("Riding the Dilu Horse", 131, Rarity.UNCOMMON, mage.cards.r.RidingTheDiluHorse.class)); - cards.add(new SetCardInfo("Riven Turnbull", 171, Rarity.UNCOMMON, mage.cards.r.RivenTurnbull.class)); - cards.add(new SetCardInfo("Rolling Earthquake", 110, Rarity.RARE, mage.cards.r.RollingEarthquake.class)); - cards.add(new SetCardInfo("Rubinia Soulsinger", 173, Rarity.RARE, mage.cards.r.RubiniaSoulsinger.class)); - cards.add(new SetCardInfo("Scrubland", 210, Rarity.RARE, mage.cards.s.Scrubland.class)); - cards.add(new SetCardInfo("Scryb Sprites", 132, Rarity.COMMON, mage.cards.s.ScrybSprites.class)); - cards.add(new SetCardInfo("Shu Cavalry", 23, Rarity.COMMON, mage.cards.s.ShuCavalry.class)); - cards.add(new SetCardInfo("Shu Elite Companions", 24, Rarity.COMMON, mage.cards.s.ShuEliteCompanions.class)); - cards.add(new SetCardInfo("Shu General", 25, Rarity.COMMON, mage.cards.s.ShuGeneral.class)); - cards.add(new SetCardInfo("Shu Soldier-Farmers", 26, Rarity.COMMON, mage.cards.s.ShuSoldierFarmers.class)); - cards.add(new SetCardInfo("Sir Shandlar of Eberyn", 174, Rarity.COMMON, mage.cards.s.SirShandlarOfEberyn.class)); - cards.add(new SetCardInfo("Sivitri Scarzam", 175, Rarity.COMMON, mage.cards.s.SivitriScarzam.class)); - cards.add(new SetCardInfo("Slashing Tiger", 133, Rarity.COMMON, mage.cards.s.SlashingTiger.class)); - cards.add(new SetCardInfo("Sol Grail", 201, Rarity.COMMON, mage.cards.s.SolGrail.class)); - cards.add(new SetCardInfo("Spirit Shackle", 74, Rarity.COMMON, mage.cards.s.SpiritShackle.class)); - cards.add(new SetCardInfo("Spoils of Victory", 134, Rarity.COMMON, mage.cards.s.SpoilsOfVictory.class)); - cards.add(new SetCardInfo("Stolen Grain", 75, Rarity.UNCOMMON, mage.cards.s.StolenGrain.class)); - cards.add(new SetCardInfo("Strategic Planning", 51, Rarity.COMMON, mage.cards.s.StrategicPlanning.class)); - cards.add(new SetCardInfo("Sunastian Falconer", 178, Rarity.UNCOMMON, mage.cards.s.SunastianFalconer.class)); - cards.add(new SetCardInfo("Sun Ce, Young Conquerer", 52, Rarity.UNCOMMON, mage.cards.s.SunCeYoungConquerer.class)); - cards.add(new SetCardInfo("Sun Quan, Lord of Wu", 53, Rarity.RARE, mage.cards.s.SunQuanLordOfWu.class)); - cards.add(new SetCardInfo("Swamp", 222, Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Swamp", 223, Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Swamp", 224, Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Tetsuo Umezawa", 179, Rarity.RARE, mage.cards.t.TetsuoUmezawa.class)); - cards.add(new SetCardInfo("The Abyss", 77, Rarity.RARE, mage.cards.t.TheAbyss.class)); - cards.add(new SetCardInfo("The Lady of the Mountain", 180, Rarity.COMMON, mage.cards.t.TheLadyOfTheMountain.class)); - cards.add(new SetCardInfo("The Tabernacle at Pendrell Vale", 212, Rarity.RARE, mage.cards.t.TheTabernacleAtPendrellVale.class)); - cards.add(new SetCardInfo("The Wretched", 78, Rarity.UNCOMMON, mage.cards.t.TheWretched.class)); - cards.add(new SetCardInfo("Three Visits", 135, Rarity.COMMON, mage.cards.t.ThreeVisits.class)); - cards.add(new SetCardInfo("Tobias Andrion", 181, Rarity.COMMON, mage.cards.t.TobiasAndrion.class)); - cards.add(new SetCardInfo("Torsten Von Ursus", 183, Rarity.COMMON, mage.cards.t.TorstenVonUrsus.class)); - cards.add(new SetCardInfo("Tor Wauki", 182, Rarity.UNCOMMON, mage.cards.t.TorWauki.class)); - cards.add(new SetCardInfo("Tracker", 136, Rarity.UNCOMMON, mage.cards.t.Tracker.class)); - cards.add(new SetCardInfo("Trip Wire", 137, Rarity.COMMON, mage.cards.t.TripWire.class)); - cards.add(new SetCardInfo("Tropical Island", 213, Rarity.RARE, mage.cards.t.TropicalIsland.class)); - cards.add(new SetCardInfo("Tuknir Deathlock", 184, Rarity.UNCOMMON, mage.cards.t.TuknirDeathlock.class)); - cards.add(new SetCardInfo("Urborg", 214, Rarity.UNCOMMON, mage.cards.u.Urborg.class)); - cards.add(new SetCardInfo("Vaevictis Asmadi", 185, Rarity.RARE, mage.cards.v.VaevictisAsmadi.class)); - cards.add(new SetCardInfo("Volcanic Island", 215, Rarity.RARE, mage.cards.v.VolcanicIsland.class)); - cards.add(new SetCardInfo("Wall of Light", 27, Rarity.COMMON, mage.cards.w.WallOfLight.class)); - cards.add(new SetCardInfo("Wandering Mage", 186, Rarity.RARE, mage.cards.w.WanderingMage.class)); - cards.add(new SetCardInfo("Wei Elite Companions", 79, Rarity.COMMON, mage.cards.w.WeiEliteCompanions.class)); - cards.add(new SetCardInfo("Wei Infantry", 80, Rarity.COMMON, mage.cards.w.WeiInfantry.class)); - cards.add(new SetCardInfo("Wei Night Raiders", 81, Rarity.UNCOMMON, mage.cards.w.WeiNightRaiders.class)); - cards.add(new SetCardInfo("Wei Strike Force", 82, Rarity.COMMON, mage.cards.w.WeiStrikeForce.class)); - cards.add(new SetCardInfo("Willow Priestess", 138, Rarity.UNCOMMON, mage.cards.w.WillowPriestess.class)); - cards.add(new SetCardInfo("Willow Satyr", 139, Rarity.RARE, mage.cards.w.WillowSatyr.class)); - cards.add(new SetCardInfo("Wormwood Treefolk", 140, Rarity.UNCOMMON, mage.cards.w.WormwoodTreefolk.class)); - cards.add(new SetCardInfo("Wu Elite Cavalry", 54, Rarity.COMMON, mage.cards.w.WuEliteCavalry.class)); - cards.add(new SetCardInfo("Wu Longbowman", 55, Rarity.COMMON, mage.cards.w.WuLongbowman.class)); - cards.add(new SetCardInfo("Wu Warship", 56, Rarity.COMMON, mage.cards.w.WuWarship.class)); - cards.add(new SetCardInfo("Xiahou Dun, the One-Eyed", 83, Rarity.UNCOMMON, mage.cards.x.XiahouDunTheOneEyed.class)); - cards.add(new SetCardInfo("Xira Arien", 187, Rarity.RARE, mage.cards.x.XiraArien.class)); - cards.add(new SetCardInfo("Young Wei Recruits", 84, Rarity.COMMON, mage.cards.y.YoungWeiRecruits.class)); - cards.add(new SetCardInfo("Zhang Fei, Fierce Warrior", 28, Rarity.UNCOMMON, mage.cards.z.ZhangFeiFierceWarrior.class)); - cards.add(new SetCardInfo("Zodiac Dragon", 112, Rarity.RARE, mage.cards.z.ZodiacDragon.class)); - } - +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.sets; + +import mage.cards.ExpansionSet; +import mage.cards.f.FeveredStrength; +import mage.constants.SetType; +import mage.constants.Rarity; +import mage.cards.CardGraphicInfo; + +/** + * + * @author LevelX2 + */ +public class MastersEditionIII extends ExpansionSet { + + private static final MastersEditionIII fINSTANCE = new MastersEditionIII(); + + public static MastersEditionIII getInstance() { + return fINSTANCE; + } + + private MastersEditionIII() { + super("Masters Edition III", "ME3", ExpansionSet.buildDate(2009, 9, 7), SetType.MAGIC_ONLINE); + this.hasBasicLands = true; + this.hasBoosters = true; + this.numBoosterLands = 1; + this.numBoosterCommon = 10; + this.numBoosterUncommon = 3; + this.numBoosterRare = 1; + this.ratioBoosterMythic = 0; + cards.add(new SetCardInfo("Active Volcano", 85, Rarity.UNCOMMON, mage.cards.a.ActiveVolcano.class)); + cards.add(new SetCardInfo("Akron Legionnaire", 1, Rarity.RARE, mage.cards.a.AkronLegionnaire.class)); + cards.add(new SetCardInfo("Amrou Kithkin", 3, Rarity.COMMON, mage.cards.a.AmrouKithkin.class)); + cards.add(new SetCardInfo("Anaba Ancestor", 86, Rarity.COMMON, mage.cards.a.AnabaAncestor.class)); + cards.add(new SetCardInfo("Anaba Spirit Crafter", 87, Rarity.COMMON, mage.cards.a.AnabaSpiritCrafter.class)); + cards.add(new SetCardInfo("Angus Mackenzie", 141, Rarity.RARE, mage.cards.a.AngusMackenzie.class)); + cards.add(new SetCardInfo("Arcades Sabboth", 142, Rarity.RARE, mage.cards.a.ArcadesSabboth.class)); + cards.add(new SetCardInfo("Arena of the Ancients", 188, Rarity.RARE, mage.cards.a.ArenaOfTheAncients.class)); + cards.add(new SetCardInfo("Ashes to Ashes", 58, Rarity.UNCOMMON, mage.cards.a.AshesToAshes.class)); + cards.add(new SetCardInfo("Astrolabe", 189, Rarity.COMMON, mage.cards.a.Astrolabe.class)); + cards.add(new SetCardInfo("Barktooth Warbeard", 144, Rarity.COMMON, mage.cards.b.BarktoothWarbeard.class)); + cards.add(new SetCardInfo("Barl's Cage", 190, Rarity.RARE, mage.cards.b.BarlsCage.class)); + cards.add(new SetCardInfo("Bartel Runeaxe", 145, Rarity.UNCOMMON, mage.cards.b.BartelRuneaxe.class)); + cards.add(new SetCardInfo("Bayou", 204, Rarity.RARE, mage.cards.b.Bayou.class)); + cards.add(new SetCardInfo("Bazaar of Baghdad", 205, Rarity.RARE, mage.cards.b.BazaarOfBaghdad.class)); + cards.add(new SetCardInfo("Black Vise", 191, Rarity.RARE, mage.cards.b.BlackVise.class)); + cards.add(new SetCardInfo("Blood Lust", 88, Rarity.COMMON, mage.cards.b.BloodLust.class)); + cards.add(new SetCardInfo("Bone Flute", 192, Rarity.COMMON, mage.cards.b.BoneFlute.class)); + cards.add(new SetCardInfo("Boomerang", 30, Rarity.COMMON, mage.cards.b.Boomerang.class)); + cards.add(new SetCardInfo("Boris Devilboon", 146, Rarity.UNCOMMON, mage.cards.b.BorisDevilboon.class)); + cards.add(new SetCardInfo("Borrowing 100,000 Arrows", 31, Rarity.UNCOMMON, mage.cards.b.Borrowing100000Arrows.class)); + cards.add(new SetCardInfo("Brilliant Plan", 32, Rarity.COMMON, mage.cards.b.BrilliantPlan.class)); + cards.add(new SetCardInfo("Burning of Xinye", 89, Rarity.RARE, mage.cards.b.BurningOfXinye.class)); + cards.add(new SetCardInfo("Capture of Jingzhou", 33, Rarity.RARE, mage.cards.c.CaptureOfJingzhou.class)); + cards.add(new SetCardInfo("Carrion Ants", 60, Rarity.UNCOMMON, mage.cards.c.CarrionAnts.class)); + cards.add(new SetCardInfo("Chain Lightning", 90, Rarity.COMMON, mage.cards.c.ChainLightning.class)); + cards.add(new SetCardInfo("Chromium", 147, Rarity.RARE, mage.cards.c.Chromium.class)); + cards.add(new SetCardInfo("Cinder Storm", 91, Rarity.UNCOMMON, mage.cards.c.CinderStorm.class)); + cards.add(new SetCardInfo("City of Shadows", 206, Rarity.RARE, mage.cards.c.CityOfShadows.class)); + cards.add(new SetCardInfo("Cleanse", 5, Rarity.RARE, mage.cards.c.Cleanse.class)); + cards.add(new SetCardInfo("Coal Golem", 193, Rarity.COMMON, mage.cards.c.CoalGolem.class)); + cards.add(new SetCardInfo("Concordant Crossroads", 114, Rarity.RARE, mage.cards.c.ConcordantCrossroads.class)); + cards.add(new SetCardInfo("Corrupt Eunuchs", 92, Rarity.UNCOMMON, mage.cards.c.CorruptEunuchs.class)); + cards.add(new SetCardInfo("Cosmic Horror", 61, Rarity.RARE, mage.cards.c.CosmicHorror.class)); + cards.add(new SetCardInfo("Crimson Kobolds", 93, Rarity.COMMON, mage.cards.c.CrimsonKobolds.class)); + cards.add(new SetCardInfo("Crimson Manticore", 94, Rarity.UNCOMMON, mage.cards.c.CrimsonManticore.class)); + cards.add(new SetCardInfo("Dance of Many", 34, Rarity.UNCOMMON, mage.cards.d.DanceOfMany.class)); + cards.add(new SetCardInfo("D'Avenant Archer", 6, Rarity.COMMON, mage.cards.d.DAvenantArcher.class)); + cards.add(new SetCardInfo("Demonic Torment", 62, Rarity.COMMON, mage.cards.d.DemonicTorment.class)); + cards.add(new SetCardInfo("Desert Twister", 115, Rarity.UNCOMMON, mage.cards.d.DesertTwister.class)); + cards.add(new SetCardInfo("Desperate Charge", 63, Rarity.COMMON, mage.cards.d.DesperateCharge.class)); + cards.add(new SetCardInfo("Didgeridoo", 194, Rarity.UNCOMMON, mage.cards.d.Didgeridoo.class)); + cards.add(new SetCardInfo("Disenchant", 7, Rarity.COMMON, mage.cards.d.Disenchant.class)); + cards.add(new SetCardInfo("Divine Intervention", 8, Rarity.RARE, mage.cards.d.DivineIntervention.class)); + cards.add(new SetCardInfo("Dong Zhou, the Tyrant", 96, Rarity.RARE, mage.cards.d.DongZhouTheTyrant.class)); + cards.add(new SetCardInfo("Elves of Deep Shadow", 116, Rarity.COMMON, mage.cards.e.ElvesOfDeepShadow.class)); + cards.add(new SetCardInfo("Evil Presence", 64, Rarity.COMMON, mage.cards.e.EvilPresence.class)); + cards.add(new SetCardInfo("Exorcist", 10, Rarity.UNCOMMON, mage.cards.e.Exorcist.class)); + cards.add(new SetCardInfo("Faerie Noble", 117, Rarity.UNCOMMON, mage.cards.f.FaerieNoble.class)); + cards.add(new SetCardInfo("False Defeat", 11, Rarity.UNCOMMON, mage.cards.f.FalseDefeat.class)); + cards.add(new SetCardInfo("Famine", 65, Rarity.UNCOMMON, mage.cards.f.Famine.class)); + cards.add(new SetCardInfo("Fellwar Stone", 195, Rarity.COMMON, mage.cards.f.FellwarStone.class)); + cards.add(new SetCardInfo("Fevered Strength", 66, Rarity.COMMON, FeveredStrength.class)); + cards.add(new SetCardInfo("Fire Ambush", 97, Rarity.COMMON, mage.cards.f.FireAmbush.class)); + cards.add(new SetCardInfo("Fire Drake", 98, Rarity.COMMON, mage.cards.f.FireDrake.class)); + cards.add(new SetCardInfo("Fire Sprites", 118, Rarity.COMMON, mage.cards.f.FireSprites.class)); + cards.add(new SetCardInfo("Flash Flood", 35, Rarity.UNCOMMON, mage.cards.f.FlashFlood.class)); + cards.add(new SetCardInfo("Forced Retreat", 37, Rarity.COMMON, mage.cards.f.ForcedRetreat.class)); + cards.add(new SetCardInfo("Force Spike", 36, Rarity.COMMON, mage.cards.f.ForceSpike.class)); + cards.add(new SetCardInfo("Forest", 228, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Forest", 229, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Forest", 230, Rarity.LAND, mage.cards.basiclands.Forest.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Frost Giant", 101, Rarity.UNCOMMON, mage.cards.f.FrostGiant.class)); + cards.add(new SetCardInfo("Gaea's Touch", 120, Rarity.UNCOMMON, mage.cards.g.GaeasTouch.class)); + cards.add(new SetCardInfo("Ghostly Visit", 67, Rarity.COMMON, mage.cards.g.GhostlyVisit.class)); + cards.add(new SetCardInfo("Ghosts of the Damned", 68, Rarity.COMMON, mage.cards.g.GhostsOfTheDamned.class)); + cards.add(new SetCardInfo("Giant Growth", 121, Rarity.COMMON, mage.cards.g.GiantGrowth.class)); + cards.add(new SetCardInfo("Grim Tutor", 69, Rarity.RARE, mage.cards.g.GrimTutor.class)); + cards.add(new SetCardInfo("Guan Yu's 1,000-Li March", 13, Rarity.RARE, mage.cards.g.GuanYus1000LiMarch.class)); + cards.add(new SetCardInfo("Guan Yu, Sainted Warrior", 12, Rarity.UNCOMMON, mage.cards.g.GuanYuSaintedWarrior.class)); + cards.add(new SetCardInfo("Gwendlyn Di Corci", 149, Rarity.RARE, mage.cards.g.GwendlynDiCorci.class)); + cards.add(new SetCardInfo("Hazezon Tamar", 151, Rarity.RARE, mage.cards.h.HazezonTamar.class)); + cards.add(new SetCardInfo("Heal", 14, Rarity.COMMON, mage.cards.h.Heal.class)); + cards.add(new SetCardInfo("Hellfire", 70, Rarity.RARE, mage.cards.h.Hellfire.class)); + cards.add(new SetCardInfo("Hua Tuo, Honored Physician", 123, Rarity.RARE, mage.cards.h.HuaTuoHonoredPhysician.class)); + cards.add(new SetCardInfo("Hunding Gjornersen", 152, Rarity.UNCOMMON, mage.cards.h.HundingGjornersen.class)); + cards.add(new SetCardInfo("Hunting Cheetah", 124, Rarity.COMMON, mage.cards.h.HuntingCheetah.class)); + cards.add(new SetCardInfo("Hurloon Minotaur", 102, Rarity.COMMON, mage.cards.h.HurloonMinotaur.class)); + cards.add(new SetCardInfo("Immolation", 103, Rarity.COMMON, mage.cards.i.Immolation.class)); + cards.add(new SetCardInfo("Infuse", 38, Rarity.COMMON, mage.cards.i.Infuse.class)); + cards.add(new SetCardInfo("Island", 219, Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Island", 220, Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Island", 221, Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Ivory Guardians", 15, Rarity.UNCOMMON, mage.cards.i.IvoryGuardians.class)); + cards.add(new SetCardInfo("Jedit Ojanen", 153, Rarity.COMMON, mage.cards.j.JeditOjanen.class)); + cards.add(new SetCardInfo("Jerrard of the Closed Fist", 154, Rarity.COMMON, mage.cards.j.JerrardOfTheClosedFist.class)); + cards.add(new SetCardInfo("Jungle Lion", 125, Rarity.COMMON, mage.cards.j.JungleLion.class)); + cards.add(new SetCardInfo("Karakas", 208, Rarity.RARE, mage.cards.k.Karakas.class)); + cards.add(new SetCardInfo("Kei Takahashi", 155, Rarity.UNCOMMON, mage.cards.k.KeiTakahashi.class)); + cards.add(new SetCardInfo("Killer Bees", 126, Rarity.UNCOMMON, mage.cards.k.KillerBees.class)); + cards.add(new SetCardInfo("Kobold Drill Sergeant", 104, Rarity.UNCOMMON, mage.cards.k.KoboldDrillSergeant.class)); + cards.add(new SetCardInfo("Kobold Overlord", 105, Rarity.UNCOMMON, mage.cards.k.KoboldOverlord.class)); + cards.add(new SetCardInfo("Kobolds of Kher Keep", 107, Rarity.COMMON, mage.cards.k.KoboldsOfKherKeep.class)); + cards.add(new SetCardInfo("Kobold Taskmaster", 106, Rarity.COMMON, mage.cards.k.KoboldTaskmaster.class)); + cards.add(new SetCardInfo("Kongming, 'Sleeping Dragon'", 16, Rarity.RARE, mage.cards.k.KongmingSleepingDragon.class)); + cards.add(new SetCardInfo("Lady Caleria", 157, Rarity.UNCOMMON, mage.cards.l.LadyCaleria.class)); + cards.add(new SetCardInfo("Lady Evangela", 158, Rarity.UNCOMMON, mage.cards.l.LadyEvangela.class)); + cards.add(new SetCardInfo("Lady Orca", 159, Rarity.COMMON, mage.cards.l.LadyOrca.class)); + cards.add(new SetCardInfo("Land Tax", 17, Rarity.RARE, mage.cards.l.LandTax.class)); + cards.add(new SetCardInfo("Lightning Blow", 18, Rarity.COMMON, mage.cards.l.LightningBlow.class)); + cards.add(new SetCardInfo("Liu Bei, Lord of Shu", 19, Rarity.RARE, mage.cards.l.LiuBeiLordOfShu.class)); + cards.add(new SetCardInfo("Living Plane", 127, Rarity.RARE, mage.cards.l.LivingPlane.class)); + cards.add(new SetCardInfo("Livonya Silone", 160, Rarity.UNCOMMON, mage.cards.l.LivonyaSilone.class)); + cards.add(new SetCardInfo("Loyal Retainers", 20, Rarity.UNCOMMON, mage.cards.l.LoyalRetainers.class)); + cards.add(new SetCardInfo("Lu Bu, Master-at-Arms", 108, Rarity.RARE, mage.cards.l.LuBuMasterAtArms.class)); + cards.add(new SetCardInfo("Lu Meng, Wu General", 41, Rarity.UNCOMMON, mage.cards.l.LuMengWuGeneral.class)); + cards.add(new SetCardInfo("Lu Xun, Scholar General", 42, Rarity.UNCOMMON, mage.cards.l.LuXunScholarGeneral.class)); + cards.add(new SetCardInfo("Mana Drain", 43, Rarity.RARE, mage.cards.m.ManaDrain.class)); + cards.add(new SetCardInfo("Mana Vortex", 44, Rarity.RARE, mage.cards.m.ManaVortex.class)); + cards.add(new SetCardInfo("Marhault Elsdragon", 161, Rarity.UNCOMMON, mage.cards.m.MarhaultElsdragon.class)); + cards.add(new SetCardInfo("Meng Huo, Barbarian King", 128, Rarity.RARE, mage.cards.m.MengHuoBarbarianKing.class)); + cards.add(new SetCardInfo("Meng Huo's Horde", 129, Rarity.COMMON, mage.cards.m.MengHuosHorde.class)); + cards.add(new SetCardInfo("Mind Twist", 72, Rarity.RARE, mage.cards.m.MindTwist.class)); + cards.add(new SetCardInfo("Mountain", 225, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Mountain", 226, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Mountain", 227, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Nether Void", 73, Rarity.RARE, mage.cards.n.NetherVoid.class)); + cards.add(new SetCardInfo("Nicol Bolas", 163, Rarity.RARE, mage.cards.n.NicolBolas.class)); + cards.add(new SetCardInfo("Old Man of the Sea", 45, Rarity.RARE, mage.cards.o.OldManOfTheSea.class)); + cards.add(new SetCardInfo("Palladia-Mors", 164, Rarity.RARE, mage.cards.p.PalladiaMors.class)); + cards.add(new SetCardInfo("Pavel Maliki", 165, Rarity.UNCOMMON, mage.cards.p.PavelMaliki.class)); + cards.add(new SetCardInfo("Peach Garden Oath", 22, Rarity.COMMON, mage.cards.p.PeachGardenOath.class)); + cards.add(new SetCardInfo("Plains", 216, Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Plains", 217, Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Plains", 218, Rarity.LAND, mage.cards.basiclands.Plains.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Plateau", 209, Rarity.RARE, mage.cards.p.Plateau.class)); + cards.add(new SetCardInfo("Princess Lucrezia", 166, Rarity.UNCOMMON, mage.cards.p.PrincessLucrezia.class)); + cards.add(new SetCardInfo("Raging Minotaur", 109, Rarity.COMMON, mage.cards.r.RagingMinotaur.class)); + cards.add(new SetCardInfo("Ragnar", 167, Rarity.UNCOMMON, mage.cards.r.Ragnar.class)); + cards.add(new SetCardInfo("Ramirez DePietro", 168, Rarity.COMMON, mage.cards.r.RamirezDePietro.class)); + cards.add(new SetCardInfo("Ramses Overdark", 169, Rarity.UNCOMMON, mage.cards.r.RamsesOverdark.class)); + cards.add(new SetCardInfo("Rasputin Dreamweaver", 170, Rarity.RARE, mage.cards.r.RasputinDreamweaver.class)); + cards.add(new SetCardInfo("Recall", 46, Rarity.UNCOMMON, mage.cards.r.Recall.class)); + cards.add(new SetCardInfo("Reincarnation", 130, Rarity.UNCOMMON, mage.cards.r.Reincarnation.class)); + cards.add(new SetCardInfo("Remove Soul", 47, Rarity.COMMON, mage.cards.r.RemoveSoul.class)); + cards.add(new SetCardInfo("Reset", 48, Rarity.RARE, mage.cards.r.Reset.class)); + cards.add(new SetCardInfo("Reveka, Wizard Savant", 49, Rarity.UNCOMMON, mage.cards.r.RevekaWizardSavant.class)); + cards.add(new SetCardInfo("Riding the Dilu Horse", 131, Rarity.UNCOMMON, mage.cards.r.RidingTheDiluHorse.class)); + cards.add(new SetCardInfo("Riven Turnbull", 171, Rarity.UNCOMMON, mage.cards.r.RivenTurnbull.class)); + cards.add(new SetCardInfo("Rolling Earthquake", 110, Rarity.RARE, mage.cards.r.RollingEarthquake.class)); + cards.add(new SetCardInfo("Rubinia Soulsinger", 173, Rarity.RARE, mage.cards.r.RubiniaSoulsinger.class)); + cards.add(new SetCardInfo("Scrubland", 210, Rarity.RARE, mage.cards.s.Scrubland.class)); + cards.add(new SetCardInfo("Scryb Sprites", 132, Rarity.COMMON, mage.cards.s.ScrybSprites.class)); + cards.add(new SetCardInfo("Shu Cavalry", 23, Rarity.COMMON, mage.cards.s.ShuCavalry.class)); + cards.add(new SetCardInfo("Shu Elite Companions", 24, Rarity.COMMON, mage.cards.s.ShuEliteCompanions.class)); + cards.add(new SetCardInfo("Shu General", 25, Rarity.COMMON, mage.cards.s.ShuGeneral.class)); + cards.add(new SetCardInfo("Shu Soldier-Farmers", 26, Rarity.COMMON, mage.cards.s.ShuSoldierFarmers.class)); + cards.add(new SetCardInfo("Sir Shandlar of Eberyn", 174, Rarity.COMMON, mage.cards.s.SirShandlarOfEberyn.class)); + cards.add(new SetCardInfo("Sivitri Scarzam", 175, Rarity.COMMON, mage.cards.s.SivitriScarzam.class)); + cards.add(new SetCardInfo("Slashing Tiger", 133, Rarity.COMMON, mage.cards.s.SlashingTiger.class)); + cards.add(new SetCardInfo("Sol Grail", 201, Rarity.COMMON, mage.cards.s.SolGrail.class)); + cards.add(new SetCardInfo("Spirit Shackle", 74, Rarity.COMMON, mage.cards.s.SpiritShackle.class)); + cards.add(new SetCardInfo("Spoils of Victory", 134, Rarity.COMMON, mage.cards.s.SpoilsOfVictory.class)); + cards.add(new SetCardInfo("Stolen Grain", 75, Rarity.UNCOMMON, mage.cards.s.StolenGrain.class)); + cards.add(new SetCardInfo("Strategic Planning", 51, Rarity.COMMON, mage.cards.s.StrategicPlanning.class)); + cards.add(new SetCardInfo("Sunastian Falconer", 178, Rarity.UNCOMMON, mage.cards.s.SunastianFalconer.class)); + cards.add(new SetCardInfo("Sun Ce, Young Conquerer", 52, Rarity.UNCOMMON, mage.cards.s.SunCeYoungConquerer.class)); + cards.add(new SetCardInfo("Sun Quan, Lord of Wu", 53, Rarity.RARE, mage.cards.s.SunQuanLordOfWu.class)); + cards.add(new SetCardInfo("Swamp", 222, Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Swamp", 223, Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Swamp", 224, Rarity.LAND, mage.cards.basiclands.Swamp.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Tetsuo Umezawa", 179, Rarity.RARE, mage.cards.t.TetsuoUmezawa.class)); + cards.add(new SetCardInfo("The Abyss", 77, Rarity.RARE, mage.cards.t.TheAbyss.class)); + cards.add(new SetCardInfo("The Lady of the Mountain", 180, Rarity.COMMON, mage.cards.t.TheLadyOfTheMountain.class)); + cards.add(new SetCardInfo("The Tabernacle at Pendrell Vale", 212, Rarity.RARE, mage.cards.t.TheTabernacleAtPendrellVale.class)); + cards.add(new SetCardInfo("The Wretched", 78, Rarity.UNCOMMON, mage.cards.t.TheWretched.class)); + cards.add(new SetCardInfo("Three Visits", 135, Rarity.COMMON, mage.cards.t.ThreeVisits.class)); + cards.add(new SetCardInfo("Tobias Andrion", 181, Rarity.COMMON, mage.cards.t.TobiasAndrion.class)); + cards.add(new SetCardInfo("Torsten Von Ursus", 183, Rarity.COMMON, mage.cards.t.TorstenVonUrsus.class)); + cards.add(new SetCardInfo("Tor Wauki", 182, Rarity.UNCOMMON, mage.cards.t.TorWauki.class)); + cards.add(new SetCardInfo("Tracker", 136, Rarity.UNCOMMON, mage.cards.t.Tracker.class)); + cards.add(new SetCardInfo("Trip Wire", 137, Rarity.COMMON, mage.cards.t.TripWire.class)); + cards.add(new SetCardInfo("Tropical Island", 213, Rarity.RARE, mage.cards.t.TropicalIsland.class)); + cards.add(new SetCardInfo("Tuknir Deathlock", 184, Rarity.UNCOMMON, mage.cards.t.TuknirDeathlock.class)); + cards.add(new SetCardInfo("Urborg", 214, Rarity.UNCOMMON, mage.cards.u.Urborg.class)); + cards.add(new SetCardInfo("Vaevictis Asmadi", 185, Rarity.RARE, mage.cards.v.VaevictisAsmadi.class)); + cards.add(new SetCardInfo("Volcanic Island", 215, Rarity.RARE, mage.cards.v.VolcanicIsland.class)); + cards.add(new SetCardInfo("Wall of Light", 27, Rarity.COMMON, mage.cards.w.WallOfLight.class)); + cards.add(new SetCardInfo("Wandering Mage", 186, Rarity.RARE, mage.cards.w.WanderingMage.class)); + cards.add(new SetCardInfo("Wei Elite Companions", 79, Rarity.COMMON, mage.cards.w.WeiEliteCompanions.class)); + cards.add(new SetCardInfo("Wei Infantry", 80, Rarity.COMMON, mage.cards.w.WeiInfantry.class)); + cards.add(new SetCardInfo("Wei Night Raiders", 81, Rarity.UNCOMMON, mage.cards.w.WeiNightRaiders.class)); + cards.add(new SetCardInfo("Wei Strike Force", 82, Rarity.COMMON, mage.cards.w.WeiStrikeForce.class)); + cards.add(new SetCardInfo("Willow Priestess", 138, Rarity.UNCOMMON, mage.cards.w.WillowPriestess.class)); + cards.add(new SetCardInfo("Willow Satyr", 139, Rarity.RARE, mage.cards.w.WillowSatyr.class)); + cards.add(new SetCardInfo("Wormwood Treefolk", 140, Rarity.UNCOMMON, mage.cards.w.WormwoodTreefolk.class)); + cards.add(new SetCardInfo("Wu Elite Cavalry", 54, Rarity.COMMON, mage.cards.w.WuEliteCavalry.class)); + cards.add(new SetCardInfo("Wu Longbowman", 55, Rarity.COMMON, mage.cards.w.WuLongbowman.class)); + cards.add(new SetCardInfo("Wu Warship", 56, Rarity.COMMON, mage.cards.w.WuWarship.class)); + cards.add(new SetCardInfo("Xiahou Dun, the One-Eyed", 83, Rarity.UNCOMMON, mage.cards.x.XiahouDunTheOneEyed.class)); + cards.add(new SetCardInfo("Xira Arien", 187, Rarity.RARE, mage.cards.x.XiraArien.class)); + cards.add(new SetCardInfo("Young Wei Recruits", 84, Rarity.COMMON, mage.cards.y.YoungWeiRecruits.class)); + cards.add(new SetCardInfo("Zhang Fei, Fierce Warrior", 28, Rarity.UNCOMMON, mage.cards.z.ZhangFeiFierceWarrior.class)); + cards.add(new SetCardInfo("Zodiac Dragon", 112, Rarity.RARE, mage.cards.z.ZodiacDragon.class)); + } + } \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/MercadianMasques.java b/Mage.Sets/src/mage/sets/MercadianMasques.java index 8662c7b524f..5c3d633d870 100644 --- a/Mage.Sets/src/mage/sets/MercadianMasques.java +++ b/Mage.Sets/src/mage/sets/MercadianMasques.java @@ -71,6 +71,7 @@ public class MercadianMasques extends ExpansionSet { cards.add(new SetCardInfo("Bog Witch", 118, Rarity.COMMON, mage.cards.b.BogWitch.class)); cards.add(new SetCardInfo("Brainstorm", 61, Rarity.COMMON, mage.cards.b.Brainstorm.class)); cards.add(new SetCardInfo("Bribery", 62, Rarity.RARE, mage.cards.b.Bribery.class)); + cards.add(new SetCardInfo("Buoyancy", 63, Rarity.COMMON, mage.cards.b.Buoyancy.class)); cards.add(new SetCardInfo("Cackling Witch", 119, Rarity.UNCOMMON, mage.cards.c.CacklingWitch.class)); cards.add(new SetCardInfo("Cateran Brute", 120, Rarity.COMMON, mage.cards.c.CateranBrute.class)); cards.add(new SetCardInfo("Cateran Enforcer", 121, Rarity.UNCOMMON, mage.cards.c.CateranEnforcer.class)); @@ -139,6 +140,7 @@ public class MercadianMasques extends ExpansionSet { cards.add(new SetCardInfo("Fountain of Cho", 317, Rarity.UNCOMMON, mage.cards.f.FountainOfCho.class)); cards.add(new SetCardInfo("Fountain Watch", 19, Rarity.RARE, mage.cards.f.FountainWatch.class)); cards.add(new SetCardInfo("Fresh Volunteers", 20, Rarity.COMMON, mage.cards.f.FreshVolunteers.class)); + cards.add(new SetCardInfo("Furious Assault", 191, Rarity.COMMON, mage.cards.f.FuriousAssault.class)); cards.add(new SetCardInfo("Gerrard's Irregulars", 192, Rarity.COMMON, mage.cards.g.GerrardsIrregulars.class)); cards.add(new SetCardInfo("Ghoul's Feast", 137, Rarity.UNCOMMON, mage.cards.g.GhoulsFeast.class)); cards.add(new SetCardInfo("Giant Caterpillar", 249, Rarity.COMMON, mage.cards.g.GiantCaterpillar.class)); diff --git a/Mage.Sets/src/mage/sets/Nemesis.java b/Mage.Sets/src/mage/sets/Nemesis.java index c694e00ca83..acf96c9fc58 100644 --- a/Mage.Sets/src/mage/sets/Nemesis.java +++ b/Mage.Sets/src/mage/sets/Nemesis.java @@ -81,6 +81,7 @@ public class Nemesis extends ExpansionSet { cards.add(new SetCardInfo("Flowstone Crusher", 81, Rarity.COMMON, mage.cards.f.FlowstoneCrusher.class)); cards.add(new SetCardInfo("Flowstone Overseer", 82, Rarity.RARE, mage.cards.f.FlowstoneOverseer.class)); cards.add(new SetCardInfo("Flowstone Slide", 83, Rarity.RARE, mage.cards.f.FlowstoneSlide.class)); + cards.add(new SetCardInfo("Flowstone Thopter", 132, Rarity.UNCOMMON, mage.cards.f.FlowstoneThopter.class)); cards.add(new SetCardInfo("Flowstone Wall", 86, Rarity.COMMON, mage.cards.f.FlowstoneWall.class)); cards.add(new SetCardInfo("Infiltrate", 33, Rarity.COMMON, mage.cards.i.Infiltrate.class)); cards.add(new SetCardInfo("Jolting Merfolk", 34, Rarity.UNCOMMON, mage.cards.j.JoltingMerfolk.class)); @@ -96,6 +97,7 @@ public class Nemesis extends ExpansionSet { cards.add(new SetCardInfo("Mogg Salvage", 94, Rarity.UNCOMMON, mage.cards.m.MoggSalvage.class)); cards.add(new SetCardInfo("Murderous Betrayal", 61, Rarity.RARE, mage.cards.m.MurderousBetrayal.class)); cards.add(new SetCardInfo("Netter en-Dal", 13, Rarity.COMMON, mage.cards.n.NetterEnDal.class)); + cards.add(new SetCardInfo("Noble Stand", 14, Rarity.UNCOMMON, mage.cards.n.NobleStand.class)); cards.add(new SetCardInfo("Off Balance", 15, Rarity.COMMON, mage.cards.o.OffBalance.class)); cards.add(new SetCardInfo("Oracle's Attendants", 16, Rarity.RARE, mage.cards.o.OraclesAttendants.class)); cards.add(new SetCardInfo("Oraxid", 35, Rarity.COMMON, mage.cards.o.Oraxid.class)); @@ -142,6 +144,7 @@ public class Nemesis extends ExpansionSet { cards.add(new SetCardInfo("Stampede Driver", 122, Rarity.UNCOMMON, mage.cards.s.StampedeDriver.class)); cards.add(new SetCardInfo("Stronghold Discipline", 73, Rarity.COMMON, mage.cards.s.StrongholdDiscipline.class)); cards.add(new SetCardInfo("Stronghold Gambit", 100, Rarity.RARE, mage.cards.s.StrongholdGambit.class)); + cards.add(new SetCardInfo("Stronghold Machinist", 46, Rarity.UNCOMMON, mage.cards.s.StrongholdMachinist.class)); cards.add(new SetCardInfo("Stronghold Zeppelin", 47, Rarity.UNCOMMON, mage.cards.s.StrongholdZeppelin.class)); cards.add(new SetCardInfo("Submerge", 48, Rarity.UNCOMMON, mage.cards.s.Submerge.class)); cards.add(new SetCardInfo("Tangle Wire", 139, Rarity.RARE, mage.cards.t.TangleWire.class)); diff --git a/Mage.Sets/src/mage/sets/OathOfTheGatewatch.java b/Mage.Sets/src/mage/sets/OathOfTheGatewatch.java index baf3c52bd11..fd9ba8fc68b 100644 --- a/Mage.Sets/src/mage/sets/OathOfTheGatewatch.java +++ b/Mage.Sets/src/mage/sets/OathOfTheGatewatch.java @@ -7,14 +7,15 @@ package mage.sets; import java.util.ArrayList; import java.util.List; +import mage.cards.CardGraphicInfo; import mage.cards.ExpansionSet; +import mage.cards.FrameStyle; import mage.cards.repository.CardCriteria; import mage.cards.repository.CardInfo; import mage.cards.repository.CardRepository; import mage.cards.w.Wastes; -import mage.constants.SetType; import mage.constants.Rarity; -import mage.cards.CardGraphicInfo; +import mage.constants.SetType; /** * @@ -218,8 +219,8 @@ public class OathOfTheGatewatch extends ExpansionSet { cards.add(new SetCardInfo("Wandering Fumarole", 182, Rarity.RARE, mage.cards.w.WanderingFumarole.class)); cards.add(new SetCardInfo("Warden of Geometries", 11, Rarity.COMMON, mage.cards.w.WardenOfGeometries.class)); cards.add(new SetCardInfo("Warping Wail", 12, Rarity.UNCOMMON, mage.cards.w.WarpingWail.class)); - cards.add(new SetCardInfo("Wastes", 183, Rarity.COMMON, Wastes.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Wastes", 184, Rarity.COMMON, Wastes.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Wastes", 183, Rarity.COMMON, Wastes.class, new CardGraphicInfo(FrameStyle.BFZ_FULL_ART_BASIC, true))); + cards.add(new SetCardInfo("Wastes", 184, Rarity.COMMON, Wastes.class, new CardGraphicInfo(FrameStyle.BFZ_FULL_ART_BASIC, true))); cards.add(new SetCardInfo("Weapons Trainer", 160, Rarity.UNCOMMON, mage.cards.w.WeaponsTrainer.class)); cards.add(new SetCardInfo("Witness the End", 82, Rarity.COMMON, mage.cards.w.WitnessTheEnd.class)); cards.add(new SetCardInfo("World Breaker", 126, Rarity.MYTHIC, mage.cards.w.WorldBreaker.class)); diff --git a/Mage.Sets/src/mage/sets/Onslaught.java b/Mage.Sets/src/mage/sets/Onslaught.java index 669b129dfb7..4f78924a0a7 100644 --- a/Mage.Sets/src/mage/sets/Onslaught.java +++ b/Mage.Sets/src/mage/sets/Onslaught.java @@ -53,10 +53,9 @@ public class Onslaught extends ExpansionSet { cards.add(new SetCardInfo("Blackmail", 127, Rarity.UNCOMMON, mage.cards.b.Blackmail.class)); cards.add(new SetCardInfo("Blatant Thievery", 71, Rarity.RARE, mage.cards.b.BlatantThievery.class)); cards.add(new SetCardInfo("Blistering Firecat", 189, Rarity.RARE, mage.cards.b.BlisteringFirecat.class)); - cards.add(new SetCardInfo("Bloodline Shaman", 249, Rarity.UNCOMMON, mage.cards.b.BloodlineShaman.class)); - cards.add(new SetCardInfo("Bloodstained Mire", 313, Rarity.RARE, mage.cards.b.BloodstainedMire.class, new CardGraphicInfo(new ObjectColor("RB"), null, - false))); - cards.add(new SetCardInfo("Bloodline Shaman", 249, Rarity.UNCOMMON, mage.cards.b.BloodlineShaman.class)); + cards.add(new SetCardInfo("Bloodline Shaman", 249, Rarity.UNCOMMON, mage.cards.b.BloodlineShaman.class)); + cards.add(new SetCardInfo("Bloodstained Mire", 313, Rarity.RARE, mage.cards.b.BloodstainedMire.class, new CardGraphicInfo(new ObjectColor("RB"), null,false))); + cards.add(new SetCardInfo("Bloodline Shaman", 249, Rarity.UNCOMMON, mage.cards.b.BloodlineShaman.class)); cards.add(new SetCardInfo("Boneknitter", 128, Rarity.UNCOMMON, mage.cards.b.Boneknitter.class)); cards.add(new SetCardInfo("Brightstone Ritual", 191, Rarity.COMMON, mage.cards.b.BrightstoneRitual.class)); cards.add(new SetCardInfo("Broodhatch Nantuko", 250, Rarity.UNCOMMON, mage.cards.b.BroodhatchNantuko.class)); @@ -289,6 +288,7 @@ public class Onslaught extends ExpansionSet { cards.add(new SetCardInfo("True Believer", 57, Rarity.RARE, mage.cards.t.TrueBeliever.class)); cards.add(new SetCardInfo("Undead Gladiator", 178, Rarity.RARE, mage.cards.u.UndeadGladiator.class)); cards.add(new SetCardInfo("Unholy Grotto", 327, Rarity.RARE, mage.cards.u.UnholyGrotto.class)); + cards.add(new SetCardInfo("Venomspout Brackus", 295, Rarity.UNCOMMON, mage.cards.v.VenomspoutBrackus.class)); cards.add(new SetCardInfo("Visara the Dreadful", 179, Rarity.RARE, mage.cards.v.VisaraTheDreadful.class)); cards.add(new SetCardInfo("Vitality Charm", 296, Rarity.COMMON, mage.cards.v.VitalityCharm.class)); cards.add(new SetCardInfo("Voice of the Woods", 297, Rarity.RARE, mage.cards.v.VoiceOfTheWoods.class)); @@ -301,17 +301,17 @@ public class Onslaught extends ExpansionSet { cards.add(new SetCardInfo("Wellwisher", 300, Rarity.COMMON, mage.cards.w.Wellwisher.class)); cards.add(new SetCardInfo("Wheel and Deal", 121, Rarity.RARE, mage.cards.w.WheelAndDeal.class)); cards.add(new SetCardInfo("Whipcorder", 60, Rarity.UNCOMMON, mage.cards.w.Whipcorder.class)); - cards.add(new SetCardInfo("Windswept Heath", 328, Rarity.RARE, mage.cards.w.WindsweptHeath.class, new CardGraphicInfo(new ObjectColor("GW"), null, - false))); - cards.add(new SetCardInfo("Bloodline Shaman", 249, Rarity.UNCOMMON, mage.cards.b.BloodlineShaman.class)); + cards.add(new SetCardInfo("Windswept Heath", 328, Rarity.RARE, mage.cards.w.WindsweptHeath.class, new CardGraphicInfo(new ObjectColor("GW"), null, false))); + cards.add(new SetCardInfo("Bloodline Shaman", 249, Rarity.UNCOMMON, mage.cards.b.BloodlineShaman.class)); + cards.add(new SetCardInfo("Venomspout Brackus", 295, Rarity.UNCOMMON, mage.cards.v.VenomspoutBrackus.class)); cards.add(new SetCardInfo("Wirewood Elf", 301, Rarity.COMMON, mage.cards.w.WirewoodElf.class)); cards.add(new SetCardInfo("Wirewood Herald", 302, Rarity.COMMON, mage.cards.w.WirewoodHerald.class)); cards.add(new SetCardInfo("Wirewood Lodge", 329, Rarity.RARE, mage.cards.w.WirewoodLodge.class)); cards.add(new SetCardInfo("Wirewood Pride", 303, Rarity.COMMON, mage.cards.w.WirewoodPride.class)); cards.add(new SetCardInfo("Wirewood Savage", 304, Rarity.COMMON, mage.cards.w.WirewoodSavage.class)); - cards.add(new SetCardInfo("Wooded Foothills", 330, Rarity.RARE, mage.cards.w.WoodedFoothills.class, new CardGraphicInfo(new ObjectColor("RG"), null, - false))); - cards.add(new SetCardInfo("Bloodline Shaman", 249, Rarity.UNCOMMON, mage.cards.b.BloodlineShaman.class)); + cards.add(new SetCardInfo("Wooded Foothills", 330, Rarity.RARE, mage.cards.w.WoodedFoothills.class, new CardGraphicInfo(new ObjectColor("RG"), null, false))); + cards.add(new SetCardInfo("Bloodline Shaman", 249, Rarity.UNCOMMON, mage.cards.b.BloodlineShaman.class)); + cards.add(new SetCardInfo("Venomspout Brackus", 295, Rarity.UNCOMMON, mage.cards.v.VenomspoutBrackus.class)); cards.add(new SetCardInfo("Words of War", 244, Rarity.RARE, mage.cards.w.WordsOfWar.class)); cards.add(new SetCardInfo("Words of Wind", 122, Rarity.RARE, mage.cards.w.WordsOfWind.class)); cards.add(new SetCardInfo("Words of Worship", 61, Rarity.RARE, mage.cards.w.WordsOfWorship.class)); diff --git a/Mage.Sets/src/mage/sets/UrzasDestiny.java b/Mage.Sets/src/mage/sets/UrzasDestiny.java index 6dffaae719f..7e70e0b1fc5 100644 --- a/Mage.Sets/src/mage/sets/UrzasDestiny.java +++ b/Mage.Sets/src/mage/sets/UrzasDestiny.java @@ -88,6 +88,7 @@ public class UrzasDestiny extends ExpansionSet { cards.add(new SetCardInfo("False Prophet", 6, Rarity.RARE, mage.cards.f.FalseProphet.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)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/abilitywords/RevoltTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/abilitywords/RevoltTest.java new file mode 100644 index 00000000000..22744031ba8 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/abilitywords/RevoltTest.java @@ -0,0 +1,82 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package org.mage.test.cards.abilities.abilitywords; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class RevoltTest extends CardTestPlayerBase { + + /** + * In a duel commander match, I played a turn 1 Narnam Renegade off a basic + * forest, and it entered the battlefield with a +1/+1 counter (it shouldn't + * have). + */ + @Test + public void testFalseCondition() { + // Deathtouch + // Revolt — Narnam Renegade enters the battlefield with a +1/+1 counter on it if a permanent you controlled left this battlefield this turn. + addCard(Zone.HAND, playerA, "Narnam Renegade", 1); // Creature 1/2 {G} + addCard(Zone.HAND, playerA, "Forest", 1); + + playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Forest"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Narnam Renegade"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPowerToughness(playerA, "Narnam Renegade", 1, 2); + } + + @Test + public void testTrueCondition() { + // Deathtouch + // Revolt — Narnam Renegade enters the battlefield with a +1/+1 counter on it if a permanent you controlled left this battlefield this turn. + addCard(Zone.HAND, playerA, "Narnam Renegade", 1); // Creature 1/2 {G} + // {T}, Sacrifice Terramorphic Expanse: Search your library for a basic land card and put it onto the battlefield tapped. Then shuffle your library. + addCard(Zone.BATTLEFIELD, playerA, "Terramorphic Expanse", 1); + addCard(Zone.HAND, playerA, "Forest", 1); + + playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Forest"); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}, Sacrifice"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Narnam Renegade"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerA, "Terramorphic Expanse", 1); + assertPowerToughness(playerA, "Narnam Renegade", 2, 3); + } + +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/SepulchralPrimordialTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/SepulchralPrimordialTest.java index 54701af759e..b546babd060 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/SepulchralPrimordialTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/enters/SepulchralPrimordialTest.java @@ -59,4 +59,35 @@ public class SepulchralPrimordialTest extends CardTestPlayerBase { assertLife(playerB, 20); } + + /** + * Sepulchral Primordial's "enter the battlefield" effect works correctly on + * cast, but does not trigger if he is returned to the battlefield by other + * means (e.g. summoned from the graveyard). I've encountered this in + * 4-player commander games with other humans. + */ + @Test + public void testETBFromGraveyardEffect() { + // Return target creature card from your graveyard to the battlefield. Put a +1/+1 counter on it. + addCard(Zone.HAND, playerA, "Miraculous Recovery", 1); // Instant {4}{W} + // When Sepulchral Primordial enters the battlefield, for each opponent, you may put up to one + // target creature card from that player's graveyard onto the battlefield under your control. + addCard(Zone.GRAVEYARD, playerA, "Sepulchral Primordial", 1); // Creature 5/4 + addCard(Zone.BATTLEFIELD, playerA, "Plains", 5); + + addCard(Zone.GRAVEYARD, playerB, "Silvercoat Lion", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Miraculous Recovery", "Sepulchral Primordial"); + addTarget(playerA, "Silvercoat Lion"); // target for ETB Sepulchral Primordial + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerA, "Miraculous Recovery", 1); + assertPowerToughness(playerA, "Sepulchral Primordial", 6, 5); + assertPermanentCount(playerA, "Silvercoat Lion", 1); + + assertLife(playerA, 20); + assertLife(playerB, 20); + + } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/CascadeTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/CascadeTest.java index f5aa2e45108..3618d4230b1 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/CascadeTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/CascadeTest.java @@ -171,27 +171,70 @@ public class CascadeTest extends CardTestPlayerBase { public void testHaveToPayAdditionalCosts() { playerA.getLibrary().clear(); - // Choose one - You draw five cards and you lose 5 life; - // or put an X/X black Demon creature token with flying onto the battlefield, where X is the number of cards in your hand as the token enters the battlefield. + // Choose one - + // - You draw five cards and you lose 5 life; + // - put an X/X black Demon creature token with flying onto the battlefield, where X is the number of cards in your hand as the token enters the battlefield. // Entwine {4} (Choose both if you pay the entwine cost.) addCard(Zone.LIBRARY, playerA, "Promise of Power", 1); - // addCard(Zone.LIBRARY, playerA, "Silvercoat Lion", 2); + addCard(Zone.LIBRARY, playerA, "Mountain", 5); + // addCard(Zone.LIBRARY, playerA, "Silvercoat Lion", 2); addCard(Zone.BATTLEFIELD, playerA, "Plains", 3); addCard(Zone.BATTLEFIELD, playerA, "Forest", 3); - // Cascade + // Cascade (When you cast this spell, exile cards from the top of your library until you exile a nonland card that costs less. + // You may cast it without paying its mana cost. Put the exiled cards on the bottom in a random order.) addCard(Zone.HAND, playerA, "Enlisted Wurm"); // Creature {4}{G}{W} 5/5 castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Enlisted Wurm"); + setChoice(playerA, "Yes"); // Use cascade on Promise of Power + setChoice(playerA, "No"); // Pay no Entwine + setModeChoice(playerA, "1"); - setStopAt(1, PhaseStep.END_TURN); + setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); - assertPermanentCount(playerA, "Enlisted Wurm", 1); assertLife(playerA, 15); assertHandCount(playerA, 5); assertPermanentCount(playerA, "Demon", 0); + assertPermanentCount(playerA, "Enlisted Wurm", 1); } + + /** + * Cascade dont work with split cards. + * + * For example: Ardent Plea + Breaking/Entering + */ + @Test + public void testWithSplitSpell() { + + playerA.getLibrary().clear(); + // Breaking - Target player puts the top eight cards of his or her library into his or her graveyard. + // Entering - Put a creature card from a graveyard onto the battlefield under your control. It gains haste until end of turn. + // Fuse (You may cast one or both halves of this card from your hand.) + addCard(Zone.LIBRARY, playerA, "Breaking // Entering", 1); // Sorcery {U}{B} // {4}{U}{B} + // addCard(Zone.LIBRARY, playerA, "Silvercoat Lion", 2); + + addCard(Zone.BATTLEFIELD, playerA, "Plains", 1); + addCard(Zone.BATTLEFIELD, playerA, "Island", 2); + + // Exalted (Whenever a creature you control attacks alone, that creature gets +1/+1 until end of turn.) + // Cascade (When you cast this spell, exile cards from the top of your library until you exile a nonland card that costs less. You may cast it without paying its mana cost. Put the exiled cards on the bottom in a random order.) + addCard(Zone.HAND, playerA, "Ardent Plea"); // Enchantment {1}{W}{U} + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Ardent Plea"); + setChoice(playerA, "Yes"); + addTarget(playerA, playerB); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "Ardent Plea", 1); + assertGraveyardCount(playerA, "Breaking // Entering", 1); + + assertGraveyardCount(playerB, 8); + + } + } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/damage/FlameheartWerewolfTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/damage/FlameheartWerewolfTest.java new file mode 100644 index 00000000000..583b54cce93 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/damage/FlameheartWerewolfTest.java @@ -0,0 +1,135 @@ +/* +* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without modification, are +* permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, this list of +* conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, this list +* of conditions and the following disclaimer in the documentation and/or other materials +* provided with the distribution. +* +* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR +* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* The views and conclusions contained in the software and documentation are those of the +* authors and should not be interpreted as representing official policies, either expressed +* or implied, of BetaSteward_at_googlemail.com. + */ +package org.mage.test.cards.abilities.oneshot.damage; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author goblin + */ +public class FlameheartWerewolfTest extends CardTestPlayerBase { + + /** + * https://github.com/magefree/mage/issues/2816 + */ + @Test + public void testBlockingKalitas() { + // this card is the second face of double-faced card + + // Flameheart Werewolf is a 3/2 with: + // Whenever Flameheart Werewolf blocks or becomes blocked by a creature, Flameheart Werewolf deals 2 damage to that creature. + // Kalitas, Traitor of Ghet is a 3/4 with: + // Lifelink + // If a nontoken creature an opponent controls would die, instead exile that card and put a 2/2 black Zombie creature token onto the battlefield + addCard(Zone.BATTLEFIELD, playerA, "Flameheart Werewolf"); + addCard(Zone.BATTLEFIELD, playerB, "Kalitas, Traitor of Ghet"); + + attack(2, playerB, "Kalitas, Traitor of Ghet"); + block(2, playerA, "Flameheart Werewolf", "Kalitas, Traitor of Ghet"); + + setStopAt(2, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertLife(playerA, 20); + assertLife(playerB, 23); // lifelinked + + // both should die + assertPermanentCount(playerA, "Flameheart Werewolf", 0); + assertExileCount("Flameheart Werewolf", 1); // exiled by Kalitas + assertPermanentCount(playerB, "Kalitas, Traitor of Ghet", 0); + assertGraveyardCount(playerB, "Kalitas, Traitor of Ghet", 1); + } + + @Test + public void testBlockedByTwo22s() { + addCard(Zone.BATTLEFIELD, playerA, "Flameheart Werewolf"); + // Both 2/2 creatures should die before the combat starts + addCard(Zone.BATTLEFIELD, playerB, "Falkenrath Reaver"); + addCard(Zone.BATTLEFIELD, playerB, "Wind Drake"); + + attack(3, playerA, "Flameheart Werewolf"); + block(3, playerB, "Falkenrath Reaver", "Flameheart Werewolf"); + block(3, playerB, "Wind Drake", "Flameheart Werewolf"); + + setStopAt(3, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + // Flameheart Werewolf was blocked, no trample + assertLife(playerA, 20); + assertLife(playerB, 20); + + // both 2/2s should die before they had a chance to deal damage + // to Flameheart Werewolf + assertGraveyardCount(playerA, "Kessig Forgemaster", 0); + assertPermanentCount(playerA, "Flameheart Werewolf", 1); + assertPermanentCount(playerB, "Falkenrath Reaver", 0); + assertGraveyardCount(playerB, "Falkenrath Reaver", 1); + assertPermanentCount(playerB, "Wind Drake", 0); + assertGraveyardCount(playerB, "Wind Drake", 1); + } + + @Test + public void testKessigForgemaster() { + addCard(Zone.BATTLEFIELD, playerA, "Kessig Forgemaster"); + // Both 1/1 creatures should die before the combat starts + addCard(Zone.BATTLEFIELD, playerB, "Wily Bandar"); + addCard(Zone.BATTLEFIELD, playerB, "Stern Constable"); + + // to prevent Kessig from transforming: + addCard(Zone.BATTLEFIELD, playerA, "Island"); + addCard(Zone.BATTLEFIELD, playerB, "Island"); + addCard(Zone.HAND, playerA, "Explosive Apparatus"); + addCard(Zone.HAND, playerB, "Explosive Apparatus"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Explosive Apparatus"); + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Explosive Apparatus"); + + attack(3, playerA, "Kessig Forgemaster"); + block(3, playerB, "Wily Bandar", "Kessig Forgemaster"); + block(3, playerB, "Stern Constable", "Kessig Forgemaster"); + + setStopAt(3, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + // Kessig Forgemaster was blocked, no trample + assertLife(playerA, 20); + assertLife(playerB, 20); + + // both 1/1s should die before they had a chance to deal damage + // to Kessig Forgemaster + assertPermanentCount(playerA, "Kessig Forgemaster", 1); + assertGraveyardCount(playerA, "Kessig Forgemaster", 0); + assertPermanentCount(playerB, "Wily Bandar", 0); + assertGraveyardCount(playerB, "Wily Bandar", 1); + assertPermanentCount(playerB, "Stern Constable", 0); + assertGraveyardCount(playerB, "Stern Constable", 1); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/control/GontiLordOfLuxuryEffectTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/control/GontiLordOfLuxuryEffectTest.java index ebc2c88a037..917d60a429a 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/control/GontiLordOfLuxuryEffectTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/control/GontiLordOfLuxuryEffectTest.java @@ -80,4 +80,94 @@ public class GontiLordOfLuxuryEffectTest extends CardTestPlayerBase { } + /** + * Opponent using Gonti, Lord of Luxury took Mirari's Wake out of my library + * and cast it. I cast Cyclonic Rift on Mirari's Wake to put it back in my + * hand and was unable to recast Mirari's Wake. + */ + @Test + public void testCanBeCastAgainCyclonicRift() { + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 9); + // Deathtouch + // When Gonti, Lord of Luxury enters the battlefield, look at the top four cards of target opponent's library, exile one of them face down, + // then put the rest on the bottom of that library in a random order. For as long as that card remains exiled, + // you may look at it, you may cast it, and you may spend mana as though it were mana of any type to cast it. + addCard(Zone.HAND, playerA, "Gonti, Lord of Luxury", 1); // Creature 2/3 {2}{B}{B} + + // Creatures you control get +1/+1. + // Whenever you tap a land for mana, add one mana to your mana pool of any type that land produced. + addCard(Zone.LIBRARY, playerB, "Mirari's Wake"); // Enchantment {3}{G}{W} + skipInitShuffling(); + + addCard(Zone.BATTLEFIELD, playerB, "Island", 2); + addCard(Zone.BATTLEFIELD, playerB, "Forest", 2); + addCard(Zone.BATTLEFIELD, playerB, "Plains", 1); + addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 1); + // Return target nonland permanent you don't control to its owner's hand. + // Overload {6}{U} (You may cast this spell for its overload cost. If you do, change its text by replacing all instances of "target" with "each.") + addCard(Zone.HAND, playerB, "Cyclonic Rift", 1); // Intant {1}{U} + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Gonti, Lord of Luxury"); + addTarget(playerA, playerB); + setChoice(playerA, "Mirari's Wake"); + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Mirari's Wake"); + castSpell(1, PhaseStep.END_TURN, playerB, "Cyclonic Rift", "Mirari's Wake"); + + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Mirari's Wake"); + + setStopAt(2, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "Gonti, Lord of Luxury", 1); + assertPowerToughness(playerA, "Gonti, Lord of Luxury", 2, 3); + assertGraveyardCount(playerB, "Cyclonic Rift", 1); + + assertPermanentCount(playerB, "Mirari's Wake", 1); + assertPowerToughness(playerB, "Silvercoat Lion", 3, 3); + + } + + /** + * I noticed in a game that when you cast Lingering Souls off of Gonti, Lord + * of Luxury and then the lingering souls goes to the graveyard it cannot be + * flashed back. The gonti was my opponent's and the lingering souls was + * mine for reference. + */ + @Test + public void testCanBeCastLaterWithFlashBack() { + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 7); + // Deathtouch + // When Gonti, Lord of Luxury enters the battlefield, look at the top four cards of target opponent's library, exile one of them face down, + // then put the rest on the bottom of that library in a random order. For as long as that card remains exiled, + // you may look at it, you may cast it, and you may spend mana as though it were mana of any type to cast it. + addCard(Zone.HAND, playerA, "Gonti, Lord of Luxury", 1); // Creature 2/3 {2}{B}{B} + + // Create two 1/1 white Spirit creature tokens with flying. + // Flashback {1}{B} + addCard(Zone.LIBRARY, playerB, "Lingering Souls"); // Sorcery {2}{W} + skipInitShuffling(); + + addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Gonti, Lord of Luxury"); + addTarget(playerA, playerB); + setChoice(playerA, "Lingering Souls"); + + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lingering Souls"); + + activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Flashback"); + + setStopAt(2, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "Gonti, Lord of Luxury", 1); + assertPowerToughness(playerA, "Gonti, Lord of Luxury", 2, 3); + assertPermanentCount(playerA, "Spirit", 2); + + assertPermanentCount(playerB, "Spirit", 2); + + assertExileCount("Lingering Souls", 1); + + } + } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/prevent/DeflectingPalmTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/prevent/DeflectingPalmTest.java index a3bba93f6ab..c98cab73a1f 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/prevent/DeflectingPalmTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/prevent/DeflectingPalmTest.java @@ -32,18 +32,18 @@ import mage.constants.Zone; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; - /** - * Deflecting Palm Instant {R}{W} - * The next time a source of your choice would deal damage to you this turn, prevent that damage. - * If damage is prevented this way, Deflecting Palm deals that much damage to that source's controller. + * Deflecting Palm Instant {R}{W} The next time a source of your choice would + * deal damage to you this turn, prevent that damage. If damage is prevented + * this way, Deflecting Palm deals that much damage to that source's controller. * * @author LevelX2 */ public class DeflectingPalmTest extends CardTestPlayerBase { /** - * Tests if a damage spell is selected as source the damage is prevented and is dealt to the controller of the damage spell + * Tests if a damage spell is selected as source the damage is prevented and + * is dealt to the controller of the damage spell */ @Test public void testPreventDamageFromSpell() { @@ -53,7 +53,7 @@ public class DeflectingPalmTest extends CardTestPlayerBase { addCard(Zone.HAND, playerB, "Deflecting Palm"); addCard(Zone.BATTLEFIELD, playerB, "Mountain"); addCard(Zone.BATTLEFIELD, playerB, "Plains"); - + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Deflecting Palm", null, "Lightning Bolt"); setChoice(playerB, "Lightning Bolt"); @@ -68,4 +68,49 @@ public class DeflectingPalmTest extends CardTestPlayerBase { assertGraveyardCount(playerB, "Deflecting Palm", 1); } + /** + * I tried to prevent damage dealt by Deflecting Palm using a Drokoma's + * Command and it seems it's not working properly. According to this, it + * should work. + */ + @Test + public void testPreventDamageWithDromokasCommand() { + + // Choose two - + // - Prevent all damage target instant or sorcery spell would deal this turn; + // - or Target player sacrifices an enchantment; + // - Put a +1/+1 counter on target creature; + // - or Target creature you control fights target creature you don't control. + addCard(Zone.HAND, playerA, "Dromoka's Command");// Instant {G}{W} + addCard(Zone.BATTLEFIELD, playerA, "Plains"); + addCard(Zone.BATTLEFIELD, playerA, "Forest"); + addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); // Creature 2/2 + + // The next time a source of your choice would deal damage to you this turn, prevent that damage. + // If damage is prevented this way, Deflecting Palm deals that much damage to that source's controller. + addCard(Zone.HAND, playerB, "Deflecting Palm"); // Instant {R}{W} + addCard(Zone.BATTLEFIELD, playerB, "Mountain"); + addCard(Zone.BATTLEFIELD, playerB, "Plains"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Deflecting Palm"); + setChoice(playerB, "Silvercoat Lion"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dromoka's Command", "Deflecting Palm"); + addTarget(playerA, "Silvercoat Lion"); + setModeChoice(playerA, "1"); + setModeChoice(playerA, "3"); + + attack(1, playerA, "Silvercoat Lion"); + + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + assertGraveyardCount(playerB, "Deflecting Palm", 1); + assertGraveyardCount(playerA, "Dromoka's Command", 1); + + assertPowerToughness(playerA, "Silvercoat Lion", 3, 3); + + assertLife(playerA, 20); + assertLife(playerB, 20); + + } + } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/tsp/HivestoneTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/tsp/HivestoneTest.java index 945e1848111..3fcfd21c844 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/single/tsp/HivestoneTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/tsp/HivestoneTest.java @@ -16,26 +16,32 @@ public class HivestoneTest extends CardTestPlayerBase { */ @Test public void abilityCheckTest() { - addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears", 1); - addCard(Zone.BATTLEFIELD, playerA, "Hivestone", 1); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 4); + addCard(Zone.HAND, playerA, "Grizzly Bears", 1); // Creature {1}{G} + // Creatures you control are Slivers in addition to their other creature types. + addCard(Zone.HAND, playerA, "Hivestone", 1); // Artifact {2} + // All Sliver creatures get +1/+1. addCard(Zone.BATTLEFIELD, playerA, "Muscle Sliver", 1); + addCard(Zone.BATTLEFIELD, playerB, "Runeclaw Bear", 1); // Creature 2/2 - addCard(Zone.BATTLEFIELD, playerB, "Runeclaw Bear", 1); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grizzly Bears"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Hivestone"); - setStopAt(1, PhaseStep.PRECOMBAT_MAIN); + setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); + assertPermanentCount(playerA, "Hivestone", 1); + assertPermanentCount(playerA, "Grizzly Bears", 1); assertPowerToughness(playerA, "Grizzly Bears", 3, 3, Filter.ComparisonScope.Any); - assertPowerToughness(playerB, "Runeclaw Bear", 2, 2, Filter.ComparisonScope.Any); - } /** - * Turns only your creatures on the battlefield, not in other zones, into Slivers. It won’t allow you to have - * Root Sliver on the battlefield and make your Grizzly Bears uncounterable, for example. + * Turns only your creatures on the battlefield, not in other zones, into + * Slivers. It won’t allow you to have Root Sliver on the battlefield and + * make your Grizzly Bears uncounterable, for example. */ @Test public void rootSliverTest() { @@ -45,7 +51,6 @@ public class HivestoneTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerA, "Root Sliver", 1); addCard(Zone.BATTLEFIELD, playerA, "Forest", 2); - addCard(Zone.BATTLEFIELD, playerB, "Island", 2); addCard(Zone.HAND, playerB, "Counterspell"); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/delayed/GlimpseOfNatureTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/delayed/GlimpseOfNatureTest.java new file mode 100644 index 00000000000..aac3efca10e --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/delayed/GlimpseOfNatureTest.java @@ -0,0 +1,75 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package org.mage.test.cards.triggers.delayed; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class GlimpseOfNatureTest extends CardTestPlayerBase { + + /** + * Glimpse of Nature triggers do not draw a card. + */ + @Test + public void testCardsAreDrawnFromCreatureCasting() { + // Whenever you cast a creature spell this turn, draw a card. + addCard(Zone.HAND, playerA, "Glimpse of Nature", 1);// Sorcery {G} + addCard(Zone.HAND, playerA, "Silvercoat Lion", 2); + + addCard(Zone.BATTLEFIELD, playerA, "Forest", 1); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 4); + + // Flash (You may cast this spell any time you could cast an instant.) + // First strike (This creature deals combat damage before creatures without first strike.) + addCard(Zone.HAND, playerB, "Benalish Knight", 1); // Creature {2}{W} + addCard(Zone.BATTLEFIELD, playerB, "Plains", 3); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Glimpse of Nature"); + + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Silvercoat Lion"); + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Silvercoat Lion"); + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Benalish Knight"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertGraveyardCount(playerA, "Glimpse of Nature", 1); + assertPermanentCount(playerA, "Silvercoat Lion", 2); + assertPermanentCount(playerB, "Benalish Knight", 1); + + assertHandCount(playerA, 2); + assertHandCount(playerB, 0); + } + +} diff --git a/Mage.Tests/src/test/java/org/mage/test/multiplayer/PlayerLeftGameTest.java b/Mage.Tests/src/test/java/org/mage/test/multiplayer/PlayerLeftGameTest.java index 12794c92806..e5f4ba40a61 100644 --- a/Mage.Tests/src/test/java/org/mage/test/multiplayer/PlayerLeftGameTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/multiplayer/PlayerLeftGameTest.java @@ -47,6 +47,7 @@ public class PlayerLeftGameTest extends CardTestMultiPlayerBase { @Override protected Game createNewGameAndPlayers() throws GameException, FileNotFoundException { + // Start Life = 2 Game game = new FreeForAll(MultiplayerAttackOption.MULTIPLE, RangeOfInfluence.ALL, 0, 2); // Player order: A -> D -> C -> B playerA = createPlayer(game, playerA, "PlayerA"); @@ -197,4 +198,35 @@ public class PlayerLeftGameTest extends CardTestMultiPlayerBase { assertGraveyardCount(playerB, "Silvercoat Lion", 1); } + /** + * Situation: I attacked an opponent with some creatures with True + * Conviction in play. There were multiple "deals combat damage to a + * player"-triggers (Edric, Spymaster of Trest, Daxos of Meletis et al), + * then the opponent lost the game during the first strike combat + * damage-step . In the second combat damage step the triggers went on the + * stack again, although there was no player being dealt damage (multiplayer + * game, so the game wasn't over yet). I don't think these abilities should + * trigger again here. + */ + @Test + public void TestPlayerDiesDuringFirstStrikeDamageStep() { + // Creatures you control have double strike and lifelink. + addCard(Zone.BATTLEFIELD, playerD, "True Conviction"); + // Whenever a creature deals combat damage to one of your opponents, its controller may draw a card. + addCard(Zone.BATTLEFIELD, playerD, "Edric, Spymaster of Trest"); + addCard(Zone.BATTLEFIELD, playerD, "Dross Crocodile", 8); // Creature 5/1 + + attack(2, playerD, "Dross Crocodile", playerC); + + setStopAt(3, PhaseStep.END_TURN); + execute(); + + assertLife(playerC, -3); + assertLife(playerD, 7); + + assertHandCount(playerD, 2); // 1 (normal draw) + 1 from True Convition + assertPermanentCount(playerC, 0); + + } + } diff --git a/Mage.Tests/src/test/java/org/mage/test/multiplayer/PrimordialTest.java b/Mage.Tests/src/test/java/org/mage/test/multiplayer/PrimordialTest.java index 7045c79628e..86fe7d95c64 100644 --- a/Mage.Tests/src/test/java/org/mage/test/multiplayer/PrimordialTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/multiplayer/PrimordialTest.java @@ -67,6 +67,39 @@ public class PrimordialTest extends CardTestMultiPlayerBase { assertGraveyardCount(playerD, "Pillarfield Ox", 0); } + /** + * Sepulchral Primordial's "enter the battlefield" effect works correctly on + * cast, but does not trigger if he is returned to the battlefield by other + * means (e.g. summoned from the graveyard). I've encountered this in + * 4-player commander games with other humans. + */ + @Test + public void SepulchralPrimordialFromGraveyardTest() { + // Return target creature card from your graveyard to the battlefield. Put a +1/+1 counter on it. + addCard(Zone.HAND, playerA, "Miraculous Recovery", 1); // Instant {4}{W} + // When Sepulchral Primordial enters the battlefield, for each opponent, you may put up to one + // target creature card from that player's graveyard onto the battlefield under your control. + addCard(Zone.GRAVEYARD, playerA, "Sepulchral Primordial"); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 5); + + // Player order: A -> D -> C -> B + addCard(Zone.GRAVEYARD, playerB, "Silvercoat Lion"); + addCard(Zone.GRAVEYARD, playerC, "Walking Corpse"); + addCard(Zone.GRAVEYARD, playerD, "Pillarfield Ox"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Miraculous Recovery", "Sepulchral Primordial"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "Sepulchral Primordial", 1); + assertPermanentCount(playerA, "Silvercoat Lion", 1); + assertPermanentCount(playerA, "Walking Corpse", 0); + assertPermanentCount(playerA, "Pillarfield Ox", 1); + assertGraveyardCount(playerC, "Walking Corpse", 1); + assertGraveyardCount(playerD, "Pillarfield Ox", 0); + } + /** * Diluvian Primordial ETB trigger never happened in a 3 player FFA * commander game. He just resolved, no ETB trigger occurred. diff --git a/Mage/src/main/java/mage/abilities/AbilityImpl.java b/Mage/src/main/java/mage/abilities/AbilityImpl.java index ae5c5cf61ee..ac6c2317005 100644 --- a/Mage/src/main/java/mage/abilities/AbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/AbilityImpl.java @@ -30,7 +30,6 @@ package mage.abilities; import java.util.ArrayList; import java.util.List; import java.util.UUID; - import mage.MageObject; import mage.MageObjectReference; import mage.Mana; @@ -39,6 +38,7 @@ import mage.abilities.costs.AlternativeSourceCosts; import mage.abilities.costs.Cost; import mage.abilities.costs.Costs; import mage.abilities.costs.CostsImpl; +import mage.abilities.costs.OptionalAdditionalModeSourceCosts; import mage.abilities.costs.OptionalAdditionalSourceCosts; import mage.abilities.costs.VariableCost; import mage.abilities.costs.common.TapSourceCost; @@ -50,8 +50,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.common.BasicManaEffect; import mage.abilities.effects.common.DynamicManaEffect; +import mage.abilities.effects.common.ManaEffect; import mage.abilities.keyword.FlashbackAbility; import mage.abilities.mana.ActivatedManaAbilityImpl; import mage.cards.Card; @@ -284,6 +284,9 @@ public abstract class AbilityImpl implements Ability { this.getManaCostsToPay().clear(); } } + if (modes.getAdditionalCost() != null) { + ((OptionalAdditionalModeSourceCosts) modes.getAdditionalCost()).addOptionalAdditionalModeCosts(this, game); + } // 20130201 - 601.2b // If the spell has alternative or additional costs that will be paid as it's being cast such // as buyback, kicker, or convoke costs (see rules 117.8 and 117.9), the player announces his @@ -415,8 +418,8 @@ public abstract class AbilityImpl implements Ability { Effect effect = getEffects().get(0); if (effect instanceof DynamicManaEffect) { mana = ((DynamicManaEffect) effect).getMana(game, this); - } else if (effect instanceof BasicManaEffect) { - mana = ((BasicManaEffect) effect).getMana(game, this); + } else if (effect instanceof ManaEffect) { + mana = ((ManaEffect) effect).getMana(game, this); } if (mana != null && mana.getAny() == 0) { // if mana == null or Any > 0 the event has to be fired in the mana effect to know which mana was produced ManaEvent event = new ManaEvent(GameEvent.EventType.TAPPED_FOR_MANA, sourceId, sourceId, controllerId, mana); diff --git a/Mage/src/main/java/mage/abilities/Modes.java b/Mage/src/main/java/mage/abilities/Modes.java index 8daf432f4b6..d8c8e42fd73 100644 --- a/Mage/src/main/java/mage/abilities/Modes.java +++ b/Mage/src/main/java/mage/abilities/Modes.java @@ -56,6 +56,7 @@ public class Modes extends LinkedHashMap { private boolean eachModeMoreThanOnce; // each mode can be selected multiple times during one choice private boolean eachModeOnlyOnce; // state if each mode can be chosen only once as long as the source object exists private final LinkedHashMap duplicateModes = new LinkedHashMap<>(); + private OptionalAdditionalModeSourceCosts optionalAdditionalModeSourceCosts = null; // only set if costs have to be paid public Modes() { this.currentMode = new Mode(); @@ -87,6 +88,7 @@ public class Modes extends LinkedHashMap { this.modeChooser = modes.modeChooser; this.eachModeOnlyOnce = modes.eachModeOnlyOnce; this.eachModeMoreThanOnce = modes.eachModeMoreThanOnce; + this.optionalAdditionalModeSourceCosts = modes.optionalAdditionalModeSourceCosts; } public Modes copy() { @@ -186,7 +188,7 @@ public class Modes extends LinkedHashMap { if (card != null) { for (Ability modeModifyingAbility : card.getAbilities()) { if (modeModifyingAbility instanceof OptionalAdditionalModeSourceCosts) { - ((OptionalAdditionalModeSourceCosts) modeModifyingAbility).addOptionalAdditionalModeCosts(source, game); + ((OptionalAdditionalModeSourceCosts) modeModifyingAbility).changeModes(source, game); } } } @@ -385,4 +387,12 @@ public class Modes extends LinkedHashMap { this.eachModeMoreThanOnce = eachModeMoreThanOnce; } + public OptionalAdditionalModeSourceCosts getAdditionalCost() { + return optionalAdditionalModeSourceCosts; + } + + public void setAdditionalCost(OptionalAdditionalModeSourceCosts optionalAdditionalModeSourceCosts) { + this.optionalAdditionalModeSourceCosts = optionalAdditionalModeSourceCosts; + } + } diff --git a/Mage/src/main/java/mage/abilities/common/BlocksOrBecomesBlockedTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/BlocksOrBecomesBlockedTriggeredAbility.java index 4bdb8c31bad..94b871001da 100644 --- a/Mage/src/main/java/mage/abilities/common/BlocksOrBecomesBlockedTriggeredAbility.java +++ b/Mage/src/main/java/mage/abilities/common/BlocksOrBecomesBlockedTriggeredAbility.java @@ -27,11 +27,11 @@ */ package mage.abilities.common; -import mage.constants.Zone; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.Effect; +import mage.constants.Zone; import mage.filter.FilterPermanent; -import mage.filter.common.FilterCreaturePermanent; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; @@ -48,7 +48,7 @@ public class BlocksOrBecomesBlockedTriggeredAbility extends TriggeredAbilityImpl protected boolean setTargetPointer; public BlocksOrBecomesBlockedTriggeredAbility(Effect effect, boolean optional) { - this(effect, new FilterCreaturePermanent(), optional, null, false); + this(effect, StaticFilters.FILTER_PERMANENT_CREATURE, optional, null, false); } public BlocksOrBecomesBlockedTriggeredAbility(Effect effect, FilterPermanent filter, boolean optional) { diff --git a/Mage/src/main/java/mage/abilities/common/CantHaveMoreThanAmountCountersSourceAbility.java b/Mage/src/main/java/mage/abilities/common/CantHaveMoreThanAmountCountersSourceAbility.java new file mode 100644 index 00000000000..813026b5f4d --- /dev/null +++ b/Mage/src/main/java/mage/abilities/common/CantHaveMoreThanAmountCountersSourceAbility.java @@ -0,0 +1,130 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.abilities.common; + +import mage.abilities.Ability; +import mage.abilities.effects.ReplacementEffectImpl; +import mage.constants.Duration; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.counters.CounterType; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.game.permanent.Permanent; +import mage.util.CardUtil; + +/** + * + * @author emerald000 + */ +public class CantHaveMoreThanAmountCountersSourceAbility extends SimpleStaticAbility { + + private final CounterType counterType; + private final int amount; + + public CantHaveMoreThanAmountCountersSourceAbility(CounterType counterType, int amount) { + super(Zone.BATTLEFIELD, new CantHaveMoreThanAmountCountersSourceEffect(counterType, amount)); + this.counterType = counterType; + this.amount = amount; + } + + private CantHaveMoreThanAmountCountersSourceAbility(CantHaveMoreThanAmountCountersSourceAbility ability) { + super(ability); + this.counterType = ability.counterType; + this.amount = ability.amount; + } + + @Override + public String getRule() { + return "Rasputin can't have more than " + CardUtil.numberToText(this.amount) + " " + this.counterType.getName() + " counters on it."; + } + + @Override + public CantHaveMoreThanAmountCountersSourceAbility copy() { + return new CantHaveMoreThanAmountCountersSourceAbility(this); + } + + public CounterType getCounterType() { + return this.counterType; + } + + public int getAmount() { + return this.amount; + } +} + +class CantHaveMoreThanAmountCountersSourceEffect extends ReplacementEffectImpl { + + private final CounterType counterType; + private final int amount; + + CantHaveMoreThanAmountCountersSourceEffect(CounterType counterType, int amount) { + super(Duration.WhileOnBattlefield, Outcome.Detriment, false); + this.counterType = counterType; + this.amount = amount; + } + + CantHaveMoreThanAmountCountersSourceEffect(final CantHaveMoreThanAmountCountersSourceEffect effect) { + super(effect); + this.counterType = effect.counterType; + this.amount = effect.amount; + } + + @Override + public boolean replaceEvent(GameEvent event, Ability source, Game game) { + return true; + } + + @Override + public boolean checksEventType(GameEvent event, Game game) { + return event.getType() == EventType.ADD_COUNTER; + } + + @Override + public boolean applies(GameEvent event, Ability source, Game game) { + Permanent permanent = game.getPermanent(event.getTargetId()); + if (permanent == null) { + permanent = game.getPermanentEntering(event.getTargetId()); + } + return permanent != null + && permanent.getId().equals(source.getSourceId()) + && event.getData().equals(this.counterType.getName()) + && permanent.getCounters(game).getCount(this.counterType) == this.amount; + } + + @Override + public boolean apply(Game game, Ability source) { + return true; + } + + @Override + public CantHaveMoreThanAmountCountersSourceEffect copy() { + return new CantHaveMoreThanAmountCountersSourceEffect(this); + } +} diff --git a/Mage/src/main/java/mage/abilities/costs/OptionalAdditionalModeSourceCosts.java b/Mage/src/main/java/mage/abilities/costs/OptionalAdditionalModeSourceCosts.java index e9c73f797c4..b0dc7599e57 100644 --- a/Mage/src/main/java/mage/abilities/costs/OptionalAdditionalModeSourceCosts.java +++ b/Mage/src/main/java/mage/abilities/costs/OptionalAdditionalModeSourceCosts.java @@ -34,9 +34,11 @@ import mage.game.Game; * * @author LevelX2 */ - - public interface OptionalAdditionalModeSourceCosts { + void addOptionalAdditionalModeCosts(Ability ability, Game game); + + void changeModes(Ability ability, Game game); + String getCastMessageSuffix(); } diff --git a/Mage/src/main/java/mage/abilities/costs/common/ExileFromGraveCost.java b/Mage/src/main/java/mage/abilities/costs/common/ExileFromGraveCost.java index c639e0dc709..dcf398ffac1 100644 --- a/Mage/src/main/java/mage/abilities/costs/common/ExileFromGraveCost.java +++ b/Mage/src/main/java/mage/abilities/costs/common/ExileFromGraveCost.java @@ -95,11 +95,11 @@ public class ExileFromGraveCost extends CostImpl { } exiledCards.add(card); } + Cards cardsToExile = new CardsImpl(); + cardsToExile.addAll(exiledCards); + controller.moveCards(cardsToExile, Zone.EXILED, ability, game); + paid = true; } - Cards cardsToExile = new CardsImpl(); - cardsToExile.addAll(exiledCards); - controller.moveCards(cardsToExile, Zone.EXILED, ability, game); - paid = true; } return paid; diff --git a/Mage/src/main/java/mage/abilities/effects/common/PreventDamageByTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/PreventDamageByTargetEffect.java index 873da6beac9..5d047321a7e 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/PreventDamageByTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/PreventDamageByTargetEffect.java @@ -25,17 +25,18 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.abilities.effects.common; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.effects.PreventionEffectImpl; +import mage.constants.CardType; import mage.constants.Duration; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.stack.Spell; +import mage.target.Target; +import mage.target.TargetSpell; /** * @author nantuko @@ -71,8 +72,15 @@ public class PreventDamageByTargetEffect extends PreventionEffectImpl { 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 instanceof Spell){ - return this.getTargetPointer().getTargets(game, source).contains(mageObject.getId()); + if (mageObject != null + && (mageObject.getCardType().contains(CardType.INSTANT) || mageObject.getCardType().contains(CardType.SORCERY))) { + for (Target target : source.getTargets()) { + if (target instanceof TargetSpell) { + if (((TargetSpell) target).getSourceIds().contains(event.getSourceId())) { + return true; + } + } + } } return this.getTargetPointer().getTargets(game, source).contains(event.getSourceId()); } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesSubtypeAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesSubtypeAllEffect.java index 7d38ce39c63..f59a794e8ed 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesSubtypeAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/BecomesSubtypeAllEffect.java @@ -70,7 +70,7 @@ public class BecomesSubtypeAllEffect extends ContinuousEffectImpl { @Override public boolean apply(Layer layer, SubLayer sublayer, Ability source, Game game) { - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, game)) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { if (permanent != null) { switch (layer) { case TypeChangingEffects_4: @@ -86,10 +86,8 @@ public class BecomesSubtypeAllEffect extends ContinuousEffectImpl { } break; } - } else { - if (duration.equals(Duration.Custom)) { - discard(); - } + } else if (duration.equals(Duration.Custom)) { + discard(); } } return true; diff --git a/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryWithLessCMCPutInPlayEffect.java b/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryWithLessCMCPutInPlayEffect.java index 75e156a20d7..889ca401dcb 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryWithLessCMCPutInPlayEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryWithLessCMCPutInPlayEffect.java @@ -45,7 +45,7 @@ import mage.target.common.TargetCardInLibrary; */ public class SearchLibraryWithLessCMCPutInPlayEffect extends OneShotEffect { - private FilterCard filter; + private final FilterCard filter; public SearchLibraryWithLessCMCPutInPlayEffect() { this(new FilterCard()); @@ -66,8 +66,9 @@ public class SearchLibraryWithLessCMCPutInPlayEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { - filter.add(new ConvertedManaCostPredicate(Filter.ComparisonType.LessThan, source.getManaCostsToPay().getX() + 1)); - TargetCardInLibrary target = new TargetCardInLibrary(filter); + FilterCard advancedFilter = filter.copy(); // never change static objects so copy the object here before + advancedFilter.add(new ConvertedManaCostPredicate(Filter.ComparisonType.LessThan, source.getManaCostsToPay().getX() + 1)); + TargetCardInLibrary target = new TargetCardInLibrary(advancedFilter); if (controller.searchLibrary(target, game)) { if (!target.getTargets().isEmpty()) { Card card = controller.getLibrary().getCard(target.getFirstTarget(), game); diff --git a/Mage/src/main/java/mage/abilities/keyword/CascadeAbility.java b/Mage/src/main/java/mage/abilities/keyword/CascadeAbility.java index 45125e1d962..274470ba92b 100644 --- a/Mage/src/main/java/mage/abilities/keyword/CascadeAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/CascadeAbility.java @@ -33,6 +33,7 @@ import mage.abilities.effects.OneShotEffect; import mage.cards.Card; import mage.cards.Cards; import mage.cards.CardsImpl; +import mage.cards.SplitCard; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Zone; @@ -120,15 +121,13 @@ class CascadeEffect extends OneShotEffect { break; } controller.moveCardsToExile(card, source, game, true, exile.getId(), exile.getName()); - } while (controller.isInGame() && card.getCardType().contains(CardType.LAND) || card.getConvertedManaCost() >= sourceCost); + } while (controller.isInGame() && (card.getCardType().contains(CardType.LAND) || !cardThatCostsLess(sourceCost, card, game))); + controller.getLibrary().reset(); // set back empty draw state if that caused an empty draw if (card != null) { - if (controller.chooseUse(outcome, "Use cascade effect on " + card.getLogName() + '?', source, game)) { - if (controller.cast(card.getSpellAbility(), game, true)) { - exile.remove(card.getId()); - } - } + if (controller.chooseUse(outcome, "Use cascade effect on " + card.getLogName() + "?", source, game)) { + controller.cast(card.getSpellAbility(), game, true); } // Move the remaining cards to the buttom of the library in a random order Cards cardsFromExile = new CardsImpl(); @@ -148,4 +147,12 @@ class CascadeEffect extends OneShotEffect { return new CascadeEffect(this); } + private boolean cardThatCostsLess(int value, Card card, Game game) { + if (card instanceof SplitCard) { + return ((SplitCard) card).getLeftHalfCard().getConvertedManaCost() < value + || ((SplitCard) card).getRightHalfCard().getConvertedManaCost() < value; + } else { + return card.getConvertedManaCost() < value; + } + } } diff --git a/Mage/src/main/java/mage/abilities/keyword/EntwineAbility.java b/Mage/src/main/java/mage/abilities/keyword/EntwineAbility.java index a51b621d910..16141ebd918 100644 --- a/Mage/src/main/java/mage/abilities/keyword/EntwineAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/EntwineAbility.java @@ -105,22 +105,17 @@ public class EntwineAbility extends StaticAbility implements OptionalAdditionalM } @Override - public void addOptionalAdditionalModeCosts(Ability ability, Game game) { + public void changeModes(Ability ability, Game game) { if (ability instanceof SpellAbility) { Player player = game.getPlayer(controllerId); if (player != null) { this.resetCosts(); if (additionalCost != null) { - if (player.chooseUse(Outcome.Benefit, "Pay " + additionalCost.getText(false) + " ?", ability, game)) { + if (additionalCost.canPay(ability, ability.getSourceId(), ability.getControllerId(), game) + && player.chooseUse(Outcome.Benefit, "Pay " + additionalCost.getText(false) + " ?", ability, game)) { + additionalCost.activate(); - for (Iterator it = ((Costs) additionalCost).iterator(); it.hasNext();) { - Cost cost = (Cost) it.next(); - if (cost instanceof ManaCostsImpl) { - ability.getManaCostsToPay().add((ManaCostsImpl) cost.copy()); - } else { - ability.getCosts().add(cost.copy()); - } - } + ability.getModes().setAdditionalCost(this); ability.getModes().setMinModes(2); ability.getModes().setMaxModes(2); } @@ -129,6 +124,20 @@ public class EntwineAbility extends StaticAbility implements OptionalAdditionalM } } + @Override + public void addOptionalAdditionalModeCosts(Ability ability, Game game) { + if (additionalCost.isActivated()) { + for (Iterator it = ((Costs) additionalCost).iterator(); it.hasNext();) { + Cost cost = (Cost) it.next(); + if (cost instanceof ManaCostsImpl) { + ability.getManaCostsToPay().add((ManaCostsImpl) cost.copy()); + } else { + ability.getCosts().add(cost.copy()); + } + } + } + } + @Override public String getRule() { StringBuilder sb = new StringBuilder(); diff --git a/Mage/src/main/java/mage/cards/CardImpl.java b/Mage/src/main/java/mage/cards/CardImpl.java index 29aa92eb2fe..e56e5f64bb7 100644 --- a/Mage/src/main/java/mage/cards/CardImpl.java +++ b/Mage/src/main/java/mage/cards/CardImpl.java @@ -275,7 +275,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card { @Override public Abilities getAbilities(Game game) { Abilities otherAbilities = game.getState().getAllOtherAbilities(objectId); - if (otherAbilities == null) { + if (otherAbilities == null || otherAbilities.isEmpty()) { return abilities; } Abilities all = new AbilitiesImpl<>(); diff --git a/Mage/src/main/java/mage/cards/repository/CardInfo.java b/Mage/src/main/java/mage/cards/repository/CardInfo.java index 36f106eee9c..09320b0c7ba 100644 --- a/Mage/src/main/java/mage/cards/repository/CardInfo.java +++ b/Mage/src/main/java/mage/cards/repository/CardInfo.java @@ -30,11 +30,16 @@ package mage.cards.repository; import com.j256.ormlite.field.DataType; import com.j256.ormlite.field.DatabaseField; import com.j256.ormlite.table.DatabaseTable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.SpellAbility; import mage.abilities.common.PlanswalkerEntersWithLoyalityCountersAbility; import mage.cards.Card; +import mage.cards.CardGraphicInfo; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.cards.FrameStyle; @@ -45,11 +50,6 @@ import mage.constants.Rarity; import mage.constants.SpellAbilityType; import org.apache.log4j.Logger; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - /** * * @author North @@ -205,7 +205,7 @@ public class CardInfo { } public Card getCard() { - return CardImpl.createCard(className, new CardSetInfo(name, setCode, cardNumber, rarity)); + return CardImpl.createCard(className, new CardSetInfo(name, setCode, cardNumber, rarity, new CardGraphicInfo(FrameStyle.valueOf(frameStyle), variousArt))); } public Card getMockCard() { @@ -216,7 +216,9 @@ public class CardInfo { } } - public boolean usesVariousArt() { return variousArt; } + public boolean usesVariousArt() { + return variousArt; + } public ObjectColor getColor() { ObjectColor color = new ObjectColor(); diff --git a/Mage/src/main/java/mage/cards/repository/CardRepository.java b/Mage/src/main/java/mage/cards/repository/CardRepository.java index 0c9ef48cdd9..94a8b3a2dd0 100644 --- a/Mage/src/main/java/mage/cards/repository/CardRepository.java +++ b/Mage/src/main/java/mage/cards/repository/CardRepository.java @@ -60,7 +60,7 @@ public enum CardRepository { // raise this if db structure was changed private static final long CARD_DB_VERSION = 50; // raise this if new cards were added to the server - private static final long CARD_CONTENT_VERSION = 69; + private static final long CARD_CONTENT_VERSION = 70; private final TreeSet landTypes = new TreeSet(); private Dao cardDao; private Set classNames; diff --git a/Mage/src/main/java/mage/counters/CounterType.java b/Mage/src/main/java/mage/counters/CounterType.java index 60f27156a57..33897e6a21f 100644 --- a/Mage/src/main/java/mage/counters/CounterType.java +++ b/Mage/src/main/java/mage/counters/CounterType.java @@ -53,6 +53,7 @@ public enum CounterType { DEVOTION("devotion"), DIVINITY("divinity"), DOOM("doom"), + DREAM("dream"), ELIXIR("elixir"), ENERGY("energy"), EON("eon"), diff --git a/Mage/src/main/java/mage/filter/StaticFilters.java b/Mage/src/main/java/mage/filter/StaticFilters.java index 310eec34584..5ec5687a926 100644 --- a/Mage/src/main/java/mage/filter/StaticFilters.java +++ b/Mage/src/main/java/mage/filter/StaticFilters.java @@ -32,6 +32,7 @@ public class StaticFilters { public static final FilterNonlandCard FILTER_CARD_NON_LAND = new FilterNonlandCard(); public static final FilterCard FILTER_CARD_ARTIFACT_OR_CREATURE = new FilterCard("artifact or creature card"); + public static final FilterCreaturePermanent FILTER_PERMANENT_CREATURE = new FilterCreaturePermanent(); public static final FilterCreaturePermanent FILTER_PERMANENT_CREATURE_GOBLINS = new FilterCreaturePermanent("Goblin", "Goblin creatures"); public static final FilterCreaturePermanent FILTER_PERMANENT_CREATURE_SLIVERS = new FilterCreaturePermanent("Sliver", "Sliver creatures"); diff --git a/Mage/src/main/java/mage/game/GameCanadianHighlanderImpl.java b/Mage/src/main/java/mage/game/GameCanadianHighlanderImpl.java new file mode 100644 index 00000000000..e2877b17fa1 --- /dev/null +++ b/Mage/src/main/java/mage/game/GameCanadianHighlanderImpl.java @@ -0,0 +1,179 @@ +/* + * Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of BetaSteward_at_googlemail.com. + */ +package mage.game; + +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import mage.constants.MultiplayerAttackOption; +import mage.constants.PhaseStep; +import mage.constants.RangeOfInfluence; +import mage.game.turn.TurnMod; +import mage.players.Player; + +public abstract class GameCanadianHighlanderImpl extends GameImpl { + + protected boolean startingPlayerSkipsDraw = true; + protected Map usedMulligans = new LinkedHashMap<>(); + + public GameCanadianHighlanderImpl(MultiplayerAttackOption attackOption, RangeOfInfluence range, int freeMulligans, int startLife) { + super(attackOption, range, 0, startLife); + } + + public GameCanadianHighlanderImpl(final GameCanadianHighlanderImpl game) { + super(game); + } + + @Override + protected void init(UUID choosingPlayerId) { + super.init(choosingPlayerId); + state.getTurnMods().add(new TurnMod(startingPlayerId, PhaseStep.DRAW)); + } + + private String getNextMulligan(String mulligan) { + if (mulligan.equals("7")) { + return "6a"; + } else if (mulligan.equals("6a")) { + return "6b"; + } else if (mulligan.equals("6b")) { + return "5a"; + } else if (mulligan.equals("5a")) { + return "5b"; + } else if (mulligan.equals("5b")) { + return "4a"; + } else if (mulligan.equals("4a")) { + return "4b"; + } else if (mulligan.equals("4b")) { + return "3a"; + } else if (mulligan.equals("3a")) { + return "3b"; + } else if (mulligan.equals("3b")) { + return "2a"; + } else if (mulligan.equals("2a")) { + return "2b"; + } else if (mulligan.equals("2b")) { + return "1a"; + } else if (mulligan.equals("1a")) { + return "1b"; + } + return "0"; + } + + private int getNextMulliganNum(String mulligan) { + if (mulligan.equals("7")) { + return 6; + } else if (mulligan.equals("6a")) { + return 6; + } else if (mulligan.equals("6b")) { + return 5; + } else if (mulligan.equals("5a")) { + return 5; + } else if (mulligan.equals("5b")) { + return 4; + } else if (mulligan.equals("4a")) { + return 4; + } else if (mulligan.equals("4b")) { + return 3; + } else if (mulligan.equals("3a")) { + return 3; + } else if (mulligan.equals("3b")) { + return 2; + } else if (mulligan.equals("2a")) { + return 2; + } else if (mulligan.equals("2b")) { + return 1; + } else if (mulligan.equals("1a")) { + return 1; + } + return 0; + } + + @Override + public int mulliganDownTo(UUID playerId) { + Player player = getPlayer(playerId); + int deduction = 1; + int numToMulliganTo = -1; + if (usedMulligans != null) { + String mulliganCode = "7"; + if (usedMulligans.containsKey(player.getId())) { + mulliganCode = usedMulligans.get(player.getId()); + } + numToMulliganTo = getNextMulliganNum(mulliganCode); + } + if (numToMulliganTo == -1) { + return player.getHand().size() - deduction; + } + return numToMulliganTo; + } + + @Override + public void mulligan(UUID playerId) { + Player player = getPlayer(playerId); + int numCards = player.getHand().size(); + int numToMulliganTo = numCards; + player.getLibrary().addAll(player.getHand().getCards(this), this); + player.getHand().clear(); + player.shuffleLibrary(null, this); + if (usedMulligans != null) { + String mulliganCode = "7"; + if (usedMulligans.containsKey(player.getId())) { + mulliganCode = usedMulligans.get(player.getId()); + } + numToMulliganTo = getNextMulliganNum(mulliganCode); + usedMulligans.put(player.getId(), getNextMulligan(mulliganCode)); + } + fireInformEvent(new StringBuilder(player.getLogName()) + .append(" mulligans to ") + .append(Integer.toString(numToMulliganTo)) + .append(numToMulliganTo == 1 ? " card" : " cards").toString()); + player.drawCards(numToMulliganTo, this); + } + + @Override + public void endMulligan(UUID playerId) { + super.endMulligan(playerId); + } + + @Override + public Set getOpponents(UUID playerId) { + Set opponents = new HashSet<>(); + for (UUID opponentId : getState().getPlayersInRange(playerId, this)) { + if (!opponentId.equals(playerId)) { + opponents.add(opponentId); + } + } + return opponents; + } + + @Override + public boolean isOpponent(Player player, UUID playerToCheck) { + return !player.getId().equals(playerToCheck); + } +} diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index c85f5f2550c..981b743f15c 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -52,6 +52,7 @@ import mage.abilities.OpeningHandAction; import mage.abilities.SpellAbility; import mage.abilities.TriggeredAbility; import mage.abilities.common.AttachableToRestrictedAbility; +import mage.abilities.common.CantHaveMoreThanAmountCountersSourceAbility; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffects; import mage.abilities.effects.Effect; @@ -1923,6 +1924,19 @@ public abstract class GameImpl implements Game, Serializable { perm.getCounters(this).removeCounter(CounterType.M1M1, min); } + // 20170120 - 704.5s + // If a permanent with an ability that says it can't have more than N counters of a certain kind on it + // has more than N counters of that kind on it, all but N of those counters are removed from it. + for (Ability ability : perm.getAbilities(this)) { + if (ability instanceof CantHaveMoreThanAmountCountersSourceAbility) { + CantHaveMoreThanAmountCountersSourceAbility counterAbility = (CantHaveMoreThanAmountCountersSourceAbility) ability; + int count = perm.getCounters(this).getCount(counterAbility.getCounterType()); + if (count > counterAbility.getAmount()) { + perm.removeCounters(counterAbility.getCounterType().getName(), count - counterAbility.getAmount(), this); + somethingHappened = true; + } + } + } } //201300713 - 704.5j // If a player controls two or more planeswalkers that share a planeswalker type, that player diff --git a/Mage/src/main/java/mage/game/combat/CombatGroup.java b/Mage/src/main/java/mage/game/combat/CombatGroup.java index ca898f12bf4..455f7fb6082 100644 --- a/Mage/src/main/java/mage/game/combat/CombatGroup.java +++ b/Mage/src/main/java/mage/game/combat/CombatGroup.java @@ -399,7 +399,9 @@ public class CombatGroup implements Serializable, Copyable { } } else { Player defender = game.getPlayer(defenderId); - defender.damage(amount, attacker.getId(), game, true, true); + if (defender.isInGame()) { + defender.damage(amount, attacker.getId(), game, true, true); + } } } diff --git a/Mage/src/main/java/mage/players/net/UserData.java b/Mage/src/main/java/mage/players/net/UserData.java index b5d52c9d0a7..b6bb290d8f2 100644 --- a/Mage/src/main/java/mage/players/net/UserData.java +++ b/Mage/src/main/java/mage/players/net/UserData.java @@ -23,6 +23,7 @@ public class UserData implements Serializable { protected boolean passPriorityActivation; protected boolean autoOrderTrigger; protected boolean useFirstManaAbility = false; + private String userIdStr; protected String matchHistory; protected int matchQuitRatio; @@ -36,7 +37,7 @@ public class UserData implements Serializable { public UserData(UserGroup userGroup, int avatarId, boolean showAbilityPickerForced, boolean allowRequestShowHandCards, boolean confirmEmptyManaPool, UserSkipPrioritySteps userSkipPrioritySteps, String flagName, boolean askMoveToGraveOrder, boolean manaPoolAutomatic, boolean manaPoolAutomaticRestricted, - boolean passPriorityCast, boolean passPriorityActivation, boolean autoOrderTrigger, boolean useFirstManaAbility) { + boolean passPriorityCast, boolean passPriorityActivation, boolean autoOrderTrigger, boolean useFirstManaAbility, String userIdStr) { this.groupId = userGroup.getGroupId(); this.avatarId = avatarId; this.showAbilityPickerForced = showAbilityPickerForced; @@ -55,6 +56,7 @@ public class UserData implements Serializable { this.matchQuitRatio = 0; this.tourneyHistory = ""; this.tourneyQuitRatio = 0; + this.userIdStr = userIdStr; } public void update(UserData userData) { @@ -72,11 +74,12 @@ public class UserData implements Serializable { this.passPriorityActivation = userData.passPriorityActivation; this.autoOrderTrigger = userData.autoOrderTrigger; this.useFirstManaAbility = userData.useFirstManaAbility; + this.userIdStr = userData.userIdStr; // todo: why we don't copy user stats here? } public static UserData getDefaultUserDataView() { - return new UserData(UserGroup.DEFAULT, 0, false, false, true, null, getDefaultFlagName(), false, true, true, false, false, false, false); + return new UserData(UserGroup.DEFAULT, 0, false, false, true, null, getDefaultFlagName(), false, true, true, false, false, false, false, ""); } public void setGroupId(int groupId) { diff --git a/Mage/src/main/java/mage/target/TargetSpell.java b/Mage/src/main/java/mage/target/TargetSpell.java index aad10b11ef8..408e277bf93 100644 --- a/Mage/src/main/java/mage/target/TargetSpell.java +++ b/Mage/src/main/java/mage/target/TargetSpell.java @@ -44,6 +44,7 @@ import mage.game.stack.StackObject; public class TargetSpell extends TargetObject { protected final FilterSpell filter; + private final Set sourceIds = new HashSet<>(); public TargetSpell() { this(1, 1, new FilterSpell()); @@ -68,6 +69,7 @@ public class TargetSpell extends TargetObject { public TargetSpell(final TargetSpell target) { super(target); this.filter = target.filter.copy(); + this.sourceIds.addAll(target.sourceIds); } @Override @@ -134,4 +136,18 @@ public class TargetSpell extends TargetObject { && game.getState().getPlayersInRange(sourceControllerId, game).contains(stackObject.getControllerId()) && filter.match(stackObject, sourceID, sourceControllerId, game); } + + @Override + public void addTarget(UUID id, Ability source, Game game, boolean skipEvent) { + Spell spell = game.getStack().getSpell(id); + if (spell != null) { // remember the original sourceID + sourceIds.add(spell.getSourceId()); + } + super.addTarget(id, source, game, skipEvent); + } + + public Set getSourceIds() { + return sourceIds; + } + } diff --git a/Utils/gen-card.pl b/Utils/gen-card.pl index 31a30365dc2..923424fd1f1 100755 --- a/Utils/gen-card.pl +++ b/Utils/gen-card.pl @@ -110,7 +110,7 @@ if (!exists $cards{$cardName}) { # Check if card is already implemented my $fileName = "../Mage.Sets/src/mage/cards/".lc(substr($cardName, 0, 1))."/".toCamelCase($cardName).".java"; if(-e $fileName) { - die "$cardName is already implemented.\n"; + die "$cardName is already implemented.\n$fileName\n"; } # Generate lines to corresponding sets