mirror of
https://github.com/magefree/mage.git
synced 2025-12-22 19:41:59 -08:00
fix 514.3a, give player priority on cleanup when something happened (#12115)
This commit is contained in:
parent
f1791a3c70
commit
72a2e32d1c
4 changed files with 106 additions and 7 deletions
|
|
@ -0,0 +1,83 @@
|
||||||
|
package org.mage.test.cards.single.iko;
|
||||||
|
|
||||||
|
import mage.constants.PhaseStep;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.players.Player;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Susucr
|
||||||
|
*/
|
||||||
|
public class RielleTheEverwiseTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link mage.cards.r.RielleTheEverwise} Rielle, the Everwise {1}{U}{R}
|
||||||
|
* Legendary Creature — Human Wizard
|
||||||
|
* Rielle, the Everwise gets +1/+0 for each instant and sorcery card in your graveyard.
|
||||||
|
* Whenever you discard one or more cards for the first time each turn, draw that many cards.
|
||||||
|
* 0/3
|
||||||
|
*/
|
||||||
|
private static final String rielle = "Rielle, the Everwise";
|
||||||
|
|
||||||
|
private static void checkMidExecute(String info, Player player, Game game, int stack, int hand, int life) {
|
||||||
|
Assert.assertEquals(info + " - stack size", stack, game.getStack().size());
|
||||||
|
Assert.assertEquals(info + " - hand size", hand, player.getHand().size());
|
||||||
|
Assert.assertEquals(info + " - life", life, player.getLife());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bug: you had no play priority to respond to Rielle's trigger at end step.
|
||||||
|
@Test
|
||||||
|
public void test_CleanupDiscard_Opp_Response() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
skipInitShuffling();
|
||||||
|
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, rielle);
|
||||||
|
addCard(Zone.HAND, playerA, "Island", 10);
|
||||||
|
addCard(Zone.LIBRARY, playerA, "Island", 3);
|
||||||
|
addCard(Zone.HAND, playerB, "Lightning Bolt");
|
||||||
|
addCard(Zone.HAND, playerB, "Shock");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 2);
|
||||||
|
|
||||||
|
// Choose to discard Islands on first cleanup
|
||||||
|
setChoice(playerA, "Island", 3);
|
||||||
|
|
||||||
|
// Rielle's Trigger on the stack.
|
||||||
|
runCode("Trigger on the stack", 1, PhaseStep.CLEANUP, playerB,
|
||||||
|
(i, p, g) -> checkMidExecute(i, playerA, g, 1, 7, 20));
|
||||||
|
|
||||||
|
// Cast Bolt in response of Rielle's trigger.
|
||||||
|
castSpell(1, PhaseStep.CLEANUP, playerB, "Lightning Bolt", playerA);
|
||||||
|
runCode("Trigger+Bolt on the stack", 1, PhaseStep.CLEANUP, playerB,
|
||||||
|
(i, p, g) -> checkMidExecute(i, playerA, g, 2, 7, 20));
|
||||||
|
|
||||||
|
waitStackResolved(1, PhaseStep.CLEANUP, 1); // resolves first bolt
|
||||||
|
runCode("Trigger+Bolt on the stack", 1, PhaseStep.CLEANUP, playerB,
|
||||||
|
(i, p, g) -> checkMidExecute(i, playerA, g, 1, 7, 20 - 3));
|
||||||
|
|
||||||
|
waitStackResolved(1, PhaseStep.CLEANUP, 1); // resolves rielle trigger
|
||||||
|
runCode("Trigger+Bolt on the stack", 1, PhaseStep.CLEANUP, playerB,
|
||||||
|
(i, p, g) -> checkMidExecute(i, playerA, g, 0, 10, 20 - 3));
|
||||||
|
|
||||||
|
// Cast Shock after Rielle's trigger resolved.
|
||||||
|
castSpell(1, PhaseStep.CLEANUP, playerB, "Shock", playerA);
|
||||||
|
runCode("Trigger+Bolt on the stack", 1, PhaseStep.CLEANUP, playerB,
|
||||||
|
(i, p, g) -> checkMidExecute(i, playerA, g, 1, 10, 20 - 3));
|
||||||
|
|
||||||
|
waitStackResolved(1, PhaseStep.CLEANUP, 1);
|
||||||
|
runCode("Trigger+Bolt on the stack", 1, PhaseStep.CLEANUP, playerB,
|
||||||
|
(i, p, g) -> checkMidExecute(i, playerA, g, 0, 10, 20 - 3 - 2));
|
||||||
|
|
||||||
|
// Discard for the second cleanup.
|
||||||
|
setChoice(playerA, "Island", 3);
|
||||||
|
|
||||||
|
setStopAt(2, PhaseStep.UPKEEP);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertLife(playerA, 20 - 3 - 2);
|
||||||
|
assertHandCount(playerA, 7);
|
||||||
|
assertGraveyardCount(playerA, "Island", 3 + 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -28,8 +28,9 @@ public class EndPhase extends Phase {
|
||||||
@Override
|
@Override
|
||||||
protected void playStep(Game game) {
|
protected void playStep(Game game) {
|
||||||
if (currentStep.getType() == PhaseStep.CLEANUP) {
|
if (currentStep.getType() == PhaseStep.CLEANUP) {
|
||||||
|
game.getState().increaseStepNum();
|
||||||
game.getTurn().setEndTurnRequested(false); // so triggers trigger again
|
game.getTurn().setEndTurnRequested(false); // so triggers trigger again
|
||||||
currentStep.beginStep(game, activePlayerId);
|
prePriority(game, activePlayerId);
|
||||||
// 514.3a At this point, the game checks to see if any state-based actions would be performed
|
// 514.3a At this point, the game checks to see if any state-based actions would be performed
|
||||||
// and/or any triggered abilities are waiting to be put onto the stack (including those that
|
// and/or any triggered abilities are waiting to be put onto the stack (including those that
|
||||||
// trigger "at the beginning of the next cleanup step"). If so, those state-based actions are
|
// trigger "at the beginning of the next cleanup step"). If so, those state-based actions are
|
||||||
|
|
@ -37,10 +38,19 @@ public class EndPhase extends Phase {
|
||||||
// priority. Players may cast spells and activate abilities. Once the stack is empty and all players
|
// priority. Players may cast spells and activate abilities. Once the stack is empty and all players
|
||||||
// pass in succession, another cleanup step begins
|
// pass in succession, another cleanup step begins
|
||||||
if (game.checkStateAndTriggered()) {
|
if (game.checkStateAndTriggered()) {
|
||||||
game.playPriority(activePlayerId, true);
|
// Queues a new cleanup step
|
||||||
playStep(game);
|
game.getState().getTurnMods().add(new TurnMod(activePlayerId).withExtraStep(new CleanupStep()));
|
||||||
|
// resume priority
|
||||||
|
if (!game.isPaused() && !game.checkIfGameIsOver() && !game.executingRollback()) {
|
||||||
|
currentStep.priority(game, activePlayerId, false);
|
||||||
|
if (game.executingRollback()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!game.isPaused() && !game.checkIfGameIsOver() && !game.executingRollback()) {
|
||||||
|
postPriority(game, activePlayerId);
|
||||||
}
|
}
|
||||||
currentStep.endStep(game, activePlayerId);
|
|
||||||
} else {
|
} else {
|
||||||
super.playStep(game);
|
super.playStep(game);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -275,4 +275,7 @@ public abstract class Phase implements Serializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return type.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
|
|
||||||
package mage.game.turn;
|
package mage.game.turn;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import mage.constants.PhaseStep;
|
import mage.constants.PhaseStep;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
import mage.game.events.GameEvent.EventType;
|
import mage.game.events.GameEvent.EventType;
|
||||||
import mage.util.Copyable;
|
import mage.util.Copyable;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Game's step
|
* Game's step
|
||||||
* <p>
|
* <p>
|
||||||
|
|
@ -85,4 +85,7 @@ public abstract class Step implements Serializable, Copyable<Step> {
|
||||||
return stepPart;
|
return stepPart;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return type.getStepText();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue