* Fixed some more available mana calculation problems. Mana of the pool is now taken into account (e.g. Coal Golem problem). Crucible of the Spirit Dragon - Conditional mana curretnly not handled correctly in available mana calculation. Crystalline Crawler works now.Related to #6698.

This commit is contained in:
LevelX2 2020-07-16 22:37:51 +02:00
parent e3b2fa1240
commit 3a82840e66
16 changed files with 253 additions and 89 deletions

View file

@ -0,0 +1,56 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package mage.abilities.dynamicvalue;
import mage.abilities.Ability;
import mage.abilities.effects.Effect;
import mage.game.Game;
/**
*
* @author LevelX2
*/
public class LimitedDynamicValue implements DynamicValue {
private final DynamicValue value;
private final int limit;
/**
* Returns a dynamic but with an upper limit.
*
* @param limit the max value the dynamic value will return
* @param value the dynamic value to calculate the row dynamic value
*/
public LimitedDynamicValue(int limit, DynamicValue value) {
this.value = value;
this.limit = limit;
}
LimitedDynamicValue(final LimitedDynamicValue dynamicValue) {
this.value = dynamicValue.value;
this.limit = dynamicValue.limit;
}
@Override
public int calculate(Game game, Ability sourceAbility, Effect effect) {
return Math.min(limit, value.calculate(game, sourceAbility, effect));
}
@Override
public LimitedDynamicValue copy() {
return new LimitedDynamicValue(this);
}
@Override
public String toString() {
return value.toString();
}
@Override
public String getMessage() {
return value.getMessage();
}
}

View file

