diff --git a/Mage.Sets/src/mage/sets/magicorigins/MageRingNetwork.java b/Mage.Sets/src/mage/sets/magicorigins/MageRingNetwork.java index 6ee273ea26..fe953e08e6 100644 --- a/Mage.Sets/src/mage/sets/magicorigins/MageRingNetwork.java +++ b/Mage.Sets/src/mage/sets/magicorigins/MageRingNetwork.java @@ -34,6 +34,7 @@ import mage.abilities.common.SimpleActivatedAbility; import mage.abilities.costs.common.RemoveVariableCountersSourceCost; import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.mana.ManaCostsImpl; +import mage.abilities.dynamicvalue.common.CountersCount; import mage.abilities.dynamicvalue.common.RemovedCountersForCostValue; import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.mana.ColorlessManaAbility; @@ -47,7 +48,7 @@ import mage.counters.CounterType; /** * * @author LoneFox - + * */ public class MageRingNetwork extends CardImpl { @@ -55,17 +56,22 @@ public class MageRingNetwork extends CardImpl { super(ownerId, 249, "Mage-Ring Network", Rarity.UNCOMMON, new CardType[]{CardType.LAND}, ""); this.expansionSetCode = "ORI"; - // {t}: Add {1} to your mana pool. + // {T}: Add {1} to your mana pool. this.addAbility(new ColorlessManaAbility()); - // {1}, {t}: Put a storage counter on Mage-Ring Network. + // {1}, {T}: Put a storage counter on Mage-Ring Network. Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.STORAGE.createInstance()), - new ManaCostsImpl("{1}")); + new ManaCostsImpl("{1}")); ability.addCost(new TapSourceCost()); this.addAbility(ability); - // {t}, Remove X storage counters from Mage-Ring Network: Add {x} to your mana pool. - ability = new DynamicManaAbility(Mana.ColorlessMana, new RemovedCountersForCostValue(), "Add {X} to your mana pool"); + // {T}, Remove X storage counters from Mage-Ring Network: Add {x} to your mana pool. + ability = new DynamicManaAbility( + Mana.ColorlessMana, + new RemovedCountersForCostValue(), + new TapSourceCost(), + "Add {X} to your mana pool", + true, new CountersCount(CounterType.STORAGE)); ability.addCost(new RemoveVariableCountersSourceCost(CounterType.STORAGE.createInstance(), - "Remove X storage counters from {this}")); + "Remove X storage counters from {this}")); this.addAbility(ability); } diff --git a/Mage.Tests/src/test/java/org/mage/test/utils/ManaOptionsTest.java b/Mage.Tests/src/test/java/org/mage/test/utils/ManaOptionsTest.java index b4b40dd99e..2f0af102cb 100644 --- a/Mage.Tests/src/test/java/org/mage/test/utils/ManaOptionsTest.java +++ b/Mage.Tests/src/test/java/org/mage/test/utils/ManaOptionsTest.java @@ -30,6 +30,7 @@ package org.mage.test.utils; import mage.abilities.mana.ManaOptions; import mage.constants.PhaseStep; import mage.constants.Zone; +import mage.counters.CounterType; import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; @@ -290,6 +291,43 @@ public class ManaOptionsTest extends CardTestPlayerBase { Assert.assertEquals("{B}{B}{B}", getManaOption(1, manaOptions)); } + @Test + public void testMageRingNetwork() { + // {T}: Add {1} to your mana pool. + // {T}, {1} : Put a storage counter on Mage-Ring Network. + // {T}, Remove X storage counters from Mage-Ring Network: Add {X} to your mana pool. + addCard(Zone.BATTLEFIELD, playerA, "Mage-Ring Network", 1); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 1); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1); + + setStopAt(1, PhaseStep.UPKEEP); + execute(); + + ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame); + + Assert.assertEquals("mana variations don't fit", 1, manaOptions.size()); + Assert.assertEquals("{1}{W}{B}", getManaOption(0, manaOptions)); + } + + @Test + public void testMageRingNetwork2() { + // {T}: Add {1} to your mana pool. + // {T}, {1} : Put a storage counter on Mage-Ring Network. + // {T}, Remove X storage counters from Mage-Ring Network: Add {X} to your mana pool. + addCard(Zone.BATTLEFIELD, playerA, "Mage-Ring Network", 1); + addCounters(1, PhaseStep.UPKEEP, playerA, "Mage-Ring Network", CounterType.STORAGE, 4); + addCard(Zone.BATTLEFIELD, playerA, "Plains", 1); + addCard(Zone.BATTLEFIELD, playerA, "Swamp", 1); + + setStopAt(1, PhaseStep.DRAW); + execute(); + + ManaOptions manaOptions = playerA.getAvailableManaTest(currentGame); + + Assert.assertEquals("mana variations don't fit", 1, manaOptions.size()); + Assert.assertEquals("{4}{W}{B}", getManaOption(0, manaOptions)); + } + @Test @Ignore // TriggeredManaAbilities not supported yet for getAvailableMana public void testCryptGhast() { diff --git a/Mage/src/mage/Mana.java b/Mage/src/mage/Mana.java index e24700d45d..b9b3e04c8f 100644 --- a/Mage/src/mage/Mana.java +++ b/Mage/src/mage/Mana.java @@ -597,10 +597,11 @@ public class Mana implements Comparable, Serializable, Copyable { } /** - * Returns the mana that is more colored but does not contain one less mana - * in any color but colorless if you call with {1}{W}{R} and {G}{W}{R} you - * get back {G}{W}{R} if you call with {G}{W}{R} and {G}{W}{R} you get back - * {G}{W}{R} if you call with {G}{W}{B} and {G}{W}{R} you get back null + * Returns the mana that is more colored or has a greater amount but does + * not contain one less mana in any color but colorless if you call with + * {1}{W}{R} and {G}{W}{R} you get back {G}{W}{R} if you call with {G}{W}{R} + * and {G}{W}{R} you get back {G}{W}{R} if you call with {G}{W}{B} and + * {G}{W}{R} you get back null * * @param mana1 * @param mana2 @@ -609,7 +610,7 @@ public class Mana implements Comparable, Serializable, Copyable { public static Mana getMoreValuableMana(Mana mana1, Mana mana2) { Mana moreMana; Mana lessMana; - if (mana2.count() > mana1.count() || mana2.getAny() > mana1.getAny() || mana2.getColorless() < mana1.getColorless()) { + if (mana2.countColored() > mana1.countColored() || mana2.getAny() > mana1.getAny() || mana2.count() > mana1.count()) { moreMana = mana2; lessMana = mana1; } else { diff --git a/Mage/src/mage/abilities/dynamicvalue/common/CountersCount.java b/Mage/src/mage/abilities/dynamicvalue/common/CountersCount.java index fd0e392619..9f6a5312a6 100644 --- a/Mage/src/mage/abilities/dynamicvalue/common/CountersCount.java +++ b/Mage/src/mage/abilities/dynamicvalue/common/CountersCount.java @@ -1,15 +1,14 @@ package mage.abilities.dynamicvalue.common; -import mage.MageObject; import mage.abilities.Ability; import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.effects.Effect; -import mage.constants.Zone; import mage.counters.CounterType; import mage.game.Game; import mage.game.permanent.Permanent; public class CountersCount implements DynamicValue { + private final CounterType counter; public CountersCount(CounterType counter) { diff --git a/Mage/src/mage/abilities/effects/common/DynamicManaEffect.java b/Mage/src/mage/abilities/effects/common/DynamicManaEffect.java index 7747f36075..80df2007eb 100644 --- a/Mage/src/mage/abilities/effects/common/DynamicManaEffect.java +++ b/Mage/src/mage/abilities/effects/common/DynamicManaEffect.java @@ -44,32 +44,39 @@ public class DynamicManaEffect extends BasicManaEffect { private final Mana computedMana; private final DynamicValue amount; + private final DynamicValue netAmount; private String text = null; private boolean oneChoice; public DynamicManaEffect(Mana mana, DynamicValue amount) { - super(mana); - this.amount = amount; - computedMana = new Mana(); + this(mana, amount, null); } public DynamicManaEffect(Mana mana, DynamicValue amount, String text) { this(mana, amount, text, false); } + public DynamicManaEffect(Mana mana, DynamicValue amount, String text, boolean oneChoice) { + this(mana, amount, text, oneChoice, null); + } + /** * * @param mana * @param amount * @param text - * @param oneChoice is all mana from the same colour or if false the player can choose different colours + * @param oneChoice is all mana from the same colour or if false the player + * can choose different colours + * @param netAmount a dynamic value that calculates the possible available + * mana (e.g. if you have to pay by removing counters from source) */ - public DynamicManaEffect(Mana mana, DynamicValue amount, String text, boolean oneChoice) { + public DynamicManaEffect(Mana mana, DynamicValue amount, String text, boolean oneChoice, DynamicValue netAmount) { super(mana); this.amount = amount; computedMana = new Mana(); this.text = text; this.oneChoice = oneChoice; + this.netAmount = netAmount; } public DynamicManaEffect(final DynamicManaEffect effect) { @@ -78,6 +85,11 @@ public class DynamicManaEffect extends BasicManaEffect { this.amount = effect.amount.copy(); this.text = effect.text; this.oneChoice = effect.oneChoice; + if (effect.netAmount != null) { + this.netAmount = effect.netAmount.copy(); + } else { + this.netAmount = null; + } } @Override @@ -106,9 +118,16 @@ public class DynamicManaEffect extends BasicManaEffect { return null; } - public Mana computeMana(boolean netMana ,Game game, Ability source){ + public Mana computeMana(boolean netMana, Game game, Ability source) { this.computedMana.clear(); - int count = amount.calculate(game, source, this); + int count; + if (netMana && netAmount != null) { + // calculate the maximum available mana + count = netAmount.calculate(game, source, this); + } else { + count = amount.calculate(game, source, this); + } + if (mana.getBlack() > 0) { computedMana.setBlack(count); } else if (mana.getBlue() > 0) { @@ -126,7 +145,7 @@ public class DynamicManaEffect extends BasicManaEffect { Player controller = game.getPlayer(source.getControllerId()); if (controller != null) { ChoiceColor choiceColor = new ChoiceColor(); - for(int i = 0; i < count; i++){ + for (int i = 0; i < count; i++) { if (!choiceColor.isChosen()) { while (!controller.choose(Outcome.Benefit, choiceColor, game)) { if (!controller.isInGame()) { @@ -150,7 +169,7 @@ public class DynamicManaEffect extends BasicManaEffect { } } } - } + } } else { computedMana.setColorless(count); } diff --git a/Mage/src/mage/abilities/mana/DynamicManaAbility.java b/Mage/src/mage/abilities/mana/DynamicManaAbility.java index 72336b74e0..15a44b71c3 100644 --- a/Mage/src/mage/abilities/mana/DynamicManaAbility.java +++ b/Mage/src/mage/abilities/mana/DynamicManaAbility.java @@ -48,6 +48,7 @@ public class DynamicManaAbility extends ManaAbility { /** * TapSourceCost added by default + * * @param mana * @param amount */ @@ -74,10 +75,24 @@ public class DynamicManaAbility extends ManaAbility { } public DynamicManaAbility(Mana mana, DynamicValue amount, Cost cost, String text, boolean oneChoice) { - super(Zone.BATTLEFIELD, new DynamicManaEffect(mana, amount, text, oneChoice), cost); - manaEffect = (DynamicManaEffect) this.getEffects().get(0); + this(mana, amount, cost, text, oneChoice, null); } + /** + * + * @param mana + * @param amount + * @param cost + * @param text + * @param oneChoice is all mana from the same colour or if false the player + * can choose different colours + * @param netAmount a dynamic value that calculates the possible available + * mana (e.g. if you have to pay by removing counters from source) + */ + public DynamicManaAbility(Mana mana, DynamicValue amount, Cost cost, String text, boolean oneChoice, DynamicValue netAmount) { + super(Zone.BATTLEFIELD, new DynamicManaEffect(mana, amount, text, oneChoice, netAmount), cost); + manaEffect = (DynamicManaEffect) this.getEffects().get(0); + } public DynamicManaAbility(final DynamicManaAbility ability) { super(ability); @@ -95,8 +110,9 @@ public class DynamicManaAbility extends ManaAbility { List newNetMana = new ArrayList<>(); if (game != null) { // TODO: effects from replacement effects like Mana Reflection are not considered yet + // TODO: effects that need a X payment (e.g. Mage-Ring Network) return always 0 newNetMana.add(manaEffect.computeMana(true, game, this)); - } - return newNetMana; + } + return newNetMana; } } diff --git a/Mage/src/mage/abilities/mana/ManaOptions.java b/Mage/src/mage/abilities/mana/ManaOptions.java index 4965a650b1..bb5977e813 100644 --- a/Mage/src/mage/abilities/mana/ManaOptions.java +++ b/Mage/src/mage/abilities/mana/ManaOptions.java @@ -95,7 +95,7 @@ public class ManaOptions extends ArrayList { Mana moreValuable = Mana.getMoreValuableMana(newMana, existingMana); if (moreValuable != null) { // only keep the more valuable mana - existingMana.setToMana(newMana); + existingMana.setToMana(moreValuable); continue SkipAddMana; } } diff --git a/Mage/src/mage/players/PlayerImpl.java b/Mage/src/mage/players/PlayerImpl.java index a285cde583..0bc26e40f1 100644 --- a/Mage/src/mage/players/PlayerImpl.java +++ b/Mage/src/mage/players/PlayerImpl.java @@ -2164,7 +2164,7 @@ public abstract class PlayerImpl implements Player, Serializable { public ManaOptions getManaAvailable(Game game) { ManaOptions available = new ManaOptions(); - List> sourceWithoutCosts = new ArrayList<>(); + List> sourceWithoutManaCosts = new ArrayList<>(); List> sourceWithCosts = new ArrayList<>(); for (Permanent permanent : game.getBattlefield().getAllActivePermanents(playerId)) { boolean canAdd = false; @@ -2183,12 +2183,12 @@ public abstract class PlayerImpl implements Player, Serializable { if (withCost) { sourceWithCosts.add(manaAbilities); } else { - sourceWithoutCosts.add(manaAbilities); + sourceWithoutManaCosts.add(manaAbilities); } } } - for (Abilities manaAbilities : sourceWithoutCosts) { + for (Abilities manaAbilities : sourceWithoutManaCosts) { available.addMana(manaAbilities, game); } for (Abilities manaAbilities : sourceWithCosts) {