SpellAbility cost adjustment moved to ManaCostBeingPaid

the adjustment modifies the instance of ManaCostBeingPaid it was called on (all callers do create a new instance anyway and call this first)
This commit is contained in:
Maxmtg
2013-04-03 06:59:25 +00:00
parent 8368b4c8c6
commit b8107ac97f
11 changed files with 283 additions and 325 deletions

View File

@@ -23,7 +23,6 @@ import java.util.regex.Pattern;
import forge.Card; import forge.Card;
import forge.CounterType; import forge.CounterType;
import forge.Singletons;
import forge.card.mana.ManaCost; import forge.card.mana.ManaCost;
import forge.card.mana.ManaCostBeingPaid; import forge.card.mana.ManaCostBeingPaid;
import forge.card.mana.ManaCostParser; import forge.card.mana.ManaCostParser;
@@ -366,7 +365,8 @@ public class Cost {
for (final CostPart part : this.costParts) { for (final CostPart part : this.costParts) {
if (part instanceof CostPartMana) { if (part instanceof CostPartMana) {
final ManaCost mana = new ManaCost(new ManaCostParser(part.toString())); final ManaCost mana = new ManaCost(new ManaCostParser(part.toString()));
final ManaCostBeingPaid changedCost = Singletons.getModel().getGame().getActionPlay().getSpellCostChange(sa, new ManaCostBeingPaid(mana)); final ManaCostBeingPaid changedCost = new ManaCostBeingPaid(mana);
changedCost.applySpellCostChange(sa);
((CostPartMana)part).setAdjustedMana(changedCost.toString(false)); ((CostPartMana)part).setAdjustedMana(changedCost.toString(false));
costChanged = true; costChanged = true;
@@ -374,7 +374,8 @@ public class Cost {
} }
if (!costChanged) { if (!costChanged) {
// Spells with a cost of 0 should be affected too // Spells with a cost of 0 should be affected too
final ManaCostBeingPaid changedCost = Singletons.getModel().getGame().getActionPlay().getSpellCostChange(sa, new ManaCostBeingPaid("0")); final ManaCostBeingPaid changedCost = new ManaCostBeingPaid("0");
changedCost.applySpellCostChange(sa);
this.costParts.add(new CostPartMana(changedCost.toString(), 0, false)); this.costParts.add(new CostPartMana(changedCost.toString(), 0, false));
} }
} }

View File

@@ -22,8 +22,21 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map.Entry; import java.util.Map.Entry;
import com.google.common.collect.Lists;
import forge.Card;
import forge.CardColor;
import forge.CardLists;
import forge.CardPredicates;
import forge.Constant; import forge.Constant;
import forge.card.MagicColor; import forge.card.MagicColor;
import forge.card.spellability.SpellAbility;
import forge.card.staticability.StaticAbility;
import forge.game.GameState;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
import forge.gui.GuiChoose;
import forge.util.MyRandom;
/** /**
* <p> * <p>
@@ -652,4 +665,165 @@ public class ManaCostBeingPaid {
public ManaCost getStartingCost() { public ManaCost getStartingCost() {
return originalCost; return originalCost;
} }
public final void applySpellCostChange(final SpellAbility sa) {
final GameState game = sa.getActivatingPlayer().getGame();
// Beached
final Card originalCard = sa.getSourceCard();
final SpellAbility spell = sa;
if (sa.isXCost() && !originalCard.isCopiedSpell()) {
originalCard.setXManaCostPaid(0);
}
if (sa.isTrigger()) {
return;
}
if (spell.isSpell()) {
if (spell.isDelve()) {
final Player pc = originalCard.getController();
final List<Card> mutableGrave = Lists.newArrayList(pc.getZone(ZoneType.Graveyard).getCards());
final List<Card> toExile = pc.getController().chooseCardsToDelve(this.getColorlessManaAmount(), mutableGrave);
for (final Card c : toExile) {
pc.getGame().getAction().exile(c);
decreaseColorlessMana(1);
}
} else if (spell.getSourceCard().hasKeyword("Convoke")) {
adjustCostByConvoke(sa, spell);
}
} // isSpell
List<Card> cardsOnBattlefield = Lists.newArrayList(game.getCardsIn(ZoneType.Battlefield));
cardsOnBattlefield.addAll(game.getCardsIn(ZoneType.Stack));
cardsOnBattlefield.addAll(game.getCardsIn(ZoneType.Command));
if (!cardsOnBattlefield.contains(originalCard)) {
cardsOnBattlefield.add(originalCard);
}
final ArrayList<StaticAbility> raiseAbilities = new ArrayList<StaticAbility>();
final ArrayList<StaticAbility> reduceAbilities = new ArrayList<StaticAbility>();
final ArrayList<StaticAbility> setAbilities = new ArrayList<StaticAbility>();
// Sort abilities to apply them in proper order
for (Card c : cardsOnBattlefield) {
final ArrayList<StaticAbility> staticAbilities = c.getStaticAbilities();
for (final StaticAbility stAb : staticAbilities) {
if (stAb.getMapParams().get("Mode").equals("RaiseCost")) {
raiseAbilities.add(stAb);
} else if (stAb.getMapParams().get("Mode").equals("ReduceCost")) {
reduceAbilities.add(stAb);
} else if (stAb.getMapParams().get("Mode").equals("SetCost")) {
setAbilities.add(stAb);
}
}
}
// Raise cost
for (final StaticAbility stAb : raiseAbilities) {
stAb.applyAbility("RaiseCost", spell, this);
}
// Reduce cost
for (final StaticAbility stAb : reduceAbilities) {
stAb.applyAbility("ReduceCost", spell, this);
}
// Set cost (only used by Trinisphere) is applied last
for (final StaticAbility stAb : setAbilities) {
stAb.applyAbility("SetCost", spell, this);
}
} // GetSpellCostChange
private void adjustCostByConvoke(final SpellAbility sa, final SpellAbility spell) {
List<Card> untappedCreats = CardLists.filter(spell.getActivatingPlayer().getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES);
untappedCreats = CardLists.filter(untappedCreats, CardPredicates.Presets.UNTAPPED);
while (!untappedCreats.isEmpty() && getConvertedManaCost() > 0) {
Card workingCard = null;
String chosenColor = null;
if (sa.getActivatingPlayer().isHuman()) {
workingCard = GuiChoose.oneOrNone("Tap for Convoke? " + toString(), untappedCreats);
if( null == workingCard )
break; // that means "I'm done"
List<String> usableColors = getConvokableColors(workingCard);
if ( !usableColors.isEmpty() ) {
chosenColor = usableColors.size() == 1 ? usableColors.get(0) : GuiChoose.one("Convoke for which color?", usableColors);
}
} else {
// TODO: AI to choose a creature to tap would go here
// Probably along with deciding how many creatures to
// tap
if ( MyRandom.getRandom().nextInt(3) == 0 ) // 66% chance to chose first creature, 33% to cancel
workingCard = untappedCreats.get(0);
if( null == workingCard )
break; // that means "I'm done"
List<String> usableColors = getConvokableColors(workingCard);
if ( !usableColors.isEmpty() ) {
// TODO: AI for choosing which color to convoke goes here.
chosenColor = usableColors.get(0);
}
}
untappedCreats.remove(workingCard);
if ( null == chosenColor )
continue;
else if (chosenColor.equals("colorless")) {
decreaseColorlessMana(1);
} else {
decreaseShard(ManaCostShard.valueOf(MagicColor.fromName(chosenColor)), 1);
}
sa.addTappedForConvoke(workingCard);
}
// Convoked creats are tapped here with triggers
// suppressed,
// Then again when payment is done(In
// InputPayManaCost.done()) with suppression cleared.
// This is to make sure that triggers go off at the
// right time
// AND that you can't use mana tapabilities of convoked
// creatures
// to pay the convoked cost.
for (final Card c : sa.getTappedForConvoke()) {
c.setTapped(true);
}
}
/**
* Gets the convokable colors.
*
* @param cardToConvoke
* the card to convoke
* @param cost
* the cost
* @return the convokable colors
*/
private List<String> getConvokableColors(final Card cardToConvoke) {
final ArrayList<String> usableColors = new ArrayList<String>();
if (getColorlessManaAmount() > 0) {
usableColors.add("colorless");
}
for (final CardColor col : cardToConvoke.getColor()) {
for (final String strCol : col.toStringList()) {
if (strCol.equals("colorless")) {
continue;
}
if (toString().contains(MagicColor.toShortString(strCol))) {
usableColors.add(strCol.toString());
}
}
}
return usableColors;
}
} }

