diff --git a/Mage.Sets/src/mage/cards/s/SeeTheTruth.java b/Mage.Sets/src/mage/cards/s/SeeTheTruth.java index d348423e466..90f898b9463 100644 --- a/Mage.Sets/src/mage/cards/s/SeeTheTruth.java +++ b/Mage.Sets/src/mage/cards/s/SeeTheTruth.java @@ -9,16 +9,17 @@ import mage.cards.CardsImpl; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Zone; +import mage.filter.FilterCard; import mage.game.Game; +import mage.game.stack.Spell; import mage.players.Player; import mage.target.common.TargetCardInLibrary; +import mage.watchers.common.SpellsCastWatcher; import java.util.UUID; -import mage.filter.FilterCard; -import mage.game.stack.Spell; /** - * @author TheElk801 + * @author TheElk801, Susucr */ public final class SeeTheTruth extends CardImpl { @@ -27,6 +28,7 @@ public final class SeeTheTruth extends CardImpl { // Look at the top three cards of your library. Put one of those cards into your hand and the rest on the bottom of your library in any order. If this spell was cast from anywhere other than your hand, put each of those cards into your hand instead. this.getSpellAbility().addEffect(new SeeTheTruthEffect()); + this.getSpellAbility().addWatcher(new SpellsCastWatcher()); } private SeeTheTruth(final SeeTheTruth card) { @@ -65,9 +67,13 @@ class SeeTheTruthEffect extends OneShotEffect { if (player == null || sourceSpell == null) { return false; } + + SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class); + boolean wasCast = watcher != null && watcher.getAllSpellsCastThisTurn().anyMatch(s -> s.getId().equals(source.getId())); + Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, 3)); if (!cards.isEmpty()) { - if (sourceSpell.isCopy() || Zone.HAND.equals(sourceSpell.getFromZone())) { // A copied spell was NOT cast at all + if (!wasCast || Zone.HAND.equals(sourceSpell.getFromZone())) { TargetCardInLibrary target = new TargetCardInLibrary(new FilterCard("card to put into your hand")); player.chooseTarget(outcome, cards, target, source, game); cards.removeIf(target.getFirstTarget()::equals); diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/m21/SeeTheTruthTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/m21/SeeTheTruthTest.java new file mode 100644 index 00000000000..80852bb961a --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/m21/SeeTheTruthTest.java @@ -0,0 +1,143 @@ +package org.mage.test.cards.single.m21; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +public class SeeTheTruthTest extends CardTestPlayerBase { + + // See the Truth {1}{U} + // Sorcery + // + // Look at the top three cards of your library. Put one of those cards into your hand and the rest on the bottom of your library in any order. If this spell was cast from anywhere other than your hand, put each of those cards into your hand instead. + private static final String seeTheTruth = "See the Truth"; + + @Test + public void castFromHand() { + setStrictChooseMode(true); + + addCard(Zone.LIBRARY, playerA, "Centaur Courser"); + addCard(Zone.LIBRARY, playerA, "Bear Cub"); + addCard(Zone.LIBRARY, playerA, "Alpine Grizzly"); + skipInitShuffling(); + + addCard(Zone.HAND, playerA, seeTheTruth); + addCard(Zone.BATTLEFIELD, playerA, "Island", 2); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, seeTheTruth); + addTarget(playerA, "Bear Cub"); // card chosen to be put in hand + + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertHandCount(playerA, 1); + + assertLibraryCount(playerA, "Alpine Grizzly", 1); + assertHandCount(playerA, "Bear Cub", 1); + assertLibraryCount(playerA, "Centaur Courser", 1); + } + + @Test + public void castFromGraveyard() { + setStrictChooseMode(true); + + addCard(Zone.LIBRARY, playerA, "Centaur Courser"); + addCard(Zone.LIBRARY, playerA, "Bear Cub"); + addCard(Zone.LIBRARY, playerA, "Alpine Grizzly"); + skipInitShuffling(); + + addCard(Zone.GRAVEYARD, playerA, seeTheTruth); + // Snapcaster Mage {1}{U} + // Flash + // When Snapcaster Mage enters the battlefield, target instant or sorcery card in your graveyard gains flashback until end of turn. The flashback cost is equal to its mana cost. + addCard(Zone.HAND, playerA, "Snapcaster Mage"); + addCard(Zone.BATTLEFIELD, playerA, "Island", 4); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Snapcaster Mage"); + addTarget(playerA, seeTheTruth); + waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, playerA); + + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Flashback", null, seeTheTruth); + // Cast from graveyard, all 3 cards are going to hand. No choice involved. + + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertHandCount(playerA, 3); + + assertHandCount(playerA, "Alpine Grizzly", 1); + assertHandCount(playerA, "Bear Cub", 1); + assertHandCount(playerA, "Centaur Courser", 1); + } + + @Test + public void copyOnStack() { + setStrictChooseMode(true); + + addCard(Zone.LIBRARY, playerA, "Feral Krushok"); + addCard(Zone.LIBRARY, playerA, "Enormous Baloth"); + addCard(Zone.LIBRARY, playerA, "Durkwood Boars"); + addCard(Zone.LIBRARY, playerA, "Centaur Courser"); + addCard(Zone.LIBRARY, playerA, "Bear Cub"); + addCard(Zone.LIBRARY, playerA, "Alpine Grizzly"); + skipInitShuffling(); + + addCard(Zone.HAND, playerA, seeTheTruth); + // Twincast {U}{U} + // Instant + // + // Copy target instant or sorcery spell. You may choose new targets for the copy. + addCard(Zone.HAND, playerA, "Twincast"); + addCard(Zone.BATTLEFIELD, playerA, "Island", 4); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, seeTheTruth); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Twincast", seeTheTruth); + addTarget(playerA, "Bear Cub"); // card chosen to be put in hand -- for the copy. + addTarget(playerA, "Enormous Baloth"); // card chosen to be put in hand -- for the initial cast. + + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertHandCount(playerA, 2); + + assertLibraryCount(playerA, "Alpine Grizzly", 1); + assertHandCount(playerA, "Bear Cub", 1); + assertLibraryCount(playerA, "Centaur Courser", 1); + assertLibraryCount(playerA, "Durkwood Boars", 1); + assertHandCount(playerA, "Enormous Baloth", 1); + assertLibraryCount(playerA, "Feral Krushok", 1); + } + + @Test + public void castCopyFromExile() { + setStrictChooseMode(true); + + addCard(Zone.LIBRARY, playerA, "Centaur Courser"); + addCard(Zone.LIBRARY, playerA, "Bear Cub"); + addCard(Zone.LIBRARY, playerA, "Alpine Grizzly"); + skipInitShuffling(); + + addCard(Zone.GRAVEYARD, playerA, "See the Truth"); + // Mizzix's Mastery {3}{R} + // Sorcery + // + // Exile target card that’s an instant or sorcery from your graveyard. For each card exiled this way, copy it, and you may cast the copy without paying its mana cost. Exile Mizzix’s Mastery. + // Overload {5}{R}{R}{R} (You may cast this spell for its overload cost. If you do, change “target” in its text to “each.”) + addCard(Zone.HAND, playerA, "Mizzix's Mastery"); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mizzix's Mastery", seeTheTruth); + setChoice(playerA, true); // answering 'yes' to: you MAY cast the copy. + // No card choice, the copy is cast so all 3 cards go to hand. + + setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); + execute(); + + assertHandCount(playerA, 3); + + assertHandCount(playerA, "Alpine Grizzly", 1); + assertHandCount(playerA, "Bear Cub", 1); + assertHandCount(playerA, "Centaur Courser", 1); + } +}