diff --git a/Mage.Sets/src/mage/cards/c/Caprichrome.java b/Mage.Sets/src/mage/cards/c/Caprichrome.java index c520ee2b8fc..c615d62baf4 100644 --- a/Mage.Sets/src/mage/cards/c/Caprichrome.java +++ b/Mage.Sets/src/mage/cards/c/Caprichrome.java @@ -8,8 +8,8 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledArtifactPermanent; -import mage.filter.common.FilterControlledPermanent; import java.util.UUID; @@ -18,7 +18,7 @@ import java.util.UUID; */ public final class Caprichrome extends CardImpl { - private static final FilterControlledPermanent filter = new FilterControlledArtifactPermanent("artifact"); + private static final FilterPermanent filter = new FilterControlledArtifactPermanent("artifact"); public Caprichrome(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}{W}"); diff --git a/Mage.Sets/src/mage/cards/d/DevouringHellion.java b/Mage.Sets/src/mage/cards/d/DevouringHellion.java index b9eae227c87..dfe1f3087f7 100644 --- a/Mage.Sets/src/mage/cards/d/DevouringHellion.java +++ b/Mage.Sets/src/mage/cards/d/DevouringHellion.java @@ -1,24 +1,14 @@ package mage.cards.d; import mage.MageInt; -import mage.abilities.Ability; -import mage.abilities.common.AsEntersBattlefieldAbility; -import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.counter.AddCountersSourceEffect; +import mage.abilities.common.SimpleStaticAbility; +import mage.abilities.effects.common.DevourEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.SubType; -import mage.counters.CounterType; -import mage.filter.FilterPermanent; -import mage.filter.common.FilterControlledPermanent; -import mage.filter.predicate.Predicates; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; -import mage.target.Target; -import mage.target.common.TargetSacrifice; +import mage.constants.Zone; +import mage.filter.StaticFilters; import java.util.UUID; @@ -35,7 +25,11 @@ public final class DevouringHellion extends CardImpl { this.toughness = new MageInt(2); // As Devouring Hellion enters the battlefield, you may sacrifice any number of creatures and/or planeswalkers. If you do, it enters with twice that many +1/+1 counters on it. - this.addAbility(new AsEntersBattlefieldAbility(new DevouringHellionEffect())); + this.addAbility(new SimpleStaticAbility(Zone.ALL, + new DevourEffect(2, StaticFilters.FILTER_CONTROLLED_PERMANENT_CREATURE_OR_PLANESWALKER) + .setText("As {this} enters the battlefield, you may sacrifice any number of creatures and/or planeswalkers." + + " If you do, it enters with twice that many +1/+1 counters on it") + )); } private DevouringHellion(final DevouringHellion card) { @@ -47,50 +41,3 @@ public final class DevouringHellion extends CardImpl { return new DevouringHellion(this); } } - -class DevouringHellionEffect extends OneShotEffect { - - private static final FilterPermanent filter = new FilterControlledPermanent("creatures and/or planeswalkers"); - - static { - filter.add(Predicates.or( - CardType.CREATURE.getPredicate(), - CardType.PLANESWALKER.getPredicate() - )); - } - - DevouringHellionEffect() { - super(Outcome.Benefit); - staticText = "you may sacrifice any number of creatures and/or planeswalkers. " + - "If you do, it enters with twice that many +1/+1 counters on it."; - } - - private DevouringHellionEffect(final DevouringHellionEffect effect) { - super(effect); - } - - @Override - public DevouringHellionEffect copy() { - return new DevouringHellionEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player == null) { - return false; - } - Target target = new TargetSacrifice(0, Integer.MAX_VALUE, filter); - if (!player.choose(Outcome.Sacrifice, target, source, game)) { - return false; - } - int xValue = 0; - for (UUID targetId : target.getTargets()) { - Permanent permanent = game.getPermanent(targetId); - if (permanent != null && permanent.sacrifice(source, game)) { - xValue++; - } - } - return new AddCountersSourceEffect(CounterType.P1P1.createInstance(2 * xValue)).apply(game, source); - } -} diff --git a/Mage.Sets/src/mage/cards/f/FeastingHobbit.java b/Mage.Sets/src/mage/cards/f/FeastingHobbit.java index c909795dfe7..a326576dbd2 100644 --- a/Mage.Sets/src/mage/cards/f/FeastingHobbit.java +++ b/Mage.Sets/src/mage/cards/f/FeastingHobbit.java @@ -14,7 +14,6 @@ import mage.filter.StaticFilters; import java.util.UUID; /** - * * @author Susucr */ public final class FeastingHobbit extends CardImpl { diff --git a/Mage.Sets/src/mage/cards/t/ThromokTheInsatiable.java b/Mage.Sets/src/mage/cards/t/ThromokTheInsatiable.java index b7a13b6d3f6..87373defd90 100644 --- a/Mage.Sets/src/mage/cards/t/ThromokTheInsatiable.java +++ b/Mage.Sets/src/mage/cards/t/ThromokTheInsatiable.java @@ -1,4 +1,3 @@ - package mage.cards.t; import mage.MageInt; @@ -26,7 +25,7 @@ public final class ThromokTheInsatiable extends CardImpl { this.toughness = new MageInt(0); // Devour X, where X is the number of creatures devoured this way (As this enters the battlefield, you may sacrifice any number of creatures. This creature enters the battlefield with X +1/+1 counters on it for each of those creatures.) - this.addAbility(DevourAbility.DevourX()); + this.addAbility(DevourAbility.devourX()); } private ThromokTheInsatiable(final ThromokTheInsatiable card) { diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DevourTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DevourTest.java index c2687ac93ed..664549309c9 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DevourTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/DevourTest.java @@ -1,4 +1,3 @@ - package org.mage.test.cards.abilities.keywords; import mage.abilities.keyword.FlyingAbility; @@ -9,6 +8,8 @@ import mage.counters.CounterType; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; +import java.util.Objects; + /** * 702.82. Devour *

@@ -27,9 +28,11 @@ public class DevourTest extends CardTestPlayerBase { String devourTargets, int assertCounter, boolean assertLion, - boolean assertMyr, + boolean assertGolem, boolean assertGinger, - boolean assertRelic + boolean assertRelic, + boolean assertAngrath, + int life ) { setStrictChooseMode(true); @@ -46,17 +49,21 @@ public class DevourTest extends CardTestPlayerBase { addCard(Zone.HAND, playerA, devourer); addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); // Creature - addCard(Zone.BATTLEFIELD, playerA, "Alpha Myr"); // Creature Artifact + addCard(Zone.BATTLEFIELD, playerA, "Enatu Golem"); // Artifact Creature - gain 4 life on death addCard(Zone.BATTLEFIELD, playerA, "Gingerbrute"); // Artifact Creature — Food Golem addCard(Zone.BATTLEFIELD, playerA, "Darksteel Relic"); // Artifact + addCard(Zone.BATTLEFIELD, playerA, "Angrath, Captain of Chaos"); // Planeswalker castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, devourer); - if (devourTargets == "") { + if (Objects.equals(devourTargets, "")) { setChoice(playerA, false); // no to devour } else { setChoice(playerA, true); // yes to devour addTarget(playerA, devourTargets); // devour targets. } + if (!assertGolem && devourer.equals("Marrow Chomper")) { + setChoice(playerA, "When {this} dies, you gain 4 life"); // order triggers + } setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); @@ -70,12 +77,15 @@ public class DevourTest extends CardTestPlayerBase { assertPermanentCount(playerA, "Silvercoat Lion", assertLion ? 1 : 0); assertGraveyardCount(playerA, "Silvercoat Lion", assertLion ? 0 : 1); - assertPermanentCount(playerA, "Alpha Myr", assertMyr ? 1 : 0); - assertGraveyardCount(playerA, "Alpha Myr", assertMyr ? 0 : 1); + assertPermanentCount(playerA, "Enatu Golem", assertGolem ? 1 : 0); + assertGraveyardCount(playerA, "Enatu Golem", assertGolem ? 0 : 1); assertPermanentCount(playerA, "Gingerbrute", assertGinger ? 1 : 0); assertGraveyardCount(playerA, "Gingerbrute", assertGinger ? 0 : 1); assertPermanentCount(playerA, "Darksteel Relic", assertRelic ? 1 : 0); assertGraveyardCount(playerA, "Darksteel Relic", assertRelic ? 0 : 1); + assertPermanentCount(playerA, "Angrath, Captain of Chaos", assertAngrath ? 1 : 0); + assertGraveyardCount(playerA, "Angrath, Captain of Chaos", assertAngrath ? 0 : 1); + assertLife(playerA, life); } private void expectedIllegalTest( @@ -97,7 +107,7 @@ public class DevourTest extends CardTestPlayerBase { addCard(Zone.HAND, playerA, devourer); addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion"); // Creature - addCard(Zone.BATTLEFIELD, playerA, "Alpha Myr"); // Creature Artifact + addCard(Zone.BATTLEFIELD, playerA, "Enatu Golem"); // Creature Artifact addCard(Zone.BATTLEFIELD, playerA, "Gingerbrute"); // Artifact Creature — Food Golem addCard(Zone.BATTLEFIELD, playerA, "Darksteel Relic"); // Artifact @@ -130,25 +140,25 @@ public class DevourTest extends CardTestPlayerBase { @Test public void Wurm_NoDevour() { expectedPossibleTest(gorgerWurm, "", - 1 * 0, true, true, true, true); + 1 * 0, true, true, true, true, true, 20); } @Test public void Wurm_OneDevour() { - expectedPossibleTest(gorgerWurm, "Alpha Myr", - 1 * 1, true, false, true, true); + expectedPossibleTest(gorgerWurm, "Enatu Golem", + 1 * 1, true, false, true, true, true, 24); } @Test public void Wurm_TwoDevour() { - expectedPossibleTest(gorgerWurm, "Alpha Myr^Gingerbrute", - 1 * 2, true, false, false, true); + expectedPossibleTest(gorgerWurm, "Enatu Golem^Gingerbrute", + 1 * 2, true, false, false, true, true, 24); } @Test public void Wurm_ThreeDevour() { - expectedPossibleTest(gorgerWurm, "Alpha Myr^Gingerbrute^Silvercoat Lion", - 1 * 3, false, false, false, true); + expectedPossibleTest(gorgerWurm, "Enatu Golem^Gingerbrute^Silvercoat Lion", + 1 * 3, false, false, false, true, true, 24); } @Test @@ -168,25 +178,25 @@ public class DevourTest extends CardTestPlayerBase { @Test public void Thromok_NoDevour() { expectedPossibleTest(thromok, "", - 0 * 0, true, true, true, true); + 0 * 0, true, true, true, true, true, 20); } @Test public void Thromok_OneDevour() { - expectedPossibleTest(thromok, "Alpha Myr", - 1 * 1, true, false, true, true); + expectedPossibleTest(thromok, "Enatu Golem", + 1 * 1, true, false, true, true, true, 24); } @Test public void Thromok_TwoDevour() { - expectedPossibleTest(thromok, "Alpha Myr^Gingerbrute", - 2 * 2, true, false, false, true); + expectedPossibleTest(thromok, "Enatu Golem^Gingerbrute", + 2 * 2, true, false, false, true, true, 24); } @Test public void Thromok_ThreeDevour() { - expectedPossibleTest(thromok, "Alpha Myr^Gingerbrute^Silvercoat Lion", - 3 * 3, false, false, false, true); + expectedPossibleTest(thromok, "Enatu Golem^Gingerbrute^Silvercoat Lion", + 3 * 3, false, false, false, true, true, 24); } @Test @@ -206,18 +216,18 @@ public class DevourTest extends CardTestPlayerBase { @Test public void Hobbit_NoDevour() { expectedPossibleTest(hobbit, "", - 3 * 0, true, true, true, true); + 3 * 0, true, true, true, true, true, 20); } @Test public void Hobbit_OneDevour() { expectedPossibleTest(hobbit, "Gingerbrute", - 3 * 1, true, true, false, true); + 3 * 1, true, true, false, true, true, 20); } @Test public void Hobbit_IllegalDevour() { - expectedIllegalTest(hobbit, "Alpha Myr"); + expectedIllegalTest(hobbit, "Enatu Golem"); } // Caprichrome @@ -236,25 +246,25 @@ public class DevourTest extends CardTestPlayerBase { @Test public void Caprichrome_NoDevour() { expectedPossibleTest(caprichrome, "", - 1 * 0, true, true, true, true); + 1 * 0, true, true, true, true, true, 20); } @Test public void Caprichrome_OneDevour() { - expectedPossibleTest(caprichrome, "Alpha Myr", - 1 * 1, true, false, true, true); + expectedPossibleTest(caprichrome, "Enatu Golem", + 1 * 1, true, false, true, true, true, 24); } @Test public void Caprichrome_TwoDevour() { - expectedPossibleTest(caprichrome, "Alpha Myr^Gingerbrute", - 1 * 2, true, false, false, true); + expectedPossibleTest(caprichrome, "Enatu Golem^Gingerbrute", + 1 * 2, true, false, false, true, true, 24); } @Test public void Caprichrome_ThreeDevour() { - expectedPossibleTest(caprichrome, "Alpha Myr^Gingerbrute^Darksteel Relic", - 1 * 3, true, false, false, false); + expectedPossibleTest(caprichrome, "Enatu Golem^Gingerbrute^Darksteel Relic", + 1 * 3, true, false, false, false, true, 24); } @Test @@ -276,31 +286,31 @@ public class DevourTest extends CardTestPlayerBase { @Test public void Hatchling_NoDevour() { expectedPossibleTest(hatchling, "", - 1 * 0, true, true, true, true); + 1 * 0, true, true, true, true, true, 20); assertAbility(playerA, hatchling, FlyingAbility.getInstance(), false); assertAbility(playerA, hatchling, TrampleAbility.getInstance(), false); } @Test public void Hatchling_OneDevour() { - expectedPossibleTest(hatchling, "Alpha Myr", - 1 * 1, true, false, true, true); + expectedPossibleTest(hatchling, "Enatu Golem", + 1 * 1, true, false, true, true, true, 24); assertAbility(playerA, hatchling, FlyingAbility.getInstance(), true); assertAbility(playerA, hatchling, TrampleAbility.getInstance(), true); } @Test public void Hatchling_TwoDevour() { - expectedPossibleTest(hatchling, "Alpha Myr^Gingerbrute", - 1 * 2, true, false, false, true); + expectedPossibleTest(hatchling, "Enatu Golem^Gingerbrute", + 1 * 2, true, false, false, true, true, 24); assertAbility(playerA, hatchling, FlyingAbility.getInstance(), true); assertAbility(playerA, hatchling, TrampleAbility.getInstance(), true); } @Test public void Hatchling_ThreeDevour() { - expectedPossibleTest(hatchling, "Alpha Myr^Gingerbrute^Silvercoat Lion", - 1 * 3, false, false, false, true); + expectedPossibleTest(hatchling, "Enatu Golem^Gingerbrute^Silvercoat Lion", + 1 * 3, false, false, false, true, true, 24); assertAbility(playerA, hatchling, FlyingAbility.getInstance(), true); assertAbility(playerA, hatchling, TrampleAbility.getInstance(), true); } @@ -322,33 +332,65 @@ public class DevourTest extends CardTestPlayerBase { @Test public void Chomper_NoDevour() { expectedPossibleTest(chomper, "", - 2 * 0, true, true, true, true); - assertLife(playerA, 20 + 2 * 0); + 2 * 0, true, true, true, true, true, 20); } @Test public void Chomper_OneDevour() { - expectedPossibleTest(chomper, "Alpha Myr", - 2 * 1, true, false, true, true); - assertLife(playerA, 20 + 2 * 1); + expectedPossibleTest(chomper, "Enatu Golem", + 2 * 1, true, false, true, true, true, 26); } @Test public void Chomper_TwoDevour() { - expectedPossibleTest(chomper, "Alpha Myr^Gingerbrute", - 2 * 2, true, false, false, true); - assertLife(playerA, 20 + 2 * 2); + expectedPossibleTest(chomper, "Enatu Golem^Gingerbrute", + 2 * 2, true, false, false, true, true, 28); } @Test public void Chomper_ThreeDevour() { - expectedPossibleTest(chomper, "Alpha Myr^Gingerbrute^Silvercoat Lion", - 2 * 3, false, false, false, true); - assertLife(playerA, 20 + 2 * 3); + expectedPossibleTest(chomper, "Enatu Golem^Gingerbrute^Silvercoat Lion", + 2 * 3, false, false, false, true, true, 30); } @Test public void Chomper_IllegalDevour() { expectedIllegalTest(chomper, "Darksteel Relic"); } -} \ No newline at end of file + + // Devouring Hellion {2}{R} + // Creature — Hellion + // As Devouring Hellion enters, you may sacrifice any number of creatures and/or planeswalkers. + // If you do, it enters with twice that many +1/+1 counters on it. + private static final String hellion = "Devouring Hellion"; + + @Test + public void hellionNoDevour() { + expectedPossibleTest(hellion, "", + 0, true, true, true, true, true, 20); + } + + @Test + public void hellionOneDevour() { + expectedPossibleTest(hellion, "Angrath, Captain of Chaos", + 2, true, true, true, true, false, 20); + } + + @Test + public void hellionTwoDevour() { + expectedPossibleTest(hellion, "Enatu Golem^Angrath, Captain of Chaos", + 4, true, false, true, true, false, 24); + } + + @Test + public void hellionThreeDevour() { + expectedPossibleTest(hellion, "Enatu Golem^Gingerbrute^Angrath, Captain of Chaos", + 6, true, false, false, true, false, 24); + } + + @Test + public void hellionIllegalDevour() { + expectedIllegalTest(hellion, "Darksteel Relic"); + } + +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/DevourEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DevourEffect.java index b2171b96d90..800c54452b5 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/DevourEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/DevourEffect.java @@ -6,8 +6,7 @@ import mage.abilities.effects.ReplacementEffectImpl; import mage.constants.Duration; import mage.constants.Outcome; import mage.counters.CounterType; -import mage.filter.common.FilterControlledPermanent; -import mage.filter.predicate.Predicate; +import mage.filter.FilterPermanent; import mage.filter.predicate.mageobject.AnotherPredicate; import mage.game.Game; import mage.game.events.EntersTheBattlefieldEvent; @@ -45,9 +44,9 @@ public class DevourEffect extends ReplacementEffectImpl { // "creature" is a special case as the rule will not mention it. // // 's' will be added to pluralize, so far so good with the current text generation. - private final FilterControlledPermanent filterDevoured; + private final FilterPermanent filterDevoured; - public DevourEffect(int devourFactor, FilterControlledPermanent filterDevoured) { + public DevourEffect(int devourFactor, FilterPermanent filterDevoured) { super(Duration.EndOfGame, Outcome.Detriment); this.devourFactor = devourFactor; this.filterDevoured = filterDevoured; @@ -81,11 +80,8 @@ public class DevourEffect extends ReplacementEffectImpl { if (creature == null || controller == null) { return false; } - - FilterControlledPermanent filter = new FilterControlledPermanent(filterDevoured.getMessage() + "s to devour"); - for (Predicate predicate : filterDevoured.getPredicates()) { - filter.add(predicate); - } + FilterPermanent filter = filterDevoured.copy(); + filter.setMessage(filterDevoured.getMessage() + "s (to devour)"); filter.add(AnotherPredicate.instance); Target target = new TargetSacrifice(1, Integer.MAX_VALUE, filter); @@ -142,9 +138,9 @@ public class DevourEffect extends ReplacementEffectImpl { text += devourFactor; } - text += " (As this enters the battlefield, you may sacrifice any number of " + text += " (As this enters, you may sacrifice any number of " + filterMessage + "s. " - + "This creature enters the battlefield with "; + + "This creature enters with "; if (devourFactor == Integer.MAX_VALUE) { text += "X +1/+1 counters on it for each of those creatures"; diff --git a/Mage/src/main/java/mage/abilities/keyword/DevourAbility.java b/Mage/src/main/java/mage/abilities/keyword/DevourAbility.java index a3b42f8807a..7f6648bc98b 100644 --- a/Mage/src/main/java/mage/abilities/keyword/DevourAbility.java +++ b/Mage/src/main/java/mage/abilities/keyword/DevourAbility.java @@ -1,11 +1,10 @@ - package mage.abilities.keyword; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.common.DevourEffect; import mage.constants.Zone; +import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.common.FilterControlledPermanent; /** * 502.82. Devour @@ -45,12 +44,12 @@ import mage.filter.common.FilterControlledPermanent; */ public class DevourAbility extends SimpleStaticAbility { - private static final FilterControlledPermanent filterCreature = new FilterControlledCreaturePermanent("creature"); + private static final FilterPermanent filterCreature = new FilterControlledCreaturePermanent("creature"); // Integer.MAX_VALUE is a special value // for "devour X, where X is the number of devored permanents" // see DevourEffect for the full details. - public static DevourAbility DevourX() { + public static DevourAbility devourX() { return new DevourAbility(Integer.MAX_VALUE); } @@ -58,7 +57,7 @@ public class DevourAbility extends SimpleStaticAbility { this(devourFactor, filterCreature); } - public DevourAbility(int devourFactor, FilterControlledPermanent filterDevoured) { + public DevourAbility(int devourFactor, FilterPermanent filterDevoured) { super(Zone.ALL, new DevourEffect(devourFactor, filterDevoured)); }