diff --git a/Mage.Sets/src/mage/sets/alarareborn/MaelstromPulse.java b/Mage.Sets/src/mage/sets/alarareborn/MaelstromPulse.java index 98fb8485438..3dffdd6e389 100644 --- a/Mage.Sets/src/mage/sets/alarareborn/MaelstromPulse.java +++ b/Mage.Sets/src/mage/sets/alarareborn/MaelstromPulse.java @@ -46,6 +46,7 @@ public class MaelstromPulse extends CardImpl { this.expansionSetCode = "ARB"; + // Destroy target nonland permanent and all other permanents with the same name as that permanent. this.getSpellAbility().addTarget(new TargetNonlandPermanent()); this.getSpellAbility().addEffect(new DestroyAllNamedPermanentsEffect()); } diff --git a/Mage.Sets/src/mage/sets/bornofthegods/BileBlight.java b/Mage.Sets/src/mage/sets/bornofthegods/BileBlight.java index fb93f00de09..88ebf9350e8 100644 --- a/Mage.Sets/src/mage/sets/bornofthegods/BileBlight.java +++ b/Mage.Sets/src/mage/sets/bornofthegods/BileBlight.java @@ -79,16 +79,18 @@ class BileBlightEffect extends BoostAllEffect { @Override public void init(Ability source, Game game) { super.init(source, game); - if (this.affectedObjectsSet) { this.objects.clear(); - UUID permanentId = targetPointer.getFirst(game, source); - Permanent target = game.getPermanent(permanentId); + Permanent target = game.getPermanent(getTargetPointer().getFirst(game, source)); if (target != null) { - String name = target.getName(); - for (Permanent perm : game.getBattlefield().getActivePermanents(source.getControllerId(), game)) { - if (perm.getName().equals(name)) { - this.objects.add(perm.getId()); + if (target.getName().isEmpty()) { // face down creature + this.objects.add(target.getId()); + } else { + String name = target.getLogName(); + for (Permanent perm : game.getBattlefield().getActivePermanents(source.getControllerId(), game)) { + if (perm.getLogName().equals(name)) { + this.objects.add(perm.getId()); + } } } } diff --git a/Mage.Sets/src/mage/sets/darksteel/EchoingCalm.java b/Mage.Sets/src/mage/sets/darksteel/EchoingCalm.java index a6d643faf25..4a2f9e5e0af 100644 --- a/Mage.Sets/src/mage/sets/darksteel/EchoingCalm.java +++ b/Mage.Sets/src/mage/sets/darksteel/EchoingCalm.java @@ -28,17 +28,17 @@ package mage.sets.darksteel; import java.util.UUID; - -import mage.constants.CardType; -import mage.constants.Rarity; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; +import mage.constants.CardType; import mage.constants.Outcome; +import mage.constants.Rarity; import mage.filter.FilterPermanent; import mage.filter.predicate.mageobject.CardTypePredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.players.Player; import mage.target.TargetPermanent; /** @@ -57,6 +57,7 @@ public class EchoingCalm extends CardImpl { this.color.setWhite(true); + // Destroy target enchantment and all other enchantments with the same name as that enchantment. this.getSpellAbility().addTarget(new TargetPermanent(filter)); this.getSpellAbility().addEffect(new EchoingCalmEffect()); } @@ -88,15 +89,19 @@ class EchoingCalmEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getFirstTarget()); - String name = permanent.getName(); - - permanent.destroy(source.getSourceId(), game, false); - for (Permanent perm : game.getBattlefield().getActivePermanents(source.getControllerId(), game)) { - if (perm.getName().equals(name) && perm.getCardType().contains(CardType.ENCHANTMENT)) - perm.destroy(source.getSourceId(), game, false); + Player controller = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (controller != null && permanent != null) { + permanent.destroy(source.getSourceId(), game, false); + if (!permanent.getName().isEmpty()) { // in case of face down enchantment creature + for (Permanent perm : game.getBattlefield().getActivePermanents(source.getControllerId(), game)) { + if (!perm.getId().equals(permanent.getId()) && perm.getName().equals(permanent.getName()) && perm.getCardType().contains(CardType.ENCHANTMENT)) { + perm.destroy(source.getSourceId(), game, false); + } + } + } + return true; } - - return true; + return false; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/sets/darksteel/EchoingDecay.java b/Mage.Sets/src/mage/sets/darksteel/EchoingDecay.java index 3fcbaa75660..cf9a214f2e2 100644 --- a/Mage.Sets/src/mage/sets/darksteel/EchoingDecay.java +++ b/Mage.Sets/src/mage/sets/darksteel/EchoingDecay.java @@ -38,7 +38,9 @@ import mage.constants.Duration; import mage.constants.Outcome; import mage.constants.Rarity; import mage.filter.common.FilterCreaturePermanent; +import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.NamePredicate; +import mage.filter.predicate.permanent.PermanentIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; @@ -53,8 +55,6 @@ public class EchoingDecay extends CardImpl { super(ownerId, 41, "Echoing Decay", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{1}{B}"); this.expansionSetCode = "DST"; - this.color.setBlack(true); - // Target creature and all other creatures with the same name as that creature get -2/-2 until end of turn. this.getSpellAbility().addEffect(new EchoingDecayEffect()); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); @@ -91,7 +91,11 @@ class EchoingDecayEffect extends OneShotEffect { Permanent targetPermanent = game.getPermanent(targetPointer.getFirst(game, source)); if (targetPermanent != null) { FilterCreaturePermanent filter = new FilterCreaturePermanent(); - filter.add(new NamePredicate(targetPermanent.getName())); + if (targetPermanent.getName().isEmpty()) { + filter.add(new PermanentIdPredicate(targetPermanent.getId())); // if no name (face down creature) only the creature itself is selected + } else { + filter.add(new NamePredicate(targetPermanent.getName())); + } ContinuousEffect effect = new BoostAllEffect(-2,-2, Duration.EndOfTurn, filter, false); game.addEffect(effect, source); return true; diff --git a/Mage.Sets/src/mage/sets/elspethvstezzeret/EchoingTruth.java b/Mage.Sets/src/mage/sets/elspethvstezzeret/EchoingTruth.java index 4f3d7719bc4..9ce94a08f01 100644 --- a/Mage.Sets/src/mage/sets/elspethvstezzeret/EchoingTruth.java +++ b/Mage.Sets/src/mage/sets/elspethvstezzeret/EchoingTruth.java @@ -37,9 +37,12 @@ import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; import mage.filter.FilterPermanent; +import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.NamePredicate; +import mage.filter.predicate.permanent.PermanentIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.players.Player; import mage.target.Target; import mage.target.common.TargetNonlandPermanent; @@ -53,8 +56,6 @@ public class EchoingTruth extends CardImpl { super(ownerId, 66, "Echoing Truth", Rarity.COMMON, new CardType[]{CardType.INSTANT}, "{1}{U}"); this.expansionSetCode = "DDF"; - this.color.setBlue(true); - // Return target nonland permanent and all other permanents with the same name as that permanent to their owners' hands. Target target = new TargetNonlandPermanent(); this.getSpellAbility().addTarget(target); @@ -88,13 +89,19 @@ class ReturnToHandAllNamedPermanentsEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); Permanent permanent = game.getPermanent(source.getFirstTarget()); - if (permanent != null) { + if (controller != null && permanent != null) { FilterPermanent filter = new FilterPermanent(); - filter.add(new NamePredicate(permanent.getName())); - for (Permanent perm: game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game)) { - perm.moveToZone(Zone.HAND, source.getSourceId(), game, false); + if (permanent.getName().isEmpty()) { + filter.add(new PermanentIdPredicate(permanent.getId())); // if no name (face down creature) only the creature itself is selected + } else { + filter.add(new NamePredicate(permanent.getLogName())); } + for (Permanent perm: game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game)) { + controller.moveCardToHandWithInfo(perm, source.getSourceId(), game, Zone.BATTLEFIELD); + } + return true; } return true; } diff --git a/Mage.Sets/src/mage/sets/gatecrash/HomingLightning.java b/Mage.Sets/src/mage/sets/gatecrash/HomingLightning.java index 419eb75844c..f3eb69a4d35 100644 --- a/Mage.Sets/src/mage/sets/gatecrash/HomingLightning.java +++ b/Mage.Sets/src/mage/sets/gatecrash/HomingLightning.java @@ -27,7 +27,6 @@ */ package mage.sets.gatecrash; -import java.util.List; import java.util.UUID; import mage.constants.CardType; @@ -38,6 +37,7 @@ import mage.cards.CardImpl; import mage.constants.Outcome; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.NamePredicate; +import mage.filter.predicate.permanent.PermanentIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; @@ -82,22 +82,22 @@ class HomingLightningEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent target = game.getPermanent(source.getFirstTarget()); - if (target == null) { + Permanent targetPermanent = game.getPermanent(source.getFirstTarget()); + if (targetPermanent == null) { return false; } FilterCreaturePermanent filter = new FilterCreaturePermanent(); - filter.add(new NamePredicate(target.getName())); - List creatures = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game); - if (target != null) { - for (Permanent creature : creatures) { - if (creature != null) { - creature.damage(4, id, game, false, true); - } - } - return true; + if (targetPermanent.getName().isEmpty()) { + filter.add(new PermanentIdPredicate(targetPermanent.getId())); // if no name (face down creature) only the creature itself is selected + } else { + filter.add(new NamePredicate(targetPermanent.getName())); } - return false; + for (Permanent creature : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game)) { + if (creature != null) { + creature.damage(4, source.getSourceId(), game, false, true); + } + } + return true; } @Override diff --git a/Mage.Sets/src/mage/sets/innistrad/EvilTwin.java b/Mage.Sets/src/mage/sets/innistrad/EvilTwin.java index de5aac94ab7..29eff084172 100644 --- a/Mage.Sets/src/mage/sets/innistrad/EvilTwin.java +++ b/Mage.Sets/src/mage/sets/innistrad/EvilTwin.java @@ -88,9 +88,11 @@ public class EvilTwin extends CardImpl { class EvilTwinApplyToPermanent extends ApplyToPermanent { private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("creature with the same name as this creature"); + static { filter.add(new EvilTwinPredicate()); } + @Override public Boolean apply(Game game, Permanent permanent) { Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new ManaCostsImpl("{U}{B}")); @@ -107,8 +109,7 @@ class EvilTwinPredicate implements ObjectSourcePlayerPredicate input, Game game) { Permanent permanent = input.getObject(); Permanent twin = game.getPermanent(input.getSourceId()); - - return permanent != null && twin != null && permanent.getName().equals(twin.getName()); + return permanent != null && twin != null && !twin.getName().isEmpty() && permanent.getName().equals(twin.getName()); } @Override diff --git a/Mage.Sets/src/mage/sets/innistrad/SeverTheBloodline.java b/Mage.Sets/src/mage/sets/innistrad/SeverTheBloodline.java index d35cf369c38..dfb03845e30 100644 --- a/Mage.Sets/src/mage/sets/innistrad/SeverTheBloodline.java +++ b/Mage.Sets/src/mage/sets/innistrad/SeverTheBloodline.java @@ -27,7 +27,6 @@ */ package mage.sets.innistrad; -import java.util.List; import java.util.UUID; import mage.constants.CardType; import mage.constants.Outcome; @@ -38,10 +37,13 @@ import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.FlashbackAbility; import mage.cards.CardImpl; +import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.NamePredicate; +import mage.filter.predicate.permanent.PermanentIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; +import mage.players.Player; import mage.target.common.TargetCreaturePermanent; /** @@ -91,13 +93,17 @@ class SeverTheBloodlineEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); Permanent targetPermanent = game.getPermanent(targetPointer.getFirst(game, source)); - if (targetPermanent != null) { + if (controller != null && targetPermanent != null) { FilterCreaturePermanent filter = new FilterCreaturePermanent(); - filter.add(new NamePredicate(targetPermanent.getName())); - List permanents = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game); - for (Permanent permanent : permanents) { - permanent.moveToExile(null, "", source.getSourceId(), game); + if (targetPermanent.getName().isEmpty()) { + filter.add(new PermanentIdPredicate(targetPermanent.getId())); // if no name (face down creature) only the creature itself is selected + } else { + filter.add(new NamePredicate(targetPermanent.getName())); + } + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { + controller.moveCardToExileWithInfo(permanent, null, "", source.getSourceId(), game, Zone.BATTLEFIELD); } return true; } diff --git a/Mage.Sets/src/mage/sets/modernmasters/EchoingCourage.java b/Mage.Sets/src/mage/sets/modernmasters/EchoingCourage.java index c62ba9df7bd..e8a3e024779 100644 --- a/Mage.Sets/src/mage/sets/modernmasters/EchoingCourage.java +++ b/Mage.Sets/src/mage/sets/modernmasters/EchoingCourage.java @@ -39,6 +39,7 @@ import mage.constants.Outcome; import mage.constants.Rarity; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.NamePredicate; +import mage.filter.predicate.permanent.PermanentIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; @@ -91,7 +92,11 @@ class EchoingCourageEffect extends OneShotEffect { Permanent targetPermanent = game.getPermanent(targetPointer.getFirst(game, source)); if (targetPermanent != null) { FilterCreaturePermanent filter = new FilterCreaturePermanent(); - filter.add(new NamePredicate(targetPermanent.getName())); + if (targetPermanent.getName().isEmpty()) { + filter.add(new PermanentIdPredicate(targetPermanent.getId())); // if no name (face down creature) only the creature itself is selected + } else { + filter.add(new NamePredicate(targetPermanent.getLogName())); + } ContinuousEffect effect = new BoostAllEffect(2,2, Duration.EndOfTurn, filter, false); game.addEffect(effect, source); return true; diff --git a/Mage.Sets/src/mage/sets/newphyrexia/ExclusionRitual.java b/Mage.Sets/src/mage/sets/newphyrexia/ExclusionRitual.java index 7502e352aaa..eb2dd899ac1 100644 --- a/Mage.Sets/src/mage/sets/newphyrexia/ExclusionRitual.java +++ b/Mage.Sets/src/mage/sets/newphyrexia/ExclusionRitual.java @@ -35,7 +35,6 @@ import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.ContinuousRuleModifiyingEffectImpl; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.ReplacementEffectImpl; import mage.cards.Card; import mage.cards.CardImpl; import mage.filter.FilterPermanent; @@ -44,6 +43,7 @@ import mage.filter.predicate.mageobject.CardTypePredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; +import mage.players.Player; import mage.target.TargetPermanent; /** @@ -94,8 +94,9 @@ class ExclusionRitualImprintEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Permanent sourcePermanent = game.getPermanent(source.getSourceId()); Permanent targetPermanent = game.getPermanent(targetPointer.getFirst(game, source)); - if (sourcePermanent != null && targetPermanent != null) { - targetPermanent.moveToExile(getId(), sourcePermanent.getLogName() + " (Imprint)", source.getSourceId(), game); + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null && sourcePermanent != null && targetPermanent != null) { + controller.moveCardToExileWithInfo(targetPermanent, getId(), sourcePermanent.getLogName(), source.getSourceId(), game, Zone.BATTLEFIELD); sourcePermanent.imprint(targetPermanent.getId(), game); } return true; diff --git a/Mage.Sets/src/mage/sets/returntoravnica/DetentionSphere.java b/Mage.Sets/src/mage/sets/returntoravnica/DetentionSphere.java index 1b11e557d69..811d8f4292c 100644 --- a/Mage.Sets/src/mage/sets/returntoravnica/DetentionSphere.java +++ b/Mage.Sets/src/mage/sets/returntoravnica/DetentionSphere.java @@ -28,6 +28,7 @@ package mage.sets.returntoravnica; import java.util.UUID; +import mage.MageObject; import mage.constants.CardType; import mage.constants.Outcome; @@ -109,11 +110,17 @@ class DetentionSphereEntersEffect extends OneShotEffect { UUID exileId = source.getSourceId(); Permanent targetPermanent = game.getPermanent(getTargetPointer().getFirst(game, source)); Player controller = game.getPlayer(source.getControllerId()); - if (exileId != null && targetPermanent != null && controller != null) { - String name = targetPermanent.getName(); - for (Permanent permanent : game.getBattlefield().getActivePermanents(source.getControllerId(), game)) { - if (permanent != null && permanent.getName().equals(name)) { - controller.moveCardToExileWithInfo(permanent, exileId, "Detention Sphere", source.getSourceId(), game, Zone.BATTLEFIELD); + MageObject sourceObject = game.getObject(source.getSourceId()); + if (sourceObject != null && exileId != null && targetPermanent != null && controller != null) { + + if (targetPermanent.getName().isEmpty()) { // face down creature + controller.moveCardToExileWithInfo(targetPermanent, exileId, sourceObject.getLogName(), source.getSourceId(), game, Zone.BATTLEFIELD); + } else { + String name = targetPermanent.getLogName(); + for (Permanent permanent : game.getBattlefield().getActivePermanents(source.getControllerId(), game)) { + if (permanent != null && permanent.getLogName().equals(name)) { + controller.moveCardToExileWithInfo(permanent, exileId, sourceObject.getLogName(), source.getSourceId(), game, Zone.BATTLEFIELD); + } } } return true; diff --git a/Mage.Sets/src/mage/sets/returntoravnica/IzzetStaticaster.java b/Mage.Sets/src/mage/sets/returntoravnica/IzzetStaticaster.java index b6313f109fc..7c1dd241c34 100644 --- a/Mage.Sets/src/mage/sets/returntoravnica/IzzetStaticaster.java +++ b/Mage.Sets/src/mage/sets/returntoravnica/IzzetStaticaster.java @@ -44,6 +44,7 @@ import mage.constants.Outcome; import mage.constants.Zone; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.NamePredicate; +import mage.filter.predicate.permanent.PermanentIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.target.common.TargetCreaturePermanent; @@ -107,13 +108,16 @@ class IzzetStaticasterDamageEffect extends OneShotEffect { Permanent targetPermanent = game.getPermanent(targetPointer.getFirst(game, source)); if (targetPermanent != null) { FilterCreaturePermanent filter = new FilterCreaturePermanent(); - filter.add(new NamePredicate(targetPermanent.getName())); - List permanents = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game); - for (Permanent permanent : permanents) { + if (targetPermanent.getName().isEmpty()) { + filter.add(new PermanentIdPredicate(targetPermanent.getId())); // if no name (face down creature) only the creature itself is selected + } else { + filter.add(new NamePredicate(targetPermanent.getName())); + } + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game)) { permanent.damage(1, source.getSourceId(), game, false, true); } return true; } return false; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/sets/riseoftheeldrazi/RealmsUncharted.java b/Mage.Sets/src/mage/sets/riseoftheeldrazi/RealmsUncharted.java index e7c37e0de2b..3e9387e7756 100644 --- a/Mage.Sets/src/mage/sets/riseoftheeldrazi/RealmsUncharted.java +++ b/Mage.Sets/src/mage/sets/riseoftheeldrazi/RealmsUncharted.java @@ -28,7 +28,9 @@ package mage.sets.riseoftheeldrazi; import java.util.List; +import java.util.Set; import java.util.UUID; +import mage.MageObject; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Rarity; @@ -43,8 +45,10 @@ import mage.filter.FilterCard; import mage.filter.common.FilterLandCard; import mage.game.Game; import mage.players.Player; +import mage.target.Target; import mage.target.TargetCard; import mage.target.common.TargetCardInLibrary; +import mage.target.common.TargetOpponent; /** * @@ -56,8 +60,6 @@ public class RealmsUncharted extends CardImpl { super(ownerId, 206, "Realms Uncharted", Rarity.RARE, new CardType[]{CardType.INSTANT}, "{2}{G}"); this.expansionSetCode = "ROE"; - this.color.setGreen(true); - // Search your library for four land cards with different names and reveal them. An opponent chooses two of those cards. Put the chosen cards into your graveyard and the rest into your hand. Then shuffle your library. this.getSpellAbility().addEffect(new RealmsUnchartedEffect()); } @@ -90,29 +92,38 @@ class RealmsUnchartedEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player == null) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = game.getObject(source.getSourceId()); + if (controller == null || sourceObject == null) { return false; } RealmsUnchartedTarget target = new RealmsUnchartedTarget(); - if (player.searchLibrary(target, game)) { + if (controller.searchLibrary(target, game)) { if (target.getTargets().size() > 0) { Cards cards = new CardsImpl(); for (UUID cardId : (List) target.getTargets()) { - Card card = player.getLibrary().remove(cardId, game); + Card card = controller.getLibrary().getCard(cardId, game); if (card != null) { cards.add(card); } } - player.revealCards("Realms Uncharted", cards, game); + controller.revealCards(sourceObject.getLogName(), cards, game); CardsImpl cardsToKeep = new CardsImpl(); if (cards.size() > 2) { cardsToKeep.addAll(cards); - Player opponent = game.getPlayer(game.getOpponents(player.getId()).iterator().next()); - TargetCard targetDiscard = new TargetCard(2, Zone.PICK, new FilterCard("cards to put in graveyard")); + Player opponent; + Set opponents = game.getOpponents(controller.getId()); + if (opponents.size() == 1) { + opponent = game.getPlayer(opponents.iterator().next()); + } else { + Target targetOpponent = new TargetOpponent(true); + controller.chooseTarget(Outcome.Detriment, targetOpponent, source, game); + opponent = game.getPlayer(targetOpponent.getFirstTarget()); + } + TargetCard targetDiscard = new TargetCard(2, Zone.LIBRARY, new FilterCard("cards to put in graveyard")); if (opponent != null && opponent.choose(Outcome.Discard, cards, targetDiscard, game)) { cardsToKeep.removeAll(targetDiscard.getTargets()); cards.removeAll(cardsToKeep); @@ -122,20 +133,20 @@ class RealmsUnchartedEffect extends OneShotEffect { for (UUID cardId : cards) { Card card = game.getCard(cardId); if (card != null) { - card.moveToZone(Zone.GRAVEYARD, source.getSourceId(), game, true); + controller.moveCardToGraveyardWithInfo(card, source.getSourceId(), game, Zone.LIBRARY); } } for (UUID cardId : cardsToKeep) { Card card = game.getCard(cardId); if (card != null) { - card.moveToZone(Zone.HAND, source.getSourceId(), game, true); + controller.moveCardToHandWithInfo(card, source.getSourceId(), game, Zone.LIBRARY); } } } - player.shuffleLibrary(game); + controller.shuffleLibrary(game); return true; } - player.shuffleLibrary(game); + controller.shuffleLibrary(game); return false; } } diff --git a/Mage.Sets/src/mage/sets/theros/SteamAugury.java b/Mage.Sets/src/mage/sets/theros/SteamAugury.java index c8bfcb406f2..8345e09289e 100644 --- a/Mage.Sets/src/mage/sets/theros/SteamAugury.java +++ b/Mage.Sets/src/mage/sets/theros/SteamAugury.java @@ -31,6 +31,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.UUID; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.cards.Card; @@ -44,6 +45,7 @@ import mage.constants.Zone; import mage.filter.FilterCard; import mage.game.Game; import mage.players.Player; +import mage.target.Target; import mage.target.TargetCard; import mage.target.common.TargetOpponent; @@ -94,28 +96,32 @@ class SteamAuguryEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player == null) { + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = game.getObject(source.getSourceId()); + if (controller == null || sourceObject == null) { return false; } - Cards cards = new CardsImpl(Zone.PICK); - int count = Math.min(player.getLibrary().size(), 5); - for (int i = 0; i < count; i++) { - Card card = player.getLibrary().removeFromTop(game); - if (card != null) { - cards.add(card); - game.setZone(card.getId(), Zone.PICK); - } + Cards cards = new CardsImpl(); + cards.addAll(controller.getLibrary().getTopCards(game, 5)); + controller.revealCards(sourceObject.getLogName(), cards, game); + + Player opponent; + Set opponents = game.getOpponents(controller.getId()); + if (opponents.size() == 1) { + opponent = game.getPlayer(opponents.iterator().next()); + } else { + Target target = new TargetOpponent(true); + controller.chooseTarget(Outcome.Detriment, target, source, game); + opponent = game.getPlayer(target.getFirstTarget()); } - player.revealCards("Steam Augury", cards, game); - Player opponent = game.getPlayer(this.getTargetPointer().getFirst(game, source)); + if (opponent != null) { TargetCard target = new TargetCard(0, cards.size(), Zone.PICK, new FilterCard("cards to put in the first pile")); List pile1 = new ArrayList<>(); Cards pile1CardsIds = new CardsImpl(); target.setRequired(false); - if (player.choose(Outcome.Neutral, cards, target, game)) { + if (controller.choose(Outcome.Neutral, cards, target, game)) { List targets = target.getTargets(); for (UUID targetId : targets) { Card card = game.getCard(targetId); @@ -134,7 +140,7 @@ class SteamAuguryEffect extends OneShotEffect { pile2CardsIds.add(card.getId()); } } - boolean choice = opponent.choosePile(Outcome.Detriment, new StringBuilder("Choose a pile to put into ").append(player.getName()).append("'s hand.").toString(), pile1, pile2, game); + boolean choice = opponent.choosePile(Outcome.Detriment, new StringBuilder("Choose a pile to put into ").append(controller.getName()).append("'s hand.").toString(), pile1, pile2, game); Zone pile1Zone = Zone.GRAVEYARD; Zone pile2Zone = Zone.HAND; @@ -143,7 +149,7 @@ class SteamAuguryEffect extends OneShotEffect { pile2Zone = Zone.GRAVEYARD; } - StringBuilder sb = new StringBuilder("Steam Augury: Pile 1, going to ").append(pile1Zone.equals(Zone.HAND)?"Hand":"Graveyard").append (": "); + StringBuilder sb = new StringBuilder(sourceObject.getLogName() + ": Pile 1, going to ").append(pile1Zone.equals(Zone.HAND)?"Hand":"Graveyard").append (": "); int i = 0; for (UUID cardUuid : pile1CardsIds) { i++; @@ -158,7 +164,7 @@ class SteamAuguryEffect extends OneShotEffect { } game.informPlayers(sb.toString()); - sb = new StringBuilder("Steam Augury: Pile 2, going to ").append(pile2Zone.equals(Zone.HAND)?"Hand":"Graveyard").append (":"); + sb = new StringBuilder(sourceObject.getLogName() + ": Pile 2, going to ").append(pile2Zone.equals(Zone.HAND)?"Hand":"Graveyard").append (":"); i = 0; for (UUID cardUuid : pile2CardsIds) { Card card = game.getCard(cardUuid); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MorphTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MorphTest.java index 20a848a6e40..49be4000767 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MorphTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MorphTest.java @@ -359,4 +359,43 @@ public class MorphTest extends CardTestPlayerBase { assertPermanentCount(playerA, "face down creature", 1); } + + /** + * Check that an effect like "arget creature and all other creatures with the same name" does + * only effect one face down creature, also if multiple on the battlefield. Because they have no + * name, they don't have the same name. + * + */ + @Test + public void testEchoingDecaySameNameEffect() { + // Sagu Mauler 6/6 - Creature - Beast + // Trample, hexproof + // Morph {3}{G}{B} (You may cast this card face down as a 2/2 creature for . Turn it face up any time for its morph cost.) + addCard(Zone.HAND, playerA, "Sagu Mauler", 2); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 6); + + // Echoing Decay {1}{B} + // Instant + // Target creature and all other creatures with the same name as that creature get -2/-2 until end of turn. + addCard(Zone.HAND, playerB, "Echoing Decay"); + addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sagu Mauler"); + setChoice(playerA, "Yes"); // cast it face down as 2/2 creature + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sagu Mauler"); + setChoice(playerA, "Yes"); // cast it face down as 2/2 creature + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Echoing Decay", "face down creature"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertLife(playerB, 20); + + assertHandCount(playerA, "Sagu Mauler", 0); + assertHandCount(playerB, "Echoing Decay", 0); + + assertPermanentCount(playerA, "face down creature", 1); + + } } diff --git a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java index 887a889602a..60306d0d756 100644 --- a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java +++ b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java @@ -592,7 +592,7 @@ public class TestPlayer extends ComputerPlayer { } for (UUID id: ability.getTargets().get(0).possibleTargets(ability.getSourceId(), ability.getControllerId(), game)) { MageObject object = game.getObject(id); - if (object != null && object.getName().equals(targetName)) { + if (object != null && object.getLogName().equals(targetName)) { if (index >= ability.getTargets().size()) { index--; } diff --git a/Mage/src/mage/abilities/effects/common/DestroyAllNamedPermanentsEffect.java b/Mage/src/mage/abilities/effects/common/DestroyAllNamedPermanentsEffect.java index 78369fcb027..30e3c36301f 100644 --- a/Mage/src/mage/abilities/effects/common/DestroyAllNamedPermanentsEffect.java +++ b/Mage/src/mage/abilities/effects/common/DestroyAllNamedPermanentsEffect.java @@ -28,10 +28,13 @@ package mage.abilities.effects.common; -import mage.constants.Outcome; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.effects.OneShotEffect; +import mage.constants.Outcome; +import mage.filter.FilterPermanent; +import mage.filter.predicate.mageobject.NamePredicate; +import mage.filter.predicate.permanent.PermanentIdPredicate; import mage.game.Game; import mage.game.permanent.Permanent; @@ -56,16 +59,19 @@ public class DestroyAllNamedPermanentsEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getFirstTarget()); - String name = permanent.getName(); - - permanent.destroy(source.getSourceId(), game, false); - for (Permanent perm: game.getBattlefield().getActivePermanents(source.getControllerId(), game)) { - if (perm.getName().equals(name)) { - perm.destroy(source.getSourceId(), game, false); - } + Permanent targetPermanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (targetPermanent == null) { + return false; + } + FilterPermanent filter = new FilterPermanent(); + if (targetPermanent.getName().isEmpty()) { + filter.add(new PermanentIdPredicate(targetPermanent.getId())); // if no name (face down creature) only the creature itself is selected + } else { + filter.add(new NamePredicate(targetPermanent.getName())); + } + for (Permanent perm: game.getBattlefield().getActivePermanents(filter, source.getControllerId(), game)) { + perm.destroy(source.getSourceId(), game, false); } - return true; } diff --git a/Mage/src/mage/filter/predicate/mageobject/NamePredicate.java b/Mage/src/mage/filter/predicate/mageobject/NamePredicate.java index c3882d9b900..24123ab8e1f 100644 --- a/Mage/src/mage/filter/predicate/mageobject/NamePredicate.java +++ b/Mage/src/mage/filter/predicate/mageobject/NamePredicate.java @@ -27,9 +27,9 @@ */ package mage.filter.predicate.mageobject; -import mage.constants.SpellAbilityType; import mage.MageObject; import mage.cards.SplitCard; +import mage.constants.SpellAbilityType; import mage.filter.predicate.Predicate; import mage.game.Game; import mage.game.stack.Spell; @@ -51,12 +51,12 @@ public class NamePredicate implements Predicate { // If a player names a card, the player may name either half of a split card, but not both. // A split card has the chosen name if one of its two names matches the chosen name. if (input instanceof SplitCard) { - return name.equals(((SplitCard)input).getLeftHalfCard().getLogName()) || name.equals(((SplitCard)input).getRightHalfCard().getLogName()); + return name.equals(((SplitCard)input).getLeftHalfCard().getName()) || name.equals(((SplitCard)input).getRightHalfCard().getLogName()); } else if (input instanceof Spell && ((Spell)input).getSpellAbility().getSpellAbilityType().equals(SpellAbilityType.SPLIT_FUSED)){ SplitCard card = (SplitCard) ((Spell)input).getCard(); - return name.equals(card.getLeftHalfCard().getLogName()) || name.equals(card.getRightHalfCard().getLogName()); + return name.equals(card.getLeftHalfCard().getName()) || name.equals(card.getRightHalfCard().getLogName()); } else { - return name.equals(input.getLogName()); + return name.equals(input.getName()); } } diff --git a/Mage/src/mage/util/trace/TraceUtil.java b/Mage/src/mage/util/trace/TraceUtil.java index 241354b567b..acd2d91db77 100644 --- a/Mage/src/mage/util/trace/TraceUtil.java +++ b/Mage/src/mage/util/trace/TraceUtil.java @@ -40,25 +40,20 @@ public class TraceUtil { * @param combat */ public static void traceCombatIfNeeded(Game game, Combat combat) { - // trace non-flying vs flying + // trace non-flying vs flying for (CombatGroup group : combat.getGroups()) { for (UUID attackerId : group.getAttackers()) { Permanent attacker = game.getPermanent(attackerId); if (attacker != null) { if (hasFlying(attacker)) { -// boolean traceDone = false; - + // traceCombat(game, attacker, null); for (UUID blockerId : group.getBlockers()) { Permanent blocker = game.getPermanent(blockerId); if (blocker != null && !hasFlying(blocker) && !hasReach(blocker)) { log.warn("Found non-flying non-reach creature blocking creature with flying"); traceCombat(game, attacker, blocker); -// traceDone = true; } } -// if (!traceDone) { -// traceCombat(game, attacker, null); -// } } if (hasIntimidate(attacker)) { for (UUID blockerId : group.getBlockers()) { @@ -70,7 +65,6 @@ public class TraceUtil { } } } - if (hasUnblockable(attacker)) { if (group.getBlockers().size() > 0) { Permanent blocker = game.getPermanent(group.getBlockers().get(0));