refactor selecting cards from multiple zones (#11584)

* refactor selecting cards from multiple zones

fix MV <= controlled lands predicate

fix filter checks without source parameter

* fix test choice
This commit is contained in:
xenohedron 2023-12-31 14:25:25 -05:00 committed by GitHub
parent 8459babbcd
commit e6bd35eb77
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 258 additions and 319 deletions

View file

@ -4,7 +4,6 @@ import mage.ApprovingObject;
import mage.MageInt; import mage.MageInt;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.ActivatedAbility;
import mage.abilities.SpellAbility; import mage.abilities.SpellAbility;
import mage.abilities.common.AttacksTriggeredAbility; import mage.abilities.common.AttacksTriggeredAbility;
import mage.abilities.costs.Cost; import mage.abilities.costs.Cost;
@ -74,8 +73,8 @@ class AnrakyrTheTravellerEffect extends OneShotEffect {
return false; return false;
} }
Set<Card> cards = player.getHand().getCards(filter, game); Set<Card> cards = player.getHand().getCards(filter, source.getControllerId(), source, game);
cards.addAll(player.getGraveyard().getCards(filter, game)); cards.addAll(player.getGraveyard().getCards(filter, source.getControllerId(), source, game));
Map<UUID, List<Card>> cardMap = new HashMap<>(); Map<UUID, List<Card>> cardMap = new HashMap<>();
for (Card card : cards) { for (Card card : cards) {
@ -103,11 +102,11 @@ class AnrakyrTheTravellerEffect extends OneShotEffect {
.stream() .stream()
.map(MageObject::getLogName) .map(MageObject::getLogName)
.collect(Collectors.joining(" or ")); .collect(Collectors.joining(" or "));
if (partsToCast.size() < 1 if (partsToCast.isEmpty()
|| !player.chooseUse( || !player.chooseUse(
Outcome.PlayForFree, "Cast spell by paying life equal to its mana value rather than paying its mana cost (" + partsInfo + ")?", source, game Outcome.PlayForFree, "Cast spell by paying life equal to its mana value rather than paying its mana cost (" + partsInfo + ")?", source, game
)) { )) {
return false; return true;
} }
partsToCast.forEach(card -> game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE)); partsToCast.forEach(card -> game.getState().setValue("PlayFromNotOwnHandZone" + card.getId(), Boolean.TRUE));
@ -119,12 +118,12 @@ class AnrakyrTheTravellerEffect extends OneShotEffect {
newCosts.addAll(cardToCast.getSpellAbility().getCosts()); newCosts.addAll(cardToCast.getSpellAbility().getCosts());
player.setCastSourceIdWithAlternateMana(cardToCast.getId(), null, newCosts); player.setCastSourceIdWithAlternateMana(cardToCast.getId(), null, newCosts);
ActivatedAbility chosenAbility; SpellAbility chosenAbility;
chosenAbility = player.chooseAbilityForCast(cardToCast, game, true); chosenAbility = player.chooseAbilityForCast(cardToCast, game, true);
boolean result = false; boolean result = false;
if (chosenAbility instanceof SpellAbility) { if (chosenAbility != null) {
result = player.cast( result = player.cast(
(SpellAbility) chosenAbility, chosenAbility,
game, true, new ApprovingObject(source, game) game, true, new ApprovingObject(source, game)
); );
} }
@ -139,4 +138,4 @@ class AnrakyrTheTravellerEffect extends OneShotEffect {
public AnrakyrTheTravellerEffect copy() { public AnrakyrTheTravellerEffect copy() {
return new AnrakyrTheTravellerEffect(this); return new AnrakyrTheTravellerEffect(this);
} }
} }

View file

@ -7,7 +7,7 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.filter.FilterCard; import mage.filter.FilterCard;
import mage.filter.predicate.card.CardManaCostLessThanControlledLandCountPredicate; import mage.filter.predicate.card.ManaValueLessThanControlledLandCountPredicate;
import mage.target.common.TargetCardInLibrary; import mage.target.common.TargetCardInLibrary;
/** /**
@ -18,7 +18,7 @@ public final class BeseechTheQueen extends CardImpl {
private static final FilterCard filter = new FilterCard("card with mana value less than or equal to the number of lands you control"); private static final FilterCard filter = new FilterCard("card with mana value less than or equal to the number of lands you control");
static { static {
filter.add(CardManaCostLessThanControlledLandCountPredicate.getInstance()); filter.add(ManaValueLessThanControlledLandCountPredicate.instance);
} }
public BeseechTheQueen(UUID ownerId, CardSetInfo setInfo) { public BeseechTheQueen(UUID ownerId, CardSetInfo setInfo) {

View file

@ -5,7 +5,7 @@ import mage.abilities.LoyaltyAbility;
import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.dynamicvalue.common.LandsYouControlCount; import mage.abilities.dynamicvalue.common.LandsYouControlCount;
import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.effects.common.ExileTargetEffect;
import mage.abilities.effects.common.PutCardFromOneOfTwoZonesOntoBattlefieldEffect; import mage.abilities.effects.common.PutCardFromHandOrGraveyardOntoBattlefieldEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.effects.keyword.SurveilEffect; import mage.abilities.effects.keyword.SurveilEffect;
import mage.abilities.hint.common.LandsYouControlHint; import mage.abilities.hint.common.LandsYouControlHint;
@ -46,7 +46,7 @@ public final class DakkonShadowSlayer extends CardImpl {
this.addAbility(ability); this.addAbility(ability);
// 6: You may put an artifact card from your hand or graveyard onto the battlefield. // 6: You may put an artifact card from your hand or graveyard onto the battlefield.
this.addAbility(new LoyaltyAbility(new PutCardFromOneOfTwoZonesOntoBattlefieldEffect(StaticFilters.FILTER_CARD_ARTIFACT), -6)); this.addAbility(new LoyaltyAbility(new PutCardFromHandOrGraveyardOntoBattlefieldEffect(StaticFilters.FILTER_CARD_ARTIFACT, false), -6));
} }
private DakkonShadowSlayer(final DakkonShadowSlayer card) { private DakkonShadowSlayer(final DakkonShadowSlayer card) {

View file

@ -59,9 +59,9 @@ public final class DanithaBenaliasHope extends CardImpl {
class DanithaBenaliasHopeEffect extends OneShotEffect { class DanithaBenaliasHopeEffect extends OneShotEffect {
public DanithaBenaliasHopeEffect() { DanithaBenaliasHopeEffect() {
super(Outcome.PutCardInPlay); super(Outcome.PutCardInPlay);
this.staticText = "put an Aura or Equipment card from your hand or graveyard onto the battlefield attached to Danitha"; this.staticText = "you may put an Aura or Equipment card from your hand or graveyard onto the battlefield attached to {this}";
} }
private DanithaBenaliasHopeEffect(final DanithaBenaliasHopeEffect effect) { private DanithaBenaliasHopeEffect(final DanithaBenaliasHopeEffect effect) {
@ -88,9 +88,12 @@ class DanithaBenaliasHopeEffect extends OneShotEffect {
SubType.EQUIPMENT.getPredicate() SubType.EQUIPMENT.getPredicate()
)); ));
Cards cards = new CardsImpl(); Cards cards = new CardsImpl();
cards.addAllCards(controller.getHand().getCards(filter, game)); cards.addAllCards(controller.getHand().getCards(filter, source.getControllerId(), source, game));
cards.addAllCards(controller.getGraveyard().getCards(filter, game)); cards.addAllCards(controller.getGraveyard().getCards(filter, source.getControllerId(), source, game));
TargetCard target = new TargetCard(Zone.ALL, filter); if (cards.isEmpty()) {
return true;
}
TargetCard target = new TargetCard(0, 1, Zone.ALL, filter);
target.withNotTarget(true); target.withNotTarget(true);
target.withChooseHint("to attach to " + sourcePermanentName); target.withChooseHint("to attach to " + sourcePermanentName);
controller.choose(outcome, cards, target, source, game); controller.choose(outcome, cards, target, source, game);

View file

@ -1,6 +1,5 @@
package mage.cards.f; package mage.cards.f;
import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ContinuousRuleModifyingEffectImpl; import mage.abilities.effects.ContinuousRuleModifyingEffectImpl;
@ -11,9 +10,7 @@ import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.filter.FilterCard; import mage.filter.FilterCard;
import mage.filter.StaticFilters; import mage.filter.predicate.card.ManaValueLessThanControlledLandCountPredicate;
import mage.filter.predicate.ObjectSourcePlayer;
import mage.filter.predicate.ObjectSourcePlayerPredicate;
import mage.game.Game; import mage.game.Game;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.watchers.common.CastSpellLastTurnWatcher; import mage.watchers.common.CastSpellLastTurnWatcher;
@ -29,7 +26,7 @@ public final class FiresOfInvention extends CardImpl {
= new FilterCard("spells with mana value less than or equal to the number of lands you control"); = new FilterCard("spells with mana value less than or equal to the number of lands you control");
static { static {
filter.add(FiresOfInventionPredicate.instance); filter.add(ManaValueLessThanControlledLandCountPredicate.instance);
} }
public FiresOfInvention(UUID ownerId, CardSetInfo setInfo) { public FiresOfInvention(UUID ownerId, CardSetInfo setInfo) {
@ -52,16 +49,6 @@ public final class FiresOfInvention extends CardImpl {
} }
} }
enum FiresOfInventionPredicate implements ObjectSourcePlayerPredicate<MageObject> {
instance;
@Override
public boolean apply(ObjectSourcePlayer<MageObject> input, Game game) {
return input.getObject().getManaValue() <=
game.getBattlefield().countAll(StaticFilters.FILTER_LAND, game.getControllerId(input.getSourceId()), game);
}
}
class FiresOfInventionCastEffect extends ContinuousRuleModifyingEffectImpl { class FiresOfInventionCastEffect extends ContinuousRuleModifyingEffectImpl {
FiresOfInventionCastEffect() { FiresOfInventionCastEffect() {
@ -96,4 +83,4 @@ class FiresOfInventionCastEffect extends ContinuousRuleModifyingEffectImpl {
|| !game.getActivePlayerId().equals(source.getControllerId()); || !game.getActivePlayerId().equals(source.getControllerId());
} }
} }

View file

@ -78,8 +78,11 @@ class LiberatedLivestockEffect extends OneShotEffect {
filter.add(SubType.AURA.getPredicate()); filter.add(SubType.AURA.getPredicate());
filter.add(new AuraCardCanAttachToPermanentId(tokenPermanent.getId())); filter.add(new AuraCardCanAttachToPermanentId(tokenPermanent.getId()));
Cards auraCards = new CardsImpl(); Cards auraCards = new CardsImpl();
auraCards.addAllCards(controller.getHand().getCards(filter, game)); auraCards.addAllCards(controller.getHand().getCards(filter, source.getControllerId(), source, game));
auraCards.addAllCards(controller.getGraveyard().getCards(filter, game)); auraCards.addAllCards(controller.getGraveyard().getCards(filter, source.getControllerId(), source, game));
if (auraCards.isEmpty()) {
continue;
}
TargetCard target = new TargetCard(0, 1, Zone.ALL, filter); TargetCard target = new TargetCard(0, 1, Zone.ALL, filter);
target.withNotTarget(true); target.withNotTarget(true);
controller.chooseTarget(outcome, auraCards, target, source, game); controller.chooseTarget(outcome, auraCards, target, source, game);

View file

@ -8,7 +8,7 @@ import mage.abilities.common.CanBeYourCommanderAbility;
import mage.abilities.effects.Effect; import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.CreateTokenEffect;
import mage.abilities.effects.common.PutCardFromOneOfTwoZonesOntoBattlefieldEffect; import mage.abilities.effects.common.PutCardFromHandOrGraveyardOntoBattlefieldEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
@ -32,7 +32,7 @@ import mage.target.common.TargetControlledPermanent;
*/ */
public final class NahiriTheLithomancer extends CardImpl { public final class NahiriTheLithomancer extends CardImpl {
private static final FilterCard filter = new FilterCard("an Equipment card"); private static final FilterCard filter = new FilterCard("Equipment card");
static { static {
filter.add(SubType.EQUIPMENT.getPredicate()); filter.add(SubType.EQUIPMENT.getPredicate());
@ -49,7 +49,7 @@ public final class NahiriTheLithomancer extends CardImpl {
this.addAbility(new LoyaltyAbility(new NahiriTheLithomancerFirstAbilityEffect(), 2)); this.addAbility(new LoyaltyAbility(new NahiriTheLithomancerFirstAbilityEffect(), 2));
// -2: You may put an Equipment card from your hand or graveyard onto the battlefield. // -2: You may put an Equipment card from your hand or graveyard onto the battlefield.
this.addAbility(new LoyaltyAbility(new PutCardFromOneOfTwoZonesOntoBattlefieldEffect(filter), -2)); this.addAbility(new LoyaltyAbility(new PutCardFromHandOrGraveyardOntoBattlefieldEffect(filter, false), -2));
// -10: Create a colorless Equipment artifact token named Stoneforged Blade. It has indestructible, "Equipped creature gets +5/+5 and has double strike," and equip {0}. // -10: Create a colorless Equipment artifact token named Stoneforged Blade. It has indestructible, "Equipped creature gets +5/+5 and has double strike," and equip {0}.
Effect effect = new CreateTokenEffect(new NahiriTheLithomancerEquipmentToken()); Effect effect = new CreateTokenEffect(new NahiriTheLithomancerEquipmentToken());

View file

@ -1,23 +1,16 @@
package mage.cards.n; package mage.cards.n;
import mage.Mana;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.DiesAttachedTriggeredAbility; import mage.abilities.common.DiesAttachedTriggeredAbility;
import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility; import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbility;
import mage.abilities.effects.Effect; import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.AttachEffect; import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.InfoEffect;
import mage.abilities.effects.common.PutCardFromOneOfTwoZonesOntoBattlefieldEffect;
import mage.abilities.effects.common.ReturnToBattlefieldAttachedEffect; import mage.abilities.effects.common.ReturnToBattlefieldAttachedEffect;
import mage.abilities.keyword.EnchantAbility; import mage.abilities.keyword.EnchantAbility;
import mage.cards.Card; import mage.cards.*;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*; import mage.constants.*;
import mage.filter.common.FilterCreatureCard; import mage.filter.common.FilterCreatureCard;
import mage.filter.predicate.Predicates;
import mage.filter.predicate.card.CastFromZonePredicate;
import mage.filter.predicate.mageobject.ManaValuePredicate; import mage.filter.predicate.mageobject.ManaValuePredicate;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
@ -25,9 +18,9 @@ import mage.players.Player;
import mage.target.TargetCard; import mage.target.TargetCard;
import mage.target.TargetPermanent; import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors;
/** /**
* @author Alex-Vasile * @author Alex-Vasile
@ -62,7 +55,7 @@ public class NextOfKin extends CardImpl {
class NextOfKinDiesEffect extends OneShotEffect { class NextOfKinDiesEffect extends OneShotEffect {
NextOfKinDiesEffect() { NextOfKinDiesEffect() {
super(Outcome.Benefit); super(Outcome.PutCardInPlay);
this.staticText = "you may put a creature card you own with lesser mana value from your hand or from the command zone onto the battlefield. " + this.staticText = "you may put a creature card you own with lesser mana value from your hand or from the command zone onto the battlefield. " +
"If you do, return {this} to the battlefield attached to that creature at the beginning of the next end step."; "If you do, return {this} to the battlefield attached to that creature at the beginning of the next end step.";
} }
@ -81,21 +74,28 @@ class NextOfKinDiesEffect extends OneShotEffect {
} }
int manaValue = ((Permanent) object).getManaValue(); int manaValue = ((Permanent) object).getManaValue();
FilterCreatureCard filterCreatureCard = new FilterCreatureCard("a creature card you own with lesser mana value from your hand or from the command zone"); FilterCreatureCard filter = new FilterCreatureCard("a creature card you own with lesser mana value");
filterCreatureCard.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, manaValue)); filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, manaValue));
Cards cards = new CardsImpl();
// This effect is used only to get the info about which card was added. cards.addAllCards(controller.getHand().getCards(filter, source.getControllerId(), source, game));
Effect hackTargetEffect = new InfoEffect(""); for (Card possibleCard : game.getCommanderCardsFromCommandZone(controller, CommanderCardType.ANY)) {
if (filter.match(possibleCard, source.getControllerId(), source, game)) {
Effect putCardEffect = new PutCardFromOneOfTwoZonesOntoBattlefieldEffect(filterCreatureCard, false, hackTargetEffect, Zone.HAND, Zone.COMMAND); cards.add(possibleCard);
boolean cardPut = putCardEffect.apply(game, source); }
if (!cardPut) { }
return false; if (cards.isEmpty()) {
return true;
}
TargetCard target = new TargetCard(0, 1, Zone.ALL, filter);
target.withNotTarget(true);
controller.choose(outcome, cards, target, source, game);
Card card = game.getCard(target.getFirstTarget());
if (card != null) {
controller.moveCards(card, Zone.BATTLEFIELD, source, game);
Effect returnToBattlefieldAttachedEffect = new ReturnToBattlefieldAttachedEffect();
returnToBattlefieldAttachedEffect.setTargetPointer(new FixedTarget(card, game));
game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(returnToBattlefieldAttachedEffect), source);
} }
Effect returnToBattlefieldAttachedEffect = new ReturnToBattlefieldAttachedEffect();
returnToBattlefieldAttachedEffect.setTargetPointer(hackTargetEffect.getTargetPointer());
game.addDelayedTriggeredAbility(new AtTheBeginOfNextEndStepDelayedTriggeredAbility(returnToBattlefieldAttachedEffect), source);
return true; return true;
} }

View file

@ -3,25 +3,23 @@ package mage.cards.n;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility; import mage.abilities.LoyaltyAbility;
import mage.abilities.common.LandfallAbility; import mage.abilities.common.LandfallAbility;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.PutCardFromOneOfTwoZonesOntoBattlefieldEffect;
import mage.abilities.effects.common.UntapTargetEffect; import mage.abilities.effects.common.UntapTargetEffect;
import mage.abilities.effects.common.continuous.BecomesCreatureTargetEffect; import mage.abilities.effects.common.continuous.BecomesCreatureTargetEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.HasteAbility;
import mage.abilities.keyword.MenaceAbility; import mage.abilities.keyword.MenaceAbility;
import mage.cards.CardImpl; import mage.cards.*;
import mage.cards.CardSetInfo;
import mage.constants.*; import mage.constants.*;
import mage.counters.CounterType; import mage.counters.CounterType;
import mage.filter.FilterCard; import mage.counters.Counters;
import mage.filter.StaticFilters; import mage.filter.StaticFilters;
import mage.filter.predicate.card.CardManaCostLessThanControlledLandCountPredicate; import mage.filter.common.FilterCreatureCard;
import mage.filter.predicate.card.ManaValueLessThanControlledLandCountPredicate;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.token.custom.CreatureToken; import mage.game.permanent.token.custom.CreatureToken;
import mage.players.Player; import mage.players.Player;
import mage.target.TargetCard;
import mage.target.TargetPermanent; import mage.target.TargetPermanent;
import java.util.UUID; import java.util.UUID;
@ -31,11 +29,6 @@ import java.util.UUID;
*/ */
public final class NissaOfShadowedBoughs extends CardImpl { public final class NissaOfShadowedBoughs extends CardImpl {
private static final FilterCard filter = new FilterCard("card with mana value less than or equal to the number of lands you control");
static {
filter.add(CardManaCostLessThanControlledLandCountPredicate.getInstance());
}
public NissaOfShadowedBoughs(UUID ownerId, CardSetInfo setInfo) { public NissaOfShadowedBoughs(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{2}{B}{G}"); super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "{2}{B}{G}");
@ -53,12 +46,7 @@ public final class NissaOfShadowedBoughs extends CardImpl {
this.addAbility(ability); this.addAbility(ability);
// 5: You may put a creature card with mana value less than or equal to the number of lands you control onto the battlefield from your hand or graveyard with two +1/+1 counters on it. // 5: You may put a creature card with mana value less than or equal to the number of lands you control onto the battlefield from your hand or graveyard with two +1/+1 counters on it.
Effect putCardEffect = new PutCardFromOneOfTwoZonesOntoBattlefieldEffect(filter, false, new AddCountersTargetEffect(CounterType.P1P1.createInstance(2))); this.addAbility(new LoyaltyAbility(new NissaOfShadowedBoughsPutCardEffect(),-5));
putCardEffect.setText("You may put a creature card with mana value less than or equal to " +
"the number of lands you control onto the battlefield from your hand or graveyard " +
"with two +1/+1 counters on it.");
this.addAbility(new LoyaltyAbility(putCardEffect,-5)
);
} }
private NissaOfShadowedBoughs(final NissaOfShadowedBoughs card) { private NissaOfShadowedBoughs(final NissaOfShadowedBoughs card) {
@ -104,3 +92,54 @@ class NissaOfShadowedBoughsLandEffect extends OneShotEffect {
return true; return true;
} }
} }
class NissaOfShadowedBoughsPutCardEffect extends OneShotEffect {
private static final FilterCreatureCard filter = new FilterCreatureCard("creature card with mana value less than or equal to the number of lands you control");
static {
filter.add(ManaValueLessThanControlledLandCountPredicate.instance);
}
NissaOfShadowedBoughsPutCardEffect() {
super(Outcome.PutCardInPlay);
this.staticText = "you may put a creature card with mana value less than or equal to " +
"the number of lands you control onto the battlefield from your hand or graveyard " +
"with two +1/+1 counters on it";
}
private NissaOfShadowedBoughsPutCardEffect(final NissaOfShadowedBoughsPutCardEffect effect) {
super(effect);
}
@Override
public NissaOfShadowedBoughsPutCardEffect copy() {
return new NissaOfShadowedBoughsPutCardEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
Cards cards = new CardsImpl();
cards.addAllCards(controller.getHand().getCards(filter, source.getControllerId(), source, game));
cards.addAllCards(controller.getGraveyard().getCards(filter, source.getControllerId(), source, game));
if (cards.isEmpty()) {
return true;
}
TargetCard target = new TargetCard(0, 1, Zone.ALL, filter);
target.withNotTarget(true);
controller.choose(outcome, cards, target, source, game);
Card card = game.getCard(target.getFirstTarget());
if (card != null) {
Counters counters = new Counters();
counters.addCounter(CounterType.P1P1.createInstance(2));
game.setEnterWithCounters(card.getId(), counters);
controller.moveCards(card, Zone.BATTLEFIELD, source, game);
}
return true;
}
}

View file

@ -1,10 +1,7 @@
package mage.cards.r; package mage.cards.r;
import mage.abilities.Mode; import mage.abilities.Mode;
import mage.abilities.effects.common.DamageAllEffect; import mage.abilities.effects.common.*;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.LoseLifeSourceControllerEffect;
import mage.abilities.effects.common.PutCardFromOneOfTwoZonesOntoBattlefieldEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
@ -42,7 +39,7 @@ public class RiveteersConfluence extends CardImpl {
this.getSpellAbility().addMode(new Mode(new DamageAllEffect(1, damageFilter))); this.getSpellAbility().addMode(new Mode(new DamageAllEffect(1, damageFilter)));
// You may put a land card from your hand or graveyard onto the battlefield tapped. // You may put a land card from your hand or graveyard onto the battlefield tapped.
this.getSpellAbility().addMode(new Mode(new PutCardFromOneOfTwoZonesOntoBattlefieldEffect(StaticFilters.FILTER_CARD_LAND_A, true))); this.getSpellAbility().addMode(new Mode(new PutCardFromHandOrGraveyardOntoBattlefieldEffect(StaticFilters.FILTER_CARD_LAND_A, true)));
} }
private RiveteersConfluence(final RiveteersConfluence card) { private RiveteersConfluence(final RiveteersConfluence card) {
@ -53,4 +50,4 @@ public class RiveteersConfluence extends CardImpl {
public RiveteersConfluence copy() { public RiveteersConfluence copy() {
return new RiveteersConfluence(this); return new RiveteersConfluence(this);
} }
} }

View file

@ -1,6 +1,5 @@
package mage.cards.s; package mage.cards.s;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility; import mage.abilities.DelayedTriggeredAbility;
@ -9,24 +8,21 @@ import mage.abilities.common.delayed.AtTheBeginOfNextEndStepDelayedTriggeredAbil
import mage.abilities.effects.ContinuousEffect; import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.Effect; import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.PutCardFromOneOfTwoZonesOntoBattlefieldEffect;
import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.abilities.effects.common.continuous.GainAbilityTargetEffect; import mage.abilities.effects.common.continuous.GainAbilityTargetEffect;
import mage.abilities.keyword.FlyingAbility; import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.HasteAbility; import mage.abilities.keyword.HasteAbility;
import mage.cards.CardImpl; import mage.cards.*;
import mage.cards.CardSetInfo; import mage.constants.*;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.ComparisonType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.filter.FilterCard; import mage.filter.FilterCard;
import mage.filter.predicate.mageobject.ManaValuePredicate; import mage.filter.predicate.mageobject.ManaValuePredicate;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.players.Player;
import mage.target.TargetCard;
import mage.target.targetpointer.FixedTarget; import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
/** /**
* *
* @author jeffwadsworth * @author jeffwadsworth
@ -50,10 +46,7 @@ public final class SwiftWarkite extends CardImpl {
this.addAbility(FlyingAbility.getInstance()); this.addAbility(FlyingAbility.getInstance());
// When Swift Warkite enters the battlefield, you may put a creature card with converted mana cost 3 or less from your hand or graveyard onto the battlefield. That creature gains haste. Return it to your hand at the beginning of the next end step. // When Swift Warkite enters the battlefield, you may put a creature card with converted mana cost 3 or less from your hand or graveyard onto the battlefield. That creature gains haste. Return it to your hand at the beginning of the next end step.
this.addAbility(new EntersBattlefieldTriggeredAbility( this.addAbility(new EntersBattlefieldTriggeredAbility(new SwiftWarkiteEffect()));
new PutCardFromOneOfTwoZonesOntoBattlefieldEffect(filter, false, new SwiftWarkiteEffect()),
true)
);
} }
private SwiftWarkite(final SwiftWarkite card) { private SwiftWarkite(final SwiftWarkite card) {
@ -68,9 +61,17 @@ public final class SwiftWarkite extends CardImpl {
class SwiftWarkiteEffect extends OneShotEffect { class SwiftWarkiteEffect extends OneShotEffect {
private static final FilterCard filter = new FilterCard("creature card with mana value 3 or less");
static {
filter.add(CardType.CREATURE.getPredicate());
filter.add(new ManaValuePredicate(ComparisonType.FEWER_THAN, 4));
}
SwiftWarkiteEffect() { SwiftWarkiteEffect() {
super(Outcome.AddAbility); super(Outcome.PutCardInPlay);
this.staticText = "That creature gains haste. Return it to your hand at the beginning of the next end step"; this.staticText = "you may put a creature card with mana value 3 or less from your hand or graveyard onto the battlefield. " +
"That creature gains haste. Return it to your hand at the beginning of the next end step";
} }
private SwiftWarkiteEffect(final SwiftWarkiteEffect effect) { private SwiftWarkiteEffect(final SwiftWarkiteEffect effect) {
@ -84,19 +85,33 @@ class SwiftWarkiteEffect extends OneShotEffect {
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Permanent movedCreature = game.getPermanent(getTargetPointer().getFirst(game, source)); Player controller = game.getPlayer(source.getControllerId());
if (movedCreature == null) { if (controller == null) {
return false; return false;
} }
Cards cards = new CardsImpl();
cards.addAllCards(controller.getHand().getCards(filter, source.getControllerId(), source, game));
cards.addAllCards(controller.getGraveyard().getCards(filter, source.getControllerId(), source, game));
if (cards.isEmpty()) {
return true;
}
TargetCard target = new TargetCard(0, 1, Zone.ALL, filter);
target.withNotTarget(true);
controller.choose(outcome, cards, target, source, game);
Card card = game.getCard(target.getFirstTarget());
if (card != null) {
controller.moveCards(card, Zone.BATTLEFIELD, source, game);
ContinuousEffect gainHasteEffect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.Custom); ContinuousEffect gainHasteEffect = new GainAbilityTargetEffect(HasteAbility.getInstance(), Duration.Custom);
gainHasteEffect.setTargetPointer(new FixedTarget(movedCreature.getId(), movedCreature.getZoneChangeCounter(game))); gainHasteEffect.setTargetPointer(new FixedTarget(card, game));
game.addEffect(gainHasteEffect, source); game.addEffect(gainHasteEffect, source);
Effect returnToHandEffect = new ReturnToHandTargetEffect(); Effect returnToHandEffect = new ReturnToHandTargetEffect();
returnToHandEffect.setTargetPointer(new FixedTarget(movedCreature.getId(), movedCreature.getZoneChangeCounter(game))); returnToHandEffect.setTargetPointer(new FixedTarget(card, game));
DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(returnToHandEffect); DelayedTriggeredAbility delayedAbility = new AtTheBeginOfNextEndStepDelayedTriggeredAbility(returnToHandEffect);
game.addDelayedTriggeredAbility(delayedAbility, source); game.addDelayedTriggeredAbility(delayedAbility, source);
}
return true; return true;
} }
} }

View file

@ -91,8 +91,11 @@ class Vault101BirthdayPartyEffect extends OneShotEffect {
return false; return false;
} }
Cards cards = new CardsImpl(); Cards cards = new CardsImpl();
cards.addAllCards(player.getHand().getCards(filter, game)); cards.addAllCards(player.getHand().getCards(filter, source.getControllerId(), source, game));
cards.addAllCards(player.getGraveyard().getCards(filter, game)); cards.addAllCards(player.getGraveyard().getCards(filter, source.getControllerId(), source, game));
if (cards.isEmpty()) {
return false;
}
TargetCard targetCard = new TargetCard(0, 1, Zone.ALL, filter); TargetCard targetCard = new TargetCard(0, 1, Zone.ALL, filter);
targetCard.withNotTarget(true); targetCard.withNotTarget(true);
player.choose(outcome, cards, targetCard, source, game); player.choose(outcome, cards, targetCard, source, game);
@ -103,7 +106,7 @@ class Vault101BirthdayPartyEffect extends OneShotEffect {
player.moveCards(card, Zone.BATTLEFIELD, source, game); player.moveCards(card, Zone.BATTLEFIELD, source, game);
Permanent equipment = game.getPermanent(card.getId()); Permanent equipment = game.getPermanent(card.getId());
if (equipment == null || !equipment.hasSubtype(SubType.EQUIPMENT, game)) { if (equipment == null || !equipment.hasSubtype(SubType.EQUIPMENT, game)) {
return false; return true;
} }
TargetPermanent targetPermanent = new TargetControlledCreaturePermanent(0, 1); TargetPermanent targetPermanent = new TargetControlledCreaturePermanent(0, 1);
targetCard.withNotTarget(true); targetCard.withNotTarget(true);

View file

@ -93,7 +93,6 @@ public class PutCardFromOneOfTwoZonesOntoBattlefieldEffectTest extends CardTestP
setStrictChooseMode(true); setStrictChooseMode(true);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "-2"); activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "-2");
setChoice(playerA, "Yes"); // For player this choice is "Hand" but tests require "Yes"
setChoice(playerA, vorpal); setChoice(playerA, vorpal);
setStopAt(1, PhaseStep.END_TURN); setStopAt(1, PhaseStep.END_TURN);
@ -113,7 +112,7 @@ public class PutCardFromOneOfTwoZonesOntoBattlefieldEffectTest extends CardTestP
public void testNissaCanPlay() { public void testNissaCanPlay() {
addCard(Zone.BATTLEFIELD, playerA, nissa); addCard(Zone.BATTLEFIELD, playerA, nissa);
addCard(Zone.HAND, playerA, swift); // {4}{B}{R} addCard(Zone.HAND, playerA, swift); // {4}{B}{R}
addCard(Zone.HAND, playerA, "Mountain", 5); addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5);
addCard(Zone.HAND, playerA, "Mountain"); addCard(Zone.HAND, playerA, "Mountain");
setStrictChooseMode(true); setStrictChooseMode(true);
@ -121,7 +120,6 @@ public class PutCardFromOneOfTwoZonesOntoBattlefieldEffectTest extends CardTestP
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mountain"); playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mountain");
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "-5"); activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "-5");
setChoice(playerA, swift); setChoice(playerA, swift);
setChoice(playerA, "Yes"); // Say yes to Swift Warkite's ETB (no further choice needed since there are no possible options
setStopAt(1, PhaseStep.END_TURN); setStopAt(1, PhaseStep.END_TURN);
@ -145,7 +143,6 @@ public class PutCardFromOneOfTwoZonesOntoBattlefieldEffectTest extends CardTestP
addCard(Zone.HAND, playerA, swift); // {4}{B}{R} addCard(Zone.HAND, playerA, swift); // {4}{B}{R}
addCard(Zone.HAND, playerA, "Mountain"); addCard(Zone.HAND, playerA, "Mountain");
setStrictChooseMode(true); setStrictChooseMode(true);
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mountain"); playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mountain");
@ -174,7 +171,6 @@ public class PutCardFromOneOfTwoZonesOntoBattlefieldEffectTest extends CardTestP
setStrictChooseMode(true); setStrictChooseMode(true);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, swift); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, swift);
setChoice(playerA, "Yes"); // Yes to activating Swift Warkite's ETB
setChoice(playerA, sliver); // Pick the sliver for the ETB setChoice(playerA, sliver); // Pick the sliver for the ETB
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN); setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);

View file

@ -5,7 +5,6 @@ import mage.abilities.keyword.FlyingAbility;
import mage.constants.PhaseStep; import mage.constants.PhaseStep;
import mage.constants.Zone; import mage.constants.Zone;
import org.junit.Test; import org.junit.Test;
import org.mage.test.player.TestPlayer;
import org.mage.test.serverside.base.CardTestPlayerBase; import org.mage.test.serverside.base.CardTestPlayerBase;
/** /**
@ -45,7 +44,7 @@ public class DanithaBenaliasHopeTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, danitha); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, danitha);
setChoice(playerA, true); // attempt to use ability setChoice(playerA, true); // attempt to use ability
setChoice(playerA, TestPlayer.CHOICE_SKIP); // choice skip not needed
setStrictChooseMode(true); setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN); setStopAt(1, PhaseStep.END_TURN);
@ -105,7 +104,7 @@ public class DanithaBenaliasHopeTest extends CardTestPlayerBase {
setChoice(playerA, true); // use ability setChoice(playerA, true); // use ability
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, 1); waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN, 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, swords, danitha); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, swords, danitha);
setChoice(playerA, TestPlayer.CHOICE_SKIP); // no longer can attach Aura // no longer can attach Aura
setStrictChooseMode(true); setStrictChooseMode(true);
setStopAt(1, PhaseStep.END_TURN); setStopAt(1, PhaseStep.END_TURN);

View file

@ -199,7 +199,7 @@ public class LiberatedLivestockTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, MURDER, LIBERATEDLIVESTOCK); castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, MURDER, LIBERATEDLIVESTOCK);
addTarget(playerA, KEENSENSE); addTarget(playerA, KEENSENSE);
addTarget(playerA, ARACHNOFORM); addTarget(playerA, ARACHNOFORM);
addTarget(playerA, TestPlayer.TARGET_SKIP); // no possible targets thus no need to target skip
waitStackResolved(1, PhaseStep.END_TURN); waitStackResolved(1, PhaseStep.END_TURN);
execute(); execute();

View file

@ -0,0 +1,69 @@
package mage.abilities.effects.common;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
import mage.util.CardUtil;
/**
* @author xenohedron
*/
public class PutCardFromHandOrGraveyardOntoBattlefieldEffect extends OneShotEffect {
private final FilterCard filter;
private final boolean tapped;
/**
* @param filter for selecting a card (don't include zone-related text in filter message)
* @param tapped ETB tapped if true
*/
public PutCardFromHandOrGraveyardOntoBattlefieldEffect(FilterCard filter, boolean tapped) {
super(Outcome.PutCardInPlay);
this.filter = filter;
this.tapped = tapped;
this.staticText = "you may put " + CardUtil.addArticle(filter.getMessage())
+ " from your hand or graveyard onto the battlefield" + (tapped ? " tapped" : "");
}
private PutCardFromHandOrGraveyardOntoBattlefieldEffect(final PutCardFromHandOrGraveyardOntoBattlefieldEffect effect) {
super(effect);
this.filter = effect.filter;
this.tapped = effect.tapped;
}
@Override
public PutCardFromHandOrGraveyardOntoBattlefieldEffect copy() {
return new PutCardFromHandOrGraveyardOntoBattlefieldEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
Cards cards = new CardsImpl();
cards.addAllCards(controller.getHand().getCards(filter, source.getControllerId(), source, game));
cards.addAllCards(controller.getGraveyard().getCards(filter, source.getControllerId(), source, game));
if (cards.isEmpty()) {
return true;
}
TargetCard target = new TargetCard(0, 1, Zone.ALL, filter);
target.withNotTarget(true);
controller.choose(outcome, cards, target, source, game);
Card card = game.getCard(target.getFirstTarget());
if (card != null) {
controller.moveCards(card, Zone.BATTLEFIELD, source, game, tapped, false, false, null);
}
return true;
}
}

View file

@ -1,164 +0,0 @@
package mage.abilities.effects.common;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.constants.CommanderCardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.filter.FilterCard;
import mage.filter.StaticFilters;
import mage.filter.common.FilterCreatureCard;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetCard;
import mage.target.common.TargetCardInCommandZone;
import mage.target.common.TargetCardInGraveyard;
import mage.target.common.TargetCardInHand;
import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil;
/**
* "Put a {filter} card from {zone 1} or {zone 2} onto the battlefield.
*
* @author TheElk801, Alex-Vasile
*/
public class PutCardFromOneOfTwoZonesOntoBattlefieldEffect extends OneShotEffect {
private final FilterCard filterCard;
private final boolean tapped;
private final Effect effectToApplyOnPermanent;
private final Zone zone1;
private final Zone zone2;
public PutCardFromOneOfTwoZonesOntoBattlefieldEffect(FilterCard filterCard) {
this(filterCard, false);
}
public PutCardFromOneOfTwoZonesOntoBattlefieldEffect(FilterCard filterCard, boolean tapped) {
this(filterCard, tapped, null);
}
/**
*
* @param filterCard Filter used to filter which cards are valid choices. (no default)
* @param tapped If the permanent should enter the battlefield tapped (default is False)
* @param effectToApplyOnPermanent An effect to apply to the permanent after it enters (default null)
* See "Swift Warkite" or "Nissa of Shadowed Boughs".
* @param zone1 The first zone to pick from (default of HAND)
* @param zone2 The second zone to pick from (defualt of GRAVEYARD)
*/
public PutCardFromOneOfTwoZonesOntoBattlefieldEffect(FilterCard filterCard, boolean tapped, Effect effectToApplyOnPermanent, Zone zone1, Zone zone2) {
super(filterCard instanceof FilterCreatureCard ? Outcome.PutCreatureInPlay : Outcome.PutCardInPlay);
this.filterCard = filterCard;
this.tapped = tapped;
this.effectToApplyOnPermanent = effectToApplyOnPermanent;
this.zone1 = zone1;
this.zone2 = zone2;
}
public PutCardFromOneOfTwoZonesOntoBattlefieldEffect(FilterCard filterCard, boolean tapped, Effect effectToApplyOnPermanent) {
this(filterCard, tapped, effectToApplyOnPermanent, Zone.HAND, Zone.GRAVEYARD);
}
public PutCardFromOneOfTwoZonesOntoBattlefieldEffect(FilterCard filterCard, Zone zone1, Zone zone2) {
this(filterCard, false, null, zone1, zone2);
}
private PutCardFromOneOfTwoZonesOntoBattlefieldEffect(final PutCardFromOneOfTwoZonesOntoBattlefieldEffect effect) {
super(effect);
this.filterCard = effect.filterCard;
this.tapped = effect.tapped;
this.zone1 = effect.zone1;
this.zone2 = effect.zone2;
if (effect.effectToApplyOnPermanent != null) {
this.effectToApplyOnPermanent = effect.effectToApplyOnPermanent.copy();
} else {
this.effectToApplyOnPermanent = null;
}
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
Cards cardsInZone1 = getCardsFromZone(game, controller, zone1);
Cards cardsInZone2 = getCardsFromZone(game, controller, zone2);
boolean cardsAvailableInZone1 = cardsInZone1.count(filterCard, game) > 0;
boolean cardsAvailableInZone2 = cardsInZone2.count(filterCard, game) > 0;
if (!cardsAvailableInZone1 && !cardsAvailableInZone2) {
return false;
}
boolean choose1stZone;
if (cardsAvailableInZone1 && cardsAvailableInZone2) {
choose1stZone = controller.chooseUse(outcome, "Where do you want to chose the card from?",
null, zone1.name(), zone2.name(), source, game);
} else {
choose1stZone = cardsAvailableInZone1;
}
Zone zone = choose1stZone ? zone1 : zone2;
Cards cards = choose1stZone ? cardsInZone1 : cardsInZone2;
TargetCard targetCard;
switch (zone) {
case HAND:
targetCard = new TargetCardInHand(filterCard);
break;
case GRAVEYARD:
targetCard = new TargetCardInGraveyard(filterCard);
break;
case COMMAND:
targetCard = new TargetCardInCommandZone(filterCard);
break;
default:
return false;
}
controller.choose(outcome, cards, targetCard, source, game);
Card card = game.getCard(targetCard.getFirstTarget());
if (card == null || !controller.moveCards(card, Zone.BATTLEFIELD, source, game, tapped, false, false, null)) {
return false;
}
if (effectToApplyOnPermanent != null) {
effectToApplyOnPermanent.setTargetPointer(new FixedTarget(card.getId()));
effectToApplyOnPermanent.apply(game, source);
}
return true;
}
private static Cards getCardsFromZone(Game game, Player player, Zone zone) {
switch (zone) {
case HAND:
return player.getHand();
case COMMAND:
return new CardsImpl(game.getCommanderCardsFromCommandZone(player, CommanderCardType.ANY));
case GRAVEYARD:
return player.getGraveyard();
default:
return new CardsImpl();
}
}
@Override
public PutCardFromOneOfTwoZonesOntoBattlefieldEffect copy() {
return new PutCardFromOneOfTwoZonesOntoBattlefieldEffect(this);
}
@Override
public String getText(Mode mode) {
return "you may put " + CardUtil.addArticle(this.filterCard.getMessage()) +
" from your hand or graveyard onto the battlefield" +
(this.tapped ? " tapped" : "") +
(effectToApplyOnPermanent == null ? "" : ". " + effectToApplyOnPermanent.getText(mode));
}
}

View file

@ -1,31 +0,0 @@
package mage.filter.predicate.card;
import mage.cards.Card;
import mage.filter.StaticFilters;
import mage.filter.predicate.Predicate;
import mage.game.Game;
/**
* @author Plopman, Alex-Vasile
*/
public class CardManaCostLessThanControlledLandCountPredicate implements Predicate<Card> {
private static final String string = "card with mana value less than or equal to the number of lands you control";
private static final CardManaCostLessThanControlledLandCountPredicate instance = new CardManaCostLessThanControlledLandCountPredicate();
private CardManaCostLessThanControlledLandCountPredicate() { }
public static CardManaCostLessThanControlledLandCountPredicate getInstance() {
return instance;
}
@Override
public boolean apply(Card input, Game game) {
return input.getManaValue() <= game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND, input.getOwnerId(), game).size();
}
@Override
public String toString() {
return string;
}
}

View file

@ -0,0 +1,24 @@
package mage.filter.predicate.card;
import mage.MageObject;
import mage.filter.StaticFilters;
import mage.filter.predicate.ObjectSourcePlayer;
import mage.filter.predicate.ObjectSourcePlayerPredicate;
import mage.game.Game;
/**
* @author xenohedron
*/
public enum ManaValueLessThanControlledLandCountPredicate implements ObjectSourcePlayerPredicate<MageObject> {
instance;
@Override
public boolean apply(ObjectSourcePlayer<MageObject> input, Game game) {
return input.getObject().getManaValue() <= game.getBattlefield().countAll(StaticFilters.FILTER_LAND, game.getControllerId(input.getSourceId()), game);
}
@Override
public String toString() {
return "mana value less than or equal to the number of lands you control";
}
}