diff --git a/Mage.Sets/src/mage/cards/e/ElshaOfTheInfinite.java b/Mage.Sets/src/mage/cards/e/ElshaOfTheInfinite.java index c86f167b62f..62e488566a7 100644 --- a/Mage.Sets/src/mage/cards/e/ElshaOfTheInfinite.java +++ b/Mage.Sets/src/mage/cards/e/ElshaOfTheInfinite.java @@ -16,6 +16,7 @@ import mage.constants.SuperType; import mage.filter.FilterCard; import mage.filter.common.FilterNonlandCard; import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardOnTopOfLibraryPredicate; import java.util.UUID; @@ -28,6 +29,7 @@ public final class ElshaOfTheInfinite extends CardImpl { static { filter.add(Predicates.not(CardType.CREATURE.getPredicate())); + filter.add(CardOnTopOfLibraryPredicate.instance); } public ElshaOfTheInfinite(UUID ownerId, CardSetInfo setInfo) { @@ -62,3 +64,4 @@ public final class ElshaOfTheInfinite extends CardImpl { return new ElshaOfTheInfinite(this); } } + diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/single/c19/ElshaOfTheInfiniteTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/single/c19/ElshaOfTheInfiniteTest.java new file mode 100644 index 00000000000..1703df289fa --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/single/c19/ElshaOfTheInfiniteTest.java @@ -0,0 +1,55 @@ +package org.mage.test.cards.single.c19; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * @author JayDi85 + */ +public class ElshaOfTheInfiniteTest extends CardTestPlayerBase { + + @Test + public void test_MustApplyToTopCardOnly() { + // bug: flash ability can be applied to all cards in hand + // https://github.com/magefree/mage/issues/7605 + + removeAllCardsFromLibrary(playerA); + removeAllCardsFromHand(playerA); + skipInitShuffling(); + + // You may look at the top card of your library any time. + // You may cast noncreature spells from the top of your library. If you cast a spell this way, you may cast it as though it had flash. + addCard(Zone.BATTLEFIELD, playerA, "Elsha of the Infinite"); + // + // Sorcery + // Bolt of Keranos deals 3 damage to any target. Scry 1. + addCard(Zone.HAND, playerA, "Bolt of Keranos", 1);// {1}{R}{R} + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3); + // + // Birgi, God of Storytelling - creature, {2}{R} + // Harnfel, Horn of Bounty - artifact, {4}{R} + addCard(Zone.LIBRARY, playerA, "Birgi, God of Storytelling", 1); + addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5); + + // possible bug: sorcery card in hand got flash and can be playable + checkPlayableAbility("hand on upkeep, can't cast", 1, PhaseStep.UPKEEP, playerA, "Cast Bolt of Keranos", false); + checkPlayableAbility("lib on upkeep, can't cast left", 1, PhaseStep.UPKEEP, playerA, "Cast Birgi, God of Storytelling", false); + checkPlayableAbility("lib on upkeep, can cast right", 1, PhaseStep.UPKEEP, playerA, "Cast Harnfel, Horn of Bounty", true); + // + checkPlayableAbility("hand on main", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Bolt of Keranos", true); + checkPlayableAbility("lib on main, can't cast left", 1, PhaseStep.UPKEEP, playerA, "Cast Birgi, God of Storytelling", false); + checkPlayableAbility("lib on main, can cast right", 1, PhaseStep.UPKEEP, playerA, "Cast Harnfel, Horn of Bounty", true); + + checkLibraryCount("before cast", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Birgi, God of Storytelling", 1); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Harnfel, Horn of Bounty"); + + setStrictChooseMode(true); + setStopAt(1, PhaseStep.END_TURN); + execute(); + assertAllCommandsUsed(); + + assertPermanentCount(playerA, "Harnfel, Horn of Bounty", 1); + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/CastAsThoughItHadFlashAllEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/CastAsThoughItHadFlashAllEffect.java index 46398e18350..6534e48f474 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/CastAsThoughItHadFlashAllEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/CastAsThoughItHadFlashAllEffect.java @@ -1,8 +1,5 @@ - - package mage.abilities.effects.common.continuous; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.AsThoughEffectImpl; import mage.abilities.keyword.MorphAbility; @@ -14,8 +11,9 @@ import mage.constants.Outcome; import mage.filter.FilterCard; import mage.game.Game; +import java.util.UUID; + /** - * * @author LevelX2 */ @@ -69,10 +67,10 @@ public class CastAsThoughItHadFlashAllEffect extends AsThoughEffectImpl { Card cardCopy = card.copy(); cardCopy.getCardType().clear(); cardCopy.addCardType(CardType.CREATURE); - return filter.match(cardCopy, game); + return filter.match(cardCopy, source.getSourceId(), affectedControllerId, game); } } - return filter.match(card, game); + return filter.match(card, source.getSourceId(), affectedControllerId, game); } } return false; diff --git a/Mage/src/main/java/mage/abilities/effects/common/continuous/PlayTheTopCardEffect.java b/Mage/src/main/java/mage/abilities/effects/common/continuous/PlayTheTopCardEffect.java index 7df1c2071e6..e986267b0d5 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/continuous/PlayTheTopCardEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/continuous/PlayTheTopCardEffect.java @@ -98,6 +98,6 @@ public class PlayTheTopCardEffect extends AsThoughEffectImpl { } // must be correct card - return filter.match(cardToCheck, source.getSourceId(), source.getControllerId(), game); + return filter.match(cardToCheck, source.getSourceId(), affectedControllerId, game); } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/PlayLandsFromGraveyardControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/PlayLandsFromGraveyardControllerEffect.java index c6fa6186615..afc1f275cd3 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/PlayLandsFromGraveyardControllerEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/ruleModifying/PlayLandsFromGraveyardControllerEffect.java @@ -77,6 +77,6 @@ public class PlayLandsFromGraveyardControllerEffect extends AsThoughEffectImpl { } // must be correct card - return filter.match(cardToCheck, source.getSourceId(), source.getControllerId(), game); + return filter.match(cardToCheck, source.getSourceId(), affectedControllerId, game); } } diff --git a/Mage/src/main/java/mage/filter/predicate/mageobject/CardOnTopOfLibraryPredicate.java b/Mage/src/main/java/mage/filter/predicate/mageobject/CardOnTopOfLibraryPredicate.java new file mode 100644 index 00000000000..f423c5552ac --- /dev/null +++ b/Mage/src/main/java/mage/filter/predicate/mageobject/CardOnTopOfLibraryPredicate.java @@ -0,0 +1,26 @@ +package mage.filter.predicate.mageobject; + +import mage.cards.Card; +import mage.filter.predicate.ObjectPlayer; +import mage.filter.predicate.ObjectPlayerPredicate; +import mage.game.Game; +import mage.players.Player; + +/** + * @author JayDi85 + */ + +public enum CardOnTopOfLibraryPredicate implements ObjectPlayerPredicate> { + instance; + + @Override + public boolean apply(ObjectPlayer input, Game game) { + Player player = game.getPlayer(input.getObject().getOwnerId()); + if (player == null) { + return false; + } + + Card topCard = player.getLibrary().getFromTop(game); + return topCard != null && topCard.getId().equals(input.getObject().getMainCard().getId()); + } +} \ No newline at end of file