From 76fcfafc8bb34c4d1b1dac57526ba57105c9ef8b Mon Sep 17 00:00:00 2001 From: "Alex W. Jackson" Date: Sat, 15 Oct 2022 21:27:55 -0400 Subject: [PATCH] Add common effect class for "Its controller searches..." (Path to Exile, etc) Fixes #9654 --- Mage.Sets/src/mage/cards/a/ArcumDagsson.java | 75 +++------------- .../src/mage/cards/a/AssassinsTrophy.java | 57 +------------ .../src/mage/cards/b/BoseijuWhoEndures.java | 85 +++++-------------- .../src/mage/cards/c/CelestialSword.java | 9 +- .../src/mage/cards/c/CleansingWildfire.java | 57 +------------ .../src/mage/cards/d/DireStrainRampage.java | 48 ++--------- Mage.Sets/src/mage/cards/f/FromTheAshes.java | 79 ++++++++--------- .../src/mage/cards/g/GeomancersGambit.java | 58 +------------ Mage.Sets/src/mage/cards/g/GhostQuarter.java | 55 ++---------- Mage.Sets/src/mage/cards/p/PathToExile.java | 59 ++----------- .../src/mage/cards/s/SettleTheWreckage.java | 35 ++++---- .../src/mage/cards/w/WindsOfAbandon.java | 39 +++------ .../effects/common/SacrificeTargetEffect.java | 11 +-- .../SearchLibraryAndExileTargetEffect.java | 44 +++------- .../search/SearchLibraryPutInPlayEffect.java | 39 ++------- ...ibraryPutInPlayTargetControllerEffect.java | 68 +++++++++++++++ ...rchLibraryPutInPlayTargetPlayerEffect.java | 42 +++------ .../src/main/java/mage/target/TargetImpl.java | 6 +- .../target/common/TargetBasicLandCard.java | 30 ------- 19 files changed, 243 insertions(+), 653 deletions(-) create mode 100644 Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryPutInPlayTargetControllerEffect.java delete mode 100644 Mage/src/main/java/mage/target/common/TargetBasicLandCard.java diff --git a/Mage.Sets/src/mage/cards/a/ArcumDagsson.java b/Mage.Sets/src/mage/cards/a/ArcumDagsson.java index 532ae254123..6d549a3d8ef 100644 --- a/Mage.Sets/src/mage/cards/a/ArcumDagsson.java +++ b/Mage.Sets/src/mage/cards/a/ArcumDagsson.java @@ -1,4 +1,3 @@ - package mage.cards.a; import java.util.UUID; @@ -6,19 +5,14 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.effects.OneShotEffect; -import mage.cards.Card; +import mage.abilities.effects.common.SacrificeTargetEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInPlayTargetControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.filter.FilterCard; -import mage.filter.FilterPermanent; -import mage.filter.common.FilterArtifactCard; -import mage.filter.common.FilterArtifactPermanent; -import mage.filter.predicate.Predicates; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; +import mage.filter.StaticFilters; +import mage.filter.common.FilterNoncreatureCard; import mage.target.TargetPermanent; import mage.target.common.TargetCardInLibrary; @@ -28,23 +22,23 @@ import mage.target.common.TargetCardInLibrary; */ public final class ArcumDagsson extends CardImpl { - private static final FilterPermanent filter = new FilterArtifactPermanent("artifact creature"); + private static final FilterCard filter = new FilterNoncreatureCard("noncreature artifact card"); static { - filter.add(CardType.CREATURE.getPredicate()); + filter.add(CardType.ARTIFACT.getPredicate()); } public ArcumDagsson(UUID ownerId, CardSetInfo setInfo) { super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}"); addSuperType(SuperType.LEGENDARY); - this.subtype.add(SubType.HUMAN); - this.subtype.add(SubType.ARTIFICER); + this.subtype.add(SubType.HUMAN, SubType.ARTIFICER); this.power = new MageInt(2); this.toughness = new MageInt(2); - // {tap}: Target artifact creature's controller sacrifices it. That player may search their library for a noncreature artifact card, put it onto the battlefield, then shuffle their library. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ArcumDagssonEffect(), new TapSourceCost()); - ability.addTarget(new TargetPermanent(filter)); + // {tap}: Target artifact creature's controller sacrifices it. That player may search their library for a noncreature artifact card, put it onto the battlefield, then shuffle. + Ability ability = new SimpleActivatedAbility(new SacrificeTargetEffect(), new TapSourceCost()); + ability.addEffect(new SearchLibraryPutInPlayTargetControllerEffect(new TargetCardInLibrary(filter), false, Outcome.PutCardInPlay, "that player")); + ability.addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_CREATURE)); this.addAbility(ability); } @@ -57,50 +51,3 @@ public final class ArcumDagsson extends CardImpl { return new ArcumDagsson(this); } } - -class ArcumDagssonEffect extends OneShotEffect { - - private static final FilterCard filter = new FilterArtifactCard("noncreature artifact card"); - - static { - filter.add(Predicates.not(CardType.CREATURE.getPredicate())); - } - - ArcumDagssonEffect() { - super(Outcome.Removal); - this.staticText = "Target artifact creature's controller sacrifices it. That player may search their library for a noncreature artifact card, put it onto the battlefield, then shuffle"; - } - - ArcumDagssonEffect(final ArcumDagssonEffect effect) { - super(effect); - } - - @Override - public ArcumDagssonEffect copy() { - return new ArcumDagssonEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent artifactCreature = game.getPermanent(this.getTargetPointer().getFirst(game, source)); - if (artifactCreature != null) { - Player player = game.getPlayer(artifactCreature.getControllerId()); - if (player != null) { - artifactCreature.sacrifice(source, game); - game.getState().processAction(game); // Workaround for https://github.com/magefree/mage/issues/8501 - if (player.chooseUse(Outcome.PutCardInPlay, "Search your library for a noncreature artifact card?", source, game)) { - TargetCardInLibrary target = new TargetCardInLibrary(filter); - if (player.searchLibrary(target, source, game)) { - Card card = game.getCard(target.getFirstTarget()); - if (card != null) { - player.moveCards(card, Zone.BATTLEFIELD, source, game); - } - } - player.shuffleLibrary(source, game); - } - return true; - } - } - return false; - } -} diff --git a/Mage.Sets/src/mage/cards/a/AssassinsTrophy.java b/Mage.Sets/src/mage/cards/a/AssassinsTrophy.java index 4551a2144f1..bbc8d2a7d7e 100644 --- a/Mage.Sets/src/mage/cards/a/AssassinsTrophy.java +++ b/Mage.Sets/src/mage/cards/a/AssassinsTrophy.java @@ -2,23 +2,14 @@ package mage.cards.a; import java.util.UUID; -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DestroyTargetEffect; -import mage.cards.Card; +import mage.abilities.effects.common.search.SearchLibraryPutInPlayTargetControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.TargetController; -import mage.constants.Zone; import mage.filter.FilterPermanent; -import mage.filter.StaticFilters; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; import mage.target.TargetPermanent; -import mage.target.common.TargetCardInLibrary; /** * @author TheElk801 @@ -34,9 +25,10 @@ public final class AssassinsTrophy extends CardImpl { public AssassinsTrophy(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}{G}"); - // Destroy target permanent an opponent controls. Its controller may search their library for a basic land card, put it onto the battlefield, then shuffle their library. + // Destroy target permanent an opponent controls. Its controller may search their + // library for a basic land card, put it onto the battlefield, then shuffle. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addEffect(new AssassinsTrophyEffect()); + this.getSpellAbility().addEffect(new SearchLibraryPutInPlayTargetControllerEffect(false)); this.getSpellAbility().addTarget(new TargetPermanent(filter)); } @@ -49,44 +41,3 @@ public final class AssassinsTrophy extends CardImpl { return new AssassinsTrophy(this); } } - -class AssassinsTrophyEffect extends OneShotEffect { - - public AssassinsTrophyEffect() { - super(Outcome.PutLandInPlay); - this.staticText = "Its controller may search their library " - + "for a basic land card, put it onto the battlefield, " - + "then shuffle"; - } - - public AssassinsTrophyEffect(final AssassinsTrophyEffect effect) { - super(effect); - } - - @Override - public AssassinsTrophyEffect copy() { - return new AssassinsTrophyEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = getTargetPointer().getFirstTargetPermanentOrLKI(game, source); - if (permanent != null) { - Player controller = game.getPlayer(permanent.getControllerId()); - if (controller != null) { - if (controller.chooseUse(Outcome.PutLandInPlay, "Search for a basic land, put it onto the battlefield and then shuffle?", source, game)) { - TargetCardInLibrary target = new TargetCardInLibrary(StaticFilters.FILTER_CARD_BASIC_LAND); - if (controller.searchLibrary(target, source, game)) { - Card card = controller.getLibrary().getCard(target.getFirstTarget(), game); - if (card != null) { - controller.moveCards(card, Zone.BATTLEFIELD, source, game); - } - } - controller.shuffleLibrary(source, game); - } - return true; - } - } - return false; - } -} diff --git a/Mage.Sets/src/mage/cards/b/BoseijuWhoEndures.java b/Mage.Sets/src/mage/cards/b/BoseijuWhoEndures.java index 98bef1013a7..25e9a22da46 100644 --- a/Mage.Sets/src/mage/cards/b/BoseijuWhoEndures.java +++ b/Mage.Sets/src/mage/cards/b/BoseijuWhoEndures.java @@ -2,11 +2,11 @@ package mage.cards.b; import mage.abilities.Ability; import mage.abilities.costs.costadjusters.LegendaryCreatureCostAdjuster; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.InfoEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInPlayTargetControllerEffect; import mage.abilities.keyword.ChannelAbility; import mage.abilities.mana.GreenManaAbility; -import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; @@ -14,9 +14,6 @@ import mage.filter.FilterCard; import mage.filter.FilterPermanent; import mage.filter.common.FilterLandCard; import mage.filter.predicate.Predicates; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; import mage.target.TargetPermanent; import mage.target.common.TargetCardInLibrary; @@ -27,12 +24,13 @@ import java.util.UUID; */ public final class BoseijuWhoEndures extends CardImpl { - private static final FilterPermanent filter + private static final FilterPermanent filterDestroy = new FilterPermanent("artifact, enchantment, or nonbasic land an opponent controls"); + private static final FilterCard filterSearch = new FilterLandCard("land card with a basic land type"); static { - filter.add(TargetController.OPPONENT.getControllerPredicate()); - filter.add(Predicates.or( + filterDestroy.add(TargetController.OPPONENT.getControllerPredicate()); + filterDestroy.add(Predicates.or( CardType.ARTIFACT.getPredicate(), CardType.ENCHANTMENT.getPredicate(), Predicates.and( @@ -40,6 +38,13 @@ public final class BoseijuWhoEndures extends CardImpl { CardType.LAND.getPredicate() ) )); + filterSearch.add(Predicates.or( + SubType.PLAINS.getPredicate(), + SubType.ISLAND.getPredicate(), + SubType.SWAMP.getPredicate(), + SubType.MOUNTAIN.getPredicate(), + SubType.FOREST.getPredicate() + )); } public BoseijuWhoEndures(UUID ownerId, CardSetInfo setInfo) { @@ -50,10 +55,17 @@ public final class BoseijuWhoEndures extends CardImpl { // {T}: Add {G}. this.addAbility(new GreenManaAbility()); - // Channel — {1}{G}, Discard Boseiju, Who Endures: Destroy target artifact, enchantment, or nonbasic land an opponent controls. That player may search their library for a land card with a basic land type, put it onto the battlefield, then shuffle. This ability costs {1} less to activate for each legendary creature you control. + // Channel — {1}{G}, Discard Boseiju, Who Endures: Destroy target artifact, enchantment, or nonbasic land an opponent controls. + // That player may search their library for a land card with a basic land type, put it onto the battlefield, then shuffle. + // This ability costs {1} less to activate for each legendary creature you control. Ability ability = new ChannelAbility("{1}{G}", new DestroyTargetEffect()); - ability.addEffect(new BoseijuWhoEnduresEffect()); - ability.addTarget(new TargetPermanent(filter)); + ability.addEffect(new SearchLibraryPutInPlayTargetControllerEffect( + new TargetCardInLibrary(filterSearch), false, Outcome.PutLandInPlay, "that player" + )); + ability.addEffect(new InfoEffect( + "This ability costs {1} less to activate for each legendary creature you control" + )); + ability.addTarget(new TargetPermanent(filterDestroy)); ability.setCostAdjuster(LegendaryCreatureCostAdjuster.instance); this.addAbility(ability.addHint(LegendaryCreatureCostAdjuster.getHint())); } @@ -67,54 +79,3 @@ public final class BoseijuWhoEndures extends CardImpl { return new BoseijuWhoEndures(this); } } - -class BoseijuWhoEnduresEffect extends OneShotEffect { - - private static final FilterCard filter = new FilterLandCard("land card with a basic land type"); - - static { - filter.add(Predicates.or( - SubType.PLAINS.getPredicate(), - SubType.ISLAND.getPredicate(), - SubType.SWAMP.getPredicate(), - SubType.MOUNTAIN.getPredicate(), - SubType.FOREST.getPredicate() - )); - } - - BoseijuWhoEnduresEffect() { - super(Outcome.Benefit); - staticText = "That player may search their library for a land card with a basic land type, " + - "put it onto the battlefield, then shuffle. " + - "This ability costs {1} less to activate for each legendary creature you control"; - } - - private BoseijuWhoEnduresEffect(final BoseijuWhoEnduresEffect effect) { - super(effect); - } - - @Override - public BoseijuWhoEnduresEffect copy() { - return new BoseijuWhoEnduresEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = getTargetPointer().getFirstTargetPermanentOrLKI(game, source); - if (permanent == null) { - return false; - } - Player player = game.getPlayer(permanent.getControllerId()); - if (!player.chooseUse(Outcome.PutCardInPlay, "Search your library for a land card?", source, game)) { - return true; - } - TargetCardInLibrary target = new TargetCardInLibrary(filter); - player.searchLibrary(target, source, game); - Card card = player.getLibrary().getCard(target.getFirstTarget(), game); - if (card != null) { - player.moveCards(card, Zone.BATTLEFIELD, source, game); - } - player.shuffleLibrary(source, game); - return true; - } -} diff --git a/Mage.Sets/src/mage/cards/c/CelestialSword.java b/Mage.Sets/src/mage/cards/c/CelestialSword.java index 552671da5c1..daec690ae73 100644 --- a/Mage.Sets/src/mage/cards/c/CelestialSword.java +++ b/Mage.Sets/src/mage/cards/c/CelestialSword.java @@ -1,4 +1,3 @@ - package mage.cards.c; import java.util.UUID; @@ -14,7 +13,6 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; -import mage.constants.Zone; import mage.target.common.TargetControlledCreaturePermanent; /** @@ -27,10 +25,13 @@ public final class CelestialSword extends CardImpl { super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{6}"); // {3}, {tap}: Target creature you control gets +3/+3 until end of turn. Its controller sacrifices it at the beginning of the next end step. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new BoostTargetEffect(3, 3, Duration.EndOfTurn), new GenericManaCost(3)); + Ability ability = new SimpleActivatedAbility(new BoostTargetEffect(3, 3, Duration.EndOfTurn), new GenericManaCost(3)); ability.addCost(new TapSourceCost()); ability.addTarget(new TargetControlledCreaturePermanent()); - ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(new SacrificeTargetEffect()))); + ability.addEffect(new CreateDelayedTriggeredAbilityEffect(new AtTheBeginOfNextEndStepDelayedTriggeredAbility( + new SacrificeTargetEffect("its controller sacrifices it") + ) + ).setText("its controller sacrifices it at the beginning of the next end step")); this.addAbility(ability); } diff --git a/Mage.Sets/src/mage/cards/c/CleansingWildfire.java b/Mage.Sets/src/mage/cards/c/CleansingWildfire.java index c42493fa97e..025a8460e66 100644 --- a/Mage.Sets/src/mage/cards/c/CleansingWildfire.java +++ b/Mage.Sets/src/mage/cards/c/CleansingWildfire.java @@ -1,20 +1,11 @@ package mage.cards.c; -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; -import mage.cards.Card; +import mage.abilities.effects.common.search.SearchLibraryPutInPlayTargetControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Zone; -import mage.filter.StaticFilters; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; -import mage.target.common.TargetCardInLibrary; import mage.target.common.TargetLandPermanent; import java.util.UUID; @@ -27,9 +18,9 @@ public final class CleansingWildfire extends CardImpl { public CleansingWildfire(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{R}"); - // Destroy target land. Its controller may search their library for a basic land card, put it onto the battlefield tapped, then shuffle their library. + // Destroy target land. Its controller may search their library for a basic land card, put it onto the battlefield tapped, then shuffle. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addEffect(new CleansingWildfireEffect()); + this.getSpellAbility().addEffect(new SearchLibraryPutInPlayTargetControllerEffect(true)); this.getSpellAbility().addTarget(new TargetLandPermanent()); // Draw a card. @@ -45,45 +36,3 @@ public final class CleansingWildfire extends CardImpl { return new CleansingWildfire(this); } } - -class CleansingWildfireEffect extends OneShotEffect { - - CleansingWildfireEffect() { - super(Outcome.Benefit); - staticText = "Its controller may search their library for a basic land card, " + - "put it onto the battlefield tapped, then shuffle."; - } - - private CleansingWildfireEffect(final CleansingWildfireEffect effect) { - super(effect); - } - - @Override - public CleansingWildfireEffect copy() { - return new CleansingWildfireEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = getTargetPointer().getFirstTargetPermanentOrLKI(game, source); - if (permanent == null) { - return false; - } - Player controller = game.getPlayer(permanent.getControllerId()); - if (controller == null) { - return false; - } - if (!controller.chooseUse(Outcome.PutLandInPlay, "Search for a basic land and put it onto the battlefield tapped?", source, game)) { - return true; - } - TargetCardInLibrary target = new TargetCardInLibrary(StaticFilters.FILTER_CARD_BASIC_LAND); - if (controller.searchLibrary(target, source, game)) { - Card card = controller.getLibrary().getCard(target.getFirstTarget(), game); - if (card != null) { - controller.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, true, null); - } - } - controller.shuffleLibrary(source, game); - return true; - } -} diff --git a/Mage.Sets/src/mage/cards/d/DireStrainRampage.java b/Mage.Sets/src/mage/cards/d/DireStrainRampage.java index 1b9f3feaeab..114d0115e57 100644 --- a/Mage.Sets/src/mage/cards/d/DireStrainRampage.java +++ b/Mage.Sets/src/mage/cards/d/DireStrainRampage.java @@ -1,26 +1,21 @@ package mage.cards.d; -import java.util.HashSet; -import java.util.Set; import java.util.UUID; import mage.abilities.Ability; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInPlayTargetControllerEffect; import mage.abilities.keyword.FlashbackAbility; -import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; -import mage.constants.TimingRule; -import mage.constants.Zone; import mage.filter.FilterPermanent; import mage.filter.StaticFilters; import mage.filter.predicate.Predicates; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.players.Player; import mage.target.TargetPermanent; import mage.target.common.TargetCardInLibrary; @@ -87,43 +82,12 @@ class DireStrainRampageEffect extends OneShotEffect { if (permanent == null) { return false; } - Player player = game.getPlayer(permanent.getControllerId()); boolean landTargeted = permanent.isLand(game); boolean destroyed = permanent.destroy(source, game, false); - boolean twoLands = false; - if (landTargeted && destroyed) { - // Check that no replacement happened (card actually went to the graveyard and "was destroyed this way") - if (game.getState().getZone(permanent.getId()) == Zone.GRAVEYARD) { - twoLands = true; - } - } - String searchString; - if (twoLands) { - searchString = "Search your library for up to two basic land cards, put them onto the battlefield tapped, then shuffle?"; - } else { - searchString = "Search your library for a basic land card, put it onto the battlefield tapped, then shuffle?"; - } - if (player != null && player.chooseUse(Outcome.PutLandInPlay, searchString, source, game)) { - TargetCardInLibrary target; - if (twoLands) { - target = new TargetCardInLibrary(0, 2, StaticFilters.FILTER_CARD_BASIC_LANDS); - } else { - target = new TargetCardInLibrary(1, 1, StaticFilters.FILTER_CARD_BASIC_LAND); - } - if (player.searchLibrary(target, source, game)) { - Set lands = new HashSet<>(); - for (UUID cardId : target.getTargets()) { - Card card = game.getCard(cardId); - if (card != null) { - lands.add(card); - } - } - if (!lands.isEmpty()) { - player.moveCards(lands, Zone.BATTLEFIELD, source, game, true, false, false, null); - } - } - player.shuffleLibrary(source, game); - } - return true; + game.getState().processAction(game); + TargetCardInLibrary target = landTargeted && destroyed ? + new TargetCardInLibrary(0, 2, StaticFilters.FILTER_CARD_BASIC_LANDS) : + new TargetCardInLibrary(1, 1, StaticFilters.FILTER_CARD_BASIC_LAND); + return new SearchLibraryPutInPlayTargetControllerEffect(target, true, Outcome.PutLandInPlay, "its controller").apply(game, source); } } diff --git a/Mage.Sets/src/mage/cards/f/FromTheAshes.java b/Mage.Sets/src/mage/cards/f/FromTheAshes.java index 90c4edbc620..e3896bcfc8f 100644 --- a/Mage.Sets/src/mage/cards/f/FromTheAshes.java +++ b/Mage.Sets/src/mage/cards/f/FromTheAshes.java @@ -13,7 +13,6 @@ import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Zone; import mage.filter.StaticFilters; -import mage.filter.common.FilterLandPermanent; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; @@ -44,8 +43,6 @@ public final class FromTheAshes extends CardImpl { class FromTheAshesEffect extends OneShotEffect { - private static final FilterLandPermanent filter = FilterLandPermanent.nonbasicLands(); - public FromTheAshesEffect() { super(Outcome.Benefit); this.staticText = "Destroy all nonbasic lands. For each land destroyed this way, its controller may search their library for a basic land card and put it onto the battlefield. Then each player who searched their library this way shuffles"; @@ -63,42 +60,46 @@ class FromTheAshesEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - Map playerAmount = new HashMap<>(); - for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { - Player player = game.getPlayer(playerId); - if (player != null) { - int amount = 0; - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, playerId, game)) { - amount++; - permanent.destroy(source, game, false); - } - playerAmount.put(playerId, amount); - } - } - game.getState().processAction(game); - for (Map.Entry entry : playerAmount.entrySet()) { - Player player = game.getPlayer(entry.getKey()); - if (player != null && player.chooseUse(outcome, "Search your library for up to " + entry.getValue() + " basic land card(s) to put it onto the battlefield?", source, game)) { - TargetCardInLibrary target = new TargetCardInLibrary(0, entry.getValue(), StaticFilters.FILTER_CARD_BASIC_LAND); - if (player.searchLibrary(target, source, game)) { - if (!target.getTargets().isEmpty()) { - player.moveCards(new CardsImpl(target.getTargets()), Zone.BATTLEFIELD, source, game); - } - } - } else { - entry.setValue(0); // no search no shuffling - } - } - game.getState().processAction(game); - for (Map.Entry entry : playerAmount.entrySet()) { - Player player = game.getPlayer(entry.getKey()); - if (player != null && entry.getValue() > 0) { - player.shuffleLibrary(source, game); - } - } - return true; + if (controller == null) { + return false; } - return false; + // Destroy all nonbasic lands. + Map playerAmount = new HashMap<>(); + for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_LANDS_NONBASIC, source.getControllerId(), source, game)) { + UUID controllerId = permanent.getControllerId(); + if (permanent.destroy(source, game, false)) { + playerAmount.merge(controllerId, 1, Integer::sum); + } + } + game.getState().processAction(game); + + // For each land destroyed this way, its controller may search their library for a basic land card and put it onto the battlefield. + for (Map.Entry entry : playerAmount.entrySet()) { + Player player = game.getPlayer(entry.getKey()); + if (player == null) { + continue; + } + TargetCardInLibrary target = new TargetCardInLibrary(0, entry.getValue(), + entry.getValue() > 1 ? StaticFilters.FILTER_CARD_BASIC_LANDS : StaticFilters.FILTER_CARD_BASIC_LAND); + if (player.chooseUse(Outcome.PutLandInPlay, "Search your library for " + target.getDescription() + '?', source, game)) { + if (player.searchLibrary(target, source, game)) { + if (!target.getTargets().isEmpty()) { + player.moveCards(new CardsImpl(target.getTargets()), Zone.BATTLEFIELD, source, game); + } + } + } else { + entry.setValue(0); // no search no shuffling + } + } + game.getState().processAction(game); + + // Then each player who searched their library this way shuffles. + for (Map.Entry entry : playerAmount.entrySet()) { + Player player = game.getPlayer(entry.getKey()); + if (player != null && entry.getValue() > 0) { + player.shuffleLibrary(source, game); + } + } + return true; } } diff --git a/Mage.Sets/src/mage/cards/g/GeomancersGambit.java b/Mage.Sets/src/mage/cards/g/GeomancersGambit.java index f5ff4dd6632..218529ab3e9 100644 --- a/Mage.Sets/src/mage/cards/g/GeomancersGambit.java +++ b/Mage.Sets/src/mage/cards/g/GeomancersGambit.java @@ -1,20 +1,11 @@ package mage.cards.g; -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DestroyTargetEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; -import mage.cards.Card; +import mage.abilities.effects.common.search.SearchLibraryPutInPlayTargetControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Zone; -import mage.filter.StaticFilters; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; -import mage.target.common.TargetCardInLibrary; import mage.target.common.TargetLandPermanent; import java.util.UUID; @@ -27,9 +18,9 @@ public final class GeomancersGambit extends CardImpl { public GeomancersGambit(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{R}"); - // Destroy target land. Its controller may search their library for a basic land card, put it onto the battlefield, then shuffle their library. + // Destroy target land. Its controller may search their library for a basic land card, put it onto the battlefield, then shuffle. this.getSpellAbility().addEffect(new DestroyTargetEffect()); - this.getSpellAbility().addEffect(new GeomancersGambitEffect()); + this.getSpellAbility().addEffect(new SearchLibraryPutInPlayTargetControllerEffect(false)); this.getSpellAbility().addTarget(new TargetLandPermanent()); // Draw a card. @@ -45,46 +36,3 @@ public final class GeomancersGambit extends CardImpl { return new GeomancersGambit(this); } } - -class GeomancersGambitEffect extends OneShotEffect { - - GeomancersGambitEffect() { - super(Outcome.PutLandInPlay); - this.staticText = "Its controller may search their library " - + "for a basic land card, put it onto the battlefield, " - + "then shuffle"; - } - - private GeomancersGambitEffect(final GeomancersGambitEffect effect) { - super(effect); - } - - @Override - public GeomancersGambitEffect copy() { - return new GeomancersGambitEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = getTargetPointer().getFirstTargetPermanentOrLKI(game, source); - if (permanent == null) { - return false; - } - Player controller = game.getPlayer(permanent.getControllerId()); - if (controller == null) { - return false; - } - if (!controller.chooseUse(Outcome.PutLandInPlay, "Search for a basic land, put it onto the battlefield, and then shuffle?", source, game)) { - return true; - } - TargetCardInLibrary target = new TargetCardInLibrary(StaticFilters.FILTER_CARD_BASIC_LAND); - if (controller.searchLibrary(target, source, game)) { - Card card = controller.getLibrary().getCard(target.getFirstTarget(), game); - if (card != null) { - controller.moveCards(card, Zone.BATTLEFIELD, source, game); - } - } - controller.shuffleLibrary(source, game); - return true; - } -} diff --git a/Mage.Sets/src/mage/cards/g/GhostQuarter.java b/Mage.Sets/src/mage/cards/g/GhostQuarter.java index f6242d01cea..41abf8b2eeb 100644 --- a/Mage.Sets/src/mage/cards/g/GhostQuarter.java +++ b/Mage.Sets/src/mage/cards/g/GhostQuarter.java @@ -5,20 +5,12 @@ import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.SacrificeSourceCost; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DestroyTargetEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInPlayTargetControllerEffect; import mage.abilities.mana.ColorlessManaAbility; -import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Zone; -import mage.filter.StaticFilters; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; -import mage.target.common.TargetCardInLibrary; import mage.target.common.TargetLandPermanent; /** @@ -32,11 +24,13 @@ public final class GhostQuarter extends CardImpl { // {T}: Add {C}. this.addAbility(new ColorlessManaAbility()); - // {T}, Sacrifice Ghost Quarter: Destroy target land. Its controller may search their library for a basic land card, put it onto the battlefield, then shuffle their library. - SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DestroyTargetEffect(), new TapSourceCost()); + + // {T}, Sacrifice Ghost Quarter: Destroy target land. Its controller may search + // their library for a basic land card, put it onto the battlefield, then shuffle. + Ability ability = new SimpleActivatedAbility(new DestroyTargetEffect(), new TapSourceCost()); + ability.addEffect(new SearchLibraryPutInPlayTargetControllerEffect(false)); ability.addCost(new SacrificeSourceCost()); ability.addTarget(new TargetLandPermanent()); - ability.addEffect(new GhostQuarterEffect()); this.addAbility(ability); } @@ -49,40 +43,3 @@ public final class GhostQuarter extends CardImpl { return new GhostQuarter(this); } } - -class GhostQuarterEffect extends OneShotEffect { - - public GhostQuarterEffect() { - super(Outcome.PutLandInPlay); - this.staticText = "Its controller may search their library for a basic land card, put it onto the battlefield, then shuffle"; - } - - public GhostQuarterEffect(final GhostQuarterEffect effect) { - super(effect); - } - - @Override - public GhostQuarterEffect copy() { - return new GhostQuarterEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = getTargetPointer().getFirstTargetPermanentOrLKI(game, source); - if (permanent != null) { - Player controller = game.getPlayer(permanent.getControllerId()); - if (controller != null && controller.chooseUse(Outcome.PutLandInPlay, "Search for a basic land, put it onto the battlefield, and then shuffle?", source, game)) { - TargetCardInLibrary target = new TargetCardInLibrary(StaticFilters.FILTER_CARD_BASIC_LAND); - if (controller.searchLibrary(target, source, game)) { - Card card = controller.getLibrary().getCard(target.getFirstTarget(), game); - if (card != null) { - controller.moveCards(card, Zone.BATTLEFIELD, source, game); - } - } - controller.shuffleLibrary(source, game); - } - return true; - } - return false; - } -} diff --git a/Mage.Sets/src/mage/cards/p/PathToExile.java b/Mage.Sets/src/mage/cards/p/PathToExile.java index 8e7be81df6c..cdfd3de85d2 100644 --- a/Mage.Sets/src/mage/cards/p/PathToExile.java +++ b/Mage.Sets/src/mage/cards/p/PathToExile.java @@ -1,19 +1,10 @@ - package mage.cards.p; -import mage.abilities.Ability; -import mage.abilities.effects.OneShotEffect; -import mage.cards.Card; +import mage.abilities.effects.common.ExileTargetEffect; +import mage.abilities.effects.common.search.SearchLibraryPutInPlayTargetControllerEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Zone; -import mage.filter.StaticFilters; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; -import mage.target.common.TargetCardInLibrary; import mage.target.common.TargetCreaturePermanent; import java.util.UUID; @@ -30,7 +21,10 @@ public final class PathToExile extends CardImpl { // Exile target creature. Its controller may search their library for a basic land card, // put that card onto the battlefield tapped, then shuffle their library. this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - this.getSpellAbility().addEffect(new PathToExileEffect()); + this.getSpellAbility().addEffect(new ExileTargetEffect()); + this.getSpellAbility().addEffect(new SearchLibraryPutInPlayTargetControllerEffect(true).setText( + "its controller may search their library for a basic land card, put that card onto the battlefield tapped, then shuffle" + )); } private PathToExile(final PathToExile card) { @@ -42,44 +36,3 @@ public final class PathToExile extends CardImpl { return new PathToExile(this); } } - -class PathToExileEffect extends OneShotEffect { - - public PathToExileEffect() { - super(Outcome.Exile); - staticText = "Exile target creature. Its controller may search their library for a basic land card, put that card onto the battlefield tapped, then shuffle"; - } - - public PathToExileEffect(final PathToExileEffect effect) { - super(effect); - } - - @Override - public PathToExileEffect copy() { - return new PathToExileEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - Permanent permanent = game.getPermanent(source.getFirstTarget()); - if (controller != null && permanent != null) { - Player player = game.getPlayer(permanent.getControllerId()); - // if the zone change to exile gets replaced does not prevent the target controller to be able to search - controller.moveCardToExileWithInfo(permanent, null, "", source, game, Zone.BATTLEFIELD, true); - if (player.chooseUse(Outcome.PutCardInPlay, "Search your library for a basic land card?", source, game)) { - TargetCardInLibrary target = new TargetCardInLibrary(StaticFilters.FILTER_CARD_BASIC_LAND); - if (player.searchLibrary(target, source, game)) { - Card card = player.getLibrary().getCard(target.getFirstTarget(), game); - if (card != null) { - player.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, false, null); - } - } - player.shuffleLibrary(source, game); - } - return true; - } - return false; - } - -} diff --git a/Mage.Sets/src/mage/cards/s/SettleTheWreckage.java b/Mage.Sets/src/mage/cards/s/SettleTheWreckage.java index 408484cafda..9178b63aee0 100644 --- a/Mage.Sets/src/mage/cards/s/SettleTheWreckage.java +++ b/Mage.Sets/src/mage/cards/s/SettleTheWreckage.java @@ -1,8 +1,6 @@ - package mage.cards.s; import java.util.HashSet; -import java.util.Iterator; import java.util.Set; import java.util.UUID; import mage.abilities.Ability; @@ -16,7 +14,6 @@ import mage.constants.Outcome; import mage.constants.Zone; import mage.filter.StaticFilters; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetPlayer; import mage.target.common.TargetCardInLibrary; @@ -48,7 +45,7 @@ public final class SettleTheWreckage extends CardImpl { class SettleTheWreckageEffect extends OneShotEffect { SettleTheWreckageEffect() { - super(Outcome.Neutral); + super(Outcome.Exile); this.staticText = "Exile all attacking creatures target player controls. That player may search their library for that many basic land cards, put those cards onto the battlefield tapped, then shuffle"; } @@ -68,23 +65,25 @@ class SettleTheWreckageEffect extends OneShotEffect { if (controller == null || player == null) { return false; } - int attackers = 0; - Set toExile = new HashSet<>(); - Iterator creatureIds = game.getCombat().getAttackers().iterator(); - while (creatureIds.hasNext()) { - Permanent creature = game.getPermanent(creatureIds.next()); - if (creature != null && creature.isControlledBy(player.getId())) { - toExile.add(creature); - attackers++; - } + Set toExile = new HashSet<>(game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_ATTACKING_CREATURES, player.getId(), game)); + int attackers = toExile.size(); + if (attackers == 0) { + return true; } controller.moveCards(toExile, Zone.EXILED, source, game); - TargetCardInLibrary target = new TargetCardInLibrary(0, attackers, StaticFilters.FILTER_CARD_BASIC_LAND); - if (player.chooseUse(Outcome.Benefit, "Search for up to " + attackers + " basic land" + ((attackers == 1) ? "" : "s") + "?", source, game) && player.searchLibrary(target, source, game)) { - player.moveCards(new CardsImpl(target.getTargets()).getCards(game), Zone.BATTLEFIELD, source, game, true, false, false, null); - player.shuffleLibrary(source, game); + game.getState().processAction(game); + + TargetCardInLibrary target = new TargetCardInLibrary(0, attackers, + attackers > 1 ? StaticFilters.FILTER_CARD_BASIC_LANDS : StaticFilters.FILTER_CARD_BASIC_LAND + ); + if (player.chooseUse(Outcome.PutLandInPlay, "Search your library for " + target.getDescription() + '?', source, game)) { + if (player.searchLibrary(target, source, game)) { + if (!target.getTargets().isEmpty()) { + player.moveCards(new CardsImpl(target.getTargets()).getCards(game), + Zone.BATTLEFIELD, source, game, true, false, false, null); + } + } } return true; - } } diff --git a/Mage.Sets/src/mage/cards/w/WindsOfAbandon.java b/Mage.Sets/src/mage/cards/w/WindsOfAbandon.java index 171d90a85f4..b0f0899ad7c 100644 --- a/Mage.Sets/src/mage/cards/w/WindsOfAbandon.java +++ b/Mage.Sets/src/mage/cards/w/WindsOfAbandon.java @@ -19,7 +19,6 @@ import mage.target.TargetPermanent; import mage.target.common.TargetCardInLibrary; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.UUID; @@ -81,10 +80,7 @@ class WindsOfAbandonEffect extends OneShotEffect { if (!controller.moveCards(permanent, Zone.EXILED, source, game)) { return true; } - - if (!player.chooseUse(Outcome.PutCardInPlay, "Search your library for a basic land card?", source, game)) { - return true; - } + game.getState().processAction(game); TargetCardInLibrary target = new TargetCardInLibrary(StaticFilters.FILTER_CARD_BASIC_LAND); if (player.searchLibrary(target, source, game)) { Card card = player.getLibrary().getCard(target.getFirstTarget(), game); @@ -121,39 +117,30 @@ class WindsOfAbandonOverloadEffect extends OneShotEffect { if (controller == null) { return false; } - Map playerMap = new HashMap<>(); + Map playerAmount = new HashMap<>(); CardsImpl cards = new CardsImpl(); for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_CREATURE_YOU_DONT_CONTROL, source.getControllerId(), source, game)) { - int count = playerMap.getOrDefault(permanent.getControllerId(), 0); - playerMap.put(permanent.getControllerId(), count + 1); + playerAmount.merge(permanent.getControllerId(), 1, Integer::sum); cards.add(permanent); } if (!controller.moveCards(cards, Zone.EXILED, source, game)) { return true; } - - for (UUID playerId : game.getOpponents(source.getControllerId())) { - Player player = game.getPlayer(playerId); - int count = playerMap.getOrDefault(playerId, 0); - if (player == null || count == 0) { + game.getState().processAction(game); + for (Map.Entry entry : playerAmount.entrySet()) { + Player player = game.getPlayer(entry.getKey()); + if (player == null) { continue; } - TargetCardInLibrary target = new TargetCardInLibrary(0, count, StaticFilters.FILTER_CARD_BASIC_LAND); - boolean moved = false; + TargetCardInLibrary target = new TargetCardInLibrary(0, entry.getValue(), + entry.getValue() > 1 ? StaticFilters.FILTER_CARD_BASIC_LANDS : StaticFilters.FILTER_CARD_BASIC_LAND); if (player.searchLibrary(target, source, game)) { - List targets = target.getTargets(); - for (UUID targetId : targets) { - Card card = player.getLibrary().getCard(targetId, game); - if (card != null) { - if (player.moveCards(card, Zone.BATTLEFIELD, source, game, true, false, false, null)) { - moved = true; - } - } + if (!target.getTargets().isEmpty()) { + player.moveCards(new CardsImpl(target.getTargets()).getCards(game), + Zone.BATTLEFIELD, source, game, true, false, false, null); } } - if (moved) { - player.shuffleLibrary(source, game); - } + player.shuffleLibrary(source, game); } return true; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/SacrificeTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/SacrificeTargetEffect.java index ebd48484efc..6b165a193c4 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/SacrificeTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/SacrificeTargetEffect.java @@ -62,14 +62,9 @@ public class SacrificeTargetEffect extends OneShotEffect { @Override public String getText(Mode mode) { - if (staticText.isEmpty() && !mode.getTargets().isEmpty()) { - if (mode.getTargets().get(0).getNumberOfTargets() == 1) { - return "The controller of target " + mode.getTargets().get(0).getTargetName() + " sacrifices it"; - } else { - return "The controller of " + mode.getTargets().get(0).getNumberOfTargets() + " target " + mode.getTargets().get(0).getTargetName() + " sacrifices it"; - } + if (staticText != null && !staticText.isEmpty()) { + return staticText; } - return staticText; + return getTargetPointer().describeTargets(mode.getTargets(), "that permanent") + "'s controller sacrifices it"; } - } diff --git a/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryAndExileTargetEffect.java b/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryAndExileTargetEffect.java index deda3c48dcf..614b230d99d 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryAndExileTargetEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryAndExileTargetEffect.java @@ -2,7 +2,7 @@ package mage.abilities.effects.common.search; import mage.abilities.Ability; import mage.abilities.Mode; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.SearchEffect; import mage.cards.Cards; import mage.cards.CardsImpl; import mage.constants.Outcome; @@ -11,26 +11,18 @@ import mage.filter.StaticFilters; import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCardInLibrary; -import mage.util.CardUtil; /** * @author TheElk801 */ -public class SearchLibraryAndExileTargetEffect extends OneShotEffect { - - private final int amount; - private final boolean upTo; +public class SearchLibraryAndExileTargetEffect extends SearchEffect { public SearchLibraryAndExileTargetEffect(int amount, boolean upTo) { - super(Outcome.Benefit); - this.amount = amount; - this.upTo = upTo; + super(new TargetCardInLibrary(upTo ? 0 : amount, amount, amount > 1 ? StaticFilters.FILTER_CARD_CARDS : StaticFilters.FILTER_CARD), Outcome.Exile); } private SearchLibraryAndExileTargetEffect(final SearchLibraryAndExileTargetEffect effect) { super(effect); - this.amount = effect.amount; - this.upTo = effect.upTo; } @Override @@ -45,16 +37,12 @@ public class SearchLibraryAndExileTargetEffect extends OneShotEffect { if (controller == null || player == null) { return false; } - TargetCardInLibrary target = new TargetCardInLibrary(upTo ? 0 : amount, amount, StaticFilters.FILTER_CARD); controller.searchLibrary(target, source, game, player.getId()); Cards cards = new CardsImpl(); target.getTargets() .stream() .map(uuid -> player.getLibrary().getCard(uuid, game)) .forEach(cards::add); - if (cards.isEmpty()) { - return false; - } controller.moveCards(cards, Zone.EXILED, source, game); player.shuffleLibrary(source, game); return true; @@ -62,24 +50,14 @@ public class SearchLibraryAndExileTargetEffect extends OneShotEffect { @Override public String getText(Mode mode) { - StringBuilder sb = new StringBuilder("search "); - if (mode.getTargets().isEmpty()) { - sb.append("that player"); - } else { - sb.append("target "); - sb.append(mode.getTargets().get(0).getTargetName()); + if (staticText != null && !staticText.isEmpty()) { + return staticText; } - sb.append("'s library for "); - if (amount > 1) { - if (upTo) { - sb.append("up to "); - } - sb.append(CardUtil.numberToText(amount)); - sb.append(" cards and exile them"); - } else { - sb.append("a card and exile it"); - } - sb.append(". Then that player shuffles"); - return sb.toString(); + return "search " + + getTargetPointer().describeTargets(mode.getTargets(), "that player") + + "'s library for " + + target.getDescription() + + (target.getMaxNumberOfTargets() > 1 ? " and exile them" : " and exile it") + + ". Then that player shuffles"; } } diff --git a/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryPutInPlayEffect.java b/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryPutInPlayEffect.java index 08d5825c86d..b5fd0db9e5f 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryPutInPlayEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryPutInPlayEffect.java @@ -8,7 +8,6 @@ import mage.constants.Zone; import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCardInLibrary; -import mage.util.CardUtil; import java.util.List; import java.util.UUID; @@ -41,7 +40,12 @@ public class SearchLibraryPutInPlayEffect extends SearchEffect { super(target, outcome); this.tapped = tapped; this.forceShuffle = forceShuffle; - setText(); + staticText = "search your library for " + + target.getDescription() + + (forceShuffle ? ", " : " and ") + + (target.getMaxNumberOfTargets() > 1 ? "put them onto the battlefield" : "put it onto the battlefield") + + (tapped ? " tapped" : "") + + (forceShuffle ? ", then shuffle" : ". If you do, shuffle"); } public SearchLibraryPutInPlayEffect(final SearchLibraryPutInPlayEffect effect) { @@ -72,39 +76,10 @@ public class SearchLibraryPutInPlayEffect extends SearchEffect { if (forceShuffle) { player.shuffleLibrary(source, game); } - return false; - } - - private void setText() { - StringBuilder sb = new StringBuilder(); - sb.append("search your library for "); - if (target.getNumberOfTargets() == 0 && target.getMaxNumberOfTargets() > 0) { - if (target.getMaxNumberOfTargets() == Integer.MAX_VALUE) { - sb.append("any number of "); - } else { - sb.append("up to ").append(CardUtil.numberToText(target.getMaxNumberOfTargets())).append(' '); - } - sb.append(target.getTargetName()); - sb.append(forceShuffle ? ", " : " and "); - sb.append("put them onto the battlefield"); - } else { - sb.append(CardUtil.addArticle(target.getTargetName())); - sb.append(forceShuffle ? ", " : " and "); - sb.append("put it onto the battlefield"); - } - if (tapped) { - sb.append(" tapped"); - } - if (forceShuffle) { - sb.append(", then shuffle"); - } else { - sb.append(". If you do, shuffle"); - } - staticText = sb.toString(); + return true; } public List getTargets() { return target.getTargets(); } - } diff --git a/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryPutInPlayTargetControllerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryPutInPlayTargetControllerEffect.java new file mode 100644 index 00000000000..55e0bab5e80 --- /dev/null +++ b/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryPutInPlayTargetControllerEffect.java @@ -0,0 +1,68 @@ +package mage.abilities.effects.common.search; + +import mage.abilities.Ability; +import mage.abilities.effects.SearchEffect; +import mage.cards.CardsImpl; +import mage.constants.Outcome; +import mage.constants.Zone; +import mage.filter.StaticFilters; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.common.TargetCardInLibrary; + +/** + * @author awjackson + */ +public class SearchLibraryPutInPlayTargetControllerEffect extends SearchEffect { + + private boolean tapped; + + public SearchLibraryPutInPlayTargetControllerEffect(boolean tapped) { + this(new TargetCardInLibrary(StaticFilters.FILTER_CARD_BASIC_LAND), tapped, Outcome.PutLandInPlay, "its controller"); + } + + public SearchLibraryPutInPlayTargetControllerEffect(TargetCardInLibrary target, boolean tapped, Outcome outcome, String whoSearch) { + super(target, outcome); + this.tapped = tapped; + staticText = whoSearch + + " may search their library for " + + target.getDescription() + + (target.getMaxNumberOfTargets() > 1 ? ", put them onto the battlefield" : ", put it onto the battlefield") + + (tapped ? " tapped" : "") + + ", then shuffle"; + } + + public SearchLibraryPutInPlayTargetControllerEffect(final SearchLibraryPutInPlayTargetControllerEffect effect) { + super(effect); + this.tapped = effect.tapped; + } + + @Override + public SearchLibraryPutInPlayTargetControllerEffect copy() { + return new SearchLibraryPutInPlayTargetControllerEffect(this); + } + + @Override + public boolean apply(Game game, Ability source) { + Permanent permanent = getTargetPointer().getFirstTargetPermanentOrLKI(game, source); + if (permanent == null) { + return false; + } + Player player = game.getPlayer(permanent.getControllerId()); + if (player == null) { + return false; + } + if (!player.chooseUse(outcome, "Search your library for " + target.getDescription() + '?', source, game)) { + return true; + } + if (player.searchLibrary(target, source, game)) { + if (!target.getTargets().isEmpty()) { + player.moveCards(new CardsImpl(target.getTargets()).getCards(game), + Zone.BATTLEFIELD, source, game, tapped, false, false, null); + } + } + player.shuffleLibrary(source, game); + return true; + } +} diff --git a/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryPutInPlayTargetPlayerEffect.java b/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryPutInPlayTargetPlayerEffect.java index f3b662d77cf..1faafb41dae 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryPutInPlayTargetPlayerEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/search/SearchLibraryPutInPlayTargetPlayerEffect.java @@ -1,6 +1,7 @@ package mage.abilities.effects.common.search; import mage.abilities.Ability; +import mage.abilities.Mode; import mage.abilities.effects.SearchEffect; import mage.cards.CardsImpl; import mage.constants.Outcome; @@ -9,9 +10,6 @@ import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCardInLibrary; -import java.util.List; -import java.util.UUID; - /** * @author LevelX2 */ @@ -46,7 +44,6 @@ public class SearchLibraryPutInPlayTargetPlayerEffect extends SearchEffect { this.tapped = tapped; this.forceShuffle = forceShuffle; this.ownerIsController = ownerIsController; - setText(); } public SearchLibraryPutInPlayTargetPlayerEffect(final SearchLibraryPutInPlayTargetPlayerEffect effect) { @@ -82,32 +79,17 @@ public class SearchLibraryPutInPlayTargetPlayerEffect extends SearchEffect { return false; } - private void setText() { - StringBuilder sb = new StringBuilder(); - sb.append("target player searches their library for "); - if (target.getNumberOfTargets() == 0 && target.getMaxNumberOfTargets() > 0) { - if (target.getMaxNumberOfTargets() == Integer.MAX_VALUE) { - sb.append("any number of ").append(' '); - } else { - sb.append("up to ").append(target.getMaxNumberOfTargets()).append(' '); - } - sb.append(target.getTargetName()).append(", puts them onto the battlefield"); - } else { - sb.append("a ").append(target.getTargetName()).append(", puts it onto the battlefield"); + @Override + public String getText(Mode mode) { + if (staticText != null && !staticText.isEmpty()) { + return staticText; } - if (tapped) { - sb.append(" tapped"); - } - if (forceShuffle) { - sb.append(", then shuffles"); - } else { - sb.append(". If that player does, they shuffle"); - } - staticText = sb.toString(); + return getTargetPointer().describeTargets(mode.getTargets(), "that player") + + " searches their library for " + + target.getDescription() + + (forceShuffle ? ", " : " and ") + + (target.getMaxNumberOfTargets() > 1 ? "puts them onto the battlefield" : "puts it onto the battlefield") + + (tapped ? " tapped" : "") + + (forceShuffle ? ", then shuffles" : ". If that player does, they shuffle"); } - - public List getTargets() { - return target.getTargets(); - } - } diff --git a/Mage/src/main/java/mage/target/TargetImpl.java b/Mage/src/main/java/mage/target/TargetImpl.java index 233afdaaaa6..98ba0d54fa4 100644 --- a/Mage/src/main/java/mage/target/TargetImpl.java +++ b/Mage/src/main/java/mage/target/TargetImpl.java @@ -119,7 +119,11 @@ public abstract class TargetImpl implements Target { if (!isNotTarget() && !getTargetName().contains("target")) { sb.append("target "); } - sb.append(getTargetName()); + if (isNotTarget() && min == 1 && max == 1) { + sb.append(CardUtil.addArticle(getTargetName())); + } else { + sb.append(getTargetName()); + } return sb.toString(); } diff --git a/Mage/src/main/java/mage/target/common/TargetBasicLandCard.java b/Mage/src/main/java/mage/target/common/TargetBasicLandCard.java deleted file mode 100644 index 8c6ac750b17..00000000000 --- a/Mage/src/main/java/mage/target/common/TargetBasicLandCard.java +++ /dev/null @@ -1,30 +0,0 @@ - - -package mage.target.common; - -import mage.constants.CardType; -import mage.constants.SuperType; -import mage.constants.Zone; -import mage.target.TargetCard; - -/** - * - * @author BetaSteward_at_googlemail.com - */ -public class TargetBasicLandCard extends TargetCard { - - public TargetBasicLandCard(Zone zone) { - super(zone); - filter.add(SuperType.BASIC.getPredicate()); - filter.add(CardType.LAND.getPredicate()); - } - - public TargetBasicLandCard(final TargetBasicLandCard target) { - super(target); - } - - @Override - public TargetBasicLandCard copy() { - return new TargetBasicLandCard(this); - } -}