mirror of
https://github.com/magefree/mage.git
synced 2025-12-23 20:11:59 -08:00
Additional and alternative costs improved:
* Now player must choose additional costs before ability's modes;
* Fixed broken kicker ability from ZNR (see comments from d4ca287f0f);
* Improved compatibility of additional cost with cost modification effects (fixed that optional multi-costs doesn't affected by cost modification);
* Improved compatibility of additional cost with alternative cost (some cards ignores additional cost on alternative usage, e.g. on play free);
This commit is contained in:
parent
586538a66c
commit
6e0c7e868c
17 changed files with 504 additions and 156 deletions
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
package org.mage.test.cards.abilities.keywords;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
|
|
@ -7,39 +6,172 @@ import org.junit.Test;
|
|||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
* @author LevelX2, JayDi85
|
||||
*/
|
||||
|
||||
public class EntwineTest extends CardTestPlayerBase {
|
||||
|
||||
@Test
|
||||
public void test_CastWithoutEntwine() {
|
||||
// Choose one —
|
||||
//• Barbed Lightning deals 3 damage to target creature.
|
||||
//• Barbed Lightning deals 3 damage to target player or planeswalker.
|
||||
// Entwine {2} (Choose both if you pay the entwine cost.)
|
||||
addCard(Zone.HAND, playerA, "Barbed Lightning", 1); // {2}{R}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3);
|
||||
//
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1); // 2/2
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Barbed Lightning");
|
||||
setChoice(playerA, "No"); // not use Entwine
|
||||
setModeChoice(playerA, "1"); // target creature
|
||||
addTarget(playerA, "Balduvian Bears");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertLife(playerA, 20);
|
||||
assertPermanentCount(playerA, "Balduvian Bears", 0);
|
||||
assertTappedCount("Mountain", true, 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_CastEntwine_Normal() {
|
||||
// Choose one —
|
||||
//• Barbed Lightning deals 3 damage to target creature.
|
||||
//• Barbed Lightning deals 3 damage to target player or planeswalker.
|
||||
// Entwine {2} (Choose both if you pay the entwine cost.)
|
||||
addCard(Zone.HAND, playerA, "Barbed Lightning", 1); // {2}{R}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3 + 2);
|
||||
//
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1); // 2/2
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Barbed Lightning");
|
||||
setChoice(playerA, "Yes"); // use Entwine
|
||||
addTarget(playerA, "Balduvian Bears");
|
||||
addTarget(playerA, playerA);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertLife(playerA, 20 - 3);
|
||||
assertPermanentCount(playerA, "Balduvian Bears", 0);
|
||||
assertTappedCount("Mountain", true, 3 + 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_CastEntwine_CostReduction() {
|
||||
addCustomEffect_SpellCostModification(playerA, -4);
|
||||
|
||||
// Choose one —
|
||||
//• Barbed Lightning deals 3 damage to target creature.
|
||||
//• Barbed Lightning deals 3 damage to target player or planeswalker.
|
||||
// Entwine {2} (Choose both if you pay the entwine cost.)
|
||||
addCard(Zone.HAND, playerA, "Barbed Lightning", 1); // {2}{R}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); // -4 as cost reduction
|
||||
//
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1); // 2/2
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Barbed Lightning");
|
||||
setChoice(playerA, "Yes"); // use Entwine
|
||||
addTarget(playerA, "Balduvian Bears");
|
||||
addTarget(playerA, playerA);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertLife(playerA, 20 - 3);
|
||||
assertPermanentCount(playerA, "Balduvian Bears", 0);
|
||||
assertTappedCount("Mountain", true, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_CastEntwine_CostIncreasing() {
|
||||
addCustomEffect_SpellCostModification(playerA, 5);
|
||||
|
||||
// Choose one —
|
||||
//• Barbed Lightning deals 3 damage to target creature.
|
||||
//• Barbed Lightning deals 3 damage to target player or planeswalker.
|
||||
// Entwine {2} (Choose both if you pay the entwine cost.)
|
||||
addCard(Zone.HAND, playerA, "Barbed Lightning", 1); // {2}{R}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 3 + 2 + 5);
|
||||
//
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1); // 2/2
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Barbed Lightning");
|
||||
setChoice(playerA, "Yes"); // use Entwine
|
||||
addTarget(playerA, "Balduvian Bears");
|
||||
addTarget(playerA, playerA);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertLife(playerA, 20 - 3);
|
||||
assertPermanentCount(playerA, "Balduvian Bears", 0);
|
||||
assertTappedCount("Mountain", true, 3 + 2 + 5);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_CastEntwine_FreeFromHand() {
|
||||
// You may cast nonland cards from your hand without paying their mana costs.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Omniscience");
|
||||
|
||||
// Choose one —
|
||||
//• Barbed Lightning deals 3 damage to target creature.
|
||||
//• Barbed Lightning deals 3 damage to target player or planeswalker.
|
||||
// Entwine {2} (Choose both if you pay the entwine cost.)
|
||||
addCard(Zone.HAND, playerA, "Barbed Lightning", 1); // {2}{R}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 2); // only Entwine pay need
|
||||
//
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1); // 2/2
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Barbed Lightning");
|
||||
setChoice(playerA, "Yes"); // cast for free
|
||||
setChoice(playerA, "Yes"); // use Entwine
|
||||
addTarget(playerA, "Balduvian Bears");
|
||||
addTarget(playerA, playerA);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertLife(playerA, 20 - 3);
|
||||
assertPermanentCount(playerA, "Balduvian Bears", 0);
|
||||
assertTappedCount("Plains", true, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_ToothAndNail() {
|
||||
setStrictChooseMode(true);
|
||||
|
||||
|
||||
addCard(Zone.LIBRARY, playerA, "Silvercoat Lion", 1);
|
||||
addCard(Zone.LIBRARY, playerA, "Pillarfield Ox", 1);
|
||||
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 9);
|
||||
// Choose one -
|
||||
// Search your library for up to two creature cards, reveal them, put them into your hand, then shuffle your library;
|
||||
// or put up to two creature cards from your hand onto the battlefield.
|
||||
// Entwine {2}
|
||||
addCard(Zone.HAND, playerA, "Tooth and Nail"); // Sorcery {5}{G}{G}
|
||||
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Tooth and Nail");
|
||||
setChoice(playerA, "Yes"); // Message: Pay Entwine {2} ?
|
||||
addTarget(playerA, "Silvercoat Lion^Pillarfield Ox");
|
||||
|
||||
setChoice(playerA, "Silvercoat Lion^Pillarfield Ox");
|
||||
|
||||
setChoice(playerA, "Silvercoat Lion^Pillarfield Ox");
|
||||
|
||||
setStopAt(1, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
assertAllCommandsUsed();
|
||||
|
||||
|
||||
assertPermanentCount(playerA, "Silvercoat Lion", 1);
|
||||
assertPermanentCount(playerA, "Pillarfield Ox", 1);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -400,6 +400,7 @@ public class KickerTest extends CardTestPlayerBase {
|
|||
assertTappedCount("Swamp", true, 5);
|
||||
assertGraveyardCount(playerA, "Marsh Casualties", 1);
|
||||
assertPowerToughness(playerB, "Centaur Courser", 1, 1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,158 @@
|
|||
package org.mage.test.cards.abilities.keywords;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class KickerWithAnyNumberModesAbilityTest extends CardTestPlayerBase {
|
||||
|
||||
@Test
|
||||
public void test_WithoutKicker() {
|
||||
// Kicker {2}{G}
|
||||
// Choose one. If this spell was kicked, choose any number instead.
|
||||
// • Put two +1/+1 counters on target creature.
|
||||
// • Target player gains X life, where X is the greatest power among creatures they control.
|
||||
// • Target creature you control fights target creature you don't control.
|
||||
addCard(Zone.HAND, playerA, "Inscription of Abundance", 1); // {1}{G}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1); // 2/2
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Inscription of Abundance");
|
||||
setChoice(playerA, "No"); // no kicker
|
||||
setModeChoice(playerA, "1");
|
||||
addTarget(playerA, "Balduvian Bears");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPowerToughness(playerA, "Balduvian Bears", 2 + 2, 2 + 2);
|
||||
assertLife(playerA, 20);
|
||||
assertTappedCount("Forest", true, 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Kicker_Normal() {
|
||||
// Kicker {2}{G}
|
||||
// Choose one. If this spell was kicked, choose any number instead.
|
||||
// • Put two +1/+1 counters on target creature.
|
||||
// • Target player gains X life, where X is the greatest power among creatures they control.
|
||||
// • Target creature you control fights target creature you don't control.
|
||||
addCard(Zone.HAND, playerA, "Inscription of Abundance", 1); // {1}{G}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2 + 3);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1); // 2/2
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Inscription of Abundance");
|
||||
setChoice(playerA, "Yes"); // use kicker
|
||||
setModeChoice(playerA, "2");
|
||||
setModeChoice(playerA, "1");
|
||||
addTarget(playerA, playerA); // gain x life
|
||||
addTarget(playerA, "Balduvian Bears"); // get counters
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPowerToughness(playerA, "Balduvian Bears", 2 + 2, 2 + 2);
|
||||
assertLife(playerA, 20 + 4);
|
||||
assertTappedCount("Forest", true, 2 + 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Kicker_CostReduction() {
|
||||
addCustomEffect_SpellCostModification(playerA, -4);
|
||||
|
||||
// Kicker {2}{G}
|
||||
// Choose one. If this spell was kicked, choose any number instead.
|
||||
// • Put two +1/+1 counters on target creature.
|
||||
// • Target player gains X life, where X is the greatest power among creatures they control.
|
||||
// • Target creature you control fights target creature you don't control.
|
||||
addCard(Zone.HAND, playerA, "Inscription of Abundance", 1); // {1}{G}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2 + 3 - 3); // -3 by cost reduction
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1); // 2/2
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Inscription of Abundance");
|
||||
setChoice(playerA, "Yes"); // use kicker
|
||||
setModeChoice(playerA, "2");
|
||||
setModeChoice(playerA, "1");
|
||||
addTarget(playerA, playerA); // gain x life
|
||||
addTarget(playerA, "Balduvian Bears"); // get counters
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPowerToughness(playerA, "Balduvian Bears", 2 + 2, 2 + 2);
|
||||
assertLife(playerA, 20 + 4);
|
||||
assertTappedCount("Forest", true, 2 + 3 - 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Kicker_CostIncreasing() {
|
||||
addCustomEffect_SpellCostModification(playerA, 5);
|
||||
|
||||
// Kicker {2}{G}
|
||||
// Choose one. If this spell was kicked, choose any number instead.
|
||||
// • Put two +1/+1 counters on target creature.
|
||||
// • Target player gains X life, where X is the greatest power among creatures they control.
|
||||
// • Target creature you control fights target creature you don't control.
|
||||
addCard(Zone.HAND, playerA, "Inscription of Abundance", 1); // {1}{G}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2 + 3 + 5); // +5 by cost increase
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1); // 2/2
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Inscription of Abundance");
|
||||
setChoice(playerA, "Yes"); // use kicker
|
||||
setModeChoice(playerA, "2");
|
||||
setModeChoice(playerA, "1");
|
||||
addTarget(playerA, playerA); // gain x life
|
||||
addTarget(playerA, "Balduvian Bears"); // get counters
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPowerToughness(playerA, "Balduvian Bears", 2 + 2, 2 + 2);
|
||||
assertLife(playerA, 20 + 4);
|
||||
assertTappedCount("Forest", true, 2 + 3 + 5);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Kicker_FreeFromHand() {
|
||||
// You may cast nonland cards from your hand without paying their mana costs.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Omniscience");
|
||||
|
||||
// Kicker {2}{G}
|
||||
// Choose one. If this spell was kicked, choose any number instead.
|
||||
// • Put two +1/+1 counters on target creature.
|
||||
// • Target player gains X life, where X is the greatest power among creatures they control.
|
||||
// • Target creature you control fights target creature you don't control.
|
||||
addCard(Zone.HAND, playerA, "Inscription of Abundance", 1); // {1}{G}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 3); // -2 by free cast
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Balduvian Bears", 1); // 2/2
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Inscription of Abundance");
|
||||
setChoice(playerA, "Yes"); // use free cast
|
||||
setChoice(playerA, "Yes"); // use kicker
|
||||
setModeChoice(playerA, "2");
|
||||
setModeChoice(playerA, "1");
|
||||
addTarget(playerA, playerA); // gain x life
|
||||
addTarget(playerA, "Balduvian Bears"); // get counters
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPowerToughness(playerA, "Balduvian Bears", 2 + 2, 2 + 2);
|
||||
assertLife(playerA, 20 + 4);
|
||||
assertTappedCount("Forest", true, 3);
|
||||
}
|
||||
}
|
||||
|
|
@ -192,7 +192,7 @@ public class CastFromHandWithoutPayingManaCostTest extends CardTestPlayerBase {
|
|||
/**
|
||||
* Omniscience is not allowing me to cast spells for free. I'm playing a
|
||||
* Commander game against the Computer, if that helps.
|
||||
*
|
||||
* <p>
|
||||
* Edit: It's not letting me cast fused spells for free. Others seems to be
|
||||
* working.
|
||||
*/
|
||||
|
|
@ -276,16 +276,23 @@ public class CastFromHandWithoutPayingManaCostTest extends CardTestPlayerBase {
|
|||
|
||||
// Choose one - Barbed Lightning deals 3 damage to target creature; or Barbed Lightning deals 3 damage to target player.
|
||||
// Entwine {2} (Choose both if you pay the entwine cost.)
|
||||
addCard(Zone.HAND, playerA, "Barbed Lightning", 1);
|
||||
addCard(Zone.HAND, playerA, "Barbed Lightning", 1); // {2}{R}
|
||||
|
||||
// Creature - 3/3 Swampwalk
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Bog Wraith", 1);
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Barbed Lightning", "Bog Wraith");
|
||||
addTarget(playerA, playerB);
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Barbed Lightning");
|
||||
setChoice(playerA, "Yes"); // cast without cost
|
||||
setChoice(playerA, "Yes"); // pay Entwine
|
||||
addTarget(playerA, "Bog Wraith"); // target form mode 1
|
||||
addTarget(playerA, playerB); // target for mode 2
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
showBattlefield("after", 1, PhaseStep.POSTCOMBAT_MAIN, playerA);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertGraveyardCount(playerA, "Barbed Lightning", 1);
|
||||
assertGraveyardCount(playerB, "Bog Wraith", 1);
|
||||
|
|
@ -293,7 +300,7 @@ public class CastFromHandWithoutPayingManaCostTest extends CardTestPlayerBase {
|
|||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 17);
|
||||
|
||||
assertTapped("Plains", true); // plains have to be tapped because {2} from Entwine have to be paid
|
||||
assertTappedCount("Plains", true, 2); // plains have to be tapped because {2} from Entwine have to be paid
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
package org.mage.test.cards.modal;
|
||||
|
||||
import mage.abilities.keyword.SwampwalkAbility;
|
||||
|
|
@ -8,7 +7,6 @@ import org.junit.Test;
|
|||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public class ChooseOneTest extends CardTestPlayerBase {
|
||||
|
|
@ -48,8 +46,10 @@ public class ChooseOneTest extends CardTestPlayerBase {
|
|||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Funeral Charm", "Silvercoat Lion");
|
||||
setModeChoice(playerA, "2");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertGraveyardCount(playerA, "Funeral Charm", 1);
|
||||
assertPowerToughness(playerB, "Silvercoat Lion", 4, 1);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue