Spells giving mana work correctly

This commit is contained in:
Maxmtg
2012-11-08 22:16:05 +00:00
parent 6c0867db19
commit 2c7876f26e
15 changed files with 70 additions and 68 deletions

View File

@@ -44,7 +44,6 @@ import forge.card.cost.Cost;
import forge.card.mana.ManaCost;
import forge.card.replacement.ReplacementEffect;
import forge.card.replacement.ReplacementResult;
import forge.card.spellability.AbilityActivated;
import forge.card.spellability.AbilityManaPart;
import forge.card.spellability.AbilityTriggered;
import forge.card.spellability.Spell;
@@ -2676,7 +2675,7 @@ public class Card extends GameEntity implements Comparable<Card> {
*
* @return a {@link java.util.ArrayList} object.
*/
public final List<AbilityActivated> getManaAbility() {
public final List<SpellAbility> getManaAbility() {
return Collections.unmodifiableList(this.getCharacteristics().getManaAbility());
}
@@ -2688,9 +2687,9 @@ public class Card extends GameEntity implements Comparable<Card> {
*
* @return a {@link java.util.ArrayList} object.
*/
public final ArrayList<AbilityActivated> getAIPlayableMana() {
final ArrayList<AbilityActivated> res = new ArrayList<AbilityActivated>();
for (final AbilityActivated a : this.getManaAbility()) {
public final ArrayList<SpellAbility> getAIPlayableMana() {
final ArrayList<SpellAbility> res = new ArrayList<SpellAbility>();
for (final SpellAbility a : this.getManaAbility()) {
// if a mana ability has a mana cost the AI will miscalculate
final Cost cost = a.getPayCosts();
@@ -2716,9 +2715,9 @@ public class Card extends GameEntity implements Comparable<Card> {
*
* @return a {@link java.util.ArrayList} object.
*/
public final List<AbilityActivated> getBasicMana() {
final List<AbilityActivated> res = new ArrayList<AbilityActivated>();
for (final AbilityActivated a : this.getManaAbility()) {
public final List<SpellAbility> getBasicMana() {
final List<SpellAbility> res = new ArrayList<SpellAbility>();
for (final SpellAbility a : this.getManaAbility()) {
if (a.getManaPart().isBasic() && !res.contains(a)) {
res.add(a);
}
@@ -2802,8 +2801,8 @@ public class Card extends GameEntity implements Comparable<Card> {
public final void addSpellAbility(final SpellAbility a) {
a.setSourceCard(this);
if (a.getManaPart() != null) {
this.getCharacteristics().getManaAbility().add((AbilityActivated) a);
if (a.isManaAbility()) {
this.getCharacteristics().getManaAbility().add(a);
} else {
this.getCharacteristics().getSpellAbility().add(a);
}
@@ -2819,7 +2818,7 @@ public class Card extends GameEntity implements Comparable<Card> {
* a {@link forge.card.spellability.SpellAbility} object.
*/
public final void removeSpellAbility(final SpellAbility a) {
if (a.getManaPart() != null) {
if (a.isManaAbility()) {
// if (a.isExtrinsic()) //never remove intrinsic mana abilities, is
// this the way to go??
this.getCharacteristics().getManaAbility().remove(a);

View File

@@ -38,7 +38,6 @@ import forge.card.CardManaCost;
import forge.card.EditionInfo;
import forge.card.abilityfactory.AbilityFactory;
import forge.card.mana.ManaCost;
import forge.card.spellability.AbilityActivated;
import forge.card.spellability.AbilityManaPart;
import forge.card.spellability.SpellAbility;
import forge.control.input.InputPayManaCostUtil;
@@ -988,16 +987,16 @@ public final class CardUtil {
colors.add(Constant.Color.COLORLESS);
}
} else if (reflectProperty.equals("Produce")) {
final ArrayList<AbilityActivated> abilities = new ArrayList<AbilityActivated>();
final ArrayList<SpellAbility> abilities = new ArrayList<SpellAbility>();
for (final Card c : cards) {
abilities.addAll(c.getManaAbility());
}
// currently reflected mana will ignore other reflected mana
// abilities
final ArrayList<AbilityActivated> reflectAbilities = new ArrayList<AbilityActivated>();
final ArrayList<SpellAbility> reflectAbilities = new ArrayList<SpellAbility>();
for (final AbilityActivated ab : abilities) {
for (final SpellAbility ab : abilities) {
if (maxChoices == colors.size()) {
break;
}
@@ -1016,7 +1015,7 @@ public final class CardUtil {
}
}
for (final AbilityActivated ab : reflectAbilities) {
for (final SpellAbility ab : reflectAbilities) {
if (maxChoices == colors.size()) {
break;
}

View File

@@ -41,7 +41,6 @@ import forge.card.cost.CostReturn;
import forge.card.cost.CostSacrifice;
import forge.card.cost.CostUtil;
import forge.card.spellability.Ability;
import forge.card.spellability.AbilityActivated;
import forge.card.spellability.AbilitySub;
import forge.card.spellability.Spell;
import forge.card.spellability.SpellAbility;
@@ -1324,12 +1323,12 @@ public final class GameActionUtil {
produces.put("Plains", "W");
produces.put("Swamp", "B");
List<Card> lands = Singletons.getModel().getGame().getCardsInGame();
List<Card> lands = Singletons.getModel().getGame().getCardsIn(ZoneType.Battlefield);
lands = CardLists.filter(lands, Presets.LANDS);
// remove all abilities granted by this Command
for (final Card land : lands) {
List<AbilityActivated> manaAbs = Lists.newArrayList(land.getManaAbility());
List<SpellAbility> manaAbs = Lists.newArrayList(land.getManaAbility());
// will get comodification exception without a different list
for (final SpellAbility sa : manaAbs) {
if (sa.getType().equals("BasicLandTypeMana")) {

View File

@@ -24,7 +24,6 @@ import java.util.TreeMap;
import forge.CardColor;
import forge.card.replacement.ReplacementEffect;
import forge.card.spellability.AbilityActivated;
import forge.card.spellability.SpellAbility;
import forge.card.staticability.StaticAbility;
import forge.card.trigger.Trigger;
@@ -44,7 +43,7 @@ public class CardCharacteristics {
private ArrayList<String> intrinsicKeyword = new ArrayList<String>();
private ArrayList<SpellAbility> spellAbility = new ArrayList<SpellAbility>();
private ArrayList<String> intrinsicAbility = new ArrayList<String>();
private final List<AbilityActivated> manaAbility = new ArrayList<AbilityActivated>();
private final List<SpellAbility> manaAbility = new ArrayList<SpellAbility>();
private ArrayList<Trigger> triggers = new ArrayList<Trigger>();
private ArrayList<ReplacementEffect> replacementEffects = new ArrayList<ReplacementEffect>();
private ArrayList<StaticAbility> staticAbilities = new ArrayList<StaticAbility>();
@@ -250,7 +249,7 @@ public class CardCharacteristics {
*
* @return the manaAbility
*/
public final List<AbilityActivated> getManaAbility() {
public final List<SpellAbility> getManaAbility() {
return this.manaAbility;
}

View File

@@ -5,7 +5,10 @@ import java.util.Map;
import forge.Card;
import forge.card.abilityfactory.effects.ChangeZoneAllEffect;
import forge.card.abilityfactory.effects.ChangeZoneEffect;
import forge.card.abilityfactory.effects.ManaEffect;
import forge.card.abilityfactory.effects.ManaReflectedEffect;
import forge.card.cost.Cost;
import forge.card.spellability.AbilityManaPart;
import forge.card.spellability.Spell;
import forge.card.spellability.Target;
@@ -21,6 +24,9 @@ public class CommonSpell extends Spell {
effect = effect0;
ai = ai0;
if ( effect0 instanceof ManaEffect || effect0 instanceof ManaReflectedEffect )
this.setManaPart(new AbilityManaPart(sourceCard, params));
if ( effect0 instanceof ChangeZoneEffect || effect0 instanceof ChangeZoneAllEffect )
AbilityFactory.adjustChangeZoneTarget(params, this);
}

View File

@@ -37,8 +37,7 @@ import forge.game.player.Player;
// if mana production has any type of SubAbility, undoable=false
final AbilitySub abSub = sa.getSubAbility();
if (abSub != null) {
if ( sa.getManaPart() != null )
sa.setUndoable(false);
sa.setUndoable(false);
AbilityFactory.resolve(abSub, false);
}
}

View File

@@ -24,7 +24,6 @@ import java.util.Map;
import forge.Constant;
import forge.Singletons;
import forge.card.spellability.AbilityActivated;
import forge.card.spellability.AbilityManaPart;
import forge.card.spellability.SpellAbility;
import forge.control.input.InputPayManaCostUtil;
@@ -480,14 +479,14 @@ public class ManaPool {
* a {@link forge.card.spellability.AbilityMana} object.
* @return a {@link forge.card.mana.ManaCost} object.
*/
public final ManaCost payManaFromAbility(final SpellAbility sa, ManaCost manaCost, final AbilityActivated ma) {
public final ManaCost payManaFromAbility(final SpellAbility sa, ManaCost manaCost, final SpellAbility ma) {
if (manaCost.isPaid() || this.isEmpty()) {
return manaCost;
}
// Mana restriction must be checked before this method is called
final List<AbilityActivated> paidAbs = sa.getPayingManaAbilities();
final List<SpellAbility> paidAbs = sa.getPayingManaAbilities();
final List<Mana> manaPaid = sa.getPayingMana();
paidAbs.add(ma); // assumes some part on the mana produced by the ability will get used
@@ -526,7 +525,7 @@ public class ManaPool {
* a boolean.
*/
public final void clearManaPaid(final SpellAbility ability, final boolean refund) {
final List<AbilityActivated> abilitiesUsedToPay = ability.getPayingManaAbilities();
final List<SpellAbility> abilitiesUsedToPay = ability.getPayingManaAbilities();
final List<Mana> manaPaid = ability.getPayingMana();
abilitiesUsedToPay.clear();
@@ -609,10 +608,10 @@ public class ManaPool {
public final void refundManaPaid(final SpellAbility sa, final boolean untap) {
// TODO having some crash in here related to undo and not tracking
// abilities properly
final List<AbilityActivated> payAbs = sa.getPayingManaAbilities();
final List<SpellAbility> payAbs = sa.getPayingManaAbilities();
// go through paidAbilities if they are undoable
for (final AbilityActivated am : payAbs) {
for (final SpellAbility am : payAbs) {
AbilityManaPart m = am.getManaPart();
if (am.isUndoable()) {
if (this.accountFor(sa, m)) {

View File

@@ -68,7 +68,7 @@ public abstract class Ability extends SpellAbility {
/** {@inheritDoc} */
@Override
public boolean canPlay() {
if (Singletons.getModel().getGame().getStack().isSplitSecondOnStack() && null == this.getManaPart()) {
if (Singletons.getModel().getGame().getStack().isSplitSecondOnStack() && !this.isManaAbility()) {
return false;
}

View File

@@ -81,7 +81,7 @@ public abstract class AbilityActivated extends SpellAbility implements java.io.S
/** {@inheritDoc} */
@Override
public boolean canPlay() {
if (Singletons.getModel().getGame().getStack().isSplitSecondOnStack() && null == this.getManaPart()) {
if (Singletons.getModel().getGame().getStack().isSplitSecondOnStack() && !this.isManaAbility()) {
return false;
}

View File

@@ -86,7 +86,7 @@ public abstract class Spell extends SpellAbility implements java.io.Serializable
/** {@inheritDoc} */
@Override
public boolean canPlay() {
if (Singletons.getModel().getGame().getStack().isSplitSecondOnStack() && null == this.getManaPart()) {
if (Singletons.getModel().getGame().getStack().isSplitSecondOnStack()) {
return false;
}

View File

@@ -102,7 +102,7 @@ public abstract class SpellAbility {
protected ApiType api = null;
private final ArrayList<Mana> payingMana = new ArrayList<Mana>();
private final List<AbilityActivated> paidAbilities = new ArrayList<AbilityActivated>();
private final List<SpellAbility> paidAbilities = new ArrayList<SpellAbility>();
private ArrayList<String> optionalAdditionalCosts = new ArrayList<String>();
private HashMap<String, List<Card>> paidLists = new HashMap<String, List<Card>>();
@@ -124,6 +124,10 @@ public abstract class SpellAbility {
public final AbilityManaPart getManaPart() {
return manaPart;
}
public final boolean isManaAbility() {
return manaPart != null && isAbility();
}
public final void setManaPart(AbilityManaPart manaPart) {
this.manaPart = manaPart;
@@ -759,7 +763,7 @@ public abstract class SpellAbility {
*
* @return a {@link java.util.ArrayList} object.
*/
public List<AbilityActivated> getPayingManaAbilities() {
public List<SpellAbility> getPayingManaAbilities() {
return this.paidAbilities;
}

View File

@@ -97,7 +97,7 @@ public class StaticAbilityCantBeCast {
return false;
}
if (params.containsKey("NonMana") && (spellAbility.getManaPart() != null )) {
if (params.containsKey("NonMana") && (spellAbility.isManaAbility())) {
return false;
}

View File

@@ -31,7 +31,6 @@ import forge.card.cost.CostMana;
import forge.card.cost.CostPayment;
import forge.card.mana.ManaCost;
import forge.card.mana.ManaPool;
import forge.card.spellability.AbilityActivated;
import forge.card.spellability.AbilityManaPart;
import forge.card.spellability.SpellAbility;
import forge.game.zone.PlayerZone;
@@ -85,10 +84,10 @@ public class InputPayManaCostUtil {
}
}
List<AbilityActivated> abilities = new ArrayList<AbilityActivated>();
List<SpellAbility> abilities = new ArrayList<SpellAbility>();
// you can't remove unneeded abilities inside a for(am:abilities) loop :(
for(AbilityActivated ma : card.getManaAbility()) {
for(SpellAbility ma : card.getManaAbility()) {
ma.setActivatingPlayer(Singletons.getControl().getPlayer());
AbilityManaPart m = ma.getManaPart();
if (!ma.canPlay()) {
@@ -151,9 +150,9 @@ public class InputPayManaCostUtil {
if (!skipExpress) {
// express Mana Choice
final ArrayList<AbilityActivated> colorMatches = new ArrayList<AbilityActivated>();
final ArrayList<SpellAbility> colorMatches = new ArrayList<SpellAbility>();
for (final AbilityActivated am : abilities) {
for (final SpellAbility am : abilities) {
AbilityManaPart m = am.getManaPart();
if (m.isReflectedMana()) {
final List<String> reflectableColors = CardUtil.getReflectableManaColors(am, am, new ArrayList<String>(), new ArrayList<Card>());
@@ -191,10 +190,10 @@ public class InputPayManaCostUtil {
}
}
AbilityActivated chosen = abilities.get(0);
SpellAbility chosen = abilities.get(0);
if ((1 < abilities.size()) && choice) {
final Map<String, AbilityActivated> ability = new HashMap<String, AbilityActivated>();
for (final AbilityActivated am : abilities) {
final Map<String, SpellAbility> ability = new HashMap<String, SpellAbility>();
for (final SpellAbility am : abilities) {
ability.put(am.toString(), am);
}
chosen = GuiChoose.one("Choose mana ability", abilities);
@@ -246,7 +245,7 @@ public class InputPayManaCostUtil {
* a {@link java.lang.String} object.
* @return a boolean.
*/
public static boolean canMake(final AbilityActivated am, final String mana) {
public static boolean canMake(final SpellAbility am, final String mana) {
if (mana.contains("1")) {
return true;
}

View File

@@ -49,7 +49,6 @@ import forge.card.cost.CostPayment;
import forge.card.cost.CostUtil;
import forge.card.mana.ManaCost;
import forge.card.mana.ManaPool;
import forge.card.spellability.AbilityActivated;
import forge.card.spellability.AbilityManaPart;
import forge.card.spellability.AbilityStatic;
import forge.card.spellability.SpellAbility;
@@ -609,9 +608,9 @@ public class ComputerUtil {
}
// get map of mana abilities
final Map<String, List<AbilityActivated>> manaAbilityMap = ComputerUtil.mapManaSources(ai, checkPlayable);
final Map<String, List<SpellAbility>> manaAbilityMap = ComputerUtil.mapManaSources(ai, checkPlayable);
// initialize ArrayList list for mana needed
final List<List<AbilityActivated>> partSources = new ArrayList<List<AbilityActivated>>();
final List<List<SpellAbility>> partSources = new ArrayList<List<SpellAbility>>();
final List<Integer> partPriority = new ArrayList<Integer>();
final String[] costParts = cost.toString().replace("X ", "").split(" ");
boolean foundAllSources = findManaSources(ai, manaAbilityMap, partSources, partPriority, costParts);
@@ -635,7 +634,7 @@ public class ComputerUtil {
final int nPart = partPriority.get(nPriority);
final ManaCost costPart = new ManaCost(costParts[nPart]);
// Loop over mana abilities that can be used to current mana cost part
for (final AbilityActivated ma : partSources.get(nPart)) {
for (final SpellAbility ma : partSources.get(nPart)) {
final Card sourceCard = ma.getSourceCard();
// Check if source has already been used
@@ -781,8 +780,8 @@ public class ComputerUtil {
* @param foundAllSources
* @return Were all mana sources found?
*/
private static boolean findManaSources(final Player ai, final Map<String, List<AbilityActivated>> manaAbilityMap,
final List<List<AbilityActivated>> partSources, final List<Integer> partPriority,
private static boolean findManaSources(final Player ai, final Map<String, List<SpellAbility>> manaAbilityMap,
final List<List<SpellAbility>> partSources, final List<Integer> partPriority,
final String[] costParts) {
final String[] shortColors = { "W", "U", "B", "R", "G" };
boolean foundAllSources;
@@ -792,7 +791,7 @@ public class ComputerUtil {
foundAllSources = true;
// loop over cost parts
for (int nPart = 0; nPart < costParts.length; nPart++) {
final List<AbilityActivated> srcFound = new ArrayList<AbilityActivated>();
final List<SpellAbility> srcFound = new ArrayList<SpellAbility>();
// Test for:
// 1) Colorless
// 2) Split e.g. 2/G
@@ -947,7 +946,7 @@ public class ComputerUtil {
@Override
public boolean apply(final Card c) {
if (checkPlayable) {
for (final AbilityActivated am : c.getAIPlayableMana()) {
for (final SpellAbility am : c.getAIPlayableMana()) {
am.setActivatingPlayer(ai);
if (am.canPlay()) {
return true;
@@ -988,9 +987,9 @@ public class ComputerUtil {
int usableManaAbilities = 0;
boolean needsLimitedResources = false;
boolean producesAnyColor = false;
final ArrayList<AbilityActivated> manaAbilities = card.getAIPlayableMana();
final ArrayList<SpellAbility> manaAbilities = card.getAIPlayableMana();
for (final AbilityActivated m : manaAbilities) {
for (final SpellAbility m : manaAbilities) {
if (m.getManaPart().isAnyMana()) {
producesAnyColor = true;
@@ -1066,16 +1065,16 @@ public class ComputerUtil {
* @param checkPlayable TODO
* @return HashMap<String, List<Card>>
*/
public static Map<String, List<AbilityActivated>> mapManaSources(final Player ai, boolean checkPlayable) {
final Map<String, List<AbilityActivated>> manaMap = new HashMap<String, List<AbilityActivated>>();
public static Map<String, List<SpellAbility>> mapManaSources(final Player ai, boolean checkPlayable) {
final Map<String, List<SpellAbility>> manaMap = new HashMap<String, List<SpellAbility>>();
final List<AbilityActivated> whiteSources = new ArrayList<AbilityActivated>();
final List<AbilityActivated> blueSources = new ArrayList<AbilityActivated>();
final List<AbilityActivated> blackSources = new ArrayList<AbilityActivated>();
final List<AbilityActivated> redSources = new ArrayList<AbilityActivated>();
final List<AbilityActivated> greenSources = new ArrayList<AbilityActivated>();
final List<AbilityActivated> colorlessSources = new ArrayList<AbilityActivated>();
final List<AbilityActivated> snowSources = new ArrayList<AbilityActivated>();
final List<SpellAbility> whiteSources = new ArrayList<SpellAbility>();
final List<SpellAbility> blueSources = new ArrayList<SpellAbility>();
final List<SpellAbility> blackSources = new ArrayList<SpellAbility>();
final List<SpellAbility> redSources = new ArrayList<SpellAbility>();
final List<SpellAbility> greenSources = new ArrayList<SpellAbility>();
final List<SpellAbility> colorlessSources = new ArrayList<SpellAbility>();
final List<SpellAbility> snowSources = new ArrayList<SpellAbility>();
// Get list of current available mana sources
final List<Card> manaSources = ComputerUtil.getAvailableMana(ai, checkPlayable);
@@ -1083,10 +1082,10 @@ public class ComputerUtil {
// Loop over all mana sources
for (int i = 0; i < manaSources.size(); i++) {
final Card sourceCard = manaSources.get(i);
final ArrayList<AbilityActivated> manaAbilities = sourceCard.getAIPlayableMana();
final ArrayList<SpellAbility> manaAbilities = sourceCard.getAIPlayableMana();
// Loop over all mana abilities for a source
for (final AbilityActivated m : manaAbilities) {
for (final SpellAbility m : manaAbilities) {
m.setActivatingPlayer(ai);
if (!m.canPlay() && checkPlayable) {
continue;

View File

@@ -305,7 +305,7 @@ public class MagicStack extends MyObservable {
} else {
// TODO: make working triggered abilities!
if (sp.getManaPart() != null || (sp instanceof AbilityTriggered)) {
if (sp.isManaAbility() || (sp instanceof AbilityTriggered)) {
sp.resolve();
} else {
this.push(sp);
@@ -419,7 +419,7 @@ public class MagicStack extends MyObservable {
public final void add(final SpellAbility sp) {
final ArrayList<TargetChoices> chosenTargets = sp.getAllTargetChoices();
if (sp.getManaPart() != null) { // Mana Abilities go straight through
if (sp.isManaAbility()) { // Mana Abilities go straight through
sp.resolve();
sp.resetOnceResolved();
game.getGameLog().add("Mana", sp.getSourceCard() + " - " + sp.getDescription(), 4);