From 43c45238d0711189b80495f648ccfe287f7797ee Mon Sep 17 00:00:00 2001 From: Susucre <34709007+Susucre@users.noreply.github.com> Date: Sun, 25 May 2025 18:58:53 +0200 Subject: [PATCH] refactor and test 'greatest [quality] among [permanent filter]' (#13666) --- Mage.Sets/src/mage/cards/a/AbzanMonument.java | 10 +- .../src/mage/cards/a/AcceleratedMutation.java | 18 +- .../src/mage/cards/a/AlenaKessigTrapper.java | 104 +++------- .../src/mage/cards/a/AmbitiousDragonborn.java | 10 +- Mage.Sets/src/mage/cards/a/ArborAdherent.java | 6 +- .../src/mage/cards/a/ArniBrokenbrow.java | 18 +- .../src/mage/cards/a/ArniSlaysTheTroll.java | 6 +- .../src/mage/cards/b/BaruWurmspeaker.java | 57 ++---- .../src/mage/cards/b/BighornerRancher.java | 11 +- Mage.Sets/src/mage/cards/b/BoonOfBoseiju.java | 47 +---- .../src/mage/cards/b/BouncersBeatdown.java | 7 +- .../src/mage/cards/c/CabalConditioning.java | 13 +- .../src/mage/cards/c/CraterhoofBehemoth.java | 13 +- .../cards/d/DarettiRocketeerEngineer.java | 48 +---- Mage.Sets/src/mage/cards/d/DeathsOasis.java | 37 +--- .../src/mage/cards/d/DispersalShield.java | 16 +- Mage.Sets/src/mage/cards/d/DodgyJalopy.java | 44 +---- .../src/mage/cards/e/EssenceHarvest.java | 69 ++----- .../src/mage/cards/f/FlourishingHunter.java | 6 +- .../src/mage/cards/f/FreelanceMuscle.java | 55 +----- .../src/mage/cards/f/FungalSprouting.java | 10 +- .../src/mage/cards/g/GarrukPrimalHunter.java | 56 +----- .../src/mage/cards/g/GhaltaAndMavren.java | 29 ++- Mage.Sets/src/mage/cards/g/GlintRaker.java | 10 +- Mage.Sets/src/mage/cards/g/GlintWeaver.java | 6 +- .../src/mage/cards/g/GodEternalBontu.java | 12 +- .../src/mage/cards/h/HuatliTheSunsHeart.java | 6 +- .../src/mage/cards/h/HuatliWarriorPoet.java | 12 +- .../src/mage/cards/i/IlluminorSzeras.java | 8 +- .../src/mage/cards/i/ImpetuousProtege.java | 65 +++---- .../src/mage/cards/i/InSearchOfGreatness.java | 24 +-- .../src/mage/cards/k/KarnLegacyReforged.java | 41 +--- .../src/mage/cards/k/KinTreeInvocation.java | 24 +-- .../src/mage/cards/l/LastMarchOfTheEnts.java | 6 +- .../src/mage/cards/l/LukkaBoundToRuin.java | 6 +- .../src/mage/cards/m/MajesticGenesis.java | 2 +- Mage.Sets/src/mage/cards/m/MimingSlime.java | 44 ++--- .../src/mage/cards/m/MoltenMonstrosity.java | 6 +- .../src/mage/cards/m/MonstrousOnslaught.java | 12 +- .../cards/m/MuzzioVisionaryArchitect.java | 36 +--- .../src/mage/cards/o/OneWithTheMachine.java | 17 +- .../src/mage/cards/o/OrcishSiegemaster.java | 7 +- .../mage/cards/o/OverwhelmingStampede.java | 57 ++---- .../src/mage/cards/p/PathbreakerIbex.java | 58 ++---- .../src/mage/cards/p/PeemaAetherSeer.java | 13 +- .../src/mage/cards/p/PeemaTrailblazer.java | 9 +- .../src/mage/cards/p/PriestOfYawgmoth.java | 5 +- .../src/mage/cards/p/PrimeSpeakerZegana.java | 47 +---- Mage.Sets/src/mage/cards/p/PyreswipeHawk.java | 44 +---- .../src/mage/cards/r/RepulsiveMutation.java | 7 +- .../mage/cards/r/ReturnOfTheWildspeaker.java | 46 +---- .../src/mage/cards/r/RewardTheFaithful.java | 13 +- .../src/mage/cards/r/RishkarsExpertise.java | 6 +- .../src/mage/cards/r/RubblebeltRioters.java | 6 +- .../src/mage/cards/r/RushOfKnowledge.java | 15 +- .../src/mage/cards/s/SeasonOfGathering.java | 18 +- .../mage/cards/s/SelvalaHeartOfTheWilds.java | 12 +- Mage.Sets/src/mage/cards/s/SoldeviAdnate.java | 8 +- Mage.Sets/src/mage/cards/s/SpellRupture.java | 69 ++----- .../mage/cards/s/StrengthTestingHammer.java | 6 +- .../mage/cards/t/TetsuoImperialChampion.java | 72 ++----- Mage.Sets/src/mage/cards/t/TheGreatHenge.java | 16 +- .../src/mage/cards/t/TheHungerTideRises.java | 9 - .../src/mage/cards/t/TheSkullsporeNexus.java | 16 +- Mage.Sets/src/mage/cards/t/TheWanderer.java | 12 +- Mage.Sets/src/mage/cards/t/TorrentOfFire.java | 13 +- .../src/mage/cards/t/ToweringGibbon.java | 46 +---- .../src/mage/cards/t/TraverseEternity.java | 65 ++----- .../src/mage/cards/t/TriumphantChomp.java | 4 +- .../src/mage/cards/t/TumbleweedRising.java | 6 +- Mage.Sets/src/mage/cards/t/TuyaBearclaw.java | 49 +---- .../src/mage/cards/t/TyvarThePummeler.java | 9 +- Mage.Sets/src/mage/cards/u/UginsInsight.java | 56 ++---- .../mage/cards/v/Vault87ForcedEvolution.java | 67 +++---- Mage.Sets/src/mage/cards/w/WyllsReversal.java | 6 +- .../single/avr/CraterhoofBehemothTest.java | 58 ++++++ .../cards/single/avr/EssenceHarvestTest.java | 59 ++++++ .../cards/single/bfz/UginsInsightTest.java | 66 +++++++ .../single/cmr/AlenaKessigTrapperTest.java | 46 +++++ .../cns/MuzzioVisionaryArchitectTest.java | 62 ++++++ .../cards/single/dmc/BaruWurmspeakerTest.java | 54 ++++++ .../dmc/TetsuoImperialChampionTest.java | 83 ++++++++ .../cards/single/gtc/SpellRuptureTest.java | 73 ++++++++ .../single/ktk/KinTreeInvocationTest.java | 57 ++++++ .../cards/single/lci/TriumphantChompTest.java | 54 ++++++ .../single/m11/OverwhelmingStampedeTest.java | 57 ++++++ .../cards/single/mom/GhaltaAndMavrenTest.java | 177 ++++++++++++++++++ .../single/scg/AcceleratedMutationTest.java | 39 ++++ .../single/who/TraverseEternityTest.java | 58 ++++++ .../common/GreatestAmongPermanentsValue.java | 117 ++++++++++++ ...estPowerAmongControlledCreaturesValue.java | 53 ------ ...oughnessAmongControlledCreaturesValue.java | 58 ------ .../common/HighestCMCOfPermanentValue.java | 61 ------ .../common/HighestManaValueCount.java | 60 ------ .../main/java/mage/filter/StaticFilters.java | 14 ++ .../permanent/AttachedToSourcePredicate.java | 29 +++ 96 files changed, 1616 insertions(+), 1638 deletions(-) create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/avr/CraterhoofBehemothTest.java create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/avr/EssenceHarvestTest.java create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/bfz/UginsInsightTest.java create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/cmr/AlenaKessigTrapperTest.java create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/cns/MuzzioVisionaryArchitectTest.java create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/dmc/BaruWurmspeakerTest.java create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/dmc/TetsuoImperialChampionTest.java create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/gtc/SpellRuptureTest.java create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/ktk/KinTreeInvocationTest.java create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/lci/TriumphantChompTest.java create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/m11/OverwhelmingStampedeTest.java create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/mom/GhaltaAndMavrenTest.java create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/scg/AcceleratedMutationTest.java create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/who/TraverseEternityTest.java create mode 100644 Mage/src/main/java/mage/abilities/dynamicvalue/common/GreatestAmongPermanentsValue.java delete mode 100644 Mage/src/main/java/mage/abilities/dynamicvalue/common/GreatestPowerAmongControlledCreaturesValue.java delete mode 100644 Mage/src/main/java/mage/abilities/dynamicvalue/common/GreatestToughnessAmongControlledCreaturesValue.java delete mode 100644 Mage/src/main/java/mage/abilities/dynamicvalue/common/HighestCMCOfPermanentValue.java delete mode 100644 Mage/src/main/java/mage/abilities/dynamicvalue/common/HighestManaValueCount.java create mode 100644 Mage/src/main/java/mage/filter/predicate/permanent/AttachedToSourcePredicate.java diff --git a/Mage.Sets/src/mage/cards/a/AbzanMonument.java b/Mage.Sets/src/mage/cards/a/AbzanMonument.java index b9c120e1fba..07bbccebb90 100644 --- a/Mage.Sets/src/mage/cards/a/AbzanMonument.java +++ b/Mage.Sets/src/mage/cards/a/AbzanMonument.java @@ -6,8 +6,9 @@ import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.dynamicvalue.common.GreatestToughnessAmongControlledCreaturesValue; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -53,7 +54,7 @@ public final class AbzanMonument extends CardImpl { ); ability.addCost(new TapSourceCost()); ability.addCost(new SacrificeSourceCost()); - this.addAbility(ability.addHint(GreatestToughnessAmongControlledCreaturesValue.ALL.getHint())); + this.addAbility(ability.addHint(GreatestAmongPermanentsValue.TOUGHNESS_CONTROLLED_CREATURES.getHint())); } private AbzanMonument(final AbzanMonument card) { @@ -85,8 +86,7 @@ class AbzanMonumentEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - return new SpiritXXToken( - GreatestToughnessAmongControlledCreaturesValue.ALL.calculate(game, source, this) - ).putOntoBattlefield(1, game, source); + int value = GreatestAmongPermanentsValue.TOUGHNESS_CONTROLLED_CREATURES.calculate(game, source, this); + return new CreateTokenEffect(new SpiritXXToken(value)).apply(game, source); } } diff --git a/Mage.Sets/src/mage/cards/a/AcceleratedMutation.java b/Mage.Sets/src/mage/cards/a/AcceleratedMutation.java index f7773673194..34f43902b95 100644 --- a/Mage.Sets/src/mage/cards/a/AcceleratedMutation.java +++ b/Mage.Sets/src/mage/cards/a/AcceleratedMutation.java @@ -1,8 +1,6 @@ package mage.cards.a; -import java.util.UUID; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.dynamicvalue.common.HighestManaValueCount; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.common.continuous.BoostTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -10,19 +8,23 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author nigelzor */ public final class AcceleratedMutation extends CardImpl { - private static final DynamicValue xValue = new HighestManaValueCount(); - public AcceleratedMutation(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{G}{G}"); - // Target creature gets +X/+X until end of turn, where X is the highest converted mana cost among permanents you control. - this.getSpellAbility().addEffect(new BoostTargetEffect(xValue, xValue, Duration.EndOfTurn)); + // Target creature gets +X/+X until end of turn, where X is the greatest converted mana cost among permanents you control. + this.getSpellAbility().addEffect(new BoostTargetEffect( + GreatestAmongPermanentsValue.MANAVALUE_CONTROLLED_PERMANENTS, + GreatestAmongPermanentsValue.MANAVALUE_CONTROLLED_PERMANENTS, + Duration.EndOfTurn + )); + this.getSpellAbility().addHint(GreatestAmongPermanentsValue.MANAVALUE_CONTROLLED_PERMANENTS.getHint()); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } diff --git a/Mage.Sets/src/mage/cards/a/AlenaKessigTrapper.java b/Mage.Sets/src/mage/cards/a/AlenaKessigTrapper.java index 42d07882554..5fa4480be29 100644 --- a/Mage.Sets/src/mage/cards/a/AlenaKessigTrapper.java +++ b/Mage.Sets/src/mage/cards/a/AlenaKessigTrapper.java @@ -1,34 +1,38 @@ package mage.cards.a; -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; -import java.util.UUID; - import mage.MageInt; -import mage.MageObject; -import mage.MageObjectReference; import mage.Mana; -import mage.abilities.Ability; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; +import mage.abilities.hint.Hint; +import mage.abilities.keyword.FirstStrikeAbility; import mage.abilities.keyword.PartnerAbility; import mage.abilities.mana.DynamicManaAbility; -import mage.constants.*; -import mage.abilities.keyword.FirstStrikeAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.game.Game; -import mage.game.events.GameEvent; -import mage.game.events.ZoneChangeEvent; -import mage.watchers.Watcher; +import mage.constants.CardType; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.permanent.EnteredThisTurnPredicate; + +import java.util.UUID; /** * @author TheElk801 */ public final class AlenaKessigTrapper extends CardImpl { + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("creatures you control that entered this turn"); + + static { + filter.add(EnteredThisTurnPredicate.instance); + } + + private static final GreatestAmongPermanentsValue xValue = new GreatestAmongPermanentsValue(GreatestAmongPermanentsValue.Quality.Power, filter); + private static final Hint hint = xValue.getHint(); + public AlenaKessigTrapper(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{R}"); @@ -43,9 +47,9 @@ public final class AlenaKessigTrapper extends CardImpl { // {T}: Add an amount of {R} equal to the greatest power among creatures you control that entered the battlefield this turn. this.addAbility(new DynamicManaAbility( - Mana.RedMana(1), AlenaKessigTrapperValue.instance, new TapSourceCost(), "Add an amount of {R} " + - "equal to the greatest power among creatures you control that entered the battlefield this turn." - ), new AlenaKessigTrapperWatcher()); + Mana.RedMana(1), xValue, new TapSourceCost(), + "Add an amount of {R} equal to the greatest power among creatures you control that entered this turn." + ).addHint(hint)); // Partner this.addAbility(PartnerAbility.getInstance()); @@ -59,64 +63,4 @@ public final class AlenaKessigTrapper extends CardImpl { public AlenaKessigTrapper copy() { return new AlenaKessigTrapper(this); } -} - -enum AlenaKessigTrapperValue implements DynamicValue { - instance; - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - AlenaKessigTrapperWatcher watcher = game.getState().getWatcher(AlenaKessigTrapperWatcher.class); - if (watcher == null) { - return 0; - } - return watcher.getPower(sourceAbility.getControllerId(), game); - } - - @Override - public AlenaKessigTrapperValue copy() { - return instance; - } - - @Override - public String getMessage() { - return ""; - } -} - -class AlenaKessigTrapperWatcher extends Watcher { - - private final Set enteredThisTurn = new HashSet<>(); - - public AlenaKessigTrapperWatcher() { - super(WatcherScope.GAME); - } - - @Override - public void watch(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.ZONE_CHANGE - && ((ZoneChangeEvent) event).getToZone() == Zone.BATTLEFIELD) { - enteredThisTurn.add(new MageObjectReference(event.getTargetId(), game)); - } - } - - @Override - public void reset() { - enteredThisTurn.clear(); - super.reset(); - } - - int getPower(UUID playerId, Game game) { - return enteredThisTurn - .stream() - .filter(Objects::nonNull) - .map(mor -> mor.getPermanent(game)) - .filter(Objects::nonNull) - .filter(permanent1 -> permanent1.isCreature(game)) - .filter(permanent -> permanent.isControlledBy(playerId)) - .map(MageObject::getPower) - .mapToInt(MageInt::getValue) - .max() - .orElse(0); - } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/a/AmbitiousDragonborn.java b/Mage.Sets/src/mage/cards/a/AmbitiousDragonborn.java index a306041ae54..5b393e6fca5 100644 --- a/Mage.Sets/src/mage/cards/a/AmbitiousDragonborn.java +++ b/Mage.Sets/src/mage/cards/a/AmbitiousDragonborn.java @@ -39,10 +39,12 @@ public final class AmbitiousDragonborn extends CardImpl { this.toughness = new MageInt(0); // Ambitious Dragonborn enters the battlefield with X +1/+1 counters on it, where X is the greatest power among creatures you control and creature cards in your graveyard. - this.addAbility(new EntersBattlefieldAbility(new AddCountersSourceEffect( - CounterType.P1P1.createInstance(), AmbitiousDragonbornValue.instance, false - ), "with X +1/+1 counters on it, where X is the greatest power " + - "among creatures you control and creature cards in your graveyard")); + this.addAbility(new EntersBattlefieldAbility( + new AddCountersSourceEffect( + CounterType.P1P1.createInstance(), AmbitiousDragonbornValue.instance, false + ), "with X +1/+1 counters on it, where X is the greatest power " + + "among creatures you control and creature cards in your graveyard" + ).addHint(hint)); } private AmbitiousDragonborn(final AmbitiousDragonborn card) { diff --git a/Mage.Sets/src/mage/cards/a/ArborAdherent.java b/Mage.Sets/src/mage/cards/a/ArborAdherent.java index 686eb403b1b..4a54e162e5c 100644 --- a/Mage.Sets/src/mage/cards/a/ArborAdherent.java +++ b/Mage.Sets/src/mage/cards/a/ArborAdherent.java @@ -3,7 +3,7 @@ package mage.cards.a; import mage.MageInt; import mage.Mana; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.dynamicvalue.common.GreatestToughnessAmongControlledCreaturesValue; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.mana.AnyColorManaAbility; import mage.abilities.mana.DynamicManaAbility; import mage.cards.CardImpl; @@ -31,10 +31,10 @@ public final class ArborAdherent extends CardImpl { // {T}: Add X mana of any one color, where X is the greatest toughness among other creatures you control. this.addAbility(new DynamicManaAbility( - Mana.AnyMana(1), GreatestToughnessAmongControlledCreaturesValue.OTHER, + Mana.AnyMana(1), GreatestAmongPermanentsValue.TOUGHNESS_OTHER_CONTROLLED_CREATURES, new TapSourceCost(), "add X mana of any one color, where X is the " + "greatest toughness among other creatures you control", true - ).addHint(GreatestToughnessAmongControlledCreaturesValue.OTHER.getHint())); + ).addHint(GreatestAmongPermanentsValue.TOUGHNESS_OTHER_CONTROLLED_CREATURES.getHint())); } private ArborAdherent(final ArborAdherent card) { diff --git a/Mage.Sets/src/mage/cards/a/ArniBrokenbrow.java b/Mage.Sets/src/mage/cards/a/ArniBrokenbrow.java index eda3f368e66..96fa8919ea6 100644 --- a/Mage.Sets/src/mage/cards/a/ArniBrokenbrow.java +++ b/Mage.Sets/src/mage/cards/a/ArniBrokenbrow.java @@ -4,6 +4,7 @@ import mage.MageInt; import mage.MageObject; import mage.abilities.Ability; import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.SetBasePowerSourceEffect; import mage.abilities.keyword.BoastAbility; @@ -11,11 +12,9 @@ import mage.abilities.keyword.HasteAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; -import mage.filter.StaticFilters; import mage.game.Game; import mage.players.Player; -import java.util.Objects; import java.util.UUID; /** @@ -36,7 +35,8 @@ public final class ArniBrokenbrow extends CardImpl { this.addAbility(HasteAbility.getInstance()); // Boast — {1}: You may change Arni Brokenbrow's base power to 1 plus the greatest power among other creatures you control until end of turn. - this.addAbility(new BoastAbility(new ArniBrokenbrowEffect(), new GenericManaCost(1))); + this.addAbility(new BoastAbility(new ArniBrokenbrowEffect(), new GenericManaCost(1)) + .addHint(GreatestAmongPermanentsValue.POWER_OTHER_CONTROLLED_CREATURES.getHint())); } private ArniBrokenbrow(final ArniBrokenbrow card) { @@ -72,17 +72,7 @@ class ArniBrokenbrowEffect extends OneShotEffect { if (controller == null || mageObject == null) { return false; } - int power = game - .getBattlefield() - .getActivePermanents(StaticFilters.FILTER_CONTROLLED_CREATURE, source.getControllerId(), game) - .stream() - .filter(Objects::nonNull) - .filter(permanent -> !permanent.getId().equals(source.getSourceId()) - || permanent.getZoneChangeCounter(game) != source.getSourceObjectZoneChangeCounter()) - .map(MageObject::getPower) - .mapToInt(MageInt::getValue) - .max() - .orElse(0); + int power = GreatestAmongPermanentsValue.POWER_OTHER_CONTROLLED_CREATURES.calculate(game, source, this); power += 1; if (controller.chooseUse(outcome, "Change base power of " + mageObject.getLogName() + " to " + power + " until end of turn?", source, game diff --git a/Mage.Sets/src/mage/cards/a/ArniSlaysTheTroll.java b/Mage.Sets/src/mage/cards/a/ArniSlaysTheTroll.java index 23a599352f2..5e937c7469f 100644 --- a/Mage.Sets/src/mage/cards/a/ArniSlaysTheTroll.java +++ b/Mage.Sets/src/mage/cards/a/ArniSlaysTheTroll.java @@ -2,7 +2,7 @@ package mage.cards.a; import mage.Mana; import mage.abilities.common.SagaAbility; -import mage.abilities.dynamicvalue.common.GreatestPowerAmongControlledCreaturesValue; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.common.FightTargetsEffect; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; @@ -58,11 +58,11 @@ public final class ArniSlaysTheTroll extends CardImpl { // III — You gain life equal to the greatest power among creatures you control. sagaAbility.addChapterEffect(this, SagaChapter.CHAPTER_III, - new GainLifeEffect(GreatestPowerAmongControlledCreaturesValue.instance, + new GainLifeEffect(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES, "You gain life equal to the greatest power among creatures you control" ) ); - sagaAbility.addHint(GreatestPowerAmongControlledCreaturesValue.getHint()); + sagaAbility.addHint(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.getHint()); this.addAbility(sagaAbility); } diff --git a/Mage.Sets/src/mage/cards/b/BaruWurmspeaker.java b/Mage.Sets/src/mage/cards/b/BaruWurmspeaker.java index c76fb6d540b..cd7ecf16294 100644 --- a/Mage.Sets/src/mage/cards/b/BaruWurmspeaker.java +++ b/Mage.Sets/src/mage/cards/b/BaruWurmspeaker.java @@ -1,28 +1,26 @@ package mage.cards.b; import mage.MageInt; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.CostAdjuster; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.InfoEffect; import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; import mage.abilities.hint.Hint; -import mage.abilities.hint.ValueHint; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.filter.FilterPermanent; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; import mage.filter.common.FilterControlledCreaturePermanent; -import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.token.Wurm44Token; import mage.util.CardUtil; @@ -34,11 +32,9 @@ import java.util.UUID; */ public final class BaruWurmspeaker extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(SubType.WURM, "Wurms"); - private static final FilterPermanent filter2 = new FilterPermanent(SubType.WURM, ""); - private static final Hint hint = new ValueHint( - "Highest power among Wurms you control", BaruWurmspeakerValue.instance - ); + private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent(SubType.WURM, "Wurms you control"); + static final GreatestAmongPermanentsValue xValue = new GreatestAmongPermanentsValue(GreatestAmongPermanentsValue.Quality.Power, filter); + private static final Hint hint = xValue.getHint(); public BaruWurmspeaker(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{G}{G}"); @@ -54,7 +50,7 @@ public final class BaruWurmspeaker extends CardImpl { 2, 2, Duration.WhileOnBattlefield, filter, false )); ability.addEffect(new GainAbilityControlledEffect( - TrampleAbility.getInstance(), Duration.WhileOnBattlefield, filter2 + TrampleAbility.getInstance(), Duration.WhileOnBattlefield, filter ).setText("and have trample")); this.addAbility(ability); @@ -64,6 +60,7 @@ public final class BaruWurmspeaker extends CardImpl { ability.addEffect(new InfoEffect("this ability costs {X} less to activate, " + "where X is the greatest power among Wurms you control")); ability.setCostAdjuster(BaruWurmspeakerAdjuster.instance); + ability.addHint(hint); this.addAbility(ability); } @@ -77,44 +74,12 @@ public final class BaruWurmspeaker extends CardImpl { } } -enum BaruWurmspeakerValue implements DynamicValue { - instance; - private static final FilterPermanent filter = new FilterControlledCreaturePermanent(SubType.WURM); - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - return game - .getBattlefield() - .getActivePermanents(filter, sourceAbility.getControllerId(), sourceAbility, game) - .stream() - .map(MageObject::getPower) - .mapToInt(MageInt::getValue) - .max() - .orElse(0); - } - - @Override - public BaruWurmspeakerValue copy() { - return this; - } - - @Override - public String getMessage() { - return ""; - } - - @Override - public String toString() { - return ""; - } -} - enum BaruWurmspeakerAdjuster implements CostAdjuster { instance; @Override public void reduceCost(Ability ability, Game game) { - int value = BaruWurmspeakerValue.instance.calculate(game, ability, null); + int value = BaruWurmspeaker.xValue.calculate(game, ability, null); if (value > 0) { CardUtil.reduceCost(ability, value); } diff --git a/Mage.Sets/src/mage/cards/b/BighornerRancher.java b/Mage.Sets/src/mage/cards/b/BighornerRancher.java index e5967f1599f..5e5f0ec2375 100644 --- a/Mage.Sets/src/mage/cards/b/BighornerRancher.java +++ b/Mage.Sets/src/mage/cards/b/BighornerRancher.java @@ -5,8 +5,7 @@ import mage.Mana; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.dynamicvalue.common.GreatestPowerAmongControlledCreaturesValue; -import mage.abilities.dynamicvalue.common.GreatestToughnessAmongControlledCreaturesValue; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.keyword.VigilanceAbility; import mage.abilities.mana.DynamicManaAbility; @@ -35,16 +34,16 @@ public final class BighornerRancher extends CardImpl { // {T}: Add an amount of {G} equal to the greatest power among creatures you control. this.addAbility(new DynamicManaAbility( - Mana.GreenMana(1), GreatestPowerAmongControlledCreaturesValue.instance, new TapSourceCost(), + Mana.GreenMana(1), GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES, new TapSourceCost(), "Add an amount of {G} equal to the greatest power among creatures you control." - ).addHint(GreatestPowerAmongControlledCreaturesValue.getHint())); + ).addHint(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.getHint())); // Sacrifice Bighorner Rancher: You gain life equal to the greatest toughness among other creatures you control. this.addAbility(new SimpleActivatedAbility( - new GainLifeEffect(GreatestToughnessAmongControlledCreaturesValue.OTHER) + new GainLifeEffect(GreatestAmongPermanentsValue.TOUGHNESS_OTHER_CONTROLLED_CREATURES) .setText("You gain life equal to the greatest toughness among other creatures you control."), new SacrificeSourceCost() - ).addHint(GreatestToughnessAmongControlledCreaturesValue.OTHER.getHint())); + ).addHint(GreatestAmongPermanentsValue.TOUGHNESS_OTHER_CONTROLLED_CREATURES.getHint())); } private BighornerRancher(final BighornerRancher card) { diff --git a/Mage.Sets/src/mage/cards/b/BoonOfBoseiju.java b/Mage.Sets/src/mage/cards/b/BoonOfBoseiju.java index 00dade8105d..ae213feda49 100644 --- a/Mage.Sets/src/mage/cards/b/BoonOfBoseiju.java +++ b/Mage.Sets/src/mage/cards/b/BoonOfBoseiju.java @@ -1,19 +1,12 @@ package mage.cards.b; -import mage.MageObject; -import mage.abilities.Ability; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.common.UntapTargetEffect; import mage.abilities.effects.common.continuous.BoostTargetEffect; -import mage.abilities.hint.Hint; -import mage.abilities.hint.ValueHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.filter.StaticFilters; -import mage.game.Game; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -28,11 +21,13 @@ public final class BoonOfBoseiju extends CardImpl { // Target creature gets +X/+X until end of turn, where X is the greatest mana value among permanents you control. Untap that creature. this.getSpellAbility().addEffect(new BoostTargetEffect( - BoonOfBoseijuValue.instance, BoonOfBoseijuValue.instance, Duration.EndOfTurn + GreatestAmongPermanentsValue.MANAVALUE_CONTROLLED_PERMANENTS, + GreatestAmongPermanentsValue.MANAVALUE_CONTROLLED_PERMANENTS, + Duration.EndOfTurn )); + this.getSpellAbility().addHint(GreatestAmongPermanentsValue.MANAVALUE_CONTROLLED_PERMANENTS.getHint()); this.getSpellAbility().addEffect(new UntapTargetEffect().setText("Untap it")); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - this.getSpellAbility().addHint(BoonOfBoseijuValue.getHint()); } private BoonOfBoseiju(final BoonOfBoseiju card) { @@ -43,36 +38,4 @@ public final class BoonOfBoseiju extends CardImpl { public BoonOfBoseiju copy() { return new BoonOfBoseiju(this); } -} - -enum BoonOfBoseijuValue implements DynamicValue { - instance; - private static final Hint hint = new ValueHint("The greatest mana value among permanents you control", instance); - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - return game.getBattlefield().getActivePermanents( - StaticFilters.FILTER_CONTROLLED_PERMANENT, - sourceAbility.getControllerId(), sourceAbility, game - ).stream().mapToInt(MageObject::getManaValue).max().orElse(0); - } - - @Override - public BoonOfBoseijuValue copy() { - return this; - } - - @Override - public String getMessage() { - return "the greatest mana value among permanents you control"; - } - - @Override - public String toString() { - return "X"; - } - - public static Hint getHint() { - return hint; - } } \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/b/BouncersBeatdown.java b/Mage.Sets/src/mage/cards/b/BouncersBeatdown.java index e0033956622..14d83654312 100644 --- a/Mage.Sets/src/mage/cards/b/BouncersBeatdown.java +++ b/Mage.Sets/src/mage/cards/b/BouncersBeatdown.java @@ -4,7 +4,7 @@ import mage.ObjectColor; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.SourceTargetsPermanentCondition; -import mage.abilities.dynamicvalue.common.GreatestPowerAmongControlledCreaturesValue; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.ExileTargetIfDiesEffect; import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect; @@ -41,10 +41,11 @@ public final class BouncersBeatdown extends CardImpl { ).setRuleAtTheTop(true)); // Bouncer's Beatdown deals X damage to target creature or planeswalker, where X is the greatest power among creatures you control. If that creature or planeswalker would die this turn, exile it instead. - this.getSpellAbility().addEffect(new DamageTargetEffect(GreatestPowerAmongControlledCreaturesValue.instance)); + this.getSpellAbility().addEffect(new DamageTargetEffect(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES) + .setText("{this} deals X damage to target creature or planeswalker, where X is the greatest power among creatures you control")); + this.getSpellAbility().addHint(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.getHint()); this.getSpellAbility().addTarget(new TargetCreatureOrPlaneswalker()); this.getSpellAbility().addEffect(new ExileTargetIfDiesEffect("creature or planeswalker")); - this.getSpellAbility().addHint(GreatestPowerAmongControlledCreaturesValue.getHint()); } private BouncersBeatdown(final BouncersBeatdown card) { diff --git a/Mage.Sets/src/mage/cards/c/CabalConditioning.java b/Mage.Sets/src/mage/cards/c/CabalConditioning.java index 0e678b17422..e96b59210b1 100644 --- a/Mage.Sets/src/mage/cards/c/CabalConditioning.java +++ b/Mage.Sets/src/mage/cards/c/CabalConditioning.java @@ -1,16 +1,16 @@ package mage.cards.c; -import java.util.UUID; -import mage.abilities.dynamicvalue.common.HighestManaValueCount; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.common.discard.DiscardTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.target.TargetPlayer; +import java.util.UUID; + /** - * * @author nigelzor */ public final class CabalConditioning extends CardImpl { @@ -18,10 +18,11 @@ public final class CabalConditioning extends CardImpl { public CabalConditioning(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{6}{B}"); - // Any number of target players each discard a number of cards equal to the highest converted mana cost among permanents you control. - this.getSpellAbility().addEffect(new DiscardTargetEffect(new HighestManaValueCount()) - .setText("Any number of target players each discard a number of cards equal to the highest mana value among permanents you control.") + // Any number of target players each discard a number of cards equal to the greatest converted mana cost among permanents you control. + this.getSpellAbility().addEffect(new DiscardTargetEffect(GreatestAmongPermanentsValue.MANAVALUE_CONTROLLED_PERMANENTS) + .setText("Any number of target players each discard a number of cards equal to the greatest mana value among permanents you control.") ); + this.getSpellAbility().addHint(GreatestAmongPermanentsValue.MANAVALUE_CONTROLLED_PERMANENTS.getHint()); this.getSpellAbility().addTarget(new TargetPlayer(0, Integer.MAX_VALUE, false)); } diff --git a/Mage.Sets/src/mage/cards/c/CraterhoofBehemoth.java b/Mage.Sets/src/mage/cards/c/CraterhoofBehemoth.java index 286e0873fd6..61f68c52bed 100644 --- a/Mage.Sets/src/mage/cards/c/CraterhoofBehemoth.java +++ b/Mage.Sets/src/mage/cards/c/CraterhoofBehemoth.java @@ -14,8 +14,7 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.constants.TargetController; -import mage.filter.common.FilterCreaturePermanent; +import mage.filter.StaticFilters; import java.util.UUID; @@ -24,12 +23,6 @@ import java.util.UUID; */ public final class CraterhoofBehemoth extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); - - static { - filter.add(TargetController.YOU.getControllerPredicate()); - } - public CraterhoofBehemoth(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{G}{G}{G}"); this.subtype.add(SubType.BEAST); @@ -41,11 +34,11 @@ public final class CraterhoofBehemoth extends CardImpl { // When Craterhoof Behemoth enters the battlefield, creatures you control gain trample and get +X/+X until end of turn, where X is the number of creatures you control. Ability ability = new EntersBattlefieldTriggeredAbility(new GainAbilityControlledEffect( - TrampleAbility.getInstance(), Duration.EndOfTurn, filter + TrampleAbility.getInstance(), Duration.EndOfTurn, StaticFilters.FILTER_CONTROLLED_CREATURES ).setText("creatures you control gain trample")); ability.addEffect(new BoostControlledEffect( CreaturesYouControlCount.instance, CreaturesYouControlCount.instance, - Duration.EndOfTurn, filter, false + Duration.EndOfTurn, StaticFilters.FILTER_CONTROLLED_CREATURES, false ).setText("and get +X/+X until end of turn, where X is the number of creatures you control")); ability.addHint(CreaturesYouControlHint.instance); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/d/DarettiRocketeerEngineer.java b/Mage.Sets/src/mage/cards/d/DarettiRocketeerEngineer.java index 3828e0ef204..ebc07004f7f 100644 --- a/Mage.Sets/src/mage/cards/d/DarettiRocketeerEngineer.java +++ b/Mage.Sets/src/mage/cards/d/DarettiRocketeerEngineer.java @@ -1,13 +1,11 @@ package mage.cards.d; import mage.MageInt; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldOrAttacksSourceTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.common.SacrificeTargetCost; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.common.DoIfCostPaid; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.abilities.effects.common.continuous.SetBasePowerSourceEffect; @@ -16,8 +14,8 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; +import mage.constants.Zone; import mage.filter.StaticFilters; -import mage.game.Game; import mage.target.common.TargetCardInYourGraveyard; import java.util.UUID; @@ -37,8 +35,11 @@ public final class DarettiRocketeerEngineer extends CardImpl { this.toughness = new MageInt(5); // Daretti's power is equal to the greatest mana value among artifacts you control. - this.addAbility(new SimpleStaticAbility(new SetBasePowerSourceEffect(DarettiRocketeerEngineerValue.instance) - .setText("{this}'s power is equal to the greatest mana value among artifacts you control"))); + this.addAbility(new SimpleStaticAbility( + Zone.ALL, + new SetBasePowerSourceEffect(GreatestAmongPermanentsValue.MANAVALUE_CONTROLLED_ARTIFACTS) + .setText("{this}'s power is equal to the greatest mana value among artifacts you control") + )); // Whenever Daretti enters or attacks, choose target artifact card in your graveyard. You may sacrifice an artifact. If you do, return the chosen card to the battlefield. Ability ability = new EntersBattlefieldOrAttacksSourceTriggeredAbility(new DoIfCostPaid( @@ -57,37 +58,4 @@ public final class DarettiRocketeerEngineer extends CardImpl { public DarettiRocketeerEngineer copy() { return new DarettiRocketeerEngineer(this); } -} - -enum DarettiRocketeerEngineerValue implements DynamicValue { - instance; - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - return game - .getBattlefield() - .getActivePermanents( - StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT, - sourceAbility.getControllerId(), sourceAbility, game - ) - .stream() - .mapToInt(MageObject::getManaValue) - .max() - .orElse(0); - } - - @Override - public DarettiRocketeerEngineerValue copy() { - return this; - } - - @Override - public String getMessage() { - return ""; - } - - @Override - public String toString() { - return "1"; - } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/d/DeathsOasis.java b/Mage.Sets/src/mage/cards/d/DeathsOasis.java index c156ca86a39..d55628c7463 100644 --- a/Mage.Sets/src/mage/cards/d/DeathsOasis.java +++ b/Mage.Sets/src/mage/cards/d/DeathsOasis.java @@ -5,8 +5,7 @@ import mage.abilities.common.DiesCreatureTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.MillCardsControllerEffect; @@ -23,7 +22,6 @@ import mage.filter.predicate.mageobject.ManaValuePredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeEvent; -import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetCard; import mage.target.common.TargetCardInYourGraveyard; @@ -41,12 +39,13 @@ public final class DeathsOasis extends CardImpl { // Whenever a nontoken creature you control dies, put the top two cards of your library into your graveyard. Then return a creature card with lesser converted mana cost than the creature that died from the graveyard to your hand. this.addAbility(new DeathsOasisTriggeredAbility()); - // {1}, Sacrifice Death's Oasis: You gain life equal to the greatest converted mana cost among creatures you control. + // {1}, Sacrifice Death's Oasis: You gain life equal to the greatest mana value among creatures you control. Ability ability = new SimpleActivatedAbility( - new GainLifeEffect(DeathsOasisValue.instance) + new GainLifeEffect(GreatestAmongPermanentsValue.MANAVALUE_CONTROLLED_CREATURES) .setText("you gain life equal to the highest mana value among creatures you control"), new GenericManaCost(1) ); + ability.addHint(GreatestAmongPermanentsValue.MANAVALUE_CONTROLLED_CREATURES.getHint()); ability.addCost(new SacrificeSourceCost()); this.addAbility(ability); } @@ -132,30 +131,4 @@ class DeathsOasisEffect extends OneShotEffect { } return player.moveCards(game.getCard(target.getFirstTarget()), Zone.HAND, source, game); } -} - -enum DeathsOasisValue implements DynamicValue { - instance; - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - return game - .getBattlefield() - .getAllActivePermanents(sourceAbility.getControllerId()) - .stream() - .filter(permanent -> permanent.isCreature(game)) - .mapToInt(Permanent::getManaValue) - .max() - .orElse(0); - } - - @Override - public DynamicValue copy() { - return this; - } - - @Override - public String getMessage() { - return "1"; - } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/d/DispersalShield.java b/Mage.Sets/src/mage/cards/d/DispersalShield.java index 172ca4223c3..2d20aae1c4d 100644 --- a/Mage.Sets/src/mage/cards/d/DispersalShield.java +++ b/Mage.Sets/src/mage/cards/d/DispersalShield.java @@ -1,9 +1,7 @@ package mage.cards.d; -import java.util.UUID; import mage.abilities.Ability; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.dynamicvalue.common.HighestManaValueCount; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -13,17 +11,19 @@ import mage.game.Game; import mage.game.stack.Spell; import mage.target.TargetSpell; +import java.util.UUID; + /** - * * @author nigelzor */ public final class DispersalShield extends CardImpl { public DispersalShield(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}"); // Counter target spell if its converted mana cost is less than or equal to the highest converted mana cost among permanents you control. this.getSpellAbility().addEffect(new DispersalShieldEffect()); + this.getSpellAbility().addHint(GreatestAmongPermanentsValue.MANAVALUE_CONTROLLED_PERMANENTS.getHint()); this.getSpellAbility().addTarget(new TargetSpell()); } @@ -41,7 +41,7 @@ class DispersalShieldEffect extends OneShotEffect { DispersalShieldEffect() { super(Outcome.Detriment); - staticText = "Counter target spell if its mana value is less than or equal to the highest mana value among permanents you control"; + staticText = "Counter target spell if its mana value is less than or equal to the greatest mana value among permanents you control"; } private DispersalShieldEffect(final DispersalShieldEffect effect) { @@ -55,9 +55,9 @@ class DispersalShieldEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - DynamicValue amount = new HighestManaValueCount(); + int amount = GreatestAmongPermanentsValue.MANAVALUE_CONTROLLED_PERMANENTS.calculate(game, source, this); Spell spell = game.getStack().getSpell(getTargetPointer().getFirst(game, source)); - if (spell != null && spell.getManaValue() <= amount.calculate(game, source, this)) { + if (spell != null && spell.getManaValue() <= amount) { return game.getStack().counter(source.getFirstTarget(), source, game); } return false; diff --git a/Mage.Sets/src/mage/cards/d/DodgyJalopy.java b/Mage.Sets/src/mage/cards/d/DodgyJalopy.java index 07c4a72fcec..40d3992ca65 100644 --- a/Mage.Sets/src/mage/cards/d/DodgyJalopy.java +++ b/Mage.Sets/src/mage/cards/d/DodgyJalopy.java @@ -1,12 +1,9 @@ package mage.cards.d; import mage.MageInt; -import mage.MageObject; -import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.common.continuous.SetBasePowerSourceEffect; import mage.abilities.keyword.CrewAbility; import mage.abilities.keyword.ScavengeAbility; @@ -16,8 +13,6 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; -import mage.filter.StaticFilters; -import mage.game.Game; import java.util.UUID; @@ -36,10 +31,12 @@ public final class DodgyJalopy extends CardImpl { // Trample this.addAbility(TrampleAbility.getInstance()); - // Dodgy Jalopy's power is equal to the highest mana value among creatures you control. + // Dodgy Jalopy's power is equal to the greatest mana value among creatures you control. this.addAbility(new SimpleStaticAbility( - Zone.ALL, new SetBasePowerSourceEffect(DodgyJalopyValue.instance) - )); + Zone.ALL, + new SetBasePowerSourceEffect(GreatestAmongPermanentsValue.MANAVALUE_CONTROLLED_CREATURES) + .setText("{this}'s power is equal to the greatest mana value among creatures you control.") + ).addHint(GreatestAmongPermanentsValue.MANAVALUE_CONTROLLED_CREATURES.getHint())); // Crew 3 this.addAbility(new CrewAbility(3)); @@ -56,31 +53,4 @@ public final class DodgyJalopy extends CardImpl { public DodgyJalopy copy() { return new DodgyJalopy(this); } -} - -enum DodgyJalopyValue implements DynamicValue { - instance; - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - return game - .getBattlefield() - .getActivePermanents( - StaticFilters.FILTER_CONTROLLED_CREATURE, - sourceAbility.getControllerId(), sourceAbility, game - ).stream() - .mapToInt(MageObject::getManaValue) - .max() - .orElse(0); - } - - @Override - public DodgyJalopyValue copy() { - return this; - } - - @Override - public String getMessage() { - return "the highest mana value among creatures you control"; - } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/e/EssenceHarvest.java b/Mage.Sets/src/mage/cards/e/EssenceHarvest.java index 644d9f273ce..ab504b529fd 100644 --- a/Mage.Sets/src/mage/cards/e/EssenceHarvest.java +++ b/Mage.Sets/src/mage/cards/e/EssenceHarvest.java @@ -1,21 +1,16 @@ package mage.cards.e; -import java.util.List; -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; +import mage.abilities.effects.common.GainLifeEffect; +import mage.abilities.effects.common.LoseLifeTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; -import mage.filter.StaticFilters; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; import mage.target.TargetPlayer; +import java.util.UUID; + /** - * * @author North */ public final class EssenceHarvest extends CardImpl { @@ -24,7 +19,15 @@ public final class EssenceHarvest extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{B}"); // Target player loses X life and you gain X life, where X is the greatest power among creatures you control. - this.getSpellAbility().addEffect(new EssenceHarvestEffect()); + this.getSpellAbility().addEffect( + new LoseLifeTargetEffect(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES) + .setText("target player loses X life") + ); + this.getSpellAbility().addEffect( + new GainLifeEffect(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES) + .setText("and you gain X life, where X is the greatest power among creatures you control") + ); + this.getSpellAbility().addHint(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.getHint()); this.getSpellAbility().addTarget(new TargetPlayer()); } @@ -36,46 +39,4 @@ public final class EssenceHarvest extends CardImpl { public EssenceHarvest copy() { return new EssenceHarvest(this); } -} - -class EssenceHarvestEffect extends OneShotEffect { - - EssenceHarvestEffect() { - super(Outcome.Damage); - this.staticText = "Target player loses X life and you gain X life, where X is the greatest power among creatures you control"; - } - - private EssenceHarvestEffect(final EssenceHarvestEffect effect) { - super(effect); - } - - @Override - public EssenceHarvestEffect copy() { - return new EssenceHarvestEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - Player targetPlayer = game.getPlayer(source.getFirstTarget()); - if (controller != null - && targetPlayer != null) { - List creatures = game.getBattlefield().getAllActivePermanents( - StaticFilters.FILTER_PERMANENT_CREATURE, controller.getId(), game); - int amount = 0; - for (Permanent creature : creatures) { - int power = creature.getPower().getValue(); - if (amount < power) { - amount = power; - } - } - - if (amount > 0) { - targetPlayer.loseLife(amount, game, source, false); - controller.gainLife(amount, game, source); - } - return true; - } - return false; - } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/f/FlourishingHunter.java b/Mage.Sets/src/mage/cards/f/FlourishingHunter.java index 89fc37c1059..e72a2a0ff26 100644 --- a/Mage.Sets/src/mage/cards/f/FlourishingHunter.java +++ b/Mage.Sets/src/mage/cards/f/FlourishingHunter.java @@ -2,7 +2,7 @@ package mage.cards.f; import mage.MageInt; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.dynamicvalue.common.GreatestToughnessAmongControlledCreaturesValue; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.common.GainLifeEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -26,9 +26,9 @@ public final class FlourishingHunter extends CardImpl { // When Flourishing Hunter enters the battlefield, you gain life equal to the greatest toughness among other creatures you control. this.addAbility(new EntersBattlefieldTriggeredAbility( - new GainLifeEffect(GreatestToughnessAmongControlledCreaturesValue.OTHER) + new GainLifeEffect(GreatestAmongPermanentsValue.TOUGHNESS_OTHER_CONTROLLED_CREATURES) .setText("you gain life equal to the greatest toughness among other creatures you control") - ).addHint(GreatestToughnessAmongControlledCreaturesValue.OTHER.getHint())); + ).addHint(GreatestAmongPermanentsValue.TOUGHNESS_OTHER_CONTROLLED_CREATURES.getHint())); } private FlourishingHunter(final FlourishingHunter card) { diff --git a/Mage.Sets/src/mage/cards/f/FreelanceMuscle.java b/Mage.Sets/src/mage/cards/f/FreelanceMuscle.java index 84c193b2beb..8d7939504fc 100644 --- a/Mage.Sets/src/mage/cards/f/FreelanceMuscle.java +++ b/Mage.Sets/src/mage/cards/f/FreelanceMuscle.java @@ -1,20 +1,14 @@ package mage.cards.f; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.AttacksOrBlocksTriggeredAbility; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.common.continuous.BoostSourceEffect; -import mage.abilities.hint.Hint; -import mage.abilities.hint.ValueHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.filter.StaticFilters; -import mage.game.Game; import java.util.UUID; @@ -23,10 +17,6 @@ import java.util.UUID; */ public final class FreelanceMuscle extends CardImpl { - private static final Hint hint = new ValueHint( - "Greatest power and/or toughness among other creatures you control", FreelanceMuscleValue.instance - ); - public FreelanceMuscle(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}"); @@ -37,9 +27,10 @@ public final class FreelanceMuscle extends CardImpl { // Whenever Freelance Muscle attacks or blocks, it gets +X/+X until end of turn, where X is the greatest power and/or toughness among other creatures you control. this.addAbility(new AttacksOrBlocksTriggeredAbility(new BoostSourceEffect( - FreelanceMuscleValue.instance, FreelanceMuscleValue.instance, + GreatestAmongPermanentsValue.POWER_OR_TOUGHNESS_OTHER_CONTROLLED_CREATURES, + GreatestAmongPermanentsValue.POWER_OR_TOUGHNESS_OTHER_CONTROLLED_CREATURES, Duration.EndOfTurn, "it" - ), false).addHint(hint)); + ), false).addHint(GreatestAmongPermanentsValue.POWER_OR_TOUGHNESS_OTHER_CONTROLLED_CREATURES.getHint())); } private FreelanceMuscle(final FreelanceMuscle card) { @@ -50,40 +41,4 @@ public final class FreelanceMuscle extends CardImpl { public FreelanceMuscle copy() { return new FreelanceMuscle(this); } -} - -enum FreelanceMuscleValue implements DynamicValue { - instance; - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - return game - .getBattlefield() - .getActivePermanents( - StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE, - sourceAbility.getControllerId(), sourceAbility, game - ) - .stream() - .mapToInt(permanent -> Math.max( - permanent.getPower().getValue(), - permanent.getToughness().getValue() - )) - .max() - .orElse(0); - } - - @Override - public FreelanceMuscleValue copy() { - return this; - } - - @Override - public String toString() { - return "X"; - } - - @Override - public String getMessage() { - return "the greatest power and/or toughness among other creatures you control"; - } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/f/FungalSprouting.java b/Mage.Sets/src/mage/cards/f/FungalSprouting.java index 0853e074cc3..59c9abc60df 100644 --- a/Mage.Sets/src/mage/cards/f/FungalSprouting.java +++ b/Mage.Sets/src/mage/cards/f/FungalSprouting.java @@ -1,16 +1,16 @@ package mage.cards.f; -import java.util.UUID; -import mage.abilities.dynamicvalue.common.GreatestPowerAmongControlledCreaturesValue; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.common.CreateTokenEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.game.permanent.token.SaprolingToken; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class FungalSprouting extends CardImpl { @@ -19,8 +19,8 @@ public final class FungalSprouting extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{G}"); // Create X 1/1 green Saproling creature tokens, where X is the greatest power among creatures you control. - this.getSpellAbility().addEffect(new CreateTokenEffect(new SaprolingToken(), GreatestPowerAmongControlledCreaturesValue.instance)); - this.getSpellAbility().addHint(GreatestPowerAmongControlledCreaturesValue.getHint()); + this.getSpellAbility().addEffect(new CreateTokenEffect(new SaprolingToken(), GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES)); + this.getSpellAbility().addHint(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.getHint()); } private FungalSprouting(final FungalSprouting card) { diff --git a/Mage.Sets/src/mage/cards/g/GarrukPrimalHunter.java b/Mage.Sets/src/mage/cards/g/GarrukPrimalHunter.java index 3f1e67e7d4f..4cdc493257e 100644 --- a/Mage.Sets/src/mage/cards/g/GarrukPrimalHunter.java +++ b/Mage.Sets/src/mage/cards/g/GarrukPrimalHunter.java @@ -1,28 +1,23 @@ package mage.cards.g; -import java.util.UUID; -import mage.abilities.Ability; import mage.abilities.LoyaltyAbility; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Outcome; import mage.constants.SuperType; -import mage.filter.StaticFilters; import mage.filter.common.FilterControlledLandPermanent; import mage.filter.common.FilterControlledPermanent; -import mage.game.Game; -import mage.game.permanent.Permanent; import mage.game.permanent.token.BeastToken; import mage.game.permanent.token.WurmToken; -import mage.players.Player; + +import java.util.UUID; /** - * * @author Loki */ public final class GarrukPrimalHunter extends CardImpl { @@ -30,7 +25,7 @@ public final class GarrukPrimalHunter extends CardImpl { private static final FilterControlledPermanent filter = new FilterControlledLandPermanent(); public GarrukPrimalHunter(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.PLANESWALKER},"{2}{G}{G}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{2}{G}{G}{G}"); this.supertype.add(SuperType.LEGENDARY); this.subtype.add(SubType.GARRUK); @@ -40,7 +35,10 @@ public final class GarrukPrimalHunter extends CardImpl { this.addAbility(new LoyaltyAbility(new CreateTokenEffect(new BeastToken()), 1)); // -3: Draw cards equal to the greatest power among creatures you control. - this.addAbility(new LoyaltyAbility(new GarrukPrimalHunterEffect(), -3)); + this.addAbility(new LoyaltyAbility( + new DrawCardSourceControllerEffect(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES) + .setText("Draw cards equal to the greatest power among creatures you control"), + -3).addHint(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.getHint())); // -6: Create a 6/6 green Wurm creature token for each land you control. this.addAbility(new LoyaltyAbility(new CreateTokenEffect(new WurmToken(), new PermanentsOnBattlefieldCount(filter)), -6)); @@ -55,38 +53,4 @@ public final class GarrukPrimalHunter extends CardImpl { return new GarrukPrimalHunter(this); } -} - -class GarrukPrimalHunterEffect extends OneShotEffect { - - GarrukPrimalHunterEffect() { - super(Outcome.DrawCard); - staticText = "Draw cards equal to the greatest power among creatures you control"; - } - - private GarrukPrimalHunterEffect(final GarrukPrimalHunterEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player != null) { - int amount = 0; - for (Permanent p : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_CONTROLLED_CREATURE, source.getControllerId(), game)) { - if (p.getPower().getValue() > amount) { - amount = p.getPower().getValue(); - } - } - player.drawCards(amount, source, game); - return true; - } - return false; - } - - @Override - public GarrukPrimalHunterEffect copy() { - return new GarrukPrimalHunterEffect(this); - } - -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/g/GhaltaAndMavren.java b/Mage.Sets/src/mage/cards/g/GhaltaAndMavren.java index de5fa5f2ed6..e2c4e58d68f 100644 --- a/Mage.Sets/src/mage/cards/g/GhaltaAndMavren.java +++ b/Mage.Sets/src/mage/cards/g/GhaltaAndMavren.java @@ -1,14 +1,16 @@ package mage.cards.g; import mage.MageInt; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.common.AttacksWithCreaturesTriggeredAbility; import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CreateTokenEffect; +import mage.abilities.hint.Hint; +import mage.abilities.hint.ValuePositiveHint; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -30,13 +32,17 @@ import java.util.UUID; */ public final class GhaltaAndMavren extends CardImpl { - static final FilterPermanent filter = new FilterAttackingCreature("other attacking creatures"); + private static final FilterPermanent filter = new FilterAttackingCreature("other attacking creatures"); static { filter.add(AnotherPredicate.instance); } - private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filter, null); + static final GreatestAmongPermanentsValue xValue = new GreatestAmongPermanentsValue(GreatestAmongPermanentsValue.Quality.Power, filter); + private static final Hint hint = new ValuePositiveHint("Greatest power among other attacking creatures", xValue); + + private static final DynamicValue xValue2 = new PermanentsOnBattlefieldCount(filter, null); + private static final Hint hint2 = new ValuePositiveHint("Number of other attacking creatures", xValue2); public GhaltaAndMavren(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{G}{G}{W}{W}"); @@ -53,9 +59,11 @@ public final class GhaltaAndMavren extends CardImpl { // Whenever you attack, choose one -- // * Create a tapped and attacking X/X green Dinosaur creature token with trample, where X is the greatest power among other attacking creatures. Ability ability = new AttacksWithCreaturesTriggeredAbility(new GhaltaAndMavrenEffect(), 1); + ability.addHint(hint); // * Create X 1/1 white Vampire creature tokens with lifelink, where X is the number of other attacking creatures. - ability.addMode(new Mode(new CreateTokenEffect(new IxalanVampireToken(), xValue))); + ability.addMode(new Mode(new CreateTokenEffect(new IxalanVampireToken(), xValue2))); + ability.addHint(hint2); this.addAbility(ability); } @@ -88,16 +96,7 @@ class GhaltaAndMavrenEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - int power = game - .getBattlefield() - .getActivePermanents(GhaltaAndMavren.filter, source.getControllerId(), source, game) - .stream() - .map(MageObject::getPower) - .mapToInt(MageInt::getValue) - .max() - .orElse(0); - return new DinosaurXXToken(power).putOntoBattlefield( - 1, game, source, source.getControllerId(), true, true - ); + int power = GhaltaAndMavren.xValue.calculate(game, source, this); + return new CreateTokenEffect(new DinosaurXXToken(power), 1, true, true).apply(game, source); } } diff --git a/Mage.Sets/src/mage/cards/g/GlintRaker.java b/Mage.Sets/src/mage/cards/g/GlintRaker.java index b86899fa2b5..e69c8348d81 100644 --- a/Mage.Sets/src/mage/cards/g/GlintRaker.java +++ b/Mage.Sets/src/mage/cards/g/GlintRaker.java @@ -3,8 +3,7 @@ package mage.cards.g; import mage.MageInt; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.dynamicvalue.common.HighestManaValueCount; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.dynamicvalue.common.SavedDamageValue; import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.common.RevealLibraryPickControllerEffect; @@ -25,8 +24,6 @@ import java.util.UUID; */ public final class GlintRaker extends CardImpl { - private static final DynamicValue xValue = new HighestManaValueCount(StaticFilters.FILTER_PERMANENT_ARTIFACTS); - public GlintRaker(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}"); @@ -39,8 +36,9 @@ public final class GlintRaker extends CardImpl { // Glint Raker gets +X/+0, where X is the highest mana value among artifacts you control. this.addAbility(new SimpleStaticAbility(new BoostSourceEffect( - xValue, StaticValue.get(0), Duration.WhileOnBattlefield - ))); + GreatestAmongPermanentsValue.MANAVALUE_CONTROLLED_ARTIFACTS, + StaticValue.get(0), Duration.WhileOnBattlefield + )).addHint(GreatestAmongPermanentsValue.MANAVALUE_CONTROLLED_ARTIFACTS.getHint())); // Whenever Glint Raker deals combat damage to a player, you may reveal that many cards from the top of your library. Put an artifact card revealed this way into your hand and the rest into your graveyard. this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility( diff --git a/Mage.Sets/src/mage/cards/g/GlintWeaver.java b/Mage.Sets/src/mage/cards/g/GlintWeaver.java index 626cd6f719c..3726a2f60e9 100644 --- a/Mage.Sets/src/mage/cards/g/GlintWeaver.java +++ b/Mage.Sets/src/mage/cards/g/GlintWeaver.java @@ -3,7 +3,7 @@ package mage.cards.g; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.dynamicvalue.common.GreatestToughnessAmongControlledCreaturesValue; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.counter.DistributeCountersEffect; import mage.abilities.keyword.ReachAbility; @@ -32,10 +32,10 @@ public final class GlintWeaver extends CardImpl { // When Glint Weaver enters the battlefield, distribute three +1/+1 counters among one, two, or three target creatures, then you gain life equal to the greatest toughness among creatures you control. Ability ability = new EntersBattlefieldTriggeredAbility(new DistributeCountersEffect()); - ability.addEffect(new GainLifeEffect(GreatestToughnessAmongControlledCreaturesValue.ALL) + ability.addEffect(new GainLifeEffect(GreatestAmongPermanentsValue.TOUGHNESS_CONTROLLED_CREATURES) .setText(", then you gain life equal to the greatest toughness among creatures you control")); ability.addTarget(new TargetCreaturePermanentAmount(3)); - this.addAbility(ability.addHint(GreatestToughnessAmongControlledCreaturesValue.ALL.getHint())); + this.addAbility(ability.addHint(GreatestAmongPermanentsValue.TOUGHNESS_CONTROLLED_CREATURES.getHint())); } private GlintWeaver(final GlintWeaver card) { diff --git a/Mage.Sets/src/mage/cards/g/GodEternalBontu.java b/Mage.Sets/src/mage/cards/g/GodEternalBontu.java index f83e63254a8..b4a0236931f 100644 --- a/Mage.Sets/src/mage/cards/g/GodEternalBontu.java +++ b/Mage.Sets/src/mage/cards/g/GodEternalBontu.java @@ -12,9 +12,7 @@ import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SubType; import mage.constants.SuperType; -import mage.filter.FilterPermanent; -import mage.filter.common.FilterControlledPermanent; -import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.StaticFilters; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; @@ -59,12 +57,6 @@ public final class GodEternalBontu extends CardImpl { class GodEternalBontuEffect extends OneShotEffect { - private static final FilterPermanent filter = new FilterControlledPermanent("other permanents you control"); - - static { - filter.add(AnotherPredicate.instance); - } - GodEternalBontuEffect() { super(Outcome.Benefit); staticText = "sacrifice any number of other permanents, then draw that many cards."; @@ -85,7 +77,7 @@ class GodEternalBontuEffect extends OneShotEffect { if (player == null) { return false; } - Target target = new TargetSacrifice(0, Integer.MAX_VALUE, filter); + Target target = new TargetSacrifice(0, Integer.MAX_VALUE, StaticFilters.FILTER_OTHER_CONTROLLED_PERMANENTS); if (!player.choose(outcome, target, source, game)) { return false; } diff --git a/Mage.Sets/src/mage/cards/h/HuatliTheSunsHeart.java b/Mage.Sets/src/mage/cards/h/HuatliTheSunsHeart.java index 37853526cdd..39419cdb5a4 100644 --- a/Mage.Sets/src/mage/cards/h/HuatliTheSunsHeart.java +++ b/Mage.Sets/src/mage/cards/h/HuatliTheSunsHeart.java @@ -2,7 +2,7 @@ package mage.cards.h; import mage.abilities.LoyaltyAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.dynamicvalue.common.GreatestToughnessAmongControlledCreaturesValue; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.ruleModifying.CombatDamageByToughnessControlledEffect; import mage.cards.CardImpl; @@ -30,9 +30,9 @@ public final class HuatliTheSunsHeart extends CardImpl { // -3: You gain life equal to the greatest toughness among creatures you control. this.addAbility(new LoyaltyAbility(new GainLifeEffect( - GreatestToughnessAmongControlledCreaturesValue.ALL, + GreatestAmongPermanentsValue.TOUGHNESS_CONTROLLED_CREATURES, "You gain life equal to the greatest toughness among creatures you control" - ), -3).addHint(GreatestToughnessAmongControlledCreaturesValue.ALL.getHint())); + ), -3).addHint(GreatestAmongPermanentsValue.TOUGHNESS_CONTROLLED_CREATURES.getHint())); } private HuatliTheSunsHeart(final HuatliTheSunsHeart card) { diff --git a/Mage.Sets/src/mage/cards/h/HuatliWarriorPoet.java b/Mage.Sets/src/mage/cards/h/HuatliWarriorPoet.java index 3fc694b3eb2..6694bc4e6fa 100644 --- a/Mage.Sets/src/mage/cards/h/HuatliWarriorPoet.java +++ b/Mage.Sets/src/mage/cards/h/HuatliWarriorPoet.java @@ -3,7 +3,7 @@ package mage.cards.h; import mage.abilities.Ability; import mage.abilities.LoyaltyAbility; import mage.abilities.dynamicvalue.common.GetXValue; -import mage.abilities.dynamicvalue.common.GreatestPowerAmongControlledCreaturesValue; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CreateTokenEffect; @@ -35,10 +35,12 @@ public final class HuatliWarriorPoet extends CardImpl { this.setStartingLoyalty(3); // +2: You gain life equal to the greatest power among creatures you control. - this.addAbility(new LoyaltyAbility(new GainLifeEffect( - GreatestPowerAmongControlledCreaturesValue.instance, - "You gain life equal to the greatest power among creatures you control" - ), 2).addHint(GreatestPowerAmongControlledCreaturesValue.getHint())); + this.addAbility(new LoyaltyAbility( + new GainLifeEffect( + GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES, + "You gain life equal to the greatest power among creatures you control" + ), 2 + ).addHint(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.getHint())); // 0: Create a 3/3 green Dinosaur creature token with trample. this.addAbility(new LoyaltyAbility(new CreateTokenEffect(new DinosaurToken()), 0)); diff --git a/Mage.Sets/src/mage/cards/i/IlluminorSzeras.java b/Mage.Sets/src/mage/cards/i/IlluminorSzeras.java index 03a334df08f..421b82c30a4 100644 --- a/Mage.Sets/src/mage/cards/i/IlluminorSzeras.java +++ b/Mage.Sets/src/mage/cards/i/IlluminorSzeras.java @@ -6,7 +6,7 @@ import mage.abilities.Ability; import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.dynamicvalue.common.HighestCMCOfPermanentValue; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.dynamicvalue.common.SacrificeCostManaValue; import mage.abilities.mana.DynamicManaAbility; import mage.cards.CardImpl; @@ -24,9 +24,6 @@ import java.util.UUID; public final class IlluminorSzeras extends CardImpl { private static final DynamicValue xValue = SacrificeCostManaValue.CREATURE; - private static final DynamicValue netValue = new HighestCMCOfPermanentValue( - StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE, true - ); public IlluminorSzeras(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{2}{B}"); @@ -39,7 +36,8 @@ public final class IlluminorSzeras extends CardImpl { // Secrets of the Soul -- {T}, Sacrifice another creature: Add an amount of {B} equal to the sacrificed creature's mana value. Ability ability = new DynamicManaAbility( Mana.BlackMana(1), xValue, new TapSourceCost(), "add an amount of {B} " + - "equal to the sacrificed creature's mana value", false, netValue + "equal to the sacrificed creature's mana value", false, + GreatestAmongPermanentsValue.MANAVALUE_OTHER_CONTROLLED_CREATURES ); ability.addCost(new SacrificeTargetCost(StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE)); this.addAbility(ability.withFlavorWord("Secrets of the Soul")); diff --git a/Mage.Sets/src/mage/cards/i/ImpetuousProtege.java b/Mage.Sets/src/mage/cards/i/ImpetuousProtege.java index 09783527e9f..65c3adbec35 100644 --- a/Mage.Sets/src/mage/cards/i/ImpetuousProtege.java +++ b/Mage.Sets/src/mage/cards/i/ImpetuousProtege.java @@ -1,31 +1,40 @@ package mage.cards.i; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; +import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.common.continuous.BoostSourceEffect; +import mage.abilities.hint.Hint; import mage.abilities.keyword.PartnerWithAbility; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.constants.Outcome; +import mage.constants.SubType; import mage.constants.TargetController; +import mage.filter.FilterPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.permanent.TappedPredicate; -import mage.game.Game; -import mage.game.permanent.Permanent; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class ImpetuousProtege extends CardImpl { + private static final FilterPermanent filter = new FilterCreaturePermanent("tapped creatures your opponents control"); + + static { + filter.add(TappedPredicate.TAPPED); + filter.add(TargetController.OPPONENT.getControllerPredicate()); + } + + private static final GreatestAmongPermanentsValue xValue = new GreatestAmongPermanentsValue(GreatestAmongPermanentsValue.Quality.Power, filter); + private static final Hint hint = xValue.getHint(); + public ImpetuousProtege(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{R}"); @@ -38,7 +47,9 @@ public final class ImpetuousProtege extends CardImpl { this.addAbility(new PartnerWithAbility("Proud Mentor")); // Whenever Impetuous Protege attacks, it gets +X/+0 until end of turn, where X is the greatest power among tapped creatures your opponents control - this.addAbility(new AttacksTriggeredAbility(new ImpetuousProtegeEffect(), false)); + this.addAbility(new AttacksTriggeredAbility( + new BoostSourceEffect(xValue, StaticValue.get(0), Duration.EndOfTurn, "it") + ).addHint(hint)); } private ImpetuousProtege(final ImpetuousProtege card) { @@ -49,38 +60,4 @@ public final class ImpetuousProtege extends CardImpl { public ImpetuousProtege copy() { return new ImpetuousProtege(this); } -} - -class ImpetuousProtegeEffect extends OneShotEffect { - - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); - - static { - filter.add(TappedPredicate.TAPPED); - filter.add(TargetController.OPPONENT.getControllerPredicate()); - } - - ImpetuousProtegeEffect() { - super(Outcome.Benefit); - this.staticText = "it gets +X/+0 until end of turn, where X is the greatest power among tapped creatures your opponents control"; - } - - private ImpetuousProtegeEffect(final ImpetuousProtegeEffect effect) { - super(effect); - } - - @Override - public ImpetuousProtegeEffect copy() { - return new ImpetuousProtegeEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - int maxPower = 0; - for (Permanent creature : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) { - maxPower = Math.max(maxPower, creature.getPower().getValue()); - } - game.addEffect(new BoostSourceEffect(maxPower, 0, Duration.EndOfTurn), source); - return true; - } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/i/InSearchOfGreatness.java b/Mage.Sets/src/mage/cards/i/InSearchOfGreatness.java index 13c14cc92ec..ead1c1d471c 100644 --- a/Mage.Sets/src/mage/cards/i/InSearchOfGreatness.java +++ b/Mage.Sets/src/mage/cards/i/InSearchOfGreatness.java @@ -1,10 +1,9 @@ package mage.cards.i; -import mage.MageObject; -import mage.MageObjectReference; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.OneShotEffect; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.cards.CardsImpl; @@ -12,7 +11,6 @@ import mage.constants.CardType; import mage.constants.ComparisonType; import mage.constants.Outcome; import mage.filter.FilterCard; -import mage.filter.StaticFilters; import mage.filter.common.FilterPermanentCard; import mage.filter.predicate.mageobject.ManaValuePredicate; import mage.filter.predicate.mageobject.PermanentPredicate; @@ -20,7 +18,6 @@ import mage.game.Game; import mage.players.Player; import mage.util.CardUtil; -import java.util.Objects; import java.util.UUID; /** @@ -31,12 +28,10 @@ public final class InSearchOfGreatness extends CardImpl { public InSearchOfGreatness(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{G}{G}"); - // At the beginning of your upkeep, you may cast a permanent spell from your hand with converted mana cost - // equal to 1 plus the highest converted mana cost among other permanents you control - // without paying its mana cost. If you don't, scry 1. + // At the beginning of your upkeep, you may cast a permanent spell from your hand with converted mana cost equal to 1 plus the greatest mana value among other permanents you control without paying its mana cost. If you don't, scry 1. this.addAbility(new BeginningOfUpkeepTriggeredAbility( new InSearchOfGreatnessEffect() - )); + ).addHint(GreatestAmongPermanentsValue.MANAVALUE_OTHER_CONTROLLED_PERMANENTS.getHint())); } private InSearchOfGreatness(final InSearchOfGreatness card) { @@ -73,16 +68,7 @@ class InSearchOfGreatnessEffect extends OneShotEffect { if (controller == null) { return false; } - MageObjectReference sourceRef = new MageObjectReference(source); - int manaValue = game - .getBattlefield() - .getActivePermanents(StaticFilters.FILTER_CONTROLLED_PERMANENT, controller.getId(), game) - .stream() - .filter(Objects::nonNull) - .filter(permanent -> !sourceRef.refersTo(permanent, game)) - .mapToInt(MageObject::getManaValue) - .max() - .orElse(0); + int manaValue = GreatestAmongPermanentsValue.MANAVALUE_OTHER_CONTROLLED_PERMANENTS.calculate(game, source, this); FilterCard filter = new FilterPermanentCard(); filter.add(new ManaValuePredicate(ComparisonType.EQUAL_TO, manaValue + 1)); filter.add(PermanentPredicate.instance); diff --git a/Mage.Sets/src/mage/cards/k/KarnLegacyReforged.java b/Mage.Sets/src/mage/cards/k/KarnLegacyReforged.java index ee1a49e88ca..eb6ac42523d 100644 --- a/Mage.Sets/src/mage/cards/k/KarnLegacyReforged.java +++ b/Mage.Sets/src/mage/cards/k/KarnLegacyReforged.java @@ -1,16 +1,14 @@ package mage.cards.k; import mage.MageInt; -import mage.MageObject; import mage.Mana; import mage.abilities.Ability; -import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.SetBasePowerToughnessSourceEffect; import mage.abilities.mana.builder.ConditionalManaBuilder; +import mage.abilities.triggers.BeginningOfUpkeepTriggeredAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; @@ -36,7 +34,7 @@ public final class KarnLegacyReforged extends CardImpl { // Karn, Legacy Reforged's power and toughness are each equal to the greatest mana value among artifacts you control. this.addAbility(new SimpleStaticAbility( - Zone.ALL, new SetBasePowerToughnessSourceEffect(KarnLegacyReforgedValue.instance) + Zone.ALL, new SetBasePowerToughnessSourceEffect(GreatestAmongPermanentsValue.MANAVALUE_CONTROLLED_ARTIFACTS) .setText("{this}'s power and toughness are each equal to the greatest mana value among artifacts you control") )); @@ -56,39 +54,6 @@ public final class KarnLegacyReforged extends CardImpl { } } -enum KarnLegacyReforgedValue implements DynamicValue { - instance; - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - return game - .getBattlefield() - .getActivePermanents( - StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT, - sourceAbility.getControllerId(), sourceAbility, game - ) - .stream() - .mapToInt(MageObject::getManaValue) - .max() - .orElse(0); - } - - @Override - public KarnLegacyReforgedValue copy() { - return this; - } - - @Override - public String getMessage() { - return ""; - } - - @Override - public String toString() { - return "1"; - } -} - class KarnLegacyReforgedEffect extends OneShotEffect { KarnLegacyReforgedEffect() { diff --git a/Mage.Sets/src/mage/cards/k/KinTreeInvocation.java b/Mage.Sets/src/mage/cards/k/KinTreeInvocation.java index 4803e5b4672..7ac3c2e7e52 100644 --- a/Mage.Sets/src/mage/cards/k/KinTreeInvocation.java +++ b/Mage.Sets/src/mage/cards/k/KinTreeInvocation.java @@ -1,22 +1,20 @@ package mage.cards.k; -import java.util.UUID; - import mage.abilities.Ability; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; -import mage.filter.StaticFilters; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.game.permanent.token.SpiritWarriorToken; -import mage.game.permanent.token.Token; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class KinTreeInvocation extends CardImpl { @@ -26,7 +24,7 @@ public final class KinTreeInvocation extends CardImpl { // Create an X/X black and green Spirit Warrior creature token, where X is the greatest toughness among creatures you control. this.getSpellAbility().addEffect(new KinTreeInvocationCreateTokenEffect()); - + this.getSpellAbility().addHint(GreatestAmongPermanentsValue.TOUGHNESS_CONTROLLED_CREATURES.getHint()); } private KinTreeInvocation(final KinTreeInvocation card) { @@ -57,16 +55,8 @@ class KinTreeInvocationCreateTokenEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - int value = Integer.MIN_VALUE; - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), game)) { - if (value < permanent.getToughness().getValue()) { - value = permanent.getToughness().getValue(); - } - } - Token token = new SpiritWarriorToken(value); - token.getAbilities().newId(); // neccessary if token has ability like DevourAbility() - token.putOntoBattlefield(1, game, source, source.getControllerId()); - return true; + int value = GreatestAmongPermanentsValue.TOUGHNESS_CONTROLLED_CREATURES.calculate(game, source, this); + return (new CreateTokenEffect(new SpiritWarriorToken(value))).apply(game, source); } } diff --git a/Mage.Sets/src/mage/cards/l/LastMarchOfTheEnts.java b/Mage.Sets/src/mage/cards/l/LastMarchOfTheEnts.java index 95efa9a8b04..81d3d757f55 100644 --- a/Mage.Sets/src/mage/cards/l/LastMarchOfTheEnts.java +++ b/Mage.Sets/src/mage/cards/l/LastMarchOfTheEnts.java @@ -2,7 +2,7 @@ package mage.cards.l; import mage.abilities.Ability; import mage.abilities.common.CantBeCounteredSourceAbility; -import mage.abilities.dynamicvalue.common.GreatestToughnessAmongControlledCreaturesValue; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; @@ -32,10 +32,10 @@ public final class LastMarchOfTheEnts extends CardImpl { // Draw cards equal to the greatest toughness among creatures you control, then put any number of creature cards from your hand onto the battlefield. this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect( - GreatestToughnessAmongControlledCreaturesValue.ALL + GreatestAmongPermanentsValue.TOUGHNESS_CONTROLLED_CREATURES ).setText("draw cards equal to the greatest toughness among creatures you control")); this.getSpellAbility().addEffect(new LastMarchOfTheEntsEffect()); - this.getSpellAbility().addHint(GreatestToughnessAmongControlledCreaturesValue.ALL.getHint()); + this.getSpellAbility().addHint(GreatestAmongPermanentsValue.TOUGHNESS_CONTROLLED_CREATURES.getHint()); } private LastMarchOfTheEnts(final LastMarchOfTheEnts card) { diff --git a/Mage.Sets/src/mage/cards/l/LukkaBoundToRuin.java b/Mage.Sets/src/mage/cards/l/LukkaBoundToRuin.java index 267548e8f33..de53a52db18 100644 --- a/Mage.Sets/src/mage/cards/l/LukkaBoundToRuin.java +++ b/Mage.Sets/src/mage/cards/l/LukkaBoundToRuin.java @@ -6,7 +6,7 @@ import mage.Mana; import mage.abilities.Ability; import mage.abilities.LoyaltyAbility; import mage.abilities.condition.Condition; -import mage.abilities.dynamicvalue.common.GreatestPowerAmongControlledCreaturesValue; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.DamageMultiEffect; @@ -56,7 +56,7 @@ public class LukkaBoundToRuin extends CardImpl { "where X is the greatest power among creatures you control as you activate this ability."); ability = new LoyaltyAbility(damageMultiEffect, -4); ability.setTargetAdjuster(LukkaBoundToRuinAdjuster.instance); - ability.addHint(GreatestPowerAmongControlledCreaturesValue.getHint()); + ability.addHint(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.getHint()); this.addAbility(ability); } @@ -133,7 +133,7 @@ enum LukkaBoundToRuinAdjuster implements TargetAdjuster { public void adjustTargets(Ability ability, Game game) { // Maximum targets is equal to the damage - as each target need to be assigned at least 1 damage ability.getTargets().clear(); - int xValue = GreatestPowerAmongControlledCreaturesValue.instance.calculate(game, ability, null); + int xValue = GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.calculate(game, ability, null); ability.addTarget(new TargetCreatureOrPlaneswalkerAmount(xValue, 0, xValue)); } } diff --git a/Mage.Sets/src/mage/cards/m/MajesticGenesis.java b/Mage.Sets/src/mage/cards/m/MajesticGenesis.java index ed6effe3c5a..7ee351f9249 100644 --- a/Mage.Sets/src/mage/cards/m/MajesticGenesis.java +++ b/Mage.Sets/src/mage/cards/m/MajesticGenesis.java @@ -26,7 +26,7 @@ public final class MajesticGenesis extends CardImpl { public MajesticGenesis(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{6}{G}{G}"); - // Reveal the top X cards of your library, where X is the highest mana value of a commander you own on the battlefield or in the command zone. You may put any number of a permanent cards from among them onto the battlefield. Put the rest on the bottom of your library in a random order. + // Reveal the top X cards of your library, where X is the greatest mana value of a commander you own on the battlefield or in the command zone. You may put any number of a permanent cards from among them onto the battlefield. Put the rest on the bottom of your library in a random order. this.getSpellAbility().addEffect(new MajesticGenesisEffect()); this.getSpellAbility().addHint(GreatestCommanderManaValue.getHint()); } diff --git a/Mage.Sets/src/mage/cards/m/MimingSlime.java b/Mage.Sets/src/mage/cards/m/MimingSlime.java index 34b3dc27aef..ea4d4bc7311 100644 --- a/Mage.Sets/src/mage/cards/m/MimingSlime.java +++ b/Mage.Sets/src/mage/cards/m/MimingSlime.java @@ -1,31 +1,30 @@ package mage.cards.m; -import java.util.List; -import java.util.UUID; import mage.abilities.Ability; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.CreateTokenEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; -import mage.filter.StaticFilters; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.game.permanent.token.OozeToken; -import mage.players.Player; + +import java.util.UUID; /** - * * @author LevelX2 */ public final class MimingSlime extends CardImpl { public MimingSlime(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{G}"); // Create an X/X green Ooze creature token, where X is the greatest power among creatures you control. - this.getSpellAbility().addEffect(new MimingSlimeEffect()); + this.getSpellAbility().addEffect(new MimingSlimeCreateTokenEffect()); + this.getSpellAbility().addHint(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.getHint()); } private MimingSlime(final MimingSlime card) { @@ -38,40 +37,25 @@ public final class MimingSlime extends CardImpl { } } -class MimingSlimeEffect extends OneShotEffect { +class MimingSlimeCreateTokenEffect extends OneShotEffect { - MimingSlimeEffect() { + MimingSlimeCreateTokenEffect() { super(Outcome.PutCreatureInPlay); staticText = "Create an X/X green Ooze creature token, where X is the greatest power among creatures you control"; } - private MimingSlimeEffect(final MimingSlimeEffect effect) { + private MimingSlimeCreateTokenEffect(final MimingSlimeCreateTokenEffect effect) { super(effect); } @Override - public MimingSlimeEffect copy() { - return new MimingSlimeEffect(this); + public MimingSlimeCreateTokenEffect copy() { + return new MimingSlimeCreateTokenEffect(this); } @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player != null) { - List creatures = game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURES, player.getId(), game); - int amount = 0; - for (Permanent creature : creatures) { - int power = creature.getPower().getValue(); - if (amount < power) { - amount = power; - } - } - OozeToken oozeToken = new OozeToken(); - oozeToken.setPower(amount); - oozeToken.setToughness(amount); - oozeToken.putOntoBattlefield(1, game, source, source.getControllerId()); - return true; - } - return false; + int value = GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.calculate(game, source, this); + return (new CreateTokenEffect(new OozeToken(value, value))).apply(game, source); } } diff --git a/Mage.Sets/src/mage/cards/m/MoltenMonstrosity.java b/Mage.Sets/src/mage/cards/m/MoltenMonstrosity.java index 62642fade32..cc506b91734 100644 --- a/Mage.Sets/src/mage/cards/m/MoltenMonstrosity.java +++ b/Mage.Sets/src/mage/cards/m/MoltenMonstrosity.java @@ -2,7 +2,7 @@ package mage.cards.m; import mage.MageInt; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.dynamicvalue.common.GreatestPowerAmongControlledCreaturesValue; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.common.cost.SpellCostReductionSourceEffect; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; @@ -27,8 +27,8 @@ public final class MoltenMonstrosity extends CardImpl { // This spell costs {X} less to cast, where X is the greatest power among creatures you control. this.addAbility(new SimpleStaticAbility( - Zone.ALL, new SpellCostReductionSourceEffect(GreatestPowerAmongControlledCreaturesValue.instance) - ).setRuleAtTheTop(true).addHint(GreatestPowerAmongControlledCreaturesValue.getHint())); + Zone.ALL, new SpellCostReductionSourceEffect(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES) + ).setRuleAtTheTop(true).addHint(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.getHint())); // Trample this.addAbility(TrampleAbility.getInstance()); diff --git a/Mage.Sets/src/mage/cards/m/MonstrousOnslaught.java b/Mage.Sets/src/mage/cards/m/MonstrousOnslaught.java index 4669d980755..077958bb41b 100644 --- a/Mage.Sets/src/mage/cards/m/MonstrousOnslaught.java +++ b/Mage.Sets/src/mage/cards/m/MonstrousOnslaught.java @@ -1,9 +1,7 @@ package mage.cards.m; -import java.util.UUID; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.dynamicvalue.common.GreatestPowerAmongControlledCreaturesValue; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.Effect; import mage.abilities.effects.common.DamageMultiEffect; import mage.cards.CardImpl; @@ -11,8 +9,9 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.target.common.TargetCreaturePermanentAmount; +import java.util.UUID; + /** - * * @author Styxo */ public final class MonstrousOnslaught extends CardImpl { @@ -21,12 +20,11 @@ public final class MonstrousOnslaught extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{G}{G}"); // Monstrous Onslaught deals X damage divided as you choose among any number of target creatures, where X is the greatest power among creatures you control as you cast Monstrous Onslaught. - DynamicValue xValue = GreatestPowerAmongControlledCreaturesValue.instance; Effect effect = new DamageMultiEffect(); effect.setText("{this} deals X damage divided as you choose among any number of target creatures, where X is the greatest power among creatures you control as you cast this spell"); this.getSpellAbility().addEffect(effect); - this.getSpellAbility().addTarget(new TargetCreaturePermanentAmount(xValue)); - this.getSpellAbility().addHint(GreatestPowerAmongControlledCreaturesValue.getHint()); + this.getSpellAbility().addTarget(new TargetCreaturePermanentAmount(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES)); + this.getSpellAbility().addHint(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.getHint()); } private MonstrousOnslaught(final MonstrousOnslaught card) { diff --git a/Mage.Sets/src/mage/cards/m/MuzzioVisionaryArchitect.java b/Mage.Sets/src/mage/cards/m/MuzzioVisionaryArchitect.java index 9bb7daa6e4c..381244a4efa 100644 --- a/Mage.Sets/src/mage/cards/m/MuzzioVisionaryArchitect.java +++ b/Mage.Sets/src/mage/cards/m/MuzzioVisionaryArchitect.java @@ -1,29 +1,23 @@ package mage.cards.m; -import java.util.List; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.OneShotEffect; import mage.cards.*; -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.SubType; -import mage.constants.SuperType; -import mage.constants.Zone; +import mage.constants.*; import mage.filter.common.FilterArtifactCard; -import mage.filter.common.FilterArtifactPermanent; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetCard; +import java.util.UUID; + /** - * * @author fireshoes */ public final class MuzzioVisionaryArchitect extends CardImpl { @@ -36,9 +30,10 @@ public final class MuzzioVisionaryArchitect extends CardImpl { this.power = new MageInt(1); this.toughness = new MageInt(3); - // {3}{U}, {tap}: Look at the top X cards of your library, where X is the highest converted mana cost among artifacts you control. You may reveal an artifact card from among them and put it onto the battlefield. Put the rest on the bottom of your library in any order. + // {3}{U}, {tap}: Look at the top X cards of your library, where X is the greatest mana value among artifacts you control. You may reveal an artifact card from among them and put it onto the battlefield. Put the rest on the bottom of your library in any order. Ability ability = new SimpleActivatedAbility(new MuzzioVisionaryArchitectEffect(), new ManaCostsImpl<>("{3}{U}")); ability.addCost(new TapSourceCost()); + ability.addHint(GreatestAmongPermanentsValue.MANAVALUE_CONTROLLED_ARTIFACTS.getHint()); this.addAbility(ability); } @@ -56,7 +51,7 @@ class MuzzioVisionaryArchitectEffect extends OneShotEffect { MuzzioVisionaryArchitectEffect() { super(Outcome.Benefit); - this.staticText = "look at the top X cards of your library, where X is the highest mana value among artifacts you control. You may put an artifact card from among them onto the battlefield. Put the rest on the bottom of your library in any order"; + this.staticText = "look at the top X cards of your library, where X is the greatest mana value among artifacts you control. You may put an artifact card from among them onto the battlefield. Put the rest on the bottom of your library in any order"; } private MuzzioVisionaryArchitectEffect(final MuzzioVisionaryArchitectEffect effect) { @@ -74,22 +69,11 @@ class MuzzioVisionaryArchitectEffect extends OneShotEffect { if (controller == null) { return false; } - - int highCMC = 0; - List controlledArtifacts = game.getBattlefield().getAllActivePermanents(new FilterArtifactPermanent(), controller.getId(), game); - for (Permanent permanent : controlledArtifacts) { - if (permanent.getSpellAbility() != null) { - int cmc = permanent.getSpellAbility().getManaCosts().manaValue(); - if (cmc > highCMC) { - highCMC = cmc; - } - } - } - - Cards cards = new CardsImpl(controller.getLibrary().getTopCards(game, highCMC)); + int amount = GreatestAmongPermanentsValue.MANAVALUE_CONTROLLED_ARTIFACTS.calculate(game, source, this); + Cards cards = new CardsImpl(controller.getLibrary().getTopCards(game, amount)); controller.lookAtCards(source, null, cards, game); if (!cards.isEmpty()) { - TargetCard target = new TargetCard(Zone.LIBRARY, new FilterArtifactCard("artifact card to put onto the battlefield")); + TargetCard target = new TargetCard(0, 1, Zone.LIBRARY, new FilterArtifactCard("artifact card to put onto the battlefield")); if (target.canChoose(controller.getId(), source, game) && controller.choose(Outcome.Benefit, cards, target, source, game)) { Card card = cards.get(target.getFirstTarget(), game); if (card != null) { diff --git a/Mage.Sets/src/mage/cards/o/OneWithTheMachine.java b/Mage.Sets/src/mage/cards/o/OneWithTheMachine.java index ab33ed55038..652332212c0 100644 --- a/Mage.Sets/src/mage/cards/o/OneWithTheMachine.java +++ b/Mage.Sets/src/mage/cards/o/OneWithTheMachine.java @@ -1,15 +1,14 @@ package mage.cards.o; -import java.util.UUID; -import mage.abilities.dynamicvalue.common.HighestManaValueCount; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.StaticFilters; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class OneWithTheMachine extends CardImpl { @@ -17,10 +16,12 @@ public final class OneWithTheMachine extends CardImpl { public OneWithTheMachine(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{U}"); - // Draw cards equal to the highest converted mana cost among artifacts you control. - this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect( - new HighestManaValueCount(StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT) - ).setText("Draw cards equal to the highest mana value among artifacts you control")); + // Draw cards equal to the greatest mana value among artifacts you control. + this.getSpellAbility().addEffect( + new DrawCardSourceControllerEffect(GreatestAmongPermanentsValue.MANAVALUE_CONTROLLED_ARTIFACTS) + .setText("Draw cards equal to the greatest mana value among artifacts you control") + ); + this.getSpellAbility().addHint(GreatestAmongPermanentsValue.MANAVALUE_CONTROLLED_ARTIFACTS.getHint()); } private OneWithTheMachine(final OneWithTheMachine card) { diff --git a/Mage.Sets/src/mage/cards/o/OrcishSiegemaster.java b/Mage.Sets/src/mage/cards/o/OrcishSiegemaster.java index 536782d61f0..306ccbce5cd 100644 --- a/Mage.Sets/src/mage/cards/o/OrcishSiegemaster.java +++ b/Mage.Sets/src/mage/cards/o/OrcishSiegemaster.java @@ -3,7 +3,7 @@ package mage.cards.o; import mage.MageInt; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.dynamicvalue.common.GreatestPowerAmongControlledCreaturesValue; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; @@ -13,7 +13,6 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.constants.Zone; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.Predicates; @@ -60,10 +59,10 @@ public final class OrcishSiegemaster extends CardImpl { // Whenever Orcish Siegemaster attacks, it gets +X/+0 until end of turn, where X is the greatest power among creatures you control. this.addAbility(new AttacksTriggeredAbility( new BoostSourceEffect( - GreatestPowerAmongControlledCreaturesValue.instance, + GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES, StaticValue.get(0), Duration.EndOfTurn, "it" ) - ).addHint(GreatestPowerAmongControlledCreaturesValue.getHint())); + ).addHint(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.getHint())); } private OrcishSiegemaster(final OrcishSiegemaster card) { diff --git a/Mage.Sets/src/mage/cards/o/OverwhelmingStampede.java b/Mage.Sets/src/mage/cards/o/OverwhelmingStampede.java index ce5311a6dcf..74b783216d2 100644 --- a/Mage.Sets/src/mage/cards/o/OverwhelmingStampede.java +++ b/Mage.Sets/src/mage/cards/o/OverwhelmingStampede.java @@ -1,10 +1,7 @@ package mage.cards.o; -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.effects.ContinuousEffect; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; import mage.abilities.keyword.TrampleAbility; @@ -12,14 +9,11 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.constants.Outcome; import mage.filter.StaticFilters; -import mage.filter.common.FilterCreaturePermanent; -import mage.game.Game; -import mage.game.permanent.Permanent; + +import java.util.UUID; /** - * * @author BetaSteward_at_googlemail.com */ public final class OverwhelmingStampede extends CardImpl { @@ -28,7 +22,14 @@ public final class OverwhelmingStampede extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{G}{G}"); // Until end of turn, creatures you control gain trample and get +X/+X, where X is the greatest power among creatures you control. - this.getSpellAbility().addEffect(new OverwhelmingStampedeInitEffect()); + this.getSpellAbility().addEffect(new GainAbilityControlledEffect( + TrampleAbility.getInstance(), Duration.EndOfTurn, StaticFilters.FILTER_CONTROLLED_CREATURES + ).setText("Until end of turn, creatures you control gain trample")); + this.getSpellAbility().addEffect(new BoostControlledEffect( + GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES, GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES, + Duration.EndOfTurn, StaticFilters.FILTER_CONTROLLED_CREATURES, false + ).setText("and get +X/+X, where X is the greatest power among creatures you control")); + this.getSpellAbility().addHint(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.getHint()); } private OverwhelmingStampede(final OverwhelmingStampede card) { @@ -39,38 +40,4 @@ public final class OverwhelmingStampede extends CardImpl { public OverwhelmingStampede copy() { return new OverwhelmingStampede(this); } -} - -class OverwhelmingStampedeInitEffect extends OneShotEffect { - - OverwhelmingStampedeInitEffect() { - super(Outcome.BoostCreature); - this.staticText = "Until end of turn, creatures you control gain trample and get +X/+X, where X is the greatest power among creatures you control"; - } - - private OverwhelmingStampedeInitEffect(final OverwhelmingStampedeInitEffect effect) { - super(effect); - } - - @Override - public OverwhelmingStampedeInitEffect copy() { - return new OverwhelmingStampedeInitEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - int maxPower = 0; - for (Permanent perm : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), game)) { - if (perm.getPower().getValue() > maxPower) { - maxPower = perm.getPower().getValue(); - } - } - ContinuousEffect effect = new GainAbilityControlledEffect(TrampleAbility.getInstance(), Duration.EndOfTurn, new FilterCreaturePermanent()); - game.addEffect(effect, source); - if (maxPower != 0) { - effect = new BoostControlledEffect(maxPower, maxPower, Duration.EndOfTurn); - game.addEffect(effect, source); - } - return true; - } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/p/PathbreakerIbex.java b/Mage.Sets/src/mage/cards/p/PathbreakerIbex.java index 2d27c01050d..1177aac355d 100644 --- a/Mage.Sets/src/mage/cards/p/PathbreakerIbex.java +++ b/Mage.Sets/src/mage/cards/p/PathbreakerIbex.java @@ -1,27 +1,23 @@ package mage.cards.p; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; -import mage.abilities.effects.ContinuousEffect; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.abilities.effects.common.continuous.GainAbilityControlledEffect; import mage.abilities.keyword.TrampleAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; -import mage.constants.Outcome; +import mage.constants.SubType; import mage.filter.StaticFilters; -import mage.game.Game; -import mage.game.permanent.Permanent; + +import java.util.UUID; /** - * * @author fireshoes */ public final class PathbreakerIbex extends CardImpl { @@ -33,7 +29,15 @@ public final class PathbreakerIbex extends CardImpl { this.toughness = new MageInt(3); // Whenever Pathbreaker Ibex attacks, creatures you control gain trample and get +X/+X until end of turn, where X is the greatest power among creatures you control. - this.addAbility(new AttacksTriggeredAbility(new PathbreakerIbexEffect(), false)); + Ability ability = new AttacksTriggeredAbility(new GainAbilityControlledEffect( + TrampleAbility.getInstance(), Duration.EndOfTurn, StaticFilters.FILTER_CONTROLLED_CREATURES + ).setText("creatures you control gain trample"), false); + ability.addEffect(new BoostControlledEffect( + GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES, GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES, + Duration.EndOfTurn, StaticFilters.FILTER_CONTROLLED_CREATURES, false + ).setText("and get +X/+X until end of turn, where X is the greatest power among creatures you control")); + ability.addHint(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.getHint()); + this.addAbility(ability); } private PathbreakerIbex(final PathbreakerIbex card) { @@ -44,38 +48,4 @@ public final class PathbreakerIbex extends CardImpl { public PathbreakerIbex copy() { return new PathbreakerIbex(this); } -} - -class PathbreakerIbexEffect extends OneShotEffect { - - PathbreakerIbexEffect() { - super(Outcome.BoostCreature); - this.staticText = "creatures you control gain trample and get +X/+X until end of turn, where X is the greatest power among creatures you control"; - } - - private PathbreakerIbexEffect(final PathbreakerIbexEffect effect) { - super(effect); - } - - @Override - public PathbreakerIbexEffect copy() { - return new PathbreakerIbexEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - int maxPower = 0; - for (Permanent perm : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), game)) { - if (perm.getPower().getValue() > maxPower) { - maxPower = perm.getPower().getValue(); - } - } - ContinuousEffect effect = new GainAbilityControlledEffect(TrampleAbility.getInstance(), Duration.EndOfTurn, StaticFilters.FILTER_PERMANENT_CREATURES); - game.addEffect(effect, source); - if (maxPower != 0) { - effect = new BoostControlledEffect(maxPower, maxPower, Duration.EndOfTurn); - game.addEffect(effect, source); - } - return true; - } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/p/PeemaAetherSeer.java b/Mage.Sets/src/mage/cards/p/PeemaAetherSeer.java index 1b38e871a9c..ad550e666f4 100644 --- a/Mage.Sets/src/mage/cards/p/PeemaAetherSeer.java +++ b/Mage.Sets/src/mage/cards/p/PeemaAetherSeer.java @@ -1,26 +1,25 @@ package mage.cards.p; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.PayEnergyCost; -import mage.abilities.dynamicvalue.common.GreatestPowerAmongControlledCreaturesValue; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.Effect; import mage.abilities.effects.common.combat.BlocksIfAbleTargetEffect; import mage.abilities.effects.common.counter.GetEnergyCountersControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Duration; -import mage.constants.Zone; +import mage.constants.SubType; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** - * * @author fireshoes */ public final class PeemaAetherSeer extends CardImpl { @@ -34,9 +33,9 @@ public final class PeemaAetherSeer extends CardImpl { this.toughness = new MageInt(2); // When Peema Aether-Seer enters the battlefield, you get an amount of {E} equal to the greatest power among creatures you control. - Effect effect = new GetEnergyCountersControllerEffect(GreatestPowerAmongControlledCreaturesValue.instance); + Effect effect = new GetEnergyCountersControllerEffect(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES); effect.setText("you get an amount of {E} equal to the greatest power among creatures you control"); - this.addAbility(new EntersBattlefieldTriggeredAbility(effect).addHint(GreatestPowerAmongControlledCreaturesValue.getHint())); + this.addAbility(new EntersBattlefieldTriggeredAbility(effect).addHint(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.getHint())); // Pay {E}{E}{E}: Target creature blocks this turn if able. Ability ability = new SimpleActivatedAbility(new BlocksIfAbleTargetEffect(Duration.EndOfTurn), new PayEnergyCost(3)); diff --git a/Mage.Sets/src/mage/cards/p/PeemaTrailblazer.java b/Mage.Sets/src/mage/cards/p/PeemaTrailblazer.java index eb050ad05f8..efec92c480e 100644 --- a/Mage.Sets/src/mage/cards/p/PeemaTrailblazer.java +++ b/Mage.Sets/src/mage/cards/p/PeemaTrailblazer.java @@ -4,7 +4,7 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.costs.common.PayEnergyCost; -import mage.abilities.dynamicvalue.common.GreatestPowerAmongControlledCreaturesValue; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.dynamicvalue.common.SavedDamageValue; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect; @@ -42,11 +42,10 @@ public final class PeemaTrailblazer extends CardImpl { final Ability ability = new ExhaustAbility( new AddCountersSourceEffect(CounterType.P1P1.createInstance(2)), new PayEnergyCost(6) ); - ability.addEffect(new DrawCardSourceControllerEffect(GreatestPowerAmongControlledCreaturesValue.instance)); - ability.addHint(GreatestPowerAmongControlledCreaturesValue.getHint()); + ability.addEffect(new DrawCardSourceControllerEffect(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES) + .setText("Then draw cards equal to the greatest power among creatures you control")); + ability.addHint(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.getHint()); this.addAbility(ability); - - } private PeemaTrailblazer(final PeemaTrailblazer card) { diff --git a/Mage.Sets/src/mage/cards/p/PriestOfYawgmoth.java b/Mage.Sets/src/mage/cards/p/PriestOfYawgmoth.java index 4931d713ffe..23c0c02957c 100644 --- a/Mage.Sets/src/mage/cards/p/PriestOfYawgmoth.java +++ b/Mage.Sets/src/mage/cards/p/PriestOfYawgmoth.java @@ -6,7 +6,7 @@ import mage.Mana; import mage.abilities.Ability; import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.dynamicvalue.common.HighestCMCOfPermanentValue; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.dynamicvalue.common.SacrificeCostManaValue; import mage.abilities.mana.DynamicManaAbility; import mage.cards.CardImpl; @@ -14,7 +14,6 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.filter.StaticFilters; -import mage.target.common.TargetControlledPermanent; import java.util.UUID; @@ -36,7 +35,7 @@ public final class PriestOfYawgmoth extends CardImpl { new TapSourceCost(), "add an amount of {B} equal to the sacrificed artifact's mana value", false, - new HighestCMCOfPermanentValue(StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT, true) + GreatestAmongPermanentsValue.MANAVALUE_OTHER_CONTROLLED_ARTIFACTS ); ability.addCost(new SacrificeTargetCost(StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT)); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/p/PrimeSpeakerZegana.java b/Mage.Sets/src/mage/cards/p/PrimeSpeakerZegana.java index a3ef20c1f5b..32446183fa2 100644 --- a/Mage.Sets/src/mage/cards/p/PrimeSpeakerZegana.java +++ b/Mage.Sets/src/mage/cards/p/PrimeSpeakerZegana.java @@ -1,10 +1,9 @@ package mage.cards.p; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.dynamicvalue.common.SourcePermanentPowerValue; import mage.abilities.effects.Effect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; @@ -15,14 +14,10 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; import mage.counters.CounterType; -import mage.filter.common.FilterControlledCreaturePermanent; -import mage.game.Game; -import mage.game.permanent.Permanent; import java.util.UUID; /** - * * @author Plopman */ public final class PrimeSpeakerZegana extends CardImpl { @@ -37,10 +32,13 @@ public final class PrimeSpeakerZegana extends CardImpl { this.toughness = new MageInt(1); //Prime Speaker Zegana enters the battlefield with X +1/+1 counters on it, where X is the greatest power among other creatures you control. - Effect effect = new AddCountersSourceEffect(CounterType.P1P1.createInstance(0), - new GreatestPowerCount(), true); + Effect effect = new AddCountersSourceEffect( + CounterType.P1P1.createInstance(0), + GreatestAmongPermanentsValue.POWER_OTHER_CONTROLLED_CREATURES, + true + ); effect.setText("with X +1/+1 counters on it, where X is the greatest power among other creatures you control."); - this.addAbility(new EntersBattlefieldAbility(effect)); + this.addAbility(new EntersBattlefieldAbility(effect).addHint(GreatestAmongPermanentsValue.POWER_OTHER_CONTROLLED_CREATURES.getHint())); //When Prime Speaker Zegana enters the battlefield, draw cards equal to its power. this.addAbility(new EntersBattlefieldTriggeredAbility(new DrawCardSourceControllerEffect(SourcePermanentPowerValue.NOT_NEGATIVE) .setText("draw cards equal to its power"))); @@ -54,33 +52,4 @@ public final class PrimeSpeakerZegana extends CardImpl { public PrimeSpeakerZegana copy() { return new PrimeSpeakerZegana(this); } -} - -class GreatestPowerCount implements DynamicValue { - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - int value = 0; - for (Permanent creature : game.getBattlefield().getActivePermanents(new FilterControlledCreaturePermanent(), sourceAbility.getControllerId(), game)) { - if (creature != null && creature.getPower().getValue() > value && !sourceAbility.getSourceId().equals(creature.getId())) { - value = creature.getPower().getValue(); - } - } - return value; - } - - @Override - public GreatestPowerCount copy() { - return new GreatestPowerCount(); - } - - @Override - public String toString() { - return "X"; - } - - @Override - public String getMessage() { - return "greatest power among other creatures you control"; - } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/p/PyreswipeHawk.java b/Mage.Sets/src/mage/cards/p/PyreswipeHawk.java index 36487417a63..5c850d40655 100644 --- a/Mage.Sets/src/mage/cards/p/PyreswipeHawk.java +++ b/Mage.Sets/src/mage/cards/p/PyreswipeHawk.java @@ -1,13 +1,11 @@ package mage.cards.p; import mage.MageInt; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.common.ExpendTriggeredAbility; -import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.dynamicvalue.common.StaticValue; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.continuous.GainControlTargetEffect; import mage.abilities.keyword.FlyingAbility; @@ -17,8 +15,6 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.filter.StaticFilters; -import mage.game.Game; import mage.target.common.TargetArtifactPermanent; import java.util.UUID; @@ -44,7 +40,8 @@ public final class PyreswipeHawk extends CardImpl { // Whenever Pyreswipe Hawk attacks, it gets +X/+0 until end of turn, where X is the greatest mana value among artifacts you control. this.addAbility(new AttacksTriggeredAbility(new BoostSourceEffect( - PyreswipeHawkValue.instance, StaticValue.get(0), Duration.EndOfTurn, "it" + GreatestAmongPermanentsValue.MANAVALUE_CONTROLLED_ARTIFACTS, + StaticValue.get(0), Duration.EndOfTurn, "it" ))); // Whenever you expend 6, gain control of up to one target artifact for as long as you control Pyreswipe Hawk. @@ -63,37 +60,4 @@ public final class PyreswipeHawk extends CardImpl { public PyreswipeHawk copy() { return new PyreswipeHawk(this); } -} - -enum PyreswipeHawkValue implements DynamicValue { - instance; - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - return game - .getBattlefield() - .getActivePermanents( - StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACT, - sourceAbility.getControllerId(), sourceAbility, game - ) - .stream() - .mapToInt(MageObject::getManaValue) - .max() - .orElse(0); - } - - @Override - public PyreswipeHawkValue copy() { - return this; - } - - @Override - public String getMessage() { - return "the greatest mana value among artifacts you control"; - } - - @Override - public String toString() { - return "X"; - } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/r/RepulsiveMutation.java b/Mage.Sets/src/mage/cards/r/RepulsiveMutation.java index 44a2aeace9e..8f341f0f143 100644 --- a/Mage.Sets/src/mage/cards/r/RepulsiveMutation.java +++ b/Mage.Sets/src/mage/cards/r/RepulsiveMutation.java @@ -2,7 +2,7 @@ package mage.cards.r; import java.util.UUID; -import mage.abilities.dynamicvalue.common.GreatestPowerAmongControlledCreaturesValue; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.dynamicvalue.common.GetXValue; import mage.abilities.effects.common.CounterUnlessPaysEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; @@ -16,7 +16,6 @@ import mage.target.common.TargetControlledCreaturePermanent; import mage.target.targetpointer.SecondTargetPointer; /** - * * @author DominionSpy */ public final class RepulsiveMutation extends CardImpl { @@ -30,11 +29,11 @@ public final class RepulsiveMutation extends CardImpl { getSpellAbility().addTarget(new TargetControlledCreaturePermanent()); // Then counter up to one target spell unless its controller pays mana equal to the greatest power among creatures you control. - getSpellAbility().addEffect(new CounterUnlessPaysEffect(GreatestPowerAmongControlledCreaturesValue.instance) + getSpellAbility().addEffect(new CounterUnlessPaysEffect(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES) .setTargetPointer(new SecondTargetPointer()) .setText("Then counter up to one target spell unless its controller pays mana equal to the greatest power among creatures you control.")); getSpellAbility().addTarget(new TargetSpell(0, 1, StaticFilters.FILTER_SPELL)); - getSpellAbility().addHint(GreatestPowerAmongControlledCreaturesValue.getHint()); + getSpellAbility().addHint(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.getHint()); } private RepulsiveMutation(final RepulsiveMutation card) { diff --git a/Mage.Sets/src/mage/cards/r/ReturnOfTheWildspeaker.java b/Mage.Sets/src/mage/cards/r/ReturnOfTheWildspeaker.java index 69e01e5b724..29f03ebce23 100644 --- a/Mage.Sets/src/mage/cards/r/ReturnOfTheWildspeaker.java +++ b/Mage.Sets/src/mage/cards/r/ReturnOfTheWildspeaker.java @@ -1,21 +1,18 @@ package mage.cards.r; -import mage.MageInt; -import mage.MageObject; -import mage.abilities.Ability; import mage.abilities.Mode; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.continuous.BoostControlledEffect; +import mage.abilities.hint.Hint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.filter.common.FilterCreaturePermanent; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.Predicates; -import mage.game.Game; import java.util.UUID; @@ -24,19 +21,23 @@ import java.util.UUID; */ public final class ReturnOfTheWildspeaker extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("non-Human creatures"); + private static final FilterPermanent filter = new FilterControlledCreaturePermanent("non-Human creatures you control"); static { filter.add(Predicates.not(SubType.HUMAN.getPredicate())); } + private static final GreatestAmongPermanentsValue xValue = new GreatestAmongPermanentsValue(GreatestAmongPermanentsValue.Quality.Power, filter); + private static final Hint hint = xValue.getHint(); + public ReturnOfTheWildspeaker(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{4}{G}"); // Choose one — // • Draw cards equal to the greatest power among non-Human creatures you control. - this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(ReturnOfTheWildspeakerValue.instance) + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(xValue) .setText("draw cards equal to the greatest power among non-Human creatures you control")); + this.getSpellAbility().addHint(hint); // • Non-Human creatures you control get +3/+3 until end of turn. this.getSpellAbility().addMode(new Mode( @@ -52,31 +53,4 @@ public final class ReturnOfTheWildspeaker extends CardImpl { public ReturnOfTheWildspeaker copy() { return new ReturnOfTheWildspeaker(this); } -} - -enum ReturnOfTheWildspeakerValue implements DynamicValue { - instance; - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - return game.getBattlefield() - .getAllActivePermanents(sourceAbility.getControllerId()) - .stream() - .filter(permanent1 -> permanent1.isCreature(game)) - .filter(permanent -> !permanent.hasSubtype(SubType.HUMAN, game)) - .map(MageObject::getPower) - .mapToInt(MageInt::getValue) - .max() - .orElse(0); - } - - @Override - public DynamicValue copy() { - return instance; - } - - @Override - public String getMessage() { - return ""; - } } \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/r/RewardTheFaithful.java b/Mage.Sets/src/mage/cards/r/RewardTheFaithful.java index dd925af7414..d55b67aa461 100644 --- a/Mage.Sets/src/mage/cards/r/RewardTheFaithful.java +++ b/Mage.Sets/src/mage/cards/r/RewardTheFaithful.java @@ -1,16 +1,16 @@ package mage.cards.r; -import java.util.UUID; -import mage.abilities.dynamicvalue.common.HighestManaValueCount; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.common.GainLifeTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.target.TargetPlayer; +import java.util.UUID; + /** - * * @author nigelzor */ public final class RewardTheFaithful extends CardImpl { @@ -18,9 +18,10 @@ public final class RewardTheFaithful extends CardImpl { public RewardTheFaithful(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{W}"); - // Any number of target players each gain life equal to the highest converted mana cost among permanents you control. - this.getSpellAbility().addEffect(new GainLifeTargetEffect(new HighestManaValueCount()) - .setText("Any number of target players each gain life equal to the highest mana value among permanents you control.")); + // Any number of target players each gain life equal to the greatest converted mana cost among permanents you control. + this.getSpellAbility().addEffect(new GainLifeTargetEffect(GreatestAmongPermanentsValue.MANAVALUE_CONTROLLED_PERMANENTS) + .setText("Any number of target players each gain life equal to the greatest mana value among permanents you control.")); + this.getSpellAbility().addHint(GreatestAmongPermanentsValue.MANAVALUE_CONTROLLED_PERMANENTS.getHint()); this.getSpellAbility().addTarget(new TargetPlayer(0, Integer.MAX_VALUE, false)); } diff --git a/Mage.Sets/src/mage/cards/r/RishkarsExpertise.java b/Mage.Sets/src/mage/cards/r/RishkarsExpertise.java index 21473b135bf..4af0f05b225 100644 --- a/Mage.Sets/src/mage/cards/r/RishkarsExpertise.java +++ b/Mage.Sets/src/mage/cards/r/RishkarsExpertise.java @@ -1,6 +1,6 @@ package mage.cards.r; -import mage.abilities.dynamicvalue.common.GreatestPowerAmongControlledCreaturesValue; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.Effect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.cost.CastFromHandForFreeEffect; @@ -28,10 +28,10 @@ public final class RishkarsExpertise extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{G}{G}"); // Draw cards equal to the greatest power among creatures you control. - Effect effect = new DrawCardSourceControllerEffect(GreatestPowerAmongControlledCreaturesValue.instance); + Effect effect = new DrawCardSourceControllerEffect(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES); effect.setText("Draw cards equal to the greatest power among creatures you control"); this.getSpellAbility().addEffect(effect); - this.getSpellAbility().addHint(GreatestPowerAmongControlledCreaturesValue.getHint()); + this.getSpellAbility().addHint(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.getHint()); // You may cast a card with converted mana cost 5 or less from your hand without paying its mana cost. this.getSpellAbility().addEffect(new CastFromHandForFreeEffect(filter).concatBy("
")); diff --git a/Mage.Sets/src/mage/cards/r/RubblebeltRioters.java b/Mage.Sets/src/mage/cards/r/RubblebeltRioters.java index 5639bff276a..d1d1bacb537 100644 --- a/Mage.Sets/src/mage/cards/r/RubblebeltRioters.java +++ b/Mage.Sets/src/mage/cards/r/RubblebeltRioters.java @@ -2,7 +2,7 @@ package mage.cards.r; import mage.MageInt; import mage.abilities.common.AttacksTriggeredAbility; -import mage.abilities.dynamicvalue.common.GreatestPowerAmongControlledCreaturesValue; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.keyword.HasteAbility; @@ -32,9 +32,9 @@ public final class RubblebeltRioters extends CardImpl { // Whenever Rubblebelt Rioters attacks, it gets +X/+0 until end of turn, where X is the greatest power among creatures you control. this.addAbility(new AttacksTriggeredAbility(new BoostSourceEffect( - GreatestPowerAmongControlledCreaturesValue.instance, StaticValue.get(0), + GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES, StaticValue.get(0), Duration.EndOfTurn - ), false).addHint(GreatestPowerAmongControlledCreaturesValue.getHint())); + ), false).addHint(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.getHint())); } private RubblebeltRioters(final RubblebeltRioters card) { diff --git a/Mage.Sets/src/mage/cards/r/RushOfKnowledge.java b/Mage.Sets/src/mage/cards/r/RushOfKnowledge.java index d271dced86b..93f60bacfe7 100644 --- a/Mage.Sets/src/mage/cards/r/RushOfKnowledge.java +++ b/Mage.Sets/src/mage/cards/r/RushOfKnowledge.java @@ -1,26 +1,27 @@ package mage.cards.r; -import java.util.UUID; -import mage.abilities.dynamicvalue.common.HighestManaValueCount; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class RushOfKnowledge extends CardImpl { public RushOfKnowledge(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{4}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{U}"); - // Draw cards equal to the highest converted mana cost among permanents you control. - DrawCardSourceControllerEffect effect = new DrawCardSourceControllerEffect(new HighestManaValueCount()); - effect.setText("Draw cards equal to the highest mana value among permanents you control"); + // Draw cards equal to the greatest mana value among permanents you control. + DrawCardSourceControllerEffect effect = new DrawCardSourceControllerEffect(GreatestAmongPermanentsValue.MANAVALUE_CONTROLLED_PERMANENTS); + effect.setText("Draw cards equal to the greatest mana value among permanents you control"); this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addHint(GreatestAmongPermanentsValue.MANAVALUE_CONTROLLED_PERMANENTS.getHint()); } private RushOfKnowledge(final RushOfKnowledge card) { diff --git a/Mage.Sets/src/mage/cards/s/SeasonOfGathering.java b/Mage.Sets/src/mage/cards/s/SeasonOfGathering.java index 5c6e94ba823..c873192b4a9 100644 --- a/Mage.Sets/src/mage/cards/s/SeasonOfGathering.java +++ b/Mage.Sets/src/mage/cards/s/SeasonOfGathering.java @@ -1,14 +1,11 @@ package mage.cards.s; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; - import mage.abilities.Ability; import mage.abilities.Mode; -import mage.abilities.dynamicvalue.common.GreatestPowerAmongControlledCreaturesValue; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.common.*; +import mage.abilities.effects.common.DestroyAllEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.keyword.TrampleAbility; import mage.abilities.keyword.VigilanceAbility; @@ -27,8 +24,11 @@ import mage.players.Player; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.targetpointer.FixedTarget; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + /** - * * @author jimga150 */ public final class SeasonOfGathering extends CardImpl { @@ -52,11 +52,11 @@ public final class SeasonOfGathering extends CardImpl { // {P}{P}{P} -- Draw cards equal to the greatest power among creatures you control. Mode mode3 = new Mode( - new DrawCardSourceControllerEffect(GreatestPowerAmongControlledCreaturesValue.instance) + new DrawCardSourceControllerEffect(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES) .setText("Draw cards equal to the greatest power among creatures you control.") ); this.getSpellAbility().addMode(mode3.withPawPrintValue(3)); - this.getSpellAbility().addHint(GreatestPowerAmongControlledCreaturesValue.getHint()); + this.getSpellAbility().addHint(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.getHint()); } private SeasonOfGathering(final SeasonOfGathering card) { diff --git a/Mage.Sets/src/mage/cards/s/SelvalaHeartOfTheWilds.java b/Mage.Sets/src/mage/cards/s/SelvalaHeartOfTheWilds.java index 6acdd4fcd86..f7d73720fb5 100644 --- a/Mage.Sets/src/mage/cards/s/SelvalaHeartOfTheWilds.java +++ b/Mage.Sets/src/mage/cards/s/SelvalaHeartOfTheWilds.java @@ -1,15 +1,14 @@ package mage.cards.s; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.dynamicvalue.common.GreatestPowerAmongControlledCreaturesValue; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.OneShotEffect; -import mage.abilities.effects.mana.ManaEffect; import mage.abilities.effects.mana.AddManaInAnyCombinationEffect; +import mage.abilities.effects.mana.ManaEffect; import mage.abilities.mana.SimpleManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -21,8 +20,9 @@ import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import java.util.UUID; + /** - * * @author maxlebedev */ public final class SelvalaHeartOfTheWilds extends CardImpl { @@ -41,11 +41,11 @@ public final class SelvalaHeartOfTheWilds extends CardImpl { // {G}, {T}: Add X mana in any combination of colors, where X is the greatest power among creatures you control. ManaEffect manaEffect = new AddManaInAnyCombinationEffect( - GreatestPowerAmongControlledCreaturesValue.instance, GreatestPowerAmongControlledCreaturesValue.instance, + GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES, GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES, ColoredManaSymbol.W, ColoredManaSymbol.U, ColoredManaSymbol.B, ColoredManaSymbol.R, ColoredManaSymbol.G); Ability ability = new SimpleManaAbility(Zone.BATTLEFIELD, manaEffect, new ManaCostsImpl<>("{G}")); ability.addCost(new TapSourceCost()); - ability.addHint(GreatestPowerAmongControlledCreaturesValue.getHint()); + ability.addHint(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.getHint()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SoldeviAdnate.java b/Mage.Sets/src/mage/cards/s/SoldeviAdnate.java index 02213349755..64b491d0f77 100644 --- a/Mage.Sets/src/mage/cards/s/SoldeviAdnate.java +++ b/Mage.Sets/src/mage/cards/s/SoldeviAdnate.java @@ -7,7 +7,7 @@ import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.costs.common.SacrificeTargetCost; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.dynamicvalue.common.HighestCMCOfPermanentValue; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.dynamicvalue.common.SacrificeCostManaValue; import mage.abilities.mana.DynamicManaAbility; import mage.cards.CardImpl; @@ -17,7 +17,6 @@ import mage.constants.SubType; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.ColorPredicate; -import mage.target.common.TargetControlledPermanent; import java.util.UUID; @@ -32,6 +31,8 @@ public final class SoldeviAdnate extends CardImpl { filter.add(Predicates.or(new ColorPredicate(ObjectColor.BLACK), CardType.ARTIFACT.getPredicate())); } + private static final GreatestAmongPermanentsValue netValue = new GreatestAmongPermanentsValue(GreatestAmongPermanentsValue.Quality.ManaValue, filter); + public SoldeviAdnate(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}"); this.subtype.add(SubType.HUMAN); @@ -41,8 +42,7 @@ public final class SoldeviAdnate extends CardImpl { // {T}, Sacrifice a black or artifact creature: Add an amount of {B} equal to the sacrificed creature's converted mana cost. Ability ability = new DynamicManaAbility(Mana.BlackMana(1), SacrificeCostManaValue.CREATURE, new TapSourceCost(), - "add an amount of {B} equal to the sacrificed creature's mana value", false, - new HighestCMCOfPermanentValue(filter, true)); + "add an amount of {B} equal to the sacrificed creature's mana value", false, netValue); ability.addCost(new SacrificeTargetCost(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/s/SpellRupture.java b/Mage.Sets/src/mage/cards/s/SpellRupture.java index 3077c3f0b9e..d36433b8e15 100644 --- a/Mage.Sets/src/mage/cards/s/SpellRupture.java +++ b/Mage.Sets/src/mage/cards/s/SpellRupture.java @@ -2,19 +2,14 @@ package mage.cards.s; import mage.MageObject; import mage.abilities.Ability; -import mage.abilities.Mode; import mage.abilities.costs.Cost; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.OneShotEffect; -import mage.abilities.hint.ValueHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; -import mage.filter.common.FilterControlledCreaturePermanent; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.game.stack.StackObject; import mage.players.Player; import mage.target.TargetSpell; @@ -33,7 +28,7 @@ public final class SpellRupture extends CardImpl { // Counter target spell unless its controller pays {X}, where X is the greatest power among creatures you control. this.getSpellAbility().addEffect(new SpellRuptureCounterUnlessPaysEffect()); this.getSpellAbility().addTarget(new TargetSpell()); - this.getSpellAbility().addHint(new ValueHint("Greatest power among your creatures", new GreatestPowerCountCreatureYouControl())); + this.getSpellAbility().addHint(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.getHint()); } private SpellRupture(final SpellRupture card) { @@ -65,50 +60,22 @@ class SpellRuptureCounterUnlessPaysEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { StackObject spell = game.getStack().getStackObject(getTargetPointer().getFirst(game, source)); - if (spell != null) { - Player player = game.getPlayer(spell.getControllerId()); - Player controller = game.getPlayer(source.getControllerId()); - MageObject sourceObject = game.getObject(source); - if (player != null && controller != null && sourceObject != null) { - int maxPower = new GreatestPowerCountCreatureYouControl().calculate(game, source, this); - Cost cost = ManaUtil.createManaCost(maxPower, true); - if (player.chooseUse(Outcome.Benefit, "Pay " + cost.getText() + "? (otherwise " + spell.getName() + " will be countered)", source, game) - && cost.pay(source, game, source, player.getId(), false)) { - return true; - } - game.informPlayers(sourceObject.getName() + ": cost wasn't payed - countering " + spell.getName()); - return game.getStack().counter(source.getFirstTarget(), source, game); - } + if (spell == null) { + return false; } - return false; - } -} - -class GreatestPowerCountCreatureYouControl implements DynamicValue { - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - int value = 0; - for (Permanent creature : game.getBattlefield().getActivePermanents(new FilterControlledCreaturePermanent(), sourceAbility.getControllerId(), game)) { - if (creature != null && creature.getPower().getValue() > value) { - value = creature.getPower().getValue(); - } + Player player = game.getPlayer(spell.getControllerId()); + Player controller = game.getPlayer(source.getControllerId()); + MageObject sourceObject = game.getObject(source); + if (player == null || controller == null || sourceObject == null) { + return false; } - return value; + int maxPower = GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.calculate(game, source, this); + Cost cost = ManaUtil.createManaCost(maxPower, true); + if (player.chooseUse(Outcome.Benefit, "Pay " + cost.getText() + ", where X is " + maxPower + "? (otherwise " + spell.getName() + " will be countered)", source, game) + && cost.pay(source, game, source, player.getId(), false)) { + return true; + } + game.informPlayers(sourceObject.getName() + ": cost wasn't payed - countering " + spell.getName()); + return game.getStack().counter(source.getFirstTarget(), source, game); } - - @Override - public GreatestPowerCountCreatureYouControl copy() { - return new GreatestPowerCountCreatureYouControl(); - } - - @Override - public String toString() { - return "X"; - } - - @Override - public String getMessage() { - return "greatest power among creatures you control"; - } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/s/StrengthTestingHammer.java b/Mage.Sets/src/mage/cards/s/StrengthTestingHammer.java index 3ae943bd288..78c8302abc0 100644 --- a/Mage.Sets/src/mage/cards/s/StrengthTestingHammer.java +++ b/Mage.Sets/src/mage/cards/s/StrengthTestingHammer.java @@ -31,11 +31,7 @@ public final class StrengthTestingHammer extends CardImpl { this.subtype.add(SubType.EQUIPMENT); - //Whenever equipped creature attacks, roll a six-sided die. - // That creature gets +X/+0 until end of turn, where X is the result. - // Then, if it has the greatest power or is tied for greatest power among creatures on the battlefield, draw a card. - - + // Whenever equipped creature attacks, roll a six-sided die. That creature gets +X/+0 until end of turn, where X is the result. Then, if it has the greatest power or is tied for greatest power among creatures on the battlefield, draw a card. TriggeredAbility ability = new AttacksAttachedTriggeredAbility(new StrengthTestingHammerEffect()); ability.addEffect(new ConditionalOneShotEffect(new DrawCardSourceControllerEffect(1), StrengthTestingHammerCondition.instance).setText("Then if it has the greatest power or is tied for greatest power among creatures on the battlefield, draw a card.")); this.addAbility(ability); diff --git a/Mage.Sets/src/mage/cards/t/TetsuoImperialChampion.java b/Mage.Sets/src/mage/cards/t/TetsuoImperialChampion.java index 721bfb1e7a6..5452d742939 100644 --- a/Mage.Sets/src/mage/cards/t/TetsuoImperialChampion.java +++ b/Mage.Sets/src/mage/cards/t/TetsuoImperialChampion.java @@ -1,18 +1,15 @@ package mage.cards.t; import mage.MageInt; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.Mode; import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.condition.common.EquippedSourceCondition; import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.effects.common.cost.CastFromHandForFreeEffect; import mage.abilities.hint.Hint; -import mage.abilities.hint.ValueHint; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -20,14 +17,14 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; import mage.filter.FilterCard; +import mage.filter.FilterPermanent; import mage.filter.common.FilterInstantOrSorceryCard; import mage.filter.predicate.ObjectSourcePlayer; import mage.filter.predicate.ObjectSourcePlayerPredicate; +import mage.filter.predicate.permanent.AttachedToSourcePredicate; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.target.common.TargetAnyTarget; -import java.util.Objects; import java.util.UUID; /** @@ -35,9 +32,15 @@ import java.util.UUID; */ public final class TetsuoImperialChampion extends CardImpl { - private static final Hint hint = new ValueHint( - "Greatest mana value of attached equipment", TetsuoImperialChampionValue.instance - ); + private static final FilterPermanent filterEquipment = new FilterPermanent("Equipment attached to {this}"); + + static { + filterEquipment.add(SubType.EQUIPMENT.getPredicate()); + filterEquipment.add(AttachedToSourcePredicate.instance); + } + + static final GreatestAmongPermanentsValue xValue = new GreatestAmongPermanentsValue(GreatestAmongPermanentsValue.Quality.ManaValue, filterEquipment); + private static final Hint hint = xValue.getHint(); private static final FilterCard filter = new FilterInstantOrSorceryCard( "an instant or sorcery spell from your hand with mana value " + "less than or equal to the highest mana value among Equipment attached to {this}" @@ -57,18 +60,18 @@ public final class TetsuoImperialChampion extends CardImpl { this.toughness = new MageInt(3); // Whenever Tetsuo, Imperial Champion attacks, if it's equipped, choose one -- - // * Tetsuo deals damage equal to the highest mana value among Equipment attached to it to any target. + // * Tetsuo deals damage equal to the greatest mana value among Equipment attached to it to any target. Ability ability = new ConditionalInterveningIfTriggeredAbility( new AttacksTriggeredAbility(new DamageTargetEffect( - TetsuoImperialChampionValue.instance, "it" - ).setText("{this} deals damage equal to the highest mana value " + + xValue, "it" + ).setText("{this} deals damage equal to the greatest mana value " + "among Equipment attached to it to any target") ).setTriggerPhrase("Whenever {this} attacks, if it's equipped, "), EquippedSourceCondition.instance, null ); ability.addTarget(new TargetAnyTarget()); - // * You may cast an instant or sorcery spell from your hand with mana value less than or equal to the highest mana value among Equipment attached to Tetsuo without paying its mana cost. + // * You may cast an instant or sorcery spell from your hand with mana value less than or equal to the greatest mana value among Equipment attached to Tetsuo without paying its mana cost. ability.addMode(new Mode(new CastFromHandForFreeEffect(filter))); this.addAbility(ability); } @@ -88,44 +91,7 @@ enum TetsuoImperialChampionPredicate implements ObjectSourcePlayerPredicate input, Game game) { - return input - .getObject() - .getManaValue() - <= TetsuoImperialChampionValue - .instance - .calculate(game, input.getSource(), null); + int value = TetsuoImperialChampion.xValue.calculate(game, input.getSource(), null); + return input.getObject().getManaValue() <= value; } -} - -enum TetsuoImperialChampionValue implements DynamicValue { - instance; - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - Permanent permanent = sourceAbility.getSourcePermanentOrLKI(game); - return permanent == null ? 0 : permanent - .getAttachments() - .stream() - .map(game::getPermanent) - .filter(Objects::nonNull) - .filter(p -> p.hasSubtype(SubType.EQUIPMENT, game)) - .mapToInt(MageObject::getManaValue) - .max() - .orElse(0); - } - - @Override - public TetsuoImperialChampionValue copy() { - return this; - } - - @Override - public String getMessage() { - return ""; - } - - @Override - public String toString() { - return "1"; - } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/t/TheGreatHenge.java b/Mage.Sets/src/mage/cards/t/TheGreatHenge.java index 78dc0a12051..2b9626453b5 100644 --- a/Mage.Sets/src/mage/cards/t/TheGreatHenge.java +++ b/Mage.Sets/src/mage/cards/t/TheGreatHenge.java @@ -1,12 +1,12 @@ package mage.cards.t; -import mage.MageInt; import mage.Mana; import mage.abilities.Ability; import mage.abilities.SpellAbility; import mage.abilities.common.EntersBattlefieldControlledTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.GainLifeEffect; import mage.abilities.effects.common.cost.CostModificationEffectImpl; @@ -18,7 +18,6 @@ import mage.constants.*; import mage.counters.CounterType; import mage.filter.StaticFilters; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.util.CardUtil; import java.util.UUID; @@ -34,7 +33,8 @@ public final class TheGreatHenge extends CardImpl { this.supertype.add(SuperType.LEGENDARY); // This spell costs {X} less to cast, where X is the greatest power among creatures you control. - this.addAbility(new SimpleStaticAbility(Zone.ALL, new TheGreatHengeCostReductionEffect())); + this.addAbility(new SimpleStaticAbility(Zone.ALL, new TheGreatHengeCostReductionEffect()) + .addHint(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.getHint())); // {T}: Add {G}{G}. You gain 2 life. Ability ability = new SimpleManaAbility(Zone.BATTLEFIELD, Mana.GreenMana(2), new TapSourceCost()); @@ -73,14 +73,8 @@ class TheGreatHengeCostReductionEffect extends CostModificationEffectImpl { @Override public boolean apply(Game game, Ability source, Ability abilityToModify) { - int reductionAmount = game.getBattlefield() - .getAllActivePermanents( - StaticFilters.FILTER_PERMANENT_CREATURE, abilityToModify.getControllerId(), game - ).stream() - .map(Permanent::getPower) - .mapToInt(MageInt::getValue) - .max() - .orElse(0); + // TODO: that abilityToModify should be source, but there is currently a bug with that #11166 + int reductionAmount = GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.calculate(game, abilityToModify, this); CardUtil.reduceCost(abilityToModify, Math.max(0, reductionAmount)); return true; } diff --git a/Mage.Sets/src/mage/cards/t/TheHungerTideRises.java b/Mage.Sets/src/mage/cards/t/TheHungerTideRises.java index 176dd6923cd..5e2d921ff6d 100644 --- a/Mage.Sets/src/mage/cards/t/TheHungerTideRises.java +++ b/Mage.Sets/src/mage/cards/t/TheHungerTideRises.java @@ -9,11 +9,8 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.FilterCard; -import mage.filter.FilterPermanent; import mage.filter.StaticFilters; -import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterCreatureCard; -import mage.filter.predicate.mageobject.AnotherPredicate; import mage.filter.predicate.mageobject.ManaValuePredicate; import mage.game.Game; import mage.game.permanent.Permanent; @@ -57,12 +54,6 @@ public final class TheHungerTideRises extends CardImpl { //Based on Scapeshift class HungerTideSacrificeSearchEffect extends OneShotEffect { - private static final FilterPermanent filter = new FilterControlledPermanent("other permanents you control"); - - static { - filter.add(AnotherPredicate.instance); - } - HungerTideSacrificeSearchEffect() { super(Outcome.Benefit); staticText = "Sacrifice any number of creatures. Search your library and/or graveyard for a creature card " diff --git a/Mage.Sets/src/mage/cards/t/TheSkullsporeNexus.java b/Mage.Sets/src/mage/cards/t/TheSkullsporeNexus.java index ff220b1df5a..eac1facb4da 100644 --- a/Mage.Sets/src/mage/cards/t/TheSkullsporeNexus.java +++ b/Mage.Sets/src/mage/cards/t/TheSkullsporeNexus.java @@ -1,6 +1,5 @@ package mage.cards.t; -import mage.MageInt; import mage.MageItem; import mage.MageObject; import mage.abilities.Ability; @@ -10,6 +9,7 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; @@ -19,7 +19,6 @@ import mage.abilities.effects.common.cost.CostModificationEffectImpl; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; -import mage.filter.StaticFilters; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.ZoneChangeGroupEvent; @@ -45,7 +44,8 @@ public final class TheSkullsporeNexus extends CardImpl { this.supertype.add(SuperType.LEGENDARY); // This spell costs {X} less to cast, where X is the greatest power among creatures you control. - this.addAbility(new SimpleStaticAbility(Zone.ALL, new TheSkullsporeNexusReductionEffect())); + this.addAbility(new SimpleStaticAbility(Zone.ALL, new TheSkullsporeNexusReductionEffect()) + .addHint(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.getHint())); // Whenever one or more nontoken creatures you control die, create a green Fungus Dinosaur creature token with base power and toughness each equal to the total power of those creatures. this.addAbility(new TheSkullsporeNexusTrigger()); @@ -83,14 +83,8 @@ class TheSkullsporeNexusReductionEffect extends CostModificationEffectImpl { @Override public boolean apply(Game game, Ability source, Ability abilityToModify) { - int reductionAmount = game.getBattlefield() - .getAllActivePermanents( - StaticFilters.FILTER_PERMANENT_CREATURE, abilityToModify.getControllerId(), game - ).stream() - .map(Permanent::getPower) - .mapToInt(MageInt::getValue) - .max() - .orElse(0); + // TODO: that abilityToModify should be source, but there is currently a bug with that #11166 + int reductionAmount = GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.calculate(game, abilityToModify, this); CardUtil.reduceCost(abilityToModify, Math.max(0, reductionAmount)); return true; } diff --git a/Mage.Sets/src/mage/cards/t/TheWanderer.java b/Mage.Sets/src/mage/cards/t/TheWanderer.java index 52bfacaca3d..62a8ce6d306 100644 --- a/Mage.Sets/src/mage/cards/t/TheWanderer.java +++ b/Mage.Sets/src/mage/cards/t/TheWanderer.java @@ -12,10 +12,9 @@ import mage.constants.ComparisonType; import mage.constants.Duration; import mage.constants.SuperType; import mage.filter.FilterPermanent; -import mage.filter.common.FilterControlledPermanent; +import mage.filter.StaticFilters; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.PowerPredicate; -import mage.filter.predicate.mageobject.AnotherPredicate; import mage.target.TargetPermanent; import java.util.UUID; @@ -26,13 +25,10 @@ import java.util.UUID; public final class TheWanderer extends CardImpl { private static final FilterPermanent filter - = new FilterControlledPermanent("other permanents you control"); - private static final FilterPermanent filter2 = new FilterCreaturePermanent("creature with power 4 or greater"); static { - filter.add(AnotherPredicate.instance); - filter2.add(new PowerPredicate(ComparisonType.MORE_THAN, 3)); + filter.add(new PowerPredicate(ComparisonType.MORE_THAN, 3)); } public TheWanderer(UUID ownerId, CardSetInfo setInfo) { @@ -43,12 +39,12 @@ public final class TheWanderer extends CardImpl { // Prevent all noncombat damage that would be dealt to you and other permanents you control. this.addAbility(new SimpleStaticAbility(new PreventAllNonCombatDamageToAllEffect( - Duration.WhileOnBattlefield, filter, true + Duration.WhileOnBattlefield, StaticFilters.FILTER_OTHER_CONTROLLED_PERMANENTS, true ))); // -2: Exile target creature with power 4 or greater. Ability ability = new LoyaltyAbility(new ExileTargetEffect(), -2); - ability.addTarget(new TargetPermanent(filter2)); + ability.addTarget(new TargetPermanent(filter)); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/t/TorrentOfFire.java b/Mage.Sets/src/mage/cards/t/TorrentOfFire.java index ad3183cc199..5a697d956e1 100644 --- a/Mage.Sets/src/mage/cards/t/TorrentOfFire.java +++ b/Mage.Sets/src/mage/cards/t/TorrentOfFire.java @@ -1,16 +1,16 @@ package mage.cards.t; -import java.util.UUID; -import mage.abilities.dynamicvalue.common.HighestManaValueCount; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.target.common.TargetAnyTarget; +import java.util.UUID; + /** - * * @author nigelzor */ public final class TorrentOfFire extends CardImpl { @@ -18,10 +18,11 @@ public final class TorrentOfFire extends CardImpl { public TorrentOfFire(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{R}{R}"); - // Torrent of Fire deals damage equal to the highest converted mana cost among permanents you control to any target. - this.getSpellAbility().addEffect(new DamageTargetEffect(new HighestManaValueCount()) - .setText("{this} deals damage to any target equal to the highest mana value among permanents you control.") + // Torrent of Fire deals damage equal to the greatest converted mana cost among permanents you control to any target. + this.getSpellAbility().addEffect(new DamageTargetEffect(GreatestAmongPermanentsValue.MANAVALUE_CONTROLLED_PERMANENTS) + .setText("{this} deals damage to any target equal to the greatest mana value among permanents you control.") ); + this.getSpellAbility().addHint(GreatestAmongPermanentsValue.MANAVALUE_CONTROLLED_PERMANENTS.getHint()); this.getSpellAbility().addTarget(new TargetAnyTarget()); } diff --git a/Mage.Sets/src/mage/cards/t/ToweringGibbon.java b/Mage.Sets/src/mage/cards/t/ToweringGibbon.java index 0ac8f2ab14c..d6082560c48 100644 --- a/Mage.Sets/src/mage/cards/t/ToweringGibbon.java +++ b/Mage.Sets/src/mage/cards/t/ToweringGibbon.java @@ -1,11 +1,8 @@ package mage.cards.t; import mage.MageInt; -import mage.MageObject; -import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.common.continuous.SetBasePowerSourceEffect; import mage.abilities.keyword.ReachAbility; import mage.cards.CardImpl; @@ -13,8 +10,6 @@ import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; -import mage.filter.StaticFilters; -import mage.game.Game; import java.util.UUID; @@ -36,9 +31,8 @@ public final class ToweringGibbon extends CardImpl { // Towering Gibbon's power is equal to the greatest mana value among creatures you control. this.addAbility(new SimpleStaticAbility( Zone.ALL, - new SetBasePowerSourceEffect( - ToweringGibbonValue.instance - ).setText("{this}'s power is equal to the greatest mana value among creatures you control") + new SetBasePowerSourceEffect(GreatestAmongPermanentsValue.MANAVALUE_CONTROLLED_CREATURES) + .setText("{this}'s power is equal to the greatest mana value among creatures you control") )); } @@ -50,36 +44,4 @@ public final class ToweringGibbon extends CardImpl { public ToweringGibbon copy() { return new ToweringGibbon(this); } -} - -enum ToweringGibbonValue implements DynamicValue { - instance; - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - return game - .getBattlefield() - .getActivePermanents( - StaticFilters.FILTER_CONTROLLED_CREATURE, - sourceAbility.getControllerId(), sourceAbility, game - ).stream() - .mapToInt(MageObject::getManaValue) - .max() - .orElse(0); - } - - @Override - public ToweringGibbonValue copy() { - return this; - } - - @Override - public String getMessage() { - return ""; - } - - @Override - public String toString() { - return "X"; - } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/t/TraverseEternity.java b/Mage.Sets/src/mage/cards/t/TraverseEternity.java index e0b832bb37d..e6b068fc161 100644 --- a/Mage.Sets/src/mage/cards/t/TraverseEternity.java +++ b/Mage.Sets/src/mage/cards/t/TraverseEternity.java @@ -1,17 +1,13 @@ package mage.cards.t; -import mage.MageObject; -import mage.abilities.Ability; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.hint.Hint; -import mage.abilities.hint.ValueHint; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.StaticFilters; -import mage.game.Game; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.HistoricPredicate; import java.util.UUID; @@ -20,13 +16,22 @@ import java.util.UUID; */ public final class TraverseEternity extends CardImpl { + private static final FilterControlledPermanent filter = new FilterControlledPermanent("historic permanents you control"); + + static { + filter.add(HistoricPredicate.instance); + } + + private static final GreatestAmongPermanentsValue xValue = new GreatestAmongPermanentsValue(GreatestAmongPermanentsValue.Quality.ManaValue, filter); + private static final Hint hint = xValue.getHint(); + public TraverseEternity(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{U}{U}"); - // Draw cards equal to the highest mana value among historic permanents you control. - this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(TraverseEternityValue.instance) + // Draw cards equal to the greatest mana value among historic permanents you control. + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(xValue) .setText("draw cards equal to the greatest mana value among historic permanents you control")); - this.getSpellAbility().addHint(TraverseEternityValue.getHint()); + this.getSpellAbility().addHint(hint); } private TraverseEternity(final TraverseEternity card) { @@ -37,42 +42,4 @@ public final class TraverseEternity extends CardImpl { public TraverseEternity copy() { return new TraverseEternity(this); } -} - -enum TraverseEternityValue implements DynamicValue { - instance; - private static final Hint hint = new ValueHint("Greatest mana value among your historic permanents", instance); - - public static Hint getHint() { - return hint; - } - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - return game - .getBattlefield() - .getActivePermanents( - StaticFilters.FILTER_CONTROLLED_PERMANENT, - sourceAbility.getControllerId(), sourceAbility, game - ).stream() - .filter(permanent -> permanent.isHistoric(game)) - .mapToInt(MageObject::getManaValue) - .max() - .orElse(0); - } - - @Override - public TraverseEternityValue copy() { - return this; - } - - @Override - public String getMessage() { - return ""; - } - - @Override - public String toString() { - return "1"; - } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/t/TriumphantChomp.java b/Mage.Sets/src/mage/cards/t/TriumphantChomp.java index a64e670092c..4161ca74378 100644 --- a/Mage.Sets/src/mage/cards/t/TriumphantChomp.java +++ b/Mage.Sets/src/mage/cards/t/TriumphantChomp.java @@ -2,7 +2,7 @@ package mage.cards.t; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.MaximumDynamicValue; -import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.effects.common.DamageTargetEffect; import mage.abilities.hint.ValueHint; @@ -23,7 +23,7 @@ public final class TriumphantChomp extends CardImpl { private static final FilterPermanent filter = new FilterControlledPermanent(SubType.DINOSAUR); private static final DynamicValue xValue = new MaximumDynamicValue( StaticValue.get(2), - new PermanentsOnBattlefieldCount(filter) + new GreatestAmongPermanentsValue(GreatestAmongPermanentsValue.Quality.Power, filter) ); public TriumphantChomp(UUID ownerId, CardSetInfo setInfo) { diff --git a/Mage.Sets/src/mage/cards/t/TumbleweedRising.java b/Mage.Sets/src/mage/cards/t/TumbleweedRising.java index fa0239749b6..caacadd5cce 100644 --- a/Mage.Sets/src/mage/cards/t/TumbleweedRising.java +++ b/Mage.Sets/src/mage/cards/t/TumbleweedRising.java @@ -1,7 +1,7 @@ package mage.cards.t; import mage.abilities.Ability; -import mage.abilities.dynamicvalue.common.GreatestPowerAmongControlledCreaturesValue; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.PlotAbility; @@ -24,7 +24,7 @@ public final class TumbleweedRising extends CardImpl { // Create an X/X green Elemental creature token, where X is the greatest power among creatures you control. this.getSpellAbility().addEffect(new TumbleweedRisingEffect()); - this.getSpellAbility().addHint(GreatestPowerAmongControlledCreaturesValue.getHint()); + this.getSpellAbility().addHint(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.getHint()); // Plot {2}{G} this.addAbility(new PlotAbility("{2}{G}")); @@ -60,7 +60,7 @@ class TumbleweedRisingEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - int xvalue = GreatestPowerAmongControlledCreaturesValue.instance.calculate(game, source, this); + int xvalue = GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.calculate(game, source, this); return new CreateTokenEffect(new ElementalXXGreenToken(xvalue)).apply(game, source); } } diff --git a/Mage.Sets/src/mage/cards/t/TuyaBearclaw.java b/Mage.Sets/src/mage/cards/t/TuyaBearclaw.java index 1ba1baa17ab..906182f308d 100644 --- a/Mage.Sets/src/mage/cards/t/TuyaBearclaw.java +++ b/Mage.Sets/src/mage/cards/t/TuyaBearclaw.java @@ -1,11 +1,8 @@ package mage.cards.t; import mage.MageInt; -import mage.MageObject; -import mage.abilities.Ability; import mage.abilities.common.AttacksTriggeredAbility; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -13,10 +10,7 @@ import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; import mage.constants.SuperType; -import mage.filter.StaticFilters; -import mage.game.Game; -import java.util.Objects; import java.util.UUID; /** @@ -35,10 +29,10 @@ public final class TuyaBearclaw extends CardImpl { // Whenever Tuya Bearclaw attacks, it gets +X/+X until end of turn, where X is the greatest power among other creatures you control. this.addAbility(new AttacksTriggeredAbility(new BoostSourceEffect( - TuyaBearclawValue.instance, - TuyaBearclawValue.instance, + GreatestAmongPermanentsValue.POWER_OTHER_CONTROLLED_CREATURES, + GreatestAmongPermanentsValue.POWER_OTHER_CONTROLLED_CREATURES, Duration.EndOfTurn - ), false)); + ), false).addHint(GreatestAmongPermanentsValue.POWER_OTHER_CONTROLLED_CREATURES.getHint())); } private TuyaBearclaw(final TuyaBearclaw card) { @@ -49,37 +43,4 @@ public final class TuyaBearclaw extends CardImpl { public TuyaBearclaw copy() { return new TuyaBearclaw(this); } -} - -enum TuyaBearclawValue implements DynamicValue { - instance; - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - return game.getBattlefield() - .getActivePermanents( - StaticFilters.FILTER_CONTROLLED_ANOTHER_CREATURE, - sourceAbility.getControllerId(), sourceAbility, game - ).stream() - .filter(Objects::nonNull) - .map(MageObject::getPower) - .mapToInt(MageInt::getValue) - .max() - .orElse(0); - } - - @Override - public TuyaBearclawValue copy() { - return instance; - } - - @Override - public String getMessage() { - return "the greatest power among other creatures you control"; - } - - @Override - public String toString() { - return "X"; - } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/t/TyvarThePummeler.java b/Mage.Sets/src/mage/cards/t/TyvarThePummeler.java index 0c8e8b9f6f0..1ab5528b2cc 100644 --- a/Mage.Sets/src/mage/cards/t/TyvarThePummeler.java +++ b/Mage.Sets/src/mage/cards/t/TyvarThePummeler.java @@ -5,7 +5,7 @@ import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapTargetCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.dynamicvalue.common.GreatestPowerAmongControlledCreaturesValue; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.common.TapSourceEffect; import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.abilities.effects.common.continuous.GainAbilitySourceEffect; @@ -56,9 +56,10 @@ public final class TyvarThePummeler extends CardImpl { // {3}{G}{G}: Creatures you control get +X/+X until end of turn, where X is the greatest power among creatures you control. this.addAbility(new SimpleActivatedAbility(new BoostControlledEffect( - GreatestPowerAmongControlledCreaturesValue.instance, - GreatestPowerAmongControlledCreaturesValue.instance, Duration.EndOfTurn - ), new ManaCostsImpl<>("{3}{G}{G}")).addHint(GreatestPowerAmongControlledCreaturesValue.getHint())); + GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES, + GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES, + Duration.EndOfTurn + ), new ManaCostsImpl<>("{3}{G}{G}")).addHint(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.getHint())); } private TyvarThePummeler(final TyvarThePummeler card) { diff --git a/Mage.Sets/src/mage/cards/u/UginsInsight.java b/Mage.Sets/src/mage/cards/u/UginsInsight.java index 1458669d91b..010080317b1 100644 --- a/Mage.Sets/src/mage/cards/u/UginsInsight.java +++ b/Mage.Sets/src/mage/cards/u/UginsInsight.java @@ -1,28 +1,29 @@ package mage.cards.u; -import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.dynamicvalue.common.HighestManaValueCount; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; +import mage.abilities.effects.keyword.ScryEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; -import mage.game.Game; -import mage.players.Player; + +import java.util.UUID; /** - * * @author fireshoes */ public final class UginsInsight extends CardImpl { public UginsInsight(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{U}{U}"); - // Scry X, where X is the highest converted mana cost among permanents you control, then draw three cards. - this.getSpellAbility().addEffect(new UginsInsightEffect()); + // Scry X, where X is the greatest mana value among permanents you control, then draw three cards. + this.getSpellAbility().addEffect( + new ScryEffect(GreatestAmongPermanentsValue.MANAVALUE_CONTROLLED_PERMANENTS) + ); + this.getSpellAbility().addHint(GreatestAmongPermanentsValue.MANAVALUE_CONTROLLED_PERMANENTS.getHint()); + this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(3).concatBy(", then")); } private UginsInsight(final UginsInsight card) { @@ -33,35 +34,4 @@ public final class UginsInsight extends CardImpl { public UginsInsight copy() { return new UginsInsight(this); } -} - -class UginsInsightEffect extends OneShotEffect { - - UginsInsightEffect() { - super(Outcome.DrawCard); - this.staticText = "Scry X, where X is the highest mana value among permanents you control, then draw three cards"; - } - - private UginsInsightEffect(final UginsInsightEffect effect) { - super(effect); - } - - @Override - public UginsInsightEffect copy() { - return new UginsInsightEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - int highCMC = new HighestManaValueCount().calculate(game, source, this); - if (highCMC > 0) { - controller.scry(highCMC, source, game); - } - controller.drawCards(3, source, game); - return true; - } - return false; - } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/v/Vault87ForcedEvolution.java b/Mage.Sets/src/mage/cards/v/Vault87ForcedEvolution.java index c5dada35a52..d5346befc1f 100644 --- a/Mage.Sets/src/mage/cards/v/Vault87ForcedEvolution.java +++ b/Mage.Sets/src/mage/cards/v/Vault87ForcedEvolution.java @@ -1,46 +1,48 @@ package mage.cards.v; -import java.util.UUID; - -import mage.MageInt; -import mage.MageObject; -import mage.abilities.Ability; import mage.abilities.common.SagaAbility; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.Effects; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.effects.common.continuous.AddCardSubTypeTargetEffect; import mage.abilities.effects.common.continuous.GainControlTargetEffect; import mage.abilities.effects.common.counter.AddCountersTargetEffect; import mage.abilities.hint.Hint; -import mage.abilities.hint.ValueHint; -import mage.constants.Duration; -import mage.constants.SagaChapter; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SagaChapter; +import mage.constants.SubType; import mage.counters.CounterType; +import mage.filter.common.FilterControlledPermanent; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.Predicates; -import mage.game.Game; import mage.target.common.TargetControlledCreaturePermanent; import mage.target.common.TargetCreaturePermanent; +import java.util.UUID; + /** * @author Cguy7777 */ public final class Vault87ForcedEvolution extends CardImpl { - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent("non-Mutant creature"); - private static final Hint hint = new ValueHint( - "Highest power among Mutants you control", Vault87ForcedEvolutionValue.instance); + private static final FilterCreaturePermanent filterNonMutant = new FilterCreaturePermanent("non-Mutant creature"); static { - filter.add(Predicates.not(SubType.MUTANT.getPredicate())); + filterNonMutant.add(Predicates.not(SubType.MUTANT.getPredicate())); } + private static final FilterControlledPermanent filterMutant = new FilterControlledPermanent("Mutants you control"); + + static { + filterMutant.add(SubType.MUTANT.getPredicate()); + } + + private static final GreatestAmongPermanentsValue xValue = new GreatestAmongPermanentsValue(GreatestAmongPermanentsValue.Quality.Power, filterMutant); + private static final Hint hint = xValue.getHint(); + public Vault87ForcedEvolution(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{G}{U}"); @@ -54,7 +56,7 @@ public final class Vault87ForcedEvolution extends CardImpl { this, SagaChapter.CHAPTER_I, new GainControlTargetEffect(Duration.WhileControlled), - new TargetCreaturePermanent(filter)); + new TargetCreaturePermanent(filterNonMutant)); // II -- Put a +1/+1 counter on target creature you control. It becomes a Mutant in addition to its other types. sagaAbility.addChapterEffect( @@ -70,7 +72,7 @@ public final class Vault87ForcedEvolution extends CardImpl { sagaAbility.addChapterEffect( this, SagaChapter.CHAPTER_III, - new DrawCardSourceControllerEffect(Vault87ForcedEvolutionValue.instance) + new DrawCardSourceControllerEffect(xValue) .setText("draw cards equal to the greatest power among Mutants you control")); this.addAbility(sagaAbility.addHint(hint)); } @@ -83,31 +85,4 @@ public final class Vault87ForcedEvolution extends CardImpl { public Vault87ForcedEvolution copy() { return new Vault87ForcedEvolution(this); } -} - -enum Vault87ForcedEvolutionValue implements DynamicValue { - instance; - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - return game.getBattlefield() - .getAllActivePermanents(sourceAbility.getControllerId()) - .stream() - .filter(permanent1 -> permanent1.isCreature(game)) - .filter(permanent -> permanent.hasSubtype(SubType.MUTANT, game)) - .map(MageObject::getPower) - .mapToInt(MageInt::getValue) - .max() - .orElse(0); - } - - @Override - public DynamicValue copy() { - return instance; - } - - @Override - public String getMessage() { - return ""; - } -} +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/w/WyllsReversal.java b/Mage.Sets/src/mage/cards/w/WyllsReversal.java index 3b46ec66e61..6bad2bf3232 100644 --- a/Mage.Sets/src/mage/cards/w/WyllsReversal.java +++ b/Mage.Sets/src/mage/cards/w/WyllsReversal.java @@ -1,7 +1,7 @@ package mage.cards.w; import mage.abilities.Ability; -import mage.abilities.dynamicvalue.common.GreatestPowerAmongControlledCreaturesValue; +import mage.abilities.dynamicvalue.common.GreatestAmongPermanentsValue; import mage.abilities.effects.common.InfoEffect; import mage.abilities.effects.common.RollDieWithResultTableEffect; import mage.cards.CardImpl; @@ -38,7 +38,7 @@ public final class WyllsReversal extends CardImpl { // 15+ | You may choose new targets for that spell or ability. Then copy it. You may choose new targets for the copy. this.getSpellAbility().addEffect(new WyllsReversalEffect()); this.getSpellAbility().addTarget(new TargetStackObject()); - this.getSpellAbility().addHint(GreatestPowerAmongControlledCreaturesValue.getHint()); + this.getSpellAbility().addHint(GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.getHint()); } private WyllsReversal(final WyllsReversal card) { @@ -94,7 +94,7 @@ class WyllsReversalEffect extends RollDieWithResultTableEffect { return false; } int result = player.rollDice(outcome, source, game, 20) - + GreatestPowerAmongControlledCreaturesValue.instance.calculate(game, source, this); + + GreatestAmongPermanentsValue.POWER_CONTROLLED_CREATURES.calculate(game, source, this); if (result >= 1) { stackObject.chooseNewTargets( game, source.getControllerId(), false, diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/avr/CraterhoofBehemothTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/avr/CraterhoofBehemothTest.java new file mode 100644 index 00000000000..131e1454fba --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/avr/CraterhoofBehemothTest.java @@ -0,0 +1,58 @@ +package org.mage.test.cards.single.avr; + +import mage.abilities.keyword.TrampleAbility; +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author Susucr + */ +public class CraterhoofBehemothTest extends CardTestPlayerBase { + + /** + * {@link mage.cards.c.CraterhoofBehemoth Craterhoof Behemoth} {5}{G}{G}{G} + * Creature — Beast + * Haste + * When this creature enters, creatures you control gain trample and get +X/+X until end of turn, where X is the number of creatures you control. + * 5/5 + */ + private static final String hoof = "Craterhoof Behemoth"; + + @Test + public void test_simple() { + + addCard(Zone.HAND, playerA, hoof, 1); + addCard(Zone.BATTLEFIELD, playerA, "Elite Vanguard", 1); + addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears", 1); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 8); + + addCard(Zone.BATTLEFIELD, playerB, "Goblin Piker", 1); + addCard(Zone.BATTLEFIELD, playerB, "Merfolk of the Pearl Trident", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, hoof); + + checkAbility("hoof gets trample", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, hoof, TrampleAbility.class, true); + checkAbility("vanguard gets trample", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Elite Vanguard", TrampleAbility.class, true); + checkAbility("bears gets trample", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Grizzly Bears", TrampleAbility.class, true); + checkAbility("opp's piker no trample", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Goblin Piker", TrampleAbility.class, false); + checkAbility("opp's merfolk no trample", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Merfolk of the Pearl Trident", TrampleAbility.class, false); + + checkPT("hoof gets +3/+3", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, hoof, 5 + 3, 5 + 3); + checkPT("vanguard gets +3/+3", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Elite Vanguard", 2 + 3, 1 + 3); + checkPT("bears gets +3/+3", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Grizzly Bears", 2 + 3, 2 + 3); + checkPT("opp's piker no PT change", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Goblin Piker", 2, 1); + checkPT("opp's merfolk no PT change", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Merfolk of the Pearl Trident", 1, 1); + + setStrictChooseMode(true); + setStopAt(2, PhaseStep.PRECOMBAT_MAIN); + execute(); + + // check effect ended. + assertPowerToughness(playerA, hoof, 5, 5); + assertPowerToughness(playerA, "Elite Vanguard", 2, 1); + assertAbility(playerA, hoof, TrampleAbility.getInstance(), false); + assertAbility(playerA, "Elite Vanguard", TrampleAbility.getInstance(), false); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/avr/EssenceHarvestTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/avr/EssenceHarvestTest.java new file mode 100644 index 00000000000..d83ca2cfae9 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/avr/EssenceHarvestTest.java @@ -0,0 +1,59 @@ +package org.mage.test.cards.single.avr; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author Susucr + */ +public class EssenceHarvestTest extends CardTestPlayerBase { + + /** + * {@link mage.cards.e.EssenceHarvest Essence Harvest} {2}{B} + * Sorcery + * Target player loses X life and you gain X life, where X is the greatest power among creatures you control. + */ + private static final String harvest = "Essence Harvest"; + + @Test + public void test_no_creature() { + addCard(Zone.HAND, playerA, harvest, 1); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3); + + addCard(Zone.BATTLEFIELD, playerB, "Goblin Piker", 1); + addCard(Zone.BATTLEFIELD, playerB, "Merfolk of the Pearl Trident", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, harvest, playerB); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertLife(playerA, 20); + assertLife(playerB, 20); + } + + @Test + public void test_4_power() { + addCard(Zone.HAND, playerA, harvest, 1); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3); + + addCard(Zone.BATTLEFIELD, playerA, "Elite Vanguard", 1); + addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears", 1); + addCard(Zone.BATTLEFIELD, playerA, "Borderland Minotaur", 1); // 4/3 + + addCard(Zone.BATTLEFIELD, playerB, "Goblin Piker", 1); + addCard(Zone.BATTLEFIELD, playerB, "Merfolk of the Pearl Trident", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, harvest, playerB); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertLife(playerA, 20 + 4); + assertLife(playerB, 20 - 4); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/bfz/UginsInsightTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/bfz/UginsInsightTest.java new file mode 100644 index 00000000000..b65e8c409f7 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/bfz/UginsInsightTest.java @@ -0,0 +1,66 @@ +package org.mage.test.cards.single.bfz; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author Susucr + */ +public class UginsInsightTest extends CardTestPlayerBase { + + /** + * {@link mage.cards.u.UginsInsight Ugin's Insight} {3}{U}{U} + * Sorcery + * Scry X, where X is the greatest mana value among permanents you control, then draw three cards. + */ + private static final String insight = "Ugin's Insight"; + + @Test + public void test_greatest_0() { + addCard(Zone.HAND, playerA, insight); + addCard(Zone.BATTLEFIELD, playerA, "Island", 5); + + addCard(Zone.BATTLEFIELD, playerB, "Barbarian Horde", 1); // 3/3 {3}{R} + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, insight); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertHandCount(playerA, 3); + } + + @Test + public void test_greatest_4() { + skipInitShuffling(); + addCard(Zone.LIBRARY, playerA, "Ageless Guardian"); + addCard(Zone.LIBRARY, playerA, "Barktooth Warbeard"); + addCard(Zone.LIBRARY, playerA, "Catacomb Crocodile"); + addCard(Zone.LIBRARY, playerA, "Devilthorn Fox"); + + addCard(Zone.HAND, playerA, insight); + addCard(Zone.BATTLEFIELD, playerA, "Island", 5); + addCard(Zone.BATTLEFIELD, playerA, "Acolyte of Bahamut", 1); // {1}{G} + addCard(Zone.BATTLEFIELD, playerA, "Barbarian Horde", 1); // 3/3 {3}{R} + addCard(Zone.BATTLEFIELD, playerA, "Sword of Fire and Ice", 1); // {3} + + addCard(Zone.BATTLEFIELD, playerB, "Barbarian Horde", 1); // 3/3 {3}{R} + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, insight); + addTarget(playerA, "Devilthorn Fox^Barktooth Warbeard"); // scry two to the bottom. + setChoice(playerA, "Barktooth Warbeard"); // order 2 to the bottom. + setChoice(playerA, "Catacomb Crocodile"); // order 2 to the top. + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertHandCount(playerA, 3); + assertHandCount(playerA, "Mountain", 1); + assertHandCount(playerA, "Catacomb Crocodile", 1); + assertHandCount(playerA, "Ageless Guardian", 1); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/cmr/AlenaKessigTrapperTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/cmr/AlenaKessigTrapperTest.java new file mode 100644 index 00000000000..b8aff4bfd13 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/cmr/AlenaKessigTrapperTest.java @@ -0,0 +1,46 @@ +package org.mage.test.cards.single.cmr; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author Susucr + */ +public class AlenaKessigTrapperTest extends CardTestPlayerBase { + + /** + * {@link mage.cards.a.AlenaKessigTrapper Alena, Kessig Trapper} {4}{R} + * Legendary Creature — Human Scout + * First strike + * {T}: Add an amount of {R} equal to the greatest power among creatures you control that entered this turn. + * Partner + * 4/3 + */ + private static final String alena = "Alena, Kessig Trapper"; + + @Test + public void test_alena() { + addCard(Zone.BATTLEFIELD, playerA, alena); + addCard(Zone.HAND, playerA, "Frost Walker"); // 4/1 {1}{U} + addCard(Zone.HAND, playerA, "Barbarian Horde", 2); // 3/3 {3}{R} + addCard(Zone.BATTLEFIELD, playerA, "Island", 2); + + // start on turn 3 as Alena has technically entered t1. + checkPlayableAbility("1: Can not cast Horde", 3, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Barbarian Horde", false); + castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Frost Walker"); + + checkPlayableAbility("2: Can cast Horde", 3, PhaseStep.POSTCOMBAT_MAIN, playerA, "Cast Barbarian Horde", true); + castSpell(3, PhaseStep.POSTCOMBAT_MAIN, playerA, "Barbarian Horde"); + + checkPlayableAbility("3: Can not cast Horde", 5, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Barbarian Horde", false); + + setStrictChooseMode(true); + setStopAt(5, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertPermanentCount(playerA, "Barbarian Horde", 1); + assertHandCount(playerA, "Barbarian Horde", 1); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/cns/MuzzioVisionaryArchitectTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/cns/MuzzioVisionaryArchitectTest.java new file mode 100644 index 00000000000..3e5f42e1f34 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/cns/MuzzioVisionaryArchitectTest.java @@ -0,0 +1,62 @@ +package org.mage.test.cards.single.cns; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author Susucr + */ +public class MuzzioVisionaryArchitectTest extends CardTestPlayerBase { + + /** + * {@link mage.cards.m.MuzzioVisionaryArchitect Muzzio, Visionary Architect} {1}{U}{U} + * Legendary Creature — Human Artificer + * {3}{U}, {T}: Look at the top X cards of your library, where X is the greatest mana value among artifacts you control. You may put an artifact card from among them onto the battlefield. Put the rest on the bottom of your library in any order. + * 1/3 + */ + private static final String muzzio = "Muzzio, Visionary Architect"; + + @Test + public void test_no_artifact() { + skipInitShuffling(); + addCard(Zone.LIBRARY, playerA, "Mox Ruby"); + addCard(Zone.LIBRARY, playerA, "Black Lotus"); + + addCard(Zone.BATTLEFIELD, playerA, muzzio); + addCard(Zone.BATTLEFIELD, playerA, "Island", 4); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{3}{U}"); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertTapped(muzzio, true); + assertPermanentCount(playerA, 5); + } + + @Test + public void test_mv2() { + skipInitShuffling(); + addCard(Zone.LIBRARY, playerA, "Mox Ruby"); + addCard(Zone.LIBRARY, playerA, "Black Lotus"); + + addCard(Zone.BATTLEFIELD, playerA, muzzio); + addCard(Zone.BATTLEFIELD, playerA, "Island", 4); + addCard(Zone.BATTLEFIELD, playerA, "Ace's Baseball Bat"); // mv 2 + addCard(Zone.BATTLEFIELD, playerA, "Chrome Mox", 2); // mv 0 + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{3}{U}"); + setChoice(playerA, "Mox Ruby"); // chosen to put on battlefield + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertTapped(muzzio, true); + assertPermanentCount(playerA, 9); + assertPermanentCount(playerA, "Mox Ruby", 1); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/dmc/BaruWurmspeakerTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/dmc/BaruWurmspeakerTest.java new file mode 100644 index 00000000000..b5e3d7a4751 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/dmc/BaruWurmspeakerTest.java @@ -0,0 +1,54 @@ +package org.mage.test.cards.single.dmc; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author Susucr + */ +public class BaruWurmspeakerTest extends CardTestPlayerBase { + + /** + * {@link mage.cards.b.BaruWurmspeaker Baru, Wurmspeaker} {2}{G}{G} + * Legendary Creature — Human Druid + * Wurms you control get +2/+2 and have trample. + * {7}{G}, {T}: Create a 4/4 green Wurm creature token. This ability costs {X} less to activate, where X is the greatest power among Wurms you control. + * 3/3 + */ + private static final String baru = "Baru, Wurmspeaker"; + + @Test + public void test_no_wurm() { + addCard(Zone.BATTLEFIELD, playerA, baru); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 8); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{7}{G},"); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertTapped(baru, true); + assertPermanentCount(playerA, "Wurm Token", 1); + assertTappedCount("Forest", true, 8); + } + + @Test + public void test_wurm() { + addCard(Zone.BATTLEFIELD, playerA, baru); + addCard(Zone.BATTLEFIELD, playerA, "Voracious Wurm"); // 2/2 Wurm + addCard(Zone.BATTLEFIELD, playerA, "Forest", 4); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{7}{G},"); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertTapped(baru, true); + assertPermanentCount(playerA, "Wurm Token", 1); + assertTappedCount("Forest", true, 4); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/dmc/TetsuoImperialChampionTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/dmc/TetsuoImperialChampionTest.java new file mode 100644 index 00000000000..29d8032dd82 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/dmc/TetsuoImperialChampionTest.java @@ -0,0 +1,83 @@ +package org.mage.test.cards.single.dmc; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author Susucr + */ +public class TetsuoImperialChampionTest extends CardTestPlayerBase { + + /** + * {@link mage.cards.t.TetsuoImperialChampion Tetsuo, Imperial Champion} {U}{B}{R} + *

+ * Legendary Creature — Human Samurai + * Whenever Tetsuo attacks, if it's equipped, choose one — + * • Tetsuo deals damage equal to the greatest mana value among Equipment attached to it to any target. + * • You may cast an instant or sorcery spell from your hand with mana value less than or equal to the greatest mana value among Equipment attached to Tetsuo without paying its mana cost. + * 3/3 + */ + private static final String tetsuo = "Tetsuo, Imperial Champion"; + + @Test + public void test_attack_notrigger() { + addCard(Zone.BATTLEFIELD, playerA, tetsuo); + + attack(1, playerA, tetsuo, playerB); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertLife(playerB, 20 - 3); + } + + @Test + public void test_attack_equipped_damage_mv3() { + addCard(Zone.BATTLEFIELD, playerA, tetsuo); + addCard(Zone.BATTLEFIELD, playerA, "Civic Saber"); // {1} +1/+0 for each color equip {1} + addCard(Zone.BATTLEFIELD, playerA, "Barbed Battlegear"); // {3} +4/-1 equip {2} + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Equip {2}", tetsuo); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Equip {1}", tetsuo); + + attack(1, playerA, tetsuo, playerB); + setModeChoice(playerA, "1"); // choose damage mode + addTarget(playerA, playerB); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertLife(playerB, 20 - 3 - 3 - 4 - 3); + } + + + @Test + public void test_attack_equipped_damage_mv1() { + addCard(Zone.BATTLEFIELD, playerA, tetsuo); + addCard(Zone.BATTLEFIELD, playerA, "Brokers Initiate"); // 0/4 + addCard(Zone.BATTLEFIELD, playerA, "Civic Saber"); // {1} +1/+0 for each color equip {1} + addCard(Zone.BATTLEFIELD, playerA, "Barbed Battlegear"); // {3} +4/-1 equip {2} + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Equip {2}", "Brokers Initiate"); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Equip {1}", tetsuo); + + attack(1, playerA, tetsuo, playerB); + attack(1, playerA, "Brokers Initiate", playerB); + setModeChoice(playerA, "1"); // choose damage mode + addTarget(playerA, playerB); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertLife(playerB, 20 - 3 - 3 - 4 - 1); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/gtc/SpellRuptureTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/gtc/SpellRuptureTest.java new file mode 100644 index 00000000000..344fae0ed87 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/gtc/SpellRuptureTest.java @@ -0,0 +1,73 @@ +package org.mage.test.cards.single.gtc; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author Susucr + */ +public class SpellRuptureTest extends CardTestPlayerBase { + + /** + * {@link mage.cards.s.SpellRupture Spell Rupture} {1}{U} + * Instant + * Counter target spell unless its controller pays {X}, where X is the greatest power among creatures you control. + */ + private static final String rupture = "Spell Rupture"; + + @Test + public void test_no_creature() { + addCard(Zone.HAND, playerA, rupture, 1); + addCard(Zone.HAND, playerA, "Lightning Bolt", 1); + addCard(Zone.BATTLEFIELD, playerA, "Volcanic Island", 10); + + addCard(Zone.BATTLEFIELD, playerB, "Goblin Piker", 1); + addCard(Zone.BATTLEFIELD, playerB, "Merfolk of the Pearl Trident", 1); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerA); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, rupture, "Lightning Bolt"); + setChoice(playerA, true); // yes for pays {0} + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertLife(playerA, 20 - 3); + assertTappedCount("Volcanic Island", true, 2 + 1); + } + + @Test + public void test_4_power() { + disableManaAutoPayment(playerA); // TODO: investigate why TestPlayer can't pay the Spell Rupture's tax mana here. + + addCard(Zone.HAND, playerA, rupture, 1); + addCard(Zone.HAND, playerA, "Lightning Bolt", 1); + addCard(Zone.BATTLEFIELD, playerA, "Volcanic Island", 10); + + addCard(Zone.BATTLEFIELD, playerA, "Elite Vanguard", 1); + addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears", 1); + addCard(Zone.BATTLEFIELD, playerA, "Borderland Minotaur", 1); // 4/3 + + addCard(Zone.BATTLEFIELD, playerB, "Goblin Piker", 1); + addCard(Zone.BATTLEFIELD, playerB, "Merfolk of the Pearl Trident", 1); + + activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}.", 5); + activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {U}.", 2); + + setChoice(playerA, "Red", 1); // pay for bolt + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerA); + setChoice(playerA, "Blue", 2); // pay for rupture + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, rupture, "Lightning Bolt"); + setChoice(playerA, true); // yes for pays {4} + setChoice(playerA, "Red", 4); // pay the 4 + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertLife(playerA, 20 - 3); + assertTappedCount("Volcanic Island", true, 2 + 1 + 4); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/ktk/KinTreeInvocationTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/ktk/KinTreeInvocationTest.java new file mode 100644 index 00000000000..8299bfec0e5 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/ktk/KinTreeInvocationTest.java @@ -0,0 +1,57 @@ +package org.mage.test.cards.single.ktk; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author Susucr + */ +public class KinTreeInvocationTest extends CardTestPlayerBase { + + /** + * {@link mage.cards.k.KinTreeInvocation Kin-Tree Invocation} {B}{G} + * Sorcery + * Create an X/X black and green Spirit Warrior creature token, where X is the greatest toughness among creatures you control. + */ + private static final String invocation = "Kin-Tree Invocation"; + + @Test + public void test_no_creature() { + addCard(Zone.HAND, playerA, invocation); + addCard(Zone.BATTLEFIELD, playerA, "Glorious Anthem", 1); // Creatures you control get +1/+1. + addCard(Zone.BATTLEFIELD, playerA, "Bayou", 2); + + addCard(Zone.BATTLEFIELD, playerB, "Barbarian Horde", 1); // 3/3 {3}{R} + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, invocation); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertPermanentCount(playerA, "Spirit Warrior Token", 1); + assertPowerToughness(playerA, "Spirit Warrior Token", 1, 1); + } + + @Test + public void test_varied_creatures() { + addCard(Zone.HAND, playerA, invocation); + addCard(Zone.BATTLEFIELD, playerA, "Axegrinder Giant", 1); // 6/4 + addCard(Zone.BATTLEFIELD, playerA, "Ancient Carp", 1); // 2/5 + addCard(Zone.BATTLEFIELD, playerA, "Goblin Piker", 1); // 2/1 + addCard(Zone.BATTLEFIELD, playerA, "Bayou", 2); + + addCard(Zone.BATTLEFIELD, playerB, "Barbarian Horde", 1); // 3/3 {3}{R} + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, invocation); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertPermanentCount(playerA, "Spirit Warrior Token", 1); + assertPowerToughness(playerA, "Spirit Warrior Token", 5, 5); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/lci/TriumphantChompTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/lci/TriumphantChompTest.java new file mode 100644 index 00000000000..aacaf38a372 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/lci/TriumphantChompTest.java @@ -0,0 +1,54 @@ +package org.mage.test.cards.single.lci; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author Susucr + */ +public class TriumphantChompTest extends CardTestPlayerBase { + + /** + * {@link mage.cards.t.TriumphantChomp Triumphant Chomp} {R} + * Sorcery + * Triumphant Chomp deals damage to target creature equal to 2 or the greatest power among Dinosaurs you control, whichever is greater. + */ + private static final String chomp = "Triumphant Chomp"; + + @Test + public void test_chomp_nodinosaur() { + addCard(Zone.HAND, playerA, chomp); + addCard(Zone.BATTLEFIELD, playerA, "Mountain"); + + addCard(Zone.BATTLEFIELD, playerA, "Enormous Baloth"); + addCard(Zone.BATTLEFIELD, playerB, "Colossadactyl"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, chomp, "Colossadactyl"); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertDamageReceived(playerB, "Colossadactyl", 2); + } + + @Test + public void test_chomp_dinosaur() { + addCard(Zone.HAND, playerA, chomp); + addCard(Zone.BATTLEFIELD, playerA, "Mountain"); + + addCard(Zone.BATTLEFIELD, playerA, "Bellowing Aegisaur"); // 3/5 dino + addCard(Zone.BATTLEFIELD, playerA, "Raging Regisaur"); // 4/4 dino + addCard(Zone.BATTLEFIELD, playerB, "Colossadactyl"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, chomp, "Colossadactyl"); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertDamageReceived(playerB, "Colossadactyl", 4); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/m11/OverwhelmingStampedeTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/m11/OverwhelmingStampedeTest.java new file mode 100644 index 00000000000..06ba3cac604 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/m11/OverwhelmingStampedeTest.java @@ -0,0 +1,57 @@ +package org.mage.test.cards.single.m11; + +import mage.abilities.keyword.TrampleAbility; +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author Susucr + */ +public class OverwhelmingStampedeTest extends CardTestPlayerBase { + + /** + * {@link mage.cards.o.OverwhelmingStampede Overwhelming Stampede} {3}{G}{G} + * Sorcery + * Until end of turn, creatures you control gain trample and get +X/+X, where X is the greatest power among creatures you control. + */ + private static final String stampede = "Overwhelming Stampede"; + + @Test + public void test_simple() { + + addCard(Zone.HAND, playerA, stampede, 1); + addCard(Zone.BATTLEFIELD, playerA, "Borderland Minotaur", 1); // 4/3 + addCard(Zone.BATTLEFIELD, playerA, "Elite Vanguard", 1); // 2/1 + addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears", 1); // 2/2 + addCard(Zone.BATTLEFIELD, playerA, "Forest", 5); + + addCard(Zone.BATTLEFIELD, playerB, "Goblin Piker", 1); // 2/1 + addCard(Zone.BATTLEFIELD, playerB, "Merfolk of the Pearl Trident", 1); // 1/1 + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, stampede); + + checkAbility("minotaur gets trample", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Borderland Minotaur", TrampleAbility.class, true); + checkAbility("vanguard gets trample", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Elite Vanguard", TrampleAbility.class, true); + checkAbility("bears gets trample", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Grizzly Bears", TrampleAbility.class, true); + checkAbility("opp's piker no trample", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Goblin Piker", TrampleAbility.class, false); + checkAbility("opp's merfolk no trample", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Merfolk of the Pearl Trident", TrampleAbility.class, false); + + checkPT("minotaur gets +4/+4", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Borderland Minotaur", 4 + 4, 3 + 4); + checkPT("vanguard gets +4/+4", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Elite Vanguard", 2 + 4, 1 + 4); + checkPT("bears gets +4/+4", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Grizzly Bears", 2 + 4, 2 + 4); + checkPT("opp's piker no PT change", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Goblin Piker", 2, 1); + checkPT("opp's merfolk no PT change", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Merfolk of the Pearl Trident", 1, 1); + + setStrictChooseMode(true); + setStopAt(2, PhaseStep.PRECOMBAT_MAIN); + execute(); + + // check effect ended. + assertPowerToughness(playerA, "Borderland Minotaur", 4, 3); + assertPowerToughness(playerA, "Elite Vanguard", 2, 1); + assertAbility(playerA, "Borderland Minotaur", TrampleAbility.getInstance(), false); + assertAbility(playerA, "Elite Vanguard", TrampleAbility.getInstance(), false); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/mom/GhaltaAndMavrenTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/mom/GhaltaAndMavrenTest.java new file mode 100644 index 00000000000..98f9fb172db --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/mom/GhaltaAndMavrenTest.java @@ -0,0 +1,177 @@ +package org.mage.test.cards.single.mom; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author Susucr + */ +public class GhaltaAndMavrenTest extends CardTestPlayerBase { + + /** + * {@link mage.cards.g.GhaltaAndMavren Ghalta and Mavren} {3}{G}{G}{W}{W} + * Legendary Creature — Dinosaur Vampire + * Trample + * Whenever you attack, choose one — + * • Create a tapped and attacking X/X green Dinosaur creature token with trample, where X is the greatest power among other attacking creatures. + * • Create X 1/1 white Vampire creature tokens with lifelink, where X is the number of other attacking creatures. + * 12/12 + */ + private static final String ghalta = "Ghalta and Mavren"; + + @Test + public void test_ghalta_attack_alone_dinosaur() { + addCard(Zone.BATTLEFIELD, playerA, ghalta); + addCard(Zone.BATTLEFIELD, playerA, "Blood Artist", 1); // to trigger on token death + + attack(1, playerA, ghalta, playerB); + setModeChoice(playerA, "1"); // create 0/0 Dinosaur + addTarget(playerA, playerB); // Blood Artist trigger + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertPermanentCount(playerA, "Dinosaur Token", 0); + assertPermanentCount(playerA, "Vampire Token", 0); + assertLife(playerB, 20 - 12 - 1); + assertLife(playerA, 20 + 1); + } + + @Test + public void test_ghalta_attack_alone_vampire() { + addCard(Zone.BATTLEFIELD, playerA, ghalta); + addCard(Zone.BATTLEFIELD, playerA, "Blood Artist", 1); // to trigger on token death + + attack(1, playerA, ghalta, playerB); + setModeChoice(playerA, "2"); // create 0 1/1 Vampire + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertPermanentCount(playerA, "Dinosaur Token", 0); + assertPermanentCount(playerA, "Vampire Token", 0); + assertLife(playerB, 20 - 12); + assertLife(playerA, 20); + } + + @Test + public void test_vanguard_attack_alone_dinosaur() { + addCard(Zone.BATTLEFIELD, playerA, ghalta); + addCard(Zone.BATTLEFIELD, playerA, "Elite Vanguard", 1); // 2/1 + + attack(1, playerA, "Elite Vanguard", playerB); + setModeChoice(playerA, "1"); // create 2/2 Dinosaur + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertPermanentCount(playerA, "Dinosaur Token", 1); + assertPowerToughness(playerA, "Dinosaur Token", 2, 2); + assertPermanentCount(playerA, "Vampire Token", 0); + assertLife(playerB, 20 - 2 - 2); + } + + @Test + public void test_bear_attack_alone_vampire() { + addCard(Zone.BATTLEFIELD, playerA, ghalta); + addCard(Zone.BATTLEFIELD, playerA, "Elite Vanguard", 1); // 2/1 + + attack(1, playerA, "Elite Vanguard", playerB); + setModeChoice(playerA, "2"); // create 1 1/1 Vampire + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertPermanentCount(playerA, "Dinosaur Token", 0); + assertPermanentCount(playerA, "Vampire Token", 1); + assertLife(playerB, 20 - 2); + } + + + @Test + public void test_vanguard_and_ghalta_attack_dinosaur() { + addCard(Zone.BATTLEFIELD, playerA, ghalta); + addCard(Zone.BATTLEFIELD, playerA, "Elite Vanguard", 1); // 2/1 + + attack(1, playerA, ghalta, playerB); + attack(1, playerA, "Elite Vanguard", playerB); + setModeChoice(playerA, "1"); // create 2/2 Dinosaur + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertPermanentCount(playerA, "Dinosaur Token", 1); + assertPowerToughness(playerA, "Dinosaur Token", 2, 2); + assertPermanentCount(playerA, "Vampire Token", 0); + assertLife(playerB, 20 - 12 - 2 - 2); + } + + @Test + public void test_vanguard_and_ghalta_attack_vampire() { + addCard(Zone.BATTLEFIELD, playerA, ghalta); + addCard(Zone.BATTLEFIELD, playerA, "Elite Vanguard", 1); // 2/1 + + attack(1, playerA, ghalta, playerB); + attack(1, playerA, "Elite Vanguard", playerB); + setModeChoice(playerA, "2"); // create 1 1/1 Vampire + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertPermanentCount(playerA, "Dinosaur Token", 0); + assertPermanentCount(playerA, "Vampire Token", 1); + assertLife(playerB, 20 - 12 - 2); + } + + + @Test + public void test_varied_attackers_dinosaur() { + addCard(Zone.BATTLEFIELD, playerA, ghalta); + addCard(Zone.BATTLEFIELD, playerA, "Elite Vanguard"); // 2/1 + addCard(Zone.BATTLEFIELD, playerA, "Barony Vampire"); // 3/2 + addCard(Zone.BATTLEFIELD, playerA, "Armored Wolf-Rider"); // 4/6 + + attack(1, playerA, "Elite Vanguard", playerB); + attack(1, playerA, "Barony Vampire", playerB); + attack(1, playerA, "Armored Wolf-Rider", playerB); + setModeChoice(playerA, "1"); // create a 4/4 Dinosaur + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertPermanentCount(playerA, "Dinosaur Token", 1); + assertPowerToughness(playerA, "Dinosaur Token", 4, 4); + assertPermanentCount(playerA, "Vampire Token", 0); + assertLife(playerB, 20 - 4 - 3 - 2 - 4); + } + + @Test + public void test_5_attackers_vampire() { + addCard(Zone.BATTLEFIELD, playerA, ghalta); + addCard(Zone.BATTLEFIELD, playerA, "Elite Vanguard", 5); // 2/1 + + attack(1, playerA, "Elite Vanguard", playerB); + attack(1, playerA, "Elite Vanguard", playerB); + attack(1, playerA, "Elite Vanguard", playerB); + attack(1, playerA, "Elite Vanguard", playerB); + attack(1, playerA, "Elite Vanguard", playerB); + setModeChoice(playerA, "2"); // create 5 1/1 Vampire + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertPermanentCount(playerA, "Dinosaur Token", 0); + assertPermanentCount(playerA, "Vampire Token", 5); + assertLife(playerB, 20 - 2 * 5); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/scg/AcceleratedMutationTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/scg/AcceleratedMutationTest.java new file mode 100644 index 00000000000..207a0157cb1 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/scg/AcceleratedMutationTest.java @@ -0,0 +1,39 @@ +package org.mage.test.cards.single.scg; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author Susucr + */ +public class AcceleratedMutationTest extends CardTestPlayerBase { + + /** + * {@link mage.cards.a.AcceleratedMutation Accelerated Mutation} {3}{G}{G} + * Instant + * Target creature gets +X/+X until end of turn, where X is the greatest mana value among permanents you control. + */ + private static final String mutation = "Accelerated Mutation"; + + @Test + public void test_simple() { + addCard(Zone.HAND, playerA, mutation); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 5); + addCard(Zone.BATTLEFIELD, playerA, "Centaur Courser"); // {2}{G} 3/3 + addCard(Zone.BATTLEFIELD, playerA, "Ingenuity Engine"); // {7} Artifact + + addCard(Zone.BATTLEFIELD, playerB, "Arboretum Elemental"); // {7}{G}{G} + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, mutation, "Centaur Courser"); + checkPT("10/10 Courser", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Centaur Courser", 10, 10); + + setStrictChooseMode(true); + setStopAt(2, PhaseStep.PRECOMBAT_MAIN); + execute(); + + // check effect stop end of turn + assertPowerToughness(playerA, "Centaur Courser", 3, 3); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/who/TraverseEternityTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/who/TraverseEternityTest.java new file mode 100644 index 00000000000..a6c28a49974 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/who/TraverseEternityTest.java @@ -0,0 +1,58 @@ +package org.mage.test.cards.single.who; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author Susucr + */ +public class TraverseEternityTest extends CardTestPlayerBase { + + /** + * {@link mage.cards.t.TraverseEternity Traverse Eternity} {2}{U}{U} + * Sorcery + * Draw cards equal to the greatest mana value among historic permanents you control. (Artifacts, legendaries, and Sagas are historic.) + */ + private static final String traverse = "Traverse Eternity"; + + @Test + public void test_greatest_2() { + addCard(Zone.HAND, playerA, traverse); + addCard(Zone.BATTLEFIELD, playerA, "Island", 5); + addCard(Zone.BATTLEFIELD, playerA, "Acolyte of Bahamut", 1); // {1}{G} + addCard(Zone.BATTLEFIELD, playerA, "Barbarian Horde", 1); // 3/3 {3}{R} + addCard(Zone.BATTLEFIELD, playerA, "Arwen Undomiel", 1); // {G}{U} -- historic + + addCard(Zone.BATTLEFIELD, playerB, "Barktooth Warbeard", 1); // 7 mv -- historic + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, traverse); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertHandCount(playerA, 2); + } + + @Test + public void test_greatest_3() { + addCard(Zone.HAND, playerA, traverse); + addCard(Zone.BATTLEFIELD, playerA, "Island", 4); + addCard(Zone.BATTLEFIELD, playerA, "Acolyte of Bahamut", 1); // {1}{G} + addCard(Zone.BATTLEFIELD, playerA, "Barbarian Horde", 1); // 3/3 {3}{R} + addCard(Zone.BATTLEFIELD, playerA, "Sword of Fire and Ice", 1); // {3} -- historic + addCard(Zone.BATTLEFIELD, playerA, "Isamaru, Hound of Konda", 1); // {W} -- historic + + addCard(Zone.BATTLEFIELD, playerB, "Barktooth Warbeard", 1); // 7 mv -- historic + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, traverse); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertHandCount(playerA, 3); + } +} diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/GreatestAmongPermanentsValue.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/GreatestAmongPermanentsValue.java new file mode 100644 index 00000000000..c800465d79c --- /dev/null +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/GreatestAmongPermanentsValue.java @@ -0,0 +1,117 @@ +package mage.abilities.dynamicvalue.common; + +import mage.abilities.Ability; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.Effect; +import mage.abilities.hint.Hint; +import mage.abilities.hint.ValueHint; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; + +import java.util.function.ToIntFunction; + + +/** + * Dynamic value for "greatest [quality] among [permanent filter]" + * For the most common ones, add a static entry instead of using new GreatestAmongPermanentsValue(...). + * + * @author Susucr + */ +public class GreatestAmongPermanentsValue implements DynamicValue { + + public static final GreatestAmongPermanentsValue POWER_CONTROLLED_CREATURES + = new GreatestAmongPermanentsValue(Quality.Power, StaticFilters.FILTER_CONTROLLED_CREATURES); + public static final GreatestAmongPermanentsValue POWER_OTHER_CONTROLLED_CREATURES + = new GreatestAmongPermanentsValue(Quality.Power, StaticFilters.FILTER_OTHER_CONTROLLED_CREATURES); + public static final GreatestAmongPermanentsValue TOUGHNESS_CONTROLLED_CREATURES + = new GreatestAmongPermanentsValue(Quality.Toughness, StaticFilters.FILTER_CONTROLLED_CREATURES); + public static final GreatestAmongPermanentsValue TOUGHNESS_OTHER_CONTROLLED_CREATURES + = new GreatestAmongPermanentsValue(Quality.Toughness, StaticFilters.FILTER_OTHER_CONTROLLED_CREATURES); + public static final GreatestAmongPermanentsValue POWER_OR_TOUGHNESS_OTHER_CONTROLLED_CREATURES + = new GreatestAmongPermanentsValue(Quality.PowerOrToughness, StaticFilters.FILTER_OTHER_CONTROLLED_CREATURES); + public static final GreatestAmongPermanentsValue MANAVALUE_CONTROLLED_CREATURES + = new GreatestAmongPermanentsValue(Quality.ManaValue, StaticFilters.FILTER_CONTROLLED_CREATURES); + public static final GreatestAmongPermanentsValue MANAVALUE_OTHER_CONTROLLED_CREATURES + = new GreatestAmongPermanentsValue(Quality.ManaValue, StaticFilters.FILTER_OTHER_CONTROLLED_CREATURES); + public static final GreatestAmongPermanentsValue MANAVALUE_CONTROLLED_ARTIFACTS + = new GreatestAmongPermanentsValue(Quality.ManaValue, StaticFilters.FILTER_CONTROLLED_PERMANENT_ARTIFACTS); + public static final GreatestAmongPermanentsValue MANAVALUE_OTHER_CONTROLLED_ARTIFACTS + = new GreatestAmongPermanentsValue(Quality.ManaValue, StaticFilters.FILTER_OTHER_CONTROLLED_ARTIFACTS); + public static final GreatestAmongPermanentsValue MANAVALUE_CONTROLLED_PERMANENTS + = new GreatestAmongPermanentsValue(Quality.ManaValue, StaticFilters.FILTER_CONTROLLED_PERMANENTS); + public static final GreatestAmongPermanentsValue MANAVALUE_OTHER_CONTROLLED_PERMANENTS + = new GreatestAmongPermanentsValue(Quality.ManaValue, StaticFilters.FILTER_OTHER_CONTROLLED_PERMANENTS); + + public enum Quality { + Power("power", (Permanent permanent) -> { + return permanent.getPower().getValue(); + }), + Toughness("toughness", (Permanent permanent) -> { + return permanent.getToughness().getValue(); + }), + ManaValue("mana value", Permanent::getManaValue), + PowerOrToughness("power and/or toughness", + (Permanent permanent) -> { + int power = permanent.getPower().getValue(); + int toughness = permanent.getToughness().getValue(); + return Math.max(power, toughness); + } + ); + + final String text; + final ToIntFunction mapToQuality; + + Quality(String text, ToIntFunction mapToQuality) { + this.text = text; + this.mapToQuality = mapToQuality; + } + } + + private final Quality quality; + private final FilterPermanent filter; + + public GreatestAmongPermanentsValue(Quality quality, FilterPermanent filter) { + this.filter = filter; + this.quality = quality; + } + + private GreatestAmongPermanentsValue(final GreatestAmongPermanentsValue value) { + super(); + this.filter = value.filter; + this.quality = value.quality; + } + + @Override + public GreatestAmongPermanentsValue copy() { + return new GreatestAmongPermanentsValue(this); + } + + @Override + public int calculate(Game game, Ability sourceAbility, Effect effect) { + return game + .getBattlefield() + .getActivePermanents( + this.filter, sourceAbility.getControllerId(), sourceAbility, game + ) + .stream() + .mapToInt(this.quality.mapToQuality) + .max() + .orElse(0); + } + + @Override + public String getMessage() { + return "the greatest " + quality.text + " among " + this.filter.getMessage(); + } + + @Override + public String toString() { + return "X"; + } + + public Hint getHint() { + return new ValueHint("Greatest " + quality.text + " among " + filter.getMessage(), this); + } +} \ No newline at end of file diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/GreatestPowerAmongControlledCreaturesValue.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/GreatestPowerAmongControlledCreaturesValue.java deleted file mode 100644 index 8a305f2e99b..00000000000 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/GreatestPowerAmongControlledCreaturesValue.java +++ /dev/null @@ -1,53 +0,0 @@ -package mage.abilities.dynamicvalue.common; - -import mage.MageInt; -import mage.MageObject; -import mage.abilities.Ability; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; -import mage.abilities.hint.Hint; -import mage.abilities.hint.ValueHint; -import mage.filter.StaticFilters; -import mage.game.Game; - -/** - * @author Styxo - */ -public enum GreatestPowerAmongControlledCreaturesValue implements DynamicValue { - instance; - - private static final Hint hint = new ValueHint("Greatest power among creatures you control", instance); - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - return game - .getBattlefield() - .getActivePermanents( - StaticFilters.FILTER_CONTROLLED_CREATURE, - sourceAbility.getControllerId(), game - ).stream() - .map(MageObject::getPower) - .mapToInt(MageInt::getValue) - .max() - .orElse(0); - } - - @Override - public GreatestPowerAmongControlledCreaturesValue copy() { - return GreatestPowerAmongControlledCreaturesValue.instance; - } - - @Override - public String getMessage() { - return "the greatest power among creatures you control"; - } - - @Override - public String toString() { - return "X"; - } - - public static Hint getHint() { - return hint; - } -} diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/GreatestToughnessAmongControlledCreaturesValue.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/GreatestToughnessAmongControlledCreaturesValue.java deleted file mode 100644 index edc372293ac..00000000000 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/GreatestToughnessAmongControlledCreaturesValue.java +++ /dev/null @@ -1,58 +0,0 @@ -package mage.abilities.dynamicvalue.common; - -import mage.MageInt; -import mage.MageObject; -import mage.abilities.Ability; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; -import mage.abilities.hint.Hint; -import mage.abilities.hint.ValueHint; -import mage.filter.FilterPermanent; -import mage.filter.StaticFilters; -import mage.game.Game; - -/** - * @author TheElk801 - */ -public enum GreatestToughnessAmongControlledCreaturesValue implements DynamicValue { - ALL(StaticFilters.FILTER_CONTROLLED_CREATURES), - OTHER(StaticFilters.FILTER_OTHER_CONTROLLED_CREATURES); - private final FilterPermanent filter; - private final Hint hint; - - GreatestToughnessAmongControlledCreaturesValue(FilterPermanent filter) { - this.filter = filter; - this.hint = new ValueHint("The greatest toughness among " + filter.getMessage(), this); - } - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - return game - .getBattlefield() - .getActivePermanents(filter, sourceAbility.getControllerId(), sourceAbility, game) - .stream() - .map(MageObject::getToughness) - .mapToInt(MageInt::getValue) - .max() - .orElse(0); - } - - @Override - public GreatestToughnessAmongControlledCreaturesValue copy() { - return this; - } - - @Override - public String getMessage() { - return "the greatest toughness among " + filter.getMessage(); - } - - @Override - public String toString() { - return "X"; - } - - public Hint getHint() { - return hint; - } -} diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/HighestCMCOfPermanentValue.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/HighestCMCOfPermanentValue.java deleted file mode 100644 index d92cc26f98a..00000000000 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/HighestCMCOfPermanentValue.java +++ /dev/null @@ -1,61 +0,0 @@ -package mage.abilities.dynamicvalue.common; - -import mage.abilities.Ability; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; -import mage.filter.FilterPermanent; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; - -/** - * @author LevelX2 - */ -public class HighestCMCOfPermanentValue implements DynamicValue { - - private final FilterPermanent filter; - private final boolean onlyIfCanBeSacrificed; - - public HighestCMCOfPermanentValue(FilterPermanent filter, boolean onlyIfCanBeSacrificed) { - super(); - this.filter = filter; - this.onlyIfCanBeSacrificed = onlyIfCanBeSacrificed; - } - - protected HighestCMCOfPermanentValue(final HighestCMCOfPermanentValue dynamicValue) { - this.filter = dynamicValue.filter; - this.onlyIfCanBeSacrificed = dynamicValue.onlyIfCanBeSacrificed; - } - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - int value = 0; - Player controller = game.getPlayer(sourceAbility.getControllerId()); - if (controller != null) { - for (Permanent permanent : game.getBattlefield() - .getActivePermanents(filter, sourceAbility.getControllerId(), sourceAbility, game)) { - if ((!onlyIfCanBeSacrificed || controller.canPaySacrificeCost(permanent, sourceAbility, sourceAbility.getControllerId(), game)) - && permanent.getManaValue() > value) { - value = permanent.getManaValue(); - } - - } - } - return value; - } - - @Override - public HighestCMCOfPermanentValue copy() { - return new HighestCMCOfPermanentValue(this); - } - - @Override - public String toString() { - return "X"; - } - - @Override - public String getMessage() { - return filter.getMessage(); - } -} diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/HighestManaValueCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/HighestManaValueCount.java deleted file mode 100644 index af92813ce48..00000000000 --- a/Mage/src/main/java/mage/abilities/dynamicvalue/common/HighestManaValueCount.java +++ /dev/null @@ -1,60 +0,0 @@ -package mage.abilities.dynamicvalue.common; - -import mage.abilities.Ability; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; -import mage.filter.FilterPermanent; -import mage.filter.StaticFilters; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; - -/** - * @author nigelzor - */ -public class HighestManaValueCount implements DynamicValue { - - private final FilterPermanent filter; - - public HighestManaValueCount() { - this(StaticFilters.FILTER_PERMANENTS); - } - - public HighestManaValueCount(FilterPermanent filter) { - this.filter = filter; - } - - protected HighestManaValueCount(final HighestManaValueCount dynamicValue) { - super(); - this.filter = dynamicValue.filter.copy(); - } - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - Player controller = game.getPlayer(sourceAbility.getControllerId()); - if (controller == null) { - return 0; - } - int highCMC = 0; - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, controller.getId(), game)) { - int cmc = permanent.getManaValue(); - highCMC = Math.max(highCMC, cmc); - } - return highCMC; - } - - @Override - public HighestManaValueCount copy() { - return new HighestManaValueCount(this); - } - - @Override - public String getMessage() { - return "the highest mana value among " + filter.getMessage() + " you control"; - } - - @Override - public String toString() { - return "X"; - } -} diff --git a/Mage/src/main/java/mage/filter/StaticFilters.java b/Mage/src/main/java/mage/filter/StaticFilters.java index cc4e5ad5ef7..78c27df088f 100644 --- a/Mage/src/main/java/mage/filter/StaticFilters.java +++ b/Mage/src/main/java/mage/filter/StaticFilters.java @@ -643,6 +643,20 @@ public final class StaticFilters { FILTER_OTHER_CONTROLLED_CREATURES.setLockedFilter(true); } + public static final FilterControlledPermanent FILTER_OTHER_CONTROLLED_PERMANENTS = new FilterControlledPermanent("other permanents you control"); + + static { + FILTER_OTHER_CONTROLLED_PERMANENTS.add(AnotherPredicate.instance); + FILTER_OTHER_CONTROLLED_PERMANENTS.setLockedFilter(true); + } + + public static final FilterControlledArtifactPermanent FILTER_OTHER_CONTROLLED_ARTIFACTS = new FilterControlledArtifactPermanent("other artifacts you control"); + + static { + FILTER_OTHER_CONTROLLED_ARTIFACTS.add(AnotherPredicate.instance); + FILTER_OTHER_CONTROLLED_ARTIFACTS.setLockedFilter(true); + } + public static final FilterControlledCreaturePermanent FILTER_CONTROLLED_A_CREATURE = new FilterControlledCreaturePermanent("a creature you control"); static { diff --git a/Mage/src/main/java/mage/filter/predicate/permanent/AttachedToSourcePredicate.java b/Mage/src/main/java/mage/filter/predicate/permanent/AttachedToSourcePredicate.java new file mode 100644 index 00000000000..41c247a0076 --- /dev/null +++ b/Mage/src/main/java/mage/filter/predicate/permanent/AttachedToSourcePredicate.java @@ -0,0 +1,29 @@ +package mage.filter.predicate.permanent; + +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; +import mage.game.Game; +import mage.game.permanent.Permanent; + +import java.util.Optional; + +/** + * @author Susucr + */ +public enum AttachedToSourcePredicate implements ObjectSourcePlayerPredicate { + instance; + + @Override + public boolean apply(ObjectSourcePlayer input, Game game) { + return Optional.of(input.getObject()) + .map(Permanent::getAttachedTo) + .filter(p -> p.equals(input.getSourceId())) + .isPresent(); + } + + @Override + public String toString() { + return "attached to {this}"; + } + +}