mirror of
https://github.com/correl/mage.git
synced 2024-11-15 03:00:16 +00:00
* Added test for spells targeting players continue resolving even when those players leave the game (closes #1600). Problem no longer reproducable.
This commit is contained in:
parent
d03bd3bf57
commit
a22e89d26a
2 changed files with 104 additions and 4 deletions
|
@ -28,12 +28,12 @@
|
|||
package mage.cards.t;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.constants.CardType;
|
||||
import mage.abilities.effects.common.GainLifeEffect;
|
||||
import mage.abilities.effects.common.LoseLifeTargetEffect;
|
||||
import mage.abilities.keyword.StormAbility;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.target.TargetPlayer;
|
||||
|
||||
/**
|
||||
|
@ -43,14 +43,13 @@ import mage.target.TargetPlayer;
|
|||
public class TendrilsOfAgony extends CardImpl {
|
||||
|
||||
public TendrilsOfAgony(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{B}{B}");
|
||||
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{B}{B}");
|
||||
|
||||
// Target player loses 2 life and you gain 2 life.
|
||||
this.getSpellAbility().addTarget(new TargetPlayer());
|
||||
this.getSpellAbility().addEffect(new LoseLifeTargetEffect(2));
|
||||
this.getSpellAbility().addEffect(new GainLifeEffect(2));
|
||||
// Storm
|
||||
// Storm (When you cast this spell, copy it for each spell cast before it this turn. You may choose new targets for the copies.)
|
||||
this.addAbility(new StormAbility());
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* 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.multiplayer;
|
||||
|
||||
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 org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestMultiPlayerBase;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class PlayerDiedStackTargetHandlingTest extends CardTestMultiPlayerBase {
|
||||
|
||||
@Override
|
||||
protected Game createNewGameAndPlayers() throws GameException, FileNotFoundException {
|
||||
// Start Life = 2
|
||||
Game game = new FreeForAll(MultiplayerAttackOption.MULTIPLE, RangeOfInfluence.ONE, 0, 3);
|
||||
// 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* If a spell or ability on the stack is targeting a player (or an object
|
||||
* controlled by that player), and that player leaves the game, then the
|
||||
* target becomes illegal and the spell or ability should be countered upon
|
||||
* resolution (assuming that player or object is the only target of the
|
||||
* spell). However, Xmage regularly continues resolving spells and abilities
|
||||
* targeting players after that player concedes, which is a problem in
|
||||
* multiplayer.
|
||||
*/
|
||||
@Test
|
||||
public void TestDeadPlayerIsNoLongerValidTarget() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
|
||||
// Lightning Helix deals 3 damage to target creature or player and you gain 3 life.
|
||||
addCard(Zone.HAND, playerA, "Lightning Helix", 2); // Instant {R}{W}
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Helix", playerD);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Helix", playerD);
|
||||
|
||||
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, "Lightning Helix", 2);
|
||||
Assert.assertTrue("Active player has to be player C", currentGame.getActivePlayerId() == playerC.getId());
|
||||
|
||||
assertLife(playerA, 6);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Player A casts Tendrils of Agony with a storm count of 10 targeting
|
||||
* Player B, who is at 10 life. After the first five copies of Tendrils
|
||||
* resolve, player A will have gained 10 life and Player B will have lost 10
|
||||
* life, so player B should die as a state-based action before the remaining
|
||||
* six copies resolve. In similar circumstances, Xmage has continued
|
||||
* resolving the additional six copies, putting player B at -12 life and
|
||||
* letting player A gain an additional 12 life inappropriately
|
||||
*/
|
||||
@Test
|
||||
public void TestDeadPlayerIsNoLongerValidTarget2() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 4);
|
||||
addCard(Zone.HAND, playerA, "Silvercoat Lion", 2);
|
||||
// Target player loses 2 life and you gain 2 life.
|
||||
// Storm (When you cast this spell, copy it for each spell cast before it this turn. You may choose new targets for the copies.)
|
||||
addCard(Zone.HAND, playerA, "Tendrils of Agony", 1); // Sorcery {2}{B}{B}
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Silvercoat Lion");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Silvercoat Lion");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Tendrils of Agony", playerD);
|
||||
addTarget(playerA, playerD);
|
||||
addTarget(playerA, playerD);
|
||||
|
||||
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, "Silvercoat Lion", 2);
|
||||
assertGraveyardCount(playerA, "Tendrils of Agony", 1);
|
||||
Assert.assertTrue("Active player has to be player C", currentGame.getActivePlayerId() == playerC.getId());
|
||||
|
||||
assertLife(playerA, 7);
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue