diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/IrencragFeatTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/IrencragFeatTest.java index 93f09009b9..3ebb83bc4c 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/IrencragFeatTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/IrencragFeatTest.java @@ -18,14 +18,23 @@ public class IrencragFeatTest extends CardTestPlayerBase { addCard(Zone.HAND, playerA, "Irencrag Feat", 1); addCard(Zone.HAND, playerA, "Dwarven Trader", 2); + // 1 + checkPlayableAbility("can cast before", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Dwarven Trader", true); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Irencrag Feat"); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + + // 2 + checkPlayableAbility("can cast after feat 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Dwarven Trader", true); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dwarven Trader"); - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dwarven Trader"); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + + // 3 + checkPlayableAbility("can't cast after feat 2", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Dwarven Trader", false); setStrictChooseMode(true); setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); - //assertAllCommandsUsed(); // second trader must be restricted to cast + assertAllCommandsUsed(); assertHandCount(playerA, "Dwarven Trader", 1); assertPermanentCount(playerA, "Dwarven Trader", 1); @@ -38,16 +47,32 @@ public class IrencragFeatTest extends CardTestPlayerBase { addCard(Zone.HAND, playerA, "Irencrag Feat", 1); addCard(Zone.HAND, playerA, "Dwarven Trader", 4); + // 1 + checkPlayableAbility("can cast before feat 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Dwarven Trader", true); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dwarven Trader"); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + + // 2 + checkPlayableAbility("can cast before feat 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Dwarven Trader", true); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dwarven Trader"); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + + // 3 castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Irencrag Feat"); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + + // 4 + checkPlayableAbility("can cast after feat 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Dwarven Trader", true); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dwarven Trader"); - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dwarven Trader"); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + + // 5 + checkPlayableAbility("can't cast after feat 2", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Dwarven Trader", false); setStrictChooseMode(true); setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); - //assertAllCommandsUsed(); // second trader must be restricted to cast + assertAllCommandsUsed(); assertHandCount(playerA, "Dwarven Trader", 1); assertPermanentCount(playerA, "Dwarven Trader", 3); @@ -59,6 +84,7 @@ public class IrencragFeatTest extends CardTestPlayerBase { addCard(Zone.HAND, playerA, "Irencrag Feat", 1); addCard(Zone.HAND, playerA, "Lightning Bolt", 4); + // no restrictions for stack castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Irencrag Feat"); @@ -80,17 +106,25 @@ public class IrencragFeatTest extends CardTestPlayerBase { addCard(Zone.HAND, playerA, "Irencrag Feat", 1); addCard(Zone.HAND, playerA, "Lightning Bolt", 4); + // on stack before + checkPlayableAbility("can cast before feat 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Lightning Bolt", true); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB); + checkPlayableAbility("can cast before feat 2", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Lightning Bolt", true); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB); + + // feat castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Irencrag Feat"); waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + + // after resolve + checkPlayableAbility("can cast after feat 1", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Lightning Bolt", true); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB); - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB); + checkPlayableAbility("can't cast after feat 2", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Lightning Bolt", false); setStrictChooseMode(true); setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); - //assertAllCommandsUsed(0); // second bolt must be restricted to cast + assertAllCommandsUsed(); assertHandCount(playerA, "Lightning Bolt", 4 - 3); assertLife(playerB, 20 - 3 * 3); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/cost/adventure/AdventureCardsTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/cost/adventure/AdventureCardsTest.java index 6fdacc5560..c73adcb959 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/cost/adventure/AdventureCardsTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/cost/adventure/AdventureCardsTest.java @@ -39,14 +39,20 @@ public class AdventureCardsTest extends CardTestPlayerBase { @Test public void testCantCastTreatsToShareTwice() { - setStrictChooseMode(true); - addCard(Zone.BATTLEFIELD, playerA, "Forest", 2); addCard(Zone.HAND, playerA, "Curious Pair"); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 2); + + checkPlayableAbility("can play on first", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Treats to Share", true); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Treats to Share"); - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Treats to Share"); + + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN); + checkPlayableAbility("can't play on second", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Treats to Share", false); + + setStrictChooseMode(true); setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); - assertActionsCount(playerA, 1); + assertAllCommandsUsed(); + assertHandCount(playerA, 0); assertPermanentCount(playerA, "Food", 1); assertExileCount(playerA, "Curious Pair", 1); @@ -430,18 +436,21 @@ public class AdventureCardsTest extends CardTestPlayerBase { @Test public void testCantCastCuriousPairWithMelek() { - setStrictChooseMode(true); - addCard(Zone.BATTLEFIELD, playerA, "Melek, Izzet Paragon"); - addCard(Zone.BATTLEFIELD, playerA, "Forest", 2); removeAllCardsFromLibrary(playerA); + + addCard(Zone.BATTLEFIELD, playerA, "Melek, Izzet Paragon"); + // addCard(Zone.LIBRARY, playerA, "Curious Pair"); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 2); - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Curious Pair"); + checkPlayableAbility("can't play", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Curious Pair", false); + checkPlayableAbility("can play", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Treats to Share", true); + setStrictChooseMode(true); setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); + assertAllCommandsUsed(); - assertActionsCount(playerA, 1); assertPermanentCount(playerA, "Curious Pair", 0); assertLibraryCount(playerA, 1); } @@ -477,19 +486,21 @@ public class AdventureCardsTest extends CardTestPlayerBase { @Test public void testCantCastTreatsToShareWithGarruksHorde() { - setStrictChooseMode(true); - addCard(Zone.BATTLEFIELD, playerA, "Garruk's Horde"); - addCard(Zone.BATTLEFIELD, playerA, "Forest"); removeAllCardsFromLibrary(playerA); + + addCard(Zone.BATTLEFIELD, playerA, "Garruk's Horde"); + // addCard(Zone.LIBRARY, playerA, "Curious Pair"); + addCard(Zone.BATTLEFIELD, playerA, "Forest", 2); - // showAvaileableAbilities("abils", 1, PhaseStep.PRECOMBAT_MAIN, playerA); - castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Treats to Share"); + checkPlayableAbility("can play", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Curious Pair", true); + checkPlayableAbility("can't play", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Treats to Share", false); + setStrictChooseMode(true); setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); + assertAllCommandsUsed(); - assertActionsCount(playerA, 1); assertPermanentCount(playerA, "Food", 0); assertLibraryCount(playerA, 1); } 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 f5bf8f8b2a..fdb665dd5e 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 @@ -42,6 +42,7 @@ import mage.game.match.Match; import mage.game.match.MatchPlayer; import mage.game.permanent.Permanent; import mage.game.permanent.PermanentToken; +import mage.game.stack.Spell; import mage.game.stack.StackObject; import mage.game.tournament.Tournament; import mage.player.ai.ComputerPlayer; @@ -430,6 +431,8 @@ public class TestPlayer implements Player { // two search mode: for cards/permanents (strict) and for abilities (like) if (object instanceof Ability) { return object.getName().startsWith(nameOrAlias); + } else if (object instanceof Spell) { + return ((Spell) object).getSpellAbility().getName().startsWith(nameOrAlias); } else { return object.getName().equals(nameOrAlias); } @@ -668,11 +671,13 @@ public class TestPlayer implements Player { } } else if (action.getAction().startsWith("waitStackResolved")) { if (game.getStack().isEmpty()) { - // can use next command + // all done, can use next command actions.remove(action); + continue; } else { - // need pass to empty stack - break; + // need to wait (don't remove command) + tryToPlayPriority(game); + return true; } } else if (action.getAction().startsWith("playerAction:")) { String command = action.getAction(); @@ -692,6 +697,7 @@ public class TestPlayer implements Player { game.concede(getId()); ((GameImpl) game).checkConcede(); actions.remove(action); + return true; } } } else if (action.getAction().startsWith(AI_PREFIX)) { @@ -786,6 +792,13 @@ public class TestPlayer implements Player { wasProccessed = true; } + // check graveyard count: card name, count + if (params[0].equals(CHECK_COMMAND_GRAVEYARD_COUNT) && params.length == 3) { + assertGraveyardCount(action, game, computerPlayer, params[1], Integer.parseInt(params[2])); + actions.remove(action); + wasProccessed = true; + } + // check hand count: count if (params[0].equals(CHECK_COMMAND_HAND_COUNT) && params.length == 2) { assertHandCount(action, game, computerPlayer, Integer.parseInt(params[1])); @@ -842,7 +855,9 @@ public class TestPlayer implements Player { wasProccessed = true; } } - if (!wasProccessed) { + if (wasProccessed) { + return true; + } else { Assert.fail("Unknow check command or params: " + command); } } else if (action.getAction().startsWith(SHOW_PREFIX)) { @@ -938,17 +953,23 @@ public class TestPlayer implements Player { } } - if (!wasProccessed) { + if (wasProccessed) { + return true; + } else { Assert.fail("Unknow show command or params: " + command); } } - } - } - if (AIPlayer) { - computerPlayer.priority(game); - } else { - computerPlayer.pass(game); + + // you don't need to use stack command all the time, so some cast commands can be skiped to next check + if (game.getStack().isEmpty()) { + this.chooseStrictModeFailed("cast/activate", game, + "Can't find available command - " + action.getAction() + " (use checkPlayableAbility for non castable checks)", true); + } + } // turn/step } + + tryToPlayPriority(game); + // check to prevent endless loops if (numberOfActions == actions.size()) { foundNoAction++; @@ -962,6 +983,14 @@ public class TestPlayer implements Player { return false; } + private void tryToPlayPriority(Game game) { + if (AIPlayer) { + computerPlayer.priority(game); + } else { + computerPlayer.pass(game); + } + } + private Permanent findPermanentWithAssert(PlayerAction action, Game game, Player player, String cardName) { for (Permanent perm : game.getBattlefield().getAllPermanents()) { // need by controller @@ -1208,6 +1237,17 @@ public class TestPlayer implements Player { Assert.assertEquals(action.getActionName() + " - card " + permanentName + " must exists in exile zone with " + count + " instances", count, foundedCount); } + private void assertGraveyardCount(PlayerAction action, Game game, Player player, String permanentName, int count) { + int foundedCount = 0; + for (Card card : player.getGraveyard().getCards(game)) { + if (isObjectHaveTargetNameOrAlias(card, permanentName) && card.isOwnedBy(player.getId())) { + foundedCount++; + } + } + + Assert.assertEquals(action.getActionName() + " - card " + permanentName + " must exists in graveyard zone with " + count + " instances", count, foundedCount); + } + private void assertHandCount(PlayerAction action, Game game, Player player, int count) { Assert.assertEquals(action.getActionName() + " - hand must contain " + count, count, player.getHand().size()); } @@ -1668,7 +1708,16 @@ public class TestPlayer implements Player { } private void chooseStrictModeFailed(String choiceType, Game game, String reason) { + chooseStrictModeFailed(choiceType, game, reason, false); + } + + private void chooseStrictModeFailed(String choiceType, Game game, String reason, boolean printAbilities) { if (strictChooseMode && !AICanChooseInStrictMode) { + if (printAbilities) { + printStart("Available abilities for " + computerPlayer.getName()); + printAbilities(game, computerPlayer.getPlayable(game, true)); + printEnd(); + } Assert.fail("Missing " + choiceType + " def for" + " turn " + game.getTurnNum() + ", step " + (game.getStep() != null ? game.getStep().getType().name() : "not started") 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 8727880ee6..6d5b96b9cf 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 @@ -93,6 +93,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement public static final String CHECK_COMMAND_PERMANENT_COUNT = "PERMANENT_COUNT"; public static final String CHECK_COMMAND_PERMANENT_COUNTERS = "PERMANENT_COUNTERS"; public static final String CHECK_COMMAND_EXILE_COUNT = "EXILE_COUNT"; + public static final String CHECK_COMMAND_GRAVEYARD_COUNT = "GRAVEYARD_COUNT"; public static final String CHECK_COMMAND_HAND_COUNT = "HAND_COUNT"; public static final String CHECK_COMMAND_HAND_CARD_COUNT = "HAND_CARD_COUNT"; public static final String CHECK_COMMAND_COMMAND_CARD_COUNT = "COMMAND_CARD_COUNT"; @@ -380,6 +381,11 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement check(checkName, turnNum, step, player, CHECK_COMMAND_EXILE_COUNT, permanentName, count.toString()); } + public void checkGraveyardCount(String checkName, int turnNum, PhaseStep step, TestPlayer player, String permanentName, Integer count) { + //Assert.assertNotEquals("", permanentName); + check(checkName, turnNum, step, player, CHECK_COMMAND_GRAVEYARD_COUNT, permanentName, count.toString()); + } + public void checkHandCount(String checkName, int turnNum, PhaseStep step, TestPlayer player, Integer count) { check(checkName, turnNum, step, player, CHECK_COMMAND_HAND_COUNT, count.toString()); } diff --git a/Mage/src/main/java/mage/abilities/SpellAbility.java b/Mage/src/main/java/mage/abilities/SpellAbility.java index 1978d8e162..a0ee47b51c 100644 --- a/Mage/src/main/java/mage/abilities/SpellAbility.java +++ b/Mage/src/main/java/mage/abilities/SpellAbility.java @@ -145,9 +145,13 @@ public class SpellAbility extends ActivatedAbilityImpl { this.costs.clearPaid(); } + public String getName() { + return this.name; + } + @Override public String toString() { - return this.name; + return getName(); } @Override