From 27b85bca88398d8bda75500a27073ef54955f65d Mon Sep 17 00:00:00 2001 From: jeffwadsworth <> Date: Wed, 24 Feb 2021 15:25:08 -0600 Subject: [PATCH] - S cards: A player now moves the card/permanent to a zone. --- Mage.Sets/src/mage/cards/s/SearchTheCity.java | 10 +++-- Mage.Sets/src/mage/cards/s/SecondSunrise.java | 32 ++++++++++----- .../src/mage/cards/s/SengirNosferatu.java | 23 +++++------ .../src/mage/cards/s/SorinGrimNemesis.java | 41 +++++++++---------- Mage.Sets/src/mage/cards/s/Soulquake.java | 18 +++++--- Mage.Sets/src/mage/cards/s/SteamAugury.java | 10 +++-- Mage.Sets/src/mage/cards/s/SunkenHope.java | 6 +-- Mage.Sets/src/mage/cards/s/SurrealMemoir.java | 18 ++++---- 8 files changed, 91 insertions(+), 67 deletions(-) diff --git a/Mage.Sets/src/mage/cards/s/SearchTheCity.java b/Mage.Sets/src/mage/cards/s/SearchTheCity.java index 95427da935f..1454aa0b2dd 100644 --- a/Mage.Sets/src/mage/cards/s/SearchTheCity.java +++ b/Mage.Sets/src/mage/cards/s/SearchTheCity.java @@ -15,7 +15,6 @@ import mage.filter.predicate.mageobject.NamePredicate; import mage.game.ExileZone; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.events.GameEvent.EventType; import mage.game.permanent.Permanent; import mage.game.stack.Spell; import mage.game.turn.TurnMod; @@ -154,11 +153,16 @@ class SearchTheCityExiledCardToHandEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { String cardName = (String) this.getValue("cardName"); + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } ExileZone searchTheCityExileZone = game.getExile().getExileZone(source.getSourceId()); - if (cardName != null && searchTheCityExileZone != null) { + if (cardName != null + && searchTheCityExileZone != null) { for (Card card : searchTheCityExileZone.getCards(game)) { if (CardUtil.haveSameNames(card, cardName, game)) { - if (card.moveToZone(Zone.HAND, source, game, true)) { + if (controller.moveCards(card, Zone.HAND, source, game)) { game.informPlayers("Search the City: put " + card.getName() + " into owner's hand"); } searchTheCityExileZone.remove(card); diff --git a/Mage.Sets/src/mage/cards/s/SecondSunrise.java b/Mage.Sets/src/mage/cards/s/SecondSunrise.java index ea869b2237e..2f22582456c 100644 --- a/Mage.Sets/src/mage/cards/s/SecondSunrise.java +++ b/Mage.Sets/src/mage/cards/s/SecondSunrise.java @@ -1,4 +1,3 @@ - package mage.cards.s; import mage.abilities.Ability; @@ -16,8 +15,11 @@ import mage.game.events.ZoneChangeEvent; import mage.watchers.Watcher; import java.util.ArrayList; +import java.util.LinkedHashSet; import java.util.List; +import java.util.Set; import java.util.UUID; +import mage.players.Player; /** * @@ -26,8 +28,7 @@ import java.util.UUID; public final class SecondSunrise extends CardImpl { public SecondSunrise(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{W}{W}"); - + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}{W}"); // Each player returns to the battlefield all artifact, creature, enchantment, and land cards in their graveyard that were put there from the battlefield this turn. this.getSpellAbility().addEffect(new SecondSunriseEffect()); @@ -59,12 +60,21 @@ class SecondSunriseEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { SecondSunriseWatcher watcher = game.getState().getWatcher(SecondSunriseWatcher.class); if (watcher != null) { + Set cardsToBattlefield = new LinkedHashSet<>(); for (UUID id : watcher.getCards()) { - Card c = game.getCard(id); - if (c != null && game.getState().getZone(id) == Zone.GRAVEYARD) { - if (c.isArtifact() || c.isCreature() || - c.isEnchantment() || c.isLand()) - c.moveToZone(Zone.BATTLEFIELD, source, game, false); + Card card = game.getCard(id); + if (card != null + && game.getState().getZone(id) == Zone.GRAVEYARD) { + if (card.isArtifact() || card.isCreature() + || card.isEnchantment() || card.isLand()) { + cardsToBattlefield.add(card); + } + } + } + for (Card card : cardsToBattlefield) { + Player owner = game.getPlayer(card.getOwnerId()); + if (owner != null) { + owner.moveCards(card, Zone.BATTLEFIELD, source, game); } } return true; @@ -79,6 +89,7 @@ class SecondSunriseEffect extends OneShotEffect { } class SecondSunriseWatcher extends Watcher { + private List cards = new ArrayList<>(); public SecondSunriseWatcher() { @@ -87,7 +98,8 @@ class SecondSunriseWatcher extends Watcher { @Override public void watch(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.ZONE_CHANGE && ((ZoneChangeEvent)event).isDiesEvent()) { + if (event.getType() == GameEvent.EventType.ZONE_CHANGE + && ((ZoneChangeEvent) event).isDiesEvent()) { cards.add(event.getTargetId()); } } @@ -98,7 +110,7 @@ class SecondSunriseWatcher extends Watcher { cards.clear(); } - public List getCards(){ + public List getCards() { return cards; } } diff --git a/Mage.Sets/src/mage/cards/s/SengirNosferatu.java b/Mage.Sets/src/mage/cards/s/SengirNosferatu.java index 3465c596bfd..7bf5b366653 100644 --- a/Mage.Sets/src/mage/cards/s/SengirNosferatu.java +++ b/Mage.Sets/src/mage/cards/s/SengirNosferatu.java @@ -1,4 +1,3 @@ - package mage.cards.s; import java.util.UUID; @@ -82,19 +81,19 @@ class ReturnSengirNosferatuEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - UUID controllerId = source.getControllerId(); - Target target = new TargetCardInExile(filter); - target.setNotTarget(true); - if (!target.canChoose(source.getSourceId(), controllerId, game)) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { return false; } - Player player = game.getPlayer(controllerId); - if (player != null) { - player.chooseTarget(Outcome.PutCreatureInPlay, target, source, game); - Card card = game.getCard(target.getTargets().get(0)); - if (card != null) { - return card.moveToZone(Zone.BATTLEFIELD, source, game, false); - } + Target target = new TargetCardInExile(filter); + target.setNotTarget(true); + if (!target.canChoose(source.getSourceId(), controller.getId(), game)) { + return false; + } + controller.chooseTarget(Outcome.PutCreatureInPlay, target, source, game); + Card card = game.getCard(target.getTargets().get(0)); + if (card != null) { + return controller.moveCards(card, Zone.BATTLEFIELD, source, game); } return false; } diff --git a/Mage.Sets/src/mage/cards/s/SorinGrimNemesis.java b/Mage.Sets/src/mage/cards/s/SorinGrimNemesis.java index 441eead7ca7..059024dccc5 100644 --- a/Mage.Sets/src/mage/cards/s/SorinGrimNemesis.java +++ b/Mage.Sets/src/mage/cards/s/SorinGrimNemesis.java @@ -22,12 +22,12 @@ import java.util.UUID; * @author fireshoes */ public final class SorinGrimNemesis extends CardImpl { - + public SorinGrimNemesis(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{4}{W}{B}"); this.addSuperType(SuperType.LEGENDARY); this.subtype.add(SubType.SORIN); - + this.addAbility(new PlaneswalkerEntersWithLoyaltyCountersAbility(6)); // +1: Reveal the top card of your library and put that card into your hand. Each opponent loses life equal to its converted mana cost. @@ -42,11 +42,11 @@ public final class SorinGrimNemesis extends CardImpl { // -9: Create a number of 1/1 black Vampire Knight creature tokens with lifelink equal to the highest life total among all players. this.addAbility(new LoyaltyAbility(new SorinTokenEffect(), -9)); } - + private SorinGrimNemesis(final SorinGrimNemesis card) { super(card); } - + @Override public SorinGrimNemesis copy() { return new SorinGrimNemesis(this); @@ -54,36 +54,36 @@ public final class SorinGrimNemesis extends CardImpl { } class SorinGrimNemesisRevealEffect extends OneShotEffect { - + public SorinGrimNemesisRevealEffect() { super(Outcome.DrawCard); this.staticText = "reveal the top card of your library and put that card into your hand. Each opponent loses life equal to that card's converted mana cost"; } - + public SorinGrimNemesisRevealEffect(final SorinGrimNemesisRevealEffect effect) { super(effect); } - + @Override public SorinGrimNemesisRevealEffect copy() { return new SorinGrimNemesisRevealEffect(this); } - + @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; } - - if (player.getLibrary().hasCards()) { - Card card = player.getLibrary().getFromTop(game); + + if (controller.getLibrary().hasCards()) { + Card card = controller.getLibrary().getFromTop(game); if (card != null) { Cards cards = new CardsImpl(); cards.add(card); - player.revealCards("Sorin, Grim Nemesis", cards, game); - - if (card.moveToZone(Zone.HAND, source, game, false)) { + controller.revealCards("Sorin, Grim Nemesis", cards, game); + + if (controller.moveCards(card, Zone.HAND, source, game)) { for (UUID playerId : game.getOpponents(source.getControllerId())) { if (card.getConvertedManaCost() > 0) { Player opponent = game.getPlayer(playerId); @@ -100,18 +100,17 @@ class SorinGrimNemesisRevealEffect extends OneShotEffect { } } - class SorinTokenEffect extends OneShotEffect { - + SorinTokenEffect() { super(Outcome.GainLife); staticText = "Create a number of 1/1 black Vampire Knight creature tokens with lifelink equal to the highest life total among all players"; } - + private SorinTokenEffect(final SorinTokenEffect effect) { super(effect); } - + @Override public boolean apply(Game game, Ability source) { int maxLife = 0; @@ -127,7 +126,7 @@ class SorinTokenEffect extends OneShotEffect { new CreateTokenEffect(new VampireKnightToken(), maxLife).apply(game, source); return true; } - + @Override public SorinTokenEffect copy() { return new SorinTokenEffect(this); diff --git a/Mage.Sets/src/mage/cards/s/Soulquake.java b/Mage.Sets/src/mage/cards/s/Soulquake.java index 808b7b991f4..b60cc69a706 100644 --- a/Mage.Sets/src/mage/cards/s/Soulquake.java +++ b/Mage.Sets/src/mage/cards/s/Soulquake.java @@ -1,6 +1,7 @@ - package mage.cards.s; +import java.util.LinkedHashSet; +import java.util.Set; import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; @@ -23,7 +24,7 @@ import mage.players.Player; public final class Soulquake extends CardImpl { public Soulquake(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{U}{U}{B}{B}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{U}{U}{B}{B}"); // Return all creatures on the battlefield and all creature cards in graveyards to their owners' hands. this.getSpellAbility().addEffect(new SoulquakeEffect()); @@ -59,17 +60,22 @@ class SoulquakeEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } + Set cardsToHand = new LinkedHashSet<>(); for (Permanent permanent : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), source.getSourceId(), game)) { - permanent.moveToZone(Zone.HAND, source, game, true); + cardsToHand.add((Card) permanent); } for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { Player player = game.getPlayer(playerId); if (player != null) { for (Card card : player.getGraveyard().getCards(filter2, game)) { - card.moveToZone(Zone.HAND, source, game, true); + cardsToHand.add(card); } } } - return true; + return controller.moveCards(cardsToHand, Zone.HAND, source, game); } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/s/SteamAugury.java b/Mage.Sets/src/mage/cards/s/SteamAugury.java index 13f2de10fec..af6f005a577 100644 --- a/Mage.Sets/src/mage/cards/s/SteamAugury.java +++ b/Mage.Sets/src/mage/cards/s/SteamAugury.java @@ -1,7 +1,7 @@ - package mage.cards.s; import java.util.ArrayList; +import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.UUID; @@ -67,6 +67,8 @@ class SteamAuguryEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); MageObject sourceObject = game.getObject(source.getSourceId()); + Set cardsToGraveyard = new LinkedHashSet<>(); + Set cardsToHand = new LinkedHashSet<>(); if (controller == null || sourceObject == null) { return false; } @@ -127,9 +129,10 @@ class SteamAuguryEffect extends OneShotEffect { if (i < pile1CardsIds.size()) { sb.append(", "); } - card.moveToZone(pile1Zone, source, game, false); + cardsToGraveyard.add(card); } } + controller.moveCards(cardsToGraveyard, pile1Zone, source, game); game.informPlayers(sb.toString()); sb = new StringBuilder(sourceObject.getLogName() + ": Pile 2, going to ").append(pile2Zone == Zone.HAND ? "Hand" : "Graveyard").append(':'); @@ -142,9 +145,10 @@ class SteamAuguryEffect extends OneShotEffect { if (i < pile2CardsIds.size()) { sb.append(", "); } - card.moveToZone(pile2Zone, source, game, false); + cardsToHand.add(card); } } + controller.moveCards(cardsToHand, pile2Zone, source, game); game.informPlayers(sb.toString()); } diff --git a/Mage.Sets/src/mage/cards/s/SunkenHope.java b/Mage.Sets/src/mage/cards/s/SunkenHope.java index d6d4141e02a..52d5b2b6224 100644 --- a/Mage.Sets/src/mage/cards/s/SunkenHope.java +++ b/Mage.Sets/src/mage/cards/s/SunkenHope.java @@ -1,4 +1,3 @@ - package mage.cards.s; import java.util.UUID; @@ -68,14 +67,15 @@ class SunkenHopeReturnToHandEffect extends OneShotEffect { Target target = new TargetControlledPermanent(1, 1, new FilterControlledCreaturePermanent(), true); if (target.canChoose(source.getSourceId(), player.getId(), game)) { - while (player.canRespond() && !target.isChosen() && target.canChoose(source.getSourceId(), player.getId(), game)) { + while (player.canRespond() && !target.isChosen() + && target.canChoose(source.getSourceId(), player.getId(), game)) { player.chooseTarget(Outcome.ReturnToHand, target, source, game); } for (UUID targetId : target.getTargets()) { Permanent permanent = game.getPermanent(targetId); if (permanent != null) { - result |= permanent.moveToZone(Zone.HAND, source, game, false); + result |= player.moveCards(permanent, Zone.HAND, source, game); } } } diff --git a/Mage.Sets/src/mage/cards/s/SurrealMemoir.java b/Mage.Sets/src/mage/cards/s/SurrealMemoir.java index 84e5be4b40a..d5ba7453b88 100644 --- a/Mage.Sets/src/mage/cards/s/SurrealMemoir.java +++ b/Mage.Sets/src/mage/cards/s/SurrealMemoir.java @@ -1,4 +1,3 @@ - package mage.cards.s; import java.util.UUID; @@ -23,8 +22,7 @@ import mage.util.RandomUtil; public final class SurrealMemoir extends CardImpl { public SurrealMemoir(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{R}"); - + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{R}"); // Return an instant card at random from your graveyard to your hand. this.getSpellAbility().addEffect(new SurrealMemoirEffect()); @@ -59,16 +57,18 @@ class SurrealMemoirEffect 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) { FilterCard filter = new FilterCard("instant card"); filter.add(CardType.INSTANT.getPredicate()); - Card[] cards = player.getGraveyard().getCards(filter, game).toArray(new Card[0]); + Card[] cards = controller.getGraveyard().getCards(filter, game).toArray(new Card[0]); if (cards.length > 0) { Card card = cards[RandomUtil.nextInt(cards.length)]; - card.moveToZone(Zone.HAND, source, game, true); - game.informPlayers(card.getName() + "returned to the hand of" + player.getLogName()); - return true; + if (card != null + && controller.moveCards(card, Zone.HAND, source, game)) { + game.informPlayers(card.getName() + "returned to the hand of" + controller.getLogName()); + return true; + } } } return false;