* No more continuous effects stay on battlefield after player leave the game;

Test framework: added real time check for player in game or not;
This commit is contained in:
Oleg Agafonov 2019-04-28 19:32:25 +04:00
parent 00633ce055
commit 9ef2e0bda7
5 changed files with 244 additions and 25 deletions

View file

@ -0,0 +1,132 @@
package org.mage.test.cards.continuous;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.common.continuous.BoostAllEffect;
import mage.constants.Duration;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestMultiPlayerBaseWithRangeAll;
/**
* @author JayDi85
*/
public class PlayerLeavesGameTest extends CardTestMultiPlayerBaseWithRangeAll {
/*
800.4a When a player leaves the game, all objects (see rule 109) owned by that player leave the game and any effects
which give that player control of any objects or players end. Then, if that player controlled any objects on the stack
not represented by cards, those objects cease to exist. Then, if there are any objects still controlled by that player,
those objects are exiled. This is not a state-based action. It happens as soon as the player leaves the game.
If the player who left the game had priority at the time he or she left, priority passes to the next player in turn
order whos still in the game.
*/
String cardBear2 = "Balduvian Bears"; // 2/2
@Test
public void test_PlayerLeaveGame() {
// Player order: A -> D -> C -> B
// B must checks A for online status
checkPlayerInGame("turn 1", 1, PhaseStep.PRECOMBAT_MAIN, playerD, playerA, true);
checkPlayerInGame("turn 2", 2, PhaseStep.PRECOMBAT_MAIN, playerD, playerA, true);
checkPlayerInGame("turn 3 before", 3, PhaseStep.PRECOMBAT_MAIN, playerD, playerA, true);
concede(3, PhaseStep.POSTCOMBAT_MAIN, playerA);
checkPlayerInGame("turn 3 after", 3, PhaseStep.END_TURN, playerD, playerA, false);
checkPlayerInGame("turn 4", 4, PhaseStep.PRECOMBAT_MAIN, playerD, playerA, false);
setStopAt(4, PhaseStep.CLEANUP);
setStrictChooseMode(true);
execute();
assertAllCommandsUsed();
}
@Test
public void test_PlayerLeaveGameWithOwnPermanent() {
// Player order: A -> D -> C -> B
addCard(Zone.BATTLEFIELD, playerA, cardBear2, 1);
// B must checks A for online status
checkPlayerInGame("turn 1", 1, PhaseStep.PRECOMBAT_MAIN, playerD, playerA, true);
checkPermanentCount("turn 1", 1, PhaseStep.PRECOMBAT_MAIN, playerD, playerA, cardBear2, 1);
checkPlayerInGame("turn 2", 2, PhaseStep.PRECOMBAT_MAIN, playerD, playerA, true);
checkPermanentCount("turn 2", 2, PhaseStep.PRECOMBAT_MAIN, playerD, playerA, cardBear2, 1);
checkPlayerInGame("turn 3 before", 3, PhaseStep.PRECOMBAT_MAIN, playerD, playerA, true);
checkPermanentCount("turn 3 before", 3, PhaseStep.PRECOMBAT_MAIN, playerD, playerA, cardBear2, 1);
concede(3, PhaseStep.POSTCOMBAT_MAIN, playerA);
checkPlayerInGame("turn 3 after", 3, PhaseStep.END_TURN, playerD, playerA, false);
checkPermanentCount("turn 3 after", 3, PhaseStep.END_TURN, playerD, playerA, cardBear2, 0);
checkPlayerInGame("turn 4", 4, PhaseStep.PRECOMBAT_MAIN, playerD, playerA, false);
checkPermanentCount("turn 4", 4, PhaseStep.PRECOMBAT_MAIN, playerD, playerA, cardBear2, 0);
setStopAt(4, PhaseStep.CLEANUP);
setStrictChooseMode(true);
execute();
assertAllCommandsUsed();
}
private void prepareAndRunLeaveGameWithEffectTest(Duration duration) {
// Player order: A -> D -> C -> B
addCard(Zone.BATTLEFIELD, playerA, cardBear2, 1);
addCard(Zone.BATTLEFIELD, playerD, cardBear2, 1);
addCustomCardWithAbility("effect", playerA, new SimpleStaticAbility(new BoostAllEffect(1, 1, duration)));
// B must checks A for online status
checkPlayerInGame(duration.toString() + " - turn 1", 1, PhaseStep.PRECOMBAT_MAIN, playerD, playerA, true);
checkPermanentCount(duration.name() + " - turn 1", 1, PhaseStep.PRECOMBAT_MAIN, playerD, playerA, cardBear2, 1);
checkPT(duration.name() + " - turn 1", 1, PhaseStep.PRECOMBAT_MAIN, playerD, cardBear2, 3, 3);
//
checkPlayerInGame(duration.name() + " - turn 2", 2, PhaseStep.PRECOMBAT_MAIN, playerD, playerA, true);
checkPermanentCount(duration.name() + " - turn 2", 2, PhaseStep.PRECOMBAT_MAIN, playerD, playerA, cardBear2, 1);
checkPT(duration.name() + " - turn 2", 2, PhaseStep.PRECOMBAT_MAIN, playerD, cardBear2, 3, 3);
//
checkPlayerInGame(duration.name() + " - turn 3 before", 3, PhaseStep.PRECOMBAT_MAIN, playerD, playerA, true);
checkPermanentCount(duration.name() + " - turn 3 before", 3, PhaseStep.PRECOMBAT_MAIN, playerD, playerA, cardBear2, 1);
checkPT(duration.name() + " - turn 3 before", 3, PhaseStep.PRECOMBAT_MAIN, playerD, cardBear2, 3, 3);
//
concede(3, PhaseStep.POSTCOMBAT_MAIN, playerA);
//
checkPlayerInGame(duration.name() + " - turn 3 after", 3, PhaseStep.END_TURN, playerD, playerA, false);
checkPermanentCount(duration.name() + " - turn 3 after", 3, PhaseStep.END_TURN, playerD, playerA, cardBear2, 0);
checkPT(duration.name() + " - turn 3 after", 3, PhaseStep.END_TURN, playerD, cardBear2, 2, 2);
//
checkPlayerInGame(duration.name() + " - turn 4", 4, PhaseStep.PRECOMBAT_MAIN, playerD, playerA, false);
checkPermanentCount(duration.name() + " - turn 4", 4, PhaseStep.PRECOMBAT_MAIN, playerD, playerA, cardBear2, 0);
checkPT(duration.name() + " - turn 4", 4, PhaseStep.PRECOMBAT_MAIN, playerD, cardBear2, 2, 2);
setStopAt(4, PhaseStep.CLEANUP);
setStrictChooseMode(true);
execute();
assertAllCommandsUsed();
}
@Test
public void test_PlayerLeaveGameWithOwnPermanentAndCustomEffect() {
prepareAndRunLeaveGameWithEffectTest(Duration.Custom);
}
@Test
public void test_PlayerLeaveGameWithOwnPermanentAndWhileOnBattlefieldEffect() {
prepareAndRunLeaveGameWithEffectTest(Duration.WhileOnBattlefield);
}
@Test
public void test_PlayerLeaveGameWithOwnPermanentAndEndOfGameEffect() {
prepareAndRunLeaveGameWithEffectTest(Duration.EndOfGame);
}
@Test
public void test_PlayerLeaveGameWithOwnPermanentAndUntilSourceLeavesBattlefielEffect() {
prepareAndRunLeaveGameWithEffectTest(Duration.UntilSourceLeavesBattlefield);
}
// TODO: add leave tests for end of step
// TODO: add leave tests for end of turn
// TODO: add leave tests for end of your turn
}

View file

@ -1,8 +1,6 @@
package org.mage.test.commander.duel;
import java.io.FileNotFoundException;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.game.Game;
@ -11,8 +9,9 @@ import org.junit.Assert;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestCommanderDuelBase;
import java.io.FileNotFoundException;
/**
*
* @author LevelX2
*/
@ -21,11 +20,11 @@ public class TeferiMageOfZhalfirTest extends CardTestCommanderDuelBase {
@Override
protected Game createNewGameAndPlayers() throws GameException, FileNotFoundException {
setDecknamePlayerA("CommanderDuel_UW.dck"); // Commander = Daxos of Meletis
return super.createNewGameAndPlayers();
return super.createNewGameAndPlayers();
}
@Test
public void castCommanderWithFlash() {
public void castCommanderWithFlash() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
@ -36,11 +35,13 @@ public class TeferiMageOfZhalfirTest extends CardTestCommanderDuelBase {
execute();
assertPermanentCount(playerA, "Daxos of Meletis", 1);
assertAllCommandsUsed();
}
@Test
public void testCommanderDamage() {
setLife(playerA, 20);
setLife(playerB, 20);
addCard(Zone.BATTLEFIELD, playerA, "Plains", 6);
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
// Enchant creature
@ -49,24 +50,30 @@ public class TeferiMageOfZhalfirTest extends CardTestCommanderDuelBase {
addCard(Zone.HAND, playerA, "Angelic Destiny");
addCard(Zone.BATTLEFIELD, playerA, "Teferi, Mage of Zhalfir");
// Daxos of Meletis can't be blocked by creatures with power 3 or greater.
// Whenever Daxos of Meletis deals combat damage to a player, exile the top card of that player's library. You gain life equal to that card's converted mana cost. Until end of turn, you may cast that card and you may spend mana as though it were mana of any color to cast it.
// Whenever Daxos of Meletis deals combat damage to a player, exile the top card of that player's library.
// You gain life equal to that card's converted mana cost. Until end of turn, you may cast that card
// and you may spend mana as though it were mana of any color to cast it.
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Daxos of Meletis");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Angelic Destiny","Daxos of Meletis");
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Angelic Destiny", "Daxos of Meletis");
attack(3, playerA, "Daxos of Meletis");
attack(5, playerA, "Daxos of Meletis");
attack(7, playerA, "Daxos of Meletis");
attack(9, playerA, "Daxos of Meletis");
checkPT("before lost", 9, PhaseStep.PRECOMBAT_MAIN, playerA, "Daxos of Meletis", 6, 6);
setStrictChooseMode(true);
setStopAt(9, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertAllCommandsUsed();
assertPermanentCount(playerA, "Daxos of Meletis", 1);
assertPowerToughness(playerA, "Daxos of Meletis", 6, 6);
assertPowerToughness(playerA, "Daxos of Meletis", 6, 6); // no effects removes after game over -- users and tests can get last game state with all affected effects
Assert.assertEquals("Player A has won because of commander damage", true, playerA.hasWon());
Assert.assertEquals("Player A has lost because of commander damage", true, playerB.hasLost());
}
Assert.assertEquals("Player B has lost because of commander damage", true, playerB.hasLost());
}
}

View file

@ -626,6 +626,13 @@ public class TestPlayer implements Player {
wasProccessed = true;
}
// check player in game: target player, must be in game
if (params[0].equals(CHECK_COMMAND_PLAYER_IN_GAME) && params.length == 3) {
assertPlayerInGame(action, game, game.getPlayer(UUID.fromString(params[1])), Boolean.parseBoolean(params[2]));
actions.remove(action);
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]));
@ -633,9 +640,9 @@ public class TestPlayer implements Player {
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]));
// check battlefield count: target player, card name, count
if (params[0].equals(CHECK_COMMAND_PERMANENT_COUNT) && params.length == 4) {
assertPermanentCount(action, game, game.getPlayer(UUID.fromString(params[1])), params[2], Integer.parseInt(params[3]));
actions.remove(action);
wasProccessed = true;
}
@ -928,6 +935,18 @@ public class TestPlayer implements Player {
Life, player.getLife());
}
private void assertPlayerInGame(PlayerAction action, Game game, Player targetPlayer, boolean mustBeInGame) {
Assert.assertNotNull("Can't find target player", targetPlayer);
if (targetPlayer.isInGame() && !mustBeInGame) {
Assert.fail(action.getActionName() + " - player " + targetPlayer.getName() + " must NOT be in game");
}
if (!targetPlayer.isInGame() && mustBeInGame) {
Assert.fail(action.getActionName() + " - player " + targetPlayer.getName() + " must be in game");
}
}
private void assertAbility(PlayerAction action, Game game, Player player, String permanentName, String abilityClass, boolean mustHave) {
Permanent perm = findPermanentWithAssert(action, game, player, permanentName);

View file

@ -64,6 +64,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
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";
public static final String CHECK_COMMAND_PLAYER_IN_GAME = "PLAYER_IN_GAME";
// TODO: add target player param to commands
public static final String SHOW_COMMAND_LIBRARY = "LIBRARY";
@ -300,6 +301,10 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
check(checkName, turnNum, step, player, CHECK_COMMAND_LIFE, life.toString());
}
public void checkPlayerInGame(String checkName, int turnNum, PhaseStep step, TestPlayer player, TestPlayer targetPlayer, Boolean mustBeInGame) {
check(checkName, turnNum, step, player, CHECK_COMMAND_PLAYER_IN_GAME, targetPlayer.getId().toString(), mustBeInGame.toString());
}
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());
@ -307,7 +312,12 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
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());
checkPermanentCount(checkName, turnNum, step, player, player, permanentName, count);
}
public void checkPermanentCount(String checkName, int turnNum, PhaseStep step, TestPlayer player, TestPlayer targetPlayer, String permanentName, Integer count) {
//Assert.assertNotEquals("", permanentName);
check(checkName, turnNum, step, player, CHECK_COMMAND_PERMANENT_COUNT, targetPlayer.getId().toString(), permanentName, count.toString());
}
public void checkPermanentCounters(String checkName, int turnNum, PhaseStep step, TestPlayer player, String permanentName, CounterType counterType, Integer count) {