From 0c1918e3f5398bfd202fe69cec67c3ea7b9df251 Mon Sep 17 00:00:00 2001 From: Susucre <34709007+Susucre@users.noreply.github.com> Date: Fri, 4 Aug 2023 04:34:11 +0200 Subject: [PATCH] Fix Keeper of the Mind (#10744) and add tests --- .../src/mage/cards/k/KeeperOfTheMind.java | 60 +++++++++----- .../cards/single/exo/KeeperOfTheMindTest.java | 78 +++++++++++++++++++ 2 files changed, 120 insertions(+), 18 deletions(-) create mode 100644 Mage.Tests/src/test/java/org/mage/test/cards/single/exo/KeeperOfTheMindTest.java diff --git a/Mage.Sets/src/mage/cards/k/KeeperOfTheMind.java b/Mage.Sets/src/mage/cards/k/KeeperOfTheMind.java index 887053918ae..ab93b50faf9 100644 --- a/Mage.Sets/src/mage/cards/k/KeeperOfTheMind.java +++ b/Mage.Sets/src/mage/cards/k/KeeperOfTheMind.java @@ -29,15 +29,17 @@ package mage.cards.k; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.Condition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.decorator.ConditionalActivatedAbility; import mage.abilities.effects.Effect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.SubType; +import mage.constants.Zone; import mage.filter.FilterOpponent; import mage.filter.predicate.ObjectSourcePlayer; import mage.filter.predicate.ObjectSourcePlayerPredicate; @@ -46,10 +48,11 @@ import mage.players.Player; import mage.target.TargetPlayer; import mage.target.targetadjustment.TargetAdjuster; +import java.util.Objects; import java.util.UUID; /** - * @author jeffwadsworth + * @author jeffwadsworth, Susucr */ public class KeeperOfTheMind extends CardImpl { @@ -64,7 +67,10 @@ public class KeeperOfTheMind extends CardImpl { // {U}, {tap}: Choose target opponent who had at least two more cards in hand than you did as you activated this ability. Draw a card. Effect effect = new DrawCardSourceControllerEffect(1); effect.setText("Choose target opponent who had at least two more cards in hand than you did as you activated this ability. Draw a card."); - Ability ability = new SimpleActivatedAbility(effect, new ManaCostsImpl<>("{U}")); + Ability ability = new ConditionalActivatedAbility( + Zone.BATTLEFIELD, effect, new ManaCostsImpl<>("{U}"), KeeperOfTheMindCondition.instance, + "{U}, {T}: Choose target opponent who had at least two more cards in " + + "hand than you did as you activated this ability. Draw a card."); ability.addCost(new TapSourceCost()); ability.setTargetAdjuster(KeeperOfTheMindAdjuster.instance); this.addAbility(ability); @@ -83,40 +89,38 @@ public class KeeperOfTheMind extends CardImpl { enum KeeperOfTheMindAdjuster implements TargetAdjuster { instance; - private static final FilterOpponent filter = new FilterOpponent(); - - static { - filter.add(new KeeperOfTheMindPredicate()); - } - @Override public void adjustTargets(Ability ability, Game game) { - Player activePlayer = game.getPlayer(game.getActivePlayerId()); - if (activePlayer == null) { + Player controller = game.getPlayer(ability.getControllerId()); + if (controller == null) { return; } ability.getTargets().clear(); + FilterOpponent filter = new FilterOpponent("opponent with two or more card in hand than you did as you activated this ability"); + filter.add(new KeeperOfTheMindPredicate(controller.getHand().size())); TargetPlayer target = new TargetPlayer(1, 1, false, filter); - target.setTargetController(activePlayer.getId()); + target.setTargetController(controller.getId()); ability.addTarget(target); } } class KeeperOfTheMindPredicate implements ObjectSourcePlayerPredicate { + private final int controllerHandSize; + + KeeperOfTheMindPredicate(int controllerHandSize) { + this.controllerHandSize = controllerHandSize; + } + @Override public boolean apply(ObjectSourcePlayer input, Game game) { Player targetPlayer = input.getObject(); - Player firstPlayer = game.getPlayer(game.getActivePlayerId()); - if (targetPlayer == null - || firstPlayer == null - || !firstPlayer.hasOpponent(targetPlayer.getId(), game)) { + if (targetPlayer == null) { return false; } int countHandTargetPlayer = targetPlayer.getHand().size(); - int countHandFirstPlayer = firstPlayer.getHand().size(); - return countHandTargetPlayer - 2 >= countHandFirstPlayer; + return countHandTargetPlayer - 2 >= controllerHandSize; } @Override @@ -124,3 +128,23 @@ class KeeperOfTheMindPredicate implements ObjectSourcePlayerPredicate { return "opponent who had at least two more cards in hand than you did as you activated this ability"; } } + +// Is there an opponent with 2 cards in hand for even try activation? +enum KeeperOfTheMindCondition implements Condition { + instance; + + @Override + public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + + int handSize = controller.getHand().size(); + return game.getOpponents(controller.getId()) + .stream() + .map(game::getPlayer) + .filter(Objects::nonNull) + .anyMatch(player -> player.getHand().size() - 2 >= handSize); + } +} diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/exo/KeeperOfTheMindTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/exo/KeeperOfTheMindTest.java new file mode 100644 index 00000000000..1c49362aed5 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/exo/KeeperOfTheMindTest.java @@ -0,0 +1,78 @@ +package org.mage.test.cards.single.exo; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author Susucr + */ +public class KeeperOfTheMindTest extends CardTestPlayerBase { + // Keeper of the Mind {U}{U} + // Creature — Human Wizard + // {U}, {T}: Choose target opponent who had at least two more cards + // in hand than you did as you activated this ability. Draw a card. + private static final String keeper = "Keeper of the Mind"; + + @Test + public void simpleActivate() { + addCard(Zone.BATTLEFIELD, playerA, "Island", 1); + addCard(Zone.BATTLEFIELD, playerA, keeper, 1); + addCard(Zone.HAND, playerB, "Island", 2); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{U}, {T}: Choose target opponent "); + + // setStrictChooseMode(true); // targetting is weird due to targetAdjuster. + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertHandCount(playerA, 1); + } + + @Test + public void activateOtherPlayerTurn() { + addCard(Zone.BATTLEFIELD, playerA, "Island", 1); + addCard(Zone.BATTLEFIELD, playerA, keeper, 1); + addCard(Zone.HAND, playerB, "Island", 2); + + activateAbility(2, PhaseStep.UPKEEP, playerA, "{U}, {T}: Choose target opponent "); + + // setStrictChooseMode(true); // targetting is weird due to targetAdjuster. + setStopAt(2, PhaseStep.DRAW); + execute(); + + assertHandCount(playerA, 1); + } + + @Test + public void cantActivateIfCardDifferenceTooLow() { + addCard(Zone.BATTLEFIELD, playerA, "Island", 1); + addCard(Zone.BATTLEFIELD, playerA, keeper, 1); + addCard(Zone.HAND, playerB, "Island", 1); + + checkPlayableAbility("No Activation", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "{U}, {T}: Choose target opponent ", false); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertHandCount(playerA, 0); + } + + @Test + public void doubleActivate() { + addCard(Zone.BATTLEFIELD, playerA, "Island", 2); + addCard(Zone.BATTLEFIELD, playerA, keeper, 2); + addCard(Zone.HAND, playerB, "Island", 2); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{U}, {T}: Choose target opponent "); + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{U}, {T}: Choose target opponent "); + + // setStrictChooseMode(true); // targetting is weird due to targetAdjuster. + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertHandCount(playerA, 2); + } +}