mirror of
https://github.com/magefree/mage.git
synced 2025-12-20 10:40:06 -08:00
[REX] Implement Ian Malcolm, Chaotician (#12117)
* Start on Ian Malcolm, Chaotician, missing key effects * fox ANY clause in DrawNthCardTriggeredAbility * Get exile effect working * Start using Evelyn, the Covetous code * align exile effect * align player clause * align card type clause * align counter check clause * align mana clause * add ownership clause * remove redundant comments * fix redundant mana clause description * fix counter clause in mana cost effect * fix active clause in mana effect * use MageObjectReference to associate exiled cards with an Ian Malcolm instance * optimize imports * Start tests, failing currently * fix test and add blink test * fix signature of constructor * fix order of super() call in checkTrigger * clarify hash maps in watcher * use correct AsThoughEffect * document header of checkExile * generalize modal and double faced cards for LKI fetch * remove land played event for watcher * Use custom MageIdentifier to filter usedMap
This commit is contained in:
parent
f8f9b0caa0
commit
40143c648f
5 changed files with 398 additions and 1 deletions
282
Mage.Sets/src/mage/cards/i/IanMalcolmChaotician.java
Normal file
282
Mage.Sets/src/mage/cards/i/IanMalcolmChaotician.java
Normal file
|
|
@ -0,0 +1,282 @@
|
||||||
|
package mage.cards.i;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import mage.MageIdentifier;
|
||||||
|
import mage.MageInt;
|
||||||
|
import mage.MageObject;
|
||||||
|
import mage.MageObjectReference;
|
||||||
|
import mage.abilities.Ability;
|
||||||
|
import mage.abilities.common.DrawNthCardTriggeredAbility;
|
||||||
|
import mage.abilities.common.SimpleStaticAbility;
|
||||||
|
import mage.abilities.effects.AsThoughEffectImpl;
|
||||||
|
import mage.abilities.effects.AsThoughManaEffect;
|
||||||
|
import mage.abilities.effects.OneShotEffect;
|
||||||
|
import mage.cards.*;
|
||||||
|
import mage.constants.*;
|
||||||
|
import mage.game.CardState;
|
||||||
|
import mage.game.Game;
|
||||||
|
import mage.game.events.GameEvent;
|
||||||
|
import mage.game.permanent.Permanent;
|
||||||
|
import mage.players.ManaPoolItem;
|
||||||
|
import mage.players.Player;
|
||||||
|
import mage.util.CardUtil;
|
||||||
|
import mage.watchers.Watcher;
|
||||||
|
import mage.target.targetpointer.FixedTarget;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author jimga150
|
||||||
|
*/
|
||||||
|
public final class IanMalcolmChaotician extends CardImpl {
|
||||||
|
|
||||||
|
public IanMalcolmChaotician(UUID ownerId, CardSetInfo setInfo) {
|
||||||
|
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}{R}");
|
||||||
|
|
||||||
|
this.supertype.add(SuperType.LEGENDARY);
|
||||||
|
this.subtype.add(SubType.HUMAN);
|
||||||
|
this.subtype.add(SubType.SCIENTIST);
|
||||||
|
this.power = new MageInt(2);
|
||||||
|
this.toughness = new MageInt(2);
|
||||||
|
|
||||||
|
// Whenever a player draws their second card each turn, that player exiles the top card of their library.
|
||||||
|
this.addAbility(new IanMalcolmChaoticianDrawTriggerAbility(), new IanMalcolmChaoticianWatcher());
|
||||||
|
|
||||||
|
// During each player's turn, that player may cast a spell from among the cards they don't own exiled with
|
||||||
|
// Ian Malcolm, Chaotician, and mana of any type can be spent to cast it.
|
||||||
|
Ability ability = new SimpleStaticAbility(new IanMalcolmChaoticianCastEffect())
|
||||||
|
.setIdentifier(MageIdentifier.IanMalcolmChaoticianWatcher);
|
||||||
|
ability.addEffect(new IanMalcolmChaoticianManaEffect());
|
||||||
|
this.addAbility(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IanMalcolmChaotician(final IanMalcolmChaotician card) {
|
||||||
|
super(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IanMalcolmChaotician copy() {
|
||||||
|
return new IanMalcolmChaotician(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class IanMalcolmChaoticianDrawTriggerAbility extends DrawNthCardTriggeredAbility {
|
||||||
|
|
||||||
|
IanMalcolmChaoticianDrawTriggerAbility() {
|
||||||
|
super(new IanMalcolmChaoticianExileEffect(), false, TargetController.ANY, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IanMalcolmChaoticianDrawTriggerAbility(final IanMalcolmChaoticianDrawTriggerAbility ability) {
|
||||||
|
super(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean checkTrigger(GameEvent event, Game game) {
|
||||||
|
if (super.checkTrigger(event, game)){
|
||||||
|
getEffects().setTargetPointer(new FixedTarget(event.getPlayerId()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IanMalcolmChaoticianDrawTriggerAbility copy() {
|
||||||
|
return new IanMalcolmChaoticianDrawTriggerAbility(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class IanMalcolmChaoticianExileEffect extends OneShotEffect {
|
||||||
|
|
||||||
|
IanMalcolmChaoticianExileEffect() {
|
||||||
|
super(Outcome.Exile);
|
||||||
|
staticText = "that player exiles the top card of their library";
|
||||||
|
}
|
||||||
|
|
||||||
|
private IanMalcolmChaoticianExileEffect(final IanMalcolmChaoticianExileEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IanMalcolmChaoticianExileEffect copy() {
|
||||||
|
return new IanMalcolmChaoticianExileEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
UUID targetPlayerID = getTargetPointer().getFirst(game, source);
|
||||||
|
Player targetPlayer = game.getPlayer(targetPlayerID);
|
||||||
|
MageObject sourceObject = source.getSourceObject(game);
|
||||||
|
if (targetPlayer == null || sourceObject == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Card card = targetPlayer.getLibrary().getFromTop(game);
|
||||||
|
if (card == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
UUID exileZoneId = CardUtil.getExileZoneId(game, sourceObject.getId(), sourceObject.getZoneChangeCounter(game));
|
||||||
|
targetPlayer.moveCardsToExile(card, source, game, true, exileZoneId, sourceObject.getIdName());
|
||||||
|
MageObjectReference sourceMOR = new MageObjectReference(source.getSourceId(), game);
|
||||||
|
IanMalcolmChaoticianWatcher.addCard(sourceMOR, card, game);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class IanMalcolmChaoticianCastEffect extends AsThoughEffectImpl {
|
||||||
|
|
||||||
|
IanMalcolmChaoticianCastEffect() {
|
||||||
|
super(AsThoughEffectType.CAST_FROM_NOT_OWN_HAND_ZONE, Duration.WhileOnBattlefield, Outcome.PlayForFree);
|
||||||
|
staticText = "During each player's turn, that player may cast a spell from among the cards they don't own " +
|
||||||
|
"exiled with {this}";
|
||||||
|
}
|
||||||
|
|
||||||
|
private IanMalcolmChaoticianCastEffect(final IanMalcolmChaoticianCastEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IanMalcolmChaoticianCastEffect copy() {
|
||||||
|
return new IanMalcolmChaoticianCastEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
|
||||||
|
if (!game.isActivePlayer(affectedControllerId) || IanMalcolmChaoticianWatcher.checkUsed(source, game)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Card card = game.getCard(CardUtil.getMainCardId(game, sourceId));
|
||||||
|
if (card == null || card.isLand(game)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
MageObjectReference sourceMOR = new MageObjectReference(source.getSourceId(), game);
|
||||||
|
return !card.getOwnerId().equals(affectedControllerId)
|
||||||
|
&& IanMalcolmChaoticianWatcher.checkExile(sourceMOR, card, game, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class IanMalcolmChaoticianManaEffect extends AsThoughEffectImpl implements AsThoughManaEffect {
|
||||||
|
|
||||||
|
IanMalcolmChaoticianManaEffect() {
|
||||||
|
super(AsThoughEffectType.SPEND_OTHER_MANA, Duration.WhileOnBattlefield, Outcome.Benefit);
|
||||||
|
staticText = ", and mana of any type can be spent to cast it";
|
||||||
|
}
|
||||||
|
|
||||||
|
private IanMalcolmChaoticianManaEffect(final IanMalcolmChaoticianManaEffect effect) {
|
||||||
|
super(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Game game, Ability source) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IanMalcolmChaoticianManaEffect copy() {
|
||||||
|
return new IanMalcolmChaoticianManaEffect(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean applies(UUID sourceId, Ability source, UUID affectedControllerId, Game game) {
|
||||||
|
if (!game.isActivePlayer(affectedControllerId) || IanMalcolmChaoticianWatcher.checkUsed(source, game)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
MageObjectReference sourceMOR = new MageObjectReference(source.getSourceId(), game);
|
||||||
|
Card card = game.getCard(CardUtil.getMainCardId(game, sourceId));
|
||||||
|
if (card == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (game.getState().getZone(card.getId()) == Zone.EXILED) {
|
||||||
|
return IanMalcolmChaoticianWatcher.checkExile(sourceMOR, card, game, 0);
|
||||||
|
}
|
||||||
|
// not exiled, must be on the stack--get LKI
|
||||||
|
CardState cardState = game.getLastKnownInformationCard(card.getMainCard().getId(), Zone.EXILED);;
|
||||||
|
return cardState != null && IanMalcolmChaoticianWatcher.checkExile(sourceMOR, card, game, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ManaType getAsThoughManaType(ManaType manaType, ManaPoolItem mana, UUID affectedControllerId, Ability source, Game game) {
|
||||||
|
return mana.getFirstAvailable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class IanMalcolmChaoticianWatcher extends Watcher {
|
||||||
|
|
||||||
|
// Maps MOR representing the specific instance of Ian Malcolm (changes when it changes zones, i.e. blinked)
|
||||||
|
// to many exiled cards exiled with Ian Malcolm
|
||||||
|
private final Map<MageObjectReference, Set<MageObjectReference>> exiledMap = new HashMap<>();
|
||||||
|
|
||||||
|
// Maps instances of approving MORs (some of which might be instances of Ian Malcolm, if his ability was used to
|
||||||
|
// cast that spell) to UUIDs of players that have used that approving object this turn
|
||||||
|
private final Map<MageObjectReference, Set<UUID>> usedMap = new HashMap<>();
|
||||||
|
|
||||||
|
IanMalcolmChaoticianWatcher() {
|
||||||
|
super(WatcherScope.GAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void watch(GameEvent event, Game game) {
|
||||||
|
if (event.getType() == GameEvent.EventType.SPELL_CAST &&
|
||||||
|
event.hasApprovingIdentifier(MageIdentifier.IanMalcolmChaoticianWatcher)) {
|
||||||
|
usedMap.computeIfAbsent(
|
||||||
|
event.getAdditionalReference()
|
||||||
|
.getApprovingMageObjectReference(),
|
||||||
|
x -> new HashSet<>()
|
||||||
|
).add(event.getPlayerId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reset() {
|
||||||
|
super.reset();
|
||||||
|
usedMap.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void addCard(MageObjectReference sourceObj, Card card, Game game) {
|
||||||
|
Set<MageObjectReference> set = game
|
||||||
|
.getState()
|
||||||
|
.getWatcher(IanMalcolmChaoticianWatcher.class)
|
||||||
|
.exiledMap
|
||||||
|
.computeIfAbsent(sourceObj, x -> new HashSet<>());
|
||||||
|
MageObjectReference mor = new MageObjectReference(card, game);
|
||||||
|
set.add(mor);
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean checkUsed(Ability source, Game game) {
|
||||||
|
Permanent sourceObject = game.getPermanent(source.getSourceId());
|
||||||
|
if (sourceObject == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return game
|
||||||
|
.getState()
|
||||||
|
.getWatcher(IanMalcolmChaoticianWatcher.class)
|
||||||
|
.usedMap
|
||||||
|
.getOrDefault(
|
||||||
|
new MageObjectReference(sourceObject, game),
|
||||||
|
Collections.emptySet()
|
||||||
|
).contains(source.getControllerId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if card was added to the tracked exiled cards under sourceObj
|
||||||
|
*
|
||||||
|
* @param sourceObj exiling card
|
||||||
|
* @param card exiled card to check
|
||||||
|
* @param game
|
||||||
|
* @param offset zone change counter offset: 0 = in exile, 1 = on the stack waiting to be cast
|
||||||
|
*/
|
||||||
|
static boolean checkExile(MageObjectReference sourceObj, Card card, Game game, int offset) {
|
||||||
|
return game
|
||||||
|
.getState()
|
||||||
|
.getWatcher(IanMalcolmChaoticianWatcher.class)
|
||||||
|
.exiledMap
|
||||||
|
.getOrDefault(sourceObj, Collections.emptySet())
|
||||||
|
.stream()
|
||||||
|
.anyMatch(mor -> mor.refersTo(card, game, offset));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -33,6 +33,7 @@ public final class JurassicWorldCollection extends ExpansionSet {
|
||||||
cards.add(new SetCardInfo("Grim Giganotosaurus", 11, Rarity.RARE, mage.cards.g.GrimGiganotosaurus.class));
|
cards.add(new SetCardInfo("Grim Giganotosaurus", 11, Rarity.RARE, mage.cards.g.GrimGiganotosaurus.class));
|
||||||
cards.add(new SetCardInfo("Henry Wu, InGen Geneticist", 12, Rarity.RARE, mage.cards.h.HenryWuInGenGeneticist.class));
|
cards.add(new SetCardInfo("Henry Wu, InGen Geneticist", 12, Rarity.RARE, mage.cards.h.HenryWuInGenGeneticist.class));
|
||||||
cards.add(new SetCardInfo("Hunting Velociraptor", 4, Rarity.RARE, mage.cards.h.HuntingVelociraptor.class));
|
cards.add(new SetCardInfo("Hunting Velociraptor", 4, Rarity.RARE, mage.cards.h.HuntingVelociraptor.class));
|
||||||
|
cards.add(new SetCardInfo("Ian Malcolm, Chaotician", 13, Rarity.RARE, mage.cards.i.IanMalcolmChaotician.class));
|
||||||
cards.add(new SetCardInfo("Indoraptor, the Perfect Hybrid", 15, Rarity.RARE, mage.cards.i.IndoraptorThePerfectHybrid.class));
|
cards.add(new SetCardInfo("Indoraptor, the Perfect Hybrid", 15, Rarity.RARE, mage.cards.i.IndoraptorThePerfectHybrid.class));
|
||||||
cards.add(new SetCardInfo("Island", 22, Rarity.LAND, mage.cards.basiclands.Island.class, FULL_ART_BFZ_VARIOUS));
|
cards.add(new SetCardInfo("Island", 22, Rarity.LAND, mage.cards.basiclands.Island.class, FULL_ART_BFZ_VARIOUS));
|
||||||
cards.add(new SetCardInfo("Island", "22b", Rarity.LAND, mage.cards.basiclands.Island.class, FULL_ART_BFZ_VARIOUS));
|
cards.add(new SetCardInfo("Island", "22b", Rarity.LAND, mage.cards.basiclands.Island.class, FULL_ART_BFZ_VARIOUS));
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,108 @@
|
||||||
|
package org.mage.test.cards.watchers;
|
||||||
|
|
||||||
|
import mage.constants.PhaseStep;
|
||||||
|
import mage.constants.Zone;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.mage.test.serverside.base.CardTestCommander4Players;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author jimga150
|
||||||
|
*/
|
||||||
|
public class IanMalcolmChaoticianTests extends CardTestCommander4Players {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testManaCostsandWatcher() {
|
||||||
|
|
||||||
|
skipInitShuffling();
|
||||||
|
|
||||||
|
// Whenever a player draws their second card each turn, that player exiles the top card of their library.
|
||||||
|
// During each player's turn, that player may cast a spell from among the cards they don't own exiled with
|
||||||
|
// Ian Malcolm, Chaotician, and mana of any type can be spent to cast it.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Ian Malcolm, Chaotician");
|
||||||
|
|
||||||
|
// Flying
|
||||||
|
// At the beginning of your draw step, draw an additional card.
|
||||||
|
// At the beginning of your end step, discard your hand.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Avaricious Dragon");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Avaricious Dragon");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerC, "Avaricious Dragon");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerD, "Avaricious Dragon");
|
||||||
|
|
||||||
|
addCard(Zone.LIBRARY, playerA, "Horde of Notions", 3);
|
||||||
|
addCard(Zone.LIBRARY, playerB, "Fusion Elemental", 10);
|
||||||
|
addCard(Zone.LIBRARY, playerC, "Chromanticore", 10);
|
||||||
|
addCard(Zone.LIBRARY, playerD, "Garth One-Eye", 10);
|
||||||
|
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Plains", 15);
|
||||||
|
|
||||||
|
// Should be able to cast all cards exiled from other players' decks
|
||||||
|
checkPlayableAbility("Can't cast card exiled with this Ian Malcolm", 5, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Fusion Elemental", true);
|
||||||
|
checkPlayableAbility("Can't cast card exiled with this Ian Malcolm", 5, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Chromanticore", true);
|
||||||
|
checkPlayableAbility("Can't cast card exiled with this Ian Malcolm", 5, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Garth One-Eye", true);
|
||||||
|
|
||||||
|
// Should NOT be able to cast own card exiled in same way
|
||||||
|
checkPlayableAbility("Able to cast Horde of Notions, but should not be.", 5, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Horde of Notions", false);
|
||||||
|
|
||||||
|
// Cast a card exiled with Ian Malcolm, preventing any future casts from this zone on this turn.
|
||||||
|
castSpell(5, PhaseStep.PRECOMBAT_MAIN, playerA, "Fusion Elemental", true);
|
||||||
|
|
||||||
|
checkPlayableAbility("Able to cast Chromanticore, but should not be due to watcher.", 5, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Chromanticore", false);
|
||||||
|
checkPlayableAbility("Able to cast Garth One-Eye, but should not be due to watcher.", 5, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Garth One-Eye", false);
|
||||||
|
|
||||||
|
setStopAt(5, PhaseStep.END_TURN);
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBlink() {
|
||||||
|
|
||||||
|
skipInitShuffling();
|
||||||
|
|
||||||
|
// Whenever a player draws their second card each turn, that player exiles the top card of their library.
|
||||||
|
// During each player's turn, that player may cast a spell from among the cards they don't own exiled with
|
||||||
|
// Ian Malcolm, Chaotician, and mana of any type can be spent to cast it.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Ian Malcolm, Chaotician");
|
||||||
|
|
||||||
|
// Flying
|
||||||
|
// At the beginning of your draw step, draw an additional card.
|
||||||
|
// At the beginning of your end step, discard your hand.
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Heightened Awareness");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerB, "Heightened Awareness");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerC, "Heightened Awareness");
|
||||||
|
addCard(Zone.BATTLEFIELD, playerD, "Heightened Awareness");
|
||||||
|
|
||||||
|
addCard(Zone.LIBRARY, playerA, "Horde of Notions", 3);
|
||||||
|
addCard(Zone.LIBRARY, playerA, "Ephemerate", 1);
|
||||||
|
addCard(Zone.LIBRARY, playerB, "Fusion Elemental", 10);
|
||||||
|
addCard(Zone.LIBRARY, playerC, "Chromanticore", 10);
|
||||||
|
addCard(Zone.LIBRARY, playerD, "Garth One-Eye", 10);
|
||||||
|
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Plains", 15);
|
||||||
|
|
||||||
|
// Should be able to cast all cards exiled from other players' decks
|
||||||
|
checkPlayableAbility("Can't cast card exiled with this Ian Malcolm", 5, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Fusion Elemental", true);
|
||||||
|
checkPlayableAbility("Can't cast card exiled with this Ian Malcolm", 5, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Chromanticore", true);
|
||||||
|
checkPlayableAbility("Can't cast card exiled with this Ian Malcolm", 5, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Garth One-Eye", true);
|
||||||
|
|
||||||
|
// Should NOT be able to cast own card exiled in same way
|
||||||
|
checkPlayableAbility("Able to cast Horde of Notions, but should not be.", 5, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Horde of Notions", false);
|
||||||
|
|
||||||
|
// Blink Ian Malcolm, causing all cards in his current exile zone to become uncastable
|
||||||
|
castSpell(5, PhaseStep.PRECOMBAT_MAIN, playerA, "Ephemerate", true);
|
||||||
|
addTarget(playerA, "Ian Malcolm, Chaotician");
|
||||||
|
|
||||||
|
// Should no longer be able to cast all cards exiled from other players' decks
|
||||||
|
checkPlayableAbility("Can't cast card exiled with this Ian Malcolm", 5, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Fusion Elemental", false);
|
||||||
|
checkPlayableAbility("Can't cast card exiled with this Ian Malcolm", 5, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Chromanticore", false);
|
||||||
|
checkPlayableAbility("Can't cast card exiled with this Ian Malcolm", 5, PhaseStep.PRECOMBAT_MAIN, playerA, "Cast Garth One-Eye", false);
|
||||||
|
|
||||||
|
setStopAt(5, PhaseStep.END_TURN);
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -24,6 +24,7 @@ public enum MageIdentifier {
|
||||||
HaukensInsightWatcher,
|
HaukensInsightWatcher,
|
||||||
IntrepidPaleontologistWatcher,
|
IntrepidPaleontologistWatcher,
|
||||||
KessDissidentMageWatcher,
|
KessDissidentMageWatcher,
|
||||||
|
IanMalcolmChaoticianWatcher,
|
||||||
MuldrothaTheGravetideWatcher,
|
MuldrothaTheGravetideWatcher,
|
||||||
ShareTheSpoilsWatcher,
|
ShareTheSpoilsWatcher,
|
||||||
WishWatcher,
|
WishWatcher,
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ public class DrawNthCardTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
setTriggerPhrase(generateTriggerPhrase());
|
setTriggerPhrase(generateTriggerPhrase());
|
||||||
}
|
}
|
||||||
|
|
||||||
private DrawNthCardTriggeredAbility(final DrawNthCardTriggeredAbility ability) {
|
protected DrawNthCardTriggeredAbility(final DrawNthCardTriggeredAbility ability) {
|
||||||
super(ability);
|
super(ability);
|
||||||
this.targetController = ability.targetController;
|
this.targetController = ability.targetController;
|
||||||
this.cardNumber = ability.cardNumber;
|
this.cardNumber = ability.cardNumber;
|
||||||
|
|
@ -72,6 +72,9 @@ public class DrawNthCardTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ANY:
|
||||||
|
// Doesn't matter who
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("TargetController " + targetController + " not supported");
|
throw new IllegalArgumentException("TargetController " + targetController + " not supported");
|
||||||
}
|
}
|
||||||
|
|
@ -87,6 +90,8 @@ public class DrawNthCardTriggeredAbility extends TriggeredAbilityImpl {
|
||||||
return "Whenever a player draws their " + CardUtil.numberToOrdinalText(cardNumber) + " card during their turn, ";
|
return "Whenever a player draws their " + CardUtil.numberToOrdinalText(cardNumber) + " card during their turn, ";
|
||||||
case OPPONENT:
|
case OPPONENT:
|
||||||
return "Whenever an opponent draws their " + CardUtil.numberToOrdinalText(cardNumber) + " card each turn, ";
|
return "Whenever an opponent draws their " + CardUtil.numberToOrdinalText(cardNumber) + " card each turn, ";
|
||||||
|
case ANY:
|
||||||
|
return "Whenever a player draws their " + CardUtil.numberToOrdinalText(cardNumber) + " card each turn, ";
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("TargetController " + targetController + " not supported");
|
throw new IllegalArgumentException("TargetController " + targetController + " not supported");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue