mirror of
https://github.com/magefree/mage.git
synced 2025-12-23 03:51:58 -08:00
- Reworked SourceOnBattlefieldControlUnchangedCondition checking now the LOST_CONTROL event which solves the problem with the old code to not be able to detect all controller changes of layered changeController effects when applied later.
- Simplified and fixed some problems of the handling of the "Until end of your next turn" duration.
- Fixed that some continous effects changed controller but shouldn't dependant from their duration type. Controller chnage will now done duration type dependant.
(that change fixes #6581 in a more general way undoing the effect specific changes of 2e8ece1dbd).
This commit is contained in:
parent
25802dc105
commit
1e36b39434
30 changed files with 534 additions and 469 deletions
|
|
@ -1,81 +1,120 @@
|
|||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.mage.test.cards.abilities.keywords;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import mage.constants.MultiplayerAttackOption;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.RangeOfInfluence;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.FreeForAll;
|
||||
import mage.game.Game;
|
||||
import mage.game.GameException;
|
||||
import mage.game.mulligan.MulliganType;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestMultiPlayerBase;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class GoadTest extends CardTestMultiPlayerBase {
|
||||
|
||||
@Override
|
||||
protected Game createNewGameAndPlayers() throws GameException, FileNotFoundException {
|
||||
Game game = new FreeForAll(MultiplayerAttackOption.MULTIPLE, RangeOfInfluence.ALL, MulliganType.GAME_DEFAULT.getMulligan(0), 40);
|
||||
// Player order: A -> D -> C -> B
|
||||
playerA = createPlayer(game, playerA, "PlayerA");
|
||||
playerB = createPlayer(game, playerB, "PlayerB");
|
||||
playerC = createPlayer(game, playerC, "PlayerC");
|
||||
playerD = createPlayer(game, playerD, "PlayerD");
|
||||
return game;
|
||||
}
|
||||
|
||||
/**
|
||||
* In a game of commander, my opponent gained control of Marisi, Breaker of
|
||||
* Coils (until end of turn) and did combat damage to another player. This
|
||||
* caused the creatures damaged by Marisi's controller to be goaded.
|
||||
* However, when the goaded creatures went to attack, they could not attack
|
||||
* me but could attack the (former) controller of Marisi.
|
||||
*/
|
||||
@Test
|
||||
public void goadWithNotOwnedCreatureTest() {
|
||||
// Your opponents can't cast spells during combat.
|
||||
// Whenever a creature you control deals combat damage to a player, goad each creature that player controls
|
||||
// (Until your next turn, that creature attacks each combat if able and attacks a player other than you if able.)
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Marisi, Breaker of the Coil", 1); // Creature 5/4
|
||||
|
||||
// Untap target creature an opponent controls and gain control of it until end of turn.
|
||||
// That creature gains haste until end of turn.
|
||||
// When you lose control of the creature, tap it.
|
||||
addCard(Zone.HAND, playerD, "Ray of Command"); // Instant {3}{U}
|
||||
addCard(Zone.BATTLEFIELD, playerD, "Island", 4);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerC, "Silvercoat Lion", 3); // Creature 2/2
|
||||
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerD, "Ray of Command", "Marisi, Breaker of the Coil");
|
||||
|
||||
attack(2, playerD, "Marisi, Breaker of the Coil", playerC);
|
||||
|
||||
attack(3, playerC, "Silvercoat Lion", playerA);
|
||||
attack(3, playerC, "Silvercoat Lion", playerB);
|
||||
attack(3, playerC, "Silvercoat Lion", playerD);
|
||||
|
||||
setStopAt(4, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
|
||||
assertGraveyardCount(playerD, "Ray of Command", 1);
|
||||
assertPermanentCount(playerA, "Marisi, Breaker of the Coil", 1);
|
||||
|
||||
assertLife(playerC, 35);
|
||||
|
||||
assertLife(playerB, 38);
|
||||
assertLife(playerA, 38);
|
||||
assertLife(playerD, 38);
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.mage.test.cards.abilities.keywords;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import mage.constants.MultiplayerAttackOption;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.RangeOfInfluence;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.FreeForAll;
|
||||
import mage.game.Game;
|
||||
import mage.game.GameException;
|
||||
import mage.game.mulligan.MulliganType;
|
||||
import mage.game.permanent.Permanent;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestMultiPlayerBase;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class GoadTest extends CardTestMultiPlayerBase {
|
||||
|
||||
@Override
|
||||
protected Game createNewGameAndPlayers() throws GameException, FileNotFoundException {
|
||||
Game game = new FreeForAll(MultiplayerAttackOption.MULTIPLE, RangeOfInfluence.ALL, MulliganType.GAME_DEFAULT.getMulligan(0), 40);
|
||||
// Player order: A -> D -> C -> B
|
||||
playerA = createPlayer(game, playerA, "PlayerA");
|
||||
playerB = createPlayer(game, playerB, "PlayerB");
|
||||
playerC = createPlayer(game, playerC, "PlayerC");
|
||||
playerD = createPlayer(game, playerD, "PlayerD");
|
||||
return game;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void goadWithOwnedCreatureTest() {
|
||||
// Your opponents can't cast spells during combat.
|
||||
// Whenever a creature you control deals combat damage to a player, goad each creature that player controls
|
||||
// (Until your next turn, that creature attacks each combat if able and attacks a player other than you if able.)
|
||||
addCard(Zone.BATTLEFIELD, playerD, "Marisi, Breaker of the Coil", 1); // Creature 5/4
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerC, "Abbey Griffin", 3); // Creature 2/2
|
||||
|
||||
attack(2, playerD, "Marisi, Breaker of the Coil", playerC);
|
||||
|
||||
setStopAt(3, PhaseStep.BEGIN_COMBAT);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
Permanent griffinPermanent = getPermanent("Abbey Griffin");
|
||||
|
||||
Assert.assertFalse("Griffin can attack playerD but should not be able",
|
||||
griffinPermanent.canAttack(playerD.getId(), currentGame));
|
||||
Assert.assertTrue("Griffin can't attack playerA but should be able",
|
||||
griffinPermanent.canAttack(playerA.getId(), currentGame));
|
||||
Assert.assertTrue("Griffin can't attack playerB but should be able",
|
||||
griffinPermanent.canAttack(playerB.getId(), currentGame));
|
||||
|
||||
assertLife(playerC, 35);
|
||||
assertLife(playerD, 40); // player D can not be attacked from C because the creatures are goaded
|
||||
assertLife(playerA, 40);
|
||||
assertLife(playerB, 40);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* In a game of commander, my opponent gained control of Marisi, Breaker of
|
||||
* Coils (until end of turn) and did combat damage to another player. This
|
||||
* caused the creatures damaged by Marisi's controller to be goaded.
|
||||
* However, when the goaded creatures went to attack, they could not attack
|
||||
* me but could attack the (former) controller of Marisi.
|
||||
*/
|
||||
@Test
|
||||
public void goadWithNotOwnedCreatureTest() {
|
||||
// Your opponents can't cast spells during combat.
|
||||
// Whenever a creature you control deals combat damage to a player, goad each creature that player controls
|
||||
// (Until your next turn, that creature attacks each combat if able and attacks a player other than you if able.)
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Marisi, Breaker of the Coil", 1); // Creature 5/4
|
||||
|
||||
// Untap target creature an opponent controls and gain control of it until end of turn.
|
||||
// That creature gains haste until end of turn.
|
||||
// When you lose control of the creature, tap it.
|
||||
addCard(Zone.HAND, playerD, "Ray of Command"); // Instant {3}{U}
|
||||
addCard(Zone.BATTLEFIELD, playerD, "Island", 4);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerC, "Silvercoat Lion", 1); // Creature 2/2
|
||||
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerD, "Ray of Command", "Marisi, Breaker of the Coil");
|
||||
|
||||
attack(2, playerD, "Marisi, Breaker of the Coil", playerC);
|
||||
|
||||
setStopAt(3, PhaseStep.BEGIN_COMBAT);
|
||||
setStrictChooseMode(true);
|
||||
execute();
|
||||
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertGraveyardCount(playerD, "Ray of Command", 1);
|
||||
assertPermanentCount(playerA, "Marisi, Breaker of the Coil", 1);
|
||||
|
||||
Permanent lion = getPermanent("Silvercoat Lion", playerC);
|
||||
|
||||
Assert.assertFalse("Silvercoat lion shouldn't be able to attack player D but can", lion.canAttack(playerD.getId(), currentGame));
|
||||
Assert.assertTrue("Silvercoat lion should be able to attack player A but can't", lion.canAttack(playerA.getId(), currentGame));
|
||||
Assert.assertTrue("Silvercoat lion should be able to attack player B but can't", lion.canAttack(playerB.getId(), currentGame));
|
||||
|
||||
assertLife(playerD, 40);
|
||||
assertLife(playerC, 35);
|
||||
assertLife(playerA, 40);
|
||||
assertLife(playerB, 40);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,11 +22,11 @@ public class TheWretchedTest extends CardTestPlayerBase {
|
|||
addCard(Zone.BATTLEFIELD, playerA, "The Wretched");
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Wall of Pine Needles"); // a 3/3 with regeneration
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Living Wall"); // 0/6 Wall with regeneration
|
||||
|
||||
|
||||
attack(3, playerA, "The Wretched");
|
||||
block(3, playerB, "Wall of Pine Needles", "The Wretched");
|
||||
block(3, playerB, "Living Wall", "The Wretched");
|
||||
setStopAt(3, PhaseStep.POSTCOMBAT_MAIN);
|
||||
setStopAt(3, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, "The Wretched", 1);
|
||||
|
|
@ -39,17 +39,17 @@ public class TheWretchedTest extends CardTestPlayerBase {
|
|||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "The Wretched");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Bad Moon"); // +1/+1 for black creatures
|
||||
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Forest"); // a 3/3 with regeneration
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Wall of Pine Needles"); // a 3/3 with regeneration
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Living Wall"); // 0/6 Wall with regeneration
|
||||
|
||||
|
||||
// The Wretched
|
||||
// Creature — Demon - Demon 2/5
|
||||
attack(3, playerA, "The Wretched");
|
||||
block(3, playerB, "Wall of Pine Needles", "The Wretched");
|
||||
block(3, playerB, "Living Wall", "The Wretched");
|
||||
|
||||
|
||||
activateAbility(3, PhaseStep.DECLARE_BLOCKERS, playerB, "{G}: Regenerate {this}."); // Wall of Pine Needles
|
||||
|
||||
setStopAt(3, PhaseStep.POSTCOMBAT_MAIN);
|
||||
|
|
@ -57,53 +57,52 @@ public class TheWretchedTest extends CardTestPlayerBase {
|
|||
|
||||
assertPermanentCount(playerA, "The Wretched", 1);
|
||||
assertPermanentCount(playerA, "Living Wall", 1);
|
||||
|
||||
|
||||
assertPermanentCount(playerB, "Wall of Pine Needles", 1);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testLoseControlOfTheWretched() {
|
||||
|
||||
// At end of combat, gain control of all creatures blocking The Wretched for as long as you control The Wretched.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "The Wretched");
|
||||
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Wall of Pine Needles"); // a 3/3 with regeneration
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Living Wall"); // 0/6 Wall with regeneration
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Island", 4);
|
||||
addCard(Zone.HAND, playerB, "Control Magic");
|
||||
|
||||
|
||||
attack(3, playerA, "The Wretched");
|
||||
block(3, playerB, "Wall of Pine Needles", "The Wretched");
|
||||
block(3, playerB, "Living Wall", "The Wretched");
|
||||
|
||||
|
||||
castSpell(4, PhaseStep.POSTCOMBAT_MAIN, playerB, "Control Magic", "The Wretched");
|
||||
|
||||
setStopAt(4, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerB, "The Wretched", 1);
|
||||
assertPermanentCount(playerA, "Wall of Pine Needles", 0);
|
||||
assertPermanentCount(playerB, "Wall of Pine Needles", 1);
|
||||
assertPermanentCount(playerB, "Living Wall", 1);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRegenTheWretchedThusRemovingFromCombat() {
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "The Wretched");
|
||||
addCard(Zone.HAND, playerA, "Regenerate");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
|
||||
|
||||
addCard(Zone.HAND, playerA, "Regenerate");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Wall of Pine Needles"); // a 3/3 with regeneration
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Wall of Spears"); // 3/2
|
||||
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Wall of Spears"); // 3/2
|
||||
|
||||
attack(3, playerA, "The Wretched");
|
||||
block(3, playerB, "Wall of Pine Needles", "The Wretched");
|
||||
block(3, playerB, "Wall of Spears", "The Wretched");
|
||||
|
||||
|
||||
castSpell(3, PhaseStep.DECLARE_BLOCKERS, playerA, "Regenerate", "The Wretched");
|
||||
|
||||
|
||||
setStopAt(3, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
package org.mage.test.cards.copy;
|
||||
|
||||
import mage.abilities.keyword.DeathtouchAbility;
|
||||
import mage.constants.SubType;
|
||||
import mage.abilities.keyword.FlyingAbility;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.permanent.Permanent;
|
||||
import org.junit.Assert;
|
||||
|
|
@ -14,12 +14,11 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
|
|||
*
|
||||
* Lazav, Dimir Mastermind
|
||||
*
|
||||
* Legendary Creature — Shapeshifter 3/3, UUBB
|
||||
* Hexproof
|
||||
* Whenever a creature card is put into an opponent's graveyard from anywhere, you may have
|
||||
* Lazav, Dimir Mastermind become a copy of that card except its name is still
|
||||
* Lazav, Dimir Mastermind, it's legendary in addition to its other types, and
|
||||
* it gains hexproof and this ability.
|
||||
* Legendary Creature — Shapeshifter 3/3, UUBB Hexproof Whenever a creature card
|
||||
* is put into an opponent's graveyard from anywhere, you may have Lazav, Dimir
|
||||
* Mastermind become a copy of that card except its name is still Lazav, Dimir
|
||||
* Mastermind, it's legendary in addition to its other types, and it gains
|
||||
* hexproof and this ability.
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
|
@ -32,25 +31,26 @@ public class LazavDimirMastermindTest extends CardTestPlayerBase {
|
|||
public void testCopySimpleCreature() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Lazav, Dimir Mastermind", 1);
|
||||
// Codex Shredder - Artifact
|
||||
// {T}: Target player mills a card.
|
||||
// {T}: Target player puts the top card of their library into their graveyard.
|
||||
// {5}, {T}, Sacrifice Codex Shredder: Return target card from your graveyard to your hand.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Codex Shredder", 1);
|
||||
|
||||
// Flying 3/2
|
||||
addCard(Zone.LIBRARY, playerB, "Assault Griffin",5);
|
||||
addCard(Zone.LIBRARY, playerB, "Assault Griffin", 5);
|
||||
skipInitShuffling();
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Target player mills a card.", playerB);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Target player puts the top card", playerB);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPermanentCount(playerA, "Lazav, Dimir Mastermind", 1);
|
||||
assertPowerToughness(playerA, "Lazav, Dimir Mastermind", 3, 2);
|
||||
|
||||
Permanent lazav = getPermanent("Lazav, Dimir Mastermind", playerA.getId());
|
||||
Assert.assertTrue(lazav.getSubtype(currentGame).contains(SubType.GRIFFIN));
|
||||
Assert.assertTrue("Lazav, Dimir Mastermind must have flying",lazav.getAbilities().contains(FlyingAbility.getInstance()));
|
||||
Assert.assertTrue("Lazav, Dimir Mastermind must have flying", lazav.getAbilities().contains(FlyingAbility.getInstance()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -64,10 +64,10 @@ public class LazavDimirMastermindTest extends CardTestPlayerBase {
|
|||
|
||||
// Whenever another nontoken creature dies, you may put a 1/1 black Rat creature token onto the battlefield.
|
||||
// Rats you control have deathtouch.
|
||||
addCard(Zone.LIBRARY, playerB, "Ogre Slumlord",5);
|
||||
addCard(Zone.LIBRARY, playerB, "Ogre Slumlord", 5);
|
||||
skipInitShuffling();
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Target player mills a card.", playerB);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Target player puts the top card", playerB);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
|
@ -86,11 +86,10 @@ public class LazavDimirMastermindTest extends CardTestPlayerBase {
|
|||
/**
|
||||
* Tests copy Nightveil Specter
|
||||
*
|
||||
* Nightveil Specter
|
||||
* Creature — Specter 2/3, {U/B}{U/B}{U/B}
|
||||
* Flying
|
||||
* Whenever Nightveil Specter deals combat damage to a player, that player exiles the top card of their library.
|
||||
* You may play cards exiled with Nightveil Specter.
|
||||
* Nightveil Specter Creature — Specter 2/3, {U/B}{U/B}{U/B} Flying Whenever
|
||||
* Nightveil Specter deals combat damage to a player, that player exiles the
|
||||
* top card of their library. You may play cards exiled with Nightveil
|
||||
* Specter.
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
|
|
@ -99,11 +98,11 @@ public class LazavDimirMastermindTest extends CardTestPlayerBase {
|
|||
addCard(Zone.BATTLEFIELD, playerA, "Lazav, Dimir Mastermind", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Codex Shredder", 1);
|
||||
|
||||
addCard(Zone.LIBRARY, playerB, "Silvercoat Lion",2);
|
||||
addCard(Zone.LIBRARY, playerB, "Nightveil Specter",1);
|
||||
addCard(Zone.LIBRARY, playerB, "Silvercoat Lion", 2);
|
||||
addCard(Zone.LIBRARY, playerB, "Nightveil Specter", 1);
|
||||
skipInitShuffling();
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Target player mills a card.", playerB);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Target player puts the top card", playerB);
|
||||
|
||||
attack(3, playerA, "Lazav, Dimir Mastermind");
|
||||
|
||||
|
|
@ -130,15 +129,15 @@ public class LazavDimirMastermindTest extends CardTestPlayerBase {
|
|||
addCard(Zone.BATTLEFIELD, playerA, "Lazav, Dimir Mastermind", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Codex Shredder", 1);
|
||||
|
||||
addCard(Zone.LIBRARY, playerB, "Silvercoat Lion",2);
|
||||
addCard(Zone.LIBRARY, playerB, "Nightveil Specter",1);
|
||||
addCard(Zone.LIBRARY, playerB, "Silvercoat Lion", 2);
|
||||
addCard(Zone.LIBRARY, playerB, "Nightveil Specter", 1);
|
||||
skipInitShuffling();
|
||||
|
||||
// Lazav becomes a Nightveil Specter
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Target player mills a card.", playerB);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Target player puts the top card", playerB);
|
||||
|
||||
// Lazav becomes a Silvercoat Lion
|
||||
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Target player mills a card.", playerB);
|
||||
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Target player puts the top card", playerB);
|
||||
|
||||
setStopAt(3, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
|
@ -151,52 +150,52 @@ public class LazavDimirMastermindTest extends CardTestPlayerBase {
|
|||
Assert.assertTrue(lazav.isLegendary());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests old copy is discarded after reanmiation of Lazav
|
||||
*/
|
||||
@Test
|
||||
public void testCopyAfterReanimation() {
|
||||
addCard(Zone.BATTLEFIELD, playerA ,"Swamp");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp");
|
||||
// Put target creature card from a graveyard onto the battlefield under your control. You lose life equal to its converted mana cost.
|
||||
addCard(Zone.HAND, playerA ,"Reanimate");
|
||||
addCard(Zone.HAND, playerA, "Reanimate");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Lazav, Dimir Mastermind", 1);
|
||||
// Codex Shredder - Artifact
|
||||
// {T}: Target player mills a card.
|
||||
// {T}: Target player puts the top card of their library into their graveyard.
|
||||
// {5}, {T}, Sacrifice Codex Shredder: Return target card from your graveyard to your hand.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Codex Shredder", 1);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerB ,"Swamp", 3);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 3);
|
||||
// Flying 3/2
|
||||
addCard(Zone.LIBRARY, playerB, "Assault Griffin",1);
|
||||
addCard(Zone.LIBRARY, playerB, "Assault Griffin", 1);
|
||||
// Target opponent sacrifices a creature. You gain life equal to that creature's toughness.
|
||||
addCard(Zone.HAND, playerB ,"Tribute to Hunger");
|
||||
|
||||
addCard(Zone.HAND, playerB, "Tribute to Hunger");
|
||||
|
||||
skipInitShuffling();
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Target player mills a card.", playerB);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Target player puts the top card", playerB);
|
||||
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Tribute to Hunger");
|
||||
|
||||
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Reanimate", "Lazav, Dimir Mastermind");
|
||||
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerB, "Tribute to Hunger", 1);
|
||||
assertGraveyardCount(playerA, "Reanimate", 1);
|
||||
|
||||
|
||||
assertLife(playerA, 16); // -4 from Reanmiate
|
||||
assertLife(playerB, 22); // +3 from Tribute to Hunger because Lazav is 3/2
|
||||
|
||||
assertLife(playerB, 22); // +3 from Tribute to Hunger because Lazav is 3/2
|
||||
|
||||
assertPermanentCount(playerA, "Lazav, Dimir Mastermind", 1);
|
||||
assertPowerToughness(playerA, "Lazav, Dimir Mastermind", 3, 3);
|
||||
Permanent lazav = getPermanent("Lazav, Dimir Mastermind", playerA.getId());
|
||||
Assert.assertFalse(lazav.getSubtype(currentGame).contains(SubType.GRIFFIN)); // no Griffin type
|
||||
Assert.assertFalse("Lazav, Dimir Mastermind must have flying",lazav.getAbilities().contains(FlyingAbility.getInstance()));
|
||||
|
||||
|
||||
Assert.assertFalse("Lazav, Dimir Mastermind must have flying", lazav.getAbilities().contains(FlyingAbility.getInstance()));
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests if Lazav remains a copy of the creature after it is exiled
|
||||
*/
|
||||
|
|
@ -204,20 +203,20 @@ public class LazavDimirMastermindTest extends CardTestPlayerBase {
|
|||
public void testCopyCreatureExiled() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Lazav, Dimir Mastermind", 1);
|
||||
// Codex Shredder - Artifact
|
||||
// {T}: Target player mills a card.
|
||||
// {T}: Target player puts the top card of their library into their graveyard.
|
||||
// {5}, {T}, Sacrifice Codex Shredder: Return target card from your graveyard to your hand.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Codex Shredder", 1);
|
||||
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
|
||||
|
||||
|
||||
addCard(Zone.HAND, playerA, "Rest in Peace", 1);
|
||||
|
||||
// Flying 3/2
|
||||
addCard(Zone.LIBRARY, playerB, "Assault Griffin",5);
|
||||
addCard(Zone.LIBRARY, playerB, "Assault Griffin", 5);
|
||||
skipInitShuffling();
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Target player mills a card.", playerB);
|
||||
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Target player puts the top card", playerB);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Rest in Peace");
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
|
|
@ -228,6 +227,6 @@ public class LazavDimirMastermindTest extends CardTestPlayerBase {
|
|||
|
||||
Permanent lazav = getPermanent("Lazav, Dimir Mastermind", playerA.getId());
|
||||
Assert.assertTrue(lazav.getSubtype(currentGame).contains(SubType.GRIFFIN));
|
||||
Assert.assertTrue("Lazav, Dimir Mastermind must have flying",lazav.getAbilities().contains(FlyingAbility.getInstance()));
|
||||
Assert.assertTrue("Lazav, Dimir Mastermind must have flying", lazav.getAbilities().contains(FlyingAbility.getInstance()));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,10 @@
|
|||
package org.mage.test.player;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import mage.MageItem;
|
||||
import mage.MageObject;
|
||||
import mage.MageObjectReference;
|
||||
|
|
@ -57,13 +62,6 @@ 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.*;
|
||||
|
||||
/**
|
||||
|
|
@ -193,7 +191,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;
|
||||
|
|
@ -1046,13 +1044,13 @@ public class TestPlayer implements Player {
|
|||
|
||||
List<String> data = cards.stream()
|
||||
.map(c -> (((c instanceof PermanentToken) ? "[T] " : "[C] ")
|
||||
+ c.getIdName()
|
||||
+ (c.isCopy() ? " [copy of " + c.getCopyFrom().getId().toString().substring(0, 3) + "]" : "")
|
||||
+ " - " + c.getPower().getValue() + "/" + c.getToughness().getValue()
|
||||
+ (c.isPlaneswalker() ? " - L" + c.getCounters(game).getCount(CounterType.LOYALTY) : "")
|
||||
+ ", " + (c.isTapped() ? "Tapped" : "Untapped")
|
||||
+ getPrintableAliases(", [", c.getId(), "]")
|
||||
+ (c.getAttachedTo() == null ? "" : ", attached to " + game.getPermanent(c.getAttachedTo()).getIdName())))
|
||||
+ c.getIdName()
|
||||
+ (c.isCopy() ? " [copy of " + c.getCopyFrom().getId().toString().substring(0, 3) + "]" : "")
|
||||
+ " - " + c.getPower().getValue() + "/" + c.getToughness().getValue()
|
||||
+ (c.isPlaneswalker() ? " - L" + c.getCounters(game).getCount(CounterType.LOYALTY) : "")
|
||||
+ ", " + (c.isTapped() ? "Tapped" : "Untapped")
|
||||
+ getPrintableAliases(", [", c.getId(), "]")
|
||||
+ (c.getAttachedTo() == null ? "" : ", attached to " + game.getPermanent(c.getAttachedTo()).getIdName())))
|
||||
.sorted()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
|
|
@ -1076,12 +1074,12 @@ public class TestPlayer implements Player {
|
|||
|
||||
List<String> data = abilities.stream()
|
||||
.map(a -> (a.getZone() + " -> "
|
||||
+ a.getSourceObject(game).getIdName() + " -> "
|
||||
+ (a.toString().startsWith("Cast ") ? "[" + a.getManaCostsToPay().getText() + "] -> " : "") // printed cost, not modified
|
||||
+ (a.toString().length() > 0
|
||||
? a.toString().substring(0, Math.min(20, a.toString().length()))
|
||||
: a.getClass().getSimpleName())
|
||||
+ "..."))
|
||||
+ a.getSourceObject(game).getIdName() + " -> "
|
||||
+ (a.toString().startsWith("Cast ") ? "[" + a.getManaCostsToPay().getText() + "] -> " : "") // printed cost, not modified
|
||||
+ (a.toString().length() > 0
|
||||
? a.toString().substring(0, Math.min(20, a.toString().length()))
|
||||
: a.getClass().getSimpleName())
|
||||
+ "..."))
|
||||
.sorted()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
|
|
@ -1446,7 +1444,7 @@ public class TestPlayer implements Player {
|
|||
UUID defenderId = null;
|
||||
boolean mustAttackByAction = false;
|
||||
boolean madeAttackByAction = false;
|
||||
for (Iterator<org.mage.test.player.PlayerAction> it = actions.iterator(); it.hasNext(); ) {
|
||||
for (Iterator<org.mage.test.player.PlayerAction> it = actions.iterator(); it.hasNext();) {
|
||||
PlayerAction action = it.next();
|
||||
|
||||
// aiXXX commands
|
||||
|
|
@ -2021,7 +2019,7 @@ public class TestPlayer implements Player {
|
|||
// skip targets
|
||||
if (targets.get(0).equals(TARGET_SKIP)) {
|
||||
Assert.assertTrue("found skip target, but it require more targets, needs "
|
||||
+ (target.getMinNumberOfTargets() - target.getTargets().size()) + " more",
|
||||
+ (target.getMinNumberOfTargets() - target.getTargets().size()) + " more",
|
||||
target.getTargets().size() >= target.getMinNumberOfTargets());
|
||||
targets.remove(0);
|
||||
return true;
|
||||
|
|
@ -2326,7 +2324,7 @@ public class TestPlayer implements Player {
|
|||
|
||||
this.chooseStrictModeFailed("choice", game,
|
||||
"Triggered list (total " + abilities.size() + "):\n"
|
||||
+ abilities.stream().map(a -> getInfo(a, game)).collect(Collectors.joining("\n")));
|
||||
+ abilities.stream().map(a -> getInfo(a, game)).collect(Collectors.joining("\n")));
|
||||
return computerPlayer.chooseTriggeredAbility(abilities, game);
|
||||
}
|
||||
|
||||
|
|
@ -3496,7 +3494,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);
|
||||
|
|
@ -3504,7 +3502,7 @@ public class TestPlayer implements Player {
|
|||
|
||||
@Override
|
||||
public boolean choose(Outcome outcome, Cards cards,
|
||||
TargetCard target, Game game
|
||||
TargetCard target, Game game
|
||||
) {
|
||||
assertAliasSupportInChoices(false);
|
||||
if (!choices.isEmpty()) {
|
||||
|
|
@ -3541,7 +3539,7 @@ public class TestPlayer implements Player {
|
|||
|
||||
@Override
|
||||
public boolean chooseTargetAmount(Outcome outcome, TargetAmount target,
|
||||
Ability source, Game game
|
||||
Ability source, Game game
|
||||
) {
|
||||
// chooseTargetAmount calls for EACH target cycle (e.g. one target per click, see TargetAmount)
|
||||
// if use want to stop choosing then chooseTargetAmount must return false (example: up to xxx)
|
||||
|
|
@ -3554,7 +3552,7 @@ public class TestPlayer implements Player {
|
|||
// skip targets
|
||||
if (targets.get(0).equals(TARGET_SKIP)) {
|
||||
Assert.assertTrue("found skip target, but it require more targets, needs "
|
||||
+ (target.getMinNumberOfTargets() - target.getTargets().size()) + " more",
|
||||
+ (target.getMinNumberOfTargets() - target.getTargets().size()) + " more",
|
||||
target.getTargets().size() >= target.getMinNumberOfTargets());
|
||||
targets.remove(0);
|
||||
return false; // false in chooseTargetAmount = stop to choose
|
||||
|
|
@ -3607,15 +3605,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;
|
||||
|
||||
|
|
@ -3665,15 +3663,15 @@ public class TestPlayer implements Player {
|
|||
|
||||
@Override
|
||||
public UUID chooseBlockerOrder(List<Permanent> blockers, CombatGroup combatGroup,
|
||||
List<UUID> blockerOrder, Game game
|
||||
List<UUID> blockerOrder, Game game
|
||||
) {
|
||||
return computerPlayer.chooseBlockerOrder(blockers, combatGroup, blockerOrder, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void assignDamage(int damage, List<UUID> targets,
|
||||
String singleTargetName, UUID sourceId,
|
||||
Game game
|
||||
String singleTargetName, UUID sourceId,
|
||||
Game game
|
||||
) {
|
||||
computerPlayer.assignDamage(damage, targets, singleTargetName, sourceId, game);
|
||||
}
|
||||
|
|
@ -3692,14 +3690,14 @@ public class TestPlayer implements Player {
|
|||
|
||||
@Override
|
||||
public void pickCard(List<Card> 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) {
|
||||
|
|
@ -3710,44 +3708,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<UUID> appliedEffects
|
||||
Ability source, Game game,
|
||||
boolean tapped, boolean faceDown, boolean byOwner, List<UUID> 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<Card> cards, Zone toZone,
|
||||
Ability source, Game game
|
||||
Ability source, Game game
|
||||
) {
|
||||
return computerPlayer.moveCards(cards, toZone, source, game);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean moveCards(Set<Card> cards, Zone toZone,
|
||||
Ability source, Game game,
|
||||
boolean tapped, boolean faceDown, boolean byOwner, List<UUID> appliedEffects
|
||||
Ability source, Game game,
|
||||
boolean tapped, boolean faceDown, boolean byOwner, List<UUID> appliedEffects
|
||||
) {
|
||||
return computerPlayer.moveCards(cards, toZone, source, game, tapped, faceDown, byOwner, appliedEffects);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue