* Mage-Ring Network - Fixed calculation of available mana.

This commit is contained in:
LevelX2 2015-07-23 12:42:02 +02:00
parent 363915075c
commit b169e7e6c7
8 changed files with 110 additions and 31 deletions

View file

@ -34,6 +34,7 @@ import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.RemoveVariableCountersSourceCost; import mage.abilities.costs.common.RemoveVariableCountersSourceCost;
import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.dynamicvalue.common.CountersCount;
import mage.abilities.dynamicvalue.common.RemovedCountersForCostValue; import mage.abilities.dynamicvalue.common.RemovedCountersForCostValue;
import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.effects.common.counter.AddCountersSourceEffect;
import mage.abilities.mana.ColorlessManaAbility; import mage.abilities.mana.ColorlessManaAbility;
@ -47,7 +48,7 @@ import mage.counters.CounterType;
/** /**
* *
* @author LoneFox * @author LoneFox
*
*/ */
public class MageRingNetwork extends CardImpl { 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}, ""); super(ownerId, 249, "Mage-Ring Network", Rarity.UNCOMMON, new CardType[]{CardType.LAND}, "");
this.expansionSetCode = "ORI"; this.expansionSetCode = "ORI";
// {t}: Add {1} to your mana pool. // {T}: Add {1} to your mana pool.
this.addAbility(new ColorlessManaAbility()); 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()), Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new AddCountersSourceEffect(CounterType.STORAGE.createInstance()),
new ManaCostsImpl("{1}")); new ManaCostsImpl("{1}"));
ability.addCost(new TapSourceCost()); ability.addCost(new TapSourceCost());
this.addAbility(ability); this.addAbility(ability);
// {t}, Remove X storage counters from Mage-Ring Network: 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(), "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(), ability.addCost(new RemoveVariableCountersSourceCost(CounterType.STORAGE.createInstance(),
"Remove X storage counters from {this}")); "Remove X storage counters from {this}"));
this.addAbility(ability); this.addAbility(ability);
} }

View file

@ -30,6 +30,7 @@ package org.mage.test.utils;
import mage.abilities.mana.ManaOptions; import mage.abilities.mana.ManaOptions;
import mage.constants.PhaseStep; import mage.constants.PhaseStep;
import mage.constants.Zone; import mage.constants.Zone;
import mage.counters.CounterType;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
@ -290,6 +291,43 @@ public class ManaOptionsTest extends CardTestPlayerBase {
Assert.assertEquals("{B}{B}{B}", getManaOption(1, manaOptions)); 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 @Test
@Ignore // TriggeredManaAbilities not supported yet for getAvailableMana @Ignore // TriggeredManaAbilities not supported yet for getAvailableMana
public void testCryptGhast() { public void testCryptGhast() {

View file

@ -597,10 +597,11 @@ public class Mana implements Comparable<Mana>, Serializable, Copyable<Mana> {
} }
/** /**
* Returns the mana that is more colored but does not contain one less mana * Returns the mana that is more colored or has a greater amount but does
* in any color but colorless if you call with {1}{W}{R} and {G}{W}{R} you * not contain one less mana in any color but colorless if you call with
* get back {G}{W}{R} if you call with {G}{W}{R} and {G}{W}{R} you get back * {1}{W}{R} and {G}{W}{R} you get back {G}{W}{R} if you call with {G}{W}{R}
* {G}{W}{R} if you call with {G}{W}{B} and {G}{W}{R} you get back null * 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 mana1
* @param mana2 * @param mana2
@ -609,7 +610,7 @@ public class Mana implements Comparable<Mana>, Serializable, Copyable<Mana> {
public static Mana getMoreValuableMana(Mana mana1, Mana mana2) { public static Mana getMoreValuableMana(Mana mana1, Mana mana2) {
Mana moreMana; Mana moreMana;
Mana lessMana; 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; moreMana = mana2;
lessMana = mana1; lessMana = mana1;
} else { } else {

View file

@ -1,15 +1,14 @@
package mage.abilities.dynamicvalue.common; package mage.abilities.dynamicvalue.common;
import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.Effect; import mage.abilities.effects.Effect;
import mage.constants.Zone;
import mage.counters.CounterType; import mage.counters.CounterType;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
public class CountersCount implements DynamicValue { public class CountersCount implements DynamicValue {
private final CounterType counter; private final CounterType counter;
public CountersCount(CounterType counter) { public CountersCount(CounterType counter) {

View file

@ -44,32 +44,39 @@ public class DynamicManaEffect extends BasicManaEffect {
private final Mana computedMana; private final Mana computedMana;
private final DynamicValue amount; private final DynamicValue amount;
private final DynamicValue netAmount;
private String text = null; private String text = null;
private boolean oneChoice; private boolean oneChoice;
public DynamicManaEffect(Mana mana, DynamicValue amount) { public DynamicManaEffect(Mana mana, DynamicValue amount) {
super(mana); this(mana, amount, null);
this.amount = amount;
computedMana = new Mana();
} }
public DynamicManaEffect(Mana mana, DynamicValue amount, String text) { public DynamicManaEffect(Mana mana, DynamicValue amount, String text) {
this(mana, amount, text, false); this(mana, amount, text, false);
} }
public DynamicManaEffect(Mana mana, DynamicValue amount, String text, boolean oneChoice) {
this(mana, amount, text, oneChoice, null);
}
/** /**
* *
* @param mana * @param mana
* @param amount * @param amount
* @param text * @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); super(mana);
this.amount = amount; this.amount = amount;
computedMana = new Mana(); computedMana = new Mana();
this.text = text; this.text = text;
this.oneChoice = oneChoice; this.oneChoice = oneChoice;
this.netAmount = netAmount;
} }
public DynamicManaEffect(final DynamicManaEffect effect) { public DynamicManaEffect(final DynamicManaEffect effect) {
@ -78,6 +85,11 @@ public class DynamicManaEffect extends BasicManaEffect {
this.amount = effect.amount.copy(); this.amount = effect.amount.copy();
this.text = effect.text; this.text = effect.text;
this.oneChoice = effect.oneChoice; this.oneChoice = effect.oneChoice;
if (effect.netAmount != null) {
this.netAmount = effect.netAmount.copy();
} else {
this.netAmount = null;
}
} }
@Override @Override
@ -106,9 +118,16 @@ public class DynamicManaEffect extends BasicManaEffect {
return null; return null;
} }
public Mana computeMana(boolean netMana ,Game game, Ability source){ public Mana computeMana(boolean netMana, Game game, Ability source) {
this.computedMana.clear(); 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) { if (mana.getBlack() > 0) {
computedMana.setBlack(count); computedMana.setBlack(count);
} else if (mana.getBlue() > 0) { } else if (mana.getBlue() > 0) {
@ -126,7 +145,7 @@ public class DynamicManaEffect extends BasicManaEffect {
Player controller = game.getPlayer(source.getControllerId()); Player controller = game.getPlayer(source.getControllerId());
if (controller != null) { if (controller != null) {
ChoiceColor choiceColor = new ChoiceColor(); ChoiceColor choiceColor = new ChoiceColor();
for(int i = 0; i < count; i++){ for (int i = 0; i < count; i++) {
if (!choiceColor.isChosen()) { if (!choiceColor.isChosen()) {
while (!controller.choose(Outcome.Benefit, choiceColor, game)) { while (!controller.choose(Outcome.Benefit, choiceColor, game)) {
if (!controller.isInGame()) { if (!controller.isInGame()) {
@ -150,7 +169,7 @@ public class DynamicManaEffect extends BasicManaEffect {
} }
} }
} }
} }
} else { } else {
computedMana.setColorless(count); computedMana.setColorless(count);
} }

View file

@ -48,6 +48,7 @@ public class DynamicManaAbility extends ManaAbility {
/** /**
* TapSourceCost added by default * TapSourceCost added by default
*
* @param mana * @param mana
* @param amount * @param amount
*/ */
@ -74,10 +75,24 @@ public class DynamicManaAbility extends ManaAbility {
} }
public DynamicManaAbility(Mana mana, DynamicValue amount, Cost cost, String text, boolean oneChoice) { public DynamicManaAbility(Mana mana, DynamicValue amount, Cost cost, String text, boolean oneChoice) {
super(Zone.BATTLEFIELD, new DynamicManaEffect(mana, amount, text, oneChoice), cost); this(mana, amount, cost, text, oneChoice, null);
manaEffect = (DynamicManaEffect) this.getEffects().get(0);
} }
/**
*
* @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) { public DynamicManaAbility(final DynamicManaAbility ability) {
super(ability); super(ability);
@ -95,8 +110,9 @@ public class DynamicManaAbility extends ManaAbility {
List<Mana> newNetMana = new ArrayList<>(); List<Mana> newNetMana = new ArrayList<>();
if (game != null) { if (game != null) {
// TODO: effects from replacement effects like Mana Reflection are not considered yet // 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)); newNetMana.add(manaEffect.computeMana(true, game, this));
} }
return newNetMana; return newNetMana;
} }
} }

View file

@ -95,7 +95,7 @@ public class ManaOptions extends ArrayList<Mana> {
Mana moreValuable = Mana.getMoreValuableMana(newMana, existingMana); Mana moreValuable = Mana.getMoreValuableMana(newMana, existingMana);
if (moreValuable != null) { if (moreValuable != null) {
// only keep the more valuable mana // only keep the more valuable mana
existingMana.setToMana(newMana); existingMana.setToMana(moreValuable);
continue SkipAddMana; continue SkipAddMana;
} }
} }

View file

@ -2164,7 +2164,7 @@ public abstract class PlayerImpl implements Player, Serializable {
public ManaOptions getManaAvailable(Game game) { public ManaOptions getManaAvailable(Game game) {
ManaOptions available = new ManaOptions(); ManaOptions available = new ManaOptions();
List<Abilities<ManaAbility>> sourceWithoutCosts = new ArrayList<>(); List<Abilities<ManaAbility>> sourceWithoutManaCosts = new ArrayList<>();
List<Abilities<ManaAbility>> sourceWithCosts = new ArrayList<>(); List<Abilities<ManaAbility>> sourceWithCosts = new ArrayList<>();
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(playerId)) { for (Permanent permanent : game.getBattlefield().getAllActivePermanents(playerId)) {
boolean canAdd = false; boolean canAdd = false;
@ -2183,12 +2183,12 @@ public abstract class PlayerImpl implements Player, Serializable {
if (withCost) { if (withCost) {
sourceWithCosts.add(manaAbilities); sourceWithCosts.add(manaAbilities);
} else { } else {
sourceWithoutCosts.add(manaAbilities); sourceWithoutManaCosts.add(manaAbilities);
} }
} }
} }
for (Abilities<ManaAbility> manaAbilities : sourceWithoutCosts) { for (Abilities<ManaAbility> manaAbilities : sourceWithoutManaCosts) {
available.addMana(manaAbilities, game); available.addMana(manaAbilities, game);
} }
for (Abilities<ManaAbility> manaAbilities : sourceWithCosts) { for (Abilities<ManaAbility> manaAbilities : sourceWithCosts) {