From e0f031801ddc849aa9e4a6e68a2d10029b590fe8 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Thu, 3 Oct 2024 12:59:14 -0400 Subject: [PATCH] more refactors --- Mage.Sets/src/mage/cards/b/BlazingEffigy.java | 20 +-- .../src/mage/cards/b/BondersOrnament.java | 24 ++-- Mage.Sets/src/mage/cards/b/BoobyTrap.java | 4 +- Mage.Sets/src/mage/cards/g/GrimReminder.java | 87 ++++--------- .../src/mage/cards/i/InvaderParasite.java | 119 ++++++------------ Mage.Sets/src/mage/cards/m/MineWorker.java | 83 +++++------- .../src/mage/cards/n/Nebuchadnezzar.java | 2 +- Mage.Sets/src/mage/cards/n/NullChamber.java | 4 +- .../src/mage/cards/p/PowerPlantWorker.java | 88 ++++++------- Mage.Sets/src/mage/cards/p/PsychicBattle.java | 2 +- Mage.Sets/src/mage/cards/r/RetracedImage.java | 41 +++--- Mage.Sets/src/mage/cards/s/Scalpelexis.java | 36 ++---- .../src/mage/cards/s/ScepterOfEmpires.java | 71 +++++------ .../src/mage/cards/s/SiftThroughSands.java | 68 +++++----- .../src/mage/cards/s/SkophosMazeWarden.java | 2 +- .../src/mage/cards/s/SphinxAmbassador.java | 69 ++++------ Mage.Sets/src/mage/cards/s/StompingSlabs.java | 22 ++-- Mage.Sets/src/mage/cards/t/TaintedPact.java | 48 ++++--- .../src/mage/cards/t/ThroneOfEmpires.java | 74 +++++------ Mage.Sets/src/mage/cards/t/TowerWorker.java | 39 +++--- 20 files changed, 348 insertions(+), 555 deletions(-) diff --git a/Mage.Sets/src/mage/cards/b/BlazingEffigy.java b/Mage.Sets/src/mage/cards/b/BlazingEffigy.java index c64d4e9826f..8aa1dd38475 100644 --- a/Mage.Sets/src/mage/cards/b/BlazingEffigy.java +++ b/Mage.Sets/src/mage/cards/b/BlazingEffigy.java @@ -1,9 +1,5 @@ - package mage.cards.b; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; import mage.MageInt; import mage.MageObjectReference; import mage.abilities.Ability; @@ -11,10 +7,10 @@ import mage.abilities.common.DiesSourceTriggeredAbility; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.Effect; import mage.abilities.effects.common.DamageTargetEffect; -import mage.constants.SubType; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; +import mage.constants.SubType; import mage.constants.WatcherScope; import mage.game.Game; import mage.game.events.GameEvent; @@ -22,8 +18,11 @@ import mage.target.common.TargetCreaturePermanent; import mage.util.CardUtil; import mage.watchers.Watcher; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + /** - * * @author TheElk801 & L_J */ public final class BlazingEffigy extends CardImpl { @@ -89,14 +88,15 @@ class BlazingEffigyWatcher extends Watcher { @Override public void watch(GameEvent event, Game game) { - if (event.getType() != GameEvent.EventType.DAMAGED_PERMANENT) { return; } - - if (event.getSourceId().equals(event.getTargetId())) { return; } + if (event.getType() != GameEvent.EventType.DAMAGED_PERMANENT + || event.getSourceId().equals(event.getTargetId())) { + return; + } // TODO: Should damageSourceRef be used for anything? MageObjectReference damageSourceRef = new MageObjectReference(event.getSourceId(), game); MageObjectReference damageTargetRef = new MageObjectReference(event.getTargetId(), game); - if (game.getPermanentOrLKIBattlefield(event.getSourceId()) != null && game.getPermanentOrLKIBattlefield(event.getSourceId()).getName().equals("Blazing Effigy")) { + if (game.getPermanentOrLKIBattlefield(event.getSourceId()) != null && game.getPermanentOrLKIBattlefield(event.getSourceId()).hasName("Blazing Effigy", game)) { damagedObjects.putIfAbsent(damageTargetRef, 0); damagedObjects.compute(damageTargetRef, (k, damage) -> damage + event.getAmount()); } diff --git a/Mage.Sets/src/mage/cards/b/BondersOrnament.java b/Mage.Sets/src/mage/cards/b/BondersOrnament.java index 8e36188ee81..f69c2d4e27a 100644 --- a/Mage.Sets/src/mage/cards/b/BondersOrnament.java +++ b/Mage.Sets/src/mage/cards/b/BondersOrnament.java @@ -1,6 +1,5 @@ package mage.cards.b; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.TapSourceCost; @@ -11,6 +10,9 @@ import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledPermanent; +import mage.filter.predicate.mageobject.NamePredicate; import mage.game.Game; import mage.players.Player; @@ -45,6 +47,12 @@ public final class BondersOrnament extends CardImpl { class BondersOrnamentEffect extends OneShotEffect { + private static final FilterPermanent filter = new FilterControlledPermanent(); + + static { + filter.add(new NamePredicate("Bonder's Ornament")); + } + BondersOrnamentEffect() { super(Outcome.Benefit); staticText = "Each player who controls a permanent named Bonder's Ornament draws a card."; @@ -63,18 +71,10 @@ class BondersOrnamentEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { for (UUID playerId : game.getState().getPlayersInRange(source.getControllerId(), game)) { Player player = game.getPlayer(playerId); - if (player == null) { - continue; + if (player != null && game.getBattlefield().contains(filter, playerId, source, game, 1)) { + player.drawCards(1, source, game); } - if (game.getBattlefield() - .getAllActivePermanents(playerId) - .stream() - .map(MageObject::getName) - .noneMatch("Bonder's Ornament"::equals)) { - continue; - } - player.drawCards(1, source, game); } return true; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/b/BoobyTrap.java b/Mage.Sets/src/mage/cards/b/BoobyTrap.java index f8fd5f92907..566d4d8730a 100644 --- a/Mage.Sets/src/mage/cards/b/BoobyTrap.java +++ b/Mage.Sets/src/mage/cards/b/BoobyTrap.java @@ -74,7 +74,7 @@ class BoobyTrapTriggeredAbility extends TriggeredAbilityImpl { Card drawn = game.getCard(event.getTargetId()); if (drawn != null) { controller.revealCards(this, new CardsImpl(drawn), game); - if (drawn.getName().equals(game.getState().getValue(getSourceId().toString() + ChooseACardNameEffect.INFO_KEY))) { + if (drawn.hasName((String) game.getState().getValue(getSourceId().toString() + ChooseACardNameEffect.INFO_KEY), game)) { //Set target this.getEffects().get(0).setTargetPointer(new FixedTarget(event.getPlayerId())); return true; @@ -94,4 +94,4 @@ class BoobyTrapTriggeredAbility extends TriggeredAbilityImpl { return "The chosen player reveals each card they draw.\n" + "When the chosen player draws the named card, sacrifice {this}. If you do, {this} deals 10 damage to that player."; } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/cards/g/GrimReminder.java b/Mage.Sets/src/mage/cards/g/GrimReminder.java index 3da95e7a63e..e45bcda64ef 100644 --- a/Mage.Sets/src/mage/cards/g/GrimReminder.java +++ b/Mage.Sets/src/mage/cards/g/GrimReminder.java @@ -1,38 +1,28 @@ - package mage.cards.g; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.condition.common.IsStepCondition; import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.decorator.ConditionalActivatedAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ReturnSourceFromGraveyardToHandEffect; -import mage.abilities.effects.common.ReturnToHandSourceEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.cards.Cards; import mage.cards.CardsImpl; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.PhaseStep; -import mage.constants.WatcherScope; import mage.constants.Zone; import mage.filter.StaticFilters; import mage.game.Game; -import mage.game.events.GameEvent; import mage.players.Player; import mage.target.common.TargetCardInLibrary; -import mage.watchers.Watcher; +import mage.watchers.common.SpellsCastWatcher; + +import java.util.UUID; /** - * * @author TheElk801 */ public final class GrimReminder extends CardImpl { @@ -42,7 +32,7 @@ public final class GrimReminder extends CardImpl { // Search your library for a nonland card and reveal it. Each opponent who cast a card this turn with the same name as that card loses 6 life. Then shuffle your library. this.getSpellAbility().addEffect(new GrimReminderEffect()); - this.getSpellAbility().addWatcher(new GrimReminderWatcher()); + this.getSpellAbility().addWatcher(new SpellsCastWatcher()); // {B}{B}: Return Grim Reminder from your graveyard to your hand. Activate this ability only during your upkeep. this.addAbility(new ConditionalActivatedAbility( @@ -85,60 +75,29 @@ class GrimReminderEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - MageObject sourceObject = source.getSourceObject(game); - if (controller != null && sourceObject != null) { - TargetCardInLibrary target = new TargetCardInLibrary(StaticFilters.FILTER_CARD_NON_LAND); - if (controller.searchLibrary(target, source, game)) { - Card card = game.getCard(target.getFirstTarget()); - if (card != null) { - Cards cardsToReveal = new CardsImpl(card); - controller.revealCards(sourceObject.getIdName(), cardsToReveal, game); - String cardName = card.getName(); - GrimReminderWatcher watcher = game.getState().getWatcher(GrimReminderWatcher.class); - if (watcher != null) { - for (UUID playerId : watcher.getPlayersCastSpell(cardName)) { - Player player = game.getPlayer(playerId); - if (player != null) { - player.loseLife(6, game, source, false); - } - } - } - } - } + if (controller == null) { + return false; + } + TargetCardInLibrary target = new TargetCardInLibrary(StaticFilters.FILTER_CARD_NON_LAND); + controller.searchLibrary(target, source, game); + Card card = controller.getLibrary().getCard(target.getFirstTarget(), game); + if (card == null) { controller.shuffleLibrary(source, game); return true; } - return false; - } -} - -class GrimReminderWatcher extends Watcher { - - private final Map> playersCastSpell = new HashMap<>(); - - public GrimReminderWatcher() { - super(WatcherScope.GAME); - } - - @Override - public void watch(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.SPELL_CAST) { - MageObject spell = game.getObject(event.getTargetId()); - UUID playerId = event.getPlayerId(); - if (playerId != null && spell != null) { - playersCastSpell.putIfAbsent(spell.getName(), new HashSet<>()); - playersCastSpell.get(spell.getName()).add(playerId); + controller.revealCards(source, new CardsImpl(card), game); + String cardName = card.getName(); + SpellsCastWatcher watcher = game.getState().getWatcher(SpellsCastWatcher.class); + for (UUID playerId : game.getOpponents(source.getControllerId())) { + Player player = game.getPlayer(playerId); + if (player != null && watcher + .getSpellsCastThisTurn(playerId) + .stream() + .anyMatch(spell -> spell.sharesName(card, game))) { + player.loseLife(6, game, source, false); } } + controller.shuffleLibrary(source, game); + return true; } - - @Override - public void reset() { - playersCastSpell.clear(); - } - - public Set getPlayersCastSpell(String spellName) { - return playersCastSpell.getOrDefault(spellName, new HashSet<>()); - } - } diff --git a/Mage.Sets/src/mage/cards/i/InvaderParasite.java b/Mage.Sets/src/mage/cards/i/InvaderParasite.java index 16bf0109e77..c64405eec47 100644 --- a/Mage.Sets/src/mage/cards/i/InvaderParasite.java +++ b/Mage.Sets/src/mage/cards/i/InvaderParasite.java @@ -1,29 +1,40 @@ - package mage.cards.i; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; -import mage.abilities.TriggeredAbilityImpl; +import mage.abilities.common.EntersBattlefieldAllTriggeredAbility; import mage.abilities.common.EntersBattlefieldTriggeredAbility; -import mage.abilities.effects.Effect; -import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DamageTargetEffect; -import mage.cards.Card; +import mage.abilities.effects.common.ExileTargetForSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.*; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterLandPermanent; +import mage.filter.predicate.ObjectSourcePlayer; +import mage.filter.predicate.ObjectSourcePlayerPredicate; import mage.game.Game; -import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.target.common.TargetLandPermanent; -import mage.target.targetpointer.FixedTarget; +import mage.util.CardUtil; + +import java.util.Collection; +import java.util.Optional; +import java.util.UUID; /** - * @author Loki + * @author TheElk801 */ public final class InvaderParasite extends CardImpl { + private static final FilterPermanent filter + = new FilterLandPermanent("a land an opponent controls with the same name as the exiled card"); + + static { + filter.add(TargetController.OPPONENT.getControllerPredicate()); + filter.add(InvaderParasitePredicate.instance); + } + public InvaderParasite(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{R}{R}"); this.subtype.add(SubType.PHYREXIAN); @@ -33,12 +44,15 @@ public final class InvaderParasite extends CardImpl { this.toughness = new MageInt(2); // Imprint - When Invader Parasite enters the battlefield, exile target land. - Ability ability = new EntersBattlefieldTriggeredAbility(new InvaderParasiteImprintEffect(), false); + Ability ability = new EntersBattlefieldTriggeredAbility(new ExileTargetForSourceEffect()); ability.addTarget(new TargetLandPermanent()); - this.addAbility(ability); + this.addAbility(ability.setAbilityWord(AbilityWord.IMPRINT)); // Whenever a land with the same name as the exiled card enters the battlefield under an opponent's control, Invader Parasite deals 2 damage to that player. - this.addAbility(new InvaderParasiteTriggeredAbility().setAbilityWord(AbilityWord.IMPRINT)); + this.addAbility(new EntersBattlefieldAllTriggeredAbility( + Zone.BATTLEFIELD, new DamageTargetEffect(2, true, "that player"), + filter, false, SetTargetPointer.PLAYER + )); } private InvaderParasite(final InvaderParasite card) { @@ -51,76 +65,19 @@ public final class InvaderParasite extends CardImpl { } } -class InvaderParasiteImprintEffect extends OneShotEffect { - - InvaderParasiteImprintEffect() { - super(Outcome.Exile); - staticText = "exile target land"; - } - - private InvaderParasiteImprintEffect(final InvaderParasiteImprintEffect effect) { - super(effect); - } +enum InvaderParasitePredicate implements ObjectSourcePlayerPredicate { + instance; @Override - public boolean apply(Game game, Ability source) { - Permanent sourcePermanent = game.getPermanent(source.getSourceId()); - Permanent targetPermanent = game.getPermanent(getTargetPointer().getFirst(game, source)); - if (sourcePermanent != null && targetPermanent != null) { - targetPermanent.moveToExile(getId(), "Invader Parasite (Imprint)", source, game); - sourcePermanent.imprint(targetPermanent.getId(), game); - } - return true; - } - - @Override - public InvaderParasiteImprintEffect copy() { - return new InvaderParasiteImprintEffect(this); - } -} - -class InvaderParasiteTriggeredAbility extends TriggeredAbilityImpl { - - InvaderParasiteTriggeredAbility() { - super(Zone.BATTLEFIELD, new DamageTargetEffect(2)); - } - - private InvaderParasiteTriggeredAbility(final InvaderParasiteTriggeredAbility ability) { - super(ability); - } - - @Override - public InvaderParasiteTriggeredAbility copy() { - return new InvaderParasiteTriggeredAbility(this); - } - - @Override - public boolean checkEventType(GameEvent event, Game game) { - return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD; - } - - @Override - public boolean checkTrigger(GameEvent event, Game game) { - if (game.getOpponents(this.controllerId).contains(event.getPlayerId())) { - Permanent targetPermanent = game.getPermanent(event.getTargetId()); - Permanent sourcePermanent = game.getPermanent(getSourceId()); - if (targetPermanent != null && sourcePermanent != null) { - if (!sourcePermanent.getImprinted().isEmpty()) { - Card imprintedCard = game.getCard(sourcePermanent.getImprinted().get(0)); - if (imprintedCard != null && targetPermanent.getName().equals(imprintedCard.getName())) { - for (Effect effect : this.getEffects()) { - effect.setTargetPointer(new FixedTarget(event.getPlayerId())); - } - return true; - } - } - } - } - return false; - } - - @Override - public String getRule() { - return "Whenever a land with the same name as the exiled card enters the battlefield under an opponent's control, {this} deals 2 damage to that player."; + public boolean apply(ObjectSourcePlayer input, Game game) { + return Optional + .ofNullable(game) + .map(Game::getExile) + .map(e -> e.getExileZone(CardUtil.getExileZoneId(game, input.getSource()))) + .filter(e -> !e.isEmpty()) + .map(e -> e.getCards(game)) + .map(Collection::stream) + .map(s -> s.anyMatch(card -> card.sharesName(input.getObject(), game))) + .orElse(false); } } diff --git a/Mage.Sets/src/mage/cards/m/MineWorker.java b/Mage.Sets/src/mage/cards/m/MineWorker.java index 250d61d1271..edb2b9c6a1a 100644 --- a/Mage.Sets/src/mage/cards/m/MineWorker.java +++ b/Mage.Sets/src/mage/cards/m/MineWorker.java @@ -1,27 +1,41 @@ package mage.cards.m; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.CompoundCondition; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.effects.OneShotEffect; -import mage.constants.Outcome; -import mage.constants.SubType; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.GainLifeEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.StaticFilters; -import mage.game.Game; -import mage.game.permanent.Permanent; -import mage.players.Player; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.mageobject.NamePredicate; + +import java.util.UUID; /** - * * @author weirddan455 */ public final class MineWorker extends CardImpl { + private static final FilterPermanent filter = new FilterControlledCreaturePermanent(); + private static final FilterPermanent filter2 = new FilterControlledCreaturePermanent(); + + static { + filter.add(new NamePredicate("Power Plant Worker")); + filter2.add(new NamePredicate("Tower Worker")); + } + + private static final Condition condition = new CompoundCondition( + new PermanentsOnTheBattlefieldCondition(filter), + new PermanentsOnTheBattlefieldCondition(filter2) + ); + public MineWorker(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{2}"); @@ -30,7 +44,10 @@ public final class MineWorker extends CardImpl { this.toughness = new MageInt(1); // {T}: You gain 1 life. If you control creatures named Power Plant Worker and Tower Worker, you gain 3 life instead. - this.addAbility(new SimpleActivatedAbility(new MineWorkerEffect(), new TapSourceCost())); + this.addAbility(new SimpleActivatedAbility(new ConditionalOneShotEffect( + new GainLifeEffect(3), new GainLifeEffect(1), condition, "you gain 1 life. " + + "If you control creatures named Power Plant Worker and Tower Worker, you gain 3 life instead" + ), new TapSourceCost())); } private MineWorker(final MineWorker card) { @@ -42,47 +59,3 @@ public final class MineWorker extends CardImpl { return new MineWorker(this); } } - -class MineWorkerEffect extends OneShotEffect { - - MineWorkerEffect() { - super(Outcome.GainLife); - this.staticText = "You gain 1 life. If you control creatures named Power Plant Worker and Tower Worker, you gain 3 life instead."; - } - - private MineWorkerEffect(final MineWorkerEffect effect) { - super(effect); - } - - @Override - public MineWorkerEffect copy() { - return new MineWorkerEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - if (controller == null) { - return false; - } - String powerPlantName = "Power Plant Worker"; - String towerName = "Tower Worker"; - boolean powerPlant = false; - boolean tower = false; - int life = 1; - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, controller.getId(), game)) { - String name = permanent.getName(); - if (!powerPlant && powerPlantName.equals(name)) { - powerPlant = true; - } else if (!tower && towerName.equals(name)) { - tower = true; - } - if (powerPlant && tower) { - life = 3; - break; - } - } - controller.gainLife(life, game, source); - return true; - } -} diff --git a/Mage.Sets/src/mage/cards/n/Nebuchadnezzar.java b/Mage.Sets/src/mage/cards/n/Nebuchadnezzar.java index 20048051a12..e70c66b9d78 100644 --- a/Mage.Sets/src/mage/cards/n/Nebuchadnezzar.java +++ b/Mage.Sets/src/mage/cards/n/Nebuchadnezzar.java @@ -86,7 +86,7 @@ class NebuchadnezzarEffect extends OneShotEffect { } } opponent.revealCards(sourceObject.getIdName(), cards, game); - cards.removeIf(uuid -> !cardName.equals(game.getCard(uuid).getName())); + cards.removeIf(uuid -> !game.getCard(uuid).hasName(cardName, game)); opponent.discard(cards, false, source, game); return true; } diff --git a/Mage.Sets/src/mage/cards/n/NullChamber.java b/Mage.Sets/src/mage/cards/n/NullChamber.java index 8aff04eb4b2..86b7a945827 100644 --- a/Mage.Sets/src/mage/cards/n/NullChamber.java +++ b/Mage.Sets/src/mage/cards/n/NullChamber.java @@ -134,8 +134,8 @@ class NullChamberReplacementEffect extends ContinuousRuleModifyingEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { MageObject object = game.getObject(event.getSourceId()); if (object != null) { - return object.getName().equals(game.getState().getValue(source.getSourceId().toString() + NullChamberChooseEffect.INFO_KEY_CONTROLLER)) - || object.getName().equals(game.getState().getValue(source.getSourceId().toString() + NullChamberChooseEffect.INFO_KEY_OPPONENT)); + return object.hasName((String) game.getState().getValue(source.getSourceId().toString() + NullChamberChooseEffect.INFO_KEY_CONTROLLER), game) + || object.hasName((String) game.getState().getValue(source.getSourceId().toString() + NullChamberChooseEffect.INFO_KEY_OPPONENT), game); } return false; } diff --git a/Mage.Sets/src/mage/cards/p/PowerPlantWorker.java b/Mage.Sets/src/mage/cards/p/PowerPlantWorker.java index ff650468a45..a7a43449baf 100644 --- a/Mage.Sets/src/mage/cards/p/PowerPlantWorker.java +++ b/Mage.Sets/src/mage/cards/p/PowerPlantWorker.java @@ -1,26 +1,46 @@ package mage.cards.p; -import java.util.UUID; import mage.MageInt; -import mage.abilities.Ability; import mage.abilities.common.LimitedTimesPerTurnActivatedAbility; +import mage.abilities.condition.CompoundCondition; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.AddContinuousEffectToGame; import mage.abilities.effects.common.continuous.BoostSourceEffect; -import mage.constants.*; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.constants.SubType; +import mage.constants.Zone; import mage.counters.CounterType; -import mage.filter.StaticFilters; -import mage.game.Game; -import mage.game.permanent.Permanent; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.mageobject.NamePredicate; + +import java.util.UUID; /** - * * @author weirddan455 */ public final class PowerPlantWorker extends CardImpl { + private static final FilterPermanent filter = new FilterControlledCreaturePermanent(); + private static final FilterPermanent filter2 = new FilterControlledCreaturePermanent(); + + static { + filter.add(new NamePredicate("Mine Worker")); + filter2.add(new NamePredicate("Tower Worker")); + } + + private static final Condition condition = new CompoundCondition( + new PermanentsOnTheBattlefieldCondition(filter), + new PermanentsOnTheBattlefieldCondition(filter2) + ); + public PowerPlantWorker(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{5}"); @@ -29,7 +49,15 @@ public final class PowerPlantWorker extends CardImpl { this.toughness = new MageInt(4); // {3}: Power Plant Worker gets +2/+2 until end of turn. If you control creatures named Mine Worker and Tower Worker, put two +1/+1 counters on Power Plant Worker instead. Activate only once each turn. - this.addAbility(new LimitedTimesPerTurnActivatedAbility(Zone.BATTLEFIELD, new PowerPlantWorkerEffect(), new GenericManaCost(3))); + this.addAbility(new LimitedTimesPerTurnActivatedAbility( + Zone.BATTLEFIELD, + new ConditionalOneShotEffect( + new AddCountersSourceEffect(CounterType.P1P1.createInstance(2)), + new AddContinuousEffectToGame(new BoostSourceEffect(2, 2, Duration.EndOfTurn)), + condition, "{this} gets +2/+2 until end of turn. If you control creatures " + + "named Mine Worker and Tower Worker, put two +1/+1 counters on {this} instead" + ), new GenericManaCost(3) + )); } private PowerPlantWorker(final PowerPlantWorker card) { @@ -41,45 +69,3 @@ public final class PowerPlantWorker extends CardImpl { return new PowerPlantWorker(this); } } - -class PowerPlantWorkerEffect extends OneShotEffect { - - PowerPlantWorkerEffect() { - super(Outcome.BoostCreature); - this.staticText = "{this} gets +2/+2 until end of turn. If you control creatures named Mine Worker and Tower Worker, put two +1/+1 counters on {this} instead."; - } - - private PowerPlantWorkerEffect(final PowerPlantWorkerEffect effect) { - super(effect); - } - - @Override - public PowerPlantWorkerEffect copy() { - return new PowerPlantWorkerEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent sourcePermanent = source.getSourcePermanentIfItStillExists(game); - if (sourcePermanent == null) { - return false; - } - String mineName = "Mine Worker"; - String towerName = "Tower Worker"; - boolean mine = false; - boolean tower = false; - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, source.getControllerId(), game)) { - String name = permanent.getName(); - if (!mine && mineName.equals(name)) { - mine = true; - } else if (!tower && towerName.equals(name)) { - tower = true; - } - if (mine && tower) { - return sourcePermanent.addCounters(CounterType.P1P1.createInstance(2), source, game); - } - } - game.addEffect(new BoostSourceEffect(2, 2, Duration.EndOfTurn), source); - return true; - } -} diff --git a/Mage.Sets/src/mage/cards/p/PsychicBattle.java b/Mage.Sets/src/mage/cards/p/PsychicBattle.java index e0e760bc84a..8d17aac1dde 100644 --- a/Mage.Sets/src/mage/cards/p/PsychicBattle.java +++ b/Mage.Sets/src/mage/cards/p/PsychicBattle.java @@ -69,7 +69,7 @@ class PsychicBattleTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { StackObject stackObject = game.getStack().getStackObject(event.getSourceId()); if (stackObject != null) { - if (!stackObject.isTargetChanged() && !stackObject.getName().equals("Psychic Battle")) { + if (!stackObject.isTargetChanged() && !stackObject.hasName("Psychic Battle", game)) { this.getEffects().get(0).setTargetPointer(new FixedTarget(event.getSourceId())); stackObject.setTargetChanged(false); // resets the targetChanged flag return true; diff --git a/Mage.Sets/src/mage/cards/r/RetracedImage.java b/Mage.Sets/src/mage/cards/r/RetracedImage.java index b52eaf19e3c..45a42882f53 100644 --- a/Mage.Sets/src/mage/cards/r/RetracedImage.java +++ b/Mage.Sets/src/mage/cards/r/RetracedImage.java @@ -1,23 +1,21 @@ package mage.cards.r; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.cards.CardsImpl; 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.TargetCardInHand; +import java.util.UUID; + /** - * * @author jeffwadsworth */ public final class RetracedImage extends CardImpl { @@ -27,7 +25,6 @@ public final class RetracedImage extends CardImpl { // Reveal a card in your hand, then put that card onto the battlefield if it has the same name as a permanent. this.getSpellAbility().addEffect(new RetracedImageEffect()); - } private RetracedImage(final RetracedImage card) { @@ -59,23 +56,21 @@ class RetracedImageEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - TargetCardInHand target = new TargetCardInHand(); - if (target.canChoose(controller.getId(), source, game) - && controller.choose(outcome, target, source, game)) { - Card chosenCard = game.getCard(target.getFirstTarget()); - if (chosenCard != null) { - Cards cards = new CardsImpl(); - cards.add(chosenCard); - controller.revealCards(source, cards, game); - for (Permanent permanent : game.getBattlefield().getAllActivePermanents()) { - if (permanent.getName().equals(chosenCard.getName())) { - return controller.moveCards(chosenCard, Zone.BATTLEFIELD, source, game); - } - } - } - } + if (controller == null || controller.getHand().isEmpty()) { + return false; } - return false; + TargetCardInHand target = new TargetCardInHand(); + controller.choose(outcome, target, source, game); + Card chosenCard = game.getCard(target.getFirstTarget()); + return chosenCard != null + && game + .getBattlefield() + .getActivePermanents( + StaticFilters.FILTER_PERMANENT, + source.getControllerId(), source, game + ) + .stream() + .anyMatch(permanent -> permanent.sharesName(chosenCard, game)) + && controller.moveCards(chosenCard, Zone.BATTLEFIELD, source, game); } } diff --git a/Mage.Sets/src/mage/cards/s/Scalpelexis.java b/Mage.Sets/src/mage/cards/s/Scalpelexis.java index 08e42551ba5..7c1927ab55c 100644 --- a/Mage.Sets/src/mage/cards/s/Scalpelexis.java +++ b/Mage.Sets/src/mage/cards/s/Scalpelexis.java @@ -1,28 +1,25 @@ - package mage.cards.s; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.keyword.FlyingAbility; -import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.cards.Cards; import mage.cards.CardsImpl; import mage.constants.CardType; -import mage.constants.SubType; import mage.constants.Outcome; +import mage.constants.SubType; import mage.constants.Zone; import mage.game.Game; import mage.players.Player; +import mage.util.CardUtil; + +import java.util.UUID; /** - * * @author jeffwadsworth */ public final class Scalpelexis extends CardImpl { @@ -69,26 +66,17 @@ class ScalpelexisEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Player targetPlayer = game.getPlayer(getTargetPointer().getFirst(game, source)); - if (targetPlayer == null) { + Player player = game.getPlayer(getTargetPointer().getFirst(game, source)); + if (player == null) { return false; } - Set cardNames = new HashSet<>(); - boolean doubleName; - do { - doubleName = false; - Cards toExile = new CardsImpl(targetPlayer.getLibrary().getTopCards(game, 4)); - cardNames.clear(); - for (Card card : toExile.getCards(game)) { - if (cardNames.contains(card.getName())) { - doubleName = true; - break; - } else { - cardNames.add(card.getName()); - } + while (player.getLibrary().hasCards()) { + Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, 4)); + player.moveCards(cards, Zone.EXILED, source, game); + if (!CardUtil.checkAnyPairs(cards.getCards(game), (c1, c2) -> c1.sharesName(c2, game))) { + break; } - targetPlayer.moveCards(toExile, Zone.EXILED, source, game); - } while (doubleName); + } return true; } } diff --git a/Mage.Sets/src/mage/cards/s/ScepterOfEmpires.java b/Mage.Sets/src/mage/cards/s/ScepterOfEmpires.java index 821d119473a..8ae2b42c7c0 100644 --- a/Mage.Sets/src/mage/cards/s/ScepterOfEmpires.java +++ b/Mage.Sets/src/mage/cards/s/ScepterOfEmpires.java @@ -1,30 +1,50 @@ - package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.CompoundCondition; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.costs.common.TapSourceCost; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.DamageTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.permanent.Permanent; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledArtifactPermanent; +import mage.filter.predicate.mageobject.NamePredicate; import mage.target.common.TargetPlayerOrPlaneswalker; +import java.util.UUID; + /** * @author nantuko */ public final class ScepterOfEmpires extends CardImpl { + private static final FilterPermanent filter = new FilterControlledArtifactPermanent(); + private static final FilterPermanent filter2 = new FilterControlledArtifactPermanent(); + + static { + filter.add(new NamePredicate("Crown of Empires")); + filter2.add(new NamePredicate("Throne of Empires")); + } + + private static final Condition condition = new CompoundCondition( + new PermanentsOnTheBattlefieldCondition(filter), + new PermanentsOnTheBattlefieldCondition(filter2) + ); + public ScepterOfEmpires(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}"); // {tap}: Scepter of Empires deals 1 damage to target player. It deals 3 damage to that player instead if you control artifacts named Crown of Empires and Throne of Empires. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ScepterOfEmpiresEffect(), new TapSourceCost()); + Ability ability = new SimpleActivatedAbility(new ConditionalOneShotEffect( + new DamageTargetEffect(3), new DamageTargetEffect(1), condition, "{this} deals " + + "1 damage to target player. It deals 3 damage to that player instead if " + + "you control artifacts named Crown of Empires and Throne of Empires" + ), new TapSourceCost()); ability.addTarget(new TargetPlayerOrPlaneswalker()); this.addAbility(ability); } @@ -38,38 +58,3 @@ public final class ScepterOfEmpires extends CardImpl { return new ScepterOfEmpires(this); } } - -class ScepterOfEmpiresEffect extends OneShotEffect { - - ScepterOfEmpiresEffect() { - super(Outcome.PutCreatureInPlay); - staticText = "Scepter of Empires deals 1 damage to target player or planeswalker. It deals 3 damage instead if you control artifacts named Crown of Empires and Throne of Empires"; - } - - private ScepterOfEmpiresEffect(final ScepterOfEmpiresEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - boolean throne = false; - boolean crown = false; - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(source.getControllerId())) { - if (permanent.getName().equals("Throne of Empires")) { - throne = true; - } else if (permanent.getName().equals("Crown of Empires")) { - crown = true; - } - if (throne && crown) { - break; - } - } - int amount = throne && crown ? 3 : 1; - return game.damagePlayerOrPermanent(source.getFirstTarget(), amount, source.getSourceId(), source, game, false, true) > 0; - } - - @Override - public ScepterOfEmpiresEffect copy() { - return new ScepterOfEmpiresEffect(this); - } -} diff --git a/Mage.Sets/src/mage/cards/s/SiftThroughSands.java b/Mage.Sets/src/mage/cards/s/SiftThroughSands.java index ee2bdd88355..edf490e5953 100644 --- a/Mage.Sets/src/mage/cards/s/SiftThroughSands.java +++ b/Mage.Sets/src/mage/cards/s/SiftThroughSands.java @@ -1,12 +1,9 @@ - package mage.cards.s; import mage.abilities.Ability; import mage.abilities.condition.Condition; import mage.abilities.decorator.ConditionalOneShotEffect; -import mage.abilities.effects.Effect; -import mage.abilities.effects.common.DrawCardSourceControllerEffect; -import mage.abilities.effects.common.discard.DiscardControllerEffect; +import mage.abilities.effects.common.DrawDiscardControllerEffect; import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; @@ -21,15 +18,15 @@ import mage.game.stack.Spell; import mage.target.common.TargetCardInLibrary; import mage.watchers.Watcher; +import java.util.HashSet; +import java.util.Set; import java.util.UUID; /** - * * @author LevelX2 */ public final class SiftThroughSands extends CardImpl { - private static final String rule = "
If you've cast a spell named Peer Through Depths and a spell named Reach Through Mists this turn, you may search your library for a card named The Unspeakable, put it onto the battlefield, then shuffle"; private static final FilterCreatureCard filter = new FilterCreatureCard("a card named The Unspeakable"); static { @@ -37,17 +34,19 @@ public final class SiftThroughSands extends CardImpl { } public SiftThroughSands(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}{U}"); + super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}{U}"); this.subtype.add(SubType.ARCANE); // Draw two cards, then discard a card. - this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(2)); - Effect effect = new DiscardControllerEffect(1); - effect.setText(", then discard a card"); - this.getSpellAbility().addEffect(effect); + this.getSpellAbility().addEffect(new DrawDiscardControllerEffect(2, 1)); // If you've cast a spell named Peer Through Depths and a spell named Reach Through Mists this turn, you may search your library for a card named The Unspeakable, put it onto the battlefield, then shuffle your library. - this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filter), false), new SiftThroughSandsCondition(), rule)); + this.getSpellAbility().addEffect(new ConditionalOneShotEffect( + new SearchLibraryPutInPlayEffect(new TargetCardInLibrary(filter), false), + SiftThroughSandsCondition.instance, "
If you've cast a spell named " + + "Peer Through Depths and a spell named Reach Through Mists this turn, you may search your library " + + "for a card named The Unspeakable, put it onto the battlefield, then shuffle" + )); this.getSpellAbility().addWatcher(new SiftThroughSandsWatcher()); } @@ -61,48 +60,51 @@ public final class SiftThroughSands extends CardImpl { } } -class SiftThroughSandsCondition implements Condition { +enum SiftThroughSandsCondition implements Condition { + instance; @Override public boolean apply(Game game, Ability source) { - SiftThroughSandsWatcher watcher = game.getState().getWatcher(SiftThroughSandsWatcher.class, source.getControllerId()); - if (watcher != null) { - return watcher.conditionMet(); - } - return false; + return SiftThroughSandsWatcher.checkPlayer(source.getControllerId(), game); } } class SiftThroughSandsWatcher extends Watcher { - boolean castPeerThroughDepths = false; - boolean castReachThroughMists = false; + Set castPeerThroughDepths = new HashSet<>(); + Set castReachThroughMists = new HashSet<>(); public SiftThroughSandsWatcher() { - super(WatcherScope.PLAYER); + super(WatcherScope.GAME); } @Override public void watch(GameEvent event, Game game) { - if (condition) { //no need to check - condition has already occured + if (event.getType() != GameEvent.EventType.SPELL_CAST) { return; } - if (event.getType() == GameEvent.EventType.SPELL_CAST - && controllerId.equals(event.getPlayerId())) { - Spell spell = game.getStack().getSpell(event.getTargetId()); - if (spell.getCard().getName().equals("Peer Through Depths")) { - castPeerThroughDepths = true; - } else if (spell.getCard().getName().equals("Reach Through Mists")) { - castReachThroughMists = true; - } - condition = castPeerThroughDepths && castReachThroughMists; + Spell spell = game.getStack().getSpell(event.getTargetId()); + if (spell.hasName("Peer Through Depths", game)) { + castPeerThroughDepths.add(spell.getControllerId()); + } + if (spell.hasName("Reach Through Mists", game)) { + castReachThroughMists.add(spell.getControllerId()); } } @Override public void reset() { super.reset(); - this.castPeerThroughDepths = false; - this.castReachThroughMists = false; + this.castPeerThroughDepths.clear(); + this.castReachThroughMists.clear(); + } + + static boolean checkPlayer(UUID playerId, Game game) { + return game.getState().getWatcher(SiftThroughSandsWatcher.class).check(playerId); + } + + private boolean check(UUID playerId) { + return castPeerThroughDepths.contains(playerId) + && castReachThroughMists.contains(playerId); } } diff --git a/Mage.Sets/src/mage/cards/s/SkophosMazeWarden.java b/Mage.Sets/src/mage/cards/s/SkophosMazeWarden.java index e76024a5546..12519208f07 100644 --- a/Mage.Sets/src/mage/cards/s/SkophosMazeWarden.java +++ b/Mage.Sets/src/mage/cards/s/SkophosMazeWarden.java @@ -82,7 +82,7 @@ class SkophosMazeWardenTriggeredAbility extends TriggeredAbilityImpl { if (permanent == null || !permanent.isControlledBy(getControllerId()) || !permanent.isLand(game) - || !permanent.getName().equals("Labyrinth of Skophos")) { + || !permanent.hasName("Labyrinth of Skophos", game)) { return false; } Permanent creature = game.getPermanent(event.getTargetId()); diff --git a/Mage.Sets/src/mage/cards/s/SphinxAmbassador.java b/Mage.Sets/src/mage/cards/s/SphinxAmbassador.java index cd61086ebd6..4a4295687f8 100644 --- a/Mage.Sets/src/mage/cards/s/SphinxAmbassador.java +++ b/Mage.Sets/src/mage/cards/s/SphinxAmbassador.java @@ -1,31 +1,25 @@ - package mage.cards.s; -import java.util.Collection; -import java.util.TreeSet; -import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.ChooseACardNameEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.choices.Choice; -import mage.choices.ChoiceHintType; -import mage.choices.ChoiceImpl; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.SubType; import mage.constants.Zone; import mage.game.Game; -import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCardInLibrary; +import java.util.UUID; + /** - * * @author North */ public final class SphinxAmbassador extends CardImpl { @@ -38,8 +32,11 @@ public final class SphinxAmbassador extends CardImpl { this.toughness = new MageInt(5); this.addAbility(FlyingAbility.getInstance()); + // Whenever Sphinx Ambassador deals combat damage to a player, search that player's library for a card, then that player names a card. If you searched for a creature card that isn't the named card, you may put it onto the battlefield under your control. Then that player shuffles their library. - this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility(new SphinxAmbassadorEffect(), false, true)); + this.addAbility(new DealsCombatDamageToAPlayerTriggeredAbility( + new SphinxAmbassadorEffect(), false, true + )); } private SphinxAmbassador(final SphinxAmbassador card) { @@ -56,7 +53,9 @@ class SphinxAmbassadorEffect extends OneShotEffect { SphinxAmbassadorEffect() { super(Outcome.PutCreatureInPlay); - this.staticText = "search that player's library for a card, then that player chooses a card name. If you searched for a creature card that doesn't have that name, you may put it onto the battlefield under your control. Then that player shuffles"; + this.staticText = "search that player's library for a card, then that player chooses a card name. " + + "If you searched for a creature card that doesn't have that name, " + + "you may put it onto the battlefield under your control. Then that player shuffles"; } private SphinxAmbassadorEffect(final SphinxAmbassadorEffect effect) { @@ -72,40 +71,20 @@ class SphinxAmbassadorEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); Player targetPlayer = game.getPlayer(getTargetPointer().getFirst(game, source)); - Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId()); - if (controller != null && targetPlayer != null && sourcePermanent != null) { - TargetCardInLibrary target = new TargetCardInLibrary(); - controller.searchLibrary(target, source, game, targetPlayer.getId()); - - Card card = game.getCard(target.getFirstTarget()); - if (card != null) { - TreeSet choices = new TreeSet<>(); - Collection cards = game.getCards(); - for (Card gameCard : cards) { - if (gameCard.isOwnedBy(targetPlayer.getId())) { - choices.add(gameCard.getName()); - } - } - - Choice cardChoice = new ChoiceImpl(false, ChoiceHintType.CARD); - cardChoice.setChoices(choices); - cardChoice.clearChoice(); - if (!targetPlayer.choose(Outcome.Benefit, cardChoice, game)) { - return false; - } - String cardName = cardChoice.getChoice(); - - game.informPlayers(sourcePermanent.getName() + ", named card: [" + cardName + ']'); - if (!card.getName().equals(cardName) && card.isCreature(game)) { - if (controller.chooseUse(outcome, "Put " + card.getName() + " onto the battlefield?", source, game)) { - controller.moveCards(card, Zone.BATTLEFIELD, source, game); - } - } - } - - targetPlayer.shuffleLibrary(source, game); - return true; + if (controller == null || targetPlayer == null) { + return false; } - return false; + TargetCardInLibrary target = new TargetCardInLibrary(); + controller.searchLibrary(target, source, game, targetPlayer.getId()); + Card card = targetPlayer.getLibrary().getCard(target.getFirstTarget(), game); + String name = ChooseACardNameEffect.TypeOfName.ALL.getChoice(targetPlayer, game, source, false); + if (card != null + && card.isCreature(game) + && !card.hasName(name, game) + && controller.chooseUse(outcome, "Put " + card.getName() + " onto the battlefield?", source, game)) { + controller.moveCards(card, Zone.BATTLEFIELD, source, game); + } + targetPlayer.shuffleLibrary(source, game); + return true; } } diff --git a/Mage.Sets/src/mage/cards/s/StompingSlabs.java b/Mage.Sets/src/mage/cards/s/StompingSlabs.java index bcf260595b5..8b62303944d 100644 --- a/Mage.Sets/src/mage/cards/s/StompingSlabs.java +++ b/Mage.Sets/src/mage/cards/s/StompingSlabs.java @@ -1,16 +1,11 @@ package mage.cards.s; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.DamageTargetEffect; -import mage.cards.Card; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; -import mage.cards.Cards; -import mage.cards.CardsImpl; +import mage.cards.*; import mage.constants.CardType; import mage.constants.Outcome; import mage.game.Game; @@ -18,14 +13,15 @@ import mage.players.Player; import mage.target.common.TargetAnyTarget; import mage.target.targetpointer.FixedTarget; +import java.util.UUID; + /** - * * @author emerald000 */ public final class StompingSlabs extends CardImpl { public StompingSlabs(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{R}"); + super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{R}"); // Reveal the top seven cards of your library, then put those cards on the bottom of your library in any order. If a card named Stomping Slabs was revealed this way, Stomping Slabs deals 7 damage to any target. this.getSpellAbility().addEffect(new StompingSlabsEffect()); @@ -43,21 +39,21 @@ public final class StompingSlabs extends CardImpl { } class StompingSlabsEffect extends OneShotEffect { - + StompingSlabsEffect() { super(Outcome.Damage); this.staticText = "Reveal the top seven cards of your library, then put those cards on the bottom of your library in any order. If a card named Stomping Slabs was revealed this way, {this} deals 7 damage to any target"; } - + private StompingSlabsEffect(final StompingSlabsEffect effect) { super(effect); } - + @Override public StompingSlabsEffect copy() { return new StompingSlabsEffect(this); } - + @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); @@ -68,7 +64,7 @@ class StompingSlabsEffect extends OneShotEffect { boolean stompingSlabsFound = false; for (UUID cardId : cards) { Card card = game.getCard(cardId); - if (card != null && card.getName().equals("Stomping Slabs")) { + if (card != null && card.hasName("Stomping Slabs", game)) { stompingSlabsFound = true; break; } diff --git a/Mage.Sets/src/mage/cards/t/TaintedPact.java b/Mage.Sets/src/mage/cards/t/TaintedPact.java index 73c3327775b..c1499d13628 100644 --- a/Mage.Sets/src/mage/cards/t/TaintedPact.java +++ b/Mage.Sets/src/mage/cards/t/TaintedPact.java @@ -1,21 +1,17 @@ package mage.cards.t; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.effects.OneShotEffect; -import mage.cards.Card; -import mage.cards.CardImpl; -import mage.cards.CardSetInfo; +import mage.cards.*; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Zone; import mage.game.Game; import mage.players.Player; +import java.util.UUID; + /** - * * @author cbt33, Ad Nauseum (North), Izzet Staticaster (LevelX2), Bane Alley * Broker (LevelX2) */ @@ -56,30 +52,28 @@ class TaintedPactEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Card sourceCard = game.getCard(source.getSourceId()); Player controller = game.getPlayer(source.getControllerId()); - if (controller == null - || sourceCard == null) { + if (controller == null) { return false; } - Set names = new HashSet<>(); - while (controller.canRespond() - && controller.getLibrary().hasCards()) { + Cards cards = new CardsImpl(); + while (controller.canRespond() && controller.getLibrary().hasCards()) { Card card = controller.getLibrary().getFromTop(game); - if (card != null) { - // the card move is sequential, not all at once. - controller.moveCards(card, Zone.EXILED, source, game); - game.processAction(); // Laelia, the Blade Reforged - // Checks if there was already exiled a card with the same name - if (names.contains(card.getName())) { - break; - } - names.add(card.getName()); - if (controller.chooseUse(outcome, "Put " + card.getName() + " into your hand?", source, game)) { - //Adds the current card to hand if it is chosen. - controller.moveCards(card, Zone.HAND, source, game); - break; - } + if (card == null) { + continue; + } + // the card move is sequential, not all at once. + controller.moveCards(card, Zone.EXILED, source, game); + game.processAction(); // Laelia, the Blade Reforged + // Checks if there was already exiled a card with the same name + if (cards.getCards(game).stream().anyMatch(c -> c.sharesName(card, game))) { + break; + } + cards.add(card); + if (controller.chooseUse(outcome, "Put " + card.getName() + " into your hand?", source, game)) { + //Adds the current card to hand if it is chosen. + controller.moveCards(card, Zone.HAND, source, game); + break; } } return true; diff --git a/Mage.Sets/src/mage/cards/t/ThroneOfEmpires.java b/Mage.Sets/src/mage/cards/t/ThroneOfEmpires.java index 103cc7baa9d..4f14310efcc 100644 --- a/Mage.Sets/src/mage/cards/t/ThroneOfEmpires.java +++ b/Mage.Sets/src/mage/cards/t/ThroneOfEmpires.java @@ -1,32 +1,51 @@ - package mage.cards.t; -import java.util.UUID; import mage.abilities.Ability; import mage.abilities.common.SimpleActivatedAbility; +import mage.abilities.condition.CompoundCondition; +import mage.abilities.condition.Condition; +import mage.abilities.condition.common.PermanentsOnTheBattlefieldCondition; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.GenericManaCost; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.CreateTokenEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Zone; -import mage.game.Game; -import mage.game.permanent.Permanent; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledArtifactPermanent; +import mage.filter.predicate.mageobject.NamePredicate; import mage.game.permanent.token.SoldierToken; -import mage.game.permanent.token.Token; + +import java.util.UUID; /** * @author nantuko */ public final class ThroneOfEmpires extends CardImpl { + private static final FilterPermanent filter = new FilterControlledArtifactPermanent(); + private static final FilterPermanent filter2 = new FilterControlledArtifactPermanent(); + + static { + filter.add(new NamePredicate("Crown of Empires")); + filter2.add(new NamePredicate("Scepter of Empires")); + } + + private static final Condition condition = new CompoundCondition( + new PermanentsOnTheBattlefieldCondition(filter), + new PermanentsOnTheBattlefieldCondition(filter2) + ); + public ThroneOfEmpires(UUID ownerId, CardSetInfo setInfo) { - super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{4}"); + super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{4}"); // {1}, {tap}: Create a 1/1 white Soldier creature token. Create five of those tokens instead if you control artifacts named Crown of Empires and Scepter of Empires. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new ThroneOfEmpiresEffect(), new GenericManaCost(1)); + Ability ability = new SimpleActivatedAbility(new ConditionalOneShotEffect( + new CreateTokenEffect(new SoldierToken(), 5), new CreateTokenEffect(new SoldierToken()), + condition, "create a 1/1 white Soldier creature token. Create five of those tokens " + + "instead if you control artifacts named Crown of Empires and Scepter of Empires" + ), new GenericManaCost(1)); ability.addCost(new TapSourceCost()); this.addAbility(ability); } @@ -40,38 +59,3 @@ public final class ThroneOfEmpires extends CardImpl { return new ThroneOfEmpires(this); } } - -class ThroneOfEmpiresEffect extends OneShotEffect { - - ThroneOfEmpiresEffect() { - super(Outcome.PutCreatureInPlay); - staticText = "Create a 1/1 white Soldier creature token. Create five of those tokens instead if you control artifacts named Crown of Empires and Scepter of Empires"; - } - - private ThroneOfEmpiresEffect(final ThroneOfEmpiresEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - boolean scepter = false; - boolean crown = false; - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(source.getControllerId())) { - if (permanent.getName().equals("Scepter of Empires")) { - scepter = true; - } else if (permanent.getName().equals("Crown of Empires")) { - crown = true; - } - if (scepter && crown) break; - } - Token soldier = new SoldierToken(); - int count = scepter && crown ? 5 : 1; - soldier.putOntoBattlefield(count, game, source, source.getControllerId()); - return false; - } - - @Override - public ThroneOfEmpiresEffect copy() { - return new ThroneOfEmpiresEffect(this); - } -} diff --git a/Mage.Sets/src/mage/cards/t/TowerWorker.java b/Mage.Sets/src/mage/cards/t/TowerWorker.java index 96e6150f870..eb37b9e682e 100644 --- a/Mage.Sets/src/mage/cards/t/TowerWorker.java +++ b/Mage.Sets/src/mage/cards/t/TowerWorker.java @@ -1,23 +1,24 @@ package mage.cards.t; -import java.util.UUID; import mage.MageInt; import mage.Mana; import mage.abilities.Ability; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.Effect; -import mage.abilities.mana.DynamicManaAbility; -import mage.constants.SubType; import mage.abilities.keyword.ReachAbility; +import mage.abilities.mana.DynamicManaAbility; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; -import mage.filter.StaticFilters; +import mage.constants.SubType; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledCreaturePermanent; +import mage.filter.predicate.mageobject.NamePredicate; import mage.game.Game; -import mage.game.permanent.Permanent; + +import java.util.UUID; /** - * * @author weirddan455 */ public final class TowerWorker extends CardImpl { @@ -51,25 +52,19 @@ public final class TowerWorker extends CardImpl { enum TowerWorkerValue implements DynamicValue { instance; + private static final FilterPermanent filter = new FilterControlledCreaturePermanent(); + private static final FilterPermanent filter2 = new FilterControlledCreaturePermanent(); + + static { + filter.add(new NamePredicate("Mine Worker")); + filter2.add(new NamePredicate("Power Plant Worker")); + } @Override public int calculate(Game game, Ability sourceAbility, Effect effect) { - String mineName = "Mine Worker"; - String powerPlantName = "Power Plant Worker"; - boolean mine = false; - boolean powerPlant = false; - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, sourceAbility.getControllerId(), game)) { - String name = permanent.getName(); - if (!mine && mineName.equals(name)) { - mine = true; - } else if (!powerPlant && powerPlantName.equals(name)) { - powerPlant = true; - } - if (mine && powerPlant) { - return 3; - } - } - return 1; + return game.getBattlefield().contains(filter, sourceAbility, game, 1) + && game.getBattlefield().contains(filter2, sourceAbility, game, 1) + ? 3 : 1; } @Override