diff --git a/Mage.Sets/src/mage/cards/c/CaveIn.java b/Mage.Sets/src/mage/cards/c/CaveIn.java index 51d6cc315e..ccccf8741c 100644 --- a/Mage.Sets/src/mage/cards/c/CaveIn.java +++ b/Mage.Sets/src/mage/cards/c/CaveIn.java @@ -1,7 +1,5 @@ - package mage.cards.c; -import java.util.UUID; import mage.ObjectColor; import mage.abilities.costs.AlternativeCostSourceAbility; import mage.abilities.costs.common.ExileFromHandCost; @@ -10,27 +8,29 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.filter.common.FilterOwnedCard; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.mageobject.CardIdPredicate; import mage.filter.predicate.mageobject.ColorPredicate; import mage.target.common.TargetCardInHand; +import java.util.UUID; + /** - * * @author emerald000 */ public final class CaveIn extends CardImpl { - public CaveIn(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{R}{R}"); + private static final FilterOwnedCard filter + = new FilterOwnedCard("a red card from your hand"); + static { + filter.add(new ColorPredicate(ObjectColor.RED)); + } + + public CaveIn(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{R}{R}"); // You may exile a red card from your hand rather than pay Cave-In's mana cost. - FilterOwnedCard filter = new FilterOwnedCard("a red card from your hand"); - filter.add(new ColorPredicate(ObjectColor.RED)); - filter.add(Predicates.not(new CardIdPredicate(this.getId()))); this.addAbility(new AlternativeCostSourceAbility(new ExileFromHandCost(new TargetCardInHand(filter)))); - + // Cave-In deals 2 damage to each creature and each player. this.getSpellAbility().addEffect(new DamageEverythingEffect(2)); } diff --git a/Mage.Sets/src/mage/cards/d/DespoilerOfSouls.java b/Mage.Sets/src/mage/cards/d/DespoilerOfSouls.java index 523cf9ba43..4e2067a33d 100644 --- a/Mage.Sets/src/mage/cards/d/DespoilerOfSouls.java +++ b/Mage.Sets/src/mage/cards/d/DespoilerOfSouls.java @@ -1,7 +1,5 @@ - package mage.cards.d; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.CantBlockAbility; @@ -16,29 +14,37 @@ import mage.constants.SubType; import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.common.FilterCreatureCard; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.mageobject.CardIdPredicate; +import mage.filter.predicate.mageobject.AnotherPredicate; import mage.target.common.TargetCardInYourGraveyard; +import java.util.UUID; + /** - * * @author fireshoes */ public final class DespoilerOfSouls extends CardImpl { - + + private static final FilterCard filter = new FilterCreatureCard("two other creature cards from your graveyard"); + + static { + filter.add(AnotherPredicate.instance); + } + public DespoilerOfSouls(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}{B}"); this.subtype.add(SubType.HORROR); this.power = new MageInt(3); this.toughness = new MageInt(1); // Despoiler of Souls can't block. this.addAbility(new CantBlockAbility()); - + // {B}{B}, Exile two other creature cards from your graveyard: Return Despoiler of Souls from your graveyard to the battlefield. - FilterCard filter = new FilterCreatureCard("two other creature cards from your graveyard"); - filter.add(Predicates.not(new CardIdPredicate(this.getId()))); - Ability ability = new SimpleActivatedAbility(Zone.GRAVEYARD, new ReturnSourceFromGraveyardToBattlefieldEffect(false), new ManaCostsImpl("{B}{B}")); + Ability ability = new SimpleActivatedAbility( + Zone.GRAVEYARD, + new ReturnSourceFromGraveyardToBattlefieldEffect(false), + new ManaCostsImpl<>("{B}{B}") + ); ability.addCost(new ExileFromGraveCost(new TargetCardInYourGraveyard(2, filter))); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/f/FlashOfInsight.java b/Mage.Sets/src/mage/cards/f/FlashOfInsight.java index c0eee07e07..7a8a577922 100644 --- a/Mage.Sets/src/mage/cards/f/FlashOfInsight.java +++ b/Mage.Sets/src/mage/cards/f/FlashOfInsight.java @@ -1,7 +1,5 @@ - package mage.cards.f; -import java.util.UUID; import mage.MageObject; import mage.ObjectColor; import mage.abilities.Ability; @@ -14,33 +12,34 @@ import mage.abilities.keyword.FlashbackAbility; import mage.cards.*; import mage.constants.CardType; import mage.constants.Outcome; -import mage.constants.TimingRule; import mage.constants.Zone; import mage.filter.FilterCard; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.mageobject.CardIdPredicate; import mage.filter.predicate.mageobject.ColorPredicate; import mage.game.Game; import mage.players.Player; import mage.target.TargetCard; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class FlashOfInsight extends CardImpl { + private static final FilterCard filter = new FilterCard("blue cards from your graveyard"); + + static { + filter.add(new ColorPredicate(ObjectColor.BLUE)); + } + public FlashOfInsight(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{X}{1}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{X}{1}{U}"); // Look at the top X cards of your library. Put one of them into your hand and the rest on the bottom of your library in any order. this.getSpellAbility().addEffect(new FlashOfInsightEffect()); // Flashback-{1}{U}, Exile X blue cards from your graveyard. - Ability ability = new FlashbackAbility(this, new ManaCostsImpl("{1}{U}")); - FilterCard filter = new FilterCard("blue cards from your graveyard"); - filter.add(new ColorPredicate(ObjectColor.BLUE)); - filter.add(Predicates.not(new CardIdPredicate(getId()))); + Ability ability = new FlashbackAbility(this, new ManaCostsImpl<>("{1}{U}")); ability.addCost(new ExileXFromYourGraveCost(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/h/HakimLoreweaver.java b/Mage.Sets/src/mage/cards/h/HakimLoreweaver.java index 8828f590c5..be8563dd85 100644 --- a/Mage.Sets/src/mage/cards/h/HakimLoreweaver.java +++ b/Mage.Sets/src/mage/cards/h/HakimLoreweaver.java @@ -1,4 +1,3 @@ - package mage.cards.h; import mage.MageInt; @@ -17,19 +16,18 @@ import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.FilterCard; import mage.filter.FilterPermanent; -import mage.filter.predicate.mageobject.CardIdPredicate; +import mage.filter.predicate.Predicate; import mage.filter.predicate.card.AuraCardCanAttachToPermanentId; -import mage.filter.predicate.permanent.AttachedToPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; import mage.target.common.TargetCardInYourGraveyard; +import java.util.Objects; import java.util.UUID; /** - * * @author jeffwadsworth, TheElk801 */ public final class HakimLoreweaver extends CardImpl { @@ -58,22 +56,16 @@ public final class HakimLoreweaver extends CardImpl { Ability ability = new ConditionalActivatedAbility( Zone.BATTLEFIELD, new HakimLoreweaverEffect(), - new ManaCostsImpl("{U}{U}"), - new HakimLoreweaverCondition()); + new ManaCostsImpl<>("{U}{U}"), + HakimLoreweaverCondition.instance + ); ability.addTarget(new TargetCardInYourGraveyard(filter)); this.addAbility(ability); // {U}{U}, {tap}: Destroy all Auras attached to Hakim. - FilterPermanent filterAurasOnHakim = new FilterPermanent("Auras attached to Hakim"); - filterAurasOnHakim.add(CardType.ENCHANTMENT.getPredicate()); - filterAurasOnHakim.add(SubType.AURA.getPredicate()); - FilterPermanent filterSourceId = new FilterPermanent(); - filterSourceId.add(new CardIdPredicate(this.getId())); - filterAurasOnHakim.add(new AttachedToPredicate(filterSourceId)); - Ability ability2 = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyAllEffect(filterAurasOnHakim), new ManaCostsImpl("{U}{U}")); + Ability ability2 = new SimpleActivatedAbility(new HakimLoreweaverEffect(), new ManaCostsImpl<>("{U}{U}")); ability2.addCost(new TapSourceCost()); this.addAbility(ability2); - } private HakimLoreweaver(final HakimLoreweaver card) { @@ -123,8 +115,8 @@ class HakimLoreweaverEffect extends OneShotEffect { } } -class HakimLoreweaverCondition implements Condition { - +enum HakimLoreweaverCondition implements Condition { + instance; static private final FilterPermanent auras = new FilterPermanent(); static { @@ -133,18 +125,18 @@ class HakimLoreweaverCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - Permanent hakimLoreweaver = game.getPermanent(source.getSourceId()); - if (hakimLoreweaver != null) { - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(auras, game)) { - if (permanent != null - && hakimLoreweaver.getAttachments().contains(permanent.getId())) { - return false; - } - } - return PhaseStep.UPKEEP == game.getStep().getType() - && game.isActivePlayer(source.getControllerId()); + if (PhaseStep.UPKEEP != game.getStep().getType() + || !game.isActivePlayer(source.getControllerId())) { + return false; } - return false; + Permanent hakimLoreweaver = source.getSourcePermanentIfItStillExists(game); + return hakimLoreweaver != null + && hakimLoreweaver + .getAttachments() + .stream() + .map(game::getPermanent) + .filter(Objects::nonNull) + .anyMatch(permanent -> permanent.hasSubtype(SubType.AURA, game)); } @Override @@ -152,3 +144,46 @@ class HakimLoreweaverCondition implements Condition { return "during your upkeep and only if {this} isn't enchanted"; } } + +class HakimLoreweaverDestroyEffect extends OneShotEffect { + + HakimLoreweaverDestroyEffect() { + super(Outcome.Benefit); + staticText = "destroy all Auras attached to {this}"; + } + + private HakimLoreweaverDestroyEffect(final HakimLoreweaverDestroyEffect effect) { + super(effect); + } + + @Override + public HakimLoreweaverDestroyEffect copy() { + return new HakimLoreweaverDestroyEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = source.getSourcePermanentIfItStillExists(game); + if (permanent == null) { + return false; + } + FilterPermanent filter = new FilterPermanent(); + filter.add(SubType.AURA.getPredicate()); + filter.add(new HakimLoreweaverPredicate(permanent)); + return new DestroyAllEffect(filter).apply(game, source); + } +} + +class HakimLoreweaverPredicate implements Predicate { + + private final Permanent permanent; + + HakimLoreweaverPredicate(Permanent permanent) { + this.permanent = permanent; + } + + @Override + public boolean apply(Permanent input, Game game) { + return input.isAttachedTo(permanent.getId()); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/i/Ichorid.java b/Mage.Sets/src/mage/cards/i/Ichorid.java index f05c7e7f4b..da61c6ff2f 100644 --- a/Mage.Sets/src/mage/cards/i/Ichorid.java +++ b/Mage.Sets/src/mage/cards/i/Ichorid.java @@ -1,10 +1,8 @@ - package mage.cards.i; -import java.util.UUID; import mage.MageInt; +import mage.MageObject; import mage.ObjectColor; -import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.BeginningOfYourEndStepTriggeredAbility; import mage.abilities.costs.common.ExileFromGraveCost; @@ -20,21 +18,20 @@ import mage.constants.TargetController; import mage.constants.Zone; import mage.filter.FilterCard; import mage.filter.common.FilterCreatureCard; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.mageobject.CardIdPredicate; +import mage.filter.predicate.mageobject.AnotherPredicate; import mage.filter.predicate.mageobject.ColorPredicate; import mage.game.Game; -import mage.players.Player; import mage.target.common.TargetCardInYourGraveyard; +import java.util.UUID; + /** - * * @author Plopman */ public final class Ichorid extends CardImpl { public Ichorid(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}"); this.subtype.add(SubType.HORROR); this.power = new MageInt(3); @@ -42,15 +39,12 @@ public final class Ichorid extends CardImpl { // Haste this.addAbility(HasteAbility.getInstance()); + // At the beginning of the end step, sacrifice Ichorid. this.addAbility(new BeginningOfYourEndStepTriggeredAbility(new SacrificeSourceEffect(), false)); + // At the beginning of your upkeep, if Ichorid is in your graveyard, you may exile a black creature card other than Ichorid from your graveyard. If you do, return Ichorid to the battlefield. - FilterCard filter = new FilterCreatureCard("a black creature card other than Ichorid from your graveyard"); - filter.add(Predicates.not(new CardIdPredicate(this.getId()))); - filter.add(new ColorPredicate(ObjectColor.BLACK)); - Ability ability = new IchoridTriggerdAbility(filter); - this.addAbility(ability); - + this.addAbility(new IchoridTriggerdAbility()); } private Ichorid(final Ichorid card) { @@ -63,16 +57,20 @@ public final class Ichorid extends CardImpl { } } -class IchoridTriggerdAbility extends BeginningOfUpkeepTriggeredAbility{ +class IchoridTriggerdAbility extends BeginningOfUpkeepTriggeredAbility { - public IchoridTriggerdAbility(FilterCard filter){ - super(Zone.GRAVEYARD, - new DoIfCostPaid(new ReturnSourceFromGraveyardToBattlefieldEffect(), - new ExileFromGraveCost( - new TargetCardInYourGraveyard(1, 1, filter, true) - ) - ), - TargetController.YOU, false); + private static final FilterCard filter = new FilterCreatureCard("another black creature card"); + + static { + filter.add(AnotherPredicate.instance); + filter.add(new ColorPredicate(ObjectColor.BLACK)); + } + + public IchoridTriggerdAbility() { + super(Zone.GRAVEYARD, new DoIfCostPaid( + new ReturnSourceFromGraveyardToBattlefieldEffect(), + new ExileFromGraveCost(new TargetCardInYourGraveyard(filter)) + ), TargetController.YOU, false); } public IchoridTriggerdAbility(IchoridTriggerdAbility ability) { @@ -83,19 +81,17 @@ class IchoridTriggerdAbility extends BeginningOfUpkeepTriggeredAbility{ public BeginningOfUpkeepTriggeredAbility copy() { return new IchoridTriggerdAbility(this); } - + @Override public boolean checkInterveningIfClause(Game game) { - Player controller = game.getPlayer(controllerId); - if(controller != null && controller.getGraveyard().contains(sourceId)){ - return super.checkInterveningIfClause(game); - } - return false; + MageObject sourceObject = getSourceObjectIfItStillExists(game); + return sourceObject != null && game.getState().getZone(getSourceId()) == Zone.GRAVEYARD; } @Override public String getRule() { - return "At the beginning of your upkeep, if {this} is in your graveyard, you may exile a black creature card other than {this} from your graveyard. If you do, return {this} to the battlefield."; + return "At the beginning of your upkeep, if {this} is in your graveyard, " + + "you may exile a black creature card other than {this} from your graveyard. " + + "If you do, return {this} to the battlefield."; } - } diff --git a/Mage.Sets/src/mage/cards/k/KabiraEvangel.java b/Mage.Sets/src/mage/cards/k/KabiraEvangel.java index 7fe59316be..d0ad7a9d2e 100644 --- a/Mage.Sets/src/mage/cards/k/KabiraEvangel.java +++ b/Mage.Sets/src/mage/cards/k/KabiraEvangel.java @@ -1,36 +1,27 @@ - package mage.cards.k; -import java.util.UUID; import mage.MageInt; -import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; -import mage.abilities.effects.Effect; +import mage.abilities.common.AllyEntersBattlefieldTriggeredAbility; import mage.abilities.effects.common.continuous.GainProtectionFromColorAllEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.FilterPermanent; -import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.mageobject.CardIdPredicate; +import mage.filter.common.FilterControlledPermanent; + +import java.util.UUID; /** - * * @author jeffwadsworth */ public final class KabiraEvangel extends CardImpl { - private static final FilterControlledCreaturePermanent FILTER1 = new FilterControlledCreaturePermanent(); - - static { - FILTER1.add(SubType.ALLY.getPredicate()); - } + private static final FilterPermanent FILTER1 = new FilterControlledPermanent(SubType.ALLY, "Ally"); public KabiraEvangel(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.CLERIC); this.subtype.add(SubType.ALLY); @@ -38,13 +29,13 @@ public final class KabiraEvangel extends CardImpl { this.power = new MageInt(2); this.toughness = new MageInt(3); - FilterPermanent filter2 = new FilterPermanent(getName() + " or another Ally"); - filter2.add(Predicates.or(new CardIdPredicate(this.getId()), SubType.ALLY.getPredicate())); - // Whenever Kabira Evangel or another Ally enters the battlefield under your control, you may choose a color. If you do, Allies you control gain protection from the chosen color until end of turn. - Effect effect = new GainProtectionFromColorAllEffect(Duration.EndOfTurn, FILTER1); - effect.setText("choose a color. If you do, Allies you control gain protection from the chosen color until end of turn."); - this.addAbility(new EntersBattlefieldControlledTriggeredAbility(Zone.BATTLEFIELD, effect, filter2, true)); + this.addAbility(new AllyEntersBattlefieldTriggeredAbility( + new GainProtectionFromColorAllEffect(Duration.EndOfTurn, FILTER1) + .setText("choose a color. If you do, Allies you control gain protection " + + "from the chosen color until end of turn."), + true + )); } private KabiraEvangel(final KabiraEvangel card) { diff --git a/Mage.Sets/src/mage/cards/l/LanternScout.java b/Mage.Sets/src/mage/cards/l/LanternScout.java index 042d19bd2a..44304962ae 100644 --- a/Mage.Sets/src/mage/cards/l/LanternScout.java +++ b/Mage.Sets/src/mage/cards/l/LanternScout.java @@ -1,48 +1,37 @@ - package mage.cards.l; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.AllyEntersBattlefieldTriggeredAbility; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.GainAbilityAllEffect; import mage.abilities.keyword.LifelinkAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.AbilityWord; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.filter.FilterPermanent; -import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.mageobject.CardIdPredicate; +import mage.filter.StaticFilters; + +import java.util.UUID; /** - * * @author fireshoes */ public final class LanternScout extends CardImpl { public LanternScout(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.SCOUT); this.subtype.add(SubType.ALLY); this.power = new MageInt(3); this.toughness = new MageInt(2); - FilterPermanent filter = new FilterPermanent("{this} or another Ally"); - filter.add(Predicates.or( - new CardIdPredicate(this.getId()), - SubType.ALLY.getPredicate())); - // Rally — Whenever Lantern Scout or another Ally enters the battlefield under your control, creatures you control gain lifelink until end of turn. - Effect effect = new GainAbilityAllEffect(LifelinkAbility.getInstance(), Duration.EndOfTurn, new FilterControlledCreaturePermanent()); - effect.setText("creatures you control gain lifelink until end of turn"); - Ability ability = new AllyEntersBattlefieldTriggeredAbility( - effect, false); - this.addAbility(ability); + this.addAbility(new AllyEntersBattlefieldTriggeredAbility(new GainAbilityAllEffect( + LifelinkAbility.getInstance(), Duration.EndOfTurn, + StaticFilters.FILTER_CONTROLLED_CREATURES + ), false).setAbilityWord(AbilityWord.RALLY)); } private LanternScout(final LanternScout card) { diff --git a/Mage.Sets/src/mage/cards/v/VineDryad.java b/Mage.Sets/src/mage/cards/v/VineDryad.java index 8f89cdeb36..4ee1864443 100644 --- a/Mage.Sets/src/mage/cards/v/VineDryad.java +++ b/Mage.Sets/src/mage/cards/v/VineDryad.java @@ -1,7 +1,5 @@ - package mage.cards.v; -import java.util.UUID; import mage.MageInt; import mage.ObjectColor; import mage.abilities.costs.AlternativeCostSourceAbility; @@ -13,19 +11,25 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.common.FilterOwnedCard; -import mage.filter.predicate.Predicates; -import mage.filter.predicate.mageobject.CardIdPredicate; import mage.filter.predicate.mageobject.ColorPredicate; import mage.target.common.TargetCardInHand; +import java.util.UUID; + /** - * * @author fireshoes */ public final class VineDryad extends CardImpl { + private static final FilterOwnedCard filter + = new FilterOwnedCard("a green card from your hand"); + + static { + filter.add(new ColorPredicate(ObjectColor.GREEN)); + } + public VineDryad(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}"); this.subtype.add(SubType.DRYAD); this.power = new MageInt(1); this.toughness = new MageInt(3); @@ -37,10 +41,6 @@ public final class VineDryad extends CardImpl { this.addAbility(new ForestwalkAbility()); // You may exile a green card from your hand rather than pay Vine Dryad's mana cost. - FilterOwnedCard filter = new FilterOwnedCard("a green card from your hand"); - filter.add(new ColorPredicate(ObjectColor.GREEN)); - filter.add(Predicates.not(new CardIdPredicate(this.getId()))); // the exile cost can never be paid with the card itself - this.addAbility(new AlternativeCostSourceAbility(new ExileFromHandCost(new TargetCardInHand(filter)))); }