* Specific instance: Snapcaster Mage granting Flashback to Repeal
*/
@Test
@@ -84,7 +81,7 @@ public class FlashbackTest extends CardTestPlayerBase {
addCard(Zone.GRAVEYARD, playerA, "Repeal", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Snapcaster Mage");
- setChoice(playerA, "Repeal");
+ addTarget(playerA, "Repeal");
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Flashback");
setChoice(playerA, "X=2");
@@ -100,10 +97,9 @@ public class FlashbackTest extends CardTestPlayerBase {
}
/**
- *
* Test Granting Flashback to spells with X in mana cost, where X has no
* influence on targeting requirements
- *
+ *
* Specific instance: Snapcaster Mage granting Flashback to Blaze
*/
@Test
@@ -115,7 +111,7 @@ public class FlashbackTest extends CardTestPlayerBase {
addCard(Zone.GRAVEYARD, playerA, "Blaze", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Snapcaster Mage");
- setChoice(playerA, "Blaze");
+ addTarget(playerA, "Blaze");
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Flashback");
setChoice(playerA, "X=1");
@@ -133,7 +129,6 @@ public class FlashbackTest extends CardTestPlayerBase {
/**
* My opponent put Iona on the battlefield using Unburial Rites, but my game
* log didn't show me the color he has chosen.
- *
*/
@Test
public void testUnburialRites() {
@@ -238,7 +233,7 @@ public class FlashbackTest extends CardTestPlayerBase {
* Ancestral Vision has no casting cost (this is different to a casting cost
* of {0}). Snapcaster Mage, for example, is able to give it flashback
* whilst it is in the graveyard.
- *
+ *
* However the controller should not be able to cast Ancestral Visions from
* the graveyard for {0} mana.
*/
@@ -348,7 +343,7 @@ public class FlashbackTest extends CardTestPlayerBase {
// When Snapcaster Mage enters the battlefield, target instant or sorcery card in your graveyard gains flashback until end of turn. The flashback cost is equal to its mana cost.
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Snapcaster Mage");
- setChoice(playerA, "Terminate");
+ addTarget(playerA, "Terminate");
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Flashback"); // Flashback Terminate
addTarget(playerA, "Icefall Regent");
@@ -537,7 +532,7 @@ public class FlashbackTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Snapcaster Mage");
- setChoice(playerA, "Force of Will");
+ addTarget(playerA, "Force of Will");
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Lightning Bolt", "Snapcaster Mage");
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Flashback", null, "Lightning Bolt");
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ManifestTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ManifestTest.java
index 75bbdb228d..55b8347561 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ManifestTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/ManifestTest.java
@@ -1,7 +1,7 @@
-
package org.mage.test.cards.abilities.keywords;
import mage.cards.Card;
+import mage.constants.EmptyNames;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.game.permanent.Permanent;
@@ -10,7 +10,6 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
- *
* @author LevelX2
*/
public class ManifestTest extends CardTestPlayerBase {
@@ -34,15 +33,16 @@ public class ManifestTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
+ assertAllCommandsUsed();
// no life gain
assertLife(playerA, 20);
assertLife(playerB, 20);
// a facedown creature is on the battlefield
- assertPermanentCount(playerA, "", 1);
- assertPowerToughness(playerA, "", 2, 2);
+ assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
+ assertPowerToughness(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 2, 2);
// not tapped
- assertTapped("", false);
+ assertTapped(EmptyNames.FACE_DOWN_CREATURE.toString(), false);
}
/**
@@ -66,13 +66,14 @@ public class ManifestTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
+ assertAllCommandsUsed();
// no life gain
assertLife(playerA, 20);
assertLife(playerB, 20);
// a facedown creature is on the battlefield
- assertPermanentCount(playerA, "", 1);
- assertPowerToughness(playerA, "", 2, 2);
+ assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
+ assertPowerToughness(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 2, 2);
// PlayerB's Silvercoat Lion should not have get -1/-1/
assertPermanentCount(playerB, "Silvercoat Lion", 1);
assertPowerToughness(playerB, "Silvercoat Lion", 2, 2);
@@ -101,6 +102,7 @@ public class ManifestTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
+ assertAllCommandsUsed();
// no life gain
assertLife(playerA, 20);
@@ -108,8 +110,8 @@ public class ManifestTest extends CardTestPlayerBase {
assertGraveyardCount(playerB, "Reality Shift", 1);
assertExileCount("Silvercoat Lion", 1);
// a facedown creature is on the battlefield
- assertPermanentCount(playerA, "", 1);
- assertPowerToughness(playerA, "", 2, 2);
+ assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
+ assertPowerToughness(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 2, 2);
// PlayerA's Pillarfield Ox should not have get -1/-1/
assertPermanentCount(playerB, "Pillarfield Ox", 1);
assertPowerToughness(playerB, "Pillarfield Ox", 2, 4);
@@ -137,6 +139,7 @@ public class ManifestTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
+ assertAllCommandsUsed();
// no life gain
assertLife(playerA, 20);
@@ -144,8 +147,8 @@ public class ManifestTest extends CardTestPlayerBase {
assertGraveyardCount(playerB, "Reality Shift", 1);
assertExileCount("Silvercoat Lion", 1);
// a facedown creature is on the battlefield
- assertPermanentCount(playerA, "", 1);
- assertPowerToughness(playerA, "", 2, 2);
+ assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
+ assertPowerToughness(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 2, 2);
}
@@ -173,6 +176,7 @@ public class ManifestTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
+ assertAllCommandsUsed();
// no life gain
assertLife(playerA, 20);
@@ -180,8 +184,8 @@ public class ManifestTest extends CardTestPlayerBase {
assertGraveyardCount(playerB, "Reality Shift", 1);
assertExileCount("Silvercoat Lion", 1);
// a facedown creature is on the battlefield
- assertPermanentCount(playerA, "", 1);
- assertPowerToughness(playerA, "", 2, 2);
+ assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
+ assertPowerToughness(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 2, 2);
assertPowerToughness(playerA, "Foundry Street Denizen", 1, 1);
}
@@ -199,7 +203,6 @@ public class ManifestTest extends CardTestPlayerBase {
// Strive — Silence the Believers costs more to cast for each target beyond the first.
// Exile any number of target creatures and all Auras attached to them.
addCard(Zone.HAND, playerB, "Silence the Believers");
- addTarget(playerB, "");
// Gore Swine {2}{R}
// 4/1
addCard(Zone.LIBRARY, playerA, "Gore Swine");
@@ -210,10 +213,13 @@ public class ManifestTest extends CardTestPlayerBase {
skipInitShuffling();
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Reality Shift", "Silvercoat Lion");
- castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Silence the Believers", "");
+ showBattlefield("A battle", 1, PhaseStep.POSTCOMBAT_MAIN, playerA);
+ showBattlefield("B battle", 1, PhaseStep.POSTCOMBAT_MAIN, playerB);
+ castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Silence the Believers", EmptyNames.FACE_DOWN_CREATURE.toString());
- setStopAt(1, PhaseStep.BEGIN_COMBAT);
+ setStopAt(1, PhaseStep.END_TURN);
execute();
+ assertAllCommandsUsed();
// no life gain
assertLife(playerA, 20);
@@ -222,7 +228,7 @@ public class ManifestTest extends CardTestPlayerBase {
assertExileCount("Silvercoat Lion", 1);
assertExileCount("Gore Swine", 1);
// no facedown creature is on the battlefield
- assertPermanentCount(playerA, "", 0);
+ assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 0);
for (Card card : currentGame.getExile().getAllCards(currentGame)) {
if (card.getName().equals("Gore Swine")) {
@@ -248,10 +254,11 @@ public class ManifestTest extends CardTestPlayerBase {
skipInitShuffling();
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{1}{B}, {T}, Sacrifice another creature");
- addTarget(playerB, "Silvercoat Lion");
+ setChoice(playerB, "Silvercoat Lion");
setStopAt(2, PhaseStep.BEGIN_COMBAT);
execute();
+ assertAllCommandsUsed();
// no life gain
assertLife(playerA, 20);
@@ -261,7 +268,7 @@ public class ManifestTest extends CardTestPlayerBase {
assertGraveyardCount(playerB, "Silvercoat Lion", 1);
// a facedown creature is on the battlefield
- assertPermanentCount(playerB, "", 1);
+ assertPermanentCount(playerB, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
}
@@ -284,12 +291,13 @@ public class ManifestTest extends CardTestPlayerBase {
skipInitShuffling();
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{1}{B}, {T}, Sacrifice another creature");
- addTarget(playerB, "Silvercoat Lion");
+ setChoice(playerB, "Silvercoat Lion");
activateAbility(2, PhaseStep.POSTCOMBAT_MAIN, playerB, "{5}{G}: Turn");
setStopAt(2, PhaseStep.END_TURN);
execute();
+ assertAllCommandsUsed();
// no life gain
assertLife(playerA, 20);
@@ -297,7 +305,7 @@ public class ManifestTest extends CardTestPlayerBase {
assertGraveyardCount(playerB, "Silvercoat Lion", 1);
- assertPermanentCount(playerB, "", 0);
+ assertPermanentCount(playerB, EmptyNames.FACE_DOWN_CREATURE.toString(), 0);
assertPermanentCount(playerB, "Aerie Bowmasters", 1);
assertPowerToughness(playerB, "Aerie Bowmasters", 4, 5); // 3/4 and the +1/+1 counter from Megamorph
Permanent aerie = getPermanent("Aerie Bowmasters", playerB);
@@ -308,7 +316,6 @@ public class ManifestTest extends CardTestPlayerBase {
/**
* When a Forest came manifested into play my Courser of Kruphix gained me a
* life.
- *
*/
@Test
public void testManifestForest() {
@@ -328,10 +335,11 @@ public class ManifestTest extends CardTestPlayerBase {
skipInitShuffling();
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{1}{B}, {T}, Sacrifice another creature");
- addTarget(playerB, "Silvercoat Lion");
+ setChoice(playerB, "Silvercoat Lion");
setStopAt(2, PhaseStep.END_TURN);
execute();
+ assertAllCommandsUsed();
// no life gain
assertLife(playerA, 20);
@@ -339,13 +347,12 @@ public class ManifestTest extends CardTestPlayerBase {
assertGraveyardCount(playerB, "Silvercoat Lion", 1);
- assertPermanentCount(playerB, "", 1);
+ assertPermanentCount(playerB, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
}
/**
* Whisperwood Elemental - Its sacrifice ability doesn't work..
- *
*/
@Test
public void testWhisperwoodElemental() {
@@ -365,6 +372,7 @@ public class ManifestTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.END_TURN);
execute();
+ assertAllCommandsUsed();
// no life gain
assertLife(playerA, 20);
@@ -374,14 +382,13 @@ public class ManifestTest extends CardTestPlayerBase {
assertGraveyardCount(playerB, "Whisperwood Elemental", 1);
assertGraveyardCount(playerB, "Silvercoat Lion", 2);
- assertPermanentCount(playerB, "", 2);
+ assertPermanentCount(playerB, EmptyNames.FACE_DOWN_CREATURE.toString(), 2);
}
/**
* I sacrificed a manifested face-down Smothering Abomination to Nantuko
* Husk and it made me draw a card.
- *
*/
@Test
public void testDiesTriggeredAbilitiesOfManifestedCreatures() {
@@ -409,10 +416,11 @@ public class ManifestTest extends CardTestPlayerBase {
setChoice(playerB, "Silvercoat Lion");
activateAbility(2, PhaseStep.POSTCOMBAT_MAIN, playerB, "Sacrifice a creature");
- setChoice(playerB, "");
+ setChoice(playerB, EmptyNames.FACE_DOWN_CREATURE.toString());
setStopAt(2, PhaseStep.END_TURN);
execute();
+ assertAllCommandsUsed();
// no life gain
assertLife(playerA, 20);
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MorphTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MorphTest.java
index c3b430166c..50bf73e391 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MorphTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/MorphTest.java
@@ -1,11 +1,7 @@
-
package org.mage.test.cards.abilities.keywords;
import mage.cards.Card;
-import mage.constants.CardType;
-import mage.constants.PhaseStep;
-import mage.constants.SubType;
-import mage.constants.Zone;
+import mage.constants.*;
import mage.filter.Filter;
import mage.game.permanent.Permanent;
import org.junit.Assert;
@@ -13,7 +9,6 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
- *
* @author levelX2
*/
public class MorphTest extends CardTestPlayerBase {
@@ -21,7 +16,6 @@ public class MorphTest extends CardTestPlayerBase {
/**
* Tests if a creature with Morph is cast normal, it behaves as normal
* creature
- *
*/
@Test
public void testCastMorphCreatureWithoutMorph() {
@@ -60,8 +54,8 @@ public class MorphTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
- assertPermanentCount(playerA, "", 1);
- assertPowerToughness(playerA, "", 2, 2);
+ assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
+ assertPowerToughness(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 2, 2);
}
@@ -76,7 +70,7 @@ public class MorphTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Pine Walker");
setChoice(playerA, "Yes"); // cast it face down as 2/2 creature
- attack(3, playerA, "");
+ attack(3, playerA, EmptyNames.FACE_DOWN_CREATURE.toString());
activateAbility(3, PhaseStep.POSTCOMBAT_MAIN, playerA, "{4}{G}: Turn this face-down permanent face up.");
setStopAt(3, PhaseStep.END_TURN);
@@ -84,7 +78,7 @@ public class MorphTest extends CardTestPlayerBase {
assertLife(playerB, 18);
- assertPermanentCount(playerA, "", 0);
+ assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 0);
assertPermanentCount(playerA, "Pine Walker", 1);
assertPowerToughness(playerA, "Pine Walker", 5, 5);
assertTapped("Pine Walker", false);
@@ -94,7 +88,6 @@ public class MorphTest extends CardTestPlayerBase {
/**
* Test that the triggered "turned face up" ability of Pine Walker does not
* trigger as long as Pine Walker is not turned face up.
- *
*/
@Test
public void testDoesNotTriggerFaceDown() {
@@ -110,8 +103,8 @@ public class MorphTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Icefeather Aven", NO_TARGET, "Pine Walker", StackClause.WHILE_NOT_ON_STACK);
setChoice(playerA, "Yes"); // cast it face down as 2/2 creature
- attack(3, playerA, "");
- attack(3, playerA, "");
+ attack(3, playerA, EmptyNames.FACE_DOWN_CREATURE.toString());
+ attack(3, playerA, EmptyNames.FACE_DOWN_CREATURE.toString());
activateAbility(3, PhaseStep.DECLARE_BLOCKERS, playerA, "{1}{G}{U}: Turn this face-down permanent face up.");
setChoice(playerA, "No"); // Don't use return permanent to hand effect
@@ -123,7 +116,7 @@ public class MorphTest extends CardTestPlayerBase {
assertHandCount(playerA, "Pine Walker", 0);
assertHandCount(playerA, "Icefeather Aven", 0);
- assertPermanentCount(playerA, "", 1);
+ assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
assertPermanentCount(playerA, "Icefeather Aven", 1);
assertTapped("Icefeather Aven", true);
@@ -132,7 +125,6 @@ public class MorphTest extends CardTestPlayerBase {
/**
* Test that Morph creature do not trigger abilities with their face up
* attributes
- *
*/
@Test
public void testMorphedRemovesAttributesCreature() {
@@ -156,14 +148,13 @@ public class MorphTest extends CardTestPlayerBase {
assertLife(playerB, 20); // and not 21
- assertPermanentCount(playerA, "", 1);
+ assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
assertPermanentCount(playerB, "Soldier of the Pantheon", 1);
}
/**
* Test to copy a morphed 2/2 creature
- *
*/
@Test
public void testCopyAMorphedCreature() {
@@ -182,22 +173,21 @@ public class MorphTest extends CardTestPlayerBase {
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Clever Impersonator");
setChoice(playerB, "Yes"); // use to copy a nonland permanent
- addTarget(playerB, ""); // Morphed creature
+ addTarget(playerB, EmptyNames.FACE_DOWN_CREATURE.toString()); // Morphed creature
setStopAt(2, PhaseStep.BEGIN_COMBAT);
execute();
assertLife(playerB, 20);
- assertPermanentCount(playerA, "", 1);
- assertPowerToughness(playerA, "", 2, 2);
- assertPermanentCount(playerB, "", 1);
- assertPowerToughness(playerB, "", 2, 2);
+ assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
+ assertPowerToughness(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 2, 2);
+ assertPermanentCount(playerB, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
+ assertPowerToughness(playerB, EmptyNames.FACE_DOWN_CREATURE.toString(), 2, 2);
}
/**
- *
*
*/
@Test
@@ -229,7 +219,7 @@ public class MorphTest extends CardTestPlayerBase {
assertHandCount(playerA, "Pine Walker", 0);
assertHandCount(playerB, "Doomwake Giant", 0);
- assertPermanentCount(playerA, "", 0);
+ assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 0);
assertPermanentCount(playerB, "Doomwake Giant", 1);
assertPermanentCount(playerA, "Pine Walker", 1);
assertPowerToughness(playerA, "Pine Walker", 4, 4);
@@ -241,7 +231,6 @@ public class MorphTest extends CardTestPlayerBase {
* morph goes down to 1/1 correctly. If you unmorph the 2/2 and is also a
* 2/2 after umorphing, the morph will be erroneously reduced to 0/0 and
* die.
- *
*/
@Test
public void testDoomwakeGiantEffect() {
@@ -271,7 +260,7 @@ public class MorphTest extends CardTestPlayerBase {
assertHandCount(playerA, "Ponyback Brigade", 0);
assertHandCount(playerB, "Doomwake Giant", 0);
- assertPermanentCount(playerA, "", 0);
+ assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 0);
assertPermanentCount(playerA, "Goblin", 3);
assertPowerToughness(playerA, "Goblin", 1, 1, Filter.ComparisonScope.Any);
assertPermanentCount(playerB, "Doomwake Giant", 1);
@@ -283,7 +272,6 @@ public class MorphTest extends CardTestPlayerBase {
/**
* Clone a Morph creature that was cast face down and meanwhile was turned
* face up
- *
*/
@Test
public void testCloneFaceUpMorphEffect() {
@@ -317,7 +305,6 @@ public class MorphTest extends CardTestPlayerBase {
/**
* Check that you can't counter a creature cast for it morph costs with
* Disdainful Stroke if it's normal cmc > 3
- *
*/
@Test
public void testCounterCastWithMorphEffect() {
@@ -346,7 +333,7 @@ public class MorphTest extends CardTestPlayerBase {
assertHandCount(playerA, "Sagu Mauler", 0);
assertHandCount(playerB, "Disdainful Stroke", 1); // can't be cast
- assertPermanentCount(playerA, "", 1);
+ assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
}
@@ -355,7 +342,6 @@ public class MorphTest extends CardTestPlayerBase {
* the same name" does only effect one face down creature, also if multiple
* on the battlefield. Because they have no name, they don't have the same
* name.
- *
*/
@Test
public void testEchoingDecaySameNameEffect() {
@@ -376,18 +362,23 @@ public class MorphTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sagu Mauler", NO_TARGET, "Sagu Mauler", StackClause.WHILE_NOT_ON_STACK);
setChoice(playerA, "Yes"); // cast it face down as 2/2 creature
- castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Echoing Decay", "");
+ showBattlefield("A battle", 1, PhaseStep.POSTCOMBAT_MAIN, playerA);
+ castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Echoing Decay", EmptyNames.FACE_DOWN_CREATURE.toString());
- setStopAt(1, PhaseStep.BEGIN_COMBAT);
+ showBattlefield("A battle after", 1, PhaseStep.END_TURN, playerA);
+ setStopAt(1, PhaseStep.END_TURN);
execute();
+ assertAllCommandsUsed();
assertLife(playerB, 20);
+ assertHandCount(playerB, "Echoing Decay", 0);
+ assertGraveyardCount(playerB, "Echoing Decay", 1);
+
assertHandCount(playerA, "Sagu Mauler", 0);
assertHandCount(playerB, "Echoing Decay", 0);
-
- assertPermanentCount(playerA, "", 1);
-
+ assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
+ assertGraveyardCount(playerA, "Sagu Mauler", 1);
}
/**
@@ -472,7 +463,7 @@ public class MorphTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Ashcloud Phoenix");
setChoice(playerA, "Yes"); // cast it face down as 2/2 creature
- castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Lightning Bolt", "");
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Lightning Bolt", EmptyNames.FACE_DOWN_CREATURE.toString());
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
@@ -513,7 +504,7 @@ public class MorphTest extends CardTestPlayerBase {
setChoice(playerA, "Yes"); // cast it face down as 2/2 creature
attack(2, playerB, "Mirri, Cat Warrior");
- block(2, playerA, "", "Mirri, Cat Warrior");
+ block(2, playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), "Mirri, Cat Warrior");
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
@@ -549,20 +540,27 @@ public class MorphTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Akroma, Angel of Fury");
setChoice(playerA, "Yes"); // cast it face down as 2/2 creature
- castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Supplant Form", "");
+ showBattlefield("A battle", 1, PhaseStep.POSTCOMBAT_MAIN, playerA);
+ showBattlefield("B battle", 1, PhaseStep.POSTCOMBAT_MAIN, playerB);
- setStopAt(1, PhaseStep.BEGIN_COMBAT);
+ castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Supplant Form");
+ addTarget(playerB, EmptyNames.FACE_DOWN_CREATURE.toString());
+
+ showBattlefield("A battle end", 1, PhaseStep.END_TURN, playerA);
+ showBattlefield("B battle end", 1, PhaseStep.END_TURN, playerB);
+ setStopAt(1, PhaseStep.END_TURN);
execute();
assertLife(playerB, 20);
- assertGraveyardCount(playerB, "Supplant Form", 1);
assertHandCount(playerA, "Akroma, Angel of Fury", 1);
+ assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 0);
+ assertPermanentCount(playerA, "Akroma, Angel of Fury", 0);
+ assertGraveyardCount(playerB, "Supplant Form", 1);
assertPermanentCount(playerB, "Akroma, Angel of Fury", 0);
- assertPermanentCount(playerB, "", 1);
- assertPowerToughness(playerB, "", 2, 2);
-
+ assertPermanentCount(playerB, EmptyNames.FACE_DOWN_TOKEN.toString(), 1);
+ assertPowerToughness(playerB, EmptyNames.FACE_DOWN_TOKEN.toString(), 2, 2);
}
/**
@@ -588,7 +586,7 @@ public class MorphTest extends CardTestPlayerBase {
assertLife(playerA, 20);
- assertPermanentCount(playerA, "", 1);
+ assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
}
@@ -613,7 +611,7 @@ public class MorphTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Pine Walker");
setChoice(playerA, "Yes"); // cast it face down as 2/2 creature
- attack(3, playerA, "");
+ attack(3, playerA, EmptyNames.FACE_DOWN_CREATURE.toString());
activateAbility(3, PhaseStep.POSTCOMBAT_MAIN, playerA, "{4}{G}: Turn this face-down permanent face up.");
setStopAt(3, PhaseStep.END_TURN);
@@ -621,7 +619,7 @@ public class MorphTest extends CardTestPlayerBase {
assertLife(playerB, 18);
- assertPermanentCount(playerA, "", 0);
+ assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 0);
assertPermanentCount(playerA, "Pine Walker", 1);
assertPowerToughness(playerA, "Pine Walker", 5, 5);
assertTapped("Pine Walker", false);
@@ -631,7 +629,7 @@ public class MorphTest extends CardTestPlayerBase {
* Reflector Mage bouncing a creature that can be played as a morph should
* not prevent the card from being replayed as a morph. Morph creatures are
* nameless.
- *
+ *
* Reported bug: Face-up morph creatures that are bounced by Reflector Mage
* should be able to be replayed as morphs without the "until the next turn"
* restriction."
@@ -666,18 +664,18 @@ public class MorphTest extends CardTestPlayerBase {
assertPermanentCount(playerA, "Reflector Mage", 1);
assertPermanentCount(playerB, "Rattleclaw Mystic", 0);
assertHandCount(playerB, "Rattleclaw Mystic", 0); // should have been replayed
- assertPermanentCount(playerB, "", 1); // Rattleclaw played as a morph
+ assertPermanentCount(playerB, EmptyNames.FACE_DOWN_CREATURE.toString(), 1); // Rattleclaw played as a morph
}
/**
* Reflector Mage bouncing a creature that can be played as a morph should
* not prevent the card from being replayed as a morph. Morph creatures are
* nameless.
- *
+ *
* Reported bug: Face-up morph creatures that are bounced by Reflector Mage
* should be able to be replayed as morphs without the "until the next turn"
* restriction."
- *
+ *
* Testing bouncing a face-down creature played next turn face-up.
*/
@Test
@@ -701,7 +699,6 @@ public class MorphTest extends CardTestPlayerBase {
setChoice(playerA, "Yes"); // cast it face down as 2/2 creature
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Reflector Mage");
- addTarget(playerB, "");
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Rattleclaw Mystic");
setChoice(playerA, "No"); // cast it face down as 2/2 creature
@@ -790,7 +787,7 @@ public class MorphTest extends CardTestPlayerBase {
assertGraveyardCount(playerB, "Fatal Push", 1);
assertGraveyardCount(playerA, "Pine Walker", 1);
- assertPermanentCount(playerA, "", 0);
+ assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 0);
}
@@ -824,7 +821,7 @@ public class MorphTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
- assertPermanentCount(playerA, "", 1);
+ assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
assertHandCount(playerA, 0);
assertTappedCount("Island", true, 3);
@@ -859,7 +856,7 @@ public class MorphTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Quicksilver Dragon");
setChoice(playerA, "Yes"); // cast it face down as 2/2 creature
- castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Lightning Bolt", "");
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Lightning Bolt", EmptyNames.FACE_DOWN_CREATURE.toString());
setStopAt(2, PhaseStep.UPKEEP);
execute();
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/SpliceOnArcaneTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/SpliceOnArcaneTest.java
index a5abc4c3f3..48f7759381 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/SpliceOnArcaneTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/keywords/SpliceOnArcaneTest.java
@@ -1,15 +1,14 @@
-
package org.mage.test.cards.abilities.keywords;
import mage.abilities.keyword.HasteAbility;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Assert;
+import org.junit.Ignore;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
- *
* @author LevelX2
*/
public class SpliceOnArcaneTest extends CardTestPlayerBase {
@@ -17,7 +16,6 @@ public class SpliceOnArcaneTest extends CardTestPlayerBase {
/**
* Test that it works to cast Through the Breach by slicing it on an arcane
* spell
- *
*/
@Test
public void testSpliceThroughTheBreach() {
@@ -32,7 +30,10 @@ public class SpliceOnArcaneTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Silvercoat Lion", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lava Spike", playerB);
- setChoice(playerA, "Silvercoat Lion");
+ // activate splice: yes -> card with splice ability -> new target for spliced ability
+ setChoice(playerA, "Yes");
+ addTarget(playerA, "Through the Breach");
+ addTarget(playerA, "Silvercoat Lion"); // target for spliced ability: put from hand to battlefield
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
@@ -60,8 +61,12 @@ public class SpliceOnArcaneTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 1);
+ // cast arcane Lava Spike
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lava Spike", playerB);
- addTarget(playerA, "Silvercoat Lion");
+ // activate splice: yes -> card with splice ability -> new target for spliced ability
+ setChoice(playerA, "Yes");
+ addTarget(playerA, "Torrent of Stone");
+ addTarget(playerA, "Silvercoat Lion"); // target for spliced ability: 4 damage
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
@@ -97,8 +102,10 @@ public class SpliceOnArcaneTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Silvercoat Lion", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Nourishing Shoal");
+ // activate splice: yes -> card with splice ability -> new target for spliced ability
setChoice(playerA, "Yes");
- setChoice(playerA, "Silvercoat Lion");
+ addTarget(playerA, "Through the Breach");
+ addTarget(playerA, "Silvercoat Lion"); // target for spliced ability: put from hand to battlefield
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
@@ -117,12 +124,12 @@ public class SpliceOnArcaneTest extends CardTestPlayerBase {
/**
* Cards involved: Nourishing Shoal, Goryo's Vengeance, Griselbrand,
* Terminate
- *
+ *
* I actually noticed this bug on the 1.4.3 client, but I didn't see it in
* the change log for 1.4.4, so I assume it is still unknown. Also, it is a
* bit of a rules corner case and I haven't seen anyone else report it, so
* the players of this deck may actually not realize it's incorrect.
- *
+ *
* The scenario was that I cast a Nourishing Shoal with a Goryo's Vengeance
* spliced to it targeting Griselbrand in my graveyard and exiling
* Worldspine Wurm. My opponent responded with a Snapcaster Mage, so to
@@ -132,7 +139,7 @@ public class SpliceOnArcaneTest extends CardTestPlayerBase {
* resolve, it should have been countered due to no legal target. However,
* it caused me to gain 11 life. It did not resurrect Griselbrand
* (correctly), but it should have done nothing at all.
- *
+ *
* I include the info about the Terminate because thinking through, it could
* be pertinent. I would guess what is going on here is one of two things.
* Either the client doesn't recognize the Shoal with a spliced Vengeance as
@@ -145,7 +152,10 @@ public class SpliceOnArcaneTest extends CardTestPlayerBase {
* the error against a bot and update this report.
*/
@Test
+ @Ignore
public void testCounteredBecauseOfNoLegalTarget() {
+ // TODO: rewrite test, it's wrong and misleading-- user report about Griselbrand was destroyed by Terminate after splice anounce, but tests don't use it at all (Griselbrand legal target all the time)
+
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 8);
// You may exile a green card with converted mana cost X from your hand rather than pay Nourishing Shoal's mana cost.
@@ -174,5 +184,4 @@ public class SpliceOnArcaneTest extends CardTestPlayerBase {
assertLife(playerB, 20);
}
-
}
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/exile/OblivionSowerTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/exile/OblivionSowerTest.java
index 3dcb48df92..19680d1380 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/exile/OblivionSowerTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/exile/OblivionSowerTest.java
@@ -30,6 +30,7 @@ public class OblivionSowerTest extends CardTestPlayerBase {
skipInitShuffling();
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Oblivion Sower");
+ addTarget(playerA, playerB);
addTarget(playerA, "Canopy Vista^Canopy Vista^Canopy Vista");
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/conditional/TragicSlipTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/conditional/TragicSlipTest.java
index 0bbcfee3ab..8d272382fb 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/conditional/TragicSlipTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/conditional/TragicSlipTest.java
@@ -1,4 +1,4 @@
- package org.mage.test.cards.conditional;
+package org.mage.test.cards.conditional;
import mage.constants.PhaseStep;
import mage.constants.Zone;
@@ -6,12 +6,8 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
- *
* @author LevelX2
*/
-
-
-
public class TragicSlipTest extends CardTestPlayerBase {
@Test
@@ -108,7 +104,7 @@ public class TragicSlipTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Tragic Slip", "Silvercoat Lion");
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Snapcaster Mage");
- setChoice(playerA, "Tragic Slip");
+ addTarget(playerA, "Tragic Slip");
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", "Snapcaster Mage");
@@ -122,7 +118,7 @@ public class TragicSlipTest extends CardTestPlayerBase {
assertPermanentCount(playerA, "Snapcaster Mage", 0);
assertExileCount("Tragic Slip", 1);
assertPermanentCount(playerB, "Silvercoat Lion", 1);
- assertPowerToughness(playerB, "Silvercoat Lion", 1,1);
+ assertPowerToughness(playerB, "Silvercoat Lion", 1, 1);
assertGraveyardCount(playerB, "Tarmogoyf", 1);
}
}
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/MasterThiefTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/MasterThiefTest.java
index ba821b9a54..8bfe2420bd 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/continuous/MasterThiefTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/continuous/MasterThiefTest.java
@@ -1,13 +1,12 @@
-
package org.mage.test.cards.continuous;
+import mage.abilities.keyword.VigilanceAbility;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
- *
* @author JayDi85
*/
public class MasterThiefTest extends CardTestPlayerBase {
@@ -42,7 +41,7 @@ public class MasterThiefTest extends CardTestPlayerBase {
// cast and get control of shield
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Master Thief");
- addTarget(playerB, "Accorder's Shield");
+ addTarget(playerA, "Accorder's Shield");
// sacrifice Master Thief -- must lost control
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Sacrifice a creature");
@@ -72,11 +71,13 @@ public class MasterThiefTest extends CardTestPlayerBase {
// cast and get control of shield
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Master Thief");
- addTarget(playerB, "Accorder's Shield");
+ addTarget(playerA, "Accorder's Shield");
+ checkPermanentCount("must control shield", 1, PhaseStep.BEGIN_COMBAT, playerA, "Accorder's Shield", 1);
// attach and boost
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Equip {3}");
addTarget(playerA, "Bearer of the Heavens");
+ checkAbility("bear must have boost", 1, PhaseStep.END_TURN, playerA, "Bearer of the Heavens", VigilanceAbility.class, true);
// sacrifice Master Thief -- must lost control, but attached and boosted
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Sacrifice a creature");
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/control/ExileAndReturnUnderYourControl.java b/Mage.Tests/src/test/java/org/mage/test/cards/control/ExileAndReturnUnderYourControl.java
index 59009ff581..8d5cbf28f5 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/control/ExileAndReturnUnderYourControl.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/control/ExileAndReturnUnderYourControl.java
@@ -1,5 +1,6 @@
package org.mage.test.cards.control;
+import mage.constants.EmptyNames;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Assert;
@@ -9,7 +10,7 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* Tests the effect: - Exile target creature you control, then return that card
* to the battlefield under your control
- *
+ *
* This effect grants you permanent control over the returned creature. So you
* mail steal opponent's creature with "Act of Treason" and then use this effect
* for permanent control effect.
@@ -103,8 +104,8 @@ public class ExileAndReturnUnderYourControl extends CardTestPlayerBase {
assertExileCount("Secret Plans", 0);
assertPermanentCount(playerA, "Secret Plans", 1);
- assertPermanentCount(playerA, "", 1);
- assertPowerToughness(playerA, "", 2, 3);
+ assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
+ assertPowerToughness(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 2, 3);
}
/**
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CopySpellTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CopySpellTest.java
index 2ec1c261ed..9c39f31353 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CopySpellTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CopySpellTest.java
@@ -1,14 +1,13 @@
-
package org.mage.test.cards.copy;
import mage.abilities.keyword.FlyingAbility;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
+import org.mage.test.player.TestPlayer;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
- *
* @author LevelX2
*/
public class CopySpellTest extends CardTestPlayerBase {
@@ -17,23 +16,38 @@ public class CopySpellTest extends CardTestPlayerBase {
public void copyChainOfVapor() {
// Return target nonland permanent to its owner's hand. Then that permanent's controller may sacrifice a land. If the player does, he or she may copy this spell and may choose a new target for that copy.
addCard(Zone.HAND, playerA, "Chain of Vapor", 1);
- addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
+ addCard(Zone.BATTLEFIELD, playerA, "Island", 10);
- addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 1);
+ addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 10);
- addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox", 1);
- addCard(Zone.BATTLEFIELD, playerB, "Island", 1);
+ addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox", 10);
+ addCard(Zone.BATTLEFIELD, playerB, "Island", 10);
+ // start chain from A - return pillar to hand
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Chain of Vapor", "Pillarfield Ox");
- setChoice(playerB, "Yes");
- addTarget(playerB, "Silvercoat Lion");
+ // chain 1 - B can return
+ addTarget(playerB, "Island"); // select a land to sacrifice
+ setChoice(playerB, "Yes"); // want to copy spell
+ setChoice(playerB, "Yes"); // want to change target
+ addTarget(playerB, "Silvercoat Lion"); // new target after copy
+ // chain 2 - A can return
+ addTarget(playerA, "Island"); // select a land to sacrifice
+ setChoice(playerA, "Yes"); // want to copy spell
+ setChoice(playerA, "Yes"); // want to change target
+ addTarget(playerA, "Pillarfield Ox"); // new target after copy
+ // stop the chain by B
+ addTarget(playerB, TestPlayer.TARGET_SKIP);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
+ assertAllCommandsUsed();
- assertGraveyardCount(playerB, "Island", 1);
- assertHandCount(playerB, "Pillarfield Ox", 1);
assertHandCount(playerA, "Silvercoat Lion", 1);
+ assertHandCount(playerB, "Pillarfield Ox", 2);
+ assertPermanentCount(playerA, "Silvercoat Lion", 10 - 1);
+ assertPermanentCount(playerB, "Pillarfield Ox", 10 - 2);
+ assertGraveyardCount(playerA, "Island", 1);
+ assertGraveyardCount(playerB, "Island", 1);
}
@Test
@@ -135,7 +149,7 @@ public class CopySpellTest extends CardTestPlayerBase {
* before it is cast and therefore before Zada's ability triggers, e.g.
* Desperate Ritual spliced onto Into the Fray should generate 3 red mana
* for every creature i control.
- *
+ *
* 702.46a Splice is a static ability that functions while a card is in your
* hand. “Splice onto [subtype] [cost]” means “You may reveal this card from
* your hand as you cast a [subtype] spell. If you do, copy this card's text
@@ -184,7 +198,7 @@ public class CopySpellTest extends CardTestPlayerBase {
* {4}{U} Enchantment (Enchant Player) Whenever enchanted player casts an
* instant or sorcery spell, each other player may copy that spell and may
* choose new targets for the copy he or she controls.
- *
+ *
* Reported bug: "A player with Curse of Echoes attached to them played
* Bribery and the player who controlled the curse had control of all 3
* copies. This seems to be the case for all spells."
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CryptoplasmTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CryptoplasmTest.java
index ec85a76ada..34c014aed2 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/CryptoplasmTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/CryptoplasmTest.java
@@ -52,15 +52,24 @@ public class CryptoplasmTest extends CardTestPlayerBase {
// At the beginning of your upkeep, you may have Cryptoplasm become a copy of another target creature. If you do, Cryptoplasm gains this ability.
addCard(Zone.BATTLEFIELD, playerB, "Cryptoplasm", 1); // {1}{U}{U}
+ // turn 2 - prepare (crypto to paladin, footsteps to crypto)
+ // crypto: copy as paladin on upkeep
+ setChoice(playerB, "Yes");
+ addTarget(playerB, "Sigiled Paladin");
+ // footsteps: enchant copy of paladin (crypto)
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Followed Footsteps");
addTarget(playerB, "Sigiled Paladin[only copy]");
+ // turn 4 - ignore crypto ask for new copy
+ setChoice(playerB, "No");
+
setStopAt(4, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerB, "Followed Footsteps", 1);
- assertPermanentCount(playerB, "Cryptoplasm", 0);
- assertPermanentCount(playerB, "Sigiled Paladin", 2);
+ assertPermanentCount(playerB, "Cryptoplasm", 0); // it's a copy
+ assertPermanentCount(playerB, "Sigiled Paladin", 2); // crypto as copy + footstep token as copy
+ assertPermanentCount(playerA, "Sigiled Paladin", 1); // original
}
/**
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/IsochronScepterTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/IsochronScepterTest.java
index c49391815c..810e5ea628 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/IsochronScepterTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/IsochronScepterTest.java
@@ -44,10 +44,12 @@ public class IsochronScepterTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Lightning Bolt");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Isochron Scepter");
- addTarget(playerA, "Lightning Bolt");
+ setChoice(playerA, "Yes"); // use imprint
+ setChoice(playerA, "Lightning Bolt"); // target for imprint (excile from hand)
+
+ // copy and cast imprinted card
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{2}, {T}:");
setChoice(playerA, "Yes");
- setChoice(playerA, "Yes");
setStopAt(1, PhaseStep.END_TURN);
execute();
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/ReversalOfFortuneTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/ReversalOfFortuneTest.java
index ad5641993a..a47e832365 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/ReversalOfFortuneTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/ReversalOfFortuneTest.java
@@ -28,8 +28,8 @@ public class ReversalOfFortuneTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerB, "Lightning Bolt");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reversal of Fortune", playerB);
- addTarget(playerA, "Lightning Bolt");
- setChoice(playerA, "Yes");
+ setChoice(playerA, "Lightning Bolt"); // select to copy
+ setChoice(playerA, "Yes"); // cast copy
setStopAt(1, PhaseStep.END_TURN);
execute();
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/SharuumTheHegemonTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/SharuumTheHegemonTest.java
index 5421dfca18..0ac2a0db44 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/SharuumTheHegemonTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/SharuumTheHegemonTest.java
@@ -1,4 +1,3 @@
-
package org.mage.test.cards.copy;
import mage.constants.PhaseStep;
@@ -7,7 +6,6 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
- *
* @author LevelX2
*/
@@ -15,34 +13,33 @@ public class SharuumTheHegemonTest extends CardTestPlayerBase {
/**
* http://www.slightlymagic.net/forum/viewtopic.php?f=70&t=16732&p=172937&hilit=Sharuum+the+Hegemon#p172920
- *
- * My Sharuum EDH deck uses the standard Sharuum + Clone Effect + Blood Artist as one of the win
- * conditions, but when I have Sharuum in plan and play a Clever Impersonator, targetting Sharuum
- * and choose to keep the Clever Impersonator and send the original Sharuum to the graveyard Xmage
- * never gives me the option to use the Sharuum Ability that the Clever Impersonator should get,
+ *
+ * My Sharuum EDH deck uses the standard Sharuum + Clone Effect + Blood Artist as one of the win
+ * conditions, but when I have Sharuum in plan and play a Clever Impersonator, targetting Sharuum
+ * and choose to keep the Clever Impersonator and send the original Sharuum to the graveyard Xmage
+ * never gives me the option to use the Sharuum Ability that the Clever Impersonator should get,
* making the combo not work.
- *
- * I run a Sharuum EDH deck that wins by cloning Sharuum for infinite death triggers. I know the rules
+ *
+ * I run a Sharuum EDH deck that wins by cloning Sharuum for infinite death triggers. I know the rules
* check out on this combo irl, but no matter how I stack the triggers for cloning Sharuum and her enter
* the battlefield effect it does not work. It either ends with Sharuum in my graveyard or the reanimate
* effect hits the stack before the legend rule applies
- *
- [1] Sharuum the Hegemon is on the battlefield.
- [2] You cast Clone (or any other Clone-like card).
- [3] When Clone resolves, you choose Sharuum for the replacement effect.
- [4] Since fake-Sharuum entered the battlefield, its EtB ability triggers.
- [5] State-based actions are checked and you are prompted to keep one Sharuum. You sacrifice real-Sharuum.
- * 116.2a Triggered abilities can trigger at any time, including while a spell is being cast, an ability is being activated, or a spell or
- * ability is resolving. (See rule 603, "Handling Triggered Abilities.") However, nothing actually happens at the time an ability triggers.
- * Each time a player would receive priority, each ability that has triggered but hasn't yet been put on the stack is put on the stack. See rule 116.5
- * 116.5. Each time a player would get priority, the game first performs all applicable state-based actions as a single event (see rule 704,
- * "State-Based Actions"), then repeats this process until no state-based actions are performed. Then triggered abilities are put on the stack
- * (see rule 603, "Handling Triggered Abilities"). These steps repeat in order until no further state-based actions are performed and no abilities
- * trigger. Then the player who would have received priority does so.
- [6] Once State-based actions are finished, triggered abilities go on the stack. You put the EtB from [4] choosing real-Sharuum.
- [7] Real-Sharuum enters the battlefield.
- [8] Rinse and repeat.
- *
+ *
+ * [1] Sharuum the Hegemon is on the battlefield.
+ * [2] You cast Clone (or any other Clone-like card).
+ * [3] When Clone resolves, you choose Sharuum for the replacement effect.
+ * [4] Since fake-Sharuum entered the battlefield, its EtB ability triggers.
+ * [5] State-based actions are checked and you are prompted to keep one Sharuum. You sacrifice real-Sharuum.
+ * 116.2a Triggered abilities can trigger at any time, including while a spell is being cast, an ability is being activated, or a spell or
+ * ability is resolving. (See rule 603, "Handling Triggered Abilities.") However, nothing actually happens at the time an ability triggers.
+ * Each time a player would receive priority, each ability that has triggered but hasn't yet been put on the stack is put on the stack. See rule 116.5
+ * 116.5. Each time a player would get priority, the game first performs all applicable state-based actions as a single event (see rule 704,
+ * "State-Based Actions"), then repeats this process until no state-based actions are performed. Then triggered abilities are put on the stack
+ * (see rule 603, "Handling Triggered Abilities"). These steps repeat in order until no further state-based actions are performed and no abilities
+ * trigger. Then the player who would have received priority does so.
+ * [6] Once State-based actions are finished, triggered abilities go on the stack. You put the EtB from [4] choosing real-Sharuum.
+ * [7] Real-Sharuum enters the battlefield.
+ * [8] Rinse and repeat.
*/
@Test
public void testCloneTriggered() {
@@ -59,17 +56,26 @@ public class SharuumTheHegemonTest extends CardTestPlayerBase {
setChoice(playerA, "Sharuum the Hegemon"); // what creature to clone
addTarget(playerA, "Sharuum the Hegemon[only copy]"); // which legend to keep
- setChoice(playerA, "Yes");
-
- addTarget(playerA, "Sharuum the Hegemon[only copy]"); // which legend to keep
- setChoice(playerA, "Yes");
+ setChoice(playerA, "Whenever {this} or another creature dies"); // blood first
+ addTarget(playerA, playerB); // damage by blood
+ setChoice(playerA, "Yes"); // return
+ addTarget(playerA, "Sharuum the Hegemon"); // return real sharuum
addTarget(playerA, "Sharuum the Hegemon[only copy]"); // which legend to keep
- setChoice(playerA, "Yes");
+ setChoice(playerA, "Whenever {this} or another creature dies"); // blood first
+ addTarget(playerA, playerB); // damage by blood
+ setChoice(playerA, "Yes"); // return
+ addTarget(playerA, "Sharuum the Hegemon"); // return real sharuum
+
+ addTarget(playerA, "Sharuum the Hegemon[only copy]"); // which legend to keep
+ setChoice(playerA, "Whenever {this} or another creature dies"); // blood first
+ addTarget(playerA, playerB); // damage by blood
+ setChoice(playerA, "Yes"); // return
+ addTarget(playerA, "Sharuum the Hegemon"); // return real sharuum
addTarget(playerA, "Sharuum the Hegemon[only copy]"); // which legend to keep
setChoice(playerA, "No"); // Don't use it anymore
-
+
setStopAt(1, PhaseStep.END_TURN);
execute();
@@ -77,7 +83,6 @@ public class SharuumTheHegemonTest extends CardTestPlayerBase {
assertLife(playerB, 16);
-
}
}
\ No newline at end of file
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/copy/SpelltwineTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/copy/SpelltwineTest.java
index 548f752852..f4859dc486 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/copy/SpelltwineTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/copy/SpelltwineTest.java
@@ -1,8 +1,8 @@
-
package org.mage.test.cards.copy;
import mage.constants.PhaseStep;
import mage.constants.Zone;
+import org.junit.Ignore;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
@@ -48,6 +48,7 @@ public class SpelltwineTest extends CardTestPlayerBase {
* after this, failing to be in the stack box or resolve all.
*/
@Test
+ @Ignore // TODO: test is wrong -- mirari exile cards and must cast their copies, on copies cast mirari triggers again (two times).
public void testCopyCardsMirari() {
addCard(Zone.BATTLEFIELD, playerA, "Island", 9);
// Exile target instant or sorcery card from your graveyard and target instant or sorcery card from an opponent's graveyard.
@@ -66,9 +67,13 @@ public class SpelltwineTest extends CardTestPlayerBase {
// Whenever you cast an instant or sorcery spell, you may pay {3}. If you do, copy that spell. You may choose new targets for the copy.
addCard(Zone.BATTLEFIELD, playerA, "Mirari", 1);
+ // cast spellwin
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Spelltwine");
- addTarget(playerA, "Impulse");
- addTarget(playerA, "Blasphemous Act");
+ addTarget(playerA, "Impulse"); // target 1 to excile
+ addTarget(playerA, "Blasphemous Act"); // target 2 to excile
+
+
+
setChoice(playerA, "Yes"); // pay {3} and copy spell
setChoice(playerA, "Yes"); // Change targets
addTarget(playerA, "Night's Whisper");
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/cost/splitcards/CastSplitCardsFromOtherZonesTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/cost/splitcards/CastSplitCardsFromOtherZonesTest.java
index ae388836b4..5d0b75df07 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/cost/splitcards/CastSplitCardsFromOtherZonesTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/cost/splitcards/CastSplitCardsFromOtherZonesTest.java
@@ -1,4 +1,3 @@
-
package org.mage.test.cards.cost.splitcards;
import mage.constants.PhaseStep;
@@ -7,7 +6,6 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
- *
* @author LevelX2
*/
public class CastSplitCardsFromOtherZonesTest extends CardTestPlayerBase {
@@ -27,31 +25,6 @@ public class CastSplitCardsFromOtherZonesTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Mindclaw Shaman"); // Creature {4}{R}
addCard(Zone.BATTLEFIELD, playerB, "Sanguine Bond", 1); // Enchantment to destroy
- // Wear
- // Destroy target artifact.
- // Tear
- // Destroy target enchantment.
- addCard(Zone.HAND, playerB, "Wear // Tear"); // Instant {1}{R} // {W}
-
- castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mindclaw Shaman");
- addTarget(playerA, "Sanguine Bond");
-
- setStopAt(1, PhaseStep.BEGIN_COMBAT);
- execute();
-
- assertPermanentCount(playerA, "Mindclaw Shaman", 1);
- assertGraveyardCount(playerB, "Wear // Tear", 1);
- assertGraveyardCount(playerB, "Sanguine Bond", 1);
-
- }
-
- @Test
- public void testCastFearFromOpponentsHand() {
- addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5);
- // When Mindclaw Shaman enters the battlefield, target opponent reveals their hand.
- // You may cast an instant or sorcery card from it without paying its mana cost.
- addCard(Zone.HAND, playerA, "Mindclaw Shaman"); // Creature {4}{R}
-
addCard(Zone.BATTLEFIELD, playerB, "Icy Manipulator", 1); // Artifact to destroy
// Wear
// Destroy target artifact.
@@ -60,7 +33,42 @@ public class CastSplitCardsFromOtherZonesTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerB, "Wear // Tear"); // Instant {1}{R} // {W}
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mindclaw Shaman");
- addTarget(playerA, "Icy Manipulator");
+ addTarget(playerA, playerB);
+ setChoice(playerA, "Wear // Tear"); // select card
+ setChoice(playerA, "Yes"); // confirm to cast
+ setChoice(playerA, "Tear"); // select tear side
+ addTarget(playerA, "Sanguine Bond"); // target for tear
+
+ setStopAt(1, PhaseStep.BEGIN_COMBAT);
+ execute();
+
+ assertPermanentCount(playerA, "Mindclaw Shaman", 1);
+ assertGraveyardCount(playerB, "Wear // Tear", 1);
+ assertGraveyardCount(playerB, "Icy Manipulator", 0);
+ assertGraveyardCount(playerB, "Sanguine Bond", 1);
+ }
+
+ @Test
+ public void testCastWearFromOpponentsHand() {
+ addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5);
+ // When Mindclaw Shaman enters the battlefield, target opponent reveals their hand.
+ // You may cast an instant or sorcery card from it without paying its mana cost.
+ addCard(Zone.HAND, playerA, "Mindclaw Shaman"); // Creature {4}{R}
+
+ addCard(Zone.BATTLEFIELD, playerB, "Sanguine Bond", 1); // Enchantment to destroy
+ addCard(Zone.BATTLEFIELD, playerB, "Icy Manipulator", 1); // Artifact to destroy
+ // Wear
+ // Destroy target artifact.
+ // Tear
+ // Destroy target enchantment.
+ addCard(Zone.HAND, playerB, "Wear // Tear"); // Instant {1}{R} // {W}
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mindclaw Shaman");
+ addTarget(playerA, playerB);
+ setChoice(playerA, "Wear // Tear"); // select card
+ setChoice(playerA, "Yes"); // confirm to cast
+ setChoice(playerA, "Wear"); // select wear side
+ addTarget(playerA, "Icy Manipulator"); // target for wear
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
@@ -68,7 +76,7 @@ public class CastSplitCardsFromOtherZonesTest extends CardTestPlayerBase {
assertPermanentCount(playerA, "Mindclaw Shaman", 1);
assertGraveyardCount(playerB, "Wear // Tear", 1);
assertGraveyardCount(playerB, "Icy Manipulator", 1);
-
+ assertGraveyardCount(playerB, "Sanguine Bond", 0);
}
@Test
@@ -87,16 +95,20 @@ public class CastSplitCardsFromOtherZonesTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerB, "Wear // Tear"); // Instant {1}{R} // {W}
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mindclaw Shaman");
- addTarget(playerA, "Sanguine Bond");
+ addTarget(playerA, playerB);
+ setChoice(playerA, "Wear // Tear"); // select card
+ setChoice(playerA, "Yes"); // confirm to cast
+ setChoice(playerA, "Wear // Tear"); // select fused
+ addTarget(playerA, "Icy Manipulator"); // target for wear
+ addTarget(playerA, "Sanguine Bond"); // target for tear
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, "Mindclaw Shaman", 1);
assertGraveyardCount(playerB, "Wear // Tear", 1);
- assertGraveyardCount(playerB, "Sanguine Bond", 1);
assertGraveyardCount(playerB, "Icy Manipulator", 1);
-
+ assertGraveyardCount(playerB, "Sanguine Bond", 1);
}
/**
@@ -119,7 +131,7 @@ public class CastSplitCardsFromOtherZonesTest extends CardTestPlayerBase {
attack(2, playerB, "Etali, Primal Storm");
setChoice(playerB, "Yes");
- setChoice(playerB, "Cast Fire");
+ setChoice(playerB, "Fire");
addTarget(playerB, "Silvercoat Lion");
setStopAt(2, PhaseStep.END_COMBAT);
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/dynamicvalue/SweepTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/dynamicvalue/SweepTest.java
index 68788a4429..61942c0313 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/dynamicvalue/SweepTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/dynamicvalue/SweepTest.java
@@ -1,14 +1,12 @@
-
-
package org.mage.test.cards.dynamicvalue;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
+import org.mage.test.player.TestPlayer;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
- *
* @author BetaSteward
*/
public class SweepTest extends CardTestPlayerBase {
@@ -18,10 +16,9 @@ public class SweepTest extends CardTestPlayerBase {
* Plow Through Reito
* 1W
* Instant -- Arcane
- * Sweep -- Return any number of Plains you control to their owner's hand.
+ * Sweep -- Return any number of Plains you control to their owner's hand.
* Target creature gets +1/+1 until end of turn for each Plains returned this way.
- *
- */
+ */
@Test
public void testSweep1x() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
@@ -29,17 +26,17 @@ public class SweepTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Plow Through Reito");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Plow Through Reito");
- addTarget(playerA, "Plains");
+ addTarget(playerA, "Raging Goblin"); // target to boost
+ addTarget(playerA, "Plains"); // targets to sweep
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, "Raging Goblin", 1);
assertPermanentCount(playerA, "Plains", 4);
- assertPowerToughness(playerA, "Raging Goblin", 2, 2);
-
+ assertPowerToughness(playerA, "Raging Goblin", 2, 2);
}
-
+
@Test
public void testSweep2x() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
@@ -47,15 +44,15 @@ public class SweepTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Plow Through Reito");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Plow Through Reito");
- addTarget(playerA, "Plains^Plains");
+ addTarget(playerA, "Raging Goblin"); // target to boost
+ addTarget(playerA, "Plains^Plains"); // targets to sweep
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, "Raging Goblin", 1);
assertPermanentCount(playerA, "Plains", 3);
- assertPowerToughness(playerA, "Raging Goblin", 3, 3);
-
+ assertPowerToughness(playerA, "Raging Goblin", 3, 3);
}
@Test
@@ -65,15 +62,15 @@ public class SweepTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Plow Through Reito");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Plow Through Reito");
- addTarget(playerA, "Plains^Plains^Plains");
+ addTarget(playerA, "Raging Goblin"); // target to boost
+ addTarget(playerA, "Plains^Plains^Plains"); // targets to sweep
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, "Raging Goblin", 1);
assertPermanentCount(playerA, "Plains", 2);
- assertPowerToughness(playerA, "Raging Goblin", 4, 4);
-
+ assertPowerToughness(playerA, "Raging Goblin", 4, 4);
}
@Test
@@ -83,14 +80,16 @@ public class SweepTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Plow Through Reito");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Plow Through Reito");
+ addTarget(playerA, "Raging Goblin"); // target to boost
+ addTarget(playerA, TestPlayer.TARGET_SKIP); // targets to sweep (zero)
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
+ assertAllCommandsUsed();
assertPermanentCount(playerA, "Raging Goblin", 1);
assertPermanentCount(playerA, "Plains", 5);
- assertPowerToughness(playerA, "Raging Goblin", 1, 1);
-
+ assertPowerToughness(playerA, "Raging Goblin", 1, 1);
}
-
+
}
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/enchantments/OathOfLiegesTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/enchantments/OathOfLiegesTest.java
index 2334af2b07..6db1d8e572 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/enchantments/OathOfLiegesTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/enchantments/OathOfLiegesTest.java
@@ -1,4 +1,3 @@
-
package org.mage.test.cards.enchantments;
import mage.constants.PhaseStep;
@@ -7,93 +6,229 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
- *
- * @author LevelX2
+ * @author LevelX2, JayDi85
*/
public class OathOfLiegesTest extends CardTestPlayerBase {
+ //addCard(Zone.BATTLEFIELD, playerA, "Hypersonic Dragon", 1); // can cast spells at any time
+ //addCard(Zone.HAND, playerA, "Breath of Life", 1); // {3}{W} // return creatures
+ //addCard(Zone.HAND, playerA, "Replenish", 1); // {3}{W} // return all enchantments
+
@Test
- public void testSearchLandOwner() {
- addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
- // At the beginning of each player's upkeep, that player chooses target player who controls more lands than he or she does and is their opponent.
- // The first player may search their library for a basic land card, put that card onto the battlefield, then shuffle their library.
- addCard(Zone.HAND, playerA, "Oath of Lieges", 1); // {1}{W}
- addCard(Zone.LIBRARY, playerA, "Plains", 1);
+ public void testOath_OwnCardTriggersOnOwnTurn() {
+ // A
+ addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
+ addCard(Zone.LIBRARY, playerA, "Plains", 5);
+ addCard(Zone.BATTLEFIELD, playerA, "Oath of Lieges", 1); // {1}{W}
+ // B
+ addCard(Zone.BATTLEFIELD, playerB, "Island", 5);
- addCard(Zone.BATTLEFIELD, playerB, "Plains", 3);
+ // turn 1 - A
+ // oath A triggers for A and activates
+ addTarget(playerA, playerB); // who control more lands
+ setChoice(playerA, "Yes"); // search library
+ addTarget(playerA, "Plains"); // card from library
- castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Oath of Lieges");
- addTarget(playerA, playerB);
- addTarget(playerA, "Plains");
-
- setStopAt(3, PhaseStep.PRECOMBAT_MAIN);
+ setStopAt(1, PhaseStep.END_TURN);
execute();
+ assertAllCommandsUsed();
- assertPermanentCount(playerA, "Oath of Lieges", 1);
- assertPermanentCount(playerA, "Plains", 3);
-
+ assertPermanentCount(playerA, "Plains", 4 + 1);
+ assertPermanentCount(playerB, "Island", 5);
}
@Test
- public void testSearchLandOpponent() {
- addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
- // At the beginning of each player's upkeep, that player chooses target player who controls more lands than he or she does and is their opponent.
- // The first player may search their library for a basic land card, put that card onto the battlefield, then shuffle their library.
- addCard(Zone.HAND, playerA, "Oath of Lieges", 1); // {1}{W}
+ public void testOath_OwnCardTriggersOnOpponentTurn() {
+ // A
+ addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
+ addCard(Zone.LIBRARY, playerA, "Plains", 5);
+ addCard(Zone.BATTLEFIELD, playerA, "Hypersonic Dragon", 1); // can cast spells at any time
+ addCard(Zone.GRAVEYARD, playerA, "Oath of Lieges", 1); // {1}{W}
+ addCard(Zone.HAND, playerA, "Replenish", 1); // {3}{W} // return all enchantments
+ // B
+ addCard(Zone.BATTLEFIELD, playerB, "Plains", 4);
+ addCard(Zone.LIBRARY, playerB, "Plains", 5);
- addCard(Zone.BATTLEFIELD, playerB, "Plains", 1);
- addCard(Zone.LIBRARY, playerB, "Plains", 1);
+ // turn 1 - A (play oath from grave)
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Replenish");
+ checkPermanentCount("A have oath", 1, PhaseStep.END_TURN, playerA, "Oath of Lieges", 1);
+ checkPermanentCount("A have 5 plains", 1, PhaseStep.END_TURN, playerA, "Plains", 5);
+ checkPermanentCount("B have 4 plains", 1, PhaseStep.END_TURN, playerB, "Plains", 4);
- castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Oath of Lieges");
- addTarget(playerB, playerA);
- addTarget(playerB, "Plains");
+ // turn 2 - B
+ // oath A triggers for B and activates
+ addTarget(playerB, playerA); // who control more lands
+ setChoice(playerB, "Yes"); // search library
+ addTarget(playerB, "Plains"); // card from library
- setStopAt(2, PhaseStep.PRECOMBAT_MAIN);
+ setStopAt(2, PhaseStep.END_TURN);
execute();
+ assertAllCommandsUsed();
- assertPermanentCount(playerA, "Oath of Lieges", 1);
- assertPermanentCount(playerA, "Plains", 2);
- assertPermanentCount(playerB, "Plains", 2);
+ assertPermanentCount(playerA, "Plains", 5);
+ assertPermanentCount(playerB, "Plains", 4 + 1);
}
@Test
- public void testSearchLandOwnerCopy() {
- addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
- // At the beginning of each player's upkeep, that player chooses target player who controls more lands than he or she does and is their opponent.
- // The first player may search their library for a basic land card, put that card onto the battlefield, then shuffle their library.
- addCard(Zone.HAND, playerA, "Oath of Lieges", 1); // {1}{W}
- addCard(Zone.LIBRARY, playerA, "Plains", 3);
- addCard(Zone.HAND, playerA, "Plains", 1);
+ public void testOath_OpponentCardTriggersOnOwnTurn() {
+ // A
+ addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
+ addCard(Zone.LIBRARY, playerA, "Plains", 5);
+ // B
+ addCard(Zone.LIBRARY, playerB, "Plains", 5);
+ addCard(Zone.BATTLEFIELD, playerB, "Plains", 5);
+ addCard(Zone.BATTLEFIELD, playerB, "Oath of Lieges", 1); // {1}{W}
+ // turn 1 - A
+ // oath B triggers for A and activates
+ addTarget(playerA, playerB); // who control more lands
+ setChoice(playerA, "Yes"); // search library
+ addTarget(playerA, "Plains"); // card from library
+
+ setStopAt(1, PhaseStep.END_TURN);
+ execute();
+ assertAllCommandsUsed();
+
+ assertPermanentCount(playerA, "Plains", 4 + 1);
+ assertPermanentCount(playerB, "Plains", 5);
+ }
+
+ @Test
+ public void testOath_DoubleOath() {
+ // A
+ addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
+ addCard(Zone.LIBRARY, playerA, "Plains", 5);
+ addCard(Zone.BATTLEFIELD, playerA, "Oath of Lieges", 2); // {1}{W}
+ // B
+ addCard(Zone.BATTLEFIELD, playerB, "Plains", 5);
+
+ // turn 1 - A
+ // oath A triggers for A and activates
+ // oath B triggers for A and activates
+ // 1
+ addTarget(playerA, playerB); // who control more lands
+ setChoice(playerA, "Yes"); // search library
+ addTarget(playerA, "Plains"); // card from library
+ // 2
+ addTarget(playerA, playerB); // who control more lands
+ setChoice(playerA, "Yes"); // search library
+ addTarget(playerA, "Plains"); // card from library
+
+ setStopAt(1, PhaseStep.END_TURN);
+ execute();
+ assertAllCommandsUsed();
+
+ assertPermanentCount(playerA, "Plains", 3 + 2);
+ assertPermanentCount(playerB, "Plains", 5);
+ }
+
+ @Test
+ public void testOath_OwnNormalAndOwnCopy() {
+ // A
+ addCard(Zone.BATTLEFIELD, playerA, "Plains", 10);
+ addCard(Zone.BATTLEFIELD, playerA, "Island", 3); // for copy
+ addCard(Zone.LIBRARY, playerA, "Plains", 5);
+ addCard(Zone.BATTLEFIELD, playerA, "Hypersonic Dragon", 1); // can cast spells at any time
+ addCard(Zone.GRAVEYARD, playerA, "Oath of Lieges", 1); // {1}{W}
+ addCard(Zone.HAND, playerA, "Replenish", 1); // {3}{W} // return all enchantments
+ addCard(Zone.HAND, playerA, "Copy Enchantment", 1); // {2}{U} // copy target
+ // B
+ addCard(Zone.BATTLEFIELD, playerB, "Plains", 12);
addCard(Zone.BATTLEFIELD, playerB, "Island", 3);
- addCard(Zone.HAND, playerB, "Copy Enchantment", 1); // {2}{U}
- addCard(Zone.LIBRARY, playerB, "Plains", 3);
+ addCard(Zone.LIBRARY, playerB, "Plains", 5);
- castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Oath of Lieges");
+ // turn 1 - A
+ // cast oath A
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Replenish");
+ showBattlefield("A perms", 1, PhaseStep.POSTCOMBAT_MAIN, playerA);
+ // cast oath copy
+ castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Copy Enchantment");
+ setChoice(playerA, "Yes"); // use copy effect
+ setChoice(playerA, "Oath of Lieges"); // target for copy
+ checkPermanentCount("A have 2 oath", 1, PhaseStep.END_TURN, playerA, "Oath of Lieges", 2);
+ checkPermanentCount("A have 10 plains", 1, PhaseStep.END_TURN, playerA, "Plains", 10);
+ checkPermanentCount("B have 12 plains", 1, PhaseStep.END_TURN, playerB, "Plains", 12);
- castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Copy Enchantment");
- setChoice(playerB, "Oath of Lieges");
+ // turn 2 - B
+ // oath A triggers for B and do nothing
+ // copy oath A triggers for B and do nothing
+ checkPermanentCount("A have 10 plains", 1, PhaseStep.END_TURN, playerA, "Plains", 10);
+ checkPermanentCount("B have 12 plains", 1, PhaseStep.END_TURN, playerB, "Plains", 12);
- // turn 3
- addTarget(playerA, playerB);
- addTarget(playerA, "Plains"); // 3rd land
- addTarget(playerA, "Plains"); // second trigger will fail because target player has no longer more lands than controller
+ // turn 3 - A
+ // oath A triggers for A and activates
+ // copy oath A triggers for A and activates
+ // 1
+ addTarget(playerA, playerB); // who control more lands
+ setChoice(playerA, "Yes"); // search library
+ addTarget(playerA, "Plains"); // card from library
+ // 2
+ addTarget(playerA, playerB); // who control more lands
+ setChoice(playerA, "Yes"); // search library
+ addTarget(playerA, "Plains"); // card from library
- playLand(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Plains"); // 4th land
-
- // turn 4
- addTarget(playerB, playerA);
- addTarget(playerB, "Plains");
- addTarget(playerB, "Plains"); // second trigger will fail because target player has no longer more lands than controller
-
- setStopAt(4, PhaseStep.PRECOMBAT_MAIN);
+ setStopAt(3, PhaseStep.END_TURN);
execute();
+ assertAllCommandsUsed();
- assertPermanentCount(playerB, "Oath of Lieges", 1);
- assertPermanentCount(playerA, "Oath of Lieges", 1);
+ assertPermanentCount(playerA, "Plains", 10 + 2);
+ assertPermanentCount(playerB, "Plains", 12);
+ }
- assertPermanentCount(playerB, "Plains", 1);
- assertPermanentCount(playerA, "Plains", 4);
+ @Test
+ public void testOath_OwnNormalAndOpponentCopy() {
+ // special test to check targetadjusters (copy card must used target adjuster from original card, not from copied)
+ // A
+ addCard(Zone.BATTLEFIELD, playerA, "Plains", 10);
+ addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
+ addCard(Zone.LIBRARY, playerA, "Plains", 5);
+ addCard(Zone.GRAVEYARD, playerA, "Oath of Lieges", 1); // {1}{W}
+ addCard(Zone.HAND, playerA, "Replenish", 1); // {3}{W} // return all enchantments
+ addCard(Zone.BATTLEFIELD, playerA, "Hypersonic Dragon", 1); // can cast spells at any time
+ // B
+ addCard(Zone.BATTLEFIELD, playerB, "Plains", 12);
+ addCard(Zone.BATTLEFIELD, playerB, "Island", 3); // for copy
+ addCard(Zone.LIBRARY, playerB, "Plains", 5);
+ addCard(Zone.HAND, playerB, "Copy Enchantment", 1); // {2}{U} // copy target
+
+ // turn 1 - A
+ // nothing
+
+ // turn 2 - B
+ // cast oath A
+ castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, "Replenish");
+ // cast oath copy by opponent
+ showBattlefield("A perms", 2, PhaseStep.POSTCOMBAT_MAIN, playerA);
+ showBattlefield("B perms", 2, PhaseStep.POSTCOMBAT_MAIN, playerB);
+ showAvaileableAbilities("B abils", 2, PhaseStep.POSTCOMBAT_MAIN, playerB);
+ showHand("B hand", 2, PhaseStep.POSTCOMBAT_MAIN, playerB);
+ castSpell(2, PhaseStep.POSTCOMBAT_MAIN, playerB, "Copy Enchantment");
+ setChoice(playerB, "Yes"); // use copy effect
+ setChoice(playerB, "Oath of Lieges"); // target for copy
+ checkPermanentCount("A have 1 oath", 2, PhaseStep.END_TURN, playerA, "Oath of Lieges", 1);
+ checkPermanentCount("B have 1 oath", 2, PhaseStep.END_TURN, playerA, "Oath of Lieges", 1);
+ checkPermanentCount("A have 10 plains", 2, PhaseStep.END_TURN, playerA, "Plains", 10);
+ checkPermanentCount("B have 12 plains", 2, PhaseStep.END_TURN, playerB, "Plains", 12);
+ showLibrary("lib B", 2, PhaseStep.END_TURN, playerB);
+
+ // turn 3 - A
+ // oath A triggers for A and activates
+ // copy oath B triggers for A and activates
+ // 1
+ addTarget(playerA, playerB); // who control more lands
+ setChoice(playerA, "Yes"); // search library
+ addTarget(playerA, "Plains"); // card from library
+ // 2
+ addTarget(playerA, playerB); // who control more lands
+ setChoice(playerA, "Yes"); // search library
+ addTarget(playerA, "Plains"); // card from library
+
+ setStopAt(3, PhaseStep.END_TURN);
+ execute();
+ assertAllCommandsUsed();
+
+ assertPermanentCount(playerA, "Plains", 10 + 2);
+ assertPermanentCount(playerB, "Plains", 12);
}
}
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/enchantments/StarfieldOfNyxTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/enchantments/StarfieldOfNyxTest.java
index ec167a6315..882c8e1efb 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/enchantments/StarfieldOfNyxTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/enchantments/StarfieldOfNyxTest.java
@@ -1,7 +1,7 @@
-
package org.mage.test.cards.enchantments;
import mage.abilities.keyword.FlyingAbility;
+import mage.constants.EmptyNames;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.filter.Filter;
@@ -11,7 +11,6 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
- *
* @author LevelX2
*/
public class StarfieldOfNyxTest extends CardTestPlayerBase {
@@ -22,7 +21,6 @@ public class StarfieldOfNyxTest extends CardTestPlayerBase {
* Starfield of Nyx not only turned both of them into creatures (it
* shouldn't, because they're auras), but it also destroyed them. The
* manifests stayed on the battlefield without Flying or Hexproof.
- *
*/
@Test
public void testCloudform() {
@@ -49,7 +47,7 @@ public class StarfieldOfNyxTest extends CardTestPlayerBase {
execute();
assertGraveyardCount(playerA, "Thopter Spy Network", 0);
- assertPowerToughness(playerA, "", 2, 2, Filter.ComparisonScope.All); // the manifested cards
+ assertPowerToughness(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 2, 2, Filter.ComparisonScope.All); // the manifested cards
assertPermanentCount(playerA, "Starfield of Nyx", 1);
assertPowerToughness(playerA, "Thopter Spy Network", 4, 4, Filter.ComparisonScope.All);
assertPermanentCount(playerA, "Cloudform", 2);
@@ -97,19 +95,19 @@ public class StarfieldOfNyxTest extends CardTestPlayerBase {
Assert.assertEquals("Singing Bell Strike not on the battlefield", false, true);
}
}
-
+
@Test
public void testStarfieldOfNyxLayers() {
-
+
addCard(Zone.BATTLEFIELD, playerA, "Starfield of Nyx"); // enchantments you control become creatures
addCard(Zone.BATTLEFIELD, playerA, "Humility"); // creatures lose all abilities and are 1/1
addCard(Zone.BATTLEFIELD, playerA, "Pharika, God of Affliction"); // enchantment
addCard(Zone.BATTLEFIELD, playerA, "Emrakul, the Aeons Torn"); //15/15 creature
addCard(Zone.BATTLEFIELD, playerA, "Crusade", 4); // enchantments to fulfill requirement of Starfield of Nyx
-
+
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
execute();
-
+
assertPowerToughness(playerA, "Pharika, God of Affliction", 3, 3, Filter.ComparisonScope.All);
assertPowerToughness(playerA, "Humility", 4, 4, Filter.ComparisonScope.All);
// Humility loses its ability in layer 6. Layer 7 never gets Humility's effect
@@ -117,6 +115,6 @@ public class StarfieldOfNyxTest extends CardTestPlayerBase {
Permanent emrakul = getPermanent("Emrakul, the Aeons Torn", playerA.getId());
Assert.assertNotNull(emrakul);
Assert.assertFalse(emrakul.getAbilities().contains(FlyingAbility.getInstance())); // loses flying though
-
+
}
}
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/facedown/GhastlyConscriptionTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/facedown/GhastlyConscriptionTest.java
index e4a92ee726..b516159d9b 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/facedown/GhastlyConscriptionTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/facedown/GhastlyConscriptionTest.java
@@ -1,5 +1,6 @@
package org.mage.test.cards.facedown;
+import mage.constants.EmptyNames;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
@@ -13,13 +14,12 @@ public class GhastlyConscriptionTest extends CardTestPlayerBase {
/**
* Ghastly Conscription
* Sorcery, 5BB (7)
- * Exile all creature cards from target player's graveyard in a face-down pile,
- * shuffle that pile, then manifest those cards. (To manifest a card, put it
- * onto the battlefield face down as a 2/2 creature. Turn it face up any time
+ * Exile all creature cards from target player's graveyard in a face-down pile,
+ * shuffle that pile, then manifest those cards. (To manifest a card, put it
+ * onto the battlefield face down as a 2/2 creature. Turn it face up any time
* for its mana cost if it's a creature card.)
- *
*/
-
+
// test that cards exiled using Ghastly Conscription return face down
@Test
public void testGhastlyConscription() {
@@ -36,9 +36,9 @@ public class GhastlyConscriptionTest extends CardTestPlayerBase {
assertLife(playerA, 20);
assertLife(playerB, 20);
-
+
assertGraveyardCount(playerA, 2);
- assertPermanentCount(playerA, "", 2);
+ assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 2);
}
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/facedown/ObscuringAetherTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/facedown/ObscuringAetherTest.java
index b0755813af..77ec01543d 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/facedown/ObscuringAetherTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/facedown/ObscuringAetherTest.java
@@ -1,13 +1,12 @@
-
package org.mage.test.cards.facedown;
+import mage.constants.EmptyNames;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
- *
* @author LevelX2
*/
public class ObscuringAetherTest extends CardTestPlayerBase {
@@ -15,7 +14,6 @@ public class ObscuringAetherTest extends CardTestPlayerBase {
/**
* Obscuring Aether cannot turn into a face down 2/2 like it should. When
* activating the ability to turn it over it, it dies immediately.
- *
*/
// test that cards exiled using Ghastly Conscription return face down
@Test
@@ -35,8 +33,8 @@ public class ObscuringAetherTest extends CardTestPlayerBase {
assertHandCount(playerA, "Obscuring Aether", 0);
assertGraveyardCount(playerA, "Obscuring Aether", 0);
- assertPermanentCount(playerA, "", 1);
- assertPowerToughness(playerA, "", 2, 2);
+ assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
+ assertPowerToughness(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 2, 2);
}
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/rules/CantCastTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/rules/CantCastTest.java
index 7fb74ea1ad..4a8ac07bbe 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/rules/CantCastTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/rules/CantCastTest.java
@@ -1,6 +1,6 @@
-
package org.mage.test.cards.rules;
+import mage.constants.EmptyNames;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.counters.CounterType;
@@ -8,7 +8,6 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
- *
* @author LevelX2
*/
public class CantCastTest extends CardTestPlayerBase {
@@ -113,7 +112,7 @@ public class CantCastTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
- assertPermanentCount(playerA, "", 0);
+ assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 0);
assertHandCount(playerA, "Pine Walker", 1);
}
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/MisdirectionTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/MisdirectionTest.java
index a84870f89d..efb30757b7 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/single/MisdirectionTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/MisdirectionTest.java
@@ -1,4 +1,3 @@
-
package org.mage.test.cards.single;
import mage.constants.PhaseStep;
@@ -7,8 +6,7 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
- *
- * @author LevelX2
+ * @author LevelX2, JayDi85
*/
public class MisdirectionTest extends CardTestPlayerBase {
@@ -17,10 +15,58 @@ public class MisdirectionTest extends CardTestPlayerBase {
* Tests if Misdirection for target opponent works correctly
* https://github.com/magefree/mage/issues/574
*/
+
@Test
- public void testChangeTargetOpponent() {
+ public void test_RakshaDiscardWorks() {
// Target opponent discards two cards. Put the top two cards of your library into your graveyard.
- addCard(Zone.HAND, playerA, "Rakshasa's Secret");
+ addCard(Zone.HAND, playerA, "Rakshasa's Secret"); // {2}{B}
+ addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
+ addCard(Zone.HAND, playerB, "Silvercoat Lion", 2);
+ addCard(Zone.HAND, playerB, "Ashcoat Bear", 5);
+
+ // A cast discard
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Rakshasa's Secret", playerB);
+ setChoice(playerB, "Silvercoat Lion"); // select target 1
+ setChoice(playerB, "Silvercoat Lion"); // select target 2
+ checkHandCardCount("B haven't lions", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Silvercoat Lion", 0);
+ checkHandCardCount("B have 5 bears", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Ashcoat Bear", 5);
+
+ setStopAt(1, PhaseStep.END_TURN);
+ execute();
+ assertAllCommandsUsed();
+ }
+
+ @Test
+ public void test_MisdirectionRetargetWorks() {
+ // Return target permanent to its owner’s hand.
+ addCard(Zone.HAND, playerA, "Boomerang", 1); // {U}{U}
+ addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
+ addCard(Zone.BATTLEFIELD, playerA, "Ashcoat Bear", 1);
+ // Change the target of target spell with a single target.
+ addCard(Zone.HAND, playerB, "Misdirection"); // {3}{U}{U}
+ addCard(Zone.BATTLEFIELD, playerB, "Island", 5);
+ addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 1);
+
+ // A cast Boomerang to remove lion
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Boomerang", "Silvercoat Lion");
+ // B counter it by Misdirection and remove bear
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Misdirection", "Boomerang", "Boomerang");
+ addTarget(playerB, "Ashcoat Bear");
+
+ setStopAt(1, PhaseStep.END_TURN);
+ execute();
+ assertAllCommandsUsed();
+
+ assertGraveyardCount(playerA, "Boomerang", 1);
+ assertPermanentCount(playerA, "Ashcoat Bear", 0);
+ assertGraveyardCount(playerB, "Misdirection", 1);
+ assertPermanentCount(playerB, "Silvercoat Lion", 1);
+ }
+
+ @Test
+ public void test_MisdirectionCantTargetToIllegal() {
+ // Target opponent discards two cards. Put the top two cards of your library into your graveyard.
+ addCard(Zone.HAND, playerA, "Rakshasa's Secret"); // {2}{B}
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
/*
Misdirection {3}{U}{U}
@@ -30,23 +76,31 @@ public class MisdirectionTest extends CardTestPlayerBase {
*/
addCard(Zone.HAND, playerB, "Misdirection");
addCard(Zone.HAND, playerB, "Silvercoat Lion", 2);
+ addCard(Zone.HAND, playerB, "Ashcoat Bear", 5);
addCard(Zone.BATTLEFIELD, playerB, "Island", 5);
-
+
+ // cast Raksha and select B
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Rakshasa's Secret", playerB);
+ // cast misdir, but it's not apply and taget will be same
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Misdirection", "Rakshasa's Secret", "Rakshasa's Secret");
- addTarget(playerB, playerA); // only legal target is player B as opponent - so player A should not be allowed
-
- setStopAt(1, PhaseStep.BEGIN_COMBAT);
+ // B must select cards to discard (2 lions, not bears)
+ setChoice(playerB, "Silvercoat Lion"); // select target 1
+ setChoice(playerB, "Silvercoat Lion"); // select target 2
+ checkHandCardCount("B haven't lions", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Silvercoat Lion", 0);
+ checkHandCardCount("B have 5 bears", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Ashcoat Bear", 5);
+
+ setStopAt(1, PhaseStep.END_TURN);
execute();
+ assertAllCommandsUsed();
assertGraveyardCount(playerA, "Rakshasa's Secret", 1);
assertGraveyardCount(playerB, "Misdirection", 1);
assertHandCount(playerB, "Silvercoat Lion", 0);
}
-
+
// check to change target permanent creature legal to to a creature the opponent of the spell controller controls
@Test
- public void testChangePublicExecution() {
+ public void test_ChangePublicExecution() {
// Destroy target creature an opponent controls. Each other creature that player controls gets -2/-0 until end of turn.
addCard(Zone.HAND, playerA, "Public Execution");
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 6);
@@ -60,26 +114,27 @@ public class MisdirectionTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox", 1);
addCard(Zone.BATTLEFIELD, playerB, "Custodian of the Trove", 1); // 4/3
addCard(Zone.BATTLEFIELD, playerB, "Island", 5);
-
+
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Public Execution", "Pillarfield Ox");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Misdirection", "Public Execution", "Public Execution");
- addTarget(playerB, "Custodian of the Trove");
-
+ addTarget(playerB, "Custodian of the Trove");
+
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
+ assertAllCommandsUsed();
assertGraveyardCount(playerA, "Public Execution", 1);
assertGraveyardCount(playerB, "Misdirection", 1);
-
- assertGraveyardCount(playerB, "Custodian of the Trove",1);
+
+ assertGraveyardCount(playerB, "Custodian of the Trove", 1);
assertPermanentCount(playerB, "Pillarfield Ox", 1);
assertPowerToughness(playerB, "Pillarfield Ox", 0, 4);
- }
-
+ }
+
// check to change target permanent creature not legal to to a creature the your opponent controls
@Test
- public void testChangePublicExecution2() {
+ public void test_ChangePublicExecution2() {
// Destroy target creature an opponent controls. Each other creature that player controls gets -2/-0 until end of turn.
addCard(Zone.HAND, playerA, "Public Execution");
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 6);
@@ -94,13 +149,13 @@ public class MisdirectionTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox", 1);
addCard(Zone.BATTLEFIELD, playerB, "Custodian of the Trove", 1); // 4/3
addCard(Zone.BATTLEFIELD, playerB, "Island", 5);
-
+
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Public Execution", "Custodian of the Trove");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Misdirection", "Public Execution", "Public Execution");
- addTarget(playerB, "Keeper of the Lens");
-
+
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
+ assertAllCommandsUsed();
assertGraveyardCount(playerA, "Public Execution", 1);
assertGraveyardCount(playerB, "Misdirection", 1);
@@ -108,8 +163,7 @@ public class MisdirectionTest extends CardTestPlayerBase {
assertPermanentCount(playerB, "Pillarfield Ox", 1);
assertPowerToughness(playerB, "Pillarfield Ox", 0, 4);
-
- assertGraveyardCount(playerB, "Custodian of the Trove",1);
- }
+ assertGraveyardCount(playerB, "Custodian of the Trove", 1);
+ }
}
\ No newline at end of file
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/fut/MuragandaPetroglyphsTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/fut/MuragandaPetroglyphsTest.java
index 713ea046c0..0b86e47c8b 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/single/fut/MuragandaPetroglyphsTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/fut/MuragandaPetroglyphsTest.java
@@ -1,5 +1,6 @@
package org.mage.test.cards.single.fut;
+import mage.constants.EmptyNames;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.filter.Filter;
@@ -50,8 +51,8 @@ public class MuragandaPetroglyphsTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
- assertPermanentCount(playerA, "", 1);
- assertPowerToughness(playerA, "", 4, 4);
+ assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
+ assertPowerToughness(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 4, 4);
}
@Test
@@ -69,8 +70,8 @@ public class MuragandaPetroglyphsTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
- assertPermanentCount(playerA, "", 1);
- assertPowerToughness(playerA, "", 2, 2);
+ assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
+ assertPowerToughness(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 2, 2);
}
@Test
@@ -155,7 +156,7 @@ public class MuragandaPetroglyphsTest extends CardTestPlayerBase {
// Enchanted creature doesn't untap during itscontroller's untap step.
addCard(Zone.HAND, playerA, "Dehydration");
- castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA,"Rancor", "Grizzly Bears");
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Rancor", "Grizzly Bears");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dehydration", "Runeclaw Bear");
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/soi/PrizedAmalgamTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/soi/PrizedAmalgamTest.java
index 807859f205..6dc75feb43 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/single/soi/PrizedAmalgamTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/soi/PrizedAmalgamTest.java
@@ -66,23 +66,24 @@ public class PrizedAmalgamTest extends CardTestPlayerBase {
public void testOpponentReturnsCreatureFromGrave() {
addCard(Zone.HAND, playerA, "Reanimate", 1);
- addCard(Zone.GRAVEYARD, playerA, "Hill Giant", 1); // {3}{R} 3/3
+ addCard(Zone.GRAVEYARD, playerA, "Hill Giant", 1); // {3}{R} 3/3, 4 CMC
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
- addCard(Zone.GRAVEYARD, playerB, "Prized Amalgam", 1);
+ addCard(Zone.GRAVEYARD, playerB, "Prized Amalgam", 1); // {1}{U}{B}, 3 CMC
- castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reanimate", "Hill Giant");
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reanimate");
+ addTarget(playerA, "Hill Giant");
setStopAt(1, PhaseStep.END_TURN);
execute();
- assertLife(playerA, 16); // lose 4 life from reanimate 4 CMC
+ assertLife(playerA, 16); // lose 4 life from reanimate 4 CMC by Hill Giant
assertPermanentCount(playerA, "Hill Giant", 1);
assertPermanentCount(playerB, "Prized Amalgam", 0); // should not recur
assertGraveyardCount(playerB, "Prized Amalgam", 1); // stays in grave
}
/*
- * Test opponent returning a card from your graveyard to battlefield.
+ * Test opponent returning a card from your graveyard to battlefield.
*/
@Test
public void testOpponentReturnsCreatureFromYourGrave() {
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/ths/PurphorosGodOfTheForgeTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/ths/PurphorosGodOfTheForgeTest.java
index 18e0ded9a0..d124f0882a 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/single/ths/PurphorosGodOfTheForgeTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/ths/PurphorosGodOfTheForgeTest.java
@@ -1,7 +1,7 @@
-
package org.mage.test.cards.single.ths;
import mage.constants.CardType;
+import mage.constants.EmptyNames;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.game.permanent.Permanent;
@@ -10,26 +10,25 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
- *
* @author LevelX2
*/
public class PurphorosGodOfTheForgeTest extends CardTestPlayerBase {
/**
* I had a situation come up today where I had a Purphoros on the field
- * and 5 devotion with an Eidolon and Phoenix. My opponent killed the
+ * and 5 devotion with an Eidolon and Phoenix. My opponent killed the
* Phoenix, but Purphoros still was "turned on".
*/
@Test
public void testFacedownNotCountedForDevotion1() {
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 5);
addCard(Zone.HAND, playerB, "Reach of Shadows");
-
+
// Indestructible
// As long as your devotion to red is less than five, Purphoros isn't a creature.
// Whenever another creature enters the battlefield under your control, Purphoros deals 2 damage to each opponent.
// {2}{R}: Creatures you control get +1/+0 until end of turn.
addCard(Zone.BATTLEFIELD, playerA, "Purphoros, God of the Forge");
-
+
// Whenever a player casts a spell with converted mana cost 3 or less,
// Eidolon of the Great Revel deals 2 damage to that player.
addCard(Zone.BATTLEFIELD, playerA, "Eidolon of the Great Revel");
@@ -46,24 +45,24 @@ public class PurphorosGodOfTheForgeTest extends CardTestPlayerBase {
assertLife(playerA, 20);
assertLife(playerB, 18); // 2 damage from the returning Phoenix
-
+
assertGraveyardCount(playerB, "Reach of Shadows", 1);
assertPermanentCount(playerA, "Ashcloud Phoenix", 0);
- assertPermanentCount(playerA, "", 1);
+ assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
Permanent purphorosGodOfTheForge = getPermanent("Purphoros, God of the Forge", playerA);
Assert.assertFalse("Purphoros may not be a creature but it is", purphorosGodOfTheForge.getCardType().contains(CardType.CREATURE));
}
-
+
@Test
- public void testFacedownNotCountedForDevotion2() {
+ public void testFacedownNotCountedForDevotion2() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
// Indestructible
// As long as your devotion to red is less than five, Purphoros isn't a creature.
// Whenever another creature enters the battlefield under your control, Purphoros deals 2 damage to each opponent.
// {2}{R}: Creatures you control get +1/+0 until end of turn.
addCard(Zone.BATTLEFIELD, playerA, "Purphoros, God of the Forge");
-
+
// Whenever a player casts a spell with converted mana cost 3 or less,
// Eidolon of the Great Revel deals 2 damage to that player.
addCard(Zone.BATTLEFIELD, playerA, "Eidolon of the Great Revel");
@@ -81,18 +80,18 @@ public class PurphorosGodOfTheForgeTest extends CardTestPlayerBase {
execute();
assertPermanentCount(playerA, "Ashcloud Phoenix", 0);
- assertPermanentCount(playerA, "", 1);
+ assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
assertLife(playerA, 18); // 2 damage from Eidolon of the Great Revel
assertLife(playerB, 18); // 2 damage from Purphoros for the morphed Phoenix
-
+
Permanent purphorosGodOfTheForge = getPermanent("Purphoros, God of the Forge", playerA);
Assert.assertFalse("Purphoros may not be a creature but it is", purphorosGodOfTheForge.getCardType().contains(CardType.CREATURE));
- }
-
+ }
+
@Test
public void testHybridManaCostsForDevotion() {
-
+
// Indestructible
// As long as your devotion to red is less than five, Purphoros isn't a creature.
// Whenever another creature enters the battlefield under your control, Purphoros deals 2 damage to each opponent.
@@ -101,11 +100,11 @@ public class PurphorosGodOfTheForgeTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, "Goblin Guide", 1); // {R}
addCard(Zone.HAND, playerA, "Boros Reckoner", 1); // {R/W}{R/W}{R/W}
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
-
+
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Boros Reckoner");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
-
+
assertLife(playerB, 18);
Permanent purphorosGodOfTheForge = getPermanent("Purphoros, God of the Forge", playerA);
Assert.assertTrue("Purphoros should be a creature now but is not", purphorosGodOfTheForge.getCardType().contains(CardType.CREATURE));
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 9c45cc42e7..af57b93243 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
@@ -1,4 +1,3 @@
-
package org.mage.test.cards.triggers;
import mage.constants.PhaseStep;
@@ -7,7 +6,6 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
- *
* @author LevelX2
*/
public class SpellskiteTest extends CardTestPlayerBase {
@@ -30,6 +28,7 @@ public class SpellskiteTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
+ assertAllCommandsUsed();
assertGraveyardCount(playerA, "Lightning Bolt", 1);
assertPermanentCount(playerA, "Spellskite", 1);
@@ -80,6 +79,7 @@ public class SpellskiteTest extends CardTestPlayerBase {
setStopAt(2, PhaseStep.BEGIN_COMBAT);
execute();
+ assertAllCommandsUsed();
assertPermanentCount(playerA, "Spellskite", 1);
assertPermanentCount(playerB, "Frost Titan", 1);
@@ -119,6 +119,7 @@ public class SpellskiteTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
+ assertAllCommandsUsed();
assertGraveyardCount(playerB, "Lightning Bolt", 1);
@@ -160,6 +161,7 @@ public class SpellskiteTest extends CardTestPlayerBase {
setStopAt(2, PhaseStep.BEGIN_COMBAT);
execute();
+ assertAllCommandsUsed();
assertGraveyardCount(playerA, "Cryptic Command", 1);
@@ -188,16 +190,16 @@ public class SpellskiteTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
- activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{U/P}: Change a target of target spell or ability to {this}.", "Lightning Bolt");
+ activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{U/P}: Change a target", "Lightning Bolt");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
+ assertAllCommandsUsed();
assertGraveyardCount(playerA, "Lightning Bolt", 1);
assertLife(playerA, 20);
assertLife(playerB, 18);
-
}
/**
@@ -219,6 +221,7 @@ public class SpellskiteTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
+ assertAllCommandsUsed();
assertGraveyardCount(playerA, "Flame Slash", 1);
assertPowerToughness(playerB, "Spellskite", 3, 7);
@@ -238,24 +241,36 @@ public class SpellskiteTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerB, "Spellskite");
addCard(Zone.BATTLEFIELD, playerB, "Scute Mob");
addCard(Zone.BATTLEFIELD, playerB, "Island");
+ //
+ addCard(Zone.BATTLEFIELD, playerB, "Memnite"); // 1/1
+ addCard(Zone.BATTLEFIELD, playerB, "Royal Assassin"); // 1/1
+ addCard(Zone.BATTLEFIELD, playerB, "Blinking Spirit"); // 2/2
+ addCard(Zone.BATTLEFIELD, playerB, "Pearled Unicorn"); // 2/2
addCard(Zone.HAND, playerA, "Fiery Justice");
+ // A cast Fiery Justice
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Fiery Justice");
- addTarget(playerA, "Scute Mob");
- setChoice(playerA, "X=1");
- addTarget(playerA, "Spellskite");
- setChoice(playerA, "X=4");
-
- activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{UP}: Change a target of target spell or ability to {this}.", "Fiery Justice", "Fiery Justice");
- setChoice(playerA, "Yes");
+ addTarget(playerA, playerB); // 5 life to B
+ addTarget(playerA, "Scute Mob^X=1"); // target 1
+ addTarget(playerA, "Spellskite^X=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
+ showBattlefield("B battle", 1, PhaseStep.BEGIN_COMBAT, playerB);
+ showGraveyard("B grave", 1, PhaseStep.BEGIN_COMBAT, playerB);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
+ assertAllCommandsUsed();
+ assertLife(playerB, 20 + 5 - 2);
assertGraveyardCount(playerB, 2);
+ assertGraveyardCount(playerB, "Scute Mob", 1);
+ assertGraveyardCount(playerB, "Spellskite", 1);
}
+ @Test
public void testThatSplitDamageCanGetRedirected() {
/* Standard redirect test
The Spellskite should die from the 5 damage that was redirected to it
@@ -267,59 +282,64 @@ public class SpellskiteTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerB, "Spellskite");// 0/4 creature
addCard(Zone.BATTLEFIELD, playerB, "Scute Mob"); // 1/1 creauture
addCard(Zone.BATTLEFIELD, playerB, "Island");
+ addCard(Zone.BATTLEFIELD, playerB, "Memnite"); // 1/1
+ addCard(Zone.BATTLEFIELD, playerB, "Royal Assassin"); // 1/1
+ addCard(Zone.BATTLEFIELD, playerB, "Blinking Spirit"); // 2/2
+ addCard(Zone.BATTLEFIELD, playerB, "Pearled Unicorn"); // 2/2
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");
- setChoice(playerA, "X=5");
+ addTarget(playerA, "Scute Mob^X=5");
- activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{UP}: Change a target of target spell or ability to {this}.", "Fiery Justice", "Fiery Justice");
- setChoice(playerA, "Yes");
+ activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{U/P}: Change a target", "Fiery Justice", "Fiery Justice");
+ setChoice(playerB, "Yes"); // pay 2 life
+ setChoice(playerB, "Yes"); // retarget
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
+ assertAllCommandsUsed();
+ assertLife(playerB, 20 + 5 - 2);
assertGraveyardCount(playerB, 1);
assertPermanentCount(playerB, "Scute Mob", 1);
}
+ @Test
public void testThatSplitDamageGetsRedirectedFromTheCorrectChoice() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
addCard(Zone.BATTLEFIELD, playerB, "Spellskite");// 0/4 creature
- addCard(Zone.BATTLEFIELD, playerB, "Memnite"); // 1/1 creauture
- addCard(Zone.BATTLEFIELD, playerB, "Royal Assassin");
- addCard(Zone.BATTLEFIELD, playerB, "Blinking Spirit");
- addCard(Zone.BATTLEFIELD, playerB, "Pearled Unicorn");
+ addCard(Zone.BATTLEFIELD, playerB, "Memnite"); // 1/1
+ addCard(Zone.BATTLEFIELD, playerB, "Royal Assassin"); // 1/1
+ addCard(Zone.BATTLEFIELD, playerB, "Blinking Spirit"); // 2/2
+ addCard(Zone.BATTLEFIELD, playerB, "Pearled Unicorn"); // 2/2
addCard(Zone.BATTLEFIELD, playerB, "Island");
addCard(Zone.HAND, playerA, "Fiery Justice");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Fiery Justice"); // 5 damage distributed to any number of targets
- addTarget(playerA, "Memnite");
- setChoice(playerA, "X=1");
- addTarget(playerA, "Royal Assassin");
- setChoice(playerA, "X=1");
- addTarget(playerA, "Blinking Spirit");
- setChoice(playerA, "X=1");
- addTarget(playerA, "Pearled Unicorn");
- setChoice(playerA, "X=2");//the unicorn deserves it
+ addTarget(playerA, "Royal Assassin^X=1");
+ addTarget(playerA, "Blinking Spirit^X=2");
+ addTarget(playerA, "Pearled Unicorn^X=2");
-
- activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{UP}: Change a target of target spell or ability to {this}.", "Fiery Justice", "Fiery Justice");
- setChoice(playerA, "No");
- setChoice(playerA, "No");
- setChoice(playerA, "No");
- setChoice(playerA, "Yes"); //of course
+ activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{U/P}: Change a target", "Fiery Justice", "Fiery Justice");
+ setChoice(playerB, "Yes"); // pay 2 life
+ setChoice(playerB, "No"); // skip royal
+ setChoice(playerB, "No"); // skip blink
+ setChoice(playerB, "Yes"); // change pearl
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
+ assertAllCommandsUsed();
- assertGraveyardCount(playerB, 3);
- assertPermanentCount(playerB, "Pearled Unicorn", 1);//it lives on
- assertPowerToughness(playerB, "Spellskite", 0, 2);
+ assertLife(playerB, 20 + 5 - 2);
+ assertGraveyardCount(playerB, "Memnite", 0);
+ assertGraveyardCount(playerB, "Royal Assassin", 1);
+ assertGraveyardCount(playerB, "Blinking Spirit", 1);
+ assertGraveyardCount(playerB, "Pearled Unicorn", 0);
+ assertGraveyardCount(playerB, "Spellskite", 0);
}
}
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/BrainMaggotTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/BrainMaggotTest.java
index 16973a7acb..f77652b4dd 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/BrainMaggotTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/BrainMaggotTest.java
@@ -1,4 +1,3 @@
-
package org.mage.test.cards.triggers.dies;
import mage.constants.PhaseStep;
@@ -7,7 +6,6 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
- *
* @author LevelX2
*/
public class BrainMaggotTest extends CardTestPlayerBase {
@@ -16,7 +14,6 @@ public class BrainMaggotTest extends CardTestPlayerBase {
* When Brain Maggot enters the battlefield, target opponent reveals his or
* her hand and you choose a nonland card from it. Exile that card until
* Brain Maggot leaves the battlefield.
- *
*/
@Test
public void testCardFromHandWillBeExiled() {
@@ -26,10 +23,12 @@ public class BrainMaggotTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerB, "Bloodflow Connoisseur", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Brain Maggot");
- addTarget(playerA, "Bloodflow Connoisseur");
+ addTarget(playerA, playerB);
+ setChoice(playerA, "Bloodflow Connoisseur");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
+ assertAllCommandsUsed();
assertPermanentCount(playerA, "Brain Maggot", 1);
assertExileCount("Bloodflow Connoisseur", 1);
@@ -45,12 +44,22 @@ public class BrainMaggotTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerB, "Lightning Bolt", 1);
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 2);
+ // exile
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Brain Maggot");
- addTarget(playerA, "Bloodflow Connoisseur");
- castSpell(1, PhaseStep.BEGIN_COMBAT, playerB, "Lightning Bolt", "Brain Maggot");
+ addTarget(playerA, playerB);
+ setChoice(playerA, "Bloodflow Connoisseur");
+ showExile("exile", 1, PhaseStep.BEGIN_COMBAT, playerB);
+ checkExileCount("blood must be in exile", 1, PhaseStep.BEGIN_COMBAT, playerB, "Bloodflow Connoisseur", 1);
- setStopAt(1, PhaseStep.DECLARE_ATTACKERS);
+ // return
+ castSpell(1, PhaseStep.END_COMBAT, playerB, "Lightning Bolt", "Brain Maggot");
+ checkPermanentCount("brain must die", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Brain Maggot", 0);
+ checkExileCount("blood must return from exile", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Bloodflow Connoisseur", 0);
+ checkHandCardCount("blood must be in hand", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Bloodflow Connoisseur", 1);
+
+ setStopAt(1, PhaseStep.END_TURN);
execute();
+ assertAllCommandsUsed();
assertGraveyardCount(playerA, "Brain Maggot", 1);
assertGraveyardCount(playerB, "Lightning Bolt", 1);
@@ -68,11 +77,14 @@ public class BrainMaggotTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 2);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mesmeric Fiend");
- addTarget(playerA, "Bloodflow Connoisseur");
+ addTarget(playerA, playerB);
+ setChoice(playerA, "Bloodflow Connoisseur");
+ //
castSpell(1, PhaseStep.BEGIN_COMBAT, playerB, "Lightning Bolt", "Mesmeric Fiend");
setStopAt(1, PhaseStep.DECLARE_ATTACKERS);
execute();
+ assertAllCommandsUsed();
assertGraveyardCount(playerA, "Mesmeric Fiend", 1);
assertGraveyardCount(playerB, "Lightning Bolt", 1);
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/OmnathLocusOfRageTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/OmnathLocusOfRageTest.java
index 0b7b8221ea..63bfb1557f 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/OmnathLocusOfRageTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/OmnathLocusOfRageTest.java
@@ -1,4 +1,3 @@
-
package org.mage.test.cards.triggers.dies;
import mage.constants.PhaseStep;
@@ -7,7 +6,6 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
- *
* @author LevelX2
*/
public class OmnathLocusOfRageTest extends CardTestPlayerBase {
@@ -27,10 +25,10 @@ public class OmnathLocusOfRageTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Diabolic Edict", playerA);
- addTarget(playerA, playerB);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
+ assertAllCommandsUsed();
assertGraveyardCount(playerB, "Diabolic Edict", 1);
assertGraveyardCount(playerA, "Omnath, Locus of Rage", 1);
@@ -53,12 +51,11 @@ public class OmnathLocusOfRageTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 7);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Lightning Bolt", "Lightning Elemental"); // Dying Lightning Elemental does no longer trigger ability of Omnath
- castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Blastfire Bolt", "Omnath, Locus of Rage", "Lightning Bolt");
- addTarget(playerA, playerB);
- addTarget(playerA, playerB);
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Blastfire Bolt", "Omnath, Locus of Rage");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
+ assertAllCommandsUsed();
assertGraveyardCount(playerB, "Lightning Bolt", 1);
assertGraveyardCount(playerB, "Blastfire Bolt", 1);
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/TidehollowScullerTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/TidehollowScullerTest.java
index 3551024a71..7661906c85 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/TidehollowScullerTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/TidehollowScullerTest.java
@@ -1,4 +1,3 @@
-
package org.mage.test.cards.triggers.dies;
import mage.constants.PhaseStep;
@@ -7,8 +6,7 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
- *
- * @author LevelX2
+ * @author LevelX2, JayDi85
*/
public class TidehollowScullerTest extends CardTestPlayerBase {
@@ -17,43 +15,104 @@ public class TidehollowScullerTest extends CardTestPlayerBase {
* Test if the same Tidehollow Sculler is cast multiple times, the correct
* corresponding exiled cards are returned
*/
+
@Test
- public void testCardFromHandWillBeExiled() {
+ public void test_CastOneCardFromHandWillBeExiled() {
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
+ addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
// Tidehollow Sculler {W}{B}
// When Tidehollow Sculler enters the battlefield, target opponent reveals their hand and you choose a nonland card from it. Exile that card.
// When Tidehollow Sculler leaves the battlefield, return the exiled card to its owner's hand.
- addCard(Zone.HAND, playerA, "Tidehollow Sculler", 1);
- // Boomerang {U}{U}
- // Return target creature card from your graveyard to your hand.
- addCard(Zone.HAND, playerA, "Boomerang", 1);
- // Scout's Warning {W}
- // The next creature card you play this turn can be played as though it had flash.
- // Draw a card.
- addCard(Zone.HAND, playerA, "Scout's Warning", 1);
+ addCard(Zone.HAND, playerA, "Tidehollow Sculler", 1); // 2/2
+ addCard(Zone.HAND, playerA, "Lightning Bolt", 1); // {R}
+ //
+ addCard(Zone.HAND, playerB, "Bloodflow Connoisseur", 1);
+
+ // cast and exile from hand
+ checkHandCardCount("B hand must have blood", 1, PhaseStep.UPKEEP, playerB, "Bloodflow Connoisseur", 1);
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Tidehollow Sculler");
+ addTarget(playerA, playerB); // choose opponent
+ setChoice(playerA, "Bloodflow Connoisseur"); // card to exile
+ checkHandCardCount("B hand must lost blood", 1, PhaseStep.BEGIN_COMBAT, playerB, "Bloodflow Connoisseur", 0);
+
+ // destroy and return card to hand
+ checkPermanentCount("A must have tide", 1, PhaseStep.END_COMBAT, playerA, "Tidehollow Sculler", 1);
+ castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", "Tidehollow Sculler");
+ checkPermanentCount("A must lost tide", 1, PhaseStep.END_TURN, playerA, "Tidehollow Sculler", 0);
+ checkHandCardCount("B must return blood", 1, PhaseStep.END_TURN, playerB, "Bloodflow Connoisseur", 1);
+
+ setStopAt(1, PhaseStep.END_TURN);
+ execute();
+ assertAllCommandsUsed();
+
+ assertHandCount(playerB, "Bloodflow Connoisseur", 1);
+ assertPermanentCount(playerA, "Tidehollow Sculler", 0);
+ }
+
+ @Test
+ public void test_CastTwoCardFromHandWillBeExiled() {
+ addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
+ addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
+ addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
+ addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
+ // Tidehollow Sculler {W}{B}
+ // When Tidehollow Sculler enters the battlefield, target opponent reveals their hand and you choose a nonland card from it. Exile that card.
+ // When Tidehollow Sculler leaves the battlefield, return the exiled card to its owner's hand.
+ addCard(Zone.HAND, playerA, "Tidehollow Sculler@tide", 2); // 2/2
+ addCard(Zone.HAND, playerA, "Lightning Bolt", 2); // {R}
+ //
addCard(Zone.HAND, playerB, "Bloodflow Connoisseur", 1);
addCard(Zone.HAND, playerB, "Silvercoat Lion", 1);
+ // turn 1 - A
+ // cast 1 and exile from hand
+ checkHandCardCount("B hand must have blood", 1, PhaseStep.UPKEEP, playerB, "Bloodflow Connoisseur", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Tidehollow Sculler");
- addTarget(playerA, "Bloodflow Connoisseur");
- castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Boomerang", "Tidehollow Sculler");
- castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Scout's Warning", null, "Boomerang");
- castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Tidehollow Sculler", null, "", "When {this} leaves the battlefield, return the exiled card to its owner's hand.");
- addTarget(playerA, "Silvercoat Lion");
+ addTarget(playerA, playerB); // choose opponent
+ setChoice(playerA, "Bloodflow Connoisseur"); // card to exile
+ checkHandCardCount("B hand must lost blood", 1, PhaseStep.BEGIN_COMBAT, playerB, "Bloodflow Connoisseur", 0);
+ // cast 2 and exile from hand
+ checkHandCardCount("B hand must have lion", 1, PhaseStep.END_COMBAT, playerB, "Silvercoat Lion", 1);
+ castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Tidehollow Sculler");
+ addTarget(playerA, playerB); // choose opponent
+ setChoice(playerA, "Silvercoat Lion"); // card to exile
+ checkHandCardCount("B hand must lost lion", 1, PhaseStep.END_TURN, playerB, "Silvercoat Lion", 0);
- setStopAt(1, PhaseStep.BEGIN_COMBAT);
+ // turn 2 - B
+ // destroy 1 and return card to hand
+ checkPermanentCount("A must have 2 tide", 2, PhaseStep.UPKEEP, playerA, "Tidehollow Sculler", 2);
+ checkHandCardCount("B hand must have 0 blood", 2, PhaseStep.UPKEEP, playerB, "Bloodflow Connoisseur", 0);
+ castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "@tide.1");
+ showHand("B hand", 2, PhaseStep.BEGIN_COMBAT, playerB);
+ checkPermanentCount("A must have 1 tide", 2, PhaseStep.BEGIN_COMBAT, playerA, "Tidehollow Sculler", 1);
+ checkHandCardCount("B hand must have 1 blood", 2, PhaseStep.BEGIN_COMBAT, playerB, "Bloodflow Connoisseur", 1);
+ // destroy 2 and return card to hand
+ checkPermanentCount("A must have 1 tide", 2, PhaseStep.END_COMBAT, playerA, "Tidehollow Sculler", 1);
+ checkHandCardCount("B hand must have 0 lion", 2, PhaseStep.END_COMBAT, playerB, "Silvercoat Lion", 0);
+ castSpell(2, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", "@tide.2");
+ checkPermanentCount("A must have 0 tide", 2, PhaseStep.END_TURN, playerA, "Tidehollow Sculler", 0);
+ checkHandCardCount("B hand must have 1 lion", 2, PhaseStep.END_TURN, playerB, "Silvercoat Lion", 1);
+
+ setStopAt(2, PhaseStep.END_TURN);
execute();
-
- assertGraveyardCount(playerA,"Boomerang", 1);
- assertGraveyardCount(playerA,"Scout's Warning", 1);
- assertHandCount(playerB, "Bloodflow Connoisseur", 0); // never comes back because first Tidehollow Sculler left battlefield before target was exiled
- assertHandCount(playerB, "Silvercoat Lion", 0);
- assertExileCount("Silvercoat Lion", 1);
-
- assertPermanentCount(playerA, "Tidehollow Sculler", 1);
-
+ assertAllCommandsUsed();
}
+
+ @Test
+ public void test_MultipleRuns() {
+ // test random selection by AI (must use direct select by alias, not AI)
+ for (int i = 1; i <= 10; i++) {
+ try {
+ this.reset();
+ System.out.println("run " + i);
+ test_CastTwoCardFromHandWillBeExiled();
+ } catch (Exception e) {
+ //
+ }
+ }
+ }
+
}
\ No newline at end of file
diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/WhisperwoodElementalTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/WhisperwoodElementalTest.java
index e2a1849c84..e6a48d117a 100644
--- a/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/WhisperwoodElementalTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/cards/triggers/dies/WhisperwoodElementalTest.java
@@ -1,6 +1,6 @@
-
package org.mage.test.cards.triggers.dies;
+import mage.constants.EmptyNames;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
@@ -18,7 +18,6 @@ public class WhisperwoodElementalTest extends CardTestPlayerBase {
/**
* Tests that the dies triggered ability of silvercoat lion (gained by sacrificed Whisperwood Elemental)
* triggers as he dies from Ligning Bolt
- *
*/
@Test
public void testDiesTriggeredAbility() {
@@ -30,17 +29,20 @@ public class WhisperwoodElementalTest extends CardTestPlayerBase {
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sacrifice {this}: Until end of turn, face-up, nontoken creatures you control gain \"When this creature dies, manifest the top card of your library.");
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", "Silvercoat Lion");
+ showBattlefield("A battle", 1, PhaseStep.END_TURN, playerA);
+ showGraveyard("A grave", 1, PhaseStep.END_TURN, playerA);
setStopAt(1, PhaseStep.END_TURN);
execute();
+ assertAllCommandsUsed();
assertLife(playerA, 20);
assertLife(playerB, 20);
-
+
assertGraveyardCount(playerA, "Whisperwood Elemental", 1);
assertGraveyardCount(playerA, "Silvercoat Lion", 1);
// Manifested creature from dying Silvercoat Lion
- assertPermanentCount(playerA, "", 1);
+ assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
}
}
diff --git a/Mage.Tests/src/test/java/org/mage/test/lki/LastKnownInformationTest.java b/Mage.Tests/src/test/java/org/mage/test/lki/LastKnownInformationTest.java
index ef91492177..352ec36de5 100644
--- a/Mage.Tests/src/test/java/org/mage/test/lki/LastKnownInformationTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/lki/LastKnownInformationTest.java
@@ -58,7 +58,7 @@ public class LastKnownInformationTest extends CardTestPlayerBase {
assertPermanentCount(playerA, "Soldier", 2);
assertGraveyardCount(playerB, "Lightning Bolt", 2);
- assertActionCount(playerB, 0);
+ assertActionsCount(playerB, 0);
}
diff --git a/Mage.Tests/src/test/java/org/mage/test/load/SimpleMageClient.java b/Mage.Tests/src/test/java/org/mage/test/load/SimpleMageClient.java
index 305b041106..930f37f2a0 100644
--- a/Mage.Tests/src/test/java/org/mage/test/load/SimpleMageClient.java
+++ b/Mage.Tests/src/test/java/org/mage/test/load/SimpleMageClient.java
@@ -16,7 +16,7 @@ import org.apache.log4j.Logger;
public class SimpleMageClient implements MageClient {
private final UUID clientId;
- private static final MageVersion version = new MageVersion(MageVersion.MAGE_VERSION_MAJOR, MageVersion.MAGE_VERSION_MINOR, MageVersion.MAGE_VERSION_PATCH, MageVersion.MAGE_VERSION_MINOR_PATCH, MageVersion.MAGE_VERSION_INFO);
+ private static final MageVersion version = new MageVersion(MageClient.class);
private static final Logger log = Logger.getLogger(SimpleMageClient.class);
diff --git a/Mage.Tests/src/test/java/org/mage/test/multiplayer/MyriadTest.java b/Mage.Tests/src/test/java/org/mage/test/multiplayer/MyriadTest.java
index 8f93c6ebee..0538e0c3d6 100644
--- a/Mage.Tests/src/test/java/org/mage/test/multiplayer/MyriadTest.java
+++ b/Mage.Tests/src/test/java/org/mage/test/multiplayer/MyriadTest.java
@@ -1,7 +1,5 @@
-
package org.mage.test.multiplayer;
-import java.io.FileNotFoundException;
import mage.constants.MultiplayerAttackOption;
import mage.constants.PhaseStep;
import mage.constants.RangeOfInfluence;
@@ -12,8 +10,9 @@ import mage.game.GameException;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestMultiPlayerBase;
+import java.io.FileNotFoundException;
+
/**
- *
* @author LevelX2
*/
public class MyriadTest extends CardTestMultiPlayerBase {
@@ -72,27 +71,32 @@ public class MyriadTest extends CardTestMultiPlayerBase {
// Myriad (Whenever this creature attacks, for each opponent other than the defending player, put a token that's a copy of this creature onto the battlefield tapped and attacking that player or a planeswalker he or she controls. Exile those tokens at the end of combat.)
addCard(Zone.BATTLEFIELD, playerD, "Caller of the Pack"); // 8/6
+ // turns: A, D, C, B
+
// +1: You gain 2 life.
// -1: Put a +1/+1 counter on each creature you control. Those creatures gain vigilance until end of turn.
// -6: Create a white Avatar creature token. It has "This creature's power and toughness are each equal to your life total."
addCard(Zone.BATTLEFIELD, playerA, "Ajani Goldmane");
+ // +2 life
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "+1:");
+ checkLife("must have +2 life", 2, PhaseStep.PRECOMBAT_MAIN, playerA, 40 + 2);
+ // D attack C, create 2 copy of caller (for each opponent exclude defender = 2) and attack to ajani
attack(2, playerD, "Caller of the Pack", playerC);
- addTarget(playerD, "Ajani Goldmane");
+ addTarget(playerD, "Ajani Goldmane"); // select ajani instead playerA for pack attack
+ checkPermanentCount("must have 3 packs", 2, PhaseStep.END_COMBAT, playerD, "Caller of the Pack", 3);
+ checkPermanentCount("ajani must die", 2, PhaseStep.END_COMBAT, playerA, "Ajani Goldmane", 0);
+ checkLife("pack must not damage playerA", 2, PhaseStep.END_COMBAT, playerA, 40 + 2);
+ checkLife("pack must damage playerB by 8", 2, PhaseStep.END_COMBAT, playerB, 40 - 8);
+ checkLife("pack must damage playerC", 2, PhaseStep.END_COMBAT, playerC, 40 - 8);
+ checkLife("pack must not damage playerD", 2, PhaseStep.END_COMBAT, playerD, 40);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertPermanentCount(playerD, "Caller of the Pack", 1);
assertGraveyardCount(playerA, "Ajani Goldmane", 1);
-
- assertLife(playerA, 42);
- assertLife(playerB, 32);
- assertLife(playerC, 32);
- assertLife(playerD, 40);
-
}
/**
diff --git a/Mage.Tests/src/test/java/org/mage/test/player/TestComputerPlayer.java b/Mage.Tests/src/test/java/org/mage/test/player/TestComputerPlayer.java
new file mode 100644
index 0000000000..7e9d8b2cf1
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/player/TestComputerPlayer.java
@@ -0,0 +1,73 @@
+package org.mage.test.player;
+
+import mage.MageObject;
+import mage.abilities.ActivatedAbility;
+import mage.abilities.SpellAbility;
+import mage.constants.Outcome;
+import mage.constants.RangeOfInfluence;
+import mage.game.Game;
+import mage.player.ai.ComputerPlayer;
+import mage.target.Target;
+
+import java.util.LinkedHashMap;
+import java.util.UUID;
+
+/**
+ * @author JayDi85
+ */
+
+// mock class to override to override AI logic for test
+public class TestComputerPlayer extends ComputerPlayer {
+
+ private TestPlayer testPlayerLink;
+
+ public TestComputerPlayer(String name, RangeOfInfluence range) {
+ super(name, range);
+ }
+
+ public void setTestPlayerLink(TestPlayer testPlayerLink) {
+ this.testPlayerLink = testPlayerLink;
+ }
+
+ @Override
+ public SpellAbility chooseSpellAbilityForCast(SpellAbility ability, Game game, boolean noMana) {
+ // copy-paste for TestComputerXXX
+
+ // workaround to cast fused cards in tests by it's NAMES (Wear, Tear, Wear // Tear)
+ // reason: TestPlayer uses outer computerPlayer to cast, not TestPlayer
+ switch (ability.getSpellAbilityType()) {
+ case SPLIT:
+ case SPLIT_FUSED:
+ case SPLIT_AFTERMATH:
+ if (!this.testPlayerLink.getChoices().isEmpty()) {
+ MageObject object = game.getObject(ability.getSourceId());
+ if (object != null) {
+ LinkedHashMap useableAbilities = this.getSpellAbilities(object, game.getState().getZone(object.getId()), game);
+
+ // left, right or fused cast
+ for (String choose : this.testPlayerLink.getChoices()) {
+ for (ActivatedAbility activatedAbility : useableAbilities.values()) {
+ if (activatedAbility instanceof SpellAbility) {
+ if (((SpellAbility) activatedAbility).getCardName().equals(choose)) {
+ return (SpellAbility) activatedAbility;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // default implementation by AI
+ return super.chooseSpellAbilityForCast(ability, game, noMana);
+ }
+
+ @Override
+ public boolean choose(Outcome outcome, Target target, UUID sourceId, Game game) {
+ // copy-paste for TestComputerXXX
+
+ // workaround for discard spells
+ // reason: TestPlayer uses outer computerPlayer to discard but inner code uses choose
+ return testPlayerLink.choose(outcome, target, sourceId, game);
+ }
+}
diff --git a/Mage.Tests/src/test/java/org/mage/test/player/TestComputerPlayer7.java b/Mage.Tests/src/test/java/org/mage/test/player/TestComputerPlayer7.java
new file mode 100644
index 0000000000..e647128bb6
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/player/TestComputerPlayer7.java
@@ -0,0 +1,73 @@
+package org.mage.test.player;
+
+import mage.MageObject;
+import mage.abilities.ActivatedAbility;
+import mage.abilities.SpellAbility;
+import mage.constants.Outcome;
+import mage.constants.RangeOfInfluence;
+import mage.game.Game;
+import mage.player.ai.ComputerPlayer7;
+import mage.target.Target;
+
+import java.util.LinkedHashMap;
+import java.util.UUID;
+
+/**
+ * @author JayDi85
+ */
+
+// mock class to override AI logic in tests
+public class TestComputerPlayer7 extends ComputerPlayer7 {
+
+ private TestPlayer testPlayerLink;
+
+ public TestComputerPlayer7(String name, RangeOfInfluence range, int skill) {
+ super(name, range, skill);
+ }
+
+ public void setTestPlayerLink(TestPlayer testPlayerLink) {
+ this.testPlayerLink = testPlayerLink;
+ }
+
+ @Override
+ public SpellAbility chooseSpellAbilityForCast(SpellAbility ability, Game game, boolean noMana) {
+ // copy-paste for TestComputerXXX
+
+ // workaround to cast fused cards in tests by it's NAMES (Wear, Tear, Wear // Tear)
+ // reason: TestPlayer uses outer computerPlayer to cast, not TestPlayer
+ switch (ability.getSpellAbilityType()) {
+ case SPLIT:
+ case SPLIT_FUSED:
+ case SPLIT_AFTERMATH:
+ if (!this.testPlayerLink.getChoices().isEmpty()) {
+ MageObject object = game.getObject(ability.getSourceId());
+ if (object != null) {
+ LinkedHashMap useableAbilities = this.getSpellAbilities(object, game.getState().getZone(object.getId()), game);
+
+ // left, right or fused cast
+ for (String choose : this.testPlayerLink.getChoices()) {
+ for (ActivatedAbility activatedAbility : useableAbilities.values()) {
+ if (activatedAbility instanceof SpellAbility) {
+ if (((SpellAbility) activatedAbility).getCardName().equals(choose)) {
+ return (SpellAbility) activatedAbility;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // default implementation by AI
+ return super.chooseSpellAbilityForCast(ability, game, noMana);
+ }
+
+ @Override
+ public boolean choose(Outcome outcome, Target target, UUID sourceId, Game game) {
+ // copy-paste for TestComputerXXX
+
+ // workaround for discard spells
+ // reason: TestPlayer uses outer computerPlayer to discard but inner code uses choose
+ return testPlayerLink.choose(outcome, target, sourceId, game);
+ }
+}
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 e6bf95d397..afdbc2270e 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
@@ -1,9 +1,6 @@
package org.mage.test.player;
-import java.io.Serializable;
-import java.util.*;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
+import mage.MageItem;
import mage.MageObject;
import mage.MageObjectReference;
import mage.ObjectColor;
@@ -50,9 +47,17 @@ import mage.players.Player;
import mage.players.net.UserData;
import mage.target.*;
import mage.target.common.*;
+import mage.util.CardUtil;
import org.apache.log4j.Logger;
import org.junit.Assert;
import org.junit.Ignore;
+
+import java.io.Serializable;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
import static org.mage.test.serverside.base.impl.CardTestPlayerAPIImpl.*;
/**
@@ -65,12 +70,15 @@ public class TestPlayer implements Player {
private static final Logger logger = Logger.getLogger(TestPlayer.class);
+ public static final String TARGET_SKIP = "[skip]";
+
private int maxCallsWithoutAction = 100;
private int foundNoAction = 0;
private boolean AIPlayer;
private final List actions = new ArrayList<>();
- private final List choices = new ArrayList<>();
- private final List targets = 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 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<>();
private final ComputerPlayer computerPlayer;
@@ -81,9 +89,16 @@ public class TestPlayer implements Player {
// Before actual turns start. Needed for checking attacker/blocker legality in the tests
private static int initialTurns = 0;
- public TestPlayer(ComputerPlayer computerPlayer) {
+ public TestPlayer(TestComputerPlayer computerPlayer) {
this.computerPlayer = computerPlayer;
AIPlayer = false;
+ computerPlayer.setTestPlayerLink(this);
+ }
+
+ public TestPlayer(TestComputerPlayer7 computerPlayer) {
+ this.computerPlayer = computerPlayer;
+ AIPlayer = false;
+ computerPlayer.setTestPlayerLink(this);
}
public TestPlayer(final TestPlayer testPlayer) {
@@ -92,6 +107,7 @@ public class TestPlayer implements Player {
this.actions.addAll(testPlayer.actions);
this.choices.addAll(testPlayer.choices);
this.targets.addAll(testPlayer.targets);
+ this.aliases.putAll(testPlayer.aliases);
this.modesSet.addAll(testPlayer.modesSet);
this.computerPlayer = testPlayer.computerPlayer.copy();
if (testPlayer.groupsForTargetHandling != null) {
@@ -103,6 +119,26 @@ public class TestPlayer implements Player {
choices.add(choice);
}
+ public List getChoices() {
+ return this.choices;
+ }
+
+ public List getTargets() {
+ return this.targets;
+ }
+
+ public Map getAliases() {
+ return this.aliases;
+ }
+
+ public UUID getAliasByName(String searchName) {
+ if (searchName.startsWith("@")) {
+ return this.aliases.getOrDefault(searchName.substring(1), null);
+ } else {
+ return this.aliases.getOrDefault(searchName, null);
+ }
+ }
+
public void addModeChoice(String mode) {
modesSet.add(mode);
}
@@ -111,6 +147,10 @@ public class TestPlayer implements Player {
targets.add(target);
}
+ public void addAlias(String name, UUID Id) {
+ aliases.put(name, Id);
+ }
+
public ManaOptions getAvailableManaTest(Game game) {
return computerPlayer.getManaAvailable(game);
}
@@ -129,7 +169,7 @@ public class TestPlayer implements Player {
/**
* @param maxCallsWithoutAction max number of priority passes a player may
- * have for this test (default = 100)
+ * have for this test (default = 100)
*/
public void setMaxCallsWithoutAction(int maxCallsWithoutAction) {
this.maxCallsWithoutAction = maxCallsWithoutAction;
@@ -181,7 +221,7 @@ public class TestPlayer implements Player {
filteredName = indexedMatcher.group(1);
index = Integer.valueOf(indexedMatcher.group(2));
}
- filter.add(new NamePredicate(filteredName));
+ filter.add(new NamePredicate(filteredName, true)); // must find any cards even without names
List allPermanents = game.getBattlefield().getAllActivePermanents(filter, controllerID, game);
if (allPermanents.isEmpty()) {
if (failOnNotFound) {
@@ -296,6 +336,31 @@ public class TestPlayer implements Player {
return result;
}
+ public String generateAliasName(String baseAlias, boolean useMiltiNames, int iteration) {
+ if (useMiltiNames) {
+ return baseAlias + "." + iteration;
+ } else {
+ return baseAlias;
+ }
+ }
+
+ private boolean isObjectHaveTargetNameOrAliase(MageObject object, String nameOrAliase) {
+ if (object == null || nameOrAliase == null) {
+ return false;
+ }
+
+ if (nameOrAliase.startsWith("@") && object.getId().equals(getAliasByName(nameOrAliase))) {
+ return true;
+ }
+
+ // must search any names, even empty
+ if (CardUtil.haveSameNames(nameOrAliase, object.getName(), true)) {
+ return true;
+ }
+
+ return object.getName().startsWith(nameOrAliase);
+ }
+
private boolean handleNonPlayerTargetTarget(String target, Ability ability, Game game) {
boolean result = true;
if (target == null) {
@@ -357,28 +422,46 @@ public class TestPlayer implements Player {
for (UUID id : currentTarget.possibleTargets(ability.getSourceId(), ability.getControllerId(), game)) {
if (!currentTarget.getTargets().contains(id)) {
MageObject object = game.getObject(id);
- if (object != null
- && ((object.isCopy() && !originOnly) || (!object.isCopy() && !copyOnly))
- && ((!targetName.isEmpty() && object.getName().startsWith(targetName)) || (targetName.isEmpty() && object.getName().isEmpty()))) {
- if (currentTarget.getNumberOfTargets() == 1) {
- currentTarget.clearChosen();
- }
- if (currentTarget instanceof TargetCreaturePermanentAmount) {
- // supports only to set the complete amount to one target
- TargetCreaturePermanentAmount targetAmount = (TargetCreaturePermanentAmount) currentTarget;
- targetAmount.setAmount(ability, game);
- int amount = targetAmount.getAmountRemaining();
- targetAmount.addTarget(id, amount, ability, game);
- targetsSet++;
- } else {
- currentTarget.addTarget(id, ability, game);
- targetsSet++;
- }
- if (currentTarget.getTargets().size() == currentTarget.getMaxNumberOfTargets()) {
- index++;
- }
- break;
+
+ if (object == null) {
+ continue;
}
+
+ // only origin
+ if (originOnly && object.isCopy()) {
+ continue;
+ }
+
+ // only copy
+ if (copyOnly && !object.isCopy()) {
+ continue;
+ }
+
+ // need by alias or by name
+ if (!isObjectHaveTargetNameOrAliase(object, targetName)) {
+ continue;
+ }
+
+ // founded, can use as target
+
+ if (currentTarget.getNumberOfTargets() == 1) {
+ currentTarget.clearChosen();
+ }
+ if (currentTarget instanceof TargetCreaturePermanentAmount) {
+ // supports only to set the complete amount to one target
+ TargetCreaturePermanentAmount targetAmount = (TargetCreaturePermanentAmount) currentTarget;
+ targetAmount.setAmount(ability, game);
+ int amount = targetAmount.getAmountRemaining();
+ targetAmount.addTarget(id, amount, ability, game);
+ targetsSet++;
+ } else {
+ currentTarget.addTarget(id, ability, game);
+ targetsSet++;
+ }
+ if (currentTarget.getTargets().size() == currentTarget.getMaxNumberOfTargets()) {
+ index++;
+ }
+ break;
}
}
}
@@ -432,6 +515,8 @@ public class TestPlayer implements Player {
groupsForTargetHandling = null;
}
}
+ // TODO: fix wrong commands (on non existing card), it's HUGE (350+ failed tests with wrong commands)
+ //Assert.fail("Can't find ability to activate command: " + command);
} else if (action.getAction().startsWith("manaActivate:")) {
String command = action.getAction();
command = command.substring(command.indexOf("manaActivate:") + 13);
@@ -512,78 +597,168 @@ public class TestPlayer implements Player {
}
} else if (action.getAction().startsWith("check:")) {
String command = action.getAction();
- command = command.substring(command.indexOf("check:") + 6);
+ command = command.substring(command.indexOf("check:") + "check:".length());
String[] params = command.split("@");
- boolean checkProccessed = false;
+ boolean wasProccessed = false;
if (params.length > 0) {
// check PT: card name, P, T
if (params[0].equals(CHECK_COMMAND_PT) && params.length == 4) {
assertPT(action, game, computerPlayer, params[1], Integer.parseInt(params[2]), Integer.parseInt(params[3]));
actions.remove(action);
- checkProccessed = true;
+ wasProccessed = true;
}
- // check PT: life
+ // check life: life
if (params[0].equals(CHECK_COMMAND_LIFE) && params.length == 2) {
assertLife(action, game, computerPlayer, Integer.parseInt(params[1]));
actions.remove(action);
- checkProccessed = true;
+ wasProccessed = true;
}
// check ability: card name, ability class, must have
if (params[0].equals(CHECK_COMMAND_ABILITY) && params.length == 4) {
assertAbility(action, game, computerPlayer, params[1], params[2], Boolean.parseBoolean(params[3]));
actions.remove(action);
- checkProccessed = true;
+ wasProccessed = true;
}
// check battlefield count: card name, count
if (params[0].equals(CHECK_COMMAND_PERMANENT_COUNT) && params.length == 3) {
assertPermanentCount(action, game, computerPlayer, params[1], Integer.parseInt(params[2]));
actions.remove(action);
- checkProccessed = true;
+ wasProccessed = true;
}
// check exile count: card name, count
if (params[0].equals(CHECK_COMMAND_EXILE_COUNT) && params.length == 3) {
assertExileCount(action, game, computerPlayer, params[1], Integer.parseInt(params[2]));
actions.remove(action);
- checkProccessed = true;
+ 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]));
actions.remove(action);
- checkProccessed = true;
+ wasProccessed = true;
+ }
+
+ // check hand card count: card name, count
+ if (params[0].equals(CHECK_COMMAND_HAND_CARD_COUNT) && params.length == 3) {
+ assertHandCardCount(action, game, computerPlayer, params[1], Integer.parseInt(params[2]));
+ actions.remove(action);
+ wasProccessed = true;
}
// check color: card name, colors, must have
if (params[0].equals(CHECK_COMMAND_COLOR) && params.length == 4) {
assertColor(action, game, computerPlayer, params[1], params[2], Boolean.parseBoolean(params[3]));
actions.remove(action);
- checkProccessed = true;
+ wasProccessed = true;
}
// check subtype: card name, subtype, must have
if (params[0].equals(CHECK_COMMAND_SUBTYPE) && params.length == 4) {
assertSubType(action, game, computerPlayer, params[1], SubType.fromString(params[2]), Boolean.parseBoolean(params[3]));
actions.remove(action);
- checkProccessed = true;
+ wasProccessed = true;
}
// check mana pool: colors, amount
if (params[0].equals(CHECK_COMMAND_MANA_POOL) && params.length == 3) {
assertManaPool(action, game, computerPlayer, params[1], Integer.parseInt(params[2]));
actions.remove(action);
- checkProccessed = true;
+ wasProccessed = true;
+ }
+
+ // check aliase at zone: alias name, zone, must have (only for TestPlayer)
+ if (params[0].equals(CHECK_COMMAND_ALIAS_ZONE) && params.length == 4) {
+ assertAliasZone(action, game, this, params[1], Zone.valueOf(params[2]), Boolean.parseBoolean(params[3]));
+ actions.remove(action);
+ wasProccessed = true;
+ }
+ }
+ if (!wasProccessed) {
+ Assert.fail("Unknow check command or params: " + command);
+ }
+ } else if (action.getAction().startsWith("show:")) {
+ String command = action.getAction();
+ command = command.substring(command.indexOf("show:") + "show:".length());
+
+ String[] params = command.split("@");
+ boolean wasProccessed = false;
+ if (params.length > 0) {
+
+ // show library
+ if (params[0].equals(SHOW_COMMAND_LIBRARY) && params.length == 1) {
+ printStart(action.getActionName());
+ printCards(computerPlayer.getLibrary().getCards(game));
+ printEnd();
+ actions.remove(action);
+ wasProccessed = true;
+ }
+
+ // show hand
+ if (params[0].equals(SHOW_COMMAND_HAND) && params.length == 1) {
+ printStart(action.getActionName());
+ printCards(computerPlayer.getHand().getCards(game));
+ printEnd();
+ actions.remove(action);
+ wasProccessed = true;
+ }
+
+ // show battlefield
+ if (params[0].equals(SHOW_COMMAND_BATTLEFIELD) && params.length == 1) {
+ printStart(action.getActionName());
+ printPermanents(game.getBattlefield().getAllActivePermanents(computerPlayer.getId()));
+ printEnd();
+ actions.remove(action);
+ wasProccessed = true;
+ }
+
+ // show graveyard
+ if (params[0].equals(SHOW_COMMAND_GRAVEYEARD) && params.length == 1) {
+ printStart(action.getActionName());
+ printCards(computerPlayer.getGraveyard().getCards(game));
+ printEnd();
+ actions.remove(action);
+ wasProccessed = true;
+ }
+
+ // show exile
+ if (params[0].equals(SHOW_COMMAND_EXILE) && params.length == 1) {
+ printStart(action.getActionName());
+ printCards(game.getExile().getAllCards(game).stream()
+ .filter(card -> card.isOwnedBy(computerPlayer.getId()))
+ .collect(Collectors.toList()));
+ printEnd();
+ actions.remove(action);
+ wasProccessed = true;
+ }
+
+ // show available abilities
+ if (params[0].equals(SHOW_COMMAND_AVAILABLE_ABILITIES) && params.length == 1) {
+ printStart(action.getActionName());
+ printAbilities(game, computerPlayer.getPlayable(game, true));
+ printEnd();
+ actions.remove(action);
+ wasProccessed = true;
+ }
+
+ // show aliases
+ if (params[0].equals(SHOW_COMMAND_ALIASES) && params.length == 1) {
+ printStart(action.getActionName());
+ printAliases(game, this);
+ printEnd();
+ actions.remove(action);
+ wasProccessed = true;
}
}
- if (!checkProccessed) {
- Assert.fail("Unknow check command or params: " + command);
+ if (!wasProccessed) {
+ Assert.fail("Unknow show command or params: " + command);
}
}
}
@@ -616,6 +791,105 @@ public class TestPlayer implements Player {
return null;
}
+ private void printStart(String name) {
+ System.out.println("\n" + name + ":");
+ }
+
+ private void printEnd() {
+ System.out.println();
+ }
+
+ private void printCards(Set cards) {
+ printCards(cards.stream().collect(Collectors.toList()));
+ }
+
+ private void printCards(List cards) {
+ System.out.println("Total cards: " + cards.size());
+
+ List data = cards.stream()
+ .map(Card::getIdName)
+ .sorted()
+ .collect(Collectors.toList());
+
+ for (String s : data) {
+ System.out.println(s);
+ }
+ }
+
+ private void printPermanents(List cards) {
+ System.out.println("Total permanents: " + cards.size());
+
+ List data = cards.stream()
+ .map(c -> (c.getIdName()
+ + " - " + c.getPower().getValue()
+ + "/" + c.getToughness().getValue()
+ + ", " + (c.isTapped() ? "Tapped" : "Untapped")
+ ))
+ .sorted()
+ .collect(Collectors.toList());
+
+ for (String s : data) {
+ System.out.println(s);
+ }
+ }
+
+ private void printAbilities(Game game, List abilities) {
+
+
+ System.out.println("Total abilities: " + (abilities != null ? abilities.size() : 0));
+ if (abilities == null) {
+ return;
+ }
+
+ List data = abilities.stream()
+ .map(a -> (
+ a.getZone() + " -> "
+ + a.getSourceObject(game).getIdName() + " -> "
+ + (a.getRule().length() > 0
+ ? a.getRule().substring(0, Math.min(20, a.getRule().length()) - 1)
+ : a.getClass().getSimpleName())
+ + "..."
+ ))
+ .sorted()
+ .collect(Collectors.toList());
+
+ for (String s : data) {
+ System.out.println(s);
+ }
+ }
+
+
+ private String getAliasInfo(Game game, TestPlayer player, String aliasName) {
+ MageItem item = findAliasObject(game, player, aliasName);
+ if (item == null) {
+ return aliasName + " [not exists]";
+ }
+
+ if (item instanceof MageObject) {
+ Zone zone = game.getState().getZone(item.getId());
+ return aliasName + " - " + ((MageObject) item).getIdName() + " - " + (zone != null ? zone.toString() : "null");
+ }
+
+ if (item instanceof Player) {
+ return aliasName + " - " + ((Player) item).getName();
+ }
+
+ return aliasName + " [unknown object " + item.getId() + "]";
+ }
+
+ private void printAliases(Game game, TestPlayer player) {
+ System.out.println("Total aliases: " + player.getAliases().size());
+
+ List data = player.getAliases().entrySet().stream()
+ .map(entry -> (getAliasInfo(game, player, entry.getKey())))
+ .sorted()
+ .collect(Collectors.toList());
+
+ for (String s : data) {
+ System.out.println(s);
+ }
+ }
+
private void assertPT(PlayerAction action, Game game, Player player, String permanentName, int Power, int Toughness) {
Permanent perm = findPermanentWithAssert(action, game, player, permanentName);
@@ -674,6 +948,18 @@ public class TestPlayer implements Player {
Assert.assertEquals(action.getActionName() + " - hand must contain " + count, count, player.getHand().size());
}
+ private void assertHandCardCount(PlayerAction action, Game game, Player player, String cardName, int count) {
+ int realCount = 0;
+ for (UUID cardId : player.getHand()) {
+ Card card = game.getCard(cardId);
+ if (card != null && card.getName().equals(cardName)) {
+ realCount++;
+ }
+ }
+
+ Assert.assertEquals(action.getActionName() + " - hand must contain " + count + " cards of " + cardName, count, realCount);
+ }
+
private void assertColor(PlayerAction action, Game game, Player player, String permanentName, String colors, boolean mustHave) {
Assert.assertNotEquals(action.getActionName() + " - must setup colors", "", colors);
@@ -718,6 +1004,36 @@ public class TestPlayer implements Player {
}
}
+ private MageItem findAliasObject(Game game, TestPlayer player, String aliasName) {
+ UUID objectId = player.getAliasByName(aliasName);
+ if (objectId == null) {
+ return null;
+ }
+
+ MageObject itemObject = game.getObject(objectId);
+ if (itemObject != null) {
+ return itemObject;
+ }
+
+ Player itemPlayer = game.getPlayer(objectId);
+ if (itemPlayer != null) {
+ return itemPlayer;
+ }
+
+ return null;
+ }
+
+ private void assertAliasZone(PlayerAction action, Game game, TestPlayer player, String aliasName, Zone needZone, boolean mustHave) {
+ MageItem item = findAliasObject(game, player, aliasName);
+ Zone currentZone = (item == null ? null : game.getState().getZone(item.getId()));
+
+ if (mustHave) {
+ Assert.assertEquals(action.getActionName() + " - alias " + aliasName + " must have zone " + needZone.toString(), needZone, currentZone);
+ } else {
+ Assert.assertNotEquals(action.getActionName() + " - alias " + aliasName + " must have not zone " + needZone.toString(), needZone, currentZone);
+ }
+ }
+
private void assertManaPoolInner(PlayerAction action, Player player, ManaType manaType, Integer amount) {
Integer current = player.getManaPool().get(manaType);
Assert.assertEquals(action.getActionName() + " - mana pool must contain [" + amount.toString() + " " + manaType.toString() + "], but found [" + current.toString() + "]", amount, current);
@@ -804,7 +1120,7 @@ public class TestPlayer implements Player {
// Loop through players and validate can attack/block this turn
UUID defenderId = null;
//List
- for (Iterator it = actions.iterator(); it.hasNext();) {
+ for (Iterator it = actions.iterator(); it.hasNext(); ) {
PlayerAction action = it.next();
if (action.getTurnNum() == game.getTurnNum() && action.getAction().startsWith("attack:")) {
String command = action.getAction();
@@ -963,6 +1279,8 @@ public class TestPlayer implements Player {
if (choice.setChoiceByAnswers(choices, true)) {
return true;
}
+ // TODO: enable fail checks and fix tests
+ //Assert.fail("Wrong choice");
}
return computerPlayer.choose(outcome, choice, game);
}
@@ -978,6 +1296,8 @@ public class TestPlayer implements Player {
}
}
}
+ // TODO: enable fail checks and fix tests
+ //Assert.fail("wrong choice");
}
return computerPlayer.chooseReplacementEffect(rEffects, game);
}
@@ -985,11 +1305,16 @@ public class TestPlayer implements Player {
@Override
public boolean choose(Outcome outcome, Target target, UUID sourceId, Game game, Map options) {
if (!choices.isEmpty()) {
+
+ List usedChoices = new ArrayList<>();
+ List usedTargets = new ArrayList<>();
+
Ability source = null;
StackObject stackObject = game.getStack().getStackObject(sourceId);
if (stackObject != null) {
source = stackObject.getStackAbility();
}
+
if ((target instanceof TargetPermanent) || (target instanceof TargetPermanentOrPlayer)) { // player target not implemted yet
FilterPermanent filterPermanent;
if (target instanceof TargetPermanentOrPlayer) {
@@ -1043,6 +1368,7 @@ public class TestPlayer implements Player {
}
}
}
+
if (target instanceof TargetPlayer) {
for (Player player : game.getPlayers().values()) {
for (String choose2 : choices) {
@@ -1056,42 +1382,74 @@ public class TestPlayer implements Player {
}
}
}
+
+ // TODO: add same choices fixes for other target types (one choice must uses only one time for one target)
if (target instanceof TargetCard) {
- TargetCard targetCard = ((TargetCard) target);
- Set possibleTargets = targetCard.possibleTargets(sourceId, target.getTargetController() == null ? getId() : target.getTargetController(), game);
- for (String choose2 : choices) {
- String[] targetList = choose2.split("\\^");
+ // one choice per target
+ // only unique targets
+ //TargetCard targetFull = ((TargetCard) target);
+
+ usedChoices.clear();
+ usedTargets.clear();
+ boolean targetCompleted = false;
+
+ CheckAllChoices:
+ for (String choiceRecord : choices) {
+ if (targetCompleted) {
+ break CheckAllChoices;
+ }
+
boolean targetFound = false;
- Choice:
- for (String targetName : targetList) {
- for (UUID targetId : possibleTargets) {
+ String[] possibleChoices = choiceRecord.split("\\^");
+
+ CheckOneChoice:
+ for (String possibleChoice : possibleChoices) {
+ Set possibleCards = target.possibleTargets(sourceId, target.getTargetController() == null ? getId() : target.getTargetController(), game);
+ CheckTargetsList:
+ for (UUID targetId : possibleCards) {
MageObject targetObject = game.getObject(targetId);
- if (targetObject != null) {
- if (targetObject.getName().equals(targetName)) {
- if (targetCard.canTarget(targetObject.getId(), game)) {
- if (targetCard.getTargets() != null && !targetCard.getTargets().contains(targetObject.getId())) {
- targetCard.add(targetObject.getId(), game);
- targetFound = true;
- if (target.getTargets().size() >= target.getMaxNumberOfTargets()) {
- break Choice;
- }
- }
+ if (targetObject != null && targetObject.getName().equals(possibleChoice)) {
+ if (target.canTarget(targetObject.getId(), game)) {
+ // only unique targets
+ if (usedTargets.contains(targetObject.getId())) {
+ continue;
}
+
+ // OK, can use it
+ target.add(targetObject.getId(), game);
+ targetFound = true;
+ usedTargets.add(targetObject.getId());
+
+ // break on full targets list
+ if (target.getTargets().size() >= target.getMaxNumberOfTargets()) {
+ targetCompleted = true;
+ break CheckOneChoice;
+ }
+
+ // restart search
+ break CheckTargetsList;
}
}
-
}
}
+
if (targetFound) {
- if (targetCard.isChosen()) {
- choices.remove(choose2);
- return true;
- } else {
- target.clearChosen();
- }
+ usedChoices.add(choiceRecord);
+ }
+ }
+
+ // apply only on ALL targets or revert
+ if (usedChoices.size() > 0) {
+ if (target.isChosen()) {
+ choices.removeAll(usedChoices);
+ return true;
+ } else {
+ Assert.fail("Not full targets list.");
+ target.clearChosen();
}
}
}
+
if (target instanceof TargetSource) {
Set possibleTargets;
TargetSource t = ((TargetSource) target);
@@ -1122,11 +1480,40 @@ public class TestPlayer implements Player {
}
}
}
+
+ // TODO: enable fail checks and fix tests
+ /*
+ if (!target.getTargetName().equals("starting player")) {
+ Assert.fail("Wrong choice");
+ }
+ */
}
return computerPlayer.choose(outcome, target, sourceId, game, options);
}
+ private void checkTargetDefinitionMarksSupport(Target needTarget, String targetDefinition, String canSupportChars) {
+ // fail on wrong chars in definition
+ // ^ - multiple targets
+ // [] - special option like [no copy]
+ // = - target type like targetPlayer=PlayerA
+ Boolean foundMulti = targetDefinition.contains("^");
+ Boolean foundSpecialStart = targetDefinition.contains("[");
+ Boolean foundSpecialClose = targetDefinition.contains("]");
+ Boolean foundEquals = targetDefinition.contains("=");
+
+ Boolean canMulti = canSupportChars.contains("^");
+ Boolean canSpecialStart = canSupportChars.contains("[");
+ Boolean canSpecialClose = canSupportChars.contains("]");
+ Boolean canEquals = canSupportChars.contains("=");
+
+ // how to fix: change target definition for addTarget in test's code or update choose from targets implementation in TestPlayer
+ if ((foundMulti && !canMulti) || (foundSpecialStart && !canSpecialStart) || (foundSpecialClose && !canSpecialClose) || (foundEquals && !canEquals)) {
+ Assert.fail("Targets list was setup by addTarget with " + targets + ", but target definition [" + targetDefinition + "]"
+ + " is not supported by [" + canSupportChars + "] for target class " + needTarget.getClass().getSimpleName());
+ }
+ }
+
@Override
public boolean chooseTarget(Outcome outcome, Target target, Ability source, Game game) {
if (!targets.isEmpty()) {
@@ -1134,67 +1521,22 @@ public class TestPlayer implements Player {
if (target.getTargetController() != null && target.getAbilityController() != null) {
abilityControllerId = target.getAbilityController();
}
- if (target instanceof TargetCardInGraveyardOrBattlefield) {
- boolean removeTargetDefinition = false;
- Filter filter = target.getFilter();
- for (String targetDefinition : targets) {
- String[] targetList = targetDefinition.split("\\^");
- boolean targetFound = false;
- for (String targetName : targetList) {
- boolean originOnly = false;
- boolean copyOnly = false;
- if (targetName.endsWith("]")) {
- if (targetName.endsWith("[no copy]")) {
- originOnly = true;
- targetName = targetName.substring(0, targetName.length() - 9);
- }
- if (targetName.endsWith("[only copy]")) {
- copyOnly = true;
- targetName = targetName.substring(0, targetName.length() - 11);
- }
- }
- for (Permanent permanent : game.getBattlefield().getAllActivePermanents()) {
- if (permanent.getName().equals(targetName) || (permanent.getName() + '-' + permanent.getExpansionSetCode()).equals(targetName)) {
- if (filter.match(permanent, game) && target.canTarget(abilityControllerId, permanent.getId(), source, game) && !target.getTargets().contains(permanent.getId())) {
- if ((permanent.isCopy() && !originOnly) || (!permanent.isCopy() && !copyOnly)) {
- target.add(permanent.getId(), game);
- targetFound = true;
- break;
- }
- }
- }
- }
- if (!targetFound) {
- for (UUID playerId : game.getState().getPlayersInRange(this.getId(), game)) {
- Player player = game.getPlayer(playerId);
- for (Card card : player.getGraveyard().getCards(((TargetCardInGraveyardOrBattlefield) target).getFilter(), game)) {
- if (card.getName().equals(targetName) || (card.getName() + '-' + card.getExpansionSetCode()).equals(targetName)) {
- if (((TargetCardInYourGraveyard) target).canTarget(abilityControllerId, card.getId(), source, game) && !target.getTargets().contains(card.getId())) {
- target.add(card.getId(), game);
- targetFound = true;
- break;
- }
- }
- }
- }
- }
- if (targetFound) {
- targetFound = false;
- removeTargetDefinition = true;
- }
- }
- if (removeTargetDefinition) {
- targets.remove(targetDefinition);
- return true;
- }
- }
+ // do not select
+ if (targets.get(0).equals(TARGET_SKIP)) {
+ Assert.assertEquals("found empty choice, but target is not support 0 choice", 0, target.getMinNumberOfTargets());
+ targets.remove(0);
+ return true;
}
+
+ // player
if (target instanceof TargetPlayer
|| target instanceof TargetAnyTarget
|| target instanceof TargetCreatureOrPlayer
- || target instanceof TargetPermanentOrPlayer) {
+ || target instanceof TargetPermanentOrPlayer
+ || target instanceof TargetDefender) {
for (String targetDefinition : targets) {
+ checkTargetDefinitionMarksSupport(target, targetDefinition, "=");
if (targetDefinition.startsWith("targetPlayer=")) {
String playerName = targetDefinition.substring(targetDefinition.indexOf("targetPlayer=") + 13);
for (Player player : game.getPlayers().values()) {
@@ -1209,11 +1551,15 @@ public class TestPlayer implements Player {
}
}
+
+ // permanent in battlefield
if ((target instanceof TargetPermanent)
|| (target instanceof TargetPermanentOrPlayer)
|| (target instanceof TargetAnyTarget)
- || (target instanceof TargetCreatureOrPlayer)) {
+ || (target instanceof TargetCreatureOrPlayer)
+ || (target instanceof TargetDefender)) {
for (String targetDefinition : targets) {
+ checkTargetDefinitionMarksSupport(target, targetDefinition, "^[]");
String[] targetList = targetDefinition.split("\\^");
boolean targetFound = false;
for (String targetName : targetList) {
@@ -1236,8 +1582,11 @@ public class TestPlayer implements Player {
if (filter instanceof FilterCreaturePlayerOrPlaneswalker) {
filter = ((FilterCreaturePlayerOrPlaneswalker) filter).getCreatureFilter();
}
- if (filter instanceof TargetPermanentOrPlayer) {
- filter = ((TargetPermanentOrPlayer) filter).getFilterPermanent();
+ if (filter instanceof FilterPermanentOrPlayer) {
+ filter = ((FilterPermanentOrPlayer) filter).getPermanentFilter();
+ }
+ if (filter instanceof FilterPlaneswalkerOrPlayer) {
+ filter = ((FilterPlaneswalkerOrPlayer) filter).getFilterPermanent();
}
for (Permanent permanent : game.getBattlefield().getAllActivePermanents((FilterPermanent) filter, game)) {
if (permanent.getName().equals(targetName) || (permanent.getName() + '-' + permanent.getExpansionSetCode()).equals(targetName)) {
@@ -1259,8 +1608,10 @@ public class TestPlayer implements Player {
}
}
+ // card in hand
if (target instanceof TargetCardInHand) {
for (String targetDefinition : targets) {
+ checkTargetDefinitionMarksSupport(target, targetDefinition, "^");
String[] targetList = targetDefinition.split("\\^");
boolean targetFound = false;
for (String targetName : targetList) {
@@ -1279,17 +1630,20 @@ public class TestPlayer implements Player {
return true;
}
}
-
}
- if (target instanceof TargetCardInYourGraveyard) {
+
+ // card in exile
+ if (target instanceof TargetCardInExile) {
+ TargetCardInExile targetFull = (TargetCardInExile) target;
for (String targetDefinition : targets) {
+ checkTargetDefinitionMarksSupport(target, targetDefinition, "^");
String[] targetList = targetDefinition.split("\\^");
boolean targetFound = false;
for (String targetName : targetList) {
- for (Card card : computerPlayer.getGraveyard().getCards(((TargetCardInYourGraveyard) target).getFilter(), game)) {
+ for (Card card : game.getExile().getCards(targetFull.getFilter(), game)) {
if (card.getName().equals(targetName) || (card.getName() + '-' + card.getExpansionSetCode()).equals(targetName)) {
- if (((TargetCardInYourGraveyard) target).canTarget(abilityControllerId, card.getId(), source, game) && !target.getTargets().contains(card.getId())) {
- target.add(card.getId(), game);
+ if (targetFull.canTarget(abilityControllerId, card.getId(), source, game) && !targetFull.getTargets().contains(card.getId())) {
+ targetFull.add(card.getId(), game);
targetFound = true;
break;
}
@@ -1301,26 +1655,22 @@ public class TestPlayer implements Player {
return true;
}
}
-
}
- if (target instanceof TargetCardInOpponentsGraveyard) {
+
+ // card in battlefield
+ if (target instanceof TargetCardInGraveyardOrBattlefield) {
+ TargetCard targetFull = (TargetCard) target;
for (String targetDefinition : targets) {
+ checkTargetDefinitionMarksSupport(target, targetDefinition, "^");
String[] targetList = targetDefinition.split("\\^");
boolean targetFound = false;
-
for (String targetName : targetList) {
- IterateOpponentsGraveyards:
- for (UUID opponentId : game.getState().getPlayersInRange(getId(), game)) {
- if (computerPlayer.hasOpponent(opponentId, game)) {
- Player opponent = game.getPlayer(opponentId);
- for (Card card : opponent.getGraveyard().getCards(((TargetCardInOpponentsGraveyard) target).getFilter(), game)) {
- if (card.getName().equals(targetName) || (card.getName() + '-' + card.getExpansionSetCode()).equals(targetName)) {
- if (((TargetCardInOpponentsGraveyard) target).canTarget(abilityControllerId, card.getId(), source, game) && !target.getTargets().contains(card.getId())) {
- target.add(card.getId(), game);
- targetFound = true;
- break IterateOpponentsGraveyards;
- }
- }
+ for (Card card : game.getBattlefield().getAllActivePermanents()) {
+ if (card.getName().equals(targetName) || (card.getName() + '-' + card.getExpansionSetCode()).equals(targetName)) {
+ if (targetFull.canTarget(abilityControllerId, card.getId(), source, game) && !targetFull.getTargets().contains(card.getId())) {
+ targetFull.add(card.getId(), game);
+ targetFound = true;
+ break;
}
}
}
@@ -1330,10 +1680,67 @@ public class TestPlayer implements Player {
return true;
}
}
+ }
+
+
+ // card in graveyard
+ if (target instanceof TargetCardInOpponentsGraveyard
+ || target instanceof TargetCardInYourGraveyard
+ || target instanceof TargetCardInGraveyard
+ || target instanceof TargetCardInGraveyardOrBattlefield) {
+ TargetCard targetFull = (TargetCard) target;
+
+ List needPlayers = game.getState().getPlayersInRange(getId(), game).toList();
+ // fix for opponent graveyard
+ if (target instanceof TargetCardInOpponentsGraveyard) {
+ // current player remove
+ Assert.assertTrue(needPlayers.contains(getId()));
+ needPlayers.remove(getId());
+ Assert.assertFalse(needPlayers.contains(getId()));
+ }
+ // fix for your graveyard
+ if (target instanceof TargetCardInYourGraveyard) {
+ // only current player
+ Assert.assertTrue(needPlayers.contains(getId()));
+ needPlayers.clear();
+ needPlayers.add(getId());
+ Assert.assertEquals(1, needPlayers.size());
+ }
+
+ for (String targetDefinition : targets) {
+ checkTargetDefinitionMarksSupport(target, targetDefinition, "^");
+
+ String[] targetList = targetDefinition.split("\\^");
+ boolean targetFound = false;
+ for (String targetName : targetList) {
+ IterateGraveyards:
+ for (UUID playerId : needPlayers) {
+ Player player = game.getPlayer(playerId);
+ for (Card card : player.getGraveyard().getCards(targetFull.getFilter(), game)) {
+ if (card.getName().equals(targetName) || (card.getName() + '-' + card.getExpansionSetCode()).equals(targetName)) {
+ if (targetFull.canTarget(abilityControllerId, card.getId(), source, game) && !target.getTargets().contains(card.getId())) {
+ target.add(card.getId(), game);
+ targetFound = true;
+ break IterateGraveyards;
+ }
+ }
+ }
+
+ }
+ }
+
+ if (targetFound) {
+ targets.remove(targetDefinition);
+ return true;
+ }
+ }
}
+
+ // stack
if (target instanceof TargetSpell) {
for (String targetDefinition : targets) {
+ checkTargetDefinitionMarksSupport(target, targetDefinition, "^");
String[] targetList = targetDefinition.split("\\^");
boolean targetFound = false;
for (String targetName : targetList) {
@@ -1351,16 +1758,33 @@ public class TestPlayer implements Player {
}
}
}
-
}
+
+ // wrong target settings by addTarget
+ // how to fix: implement target class processing above
+ if (!targets.isEmpty()) {
+ String message;
+
+ if (source != null) {
+ message = "Targets list was setup by addTarget with " + targets + ", but not used in ["
+ + "card " + source.getSourceObject(game)
+ + " -> ability " + source.getClass().getSimpleName() + " (" + source.getRule().substring(0, Math.min(20, source.getRule().length()) - 1) + "..." + ")"
+ + " -> target " + target.getClass().getSimpleName() + " (" + target.getMessage() + ")"
+ + "]";
+ } else {
+ message = "Targets list was setup by addTarget with " + targets + ", but not used in ["
+ + "card XXX"
+ + " -> target " + target.getClass().getSimpleName() + " (" + target.getMessage() + ")"
+ + "]";
+ }
+ Assert.fail(message);
+ }
+
return computerPlayer.chooseTarget(outcome, target, source, game);
}
@Override
- public boolean chooseTarget(Outcome outcome, Cards cards,
- TargetCard target, Ability source,
- Game game
- ) {
+ public boolean chooseTarget(Outcome outcome, Cards cards, TargetCard target, Ability source, Game game) {
if (!targets.isEmpty()) {
for (String targetDefinition : targets) {
String[] targetList = targetDefinition.split("\\^");
@@ -1379,13 +1803,15 @@ public class TestPlayer implements Player {
return true;
}
}
+
+ // TODO: enable fail checks and fix tests
+ //Assert.fail("Wrong target");
}
return computerPlayer.chooseTarget(outcome, cards, target, source, game);
}
@Override
- public TriggeredAbility chooseTriggeredAbility(List abilities, Game game
- ) {
+ public TriggeredAbility chooseTriggeredAbility(List abilities, Game game) {
if (!choices.isEmpty()) {
for (TriggeredAbility ability : abilities) {
if (ability.toString().startsWith(choices.get(0))) {
@@ -1393,23 +1819,19 @@ public class TestPlayer implements Player {
return ability;
}
}
+ // TODO: enable fail checks and fix tests
+ //Assert.fail("Wrong choice");
}
return computerPlayer.chooseTriggeredAbility(abilities, game);
}
@Override
- public boolean chooseUse(Outcome outcome, String message,
- Ability source, Game game
- ) {
+ public boolean chooseUse(Outcome outcome, String message, Ability source, Game game) {
return this.chooseUse(outcome, message, null, null, null, source, game);
}
@Override
- public boolean chooseUse(Outcome outcome, String message,
- String secondMessage, String trueText,
- String falseText, Ability source,
- Game game
- ) {
+ public boolean chooseUse(Outcome outcome, String message, String secondMessage, String trueText, String falseText, Ability source, Game game) {
if (message.equals("Scry 1?")) {
return false;
}
@@ -1422,14 +1844,14 @@ public class TestPlayer implements Player {
choices.remove(0);
return true;
}
+ // TODO: enable fail checks and fix tests
+ //Assert.fail("Wrong choice");
}
return computerPlayer.chooseUse(outcome, message, secondMessage, trueText, falseText, source, game);
}
@Override
- public int announceXMana(int min, int max, String message,
- Game game, Ability ability
- ) {
+ public int announceXMana(int min, int max, String message, Game game, Ability ability) {
if (!choices.isEmpty()) {
for (String choice : choices) {
if (choice.startsWith("X=")) {
@@ -1443,10 +1865,7 @@ public class TestPlayer implements Player {
}
@Override
- public int announceXCost(int min, int max, String message,
- Game game, Ability ability,
- VariableCost variablCost
- ) {
+ public int announceXCost(int min, int max, String message, Game game, Ability ability, VariableCost variablCost) {
if (!choices.isEmpty()) {
if (choices.get(0).startsWith("X=")) {
int xValue = Integer.parseInt(choices.get(0).substring(2));
@@ -1458,9 +1877,7 @@ public class TestPlayer implements Player {
}
@Override
- public int getAmount(int min, int max, String message,
- Game game
- ) {
+ public int getAmount(int min, int max, String message, Game game) {
if (!choices.isEmpty()) {
if (choices.get(0).startsWith("X=")) {
int xValue = Integer.parseInt(choices.get(0).substring(2));
@@ -1472,14 +1889,12 @@ public class TestPlayer implements Player {
}
@Override
- public void addAbility(Ability ability
- ) {
+ public void addAbility(Ability ability) {
computerPlayer.addAbility(ability);
}
@Override
- public boolean activateAbility(ActivatedAbility ability, Game game
- ) {
+ public boolean activateAbility(ActivatedAbility ability, Game game) {
return computerPlayer.activateAbility(ability, game);
}
@@ -1499,14 +1914,12 @@ public class TestPlayer implements Player {
}
@Override
- public void won(Game game
- ) {
+ public void won(Game game) {
computerPlayer.won(game);
}
@Override
- public void restore(Player player
- ) {
+ public void restore(Player player) {
this.modesSet.clear();
this.modesSet.addAll(((TestPlayer) player).modesSet);
this.actions.clear();
@@ -1515,25 +1928,24 @@ public class TestPlayer implements Player {
this.choices.addAll(((TestPlayer) player).choices);
this.targets.clear();
this.targets.addAll(((TestPlayer) player).targets);
+ this.aliases.clear();
+ this.aliases.putAll(((TestPlayer) player).aliases);
computerPlayer.restore(player);
}
@Override
- public void useDeck(Deck deck, Game game
- ) {
+ public void useDeck(Deck deck, Game game) {
computerPlayer.useDeck(deck, game);
}
@Override
- public void init(Game game
- ) {
+ public void init(Game game) {
initialTurns = 0;
computerPlayer.init(game);
}
@Override
- public void init(Game game, boolean testMode
- ) {
+ public void init(Game game, boolean testMode) {
initialTurns = 0;
computerPlayer.init(game, testMode);
}
@@ -1549,14 +1961,12 @@ public class TestPlayer implements Player {
}
@Override
- public void otherPlayerLeftGame(Game game
- ) {
+ public void otherPlayerLeftGame(Game game) {
computerPlayer.otherPlayerLeftGame(game);
}
@Override
- public void beginTurn(Game game
- ) {
+ public void beginTurn(Game game) {
checkLegalMovesThisTurn(game);
computerPlayer.beginTurn(game);
}
@@ -1577,14 +1987,12 @@ public class TestPlayer implements Player {
}
@Override
- public void controlPlayersTurn(Game game, UUID playerId
- ) {
+ public void controlPlayersTurn(Game game, UUID playerId) {
computerPlayer.controlPlayersTurn(game, playerId);
}
@Override
- public void setTurnControlledBy(UUID playerId
- ) {
+ public void setTurnControlledBy(UUID playerId) {
computerPlayer.setTurnControlledBy(playerId);
}
@@ -1604,98 +2012,77 @@ public class TestPlayer implements Player {
}
@Override
- public void setGameUnderYourControl(boolean value
- ) {
+ public void setGameUnderYourControl(boolean value) {
computerPlayer.setGameUnderYourControl(value);
}
@Override
- public void setGameUnderYourControl(boolean value, boolean fullRestore
- ) {
+ public void setGameUnderYourControl(boolean value, boolean fullRestore) {
computerPlayer.setGameUnderYourControl(value, fullRestore);
}
@Override
- public void endOfTurn(Game game
- ) {
+ public void endOfTurn(Game game) {
computerPlayer.endOfTurn(game);
}
@Override
- public boolean canBeTargetedBy(MageObject source, UUID sourceControllerId,
- Game game
- ) {
+ public boolean canBeTargetedBy(MageObject source, UUID sourceControllerId, Game game) {
return computerPlayer.canBeTargetedBy(source, sourceControllerId, game);
}
@Override
- public boolean hasProtectionFrom(MageObject source, Game game
- ) {
+ public boolean hasProtectionFrom(MageObject source, Game game) {
return computerPlayer.hasProtectionFrom(source, game);
}
@Override
- public int drawCards(int num, Game game
- ) {
+ public int drawCards(int num, Game game) {
return computerPlayer.drawCards(num, game);
}
@Override
- public int drawCards(int num, Game game,
- List appliedEffects
- ) {
+ public int drawCards(int num, Game game, List appliedEffects) {
return computerPlayer.drawCards(num, game, appliedEffects);
}
@Override
- public void discardToMax(Game game
- ) {
+ public void discardToMax(Game game) {
computerPlayer.discardToMax(game);
}
@Override
- public boolean putInHand(Card card, Game game
- ) {
+ public boolean putInHand(Card card, Game game) {
return computerPlayer.putInHand(card, game);
}
@Override
- public boolean removeFromHand(Card card, Game game
- ) {
+ public boolean removeFromHand(Card card, Game game) {
return computerPlayer.removeFromHand(card, game);
}
@Override
- public boolean removeFromLibrary(Card card, Game game
- ) {
+ public boolean removeFromLibrary(Card card, Game game) {
return computerPlayer.removeFromLibrary(card, game);
}
@Override
- public void discard(int amount, Ability source,
- Game game
- ) {
+ public void discard(int amount, Ability source, Game game) {
computerPlayer.discard(amount, source, game);
}
@Override
- public Card discardOne(boolean random, Ability source,
- Game game
- ) {
+ public Card discardOne(boolean random, Ability source, Game game) {
return computerPlayer.discardOne(random, source, game);
}
@Override
- public Cards discard(int amount, boolean random, Ability source,
- Game game
- ) {
+ public Cards discard(int amount, boolean random, Ability source, Game game) {
return computerPlayer.discard(amount, random, source, game);
}
@Override
- public boolean discard(Card card, Ability source,
- Game game
- ) {
+ public boolean discard(Card card, Ability source, Game game) {
return computerPlayer.discard(card, source, game);
}
@@ -1705,67 +2092,52 @@ public class TestPlayer implements Player {
}
@Override
- public boolean addAttachment(UUID permanentId, Game game
- ) {
+ public boolean addAttachment(UUID permanentId, Game game) {
return computerPlayer.addAttachment(permanentId, game);
}
@Override
- public boolean removeAttachment(Permanent attachment, Game game
- ) {
+ public boolean removeAttachment(Permanent attachment, Game game) {
return computerPlayer.removeAttachment(attachment, game);
}
@Override
- public boolean removeFromBattlefield(Permanent permanent, Game game
- ) {
+ public boolean removeFromBattlefield(Permanent permanent, Game game) {
return computerPlayer.removeFromBattlefield(permanent, game);
}
@Override
- public boolean putInGraveyard(Card card, Game game
- ) {
+ public boolean putInGraveyard(Card card, Game game) {
return computerPlayer.putInGraveyard(card, game);
}
@Override
- public boolean removeFromGraveyard(Card card, Game game
- ) {
+ public boolean removeFromGraveyard(Card card, Game game) {
return computerPlayer.removeFromGraveyard(card, game);
}
@Override
- public boolean putCardsOnBottomOfLibrary(Card card, Game game,
- Ability source, boolean anyOrder
- ) {
+ public boolean putCardsOnBottomOfLibrary(Card card, Game game, Ability source, boolean anyOrder) {
return computerPlayer.putCardsOnBottomOfLibrary(card, game, source, anyOrder);
}
@Override
- public boolean putCardsOnBottomOfLibrary(Cards cards, Game game,
- Ability source, boolean anyOrder
- ) {
+ public boolean putCardsOnBottomOfLibrary(Cards cards, Game game, Ability source, boolean anyOrder) {
return computerPlayer.putCardsOnBottomOfLibrary(cards, game, source, anyOrder);
}
@Override
- public boolean putCardOnTopXOfLibrary(Card card, Game game,
- Ability source, int xFromTheTop
- ) {
+ public boolean putCardOnTopXOfLibrary(Card card, Game game, Ability source, int xFromTheTop) {
return computerPlayer.putCardOnTopXOfLibrary(card, game, source, xFromTheTop);
}
@Override
- public boolean putCardsOnTopOfLibrary(Cards cards, Game game,
- Ability source, boolean anyOrder
- ) {
+ public boolean putCardsOnTopOfLibrary(Cards cards, Game game, Ability source, boolean anyOrder) {
return computerPlayer.putCardsOnTopOfLibrary(cards, game, source, anyOrder);
}
@Override
- public void setCastSourceIdWithAlternateMana(UUID sourceId, ManaCosts manaCosts,
- Costs costs
- ) {
+ public void setCastSourceIdWithAlternateMana(UUID sourceId, ManaCosts manaCosts, Costs costs) {
computerPlayer.setCastSourceIdWithAlternateMana(sourceId, manaCosts, costs);
}
@@ -1790,36 +2162,29 @@ public class TestPlayer implements Player {
}
@Override
- public boolean cast(SpellAbility ability, Game game,
- boolean noMana, MageObjectReference reference
- ) {
+ public boolean cast(SpellAbility ability, Game game, boolean noMana, MageObjectReference reference) {
+ // TestPlayer, ComputerPlayer always call inherited cast() from PlayerImpl
+ // that's why chooseSpellAbilityForCast will be ignored in TestPlayer, see workaround with TestComputerPlayerXXX
return computerPlayer.cast(ability, game, noMana, reference);
}
@Override
- public boolean playCard(Card card, Game game,
- boolean noMana, boolean ignoreTiming, MageObjectReference reference
- ) {
+ public boolean playCard(Card card, Game game, boolean noMana, boolean ignoreTiming, MageObjectReference reference) {
return computerPlayer.playCard(card, game, noMana, ignoreTiming, reference);
}
@Override
- public boolean playLand(Card card, Game game,
- boolean ignoreTiming
- ) {
+ public boolean playLand(Card card, Game game, boolean ignoreTiming) {
return computerPlayer.playLand(card, game, ignoreTiming);
}
@Override
- public boolean triggerAbility(TriggeredAbility source, Game game
- ) {
+ public boolean triggerAbility(TriggeredAbility source, Game game) {
return computerPlayer.triggerAbility(source, game);
}
@Override
- public LinkedHashMap getUseableActivatedAbilities(MageObject object, Zone zone,
- Game game
- ) {
+ public LinkedHashMap getUseableActivatedAbilities(MageObject object, Zone zone, Game game) {
return computerPlayer.getUseableActivatedAbilities(object, zone, game);
}
@@ -1834,77 +2199,57 @@ public class TestPlayer implements Player {
}
@Override
- public void shuffleLibrary(Ability source, Game game
- ) {
+ public void shuffleLibrary(Ability source, Game game) {
computerPlayer.shuffleLibrary(source, game);
}
@Override
- public void revealCards(Ability source, Cards cards,
- Game game
- ) {
+ public void revealCards(Ability source, Cards cards, Game game) {
computerPlayer.revealCards(source, cards, game);
}
@Override
- public void revealCards(String name, Cards cards,
- Game game
- ) {
+ public void revealCards(String name, Cards cards, Game game) {
computerPlayer.revealCards(name, cards, game);
}
@Override
- public void revealCards(Ability source, String name,
- Cards cards, Game game
- ) {
+ public void revealCards(Ability source, String name, Cards cards, Game game) {
computerPlayer.revealCards(name, cards, game);
}
@Override
- public void revealCards(String name, Cards cards,
- Game game, boolean postToLog
- ) {
+ public void revealCards(String name, Cards cards, Game game, boolean postToLog) {
computerPlayer.revealCards(name, cards, game, postToLog);
}
@Override
- public void revealCards(Ability source, String name,
- Cards cards, Game game,
- boolean postToLog
- ) {
+ public void revealCards(Ability source, String name, Cards cards, Game game, boolean postToLog) {
computerPlayer.revealCards(name, cards, game, postToLog);
}
@Override
- public void lookAtCards(String name, Cards cards,
- Game game
- ) {
+ public void lookAtCards(String name, Cards cards, Game game) {
computerPlayer.lookAtCards(name, cards, game);
}
@Override
- public void lookAtCards(Ability source, String name,
- Cards cards, Game game
- ) {
+ public void lookAtCards(Ability source, String name, Cards cards, Game game) {
computerPlayer.lookAtCards(source, name, cards, game);
}
@Override
- public void lookAtCards(String name, Card card,
- Game game
- ) {
+ public void lookAtCards(String name, Card card, Game game) {
computerPlayer.lookAtCards(name, card, game);
}
@Override
- public void phasing(Game game
- ) {
+ public void phasing(Game game) {
computerPlayer.phasing(game);
}
@Override
- public void untap(Game game
- ) {
+ public void untap(Game game) {
computerPlayer.untap(game);
}
@@ -1959,28 +2304,22 @@ public class TestPlayer implements Player {
}
@Override
- public void initLife(int life
- ) {
+ public void initLife(int life) {
computerPlayer.initLife(life);
}
@Override
- public void setLife(int life, Game game,
- UUID sourceId
- ) {
+ public void setLife(int life, Game game, UUID sourceId) {
computerPlayer.setLife(life, game, sourceId);
}
@Override
- public void setLife(int life, Game game,
- Ability source
- ) {
+ public void setLife(int life, Game game, Ability source) {
computerPlayer.setLife(life, game, source);
}
@Override
- public void setLifeTotalCanChange(boolean lifeTotalCanChange
- ) {
+ public void setLifeTotalCanChange(boolean lifeTotalCanChange) {
computerPlayer.setLifeTotalCanChange(lifeTotalCanChange);
}
@@ -2000,15 +2339,12 @@ public class TestPlayer implements Player {
}
@Override
- public void setCanLoseLife(boolean canLoseLife
- ) {
+ public void setCanLoseLife(boolean canLoseLife) {
computerPlayer.setCanLoseLife(canLoseLife);
}
@Override
- public int loseLife(int amount, Game game,
- boolean atCombat
- ) {
+ public int loseLife(int amount, Game game, boolean atCombat) {
return computerPlayer.loseLife(amount, game, atCombat);
}
@@ -2018,49 +2354,37 @@ public class TestPlayer implements Player {
}
@Override
- public void setCanGainLife(boolean canGainLife
- ) {
+ public void setCanGainLife(boolean canGainLife) {
computerPlayer.setCanGainLife(canGainLife);
}
@Override
- public int gainLife(int amount, Game game,
- Ability source
- ) {
+ public int gainLife(int amount, Game game, Ability source) {
return computerPlayer.gainLife(amount, game, source);
}
@Override
- public int gainLife(int amount, Game game,
- UUID sourceId
- ) {
+ public int gainLife(int amount, Game game, UUID sourceId) {
return computerPlayer.gainLife(amount, game, sourceId);
}
@Override
- public int damage(int damage, UUID sourceId,
- Game game, boolean combatDamage, boolean preventable
- ) {
+ public int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable) {
return computerPlayer.damage(damage, sourceId, game, combatDamage, preventable);
}
@Override
- public int damage(int damage, UUID sourceId,
- Game game, boolean combatDamage, boolean preventable, List appliedEffects
- ) {
+ public int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable, List appliedEffects) {
return computerPlayer.damage(damage, sourceId, game, combatDamage, preventable, appliedEffects);
}
@Override
- public boolean addCounters(Counter counter, Game game
- ) {
+ public boolean addCounters(Counter counter, Game game) {
return computerPlayer.addCounters(counter, game);
}
@Override
- public void removeCounters(String name, int amount, Ability source,
- Game game
- ) {
+ public void removeCounters(String name, int amount, Ability source, Game game) {
computerPlayer.removeCounters(name, amount, source, game);
}
@@ -2075,8 +2399,7 @@ public class TestPlayer implements Player {
}
@Override
- public void setLandsPerTurn(int landsPerTurn
- ) {
+ public void setLandsPerTurn(int landsPerTurn) {
computerPlayer.setLandsPerTurn(landsPerTurn);
}
@@ -2086,8 +2409,7 @@ public class TestPlayer implements Player {
}
@Override
- public void setLoyaltyUsePerTurn(int loyaltyUsePerTurn
- ) {
+ public void setLoyaltyUsePerTurn(int loyaltyUsePerTurn) {
computerPlayer.setLoyaltyUsePerTurn(loyaltyUsePerTurn);
}
@@ -2097,14 +2419,12 @@ public class TestPlayer implements Player {
}
@Override
- public void setMaxHandSize(int maxHandSize
- ) {
+ public void setMaxHandSize(int maxHandSize) {
computerPlayer.setMaxHandSize(maxHandSize);
}
@Override
- public void setMaxAttackedBy(int maxAttackedBy
- ) {
+ public void setMaxAttackedBy(int maxAttackedBy) {
computerPlayer.setMaxAttackedBy(maxAttackedBy);
}
@@ -2114,32 +2434,27 @@ public class TestPlayer implements Player {
}
@Override
- public void setResponseString(String responseString
- ) {
+ public void setResponseString(String responseString) {
computerPlayer.setResponseString(responseString);
}
@Override
- public void setResponseManaType(UUID manaTypePlayerId, ManaType responseManaType
- ) {
+ public void setResponseManaType(UUID manaTypePlayerId, ManaType responseManaType) {
computerPlayer.setResponseManaType(manaTypePlayerId, responseManaType);
}
@Override
- public void setResponseUUID(UUID responseUUID
- ) {
+ public void setResponseUUID(UUID responseUUID) {
computerPlayer.setResponseUUID(responseUUID);
}
@Override
- public void setResponseBoolean(Boolean responseBoolean
- ) {
+ public void setResponseBoolean(Boolean responseBoolean) {
computerPlayer.setResponseBoolean(responseBoolean);
}
@Override
- public void setResponseInteger(Integer responseInteger
- ) {
+ public void setResponseInteger(Integer responseInteger) {
computerPlayer.setResponseInteger(responseInteger);
}
@@ -2149,8 +2464,7 @@ public class TestPlayer implements Player {
}
@Override
- public void pass(Game game
- ) {
+ public void pass(Game game) {
computerPlayer.pass(game);
}
@@ -2170,33 +2484,27 @@ public class TestPlayer implements Player {
}
@Override
- public void quit(Game game
- ) {
+ public void quit(Game game) {
computerPlayer.quit(game);
}
@Override
- public void timerTimeout(Game game
- ) {
+ public void timerTimeout(Game game) {
computerPlayer.timerTimeout(game);
}
@Override
- public void idleTimeout(Game game
- ) {
+ public void idleTimeout(Game game) {
computerPlayer.idleTimeout(game);
}
@Override
- public void concede(Game game
- ) {
+ public void concede(Game game) {
computerPlayer.concede(game);
}
@Override
- public void sendPlayerAction(mage.constants.PlayerAction playerAction, Game game,
- Object data
- ) {
+ public void sendPlayerAction(mage.constants.PlayerAction playerAction, Game game, Object data) {
computerPlayer.sendPlayerAction(playerAction, game, data);
}
@@ -2211,8 +2519,7 @@ public class TestPlayer implements Player {
}
@Override
- public void lost(Game game
- ) {
+ public void lost(Game game) {
computerPlayer.lost(game);
}
@@ -2222,20 +2529,17 @@ public class TestPlayer implements Player {
}
@Override
- public void drew(Game game
- ) {
+ public void drew(Game game) {
computerPlayer.drew(game);
}
@Override
- public void lostForced(Game game
- ) {
+ public void lostForced(Game game) {
computerPlayer.lostForced(game);
}
@Override
- public boolean canLose(Game game
- ) {
+ public boolean canLose(Game game) {
return computerPlayer.canLose(game);
}
@@ -2260,51 +2564,37 @@ public class TestPlayer implements Player {
}
@Override
- public void declareAttacker(UUID attackerId, UUID defenderId,
- Game game, boolean allowUndo
- ) {
+ public void declareAttacker(UUID attackerId, UUID defenderId, Game game, boolean allowUndo) {
computerPlayer.declareAttacker(attackerId, defenderId, game, allowUndo);
}
@Override
- public void declareBlocker(UUID defenderId, UUID blockerId,
- UUID attackerId, Game game
- ) {
+ public void declareBlocker(UUID defenderId, UUID blockerId, UUID attackerId, Game game) {
computerPlayer.declareBlocker(defenderId, blockerId, attackerId, game);
}
@Override
- public void declareBlocker(UUID defenderId, UUID blockerId,
- UUID attackerId, Game game,
- boolean allowUndo
- ) {
+ public void declareBlocker(UUID defenderId, UUID blockerId, UUID attackerId, Game game, boolean allowUndo) {
computerPlayer.declareBlocker(defenderId, blockerId, attackerId, game, allowUndo);
}
@Override
- public boolean searchLibrary(TargetCardInLibrary target, Game game
- ) {
+ public boolean searchLibrary(TargetCardInLibrary target, Game game) {
return computerPlayer.searchLibrary(target, game);
}
@Override
- public boolean searchLibrary(TargetCardInLibrary target, Game game,
- boolean triggerEvents
- ) {
+ public boolean searchLibrary(TargetCardInLibrary target, Game game, boolean triggerEvents) {
return computerPlayer.searchLibrary(target, game, triggerEvents);
}
@Override
- public boolean searchLibrary(TargetCardInLibrary target, Game game,
- UUID targetPlayerId
- ) {
+ public boolean searchLibrary(TargetCardInLibrary target, Game game, UUID targetPlayerId) {
return computerPlayer.searchLibrary(target, game, targetPlayerId);
}
@Override
- public boolean searchLibrary(TargetCardInLibrary target, Game game,
- UUID targetPlayerId, boolean triggerEvents
- ) {
+ public boolean searchLibrary(TargetCardInLibrary target, Game game, UUID targetPlayerId, boolean triggerEvents) {
return computerPlayer.searchLibrary(target, game, targetPlayerId, triggerEvents);
}
@@ -2319,45 +2609,37 @@ public class TestPlayer implements Player {
}
@Override
- public boolean flipCoin(Game game, ArrayList appliedEffects
- ) {
+ public boolean flipCoin(Game game, ArrayList appliedEffects) {
return computerPlayer.flipCoin(game, appliedEffects);
}
@Override
- public int rollDice(Game game, int numSides
- ) {
+ public int rollDice(Game game, int numSides) {
return computerPlayer.rollDice(game, numSides);
}
@Override
- public int rollDice(Game game, ArrayList appliedEffects,
- int numSides
- ) {
+ public int rollDice(Game game, ArrayList appliedEffects, int numSides) {
return computerPlayer.rollDice(game, appliedEffects, numSides);
}
@Override
- public List getAvailableAttackers(Game game
- ) {
+ public List getAvailableAttackers(Game game) {
return computerPlayer.getAvailableAttackers(game);
}
@Override
- public List getAvailableAttackers(UUID defenderId, Game game
- ) {
+ public List getAvailableAttackers(UUID defenderId, Game game) {
return computerPlayer.getAvailableAttackers(defenderId, game);
}
@Override
- public List getAvailableBlockers(Game game
- ) {
+ public List getAvailableBlockers(Game game) {
return computerPlayer.getAvailableBlockers(game);
}
@Override
- public ManaOptions getManaAvailable(Game game
- ) {
+ public ManaOptions getManaAvailable(Game game) {
return computerPlayer.getManaAvailable(game);
}
@@ -2682,24 +2964,7 @@ public class TestPlayer implements Player {
@Override
public SpellAbility chooseSpellAbilityForCast(SpellAbility ability, Game game, boolean noMana) {
- switch (ability.getSpellAbilityType()) {
- case SPLIT:
- case SPLIT_FUSED:
- case SPLIT_AFTERMATH:
- if (!choices.isEmpty()) {
- MageObject object = game.getObject(ability.getSourceId());
- if (object != null) {
- LinkedHashMap useableAbilities = computerPlayer.getSpellAbilities(object, game.getState().getZone(object.getId()), game);
- for (String choose : choices) {
- for (ActivatedAbility actiavtedAbility : useableAbilities.values()) {
- if (actiavtedAbility.getRule().startsWith(choose)) {
- return (SpellAbility) actiavtedAbility;
- }
- }
- }
- }
- }
- }
+ Assert.fail("That's method must calls only from computerPlayer->cast(), see TestComputerPlayerXXX");
return computerPlayer.chooseSpellAbilityForCast(ability, game, noMana);
}
@@ -2710,7 +2975,7 @@ public class TestPlayer implements Player {
@Override
public boolean choose(Outcome outcome, Target target,
- UUID sourceId, Game game
+ UUID sourceId, Game game
) {
// needed to call here the TestPlayer because it's overwitten
return choose(outcome, target, sourceId, game, null);
@@ -2718,7 +2983,7 @@ public class TestPlayer implements Player {
@Override
public boolean choose(Outcome outcome, Cards cards,
- TargetCard target, Game game
+ TargetCard target, Game game
) {
if (!choices.isEmpty()) {
for (String choose2 : choices) {
@@ -2744,14 +3009,61 @@ public class TestPlayer implements Player {
return true;
}
}
+ // TODO: enable fail checks and fix tests
+ //Assert.fail("Wrong choice");
}
return computerPlayer.choose(outcome, cards, target, game);
}
@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 (founded) {
+ // all done
+ targets.remove(foundedRecord);
+ return true;
+ }
+ }
+
return computerPlayer.chooseTargetAmount(outcome, target, source, game);
}
@@ -2763,15 +3075,15 @@ public class TestPlayer implements Player {
@Override
public boolean choosePile(Outcome outcome, String message,
- List extends Card> pile1, List extends Card> pile2,
- Game game
+ List extends Card> pile1, List extends Card> pile2,
+ Game game
) {
return computerPlayer.choosePile(outcome, message, pile1, pile2, game);
}
@Override
public boolean playMana(Ability ability, ManaCost unpaid,
- String promptText, Game game
+ String promptText, Game game
) {
groupsForTargetHandling = null;
return computerPlayer.playMana(ability, unpaid, promptText, game);
@@ -2785,15 +3097,15 @@ public class TestPlayer implements Player {
@Override
public UUID chooseBlockerOrder(List blockers, CombatGroup combatGroup,
- List blockerOrder, Game game
+ List blockerOrder, Game game
) {
return computerPlayer.chooseBlockerOrder(blockers, combatGroup, blockerOrder, game);
}
@Override
public void assignDamage(int damage, List targets,
- String singleTargetName, UUID sourceId,
- Game game
+ String singleTargetName, UUID sourceId,
+ Game game
) {
computerPlayer.assignDamage(damage, targets, singleTargetName, sourceId, game);
}
@@ -2812,14 +3124,14 @@ public class TestPlayer implements Player {
@Override
public void pickCard(List cards, Deck deck,
- Draft draft
+ Draft draft
) {
computerPlayer.pickCard(cards, deck, draft);
}
@Override
public boolean scry(int value, Ability source,
- Game game
+ Game game
) {
// Don't scry at the start of the game.
if (game.getTurnNum() == 1 && game.getStep() == null) {
@@ -2830,44 +3142,44 @@ public class TestPlayer implements Player {
@Override
public boolean surveil(int value, Ability source,
- Game game
+ Game game
) {
return computerPlayer.surveil(value, source, game);
}
@Override
public boolean moveCards(Card card, Zone toZone,
- Ability source, Game game
+ Ability source, Game game
) {
return computerPlayer.moveCards(card, toZone, source, game);
}
@Override
public boolean moveCards(Card card, Zone toZone,
- Ability source, Game game,
- boolean tapped, boolean faceDown, boolean byOwner, List appliedEffects
+ Ability source, Game game,
+ boolean tapped, boolean faceDown, boolean byOwner, List appliedEffects
) {
return computerPlayer.moveCards(card, toZone, source, game, tapped, faceDown, byOwner, appliedEffects);
}
@Override
public boolean moveCards(Cards cards, Zone toZone,
- Ability source, Game game
+ Ability source, Game game
) {
return computerPlayer.moveCards(cards, toZone, source, game);
}
@Override
public boolean moveCards(Set cards, Zone toZone,
- Ability source, Game game
+ Ability source, Game game
) {
return computerPlayer.moveCards(cards, toZone, source, game);
}
@Override
public boolean moveCards(Set cards, Zone toZone,
- Ability source, Game game,
- boolean tapped, boolean faceDown, boolean byOwner, List appliedEffects
+ Ability source, Game game,
+ boolean tapped, boolean faceDown, boolean byOwner, List appliedEffects
) {
return computerPlayer.moveCards(cards, toZone, source, game, tapped, faceDown, byOwner, appliedEffects);
}
diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/CardTestPlayerBaseAI.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/CardTestPlayerBaseAI.java
index fa1a5241d2..89e522fd5a 100644
--- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/CardTestPlayerBaseAI.java
+++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/CardTestPlayerBaseAI.java
@@ -1,18 +1,17 @@
-
package org.mage.test.serverside.base;
-import java.io.FileNotFoundException;
import mage.constants.MultiplayerAttackOption;
import mage.constants.RangeOfInfluence;
import mage.game.Game;
import mage.game.GameException;
import mage.game.TwoPlayerDuel;
-import mage.player.ai.ComputerPlayer7;
+import org.mage.test.player.TestComputerPlayer7;
import org.mage.test.player.TestPlayer;
import org.mage.test.serverside.base.impl.CardTestPlayerAPIImpl;
+import java.io.FileNotFoundException;
+
/**
- *
* @author LevelX2
*/
public abstract class CardTestPlayerBaseAI extends CardTestPlayerAPIImpl {
@@ -31,7 +30,7 @@ public abstract class CardTestPlayerBaseAI extends CardTestPlayerAPIImpl {
@Override
protected TestPlayer createPlayer(String name, RangeOfInfluence rangeOfInfluence) {
if (name.equals("PlayerA")) {
- TestPlayer testPlayer = new TestPlayer(new ComputerPlayer7("PlayerA", RangeOfInfluence.ONE, skill));
+ TestPlayer testPlayer = new TestPlayer(new TestComputerPlayer7("PlayerA", RangeOfInfluence.ONE, skill));
testPlayer.setAIPlayer(true);
return testPlayer;
}
diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestPlayerBase.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestPlayerBase.java
index b514cc68b4..c6ad3f2f68 100644
--- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestPlayerBase.java
+++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/MageTestPlayerBase.java
@@ -1,16 +1,6 @@
package org.mage.test.serverside.base;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Scanner;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
import mage.cards.Card;
-import mage.cards.decks.Deck;
import mage.cards.decks.DeckCardLists;
import mage.cards.repository.CardInfo;
import mage.cards.repository.CardRepository;
@@ -21,7 +11,6 @@ import mage.game.Game;
import mage.game.match.MatchType;
import mage.game.permanent.PermanentCard;
import mage.game.tournament.TournamentType;
-import mage.player.ai.ComputerPlayer;
import mage.players.Player;
import mage.server.game.GameFactory;
import mage.server.util.ConfigSettings;
@@ -32,8 +21,15 @@ import mage.util.Copier;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.junit.BeforeClass;
+import org.mage.test.player.TestComputerPlayer;
import org.mage.test.player.TestPlayer;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
/**
* Base class for all tests.
*
@@ -334,7 +330,7 @@ public abstract class MageTestPlayerBase {
}
protected TestPlayer createPlayer(String name, RangeOfInfluence rangeOfInfluence) {
- return new TestPlayer(new ComputerPlayer(name, rangeOfInfluence));
+ return new TestPlayer(new TestComputerPlayer(name, rangeOfInfluence));
}
}
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 b858d8609b..4c18ad006f 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
@@ -24,8 +24,10 @@ import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentCard;
import mage.players.ManaPool;
import mage.players.Player;
+import mage.util.CardUtil;
import org.junit.Assert;
import org.junit.Before;
+import org.mage.test.player.PlayerAction;
import org.mage.test.player.TestPlayer;
import org.mage.test.serverside.base.CardTestAPI;
import org.mage.test.serverside.base.MageTestPlayerBase;
@@ -48,15 +50,30 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
// Defines the constant if for activate ability is not target but a ability on the stack to define
public static final String NO_TARGET = "NO_TARGET";
+ // TODO: add target player param to commands
public static final String CHECK_COMMAND_PT = "PT";
public static final String CHECK_COMMAND_LIFE = "LIFE";
public static final String CHECK_COMMAND_ABILITY = "ABILITY";
public static final String CHECK_COMMAND_PERMANENT_COUNT = "PERMANENT_COUNT";
public static final String CHECK_COMMAND_EXILE_COUNT = "EXILE_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_COLOR = "COLOR";
public static final String CHECK_COMMAND_SUBTYPE = "SUBTYPE";
public static final String CHECK_COMMAND_MANA_POOL = "MANA_POOL";
+ public static final String CHECK_COMMAND_ALIAS_ZONE = "ALIAS_ZONE";
+
+ // TODO: add target player param to commands
+ public static final String SHOW_COMMAND_LIBRARY = "LIBRARY";
+ public static final String SHOW_COMMAND_HAND = "HAND";
+ public static final String SHOW_COMMAND_BATTLEFIELD = "BATTLEFIELD";
+ public static final String SHOW_COMMAND_GRAVEYEARD = "GRAVEYARD";
+ public static final String SHOW_COMMAND_EXILE = "EXILE";
+ public static final String SHOW_COMMAND_AVAILABLE_ABILITIES = "AVAILABLE_ABILITIES";
+ public static final String SHOW_COMMAND_ALIASES = "ALIASES";
+
+ // TODO: add target player param to commands
+ public static final String ALIAS_COMMAND_ADD = "ADD";
protected GameOptions gameOptions;
@@ -211,6 +228,8 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
logger.debug("Winner: " + currentGame.getWinner());
logger.info("Test has been executed. Execution time: " + (t2 - t1) / 1000000 + " ms");
+ // TODO: 01.12.2018, JayDi85 - uncomment and fix MANY broken tests with wrong commands
+ //assertAllCommandsUsed();
}
protected TestPlayer createNewPlayer(String playerName, RangeOfInfluence rangeOfInfluence) {
@@ -238,6 +257,8 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
return player;
}
+ // check commands
+
private void check(String checkName, int turnNum, PhaseStep step, TestPlayer player, String command, String... params) {
String res = "check:" + command;
for (String param : params) {
@@ -247,6 +268,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
}
public void checkPT(String checkName, int turnNum, PhaseStep step, TestPlayer player, String permanentName, Integer power, Integer toughness) {
+ //Assert.assertNotEquals("", permanentName);
check(checkName, turnNum, step, player, CHECK_COMMAND_PT, permanentName, power.toString(), toughness.toString());
}
@@ -255,14 +277,17 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
}
public void checkAbility(String checkName, int turnNum, PhaseStep step, TestPlayer player, String permanentName, Class> abilityClass, Boolean mustHave) {
+ //Assert.assertNotEquals("", permanentName);
check(checkName, turnNum, step, player, CHECK_COMMAND_ABILITY, permanentName, abilityClass.getName(), mustHave.toString());
}
public void checkPermanentCount(String checkName, int turnNum, PhaseStep step, TestPlayer player, String permanentName, Integer count) {
+ //Assert.assertNotEquals("", permanentName);
check(checkName, turnNum, step, player, CHECK_COMMAND_PERMANENT_COUNT, permanentName, count.toString());
}
public void checkExileCount(String checkName, int turnNum, PhaseStep step, TestPlayer player, String permanentName, Integer count) {
+ //Assert.assertNotEquals("", permanentName);
check(checkName, turnNum, step, player, CHECK_COMMAND_EXILE_COUNT, permanentName, count.toString());
}
@@ -270,11 +295,18 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
check(checkName, turnNum, step, player, CHECK_COMMAND_HAND_COUNT, count.toString());
}
+ public void checkHandCardCount(String checkName, int turnNum, PhaseStep step, TestPlayer player, String cardName, Integer count) {
+ //Assert.assertNotEquals("", cardName);
+ check(checkName, turnNum, step, player, CHECK_COMMAND_HAND_CARD_COUNT, cardName, count.toString());
+ }
+
public void checkColor(String checkName, int turnNum, PhaseStep step, TestPlayer player, String permanentName, String colors, Boolean mustHave) {
+ //Assert.assertNotEquals("", permanentName);
check(checkName, turnNum, step, player, CHECK_COMMAND_COLOR, permanentName, colors, mustHave.toString());
}
public void checkSubType(String checkName, int turnNum, PhaseStep step, TestPlayer player, String permanentName, SubType subType, Boolean mustHave) {
+ //Assert.assertNotEquals("", permanentName);
check(checkName, turnNum, step, player, CHECK_COMMAND_SUBTYPE, permanentName, subType.toString(), mustHave.toString());
}
@@ -282,6 +314,52 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
check(checkName, turnNum, step, player, CHECK_COMMAND_MANA_POOL, colors, amount.toString());
}
+ public void checkAliasZone(String checkName, int turnNum, PhaseStep step, TestPlayer player, String alias, Zone zone) {
+ checkAliasZone(checkName, turnNum, step, player, alias, zone, true);
+ }
+
+ public void checkAliasZone(String checkName, int turnNum, PhaseStep step, TestPlayer player, String alias, Zone zone, Boolean mustHave) {
+ check(checkName, turnNum, step, player, CHECK_COMMAND_ALIAS_ZONE, alias, zone.toString(), mustHave.toString());
+ }
+
+ // show commands
+
+ private void show(String showName, int turnNum, PhaseStep step, TestPlayer player, String command, String... params) {
+ String res = "show:" + command;
+ for (String param : params) {
+ res += "@" + param;
+ }
+ player.addAction(showName, turnNum, step, res);
+ }
+
+ public void showLibrary(String showName, int turnNum, PhaseStep step, TestPlayer player) {
+ show(showName, turnNum, step, player, SHOW_COMMAND_LIBRARY);
+ }
+
+ public void showHand(String showName, int turnNum, PhaseStep step, TestPlayer player) {
+ show(showName, turnNum, step, player, SHOW_COMMAND_HAND);
+ }
+
+ public void showBattlefield(String showName, int turnNum, PhaseStep step, TestPlayer player) {
+ show(showName, turnNum, step, player, SHOW_COMMAND_BATTLEFIELD);
+ }
+
+ public void showGraveyard(String showName, int turnNum, PhaseStep step, TestPlayer player) {
+ show(showName, turnNum, step, player, SHOW_COMMAND_GRAVEYEARD);
+ }
+
+ public void showExile(String showName, int turnNum, PhaseStep step, TestPlayer player) {
+ show(showName, turnNum, step, player, SHOW_COMMAND_EXILE);
+ }
+
+ public void showAvaileableAbilities(String showName, int turnNum, PhaseStep step, TestPlayer player) {
+ show(showName, turnNum, step, player, SHOW_COMMAND_AVAILABLE_ABILITIES);
+ }
+
+ public void showAliases(String showName, int turnNum, PhaseStep step, TestPlayer player) {
+ show(showName, turnNum, step, player, SHOW_COMMAND_ALIASES);
+ }
+
/**
* Removes all cards from player's library from the game. Usually this
* should be used once before initialization to form the library in certain
@@ -346,6 +424,19 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
@Override
public void addCard(Zone gameZone, TestPlayer player, String cardName, int count, boolean tapped) {
+ // aliases for mage objects
+ String aliasName = "";
+ boolean useAliasMultiNames = (count != 1);
+ if (cardName.contains("@")) {
+ aliasName = cardName.substring(cardName.indexOf("@") + 1);
+ cardName = cardName.substring(0, cardName.indexOf("@"));
+ }
+
+ // one card = one aliase, massive adds can use auto-name
+ if (!useAliasMultiNames && !aliasName.isEmpty() && player.getAliasByName(aliasName) != null) {
+ Assert.fail("Can't add card " + cardName + " - alias " + aliasName + " already exists for " + player.getName());
+ }
+
if (gameZone == Zone.BATTLEFIELD) {
for (int i = 0; i < count; i++) {
CardInfo cardInfo = CardRepository.instance.findCard(cardName);
@@ -356,6 +447,10 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
PermanentCard p = new PermanentCard(card.copy(), player.getId(), currentGame);
p.setTapped(tapped);
getBattlefieldCards(player).add(p);
+
+ if (!aliasName.isEmpty()) {
+ player.addAlias(player.generateAliasName(aliasName, useAliasMultiNames, i + 1), p.getId());
+ }
}
} else {
if (tapped) {
@@ -369,6 +464,10 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
throw new AssertionError("Couldn't find a card: " + cardName);
}
cards.add(card);
+
+ if (!aliasName.isEmpty()) {
+ player.addAlias(player.generateAliasName(aliasName, useAliasMultiNames, i + 1), card.getId());
+ }
}
}
}
@@ -403,7 +502,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
*/
@Override
public void setLife(TestPlayer player, int life) {
- getCommands(player).put(Zone.OUTSIDE, "life:" + String.valueOf(life));
+ getCommands(player).put(Zone.OUTSIDE, "life:" + life);
}
/**
@@ -505,6 +604,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
@Override
public void assertPowerToughness(Player player, String cardName, int power, int toughness, Filter.ComparisonScope scope)
throws AssertionError {
+ //Assert.assertNotEquals("", cardName);
int count = 0;
int fit = 0;
int foundPower = 0;
@@ -559,6 +659,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
@Override
public void assertAbilities(Player player, String cardName, List abilities)
throws AssertionError {
+ //Assert.assertNotEquals("", cardName);
int count = 0;
Permanent found = null;
for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents(player.getId())) {
@@ -594,6 +695,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @throws AssertionError
*/
public void assertAbility(Player player, String cardName, Ability ability, boolean mustHave, int count) throws AssertionError {
+ //Assert.assertNotEquals("", cardName);
int foundCount = 0;
Permanent found = null;
for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents(player.getId())) {
@@ -644,6 +746,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
*/
@Override
public void assertPermanentCount(Player player, String cardName, int count) throws AssertionError {
+ //Assert.assertNotEquals("", cardName);
int actualCount = 0;
for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents()) {
if (permanent.getControllerId().equals(player.getId())) {
@@ -657,6 +760,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
@Override
public void assertCommandZoneCount(Player player, String commandZoneObjectName, int count) throws AssertionError {
+ //Assert.assertNotEquals("", commandZoneObjectName);
int actualCount = 0;
for (CommandObject commandObject : currentGame.getState().getCommand()) {
if (commandObject.getControllerId().equals(player.getId()) && commandObject.getName().equals(commandZoneObjectName)) {
@@ -696,6 +800,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
}
public void assertCounterCount(Player player, String cardName, CounterType type, int count) throws AssertionError {
+ //Assert.assertNotEquals("", cardName);
Permanent found = null;
for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents()) {
if (permanent.getName().equals(cardName) && (player == null || permanent.getControllerId().equals(player.getId()))) {
@@ -715,11 +820,12 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param count Expected count.
*/
public void assertCounterOnExiledCardCount(String cardName, CounterType type, int count) throws AssertionError {
+ //Assert.assertNotEquals("", cardName);
Card found = null;
if (found == null) {
for (Card card : currentGame.getExile().getAllCards(currentGame)) {
- if (card.getName().equals(cardName)) {
+ if (CardUtil.haveSameNames(card.getName(), cardName, true)) {
found = card;
break;
}
@@ -749,6 +855,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param mustHave true if creature should have type, false if it should not
*/
public void assertType(String cardName, CardType type, boolean mustHave) throws AssertionError {
+ //Assert.assertNotEquals("", cardName);
Permanent found = null;
for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents()) {
if (permanent.getName().equals(cardName)) {
@@ -771,6 +878,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param subType a subtype to test for
*/
public void assertType(String cardName, CardType type, SubType subType) throws AssertionError {
+ //Assert.assertNotEquals("", cardName);
Permanent found = getPermanent(cardName);
Assert.assertTrue("(Battlefield) card type not found (" + cardName + ':' + type + ')', found.getCardType().contains(type));
if (subType != null) {
@@ -785,6 +893,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param type A type to test for
*/
public void assertNotType(String cardName, CardType type) throws AssertionError {
+ //Assert.assertNotEquals("", cardName);
Permanent found = getPermanent(cardName);
Assert.assertFalse("(Battlefield) card type found (" + cardName + ':' + type + ')', found.getCardType().contains(type));
}
@@ -796,6 +905,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param subType a subtype to test for
*/
public void assertNotSubtype(String cardName, SubType subType) throws AssertionError {
+ //Assert.assertNotEquals("", cardName);
Permanent found = getPermanent(cardName);
if (subType != null) {
Assert.assertFalse("(Battlefield) card sub-type equal (" + cardName + ':' + subType.getDescription() + ')', found.getSubtype(currentGame).contains(subType));
@@ -811,6 +921,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param mustHave must or not must have that colors
*/
public void assertColor(Player player, String cardName, ObjectColor searchColors, boolean mustHave) {
+ //Assert.assertNotEquals("", cardName);
Assert.assertNotEquals("must setup colors to search", 0, searchColors.getColorCount());
Permanent card = getPermanent(cardName, player);
@@ -845,6 +956,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param tapped Whether the permanent is tapped or not
*/
public void assertTapped(String cardName, boolean tapped) throws AssertionError {
+ //Assert.assertNotEquals("", cardName);
Permanent found = null;
for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents()) {
if (permanent.getName().equals(cardName)) {
@@ -870,6 +982,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param count The amount of this permanents that should be tapped
*/
public void assertTappedCount(String cardName, boolean tapped, int count) throws AssertionError {
+ //Assert.assertNotEquals("", cardName);
int tappedAmount = 0;
Permanent found = null;
for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents()) {
@@ -891,6 +1004,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param attacking Whether the permanent is attacking or not
*/
public void assertAttacking(String cardName, boolean attacking) throws AssertionError {
+ //Assert.assertNotEquals("", cardName);
Permanent found = null;
for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents()) {
if (permanent.getName().equals(cardName)) {
@@ -922,17 +1036,18 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param count Expected count.
*/
public void assertHandCount(Player player, String cardName, int count) throws AssertionError {
+ //Assert.assertNotEquals("", cardName);
int actual;
if (cardName.contains("//")) { // special logic for cheched split cards, because in game logic of card name filtering is different than for test
actual = 0;
for (Card card : currentGame.getPlayer(player.getId()).getHand().getCards(currentGame)) {
- if (card.getName().equals(cardName)) {
+ if (CardUtil.haveSameNames(card.getName(), cardName, true)) {
actual++;
}
}
} else {
FilterCard filter = new FilterCard();
- filter.add(new NamePredicate(cardName));
+ filter.add(new NamePredicate(cardName, true)); // must find any cards even without names
actual = currentGame.getPlayer(player.getId()).getHand().count(filter, player.getId(), currentGame);
}
Assert.assertEquals("(Hand) Card counts for card " + cardName + " for " + player.getName() + " are not equal ", count, actual);
@@ -981,10 +1096,11 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param count Expected count.
*/
public void assertExileCount(String cardName, int count) throws AssertionError {
+ //Assert.assertNotEquals("", cardName);
int actualCount = 0;
for (ExileZone exile : currentGame.getExile().getExileZones()) {
for (Card card : exile.getCards(currentGame)) {
- if (card.getName().equals(cardName)) {
+ if (CardUtil.haveSameNames(card.getName(), cardName, true)) {
actualCount++;
}
}
@@ -1020,6 +1136,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param count Expected count.
*/
public void assertExileCount(Player owner, String cardName, int count) throws AssertionError {
+ //Assert.assertNotEquals("", cardName);
int actualCount = 0;
for (ExileZone exile : currentGame.getExile().getExileZones()) {
for (Card card : exile.getCards(currentGame)) {
@@ -1039,9 +1156,10 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param count Expected count.
*/
public void assertGraveyardCount(Player player, String cardName, int count) throws AssertionError {
+ //Assert.assertNotEquals("", cardName);
int actualCount = 0;
for (Card card : player.getGraveyard().getCards(currentGame)) {
- if (card.getName().equals(cardName)) {
+ if (CardUtil.haveSameNames(card.getName(), cardName, true)) {
actualCount++;
}
}
@@ -1056,7 +1174,6 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param count Expected count.
*/
public void assertLibraryCount(Player player, int count) throws AssertionError {
-
List libraryList = player.getLibrary().getCards(currentGame);
int actualCount = libraryList != null && !libraryList.isEmpty() ? libraryList.size() : 0;
Assert.assertEquals("(Library " + player.getName() + ") counts are not equal", count, actualCount);
@@ -1070,9 +1187,10 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param count Expected count.
*/
public void assertLibraryCount(Player player, String cardName, int count) throws AssertionError {
+ //Assert.assertNotEquals("", cardName);
int actualCount = 0;
for (Card card : player.getLibrary().getCards(currentGame)) {
- if (card.getName().equals(cardName)) {
+ if (CardUtil.haveSameNames(card.getName(), cardName, true)) {
actualCount++;
}
}
@@ -1080,15 +1198,27 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
Assert.assertEquals("(Library " + player.getName() + ") Card counts are not equal (" + cardName + ')', count, actualCount);
}
- /**
- * Asserts added actions count. Useful to make sure that all actions were
- * executed.
- *
- * @param player
- * @param count
- */
- public void assertActionCount(TestPlayer player, int count) {
- Assert.assertEquals("Actions left are not equal: ", count, player.getActionCount());
+ public void assertActionsCount(TestPlayer player, int count) throws AssertionError {
+ Assert.assertEquals("(Actions of " + player.getName() + ") Count are not equel (founded ["
+ + player.getActions().stream().map(PlayerAction::getAction).collect(Collectors.joining(", "))
+ + "])", count, player.getActions().size());
+ }
+
+ public void assertChoicesCount(TestPlayer player, int count) throws AssertionError {
+ Assert.assertEquals("(Choices of " + player.getName() + ") Count are not equel (founded " + player.getChoices() + ")", count, player.getChoices().size());
+ }
+
+ public void assertTargetsCount(TestPlayer player, int count) throws AssertionError {
+ Assert.assertEquals("(Targets of " + player.getName() + ") Count are not equel (founded " + player.getTargets() + ")", count, player.getTargets().size());
+ }
+
+ public void assertAllCommandsUsed() throws AssertionError {
+ for (Player player : currentGame.getPlayers().values()) {
+ TestPlayer testPlayer = (TestPlayer) player;
+ assertActionsCount(testPlayer, 0);
+ assertChoicesCount(testPlayer, 0);
+ assertTargetsCount(testPlayer, 0);
+ }
}
public void assertActivePlayer(TestPlayer player) {
@@ -1129,18 +1259,22 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
}
public void playLand(int turnNum, PhaseStep step, TestPlayer player, String cardName) {
+ //Assert.assertNotEquals("", cardName);
player.addAction(turnNum, step, "activate:Play " + cardName);
}
public void castSpell(int turnNum, PhaseStep step, TestPlayer player, String cardName) {
+ //Assert.assertNotEquals("", cardName);
player.addAction(turnNum, step, "activate:Cast " + cardName);
}
public void castSpell(int turnNum, PhaseStep step, TestPlayer player, String cardName, Player target) {
+ //Assert.assertNotEquals("", cardName);
player.addAction(turnNum, step, "activate:Cast " + cardName + "$targetPlayer=" + target.getName());
}
public void castSpell(int turnNum, PhaseStep step, TestPlayer player, String cardName, Player target, int manaInPool) {
+ //Assert.assertNotEquals("", cardName);
player.addAction(turnNum, step, "activate:Cast " + cardName + "$targetPlayer=" + target.getName() + "$manaInPool=" + manaInPool);
}
@@ -1177,11 +1311,11 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* multiple targets can be seperated by ^
*/
public void castSpell(int turnNum, PhaseStep step, TestPlayer player, String cardName, String targetName) {
+ //Assert.assertNotEquals("", cardName);
player.addAction(turnNum, step, "activate:Cast " + cardName + "$target=" + targetName);
}
public enum StackClause {
-
WHILE_ON_STACK,
WHILE_COPY_ON_STACK,
WHILE_NOT_ON_STACK
@@ -1216,6 +1350,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param clause
*/
public void castSpell(int turnNum, PhaseStep step, TestPlayer player, String cardName, String targetName, String spellOnStack, StackClause clause) {
+ //Assert.assertNotEquals("", cardName);
if (StackClause.WHILE_ON_STACK == clause) {
player.addAction(turnNum, step, "activate:Cast " + cardName
+ '$' + (targetName != null && targetName.startsWith("target") ? targetName : "target=" + targetName)
@@ -1228,6 +1363,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
}
public void castSpell(int turnNum, PhaseStep step, TestPlayer player, String cardName, String targetName, String spellOnStack, String spellOnTopOfStack) {
+ //Assert.assertNotEquals("", cardName);
String action = "activate:Cast " + cardName + "$target=" + targetName;
if (spellOnStack != null && !spellOnStack.isEmpty()) {
action += "$spellOnStack=" + spellOnStack;
@@ -1243,18 +1379,22 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
}
public void activateAbility(int turnNum, PhaseStep step, TestPlayer player, String ability) {
+ // TODO: it's uses computerPlayer to execute, only ability target will work, but choices and targets commands aren't
player.addAction(turnNum, step, "activate:" + ability);
}
public void activateAbility(int turnNum, PhaseStep step, TestPlayer player, String ability, Player target) {
+ // TODO: it's uses computerPlayer to execute, only ability target will work, but choices and targets commands aren't
player.addAction(turnNum, step, "activate:" + ability + "$targetPlayer=" + target.getName());
}
public void activateAbility(int turnNum, PhaseStep step, TestPlayer player, String ability, String... targetNames) {
+ // TODO: it's uses computerPlayer to execute, only ability target will work, but choices and targets commands aren't
player.addAction(turnNum, step, "activate:" + ability + "$target=" + String.join("^", targetNames));
}
public void activateAbility(int turnNum, PhaseStep step, TestPlayer player, String ability, String targetName, String spellOnStack) {
+ // TODO: it's uses computerPlayer to execute, only ability target will work, but choices and targets commands aren't
this.activateAbility(turnNum, step, player, ability, targetName, spellOnStack, StackClause.WHILE_ON_STACK);
}
@@ -1292,22 +1432,28 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
}
public void addCounters(int turnNum, PhaseStep step, TestPlayer player, String cardName, CounterType type, int count) {
+ //Assert.assertNotEquals("", cardName);
player.addAction(turnNum, step, "addCounters:" + cardName + '$' + type.getName() + '$' + count);
}
public void attack(int turnNum, TestPlayer player, String attacker) {
+ //Assert.assertNotEquals("", attacker);
player.addAction(turnNum, PhaseStep.DECLARE_ATTACKERS, "attack:" + attacker);
}
public void attack(int turnNum, TestPlayer player, String attacker, TestPlayer defendingPlayer) {
+ //Assert.assertNotEquals("", attacker);
player.addAction(turnNum, PhaseStep.DECLARE_ATTACKERS, "attack:" + attacker + "$defendingPlayer=" + defendingPlayer.getName());
}
public void attack(int turnNum, TestPlayer player, String attacker, String planeswalker) {
+ //Assert.assertNotEquals("", attacker);
player.addAction(turnNum, PhaseStep.DECLARE_ATTACKERS, new StringBuilder("attack:").append(attacker).append("$planeswalker=").append(planeswalker).toString());
}
public void block(int turnNum, TestPlayer player, String blocker, String attacker) {
+ //Assert.assertNotEquals("", blocker);
+ //Assert.assertNotEquals("", attacker);
player.addAction(turnNum, PhaseStep.DECLARE_BLOCKERS, "block:" + blocker + '$' + attacker);
}
@@ -1401,6 +1547,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
}
public void assertDamageReceived(Player player, String cardName, int expected) {
+ //Assert.assertNotEquals("", cardName);
Permanent p = getPermanent(cardName, player.getId());
if (p != null) {
Assert.assertEquals("Wrong damage received: ", expected, p.getDamage());
diff --git a/Mage.Tests/src/test/java/org/mage/test/testapi/TestAliases.java b/Mage.Tests/src/test/java/org/mage/test/testapi/TestAliases.java
new file mode 100644
index 0000000000..13d6915f92
--- /dev/null
+++ b/Mage.Tests/src/test/java/org/mage/test/testapi/TestAliases.java
@@ -0,0 +1,128 @@
+package org.mage.test.testapi;
+
+import mage.constants.EmptyNames;
+import mage.constants.PhaseStep;
+import mage.constants.Zone;
+import mage.util.CardUtil;
+import org.junit.Assert;
+import org.junit.Test;
+import org.mage.test.serverside.base.CardTestPlayerBase;
+
+/**
+ * @author JayDi85
+ */
+
+public class TestAliases extends CardTestPlayerBase {
+
+ @Test
+ public void test_NamesEquals() {
+ // empty names for face down cards
+ Assert.assertTrue(CardUtil.haveEmptyName(""));
+ Assert.assertTrue(CardUtil.haveEmptyName(EmptyNames.FACE_DOWN_CREATURE.toString()));
+ Assert.assertFalse(CardUtil.haveEmptyName(" "));
+ Assert.assertFalse(CardUtil.haveEmptyName("123"));
+ Assert.assertFalse(CardUtil.haveEmptyName("Sample Name"));
+
+ // same names (empty names can't be same)
+ Assert.assertFalse(CardUtil.haveSameNames("", ""));
+ Assert.assertFalse(CardUtil.haveSameNames(EmptyNames.FACE_DOWN_CREATURE.toString(), ""));
+ Assert.assertFalse(CardUtil.haveSameNames(EmptyNames.FACE_DOWN_CREATURE.toString(), EmptyNames.FACE_DOWN_CREATURE.toString()));
+ Assert.assertFalse(CardUtil.haveSameNames(EmptyNames.FACE_DOWN_TOKEN.toString(), ""));
+ Assert.assertFalse(CardUtil.haveSameNames(EmptyNames.FACE_DOWN_TOKEN.toString(), EmptyNames.FACE_DOWN_CREATURE.toString()));
+ Assert.assertTrue(CardUtil.haveSameNames("Name", "Name"));
+ Assert.assertFalse(CardUtil.haveSameNames("Name", ""));
+ Assert.assertFalse(CardUtil.haveSameNames("Name", " "));
+ Assert.assertFalse(CardUtil.haveSameNames("Name", "123"));
+ Assert.assertFalse(CardUtil.haveSameNames("Name", EmptyNames.FACE_DOWN_CREATURE.toString()));
+ Assert.assertFalse(CardUtil.haveSameNames("Name1", "Name2"));
+
+ // ignore mtg rules (empty names must be same)
+ Assert.assertTrue(CardUtil.haveSameNames("", "", true));
+ Assert.assertTrue(CardUtil.haveSameNames(EmptyNames.FACE_DOWN_CREATURE.toString(), EmptyNames.FACE_DOWN_CREATURE.toString(), true));
+ Assert.assertTrue(CardUtil.haveSameNames("Name", "Name", true));
+ Assert.assertFalse(CardUtil.haveSameNames("Name", "", true));
+ Assert.assertFalse(CardUtil.haveSameNames("Name", " ", true));
+ Assert.assertFalse(CardUtil.haveSameNames("Name", "123", true));
+ Assert.assertFalse(CardUtil.haveSameNames("Name", EmptyNames.FACE_DOWN_CREATURE.toString(), true));
+ Assert.assertFalse(CardUtil.haveSameNames("Name1", "Name2", true));
+ }
+
+ @Test
+ public void test_DifferentZones() {
+ addCard(Zone.LIBRARY, playerA, "Swamp@lib", 1);
+ addCard(Zone.HAND, playerA, "Swamp@hand", 1);
+ addCard(Zone.BATTLEFIELD, playerA, "Swamp@battle", 1);
+ addCard(Zone.GRAVEYARD, playerA, "Swamp@grave", 1);
+
+ showAliases("A aliases", 1, PhaseStep.UPKEEP, playerA);
+ checkAliasZone("lib", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "lib", Zone.LIBRARY);
+ checkAliasZone("hand", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "hand", Zone.HAND);
+ checkAliasZone("battle", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "battle", Zone.BATTLEFIELD);
+ checkAliasZone("grave", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "grave", Zone.GRAVEYARD);
+
+ setStopAt(1, PhaseStep.END_TURN);
+ execute();
+ assertAllCommandsUsed();
+ }
+
+ @Test
+ public void test_MultipleNames() {
+ addCard(Zone.BATTLEFIELD, playerA, "Swamp", 5);
+ addCard(Zone.BATTLEFIELD, playerA, "Island@isl", 5);
+ addCard(Zone.BATTLEFIELD, playerB, "Plains", 5);
+ addCard(Zone.BATTLEFIELD, playerB, "Mountain@mnt", 5);
+
+ checkPermanentCount("Swamp must exists", 1, PhaseStep.UPKEEP, playerA, "Swamp", 5);
+ checkPermanentCount("Island must exists", 1, PhaseStep.UPKEEP, playerA, "Island", 5);
+ checkPermanentCount("Plains must exists", 1, PhaseStep.UPKEEP, playerB, "Plains", 5);
+ checkPermanentCount("Mountain must exists", 1, PhaseStep.UPKEEP, playerB, "Mountain", 5);
+ //
+ showAliases("A aliases", 1, PhaseStep.UPKEEP, playerA);
+ showAliases("B aliases", 1, PhaseStep.UPKEEP, playerB);
+ // A
+ checkAliasZone("Swamp must not", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Swamp", Zone.BATTLEFIELD, false);
+ checkAliasZone("Swamp.1 must not", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Swamp.1", Zone.BATTLEFIELD, false);
+ checkAliasZone("Island must not", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Island", Zone.BATTLEFIELD, false);
+ checkAliasZone("isl must not", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "isl", Zone.BATTLEFIELD, false);
+ checkAliasZone("isl.1 must", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "isl.1", Zone.BATTLEFIELD, true);
+ checkAliasZone("isl.2 must", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "isl.2", Zone.BATTLEFIELD, true);
+ checkAliasZone("isl.5 must", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "isl.5", Zone.BATTLEFIELD, true);
+ // B
+ checkAliasZone("Plains must not", 1, PhaseStep.PRECOMBAT_MAIN, playerB, "Plains", Zone.BATTLEFIELD, false);
+ checkAliasZone("Plains.1 must not", 1, PhaseStep.PRECOMBAT_MAIN, playerB, "Plains.1", Zone.BATTLEFIELD, false);
+ checkAliasZone("Plains must not", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Plains", Zone.BATTLEFIELD, false);
+ checkAliasZone("mnt must not", 1, PhaseStep.PRECOMBAT_MAIN, playerB, "mnt", Zone.BATTLEFIELD, false);
+ checkAliasZone("mnt.1 must", 1, PhaseStep.PRECOMBAT_MAIN, playerB, "mnt.1", Zone.BATTLEFIELD, true);
+ checkAliasZone("mnt.2 must", 1, PhaseStep.PRECOMBAT_MAIN, playerB, "mnt.2", Zone.BATTLEFIELD, true);
+ checkAliasZone("mnt.5 must", 1, PhaseStep.PRECOMBAT_MAIN, playerB, "mnt.5", Zone.BATTLEFIELD, true);
+
+ setStopAt(1, PhaseStep.END_TURN);
+ execute();
+ assertAllCommandsUsed();
+ }
+
+ @Test
+ public void test_CastTarget() {
+ addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion@lion", 5);
+ addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5);
+ addCard(Zone.HAND, playerA, "Lightning Bolt", 3);
+
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "@lion.1");
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "@lion.3");
+ castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "@lion.5");
+
+ showAliases("A aliases", 1, PhaseStep.POSTCOMBAT_MAIN, playerA);
+ checkAliasZone("1", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "lion.1", Zone.BATTLEFIELD, false);
+ checkAliasZone("2", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "lion.2", Zone.BATTLEFIELD, true);
+ checkAliasZone("3", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "lion.3", Zone.BATTLEFIELD, false);
+ checkAliasZone("4", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "lion.4", Zone.BATTLEFIELD, true);
+ checkAliasZone("5", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "lion.5", Zone.BATTLEFIELD, false);
+
+ setStopAt(1, PhaseStep.END_TURN);
+ execute();
+ assertAllCommandsUsed();
+
+ assertGraveyardCount(playerA, "Lightning Bolt", 3);
+ assertGraveyardCount(playerA, "Silvercoat Lion", 3);
+ }
+}
\ No newline at end of file
diff --git a/Mage.Verify/src/main/java/mage/verify/Booster.java b/Mage.Verify/src/main/java/mage/verify/Booster.java
deleted file mode 100644
index 161dcfff1d..0000000000
--- a/Mage.Verify/src/main/java/mage/verify/Booster.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package mage.verify;
-
-public class Booster {
-
- public Booster(String mythic){
-
- }
-}
diff --git a/Mage.Verify/src/main/java/mage/verify/JsonCard.java b/Mage.Verify/src/main/java/mage/verify/JsonCard.java
index ef857d8d75..aa9f28c650 100644
--- a/Mage.Verify/src/main/java/mage/verify/JsonCard.java
+++ b/Mage.Verify/src/main/java/mage/verify/JsonCard.java
@@ -3,59 +3,48 @@ package mage.verify;
import java.util.List;
class JsonCard {
+ // docs: https://mtgjson.com/v4/docs.html
- public String uuid;
- public String convertedManaCost;
- public List foreignData;
- public boolean isReserved;
- public String side;
- public Legality legalities;
- public List printings;
- public List rulings;
+ public String artist;
+ public String borderColor;
+ public List colorIdentity;
public List colorIndicator;
- public String layout;
- public String name;
- public List names; // flip cards
- public String manaCost;
+ public List colors;
+ public float convertedManaCost;
+ public float faceConvertedManaCost;
+ public String flavorText;
+ public List foreignData;
+ public String frameVersion;
public boolean hasFoil;
public boolean hasNonFoil;
- public String multiverseId;
- public String frameVersion;
- public int cmc;
- public List colors;
- public List colorIdentity;
- public String type;
- public List supertypes;
- public List types;
- public List subtypes;
- public String text;
- public String power;
- public String toughness;
+ public boolean isOnlineOnly;
+ public boolean isOversized;
+ public boolean isReserved;
+ public boolean isTimeshifted;
+ public String layout;
+ public JsonLegalities legalities;
public String loyalty;
- public String imageName;
- public boolean starter; // only available in boxed sets and not in boosters
- public int hand; // vanguard
- public int life; // vanguard
+ public String manaCost;
+ public int multiverseId;
+ public String name;
+ public List names;
+ public String number;
public String originalText;
public String originalType;
- public String flavorText;
- public boolean isOnlineOnly;
-
- // only available in AllSets.json
- public String artist;
- public String flavor;
- public String id;
- public int multiverseid;
+ public List printings;
+ public String power;
public String rarity;
- public boolean reserved;
- public int[] variations;
- public String number;
- public String mciNumber;
- public String releaseDate; // promos
- public String border;
+ public boolean starter;
+ public String side;
+ public List rulings;
+ public List subtypes;
+ public List supertypes;
+ public String text;
+ public String toughness;
+ public String type;
+ public List types;
+ public String uuid;
+ public List variations;
public String watermark;
- public boolean timeshifted;
- public String borderColor;
- public boolean isOversized;
- public String faceConvertedManaCost;
+ public String tcgplayerProductId;
}
diff --git a/Mage.Verify/src/main/java/mage/verify/ForeignData.java b/Mage.Verify/src/main/java/mage/verify/JsonForeignData.java
similarity index 71%
rename from Mage.Verify/src/main/java/mage/verify/ForeignData.java
rename to Mage.Verify/src/main/java/mage/verify/JsonForeignData.java
index e410fb24d7..c6ca9353e4 100644
--- a/Mage.Verify/src/main/java/mage/verify/ForeignData.java
+++ b/Mage.Verify/src/main/java/mage/verify/JsonForeignData.java
@@ -1,12 +1,10 @@
package mage.verify;
-public class ForeignData {
-
-
- public String language;
- public String name;
- public String type;
- public String text;
+public class JsonForeignData {
public String flavorText;
- public String multiverseId;
+ public String language;
+ public int multiverseId;
+ public String name;
+ public String text;
+ public String type;
}
diff --git a/Mage.Verify/src/main/java/mage/verify/Legality.java b/Mage.Verify/src/main/java/mage/verify/JsonLegalities.java
similarity index 58%
rename from Mage.Verify/src/main/java/mage/verify/Legality.java
rename to Mage.Verify/src/main/java/mage/verify/JsonLegalities.java
index 925bc2189e..064838754e 100644
--- a/Mage.Verify/src/main/java/mage/verify/Legality.java
+++ b/Mage.Verify/src/main/java/mage/verify/JsonLegalities.java
@@ -2,18 +2,18 @@ package mage.verify;
import com.fasterxml.jackson.annotation.JsonProperty;
-public class Legality {
+public class JsonLegalities {
@JsonProperty("1v1")
public String oneVersusOne;
+ public String brawl;
public String commander;
public String duel;
+ public String frontier;
+ public String future;
public String legacy;
+ public String modern;
public String penny;
+ public String pauper;
+ public String standard;
public String vintage;
-public String frontier;
-public String modern;
-public String pauper;
-public String brawl;
-public String future;
-public String standard;
}
diff --git a/Mage.Verify/src/main/java/mage/verify/Meta.java b/Mage.Verify/src/main/java/mage/verify/JsonMeta.java
similarity index 75%
rename from Mage.Verify/src/main/java/mage/verify/Meta.java
rename to Mage.Verify/src/main/java/mage/verify/JsonMeta.java
index 4a93171da0..4d68703479 100644
--- a/Mage.Verify/src/main/java/mage/verify/Meta.java
+++ b/Mage.Verify/src/main/java/mage/verify/JsonMeta.java
@@ -1,6 +1,6 @@
package mage.verify;
-public class Meta {
+public class JsonMeta {
public String date;
public String version;
}
diff --git a/Mage.Verify/src/main/java/mage/verify/Ruling.java b/Mage.Verify/src/main/java/mage/verify/JsonRuling.java
similarity index 73%
rename from Mage.Verify/src/main/java/mage/verify/Ruling.java
rename to Mage.Verify/src/main/java/mage/verify/JsonRuling.java
index 5bcb036329..1576700d58 100644
--- a/Mage.Verify/src/main/java/mage/verify/Ruling.java
+++ b/Mage.Verify/src/main/java/mage/verify/JsonRuling.java
@@ -1,6 +1,6 @@
package mage.verify;
-public class Ruling {
- public String text;
+public class JsonRuling {
public String date;
+ public String text;
}
diff --git a/Mage.Verify/src/main/java/mage/verify/JsonSet.java b/Mage.Verify/src/main/java/mage/verify/JsonSet.java
index 466ebbfb63..614d73123d 100644
--- a/Mage.Verify/src/main/java/mage/verify/JsonSet.java
+++ b/Mage.Verify/src/main/java/mage/verify/JsonSet.java
@@ -1,36 +1,21 @@
package mage.verify;
-import com.fasterxml.jackson.annotation.JsonIgnore;
-
import java.util.List;
-import java.util.Map;
class JsonSet {
- public String name;
- public String code;
- public String oldCode;
- public String gathererCode;
- public String magicCardsInfoCode;
- public String[] magicRaritiesCodes;
- public String[] alternativeNames;
- public String releaseDate;
- public String border;
- public String type;
- public List