* Fixed a bug that triggered abilities went under certain circumstances to stack at the wrong time (fixes the not working Sharuum The Hegemnon + Clone + Blood Artist combo).

This commit is contained in:
LevelX2 2015-05-07 18:12:58 +02:00
parent af26b1533a
commit 4d62d62768
6 changed files with 35 additions and 10 deletions

View file

@ -24,9 +24,12 @@ public class HarvesterOfSoulsTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Day of Judgment", 1); addCard(Zone.HAND, playerA, "Day of Judgment", 1);
addCard(Zone.HAND, playerA, "Thatcher Revolt", 1); addCard(Zone.HAND, playerA, "Thatcher Revolt", 1);
// Creature - Demon 5/5 {4}{B}{B}
// Deathtouch
// Whenever another nontoken creature dies, you may draw a card. // Whenever another nontoken creature dies, you may draw a card.
addCard(Zone.BATTLEFIELD, playerA, "Harvester of Souls", 1); addCard(Zone.BATTLEFIELD, playerA, "Harvester of Souls", 1);
// Creature - Wurm 6/4 {4}{G}{G}
addCard(Zone.BATTLEFIELD, playerA, "Craw Wurm", 1); addCard(Zone.BATTLEFIELD, playerA, "Craw Wurm", 1);
// Whenever Arrogant Bloodlord blocks or becomes blocked by a creature with power 1 or less, destroy Arrogant Bloodlord at end of combat. // Whenever Arrogant Bloodlord blocks or becomes blocked by a creature with power 1 or less, destroy Arrogant Bloodlord at end of combat.
addCard(Zone.BATTLEFIELD, playerB, "Arrogant Bloodlord", 1); addCard(Zone.BATTLEFIELD, playerB, "Arrogant Bloodlord", 1);
@ -42,7 +45,7 @@ public class HarvesterOfSoulsTest extends CardTestPlayerBase {
assertLife(playerA, 20); assertLife(playerA, 20);
assertLife(playerB, 20); assertLife(playerB, 20);
assertHandCount(playerA, 2); assertHandCount(playerA, 2); // draw a card for Harvester and Craw Wurm
assertHandCount(playerB, 0); assertHandCount(playerB, 0);
} }

View file

@ -7,7 +7,6 @@ package org.mage.test.cards.triggers.state;
import mage.constants.PhaseStep; import mage.constants.PhaseStep;
import mage.constants.Zone; import mage.constants.Zone;
import mage.counters.CounterType;
import org.junit.Test; import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase; import org.mage.test.serverside.base.CardTestPlayerBase;
@ -51,6 +50,7 @@ public class SynodCenturionTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 6); addCard(Zone.BATTLEFIELD, playerA, "Plains", 6);
addCard(Zone.BATTLEFIELD, playerA, "Bottle Gnomes"); addCard(Zone.BATTLEFIELD, playerA, "Bottle Gnomes");
addCard(Zone.HAND, playerA, "Cloudshift"); addCard(Zone.HAND, playerA, "Cloudshift");
// When you control no other artifacts, sacrifice Synod Centurion.
addCard(Zone.HAND, playerA, "Synod Centurion"); addCard(Zone.HAND, playerA, "Synod Centurion");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Synod Centurion"); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Synod Centurion");

View file

@ -387,15 +387,22 @@ public class TestPlayer extends ComputerPlayer {
String[] targetList = targetDefinition.split("\\^"); String[] targetList = targetDefinition.split("\\^");
boolean targetFound = false; boolean targetFound = false;
for (String targetName: targetList) { for (String targetName: targetList) {
boolean allowCopy = true; boolean originOnly = false;
boolean copyOnly = false;
if (targetName.endsWith("]")) {
if (targetName.endsWith("[no copy]")) { if (targetName.endsWith("[no copy]")) {
allowCopy = false; originOnly = true;
targetName = targetName.substring(0, targetName.length()-9); targetName = targetName.substring(0, targetName.length()-9);
} }
if (targetName.endsWith("[only copy]")) {
copyOnly = true;
targetName = targetName.substring(0, targetName.length()-11);
}
}
for (Permanent permanent : game.getBattlefield().getAllActivePermanents((FilterPermanent)target.getFilter(), game)) { for (Permanent permanent : game.getBattlefield().getAllActivePermanents((FilterPermanent)target.getFilter(), game)) {
if (permanent.getName().equals(targetName) || (permanent.getName()+"-"+permanent.getExpansionSetCode()).equals(targetName)) { if (permanent.getName().equals(targetName) || (permanent.getName()+"-"+permanent.getExpansionSetCode()).equals(targetName)) {
if (((TargetPermanent)target).canTarget(source == null ? this.getId(): source.getControllerId(), permanent.getId(), source, game) && !target.getTargets().contains(permanent.getId())) { if (((TargetPermanent)target).canTarget(source == null ? this.getId(): source.getControllerId(), permanent.getId(), source, game) && !target.getTargets().contains(permanent.getId())) {
if (!permanent.isCopy() || allowCopy) { if ((permanent.isCopy() && !originOnly) || (!permanent.isCopy() && !copyOnly )) {
target.add(permanent.getId(), game); target.add(permanent.getId(), game);
targetFound = true; targetFound = true;
break; break;

View file

@ -861,7 +861,8 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* e.g. "creatureName1^creatureName2" * e.g. "creatureName1^creatureName2"
* you can qualify the target additional by setcode * you can qualify the target additional by setcode
* e.g. "creatureName-M15" * e.g. "creatureName-M15"
* you can add [no copy] to prohibite targets that are copied * you can add [no copy] to the end of the target name to prohibite targets that are copied
* you can add [only copy] to the end of the target name to allow only targets that are copies
*/ */
public void addTarget(TestPlayer player, String target) { public void addTarget(TestPlayer player, String target) {
player.addTarget(target); player.addTarget(target);

View file

@ -1207,7 +1207,6 @@ public abstract class GameImpl implements Game, Serializable {
if (!getTurn().isEndTurnRequested()) { if (!getTurn().isEndTurnRequested()) {
while (state.hasSimultaneousEvents()) { while (state.hasSimultaneousEvents()) {
state.handleSimultaneousEvent(this); state.handleSimultaneousEvent(this);
checkTriggered();
} }
} }
} }
@ -1356,6 +1355,15 @@ public abstract class GameImpl implements Game, Serializable {
state.addDelayedTriggeredAbility(newAbility); state.addDelayedTriggeredAbility(newAbility);
} }
/**
* 116.5. Each time a player would get priority, the game first performs all applicable state-based actions as a single event (see rule 704,
* State-Based Actions), then repeats this process until no state-based actions are performed. Then triggered abilities are put on the stack
* (see rule 603, Handling Triggered Abilities). These steps repeat in order until no further state-based actions are performed and no abilities
* trigger. Then the player who would have received priority does so.
*
* @return
*/
@Override @Override
public boolean checkStateAndTriggered() { public boolean checkStateAndTriggered() {
boolean trigger = !getTurn().isEndTurnRequested(); boolean trigger = !getTurn().isEndTurnRequested();
@ -1419,6 +1427,13 @@ public abstract class GameImpl implements Game, Serializable {
return played; return played;
} }
/**
* 116.5. Each time a player would get priority, the game first performs all applicable state-based actions as a single event (see rule 704,
* State-Based Actions), then repeats this process until no state-based actions are performed. Then triggered abilities are put on the stack
* (see rule 603, Handling Triggered Abilities). These steps repeat in order until no further state-based actions are performed and no abilities
* trigger. Then the player who would have received priority does so.
* @return
*/
protected boolean checkStateBasedActions() { protected boolean checkStateBasedActions() {
boolean somethingHappened = false; boolean somethingHappened = false;

View file

@ -240,7 +240,6 @@ public class Spell implements StackObject, Card {
card.getCardType().add(CardType.CREATURE); card.getCardType().add(CardType.CREATURE);
card.getSubtype().remove("Aura"); card.getSubtype().remove("Aura");
} }
game.getState().handleSimultaneousEvent(game);
return ability.resolve(game); return ability.resolve(game);
} }
if (bestow) { if (bestow) {