Fixed that a planeswalker that left the battlefield was not correctly removed from combat.

This commit is contained in:
LevelX2 2016-02-25 21:41:38 +01:00
parent ff298938c1
commit 9f35637e6d
4 changed files with 68 additions and 12 deletions

View file

@ -127,4 +127,41 @@ public class ItThatBetraysTest extends CardTestPlayerBase {
assertGraveyardCount(playerA, "Spreading Seas", 0);
assertPermanentCount(playerB, "Spreading Seas", 1);
}
/**
* It That Betrays had a strange bug. Attacked opponent's planeswalker with
* him (I think it was Venser, the Sojourner), then opponent sacrificed said
* planeswalker to ITB (It That Betrays) annihilator ability, ITB ability
* triggered and Venser came over to my control, but ITB was still attacking
* my own planeswalker and killed it. Shouldn't happen because that's an
* entirely new planeswalker, not the one I was attacking. That one died,
* therefore the attack was invalid.
*/
@Test
public void testExileAttackedPlaneswalker() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
// +2: Exile target permanent you own. Return it to the battlefield under your control at the beginning of the next end step.
// -1: Creatures can't be blocked this turn.
// -8: You get an emblem with "Whenever you cast a spell, exile target permanent."
addCard(Zone.BATTLEFIELD, playerA, "Venser, the Sojourner", 1);
// Annihilator 2 (Whenever this creature attacks, defending player sacrifices two permanents.)
// Whenever an opponent sacrifices a nontoken permanent, put that card onto the battlefield under your control.
addCard(Zone.BATTLEFIELD, playerB, "It That Betrays"); // 11/11
attack(2, playerB, "It That Betrays", "Venser, the Sojourner");
setChoice(playerA, "Venser, the Sojourner");
setChoice(playerA, "Mountain");
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerA, 20);
assertLife(playerB, 20);
// Player B now controls a Silvercoat Lion and Spreading Seas
assertPermanentCount(playerB, "Venser, the Sojourner", 1);
assertPermanentCount(playerB, "Mountain", 1);
}
}

View file

@ -1110,6 +1110,17 @@ public class Combat implements Serializable, Copyable<Combat> {
}
}
public boolean removePlaneswalkerFromCombat(UUID planeswalkerId, Game game, boolean withInfo) {
boolean result = false;
for (CombatGroup group : groups) {
if (group.getDefenderId().equals(planeswalkerId)) {
group.removeAttackedPlaneswalker(planeswalkerId);
result = true;
}
}
return result;
}
public boolean removeFromCombat(UUID creatureId, Game game, boolean withInfo) {
boolean result = false;
Permanent creature = game.getPermanent(creatureId);

View file

@ -503,19 +503,25 @@ public class CombatGroup implements Serializable, Copyable<CombatGroup> {
return defenderIsPlaneswalker;
}
public boolean removeAttackedPlaneswalker(UUID planeswalkerId) {
if (defenderIsPlaneswalker && defenderId.equals(planeswalkerId)) {
defenderId = null;
return true;
}
return false;
}
public boolean remove(UUID creatureId) {
boolean result = false;
if (attackers.contains(creatureId)) {
attackers.remove(creatureId);
result = true;
} else {
if (blockers.contains(creatureId)) {
blockers.remove(creatureId);
result = true;
//20100423 - 509.2a
if (blockerOrder.contains(creatureId)) {
blockerOrder.remove(creatureId);
}
} else if (blockers.contains(creatureId)) {
blockers.remove(creatureId);
result = true;
//20100423 - 509.2a
if (blockerOrder.contains(creatureId)) {
blockerOrder.remove(creatureId);
}
}
return result;

View file

@ -1091,10 +1091,8 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
if (!oneCanBeAttacked) {
return false;
}
} else {
if (!canAttackCheckRestrictionEffects(defenderId, game)) {
return false;
}
} else if (!canAttackCheckRestrictionEffects(defenderId, game)) {
return false;
}
return !abilities.containsKey(DefenderAbility.getInstance().getId())
@ -1223,6 +1221,10 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
public boolean removeFromCombat(Game game, boolean withInfo) {
if (this.isAttacking() || this.blocking > 0) {
return game.getCombat().removeFromCombat(objectId, game, withInfo);
} else if (getCardType().contains(CardType.PLANESWALKER)) {
if (game.getCombat().getDefenders().contains(getId())) {
game.getCombat().removePlaneswalkerFromCombat(objectId, game, withInfo);
}
}
return false;
}