Repository: magefree/mage (Java)

Issue:
Sacrifice from evoke doesn't resolve when control of creature changes
I had a [[Confusion in the Ranks]] out. I evoked an [[Ingot Chewer]], with the sacrifice from evoke on the bottom of the stack, resolving last of the 3 triggers. I exchanged control of the Chewer with one of my opponent's creatures, but the sacrifice never then happened once it was under their control.


Discussion: **[Confusion in the Ranks](https://cards.scryfall.io/normal/front/9/d/9d46aca2-4714-4d2c-9466-5f1c043b8726.jpg?1562152213)** - [(Gatherer)](https://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=49528&printed=false) [(Scryfall)](https://scryfall.com/card/mrd/87/confusion-in-the-ranks?utm_source=api) [(EDHREC)](https://edhrec.com/route/?cc=Confusion+in+the+Ranks)
> {3}{R}{R}
> Enchantment
> Whenever an artifact, creature, or enchantment enters the battlefield, its controller chooses target permanent another player controls that shares a card type with it. Exchange control of those permanents.

**[Ingot Chewer](https://cards.scryfall.io/normal/front/f/8/f84b4b61-0e92-4ca2-b4e0-ae846a2a8e37.jpg?1547517288)** - [(Gatherer)](https://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=456731&printed=false) [(Scryfall)](https://scryfall.com/card/uma/135/ingot-chewer?utm_source=api) [(EDHREC)](https://edhrec.com/route/?cc=Ingot+Chewer)
> {4}{R}
> Creature — Elemental
> 3/3
> When Ingot Chewer enters the battlefield, destroy target artifact.
> Evoke {R} (You may cast this spell for its evoke cost. If you do, it's sacrificed when it enters the battlefield.)
I believe that is correct behavior. You are the controller of the trigger that triggered when the Ingot Chewer enters. Control of the creature changes but the trigger does not.

> 701.17a. To sacrifice a permanent, its controller moves it from the battlefield directly to its owner's graveyard. **A player can't sacrifice something that isn't a permanent, or something that's a permanent they don't control**. Sacrificing a permanent doesn't destroy it, so regeneration or other effects that replace destruction can't affect this action.
Oh wait, didn't read the Evoke rules properly. Yeah, looks like Evoke is implemented incorrectly.

> 702.74a. Evoke represents two abilities: a static ability that functions in any zone from which the card with evoke can be cast and a triggered ability that functions on the battlefield. "Evoke [cost]" means "You may cast this card by paying [cost] rather than paying its mana cost" and "When this permanent enters the battlefield, if its evoke cost was paid, **its controller sacrifices it**." Casting a spell for its evoke cost follows the rules for paying alternative costs in rules 601.2b and 601.2f-h.



Fix (patch):
diff --git a/Mage/src/main/java/mage/abilities/common/SacrificeIfCastAtInstantTimeTriggeredAbility.java b/Mage/src/main/java/mage/abilities/common/SacrificeIfCastAtInstantTimeTriggeredAbility.java
index 8dc82bd667ad..913964d95004 100644
--- a/Mage/src/main/java/mage/abilities/common/SacrificeIfCastAtInstantTimeTriggeredAbility.java
+++ b/Mage/src/main/java/mage/abilities/common/SacrificeIfCastAtInstantTimeTriggeredAbility.java
@@ -8,7 +8,6 @@
 import mage.abilities.effects.common.SacrificeSourceEffect;
 import mage.constants.Zone;
 import mage.game.Game;
-import mage.game.events.GameEvent.EventType;
 import mage.game.events.GameEvent;
 import mage.game.stack.Spell;
 
@@ -18,7 +17,7 @@
 public class SacrificeIfCastAtInstantTimeTriggeredAbility extends TriggeredAbilityImpl {
 
     public SacrificeIfCastAtInstantTimeTriggeredAbility() {
-        super(Zone.STACK, new CreateDelayedTriggeredAbilityEffect(new AtTheBeginOfNextCleanupDelayedTriggeredAbility(new SacrificeSourceEffect())));
+        super(Zone.STACK, new CreateDelayedTriggeredAbilityEffect(new AtTheBeginOfNextCleanupDelayedTriggeredAbility(new SacrificeSourceEffect(true))));
     }
 
     protected SacrificeIfCastAtInstantTimeTriggeredAbility(final SacrificeIfCastAtInstantTimeTriggeredAbility ability) {
diff --git a/Mage/src/main/java/mage/abilities/effects/common/SacrificeSourceEffect.java b/Mage/src/main/java/mage/abilities/effects/common/SacrificeSourceEffect.java
index 3ec8d9ed3a70..c74c2318ea4f 100644
--- a/Mage/src/main/java/mage/abilities/effects/common/SacrificeSourceEffect.java
+++ b/Mage/src/main/java/mage/abilities/effects/common/SacrificeSourceEffect.java
@@ -13,13 +13,21 @@
  */
 public class SacrificeSourceEffect extends OneShotEffect {
 
+    private final boolean controllerSacrifices;
+
     public SacrificeSourceEffect() {
+        this(false);
+    }
+
+    public SacrificeSourceEffect(boolean controllerSacrifices) {
         super(Outcome.Sacrifice);
-        staticText = "sacrifice {this}";
+        this.controllerSacrifices = controllerSacrifices;
+        staticText = (controllerSacrifices ? "{this}'s controller sacrifices it" : "sacrifice {this}");
     }
 
     protected SacrificeSourceEffect(final SacrificeSourceEffect effect) {
         super(effect);
+        controllerSacrifices = effect.controllerSacrifices;
     }
 
     @Override
@@ -40,7 +48,7 @@ public boolean apply(Game game, Ability source) {
         if (sourceObject instanceof Permanent) {
             Permanent permanent = (Permanent) sourceObject;
             // you can only sacrifice a permanent you control
-            if (source.isControlledBy(permanent.getControllerId())) {
+            if (controllerSacrifices || source.isControlledBy(permanent.getControllerId())) {
                 return permanent.sacrifice(source, game);
             }
             return true;
diff --git a/Mage/src/main/java/mage/abilities/keyword/EvokeAbility.java b/Mage/src/main/java/mage/abilities/keyword/EvokeAbility.java
index be32bb39a97b..c14e5336849d 100644
--- a/Mage/src/main/java/mage/abilities/keyword/EvokeAbility.java
+++ b/Mage/src/main/java/mage/abilities/keyword/EvokeAbility.java
@@ -25,8 +25,8 @@ public EvokeAbility(String manaString) {
     public EvokeAbility(Cost cost) {
         super(EVOKE_KEYWORD, REMINDER_TEXT, cost);
         Ability ability = new ConditionalInterveningIfTriggeredAbility(
-                new EntersBattlefieldTriggeredAbility(new SacrificeSourceEffect()),
-                EvokedCondition.instance, "Sacrifice {this} when it enters the battlefield and was evoked.");
+                new EntersBattlefieldTriggeredAbility(new SacrificeSourceEffect(true)),
+                EvokedCondition.instance, "When this permanent enters the battlefield, if its evoke cost was paid, its controller sacrifices it.");
         ability.setRuleVisible(false);
         addSubAbility(ability);
     }