* Guilded Drake - Fixed that the sacrifice did not happen if the target creature for exchange is no longer a valid target during resolution (fixes #1546).

This commit is contained in:
LevelX2 2016-02-21 10:20:26 +01:00
parent ea5c825897
commit cf3488d5e5
8 changed files with 80 additions and 22 deletions

View file

@ -70,8 +70,10 @@ public class GildedDrake extends CardImpl {
// Flying
this.addAbility(FlyingAbility.getInstance());
// When Gilded Drake enters the battlefield, exchange control of Gilded Drake and up to one target creature an opponent controls. If you don't make an exchange, sacrifice Gilded Drake. This ability can't be countered except by spells and abilities.
// When Gilded Drake enters the battlefield, exchange control of Gilded Drake and up to one target creature an opponent controls. If you don't make an exchange, sacrifice Gilded Drake.
// This ability can't be countered except by spells and abilities.
Ability ability = new EntersBattlefieldTriggeredAbility(new GildedDrakeEffect());
ability.setCanFizzle(false);
ability.addTarget(new TargetCreaturePermanent(0, 1, filter, false));
this.addAbility(ability);
}

View file

@ -117,13 +117,13 @@ class MarchesaTheBlackRoseTriggeredAbility extends TriggeredAbilityImpl {
public boolean checkTrigger(GameEvent event, Game game) {
if (((ZoneChangeEvent) event).getToZone() == Zone.GRAVEYARD
&& ((ZoneChangeEvent) event).getFromZone() == Zone.BATTLEFIELD) {
Permanent permanent = (Permanent) game.getLastKnownInformation(event.getTargetId(), Zone.BATTLEFIELD);
Permanent permanent = ((ZoneChangeEvent) event).getTarget();
if (permanent != null
&& permanent.getControllerId().equals(this.getControllerId())
&& permanent.getCardType().contains(CardType.CREATURE)
&& permanent.getCounters().getCount(CounterType.P1P1) > 0) {
for (Effect effect : this.getEffects()) {
effect.setTargetPointer(new FixedTarget(permanent.getId()));
effect.setTargetPointer(new FixedTarget(permanent.getId(), permanent.getZoneChangeCounter(game) + 1));
}
return true;
}

View file

@ -35,7 +35,8 @@ public class ExchangeControlTest extends CardTestPlayerBase {
}
/**
* Tests switching control for two creature on one side (both creatures are under the same player's control)
* Tests switching control for two creature on one side (both creatures are
* under the same player's control)
*
* Also tests "7/1/2012: You don't have to control either target."
*/
@ -61,8 +62,8 @@ public class ExchangeControlTest extends CardTestPlayerBase {
}
/**
* Tests:
* 7/1/2012: If one of the target creatures is an illegal target when Switcheroo resolves, the exchange won't happen.
* Tests: 7/1/2012: If one of the target creatures is an illegal target when
* Switcheroo resolves, the exchange won't happen.
*
* Targets opponent's creature
*/
@ -90,10 +91,10 @@ public class ExchangeControlTest extends CardTestPlayerBase {
}
/**
* Tests:
* 7/1/2012: If one of the target creatures is an illegal target when Switcheroo resolves, the exchange won't happen.
* Tests: 7/1/2012: If one of the target creatures is an illegal target when
* Switcheroo resolves, the exchange won't happen.
*
* Targets its own creature.
* Targets its own creature.
*/
@Test
public void testOneTargetBecomesIllegal2() {
@ -119,8 +120,8 @@ public class ExchangeControlTest extends CardTestPlayerBase {
}
/**
* First gain control by Act of Treason.
* Then exchange control with other opponent's creature.
* First gain control by Act of Treason. Then exchange control with other
* opponent's creature.
*
* Finally second creature should stay under ours control permanently.
*/
@ -183,9 +184,10 @@ public class ExchangeControlTest extends CardTestPlayerBase {
}
/**
* An control exchanged creature gets an copy effect from
* an creature with an activated ability to the by exchange controlled creature.
* Check that the activated ability is controlled by the new controller of the copy target.
* An control exchanged creature gets an copy effect from an creature with
* an activated ability to the by exchange controlled creature. Check that
* the activated ability is controlled by the new controller of the copy
* target.
*/
@Test
public void testExchangeAnCopyEffect() {
@ -208,7 +210,7 @@ public class ExchangeControlTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Gilded Drake");
addTarget(playerA, "Silvercoat Lion");
// Let your Silvercoat Lion now be a copy of the Manta Riders
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Polymorphous Rush","Silvercoat Lion");
castSpell(1, PhaseStep.BEGIN_COMBAT, playerA, "Polymorphous Rush", "Silvercoat Lion");
addTarget(playerA, "Manta Riders");
// now use the activated ability to make the "Silvercoat Lions" (that became Mana Riders) flying
@ -229,10 +231,43 @@ public class ExchangeControlTest extends CardTestPlayerBase {
assertPermanentCount(playerB, "Manta Riders", 1);
assertPermanentCount(playerA, "Manta Riders", 1);
Permanent controlledMantas = getPermanent("Manta Riders", playerA.getId());
Assert.assertTrue("Manta Riders should have flying ability", controlledMantas.getAbilities().contains(FlyingAbility.getInstance()));
}
/**
* Gilded Drake doesn't get sacrificed if the creature its ability targets
* is invalid when it enters the battlefield
*/
@Test
public void testDrakeSacrificedIfNoExchangeHappens() {
addCard(Zone.BATTLEFIELD, playerA, "Island", 6);
// Gilded Drake {1}{U} Creature - Drake
// Flying
// When Gilded Drake enters the battlefield, exchange control of Gilded Drake and up to one target
// creature an opponent controls. If you don't make an exchange, sacrifice Gilded Drake. This ability
// can't be countered except by spells and abilities. (This effect lasts indefinitely.)
addCard(Zone.HAND, playerA, "Gilded Drake");
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion");
addCard(Zone.BATTLEFIELD, playerB, "Mountain");
addCard(Zone.HAND, playerB, "Lightning Bolt");
// exchange control between Gilded Drake and Silvercoat Lion
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Gilded Drake");
addTarget(playerA, "Silvercoat Lion");
// Destroy Silvercoat Lion before the exchange resolves so the Drake has to be sacrificed
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Lightning Bolt", "Silvercoat Lion", "When");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerB, "Lightning Bolt", 1);
assertGraveyardCount(playerB, "Silvercoat Lion", 1);
assertGraveyardCount(playerA, "Gilded Drake", 1);
}
}

View file

@ -59,7 +59,7 @@ public class ReturnToBattlefieldEffectsTest extends CardTestPlayerBase {
}
/**
* That that the creature with a +1/+1 counter returns
* Test that the creature with a +1/+1 counter returns
*/
@Test
public void testMarchesatheBlackRose() {

View file

@ -568,4 +568,8 @@ public interface Ability extends Controllable, Serializable {
MageObject getSourceObjectIfItStillExists(Game game);
String getTargetDescription(Targets targets, Game game);
void setCanFizzle(boolean canFizzle);
boolean canFizzle();
}

View file

@ -114,6 +114,7 @@ public abstract class AbilityImpl implements Ability {
protected int sourceObjectZoneChangeCounter;
protected List<Watcher> watchers = null;
protected List<Ability> subAbilities = null;
protected boolean canFizzle = true;
public AbilityImpl(AbilityType abilityType, Zone zone) {
this.id = UUID.randomUUID();
@ -164,6 +165,7 @@ public abstract class AbilityImpl implements Ability {
this.abilityWord = ability.abilityWord;
this.sourceObject = ability.sourceObject;
this.sourceObjectZoneChangeCounter = ability.sourceObjectZoneChangeCounter;
this.canFizzle = ability.canFizzle;
}
@Override
@ -1222,4 +1224,14 @@ public abstract class AbilityImpl implements Ability {
this.sourceObjectZoneChangeCounter = game.getState().getZoneChangeCounter(sourceId);
}
@Override
public boolean canFizzle() {
return canFizzle;
}
@Override
public void setCanFizzle(boolean canFizzle) {
this.canFizzle = canFizzle;
}
}

View file

@ -1486,10 +1486,6 @@ public abstract class GameImpl implements Game, Serializable {
} else {
TriggeredAbility newAbility = ability.copy();
newAbility.newId();
// Too early, because no targets set yet !!!!!!!!!!!
for (Effect effect : newAbility.getEffects()) {
effect.getTargetPointer().init(this, newAbility);
}
state.addTriggeredAbility(newAbility);
}
}

View file

@ -104,7 +104,7 @@ public class StackAbility extends StackObjImpl implements Ability {
@Override
public boolean resolve(Game game) {
if (ability.getTargets().stillLegal(ability, game)) {
if (ability.getTargets().stillLegal(ability, game) || !canFizzle()) {
boolean result = ability.resolve(game);
game.getStack().remove(this);
return result;
@ -581,4 +581,13 @@ public class StackAbility extends StackObjImpl implements Ability {
return getAbilities().get(0).getTargetDescription(targets, game);
}
@Override
public boolean canFizzle() {
return ability.canFizzle();
}
@Override
public void setCanFizzle(boolean canFizzle) {
throw new UnsupportedOperationException("Not supported.");
}
}