Merge pull request #5453 from magefree/addTarget-tests-fixes

Improved test framework (fixed addTarget, aliases, dozen of tests and many more)
This commit is contained in:
Oleg Agafonov 2018-12-07 14:31:20 +04:00 committed by GitHub
commit 424aba6201
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
135 changed files with 2937 additions and 1752 deletions

View file

@ -1,6 +1,5 @@
package mage.cards.a;
import java.util.*;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
@ -16,6 +15,10 @@ import mage.game.stack.Spell;
import mage.players.Player;
import mage.watchers.Watcher;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* @author stravant
*/
@ -64,7 +67,7 @@ class ApproachOfTheSecondSunEffect extends OneShotEffect {
ApproachOfTheSecondSunWatcher watcher
= (ApproachOfTheSecondSunWatcher) game.getState().getWatchers().get(ApproachOfTheSecondSunWatcher.class.getSimpleName());
if (watcher != null
&& !spell.isCopiedSpell()
&& !spell.isCopy()
&& watcher.getApproachesCast(controller.getId()) > 1
&& spell.getFromZone() == Zone.HAND) {
// Win the game
@ -74,7 +77,7 @@ class ApproachOfTheSecondSunEffect extends OneShotEffect {
controller.gainLife(7, game, source);
// Put this into the library as the 7th from the top
if (spell.isCopiedSpell()) {
if (spell.isCopy()) {
return true;
}
Card spellCard = game.getStack().getSpell(source.getSourceId()).getCard();

View file

@ -1,7 +1,5 @@
package mage.cards.b;
import java.util.UUID;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.effects.common.continuous.BoostAllEffect;
@ -12,15 +10,17 @@ import mage.constants.Duration;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetCreaturePermanent;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author Quercitron
*/
public final class BileBlight extends CardImpl {
public BileBlight(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{B}{B}");
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{B}{B}");
// Target creature and all creatures with the same name as that creature get -3/-3 until end of turn.
@ -56,12 +56,12 @@ class BileBlightEffect extends BoostAllEffect {
if (this.affectedObjectsSet) {
Permanent target = game.getPermanent(getTargetPointer().getFirst(game, source));
if (target != null) {
if (target.getName().isEmpty()) { // face down creature
if (CardUtil.haveEmptyName(target)) { // face down creature
affectedObjectList.add(new MageObjectReference(target, game));
} else {
String name = target.getName();
for (Permanent perm : game.getBattlefield().getActivePermanents(source.getControllerId(), game)) {
if (perm.getName().equals(name)) {
if (CardUtil.haveSameNames(perm.getName(), name)) {
affectedObjectList.add(new MageObjectReference(perm, game));
}
}

View file

@ -1,7 +1,5 @@
package mage.cards.b;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
@ -14,15 +12,17 @@ import mage.constants.Outcome;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPlayer;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author Styxo
*/
public final class BrainPry extends CardImpl {
public BrainPry(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{B}");
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{B}");
//Name a nonland card. Target player reveals their hand. That player discards a card with that name. If he or she can't, you draw a card.
this.getSpellAbility().addEffect((new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.NON_LAND_NAME)));
@ -60,7 +60,7 @@ class BrainPryEffect extends OneShotEffect {
if (targetPlayer != null && controller != null && sourceObject != null && cardName != null) {
boolean hasDiscarded = false;
for (Card card : targetPlayer.getHand().getCards(game)) {
if (card.getName().equals(cardName)) {
if (CardUtil.haveSameNames(card.getName(), cardName)) {
targetPlayer.discard(card, source, game);
hasDiscarded = true;
break;

View file

@ -15,11 +15,11 @@ import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPlayer;
import mage.target.common.TargetControlledCreaturePermanent;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author jonubuu
*/
public final class CabalTherapy extends CardImpl {
@ -71,13 +71,13 @@ class CabalTherapyEffect extends OneShotEffect {
for (Card card : hand.getCards(game)) {
if (card.isSplitCard()) {
SplitCard splitCard = (SplitCard) card;
if (splitCard.getLeftHalfCard().getName().equals(cardName)) {
if (CardUtil.haveSameNames(splitCard.getLeftHalfCard().getName(), cardName)) {
targetPlayer.discard(card, source, game);
} else if (splitCard.getRightHalfCard().getName().equals(cardName)) {
} else if (CardUtil.haveSameNames(splitCard.getRightHalfCard().getName(), cardName)) {
targetPlayer.discard(card, source, game);
}
}
if (card.getName().equals(cardName)) {
if (CardUtil.haveSameNames(card.getName(), cardName)) {
targetPlayer.discard(card, source, game);
}
}

View file

@ -1,7 +1,5 @@
package mage.cards.c;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@ -17,9 +15,11 @@ import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author Styxo
*/
public final class CandlesOfLeng extends CardImpl {
@ -73,7 +73,7 @@ class CandlesOfLengEffect extends OneShotEffect {
controller.revealCards(sourceObject.getName(), cards, game);
boolean hasTheSameName = false;
for (UUID uuid : controller.getGraveyard()) {
if (card.getName().equals(game.getCard(uuid).getName())) {
if (CardUtil.haveSameNames(card, game.getCard(uuid))) {
hasTheSameName = true;
}
}

View file

@ -1,4 +1,3 @@
package mage.cards.c;
import mage.MageInt;
@ -136,7 +135,7 @@ class CircuDimirLobotomistRuleModifyingEffect extends ContinuousRuleModifyingEff
ExileZone exileZone = game.getExile().getExileZone(CardUtil.getCardExileZoneId(game, source));
if ((exileZone != null)) {
for (Card card : exileZone.getCards(game)) {
if ((card.getName().equals(object.getName()))) {
if (CardUtil.haveSameNames(card, object)) {
return true;
}
}

View file

@ -1,7 +1,5 @@
package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
@ -18,9 +16,11 @@ import mage.constants.SubType;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public final class ConundrumSphinx extends CardImpl {
@ -85,7 +85,7 @@ class ConundrumSphinxEffect extends OneShotEffect {
if (card != null) {
Cards cards = new CardsImpl(card);
player.revealCards(source, player.getName(), cards, game);
if (card.getName().equals(cardName)) {
if (CardUtil.haveSameNames(card.getName(), cardName)) {
player.moveCards(cards, Zone.HAND, source, game);
} else {
player.putCardsOnBottomOfLibrary(cards, game, source, false);

View file

@ -2,6 +2,8 @@
package mage.cards.c;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.SpellAbility;
import mage.abilities.common.EntersBattlefieldAbility;
@ -17,6 +19,7 @@ import mage.filter.FilterPermanent;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentCard;
import mage.players.Player;
import mage.target.Target;
import mage.util.functions.EmptyApplyToPermanent;

View file

@ -1,13 +1,5 @@
package mage.cards.c;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import mage.MageInt;
import mage.MageObjectReference;
import mage.abilities.Ability;
@ -18,12 +10,7 @@ import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.TurnPhase;
import mage.constants.WatcherScope;
import mage.constants.Zone;
import mage.constants.*;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.EquippedPredicate;
import mage.game.Game;
@ -31,10 +18,12 @@ import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.util.CardUtil;
import mage.watchers.Watcher;
import java.util.*;
/**
*
* @author rscoates
*/
public final class CorrosiveOoze extends CardImpl {
@ -156,7 +145,7 @@ class CorrosiveOozeCombatWatcher extends Watcher {
if (event.getType() == GameEvent.EventType.BLOCKER_DECLARED) {
Permanent attacker = game.getPermanent(event.getTargetId());
Permanent blocker = game.getPermanent(event.getSourceId());
if (attacker != null && attacker.getName().equals("Corrosive Ooze")) { // To check for name is not working if Ooze is copied but name changed
if (attacker != null && CardUtil.haveSameNames(attacker.getName(), "Corrosive Ooze")) { // To check for name is not working if Ooze is copied but name changed
if (blocker != null && hasAttachedEquipment(game, blocker)) {
MageObjectReference oozeMor = new MageObjectReference(attacker, game);
HashSet<MageObjectReference> relatedCreatures = oozeBlocksOrBlocked.getOrDefault(oozeMor, new HashSet<>());
@ -164,7 +153,7 @@ class CorrosiveOozeCombatWatcher extends Watcher {
oozeBlocksOrBlocked.put(oozeMor, relatedCreatures);
}
}
if (blocker != null && blocker.getName().equals("Corrosive Ooze")) {
if (blocker != null && CardUtil.haveSameNames(blocker.getName(), "Corrosive Ooze")) {
if (attacker != null && hasAttachedEquipment(game, attacker)) {
MageObjectReference oozeMor = new MageObjectReference(blocker, game);
HashSet<MageObjectReference> relatedCreatures = oozeBlocksOrBlocked.getOrDefault(oozeMor, new HashSet<>());

View file

@ -1,6 +1,5 @@
package mage.cards.c;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
@ -19,8 +18,9 @@ import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class CouncilOfTheAbsolute extends CardImpl {
@ -92,7 +92,8 @@ class CouncilOfTheAbsoluteReplacementEffect extends ContinuousRuleModifyingEffec
public boolean applies(GameEvent event, Ability source, Game game) {
if (game.getOpponents(source.getControllerId()).contains(event.getPlayerId())) {
MageObject object = game.getObject(event.getSourceId());
if (object != null && object.getName().equals(game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY))) {
String needName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
if (object != null && CardUtil.haveSameNames(object.getName(), needName)) {
return true;
}
}
@ -122,7 +123,8 @@ class CouncilOfTheAbsoluteCostReductionEffect extends CostModificationEffectImpl
if ((abilityToModify instanceof SpellAbility)
&& abilityToModify.isControlledBy(source.getControllerId())) {
Card card = game.getCard(abilityToModify.getSourceId());
return card.getName().equals(game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY));
String needName = (String) game.getState().getValue(source.getSourceId().toString() + ChooseACardNameEffect.INFO_KEY);
return CardUtil.haveSameNames(card.getName(), needName);
}
return false;
}

View file

@ -1,7 +1,5 @@
package mage.cards.c;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.common.SimpleActivatedAbility;
@ -17,6 +15,9 @@ import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetCreaturePermanent;
import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil;
import java.util.UUID;
/**
* @author nantuko
@ -24,7 +25,7 @@ import mage.target.targetpointer.FixedTarget;
public final class CrownOfEmpires extends CardImpl {
public CrownOfEmpires(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{2}");
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{2}");
// {3}, {tap}: Tap target creature. Gain control of that creature instead if you control artifacts named Scepter of Empires and Throne of Empires.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new CrownOfEmpiresEffect(), new GenericManaCost(3));
@ -60,9 +61,9 @@ class CrownOfEmpiresEffect extends OneShotEffect {
boolean scepter = false;
boolean throne = false;
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(source.getControllerId())) {
if (permanent.getName().equals("Scepter of Empires")) {
if (CardUtil.haveSameNames(permanent.getName(), "Scepter of Empires")) {
scepter = true;
} else if (permanent.getName().equals("Throne of Empires")) {
} else if (CardUtil.haveSameNames(permanent.getName(), "Throne of Empires")) {
throne = true;
}
if (scepter && throne) break;

View file

@ -1,6 +1,5 @@
package mage.cards.c;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@ -16,11 +15,12 @@ import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetAnyTarget;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author jeffwadsworth
*
*/
public final class CursedScroll extends CardImpl {
@ -70,7 +70,7 @@ class CursedScrollEffect extends OneShotEffect {
}
revealed.add(card);
controller.revealCards(sourceObject.getIdName(), revealed, game);
if (card.getName().equals(cardName)) {
if (CardUtil.haveSameNames(card.getName(), cardName)) {
Permanent creature = game.getPermanent(targetPointer.getFirst(game, source));
if (creature != null) {
creature.damage(2, source.getSourceId(), game, false, true);

View file

@ -1,9 +1,5 @@
package mage.cards.d;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
@ -20,9 +16,13 @@ import mage.game.permanent.PermanentToken;
import mage.game.permanent.token.ClueArtifactToken;
import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
import mage.util.CardUtil;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
/**
*
* @author escplan9 (Derek Monturo - dmontur1 at gmail dot com)
*/
public final class DeclarationInStone extends CardImpl {
@ -66,7 +66,7 @@ class DeclarationInStoneEffect extends OneShotEffect {
if (targetPermanent != null) {
Set<Card> cardsToExile = new HashSet<>();
int nonTokenCount = 0;
if (targetPermanent.getName().isEmpty()) { // face down creature
if (CardUtil.haveEmptyName(targetPermanent)) { // face down creature
cardsToExile.add(targetPermanent);
if (!(targetPermanent instanceof PermanentToken)) {
nonTokenCount++;
@ -78,7 +78,7 @@ class DeclarationInStoneEffect extends OneShotEffect {
}
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURES, targetPermanent.getControllerId(), game)) {
if (!permanent.getId().equals(targetPermanent.getId())
&& permanent.getName().equals(targetPermanent.getName())) {
&& CardUtil.haveSameNames(permanent, targetPermanent)) {
cardsToExile.add(permanent);
// exiled count only matters for non-tokens
if (!(permanent instanceof PermanentToken)) {

View file

@ -1,6 +1,5 @@
package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
@ -18,9 +17,11 @@ import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetOpponent;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author fireshoes
*/
public final class DementiaSliver extends CardImpl {
@ -44,9 +45,9 @@ public final class DementiaSliver extends CardImpl {
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
new GainAbilityAllEffect(gainedAbility, Duration.WhileOnBattlefield, filter,
"All Slivers have \"{T}: Choose a card name. "
+ "Target opponent reveals a card at random from their hand."
+ " If that card has the chosen name, that player discards it."
+ " Activate this ability only during your turn.\""
+ "Target opponent reveals a card at random from their hand."
+ " If that card has the chosen name, that player discards it."
+ " Activate this ability only during your turn.\""
)
));
}
@ -84,7 +85,7 @@ class DementiaSliverEffect extends OneShotEffect {
if (card != null) {
revealed.add(card);
opponent.revealCards(sourceObject.getName(), revealed, game);
if (card.getName().equals(cardName)) {
if (CardUtil.haveSameNames(card.getName(), cardName)) {
opponent.discard(card, source, game);
}
}

View file

@ -1,7 +1,5 @@
package mage.cards.d;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ChooseACardNameEffect;
@ -11,19 +9,21 @@ import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.game.Game;
import mage.players.Player;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.target.TargetSpell;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author L_J
*/
public final class Denied extends CardImpl {
public Denied(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{U}");
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{U}");
// Choose a card name, then target spell's controller reveals their hand. If a card with the chosen name is revealed this way, counter that spell.
this.getSpellAbility().addEffect(new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.ALL));
this.getSpellAbility().addEffect(new DeniedEffect());
@ -63,7 +63,7 @@ class DeniedEffect extends OneShotEffect {
player.revealCards("Denied!", player.getHand(), game, true);
String namedCard = (String) object;
for (Card card : player.getHand().getCards(game)) {
if (card != null && card.getName().equals(namedCard)) {
if (card != null && CardUtil.haveSameNames(card.getName(), namedCard)) {
game.getStack().counter(targetSpell.getId(), source.getSourceId(), game);
break;
}

View file

@ -1,7 +1,5 @@
package mage.cards.d;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
@ -25,8 +23,9 @@ import mage.target.TargetPermanent;
import mage.util.CardUtil;
import org.apache.log4j.Logger;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class DetentionSphere extends CardImpl {
@ -81,12 +80,12 @@ class DetentionSphereEntersEffect extends OneShotEffect {
MageObject sourceObject = game.getObject(source.getSourceId());
if (sourceObject != null && exileId != null && targetPermanent != null && controller != null) {
if (targetPermanent.getName().isEmpty()) { // face down creature
if (CardUtil.haveEmptyName(targetPermanent)) { // face down creature
controller.moveCardToExileWithInfo(targetPermanent, exileId, sourceObject.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true);
} else {
String name = targetPermanent.getName();
for (Permanent permanent : game.getBattlefield().getActivePermanents(source.getControllerId(), game)) {
if (permanent != null && permanent.getName().equals(name)) {
if (permanent != null && CardUtil.haveSameNames(permanent.getName(), name)) {
controller.moveCardToExileWithInfo(permanent, exileId, sourceObject.getIdName(), source.getSourceId(), game, Zone.BATTLEFIELD, true);
}
}

View file

@ -1,7 +1,5 @@
package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
@ -21,9 +19,11 @@ import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetCardInHand;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author maxlebedev
*/
public final class DiviningWitch extends CardImpl {
@ -92,7 +92,7 @@ public final class DiviningWitch extends CardImpl {
if (card != null) {
cardsToReaveal.add(card);
// Put that card into your hand
if (card.getName().equals(name)) {
if (CardUtil.haveSameNames(card.getName(), name)) {
cardToHand = card;
break;
}

View file

@ -1,7 +1,5 @@
package mage.cards.d;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.SimpleStaticAbility;
@ -13,20 +11,18 @@ import mage.abilities.keyword.HasteAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.SuperType;
import mage.constants.Zone;
import mage.constants.*;
import mage.filter.StaticFilters;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class DragonlordKolaghan extends CardImpl {
@ -95,7 +91,7 @@ class DragonlordKolaghanTriggeredAbility extends TriggeredAbilityImpl {
Player opponent = game.getPlayer(event.getPlayerId());
boolean sameName = false;
for (Card graveCard : opponent.getGraveyard().getCards(game)) {
if (graveCard.getName().equals(spell.getName())) {
if (CardUtil.haveSameNames(graveCard, spell)) {
sameName = true;
break;
}

View file

@ -1,7 +1,5 @@
package mage.cards.e;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
@ -12,6 +10,9 @@ import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetEnchantmentPermanent;
import mage.util.CardUtil;
import java.util.UUID;
/**
* @author Loki
@ -19,7 +20,7 @@ import mage.target.common.TargetEnchantmentPermanent;
public final class EchoingCalm extends CardImpl {
public EchoingCalm(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{W}");
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}");
// Destroy target enchantment and all other enchantments with the same name as that enchantment.
@ -58,9 +59,9 @@ class EchoingCalmEffect extends OneShotEffect {
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (controller != null && permanent != null) {
permanent.destroy(source.getSourceId(), game, false);
if (!permanent.getName().isEmpty()) { // in case of face down enchantment creature
if (!CardUtil.haveEmptyName(permanent)) { // in case of face down enchantment creature
for (Permanent perm : game.getBattlefield().getActivePermanents(source.getControllerId(), game)) {
if (!perm.getId().equals(permanent.getId()) && perm.getName().equals(permanent.getName()) && perm.isEnchantment()) {
if (!perm.getId().equals(permanent.getId()) && CardUtil.haveSameNames(perm, permanent) && perm.isEnchantment()) {
perm.destroy(source.getSourceId(), game, false);
}
}

View file

@ -1,7 +1,5 @@
package mage.cards.e;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
@ -17,15 +15,17 @@ import mage.filter.predicate.permanent.PermanentIdPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetCreaturePermanent;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class EchoingCourage extends CardImpl {
public EchoingCourage(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{G}");
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{G}");
// Target creature and all other creatures with the same name as that creature get +2/+2 until end of turn.
@ -64,12 +64,12 @@ class EchoingCourageEffect extends OneShotEffect {
Permanent targetPermanent = game.getPermanent(targetPointer.getFirst(game, source));
if (targetPermanent != null) {
FilterCreaturePermanent filter = new FilterCreaturePermanent();
if (targetPermanent.getName().isEmpty()) {
if (CardUtil.haveEmptyName(targetPermanent)) {
filter.add(new PermanentIdPredicate(targetPermanent.getId())); // if no name (face down creature) only the creature itself is selected
} else {
filter.add(new NamePredicate(targetPermanent.getName()));
}
ContinuousEffect effect = new BoostAllEffect(2,2, Duration.EndOfTurn, filter, false);
ContinuousEffect effect = new BoostAllEffect(2, 2, Duration.EndOfTurn, filter, false);
game.addEffect(effect, source);
return true;
}

View file

@ -1,7 +1,5 @@
package mage.cards.e;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
@ -17,15 +15,17 @@ import mage.filter.predicate.permanent.PermanentIdPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetCreaturePermanent;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author fireshoes
*/
public final class EchoingDecay extends CardImpl {
public EchoingDecay(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{B}");
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{B}");
// Target creature and all other creatures with the same name as that creature get -2/-2 until end of turn.
this.getSpellAbility().addEffect(new EchoingDecayEffect());
@ -63,12 +63,12 @@ class EchoingDecayEffect extends OneShotEffect {
Permanent targetPermanent = game.getPermanent(targetPointer.getFirst(game, source));
if (targetPermanent != null) {
FilterCreaturePermanent filter = new FilterCreaturePermanent();
if (targetPermanent.getName().isEmpty()) {
if (CardUtil.haveEmptyName(targetPermanent)) {
filter.add(new PermanentIdPredicate(targetPermanent.getId())); // if no name (face down creature) only the creature itself is selected
} else {
filter.add(new NamePredicate(targetPermanent.getName()));
}
ContinuousEffect effect = new BoostAllEffect(-2,-2, Duration.EndOfTurn, filter, false);
ContinuousEffect effect = new BoostAllEffect(-2, -2, Duration.EndOfTurn, filter, false);
game.addEffect(effect, source);
return true;
}

View file

@ -1,7 +1,5 @@
package mage.cards.e;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
@ -14,21 +12,23 @@ import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.TargetPermanent;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author fireshoes
*/
public final class EchoingRuin extends CardImpl {
private static final FilterPermanent filter = new FilterPermanent("artifact");
private static final FilterPermanent filter = new FilterPermanent("artifact");
static {
filter.add(new CardTypePredicate(CardType.ARTIFACT));
}
public EchoingRuin(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{1}{R}");
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{1}{R}");
// Destroy target artifact and all other artifacts with the same name as that artifact.
this.getSpellAbility().addTarget(new TargetPermanent(filter));
@ -66,9 +66,9 @@ class EchoingRuinEffect extends OneShotEffect {
Permanent permanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (controller != null && permanent != null) {
permanent.destroy(source.getSourceId(), game, false);
if (!permanent.getName().isEmpty()) { // in case of face down artifact creature
if (!CardUtil.haveEmptyName(permanent)) { // in case of face down artifact creature
for (Permanent perm : game.getBattlefield().getActivePermanents(source.getControllerId(), game)) {
if (!perm.getId().equals(permanent.getId()) && perm.getName().equals(permanent.getName()) && perm.isArtifact()) {
if (!perm.getId().equals(permanent.getId()) && CardUtil.haveSameNames(perm, permanent) && perm.isArtifact()) {
perm.destroy(source.getSourceId(), game, false);
}
}

View file

@ -1,7 +1,5 @@
package mage.cards.e;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.OneShotEffect;
@ -20,15 +18,17 @@ import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.Target;
import mage.target.common.TargetNonlandPermanent;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class EchoingTruth extends CardImpl {
public EchoingTruth(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}");
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}");
// Return target nonland permanent and all other permanents with the same name as that permanent to their owners' hands.
Target target = new TargetNonlandPermanent();
@ -67,7 +67,7 @@ class ReturnToHandAllNamedPermanentsEffect extends OneShotEffect {
Permanent permanent = game.getPermanent(source.getFirstTarget());
if (controller != null && permanent != null) {
FilterPermanent filter = new FilterPermanent();
if (permanent.getName().isEmpty()) {
if (CardUtil.haveEmptyName(permanent)) {
filter.add(new PermanentIdPredicate(permanent.getId())); // if no name (face down creature) only the creature itself is selected
} else {
filter.add(new NamePredicate(permanent.getName()));

View file

@ -1,7 +1,5 @@
package mage.cards.e;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
@ -24,10 +22,12 @@ import mage.filter.predicate.ObjectSourcePlayerPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetCreaturePermanent;
import mage.util.CardUtil;
import mage.util.functions.ApplyToPermanent;
import java.util.UUID;
/**
*
* @author BetaSteward
*/
public final class EvilTwin extends CardImpl {
@ -90,7 +90,7 @@ class EvilTwinPredicate implements ObjectSourcePlayerPredicate<ObjectSourcePlaye
public boolean apply(ObjectSourcePlayer<Permanent> input, Game game) {
Permanent permanent = input.getObject();
Permanent twin = game.getPermanent(input.getSourceId());
return permanent != null && twin != null && !twin.getName().isEmpty() && permanent.getName().equals(twin.getName());
return CardUtil.haveSameNames(permanent, twin);
}
@Override

View file

@ -1,13 +1,11 @@
package mage.cards.f;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.delayed.AtTheBeginOfNextUpkeepDelayedTriggeredAbility;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ChooseACardNameEffect;
import mage.abilities.effects.common.CreateDelayedTriggeredAbilityEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.ChooseACardNameEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@ -17,21 +15,23 @@ import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetOpponent;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author Quercitron & L_J
*/
public final class Foreshadow extends CardImpl {
public Foreshadow(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}");
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}");
// Choose a card name, then target opponent puts the top card of their library into their graveyard. If that card has the chosen name, you draw a card.
this.getSpellAbility().addEffect(new ChooseACardNameEffect(ChooseACardNameEffect.TypeOfName.ALL));
this.getSpellAbility().addEffect(new ForeshadowEffect());
this.getSpellAbility().addTarget(new TargetOpponent());
// Draw a card at the beginning of the next turn's upkeep.
this.getSpellAbility().addEffect(new CreateDelayedTriggeredAbilityEffect(
new AtTheBeginOfNextUpkeepDelayedTriggeredAbility(new DrawCardSourceControllerEffect(1)), false));
@ -72,8 +72,8 @@ class ForeshadowEffect extends OneShotEffect {
Card card = targetPlayer.getLibrary().getFromTop(game);
if (card != null) {
controller.moveCards(card, Zone.GRAVEYARD, source, game);
if (card.getName().equals(cardName)) {
controller.drawCards(1, game);
if (CardUtil.haveSameNames(card.getName(), cardName)) {
controller.drawCards(1, game);
}
}
return true;

View file

@ -1,7 +1,5 @@
package mage.cards.h;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.cards.CardImpl;
@ -14,15 +12,17 @@ import mage.filter.predicate.permanent.PermanentIdPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetCreaturePermanent;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author jeffwadsworth
*/
public final class HomingLightning extends CardImpl {
public HomingLightning(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{2}{R}{R}");
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{2}{R}{R}");
// Homing Lightning deals 4 damage to target creature and each other creature with the same name as that creature.
@ -58,7 +58,7 @@ class HomingLightningEffect extends OneShotEffect {
return false;
}
FilterCreaturePermanent filter = new FilterCreaturePermanent();
if (targetPermanent.getName().isEmpty()) {
if (CardUtil.haveEmptyName(targetPermanent)) {
filter.add(new PermanentIdPredicate(targetPermanent.getId())); // if no name (face down creature) only the creature itself is selected
} else {
filter.add(new NamePredicate(targetPermanent.getName()));

View file

@ -1,7 +1,5 @@
package mage.cards.i;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@ -12,8 +10,8 @@ import mage.abilities.keyword.HasteAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.mageobject.NamePredicate;
@ -21,15 +19,17 @@ import mage.filter.predicate.permanent.PermanentIdPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.target.common.TargetCreaturePermanent;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class IzzetStaticaster extends CardImpl {
public IzzetStaticaster(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{U}{R}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{R}");
this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.WIZARD);
@ -79,7 +79,7 @@ class IzzetStaticasterDamageEffect extends OneShotEffect {
Permanent targetPermanent = game.getPermanent(targetPointer.getFirst(game, source));
if (targetPermanent != null) {
FilterCreaturePermanent filter = new FilterCreaturePermanent();
if (targetPermanent.getName().isEmpty()) {
if (CardUtil.haveEmptyName(targetPermanent)) {
filter.add(new PermanentIdPredicate(targetPermanent.getId())); // if no name (face down creature) only the creature itself is selected
} else {
filter.add(new NamePredicate(targetPermanent.getName()));

View file

@ -1,7 +1,5 @@
package mage.cards.k;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
@ -14,13 +12,7 @@ import mage.abilities.keyword.MorphAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.AsThoughEffectType;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.constants.ZoneDetail;
import mage.constants.*;
import mage.game.Game;
import mage.game.stack.Spell;
import mage.game.stack.StackObject;
@ -28,14 +20,15 @@ import mage.players.Player;
import mage.target.TargetSpell;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
/**
*
* @author emerald000
*/
public final class KheruSpellsnatcher extends CardImpl {
public KheruSpellsnatcher(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{3}{U}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{3}{U}");
this.subtype.add(SubType.NAGA);
this.subtype.add(SubType.WIZARD);
@ -85,7 +78,7 @@ class KheruSpellsnatcherEffect extends OneShotEffect {
StackObject stackObject = game.getStack().getStackObject(objectId);
if (stackObject != null
&& game.getStack().counter(targetPointer.getFirst(game, source), source.getSourceId(), game, Zone.EXILED, false, ZoneDetail.NONE)) {
if (!((Spell) stackObject).isCopiedSpell()) {
if (!((Spell) stackObject).isCopy()) {
MageObject card = game.getObject(stackObject.getSourceId());
if (card instanceof Card) {
((Card) card).moveToZone(Zone.EXILED, sourceId, game, true);

View file

@ -1,10 +1,9 @@
package mage.cards.l;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.abilities.effects.common.ChooseACardNameEffect;
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
@ -14,9 +13,11 @@ import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPlayer;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author Styxo
*/
public final class LammastideWeave extends CardImpl {
@ -70,7 +71,7 @@ class LammastideWeaveEffect extends OneShotEffect {
Card card = targetPlayer.getLibrary().getFromTop(game);
if (card != null) {
controller.moveCards(card, Zone.GRAVEYARD, source, game);
if (card.getName().equals(cardName)) {
if (CardUtil.haveSameNames(card.getName(), cardName)) {
controller.gainLife(card.getConvertedManaCost(), game, source);
}
}

View file

@ -1,7 +1,5 @@
package mage.cards.l;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost;
@ -20,9 +18,11 @@ import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.common.TargetOpponent;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author L_J
*/
public final class LiarsPendulum extends CardImpl {
@ -93,7 +93,7 @@ class LiarsPendulumEffect extends OneShotEffect {
rightGuess = opponentGuess;
}
}
if (card.getName().equals(cardName)) {
if (CardUtil.haveSameNames(card.getName(), cardName)) {
rightGuess = opponentGuess;
}
}

View file

@ -1,7 +1,5 @@
package mage.cards.m;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
@ -10,11 +8,7 @@ import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ChooseACardNameEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.cards.*;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.SubType;
@ -23,9 +17,11 @@ import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetAnyTarget;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author fireshoes
*/
public final class MagusOfTheScroll extends CardImpl {
@ -80,7 +76,7 @@ class MagusOfTheScrollEffect extends OneShotEffect {
}
revealed.add(card);
you.revealCards(sourceObject.getName(), revealed, game);
if (card.getName().equals(cardName)) {
if (CardUtil.haveSameNames(card.getName(), cardName)) {
Permanent creature = game.getPermanent(targetPointer.getFirst(game, source));
if (creature != null) {
creature.damage(2, source.getSourceId(), game, false, true);

View file

@ -1,7 +1,5 @@
package mage.cards.m;
import java.util.UUID;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.costs.mana.GenericManaCost;
import mage.abilities.effects.Effect;
@ -19,17 +17,17 @@ import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.game.stack.Spell;
import mage.target.TargetSpell;
import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class Mirari extends CardImpl {
public Mirari(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{5}");
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT}, "{5}");
addSuperType(SuperType.LEGENDARY);
// Whenever you cast an instant or sorcery spell, you may pay {3}. If you do, copy that spell. You may choose new targets for the copy.
@ -58,8 +56,9 @@ class MirariTriggeredAbility extends TriggeredAbilityImpl {
}
MirariTriggeredAbility() {
super(Zone.BATTLEFIELD, new DoIfCostPaid(new CopyTargetSpellEffect(true), new GenericManaCost(3)), false);
this.addTarget(new TargetSpell(filter));
super(Zone.BATTLEFIELD, new DoIfCostPaid(
new CopyTargetSpellEffect(true),
new GenericManaCost(3)), false);
}
MirariTriggeredAbility(final MirariTriggeredAbility ability) {
@ -82,7 +81,11 @@ class MirariTriggeredAbility extends TriggeredAbilityImpl {
Spell spell = game.getStack().getSpell(event.getTargetId());
if (isControlledInstantOrSorcery(spell)) {
for (Effect effect : getEffects()) {
effect.setTargetPointer(new FixedTarget(spell.getId()));
if (effect instanceof DoIfCostPaid) {
for (Effect execEffect : ((DoIfCostPaid) effect).getExecutingEffects()) {
execEffect.setTargetPointer(new FixedTarget(spell.getId()));
}
}
}
return true;
}

View file

@ -1,4 +1,3 @@
package mage.cards.o;
import mage.abilities.Ability;
@ -18,6 +17,7 @@ import mage.filter.predicate.ObjectSourcePlayer;
import mage.filter.predicate.ObjectSourcePlayerPredicate;
import mage.game.Game;
import mage.players.Player;
import mage.target.Target;
import mage.target.TargetPlayer;
import mage.target.common.TargetCardInLibrary;
import mage.target.targetpointer.FixedTarget;
@ -25,12 +25,10 @@ import mage.target.targetpointer.FixedTarget;
import java.util.UUID;
/**
*
* @author emerald000
*/
public final class OathOfLieges extends CardImpl {
private final UUID originalId;
private static final FilterPlayer FILTER = new FilterPlayer("player who controls more lands than you do and is your opponent");
static {
@ -43,26 +41,19 @@ public final class OathOfLieges extends CardImpl {
// At the beginning of each player's upkeep, that player chooses target player who controls more lands than he or she does and is their opponent. The first player may search their library for a basic land card, put that card onto the battlefield, then shuffle their library.
Ability ability = new BeginningOfUpkeepTriggeredAbility(new OathOfLiegesEffect(), TargetController.ANY, false);
ability.addTarget(new TargetPlayer(1, 1, false, FILTER));
originalId = ability.getOriginalId();
this.addAbility(ability);
}
@Override
public void adjustTargets(Ability ability, Game game) {
if (ability.getOriginalId().equals(originalId)) {
Player activePlayer = game.getPlayer(game.getActivePlayerId());
if (activePlayer != null) {
ability.getTargets().clear();
TargetPlayer target = new TargetPlayer(1, 1, false, FILTER);
target.setTargetController(activePlayer.getId());
ability.getTargets().add(target);
}
// target controller must be active player (even for copies)
for (Target target : ability.getTargets()) {
target.setTargetController(game.getActivePlayerId());
}
}
public OathOfLieges(final OathOfLieges card) {
super(card);
this.originalId = card.originalId;
}
@Override
@ -93,7 +84,7 @@ class OathOfLiegesEffect extends OneShotEffect {
Player activePlayer = game.getPlayer(game.getActivePlayerId());
if (activePlayer != null) {
if (activePlayer.chooseUse(outcome, "Search your library for a basic land card, put that card onto the battlefield, then shuffle your library?", source, game)) {
Effect effect = new SearchLibraryPutInPlayTargetPlayerEffect(new TargetCardInLibrary(StaticFilters.FILTER_CARD_BASIC_LAND), false, true, Outcome.PutLandInPlay, true);
Effect effect = new SearchLibraryPutInPlayTargetPlayerEffect(new TargetCardInLibrary(StaticFilters.FILTER_CARD_BASIC_LAND), false, false, Outcome.PutLandInPlay, true);
effect.setTargetPointer(new FixedTarget(game.getActivePlayerId()));
return effect.apply(game, source);
}
@ -110,18 +101,25 @@ class OathOfLiegesPredicate implements ObjectSourcePlayerPredicate<ObjectSourceP
@Override
public boolean apply(ObjectSourcePlayer<Player> input, Game game) {
// input.getPlayerId() -- source controller id
// input.getObject() -- checking player
Player targetPlayer = input.getObject();
//Get active input.playerId because adjust target is used after canTarget function
UUID activePlayerId = game.getActivePlayerId();
if (targetPlayer == null || activePlayerId == null) {
return false;
}
if (!targetPlayer.hasOpponent(activePlayerId, game)) {
return false;
}
int countTargetPlayer = game.getBattlefield().countAll(FILTER, targetPlayer.getId(), game);
int countActivePlayer = game.getBattlefield().countAll(FILTER, activePlayerId, game);
Player activePlayer = game.getPlayer(game.getActivePlayerId());
if (targetPlayer == null || activePlayer == null) {
return false;
}
// must be opponent
if (!activePlayer.hasOpponent(targetPlayer.getId(), game)) {
return false;
}
// must have more lands than active player
int countTargetPlayer = game.getBattlefield().countAll(FILTER, targetPlayer.getId(), game);
int countActivePlayer = game.getBattlefield().countAll(FILTER, activePlayer.getId(), game);
return countTargetPlayer > countActivePlayer;
}

View file

@ -1,23 +1,20 @@
package mage.cards.p;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.effects.ReplacementEffectImpl;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.constants.*;
import mage.game.Game;
import mage.game.events.DamageEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.util.CardUtil;
import java.util.UUID;
/**
* @author LevelX2
@ -43,7 +40,7 @@ import mage.players.Player;
public final class PalisadeGiant extends CardImpl {
public PalisadeGiant(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{W}{W}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}{W}");
this.subtype.add(SubType.GIANT);
this.subtype.add(SubType.SOLDIER);
@ -51,7 +48,7 @@ public final class PalisadeGiant extends CardImpl {
this.toughness = new MageInt(7);
// All damage that would be dealt to you or another permanent you control is dealt to Palisade Giant instead.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PalisadeGiantReplacementEffect()));
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PalisadeGiantReplacementEffect()));
}
public PalisadeGiant(final PalisadeGiant card) {
@ -77,7 +74,7 @@ class PalisadeGiantReplacementEffect extends ReplacementEffectImpl {
@Override
public boolean checksEventType(GameEvent event, Game game) {
switch(event.getType()) {
switch (event.getType()) {
case DAMAGE_CREATURE:
case DAMAGE_PLAYER:
case DAMAGE_PLANESWALKER:
@ -89,17 +86,15 @@ class PalisadeGiantReplacementEffect extends ReplacementEffectImpl {
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getType() == GameEvent.EventType.DAMAGE_PLAYER && event.getPlayerId().equals(source.getControllerId()))
{
return true;
if (event.getType() == GameEvent.EventType.DAMAGE_PLAYER && event.getPlayerId().equals(source.getControllerId())) {
return true;
}
if (event.getType() == GameEvent.EventType.DAMAGE_CREATURE || event.getType() == GameEvent.EventType.DAMAGE_PLANESWALKER)
{
if (event.getType() == GameEvent.EventType.DAMAGE_CREATURE || event.getType() == GameEvent.EventType.DAMAGE_PLANESWALKER) {
Permanent targetPermanent = game.getPermanent(event.getTargetId());
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
if (targetPermanent != null &&
if (targetPermanent != null &&
targetPermanent.isControlledBy(source.getControllerId()) &&
!targetPermanent.getName().equals(sourcePermanent.getName())) { // no redirection from or to other Palisade Giants
!CardUtil.haveSameNames(targetPermanent, sourcePermanent)) { // no redirection from or to other Palisade Giants
return true;
}
}
@ -108,7 +103,7 @@ class PalisadeGiantReplacementEffect extends ReplacementEffectImpl {
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
DamageEvent damageEvent = (DamageEvent)event;
DamageEvent damageEvent = (DamageEvent) event;
Permanent sourcePermanent = game.getPermanent(source.getSourceId());
if (sourcePermanent != null) {
// get name of old target
@ -118,13 +113,11 @@ class PalisadeGiantReplacementEffect extends ReplacementEffectImpl {
message.append(damageEvent.getAmount()).append(" damage redirected from ");
if (targetPermanent != null) {
message.append(targetPermanent.getName());
}
else {
} else {
Player targetPlayer = game.getPlayer(event.getTargetId());
if (targetPlayer != null) {
message.append(targetPlayer.getLogName());
}
else {
} else {
message.append("unknown");
}

View file

@ -1,7 +1,5 @@
package mage.cards.p;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.common.DiesAttachedTriggeredAbility;
import mage.abilities.effects.Effect;
@ -11,22 +9,23 @@ import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Outcome;
import mage.constants.SetTargetPointer;
import mage.constants.SubType;
import mage.filter.common.FilterCreatureCard;
import mage.target.TargetPermanent;
import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class PatternOfRebirth extends CardImpl {
public PatternOfRebirth(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{G}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{G}");
this.subtype.add(SubType.AURA);
// Enchant creature
@ -37,7 +36,7 @@ public final class PatternOfRebirth extends CardImpl {
this.addAbility(ability);
// When enchanted creature dies, that creature's controller may search their library for a creature card and put that card onto the battlefield. If that player does, he or she shuffles their library.
Effect effect = new SearchLibraryPutInPlayTargetPlayerEffect(new TargetCardInLibrary(new FilterCreatureCard()), false, true, Outcome.PutCreatureInPlay);
Effect effect = new SearchLibraryPutInPlayTargetPlayerEffect(new TargetCardInLibrary(new FilterCreatureCard()), false, false, Outcome.PutCreatureInPlay);
effect.setText("that creature's controller may search their library for a creature card and put that card onto the battlefield. If that player does, he or she shuffles their library");
this.addAbility(new DiesAttachedTriggeredAbility(effect, "enchanted creature", true, true, SetTargetPointer.ATTACHED_TO_CONTROLLER));

View file

@ -1,7 +1,5 @@
package mage.cards.p;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@ -20,8 +18,9 @@ import mage.players.Player;
import mage.target.TargetPlayer;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author BetaSteward_at_googlemail.com & L_J
*/
public final class PetraSphinx extends CardImpl {
@ -79,7 +78,7 @@ class PetraSphinxEffect extends OneShotEffect {
if (card != null) {
Cards cards = new CardsImpl(card);
player.revealCards(source, cards, game);
if (card.getName().equals(cardName)) {
if (CardUtil.haveSameNames(card.getName(), cardName)) {
player.moveCards(cards, Zone.HAND, source, game);
} else {
player.moveCards(cards, Zone.GRAVEYARD, source, game);

View file

@ -1,6 +1,5 @@
package mage.cards.p;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ChooseACardNameEffect;
@ -13,9 +12,11 @@ import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPlayer;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author Quercitron
*/
public final class Predict extends CardImpl {
@ -66,7 +67,7 @@ class PredictEffect extends OneShotEffect {
Card card = targetPlayer.getLibrary().getFromTop(game);
if (card != null) {
controller.moveCards(card, Zone.GRAVEYARD, source, game);
if (card.getName().equals(cardName)) {
if (CardUtil.haveSameNames(card.getName(), cardName)) {
amount = 2;
}
}

View file

@ -1,8 +1,5 @@
package mage.cards.p;
import java.util.UUID;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.effects.common.CopyTargetSpellEffect;
import mage.abilities.effects.common.counter.AddCountersSourceEffect;
@ -17,19 +14,21 @@ import mage.game.events.GameEvent;
import mage.game.permanent.Permanent;
import mage.game.stack.Spell;
import mage.target.targetpointer.FixedTarget;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author nantuko
*/
public final class PyromancerAscension extends CardImpl {
public PyromancerAscension(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{1}{R}");
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{1}{R}");
// Whenever you cast an instant or sorcery spell that has the same name as a card in your graveyard, you may put a quest counter on Pyromancer Ascension.
this.addAbility(new PyromancerAscensionQuestTriggeredAbility());
// Whenever you cast an instant or sorcery spell while Pyromancer Ascension has two or more quest counters on it, you may copy that spell. You may choose new targets for the copy.
this.addAbility(new PyromancerAscensionCopyTriggeredAbility());
}
@ -75,21 +74,21 @@ class PyromancerAscensionQuestTriggeredAbility extends TriggeredAbilityImpl {
for (UUID uuid : game.getPlayer(this.getControllerId()).getGraveyard()) {
if (!uuid.equals(sourceCard.getId())) {
Card card = game.getCard(uuid);
if (card != null && card.getName().equals(sourceCard.getName())) {
if (CardUtil.haveSameNames(card, sourceCard)) {
return true;
}
}
}
}
}
}
}
return false;
}
private boolean isControlledInstantOrSorcery(Spell spell) {
return spell != null &&
(spell.isControlledBy(this.getControllerId())) &&
(spell.isInstant() || spell.isSorcery());
return spell != null &&
(spell.isControlledBy(this.getControllerId())) &&
(spell.isInstant() || spell.isSorcery());
}
@Override
@ -112,12 +111,12 @@ class PyromancerAscensionCopyTriggeredAbility extends TriggeredAbilityImpl {
public PyromancerAscensionCopyTriggeredAbility copy() {
return new PyromancerAscensionCopyTriggeredAbility(this);
}
@Override
public boolean checkEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.SPELL_CAST;
}
@Override
public boolean checkTrigger(GameEvent event, Game game) {
if (event.getPlayerId().equals(this.getControllerId())) {
@ -134,9 +133,9 @@ class PyromancerAscensionCopyTriggeredAbility extends TriggeredAbilityImpl {
}
private boolean isControlledInstantOrSorcery(Spell spell) {
return spell != null &&
(spell.isControlledBy(this.getControllerId())) &&
(spell.isInstant() || spell.isSorcery());
return spell != null &&
(spell.isControlledBy(this.getControllerId())) &&
(spell.isInstant() || spell.isSorcery());
}
@Override

View file

@ -1,8 +1,5 @@
package mage.cards.r;
import java.util.Objects;
import java.util.UUID;
import mage.MageInt;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
@ -11,12 +8,7 @@ import mage.abilities.effects.OneShotEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.TargetController;
import mage.constants.Zone;
import mage.constants.*;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.permanent.ControllerPredicate;
import mage.game.Game;
@ -25,9 +17,12 @@ import mage.game.permanent.Permanent;
import mage.game.stack.Spell;
import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
import mage.util.CardUtil;
import java.util.Objects;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class ReflectorMage extends CardImpl {
@ -84,7 +79,7 @@ class ReflectorMageEffect extends OneShotEffect {
Permanent targetCreature = game.getPermanent(getTargetPointer().getFirst(game, source));
if (targetCreature != null) {
controller.moveCards(targetCreature, Zone.HAND, source, game);
if (!targetCreature.getName().isEmpty()) { // if the creature had no name, no restrict effect will be created
if (!CardUtil.haveEmptyName(targetCreature)) { // if the creature had no name, no restrict effect will be created
game.addEffect(new ExclusionRitualReplacementEffect(targetCreature.getName(), targetCreature.getOwnerId()), source);
}
}
@ -125,7 +120,7 @@ class ExclusionRitualReplacementEffect extends ContinuousRuleModifyingEffectImpl
if (spell != null && spell.isFaceDown(game)) {
return false; // Face Down cast spell (Morph creature) has no name
}
return card.getName().equals(creatureName) && Objects.equals(ownerId, card.getOwnerId());
return CardUtil.haveSameNames(card.getName(), creatureName) && Objects.equals(ownerId, card.getOwnerId());
}
return false;
}

View file

@ -1,7 +1,5 @@
package mage.cards.s;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.TriggeredAbilityImpl;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
@ -22,9 +20,11 @@ import mage.game.permanent.Permanent;
import mage.game.stack.Spell;
import mage.game.turn.TurnMod;
import mage.players.Player;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class SearchTheCity extends CardImpl {
@ -157,7 +157,7 @@ class SearchTheCityExiledCardToHandEffect extends OneShotEffect {
ExileZone searchTheCityExileZone = game.getExile().getExileZone(source.getSourceId());
if (cardName != null && searchTheCityExileZone != null) {
for (Card card : searchTheCityExileZone.getCards(game)) {
if (card.getName().equals(cardName)) {
if (CardUtil.haveSameNames(card.getName(), cardName)) {
if (card.moveToZone(Zone.HAND, source.getSourceId(), game, true)) {
game.informPlayers("Search the City: put " + card.getName() + " into owner's hand");
}

View file

@ -1,7 +1,5 @@
package mage.cards.s;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.OneShotEffect;
@ -19,15 +17,17 @@ import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetCreaturePermanent;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author North
*/
public final class SeverTheBloodline extends CardImpl {
public SeverTheBloodline(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{B}");
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{B}");
// Exile target creature and all other creatures with the same name as that creature.
@ -69,7 +69,7 @@ class SeverTheBloodlineEffect extends OneShotEffect {
Permanent targetPermanent = game.getPermanent(targetPointer.getFirst(game, source));
if (controller != null && targetPermanent != null) {
FilterCreaturePermanent filter = new FilterCreaturePermanent();
if (targetPermanent.getName().isEmpty()) {
if (CardUtil.haveEmptyName(targetPermanent)) {
filter.add(new PermanentIdPredicate(targetPermanent.getId())); // if no name (face down creature) only the creature itself is selected
} else {
filter.add(new NamePredicate(targetPermanent.getName()));

View file

@ -1,14 +1,11 @@
package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.ContinuousEffectImpl;
import mage.abilities.effects.Effect;
import mage.abilities.effects.GainAbilitySpellsEffect;
import mage.abilities.effects.ReplacementEffectImpl;
@ -16,13 +13,7 @@ import mage.abilities.keyword.LifelinkAbility;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Layer;
import mage.constants.Outcome;
import mage.constants.SubLayer;
import mage.constants.Zone;
import mage.constants.*;
import mage.filter.FilterCard;
import mage.filter.FilterObject;
import mage.filter.predicate.Predicates;
@ -30,13 +21,12 @@ import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.game.Game;
import mage.game.events.GameEvent;
import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent;
import mage.game.stack.Spell;
import mage.game.stack.StackObject;
import mage.players.Player;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public final class SoulfireGrandMaster extends CardImpl {
@ -111,7 +101,7 @@ class SoulfireGrandMasterCastFromHandReplacementEffect extends ReplacementEffect
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
MageObject mageObject = game.getObject(spellId);
if (!(mageObject instanceof Spell) || ((Spell) mageObject).isCopiedSpell()) {
if (!(mageObject instanceof Spell) || ((Spell) mageObject).isCopy()) {
return false;
} else {
Card sourceCard = game.getCard(spellId);

View file

@ -1,23 +1,20 @@
package mage.cards.s;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ChooseACardNameEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.cards.*;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author Plopman
*/
public final class SpoilsOfTheVault extends CardImpl {
@ -71,7 +68,7 @@ class SpoilsOfTheVaultEffect extends OneShotEffect {
for (Card card : controller.getLibrary().getCards(game)) {
if (card != null) {
cardsToReveal.add(card);
if (card.getName().equals(cardName)) {
if (CardUtil.haveSameNames(card.getName(), cardName)) {
controller.moveCards(card, Zone.HAND, source, game);
break;
} else {

View file

@ -1,9 +1,5 @@
package mage.cards.t;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
@ -21,9 +17,14 @@ import mage.players.Player;
import mage.target.TargetPlayer;
import mage.target.common.TargetCardInHand;
import mage.target.common.TargetCardInLibrary;
import mage.util.CardUtil;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
/**
*
* @author jeffwadsworth
*/
public final class ThoughtHemorrhage extends CardImpl {
@ -74,7 +75,7 @@ class ThoughtHemorrhageEffect extends OneShotEffect {
targetPlayer.revealCards("hand of " + targetPlayer.getName(), targetPlayer.getHand(), game);
int cardsFound = 0;
for (Card card : targetPlayer.getHand().getCards(game)) {
if (card.getName().equals(cardName)) {
if (CardUtil.haveSameNames(card.getName(), cardName)) {
cardsFound++;
}
}

View file

@ -1,23 +1,20 @@
package mage.cards.t;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ChooseACardNameEffect;
import mage.cards.Card;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.cards.*;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPlayer;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author escplan9 (Derek Monturo - dmontur1 at gmail dot com)
*/
public final class TunnelVision extends CardImpl {
@ -76,7 +73,7 @@ class TunnelVisionEffect extends OneShotEffect {
for (Card card : targetPlayer.getLibrary().getCards(game)) {
cardsToReveal.add(card);
if (card.getName().equals(cardName)) {
if (CardUtil.haveSameNames(card.getName(), cardName)) {
namedCard = card;
break;
}

View file

@ -1,7 +1,5 @@
package mage.cards.v;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.SimpleActivatedAbility;
@ -18,9 +16,11 @@ import mage.constants.Zone;
import mage.game.Game;
import mage.players.Player;
import mage.target.TargetPlayer;
import mage.util.CardUtil;
import java.util.UUID;
/**
*
* @author BetaSteward_at_googlemail.com & L_J
*/
public final class VexingArcanix extends CardImpl {
@ -74,7 +74,7 @@ class VexingArcanixEffect extends OneShotEffect {
if (card != null) {
Cards cards = new CardsImpl(card);
player.revealCards(sourceObject.getIdName(), cards, game);
if (card.getName().equals(cardName)) {
if (CardUtil.haveSameNames(card.getName(), cardName)) {
player.moveCards(cards, Zone.HAND, source, game);
} else {
player.moveCards(cards, Zone.GRAVEYARD, source, game);

View file

@ -86,7 +86,7 @@ public final class GuildsOfRavnica extends ExpansionSet {
cards.add(new SetCardInfo("Deadly Visit", 68, Rarity.COMMON, mage.cards.d.DeadlyVisit.class));
cards.add(new SetCardInfo("Deafening Clarion", 165, Rarity.RARE, mage.cards.d.DeafeningClarion.class));
cards.add(new SetCardInfo("Demotion", 9, Rarity.UNCOMMON, mage.cards.d.Demotion.class));
cards.add(new SetCardInfo("Devious Cover-up", 35, Rarity.COMMON, mage.cards.d.DeviousCoverUp.class));
cards.add(new SetCardInfo("Devious Cover-Up", 35, Rarity.COMMON, mage.cards.d.DeviousCoverUp.class));
cards.add(new SetCardInfo("Devkarin Dissident", 127, Rarity.COMMON, mage.cards.d.DevkarinDissident.class));
cards.add(new SetCardInfo("Dimir Guildgate", 245, Rarity.COMMON, mage.cards.d.DimirGuildgate.class, NON_FULL_USE_VARIOUS));
cards.add(new SetCardInfo("Dimir Guildgate", 246, Rarity.COMMON, mage.cards.d.DimirGuildgate.class, NON_FULL_USE_VARIOUS));

View file

@ -1,4 +1,3 @@
package mage.sets;
import mage.cards.ExpansionSet;
@ -27,6 +26,7 @@ public final class Stronghold extends ExpansionSet {
this.numBoosterUncommon = 3;
this.numBoosterRare = 1;
this.ratioBoosterMythic = 0;
cards.add(new SetCardInfo("Acidic Sliver", 126, Rarity.UNCOMMON, mage.cards.a.AcidicSliver.class));
cards.add(new SetCardInfo("Amok", 76, Rarity.RARE, mage.cards.a.Amok.class));
cards.add(new SetCardInfo("Awakening", 101, Rarity.RARE, mage.cards.a.Awakening.class));
@ -77,7 +77,7 @@ public final class Stronghold extends ExpansionSet {
cards.add(new SetCardInfo("Hermit Druid", 108, Rarity.RARE, mage.cards.h.HermitDruid.class));
cards.add(new SetCardInfo("Hesitation", 33, Rarity.UNCOMMON, mage.cards.h.Hesitation.class));
cards.add(new SetCardInfo("Hibernation Sliver", 128, Rarity.UNCOMMON, mage.cards.h.HibernationSliver.class));
cards.add(new SetCardInfo("Hidden Retreat", 106, Rarity.RARE, mage.cards.h.HiddenRetreat.class));
cards.add(new SetCardInfo("Hidden Retreat", 6, Rarity.RARE, mage.cards.h.HiddenRetreat.class));
cards.add(new SetCardInfo("Honor Guard", 7, Rarity.COMMON, mage.cards.h.HonorGuard.class));
cards.add(new SetCardInfo("Horn of Greed", 135, Rarity.RARE, mage.cards.h.HornOfGreed.class));
cards.add(new SetCardInfo("Hornet Cannon", 136, Rarity.UNCOMMON, mage.cards.h.HornetCannon.class));
@ -117,7 +117,7 @@ public final class Stronghold extends ExpansionSet {
cards.add(new SetCardInfo("Rolling Stones", 11, Rarity.RARE, mage.cards.r.RollingStones.class));
cards.add(new SetCardInfo("Ruination", 95, Rarity.RARE, mage.cards.r.Ruination.class));
cards.add(new SetCardInfo("Sacred Ground", 12, Rarity.RARE, mage.cards.s.SacredGround.class));
cards.add(new SetCardInfo("Samite Blessing", 113, Rarity.COMMON, mage.cards.s.SamiteBlessing.class));
cards.add(new SetCardInfo("Samite Blessing", 13, Rarity.COMMON, mage.cards.s.SamiteBlessing.class));
cards.add(new SetCardInfo("Scapegoat", 14, Rarity.UNCOMMON, mage.cards.s.Scapegoat.class));
cards.add(new SetCardInfo("Seething Anger", 96, Rarity.COMMON, mage.cards.s.SeethingAnger.class));
cards.add(new SetCardInfo("Serpent Warrior", 69, Rarity.COMMON, mage.cards.s.SerpentWarrior.class));
@ -127,7 +127,7 @@ public final class Stronghold extends ExpansionSet {
cards.add(new SetCardInfo("Shock", 98, Rarity.COMMON, mage.cards.s.Shock.class));
cards.add(new SetCardInfo("Sift", 42, Rarity.COMMON, mage.cards.s.Sift.class));
cards.add(new SetCardInfo("Silver Wyvern", 43, Rarity.RARE, mage.cards.s.SilverWyvern.class));
cards.add(new SetCardInfo("Skeleton Scavengers", 20, Rarity.RARE, mage.cards.s.SkeletonScavengers.class));
cards.add(new SetCardInfo("Skeleton Scavengers", 70, Rarity.RARE, mage.cards.s.SkeletonScavengers.class));
cards.add(new SetCardInfo("Skyshroud Archer", 114, Rarity.COMMON, mage.cards.s.SkyshroudArcher.class));
cards.add(new SetCardInfo("Skyshroud Falcon", 16, Rarity.COMMON, mage.cards.s.SkyshroudFalcon.class));
cards.add(new SetCardInfo("Skyshroud Troopers", 115, Rarity.COMMON, mage.cards.s.SkyshroudTroopers.class));

View file

@ -1,13 +1,5 @@
package org.mage.test.clientside.base;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.Date;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import mage.constants.MultiplayerAttackOption;
import mage.constants.RangeOfInfluence;
import mage.game.match.MatchOptions;
@ -20,7 +12,15 @@ import mage.interfaces.callback.ClientCallback;
import mage.server.Main;
import mage.sets.Sets;
import mage.util.Logging;
import mage.view.*;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.Date;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Base for starting Mage server. Controls interactions between MageAPI and Mage
@ -205,7 +205,7 @@ public class MageBase {
}
gameView = server.getGameView(gameId, sessionId, playerId);
for (CardView card : gameView.getHand().values()) {
if (card.getName().equals(cardName)) {
if (CardUtil.haveSameNames(card.getName(), cardName)) {
return true;
}
}
@ -224,7 +224,7 @@ public class MageBase {
CardsView cards = gameView.getHand();
CardView cardToPlay = null;
for (CardView card : cards.values()) {
if (card.getName().equals(cardName)) {
if (CardUtil.haveSameNames(card.getName(), cardName)) {
cardToPlay = card;
}
}

View file

@ -59,7 +59,7 @@ public class LicidAbilityTest extends CardTestPlayerBase {
execute();
assertActionCount(playerA, 0);
assertActionsCount(playerA, 0);
assertAbility(playerA, "Pillarfield Ox", HasteAbility.getInstance(), false);
assertAbility(playerA, "Enraging Licid", new LicidAbility(new ColoredManaCost(ColoredManaSymbol.R), new ColoredManaCost(ColoredManaSymbol.R)), true);
assertType("Enraging Licid", CardType.ENCHANTMENT, false);

View file

@ -1,4 +1,3 @@
package org.mage.test.cards.abilities.equipped;
import mage.constants.PhaseStep;
@ -9,7 +8,6 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class EquipRestrictedTest extends CardTestPlayerBase {
@ -21,7 +19,7 @@ public class EquipRestrictedTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerB, "Leonin Scimitar");
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{T}: Attach target Equipment you control to target creature you control.", "Leonin Scimitar");
addTarget(playerB, "Silvercout Lion");
addTarget(playerB, "Silvercoat Lion");
setStopAt(2, PhaseStep.BEGIN_COMBAT);
execute();
@ -43,7 +41,7 @@ public class EquipRestrictedTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerB, "Konda's Banner");
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{T}: Attach target Equipment you control to target creature you control.", "Konda's Banner");
addTarget(playerB, "Silvercout Lion");
addTarget(playerB, "Silvercoat Lion");
setStopAt(2, PhaseStep.BEGIN_COMBAT);
execute();

View file

@ -1,68 +1,66 @@
package org.mage.test.cards.abilities.keywords;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class CipherTest extends CardTestPlayerBase {
/**
* Produced a copy of the opponents Roil Elemental with Stolen Identity and
* used Cipher on that same token. The token's landfall ability then did
* trigger normally up to the point where a target creature could be
* selected. The selection was logged by XMage, but the effect simply did
* not work. The original Roil Elemental controlled by the other player
* worked as intended, though.
*
* Edit: Opponent was AI, if that helps.
*/
@Test
public void testStolenIdentity() {
addCard(Zone.BATTLEFIELD, playerA, "Island", 6);
addCard(Zone.HAND, playerA, "Mountain", 1);
// Create a token that's a copy of target artifact or creature.
// Cipher (Then you may exile this spell card encoded on a creature you control. Whenever that creature deals combat damage to a player, its controller may cast a copy of the encoded card without paying its mana cost.)
addCard(Zone.HAND, playerA, "Stolen Identity"); // Sorcery {4}{U}{U}
// Flying
// Landfall - Whenever a land enters the battlefield under your control, you may gain control of target creature for as long as you control Roil Elemental.
addCard(Zone.BATTLEFIELD, playerB, "Roil Elemental");
addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox");
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Stolen Identity", "Roil Elemental");
setChoice(playerA, "Yes");
playLand(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Mountain");
addTarget(playerA, "Silvercoat Lion"); // Triggered ability of copied Roil Elemental to gain control
attack(3, playerA, "Roil Elemental"); // Creature 3/2
addTarget(playerA, "Pillarfield Ox");
setStopAt(3, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerB, 17);
assertExileCount(playerA, "Stolen Identity", 1);
assertPermanentCount(playerA, "Mountain", 1);
assertPermanentCount(playerB, "Pillarfield Ox", 1);
assertPermanentCount(playerA, "Pillarfield Ox", 1); // a copy from the cipered Stolen Identity caused by the Roil Elelemtal Attack
assertPermanentCount(playerB, "Silvercoat Lion", 0);
assertPermanentCount(playerA, "Silvercoat Lion", 1); // Gain control from triggered ability of the copied Roil Elemental ????? TARGET ???
assertPermanentCount(playerB, "Roil Elemental", 1);
assertPermanentCount(playerA, "Roil Elemental", 1);
}
}
package org.mage.test.cards.abilities.keywords;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class CipherTest extends CardTestPlayerBase {
/**
* Produced a copy of the opponents Roil Elemental with Stolen Identity and
* used Cipher on that same token. The token's landfall ability then did
* trigger normally up to the point where a target creature could be
* selected. The selection was logged by XMage, but the effect simply did
* not work. The original Roil Elemental controlled by the other player
* worked as intended, though.
*
* Edit: Opponent was AI, if that helps.
*/
@Test
public void testStolenIdentity() {
addCard(Zone.BATTLEFIELD, playerA, "Island", 6);
addCard(Zone.HAND, playerA, "Mountain", 1);
// Create a token that's a copy of target artifact or creature.
// Cipher (Then you may exile this spell card encoded on a creature you control. Whenever that creature deals combat damage to a player, its controller may cast a copy of the encoded card without paying its mana cost.)
addCard(Zone.HAND, playerA, "Stolen Identity"); // Sorcery {4}{U}{U}
// Flying
// Landfall - Whenever a land enters the battlefield under your control, you may gain control of target creature for as long as you control Roil Elemental.
addCard(Zone.BATTLEFIELD, playerB, "Roil Elemental");
addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox");
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion");
// cast spell, create copy token, exile spell card and encode it to that token of Roil Elemental
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Stolen Identity", "Roil Elemental");
setChoice(playerA, "Yes"); // Cipher activate
addTarget(playerA, "Roil Elemental"); // Cipher target for encode
checkPermanentCount("playerA must have Roil Elemental", 2, PhaseStep.PRECOMBAT_MAIN, playerA, "Roil Elemental", 1);
checkPermanentCount("playerB must have Roil Elemental", 2, PhaseStep.PRECOMBAT_MAIN, playerB, "Roil Elemental", 1);
checkExileCount("Stolen Identity must be in exile zone", 2, PhaseStep.PRECOMBAT_MAIN, playerA, "Stolen Identity", 1);
// Roil Elemental must activated on new land
playLand(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Mountain");
setChoice(playerA, "Yes"); // activate landfall to control opponent creature
addTarget(playerA, "Silvercoat Lion"); // Triggered ability of copied Roil Elemental to gain control
checkPermanentCount("must gain control of Lion", 3, PhaseStep.POSTCOMBAT_MAIN, playerA, "Silvercoat Lion", 1);
checkPermanentCount("must lose control of Lion", 3, PhaseStep.POSTCOMBAT_MAIN, playerB, "Silvercoat Lion", 0);
// on attack must activated ability to free cast
attack(5, playerA, "Roil Elemental");
setChoice(playerA, "Yes"); // activate free cast of encoded card
checkPermanentCount("playerA must have 2 Roil Elemental", 5, PhaseStep.POSTCOMBAT_MAIN, playerA, "Roil Elemental", 2);
checkPermanentCount("playerB must have Roil Elemental", 5, PhaseStep.POSTCOMBAT_MAIN, playerB, "Roil Elemental", 1);
setStopAt(5, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertLife(playerB, 17); // -3 by Roil
}
}

View file

@ -1,4 +1,3 @@
package org.mage.test.cards.abilities.keywords;
import mage.constants.PhaseStep;
@ -7,29 +6,27 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class EchoTest extends CardTestPlayerBase {
/*
* I flickered an Avalanche Riders with its Echo trigger on the stack with Restoration Angel.
* When the trigger resolved, my Riders was sacrificed, even though it should have been
* considered a new permanent.
*/
/*
* I flickered an Avalanche Riders with its Echo trigger on the stack with Restoration Angel.
* When the trigger resolved, my Riders was sacrificed, even though it should have been
* considered a new permanent.
*/
@Test
public void testEchoTriggerChecksIdentity() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
// Avalanche Riders Creature - Human Nomad 2/2
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
// Avalanche Riders Creature - Human Nomad 2/2 {3}{R}
// Haste
// Echo (At the beginning of your upkeep, if this came under your control since the beginning of your last upkeep, sacrifice it unless you pay its echo cost.)
// When Avalanche Riders enters the battlefield, destroy target land.
addCard(Zone.HAND, playerA, "Avalanche Riders");
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
// Restoration Angel {3}{W}
// Flash
// Flying
@ -37,12 +34,19 @@ public class EchoTest extends CardTestPlayerBase {
// then return that card to the battlefield under your control.
addCard(Zone.HAND, playerA, "Restoration Angel");
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1);
// cast Avalanche Riders and destroy forest
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Avalanche Riders");
addTarget(playerA, "Forest");
// Avalanche Riders go to echo, cast Restoration Angel to restore rider (do not apply echo with 4 mana)
activateManaAbility(3, PhaseStep.UPKEEP, playerA, "{T}: Add {W}");
activateManaAbility(3, PhaseStep.UPKEEP, playerA, "{T}: Add {W}");
activateManaAbility(3, PhaseStep.UPKEEP, playerA, "{T}: Add {W}");
activateManaAbility(3, PhaseStep.UPKEEP, playerA, "{T}: Add {W}");
castSpell(3, PhaseStep.UPKEEP, playerA, "Restoration Angel", null, "Echo {3}{R} <i>(At the beginning of your upkeep, if this came under your control since the beginning of your last upkeep, sacrifice it unless you pay its echo cost.)</i>");
addTarget(playerA, "Avalanche Riders");
setChoice(playerA, "Yes"); // raider do restore
setStopAt(3, PhaseStep.PRECOMBAT_MAIN);
execute();
@ -52,7 +56,9 @@ public class EchoTest extends CardTestPlayerBase {
assertPermanentCount(playerA, "Avalanche Riders", 1);
assertPermanentCount(playerA, "Restoration Angel", 1);
assertPermanentCount(playerB, "Mountain", 0);
assertPermanentCount(playerB, "Forest", 0);
assertTappedCount("Plains", true, 4);
assertTappedCount("Mountain", true, 0);
}

View file

@ -1,4 +1,3 @@
package org.mage.test.cards.abilities.keywords;
import mage.abilities.keyword.TrampleAbility;
@ -9,7 +8,6 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class FlashbackTest extends CardTestPlayerBase {
@ -71,10 +69,9 @@ public class FlashbackTest extends CardTestPlayerBase {
}
/**
*
* Test Granting Flashback to spells with X in manacost which have targeting
* requirements depending on the choice of X
*
* <p>
* Specific instance: Snapcaster Mage granting Flashback to Repeal
*/
@Test
@ -84,7 +81,7 @@ public class FlashbackTest extends CardTestPlayerBase {
addCard(Zone.GRAVEYARD, playerA, "Repeal", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Snapcaster Mage");
setChoice(playerA, "Repeal");
addTarget(playerA, "Repeal");
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Flashback");
setChoice(playerA, "X=2");
@ -100,10 +97,9 @@ public class FlashbackTest extends CardTestPlayerBase {
}
/**
*
* Test Granting Flashback to spells with X in mana cost, where X has no
* influence on targeting requirements
*
* <p>
* Specific instance: Snapcaster Mage granting Flashback to Blaze
*/
@Test
@ -115,7 +111,7 @@ public class FlashbackTest extends CardTestPlayerBase {
addCard(Zone.GRAVEYARD, playerA, "Blaze", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Snapcaster Mage");
setChoice(playerA, "Blaze");
addTarget(playerA, "Blaze");
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Flashback");
setChoice(playerA, "X=1");
@ -133,7 +129,6 @@ public class FlashbackTest extends CardTestPlayerBase {
/**
* My opponent put Iona on the battlefield using Unburial Rites, but my game
* log didn't show me the color he has chosen.
*
*/
@Test
public void testUnburialRites() {
@ -238,7 +233,7 @@ public class FlashbackTest extends CardTestPlayerBase {
* Ancestral Vision has no casting cost (this is different to a casting cost
* of {0}). Snapcaster Mage, for example, is able to give it flashback
* whilst it is in the graveyard.
*
* <p>
* However the controller should not be able to cast Ancestral Visions from
* the graveyard for {0} mana.
*/
@ -348,7 +343,7 @@ public class FlashbackTest extends CardTestPlayerBase {
// When Snapcaster Mage enters the battlefield, target instant or sorcery card in your graveyard gains flashback until end of turn. The flashback cost is equal to its mana cost.
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Snapcaster Mage");
setChoice(playerA, "Terminate");
addTarget(playerA, "Terminate");
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Flashback"); // Flashback Terminate
addTarget(playerA, "Icefall Regent");
@ -537,7 +532,7 @@ public class FlashbackTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Snapcaster Mage");
setChoice(playerA, "Force of Will");
addTarget(playerA, "Force of Will");
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Lightning Bolt", "Snapcaster Mage");
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Flashback", null, "Lightning Bolt");

View file

@ -1,7 +1,7 @@
package org.mage.test.cards.abilities.keywords;
import mage.cards.Card;
import mage.constants.EmptyNames;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.game.permanent.Permanent;
@ -10,7 +10,6 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class ManifestTest extends CardTestPlayerBase {
@ -34,15 +33,16 @@ public class ManifestTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
// no life gain
assertLife(playerA, 20);
assertLife(playerB, 20);
// a facedown creature is on the battlefield
assertPermanentCount(playerA, "", 1);
assertPowerToughness(playerA, "", 2, 2);
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
assertPowerToughness(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 2, 2);
// not tapped
assertTapped("", false);
assertTapped(EmptyNames.FACE_DOWN_CREATURE.toString(), false);
}
/**
@ -66,13 +66,14 @@ public class ManifestTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
// no life gain
assertLife(playerA, 20);
assertLife(playerB, 20);
// a facedown creature is on the battlefield
assertPermanentCount(playerA, "", 1);
assertPowerToughness(playerA, "", 2, 2);
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
assertPowerToughness(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 2, 2);
// PlayerB's Silvercoat Lion should not have get -1/-1/
assertPermanentCount(playerB, "Silvercoat Lion", 1);
assertPowerToughness(playerB, "Silvercoat Lion", 2, 2);
@ -101,6 +102,7 @@ public class ManifestTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
// no life gain
assertLife(playerA, 20);
@ -108,8 +110,8 @@ public class ManifestTest extends CardTestPlayerBase {
assertGraveyardCount(playerB, "Reality Shift", 1);
assertExileCount("Silvercoat Lion", 1);
// a facedown creature is on the battlefield
assertPermanentCount(playerA, "", 1);
assertPowerToughness(playerA, "", 2, 2);
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
assertPowerToughness(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 2, 2);
// PlayerA's Pillarfield Ox should not have get -1/-1/
assertPermanentCount(playerB, "Pillarfield Ox", 1);
assertPowerToughness(playerB, "Pillarfield Ox", 2, 4);
@ -137,6 +139,7 @@ public class ManifestTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
// no life gain
assertLife(playerA, 20);
@ -144,8 +147,8 @@ public class ManifestTest extends CardTestPlayerBase {
assertGraveyardCount(playerB, "Reality Shift", 1);
assertExileCount("Silvercoat Lion", 1);
// a facedown creature is on the battlefield
assertPermanentCount(playerA, "", 1);
assertPowerToughness(playerA, "", 2, 2);
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
assertPowerToughness(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 2, 2);
}
@ -173,6 +176,7 @@ public class ManifestTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
// no life gain
assertLife(playerA, 20);
@ -180,8 +184,8 @@ public class ManifestTest extends CardTestPlayerBase {
assertGraveyardCount(playerB, "Reality Shift", 1);
assertExileCount("Silvercoat Lion", 1);
// a facedown creature is on the battlefield
assertPermanentCount(playerA, "", 1);
assertPowerToughness(playerA, "", 2, 2);
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
assertPowerToughness(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 2, 2);
assertPowerToughness(playerA, "Foundry Street Denizen", 1, 1);
}
@ -199,7 +203,6 @@ public class ManifestTest extends CardTestPlayerBase {
// Strive Silence the Believers costs more to cast for each target beyond the first.
// Exile any number of target creatures and all Auras attached to them.
addCard(Zone.HAND, playerB, "Silence the Believers");
addTarget(playerB, "");
// Gore Swine {2}{R}
// 4/1
addCard(Zone.LIBRARY, playerA, "Gore Swine");
@ -210,10 +213,13 @@ public class ManifestTest extends CardTestPlayerBase {
skipInitShuffling();
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Reality Shift", "Silvercoat Lion");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Silence the Believers", "");
showBattlefield("A battle", 1, PhaseStep.POSTCOMBAT_MAIN, playerA);
showBattlefield("B battle", 1, PhaseStep.POSTCOMBAT_MAIN, playerB);
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Silence the Believers", EmptyNames.FACE_DOWN_CREATURE.toString());
setStopAt(1, PhaseStep.BEGIN_COMBAT);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
// no life gain
assertLife(playerA, 20);
@ -222,7 +228,7 @@ public class ManifestTest extends CardTestPlayerBase {
assertExileCount("Silvercoat Lion", 1);
assertExileCount("Gore Swine", 1);
// no facedown creature is on the battlefield
assertPermanentCount(playerA, "", 0);
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 0);
for (Card card : currentGame.getExile().getAllCards(currentGame)) {
if (card.getName().equals("Gore Swine")) {
@ -248,10 +254,11 @@ public class ManifestTest extends CardTestPlayerBase {
skipInitShuffling();
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{1}{B}, {T}, Sacrifice another creature");
addTarget(playerB, "Silvercoat Lion");
setChoice(playerB, "Silvercoat Lion");
setStopAt(2, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
// no life gain
assertLife(playerA, 20);
@ -261,7 +268,7 @@ public class ManifestTest extends CardTestPlayerBase {
assertGraveyardCount(playerB, "Silvercoat Lion", 1);
// a facedown creature is on the battlefield
assertPermanentCount(playerB, "", 1);
assertPermanentCount(playerB, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
}
@ -284,12 +291,13 @@ public class ManifestTest extends CardTestPlayerBase {
skipInitShuffling();
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{1}{B}, {T}, Sacrifice another creature");
addTarget(playerB, "Silvercoat Lion");
setChoice(playerB, "Silvercoat Lion");
activateAbility(2, PhaseStep.POSTCOMBAT_MAIN, playerB, "{5}{G}: Turn");
setStopAt(2, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
// no life gain
assertLife(playerA, 20);
@ -297,7 +305,7 @@ public class ManifestTest extends CardTestPlayerBase {
assertGraveyardCount(playerB, "Silvercoat Lion", 1);
assertPermanentCount(playerB, "", 0);
assertPermanentCount(playerB, EmptyNames.FACE_DOWN_CREATURE.toString(), 0);
assertPermanentCount(playerB, "Aerie Bowmasters", 1);
assertPowerToughness(playerB, "Aerie Bowmasters", 4, 5); // 3/4 and the +1/+1 counter from Megamorph
Permanent aerie = getPermanent("Aerie Bowmasters", playerB);
@ -308,7 +316,6 @@ public class ManifestTest extends CardTestPlayerBase {
/**
* When a Forest came manifested into play my Courser of Kruphix gained me a
* life.
*
*/
@Test
public void testManifestForest() {
@ -328,10 +335,11 @@ public class ManifestTest extends CardTestPlayerBase {
skipInitShuffling();
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{1}{B}, {T}, Sacrifice another creature");
addTarget(playerB, "Silvercoat Lion");
setChoice(playerB, "Silvercoat Lion");
setStopAt(2, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
// no life gain
assertLife(playerA, 20);
@ -339,13 +347,12 @@ public class ManifestTest extends CardTestPlayerBase {
assertGraveyardCount(playerB, "Silvercoat Lion", 1);
assertPermanentCount(playerB, "", 1);
assertPermanentCount(playerB, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
}
/**
* Whisperwood Elemental - Its sacrifice ability doesn't work..
*
*/
@Test
public void testWhisperwoodElemental() {
@ -365,6 +372,7 @@ public class ManifestTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
// no life gain
assertLife(playerA, 20);
@ -374,14 +382,13 @@ public class ManifestTest extends CardTestPlayerBase {
assertGraveyardCount(playerB, "Whisperwood Elemental", 1);
assertGraveyardCount(playerB, "Silvercoat Lion", 2);
assertPermanentCount(playerB, "", 2);
assertPermanentCount(playerB, EmptyNames.FACE_DOWN_CREATURE.toString(), 2);
}
/**
* I sacrificed a manifested face-down Smothering Abomination to Nantuko
* Husk and it made me draw a card.
*
*/
@Test
public void testDiesTriggeredAbilitiesOfManifestedCreatures() {
@ -409,10 +416,11 @@ public class ManifestTest extends CardTestPlayerBase {
setChoice(playerB, "Silvercoat Lion");
activateAbility(2, PhaseStep.POSTCOMBAT_MAIN, playerB, "Sacrifice a creature");
setChoice(playerB, "");
setChoice(playerB, EmptyNames.FACE_DOWN_CREATURE.toString());
setStopAt(2, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
// no life gain
assertLife(playerA, 20);

View file

@ -1,11 +1,7 @@
package org.mage.test.cards.abilities.keywords;
import mage.cards.Card;
import mage.constants.CardType;
import mage.constants.PhaseStep;
import mage.constants.SubType;
import mage.constants.Zone;
import mage.constants.*;
import mage.filter.Filter;
import mage.game.permanent.Permanent;
import org.junit.Assert;
@ -13,7 +9,6 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author levelX2
*/
public class MorphTest extends CardTestPlayerBase {
@ -21,7 +16,6 @@ public class MorphTest extends CardTestPlayerBase {
/**
* Tests if a creature with Morph is cast normal, it behaves as normal
* creature
*
*/
@Test
public void testCastMorphCreatureWithoutMorph() {
@ -60,8 +54,8 @@ public class MorphTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, "", 1);
assertPowerToughness(playerA, "", 2, 2);
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
assertPowerToughness(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 2, 2);
}
@ -76,7 +70,7 @@ public class MorphTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Pine Walker");
setChoice(playerA, "Yes"); // cast it face down as 2/2 creature
attack(3, playerA, "");
attack(3, playerA, EmptyNames.FACE_DOWN_CREATURE.toString());
activateAbility(3, PhaseStep.POSTCOMBAT_MAIN, playerA, "{4}{G}: Turn this face-down permanent face up.");
setStopAt(3, PhaseStep.END_TURN);
@ -84,7 +78,7 @@ public class MorphTest extends CardTestPlayerBase {
assertLife(playerB, 18);
assertPermanentCount(playerA, "", 0);
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 0);
assertPermanentCount(playerA, "Pine Walker", 1);
assertPowerToughness(playerA, "Pine Walker", 5, 5);
assertTapped("Pine Walker", false);
@ -94,7 +88,6 @@ public class MorphTest extends CardTestPlayerBase {
/**
* Test that the triggered "turned face up" ability of Pine Walker does not
* trigger as long as Pine Walker is not turned face up.
*
*/
@Test
public void testDoesNotTriggerFaceDown() {
@ -110,8 +103,8 @@ public class MorphTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Icefeather Aven", NO_TARGET, "Pine Walker", StackClause.WHILE_NOT_ON_STACK);
setChoice(playerA, "Yes"); // cast it face down as 2/2 creature
attack(3, playerA, "");
attack(3, playerA, "");
attack(3, playerA, EmptyNames.FACE_DOWN_CREATURE.toString());
attack(3, playerA, EmptyNames.FACE_DOWN_CREATURE.toString());
activateAbility(3, PhaseStep.DECLARE_BLOCKERS, playerA, "{1}{G}{U}: Turn this face-down permanent face up.");
setChoice(playerA, "No"); // Don't use return permanent to hand effect
@ -123,7 +116,7 @@ public class MorphTest extends CardTestPlayerBase {
assertHandCount(playerA, "Pine Walker", 0);
assertHandCount(playerA, "Icefeather Aven", 0);
assertPermanentCount(playerA, "", 1);
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
assertPermanentCount(playerA, "Icefeather Aven", 1);
assertTapped("Icefeather Aven", true);
@ -132,7 +125,6 @@ public class MorphTest extends CardTestPlayerBase {
/**
* Test that Morph creature do not trigger abilities with their face up
* attributes
*
*/
@Test
public void testMorphedRemovesAttributesCreature() {
@ -156,14 +148,13 @@ public class MorphTest extends CardTestPlayerBase {
assertLife(playerB, 20); // and not 21
assertPermanentCount(playerA, "", 1);
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
assertPermanentCount(playerB, "Soldier of the Pantheon", 1);
}
/**
* Test to copy a morphed 2/2 creature
*
*/
@Test
public void testCopyAMorphedCreature() {
@ -182,22 +173,21 @@ public class MorphTest extends CardTestPlayerBase {
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Clever Impersonator");
setChoice(playerB, "Yes"); // use to copy a nonland permanent
addTarget(playerB, ""); // Morphed creature
addTarget(playerB, EmptyNames.FACE_DOWN_CREATURE.toString()); // Morphed creature
setStopAt(2, PhaseStep.BEGIN_COMBAT);
execute();
assertLife(playerB, 20);
assertPermanentCount(playerA, "", 1);
assertPowerToughness(playerA, "", 2, 2);
assertPermanentCount(playerB, "", 1);
assertPowerToughness(playerB, "", 2, 2);
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
assertPowerToughness(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 2, 2);
assertPermanentCount(playerB, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
assertPowerToughness(playerB, EmptyNames.FACE_DOWN_CREATURE.toString(), 2, 2);
}
/**
*
*
*/
@Test
@ -229,7 +219,7 @@ public class MorphTest extends CardTestPlayerBase {
assertHandCount(playerA, "Pine Walker", 0);
assertHandCount(playerB, "Doomwake Giant", 0);
assertPermanentCount(playerA, "", 0);
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 0);
assertPermanentCount(playerB, "Doomwake Giant", 1);
assertPermanentCount(playerA, "Pine Walker", 1);
assertPowerToughness(playerA, "Pine Walker", 4, 4);
@ -241,7 +231,6 @@ public class MorphTest extends CardTestPlayerBase {
* morph goes down to 1/1 correctly. If you unmorph the 2/2 and is also a
* 2/2 after umorphing, the morph will be erroneously reduced to 0/0 and
* die.
*
*/
@Test
public void testDoomwakeGiantEffect() {
@ -271,7 +260,7 @@ public class MorphTest extends CardTestPlayerBase {
assertHandCount(playerA, "Ponyback Brigade", 0);
assertHandCount(playerB, "Doomwake Giant", 0);
assertPermanentCount(playerA, "", 0);
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 0);
assertPermanentCount(playerA, "Goblin", 3);
assertPowerToughness(playerA, "Goblin", 1, 1, Filter.ComparisonScope.Any);
assertPermanentCount(playerB, "Doomwake Giant", 1);
@ -283,7 +272,6 @@ public class MorphTest extends CardTestPlayerBase {
/**
* Clone a Morph creature that was cast face down and meanwhile was turned
* face up
*
*/
@Test
public void testCloneFaceUpMorphEffect() {
@ -317,7 +305,6 @@ public class MorphTest extends CardTestPlayerBase {
/**
* Check that you can't counter a creature cast for it morph costs with
* Disdainful Stroke if it's normal cmc > 3
*
*/
@Test
public void testCounterCastWithMorphEffect() {
@ -346,7 +333,7 @@ public class MorphTest extends CardTestPlayerBase {
assertHandCount(playerA, "Sagu Mauler", 0);
assertHandCount(playerB, "Disdainful Stroke", 1); // can't be cast
assertPermanentCount(playerA, "", 1);
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
}
@ -355,7 +342,6 @@ public class MorphTest extends CardTestPlayerBase {
* the same name" does only effect one face down creature, also if multiple
* on the battlefield. Because they have no name, they don't have the same
* name.
*
*/
@Test
public void testEchoingDecaySameNameEffect() {
@ -376,18 +362,23 @@ public class MorphTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sagu Mauler", NO_TARGET, "Sagu Mauler", StackClause.WHILE_NOT_ON_STACK);
setChoice(playerA, "Yes"); // cast it face down as 2/2 creature
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Echoing Decay", "");
showBattlefield("A battle", 1, PhaseStep.POSTCOMBAT_MAIN, playerA);
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Echoing Decay", EmptyNames.FACE_DOWN_CREATURE.toString());
setStopAt(1, PhaseStep.BEGIN_COMBAT);
showBattlefield("A battle after", 1, PhaseStep.END_TURN, playerA);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
assertLife(playerB, 20);
assertHandCount(playerB, "Echoing Decay", 0);
assertGraveyardCount(playerB, "Echoing Decay", 1);
assertHandCount(playerA, "Sagu Mauler", 0);
assertHandCount(playerB, "Echoing Decay", 0);
assertPermanentCount(playerA, "", 1);
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
assertGraveyardCount(playerA, "Sagu Mauler", 1);
}
/**
@ -472,7 +463,7 @@ public class MorphTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Ashcloud Phoenix");
setChoice(playerA, "Yes"); // cast it face down as 2/2 creature
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Lightning Bolt", "");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Lightning Bolt", EmptyNames.FACE_DOWN_CREATURE.toString());
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
@ -513,7 +504,7 @@ public class MorphTest extends CardTestPlayerBase {
setChoice(playerA, "Yes"); // cast it face down as 2/2 creature
attack(2, playerB, "Mirri, Cat Warrior");
block(2, playerA, "", "Mirri, Cat Warrior");
block(2, playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), "Mirri, Cat Warrior");
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
@ -549,20 +540,27 @@ public class MorphTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Akroma, Angel of Fury");
setChoice(playerA, "Yes"); // cast it face down as 2/2 creature
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Supplant Form", "");
showBattlefield("A battle", 1, PhaseStep.POSTCOMBAT_MAIN, playerA);
showBattlefield("B battle", 1, PhaseStep.POSTCOMBAT_MAIN, playerB);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Supplant Form");
addTarget(playerB, EmptyNames.FACE_DOWN_CREATURE.toString());
showBattlefield("A battle end", 1, PhaseStep.END_TURN, playerA);
showBattlefield("B battle end", 1, PhaseStep.END_TURN, playerB);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertLife(playerB, 20);
assertGraveyardCount(playerB, "Supplant Form", 1);
assertHandCount(playerA, "Akroma, Angel of Fury", 1);
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 0);
assertPermanentCount(playerA, "Akroma, Angel of Fury", 0);
assertGraveyardCount(playerB, "Supplant Form", 1);
assertPermanentCount(playerB, "Akroma, Angel of Fury", 0);
assertPermanentCount(playerB, "", 1);
assertPowerToughness(playerB, "", 2, 2);
assertPermanentCount(playerB, EmptyNames.FACE_DOWN_TOKEN.toString(), 1);
assertPowerToughness(playerB, EmptyNames.FACE_DOWN_TOKEN.toString(), 2, 2);
}
/**
@ -588,7 +586,7 @@ public class MorphTest extends CardTestPlayerBase {
assertLife(playerA, 20);
assertPermanentCount(playerA, "", 1);
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
}
@ -613,7 +611,7 @@ public class MorphTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Pine Walker");
setChoice(playerA, "Yes"); // cast it face down as 2/2 creature
attack(3, playerA, "");
attack(3, playerA, EmptyNames.FACE_DOWN_CREATURE.toString());
activateAbility(3, PhaseStep.POSTCOMBAT_MAIN, playerA, "{4}{G}: Turn this face-down permanent face up.");
setStopAt(3, PhaseStep.END_TURN);
@ -621,7 +619,7 @@ public class MorphTest extends CardTestPlayerBase {
assertLife(playerB, 18);
assertPermanentCount(playerA, "", 0);
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 0);
assertPermanentCount(playerA, "Pine Walker", 1);
assertPowerToughness(playerA, "Pine Walker", 5, 5);
assertTapped("Pine Walker", false);
@ -631,7 +629,7 @@ public class MorphTest extends CardTestPlayerBase {
* Reflector Mage bouncing a creature that can be played as a morph should
* not prevent the card from being replayed as a morph. Morph creatures are
* nameless.
*
* <p>
* Reported bug: Face-up morph creatures that are bounced by Reflector Mage
* should be able to be replayed as morphs without the "until the next turn"
* restriction."
@ -666,18 +664,18 @@ public class MorphTest extends CardTestPlayerBase {
assertPermanentCount(playerA, "Reflector Mage", 1);
assertPermanentCount(playerB, "Rattleclaw Mystic", 0);
assertHandCount(playerB, "Rattleclaw Mystic", 0); // should have been replayed
assertPermanentCount(playerB, "", 1); // Rattleclaw played as a morph
assertPermanentCount(playerB, EmptyNames.FACE_DOWN_CREATURE.toString(), 1); // Rattleclaw played as a morph
}
/**
* Reflector Mage bouncing a creature that can be played as a morph should
* not prevent the card from being replayed as a morph. Morph creatures are
* nameless.
*
* <p>
* Reported bug: Face-up morph creatures that are bounced by Reflector Mage
* should be able to be replayed as morphs without the "until the next turn"
* restriction."
*
* <p>
* Testing bouncing a face-down creature played next turn face-up.
*/
@Test
@ -701,7 +699,6 @@ public class MorphTest extends CardTestPlayerBase {
setChoice(playerA, "Yes"); // cast it face down as 2/2 creature
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Reflector Mage");
addTarget(playerB, "");
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Rattleclaw Mystic");
setChoice(playerA, "No"); // cast it face down as 2/2 creature
@ -790,7 +787,7 @@ public class MorphTest extends CardTestPlayerBase {
assertGraveyardCount(playerB, "Fatal Push", 1);
assertGraveyardCount(playerA, "Pine Walker", 1);
assertPermanentCount(playerA, "", 0);
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 0);
}
@ -824,7 +821,7 @@ public class MorphTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, "", 1);
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
assertHandCount(playerA, 0);
assertTappedCount("Island", true, 3);
@ -859,7 +856,7 @@ public class MorphTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Quicksilver Dragon");
setChoice(playerA, "Yes"); // cast it face down as 2/2 creature
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Lightning Bolt", "");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Lightning Bolt", EmptyNames.FACE_DOWN_CREATURE.toString());
setStopAt(2, PhaseStep.UPKEEP);
execute();

View file

@ -1,15 +1,14 @@
package org.mage.test.cards.abilities.keywords;
import mage.abilities.keyword.HasteAbility;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class SpliceOnArcaneTest extends CardTestPlayerBase {
@ -17,7 +16,6 @@ public class SpliceOnArcaneTest extends CardTestPlayerBase {
/**
* Test that it works to cast Through the Breach by slicing it on an arcane
* spell
*
*/
@Test
public void testSpliceThroughTheBreach() {
@ -32,7 +30,10 @@ public class SpliceOnArcaneTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Silvercoat Lion", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lava Spike", playerB);
setChoice(playerA, "Silvercoat Lion");
// activate splice: yes -> card with splice ability -> new target for spliced ability
setChoice(playerA, "Yes");
addTarget(playerA, "Through the Breach");
addTarget(playerA, "Silvercoat Lion"); // target for spliced ability: put from hand to battlefield
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
@ -60,8 +61,12 @@ public class SpliceOnArcaneTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 1);
// cast arcane Lava Spike
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lava Spike", playerB);
addTarget(playerA, "Silvercoat Lion");
// activate splice: yes -> card with splice ability -> new target for spliced ability
setChoice(playerA, "Yes");
addTarget(playerA, "Torrent of Stone");
addTarget(playerA, "Silvercoat Lion"); // target for spliced ability: 4 damage
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
@ -97,8 +102,10 @@ public class SpliceOnArcaneTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Silvercoat Lion", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Nourishing Shoal");
// activate splice: yes -> card with splice ability -> new target for spliced ability
setChoice(playerA, "Yes");
setChoice(playerA, "Silvercoat Lion");
addTarget(playerA, "Through the Breach");
addTarget(playerA, "Silvercoat Lion"); // target for spliced ability: put from hand to battlefield
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
@ -117,12 +124,12 @@ public class SpliceOnArcaneTest extends CardTestPlayerBase {
/**
* Cards involved: Nourishing Shoal, Goryo's Vengeance, Griselbrand,
* Terminate
*
* <p>
* I actually noticed this bug on the 1.4.3 client, but I didn't see it in
* the change log for 1.4.4, so I assume it is still unknown. Also, it is a
* bit of a rules corner case and I haven't seen anyone else report it, so
* the players of this deck may actually not realize it's incorrect.
*
* <p>
* The scenario was that I cast a Nourishing Shoal with a Goryo's Vengeance
* spliced to it targeting Griselbrand in my graveyard and exiling
* Worldspine Wurm. My opponent responded with a Snapcaster Mage, so to
@ -132,7 +139,7 @@ public class SpliceOnArcaneTest extends CardTestPlayerBase {
* resolve, it should have been countered due to no legal target. However,
* it caused me to gain 11 life. It did not resurrect Griselbrand
* (correctly), but it should have done nothing at all.
*
* <p>
* I include the info about the Terminate because thinking through, it could
* be pertinent. I would guess what is going on here is one of two things.
* Either the client doesn't recognize the Shoal with a spliced Vengeance as
@ -145,7 +152,10 @@ public class SpliceOnArcaneTest extends CardTestPlayerBase {
* the error against a bot and update this report.
*/
@Test
@Ignore
public void testCounteredBecauseOfNoLegalTarget() {
// TODO: rewrite test, it's wrong and misleading-- user report about Griselbrand was destroyed by Terminate after splice anounce, but tests don't use it at all (Griselbrand legal target all the time)
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 8);
// You may exile a green card with converted mana cost X from your hand rather than pay Nourishing Shoal's mana cost.
@ -174,5 +184,4 @@ public class SpliceOnArcaneTest extends CardTestPlayerBase {
assertLife(playerB, 20);
}
}

View file

@ -30,6 +30,7 @@ public class OblivionSowerTest extends CardTestPlayerBase {
skipInitShuffling();
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Oblivion Sower");
addTarget(playerA, playerB);
addTarget(playerA, "Canopy Vista^Canopy Vista^Canopy Vista");

View file

@ -1,4 +1,4 @@
package org.mage.test.cards.conditional;
package org.mage.test.cards.conditional;
import mage.constants.PhaseStep;
import mage.constants.Zone;
@ -6,12 +6,8 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class TragicSlipTest extends CardTestPlayerBase {
@Test
@ -108,7 +104,7 @@ public class TragicSlipTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Tragic Slip", "Silvercoat Lion");
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Snapcaster Mage");
setChoice(playerA, "Tragic Slip");
addTarget(playerA, "Tragic Slip");
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", "Snapcaster Mage");
@ -122,7 +118,7 @@ public class TragicSlipTest extends CardTestPlayerBase {
assertPermanentCount(playerA, "Snapcaster Mage", 0);
assertExileCount("Tragic Slip", 1);
assertPermanentCount(playerB, "Silvercoat Lion", 1);
assertPowerToughness(playerB, "Silvercoat Lion", 1,1);
assertPowerToughness(playerB, "Silvercoat Lion", 1, 1);
assertGraveyardCount(playerB, "Tarmogoyf", 1);
}
}

View file

@ -1,13 +1,12 @@
package org.mage.test.cards.continuous;
import mage.abilities.keyword.VigilanceAbility;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author JayDi85
*/
public class MasterThiefTest extends CardTestPlayerBase {
@ -42,7 +41,7 @@ public class MasterThiefTest extends CardTestPlayerBase {
// cast and get control of shield
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Master Thief");
addTarget(playerB, "Accorder's Shield");
addTarget(playerA, "Accorder's Shield");
// sacrifice Master Thief -- must lost control
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Sacrifice a creature");
@ -72,11 +71,13 @@ public class MasterThiefTest extends CardTestPlayerBase {
// cast and get control of shield
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Master Thief");
addTarget(playerB, "Accorder's Shield");
addTarget(playerA, "Accorder's Shield");
checkPermanentCount("must control shield", 1, PhaseStep.BEGIN_COMBAT, playerA, "Accorder's Shield", 1);
// attach and boost
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Equip {3}");
addTarget(playerA, "Bearer of the Heavens");
checkAbility("bear must have boost", 1, PhaseStep.END_TURN, playerA, "Bearer of the Heavens", VigilanceAbility.class, true);
// sacrifice Master Thief -- must lost control, but attached and boosted
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Sacrifice a creature");

View file

@ -1,5 +1,6 @@
package org.mage.test.cards.control;
import mage.constants.EmptyNames;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Assert;
@ -9,7 +10,7 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* Tests the effect: - Exile target creature you control, then return that card
* to the battlefield under your control
*
* <p>
* This effect grants you permanent control over the returned creature. So you
* mail steal opponent's creature with "Act of Treason" and then use this effect
* for permanent control effect.
@ -103,8 +104,8 @@ public class ExileAndReturnUnderYourControl extends CardTestPlayerBase {
assertExileCount("Secret Plans", 0);
assertPermanentCount(playerA, "Secret Plans", 1);
assertPermanentCount(playerA, "", 1);
assertPowerToughness(playerA, "", 2, 3);
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
assertPowerToughness(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 2, 3);
}
/**

View file

@ -1,14 +1,13 @@
package org.mage.test.cards.copy;
import mage.abilities.keyword.FlyingAbility;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.player.TestPlayer;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class CopySpellTest extends CardTestPlayerBase {
@ -17,23 +16,38 @@ public class CopySpellTest extends CardTestPlayerBase {
public void copyChainOfVapor() {
// Return target nonland permanent to its owner's hand. Then that permanent's controller may sacrifice a land. If the player does, he or she may copy this spell and may choose a new target for that copy.
addCard(Zone.HAND, playerA, "Chain of Vapor", 1);
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
addCard(Zone.BATTLEFIELD, playerA, "Island", 10);
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 1);
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 10);
addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox", 1);
addCard(Zone.BATTLEFIELD, playerB, "Island", 1);
addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox", 10);
addCard(Zone.BATTLEFIELD, playerB, "Island", 10);
// start chain from A - return pillar to hand
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Chain of Vapor", "Pillarfield Ox");
setChoice(playerB, "Yes");
addTarget(playerB, "Silvercoat Lion");
// chain 1 - B can return
addTarget(playerB, "Island"); // select a land to sacrifice
setChoice(playerB, "Yes"); // want to copy spell
setChoice(playerB, "Yes"); // want to change target
addTarget(playerB, "Silvercoat Lion"); // new target after copy
// chain 2 - A can return
addTarget(playerA, "Island"); // select a land to sacrifice
setChoice(playerA, "Yes"); // want to copy spell
setChoice(playerA, "Yes"); // want to change target
addTarget(playerA, "Pillarfield Ox"); // new target after copy
// stop the chain by B
addTarget(playerB, TestPlayer.TARGET_SKIP);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
assertGraveyardCount(playerB, "Island", 1);
assertHandCount(playerB, "Pillarfield Ox", 1);
assertHandCount(playerA, "Silvercoat Lion", 1);
assertHandCount(playerB, "Pillarfield Ox", 2);
assertPermanentCount(playerA, "Silvercoat Lion", 10 - 1);
assertPermanentCount(playerB, "Pillarfield Ox", 10 - 2);
assertGraveyardCount(playerA, "Island", 1);
assertGraveyardCount(playerB, "Island", 1);
}
@Test
@ -135,7 +149,7 @@ public class CopySpellTest extends CardTestPlayerBase {
* before it is cast and therefore before Zada's ability triggers, e.g.
* Desperate Ritual spliced onto Into the Fray should generate 3 red mana
* for every creature i control.
*
* <p>
* 702.46a Splice is a static ability that functions while a card is in your
* hand. Splice onto [subtype] [cost] means You may reveal this card from
* your hand as you cast a [subtype] spell. If you do, copy this card's text
@ -184,7 +198,7 @@ public class CopySpellTest extends CardTestPlayerBase {
* {4}{U} Enchantment (Enchant Player) Whenever enchanted player casts an
* instant or sorcery spell, each other player may copy that spell and may
* choose new targets for the copy he or she controls.
*
* <p>
* Reported bug: "A player with Curse of Echoes attached to them played
* Bribery and the player who controlled the curse had control of all 3
* copies. This seems to be the case for all spells."

View file

@ -52,15 +52,24 @@ public class CryptoplasmTest extends CardTestPlayerBase {
// At the beginning of your upkeep, you may have Cryptoplasm become a copy of another target creature. If you do, Cryptoplasm gains this ability.
addCard(Zone.BATTLEFIELD, playerB, "Cryptoplasm", 1); // {1}{U}{U}
// turn 2 - prepare (crypto to paladin, footsteps to crypto)
// crypto: copy as paladin on upkeep
setChoice(playerB, "Yes");
addTarget(playerB, "Sigiled Paladin");
// footsteps: enchant copy of paladin (crypto)
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Followed Footsteps");
addTarget(playerB, "Sigiled Paladin[only copy]");
// turn 4 - ignore crypto ask for new copy
setChoice(playerB, "No");
setStopAt(4, PhaseStep.END_TURN);
execute();
assertPermanentCount(playerB, "Followed Footsteps", 1);
assertPermanentCount(playerB, "Cryptoplasm", 0);
assertPermanentCount(playerB, "Sigiled Paladin", 2);
assertPermanentCount(playerB, "Cryptoplasm", 0); // it's a copy
assertPermanentCount(playerB, "Sigiled Paladin", 2); // crypto as copy + footstep token as copy
assertPermanentCount(playerA, "Sigiled Paladin", 1); // original
}
/**

View file

@ -44,10 +44,12 @@ public class IsochronScepterTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Lightning Bolt");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Isochron Scepter");
addTarget(playerA, "Lightning Bolt");
setChoice(playerA, "Yes"); // use imprint
setChoice(playerA, "Lightning Bolt"); // target for imprint (excile from hand)
// copy and cast imprinted card
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{2}, {T}:");
setChoice(playerA, "Yes");
setChoice(playerA, "Yes");
setStopAt(1, PhaseStep.END_TURN);
execute();

View file

@ -28,8 +28,8 @@ public class ReversalOfFortuneTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerB, "Lightning Bolt");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reversal of Fortune", playerB);
addTarget(playerA, "Lightning Bolt");
setChoice(playerA, "Yes");
setChoice(playerA, "Lightning Bolt"); // select to copy
setChoice(playerA, "Yes"); // cast copy
setStopAt(1, PhaseStep.END_TURN);
execute();

View file

@ -1,4 +1,3 @@
package org.mage.test.cards.copy;
import mage.constants.PhaseStep;
@ -7,7 +6,6 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
@ -15,34 +13,33 @@ public class SharuumTheHegemonTest extends CardTestPlayerBase {
/**
* http://www.slightlymagic.net/forum/viewtopic.php?f=70&t=16732&p=172937&hilit=Sharuum+the+Hegemon#p172920
*
* My Sharuum EDH deck uses the standard Sharuum + Clone Effect + Blood Artist as one of the win
* conditions, but when I have Sharuum in plan and play a Clever Impersonator, targetting Sharuum
* and choose to keep the Clever Impersonator and send the original Sharuum to the graveyard Xmage
* never gives me the option to use the Sharuum Ability that the Clever Impersonator should get,
* <p>
* My Sharuum EDH deck uses the standard Sharuum + Clone Effect + Blood Artist as one of the win
* conditions, but when I have Sharuum in plan and play a Clever Impersonator, targetting Sharuum
* and choose to keep the Clever Impersonator and send the original Sharuum to the graveyard Xmage
* never gives me the option to use the Sharuum Ability that the Clever Impersonator should get,
* making the combo not work.
*
* I run a Sharuum EDH deck that wins by cloning Sharuum for infinite death triggers. I know the rules
* <p>
* I run a Sharuum EDH deck that wins by cloning Sharuum for infinite death triggers. I know the rules
* check out on this combo irl, but no matter how I stack the triggers for cloning Sharuum and her enter
* the battlefield effect it does not work. It either ends with Sharuum in my graveyard or the reanimate
* effect hits the stack before the legend rule applies
*
[1] Sharuum the Hegemon is on the battlefield.
[2] You cast Clone (or any other Clone-like card).
[3] When Clone resolves, you choose Sharuum for the replacement effect.
[4] Since fake-Sharuum entered the battlefield, its EtB ability triggers.
[5] State-based actions are checked and you are prompted to keep one Sharuum. You sacrifice real-Sharuum.
* 116.2a Triggered abilities can trigger at any time, including while a spell is being cast, an ability is being activated, or a spell or
* ability is resolving. (See rule 603, "Handling Triggered Abilities.") However, nothing actually happens at the time an ability triggers.
* Each time a player would receive priority, each ability that has triggered but hasn't yet been put on the stack is put on the stack. See rule 116.5
* 116.5. Each time a player would get priority, the game first performs all applicable state-based actions as a single event (see rule 704,
* "State-Based Actions"), then repeats this process until no state-based actions are performed. Then triggered abilities are put on the stack
* (see rule 603, "Handling Triggered Abilities"). These steps repeat in order until no further state-based actions are performed and no abilities
* trigger. Then the player who would have received priority does so.
[6] Once State-based actions are finished, triggered abilities go on the stack. You put the EtB from [4] choosing real-Sharuum.
[7] Real-Sharuum enters the battlefield.
[8] Rinse and repeat.
*
* <p>
* [1] Sharuum the Hegemon is on the battlefield.
* [2] You cast Clone (or any other Clone-like card).
* [3] When Clone resolves, you choose Sharuum for the replacement effect.
* [4] Since fake-Sharuum entered the battlefield, its EtB ability triggers.
* [5] State-based actions are checked and you are prompted to keep one Sharuum. You sacrifice real-Sharuum.
* 116.2a Triggered abilities can trigger at any time, including while a spell is being cast, an ability is being activated, or a spell or
* ability is resolving. (See rule 603, "Handling Triggered Abilities.") However, nothing actually happens at the time an ability triggers.
* Each time a player would receive priority, each ability that has triggered but hasn't yet been put on the stack is put on the stack. See rule 116.5
* 116.5. Each time a player would get priority, the game first performs all applicable state-based actions as a single event (see rule 704,
* "State-Based Actions"), then repeats this process until no state-based actions are performed. Then triggered abilities are put on the stack
* (see rule 603, "Handling Triggered Abilities"). These steps repeat in order until no further state-based actions are performed and no abilities
* trigger. Then the player who would have received priority does so.
* [6] Once State-based actions are finished, triggered abilities go on the stack. You put the EtB from [4] choosing real-Sharuum.
* [7] Real-Sharuum enters the battlefield.
* [8] Rinse and repeat.
*/
@Test
public void testCloneTriggered() {
@ -59,17 +56,26 @@ public class SharuumTheHegemonTest extends CardTestPlayerBase {
setChoice(playerA, "Sharuum the Hegemon"); // what creature to clone
addTarget(playerA, "Sharuum the Hegemon[only copy]"); // which legend to keep
setChoice(playerA, "Yes");
addTarget(playerA, "Sharuum the Hegemon[only copy]"); // which legend to keep
setChoice(playerA, "Yes");
setChoice(playerA, "Whenever {this} or another creature dies"); // blood first
addTarget(playerA, playerB); // damage by blood
setChoice(playerA, "Yes"); // return
addTarget(playerA, "Sharuum the Hegemon"); // return real sharuum
addTarget(playerA, "Sharuum the Hegemon[only copy]"); // which legend to keep
setChoice(playerA, "Yes");
setChoice(playerA, "Whenever {this} or another creature dies"); // blood first
addTarget(playerA, playerB); // damage by blood
setChoice(playerA, "Yes"); // return
addTarget(playerA, "Sharuum the Hegemon"); // return real sharuum
addTarget(playerA, "Sharuum the Hegemon[only copy]"); // which legend to keep
setChoice(playerA, "Whenever {this} or another creature dies"); // blood first
addTarget(playerA, playerB); // damage by blood
setChoice(playerA, "Yes"); // return
addTarget(playerA, "Sharuum the Hegemon"); // return real sharuum
addTarget(playerA, "Sharuum the Hegemon[only copy]"); // which legend to keep
setChoice(playerA, "No"); // Don't use it anymore
setStopAt(1, PhaseStep.END_TURN);
execute();
@ -77,7 +83,6 @@ public class SharuumTheHegemonTest extends CardTestPlayerBase {
assertLife(playerB, 16);
}
}

View file

@ -1,8 +1,8 @@
package org.mage.test.cards.copy;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Ignore;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
@ -48,6 +48,7 @@ public class SpelltwineTest extends CardTestPlayerBase {
* after this, failing to be in the stack box or resolve all.
*/
@Test
@Ignore // TODO: test is wrong -- mirari exile cards and must cast their copies, on copies cast mirari triggers again (two times).
public void testCopyCardsMirari() {
addCard(Zone.BATTLEFIELD, playerA, "Island", 9);
// Exile target instant or sorcery card from your graveyard and target instant or sorcery card from an opponent's graveyard.
@ -66,9 +67,13 @@ public class SpelltwineTest extends CardTestPlayerBase {
// Whenever you cast an instant or sorcery spell, you may pay {3}. If you do, copy that spell. You may choose new targets for the copy.
addCard(Zone.BATTLEFIELD, playerA, "Mirari", 1);
// cast spellwin
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Spelltwine");
addTarget(playerA, "Impulse");
addTarget(playerA, "Blasphemous Act");
addTarget(playerA, "Impulse"); // target 1 to excile
addTarget(playerA, "Blasphemous Act"); // target 2 to excile
setChoice(playerA, "Yes"); // pay {3} and copy spell
setChoice(playerA, "Yes"); // Change targets
addTarget(playerA, "Night's Whisper");

View file

@ -1,4 +1,3 @@
package org.mage.test.cards.cost.splitcards;
import mage.constants.PhaseStep;
@ -7,7 +6,6 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class CastSplitCardsFromOtherZonesTest extends CardTestPlayerBase {
@ -27,31 +25,6 @@ public class CastSplitCardsFromOtherZonesTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Mindclaw Shaman"); // Creature {4}{R}
addCard(Zone.BATTLEFIELD, playerB, "Sanguine Bond", 1); // Enchantment to destroy
// Wear
// Destroy target artifact.
// Tear
// Destroy target enchantment.
addCard(Zone.HAND, playerB, "Wear // Tear"); // Instant {1}{R} // {W}
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mindclaw Shaman");
addTarget(playerA, "Sanguine Bond");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, "Mindclaw Shaman", 1);
assertGraveyardCount(playerB, "Wear // Tear", 1);
assertGraveyardCount(playerB, "Sanguine Bond", 1);
}
@Test
public void testCastFearFromOpponentsHand() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5);
// When Mindclaw Shaman enters the battlefield, target opponent reveals their hand.
// You may cast an instant or sorcery card from it without paying its mana cost.
addCard(Zone.HAND, playerA, "Mindclaw Shaman"); // Creature {4}{R}
addCard(Zone.BATTLEFIELD, playerB, "Icy Manipulator", 1); // Artifact to destroy
// Wear
// Destroy target artifact.
@ -60,7 +33,42 @@ public class CastSplitCardsFromOtherZonesTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerB, "Wear // Tear"); // Instant {1}{R} // {W}
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mindclaw Shaman");
addTarget(playerA, "Icy Manipulator");
addTarget(playerA, playerB);
setChoice(playerA, "Wear // Tear"); // select card
setChoice(playerA, "Yes"); // confirm to cast
setChoice(playerA, "Tear"); // select tear side
addTarget(playerA, "Sanguine Bond"); // target for tear
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, "Mindclaw Shaman", 1);
assertGraveyardCount(playerB, "Wear // Tear", 1);
assertGraveyardCount(playerB, "Icy Manipulator", 0);
assertGraveyardCount(playerB, "Sanguine Bond", 1);
}
@Test
public void testCastWearFromOpponentsHand() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5);
// When Mindclaw Shaman enters the battlefield, target opponent reveals their hand.
// You may cast an instant or sorcery card from it without paying its mana cost.
addCard(Zone.HAND, playerA, "Mindclaw Shaman"); // Creature {4}{R}
addCard(Zone.BATTLEFIELD, playerB, "Sanguine Bond", 1); // Enchantment to destroy
addCard(Zone.BATTLEFIELD, playerB, "Icy Manipulator", 1); // Artifact to destroy
// Wear
// Destroy target artifact.
// Tear
// Destroy target enchantment.
addCard(Zone.HAND, playerB, "Wear // Tear"); // Instant {1}{R} // {W}
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mindclaw Shaman");
addTarget(playerA, playerB);
setChoice(playerA, "Wear // Tear"); // select card
setChoice(playerA, "Yes"); // confirm to cast
setChoice(playerA, "Wear"); // select wear side
addTarget(playerA, "Icy Manipulator"); // target for wear
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
@ -68,7 +76,7 @@ public class CastSplitCardsFromOtherZonesTest extends CardTestPlayerBase {
assertPermanentCount(playerA, "Mindclaw Shaman", 1);
assertGraveyardCount(playerB, "Wear // Tear", 1);
assertGraveyardCount(playerB, "Icy Manipulator", 1);
assertGraveyardCount(playerB, "Sanguine Bond", 0);
}
@Test
@ -87,16 +95,20 @@ public class CastSplitCardsFromOtherZonesTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerB, "Wear // Tear"); // Instant {1}{R} // {W}
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mindclaw Shaman");
addTarget(playerA, "Sanguine Bond");
addTarget(playerA, playerB);
setChoice(playerA, "Wear // Tear"); // select card
setChoice(playerA, "Yes"); // confirm to cast
setChoice(playerA, "Wear // Tear"); // select fused
addTarget(playerA, "Icy Manipulator"); // target for wear
addTarget(playerA, "Sanguine Bond"); // target for tear
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, "Mindclaw Shaman", 1);
assertGraveyardCount(playerB, "Wear // Tear", 1);
assertGraveyardCount(playerB, "Sanguine Bond", 1);
assertGraveyardCount(playerB, "Icy Manipulator", 1);
assertGraveyardCount(playerB, "Sanguine Bond", 1);
}
/**
@ -119,7 +131,7 @@ public class CastSplitCardsFromOtherZonesTest extends CardTestPlayerBase {
attack(2, playerB, "Etali, Primal Storm");
setChoice(playerB, "Yes");
setChoice(playerB, "Cast Fire");
setChoice(playerB, "Fire");
addTarget(playerB, "Silvercoat Lion");
setStopAt(2, PhaseStep.END_COMBAT);

View file

@ -1,14 +1,12 @@
package org.mage.test.cards.dynamicvalue;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.player.TestPlayer;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author BetaSteward
*/
public class SweepTest extends CardTestPlayerBase {
@ -18,10 +16,9 @@ public class SweepTest extends CardTestPlayerBase {
* Plow Through Reito
* 1W
* Instant -- Arcane
* Sweep -- Return any number of Plains you control to their owner's hand.
* Sweep -- Return any number of Plains you control to their owner's hand.
* Target creature gets +1/+1 until end of turn for each Plains returned this way.
*
*/
*/
@Test
public void testSweep1x() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
@ -29,17 +26,17 @@ public class SweepTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Plow Through Reito");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Plow Through Reito");
addTarget(playerA, "Plains");
addTarget(playerA, "Raging Goblin"); // target to boost
addTarget(playerA, "Plains"); // targets to sweep
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, "Raging Goblin", 1);
assertPermanentCount(playerA, "Plains", 4);
assertPowerToughness(playerA, "Raging Goblin", 2, 2);
assertPowerToughness(playerA, "Raging Goblin", 2, 2);
}
@Test
public void testSweep2x() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
@ -47,15 +44,15 @@ public class SweepTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Plow Through Reito");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Plow Through Reito");
addTarget(playerA, "Plains^Plains");
addTarget(playerA, "Raging Goblin"); // target to boost
addTarget(playerA, "Plains^Plains"); // targets to sweep
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, "Raging Goblin", 1);
assertPermanentCount(playerA, "Plains", 3);
assertPowerToughness(playerA, "Raging Goblin", 3, 3);
assertPowerToughness(playerA, "Raging Goblin", 3, 3);
}
@Test
@ -65,15 +62,15 @@ public class SweepTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Plow Through Reito");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Plow Through Reito");
addTarget(playerA, "Plains^Plains^Plains");
addTarget(playerA, "Raging Goblin"); // target to boost
addTarget(playerA, "Plains^Plains^Plains"); // targets to sweep
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, "Raging Goblin", 1);
assertPermanentCount(playerA, "Plains", 2);
assertPowerToughness(playerA, "Raging Goblin", 4, 4);
assertPowerToughness(playerA, "Raging Goblin", 4, 4);
}
@Test
@ -83,14 +80,16 @@ public class SweepTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Plow Through Reito");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Plow Through Reito");
addTarget(playerA, "Raging Goblin"); // target to boost
addTarget(playerA, TestPlayer.TARGET_SKIP); // targets to sweep (zero)
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
assertPermanentCount(playerA, "Raging Goblin", 1);
assertPermanentCount(playerA, "Plains", 5);
assertPowerToughness(playerA, "Raging Goblin", 1, 1);
assertPowerToughness(playerA, "Raging Goblin", 1, 1);
}
}

View file

@ -1,4 +1,3 @@
package org.mage.test.cards.enchantments;
import mage.constants.PhaseStep;
@ -7,93 +6,229 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
* @author LevelX2, JayDi85
*/
public class OathOfLiegesTest extends CardTestPlayerBase {
//addCard(Zone.BATTLEFIELD, playerA, "Hypersonic Dragon", 1); // can cast spells at any time
//addCard(Zone.HAND, playerA, "Breath of Life", 1); // {3}{W} // return creatures
//addCard(Zone.HAND, playerA, "Replenish", 1); // {3}{W} // return all enchantments
@Test
public void testSearchLandOwner() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
// At the beginning of each player's upkeep, that player chooses target player who controls more lands than he or she does and is their opponent.
// The first player may search their library for a basic land card, put that card onto the battlefield, then shuffle their library.
addCard(Zone.HAND, playerA, "Oath of Lieges", 1); // {1}{W}
addCard(Zone.LIBRARY, playerA, "Plains", 1);
public void testOath_OwnCardTriggersOnOwnTurn() {
// A
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
addCard(Zone.LIBRARY, playerA, "Plains", 5);
addCard(Zone.BATTLEFIELD, playerA, "Oath of Lieges", 1); // {1}{W}
// B
addCard(Zone.BATTLEFIELD, playerB, "Island", 5);
addCard(Zone.BATTLEFIELD, playerB, "Plains", 3);
// turn 1 - A
// oath A triggers for A and activates
addTarget(playerA, playerB); // who control more lands
setChoice(playerA, "Yes"); // search library
addTarget(playerA, "Plains"); // card from library
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Oath of Lieges");
addTarget(playerA, playerB);
addTarget(playerA, "Plains");
setStopAt(3, PhaseStep.PRECOMBAT_MAIN);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
assertPermanentCount(playerA, "Oath of Lieges", 1);
assertPermanentCount(playerA, "Plains", 3);
assertPermanentCount(playerA, "Plains", 4 + 1);
assertPermanentCount(playerB, "Island", 5);
}
@Test
public void testSearchLandOpponent() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
// At the beginning of each player's upkeep, that player chooses target player who controls more lands than he or she does and is their opponent.
// The first player may search their library for a basic land card, put that card onto the battlefield, then shuffle their library.
addCard(Zone.HAND, playerA, "Oath of Lieges", 1); // {1}{W}
public void testOath_OwnCardTriggersOnOpponentTurn() {
// A
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
addCard(Zone.LIBRARY, playerA, "Plains", 5);
addCard(Zone.BATTLEFIELD, playerA, "Hypersonic Dragon", 1); // can cast spells at any time
addCard(Zone.GRAVEYARD, playerA, "Oath of Lieges", 1); // {1}{W}
addCard(Zone.HAND, playerA, "Replenish", 1); // {3}{W} // return all enchantments
// B
addCard(Zone.BATTLEFIELD, playerB, "Plains", 4);
addCard(Zone.LIBRARY, playerB, "Plains", 5);
addCard(Zone.BATTLEFIELD, playerB, "Plains", 1);
addCard(Zone.LIBRARY, playerB, "Plains", 1);
// turn 1 - A (play oath from grave)
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Replenish");
checkPermanentCount("A have oath", 1, PhaseStep.END_TURN, playerA, "Oath of Lieges", 1);
checkPermanentCount("A have 5 plains", 1, PhaseStep.END_TURN, playerA, "Plains", 5);
checkPermanentCount("B have 4 plains", 1, PhaseStep.END_TURN, playerB, "Plains", 4);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Oath of Lieges");
addTarget(playerB, playerA);
addTarget(playerB, "Plains");
// turn 2 - B
// oath A triggers for B and activates
addTarget(playerB, playerA); // who control more lands
setChoice(playerB, "Yes"); // search library
addTarget(playerB, "Plains"); // card from library
setStopAt(2, PhaseStep.PRECOMBAT_MAIN);
setStopAt(2, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
assertPermanentCount(playerA, "Oath of Lieges", 1);
assertPermanentCount(playerA, "Plains", 2);
assertPermanentCount(playerB, "Plains", 2);
assertPermanentCount(playerA, "Plains", 5);
assertPermanentCount(playerB, "Plains", 4 + 1);
}
@Test
public void testSearchLandOwnerCopy() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2);
// At the beginning of each player's upkeep, that player chooses target player who controls more lands than he or she does and is their opponent.
// The first player may search their library for a basic land card, put that card onto the battlefield, then shuffle their library.
addCard(Zone.HAND, playerA, "Oath of Lieges", 1); // {1}{W}
addCard(Zone.LIBRARY, playerA, "Plains", 3);
addCard(Zone.HAND, playerA, "Plains", 1);
public void testOath_OpponentCardTriggersOnOwnTurn() {
// A
addCard(Zone.BATTLEFIELD, playerA, "Plains", 4);
addCard(Zone.LIBRARY, playerA, "Plains", 5);
// B
addCard(Zone.LIBRARY, playerB, "Plains", 5);
addCard(Zone.BATTLEFIELD, playerB, "Plains", 5);
addCard(Zone.BATTLEFIELD, playerB, "Oath of Lieges", 1); // {1}{W}
// turn 1 - A
// oath B triggers for A and activates
addTarget(playerA, playerB); // who control more lands
setChoice(playerA, "Yes"); // search library
addTarget(playerA, "Plains"); // card from library
setStopAt(1, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
assertPermanentCount(playerA, "Plains", 4 + 1);
assertPermanentCount(playerB, "Plains", 5);
}
@Test
public void testOath_DoubleOath() {
// A
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
addCard(Zone.LIBRARY, playerA, "Plains", 5);
addCard(Zone.BATTLEFIELD, playerA, "Oath of Lieges", 2); // {1}{W}
// B
addCard(Zone.BATTLEFIELD, playerB, "Plains", 5);
// turn 1 - A
// oath A triggers for A and activates
// oath B triggers for A and activates
// 1
addTarget(playerA, playerB); // who control more lands
setChoice(playerA, "Yes"); // search library
addTarget(playerA, "Plains"); // card from library
// 2
addTarget(playerA, playerB); // who control more lands
setChoice(playerA, "Yes"); // search library
addTarget(playerA, "Plains"); // card from library
setStopAt(1, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
assertPermanentCount(playerA, "Plains", 3 + 2);
assertPermanentCount(playerB, "Plains", 5);
}
@Test
public void testOath_OwnNormalAndOwnCopy() {
// A
addCard(Zone.BATTLEFIELD, playerA, "Plains", 10);
addCard(Zone.BATTLEFIELD, playerA, "Island", 3); // for copy
addCard(Zone.LIBRARY, playerA, "Plains", 5);
addCard(Zone.BATTLEFIELD, playerA, "Hypersonic Dragon", 1); // can cast spells at any time
addCard(Zone.GRAVEYARD, playerA, "Oath of Lieges", 1); // {1}{W}
addCard(Zone.HAND, playerA, "Replenish", 1); // {3}{W} // return all enchantments
addCard(Zone.HAND, playerA, "Copy Enchantment", 1); // {2}{U} // copy target
// B
addCard(Zone.BATTLEFIELD, playerB, "Plains", 12);
addCard(Zone.BATTLEFIELD, playerB, "Island", 3);
addCard(Zone.HAND, playerB, "Copy Enchantment", 1); // {2}{U}
addCard(Zone.LIBRARY, playerB, "Plains", 3);
addCard(Zone.LIBRARY, playerB, "Plains", 5);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Oath of Lieges");
// turn 1 - A
// cast oath A
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Replenish");
showBattlefield("A perms", 1, PhaseStep.POSTCOMBAT_MAIN, playerA);
// cast oath copy
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Copy Enchantment");
setChoice(playerA, "Yes"); // use copy effect
setChoice(playerA, "Oath of Lieges"); // target for copy
checkPermanentCount("A have 2 oath", 1, PhaseStep.END_TURN, playerA, "Oath of Lieges", 2);
checkPermanentCount("A have 10 plains", 1, PhaseStep.END_TURN, playerA, "Plains", 10);
checkPermanentCount("B have 12 plains", 1, PhaseStep.END_TURN, playerB, "Plains", 12);
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Copy Enchantment");
setChoice(playerB, "Oath of Lieges");
// turn 2 - B
// oath A triggers for B and do nothing
// copy oath A triggers for B and do nothing
checkPermanentCount("A have 10 plains", 1, PhaseStep.END_TURN, playerA, "Plains", 10);
checkPermanentCount("B have 12 plains", 1, PhaseStep.END_TURN, playerB, "Plains", 12);
// turn 3
addTarget(playerA, playerB);
addTarget(playerA, "Plains"); // 3rd land
addTarget(playerA, "Plains"); // second trigger will fail because target player has no longer more lands than controller
// turn 3 - A
// oath A triggers for A and activates
// copy oath A triggers for A and activates
// 1
addTarget(playerA, playerB); // who control more lands
setChoice(playerA, "Yes"); // search library
addTarget(playerA, "Plains"); // card from library
// 2
addTarget(playerA, playerB); // who control more lands
setChoice(playerA, "Yes"); // search library
addTarget(playerA, "Plains"); // card from library
playLand(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Plains"); // 4th land
// turn 4
addTarget(playerB, playerA);
addTarget(playerB, "Plains");
addTarget(playerB, "Plains"); // second trigger will fail because target player has no longer more lands than controller
setStopAt(4, PhaseStep.PRECOMBAT_MAIN);
setStopAt(3, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
assertPermanentCount(playerB, "Oath of Lieges", 1);
assertPermanentCount(playerA, "Oath of Lieges", 1);
assertPermanentCount(playerA, "Plains", 10 + 2);
assertPermanentCount(playerB, "Plains", 12);
}
assertPermanentCount(playerB, "Plains", 1);
assertPermanentCount(playerA, "Plains", 4);
@Test
public void testOath_OwnNormalAndOpponentCopy() {
// special test to check targetadjusters (copy card must used target adjuster from original card, not from copied)
// A
addCard(Zone.BATTLEFIELD, playerA, "Plains", 10);
addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
addCard(Zone.LIBRARY, playerA, "Plains", 5);
addCard(Zone.GRAVEYARD, playerA, "Oath of Lieges", 1); // {1}{W}
addCard(Zone.HAND, playerA, "Replenish", 1); // {3}{W} // return all enchantments
addCard(Zone.BATTLEFIELD, playerA, "Hypersonic Dragon", 1); // can cast spells at any time
// B
addCard(Zone.BATTLEFIELD, playerB, "Plains", 12);
addCard(Zone.BATTLEFIELD, playerB, "Island", 3); // for copy
addCard(Zone.LIBRARY, playerB, "Plains", 5);
addCard(Zone.HAND, playerB, "Copy Enchantment", 1); // {2}{U} // copy target
// turn 1 - A
// nothing
// turn 2 - B
// cast oath A
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, "Replenish");
// cast oath copy by opponent
showBattlefield("A perms", 2, PhaseStep.POSTCOMBAT_MAIN, playerA);
showBattlefield("B perms", 2, PhaseStep.POSTCOMBAT_MAIN, playerB);
showAvaileableAbilities("B abils", 2, PhaseStep.POSTCOMBAT_MAIN, playerB);
showHand("B hand", 2, PhaseStep.POSTCOMBAT_MAIN, playerB);
castSpell(2, PhaseStep.POSTCOMBAT_MAIN, playerB, "Copy Enchantment");
setChoice(playerB, "Yes"); // use copy effect
setChoice(playerB, "Oath of Lieges"); // target for copy
checkPermanentCount("A have 1 oath", 2, PhaseStep.END_TURN, playerA, "Oath of Lieges", 1);
checkPermanentCount("B have 1 oath", 2, PhaseStep.END_TURN, playerA, "Oath of Lieges", 1);
checkPermanentCount("A have 10 plains", 2, PhaseStep.END_TURN, playerA, "Plains", 10);
checkPermanentCount("B have 12 plains", 2, PhaseStep.END_TURN, playerB, "Plains", 12);
showLibrary("lib B", 2, PhaseStep.END_TURN, playerB);
// turn 3 - A
// oath A triggers for A and activates
// copy oath B triggers for A and activates
// 1
addTarget(playerA, playerB); // who control more lands
setChoice(playerA, "Yes"); // search library
addTarget(playerA, "Plains"); // card from library
// 2
addTarget(playerA, playerB); // who control more lands
setChoice(playerA, "Yes"); // search library
addTarget(playerA, "Plains"); // card from library
setStopAt(3, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
assertPermanentCount(playerA, "Plains", 10 + 2);
assertPermanentCount(playerB, "Plains", 12);
}
}

View file

@ -1,7 +1,7 @@
package org.mage.test.cards.enchantments;
import mage.abilities.keyword.FlyingAbility;
import mage.constants.EmptyNames;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.filter.Filter;
@ -11,7 +11,6 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class StarfieldOfNyxTest extends CardTestPlayerBase {
@ -22,7 +21,6 @@ public class StarfieldOfNyxTest extends CardTestPlayerBase {
* Starfield of Nyx not only turned both of them into creatures (it
* shouldn't, because they're auras), but it also destroyed them. The
* manifests stayed on the battlefield without Flying or Hexproof.
*
*/
@Test
public void testCloudform() {
@ -49,7 +47,7 @@ public class StarfieldOfNyxTest extends CardTestPlayerBase {
execute();
assertGraveyardCount(playerA, "Thopter Spy Network", 0);
assertPowerToughness(playerA, "", 2, 2, Filter.ComparisonScope.All); // the manifested cards
assertPowerToughness(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 2, 2, Filter.ComparisonScope.All); // the manifested cards
assertPermanentCount(playerA, "Starfield of Nyx", 1);
assertPowerToughness(playerA, "Thopter Spy Network", 4, 4, Filter.ComparisonScope.All);
assertPermanentCount(playerA, "Cloudform", 2);
@ -97,19 +95,19 @@ public class StarfieldOfNyxTest extends CardTestPlayerBase {
Assert.assertEquals("Singing Bell Strike not on the battlefield", false, true);
}
}
@Test
public void testStarfieldOfNyxLayers() {
addCard(Zone.BATTLEFIELD, playerA, "Starfield of Nyx"); // enchantments you control become creatures
addCard(Zone.BATTLEFIELD, playerA, "Humility"); // creatures lose all abilities and are 1/1
addCard(Zone.BATTLEFIELD, playerA, "Pharika, God of Affliction"); // enchantment
addCard(Zone.BATTLEFIELD, playerA, "Emrakul, the Aeons Torn"); //15/15 creature
addCard(Zone.BATTLEFIELD, playerA, "Crusade", 4); // enchantments to fulfill requirement of Starfield of Nyx
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertPowerToughness(playerA, "Pharika, God of Affliction", 3, 3, Filter.ComparisonScope.All);
assertPowerToughness(playerA, "Humility", 4, 4, Filter.ComparisonScope.All);
// Humility loses its ability in layer 6. Layer 7 never gets Humility's effect
@ -117,6 +115,6 @@ public class StarfieldOfNyxTest extends CardTestPlayerBase {
Permanent emrakul = getPermanent("Emrakul, the Aeons Torn", playerA.getId());
Assert.assertNotNull(emrakul);
Assert.assertFalse(emrakul.getAbilities().contains(FlyingAbility.getInstance())); // loses flying though
}
}

View file

@ -1,5 +1,6 @@
package org.mage.test.cards.facedown;
import mage.constants.EmptyNames;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
@ -13,13 +14,12 @@ public class GhastlyConscriptionTest extends CardTestPlayerBase {
/**
* Ghastly Conscription
* Sorcery, 5BB (7)
* Exile all creature cards from target player's graveyard in a face-down pile,
* shuffle that pile, then manifest those cards. (To manifest a card, put it
* onto the battlefield face down as a 2/2 creature. Turn it face up any time
* Exile all creature cards from target player's graveyard in a face-down pile,
* shuffle that pile, then manifest those cards. (To manifest a card, put it
* onto the battlefield face down as a 2/2 creature. Turn it face up any time
* for its mana cost if it's a creature card.)
*
*/
// test that cards exiled using Ghastly Conscription return face down
@Test
public void testGhastlyConscription() {
@ -36,9 +36,9 @@ public class GhastlyConscriptionTest extends CardTestPlayerBase {
assertLife(playerA, 20);
assertLife(playerB, 20);
assertGraveyardCount(playerA, 2);
assertPermanentCount(playerA, "", 2);
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 2);
}

View file

@ -1,13 +1,12 @@
package org.mage.test.cards.facedown;
import mage.constants.EmptyNames;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class ObscuringAetherTest extends CardTestPlayerBase {
@ -15,7 +14,6 @@ public class ObscuringAetherTest extends CardTestPlayerBase {
/**
* Obscuring Aether cannot turn into a face down 2/2 like it should. When
* activating the ability to turn it over it, it dies immediately.
*
*/
// test that cards exiled using Ghastly Conscription return face down
@Test
@ -35,8 +33,8 @@ public class ObscuringAetherTest extends CardTestPlayerBase {
assertHandCount(playerA, "Obscuring Aether", 0);
assertGraveyardCount(playerA, "Obscuring Aether", 0);
assertPermanentCount(playerA, "", 1);
assertPowerToughness(playerA, "", 2, 2);
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
assertPowerToughness(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 2, 2);
}

View file

@ -1,6 +1,6 @@
package org.mage.test.cards.rules;
import mage.constants.EmptyNames;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.counters.CounterType;
@ -8,7 +8,6 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class CantCastTest extends CardTestPlayerBase {
@ -113,7 +112,7 @@ public class CantCastTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, "", 0);
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 0);
assertHandCount(playerA, "Pine Walker", 1);
}

View file

@ -1,4 +1,3 @@
package org.mage.test.cards.single;
import mage.constants.PhaseStep;
@ -7,8 +6,7 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
* @author LevelX2, JayDi85
*/
public class MisdirectionTest extends CardTestPlayerBase {
@ -17,10 +15,58 @@ public class MisdirectionTest extends CardTestPlayerBase {
* Tests if Misdirection for target opponent works correctly
* https://github.com/magefree/mage/issues/574
*/
@Test
public void testChangeTargetOpponent() {
public void test_RakshaDiscardWorks() {
// Target opponent discards two cards. Put the top two cards of your library into your graveyard.
addCard(Zone.HAND, playerA, "Rakshasa's Secret");
addCard(Zone.HAND, playerA, "Rakshasa's Secret"); // {2}{B}
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
addCard(Zone.HAND, playerB, "Silvercoat Lion", 2);
addCard(Zone.HAND, playerB, "Ashcoat Bear", 5);
// A cast discard
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Rakshasa's Secret", playerB);
setChoice(playerB, "Silvercoat Lion"); // select target 1
setChoice(playerB, "Silvercoat Lion"); // select target 2
checkHandCardCount("B haven't lions", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Silvercoat Lion", 0);
checkHandCardCount("B have 5 bears", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Ashcoat Bear", 5);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
}
@Test
public void test_MisdirectionRetargetWorks() {
// Return target permanent to its owners hand.
addCard(Zone.HAND, playerA, "Boomerang", 1); // {U}{U}
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
addCard(Zone.BATTLEFIELD, playerA, "Ashcoat Bear", 1);
// Change the target of target spell with a single target.
addCard(Zone.HAND, playerB, "Misdirection"); // {3}{U}{U}
addCard(Zone.BATTLEFIELD, playerB, "Island", 5);
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 1);
// A cast Boomerang to remove lion
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Boomerang", "Silvercoat Lion");
// B counter it by Misdirection and remove bear
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Misdirection", "Boomerang", "Boomerang");
addTarget(playerB, "Ashcoat Bear");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
assertGraveyardCount(playerA, "Boomerang", 1);
assertPermanentCount(playerA, "Ashcoat Bear", 0);
assertGraveyardCount(playerB, "Misdirection", 1);
assertPermanentCount(playerB, "Silvercoat Lion", 1);
}
@Test
public void test_MisdirectionCantTargetToIllegal() {
// Target opponent discards two cards. Put the top two cards of your library into your graveyard.
addCard(Zone.HAND, playerA, "Rakshasa's Secret"); // {2}{B}
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
/*
Misdirection {3}{U}{U}
@ -30,23 +76,31 @@ public class MisdirectionTest extends CardTestPlayerBase {
*/
addCard(Zone.HAND, playerB, "Misdirection");
addCard(Zone.HAND, playerB, "Silvercoat Lion", 2);
addCard(Zone.HAND, playerB, "Ashcoat Bear", 5);
addCard(Zone.BATTLEFIELD, playerB, "Island", 5);
// cast Raksha and select B
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Rakshasa's Secret", playerB);
// cast misdir, but it's not apply and taget will be same
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Misdirection", "Rakshasa's Secret", "Rakshasa's Secret");
addTarget(playerB, playerA); // only legal target is player B as opponent - so player A should not be allowed
setStopAt(1, PhaseStep.BEGIN_COMBAT);
// B must select cards to discard (2 lions, not bears)
setChoice(playerB, "Silvercoat Lion"); // select target 1
setChoice(playerB, "Silvercoat Lion"); // select target 2
checkHandCardCount("B haven't lions", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Silvercoat Lion", 0);
checkHandCardCount("B have 5 bears", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Ashcoat Bear", 5);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
assertGraveyardCount(playerA, "Rakshasa's Secret", 1);
assertGraveyardCount(playerB, "Misdirection", 1);
assertHandCount(playerB, "Silvercoat Lion", 0);
}
// check to change target permanent creature legal to to a creature the opponent of the spell controller controls
@Test
public void testChangePublicExecution() {
public void test_ChangePublicExecution() {
// Destroy target creature an opponent controls. Each other creature that player controls gets -2/-0 until end of turn.
addCard(Zone.HAND, playerA, "Public Execution");
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 6);
@ -60,26 +114,27 @@ public class MisdirectionTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox", 1);
addCard(Zone.BATTLEFIELD, playerB, "Custodian of the Trove", 1); // 4/3
addCard(Zone.BATTLEFIELD, playerB, "Island", 5);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Public Execution", "Pillarfield Ox");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Misdirection", "Public Execution", "Public Execution");
addTarget(playerB, "Custodian of the Trove");
addTarget(playerB, "Custodian of the Trove");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
assertGraveyardCount(playerA, "Public Execution", 1);
assertGraveyardCount(playerB, "Misdirection", 1);
assertGraveyardCount(playerB, "Custodian of the Trove",1);
assertGraveyardCount(playerB, "Custodian of the Trove", 1);
assertPermanentCount(playerB, "Pillarfield Ox", 1);
assertPowerToughness(playerB, "Pillarfield Ox", 0, 4);
}
}
// check to change target permanent creature not legal to to a creature the your opponent controls
@Test
public void testChangePublicExecution2() {
public void test_ChangePublicExecution2() {
// Destroy target creature an opponent controls. Each other creature that player controls gets -2/-0 until end of turn.
addCard(Zone.HAND, playerA, "Public Execution");
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 6);
@ -94,13 +149,13 @@ public class MisdirectionTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerB, "Pillarfield Ox", 1);
addCard(Zone.BATTLEFIELD, playerB, "Custodian of the Trove", 1); // 4/3
addCard(Zone.BATTLEFIELD, playerB, "Island", 5);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Public Execution", "Custodian of the Trove");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Misdirection", "Public Execution", "Public Execution");
addTarget(playerB, "Keeper of the Lens");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
assertGraveyardCount(playerA, "Public Execution", 1);
assertGraveyardCount(playerB, "Misdirection", 1);
@ -108,8 +163,7 @@ public class MisdirectionTest extends CardTestPlayerBase {
assertPermanentCount(playerB, "Pillarfield Ox", 1);
assertPowerToughness(playerB, "Pillarfield Ox", 0, 4);
assertGraveyardCount(playerB, "Custodian of the Trove",1);
}
assertGraveyardCount(playerB, "Custodian of the Trove", 1);
}
}

View file

@ -1,5 +1,6 @@
package org.mage.test.cards.single.fut;
import mage.constants.EmptyNames;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.filter.Filter;
@ -50,8 +51,8 @@ public class MuragandaPetroglyphsTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, "", 1);
assertPowerToughness(playerA, "", 4, 4);
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
assertPowerToughness(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 4, 4);
}
@Test
@ -69,8 +70,8 @@ public class MuragandaPetroglyphsTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, "", 1);
assertPowerToughness(playerA, "", 2, 2);
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
assertPowerToughness(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 2, 2);
}
@Test
@ -155,7 +156,7 @@ public class MuragandaPetroglyphsTest extends CardTestPlayerBase {
// Enchanted creature doesn't untap during itscontroller's untap step.
addCard(Zone.HAND, playerA, "Dehydration");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA,"Rancor", "Grizzly Bears");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Rancor", "Grizzly Bears");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dehydration", "Runeclaw Bear");

View file

@ -66,23 +66,24 @@ public class PrizedAmalgamTest extends CardTestPlayerBase {
public void testOpponentReturnsCreatureFromGrave() {
addCard(Zone.HAND, playerA, "Reanimate", 1);
addCard(Zone.GRAVEYARD, playerA, "Hill Giant", 1); // {3}{R} 3/3
addCard(Zone.GRAVEYARD, playerA, "Hill Giant", 1); // {3}{R} 3/3, 4 CMC
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
addCard(Zone.GRAVEYARD, playerB, "Prized Amalgam", 1);
addCard(Zone.GRAVEYARD, playerB, "Prized Amalgam", 1); // {1}{U}{B}, 3 CMC
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reanimate", "Hill Giant");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reanimate");
addTarget(playerA, "Hill Giant");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertLife(playerA, 16); // lose 4 life from reanimate 4 CMC
assertLife(playerA, 16); // lose 4 life from reanimate 4 CMC by Hill Giant
assertPermanentCount(playerA, "Hill Giant", 1);
assertPermanentCount(playerB, "Prized Amalgam", 0); // should not recur
assertGraveyardCount(playerB, "Prized Amalgam", 1); // stays in grave
}
/*
* Test opponent returning a card from your graveyard to battlefield.
* Test opponent returning a card from your graveyard to battlefield.
*/
@Test
public void testOpponentReturnsCreatureFromYourGrave() {

View file

@ -1,7 +1,7 @@
package org.mage.test.cards.single.ths;
import mage.constants.CardType;
import mage.constants.EmptyNames;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.game.permanent.Permanent;
@ -10,26 +10,25 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class PurphorosGodOfTheForgeTest extends CardTestPlayerBase {
/**
* I had a situation come up today where I had a Purphoros on the field
* and 5 devotion with an Eidolon and Phoenix. My opponent killed the
* and 5 devotion with an Eidolon and Phoenix. My opponent killed the
* Phoenix, but Purphoros still was "turned on".
*/
@Test
public void testFacedownNotCountedForDevotion1() {
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 5);
addCard(Zone.HAND, playerB, "Reach of Shadows");
// Indestructible
// As long as your devotion to red is less than five, Purphoros isn't a creature.
// Whenever another creature enters the battlefield under your control, Purphoros deals 2 damage to each opponent.
// {2}{R}: Creatures you control get +1/+0 until end of turn.
addCard(Zone.BATTLEFIELD, playerA, "Purphoros, God of the Forge");
// Whenever a player casts a spell with converted mana cost 3 or less,
// Eidolon of the Great Revel deals 2 damage to that player.
addCard(Zone.BATTLEFIELD, playerA, "Eidolon of the Great Revel");
@ -46,24 +45,24 @@ public class PurphorosGodOfTheForgeTest extends CardTestPlayerBase {
assertLife(playerA, 20);
assertLife(playerB, 18); // 2 damage from the returning Phoenix
assertGraveyardCount(playerB, "Reach of Shadows", 1);
assertPermanentCount(playerA, "Ashcloud Phoenix", 0);
assertPermanentCount(playerA, "", 1);
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
Permanent purphorosGodOfTheForge = getPermanent("Purphoros, God of the Forge", playerA);
Assert.assertFalse("Purphoros may not be a creature but it is", purphorosGodOfTheForge.getCardType().contains(CardType.CREATURE));
}
@Test
public void testFacedownNotCountedForDevotion2() {
public void testFacedownNotCountedForDevotion2() {
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
// Indestructible
// As long as your devotion to red is less than five, Purphoros isn't a creature.
// Whenever another creature enters the battlefield under your control, Purphoros deals 2 damage to each opponent.
// {2}{R}: Creatures you control get +1/+0 until end of turn.
addCard(Zone.BATTLEFIELD, playerA, "Purphoros, God of the Forge");
// Whenever a player casts a spell with converted mana cost 3 or less,
// Eidolon of the Great Revel deals 2 damage to that player.
addCard(Zone.BATTLEFIELD, playerA, "Eidolon of the Great Revel");
@ -81,18 +80,18 @@ public class PurphorosGodOfTheForgeTest extends CardTestPlayerBase {
execute();
assertPermanentCount(playerA, "Ashcloud Phoenix", 0);
assertPermanentCount(playerA, "", 1);
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
assertLife(playerA, 18); // 2 damage from Eidolon of the Great Revel
assertLife(playerB, 18); // 2 damage from Purphoros for the morphed Phoenix
Permanent purphorosGodOfTheForge = getPermanent("Purphoros, God of the Forge", playerA);
Assert.assertFalse("Purphoros may not be a creature but it is", purphorosGodOfTheForge.getCardType().contains(CardType.CREATURE));
}
}
@Test
public void testHybridManaCostsForDevotion() {
// Indestructible
// As long as your devotion to red is less than five, Purphoros isn't a creature.
// Whenever another creature enters the battlefield under your control, Purphoros deals 2 damage to each opponent.
@ -101,11 +100,11 @@ public class PurphorosGodOfTheForgeTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, "Goblin Guide", 1); // {R}
addCard(Zone.HAND, playerA, "Boros Reckoner", 1); // {R/W}{R/W}{R/W}
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Boros Reckoner");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertLife(playerB, 18);
Permanent purphorosGodOfTheForge = getPermanent("Purphoros, God of the Forge", playerA);
Assert.assertTrue("Purphoros should be a creature now but is not", purphorosGodOfTheForge.getCardType().contains(CardType.CREATURE));

View file

@ -1,4 +1,3 @@
package org.mage.test.cards.triggers;
import mage.constants.PhaseStep;
@ -7,7 +6,6 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class SpellskiteTest extends CardTestPlayerBase {
@ -30,6 +28,7 @@ public class SpellskiteTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
assertGraveyardCount(playerA, "Lightning Bolt", 1);
assertPermanentCount(playerA, "Spellskite", 1);
@ -80,6 +79,7 @@ public class SpellskiteTest extends CardTestPlayerBase {
setStopAt(2, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
assertPermanentCount(playerA, "Spellskite", 1);
assertPermanentCount(playerB, "Frost Titan", 1);
@ -119,6 +119,7 @@ public class SpellskiteTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
assertGraveyardCount(playerB, "Lightning Bolt", 1);
@ -160,6 +161,7 @@ public class SpellskiteTest extends CardTestPlayerBase {
setStopAt(2, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
assertGraveyardCount(playerA, "Cryptic Command", 1);
@ -188,16 +190,16 @@ public class SpellskiteTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{U/P}: Change a target of target spell or ability to {this}.", "Lightning Bolt");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{U/P}: Change a target", "Lightning Bolt");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
assertGraveyardCount(playerA, "Lightning Bolt", 1);
assertLife(playerA, 20);
assertLife(playerB, 18);
}
/**
@ -219,6 +221,7 @@ public class SpellskiteTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
assertGraveyardCount(playerA, "Flame Slash", 1);
assertPowerToughness(playerB, "Spellskite", 3, 7);
@ -238,24 +241,36 @@ public class SpellskiteTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerB, "Spellskite");
addCard(Zone.BATTLEFIELD, playerB, "Scute Mob");
addCard(Zone.BATTLEFIELD, playerB, "Island");
//
addCard(Zone.BATTLEFIELD, playerB, "Memnite"); // 1/1
addCard(Zone.BATTLEFIELD, playerB, "Royal Assassin"); // 1/1
addCard(Zone.BATTLEFIELD, playerB, "Blinking Spirit"); // 2/2
addCard(Zone.BATTLEFIELD, playerB, "Pearled Unicorn"); // 2/2
addCard(Zone.HAND, playerA, "Fiery Justice");
// A cast Fiery Justice
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Fiery Justice");
addTarget(playerA, "Scute Mob");
setChoice(playerA, "X=1");
addTarget(playerA, "Spellskite");
setChoice(playerA, "X=4");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{UP}: Change a target of target spell or ability to {this}.", "Fiery Justice", "Fiery Justice");
setChoice(playerA, "Yes");
addTarget(playerA, playerB); // 5 life to B
addTarget(playerA, "Scute Mob^X=1"); // target 1
addTarget(playerA, "Spellskite^X=4"); // target 2
// B activate Spellskite, but can't change any targets cause it's already targeted
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{U/P}: Change a target", "Fiery Justice", "Fiery Justice");
setChoice(playerB, "Yes"); // pay 2 life
showBattlefield("B battle", 1, PhaseStep.BEGIN_COMBAT, playerB);
showGraveyard("B grave", 1, PhaseStep.BEGIN_COMBAT, playerB);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
assertLife(playerB, 20 + 5 - 2);
assertGraveyardCount(playerB, 2);
assertGraveyardCount(playerB, "Scute Mob", 1);
assertGraveyardCount(playerB, "Spellskite", 1);
}
@Test
public void testThatSplitDamageCanGetRedirected() {
/* Standard redirect test
The Spellskite should die from the 5 damage that was redirected to it
@ -267,59 +282,64 @@ public class SpellskiteTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerB, "Spellskite");// 0/4 creature
addCard(Zone.BATTLEFIELD, playerB, "Scute Mob"); // 1/1 creauture
addCard(Zone.BATTLEFIELD, playerB, "Island");
addCard(Zone.BATTLEFIELD, playerB, "Memnite"); // 1/1
addCard(Zone.BATTLEFIELD, playerB, "Royal Assassin"); // 1/1
addCard(Zone.BATTLEFIELD, playerB, "Blinking Spirit"); // 2/2
addCard(Zone.BATTLEFIELD, playerB, "Pearled Unicorn"); // 2/2
addCard(Zone.HAND, playerA, "Fiery Justice");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Fiery Justice"); // 5 damage distributed to any number of targets
addTarget(playerA, "Scute Mob");
setChoice(playerA, "X=5");
addTarget(playerA, "Scute Mob^X=5");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{UP}: Change a target of target spell or ability to {this}.", "Fiery Justice", "Fiery Justice");
setChoice(playerA, "Yes");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{U/P}: Change a target", "Fiery Justice", "Fiery Justice");
setChoice(playerB, "Yes"); // pay 2 life
setChoice(playerB, "Yes"); // retarget
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
assertLife(playerB, 20 + 5 - 2);
assertGraveyardCount(playerB, 1);
assertPermanentCount(playerB, "Scute Mob", 1);
}
@Test
public void testThatSplitDamageGetsRedirectedFromTheCorrectChoice() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
addCard(Zone.BATTLEFIELD, playerB, "Spellskite");// 0/4 creature
addCard(Zone.BATTLEFIELD, playerB, "Memnite"); // 1/1 creauture
addCard(Zone.BATTLEFIELD, playerB, "Royal Assassin");
addCard(Zone.BATTLEFIELD, playerB, "Blinking Spirit");
addCard(Zone.BATTLEFIELD, playerB, "Pearled Unicorn");
addCard(Zone.BATTLEFIELD, playerB, "Memnite"); // 1/1
addCard(Zone.BATTLEFIELD, playerB, "Royal Assassin"); // 1/1
addCard(Zone.BATTLEFIELD, playerB, "Blinking Spirit"); // 2/2
addCard(Zone.BATTLEFIELD, playerB, "Pearled Unicorn"); // 2/2
addCard(Zone.BATTLEFIELD, playerB, "Island");
addCard(Zone.HAND, playerA, "Fiery Justice");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Fiery Justice"); // 5 damage distributed to any number of targets
addTarget(playerA, "Memnite");
setChoice(playerA, "X=1");
addTarget(playerA, "Royal Assassin");
setChoice(playerA, "X=1");
addTarget(playerA, "Blinking Spirit");
setChoice(playerA, "X=1");
addTarget(playerA, "Pearled Unicorn");
setChoice(playerA, "X=2");//the unicorn deserves it
addTarget(playerA, "Royal Assassin^X=1");
addTarget(playerA, "Blinking Spirit^X=2");
addTarget(playerA, "Pearled Unicorn^X=2");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{UP}: Change a target of target spell or ability to {this}.", "Fiery Justice", "Fiery Justice");
setChoice(playerA, "No");
setChoice(playerA, "No");
setChoice(playerA, "No");
setChoice(playerA, "Yes"); //of course
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{U/P}: Change a target", "Fiery Justice", "Fiery Justice");
setChoice(playerB, "Yes"); // pay 2 life
setChoice(playerB, "No"); // skip royal
setChoice(playerB, "No"); // skip blink
setChoice(playerB, "Yes"); // change pearl
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
assertGraveyardCount(playerB, 3);
assertPermanentCount(playerB, "Pearled Unicorn", 1);//it lives on
assertPowerToughness(playerB, "Spellskite", 0, 2);
assertLife(playerB, 20 + 5 - 2);
assertGraveyardCount(playerB, "Memnite", 0);
assertGraveyardCount(playerB, "Royal Assassin", 1);
assertGraveyardCount(playerB, "Blinking Spirit", 1);
assertGraveyardCount(playerB, "Pearled Unicorn", 0);
assertGraveyardCount(playerB, "Spellskite", 0);
}
}

View file

@ -1,4 +1,3 @@
package org.mage.test.cards.triggers.dies;
import mage.constants.PhaseStep;
@ -7,7 +6,6 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class BrainMaggotTest extends CardTestPlayerBase {
@ -16,7 +14,6 @@ public class BrainMaggotTest extends CardTestPlayerBase {
* When Brain Maggot enters the battlefield, target opponent reveals his or
* her hand and you choose a nonland card from it. Exile that card until
* Brain Maggot leaves the battlefield.
*
*/
@Test
public void testCardFromHandWillBeExiled() {
@ -26,10 +23,12 @@ public class BrainMaggotTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerB, "Bloodflow Connoisseur", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Brain Maggot");
addTarget(playerA, "Bloodflow Connoisseur");
addTarget(playerA, playerB);
setChoice(playerA, "Bloodflow Connoisseur");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
assertPermanentCount(playerA, "Brain Maggot", 1);
assertExileCount("Bloodflow Connoisseur", 1);
@ -45,12 +44,22 @@ public class BrainMaggotTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerB, "Lightning Bolt", 1);
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 2);
// exile
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Brain Maggot");
addTarget(playerA, "Bloodflow Connoisseur");
castSpell(1, PhaseStep.BEGIN_COMBAT, playerB, "Lightning Bolt", "Brain Maggot");
addTarget(playerA, playerB);
setChoice(playerA, "Bloodflow Connoisseur");
showExile("exile", 1, PhaseStep.BEGIN_COMBAT, playerB);
checkExileCount("blood must be in exile", 1, PhaseStep.BEGIN_COMBAT, playerB, "Bloodflow Connoisseur", 1);
setStopAt(1, PhaseStep.DECLARE_ATTACKERS);
// return
castSpell(1, PhaseStep.END_COMBAT, playerB, "Lightning Bolt", "Brain Maggot");
checkPermanentCount("brain must die", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Brain Maggot", 0);
checkExileCount("blood must return from exile", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Bloodflow Connoisseur", 0);
checkHandCardCount("blood must be in hand", 1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Bloodflow Connoisseur", 1);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
assertGraveyardCount(playerA, "Brain Maggot", 1);
assertGraveyardCount(playerB, "Lightning Bolt", 1);
@ -68,11 +77,14 @@ public class BrainMaggotTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 2);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mesmeric Fiend");
addTarget(playerA, "Bloodflow Connoisseur");
addTarget(playerA, playerB);
setChoice(playerA, "Bloodflow Connoisseur");
//
castSpell(1, PhaseStep.BEGIN_COMBAT, playerB, "Lightning Bolt", "Mesmeric Fiend");
setStopAt(1, PhaseStep.DECLARE_ATTACKERS);
execute();
assertAllCommandsUsed();
assertGraveyardCount(playerA, "Mesmeric Fiend", 1);
assertGraveyardCount(playerB, "Lightning Bolt", 1);

View file

@ -1,4 +1,3 @@
package org.mage.test.cards.triggers.dies;
import mage.constants.PhaseStep;
@ -7,7 +6,6 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class OmnathLocusOfRageTest extends CardTestPlayerBase {
@ -27,10 +25,10 @@ public class OmnathLocusOfRageTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerB, "Swamp", 2);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Diabolic Edict", playerA);
addTarget(playerA, playerB);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
assertGraveyardCount(playerB, "Diabolic Edict", 1);
assertGraveyardCount(playerA, "Omnath, Locus of Rage", 1);
@ -53,12 +51,11 @@ public class OmnathLocusOfRageTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 7);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Lightning Bolt", "Lightning Elemental"); // Dying Lightning Elemental does no longer trigger ability of Omnath
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Blastfire Bolt", "Omnath, Locus of Rage", "Lightning Bolt");
addTarget(playerA, playerB);
addTarget(playerA, playerB);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Blastfire Bolt", "Omnath, Locus of Rage");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertAllCommandsUsed();
assertGraveyardCount(playerB, "Lightning Bolt", 1);
assertGraveyardCount(playerB, "Blastfire Bolt", 1);

View file

@ -1,4 +1,3 @@
package org.mage.test.cards.triggers.dies;
import mage.constants.PhaseStep;
@ -7,8 +6,7 @@ import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
* @author LevelX2, JayDi85
*/
public class TidehollowScullerTest extends CardTestPlayerBase {
@ -17,43 +15,104 @@ public class TidehollowScullerTest extends CardTestPlayerBase {
* Test if the same Tidehollow Sculler is cast multiple times, the correct
* corresponding exiled cards are returned
*/
@Test
public void testCardFromHandWillBeExiled() {
public void test_CastOneCardFromHandWillBeExiled() {
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
// Tidehollow Sculler {W}{B}
// When Tidehollow Sculler enters the battlefield, target opponent reveals their hand and you choose a nonland card from it. Exile that card.
// When Tidehollow Sculler leaves the battlefield, return the exiled card to its owner's hand.
addCard(Zone.HAND, playerA, "Tidehollow Sculler", 1);
// Boomerang {U}{U}
// Return target creature card from your graveyard to your hand.
addCard(Zone.HAND, playerA, "Boomerang", 1);
// Scout's Warning {W}
// The next creature card you play this turn can be played as though it had flash.
// Draw a card.
addCard(Zone.HAND, playerA, "Scout's Warning", 1);
addCard(Zone.HAND, playerA, "Tidehollow Sculler", 1); // 2/2
addCard(Zone.HAND, playerA, "Lightning Bolt", 1); // {R}
//
addCard(Zone.HAND, playerB, "Bloodflow Connoisseur", 1);
// cast and exile from hand
checkHandCardCount("B hand must have blood", 1, PhaseStep.UPKEEP, playerB, "Bloodflow Connoisseur", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Tidehollow Sculler");
addTarget(playerA, playerB); // choose opponent
setChoice(playerA, "Bloodflow Connoisseur"); // card to exile
checkHandCardCount("B hand must lost blood", 1, PhaseStep.BEGIN_COMBAT, playerB, "Bloodflow Connoisseur", 0);
// destroy and return card to hand
checkPermanentCount("A must have tide", 1, PhaseStep.END_COMBAT, playerA, "Tidehollow Sculler", 1);
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", "Tidehollow Sculler");
checkPermanentCount("A must lost tide", 1, PhaseStep.END_TURN, playerA, "Tidehollow Sculler", 0);
checkHandCardCount("B must return blood", 1, PhaseStep.END_TURN, playerB, "Bloodflow Connoisseur", 1);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
assertHandCount(playerB, "Bloodflow Connoisseur", 1);
assertPermanentCount(playerA, "Tidehollow Sculler", 0);
}
@Test
public void test_CastTwoCardFromHandWillBeExiled() {
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
addCard(Zone.BATTLEFIELD, playerA, "Island", 2);
addCard(Zone.BATTLEFIELD, playerA, "Plains", 3);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
// Tidehollow Sculler {W}{B}
// When Tidehollow Sculler enters the battlefield, target opponent reveals their hand and you choose a nonland card from it. Exile that card.
// When Tidehollow Sculler leaves the battlefield, return the exiled card to its owner's hand.
addCard(Zone.HAND, playerA, "Tidehollow Sculler@tide", 2); // 2/2
addCard(Zone.HAND, playerA, "Lightning Bolt", 2); // {R}
//
addCard(Zone.HAND, playerB, "Bloodflow Connoisseur", 1);
addCard(Zone.HAND, playerB, "Silvercoat Lion", 1);
// turn 1 - A
// cast 1 and exile from hand
checkHandCardCount("B hand must have blood", 1, PhaseStep.UPKEEP, playerB, "Bloodflow Connoisseur", 1);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Tidehollow Sculler");
addTarget(playerA, "Bloodflow Connoisseur");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Boomerang", "Tidehollow Sculler");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Scout's Warning", null, "Boomerang");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Tidehollow Sculler", null, "", "When {this} leaves the battlefield, return the exiled card to its owner's hand.");
addTarget(playerA, "Silvercoat Lion");
addTarget(playerA, playerB); // choose opponent
setChoice(playerA, "Bloodflow Connoisseur"); // card to exile
checkHandCardCount("B hand must lost blood", 1, PhaseStep.BEGIN_COMBAT, playerB, "Bloodflow Connoisseur", 0);
// cast 2 and exile from hand
checkHandCardCount("B hand must have lion", 1, PhaseStep.END_COMBAT, playerB, "Silvercoat Lion", 1);
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Tidehollow Sculler");
addTarget(playerA, playerB); // choose opponent
setChoice(playerA, "Silvercoat Lion"); // card to exile
checkHandCardCount("B hand must lost lion", 1, PhaseStep.END_TURN, playerB, "Silvercoat Lion", 0);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
// turn 2 - B
// destroy 1 and return card to hand
checkPermanentCount("A must have 2 tide", 2, PhaseStep.UPKEEP, playerA, "Tidehollow Sculler", 2);
checkHandCardCount("B hand must have 0 blood", 2, PhaseStep.UPKEEP, playerB, "Bloodflow Connoisseur", 0);
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "@tide.1");
showHand("B hand", 2, PhaseStep.BEGIN_COMBAT, playerB);
checkPermanentCount("A must have 1 tide", 2, PhaseStep.BEGIN_COMBAT, playerA, "Tidehollow Sculler", 1);
checkHandCardCount("B hand must have 1 blood", 2, PhaseStep.BEGIN_COMBAT, playerB, "Bloodflow Connoisseur", 1);
// destroy 2 and return card to hand
checkPermanentCount("A must have 1 tide", 2, PhaseStep.END_COMBAT, playerA, "Tidehollow Sculler", 1);
checkHandCardCount("B hand must have 0 lion", 2, PhaseStep.END_COMBAT, playerB, "Silvercoat Lion", 0);
castSpell(2, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", "@tide.2");
checkPermanentCount("A must have 0 tide", 2, PhaseStep.END_TURN, playerA, "Tidehollow Sculler", 0);
checkHandCardCount("B hand must have 1 lion", 2, PhaseStep.END_TURN, playerB, "Silvercoat Lion", 1);
setStopAt(2, PhaseStep.END_TURN);
execute();
assertGraveyardCount(playerA,"Boomerang", 1);
assertGraveyardCount(playerA,"Scout's Warning", 1);
assertHandCount(playerB, "Bloodflow Connoisseur", 0); // never comes back because first Tidehollow Sculler left battlefield before target was exiled
assertHandCount(playerB, "Silvercoat Lion", 0);
assertExileCount("Silvercoat Lion", 1);
assertPermanentCount(playerA, "Tidehollow Sculler", 1);
assertAllCommandsUsed();
}
@Test
public void test_MultipleRuns() {
// test random selection by AI (must use direct select by alias, not AI)
for (int i = 1; i <= 10; i++) {
try {
this.reset();
System.out.println("run " + i);
test_CastTwoCardFromHandWillBeExiled();
} catch (Exception e) {
//
}
}
}
}

View file

@ -1,6 +1,6 @@
package org.mage.test.cards.triggers.dies;
import mage.constants.EmptyNames;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
@ -18,7 +18,6 @@ public class WhisperwoodElementalTest extends CardTestPlayerBase {
/**
* Tests that the dies triggered ability of silvercoat lion (gained by sacrificed Whisperwood Elemental)
* triggers as he dies from Ligning Bolt
*
*/
@Test
public void testDiesTriggeredAbility() {
@ -30,17 +29,20 @@ public class WhisperwoodElementalTest extends CardTestPlayerBase {
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Sacrifice {this}: Until end of turn, face-up, nontoken creatures you control gain \"When this creature dies, manifest the top card of your library.");
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", "Silvercoat Lion");
showBattlefield("A battle", 1, PhaseStep.END_TURN, playerA);
showGraveyard("A grave", 1, PhaseStep.END_TURN, playerA);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
assertLife(playerA, 20);
assertLife(playerB, 20);
assertGraveyardCount(playerA, "Whisperwood Elemental", 1);
assertGraveyardCount(playerA, "Silvercoat Lion", 1);
// Manifested creature from dying Silvercoat Lion
assertPermanentCount(playerA, "", 1);
assertPermanentCount(playerA, EmptyNames.FACE_DOWN_CREATURE.toString(), 1);
}
}

View file

@ -58,7 +58,7 @@ public class LastKnownInformationTest extends CardTestPlayerBase {
assertPermanentCount(playerA, "Soldier", 2);
assertGraveyardCount(playerB, "Lightning Bolt", 2);
assertActionCount(playerB, 0);
assertActionsCount(playerB, 0);
}

View file

@ -1,7 +1,5 @@
package org.mage.test.multiplayer;
import java.io.FileNotFoundException;
import mage.constants.MultiplayerAttackOption;
import mage.constants.PhaseStep;
import mage.constants.RangeOfInfluence;
@ -12,8 +10,9 @@ import mage.game.GameException;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestMultiPlayerBase;
import java.io.FileNotFoundException;
/**
*
* @author LevelX2
*/
public class MyriadTest extends CardTestMultiPlayerBase {
@ -72,27 +71,32 @@ public class MyriadTest extends CardTestMultiPlayerBase {
// Myriad (Whenever this creature attacks, for each opponent other than the defending player, put a token that's a copy of this creature onto the battlefield tapped and attacking that player or a planeswalker he or she controls. Exile those tokens at the end of combat.)
addCard(Zone.BATTLEFIELD, playerD, "Caller of the Pack"); // 8/6
// turns: A, D, C, B
// +1: You gain 2 life.
// -1: Put a +1/+1 counter on each creature you control. Those creatures gain vigilance until end of turn.
// -6: Create a white Avatar creature token. It has "This creature's power and toughness are each equal to your life total."
addCard(Zone.BATTLEFIELD, playerA, "Ajani Goldmane");
// +2 life
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "+1:");
checkLife("must have +2 life", 2, PhaseStep.PRECOMBAT_MAIN, playerA, 40 + 2);
// D attack C, create 2 copy of caller (for each opponent exclude defender = 2) and attack to ajani
attack(2, playerD, "Caller of the Pack", playerC);
addTarget(playerD, "Ajani Goldmane");
addTarget(playerD, "Ajani Goldmane"); // select ajani instead playerA for pack attack
checkPermanentCount("must have 3 packs", 2, PhaseStep.END_COMBAT, playerD, "Caller of the Pack", 3);
checkPermanentCount("ajani must die", 2, PhaseStep.END_COMBAT, playerA, "Ajani Goldmane", 0);
checkLife("pack must not damage playerA", 2, PhaseStep.END_COMBAT, playerA, 40 + 2);
checkLife("pack must damage playerB by 8", 2, PhaseStep.END_COMBAT, playerB, 40 - 8);
checkLife("pack must damage playerC", 2, PhaseStep.END_COMBAT, playerC, 40 - 8);
checkLife("pack must not damage playerD", 2, PhaseStep.END_COMBAT, playerD, 40);
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertPermanentCount(playerD, "Caller of the Pack", 1);
assertGraveyardCount(playerA, "Ajani Goldmane", 1);
assertLife(playerA, 42);
assertLife(playerB, 32);
assertLife(playerC, 32);
assertLife(playerD, 40);
}
/**

View file

@ -0,0 +1,73 @@
package org.mage.test.player;
import mage.MageObject;
import mage.abilities.ActivatedAbility;
import mage.abilities.SpellAbility;
import mage.constants.Outcome;
import mage.constants.RangeOfInfluence;
import mage.game.Game;
import mage.player.ai.ComputerPlayer;
import mage.target.Target;
import java.util.LinkedHashMap;
import java.util.UUID;
/**
* @author JayDi85
*/
// mock class to override to override AI logic for test
public class TestComputerPlayer extends ComputerPlayer {
private TestPlayer testPlayerLink;
public TestComputerPlayer(String name, RangeOfInfluence range) {
super(name, range);
}
public void setTestPlayerLink(TestPlayer testPlayerLink) {
this.testPlayerLink = testPlayerLink;
}
@Override
public SpellAbility chooseSpellAbilityForCast(SpellAbility ability, Game game, boolean noMana) {
// copy-paste for TestComputerXXX
// workaround to cast fused cards in tests by it's NAMES (Wear, Tear, Wear // Tear)
// reason: TestPlayer uses outer computerPlayer to cast, not TestPlayer
switch (ability.getSpellAbilityType()) {
case SPLIT:
case SPLIT_FUSED:
case SPLIT_AFTERMATH:
if (!this.testPlayerLink.getChoices().isEmpty()) {
MageObject object = game.getObject(ability.getSourceId());
if (object != null) {
LinkedHashMap<UUID, ActivatedAbility> useableAbilities = this.getSpellAbilities(object, game.getState().getZone(object.getId()), game);
// left, right or fused cast
for (String choose : this.testPlayerLink.getChoices()) {
for (ActivatedAbility activatedAbility : useableAbilities.values()) {
if (activatedAbility instanceof SpellAbility) {
if (((SpellAbility) activatedAbility).getCardName().equals(choose)) {
return (SpellAbility) activatedAbility;
}
}
}
}
}
}
}
// default implementation by AI
return super.chooseSpellAbilityForCast(ability, game, noMana);
}
@Override
public boolean choose(Outcome outcome, Target target, UUID sourceId, Game game) {
// copy-paste for TestComputerXXX
// workaround for discard spells
// reason: TestPlayer uses outer computerPlayer to discard but inner code uses choose
return testPlayerLink.choose(outcome, target, sourceId, game);
}
}

View file

@ -0,0 +1,73 @@
package org.mage.test.player;
import mage.MageObject;
import mage.abilities.ActivatedAbility;
import mage.abilities.SpellAbility;
import mage.constants.Outcome;
import mage.constants.RangeOfInfluence;
import mage.game.Game;
import mage.player.ai.ComputerPlayer7;
import mage.target.Target;
import java.util.LinkedHashMap;
import java.util.UUID;
/**
* @author JayDi85
*/
// mock class to override AI logic in tests
public class TestComputerPlayer7 extends ComputerPlayer7 {
private TestPlayer testPlayerLink;
public TestComputerPlayer7(String name, RangeOfInfluence range, int skill) {
super(name, range, skill);
}
public void setTestPlayerLink(TestPlayer testPlayerLink) {
this.testPlayerLink = testPlayerLink;
}
@Override
public SpellAbility chooseSpellAbilityForCast(SpellAbility ability, Game game, boolean noMana) {
// copy-paste for TestComputerXXX
// workaround to cast fused cards in tests by it's NAMES (Wear, Tear, Wear // Tear)
// reason: TestPlayer uses outer computerPlayer to cast, not TestPlayer
switch (ability.getSpellAbilityType()) {
case SPLIT:
case SPLIT_FUSED:
case SPLIT_AFTERMATH:
if (!this.testPlayerLink.getChoices().isEmpty()) {
MageObject object = game.getObject(ability.getSourceId());
if (object != null) {
LinkedHashMap<UUID, ActivatedAbility> useableAbilities = this.getSpellAbilities(object, game.getState().getZone(object.getId()), game);
// left, right or fused cast
for (String choose : this.testPlayerLink.getChoices()) {
for (ActivatedAbility activatedAbility : useableAbilities.values()) {
if (activatedAbility instanceof SpellAbility) {
if (((SpellAbility) activatedAbility).getCardName().equals(choose)) {
return (SpellAbility) activatedAbility;
}
}
}
}
}
}
}
// default implementation by AI
return super.chooseSpellAbilityForCast(ability, game, noMana);
}
@Override
public boolean choose(Outcome outcome, Target target, UUID sourceId, Game game) {
// copy-paste for TestComputerXXX
// workaround for discard spells
// reason: TestPlayer uses outer computerPlayer to discard but inner code uses choose
return testPlayerLink.choose(outcome, target, sourceId, game);
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,18 +1,17 @@
package org.mage.test.serverside.base;
import java.io.FileNotFoundException;
import mage.constants.MultiplayerAttackOption;
import mage.constants.RangeOfInfluence;
import mage.game.Game;
import mage.game.GameException;
import mage.game.TwoPlayerDuel;
import mage.player.ai.ComputerPlayer7;
import org.mage.test.player.TestComputerPlayer7;
import org.mage.test.player.TestPlayer;
import org.mage.test.serverside.base.impl.CardTestPlayerAPIImpl;
import java.io.FileNotFoundException;
/**
*
* @author LevelX2
*/
public abstract class CardTestPlayerBaseAI extends CardTestPlayerAPIImpl {
@ -31,7 +30,7 @@ public abstract class CardTestPlayerBaseAI extends CardTestPlayerAPIImpl {
@Override
protected TestPlayer createPlayer(String name, RangeOfInfluence rangeOfInfluence) {
if (name.equals("PlayerA")) {
TestPlayer testPlayer = new TestPlayer(new ComputerPlayer7("PlayerA", RangeOfInfluence.ONE, skill));
TestPlayer testPlayer = new TestPlayer(new TestComputerPlayer7("PlayerA", RangeOfInfluence.ONE, skill));
testPlayer.setAIPlayer(true);
return testPlayer;
}

View file

@ -1,16 +1,6 @@
package org.mage.test.serverside.base;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import mage.cards.Card;
import mage.cards.decks.Deck;
import mage.cards.decks.DeckCardLists;
import mage.cards.repository.CardInfo;
import mage.cards.repository.CardRepository;
@ -21,7 +11,6 @@ import mage.game.Game;
import mage.game.match.MatchType;
import mage.game.permanent.PermanentCard;
import mage.game.tournament.TournamentType;
import mage.player.ai.ComputerPlayer;
import mage.players.Player;
import mage.server.game.GameFactory;
import mage.server.util.ConfigSettings;
@ -32,8 +21,15 @@ import mage.util.Copier;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.junit.BeforeClass;
import org.mage.test.player.TestComputerPlayer;
import org.mage.test.player.TestPlayer;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Base class for all tests.
*
@ -334,7 +330,7 @@ public abstract class MageTestPlayerBase {
}
protected TestPlayer createPlayer(String name, RangeOfInfluence rangeOfInfluence) {
return new TestPlayer(new ComputerPlayer(name, rangeOfInfluence));
return new TestPlayer(new TestComputerPlayer(name, rangeOfInfluence));
}
}

View file

@ -24,8 +24,10 @@ import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentCard;
import mage.players.ManaPool;
import mage.players.Player;
import mage.util.CardUtil;
import org.junit.Assert;
import org.junit.Before;
import org.mage.test.player.PlayerAction;
import org.mage.test.player.TestPlayer;
import org.mage.test.serverside.base.CardTestAPI;
import org.mage.test.serverside.base.MageTestPlayerBase;
@ -48,15 +50,30 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
// Defines the constant if for activate ability is not target but a ability on the stack to define
public static final String NO_TARGET = "NO_TARGET";
// TODO: add target player param to commands
public static final String CHECK_COMMAND_PT = "PT";
public static final String CHECK_COMMAND_LIFE = "LIFE";
public static final String CHECK_COMMAND_ABILITY = "ABILITY";
public static final String CHECK_COMMAND_PERMANENT_COUNT = "PERMANENT_COUNT";
public static final String CHECK_COMMAND_EXILE_COUNT = "EXILE_COUNT";
public static final String CHECK_COMMAND_HAND_COUNT = "HAND_COUNT";
public static final String CHECK_COMMAND_HAND_CARD_COUNT = "HAND_CARD_COUNT";
public static final String CHECK_COMMAND_COLOR = "COLOR";
public static final String CHECK_COMMAND_SUBTYPE = "SUBTYPE";
public static final String CHECK_COMMAND_MANA_POOL = "MANA_POOL";
public static final String CHECK_COMMAND_ALIAS_ZONE = "ALIAS_ZONE";
// TODO: add target player param to commands
public static final String SHOW_COMMAND_LIBRARY = "LIBRARY";
public static final String SHOW_COMMAND_HAND = "HAND";
public static final String SHOW_COMMAND_BATTLEFIELD = "BATTLEFIELD";
public static final String SHOW_COMMAND_GRAVEYEARD = "GRAVEYARD";
public static final String SHOW_COMMAND_EXILE = "EXILE";
public static final String SHOW_COMMAND_AVAILABLE_ABILITIES = "AVAILABLE_ABILITIES";
public static final String SHOW_COMMAND_ALIASES = "ALIASES";
// TODO: add target player param to commands
public static final String ALIAS_COMMAND_ADD = "ADD";
protected GameOptions gameOptions;
@ -211,6 +228,8 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
logger.debug("Winner: " + currentGame.getWinner());
logger.info("Test has been executed. Execution time: " + (t2 - t1) / 1000000 + " ms");
// TODO: 01.12.2018, JayDi85 - uncomment and fix MANY broken tests with wrong commands
//assertAllCommandsUsed();
}
protected TestPlayer createNewPlayer(String playerName, RangeOfInfluence rangeOfInfluence) {
@ -238,6 +257,8 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
return player;
}
// check commands
private void check(String checkName, int turnNum, PhaseStep step, TestPlayer player, String command, String... params) {
String res = "check:" + command;
for (String param : params) {
@ -247,6 +268,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
}
public void checkPT(String checkName, int turnNum, PhaseStep step, TestPlayer player, String permanentName, Integer power, Integer toughness) {
//Assert.assertNotEquals("", permanentName);
check(checkName, turnNum, step, player, CHECK_COMMAND_PT, permanentName, power.toString(), toughness.toString());
}
@ -255,14 +277,17 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
}
public void checkAbility(String checkName, int turnNum, PhaseStep step, TestPlayer player, String permanentName, Class<?> abilityClass, Boolean mustHave) {
//Assert.assertNotEquals("", permanentName);
check(checkName, turnNum, step, player, CHECK_COMMAND_ABILITY, permanentName, abilityClass.getName(), mustHave.toString());
}
public void checkPermanentCount(String checkName, int turnNum, PhaseStep step, TestPlayer player, String permanentName, Integer count) {
//Assert.assertNotEquals("", permanentName);
check(checkName, turnNum, step, player, CHECK_COMMAND_PERMANENT_COUNT, permanentName, count.toString());
}
public void checkExileCount(String checkName, int turnNum, PhaseStep step, TestPlayer player, String permanentName, Integer count) {
//Assert.assertNotEquals("", permanentName);
check(checkName, turnNum, step, player, CHECK_COMMAND_EXILE_COUNT, permanentName, count.toString());
}
@ -270,11 +295,18 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
check(checkName, turnNum, step, player, CHECK_COMMAND_HAND_COUNT, count.toString());
}
public void checkHandCardCount(String checkName, int turnNum, PhaseStep step, TestPlayer player, String cardName, Integer count) {
//Assert.assertNotEquals("", cardName);
check(checkName, turnNum, step, player, CHECK_COMMAND_HAND_CARD_COUNT, cardName, count.toString());
}
public void checkColor(String checkName, int turnNum, PhaseStep step, TestPlayer player, String permanentName, String colors, Boolean mustHave) {
//Assert.assertNotEquals("", permanentName);
check(checkName, turnNum, step, player, CHECK_COMMAND_COLOR, permanentName, colors, mustHave.toString());
}
public void checkSubType(String checkName, int turnNum, PhaseStep step, TestPlayer player, String permanentName, SubType subType, Boolean mustHave) {
//Assert.assertNotEquals("", permanentName);
check(checkName, turnNum, step, player, CHECK_COMMAND_SUBTYPE, permanentName, subType.toString(), mustHave.toString());
}
@ -282,6 +314,52 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
check(checkName, turnNum, step, player, CHECK_COMMAND_MANA_POOL, colors, amount.toString());
}
public void checkAliasZone(String checkName, int turnNum, PhaseStep step, TestPlayer player, String alias, Zone zone) {
checkAliasZone(checkName, turnNum, step, player, alias, zone, true);
}
public void checkAliasZone(String checkName, int turnNum, PhaseStep step, TestPlayer player, String alias, Zone zone, Boolean mustHave) {
check(checkName, turnNum, step, player, CHECK_COMMAND_ALIAS_ZONE, alias, zone.toString(), mustHave.toString());
}
// show commands
private void show(String showName, int turnNum, PhaseStep step, TestPlayer player, String command, String... params) {
String res = "show:" + command;
for (String param : params) {
res += "@" + param;
}
player.addAction(showName, turnNum, step, res);
}
public void showLibrary(String showName, int turnNum, PhaseStep step, TestPlayer player) {
show(showName, turnNum, step, player, SHOW_COMMAND_LIBRARY);
}
public void showHand(String showName, int turnNum, PhaseStep step, TestPlayer player) {
show(showName, turnNum, step, player, SHOW_COMMAND_HAND);
}
public void showBattlefield(String showName, int turnNum, PhaseStep step, TestPlayer player) {
show(showName, turnNum, step, player, SHOW_COMMAND_BATTLEFIELD);
}
public void showGraveyard(String showName, int turnNum, PhaseStep step, TestPlayer player) {
show(showName, turnNum, step, player, SHOW_COMMAND_GRAVEYEARD);
}
public void showExile(String showName, int turnNum, PhaseStep step, TestPlayer player) {
show(showName, turnNum, step, player, SHOW_COMMAND_EXILE);
}
public void showAvaileableAbilities(String showName, int turnNum, PhaseStep step, TestPlayer player) {
show(showName, turnNum, step, player, SHOW_COMMAND_AVAILABLE_ABILITIES);
}
public void showAliases(String showName, int turnNum, PhaseStep step, TestPlayer player) {
show(showName, turnNum, step, player, SHOW_COMMAND_ALIASES);
}
/**
* Removes all cards from player's library from the game. Usually this
* should be used once before initialization to form the library in certain
@ -346,6 +424,19 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
@Override
public void addCard(Zone gameZone, TestPlayer player, String cardName, int count, boolean tapped) {
// aliases for mage objects
String aliasName = "";
boolean useAliasMultiNames = (count != 1);
if (cardName.contains("@")) {
aliasName = cardName.substring(cardName.indexOf("@") + 1);
cardName = cardName.substring(0, cardName.indexOf("@"));
}
// one card = one aliase, massive adds can use auto-name
if (!useAliasMultiNames && !aliasName.isEmpty() && player.getAliasByName(aliasName) != null) {
Assert.fail("Can't add card " + cardName + " - alias " + aliasName + " already exists for " + player.getName());
}
if (gameZone == Zone.BATTLEFIELD) {
for (int i = 0; i < count; i++) {
CardInfo cardInfo = CardRepository.instance.findCard(cardName);
@ -356,6 +447,10 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
PermanentCard p = new PermanentCard(card.copy(), player.getId(), currentGame);
p.setTapped(tapped);
getBattlefieldCards(player).add(p);
if (!aliasName.isEmpty()) {
player.addAlias(player.generateAliasName(aliasName, useAliasMultiNames, i + 1), p.getId());
}
}
} else {
if (tapped) {
@ -369,6 +464,10 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
throw new AssertionError("Couldn't find a card: " + cardName);
}
cards.add(card);
if (!aliasName.isEmpty()) {
player.addAlias(player.generateAliasName(aliasName, useAliasMultiNames, i + 1), card.getId());
}
}
}
}
@ -403,7 +502,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
*/
@Override
public void setLife(TestPlayer player, int life) {
getCommands(player).put(Zone.OUTSIDE, "life:" + String.valueOf(life));
getCommands(player).put(Zone.OUTSIDE, "life:" + life);
}
/**
@ -505,6 +604,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
@Override
public void assertPowerToughness(Player player, String cardName, int power, int toughness, Filter.ComparisonScope scope)
throws AssertionError {
//Assert.assertNotEquals("", cardName);
int count = 0;
int fit = 0;
int foundPower = 0;
@ -559,6 +659,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
@Override
public void assertAbilities(Player player, String cardName, List<Ability> abilities)
throws AssertionError {
//Assert.assertNotEquals("", cardName);
int count = 0;
Permanent found = null;
for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents(player.getId())) {
@ -594,6 +695,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @throws AssertionError
*/
public void assertAbility(Player player, String cardName, Ability ability, boolean mustHave, int count) throws AssertionError {
//Assert.assertNotEquals("", cardName);
int foundCount = 0;
Permanent found = null;
for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents(player.getId())) {
@ -644,6 +746,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
*/
@Override
public void assertPermanentCount(Player player, String cardName, int count) throws AssertionError {
//Assert.assertNotEquals("", cardName);
int actualCount = 0;
for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents()) {
if (permanent.getControllerId().equals(player.getId())) {
@ -657,6 +760,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
@Override
public void assertCommandZoneCount(Player player, String commandZoneObjectName, int count) throws AssertionError {
//Assert.assertNotEquals("", commandZoneObjectName);
int actualCount = 0;
for (CommandObject commandObject : currentGame.getState().getCommand()) {
if (commandObject.getControllerId().equals(player.getId()) && commandObject.getName().equals(commandZoneObjectName)) {
@ -696,6 +800,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
}
public void assertCounterCount(Player player, String cardName, CounterType type, int count) throws AssertionError {
//Assert.assertNotEquals("", cardName);
Permanent found = null;
for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents()) {
if (permanent.getName().equals(cardName) && (player == null || permanent.getControllerId().equals(player.getId()))) {
@ -715,11 +820,12 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param count Expected count.
*/
public void assertCounterOnExiledCardCount(String cardName, CounterType type, int count) throws AssertionError {
//Assert.assertNotEquals("", cardName);
Card found = null;
if (found == null) {
for (Card card : currentGame.getExile().getAllCards(currentGame)) {
if (card.getName().equals(cardName)) {
if (CardUtil.haveSameNames(card.getName(), cardName, true)) {
found = card;
break;
}
@ -749,6 +855,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param mustHave true if creature should have type, false if it should not
*/
public void assertType(String cardName, CardType type, boolean mustHave) throws AssertionError {
//Assert.assertNotEquals("", cardName);
Permanent found = null;
for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents()) {
if (permanent.getName().equals(cardName)) {
@ -771,6 +878,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param subType a subtype to test for
*/
public void assertType(String cardName, CardType type, SubType subType) throws AssertionError {
//Assert.assertNotEquals("", cardName);
Permanent found = getPermanent(cardName);
Assert.assertTrue("(Battlefield) card type not found (" + cardName + ':' + type + ')', found.getCardType().contains(type));
if (subType != null) {
@ -785,6 +893,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param type A type to test for
*/
public void assertNotType(String cardName, CardType type) throws AssertionError {
//Assert.assertNotEquals("", cardName);
Permanent found = getPermanent(cardName);
Assert.assertFalse("(Battlefield) card type found (" + cardName + ':' + type + ')', found.getCardType().contains(type));
}
@ -796,6 +905,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param subType a subtype to test for
*/
public void assertNotSubtype(String cardName, SubType subType) throws AssertionError {
//Assert.assertNotEquals("", cardName);
Permanent found = getPermanent(cardName);
if (subType != null) {
Assert.assertFalse("(Battlefield) card sub-type equal (" + cardName + ':' + subType.getDescription() + ')', found.getSubtype(currentGame).contains(subType));
@ -811,6 +921,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param mustHave must or not must have that colors
*/
public void assertColor(Player player, String cardName, ObjectColor searchColors, boolean mustHave) {
//Assert.assertNotEquals("", cardName);
Assert.assertNotEquals("must setup colors to search", 0, searchColors.getColorCount());
Permanent card = getPermanent(cardName, player);
@ -845,6 +956,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param tapped Whether the permanent is tapped or not
*/
public void assertTapped(String cardName, boolean tapped) throws AssertionError {
//Assert.assertNotEquals("", cardName);
Permanent found = null;
for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents()) {
if (permanent.getName().equals(cardName)) {
@ -870,6 +982,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param count The amount of this permanents that should be tapped
*/
public void assertTappedCount(String cardName, boolean tapped, int count) throws AssertionError {
//Assert.assertNotEquals("", cardName);
int tappedAmount = 0;
Permanent found = null;
for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents()) {
@ -891,6 +1004,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param attacking Whether the permanent is attacking or not
*/
public void assertAttacking(String cardName, boolean attacking) throws AssertionError {
//Assert.assertNotEquals("", cardName);
Permanent found = null;
for (Permanent permanent : currentGame.getBattlefield().getAllActivePermanents()) {
if (permanent.getName().equals(cardName)) {
@ -922,17 +1036,18 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param count Expected count.
*/
public void assertHandCount(Player player, String cardName, int count) throws AssertionError {
//Assert.assertNotEquals("", cardName);
int actual;
if (cardName.contains("//")) { // special logic for cheched split cards, because in game logic of card name filtering is different than for test
actual = 0;
for (Card card : currentGame.getPlayer(player.getId()).getHand().getCards(currentGame)) {
if (card.getName().equals(cardName)) {
if (CardUtil.haveSameNames(card.getName(), cardName, true)) {
actual++;
}
}
} else {
FilterCard filter = new FilterCard();
filter.add(new NamePredicate(cardName));
filter.add(new NamePredicate(cardName, true)); // must find any cards even without names
actual = currentGame.getPlayer(player.getId()).getHand().count(filter, player.getId(), currentGame);
}
Assert.assertEquals("(Hand) Card counts for card " + cardName + " for " + player.getName() + " are not equal ", count, actual);
@ -981,10 +1096,11 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param count Expected count.
*/
public void assertExileCount(String cardName, int count) throws AssertionError {
//Assert.assertNotEquals("", cardName);
int actualCount = 0;
for (ExileZone exile : currentGame.getExile().getExileZones()) {
for (Card card : exile.getCards(currentGame)) {
if (card.getName().equals(cardName)) {
if (CardUtil.haveSameNames(card.getName(), cardName, true)) {
actualCount++;
}
}
@ -1020,6 +1136,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param count Expected count.
*/
public void assertExileCount(Player owner, String cardName, int count) throws AssertionError {
//Assert.assertNotEquals("", cardName);
int actualCount = 0;
for (ExileZone exile : currentGame.getExile().getExileZones()) {
for (Card card : exile.getCards(currentGame)) {
@ -1039,9 +1156,10 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param count Expected count.
*/
public void assertGraveyardCount(Player player, String cardName, int count) throws AssertionError {
//Assert.assertNotEquals("", cardName);
int actualCount = 0;
for (Card card : player.getGraveyard().getCards(currentGame)) {
if (card.getName().equals(cardName)) {
if (CardUtil.haveSameNames(card.getName(), cardName, true)) {
actualCount++;
}
}
@ -1056,7 +1174,6 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param count Expected count.
*/
public void assertLibraryCount(Player player, int count) throws AssertionError {
List<Card> libraryList = player.getLibrary().getCards(currentGame);
int actualCount = libraryList != null && !libraryList.isEmpty() ? libraryList.size() : 0;
Assert.assertEquals("(Library " + player.getName() + ") counts are not equal", count, actualCount);
@ -1070,9 +1187,10 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param count Expected count.
*/
public void assertLibraryCount(Player player, String cardName, int count) throws AssertionError {
//Assert.assertNotEquals("", cardName);
int actualCount = 0;
for (Card card : player.getLibrary().getCards(currentGame)) {
if (card.getName().equals(cardName)) {
if (CardUtil.haveSameNames(card.getName(), cardName, true)) {
actualCount++;
}
}
@ -1080,15 +1198,27 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
Assert.assertEquals("(Library " + player.getName() + ") Card counts are not equal (" + cardName + ')', count, actualCount);
}
/**
* Asserts added actions count. Useful to make sure that all actions were
* executed.
*
* @param player
* @param count
*/
public void assertActionCount(TestPlayer player, int count) {
Assert.assertEquals("Actions left are not equal: ", count, player.getActionCount());
public void assertActionsCount(TestPlayer player, int count) throws AssertionError {
Assert.assertEquals("(Actions of " + player.getName() + ") Count are not equel (founded ["
+ player.getActions().stream().map(PlayerAction::getAction).collect(Collectors.joining(", "))
+ "])", count, player.getActions().size());
}
public void assertChoicesCount(TestPlayer player, int count) throws AssertionError {
Assert.assertEquals("(Choices of " + player.getName() + ") Count are not equel (founded " + player.getChoices() + ")", count, player.getChoices().size());
}
public void assertTargetsCount(TestPlayer player, int count) throws AssertionError {
Assert.assertEquals("(Targets of " + player.getName() + ") Count are not equel (founded " + player.getTargets() + ")", count, player.getTargets().size());
}
public void assertAllCommandsUsed() throws AssertionError {
for (Player player : currentGame.getPlayers().values()) {
TestPlayer testPlayer = (TestPlayer) player;
assertActionsCount(testPlayer, 0);
assertChoicesCount(testPlayer, 0);
assertTargetsCount(testPlayer, 0);
}
}
public void assertActivePlayer(TestPlayer player) {
@ -1129,18 +1259,22 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
}
public void playLand(int turnNum, PhaseStep step, TestPlayer player, String cardName) {
//Assert.assertNotEquals("", cardName);
player.addAction(turnNum, step, "activate:Play " + cardName);
}
public void castSpell(int turnNum, PhaseStep step, TestPlayer player, String cardName) {
//Assert.assertNotEquals("", cardName);
player.addAction(turnNum, step, "activate:Cast " + cardName);
}
public void castSpell(int turnNum, PhaseStep step, TestPlayer player, String cardName, Player target) {
//Assert.assertNotEquals("", cardName);
player.addAction(turnNum, step, "activate:Cast " + cardName + "$targetPlayer=" + target.getName());
}
public void castSpell(int turnNum, PhaseStep step, TestPlayer player, String cardName, Player target, int manaInPool) {
//Assert.assertNotEquals("", cardName);
player.addAction(turnNum, step, "activate:Cast " + cardName + "$targetPlayer=" + target.getName() + "$manaInPool=" + manaInPool);
}
@ -1177,11 +1311,11 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* multiple targets can be seperated by ^
*/
public void castSpell(int turnNum, PhaseStep step, TestPlayer player, String cardName, String targetName) {
//Assert.assertNotEquals("", cardName);
player.addAction(turnNum, step, "activate:Cast " + cardName + "$target=" + targetName);
}
public enum StackClause {
WHILE_ON_STACK,
WHILE_COPY_ON_STACK,
WHILE_NOT_ON_STACK
@ -1216,6 +1350,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
* @param clause
*/
public void castSpell(int turnNum, PhaseStep step, TestPlayer player, String cardName, String targetName, String spellOnStack, StackClause clause) {
//Assert.assertNotEquals("", cardName);
if (StackClause.WHILE_ON_STACK == clause) {
player.addAction(turnNum, step, "activate:Cast " + cardName
+ '$' + (targetName != null && targetName.startsWith("target") ? targetName : "target=" + targetName)
@ -1228,6 +1363,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
}
public void castSpell(int turnNum, PhaseStep step, TestPlayer player, String cardName, String targetName, String spellOnStack, String spellOnTopOfStack) {
//Assert.assertNotEquals("", cardName);
String action = "activate:Cast " + cardName + "$target=" + targetName;
if (spellOnStack != null && !spellOnStack.isEmpty()) {
action += "$spellOnStack=" + spellOnStack;
@ -1243,18 +1379,22 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
}
public void activateAbility(int turnNum, PhaseStep step, TestPlayer player, String ability) {
// TODO: it's uses computerPlayer to execute, only ability target will work, but choices and targets commands aren't
player.addAction(turnNum, step, "activate:" + ability);
}
public void activateAbility(int turnNum, PhaseStep step, TestPlayer player, String ability, Player target) {
// TODO: it's uses computerPlayer to execute, only ability target will work, but choices and targets commands aren't
player.addAction(turnNum, step, "activate:" + ability + "$targetPlayer=" + target.getName());
}
public void activateAbility(int turnNum, PhaseStep step, TestPlayer player, String ability, String... targetNames) {
// TODO: it's uses computerPlayer to execute, only ability target will work, but choices and targets commands aren't
player.addAction(turnNum, step, "activate:" + ability + "$target=" + String.join("^", targetNames));
}
public void activateAbility(int turnNum, PhaseStep step, TestPlayer player, String ability, String targetName, String spellOnStack) {
// TODO: it's uses computerPlayer to execute, only ability target will work, but choices and targets commands aren't
this.activateAbility(turnNum, step, player, ability, targetName, spellOnStack, StackClause.WHILE_ON_STACK);
}
@ -1292,22 +1432,28 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
}
public void addCounters(int turnNum, PhaseStep step, TestPlayer player, String cardName, CounterType type, int count) {
//Assert.assertNotEquals("", cardName);
player.addAction(turnNum, step, "addCounters:" + cardName + '$' + type.getName() + '$' + count);
}
public void attack(int turnNum, TestPlayer player, String attacker) {
//Assert.assertNotEquals("", attacker);
player.addAction(turnNum, PhaseStep.DECLARE_ATTACKERS, "attack:" + attacker);
}
public void attack(int turnNum, TestPlayer player, String attacker, TestPlayer defendingPlayer) {
//Assert.assertNotEquals("", attacker);
player.addAction(turnNum, PhaseStep.DECLARE_ATTACKERS, "attack:" + attacker + "$defendingPlayer=" + defendingPlayer.getName());
}
public void attack(int turnNum, TestPlayer player, String attacker, String planeswalker) {
//Assert.assertNotEquals("", attacker);
player.addAction(turnNum, PhaseStep.DECLARE_ATTACKERS, new StringBuilder("attack:").append(attacker).append("$planeswalker=").append(planeswalker).toString());
}
public void block(int turnNum, TestPlayer player, String blocker, String attacker) {
//Assert.assertNotEquals("", blocker);
//Assert.assertNotEquals("", attacker);
player.addAction(turnNum, PhaseStep.DECLARE_BLOCKERS, "block:" + blocker + '$' + attacker);
}
@ -1401,6 +1547,7 @@ public abstract class CardTestPlayerAPIImpl extends MageTestPlayerBase implement
}
public void assertDamageReceived(Player player, String cardName, int expected) {
//Assert.assertNotEquals("", cardName);
Permanent p = getPermanent(cardName, player.getId());
if (p != null) {
Assert.assertEquals("Wrong damage received: ", expected, p.getDamage());

View file

@ -0,0 +1,128 @@
package org.mage.test.testapi;
import mage.constants.EmptyNames;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.util.CardUtil;
import org.junit.Assert;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* @author JayDi85
*/
public class TestAliases extends CardTestPlayerBase {
@Test
public void test_NamesEquals() {
// empty names for face down cards
Assert.assertTrue(CardUtil.haveEmptyName(""));
Assert.assertTrue(CardUtil.haveEmptyName(EmptyNames.FACE_DOWN_CREATURE.toString()));
Assert.assertFalse(CardUtil.haveEmptyName(" "));
Assert.assertFalse(CardUtil.haveEmptyName("123"));
Assert.assertFalse(CardUtil.haveEmptyName("Sample Name"));
// same names (empty names can't be same)
Assert.assertFalse(CardUtil.haveSameNames("", ""));
Assert.assertFalse(CardUtil.haveSameNames(EmptyNames.FACE_DOWN_CREATURE.toString(), ""));
Assert.assertFalse(CardUtil.haveSameNames(EmptyNames.FACE_DOWN_CREATURE.toString(), EmptyNames.FACE_DOWN_CREATURE.toString()));
Assert.assertFalse(CardUtil.haveSameNames(EmptyNames.FACE_DOWN_TOKEN.toString(), ""));
Assert.assertFalse(CardUtil.haveSameNames(EmptyNames.FACE_DOWN_TOKEN.toString(), EmptyNames.FACE_DOWN_CREATURE.toString()));
Assert.assertTrue(CardUtil.haveSameNames("Name", "Name"));
Assert.assertFalse(CardUtil.haveSameNames("Name", ""));
Assert.assertFalse(CardUtil.haveSameNames("Name", " "));
Assert.assertFalse(CardUtil.haveSameNames("Name", "123"));
Assert.assertFalse(CardUtil.haveSameNames("Name", EmptyNames.FACE_DOWN_CREATURE.toString()));
Assert.assertFalse(CardUtil.haveSameNames("Name1", "Name2"));
// ignore mtg rules (empty names must be same)
Assert.assertTrue(CardUtil.haveSameNames("", "", true));
Assert.assertTrue(CardUtil.haveSameNames(EmptyNames.FACE_DOWN_CREATURE.toString(), EmptyNames.FACE_DOWN_CREATURE.toString(), true));
Assert.assertTrue(CardUtil.haveSameNames("Name", "Name", true));
Assert.assertFalse(CardUtil.haveSameNames("Name", "", true));
Assert.assertFalse(CardUtil.haveSameNames("Name", " ", true));
Assert.assertFalse(CardUtil.haveSameNames("Name", "123", true));
Assert.assertFalse(CardUtil.haveSameNames("Name", EmptyNames.FACE_DOWN_CREATURE.toString(), true));
Assert.assertFalse(CardUtil.haveSameNames("Name1", "Name2", true));
}
@Test
public void test_DifferentZones() {
addCard(Zone.LIBRARY, playerA, "Swamp@lib", 1);
addCard(Zone.HAND, playerA, "Swamp@hand", 1);
addCard(Zone.BATTLEFIELD, playerA, "Swamp@battle", 1);
addCard(Zone.GRAVEYARD, playerA, "Swamp@grave", 1);
showAliases("A aliases", 1, PhaseStep.UPKEEP, playerA);
checkAliasZone("lib", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "lib", Zone.LIBRARY);
checkAliasZone("hand", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "hand", Zone.HAND);
checkAliasZone("battle", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "battle", Zone.BATTLEFIELD);
checkAliasZone("grave", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "grave", Zone.GRAVEYARD);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
}
@Test
public void test_MultipleNames() {
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 5);
addCard(Zone.BATTLEFIELD, playerA, "Island@isl", 5);
addCard(Zone.BATTLEFIELD, playerB, "Plains", 5);
addCard(Zone.BATTLEFIELD, playerB, "Mountain@mnt", 5);
checkPermanentCount("Swamp must exists", 1, PhaseStep.UPKEEP, playerA, "Swamp", 5);
checkPermanentCount("Island must exists", 1, PhaseStep.UPKEEP, playerA, "Island", 5);
checkPermanentCount("Plains must exists", 1, PhaseStep.UPKEEP, playerB, "Plains", 5);
checkPermanentCount("Mountain must exists", 1, PhaseStep.UPKEEP, playerB, "Mountain", 5);
//
showAliases("A aliases", 1, PhaseStep.UPKEEP, playerA);
showAliases("B aliases", 1, PhaseStep.UPKEEP, playerB);
// A
checkAliasZone("Swamp must not", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Swamp", Zone.BATTLEFIELD, false);
checkAliasZone("Swamp.1 must not", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Swamp.1", Zone.BATTLEFIELD, false);
checkAliasZone("Island must not", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Island", Zone.BATTLEFIELD, false);
checkAliasZone("isl must not", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "isl", Zone.BATTLEFIELD, false);
checkAliasZone("isl.1 must", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "isl.1", Zone.BATTLEFIELD, true);
checkAliasZone("isl.2 must", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "isl.2", Zone.BATTLEFIELD, true);
checkAliasZone("isl.5 must", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "isl.5", Zone.BATTLEFIELD, true);
// B
checkAliasZone("Plains must not", 1, PhaseStep.PRECOMBAT_MAIN, playerB, "Plains", Zone.BATTLEFIELD, false);
checkAliasZone("Plains.1 must not", 1, PhaseStep.PRECOMBAT_MAIN, playerB, "Plains.1", Zone.BATTLEFIELD, false);
checkAliasZone("Plains must not", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "Plains", Zone.BATTLEFIELD, false);
checkAliasZone("mnt must not", 1, PhaseStep.PRECOMBAT_MAIN, playerB, "mnt", Zone.BATTLEFIELD, false);
checkAliasZone("mnt.1 must", 1, PhaseStep.PRECOMBAT_MAIN, playerB, "mnt.1", Zone.BATTLEFIELD, true);
checkAliasZone("mnt.2 must", 1, PhaseStep.PRECOMBAT_MAIN, playerB, "mnt.2", Zone.BATTLEFIELD, true);
checkAliasZone("mnt.5 must", 1, PhaseStep.PRECOMBAT_MAIN, playerB, "mnt.5", Zone.BATTLEFIELD, true);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
}
@Test
public void test_CastTarget() {
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion@lion", 5);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 5);
addCard(Zone.HAND, playerA, "Lightning Bolt", 3);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "@lion.1");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "@lion.3");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", "@lion.5");
showAliases("A aliases", 1, PhaseStep.POSTCOMBAT_MAIN, playerA);
checkAliasZone("1", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "lion.1", Zone.BATTLEFIELD, false);
checkAliasZone("2", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "lion.2", Zone.BATTLEFIELD, true);
checkAliasZone("3", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "lion.3", Zone.BATTLEFIELD, false);
checkAliasZone("4", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "lion.4", Zone.BATTLEFIELD, true);
checkAliasZone("5", 1, PhaseStep.POSTCOMBAT_MAIN, playerA, "lion.5", Zone.BATTLEFIELD, false);
setStopAt(1, PhaseStep.END_TURN);
execute();
assertAllCommandsUsed();
assertGraveyardCount(playerA, "Lightning Bolt", 3);
assertGraveyardCount(playerA, "Silvercoat Lion", 3);
}
}

View file

@ -1,8 +0,0 @@
package mage.verify;
public class Booster {
public Booster(String mythic){
}
}

View file

@ -3,59 +3,47 @@ package mage.verify;
import java.util.List;
class JsonCard {
// docs: https://mtgjson.com/v4/docs.html
public String uuid;
public String convertedManaCost;
public List<ForeignData> foreignData;
public boolean isReserved;
public String side;
public Legality legalities;
public List<String> printings;
public List<Ruling> rulings;
public String artist;
public String borderColor;
public List<String> colorIdentity;
public List<String> colorIndicator;
public String layout;
public String name;
public List<String> names; // flip cards
public String manaCost;
public List<String> colors;
public float convertedManaCost;
public float faceConvertedManaCost;
public String flavorText;
public List<JsonForeignData> foreignData;
public String frameVersion;
public boolean hasFoil;
public boolean hasNonFoil;
public String multiverseId;
public String frameVersion;
public int cmc;
public List<String> colors;
public List<String> colorIdentity;
public String type;
public List<String> supertypes;
public List<String> types;
public List<String> subtypes;
public String text;
public String power;
public String toughness;
public boolean isOnlineOnly;
public boolean isOversized;
public boolean isReserved;
public boolean isTimeshifted;
public String layout;
public JsonLegalities legalities;
public String loyalty;
public String imageName;
public boolean starter; // only available in boxed sets and not in boosters
public int hand; // vanguard
public int life; // vanguard
public String manaCost;
public int multiverseId;
public String name;
public List<String> names;
public String number;
public String originalText;
public String originalType;
public String flavorText;
public boolean isOnlineOnly;
// only available in AllSets.json
public String artist;
public String flavor;
public String id;
public int multiverseid;
public List<String> printings;
public String power;
public String rarity;
public boolean reserved;
public int[] variations;
public String number;
public String mciNumber;
public String releaseDate; // promos
public String border;
public boolean starter;
public String side;
public List<JsonRuling> rulings;
public List<String> subtypes;
public List<String> supertypes;
public String text;
public String toughness;
public String type;
public List<String> types;
public String uuid;
public List<String> variations;
public String watermark;
public boolean timeshifted;
public String borderColor;
public boolean isOversized;
public String faceConvertedManaCost;
}

View file

@ -1,12 +1,10 @@
package mage.verify;
public class ForeignData {
public String language;
public String name;
public String type;
public String text;
public class JsonForeignData {
public String flavorText;
public String multiverseId;
public String language;
public int multiverseId;
public String name;
public String text;
public String type;
}

View file

@ -2,18 +2,18 @@ package mage.verify;
import com.fasterxml.jackson.annotation.JsonProperty;
public class Legality {
public class JsonLegalities {
@JsonProperty("1v1")
public String oneVersusOne;
public String brawl;
public String commander;
public String duel;
public String frontier;
public String future;
public String legacy;
public String modern;
public String penny;
public String pauper;
public String standard;
public String vintage;
public String frontier;
public String modern;
public String pauper;
public String brawl;
public String future;
public String standard;
}

View file

@ -1,6 +1,6 @@
package mage.verify;
public class Meta {
public class JsonMeta {
public String date;
public String version;
}

View file

@ -1,6 +1,6 @@
package mage.verify;
public class Ruling {
public String text;
public class JsonRuling {
public String date;
public String text;
}

View file

@ -1,36 +1,20 @@
package mage.verify;
import com.fasterxml.jackson.annotation.JsonIgnore;
import java.util.List;
import java.util.Map;
class JsonSet {
public String name;
public String code;
public String oldCode;
public String gathererCode;
public String magicCardsInfoCode;
public String[] magicRaritiesCodes;
public String[] alternativeNames;
public String releaseDate;
public String border;
public String type;
public List<Object> booster; // [String|[String]]
public List<JsonCard> cards;
public String block;
public boolean onlineOnly;
public String mkm_id;
public String mkm_name;
public Map<String, String> translations;
public int baseSetSize;
@JsonIgnore
public List<Booster> boosterV3;
public String borderColor;
public Meta meta;
public String mtgoCode;
public List<Token> tokens;
public int totalSetSize;
public boolean isOnlineOnly;
public String block;
public List<Object> boosterV3; // [["rare", "mythic rare"], "uncommon", "uncommon", "uncommon", "common"]
public List<JsonCard> cards;
public String code;
public boolean isFoilOnly;
public boolean isOnlineOnly;
public JsonMeta meta;
public String mtgoCode;
public String name;
public String releaseDate;
public List<JsonToken> tokens;
public int totalSetSize;
public String type;
}

View file

@ -2,17 +2,20 @@ package mage.verify;
import java.util.List;
public class Token {
public class JsonToken {
public String artist;
public String borderColor;
public List<String> colorIdentity;
public List<String> colorIndicator;
public List<String> colors;
public String loyalty;
public String name;
public String number;
public String power;
public String toughness;
public List<String> reverseRelated;
public String side;
public String text;
public String toughness;
public String type;
public String uuid;
public String watermark;

Some files were not shown because too many files have changed in this diff Show more