From 734bd6f1187afae8ca76c6d71a02567678d04728 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Sun, 4 Apr 2021 13:19:15 -0400 Subject: [PATCH] fixed Blatant Thievery test failure --- .../src/mage/cards/b/BlatantThievery.java | 44 ++++++++++++- .../src/mage/cards/t/TemptedByTheOriq.java | 47 ++++++++++++-- .../test/multiplayer/BlatantThieveryTest.java | 3 + .../continuous/GainControlTargetEffect.java | 65 ++++++++++--------- 4 files changed, 121 insertions(+), 38 deletions(-) diff --git a/Mage.Sets/src/mage/cards/b/BlatantThievery.java b/Mage.Sets/src/mage/cards/b/BlatantThievery.java index 5684259373..95eebac7c8 100644 --- a/Mage.Sets/src/mage/cards/b/BlatantThievery.java +++ b/Mage.Sets/src/mage/cards/b/BlatantThievery.java @@ -1,20 +1,29 @@ package mage.cards.b; import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.GainControlTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; +import mage.constants.Outcome; import mage.filter.FilterPermanent; import mage.filter.StaticFilters; import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; +import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.Target; import mage.target.TargetPermanent; import mage.target.targetadjustment.TargetAdjuster; +import mage.target.targetpointer.FixedTargets; +import java.util.Collection; +import java.util.List; +import java.util.Objects; import java.util.UUID; +import java.util.stream.Collectors; /** * @author emerald000 @@ -25,8 +34,7 @@ public final class BlatantThievery extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{U}{U}{U}"); // For each opponent, gain control of target permanent that player controls. - this.getSpellAbility().addEffect(new GainControlTargetEffect(Duration.EndOfGame) - .setText("for each opponent, gain control of target permanent that player controls")); + this.getSpellAbility().addEffect(new BlatantThieveryEffect()); this.getSpellAbility().setTargetAdjuster(BlatantThieveryAdjuster.instance); } @@ -61,3 +69,35 @@ enum BlatantThieveryAdjuster implements TargetAdjuster { } } } + +class BlatantThieveryEffect extends OneShotEffect { + + BlatantThieveryEffect() { + super(Outcome.Benefit); + staticText = "for each opponent, gain control of target permanent that player controls"; + } + + private BlatantThieveryEffect(final BlatantThieveryEffect effect) { + super(effect); + } + + @Override + public BlatantThieveryEffect copy() { + return new BlatantThieveryEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + List permanents = source + .getTargets() + .stream() + .map(Target::getTargets) + .flatMap(Collection::stream) + .map(game::getPermanent) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + game.addEffect(new GainControlTargetEffect(Duration.Custom, true) + .setTargetPointer(new FixedTargets(permanents, game)), source); + return true; + } +} diff --git a/Mage.Sets/src/mage/cards/t/TemptedByTheOriq.java b/Mage.Sets/src/mage/cards/t/TemptedByTheOriq.java index 20c0f11967..28a43b1259 100644 --- a/Mage.Sets/src/mage/cards/t/TemptedByTheOriq.java +++ b/Mage.Sets/src/mage/cards/t/TemptedByTheOriq.java @@ -1,22 +1,31 @@ package mage.cards.t; import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.continuous.GainControlTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.ComparisonType; import mage.constants.Duration; +import mage.constants.Outcome; import mage.filter.FilterPermanent; import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent; import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.Game; +import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.Target; import mage.target.TargetPermanent; import mage.target.targetadjustment.TargetAdjuster; +import mage.target.targetpointer.FixedTargets; +import java.util.Collection; +import java.util.List; +import java.util.Objects; import java.util.UUID; +import java.util.stream.Collectors; /** * @author TheElk801 @@ -27,10 +36,7 @@ public final class TemptedByTheOriq extends CardImpl { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{U}{U}{U}"); // For each opponent, gain control of up to one target creature or planeswalker that player controls with mana value 3 or less. - this.getSpellAbility().addEffect(new GainControlTargetEffect(Duration.EndOfGame).setText( - "for each opponent, gain control of up to one target creature or planeswalker " + - "that player controls with mana value 3 or less" - )); + this.getSpellAbility().addEffect(new TemptedByTheOriqEffect()); this.getSpellAbility().setTargetAdjuster(TemptedByTheOriqAdjuster.instance); } @@ -64,3 +70,36 @@ enum TemptedByTheOriqAdjuster implements TargetAdjuster { } } } + +class TemptedByTheOriqEffect extends OneShotEffect { + + TemptedByTheOriqEffect() { + super(Outcome.Benefit); + staticText = "for each opponent, gain control of up to one target creature " + + "or planeswalker that player controls with mana value 3 or less"; + } + + private TemptedByTheOriqEffect(final TemptedByTheOriqEffect effect) { + super(effect); + } + + @Override + public TemptedByTheOriqEffect copy() { + return new TemptedByTheOriqEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + List permanents = source + .getTargets() + .stream() + .map(Target::getTargets) + .flatMap(Collection::stream) + .map(game::getPermanent) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + game.addEffect(new GainControlTargetEffect(Duration.Custom, true) + .setTargetPointer(new FixedTargets(permanents, game)), source); + return true; + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/multiplayer/BlatantThieveryTest.java b/Mage.Tests/src/test/java/org/mage/test/multiplayer/BlatantThieveryTest.java index 9ed8d48545..300e7964ef 100644 --- a/Mage.Tests/src/test/java/org/mage/test/multiplayer/BlatantThieveryTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/multiplayer/BlatantThieveryTest.java @@ -45,8 +45,10 @@ public class BlatantThieveryTest extends CardTestMultiPlayerBase { addTarget(playerA, "Walking Corpse"); addTarget(playerA, "Pillarfield Ox"); + setStrictChooseMode(true); setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); + assertAllCommandsUsed(); assertGraveyardCount(playerA, "Blatant Thievery", 1); assertPermanentCount(playerA, "Silvercoat Lion", 1); @@ -79,6 +81,7 @@ public class BlatantThieveryTest extends CardTestMultiPlayerBase { setStopAt(1, PhaseStep.BEGIN_COMBAT); execute(); + assertAllCommandsUsed(); assertGraveyardCount(playerA, "Blatant Thievery", 1); assertGraveyardCount(playerB, "Act of Aggression", 1); diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainControlTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainControlTargetEffect.java index da5aef9bda..ad66fc7eee 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/GainControlTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/GainControlTargetEffect.java @@ -9,7 +9,6 @@ import mage.constants.Layer; import mage.constants.Outcome; import mage.constants.SubLayer; import mage.game.Game; -import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.Target; @@ -76,42 +75,44 @@ public class GainControlTargetEffect extends ContinuousEffectImpl { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - boolean oneTargetStillExists = false; - for (UUID permanentId : getTargetPointer().getTargets(game, source)) { - Permanent permanent = game.getPermanent(permanentId); - if (permanent != null) { - oneTargetStillExists = true; - if (!permanent.isControlledBy(controllingPlayerId)) { - boolean controlChanged = false; - if (controllingPlayerId != null) { - if (permanent.changeControllerId(controllingPlayerId, game, source)) { - controlChanged = true; - } - } else { - if (permanent.changeControllerId(source.getControllerId(), game, source)) { - controlChanged = true; - } - } - if (source instanceof ActivatedAbility - && firstControlChange && !controlChanged) { - // If it was not possible to get control of target permanent by the activated ability the first time it took place - // the effect failed (e.g. because of Guardian Beast) and must be discarded - // This does not handle correctly multiple targets at once - discard(); - } - } + if (controller == null) { + discard(); // controller no longer exists + return false; + } + boolean oneTargetStillExists = false; + for (UUID permanentId : getTargetPointer().getTargets(game, source)) { + Permanent permanent = game.getPermanent(permanentId); + if (permanent == null) { + continue; + } + oneTargetStillExists = true; + if (permanent.isControlledBy(controllingPlayerId)) { + continue; + } + boolean controlChanged = false; + if (controllingPlayerId != null) { + if (permanent.changeControllerId(controllingPlayerId, game, source)) { + controlChanged = true; + } + } else { + if (permanent.changeControllerId(source.getControllerId(), game, source)) { + controlChanged = true; } } - // no valid target exists and the controller is no longer in the game, effect can be discarded - if (!oneTargetStillExists || !controller.isInGame()) { + if (source instanceof ActivatedAbility + && firstControlChange && !controlChanged) { + // If it was not possible to get control of target permanent by the activated ability the first time it took place + // the effect failed (e.g. because of Guardian Beast) and must be discarded + // This does not handle correctly multiple targets at once discard(); } - firstControlChange = false; - return true; } - discard(); // controller no longer exists - return false; + // no valid target exists and the controller is no longer in the game, effect can be discarded + if (!oneTargetStillExists || !controller.isInGame()) { + discard(); + } + firstControlChange = false; + return true; } @Override