From 0cf13c9a7a492325d7ad7c8fc5e4014151f0851e Mon Sep 17 00:00:00 2001 From: theelk801 Date: Fri, 19 Dec 2025 16:30:18 -0500 Subject: [PATCH] refactor effects which care about the amount of colors among controlled permanents --- Mage.Sets/src/mage/cards/b/BloomTender.java | 55 +-------- .../mage/cards/c/CaseOfTheShatteredPact.java | 40 +----- .../src/mage/cards/c/ChromaticOrrery.java | 10 +- .../src/mage/cards/c/ConquerorsFlail.java | 41 +------ Mage.Sets/src/mage/cards/e/EarthenAlly.java | 69 +---------- .../src/mage/cards/f/FaeburrowElder.java | 92 +------------- Mage.Sets/src/mage/cards/g/GeneralTazri.java | 84 +++---------- .../cards/s/SisayWeatherlightCaptain.java | 45 +------ Mage.Sets/src/mage/cards/s/SoulOfRavnica.java | 12 +- .../src/mage/cards/t/TarnationVista.java | 56 ++------- Mage/src/main/java/mage/Mana.java | 22 +++- .../ColorsAmongControlledPermanentsCount.java | 114 ++++++++++++++++++ ...hColorAmongControlledPermanentsEffect.java | 57 --------- .../AddEachControlledColorManaAbility.java | 54 +++++++++ 14 files changed, 252 insertions(+), 499 deletions(-) create mode 100644 Mage/src/main/java/mage/abilities/dynamicvalue/common/ColorsAmongControlledPermanentsCount.java delete mode 100644 Mage/src/main/java/mage/abilities/effects/common/DrawCardForEachColorAmongControlledPermanentsEffect.java create mode 100644 Mage/src/main/java/mage/abilities/mana/AddEachControlledColorManaAbility.java diff --git a/Mage.Sets/src/mage/cards/b/BloomTender.java b/Mage.Sets/src/mage/cards/b/BloomTender.java index ef4aa4345b1..a98cf4918bd 100644 --- a/Mage.Sets/src/mage/cards/b/BloomTender.java +++ b/Mage.Sets/src/mage/cards/b/BloomTender.java @@ -1,18 +1,11 @@ package mage.cards.b; import mage.MageInt; -import mage.Mana; -import mage.abilities.Ability; -import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.effects.mana.ManaEffect; -import mage.abilities.mana.SimpleManaAbility; +import mage.abilities.mana.AddEachControlledColorManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.permanent.Permanent; import java.util.UUID; @@ -29,8 +22,7 @@ public final class BloomTender extends CardImpl { this.toughness = new MageInt(1); // {T}: For each color among permanents you control, add one mana of that color. - this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, new BloomTenderEffect(), new TapSourceCost())); - + this.addAbility(new AddEachControlledColorManaAbility()); } private BloomTender(final BloomTender card) { @@ -42,46 +34,3 @@ public final class BloomTender extends CardImpl { return new BloomTender(this); } } - -class BloomTenderEffect extends ManaEffect { - - BloomTenderEffect() { - super(); - staticText = "For each color among permanents you control, add one mana of that color"; - } - - private BloomTenderEffect(final BloomTenderEffect effect) { - super(effect); - } - - @Override - public BloomTenderEffect copy() { - return new BloomTenderEffect(this); - } - - @Override - public Mana produceMana(Game game, Ability source) { - Mana mana = new Mana(); - if (game == null) { - return mana; - } - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(source.getControllerId())) { - if (mana.getBlack() == 0 && permanent.getColor(game).isBlack()) { - mana.increaseBlack(); - } - if (mana.getBlue() == 0 && permanent.getColor(game).isBlue()) { - mana.increaseBlue(); - } - if (mana.getRed() == 0 && permanent.getColor(game).isRed()) { - mana.increaseRed(); - } - if (mana.getGreen() == 0 && permanent.getColor(game).isGreen()) { - mana.increaseGreen(); - } - if (mana.getWhite() == 0 && permanent.getColor(game).isWhite()) { - mana.increaseWhite(); - } - } - return mana; - } -} diff --git a/Mage.Sets/src/mage/cards/c/CaseOfTheShatteredPact.java b/Mage.Sets/src/mage/cards/c/CaseOfTheShatteredPact.java index 2aaf706104a..20d4cdf2f01 100644 --- a/Mage.Sets/src/mage/cards/c/CaseOfTheShatteredPact.java +++ b/Mage.Sets/src/mage/cards/c/CaseOfTheShatteredPact.java @@ -1,14 +1,13 @@ package mage.cards.c; -import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.common.CaseAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.condition.Condition; import mage.abilities.condition.common.SolvedSourceCondition; +import mage.abilities.dynamicvalue.common.ColorsAmongControlledPermanentsCount; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; -import mage.abilities.hint.common.CaseSolvedHint; import mage.abilities.keyword.DoubleStrikeAbility; import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.VigilanceAbility; @@ -49,7 +48,7 @@ public final class CaseOfTheShatteredPact extends CardImpl { solvedAbility.addTarget(new TargetControlledCreaturePermanent()); this.addAbility(new CaseAbility(initialAbility, CaseOfTheShatteredPactCondition.instance, solvedAbility) - .addHint(new CaseOfTheShatteredPactHint(CaseOfTheShatteredPactCondition.instance))); + .addHint(ColorsAmongControlledPermanentsCount.ALL_PERMANENTS.getHint())); } private CaseOfTheShatteredPact(final CaseOfTheShatteredPact card) { @@ -67,13 +66,7 @@ enum CaseOfTheShatteredPactCondition implements Condition { @Override public boolean apply(Game game, Ability source) { - ObjectColor color = new ObjectColor(""); - game.getBattlefield() - .getAllActivePermanents(source.getControllerId()) - .stream() - .map(permanent -> permanent.getColor(game)) - .forEach(color::addColor); - return color.getColorCount() == 5; + return ColorsAmongControlledPermanentsCount.ALL_PERMANENTS.calculate(game, source, null) >= 5; } @Override @@ -81,30 +74,3 @@ enum CaseOfTheShatteredPactCondition implements Condition { return "There are five colors among permanents you control"; } } - -class CaseOfTheShatteredPactHint extends CaseSolvedHint { - - CaseOfTheShatteredPactHint(Condition condition) { - super(condition); - } - - CaseOfTheShatteredPactHint(final CaseOfTheShatteredPactHint hint) { - super(hint); - } - - @Override - public CaseOfTheShatteredPactHint copy() { - return new CaseOfTheShatteredPactHint(this); - } - - @Override - public String getConditionText(Game game, Ability ability) { - ObjectColor color = new ObjectColor(""); - game.getBattlefield() - .getAllActivePermanents(ability.getControllerId()) - .stream() - .map(permanent -> permanent.getColor(game)) - .forEach(color::addColor); - return "Colors: " + color.getColorCount() + " (need 5)."; - } -} diff --git a/Mage.Sets/src/mage/cards/c/ChromaticOrrery.java b/Mage.Sets/src/mage/cards/c/ChromaticOrrery.java index 75389e5015d..1475f3a214d 100644 --- a/Mage.Sets/src/mage/cards/c/ChromaticOrrery.java +++ b/Mage.Sets/src/mage/cards/c/ChromaticOrrery.java @@ -6,9 +6,10 @@ 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.ColorsAmongControlledPermanentsCount; import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.effects.AsThoughManaEffect; -import mage.abilities.effects.common.DrawCardForEachColorAmongControlledPermanentsEffect; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.mana.SimpleManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -19,14 +20,13 @@ import mage.players.ManaPoolItem; import java.util.UUID; /** - * * @author htrajan */ public final class ChromaticOrrery extends CardImpl { public ChromaticOrrery(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{7}"); - + this.supertype.add(SuperType.LEGENDARY); // You may spend mana as though it were mana of any color. @@ -36,9 +36,9 @@ public final class ChromaticOrrery extends CardImpl { this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, Mana.ColorlessMana(5), new TapSourceCost())); // {5}, {T}: Draw a card for each color among permanents you control. - Ability ability = new SimpleActivatedAbility(new DrawCardForEachColorAmongControlledPermanentsEffect(), new GenericManaCost(5)); + Ability ability = new SimpleActivatedAbility(new DrawCardSourceControllerEffect(ColorsAmongControlledPermanentsCount.ALL_PERMANENTS), new GenericManaCost(5)); ability.addCost(new TapSourceCost()); - this.addAbility(ability); + this.addAbility(ability.addHint(ColorsAmongControlledPermanentsCount.ALL_PERMANENTS.getHint())); } private ChromaticOrrery(final ChromaticOrrery card) { diff --git a/Mage.Sets/src/mage/cards/c/ConquerorsFlail.java b/Mage.Sets/src/mage/cards/c/ConquerorsFlail.java index 32539d56033..2e0877745c9 100644 --- a/Mage.Sets/src/mage/cards/c/ConquerorsFlail.java +++ b/Mage.Sets/src/mage/cards/c/ConquerorsFlail.java @@ -1,12 +1,10 @@ package mage.cards.c; -import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.ColorsAmongControlledPermanentsCount; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.BoostEquippedEffect; import mage.abilities.keyword.EquipAbility; import mage.cards.CardImpl; @@ -19,7 +17,6 @@ import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; -import java.util.Objects; import java.util.Optional; import java.util.UUID; @@ -35,8 +32,10 @@ public final class ConquerorsFlail extends CardImpl { // Equipped creature gets +1/+1 for each color among permanents you control. this.addAbility(new SimpleStaticAbility(new BoostEquippedEffect( - ConquerorsFlailColorCount.instance, ConquerorsFlailColorCount.instance, Duration.WhileOnBattlefield - ))); + ColorsAmongControlledPermanentsCount.ALL_PERMANENTS, + ColorsAmongControlledPermanentsCount.ALL_PERMANENTS, + Duration.WhileOnBattlefield + )).addHint(ColorsAmongControlledPermanentsCount.ALL_PERMANENTS.getHint())); // As long as Conqueror's Flail is attached to a creature, your opponents can't cast spells during your turn. this.addAbility(new SimpleStaticAbility(new ConquerorsFlailEffect())); @@ -55,36 +54,6 @@ public final class ConquerorsFlail extends CardImpl { } } -enum ConquerorsFlailColorCount implements DynamicValue { - instance; - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - ObjectColor color = new ObjectColor(""); - game.getBattlefield() - .getAllActivePermanents(sourceAbility.getControllerId()) - .stream() - .map(permanent -> permanent.getColor(game)) - .forEach(color::addColor); - return color.getColorCount(); - } - - @Override - public String toString() { - return "1"; - } - - @Override - public String getMessage() { - return "color among permanents you control"; - } - - @Override - public ConquerorsFlailColorCount copy() { - return this; - } -} - class ConquerorsFlailEffect extends ContinuousRuleModifyingEffectImpl { ConquerorsFlailEffect() { diff --git a/Mage.Sets/src/mage/cards/e/EarthenAlly.java b/Mage.Sets/src/mage/cards/e/EarthenAlly.java index e2e6715fc0b..76a915c7fc4 100644 --- a/Mage.Sets/src/mage/cards/e/EarthenAlly.java +++ b/Mage.Sets/src/mage/cards/e/EarthenAlly.java @@ -1,29 +1,22 @@ package mage.cards.e; import mage.MageInt; -import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.common.SimpleStaticAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.dynamicvalue.common.ColorsAmongControlledPermanentsCount; import mage.abilities.dynamicvalue.common.StaticValue; -import mage.abilities.effects.Effect; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.keyword.EarthbendTargetEffect; -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.FilterPermanent; -import mage.filter.common.FilterControlledPermanent; -import mage.game.Game; import mage.target.common.TargetControlledLandPermanent; import java.util.UUID; -import java.util.stream.Collectors; /** * @author TheElk801 @@ -41,8 +34,8 @@ public final class EarthenAlly extends CardImpl { // This creature gets +1/+0 for each color among Allies you control. this.addAbility(new SimpleStaticAbility(new BoostSourceEffect( - EarthenAllyValue.instance, StaticValue.get(0), Duration.WhileOnBattlefield - )).addHint(EarthenAllyHint.instance)); + ColorsAmongControlledPermanentsCount.ALLIES, StaticValue.get(0), Duration.WhileOnBattlefield + )).addHint(ColorsAmongControlledPermanentsCount.ALLIES.getHint())); // {2}{W}{U}{B}{R}{G}: Earthbend 5. Ability ability = new SimpleActivatedAbility( @@ -61,59 +54,3 @@ public final class EarthenAlly extends CardImpl { return new EarthenAlly(this); } } - -enum EarthenAllyValue implements DynamicValue { - instance; - private static final FilterPermanent filter = new FilterControlledPermanent(SubType.ALLY); - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - return getColors(game, sourceAbility).getColorCount(); - } - - static ObjectColor getColors(Game game, Ability sourceAbility) { - return game.getBattlefield() - .getActivePermanents(filter, sourceAbility.getControllerId(), sourceAbility, game) - .stream() - .map(permanent -> permanent.getColor(game)) - .collect(Collectors.reducing((c1, c2) -> c1.union(c2))) - .orElseGet(ObjectColor::new); - } - - @Override - public EarthenAllyValue copy() { - return this; - } - - @Override - public String getMessage() { - return "color among Allies you control"; - } - - @Override - public String toString() { - return "1"; - } -} - -enum EarthenAllyHint implements Hint { - instance; - - @Override - public String getText(Game game, Ability ability) { - ObjectColor color = EarthenAllyValue.getColors(game, ability); - return "Colors among Allies you control: " + color.getColorCount() + - (color.getColorCount() > 0 - ? color - .getColors() - .stream() - .map(ObjectColor::getDescription) - .collect(Collectors.joining(", ", " (", ")")) - : ""); - } - - @Override - public Hint copy() { - return this; - } -} diff --git a/Mage.Sets/src/mage/cards/f/FaeburrowElder.java b/Mage.Sets/src/mage/cards/f/FaeburrowElder.java index 4719ae68424..2beb94fb902 100644 --- a/Mage.Sets/src/mage/cards/f/FaeburrowElder.java +++ b/Mage.Sets/src/mage/cards/f/FaeburrowElder.java @@ -1,25 +1,16 @@ package mage.cards.f; import mage.MageInt; -import mage.Mana; -import mage.ObjectColor; -import mage.abilities.Ability; import mage.abilities.common.SimpleStaticAbility; -import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; +import mage.abilities.dynamicvalue.common.ColorsAmongControlledPermanentsCount; import mage.abilities.effects.common.continuous.BoostSourceEffect; -import mage.abilities.effects.mana.ManaEffect; import mage.abilities.keyword.VigilanceAbility; -import mage.abilities.mana.SimpleManaAbility; +import mage.abilities.mana.AddEachControlledColorManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.SubType; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.permanent.Permanent; import java.util.UUID; @@ -41,11 +32,13 @@ public final class FaeburrowElder extends CardImpl { // Faeburrow Elder gets +1/+1 for each color among permanents you control. this.addAbility(new SimpleStaticAbility(new BoostSourceEffect( - FaeburrowElderValue.instance, FaeburrowElderValue.instance, Duration.WhileOnBattlefield + ColorsAmongControlledPermanentsCount.ALL_PERMANENTS, + ColorsAmongControlledPermanentsCount.ALL_PERMANENTS, + Duration.WhileOnBattlefield ))); // {T}: For each color among permanents you control, add one mana of that color. - this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, new FaeburrowElderManaEffect(), new TapSourceCost())); + this.addAbility(new AddEachControlledColorManaAbility()); } private FaeburrowElder(final FaeburrowElder card) { @@ -57,76 +50,3 @@ public final class FaeburrowElder extends CardImpl { return new FaeburrowElder(this); } } - -enum FaeburrowElderValue implements DynamicValue { - instance; - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - ObjectColor color = new ObjectColor(""); - game.getBattlefield() - .getAllActivePermanents(sourceAbility.getControllerId()) - .stream() - .map(permanent -> permanent.getColor(game)) - .forEach(color::addColor); - return color.getColorCount(); - } - - @Override - public FaeburrowElderValue copy() { - return instance; - } - - @Override - public String toString() { - return "1"; - } - - @Override - public String getMessage() { - return "color among permanents you control"; - } -} - -class FaeburrowElderManaEffect extends ManaEffect { - - FaeburrowElderManaEffect() { - super(); - staticText = "For each color among permanents you control, add one mana of that color"; - } - - private FaeburrowElderManaEffect(final FaeburrowElderManaEffect effect) { - super(effect); - } - - @Override - public FaeburrowElderManaEffect copy() { - return new FaeburrowElderManaEffect(this); - } - - @Override - public Mana produceMana(Game game, Ability source) { - Mana mana = new Mana(); - if (game == null) { - return mana; - } - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(source.getControllerId())) { - if (mana.getBlack() == 0 && permanent.getColor(game).isBlack()) { - mana.increaseBlack(); - } - if (mana.getBlue() == 0 && permanent.getColor(game).isBlue()) { - mana.increaseBlue(); - } - if (mana.getRed() == 0 && permanent.getColor(game).isRed()) { - mana.increaseRed(); - } - if (mana.getGreen() == 0 && permanent.getColor(game).isGreen()) { - mana.increaseGreen(); - } - if (mana.getWhite() == 0 && permanent.getColor(game).isWhite()) { - mana.increaseWhite(); - } - } - return mana; - } -} diff --git a/Mage.Sets/src/mage/cards/g/GeneralTazri.java b/Mage.Sets/src/mage/cards/g/GeneralTazri.java index a9d0c7dc56f..b8b479bfabb 100644 --- a/Mage.Sets/src/mage/cards/g/GeneralTazri.java +++ b/Mage.Sets/src/mage/cards/g/GeneralTazri.java @@ -1,33 +1,31 @@ - package mage.cards.g; -import java.util.UUID; import mage.MageInt; -import mage.ObjectColor; -import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.dynamicvalue.DynamicValue; -import mage.abilities.effects.Effect; +import mage.abilities.dynamicvalue.common.ColorsAmongControlledPermanentsCount; import mage.abilities.effects.common.continuous.BoostControlledEffect; import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.SuperType; import mage.filter.common.FilterCreatureCard; import mage.filter.common.FilterCreaturePermanent; -import mage.game.Game; -import mage.game.permanent.Permanent; import mage.target.common.TargetCardInLibrary; +import java.util.UUID; + /** - * * @author LevelX2 */ public final class GeneralTazri extends CardImpl { private static final FilterCreatureCard filter = new FilterCreatureCard("an Ally creature card"); + private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent(SubType.ALLY, "Ally creatures"); static { filter.add(SubType.ALLY.getPredicate()); @@ -42,14 +40,20 @@ public final class GeneralTazri extends CardImpl { this.toughness = new MageInt(4); // When General Tazri enters the battlefield, you may search your library for an Ally creature card, reveal it, put it into your hand, then shuffle your library. - this.addAbility(new EntersBattlefieldTriggeredAbility(new SearchLibraryPutInHandEffect( - new TargetCardInLibrary(filter), true), true)); + this.addAbility(new EntersBattlefieldTriggeredAbility( + new SearchLibraryPutInHandEffect(new TargetCardInLibrary(filter), true), true + )); + // {W}{U}{B}{R}{G}: Ally creatures you control get +X/+X until end of turn, where X is the number of colors among those creatures. - DynamicValue xValue = new GeneralTazriColorCount(); - BoostControlledEffect effect = new BoostControlledEffect(xValue, xValue, Duration.EndOfTurn, new FilterCreaturePermanent(SubType.ALLY, "Ally creatures"), false); this.addAbility(new SimpleActivatedAbility( - effect, - new ManaCostsImpl<>("{W}{U}{B}{R}{G}"))); + new BoostControlledEffect( + ColorsAmongControlledPermanentsCount.ALLIES, + ColorsAmongControlledPermanentsCount.ALLIES, + Duration.EndOfTurn, filter2, false + ).setText("Ally creatures you control get +X/+X until end of turn, " + + "where X is the number of colors among those creatures"), + new ManaCostsImpl<>("{W}{U}{B}{R}{G}") + ).addHint(ColorsAmongControlledPermanentsCount.ALLIES.getHint())); } @@ -62,51 +66,3 @@ public final class GeneralTazri extends CardImpl { return new GeneralTazri(this); } } - -class GeneralTazriColorCount implements DynamicValue { - - private static final FilterCreaturePermanent filter = new FilterCreaturePermanent(); - - static { - filter.add(SubType.ALLY.getPredicate()); - } - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - int count = 0; - boolean black = false; - boolean red = false; - boolean white = false; - boolean green = false; - boolean blue = false; - for (Permanent creature : game.getBattlefield().getAllActivePermanents(filter, sourceAbility.getControllerId(), game)) { - ObjectColor color = creature.getColor(game); - black |= color.isBlack(); - red |= color.isRed(); - white |= color.isWhite(); - green |= color.isGreen(); - blue |= color.isBlue(); - } - count += black ? 1 : 0; - count += red ? 1 : 0; - count += white ? 1 : 0; - count += green ? 1 : 0; - count += blue ? 1 : 0; - return count; - } - - @Override - public GeneralTazriColorCount copy() { - return new GeneralTazriColorCount(); - } - - @Override - public String getMessage() { - return "the number of colors among those creatures"; - } - - @Override - public String toString() { - return "X"; - } -} diff --git a/Mage.Sets/src/mage/cards/s/SisayWeatherlightCaptain.java b/Mage.Sets/src/mage/cards/s/SisayWeatherlightCaptain.java index 633e0672e50..cba122f8e55 100644 --- a/Mage.Sets/src/mage/cards/s/SisayWeatherlightCaptain.java +++ b/Mage.Sets/src/mage/cards/s/SisayWeatherlightCaptain.java @@ -1,13 +1,11 @@ package mage.cards.s; import mage.MageInt; -import mage.ObjectColor; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; 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.ColorsAmongControlledPermanentsCount; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.BoostSourceEffect; import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; @@ -15,7 +13,6 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.FilterCard; -import mage.filter.StaticFilters; import mage.filter.common.FilterPermanentCard; import mage.filter.predicate.mageobject.ManaValuePredicate; import mage.game.Game; @@ -40,10 +37,10 @@ public final class SisayWeatherlightCaptain extends CardImpl { // Sisay, Weatherlight Captain gets +1/+1 for each color among other legendary permanents you control. this.addAbility(new SimpleStaticAbility(new BoostSourceEffect( - SisayWeatherlightCaptainValue.instance, - SisayWeatherlightCaptainValue.instance, + ColorsAmongControlledPermanentsCount.OTHER_LEGENDARY, + ColorsAmongControlledPermanentsCount.OTHER_LEGENDARY, Duration.WhileOnBattlefield - ))); + )).addHint(ColorsAmongControlledPermanentsCount.OTHER_LEGENDARY.getHint())); // {W}{U}{B}{R}{G}: Search your library for a legendary permanent card with converted mana cost less than Sisay's power, put that card onto the battlefield, then shuffle your library. this.addAbility(new SimpleActivatedAbility( @@ -62,38 +59,6 @@ public final class SisayWeatherlightCaptain extends CardImpl { } } -enum SisayWeatherlightCaptainValue implements DynamicValue { - instance; - - @Override - public int calculate(Game game, Ability sourceAbility, Effect effect) { - ObjectColor color = new ObjectColor(); - for (Permanent permanent : game.getBattlefield().getAllActivePermanents( - StaticFilters.FILTER_PERMANENT_LEGENDARY, sourceAbility.getControllerId(), game - )) { - if (permanent != null && !permanent.getId().equals(sourceAbility.getSourceId())) { - color.addColor(permanent.getColor(game)); - } - } - return color.getColorCount(); - } - - @Override - public DynamicValue copy() { - return instance; - } - - @Override - public String getMessage() { - return "color among other legendary permanents you control"; - } - - @Override - public String toString() { - return "1"; - } -} - class SisayWeatherlightCaptainEffect extends OneShotEffect { SisayWeatherlightCaptainEffect() { @@ -123,4 +88,4 @@ class SisayWeatherlightCaptainEffect extends OneShotEffect { filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, power)); return new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filter)).apply(game, source); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/s/SoulOfRavnica.java b/Mage.Sets/src/mage/cards/s/SoulOfRavnica.java index dad384c2e10..74480a77692 100644 --- a/Mage.Sets/src/mage/cards/s/SoulOfRavnica.java +++ b/Mage.Sets/src/mage/cards/s/SoulOfRavnica.java @@ -1,4 +1,3 @@ - package mage.cards.s; import mage.MageInt; @@ -6,7 +5,8 @@ import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.ExileSourceFromGraveCost; import mage.abilities.costs.mana.ManaCostsImpl; -import mage.abilities.effects.common.DrawCardForEachColorAmongControlledPermanentsEffect; +import mage.abilities.dynamicvalue.common.ColorsAmongControlledPermanentsCount; +import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -17,13 +17,12 @@ import mage.constants.Zone; import java.util.UUID; /** - * * @author LevelX2 */ public final class SoulOfRavnica extends CardImpl { public SoulOfRavnica(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{U}{U}"); this.subtype.add(SubType.AVATAR); this.power = new MageInt(6); @@ -33,10 +32,11 @@ public final class SoulOfRavnica extends CardImpl { this.addAbility(FlyingAbility.getInstance()); // {5}{U}{U}: Draw a card for each color among permanents you control. - this.addAbility(new SimpleActivatedAbility(new DrawCardForEachColorAmongControlledPermanentsEffect(), new ManaCostsImpl<>("{5}{U}{U}"))); + this.addAbility(new SimpleActivatedAbility(new DrawCardSourceControllerEffect(ColorsAmongControlledPermanentsCount.ALL_PERMANENTS), new ManaCostsImpl<>("{5}{U}{U}")) + .addHint(ColorsAmongControlledPermanentsCount.ALL_PERMANENTS.getHint())); // {5}{U}{U}, Exile Soul of Ravnica from your graveyard: Draw a card for each color among permanents you control. - Ability ability = new SimpleActivatedAbility(Zone.GRAVEYARD, new DrawCardForEachColorAmongControlledPermanentsEffect(), new ManaCostsImpl<>("{5}{U}{U}")); + Ability ability = new SimpleActivatedAbility(Zone.GRAVEYARD, new DrawCardSourceControllerEffect(ColorsAmongControlledPermanentsCount.ALL_PERMANENTS), new ManaCostsImpl<>("{5}{U}{U}")); ability.addCost(new ExileSourceFromGraveCost()); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/t/TarnationVista.java b/Mage.Sets/src/mage/cards/t/TarnationVista.java index d2f684026e1..4ea1f5d26d1 100644 --- a/Mage.Sets/src/mage/cards/t/TarnationVista.java +++ b/Mage.Sets/src/mage/cards/t/TarnationVista.java @@ -5,16 +5,14 @@ import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTappedAsItEntersChooseColorAbility; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; +import mage.abilities.dynamicvalue.common.ColorsAmongControlledPermanentsCount; import mage.abilities.effects.mana.AddManaChosenColorEffect; import mage.abilities.effects.mana.ManaEffect; -import mage.abilities.mana.ActivatedManaAbilityImpl; import mage.abilities.mana.SimpleManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Zone; import mage.game.Game; -import mage.game.permanent.Permanent; import java.util.UUID; @@ -30,10 +28,12 @@ public final class TarnationVista extends CardImpl { this.addAbility(new EntersBattlefieldTappedAsItEntersChooseColorAbility()); // {T}: Add one mana of the chosen color. - this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, new AddManaChosenColorEffect(), new TapSourceCost())); + this.addAbility(new SimpleManaAbility(new AddManaChosenColorEffect(), new TapSourceCost())); // {1}, {T}: For each color among monocolored permanents you control, add one mana of that color. - this.addAbility(new TarnationVistaManaAbility()); + Ability ability = new SimpleManaAbility(new TarnationVistaEffect(), new GenericManaCost(1)); + ability.addCost(new TapSourceCost()); + this.addAbility(ability.addHint(ColorsAmongControlledPermanentsCount.MONOCOLORED_PERMANENTS.getHint())); } private TarnationVista(final TarnationVista card) { @@ -46,30 +46,11 @@ public final class TarnationVista extends CardImpl { } } -class TarnationVistaManaAbility extends ActivatedManaAbilityImpl { - - TarnationVistaManaAbility() { - super(Zone.BATTLEFIELD, new TarnationVistaEffect(), new GenericManaCost(1)); - this.addCost(new TapSourceCost()); - } - - private TarnationVistaManaAbility(final TarnationVistaManaAbility ability) { - super(ability); - } - - @Override - public TarnationVistaManaAbility copy() { - return new TarnationVistaManaAbility(this); - } - -} - -// Inspired by Bloom Tender class TarnationVistaEffect extends ManaEffect { TarnationVistaEffect() { super(); - staticText = "For each color among monocolored permanents you control, add one mana of that color"; + staticText = "for each color among monocolored permanents you control, add one mana of that color"; } private TarnationVistaEffect(final TarnationVistaEffect effect) { @@ -83,30 +64,9 @@ class TarnationVistaEffect extends ManaEffect { @Override public Mana produceMana(Game game, Ability source) { - Mana mana = new Mana(); if (game == null) { - return mana; + return new Mana(); } - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(source.getControllerId())) { - if (permanent.getColor(game).getColorCount() != 1) { - continue; - } - if (mana.getBlack() == 0 && permanent.getColor(game).isBlack()) { - mana.increaseBlack(); - } - if (mana.getBlue() == 0 && permanent.getColor(game).isBlue()) { - mana.increaseBlue(); - } - if (mana.getRed() == 0 && permanent.getColor(game).isRed()) { - mana.increaseRed(); - } - if (mana.getGreen() == 0 && permanent.getColor(game).isGreen()) { - mana.increaseGreen(); - } - if (mana.getWhite() == 0 && permanent.getColor(game).isWhite()) { - mana.increaseWhite(); - } - } - return mana; + return Mana.fromColor(ColorsAmongControlledPermanentsCount.MONOCOLORED_PERMANENTS.getAllControlledColors(game, source)); } } diff --git a/Mage/src/main/java/mage/Mana.java b/Mage/src/main/java/mage/Mana.java index 79a36018a96..d77f7a63962 100644 --- a/Mage/src/main/java/mage/Mana.java +++ b/Mage/src/main/java/mage/Mana.java @@ -1479,7 +1479,7 @@ public class Mana implements Comparable, Serializable, Copyable { /** * Hardcoding here versus using Objects.hash in order to increase performance since this is - * called thousands of times by {@link mage.abilities.mana.ManaOptions#addManaWithCost(List, Game)} + * called thousands of times by {@link mage.abilities.mana.ManaOptions#addManaWithCost(List, mage.game.Game)} * * @return */ @@ -1517,4 +1517,24 @@ public class Mana implements Comparable, Serializable, Copyable { } return value; } + + public static Mana fromColor(ObjectColor color) { + Mana mana = new Mana(); + if (color.isWhite()) { + mana.increaseWhite(); + } + if (color.isBlue()) { + mana.increaseBlue(); + } + if (color.isBlack()) { + mana.increaseBlack(); + } + if (color.isRed()) { + mana.increaseRed(); + } + if (color.isGreen()) { + mana.increaseGreen(); + } + return mana; + } } diff --git a/Mage/src/main/java/mage/abilities/dynamicvalue/common/ColorsAmongControlledPermanentsCount.java b/Mage/src/main/java/mage/abilities/dynamicvalue/common/ColorsAmongControlledPermanentsCount.java new file mode 100644 index 00000000000..1fa1bfd017e --- /dev/null +++ b/Mage/src/main/java/mage/abilities/dynamicvalue/common/ColorsAmongControlledPermanentsCount.java @@ -0,0 +1,114 @@ +package mage.abilities.dynamicvalue.common; + +import mage.ObjectColor; +import mage.abilities.Ability; +import mage.abilities.dynamicvalue.DynamicValue; +import mage.abilities.effects.Effect; +import mage.abilities.hint.Hint; +import mage.constants.SubType; +import mage.constants.SuperType; +import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.AnotherPredicate; +import mage.filter.predicate.mageobject.MonocoloredPredicate; +import mage.game.Game; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author TheElk801 + */ +public enum ColorsAmongControlledPermanentsCount implements DynamicValue { + ALL_PERMANENTS(StaticFilters.FILTER_CONTROLLED_PERMANENTS), + MONOCOLORED_PERMANENTS(PermanentFilters.MONOCOLORED_PERMANENTS), + OTHER_LEGENDARY(PermanentFilters.OTHER_LEGENDARY), + ALLIES(new FilterControlledPermanent(SubType.ALLY, "Allies you control")); + private final FilterPermanent filter; + private final Hint hint; + + ColorsAmongControlledPermanentsCount(FilterPermanent filter) { + this.filter = filter; + this.hint = new ColorsAmongControlledPermanentsHint(this); + } + + @Override + public int calculate(Game game, Ability sourceAbility, Effect effect) { + return getAllControlledColors(game, sourceAbility).getColorCount(); + } + + @Override + public ColorsAmongControlledPermanentsCount copy() { + return this; + } + + @Override + public String getMessage() { + return "for each color among " + filter.getMessage(); + } + + @Override + public String toString() { + return "1"; + } + + public Hint getHint() { + return hint; + } + + public FilterPermanent getFilter() { + return filter; + } + + public ObjectColor getAllControlledColors(Game game, Ability source) { + return game + .getBattlefield() + .getActivePermanents(filter, source.getControllerId(), source, game) + .stream() + .map(permanent -> permanent.getColor(game)) + .reduce(new ObjectColor(), (c1, c2) -> c1.union(c2)); + } +} + +class ColorsAmongControlledPermanentsHint implements Hint { + + private final ColorsAmongControlledPermanentsCount count; + + ColorsAmongControlledPermanentsHint(ColorsAmongControlledPermanentsCount count) { + this.count = count; + } + + @Override + public String getText(Game game, Ability ability) { + List colors = this + .count + .getAllControlledColors(game, ability) + .getColors() + .stream() + .map(ObjectColor::getDescription) + .collect(Collectors.toList()); + return "Colors among " + this.count.getFilter().getMessage() + ": " + colors.size() + + (colors.size() > 0 ? " (" + String.join(", ", colors) + ')' : ""); + } + + @Override + public Hint copy() { + return this; + } +} + +class PermanentFilters { + static final FilterPermanent MONOCOLORED_PERMANENTS = new FilterControlledPermanent("monocolored permanents you control"); + + static { + MONOCOLORED_PERMANENTS.add(MonocoloredPredicate.instance); + } + + static final FilterPermanent OTHER_LEGENDARY = new FilterControlledPermanent("other legendary permanents you control"); + + static { + OTHER_LEGENDARY.add(AnotherPredicate.instance); + OTHER_LEGENDARY.add(SuperType.LEGENDARY.getPredicate()); + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/DrawCardForEachColorAmongControlledPermanentsEffect.java b/Mage/src/main/java/mage/abilities/effects/common/DrawCardForEachColorAmongControlledPermanentsEffect.java deleted file mode 100644 index 00df6e96f72..00000000000 --- a/Mage/src/main/java/mage/abilities/effects/common/DrawCardForEachColorAmongControlledPermanentsEffect.java +++ /dev/null @@ -1,57 +0,0 @@ -package mage.abilities.effects.common; - -import mage.ObjectColor; -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; -import mage.constants.Outcome; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; - -import java.util.HashSet; -import java.util.Set; - -public class DrawCardForEachColorAmongControlledPermanentsEffect extends OneShotEffect { - - public DrawCardForEachColorAmongControlledPermanentsEffect() { - super(Outcome.DrawCard); - this.staticText = "Draw a card for each color among permanents you control"; - } - - protected DrawCardForEachColorAmongControlledPermanentsEffect(final DrawCardForEachColorAmongControlledPermanentsEffect effect) { - super(effect); - } - - @Override - public DrawCardForEachColorAmongControlledPermanentsEffect copy() { - return new DrawCardForEachColorAmongControlledPermanentsEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - Set colors = new HashSet<>(); - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(controller.getId())) { - if (permanent.getColor(game).isBlack()) { - colors.add(ObjectColor.BLACK); - } - if (permanent.getColor(game).isBlue()) { - colors.add(ObjectColor.BLUE); - } - if (permanent.getColor(game).isRed()) { - colors.add(ObjectColor.RED); - } - if (permanent.getColor(game).isGreen()) { - colors.add(ObjectColor.GREEN); - } - if (permanent.getColor(game).isWhite()) { - colors.add(ObjectColor.WHITE); - } - } - controller.drawCards(colors.size(), source, game); - return true; - } - return false; - } -} diff --git a/Mage/src/main/java/mage/abilities/mana/AddEachControlledColorManaAbility.java b/Mage/src/main/java/mage/abilities/mana/AddEachControlledColorManaAbility.java new file mode 100644 index 00000000000..66ec5373483 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/mana/AddEachControlledColorManaAbility.java @@ -0,0 +1,54 @@ +package mage.abilities.mana; + +import mage.Mana; +import mage.abilities.Ability; +import mage.abilities.costs.common.TapSourceCost; +import mage.abilities.dynamicvalue.common.ColorsAmongControlledPermanentsCount; +import mage.abilities.effects.mana.ManaEffect; +import mage.constants.Zone; +import mage.game.Game; + +/** + * @author TheElk801 + */ +public class AddEachControlledColorManaAbility extends ActivatedManaAbilityImpl { + + public AddEachControlledColorManaAbility() { + super(Zone.BATTLEFIELD, new AddEachControlledColorManaEffect(), new TapSourceCost()); + this.addHint(ColorsAmongControlledPermanentsCount.ALL_PERMANENTS.getHint()); + } + + private AddEachControlledColorManaAbility(final AddEachControlledColorManaAbility ability) { + super(ability); + } + + @Override + public AddEachControlledColorManaAbility copy() { + return new AddEachControlledColorManaAbility(this); + } +} + +class AddEachControlledColorManaEffect extends ManaEffect { + + AddEachControlledColorManaEffect() { + super(); + staticText = "for each color among permanents you control, add one mana of that color"; + } + + private AddEachControlledColorManaEffect(final AddEachControlledColorManaEffect effect) { + super(effect); + } + + @Override + public AddEachControlledColorManaEffect copy() { + return new AddEachControlledColorManaEffect(this); + } + + @Override + public Mana produceMana(Game game, Ability source) { + if (game == null) { + return new Mana(); + } + return Mana.fromColor(ColorsAmongControlledPermanentsCount.ALL_PERMANENTS.getAllControlledColors(game, source)); + } +}