From b8107ac97f16372ec8ab5b0dd75717bc4b4464b6 Mon Sep 17 00:00:00 2001 From: Maxmtg Date: Wed, 3 Apr 2013 06:59:25 +0000 Subject: [PATCH] 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) --- src/main/java/forge/card/cost/Cost.java | 7 +- .../forge/card/mana/ManaCostBeingPaid.java | 174 +++++++++++ .../card/staticability/StaticAbility.java | 14 +- .../StaticAbilityCostChange.java | 63 ++-- src/main/java/forge/game/GameActionPlay.java | 274 ------------------ src/main/java/forge/game/ai/AiController.java | 30 ++ .../java/forge/game/ai/ComputerUtilMana.java | 4 +- .../java/forge/game/player/HumanPlayer.java | 6 +- .../forge/game/player/PlayerController.java | 1 + .../forge/game/player/PlayerControllerAi.java | 8 + .../game/player/PlayerControllerHuman.java | 27 ++ 11 files changed, 283 insertions(+), 325 deletions(-) diff --git a/src/main/java/forge/card/cost/Cost.java b/src/main/java/forge/card/cost/Cost.java index b9ed4412aa5..016ea4e9982 100644 --- a/src/main/java/forge/card/cost/Cost.java +++ b/src/main/java/forge/card/cost/Cost.java @@ -23,7 +23,6 @@ import java.util.regex.Pattern; import forge.Card; import forge.CounterType; -import forge.Singletons; import forge.card.mana.ManaCost; import forge.card.mana.ManaCostBeingPaid; import forge.card.mana.ManaCostParser; @@ -366,7 +365,8 @@ public class Cost { for (final CostPart part : this.costParts) { if (part instanceof CostPartMana) { 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)); costChanged = true; @@ -374,7 +374,8 @@ public class Cost { } if (!costChanged) { // 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)); } } diff --git a/src/main/java/forge/card/mana/ManaCostBeingPaid.java b/src/main/java/forge/card/mana/ManaCostBeingPaid.java index 224309c1312..dd4ebeb4803 100644 --- a/src/main/java/forge/card/mana/ManaCostBeingPaid.java +++ b/src/main/java/forge/card/mana/ManaCostBeingPaid.java @@ -22,8 +22,21 @@ import java.util.HashMap; import java.util.List; 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.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; /** *

@@ -652,4 +665,165 @@ public class ManaCostBeingPaid { public ManaCost getStartingCost() { 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 mutableGrave = Lists.newArrayList(pc.getZone(ZoneType.Graveyard).getCards()); + final List 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 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 raiseAbilities = new ArrayList(); + final ArrayList reduceAbilities = new ArrayList(); + final ArrayList setAbilities = new ArrayList(); + + // Sort abilities to apply them in proper order + for (Card c : cardsOnBattlefield) { + final ArrayList 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 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 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 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 getConvokableColors(final Card cardToConvoke) { + final ArrayList usableColors = new ArrayList(); + + 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; + } } diff --git a/src/main/java/forge/card/staticability/StaticAbility.java b/src/main/java/forge/card/staticability/StaticAbility.java index 3ca3ff50eba..709fd184631 100644 --- a/src/main/java/forge/card/staticability/StaticAbility.java +++ b/src/main/java/forge/card/staticability/StaticAbility.java @@ -358,28 +358,26 @@ public class StaticAbility { * the originalCost * @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 if (!this.params.get("Mode").equals(mode)) { - return originalCost; + return; } if (this.isSuppressed() || !this.checkConditions()) { - return originalCost; + return; } if (mode.equals("RaiseCost")) { - return StaticAbilityCostChange.applyRaiseCostAbility(this, sa, originalCost); + StaticAbilityCostChange.applyRaiseCostAbility(this, sa, originalCost); } 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 - return StaticAbilityCostChange.applyRaiseCostAbility(this, sa, originalCost); + StaticAbilityCostChange.applyRaiseCostAbility(this, sa, originalCost); } - - return originalCost; } /** diff --git a/src/main/java/forge/card/staticability/StaticAbilityCostChange.java b/src/main/java/forge/card/staticability/StaticAbilityCostChange.java index c989725b489..468ff7ab41f 100644 --- a/src/main/java/forge/card/staticability/StaticAbilityCostChange.java +++ b/src/main/java/forge/card/staticability/StaticAbilityCostChange.java @@ -45,51 +45,50 @@ public class StaticAbilityCostChange { * @param originalCost * a ManaCost */ - public static ManaCostBeingPaid applyRaiseCostAbility(final StaticAbility staticAbility, final SpellAbility sa - , final ManaCostBeingPaid originalCost) { + public static void applyRaiseCostAbility(final StaticAbility staticAbility, final SpellAbility sa, final ManaCostBeingPaid manaCost) { final HashMap params = staticAbility.getMapParams(); final Card hostCard = staticAbility.getHostCard(); final Player activator = sa.getActivatingPlayer(); final Card card = sa.getSourceCard(); final String amount = params.get("Amount"); - final ManaCostBeingPaid manaCost = new ManaCostBeingPaid(originalCost.toString()); + if (params.containsKey("ValidCard") && !card.isValid(params.get("ValidCard").split(","), hostCard.getController(), hostCard)) { - return originalCost; + return; } if (params.containsKey("Activator") && ((activator == null) || !activator.isValid(params.get("Activator"), hostCard.getController(), hostCard))) { - return originalCost; + return; } if (params.containsKey("Type")) { if (params.get("Type").equals("Spell")) { if (!sa.isSpell()) { - return originalCost; + return; } } else if (params.get("Type").equals("Ability")) { if (!(sa instanceof AbilityActivated)) { - return originalCost; + return; } } else if (params.get("Type").equals("NonManaAbility")) { if (!(sa instanceof AbilityActivated) || sa.isManaAbility()) { - return originalCost; + return; } } else if (params.get("Type").equals("Flashback")) { if (!sa.isFlashBackAbility()) { - return originalCost; + return; } } } if (params.containsKey("AffectedZone") && !card.isInZone(ZoneType.smartValueOf(params.get("AffectedZone")))) { - return originalCost; + return; } if (params.containsKey("ValidTarget")) { Target tgt = sa.getTarget(); if (tgt == null) { - return originalCost; + return; } boolean targetValid = false; for (Object target : tgt.getTargets()) { @@ -101,13 +100,13 @@ public class StaticAbilityCostChange { } } if (!targetValid) { - return originalCost; + return; } } if (params.containsKey("ValidSpellTarget")) { Target tgt = sa.getTarget(); if (tgt == null) { - return originalCost; + return; } boolean targetValid = false; for (Object target : tgt.getTargets()) { @@ -119,7 +118,7 @@ public class StaticAbilityCostChange { } } if (!targetValid) { - return originalCost; + return; } } int value = 0; @@ -155,8 +154,6 @@ public class StaticAbilityCostChange { manaCost.increaseShard(ManaCostShard.GREEN, value); } } - - return manaCost; } /** @@ -169,58 +166,57 @@ public class StaticAbilityCostChange { * @param originalCost * a ManaCost */ - public static ManaCostBeingPaid applyReduceCostAbility(final StaticAbility staticAbility, final SpellAbility sa - , final ManaCostBeingPaid originalCost) { + public static void applyReduceCostAbility(final StaticAbility staticAbility, final SpellAbility sa, final ManaCostBeingPaid manaCost) { //Can't reduce zero cost - if (originalCost.toString().equals("0")) { - return originalCost; + if (manaCost.toString().equals("0")) { + return; } final HashMap params = staticAbility.getMapParams(); final Card hostCard = staticAbility.getHostCard(); final Player activator = sa.getActivatingPlayer(); final Card card = sa.getSourceCard(); final String amount = params.get("Amount"); - final ManaCostBeingPaid manaCost = new ManaCostBeingPaid(originalCost.toString()); + if (params.containsKey("ValidCard") && !card.isValid(params.get("ValidCard").split(","), hostCard.getController(), hostCard)) { - return originalCost; + return; } if (params.containsKey("Activator") && ((activator == null) || !activator.isValid(params.get("Activator"), hostCard.getController(), hostCard))) { - return originalCost; + return; } if (params.containsKey("Type")) { if (params.get("Type").equals("Spell")) { if (!sa.isSpell()) { - return originalCost; + return; } } else if (params.get("Type").equals("Ability")) { if (!(sa instanceof AbilityActivated)) { - return originalCost; + return; } } else if (params.get("Type").equals("Buyback")) { if (!sa.isBuyBackAbility()) { - return originalCost; + return; } } else if (params.get("Type").equals("Cycling")) { if (!sa.isCycling()) { - return originalCost; + return; } } else if (params.get("Type").equals("Equip")) { if (!(sa instanceof AbilityActivated) || !sa.hasParam("Equip")) { - return originalCost; + return; } } else if (params.get("Type").equals("Flashback")) { if (!sa.isFlashBackAbility()) { - return originalCost; + return; } } } if (params.containsKey("ValidTarget")) { Target tgt = sa.getTarget(); if (tgt == null) { - return originalCost; + return; } boolean targetValid = false; for (Object target : tgt.getTargets()) { @@ -232,11 +228,11 @@ public class StaticAbilityCostChange { } } if (!targetValid) { - return originalCost; + return; } } if (params.containsKey("AffectedZone") && !card.isInZone(ZoneType.smartValueOf(params.get("AffectedZone")))) { - return originalCost; + return; } int value = 0; if ("X".equals(amount)) { @@ -259,8 +255,5 @@ public class StaticAbilityCostChange { manaCost.decreaseShard(ManaCostShard.GREEN, value); } } - - - return manaCost; } } diff --git a/src/main/java/forge/game/GameActionPlay.java b/src/main/java/forge/game/GameActionPlay.java index fff072e4b3e..99724219ab2 100644 --- a/src/main/java/forge/game/GameActionPlay.java +++ b/src/main/java/forge/game/GameActionPlay.java @@ -1,27 +1,15 @@ package forge.game; -import java.util.ArrayList; import java.util.List; -import com.google.common.collect.Lists; - import forge.Card; -import forge.CardColor; -import forge.CardLists; -import forge.CardPredicates; import forge.FThreads; -import forge.card.MagicColor; import forge.card.ability.ApiType; import forge.card.ability.effects.CharmEffect; import forge.card.cost.CostPayment; -import forge.card.mana.ManaCostBeingPaid; import forge.card.mana.ManaCostShard; import forge.card.spellability.SpellAbility; import forge.card.spellability.HumanPlaySpellAbility; -import forge.card.staticability.StaticAbility; -import forge.game.ai.ComputerUtilCard; import forge.game.player.Player; -import forge.game.zone.ZoneType; -import forge.gui.GuiChoose; /** * TODO: Write javadoc for this type. @@ -84,266 +72,4 @@ public class GameActionPlay { game.getStack().add(sa, x); } } - - /** - *

- * getSpellCostChange. - *

- * - * @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 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 raiseAbilities = new ArrayList(); - final ArrayList reduceAbilities = new ArrayList(); - final ArrayList setAbilities = new ArrayList(); - - // Sort abilities to apply them in proper order - for (Card c : cardsOnBattlefield) { - final ArrayList 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 untappedCreats = CardLists.filter(spell.getActivatingPlayer().getCardsIn(ZoneType.Battlefield), CardPredicates.Presets.CREATURES); - untappedCreats = CardLists.filter(untappedCreats, CardPredicates.Presets.UNTAPPED); - - if (!untappedCreats.isEmpty()) { - final List choices = new ArrayList(); - choices.addAll(untappedCreats); - ArrayList usableColors = new ArrayList(); - 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 choices = new ArrayList(pc.getCardsIn(ZoneType.Graveyard)); - final List chosen = new ArrayList(); - 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 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 getConvokableColors(final Card cardToConvoke, final ManaCostBeingPaid cost) { - final ArrayList usableColors = new ArrayList(); - - 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; - } } diff --git a/src/main/java/forge/game/ai/AiController.java b/src/main/java/forge/game/ai/AiController.java index ac386890e3e..1c17d34b6fe 100644 --- a/src/main/java/forge/game/ai/AiController.java +++ b/src/main/java/forge/game/ai/AiController.java @@ -864,5 +864,35 @@ public class AiController { } while ( sa != null ); } + public List chooseCardsToDelve(int colorlessCost, List grave) { + List toExile = new ArrayList(); + 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; + } } diff --git a/src/main/java/forge/game/ai/ComputerUtilMana.java b/src/main/java/forge/game/ai/ComputerUtilMana.java index 123a7807f15..343242388d2 100644 --- a/src/main/java/forge/game/ai/ComputerUtilMana.java +++ b/src/main/java/forge/game/ai/ComputerUtilMana.java @@ -13,7 +13,6 @@ import forge.Card; import forge.CardLists; import forge.CardUtil; import forge.Constant; -import forge.Singletons; import forge.card.MagicColor; import forge.card.ability.AbilityUtils; import forge.card.ability.ApiType; @@ -398,8 +397,7 @@ public class ComputerUtilMana { final ManaCost mana = sa.getPayCosts() != null ? sa.getPayCosts().getTotalMana() : sa.getManaCost(); ManaCostBeingPaid cost = new ManaCostBeingPaid(mana); - - cost = Singletons.getModel().getGame().getActionPlay().getSpellCostChange(sa, cost); + cost.applySpellCostChange(sa); final Card card = sa.getSourceCard(); // Tack xMana Payments into mana here if X is a set value diff --git a/src/main/java/forge/game/player/HumanPlayer.java b/src/main/java/forge/game/player/HumanPlayer.java index 80fe463e5d3..1e329bd33b6 100644 --- a/src/main/java/forge/game/player/HumanPlayer.java +++ b/src/main/java/forge/game/player/HumanPlayer.java @@ -144,7 +144,8 @@ public class HumanPlayer extends Player { if (sa.getSourceCard().isCopiedSpell() && sa.isSpell()) { manaCost = new ManaCostBeingPaid("0"); } else { - manaCost = game.getActionPlay().getSpellCostChange(sa, new ManaCostBeingPaid(sa.getManaCost())); + manaCost = new ManaCostBeingPaid(sa.getManaCost()); + manaCost.applySpellCostChange(sa); } if (!manaCost.isPaid()) { @@ -193,7 +194,8 @@ public class HumanPlayer extends Player { if (sa.getSourceCard().isCopiedSpell() && sa.isSpell()) { manaCost = new ManaCostBeingPaid("0"); } else { - manaCost = game.getActionPlay().getSpellCostChange(sa, new ManaCostBeingPaid(sa.getManaCost())); + manaCost = new ManaCostBeingPaid(sa.getManaCost()); + manaCost.applySpellCostChange(sa); } if( !manaCost.isPaid() ) { diff --git a/src/main/java/forge/game/player/PlayerController.java b/src/main/java/forge/game/player/PlayerController.java index 223969c1676..093a5b82b97 100644 --- a/src/main/java/forge/game/player/PlayerController.java +++ b/src/main/java/forge/game/player/PlayerController.java @@ -118,4 +118,5 @@ public abstract class PlayerController { public abstract void playMiracle(SpellAbility miracle, Card card); public abstract void playMadness(SpellAbility madness); + public abstract List chooseCardsToDelve(int colorLessAmount, List grave); } diff --git a/src/main/java/forge/game/player/PlayerControllerAi.java b/src/main/java/forge/game/player/PlayerControllerAi.java index 9b7e0f7c909..5760322bc4f 100644 --- a/src/main/java/forge/game/player/PlayerControllerAi.java +++ b/src/main/java/forge/game/player/PlayerControllerAi.java @@ -244,4 +244,12 @@ public class PlayerControllerAi extends PlayerController { getAi().chooseAndPlaySa(false, false, madness); } + /* (non-Javadoc) + * @see forge.game.player.PlayerController#chooseCardsToDelve(int, java.util.List) + */ + @Override + public List chooseCardsToDelve(int colorlessCost, List grave) { + return getAi().chooseCardsToDelve(colorlessCost, grave); + } + } diff --git a/src/main/java/forge/game/player/PlayerControllerHuman.java b/src/main/java/forge/game/player/PlayerControllerHuman.java index 2dd14120caf..54b951f445c 100644 --- a/src/main/java/forge/game/player/PlayerControllerHuman.java +++ b/src/main/java/forge/game/player/PlayerControllerHuman.java @@ -374,4 +374,31 @@ public class PlayerControllerHuman extends PlayerController { player.playSpellAbility(madness); } } + + @Override + public List chooseCardsToDelve(int colorLessAmount, List grave) { + List toExile = new ArrayList(); + 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; + } }