diff --git a/Mage.Sets/src/mage/cards/e/EcologicalAppreciation.java b/Mage.Sets/src/mage/cards/e/EcologicalAppreciation.java new file mode 100644 index 000000000000..03f4504155f1 --- /dev/null +++ b/Mage.Sets/src/mage/cards/e/EcologicalAppreciation.java @@ -0,0 +1,157 @@ +package mage.cards.e; + +import com.google.common.collect.Sets; +import mage.MageObject; +import mage.abilities.Ability; +import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ExileSpellEffect; +import mage.cards.*; +import mage.constants.CardType; +import mage.constants.ComparisonType; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.FilterCard; +import mage.filter.StaticFilters; +import mage.filter.common.FilterCreatureCard; +import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; +import mage.game.Game; +import mage.players.Player; +import mage.target.TargetCard; +import mage.target.common.TargetCardInLibrary; +import mage.target.common.TargetCardInYourGraveyard; +import mage.target.common.TargetOpponent; +import mage.util.CardUtil; + +import java.util.Objects; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; + +/** + * + * @author htrajan + */ +public final class EcologicalAppreciation extends CardImpl { + + public EcologicalAppreciation(UUID ownerId, CardSetInfo setInfo) { + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{X}{2}{G}"); + + // Search your library and graveyard for up to four creature cards with different names that each have mana value X or less and reveal them. An opponent chooses two of those cards. Shuffle the chosen cards into your library and put the rest onto the battlefield. Exile Ecological Appreciation. + this.getSpellAbility().addEffect(new EcologicalAppreciationEffect()); + this.getSpellAbility().addEffect(ExileSpellEffect.getInstance()); + } + + private EcologicalAppreciation(final EcologicalAppreciation card) { + super(card); + } + + @Override + public EcologicalAppreciation copy() { + return new EcologicalAppreciation(this); + } +} + +class EcologicalAppreciationEffect extends OneShotEffect { + + EcologicalAppreciationEffect() { + super(Outcome.Benefit); + staticText = "search your library and graveyard for up to four creature cards with different names that each have mana value X or less and reveal them. An opponent chooses two of those cards. Shuffle the chosen cards into your library and put the rest onto the battlefield"; + } + + private EcologicalAppreciationEffect(final EcologicalAppreciationEffect effect) { + super(effect); + } + + @Override + public EcologicalAppreciationEffect copy() { + return new EcologicalAppreciationEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Player player = game.getPlayer(source.getControllerId()); + if (player == null) { + return false; + } + int xValue = source.getManaCostsToPay().getX(); + FilterCard filter = new FilterCreatureCard(); + filter.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, xValue + 1)); + TargetCard targetCardsInLibrary = new TargetCardInLibrary(0, 4, filter) { + @Override + public boolean canTarget(UUID playerId, UUID id, Ability source, Game game) { + if (!super.canTarget(playerId, id, source, game)) { + return false; + } + Card card = game.getCard(id); + Set disallowedCards = this.getTargets().stream() + .map(game::getCard) + .collect(Collectors.toSet()); + return isValidTarget(card, disallowedCards); + } + }; + targetCardsInLibrary.setNotTarget(true); + targetCardsInLibrary.withChooseHint("Step 1 of 2: Search library"); + player.choose(Outcome.PutCreatureInPlay, new CardsImpl(player.getLibrary().getCards(game)), targetCardsInLibrary, game); + Cards cards = new CardsImpl(targetCardsInLibrary.getTargets()); + + boolean status = !cards.isEmpty(); + + if (status) { + int remainingCards = 4 - cards.size(); + if (remainingCards > 0) { + TargetCard targetCardsInGY = new TargetCardInYourGraveyard(0, remainingCards, filter) { + @Override + public boolean canTarget(UUID playerId, UUID id, Ability source, Game game) { + if (!super.canTarget(playerId, id, source, game)) { + return false; + } + Card card = game.getCard(id); + Set disallowedCards = this.getTargets().stream() + .map(game::getCard) + .collect(Collectors.toSet()); + return isValidTarget(card, Sets.union(disallowedCards, cards.getCards(game))); + } + }; + targetCardsInGY.setNotTarget(true); + targetCardsInGY.withChooseHint("Step 2 of 2: Search graveyard"); + player.choose(Outcome.PutCreatureInPlay, new CardsImpl(player.getGraveyard().getCards(game)), targetCardsInGY, game); + cards.addAll(targetCardsInGY.getTargets()); + } + + TargetOpponent targetOpponent = new TargetOpponent(); + targetOpponent.setNotTarget(true); + player.choose(outcome, targetOpponent, source.getSourceId(), game); + Player opponent = game.getPlayer(targetOpponent.getFirstTarget()); + + if (opponent == null) { + status = false; + } + + if (status) { + TargetCard chosenCards = new TargetCard(2, Zone.ALL, StaticFilters.FILTER_CARD); + chosenCards.setNotTarget(true); + opponent.choose(outcome, cards, chosenCards, game); + Cards toShuffle = new CardsImpl(chosenCards.getTargets().stream() + .map(game::getCard) + .collect(Collectors.toList())); + + player.putCardsOnTopOfLibrary(toShuffle, game, source, false); + cards.removeAll(toShuffle); + + player.moveCards(cards, Zone.BATTLEFIELD, source, game); + } + } + + player.shuffleLibrary(source, game); + + return status; + } + + private boolean isValidTarget(Card target, Set disallowedCards) { + return target != null && + disallowedCards.stream() + .filter(Objects::nonNull) + .map(MageObject::getName) + .noneMatch(name -> CardUtil.haveSameNames(name, target.getName())); + } +} \ No newline at end of file diff --git a/Mage.Sets/src/mage/cards/e/EmergentUltimatum.java b/Mage.Sets/src/mage/cards/e/EmergentUltimatum.java index 5d5d980c496c..f971b7538e98 100644 --- a/Mage.Sets/src/mage/cards/e/EmergentUltimatum.java +++ b/Mage.Sets/src/mage/cards/e/EmergentUltimatum.java @@ -68,6 +68,7 @@ public boolean apply(Game game, Ability source) { return false; } TargetCardInLibrary targetCardInLibrary = new EmergentUltimatumTarget(); + targetCardInLibrary.setNotTarget(true); boolean searched = player.searchLibrary(targetCardInLibrary, source, game); Cards cards = new CardsImpl(targetCardInLibrary.getTargets()); player.moveCards(cards, Zone.EXILED, source, game); @@ -85,9 +86,10 @@ public boolean apply(Game game, Ability source) { if (searched) { player.shuffleLibrary(source, game); } - return true; + return false; } TargetCardInExile targetCardInExile = new TargetCardInExile(StaticFilters.FILTER_CARD); + targetCardInExile.setNotTarget(true); opponent.choose(outcome, cards, targetCardInExile, game); Card toShuffle = game.getCard(targetCardInExile.getFirstTarget()); if (toShuffle != null) { diff --git a/Mage.Sets/src/mage/sets/StrixhavenSchoolOfMages.java b/Mage.Sets/src/mage/sets/StrixhavenSchoolOfMages.java index 22cf6340b7ea..b1d8a5d8915a 100644 --- a/Mage.Sets/src/mage/sets/StrixhavenSchoolOfMages.java +++ b/Mage.Sets/src/mage/sets/StrixhavenSchoolOfMages.java @@ -97,6 +97,7 @@ private StrixhavenSchoolOfMages() { cards.add(new SetCardInfo("Dream Strix", 42, Rarity.RARE, mage.cards.d.DreamStrix.class)); cards.add(new SetCardInfo("Dueling Coach", 15, Rarity.UNCOMMON, mage.cards.d.DuelingCoach.class)); cards.add(new SetCardInfo("Eager First-Year", 16, Rarity.COMMON, mage.cards.e.EagerFirstYear.class)); + cards.add(new SetCardInfo("Ecological Appreciation", 128, Rarity.MYTHIC, mage.cards.e.EcologicalAppreciation.class)); cards.add(new SetCardInfo("Elemental Expressionist", 181, Rarity.RARE, mage.cards.e.ElementalExpressionist.class)); cards.add(new SetCardInfo("Elemental Masterpiece", 182, Rarity.COMMON, mage.cards.e.ElementalMasterpiece.class)); cards.add(new SetCardInfo("Elemental Summoning", 183, Rarity.COMMON, mage.cards.e.ElementalSummoning.class));