add test for AddManaInAnyCombinationEffect

cleanup Grand Warlord Radha, add test

simplify some abilities to common class

remove unused constructors
This commit is contained in:
xenohedron 2024-07-25 01:35:20 -04:00
parent be3065789d
commit 5cc4901580
8 changed files with 104 additions and 354 deletions

View file

@ -1,26 +1,20 @@
package mage.cards.g;
import mage.MageInt;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.mana.ManaEffect;
import mage.abilities.effects.mana.AddManaInAnyCombinationEffect;
import mage.abilities.mana.SimpleManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.ColoredManaSymbol;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterControlledPermanent;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetControlledPermanent;
import java.util.*;
import java.util.UUID;
/**
* @author BursegSardaukar
@ -41,7 +35,9 @@ public final class GoblinClearcutter extends CardImpl {
this.toughness = new MageInt(3);
// {T}, Sacrifice a Forest: Add three mana in any combination of {R} and/or {G}.
Ability ability = new SimpleManaAbility(Zone.BATTLEFIELD, new GoblinClearCutterManaEffect(), new TapSourceCost());
Ability ability = new SimpleManaAbility(Zone.BATTLEFIELD, new AddManaInAnyCombinationEffect(
3, ColoredManaSymbol.R, ColoredManaSymbol.G
), new TapSourceCost());
ability.addCost(new SacrificeTargetCost(filter));
this.addAbility(ability);
}
@ -55,63 +51,3 @@ public final class GoblinClearcutter extends CardImpl {
return new GoblinClearcutter(this);
}
}
class GoblinClearCutterManaEffect extends ManaEffect {
private final List<Mana> netMana = new ArrayList<>();
public GoblinClearCutterManaEffect() {
super();
this.staticText = "Add three mana in any combination of {R} and/or {G}";
netMana.add(new Mana(0, 0, 0, 0, 3, 0, 0, 0));
netMana.add(new Mana(0, 0, 0, 1, 2, 0, 0, 0));
netMana.add(new Mana(0, 0, 0, 2, 1, 0, 0, 0));
netMana.add(new Mana(0, 0, 0, 3, 0, 0, 0, 0));
}
private GoblinClearCutterManaEffect(final GoblinClearCutterManaEffect effect) {
super(effect);
netMana.addAll(effect.netMana);
}
@Override
public GoblinClearCutterManaEffect copy() {
return new GoblinClearCutterManaEffect(this);
}
@Override
public List<Mana> getNetMana(Game game, Ability source) {
return new ArrayList<>(netMana);
}
@Override
public Mana produceMana(Game game, Ability source) {
Mana mana = new Mana();
if (game == null) {
return mana;
}
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
Choice manaChoice = new ChoiceImpl(false);
Set<String> choices = new LinkedHashSet<>();
choices.add("Red");
choices.add("Green");
manaChoice.setChoices(choices);
manaChoice.setMessage("Select color of mana to add");
for (int i = 0; i < 3; i++) {
if (!player.choose(Outcome.Benefit, manaChoice, game)) {
return mana;
}
switch (manaChoice.getChoice()) {
case "Green":
mana.increaseGreen();
break;
case "Red":
mana.increaseRed();
break;
}
}
}
return mana;
}
}

View file

@ -1,32 +1,20 @@
package mage.cards.g;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageInt;
import mage.MageObjectReference;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.AttacksWithCreaturesTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.abilities.keyword.HasteAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.WatcherScope;
import mage.constants.Zone;
import mage.constants.*;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.watchers.Watcher;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
/**
*
@ -47,7 +35,9 @@ public final class GrandWarlordRadha extends CardImpl {
this.addAbility(HasteAbility.getInstance());
// Whenever one or more creatures you control attack, add that much mana in any combination of {R} and/or {G}. Until end of turn, you don't lose this mana as steps and phases end.
this.addAbility(new GrandWarlordRadhaTriggeredAbility(), new CreaturesAttackedWatcher());
this.addAbility(new AttacksWithCreaturesTriggeredAbility(
new GrandWarlordRadhaEffect(), 1
).setTriggerPhrase("Whenever one or more creatures you control attack, "));
}
private GrandWarlordRadha(final GrandWarlordRadha card) {
@ -60,68 +50,10 @@ public final class GrandWarlordRadha extends CardImpl {
}
}
class CreaturesAttackedWatcher extends Watcher {
private final Set<MageObjectReference> attackedThisTurnCreatures = new HashSet<>();
public CreaturesAttackedWatcher() {
super(WatcherScope.GAME);
}
@Override
public void watch(GameEvent event, Game game) {
if (event.getType() == GameEvent.EventType.BEGIN_COMBAT_STEP_PRE) {
this.attackedThisTurnCreatures.clear();
}
if (event.getType() == GameEvent.EventType.ATTACKER_DECLARED) {
this.attackedThisTurnCreatures.add(new MageObjectReference(event.getSourceId(), game));
}
}
public Set<MageObjectReference> getAttackedThisTurnCreatures() {
return this.attackedThisTurnCreatures;
}
}
class GrandWarlordRadhaTriggeredAbility extends TriggeredAbilityImpl {
public GrandWarlordRadhaTriggeredAbility() {
super(Zone.BATTLEFIELD, new GrandWarlordRadhaEffect(), false);
setTriggerPhrase("Whenever one or more creatures you control attack, ");
}
private GrandWarlordRadhaTriggeredAbility(final GrandWarlordRadhaTriggeredAbility ability) {
super(ability);
}
@Override
public GrandWarlordRadhaTriggeredAbility copy() {
return new GrandWarlordRadhaTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DECLARED_ATTACKERS;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
for (UUID attacker : game.getCombat().getAttackers()) {
Permanent creature = game.getPermanent(attacker);
if (creature != null
&& creature.getControllerId() != null
&& creature.isControlledBy(this.getControllerId())) {
return true;
}
}
return false;
}
}
class GrandWarlordRadhaEffect extends OneShotEffect {
GrandWarlordRadhaEffect() {
super(Outcome.Benefit);
super(Outcome.PutManaInPool);
this.staticText = "add that much mana in any combination of {R} and/or {G}. Until end of turn, you don't lose this mana as steps and phases end";
}
@ -137,46 +69,17 @@ class GrandWarlordRadhaEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
CreaturesAttackedWatcher watcher = game.getState().getWatcher(CreaturesAttackedWatcher.class);
if (watcher != null) {
int attackingCreatures = 0;
for (MageObjectReference attacker : watcher.getAttackedThisTurnCreatures()) {
if (attacker.getPermanentOrLKIBattlefield(game).isControlledBy(controller.getId())) {
attackingCreatures++;
}
}
if (attackingCreatures > 0) {
Choice manaChoice = new ChoiceImpl(false);
Set<String> choices = new LinkedHashSet<>();
choices.add("Red");
choices.add("Green");
manaChoice.setChoices(choices);
manaChoice.setMessage("Select color of mana to add");
for (int i = 0; i < attackingCreatures; i++) {
Mana mana = new Mana();
if (!controller.choose(Outcome.Benefit, manaChoice, game)) {
return false;
}
if (manaChoice.getChoice() == null) { // can happen if player leaves game
return false;
}
switch (manaChoice.getChoice()) {
case "Green":
mana.increaseGreen();
break;
case "Red":
mana.increaseRed();
break;
}
controller.getManaPool().addMana(mana, game, source, true);
}
return true;
}
return true;
}
int amount = (Integer) getValue(AttacksWithCreaturesTriggeredAbility.VALUEKEY_NUMBER_ATTACKERS);
if (controller == null || amount < 1) {
return false;
}
return false;
List<Integer> manaList = controller.getMultiAmount(this.outcome, Arrays.asList("R", "G"), 0, amount, MultiAmountType.MANA, game);
Mana mana = new Mana();
mana.add(new Mana(ColoredManaSymbol.R, manaList.get(0)));
mana.add(new Mana(ColoredManaSymbol.G, manaList.get(1)));
controller.getManaPool().addMana(mana, game, source, true);
return true;
}
}

View file

@ -1,26 +1,20 @@
package mage.cards.o;
import mage.MageInt;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.costs.common.SacrificeTargetCost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.effects.mana.ManaEffect;
import mage.abilities.effects.mana.AddManaInAnyCombinationEffect;
import mage.abilities.mana.SimpleManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.ColoredManaSymbol;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterControlledPermanent;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetControlledPermanent;
import java.util.*;
import java.util.UUID;
/**
* @author LevelX2
@ -41,7 +35,9 @@ public final class OrcishLumberjack extends CardImpl {
this.toughness = new MageInt(1);
// {tap}, Sacrifice a Forest: Add three mana in any combination of {R} and/or {G}.
Ability ability = new SimpleManaAbility(Zone.BATTLEFIELD, new OrcishLumberjackManaEffect(), new TapSourceCost());
Ability ability = new SimpleManaAbility(Zone.BATTLEFIELD, new AddManaInAnyCombinationEffect(
3, ColoredManaSymbol.R, ColoredManaSymbol.G
), new TapSourceCost());
ability.addCost(new SacrificeTargetCost(filter));
this.addAbility(ability);
@ -56,64 +52,3 @@ public final class OrcishLumberjack extends CardImpl {
return new OrcishLumberjack(this);
}
}
class OrcishLumberjackManaEffect extends ManaEffect {
private List<Mana> netMana = new ArrayList<>();
public OrcishLumberjackManaEffect() {
super();
this.staticText = "Add three mana in any combination of {R} and/or {G}";
netMana.add(new Mana(0, 0, 0, 0, 3, 0, 0, 0));
netMana.add(new Mana(0, 0, 0, 1, 2, 0, 0, 0));
netMana.add(new Mana(0, 0, 0, 2, 1, 0, 0, 0));
netMana.add(new Mana(0, 0, 0, 3, 0, 0, 0, 0));
}
private OrcishLumberjackManaEffect(final OrcishLumberjackManaEffect effect) {
super(effect);
netMana.addAll(effect.netMana);
}
@Override
public OrcishLumberjackManaEffect copy() {
return new OrcishLumberjackManaEffect(this);
}
@Override
public List<Mana> getNetMana(Game game, Ability source) {
return netMana;
}
@Override
public Mana produceMana(Game game, Ability source) {
Mana mana = new Mana();
if (game == null) {
return mana;
}
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
Choice manaChoice = new ChoiceImpl(false);
Set<String> choices = new LinkedHashSet<>();
choices.add("Red");
choices.add("Green");
manaChoice.setChoices(choices);
manaChoice.setMessage("Select color of mana to add");
for (int i = 0; i < 3; i++) {
if (!player.choose(Outcome.Benefit, manaChoice, game)) {
return mana;
}
switch (manaChoice.getChoice()) {
case "Green":
mana.increaseGreen();
break;
case "Red":
mana.increaseRed();
break;
}
}
}
return mana;
}
}

View file

@ -1,29 +1,21 @@
package mage.cards.s;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.UUID;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect;
import mage.abilities.effects.mana.AddManaOfAnyColorEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.choices.Choice;
import mage.choices.ChoiceImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.SuperType;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.game.permanent.token.DragonToken;
import mage.players.Player;
import mage.target.common.TargetCardInLibrary;
import java.util.UUID;
/**
*
* @author JRHerlehy
@ -44,7 +36,9 @@ public final class SarkhanUnbroken extends CardImpl {
this.setStartingLoyalty(4);
// +1: Draw a card, then add one mana of any color.
this.addAbility(new LoyaltyAbility(new SarkhanUnbrokenAbility1(), 1));
LoyaltyAbility loyaltyAbility = new LoyaltyAbility(new DrawCardSourceControllerEffect(1), 1);
loyaltyAbility.addEffect(new AddManaOfAnyColorEffect().concatBy(", then"));
this.addAbility(loyaltyAbility);
// -2: Create a 4/4 red Dragon creature token with flying.
this.addAbility(new LoyaltyAbility(new CreateTokenEffect(new DragonToken(), 1), -2));
// -8: Search your library for any number of Dragon creature cards and put them onto the battlefield. Then shuffle your library.
@ -60,68 +54,3 @@ public final class SarkhanUnbroken extends CardImpl {
return new SarkhanUnbroken(this);
}
}
class SarkhanUnbrokenAbility1 extends OneShotEffect {
public SarkhanUnbrokenAbility1() {
super(Outcome.Benefit);
this.staticText = "Draw a card, then add one mana of any color.";
}
private SarkhanUnbrokenAbility1(final SarkhanUnbrokenAbility1 effect) {
super(effect);
}
@Override
public SarkhanUnbrokenAbility1 copy() {
return new SarkhanUnbrokenAbility1(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
controller.drawCards(1, source, game);
game.fireUpdatePlayersEvent();
Choice manaChoice = new ChoiceImpl(false);
Set<String> choices = new LinkedHashSet<>();
choices.add("White");
choices.add("Blue");
choices.add("Black");
choices.add("Red");
choices.add("Green");
manaChoice.setChoices(choices);
manaChoice.setMessage("Select color of mana to add");
Mana mana = new Mana();
if (!controller.choose(Outcome.Benefit, manaChoice, game)) {
return false;
}
switch (manaChoice.getChoice()) {
case "White":
mana.increaseWhite();
break;
case "Blue":
mana.increaseBlue();
break;
case "Black":
mana.increaseBlack();
break;
case "Red":
mana.increaseRed();
break;
case "Green":
mana.increaseGreen();
break;
}
controller.getManaPool().addMana(mana, game, source);
return true;
}
return false;
}
}

View file

@ -0,0 +1,31 @@
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;
public class AddManaAnyCombinationTest extends CardTestPlayerBase {
@Test
public void testOrcishLumberjack() {
String ability = "{T}, Sacrifice a Forest: Add three mana in any combination of {R} and/or {G}.";
addCard(Zone.BATTLEFIELD, playerA, "Orcish Lumberjack");
addCard(Zone.BATTLEFIELD, playerA, "Forest");
addCard(Zone.HAND, playerA, "Living Twister");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, ability);
setChoice(playerA, "Forest"); // to sac
setChoiceAmount(playerA, 2, 1); // RRG
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Living Twister");
setStrictChooseMode(true);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPowerToughness(playerA, "Living Twister", 2, 5);
assertGraveyardCount(playerA, "Forest", 1);
}
}

View file

@ -0,0 +1,31 @@
package org.mage.test.cards.single.dom;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
public class GrandWarlordRadhaTest extends CardTestPlayerBase {
@Test
public void testMana() {
addCard(Zone.BATTLEFIELD, playerA, "Raging Goblin");
addCard(Zone.BATTLEFIELD, playerA, "Lightning Elemental");
addCard(Zone.BATTLEFIELD, playerA, "Grand Warlord Radha");
addCard(Zone.HAND, playerA, "Living Twister");
attack(1, playerA, "Raging Goblin");
attack(1, playerA, "Lightning Elemental");
attack(1, playerA, "Grand Warlord Radha");
setChoiceAmount(playerA, 2, 1); // RRG
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Living Twister");
setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertPowerToughness(playerA, "Living Twister", 2, 5);
}
}

View file

@ -19,7 +19,7 @@ import java.util.*;
*/
public class AddManaInAnyCombinationEffect extends ManaEffect {
private ArrayList<ColoredManaSymbol> manaSymbols = new ArrayList<>();
private List<ColoredManaSymbol> manaSymbols = new ArrayList<>();
private final DynamicValue amount;
private final DynamicValue netAmount;
@ -45,21 +45,6 @@ public class AddManaInAnyCombinationEffect extends ManaEffect {
this.netAmount = netAmount;
}
public AddManaInAnyCombinationEffect(int amount, String text) {
this(amount);
this.staticText = text;
}
public AddManaInAnyCombinationEffect(int amount, String text, ColoredManaSymbol... coloredManaSymbols) {
this(amount, coloredManaSymbols);
this.staticText = text;
}
public AddManaInAnyCombinationEffect(DynamicValue amount, DynamicValue netAmount, String text, ColoredManaSymbol... coloredManaSymbols) {
this(amount, netAmount, coloredManaSymbols);
this.staticText = text;
}
protected AddManaInAnyCombinationEffect(final AddManaInAnyCombinationEffect effect) {
super(effect);
this.manaSymbols = effect.manaSymbols;

View file

@ -19,7 +19,7 @@ import java.util.Set;
*/
public abstract class ManaEffect extends OneShotEffect {
public ManaEffect() {
protected ManaEffect() {
super(Outcome.PutManaInPool);
}