refactor: improved targets that find a [type1] card and/or a [type2] card (#11497)

This commit is contained in:
xenohedron 2023-12-01 10:26:30 -05:00 committed by GitHub
parent f3e310cfd3
commit 264b73355a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 212 additions and 459 deletions

View file

@ -6,16 +6,13 @@ import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.SacrificeSourceCost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.dynamicvalue.common.SubTypeAssignment;
import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect;
import mage.abilities.mana.WhiteManaAbility;
import mage.cards.*;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.filter.FilterCard;
import mage.filter.predicate.Predicates;
import mage.game.Game;
import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetCardAndOrCardInLibrary;
import java.util.UUID;
@ -35,9 +32,7 @@ public final class AxgardArmory extends CardImpl {
// {1}{R}{R}{W}, {T}: Sacrifice Axgard Armory: Search your library for an Aura card and/or Equipment card, reveal them, put them into your hand, then shuffle your library.
Ability ability = new SimpleActivatedAbility(
new SearchLibraryPutInHandEffect(new AxgardArmoryTarget(), true)
.setText("search your library for an Aura card and/or an Equipment card, reveal them, " +
"put them into your hand, then shuffle"),
new SearchLibraryPutInHandEffect(new TargetCardAndOrCardInLibrary(SubType.AURA, SubType.EQUIPMENT), true),
new ManaCostsImpl<>("{1}{R}{R}{W}")
);
ability.addCost(new TapSourceCost());
@ -54,49 +49,3 @@ public final class AxgardArmory extends CardImpl {
return new AxgardArmory(this);
}
}
class AxgardArmoryTarget extends TargetCardInLibrary {
private static final FilterCard filter
= new FilterCard("an Aura card and/or an Equipment card");
static {
filter.add(Predicates.or(
SubType.AURA.getPredicate(),
SubType.EQUIPMENT.getPredicate()
));
}
private static final SubTypeAssignment subTypeAssigner
= new SubTypeAssignment(SubType.AURA, SubType.EQUIPMENT);
AxgardArmoryTarget() {
super(0, 2, filter);
}
private AxgardArmoryTarget(final AxgardArmoryTarget target) {
super(target);
}
@Override
public AxgardArmoryTarget copy() {
return new AxgardArmoryTarget(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);
if (card == null) {
return false;
}
if (this.getTargets().isEmpty()) {
return true;
}
Cards cards = new CardsImpl(this.getTargets());
cards.add(card);
return subTypeAssigner.getRoleCount(cards, game) >= cards.size();
}
}

View file

@ -1,11 +1,7 @@
package mage.cards.b;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Cards;
@ -13,11 +9,12 @@ import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.common.FilterCreatureCard;
import mage.filter.common.FilterEnchantmentCard;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetCardAndOrCardInLibrary;
import java.util.UUID;
/**
*
@ -44,9 +41,11 @@ public final class BenefactionOfRhonas extends CardImpl {
class BenefactionOfRhonasEffect extends OneShotEffect {
public BenefactionOfRhonasEffect() {
BenefactionOfRhonasEffect() {
super(Outcome.DrawCard);
this.staticText = "Reveal the top five cards of your library. You may put a creature card and/or an enchantment card from among them into your hand. Put the rest into your graveyard";
this.staticText = "Reveal the top five cards of your library. " +
"You may put a creature card and/or an enchantment card from among them into your hand. " +
"Put the rest into your graveyard";
}
private BenefactionOfRhonasEffect(final BenefactionOfRhonasEffect effect) {
@ -60,52 +59,19 @@ class BenefactionOfRhonasEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = game.getObject(source);
if (sourceObject != null && controller != null) {
Cards cards = new CardsImpl(controller.getLibrary().getTopCards(game, 5));
boolean creatureCardFound = false;
boolean enchantmentCardFound = false;
for (UUID cardId : cards) {
Card card = game.getCard(cardId);
if (card != null) {
cards.add(card);
if (card.isCreature(game)) {
creatureCardFound = true;
}
if (card.isEnchantment(game)) {
enchantmentCardFound = true;
}
}
}
if (!cards.isEmpty()) {
controller.revealCards(sourceObject.getName(), cards, game);
if ((creatureCardFound || enchantmentCardFound)
&& controller.chooseUse(Outcome.DrawCard,
"Put a creature card and/or enchantment card into your hand?", source, game)) {
TargetCard target = new TargetCard(Zone.LIBRARY, new FilterCreatureCard("creature card to put into your hand"));
if (creatureCardFound && controller.chooseTarget(Outcome.DrawCard, cards, target, source, game)) {
Card card = cards.get(target.getFirstTarget(), game);
if (card != null) {
cards.remove(card);
controller.moveCards(card, Zone.HAND, source, game);
}
}
target = new TargetCard(Zone.LIBRARY, new FilterEnchantmentCard("enchantment card to put into your hand"));
if (enchantmentCardFound && controller.chooseTarget(Outcome.DrawCard, cards, target, source, game)) {
Card card = cards.get(target.getFirstTarget(), game);
if (card != null) {
cards.remove(card);
controller.moveCards(card, Zone.HAND, source, game);
}
}
}
}
controller.moveCards(cards, Zone.GRAVEYARD, source, game);
return true;
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
return false;
Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, 5));
player.revealCards(source, cards, game);
TargetCard target = new TargetCardAndOrCardInLibrary(CardType.CREATURE, CardType.ENCHANTMENT);
player.choose(outcome, cards, target, source, game);
Cards toHand = new CardsImpl();
toHand.addAll(target.getTargets());
player.moveCards(toHand, Zone.HAND, source, game);
cards.removeAll(toHand);
player.moveCards(cards, Zone.GRAVEYARD, source, game);
return true;
}
}

View file

@ -1,18 +1,15 @@
package mage.cards.g;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.common.CardTypeAssignment;
import mage.abilities.effects.OneShotEffect;
import mage.cards.*;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.predicate.Predicates;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetCardAndOrCardInLibrary;
import java.util.UUID;
@ -63,7 +60,7 @@ class GiftOfTheGargantuanEffect extends OneShotEffect {
return false;
}
Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, 4));
TargetCard target = new GiftOfTheGargantuanTarget();
TargetCard target = new TargetCardAndOrCardInLibrary(CardType.CREATURE, CardType.LAND);
player.choose(outcome, cards, target, source, game);
Cards toHand = new CardsImpl();
toHand.addAll(target.getTargets());
@ -74,49 +71,3 @@ class GiftOfTheGargantuanEffect extends OneShotEffect {
return true;
}
}
class GiftOfTheGargantuanTarget extends TargetCardInLibrary {
private static final FilterCard filter
= new FilterCard("a creature card and/or a land card");
static {
filter.add(Predicates.or(
CardType.CREATURE.getPredicate(),
CardType.LAND.getPredicate()
));
}
private static final CardTypeAssignment cardTypeAssigner
= new CardTypeAssignment(CardType.CREATURE, CardType.LAND);
GiftOfTheGargantuanTarget() {
super(0, 2, filter);
}
private GiftOfTheGargantuanTarget(final GiftOfTheGargantuanTarget target) {
super(target);
}
@Override
public GiftOfTheGargantuanTarget copy() {
return new GiftOfTheGargantuanTarget(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);
if (card == null) {
return false;
}
if (this.getTargets().isEmpty()) {
return true;
}
Cards cards = new CardsImpl(this.getTargets());
cards.add(card);
return cardTypeAssigner.getRoleCount(cards, game) >= cards.size();
}
}

View file

@ -1,18 +1,15 @@
package mage.cards.g;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.common.CardTypeAssignment;
import mage.abilities.effects.OneShotEffect;
import mage.cards.*;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.predicate.Predicates;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetCardAndOrCardInLibrary;
import java.util.UUID;
@ -66,7 +63,7 @@ class GreenSunsTwilightEffect extends OneShotEffect {
int xValue = source.getManaCostsToPay().getX();
Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, xValue + 1));
player.revealCards(source, cards, game);
TargetCard target = new GreenSunsTwilightTarget();
TargetCard target = new TargetCardAndOrCardInLibrary(CardType.CREATURE, CardType.LAND);
player.choose(outcome, cards, target, source, game);
Cards toMove = new CardsImpl(target.getTargets());
if (!toMove.isEmpty()) {
@ -81,49 +78,3 @@ class GreenSunsTwilightEffect extends OneShotEffect {
return true;
}
}
class GreenSunsTwilightTarget extends TargetCardInLibrary {
private static final FilterCard filter
= new FilterCard("a creature card and/or a land card");
static {
filter.add(Predicates.or(
CardType.CREATURE.getPredicate(),
CardType.LAND.getPredicate()
));
}
private static final CardTypeAssignment cardTypeAssigner
= new CardTypeAssignment(CardType.CREATURE, CardType.LAND);
GreenSunsTwilightTarget() {
super(0, 2, filter);
}
private GreenSunsTwilightTarget(final GreenSunsTwilightTarget target) {
super(target);
}
@Override
public GreenSunsTwilightTarget copy() {
return new GreenSunsTwilightTarget(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);
if (card == null) {
return false;
}
if (this.getTargets().isEmpty()) {
return true;
}
Cards cards = new CardsImpl(this.getTargets());
cards.add(card);
return cardTypeAssigner.getRoleCount(cards, game) >= cards.size();
}
}

View file

@ -1,18 +1,15 @@
package mage.cards.i;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.common.CardTypeAssignment;
import mage.abilities.effects.OneShotEffect;
import mage.cards.*;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.predicate.Predicates;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetCardAndOrCardInLibrary;
import java.util.UUID;
@ -25,7 +22,7 @@ public final class InThePresenceOfAges extends CardImpl {
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{G}");
// Reveal the top four cards of your library. You may put a creature card and/or a land card from among them into your hand. Put the rest into your graveyard.
this.getSpellAbility().addEffect(new InThePresenceOfAgeEffect());
this.getSpellAbility().addEffect(new InThePresenceOfAgesEffect());
}
private InThePresenceOfAges(final InThePresenceOfAges card) {
@ -38,22 +35,22 @@ public final class InThePresenceOfAges extends CardImpl {
}
}
class InThePresenceOfAgeEffect extends OneShotEffect {
class InThePresenceOfAgesEffect extends OneShotEffect {
InThePresenceOfAgeEffect() {
InThePresenceOfAgesEffect() {
super(Outcome.DrawCard);
this.staticText = "Reveal the top four cards of your library. "
+ "You may put a creature card and/or a land card from among them into your hand. "
+ "Put the rest into your graveyard";
}
private InThePresenceOfAgeEffect(final InThePresenceOfAgeEffect effect) {
private InThePresenceOfAgesEffect(final InThePresenceOfAgesEffect effect) {
super(effect);
}
@Override
public InThePresenceOfAgeEffect copy() {
return new InThePresenceOfAgeEffect(this);
public InThePresenceOfAgesEffect copy() {
return new InThePresenceOfAgesEffect(this);
}
@Override
@ -64,7 +61,7 @@ class InThePresenceOfAgeEffect extends OneShotEffect {
}
Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, 4));
player.revealCards(source, cards, game);
TargetCard target = new InThePresenceOfAgesTarget();
TargetCard target = new TargetCardAndOrCardInLibrary(CardType.CREATURE, CardType.LAND);
player.choose(outcome, cards, target, source, game);
Cards toHand = new CardsImpl();
toHand.addAll(target.getTargets());
@ -74,49 +71,3 @@ class InThePresenceOfAgeEffect extends OneShotEffect {
return true;
}
}
class InThePresenceOfAgesTarget extends TargetCardInLibrary {
private static final FilterCard filter
= new FilterCard("a creature card and/or a land card");
static {
filter.add(Predicates.or(
CardType.CREATURE.getPredicate(),
CardType.LAND.getPredicate()
));
}
private static final CardTypeAssignment cardTypeAssigner
= new CardTypeAssignment(CardType.CREATURE, CardType.LAND);
InThePresenceOfAgesTarget() {
super(0, 2, filter);
}
private InThePresenceOfAgesTarget(final InThePresenceOfAgesTarget target) {
super(target);
}
@Override
public InThePresenceOfAgesTarget copy() {
return new InThePresenceOfAgesTarget(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);
if (card == null) {
return false;
}
if (this.getTargets().isEmpty()) {
return true;
}
Cards cards = new CardsImpl(this.getTargets());
cards.add(card);
return cardTypeAssigner.getRoleCount(cards, game) >= cards.size();
}
}

View file

@ -1,20 +1,18 @@
package mage.cards.i;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.common.CardTypeAssignment;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.SwitchPowerToughnessTargetEffect;
import mage.abilities.effects.common.search.SearchLibraryPutInHandEffect;
import mage.cards.*;
import mage.cards.CardSetInfo;
import mage.cards.SplitCard;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SpellAbilityType;
import mage.filter.FilterCard;
import mage.filter.common.FilterInstantOrSorceryCard;
import mage.game.Game;
import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetCardAndOrCardInLibrary;
import mage.target.common.TargetCreaturePermanent;
import mage.target.targetpointer.FixedTarget;
@ -35,7 +33,8 @@ public final class InvertInvent extends SplitCard {
// Invent
// Search your library for an instant card and/or a sorcery card, reveal them, put them into your hand, then shuffle your library.
this.getRightHalfCard().getSpellAbility().addEffect(new SearchLibraryPutInHandEffect(new InventTarget(), true).setText("search your library for an instant card and/or a sorcery card, reveal them, put them into your hand, then shuffle"));
this.getRightHalfCard().getSpellAbility().addEffect(new SearchLibraryPutInHandEffect(
new TargetCardAndOrCardInLibrary(CardType.INSTANT, CardType.SORCERY), true));
}
private InvertInvent(final InvertInvent card) {
@ -75,41 +74,3 @@ class InvertEffect extends OneShotEffect {
return true;
}
}
class InventTarget extends TargetCardInLibrary {
private static final FilterCard filter
= new FilterInstantOrSorceryCard("an instant card and/or a sorcery card");
private static final CardTypeAssignment cardTypeAssigner
= new CardTypeAssignment(CardType.INSTANT, CardType.SORCERY);
InventTarget() {
super(0, 2, filter);
}
private InventTarget(final InventTarget target) {
super(target);
}
@Override
public InventTarget copy() {
return new InventTarget(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);
if (card == null) {
return false;
}
if (this.getTargets().isEmpty()) {
return true;
}
Cards cards = new CardsImpl(this.getTargets());
cards.add(card);
return cardTypeAssigner.getRoleCount(cards, game) >= cards.size();
}
}

View file

@ -1,6 +1,5 @@
package mage.cards.k;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.effects.OneShotEffect;
@ -8,10 +7,7 @@ import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.GetEmblemEffect;
import mage.cards.*;
import mage.constants.*;
import mage.filter.FilterCard;
import mage.filter.StaticFilters;
import mage.filter.common.FilterCreatureCard;
import mage.filter.common.FilterLandCard;
import mage.game.Game;
import mage.game.command.emblems.KioraMasterOfTheDepthsEmblem;
import mage.game.permanent.token.OctopusToken;
@ -19,7 +15,7 @@ import mage.players.Player;
import mage.target.Target;
import mage.target.TargetCard;
import mage.target.TargetPermanent;
import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetCardAndOrCardInLibrary;
import java.util.Collection;
import java.util.Objects;
@ -94,11 +90,6 @@ class KioraUntapEffect extends OneShotEffect {
class KioraRevealEffect extends OneShotEffect {
private static final FilterCard creatureFilter
= new FilterCreatureCard("creature card to put into your hand");
private static final FilterCard landFilter
= new FilterLandCard("land card to put into your hand");
KioraRevealEffect() {
super(Outcome.DrawCard);
this.staticText = "Reveal the top four cards of your library. " +
@ -117,46 +108,19 @@ class KioraRevealEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = game.getObject(source);
if (controller == null || sourceObject == null) {
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
Cards cards = new CardsImpl(controller.getLibrary().getTopCards(game, 4));
if (cards.isEmpty()) {
return false;
}
controller.revealCards(sourceObject.getName(), cards, game);
boolean creatureCardFound = cards.getCards(game).stream().anyMatch(card -> card.isCreature(game));
boolean landCardFound = cards.getCards(game).stream().anyMatch(card -> card.isLand(game));
if (!creatureCardFound && !landCardFound) {
controller.moveCards(cards, Zone.GRAVEYARD, source, game);
return true;
}
Cards cardsToHand = new CardsImpl();
if (creatureCardFound) {
TargetCard target = new TargetCardInLibrary(0, 1, creatureFilter);
controller.chooseTarget(Outcome.DrawCard, cards, target, source, game);
if (target.getFirstTarget() != null) {
cards.remove(target.getFirstTarget());
cardsToHand.add(target.getFirstTarget());
}
}
if (landCardFound) {
TargetCard target = new TargetCardInLibrary(0, 1, landFilter);
controller.chooseTarget(Outcome.DrawCard, cards, target, source, game);
if (target.getFirstTarget() != null) {
cards.remove(target.getFirstTarget());
cardsToHand.add(target.getFirstTarget());
}
}
controller.moveCards(cardsToHand, Zone.HAND, source, game);
controller.moveCards(cards, Zone.GRAVEYARD, source, game);
Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, 4));
player.revealCards(source, cards, game);
TargetCard target = new TargetCardAndOrCardInLibrary(CardType.CREATURE, CardType.LAND);
player.choose(outcome, cards, target, source, game);
Cards toHand = new CardsImpl();
toHand.addAll(target.getTargets());
player.moveCards(toHand, Zone.HAND, source, game);
cards.removeAll(toHand);
player.moveCards(cards, Zone.GRAVEYARD, source, game);
return true;
}
}

View file

@ -5,18 +5,15 @@ import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.DealsCombatDamageToAPlayerTriggeredAbility;
import mage.abilities.common.DiesSourceTriggeredAbility;
import mage.abilities.dynamicvalue.common.CardTypeAssignment;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.keyword.TrampleAbility;
import mage.abilities.keyword.TransformAbility;
import mage.cards.*;
import mage.constants.*;
import mage.filter.FilterCard;
import mage.filter.predicate.Predicates;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetCardAndOrCardInLibrary;
import java.util.UUID;
@ -118,7 +115,7 @@ class OjerKaslemDeepestGrowthEffect extends OneShotEffect {
Cards cards = new CardsImpl(controller.getLibrary().getTopCards(game, xValue));
if (!cards.isEmpty()) {
controller.revealCards(source, cards, game);
TargetCard target = new OjerKaslemDeepestGrowthTarget();
TargetCard target = new TargetCardAndOrCardInLibrary(CardType.CREATURE, CardType.LAND);
controller.choose(Outcome.PutCardInPlay, cards, target, source, game);
Cards toBattlefield = new CardsImpl(target.getTargets());
cards.removeAll(toBattlefield);
@ -128,49 +125,3 @@ class OjerKaslemDeepestGrowthEffect extends OneShotEffect {
return true;
}
}
class OjerKaslemDeepestGrowthTarget extends TargetCardInLibrary {
private static final FilterCard filter
= new FilterCard("a creature card and/or a land card");
static {
filter.add(Predicates.or(
CardType.CREATURE.getPredicate(),
CardType.LAND.getPredicate()
));
}
private static final CardTypeAssignment cardTypeAssigner
= new CardTypeAssignment(CardType.CREATURE, CardType.LAND);
OjerKaslemDeepestGrowthTarget() {
super(0, 2, filter);
}
private OjerKaslemDeepestGrowthTarget(final OjerKaslemDeepestGrowthTarget target) {
super(target);
}
@Override
public OjerKaslemDeepestGrowthTarget copy() {
return new OjerKaslemDeepestGrowthTarget(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);
if (card == null) {
return false;
}
if (this.getTargets().isEmpty()) {
return true;
}
Cards cards = new CardsImpl(this.getTargets());
cards.add(card);
return cardTypeAssigner.getRoleCount(cards, game) >= cards.size();
}
}

View file

@ -1,19 +1,18 @@
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;
import mage.filter.FilterCard;
import mage.filter.common.FilterCreatureCard;
import mage.filter.common.FilterLandCard;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetCardAndOrCardInLibrary;
import java.util.UUID;
@ -41,10 +40,6 @@ public final class RelentlessPursuit extends CardImpl {
class RelentlessPursuitEffect extends OneShotEffect {
private static final FilterCard creatureFilter
= new FilterCreatureCard("creature card to put into your hand");
private static final FilterCard landFilter
= new FilterLandCard("land card to put into your hand");
RelentlessPursuitEffect() {
super(Outcome.DrawCard);
@ -64,46 +59,19 @@ class RelentlessPursuitEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
MageObject sourceObject = game.getObject(source);
if (controller == null || sourceObject == null) {
Player player = game.getPlayer(source.getControllerId());
if (player == null) {
return false;
}
Cards cards = new CardsImpl(controller.getLibrary().getTopCards(game, 4));
if (cards.isEmpty()) {
return false;
}
controller.revealCards(sourceObject.getName(), cards, game);
boolean creatureCardFound = cards.getCards(game).stream().anyMatch(card -> card.isCreature(game));
boolean landCardFound = cards.getCards(game).stream().anyMatch(card -> card.isLand(game));
if (!creatureCardFound && !landCardFound) {
controller.moveCards(cards, Zone.GRAVEYARD, source, game);
return true;
}
Cards cardsToHand = new CardsImpl();
if (creatureCardFound) {
TargetCard target = new TargetCardInLibrary(0, 1, creatureFilter);
controller.chooseTarget(Outcome.DrawCard, cards, target, source, game);
if (target.getFirstTarget() != null) {
cards.remove(target.getFirstTarget());
cardsToHand.add(target.getFirstTarget());
}
}
if (landCardFound) {
TargetCard target = new TargetCardInLibrary(0, 1, landFilter);
controller.chooseTarget(Outcome.DrawCard, cards, target, source, game);
if (target.getFirstTarget() != null) {
cards.remove(target.getFirstTarget());
cardsToHand.add(target.getFirstTarget());
}
}
controller.moveCards(cardsToHand, Zone.HAND, source, game);
controller.moveCards(cards, Zone.GRAVEYARD, source, game);
Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, 4));
player.revealCards(source, cards, game);
TargetCard target = new TargetCardAndOrCardInLibrary(CardType.CREATURE, CardType.LAND);
player.choose(outcome, cards, target, source, game);
Cards toHand = new CardsImpl();
toHand.addAll(target.getTargets());
player.moveCards(toHand, Zone.HAND, source, game);
cards.removeAll(toHand);
player.moveCards(cards, Zone.GRAVEYARD, source, game);
return true;
}
}

View file

@ -0,0 +1,24 @@
package mage.abilities.dynamicvalue.common;
import mage.abilities.dynamicvalue.RoleAssignment;
import mage.cards.Card;
import mage.filter.predicate.Predicate;
import mage.game.Game;
import java.util.Set;
import java.util.stream.Collectors;
public class PredicateCardAssignment extends RoleAssignment<Predicate<? super Card>> {
public PredicateCardAssignment(Predicate<? super Card>... predicates) {
super(predicates);
}
@Override
protected Set<Predicate<? super Card>> makeSet(Card card, Game game) {
return attributes
.stream()
.filter(predicate -> predicate.apply(card, game))
.collect(Collectors.toSet());
}
}

View file

@ -0,0 +1,117 @@
package mage.target.common;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.common.PredicateCardAssignment;
import mage.cards.Card;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.filter.FilterCard;
import mage.filter.predicate.Predicate;
import mage.filter.predicate.Predicates;
import mage.game.Game;
import mage.util.CardUtil;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
/**
* @author xenohedron
*/
public class TargetCardAndOrCardInLibrary extends TargetCardInLibrary {
private static FilterCard makeFilter(Predicate<? super Card> firstPredicate,
Predicate<? super Card> secondPredicate,
String filterText) {
FilterCard filter = new FilterCard(filterText);
filter.add(Predicates.or(
firstPredicate, secondPredicate
));
return filter;
}
private static String makeFilterText(String first, String second) {
return CardUtil.addArticle(first) + " card and/or " + CardUtil.addArticle(second) + " card";
}
private final PredicateCardAssignment assignment;
/**
* a [firstType] card and/or a [secondType] card
*/
protected TargetCardAndOrCardInLibrary(Predicate<? super Card> firstPredicate, Predicate<? super Card> secondPredicate, String filterText) {
super(0, 2, makeFilter(firstPredicate, secondPredicate, filterText));
this.assignment = new PredicateCardAssignment(firstPredicate, secondPredicate);
}
public TargetCardAndOrCardInLibrary(CardType firstType, CardType secondType) {
this(firstType.getPredicate(), secondType.getPredicate(), makeFilterText(
CardUtil.getTextWithFirstCharLowerCase(firstType.toString()),
CardUtil.getTextWithFirstCharLowerCase(secondType.toString())));
}
public TargetCardAndOrCardInLibrary(SubType firstType, SubType secondType) {
this(firstType.getPredicate(), secondType.getPredicate(), makeFilterText(firstType.getDescription(), secondType.getDescription()));
}
protected TargetCardAndOrCardInLibrary(final TargetCardAndOrCardInLibrary target) {
super(target);
this.assignment = target.assignment;
}
@Override
public TargetCardAndOrCardInLibrary copy() {
return new TargetCardAndOrCardInLibrary(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);
if (card == null) {
return false;
}
if (this.getTargets().isEmpty()) {
return true;
}
Cards cards = new CardsImpl(this.getTargets());
cards.add(card);
return assignment.getRoleCount(cards, game) >= cards.size();
}
@Override
public Set<UUID> possibleTargets(UUID sourceControllerId, Ability source, Game game) {
Set<UUID> possibleTargets = super.possibleTargets(sourceControllerId, source, game);
// assuming max targets = 2, need to expand this code if not
Card card = game.getCard(this.getFirstTarget());
if (card == null) {
return possibleTargets; // no further restriction if no target yet chosen
}
Cards cards = new CardsImpl(card);
if (assignment.getRoleCount(cards, game) == 2) {
// if the first chosen target is both types, no further restriction
return possibleTargets;
}
Set<UUID> leftPossibleTargets = new HashSet<>();
for (UUID possibleId : possibleTargets) {
Card possibleCard = game.getCard(possibleId);
Cards checkCards = cards.copy();
checkCards.add(possibleCard);
if (assignment.getRoleCount(checkCards, game) == 2) {
// if the possible target and the existing target have both types, it's legal
// but this prevents the case of both targets with the same type
leftPossibleTargets.add(possibleId);
}
}
return leftPossibleTargets;
}
@Override
public String getDescription() {
return filter.getMessage();
}
}