diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/asthough/SpendOtherManaTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/asthough/SpendOtherManaTest.java index 3176f1d128..a25c1ea544 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/asthough/SpendOtherManaTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/asthough/SpendOtherManaTest.java @@ -2,6 +2,7 @@ package org.mage.test.cards.asthough; import mage.constants.PhaseStep; import mage.constants.Zone; +import org.junit.Assert; import org.junit.Test; import org.mage.test.serverside.base.CardTestPlayerBase; @@ -200,4 +201,60 @@ public class SpendOtherManaTest extends CardTestPlayerBase { assertLife(playerA, 20); assertLife(playerB, 20 - 1); } + + /** + * Chromatic Orrery allows it's controller to spend mana of any color as + * though it were mana of any color. With mana from Food Chain I should be + * able to cast creature spells using abritrary color of mana. But the game + * still requires to pay appropriate color as though there was no Orrery on + * my side of battlefield. + */ + @Test + public void testFoodChainWithChromaticOrrery() { + setStrictChooseMode(true); + addCard(Zone.HAND, playerA, "Adriana, Captain of the Guard", 1); // Creature {3}{R}{W} + + addCard(Zone.BATTLEFIELD, playerA, "Pillarfield Ox", 1); // Creature {3}{W} + + // Exile a creature you control: Add X mana of any one color, where X is the exiled creature's converted mana cost plus one. + // Spend this mana only to cast creature spells. + addCard(Zone.BATTLEFIELD, playerA, "Food Chain"); // Enchantment {2}{G} + + // You may spend mana as though it were mana of any color. + // {T}: Add {C}{C}{C}{C}{C}. + // {5}, {T}: Draw a card for each color among permanents you control. + addCard(Zone.BATTLEFIELD, playerA, "Chromatic Orrery"); // Artifact {7} + activateAbility(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Exile a creature you control"); + setChoice(playerA, "Pillarfield Ox"); + setChoice(playerA, "Red"); + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Adriana, Captain of the Guard"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + assertAllCommandsUsed(); + + Assert.assertTrue("Mana pool of conditional mana has to be empty", playerA.getManaPool().getConditionalMana().isEmpty()); + assertExileCount("Pillarfield Ox", 1); + assertPermanentCount(playerA, "Adriana, Captain of the Guard", 1); + } + + @Test + public void testChromaticOrrery() { + setStrictChooseMode(true); + addCard(Zone.HAND, playerA, "Adriana, Captain of the Guard", 1); // Creature {3}{R}{W} + + // You may spend mana as though it were mana of any color. + // {T}: Add {C}{C}{C}{C}{C}. + // {5}, {T}: Draw a card for each color among permanents you control. + addCard(Zone.BATTLEFIELD, playerA, "Chromatic Orrery"); // Artifact {7} + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Adriana, Captain of the Guard"); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + assertAllCommandsUsed(); + + assertPermanentCount(playerA, "Adriana, Captain of the Guard", 1); + } } diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/mana/TappedForManaRelatedTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/mana/TappedForManaRelatedTest.java index 4f5447c688..ecbe7ca846 100644 --- a/Mage.Tests/src/test/java/org/mage/test/cards/mana/TappedForManaRelatedTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/cards/mana/TappedForManaRelatedTest.java @@ -296,4 +296,22 @@ public class TappedForManaRelatedTest extends CardTestPlayerBase { Assert.assertEquals("mana variations don't fit", 1, manaOptions.size()); assertManaOptions("{B}{B}{Any}{Any}{Any}{Any}", manaOptions); } + + @Test + public void TestChromaticOrrery() { + setStrictChooseMode(true); + // You may spend mana as though it were mana of any color. + // {T}: Add {C}{C}{C}{C}{C}. + // {5}, {T}: Draw a card for each color among permanents you control. + addCard(Zone.BATTLEFIELD, playerA, "Chromatic Orrery", 1); + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertAllCommandsUsed(); + + ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame); + Assert.assertEquals("mana variations don't fit", 1, manaOptions.size()); + assertManaOptions("{C}{C}{C}{C}{C}", manaOptions); + } } diff --git a/Mage/src/main/java/mage/players/ManaPool.java b/Mage/src/main/java/mage/players/ManaPool.java index 334c698eed..c0178f702f 100644 --- a/Mage/src/main/java/mage/players/ManaPool.java +++ b/Mage/src/main/java/mage/players/ManaPool.java @@ -88,15 +88,14 @@ public class ManaPool implements Serializable { * @return */ public boolean pay(ManaType manaType, Ability ability, Filter filter, Game game, Cost costToPay, Mana usedManaToPay) { - if (!isAutoPayment() - && manaType != unlockedManaType) { + if (!isAutoPayment() && manaType != unlockedManaType) { // if manual payment and the needed mana type was not unlocked, nothing will be paid return false; } ManaType possibleAsThoughPoolManaType = null; if (isAutoPayment() && isAutoPaymentRestricted() - && !wasManaAddedBeyondStock() + && !wasManaAddedBeyondStock() // was not more mana added than at the start of casting something && manaType != unlockedManaType) { // if automatic restricted payment and there is already mana in the pool // and the needed mana type was not unlocked, nothing will be paid @@ -111,9 +110,10 @@ public class ManaPool implements Serializable { return false; // if it's not possible return } } - - if (getConditional(manaType, ability, filter, game, costToPay) > 0) { - removeConditional(manaType, ability, game, costToPay, usedManaToPay); + // first try to pay from conditional mana (the returned manaType can be changed if AsThoughEffects are active) + ManaType conditionalManaType = getConditional(manaType, ability, filter, game, costToPay, possibleAsThoughPoolManaType); + if (conditionalManaType != null) { + removeConditional(conditionalManaType, ability, game, costToPay, usedManaToPay); lockManaType(); // pay only one mana if mana payment is set to manually return true; } @@ -160,21 +160,33 @@ public class ManaPool implements Serializable { return getMana().get(manaType); } - private int getConditional(ManaType manaType, Ability ability, Filter filter, Game game, Cost costToPay) { + private ManaType getConditional(ManaType manaType, Ability ability, Filter filter, Game game, Cost costToPay, ManaType possibleAsThoughPoolManaType) { if (ability == null || getConditionalMana().isEmpty()) { - return 0; + return null; } for (ManaPoolItem mana : manaItems) { - if (mana.isConditional() - && mana.getConditionalMana().get(manaType) > 0 - && mana.getConditionalMana().apply(ability, game, mana.getSourceId(), costToPay)) { - if (filter == null - || filter.match(mana.getSourceObject(), game)) { - return mana.getConditionalMana().get(manaType); + if (mana.isConditional()) { + ManaType manaTypeToUse = null; + if (mana.getConditionalMana().get(manaType) > 0) { + manaTypeToUse = manaType; + } else { + if (possibleAsThoughPoolManaType == null) { + possibleAsThoughPoolManaType = game.getContinuousEffects().asThoughMana(manaType, mana, ability.getSourceId(), ability, ability.getControllerId(), game); + } + if (possibleAsThoughPoolManaType != null && mana.getConditionalMana().get(possibleAsThoughPoolManaType) > 0) { + manaTypeToUse = possibleAsThoughPoolManaType; + } + } + if (manaTypeToUse != null && mana.getConditionalMana().apply(ability, game, mana.getSourceId(), costToPay)) { + if (filter == null + || filter.match(mana.getSourceObject(), game)) { + return manaTypeToUse; + } } } } - return 0; + + return null; } public int getConditionalCount(Ability ability, Game game, FilterMana filter, Cost costToPay) { diff --git a/Mage/src/main/java/mage/players/ManaPoolItem.java b/Mage/src/main/java/mage/players/ManaPoolItem.java index 34db510c20..b694bbe852 100644 --- a/Mage/src/main/java/mage/players/ManaPoolItem.java +++ b/Mage/src/main/java/mage/players/ManaPoolItem.java @@ -1,4 +1,3 @@ - package mage.players; import java.io.Serializable; @@ -205,6 +204,21 @@ public class ManaPoolItem implements Serializable { } else if (colorless > 0) { return ManaType.COLORLESS; } + if (conditionalMana != null) { + if (conditionalMana.getBlack() > 0) { + return ManaType.BLACK; + } else if (conditionalMana.getBlue() > 0) { + return ManaType.BLUE; + } else if (conditionalMana.getGreen() > 0) { + return ManaType.GREEN; + } else if (conditionalMana.getRed() > 0) { + return ManaType.RED; + } else if (conditionalMana.getWhite() > 0) { + return ManaType.WHITE; + } else if (conditionalMana.getColorless() > 0) { + return ManaType.COLORLESS; + } + } return null; }