From 717308ba12f380d93e562727416c374409cf25ae Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 9 Jun 2018 14:10:48 +0200 Subject: [PATCH] * Fixed that commanders of players were not removed if a player left a game. Fixed a problem that continuous effects of objects of players that left the game were not removed immediately. --- .../test/commander/FFA3/PlayerLeftTest.java | 34 +++++++ .../PlayerLeftGameRangeAllTest.java | 95 ++++++++++++++++++- .../base/CardTestCommander3PlayersFFA.java | 7 +- Mage/src/main/java/mage/game/GameImpl.java | 7 +- 4 files changed, 135 insertions(+), 8 deletions(-) create mode 100644 Mage.Tests/src/test/java/org/mage/test/commander/FFA3/PlayerLeftTest.java diff --git a/Mage.Tests/src/test/java/org/mage/test/commander/FFA3/PlayerLeftTest.java b/Mage.Tests/src/test/java/org/mage/test/commander/FFA3/PlayerLeftTest.java new file mode 100644 index 00000000000..179402a7de2 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/commander/FFA3/PlayerLeftTest.java @@ -0,0 +1,34 @@ +/* + * 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.commander.FFA3; + +import mage.constants.PhaseStep; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestCommander3PlayersFFA; + +/** + * + * @author LevelX2 + */ +public class PlayerLeftTest extends CardTestCommander3PlayersFFA { + + /** + * Check that if a player left the game, it's commander is also removed + */ + @Test + public void TestCommanderRemoved() { + + concede(1, PhaseStep.PRECOMBAT_MAIN, playerA); + setStopAt(1, PhaseStep.DECLARE_ATTACKERS); + execute(); + + assertCommandZoneCount(playerB, "Ob Nixilis of the Black Oath", 1); + assertCommandZoneCount(playerC, "Ob Nixilis of the Black Oath", 1); + assertCommandZoneCount(playerA, "Ob Nixilis of the Black Oath", 0); + + } + +} diff --git a/Mage.Tests/src/test/java/org/mage/test/multiplayer/PlayerLeftGameRangeAllTest.java b/Mage.Tests/src/test/java/org/mage/test/multiplayer/PlayerLeftGameRangeAllTest.java index 3bb09b04402..f2fbfe06a75 100644 --- a/Mage.Tests/src/test/java/org/mage/test/multiplayer/PlayerLeftGameRangeAllTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/multiplayer/PlayerLeftGameRangeAllTest.java @@ -1,4 +1,3 @@ - package org.mage.test.multiplayer; import java.io.FileNotFoundException; @@ -324,4 +323,98 @@ public class PlayerLeftGameRangeAllTest extends CardTestMultiPlayerBase { assertPermanentCount(playerD, "Silvercoat Lion", 1); } + + /** + * In an EDH game, a player controlling Thalia left the game and the ability + * still lasted for the rest of the game. Gamelog if it helps. + */ + @Test + public void TestThaliaHereticCatharContinuousEffectEndsIfPlayerDies() { + // Player order: A -> D -> C -> B + + addCard(Zone.BATTLEFIELD, playerA, "Plains", 3); + // First strike + // Creatures and nonbasic lands your opponents control enter the battlefield tapped. + addCard(Zone.HAND, playerA, "Thalia, Heretic Cathar"); // Creature {2}{W} + + addCard(Zone.HAND, playerD, "Lightning Bolt"); + addCard(Zone.BATTLEFIELD, playerD, "Mountain", 1); + + addCard(Zone.HAND, playerC, "Pillarfield Ox", 1); + addCard(Zone.BATTLEFIELD, playerC, "Plains", 4); + + addCard(Zone.HAND, playerB, "Silvercoat Lion", 1); + addCard(Zone.BATTLEFIELD, playerB, "Plains", 2); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Thalia, Heretic Cathar"); + + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerD, "Lightning Bolt", playerA); + + castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerC, "Pillarfield Ox"); + + castSpell(4, PhaseStep.PRECOMBAT_MAIN, playerB, "Silvercoat Lion"); + + setStopAt(4, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerD, "Lightning Bolt", 1); + + assertLife(playerA, -1); + Assert.assertFalse("Player D is no longer in the game", playerA.isInGame()); + + assertPermanentCount(playerC, "Pillarfield Ox", 1); + assertPermanentCount(playerB, "Silvercoat Lion", 1); + + assertTapped("Pillarfield Ox", false); + assertTapped("Silvercoat Lion", false); + + } + + /** + * In an EDH game, a player controlling Thalia left the game and the ability + * still lasted for the rest of the game. Gamelog if it helps. + */ + @Test + public void TestThaliaHereticCatharContinuousEffectEndsIfPlayerConcedes() { + // Player order: A -> D -> C -> B + + addCard(Zone.BATTLEFIELD, playerA, "Plains", 3); + // First strike + // Creatures and nonbasic lands your opponents control enter the battlefield tapped. + addCard(Zone.HAND, playerA, "Thalia, Heretic Cathar"); // Creature {2}{W} + + addCard(Zone.HAND, playerD, "Juggernaut"); + addCard(Zone.BATTLEFIELD, playerD, "Plains", 4); + + addCard(Zone.HAND, playerC, "Pillarfield Ox", 1); + addCard(Zone.BATTLEFIELD, playerC, "Plains", 4); + + addCard(Zone.HAND, playerB, "Silvercoat Lion", 1); + addCard(Zone.BATTLEFIELD, playerB, "Plains", 2); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Thalia, Heretic Cathar"); + + concede(2, PhaseStep.PRECOMBAT_MAIN, playerA); + castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerD, "Juggernaut"); + + castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerC, "Pillarfield Ox"); + + castSpell(4, PhaseStep.PRECOMBAT_MAIN, playerB, "Silvercoat Lion"); + + setStopAt(4, PhaseStep.BEGIN_COMBAT); + execute(); + + Assert.assertFalse("Player D is no longer in the game", playerA.isInGame()); + assertLife(playerA, 2); + + assertPermanentCount(playerD, "Juggernaut", 1); + assertPermanentCount(playerC, "Pillarfield Ox", 1); + assertPermanentCount(playerB, "Silvercoat Lion", 1); + + assertTapped("Pillarfield Ox", false); + assertTapped("Silvercoat Lion", false); + assertTapped("Juggernaut", false); + + } + } diff --git a/Mage.Tests/src/test/java/org/mage/test/serverside/base/CardTestCommander3PlayersFFA.java b/Mage.Tests/src/test/java/org/mage/test/serverside/base/CardTestCommander3PlayersFFA.java index f6790b940b5..c094cf874c8 100644 --- a/Mage.Tests/src/test/java/org/mage/test/serverside/base/CardTestCommander3PlayersFFA.java +++ b/Mage.Tests/src/test/java/org/mage/test/serverside/base/CardTestCommander3PlayersFFA.java @@ -1,4 +1,3 @@ - package org.mage.test.serverside.base; import java.io.FileNotFoundException; @@ -25,9 +24,9 @@ public abstract class CardTestCommander3PlayersFFA extends CardTestPlayerAPIImpl @Override protected Game createNewGameAndPlayers() throws GameException, FileNotFoundException { Game game = new CommanderFreeForAll(MultiplayerAttackOption.MULTIPLE, RangeOfInfluence.ONE, 0, 40); - playerA = createPlayer(game, playerA, "PlayerA"); - playerB = createPlayer(game, playerB, "PlayerB"); - playerC = createPlayer(game, playerC, "PlayerC"); + playerA = createPlayer(game, playerA, "PlayerA", deckNameA); + playerB = createPlayer(game, playerB, "PlayerB", deckNameB); + playerC = createPlayer(game, playerC, "PlayerC", deckNameC); return game; } diff --git a/Mage/src/main/java/mage/game/GameImpl.java b/Mage/src/main/java/mage/game/GameImpl.java index ae94942ac2d..2292c2737b3 100644 --- a/Mage/src/main/java/mage/game/GameImpl.java +++ b/Mage/src/main/java/mage/game/GameImpl.java @@ -1,4 +1,3 @@ - package mage.game; import java.io.IOException; @@ -2552,11 +2551,11 @@ public abstract class GameImpl implements Game, Serializable { } } - //Remove all emblems/plane the player controls + //Remove all commander/emblems/plane the player controls boolean addPlaneAgain = false; for (Iterator it = this.getState().getCommand().iterator(); it.hasNext();) { CommandObject obj = it.next(); - if ((obj instanceof Emblem || obj instanceof Plane) && obj.getControllerId().equals(playerId)) { + if (obj.getControllerId().equals(playerId)) { if (obj instanceof Emblem) { ((Emblem) obj).discardEffects();// This may not be the best fix but it works } @@ -2590,6 +2589,8 @@ public abstract class GameImpl implements Game, Serializable { it.remove(); } } + // Make sure effects of no longer existing objects are removed + getContinuousEffects().removeInactiveEffects(this); // If the current monarch leaves the game. When that happens, the player whose turn it is becomes the monarch. // If the monarch leaves the game on their turn, the next player in turn order becomes the monarch. if (playerId.equals(getMonarchId())) {