mirror of
https://github.com/magefree/mage.git
synced 2025-12-30 07:22:03 -08:00
Ability refactor: fixed broken effects timestamp in some use cases
This commit is contained in:
parent
f3f1c29926
commit
d63a3e88ce
6 changed files with 213 additions and 42 deletions
|
|
@ -0,0 +1,70 @@
|
|||
package org.mage.test.cards.abilities.other;
|
||||
|
||||
import mage.abilities.effects.common.DrawCardSourceControllerEffect;
|
||||
import mage.abilities.keyword.VigilanceAbility;
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import mage.game.permanent.Permanent;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class GainAbilitiesTest extends CardTestPlayerBase {
|
||||
|
||||
@Test
|
||||
public void test_AttachmentSingleton() {
|
||||
// {2}{W}
|
||||
// Enchanted creature gets +2/+2.
|
||||
// Enchanted creature has vigilance as long as you control a black or green permanent.
|
||||
addCard(Zone.HAND, playerA, "Abzan Runemark@attach", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 6);
|
||||
//
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears@bear", 1); // 2/2
|
||||
|
||||
// attach all
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "@attach.1", "@bear");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "@attach.2", "@bear");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
checkAbility("after", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "@bear", VigilanceAbility.class, true);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
Permanent permanent = getPermanent("Balduvian Bears");
|
||||
Assert.assertEquals("must have only 1 singleton ability instance from two attachments",
|
||||
1, permanent.getAbilities(currentGame).stream().filter(a -> a instanceof VigilanceAbility).count());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_AttachmentUnique() {
|
||||
// {R}
|
||||
// Enchanted creature has "{R}, {T}, Discard a card: Draw a card."
|
||||
addCard(Zone.HAND, playerA, "Epiphany Storm@attach", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 2);
|
||||
//
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears@bear", 1); // 2/2
|
||||
|
||||
// attach all
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "@attach.1", "@bear");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "@attach.2", "@bear");
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
//checkAbility("after", 1, PhaseStep.PRECOMBAT_MAIN, playerA, "@bear", VigilanceAbility.class, true);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
Permanent permanent = getPermanent("Balduvian Bears");
|
||||
Assert.assertEquals("must have 2 dynamic ability instances from two attachments",
|
||||
2, permanent.getAbilities(currentGame).stream().filter(
|
||||
a -> a.getEffects().stream().anyMatch(e -> e instanceof DrawCardSourceControllerEffect)
|
||||
).count());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -14,20 +14,17 @@ import org.junit.Test;
|
|||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class LandTypeChangingEffectsTest extends CardTestPlayerBase {
|
||||
|
||||
/**
|
||||
*
|
||||
* Playing a commander game. Opponent had a Magus of the Moon, and I later
|
||||
* dropped a Chromatic Lantern.
|
||||
*
|
||||
* <p>
|
||||
* I was not allowed to use the Chromatic Lantern's ability. Since layers
|
||||
* are tricky I asked on the Judge's chat to confirm and the user "luma"
|
||||
* said it should work on this scenario.
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testMagusOfTheMoonAndChromaticLantern() {
|
||||
|
|
@ -42,8 +39,10 @@ public class LandTypeChangingEffectsTest extends CardTestPlayerBase {
|
|||
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Chromatic Lantern");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(2, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPermanentCount(playerB, "Chromatic Lantern", 1);
|
||||
|
||||
|
|
@ -66,8 +65,11 @@ public class LandTypeChangingEffectsTest extends CardTestPlayerBase {
|
|||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Chromatic Lantern");
|
||||
|
||||
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, "Magus of the Moon");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(3, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPermanentCount(playerB, "Chromatic Lantern", 1);
|
||||
assertPermanentCount(playerA, "Magus of the Moon", 1);
|
||||
|
|
@ -97,8 +99,11 @@ public class LandTypeChangingEffectsTest extends CardTestPlayerBase {
|
|||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Aquitect's Will", "Forbidding Watchtower");
|
||||
|
||||
activateAbility(2, PhaseStep.PRECOMBAT_MAIN, playerB, "{1}{W}:");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(2, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertGraveyardCount(playerA, "Aquitect's Will", 1);
|
||||
|
||||
|
|
@ -128,8 +133,10 @@ public class LandTypeChangingEffectsTest extends CardTestPlayerBase {
|
|||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, bloodmoon);
|
||||
playLand(1, PhaseStep.POSTCOMBAT_MAIN, playerA, urborgtoy);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(2, PhaseStep.PRECOMBAT_MAIN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPermanentCount(playerA, bloodmoon, 1);
|
||||
assertPermanentCount(playerA, urborgtoy, 1);
|
||||
|
|
@ -157,8 +164,10 @@ public class LandTypeChangingEffectsTest extends CardTestPlayerBase {
|
|||
playLand(1, PhaseStep.PRECOMBAT_MAIN, playerA, urborgtoy);
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, bloodmoon);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(2, PhaseStep.PRECOMBAT_MAIN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPermanentCount(playerA, bloodmoon, 1);
|
||||
assertPermanentCount(playerA, urborgtoy, 1);
|
||||
|
|
@ -176,7 +185,7 @@ public class LandTypeChangingEffectsTest extends CardTestPlayerBase {
|
|||
In terms of time-stamp order, Urborg was down first, then Kormus Bell, then Quicksilver.
|
||||
When I put a flood counter on a basic swamp, it would become a 0/0 instead of a 1/1 and die.
|
||||
*/
|
||||
|
||||
|
||||
@Test
|
||||
public void testCormusBellAfterUrborg() {
|
||||
// Land - Legendary
|
||||
|
|
@ -198,14 +207,14 @@ public class LandTypeChangingEffectsTest extends CardTestPlayerBase {
|
|||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Kormus Bell");
|
||||
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Quicksilver Fountain");
|
||||
|
||||
|
||||
addTarget(playerA, "Mountain");
|
||||
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(3, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
|
||||
assertPermanentCount(playerA, urborgtoy, 1);
|
||||
assertPermanentCount(playerA, "Kormus Bell", 1);
|
||||
assertPermanentCount(playerB, "Quicksilver Fountain", 1);
|
||||
|
|
@ -245,8 +254,10 @@ public class LandTypeChangingEffectsTest extends CardTestPlayerBase {
|
|||
addCard(Zone.BATTLEFIELD, playerA, "Stormtide Leviathan"); // all lands are islands in addition to their other types
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Darksteel Citadel"); // land has indestructible ability
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(3, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
Permanent darksteel = getPermanent("Darksteel Citadel", playerA.getId());
|
||||
Assert.assertNotNull(darksteel);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
package org.mage.test.cards.planeswalker;
|
||||
|
||||
import mage.abilities.keyword.IndestructibleAbility;
|
||||
|
|
@ -11,7 +10,6 @@ import org.junit.Test;
|
|||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class GideonTest extends CardTestPlayerBase {
|
||||
|
|
@ -116,16 +114,23 @@ public class GideonTest extends CardTestPlayerBase {
|
|||
// Equip {2}
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Stitcher's Graft", 1);
|
||||
|
||||
// transform
|
||||
attack(2, playerB, "Kytheon, Hero of Akros");
|
||||
attack(2, playerB, "Silvercoat Lion");
|
||||
attack(2, playerB, "Pillarfield Ox");
|
||||
checkPermanentCount("after transform", 2, PhaseStep.POSTCOMBAT_MAIN, playerB, "Gideon, Battle-Forged", 1);
|
||||
|
||||
// become creature and equip
|
||||
activateAbility(4, PhaseStep.PRECOMBAT_MAIN, playerB, "0: Until ");
|
||||
waitStackResolved(4, PhaseStep.PRECOMBAT_MAIN);
|
||||
activateAbility(4, PhaseStep.PRECOMBAT_MAIN, playerB, "Equip {2}", "Gideon, Battle-Forged");
|
||||
|
||||
attack(4, playerB, "Gideon, Battle-Forged"); // 7 damage
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(5, PhaseStep.PRECOMBAT_MAIN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPermanentCount(playerB, "Silvercoat Lion", 1);
|
||||
assertLife(playerA, 7);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
package org.mage.test.cards.triggers.dies;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
|
|
@ -7,7 +6,6 @@ import org.junit.Test;
|
|||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
|
||||
|
|
@ -16,10 +14,9 @@ public class ShowstopperTest extends CardTestPlayerBase {
|
|||
/**
|
||||
* Tests that the dies triggered ability of silvercoat lion (gained by Showstopper)
|
||||
* triggers as he dies from Lightning Bolt
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testDiesTriggeredAbility() {
|
||||
public void test_OneTrigger() {
|
||||
// Showstopper Instant {1}{B}{R}
|
||||
// Until end of turn, creatures you control gain "When this creature dies, it deals 2 damage to target creature an opponent controls."
|
||||
addCard(Zone.HAND, playerA, "Showstopper");
|
||||
|
|
@ -30,10 +27,14 @@ public class ShowstopperTest extends CardTestPlayerBase {
|
|||
addCard(Zone.BATTLEFIELD, playerB, "Ornithopter", 1);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Showstopper");
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", "Silvercoat Lion");
|
||||
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "Lightning Bolt", "Silvercoat Lion");
|
||||
addTarget(playerA, "Ornithopter");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 20);
|
||||
|
|
@ -43,12 +44,13 @@ public class ShowstopperTest extends CardTestPlayerBase {
|
|||
|
||||
assertGraveyardCount(playerB, "Ornithopter", 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if Showstopper is called twice
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testTwoDiesTriggeredAbilities() {
|
||||
public void test_TwoTriggers() {
|
||||
// Showstopper Instant {1}{B}{R}
|
||||
// Until end of turn, creatures you control gain "When this creature dies, it deals 2 damage to target creature an opponent controls."
|
||||
addCard(Zone.HAND, playerA, "Showstopper", 2);
|
||||
|
|
@ -62,12 +64,16 @@ public class ShowstopperTest extends CardTestPlayerBase {
|
|||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Showstopper");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Showstopper");
|
||||
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Lightning Bolt", "Silvercoat Lion");
|
||||
setChoice(playerA, "When {this} dies"); // choose from two triggers
|
||||
addTarget(playerA, "Ornithopter");
|
||||
addTarget(playerA, "Grizzly Bears");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 20);
|
||||
|
|
@ -79,4 +85,65 @@ public class ShowstopperTest extends CardTestPlayerBase {
|
|||
assertGraveyardCount(playerB, "Ornithopter", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_TwoTriggersAndCopies() {
|
||||
// Showstopper Instant {1}{B}{R}
|
||||
// Until end of turn, creatures you control gain "When this creature dies, it deals 2 damage to target creature an opponent controls."
|
||||
addCard(Zone.HAND, playerA, "Showstopper", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Silvercoat Lion", 1);
|
||||
addCard(Zone.HAND, playerB, "Lightning Bolt");
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Ornithopter", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Grizzly Bears", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Alchemist's Apprentice", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Augmenting Automaton", 1);
|
||||
//
|
||||
// When you next cast an instant spell, cast a sorcery spell, or activate a loyalty ability this turn, copy that spell or ability twice.
|
||||
// You may choose new targets for the copies.
|
||||
addCard(Zone.HAND, playerA, "Repeated Reverberation", 1); // {2}{R}{R}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 4);
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 4);
|
||||
|
||||
// first spell
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {B}", 2);
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Showstopper");
|
||||
|
||||
// prepare copy
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}", 4);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Repeated Reverberation");
|
||||
|
||||
// second spell with 2x copy
|
||||
waitStackResolved(1, PhaseStep.PRECOMBAT_MAIN);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Showstopper");
|
||||
|
||||
castSpell(1, PhaseStep.POSTCOMBAT_MAIN, playerB, "Lightning Bolt", "Silvercoat Lion");
|
||||
setChoice(playerA, "When {this} dies"); // choose from 4 triggers
|
||||
setChoice(playerA, "When {this} dies"); // choose from 4 triggers
|
||||
setChoice(playerA, "When {this} dies"); // choose from 4 triggers
|
||||
addTarget(playerA, "Ornithopter");
|
||||
addTarget(playerA, "Grizzly Bears");
|
||||
addTarget(playerA, "Alchemist's Apprentice");
|
||||
addTarget(playerA, "Augmenting Automaton");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 20);
|
||||
|
||||
assertGraveyardCount(playerA, "Showstopper", 2);
|
||||
assertGraveyardCount(playerA, "Silvercoat Lion", 1);
|
||||
|
||||
assertGraveyardCount(playerB, "Grizzly Bears", 1);
|
||||
assertGraveyardCount(playerB, "Ornithopter", 1);
|
||||
assertGraveyardCount(playerB, "Alchemist's Apprentice", 1);
|
||||
assertGraveyardCount(playerB, "Augmenting Automaton", 1);
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue