added shared class for cards which search for different names

This commit is contained in:
Evan Kranzler 2022-03-16 16:52:13 -04:00
parent ddabfacbe7
commit 8b7a5c370a
13 changed files with 235 additions and 643 deletions

View file

@ -1,25 +1,24 @@
package mage.cards.a;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.PermanentsOnBattlefieldCount;
import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.BoostSourceEffect;
import mage.cards.*;
import mage.constants.*;
import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.SubType;
import mage.filter.FilterCard;
import mage.filter.common.FilterAttackingCreature;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.filter.predicate.mageobject.AnotherPredicate;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCardInLibrary;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.target.common.TargetCardWithDifferentNameInLibrary;
import java.util.UUID;
@ -29,9 +28,15 @@ import java.util.UUID;
public final class AlpineHoundmaster extends CardImpl {
private static final FilterAttackingCreature filter = new FilterAttackingCreature("other attacking creatures");
private static final FilterCard filter2
= new FilterCard("card named Alpine Watchdog and/or a card named Igneous Cur");
static {
filter.add(AnotherPredicate.instance);
filter2.add(Predicates.or(
new NamePredicate("Alpine Watchdog"),
new NamePredicate("Igneous Cur")
));
}
private static final DynamicValue xValue = new PermanentsOnBattlefieldCount(filter, null);
@ -45,10 +50,14 @@ public final class AlpineHoundmaster extends CardImpl {
this.toughness = new MageInt(2);
// When Alpine Houndmaster enters the battlefield, you may search your library for a card named Alpine Watchdog and/or a card named Igneous Cur, reveal them, put them into your hand, then shuffle your library.
this.addAbility(new EntersBattlefieldTriggeredAbility(new AlpineHoundmasterEffect(), true));
this.addAbility(new EntersBattlefieldTriggeredAbility(new SearchLibraryPutInHandEffect(
new TargetCardWithDifferentNameInLibrary(0, 2, filter2), true, true
).setText("search your library for a card named Alpine Watchdog and/or a card named Igneous Cur, reveal them, put them into your hand, then shuffle"), true));
// Whenever Alpine Houndmaster attacks, it gets +X/+0 until end of turn, where X is the number of other attacking creatures.
this.addAbility(new AttacksTriggeredAbility(new BoostSourceEffect(xValue, StaticValue.get(0), Duration.EndOfTurn, true, "it"), false));
this.addAbility(new AttacksTriggeredAbility(new BoostSourceEffect(
xValue, StaticValue.get(0), Duration.EndOfTurn, true, "it"
), false));
}
private AlpineHoundmaster(final AlpineHoundmaster card) {
@ -60,78 +69,3 @@ public final class AlpineHoundmaster extends CardImpl {
return new AlpineHoundmaster(this);
}
}
class AlpineHoundmasterEffect extends OneShotEffect {
AlpineHoundmasterEffect() {
super(Outcome.Benefit);
staticText = "search your library for a card named Alpine Watchdog and/or a card named Igneous Cur, " +
"reveal them, put them into your hand, then shuffle";
}
private AlpineHoundmasterEffect(final AlpineHoundmasterEffect effect) {
super(effect);
}
@Override
public AlpineHoundmasterEffect copy() {
return new AlpineHoundmasterEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
TargetCardInLibrary target = new AlpineHoundmasterTarget();
player.searchLibrary(target, source, game);
Cards cards = new CardsImpl(target.getTargets());
player.revealCards(source, cards, game);
player.moveCards(cards, Zone.HAND, source, game);
player.shuffleLibrary(source, game);
return true;
}
}
class AlpineHoundmasterTarget extends TargetCardInLibrary {
private static final FilterCard filter
= new FilterCard("card named Alpine Watchdog and/or a card named Igneous Cur");
static {
filter.add(Predicates.or(
new NamePredicate("Alpine Watchdog"),
new NamePredicate("Igneous Cur")
));
}
AlpineHoundmasterTarget() {
super(0, 2, filter);
}
private AlpineHoundmasterTarget(final AlpineHoundmasterTarget target) {
super(target);
}
@Override
public AlpineHoundmasterTarget copy() {
return new AlpineHoundmasterTarget(this);
}
@Override
public boolean canTarget(UUID controllerId, UUID id, Ability source, Game game) {
if (!super.canTarget(controllerId, id, source, game)) {
return false;
}
Card card = game.getCard(id);
if (card == null) {
return false;
}
return this.getTargets()
.stream()
.map(game::getCard)
.map(MageObject::getName)
.noneMatch(card.getName()::equals);
}
}

View file

@ -1,17 +1,14 @@
package mage.cards.b;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.*;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.abilities.keyword.FlyingAbility;
import mage.constants.CardType;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.StaticFilters;
@ -21,11 +18,13 @@ import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetCardWithDifferentNameInLibrary;
import mage.target.common.TargetOpponent;
import mage.util.CardUtil;
import java.util.Set;
import java.util.UUID;
/**
*
* @author weirddan455
*/
public final class BurningRuneDemon extends CardImpl {
@ -60,6 +59,13 @@ public final class BurningRuneDemon extends CardImpl {
class BurningRuneDemonEffect extends OneShotEffect {
private static final FilterCard filter
= new FilterCard("cards not named Burning-Rune Demon that have different names");
static {
filter.add(Predicates.not(new NamePredicate("Burning-Rune Demon")));
}
public BurningRuneDemonEffect() {
super(Outcome.Benefit);
staticText = "search your library for exactly two cards "
@ -81,7 +87,7 @@ class BurningRuneDemonEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
TargetCardInLibrary targetCardInLibrary = new BurningRuneDemonTarget();
TargetCardInLibrary targetCardInLibrary = new TargetCardWithDifferentNameInLibrary(2, 2, filter);
if (controller.searchLibrary(targetCardInLibrary, source, game)) {
Cards cards = new CardsImpl(targetCardInLibrary.getTargets());
if (!cards.isEmpty()) {
@ -115,41 +121,3 @@ class BurningRuneDemonEffect extends OneShotEffect {
return false;
}
}
class BurningRuneDemonTarget extends TargetCardInLibrary {
private static final FilterCard filter
= new FilterCard("cards not named Burning-Rune Demon that have different names");
static {
filter.add(Predicates.not(new NamePredicate("Burning-Rune Demon")));
}
public BurningRuneDemonTarget() {
super(2, filter);
}
private BurningRuneDemonTarget(final BurningRuneDemonTarget target) {
super(target);
}
@Override
public BurningRuneDemonTarget copy() {
return new BurningRuneDemonTarget(this);
}
@Override
public boolean canTarget(UUID playerId, UUID id, Ability source, Game game) {
if (!super.canTarget(playerId, id, source, game)) {
return false;
}
Card card = game.getCard(id);
return card != null
&& this.getTargets()
.stream()
.map(game::getCard)
.filter(Objects::nonNull)
.map(Card::getName)
.noneMatch(n -> CardUtil.haveSameNames(card, n, game));
}
}

View file

@ -1,20 +1,14 @@
package mage.cards.d;
import mage.abilities.Ability;
import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.filter.FilterCard;
import mage.filter.common.FilterCreatureCard;
import mage.game.Game;
import mage.target.common.TargetCardInLibrary;
import mage.util.CardUtil;
import mage.target.common.TargetCardWithDifferentNameInLibrary;
import java.util.Objects;
import java.util.UUID;
/**
@ -22,11 +16,20 @@ import java.util.UUID;
*/
public final class DeathbellowWarCry extends CardImpl {
private static final FilterCard minotaurFilter
= new FilterCreatureCard("Minotaur creature cards with different names");
static {
minotaurFilter.add(SubType.MINOTAUR.getPredicate());
}
public DeathbellowWarCry(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{5}{R}{R}{R}");
// Search your library for up to four Minotaur creature cards with different names, put them onto the battlefield, then shuffle your library.
this.getSpellAbility().addEffect(new SearchLibraryPutInPlayEffect(new DeathbellowWarCryTarget()));
this.getSpellAbility().addEffect(new SearchLibraryPutInPlayEffect(
new TargetCardWithDifferentNameInLibrary(0, 4, minotaurFilter)
));
}
private DeathbellowWarCry(final DeathbellowWarCry card) {
@ -38,40 +41,3 @@ public final class DeathbellowWarCry extends CardImpl {
return new DeathbellowWarCry(this);
}
}
class DeathbellowWarCryTarget extends TargetCardInLibrary {
private static final FilterCard minotaurFilter
= new FilterCreatureCard("Minotaur creature cards with different names");
static {
minotaurFilter.add(SubType.MINOTAUR.getPredicate());
}
DeathbellowWarCryTarget() {
super(0, 4, minotaurFilter);
}
private DeathbellowWarCryTarget(final DeathbellowWarCryTarget target) {
super(target);
}
@Override
public DeathbellowWarCryTarget copy() {
return new DeathbellowWarCryTarget(this);
}
@Override
public boolean canTarget(UUID playerId, UUID id, Ability source, Cards cards, Game game) {
Card card = cards.get(id, game);
return card != null
&& filter.match(card, playerId, game)
&& this
.getTargets()
.stream()
.map(game::getCard)
.filter(Objects::nonNull)
.map(Card::getName)
.noneMatch(n -> CardUtil.haveSameNames(card, n, game));
}
}

View file

@ -1,6 +1,5 @@
package mage.cards.e;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileSpellEffect;
@ -18,6 +17,7 @@ import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetCardInYourGraveyard;
import mage.target.common.TargetCardWithDifferentNameInLibrary;
import mage.target.common.TargetOpponent;
import mage.util.CardUtil;
@ -28,7 +28,6 @@ import java.util.UUID;
import java.util.stream.Collectors;
/**
*
* @author htrajan
*/
public final class EcologicalAppreciation extends CardImpl {
@ -55,7 +54,9 @@ class EcologicalAppreciationEffect extends OneShotEffect {
EcologicalAppreciationEffect() {
super(Outcome.Benefit);
staticText = "search your library and graveyard for up to four creature cards with different names that each have mana value X or less and reveal them. An opponent chooses two of those cards. Shuffle the chosen cards into your library and put the rest onto the battlefield";
staticText = "search your library and graveyard for up to four creature cards with different names " +
"that each have mana value X or less and reveal them. An opponent chooses two of those cards. " +
"Shuffle the chosen cards into your library and put the rest onto the battlefield";
}
private EcologicalAppreciationEffect(final EcologicalAppreciationEffect effect) {
@ -76,85 +77,69 @@ class EcologicalAppreciationEffect extends OneShotEffect {
int xValue = source.getManaCostsToPay().getX();
FilterCard filter = new FilterCreatureCard();
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, xValue + 1));
TargetCard targetCardsInLibrary = new TargetCardInLibrary(0, 4, filter) {
@Override
public boolean canTarget(UUID playerId, UUID id, Ability source, Game game) {
if (!super.canTarget(playerId, id, source, game)) {
return false;
}
Card card = game.getCard(id);
Set<Card> disallowedCards = this.getTargets().stream()
.map(game::getCard)
.collect(Collectors.toSet());
return isValidTarget(card, disallowedCards);
}
};
TargetCardInLibrary targetCardsInLibrary = new TargetCardWithDifferentNameInLibrary(0, 4, filter);
targetCardsInLibrary.setNotTarget(true);
targetCardsInLibrary.withChooseHint("Step 1 of 2: Search library");
player.choose(Outcome.PutCreatureInPlay, new CardsImpl(player.getLibrary().getCards(game)), targetCardsInLibrary, game);
player.searchLibrary(targetCardsInLibrary, source, game);
Cards cards = new CardsImpl(targetCardsInLibrary.getTargets());
cards.retainZone(Zone.LIBRARY, game);
boolean status = !cards.isEmpty();
if (status) {
int remainingCards = 4 - cards.size();
if (remainingCards > 0) {
TargetCard targetCardsInGY = new TargetCardInYourGraveyard(0, remainingCards, filter) {
@Override
public boolean canTarget(UUID playerId, UUID id, Ability source, Game game) {
if (!super.canTarget(playerId, id, source, game)) {
return false;
}
Card card = game.getCard(id);
Set<Card> disallowedCards = this.getTargets().stream()
int remainingCards = 4 - cards.size();
if (remainingCards > 0) {
TargetCard targetCardsInGY = new TargetCardInYourGraveyard(0, remainingCards, filter) {
@Override
public boolean canTarget(UUID playerId, UUID id, Ability source, Game game) {
if (!super.canTarget(playerId, id, source, game)) {
return false;
}
Card card = game.getCard(id);
Set<Card> disallowedCards = this.getTargets().stream()
.map(game::getCard)
.collect(Collectors.toSet());
Set<Card> checkList = new HashSet<>();
checkList.addAll(disallowedCards);
checkList.addAll(cards.getCards(game));
return isValidTarget(card, checkList);
}
};
targetCardsInGY.setNotTarget(true);
targetCardsInGY.withChooseHint("Step 2 of 2: Search graveyard");
player.choose(Outcome.PutCreatureInPlay, new CardsImpl(player.getGraveyard().getCards(game)), targetCardsInGY, game);
cards.addAll(targetCardsInGY.getTargets());
}
Set<Card> checkList = new HashSet<>();
checkList.addAll(disallowedCards);
checkList.addAll(cards.getCards(game));
return isValidTarget(card, checkList);
}
};
targetCardsInGY.setNotTarget(true);
targetCardsInGY.withChooseHint("Step 2 of 2: Search graveyard");
player.choose(Outcome.PutCreatureInPlay, player.getGraveyard(), targetCardsInGY, game);
cards.addAll(targetCardsInGY.getTargets());
cards.removeIf(uuid -> {
Zone zone = game.getState().getZone(uuid);
return zone != Zone.GRAVEYARD && zone != Zone.LIBRARY;
});
}
TargetOpponent targetOpponent = new TargetOpponent();
targetOpponent.setNotTarget(true);
player.choose(outcome, targetOpponent, source.getSourceId(), game);
Player opponent = game.getPlayer(targetOpponent.getFirstTarget());
TargetOpponent targetOpponent = new TargetOpponent();
targetOpponent.setNotTarget(true);
player.choose(outcome, targetOpponent, source.getSourceId(), game);
Player opponent = game.getPlayer(targetOpponent.getFirstTarget());
if (opponent == null) {
status = false;
}
if (status) {
TargetCard chosenCards = new TargetCard(2, Zone.ALL, StaticFilters.FILTER_CARD);
chosenCards.setNotTarget(true);
opponent.choose(outcome, cards, chosenCards, game);
Cards toShuffle = new CardsImpl(chosenCards.getTargets().stream()
if (opponent != null) {
TargetCard chosenCards = new TargetCard(2, Zone.ALL, StaticFilters.FILTER_CARD);
chosenCards.setNotTarget(true);
opponent.choose(outcome, cards, chosenCards, game);
Cards toShuffle = new CardsImpl(chosenCards.getTargets().stream()
.map(game::getCard)
.collect(Collectors.toList()));
player.putCardsOnTopOfLibrary(toShuffle, game, source, false);
cards.removeAll(toShuffle);
player.putCardsOnTopOfLibrary(toShuffle, game, source, false);
cards.removeAll(toShuffle);
player.moveCards(cards, Zone.BATTLEFIELD, source, game);
}
player.moveCards(cards, Zone.BATTLEFIELD, source, game);
}
player.shuffleLibrary(source, game);
return status;
return true;
}
private boolean isValidTarget(Card target, Set<Card> disallowedCards) {
return target != null &&
disallowedCards.stream()
return target != null
&& disallowedCards.stream()
.filter(Objects::nonNull)
.map(MageObject::getName)
.noneMatch(name -> CardUtil.haveSameNames(name, target.getName()));
.noneMatch(card -> CardUtil.haveSameNames(card, target));
}
}

View file

@ -1,6 +1,5 @@
package mage.cards.e;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ExileSpellEffect;
@ -15,10 +14,11 @@ import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCardInExile;
import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetCardWithDifferentNameInLibrary;
import mage.target.common.TargetOpponent;
import mage.util.CardUtil;
import java.util.UUID;
import mage.ApprovingObject;
/**
* @author TheElk801
@ -45,6 +45,13 @@ public final class EmergentUltimatum extends CardImpl {
class EmergentUltimatumEffect extends OneShotEffect {
private static final FilterCard filter
= new FilterCard("monocolored cards with different names");
static {
filter.add(MonocoloredPredicate.instance);
}
EmergentUltimatumEffect() {
super(Outcome.Benefit);
staticText = "Search your library for up to three monocolored cards with different names and exile them. " +
@ -67,7 +74,7 @@ class EmergentUltimatumEffect extends OneShotEffect {
if (player == null) {
return false;
}
TargetCardInLibrary targetCardInLibrary = new EmergentUltimatumTarget();
TargetCardInLibrary targetCardInLibrary = new TargetCardWithDifferentNameInLibrary(0, 3, filter);
targetCardInLibrary.setNotTarget(true);
boolean searched = player.searchLibrary(targetCardInLibrary, source, game);
Cards cards = new CardsImpl(targetCardInLibrary.getTargets());
@ -97,67 +104,7 @@ class EmergentUltimatumEffect extends OneShotEffect {
player.shuffleLibrary(source, game);
cards.remove(toShuffle);
}
while (!cards.isEmpty()) {
if (!player.chooseUse(Outcome.PlayForFree, "Cast an exiled card without paying its mana cost?", source, game)) {
break;
}
targetCardInExile.clearChosen();
if (!player.choose(Outcome.PlayForFree, cards, targetCardInExile, game)) {
continue;
}
Card card = game.getCard(targetCardInExile.getFirstTarget());
if (card == null) {
continue;
}
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE);
Boolean cardWasCast = player.cast(player.chooseAbilityForCast(card, game, true),
game, true, new ApprovingObject(source, game));
game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), null);
cards.remove(card); // remove on non cast too (infinite freeze fix)
if (cardWasCast) {
cards.remove(card);
} else {
game.informPlayer(player, "You're not able to cast "
+ card.getIdName() + " or you canceled the casting.");
}
}
CardUtil.castMultipleWithAttributeForFree(player, source, game, cards, StaticFilters.FILTER_CARD);
return true;
}
}
class EmergentUltimatumTarget extends TargetCardInLibrary {
private static final FilterCard filter
= new FilterCard("monocolored cards with different names");
static {
filter.add(MonocoloredPredicate.instance);
}
EmergentUltimatumTarget() {
super(0, 3, filter);
}
private EmergentUltimatumTarget(final EmergentUltimatumTarget target) {
super(target);
}
@Override
public EmergentUltimatumTarget copy() {
return new EmergentUltimatumTarget(this);
}
@Override
public boolean canTarget(UUID playerId, UUID id, Ability source, Game game) {
if (!super.canTarget(playerId, id, source, game)) {
return false;
}
Card card = game.getCard(id);
return card != null
&& this.getTargets()
.stream()
.map(game::getCard)
.map(MageObject::getName)
.noneMatch(card.getName()::equals);
}
}

View file

@ -2,7 +2,10 @@ package mage.cards.g;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.*;
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;
@ -11,10 +14,9 @@ import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetCardWithDifferentNameInLibrary;
import mage.target.common.TargetOpponent;
import mage.util.CardUtil;
import java.util.Objects;
import java.util.UUID;
/**
@ -42,7 +44,8 @@ public final class GiftsUngiven extends CardImpl {
class GiftsUngivenEffect extends OneShotEffect {
private static final FilterCard filter = new FilterCard("cards to put in graveyard");
private static final FilterCard filter = new FilterCard("cards with different names");
private static final FilterCard filter2 = new FilterCard("cards to put in graveyard");
public GiftsUngivenEffect() {
super(Outcome.DrawCard);
@ -67,13 +70,10 @@ class GiftsUngivenEffect extends OneShotEffect {
if (player == null || opponent == null) {
return false;
}
GiftsUngivenTarget target = new GiftsUngivenTarget();
TargetCardInLibrary target = new TargetCardWithDifferentNameInLibrary(0, 4, filter);
player.searchLibrary(target, source, game);
Cards cards = new CardsImpl();
target.getTargets()
.stream()
.map(uuid -> player.getLibrary().getCard(uuid, game))
.forEach(cards::add);
Cards cards = new CardsImpl(target.getTargets());
cards.retainZone(Zone.LIBRARY, game);
if (cards.isEmpty()) {
player.shuffleLibrary(source, game);
}
@ -82,7 +82,7 @@ class GiftsUngivenEffect extends OneShotEffect {
if (cards.size() > 2) {
Cards cardsToKeep = new CardsImpl();
cardsToKeep.addAll(cards);
TargetCard targetDiscard = new TargetCard(2, Zone.LIBRARY, filter);
TargetCard targetDiscard = new TargetCard(2, Zone.LIBRARY, filter2);
if (opponent.choose(Outcome.Discard, cards, targetDiscard, game)) {
cardsToKeep.removeIf(targetDiscard.getTargets()::contains);
cards.removeAll(cardsToKeep);
@ -95,36 +95,3 @@ class GiftsUngivenEffect extends OneShotEffect {
return true;
}
}
class GiftsUngivenTarget extends TargetCardInLibrary {
private static final FilterCard filter = new FilterCard("cards with different names");
GiftsUngivenTarget() {
super(0, 4, filter);
}
private GiftsUngivenTarget(final GiftsUngivenTarget target) {
super(target);
}
@Override
public GiftsUngivenTarget copy() {
return new GiftsUngivenTarget(this);
}
@Override
public boolean canTarget(UUID playerId, UUID id, Ability source, Cards cards, Game game) {
if (!super.canTarget(playerId, id, source, cards, game)) {
return false;
}
Card card = cards.get(id, game);
return card != null
&& this
.getTargets()
.stream()
.map(game::getCard)
.filter(Objects::nonNull)
.noneMatch(c -> CardUtil.haveSameNames(c, card));
}
}

View file

@ -1,9 +1,11 @@
package mage.cards.r;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.*;
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;
@ -11,12 +13,11 @@ import mage.filter.FilterCard;
import mage.filter.common.FilterLandCard;
import mage.game.Game;
import mage.players.Player;
import mage.target.Target;
import mage.target.TargetCard;
import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetCardWithDifferentNameInLibrary;
import mage.target.common.TargetOpponent;
import java.util.Set;
import java.util.UUID;
/**
@ -43,9 +44,14 @@ public final class RealmsUncharted extends CardImpl {
class RealmsUnchartedEffect extends OneShotEffect {
private static final FilterCard filter = new FilterLandCard("land cards with different names");
private static final FilterCard filter2 = new FilterCard("cards to put in graveyard");
public RealmsUnchartedEffect() {
super(Outcome.DrawCard);
this.staticText = "Search your library for up to four land cards with different names and reveal them. An opponent chooses two of those cards. Put the chosen cards into your graveyard and the rest into your hand. Then shuffle";
this.staticText = "Search your library for up to four land cards with different names and reveal them. " +
"An opponent chooses two of those cards. Put the chosen cards into your graveyard " +
"and the rest into your hand. Then shuffle";
}
public RealmsUnchartedEffect(final RealmsUnchartedEffect effect) {
@ -59,81 +65,36 @@ class RealmsUnchartedEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = game.getObject(source.getSourceId());
if (controller == null || sourceObject == null) {
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
RealmsUnchartedTarget target = new RealmsUnchartedTarget();
if (controller.searchLibrary(target, source, game)) {
if (!target.getTargets().isEmpty()) {
Cards cards = new CardsImpl();
for (UUID cardId : target.getTargets()) {
Card card = controller.getLibrary().getCard(cardId, game);
if (card != null) {
cards.add(card);
}
}
controller.revealCards(sourceObject.getName(), cards, game);
CardsImpl cardsToKeep = new CardsImpl();
if (cards.size() > 2) {
cardsToKeep.addAll(cards);
Player opponent;
Set<UUID> opponents = game.getOpponents(controller.getId());
if (opponents.size() == 1) {
opponent = game.getPlayer(opponents.iterator().next());
} else {
Target targetOpponent = new TargetOpponent(true);
controller.chooseTarget(Outcome.Detriment, targetOpponent, source, game);
opponent = game.getPlayer(targetOpponent.getFirstTarget());
}
TargetCard targetDiscard = new TargetCard(2, Zone.LIBRARY, new FilterCard("cards to put in graveyard"));
if (opponent != null && opponent.choose(Outcome.Discard, cards, targetDiscard, game)) {
cardsToKeep.removeAll(targetDiscard.getTargets());
cards.removeAll(cardsToKeep);
}
}
controller.moveCards(cards, Zone.GRAVEYARD, source, game);
controller.moveCards(cardsToKeep, Zone.HAND, source, game);
}
controller.shuffleLibrary(source, game);
return true;
TargetCardInLibrary target = new TargetCardWithDifferentNameInLibrary(0, 4, filter);
player.searchLibrary(target, source, game);
Cards cards = new CardsImpl(target.getTargets());
cards.retainZone(Zone.LIBRARY, game);
if (cards.isEmpty()) {
player.shuffleLibrary(source, game);
}
controller.shuffleLibrary(source, game);
return false;
}
}
class RealmsUnchartedTarget extends TargetCardInLibrary {
public RealmsUnchartedTarget() {
super(0, 4, new FilterLandCard("land cards with different names"));
}
public RealmsUnchartedTarget(final RealmsUnchartedTarget target) {
super(target);
}
@Override
public RealmsUnchartedTarget copy() {
return new RealmsUnchartedTarget(this);
}
@Override
public boolean canTarget(UUID playerId, UUID id, Ability source, Cards cards, Game game) {
Card card = cards.get(id, game);
if (card != null) {
for (UUID targetId : this.getTargets()) {
Card iCard = game.getCard(targetId);
if (iCard != null && iCard.getName().equals(card.getName())) {
return false;
}
}
return filter.match(card, playerId, game);
}
return false;
player.revealCards(source, cards, game);
if (cards.size() > 2) {
TargetOpponent targetOpponent = new TargetOpponent();
targetOpponent.setNotTarget(true);
player.choose(outcome, target, source.getSourceId(), game);
Player opponent = game.getPlayer(targetOpponent.getFirstTarget());
Cards cardsToKeep = new CardsImpl();
cardsToKeep.addAll(cards);
TargetCard targetDiscard = new TargetCard(2, Zone.LIBRARY, filter2);
if (opponent.choose(Outcome.Discard, cards, targetDiscard, game)) {
cardsToKeep.removeIf(targetDiscard.getTargets()::contains);
cards.removeAll(cardsToKeep);
}
player.moveCards(cardsToKeep, Zone.HAND, source, game);
}
player.moveCards(cards, Zone.GRAVEYARD, source, game);
player.shuffleLibrary(source, game);
return true;
}
}

View file

@ -11,16 +11,15 @@ import mage.abilities.effects.common.DamagePlayersEffect;
import mage.abilities.effects.common.ExileTargetEffect;
import mage.abilities.effects.common.search.SearchLibraryPutInPlayEffect;
import mage.abilities.effects.keyword.ScryEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.constants.*;
import mage.filter.FilterCard;
import mage.filter.StaticFilters;
import mage.filter.common.FilterArtifactCard;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetCardWithDifferentNameInLibrary;
import mage.target.common.TargetControlledPermanent;
import mage.target.targetpointer.FixedTarget;
@ -31,6 +30,8 @@ import java.util.UUID;
*/
public final class SaheeliRai extends CardImpl {
private static final FilterCard filter = new FilterArtifactCard("artifact cards with different names");
public SaheeliRai(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{1}{U}{R}");
this.addSuperType(SuperType.LEGENDARY);
@ -51,7 +52,7 @@ public final class SaheeliRai extends CardImpl {
this.addAbility(ability);
// -7: Search your library for up to three artifact cards with different names, put them onto the battlefield, then shuffle your library.
this.addAbility(new LoyaltyAbility(new SearchLibraryPutInPlayEffect(new SaheeliRaiTarget()), -7));
this.addAbility(new LoyaltyAbility(new SearchLibraryPutInPlayEffect(new TargetCardWithDifferentNameInLibrary(0, 3, filter)), -7));
}
private SaheeliRai(final SaheeliRai card) {
@ -98,34 +99,3 @@ class SaheeliRaiCreateTokenEffect extends OneShotEffect {
return false;
}
}
class SaheeliRaiTarget extends TargetCardInLibrary {
SaheeliRaiTarget() {
super(0, 3, new FilterArtifactCard("artifact cards with different names"));
}
SaheeliRaiTarget(final SaheeliRaiTarget target) {
super(target);
}
@Override
public SaheeliRaiTarget copy() {
return new SaheeliRaiTarget(this);
}
@Override
public boolean canTarget(UUID playerId, UUID id, Ability source, Cards cards, Game game) {
Card card = cards.get(id, game);
if (card != null) {
for (UUID targetId : this.getTargets()) {
Card iCard = game.getCard(targetId);
if (iCard != null && iCard.getName().equals(card.getName())) {
return false;
}
}
return filter.match(card, playerId, game);
}
return false;
}
}

View file

@ -1,18 +1,13 @@
package mage.cards.s;
import mage.abilities.Ability;
import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.constants.CardType;
import mage.filter.FilterCard;
import mage.filter.common.FilterCreatureCard;
import mage.game.Game;
import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetCardWithDifferentNameInLibrary;
import java.util.Objects;
import java.util.UUID;
/**
@ -20,12 +15,14 @@ import java.util.UUID;
*/
public final class SharedSummons extends CardImpl {
private static final FilterCard filter = new FilterCreatureCard("creature cards with different names");
public SharedSummons(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{G}{G}");
// Search your library for up to two creature cards with different names, reveal them, put them into your hand, then shuffle your library.
this.getSpellAbility().addEffect(new SearchLibraryPutInHandEffect(
new SharedSummonsTarget(), true, true
new TargetCardWithDifferentNameInLibrary(0, 2, filter), true, true
));
}
@ -38,40 +35,3 @@ public final class SharedSummons extends CardImpl {
return new SharedSummons(this);
}
}
class SharedSummonsTarget extends TargetCardInLibrary {
private static final FilterCard filter2 = new FilterCreatureCard("creature cards with different names");
SharedSummonsTarget() {
super(0, 2, filter2);
}
private SharedSummonsTarget(final SharedSummonsTarget target) {
super(target);
}
@Override
public SharedSummonsTarget copy() {
return new SharedSummonsTarget(this);
}
@Override
public boolean canTarget(UUID playerId, UUID id, Ability source, Cards cards, Game game) {
Card card = cards.get(id, game);
if (card == null || !card.isCreature(game)) {
return false;
}
if (!filter.match(card, playerId, game)) {
return false;
}
return this
.getTargets()
.stream()
.map(game::getCard)
.filter(Objects::nonNull)
.noneMatch(c -> c != null && c.getName().equals(card.getName()));
}
}

View file

@ -1,16 +1,12 @@
package mage.cards.t;
import mage.abilities.Ability;
import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetCardWithDifferentNameInLibrary;
import java.util.UUID;
@ -19,12 +15,20 @@ import java.util.UUID;
*/
public final class ThreeDreams extends CardImpl {
private static final FilterCard aurafilter = new FilterCard("Aura cards with different names");
static {
aurafilter.add(SubType.AURA.getPredicate());
}
public ThreeDreams(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{W}");
// Search your library for up to three Aura cards with different names, reveal them, and put them into your hand. Then shuffle your library.
this.getSpellAbility().addEffect(new SearchLibraryPutInHandEffect(new ThreeDreamsTarget(), true, true));
this.getSpellAbility().addEffect(new SearchLibraryPutInHandEffect(
new TargetCardWithDifferentNameInLibrary(0, 3, aurafilter),
true, true
));
}
private ThreeDreams(final ThreeDreams card) {
@ -36,41 +40,3 @@ public final class ThreeDreams extends CardImpl {
return new ThreeDreams(this);
}
}
class ThreeDreamsTarget extends TargetCardInLibrary {
private static final FilterCard aurafilter = new FilterCard("Aura cards with different names");
static {
aurafilter.add(SubType.AURA.getPredicate());
}
public ThreeDreamsTarget() {
super(0, 3, aurafilter.copy());
}
public ThreeDreamsTarget(final ThreeDreamsTarget target) {
super(target);
}
@Override
public ThreeDreamsTarget copy() {
return new ThreeDreamsTarget(this);
}
@Override
public boolean canTarget(UUID playerId, UUID id, Ability source, Cards cards, Game game) {
Card card = cards.get(id, game);
if (card != null) {
// check if card with that name was selected before
for (UUID targetId : this.getTargets()) {
Card iCard = game.getCard(targetId);
if (iCard != null && iCard.getName().equals(card.getName())) {
return false;
}
}
return filter.match(card, playerId, game);
}
return false;
}
}

View file

@ -1,16 +1,13 @@
package mage.cards.t;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.condition.common.CastFromEverywhereSourceCondition;
import mage.abilities.decorator.ConditionalInterveningIfTriggeredAbility;
import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.SuperType;
@ -18,11 +15,8 @@ import mage.filter.FilterCard;
import mage.filter.common.FilterCreatureCard;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.mageobject.NamePredicate;
import mage.game.Game;
import mage.target.common.TargetCardInLibrary;
import mage.util.CardUtil;
import mage.target.common.TargetCardWithDifferentNameInLibrary;
import java.util.Objects;
import java.util.UUID;
/**
@ -30,6 +24,14 @@ import java.util.UUID;
*/
public final class Tiamat extends CardImpl {
private static final FilterCard filter
= new FilterCreatureCard("Dragon cards not named Tiamat that each have different names");
static {
filter.add(SubType.DRAGON.getPredicate());
filter.add(Predicates.not(new NamePredicate("Tiamat")));
}
public Tiamat(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{W}{U}{B}{R}{G}");
@ -44,8 +46,9 @@ public final class Tiamat extends CardImpl {
// When Tiamat enters the battlefield, if you cast it, search your library for up to five Dragon cards named Tiama that each have different names, reveal them, put them into your hand, then shuffle.
this.addAbility(new ConditionalInterveningIfTriggeredAbility(new EntersBattlefieldTriggeredAbility(
new SearchLibraryPutInHandEffect(new TiamatTarget(), true, true)),
CastFromEverywhereSourceCondition.instance, "When {this} enters the battlefield, " +
new SearchLibraryPutInHandEffect(
new TargetCardWithDifferentNameInLibrary(0, 5, filter), true, true
)), CastFromEverywhereSourceCondition.instance, "When {this} enters the battlefield, " +
"if you cast it, search your library for up to five Dragon cards not named Tiamat " +
"that each have different names, reveal them, put them into your hand, then shuffle."
));
@ -60,41 +63,3 @@ public final class Tiamat extends CardImpl {
return new Tiamat(this);
}
}
class TiamatTarget extends TargetCardInLibrary {
private static final FilterCard filter
= new FilterCreatureCard("Dragon cards not named Tiamat that each have different names");
static {
filter.add(SubType.DRAGON.getPredicate());
filter.add(Predicates.not(new NamePredicate("Tiamat")));
}
TiamatTarget() {
super(0, 5, filter);
}
private TiamatTarget(final TiamatTarget target) {
super(target);
}
@Override
public TiamatTarget copy() {
return new TiamatTarget(this);
}
@Override
public boolean canTarget(UUID playerId, UUID id, Ability source, Cards cards, Game game) {
Card card = cards.get(id, game);
return card != null
&& filter.match(card, playerId, game)
&& this
.getTargets()
.stream()
.map(game::getCard)
.filter(Objects::nonNull)
.map(Card::getName)
.noneMatch(n -> CardUtil.haveSameNames(card, n, game));
}
}

View file

@ -3,17 +3,16 @@ package mage.cards.u;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.constants.CardType;
import mage.constants.ComparisonType;
import mage.constants.Outcome;
import mage.filter.FilterCard;
import mage.filter.common.FilterCreatureCard;
import mage.filter.predicate.mageobject.ManaValuePredicate;
import mage.game.Game;
import mage.target.common.TargetCardInLibrary;
import mage.util.CardUtil;
import mage.target.common.TargetCardWithDifferentNameInLibrary;
import java.util.UUID;
@ -41,12 +40,6 @@ public final class UncageTheMenagerie extends CardImpl {
class UncageTheMenagerieEffect extends OneShotEffect {
private static final FilterCard filter = new FilterCard("creature");
static {
filter.add(CardType.CREATURE.getPredicate());
}
public UncageTheMenagerieEffect() {
super(Outcome.DrawCard);
this.staticText = "Search your library for up to X creature cards with different names " +
@ -64,42 +57,11 @@ class UncageTheMenagerieEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
return new SearchLibraryPutInHandEffect(new UncageTheMenagerieTarget(
source.getManaCostsToPay().getX()), true, true
int xValue = source.getManaCostsToPay().getX();
FilterCard filter = new FilterCreatureCard(xValue + " creature cards with different names that each have mana value " + xValue);
filter.add(new ManaValuePredicate(ComparisonType.EQUAL_TO, xValue));
return new SearchLibraryPutInHandEffect(
new TargetCardWithDifferentNameInLibrary(0, xValue, filter), true, true
).apply(game, source);
}
}
class UncageTheMenagerieTarget extends TargetCardInLibrary {
private final int xValue;
public UncageTheMenagerieTarget(int xValue) {
super(0, xValue, new FilterCreatureCard(xValue + " creature cards with different names with mana value " + xValue));
this.xValue = xValue;
}
public UncageTheMenagerieTarget(final UncageTheMenagerieTarget target) {
super(target);
this.xValue = target.xValue;
}
@Override
public UncageTheMenagerieTarget copy() {
return new UncageTheMenagerieTarget(this);
}
@Override
public boolean canTarget(UUID playerId, UUID id, Ability source, Cards cards, Game game) {
if (!super.canTarget(playerId, id, source, cards, game)) {
return false;
}
Card card = cards.get(id, game);
return card.getManaValue() == xValue
&& this
.getTargets()
.stream()
.map(game::getCard)
.noneMatch(c -> CardUtil.haveSameNames(c, card));
}
}

View file

@ -0,0 +1,41 @@
package mage.target.common;
import mage.abilities.Ability;
import mage.cards.Card;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.util.CardUtil;
import java.util.UUID;
/**
* @author TheElk801
*/
public class TargetCardWithDifferentNameInLibrary extends TargetCardInLibrary {
public TargetCardWithDifferentNameInLibrary(int minNumTargets, int maxNumTargets, FilterCard filter) {
super(minNumTargets, maxNumTargets, filter);
}
protected TargetCardWithDifferentNameInLibrary(final TargetCardWithDifferentNameInLibrary target) {
super(target);
}
@Override
public TargetCardWithDifferentNameInLibrary copy() {
return new TargetCardWithDifferentNameInLibrary(this);
}
@Override
public boolean canTarget(UUID playerId, UUID id, Ability source, Game game) {
if (!super.canTarget(playerId, id, source, game)) {
return false;
}
Card card = game.getCard(id);
return card != null
&& this.getTargets()
.stream()
.map(game::getCard)
.noneMatch(c -> CardUtil.haveSameNames(c, card));
}
}