From 388fb0b8fdd291120a8d9100ec51863367ac6b8e Mon Sep 17 00:00:00 2001 From: theelk801 Date: Mon, 9 Sep 2024 14:12:35 -0400 Subject: [PATCH 1/3] add hasName method --- Mage/src/main/java/mage/MageObject.java | 6 ++++++ Mage/src/main/java/mage/MageObjectImpl.java | 5 +++++ Mage/src/main/java/mage/cards/ModalDoubleFacedCard.java | 5 +++++ Mage/src/main/java/mage/designations/Designation.java | 5 +++++ Mage/src/main/java/mage/game/command/Commander.java | 5 +++++ Mage/src/main/java/mage/game/command/Dungeon.java | 5 +++++ Mage/src/main/java/mage/game/command/Emblem.java | 6 +++++- Mage/src/main/java/mage/game/command/Plane.java | 6 ++++++ .../main/java/mage/game/command/emblems/TheRingEmblem.java | 5 +++++ Mage/src/main/java/mage/game/stack/Spell.java | 5 +++++ Mage/src/main/java/mage/game/stack/StackAbility.java | 5 +++++ 11 files changed, 57 insertions(+), 1 deletion(-) diff --git a/Mage/src/main/java/mage/MageObject.java b/Mage/src/main/java/mage/MageObject.java index 660759e8ab51..6b54aceebdeb 100644 --- a/Mage/src/main/java/mage/MageObject.java +++ b/Mage/src/main/java/mage/MageObject.java @@ -622,5 +622,11 @@ default boolean shareCreatureTypes(Game game, MageObject otherCard) { */ void setIsAllNonbasicLandTypes(Game game, boolean value); + default boolean hasName(String name) { + return hasName(name, null); + } + + boolean hasName(String name, Game game); + void removePTCDA(); } diff --git a/Mage/src/main/java/mage/MageObjectImpl.java b/Mage/src/main/java/mage/MageObjectImpl.java index 51a2dd48d674..4ffe5f13bde8 100644 --- a/Mage/src/main/java/mage/MageObjectImpl.java +++ b/Mage/src/main/java/mage/MageObjectImpl.java @@ -409,4 +409,9 @@ public void removePTCDA() { public String toString() { return getIdName() + " (" + super.getClass().getSuperclass().getSimpleName() + " -> " + this.getClass().getSimpleName() + ")"; } + + @Override + public boolean hasName(String name, Game game) { + return Objects.equals(name, this.name); + } } diff --git a/Mage/src/main/java/mage/cards/ModalDoubleFacedCard.java b/Mage/src/main/java/mage/cards/ModalDoubleFacedCard.java index eb8f3fcd19f2..52e60b3cb044 100644 --- a/Mage/src/main/java/mage/cards/ModalDoubleFacedCard.java +++ b/Mage/src/main/java/mage/cards/ModalDoubleFacedCard.java @@ -432,4 +432,9 @@ public MageInt getPower() { public MageInt getToughness() { return leftHalfCard.getToughness(); } + + @Override + public boolean hasName(String name, Game game) { + return leftHalfCard.hasName(name, game); + } } diff --git a/Mage/src/main/java/mage/designations/Designation.java b/Mage/src/main/java/mage/designations/Designation.java index cb76e274bc05..3be17b33b3f5 100644 --- a/Mage/src/main/java/mage/designations/Designation.java +++ b/Mage/src/main/java/mage/designations/Designation.java @@ -201,4 +201,9 @@ public void setIsAllCreatureTypes(Game game, boolean value) { public boolean isUnique() { return unique; } + + @Override + public boolean hasName(String name, Game game) { + return false; + } } diff --git a/Mage/src/main/java/mage/game/command/Commander.java b/Mage/src/main/java/mage/game/command/Commander.java index 7ff69e6101de..dfdd5c6211ee 100644 --- a/Mage/src/main/java/mage/game/command/Commander.java +++ b/Mage/src/main/java/mage/game/command/Commander.java @@ -331,6 +331,11 @@ public void setIsAllNonbasicLandTypes(Game game, boolean value) { sourceObject.setIsAllNonbasicLandTypes(game, value); } + @Override + public boolean hasName(String name, Game game) { + return sourceObject.hasName(name, game); + } + @Override public void removePTCDA() { } diff --git a/Mage/src/main/java/mage/game/command/Dungeon.java b/Mage/src/main/java/mage/game/command/Dungeon.java index adf15b5b8f4d..a5f28744cfb9 100644 --- a/Mage/src/main/java/mage/game/command/Dungeon.java +++ b/Mage/src/main/java/mage/game/command/Dungeon.java @@ -344,6 +344,11 @@ public void setIsAllNonbasicLandTypes(boolean value) { public void setIsAllNonbasicLandTypes(Game game, boolean value) { } + @Override + public boolean hasName(String name, Game game) { + return Objects.equals(name, getName()); + } + public void discardEffects() { for (Ability ability : abilites) { for (Effect effect : ability.getEffects()) { diff --git a/Mage/src/main/java/mage/game/command/Emblem.java b/Mage/src/main/java/mage/game/command/Emblem.java index 1070de0d4759..d760b30bb006 100644 --- a/Mage/src/main/java/mage/game/command/Emblem.java +++ b/Mage/src/main/java/mage/game/command/Emblem.java @@ -19,7 +19,6 @@ import mage.constants.SuperType; import mage.game.Game; import mage.game.events.ZoneChangeEvent; -import mage.util.CardUtil; import mage.util.SubTypes; import java.util.Collections; @@ -260,6 +259,11 @@ public void setIsAllNonbasicLandTypes(boolean value) { public void setIsAllNonbasicLandTypes(Game game, boolean value) { } + @Override + public boolean hasName(String name, Game game) { + return false; + } + public void discardEffects() { for (Ability ability : abilities) { for (Effect effect : ability.getEffects()) { diff --git a/Mage/src/main/java/mage/game/command/Plane.java b/Mage/src/main/java/mage/game/command/Plane.java index 4e48daaf7cdf..86614955838f 100644 --- a/Mage/src/main/java/mage/game/command/Plane.java +++ b/Mage/src/main/java/mage/game/command/Plane.java @@ -26,6 +26,7 @@ import java.lang.reflect.Constructor; import java.util.Collections; import java.util.List; +import java.util.Objects; import java.util.UUID; /** @@ -281,6 +282,11 @@ public void setIsAllNonbasicLandTypes(boolean value) { public void setIsAllNonbasicLandTypes(Game game, boolean value) { } + @Override + public boolean hasName(String name, Game game) { + return Objects.equals(name, getName()); + } + public void discardEffects() { for (Ability ability : abilites) { for (Effect effect : ability.getEffects()) { diff --git a/Mage/src/main/java/mage/game/command/emblems/TheRingEmblem.java b/Mage/src/main/java/mage/game/command/emblems/TheRingEmblem.java index e99284e9dd50..1bbc6e5b6b7b 100644 --- a/Mage/src/main/java/mage/game/command/emblems/TheRingEmblem.java +++ b/Mage/src/main/java/mage/game/command/emblems/TheRingEmblem.java @@ -98,6 +98,11 @@ Zone.COMMAND, new LoseLifeOpponentsEffect(3), filter, false, } game.informPlayers(name + " gains a new Ring ability: \"" + logText + "\""); } + + @Override + public boolean hasName(String name, Game game) { + return "The One Ring".equals(name); + } } enum TheRingEmblemPredicate implements Predicate { diff --git a/Mage/src/main/java/mage/game/stack/Spell.java b/Mage/src/main/java/mage/game/stack/Spell.java index c234e901643a..579224ba7109 100644 --- a/Mage/src/main/java/mage/game/stack/Spell.java +++ b/Mage/src/main/java/mage/game/stack/Spell.java @@ -1257,4 +1257,9 @@ public boolean hasCardTypeForDeckbuilding(CardType cardType) { public boolean hasSubTypeForDeckbuilding(SubType subType) { return false; } + + @Override + public boolean hasName(String name, Game game) { + return Objects.equals(name, getName()); + } } diff --git a/Mage/src/main/java/mage/game/stack/StackAbility.java b/Mage/src/main/java/mage/game/stack/StackAbility.java index d87f9fdf8713..5be8efe63f8a 100644 --- a/Mage/src/main/java/mage/game/stack/StackAbility.java +++ b/Mage/src/main/java/mage/game/stack/StackAbility.java @@ -856,4 +856,9 @@ public AbilityImpl setIdentifier(MageIdentifier identifier) { public String toString() { return this.name; } + + @Override + public boolean hasName(String name, Game game) { + return Objects.equals(name, this.name); + } } From 1814467bcda47791483b702797d2a171064243d6 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Wed, 11 Sep 2024 16:42:20 -0400 Subject: [PATCH 2/3] some more changes --- .../src/mage/cards/a/AgencyOutfitter.java | 9 +- .../mage/cards/a/AlhammarretHighArbiter.java | 3 +- .../src/mage/cards/a/AnointedPeacekeeper.java | 2 +- Mage.Sets/src/mage/cards/b/BileBlight.java | 4 +- Mage.Sets/src/mage/cards/b/BrainPry.java | 3 +- .../src/mage/cards/c/CabalTherapist.java | 4 +- Mage.Sets/src/mage/cards/c/CabalTherapy.java | 4 +- Mage.Sets/src/mage/cards/c/ConjurersBan.java | 3 +- .../src/mage/cards/c/ConundrumSphinx.java | 3 +- .../src/mage/cards/c/CorneredMarket.java | 50 ++++---- .../src/mage/cards/c/CrownOfEmpires.java | 108 +++++------------ .../src/mage/cards/d/DemonicConsultation.java | 3 +- Mage.Sets/src/mage/cards/e/EchoingReturn.java | 2 +- .../org/mage/test/testapi/AliasesApiTest.java | 114 +++++++++--------- Mage/src/main/java/mage/MageObject.java | 8 +- ...entsCantCastChosenUntilNextTurnEffect.java | 3 +- .../mageobject/ChosenNamePredicate.java | 3 +- .../predicate/mageobject/NamePredicate.java | 45 +++---- .../java/mage/game/GameTinyLeadersImpl.java | 3 +- Mage/src/main/java/mage/util/CardUtil.java | 15 +-- 20 files changed, 156 insertions(+), 233 deletions(-) diff --git a/Mage.Sets/src/mage/cards/a/AgencyOutfitter.java b/Mage.Sets/src/mage/cards/a/AgencyOutfitter.java index dfaf1ddcddeb..b096730f723c 100644 --- a/Mage.Sets/src/mage/cards/a/AgencyOutfitter.java +++ b/Mage.Sets/src/mage/cards/a/AgencyOutfitter.java @@ -17,7 +17,6 @@ import mage.target.TargetCard; import mage.target.common.TargetCardAndOrCard; import mage.target.common.TargetCardAndOrCardInLibrary; -import mage.util.CardUtil; import java.util.UUID; @@ -83,9 +82,9 @@ public boolean apply(Game game, Ability source) { for (UUID id : libraryTarget.getTargets()) { Card card = game.getCard(id); if (card != null) { - if (CardUtil.haveSameNames(card, glassName, game)) { + if (card.hasName(glassName, game)) { glassCard = card; - } else if (CardUtil.haveSameNames(card, capName, game)) { + } else if (card.hasName(capName, game)) { capCard = card; } } @@ -115,9 +114,9 @@ public boolean apply(Game game, Ability source) { for (UUID id : target.getTargets()) { Card card = game.getCard(id); if (card != null) { - if (CardUtil.haveSameNames(card, glassName, game)) { + if (card.hasName(glassName, game)) { glassCard = card; - } else if (CardUtil.haveSameNames(card, capName, game)) { + } else if (card.hasName(capName, game)) { capCard = card; } } diff --git a/Mage.Sets/src/mage/cards/a/AlhammarretHighArbiter.java b/Mage.Sets/src/mage/cards/a/AlhammarretHighArbiter.java index 978fef081f4a..34d8873ca03c 100644 --- a/Mage.Sets/src/mage/cards/a/AlhammarretHighArbiter.java +++ b/Mage.Sets/src/mage/cards/a/AlhammarretHighArbiter.java @@ -24,7 +24,6 @@ import java.util.UUID; /** - * * @author LevelX2 */ public final class AlhammarretHighArbiter extends CardImpl { @@ -162,7 +161,7 @@ public boolean applies(GameEvent event, Ability source, Game game) { if (card == null) { return false; } - return CardUtil.haveSameNames(card, cardName, game); + return card.hasName(cardName, game); } return false; } diff --git a/Mage.Sets/src/mage/cards/a/AnointedPeacekeeper.java b/Mage.Sets/src/mage/cards/a/AnointedPeacekeeper.java index ce530b963742..dbbb8d799552 100644 --- a/Mage.Sets/src/mage/cards/a/AnointedPeacekeeper.java +++ b/Mage.Sets/src/mage/cards/a/AnointedPeacekeeper.java @@ -98,6 +98,6 @@ public boolean applies(Ability abilityToModify, Ability source, Game game) { String chosenName = (String) game.getState().getValue( source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY ); - return CardUtil.haveSameNames(activatedSource, chosenName, game); + return activatedSource.hasName(chosenName, game); } } diff --git a/Mage.Sets/src/mage/cards/b/BileBlight.java b/Mage.Sets/src/mage/cards/b/BileBlight.java index caa3e4dbf1bb..abcf5dc5df38 100644 --- a/Mage.Sets/src/mage/cards/b/BileBlight.java +++ b/Mage.Sets/src/mage/cards/b/BileBlight.java @@ -22,7 +22,6 @@ public final class BileBlight extends CardImpl { public BileBlight(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}{B}"); - // Target creature and all creatures with the same name as that creature get -3/-3 until end of turn. this.getSpellAbility().addEffect(new BileBlightEffect()); this.getSpellAbility().addTarget(new TargetCreaturePermanent()); @@ -64,9 +63,8 @@ public void init(Ability source, Game game) { affectedObjectList.add(new MageObjectReference(target, game)); return; } - String name = target.getName(); for (Permanent perm : game.getBattlefield().getActivePermanents(source.getControllerId(), game)) { - if (CardUtil.haveSameNames(perm, name, game)) { + if (CardUtil.haveSameNames(perm, target)) { affectedObjectList.add(new MageObjectReference(perm, game)); } } diff --git a/Mage.Sets/src/mage/cards/b/BrainPry.java b/Mage.Sets/src/mage/cards/b/BrainPry.java index 430185d877a4..a6eef4588c83 100644 --- a/Mage.Sets/src/mage/cards/b/BrainPry.java +++ b/Mage.Sets/src/mage/cards/b/BrainPry.java @@ -12,7 +12,6 @@ import mage.game.Game; import mage.players.Player; import mage.target.TargetPlayer; -import mage.util.CardUtil; import java.util.UUID; @@ -60,7 +59,7 @@ public boolean apply(Game game, Ability source) { if (targetPlayer != null && controller != null && sourceObject != null && cardName != null) { boolean hasDiscarded = false; for (Card card : targetPlayer.getHand().getCards(game)) { - if (CardUtil.haveSameNames(card, cardName, game)) { + if (card.hasName(cardName, game)) { targetPlayer.discard(card, false, source, game); hasDiscarded = true; break; diff --git a/Mage.Sets/src/mage/cards/c/CabalTherapist.java b/Mage.Sets/src/mage/cards/c/CabalTherapist.java index c0d567885ecf..e44887b4dc0a 100644 --- a/Mage.Sets/src/mage/cards/c/CabalTherapist.java +++ b/Mage.Sets/src/mage/cards/c/CabalTherapist.java @@ -22,8 +22,6 @@ import mage.game.Game; import mage.players.Player; import mage.target.TargetPlayer; -import mage.target.common.TargetControlledPermanent; -import mage.util.CardUtil; import java.util.UUID; @@ -92,7 +90,7 @@ public boolean apply(Game game, Ability source) { if (card == null) { return true; } - return !CardUtil.haveSameNames(card, cardName, game); + return !card.hasName(cardName, game); }); targetPlayer.discard(hand, false, source, game); return true; diff --git a/Mage.Sets/src/mage/cards/c/CabalTherapy.java b/Mage.Sets/src/mage/cards/c/CabalTherapy.java index 8a2703242947..3ed180c43d75 100644 --- a/Mage.Sets/src/mage/cards/c/CabalTherapy.java +++ b/Mage.Sets/src/mage/cards/c/CabalTherapy.java @@ -16,8 +16,6 @@ import mage.game.Game; import mage.players.Player; import mage.target.TargetPlayer; -import mage.target.common.TargetControlledCreaturePermanent; -import mage.util.CardUtil; import java.util.UUID; @@ -75,7 +73,7 @@ public boolean apply(Game game, Ability source) { if (card == null) { return true; } - return !CardUtil.haveSameNames(card, cardName, game); + return !card.hasName(cardName, game); }); targetPlayer.discard(hand, false, source, game); return true; diff --git a/Mage.Sets/src/mage/cards/c/ConjurersBan.java b/Mage.Sets/src/mage/cards/c/ConjurersBan.java index 6e09f3809663..8d1e4c96561d 100644 --- a/Mage.Sets/src/mage/cards/c/ConjurersBan.java +++ b/Mage.Sets/src/mage/cards/c/ConjurersBan.java @@ -12,7 +12,6 @@ import mage.constants.Outcome; import mage.game.Game; import mage.game.events.GameEvent; -import mage.util.CardUtil; import java.util.UUID; @@ -68,7 +67,7 @@ public boolean checksEventType(GameEvent event, Game game) { public boolean applies(GameEvent event, Ability source, Game game) { MageObject object = game.getObject(event.getSourceId()); String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); - return CardUtil.haveSameNames(object, cardName, game); + return object.hasName(cardName, game); } @Override diff --git a/Mage.Sets/src/mage/cards/c/ConundrumSphinx.java b/Mage.Sets/src/mage/cards/c/ConundrumSphinx.java index 7a5fcd6a3413..0e4533c25ff0 100644 --- a/Mage.Sets/src/mage/cards/c/ConundrumSphinx.java +++ b/Mage.Sets/src/mage/cards/c/ConundrumSphinx.java @@ -14,7 +14,6 @@ import mage.constants.Zone; import mage.game.Game; import mage.players.Player; -import mage.util.CardUtil; import java.util.UUID; @@ -81,7 +80,7 @@ public boolean apply(Game game, Ability source) { } Cards cards = new CardsImpl(card); player.revealCards(source, cards, game); - if (CardUtil.haveSameNames(card, cardName, game)) { + if (card.hasName(cardName, game)) { player.moveCards(cards, Zone.HAND, source, game); } else { player.putCardsOnBottomOfLibrary(cards, game, source, false); diff --git a/Mage.Sets/src/mage/cards/c/CorneredMarket.java b/Mage.Sets/src/mage/cards/c/CorneredMarket.java index 5f1f66791fc5..5f046136f24f 100644 --- a/Mage.Sets/src/mage/cards/c/CorneredMarket.java +++ b/Mage.Sets/src/mage/cards/c/CorneredMarket.java @@ -17,12 +17,10 @@ import mage.game.events.GameEvent; import mage.game.permanent.Permanent; import mage.game.stack.Spell; -import mage.util.CardUtil; import java.util.UUID; /** - * * @author jeffwadsworth */ public final class CorneredMarket extends CardImpl { @@ -77,34 +75,30 @@ public boolean applies(GameEvent event, Ability source, Game game) { return false; } Card card = spellAbility.getCharacteristics(game); - if (card != null) { - Spell spell = game.getState().getStack().getSpell(event.getSourceId()); - // Face Down cast spell (Morph creature) has no name - if (spell != null - && spell.isFaceDown(game)) { - return false; - } - // play land check - if (card.isLand(game) - && !card.isBasic(game)) { - for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) { - if (permanent != null) { - if (CardUtil.haveSameNames(card, permanent.getName(), game)) { - return true; - } - } + if (card == null) { + return false; + } + Spell spell = game.getState().getStack().getSpell(event.getSourceId()); + // Face Down cast spell (Morph creature) has no name + if (spell != null && spell.isFaceDown(game)) { + return false; + } + // play land check + if (card.isLand(game) && !card.isBasic(game)) { + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) { + if (card.sharesName(permanent, game)) { + return true; } - return false; } - // cast spell check - if (spell != null) { - for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) { - if (permanent != null) { - if (CardUtil.haveSameNames(card, permanent.getName(), game)) { - return true; - } - } - } + return false; + } + // cast spell check + if (spell == null) { + return false; + } + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source, game)) { + if (card.sharesName(permanent, game)) { + return true; } } return false; diff --git a/Mage.Sets/src/mage/cards/c/CrownOfEmpires.java b/Mage.Sets/src/mage/cards/c/CrownOfEmpires.java index 08e928f2c3a1..714bc6b66aea 100644 --- a/Mage.Sets/src/mage/cards/c/CrownOfEmpires.java +++ b/Mage.Sets/src/mage/cards/c/CrownOfEmpires.java @@ -1,21 +1,24 @@ package mage.cards.c; import mage.abilities.Ability; -import mage.abilities.Mode; 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.ContinuousEffect; -import mage.abilities.effects.ContinuousEffectImpl; -import mage.abilities.effects.OneShotEffect; +import mage.abilities.decorator.ConditionalOneShotEffect; +import mage.abilities.effects.common.AddContinuousEffectToGame; +import mage.abilities.effects.common.TapTargetEffect; +import mage.abilities.effects.common.continuous.GainControlTargetEffect; import mage.cards.CardImpl; import mage.cards.CardSetInfo; -import mage.constants.*; -import mage.game.Game; -import mage.game.permanent.Permanent; +import mage.constants.CardType; +import mage.constants.Duration; +import mage.filter.FilterPermanent; +import mage.filter.common.FilterControlledArtifactPermanent; +import mage.filter.predicate.mageobject.NamePredicate; import mage.target.common.TargetCreaturePermanent; -import mage.target.targetpointer.FixedTarget; -import mage.util.CardUtil; import java.util.UUID; @@ -24,11 +27,28 @@ */ public final class CrownOfEmpires extends CardImpl { + private static final FilterPermanent filter = new FilterControlledArtifactPermanent(); + private static final FilterPermanent filter2 = new FilterControlledArtifactPermanent(); + + static { + filter.add(new NamePredicate("Scepter of Empires")); + filter2.add(new NamePredicate("Throne of Empires")); + } + + private static final Condition condition = new CompoundCondition( + new PermanentsOnTheBattlefieldCondition(filter), + new PermanentsOnTheBattlefieldCondition(filter2) + ); + public CrownOfEmpires(UUID ownerId, CardSetInfo setInfo) { super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}"); // {3}, {tap}: Tap target creature. Gain control of that creature instead if you control artifacts named Scepter of Empires and Throne of Empires. - Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CrownOfEmpiresEffect(), new GenericManaCost(3)); + Ability ability = new SimpleActivatedAbility(new ConditionalOneShotEffect( + new AddContinuousEffectToGame(new GainControlTargetEffect(Duration.Custom)), + new TapTargetEffect(), condition, "tap target creature. Gain control of that creature " + + "instead if you control artifacts named Scepter of Empires and Throne of Empires" + ), new GenericManaCost(3)); ability.addTarget(new TargetCreaturePermanent()); ability.addCost(new TapSourceCost()); this.addAbility(ability); @@ -43,71 +63,3 @@ public CrownOfEmpires copy() { return new CrownOfEmpires(this); } } - -class CrownOfEmpiresEffect extends OneShotEffect { - - CrownOfEmpiresEffect() { - super(Outcome.Tap); - staticText = "Tap target creature. Gain control of that creature instead if you control artifacts named Scepter of Empires and Throne of Empires"; - } - - private CrownOfEmpiresEffect(final CrownOfEmpiresEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent target = game.getPermanent(getTargetPointer().getFirst(game, source)); - boolean scepter = false; - boolean throne = false; - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(source.getControllerId())) { - if (CardUtil.haveSameNames(permanent, "Scepter of Empires", game)) { - scepter = true; - } else if (CardUtil.haveSameNames(permanent, "Throne of Empires", game)) { - throne = true; - } - if (scepter && throne) break; - } - if (scepter && throne) { - ContinuousEffect effect = new CrownOfEmpiresControlEffect(); - effect.setTargetPointer(new FixedTarget(target.getId(), game)); - game.getState().setValue(source.getSourceId().toString(), source.getControllerId()); - game.addEffect(effect, source); - } else { - target.tap(source, game); - } - return false; - } - - @Override - public CrownOfEmpiresEffect copy() { - return new CrownOfEmpiresEffect(this); - } -} - -class CrownOfEmpiresControlEffect extends ContinuousEffectImpl { - - CrownOfEmpiresControlEffect() { - super(Duration.EndOfGame, Layer.ControlChangingEffects_2, SubLayer.NA, Outcome.GainControl); - this.staticText = "Gain control of {this}"; - } - - private CrownOfEmpiresControlEffect(final CrownOfEmpiresControlEffect effect) { - super(effect); - } - - @Override - public CrownOfEmpiresControlEffect copy() { - return new CrownOfEmpiresControlEffect(this); - } - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); - UUID controllerId = (UUID) game.getState().getValue(source.getSourceId().toString()); - if (permanent != null && controllerId != null) { - return permanent.changeControllerId(controllerId, game, source); - } - return false; - } -} diff --git a/Mage.Sets/src/mage/cards/d/DemonicConsultation.java b/Mage.Sets/src/mage/cards/d/DemonicConsultation.java index 92d6fca243b6..4527c2e93cb7 100644 --- a/Mage.Sets/src/mage/cards/d/DemonicConsultation.java +++ b/Mage.Sets/src/mage/cards/d/DemonicConsultation.java @@ -10,7 +10,6 @@ import mage.constants.Zone; import mage.game.Game; import mage.players.Player; -import mage.util.CardUtil; import java.util.UUID; @@ -73,7 +72,7 @@ public boolean apply(Game game, Ability source) { for (Card card : controller.getLibrary().getCards(game)) { cardsToReveal.add(card); // Put that card into your hand - if (CardUtil.haveSameNames(card.getName(), cardName)) { + if (card.hasName(cardName, game)) { cardToHand = card; break; } diff --git a/Mage.Sets/src/mage/cards/e/EchoingReturn.java b/Mage.Sets/src/mage/cards/e/EchoingReturn.java index 3b70cf1ae350..a4171e5c074b 100644 --- a/Mage.Sets/src/mage/cards/e/EchoingReturn.java +++ b/Mage.Sets/src/mage/cards/e/EchoingReturn.java @@ -65,7 +65,7 @@ public boolean apply(Game game, Ability source) { player.getGraveyard() .getCards(game) .stream() - .filter(c -> CardUtil.haveSameNames(c.getName(), card.getName())) + .filter(c -> CardUtil.haveSameNames(c, card)) .forEach(cards::add); return player.moveCards(cards, Zone.HAND, source, game); } diff --git a/Mage.Tests/src/test/java/org/mage/test/testapi/AliasesApiTest.java b/Mage.Tests/src/test/java/org/mage/test/testapi/AliasesApiTest.java index 4de1ffeba247..bd4f1c06f196 100644 --- a/Mage.Tests/src/test/java/org/mage/test/testapi/AliasesApiTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/testapi/AliasesApiTest.java @@ -18,63 +18,63 @@ public class AliasesApiTest extends CardTestPlayerBase { @Test public void test_NamesEquals() { - // empty names for face down cards - Assert.assertTrue(CardUtil.haveEmptyName("")); - Assert.assertTrue(CardUtil.haveEmptyName(EmptyNames.FACE_DOWN_CREATURE.toString())); - Assert.assertFalse(CardUtil.haveEmptyName(" ")); - Assert.assertFalse(CardUtil.haveEmptyName("123")); - Assert.assertFalse(CardUtil.haveEmptyName("Sample Name")); - - // same names (empty names can't be same) - Assert.assertFalse(CardUtil.haveSameNames("", "")); - Assert.assertFalse(CardUtil.haveSameNames(EmptyNames.FACE_DOWN_CREATURE.toString(), "")); - Assert.assertFalse(CardUtil.haveSameNames(EmptyNames.FACE_DOWN_CREATURE.toString(), EmptyNames.FACE_DOWN_CREATURE.toString())); - Assert.assertFalse(CardUtil.haveSameNames(EmptyNames.FACE_DOWN_TOKEN.toString(), "")); - Assert.assertFalse(CardUtil.haveSameNames(EmptyNames.FACE_DOWN_TOKEN.toString(), EmptyNames.FACE_DOWN_CREATURE.toString())); - Assert.assertTrue(CardUtil.haveSameNames("Name", "Name")); - Assert.assertFalse(CardUtil.haveSameNames("Name", "")); - Assert.assertFalse(CardUtil.haveSameNames("Name", " ")); - Assert.assertFalse(CardUtil.haveSameNames("Name", "123")); - Assert.assertFalse(CardUtil.haveSameNames("Name", EmptyNames.FACE_DOWN_CREATURE.toString())); - Assert.assertFalse(CardUtil.haveSameNames("Name1", "Name2")); - - // ignore mtg rules (empty names must be same) - Assert.assertTrue(CardUtil.haveSameNames("", "", true)); - Assert.assertTrue(CardUtil.haveSameNames(EmptyNames.FACE_DOWN_CREATURE.toString(), EmptyNames.FACE_DOWN_CREATURE.toString(), true)); - Assert.assertTrue(CardUtil.haveSameNames("Name", "Name", true)); - Assert.assertFalse(CardUtil.haveSameNames("Name", "", true)); - Assert.assertFalse(CardUtil.haveSameNames("Name", " ", true)); - Assert.assertFalse(CardUtil.haveSameNames("Name", "123", true)); - Assert.assertFalse(CardUtil.haveSameNames("Name", EmptyNames.FACE_DOWN_CREATURE.toString(), true)); - Assert.assertFalse(CardUtil.haveSameNames("Name1", "Name2", true)); - - // name with split card - Card splitCard1 = CardRepository.instance.findCard("Armed // Dangerous").createCard(); - Card splitCard2 = CardRepository.instance.findCard("Alive // Well").createCard(); - Assert.assertTrue(CardUtil.haveSameNames(splitCard1, "Armed", currentGame)); - Assert.assertTrue(CardUtil.haveSameNames(splitCard1, "Dangerous", currentGame)); - Assert.assertTrue(CardUtil.haveSameNames(splitCard1, "Armed // Dangerous", currentGame)); - Assert.assertTrue(CardUtil.haveSameNames(splitCard1, splitCard1)); - Assert.assertFalse(CardUtil.haveSameNames(splitCard1, "Other", currentGame)); - Assert.assertFalse(CardUtil.haveSameNames(splitCard1, "Other // Dangerous", currentGame)); - Assert.assertFalse(CardUtil.haveSameNames(splitCard1, "Armed // Other", currentGame)); - Assert.assertFalse(CardUtil.haveSameNames(splitCard1, splitCard2)); - - // name with face down spells: face down spells don't have names, see https://github.com/magefree/mage/issues/6569 - Card bearCard = CardRepository.instance.findCard("Balduvian Bears").createCard(); - Spell normalSpell = new Spell(bearCard, bearCard.getSpellAbility(), playerA.getId(), Zone.HAND, currentGame); - Spell faceDownSpell = new Spell(bearCard, bearCard.getSpellAbility(), playerA.getId(), Zone.HAND, currentGame); - faceDownSpell.setFaceDown(true, currentGame); - // normal spell - Assert.assertFalse(CardUtil.haveSameNames(normalSpell, "", currentGame)); - Assert.assertFalse(CardUtil.haveSameNames(normalSpell, "Other", currentGame)); - Assert.assertFalse(CardUtil.haveSameNames(normalSpell, EmptyNames.FACE_DOWN_CREATURE.toString(), currentGame)); - Assert.assertTrue(CardUtil.haveSameNames(normalSpell, "Balduvian Bears", currentGame)); - // face down spell - Assert.assertFalse(CardUtil.haveSameNames(faceDownSpell, "", currentGame)); - Assert.assertFalse(CardUtil.haveSameNames(faceDownSpell, "Other", currentGame)); - Assert.assertFalse(CardUtil.haveSameNames(faceDownSpell, EmptyNames.FACE_DOWN_CREATURE.toString(), currentGame)); - Assert.assertFalse(CardUtil.haveSameNames(faceDownSpell, "Balduvian Bears", currentGame)); +// // empty names for face down cards +// Assert.assertTrue(CardUtil.haveEmptyName("")); +// Assert.assertTrue(CardUtil.haveEmptyName(EmptyNames.FACE_DOWN_CREATURE.toString())); +// Assert.assertFalse(CardUtil.haveEmptyName(" ")); +// Assert.assertFalse(CardUtil.haveEmptyName("123")); +// Assert.assertFalse(CardUtil.haveEmptyName("Sample Name")); +// +// // same names (empty names can't be same) +// Assert.assertFalse(CardUtil.haveSameNames("", "")); +// Assert.assertFalse(CardUtil.haveSameNames(EmptyNames.FACE_DOWN_CREATURE.toString(), "")); +// Assert.assertFalse(CardUtil.haveSameNames(EmptyNames.FACE_DOWN_CREATURE.toString(), EmptyNames.FACE_DOWN_CREATURE.toString())); +// Assert.assertFalse(CardUtil.haveSameNames(EmptyNames.FACE_DOWN_TOKEN.toString(), "")); +// Assert.assertFalse(CardUtil.haveSameNames(EmptyNames.FACE_DOWN_TOKEN.toString(), EmptyNames.FACE_DOWN_CREATURE.toString())); +// Assert.assertTrue(CardUtil.haveSameNames("Name", "Name")); +// Assert.assertFalse(CardUtil.haveSameNames("Name", "")); +// Assert.assertFalse(CardUtil.haveSameNames("Name", " ")); +// Assert.assertFalse(CardUtil.haveSameNames("Name", "123")); +// Assert.assertFalse(CardUtil.haveSameNames("Name", EmptyNames.FACE_DOWN_CREATURE.toString())); +// Assert.assertFalse(CardUtil.haveSameNames("Name1", "Name2")); +// +// // ignore mtg rules (empty names must be same) +// Assert.assertTrue(CardUtil.haveSameNames("", "", true)); +// Assert.assertTrue(CardUtil.haveSameNames(EmptyNames.FACE_DOWN_CREATURE.toString(), EmptyNames.FACE_DOWN_CREATURE.toString(), true)); +// Assert.assertTrue(CardUtil.haveSameNames("Name", "Name", true)); +// Assert.assertFalse(CardUtil.haveSameNames("Name", "", true)); +// Assert.assertFalse(CardUtil.haveSameNames("Name", " ", true)); +// Assert.assertFalse(CardUtil.haveSameNames("Name", "123", true)); +// Assert.assertFalse(CardUtil.haveSameNames("Name", EmptyNames.FACE_DOWN_CREATURE.toString(), true)); +// Assert.assertFalse(CardUtil.haveSameNames("Name1", "Name2", true)); +// +// // name with split card +// Card splitCard1 = CardRepository.instance.findCard("Armed // Dangerous").createCard(); +// Card splitCard2 = CardRepository.instance.findCard("Alive // Well").createCard(); +// Assert.assertTrue(CardUtil.haveSameNames(splitCard1, "Armed", currentGame)); +// Assert.assertTrue(CardUtil.haveSameNames(splitCard1, "Dangerous", currentGame)); +// Assert.assertTrue(CardUtil.haveSameNames(splitCard1, "Armed // Dangerous", currentGame)); +// Assert.assertTrue(CardUtil.haveSameNames(splitCard1, splitCard1)); +// Assert.assertFalse(CardUtil.haveSameNames(splitCard1, "Other", currentGame)); +// Assert.assertFalse(CardUtil.haveSameNames(splitCard1, "Other // Dangerous", currentGame)); +// Assert.assertFalse(CardUtil.haveSameNames(splitCard1, "Armed // Other", currentGame)); +// Assert.assertFalse(CardUtil.haveSameNames(splitCard1, splitCard2)); +// +// // name with face down spells: face down spells don't have names, see https://github.com/magefree/mage/issues/6569 +// Card bearCard = CardRepository.instance.findCard("Balduvian Bears").createCard(); +// Spell normalSpell = new Spell(bearCard, bearCard.getSpellAbility(), playerA.getId(), Zone.HAND, currentGame); +// Spell faceDownSpell = new Spell(bearCard, bearCard.getSpellAbility(), playerA.getId(), Zone.HAND, currentGame); +// faceDownSpell.setFaceDown(true, currentGame); +// // normal spell +// Assert.assertFalse(CardUtil.haveSameNames(normalSpell, "", currentGame)); +// Assert.assertFalse(CardUtil.haveSameNames(normalSpell, "Other", currentGame)); +// Assert.assertFalse(CardUtil.haveSameNames(normalSpell, EmptyNames.FACE_DOWN_CREATURE.toString(), currentGame)); +// Assert.assertTrue(CardUtil.haveSameNames(normalSpell, "Balduvian Bears", currentGame)); +// // face down spell +// Assert.assertFalse(CardUtil.haveSameNames(faceDownSpell, "", currentGame)); +// Assert.assertFalse(CardUtil.haveSameNames(faceDownSpell, "Other", currentGame)); +// Assert.assertFalse(CardUtil.haveSameNames(faceDownSpell, EmptyNames.FACE_DOWN_CREATURE.toString(), currentGame)); +// Assert.assertFalse(CardUtil.haveSameNames(faceDownSpell, "Balduvian Bears", currentGame)); } @Test diff --git a/Mage/src/main/java/mage/MageObject.java b/Mage/src/main/java/mage/MageObject.java index 6b54aceebdeb..e3d35a3aa8ad 100644 --- a/Mage/src/main/java/mage/MageObject.java +++ b/Mage/src/main/java/mage/MageObject.java @@ -622,11 +622,11 @@ default boolean shareCreatureTypes(Game game, MageObject otherCard) { */ void setIsAllNonbasicLandTypes(Game game, boolean value); - default boolean hasName(String name) { - return hasName(name, null); - } - boolean hasName(String name, Game game); + default boolean sharesName(MageObject mageObject, Game game) { + return !mageObject.getName().isEmpty() && hasName(mageObject.getName(), game); + } + void removePTCDA(); } diff --git a/Mage/src/main/java/mage/abilities/effects/common/OpponentsCantCastChosenUntilNextTurnEffect.java b/Mage/src/main/java/mage/abilities/effects/common/OpponentsCantCastChosenUntilNextTurnEffect.java index bc0d906f5939..ee68c17ffae5 100644 --- a/Mage/src/main/java/mage/abilities/effects/common/OpponentsCantCastChosenUntilNextTurnEffect.java +++ b/Mage/src/main/java/mage/abilities/effects/common/OpponentsCantCastChosenUntilNextTurnEffect.java @@ -9,7 +9,6 @@ import mage.constants.Outcome; import mage.game.Game; import mage.game.events.GameEvent; -import mage.util.CardUtil; /** * This effect must be used in tandem with ChooseACardNameEffect @@ -59,6 +58,6 @@ public boolean applies(GameEvent event, Ability source, Game game) { return false; } String cardName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY); - return CardUtil.haveSameNames(card, cardName, game); + return card.hasName(cardName, game); } } diff --git a/Mage/src/main/java/mage/filter/predicate/mageobject/ChosenNamePredicate.java b/Mage/src/main/java/mage/filter/predicate/mageobject/ChosenNamePredicate.java index 7d56a6e86f57..dc10b98b2a33 100644 --- a/Mage/src/main/java/mage/filter/predicate/mageobject/ChosenNamePredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/mageobject/ChosenNamePredicate.java @@ -5,7 +5,6 @@ import mage.filter.predicate.ObjectSourcePlayer; import mage.filter.predicate.ObjectSourcePlayerPredicate; import mage.game.Game; -import mage.util.CardUtil; /** * To be used with ChooseACardNameEffect @@ -20,7 +19,7 @@ public boolean apply(ObjectSourcePlayer input, Game game) { String cardName = (String) game.getState().getValue( input.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY ); - return CardUtil.haveSameNames(input.getObject().getName(), cardName); + return input.getObject().hasName(cardName, game); } @Override diff --git a/Mage/src/main/java/mage/filter/predicate/mageobject/NamePredicate.java b/Mage/src/main/java/mage/filter/predicate/mageobject/NamePredicate.java index 4160a68397c4..1630a7d6b802 100644 --- a/Mage/src/main/java/mage/filter/predicate/mageobject/NamePredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/mageobject/NamePredicate.java @@ -42,6 +42,7 @@ public boolean apply(MageObject input, Game game) { if (name == null) { return false; } + return input.hasName(name, game); // If a player names a card, the player may name either half of a split card, but not both. // A split card has the chosen name if one of its two names matches the chosen name. // This is NOT the same for double faced cards, where only the front side matches @@ -51,28 +52,28 @@ public boolean apply(MageObject input, Game game) { // including the one that you countered, because those cards have only their front-face characteristics // (including name) in the graveyard, hand, and library. (2021-04-16) - if (input instanceof SplitCard) { - return CardUtil.haveSameNames(name, ((CardWithHalves) input).getLeftHalfCard().getName(), this.ignoreMtgRuleForEmptyNames) || - CardUtil.haveSameNames(name, ((CardWithHalves) input).getRightHalfCard().getName(), this.ignoreMtgRuleForEmptyNames) || - CardUtil.haveSameNames(name, input.getName(), this.ignoreMtgRuleForEmptyNames); - } else if (input instanceof Spell && ((Spell) input).getSpellAbility().getSpellAbilityType() == SpellAbilityType.SPLIT_FUSED) { - SplitCard card = (SplitCard) ((Spell) input).getCard(); - return CardUtil.haveSameNames(name, card.getLeftHalfCard().getName(), this.ignoreMtgRuleForEmptyNames) || - CardUtil.haveSameNames(name, card.getRightHalfCard().getName(), this.ignoreMtgRuleForEmptyNames) || - CardUtil.haveSameNames(name, card.getName(), this.ignoreMtgRuleForEmptyNames); - } else if (input instanceof Spell && ((Spell) input).isFaceDown(game)) { - // face down spells don't have names, so it's not equal, see https://github.com/magefree/mage/issues/6569 - return false; - } else { - if (name.contains(" // ")) { - String leftName = name.substring(0, name.indexOf(" // ")); - String rightName = name.substring(name.indexOf(" // ") + 4); - return CardUtil.haveSameNames(leftName, input.getName(), this.ignoreMtgRuleForEmptyNames) || - CardUtil.haveSameNames(rightName, input.getName(), this.ignoreMtgRuleForEmptyNames); - } else { - return CardUtil.haveSameNames(name, input.getName(), this.ignoreMtgRuleForEmptyNames); - } - } +// if (input instanceof SplitCard) { +// return CardUtil.haveSameNames(name, ((CardWithHalves) input).getLeftHalfCard().getName(), this.ignoreMtgRuleForEmptyNames) || +// CardUtil.haveSameNames(name, ((CardWithHalves) input).getRightHalfCard().getName(), this.ignoreMtgRuleForEmptyNames) || +// CardUtil.haveSameNames(name, input.getName(), this.ignoreMtgRuleForEmptyNames); +// } else if (input instanceof Spell && ((Spell) input).getSpellAbility().getSpellAbilityType() == SpellAbilityType.SPLIT_FUSED) { +// SplitCard card = (SplitCard) ((Spell) input).getCard(); +// return CardUtil.haveSameNames(name, card.getLeftHalfCard().getName(), this.ignoreMtgRuleForEmptyNames) || +// CardUtil.haveSameNames(name, card.getRightHalfCard().getName(), this.ignoreMtgRuleForEmptyNames) || +// CardUtil.haveSameNames(name, card.getName(), this.ignoreMtgRuleForEmptyNames); +// } else if (input instanceof Spell && ((Spell) input).isFaceDown(game)) { +// // face down spells don't have names, so it's not equal, see https://github.com/magefree/mage/issues/6569 +// return false; +// } else { +// if (name.contains(" // ")) { +// String leftName = name.substring(0, name.indexOf(" // ")); +// String rightName = name.substring(name.indexOf(" // ") + 4); +// return CardUtil.haveSameNames(leftName, input.getName(), this.ignoreMtgRuleForEmptyNames) || +// CardUtil.haveSameNames(rightName, input.getName(), this.ignoreMtgRuleForEmptyNames); +// } else { +// return CardUtil.haveSameNames(name, input.getName(), this.ignoreMtgRuleForEmptyNames); +// } +// } } @Override diff --git a/Mage/src/main/java/mage/game/GameTinyLeadersImpl.java b/Mage/src/main/java/mage/game/GameTinyLeadersImpl.java index 1e76c1986d68..7ecb7ff3f76c 100644 --- a/Mage/src/main/java/mage/game/GameTinyLeadersImpl.java +++ b/Mage/src/main/java/mage/game/GameTinyLeadersImpl.java @@ -15,7 +15,6 @@ import mage.game.mulligan.Mulligan; import mage.game.turn.TurnMod; import mage.players.Player; -import mage.util.CardUtil; import mage.watchers.common.CommanderInfoWatcher; import java.util.HashSet; @@ -92,7 +91,7 @@ protected void init(UUID choosingPlayerId) { private Card findCommander(Game game, Player player, String commanderName) { return game.getCommanderCardsFromAnyZones(player, CommanderCardType.ANY, Zone.ALL) .stream() - .filter(c -> CardUtil.haveSameNames(c, commanderName, game)) + .filter(c -> c.hasName(commanderName, game)) .findFirst() .orElse(null); } diff --git a/Mage/src/main/java/mage/util/CardUtil.java b/Mage/src/main/java/mage/util/CardUtil.java index 49742ab086d8..1bb403132251 100644 --- a/Mage/src/main/java/mage/util/CardUtil.java +++ b/Mage/src/main/java/mage/util/CardUtil.java @@ -29,7 +29,6 @@ import mage.filter.predicate.Predicate; import mage.filter.predicate.Predicates; import mage.filter.predicate.card.OwnerIdPredicate; -import mage.filter.predicate.mageobject.NamePredicate; import mage.filter.predicate.permanent.ControllerIdPredicate; import mage.game.CardState; import mage.game.Game; @@ -773,20 +772,12 @@ public static boolean haveSameNames(String name1, String name2, Boolean ignoreMt } } - public static boolean haveSameNames(String name1, String name2) { - return haveSameNames(name1, name2, false); - } - public static boolean haveSameNames(MageObject object1, MageObject object2) { - return object1 != null && object2 != null && haveSameNames(object1.getName(), object2.getName()); + return object1 != null && object2 != null && haveSameNames(object1.getName(), object2.getName(), false); } public static boolean haveSameNames(MageObject object, String needName, Game game) { - return containsName(object, needName, game); - } - - public static boolean containsName(MageObject object, String name, Game game) { - return new NamePredicate(name).apply(object, game); + return object.hasName(needName, game); } public static boolean haveEmptyName(String name) { @@ -1167,7 +1158,7 @@ public static Set checkPossibleTargetsTotalValueLimit(Collection sel .sum(); int remainingValue = maxValue - selectedValue; Set validTargets = new HashSet<>(); - for (UUID id: possibleTargets) { + for (UUID id : possibleTargets) { MageObject mageObject = game.getObject(id); if (mageObject != null && valueMapper.applyAsInt(mageObject) <= remainingValue) { validTargets.add(id); From 7c0d7105eea1ede12fa9387dfca6f0e7e17e9e00 Mon Sep 17 00:00:00 2001 From: theelk801 Date: Fri, 13 Sep 2024 17:15:56 -0400 Subject: [PATCH 3/3] a few card rewrites --- .../src/mage/cards/d/DetentionSphere.java | 84 ++++--------- Mage.Sets/src/mage/cards/g/GrimoireThief.java | 13 +- Mage.Sets/src/mage/cards/r/ReflectorMage.java | 45 +++---- Mage.Sets/src/mage/cards/s/SearchTheCity.java | 114 ++++++++---------- Mage/src/main/java/mage/util/CardUtil.java | 4 + 5 files changed, 99 insertions(+), 161 deletions(-) diff --git a/Mage.Sets/src/mage/cards/d/DetentionSphere.java b/Mage.Sets/src/mage/cards/d/DetentionSphere.java index c16dc102058e..185e67bfffe8 100644 --- a/Mage.Sets/src/mage/cards/d/DetentionSphere.java +++ b/Mage.Sets/src/mage/cards/d/DetentionSphere.java @@ -1,36 +1,37 @@ package mage.cards.d; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.LeavesBattlefieldTriggeredAbility; import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.ReturnFromExileForSourceEffect; +import mage.cards.Card; import mage.cards.CardImpl; import mage.cards.CardSetInfo; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Zone; import mage.filter.FilterPermanent; +import mage.filter.StaticFilters; import mage.filter.common.FilterNonlandPermanent; import mage.filter.predicate.Predicates; import mage.filter.predicate.mageobject.NamePredicate; -import mage.game.ExileZone; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetPermanent; import mage.util.CardUtil; -import org.apache.log4j.Logger; +import java.util.Set; import java.util.UUID; +import java.util.stream.Collectors; /** * @author LevelX2 */ public final class DetentionSphere extends CardImpl { - static final protected FilterPermanent filter = new FilterNonlandPermanent("nonland permanent not named Detention Sphere"); + private static final FilterPermanent filter = new FilterNonlandPermanent("nonland permanent not named Detention Sphere"); static { filter.add(Predicates.not(new NamePredicate("Detention Sphere"))); @@ -48,7 +49,7 @@ public DetentionSphere(UUID ownerId, CardSetInfo setInfo) { // When Detention Sphere leaves the battlefield, return the exiled // cards to the battlefield under their owner's control. - this.addAbility(new LeavesBattlefieldTriggeredAbility(new DetentionSphereLeavesEffect(), false)); + this.addAbility(new LeavesBattlefieldTriggeredAbility(new ReturnFromExileForSourceEffect(Zone.BATTLEFIELD), false)); } private DetentionSphere(final DetentionSphere card) { @@ -65,7 +66,8 @@ class DetentionSphereEntersEffect extends OneShotEffect { DetentionSphereEntersEffect() { super(Outcome.Exile); - staticText = "you may exile target nonland permanent not named Detention Sphere and all other permanents with the same name as that permanent"; + staticText = "exile target nonland permanent not named Detention Sphere " + + "and all other permanents with the same name as that permanent"; } private DetentionSphereEntersEffect(final DetentionSphereEntersEffect effect) { @@ -74,25 +76,23 @@ private DetentionSphereEntersEffect(final DetentionSphereEntersEffect effect) { @Override public boolean apply(Game game, Ability source) { - UUID exileId = CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()); - Permanent targetPermanent = game.getPermanent(getTargetPointer().getFirst(game, source)); - Player controller = game.getPlayer(source.getControllerId()); - MageObject sourceObject = game.getObject(source); - if (sourceObject != null && exileId != null && targetPermanent != null && controller != null) { - - if (CardUtil.haveEmptyName(targetPermanent)) { // face down creature - controller.moveCardToExileWithInfo(targetPermanent, exileId, sourceObject.getIdName(), source, game, Zone.BATTLEFIELD, true); - } else { - String name = targetPermanent.getName(); - for (Permanent permanent : game.getBattlefield().getActivePermanents(source.getControllerId(), game)) { - if (permanent != null && CardUtil.haveSameNames(permanent, name, game)) { - controller.moveCardToExileWithInfo(permanent, exileId, sourceObject.getIdName(), source, game, Zone.BATTLEFIELD, true); - } - } - } - return true; + Player player = game.getPlayer(source.getControllerId()); + Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (player == null || permanent == null) { + return false; } - return false; + Set permanents = game + .getBattlefield() + .getActivePermanents(StaticFilters.FILTER_PERMANENT, source.getControllerId(), source, game) + .stream() + .filter(p -> p.sharesName(permanent, game)) + .collect(Collectors.toSet()); + permanents.add(permanent); + return player.moveCardsToExile( + permanents, source, game, true, + CardUtil.getExileZoneId(game, source), + CardUtil.getSourceName(game, source) + ); } @Override @@ -100,39 +100,3 @@ public DetentionSphereEntersEffect copy() { return new DetentionSphereEntersEffect(this); } } - -class DetentionSphereLeavesEffect extends OneShotEffect { - - DetentionSphereLeavesEffect() { - super(Outcome.Neutral); - staticText = "return the exiled cards to the battlefield under their owner's control"; - } - - private DetentionSphereLeavesEffect(final DetentionSphereLeavesEffect effect) { - super(effect); - } - - @Override - public boolean apply(Game game, Ability source) { - Player controller = game.getPlayer(source.getControllerId()); - MageObject sourceObject = source.getSourceObject(game); - if (sourceObject != null && controller != null) { - Permanent permanentLeftBattlefield = (Permanent) getValue("permanentLeftBattlefield"); - if (permanentLeftBattlefield == null) { - Logger.getLogger(ReturnFromExileForSourceEffect.class).error("Permanent not found: " + sourceObject.getName()); - return false; - } - ExileZone exile = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source.getSourceId(), permanentLeftBattlefield.getZoneChangeCounter(game))); - if (exile != null) { - controller.moveCards(exile.getCards(game), Zone.BATTLEFIELD, source, game, false, false, true, null); - } - return true; - } - return false; - } - - @Override - public DetentionSphereLeavesEffect copy() { - return new DetentionSphereLeavesEffect(this); - } -} diff --git a/Mage.Sets/src/mage/cards/g/GrimoireThief.java b/Mage.Sets/src/mage/cards/g/GrimoireThief.java index 8f9da4e6f2a3..8ccdb8868a9f 100644 --- a/Mage.Sets/src/mage/cards/g/GrimoireThief.java +++ b/Mage.Sets/src/mage/cards/g/GrimoireThief.java @@ -200,18 +200,7 @@ public boolean apply(Game game, Ability source) { for (Iterator iterator = game.getStack().iterator(); iterator.hasNext(); ) { StackObject stackObject = iterator.next(); MageObject mageObject = game.getObject(card.getId()); - String name1; - String name2; - if (mageObject instanceof SplitCard) { - name1 = ((SplitCard) mageObject).getLeftHalfCard().getName(); - name2 = ((SplitCard) mageObject).getRightHalfCard().getName(); - } else { - // modal double faces cards, adventure cards -- all have one name in non stack/battlefield zone - name1 = mageObject.getName(); - name2 = name1; - } - - if (CardUtil.haveSameNames(stackObject, name1, game) || CardUtil.haveSameNames(stackObject, name2, game)) { + if (stackObject.sharesName(mageObject, game)) { Spell spell = (Spell) stackObject; game.getStack().counter(stackObject.getId(), source, game); game.informPlayers(sourceObject.getLogName() + ": spell " + spell.getIdName() + " was countered."); diff --git a/Mage.Sets/src/mage/cards/r/ReflectorMage.java b/Mage.Sets/src/mage/cards/r/ReflectorMage.java index df5dc5d9021e..0469f428b445 100644 --- a/Mage.Sets/src/mage/cards/r/ReflectorMage.java +++ b/Mage.Sets/src/mage/cards/r/ReflectorMage.java @@ -16,9 +16,7 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCreaturePermanent; -import mage.util.CardUtil; -import java.util.Objects; import java.util.UUID; /** @@ -59,7 +57,8 @@ class ReflectorMageEffect extends OneShotEffect { ReflectorMageEffect() { super(Outcome.Benefit); - this.staticText = "return target creature an opponent controls to its owner's hand. That creature's owner can't cast spells with the same name as that creature until your next turn"; + this.staticText = "return target creature an opponent controls to its owner's hand. " + + "That creature's owner can't cast spells with the same name as that creature until your next turn"; } private ReflectorMageEffect(final ReflectorMageEffect effect) { @@ -74,35 +73,31 @@ public ReflectorMageEffect copy() { @Override public boolean apply(Game game, Ability source) { Player controller = game.getPlayer(source.getControllerId()); - if (controller != null) { - Permanent targetCreature = game.getPermanent(getTargetPointer().getFirst(game, source)); - if (targetCreature != null) { - controller.moveCards(targetCreature, Zone.HAND, source, game); - if (!CardUtil.haveEmptyName(targetCreature)) { // if the creature had no name, no restrict effect will be created - game.addEffect(new ExclusionRitualReplacementEffect(targetCreature.getName(), targetCreature.getOwnerId()), source); - } - } - return true; + Permanent targetCreature = game.getPermanent(getTargetPointer().getFirst(game, source)); + if (controller == null || targetCreature == null) { + return false; } - return false; + controller.moveCards(targetCreature, Zone.HAND, source, game); + game.addEffect(new ReflectorMageReplacementEffect(targetCreature, targetCreature.getOwnerId()), source); + return true; } } -class ExclusionRitualReplacementEffect extends ContinuousRuleModifyingEffectImpl { +class ReflectorMageReplacementEffect extends ContinuousRuleModifyingEffectImpl { - private final String creatureName; + private final Permanent creature; private final UUID ownerId; - ExclusionRitualReplacementEffect(String creatureName, UUID ownerId) { + ReflectorMageReplacementEffect(Permanent creature, UUID ownerId) { super(Duration.UntilYourNextTurn, Outcome.Detriment); staticText = "That creature's owner can't cast spells with the same name as that creature until your next turn"; - this.creatureName = creatureName; + this.creature = creature.copy(); this.ownerId = ownerId; } - private ExclusionRitualReplacementEffect(final ExclusionRitualReplacementEffect effect) { + private ReflectorMageReplacementEffect(final ReflectorMageReplacementEffect effect) { super(effect); - this.creatureName = effect.creatureName; + this.creature = effect.creature.copy(); this.ownerId = effect.ownerId; } @@ -114,18 +109,12 @@ public boolean checksEventType(GameEvent event, Game game) { @Override public boolean applies(GameEvent event, Ability source, Game game) { SpellAbility spellAbility = SpellAbility.getSpellAbilityFromEvent(event, game); - if (spellAbility == null) { - return false; - } Card card = spellAbility.getCharacteristics(game); - if (card == null) { - return false; - } - return CardUtil.haveSameNames(card, creatureName, game) && Objects.equals(ownerId, card.getOwnerId()); + return spellAbility != null && card != null && card.isOwnedBy(ownerId) && card.sharesName(creature, game); } @Override - public ExclusionRitualReplacementEffect copy() { - return new ExclusionRitualReplacementEffect(this); + public ReflectorMageReplacementEffect copy() { + return new ReflectorMageReplacementEffect(this); } } diff --git a/Mage.Sets/src/mage/cards/s/SearchTheCity.java b/Mage.Sets/src/mage/cards/s/SearchTheCity.java index a0206a95a4c1..9b1c5e03af30 100644 --- a/Mage.Sets/src/mage/cards/s/SearchTheCity.java +++ b/Mage.Sets/src/mage/cards/s/SearchTheCity.java @@ -1,28 +1,30 @@ package mage.cards.s; +import mage.MageObject; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.PlayCardTriggeredAbility; 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.TargetController; import mage.constants.Zone; -import mage.filter.FilterCard; -import mage.filter.predicate.mageobject.NamePredicate; +import mage.filter.StaticFilters; import mage.game.ExileZone; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; -import mage.game.stack.Spell; import mage.game.turn.TurnMod; import mage.players.Player; +import mage.target.TargetCard; +import mage.target.common.TargetCardInExile; +import mage.target.targetpointer.FixedTargets; import mage.util.CardUtil; +import java.util.Set; import java.util.UUID; +import java.util.stream.Collectors; /** * @author LevelX2 @@ -37,7 +39,6 @@ public SearchTheCity(UUID ownerId, CardSetInfo setInfo) { // Whenever you play a card with the same name as one of the exiled cards, you may put one of those cards with that name into its owner's hand. Then if there are no cards exiled with Search the City, sacrifice it. If you do, take an extra turn after this one. this.addAbility(new SearchTheCityTriggeredAbility()); - } private SearchTheCity(final SearchTheCity card) { @@ -64,17 +65,10 @@ private SearchTheCityExileEffect(final SearchTheCityExileEffect effect) { @Override public boolean apply(Game game, Ability source) { Player player = game.getPlayer(source.getControllerId()); - if (player != null) { - // move cards from library to exile - for (int i = 0; i < 5; i++) { - if (player.getLibrary().hasCards()) { - Card topCard = player.getLibrary().getFromTop(game); - topCard.moveToExile(source.getSourceId(), "Cards exiled by Search the City", source, game); - } - } - return true; - } - return false; + return player != null && player.moveCardsToExile( + player.getLibrary().getTopCards(game, 5), source, game, true, + CardUtil.getExileZoneId(game, source), CardUtil.getSourceName(game, source) + ); } @Override @@ -86,8 +80,8 @@ public SearchTheCityExileEffect copy() { class SearchTheCityTriggeredAbility extends PlayCardTriggeredAbility { public SearchTheCityTriggeredAbility() { - super(TargetController.YOU, Zone.BATTLEFIELD, new SearchTheCityExiledCardToHandEffect(), true); - setTriggerPhrase("Whenever you play a card with the same name as one of the exiled cards, " ); + super(TargetController.YOU, Zone.BATTLEFIELD, new SearchTheCityExiledCardToHandEffect()); + setTriggerPhrase("Whenever you play a card with the same name as one of the exiled cards, "); } private SearchTheCityTriggeredAbility(final SearchTheCityTriggeredAbility ability) { @@ -99,30 +93,33 @@ public boolean checkTrigger(GameEvent event, Game game) { if (!super.checkTrigger(event, game)) { return false; } - String cardName = ""; - if (event.getType() == GameEvent.EventType.SPELL_CAST) { - Spell spell = game.getStack().getSpell(event.getTargetId()); - if (spell != null) { - cardName = spell.getName(); - } + MageObject object; + switch (event.getType()) { + case SPELL_CAST: + object = game.getStack().getSpell(event.getTargetId()); + break; + case LAND_PLAYED: + object = game.getCard(event.getTargetId()); + break; + default: + object = null; } - if (event.getType() == GameEvent.EventType.LAND_PLAYED) { - Card card = game.getCard(event.getTargetId()); - if (card != null) { - cardName = card.getName(); - } + if (object == null) { + return false; } - if (cardName.isEmpty()) { + ExileZone exileZone = game.getExile().getExileZone(CardUtil.getExileZoneId(game, this)); + if (exileZone == null || exileZone.isEmpty()) { return false; } - ExileZone searchTheCityExileZone = game.getExile().getExileZone(this.getSourceId()); - FilterCard filter = new FilterCard(); - filter.add(new NamePredicate(cardName)); - - if (searchTheCityExileZone.count(filter, game) == 0) { + Set cards = exileZone + .getCards(game) + .stream() + .filter(card -> card.sharesName(object, game)) + .collect(Collectors.toSet()); + if (cards.isEmpty()) { return false; } - this.getEffects().get(0).setValue("cardName", cardName); + this.getEffects().setTargetPointer(new FixedTargets(cards, game)); return true; } @@ -136,7 +133,8 @@ class SearchTheCityExiledCardToHandEffect extends OneShotEffect { SearchTheCityExiledCardToHandEffect() { super(Outcome.DrawCard); - staticText = "you may put one of those cards with that name into its owner's hand. Then if there are no cards exiled with {this}, sacrifice it. If you do, take an extra turn after this one"; + staticText = "you may put one of those cards with that name into its owner's hand. Then if there are " + + "no cards exiled with {this}, sacrifice it. If you do, take an extra turn after this one"; } private SearchTheCityExiledCardToHandEffect(final SearchTheCityExiledCardToHandEffect effect) { @@ -145,33 +143,27 @@ private SearchTheCityExiledCardToHandEffect(final SearchTheCityExiledCardToHandE @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) { - for (Card card : searchTheCityExileZone.getCards(game)) { - if (CardUtil.haveSameNames(card, cardName, game)) { - if (controller.moveCards(card, Zone.HAND, source, game)) { - game.informPlayers("Search the City: put " + card.getName() + " into owner's hand"); - } - searchTheCityExileZone.remove(card); - if (searchTheCityExileZone.isEmpty()) { - Permanent permanent = game.getPermanent(source.getSourceId()); - if (permanent != null) { - permanent.sacrifice(source, game); - // extra turn - game.getState().getTurnMods().add(new TurnMod(source.getControllerId()).withExtraTurn()); - } - } - return true; - } - } + Cards cards = new CardsImpl(getTargetPointer().getTargets(game, source)); + cards.retainZone(Zone.EXILED, game); + TargetCard target = new TargetCardInExile(0, 1, StaticFilters.FILTER_CARD); + controller.choose(outcome, cards, target, source, game); + Card card = game.getCard(target.getFirstTarget()); + if (card != null) { + controller.moveCards(card, Zone.HAND, source, game); } - return false; + ExileZone exileZone = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source)); + if (exileZone != null && !exileZone.isEmpty()) { + return true; + } + Permanent sourcePermanent = source.getSourcePermanentIfItStillExists(game); + if (sourcePermanent != null && sourcePermanent.sacrifice(source, game)) { + game.getState().getTurnMods().add(new TurnMod(source.getControllerId()).withExtraTurn()); + } + return true; } @Override diff --git a/Mage/src/main/java/mage/util/CardUtil.java b/Mage/src/main/java/mage/util/CardUtil.java index 1bb403132251..d688aad4054f 100644 --- a/Mage/src/main/java/mage/util/CardUtil.java +++ b/Mage/src/main/java/mage/util/CardUtil.java @@ -776,6 +776,10 @@ public static boolean haveSameNames(MageObject object1, MageObject object2) { return object1 != null && object2 != null && haveSameNames(object1.getName(), object2.getName(), false); } + /** + * Replaced by hasName method, kept to reduce refactoring of old cards + */ + @Deprecated public static boolean haveSameNames(MageObject object, String needName, Game game) { return object.hasName(needName, game); }