mirror of
https://github.com/correl/mage.git
synced 2024-11-15 11:09:30 +00:00
* Added a simple check for infinite loops so that if players confirm the game ends in a draw (#3329).
This commit is contained in:
parent
7b61ad7455
commit
5ce813ad87
2 changed files with 75 additions and 0 deletions
|
@ -7,6 +7,7 @@ package org.mage.test.game.ends;
|
|||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.permanent.Permanent;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
@ -77,4 +78,45 @@ public class GameIsADrawTest extends CardTestPlayerBase {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* So here I made a simple infinite loop with Stuffy Doll and Pariah's
|
||||
* Shield, which should make the game a draw. But instead, it just keeps
|
||||
* going...
|
||||
*/
|
||||
@Test
|
||||
public void GameDrawByInfiniteLoop() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
|
||||
|
||||
// All damage that would be dealt to you is dealt to equipped creature instead.
|
||||
// Equip {3}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Pariah's Shield", 1); // Artifact Equipment {5}
|
||||
|
||||
// As Stuffy Doll enters the battlefield, choose a player.
|
||||
// Stuffy Doll is indestructible.
|
||||
// Whenever Stuffy Doll is dealt damage, it deals that much damage to the chosen player.
|
||||
// {T}: Stuffy Doll deals 1 damage to itself.
|
||||
addCard(Zone.HAND, playerA, "Stuffy Doll", 1); // Artifact Creature {5} 0/1
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Stuffy Doll");
|
||||
setChoice(playerA, "PlayerA");
|
||||
setChoice(playerA, "PlayerA");
|
||||
|
||||
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Equip", "Stuffy Doll");
|
||||
activateAbility(3, PhaseStep.POSTCOMBAT_MAIN, playerA, "{T}");
|
||||
setStopAt(3, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, "Stuffy Doll", 1);
|
||||
Permanent shield = getPermanent("Pariah's Shield");
|
||||
Assert.assertTrue("Pariah's Shield is attached", shield.getAttachedTo() != null);
|
||||
|
||||
Assert.assertFalse("Player A has not won.", playerA.hasWon());
|
||||
Assert.assertFalse("Player B has not won.", playerB.hasWon());
|
||||
|
||||
Assert.assertTrue("Game has ended.", currentGame.hasEnded());
|
||||
|
||||
Assert.assertTrue("Inifinite loop detected, game has be de a draw.", currentGame.isADraw());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1233,6 +1233,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
@Override
|
||||
public void playPriority(UUID activePlayerId, boolean resuming) {
|
||||
int errorContinueCounter = 0;
|
||||
int infiniteLoopCounter = 0;
|
||||
int bookmark = 0;
|
||||
clearAllBookmarks();
|
||||
try {
|
||||
|
@ -1286,6 +1287,13 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
if (allPassed()) {
|
||||
if (!state.getStack().isEmpty()) {
|
||||
if (getStack().size() < 4) {
|
||||
infiniteLoopCounter++;
|
||||
if (infiniteLoopCounter > 15) {
|
||||
isInfiniteLoop();
|
||||
infiniteLoopCounter = 0;
|
||||
}
|
||||
}
|
||||
//20091005 - 115.4
|
||||
resolve();
|
||||
applyEffects();
|
||||
|
@ -1294,6 +1302,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
resetShortLivingLKI();
|
||||
break;
|
||||
} else {
|
||||
infiniteLoopCounter = 0;
|
||||
resetLKI();
|
||||
return;
|
||||
}
|
||||
|
@ -1350,6 +1359,30 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
protected void isInfiniteLoop() {
|
||||
StackObject stackObject = getStack().getFirst();
|
||||
if (stackObject != null) {
|
||||
Player controller = getPlayer(stackObject.getControllerId());
|
||||
if (controller != null) {
|
||||
for (UUID playerId : getState().getPlayersInRange(controller.getId(), this)) {
|
||||
Player player = getPlayer(playerId);
|
||||
if (!player.chooseUse(Outcome.Detriment, "Draw game because of infinite looping?", null, this)) {
|
||||
informPlayers(controller.getLogName() + " has NOT confirmed that the game is a draw because of infinite looping.");
|
||||
return;
|
||||
}
|
||||
informPlayers(controller.getLogName() + " has confirmed that the game is a draw because of infinite looping.");
|
||||
}
|
||||
for (UUID playerId : getState().getPlayersInRange(controller.getId(), this)) {
|
||||
Player player = getPlayer(playerId);
|
||||
if (player != null) {
|
||||
player.drew(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected boolean allPassed() {
|
||||
for (Player player : state.getPlayers().values()) {
|
||||
if (!player.isPassed() && player.canRespond()) {
|
||||
|
|
Loading…
Reference in a new issue