mirror of
https://github.com/magefree/mage.git
synced 2026-01-23 19:59:54 -08:00
* Monohybrid mana cost improves:
* fixed wrong manually pay by mana pool (it pays generic cost instead colored part of monohybrid); * fixed not working cost reduction effects (now monohybrid cost will be reduced correctly with some limitation, see #6130);
This commit is contained in:
parent
13ad86cb21
commit
b5acf64772
9 changed files with 589 additions and 78 deletions
|
|
@ -0,0 +1,159 @@
|
|||
package org.mage.test.cards.cost.modification;
|
||||
|
||||
import mage.abilities.costs.mana.ManaCost;
|
||||
import mage.abilities.costs.mana.ManaCosts;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.util.CardUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class CostReduceTest extends CardTestPlayerBase {
|
||||
|
||||
private void testReduce(String sourceCost, int reduceAmount, String needReducedCost) {
|
||||
// load mana by sctrict mode (e.g. for real mana usage in param)
|
||||
ManaCosts<ManaCost> source = new ManaCostsImpl<>();
|
||||
source.load(sourceCost, true);
|
||||
ManaCosts<ManaCost> need = new ManaCostsImpl<>();
|
||||
need.load(needReducedCost, true);
|
||||
ManaCosts<ManaCost> reduced = CardUtil.reduceCost(source, reduceAmount);
|
||||
|
||||
if (!reduced.getText().equals(need.getText())) {
|
||||
Assert.fail(sourceCost + " after reduction by " + reduceAmount + " must be " + need.getText() + ", but get " + reduced.getText());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_Monohybrid() {
|
||||
// extra test to ensure about mono hybrid test code
|
||||
ManaCosts<ManaCost> testCost = new ManaCostsImpl<>();
|
||||
testCost.load("{1/R}");
|
||||
Assert.assertEquals("normal mono hybrid always 2 generics", "{2/R}", testCost.getText());
|
||||
testCost = new ManaCostsImpl<>();
|
||||
testCost.load("{1/R}", true);
|
||||
Assert.assertEquals("test mono hybrid have variant generic", "{1/R}", testCost.getText());
|
||||
testReduce("{5/R}", 0, "{5/R}"); // ensure that mono hybrid in test mode
|
||||
|
||||
// DECREASE COST
|
||||
|
||||
// colorless is not reduce
|
||||
testReduce("{C}", 1, "{C}");
|
||||
testReduce("{C}{G}", 1, "{C}{G}");
|
||||
|
||||
// 0 generic, decrease cost by 1
|
||||
testReduce("", 1, "");
|
||||
testReduce("{R}", 1, "{R}");
|
||||
testReduce("{R}{G}", 1, "{R}{G}");
|
||||
|
||||
// 1 generic, decrease cost by 1
|
||||
testReduce("{1}", 1, "");
|
||||
testReduce("{R}{1}", 1, "{R}");
|
||||
testReduce("{1}{R}", 1, "{R}");
|
||||
testReduce("{1}{R}{G}", 1, "{R}{G}");
|
||||
testReduce("{R}{1}{G}", 1, "{R}{G}");
|
||||
testReduce("{R}{G}{1}", 1, "{R}{G}");
|
||||
|
||||
// 2 generics, decrease cost by 1
|
||||
testReduce("{2}", 1, "{1}");
|
||||
testReduce("{R}{2}", 1, "{R}{1}");
|
||||
testReduce("{2}{R}", 1, "{1}{R}");
|
||||
testReduce("{2}{R}{G}", 1, "{1}{R}{G}");
|
||||
testReduce("{R}{2}{G}", 1, "{R}{1}{G}");
|
||||
testReduce("{R}{G}{2}", 1, "{R}{G}{1}");
|
||||
|
||||
// 3 generics, decrease cost by 2
|
||||
testReduce("{2}", 2, "");
|
||||
testReduce("{3}", 2, "{1}");
|
||||
testReduce("{R}{3}", 2, "{R}{1}");
|
||||
testReduce("{3}{R}", 2, "{1}{R}");
|
||||
testReduce("{3}{R}{G}", 2, "{1}{R}{G}");
|
||||
testReduce("{R}{3}{G}", 2, "{R}{1}{G}");
|
||||
testReduce("{R}{G}{3}", 2, "{R}{G}{1}");
|
||||
|
||||
// INCREASE COST
|
||||
|
||||
// colorless, increase cost by 1
|
||||
testReduce("{C}", -1, "{C}{1}");
|
||||
testReduce("{C}{G}", -1, "{C}{G}{1}");
|
||||
|
||||
// 0 generic, increase cost by 1
|
||||
testReduce("", -1, "{1}");
|
||||
testReduce("{R}", -1, "{R}{1}");
|
||||
testReduce("{R}{G}", -1, "{R}{G}{1}");
|
||||
|
||||
// 1 generic, increase cost by 1
|
||||
testReduce("{1}", -1, "{2}");
|
||||
testReduce("{R}{1}", -1, "{R}{2}");
|
||||
testReduce("{1}{R}", -1, "{2}{R}");
|
||||
testReduce("{1}{R}{G}", -1, "{2}{R}{G}");
|
||||
testReduce("{R}{1}{G}", -1, "{R}{2}{G}");
|
||||
testReduce("{R}{G}{1}", -1, "{R}{G}{2}");
|
||||
|
||||
// 2 generics, increase cost by 1
|
||||
testReduce("{2}", -1, "{3}");
|
||||
testReduce("{R}{2}", -1, "{R}{3}");
|
||||
testReduce("{2}{R}", -1, "{3}{R}");
|
||||
testReduce("{2}{R}{G}", -1, "{3}{R}{G}");
|
||||
testReduce("{R}{2}{G}", -1, "{R}{3}{G}");
|
||||
testReduce("{R}{G}{2}", -1, "{R}{G}{3}");
|
||||
|
||||
// 3 generics, increase cost by 2
|
||||
testReduce("{3}", -2, "{5}");
|
||||
testReduce("{R}{3}", -2, "{R}{5}");
|
||||
testReduce("{3}{R}", -2, "{5}{R}");
|
||||
testReduce("{3}{R}{G}", -2, "{5}{R}{G}");
|
||||
testReduce("{R}{3}{G}", -2, "{R}{5}{G}");
|
||||
testReduce("{R}{G}{3}", -2, "{R}{G}{5}");
|
||||
|
||||
// HYBRID
|
||||
// from Reaper King
|
||||
// If an effect reduces the cost to cast a spell by an amount of generic mana, it applies to a monocolored hybrid
|
||||
// spell only if you’ve chosen a method of paying for it that includes generic mana.
|
||||
// (2008-05-01)
|
||||
|
||||
// MONO HYBRID
|
||||
// 1. Mono hybrid always 2 generic mana like 2/R
|
||||
// 2. Generic must have priority over hybrid
|
||||
|
||||
// no generic, normal amount
|
||||
// mono hybrid, decrease cost by 1
|
||||
testReduce("{2/R}", 1, "{1/R}");
|
||||
testReduce("{2/R}{2/G}", 1, "{1/R}{2/G}"); // TODO: add or/or reduction? (see https://github.com/magefree/mage/issues/6130 )
|
||||
// mono hybrid, increase cost by 1
|
||||
testReduce("{2/R}", -1, "{2/R}{1}");
|
||||
testReduce("{2/R}{2/G}", -1, "{2/R}{2/G}{1}");
|
||||
|
||||
// generic, normal amount
|
||||
// mono hybrid + 1 generic, decrease cost by 1
|
||||
testReduce("{2/R}{1}", 1, "{2/R}");
|
||||
testReduce("{2/R}{2/G}{1}", 1, "{2/R}{2/G}");
|
||||
// mono hybrid + 1 generic, increase cost by 1
|
||||
testReduce("{2/R}{1}", -1, "{2/R}{2}");
|
||||
testReduce("{2/R}{2/G}{1}", -1, "{2/R}{2/G}{2}");
|
||||
|
||||
// generic, too much generic
|
||||
// mono hybrid + 2 generic, decrease cost by 1
|
||||
testReduce("{2/R}{2}", 1, "{2/R}{1}");
|
||||
testReduce("{2/R}{2/G}{2}", 1, "{2/R}{2/G}{1}");
|
||||
// mono hybrid + 2 generic, increase cost by 1
|
||||
testReduce("{2/R}{2}", -1, "{2/R}{3}");
|
||||
testReduce("{2/R}{2/G}{2}", -1, "{2/R}{2/G}{3}");
|
||||
|
||||
// generic, too much reduce
|
||||
// mono hybrid + 1 generic, decrease cost by 2
|
||||
testReduce("{2/R}{1}", 2, "{1/R}");
|
||||
testReduce("{2/R}{2/G}{1}", 2, "{1/R}{2/G}"); // TODO: add or/or reduction? (see https://github.com/magefree/mage/issues/6130 )
|
||||
// mono hybrid + 1 generic, increase cost by 2
|
||||
testReduce("{2/R}{1}", -2, "{2/R}{3}");
|
||||
testReduce("{2/R}{2/G}{1}", -2, "{2/R}{2/G}{3}");
|
||||
|
||||
// EXTRA
|
||||
// TODO: add or/or reduction? (see https://github.com/magefree/mage/issues/6130 )
|
||||
testReduce("{2}{2/R}{2/G}", 3, "{1/R}{2/G}");
|
||||
testReduce("{2}{2/R}{2/G}", 4, "{0/R}{2/G}");
|
||||
testReduce("{2}{2/R}{2/G}", 5, "{0/R}{1/G}");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package org.mage.test.cards.cost.modification;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class MonohybridCostReduceTest extends CardTestPlayerBase {
|
||||
|
||||
@Test
|
||||
public void test_CostReduction_First() {
|
||||
// monohybrid supports with some limitation -- it reduce first hybrid cost, see https://github.com/magefree/mage/issues/6130
|
||||
|
||||
// Artifact spells you cast cost {1} less to cast.
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Etherium Sculptor");
|
||||
//
|
||||
// Reaper King
|
||||
addCard(Zone.HAND, playerA, "Reaper King"); // {2/W}{2/U}{2/B}{2/R}{2/G}
|
||||
// Add {C}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Blinkmoth Nexus", 2 * 5 - 1); // one less to test cost reduction
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reaper King");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
package org.mage.test.cards.cost.modification;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class MonohybridManaPayTest extends CardTestPlayerBase {
|
||||
|
||||
@Test
|
||||
public void test_PaySimpleMana_Manually() {
|
||||
// simulate user click on mana pool icons
|
||||
disableManaAutoPayment(playerA);
|
||||
|
||||
addCard(Zone.HAND, playerA, "Balduvian Bears");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
|
||||
|
||||
// fill mana pool
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {G}");
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {B}");
|
||||
// cast spell
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Balduvian Bears");
|
||||
// unlock mana order in pool
|
||||
setChoice(playerA, "Green");
|
||||
setChoice(playerA, "Black");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPermanentCount(playerA, "Balduvian Bears", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_PayMonohybridMana_ColorPart_SameUnlockOrder() {
|
||||
// simulate user click on mana pool icons
|
||||
// mono hybrid can be paid by color or {2}
|
||||
disableManaAutoPayment(playerA);
|
||||
|
||||
// Reaper King
|
||||
addCard(Zone.HAND, playerA, "Reaper King"); // {2/W}{2/U}{2/B}{2/R}{2/G}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
|
||||
|
||||
// fill mana pool
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {W}");
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {U}");
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {B}");
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {G}");
|
||||
// cast spell
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reaper King");
|
||||
// unlock mana order in pool (SAME ORDER AS PAYMENT - {W}{U}{B}{R}{G})
|
||||
setChoice(playerA, "White");
|
||||
setChoice(playerA, "Blue");
|
||||
setChoice(playerA, "Black");
|
||||
setChoice(playerA, "Red");
|
||||
setChoice(playerA, "Green");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPermanentCount(playerA, "Reaper King", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_PayMonohybridMana_ColorPart_AnyUnlockOrder() {
|
||||
// simulate user click on mana pool icons
|
||||
// mono hybrid can be paid by color or {2}
|
||||
disableManaAutoPayment(playerA);
|
||||
|
||||
// Reaper King
|
||||
addCard(Zone.HAND, playerA, "Reaper King"); // {2/W}{2/U}{2/B}{2/R}{2/G}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Plains", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
|
||||
|
||||
// fill mana pool
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {W}");
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {U}");
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {B}");
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}");
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {G}");
|
||||
// cast spell
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reaper King");
|
||||
// unlock mana order in pool (DIFFERENT ORDER AS PAYMENT - {R}{G}{W}{U}{B})
|
||||
setChoice(playerA, "Red");
|
||||
setChoice(playerA, "Green");
|
||||
setChoice(playerA, "White");
|
||||
setChoice(playerA, "Blue");
|
||||
setChoice(playerA, "Black");
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPermanentCount(playerA, "Reaper King", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_PayMonohybridMana_GenericPart_AnyUnlockOrder() {
|
||||
// simulate user click on mana pool icons
|
||||
// mono hybrid must be payed as color first
|
||||
disableManaAutoPayment(playerA); // must pay by mana unlock command (like human clicks on mana pool icons)
|
||||
|
||||
// Reaper King
|
||||
addCard(Zone.HAND, playerA, "Reaper King"); // {2/W}{2/U}{2/B}{2/R}{2/G}
|
||||
//addCard(Zone.BATTLEFIELD, playerA, "Plains", 1); -- white mana paid by {2}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 1 + 2 + 2);
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1);
|
||||
//addCard(Zone.BATTLEFIELD, playerA, "Mountain", 1); -- red mana paid by {2}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 1);
|
||||
|
||||
// fill mana pool
|
||||
//activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {W}"); -- paid by {2}
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {U}", 5); // pay for {U}, 2/W and 2/R
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {B}");
|
||||
//activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {R}"); -- paid by {2}
|
||||
activateManaAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "{T}: Add {G}");
|
||||
// cast spell
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reaper King");
|
||||
// unlock mana order in pool (ANY ORDER)
|
||||
setChoice(playerA, "Black");
|
||||
setChoice(playerA, "Green");
|
||||
setChoice(playerA, "Blue", 5); // unlocks and pays for U, 2/W and 2/R // TODO: add support to pay one by one, not all
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPermanentCount(playerA, "Reaper King", 1);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue