mirror of
https://github.com/magefree/mage.git
synced 2026-01-19 01:39:58 -08:00
more refactoring
This commit is contained in:
parent
e0f031801d
commit
a9ef69885e
23 changed files with 432 additions and 405 deletions
|
|
@ -27,7 +27,6 @@ public final class DeadlyCoverUp extends CardImpl {
|
|||
public DeadlyCoverUp(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}{B}");
|
||||
|
||||
|
||||
// As an additional cost to cast this spell, you may collect evidence 6.
|
||||
this.addAbility(new CollectEvidenceAbility(6));
|
||||
|
||||
|
|
@ -70,16 +69,18 @@ class DeadlyCoverUpEffect extends SearchTargetGraveyardHandLibraryForCardNameAnd
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
if (player == null) {
|
||||
return true;
|
||||
}
|
||||
TargetCardInOpponentsGraveyard target = new TargetCardInOpponentsGraveyard(StaticFilters.FILTER_CARD);
|
||||
target.withNotTarget(true);
|
||||
if (player != null && player.chooseTarget(Outcome.Exile, target, source, game)) {
|
||||
Card cardToExile = game.getCard(target.getFirstTarget());
|
||||
if (cardToExile == null) {
|
||||
return false;
|
||||
}
|
||||
player.moveCards(cardToExile, Zone.EXILED, source, game);
|
||||
this.applySearchAndExile(game, source, cardToExile.getName(), cardToExile.getOwnerId());
|
||||
player.chooseTarget(Outcome.Exile, target, source, game);
|
||||
Card cardToExile = game.getCard(target.getFirstTarget());
|
||||
if (cardToExile == null) {
|
||||
return false;
|
||||
}
|
||||
player.moveCards(cardToExile, Zone.EXILED, source, game);
|
||||
this.applySearchAndExile(game, source, cardToExile, cardToExile.getOwnerId());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package mage.cards.d;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.effects.common.search.SearchTargetGraveyardHandLibraryForCardNameAndExileEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
|
|
@ -53,12 +52,8 @@ class DeicideExileEffect extends SearchTargetGraveyardHandLibraryForCardNameAndE
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
Card sourceCard = game.getCard(source.getSourceId());
|
||||
if (controller == null || sourceCard == null) {
|
||||
return false;
|
||||
}
|
||||
Permanent targetEnchantment = game.getPermanent(getTargetPointer().getFirst(game, source));
|
||||
if (targetEnchantment == null) {
|
||||
if (controller == null || targetEnchantment == null) {
|
||||
return false;
|
||||
}
|
||||
controller.moveCards(targetEnchantment, Zone.EXILED, source, game);
|
||||
|
|
@ -69,11 +64,11 @@ class DeicideExileEffect extends SearchTargetGraveyardHandLibraryForCardNameAndE
|
|||
// if it is a God. For each of the Gods in the Theros block, it won't matter what your
|
||||
// devotion to its color(s) was. The card is a God card when not on the battlefield.
|
||||
Card cardInExile = game.getExile().getCard(targetEnchantment.getId(), game);
|
||||
if (cardInExile != null && cardInExile.hasSubtype(SubType.GOD, game)) {
|
||||
Player enchantmentController = game.getPlayer(targetEnchantment.getControllerId());
|
||||
return enchantmentController != null && super.applySearchAndExile(game, source, cardInExile.getName(), enchantmentController.getId());
|
||||
if (cardInExile == null || !cardInExile.hasSubtype(SubType.GOD, game)) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
Player enchantmentController = game.getPlayer(targetEnchantment.getControllerId());
|
||||
return enchantmentController != null && super.applySearchAndExile(game, source, cardInExile, enchantmentController.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -1,23 +1,20 @@
|
|||
package mage.cards.i;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.condition.common.DeliriumCondition;
|
||||
import mage.abilities.effects.common.search.SearchTargetGraveyardHandLibraryForCardNameAndExileEffect;
|
||||
import mage.abilities.hint.common.CardTypesInGraveyardHint;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.constants.CardType;
|
||||
import mage.filter.FilterSpell;
|
||||
import mage.game.Game;
|
||||
import mage.game.stack.StackObject;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetSpell;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
|
@ -71,28 +68,12 @@ class InvasiveSurgeryEffect extends SearchTargetGraveyardHandLibraryForCardNameA
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller == null) {
|
||||
Spell spell = game.getSpell(getTargetPointer().getFirst(game, source));
|
||||
if (controller == null || spell == null) {
|
||||
return false;
|
||||
}
|
||||
String cardName = "";
|
||||
UUID spellController = null;
|
||||
if (source.getTargets().get(0) instanceof TargetSpell) {
|
||||
UUID objectId = source.getFirstTarget();
|
||||
StackObject stackObject = game.getStack().getStackObject(objectId);
|
||||
if (stackObject != null) {
|
||||
MageObject targetObject = game.getObject(stackObject.getSourceId());
|
||||
if (targetObject instanceof Card) {
|
||||
cardName = targetObject.getName();
|
||||
}
|
||||
spellController = stackObject.getControllerId();
|
||||
game.getStack().counter(objectId, source, game);
|
||||
}
|
||||
}
|
||||
|
||||
// Check the Delirium condition
|
||||
if (!DeliriumCondition.instance.apply(game, source)) {
|
||||
return true;
|
||||
}
|
||||
return this.applySearchAndExile(game, source, cardName, spellController);
|
||||
game.getStack().counter(spell.getId(), source, game);
|
||||
return !DeliriumCondition.instance.apply(game, source)
|
||||
|| this.applySearchAndExile(game, source, spell, spell.getControllerId());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ class MinamosMeddlingCounterTargetEffect extends OneShotEffect {
|
|||
for (SpellAbility spellAbility : spell.getSpellAbilities()) {
|
||||
if (spellAbility.getSpellAbilityType() == SpellAbilityType.SPLICE) {
|
||||
for (Card card : spellController.getHand().getCards(game)) {
|
||||
if (card.getName().equals(spellAbility.getCardName())) {
|
||||
if (card.hasName(spellAbility.getCardName(), game)) {
|
||||
cardsToDiscard.add(card);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package mage.cards.n;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.assignment.common.NameAssignment;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.*;
|
||||
import mage.constants.CardType;
|
||||
|
|
@ -13,9 +14,9 @@ import mage.game.Game;
|
|||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.common.TargetCardInLibrary;
|
||||
import mage.target.common.TargetCardInYourGraveyard;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
|
|
@ -28,7 +29,6 @@ public final class NissasEncouragement extends CardImpl {
|
|||
|
||||
// Search your library and graveyard for a card named Forest, a card named Brambleweft Behemoth, and a card named Nissa, Genesis Mage. Reveal those cards, put them into your hand, then shuffle your library.
|
||||
this.getSpellAbility().addEffect(new NissasEncouragementEffect());
|
||||
|
||||
}
|
||||
|
||||
private NissasEncouragement(final NissasEncouragement card) {
|
||||
|
|
@ -43,16 +43,11 @@ public final class NissasEncouragement extends CardImpl {
|
|||
|
||||
class NissasEncouragementEffect extends OneShotEffect {
|
||||
|
||||
private static final FilterCard filter = new FilterCard("card named Forest, a card named Brambleweft Behemoth, and a card named Nissa, Genesis Mage");
|
||||
private static final FilterCard filterGY = new FilterCard();
|
||||
|
||||
static {
|
||||
filter.add(Predicates.or(new NamePredicate("Forest"), new NamePredicate("Brambleweft Behemoth"), new NamePredicate("Nissa, Genesis Mage")));
|
||||
}
|
||||
|
||||
public NissasEncouragementEffect() {
|
||||
super(Outcome.DrawCard);
|
||||
this.staticText = "Search your library and graveyard for a card named Forest, a card named Brambleweft Behemoth, and a card named Nissa, Genesis Mage. Reveal those cards, put them into your hand, then shuffle.";
|
||||
this.staticText = "Search your library and graveyard for a card named Forest, " +
|
||||
"a card named Brambleweft Behemoth, and a card named Nissa, Genesis Mage. " +
|
||||
"Reveal those cards, put them into your hand, then shuffle.";
|
||||
}
|
||||
|
||||
private NissasEncouragementEffect(final NissasEncouragementEffect effect) {
|
||||
|
|
@ -67,95 +62,140 @@ class NissasEncouragementEffect extends OneShotEffect {
|
|||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
Card sourceCard = game.getCard(source.getSourceId());
|
||||
if (player == null || sourceCard == null) {
|
||||
if (player == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
NissasEncouragementTarget target = new NissasEncouragementTarget(filter);
|
||||
if (player.searchLibrary(target, source, game)) {
|
||||
boolean searchGY = false;
|
||||
|
||||
if (target.getTargets().size() < 3) {
|
||||
searchGY = true;
|
||||
}
|
||||
|
||||
Map<String, Integer> foundCards = new HashMap<>();
|
||||
foundCards.put("Forest", 0);
|
||||
foundCards.put("Brambleweft Behemoth", 0);
|
||||
foundCards.put("Nissa, Genesis Mage", 0);
|
||||
Cards cards = new CardsImpl();
|
||||
|
||||
if (!target.getTargets().isEmpty()) {
|
||||
for (UUID cardId : target.getTargets()) {
|
||||
Card card = player.getLibrary().remove(cardId, game);
|
||||
|
||||
if (card != null) {
|
||||
cards.add(card);
|
||||
foundCards.put(card.getName(), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (searchGY) {
|
||||
for (String name : foundCards.keySet()) {
|
||||
if (foundCards.get(name) == 1) {
|
||||
continue;
|
||||
}
|
||||
// Look in graveyard for any with this name
|
||||
FilterCard namedFilterGY = filterGY.copy(); // never change static objects so copy the object here before
|
||||
namedFilterGY.add(new NamePredicate(name));
|
||||
if (player.getGraveyard().count(namedFilterGY, game) > 0) {
|
||||
TargetCard targetGY = new TargetCard(0, 1, Zone.GRAVEYARD, namedFilterGY);
|
||||
if (player.choose(Outcome.ReturnToHand, player.getGraveyard(), targetGY, source, game)) {
|
||||
for (UUID cardIdGY : targetGY.getTargets()) {
|
||||
Card cardGY = player.getGraveyard().get(cardIdGY, game);
|
||||
cards.add(cardGY);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!cards.isEmpty()) {
|
||||
player.revealCards(sourceCard.getIdName(), cards, game);
|
||||
player.moveCards(cards, Zone.HAND, source, game);
|
||||
player.shuffleLibrary(source, game);
|
||||
return true;
|
||||
}
|
||||
TargetCardInLibrary target = new NissasEncouragementLibraryTarget();
|
||||
player.searchLibrary(target, source, game);
|
||||
Cards cards = new CardsImpl();
|
||||
for (UUID targetId : target.getTargets()) {
|
||||
cards.add(player.getLibrary().getCard(targetId, game));
|
||||
}
|
||||
if (cards.size() < 3) {
|
||||
TargetCard graveyardTarget = new NissasEncouragementGraveyardTarget(cards);
|
||||
player.choose(outcome, target, source, game);
|
||||
cards.addAll(graveyardTarget.getTargets());
|
||||
}
|
||||
if (!cards.isEmpty()) {
|
||||
player.revealCards(source, cards, game);
|
||||
player.moveCards(cards, Zone.HAND, source, game);
|
||||
}
|
||||
player.shuffleLibrary(source, game);
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class NissasEncouragementTarget extends TargetCardInLibrary {
|
||||
class NissasEncouragementLibraryTarget extends TargetCardInLibrary {
|
||||
|
||||
public NissasEncouragementTarget(FilterCard filter) {
|
||||
private static final FilterCard filter
|
||||
= new FilterCard("card named Forest, a card named Brambleweft Behemoth, and a card named Nissa, Genesis Mage");
|
||||
|
||||
static {
|
||||
filter.add(Predicates.or(
|
||||
new NamePredicate("Forest"),
|
||||
new NamePredicate("Brambleweft Behemoth"),
|
||||
new NamePredicate("Nissa, Genesis Mage")
|
||||
));
|
||||
}
|
||||
|
||||
private static final NameAssignment nameAssigner = new NameAssignment(
|
||||
"Forest", "Brambleweft Behemoth", "Nissa, Genesis Mage"
|
||||
);
|
||||
|
||||
public NissasEncouragementLibraryTarget() {
|
||||
super(0, 3, filter);
|
||||
}
|
||||
|
||||
private NissasEncouragementTarget(final NissasEncouragementTarget target) {
|
||||
private NissasEncouragementLibraryTarget(final NissasEncouragementLibraryTarget target) {
|
||||
super(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NissasEncouragementTarget copy() {
|
||||
return new NissasEncouragementTarget(this);
|
||||
public NissasEncouragementLibraryTarget copy() {
|
||||
return new NissasEncouragementLibraryTarget(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canTarget(UUID playerId, UUID id, Ability source, Cards cards, Game game) {
|
||||
Card card = cards.get(id, game);
|
||||
if (card != null) {
|
||||
for (UUID targetId : this.getTargets()) {
|
||||
Card iCard = game.getCard(targetId);
|
||||
if (iCard != null && iCard.getName().equals(card.getName())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return filter.match(card, playerId, game);
|
||||
public boolean canTarget(UUID playerId, UUID id, Ability source, Game game) {
|
||||
if (!super.canTarget(playerId, id, source, game)) {
|
||||
return false;
|
||||
}
|
||||
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 nameAssigner.getRoleCount(cards, game) >= cards.size();
|
||||
}
|
||||
}
|
||||
|
||||
class NissasEncouragementGraveyardTarget extends TargetCardInYourGraveyard {
|
||||
|
||||
private static final FilterCard filter
|
||||
= new FilterCard("card named Forest, a card named Brambleweft Behemoth, and a card named Nissa, Genesis Mage");
|
||||
|
||||
static {
|
||||
filter.add(Predicates.or(
|
||||
new NamePredicate("Forest"),
|
||||
new NamePredicate("Brambleweft Behemoth"),
|
||||
new NamePredicate("Nissa, Genesis Mage")
|
||||
));
|
||||
}
|
||||
|
||||
private final Cards cardsAlreadyFound = new CardsImpl();
|
||||
private static final NameAssignment nameAssigner = new NameAssignment(
|
||||
"Forest", "Brambleweft Behemoth", "Nissa, Genesis Mage"
|
||||
);
|
||||
|
||||
public NissasEncouragementGraveyardTarget(Cards cardsAlreadyFound) {
|
||||
super(0, 3, filter, true);
|
||||
this.cardsAlreadyFound.addAll(cardsAlreadyFound);
|
||||
}
|
||||
|
||||
private NissasEncouragementGraveyardTarget(final NissasEncouragementGraveyardTarget target) {
|
||||
super(target);
|
||||
this.cardsAlreadyFound.addAll(target.cardsAlreadyFound);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NissasEncouragementGraveyardTarget copy() {
|
||||
return new NissasEncouragementGraveyardTarget(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.addAll(this.cardsAlreadyFound);
|
||||
cards.add(card);
|
||||
return nameAssigner.getRoleCount(cards, game) >= cards.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> possibleTargets(UUID sourceControllerId, Ability source, Game game) {
|
||||
Set<UUID> possibleTargets = super.possibleTargets(sourceControllerId, source, game);
|
||||
if (this.getTargets().isEmpty()) {
|
||||
return possibleTargets;
|
||||
}
|
||||
possibleTargets.removeIf(uuid -> {
|
||||
Cards cards = new CardsImpl(this.getTargets());
|
||||
cards.addAll(this.cardsAlreadyFound);
|
||||
cards.add(game.getCard(uuid));
|
||||
return nameAssigner.getRoleCount(cards, game) < cards.size();
|
||||
});
|
||||
return possibleTargets;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
package mage.cards.p;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.Mode;
|
||||
import mage.abilities.condition.common.DeliriumCondition;
|
||||
import mage.abilities.effects.common.search.SearchTargetGraveyardHandLibraryForCardNameAndExileEffect;
|
||||
import mage.abilities.hint.common.CardTypesInGraveyardHint;
|
||||
|
|
@ -19,6 +16,8 @@ import mage.players.Player;
|
|||
import mage.target.TargetCard;
|
||||
import mage.target.common.TargetOpponent;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* @author escplan9 (Derek Monturo - dmontur1 at gmail dot com)
|
||||
*/
|
||||
|
|
@ -65,26 +64,21 @@ class PickTheBrainEffect extends SearchTargetGraveyardHandLibraryForCardNameAndE
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player opponent = game.getPlayer(this.getTargetPointer().getFirst(game, source));
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (opponent != null && controller != null) {
|
||||
if (!opponent.getHand().isEmpty()) {
|
||||
opponent.revealCards("Exile " + StaticFilters.FILTER_CARD_A_NON_LAND.getMessage(), opponent.getHand(), game);
|
||||
TargetCard target = new TargetCard(Zone.HAND, StaticFilters.FILTER_CARD_A_NON_LAND);
|
||||
if (controller.choose(Outcome.Exile, opponent.getHand(), target, source, game)) {
|
||||
Card card = opponent.getHand().get(target.getFirstTarget(), game);
|
||||
if (card != null) {
|
||||
controller.moveCardToExileWithInfo(card, null, "", source, game, Zone.HAND, true);
|
||||
|
||||
// Check the Delirium condition
|
||||
if (!DeliriumCondition.instance.apply(game, source)) {
|
||||
return true;
|
||||
}
|
||||
return this.applySearchAndExile(game, source, card.getName(), opponent.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
Player opponent = game.getPlayer(this.getTargetPointer().getFirst(game, source));
|
||||
if (controller == null || opponent == null || opponent.getHand().isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
opponent.revealCards("Exile " + StaticFilters.FILTER_CARD_A_NON_LAND.getMessage(), opponent.getHand(), game);
|
||||
TargetCard target = new TargetCard(Zone.HAND, StaticFilters.FILTER_CARD_A_NON_LAND);
|
||||
controller.choose(Outcome.Exile, opponent.getHand(), target, source, game);
|
||||
Card card = opponent.getHand().get(target.getFirstTarget(), game);
|
||||
if (card == null) {
|
||||
return false;
|
||||
}
|
||||
controller.moveCards(card, Zone.EXILED, source, game);
|
||||
// Check the Delirium condition
|
||||
return !DeliriumCondition.instance.apply(game, source)
|
||||
|| this.applySearchAndExile(game, source, card, opponent.getId());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,6 +65,6 @@ enum PompousGadaboutPredicate implements Predicate<Permanent> {
|
|||
|
||||
@Override
|
||||
public boolean apply(Permanent input, Game game) {
|
||||
return input.getName() == null || input.getName().isEmpty();
|
||||
return input.hasNoName(game);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
package mage.cards.s;
|
||||
|
||||
import com.google.common.base.Functions;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.condition.Condition;
|
||||
import mage.abilities.costs.common.TapSourceCost;
|
||||
|
|
@ -15,9 +13,12 @@ import mage.constants.SuperType;
|
|||
import mage.constants.Zone;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.util.RandomUtil;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author TheElk801
|
||||
|
|
@ -54,22 +55,25 @@ enum SceptreOfEternalGloryCondition implements Condition {
|
|||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
return game
|
||||
.getBattlefield()
|
||||
.getActivePermanents(
|
||||
StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND,
|
||||
source.getControllerId(), source, game
|
||||
)
|
||||
.stream()
|
||||
.map(MageObject::getName)
|
||||
.filter(s -> !s.isEmpty())
|
||||
.collect(Collectors.toMap(
|
||||
Functions.identity(),
|
||||
x -> 1, Integer::sum
|
||||
))
|
||||
.values()
|
||||
.stream()
|
||||
.anyMatch(x -> x >= 3);
|
||||
Set<Permanent> lands = new HashSet<>(game.getBattlefield().getActivePermanents(
|
||||
StaticFilters.FILTER_CONTROLLED_PERMANENT_LAND,
|
||||
source.getControllerId(), source, game
|
||||
));
|
||||
while (lands.size() >= 3) {
|
||||
Permanent land = RandomUtil.randomFromCollection(lands);
|
||||
lands.remove(land);
|
||||
int amount = 0;
|
||||
for (Permanent permanent : lands) {
|
||||
if (!permanent.sharesName(land, game)) {
|
||||
continue;
|
||||
}
|
||||
amount++;
|
||||
if (amount >= 3) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -1,29 +1,32 @@
|
|||
package mage.cards.s;
|
||||
|
||||
import mage.MageItem;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.TriggeredAbilityImpl;
|
||||
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
import mage.abilities.effects.common.ExileTargetCardCopyAndCastEffect;
|
||||
import mage.abilities.effects.common.ExileTargetForSourceEffect;
|
||||
import mage.cards.*;
|
||||
import mage.constants.AbilityWord;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Outcome;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.StaticFilters;
|
||||
import mage.game.ExileZone;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.stack.Spell;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
import mage.target.common.TargetCardInASingleGraveyard;
|
||||
import mage.target.common.TargetCardInExile;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
import mage.util.CardUtil;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.ApprovingObject;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author emerald000
|
||||
|
|
@ -40,7 +43,7 @@ public final class SpellweaverHelix extends CardImpl {
|
|||
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{3}");
|
||||
|
||||
// Imprint - When Spellweaver Helix enters the battlefield, you may exile two target sorcery cards from a single graveyard.
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(new SpellweaverHelixImprintEffect(), true);
|
||||
Ability ability = new EntersBattlefieldTriggeredAbility(new ExileTargetForSourceEffect(), true);
|
||||
ability.addTarget(new TargetCardInASingleGraveyard(2, 2, filter));
|
||||
ability.setAbilityWord(AbilityWord.IMPRINT);
|
||||
this.addAbility(ability);
|
||||
|
|
@ -59,42 +62,6 @@ public final class SpellweaverHelix extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
class SpellweaverHelixImprintEffect extends OneShotEffect {
|
||||
|
||||
SpellweaverHelixImprintEffect() {
|
||||
super(Outcome.Exile);
|
||||
this.staticText = "you may exile two target sorcery cards from a single graveyard";
|
||||
}
|
||||
|
||||
private SpellweaverHelixImprintEffect(final SpellweaverHelixImprintEffect effect) {
|
||||
super(effect);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpellweaverHelixImprintEffect copy() {
|
||||
return new SpellweaverHelixImprintEffect(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
|
||||
for (UUID targetId : this.getTargetPointer().getTargets(game, source)) {
|
||||
Card card = game.getCard(targetId);
|
||||
if (card != null) {
|
||||
controller.moveCardsToExile(card, source, game, true, CardUtil.getExileZoneId(game, source.getSourceId(), source.getSourceObjectZoneChangeCounter()), source.getSourceObject(game).getIdName());
|
||||
if (sourcePermanent != null) {
|
||||
sourcePermanent.imprint(targetId, game);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class SpellweaverHelixTriggeredAbility extends TriggeredAbilityImpl {
|
||||
|
||||
SpellweaverHelixTriggeredAbility() {
|
||||
|
|
@ -118,44 +85,41 @@ class SpellweaverHelixTriggeredAbility extends TriggeredAbilityImpl {
|
|||
@Override
|
||||
public boolean checkTrigger(GameEvent event, Game game) {
|
||||
Spell spell = game.getStack().getSpell(event.getTargetId());
|
||||
if (spell != null && spell.getCard() != null && !spell.getCard().isCopy()) {
|
||||
for (Effect effect : this.getEffects()) {
|
||||
effect.setTargetPointer(new FixedTarget(spell.getId()));
|
||||
}
|
||||
return true;
|
||||
if (spell == null || spell.getCard() == null || spell.getCard().isCopy()) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
this.getEffects().setValue("spellCast", spell);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkInterveningIfClause(Game game) {
|
||||
Spell spell = game.getStack().getSpell(this.getEffects().get(0).getTargetPointer().getFirst(game, this));
|
||||
if (spell != null) {
|
||||
String spellName = spell.getName();
|
||||
Permanent sourcePermanent = game.getPermanent(this.getSourceId());
|
||||
if (sourcePermanent != null) {
|
||||
for (UUID imprintId : sourcePermanent.getImprinted()) {
|
||||
Card card = game.getCard(imprintId);
|
||||
if (card != null && card.getName().equals(spellName)) {
|
||||
((SpellweaverHelixCastEffect) this.getEffects().get(0)).setSpellName(spellName);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
Spell spell = this
|
||||
.getEffects()
|
||||
.stream()
|
||||
.map(effect -> (Spell) effect.getValue("spellCast"))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
return spell != null
|
||||
&& Optional.ofNullable(game)
|
||||
.map(Game::getExile)
|
||||
.map(exile -> exile.getExileZone(CardUtil.getExileZoneId(game, this)))
|
||||
.filter(Objects::nonNull)
|
||||
.map(e -> e.getCards(game))
|
||||
.map(Collection::stream)
|
||||
.map(s -> s.anyMatch(card -> card.sharesName(spell, game)))
|
||||
.orElse(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Whenever a player casts a card, if it has the same name as one of the cards exiled with Spellweaver Helix, you may copy the other. If you do, you may cast the copy without paying its mana cost.";
|
||||
return "Whenever a player casts a card, if it has the same name as one of the cards exiled with {this}, " +
|
||||
"you may copy the other. If you do, you may cast the copy without paying its mana cost.";
|
||||
}
|
||||
}
|
||||
|
||||
class SpellweaverHelixCastEffect extends OneShotEffect {
|
||||
|
||||
private String spellName = "";
|
||||
|
||||
SpellweaverHelixCastEffect() {
|
||||
super(Outcome.Benefit);
|
||||
this.staticText = "you may copy the other. If you do, you may cast the copy without paying its mana cost";
|
||||
|
|
@ -163,7 +127,6 @@ class SpellweaverHelixCastEffect extends OneShotEffect {
|
|||
|
||||
private SpellweaverHelixCastEffect(final SpellweaverHelixCastEffect effect) {
|
||||
super(effect);
|
||||
this.spellName = effect.spellName;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -171,38 +134,39 @@ class SpellweaverHelixCastEffect extends OneShotEffect {
|
|||
return new SpellweaverHelixCastEffect(this);
|
||||
}
|
||||
|
||||
public void setSpellName(String spellName) {
|
||||
this.spellName = spellName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(Game game, Ability source) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (controller != null) {
|
||||
Permanent sourcePermanent = game.getPermanentOrLKIBattlefield(source.getSourceId());
|
||||
if (sourcePermanent != null) {
|
||||
boolean foundSpellWithSameName = false;
|
||||
for (UUID imprintId : sourcePermanent.getImprinted()) {
|
||||
Card card = game.getCard(imprintId);
|
||||
if (card != null) {
|
||||
if (!foundSpellWithSameName && card.getName().equals(spellName)) {
|
||||
foundSpellWithSameName = true;
|
||||
} else {
|
||||
if (controller.chooseUse(Outcome.Copy, "Copy " + card.getIdName(), source, game)) {
|
||||
Card copy = game.copyCard(card, source, source.getControllerId());
|
||||
if (controller.chooseUse(Outcome.PlayForFree, "Cast " + copy.getIdName() + " without paying its mana cost?", source, game)) {
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + copy.getId(), Boolean.TRUE);
|
||||
controller.cast(controller.chooseAbilityForCast(copy, game, true),
|
||||
game, true, new ApprovingObject(source, game));
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + copy.getId(), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
Player player = game.getPlayer(source.getControllerId());
|
||||
Spell spell = (Spell) getValue("spellCast");
|
||||
ExileZone exileZone = game.getExile().getExileZone(CardUtil.getExileZoneId(game, source));
|
||||
if (player == null || spell == null || exileZone == null || exileZone.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
Cards cards = new CardsImpl(exileZone);
|
||||
Set<UUID> matching = exileZone
|
||||
.getCards(game)
|
||||
.stream()
|
||||
.filter(card -> card.sharesName(spell, game))
|
||||
.map(MageItem::getId)
|
||||
.collect(Collectors.toSet());
|
||||
if (matching.size() < 2) { // If two or more cards match then all cards are valid choices
|
||||
cards.removeAll(matching);
|
||||
}
|
||||
Card card;
|
||||
switch (cards.size()) {
|
||||
case 0:
|
||||
return false;
|
||||
case 1:
|
||||
card = cards.getRandom(game);
|
||||
break;
|
||||
default:
|
||||
TargetCard target = new TargetCardInExile(0, 1, StaticFilters.FILTER_CARD);
|
||||
player.choose(outcome, cards, target, source, game);
|
||||
card = cards.get(target.getFirstTarget(), game);
|
||||
}
|
||||
return card != null
|
||||
&& new ExileTargetCardCopyAndCastEffect(true, true)
|
||||
.setTargetPointer(new FixedTarget(card, game))
|
||||
.apply(game, source);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import org.junit.Test;
|
|||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author noxx
|
||||
*/
|
||||
public class ProteanHydraTest extends CardTestPlayerBase {
|
||||
|
|
@ -31,7 +30,7 @@ public class ProteanHydraTest extends CardTestPlayerBase {
|
|||
assertLife(playerB, 20);
|
||||
|
||||
for (Permanent permanent : currentGame.getBattlefield().getAllPermanents()) {
|
||||
if (permanent.getName().equals("Forest")) {
|
||||
if (permanent.hasName("Forest", currentGame)) {
|
||||
// check all mana was spent
|
||||
Assert.assertTrue(permanent.isTapped());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ public class DisguiseTest extends CardTestPlayerBase {
|
|||
.findFirst()
|
||||
.orElse(null);
|
||||
Assert.assertNotNull("server side: can't find disguised permanent", permanent);
|
||||
Assert.assertEquals("server side: wrong name", EmptyNames.FACE_DOWN_CREATURE.toString(), permanent.getName());
|
||||
Assert.assertTrue("server side: wrong name", permanent.hasNoName(currentGame));
|
||||
Assert.assertEquals("server side: wrong color", "", permanent.getColor(currentGame).toString());
|
||||
Assert.assertEquals("server side: wrong power", "2", permanent.getPower().toString());
|
||||
Assert.assertEquals("server side: wrong toughness", "2", permanent.getToughness().toString());
|
||||
|
|
@ -150,11 +150,11 @@ public class DisguiseTest extends CardTestPlayerBase {
|
|||
runCode("after face up", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, (info, player, game) -> {
|
||||
Permanent permanent = currentGame.getBattlefield().getAllPermanents()
|
||||
.stream()
|
||||
.filter(p -> p.getName().equals("Dog Walker"))
|
||||
.filter(p -> p.hasName("Dog Walker", game))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
Assert.assertNotNull("server side: can't find normal permanent", permanent);
|
||||
Assert.assertEquals("server side: wrong name", "Dog Walker", permanent.getName());
|
||||
Assert.assertTrue("server side: wrong name", permanent.hasName("Dog Walker", currentGame));
|
||||
Assert.assertEquals("server side: wrong color", "WR", permanent.getColor(currentGame).toString());
|
||||
Assert.assertEquals("server side: wrong power", "3", permanent.getPower().toString());
|
||||
Assert.assertEquals("server side: wrong toughness", "1", permanent.getToughness().toString());
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@ public class DisturbTest extends CardTestPlayerBase {
|
|||
|
||||
/**
|
||||
* Relevant ruling:
|
||||
* - When you cast a spell using a card's disturb ability, the card is put onto the stack with its
|
||||
* back face up. The resulting spell has all the characteristics of that face.
|
||||
* - The mana value of a spell cast using disturb is determined by the mana cost on the
|
||||
* front face of the card, no matter what the total cost to cast the spell was.
|
||||
* - When you cast a spell using a card's disturb ability, the card is put onto the stack with its
|
||||
* back face up. The resulting spell has all the characteristics of that face.
|
||||
* - The mana value of a spell cast using disturb is determined by the mana cost on the
|
||||
* front face of the card, no matter what the total cost to cast the spell was.
|
||||
*/
|
||||
@Test
|
||||
public void test_SpellAttributesOnStack() {
|
||||
|
|
@ -41,7 +41,7 @@ public class DisturbTest extends CardTestPlayerBase {
|
|||
runCode("check stack", 1, PhaseStep.PRECOMBAT_MAIN, playerA, (info, player, game) -> {
|
||||
// Stack must contain another card side, so spell/card characteristics must be diff from main side (only mana value is same)
|
||||
Spell spell = (Spell) game.getStack().getFirst();
|
||||
Assert.assertEquals("Hook-Haunt Drifter", spell.getName());
|
||||
Assert.assertTrue(spell.hasName("Hook-Haunt Drifter", currentGame));
|
||||
Assert.assertEquals(1, spell.getCardType(game).size());
|
||||
Assert.assertEquals(CardType.CREATURE, spell.getCardType(game).get(0));
|
||||
Assert.assertEquals(1, spell.getSubtype(game).size());
|
||||
|
|
@ -92,7 +92,7 @@ public class DisturbTest extends CardTestPlayerBase {
|
|||
runCode("check stack", 1, PhaseStep.PRECOMBAT_MAIN, playerA, (info, player, game) -> {
|
||||
// Stack must contain another card side, so spell/card characteristics must be diff from main side (only mana value is same)
|
||||
Spell spell = (Spell) game.getStack().getFirst();
|
||||
Assert.assertEquals("Waildrifter", spell.getName());
|
||||
Assert.assertTrue(spell.hasName("Waildrifter", currentGame));
|
||||
Assert.assertEquals(1, spell.getCardType(game).size());
|
||||
Assert.assertEquals(CardType.CREATURE, spell.getCardType(game).get(0));
|
||||
Assert.assertEquals(2, spell.getSubtype(game).size());
|
||||
|
|
@ -122,7 +122,7 @@ public class DisturbTest extends CardTestPlayerBase {
|
|||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertTappedCount("Volcanic Island",true,6); //5+1
|
||||
assertTappedCount("Volcanic Island", true, 6); //5+1
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -133,7 +133,7 @@ public class DisturbTest extends CardTestPlayerBase {
|
|||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 7);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Firebrand Archer", 1);
|
||||
//
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Sinner's Judgment using Disturb",playerB);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Sinner's Judgment using Disturb", playerB);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
|
|
@ -163,12 +163,12 @@ public class DisturbTest extends CardTestPlayerBase {
|
|||
|
||||
/**
|
||||
* Relevant ruling:
|
||||
* To determine the total cost of a spell, start with the mana cost or alternative cost
|
||||
* (such as a disturb cost) you're paying, add any cost increases, then apply any cost
|
||||
* reductions. The mana value of a spell cast using disturb is determined by the mana cost on
|
||||
* the front face of the card, no matter what the total cost to cast the spell was. (This is
|
||||
* a special rule that applies only to transforming double faced-cards, including ones with
|
||||
* disturb.)
|
||||
* To determine the total cost of a spell, start with the mana cost or alternative cost
|
||||
* (such as a disturb cost) you're paying, add any cost increases, then apply any cost
|
||||
* reductions. The mana value of a spell cast using disturb is determined by the mana cost on
|
||||
* the front face of the card, no matter what the total cost to cast the spell was. (This is
|
||||
* a special rule that applies only to transforming double faced-cards, including ones with
|
||||
* disturb.)
|
||||
*/
|
||||
@Test
|
||||
public void test_CostModification_CanPlay() {
|
||||
|
|
@ -230,7 +230,7 @@ public class DisturbTest extends CardTestPlayerBase {
|
|||
//net -2
|
||||
|
||||
//
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Sinner's Judgment using Disturb",playerB);
|
||||
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Sinner's Judgment using Disturb", playerB);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
|
|
@ -262,8 +262,8 @@ public class DisturbTest extends CardTestPlayerBase {
|
|||
|
||||
/**
|
||||
* Relevant rule:
|
||||
* If you copy a permanent spell cast this way (perhaps with a card like Double Major), the copy becomes
|
||||
* a token that's a copy of the card's back face, even though it isn't itself a double-faced card.
|
||||
* If you copy a permanent spell cast this way (perhaps with a card like Double Major), the copy becomes
|
||||
* a token that's a copy of the card's back face, even though it isn't itself a double-faced card.
|
||||
*/
|
||||
@Test
|
||||
public void test_CopySpell() {
|
||||
|
|
@ -297,10 +297,10 @@ public class DisturbTest extends CardTestPlayerBase {
|
|||
|
||||
/**
|
||||
* Relevant ruling:
|
||||
* The back face of each card with disturb has an ability that instructs its controller to exile
|
||||
* if it would be put into a graveyard from anywhere. This includes going to the graveyard from the
|
||||
* stack, so if the spell is countered after you cast it using the disturb ability, it will
|
||||
* be put into exile.
|
||||
* The back face of each card with disturb has an ability that instructs its controller to exile
|
||||
* if it would be put into a graveyard from anywhere. This includes going to the graveyard from the
|
||||
* stack, so if the spell is countered after you cast it using the disturb ability, it will
|
||||
* be put into exile.
|
||||
*/
|
||||
@Test
|
||||
public void test_Counter() {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import org.junit.Test;
|
|||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward
|
||||
*/
|
||||
public class HauntTest extends CardTestPlayerBase {
|
||||
|
|
@ -21,13 +20,12 @@ public class HauntTest extends CardTestPlayerBase {
|
|||
* Flying
|
||||
* Haunt (When this creature dies, exile it haunting target creature.)
|
||||
* When Blind Hunter enters the battlefield or the creature it haunts dies, target player loses 2 life and you gain 2 life.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
// test that Haunting and Haunted by rules are added to cards
|
||||
@Test
|
||||
public void testAddHaunt() {
|
||||
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Blind Hunter", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Goblin Roughrider");
|
||||
addCard(Zone.HAND, playerA, "Lightning Bolt", 1);
|
||||
|
|
@ -40,12 +38,12 @@ public class HauntTest extends CardTestPlayerBase {
|
|||
|
||||
assertGraveyardCount(playerA, "Lightning Bolt", 1);
|
||||
assertExileCount("Blind Hunter", 1);
|
||||
|
||||
|
||||
boolean found = false;
|
||||
for (Card card : currentGame.getExile().getAllCards(currentGame)) {
|
||||
if (card.getName().equals("Blind Hunter")) {
|
||||
if (card.hasName("Blind Hunter", currentGame)) {
|
||||
for (String rule : card.getRules(currentGame)) {
|
||||
if (rule.startsWith("Haunting") && rule.contains("Goblin Roughrider")) {
|
||||
if (rule.startsWith("Haunting") && rule.contains("Goblin Roughrider")) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -56,7 +54,7 @@ public class HauntTest extends CardTestPlayerBase {
|
|||
|
||||
found = false;
|
||||
for (Card card : currentGame.getBattlefield().getAllActivePermanents()) {
|
||||
if (card.getName().equals("Goblin Roughrider")) {
|
||||
if (card.hasName("Goblin Roughrider", currentGame)) {
|
||||
for (String rule : card.getRules(currentGame)) {
|
||||
if (rule.startsWith("Haunted by") && rule.contains("Blind Hunter")) {
|
||||
found = true;
|
||||
|
|
@ -66,13 +64,13 @@ public class HauntTest extends CardTestPlayerBase {
|
|||
}
|
||||
}
|
||||
Assert.assertTrue("Couldn't find Haunted by rule text displayed for the card", found);
|
||||
|
||||
|
||||
}
|
||||
|
||||
// test that Haunted by rule is removed from cards (it is only added to permanent)
|
||||
@Test
|
||||
public void testRemoveHaunt() {
|
||||
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Blind Hunter", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Goblin Roughrider");
|
||||
addCard(Zone.HAND, playerA, "Lightning Bolt", 2);
|
||||
|
|
@ -91,7 +89,7 @@ public class HauntTest extends CardTestPlayerBase {
|
|||
|
||||
boolean found = false;
|
||||
for (Card card : currentGame.getPlayer(playerA.getId()).getGraveyard().getCards(currentGame)) {
|
||||
if (card.getName().equals("Goblin Roughrider")) {
|
||||
if (card.hasName("Goblin Roughrider", currentGame)) {
|
||||
for (String rule : card.getRules(currentGame)) {
|
||||
if (rule.startsWith("Haunted by") && rule.contains("Blind Hunter")) {
|
||||
found = true;
|
||||
|
|
@ -101,7 +99,7 @@ public class HauntTest extends CardTestPlayerBase {
|
|||
}
|
||||
}
|
||||
Assert.assertFalse("Found Haunted by rule text displayed for the card", found);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -122,5 +120,5 @@ public class HauntTest extends CardTestPlayerBase {
|
|||
assertExileCount("Blind Hunter", 1);
|
||||
assertLife(playerA, 22);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package org.mage.test.cards.abilities.keywords;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.repository.TokenRepository;
|
||||
import mage.constants.EmptyNames;
|
||||
|
|
@ -149,14 +148,14 @@ public class ManifestTest extends CardTestPlayerBase {
|
|||
Assert.assertEquals("after blink card must keep in exile",
|
||||
1, currentGame.getExile().getAllCardsByRange(currentGame, playerA.getId()).size());
|
||||
} else {
|
||||
String realPermanentName = currentGame.getBattlefield().getAllPermanents()
|
||||
Permanent realPermanent = currentGame
|
||||
.getBattlefield()
|
||||
.getAllPermanents()
|
||||
.stream()
|
||||
.map(MageObject::getName)
|
||||
.filter(name -> name.equals(cardAfterBlink))
|
||||
.filter(permanent -> permanent.hasName(cardAfterBlink, currentGame))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
Assert.assertEquals("after blink card must go to battlefield",
|
||||
cardAfterBlink, realPermanentName);
|
||||
Assert.assertNotNull("after blink card must go to battlefield", realPermanent);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -428,8 +427,8 @@ public class ManifestTest extends CardTestPlayerBase {
|
|||
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 0);
|
||||
|
||||
for (Card card : currentGame.getExile().getAllCards(currentGame)) {
|
||||
if (card.getName().equals("Gore Swine")) {
|
||||
Assert.assertTrue("Gore Swine may not be face down in exile", !card.isFaceDown(currentGame));
|
||||
if (card.hasName("Gore Swine", currentGame)) {
|
||||
Assert.assertFalse("Gore Swine may not be face down in exile", card.isFaceDown(currentGame));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -731,7 +730,7 @@ public class ManifestTest extends CardTestPlayerBase {
|
|||
.stream()
|
||||
.filter(permanent -> permanent.isFaceDown(game))
|
||||
.filter(permanent -> {
|
||||
Assert.assertEquals("face down permanent must have not name", "", permanent.getName());
|
||||
Assert.assertTrue("face down permanent must have not name", permanent.hasNoName(currentGame));
|
||||
// TODO: buggy, manifested card must have some rules
|
||||
//Assert.assertTrue("face down permanent must have abilities", permanent.getAbilities().size() > 0);
|
||||
return true;
|
||||
|
|
@ -739,7 +738,7 @@ public class ManifestTest extends CardTestPlayerBase {
|
|||
.findFirst()
|
||||
.orElse(null);
|
||||
Assert.assertNotNull(perm);
|
||||
Assert.assertEquals("server side face down permanent must have empty name", EmptyNames.FACE_DOWN_CREATURE.toString(), perm.getName());
|
||||
Assert.assertTrue("server side face down permanent must have empty name", perm.hasNoName(currentGame));
|
||||
GameView gameView = new GameView(game.getState(), game, viewFromPlayer.getId(), null);
|
||||
PlayerView playerView = gameView.getPlayers()
|
||||
.stream()
|
||||
|
|
@ -836,8 +835,8 @@ public class ManifestTest extends CardTestPlayerBase {
|
|||
|
||||
attack(1, playerA, infiltrator, playerB);
|
||||
|
||||
checkPlayableAbility("missionary manifest",1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{1}{W}: Turn ", true);
|
||||
checkPlayableAbility("infiltrator manifest",1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{2}{U}: Turn ", true);
|
||||
checkPlayableAbility("missionary manifest", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{1}{W}: Turn ", true);
|
||||
checkPlayableAbility("infiltrator manifest", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{2}{U}: Turn ", true);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
|
|
|
|||
|
|
@ -422,7 +422,7 @@ public class MorphTest extends CardTestPlayerBase {
|
|||
assertExileCount("Birchlore Rangers", 1);
|
||||
|
||||
for (Card card : currentGame.getExile().getAllCards(currentGame)) {
|
||||
if (card.getName().equals("Birchlore Rangers")) {
|
||||
if (card.hasName("Birchlore Rangers", currentGame)) {
|
||||
Assert.assertFalse("Birchlore Rangers has to be face up in exile", card.isFaceDown(currentGame));
|
||||
break;
|
||||
}
|
||||
|
|
@ -461,7 +461,7 @@ public class MorphTest extends CardTestPlayerBase {
|
|||
assertGraveyardCount(playerA, "Ashcloud Phoenix", 1);
|
||||
|
||||
for (Card card : playerA.getGraveyard().getCards(currentGame)) {
|
||||
if (card.getName().equals("Ashcloud Phoenix")) {
|
||||
if (card.hasName("Ashcloud Phoenix", currentGame)) {
|
||||
Assert.assertFalse("Ashcloud Phoenix has to be face up in graveyard", card.isFaceDown(currentGame));
|
||||
break;
|
||||
}
|
||||
|
|
@ -497,7 +497,7 @@ public class MorphTest extends CardTestPlayerBase {
|
|||
assertGraveyardCount(playerA, "Ashcloud Phoenix", 1);
|
||||
|
||||
for (Card card : playerA.getGraveyard().getCards(currentGame)) {
|
||||
if (card.getName().equals("Ashcloud Phoenix")) {
|
||||
if (card.hasName("Ashcloud Phoenix", currentGame)) {
|
||||
Assert.assertFalse("Ashcloud Phoenix has to be face up in graveyard", card.isFaceDown(currentGame));
|
||||
break;
|
||||
}
|
||||
|
|
@ -1236,7 +1236,7 @@ public class MorphTest extends CardTestPlayerBase {
|
|||
.findFirst()
|
||||
.orElse(null);
|
||||
Assert.assertNotNull(info + ", server side: can't find morphed permanent", permanent);
|
||||
Assert.assertEquals(info + ", server side: wrong name", EmptyNames.FACE_DOWN_CREATURE.toString(), permanent.getName());
|
||||
Assert.assertTrue(info + ", server side: wrong name", permanent.hasNoName(currentGame));
|
||||
Assert.assertEquals(info + ", server side: wrong color", needColor, permanent.getColor(currentGame).toString());
|
||||
|
||||
// client side - controller
|
||||
|
|
@ -1299,7 +1299,7 @@ public class MorphTest extends CardTestPlayerBase {
|
|||
public void test_Morph_HoodedHydra() {
|
||||
// Morph {2}
|
||||
addCard(Zone.HAND, playerA, "Hooded Hydra");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3+5);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3 + 5);
|
||||
|
||||
// prepare face down
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Hooded Hydra using Morph");
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ public class OffspringTest extends CardTestPlayerBase {
|
|||
|
||||
private Permanent getCreature(String name, boolean isToken) {
|
||||
for (Permanent permanent : currentGame.getBattlefield().getActivePermanents(playerA.getId(), currentGame)) {
|
||||
if (name.equals(permanent.getName()) && (permanent instanceof PermanentToken) == isToken) {
|
||||
if (permanent.hasName(name, currentGame) && (permanent instanceof PermanentToken) == isToken) {
|
||||
return permanent;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ public class PoisonousTest extends CardTestPlayerBase {
|
|||
int permanentCount = 0;
|
||||
Permanent found = null;
|
||||
for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents(player.getId())) {
|
||||
if (permanent.getName().equals(cardName)) {
|
||||
if (permanent.hasName(cardName, currentGame)) {
|
||||
found = permanent;
|
||||
permanentCount++;
|
||||
}
|
||||
|
|
@ -46,8 +46,6 @@ public class PoisonousTest extends CardTestPlayerBase {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testNormalCombatDamageIsDealt() {
|
||||
// Virulent Sliver gives all slivers Poisonous 1
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ public class PrototypeTest extends CardTestPlayerBase {
|
|||
// Prototype {2}{R} - 3/2
|
||||
private static final String automaton = "Blitz Automaton";
|
||||
private static final String withPrototype = " using Prototype";
|
||||
private static final String automatonWithPrototype = automaton+withPrototype;
|
||||
private static final String automatonWithPrototype = automaton + withPrototype;
|
||||
|
||||
private static final String bolt = "Lightning Bolt";
|
||||
private static final String cloudshift = "Cloudshift";
|
||||
|
|
@ -44,7 +44,7 @@ public class PrototypeTest extends CardTestPlayerBase {
|
|||
for (Permanent permanent : currentGame.getBattlefield().getActivePermanents(
|
||||
StaticFilters.FILTER_PERMANENT, playerA.getId(), currentGame
|
||||
)) {
|
||||
if (!permanent.getName().equals(automaton)) {
|
||||
if (!permanent.hasName(automaton, currentGame)) {
|
||||
continue;
|
||||
}
|
||||
Assert.assertTrue("Needs haste", permanent.getAbilities(currentGame).contains(HasteAbility.getInstance()));
|
||||
|
|
@ -120,7 +120,7 @@ public class PrototypeTest extends CardTestPlayerBase {
|
|||
.getGraveyard()
|
||||
.getCards(currentGame)
|
||||
.stream()
|
||||
.filter(c -> c.getName().equals(automaton))
|
||||
.filter(c -> c.hasName(automaton, currentGame))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
Assert.assertTrue("Card should be colorless", card.getColor(currentGame).isColorless());
|
||||
|
|
@ -452,9 +452,9 @@ public class PrototypeTest extends CardTestPlayerBase {
|
|||
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Taiga");
|
||||
|
||||
//checkPlayableAbility("cast even proto", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Cast Boulderbranch Golem"+withPrototype, false);
|
||||
checkPlayableAbility("cast odd proto", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Cast Fallaji Dragon Engine"+withPrototype, true);
|
||||
checkPlayableAbility("cast odd proto", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Cast Fallaji Dragon Engine" + withPrototype, true);
|
||||
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, evenRegOddProto+withPrototype);
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, evenRegOddProto + withPrototype);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
setStrictChooseMode(true);
|
||||
|
|
@ -462,9 +462,10 @@ public class PrototypeTest extends CardTestPlayerBase {
|
|||
|
||||
assertPowerToughness(playerA, evenRegOddProto, 1, 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCopyOnStack() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Frontier Bivouac", 3+2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Frontier Bivouac", 3 + 2);
|
||||
addCard(Zone.HAND, playerA, automaton);
|
||||
addCard(Zone.HAND, playerA, "Double Major");
|
||||
|
||||
|
|
@ -477,9 +478,10 @@ public class PrototypeTest extends CardTestPlayerBase {
|
|||
|
||||
checkAutomaton(true, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHumility() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plateau", 4+3+2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plateau", 4 + 3 + 2);
|
||||
addCard(Zone.HAND, playerA, automaton);
|
||||
addCard(Zone.HAND, playerA, "Humility");
|
||||
addCard(Zone.HAND, playerA, "Disenchant");
|
||||
|
|
@ -498,6 +500,7 @@ public class PrototypeTest extends CardTestPlayerBase {
|
|||
|
||||
checkAutomaton(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testColorCostReduction() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
|
||||
|
|
@ -513,6 +516,7 @@ public class PrototypeTest extends CardTestPlayerBase {
|
|||
checkAutomaton(true);
|
||||
assertTappedCount("Mountain", true, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAbilityRemovalPre() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Volcanic Island", 5);
|
||||
|
|
@ -528,6 +532,7 @@ public class PrototypeTest extends CardTestPlayerBase {
|
|||
|
||||
assertPowerToughness(playerA, automaton, 3, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAbilityRemovalPost() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Volcanic Island", 5);
|
||||
|
|
@ -543,6 +548,7 @@ public class PrototypeTest extends CardTestPlayerBase {
|
|||
|
||||
assertPowerToughness(playerA, automaton, 3, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEssenceOfWild() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Volcanic Island", 5);
|
||||
|
|
@ -559,6 +565,7 @@ public class PrototypeTest extends CardTestPlayerBase {
|
|||
|
||||
assertPermanentCount(playerA, "Essence of the Wild", 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChainer() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Volcanic Island", 3);
|
||||
|
|
@ -577,9 +584,10 @@ public class PrototypeTest extends CardTestPlayerBase {
|
|||
|
||||
checkAutomaton(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMetamorphCopyA() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Volcanic Island", 3+9);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Volcanic Island", 3 + 9);
|
||||
addCard(Zone.HAND, playerA, automaton);
|
||||
addCard(Zone.HAND, playerA, "Hulking Metamorph");
|
||||
|
||||
|
|
@ -596,15 +604,16 @@ public class PrototypeTest extends CardTestPlayerBase {
|
|||
assertPowerToughness(playerA, automaton, 3, 2);
|
||||
assertPowerToughness(playerA, automaton, 7, 7);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMetamorphCopyB() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Volcanic Island", 7+4);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Volcanic Island", 7 + 4);
|
||||
addCard(Zone.HAND, playerA, automaton);
|
||||
addCard(Zone.HAND, playerA, "Hulking Metamorph");
|
||||
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, automaton);
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Hulking Metamorph"+withPrototype);
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Hulking Metamorph" + withPrototype);
|
||||
setChoice(playerA, true);
|
||||
setChoice(playerA, automaton);
|
||||
|
||||
|
|
@ -615,9 +624,10 @@ public class PrototypeTest extends CardTestPlayerBase {
|
|||
assertPowerToughness(playerA, automaton, 6, 4);
|
||||
assertPowerToughness(playerA, automaton, 3, 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReflectionA() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Volcanic Island", 3+6+6);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Volcanic Island", 3 + 6 + 6);
|
||||
addCard(Zone.HAND, playerA, automaton);
|
||||
addCard(Zone.HAND, playerA, "Goring Warplow");
|
||||
addCard(Zone.HAND, playerA, "Infinite Reflection");
|
||||
|
|
@ -634,9 +644,10 @@ public class PrototypeTest extends CardTestPlayerBase {
|
|||
|
||||
checkAutomaton(true, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReflectionB() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Underground Sea", 7+6+2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Underground Sea", 7 + 6 + 2);
|
||||
addCard(Zone.HAND, playerA, automaton);
|
||||
addCard(Zone.HAND, playerA, "Goring Warplow");
|
||||
addCard(Zone.HAND, playerA, "Infinite Reflection");
|
||||
|
|
@ -645,7 +656,7 @@ public class PrototypeTest extends CardTestPlayerBase {
|
|||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, automaton);
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Infinite Reflection", automaton);
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Goring Warplow"+withPrototype);
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Goring Warplow" + withPrototype);
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
setStrictChooseMode(true);
|
||||
|
|
@ -653,9 +664,10 @@ public class PrototypeTest extends CardTestPlayerBase {
|
|||
|
||||
checkAutomaton(false, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProgenitor() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Frontier Bivouac", 3+6);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Frontier Bivouac", 3 + 6);
|
||||
addCard(Zone.HAND, playerA, automaton);
|
||||
addCard(Zone.HAND, playerA, "Progenitor Mimic");
|
||||
|
||||
|
|
@ -671,9 +683,10 @@ public class PrototypeTest extends CardTestPlayerBase {
|
|||
|
||||
checkAutomaton(true, 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInstantaneousLKI() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Volcanic Island", 3+2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Volcanic Island", 3 + 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Flowstone Surge", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Drizzt Do'Urden", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Warstorm Surge", 1);
|
||||
|
|
@ -681,7 +694,7 @@ public class PrototypeTest extends CardTestPlayerBase {
|
|||
addCard(Zone.HAND, playerA, "Slimebind");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Slimebind", "Drizzt Do'Urden");
|
||||
checkPT("Drizzt is shrunk",1, PhaseStep.BEGIN_COMBAT, playerA, "Drizzt Do'Urden",1, 1);
|
||||
checkPT("Drizzt is shrunk", 1, PhaseStep.BEGIN_COMBAT, playerA, "Drizzt Do'Urden", 1, 1);
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, automatonWithPrototype); // 5/0
|
||||
setChoice(playerA, "Whenever a creature you control enters"); //Stack the trigger
|
||||
addTarget(playerA, playerB);
|
||||
|
|
@ -692,11 +705,12 @@ public class PrototypeTest extends CardTestPlayerBase {
|
|||
|
||||
assertPowerToughness(playerA, "Drizzt Do'Urden", 5, 5);
|
||||
assertGraveyardCount(playerA, automaton, 1);
|
||||
assertLife(playerB, 20-5);
|
||||
assertLife(playerB, 20 - 5);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReanimate() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Badlands", 3+1+1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Badlands", 3 + 1 + 1);
|
||||
addCard(Zone.HAND, playerA, automaton);
|
||||
addCard(Zone.HAND, playerA, "Cut Down");
|
||||
addCard(Zone.HAND, playerA, "Reanimate");
|
||||
|
|
@ -710,7 +724,7 @@ public class PrototypeTest extends CardTestPlayerBase {
|
|||
execute();
|
||||
|
||||
checkAutomaton(false);
|
||||
assertLife(playerA, 20-7);
|
||||
assertLife(playerA, 20 - 7);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package org.mage.test.cards.abilities.oneshot.library;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import mage.cards.Card;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
|
|
@ -8,8 +7,9 @@ import org.junit.Assert;
|
|||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class PutToLibraryTest extends CardTestPlayerBase {
|
||||
|
|
@ -37,7 +37,7 @@ public class PutToLibraryTest extends CardTestPlayerBase {
|
|||
Assert.assertTrue("Library has no cards but should have", cardArray.size() > 1);
|
||||
Card secondCard = cardArray.get(1);
|
||||
Assert.assertTrue("Second card from top should be Dread Wanderer, but it isn't",
|
||||
secondCard != null && secondCard.getName().equals("Dread Wanderer"));
|
||||
secondCard != null && secondCard.hasName("Dread Wanderer", currentGame));
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -66,7 +66,7 @@ public class PutToLibraryTest extends CardTestPlayerBase {
|
|||
Assert.assertTrue("Library has no cards but should have", cardArray.size() > 3);
|
||||
Card fourthCard = cardArray.get(3);// get the 4th element
|
||||
Assert.assertTrue("Fourth card from top should be Skyrider Patrol, but it isn't",
|
||||
fourthCard != null && fourthCard.getName().equals("Skyrider Patrol"));
|
||||
fourthCard != null && fourthCard.hasName("Skyrider Patrol", currentGame));
|
||||
|
||||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 20);
|
||||
|
|
|
|||
|
|
@ -624,6 +624,10 @@ public interface MageObject extends MageItem, Serializable, Copyable<MageObject>
|
|||
|
||||
boolean hasName(String name, Game game);
|
||||
|
||||
default boolean hasNoName(Game game) {
|
||||
return false;
|
||||
}
|
||||
|
||||
default boolean sharesName(MageObject mageObject, Game game) {
|
||||
return !mageObject.getName().isEmpty() && hasName(mageObject.getName(), game);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
package mage.abilities.assignment.common;
|
||||
|
||||
import mage.abilities.assignment.RoleAssignment;
|
||||
import mage.cards.Card;
|
||||
import mage.game.Game;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class NameAssignment extends RoleAssignment<String> {
|
||||
|
||||
public NameAssignment(String... names) {
|
||||
super(names);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<String> makeSet(Card card, Game game) {
|
||||
return attributes
|
||||
.stream()
|
||||
.filter(s -> card.hasName(s, game))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
}
|
||||
|
|
@ -48,10 +48,12 @@ public class ExileTargetCardCopyAndCastEffect extends OneShotEffect {
|
|||
if (player == null || card == null) {
|
||||
return false;
|
||||
}
|
||||
player.moveCards(card, Zone.EXILED, source, game);
|
||||
if (!Zone.EXILED.match(game.getState().getZone(card.getId()))) {
|
||||
player.moveCards(card, Zone.EXILED, source, game);
|
||||
}
|
||||
Card cardCopy = game.copyCard(card, source, source.getControllerId());
|
||||
if (optional && !player.chooseUse(outcome, "Cast copy of " +
|
||||
card.getName() + (this.noMana ? " without paying its mana cost?" : "?" ), source, game)) {
|
||||
card.getName() + (this.noMana ? " without paying its mana cost?" : "?"), source, game)) {
|
||||
return true;
|
||||
}
|
||||
game.getState().setValue("PlayFromNotOwnHandZone" + cardCopy.getId(), Boolean.TRUE);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package mage.abilities.effects.common.search;
|
||||
|
||||
import mage.MageObject;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.cards.Cards;
|
||||
|
|
@ -8,6 +9,7 @@ import mage.constants.Outcome;
|
|||
import mage.constants.Zone;
|
||||
import mage.filter.FilterCard;
|
||||
import mage.filter.predicate.mageobject.NamePredicate;
|
||||
import mage.filter.predicate.mageobject.SharesNamePredicate;
|
||||
import mage.game.Game;
|
||||
import mage.players.Player;
|
||||
import mage.target.TargetCard;
|
||||
|
|
@ -40,6 +42,7 @@ public abstract class SearchTargetGraveyardHandLibraryForCardNameAndExileEffect
|
|||
protected SearchTargetGraveyardHandLibraryForCardNameAndExileEffect(boolean graveyardExileOptional, String searchWhatText, String searchForText, boolean drawForEachHandCard) {
|
||||
this(graveyardExileOptional, searchWhatText, searchForText, drawForEachHandCard, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
protected SearchTargetGraveyardHandLibraryForCardNameAndExileEffect(boolean graveyardExileOptional, String searchWhatText, String searchForText, boolean drawForEachHandCard, int maxAmount) {
|
||||
super(Outcome.Exile);
|
||||
this.searchWhatText = searchWhatText;
|
||||
|
|
@ -69,59 +72,67 @@ public abstract class SearchTargetGraveyardHandLibraryForCardNameAndExileEffect
|
|||
* @return
|
||||
*/
|
||||
protected boolean applySearchAndExile(Game game, Ability source, String cardName, UUID targetPlayerId) {
|
||||
FilterCard filter = new FilterCard("card named \"" + cardName + "\"");
|
||||
filter.add(new NamePredicate(cardName));
|
||||
return applySearchAndExile(game, source, filter, targetPlayerId);
|
||||
}
|
||||
|
||||
protected boolean applySearchAndExile(Game game, Ability source, MageObject mageObject, UUID targetPlayerId) {
|
||||
FilterCard filter = new FilterCard("card that shares a name with " + mageObject.getName());
|
||||
filter.add(new SharesNamePredicate(mageObject));
|
||||
return applySearchAndExile(game, source, filter, targetPlayerId);
|
||||
}
|
||||
|
||||
private boolean applySearchAndExile(Game game, Ability source, FilterCard filter, UUID targetPlayerId) {
|
||||
Player controller = game.getPlayer(source.getControllerId());
|
||||
if (cardName != null && controller != null) {
|
||||
Player targetPlayer = game.getPlayer(targetPlayerId);
|
||||
if (targetPlayer != null) {
|
||||
int handCards = 0;
|
||||
int maxRemaining = maxAmount;
|
||||
FilterCard filter = new FilterCard("card named \"" + cardName + "\"");
|
||||
filter.add(new NamePredicate(cardName));
|
||||
|
||||
// cards in Graveyard
|
||||
int cardsCount = Math.min(targetPlayer.getGraveyard().count(filter, game), maxRemaining);
|
||||
if (cardsCount > 0) {
|
||||
filter.setMessage("card named " + cardName + " in the graveyard of " + targetPlayer.getName());
|
||||
TargetCard target = new TargetCard((graveyardExileOptional ? 0 : cardsCount), cardsCount, Zone.GRAVEYARD, filter);
|
||||
target.withNotTarget(true);
|
||||
if (controller.choose(Outcome.Exile, targetPlayer.getGraveyard(), target, source, game)) {
|
||||
maxRemaining -= target.getTargets().size();
|
||||
controller.moveCards(new CardsImpl(target.getTargets()), Zone.EXILED, source, game);
|
||||
}
|
||||
}
|
||||
|
||||
// cards in Hand
|
||||
cardsCount = Math.min(targetPlayer.getHand().count(filter, game), maxRemaining);
|
||||
filter.setMessage("card named " + cardName + " in the hand of " + targetPlayer.getName());
|
||||
TargetCard target = new TargetCard(0, cardsCount, Zone.HAND, filter);
|
||||
target.withNotTarget(true);
|
||||
if (controller.choose(Outcome.Exile, targetPlayer.getHand(), target, source, game)) {
|
||||
maxRemaining -= target.getTargets().size();
|
||||
if (drawForEachHandCard) {
|
||||
handCards = target.getTargets().size();
|
||||
}
|
||||
controller.moveCards(new CardsImpl(target.getTargets()), Zone.EXILED, source, game);
|
||||
}
|
||||
|
||||
// cards in Library
|
||||
Cards cardsInLibrary = new CardsImpl();
|
||||
cardsInLibrary.addAllCards(targetPlayer.getLibrary().getCards(game));
|
||||
cardsCount = Math.min(cardsInLibrary.count(filter, game), maxRemaining);
|
||||
filter.setMessage("card named " + cardName + " in the library of " + targetPlayer.getLogName());
|
||||
TargetCardInLibrary targetLib = new TargetCardInLibrary(0, cardsCount, filter);
|
||||
if (controller.choose(Outcome.Exile, cardsInLibrary, targetLib, source, game)) {
|
||||
controller.moveCards(new CardsImpl(targetLib.getTargets()), Zone.EXILED, source, game);
|
||||
}
|
||||
targetPlayer.shuffleLibrary(source, game);
|
||||
|
||||
if (handCards > 0) {
|
||||
targetPlayer.drawCards(handCards, source, game);
|
||||
}
|
||||
Player targetPlayer = game.getPlayer(targetPlayerId);
|
||||
if (controller == null || targetPlayer == null) {
|
||||
return false;
|
||||
}
|
||||
String message = filter.getMessage();
|
||||
int handCards = 0;
|
||||
int maxRemaining = maxAmount;
|
||||
// cards in Graveyard
|
||||
int cardsCount = Math.min(targetPlayer.getGraveyard().count(filter, game), maxRemaining);
|
||||
if (cardsCount > 0) {
|
||||
filter.setMessage(message + " in the graveyard of " + targetPlayer.getName());
|
||||
TargetCard target = new TargetCard((graveyardExileOptional ? 0 : cardsCount), cardsCount, Zone.GRAVEYARD, filter);
|
||||
target.withNotTarget(true);
|
||||
if (controller.choose(Outcome.Exile, targetPlayer.getGraveyard(), target, source, game)) {
|
||||
maxRemaining -= target.getTargets().size();
|
||||
controller.moveCards(new CardsImpl(target.getTargets()), Zone.EXILED, source, game);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
// cards in Hand
|
||||
cardsCount = Math.min(targetPlayer.getHand().count(filter, game), maxRemaining);
|
||||
filter.setMessage(message + " in the hand of " + targetPlayer.getName());
|
||||
TargetCard target = new TargetCard(0, cardsCount, Zone.HAND, filter);
|
||||
target.withNotTarget(true);
|
||||
if (controller.choose(Outcome.Exile, targetPlayer.getHand(), target, source, game)) {
|
||||
maxRemaining -= target.getTargets().size();
|
||||
if (drawForEachHandCard) {
|
||||
handCards = target.getTargets().size();
|
||||
}
|
||||
controller.moveCards(new CardsImpl(target.getTargets()), Zone.EXILED, source, game);
|
||||
}
|
||||
|
||||
// cards in Library
|
||||
Cards cardsInLibrary = new CardsImpl();
|
||||
cardsInLibrary.addAllCards(targetPlayer.getLibrary().getCards(game));
|
||||
cardsCount = Math.min(cardsInLibrary.count(filter, game), maxRemaining);
|
||||
filter.setMessage(message + " in the library of " + targetPlayer.getLogName());
|
||||
TargetCardInLibrary targetLib = new TargetCardInLibrary(0, cardsCount, filter);
|
||||
if (controller.choose(Outcome.Exile, cardsInLibrary, targetLib, source, game)) {
|
||||
controller.moveCards(new CardsImpl(targetLib.getTargets()), Zone.EXILED, source, game);
|
||||
}
|
||||
targetPlayer.shuffleLibrary(source, game);
|
||||
|
||||
if (handCards > 0) {
|
||||
targetPlayer.drawCards(handCards, source, game);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue