From ac2a59fdc2207faa4f333dc5ebf1b2076c8edf78 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Fri, 10 Jan 2020 15:48:21 +0100 Subject: [PATCH] * Added better handling of TargetAmount for tests. --- .../test/cards/triggers/SpellskiteTest.java | 16 ++-- .../java/org/mage/test/player/TestPlayer.java | 84 +++++++++---------- .../test/serverside/base/MageTestBase.java | 31 +++---- .../base/impl/CardTestPlayerAPIImpl.java | 5 ++ 4 files changed, 68 insertions(+), 68 deletions(-) diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/SpellskiteTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/SpellskiteTest.java index 976276de27c..a00fce8d9d0 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/SpellskiteTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/SpellskiteTest.java @@ -246,14 +246,14 @@ public class SpellskiteTest extends CardTestPlayerBase { addCard(Zone.BATTLEFIELD, playerB, "Royal Assassin"); // 1/1 addCard(Zone.BATTLEFIELD, playerB, "Blinking Spirit"); // 2/2 addCard(Zone.BATTLEFIELD, playerB, "Pearled Unicorn"); // 2/2 - + // Fiery Justice deals 5 damage divided as you choose among any number of target creatures and/or players. Target opponent gains 5 life. addCard(Zone.HAND, playerA, "Fiery Justice"); - // A cast Fiery Justice + // Cast Fiery Justice castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Fiery Justice"); addTarget(playerA, playerB); // 5 life to B - addTarget(playerA, "Scute Mob^X=1"); // target 1 - addTarget(playerA, "Spellskite^X=4"); // target 2 + addTargetAmount(playerA, "Scute Mob" , 1); // target 1 + addTargetAmount(playerA, "Spellskite", 4); // target 2 // B activate Spellskite, but can't change any targets cause it's already targeted activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{U/P}: Change a target", "Fiery Justice", "Fiery Justice"); setChoice(playerB, "Yes"); // pay 2 life @@ -288,7 +288,7 @@ public class SpellskiteTest extends CardTestPlayerBase { addCard(Zone.HAND, playerA, "Fiery Justice"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Fiery Justice"); // 5 damage distributed to any number of targets - addTarget(playerA, "Scute Mob^X=5"); + addTargetAmount(playerA, "Scute Mob", 5); activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{U/P}: Change a target", "Fiery Justice", "Fiery Justice"); setChoice(playerB, "Yes"); // pay 2 life @@ -319,9 +319,9 @@ public class SpellskiteTest extends CardTestPlayerBase { addCard(Zone.HAND, playerA, "Fiery Justice"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Fiery Justice"); // 5 damage distributed to any number of targets - addTarget(playerA, "Royal Assassin^X=1"); - addTarget(playerA, "Blinking Spirit^X=2"); - addTarget(playerA, "Pearled Unicorn^X=2"); + addTargetAmount(playerA, "Royal Assassin",1); + addTargetAmount(playerA, "Blinking Spirit",2); + addTargetAmount(playerA, "Pearled Unicorn",2); activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{U/P}: Change a target", "Fiery Justice", "Fiery Justice"); setChoice(playerB, "Yes"); // pay 2 life diff --git a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java index 329c16b95d1..651a8d0fab1 100644 --- a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java +++ b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java @@ -2,6 +2,7 @@ package org.mage.test.player; import java.io.Serializable; import java.util.*; +import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -16,6 +17,7 @@ import mage.abilities.costs.Costs; import mage.abilities.costs.VariableCost; import mage.abilities.costs.mana.ManaCost; import mage.abilities.costs.mana.ManaCosts; +import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.mana.ActivatedManaAbilityImpl; import mage.abilities.mana.ManaOptions; import mage.cards.Card; @@ -70,7 +72,7 @@ import static org.mage.test.serverside.base.impl.CardTestPlayerAPIImpl.*; @Ignore public class TestPlayer implements Player { - private static final Logger logger = Logger.getLogger(TestPlayer.class); + private static final Logger LOGGER = Logger.getLogger(TestPlayer.class); public static final String TARGET_SKIP = "[target_skip]"; public static final String BLOCK_SKIP = "[block_skip]"; @@ -82,6 +84,7 @@ public class TestPlayer implements Player { private final List actions = new ArrayList<>(); private final List choices = new ArrayList<>(); // choices stack for choice private final List targets = new ArrayList<>(); // targets stack for choose (it's uses on empty direct target by cast command) + private final LinkedHashMap targetsAmount = new LinkedHashMap<>(); // targets and amounts for targets that also need to set an amount private final Map aliases = new HashMap<>(); // aliases for game objects/players (use it for cards with same name to save and use) private final List modesSet = new ArrayList<>(); @@ -153,6 +156,16 @@ public class TestPlayer implements Player { targets.add(target); } + /** + * Sets the data for TargetAmount classes that include also an amount beside the target like TargetPermanentAmount + * + * @param targetName + * @param amount + */ + public void addTargetAmount(String targetName, Integer amount) { + targetsAmount.put(targetName, amount); + } + public void addAlias(String name, UUID Id) { aliases.put(name, Id); } @@ -3277,59 +3290,40 @@ public class TestPlayer implements Player { return computerPlayer.choose(outcome, cards, target, game); } - @Override + @Override public boolean chooseTargetAmount(Outcome outcome, TargetAmount target, - Ability source, Game game + Ability source, Game game ) { - // command format: targetName^X=3 - - // chooseTargetAmount calls by TargetAmount for EACH target cycle - Assert.assertTrue("chooseTargetAmount supports only one target, but found " + target.getMaxNumberOfTargets(), target.getMaxNumberOfTargets() <= 1); - Assert.assertNotEquals("chooseTargetAmount need remaining > 0", 0, target.getAmountRemaining()); - - if (!targets.isEmpty()) { - - boolean founded = false; - String foundedRecord = ""; - CheckTargets: - for (String targetRecord : targets) { - String[] choiceSettings = targetRecord.split("\\^"); - if (choiceSettings.length == 2 && choiceSettings[1].startsWith("X=")) { - // can choice - String choiceName = choiceSettings[0]; - int choiceAmount = Integer.parseInt(choiceSettings[1].substring(2)); - - Assert.assertNotEquals("choice amount must be not zero", 0, choiceAmount); - Assert.assertTrue("choice amount " + choiceAmount + "must be <= remaining " + target.getAmountRemaining(), choiceAmount <= target.getAmountRemaining()); - - for (UUID possibleTarget : target.possibleTargets(source.getSourceId(), source.getControllerId(), game)) { - MageObject objectPermanent = game.getObject(possibleTarget); - Player objectPlayer = game.getPlayer(possibleTarget); - String objectName = objectPermanent != null ? objectPermanent.getName() : objectPlayer.getName(); - if (objectName.equals(choiceName)) { - if (!target.getTargets().contains(possibleTarget) && target.canTarget(possibleTarget, source, game)) { - // can select - target.addTarget(possibleTarget, choiceAmount, source, game); - founded = true; - foundedRecord = targetRecord; - break CheckTargets; + if (!targetsAmount.isEmpty()) { + for (Iterator> iterator = targetsAmount.entrySet().iterator(); iterator.hasNext();) { + Entry targetRecord = iterator.next(); + if (target.getAmountRemaining() > 0) { + target.possibleTargets(source.getSourceId(), source.getControllerId(), game).forEach((possibleTarget) -> { + MageObject objectPermanent = game.getObject(possibleTarget); + Player objectPlayer = game.getPlayer(possibleTarget); + String objectName = objectPermanent != null ? objectPermanent.getName() : objectPlayer.getName(); + if (objectName.equals(targetRecord.getKey())) { + if (!target.getTargets().contains(possibleTarget) && target.canTarget(possibleTarget, source, game)) { + // can select + target.addTarget(possibleTarget, targetRecord.getValue(), source, game); + iterator.remove(); + } } - } - } + }); } - } - - if (founded) { - // all done - targets.remove(foundedRecord); + } + } + if (!target.isRequired() && target.getAmountRemaining() > 0) { + if (strictChooseMode) { + target.setAmountDefinition(StaticValue.get(0)); + target.setAmount(source, game); return true; } } - - this.chooseStrictModeFailed(game, getInfo(source) + "; " + getInfo(target)); + this.chooseStrictModeFailed(game, getInfo(source) + "; " + getInfo(target)); return computerPlayer.chooseTargetAmount(outcome, target, source, game); } - + @Override public boolean chooseMulligan(Game game ) { diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestBase.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestBase.java index a8573992fd8..6aca7be4ffc 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestBase.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestBase.java @@ -43,7 +43,7 @@ public abstract class MageTestBase { public static PluginClassLoader classLoader = new PluginClassLoader(); - private static final String pluginFolder = "plugins"; + private static final String PLUGIN_FOLDER = "plugins"; protected Pattern pattern = Pattern.compile("([a-zA-Z]*):([\\w]*):([a-zA-Z ,\\-.!'\\d]*):([\\d]*)(:\\{tapped\\})?"); @@ -88,7 +88,7 @@ public abstract class MageTestBase { /** * Expected results of the test. Read from test case in {@link String} based * format: - *

+ *

* Example: turn:1 result:won:ComputerA life:ComputerA:20 life:ComputerB:0 * battlefield:ComputerB:Tine Shrike:0 graveyard:ComputerB:Tine Shrike:1 */ @@ -103,24 +103,25 @@ public abstract class MageTestBase { logger.info("Logging level: " + logger.getLevel()); deleteSavedGames(); ConfigSettings config = ConfigSettings.instance; - for (GamePlugin plugin : config.getGameTypes()) { - GameFactory.instance.addGameType(plugin.getName(), loadGameType(plugin), loadPlugin(plugin)); - } - for (GamePlugin plugin : config.getTournamentTypes()) { - TournamentFactory.instance.addTournamentType(plugin.getName(), loadTournamentType(plugin), loadPlugin(plugin)); - } - for (Plugin plugin : config.getPlayerTypes()) { - PlayerFactory.instance.addPlayerType(plugin.getName(), loadPlugin(plugin)); - } + config.getGameTypes().forEach((gameType) -> { + GameFactory.instance.addGameType(gameType.getName(), loadGameType(gameType), loadPlugin(gameType)); + }); + config.getTournamentTypes().forEach((tournamentType) -> { + TournamentFactory.instance.addTournamentType(tournamentType.getName(), loadTournamentType(tournamentType), loadPlugin(tournamentType)); + }); + config.getPlayerTypes().forEach((playerType) -> { + PlayerFactory.instance.addPlayerType(playerType.getName(), loadPlugin(playerType)); + }); // for (Plugin plugin : config.getDeckTypes()) { // DeckValidatorFactory.getInstance().addDeckType(plugin.getName(), loadPlugin(plugin)); // } Copier.setLoader(classLoader); } + @SuppressWarnings("UseSpecificCatch") private static Class loadPlugin(Plugin plugin) { try { - classLoader.addURL(new File(pluginFolder + '/' + plugin.getJar()).toURI().toURL()); + classLoader.addURL(new File(PLUGIN_FOLDER + '/' + plugin.getJar()).toURI().toURL()); logger.debug("Loading plugin: " + plugin.getClassName()); return Class.forName(plugin.getClassName(), true, classLoader); } catch (ClassNotFoundException ex) { @@ -133,11 +134,11 @@ public abstract class MageTestBase { private static MatchType loadGameType(GamePlugin plugin) { try { - classLoader.addURL(new File(pluginFolder + '/' + plugin.getJar()).toURI().toURL()); + classLoader.addURL(new File(PLUGIN_FOLDER + '/' + plugin.getJar()).toURI().toURL()); logger.debug("Loading game type: " + plugin.getClassName()); return (MatchType) Class.forName(plugin.getTypeName(), true, classLoader).getConstructor().newInstance(); } catch (ClassNotFoundException ex) { - logger.warn("Game type not found:" + plugin.getJar() + " - check plugin folder"); + logger.warn("Game type not found:" + plugin.getJar() + " - check plugin folder", ex); } catch (Exception ex) { logger.fatal("Error loading game type " + plugin.getJar(), ex); } @@ -146,7 +147,7 @@ public abstract class MageTestBase { private static TournamentType loadTournamentType(GamePlugin plugin) { try { - classLoader.addURL(new File(pluginFolder + '/' + plugin.getJar()).toURI().toURL()); + classLoader.addURL(new File(PLUGIN_FOLDER + '/' + plugin.getJar()).toURI().toURL()); logger.info("Loading tournament type: " + plugin.getClassName()); return (TournamentType) Class.forName(plugin.getTypeName(), true, classLoader).getConstructor().newInstance(); } catch (ClassNotFoundException ex) { diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java index a5afdfc8020..c7f159a9526 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/impl/CardTestPlayerAPIImpl.java @@ -1604,6 +1604,11 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement player.addTarget("targetPlayer=" + targetPlayer.getName()); } + public void addTargetAmount(TestPlayer player, String target, int amount) { + player.addTargetAmount(target, amount); + } + + public void setDecknamePlayerA(String deckname) { deckNameA = deckname; }