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/PreferencesDialog.java b/Mage.Client/src/main/java/mage/client/dialog/PreferencesDialog.java index da61f41dfb0..4423038e08b 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"; 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/org/mage/card/arcane/CardRenderer.java b/Mage.Client/src/main/java/org/mage/card/arcane/CardRenderer.java index 7c4dbf24804..4b3bcc54b64 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/CardRenderer.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/CardRenderer.java @@ -21,7 +21,6 @@ import mage.utils.CardUtil; import mage.view.CardView; import mage.view.CounterView; import mage.view.PermanentView; -import org.apache.log4j.Logger; /** * @author stravant@gmail.com @@ -56,8 +55,6 @@ import org.apache.log4j.Logger; */ public abstract class CardRenderer { - private static final Logger LOGGER = Logger.getLogger(CardPanel.class); - /////////////////////////////////////////////////////////////////////////// // Common layout metrics between all cards // The card to be rendered diff --git a/Mage.Client/src/main/java/org/mage/card/arcane/ManaSymbols.java b/Mage.Client/src/main/java/org/mage/card/arcane/ManaSymbols.java index d1e37c6034f..32e2e6c0e79 100644 --- a/Mage.Client/src/main/java/org/mage/card/arcane/ManaSymbols.java +++ b/Mage.Client/src/main/java/org/mage/card/arcane/ManaSymbols.java @@ -17,6 +17,7 @@ import java.nio.file.SimpleFileVisitor; import java.nio.file.StandardCopyOption; import java.nio.file.attribute.BasicFileAttributes; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.StringTokenizer; @@ -38,6 +39,23 @@ public class ManaSymbols { private static boolean mediumSymbolsFound = false; private static final Map> setImages = new HashMap<>(); + + private static final HashSet onlyMythics = new HashSet<>(); + private static final HashSet withoutSymbols = new HashSet<>(); + + static { + onlyMythics.add("DRB"); + onlyMythics.add("V09"); + onlyMythics.add("V12"); + onlyMythics.add("V13"); + onlyMythics.add("V14"); + onlyMythics.add("V15"); + onlyMythics.add("V16"); + onlyMythics.add("EXP"); + onlyMythics.add("MPS"); + + withoutSymbols.add("MPRP"); + } private static final Map setImagesExist = new HashMap<>(); private static final Pattern REPLACE_SYMBOLS_PATTERN = Pattern.compile("\\{([^}/]*)/?([^}]*)\\}"); private static String cachedPath; @@ -57,7 +75,15 @@ public class ManaSymbols { return; } for (String set : setCodes) { - String[] codes = new String[]{"C", "U", "R", "M"}; + if (withoutSymbols.contains(set)) { + continue; + } + String[] codes; + if (onlyMythics.contains(set)) { + codes = new String[]{"M"}; + } else { + codes = new String[]{"C", "U", "R", "M"}; + } Map rarityImages = new HashMap<>(); setImages.put(set, rarityImages); @@ -72,7 +98,7 @@ public class ManaSymbols { if (h > 0) { Rectangle r = new Rectangle(21, (int) (h * 21.0f / width)); BufferedImage resized = ImageHelper.getResizedImage(BufferedImageBuilder.bufferImage(image, BufferedImage.TYPE_INT_ARGB), r); - rarityImages.put(set, resized); + rarityImages.put(rarityCode, resized); } } else { rarityImages.put(rarityCode, image); diff --git a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/GathererSets.java b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/GathererSets.java index 35df3572430..5d63f8ee150 100644 --- a/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/GathererSets.java +++ b/Mage.Client/src/main/java/org/mage/plugins/card/dl/sources/GathererSets.java @@ -58,13 +58,16 @@ public class GathererSets implements Iterable { "KTK", "FRF", "DTK", "BFZ", "OGW", "SOI", "EMN", - "KLD", "MPS", "AER", + "KLD", "AER", "AKH", "HOU" }; private static final String[] onlyMythics = { "DRB", "V09", "V12", "V12", "V13", "V14", "V15", "V16", "EXP" }; + private static final String[] onlyMythicsAsSpecial = { + "MPS" + }; private static final HashMap symbolsReplacements = new HashMap<>(); @@ -93,6 +96,7 @@ public class GathererSets implements Iterable { symbolsReplacements.put("LEA", "1E"); symbolsReplacements.put("LEB", "2E"); symbolsReplacements.put("LEG", "LE"); + symbolsReplacements.put("MPS", "MPS_KLD"); symbolsReplacements.put("MIR", "MI"); symbolsReplacements.put("MMQ", "MM"); symbolsReplacements.put("NEM", "NE"); @@ -123,41 +127,47 @@ public class GathererSets implements Iterable { public Iterator iterator() { Calendar c = Calendar.getInstance(); c.setTime(new Date()); - c.add(Calendar.DATE, -14); + c.add(Calendar.DATE, +14); // Try to load the symbols eralies 14 days before release date Date compareDate = c.getTime(); ArrayList jobs = new ArrayList<>(); for (String symbol : symbols) { ExpansionSet exp = Sets.findSet(symbol); if (exp != null && exp.getReleaseDate().before(compareDate)) { - jobs.add(generateDownloadJob(symbol, "C")); - jobs.add(generateDownloadJob(symbol, "U")); - jobs.add(generateDownloadJob(symbol, "R")); + jobs.add(generateDownloadJob(symbol, "C", "C")); + jobs.add(generateDownloadJob(symbol, "U", "U")); + jobs.add(generateDownloadJob(symbol, "R", "R")); } } for (String symbol : withMythics) { ExpansionSet exp = Sets.findSet(symbol); if (exp != null && exp.getReleaseDate().before(compareDate)) { - jobs.add(generateDownloadJob(symbol, "C")); - jobs.add(generateDownloadJob(symbol, "U")); - jobs.add(generateDownloadJob(symbol, "R")); - jobs.add(generateDownloadJob(symbol, "M")); + jobs.add(generateDownloadJob(symbol, "C", "C")); + jobs.add(generateDownloadJob(symbol, "U", "U")); + jobs.add(generateDownloadJob(symbol, "R", "R")); + jobs.add(generateDownloadJob(symbol, "M", "M")); } } for (String symbol : onlyMythics) { ExpansionSet exp = Sets.findSet(symbol); if (exp != null && exp.getReleaseDate().before(compareDate)) { - jobs.add(generateDownloadJob(symbol, "M")); + jobs.add(generateDownloadJob(symbol, "M", "M")); + } + } + for (String symbol : onlyMythicsAsSpecial) { + ExpansionSet exp = Sets.findSet(symbol); + if (exp != null && exp.getReleaseDate().before(compareDate)) { + jobs.add(generateDownloadJob(symbol, "M", "S")); } } return jobs.iterator(); } - private DownloadJob generateDownloadJob(String set, String rarity) { + private DownloadJob generateDownloadJob(String set, String rarity, String urlRarity) { File dst = new File(outDir, set + "-" + rarity + ".jpg"); if (symbolsReplacements.containsKey(set)) { set = symbolsReplacements.get(set); } - String url = "http://gatherer.wizards.com/Handlers/Image.ashx?type=symbol&set=" + set + "&size=small&rarity=" + rarity; + String url = "http://gatherer.wizards.com/Handlers/Image.ashx?type=symbol&set=" + set + "&size=small&rarity=" + urlRarity; return new DownloadJob(set + "-" + rarity, fromURL(url), toFile(dst)); } diff --git a/Mage.Common/src/mage/utils/MageVersion.java b/Mage.Common/src/mage/utils/MageVersion.java index 33185a3fd3e..adf31bb5b63 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 = "V0"; + public final static String MAGE_VERSION_MINOR_PATCH = "V1"; public final static String MAGE_VERSION_INFO = ""; private final int major; diff --git a/Mage.Server/config/config.xml b/Mage.Server/config/config.xml index fd41c97a47c..1192fab3840 100644 --- a/Mage.Server/config/config.xml +++ b/Mage.Server/config/config.xml @@ -107,6 +107,7 @@ + diff --git a/Mage.Server/release/config/config.xml b/Mage.Server/release/config/config.xml index 0f2c1d167eb..e488bf20e9e 100644 --- a/Mage.Server/release/config/config.xml +++ b/Mage.Server/release/config/config.xml @@ -104,6 +104,7 @@ + diff --git a/Mage.Server/src/main/java/mage/server/ChatManager.java b/Mage.Server/src/main/java/mage/server/ChatManager.java index 69c51f2a6d1..eb0938a0e2e 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/TableController.java b/Mage.Server/src/main/java/mage/server/TableController.java index 28f1be09b7b..21d6f8aec6c 100644 --- a/Mage.Server/src/main/java/mage/server/TableController.java +++ b/Mage.Server/src/main/java/mage/server/TableController.java @@ -27,6 +27,14 @@ */ package mage.server; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Optional; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; import mage.MageException; import mage.cards.decks.Deck; import mage.cards.decks.DeckCardLists; @@ -60,15 +68,6 @@ import mage.server.util.ThreadExecutor; import mage.view.ChatMessage; import org.apache.log4j.Logger; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Optional; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; - /** * @author BetaSteward_at_googlemail.com */ @@ -96,10 +95,9 @@ public class TableController { if (userId != null) { Optional user = UserManager.getInstance().getUser(userId); // TODO: Handle if user == null - if(user.isPresent()) { + if (user.isPresent()) { controllerName = user.get().getName(); - } - else{ + } else { controllerName = "undefined"; } } else { @@ -578,10 +576,10 @@ public class TableController { GameManager.getInstance().createGameSession(match.getGame(), userPlayerMap, table.getId(), choosingPlayerId, gameOptions); String creator = null; StringBuilder opponent = new StringBuilder(); - for (Entry entry : userPlayerMap.entrySet()) { // no AI players + for (Entry entry : userPlayerMap.entrySet()) { // do only for no AI players if (match.getPlayer(entry.getValue()) != null && !match.getPlayer(entry.getValue()).hasQuit()) { Optional _user = UserManager.getInstance().getUser(entry.getKey()); - if (!_user.isPresent()) { + if (_user.isPresent()) { User user = _user.get(); user.ccGameStarted(match.getGame().getId(), entry.getValue()); @@ -978,8 +976,8 @@ public class TableController { void cleanUp() { if (!table.isTournamentSubTable()) { for (Map.Entry entry : userPlayerMap.entrySet()) { - UserManager.getInstance().getUser(entry.getKey()).ifPresent(user -> - user.removeTable(entry.getValue())); + UserManager.getInstance().getUser(entry.getKey()).ifPresent(user + -> user.removeTable(entry.getValue())); } } 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 0417687ab76..854f40680ed 100644 --- a/Mage.Server/src/main/java/mage/server/game/GameController.java +++ b/Mage.Server/src/main/java/mage/server/game/GameController.java @@ -313,7 +313,7 @@ public class GameController implements GameCallback { logger.fatal("- userId: " + userId); return; } - if(!user.isPresent(){ + if (!user.isPresent()) { logger.fatal("User not found : "+userId); return; } diff --git a/Mage.Sets/src/mage/cards/a/AidFromTheCowl.java b/Mage.Sets/src/mage/cards/a/AidFromTheCowl.java index 81d8be69464..95e03ecdca5 100644 --- a/Mage.Sets/src/mage/cards/a/AidFromTheCowl.java +++ b/Mage.Sets/src/mage/cards/a/AidFromTheCowl.java @@ -110,6 +110,8 @@ class AidFromTheCowlEffect extends OneShotEffect { controller.moveCards(card, Zone.BATTLEFIELD, source, game); } else if (controller.chooseUse(Outcome.Neutral, "Put " + card.getIdName() + " on the bottom of your library?", source, game)) { controller.putCardsOnBottomOfLibrary(cards, game, source, false); + } else { + game.informPlayers(controller.getLogName() + " puts the revealed card back to the top of the library."); } } } diff --git a/Mage.Sets/src/mage/cards/b/BlanketOfNight.java b/Mage.Sets/src/mage/cards/b/BlanketOfNight.java new file mode 100644 index 00000000000..5807f7a5a6d --- /dev/null +++ b/Mage.Sets/src/mage/cards/b/BlanketOfNight.java @@ -0,0 +1,70 @@ +/* + * 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.Ability; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.GainAbilityAllEffect; +import mage.abilities.mana.BlackManaAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.abilities.effects.common.continuous.AddCardSubtypeAllEffect; +import mage.constants.CardType; +import mage.constants.DependencyType; +import mage.constants.Duration; +import mage.constants.Zone; +import mage.filter.common.FilterLandPermanent; + +/** + * + * @author Galatolol + */ +public class BlanketOfNight extends CardImpl { + + public BlanketOfNight(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{B}{B}"); + + + // Each land is a Swamp in addition to its other land types. + Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(new BlackManaAbility(), Duration.WhileOnBattlefield, new FilterLandPermanent(), + "Each land is a Swamp in addition to its other land types")); + ability.addEffect(new AddCardSubtypeAllEffect(new FilterLandPermanent(), "Swamp", DependencyType.BecomeSwamp)); + this.addAbility(ability); + } + + public BlanketOfNight(final BlanketOfNight card) { + super(card); + } + + @Override + public BlanketOfNight copy() { + return new BlanketOfNight(this); + } +} diff --git a/Mage.Sets/src/mage/cards/c/ChiefOfTheFoundry.java b/Mage.Sets/src/mage/cards/c/ChiefOfTheFoundry.java index 56b27d77b6d..8b309aabc70 100644 --- a/Mage.Sets/src/mage/cards/c/ChiefOfTheFoundry.java +++ b/Mage.Sets/src/mage/cards/c/ChiefOfTheFoundry.java @@ -46,8 +46,8 @@ import mage.filter.predicate.permanent.ControllerPredicate; * @author fireshoes */ public class ChiefOfTheFoundry extends CardImpl { - - private static final FilterCreaturePermanent filterBoosted = new FilterCreaturePermanent("artifact creatures"); + + private static final FilterCreaturePermanent filterBoosted = new FilterCreaturePermanent("Other artifact creatures you control"); static { filterBoosted.add(new CardTypePredicate(CardType.ARTIFACT)); @@ -55,7 +55,7 @@ public class ChiefOfTheFoundry extends CardImpl { } public ChiefOfTheFoundry(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{3}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}"); this.subtype.add("Construct"); this.power = new MageInt(2); this.toughness = new MageInt(3); diff --git a/Mage.Sets/src/mage/cards/c/CorruptedZendikon.java b/Mage.Sets/src/mage/cards/c/CorruptedZendikon.java index 8dd44ba5c60..a9712413b6c 100644 --- a/Mage.Sets/src/mage/cards/c/CorruptedZendikon.java +++ b/Mage.Sets/src/mage/cards/c/CorruptedZendikon.java @@ -27,6 +27,8 @@ */ package mage.cards.c; +import java.util.UUID; +import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.DiesAttachedTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; @@ -37,12 +39,10 @@ import mage.abilities.keyword.EnchantAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; -import mage.game.permanent.token.OozeToken; +import mage.game.permanent.token.Token; import mage.target.TargetPermanent; import mage.target.common.TargetLandPermanent; -import java.util.UUID; - /** * * @author jeffwadsworth @@ -54,17 +54,19 @@ public class CorruptedZendikon extends CardImpl { this.subtype.add("Aura"); // Enchant land - // Enchanted land is a 3/3 black Ooze creature. It's still a land. - // When enchanted land dies, return that card to its owner's hand. TargetPermanent auraTarget = new TargetLandPermanent(); this.getSpellAbility().addTarget(auraTarget); this.getSpellAbility().addEffect(new AttachEffect(Outcome.PutCreatureInPlay)); Ability ability = new EnchantAbility(auraTarget.getTargetName()); this.addAbility(ability); - Ability ability2 = new SimpleStaticAbility(Zone.BATTLEFIELD, new BecomesCreatureAttachedEffect(new OozeToken(3, 3), "Enchanted land is a 3/3 black Ooze creature. It's still a land.", Duration.WhileOnBattlefield)); + // Enchanted land is a 3/3 black Ooze creature. It's still a land. + Ability ability2 = new SimpleStaticAbility(Zone.BATTLEFIELD, + new BecomesCreatureAttachedEffect(new CorruptedZendikonOozeToken(), + "Enchanted land is a 3/3 black Ooze creature. It's still a land.", Duration.WhileOnBattlefield)); this.addAbility(ability2); + // When enchanted land dies, return that card to its owner's hand. Ability ability3 = new DiesAttachedTriggeredAbility(new ReturnToHandAttachedEffect(), "enchanted land", false); this.addAbility(ability3); } @@ -78,3 +80,16 @@ public class CorruptedZendikon extends CardImpl { return new CorruptedZendikon(this); } } + +class CorruptedZendikonOozeToken extends Token { + + public CorruptedZendikonOozeToken() { + super("Ooze", "3/3 black Ooze creature"); + cardType.add(CardType.CREATURE); + color.setBlack(true); + subtype.add("Ooze"); + this.power = new MageInt(3); + this.toughness = new MageInt(3); + } + +} diff --git a/Mage.Sets/src/mage/cards/d/Donate.java b/Mage.Sets/src/mage/cards/d/Donate.java index 338195434fc..de1284c6656 100644 --- a/Mage.Sets/src/mage/cards/d/Donate.java +++ b/Mage.Sets/src/mage/cards/d/Donate.java @@ -29,19 +29,20 @@ package mage.cards.d; import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.effects.ContinuousEffectImpl; +import mage.abilities.effects.ContinuousEffect; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.continuous.GainControlTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.constants.Layer; import mage.constants.Outcome; -import mage.constants.SubLayer; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetPlayer; import mage.target.common.TargetControlledPermanent; +import mage.target.targetpointer.FixedTarget; /** * @@ -52,7 +53,6 @@ public class Donate extends CardImpl { public Donate(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{U}"); - // Target player gains control of target permanent you control. this.getSpellAbility().addEffect(new DonateEffect()); this.getSpellAbility().addTarget(new TargetPlayer()); @@ -69,10 +69,10 @@ public class Donate extends CardImpl { } } -class DonateEffect extends ContinuousEffectImpl { +class DonateEffect extends OneShotEffect { public DonateEffect() { - super(Duration.EndOfGame, Layer.ControlChangingEffects_2, SubLayer.NA, Outcome.Benefit); + super(Outcome.Detriment); this.staticText = "Target player gains control of target permanent you control"; } @@ -86,14 +86,13 @@ class DonateEffect extends ContinuousEffectImpl { } @Override - public boolean apply(Game game, Ability source) { - UUID controllerId = source.getTargets().get(0).getFirstTarget(); - Player controller = game.getPlayer(controllerId); + public boolean apply(Game game, Ability source) { + Player targetPlayer = game.getPlayer(getTargetPointer().getFirst(game, source)); Permanent permanent = game.getPermanent(source.getTargets().get(1).getFirstTarget()); - if (controller != null && permanent != null) { - permanent.changeControllerId(controllerId, game); - } else { - this.discard(); + if (targetPlayer != null && permanent != null) { + ContinuousEffect effect = new GainControlTargetEffect(Duration.Custom, true, targetPlayer.getId()); + effect.setTargetPointer(new FixedTarget(permanent, game)); + game.addEffect(effect, source); } return true; } diff --git a/Mage.Sets/src/mage/cards/e/EternalScourge.java b/Mage.Sets/src/mage/cards/e/EternalScourge.java index 400375ae396..85e7fb3a751 100644 --- a/Mage.Sets/src/mage/cards/e/EternalScourge.java +++ b/Mage.Sets/src/mage/cards/e/EternalScourge.java @@ -53,7 +53,7 @@ import mage.game.events.GameEvent.EventType; public class EternalScourge extends CardImpl { public EternalScourge(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}"); this.subtype.add("Eldrazi"); this.subtype.add("Horror"); this.power = new MageInt(3); @@ -101,13 +101,14 @@ class EternalScourgePlayEffect extends AsThoughEffectImpl { public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) { if (sourceId.equals(source.getSourceId())) { Card card = game.getCard(source.getSourceId()); - if (card != null && card.getOwnerId().equals(source.getControllerId()) && game.getState().getZone(source.getSourceId()) == Zone.EXILED) { + if (card != null && card.getOwnerId().equals(affectedControllerId) && game.getState().getZone(source.getSourceId()) == Zone.EXILED) { return true; } } return false; } } + class EternalScourgeAbility extends TriggeredAbilityImpl { public EternalScourgeAbility() { diff --git a/Mage.Sets/src/mage/cards/f/FairgroundsTrumpeter.java b/Mage.Sets/src/mage/cards/f/FairgroundsTrumpeter.java index 6d31fd6d877..21831facd9c 100644 --- a/Mage.Sets/src/mage/cards/f/FairgroundsTrumpeter.java +++ b/Mage.Sets/src/mage/cards/f/FairgroundsTrumpeter.java @@ -115,6 +115,9 @@ class FairgroundsTrumpeterWatcher extends Watcher { public void watch(GameEvent event, Game game) { if (event.getType() == GameEvent.EventType.COUNTER_ADDED && event.getData().equals(CounterType.P1P1.getName())) { Permanent permanent = game.getPermanentOrLKIBattlefield(event.getTargetId()); + if (permanent == null) { + permanent = game.getPermanentEntering(event.getTargetId()); + } if (permanent != null) { players.add(permanent.getControllerId()); } diff --git a/Mage.Sets/src/mage/cards/f/FatalPush.java b/Mage.Sets/src/mage/cards/f/FatalPush.java index 33503498e84..9ff7c18c237 100644 --- a/Mage.Sets/src/mage/cards/f/FatalPush.java +++ b/Mage.Sets/src/mage/cards/f/FatalPush.java @@ -71,7 +71,7 @@ class FatalPushEffect extends OneShotEffect { FatalPushEffect() { super(Outcome.DestroyPermanent); - this.staticText = "Destroy target creature if it has converted mana cost 2 or less.
Revolt — Destroy that creature if it has converted mana cost 4 or less instead if a permanent you controlled left the battlefield this turn."; + this.staticText = "Destroy target creature if it has converted mana cost 2 or less.
Revolt — Destroy that creature if it has converted mana cost 4 or less instead if a permanent you controlled left the battlefield this turn"; } FatalPushEffect(final FatalPushEffect effect) { diff --git a/Mage.Sets/src/mage/cards/g/GhostHounds.java b/Mage.Sets/src/mage/cards/g/GhostHounds.java new file mode 100644 index 00000000000..5dbef9e482a --- /dev/null +++ b/Mage.Sets/src/mage/cards/g/GhostHounds.java @@ -0,0 +1,79 @@ +/* + * 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.g; + +import java.util.UUID; +import mage.MageInt; +import mage.ObjectColor; +import mage.abilities.common.BlocksOrBecomesBlockedTriggeredAbility; +import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; +import mage.abilities.keyword.FirstStrikeAbility; +import mage.abilities.keyword.VigilanceAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.mageobject.ColorPredicate; + +/** + * + * @author Galatolol + */ +public class GhostHounds extends CardImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("white creature"); + + static { + filter.add(new ColorPredicate(ObjectColor.WHITE)); + } + + public GhostHounds(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); + + this.subtype.add("Hound"); + this.subtype.add("Spirit"); + this.power = new MageInt(1); + this.toughness = new MageInt(1); + + // Vigilance + this.addAbility(VigilanceAbility.getInstance()); + + // Whenever Ghost Hounds blocks or becomes blocked by a white creature, Ghost Hounds gains first strike until end of turn. + this.addAbility(new BlocksOrBecomesBlockedTriggeredAbility(new GainAbilitySourceEffect(FirstStrikeAbility.getInstance(), Duration.EndOfTurn), filter, false)); + + } + + public GhostHounds(final GhostHounds card) { + super(card); + } + @Override + public GhostHounds copy() { + return new GhostHounds(this); + } +} diff --git a/Mage.Sets/src/mage/cards/h/Hivestone.java b/Mage.Sets/src/mage/cards/h/Hivestone.java new file mode 100644 index 00000000000..2f5d24e4a4b --- /dev/null +++ b/Mage.Sets/src/mage/cards/h/Hivestone.java @@ -0,0 +1,46 @@ +package mage.cards.h; + +import java.util.ArrayList; +import java.util.UUID; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.continuous.BecomesSubtypeAllEffect; +import mage.cards.Card; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.*; +import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.permanent.ControllerPredicate; + +/** + * Created by Alexsandr0x. + */ +public class Hivestone extends CardImpl { + + private final static FilterCreaturePermanent filter = new FilterCreaturePermanent("Creatures you control"); + + static { + filter.add(new ControllerPredicate(TargetController.YOU)); + } + + public Hivestone(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); + + // Creatures you control are Slivers in addition to their other creature types. + ArrayList subTypes = new ArrayList<>(); + subTypes.add("Slivers"); + 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)); + } + + public Hivestone(final Hivestone card) { + super(card); + } + + @Override + public Card copy() { + return new Hivestone(this); + } + +} diff --git a/Mage.Sets/src/mage/cards/h/HopeOfGhirapur.java b/Mage.Sets/src/mage/cards/h/HopeOfGhirapur.java index 0dfb3029ca5..411652317cc 100644 --- a/Mage.Sets/src/mage/cards/h/HopeOfGhirapur.java +++ b/Mage.Sets/src/mage/cards/h/HopeOfGhirapur.java @@ -33,6 +33,7 @@ import java.util.Set; import java.util.UUID; import mage.MageInt; import mage.MageObject; +import mage.MageObjectReference; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.SacrificeSourceCost; @@ -88,7 +89,8 @@ public class HopeOfGhirapur extends CardImpl { if (sourceObject != null) { ability.getTargets().clear(); FilterPlayer playerFilter = new FilterPlayer("player who was dealt combat damage by " + sourceObject.getIdName() + " this turn"); - playerFilter.add(new HopeOfGhirapurPlayerLostLifePredicate(ability.getSourceId())); + MageObjectReference sourceReference = new MageObjectReference(ability.getSourceId(), ability.getSourceObjectZoneChangeCounter(), game); + playerFilter.add(new HopeOfGhirapurPlayerLostLifePredicate(sourceReference)); ability.addTarget(new TargetPlayer(1, 1, false, playerFilter)); } } @@ -155,17 +157,17 @@ class HopeOfGhirapurCantCastEffect extends ContinuousRuleModifyingEffectImpl { class HopeOfGhirapurPlayerLostLifePredicate implements Predicate { - private final UUID sourceId; + private final MageObjectReference sourceReference; - public HopeOfGhirapurPlayerLostLifePredicate(UUID sourceId) { - this.sourceId = sourceId; + public HopeOfGhirapurPlayerLostLifePredicate(MageObjectReference sourceReference) { + this.sourceReference = sourceReference; } @Override public boolean apply(Player input, Game game) { HopeOfGhirapurCombatDamageWatcher watcher = (HopeOfGhirapurCombatDamageWatcher) game.getState().getWatchers().get(HopeOfGhirapurCombatDamageWatcher.class.getName()); if (watcher != null) { - return watcher.playerGotCombatDamage(sourceId, input.getId()); + return watcher.playerGotCombatDamage(sourceReference, input.getId()); } return false; } @@ -173,7 +175,7 @@ class HopeOfGhirapurPlayerLostLifePredicate implements Predicate { class HopeOfGhirapurCombatDamageWatcher extends Watcher { - private final HashMap> combatDamagedPlayers = new HashMap<>(); + private final HashMap> combatDamagedPlayers = new HashMap<>(); public HopeOfGhirapurCombatDamageWatcher() { super(HopeOfGhirapurCombatDamageWatcher.class.getName(), WatcherScope.GAME); @@ -181,10 +183,10 @@ class HopeOfGhirapurCombatDamageWatcher extends Watcher { public HopeOfGhirapurCombatDamageWatcher(final HopeOfGhirapurCombatDamageWatcher watcher) { super(watcher); - for (UUID objectId : watcher.combatDamagedPlayers.keySet()) { + for (MageObjectReference sourceReference : watcher.combatDamagedPlayers.keySet()) { Set players = new HashSet<>(); - players.addAll(watcher.combatDamagedPlayers.get(objectId)); - this.combatDamagedPlayers.put(objectId, players); + players.addAll(watcher.combatDamagedPlayers.get(sourceReference)); + this.combatDamagedPlayers.put(sourceReference, players); } } @@ -196,28 +198,29 @@ class HopeOfGhirapurCombatDamageWatcher extends Watcher { @Override public void watch(GameEvent event, Game game) { if (event.getType() == EventType.DAMAGED_PLAYER && ((DamagedPlayerEvent) event).isCombatDamage()) { + MageObjectReference sourceReference = new MageObjectReference(event.getSourceId(), game); Set players; - if (combatDamagedPlayers.containsKey(event.getSourceId())) { - players = combatDamagedPlayers.get(event.getSourceId()); + if (combatDamagedPlayers.containsKey(sourceReference)) { + players = combatDamagedPlayers.get(sourceReference); } else { players = new HashSet<>(); - combatDamagedPlayers.put(event.getSourceId(), players); + combatDamagedPlayers.put(sourceReference, players); } players.add(event.getTargetId()); } } /** - * Checks if the current object with sourceId has damaged the player during - * the current turn. The zoneChangeCounter will be taken into account. + * Checks if the current object has damaged the player during + * the current turn. * - * @param sourceId - * @param game + * @param objectReference + * @param playerId * @return */ - public boolean playerGotCombatDamage(UUID sourceId, UUID playerId) { - if (combatDamagedPlayers.containsKey(sourceId)) { - return combatDamagedPlayers.get(sourceId).contains(playerId); + public boolean playerGotCombatDamage(MageObjectReference objectReference, UUID playerId) { + if (combatDamagedPlayers.containsKey(objectReference)) { + return combatDamagedPlayers.get(objectReference).contains(playerId); } return false; } diff --git a/Mage.Sets/src/mage/cards/i/InvaderParasite.java b/Mage.Sets/src/mage/cards/i/InvaderParasite.java index 87754e3d489..9f9197a62b7 100644 --- a/Mage.Sets/src/mage/cards/i/InvaderParasite.java +++ b/Mage.Sets/src/mage/cards/i/InvaderParasite.java @@ -54,15 +54,18 @@ import mage.target.targetpointer.FixedTarget; public class InvaderParasite extends CardImpl { public InvaderParasite(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{R}"); this.subtype.add("Insect"); this.power = new MageInt(3); this.toughness = new MageInt(2); + // Imprint - When Invader Parasite enters the battlefield, exile target land. Ability ability = new EntersBattlefieldTriggeredAbility(new InvaderParasiteImprintEffect(), false); ability.addTarget(new TargetLandPermanent()); this.addAbility(ability); + + // Whenever a land with the same name as the exiled card enters the battlefield under an opponent's control, Invader Parasite deals 2 damage to that player. this.addAbility(new InvaderParasiteTriggeredAbility()); } @@ -77,6 +80,7 @@ public class InvaderParasite extends CardImpl { } class InvaderParasiteImprintEffect extends OneShotEffect { + InvaderParasiteImprintEffect() { super(Outcome.Exile); staticText = "exile target land"; @@ -104,6 +108,7 @@ class InvaderParasiteImprintEffect extends OneShotEffect { } class InvaderParasiteTriggeredAbility extends TriggeredAbilityImpl { + InvaderParasiteTriggeredAbility() { super(Zone.BATTLEFIELD, new DamageTargetEffect(2)); } @@ -125,12 +130,12 @@ class InvaderParasiteTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { if (game.getOpponents(this.controllerId).contains(event.getPlayerId())) { - Permanent p = game.getPermanent(event.getTargetId()); + Permanent targetPermanent = game.getPermanent(event.getTargetId()); Permanent sourcePermanent = game.getPermanent(getSourceId()); - if (p != null && sourcePermanent != null) { + if (targetPermanent != null && sourcePermanent != null) { if (sourcePermanent.getImprinted().size() > 0) { Card imprintedCard = game.getCard(sourcePermanent.getImprinted().get(0)); - if (p.getName().equals(imprintedCard.getName())) { + if (imprintedCard != null && targetPermanent.getName().equals(imprintedCard.getName())) { for (Effect effect : this.getEffects()) { effect.setTargetPointer(new FixedTarget(event.getPlayerId())); } diff --git a/Mage.Sets/src/mage/cards/l/LightningRunner.java b/Mage.Sets/src/mage/cards/l/LightningRunner.java index 4bb0e1dd231..3c992aee573 100644 --- a/Mage.Sets/src/mage/cards/l/LightningRunner.java +++ b/Mage.Sets/src/mage/cards/l/LightningRunner.java @@ -87,8 +87,8 @@ class LightningRunnerEffect extends OneShotEffect { LightningRunnerEffect() { super(Outcome.Benefit); - staticText = "you get {E}{E}, then you may pay {E}{E}{E}{E}{E}{E}{E}{E}. If you do, " + - "untap all creatures you control and after this phase, there is an additional combat phase"; + staticText = "you get {E}{E}, then you may pay {E}{E}{E}{E}{E}{E}{E}{E}. If you do, " + + "untap all creatures you control and after this phase, there is an additional combat phase"; } LightningRunnerEffect(final LightningRunnerEffect effect) { @@ -100,11 +100,15 @@ class LightningRunnerEffect extends OneShotEffect { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { new GetEnergyCountersControllerEffect(2).apply(game, source); - if (controller.getCounters().getCount(CounterType.ENERGY) > 5) { - Cost cost = new PayEnergyCost(6); - if (cost.pay(source, game, source.getSourceId(), source.getControllerId(), true)) { - new UntapAllControllerEffect(new FilterControlledCreaturePermanent(), "untap all creatures you control").apply(game, source); - new AdditionalCombatPhaseEffect("and after this phase, there is an additional combat phase").apply(game, source); + if (controller.getCounters().getCount(CounterType.ENERGY) > 7) { + Cost cost = new PayEnergyCost(8); + if (controller.chooseUse(outcome, + "Pay {E}{E}{E}{E}{E}{E}{E}{E} to use this? ", + "Untap all creatures you control and after this phase, there is an additional combat phase.", + "Yes", "No", source, game) + && cost.pay(source, game, source.getSourceId(), source.getControllerId(), true)) { + new UntapAllControllerEffect(new FilterControlledCreaturePermanent()).apply(game, source); + new AdditionalCombatPhaseEffect().apply(game, source); } } return true; diff --git a/Mage.Sets/src/mage/cards/m/Morale.java b/Mage.Sets/src/mage/cards/m/Morale.java new file mode 100644 index 00000000000..93b40bb0f26 --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/Morale.java @@ -0,0 +1,62 @@ +/* + * 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.m; + +import java.util.UUID; + +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.filter.common.FilterAttackingCreature; + +/** + * + * @author Galatolol + */ +public class Morale extends CardImpl { + + public Morale(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}{W}"); + + + // Attacking creatures get +1/+1 until end of turn. + this.getSpellAbility().addEffect(new BoostAllEffect(1, 1, Duration.EndOfTurn, new FilterAttackingCreature("Attacking creatures"), false)); + + } + + public Morale(final Morale card) { + super(card); + } + + @Override + public Morale copy() { + return new Morale(this); + } +} diff --git a/Mage.Sets/src/mage/cards/m/MuragandaPetroglyphs.java b/Mage.Sets/src/mage/cards/m/MuragandaPetroglyphs.java new file mode 100644 index 00000000000..78181d7245d --- /dev/null +++ b/Mage.Sets/src/mage/cards/m/MuragandaPetroglyphs.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.m; + +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Abilities; +import mage.abilities.Ability; +import mage.abilities.SpellAbility; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.continuous.BoostAllEffect; +import mage.cards.Card; +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; +import mage.filter.predicate.Predicate; +import mage.game.Game; + +/** + * + * @author anonymous + */ +public class MuragandaPetroglyphs extends CardImpl { + + private static final FilterCreaturePermanent filterNoAbilities + = new FilterCreaturePermanent("Creatures with no ability"); + + static { + filterNoAbilities.add(new NoAbilityPredicate()); + } + + public MuragandaPetroglyphs(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{G}"); + this.expansionSetCode = "FUT"; + + // Creatures with no abilities get +2/+2. + this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostAllEffect( + 2, 2, Duration.WhileOnBattlefield, filterNoAbilities, false))); + } + + public MuragandaPetroglyphs(final MuragandaPetroglyphs card) { + super(card); + } + + @Override + public MuragandaPetroglyphs copy() { + return new MuragandaPetroglyphs(this); + } +} + +class NoAbilityPredicate implements Predicate { + + @Override + public boolean apply(MageObject input, Game game) { + boolean isFaceDown = false; + Abilities abilities; + if (input instanceof Card) { + abilities = ((Card) input).getAbilities(game); + isFaceDown = ((Card) input).isFaceDown(game); + } else { + abilities = input.getAbilities(); + } + if (isFaceDown) { + for (Ability ability : abilities) { + if (!ability.getSourceId().equals(input.getId())) { + return false; + } + } + return true; + } + + for (Ability ability : abilities) { + if (ability.getClass() != SpellAbility.class) { + + return false; + } + } + return true; + } + + @Override + public String toString() { + return "with no abilities"; + } +} diff --git a/Mage.Sets/src/mage/cards/p/PossibilityStorm.java b/Mage.Sets/src/mage/cards/p/PossibilityStorm.java index 30742acac95..8ebea656995 100644 --- a/Mage.Sets/src/mage/cards/p/PossibilityStorm.java +++ b/Mage.Sets/src/mage/cards/p/PossibilityStorm.java @@ -56,7 +56,7 @@ import mage.target.targetpointer.FixedTarget; public class PossibilityStorm extends CardImpl { public PossibilityStorm(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{R}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{R}{R}"); // Whenever a player casts a spell from his or her hand, that player exiles it, then exiles cards from // the top of his or her library until he or she exiles a card that shares a card type with it. That @@ -133,14 +133,14 @@ class PossibilityStormEffect extends OneShotEffect { if (sourceObject != null && spell != null) { Player spellController = game.getPlayer(spell.getControllerId()); if (spellController != null - && spellController.moveCardToExileWithInfo(spell, source.getSourceId(), sourceObject.getIdName(), source.getSourceId(), game, Zone.STACK, true)) { + && spellController.moveCardsToExile(spell, source, game, true, source.getSourceId(), sourceObject.getIdName())) { if (spellController.getLibrary().size() > 0) { Library library = spellController.getLibrary(); Card card; do { - card = library.removeFromTop(game); + card = library.getFromTop(game); if (card != null) { - spellController.moveCardToExileWithInfo(card, source.getSourceId(), sourceObject.getIdName(), source.getSourceId(), game, Zone.LIBRARY, true); + spellController.moveCardsToExile(card, source, game, true, source.getSourceId(), sourceObject.getIdName()); } } while (library.size() > 0 && card != null && !sharesType(card, spell.getCardType())); @@ -154,10 +154,7 @@ class PossibilityStormEffect extends OneShotEffect { ExileZone exile = game.getExile().getExileZone(source.getSourceId()); if (exile != null) { - while (exile.size() > 0) { - card = exile.getRandom(game); - spellController.moveCardToLibraryWithInfo(card, source.getSourceId(), game, Zone.EXILED, false, false); - } + spellController.putCardsOnBottomOfLibrary(exile, game, source, false); } } diff --git a/Mage.Sets/src/mage/cards/p/PowerstoneMinefield.java b/Mage.Sets/src/mage/cards/p/PowerstoneMinefield.java new file mode 100644 index 00000000000..a86873d9659 --- /dev/null +++ b/Mage.Sets/src/mage/cards/p/PowerstoneMinefield.java @@ -0,0 +1,106 @@ +/* + * 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.p; + +import java.util.UUID; +import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.effects.Effect; +import mage.abilities.effects.common.DamageTargetEffect; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Zone; +import mage.filter.common.FilterCreaturePermanent; +import mage.game.Game; +import mage.game.events.GameEvent; +import mage.game.events.GameEvent.EventType; +import mage.game.permanent.Permanent; +import mage.target.targetpointer.FixedTarget; + +/** + * + * @author vereena42 + */ +public class PowerstoneMinefield extends CardImpl { + + public PowerstoneMinefield(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}{W}"); + + // Whenever a creature attacks or blocks, Powerstone Minefield deals 2 damage to it. + this.addAbility(new PowerstoneMinefieldTriggeredAbility()); + } + + public PowerstoneMinefield(final PowerstoneMinefield card) { + super(card); + } + + @Override + public PowerstoneMinefield copy() { + return new PowerstoneMinefield(this); + } +} + +class PowerstoneMinefieldTriggeredAbility extends TriggeredAbilityImpl { + + private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); + + public PowerstoneMinefieldTriggeredAbility() { + super(Zone.BATTLEFIELD, new DamageTargetEffect(2), false); + } + + public PowerstoneMinefieldTriggeredAbility(PowerstoneMinefieldTriggeredAbility ability) { + super(ability); + } + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == EventType.ATTACKER_DECLARED || event.getType() == EventType.BLOCKER_DECLARED; + } + + @Override + public boolean checkTrigger(GameEvent event, Game game) { + Permanent permanent = game.getPermanent(event.getSourceId()); + if (filter.match(permanent, getSourceId(), getControllerId(), game)) { + for (Effect effect : this.getEffects()) { + effect.setTargetPointer(new FixedTarget(permanent, game)); + } + return true; + } + return false; + } + + @Override + public String getRule() { + return "Whenever a creature attacks or blocks, {this} deals 2 damage to it."; + } + + @Override + public PowerstoneMinefieldTriggeredAbility copy() { + return new PowerstoneMinefieldTriggeredAbility(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SeeBeyond.java b/Mage.Sets/src/mage/cards/s/SeeBeyond.java index a591e49dba8..c0db7992f86 100644 --- a/Mage.Sets/src/mage/cards/s/SeeBeyond.java +++ b/Mage.Sets/src/mage/cards/s/SeeBeyond.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,23 +20,22 @@ * 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.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Zone; 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.FilterCard; import mage.game.Game; import mage.players.Player; @@ -49,7 +48,7 @@ import mage.target.TargetCard; public class SeeBeyond extends CardImpl { public SeeBeyond(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{U}"); this.getSpellAbility().addEffect(new SeeBeyondEffect()); } @@ -67,8 +66,6 @@ public class SeeBeyond extends CardImpl { class SeeBeyondEffect extends OneShotEffect { - private static FilterCard filter = new FilterCard("card to shuffle into your library"); - public SeeBeyondEffect() { super(Outcome.DrawCard); staticText = "Draw two cards, then shuffle a card from your hand into your library"; @@ -80,18 +77,18 @@ class SeeBeyondEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - player.drawCards(2, game); - if (player.getHand().size() > 0) { - TargetCard target = new TargetCard(Zone.HAND, filter); - player.choose(Outcome.Detriment, player.getHand(), target, game); - Card card = player.getHand().get(target.getFirstTarget(), game); + Player controller = game.getPlayer(source.getControllerId()); + controller.drawCards(2, game); + if (controller.getHand().size() > 0) { + TargetCard target = new TargetCard(Zone.HAND, new FilterCard("card to shuffle into your library")); + controller.choose(Outcome.Detriment, controller.getHand(), target, game); + Card card = controller.getHand().get(target.getFirstTarget(), game); if (card != null) { - player.removeFromHand(card, game); - card.moveToZone(Zone.LIBRARY, source.getSourceId(), game, true); - player.shuffleLibrary(source, game); - return true; + controller.moveCards(card, Zone.LIBRARY, source, game); + controller.shuffleLibrary(source, game); } + return true; + } return true; } @@ -101,4 +98,4 @@ class SeeBeyondEffect extends OneShotEffect { return new SeeBeyondEffect(this); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/s/SelvalaExplorerReturned.java b/Mage.Sets/src/mage/cards/s/SelvalaExplorerReturned.java index 86c622c4aa2..3020d82c760 100644 --- a/Mage.Sets/src/mage/cards/s/SelvalaExplorerReturned.java +++ b/Mage.Sets/src/mage/cards/s/SelvalaExplorerReturned.java @@ -36,6 +36,7 @@ import mage.abilities.dynamicvalue.common.ParleyCount; import mage.abilities.effects.Effect; import mage.abilities.effects.common.DrawCardAllEffect; import mage.abilities.effects.common.ManaEffect; +import mage.abilities.mana.ActivatedManaAbilityImpl; import mage.abilities.mana.SimpleManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -60,13 +61,13 @@ public class SelvalaExplorerReturned extends CardImpl { this.toughness = new MageInt(4); // Parley - {T}: Each player reveals the top card of his or her library. For each nonland card revealed this way, add {G} to your mana pool and you gain 1 life. Then each player draws a card. - Ability ability = new SimpleManaAbility(Zone.BATTLEFIELD, new SelvalaExplorerReturnedEffect(), new TapSourceCost()); - - ability.setAbilityWord(AbilityWord.PARLEY); + ActivatedManaAbilityImpl manaAbility = new SimpleManaAbility(Zone.BATTLEFIELD, new SelvalaExplorerReturnedEffect(), new TapSourceCost(), false); + manaAbility.setUndoPossible(false); + manaAbility.setAbilityWord(AbilityWord.PARLEY); Effect effect = new DrawCardAllEffect(1); effect.setText("Then each player draws a card"); - ability.addEffect(effect); - this.addAbility(ability); + manaAbility.addEffect(effect); + this.addAbility(manaAbility); } public SelvalaExplorerReturned(final SelvalaExplorerReturned card) { diff --git a/Mage.Sets/src/mage/cards/s/SelvalaHeartOfTheWilds.java b/Mage.Sets/src/mage/cards/s/SelvalaHeartOfTheWilds.java index f61d61c9b53..54f495df6d7 100644 --- a/Mage.Sets/src/mage/cards/s/SelvalaHeartOfTheWilds.java +++ b/Mage.Sets/src/mage/cards/s/SelvalaHeartOfTheWilds.java @@ -63,7 +63,7 @@ public class SelvalaHeartOfTheWilds extends CardImpl { filter.add(new GreatestPowerPredicate()); } - private static final String rule = "Whenever another creature enters the battlefield, its controller may draw a card if its power is greater than each other creature's power"; + private static final String rule = "Whenever another creature enters the battlefield, its controller may draw a card if its power is greater than each other creature's power."; public SelvalaHeartOfTheWilds(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{G}{G}"); diff --git a/Mage.Sets/src/mage/cards/s/SpiritShackle.java b/Mage.Sets/src/mage/cards/s/SpiritShackle.java new file mode 100644 index 00000000000..d4c64a56972 --- /dev/null +++ b/Mage.Sets/src/mage/cards/s/SpiritShackle.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.s; + +import java.util.UUID; + +import mage.abilities.common.BecomesTappedAttachedTriggeredAbility; +import mage.abilities.effects.common.counter.AddCountersAttachedEffect; +import mage.counters.BoostCounter; +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 SpiritShackle extends CardImpl { + + public SpiritShackle(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{B}{B}"); + + this.subtype.add("Aura"); + + // Enchant creature + TargetPermanent auraTarget = new TargetCreaturePermanent(); + this.getSpellAbility().addTarget(auraTarget); + this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature)); + Ability ability = new EnchantAbility(auraTarget.getTargetName()); + this.addAbility(ability); + + // Whenever enchanted creature becomes tapped, put a -0/-2 counter on it. + this.addAbility(new BecomesTappedAttachedTriggeredAbility(new AddCountersAttachedEffect(new BoostCounter(0, -2), "it"), "enchanted creature")); + + } + + public SpiritShackle(final SpiritShackle card) { + super(card); + } + + @Override + public SpiritShackle copy() { + return new SpiritShackle(this); + } +} diff --git a/Mage.Sets/src/mage/cards/s/SteelGolem.java b/Mage.Sets/src/mage/cards/s/SteelGolem.java index 99315c240b0..33467159101 100644 --- a/Mage.Sets/src/mage/cards/s/SteelGolem.java +++ b/Mage.Sets/src/mage/cards/s/SteelGolem.java @@ -28,18 +28,16 @@ package mage.cards.s; import java.util.UUID; - -import mage.constants.*; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; +import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.filter.common.FilterCreatureSpell; +import mage.constants.*; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.stack.Spell; /** * @@ -70,8 +68,6 @@ public class SteelGolem extends CardImpl { class SteelGolemEffect extends ContinuousRuleModifyingEffectImpl { - private static final FilterCreatureSpell filter = new FilterCreatureSpell(); - public SteelGolemEffect() { super(Duration.WhileOnBattlefield, Outcome.Detriment); staticText = "You can't cast creature spells"; @@ -94,10 +90,8 @@ class SteelGolemEffect extends ContinuousRuleModifyingEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { if (event.getPlayerId().equals(source.getControllerId())) { - Spell spell = game.getStack().getSpell(event.getSourceId()); - if (spell != null && filter.match(spell, game)) { - return true; - } + Card card = game.getCard(event.getSourceId()); + return card != null && card.getCardType().contains(CardType.CREATURE); } return false; } diff --git a/Mage.Sets/src/mage/cards/u/UrborgTombOfYawgmoth.java b/Mage.Sets/src/mage/cards/u/UrborgTombOfYawgmoth.java index 4d3a9e52235..5c0818e58c3 100644 --- a/Mage.Sets/src/mage/cards/u/UrborgTombOfYawgmoth.java +++ b/Mage.Sets/src/mage/cards/u/UrborgTombOfYawgmoth.java @@ -32,14 +32,12 @@ import java.util.UUID; import mage.constants.*; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.effects.ContinuousEffectImpl; import mage.abilities.effects.common.continuous.GainAbilityAllEffect; import mage.abilities.mana.BlackManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.filter.common.FilterLandPermanent; -import mage.game.Game; -import mage.game.permanent.Permanent; +import mage.abilities.effects.common.continuous.AddCardSubtypeAllEffect; /** * @@ -54,7 +52,7 @@ public class UrborgTombOfYawgmoth extends CardImpl { // Each land is a Swamp in addition to its other land types. Ability ability = new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(new BlackManaAbility(), Duration.WhileOnBattlefield, new FilterLandPermanent(), "Each land is a Swamp in addition to its other land types")); - ability.addEffect(new AddCardSubtypeAllEffect()); + ability.addEffect(new AddCardSubtypeAllEffect(new FilterLandPermanent(), "Swamp", DependencyType.BecomeSwamp)); this.addAbility(ability); } @@ -68,35 +66,3 @@ public class UrborgTombOfYawgmoth extends CardImpl { return new UrborgTombOfYawgmoth(this); } } - -class AddCardSubtypeAllEffect extends ContinuousEffectImpl { - - private static final FilterLandPermanent filter = new FilterLandPermanent(); - private static final String addedSubtype = "Swamp"; - - public AddCardSubtypeAllEffect() { - super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit); - staticText = ""; - addDependencyType(DependencyType.BecomeSwamp); - } - - public AddCardSubtypeAllEffect(final AddCardSubtypeAllEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - for (Permanent perm : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { - if (perm != null && !perm.getSubtype(game).contains(addedSubtype)) { - perm.getSubtype(game).add(addedSubtype); - } - } - return true; - } - - @Override - public AddCardSubtypeAllEffect copy() { - return new AddCardSubtypeAllEffect(this); - } - -} diff --git a/Mage.Sets/src/mage/cards/w/WallOfLava.java b/Mage.Sets/src/mage/cards/w/WallOfLava.java new file mode 100644 index 00000000000..9c032f6f497 --- /dev/null +++ b/Mage.Sets/src/mage/cards/w/WallOfLava.java @@ -0,0 +1,70 @@ +/* + * 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.w; + +import java.util.UUID; +import mage.MageInt; +import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.keyword.DefenderAbility; +import mage.cards.CardImpl; +import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.Zone; + +/** + * + * @author anonymous + */ +public class WallOfLava extends CardImpl { + + public WallOfLava(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{R}{R}"); + + this.subtype.add("Wall"); + this.power = new MageInt(1); + this.toughness = new MageInt(3); + + // Defender + this.addAbility(DefenderAbility.getInstance()); + + // {R}: Wall of Lava gets +1/+1 until end of turn. + this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostSourceEffect(1, 1, Duration.EndOfTurn), new ManaCostsImpl("{R}"))); + } + + public WallOfLava(final WallOfLava card) { + super(card); + } + + @Override + public WallOfLava copy() { + return new WallOfLava(this); + } +} diff --git a/Mage.Sets/src/mage/sets/Apocalypse.java b/Mage.Sets/src/mage/sets/Apocalypse.java index 8369a55174b..2ce5226b2cf 100644 --- a/Mage.Sets/src/mage/sets/Apocalypse.java +++ b/Mage.Sets/src/mage/sets/Apocalypse.java @@ -110,6 +110,7 @@ public class Apocalypse extends ExpansionSet { cards.add(new SetCardInfo("Phyrexian Gargantua", 48, Rarity.UNCOMMON, mage.cards.p.PhyrexianGargantua.class)); cards.add(new SetCardInfo("Phyrexian Rager", 49, Rarity.COMMON, mage.cards.p.PhyrexianRager.class)); cards.add(new SetCardInfo("Planar Despair", 50, Rarity.RARE, mage.cards.p.PlanarDespair.class)); + cards.add(new SetCardInfo("Powerstone Minefield", 115, Rarity.RARE, mage.cards.p.PowerstoneMinefield.class)); cards.add(new SetCardInfo("Prophetic Bolt", 116, Rarity.RARE, mage.cards.p.PropheticBolt.class)); cards.add(new SetCardInfo("Putrid Warrior", 117, Rarity.COMMON, mage.cards.p.PutridWarrior.class)); cards.add(new SetCardInfo("Quagmire Druid", 51, Rarity.COMMON, mage.cards.q.QuagmireDruid.class)); diff --git a/Mage.Sets/src/mage/sets/EighthEdition.java b/Mage.Sets/src/mage/sets/EighthEdition.java index 17e5ec1d2b8..4b710f875e8 100644 --- a/Mage.Sets/src/mage/sets/EighthEdition.java +++ b/Mage.Sets/src/mage/sets/EighthEdition.java @@ -1,11 +1,11 @@ package mage.sets; +import mage.cards.CardGraphicInfo; +import mage.cards.ExpansionSet; import mage.cards.o.OrcishSpy; import mage.cards.r.RukhEgg; -import mage.constants.SetType; -import mage.cards.ExpansionSet; import mage.constants.Rarity; -import mage.cards.CardGraphicInfo; +import mage.constants.SetType; public class EighthEdition extends ExpansionSet { @@ -100,7 +100,6 @@ public class EighthEdition extends ExpansionSet { cards.add(new SetCardInfo("Drudge Skeletons", 129, Rarity.COMMON, mage.cards.d.DrudgeSkeletons.class)); cards.add(new SetCardInfo("Dusk Imp", 130, Rarity.COMMON, mage.cards.d.DuskImp.class)); cards.add(new SetCardInfo("Dwarven Demolition Team", 184, Rarity.UNCOMMON, mage.cards.d.DwarvenDemolitionTeam.class)); - cards.add(new SetCardInfo("Eager Cadet", 1, Rarity.COMMON, mage.cards.e.EagerCadet.class)); cards.add(new SetCardInfo("Eastern Paladin", 131, Rarity.RARE, mage.cards.e.EasternPaladin.class)); cards.add(new SetCardInfo("Elfhame Palace", 324, Rarity.UNCOMMON, mage.cards.e.ElfhamePalace.class)); cards.add(new SetCardInfo("Elite Archers", 18, Rarity.RARE, mage.cards.e.EliteArchers.class)); @@ -111,7 +110,6 @@ public class EighthEdition extends ExpansionSet { cards.add(new SetCardInfo("Elvish Piper", 244, Rarity.RARE, mage.cards.e.ElvishPiper.class)); cards.add(new SetCardInfo("Elvish Scrapper", 245, Rarity.UNCOMMON, mage.cards.e.ElvishScrapper.class)); cards.add(new SetCardInfo("Emperor Crocodile", 246, Rarity.RARE, mage.cards.e.EmperorCrocodile.class)); - cards.add(new SetCardInfo("Enormous Baloth", 6, Rarity.UNCOMMON, mage.cards.e.EnormousBaloth.class)); cards.add(new SetCardInfo("Enrage", 185, Rarity.UNCOMMON, mage.cards.e.Enrage.class)); cards.add(new SetCardInfo("Ensnaring Bridge", 300, Rarity.RARE, mage.cards.e.EnsnaringBridge.class)); cards.add(new SetCardInfo("Evacuation", 76, Rarity.RARE, mage.cards.e.Evacuation.class)); @@ -282,7 +280,6 @@ public class EighthEdition extends ExpansionSet { cards.add(new SetCardInfo("Sanctimony", 42, Rarity.UNCOMMON, mage.cards.s.Sanctimony.class)); cards.add(new SetCardInfo("Savannah Lions", 43, Rarity.RARE, mage.cards.s.SavannahLions.class)); cards.add(new SetCardInfo("Scathe Zombies", 160, Rarity.COMMON, mage.cards.s.ScatheZombies.class)); - cards.add(new SetCardInfo("Sea Eagle", 4, Rarity.COMMON, mage.cards.s.SeaEagle.class)); cards.add(new SetCardInfo("Sea Monster", 99, Rarity.COMMON, mage.cards.s.SeaMonster.class)); cards.add(new SetCardInfo("Searing Wind", 218, Rarity.RARE, mage.cards.s.SearingWind.class)); cards.add(new SetCardInfo("Seasoned Marshal", 44, Rarity.UNCOMMON, mage.cards.s.SeasonedMarshal.class)); @@ -297,7 +294,6 @@ public class EighthEdition extends ExpansionSet { cards.add(new SetCardInfo("Shivan Oasis", 326, Rarity.UNCOMMON, mage.cards.s.ShivanOasis.class)); cards.add(new SetCardInfo("Shock", 222, Rarity.COMMON, mage.cards.s.Shock.class)); cards.add(new SetCardInfo("Shock Troops", 223, Rarity.COMMON, mage.cards.s.ShockTroops.class)); - cards.add(new SetCardInfo("Silverback Ape", 7, Rarity.UNCOMMON, mage.cards.s.SilverbackApe.class)); cards.add(new SetCardInfo("Sizzle", 224, Rarity.COMMON, mage.cards.s.Sizzle.class)); cards.add(new SetCardInfo("Skull of Orm", 313, Rarity.RARE, mage.cards.s.SkullOfOrm.class)); cards.add(new SetCardInfo("Slay", 164, Rarity.UNCOMMON, mage.cards.s.Slay.class)); @@ -352,14 +348,12 @@ public class EighthEdition extends ExpansionSet { cards.add(new SetCardInfo("Urza's Power Plant", 329, Rarity.COMMON, mage.cards.u.UrzasPowerPlant.class)); cards.add(new SetCardInfo("Urza's Tower", 330, Rarity.COMMON, mage.cards.u.UrzasTower.class)); cards.add(new SetCardInfo("Vampiric Spirit", 170, Rarity.RARE, mage.cards.v.VampiricSpirit.class)); - cards.add(new SetCardInfo("Venerable Monk", 55, Rarity.COMMON, mage.cards.v.VenerableMonk.class)); - cards.add(new SetCardInfo("Vengeance", 2, Rarity.UNCOMMON, mage.cards.v.Vengeance.class)); + cards.add(new SetCardInfo("Venerable Monk", 55, Rarity.COMMON, mage.cards.v.VenerableMonk.class)); cards.add(new SetCardInfo("Verduran Enchantress", 285, Rarity.RARE, mage.cards.v.VerduranEnchantress.class)); cards.add(new SetCardInfo("Vernal Bloom", 286, Rarity.RARE, mage.cards.v.VernalBloom.class)); cards.add(new SetCardInfo("Viashino Sandstalker", 230, Rarity.UNCOMMON, mage.cards.v.ViashinoSandstalker.class)); cards.add(new SetCardInfo("Vicious Hunger", 171, Rarity.COMMON, mage.cards.v.ViciousHunger.class)); cards.add(new SetCardInfo("Vine Trellis", 287, Rarity.COMMON, mage.cards.v.VineTrellis.class)); - cards.add(new SetCardInfo("Vizzerdrix", 5, Rarity.RARE, mage.cards.v.Vizzerdrix.class)); cards.add(new SetCardInfo("Volcanic Hammer", 231, Rarity.COMMON, mage.cards.v.VolcanicHammer.class)); cards.add(new SetCardInfo("Wall of Air", 113, Rarity.UNCOMMON, mage.cards.w.WallOfAir.class)); cards.add(new SetCardInfo("Wall of Spears", 320, Rarity.UNCOMMON, mage.cards.w.WallOfSpears.class)); @@ -377,6 +371,14 @@ public class EighthEdition extends ExpansionSet { cards.add(new SetCardInfo("Yavimaya Enchantress", 290, Rarity.UNCOMMON, mage.cards.y.YavimayaEnchantress.class)); cards.add(new SetCardInfo("Zombify", 174, Rarity.UNCOMMON, mage.cards.z.Zombify.class)); cards.add(new SetCardInfo("Zur's Weirding", 116, Rarity.RARE, mage.cards.z.ZursWeirding.class)); + // 8ed Edition Box Set (we need to create own set) + // cards.add(new SetCardInfo("Eager Cadet", 1, Rarity.COMMON, mage.cards.e.EagerCadet.class)); + // cards.add(new SetCardInfo("Vengeance", 2, Rarity.UNCOMMON, mage.cards.v.Vengeance.class)); + // cards.add(new SetCardInfo("Sea Eagle", 4, Rarity.COMMON, mage.cards.s.SeaEagle.class)); + // cards.add(new SetCardInfo("Vizzerdrix", 5, Rarity.RARE, mage.cards.v.Vizzerdrix.class)); + // cards.add(new SetCardInfo("Enormous Baloth", 6, Rarity.UNCOMMON, mage.cards.e.EnormousBaloth.class)); + // cards.add(new SetCardInfo("Silverback Ape", 7, Rarity.UNCOMMON, mage.cards.s.SilverbackApe.class)); + } } diff --git a/Mage.Sets/src/mage/sets/FourthEdition.java b/Mage.Sets/src/mage/sets/FourthEdition.java index 2e819a3c2ae..6efaa0aa398 100644 --- a/Mage.Sets/src/mage/sets/FourthEdition.java +++ b/Mage.Sets/src/mage/sets/FourthEdition.java @@ -254,6 +254,7 @@ public class FourthEdition extends ExpansionSet { cards.add(new SetCardInfo("Mind Twist", 31, Rarity.RARE, mage.cards.m.MindTwist.class)); cards.add(new SetCardInfo("Mishra's Factory", 181, Rarity.UNCOMMON, mage.cards.m.MishrasFactory.class)); cards.add(new SetCardInfo("Mons's Goblin Raiders", 231, Rarity.COMMON, mage.cards.m.MonssGoblinRaiders.class)); + cards.add(new SetCardInfo("Morale", 288, Rarity.COMMON, mage.cards.m.Morale.class)); cards.add(new SetCardInfo("Mountain", 182, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(null, true))); cards.add(new SetCardInfo("Mountain", 183, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(null, true))); cards.add(new SetCardInfo("Mountain", 184, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(null, true))); @@ -325,6 +326,7 @@ public class FourthEdition extends ExpansionSet { cards.add(new SetCardInfo("Soul Net", 364, Rarity.UNCOMMON, mage.cards.s.SoulNet.class)); cards.add(new SetCardInfo("Spell Blast", 103, Rarity.COMMON, mage.cards.s.SpellBlast.class)); cards.add(new SetCardInfo("Spirit Link", 301, Rarity.UNCOMMON, mage.cards.s.SpiritLink.class)); + cards.add(new SetCardInfo("Spirit Shackle", 47, Rarity.UNCOMMON, mage.cards.s.SpiritShackle.class)); cards.add(new SetCardInfo("Stasis", 104, Rarity.RARE, mage.cards.s.Stasis.class)); cards.add(new SetCardInfo("Steal Artifact", 105, Rarity.UNCOMMON, mage.cards.s.StealArtifact.class)); cards.add(new SetCardInfo("Stone Giant", 241, Rarity.UNCOMMON, mage.cards.s.StoneGiant.class)); diff --git a/Mage.Sets/src/mage/sets/FridayNightMagic.java b/Mage.Sets/src/mage/sets/FridayNightMagic.java index 69fe4f78abf..0ca33510089 100644 --- a/Mage.Sets/src/mage/sets/FridayNightMagic.java +++ b/Mage.Sets/src/mage/sets/FridayNightMagic.java @@ -52,6 +52,7 @@ public class FridayNightMagic extends ExpansionSet { cards.add(new SetCardInfo("Abzan Beastmaster", 180, Rarity.UNCOMMON, mage.cards.a.AbzanBeastmaster.class)); cards.add(new SetCardInfo("Accumulated Knowledge", 51, Rarity.COMMON, mage.cards.a.AccumulatedKnowledge.class)); cards.add(new SetCardInfo("Acidic Slime", 145, Rarity.UNCOMMON, mage.cards.a.AcidicSlime.class)); + cards.add(new SetCardInfo("Aether Hub", 205, Rarity.SPECIAL, mage.cards.a.AetherHub.class)); cards.add(new SetCardInfo("Albino Troll", 20, Rarity.UNCOMMON, mage.cards.a.AlbinoTroll.class)); cards.add(new SetCardInfo("Anathemancer", 122, Rarity.UNCOMMON, mage.cards.a.Anathemancer.class)); cards.add(new SetCardInfo("Ancient Grudge", 144, Rarity.COMMON, mage.cards.a.AncientGrudge.class)); @@ -206,6 +207,7 @@ public class FridayNightMagic extends ExpansionSet { cards.add(new SetCardInfo("Searing Spear", 152, Rarity.COMMON, mage.cards.s.SearingSpear.class)); cards.add(new SetCardInfo("Serrated Arrows", 101, Rarity.UNCOMMON, mage.cards.s.SerratedArrows.class)); cards.add(new SetCardInfo("Serum Visions", 183, Rarity.COMMON, mage.cards.s.SerumVisions.class)); + cards.add(new SetCardInfo("Servo Exhibition", 203, Rarity.SPECIAL, mage.cards.s.ServoExhibition.class)); cards.add(new SetCardInfo("Shock", 6, Rarity.COMMON, mage.cards.s.Shock.class)); cards.add(new SetCardInfo("Shrapnel Blast", 103, Rarity.UNCOMMON, mage.cards.s.ShrapnelBlast.class)); cards.add(new SetCardInfo("Silver Knight", 46, Rarity.UNCOMMON, mage.cards.s.SilverKnight.class)); @@ -236,6 +238,7 @@ public class FridayNightMagic extends ExpansionSet { cards.add(new SetCardInfo("Tormod's Crypt", 93, Rarity.UNCOMMON, mage.cards.t.TormodsCrypt.class)); cards.add(new SetCardInfo("Treetop Village", 50, Rarity.UNCOMMON, mage.cards.t.TreetopVillage.class)); cards.add(new SetCardInfo("Ultimate Price", 185, Rarity.UNCOMMON, mage.cards.u.UltimatePrice.class)); + cards.add(new SetCardInfo("Unlicensed Disintegration", 204, Rarity.SPECIAL, mage.cards.u.UnlicensedDisintegration.class)); cards.add(new SetCardInfo("Volcanic Geyser", 4, Rarity.UNCOMMON, mage.cards.v.VolcanicGeyser.class)); cards.add(new SetCardInfo("Wall of Blossoms", 23, Rarity.UNCOMMON, mage.cards.w.WallOfBlossoms.class)); cards.add(new SetCardInfo("Wall of Omens", 130, Rarity.UNCOMMON, mage.cards.w.WallOfOmens.class)); diff --git a/Mage.Sets/src/mage/sets/FutureSight.java b/Mage.Sets/src/mage/sets/FutureSight.java index fc74fe637e9..6a06a53d501 100644 --- a/Mage.Sets/src/mage/sets/FutureSight.java +++ b/Mage.Sets/src/mage/sets/FutureSight.java @@ -146,6 +146,7 @@ public class FutureSight extends ExpansionSet { cards.add(new SetCardInfo("Minions' Murmurs", 71, Rarity.UNCOMMON, mage.cards.m.MinionsMurmurs.class)); cards.add(new SetCardInfo("Mistmeadow Skulk", 27, Rarity.UNCOMMON, mage.cards.m.MistmeadowSkulk.class)); cards.add(new SetCardInfo("Molten Disaster", 102, Rarity.RARE, mage.cards.m.MoltenDisaster.class)); + cards.add(new SetCardInfo("Muraganda Petroglyphs", 146, Rarity.RARE, mage.cards.m.MuragandaPetroglyphs.class)); cards.add(new SetCardInfo("Mystic Speculation", 41, Rarity.UNCOMMON, mage.cards.m.MysticSpeculation.class)); cards.add(new SetCardInfo("Nacatl War-Pride", 147, Rarity.UNCOMMON, mage.cards.n.NacatlWarPride.class)); cards.add(new SetCardInfo("Narcomoeba", 54, Rarity.UNCOMMON, mage.cards.n.Narcomoeba.class)); diff --git a/Mage.Sets/src/mage/sets/Homelands.java b/Mage.Sets/src/mage/sets/Homelands.java index 39f394bba35..ab98fecde2b 100644 --- a/Mage.Sets/src/mage/sets/Homelands.java +++ b/Mage.Sets/src/mage/sets/Homelands.java @@ -115,6 +115,7 @@ public class Homelands extends ExpansionSet { cards.add(new SetCardInfo("Folk of An-Havva", 58, Rarity.COMMON, FolkOfAnHavva.class, new CardGraphicInfo(null, true))); cards.add(new SetCardInfo("Folk of An-Havva", 59, Rarity.COMMON, FolkOfAnHavva.class, new CardGraphicInfo(null, true))); cards.add(new SetCardInfo("Forget", 32, Rarity.RARE, mage.cards.f.Forget.class)); + cards.add(new SetCardInfo("Ghost Hounds", 12, Rarity.UNCOMMON, mage.cards.g.GhostHounds.class)); cards.add(new SetCardInfo("Grandmother Sengir", 13, Rarity.RARE, mage.cards.g.GrandmotherSengir.class)); cards.add(new SetCardInfo("Headstone", 15, Rarity.COMMON, mage.cards.h.Headstone.class)); cards.add(new SetCardInfo("Hungry Mist", 60, Rarity.COMMON, mage.cards.h.HungryMist.class, new CardGraphicInfo(null, true))); diff --git a/Mage.Sets/src/mage/sets/IceAge.java b/Mage.Sets/src/mage/sets/IceAge.java index b8b5459f826..77637654872 100644 --- a/Mage.Sets/src/mage/sets/IceAge.java +++ b/Mage.Sets/src/mage/sets/IceAge.java @@ -277,6 +277,7 @@ public class IceAge extends ExpansionSet { cards.add(new SetCardInfo("Veldt", 358, Rarity.RARE, mage.cards.v.Veldt.class)); cards.add(new SetCardInfo("Vertigo", 222, Rarity.UNCOMMON, mage.cards.v.Vertigo.class)); cards.add(new SetCardInfo("Walking Wall", 321, Rarity.UNCOMMON, mage.cards.w.WalkingWall.class)); + cards.add(new SetCardInfo("Wall of Lava", 223, Rarity.UNCOMMON, mage.cards.w.WallOfLava.class)); cards.add(new SetCardInfo("Wall of Pine Needles", 162, Rarity.UNCOMMON, mage.cards.w.WallOfPineNeedles.class)); cards.add(new SetCardInfo("War Chariot", 323, Rarity.UNCOMMON, mage.cards.w.WarChariot.class)); cards.add(new SetCardInfo("Warning", 279, Rarity.COMMON, mage.cards.w.Warning.class)); diff --git a/Mage.Sets/src/mage/sets/JudgePromo.java b/Mage.Sets/src/mage/sets/JudgePromo.java index 23f5fe90e41..a6c06f4b072 100644 --- a/Mage.Sets/src/mage/sets/JudgePromo.java +++ b/Mage.Sets/src/mage/sets/JudgePromo.java @@ -24,14 +24,13 @@ * 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.constants.SetType; +import mage.cards.CardGraphicInfo; import mage.cards.ExpansionSet; import mage.constants.Rarity; -import mage.cards.CardGraphicInfo; +import mage.constants.SetType; /** * @@ -50,14 +49,14 @@ public class JudgePromo extends ExpansionSet { this.hasBoosters = false; cards.add(new SetCardInfo("Argothian Enchantress", 12, Rarity.RARE, mage.cards.a.ArgothianEnchantress.class)); cards.add(new SetCardInfo("Armageddon", 14, Rarity.RARE, mage.cards.a.Armageddon.class)); - cards.add(new SetCardInfo("Azusa, Lost but Seeking", 102, Rarity.RARE, mage.cards.a.AzusaLostButSeeking.class)); + cards.add(new SetCardInfo("Azusa, Lost but Seeking", 102, Rarity.RARE, mage.cards.a.AzusaLostButSeeking.class));// 2016 003/008 cards.add(new SetCardInfo("Balance", 15, Rarity.RARE, mage.cards.b.Balance.class)); cards.add(new SetCardInfo("Ball Lightning", 7, Rarity.RARE, mage.cards.b.BallLightning.class)); cards.add(new SetCardInfo("Bitterblossom", 59, Rarity.RARE, mage.cards.b.Bitterblossom.class)); cards.add(new SetCardInfo("Bloodstained Mire", 43, Rarity.RARE, mage.cards.b.BloodstainedMire.class)); cards.add(new SetCardInfo("Bribery", 73, Rarity.RARE, mage.cards.b.Bribery.class)); cards.add(new SetCardInfo("Burning Wish", 42, Rarity.RARE, mage.cards.b.BurningWish.class)); - cards.add(new SetCardInfo("Command Beacon", 105, Rarity.RARE, mage.cards.c.CommandBeacon.class)); + cards.add(new SetCardInfo("Command Beacon", 105, Rarity.RARE, mage.cards.c.CommandBeacon.class));// 2016 004/008 cards.add(new SetCardInfo("Command Tower", 71, Rarity.COMMON, mage.cards.c.CommandTower.class)); cards.add(new SetCardInfo("Counterspell", 5, Rarity.COMMON, mage.cards.c.Counterspell.class)); cards.add(new SetCardInfo("Crucible of Worlds", 75, Rarity.RARE, mage.cards.c.CrucibleOfWorlds.class)); @@ -66,7 +65,7 @@ public class JudgePromo extends ExpansionSet { cards.add(new SetCardInfo("Dark Confidant", 61, Rarity.RARE, mage.cards.d.DarkConfidant.class)); cards.add(new SetCardInfo("Dark Ritual", 38, Rarity.COMMON, mage.cards.d.DarkRitual.class)); cards.add(new SetCardInfo("Decree of Justice", 32, Rarity.RARE, mage.cards.d.DecreeOfJustice.class)); - cards.add(new SetCardInfo("Defense of the Heart", 106, Rarity.RARE, mage.cards.d.DefenseOfTheHeart.class)); + cards.add(new SetCardInfo("Defense of the Heart", 106, Rarity.RARE, mage.cards.d.DefenseOfTheHeart.class)); // 2016 007/008 cards.add(new SetCardInfo("Demonic Tutor", 35, Rarity.UNCOMMON, mage.cards.d.DemonicTutor.class)); cards.add(new SetCardInfo("Deranged Hermit", 18, Rarity.RARE, mage.cards.d.DerangedHermit.class)); cards.add(new SetCardInfo("Doubling Season", 62, Rarity.RARE, mage.cards.d.DoublingSeason.class)); @@ -91,7 +90,7 @@ public class JudgePromo extends ExpansionSet { cards.add(new SetCardInfo("Hanna, Ship's Navigator", 84, Rarity.RARE, mage.cards.h.HannaShipsNavigator.class)); cards.add(new SetCardInfo("Hermit Druid", 19, Rarity.RARE, mage.cards.h.HermitDruid.class)); cards.add(new SetCardInfo("Imperial Recruiter", 74, Rarity.UNCOMMON, mage.cards.i.ImperialRecruiter.class)); - cards.add(new SetCardInfo("Imperial Seal", 109, Rarity.SPECIAL, mage.cards.i.ImperialSeal.class)); + cards.add(new SetCardInfo("Imperial Seal", 109, Rarity.SPECIAL, mage.cards.i.ImperialSeal.class));// 2016 006/008 cards.add(new SetCardInfo("Intuition", 11, Rarity.RARE, mage.cards.i.Intuition.class)); cards.add(new SetCardInfo("Island", 90, Rarity.LAND, mage.cards.basiclands.Island.class, new CardGraphicInfo(null, true))); cards.add(new SetCardInfo("Karador, Ghost Chieftain", 80, Rarity.MYTHIC, mage.cards.k.KaradorGhostChieftain.class)); @@ -102,7 +101,7 @@ public class JudgePromo extends ExpansionSet { cards.add(new SetCardInfo("Living Death", 13, Rarity.RARE, mage.cards.l.LivingDeath.class)); cards.add(new SetCardInfo("Living Wish", 37, Rarity.RARE, mage.cards.l.LivingWish.class)); cards.add(new SetCardInfo("Mana Crypt", 60, Rarity.RARE, mage.cards.m.ManaCrypt.class)); - cards.add(new SetCardInfo("Mana Drain", 103, Rarity.UNCOMMON, mage.cards.m.ManaDrain.class)); + cards.add(new SetCardInfo("Mana Drain", 103, Rarity.UNCOMMON, mage.cards.m.ManaDrain.class));// 2016 002/008 cards.add(new SetCardInfo("Maze of Ith", 39, Rarity.UNCOMMON, mage.cards.m.MazeOfIth.class)); cards.add(new SetCardInfo("Meddling Mage", 26, Rarity.RARE, mage.cards.m.MeddlingMage.class)); cards.add(new SetCardInfo("Memory Lapse", 4, Rarity.COMMON, mage.cards.m.MemoryLapse.class)); @@ -110,7 +109,7 @@ public class JudgePromo extends ExpansionSet { cards.add(new SetCardInfo("Mishra's Factory", 23, Rarity.UNCOMMON, mage.cards.m.MishrasFactory.class)); cards.add(new SetCardInfo("Morphling", 53, Rarity.RARE, mage.cards.m.Morphling.class)); cards.add(new SetCardInfo("Mountain", 92, Rarity.LAND, mage.cards.basiclands.Mountain.class, new CardGraphicInfo(null, true))); - cards.add(new SetCardInfo("Mystic Confluence", 109, Rarity.SPECIAL, mage.cards.m.MysticConfluence.class, new CardGraphicInfo(null, true))); + cards.add(new SetCardInfo("Mystic Confluence", 108, Rarity.SPECIAL, mage.cards.m.MysticConfluence.class, new CardGraphicInfo(null, true))); // 2016 005/008 cards.add(new SetCardInfo("Natural Order", 49, Rarity.RARE, mage.cards.n.NaturalOrder.class)); cards.add(new SetCardInfo("Nekusar, the Mindrazer", 86, Rarity.MYTHIC, mage.cards.n.NekusarTheMindrazer.class)); cards.add(new SetCardInfo("Noble Hierarch", 66, Rarity.RARE, mage.cards.n.NobleHierarch.class)); @@ -155,7 +154,7 @@ public class JudgePromo extends ExpansionSet { cards.add(new SetCardInfo("Wooded Foothills", 47, Rarity.RARE, mage.cards.w.WoodedFoothills.class)); cards.add(new SetCardInfo("Xiahou Dun, the One-Eyed", 64, Rarity.RARE, mage.cards.x.XiahouDunTheOneEyed.class)); cards.add(new SetCardInfo("Yawgmoth's Will", 30, Rarity.RARE, mage.cards.y.YawgmothsWill.class)); - cards.add(new SetCardInfo("Zur the Enchanter", 107, Rarity.RARE, mage.cards.z.ZurTheEnchanter.class)); + cards.add(new SetCardInfo("Zur the Enchanter", 107, Rarity.RARE, mage.cards.z.ZurTheEnchanter.class)); // 2016 008/008 } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/sets/Legends.java b/Mage.Sets/src/mage/sets/Legends.java index 0729bc30cae..5bb2f82516e 100644 --- a/Mage.Sets/src/mage/sets/Legends.java +++ b/Mage.Sets/src/mage/sets/Legends.java @@ -204,6 +204,7 @@ public class Legends extends ExpansionSet { cards.add(new SetCardInfo("Sol'kanar the Swamp King", 299, Rarity.RARE, mage.cards.s.SolkanarTheSwampKing.class)); cards.add(new SetCardInfo("Spinal Villain", 161, Rarity.RARE, mage.cards.s.SpinalVillain.class)); cards.add(new SetCardInfo("Spirit Link", 206, Rarity.UNCOMMON, mage.cards.s.SpiritLink.class)); + cards.add(new SetCardInfo("Spirit Shackle", 31, Rarity.COMMON, mage.cards.s.SpiritShackle.class)); cards.add(new SetCardInfo("Storm Seeker", 119, Rarity.UNCOMMON, mage.cards.s.StormSeeker.class)); cards.add(new SetCardInfo("Sunastian Falconer", 301, Rarity.UNCOMMON, mage.cards.s.SunastianFalconer.class)); cards.add(new SetCardInfo("Sylvan Library", 121, Rarity.UNCOMMON, mage.cards.s.SylvanLibrary.class)); @@ -233,7 +234,7 @@ public class Legends extends ExpansionSet { cards.add(new SetCardInfo("Wall of Earth", 166, Rarity.COMMON, mage.cards.w.WallOfEarth.class)); cards.add(new SetCardInfo("Wall of Heat", 167, Rarity.COMMON, mage.cards.w.WallOfHeat.class)); cards.add(new SetCardInfo("Wall of Light", 212, Rarity.UNCOMMON, mage.cards.w.WallOfLight.class)); - cards.add(new SetCardInfo("Wall of Putrid Flesh", 41, Rarity.UNCOMMON, mage.cards.w.WallOfPutridFlesh.class)); + cards.add(new SetCardInfo("Wall of Putrid Flesh", 41, Rarity.UNCOMMON, mage.cards.w.WallOfPutridFlesh.class)); cards.add(new SetCardInfo("Wall of Wonder", 85, Rarity.UNCOMMON, mage.cards.w.WallOfWonder.class)); cards.add(new SetCardInfo("Whirling Dervish", 125, Rarity.UNCOMMON, mage.cards.w.WhirlingDervish.class)); cards.add(new SetCardInfo("Willow Satyr", 126, Rarity.RARE, mage.cards.w.WillowSatyr.class)); diff --git a/Mage.Sets/src/mage/sets/MagicPlayerRewards.java b/Mage.Sets/src/mage/sets/MagicPlayerRewards.java index d7e730072e0..02d6a2b24c3 100644 --- a/Mage.Sets/src/mage/sets/MagicPlayerRewards.java +++ b/Mage.Sets/src/mage/sets/MagicPlayerRewards.java @@ -27,11 +27,14 @@ */ package mage.sets; +import mage.cards.CardGraphicInfo; import mage.cards.ExpansionSet; -import mage.constants.SetType; +import mage.cards.FrameStyle; import mage.constants.Rarity; +import mage.constants.SetType; public class MagicPlayerRewards extends ExpansionSet { + private static final MagicPlayerRewards fINSTANCE = new MagicPlayerRewards(); public static MagicPlayerRewards getInstance() { @@ -42,58 +45,59 @@ public class MagicPlayerRewards extends ExpansionSet { super("Magic Player Rewards", "MPRP", ExpansionSet.buildDate(1990, 1, 1), SetType.PROMOTIONAL); this.hasBoosters = false; this.hasBasicLands = false; - cards.add(new SetCardInfo("Bituminous Blast", 46, Rarity.SPECIAL, mage.cards.b.BituminousBlast.class)); - cards.add(new SetCardInfo("Blightning", 36, Rarity.SPECIAL, mage.cards.b.Blightning.class)); - cards.add(new SetCardInfo("Brave the Elements", 50, Rarity.SPECIAL, mage.cards.b.BraveTheElements.class)); - cards.add(new SetCardInfo("Burst Lightning", 47, Rarity.SPECIAL, mage.cards.b.BurstLightning.class)); - cards.add(new SetCardInfo("Cancel", 41, Rarity.SPECIAL, mage.cards.c.Cancel.class)); - cards.add(new SetCardInfo("Celestial Purge", 45, Rarity.SPECIAL, mage.cards.c.CelestialPurge.class)); - cards.add(new SetCardInfo("Condemn", 18, Rarity.SPECIAL, mage.cards.c.Condemn.class)); - cards.add(new SetCardInfo("Corrupt", 30, Rarity.SPECIAL, mage.cards.c.Corrupt.class)); - cards.add(new SetCardInfo("Cruel Edict", 21, Rarity.SPECIAL, mage.cards.c.CruelEdict.class)); - cards.add(new SetCardInfo("Cryptic Command", 31, Rarity.SPECIAL, mage.cards.c.CrypticCommand.class)); - cards.add(new SetCardInfo("Damnation", 24, Rarity.SPECIAL, mage.cards.d.Damnation.class)); - cards.add(new SetCardInfo("Day of Judgment", 49, Rarity.SPECIAL, mage.cards.d.DayOfJudgment.class)); - cards.add(new SetCardInfo("Disenchant", 22, Rarity.SPECIAL, mage.cards.d.Disenchant.class)); - cards.add(new SetCardInfo("Doom Blade", 51, Rarity.SPECIAL, mage.cards.d.DoomBlade.class)); - cards.add(new SetCardInfo("Fireball", 6, Rarity.SPECIAL, mage.cards.f.Fireball.class)); - cards.add(new SetCardInfo("Flame Javelin", 32, Rarity.SPECIAL, mage.cards.f.FlameJavelin.class)); - cards.add(new SetCardInfo("Giant Growth", 13, Rarity.SPECIAL, mage.cards.g.GiantGrowth.class)); - cards.add(new SetCardInfo("Harmonize", 28, Rarity.SPECIAL, mage.cards.h.Harmonize.class)); - cards.add(new SetCardInfo("Harrow", 48, Rarity.SPECIAL, mage.cards.h.Harrow.class)); - cards.add(new SetCardInfo("Hinder", 11, Rarity.SPECIAL, mage.cards.h.Hinder.class)); + CardGraphicInfo graphicInfo = new CardGraphicInfo(FrameStyle.MPRP_FULL_ART_BASIC, false); + cards.add(new SetCardInfo("Bituminous Blast", 46, Rarity.SPECIAL, mage.cards.b.BituminousBlast.class, graphicInfo)); + cards.add(new SetCardInfo("Blightning", 36, Rarity.SPECIAL, mage.cards.b.Blightning.class, graphicInfo)); + cards.add(new SetCardInfo("Brave the Elements", 50, Rarity.SPECIAL, mage.cards.b.BraveTheElements.class, graphicInfo)); + cards.add(new SetCardInfo("Burst Lightning", 47, Rarity.SPECIAL, mage.cards.b.BurstLightning.class, graphicInfo)); + cards.add(new SetCardInfo("Cancel", 41, Rarity.SPECIAL, mage.cards.c.Cancel.class, graphicInfo)); + cards.add(new SetCardInfo("Celestial Purge", 45, Rarity.SPECIAL, mage.cards.c.CelestialPurge.class, graphicInfo)); + cards.add(new SetCardInfo("Condemn", 18, Rarity.SPECIAL, mage.cards.c.Condemn.class, graphicInfo)); + cards.add(new SetCardInfo("Corrupt", 30, Rarity.SPECIAL, mage.cards.c.Corrupt.class, graphicInfo)); + cards.add(new SetCardInfo("Cruel Edict", 21, Rarity.SPECIAL, mage.cards.c.CruelEdict.class, graphicInfo)); + cards.add(new SetCardInfo("Cryptic Command", 31, Rarity.SPECIAL, mage.cards.c.CrypticCommand.class, graphicInfo)); + cards.add(new SetCardInfo("Damnation", 24, Rarity.SPECIAL, mage.cards.d.Damnation.class, graphicInfo)); + cards.add(new SetCardInfo("Day of Judgment", 49, Rarity.SPECIAL, mage.cards.d.DayOfJudgment.class, graphicInfo)); + cards.add(new SetCardInfo("Disenchant", 22, Rarity.SPECIAL, mage.cards.d.Disenchant.class, graphicInfo)); + cards.add(new SetCardInfo("Doom Blade", 51, Rarity.SPECIAL, mage.cards.d.DoomBlade.class, graphicInfo)); + cards.add(new SetCardInfo("Fireball", 6, Rarity.SPECIAL, mage.cards.f.Fireball.class, graphicInfo)); + cards.add(new SetCardInfo("Flame Javelin", 32, Rarity.SPECIAL, mage.cards.f.FlameJavelin.class, graphicInfo)); + cards.add(new SetCardInfo("Giant Growth", 13, Rarity.SPECIAL, mage.cards.g.GiantGrowth.class, graphicInfo)); + cards.add(new SetCardInfo("Harmonize", 28, Rarity.SPECIAL, mage.cards.h.Harmonize.class, graphicInfo)); + cards.add(new SetCardInfo("Harrow", 48, Rarity.SPECIAL, mage.cards.h.Harrow.class, graphicInfo)); + cards.add(new SetCardInfo("Hinder", 11, Rarity.SPECIAL, mage.cards.h.Hinder.class, graphicInfo)); cards.add(new SetCardInfo("Hypnotic Specter", 10, Rarity.SPECIAL, mage.cards.h.HypnoticSpecter.class)); - cards.add(new SetCardInfo("Incinerate", 26, Rarity.SPECIAL, mage.cards.i.Incinerate.class)); - cards.add(new SetCardInfo("Infest", 43, Rarity.SPECIAL, mage.cards.i.Infest.class)); - cards.add(new SetCardInfo("Lightning Bolt", 40, Rarity.SPECIAL, mage.cards.l.LightningBolt.class)); - cards.add(new SetCardInfo("Lightning Helix", 16, Rarity.SPECIAL, mage.cards.l.LightningHelix.class)); - cards.add(new SetCardInfo("Mana Leak", 8, Rarity.SPECIAL, mage.cards.m.ManaLeak.class)); - cards.add(new SetCardInfo("Mana Tithe", 27, Rarity.SPECIAL, mage.cards.m.ManaTithe.class)); - cards.add(new SetCardInfo("Mortify", 19, Rarity.SPECIAL, mage.cards.m.Mortify.class)); - cards.add(new SetCardInfo("Nameless Inversion", 34, Rarity.SPECIAL, mage.cards.n.NamelessInversion.class)); - cards.add(new SetCardInfo("Negate", 38, Rarity.SPECIAL, mage.cards.n.Negate.class)); - cards.add(new SetCardInfo("Oxidize", 7, Rarity.SPECIAL, mage.cards.o.Oxidize.class)); - cards.add(new SetCardInfo("Ponder", 29, Rarity.SPECIAL, mage.cards.p.Ponder.class)); + cards.add(new SetCardInfo("Incinerate", 26, Rarity.SPECIAL, mage.cards.i.Incinerate.class, graphicInfo)); + cards.add(new SetCardInfo("Infest", 43, Rarity.SPECIAL, mage.cards.i.Infest.class, graphicInfo)); + cards.add(new SetCardInfo("Lightning Bolt", 40, Rarity.SPECIAL, mage.cards.l.LightningBolt.class, graphicInfo)); + cards.add(new SetCardInfo("Lightning Helix", 16, Rarity.SPECIAL, mage.cards.l.LightningHelix.class, graphicInfo)); + cards.add(new SetCardInfo("Mana Leak", 8, Rarity.SPECIAL, mage.cards.m.ManaLeak.class, graphicInfo)); + cards.add(new SetCardInfo("Mana Tithe", 27, Rarity.SPECIAL, mage.cards.m.ManaTithe.class, graphicInfo)); + cards.add(new SetCardInfo("Mortify", 19, Rarity.SPECIAL, mage.cards.m.Mortify.class, graphicInfo)); + cards.add(new SetCardInfo("Nameless Inversion", 34, Rarity.SPECIAL, mage.cards.n.NamelessInversion.class, graphicInfo)); + cards.add(new SetCardInfo("Negate", 38, Rarity.SPECIAL, mage.cards.n.Negate.class, graphicInfo)); + cards.add(new SetCardInfo("Oxidize", 7, Rarity.SPECIAL, mage.cards.o.Oxidize.class, graphicInfo)); + cards.add(new SetCardInfo("Ponder", 29, Rarity.SPECIAL, mage.cards.p.Ponder.class, graphicInfo)); cards.add(new SetCardInfo("Powder Keg", 3, Rarity.SPECIAL, mage.cards.p.PowderKeg.class)); - cards.add(new SetCardInfo("Psionic Blast", 20, Rarity.COMMON, mage.cards.p.PsionicBlast.class)); + cards.add(new SetCardInfo("Psionic Blast", 20, Rarity.SPECIAL, mage.cards.p.PsionicBlast.class, graphicInfo)); cards.add(new SetCardInfo("Psychatog", 4, Rarity.SPECIAL, mage.cards.p.Psychatog.class)); - cards.add(new SetCardInfo("Putrefy", 14, Rarity.SPECIAL, mage.cards.p.Putrefy.class)); - cards.add(new SetCardInfo("Pyroclasm", 12, Rarity.SPECIAL, mage.cards.p.Pyroclasm.class)); - cards.add(new SetCardInfo("Rampant Growth", 37, Rarity.SPECIAL, mage.cards.r.RampantGrowth.class)); - cards.add(new SetCardInfo("Reciprocate", 9, Rarity.SPECIAL, mage.cards.r.Reciprocate.class)); - cards.add(new SetCardInfo("Recollect", 23, Rarity.SPECIAL, mage.cards.r.Recollect.class)); - cards.add(new SetCardInfo("Remove Soul", 35, Rarity.SPECIAL, mage.cards.r.RemoveSoul.class)); - cards.add(new SetCardInfo("Searing Blaze", 53, Rarity.SPECIAL, mage.cards.s.SearingBlaze.class)); - cards.add(new SetCardInfo("Sign in Blood", 42, Rarity.SPECIAL, mage.cards.s.SignInBlood.class)); - cards.add(new SetCardInfo("Terminate", 39, Rarity.SPECIAL, mage.cards.t.Terminate.class)); - cards.add(new SetCardInfo("Terror", 5, Rarity.SPECIAL, mage.cards.t.Terror.class)); - cards.add(new SetCardInfo("Tidings", 25, Rarity.SPECIAL, mage.cards.t.Tidings.class)); - cards.add(new SetCardInfo("Treasure Hunt", 52, Rarity.SPECIAL, mage.cards.t.TreasureHunt.class)); - cards.add(new SetCardInfo("Unmake", 33, Rarity.SPECIAL, mage.cards.u.Unmake.class)); + cards.add(new SetCardInfo("Putrefy", 14, Rarity.SPECIAL, mage.cards.p.Putrefy.class, graphicInfo)); + cards.add(new SetCardInfo("Pyroclasm", 12, Rarity.SPECIAL, mage.cards.p.Pyroclasm.class, graphicInfo)); + cards.add(new SetCardInfo("Rampant Growth", 37, Rarity.SPECIAL, mage.cards.r.RampantGrowth.class, graphicInfo)); + cards.add(new SetCardInfo("Reciprocate", 9, Rarity.SPECIAL, mage.cards.r.Reciprocate.class, graphicInfo)); + cards.add(new SetCardInfo("Recollect", 23, Rarity.SPECIAL, mage.cards.r.Recollect.class, graphicInfo)); + cards.add(new SetCardInfo("Remove Soul", 35, Rarity.SPECIAL, mage.cards.r.RemoveSoul.class, graphicInfo)); + cards.add(new SetCardInfo("Searing Blaze", 53, Rarity.SPECIAL, mage.cards.s.SearingBlaze.class, graphicInfo)); + cards.add(new SetCardInfo("Sign in Blood", 42, Rarity.SPECIAL, mage.cards.s.SignInBlood.class, graphicInfo)); + cards.add(new SetCardInfo("Terminate", 39, Rarity.SPECIAL, mage.cards.t.Terminate.class, graphicInfo)); + cards.add(new SetCardInfo("Terror", 5, Rarity.SPECIAL, mage.cards.t.Terror.class, graphicInfo)); + cards.add(new SetCardInfo("Tidings", 25, Rarity.SPECIAL, mage.cards.t.Tidings.class, graphicInfo)); + cards.add(new SetCardInfo("Treasure Hunt", 52, Rarity.SPECIAL, mage.cards.t.TreasureHunt.class, graphicInfo)); + cards.add(new SetCardInfo("Unmake", 33, Rarity.SPECIAL, mage.cards.u.Unmake.class, graphicInfo)); cards.add(new SetCardInfo("Voidmage Prodigy", 2, Rarity.SPECIAL, mage.cards.v.VoidmageProdigy.class)); - cards.add(new SetCardInfo("Volcanic Fallout", 44, Rarity.SPECIAL, mage.cards.v.VolcanicFallout.class)); - cards.add(new SetCardInfo("Wasteland", 1, Rarity.SPECIAL, mage.cards.w.Wasteland.class)); - cards.add(new SetCardInfo("Wrath of God", 17, Rarity.SPECIAL, mage.cards.w.WrathOfGod.class)); - cards.add(new SetCardInfo("Zombify", 15, Rarity.SPECIAL, mage.cards.z.Zombify.class)); + cards.add(new SetCardInfo("Volcanic Fallout", 44, Rarity.SPECIAL, mage.cards.v.VolcanicFallout.class, graphicInfo)); + cards.add(new SetCardInfo("Wasteland", 1, Rarity.SPECIAL, mage.cards.w.Wasteland.class, graphicInfo)); + cards.add(new SetCardInfo("Wrath of God", 17, Rarity.SPECIAL, mage.cards.w.WrathOfGod.class, graphicInfo)); + cards.add(new SetCardInfo("Zombify", 15, Rarity.SPECIAL, mage.cards.z.Zombify.class, graphicInfo)); } } diff --git a/Mage.Sets/src/mage/sets/MasterpieceSeries.java b/Mage.Sets/src/mage/sets/MasterpieceSeries.java index 9145913fa1e..756a7ffd28d 100644 --- a/Mage.Sets/src/mage/sets/MasterpieceSeries.java +++ b/Mage.Sets/src/mage/sets/MasterpieceSeries.java @@ -27,11 +27,11 @@ */ package mage.sets; -import mage.cards.ExpansionSet; -import mage.constants.SetType; -import mage.constants.Rarity; import mage.cards.CardGraphicInfo; +import mage.cards.ExpansionSet; import mage.cards.FrameStyle; +import mage.constants.Rarity; +import mage.constants.SetType; /** * @@ -49,72 +49,60 @@ public class MasterpieceSeries extends ExpansionSet { super("Masterpiece Series", "MPS", ExpansionSet.buildDate(2016, 9, 30), SetType.PROMOTIONAL); this.hasBoosters = false; this.hasBasicLands = false; - cards.add(new SetCardInfo("Aether Vial", 6, Rarity.MYTHIC, mage.cards.a.AetherVial.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Arcbound Ravager", 31, Rarity.MYTHIC, mage.cards.a.ArcboundRavager.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Black Vise", 32, Rarity.MYTHIC, mage.cards.b.BlackVise.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Cataclysmic Gearhulk", 1, Rarity.MYTHIC, mage.cards.c.CataclysmicGearhulk.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Chalice of the Void", 33, Rarity.MYTHIC, mage.cards.c.ChaliceOfTheVoid.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Champion's Helm", 7, Rarity.MYTHIC, mage.cards.c.ChampionsHelm.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Chromatic Lantern", 8, Rarity.MYTHIC, mage.cards.c.ChromaticLantern.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, - false))); - cards.add(new SetCardInfo("Chrome Mox", 9, Rarity.MYTHIC, mage.cards.c.ChromeMox.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Cloudstone Curio", 10, Rarity.MYTHIC, mage.cards.c.CloudstoneCurio.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, - false))); - cards.add(new SetCardInfo("Combustible Gearhulk", 2, Rarity.MYTHIC, mage.cards.c.CombustibleGearhulk.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Crucible of Worlds", 11, Rarity.MYTHIC, mage.cards.c.CrucibleOfWorlds.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, - false))); - cards.add(new SetCardInfo("Defense Grid", 34, Rarity.MYTHIC, mage.cards.d.DefenseGrid.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Duplicant", 35, Rarity.MYTHIC, mage.cards.d.Duplicant.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Engineered Explosives", 36, Rarity.MYTHIC, mage.cards.e.EngineeredExplosives.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Ensnaring Bridge", 37, Rarity.MYTHIC, mage.cards.e.EnsnaringBridge.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Extraplanar Lens", 38, Rarity.MYTHIC, mage.cards.e.ExtraplanarLens.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Gauntlet of Power", 12, Rarity.MYTHIC, mage.cards.g.GauntletOfPower.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, - false))); - cards.add(new SetCardInfo("Grindstone", 39, Rarity.MYTHIC, mage.cards.g.Grindstone.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Hangarback Walker", 13, Rarity.MYTHIC, mage.cards.h.HangarbackWalker.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, - false))); - cards.add(new SetCardInfo("Lightning Greaves", 14, Rarity.MYTHIC, mage.cards.l.LightningGreaves.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, - false))); - cards.add(new SetCardInfo("Lotus Petal", 15, Rarity.MYTHIC, mage.cards.l.LotusPetal.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Mana Crypt", 16, Rarity.MYTHIC, mage.cards.m.ManaCrypt.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Mana Vault", 17, Rarity.MYTHIC, mage.cards.m.ManaVault.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Meekstone", 40, Rarity.MYTHIC, mage.cards.m.Meekstone.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Mind's Eye", 18, Rarity.MYTHIC, mage.cards.m.MindsEye.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Mox Opal", 19, Rarity.MYTHIC, mage.cards.m.MoxOpal.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Noxious Gearhulk", 3, Rarity.MYTHIC, mage.cards.n.NoxiousGearhulk.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Oblivion Stone", 41, Rarity.MYTHIC, mage.cards.o.OblivionStone.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Ornithopter", 42, Rarity.MYTHIC, mage.cards.o.Ornithopter.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Painter's Servant", 20, Rarity.MYTHIC, mage.cards.p.PaintersServant.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, - false))); + CardGraphicInfo cardGraphicInfo = new CardGraphicInfo(FrameStyle.KLD_INVENTION, false); + cards.add(new SetCardInfo("Aether Vial", 6, Rarity.MYTHIC, mage.cards.a.AetherVial.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Arcbound Ravager", 31, Rarity.MYTHIC, mage.cards.a.ArcboundRavager.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Black Vise", 32, Rarity.MYTHIC, mage.cards.b.BlackVise.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Cataclysmic Gearhulk", 1, Rarity.MYTHIC, mage.cards.c.CataclysmicGearhulk.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Chalice of the Void", 33, Rarity.MYTHIC, mage.cards.c.ChaliceOfTheVoid.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Champion's Helm", 7, Rarity.MYTHIC, mage.cards.c.ChampionsHelm.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Chromatic Lantern", 8, Rarity.MYTHIC, mage.cards.c.ChromaticLantern.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Chrome Mox", 9, Rarity.MYTHIC, mage.cards.c.ChromeMox.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Cloudstone Curio", 10, Rarity.MYTHIC, mage.cards.c.CloudstoneCurio.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Combustible Gearhulk", 2, Rarity.MYTHIC, mage.cards.c.CombustibleGearhulk.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Crucible of Worlds", 11, Rarity.MYTHIC, mage.cards.c.CrucibleOfWorlds.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Defense Grid", 34, Rarity.MYTHIC, mage.cards.d.DefenseGrid.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Duplicant", 35, Rarity.MYTHIC, mage.cards.d.Duplicant.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Engineered Explosives", 36, Rarity.MYTHIC, mage.cards.e.EngineeredExplosives.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Ensnaring Bridge", 37, Rarity.MYTHIC, mage.cards.e.EnsnaringBridge.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Extraplanar Lens", 38, Rarity.MYTHIC, mage.cards.e.ExtraplanarLens.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Gauntlet of Power", 12, Rarity.MYTHIC, mage.cards.g.GauntletOfPower.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Grindstone", 39, Rarity.MYTHIC, mage.cards.g.Grindstone.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Hangarback Walker", 13, Rarity.MYTHIC, mage.cards.h.HangarbackWalker.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Lightning Greaves", 14, Rarity.MYTHIC, mage.cards.l.LightningGreaves.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Lotus Petal", 15, Rarity.MYTHIC, mage.cards.l.LotusPetal.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Mana Crypt", 16, Rarity.MYTHIC, mage.cards.m.ManaCrypt.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Mana Vault", 17, Rarity.MYTHIC, mage.cards.m.ManaVault.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Meekstone", 40, Rarity.MYTHIC, mage.cards.m.Meekstone.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Mind's Eye", 18, Rarity.MYTHIC, mage.cards.m.MindsEye.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Mox Opal", 19, Rarity.MYTHIC, mage.cards.m.MoxOpal.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Noxious Gearhulk", 3, Rarity.MYTHIC, mage.cards.n.NoxiousGearhulk.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Oblivion Stone", 41, Rarity.MYTHIC, mage.cards.o.OblivionStone.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Ornithopter", 42, Rarity.MYTHIC, mage.cards.o.Ornithopter.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Painter's Servant", 20, Rarity.MYTHIC, mage.cards.p.PaintersServant.class, cardGraphicInfo)); cards.add(new SetCardInfo("Paradox Engine", 43, Rarity.MYTHIC, mage.cards.p.ParadoxEngine.class)); - cards.add(new SetCardInfo("Pithing Needle", 44, Rarity.MYTHIC, mage.cards.p.PithingNeedle.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); + cards.add(new SetCardInfo("Pithing Needle", 44, Rarity.MYTHIC, mage.cards.p.PithingNeedle.class, cardGraphicInfo)); cards.add(new SetCardInfo("Planar Bridge", 45, Rarity.MYTHIC, mage.cards.p.PlanarBridge.class)); - cards.add(new SetCardInfo("Platinum Angel", 46, Rarity.MYTHIC, mage.cards.p.PlatinumAngel.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Rings of Brighthearth", 21, Rarity.MYTHIC, mage.cards.r.RingsOfBrighthearth.class, new CardGraphicInfo( - FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Scroll Rack", 22, Rarity.MYTHIC, mage.cards.s.ScrollRack.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Sculpting Steel", 23, Rarity.MYTHIC, mage.cards.s.SculptingSteel.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Solemn Simulacrum", 25, Rarity.MYTHIC, mage.cards.s.SolemnSimulacrum.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, - false))); - cards.add(new SetCardInfo("Sol Ring", 24, Rarity.MYTHIC, mage.cards.s.SolRing.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Sphere of Resistance", 47, Rarity.MYTHIC, mage.cards.s.SphereOfResistance.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Staff of Domination", 48, Rarity.MYTHIC, mage.cards.s.StaffOfDomination.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Static Orb", 26, Rarity.MYTHIC, mage.cards.s.StaticOrb.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Steel Overseer", 27, Rarity.MYTHIC, mage.cards.s.SteelOverseer.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Sundering Titan", 49, Rarity.MYTHIC, mage.cards.s.SunderingTitan.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Sword of Body and Mind", 50, Rarity.MYTHIC, mage.cards.s.SwordOfBodyAndMind.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Sword of Feast and Famine", 28, Rarity.MYTHIC, mage.cards.s.SwordOfFeastAndFamine.class, new CardGraphicInfo( - FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Sword of Fire and Ice", 29, Rarity.MYTHIC, mage.cards.s.SwordOfFireAndIce.class, new CardGraphicInfo( - FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Sword of Light and Shadow", 30, Rarity.MYTHIC, mage.cards.s.SwordOfLightAndShadow.class, new CardGraphicInfo( - FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Sword of War and Peace", 51, Rarity.MYTHIC, mage.cards.s.SwordOfWarAndPeace.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Torrential Gearhulk", 4, Rarity.MYTHIC, mage.cards.t.TorrentialGearhulk.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Trinisphere", 52, Rarity.MYTHIC, mage.cards.t.Trinisphere.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Vedalken Shackles", 53, Rarity.MYTHIC, mage.cards.v.VedalkenShackles.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); - cards.add(new SetCardInfo("Verdurous Gearhulk", 5, Rarity.MYTHIC, mage.cards.v.VerdurousGearhulk.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, - false))); - cards.add(new SetCardInfo("Wurmcoil Engine", 54, Rarity.MYTHIC, mage.cards.w.WurmcoilEngine.class, new CardGraphicInfo(FrameStyle.KLD_INVENTION, false))); + cards.add(new SetCardInfo("Platinum Angel", 46, Rarity.MYTHIC, mage.cards.p.PlatinumAngel.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Rings of Brighthearth", 21, Rarity.MYTHIC, mage.cards.r.RingsOfBrighthearth.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Scroll Rack", 22, Rarity.MYTHIC, mage.cards.s.ScrollRack.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Sculpting Steel", 23, Rarity.MYTHIC, mage.cards.s.SculptingSteel.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Solemn Simulacrum", 25, Rarity.MYTHIC, mage.cards.s.SolemnSimulacrum.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Sol Ring", 24, Rarity.MYTHIC, mage.cards.s.SolRing.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Sphere of Resistance", 47, Rarity.MYTHIC, mage.cards.s.SphereOfResistance.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Staff of Domination", 48, Rarity.MYTHIC, mage.cards.s.StaffOfDomination.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Static Orb", 26, Rarity.MYTHIC, mage.cards.s.StaticOrb.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Steel Overseer", 27, Rarity.MYTHIC, mage.cards.s.SteelOverseer.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Sundering Titan", 49, Rarity.MYTHIC, mage.cards.s.SunderingTitan.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Sword of Body and Mind", 50, Rarity.MYTHIC, mage.cards.s.SwordOfBodyAndMind.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Sword of Feast and Famine", 28, Rarity.MYTHIC, mage.cards.s.SwordOfFeastAndFamine.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Sword of Fire and Ice", 29, Rarity.MYTHIC, mage.cards.s.SwordOfFireAndIce.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Sword of Light and Shadow", 30, Rarity.MYTHIC, mage.cards.s.SwordOfLightAndShadow.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Sword of War and Peace", 51, Rarity.MYTHIC, mage.cards.s.SwordOfWarAndPeace.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Torrential Gearhulk", 4, Rarity.MYTHIC, mage.cards.t.TorrentialGearhulk.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Trinisphere", 52, Rarity.MYTHIC, mage.cards.t.Trinisphere.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Vedalken Shackles", 53, Rarity.MYTHIC, mage.cards.v.VedalkenShackles.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Verdurous Gearhulk", 5, Rarity.MYTHIC, mage.cards.v.VerdurousGearhulk.class, cardGraphicInfo)); + cards.add(new SetCardInfo("Wurmcoil Engine", 54, Rarity.MYTHIC, mage.cards.w.WurmcoilEngine.class, cardGraphicInfo)); } } diff --git a/Mage.Sets/src/mage/sets/MastersEditionIII.java b/Mage.Sets/src/mage/sets/MastersEditionIII.java index 1551119c2a6..ae8ce58ab70 100644 --- a/Mage.Sets/src/mage/sets/MastersEditionIII.java +++ b/Mage.Sets/src/mage/sets/MastersEditionIII.java @@ -204,6 +204,7 @@ public class MastersEditionIII extends ExpansionSet { 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)); diff --git a/Mage.Sets/src/mage/sets/TheDark.java b/Mage.Sets/src/mage/sets/TheDark.java index 5629aef5f15..a753868ffd5 100644 --- a/Mage.Sets/src/mage/sets/TheDark.java +++ b/Mage.Sets/src/mage/sets/TheDark.java @@ -63,7 +63,7 @@ public class TheDark extends ExpansionSet { cards.add(new SetCardInfo("Bog Rats", 4, Rarity.COMMON, mage.cards.b.BogRats.class)); cards.add(new SetCardInfo("Bone Flute", 94, Rarity.UNCOMMON, mage.cards.b.BoneFlute.class)); cards.add(new SetCardInfo("Book of Rass", 95, Rarity.UNCOMMON, mage.cards.b.BookOfRass.class)); - cards.add(new SetCardInfo("Brainwash", 76, Rarity.COMMON, mage.cards.b.Brainwash.class)); + cards.add(new SetCardInfo("Brainwash", 76, Rarity.COMMON, mage.cards.b.Brainwash.class)); cards.add(new SetCardInfo("Brothers of Fire", 58, Rarity.UNCOMMON, mage.cards.b.BrothersOfFire.class)); cards.add(new SetCardInfo("Carnivorous Plant", 38, Rarity.COMMON, mage.cards.c.CarnivorousPlant.class)); cards.add(new SetCardInfo("Cave People", 59, Rarity.UNCOMMON, mage.cards.c.CavePeople.class)); @@ -104,6 +104,7 @@ public class TheDark extends ExpansionSet { cards.add(new SetCardInfo("Marsh Viper", 44, Rarity.COMMON, mage.cards.m.MarshViper.class)); cards.add(new SetCardInfo("Maze of Ith", 114, Rarity.UNCOMMON, mage.cards.m.MazeOfIth.class)); cards.add(new SetCardInfo("Merfolk Assassin", 31, Rarity.UNCOMMON, mage.cards.m.MerfolkAssassin.class)); + cards.add(new SetCardInfo("Morale", 87, Rarity.COMMON, mage.cards.m.Morale.class)); cards.add(new SetCardInfo("Murk Dwellers", 11, Rarity.COMMON, mage.cards.m.MurkDwellers.class)); cards.add(new SetCardInfo("Niall Silvain", 45, Rarity.RARE, mage.cards.n.NiallSilvain.class)); cards.add(new SetCardInfo("Orc General", 72, Rarity.UNCOMMON, mage.cards.o.OrcGeneral.class)); @@ -119,7 +120,7 @@ public class TheDark extends ExpansionSet { cards.add(new SetCardInfo("Sisters of the Flame", 73, Rarity.UNCOMMON, mage.cards.s.SistersOfTheFlame.class)); cards.add(new SetCardInfo("Skull of Orm", 106, Rarity.UNCOMMON, mage.cards.s.SkullOfOrm.class)); cards.add(new SetCardInfo("Squire", 90, Rarity.COMMON, mage.cards.s.Squire.class)); - cards.add(new SetCardInfo("Standing Stones", 107, Rarity.UNCOMMON, mage.cards.s.StandingStones.class)); + cards.add(new SetCardInfo("Standing Stones", 107, Rarity.UNCOMMON, mage.cards.s.StandingStones.class)); cards.add(new SetCardInfo("Stone Calendar", 108, Rarity.RARE, mage.cards.s.StoneCalendar.class)); cards.add(new SetCardInfo("Sunken City", 35, Rarity.COMMON, mage.cards.s.SunkenCity.class)); cards.add(new SetCardInfo("Tivadar's Crusade", 91, Rarity.UNCOMMON, mage.cards.t.TivadarsCrusade.class)); diff --git a/Mage.Sets/src/mage/sets/TimeSpiral.java b/Mage.Sets/src/mage/sets/TimeSpiral.java index b3c01a8ad82..f943f5cb345 100644 --- a/Mage.Sets/src/mage/sets/TimeSpiral.java +++ b/Mage.Sets/src/mage/sets/TimeSpiral.java @@ -130,6 +130,7 @@ public class TimeSpiral extends ExpansionSet { cards.add(new SetCardInfo("Haunting Hymn", 112, Rarity.UNCOMMON, mage.cards.h.HauntingHymn.class)); cards.add(new SetCardInfo("Havenwood Wurm", 199, Rarity.COMMON, mage.cards.h.HavenwoodWurm.class)); cards.add(new SetCardInfo("Herd Gnarr", 200, Rarity.COMMON, mage.cards.h.HerdGnarr.class)); + cards.add(new SetCardInfo("Hivestone", 256, Rarity.RARE, mage.cards.h.Hivestone.class)); cards.add(new SetCardInfo("Hypergenesis", 201, Rarity.RARE, mage.cards.h.Hypergenesis.class)); cards.add(new SetCardInfo("Ib Halfheart, Goblin Tactician", 163, Rarity.RARE, mage.cards.i.IbHalfheartGoblinTactician.class)); cards.add(new SetCardInfo("Icatian Crier", 23, Rarity.COMMON, mage.cards.i.IcatianCrier.class)); diff --git a/Mage.Sets/src/mage/sets/Visions.java b/Mage.Sets/src/mage/sets/Visions.java index 868a648f504..25b49f8b709 100644 --- a/Mage.Sets/src/mage/sets/Visions.java +++ b/Mage.Sets/src/mage/sets/Visions.java @@ -58,6 +58,7 @@ public class Visions extends ExpansionSet { cards.add(new SetCardInfo("Archangel", 101, Rarity.RARE, mage.cards.a.Archangel.class)); cards.add(new SetCardInfo("Army Ants", 126, Rarity.UNCOMMON, mage.cards.a.ArmyAnts.class)); cards.add(new SetCardInfo("Betrayal", 26, Rarity.COMMON, mage.cards.b.Betrayal.class)); + cards.add(new SetCardInfo("Blanket of Night", 2, Rarity.UNCOMMON, mage.cards.b.BlanketOfNight.class)); cards.add(new SetCardInfo("Breezekeeper", 27, Rarity.COMMON, mage.cards.b.Breezekeeper.class)); cards.add(new SetCardInfo("Chronatog", 28, Rarity.RARE, mage.cards.c.Chronatog.class)); cards.add(new SetCardInfo("City of Solitude", 52, Rarity.RARE, mage.cards.c.CityOfSolitude.class)); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/counter/AddingCountersToPermanentsTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/counter/AddingCountersToPermanentsTest.java index 131b7b18b0d..f341e607f4b 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/counter/AddingCountersToPermanentsTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/counter/AddingCountersToPermanentsTest.java @@ -67,4 +67,28 @@ public class AddingCountersToPermanentsTest extends CardTestPlayerBase { } + /** + * Fairgrounds Trumpeter does not get a counter at the end of turn when + * Woodland Wanderer enters the battlefield + */ + @Test + public void testFairgroundsTrumpeter() { + addCard(Zone.BATTLEFIELD, playerA, "Forest", 7); + // At the beginning of each end step, if a +1/+1 counter was placed on a permanent under your control this turn, put a +1/+1 counter on Fairgrounds Trumpeter. + addCard(Zone.HAND, playerA, "Fairgrounds Trumpeter", 1); // Creature 2/2 {2}{G} + // Vigilance, trample + // Converge — Woodland Wanderer enters the battlefield with a +1/+1 counter on it for each color of mana spent to cast it. + addCard(Zone.HAND, playerA, "Woodland Wanderer", 1); // Creature 2/2 {3}{G} + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Woodland Wanderer"); + castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Fairgrounds Trumpeter"); + + setStopAt(1, PhaseStep.END_TURN); + execute(); + + assertPowerToughness(playerA, "Woodland Wanderer", 3, 3); + assertPowerToughness(playerA, "Fairgrounds Trumpeter", 3, 3); + + } + } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/control/GainControlTargetEffectTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/control/GainControlTargetEffectTest.java index 67d160b6b8b..cad199d155f 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/control/GainControlTargetEffectTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/control/GainControlTargetEffectTest.java @@ -105,4 +105,36 @@ public class GainControlTargetEffectTest extends CardTestPlayerBase { assertPermanentCount(playerA, "Mutavault", 1); } + + /** + * Steel Golem, once Donate'd to another player does not disable their ability to play creature cards. + */ + @Test + public void testDonateSteelGolem() { + // You can't cast creature spells. + addCard(Zone.HAND, playerA, "Steel Golem", 1); // Creature 3/4 {3} + // Target player gains control of target permanent you control. + addCard(Zone.HAND, playerA, "Donate", 1); // Sorcery {2}{U} + addCard(Zone.BATTLEFIELD, playerA, "Island", 6); + + addCard(Zone.BATTLEFIELD, playerB, "Plains", 2); + addCard(Zone.HAND, playerB, "Silvercoat Lion", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Steel Golem"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Donate", playerB); + addTarget(playerA, "Steel Golem"); + + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Silvercoat Lion"); + + setStopAt(2, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerA, "Donate", 1); + assertPermanentCount(playerA, "Steel Golem", 0); + assertPermanentCount(playerB, "Steel Golem", 1); + assertPermanentCount(playerB, "Silvercoat Lion", 0); + assertHandCount(playerB, "Silvercoat Lion", 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..f5975fe686d 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 @@ -79,5 +79,51 @@ public class GontiLordOfLuxuryEffectTest extends CardTestPlayerBase { assertPermanentCount(playerB, "Rashmi, Eternities Crafter", 1); } + /** + * 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); + + } + } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/aer/HopeOfGhirapurTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/aer/HopeOfGhirapurTest.java new file mode 100644 index 00000000000..b0340abb5b6 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/aer/HopeOfGhirapurTest.java @@ -0,0 +1,59 @@ +package org.mage.test.cards.single.aer; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author Quercitron + */ +public class HopeOfGhirapurTest extends CardTestPlayerBase { + + @Test + public void testThatNoncreatureSpellsCannotBeCast() { + addCard(Zone.BATTLEFIELD, playerA, "Hope of Ghirapur"); + + addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1); + addCard(Zone.HAND, playerB, "Shock"); + + attack(1, playerA, "Hope of Ghirapur"); + activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Sacrifice", playerB); + + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Shock", playerA); + + setStopAt(2, PhaseStep.BEGIN_COMBAT); + execute(); + + assertLife(playerA, 20); + assertLife(playerB, 19); + assertPermanentCount(playerA, "Hope of Ghirapur", 0); + } + + // Test that ability cannot be activated if after damage Hope of Ghirapur was removed + // from the battlefield and returned back. + @Test + public void testWhenHopeOfGhirapurWasRemovedAndReturnedBack() { + addCard(Zone.BATTLEFIELD, playerA, "Hope of Ghirapur"); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 1); + addCard(Zone.HAND, playerA, "Cloudshift"); + + addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1); + addCard(Zone.HAND, playerB, "Shock"); + + attack(1, playerA, "Hope of Ghirapur"); + castSpell(1, PhaseStep.END_COMBAT, playerA, "Cloudshift", "Hope of Ghirapur"); + activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Sacrifice", playerB); + + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Shock", playerA); + + setStopAt(2, PhaseStep.BEGIN_COMBAT); + execute(); + + assertLife(playerA, 18); + assertLife(playerB, 19); + assertPermanentCount(playerA, "Hope of Ghirapur", 1); + } + +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/fut/MuragandaPetroglyphsTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/fut/MuragandaPetroglyphsTest.java new file mode 100644 index 00000000000..c8263589cbb --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/fut/MuragandaPetroglyphsTest.java @@ -0,0 +1,189 @@ +package org.mage.test.cards.single.fut; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import mage.filter.Filter; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * This test is based on rulings of the card Muraganda Petroglyphs in magic Gatherer site + * (http://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=145110), accessed in + * 08/01/2017. + * + * @author alexsandro. + */ +public class MuragandaPetroglyphsTest extends CardTestPlayerBase { + + + /** + * Muraganda Petroglyphs gives a bonus only to creatures that have no rules text at all. + * This includes true vanilla creatures (such as Grizzly Bears), face-down creatures, + * many tokens, and creatures that have lost their abilities (due to Ovinize, for example). + * Any ability of any kind, whether or not the ability functions in the on the battlefield zone, + * including things like “Cycling 2” means the creature doesn’t get the bonus. + */ + @Test + public void trueVanillaCardsTest() { + addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears", 1); + addCard(Zone.BATTLEFIELD, playerB, "Grizzly Bears", 1); + + addCard(Zone.BATTLEFIELD, playerA, "Muraganda Petroglyphs", 1); + + setStopAt(1, PhaseStep.PRECOMBAT_MAIN); + execute(); + + assertPowerToughness(playerA, "Grizzly Bears", 4, 4, Filter.ComparisonScope.Any); + assertPowerToughness(playerB, "Grizzly Bears", 4, 4, Filter.ComparisonScope.Any); + + } + + @Test + public void faceDownCreaturesTest() { + addCard(Zone.HAND, playerA, "Pine Walker"); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 3); + addCard(Zone.BATTLEFIELD, playerA, "Muraganda Petroglyphs", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Pine Walker"); + setChoice(playerA, "Yes"); // cast it face down as 2/2 creature + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "", 1); + assertPowerToughness(playerA, "", 4, 4); + } + + @Test + public void faceDownGainedAbilityTest() { + addCard(Zone.HAND, playerA, "Pine Walker"); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 5); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); + addCard(Zone.BATTLEFIELD, playerA, "Mass Hysteria"); // All creatures have haste. + + addCard(Zone.BATTLEFIELD, playerA, "Muraganda Petroglyphs", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Pine Walker"); + setChoice(playerA, "Yes"); // cast it face down as 2/2 creature + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPermanentCount(playerA, "", 1); + assertPowerToughness(playerA, "", 2, 2); + } + + @Test + public void tokenTest() { + addCard(Zone.BATTLEFIELD, playerA, "Plains", 2); + addCard(Zone.BATTLEFIELD, playerA, "Muraganda Petroglyphs", 1); + // Put two 1/1 white Soldier creature tokens onto the battlefield. + addCard(Zone.HAND, playerA, "Raise the Alarm"); // Instant {1}{W} + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Raise the Alarm"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPowerToughness(playerA, "Soldier", 3, 3); + } + + @Test + public void loseAbilitiesTest() { + addCard(Zone.BATTLEFIELD, playerA, "Island", 2); + addCard(Zone.BATTLEFIELD, playerB, "Goblin Guide", 1); + addCard(Zone.BATTLEFIELD, playerA, "Muraganda Petroglyphs", 1); + + addCard(Zone.HAND, playerA, "Ovinize"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Ovinize", "Goblin Guide"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPowerToughness(playerB, "Goblin Guide", 2, 3); + } + + @Test + public void CyclingAbilityTest() { + addCard(Zone.BATTLEFIELD, playerA, "Hundroog", 1); // Cycling {3}, 4/7 + addCard(Zone.BATTLEFIELD, playerA, "Muraganda Petroglyphs", 1); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPowerToughness(playerA, "Hundroog", 4, 7); + } + + /** + * Animated basic lands have mana abilities, so they won’t get the bonus. + */ + + @Test + public void animateBasicLandTest() { + addCard(Zone.BATTLEFIELD, playerA, "Forest", 5); + addCard(Zone.BATTLEFIELD, playerA, "Muraganda Petroglyphs", 1); + addCard(Zone.HAND, playerA, "Vastwood Zendikon"); + + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Vastwood Zendikon", "Forest"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPowerToughness(playerA, "Forest", 6, 4); + + } + + /** + * Some Auras and Equipment grant abilities to creatures, meaning the affected creature would no longer + * get the +2/+2 bonus. For example, Flight grants flying to the enchanted creature. Other Auras and Equipment + * do not, meaning the affected creature would continue to get the +2/+2 bonus. For example, Dehydration states + * something now true about the enchanted creature, but doesn’t give it any abilities. Auras and Equipment that + * grant abilities will use the words “gains” or “has,” and they’ll list a keyword ability or an ability in + * quotation marks. + */ + @Test + public void grantAbilitiesTest() { + addCard(Zone.BATTLEFIELD, playerA, "Forest", 5); + addCard(Zone.BATTLEFIELD, playerA, "Island", 5); + addCard(Zone.BATTLEFIELD, playerA, "Muraganda Petroglyphs", 1); + addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears", 1); + addCard(Zone.BATTLEFIELD, playerA, "Runeclaw Bear", 1); + // Enchanted creature gets +2/+0 and has trample. + addCard(Zone.HAND, playerA, "Rancor"); + // Enchanted creature doesn't untap during itscontroller's untap step. + addCard(Zone.HAND, playerA, "Dehydration"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA,"Rancor", "Grizzly Bears"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dehydration", "Runeclaw Bear"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPowerToughness(playerA, "Grizzly Bears", 4, 2); + + assertPowerToughness(playerA, "Runeclaw Bear", 4, 4); + + } + + /** + * Cipher grants an ability to creatures, meaning the affected creatures would no longer get the +2/+2 bonus. + */ + @Test + public void cipherTest() { + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 6); + addCard(Zone.BATTLEFIELD, playerA, "Muraganda Petroglyphs", 1); + addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears", 1); + + addCard(Zone.HAND, playerA, "Shadow Slice"); // {4}{B} + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Shadow Slice"); + setChoice(playerA, "Grizzly Bears"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertPowerToughness(playerA, "Grizzly Bears", 2, 2); + } +} 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 new file mode 100644 index 00000000000..945e1848111 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/tsp/HivestoneTest.java @@ -0,0 +1,60 @@ +package org.mage.test.cards.single.tsp; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import mage.filter.Filter; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * Created by Alexsandr0x. + */ +public class HivestoneTest extends CardTestPlayerBase { + + /** + * If a creature is already a Sliver, Hivestone has no effect on it. + */ + @Test + public void abilityCheckTest() { + addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears", 1); + addCard(Zone.BATTLEFIELD, playerA, "Hivestone", 1); + + addCard(Zone.BATTLEFIELD, playerA, "Muscle Sliver", 1); + + addCard(Zone.BATTLEFIELD, playerB, "Runeclaw Bear", 1); + + setStopAt(1, PhaseStep.PRECOMBAT_MAIN); + execute(); + + 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. + */ + @Test + public void rootSliverTest() { + addCard(Zone.HAND, playerA, "Grizzly Bears", 1); + addCard(Zone.BATTLEFIELD, playerA, "Hivestone", 1); + // Root Sliver can't be countered. Sliver spells can't be countered by spells or abilities. + addCard(Zone.BATTLEFIELD, playerA, "Root Sliver", 1); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 2); + + + addCard(Zone.BATTLEFIELD, playerB, "Island", 2); + addCard(Zone.HAND, playerB, "Counterspell"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Grizzly Bears"); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Counterspell", "Grizzly Bears", "Grizzly Bears"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerA, 1); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/PossibilityStormTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/PossibilityStormTest.java index 84ef7030c2b..69403791c3a 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/PossibilityStormTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/PossibilityStormTest.java @@ -27,10 +27,8 @@ */ package org.mage.test.cards.triggers; -import mage.cards.Card; import mage.constants.PhaseStep; import mage.constants.Zone; -import org.junit.Assert; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; @@ -61,7 +59,7 @@ public class PossibilityStormTest extends CardTestPlayerBase { // the top of his or her library until he or she exiles a card that shares a card type with it. That // player may cast that card without paying its mana cost. Then he or she puts all cards exiled with // Possibility Storm on the bottom of his or her library in a random order. - addCard(Zone.BATTLEFIELD, playerA, "Possibility Storm", 2); + addCard(Zone.BATTLEFIELD, playerA, "Possibility Storm", 1); // {T}: Add {C} to your mana pool. // Morph {2} @@ -78,14 +76,7 @@ public class PossibilityStormTest extends CardTestPlayerBase { assertPermanentCount(playerA, "Zoetic Cavern", 0); - boolean zoeticCavernInLibrary = false; - for (Card card : playerA.getLibrary().getCards(currentGame)) { - if (card.getName().equals("Zoetic Cavern")) { - zoeticCavernInLibrary = true; - } - } - Assert.assertEquals("Zoetic Cavern has to be in the library", true, zoeticCavernInLibrary); - + assertLibraryCount(playerA, "Zoetic Cavern", 1); assertPermanentCount(playerA, "Silvercoat Lion", 1); } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/watchers/SpiritOfTheLabyrinthTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/watchers/SpiritOfTheLabyrinthTest.java index 2dae2257e5e..8cf128f6aa9 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/watchers/SpiritOfTheLabyrinthTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/watchers/SpiritOfTheLabyrinthTest.java @@ -10,28 +10,50 @@ import org.mage.test.serverside.base.CardTestPlayerBase; * @author BetaSteward */ public class SpiritOfTheLabyrinthTest extends CardTestPlayerBase { + /* * Spirit of the Labyrinth * Enchantment Creature — Spirit 3/1, 1W (2) * Each player can't draw more than one card each turn. * - */ - + */ + // test that only 1 card is drawn @Test public void testDrawCard() { addCard(Zone.BATTLEFIELD, playerA, "Island", 5); addCard(Zone.BATTLEFIELD, playerA, "Spirit of the Labyrinth"); addCard(Zone.HAND, playerA, "Brilliant Plan"); - + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Brilliant Plan"); - + setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); - - this.assertHandCount(playerA, 1); - - } - + this.assertHandCount(playerA, 1); + + } + + // test that only 1 card is drawn + @Test + public void testDrawCardHondenOfSeeingWinds() { + addCard(Zone.BATTLEFIELD, playerA, "Island", 5); + addCard(Zone.BATTLEFIELD, playerA, "Spirit of the Labyrinth"); + addCard(Zone.HAND, playerA, "Brilliant Plan"); + + // At the beginning of your upkeep, draw a card for each Shrine you control. + addCard(Zone.BATTLEFIELD, playerB, "Honden of Seeing Winds"); + // At the beginning of your upkeep, put a 1/1 colorless Spirit creature token onto the battlefield for each Shrine you control. + addCard(Zone.BATTLEFIELD, playerB, "Honden of Life's Web"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Brilliant Plan"); + + setStopAt(2, PhaseStep.PRECOMBAT_MAIN); + execute(); + + assertPermanentCount(playerB, "Spirit", 2); + this.assertHandCount(playerA, 1); + this.assertHandCount(playerB, 1); + + } } diff --git a/Mage/src/main/java/mage/abilities/condition/common/RevoltCondition.java b/Mage/src/main/java/mage/abilities/condition/common/RevoltCondition.java index 799a7362f7c..33d1ce9744a 100644 --- a/Mage/src/main/java/mage/abilities/condition/common/RevoltCondition.java +++ b/Mage/src/main/java/mage/abilities/condition/common/RevoltCondition.java @@ -45,7 +45,7 @@ public class RevoltCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - RevoltWatcher watcher = (RevoltWatcher) game.getState().getWatchers().get("Revolt"); + RevoltWatcher watcher = (RevoltWatcher) game.getState().getWatchers().get(RevoltWatcher.class.getName()); return watcher != null && watcher.revoltActive(source.getControllerId()); } diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubtypeAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubtypeAllEffect.java new file mode 100644 index 00000000000..d47f92f5cc9 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/AddCardSubtypeAllEffect.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 mage.abilities.effects.common.continuous; + +import mage.abilities.Ability; +import mage.abilities.effects.ContinuousEffectImpl; +import mage.constants.*; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterLandPermanent; +import mage.game.Game; +import mage.game.permanent.Permanent; + +/** + * @author Galatolol + */ + +public class AddCardSubtypeAllEffect extends ContinuousEffectImpl { + + private static FilterPermanent filter; + private static String addedSubtype; + + public AddCardSubtypeAllEffect(FilterPermanent _filter, String _addedSubtype, DependencyType _dependency) { + super(Duration.WhileOnBattlefield, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit); + filter = _filter; + staticText = ""; + addedSubtype = _addedSubtype; + addDependencyType(_dependency); + } + + public AddCardSubtypeAllEffect(final AddCardSubtypeAllEffect effect) { + super(effect); + } + + @Override + public boolean apply(Game game, Ability source) { + for (Permanent perm : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { + if (perm != null && !perm.getSubtype(game).contains(addedSubtype)) { + perm.getSubtype(game).add(addedSubtype); + } + } + return true; + } + + @Override + public AddCardSubtypeAllEffect copy() { + return new AddCardSubtypeAllEffect(this); + } + +} \ No newline at end of file diff --git a/Mage/src/main/java/mage/abilities/effects/common/counter/GetEnergyCountersControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/counter/GetEnergyCountersControllerEffect.java index 3cf03ea452b..b2555462216 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/counter/GetEnergyCountersControllerEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/counter/GetEnergyCountersControllerEffect.java @@ -61,9 +61,9 @@ public class GetEnergyCountersControllerEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player != null) { - return player.addCounters(CounterType.ENERGY.createInstance(value.calculate(game, source, this)), game); + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + return controller.addCounters(CounterType.ENERGY.createInstance(value.calculate(game, source, this)), game); } return false; } @@ -72,7 +72,7 @@ public class GetEnergyCountersControllerEffect extends OneShotEffect { if (!staticText.isEmpty()) { return; } - + StringBuilder sb = new StringBuilder(); sb.append("you get "); int val = 1; diff --git a/Mage/src/main/java/mage/abilities/keyword/MorphAbility.java b/Mage/src/main/java/mage/abilities/keyword/MorphAbility.java index 2738a548469..7ea7f48f7e1 100644 --- a/Mage/src/main/java/mage/abilities/keyword/MorphAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/MorphAbility.java @@ -100,7 +100,7 @@ public class MorphAbility extends StaticAbility implements AlternativeSourceCost protected static final String ABILITY_KEYWORD = "Morph"; protected static final String ABILITY_KEYWORD_MEGA = "Megamorph"; protected static final String REMINDER_TEXT = "(You may cast this card face down as a 2/2 creature for {3}. Turn it face up any time for its morph cost.)"; - protected static final String REMINDER_TEXT_MEGA = "(You may cast this card face down as a 2/2 creature for {3}. Turn it face up any time for its megamorph cost and put a +1/+1 counter on it.)"; + protected static final String REMINDER_TEXT_MEGA = "(You may cast this card face down as a 2/2 creature for {3}. Turn it face up any time for its megamorph cost and put a +1/+1 counter on it.)"; protected String ruleText; protected AlternativeCost2Impl alternateCosts = new AlternativeCost2Impl(ABILITY_KEYWORD, REMINDER_TEXT, new GenericManaCost(3)); protected Costs morphCosts; @@ -194,7 +194,8 @@ public class MorphAbility extends StaticAbility implements AlternativeSourceCost @Override public boolean isAvailable(Ability source, Game game) { - return true; + return game.isMainPhase() && game.getActivePlayerId().equals(source.getControllerId()) + && (game.getStack().isEmpty() || (game.getStack().size() == 1 && game.getStack().getFirst().getSourceId().equals(source.getSourceId()))); } @Override @@ -282,10 +283,7 @@ public class MorphAbility extends StaticAbility implements AlternativeSourceCost @Override public String getCastMessageSuffix(Game game) { - StringBuilder sb = new StringBuilder(); - int position = 0; - sb.append(alternateCosts.getCastSuffixMessage(position)); - return sb.toString(); + return alternateCosts.getCastSuffixMessage(0); } @Override diff --git a/Mage/src/main/java/mage/abilities/mana/ActivatedManaAbilityImpl.java b/Mage/src/main/java/mage/abilities/mana/ActivatedManaAbilityImpl.java index 4a146d9c815..1c7b4d68746 100644 --- a/Mage/src/main/java/mage/abilities/mana/ActivatedManaAbilityImpl.java +++ b/Mage/src/main/java/mage/abilities/mana/ActivatedManaAbilityImpl.java @@ -98,6 +98,11 @@ public abstract class ActivatedManaAbilityImpl extends ActivatedAbilityImpl impl return netMana.size() > 0; } + /** + * Is it allowed to undo the mana creation. + * It's e.g. not allowed if some game revealing information is related (like reveal the top card of the library) + * @return + */ public boolean isUndoPossible() { return undoPossible; } diff --git a/Mage/src/main/java/mage/abilities/mana/AnyColorLandsProduceManaAbility.java b/Mage/src/main/java/mage/abilities/mana/AnyColorLandsProduceManaAbility.java index 989b558f609..80812218084 100644 --- a/Mage/src/main/java/mage/abilities/mana/AnyColorLandsProduceManaAbility.java +++ b/Mage/src/main/java/mage/abilities/mana/AnyColorLandsProduceManaAbility.java @@ -29,6 +29,8 @@ package mage.abilities.mana; import java.util.ArrayList; import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; import mage.Mana; import mage.abilities.Abilities; import mage.abilities.Ability; @@ -161,6 +163,7 @@ class AnyColorLandsProduceManaEffect extends ManaEffect { } private Mana getManaTypes(Game game, Ability source) { + Logger.getLogger(this.getClass().getName()).log(Level.WARNING, "needed to identify endless loop causing cards: {0}", source.getSourceObject(game).getName()); List lands = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game); Mana types = new Mana(); for (Permanent land : lands) { diff --git a/Mage/src/main/java/mage/abilities/mana/SimpleManaAbility.java b/Mage/src/main/java/mage/abilities/mana/SimpleManaAbility.java index 6f78fabdce7..4ff06bd4e63 100644 --- a/Mage/src/main/java/mage/abilities/mana/SimpleManaAbility.java +++ b/Mage/src/main/java/mage/abilities/mana/SimpleManaAbility.java @@ -43,17 +43,32 @@ import mage.game.Game; */ public class SimpleManaAbility extends ActivatedManaAbilityImpl { + private boolean predictable; + public SimpleManaAbility(Zone zone, ManaEffect effect, Cost cost) { + this(zone, effect, cost, true); + } + /** + * + * @param zone + * @param effect + * @param cost + * @param predictable set to false if definig the mana type or amount needs to reveal information and can't be predicted + */ + public SimpleManaAbility(Zone zone, ManaEffect effect, Cost cost, boolean predictable) { super(zone, effect, cost); + this.predictable = predictable; } public SimpleManaAbility(Zone zone, Mana mana, Cost cost) { super(zone, new BasicManaEffect(mana), cost); this.netMana.add(mana.copy()); + this.predictable = true; } public SimpleManaAbility(final SimpleManaAbility ability) { super(ability); + this.predictable = ability.predictable; } @Override @@ -63,7 +78,7 @@ public class SimpleManaAbility extends ActivatedManaAbilityImpl { @Override public List getNetMana(Game game) { - if (netMana.isEmpty()) { + if (netMana.isEmpty() && predictable) { for (Effect effect: getEffects()) { if (effect instanceof ManaEffect) { Mana effectMana =((ManaEffect)effect).getMana(game, this); diff --git a/Mage/src/main/java/mage/cards/FrameStyle.java b/Mage/src/main/java/mage/cards/FrameStyle.java index add2795cc52..13a4dae88bd 100644 --- a/Mage/src/main/java/mage/cards/FrameStyle.java +++ b/Mage/src/main/java/mage/cards/FrameStyle.java @@ -26,6 +26,10 @@ public enum FrameStyle { * Zenkikar full art lands */ ZEN_FULL_ART_BASIC(BorderType.MOD, true), + /** + * Magic Player Rewards full art cards + */ + MPRP_FULL_ART_BASIC(BorderType.MOD, true), /** * Unhinged full art lands */ diff --git a/Mage/src/main/java/mage/cards/repository/CardRepository.java b/Mage/src/main/java/mage/cards/repository/CardRepository.java index 41d39928c75..06620498952 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 = 68; + private static final long CARD_CONTENT_VERSION = 69; private final TreeSet landTypes = new TreeSet(); private Dao cardDao; private Set classNames; diff --git a/Mage/src/main/java/mage/cards/repository/ExpansionRepository.java b/Mage/src/main/java/mage/cards/repository/ExpansionRepository.java index 42b699aca27..c8c23f729e5 100644 --- a/Mage/src/main/java/mage/cards/repository/ExpansionRepository.java +++ b/Mage/src/main/java/mage/cards/repository/ExpansionRepository.java @@ -28,7 +28,7 @@ public enum ExpansionRepository { private static final String JDBC_URL = "jdbc:h2:file:./db/cards.h2;AUTO_SERVER=TRUE"; private static final String VERSION_ENTITY_NAME = "expansion"; private static final long EXPANSION_DB_VERSION = 5; - private static final long EXPANSION_CONTENT_VERSION = 11; + private static final long EXPANSION_CONTENT_VERSION = 12; private Dao expansionDao; diff --git a/Mage/src/main/java/mage/game/combat/CombatGroup.java b/Mage/src/main/java/mage/game/combat/CombatGroup.java index 713929dcfe3..b18d6f76105 100644 --- a/Mage/src/main/java/mage/game/combat/CombatGroup.java +++ b/Mage/src/main/java/mage/game/combat/CombatGroup.java @@ -299,7 +299,7 @@ public class CombatGroup implements Serializable, Copyable { } if (damage > 0 && hasTrample(attacker)) { defenderDamage(attacker, damage, game); - } else { + } else if (!blockerOrder.isEmpty()) { // Assign the damge left to first blocker assigned.put(blockerOrder.get(0), assigned.get(blockerOrder.get(0)) + damage); } diff --git a/Mage/src/main/java/mage/game/stack/Spell.java b/Mage/src/main/java/mage/game/stack/Spell.java index 57a0fb74f9c..bd421709e68 100644 --- a/Mage/src/main/java/mage/game/stack/Spell.java +++ b/Mage/src/main/java/mage/game/stack/Spell.java @@ -432,6 +432,13 @@ public class Spell extends StackObjImpl implements Card { @Override public String getLogName() { + if (faceDown) { + if (getCardType().contains(CardType.CREATURE)) { + return "face down creature spell"; + } else { + return "face down spell"; + } + } return GameLog.getColoredObjectIdName(card); } @@ -451,7 +458,7 @@ public class Spell extends StackObjImpl implements Card { @Override public List getCardType() { - if (this.getSpellAbility().getSpellAbilityType().equals(SpellAbilityType.FACE_DOWN_CREATURE)) { + if (faceDown) { List cardTypes = new ArrayList<>(); cardTypes.add(CardType.CREATURE); return cardTypes; diff --git a/Mage/src/main/java/mage/players/Player.java b/Mage/src/main/java/mage/players/Player.java index 0f9638e302a..e915ac498a2 100644 --- a/Mage/src/main/java/mage/players/Player.java +++ b/Mage/src/main/java/mage/players/Player.java @@ -506,6 +506,7 @@ public interface Player extends MageItem, Copyable { * @param cards - list of cards that have to be moved * @param game - game * @param anyOrder - true if player can determine the order of the cards + * else random order * @param source - source ability * @return */ diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index 70308b01bbe..0b84f713b1a 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -825,8 +825,10 @@ public abstract class PlayerImpl implements Player, Serializable { if (!cardsToLibrary.isEmpty()) { Cards cards = new CardsImpl(cardsToLibrary); // prevent possible ConcurrentModificationException if (!anyOrder) { - for (UUID objectId : cards) { - moveObjectToLibrary(objectId, source == null ? null : source.getSourceId(), game, false, false); + while (!cards.isEmpty()) { + UUID cardId = cards.getRandom(game).getId(); + cards.remove(cardId); + moveObjectToLibrary(cardId, source == null ? null : source.getSourceId(), game, false, false); } } else { TargetCard target = new TargetCard(Zone.ALL, new FilterCard("card to put on the bottom of your library (last one chosen will be bottommost)")); @@ -864,8 +866,10 @@ public abstract class PlayerImpl implements Player, Serializable { Cards cards = new CardsImpl(cardsToLibrary); // prevent possible ConcurrentModificationException UUID sourceId = (source == null ? null : source.getSourceId()); if (!anyOrder) { - for (UUID cardId : cards) { - moveObjectToLibrary(cardId, sourceId, game, true, false); + while (!cards.isEmpty()) { + UUID cardId = cards.getRandom(game).getId(); + cards.remove(cardId); + moveObjectToLibrary(cardId, source == null ? null : source.getSourceId(), game, true, false); } } else { TargetCard target = new TargetCard(Zone.LIBRARY, new FilterCard("card to put on the top of your library (last one chosen will be topmost)")); @@ -2764,7 +2768,9 @@ public abstract class PlayerImpl implements Player, Serializable { case STATIC: if (card.getCardType().contains(CardType.LAND) && ability instanceof AlternativeSourceCosts) { if (canLandPlayAlternateSourceCostsAbility(card, available, ability, game)) { // e.g. Land with Morph - playable.add(card.getId()); + if (game.canPlaySorcery(getId())) { + playable.add(card.getId()); + } break Abilities; } } @@ -3289,6 +3295,9 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public boolean moveCardToGraveyardWithInfo(Card card, UUID sourceId, Game game, Zone fromZone) { + if (card == null) { + return false; + } boolean result = false; // Zone fromZone = game.getState().getZone(card.getId()); if (card.moveToZone(Zone.GRAVEYARD, sourceId, game, fromZone != null ? fromZone == Zone.BATTLEFIELD : false)) { @@ -3313,6 +3322,9 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public boolean moveCardToLibraryWithInfo(Card card, UUID sourceId, Game game, Zone fromZone, boolean toTop, boolean withName) { + if (card == null) { + return false; + } boolean result = false; if (card.moveToZone(Zone.LIBRARY, sourceId, game, toTop)) { if (!game.isSimulation()) { @@ -3342,6 +3354,9 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public boolean moveCardToExileWithInfo(Card card, UUID exileId, String exileName, UUID sourceId, Game game, Zone fromZone, boolean withName) { + if (card == null) { + return false; + } boolean result = false; if (card.moveToExile(exileId, exileName, sourceId, game)) { if (!game.isSimulation()) { diff --git a/Mage/src/main/java/mage/watchers/common/RevoltWatcher.java b/Mage/src/main/java/mage/watchers/common/RevoltWatcher.java index 549e3e5bc92..63f9d33717f 100644 --- a/Mage/src/main/java/mage/watchers/common/RevoltWatcher.java +++ b/Mage/src/main/java/mage/watchers/common/RevoltWatcher.java @@ -25,7 +25,6 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.watchers.common; import java.util.HashSet; @@ -49,11 +48,12 @@ public class RevoltWatcher extends Watcher { private final Set revoltActivePlayerIds = new HashSet<>(0); public RevoltWatcher() { - super("Revolt", WatcherScope.GAME); + super(RevoltWatcher.class.getName(), WatcherScope.GAME); } public RevoltWatcher(final RevoltWatcher watcher) { super(watcher); + this.revoltActivePlayerIds.addAll(watcher.revoltActivePlayerIds); } @Override @@ -78,8 +78,6 @@ public class RevoltWatcher extends Watcher { revoltActivePlayerIds.clear(); } - - @Override public RevoltWatcher copy() { return new RevoltWatcher(this); 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