* Added getProducableManaTypes method for mana effects to handle Squandered Resources or Reflecting Pool like abilities.

* Fixes to Soldevi Adnate, Skirge Familiar, Mana Web.
This commit is contained in:
LevelX2 2020-08-02 10:51:22 +02:00
parent 121e1043ab
commit 67dd45c1c7
25 changed files with 420 additions and 404 deletions

View file

@ -170,39 +170,22 @@ public abstract class MageObjectImpl implements MageObject {
// its frame colors.
if (this.isLand()) {
ObjectColor cl = frameColor.copy();
Set<ManaType> manaTypes = EnumSet.noneOf(ManaType.class);
for (Ability ab : getAbilities()) {
if (ab instanceof ActivatedManaAbilityImpl) {
ActivatedManaAbilityImpl mana = (ActivatedManaAbilityImpl) ab;
try {
List<Mana> manaAdded = mana.getNetMana(game);
for (Mana m : manaAdded) {
if (m.getAny() > 0) {
return new ObjectColor("WUBRG");
}
if (m.getWhite() > 0) {
cl.setWhite(true);
}
if (m.getBlue() > 0) {
cl.setBlue(true);
}
if (m.getBlack() > 0) {
cl.setBlack(true);
}
if (m.getRed() > 0) {
cl.setRed(true);
}
if (m.getGreen() > 0) {
cl.setGreen(true);
}
}
} catch (NullPointerException e) {
// Ability depends on game
// but no game passed
// All such abilities are 5-color ones
return new ObjectColor("WUBRG");
}
manaTypes.addAll(((ActivatedManaAbilityImpl) ab).getProducableManaTypes(game));
}
}
cl.setWhite(manaTypes.contains(ManaType.WHITE));
cl.setBlue(manaTypes.contains(ManaType.BLUE));
cl.setBlack(manaTypes.contains(ManaType.BLACK));
cl.setRed(manaTypes.contains(ManaType.RED));
cl.setGreen(manaTypes.contains(ManaType.GREEN));
// // Ability depends on game
// // but no game passed
// // All such abilities are 5-color ones
// return new ObjectColor("WUBRG");
return cl;
} else {
// For everything else, just return the frame colors

View file

@ -1152,10 +1152,7 @@ public class Mana implements Comparable<Mana>, Serializable, Copyable<Mana> {
}
}
if (lessMana.getColorless() > moreMana.getColorless()) {
anyDiff -= lessMana.getColorless() - moreMana.getColorless();
if (anyDiff < 0) {
return null;
}
return null; // Any (color) can't produce colorless mana
}
if (lessMana.getAny() > moreMana.getAny()) {
return null;

View file

@ -23,6 +23,7 @@ import mage.watchers.Watcher;
import java.io.Serializable;
import java.util.List;
import java.util.UUID;
import mage.abilities.costs.common.TapSourceCost;
/**
* Practically everything in the game is started from an Ability. This interface
@ -366,6 +367,19 @@ public interface Ability extends Controllable, Serializable {
* @return
*/
boolean hasSourceObjectAbility(Game game, MageObject source, GameEvent event);
/**
* Returns true if the ability has a tap itself in their costs
* @return
*/
default boolean hasTapCost() {
for (Cost cost : this.getCosts()) {
if (cost instanceof TapSourceCost) {
return true;
}
}
return false;
}
/**
* Returns true if this ability has to be shown as topmost of all the rules

View file

@ -35,6 +35,7 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
import mage.abilities.costs.common.TapSourceCost;
/**
* @author BetaSteward_at_googlemail.com

View file

@ -13,24 +13,23 @@ import mage.game.events.ManaEvent;
import mage.players.Player;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import mage.abilities.TriggeredAbility;
import mage.constants.ManaType;
/**
* @author BetaSteward_at_googlemail.com
*/
public abstract class ManaEffect extends OneShotEffect {
protected Mana createdMana;
public ManaEffect() {
super(Outcome.PutManaInPool);
createdMana = null;
}
public ManaEffect(final ManaEffect effect) {
super(effect);
this.createdMana = effect.createdMana == null ? null : effect.createdMana.copy();
}
@Override
@ -81,6 +80,53 @@ public abstract class ManaEffect extends OneShotEffect {
return netMana;
}
/**
* The type of mana a permanent "could produce" is the type of mana that any
* ability of that permanent can generate, taking into account any
* applicable replacement effects. If the type of mana cant be defined,
* theres no type of mana that that permanent could produce. The "type" of
* mana is its color, or lack thereof (for colorless mana).
*
* @param game
* @param source
* @return
*/
public Set<ManaType> getProducableManaTypes(Game game, Ability source) {
return getManaTypesFromManaList(getNetMana(game, source));
}
public static Set<ManaType> getManaTypesFromManaList(List<Mana> manaList) {
Set<ManaType> manaTypes = new HashSet<>();
for (Mana mana : manaList) {
if (mana.getAny() > 0) {
manaTypes.add(ManaType.BLACK);
manaTypes.add(ManaType.BLUE);
manaTypes.add(ManaType.GREEN);
manaTypes.add(ManaType.WHITE);
manaTypes.add(ManaType.RED);
}
if (mana.getBlack() > 0) {
manaTypes.add(ManaType.BLACK);
}
if (mana.getBlue() > 0) {
manaTypes.add(ManaType.BLUE);
}
if (mana.getGreen() > 0) {
manaTypes.add(ManaType.GREEN);
}
if (mana.getWhite() > 0) {
manaTypes.add(ManaType.WHITE);
}
if (mana.getRed() > 0) {
manaTypes.add(ManaType.RED);
}
if (mana.getColorless() > 0) {
manaTypes.add(ManaType.COLORLESS);
}
}
return manaTypes;
}
/**
* Produced the mana the effect can produce (DO NOT add it to mana pool --
* return all added as mana object to process by replace events)
@ -105,14 +151,10 @@ public abstract class ManaEffect extends OneShotEffect {
* @param source
*/
public void checkToFirePossibleEvents(Mana mana, Game game, Ability source) {
if (source.getAbilityType() == AbilityType.MANA) {
for (Cost cost : source.getCosts()) {
if (cost instanceof TapSourceCost) {
ManaEvent event = new ManaEvent(GameEvent.EventType.TAPPED_FOR_MANA, source.getSourceId(), source.getSourceId(), source.getControllerId(), mana);
if (!game.replaceEvent(event)) {
game.fireEvent(event);
}
}
if (source.getAbilityType() == AbilityType.MANA && source.hasTapCost()) {
ManaEvent event = new ManaEvent(GameEvent.EventType.TAPPED_FOR_MANA, source.getSourceId(), source.getSourceId(), source.getControllerId(), mana);
if (!game.replaceEvent(event)) {
game.fireEvent(event);
}
}
}

View file

@ -2,7 +2,9 @@ package mage.abilities.effects.mana;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import mage.Mana;
import mage.abilities.Ability;
@ -11,6 +13,7 @@ import mage.abilities.dynamicvalue.common.StaticValue;
import mage.abilities.effects.common.ManaEffect;
import mage.abilities.mana.ManaOptions;
import mage.constants.ColoredManaSymbol;
import mage.constants.ManaType;
import mage.game.Game;
import mage.players.Player;
import mage.util.CardUtil;
@ -101,8 +104,7 @@ public class AddManaInAnyCombinationEffect extends ManaEffect {
}
@Override
public Mana produceMana(Game game, Ability source
) {
public Mana produceMana(Game game, Ability source) {
Player player = game.getPlayer(source.getControllerId());
if (player != null) {
Mana mana = new Mana();
@ -130,6 +132,29 @@ public class AddManaInAnyCombinationEffect extends ManaEffect {
return null;
}
@Override
public Set<ManaType> getProducableManaTypes(Game game, Ability source) {
Set<ManaType> manaTypes = new HashSet<>();
for(ColoredManaSymbol coloredManaSymbol: manaSymbols) {
if (coloredManaSymbol.equals(ColoredManaSymbol.B)) {
manaTypes.add(ManaType.BLACK);
}
if (coloredManaSymbol.equals(ColoredManaSymbol.R)) {
manaTypes.add(ManaType.RED);
}
if (coloredManaSymbol.equals(ColoredManaSymbol.G)) {
manaTypes.add(ManaType.GREEN);
}
if (coloredManaSymbol.equals(ColoredManaSymbol.U)) {
manaTypes.add(ManaType.BLUE);
}
if (coloredManaSymbol.equals(ColoredManaSymbol.W)) {
manaTypes.add(ManaType.WHITE);
}
}
return manaTypes;
}
private String setText() {
StringBuilder sb = new StringBuilder("Add ");
sb.append(CardUtil.numberToText(amount.toString()));

View file

@ -47,29 +47,31 @@ public class BasicManaEffect extends ManaEffect {
// calculate the maximum available mana
int count = netAmount.calculate(game, source, this);
Mana computedMana = new Mana();
if (manaTemplate.getBlack() > 0) {
computedMana.setBlack(count * manaTemplate.getBlack());
}
if (manaTemplate.getBlue() > 0) {
computedMana.setBlue(count * manaTemplate.getBlue());
}
if (manaTemplate.getGreen() > 0) {
computedMana.setGreen(count * manaTemplate.getGreen());
}
if (manaTemplate.getRed() > 0) {
computedMana.setRed(count * manaTemplate.getRed());
}
if (manaTemplate.getWhite() > 0) {
computedMana.setWhite(count * manaTemplate.getWhite());
}
if (manaTemplate.getColorless() > 0) {
computedMana.setColorless(count * manaTemplate.getColorless());
}
if (manaTemplate.getAny() > 0) {
throw new IllegalArgumentException("BasicManaEffect does not support {Any} mana!");
}
if (manaTemplate.getGeneric() > 0) {
computedMana.setGeneric(count * manaTemplate.getGeneric());
if (count > 0) {
if (manaTemplate.getBlack() > 0) {
computedMana.setBlack(count * manaTemplate.getBlack());
}
if (manaTemplate.getBlue() > 0) {
computedMana.setBlue(count * manaTemplate.getBlue());
}
if (manaTemplate.getGreen() > 0) {
computedMana.setGreen(count * manaTemplate.getGreen());
}
if (manaTemplate.getRed() > 0) {
computedMana.setRed(count * manaTemplate.getRed());
}
if (manaTemplate.getWhite() > 0) {
computedMana.setWhite(count * manaTemplate.getWhite());
}
if (manaTemplate.getColorless() > 0) {
computedMana.setColorless(count * manaTemplate.getColorless());
}
if (manaTemplate.getAny() > 0) {
throw new IllegalArgumentException("BasicManaEffect does not support {Any} mana!");
}
if (manaTemplate.getGeneric() > 0) {
computedMana.setGeneric(count * manaTemplate.getGeneric());
}
}
return new ArrayList<>(Arrays.asList(computedMana));
}

View file

@ -1,15 +1,19 @@
package mage.abilities.mana;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.ActivatedAbilityImpl;
import mage.abilities.costs.Cost;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.ManaEffect;
import mage.constants.AbilityType;
import mage.constants.AsThoughEffectType;
import mage.constants.ManaType;
import mage.constants.TimingRule;
import mage.constants.Zone;
import mage.game.Game;
@ -105,6 +109,17 @@ public abstract class ActivatedManaAbilityImpl extends ActivatedAbilityImpl impl
return netManaCopy;
}
@Override
public Set<ManaType> getProducableManaTypes(Game game) {
Set<ManaType> manaTypes = new HashSet<>();
for (Effect effect : getEffects()) {
if (effect instanceof ManaEffect) {
manaTypes.addAll(((ManaEffect) effect).getProducableManaTypes(game, this));
}
}
return manaTypes;
}
/**
* Used to check if the ability itself defines mana types it can produce.
*

View file

@ -17,7 +17,10 @@ import mage.game.permanent.Permanent;
import mage.players.Player;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import mage.constants.ManaType;
/**
* @author LevelX2
@ -55,6 +58,16 @@ public class AnyColorLandsProduceManaAbility extends ActivatedManaAbilityImpl {
return true;
}
public static Set<ManaType> getManaTypesFromPermanent(Permanent permanent, Game game) {
Set<ManaType> allTypes = new HashSet<>();
if (permanent != null) {
Abilities<ActivatedManaAbilityImpl> manaAbilities = permanent.getAbilities().getActivatedManaAbilities(Zone.BATTLEFIELD);
for (ActivatedManaAbilityImpl ability : manaAbilities) {
allTypes.addAll(ability.getProducableManaTypes(game));
}
}
return allTypes;
}
}
class AnyColorLandsProduceManaEffect extends ManaEffect {
@ -87,27 +100,30 @@ class AnyColorLandsProduceManaEffect extends ManaEffect {
@Override
public List<Mana> getNetMana(Game game, Ability source) {
List<Mana> netManas = new ArrayList<>();
Mana types = getManaTypes(game, source);
if (types.getBlack() > 0) {
netManas.add(new Mana(ColoredManaSymbol.B));
}
if (types.getRed() > 0) {
netManas.add(new Mana(ColoredManaSymbol.R));
}
if (types.getBlue() > 0) {
netManas.add(new Mana(ColoredManaSymbol.U));
}
if (types.getGreen() > 0) {
netManas.add(new Mana(ColoredManaSymbol.G));
}
if (types.getWhite() > 0) {
netManas.add(new Mana(ColoredManaSymbol.W));
}
if (!onlyColors && types.getColorless() > 0) {
netManas.add(Mana.ColorlessMana(1));
}
if (types.getAny() > 0) {
netManas.add(Mana.AnyMana(1));
if (game != null) {
Set<ManaType> manaTypes = getManaTypes(game, source);
if ((manaTypes.size() == 5 && !manaTypes.contains(ManaType.COLORLESS)) || manaTypes.size() == 6) { // GENERIC should never be returned from getManaTypes
netManas.add(Mana.AnyMana(1));
} else {
if (manaTypes.contains(ManaType.BLACK)) {
netManas.add(Mana.BlackMana(1));
}
if (manaTypes.contains(ManaType.RED)) {
netManas.add(Mana.RedMana(1));
}
if (manaTypes.contains(ManaType.BLUE)) {
netManas.add(Mana.BlueMana(1));
}
if (manaTypes.contains(ManaType.GREEN)) {
netManas.add(Mana.GreenMana(1));
}
if (manaTypes.contains(ManaType.WHITE)) {
netManas.add(Mana.WhiteMana(1));
}
}
if (!onlyColors && manaTypes.contains(ManaType.COLORLESS)) {
netManas.add(Mana.ColorlessMana(1));
}
}
return netManas;
}
@ -118,35 +134,28 @@ class AnyColorLandsProduceManaEffect extends ManaEffect {
if (game == null) {
return mana;
}
Mana types = getManaTypes(game, source);
Set<ManaType> types = getManaTypes(game, source);
Choice choice = new ChoiceColor(true);
choice.getChoices().clear();
choice.setMessage("Pick a mana color");
if (types.getBlack() > 0) {
choice.setMessage("Pick a mana " + (onlyColors ? "color" : "type"));
if (types.contains(ManaType.BLACK)) {
choice.getChoices().add("Black");
}
if (types.getRed() > 0) {
if (types.contains(ManaType.RED)) {
choice.getChoices().add("Red");
}
if (types.getBlue() > 0) {
if (types.contains(ManaType.BLUE)) {
choice.getChoices().add("Blue");
}
if (types.getGreen() > 0) {
if (types.contains(ManaType.GREEN)) {
choice.getChoices().add("Green");
}
if (types.getWhite() > 0) {
if (types.contains(ManaType.WHITE)) {
choice.getChoices().add("White");
}
if (!onlyColors && types.getColorless() > 0) {
if (types.contains(ManaType.COLORLESS)) {
choice.getChoices().add("Colorless");
}
if (types.getAny() > 0) { // Only any Color
choice.getChoices().add("Black");
choice.getChoices().add("Red");
choice.getChoices().add("Blue");
choice.getChoices().add("Green");
choice.getChoices().add("White");
}
if (!choice.getChoices().isEmpty()) {
Player player = game.getPlayer(source.getControllerId());
if (choice.getChoices().size() == 1) {
@ -182,24 +191,19 @@ class AnyColorLandsProduceManaEffect extends ManaEffect {
return mana;
}
private Mana getManaTypes(Game game, Ability source) {
Mana types = new Mana();
private Set<ManaType> getManaTypes(Game game, Ability source) {
Set types = new HashSet<>();
if (game == null || game.getPhase() == null) {
return types;
}
if (inManaTypeCalculation) {
if (inManaTypeCalculation) { // Stop endless loops
return types;
}
inManaTypeCalculation = true;
List<Permanent> lands = game.getBattlefield().getActivePermanents(filter, source.getControllerId(), source.getSourceId(), game);
for (Permanent land : lands) {
Abilities<ActivatedManaAbilityImpl> mana = land.getAbilities().getActivatedManaAbilities(Zone.BATTLEFIELD);
for (ActivatedManaAbilityImpl ability : mana) {
if (!ability.getSourceId().equals(source.getSourceId()) && ability.definesMana(game)) {
for (Mana netMana : ability.getNetMana(game)) {
types.add(netMana);
}
}
if (!land.getId().equals(source.getSourceId())) {
types.addAll(AnyColorLandsProduceManaAbility.getManaTypesFromPermanent(land, game));
}
}
inManaTypeCalculation = false;
@ -210,4 +214,5 @@ class AnyColorLandsProduceManaEffect extends ManaEffect {
public AnyColorLandsProduceManaEffect copy() {
return new AnyColorLandsProduceManaEffect(this);
}
}

View file

@ -6,7 +6,9 @@
package mage.abilities.mana;
import java.util.List;
import java.util.Set;
import mage.Mana;
import mage.constants.ManaType;
import mage.game.Game;
/**
@ -24,6 +26,18 @@ public interface ManaAbility {
*/
List<Mana> getNetMana(Game game);
/**
* The type of mana a permanent "could produce" is the type of mana that any
* ability of that permanent can generate, taking into account any
* applicable replacement effects. If the type of mana cant be defined,
* theres no type of mana that that permanent could produce. The "type" of
* mana is its color, or lack thereof (for colorless mana).
*
* @param game
* @return
*/
Set<ManaType> getProducableManaTypes(Game game);
/**
* Used to check if the ability itself defines mana types it can produce.
*

View file

@ -94,7 +94,7 @@ public class ManaOptions extends ArrayList<Mana> {
this.clear();
for (Mana netMana : netManas) {
for (Mana mana : copy) {
if (!hasTapCost(ability) || checkManaReplacementAndTriggeredMana(ability, game, netMana)) {
if (ability.hasTapCost() || checkManaReplacementAndTriggeredMana(ability, game, netMana)) {
Mana newMana = new Mana();
newMana.add(mana);
newMana.add(netMana);
@ -104,7 +104,7 @@ public class ManaOptions extends ArrayList<Mana> {
}
}
private List<List<Mana>> getSimulatedTriggeredManaFromPlayer(Game game, Ability ability) {
private static List<List<Mana>> getSimulatedTriggeredManaFromPlayer(Game game, Ability ability) {
Player player = game.getPlayer(ability.getControllerId());
List<List<Mana>> newList = new ArrayList<>();
if (player != null) {
@ -124,7 +124,7 @@ public class ManaOptions extends ArrayList<Mana> {
* @return false if mana production was completely replaced
*/
private boolean checkManaReplacementAndTriggeredMana(Ability ability, Game game, Mana mana) {
if (hasTapCost(ability)) {
if (ability.hasTapCost()) {
ManaEvent event = new ManaEvent(GameEvent.EventType.TAPPED_FOR_MANA, ability.getSourceId(), ability.getSourceId(), ability.getControllerId(), mana);
if (game.replaceEvent(event)) {
return false;
@ -137,15 +137,6 @@ public class ManaOptions extends ArrayList<Mana> {
return true;
}
public boolean hasTapCost(Ability ability) {
for (Cost cost : ability.getCosts()) {
if (cost instanceof TapSourceCost) {
return true;
}
}
return false;
}
/**
* This adds the mana the abilities can produce to the possible mana
* variabtion.
@ -267,10 +258,10 @@ public class ManaOptions extends ArrayList<Mana> {
return wasUsable;
}
private List<Mana> getTriggeredManaVariations(Game game, Ability ability, Mana baseMana) {
public static List<Mana> getTriggeredManaVariations(Game game, Ability ability, Mana baseMana) {
List<Mana> baseManaPlusTriggeredMana = new ArrayList<>();
baseManaPlusTriggeredMana.add(baseMana);
List<List<Mana>> availableTriggeredManaList = getSimulatedTriggeredManaFromPlayer(game, ability);
List<List<Mana>> availableTriggeredManaList = ManaOptions.getSimulatedTriggeredManaFromPlayer(game, ability);
for (List<Mana> availableTriggeredMana : availableTriggeredManaList) {
if (availableTriggeredMana.size() == 1) {
for (Mana prevMana : baseManaPlusTriggeredMana) {
@ -372,7 +363,7 @@ public class ManaOptions extends ArrayList<Mana> {
Mana prevMana = currentMana.copy();
// generic mana costs can be paid with different colored mana, can lead to different color combinations
if (cost.getGeneric() > 0 && cost.getGeneric() > (currentMana.getGeneric() + currentMana.getColorless())) {
for (Mana payCombination : getPossiblePayCombinations(cost.getGeneric(), currentMana)) {
for (Mana payCombination : ManaOptions.getPossiblePayCombinations(cost.getGeneric(), currentMana)) {
Mana currentManaCopy = currentMana.copy();
while (currentManaCopy.includesMana(payCombination)) { // loop for multiple usage if possible
boolean newCombinations = false;
@ -420,7 +411,13 @@ public class ManaOptions extends ArrayList<Mana> {
return oldManaWasReplaced;
}
private List<Mana> getPossiblePayCombinations(int number, Mana manaAvailable) {
/**
*
* @param number of generic mana
* @param manaAvailable
* @return
*/
public static List<Mana> getPossiblePayCombinations(int number, Mana manaAvailable) {
List<Mana> payCombinations = new ArrayList<>();
List<String> payCombinationsStrings = new ArrayList<>();
if (manaAvailable.countColored() > 0) {
@ -439,28 +436,28 @@ public class ManaOptions extends ArrayList<Mana> {
manaToPayFrom.subtract(existingMana);
if (manaToPayFrom.getBlack() > 0 && !payCombinationsStrings.contains(existingMana.toString() + Mana.BlackMana(1).toString())) {
manaToPayFrom.subtract(Mana.BlackMana(1));
addManaCombination(Mana.BlackMana(1), existingMana, payCombinations, payCombinationsStrings);
ManaOptions.addManaCombination(Mana.BlackMana(1), existingMana, payCombinations, payCombinationsStrings);
}
if (manaToPayFrom.getBlue() > 0 && !payCombinationsStrings.contains(existingMana.toString() + Mana.BlueMana(1).toString())) {
manaToPayFrom.subtract(Mana.BlueMana(1));
addManaCombination(Mana.BlueMana(1), existingMana, payCombinations, payCombinationsStrings);
ManaOptions.addManaCombination(Mana.BlueMana(1), existingMana, payCombinations, payCombinationsStrings);
}
if (manaToPayFrom.getGreen() > 0 && !payCombinationsStrings.contains(existingMana.toString() + Mana.GreenMana(1).toString())) {
manaToPayFrom.subtract(Mana.GreenMana(1));
addManaCombination(Mana.GreenMana(1), existingMana, payCombinations, payCombinationsStrings);
ManaOptions.addManaCombination(Mana.GreenMana(1), existingMana, payCombinations, payCombinationsStrings);
}
if (manaToPayFrom.getRed() > 0 && !payCombinationsStrings.contains(existingMana.toString() + Mana.RedMana(1).toString())) {
manaToPayFrom.subtract(Mana.RedMana(1));
addManaCombination(Mana.RedMana(1), existingMana, payCombinations, payCombinationsStrings);
ManaOptions.addManaCombination(Mana.RedMana(1), existingMana, payCombinations, payCombinationsStrings);
}
if (manaToPayFrom.getWhite() > 0 && !payCombinationsStrings.contains(existingMana.toString() + Mana.WhiteMana(1).toString())) {
manaToPayFrom.subtract(Mana.WhiteMana(1));
addManaCombination(Mana.WhiteMana(1), existingMana, payCombinations, payCombinationsStrings);
ManaOptions.addManaCombination(Mana.WhiteMana(1), existingMana, payCombinations, payCombinationsStrings);
}
// Pay with any only needed if colored payment was not possible
if (payCombinations.isEmpty() && manaToPayFrom.getAny() > 0 && !payCombinationsStrings.contains(existingMana.toString() + Mana.AnyMana(1).toString())) {
manaToPayFrom.subtract(Mana.AnyMana(1));
addManaCombination(Mana.AnyMana(1), existingMana, payCombinations, payCombinationsStrings);
ManaOptions.addManaCombination(Mana.AnyMana(1), existingMana, payCombinations, payCombinationsStrings);
}
}
}
@ -480,7 +477,7 @@ public class ManaOptions extends ArrayList<Mana> {
return false;
}
private void addManaCombination(Mana mana, Mana existingMana, List<Mana> payCombinations, List<String> payCombinationsStrings) {
public static void addManaCombination(Mana mana, Mana existingMana, List<Mana> payCombinations, List<String> payCombinationsStrings) {
Mana newMana = existingMana.copy();
newMana.add(mana);
payCombinations.add(newMana);

View file

@ -9,7 +9,10 @@ import mage.constants.Zone;
import mage.game.Game;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import mage.constants.ManaType;
/**
* see 20110715 - 605.1b
@ -56,7 +59,18 @@ public abstract class TriggeredManaAbility extends TriggeredAbilityImpl implemen
}
return new ArrayList<>(netMana);
}
@Override
public Set<ManaType> getProducableManaTypes(Game game) {
Set<ManaType> manaTypes = new HashSet<>();
for (Effect effect : getEffects()) {
if (effect instanceof ManaEffect) {
manaTypes.addAll(((ManaEffect) effect).getProducableManaTypes(game, this));
}
}
return manaTypes;
}
/**
* Used to check if the ability itself defines mana types it can produce.
*

View file

@ -2906,7 +2906,7 @@ public abstract class PlayerImpl implements Player, Serializable {
}
if (canUse && ability.canActivate(playerId, game).canActivate()) {
// abilities without Tap costs have to be handled as separate sources, because they can be used also
if (!availableMana.hasTapCost(ability)) {
if (!ability.hasTapCost()) {
it.remove();
Abilities<ActivatedManaAbilityImpl> noTapAbilities = new AbilitiesImpl<>(ability);
if (ability.getManaCosts().isEmpty()) {