This commit is contained in:
ingmargoudt 2017-03-09 21:05:37 +01:00
commit d0a9006f37
60 changed files with 567 additions and 212 deletions

View file

@ -148,7 +148,6 @@ public final class UI {
}
public static String getDisplayManaCost (String manaCost) {
manaCost = manaCost.replace("/", "");
// A pipe in the cost means "process left of the pipe as the card color, but display right of the pipe as the cost".
int pipePosition = manaCost.indexOf("{|}");
if (pipePosition != -1) {

View file

@ -1543,7 +1543,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
}
//TODO: improve this
if (min < max && min == 0) {
return RandomUtil.nextInt(max + 1);
return RandomUtil.nextInt(max);
}
return min;
}

View file

@ -823,9 +823,6 @@ public class HumanPlayer extends PlayerImpl {
protected boolean playManaHandling(Ability abilityToCast, ManaCost unpaid, String promptText, Game game) {
updateGameStatePriority("playMana", game);
Map<String, Serializable> options = new HashMap<>();
if (unpaid.getText().contains("P}")) {
options.put(Constants.Option.SPECIAL_BUTTON, (Serializable) "Pay 2 life");
}
game.firePlayManaEvent(playerId, "Pay " + promptText, options);
waitForResponse(game);
if (!this.canRespond()) {
@ -838,18 +835,6 @@ public class HumanPlayer extends PlayerImpl {
} else if (response.getString() != null && response.getString().equals("special")) {
if (unpaid instanceof ManaCostsImpl) {
specialManaAction(unpaid, game);
// TODO: delve or convoke cards with PhyrexianManaCost won't work together (this combinaton does not exist yet)
@SuppressWarnings("unchecked")
ManaCostsImpl<ManaCost> costs = (ManaCostsImpl<ManaCost>) unpaid;
for (ManaCost cost : costs.getUnpaid()) {
if (cost instanceof PhyrexianManaCost) {
PhyrexianManaCost ph = (PhyrexianManaCost) cost;
if (ph.canPay(null, null, playerId, game)) {
((PhyrexianManaCost) cost).pay(null, game, null, playerId, false, null);
}
break;
}
}
}
} else if (response.getManaType() != null) {
// this mana type can be paid once from pool
@ -907,7 +892,7 @@ public class HumanPlayer extends PlayerImpl {
}
Spell spell = game.getStack().getSpell(abilityToCast.getSourceId());
if (spell != null && spell.isDoneActivatingManaAbilities()) {
game.informPlayer(this, "You can't no longer use activated mana abilities to pay for the current spell. Cancel and recast the spell and activate mana abilities first.");
game.informPlayer(this, "You can no longer use activated mana abilities to pay for the current spell. Cancel and recast the spell and activate mana abilities first.");
return;
}
Zone zone = game.getState().getZone(object.getId());

View file

@ -34,7 +34,6 @@ import mage.game.draft.DraftCube;
* @author fireshoes
*/
public class ModernCube2017 extends DraftCube {
public ModernCube2017() {
super("Modern Cube 2017"); // http://magic.wizards.com/en/articles/archive/magic-online/modern-cube-cardlist-2017-03-02
@ -60,6 +59,7 @@ public class ModernCube2017 extends DraftCube {
cubeCards.add(new CardIdentity("Arbor Elf", ""));
cubeCards.add(new CardIdentity("Arc Trail", ""));
cubeCards.add(new CardIdentity("Archangel Avacyn", ""));
cubeCards.add(new CardIdentity("Archangel of Thune", ""));
cubeCards.add(new CardIdentity("Arid Mesa", ""));
cubeCards.add(new CardIdentity("Arlinn Kord", ""));
cubeCards.add(new CardIdentity("Ashiok, Nightmare Weaver", ""));
@ -70,6 +70,7 @@ public class ModernCube2017 extends DraftCube {
cubeCards.add(new CardIdentity("Azure Mage", ""));
cubeCards.add(new CardIdentity("Banefire", ""));
cubeCards.add(new CardIdentity("Baneslayer Angel", ""));
cubeCards.add(new CardIdentity("Banishing Light", ""));
cubeCards.add(new CardIdentity("Bant Charm", ""));
cubeCards.add(new CardIdentity("Baral, Chief of Compliance", ""));
cubeCards.add(new CardIdentity("Batterskull", ""));
@ -124,6 +125,7 @@ public class ModernCube2017 extends DraftCube {
cubeCards.add(new CardIdentity("Coalition Relic", ""));
cubeCards.add(new CardIdentity("Coldsteel Heart", ""));
cubeCards.add(new CardIdentity("Collective Defiance", ""));
cubeCards.add(new CardIdentity("Collective Effort", ""));
cubeCards.add(new CardIdentity("Compulsive Research", ""));
cubeCards.add(new CardIdentity("Condemn", ""));
cubeCards.add(new CardIdentity("Condescend", ""));
@ -249,13 +251,14 @@ public class ModernCube2017 extends DraftCube {
cubeCards.add(new CardIdentity("Hellrider", ""));
cubeCards.add(new CardIdentity("Herald of Torment", ""));
cubeCards.add(new CardIdentity("Hero of Bladehold", ""));
cubeCards.add(new CardIdentity("Hero of Oxid Ridge", ""));
cubeCards.add(new CardIdentity("Hero's Downfall", ""));
cubeCards.add(new CardIdentity("Hinterland Harbor", ""));
cubeCards.add(new CardIdentity("Honor of the Pure", ""));
cubeCards.add(new CardIdentity("Hornet Nest", ""));
cubeCards.add(new CardIdentity("Hornet Queen", ""));
cubeCards.add(new CardIdentity("Huntmaster of the Fells", ""));
cubeCards.add(new CardIdentity("Hypotic Specter", ""));
cubeCards.add(new CardIdentity("Hypnotic Specter", ""));
cubeCards.add(new CardIdentity("Icy Manipulator", ""));
cubeCards.add(new CardIdentity("Imposing Sovereign", ""));
cubeCards.add(new CardIdentity("Imprisoned in the Moon", ""));
@ -268,7 +271,7 @@ public class ModernCube2017 extends DraftCube {
cubeCards.add(new CardIdentity("Isolated Chapel", ""));
cubeCards.add(new CardIdentity("Izzet Charm", ""));
cubeCards.add(new CardIdentity("Jace Beleren", ""));
cubeCards.add(new CardIdentity("Jace, Architect of Though", ""));
cubeCards.add(new CardIdentity("Jace, Architect of Thought", ""));
cubeCards.add(new CardIdentity("Jace, Unraveler of Secrets", ""));
cubeCards.add(new CardIdentity("Jace, Vryn's Prodigy", ""));
cubeCards.add(new CardIdentity("Jinxed Choker", ""));
@ -280,7 +283,7 @@ public class ModernCube2017 extends DraftCube {
cubeCards.add(new CardIdentity("Karplusan Forest", ""));
cubeCards.add(new CardIdentity("Kessig Prowler", ""));
cubeCards.add(new CardIdentity("Kessig Wolf Run", ""));
cubeCards.add(new CardIdentity("Kik-Jiki, Mirror Breaker", ""));
cubeCards.add(new CardIdentity("Kiki-Jiki, Mirror Breaker", ""));
cubeCards.add(new CardIdentity("Kiora, Master of the Depths", ""));
cubeCards.add(new CardIdentity("Kira, Great Glass-Spinner", ""));
cubeCards.add(new CardIdentity("Kitchen Finks", ""));
@ -297,8 +300,8 @@ public class ModernCube2017 extends DraftCube {
cubeCards.add(new CardIdentity("Lightning Helix", ""));
cubeCards.add(new CardIdentity("Lightning Mauler", ""));
cubeCards.add(new CardIdentity("Lightning Strike", ""));
cubeCards.add(new CardIdentity("Liliana of the Veil", ""));
cubeCards.add(new CardIdentity("Liliana Vess", ""));
cubeCards.add(new CardIdentity("Liliana of the Veil", ""));
cubeCards.add(new CardIdentity("Liliana's Specter", ""));
cubeCards.add(new CardIdentity("Liliana, Heretical Healer", ""));
cubeCards.add(new CardIdentity("Liliana, the Last Hope", ""));
@ -360,7 +363,7 @@ public class ModernCube2017 extends DraftCube {
cubeCards.add(new CardIdentity("Overwhelming Stampede", ""));
cubeCards.add(new CardIdentity("Pack Rat", ""));
cubeCards.add(new CardIdentity("Pact of Negation", ""));
cubeCards.add(new CardIdentity("Palldium Myr", ""));
cubeCards.add(new CardIdentity("Palladium Myr", ""));
cubeCards.add(new CardIdentity("Path to Exile", ""));
cubeCards.add(new CardIdentity("Perilous Myr", ""));
cubeCards.add(new CardIdentity("Pestermite", ""));
@ -415,7 +418,7 @@ public class ModernCube2017 extends DraftCube {
cubeCards.add(new CardIdentity("Rune Snag", ""));
cubeCards.add(new CardIdentity("Rune-Scarred Demon", ""));
cubeCards.add(new CardIdentity("Ruthless Ripper", ""));
cubeCards.add(new CardIdentity("Scader Foundry", ""));
cubeCards.add(new CardIdentity("Sacred Foundry", ""));
cubeCards.add(new CardIdentity("Saheeli Rai", ""));
cubeCards.add(new CardIdentity("Sakura-Tribe Elder", ""));
cubeCards.add(new CardIdentity("Sarkhan, the Dragonspeaker", ""));
@ -425,6 +428,7 @@ public class ModernCube2017 extends DraftCube {
cubeCards.add(new CardIdentity("Seachrome Coast", ""));
cubeCards.add(new CardIdentity("Search for Tomorrow", ""));
cubeCards.add(new CardIdentity("Searing Blaze", ""));
cubeCards.add(new CardIdentity("Searing Blood", ""));
cubeCards.add(new CardIdentity("Seeker of the Way", ""));
cubeCards.add(new CardIdentity("Selesnya Charm", ""));
cubeCards.add(new CardIdentity("Selfless Spirit", ""));
@ -459,7 +463,7 @@ public class ModernCube2017 extends DraftCube {
cubeCards.add(new CardIdentity("Sower of Temptation", ""));
cubeCards.add(new CardIdentity("Spear of Heliod", ""));
cubeCards.add(new CardIdentity("Spectral Procession", ""));
cubeCards.add(new CardIdentity("Spell Piece", ""));
cubeCards.add(new CardIdentity("Spell Pierce", ""));
cubeCards.add(new CardIdentity("Spell Queller", ""));
cubeCards.add(new CardIdentity("Spellskite", ""));
cubeCards.add(new CardIdentity("Sphere of the Suns", ""));
@ -488,15 +492,17 @@ public class ModernCube2017 extends DraftCube {
cubeCards.add(new CardIdentity("Sword of Light and Shadow", ""));
cubeCards.add(new CardIdentity("Sword of War and Peace", ""));
cubeCards.add(new CardIdentity("Sylvan Advocate", ""));
cubeCards.add(new CardIdentity("Sylvan Caryatid", ""));
cubeCards.add(new CardIdentity("Tamiyo, the Moon Sage", ""));
cubeCards.add(new CardIdentity("Tasigur, the Golder Fang", ""));
cubeCards.add(new CardIdentity("Tasigur, the Golden Fang", ""));
cubeCards.add(new CardIdentity("Teferi, Mage of Zhalfir", ""));
cubeCards.add(new CardIdentity("Temple Garden", ""));
cubeCards.add(new CardIdentity("Temple of Epiphany", ""));
cubeCards.add(new CardIdentity("Temple of Maladay", ""));
cubeCards.add(new CardIdentity("Temple of Malady", ""));
cubeCards.add(new CardIdentity("Temple of Mystery", ""));
cubeCards.add(new CardIdentity("Temple of Silence", ""));
cubeCards.add(new CardIdentity("Temple of Triumph", ""));
cubeCards.add(new CardIdentity("Temporal Isolation", ""));
cubeCards.add(new CardIdentity("Temporal Mastery", ""));
cubeCards.add(new CardIdentity("Terastodon", ""));
cubeCards.add(new CardIdentity("Terramorphic Expanse", ""));
@ -507,7 +513,7 @@ public class ModernCube2017 extends DraftCube {
cubeCards.add(new CardIdentity("Thragtusk", ""));
cubeCards.add(new CardIdentity("Threads of Disloyalty", ""));
cubeCards.add(new CardIdentity("Thriving Grubs", ""));
cubeCards.add(new CardIdentity("Thurn, the Last Troll", ""));
cubeCards.add(new CardIdentity("Thrun, the Last Troll", ""));
cubeCards.add(new CardIdentity("Thunderbreak Regent", ""));
cubeCards.add(new CardIdentity("Thundermaw Hellkite", ""));
cubeCards.add(new CardIdentity("Tidings", ""));

View file

@ -54,7 +54,7 @@ public class ActOfAggression extends CardImpl {
}
public ActOfAggression(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{3}{RP}{RP}");
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{3}{R/P}{R/P}");
this.getSpellAbility().addTarget(new TargetCreaturePermanent(filter));
this.getSpellAbility().addEffect(new GainControlTargetEffect(Duration.EndOfTurn));

View file

@ -63,9 +63,9 @@ public class ApostlesBlessing extends CardImpl {
}
public ApostlesBlessing(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{WP}");
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{W/P}");
// ({WP} can be paid with either {W} or 2 life.)
// ({W/P} can be paid with either {W} or 2 life.)
// Target artifact or creature you control gains protection from artifacts or from the color of your choice until end of turn.
this.getSpellAbility().addEffect(new ApostlesBlessingEffect());
this.getSpellAbility().addTarget(new TargetControlledPermanent(filter));

View file

@ -57,11 +57,11 @@ import mage.target.common.TargetControlledCreaturePermanent;
public class BirthingPod extends CardImpl {
public BirthingPod(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}{GP}");
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}{G/P}");
// {1}{GP}, {tap}, Sacrifice a creature: Search your library for a creature card with converted mana cost equal to 1 plus the sacrificed creature's converted mana cost,
// {1}{G/P}, {tap}, Sacrifice a creature: Search your library for a creature card with converted mana cost equal to 1 plus the sacrificed creature's converted mana cost,
// put that card onto the battlefield, then shuffle your library. Activate this ability only any time you could cast a sorcery.
Ability ability = new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new BirthingPodEffect(), new ManaCostsImpl("{1}{GP}"));
Ability ability = new ActivateAsSorceryActivatedAbility(Zone.BATTLEFIELD, new BirthingPodEffect(), new ManaCostsImpl("{1}{G/P}"));
ability.addCost(new TapSourceCost());
ability.addCost(new SacrificeTargetCost(new TargetControlledCreaturePermanent()));
this.addAbility(ability);

View file

@ -53,7 +53,7 @@ public class BlindingSouleater extends CardImpl {
this.power = new MageInt(1);
this.toughness = new MageInt(3);
// {WP},{T}: Tap target creature. ( can be paid with either or 2 life.)
// {W/P},{T}: Tap target creature. ( can be paid with either or 2 life.)
SimpleActivatedAbility ability = new SimpleActivatedAbility(Zone.BATTLEFIELD,
new TapTargetEffect(),
new PhyrexianManaCost(ColoredManaSymbol.W));

View file

@ -51,13 +51,13 @@ import java.util.UUID;
public class CathedralMembrane extends CardImpl {
public CathedralMembrane(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{1}{WP}");
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{1}{W/P}");
this.subtype.add("Wall");
this.power = new MageInt(0);
this.toughness = new MageInt(3);
// <i>({WP} can be paid with either {W} or 2 life.)</i>
// <i>({W/P} can be paid with either {W} or 2 life.)</i>
this.addAbility(DefenderAbility.getInstance());
// When Cathedral Membrane dies during combat, it deals 6 damage to each creature it blocked this combat.

View file

@ -0,0 +1,84 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.cards.c;
import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.condition.common.EnchantedCreatureSubtypeCondition;
import mage.abilities.decorator.ConditionalContinuousEffect;
import mage.abilities.effects.common.AttachEffect;
import mage.abilities.effects.common.continuous.BoostEnchantedEffect;
import mage.abilities.keyword.EnchantAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Outcome;
import mage.constants.Zone;
import mage.target.TargetPermanent;
import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/**
*
* @author JRHerlehy
*/
public class ClutchOfUndeath extends CardImpl {
public ClutchOfUndeath(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{B}{B}");
this.subtype.add("Aura");
// Enchant creature
TargetPermanent auraTarget = new TargetCreaturePermanent();
this.getSpellAbility().addTarget(auraTarget);
this.getSpellAbility().addEffect(new AttachEffect(Outcome.BoostCreature));
Ability ability = new EnchantAbility(auraTarget.getTargetName());
this.addAbility(ability);
// Enchanted creature gets +3/+3 as long as it's a Zombie. Otherwise, it gets -3/-3.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
new ConditionalContinuousEffect(
new BoostEnchantedEffect(3, 3),
new BoostEnchantedEffect(-3, -3),
new EnchantedCreatureSubtypeCondition("Zombie"),
"Enchanted creature gets +3/+3 as long as it's a Zombie. Otherwise, it gets -3/-3.")
)
);
}
public ClutchOfUndeath(final ClutchOfUndeath card) {
super(card);
}
@Override
public ClutchOfUndeath copy() {
return new ClutchOfUndeath(this);
}
}

View file

@ -50,7 +50,7 @@ public class CorrosiveGale extends CardImpl {
}
public CorrosiveGale(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{GP}");
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{G/P}");
this.getSpellAbility().addEffect(new DamageAllEffect(new ManacostVariableValue(), filter));

View file

@ -27,9 +27,6 @@
*/
package mage.cards.d;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.LoyaltyAbility;
import mage.abilities.SpellAbility;
@ -59,6 +56,11 @@ import mage.players.Player;
import mage.target.Target;
import mage.target.TargetPlayer;
import mage.target.common.TargetArtifactPermanent;
import mage.target.targetpointer.FixedTargets;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/**
*
@ -135,7 +137,7 @@ class DackFaydenEmblemTriggeredAbility extends TriggeredAbilityImpl {
@Override
public boolean checkTrigger(GameEvent event, Game game) {
boolean returnValue = false;
List<UUID> targettedPermanents = new ArrayList<>(0);
List<UUID> targetedPermanentIds = new ArrayList<>(0);
Player player = game.getPlayer(this.getControllerId());
if (player != null) {
if (event.getPlayerId().equals(this.getControllerId())) {
@ -147,7 +149,7 @@ class DackFaydenEmblemTriggeredAbility extends TriggeredAbilityImpl {
for (UUID targetId : target.getTargets()) {
if (game.getBattlefield().containsPermanent(targetId)) {
returnValue = true;
targettedPermanents.add(targetId);
targetedPermanentIds.add(targetId);
}
}
}
@ -156,7 +158,7 @@ class DackFaydenEmblemTriggeredAbility extends TriggeredAbilityImpl {
for (UUID targetId : effect.getTargetPointer().getTargets(game, spellAbility)) {
if (game.getBattlefield().containsPermanent(targetId)) {
returnValue = true;
targettedPermanents.add(targetId);
targetedPermanentIds.add(targetId);
}
}
}
@ -166,7 +168,15 @@ class DackFaydenEmblemTriggeredAbility extends TriggeredAbilityImpl {
for (Effect effect : this.getEffects()) {
if (effect instanceof DackFaydenEmblemEffect) {
DackFaydenEmblemEffect dackEffect = (DackFaydenEmblemEffect) effect;
dackEffect.setPermanents(targettedPermanents);
List<Permanent> permanents = new ArrayList<>();
for(UUID permanentId : targetedPermanentIds) {
Permanent permanent = game.getPermanent(permanentId);
if(permanent != null) {
permanents.add(permanent);
}
}
dackEffect.setTargets(permanents, game);
}
}
return returnValue;
@ -180,7 +190,7 @@ class DackFaydenEmblemTriggeredAbility extends TriggeredAbilityImpl {
class DackFaydenEmblemEffect extends ContinuousEffectImpl {
protected List<UUID> permanents;
protected FixedTargets fixedTargets;
DackFaydenEmblemEffect() {
super(Duration.EndOfGame, Layer.ControlChangingEffects_2, SubLayer.NA, Outcome.GainControl);
@ -189,7 +199,7 @@ class DackFaydenEmblemEffect extends ContinuousEffectImpl {
DackFaydenEmblemEffect(final DackFaydenEmblemEffect effect) {
super(effect);
this.permanents = effect.permanents;
this.fixedTargets = effect.fixedTargets;
}
@Override
@ -199,7 +209,7 @@ class DackFaydenEmblemEffect extends ContinuousEffectImpl {
@Override
public boolean apply(Game game, Ability source) {
for (UUID permanentId : this.permanents) {
for (UUID permanentId : fixedTargets.getTargets(game, source)) {
Permanent permanent = game.getPermanent(permanentId);
if (permanent != null) {
permanent.changeControllerId(source.getControllerId(), game);
@ -208,7 +218,7 @@ class DackFaydenEmblemEffect extends ContinuousEffectImpl {
return true;
}
public void setPermanents(List<UUID> targettedPermanents) {
this.permanents = new ArrayList<>(targettedPermanents);
public void setTargets(List<Permanent> targetedPermanents, Game game) {
this.fixedTargets = new FixedTargets(targetedPermanents, game);
}
}

View file

@ -44,7 +44,7 @@ import mage.target.common.TargetCreaturePermanent;
public class Dismember extends CardImpl {
public Dismember (UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{BP}{BP}");
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{B/P}{B/P}");
// Target creature gets -5/-5 until end of turn.

View file

@ -42,7 +42,7 @@ import mage.target.TargetPlayer;
public class GitaxianProbe extends CardImpl {
public GitaxianProbe(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{UP}");
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{U/P}");
// Look at target player's hand.
this.getSpellAbility().addEffect(new LookAtTargetPlayerHandEffect());

View file

@ -41,7 +41,7 @@ import mage.target.common.TargetCreatureOrPlayer;
public class GutShot extends CardImpl {
public GutShot(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{RP}");
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{R/P}");
this.getSpellAbility().addEffect(new DamageTargetEffect(1));
this.getSpellAbility().addTarget(new TargetCreatureOrPlayer());

View file

@ -46,7 +46,7 @@ public class Hex extends CardImpl {
// Destroy six target creatures.
this.getSpellAbility().addEffect(new DestroyTargetEffect());
this.getSpellAbility().addTarget(new TargetCreaturePermanent(6, 6));
this.getSpellAbility().addTarget(new TargetCreaturePermanent(6));
}
public Hex(final Hex card) {

View file

@ -58,8 +58,8 @@ public class HexParasite extends CardImpl {
this.power = new MageInt(1);
this.toughness = new MageInt(1);
// {X}{BP}: Remove up to X counters from target permanent. For each counter removed this way, Hex Parasite gets +1/+0 until end of turn.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new HexParasiteEffect(), new ManaCostsImpl("{X}{BP}"));
// {X}{B/P}: Remove up to X counters from target permanent. For each counter removed this way, Hex Parasite gets +1/+0 until end of turn.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new HexParasiteEffect(), new ManaCostsImpl("{X}{B/P}"));
ability.addTarget(new TargetPermanent());
this.addAbility(ability);
}

View file

@ -64,7 +64,7 @@ public class Lashwrithe extends CardImpl {
this.addAbility(new LivingWeaponAbility());
PermanentsOnBattlefieldCount value = new PermanentsOnBattlefieldCount(filter);
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new BoostEquippedEffect(value, value)));
this.addAbility(new EquipAbility(Outcome.BoostCreature, new ManaCostsImpl("{BP}{BP}")));
this.addAbility(new EquipAbility(Outcome.BoostCreature, new ManaCostsImpl("{B/P}{B/P}")));
}
public Lashwrithe(final Lashwrithe card) {

View file

@ -41,7 +41,7 @@ import mage.filter.common.FilterAttackingCreature;
public class MarrowShards extends CardImpl {
public MarrowShards(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{WP}");
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{W/P}");
this.getSpellAbility().addEffect(new DamageAllEffect(1, new FilterAttackingCreature()));

View file

@ -50,7 +50,7 @@ public class MentalMisstep extends CardImpl {
}
public MentalMisstep(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{UP}");
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{U/P}");
// Counter target spell with converted mana cost 1.
this.getSpellAbility().addEffect(new CounterTargetEffect());

View file

@ -47,7 +47,7 @@ import mage.constants.Zone;
public class MoltensteelDragon extends CardImpl {
public MoltensteelDragon(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{4}{RP}{RP}");
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{4}{R/P}{R/P}");
this.subtype.add("Dragon");
this.power = new MageInt(4);

View file

@ -43,7 +43,7 @@ import mage.target.common.TargetCreaturePermanent;
public class MutagenicGrowth extends CardImpl {
public MutagenicGrowth (UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{GP}");
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{G/P}");
this.getSpellAbility().addTarget(new TargetCreaturePermanent());
this.getSpellAbility().addEffect(new BoostTargetEffect(2, 2, Duration.EndOfTurn));

View file

@ -42,11 +42,11 @@ import mage.constants.Zone;
public class NornsAnnex extends CardImpl {
public NornsAnnex(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}{WP}{WP}");
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{3}{W/P}{W/P}");
// {WP} ({WP} can be paid with either or 2 life.)
// Creatures can't attack you or a planeswalker you control unless their controller pays {WP} for each of those creatures.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantAttackYouUnlessPayManaAllEffect(new ManaCostsImpl<>("{WP}"), true)));
// {W/P} ({W/P} can be paid with either or 2 life.)
// Creatures can't attack you or a planeswalker you control unless their controller pays {W/P} for each of those creatures.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new CantAttackYouUnlessPayManaAllEffect(new ManaCostsImpl<>("{W/P}"), true)));
}
public NornsAnnex(final NornsAnnex card) {

View file

@ -42,7 +42,7 @@ import mage.target.common.TargetCardInGraveyard;
public class NoxiousRevival extends CardImpl {
public NoxiousRevival (UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{GP}");
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{G/P}");
this.getSpellAbility().addEffect(new PutOnLibraryTargetEffect(true));
this.getSpellAbility().addTarget(new TargetCardInGraveyard());

View file

@ -61,7 +61,7 @@ public class PhyrexianMetamorph extends CardImpl {
}
public PhyrexianMetamorph(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}{UP}");
super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{3}{U/P}");
this.subtype.add("Shapeshifter");
this.power = new MageInt(0);
@ -83,7 +83,7 @@ public class PhyrexianMetamorph extends CardImpl {
};
// {UP} ( can be paid with either {U} or 2 life.)
// {U/P} ( can be paid with either {U} or 2 life.)
// You may have Phyrexian Metamorph enter the battlefield as a copy of any artifact or creature on the battlefield, except it's an artifact in addition to its other types.
Effect effect = new CopyPermanentEffect(filter, phyrexianMetamorphApplier);
effect.setText("You may have {this} enter the battlefield as a copy of any artifact or creature on the battlefield, except it's an artifact in addition to its other types");

View file

@ -44,7 +44,7 @@ import mage.target.common.TargetCreaturePermanent;
public class PithDriller extends CardImpl {
public PithDriller(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{4}{BP}");
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{4}{B/P}");
this.subtype.add("Horror");
this.power = new MageInt(2);

View file

@ -41,7 +41,7 @@ import mage.cards.CardSetInfo;
public class PorcelainLegionnaire extends CardImpl {
public PorcelainLegionnaire(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{2}{WP}");
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{2}{W/P}");
this.subtype.add("Soldier");
this.power = new MageInt(3);

View file

@ -28,8 +28,6 @@
package mage.cards.p;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Ability;
@ -131,11 +129,18 @@ class PossibilityStormEffect extends OneShotEffect {
@Override
public boolean apply(Game game, Ability source) {
Spell spell = game.getStack().getSpell(targetPointer.getFirst(game, source));
boolean noLongerOnStack = false; // spell was exiled already by another effect, for example NivMagus Elemental
if (spell == null) {
spell = ((Spell) game.getLastKnownInformation(targetPointer.getFirst(game, source), Zone.STACK));
noLongerOnStack = true;
}
MageObject sourceObject = source.getSourceObject(game);
if (sourceObject != null && spell != null) {
Player spellController = game.getPlayer(spell.getControllerId());
if (spellController != null
&& spellController.moveCardsToExile(spell, source, game, true, source.getSourceId(), sourceObject.getIdName())) {
if (spellController != null) {
if (!noLongerOnStack) {
spellController.moveCardsToExile(spell, source, game, true, source.getSourceId(), sourceObject.getIdName());
}
if (spellController.getLibrary().hasCards()) {
Library library = spellController.getLibrary();
Card card;

View file

@ -60,7 +60,7 @@ import mage.target.targetpointer.FixedTarget;
public class PostmortemLunge extends CardImpl {
public PostmortemLunge(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{BP}");
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{X}{B/P}");
// Return target creature card with converted mana cost X from your graveyard to the battlefield. It gains haste. Exile it at the beginning of the next end step.
this.getSpellAbility().addEffect(new PostmortemLungeEffect());

View file

@ -49,7 +49,7 @@ import mage.target.common.TargetCreatureOrPlayer;
public class RageExtractor extends CardImpl {
public RageExtractor(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{4}{RP}");
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT},"{4}{R/P}");
this.addAbility(new RageExtractorTriggeredAbility());

View file

@ -46,7 +46,7 @@ import mage.game.permanent.Permanent;
public class RuthlessInvasion extends CardImpl {
public RuthlessInvasion (UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{RP}");
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{R/P}");
this.getSpellAbility().addEffect(new RuthlessInvasionEffect());
}

View file

@ -29,22 +29,23 @@ package mage.cards.s;
import java.util.UUID;
import mage.MageInt;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAllTriggeredAbility;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.GreatestPowerAmongControlledCreaturesValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.mana.DynamicManaAbility;
import mage.abilities.effects.common.AddManaInAnyCombinationEffect;
import mage.abilities.effects.common.ManaEffect;
import mage.abilities.mana.SimpleManaAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.*;
import mage.filter.common.FilterControlledCreaturePermanent;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.predicate.ObjectSourcePlayer;
import mage.filter.predicate.ObjectSourcePlayerPredicate;
import mage.filter.predicate.Predicate;
import mage.filter.predicate.permanent.AnotherPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
@ -60,13 +61,13 @@ public class SelvalaHeartOfTheWilds extends CardImpl {
static {
filter.add(new AnotherPredicate());
filter.add(new GreatestPowerPredicate());
}
private static final String rule = "Whenever another creature enters the battlefield, its controller may draw a card if its power is greater than each other creature's power.";
private static final String rule2 = "Add X mana in any combination of colors to your mana pool, where X is the greatest power among creatures you control.";
public SelvalaHeartOfTheWilds(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{G}{G}");
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}{G}");
this.supertype.add("Legendary");
this.subtype.add("Elf");
this.subtype.add("Scout");
@ -77,8 +78,8 @@ public class SelvalaHeartOfTheWilds extends CardImpl {
this.addAbility(new EntersBattlefieldAllTriggeredAbility(Zone.BATTLEFIELD, new SelvalaHeartOfTheWildsEffect(), filter, false, SetTargetPointer.PERMANENT, rule));
// {G}, {T}: Add X mana in any combination of colors to your mana pool, where X is the greatest power among creatures you control.
Ability ability = new DynamicManaAbility(new Mana(0, 0, 0, 0, 0, 0, 1, 0), new GreatestPowerYouControlValue(), new ManaCostsImpl<>("{G}"),
"Add X mana in any combination of colors to your mana pool, where X is the greatest power among creatures you control.");
ManaEffect manaEffect = new AddManaInAnyCombinationEffect(new GreatestPowerAmongControlledCreaturesValue(), rule2, ColoredManaSymbol.B, ColoredManaSymbol.U, ColoredManaSymbol.R, ColoredManaSymbol.W, ColoredManaSymbol.G);
Ability ability = new SimpleManaAbility(Zone.BATTLEFIELD, manaEffect, new ManaCostsImpl("{G}"));
ability.addCost(new TapSourceCost());
this.addAbility(ability);
@ -96,6 +97,12 @@ public class SelvalaHeartOfTheWilds extends CardImpl {
class SelvalaHeartOfTheWildsEffect extends OneShotEffect {
private static final FilterCreaturePermanent filter2 = new FilterCreaturePermanent();
static {
filter2.add(new GreatestPowerPredicate());
}
public SelvalaHeartOfTheWildsEffect() {
super(Outcome.Benefit);
this.staticText = "that creature's controller may draw a card";
@ -116,27 +123,28 @@ class SelvalaHeartOfTheWildsEffect extends OneShotEffect {
if (permanent == null) {
permanent = (Permanent) game.getLastKnownInformation(targetPointer.getFirst(game, source), Zone.BATTLEFIELD);
}
if (permanent != null) {
Player cardowner = game.getPlayer(permanent.getControllerId());
if (cardowner.chooseUse(Outcome.DrawCard, "Would you like to draw a card?", source, game)) {
cardowner.drawCards(1, game);
if (permanent != null
&& filter2.match(permanent, game)) {
Player permanentController = game.getPlayer(permanent.getControllerId());
if (permanentController.chooseUse(Outcome.DrawCard, "Would you like to draw a card?", source, game)) {
permanentController.drawCards(1, game);
return true;
}
}
return true;
return false;
}
}
class GreatestPowerPredicate implements ObjectSourcePlayerPredicate<ObjectSourcePlayer<Permanent>> {
class GreatestPowerPredicate implements Predicate<Permanent> {
@Override
public boolean apply(ObjectSourcePlayer<Permanent> input, Game game) {
int pow = input.getObject().getPower().getValue();
for (UUID id : game.getPlayerList()) {
Player player = game.getPlayer(id);
public boolean apply(Permanent input, Game game) {
int power = input.getPower().getValue();
for (UUID playerId : game.getPlayerList()) {
Player player = game.getPlayer(playerId);
if (player != null) {
for (Permanent p : game.getBattlefield().getActivePermanents(new FilterControlledCreaturePermanent(), id, game)) {
if (p.getPower().getValue() >= pow && !p.equals(input.getObject())) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterCreaturePermanent(), playerId, game)) {
if (permanent.getPower().getValue() >= power && !permanent.equals(input)) {
return false; //we found something with equal/more power
}
}
@ -158,9 +166,9 @@ class GreatestPowerYouControlValue implements DynamicValue {
Player player = game.getPlayer(sourceAbility.getControllerId());
int amount = 0;
if (player != null) {
for (Permanent p : game.getBattlefield().getActivePermanents(new FilterControlledCreaturePermanent(), sourceAbility.getControllerId(), game)) {
if (p.getPower().getValue() > amount) {
amount = p.getPower().getValue();
for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterControlledCreaturePermanent(), sourceAbility.getControllerId(), game)) {
if (permanent.getPower().getValue() > amount) {
amount = permanent.getPower().getValue();
}
}
}
@ -174,6 +182,6 @@ class GreatestPowerYouControlValue implements DynamicValue {
@Override
public String getMessage() {
return "Add X mana in any combination of colors to your mana pool, where X is the number of creatures with defender you control.";
return "Add X mana in any combination of colors to your mana pool, where X is the greatest power among creatures you control.";
}
}

View file

@ -41,7 +41,7 @@ import mage.cards.CardSetInfo;
public class SlashPanther extends CardImpl {
public SlashPanther(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{4}{RP}");
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{4}{R/P}");
this.subtype.add("Cat");
this.power = new MageInt(4);

View file

@ -61,8 +61,8 @@ public class Spellskite extends CardImpl {
this.power = new MageInt(0);
this.toughness = new MageInt(4);
// {UP}: Change a target of target spell or ability to Spellskite.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new SpellskiteEffect(), new ManaCostsImpl("{UP}"));
// {U/P}: Change a target of target spell or ability to Spellskite.
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new SpellskiteEffect(), new ManaCostsImpl("{U/P}"));
ability.addTarget(new TargetStackObject());
this.addAbility(ability);
}
@ -129,12 +129,14 @@ class SpellskiteEffect extends OneShotEffect {
for (Target target : targets) {
for (UUID targetId : target.getTargets()) {
String name = getTargetName(targetId, game);
if (!targetId.equals(source.getSourceId()) && target.getTargets().contains(source.getSourceId())) {
if (targetId.equals(source.getSourceId())
|| target.getTargets().contains(source.getSourceId())) {
// you can't change this target to source because the source is already another targetId of that target.
twoTimesTarget = true;
continue;
}
if (target.canTarget(stackObject.getControllerId(), source.getSourceId(), sourceAbility, game)) {
if (target.canTarget(stackObject.getControllerId(), source.getSourceId(), sourceAbility, game)
&& !twoTimesTarget) {
validTargets = true;
if (name != null
&& controller.chooseUse(Outcome.Neutral, "Change target from " + name + " to " + sourceObject.getLogName() + '?', source, game)) {

View file

@ -41,7 +41,7 @@ import mage.cards.CardSetInfo;
public class SpinedThopter extends CardImpl {
public SpinedThopter(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{2}{UP}");
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{2}{U/P}");
this.subtype.add("Thopter");
this.power = new MageInt(2);

View file

@ -63,7 +63,7 @@ public class SurgicalExtraction extends CardImpl {
}
public SurgicalExtraction(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{BP}");
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{B/P}");
// Choose target card in a graveyard other than a basic land card. Search its owner's graveyard,
// hand, and library for any number of cards with the same name as that card and exile them.

View file

@ -41,7 +41,7 @@ import mage.cards.CardSetInfo;
public class TezzeretsGambit extends CardImpl {
public TezzeretsGambit(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{UP}");
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{3}{U/P}");
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(2));
this.getSpellAbility().addEffect(new ProliferateEffect());

View file

@ -41,7 +41,7 @@ import mage.cards.CardSetInfo;
public class ThunderingTanadon extends CardImpl {
public ThunderingTanadon(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{4}{GP}{GP}");
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{4}{G/P}{G/P}");
this.subtype.add("Beast");
this.power = new MageInt(5);

View file

@ -52,7 +52,7 @@ public class TrespassingSouleater extends CardImpl {
this.power = new MageInt(2);
this.toughness = new MageInt(2);
// {UP}: Trespassing Souleater can't be blocked this turn.
// {U/P}: Trespassing Souleater can't be blocked this turn.
this.addAbility(new SimpleActivatedAbility(Zone.BATTLEFIELD,
new CantBeBlockedSourceEffect(Duration.EndOfTurn),
new PhyrexianManaCost(ColoredManaSymbol.U)));

View file

@ -42,7 +42,7 @@ import mage.cards.CardSetInfo;
public class VaultSkirge extends CardImpl {
public VaultSkirge(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{1}{BP}");
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{1}{B/P}");
this.subtype.add("Imp");
this.power = new MageInt(1);

View file

@ -28,8 +28,8 @@
package mage.sets;
import mage.cards.ExpansionSet;
import mage.constants.SetType;
import mage.constants.Rarity;
import mage.constants.SetType;
/**
*
@ -69,15 +69,16 @@ public class Scourge extends ExpansionSet {
cards.add(new SetCardInfo("Break Asunder", 113, Rarity.COMMON, mage.cards.b.BreakAsunder.class));
cards.add(new SetCardInfo("Cabal Conditioning", 56, Rarity.RARE, mage.cards.c.CabalConditioning.class));
cards.add(new SetCardInfo("Cabal Interrogator", 57, Rarity.UNCOMMON, mage.cards.c.CabalInterrogator.class));
cards.add(new SetCardInfo("Dawn Elemental", 7, Rarity.RARE, mage.cards.d.DawnElemental.class));
cards.add(new SetCardInfo("Call to the Grave", 58, Rarity.RARE, mage.cards.c.CallToTheGrave.class));
cards.add(new SetCardInfo("Carbonize", 83, Rarity.UNCOMMON, mage.cards.c.Carbonize.class));
cards.add(new SetCardInfo("Carrion Feeder", 59, Rarity.COMMON, mage.cards.c.CarrionFeeder.class));
cards.add(new SetCardInfo("Chartooth Cougar", 84, Rarity.COMMON, mage.cards.c.ChartoothCougar.class));
cards.add(new SetCardInfo("Claws of Wirewood", 114, Rarity.UNCOMMON, mage.cards.c.ClawsOfWirewood.class));
cards.add(new SetCardInfo("Clutch of Undeath", 61, Rarity.COMMON, mage.cards.c.ClutchOfUndeath.class));
cards.add(new SetCardInfo("Coast Watcher", 30, Rarity.COMMON, mage.cards.c.CoastWatcher.class));
cards.add(new SetCardInfo("Consumptive Goo", 62, Rarity.RARE, mage.cards.c.ConsumptiveGoo.class));
cards.add(new SetCardInfo("Daru Warchief", 6, Rarity.UNCOMMON, mage.cards.d.DaruWarchief.class));
cards.add(new SetCardInfo("Dawn Elemental", 7, Rarity.RARE, mage.cards.d.DawnElemental.class));
cards.add(new SetCardInfo("Day of the Dragons", 31, Rarity.RARE, mage.cards.d.DayOfTheDragons.class));
cards.add(new SetCardInfo("Death's-Head Buzzard", 63, Rarity.COMMON, mage.cards.d.DeathsHeadBuzzard.class));
cards.add(new SetCardInfo("Decree of Annihilation", 85, Rarity.RARE, mage.cards.d.DecreeOfAnnihilation.class));

View file

@ -51,10 +51,10 @@ public class HideousEndTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerB, "Plains");
addCard(Zone.BATTLEFIELD, playerB, "Copper Myr");
// Target artifact or creature you control gains protection from artifacts or from the color of your choice until end of turn.
addCard(Zone.HAND, playerB, "Apostle's Blessing");
addCard(Zone.HAND, playerB, "Blessed Breath");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Hideous End", "Copper Myr");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Apostle's Blessing", "Copper Myr");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB, "Blessed Breath", "Copper Myr");
setChoice(playerB, "Black");
setStopAt(1, PhaseStep.BEGIN_COMBAT);

View file

@ -0,0 +1,52 @@
package org.mage.test.cards.conditional;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* @author JRHerlehy
* Created on 3/9/17.
*/
public class ClutchOfUndeathTest extends CardTestPlayerBase{
@Test
public void testEnchantNonZombie() {
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 5);
addCard(Zone.BATTLEFIELD, playerA, "Griselbrand");
addCard(Zone.HAND, playerA, "Clutch of Undeath");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Clutch of Undeath", "Griselbrand");
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertPowerToughness(playerA, "Griselbrand", 4, 4);
}
@Test
public void testEnchantZombie() {
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 5);
addCard(Zone.BATTLEFIELD, playerA, "Gurmag Angler");
addCard(Zone.HAND, playerA, "Clutch of Undeath");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Clutch of Undeath", "Gurmag Angler");
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertPowerToughness(playerA, "Gurmag Angler", 8, 8);
}
@Test
public void testEnchantChangeling() {
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 5);
addCard(Zone.BATTLEFIELD, playerA, "Amoeboid Changeling");
addCard(Zone.HAND, playerA, "Clutch of Undeath");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Clutch of Undeath", "Amoeboid Changeling");
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
execute();
assertPowerToughness(playerA, "Amoeboid Changeling", 4, 4);
}
}

View file

@ -0,0 +1,73 @@
package org.mage.test.cards.control;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.counters.CounterType;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
public class DackFaydenTest extends CardTestPlayerBase {
@Test
public void testDackFaydenEmblem() {
addCard(Zone.BATTLEFIELD, playerA, "Dack Fayden");
addCard(Zone.BATTLEFIELD, playerB, "Ornithopter");
addCard(Zone.HAND, playerA, "Gut Shot");
for(int i = 1; i < 8; i+= 2) {
activateAbility(i, PhaseStep.PRECOMBAT_MAIN, playerA,"+1: Target player draws two cards, then discards two cards.", playerB);
}
activateAbility(9, PhaseStep.PRECOMBAT_MAIN, playerA,
"-6: You get an emblem with \"Whenever you cast a spell that targets one or more permanents, gain control of those permanents.\"");
castSpell(10, PhaseStep.PRECOMBAT_MAIN, playerA, "Gut Shot", "Ornithopter");
setStopAt(10, PhaseStep.END_TURN);
execute();
assertLife(playerA, 18);
assertLife(playerB, 20);
assertCounterCount("Dack Fayden", CounterType.LOYALTY, 1);
assertPermanentCount(playerA, "Ornithopter", 1);
}
//Ensure that if a permanent moves to a different zone and comes back,
//it won't still be under the controller of Dack's Emblem.
@Test
public void testDackFaydenEmblemAcrossZones() {
addCard(Zone.BATTLEFIELD, playerA, "Dack Fayden");
addCard(Zone.BATTLEFIELD, playerB, "Ornithopter");
addCard(Zone.HAND, playerA, "Gut Shot");
addCard(Zone.HAND, playerA, "Unsummon");
addCard(Zone.BATTLEFIELD, playerA, "Island");
for(int i = 1; i < 8; i+= 2) {
activateAbility(i, PhaseStep.PRECOMBAT_MAIN, playerA,"+1: Target player draws two cards, then discards two cards.", playerB);
}
activateAbility(9, PhaseStep.PRECOMBAT_MAIN, playerA,
"-6: You get an emblem with \"Whenever you cast a spell that targets one or more permanents, gain control of those permanents.\"");
castSpell(10, PhaseStep.PRECOMBAT_MAIN, playerA, "Gut Shot", "Ornithopter");
castSpell(10, PhaseStep.PRECOMBAT_MAIN, playerA, "Unsummon", "Ornithopter", "Gut Shot", StackClause.WHILE_NOT_ON_STACK);
castSpell(10, PhaseStep.PRECOMBAT_MAIN, playerB, "Ornithopter");
setStopAt(10, PhaseStep.END_TURN);
execute();
assertLife(playerA, 18);
assertLife(playerB, 20);
assertCounterCount("Dack Fayden", CounterType.LOYALTY, 1);
assertPermanentCount(playerB, "Ornithopter", 1);
}
}

View file

@ -88,7 +88,7 @@ public class MimicVatTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, "Phyrexian Vault", 1);
// You may have Phyrexian Metamorph enter the battlefield as a copy of any artifact or creature on the battlefield, except it's an artifact in addition to its other types.
addCard(Zone.HAND, playerA, "Phyrexian Metamorph", 1);// Creature {3}{UP}
addCard(Zone.HAND, playerA, "Phyrexian Metamorph", 1);// Creature {3}{U/P}
addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion", 1);

View file

@ -44,7 +44,7 @@ public class PhyrexianMetamorphTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 5);
// You may have Phyrexian Metamorph enter the battlefield as a copy of any artifact or creature on the battlefield, except it's an artifact in addition to its other types.
addCard(Zone.HAND, playerA, "Phyrexian Metamorph"); // {3}{UP}
addCard(Zone.HAND, playerA, "Phyrexian Metamorph"); // {3}{U/P}
addCard(Zone.HAND, playerA, "Cloudshift");
//Flying
@ -64,7 +64,7 @@ public class PhyrexianMetamorphTest extends CardTestPlayerBase {
setStopAt(1, PhaseStep.END_TURN);
execute();
assertLife(playerA, 24);
assertLife(playerA, 22);
assertLife(playerB, 20);
assertGraveyardCount(playerA, "Cloudshift", 1);
@ -87,7 +87,7 @@ public class PhyrexianMetamorphTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
// You may have Phyrexian Metamorph enter the battlefield as a copy of any artifact or creature on the battlefield, except it's an artifact in addition to its other types.
addCard(Zone.HAND, playerA, "Phyrexian Metamorph"); // {3}{UP}
addCard(Zone.HAND, playerA, "Phyrexian Metamorph"); // {3}{U/P}
// Flying
// When Brago, King Eternal deals combat damage to a player, exile any number of target nonland permanents you control, then return those cards to the battlefield under their owner's control.
@ -109,7 +109,7 @@ public class PhyrexianMetamorphTest extends CardTestPlayerBase {
setStopAt(3, PhaseStep.END_COMBAT);
execute();
assertLife(playerA, 20);
assertLife(playerA, 18);
assertLife(playerB, 18);
assertPermanentCount(playerA, "Ponyback Brigade", 1);
@ -128,7 +128,7 @@ public class PhyrexianMetamorphTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
// You may have Phyrexian Metamorph enter the battlefield as a copy of any artifact or creature on the battlefield, except it's an artifact in addition to its other types.
addCard(Zone.HAND, playerA, "Phyrexian Metamorph"); // {3}{UP}
addCard(Zone.HAND, playerA, "Phyrexian Metamorph"); // {3}{U/P}
addCard(Zone.BATTLEFIELD, playerB, "Alloy Myr", 1);
addCard(Zone.BATTLEFIELD, playerB, "Kitesail", 1);

View file

@ -57,7 +57,7 @@ public class CostModificationTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerB, "Plains", 2);
// Look at target player's hand.
// Draw a card.
addCard(Zone.HAND, playerB, "Gitaxian Probe"); // Sorcery {UP}
addCard(Zone.HAND, playerB, "Gitaxian Probe"); // Sorcery {U/P}
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Gitaxian Probe", playerA);
setStopAt(2, PhaseStep.BEGIN_COMBAT);

View file

@ -192,4 +192,28 @@ public class DoublingSeasonTest extends CardTestPlayerBase {
assertLife(playerA, 20);
}
/**
* Gatherer Ruling:
* 10/1/2005: Planeswalkers will enter the battlefield with double the normal amount of loyalty counters. However,
* if you activate an ability whose cost has you put loyalty counters on a planeswalker, the number you put on isnt doubled.
* This is because those counters are put on as a cost, not as an effect.
*/
@Test
public void testPlaneswalkerLoyalty() {
addCard(Zone.BATTLEFIELD, playerA, "Tibalt, the Fiend-Blooded");
addCard(Zone.BATTLEFIELD, playerA, "Doubling Season");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA,"+1: Draw a card, then discard a card at random.");
setStopAt(1, PhaseStep.END_TURN);
execute();
assertLife(playerA, 20);
assertLife(playerB, 20);
//Should not be doubled
assertCounterCount("Tibalt, the Fiend-Blooded", CounterType.LOYALTY, 3);
}
}

View file

@ -1,40 +0,0 @@
package org.mage.test.cards.single;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* Created by goesta on 12/02/2017.
*/
public class SpellskiteTest extends CardTestPlayerBase {
@Test
public void testThatSplitDamageCanGetRedirected() {
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
addCard(Zone.BATTLEFIELD, playerB, "Spellskite");
addCard(Zone.BATTLEFIELD, playerB, "Scute Mob");
addCard(Zone.BATTLEFIELD, playerB, "Island");
addCard(Zone.HAND, playerA, "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");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerB, 1);
assertPowerToughness(playerB, "Scute Mob", 1, 1);
}
}

View file

@ -52,13 +52,13 @@ public class BecomesTheTargetTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 1);
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{WP},{T}: Tap target creature", "Silvercoat Lion");
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{W/P},{T}: Tap target creature", "Silvercoat Lion");
setStopAt(2, PhaseStep.BEGIN_COMBAT);
execute();
assertLife(playerA, 20);
assertLife(playerB, 20);
assertLife(playerB, 18);
assertPermanentCount(playerA, "Silvercoat Lion", 0);
assertTapped("Silvercoat Lion", true);

View file

@ -157,7 +157,7 @@ public class SacredGroundTest extends CardTestPlayerBase {
// Choose target card in a graveyard other than a basic land card. Search its owner's graveyard,
// hand, and library for any number of cards with the same name as that card and exile them.
// Then that player shuffles his or her library.
addCard(Zone.HAND, playerA, "Surgical Extraction"); // Instant {BP}
addCard(Zone.HAND, playerA, "Surgical Extraction"); // Instant {B/P}
addCard(Zone.BATTLEFIELD, playerB, "Caves of Koilos", 1);
/**
@ -177,7 +177,7 @@ public class SacredGroundTest extends CardTestPlayerBase {
assertGraveyardCount(playerA, "Surgical Extraction", 1);
assertExileCount("Caves of Koilos", 1);
assertLife(playerA, 20);
assertLife(playerA, 18);
assertLife(playerB, 18);
}

View file

@ -52,7 +52,7 @@ public class SpellskiteTest extends CardTestPlayerBase {
addCard(Zone.HAND, playerA, "Lightning Bolt");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{UP}: Change a target of target spell or ability to {this}.", "Lightning Bolt");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{U/P}: Change a target of target spell or ability to {this}.", "Lightning Bolt");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
@ -60,7 +60,7 @@ public class SpellskiteTest extends CardTestPlayerBase {
assertGraveyardCount(playerA, "Lightning Bolt", 1);
assertPermanentCount(playerA, "Spellskite", 1);
assertLife(playerA, 20);
assertLife(playerA, 18);
assertLife(playerB, 20);
assertPowerToughness(playerA, "Spellskite", 3, 7);
@ -90,7 +90,7 @@ public class SpellskiteTest extends CardTestPlayerBase {
addCard(Zone.BATTLEFIELD, playerA, "Vedalken Shackles", 1);
addCard(Zone.BATTLEFIELD, playerB, "Island", 6);
// {UP}: Change a target of target spell or ability to Spellskite.
// {U/P}: Change a target of target spell or ability to Spellskite.
addCard(Zone.BATTLEFIELD, playerB, "Spellskite", 1);
// {4}{U}{U}
// Whenever Frost Titan becomes the target of a spell or ability an opponent controls, counter that spell or ability unless its controller pays 2.
@ -102,7 +102,7 @@ public class SpellskiteTest extends CardTestPlayerBase {
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Frost Titan");
addTarget(playerB, "Silvercoat Lion");
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{UP}: Change a target", "stack ability (Whenever {this} enters ");
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerA, "{U/P}: Change a target", "stack ability (Whenever {this} enters ");
setStopAt(2, PhaseStep.BEGIN_COMBAT);
execute();
@ -141,7 +141,7 @@ public class SpellskiteTest extends CardTestPlayerBase {
setModeChoice(playerA, "1"); // Counter target spell
setModeChoice(playerA, "2"); // return target permanent to its owner's hand
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{UP}: Change a target of target spell or ability to {this}.", "Cryptic Command", "Cryptic Command");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{U/P}: Change a target of target spell or ability to {this}.", "Cryptic Command", "Cryptic Command");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
@ -154,7 +154,7 @@ public class SpellskiteTest extends CardTestPlayerBase {
assertPermanentCount(playerB, "Silvercoat Lion", 1);
assertLife(playerA, 20);
assertLife(playerB, 20);
assertLife(playerB, 18);
}
@ -182,7 +182,7 @@ public class SpellskiteTest extends CardTestPlayerBase {
setModeChoice(playerA, "2"); // return target permanent to its owner's hand
setModeChoice(playerA, "3"); // tap all creatures your opponents control
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{UP}: Change a target of target spell or ability to {this}.", "Cryptic Command");
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{U/P}: Change a target of target spell or ability to {this}.", "Cryptic Command");
setStopAt(2, PhaseStep.BEGIN_COMBAT);
execute();
@ -194,7 +194,7 @@ public class SpellskiteTest extends CardTestPlayerBase {
assertTapped("Silvercoat Lion", true);
assertLife(playerA, 20);
assertLife(playerB, 20);
assertLife(playerB, 18);
}
@ -214,7 +214,7 @@ public class SpellskiteTest extends CardTestPlayerBase {
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Lightning Bolt", playerB);
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{UP}: Change a target of target spell or ability to {this}.", "Lightning Bolt");
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerB, "{U/P}: Change a target of target spell or ability to {this}.", "Lightning Bolt");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
@ -222,7 +222,7 @@ public class SpellskiteTest extends CardTestPlayerBase {
assertGraveyardCount(playerA, "Lightning Bolt", 1);
assertLife(playerA, 20);
assertLife(playerB, 20);
assertLife(playerB, 18);
}
@ -250,4 +250,102 @@ public class SpellskiteTest extends CardTestPlayerBase {
assertPowerToughness(playerB, "Spellskite", 3, 7);
}
@Test
public void testThatSpellSkiteCantBeTargetedTwiceOrMore() {
/* According to rules, the same object can be a legal target only
once for each instances of the word target in the text
of a spell or ability. In this case, the target can't be changed
due to Spellskite already being a target.
*/
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
addCard(Zone.BATTLEFIELD, playerB, "Spellskite");
addCard(Zone.BATTLEFIELD, playerB, "Scute Mob");
addCard(Zone.BATTLEFIELD, playerB, "Island");
addCard(Zone.HAND, playerA, "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");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerB, 2);
}
public void testThatSplitDamageCanGetRedirected() {
/* Standard redirect test
The Spellskite should die from the 5 damage that was redirected to it
*/
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, "Scute Mob"); // 1/1 creauture
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, "Scute Mob");
setChoice(playerA, "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");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerB, 1);
assertPermanentCount(playerB, "Scute Mob", 1);
}
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, "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
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
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerB, 3);
assertPermanentCount(playerB, "Pearled Unicorn", 1);//it lives on
assertPowerToughness(playerB, "Spellskite", 0, 2);
}
}

View file

@ -18,7 +18,7 @@ public class PostMortemLungeTest extends CardTestPlayerBase {
public void testExilesCreatureAtEndStep() {
/*
{P}{X} - Sorcery
{X}{B/P} - Sorcery
Return target creature card with converted mana cost X from your graveyard to the battlefield.
It gains haste. Exile it at the beginning of the next end step.
*/

View file

@ -43,7 +43,7 @@ public class ThragtuskTest extends CardTestPlayerBase {
/**
* Test if a Thragtusk is copied by a PhyrexianMetamorph that both triggers
* cotrrect work
* correct work
*/
@Test
public void testPhyrexianMetamorph() {
@ -69,7 +69,7 @@ public class ThragtuskTest extends CardTestPlayerBase {
assertGraveyardCount(playerA, "Phyrexian Metamorph", 1);
assertGraveyardCount(playerB, "Public Execution", 1);
assertLife(playerA, 25);
assertLife(playerA, 23);
assertLife(playerB, 20); // Thragtusk ETB ability does not trigger if set to battlefield on test game start
assertPermanentCount(playerA, "Beast", 1);
@ -116,7 +116,7 @@ public class ThragtuskTest extends CardTestPlayerBase {
assertGraveyardCount(playerA, "Phyrexian Metamorph", 1);
assertGraveyardCount(playerB, "Public Execution", 1);
assertLife(playerA, 25);
assertLife(playerA, 23);
assertLife(playerB, 20); // Thragtusk ETB ability does not trigger if set to battlefield on test game start
assertPermanentCount(playerA, "Beast", 0);

View file

@ -31,11 +31,9 @@ import mage.MageObject;
import mage.MageObjectReference;
import mage.Mana;
import mage.abilities.costs.*;
import mage.abilities.costs.common.PayLifeCost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCost;
import mage.abilities.costs.mana.ManaCosts;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.costs.mana.VariableManaCost;
import mage.abilities.costs.mana.*;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.Effect;
import mage.abilities.effects.Effects;
@ -62,6 +60,7 @@ import mage.watchers.Watcher;
import org.apache.log4j.Logger;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
@ -298,6 +297,9 @@ public abstract class AbilityImpl implements Ability {
&& game.replaceEvent(GameEvent.getEvent(GameEvent.EventType.CAST_SPELL_LATE, getId(), getSourceId(), getControllerId()), this)) {
return false;
}
handlePhyrexianManaCosts(game, sourceId, controller);
for (UUID modeId : this.getModes().getSelectedModes()) {
this.getModes().setActiveMode(modeId);
//20121001 - 601.2c
@ -503,6 +505,27 @@ public abstract class AbilityImpl implements Ability {
return announceString.toString();
}
/**
* 601.2b
* If a cost that will be paid as the spell is being cast includes Phyrexian mana symbols,
* the player announces whether he or she intends to pay 2 life or the corresponding colored mana cost for each of those symbols.
*/
private void handlePhyrexianManaCosts(Game game, UUID sourceId, Player controller) {
Iterator<ManaCost> costIterator = manaCostsToPay.iterator();
while(costIterator.hasNext()) {
ManaCost cost = costIterator.next();
if(cost instanceof PhyrexianManaCost) {
PhyrexianManaCost phyrexianManaCost = (PhyrexianManaCost)cost;
PayLifeCost payLifeCost = new PayLifeCost(2);
if(payLifeCost.canPay(this, sourceId, controller.getId(), game) &&
controller.chooseUse(Outcome.LoseLife, "Pay 2 life instead of " + phyrexianManaCost.getBaseText() + "?", this, game)) {
costIterator.remove();
costs.add(payLifeCost);
}
}
}
}
/**
* Handles X mana costs and sets manaCostsToPay.
*

View file

@ -27,7 +27,6 @@
*/
package mage.abilities.costs.common;
import java.util.UUID;
import mage.abilities.Ability;
import mage.abilities.costs.Cost;
import mage.abilities.costs.CostImpl;
@ -35,6 +34,8 @@ import mage.counters.CounterType;
import mage.game.Game;
import mage.game.permanent.Permanent;
import java.util.UUID;
/**
*
* @author BetaSteward_at_googlemail.com
@ -62,6 +63,12 @@ public class PayLoyaltyCost extends CostImpl {
return planeswalker != null && planeswalker.getCounters(game).getCount(CounterType.LOYALTY) + amount >= 0 && planeswalker.canLoyaltyBeUsed(game);
}
/**
* Gatherer Ruling:
* 10/1/2005: Planeswalkers will enter the battlefield with double the normal amount of loyalty counters. However,
* if you activate an ability whose cost has you put loyalty counters on a planeswalker, the number you put on isnt doubled.
* This is because those counters are put on as a cost, not as an effect.
**/
@Override
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) {
Permanent planeswalker = game.getPermanent(sourceId);

View file

@ -50,34 +50,20 @@ public class PhyrexianManaCost extends ColoredManaCost {
super(manaCost);
}
@Override
public void assignPayment(Game game, Ability ability, ManaPool pool, Cost costToPay) {
assignColored(ability, game, pool, this.mana, costToPay);
}
@Override
public String getText() {
return '{' + mana.toString() + "P}";
return '{' + mana.toString() + "/P}";
}
public String getBaseText() {
return super.getText();
}
@Override
public PhyrexianManaCost getUnpaid() {
return this;
public ColoredManaCost getUnpaid() {
return new ColoredManaCost(this);
}
@Override
public boolean canPay(Ability ability, UUID sourceId, UUID controllerId, Game game) {
if (!game.getPlayer(controllerId).isLifeTotalCanChange()) {
return false;
}
return game.getPlayer(controllerId).getLife() >= 2;
}
@Override
public boolean pay(Ability ability, Game game, UUID sourceId, UUID controllerId, boolean noMana, Cost costToPay) {
this.paid = game.getPlayer(controllerId).loseLife(2, game, false) == 2;
return paid;
}
@Override
public PhyrexianManaCost copy() {

View file

@ -29,8 +29,13 @@ package mage.abilities.effects;
import mage.abilities.Ability;
import mage.abilities.costs.Cost;
import mage.abilities.costs.Costs;
import mage.abilities.costs.CostsImpl;
import mage.abilities.costs.common.PayLifeCost;
import mage.abilities.costs.mana.ManaCost;
import mage.abilities.costs.mana.ManaCosts;
import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.costs.mana.PhyrexianManaCost;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.game.Game;
@ -38,6 +43,9 @@ import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType;
import mage.players.Player;
import java.util.Iterator;
import java.util.List;
/**
*
* @author LevelX2
@ -141,6 +149,7 @@ public abstract class PayCostToAttackBlockEffectImpl extends ReplacementEffectIm
attackBlockManaTax.clearPaid();
if (attackBlockManaTax.canPay(source, source.getSourceId(), player.getId(), game)
&& player.chooseUse(Outcome.Neutral, chooseText, source, game)) {
handlePhyrexianManaCosts(manaCosts, player, source, game);
if (attackBlockManaTax instanceof ManaCostsImpl) {
if (attackBlockManaTax.payOrRollback(source, game, source.getSourceId(), event.getPlayerId())) {
return false;
@ -152,6 +161,27 @@ public abstract class PayCostToAttackBlockEffectImpl extends ReplacementEffectIm
return false;
}
private void handlePhyrexianManaCosts(ManaCosts<ManaCost> manaCosts, Player player, Ability source, Game game) {
Iterator<ManaCost> manaCostIterator = manaCosts.iterator();
Costs<PayLifeCost> costs = new CostsImpl<>();
while(manaCostIterator.hasNext()) {
ManaCost manaCost = manaCostIterator.next();
if(manaCost instanceof PhyrexianManaCost) {
PhyrexianManaCost phyrexianManaCost = (PhyrexianManaCost)manaCost;
PayLifeCost payLifeCost = new PayLifeCost(2);
if(payLifeCost.canPay(source, source.getSourceId(), player.getId(), game) &&
player.chooseUse(Outcome.LoseLife, "Pay 2 life instead of " + phyrexianManaCost.getBaseText() + "?", source, game)) {
manaCostIterator.remove();
costs.add(payLifeCost);
}
}
}
costs.pay(source, game, source.getSourceId(), player.getId(), false, null);
}
private boolean handleOtherCosts(Cost attackBlockOtherTax, GameEvent event, Ability source, Game game) {
Player player = game.getPlayer(event.getPlayerId());
if (player != null) {

View file

@ -2438,7 +2438,9 @@ public abstract class PlayerImpl implements Player, Serializable {
if (!copy.canActivate(playerId, game)) {
return false;
}
game.getContinuousEffects().costModification(copy, game);
if(available != null) {
game.getContinuousEffects().costModification(copy, game);
}
Card card = game.getCard(ability.getSourceId());
if (card != null) {

View file

@ -135,12 +135,12 @@ public class TargetDefender extends TargetImpl {
MageObject targetSource = game.getObject(sourceId);
for (UUID playerId: game.getState().getPlayersInRange(sourceControllerId, game)) {
Player player = game.getPlayer(playerId);
if (player != null && player.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.match(player, game)) {
if (player != null && (player.canBeTargetedBy(targetSource, sourceControllerId, game) || notTarget) && filter.match(player, game)) {
possibleTargets.add(playerId);
}
}
for (Permanent permanent: game.getBattlefield().getActivePermanents(new FilterPlaneswalkerPermanent(), sourceControllerId, game)) {
if (permanent.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.match(permanent, game)) {
if ((permanent.canBeTargetedBy(targetSource, sourceControllerId, game) || notTarget) && filter.match(permanent, game)) {
possibleTargets.add(permanent.getId());
}
}