* 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:
Oleg Agafonov 2020-02-11 22:29:07 +04:00
parent 13ad86cb21
commit b5acf64772
9 changed files with 589 additions and 78 deletions

View file

@ -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 youve 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}");
}
}

View file

@ -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();
}
}

View file

@ -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);
}
}