mirror of
https://github.com/magefree/mage.git
synced 2025-12-22 03:22:00 -08:00
implement [MH3] Grist, Voracious Larva // Grist, the Plague Swarm
This commit is contained in:
parent
79165f269c
commit
a1bbb49a38
4 changed files with 595 additions and 0 deletions
163
Mage.Sets/src/mage/cards/g/GristThePlagueSwarm.java
Normal file
163
Mage.Sets/src/mage/cards/g/GristThePlagueSwarm.java
Normal file
|
|
@ -0,0 +1,163 @@
|
||||||
|
package mage.cards.g;
|
||||||
|
|
||||||
|
import mage.ObjectColor;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.LoyaltyAbility;
|
||||||
|
import mage.abilities.effects.Effect;
|
||||||
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
import mage.abilities.effects.common.CreateTokenCopyTargetEffect;
|
||||||
|
import mage.abilities.effects.common.CreateTokenEffect;
|
||||||
|
import mage.abilities.effects.common.DestroyTargetEffect;
|
||||||
|
import mage.abilities.effects.common.counter.AddCountersTargetEffect;
|
||||||
|
import mage.cards.Card;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.cards.Cards;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.Outcome;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.constants.SuperType;
|
||||||
|
import mage.counters.CounterType;
|
||||||
|
import mage.filter.StaticFilters;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
import mage.game.permanent.PermanentCard;
|
||||||
|
import mage.game.permanent.token.IzoniInsectToken;
|
||||||
|
import mage.players.Player;
|
||||||
|
import mage.target.TargetPermanent;
|
||||||
|
import mage.target.targetpointer.FixedTargets;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Susucr
|
||||||
|
*/
|
||||||
|
public final class GristThePlagueSwarm extends CardImpl {
|
||||||
|
|
||||||
|
public GristThePlagueSwarm(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.PLANESWALKER}, "");
|
||||||
|
|
||||||
|
this.supertype.add(SuperType.LEGENDARY);
|
||||||
|
this.subtype.add(SubType.GRIST);
|
||||||
|
this.setStartingLoyalty(3);
|
||||||
|
|
||||||
|
this.color.setBlack(true);
|
||||||
|
this.color.setGreen(true);
|
||||||
|
this.nightCard = true;
|
||||||
|
|
||||||
|
// +1: Create a 1/1 black and green Insect creature token, then mill two cards. Put a deathtouch counter on the token if a black card was milled this way.
|
||||||
|
this.addAbility(new LoyaltyAbility(new GristThePlagueSwarmPlus1Effect(), 1));
|
||||||
|
|
||||||
|
// -2: Destroy target artifact or enchantment.
|
||||||
|
Ability ability = new LoyaltyAbility(new DestroyTargetEffect(), -2);
|
||||||
|
ability.addTarget(new TargetPermanent(StaticFilters.FILTER_PERMANENT_ARTIFACT_OR_ENCHANTMENT));
|
||||||
|
this.addAbility(ability);
|
||||||
|
|
||||||
|
// -6: For each creature card in your graveyard, create a token that's a copy of it, except it's a 1/1 black and green Insect.
|
||||||
|
this.addAbility(new LoyaltyAbility(new GristThePlagueSwarmMinus6Effect(), -6));
|
||||||
|
}
|
||||||
|
|
||||||
|
private GristThePlagueSwarm(final GristThePlagueSwarm card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GristThePlagueSwarm copy() {
|
||||||
|
return new GristThePlagueSwarm(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GristThePlagueSwarmPlus1Effect extends OneShotEffect {
|
||||||
|
|
||||||
|
GristThePlagueSwarmPlus1Effect() {
|
||||||
|
super(Outcome.PutCreatureInPlay);
|
||||||
|
staticText = "Create a 1/1 black and green Insect creature token, then mill two cards. "
|
||||||
|
+ "Put a deathtouch counter on the token if a black card was milled this way.";
|
||||||
|
}
|
||||||
|
|
||||||
|
private GristThePlagueSwarmPlus1Effect(final GristThePlagueSwarmPlus1Effect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GristThePlagueSwarmPlus1Effect copy() {
|
||||||
|
return new GristThePlagueSwarmPlus1Effect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
|
if (controller == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a 1/1 black and green Insect creature token
|
||||||
|
CreateTokenEffect effect = new CreateTokenEffect(new IzoniInsectToken());
|
||||||
|
effect.apply(game, source);
|
||||||
|
|
||||||
|
// Then mill two cards
|
||||||
|
Cards cards = controller.millCards(2, source, game);
|
||||||
|
|
||||||
|
// Put a deathtouch counter on the token if a black card was milled this way.
|
||||||
|
if (cards.getCards(game).stream().anyMatch(card -> card.getColor(game).isBlack())) {
|
||||||
|
List<Permanent> tokens = effect
|
||||||
|
.getLastAddedTokenIds()
|
||||||
|
.stream()
|
||||||
|
.map(game::getPermanent)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
if (!tokens.isEmpty()) {
|
||||||
|
Effect addEffect = new AddCountersTargetEffect(CounterType.DEATHTOUCH.createInstance());
|
||||||
|
addEffect.setTargetPointer(new FixedTargets(tokens, game));
|
||||||
|
addEffect.apply(game, source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GristThePlagueSwarmMinus6Effect extends OneShotEffect {
|
||||||
|
|
||||||
|
GristThePlagueSwarmMinus6Effect() {
|
||||||
|
super(Outcome.PutCreatureInPlay);
|
||||||
|
staticText = "For each creature card in your graveyard, create a token that's a copy of it, "
|
||||||
|
+ "except it's a 1/1 black and green Insect.";
|
||||||
|
}
|
||||||
|
|
||||||
|
private GristThePlagueSwarmMinus6Effect(final GristThePlagueSwarmMinus6Effect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GristThePlagueSwarmMinus6Effect copy() {
|
||||||
|
return new GristThePlagueSwarmMinus6Effect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
Player controller = game.getPlayer(source.getControllerId());
|
||||||
|
if (controller == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Set<Card> cards = controller.getGraveyard().getCards(StaticFilters.FILTER_CARD_CREATURE, game);
|
||||||
|
if (cards.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (Card card : cards) {
|
||||||
|
CreateTokenCopyTargetEffect effect = new CreateTokenCopyTargetEffect(
|
||||||
|
null, null, false, 1, false,
|
||||||
|
false, null, 1, 1, false
|
||||||
|
);
|
||||||
|
effect.setSavedPermanent(new PermanentCard(card, controller.getId(), game));
|
||||||
|
effect.setOnlyColor(new ObjectColor("BG"));
|
||||||
|
effect.setOnlySubType(SubType.INSECT);
|
||||||
|
effect.apply(game, source);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
103
Mage.Sets/src/mage/cards/g/GristVoraciousLarva.java
Normal file
103
Mage.Sets/src/mage/cards/g/GristVoraciousLarva.java
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
package mage.cards.g;
|
||||||
|
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.abilities.Pronoun;
|
||||||
|
import mage.abilities.common.EntersBattlefieldThisOrAnotherTriggeredAbility;
|
||||||
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
|
import mage.abilities.effects.common.DoIfCostPaid;
|
||||||
|
import mage.abilities.effects.common.ExileAndReturnSourceEffect;
|
||||||
|
import mage.abilities.keyword.DeathtouchAbility;
|
||||||
|
import mage.abilities.keyword.TransformAbility;
|
||||||
|
import mage.cards.CardImpl;
|
||||||
|
import mage.cards.CardSetInfo;
|
||||||
|
import mage.constants.*;
|
||||||
|
import mage.filter.StaticFilters;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.events.EntersTheBattlefieldEvent;
|
||||||
|
import mage.game.events.GameEvent;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
import mage.game.stack.Spell;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Susucr
|
||||||
|
*/
|
||||||
|
public final class GristVoraciousLarva extends CardImpl {
|
||||||
|
|
||||||
|
public GristVoraciousLarva(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}");
|
||||||
|
|
||||||
|
this.supertype.add(SuperType.LEGENDARY);
|
||||||
|
this.subtype.add(SubType.INSECT);
|
||||||
|
this.power = new MageInt(1);
|
||||||
|
this.toughness = new MageInt(2);
|
||||||
|
|
||||||
|
this.secondSideCardClazz = GristThePlagueSwarm.class;
|
||||||
|
|
||||||
|
// Deathtouch
|
||||||
|
this.addAbility(DeathtouchAbility.getInstance());
|
||||||
|
|
||||||
|
// Whenever Grist, Voracious Larva or another creature enters the battlefield under your control, if it entered from your graveyard or was cast from your graveyard, you may pay {G}. If you do, exile Grist, then return it to the battlefield transformed under its owner's control.
|
||||||
|
this.addAbility(new TransformAbility());
|
||||||
|
this.addAbility(new GristVoraciousLarvaTriggeredAbility());
|
||||||
|
}
|
||||||
|
|
||||||
|
private GristVoraciousLarva(final GristVoraciousLarva card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GristVoraciousLarva copy() {
|
||||||
|
return new GristVoraciousLarva(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GristVoraciousLarvaTriggeredAbility extends EntersBattlefieldThisOrAnotherTriggeredAbility {
|
||||||
|
|
||||||
|
GristVoraciousLarvaTriggeredAbility() {
|
||||||
|
super(
|
||||||
|
new DoIfCostPaid(
|
||||||
|
new ExileAndReturnSourceEffect(PutCards.BATTLEFIELD_TRANSFORMED, Pronoun.IT),
|
||||||
|
new ManaCostsImpl<>("{G}")
|
||||||
|
), StaticFilters.FILTER_PERMANENT_CREATURE, false, true);
|
||||||
|
setTriggerPhrase("Whenever {this} or another creature enters the battlefield under your control, "
|
||||||
|
+ "if it entered from your graveyard or was cast from your graveyard, ");
|
||||||
|
}
|
||||||
|
|
||||||
|
private GristVoraciousLarvaTriggeredAbility(final GristVoraciousLarvaTriggeredAbility ability) {
|
||||||
|
super(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GristVoraciousLarvaTriggeredAbility copy() {
|
||||||
|
return new GristVoraciousLarvaTriggeredAbility(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
|
EntersTheBattlefieldEvent zEvent = (EntersTheBattlefieldEvent) event;
|
||||||
|
if (zEvent == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Permanent permanent = zEvent.getTarget();
|
||||||
|
if (permanent == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Zone fromZone = zEvent.getFromZone();
|
||||||
|
boolean fromGraveyard = false;
|
||||||
|
if (fromZone == Zone.GRAVEYARD) {
|
||||||
|
// Directly from the graveyard
|
||||||
|
fromGraveyard = true;
|
||||||
|
} else if (fromZone == Zone.STACK) {
|
||||||
|
// Get spell in the stack.
|
||||||
|
Spell spell = game.getSpellOrLKIStack(permanent.getId());
|
||||||
|
if (spell != null && spell.getFromZone() == Zone.GRAVEYARD) {
|
||||||
|
// Creature was cast from graveyard
|
||||||
|
fromGraveyard = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fromGraveyard && super.checkTrigger(event, game);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -46,6 +46,8 @@ public final class ModernHorizons3 extends ExpansionSet {
|
||||||
cards.add(new SetCardInfo("Forest", 308, Rarity.LAND, mage.cards.basiclands.Forest.class, FULL_ART_BFZ_VARIOUS));
|
cards.add(new SetCardInfo("Forest", 308, Rarity.LAND, mage.cards.basiclands.Forest.class, FULL_ART_BFZ_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Frogmyr Enforcer", 120, Rarity.UNCOMMON, mage.cards.f.FrogmyrEnforcer.class));
|
cards.add(new SetCardInfo("Frogmyr Enforcer", 120, Rarity.UNCOMMON, mage.cards.f.FrogmyrEnforcer.class));
|
||||||
cards.add(new SetCardInfo("Grim Servant", 97, Rarity.UNCOMMON, mage.cards.g.GrimServant.class));
|
cards.add(new SetCardInfo("Grim Servant", 97, Rarity.UNCOMMON, mage.cards.g.GrimServant.class));
|
||||||
|
cards.add(new SetCardInfo("Grist, the Plague Swarm", 251, Rarity.MYTHIC, mage.cards.g.GristThePlagueSwarm.class));
|
||||||
|
cards.add(new SetCardInfo("Grist, Voracious Larva", 251, Rarity.MYTHIC, mage.cards.g.GristVoraciousLarva.class));
|
||||||
cards.add(new SetCardInfo("Island", 305, Rarity.LAND, mage.cards.basiclands.Island.class, FULL_ART_BFZ_VARIOUS));
|
cards.add(new SetCardInfo("Island", 305, Rarity.LAND, mage.cards.basiclands.Island.class, FULL_ART_BFZ_VARIOUS));
|
||||||
cards.add(new SetCardInfo("It That Heralds the End", 9, Rarity.UNCOMMON, mage.cards.i.ItThatHeraldsTheEnd.class));
|
cards.add(new SetCardInfo("It That Heralds the End", 9, Rarity.UNCOMMON, mage.cards.i.ItThatHeraldsTheEnd.class));
|
||||||
cards.add(new SetCardInfo("Jet Medallion", 292, Rarity.RARE, mage.cards.j.JetMedallion.class));
|
cards.add(new SetCardInfo("Jet Medallion", 292, Rarity.RARE, mage.cards.j.JetMedallion.class));
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,327 @@
|
||||||
|
package org.mage.test.cards.single.mh3;
|
||||||
|
|
||||||
|
import mage.ObjectColor;
|
||||||
|
import mage.constants.CardType;
|
||||||
|
import mage.constants.PhaseStep;
|
||||||
|
import mage.constants.SubType;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import mage.counters.CounterType;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Susucr
|
||||||
|
*/
|
||||||
|
public class GristVoraciousLarvaTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link mage.cards.g.GristVoraciousLarva Grist, Voracious Larva} {G}
|
||||||
|
* Legendary Creature — Insect
|
||||||
|
* Deathtouch
|
||||||
|
* Whenever Grist, Voracious Larva or another creature enters the battlefield under your control, if it entered from your graveyard or you cast it from your graveyard, you may pay {G}. If you do, exile Grist, then return it to the battlefield transformed under its owner’s control.
|
||||||
|
* 1/2
|
||||||
|
* // {@link mage.cards.g.GristThePlagueSwarm Grist, the Plague Swarm}
|
||||||
|
* Legendary Planeswalker — Grist
|
||||||
|
* +1: Create a 1/1 black and green Insect creature token, then mill two cards. Put a deathtouch counter on the token if a black card was milled this way.
|
||||||
|
* −2: Destroy target artifact or enchantment.
|
||||||
|
* −6: For each creature card in your graveyard, create a token that’s a copy of it, except it’s a 1/1 black and green Insect.
|
||||||
|
* Loyalty: 3
|
||||||
|
*/
|
||||||
|
private static final String grist = "Grist, Voracious Larva";
|
||||||
|
private static final String gristPW = "Grist, the Plague Swarm";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_Unearth_Trigger_NoMana() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
|
||||||
|
addCard(Zone.GRAVEYARD, playerA, grist);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Swamp");
|
||||||
|
addCard(Zone.HAND, playerA, "Unearth");
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Unearth", grist);
|
||||||
|
setChoice(playerA, false); // can't pay for the trigger
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, grist, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_Unearth_Trigger_Pay() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
|
||||||
|
addCard(Zone.GRAVEYARD, playerA, grist);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Swamp");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest");
|
||||||
|
addCard(Zone.HAND, playerA, "Unearth");
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Unearth", grist);
|
||||||
|
setChoice(playerA, true); // pay for the trigger
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, gristPW, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_Unearth_Trigger_NoPay() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
|
||||||
|
addCard(Zone.GRAVEYARD, playerA, grist);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Swamp");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest");
|
||||||
|
addCard(Zone.HAND, playerA, "Unearth");
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Unearth", grist);
|
||||||
|
setChoice(playerA, false); // don't pay for the trigger
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, grist, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_Bloodghast_Trigger() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, grist);
|
||||||
|
addCard(Zone.HAND, playerA, "Forest");
|
||||||
|
addCard(Zone.GRAVEYARD, playerA, "Bloodghast");
|
||||||
|
|
||||||
|
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Forest");
|
||||||
|
setChoice(playerA, true); // yes to Bloodghast's trigger
|
||||||
|
setChoice(playerA, true); // pay for Grist's trigger
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, gristPW, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_CastBloodghast_NoTrigger() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, grist);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Bayou", 3);
|
||||||
|
addCard(Zone.HAND, playerA, "Bloodghast");
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Bloodghast");
|
||||||
|
// no Grist's trigger
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, grist, 1);
|
||||||
|
assertPermanentCount(playerA, "Bloodghast", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_CastGravecrawler_Trigger() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, grist);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Bayou", 2);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Gravecrawler");
|
||||||
|
addCard(Zone.GRAVEYARD, playerA, "Gravecrawler");
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Gravecrawler");
|
||||||
|
setChoice(playerA, true); // pay for Grist's trigger
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, gristPW, 1);
|
||||||
|
assertPermanentCount(playerA, "Gravecrawler", 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_Cast_NonCreature_NoTrigger() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, grist);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Muldrotha, the Gravetide"); // During each of your turns, you may play a land and cast a permanent spell of each permanent type from your graveyard.
|
||||||
|
addCard(Zone.GRAVEYARD, playerA, "Mox Jet");
|
||||||
|
|
||||||
|
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Mox Jet");
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, grist, 1);
|
||||||
|
assertPermanentCount(playerA, "Mox Jet", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_Play_DryadArbor_FromGraveyard_Trigger() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, grist);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Muldrotha, the Gravetide"); // During each of your turns, you may play a land and cast a permanent spell of each permanent type from your graveyard.
|
||||||
|
addCard(Zone.GRAVEYARD, playerA, "Dryad Arbor");
|
||||||
|
|
||||||
|
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Dryad Arbor");
|
||||||
|
setChoice(playerA, "Land"); // Choose to consume the Land part of Muldrotha, "Creature" would have not worked anyway since Dryad Arbor can not be cast.
|
||||||
|
setChoice(playerA, true); // pay for Grist's trigger
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, gristPW, 1);
|
||||||
|
assertPermanentCount(playerA, "Dryad Arbor", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_PlusOne_NoLibrary() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
removeAllCardsFromLibrary(playerA);
|
||||||
|
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, gristPW);
|
||||||
|
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "+1");
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertGraveyardCount(playerA, 0);
|
||||||
|
assertPermanentCount(playerA, gristPW, 1);
|
||||||
|
assertCounterCount(playerA, gristPW, CounterType.LOYALTY, 3 + 1);
|
||||||
|
assertPermanentCount(playerA, "Insect Token", 1);
|
||||||
|
assertCounterCount(playerA, "Insect Token", CounterType.DEATHTOUCH, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_PlusOne_MillNonBlack() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
skipInitShuffling();
|
||||||
|
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, gristPW);
|
||||||
|
addCard(Zone.LIBRARY, playerA, "Grizzly Bears", 2);
|
||||||
|
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "+1");
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertGraveyardCount(playerA, 2);
|
||||||
|
assertPermanentCount(playerA, gristPW, 1);
|
||||||
|
assertCounterCount(playerA, gristPW, CounterType.LOYALTY, 3 + 1);
|
||||||
|
assertPermanentCount(playerA, "Insect Token", 1);
|
||||||
|
assertCounterCount(playerA, "Insect Token", CounterType.DEATHTOUCH, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_PlusOne_MillBlack() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
skipInitShuffling();
|
||||||
|
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, gristPW);
|
||||||
|
addCard(Zone.LIBRARY, playerA, "Blood Artist", 1);
|
||||||
|
addCard(Zone.LIBRARY, playerA, "Grizzly Bears", 1);
|
||||||
|
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "+1");
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertGraveyardCount(playerA, 2);
|
||||||
|
assertPermanentCount(playerA, gristPW, 1);
|
||||||
|
assertCounterCount(playerA, gristPW, CounterType.LOYALTY, 3 + 1);
|
||||||
|
assertPermanentCount(playerA, "Insect Token", 1);
|
||||||
|
assertCounterCount(playerA, "Insect Token", CounterType.DEATHTOUCH, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_PlusOne_MillBlack_Chatterfang() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
skipInitShuffling();
|
||||||
|
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, gristPW);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Chatterfang, Squirrel General"); // If one or more tokens would be created under your control, those tokens plus that many 1/1 green Squirrel creature tokens are created instead.
|
||||||
|
addCard(Zone.LIBRARY, playerA, "Blood Artist", 1);
|
||||||
|
addCard(Zone.LIBRARY, playerA, "Grizzly Bears", 1);
|
||||||
|
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "+1");
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertGraveyardCount(playerA, 2);
|
||||||
|
assertPermanentCount(playerA, gristPW, 1);
|
||||||
|
assertCounterCount(playerA, gristPW, CounterType.LOYALTY, 3 + 1);
|
||||||
|
assertPermanentCount(playerA, "Insect Token", 1);
|
||||||
|
assertCounterCount(playerA, "Insect Token", CounterType.DEATHTOUCH, 1);
|
||||||
|
assertPermanentCount(playerA, "Squirrel Token", 1);
|
||||||
|
assertCounterCount(playerA, "Squirrel Token", CounterType.DEATHTOUCH, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_Minus6() {
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
skipInitShuffling();
|
||||||
|
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, gristPW);
|
||||||
|
addCard(Zone.GRAVEYARD, playerA, "Dryad Arbor", 1);
|
||||||
|
addCard(Zone.GRAVEYARD, playerA, "Bitterblossom", 1);
|
||||||
|
addCard(Zone.GRAVEYARD, playerA, "Taiga", 1);
|
||||||
|
addCard(Zone.GRAVEYARD, playerA, "Baneslayer Angel", 1);
|
||||||
|
addCard(Zone.GRAVEYARD, playerA, "Keranos, God of Storms", 1);
|
||||||
|
addCard(Zone.GRAVEYARD, playerA, "Grist, the Hunger Tide", 1);
|
||||||
|
|
||||||
|
addCounters(1, PhaseStep.PRECOMBAT_MAIN, playerA, gristPW, CounterType.LOYALTY, 4);
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "-6");
|
||||||
|
|
||||||
|
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertGraveyardCount(playerA, 6); // cards are still there
|
||||||
|
assertPermanentCount(playerA, 1 + 4);
|
||||||
|
assertCounterCount(playerA, gristPW, CounterType.LOYALTY, 1);
|
||||||
|
|
||||||
|
// None of those are creature in graveyard
|
||||||
|
assertPermanentCount(playerA, "Bitterblossom", 0);
|
||||||
|
assertPermanentCount(playerA, "Taiga", 0);
|
||||||
|
|
||||||
|
// All of those are creature in graveyard
|
||||||
|
assertPermanentCount(playerA, "Dryad Arbor", 1);
|
||||||
|
assertPermanentCount(playerA, "Baneslayer Angel", 1);
|
||||||
|
assertPermanentCount(playerA, "Keranos, God of Storms", 1);
|
||||||
|
assertPermanentCount(playerA, "Grist, the Hunger Tide", 1);
|
||||||
|
|
||||||
|
// Dryad Arbor is still a Land Forest, but no longer Dryad
|
||||||
|
assertPowerToughness(playerA, "Dryad Arbor", 1, 1);
|
||||||
|
assertType("Dryad Arbor", CardType.CREATURE, true);
|
||||||
|
assertType("Dryad Arbor", CardType.LAND, true);
|
||||||
|
assertSubtype("Dryad Arbor", SubType.INSECT);
|
||||||
|
assertNotSubtype("Dryad Arbor", SubType.DRYAD);
|
||||||
|
assertSubtype("Dryad Arbor", SubType.FOREST);
|
||||||
|
assertColor(playerA, "Dryad Arbor", "{G}{B}", true);
|
||||||
|
|
||||||
|
// Baneslayer Angel is now a Baneslayer Insect
|
||||||
|
assertPowerToughness(playerA, "Baneslayer Angel", 1, 1);
|
||||||
|
assertType("Baneslayer Angel", CardType.CREATURE, true);
|
||||||
|
assertSubtype("Baneslayer Angel", SubType.INSECT);
|
||||||
|
assertNotSubtype("Baneslayer Angel", SubType.ANGEL);
|
||||||
|
assertColor(playerA, "Baneslayer Angel", "{G}{B}", true);
|
||||||
|
assertColor(playerA, "Baneslayer Angel", ObjectColor.WHITE, false);
|
||||||
|
|
||||||
|
// Keranos token is just an Enchantment
|
||||||
|
assertType("Keranos, God of Storms", CardType.CREATURE, false);
|
||||||
|
assertType("Keranos, God of Storms", CardType.ENCHANTMENT, true);
|
||||||
|
assertNotSubtype("Keranos, God of Storms", SubType.INSECT);
|
||||||
|
assertColor(playerA, "Keranos, God of Storms", "{G}{B}", true);
|
||||||
|
assertColor(playerA, "Baneslayer Angel", "{R}{U}", false);
|
||||||
|
|
||||||
|
// Grist, the Hunger Tide is not a Creature (It would become a 1/1 Insect if animated somehow with an effect preserving its p/t/subtype)
|
||||||
|
assertType("Grist, the Hunger Tide", CardType.CREATURE, false);
|
||||||
|
assertType("Grist, the Hunger Tide", CardType.PLANESWALKER, true);
|
||||||
|
assertNotSubtype("Grist, the Hunger Tide", SubType.INSECT);
|
||||||
|
assertSubtype("Grist, the Hunger Tide", SubType.GRIST);
|
||||||
|
assertColor(playerA, "Grist, the Hunger Tide", "{G}{B}", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue