From e2f22d3bc98db8e16f4343241ff6c608f542dfc0 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Tue, 15 May 2018 17:56:55 +0200 Subject: [PATCH] Reworked some card movement handling (#4866). --- .../src/mage/cards/a/AcademyResearchers.java | 4 +- Mage.Sets/src/mage/cards/a/AccursedWitch.java | 7 +- Mage.Sets/src/mage/cards/a/AllHallowsEve.java | 10 +-- .../src/mage/cards/a/AngelOfGlorysRise.java | 29 +++---- .../src/mage/cards/a/ArachnusSpinner.java | 34 ++++---- .../src/mage/cards/a/AuratouchedMage.java | 26 ++++--- .../src/mage/cards/b/BreakingEntering.java | 8 +- .../src/mage/cards/c/CharmedGriffin.java | 4 +- .../src/mage/cards/c/CollectiveVoyage.java | 10 +-- .../mage/cards/d/DarigaazReincarnated.java | 17 ++-- .../src/mage/cards/d/DarkSupplicant.java | 78 +++++++++---------- Mage.Sets/src/mage/cards/d/DoublingChant.java | 64 ++++++++------- Mage.Sets/src/mage/cards/d/DreadSlaver.java | 12 +-- .../src/mage/cards/d/DruidicSatchel.java | 25 +++--- Mage.Sets/src/mage/cards/e/Evershrike.java | 20 ++--- .../src/mage/cards/g/GateToTheAfterlife.java | 11 ++- .../src/mage/cards/p/PraetorsCounsel.java | 23 +++--- .../effects/common/CreateTokenEffect.java | 6 +- .../main/java/mage/players/PlayerImpl.java | 9 +++ 19 files changed, 199 insertions(+), 198 deletions(-) diff --git a/Mage.Sets/src/mage/cards/a/AcademyResearchers.java b/Mage.Sets/src/mage/cards/a/AcademyResearchers.java index d57acd4553d..965f5c223f8 100644 --- a/Mage.Sets/src/mage/cards/a/AcademyResearchers.java +++ b/Mage.Sets/src/mage/cards/a/AcademyResearchers.java @@ -54,7 +54,7 @@ import mage.target.common.TargetCardInHand; public class AcademyResearchers extends CardImpl { public AcademyResearchers(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{U}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.WIZARD); @@ -104,7 +104,7 @@ class AcademyResearchersEffect extends OneShotEffect { Card auraInHand = game.getCard(target.getFirstTarget()); if (auraInHand != null) { game.getState().setValue("attachTo:" + auraInHand.getId(), academyResearchers); - auraInHand.putOntoBattlefield(game, Zone.HAND, source.getSourceId(), controller.getId()); + controller.moveCards(auraInHand, Zone.BATTLEFIELD, source, game); if (academyResearchers.addAttachment(auraInHand.getId(), game)) { game.informPlayers(controller.getLogName() + " put " + auraInHand.getLogName() + " on the battlefield attached to " + academyResearchers.getLogName() + '.'); return true; diff --git a/Mage.Sets/src/mage/cards/a/AccursedWitch.java b/Mage.Sets/src/mage/cards/a/AccursedWitch.java index f3fcf894818..c81b3be1ca5 100644 --- a/Mage.Sets/src/mage/cards/a/AccursedWitch.java +++ b/Mage.Sets/src/mage/cards/a/AccursedWitch.java @@ -37,10 +37,10 @@ import mage.abilities.common.SimpleStaticAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.cost.CostModificationEffectImpl; import mage.abilities.keyword.TransformAbility; -import mage.cards.i.InfectiousCurse; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.cards.i.InfectiousCurse; import mage.constants.*; import mage.game.Game; import mage.game.permanent.Permanent; @@ -55,7 +55,7 @@ import mage.util.CardUtil; public class AccursedWitch extends CardImpl { public AccursedWitch(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.SHAMAN); this.power = new MageInt(4); @@ -106,8 +106,7 @@ class AccursedWitchReturnTransformedEffect extends OneShotEffect { //note: should check for null after game.getCard Card card = game.getCard(source.getSourceId()); if (card != null) { - card.removeFromZone(game, Zone.GRAVEYARD, source.getSourceId()); - card.putOntoBattlefield(game, Zone.BATTLEFIELD, source.getSourceId(), source.getControllerId(), false); + controller.moveCards(card, Zone.BATTLEFIELD, source, game); } } return true; diff --git a/Mage.Sets/src/mage/cards/a/AllHallowsEve.java b/Mage.Sets/src/mage/cards/a/AllHallowsEve.java index ea588cba6ba..e79afec154b 100644 --- a/Mage.Sets/src/mage/cards/a/AllHallowsEve.java +++ b/Mage.Sets/src/mage/cards/a/AllHallowsEve.java @@ -41,7 +41,7 @@ import mage.constants.Outcome; import mage.constants.TargetController; import mage.constants.Zone; import mage.counters.CounterType; -import mage.filter.common.FilterCreatureCard; +import mage.filter.StaticFilters; import mage.game.Game; import mage.players.Player; @@ -101,18 +101,12 @@ class AllHallowsEveEffect extends OneShotEffect { allHallowsEve.getCounters(game).removeCounter(CounterType.SCREAM, 1); if (allHallowsEve.getCounters(game).getCount(CounterType.SCREAM) == 0) { allHallowsEve.moveToZone(Zone.GRAVEYARD, source.getId(), game, false); - Cards creatures = new CardsImpl(); for (UUID playerId : game.getState().getPlayersInRange(controller.getId(), game)) { Player player = game.getPlayer(playerId); if (player != null) { - for (Card creatureCard : player.getGraveyard().getCards(new FilterCreatureCard(), game)) { - creatures.add(creatureCard); - } + player.moveCards(player.getGraveyard().getCards(StaticFilters.FILTER_CARD_CREATURE, game), Zone.BATTLEFIELD, source, game); } } - for (Card card : creatures.getCards(game)) { - card.putOntoBattlefield(game, Zone.GRAVEYARD, source.getId(), card.getOwnerId()); - } } return true; } diff --git a/Mage.Sets/src/mage/cards/a/AngelOfGlorysRise.java b/Mage.Sets/src/mage/cards/a/AngelOfGlorysRise.java index b44b630479c..39355c6b025 100644 --- a/Mage.Sets/src/mage/cards/a/AngelOfGlorysRise.java +++ b/Mage.Sets/src/mage/cards/a/AngelOfGlorysRise.java @@ -27,6 +27,8 @@ */ package mage.cards.a; +import java.util.HashSet; +import java.util.Set; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; @@ -44,7 +46,6 @@ import mage.filter.common.FilterCreatureCard; import mage.filter.common.FilterCreaturePermanent; import mage.filter.predicate.mageobject.SubtypePredicate; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.players.Player; /** @@ -54,7 +55,7 @@ import mage.players.Player; public class AngelOfGlorysRise extends CardImpl { public AngelOfGlorysRise(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{5}{W}{W}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{W}{W}"); this.subtype.add(SubType.ANGEL); this.power = new MageInt(4); @@ -79,14 +80,6 @@ public class AngelOfGlorysRise extends CardImpl { class AngelOfGlorysRiseEffect extends OneShotEffect { - private static final FilterCreatureCard filterHuman = new FilterCreatureCard(); - private static final FilterCreaturePermanent filterZombie = new FilterCreaturePermanent(); - - static { - filterZombie.add(new SubtypePredicate(SubType.ZOMBIE)); - filterHuman.add(new SubtypePredicate(SubType.HUMAN)); - } - public AngelOfGlorysRiseEffect() { super(Outcome.PutCreatureInPlay); staticText = "Exile all Zombies, then return all Human creature cards from your graveyard to the battlefield"; @@ -103,14 +96,14 @@ class AngelOfGlorysRiseEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player != null) { - for (Permanent zombie : game.getBattlefield().getActivePermanents(filterZombie, source.getControllerId(), source.getSourceId(), game)) { - zombie.moveToExile(source.getSourceId(), zombie.getName(), source.getSourceId(), game); - } - for (Card human : player.getGraveyard().getCards(filterHuman, game)) { - human.putOntoBattlefield(game, Zone.GRAVEYARD, source.getSourceId(), source.getControllerId()); - } + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Set toExile = new HashSet<>(game.getBattlefield() + .getActivePermanents(new FilterCreaturePermanent(SubType.ZOMBIE, "Zombie"), source.getControllerId(), source.getSourceId(), game)); + controller.moveCards(toExile, Zone.EXILED, source, game); + FilterCreatureCard filterHuman = new FilterCreatureCard(); + filterHuman.add(new SubtypePredicate(SubType.HUMAN)); + controller.moveCards(controller.getGraveyard().getCards(filterHuman, game), Zone.GRAVEYARD, source, game); } return true; } diff --git a/Mage.Sets/src/mage/cards/a/ArachnusSpinner.java b/Mage.Sets/src/mage/cards/a/ArachnusSpinner.java index ebd60604248..c9e8c9982a5 100644 --- a/Mage.Sets/src/mage/cards/a/ArachnusSpinner.java +++ b/Mage.Sets/src/mage/cards/a/ArachnusSpinner.java @@ -69,7 +69,7 @@ public class ArachnusSpinner extends CardImpl { } public ArachnusSpinner(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{5}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{5}{G}"); this.subtype.add(SubType.SPIDER); this.power = new MageInt(5); @@ -98,8 +98,10 @@ public class ArachnusSpinner extends CardImpl { class ArachnusSpinnerEffect extends OneShotEffect { public ArachnusSpinnerEffect() { - super(Outcome.UnboostCreature); - this.staticText = "Search your graveyard and/or library for a card named Arachnus Web and put it onto the battlefield attached to target creature. If you search your library this way, shuffle it"; + super(Outcome.PutCardInPlay); + this.staticText = "Search your graveyard and/or library for a card named Arachnus Web " + + "and put it onto the battlefield attached to target creature. " + + "If you search your library this way, shuffle it"; } public ArachnusSpinnerEffect(final ArachnusSpinnerEffect effect) { @@ -113,8 +115,8 @@ class ArachnusSpinnerEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player == null) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { return false; } @@ -122,34 +124,28 @@ class ArachnusSpinnerEffect extends OneShotEffect { filter.add(new NamePredicate("Arachnus Web")); Card card = null; - Zone zone = null; - if (player.chooseUse(Outcome.Neutral, "Search your graveyard for Arachnus Web?", source, game)) { + if (controller.chooseUse(Outcome.Neutral, "Search your graveyard for Arachnus Web?", source, game)) { TargetCardInYourGraveyard target = new TargetCardInYourGraveyard(filter); - if (player.choose(Outcome.PutCardInPlay, player.getGraveyard(), target, game)) { + if (controller.choose(Outcome.PutCardInPlay, controller.getGraveyard(), target, game)) { card = game.getCard(target.getFirstTarget()); - if (card != null) { - zone = Zone.GRAVEYARD; - } } } if (card == null) { TargetCardInLibrary target = new TargetCardInLibrary(filter); - if (player.searchLibrary(target, game)) { + if (controller.searchLibrary(target, game)) { card = game.getCard(target.getFirstTarget()); - if (card != null) { - zone = Zone.LIBRARY; - } } - player.shuffleLibrary(source, game); + controller.shuffleLibrary(source, game); } if (card != null) { Permanent permanent = game.getPermanent(source.getFirstTarget()); if (permanent != null) { game.getState().setValue("attachTo:" + card.getId(), permanent.getId()); - card.putOntoBattlefield(game, zone, source.getSourceId(), source.getControllerId()); - return permanent.addAttachment(card.getId(), game); + if (controller.moveCards(card, Zone.BATTLEFIELD, source, game)) { + permanent.addAttachment(card.getId(), game); // shouldn't this be done automatically by the logic using the "attachTo:" calue? + } } } - return false; + return true; } } diff --git a/Mage.Sets/src/mage/cards/a/AuratouchedMage.java b/Mage.Sets/src/mage/cards/a/AuratouchedMage.java index 5db38557b08..5c0dee373c1 100644 --- a/Mage.Sets/src/mage/cards/a/AuratouchedMage.java +++ b/Mage.Sets/src/mage/cards/a/AuratouchedMage.java @@ -88,28 +88,32 @@ class AuratouchedMageEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - Permanent auratouchedMage = game.getPermanentOrLKIBattlefield(source.getSourceId()); //must be LKI to resolve - if (controller != null && auratouchedMage != null) { - FilterCard filter = new FilterCard("aura that could enchant " + auratouchedMage.getName()); + + if (controller != null) { + FilterCard filter = new FilterCard("aura that could enchant " + source.getSourceObject(game).getName()); filter.add(new SubtypePredicate(SubType.AURA)); - filter.add(new AuraCardCanAttachToLKIPermanentId(auratouchedMage.getId())); + filter.add(new AuraCardCanAttachToLKIPermanentId(source.getSourceId())); TargetCardInLibrary target = new TargetCardInLibrary(filter); target.setNotTarget(true); if (controller.searchLibrary(target, game)) { if (target.getFirstTarget() != null) { Card aura = game.getCard(target.getFirstTarget()); - if (game.getBattlefield().containsPermanent(auratouchedMage.getId())) { //verify that it is still on the battlefield + Permanent auratouchedMage = source.getSourcePermanentIfItStillExists(game); + if (aura != null && auratouchedMage != null + && game.getState().getZoneChangeCounter(source.getSourceId()) == source.getSourceObjectZoneChangeCounter()) { game.getState().setValue("attachTo:" + aura.getId(), auratouchedMage); - aura.putOntoBattlefield(game, Zone.LIBRARY, source.getSourceId(), controller.getId()); - return auratouchedMage.addAttachment(aura.getId(), game); + if (controller.moveCards(aura, Zone.BATTLEFIELD, source, game)) { + auratouchedMage.addAttachment(aura.getId(), game); + } + } else { + Cards auraRevealed = new CardsImpl(aura); + controller.revealCards(source, auraRevealed, game); + controller.moveCards(aura, Zone.HAND, source, game); } - Cards auraRevealed = new CardsImpl(); - auraRevealed.add(aura); - controller.revealCards(auratouchedMage.getName(), auraRevealed, game); - controller.putInHand(aura, game); } } controller.shuffleLibrary(source, game); + return true; } return false; } diff --git a/Mage.Sets/src/mage/cards/b/BreakingEntering.java b/Mage.Sets/src/mage/cards/b/BreakingEntering.java index 9779e83afc7..9a3756f8164 100644 --- a/Mage.Sets/src/mage/cards/b/BreakingEntering.java +++ b/Mage.Sets/src/mage/cards/b/BreakingEntering.java @@ -94,15 +94,15 @@ class EnteringReturnFromGraveyardToBattlefieldEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - if (player != null) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { Target target = new TargetCardInGraveyard(new FilterCreatureCard()); target.setNotTarget(true); if (target.canChoose(source.getSourceId(), source.getControllerId(), game) - && player.chooseTarget(outcome, target, source, game)) { + && controller.chooseTarget(outcome, target, source, game)) { Card card = game.getCard(target.getFirstTarget()); if (card != null) { - if (card.putOntoBattlefield(game, Zone.GRAVEYARD, source.getSourceId(), source.getControllerId())) { + if (controller.moveCards(card, Zone.BATTLEFIELD, source, game)) { ContinuousEffect effect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.EndOfTurn); effect.setTargetPointer(new FixedTarget(card.getId())); game.addEffect(effect, source); diff --git a/Mage.Sets/src/mage/cards/c/CharmedGriffin.java b/Mage.Sets/src/mage/cards/c/CharmedGriffin.java index c596f29aa67..93e724de4f8 100644 --- a/Mage.Sets/src/mage/cards/c/CharmedGriffin.java +++ b/Mage.Sets/src/mage/cards/c/CharmedGriffin.java @@ -37,8 +37,8 @@ import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Outcome; +import mage.constants.SubType; import mage.constants.Zone; import mage.filter.common.FilterArtifactOrEnchantmentCard; import mage.game.Game; @@ -105,7 +105,7 @@ class CharmedGriffinEffect extends OneShotEffect { && player.choose(Outcome.PutCardInPlay, target, source.getSourceId(), game)) { Card card = game.getCard(target.getFirstTarget()); if (card != null) { - card.putOntoBattlefield(game, Zone.HAND, source.getSourceId(), player.getId()); + controller.moveCards(card, Zone.BATTLEFIELD, source, game); } } } diff --git a/Mage.Sets/src/mage/cards/c/CollectiveVoyage.java b/Mage.Sets/src/mage/cards/c/CollectiveVoyage.java index 88728d60278..bd26b4b5564 100644 --- a/Mage.Sets/src/mage/cards/c/CollectiveVoyage.java +++ b/Mage.Sets/src/mage/cards/c/CollectiveVoyage.java @@ -33,9 +33,9 @@ import mage.abilities.Ability; import mage.abilities.costs.Cost; import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.OneShotEffect; -import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.cards.CardsImpl; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Zone; @@ -103,13 +103,7 @@ class CollectiveVoyageEffect extends OneShotEffect { if (player != null) { TargetCardInLibrary target = new TargetCardInLibrary(0, xSum, StaticFilters.FILTER_BASIC_LAND_CARD); if (player.searchLibrary(target, game)) { - for (UUID cardId : target.getTargets()) { - Card card = player.getLibrary().getCard(cardId, game); - if (card != null) { - card.putOntoBattlefield(game, Zone.LIBRARY, source.getSourceId(), player.getId(), true); - } - - } + player.moveCards(new CardsImpl(target.getTargets()).getCards(game), Zone.BATTLEFIELD, source, game, true, false, true, null); player.shuffleLibrary(source, game); } diff --git a/Mage.Sets/src/mage/cards/d/DarigaazReincarnated.java b/Mage.Sets/src/mage/cards/d/DarigaazReincarnated.java index 12d2e821777..c381ca3fa52 100644 --- a/Mage.Sets/src/mage/cards/d/DarigaazReincarnated.java +++ b/Mage.Sets/src/mage/cards/d/DarigaazReincarnated.java @@ -29,6 +29,7 @@ package mage.cards.d; import java.util.UUID; import mage.MageInt; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.SimpleStaticAbility; @@ -181,14 +182,18 @@ class DarigaazReincarnatedReturnEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - Card card = game.getCard(source.getSourceId()); - if (player == null || card == null) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { return false; } - new RemoveCounterSourceEffect(CounterType.EGG.createInstance()).apply(game, source); - if (card.getCounters(game).getCount(CounterType.EGG) == 0) { - return card.putOntoBattlefield(game, Zone.EXILED, source.getSourceId(), player.getId()); + MageObject sourceObject = source.getSourceObjectIfItStillExists(game); + if (sourceObject != null && sourceObject instanceof Card) { + Card card = (Card) sourceObject; + new RemoveCounterSourceEffect(CounterType.EGG.createInstance()).apply(game, source); + if (card.getCounters(game).getCount(CounterType.EGG) == 0) { + controller.moveCards(card, Zone.BATTLEFIELD, source, game); + } + return true; } return false; } diff --git a/Mage.Sets/src/mage/cards/d/DarkSupplicant.java b/Mage.Sets/src/mage/cards/d/DarkSupplicant.java index 34d342b90d2..11ea6f0ef41 100644 --- a/Mage.Sets/src/mage/cards/d/DarkSupplicant.java +++ b/Mage.Sets/src/mage/cards/d/DarkSupplicant.java @@ -27,7 +27,6 @@ */ package mage.cards.d; -import java.util.List; import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; @@ -38,7 +37,6 @@ import mage.abilities.effects.OneShotEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.cards.Cards; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SubType; @@ -49,7 +47,9 @@ import mage.filter.predicate.mageobject.NamePredicate; import mage.filter.predicate.mageobject.SubtypePredicate; import mage.game.Game; import mage.players.Player; +import mage.target.common.TargetCardInHand; import mage.target.common.TargetCardInLibrary; +import mage.target.common.TargetCardInYourGraveyard; import mage.target.common.TargetControlledPermanent; /** @@ -65,14 +65,14 @@ public class DarkSupplicant extends CardImpl { } public DarkSupplicant(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{B}"); this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.CLERIC); this.power = new MageInt(1); this.toughness = new MageInt(1); - // {tap}, Sacrifice three Clerics: Search your graveyard, hand, and/or library for a card named Scion of Darkness and put it onto the battlefield. If you search your library this way, shuffle it. + // {T}, Sacrifice three Clerics: Search your graveyard, hand, and/or library for a card named Scion of Darkness and put it onto the battlefield. If you search your library this way, shuffle it. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DarkSupplicantEffect(), new TapSourceCost()); ability.addCost(new SacrificeTargetCost(new TargetControlledPermanent(3, 3, filter, true))); this.addAbility(ability); @@ -91,7 +91,7 @@ public class DarkSupplicant extends CardImpl { class DarkSupplicantEffect extends OneShotEffect { public DarkSupplicantEffect() { - super(Outcome.Benefit); + super(Outcome.PutCardInPlay); this.staticText = "Search your graveyard, hand, and/or library for a card named Scion of Darkness and put it onto the battlefield. If you search your library this way, shuffle it"; } @@ -106,51 +106,49 @@ class DarkSupplicantEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); + Player controller = game.getPlayer(source.getControllerId()); FilterCard filter = new FilterCard("card named Scion of Darkness"); filter.add(new NamePredicate("Scion of Darkness")); - TargetCardInLibrary target = new TargetCardInLibrary(filter); - if (player == null) { + if (controller == null) { return false; } - // Library check - if (player.chooseUse(Outcome.Benefit, "Do you want to search your library for Scion of Darkness?", source, game)) { - if (player.searchLibrary(target, game)) { - if (!target.getTargets().isEmpty()) { - for (UUID cardId : (List) target.getTargets()) { - Card card = player.getLibrary().getCard(cardId, game); - if (card != null) { - if (card.putOntoBattlefield(game, Zone.LIBRARY, source.getSourceId(), source.getControllerId())) { - return true; - } - } - } - } - } - player.shuffleLibrary(source, game); - } + Card selectedCard = null; // Graveyard check - if (player.chooseUse(Outcome.Benefit, "Do you want to search your graveyard for Scion of Darkness?", source, game)) { - Cards graveyard = player.getGraveyard().copy(); - for (UUID card : graveyard) { - Card checkCard = game.getCard(card); - if (checkCard.getName().equals("Scion of Darkness")) { - checkCard.putOntoBattlefield(game, Zone.GRAVEYARD, source.getSourceId(), source.getControllerId()); - return true; - } + if (controller.chooseUse(Outcome.Benefit, "Do you want to search your graveyard for Scion of Darkness?", source, game)) { + TargetCardInYourGraveyard target = new TargetCardInYourGraveyard(1, 1, filter, true); + if (controller.choose(outcome, controller.getGraveyard(), target, game)) { + selectedCard = game.getCard(target.getFirstTarget()); } } // Hand check - if (player.chooseUse(Outcome.Benefit, "Do you want to search your hand for Scion of Darkness?", source, game)) { - Cards hand = player.getHand().copy(); - for (UUID card : hand) { - Card checkCard = game.getCard(card); - if (checkCard.getName().equals("Scion of Darkness")) { - checkCard.putOntoBattlefield(game, Zone.HAND, source.getSourceId(), source.getControllerId()); - return true; + if (selectedCard == null + && controller.chooseUse(Outcome.Benefit, "Do you want to search your hand for Scion of Darkness?", source, game)) { + TargetCardInHand target = new TargetCardInHand(0, 1, filter); + if (controller.choose(Outcome.PutCardInPlay, controller.getHand(), target, game)) { + if (!target.getTargets().isEmpty()) { + selectedCard = game.getCard(target.getFirstTarget()); } } } - return false; + // Library check + boolean librarySearched = false; + if (selectedCard == null + && controller.chooseUse(Outcome.Benefit, "Do you want to search your library for Scion of Darkness?", source, game)) { + librarySearched = true; + TargetCardInLibrary target = new TargetCardInLibrary(0, 1, filter); + if (controller.searchLibrary(target, game)) { + if (!target.getTargets().isEmpty()) { + selectedCard = game.getCard(target.getFirstTarget()); + } + } + + } + if (selectedCard != null) { + controller.moveCards(selectedCard, Zone.BATTLEFIELD, source, game); + } + if (librarySearched) { + controller.shuffleLibrary(source, game); + } + return true; } } diff --git a/Mage.Sets/src/mage/cards/d/DoublingChant.java b/Mage.Sets/src/mage/cards/d/DoublingChant.java index 61f724ed0d7..7e1cb668100 100644 --- a/Mage.Sets/src/mage/cards/d/DoublingChant.java +++ b/Mage.Sets/src/mage/cards/d/DoublingChant.java @@ -28,7 +28,9 @@ package mage.cards.d; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; @@ -40,6 +42,8 @@ import mage.constants.Outcome; import mage.constants.Zone; import mage.filter.StaticFilters; import mage.filter.common.FilterCreatureCard; +import mage.filter.predicate.Predicates; +import mage.filter.predicate.mageobject.CardIdPredicate; import mage.filter.predicate.mageobject.NamePredicate; import mage.game.Game; import mage.game.permanent.Permanent; @@ -55,6 +59,8 @@ public class DoublingChant extends CardImpl { public DoublingChant(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{5}{G}"); + // For each creature you control, you may search your library for a creature card with the same name as that creature. + // Put those cards onto the battlefield, then shuffle your library. this.getSpellAbility().addEffect(new DoublingChantEffect()); } @@ -86,41 +92,43 @@ class DoublingChantEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - List chosenCards = new ArrayList<>(); - List namesFiltered = new ArrayList<>(); - - Player player = game.getPlayer(source.getControllerId()); - if (player == null) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { return false; } + Set chosenCards = new HashSet<>(); List creatures = game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), game); - for (Permanent creature : creatures) { - final String creatureName = creature.getName(); - if (!namesFiltered.contains(creatureName)) { - StringBuilder sb = new StringBuilder(); - sb.append("Search for ").append(creatureName).append(" in your library?"); - - if (player.chooseUse(Outcome.PutCreatureInPlay, sb.toString(), source, game)) { - FilterCreatureCard filter = new FilterCreatureCard("creature card named" + creatureName); - filter.add(new NamePredicate(creatureName)); - TargetCardInLibrary target = new TargetCardInLibrary(filter); - - if (player.searchLibrary(target, game)) { - Card card = player.getLibrary().getCard(target.getFirstTarget(), game); - if (card != null) { - chosenCards.add(card); - } - } - } else { - namesFiltered.add(creatureName); - } + if (creatures.isEmpty()) { + //9/22/2011: If you control no creatures when Doubling Chant resolves, you may still search your library and you must shuffle your library. + if (controller.chooseUse(Outcome.PutCreatureInPlay, "Search in your library?", source, game)) { + FilterCreatureCard filter = new FilterCreatureCard("nothing (no valid card available)"); + filter.add(new NamePredicate("creatureName")); + TargetCardInLibrary target = new TargetCardInLibrary(0, 1, filter); + controller.searchLibrary(target, game); } } + for (Permanent creature : creatures) { + final String creatureName = creature.getName(); + List uuidPredicates = new ArrayList<>(); + if (controller.chooseUse(Outcome.PutCreatureInPlay, "Search for " + creatureName + " in your library?", source, game)) { + FilterCreatureCard filter = new FilterCreatureCard("creature card named " + creatureName); + filter.add(new NamePredicate(creatureName)); + if (!uuidPredicates.isEmpty()) { // Prevent to select a card twice + filter.add(Predicates.not(Predicates.or(uuidPredicates))); + } + TargetCardInLibrary target = new TargetCardInLibrary(filter); + if (controller.searchLibrary(target, game)) { + Card card = controller.getLibrary().getCard(target.getFirstTarget(), game); + if (card != null) { + chosenCards.add(card); + uuidPredicates.add(new CardIdPredicate(card.getId())); + } + } + } - for (Card card : chosenCards) { - card.putOntoBattlefield(game, Zone.LIBRARY, source.getSourceId(), source.getControllerId()); } - player.shuffleLibrary(source, game); + controller.moveCards(chosenCards, Zone.BATTLEFIELD, source, game); + controller.shuffleLibrary(source, game); return true; } } diff --git a/Mage.Sets/src/mage/cards/d/DreadSlaver.java b/Mage.Sets/src/mage/cards/d/DreadSlaver.java index ce4f156e907..27028db67b2 100644 --- a/Mage.Sets/src/mage/cards/d/DreadSlaver.java +++ b/Mage.Sets/src/mage/cards/d/DreadSlaver.java @@ -39,17 +39,16 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; import mage.game.Game; +import mage.players.Player; import mage.target.targetpointer.FixedTarget; - - /** * @author noxx */ public class DreadSlaver extends CardImpl { public DreadSlaver(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{B}{B}"); this.subtype.add(SubType.ZOMBIE); this.subtype.add(SubType.HORROR); @@ -88,10 +87,13 @@ class DreadSlaverEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } Card card = game.getCard(targetPointer.getFirst(game, source)); if (card != null) { - Zone currentZone = game.getState().getZone(card.getId()); - if (card.putOntoBattlefield(game, currentZone, source.getSourceId(), source.getControllerId())) { + if (controller.moveCards(card, Zone.BATTLEFIELD, source, game)) { ContinuousEffect effect = new BecomesBlackZombieAdditionEffect(); effect.setTargetPointer(new FixedTarget(card.getId())); game.addEffect(effect, source); diff --git a/Mage.Sets/src/mage/cards/d/DruidicSatchel.java b/Mage.Sets/src/mage/cards/d/DruidicSatchel.java index 2ab51a3e612..d2ffd5a27ad 100644 --- a/Mage.Sets/src/mage/cards/d/DruidicSatchel.java +++ b/Mage.Sets/src/mage/cards/d/DruidicSatchel.java @@ -39,8 +39,6 @@ import mage.constants.Outcome; import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.token.SaprolingToken; -import mage.game.permanent.token.TokenImpl; -import mage.game.permanent.token.Token; import mage.players.Player; /** @@ -80,27 +78,24 @@ class DruidicSatchelEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - Card card = player.getLibrary().getFromTop(game); + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + Card card = controller.getLibrary().getFromTop(game); if (card != null) { + controller.revealCards(source, new CardsImpl(card), game); if (card.isCreature()) { - Token token = new SaprolingToken(); - token.putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId()); + new SaprolingToken().putOntoBattlefield(1, game, source.getSourceId(), source.getControllerId()); } if (card.isLand()) { - player.getLibrary().getCard(card.getId(), game); - card.putOntoBattlefield(game, Zone.LIBRARY, source.getSourceId(), source.getControllerId()); + controller.moveCards(card, Zone.BATTLEFIELD, source, game); } if (!card.isCreature() && !card.isLand()) { - player.gainLife(2, game, source); + controller.gainLife(2, game, source); } - - Cards cards = new CardsImpl(); - cards.add(card); - player.revealCards("Druidic Satchel", cards, game); - return true; } - return false; + return true; } @Override diff --git a/Mage.Sets/src/mage/cards/e/Evershrike.java b/Mage.Sets/src/mage/cards/e/Evershrike.java index 6a17ed06235..586d1b8a2ee 100644 --- a/Mage.Sets/src/mage/cards/e/Evershrike.java +++ b/Mage.Sets/src/mage/cards/e/Evershrike.java @@ -99,37 +99,37 @@ class EvershrikeEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - boolean exiled = true; Card evershrikeCard = game.getCard(source.getSourceId()); Player controller = game.getPlayer(source.getControllerId()); - int xAmount = source.getManaCostsToPay().getX() + 1; - if (evershrikeCard != null) { + if (controller != null && evershrikeCard != null) { if (evershrikeCard.moveToZone(Zone.BATTLEFIELD, source.getSourceId(), game, false)) { + int xAmount = source.getManaCostsToPay().getX() + 1; Permanent evershrikePermanent = game.getPermanent(source.getSourceId()); if (evershrikePermanent == null) { return false; } + boolean exileSource = true; FilterCard filterAuraCard = new FilterCard("Aura card with converted mana cost X or less from your hand"); filterAuraCard.add(new CardTypePredicate(CardType.ENCHANTMENT)); filterAuraCard.add(new SubtypePredicate(SubType.AURA)); filterAuraCard.add(new AuraCardCanAttachToPermanentId(evershrikePermanent.getId())); filterAuraCard.add(new ConvertedManaCostPredicate(ComparisonType.FEWER_THAN, xAmount)); int count = controller.getHand().count(filterAuraCard, game); - while (controller.canRespond() && count > 0 && controller.chooseUse(Outcome.Benefit, "Do you wish to put an Aura card from your hand onto Evershrike", source, game)) { + if (count > 0 && controller.chooseUse(Outcome.Benefit, "Do you wish to put an Aura card from your hand onto " + evershrikeCard.getIdName() + "?", source, game)) { TargetCard targetAura = new TargetCard(Zone.HAND, filterAuraCard); if (controller.choose(Outcome.Benefit, controller.getHand(), targetAura, game)) { Card aura = game.getCard(targetAura.getFirstTarget()); if (aura != null) { game.getState().setValue("attachTo:" + aura.getId(), evershrikePermanent); - aura.putOntoBattlefield(game, Zone.HAND, source.getSourceId(), controller.getId()); - evershrikePermanent.addAttachment(aura.getId(), game); - exiled = false; - count = controller.getHand().count(filterAuraCard, game); + if (controller.moveCards(aura, Zone.BATTLEFIELD, source, game)) { + evershrikePermanent.addAttachment(aura.getId(), game); + } + exileSource = false; } } } - if (exiled) { - return evershrikePermanent.moveToExile(source.getSourceId(), "Evershrike Exile", source.getSourceId(), game); + if (exileSource) { + controller.moveCards(evershrikeCard, Zone.EXILED, source, game); } return true; } diff --git a/Mage.Sets/src/mage/cards/g/GateToTheAfterlife.java b/Mage.Sets/src/mage/cards/g/GateToTheAfterlife.java index 1f1879647e3..4b8cbaf2c57 100644 --- a/Mage.Sets/src/mage/cards/g/GateToTheAfterlife.java +++ b/Mage.Sets/src/mage/cards/g/GateToTheAfterlife.java @@ -132,20 +132,22 @@ class GateToTheAfterlifeEffect extends OneShotEffect { Card card = null; // Graveyard check if (controller.chooseUse(Outcome.Benefit, "Do you want to search your graveyard for " + cardName + "?", source, game)) { - TargetCardInYourGraveyard target = new TargetCardInYourGraveyard(filter); - if (controller.choose(Outcome.PutCardInPlay, controller.getGraveyard(), target, game)) { + TargetCardInYourGraveyard target = new TargetCardInYourGraveyard(1, 1, filter, true); + if (controller.choose(outcome, controller.getGraveyard(), target, game)) { card = game.getCard(target.getFirstTarget()); } } // Hand check if (card == null && controller.chooseUse(Outcome.Benefit, "Do you want to search your hand for " + cardName + "?", source, game)) { - TargetCardInHand target = new TargetCardInHand(filter); + TargetCardInHand target = new TargetCardInHand(0, 1, filter); if (controller.choose(Outcome.PutCardInPlay, controller.getHand(), target, game)) { card = game.getCard(target.getFirstTarget()); } } // Library check + boolean librarySearched = false; if (card == null && controller.chooseUse(Outcome.Benefit, "Do you want to search your library for " + cardName + "?", source, game)) { + librarySearched = true; TargetCardInLibrary target = new TargetCardInLibrary(filter); if (controller.searchLibrary(target, game)) { card = game.getCard(target.getFirstTarget()); @@ -155,6 +157,9 @@ class GateToTheAfterlifeEffect extends OneShotEffect { if (card != null) { controller.moveCards(card, Zone.BATTLEFIELD, source, game); } + if (librarySearched) { + controller.shuffleLibrary(source, game); + } return true; } } diff --git a/Mage.Sets/src/mage/cards/p/PraetorsCounsel.java b/Mage.Sets/src/mage/cards/p/PraetorsCounsel.java index 10ac47cf8f5..fc23566e4ce 100644 --- a/Mage.Sets/src/mage/cards/p/PraetorsCounsel.java +++ b/Mage.Sets/src/mage/cards/p/PraetorsCounsel.java @@ -1,16 +1,16 @@ /* * Copyright 2011 BetaSteward_at_googlemail.com. All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: - * + * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. - * + * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. - * + * * THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR @@ -20,7 +20,7 @@ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * + * * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. @@ -33,12 +33,12 @@ import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ExileSpellEffect; import mage.abilities.effects.common.continuous.MaximumHandSizeControllerEffect; import mage.abilities.effects.common.continuous.MaximumHandSizeControllerEffect.HandSizeModification; -import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Outcome; +import mage.constants.Zone; import mage.game.Game; import mage.players.Player; @@ -49,8 +49,9 @@ import mage.players.Player; public class PraetorsCounsel extends CardImpl { public PraetorsCounsel(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{5}{G}{G}{G}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{5}{G}{G}{G}"); + // Return all cards from your graveyard to your hand. Exile Praetor's Counsel. You have no maximum hand size for the rest of the game. this.getSpellAbility().addEffect(new PraetorsCounselEffect()); this.getSpellAbility().addEffect(ExileSpellEffect.getInstance()); this.getSpellAbility().addEffect(new MaximumHandSizeControllerEffect(Integer.MAX_VALUE, Duration.EndOfGame, HandSizeModification.SET)); @@ -85,11 +86,11 @@ class PraetorsCounselEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player player = game.getPlayer(source.getControllerId()); - for (Card card: player.getGraveyard().getCards(game)) { - player.putInHand(card, game); + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + controller.moveCards(controller.getGraveyard(), Zone.HAND, source, game); + return true; } - player.getGraveyard().clear(); return false; } diff --git a/Mage/src/main/java/mage/abilities/effects/common/CreateTokenEffect.java b/Mage/src/main/java/mage/abilities/effects/common/CreateTokenEffect.java index 46b82048c04..dc6a49c31c2 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/CreateTokenEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/CreateTokenEffect.java @@ -27,6 +27,8 @@ */ package mage.abilities.effects.common; +import java.util.ArrayList; +import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; import mage.abilities.common.delayed.AtTheEndOfCombatDelayedTriggeredAbility; @@ -37,14 +39,10 @@ import mage.constants.Outcome; import mage.constants.Zone; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.game.permanent.token.TokenImpl; import mage.game.permanent.token.Token; import mage.target.targetpointer.FixedTarget; import mage.util.CardUtil; -import java.util.ArrayList; -import java.util.UUID; - /** * * @author BetaSteward_at_googlemail.com diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index 6a0524ddc61..a2be32c19e4 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -655,6 +655,15 @@ public abstract class PlayerImpl implements Player, Serializable { } } + /** + * Don't use this in normal card code, it's for more internal use. Always + * use the [Player].moveCards methods if possible for card movement of card + * code. + * + * @param card + * @param game + * @return + */ @Override public boolean putInHand(Card card, Game game) { if (card.getOwnerId().equals(playerId)) {