diff --git a/Mage.Sets/src/mage/cards/b/BirchloreRangers.java b/Mage.Sets/src/mage/cards/b/BirchloreRangers.java index 812fdb387b6..c130b15d1ce 100644 --- a/Mage.Sets/src/mage/cards/b/BirchloreRangers.java +++ b/Mage.Sets/src/mage/cards/b/BirchloreRangers.java @@ -1,19 +1,26 @@ - package mage.cards.b; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; import mage.MageInt; +import mage.Mana; +import mage.abilities.Ability; import mage.abilities.costs.common.TapTargetCost; import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.effects.mana.AddManaOfAnyColorEffect; import mage.abilities.keyword.MorphAbility; -import mage.abilities.mana.AnyColorManaAbility; +import mage.abilities.mana.SimpleManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import mage.constants.Zone; +import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.permanent.TappedPredicate; +import mage.game.Game; import mage.target.common.TargetControlledCreaturePermanent; /** @@ -22,22 +29,22 @@ import mage.target.common.TargetControlledCreaturePermanent; */ public final class BirchloreRangers extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped Elves you control"); - - static { - filter.add(Predicates.not(TappedPredicate.instance)); - filter.add(SubType.ELF.getPredicate()); - } - public BirchloreRangers(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}"); this.subtype.add(SubType.ELF, SubType.DRUID); this.power = new MageInt(1); this.toughness = new MageInt(1); // Tap two untapped Elves you control: Add one mana of any color. - this.addAbility(new AnyColorManaAbility(new TapTargetCost(new TargetControlledCreaturePermanent(2, 2, filter, false)))); + FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped Elves you control"); + filter.add(Predicates.not(TappedPredicate.instance)); + filter.add(SubType.ELF.getPredicate()); + this.addAbility(new SimpleManaAbility( + Zone.BATTLEFIELD, + new BirchloreRangersManaEffect(filter), + new TapTargetCost(new TargetControlledCreaturePermanent(2, 2, filter, false)))); + // Morph {G} this.addAbility(new MorphAbility(this, new ManaCostsImpl("{G}"))); } @@ -51,3 +58,35 @@ public final class BirchloreRangers extends CardImpl { return new BirchloreRangers(this); } } + +class BirchloreRangersManaEffect extends AddManaOfAnyColorEffect { + + private final FilterPermanent filter; + + public BirchloreRangersManaEffect(FilterPermanent filter) { + super(1); + this.filter = filter; + } + + public BirchloreRangersManaEffect(final BirchloreRangersManaEffect effect) { + super(effect); + this.filter = effect.filter.copy(); + } + + @Override + public BirchloreRangersManaEffect copy() { + return new BirchloreRangersManaEffect(this); + } + + @Override + public List getNetMana(Game game, Ability source) { + if (game.inCheckPlayableState()) { + int count = game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game) / 2; + List netManaCalculated = new ArrayList<>(); + netManaCalculated.add(new Mana(0, 0, 0, 0, 0, 0, count * 2, 0)); + return netManaCalculated; + } + return super.getNetMana(game, source); + } + +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/g/GoblinClearcutter.java b/Mage.Sets/src/mage/cards/g/GoblinClearcutter.java index ed9702a2ce6..74224e3c00f 100644 --- a/Mage.Sets/src/mage/cards/g/GoblinClearcutter.java +++ b/Mage.Sets/src/mage/cards/g/GoblinClearcutter.java @@ -56,10 +56,9 @@ public final class GoblinClearcutter extends CardImpl { } } -// TODO: replace by mana effect to use with mana reflection class GoblinClearCutterManaEffect extends ManaEffect { - private List netMana = new ArrayList<>(); + private final List netMana = new ArrayList<>(); public GoblinClearCutterManaEffect() { super(); diff --git a/Mage.Sets/src/mage/cards/g/GrandArchitect.java b/Mage.Sets/src/mage/cards/g/GrandArchitect.java index 8907f8e8dc7..5818a306fcf 100644 --- a/Mage.Sets/src/mage/cards/g/GrandArchitect.java +++ b/Mage.Sets/src/mage/cards/g/GrandArchitect.java @@ -1,5 +1,7 @@ package mage.cards.g; +import java.util.ArrayList; +import java.util.List; import mage.*; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; @@ -25,6 +27,7 @@ import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import java.util.UUID; +import mage.filter.FilterPermanent; /** * @author BetaSteward_at_googlemail.com, nantuko @@ -56,7 +59,10 @@ public final class GrandArchitect extends CardImpl { this.addAbility(ability); // Tap an untapped blue creature you control: Add {C}{C}. Spend this mana only to cast artifact spells or activate abilities of artifacts. - this.addAbility(new GrandArchitectManaAbility()); + FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped blue creature"); + filter.add(new ColorPredicate(ObjectColor.BLUE)); + filter.add(Predicates.not(TappedPredicate.instance)); + this.addAbility(new GrandArchitectManaAbility(filter)); } public GrandArchitect(final GrandArchitect card) { @@ -104,20 +110,31 @@ class GrandArchitectEffect extends ContinuousEffectImpl { class GrandArchitectManaAbility extends ActivatedManaAbilityImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped blue creature"); + private final FilterPermanent filter; - static { - filter.add(new ColorPredicate(ObjectColor.BLUE)); - filter.add(Predicates.not(TappedPredicate.instance)); - } - - GrandArchitectManaAbility() { - super(Zone.BATTLEFIELD, new BasicManaEffect(new GrandArchitectConditionalMana()), new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, true))); - this.netMana.add(Mana.ColorlessMana(2)); + GrandArchitectManaAbility(FilterControlledCreaturePermanent filter) { + super(Zone.BATTLEFIELD, new BasicManaEffect(new GrandArchitectConditionalMana()), + new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, true))); + this.netMana.add(new GrandArchitectConditionalMana()); + this.filter = filter; } GrandArchitectManaAbility(GrandArchitectManaAbility ability) { super(ability); + this.filter = ability.filter.copy(); + } + + @Override + public List getNetMana(Game game) { + if (game.inCheckPlayableState()) { + int count = game.getBattlefield().count(filter, getSourceId(), getControllerId(), game); + List netManaCalculated = new ArrayList<>(); + ConditionalMana mana = new GrandArchitectConditionalMana(); + mana.setColorless(count * 2); + netManaCalculated.add(mana); + return netManaCalculated; + } + return super.getNetMana(game); } @Override diff --git a/Mage.Sets/src/mage/cards/h/HeritageDruid.java b/Mage.Sets/src/mage/cards/h/HeritageDruid.java index 804c1393733..844eab75f4d 100644 --- a/Mage.Sets/src/mage/cards/h/HeritageDruid.java +++ b/Mage.Sets/src/mage/cards/h/HeritageDruid.java @@ -1,19 +1,24 @@ - package mage.cards.h; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; import mage.MageInt; import mage.Mana; +import mage.abilities.Ability; import mage.abilities.costs.common.TapTargetCost; +import mage.abilities.effects.mana.BasicManaEffect; import mage.abilities.mana.SimpleManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; import mage.constants.Zone; +import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledPermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.permanent.TappedPredicate; +import mage.game.Game; import mage.target.common.TargetControlledPermanent; /** @@ -21,15 +26,8 @@ import mage.target.common.TargetControlledPermanent; */ public final class HeritageDruid extends CardImpl { - private static final FilterControlledPermanent filter = new FilterControlledPermanent("untapped Elves you control"); - - static { - filter.add(Predicates.not(TappedPredicate.instance)); - filter.add(SubType.ELF.getPredicate()); - } - public HeritageDruid(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}"); this.subtype.add(SubType.ELF); this.subtype.add(SubType.DRUID); @@ -37,7 +35,13 @@ public final class HeritageDruid extends CardImpl { this.toughness = new MageInt(1); // Tap three untapped Elves you control: Add {G}{G}{G}. - this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, Mana.GreenMana(3), new TapTargetCost(new TargetControlledPermanent(3, 3, filter, true)))); + FilterControlledPermanent filter = new FilterControlledPermanent("untapped Elves you control"); + filter.add(Predicates.not(TappedPredicate.instance)); + filter.add(SubType.ELF.getPredicate()); + this.addAbility(new SimpleManaAbility( + Zone.BATTLEFIELD, + new HeritageDruidManaEffect(filter), + new TapTargetCost(new TargetControlledPermanent(3, 3, filter, true)))); } public HeritageDruid(final HeritageDruid card) { @@ -49,3 +53,35 @@ public final class HeritageDruid extends CardImpl { return new HeritageDruid(this); } } + +class HeritageDruidManaEffect extends BasicManaEffect { + + private final FilterPermanent filter; + + public HeritageDruidManaEffect(FilterPermanent filter) { + super(Mana.GreenMana(3)); + this.filter = filter; + } + + public HeritageDruidManaEffect(final HeritageDruidManaEffect effect) { + super(effect); + this.filter = effect.filter.copy(); + } + + @Override + public HeritageDruidManaEffect copy() { + return new HeritageDruidManaEffect(this); + } + + @Override + public List getNetMana(Game game, Ability source) { + if (game.inCheckPlayableState()) { + int count = game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game) / 3; + List netMana = new ArrayList<>(); + netMana.add(new Mana(0, count * 3, 0, 0, 0, 0, 0, 0)); + return netMana; + } + return super.getNetMana(game, source); + } + +} diff --git a/Mage.Sets/src/mage/cards/s/SetonKrosanProtector.java b/Mage.Sets/src/mage/cards/s/SetonKrosanProtector.java index 298a22bcd73..892bcefe343 100644 --- a/Mage.Sets/src/mage/cards/s/SetonKrosanProtector.java +++ b/Mage.Sets/src/mage/cards/s/SetonKrosanProtector.java @@ -1,10 +1,14 @@ package mage.cards.s; +import java.util.ArrayList; +import java.util.List; import java.util.UUID; import mage.MageInt; import mage.Mana; +import mage.abilities.Ability; import mage.abilities.costs.common.TapTargetCost; +import mage.abilities.effects.mana.BasicManaEffect; import mage.abilities.mana.SimpleManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -12,9 +16,11 @@ import mage.constants.CardType; import mage.constants.SubType; import mage.constants.SuperType; import mage.constants.Zone; +import mage.filter.FilterPermanent; import mage.filter.common.FilterControlledCreaturePermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.permanent.TappedPredicate; +import mage.game.Game; import mage.target.common.TargetControlledCreaturePermanent; /** @@ -23,13 +29,6 @@ import mage.target.common.TargetControlledCreaturePermanent; */ public final class SetonKrosanProtector extends CardImpl { - private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped Druid you control"); - - static { - filter.add(Predicates.not(TappedPredicate.instance)); - filter.add(SubType.DRUID.getPredicate()); - } - public SetonKrosanProtector(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{G}{G}{G}"); addSuperType(SuperType.LEGENDARY); @@ -40,7 +39,12 @@ public final class SetonKrosanProtector extends CardImpl { this.toughness = new MageInt(2); // Tap an untapped Druid you control: Add {G}. - this.addAbility(new SimpleManaAbility(Zone.BATTLEFIELD, Mana.GreenMana(1), + FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("untapped Druid you control"); + filter.add(Predicates.not(TappedPredicate.instance)); + filter.add(SubType.DRUID.getPredicate()); + this.addAbility(new SimpleManaAbility( + Zone.BATTLEFIELD, + new SetonKrosanProtectorManaEffect(filter), new TapTargetCost(new TargetControlledCreaturePermanent(1, 1, filter, true)))); } @@ -53,3 +57,37 @@ public final class SetonKrosanProtector extends CardImpl { return new SetonKrosanProtector(this); } } + +class SetonKrosanProtectorManaEffect extends BasicManaEffect { + + private final FilterPermanent filter; + + public SetonKrosanProtectorManaEffect(FilterPermanent filter) { + super(Mana.GreenMana(1)); + this.filter = filter; + } + + public SetonKrosanProtectorManaEffect(final SetonKrosanProtectorManaEffect effect) { + super(effect); + this.filter = effect.filter.copy(); + } + + @Override + public SetonKrosanProtectorManaEffect copy() { + return new SetonKrosanProtectorManaEffect(this); + } + + @Override + public List getNetMana(Game game, Ability source) { + if (game.inCheckPlayableState()) { + // Because the ability can be used multiple times, multiply with untapped druids + int count = game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game); + List netMana = new ArrayList<>(); + netMana.add(new Mana(0, count, 0,0,0,0,0,0)); + return netMana; + + } + return super.getNetMana(game, source); + } + +} diff --git a/Mage.Sets/src/mage/cards/u/UrzaLordHighArtificer.java b/Mage.Sets/src/mage/cards/u/UrzaLordHighArtificer.java index 2d783f9150a..5754b272882 100644 --- a/Mage.Sets/src/mage/cards/u/UrzaLordHighArtificer.java +++ b/Mage.Sets/src/mage/cards/u/UrzaLordHighArtificer.java @@ -1,5 +1,7 @@ package mage.cards.u; +import java.util.ArrayList; +import java.util.List; import mage.MageInt; import mage.MageObject; import mage.Mana; @@ -27,19 +29,14 @@ import mage.players.Player; import mage.target.common.TargetControlledPermanent; import java.util.UUID; +import mage.abilities.effects.mana.BasicManaEffect; +import mage.filter.FilterPermanent; /** * @author TheElk801 */ public final class UrzaLordHighArtificer extends CardImpl { - private static final FilterControlledPermanent filter - = new FilterControlledArtifactPermanent("untapped artifact you control"); - - static { - filter.add(Predicates.not(TappedPredicate.instance)); - } - public UrzaLordHighArtificer(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}{U}"); @@ -55,9 +52,12 @@ public final class UrzaLordHighArtificer extends CardImpl { ); // Tap an untapped artifact you control: Add {U}. + FilterControlledPermanent filter = new FilterControlledArtifactPermanent("untapped artifact you control"); + filter.add(Predicates.not(TappedPredicate.instance)); this.addAbility(new SimpleManaAbility( - Zone.BATTLEFIELD, Mana.BlueMana(1), new TapTargetCost(new TargetControlledPermanent(filter)) - )); + Zone.BATTLEFIELD, + new UrzaLordHighArtificerManaEffect(filter), + new TapTargetCost(new TargetControlledPermanent(filter)))); // {5}: Shuffle your library, then exile the top card. Until end of turn, you may play that card without paying its mana cost. this.addAbility(new SimpleActivatedAbility(new UrzaLordHighArtificerEffect(), new GenericManaCost(5))); @@ -103,3 +103,35 @@ class UrzaLordHighArtificerEffect extends OneShotEffect { TargetController.YOU, Duration.EndOfTurn, true); } } + +class UrzaLordHighArtificerManaEffect extends BasicManaEffect { + + private final FilterPermanent filter; + + public UrzaLordHighArtificerManaEffect(FilterPermanent filter) { + super(Mana.BlueMana(1)); + this.filter = filter; + } + + public UrzaLordHighArtificerManaEffect(final UrzaLordHighArtificerManaEffect effect) { + super(effect); + this.filter = effect.filter.copy(); + } + + @Override + public UrzaLordHighArtificerManaEffect copy() { + return new UrzaLordHighArtificerManaEffect(this); + } + + @Override + public List getNetMana(Game game, Ability source) { + if (game.inCheckPlayableState()) { + int count = game.getBattlefield().count(filter, source.getSourceId(), source.getControllerId(), game); + List netMana = new ArrayList<>(); + netMana.add(new Mana(0, 0, count, 0,0,0,0,0)); + return netMana; + } + return super.getNetMana(game, source); + } + +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/mana/MultipleTimesUsableActivatedManaAbilitiesTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/mana/MultipleTimesUsableActivatedManaAbilitiesTest.java new file mode 100644 index 00000000000..f6fe75c5fe3 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/mana/MultipleTimesUsableActivatedManaAbilitiesTest.java @@ -0,0 +1,45 @@ +package org.mage.test.cards.mana; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class MultipleTimesUsableActivatedManaAbilitiesTest extends CardTestPlayerBase { + + /** + * Seton, Krosan Protector - only seems to get counted as if it were one + * mana for determining if a spell can be cast, regardless of how many + * druids you have in playF + */ + @Test + public void testCanBeCastWithSetonKrosanProtector() { + // Tap an untapped Druid you control: Add {G}. + addCard(Zone.BATTLEFIELD, playerA, "Seton, Krosan Protector", 1); // Creature {G}{G}{G} + addCard(Zone.BATTLEFIELD, playerA, "Citanul Druid", 3); + + addCard(Zone.HAND, playerA, "Leatherback Baloth", 1); // Creature 4/5 + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Leatherback Baloth"); + + setChoice(playerA, "Citanul Druid"); + setChoice(playerA, "Citanul Druid"); + setChoice(playerA, "Citanul Druid"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + + + setStrictChooseMode(true); + execute(); + + assertAllCommandsUsed(); + + assertTappedCount("Citanul Druid", true, 3); + assertPermanentCount(playerA, "Leatherback Baloth", 1); + } + +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/ManaReflectionTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/ManaReflectionTest.java index a6175983615..7ff304ebdfb 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/replacement/ManaReflectionTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/replacement/ManaReflectionTest.java @@ -1,11 +1,15 @@ package org.mage.test.cards.replacement; +import mage.abilities.mana.ManaOptions; import mage.constants.ManaType; import mage.constants.PhaseStep; import mage.constants.Zone; import mage.counters.CounterType; +import org.junit.Assert; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; +import static org.mage.test.utils.ManaOptionsTestUtils.assertDuplicatedManaOptions; +import static org.mage.test.utils.ManaOptionsTestUtils.assertManaOptions; public class ManaReflectionTest extends CardTestPlayerBase { @@ -54,4 +58,26 @@ public class ManaReflectionTest extends CardTestPlayerBase { assertManaPool(playerA, ManaType.GREEN, 2); } + + @Test + public void ManaReflectionWithGoblinClearcutterTest() { + // If you tap a permanent for mana, it produces twice as much of that mana instead. + addCard(Zone.BATTLEFIELD, playerA, "Mana Reflection"); + // {T}, Sacrifice a Forest: Add three mana in any combination of {R} and/or {G}. + addCard(Zone.BATTLEFIELD, playerA, "Goblin Clearcutter"); + addCard(Zone.BATTLEFIELD, playerA, "Forest"); + + setStopAt(1, PhaseStep.PRECOMBAT_MAIN); + execute(); + + ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame); + assertDuplicatedManaOptions(manaOptions); + + Assert.assertEquals("mana variations don't fit", 4, manaOptions.size()); + assertManaOptions("{R}{R}{R}{R}{R}{R}{G}{G}", manaOptions); + assertManaOptions("{R}{R}{R}{R}{G}{G}{G}{G}", manaOptions); + assertManaOptions("{R}{R}{G}{G}{G}{G}{G}{G}", manaOptions); + assertManaOptions("{G}{G}{G}{G}{G}{G}{G}{G}", manaOptions); + } + } diff --git a/Mage/src/main/java/mage/abilities/mana/SimpleManaAbility.java b/Mage/src/main/java/mage/abilities/mana/SimpleManaAbility.java index 0877a667c25..dc469b3a7a9 100644 --- a/Mage/src/main/java/mage/abilities/mana/SimpleManaAbility.java +++ b/Mage/src/main/java/mage/abilities/mana/SimpleManaAbility.java @@ -55,7 +55,7 @@ public class SimpleManaAbility extends ActivatedManaAbilityImpl { if (predictable) { return super.getNetMana(game); } - return new ArrayList(netMana); + return new ArrayList<>(netMana); } }