mirror of
https://github.com/magefree/mage.git
synced 2025-12-23 12:02:01 -08:00
Fixes to Mana.enough: mana of any color (ManaType.Any) was being used to pay for colourless mana. Fixes for Mana.needed: mana of any color (ManaType.Any) was being used to pay for colourless mana. calculation for generic mana remaining was using min(0, available) instead of max(0, available) meaning that leftover mana of other types was never used to pay for any leftover generic costs. Other: Added tests for both .needed and .enough. Moved tests some tests from ManaUtilTest to ManaTest Simplified Mana.subtractCosts by calling Mana.substract first to make use of common functionality. Added more documentation Added tests for both .needed Added more tests for .enough to cover the changes with colourless mana.
This commit is contained in:
parent
16914632c4
commit
e679574a15
4 changed files with 293 additions and 196 deletions
|
|
@ -3,9 +3,7 @@ package org.mage.test.utils;
|
|||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import mage.Mana;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.SpellAbility;
|
||||
import mage.abilities.costs.mana.ManaCost;
|
||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||
import mage.abilities.mana.BasicManaAbility;
|
||||
|
|
@ -15,7 +13,6 @@ import mage.abilities.mana.RedManaAbility;
|
|||
import mage.abilities.mana.WhiteManaAbility;
|
||||
import mage.cards.Card;
|
||||
import mage.cards.repository.CardRepository;
|
||||
import mage.util.CardUtil;
|
||||
import mage.util.ManaUtil;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
|
@ -27,42 +24,42 @@ import org.mage.test.serverside.base.CardTestPlayerBase;
|
|||
public class ManaUtilTest extends CardTestPlayerBase {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
testManaToPayVsLand("{R}", "Blood Crypt", 2, 1); // should use {R}
|
||||
testManaToPayVsLand("{1}{R}", "Blood Crypt", 2, RedManaAbility.class); // should use {R}
|
||||
testManaToPayVsLand("{R}{B}", "Blood Crypt", 2, 2); // can't auto choose to pay
|
||||
testManaToPayVsLand("{2}{R}{B}", "Blood Crypt", 2, 2); // can't auto choose to pay
|
||||
testManaToPayVsLand("{R}{R}{B}{B}", "Blood Crypt", 2, 2); // can't auto choose to pay
|
||||
testManaToPayVsLand("{R}{G}{W}{W}{U}", "Blood Crypt", 2, RedManaAbility.class); // should use {R}
|
||||
public void testAutoPay() {
|
||||
testManaToPayVsLand("{R}", "Blood Crypt", 2, 1); // should use {R}
|
||||
testManaToPayVsLand("{1}{R}", "Blood Crypt", 2, RedManaAbility.class); // should use {R}
|
||||
testManaToPayVsLand("{R}{B}", "Blood Crypt", 2, 2); // can't auto choose to pay
|
||||
testManaToPayVsLand("{2}{R}{B}", "Blood Crypt", 2, 2); // can't auto choose to pay
|
||||
testManaToPayVsLand("{R}{R}{B}{B}", "Blood Crypt", 2, 2); // can't auto choose to pay
|
||||
testManaToPayVsLand("{R}{G}{W}{W}{U}", "Blood Crypt", 2, RedManaAbility.class); // should use {R}
|
||||
testManaToPayVsLand("{R}{R}{G}{W}{W}{U}", "Blood Crypt", 2, RedManaAbility.class); // should use {R}
|
||||
testManaToPayVsLand("{R}{R}", "Blood Crypt", 2, RedManaAbility.class); // should use {R}
|
||||
testManaToPayVsLand("{G}{W}", "Blood Crypt", 2, 2); // can't auto choose to pay
|
||||
testManaToPayVsLand("{1}{G}{W}", "Blood Crypt", 2, 1); // should use any but auto choose it
|
||||
testManaToPayVsLand("{2}{G}{W}{U}", "Blood Crypt", 2, 1); // should use any but auto choose it
|
||||
testManaToPayVsLand("{3}", "Blood Crypt", 2, 1); // should use any but auto choose it
|
||||
testManaToPayVsLand("{R}{R}", "Blood Crypt", 2, RedManaAbility.class); // should use {R}
|
||||
testManaToPayVsLand("{G}{W}", "Blood Crypt", 2, 2); // can't auto choose to pay
|
||||
testManaToPayVsLand("{1}{G}{W}", "Blood Crypt", 2, 1); // should use any but auto choose it
|
||||
testManaToPayVsLand("{2}{G}{W}{U}", "Blood Crypt", 2, 1); // should use any but auto choose it
|
||||
testManaToPayVsLand("{3}", "Blood Crypt", 2, 1); // should use any but auto choose it
|
||||
|
||||
testManaToPayVsLand("{R}{R}{G}{W}{W}{U}", "Watery Grave", 2, 1); // should use {U}
|
||||
testManaToPayVsLand("{R}{R}{G}{W}{W}", "Steam Vents", 2, 1); // should use {R}
|
||||
testManaToPayVsLand("{R}{R}{G}{B}{U}", "Temple Garden", 2, 1); // should use {G}
|
||||
testManaToPayVsLand("{W}{W}{G}{B}{U}", "Sacred Foundry", 2, 1); // should use {W}
|
||||
testManaToPayVsLand("{W}{W}{R}{B}{U}", "Overgrown Tomb", 2, BlackManaAbility.class); // should use {B}
|
||||
testManaToPayVsLand("{W}{W}{R}{B}{U}", "Swamp", 1, BlackManaAbility.class);
|
||||
testManaToPayVsLand("{W}{W}{R}{B}{U}", "Plains", 1, WhiteManaAbility.class);
|
||||
testManaToPayVsLand("{R}{R}{G}{W}{W}{U}", "Watery Grave", 2, 1); // should use {U}
|
||||
testManaToPayVsLand("{R}{R}{G}{W}{W}", "Steam Vents", 2, 1); // should use {R}
|
||||
testManaToPayVsLand("{R}{R}{G}{B}{U}", "Temple Garden", 2, 1); // should use {G}
|
||||
testManaToPayVsLand("{W}{W}{G}{B}{U}", "Sacred Foundry", 2, 1); // should use {W}
|
||||
testManaToPayVsLand("{W}{W}{R}{B}{U}", "Overgrown Tomb", 2, BlackManaAbility.class); // should use {B}
|
||||
testManaToPayVsLand("{W}{W}{R}{B}{U}", "Swamp", 1, BlackManaAbility.class);
|
||||
testManaToPayVsLand("{W}{W}{R}{B}{U}", "Plains", 1, WhiteManaAbility.class);
|
||||
|
||||
testManaToPayVsLand("{1}{R}", "Cavern of Souls", 2, 2); // can't auto choose to pay
|
||||
testManaToPayVsLand("{2}", "Cavern of Souls", 2, 2); // can't auto choose to pay
|
||||
testManaToPayVsLand("{1}{R}", "Cavern of Souls", 2, 2); // can't auto choose to pay
|
||||
testManaToPayVsLand("{2}", "Cavern of Souls", 2, 2); // can't auto choose to pay
|
||||
|
||||
testManaToPayVsLand("{2}", "Eldrazi Temple", 2, 2); // can't auto choose to pay
|
||||
|
||||
// hybrid mana
|
||||
testManaToPayVsLand("{W/R}{W/R}{W/R}", "Sacred Foundry", 2, 1); // auto choose for hybrid mana: choose any
|
||||
testManaToPayVsLand("{R}{W/R}", "Sacred Foundry", 2, RedManaAbility.class); // auto choose for hybrid mana: we should choose {R}
|
||||
testManaToPayVsLand("{G}{W/R}", "Sacred Foundry", 2, 1); // auto choose for hybrid mana: choose any
|
||||
testManaToPayVsLand("{G}{W/R}{W}", "Sacred Foundry", 2, WhiteManaAbility.class); // auto choose for hybrid mana: choose {W}
|
||||
testManaToPayVsLand("{W/B}{W/B}", "Swamp", 1, BlackManaAbility.class);
|
||||
testManaToPayVsLand("{W/R}{W/R}{W/R}", "Sacred Foundry", 2, 1); // auto choose for hybrid mana: choose any
|
||||
testManaToPayVsLand("{R}{W/R}", "Sacred Foundry", 2, RedManaAbility.class); // auto choose for hybrid mana: we should choose {R}
|
||||
testManaToPayVsLand("{G}{W/R}", "Sacred Foundry", 2, 1); // auto choose for hybrid mana: choose any
|
||||
testManaToPayVsLand("{G}{W/R}{W}", "Sacred Foundry", 2, WhiteManaAbility.class); // auto choose for hybrid mana: choose {W}
|
||||
testManaToPayVsLand("{W/B}{W/B}", "Swamp", 1, BlackManaAbility.class);
|
||||
|
||||
testManaToPayVsLand("{R}", "Glimmervoid", 1, 1);
|
||||
testManaToPayVsLand("{R}{1}", "Glimmervoid", 1, 1);
|
||||
testManaToPayVsLand("{R}", "Glimmervoid", 1, 1);
|
||||
testManaToPayVsLand("{R}{1}", "Glimmervoid", 1, 1);
|
||||
|
||||
// we can't auto choose here:
|
||||
// let say we auto choose {R}, then we have to use it to pay for {R} not {W/R} (as {W/R} is more generic cost)
|
||||
|
|
@ -75,100 +72,24 @@ public class ManaUtilTest extends CardTestPlayerBase {
|
|||
testManaToPayVsLand("{W/R}{R/G}", "Sacred Foundry", 2, 2); // can't auto choose to pay
|
||||
}
|
||||
|
||||
/**
|
||||
* Mana.condenseManaCostString is used to simplify the String representation of a mana cost to make it more readable.
|
||||
*/
|
||||
@Test
|
||||
public void testManaCondensing() {
|
||||
Assert.assertEquals("{5}{W}", ManaUtil.condenseManaCostString(("{1}{1}{1}{2}{W}")));
|
||||
Assert.assertEquals("{4}{B}{B}", ManaUtil.condenseManaCostString("{2}{B}{2}{B}"));
|
||||
Assert.assertEquals("{6}{R}{R}{R}{U}", ManaUtil.condenseManaCostString("{R}{1}{R}{2}{R}{3}{U}"));
|
||||
Assert.assertEquals("{5}{B}{U}{W}", ManaUtil.condenseManaCostString("{1}{B}{W}{4}{U}"));
|
||||
Assert.assertEquals("{8}{B}{G}{G}{U}", ManaUtil.condenseManaCostString("{1}{G}{1}{2}{3}{G}{B}{U}{1}"));
|
||||
Assert.assertEquals("{3}{R}{U}", ManaUtil.condenseManaCostString("{3}{R}{U}"));
|
||||
Assert.assertEquals("{10}", ManaUtil.condenseManaCostString("{1}{2}{3}{4}"));
|
||||
Assert.assertEquals("{B}{G}{R}{U}{W}", ManaUtil.condenseManaCostString("{B}{G}{R}{U}{W}"));
|
||||
Assert.assertEquals("{R}{R}", ManaUtil.condenseManaCostString("{R}{R}"));
|
||||
Assert.assertEquals("{U}", ManaUtil.condenseManaCostString("{U}"));
|
||||
Assert.assertEquals("{2}", ManaUtil.condenseManaCostString("{2}"));
|
||||
Assert.assertEquals("", ManaUtil.condenseManaCostString("{}"));
|
||||
Assert.assertEquals("{5}{C}{R}{R}{R}{U}", ManaUtil.condenseManaCostString("{R}{C}{R}{2}{R}{3}{U}"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Mana.enough is used to check if a spell can be cast with an given amount
|
||||
* of avalable mana
|
||||
*/
|
||||
@Test
|
||||
public void testManaEnough() {
|
||||
testManaAvailEnough("{G}", 1, "", true);
|
||||
testManaAvailEnough("{G}", 0, "{G}", true);
|
||||
testManaAvailEnough("{R}", 0, "{G}", false);
|
||||
testManaAvailEnough("{B}", 0, "{G}", false);
|
||||
testManaAvailEnough("{U}", 0, "{G}", false);
|
||||
testManaAvailEnough("{W}", 0, "{G}", false);
|
||||
|
||||
testManaAvailEnough("{R}", 1, "", true);
|
||||
testManaAvailEnough("{R}", 0, "{R}", true);
|
||||
testManaAvailEnough("{G}", 0, "{R}", false);
|
||||
testManaAvailEnough("{B}", 0, "{R}", false);
|
||||
testManaAvailEnough("{U}", 0, "{R}", false);
|
||||
testManaAvailEnough("{W}", 0, "{R}", false);
|
||||
|
||||
testManaAvailEnough("{U}{B}{W}{G}{R}", 4, "{R}", true);
|
||||
testManaAvailEnough("{U}{B}{W}{G}{R}", 3, "{R}{B}", true);
|
||||
|
||||
testManaAvailEnough("{U}{U}{U}{G}{G}{2}", 2, "{U}{U}{G}{R}{B}", true);
|
||||
|
||||
testManaAvailEnough("{2}{U}{U}", 0, "{U}{U}{U}{U}", true);
|
||||
testManaAvailEnough("{2}{U}{U}", 0, "{4}", false);
|
||||
testManaAvailEnough("{2}{U}{U}", 0, "{B}{B}{4}", false);
|
||||
|
||||
testManaAvailEnough("{G}", 0, "{G/W}", true);
|
||||
testManaAvailEnough("{G}{W}", 0, "{G/W}{G/W}", true);
|
||||
testManaAvailEnough("{W}{W}", 0, "{G/W}{G/W}", true);
|
||||
testManaAvailEnough("{G}{G}", 0, "{G/W}{G/W}", true);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Mana.enough is used to check if a spell can be cast with an given amount
|
||||
* of avalable mana
|
||||
*/
|
||||
@Test
|
||||
public void testManaIncrease() {
|
||||
// cost - reduction - rest
|
||||
testManaReduction("{G}{G}", "{G}", "{G}");
|
||||
testManaReduction("{1}{G}{G}", "{G}", "{1}{G}");
|
||||
testManaReduction("{B}{B}", "{B}", "{B}");
|
||||
testManaReduction("{1}{B}{B}", "{B}", "{1}{B}");
|
||||
testManaReduction("{W}{W}", "{W}", "{W}");
|
||||
testManaReduction("{1}{W}{W}", "{W}", "{1}{W}");
|
||||
testManaReduction("{U}{U}", "{U}", "{U}");
|
||||
testManaReduction("{1}{U}{U}", "{U}", "{1}{U}");
|
||||
testManaReduction("{R}{R}", "{R}", "{R}");
|
||||
testManaReduction("{1}{R}{R}", "{R}", "{1}{R}");
|
||||
|
||||
testManaReduction("{R}{G}{B}{U}{W}", "{R}{G}{B}{U}{W}", "{0}");
|
||||
|
||||
// Hybrid Mana
|
||||
testManaReduction("{2/B}{2/B}{2/B}", "{B}{B}", "{2/B}");
|
||||
testManaReduction("{2/B}{2/B}{2/B}", "{B}{B}{B}", "{0}");
|
||||
testManaReduction("{2/W}{2/W}{2/W}", "{W}{W}", "{2/W}");
|
||||
testManaReduction("{2/W}{2/W}{2/W}", "{W}{W}{W}", "{0}");
|
||||
|
||||
testManaReduction("{G/B}{G/B}{G/B}", "{B}{G}{B}", "{0}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a given mana reduction left the expected amount of mana costs
|
||||
*
|
||||
* @param manaCostsToPay
|
||||
* @param availablyAny
|
||||
* @param available
|
||||
* @param expected
|
||||
*/
|
||||
private void testManaReduction(String manaCostsToPay, String manaToReduce, String restMana) {
|
||||
SpellAbility spellAbility = new SpellAbility(new ManaCostsImpl(manaCostsToPay), "Test");
|
||||
CardUtil.adjustCost(spellAbility, new ManaCostsImpl(manaToReduce), true);
|
||||
Assert.assertTrue("The mana cost to pay " + manaCostsToPay + " reduced by " + manaToReduce + " should left " + restMana + " but the rest was " + spellAbility.getManaCostsToPay().getText(), spellAbility.getManaCostsToPay().getText().equals(restMana));
|
||||
Assert.assertEquals("{5}{W}", ManaUtil.condenseManaCostString("{1}{1}{1}{2}{W}"));
|
||||
Assert.assertEquals("{4}{B}{B}", ManaUtil.condenseManaCostString("{2}{B}{2}{B}"));
|
||||
Assert.assertEquals("{6}{R}{R}{R}{U}", ManaUtil.condenseManaCostString("{R}{1}{R}{2}{R}{3}{U}"));
|
||||
Assert.assertEquals("{5}{B}{U}{W}", ManaUtil.condenseManaCostString("{1}{B}{W}{4}{U}"));
|
||||
Assert.assertEquals("{8}{B}{G}{G}{U}", ManaUtil.condenseManaCostString("{1}{G}{1}{2}{3}{G}{B}{U}{1}"));
|
||||
Assert.assertEquals("{3}{R}{U}", ManaUtil.condenseManaCostString("{3}{R}{U}"));
|
||||
Assert.assertEquals("{10}", ManaUtil.condenseManaCostString("{1}{2}{3}{4}"));
|
||||
Assert.assertEquals("{B}{G}{R}{U}{W}", ManaUtil.condenseManaCostString("{B}{G}{R}{U}{W}"));
|
||||
Assert.assertEquals("{R}{R}", ManaUtil.condenseManaCostString("{R}{R}"));
|
||||
Assert.assertEquals("{U}", ManaUtil.condenseManaCostString("{U}"));
|
||||
Assert.assertEquals("{2}", ManaUtil.condenseManaCostString("{2}"));
|
||||
Assert.assertEquals("", ManaUtil.condenseManaCostString("{}"));
|
||||
Assert.assertEquals("{5}{C}{R}{R}{R}{U}", ManaUtil.condenseManaCostString("{R}{C}{R}{2}{R}{3}{U}"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -184,7 +105,7 @@ public class ManaUtilTest extends CardTestPlayerBase {
|
|||
* should be returned after optimization.
|
||||
*/
|
||||
private void testManaToPayVsLand(String manaToPay, String landName, int expected1, int expected2) {
|
||||
ManaCost unpaid = new ManaCostsImpl(manaToPay);
|
||||
ManaCost unpaid = new ManaCostsImpl<>(manaToPay);
|
||||
Card card = CardRepository.instance.findCard(landName).getCard();
|
||||
Assert.assertNotNull(card);
|
||||
|
||||
|
|
@ -206,13 +127,13 @@ public class ManaUtilTest extends CardTestPlayerBase {
|
|||
* We get all mana abilities, then try to auto pay and compare to expected1
|
||||
* and expected2 params.
|
||||
*
|
||||
* @param manaToPay Mana that should be paid using land.
|
||||
* @param landName Land to use as mana producer.
|
||||
* @param expected1 The amount of mana abilities the land should have.
|
||||
* @param expectedChosen
|
||||
* @param manaToPay Mana that should be paid using land.
|
||||
* @param landName Land to use as mana producer.
|
||||
* @param expected1 The amount of mana abilities the land should have.
|
||||
* @param expectedChosen The mana ability expected to be chosen.
|
||||
*/
|
||||
private void testManaToPayVsLand(String manaToPay, String landName, int expected1, Class<? extends BasicManaAbility> expectedChosen) {
|
||||
ManaCost unpaid = new ManaCostsImpl(manaToPay);
|
||||
ManaCost unpaid = new ManaCostsImpl<>(manaToPay);
|
||||
Card card = CardRepository.instance.findCard(landName).getCard();
|
||||
Assert.assertNotNull(card);
|
||||
|
||||
|
|
@ -225,31 +146,11 @@ public class ManaUtilTest extends CardTestPlayerBase {
|
|||
Assert.assertTrue("Wrong mana ability has been chosen", expectedChosen.isInstance(ability));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given available Mana is enough to pay a given mana cost
|
||||
*
|
||||
* @param manaCostsToPay
|
||||
* @param availablyAny
|
||||
* @param available
|
||||
* @param expected
|
||||
*/
|
||||
private void testManaAvailEnough(String manaCostsToPay, int availablyAny, String available, boolean expected) {
|
||||
ManaCost unpaid = new ManaCostsImpl(manaCostsToPay);
|
||||
ManaCost costAvailable = new ManaCostsImpl(available);
|
||||
Mana manaAvailable = costAvailable.getMana();
|
||||
manaAvailable.setAny(availablyAny);
|
||||
if (expected) {
|
||||
Assert.assertTrue("The available Mana " + costAvailable.getText() + " should be enough to pay the costs " + unpaid.getText(), unpaid.getMana().enough(manaAvailable));
|
||||
} else {
|
||||
Assert.assertFalse("The available Mana " + costAvailable.getText() + " shouldn't be enough to pay the costs " + unpaid.getText(), unpaid.getMana().enough(manaAvailable));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts mana abilities from the card.
|
||||
*
|
||||
* @param card Card to extract mana abilities from.
|
||||
* @return
|
||||
* @param card Card to extract mana abilities from.
|
||||
* @return Map between the UUID of each ability on the card and the ability.
|
||||
*/
|
||||
private Map<UUID, ActivatedManaAbilityImpl> getManaAbilities(Card card) {
|
||||
Map<UUID, ActivatedManaAbilityImpl> useableAbilities = new LinkedHashMap<>();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue