- 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:
LevelX2 2020-06-10 22:28:23 +02:00
parent 25802dc105
commit 1e36b39434
30 changed files with 534 additions and 469 deletions

View file

@ -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);
}
}

View file

@ -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();

View file

@ -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()));
}
}

View file

@ -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);
}