From 32d7072a4e04245bbf777d8022d0e041c09ea5a1 Mon Sep 17 00:00:00 2001 From: nickmyers Date: Sat, 28 Feb 2015 12:00:34 -0600 Subject: [PATCH 1/5] Implemented TinyLeaders.java extending DeckValidator --- .../src/mage/deck/TinyLeaders.java | 172 ++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/TinyLeaders.java diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/TinyLeaders.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/TinyLeaders.java new file mode 100644 index 0000000000..41d759ba90 --- /dev/null +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/TinyLeaders.java @@ -0,0 +1,172 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package mage.deck; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import mage.abilities.common.CanBeYourCommanderAbility; +import mage.cards.Card; +import mage.cards.decks.Deck; +import mage.cards.decks.DeckValidator; +import mage.constants.CardType; +import mage.filter.FilterMana; +import mage.util.CardUtil; + +/** + * + * @author nickmyers + */ +public class TinyLeaders extends DeckValidator { + + protected List banned = new ArrayList<>(); + protected List bannedCommander = new ArrayList<>(); + + public TinyLeaders(String name) { + super(name); + } + + public TinyLeaders() { + this("Tiny Leaders"); + banned.add("Ancestral Recall"); + banned.add("Black Lotus"); + banned.add("Black Vise"); + banned.add("Channel"); + banned.add("Counterbalance"); + banned.add("Demonic Tutor"); + banned.add("Earthcraft"); + banned.add("Edric, Spymaster of Trest"); + banned.add("Fastbond"); + banned.add("Goblin Recruiter"); + banned.add("Hermit Druid"); + banned.add("Imperial Seal"); + banned.add("Library of Alexandria"); + banned.add("Karakas"); + banned.add("Mana Crypt"); + banned.add("Mana Drain"); + banned.add("Mana Vault"); + banned.add("Metalworker"); + banned.add("Mind Twist"); + banned.add("Mishra's Workshop"); + banned.add("Mox Emerald"); + banned.add("Mox Jet"); + banned.add("Mox Pearl"); + banned.add("Mox Ruby"); + banned.add("Mox Sapphire"); + banned.add("Necropotence"); + banned.add("Painter's Servant"); + banned.add("Shahrazad"); + banned.add("Skullclamp"); + banned.add("Sol Ring"); + banned.add("Strip Mine"); + banned.add("Survival of the Fittest"); + banned.add("Sword of Body and Mind"); + banned.add("Time Vault"); + banned.add("Time Walk"); + banned.add("Timetwister"); + banned.add("Tolarian Academy"); + banned.add("Umezawa's Jitte"); + banned.add("Vampiric Tutor"); + banned.add("Wheel of Fortune"); + banned.add("Yawgmoth's Will"); + + bannedCommander.add("Erayo, Soratami Ascendant"); + bannedCommander.add("Rofellos, Llanowar Emissary"); + bannedCommander.add("Derevi, Empyrical Tactician"); + + } + + @Override + public boolean validate(Deck deck) { + boolean valid = true; + + // Check CMC <= 3 of main deck + for(Card card : deck.getCards()) { + if(card.getManaCost().convertedManaCost() > 3) { + invalid.put("Mana Cost", "Converted Mana Cost of " + card.getName() + " is too high"); + valid = false; + } + } + + // Check CMC <=3 for commander + for(Card card : deck.getSideboard()) { + if(card.getManaCost().convertedManaCost() > 3) { + invalid.put("Commander Mana Cost", "Converted Mana Cost of " + card.getName() + " is too high"); + } + } + + if (deck.getCards().size() != 49) { + invalid.put("Deck", "Must contain 49 cards: has " + deck.getCards().size() + " cards"); + valid = false; + } + + List basicLandNames = new ArrayList<>(Arrays.asList("Forest", "Island", "Mountain", "Swamp", "Plains", + "Snow-Covered Forest", "Snow-Covered Island", "Snow-Covered Mountain", "Snow-Covered Swamp", "Snow-Covered Plains")); + Map counts = new HashMap<>(); + countCards(counts, deck.getCards()); + countCards(counts, deck.getSideboard()); + for (Map.Entry entry : counts.entrySet()) { + if (entry.getValue() > 1) { + if (!basicLandNames.contains(entry.getKey()) && !entry.getKey().equals("Relentless Rats") && !entry.getKey().equals("Shadowborn Apostle")) { + invalid.put(entry.getKey(), "Too many: " + entry.getValue()); + valid = false; + } + } + } + + for (String bannedCard : banned) { + if (counts.containsKey(bannedCard)) { + invalid.put(bannedCard, "Banned"); + valid = false; + } + } + + if (deck.getSideboard().size() == 1) { + Card commander = (Card) deck.getSideboard().toArray()[0]; + if (commander == null) { + invalid.put("Commander", "Commander invalid "); + return false; + } + if ((commander.getCardType().contains(CardType.CREATURE) && commander.getSupertype().contains("Legendary")) || + (commander.getCardType().contains(CardType.PLANESWALKER) && commander.getAbilities().contains(CanBeYourCommanderAbility.getInstance()))) { + if (!bannedCommander.contains(commander.getName())) { + FilterMana color = CardUtil.getColorIdentity(commander); + for (Card card : deck.getCards()) { + if (!cardHasValideColor(color, card)) { + invalid.put(card.getName(), "Invalid color (" + commander.getName() +")"); + valid = false; + } + } + } else { + invalid.put("Commander", "Commander banned (" + commander.getName() +")"); + valid = false; + } + } else { + invalid.put("Commander", "Commander invalid (" + commander.getName() +")"); + valid = false; + } + } else { + invalid.put("Commander", "Sideboard must contain only the commander"); + } + + return valid; + } + + public boolean cardHasValideColor(FilterMana commander, Card card) { + FilterMana cardColor = CardUtil.getColorIdentity(card); + if (cardColor.isBlack() && !commander.isBlack() + || cardColor.isBlue() && !commander.isBlue() + || cardColor.isGreen() && !commander.isGreen() + || cardColor.isRed() && !commander.isRed() + || cardColor.isWhite() && !commander.isWhite()) { + return false; + } + return true; + } + +} From 0c5fdb7301fbe5dc1ae109e5ed591b4a59f46f19 Mon Sep 17 00:00:00 2001 From: myersn024 Date: Tue, 3 Mar 2015 12:51:41 -0600 Subject: [PATCH 2/5] Updated implmentation of TinyLeaders.java Made several changes. The commander card should now be in the main board. It is found and verified against the deck name attribute. Both main board and sideboard are checked for the proper number of cards (50 and 10 respectively). Main board and sideboard card colors are also verified against the colors of the commander. I haven't written the server plugin for the game type yet, so this isn't tested. It should be very close to being right, though. --- .../src/mage/deck/TinyLeaders.java | 58 ++++++++++++------- 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/TinyLeaders.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/TinyLeaders.java index 41d759ba90..88c458dfc8 100644 --- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/TinyLeaders.java +++ b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/TinyLeaders.java @@ -10,7 +10,6 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; -import mage.abilities.common.CanBeYourCommanderAbility; import mage.cards.Card; import mage.cards.decks.Deck; import mage.cards.decks.DeckValidator; @@ -93,17 +92,23 @@ public class TinyLeaders extends DeckValidator { } } - // Check CMC <=3 for commander + // Check CMC <=3 for sideboard for(Card card : deck.getSideboard()) { if(card.getManaCost().convertedManaCost() > 3) { invalid.put("Commander Mana Cost", "Converted Mana Cost of " + card.getName() + " is too high"); - } + } } - if (deck.getCards().size() != 49) { - invalid.put("Deck", "Must contain 49 cards: has " + deck.getCards().size() + " cards"); + // make sure main deck and sideboard have the appropriate number of cards + if (deck.getCards().size() != 50) { + invalid.put("Deck", "Main deck must contain 50 cards including your commander: has " + deck.getCards().size() + " cards"); valid = false; } + + if (deck.getSideboard().size() != 10) { + invalid.put("Sideboard", "Sideboard must contain 10 cards: has " + deck.getSideboard().size() + " cards"); + valid = false; + } List basicLandNames = new ArrayList<>(Arrays.asList("Forest", "Island", "Mountain", "Swamp", "Plains", "Snow-Covered Forest", "Snow-Covered Island", "Snow-Covered Mountain", "Snow-Covered Swamp", "Snow-Covered Plains")); @@ -125,39 +130,52 @@ public class TinyLeaders extends DeckValidator { valid = false; } } - - if (deck.getSideboard().size() == 1) { - Card commander = (Card) deck.getSideboard().toArray()[0]; - if (commander == null) { - invalid.put("Commander", "Commander invalid "); - return false; + + // find commander in the main board + Card commander = null; + for (Card card : deck.getCards()) { + if(card.getName().equals(deck.getName())) { + commander = card.copy(); } - if ((commander.getCardType().contains(CardType.CREATURE) && commander.getSupertype().contains("Legendary")) || - (commander.getCardType().contains(CardType.PLANESWALKER) && commander.getAbilities().contains(CanBeYourCommanderAbility.getInstance()))) { - if (!bannedCommander.contains(commander.getName())) { + } + if(commander != null) { + // verify legendary creature + if (commander.getCardType().contains(CardType.CREATURE) && commander.getSupertype().contains("Legendary")) { + // verify commander against banned list + if(!bannedCommander.contains(commander.getName())) { + // verify deck colors FilterMana color = CardUtil.getColorIdentity(commander); for (Card card : deck.getCards()) { - if (!cardHasValideColor(color, card)) { + if (!cardHasValidColor(color, card)) { invalid.put(card.getName(), "Invalid color (" + commander.getName() +")"); valid = false; } } + + // verify sideboard colors + for (Card card : deck.getSideboard()) { + if (!cardHasValidColor(color,card)) { + invalid.put(card.getName(), "Invalid color (" + commander.getName() +")"); + valid = false; + } + } + } else { - invalid.put("Commander", "Commander banned (" + commander.getName() +")"); + invalid.put("Commander", "Commander banned (" + commander.getName() + ")"); valid = false; } } else { - invalid.put("Commander", "Commander invalid (" + commander.getName() +")"); + invalid.put("Commander", "Commander invalid (" + commander.getName() + ")"); valid = false; } } else { - invalid.put("Commander", "Sideboard must contain only the commander"); + invalid.put("Commander", deck.getName() + " not found in main board"); + valid = false; } - return valid; } - public boolean cardHasValideColor(FilterMana commander, Card card) { + public boolean cardHasValidColor(FilterMana commander, Card card) { FilterMana cardColor = CardUtil.getColorIdentity(card); if (cardColor.isBlack() && !commander.isBlack() || cardColor.isBlue() && !commander.isBlue() From ee224a391f78c39098192fb03b266a1ee3d7160d Mon Sep 17 00:00:00 2001 From: myersn024 Date: Tue, 3 Mar 2015 14:50:20 -0600 Subject: [PATCH 3/5] Implemented ForcedMarch.java --- .../sets/mercadianmasques/ForcedMarch.java | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 Mage.Sets/src/mage/sets/mercadianmasques/ForcedMarch.java diff --git a/Mage.Sets/src/mage/sets/mercadianmasques/ForcedMarch.java b/Mage.Sets/src/mage/sets/mercadianmasques/ForcedMarch.java new file mode 100644 index 0000000000..b4bda57d62 --- /dev/null +++ b/Mage.Sets/src/mage/sets/mercadianmasques/ForcedMarch.java @@ -0,0 +1,68 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package mage.sets.mercadianmasques; + +import java.util.UUID; +import mage.abilities.Ability; +import mage.constants.CardType; +import mage.constants.Rarity; + +/** + * + * @author nick.myers + */ +import mage.abilities.effects.OneShotEffect; +import mage.cards.CardImpl; +import mage.constants.Outcome; +import mage.game.Game; +import mage.game.permanent.Permanent; + + +public class ForcedMarch extends CardImpl { + + public ForcedMarch(UUID ownerId) { + super(ownerId, 136, "Forced March", Rarity.RARE, new CardType[]{CardType.SORCERY}, "{X}{B}{B}{B}"); + this.expansionSetCode = "MMQ"; + + // Destroy all creatures with converted mana cost X or less + this.getSpellAbility().addEffect(new ForcedMarchEffect()); + } + + public ForcedMarch(final ForcedMarch card) { + super(card); + } + + @Override + public ForcedMarch copy() { + return new ForcedMarch(this); + } +} + +class ForcedMarchEffect extends OneShotEffect { + public ForcedMarchEffect() { + super(Outcome.DestroyPermanent); + staticText = "Destroy all creatures with converted mana cost X or less"; + } + + public ForcedMarchEffect(final ForcedMarchEffect effect) { + super(effect); + } + + @Override + public ForcedMarchEffect copy() { + return new ForcedMarchEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + for(Permanent permanent : game.getBattlefield().getAllActivePermanents(CardType.CREATURE)) { + if (permanent.getManaCost().convertedManaCost() <= source.getManaCostsToPay().getX()) { + permanent.destroy(source.getSourceId(), game, false); + } + } + return true; + } +} From 123e8c408806d37be7e0222bc94f2e971f1bf3e9 Mon Sep 17 00:00:00 2001 From: myersn024 Date: Tue, 3 Mar 2015 14:51:16 -0600 Subject: [PATCH 4/5] Delete TinyLeaders.java --- .../src/mage/deck/TinyLeaders.java | 190 ------------------ 1 file changed, 190 deletions(-) delete mode 100644 Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/TinyLeaders.java diff --git a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/TinyLeaders.java b/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/TinyLeaders.java deleted file mode 100644 index 88c458dfc8..0000000000 --- a/Mage.Server.Plugins/Mage.Deck.Constructed/src/mage/deck/TinyLeaders.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ -package mage.deck; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import mage.cards.Card; -import mage.cards.decks.Deck; -import mage.cards.decks.DeckValidator; -import mage.constants.CardType; -import mage.filter.FilterMana; -import mage.util.CardUtil; - -/** - * - * @author nickmyers - */ -public class TinyLeaders extends DeckValidator { - - protected List banned = new ArrayList<>(); - protected List bannedCommander = new ArrayList<>(); - - public TinyLeaders(String name) { - super(name); - } - - public TinyLeaders() { - this("Tiny Leaders"); - banned.add("Ancestral Recall"); - banned.add("Black Lotus"); - banned.add("Black Vise"); - banned.add("Channel"); - banned.add("Counterbalance"); - banned.add("Demonic Tutor"); - banned.add("Earthcraft"); - banned.add("Edric, Spymaster of Trest"); - banned.add("Fastbond"); - banned.add("Goblin Recruiter"); - banned.add("Hermit Druid"); - banned.add("Imperial Seal"); - banned.add("Library of Alexandria"); - banned.add("Karakas"); - banned.add("Mana Crypt"); - banned.add("Mana Drain"); - banned.add("Mana Vault"); - banned.add("Metalworker"); - banned.add("Mind Twist"); - banned.add("Mishra's Workshop"); - banned.add("Mox Emerald"); - banned.add("Mox Jet"); - banned.add("Mox Pearl"); - banned.add("Mox Ruby"); - banned.add("Mox Sapphire"); - banned.add("Necropotence"); - banned.add("Painter's Servant"); - banned.add("Shahrazad"); - banned.add("Skullclamp"); - banned.add("Sol Ring"); - banned.add("Strip Mine"); - banned.add("Survival of the Fittest"); - banned.add("Sword of Body and Mind"); - banned.add("Time Vault"); - banned.add("Time Walk"); - banned.add("Timetwister"); - banned.add("Tolarian Academy"); - banned.add("Umezawa's Jitte"); - banned.add("Vampiric Tutor"); - banned.add("Wheel of Fortune"); - banned.add("Yawgmoth's Will"); - - bannedCommander.add("Erayo, Soratami Ascendant"); - bannedCommander.add("Rofellos, Llanowar Emissary"); - bannedCommander.add("Derevi, Empyrical Tactician"); - - } - - @Override - public boolean validate(Deck deck) { - boolean valid = true; - - // Check CMC <= 3 of main deck - for(Card card : deck.getCards()) { - if(card.getManaCost().convertedManaCost() > 3) { - invalid.put("Mana Cost", "Converted Mana Cost of " + card.getName() + " is too high"); - valid = false; - } - } - - // Check CMC <=3 for sideboard - for(Card card : deck.getSideboard()) { - if(card.getManaCost().convertedManaCost() > 3) { - invalid.put("Commander Mana Cost", "Converted Mana Cost of " + card.getName() + " is too high"); - } - } - - // make sure main deck and sideboard have the appropriate number of cards - if (deck.getCards().size() != 50) { - invalid.put("Deck", "Main deck must contain 50 cards including your commander: has " + deck.getCards().size() + " cards"); - valid = false; - } - - if (deck.getSideboard().size() != 10) { - invalid.put("Sideboard", "Sideboard must contain 10 cards: has " + deck.getSideboard().size() + " cards"); - valid = false; - } - - List basicLandNames = new ArrayList<>(Arrays.asList("Forest", "Island", "Mountain", "Swamp", "Plains", - "Snow-Covered Forest", "Snow-Covered Island", "Snow-Covered Mountain", "Snow-Covered Swamp", "Snow-Covered Plains")); - Map counts = new HashMap<>(); - countCards(counts, deck.getCards()); - countCards(counts, deck.getSideboard()); - for (Map.Entry entry : counts.entrySet()) { - if (entry.getValue() > 1) { - if (!basicLandNames.contains(entry.getKey()) && !entry.getKey().equals("Relentless Rats") && !entry.getKey().equals("Shadowborn Apostle")) { - invalid.put(entry.getKey(), "Too many: " + entry.getValue()); - valid = false; - } - } - } - - for (String bannedCard : banned) { - if (counts.containsKey(bannedCard)) { - invalid.put(bannedCard, "Banned"); - valid = false; - } - } - - // find commander in the main board - Card commander = null; - for (Card card : deck.getCards()) { - if(card.getName().equals(deck.getName())) { - commander = card.copy(); - } - } - if(commander != null) { - // verify legendary creature - if (commander.getCardType().contains(CardType.CREATURE) && commander.getSupertype().contains("Legendary")) { - // verify commander against banned list - if(!bannedCommander.contains(commander.getName())) { - // verify deck colors - FilterMana color = CardUtil.getColorIdentity(commander); - for (Card card : deck.getCards()) { - if (!cardHasValidColor(color, card)) { - invalid.put(card.getName(), "Invalid color (" + commander.getName() +")"); - valid = false; - } - } - - // verify sideboard colors - for (Card card : deck.getSideboard()) { - if (!cardHasValidColor(color,card)) { - invalid.put(card.getName(), "Invalid color (" + commander.getName() +")"); - valid = false; - } - } - - } else { - invalid.put("Commander", "Commander banned (" + commander.getName() + ")"); - valid = false; - } - } else { - invalid.put("Commander", "Commander invalid (" + commander.getName() + ")"); - valid = false; - } - } else { - invalid.put("Commander", deck.getName() + " not found in main board"); - valid = false; - } - return valid; - } - - public boolean cardHasValidColor(FilterMana commander, Card card) { - FilterMana cardColor = CardUtil.getColorIdentity(card); - if (cardColor.isBlack() && !commander.isBlack() - || cardColor.isBlue() && !commander.isBlue() - || cardColor.isGreen() && !commander.isGreen() - || cardColor.isRed() && !commander.isRed() - || cardColor.isWhite() && !commander.isWhite()) { - return false; - } - return true; - } - -} From 6586f6fa85173f3928fd3178a91f62280e78afca Mon Sep 17 00:00:00 2001 From: nickmyers Date: Tue, 3 Mar 2015 18:02:05 -0600 Subject: [PATCH 5/5] Fixed small issue in ForcedMarch.java --- Mage.Sets/src/mage/sets/mercadianmasques/ForcedMarch.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Mage.Sets/src/mage/sets/mercadianmasques/ForcedMarch.java b/Mage.Sets/src/mage/sets/mercadianmasques/ForcedMarch.java index b4bda57d62..087e7e7b52 100644 --- a/Mage.Sets/src/mage/sets/mercadianmasques/ForcedMarch.java +++ b/Mage.Sets/src/mage/sets/mercadianmasques/ForcedMarch.java @@ -17,6 +17,7 @@ import mage.constants.Rarity; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.constants.Outcome; +import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; @@ -58,7 +59,12 @@ class ForcedMarchEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - for(Permanent permanent : game.getBattlefield().getAllActivePermanents(CardType.CREATURE)) { + + // for(Permanent permanent : game.getBattlefield().getAllActivePermanents(CardType.CREATURE)) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterCreaturePermanent(), + source.getControllerId(), + source.getSourceId(), + game)) { if (permanent.getManaCost().convertedManaCost() <= source.getManaCostsToPay().getX()) { permanent.destroy(source.getSourceId(), game, false); }