@ -1,5 +1,7 @@
package mage.abilities.effects.mana;
import java.util.ArrayList;
import java.util.List;
import mage.ConditionalMana;
import mage.Mana;
import mage.abilities.Ability;
@ -13,9 +15,6 @@ import mage.players.Player;
import mage.util.CardUtil;
import org.apache.log4j.Logger;
import java.util.ArrayList;
import java.util.List;
/**
* @author noxx
*/
@ -24,20 +23,22 @@ public class AddConditionalManaOfAnyColorEffect extends ManaEffect {
private static final Logger logger = Logger.getLogger(AddConditionalManaOfAnyColorEffect.class);
private final DynamicValue amount;
private final DynamicValue netAmount;
private final ConditionalManaBuilder manaBuilder;
private final boolean oneChoice;
public AddConditionalManaOfAnyColorEffect(int amount, ConditionalManaBuilder manaBuilder) {
this(StaticValue.get(amount), manaBuilder);
this(StaticValue.get(amount), StaticValue.get(amount), manaBuilder);
}
public AddConditionalManaOfAnyColorEffect(DynamicValue amount, ConditionalManaBuilder manaBuilder) {
this(amount, manaBuilder, true);
public AddConditionalManaOfAnyColorEffect(DynamicValue amount, DynamicValue netAmount, ConditionalManaBuilder manaBuilder) {
this(amount, netAmount, manaBuilder, true);
}
public AddConditionalManaOfAnyColorEffect(DynamicValue amount, ConditionalManaBuilder manaBuilder, boolean oneChoice) {
public AddConditionalManaOfAnyColorEffect(DynamicValue amount, DynamicValue netAmount, ConditionalManaBuilder manaBuilder, boolean oneChoice) {
super();
this.amount = amount;
this.netAmount = netAmount;
this.manaBuilder = manaBuilder;
this.oneChoice = oneChoice;
//
@ -53,6 +54,7 @@ public class AddConditionalManaOfAnyColorEffect extends ManaEffect {
public AddConditionalManaOfAnyColorEffect(final AddConditionalManaOfAnyColorEffect effect) {
super(effect);
this.amount = effect.amount;
this.netAmount = effect.netAmount;
this.manaBuilder = effect.manaBuilder;
this.oneChoice = effect.oneChoice;
}
@ -66,9 +68,16 @@ public class AddConditionalManaOfAnyColorEffect extends ManaEffect {
public List<Mana> getNetMana(Game game, Ability source) {
List<Mana> netMana = new ArrayList<>();
if (game != null) {
int value = amount.calculate(game, source, this);
if (value > 0) {
netMana.add(Mana.AnyMana(value));
if (game.inCheckPlayableState()) {
int amountAvailableMana = netAmount.calculate(game, source, this);
if (amountAvailableMana > 0) {
netMana.add(manaBuilder.setMana(Mana.AnyMana(amountAvailableMana), source, game).build());
}
} else {
int amountOfManaLeft = amount.calculate(game, source, this);
if (amountOfManaLeft > 0) {
netMana.add(Mana.AnyMana(amountOfManaLeft));
}
}
}
return netMana;

View file

@ -1,21 +1,22 @@
package mage.abilities.effects.mana;
import java.util.ArrayList;
import java.util.List;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.choices.ChoiceColor;
import mage.game.Game;
import mage.players.Player;
import mage.util.CardUtil;
import java.util.ArrayList;
import java.util.List;
/**
* @author BetaSteward_at_googlemail.com
*/
public class AddManaOfAnyColorEffect extends BasicManaEffect {
protected final int amount;
protected final DynamicValue netAmount;
protected final ArrayList<Mana> netMana = new ArrayList<>();
protected final boolean setFlag;
@ -28,8 +29,13 @@ public class AddManaOfAnyColorEffect extends BasicManaEffect {
}
public AddManaOfAnyColorEffect(int amount, boolean setFlag) {
this(amount, null, setFlag);
}
public AddManaOfAnyColorEffect(int amount, DynamicValue netAmount, boolean setFlag) {
super(new Mana(0, 0, 0, 0, 0, 0, amount, 0));
this.amount = amount;
this.netAmount = netAmount;
netMana.add(Mana.AnyMana(amount));
this.staticText = "add " + CardUtil.numberToText(amount) + " mana of any " + (amount > 1 ? "one " : "") + "color";
this.setFlag = setFlag;
@ -40,6 +46,12 @@ public class AddManaOfAnyColorEffect extends BasicManaEffect {
this.amount = effect.amount;
this.netMana.addAll(effect.netMana);
this.setFlag = effect.setFlag;
if (effect.netAmount == null) {
this.netAmount = null;
} else {
this.netAmount = effect.netAmount.copy();
}
}
@Override
@ -49,6 +61,16 @@ public class AddManaOfAnyColorEffect extends BasicManaEffect {
@Override
public List<Mana> getNetMana(Game game, Ability source) {
if (game != null && game.inCheckPlayableState()) {
if (netAmount != null) {
int count = netAmount.calculate(game, source, this);
Mana mana = new Mana();
mana.setAny(count * amount);
ArrayList<Mana> possibleNetMana = new ArrayList<>();
possibleNetMana.add(mana);
return possibleNetMana;
}
}
return new ArrayList<>(this.netMana);
}

View file

@ -1,5 +1,6 @@
package mage.abilities.keyword;
import java.util.UUID;
import mage.Mana;
import mage.abilities.Ability;
import mage.abilities.SpecialAction;
@ -20,22 +21,20 @@ import mage.target.Target;
import mage.target.TargetPlayer;
import mage.util.ManaUtil;
import java.util.UUID;
/**
* 702.131. Assist
* <p>
* 702.131a Assist is a static ability that modifies the rules of paying for the spell with assist (see rules 601.2g-h).
* If the total cost to cast a spell with assist includes a generic mana component, before you activate mana
* abilities while casting it, you may choose another player. That player has a chance to activate mana abilities.
* Once that player chooses not to activate any more mana abilities, you have a chance to activate mana abilities.
* Before you begin to pay the total cost of the spell, the player you chose may pay for any amount of the generic
* mana in the spells total cost.
* 702.131a Assist is a static ability that modifies the rules of paying for the
* spell with assist (see rules 601.2g-h). If the total cost to cast a spell
* with assist includes a generic mana component, before you activate mana
* abilities while casting it, you may choose another player. That player has a
* chance to activate mana abilities. Once that player chooses not to activate
* any more mana abilities, you have a chance to activate mana abilities. Before
* you begin to pay the total cost of the spell, the player you chose may pay
* for any amount of the generic mana in the spells total cost.
*
* @author emerald000, JayDi85
*/
public class AssistAbility extends SimpleStaticAbility implements AlternateManaPaymentAbility {
private static final FilterPlayer filter = new FilterPlayer("another player");
@ -107,7 +106,7 @@ public class AssistAbility extends SimpleStaticAbility implements AlternateManaP
if (opponent != null) {
// basic and pool, but no coditional mana
ManaOptions availableMana = opponent.getManaAvailable(game);
availableMana.addMana(opponent.getManaPool().getMana());
// availableMana.addMana(opponent.getManaPool().getMana());
for (Mana mana : availableMana) {
if (mana.count() > 0) {
opponentCanPayMax = Math.max(opponentCanPayMax, mana.count());

View file

@ -1,10 +1,16 @@
package mage.abilities.mana;
import java.util.ArrayList;
import java.util.List;
import mage.Mana;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.ManaEffect;
import mage.abilities.effects.mana.AddManaOfAnyColorEffect;
import mage.constants.Zone;
import mage.game.Game;
public class AnyColorManaAbility extends ActivatedManaAbilityImpl {
@ -21,10 +27,39 @@ public class AnyColorManaAbility extends ActivatedManaAbilityImpl {
this.netMana.add(new Mana(0, 0, 0, 0, 0, 0, 1, 0));
}
/**
*
* @param cost
* @param netAmount dynamic value used during available mana calculation to
* set the max possible amount the source can produce
* @param setFlag
*/
public AnyColorManaAbility(Cost cost, DynamicValue netAmount, boolean setFlag) {
super(Zone.BATTLEFIELD, new AddManaOfAnyColorEffect(1, netAmount, setFlag), cost);
this.netMana.add(new Mana(0, 0, 0, 0, 0, 0, 1, 0));
}
public AnyColorManaAbility(final AnyColorManaAbility ability) {
super(ability);
}
@Override
public List<Mana> getNetMana(Game game) {
if (game != null && game.inCheckPlayableState()) {
List<Mana> dynamicNetMana = new ArrayList<>();
for (Effect effect : getEffects()) {
if (effect instanceof ManaEffect) {
List<Mana> effectNetMana = ((ManaEffect) effect).getNetMana(game, this);
if (effectNetMana != null) {
dynamicNetMana.addAll(effectNetMana);
}
}
}
return dynamicNetMana;
}
return super.getNetMana(game);
}
@Override
public AnyColorManaAbility copy() {
return new AnyColorManaAbility(this);

View file

@ -1,6 +1,6 @@
package mage.abilities.mana;
import java.util.List;
import mage.Mana;
import mage.abilities.costs.Cost;
import mage.abilities.costs.common.TapSourceCost;
@ -11,11 +11,9 @@ import mage.abilities.mana.builder.ConditionalManaBuilder;
import mage.constants.Zone;
import mage.game.Game;
import java.util.List;
/**
* For cards like:
* {tap}: Add three mana of any one color. Spend this mana only to cast creature spells.
* For cards like: {tap}: Add three mana of any one color. Spend this mana only
* to cast creature spells.
*
* @author noxx
*/
@ -32,11 +30,11 @@ public class ConditionalAnyColorManaAbility extends ActivatedManaAbilityImpl {
}
public ConditionalAnyColorManaAbility(Cost cost, int amount, ConditionalManaBuilder manaBuilder, boolean oneChoice) {
this(cost, StaticValue.get(amount), manaBuilder, oneChoice);
this(cost, StaticValue.get(amount), StaticValue.get(amount), manaBuilder, oneChoice);
}
public ConditionalAnyColorManaAbility(Cost cost, DynamicValue amount, ConditionalManaBuilder manaBuilder, boolean oneChoice) {
super(Zone.BATTLEFIELD, new AddConditionalManaOfAnyColorEffect(amount, manaBuilder, oneChoice), cost);
public ConditionalAnyColorManaAbility(Cost cost, DynamicValue amount, DynamicValue netAmount, ConditionalManaBuilder manaBuilder, boolean oneChoice) {
super(Zone.BATTLEFIELD, new AddConditionalManaOfAnyColorEffect(amount, netAmount, manaBuilder, oneChoice), cost);
this.amount = amount;
}
@ -60,7 +58,6 @@ public class ConditionalAnyColorManaAbility extends ActivatedManaAbilityImpl {
return true;
}
@Override
public ConditionalAnyColorManaAbility copy() {
return new ConditionalAnyColorManaAbility(this);

View file

@ -22,6 +22,9 @@ import org.apache.log4j.Logger;
* be used to find all the ways to pay a mana cost or all the different mana
* combinations available to a player
*
* TODO: Conditional Mana is not supported yet. The mana adding removes the
* condition of conditional mana
*
*/
public class ManaOptions extends ArrayList<Mana> {

View file

@ -2881,6 +2881,11 @@ public abstract class PlayerImpl implements Player, Serializable {
game.setCheckPlayableState(true);
ManaOptions availableMana = new ManaOptions();
availableMana.addMana(manaPool.getMana());
// conditional mana
for (ConditionalMana conditionalMana : manaPool.getConditionalMana()) {
availableMana.addMana(conditionalMana);
}
List<Abilities<ActivatedManaAbilityImpl>> sourceWithoutManaCosts = new ArrayList<>();
List<Abilities<ActivatedManaAbilityImpl>> sourceWithCosts = new ArrayList<>();
@ -3407,11 +3412,11 @@ public abstract class PlayerImpl implements Player, Serializable {
try {
// basic mana
ManaOptions availableMana = getManaAvailable(game);
availableMana.addMana(manaPool.getMana());
// availableMana.addMana(manaPool.getMana());
// conditional mana
for (ConditionalMana conditionalMana : manaPool.getConditionalMana()) {
availableMana.addMana(conditionalMana);
}
// for (ConditionalMana conditionalMana : manaPool.getConditionalMana()) {
// availableMana.addMana(conditionalMana);
// }
boolean fromAll = fromZone.equals(Zone.ALL);
if (hidden && (fromAll || fromZone == Zone.HAND)) {