* 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, "Thatcher Revolt", 1);
// Creature - Demon 5/5 {4}{B}{B}
// Deathtouch
// Whenever another nontoken creature dies, you may draw a card.
addCard(Zone.BATTLEFIELD, playerA, "Harvester of Souls", 1);
// Creature - Wurm 6/4 {4}{G}{G}
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.
addCard(Zone.BATTLEFIELD, playerB, "Arrogant Bloodlord", 1);
@ -42,7 +45,7 @@ public class HarvesterOfSoulsTest extends CardTestPlayerBase {
assertLife(playerA, 20);
assertLife(playerB, 20);
assertHandCount(playerA, 2);
assertHandCount(playerA, 2); // draw a card for Harvester and Craw Wurm
assertHandCount(playerB, 0);
}

View file

@ -7,7 +7,6 @@ package org.mage.test.cards.triggers.state;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.counters.CounterType;
import org.junit.Test;
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, "Bottle Gnomes");
addCard(Zone.HAND, playerA, "Cloudshift");
// When you control no other artifacts, sacrifice Synod Centurion.
addCard(Zone.HAND, 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("\\^");
boolean targetFound = false;
for (String targetName: targetList) {
boolean allowCopy = true;
if (targetName.endsWith("[no copy]")) {
allowCopy = false;
targetName = targetName.substring(0, targetName.length()-9);
boolean originOnly = false;
boolean copyOnly = false;
if (targetName.endsWith("]")) {
if (targetName.endsWith("[no copy]")) {
originOnly = true;
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)) {
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 (!permanent.isCopy() || allowCopy) {
if ((permanent.isCopy() && !originOnly) || (!permanent.isCopy() && !copyOnly )) {
target.add(permanent.getId(), game);
targetFound = true;
break;

View file

@ -861,7 +861,8 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* e.g. "creatureName1^creatureName2"
* you can qualify the target additional by setcode
* 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) {
player.addTarget(target);

View file

@ -1207,7 +1207,6 @@ public abstract class GameImpl implements Game, Serializable {
if (!getTurn().isEndTurnRequested()) {
while (state.hasSimultaneousEvents()) {
state.handleSimultaneousEvent(this);
checkTriggered();
}
}
}
@ -1356,6 +1355,15 @@ public abstract class GameImpl implements Game, Serializable {
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
public boolean checkStateAndTriggered() {
boolean trigger = !getTurn().isEndTurnRequested();
@ -1419,6 +1427,13 @@ public abstract class GameImpl implements Game, Serializable {
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() {
boolean somethingHappened = false;

View file

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