refactored card.moveToExile for M-N

reworked Mindreaver
This commit is contained in:
Evan Kranzler 2021-03-03 10:04:15 -05:00
parent 4c3de17006
commit 29be124725
7 changed files with 180 additions and 179 deletions

View file

@ -2,21 +2,20 @@ package mage.cards.m;
import mage.abilities.Ability;
import mage.abilities.effects.SearchEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.filter.FilterCard;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCardInLibrary;
import java.util.List;
import java.util.UUID;
/**
*
* @author emerald000
*/
public final class ManipulateFate extends CardImpl {
@ -26,7 +25,6 @@ public final class ManipulateFate extends CardImpl {
// Search your library for three cards, exile them, then shuffle your library.
this.getSpellAbility().addEffect(new ManipulateFateEffect());
}
private ManipulateFate(final ManipulateFate card) {
@ -42,12 +40,12 @@ public final class ManipulateFate extends CardImpl {
class ManipulateFateEffect extends SearchEffect {
ManipulateFateEffect() {
super(new TargetCardInLibrary(3, new FilterCard()), Outcome.Benefit);
super(new TargetCardInLibrary(3, StaticFilters.FILTER_CARD), Outcome.Benefit);
staticText = "Search your library for three cards, exile them, "
+ "then shuffle your library. Draw a card";
+ "then shuffle your library. Draw a card";
}
ManipulateFateEffect(final ManipulateFateEffect effect) {
private ManipulateFateEffect(final ManipulateFateEffect effect) {
super(effect);
}
@ -59,24 +57,13 @@ class ManipulateFateEffect extends SearchEffect {
@Override
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
if (player.searchLibrary(target, source, game)) {
for (UUID targetId : getTargets()) {
Card card = player.getLibrary().getCard(targetId, game);
if (card != null) {
card.moveToExile(null, null, source, game);
}
}
}
player.shuffleLibrary(source, game);
player.drawCards(1, source, game);
return true;
if (player == null) {
return false;
}
return false;
player.searchLibrary(target, source, game);
player.moveCards(new CardsImpl(target.getTargets()), Zone.EXILED, source, game);
player.shuffleLibrary(source, game);
player.drawCards(1, source, game);
return true;
}
public List<UUID> getTargets() {
return target.getTargets();
}
}

View file

@ -1,22 +1,30 @@
package mage.cards.m;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.UUID;
import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterPermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.ColorPredicate;
import mage.game.Controllable;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
*
* @author TheElk801
*/
public final class MartyrsCry extends CardImpl {
@ -40,12 +48,18 @@ public final class MartyrsCry extends CardImpl {
class MartyrsCryEffect extends OneShotEffect {
private static final FilterPermanent filter = new FilterCreaturePermanent();
static {
filter.add(new ColorPredicate(ObjectColor.WHITE));
}
MartyrsCryEffect() {
super(Outcome.Exile);
this.staticText = "Exile all white creatures. For each creature exiled this way, its controller draws a card.";
}
MartyrsCryEffect(final MartyrsCryEffect effect) {
private MartyrsCryEffect(final MartyrsCryEffect effect) {
super(effect);
}
@ -56,19 +70,29 @@ class MartyrsCryEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Map<UUID, Integer> playerCrtCount = new HashMap<>();
for (Iterator<Permanent> it = game.getBattlefield().getActivePermanents(source.getControllerId(), game).iterator(); it.hasNext();) {
Permanent perm = it.next();
if (perm != null && perm.isCreature() && perm.getColor(game).isWhite() && perm.moveToExile(null, null, source, game)) {
playerCrtCount.putIfAbsent(perm.getControllerId(), 0);
playerCrtCount.compute(perm.getControllerId(), (p, amount) -> amount + 1);
}
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
for (UUID playerId : game.getPlayerList().toList()) {
Player player = game.getPlayer(playerId);
if (player != null) {
player.drawCards(playerCrtCount.getOrDefault(playerId, 0), source, game);
List<Permanent> permanents = game.getBattlefield().getActivePermanents(
filter, source.getControllerId(), source.getSourceId(), game
);
Map<UUID, Integer> playerMap = permanents
.stream()
.filter(Objects::nonNull)
.map(Controllable::getControllerId)
.collect(Collectors.toMap(
Function.identity(),
uuid -> 1,
Integer::sum
));
controller.moveCards(new CardsImpl(permanents), Zone.EXILED, source, game);
for (Map.Entry<UUID, Integer> entry : playerMap.entrySet()) {
Player player = game.getPlayer(entry.getKey());
if (player == null) {
continue;
}
player.drawCards(entry.getValue(), source, game);
}
return true;
}

View file

@ -9,24 +9,23 @@ import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CounterTargetEffect;
import mage.abilities.keyword.HeroicAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.FilterSpell;
import mage.filter.predicate.Predicate;
import mage.game.ExileZone;
import mage.game.Game;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.target.TargetPlayer;
import mage.target.TargetSpell;
import mage.util.CardUtil;
import java.util.HashSet;
import java.util.Set;
import java.util.Objects;
import java.util.UUID;
/**
@ -48,11 +47,9 @@ public final class Mindreaver extends CardImpl {
this.addAbility(ability);
// {U}{U}, Sacrifice Mindreaver: Counter target spell with the same name as a card exiled with Mindreaver.
ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CounterTargetEffect(), new ManaCostsImpl("{U}{U}"));
FilterSpell filter = new FilterSpell("spell with the same name as a card exiled with {this}");
filter.add(new MindreaverNamePredicate(this.getId()));
ability.addTarget(new TargetSpell(filter));
ability = new SimpleActivatedAbility(new CounterTargetEffect(), new ManaCostsImpl("{U}{U}"));
ability.addCost(new SacrificeSourceCost());
ability.addTarget(new MindreaverTarget());
this.addAbility(ability);
}
@ -66,14 +63,43 @@ public final class Mindreaver extends CardImpl {
}
}
class MindreaverExileEffect extends OneShotEffect {
class MindreaverTarget extends TargetSpell {
public MindreaverExileEffect() {
super(Outcome.Exile);
this.staticText = "exile the top three cards of target opponent's library";
private static final FilterSpell filter
= new FilterSpell("spell with the same name as a card exiled with {this}");
MindreaverTarget() {
super(filter);
}
public MindreaverExileEffect(final MindreaverExileEffect effect) {
private MindreaverTarget(final MindreaverTarget target) {
super(target);
}
@Override
public boolean canTarget(UUID id, Ability source, Game game) {
Spell spell = game.getSpell(id);
ExileZone exileZone = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source));
return super.canTarget(id, source, game)
&& spell != null
&& exileZone != null
&& !exileZone.isEmpty()
&& exileZone
.getCards(game)
.stream()
.filter(Objects::nonNull)
.anyMatch(card -> CardUtil.haveSameNames(spell, card));
}
}
class MindreaverExileEffect extends OneShotEffect {
MindreaverExileEffect() {
super(Outcome.Exile);
this.staticText = "exile the top three cards of target player's library";
}
private MindreaverExileEffect(final MindreaverExileEffect effect) {
super(effect);
}
@ -84,44 +110,16 @@ class MindreaverExileEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
UUID exileId = CardUtil.getCardExileZoneId(game, source);
MageObject sourceObject = source.getSourceObject(game);
Player opponent = game.getPlayer(this.getTargetPointer().getFirst(game, source));
if (opponent != null && sourceObject != null) {
for (int i = 0; i < 3; i++) {
Card card = opponent.getLibrary().getFromTop(game);
if (card != null) {
card.moveToExile(exileId, sourceObject.getIdName(), source, game);
}
}
Player controller = game.getPlayer(source.getControllerId());
Player player = game.getPlayer(source.getFirstTarget());
MageObject mageObject = source.getSourceObject(game);
if (controller == null || player == null || mageObject == null) {
return false;
}
return false;
}
}
class MindreaverNamePredicate implements Predicate<MageObject> {
private final UUID sourceId;
public MindreaverNamePredicate(UUID sourceId) {
this.sourceId = sourceId;
}
@Override
public boolean apply(MageObject input, Game game) {
Set<String> cardNames = new HashSet<>();
UUID exileId = CardUtil.getCardExileZoneId(game, sourceId);
ExileZone exileZone = game.getExile().getExileZone(exileId);
if (exileZone != null) {
for (Card card : exileZone.getCards(game)) {
cardNames.add(card.getName());
}
}
return cardNames.stream().anyMatch(needName -> CardUtil.haveSameNames(input, needName, game));
}
@Override
public String toString() {
return "spell with the same name as a card exiled with {this}";
Cards cards = new CardsImpl(player.getLibrary().getTopCards(game, 3));
return controller.moveCardsToExile(
cards.getCards(game), source, game, true,
CardUtil.getExileZoneId(game, source), mageObject.getIdName()
);
}
}

View file

@ -1,7 +1,5 @@
package mage.cards.m;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
@ -9,27 +7,29 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.common.FilterCreatureCard;
import mage.game.Game;
import mage.game.permanent.token.SaprolingToken;
import mage.players.Player;
import mage.target.common.TargetCardInGraveyard;
import java.util.UUID;
/**
*
* @author jeffwadsworth
*/
public final class MorbidBloom extends CardImpl {
private static final FilterCard filter = new FilterCreatureCard("creature card from a graveyard");
public MorbidBloom(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{4}{B}{G}");
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{B}{G}");
// Exile target creature card from a graveyard, then create X 1/1 green Saproling creature tokens, where X is the exiled card's toughness.
this.getSpellAbility().addEffect(new MorbidBloomEffect());
this.getSpellAbility().addTarget(new TargetCardInGraveyard(new FilterCreatureCard("creature from a graveyard")));
this.getSpellAbility().addTarget(new TargetCardInGraveyard(filter));
}
private MorbidBloom(final MorbidBloom card) {
@ -44,12 +44,14 @@ public final class MorbidBloom extends CardImpl {
class MorbidBloomEffect extends OneShotEffect {
public MorbidBloomEffect() {
MorbidBloomEffect() {
super(Outcome.PutCreatureInPlay);
staticText = "Exile target creature card from a graveyard, then create X 1/1 green Saproling creature tokens, where X is the exiled card's toughness";
staticText = "Exile target creature card from a graveyard, " +
"then create X 1/1 green Saproling creature tokens, " +
"where X is the exiled card's toughness";
}
public MorbidBloomEffect(final MorbidBloomEffect effect) {
private MorbidBloomEffect(final MorbidBloomEffect effect) {
super(effect);
}
@ -60,13 +62,16 @@ class MorbidBloomEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Card targetCreatureCard = game.getCard(source.getFirstTarget());
if (targetCreatureCard != null) {
targetCreatureCard.moveToExile(null, null, source, game);
int toughness = targetCreatureCard.getToughness().getValue();
SaprolingToken token = new SaprolingToken();
return token.putOntoBattlefield(toughness, game, source, source.getControllerId());
Player player = game.getPlayer(source.getControllerId());
Card card = game.getCard(source.getFirstTarget());
if (player == null || card == null) {
return false;
}
return false;
player.moveCards(card, Zone.EXILED, source, game);
int toughness = card.getToughness().getValue();
if (toughness < 1) {
return true;
}
return new SaprolingToken().putOntoBattlefield(toughness, game, source, player.getId());
}
}

View file

@ -1,29 +1,26 @@
package mage.cards.m;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.filter.FilterCard;
import mage.filter.common.FilterLandCard;
import mage.constants.Zone;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPlayer;
import java.util.UUID;
/**
*
* @author cbt33
*/
public final class Mudhole extends CardImpl {
public Mudhole(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{R}");
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R}");
// Target player exiles all land cards from their graveyard.
this.getSpellAbility().addTarget(new TargetPlayer());
@ -42,27 +39,24 @@ public final class Mudhole extends CardImpl {
class MudholeEffect extends OneShotEffect {
private static final FilterCard filter = new FilterLandCard();
public MudholeEffect() {
MudholeEffect() {
super(Outcome.Exile);
staticText = "Target player exiles all land cards from their graveyard";
}
public MudholeEffect(final MudholeEffect effect) {
private MudholeEffect(final MudholeEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player targetPlayer = game.getPlayer(this.getTargetPointer().getFirst(game, source));
if (targetPlayer != null) {
for (Card card : targetPlayer.getGraveyard().getCards(filter, game)) {
card.moveToExile(null, "", source, game);
}
return true;
Player player = game.getPlayer(source.getFirstTarget());
if (player == null) {
return false;
}
return false;
return player.moveCards(player.getGraveyard().getCards(
StaticFilters.FILTER_CARD_LAND, game
), Zone.EXILED, source, game);
}
@Override

View file

@ -1,34 +1,36 @@
package mage.cards.n;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.continuous.GainAbilityAllEffect;
import mage.abilities.keyword.LifelinkAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.filter.FilterPermanent;
import mage.filter.StaticFilters;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterControlledPermanent;
import mage.game.Game;
import mage.game.permanent.token.ZombieToken;
import mage.players.Player;
import mage.target.TargetPlayer;
import java.util.UUID;
/**
*
* @author jeffwadsworth
*/
public final class NecromancersCovenant extends CardImpl {
private static final FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("Zombies you control");
static {
filter.add(SubType.ZOMBIE.getPredicate());
}
private static final FilterPermanent filter
= new FilterControlledPermanent(SubType.ZOMBIE, "Zombies you control");
public NecromancersCovenant(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{W}{B}{B}");
@ -39,7 +41,9 @@ public final class NecromancersCovenant extends CardImpl {
this.addAbility(ability);
// Zombies you control have lifelink.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GainAbilityAllEffect(LifelinkAbility.getInstance(), Duration.WhileOnBattlefield, filter)));
this.addAbility(new SimpleStaticAbility(new GainAbilityAllEffect(
LifelinkAbility.getInstance(), Duration.WhileOnBattlefield, filter
)));
}
private NecromancersCovenant(final NecromancersCovenant card) {
@ -54,32 +58,26 @@ public final class NecromancersCovenant extends CardImpl {
class NecromancersConvenantEffect extends OneShotEffect {
public NecromancersConvenantEffect() {
NecromancersConvenantEffect() {
super(Outcome.PutCreatureInPlay);
staticText = "exile all creature cards from target player's graveyard, then create a 2/2 black Zombie creature token for each card exiled this way";
staticText = "exile all creature cards from target player's graveyard, " +
"then create a 2/2 black Zombie creature token for each card exiled this way";
}
public NecromancersConvenantEffect(NecromancersConvenantEffect effect) {
private NecromancersConvenantEffect(NecromancersConvenantEffect effect) {
super(effect);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
Player player = game.getPlayer(source.getFirstTarget());
if (player == null) {
if (controller == null || player == null) {
return false;
}
int count = 0;
for (Card card : player.getGraveyard().getCards(StaticFilters.FILTER_CARD_CREATURE, game)) {
if (card.moveToExile(source.getSourceId(), "Necromancer Covenant", source, game)) {
count += 1;
}
}
ZombieToken zombieToken = new ZombieToken();
if (zombieToken.putOntoBattlefield(count, game, source, source.getControllerId())) {
return true;
}
return false;
Cards cards = new CardsImpl(player.getGraveyard().getCards(StaticFilters.FILTER_CARD_CREATURE, game));
int count = cards.size();
return count > 0 && new ZombieToken().putOntoBattlefield(count, game, source, controller.getId());
}
@Override

View file

@ -1,7 +1,5 @@
package mage.cards.n;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
@ -10,21 +8,21 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.common.FilterNonlandCard;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.TargetPlayer;
import java.util.UUID;
/**
*
* @author North
*/
public final class NightTerrors extends CardImpl {
public NightTerrors(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{B}");
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{B}");
// Target player reveals their hand. You choose a nonland card from it. Exile that card.
this.getSpellAbility().addTarget(new TargetPlayer());
@ -43,12 +41,12 @@ public final class NightTerrors extends CardImpl {
class NightTerrorsEffect extends OneShotEffect {
public NightTerrorsEffect() {
NightTerrorsEffect() {
super(Outcome.Exile);
this.staticText = "Target player reveals their hand. You choose a nonland card from it. Exile that card";
}
public NightTerrorsEffect(final NightTerrorsEffect effect) {
private NightTerrorsEffect(final NightTerrorsEffect effect) {
super(effect);
}
@ -61,19 +59,16 @@ class NightTerrorsEffect extends OneShotEffect {
public boolean apply(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
Player targetPlayer = game.getPlayer(source.getFirstTarget());
if (player != null && targetPlayer != null) {
targetPlayer.revealCards("Night Terrors", targetPlayer.getHand(), game);
TargetCard target = new TargetCard(Zone.HAND, new FilterNonlandCard("nonland card to exile"));
if (player.choose(Outcome.Exile, targetPlayer.getHand(), target, game)) {
Card card = targetPlayer.getHand().get(target.getFirstTarget(), game);
if (card != null) {
card.moveToExile(null, "", source, game);
}
}
if (player == null || targetPlayer == null) {
return false;
}
targetPlayer.revealCards(source, targetPlayer.getHand(), game);
TargetCard target = new TargetCard(Zone.HAND, StaticFilters.FILTER_CARD_NON_LAND);
if (!player.choose(Outcome.Exile, targetPlayer.getHand(), target, game)) {
return true;
}
return false;
Card card = targetPlayer.getHand().get(target.getFirstTarget(), game);
return card != null && player.moveCards(card, Zone.EXILED, source, game);
}
}