View File

@@ -358,28 +358,26 @@ public class StaticAbility {
* the originalCost * the originalCost
* @return the modified ManaCost * @return the modified ManaCost
*/ */
public final ManaCostBeingPaid applyAbility(final String mode, final SpellAbility sa, final ManaCostBeingPaid originalCost) { public final void applyAbility(final String mode, final SpellAbility sa, final ManaCostBeingPaid originalCost) {
// don't apply the ability if it hasn't got the right mode // don't apply the ability if it hasn't got the right mode
if (!this.params.get("Mode").equals(mode)) { if (!this.params.get("Mode").equals(mode)) {
return originalCost; return;
} }
if (this.isSuppressed() || !this.checkConditions()) { if (this.isSuppressed() || !this.checkConditions()) {
return originalCost; return;
} }
if (mode.equals("RaiseCost")) { if (mode.equals("RaiseCost")) {
return StaticAbilityCostChange.applyRaiseCostAbility(this, sa, originalCost); StaticAbilityCostChange.applyRaiseCostAbility(this, sa, originalCost);
} }
if (mode.equals("ReduceCost")) { if (mode.equals("ReduceCost")) {
return StaticAbilityCostChange.applyReduceCostAbility(this, sa, originalCost); StaticAbilityCostChange.applyReduceCostAbility(this, sa, originalCost);
} }
if (mode.equals("SetCost")) { //Set cost is only used by Trinisphere if (mode.equals("SetCost")) { //Set cost is only used by Trinisphere
return StaticAbilityCostChange.applyRaiseCostAbility(this, sa, originalCost); StaticAbilityCostChange.applyRaiseCostAbility(this, sa, originalCost);
} }
return originalCost;
} }
/** /**

View File

@@ -45,51 +45,50 @@ public class StaticAbilityCostChange {
* @param originalCost * @param originalCost
* a ManaCost * a ManaCost
*/ */
public static ManaCostBeingPaid applyRaiseCostAbility(final StaticAbility staticAbility, final SpellAbility sa public static void applyRaiseCostAbility(final StaticAbility staticAbility, final SpellAbility sa, final ManaCostBeingPaid manaCost) {
, final ManaCostBeingPaid originalCost) {
final HashMap<String, String> params = staticAbility.getMapParams(); final HashMap<String, String> params = staticAbility.getMapParams();
final Card hostCard = staticAbility.getHostCard(); final Card hostCard = staticAbility.getHostCard();
final Player activator = sa.getActivatingPlayer(); final Player activator = sa.getActivatingPlayer();
final Card card = sa.getSourceCard(); final Card card = sa.getSourceCard();
final String amount = params.get("Amount"); final String amount = params.get("Amount");
final ManaCostBeingPaid manaCost = new ManaCostBeingPaid(originalCost.toString());
if (params.containsKey("ValidCard") if (params.containsKey("ValidCard")
&& !card.isValid(params.get("ValidCard").split(","), hostCard.getController(), hostCard)) { && !card.isValid(params.get("ValidCard").split(","), hostCard.getController(), hostCard)) {
return originalCost; return;
} }
if (params.containsKey("Activator") && ((activator == null) if (params.containsKey("Activator") && ((activator == null)
|| !activator.isValid(params.get("Activator"), hostCard.getController(), hostCard))) { || !activator.isValid(params.get("Activator"), hostCard.getController(), hostCard))) {
return originalCost; return;
} }
if (params.containsKey("Type")) { if (params.containsKey("Type")) {
if (params.get("Type").equals("Spell")) { if (params.get("Type").equals("Spell")) {
if (!sa.isSpell()) { if (!sa.isSpell()) {
return originalCost; return;
} }
} else if (params.get("Type").equals("Ability")) { } else if (params.get("Type").equals("Ability")) {
if (!(sa instanceof AbilityActivated)) { if (!(sa instanceof AbilityActivated)) {
return originalCost; return;
} }
} else if (params.get("Type").equals("NonManaAbility")) { } else if (params.get("Type").equals("NonManaAbility")) {
if (!(sa instanceof AbilityActivated) || sa.isManaAbility()) { if (!(sa instanceof AbilityActivated) || sa.isManaAbility()) {
return originalCost; return;
} }
} else if (params.get("Type").equals("Flashback")) { } else if (params.get("Type").equals("Flashback")) {
if (!sa.isFlashBackAbility()) { if (!sa.isFlashBackAbility()) {
return originalCost; return;
} }
} }
} }
if (params.containsKey("AffectedZone") && !card.isInZone(ZoneType.smartValueOf(params.get("AffectedZone")))) { if (params.containsKey("AffectedZone") && !card.isInZone(ZoneType.smartValueOf(params.get("AffectedZone")))) {
return originalCost; return;
} }
if (params.containsKey("ValidTarget")) { if (params.containsKey("ValidTarget")) {
Target tgt = sa.getTarget(); Target tgt = sa.getTarget();
if (tgt == null) { if (tgt == null) {
return originalCost; return;
} }
boolean targetValid = false; boolean targetValid = false;
for (Object target : tgt.getTargets()) { for (Object target : tgt.getTargets()) {
@@ -101,13 +100,13 @@ public class StaticAbilityCostChange {
} }
} }
if (!targetValid) { if (!targetValid) {
return originalCost; return;
} }
} }
if (params.containsKey("ValidSpellTarget")) { if (params.containsKey("ValidSpellTarget")) {
Target tgt = sa.getTarget(); Target tgt = sa.getTarget();
if (tgt == null) { if (tgt == null) {
return originalCost; return;
} }
boolean targetValid = false; boolean targetValid = false;
for (Object target : tgt.getTargets()) { for (Object target : tgt.getTargets()) {
@@ -119,7 +118,7 @@ public class StaticAbilityCostChange {
} }
} }
if (!targetValid) { if (!targetValid) {
return originalCost; return;
} }
} }
int value = 0; int value = 0;
@@ -155,8 +154,6 @@ public class StaticAbilityCostChange {
manaCost.increaseShard(ManaCostShard.GREEN, value); manaCost.increaseShard(ManaCostShard.GREEN, value);
} }
} }
return manaCost;
} }
/** /**
@@ -169,58 +166,57 @@ public class StaticAbilityCostChange {
* @param originalCost * @param originalCost
* a ManaCost * a ManaCost
*/ */
public static ManaCostBeingPaid applyReduceCostAbility(final StaticAbility staticAbility, final SpellAbility sa public static void applyReduceCostAbility(final StaticAbility staticAbility, final SpellAbility sa, final ManaCostBeingPaid manaCost) {
, final ManaCostBeingPaid originalCost) {
//Can't reduce zero cost //Can't reduce zero cost
if (originalCost.toString().equals("0")) { if (manaCost.toString().equals("0")) {
return originalCost; return;
} }
final HashMap<String, String> params = staticAbility.getMapParams(); final HashMap<String, String> params = staticAbility.getMapParams();
final Card hostCard = staticAbility.getHostCard(); final Card hostCard = staticAbility.getHostCard();
final Player activator = sa.getActivatingPlayer(); final Player activator = sa.getActivatingPlayer();
final Card card = sa.getSourceCard(); final Card card = sa.getSourceCard();
final String amount = params.get("Amount"); final String amount = params.get("Amount");
final ManaCostBeingPaid manaCost = new ManaCostBeingPaid(originalCost.toString());
if (params.containsKey("ValidCard") if (params.containsKey("ValidCard")
&& !card.isValid(params.get("ValidCard").split(","), hostCard.getController(), hostCard)) { && !card.isValid(params.get("ValidCard").split(","), hostCard.getController(), hostCard)) {
return originalCost; return;
} }
if (params.containsKey("Activator") && ((activator == null) if (params.containsKey("Activator") && ((activator == null)
|| !activator.isValid(params.get("Activator"), hostCard.getController(), hostCard))) { || !activator.isValid(params.get("Activator"), hostCard.getController(), hostCard))) {
return originalCost; return;
} }
if (params.containsKey("Type")) { if (params.containsKey("Type")) {
if (params.get("Type").equals("Spell")) { if (params.get("Type").equals("Spell")) {
if (!sa.isSpell()) { if (!sa.isSpell()) {
return originalCost; return;
} }
} else if (params.get("Type").equals("Ability")) { } else if (params.get("Type").equals("Ability")) {
if (!(sa instanceof AbilityActivated)) { if (!(sa instanceof AbilityActivated)) {
return originalCost; return;
} }
} else if (params.get("Type").equals("Buyback")) { } else if (params.get("Type").equals("Buyback")) {
if (!sa.isBuyBackAbility()) { if (!sa.isBuyBackAbility()) {
return originalCost; return;
} }
} else if (params.get("Type").equals("Cycling")) { } else if (params.get("Type").equals("Cycling")) {
if (!sa.isCycling()) { if (!sa.isCycling()) {
return originalCost; return;
} }
} else if (params.get("Type").equals("Equip")) { } else if (params.get("Type").equals("Equip")) {
if (!(sa instanceof AbilityActivated) || !sa.hasParam("Equip")) { if (!(sa instanceof AbilityActivated) || !sa.hasParam("Equip")) {
return originalCost; return;
} }
} else if (params.get("Type").equals("Flashback")) { } else if (params.get("Type").equals("Flashback")) {
if (!sa.isFlashBackAbility()) { if (!sa.isFlashBackAbility()) {
return originalCost; return;
} }
} }
} }
if (params.containsKey("ValidTarget")) { if (params.containsKey("ValidTarget")) {
Target tgt = sa.getTarget(); Target tgt = sa.getTarget();
if (tgt == null) { if (tgt == null) {
return originalCost; return;
} }
boolean targetValid = false; boolean targetValid = false;
for (Object target : tgt.getTargets()) { for (Object target : tgt.getTargets()) {
@@ -232,11 +228,11 @@ public class StaticAbilityCostChange {
} }
} }
if (!targetValid) { if (!targetValid) {
return originalCost; return;
} }
} }
if (params.containsKey("AffectedZone") && !card.isInZone(ZoneType.smartValueOf(params.get("AffectedZone")))) { if (params.containsKey("AffectedZone") && !card.isInZone(ZoneType.smartValueOf(params.get("AffectedZone")))) {
return originalCost; return;
} }
int value = 0; int value = 0;
if ("X".equals(amount)) { if ("X".equals(amount)) {
@@ -259,8 +255,5 @@ public class StaticAbilityCostChange {
manaCost.decreaseShard(ManaCostShard.GREEN, value); manaCost.decreaseShard(ManaCostShard.GREEN, value);
} }
} }
return manaCost;
} }
} }

View File

@@ -1,27 +1,15 @@
package forge.game; package forge.game;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import com.google.common.collect.Lists;
import forge.Card; import forge.Card;
import forge.CardColor;
import forge.CardLists;
import forge.CardPredicates;
import forge.FThreads; import forge.FThreads;
import forge.card.MagicColor;
import forge.card.ability.ApiType; import forge.card.ability.ApiType;
import forge.card.ability.effects.CharmEffect; import forge.card.ability.effects.CharmEffect;
import forge.card.cost.CostPayment; import forge.card.cost.CostPayment;
import forge.card.mana.ManaCostBeingPaid;
import forge.card.mana.ManaCostShard; import forge.card.mana.ManaCostShard;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.HumanPlaySpellAbility; import forge.card.spellability.HumanPlaySpellAbility;
import forge.card.staticability.StaticAbility;
import forge.game.ai.ComputerUtilCard;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.zone.ZoneType;
import forge.gui.GuiChoose;
/** /**
* TODO: Write javadoc for this type. * TODO: Write javadoc for this type.
@@ -84,266 +72,4 @@ public class GameActionPlay {
game.getStack().add(sa, x); game.getStack().add(sa, x);
} }
} }
/**
* <p>
* getSpellCostChange.
* </p>
*
* @param sa
* a {@link forge.card.spellability.SpellAbility} object.
* @param originalCost
* a {@link forge.card.mana.ManaCostBeingPaid} object.
* @return a {@link forge.card.mana.ManaCostBeingPaid} object.
*/
public final ManaCostBeingPaid getSpellCostChange(final SpellAbility sa, final ManaCostBeingPaid originalCost) {
// Beached
final Card originalCard = sa.getSourceCard();
final SpellAbility spell = sa;
String mana = originalCost.toString();
ManaCostBeingPaid manaCost = new ManaCostBeingPaid(mana);
if (sa.isXCost() && !originalCard.isCopiedSpell()) {
originalCard.setXManaCostPaid(0);
}
if (game == null || sa.isTrigger()) {
return manaCost;
}
if (spell.isSpell()) {
if (spell.isDelve()) {
manaCost = getCostAfterDelve(originalCost, originalCard);
} else if (spell.getSourceCard().hasKeyword("Convoke")) {
ManaCostBeingPaid convokeCost = getCostAfterConvoke(sa, originalCost, spell);
if ( null != convokeCost )
manaCost = convokeCost;
}
} // isSpell
List<Card> cardsOnBattlefield = Lists.newArrayList(game.getCardsIn(ZoneType.Battlefield));
cardsOnBattlefield.addAll(game.getCardsIn(ZoneType.Stack));
cardsOnBattlefield.addAll(game.getCardsIn(ZoneType.Command));
if (!cardsOnBattlefield.contains(originalCard)) {
cardsOnBattlefield.add(originalCard);
}
final ArrayList<StaticAbility> raiseAbilities = new ArrayList<StaticAbility>();
final ArrayList<StaticAbility> reduceAbilities = new ArrayList<StaticAbility>();
final ArrayList<StaticAbility> setAbilities = new ArrayList<StaticAbility>();
// Sort abilities to apply them in proper order
for (Card c : cardsOnBattlefield) {
final ArrayList<StaticAbility> staticAbilities = c.getStaticAbilities();
for (final StaticAbility stAb : staticAbilities) {
if (stAb.getMapParams().get("Mode").equals("RaiseCost")) {
raiseAbilities.add(stAb);
} else if (stAb.getMapParams().get("Mode").equals("ReduceCost")) {
reduceAbilities.add(stAb);
} else if (stAb.getMapParams().get("Mode").equals("SetCost")) {
setAbilities.add(stAb);
}
}
}
// Raise cost
for (final StaticAbility stAb : raiseAbilities) {
manaCost = stAb.applyAbility("RaiseCost", spell, manaCost);
}
// Reduce cost
for (final StaticAbility stAb : reduceAbilities) {
manaCost = stAb.applyAbility("ReduceCost", spell, manaCost);
}
// Set cost (only used by Trinisphere) is applied last
for (final StaticAbility stAb : setAbilities) {
manaCost = stAb.applyAbility("SetCost", spell, manaCost);
}
return manaCost;
} // GetSpellCostChange
private ManaCostBeingPaid getCostAfterConvoke(final SpellAbility sa, final ManaCostBeingPaid originalCost, final SpellAbility spell) {
List<Card> untappedCreats = CardLists.filter(spell.getActivatingPlayer().getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES);
untappedCreats = CardLists.filter(untappedCreats, CardPredicates.Presets.UNTAPPED);
if (!untappedCreats.isEmpty()) {
final List<Card> choices = new ArrayList<Card>();
choices.addAll(untappedCreats);
ArrayList<String> usableColors = new ArrayList<String>();
ManaCostBeingPaid newCost = new ManaCostBeingPaid(originalCost.toString());
Card tapForConvoke = null;
if (sa.getActivatingPlayer().isHuman()) {
tapForConvoke = GuiChoose.oneOrNone("Tap for Convoke? " + newCost.toString(), choices);
} else {
// TODO: AI to choose a creature to tap would go here
// Probably along with deciding how many creatures to
// tap
}
while (tapForConvoke != null && !untappedCreats.isEmpty()) {
final Card workingCard = (Card) tapForConvoke;
usableColors = GameActionPlay.getConvokableColors(workingCard, newCost);
if (usableColors.size() != 0) {
String chosenColor = usableColors.get(0);
if (usableColors.size() > 1) {
if (sa.getActivatingPlayer().isHuman()) {
chosenColor = GuiChoose.one("Convoke for which color?", usableColors);
} else {
// TODO: AI for choosing which color to
// convoke goes here.
}
}
if (chosenColor.equals("colorless")) {
newCost.decreaseColorlessMana(1);
} else {
String newCostStr = newCost.toString();
newCostStr = newCostStr.replaceFirst(
MagicColor.toShortString(chosenColor), "").replaceFirst(" ", " ");
newCost = new ManaCostBeingPaid(newCostStr.trim());
}
sa.addTappedForConvoke(workingCard);
choices.remove(workingCard);
untappedCreats.remove(workingCard);
if (choices.isEmpty() || (newCost.getConvertedManaCost() == 0)) {
break;
}
} else {
untappedCreats.remove(workingCard);
}
if (sa.getActivatingPlayer().isHuman()) {
tapForConvoke = GuiChoose.oneOrNone("Tap for Convoke? " + newCost.toString(), choices);
} else {
// TODO: AI to choose a creature to tap would go
// here
}
}
// will only be null if user cancelled.
if (!sa.getTappedForConvoke().isEmpty()) {
// Convoked creats are tapped here with triggers
// suppressed,
// Then again when payment is done(In
// InputPayManaCost.done()) with suppression cleared.
// This is to make sure that triggers go off at the
// right time
// AND that you can't use mana tapabilities of convoked
// creatures
// to pay the convoked cost.
for (final Card c : sa.getTappedForConvoke()) {
c.setTapped(true);
}
return newCost;
}
}
return null;
}
private ManaCostBeingPaid getCostAfterDelve(final ManaCostBeingPaid originalCost, final Card originalCard) {
ManaCostBeingPaid manaCost;
final int cardsInGrave = originalCard.getController().getCardsIn(ZoneType.Graveyard).size();
final Player pc = originalCard.getController();
if (pc.isHuman()) {
final Integer[] cntChoice = new Integer[cardsInGrave + 1];
for (int i = 0; i <= cardsInGrave; i++) {
cntChoice[i] = Integer.valueOf(i);
}
final Integer chosenAmount = GuiChoose.one("Exile how many cards?", cntChoice);
System.out.println("Delve for " + chosenAmount);
final List<Card> choices = new ArrayList<Card>(pc.getCardsIn(ZoneType.Graveyard));
final List<Card> chosen = new ArrayList<Card>();
for (int i = 0; i < chosenAmount; i++) {
final Card nowChosen = GuiChoose.oneOrNone("Exile which card?", choices);
if (nowChosen == null) {
// User canceled,abort delving.
chosen.clear();
break;
}
choices.remove(nowChosen);
chosen.add(nowChosen);
}
for (final Card c : chosen) {
game.getAction().exile(c);
}
manaCost = new ManaCostBeingPaid(originalCost.toString());
manaCost.decreaseColorlessMana(chosenAmount);
} else {
// AI
int numToExile = 0;
final int colorlessCost = originalCost.getColorlessManaAmount();
if (cardsInGrave <= colorlessCost) {
numToExile = cardsInGrave;
} else {
numToExile = colorlessCost;
}
for (int i = 0; i < numToExile; i++) {
final List<Card> grave = pc.getZone(ZoneType.Graveyard).getCards();
Card chosen = null;
for (final Card c : grave) { // Exile noncreatures first
// in
// case we can revive. Might
// wanna do some additional
// checking here for Flashback
// and the like.
if (!c.isCreature()) {
chosen = c;
break;
}
}
if (chosen == null) {
chosen = ComputerUtilCard.getWorstCreatureAI(grave);
}
if (chosen == null) {
// Should never get here but... You know how it is.
chosen = grave.get(0);
}
game.getAction().exile(chosen);
}
manaCost = new ManaCostBeingPaid(originalCost.toString());
manaCost.decreaseColorlessMana(numToExile);
}
return manaCost;
}
/**
* Gets the convokable colors.
*
* @param cardToConvoke
* the card to convoke
* @param cost
* the cost
* @return the convokable colors
*/
public static ArrayList<String> getConvokableColors(final Card cardToConvoke, final ManaCostBeingPaid cost) {
final ArrayList<String> usableColors = new ArrayList<String>();
if (cost.getColorlessManaAmount() > 0) {
usableColors.add("colorless");
}
for (final CardColor col : cardToConvoke.getColor()) {
for (final String strCol : col.toStringList()) {
if (strCol.equals("colorless")) {
continue;
}
if (cost.toString().contains(MagicColor.toShortString(strCol))) {
usableColors.add(strCol.toString());
}
}
}
return usableColors;
}
} }

View File

@@ -864,5 +864,35 @@ public class AiController {
} while ( sa != null ); } while ( sa != null );
} }
public List<Card> chooseCardsToDelve(int colorlessCost, List<Card> grave) {
List<Card> toExile = new ArrayList<Card>();
int numToExile = Math.min(grave.size(), colorlessCost);
for (int i = 0; i < numToExile; i++) {
Card chosen = null;
for (final Card c : grave) { // Exile noncreatures first in
// case we can revive. Might
// wanna do some additional
// checking here for Flashback
// and the like.
if (!c.isCreature()) {
chosen = c;
break;
}
}
if (chosen == null) {
chosen = ComputerUtilCard.getWorstCreatureAI(grave);
}
if (chosen == null) {
// Should never get here but... You know how it is.
chosen = grave.get(0);
}
toExile.add(chosen);
grave.remove(chosen);
}
return toExile;
}
} }

View File

@@ -13,7 +13,6 @@ import forge.Card;
import forge.CardLists; import forge.CardLists;
import forge.CardUtil; import forge.CardUtil;
import forge.Constant; import forge.Constant;
import forge.Singletons;
import forge.card.MagicColor; import forge.card.MagicColor;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.ApiType; import forge.card.ability.ApiType;
@@ -398,8 +397,7 @@ public class ComputerUtilMana {
final ManaCost mana = sa.getPayCosts() != null ? sa.getPayCosts().getTotalMana() : sa.getManaCost(); final ManaCost mana = sa.getPayCosts() != null ? sa.getPayCosts().getTotalMana() : sa.getManaCost();
ManaCostBeingPaid cost = new ManaCostBeingPaid(mana); ManaCostBeingPaid cost = new ManaCostBeingPaid(mana);
cost.applySpellCostChange(sa);
cost = Singletons.getModel().getGame().getActionPlay().getSpellCostChange(sa, cost);
final Card card = sa.getSourceCard(); final Card card = sa.getSourceCard();
// Tack xMana Payments into mana here if X is a set value // Tack xMana Payments into mana here if X is a set value

View File

@@ -144,7 +144,8 @@ public class HumanPlayer extends Player {
if (sa.getSourceCard().isCopiedSpell() && sa.isSpell()) { if (sa.getSourceCard().isCopiedSpell() && sa.isSpell()) {
manaCost = new ManaCostBeingPaid("0"); manaCost = new ManaCostBeingPaid("0");
} else { } else {
manaCost = game.getActionPlay().getSpellCostChange(sa, new ManaCostBeingPaid(sa.getManaCost())); manaCost = new ManaCostBeingPaid(sa.getManaCost());
manaCost.applySpellCostChange(sa);
} }
if (!manaCost.isPaid()) { if (!manaCost.isPaid()) {
@@ -193,7 +194,8 @@ public class HumanPlayer extends Player {
if (sa.getSourceCard().isCopiedSpell() && sa.isSpell()) { if (sa.getSourceCard().isCopiedSpell() && sa.isSpell()) {
manaCost = new ManaCostBeingPaid("0"); manaCost = new ManaCostBeingPaid("0");
} else { } else {
manaCost = game.getActionPlay().getSpellCostChange(sa, new ManaCostBeingPaid(sa.getManaCost())); manaCost = new ManaCostBeingPaid(sa.getManaCost());
manaCost.applySpellCostChange(sa);
} }
if( !manaCost.isPaid() ) { if( !manaCost.isPaid() ) {

View File

@@ -118,4 +118,5 @@ public abstract class PlayerController {
public abstract void playMiracle(SpellAbility miracle, Card card); public abstract void playMiracle(SpellAbility miracle, Card card);
public abstract void playMadness(SpellAbility madness); public abstract void playMadness(SpellAbility madness);
public abstract List<Card> chooseCardsToDelve(int colorLessAmount, List<Card> grave);
} }

View File

@@ -244,4 +244,12 @@ public class PlayerControllerAi extends PlayerController {
getAi().chooseAndPlaySa(false, false, madness); getAi().chooseAndPlaySa(false, false, madness);
} }
/* (non-Javadoc)
* @see forge.game.player.PlayerController#chooseCardsToDelve(int, java.util.List)
*/
@Override
public List<Card> chooseCardsToDelve(int colorlessCost, List<Card> grave) {
return getAi().chooseCardsToDelve(colorlessCost, grave);
}
} }

View File

@@ -374,4 +374,31 @@ public class PlayerControllerHuman extends PlayerController {
player.playSpellAbility(madness); player.playSpellAbility(madness);
} }
} }
@Override
public List<Card> chooseCardsToDelve(int colorLessAmount, List<Card> grave) {
List<Card> toExile = new ArrayList<Card>();
int cardsInGrave = grave.size();
final Integer[] cntChoice = new Integer[cardsInGrave + 1];
for (int i = 0; i <= cardsInGrave; i++) {
cntChoice[i] = Integer.valueOf(i);
}
final Integer chosenAmount = GuiChoose.one("Exile how many cards?", cntChoice);
System.out.println("Delve for " + chosenAmount);
for (int i = 0; i < chosenAmount; i++) {
final Card nowChosen = GuiChoose.oneOrNone("Exile which card?", grave);
if (nowChosen == null) {
// User canceled,abort delving.
toExile.clear();
break;
}
grave.remove(nowChosen);
toExile.add(nowChosen);
}
return toExile;
}
} }