mirror of
https://github.com/magefree/mage.git
synced 2025-12-20 10:40:06 -08:00
cleanup The Tomb of Aclazotz without breaking it (#11648)
* add test for Tarrian's Journal // The Tomb of Aclazotz * re-apply cleanup without breaking this time
This commit is contained in:
parent
ac53e5b518
commit
f0043ee9d9
2 changed files with 73 additions and 45 deletions
|
|
@ -1,9 +1,5 @@
|
||||||
package mage.cards.t;
|
package mage.cards.t;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
import mage.MageIdentifier;
|
import mage.MageIdentifier;
|
||||||
import mage.MageObject;
|
import mage.MageObject;
|
||||||
import mage.MageObjectReference;
|
import mage.MageObjectReference;
|
||||||
|
|
@ -19,16 +15,7 @@ import mage.abilities.mana.BlackManaAbility;
|
||||||
import mage.cards.Card;
|
import mage.cards.Card;
|
||||||
import mage.cards.CardImpl;
|
import mage.cards.CardImpl;
|
||||||
import mage.cards.CardSetInfo;
|
import mage.cards.CardSetInfo;
|
||||||
import mage.constants.AsThoughEffectType;
|
import mage.constants.*;
|
||||||
import mage.constants.CardType;
|
|
||||||
import mage.constants.Duration;
|
|
||||||
import mage.constants.Layer;
|
|
||||||
import mage.constants.Outcome;
|
|
||||||
import mage.constants.SubLayer;
|
|
||||||
import mage.constants.SubType;
|
|
||||||
import mage.constants.SuperType;
|
|
||||||
import mage.constants.WatcherScope;
|
|
||||||
import mage.constants.Zone;
|
|
||||||
import mage.counters.CounterType;
|
import mage.counters.CounterType;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.game.events.GameEvent;
|
import mage.game.events.GameEvent;
|
||||||
|
|
@ -39,6 +26,10 @@ import mage.util.CardUtil;
|
||||||
import mage.util.SubTypes;
|
import mage.util.SubTypes;
|
||||||
import mage.watchers.Watcher;
|
import mage.watchers.Watcher;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author jeffwadsworth
|
* @author jeffwadsworth
|
||||||
|
|
@ -78,7 +69,7 @@ class TheTombOfAclazotzEffect extends AsThoughEffectImpl {
|
||||||
|
|
||||||
TheTombOfAclazotzEffect() {
|
TheTombOfAclazotzEffect() {
|
||||||
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit);
|
super(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, Duration.EndOfTurn, Outcome.Benefit);
|
||||||
staticText = "You may cast a creature spell from your graveyard this turn. If you do, it enters the battlefield with a finality counter on it and is a Vampire in addition to its other types. (If a creature with a finality counter on it would die, exile it instead.)";
|
staticText = "You may cast a creature spell from your graveyard this turn. If you do, it enters the battlefield with a finality counter on it and is a Vampire in addition to its other types. <i>(If a creature with a finality counter on it would die, exile it instead.)</i>";
|
||||||
}
|
}
|
||||||
|
|
||||||
private TheTombOfAclazotzEffect(final TheTombOfAclazotzEffect effect) {
|
private TheTombOfAclazotzEffect(final TheTombOfAclazotzEffect effect) {
|
||||||
|
|
@ -119,20 +110,16 @@ class TheTombOfAclazotzEffect extends AsThoughEffectImpl {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Card card = game.getCard(objectId);
|
Card card = game.getCard(objectId);
|
||||||
if (card != null
|
return card != null
|
||||||
&& affectedAbility instanceof SpellAbility
|
&& affectedAbility instanceof SpellAbility
|
||||||
&& card.getOwnerId().equals(playerId)
|
&& card.getOwnerId().equals(playerId)
|
||||||
&& card.isCreature(game)) {
|
&& card.isCreature(game);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TheTombOfAclazotzWatcher extends Watcher {
|
class TheTombOfAclazotzWatcher extends Watcher {
|
||||||
|
|
||||||
private final Map<MageObjectReference, Map<UUID, Integer>> morMap = new HashMap<>();
|
private final Map<MageObjectReference, Map<UUID, Integer>> morMap = new HashMap<>();
|
||||||
private MageObjectReference mor;
|
|
||||||
private UUID playFromAnywhereEffectId;
|
private UUID playFromAnywhereEffectId;
|
||||||
|
|
||||||
TheTombOfAclazotzWatcher() {
|
TheTombOfAclazotzWatcher() {
|
||||||
|
|
@ -146,19 +133,16 @@ class TheTombOfAclazotzWatcher extends Watcher {
|
||||||
Spell target = game.getSpell(event.getTargetId());
|
Spell target = game.getSpell(event.getTargetId());
|
||||||
Card card = target.getCard();
|
Card card = target.getCard();
|
||||||
if (card != null) {
|
if (card != null) {
|
||||||
mor = new MageObjectReference(card.getId(), card.getZoneChangeCounter(game), game);
|
game.getState().addEffect(new AddCounterEnteringCreatureEffect(new MageObjectReference(target.getCard(), game),
|
||||||
if (mor != null) {
|
CounterType.FINALITY.createInstance(), Outcome.Neutral),
|
||||||
game.getState().addEffect(new AddCounterEnteringCreatureEffect(new MageObjectReference(target.getCard(), game),
|
target.getSpellAbility());
|
||||||
CounterType.FINALITY.createInstance(), Outcome.Neutral),
|
game.getState().addEffect(new AddSubtypeEnteringCreatureEffect(new MageObjectReference(target.getCard(), game), SubType.VAMPIRE, Outcome.Benefit), card.getSpellAbility());
|
||||||
target.getSpellAbility());
|
// Rule 728.2 we must insure the effect is used (creature is cast successfully) before discarding the play effect
|
||||||
game.getState().addEffect(new AddSubtypeEnteringCreatureEffect(new MageObjectReference(target.getCard(), game), SubType.VAMPIRE, Outcome.Benefit), card.getSpellAbility());
|
UUID playEffectId = this.getPlayFromAnywhereEffect();
|
||||||
// Rule 728.2 we must insure the effect is used (creature is cast successfully) before discarding the play effect
|
if (playEffectId != null
|
||||||
UUID playEffectId = this.getPlayFromAnywhereEffect();
|
&& game.getContinuousEffects().getApplicableAsThoughEffects(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, game).listIterator().next().getId().equals(playEffectId)) {
|
||||||
if (playEffectId != null
|
// discard the play effect
|
||||||
&& game.getContinuousEffects().getApplicableAsThoughEffects(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, game).listIterator().next().getId().equals(playEffectId)) {
|
game.getContinuousEffects().getApplicableAsThoughEffects(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, game).listIterator().next().discard();
|
||||||
// discard the play effect
|
|
||||||
game.getContinuousEffects().getApplicableAsThoughEffects(AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, game).listIterator().next().discard();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -203,7 +187,7 @@ class AddSubtypeEnteringCreatureEffect extends ReplacementEffectImpl {
|
||||||
private final MageObjectReference mor;
|
private final MageObjectReference mor;
|
||||||
private final SubType subType;
|
private final SubType subType;
|
||||||
|
|
||||||
public AddSubtypeEnteringCreatureEffect(MageObjectReference mor, SubType subType, Outcome outcome) {
|
AddSubtypeEnteringCreatureEffect(MageObjectReference mor, SubType subType, Outcome outcome) {
|
||||||
super(Duration.WhileOnBattlefield, outcome);
|
super(Duration.WhileOnBattlefield, outcome);
|
||||||
this.mor = mor;
|
this.mor = mor;
|
||||||
this.subType = subType;
|
this.subType = subType;
|
||||||
|
|
@ -223,11 +207,7 @@ class AddSubtypeEnteringCreatureEffect extends ReplacementEffectImpl {
|
||||||
@Override
|
@Override
|
||||||
public boolean applies(GameEvent event, Ability source, Game game) {
|
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||||
MageObject spell = game.getObject(event.getSourceId());
|
MageObject spell = game.getObject(event.getSourceId());
|
||||||
if (spell != null
|
return spell != null && mor.refersTo(spell, game);
|
||||||
&& mor.refersTo(spell, game)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -237,7 +217,6 @@ class AddSubtypeEnteringCreatureEffect extends ReplacementEffectImpl {
|
||||||
AddCardSubTypeEnteringTargetEffect effect = new AddCardSubTypeEnteringTargetEffect(mor, subType, Duration.WhileOnBattlefield);
|
AddCardSubTypeEnteringTargetEffect effect = new AddCardSubTypeEnteringTargetEffect(mor, subType, Duration.WhileOnBattlefield);
|
||||||
effect.setTargetPointer(new FixedTarget(target, game));
|
effect.setTargetPointer(new FixedTarget(target, game));
|
||||||
game.addEffect(effect, source);
|
game.addEffect(effect, source);
|
||||||
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -251,10 +230,10 @@ class AddSubtypeEnteringCreatureEffect extends ReplacementEffectImpl {
|
||||||
class AddCardSubTypeEnteringTargetEffect extends ContinuousEffectImpl {
|
class AddCardSubTypeEnteringTargetEffect extends ContinuousEffectImpl {
|
||||||
|
|
||||||
private final SubType addedSubType;
|
private final SubType addedSubType;
|
||||||
private MageObjectReference mor;
|
private final MageObjectReference mor;
|
||||||
private Card card;
|
private Card card;
|
||||||
|
|
||||||
public AddCardSubTypeEnteringTargetEffect(MageObjectReference mor, SubType addedSubType, Duration duration) {
|
AddCardSubTypeEnteringTargetEffect(MageObjectReference mor, SubType addedSubType, Duration duration) {
|
||||||
super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit);
|
super(duration, Layer.TypeChangingEffects_4, SubLayer.NA, Outcome.Benefit);
|
||||||
this.addedSubType = addedSubType;
|
this.addedSubType = addedSubType;
|
||||||
this.mor = mor;
|
this.mor = mor;
|
||||||
|
|
@ -264,6 +243,7 @@ class AddCardSubTypeEnteringTargetEffect extends ContinuousEffectImpl {
|
||||||
super(effect);
|
super(effect);
|
||||||
this.addedSubType = effect.addedSubType;
|
this.addedSubType = effect.addedSubType;
|
||||||
this.mor = effect.mor;
|
this.mor = effect.mor;
|
||||||
|
this.card = effect.card;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -273,8 +253,7 @@ class AddCardSubTypeEnteringTargetEffect extends ContinuousEffectImpl {
|
||||||
if (spell != null) {
|
if (spell != null) {
|
||||||
card = spell.getCard();
|
card = spell.getCard();
|
||||||
}
|
}
|
||||||
for (Iterator<StackObject> iterator = game.getStack().iterator(); iterator.hasNext();) {
|
for (StackObject stackObject : game.getStack()) {
|
||||||
StackObject stackObject = iterator.next();
|
|
||||||
if (stackObject instanceof Spell
|
if (stackObject instanceof Spell
|
||||||
&& target != null
|
&& target != null
|
||||||
&& target.equals(stackObject)
|
&& target.equals(stackObject)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
package org.mage.test.cards.single.lci;
|
||||||
|
|
||||||
|
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 xenohedron
|
||||||
|
*/
|
||||||
|
public class TarriansJournalTest extends CardTestPlayerBase {
|
||||||
|
|
||||||
|
private static final String tj = "Tarrian's Journal";
|
||||||
|
private static final String transformAbility = "{2}, {T}, Discard your hand: Transform";
|
||||||
|
private static final String mayCastAbility = "{T}: You may cast a creature spell from your graveyard this turn. ";
|
||||||
|
// If you do, it enters the battlefield with a finality counter on it and is a Vampire in addition to its other types.
|
||||||
|
private static final String edgarMarkov = "Edgar Markov";
|
||||||
|
// Whenever you cast another Vampire spell, if Edgar Markov is in the command zone or on the battlefield, create a 1/1 black Vampire creature token.
|
||||||
|
private static final String kraken = "Kraken Hatchling"; // not a vampire
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFunctionality() {
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, tj);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, edgarMarkov);
|
||||||
|
addCard(Zone.BATTLEFIELD, playerA, "Island", 3);
|
||||||
|
addCard(Zone.HAND, playerA, kraken);
|
||||||
|
|
||||||
|
activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, transformAbility);
|
||||||
|
|
||||||
|
checkHandCount("Hand discarded", 1, PhaseStep.BEGIN_COMBAT, playerA, 0);
|
||||||
|
checkGraveyardCount("Kraken discarded", 1, PhaseStep.BEGIN_COMBAT, playerA, kraken, 1);
|
||||||
|
checkPermanentCount("transformed", 1, PhaseStep.BEGIN_COMBAT, playerA, "The Tomb of Aclazotz", 1);
|
||||||
|
|
||||||
|
activateAbility(3, PhaseStep.PRECOMBAT_MAIN, playerA, mayCastAbility);
|
||||||
|
|
||||||
|
castSpell(3, PhaseStep.POSTCOMBAT_MAIN, playerA, kraken);
|
||||||
|
|
||||||
|
setStrictChooseMode(true);
|
||||||
|
setStopAt(3, PhaseStep.END_TURN);
|
||||||
|
execute();
|
||||||
|
|
||||||
|
assertPermanentCount(playerA, kraken, 1);
|
||||||
|
assertPermanentCount(playerA, "Vampire Token", 1);
|
||||||
|
assertSubtype(kraken, SubType.VAMPIRE);
|
||||||
|
assertCounterCount(kraken, CounterType.FINALITY, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue