Fixed a bug that triggred abilities of permanents that were controlled by a player that is not the owner could sometime trigger for a wrong player (Fixes #271).

This commit is contained in:
LevelX2 2013-09-14 17:20:45 +02:00
parent 0751b934ac
commit 857da3a08a
5 changed files with 66 additions and 15 deletions

View file

@ -53,9 +53,17 @@ public class UndyingTest extends CardTestPlayerBase {
*/
@Test
public void testUndyingEvil() {
// Elite Vanguard
// Creature Human Soldier 2/1
addCard(Zone.BATTLEFIELD, playerA, "Elite Vanguard");
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
// Last Gasp
// Instant, 1B
// Target creature gets -3/-3 until end of turn.
addCard(Zone.HAND, playerA, "Last Gasp");
// Undying Evil
// Target creature gains undying until end of turn.
// When it dies, if it had no +1/+1 counters on it, return it to the battlefield under its owner's control with a +1/+1 counter on it.)
addCard(Zone.HAND, playerA, "Undying Evil");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Last Gasp", "Elite Vanguard");

View file

@ -50,8 +50,19 @@ public class SorinLordOfInnistradTest extends CardTestPlayerBase {
@Test
public void testCard3() {
// Sorin, Lord of Innistrad English
// Planeswalker Sorin (Loyalty: 3), 2WB
// +1: Put a 1/1 black Vampire creature token with lifelink onto the battlefield.
// -2: You get an emblem with "Creatures you control get +1/+0."
// -6: Destroy up to three target creatures and/or other planeswalkers. Return each card put into a graveyard this way to the battlefield under your control.
addCard(Zone.BATTLEFIELD, playerA, "Sorin, Lord of Innistrad");
// Craw Wurm
// Creature Wurm 6/4, 4GG
addCard(Zone.BATTLEFIELD, playerB, "Craw Wurm");
// Angel of Mercy English
// Creature Angel 3/3, 4W (5)
// Flying
// When Angel of Mercy enters the battlefield, you gain 3 life.
addCard(Zone.BATTLEFIELD, playerB, "Angel of Mercy");
addCounters(1, PhaseStep.UPKEEP, playerA, "Sorin, Lord of Innistrad", CounterType.LOYALTY, 3);
@ -62,8 +73,9 @@ public class SorinLordOfInnistradTest extends CardTestPlayerBase {
assertPermanentCount(playerA, "Craw Wurm", 1);
assertPermanentCount(playerA, "Angel of Mercy", 1);
assertLife(playerA, 23);
assertLife(playerB, 20);
assertLife(playerA, 23);
assertPermanentCount(playerA, "Sorin, Lord of Innistrad", 0);
assertPermanentCount(playerB, "Craw Wurm", 0);
assertPermanentCount(playerB, "Angel of Mercy", 0);

View file

@ -36,6 +36,7 @@ import java.util.List;
import java.util.Map;
import java.util.UUID;
import mage.MageObject;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
@ -64,7 +65,13 @@ public class TriggeredAbilities extends HashMap<String, TriggeredAbility> {
public void checkTriggers(GameEvent event, Game game) {
for (TriggeredAbility ability: this.values()) {
if (ability.isInUseableZone(game, null, true)) {
MageObject object = getMageObject(event, game, ability);
MageObject object = null;
if (!ability.getZone().equals(Zone.COMMAND) && !game.getState().getZone(ability.getSourceId()).equals(ability.getZone())) {
object = game.getShortLivingLKI(ability.getSourceId(), ability.getZone());
}
if (object == null) {
object = getMageObject(event, game, ability);
}
if (object != null) {
if (checkAbilityStillExists(ability, event, object)) {
if (object instanceof Permanent) {

View file

@ -127,9 +127,9 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
protected transient TableEventSource tableEventSource = new TableEventSource();
protected transient PlayerQueryEventSource playerQueryEventSource = new PlayerQueryEventSource();
protected Map<UUID, Card> gameCards = new HashMap<UUID, Card>();
protected Map<UUID, MageObject> lki = new HashMap<UUID, MageObject>();
protected Map<UUID, MageObject> shortLivingLKI = new HashMap<UUID, MageObject>();
protected Map<UUID, Card> gameCards = new HashMap<UUID, Card>();
protected Map<Zone,HashMap<UUID, MageObject>> lki = new EnumMap<Zone, HashMap<UUID, MageObject>>(Zone.class);
protected Map<Zone,HashMap<UUID, MageObject>> shortLivingLKI = new EnumMap<Zone, HashMap<UUID, MageObject>>(Zone.class);
protected GameState state;
protected Date startTime;
@ -1763,18 +1763,24 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
/*if (!lki.containsKey(objectId)) {
return getCard(objectId);
}*/
MageObject object = lki.get(objectId);
if (object != null) {
return object.copy();
Map<UUID, MageObject> lkiMap = lki.get(zone);
if (lkiMap != null) {
MageObject object = lkiMap.get(objectId);
if (object != null) {
return object.copy();
}
}
return null;
}
@Override
public MageObject getShortLivingLKI(UUID objectId, Zone zone) {
MageObject object = shortLivingLKI.get(objectId);
if (object != null) {
return object.copy();
Map<UUID, MageObject> shortLivingLkiMap = shortLivingLKI.get(zone);
if (shortLivingLkiMap != null) {
MageObject object = shortLivingLkiMap.get(objectId);
if (object != null) {
return object.copy();
}
}
return null;
}
@ -1790,8 +1796,24 @@ public abstract class GameImpl<T extends GameImpl<T>> implements Game, Serializa
public void rememberLKI(UUID objectId, Zone zone, MageObject object) {
if (object instanceof Permanent || object instanceof StackObject) {
MageObject copy = object.copy();
lki.put(objectId, copy);
shortLivingLKI.put(objectId, copy);
Map<UUID, MageObject> lkiMap = lki.get(zone);
if (lkiMap != null) {
lkiMap.put(objectId, copy);
} else {
HashMap<UUID, MageObject> newMap = new HashMap<UUID, MageObject>();
newMap.put(objectId, copy);
lki.put(zone, newMap);
}
Map<UUID, MageObject> shortLivingLkiMap = shortLivingLKI.get(zone);
if (shortLivingLkiMap != null) {
shortLivingLkiMap.put(objectId, copy);
} else {
HashMap<UUID, MageObject> newMap = new HashMap<UUID, MageObject>();
newMap.put(objectId, copy);
shortLivingLKI.put(zone, newMap);
}
}
}

View file

@ -185,6 +185,7 @@ public class PermanentCard extends PermanentImpl<PermanentCard> {
Player owner = game.getPlayer(ownerId);
game.rememberLKI(objectId, Zone.BATTLEFIELD, this);
if (owner != null) {
this.setControllerId(ownerId); // neccessary for e.g. abilities in graveyard or hand to not have a controller != owner
switch (event.getToZone()) {
case GRAVEYARD:
owner.putInGraveyard(card, game, !flag);
@ -199,10 +200,11 @@ public class PermanentCard extends PermanentImpl<PermanentCard> {
game.addCommander(new Commander(card));
break;
case LIBRARY:
if (flag)
if (flag) {
owner.getLibrary().putOnTop(card, game);
else
} else {
owner.getLibrary().putOnBottom(card, game);
}
break;
case BATTLEFIELD:
//should never happen