diff --git a/.gitattributes b/.gitattributes index 1f9a232296b..632ccfcbb2b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -14703,7 +14703,7 @@ forge-gui/src/main/java/forge/Singletons.java svneol=native#text/plain forge-gui/src/main/java/forge/ai/AiAttackController.java svneol=native#text/plain forge-gui/src/main/java/forge/ai/AiBlockController.java svneol=native#text/plain forge-gui/src/main/java/forge/ai/AiController.java svneol=native#text/plain -forge-gui/src/main/java/forge/ai/AiCostPayment.java -text +forge-gui/src/main/java/forge/ai/AiCostDecision.java -text forge-gui/src/main/java/forge/ai/AiProfileUtil.java -text forge-gui/src/main/java/forge/ai/ComputerUtil.java svneol=native#text/plain forge-gui/src/main/java/forge/ai/ComputerUtilCard.java -text diff --git a/forge-gui/src/main/java/forge/ai/AiCostDecision.java b/forge-gui/src/main/java/forge/ai/AiCostDecision.java new file mode 100644 index 00000000000..cf267c6f466 --- /dev/null +++ b/forge-gui/src/main/java/forge/ai/AiCostDecision.java @@ -0,0 +1,666 @@ +package forge.ai; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import com.google.common.base.Predicate; +import com.google.common.collect.Lists; + +import forge.game.Game; +import forge.game.ability.AbilityUtils; +import forge.game.card.Card; +import forge.game.card.CardLists; +import forge.game.card.CardPredicates; +import forge.game.card.CounterType; +import forge.game.card.CardPredicates.Presets; +import forge.game.cost.CostAddMana; +import forge.game.cost.CostChooseCreatureType; +import forge.game.cost.CostDamage; +import forge.game.cost.CostDiscard; +import forge.game.cost.CostDraw; +import forge.game.cost.CostExile; +import forge.game.cost.CostExileAndPay; +import forge.game.cost.CostExiledMoveToGrave; +import forge.game.cost.CostFlipCoin; +import forge.game.cost.CostGainControl; +import forge.game.cost.CostGainLife; +import forge.game.cost.CostMill; +import forge.game.cost.CostPartMana; +import forge.game.cost.CostPayLife; +import forge.game.cost.CostPutCardToLib; +import forge.game.cost.CostPutCounter; +import forge.game.cost.CostRemoveAnyCounter; +import forge.game.cost.CostRemoveCounter; +import forge.game.cost.CostReturn; +import forge.game.cost.CostReveal; +import forge.game.cost.CostSacrifice; +import forge.game.cost.CostTap; +import forge.game.cost.CostTapType; +import forge.game.cost.CostUnattach; +import forge.game.cost.CostUntap; +import forge.game.cost.CostUntapType; +import forge.game.cost.PaymentDecision; +import forge.game.cost.ICostVisitor; +import forge.game.player.Player; +import forge.game.player.PlayerControllerAi; +import forge.game.spellability.SpellAbility; +import forge.game.spellability.SpellPermanent; +import forge.game.zone.ZoneType; + +public class AiCostDecision implements ICostVisitor { + + private final Player ai; + private final SpellAbility ability; + private final Card source; + + public AiCostDecision(Player ai0, SpellAbility sa, Card source0) { + ai = ai0; + ability = sa; + source = source0; + } + + + @Override + public PaymentDecision visit(CostAddMana cost) { + Integer c = cost.convertAmount(); + + if (c == null) { + c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability); + } + + return new PaymentDecision(c); + } + + + @Override + public PaymentDecision visit(CostChooseCreatureType cost) { + Integer c = cost.convertAmount(); + + if (c == null) { + final String sVar = ability.getSVar(cost.getAmount()); + // Generalize cost + if (sVar.equals("XChoice")) { + return null; // cannot pay + } else { + c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability); + } + } + return new PaymentDecision(c); + } + + @Override + public PaymentDecision visit(CostDiscard cost) { + final String type = cost.getType(); + + final List hand = ai.getCardsIn(ZoneType.Hand); + if (type.equals("LastDrawn")) { + if (!hand.contains(ai.getLastDrawnCard())) { + return null; + } + return new PaymentDecision(ai.getLastDrawnCard()); + } + else if (cost.payCostFromSource()) { + if (!hand.contains(source)) { + return null; + } + + return new PaymentDecision(source); + } + else if (type.equals("Hand")) { + return new PaymentDecision(hand); + } + + if (type.contains("WithSameName")) { + return null; + } + Integer c = cost.convertAmount(); + if (c == null) { + final String sVar = ability.getSVar(cost.getAmount()); + if (sVar.equals("XChoice")) { + return null; + } + c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability); + } + + if (type.equals("Random")) { + return new PaymentDecision(CardLists.getRandomSubList(hand, c)); + } + else { + final AiController aic = ((PlayerControllerAi)ai.getController()).getAi(); + return new PaymentDecision(aic.getCardsToDiscard(c, type.split(";"), ability)); + } + } + + @Override + public PaymentDecision visit(CostDamage cost) { + Integer c = cost.convertAmount(); + + if (c == null) { + final String sVar = ability.getSVar(cost.getAmount()); + // Generalize cost + if (sVar.equals("XChoice")) { + return null; // cannot pay + } else { + c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability); + } + } + + return new PaymentDecision(c); + } + + @Override + public PaymentDecision visit(CostDraw cost) { + Integer c = cost.convertAmount(); + + if (c == null) { + c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability); + } + + return new PaymentDecision(c); + } + + @Override + public PaymentDecision visit(CostExile cost) { + if (cost.payCostFromSource()) { + return new PaymentDecision(source); + } + + if (cost.getType().equals("All")) { + return new PaymentDecision(new ArrayList(ai.getCardsIn(cost.getFrom()))); + } + else if (cost.getType().contains("FromTopGrave")) { + return null; + } + + Integer c = cost.convertAmount(); + if (c == null) { + final String sVar = ability.getSVar(cost.getAmount()); + // Generalize cost + if (sVar.equals("XChoice")) { + return null; + } + c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability); + } + + if (cost.getFrom().equals(ZoneType.Library)) { + return new PaymentDecision(ai.getCardsIn(ZoneType.Library, c)); + } + else if (cost.sameZone) { + // TODO Determine exile from same zone for AI + return null; + } + else { + List chosen = ComputerUtil.chooseExileFrom(ai, cost.getFrom(), cost.getType(), source, ability.getTargetCard(), c); + return null == chosen ? null : new PaymentDecision(chosen); + } + } + + @Override + public PaymentDecision visit(CostExileAndPay cost) { + List validGrave = CardLists.getValidCards(ability.getActivatingPlayer().getZone(ZoneType.Graveyard), "Creature", ability.getActivatingPlayer(), ability.getSourceCard()); + + if(validGrave.size() == 0) + { + return null; + } + + Card bestCard = null; + int bestScore = 0; + + for(Card candidate : validGrave) + { + boolean selectable = false; + for(SpellAbility sa : candidate.getSpellAbilities()) + { + if(sa instanceof SpellPermanent) + { + if(ComputerUtilCost.canPayCost(sa, ai)) + { + selectable = true; + } + } + } + + if(!selectable) + { + continue; + } + + int candidateScore = ComputerUtilCard.evaluateCreature(candidate); + if(candidateScore > bestScore) + { + bestScore = candidateScore; + bestCard = candidate; + } + } + + return bestCard == null ? null : new PaymentDecision(bestCard); + } + + @Override + public PaymentDecision visit(CostExiledMoveToGrave cost) { + Integer c = cost.convertAmount(); + List chosen = new ArrayList(); + + if (c == null) { + c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability); + } + + List typeList = ai.getGame().getCardsIn(ZoneType.Exile); + + typeList = CardLists.getValidCards(typeList, cost.getType().split(";"), ai, source); + + if (typeList.size() < c) { + return null; + } + + CardLists.sortByPowerAsc(typeList); + Collections.reverse(typeList); + + for (int i = 0; i < c; i++) { + chosen.add(typeList.get(i)); + } + + return chosen.isEmpty() ? null : new PaymentDecision(chosen); + } + + @Override + public PaymentDecision visit(CostFlipCoin cost) { + Integer c = cost.convertAmount(); + if (c == null) { + final String sVar = ability.getSVar(cost.getAmount()); + // Generalize cost + if (sVar.equals("XChoice")) { + return null; + } + c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability); + } + return new PaymentDecision(c); + } + + @Override + public PaymentDecision visit(CostGainControl cost) { + if (cost.payCostFromSource()) + return new PaymentDecision(source); + + Integer c = cost.convertAmount(); + if (c == null) { + c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability); + } + + final List typeList = CardLists.getValidCards(ai.getGame().getCardsIn(ZoneType.Battlefield), cost.getType().split(";"), ai, source); + + + if (typeList.size() < c) { + return null; + } + + CardLists.sortByPowerAsc(typeList); + final List res = new ArrayList(); + + for (int i = 0; i < c; i++) { + res.add(typeList.get(i)); + } + return res.isEmpty() ? null : new PaymentDecision(res); + } + + + @Override + public PaymentDecision visit(CostGainLife cost) { + Integer c = cost.convertAmount(); + if (c == null) { + final String sVar = ability.getSVar(cost.getAmount()); + // Generalize cost + if (sVar.equals("XChoice")) { + return null; + } else { + c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability); + } + } + + final List oppsThatCanGainLife = new ArrayList(); + for (final Player opp : ai.getOpponents()) { + if (opp.canGainLife()) { + oppsThatCanGainLife.add(opp); + } + } + + if (oppsThatCanGainLife.size() == 0) { + return null; + } + + return new PaymentDecision(c); + } + + + @Override + public PaymentDecision visit(CostMill cost) { + Integer c = cost.convertAmount(); + if (c == null) { + final String sVar = ability.getSVar(cost.getAmount()); + // Generalize cost + if (sVar.equals("XChoice")) { + return null; + } + + c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability); + } + + List topLib = ai.getCardsIn(ZoneType.Library, c); + return topLib.size() < c ? null : new PaymentDecision(topLib); + } + + @Override + public PaymentDecision visit(CostPartMana cost) { + return new PaymentDecision(0); + } + + @Override + public PaymentDecision visit(CostPayLife cost) { + Integer c = cost.convertAmount(); + if (c == null) { + final String sVar = ability.getSVar(cost.getAmount()); + // Generalize cost + if (sVar.equals("XChoice")) { + return null; + } else { + c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability); + } + } + if (!ai.canPayLife(c)) { + return null; + } + // activator.payLife(c, null); + return new PaymentDecision(c); + } + + + @Override + public PaymentDecision visit(CostPutCardToLib cost) { + Integer c = cost.convertAmount(); + final Game game = ai.getGame(); + List chosen = new ArrayList(); + List list; + + if (cost.isSameZone()) { + list = new ArrayList(game.getCardsIn(cost.getFrom())); + } else { + list = new ArrayList(ai.getCardsIn(cost.getFrom())); + } + + if (c == null) { + final String sVar = ability.getSVar(cost.getAmount()); + // Generalize cost + if (sVar.equals("XChoice")) { + return null; + } + + c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability); + } + + list = CardLists.getValidCards(list, cost.getType().split(";"), ai, source); + + if (cost.isSameZone()) { + // Jotun Grunt + // TODO: improve AI + final List players = game.getPlayers(); + for (Player p : players) { + List enoughType = CardLists.filter(list, CardPredicates.isOwner(p)); + if (enoughType.size() >= c) { + chosen.addAll(enoughType); + break; + } + } + chosen = chosen.subList(0, c); + } else { + chosen = ComputerUtil.choosePutToLibraryFrom(ai, cost.getFrom(), cost.getType(), source, ability.getTargetCard(), c); + } + return chosen.isEmpty() ? null : new PaymentDecision(chosen); + } + + @Override + public PaymentDecision visit(CostPutCounter cost) { + + if (cost.payCostFromSource()) { + return new PaymentDecision(source); + + } + + final List typeList = CardLists.getValidCards(ai.getGame().getCardsIn(ZoneType.Battlefield), cost.getType().split(";"), ai, source); + + Card card = null; + if (cost.getType().equals("Creature.YouCtrl")) { + card = ComputerUtilCard.getWorstCreatureAI(typeList); + } else { + card = ComputerUtilCard.getWorstPermanentAI(typeList, false, false, false, false); + } + return new PaymentDecision(card); + } + + + @Override + public PaymentDecision visit(CostTap cost) { + return new PaymentDecision(0); + } + + @Override + public PaymentDecision visit(CostTapType cost) { + final String amount = cost.getAmount(); + Integer c = cost.convertAmount(); + if (c == null) { + final String sVar = ability.getSVar(amount); + if (sVar.equals("XChoice")) { + List typeList = + CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), cost.getType().split(";"), ability.getActivatingPlayer(), ability.getSourceCard()); + typeList = CardLists.filter(typeList, Presets.UNTAPPED); + c = typeList.size(); + source.setSVar("ChosenX", "Number$" + Integer.toString(c)); + } else { + c = AbilityUtils.calculateAmount(source, amount, ability); + } + } + if (cost.getType().contains("sharesCreatureTypeWith") || cost.getType().contains("withTotalPowerGE")) { + return null; + } + + List totap = ComputerUtil.chooseTapType(ai, cost.getType(), source, !cost.canTapSource, c); + + + if (totap == null) { + System.out.println("Couldn't find a valid card to tap for: " + source.getName()); + return null; + } + + return new PaymentDecision(totap); + } + + + @Override + public PaymentDecision visit(CostSacrifice cost) { + if (cost.payCostFromSource()) { + return new PaymentDecision(source); + } + if (cost.getAmount().equals("All")) { + /*List typeList = new ArrayList(activator.getCardsIn(ZoneType.Battlefield)); + typeList = CardLists.getValidCards(typeList, cost.getType().split(";"), activator, source); + if (activator.hasKeyword("You can't sacrifice creatures to cast spells or activate abilities.")) { + typeList = CardLists.getNotType(typeList, "Creature"); + }*/ + // Does the AI want to use Sacrifice All? + return null; + } + + Integer c = cost.convertAmount(); + if (c == null) { + if (ability.getSVar(cost.getAmount()).equals("XChoice")) { + return null; + } + + c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability); + } + List list = ComputerUtil.chooseSacrificeType(ai, cost.getType(), source, ability.getTargetCard(), c); + return new PaymentDecision(list); + } + + @Override + public PaymentDecision visit(CostReturn cost) { + if (cost.payCostFromSource()) + return new PaymentDecision(source); + + Integer c = cost.convertAmount(); + if (c == null) { + c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability); + } + + List res = ComputerUtil.chooseReturnType(ai, cost.getType(), source, ability.getTargetCard(), c); + return res.isEmpty() ? null : new PaymentDecision(res); + } + + @Override + public PaymentDecision visit(CostReveal cost) { + + final String type = cost.getType(); + List hand = new ArrayList(ai.getCardsIn(ZoneType.Hand)); + + if (cost.payCostFromSource()) { + if (!hand.contains(source)) { + return null; + } + return new PaymentDecision(source); + } + + if (cost.getType().equals("Hand")) + return new PaymentDecision(new ArrayList(ai.getCardsIn(ZoneType.Hand))); + + if (cost.getType().equals("SameColor")) { + return null; + } + + hand = CardLists.getValidCards(hand, type.split(";"), ai, source); + Integer c = cost.convertAmount(); + if (c == null) { + final String sVar = ability.getSVar(cost.getAmount()); + if (sVar.equals("XChoice")) { + c = hand.size(); + } else { + c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability); + } + } + + final AiController aic = ((PlayerControllerAi)ai.getController()).getAi(); + return new PaymentDecision(aic.getCardsToDiscard(c, type.split(";"), ability)); + } + + @Override + public PaymentDecision visit(CostRemoveAnyCounter cost) { + final String amount = cost.getAmount(); + final int c = AbilityUtils.calculateAmount(source, amount, ability); + final String type = cost.getType(); + + List typeList = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), type.split(";"), ai, source); + List hperms = CardLists.filter(typeList, new Predicate() { + @Override + public boolean apply(final Card crd) { + for (final CounterType c1 : CounterType.values()) { + if (crd.getCounters(c1) >= c && ComputerUtil.isNegativeCounter(c1, crd)) { + return true; + } + } + return false; + } + }); + // Only find cards with enough negative counters + // TODO: add ai for Chisei, Heart of Oceans + return hperms.isEmpty() ? null : new PaymentDecision(hperms); + } + + @Override + public PaymentDecision visit(CostRemoveCounter cost) { + final String amount = cost.getAmount(); + Integer c = cost.convertAmount(); + final String type = cost.getType(); + + if (c == null) { + final String sVar = ability.getSVar(amount); + if (sVar.equals("XChoice")) { + return null; + } + if (amount.equals("All")) { + c = source.getCounters(cost.getCounter()); + } else { + c = AbilityUtils.calculateAmount(source, amount, ability); + } + } + + if (!cost.payCostFromSource()) { + List typeList; + if (type.equals("OriginalHost")) { + typeList = Lists.newArrayList(ability.getOriginalHost()); + } else { + typeList = CardLists.getValidCards(ai.getCardsIn(cost.getZone()), type.split(";"), ai, source); + } + for (Card card : typeList) { + if (card.getCounters(cost.getCounter()) >= c) { + return new PaymentDecision(card); + } + } + return null; + } + + if (c > source.getCounters(cost.getCounter())) { + System.out.println("Not enough " + cost.getCounter() + " on " + source.getName()); + return null; + } + + PaymentDecision result = new PaymentDecision(source); + result.c = c; // cost.cntRemoved = c; + return result; + } + + @Override + public PaymentDecision visit(CostUntapType cost) { + final String amount = cost.getAmount(); + Integer c = cost.convertAmount(); + if (c == null) { + final String sVar = ability.getSVar(amount); + if (sVar.equals("XChoice")) { + List typeList = ai.getGame().getCardsIn(ZoneType.Battlefield); + typeList = CardLists.getValidCards(typeList, cost.getType().split(";"), ai, ability.getSourceCard()); + if (!cost.canUntapSource) { + typeList.remove(source); + } + typeList = CardLists.filter(typeList, Presets.TAPPED); + c = typeList.size(); + source.setSVar("ChosenX", "Number$" + Integer.toString(c)); + } else { + c = AbilityUtils.calculateAmount(source, amount, ability); + } + } + + List list = ComputerUtil.chooseUntapType(ai, cost.getType(), source, cost.canUntapSource, c); + + if (list == null) { + System.out.println("Couldn't find a valid card to untap for: " + source.getName()); + return null; + } + + return new PaymentDecision(list); + } + + @Override + public PaymentDecision visit(CostUntap cost) { + return new PaymentDecision(0); + } + + @Override + public PaymentDecision visit(CostUnattach cost) { + Card cardToUnattach = cost.findCardToUnattach(source, (Player) ai, ability); + if (cardToUnattach == null) { + // We really shouldn't be able to get here if there's nothing to unattach + return null; + } + return new PaymentDecision(cardToUnattach); + } +} + diff --git a/forge-gui/src/main/java/forge/ai/AiCostPayment.java b/forge-gui/src/main/java/forge/ai/AiCostPayment.java deleted file mode 100644 index 83dd3a02f93..00000000000 --- a/forge-gui/src/main/java/forge/ai/AiCostPayment.java +++ /dev/null @@ -1,8 +0,0 @@ -package forge.ai; - -import forge.game.cost.PaymentDecision; -import forge.game.cost.ICostVisitor; - -public class AiCostPayment extends ICostVisitor.Base { - -} diff --git a/forge-gui/src/main/java/forge/ai/ability/DrawAi.java b/forge-gui/src/main/java/forge/ai/ability/DrawAi.java index 8e5040c3e47..b60a8bd6369 100644 --- a/forge-gui/src/main/java/forge/ai/ability/DrawAi.java +++ b/forge-gui/src/main/java/forge/ai/ability/DrawAi.java @@ -18,6 +18,7 @@ */ package forge.ai.ability; +import forge.ai.AiCostDecision; import forge.ai.ComputerUtil; import forge.ai.ComputerUtilCost; import forge.ai.ComputerUtilMana; @@ -65,10 +66,10 @@ public class DrawAi extends SpellAbilityAi { } if (!ComputerUtilCost.checkDiscardCost(ai, abCost, source)) { + AiCostDecision aiDecisions = new AiCostDecision(ai, sa, source); for (final CostPart part : abCost.getCostParts()) { if (part instanceof CostDiscard) { - CostDiscard cd = (CostDiscard) part; - PaymentDecision decision = cd.decideAIPayment(ai, sa, sa.getSourceCard()); + PaymentDecision decision = part.accept(aiDecisions); if ( null == decision ) return false; for (Card discard : decision.cards) { diff --git a/forge-gui/src/main/java/forge/game/cost/CostAddMana.java b/forge-gui/src/main/java/forge/game/cost/CostAddMana.java index c19b3a6323f..25bb2e0e51a 100644 --- a/forge-gui/src/main/java/forge/game/cost/CostAddMana.java +++ b/forge-gui/src/main/java/forge/game/cost/CostAddMana.java @@ -151,24 +151,6 @@ public class CostAddMana extends CostPart { return true; } - /* - * (non-Javadoc) - * - * @see - * forge.card.cost.CostPart#decideAIPayment(forge.card.spellability.SpellAbility - * , forge.Card, forge.card.cost.Cost_Payment) - */ - @Override - public final PaymentDecision decideAIPayment(final Player ai, final SpellAbility ability, final Card source) { - Integer c = this.convertAmount(); - - if (c == null) { - c = AbilityUtils.calculateAmount(source, this.getAmount(), ability); - } - - return new PaymentDecision(c); - } - @Override public T accept(ICostVisitor visitor) { return visitor.visit(this); diff --git a/forge-gui/src/main/java/forge/game/cost/CostChooseCreatureType.java b/forge-gui/src/main/java/forge/game/cost/CostChooseCreatureType.java index 2f79240983d..4543ac79a5b 100644 --- a/forge-gui/src/main/java/forge/game/cost/CostChooseCreatureType.java +++ b/forge-gui/src/main/java/forge/game/cost/CostChooseCreatureType.java @@ -20,7 +20,6 @@ package forge.game.cost; import java.util.ArrayList; import forge.card.CardType; -import forge.game.ability.AbilityUtils; import forge.game.card.Card; import forge.game.player.Player; import forge.game.spellability.SpellAbility; @@ -85,28 +84,8 @@ public class CostChooseCreatureType extends CostPart { } - /* (non-Javadoc) - * @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card) - */ - @Override - public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) { - Integer c = this.convertAmount(); - - if (c == null) { - final String sVar = ability.getSVar(this.getAmount()); - // Generalize this - if (sVar.equals("XChoice")) { - return null; // cannot pay - } else { - c = AbilityUtils.calculateAmount(source, this.getAmount(), ability); - } - } - return new PaymentDecision(c); - } - @Override - public boolean payAI(PaymentDecision decision, Player ai, - SpellAbility ability, Card source) { + public boolean payAI(PaymentDecision decision, Player ai, SpellAbility ability, Card source) { String choice = ai.getController().chooseSomeType("Creature", ability, new ArrayList(CardType.getCreatureTypes()), new ArrayList()); source.setChosenType(choice); return true; diff --git a/forge-gui/src/main/java/forge/game/cost/CostDamage.java b/forge-gui/src/main/java/forge/game/cost/CostDamage.java index 178ae82a24b..31b6545eb26 100644 --- a/forge-gui/src/main/java/forge/game/cost/CostDamage.java +++ b/forge-gui/src/main/java/forge/game/cost/CostDamage.java @@ -98,30 +98,6 @@ public class CostDamage extends CostPart { return false; } - /* - * (non-Javadoc) - * - * @see - * forge.card.cost.CostPart#decideAIPayment(forge.card.spellability.SpellAbility - * , forge.Card, forge.card.cost.Cost_Payment) - */ - @Override - public final PaymentDecision decideAIPayment(final Player ai, final SpellAbility ability, final Card source) { - Integer c = this.convertAmount(); - - if (c == null) { - final String sVar = ability.getSVar(this.getAmount()); - // Generalize this - if (sVar.equals("XChoice")) { - return null; // cannot pay - } else { - c = AbilityUtils.calculateAmount(source, this.getAmount(), ability); - } - } - - return new PaymentDecision(c); - } - @Override public T accept(ICostVisitor visitor) { return visitor.visit(this); diff --git a/forge-gui/src/main/java/forge/game/cost/CostDiscard.java b/forge-gui/src/main/java/forge/game/cost/CostDiscard.java index bae3e3f3da5..72b99e77357 100644 --- a/forge-gui/src/main/java/forge/game/cost/CostDiscard.java +++ b/forge-gui/src/main/java/forge/game/cost/CostDiscard.java @@ -21,13 +21,11 @@ import java.util.ArrayList; import java.util.List; import com.google.common.base.Predicate; -import forge.ai.AiController; import forge.game.ability.AbilityUtils; import forge.game.card.Card; import forge.game.card.CardLists; import forge.game.card.CardPredicates; import forge.game.player.Player; -import forge.game.player.PlayerControllerAi; import forge.game.spellability.SpellAbility; import forge.game.zone.ZoneType; import forge.gui.input.InputSelectCardsFromList; @@ -257,52 +255,6 @@ public class CostDiscard extends CostPartWithList { } } - /* (non-Javadoc) - * @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card) - */ - @Override - public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) { - final String type = this.getType(); - - final List hand = ai.getCardsIn(ZoneType.Hand); - if (type.equals("LastDrawn")) { - if (!hand.contains(ai.getLastDrawnCard())) { - return null; - } - return new PaymentDecision(ai.getLastDrawnCard()); - } - else if (this.payCostFromSource()) { - if (!hand.contains(source)) { - return null; - } - - return new PaymentDecision(source); - } - else if (type.equals("Hand")) { - return new PaymentDecision(hand); - } - - if (type.contains("WithSameName")) { - return null; - } - Integer c = this.convertAmount(); - if (c == null) { - final String sVar = ability.getSVar(this.getAmount()); - if (sVar.equals("XChoice")) { - return null; - } - c = AbilityUtils.calculateAmount(source, this.getAmount(), ability); - } - - if (type.equals("Random")) { - return new PaymentDecision(CardLists.getRandomSubList(hand, c)); - } - else { - final AiController aic = ((PlayerControllerAi)ai.getController()).getAi(); - return new PaymentDecision(aic.getCardsToDiscard(c, type.split(";"), ability)); - } - } - /* (non-Javadoc) * @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card) */ diff --git a/forge-gui/src/main/java/forge/game/cost/CostDraw.java b/forge-gui/src/main/java/forge/game/cost/CostDraw.java index b900b850fc9..00a33356042 100644 --- a/forge-gui/src/main/java/forge/game/cost/CostDraw.java +++ b/forge-gui/src/main/java/forge/game/cost/CostDraw.java @@ -122,24 +122,6 @@ public class CostDraw extends CostPart { return true; } - /* - * (non-Javadoc) - * - * @see - * forge.card.cost.CostPart#decideAIPayment(forge.card.spellability.SpellAbility - * , forge.Card, forge.card.cost.Cost_Payment) - */ - @Override - public final PaymentDecision decideAIPayment(final Player ai, final SpellAbility ability, final Card source) { - Integer c = this.convertAmount(); - - if (c == null) { - c = AbilityUtils.calculateAmount(source, this.getAmount(), ability); - } - - return new PaymentDecision(c); - } - @Override public T accept(ICostVisitor visitor) { return visitor.visit(this); diff --git a/forge-gui/src/main/java/forge/game/cost/CostExile.java b/forge-gui/src/main/java/forge/game/cost/CostExile.java index f3d53ff7cf8..0dce95431bb 100644 --- a/forge-gui/src/main/java/forge/game/cost/CostExile.java +++ b/forge-gui/src/main/java/forge/game/cost/CostExile.java @@ -22,7 +22,6 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; -import forge.ai.ComputerUtil; import forge.game.Game; import forge.game.ability.AbilityUtils; import forge.game.card.Card; @@ -51,7 +50,7 @@ public class CostExile extends CostPartWithList { */ private ZoneType from = ZoneType.Battlefield; - private boolean sameZone = false; + public final boolean sameZone; /** * Gets the from. @@ -75,14 +74,14 @@ public class CostExile extends CostPartWithList { * the from */ public CostExile(final String amount, final String type, final String description, final ZoneType from) { + this(amount, type, description, from, false); + } + + public CostExile(final String amount, final String type, final String description, final ZoneType from, final boolean sameZone) { super(amount, type, description); if (from != null) { this.from = from; } - } - - public CostExile(final String amount, final String type, final String description, final ZoneType from, final boolean sameZone) { - this(amount, type, description, from); this.sameZone = sameZone; } @@ -459,45 +458,6 @@ public class CostExile extends CostPartWithList { return "Exiled"; } - /* (non-Javadoc) - * @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card) - */ - @Override - public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) { - if (this.payCostFromSource()) { - return new PaymentDecision(source); - } - - if (this.getType().equals("All")) { - return new PaymentDecision(new ArrayList(ai.getCardsIn(this.getFrom()))); - } - else if (this.getType().contains("FromTopGrave")) { - return null; - } - - Integer c = this.convertAmount(); - if (c == null) { - final String sVar = ability.getSVar(this.getAmount()); - // Generalize this - if (sVar.equals("XChoice")) { - return null; - } - c = AbilityUtils.calculateAmount(source, this.getAmount(), ability); - } - - if (this.from.equals(ZoneType.Library)) { - return new PaymentDecision(ai.getCardsIn(ZoneType.Library, c)); - } - else if (this.sameZone) { - // TODO Determine exile from same zone for AI - return null; - } - else { - List chosen = ComputerUtil.chooseExileFrom(ai, this.getFrom(), this.getType(), source, ability.getTargetCard(), c); - return null == chosen ? null : new PaymentDecision(chosen); - } - } - /* (non-Javadoc) * @see forge.card.cost.CostPart#payAI(forge.card.cost.PaymentDecision, forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card) */ diff --git a/forge-gui/src/main/java/forge/game/cost/CostExileAndPay.java b/forge-gui/src/main/java/forge/game/cost/CostExileAndPay.java index 48e40cc69c6..aaaa1763db5 100644 --- a/forge-gui/src/main/java/forge/game/cost/CostExileAndPay.java +++ b/forge-gui/src/main/java/forge/game/cost/CostExileAndPay.java @@ -3,7 +3,6 @@ package forge.game.cost; import java.util.ArrayList; import java.util.List; -import forge.ai.ComputerUtilCard; import forge.ai.ComputerUtilCost; import forge.game.card.Card; import forge.game.card.CardLists; @@ -43,51 +42,6 @@ public class CostExileAndPay extends CostPartWithList { return CardLists.getValidCards(ability.getActivatingPlayer().getZone(ZoneType.Graveyard), "Creature", ability.getActivatingPlayer(), ability.getSourceCard()).size() > 0; } - /* (non-Javadoc) - * @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card) - */ - @Override - public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) { - List validGrave = CardLists.getValidCards(ability.getActivatingPlayer().getZone(ZoneType.Graveyard), "Creature", ability.getActivatingPlayer(), ability.getSourceCard()); - - if(validGrave.size() == 0) - { - return null; - } - - Card bestCard = null; - int bestScore = 0; - - for(Card candidate : validGrave) - { - boolean selectable = false; - for(SpellAbility sa : candidate.getSpellAbilities()) - { - if(sa instanceof SpellPermanent) - { - if(ComputerUtilCost.canPayCost(sa, ai)) - { - selectable = true; - } - } - } - - if(!selectable) - { - continue; - } - - int candidateScore = ComputerUtilCard.evaluateCreature(candidate); - if(candidateScore > bestScore) - { - bestScore = candidateScore; - bestCard = candidate; - } - } - - return bestCard == null ? null : new PaymentDecision(bestCard); - } - /* (non-Javadoc) * @see forge.card.cost.CostPart#payHuman(forge.card.spellability.SpellAbility, forge.game.GameState) */ diff --git a/forge-gui/src/main/java/forge/game/cost/CostExiledMoveToGrave.java b/forge-gui/src/main/java/forge/game/cost/CostExiledMoveToGrave.java index 9de3d6c5964..60b2a849d89 100644 --- a/forge-gui/src/main/java/forge/game/cost/CostExiledMoveToGrave.java +++ b/forge-gui/src/main/java/forge/game/cost/CostExiledMoveToGrave.java @@ -17,8 +17,6 @@ */ package forge.game.cost; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; import forge.game.ability.AbilityUtils; @@ -155,36 +153,6 @@ public class CostExiledMoveToGrave extends CostPartWithList { targetCard.getGame().getAction().moveToGraveyard(targetCard); } - /* (non-Javadoc) - * @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card) - */ - @Override - public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) { - Integer c = this.convertAmount(); - List chosen = new ArrayList(); - - if (c == null) { - c = AbilityUtils.calculateAmount(source, this.getAmount(), ability); - } - - List typeList = ai.getGame().getCardsIn(ZoneType.Exile); - - typeList = CardLists.getValidCards(typeList, this.getType().split(";"), ai, source); - - if (typeList.size() < c) { - return null; - } - - CardLists.sortByPowerAsc(typeList); - Collections.reverse(typeList); - - for (int i = 0; i < c; i++) { - chosen.add(typeList.get(i)); - } - - return chosen.isEmpty() ? null : new PaymentDecision(chosen); - } - public T accept(ICostVisitor visitor) { return visitor.visit(this); } diff --git a/forge-gui/src/main/java/forge/game/cost/CostFlipCoin.java b/forge-gui/src/main/java/forge/game/cost/CostFlipCoin.java index e2566d6e8c2..a8af079a76d 100644 --- a/forge-gui/src/main/java/forge/game/cost/CostFlipCoin.java +++ b/forge-gui/src/main/java/forge/game/cost/CostFlipCoin.java @@ -106,22 +106,6 @@ public class CostFlipCoin extends CostPartWithList { FlipCoinEffect.flipCoinCall(activator, ability, i); } - /* (non-Javadoc) - * @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card) - */ - @Override - public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) { - Integer c = this.convertAmount(); - if (c == null) { - final String sVar = ability.getSVar(this.getAmount()); - // Generalize this - if (sVar.equals("XChoice")) { - return null; - } - c = AbilityUtils.calculateAmount(source, this.getAmount(), ability); - } - return new PaymentDecision(c); - } /* * (non-Javadoc) * diff --git a/forge-gui/src/main/java/forge/game/cost/CostGainControl.java b/forge-gui/src/main/java/forge/game/cost/CostGainControl.java index 820af3e8449..57f5bd822ae 100644 --- a/forge-gui/src/main/java/forge/game/cost/CostGainControl.java +++ b/forge-gui/src/main/java/forge/game/cost/CostGainControl.java @@ -116,39 +116,6 @@ public class CostGainControl extends CostPartWithList { return true; } - /* - * (non-Javadoc) - * - * @see - * forge.card.cost.CostPart#decideAIPayment(forge.card.spellability.SpellAbility - * , forge.Card, forge.card.cost.Cost_Payment) - */ - @Override - public final PaymentDecision decideAIPayment(final Player ai, final SpellAbility ability, final Card source) { - if (this.payCostFromSource()) - return new PaymentDecision(source); - - Integer c = this.convertAmount(); - if (c == null) { - c = AbilityUtils.calculateAmount(source, this.getAmount(), ability); - } - - final List typeList = CardLists.getValidCards(ai.getGame().getCardsIn(ZoneType.Battlefield), this.getType().split(";"), ai, source); - - - if (typeList.size() < c) { - return null; - } - - CardLists.sortByPowerAsc(typeList); - final List res = new ArrayList(); - - for (int i = 0; i < c; i++) { - res.add(typeList.get(i)); - } - return res.isEmpty() ? null : new PaymentDecision(res); - } - /* (non-Javadoc) * @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card) */ diff --git a/forge-gui/src/main/java/forge/game/cost/CostGainLife.java b/forge-gui/src/main/java/forge/game/cost/CostGainLife.java index e7a042fc238..76bbdc9bab7 100644 --- a/forge-gui/src/main/java/forge/game/cost/CostGainLife.java +++ b/forge-gui/src/main/java/forge/game/cost/CostGainLife.java @@ -161,39 +161,6 @@ public class CostGainLife extends CostPart { return true; } - /* - * (non-Javadoc) - * - * @see - * forge.card.cost.CostPart#decideAIPayment(forge.card.spellability.SpellAbility - * , forge.Card, forge.card.cost.Cost_Payment) - */ - @Override - public final PaymentDecision decideAIPayment(final Player ai, final SpellAbility ability, final Card source) { - Integer c = this.convertAmount(); - if (c == null) { - final String sVar = ability.getSVar(this.getAmount()); - // Generalize this - if (sVar.equals("XChoice")) { - return null; - } else { - c = AbilityUtils.calculateAmount(source, this.getAmount(), ability); - } - } - - final List oppsThatCanGainLife = new ArrayList(); - for (final Player opp : ai.getOpponents()) { - if (opp.canGainLife()) { - oppsThatCanGainLife.add(opp); - } - } - - if (oppsThatCanGainLife.size() == 0) { - return null; - } - - return new PaymentDecision(c); - } public T accept(ICostVisitor visitor) { return visitor.visit(this); diff --git a/forge-gui/src/main/java/forge/game/cost/CostMill.java b/forge-gui/src/main/java/forge/game/cost/CostMill.java index a69de8e4517..4a1f8110436 100644 --- a/forge-gui/src/main/java/forge/game/cost/CostMill.java +++ b/forge-gui/src/main/java/forge/game/cost/CostMill.java @@ -147,26 +147,6 @@ public class CostMill extends CostPartWithList { targetCard.getGame().getAction().moveToGraveyard(targetCard); } - /* (non-Javadoc) - * @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card) - */ - @Override - public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) { - Integer c = this.convertAmount(); - if (c == null) { - final String sVar = ability.getSVar(this.getAmount()); - // Generalize this - if (sVar.equals("XChoice")) { - return null; - } - - c = AbilityUtils.calculateAmount(source, this.getAmount(), ability); - } - - List topLib = ai.getCardsIn(ZoneType.Library, c); - return topLib.size() < c ? null : new PaymentDecision(topLib); - } - public T accept(ICostVisitor visitor) { return visitor.visit(this); } diff --git a/forge-gui/src/main/java/forge/game/cost/CostPart.java b/forge-gui/src/main/java/forge/game/cost/CostPart.java index edbb2956cc7..79e6776419a 100644 --- a/forge-gui/src/main/java/forge/game/cost/CostPart.java +++ b/forge-gui/src/main/java/forge/game/cost/CostPart.java @@ -149,21 +149,6 @@ public abstract class CostPart { */ public abstract boolean canPay(SpellAbility ability); - /** - * Decide ai payment. - * - * @param ai - * {@link forge.player.Player} - * @param ability - * {@link forge.game.spellability.SpellAbility} - * @param source - * {@link forge.game.card.Card} - * @param payment - * {@link forge.game.cost.CostPayment} - * @return true, if successful - */ - public abstract PaymentDecision decideAIPayment(final Player ai, SpellAbility ability, Card source); - public abstract T accept(final ICostVisitor visitor); public abstract boolean payAI(final PaymentDecision decision, final Player ai, SpellAbility ability, Card source); diff --git a/forge-gui/src/main/java/forge/game/cost/CostPartMana.java b/forge-gui/src/main/java/forge/game/cost/CostPartMana.java index 3a1686ab46f..d105afbfa5d 100644 --- a/forge-gui/src/main/java/forge/game/cost/CostPartMana.java +++ b/forge-gui/src/main/java/forge/game/cost/CostPartMana.java @@ -182,15 +182,6 @@ public class CostPartMana extends CostPart { return ComputerUtilMana.payManaCost(ai, ability); } - - /* (non-Javadoc) - * @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card) - */ - @Override - public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) { - return new PaymentDecision(0); - } - /** * TODO: Write javadoc for this method. * @return diff --git a/forge-gui/src/main/java/forge/game/cost/CostPayLife.java b/forge-gui/src/main/java/forge/game/cost/CostPayLife.java index e2249898ade..71f6d32314e 100644 --- a/forge-gui/src/main/java/forge/game/cost/CostPayLife.java +++ b/forge-gui/src/main/java/forge/game/cost/CostPayLife.java @@ -138,28 +138,6 @@ public class CostPayLife extends CostPart { return false; } - /* (non-Javadoc) - * @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card) - */ - @Override - public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) { - Integer c = this.convertAmount(); - if (c == null) { - final String sVar = ability.getSVar(this.getAmount()); - // Generalize this - if (sVar.equals("XChoice")) { - return null; - } else { - c = AbilityUtils.calculateAmount(source, this.getAmount(), ability); - } - } - if (!ai.canPayLife(c)) { - return null; - } - // activator.payLife(c, null); - return new PaymentDecision(c); - } - public T accept(ICostVisitor visitor) { return visitor.visit(this); } diff --git a/forge-gui/src/main/java/forge/game/cost/CostPayment.java b/forge-gui/src/main/java/forge/game/cost/CostPayment.java index 505d677f657..01aa7dee3f9 100644 --- a/forge-gui/src/main/java/forge/game/cost/CostPayment.java +++ b/forge-gui/src/main/java/forge/game/cost/CostPayment.java @@ -21,6 +21,8 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; + +import forge.ai.AiCostDecision; import forge.game.Game; import forge.game.card.Card; import forge.game.player.Player; @@ -178,10 +180,11 @@ public class CostPayment { final List parts = this.cost.getCostParts(); Map, PaymentDecision> decisions = new HashMap, PaymentDecision>(); + AiCostDecision aiDecisions = new AiCostDecision(ai, ability, source); // Set all of the decisions before attempting to pay anything for (final CostPart part : parts) { - PaymentDecision decision = part.decideAIPayment(ai, this.ability, source); + PaymentDecision decision = part.accept(aiDecisions); if ( null == decision ) return false; decisions.put(part.getClass(), decision); } diff --git a/forge-gui/src/main/java/forge/game/cost/CostPutCardToLib.java b/forge-gui/src/main/java/forge/game/cost/CostPutCardToLib.java index 3da36239608..4016a58f4b4 100644 --- a/forge-gui/src/main/java/forge/game/cost/CostPutCardToLib.java +++ b/forge-gui/src/main/java/forge/game/cost/CostPutCardToLib.java @@ -20,7 +20,6 @@ package forge.game.cost; import java.util.ArrayList; import java.util.List; -import forge.ai.ComputerUtil; import forge.game.Game; import forge.game.ability.AbilityUtils; import forge.game.card.Card; @@ -319,52 +318,7 @@ public class CostPutCardToLib extends CostPartWithList { targetCard.getGame().getAction().moveToLibrary(targetCard, Integer.parseInt(getLibPos())); } - /* (non-Javadoc) - * @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card) - */ - @Override - public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) { - Integer c = this.convertAmount(); - final Game game = ai.getGame(); - List chosen = new ArrayList(); - List list; - if (this.sameZone) { - list = new ArrayList(game.getCardsIn(this.getFrom())); - } else { - list = new ArrayList(ai.getCardsIn(this.getFrom())); - } - - if (c == null) { - final String sVar = ability.getSVar(this.getAmount()); - // Generalize this - if (sVar.equals("XChoice")) { - return null; - } - - c = AbilityUtils.calculateAmount(source, this.getAmount(), ability); - } - - list = CardLists.getValidCards(list, this.getType().split(";"), ai, source); - - if (this.sameZone) { - // Jotun Grunt - // TODO: improve AI - final List players = game.getPlayers(); - for (Player p : players) { - List enoughType = CardLists.filter(list, CardPredicates.isOwner(p)); - if (enoughType.size() >= c) { - chosen.addAll(enoughType); - break; - } - } - chosen = chosen.subList(0, c); - } else { - chosen = ComputerUtil.choosePutToLibraryFrom(ai, this.getFrom(), this.getType(), source, ability.getTargetCard(), c); - } - return chosen.isEmpty() ? null : new PaymentDecision(chosen); - } - public T accept(ICostVisitor visitor) { return visitor.visit(this); } diff --git a/forge-gui/src/main/java/forge/game/cost/CostPutCounter.java b/forge-gui/src/main/java/forge/game/cost/CostPutCounter.java index 7f57575645c..e4ff7956238 100644 --- a/forge-gui/src/main/java/forge/game/cost/CostPutCounter.java +++ b/forge-gui/src/main/java/forge/game/cost/CostPutCounter.java @@ -18,7 +18,6 @@ package forge.game.cost; import java.util.List; -import forge.ai.ComputerUtilCard; import forge.game.ability.AbilityUtils; import forge.game.card.Card; import forge.game.card.CardLists; @@ -236,28 +235,6 @@ public class CostPutCounter extends CostPartWithList { return "CounterPut"; } - /* (non-Javadoc) - * @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card) - */ - @Override - public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) { - - if (this.payCostFromSource()) { - return new PaymentDecision(source); - - } - - final List typeList = CardLists.getValidCards(ai.getGame().getCardsIn(ZoneType.Battlefield), this.getType().split(";"), ai, source); - - Card card = null; - if (this.getType().equals("Creature.YouCtrl")) { - card = ComputerUtilCard.getWorstCreatureAI(typeList); - } else { - card = ComputerUtilCard.getWorstPermanentAI(typeList, false, false, false, false); - } - return new PaymentDecision(card); - } - public T accept(ICostVisitor visitor) { return visitor.visit(this); } diff --git a/forge-gui/src/main/java/forge/game/cost/CostRemoveAnyCounter.java b/forge-gui/src/main/java/forge/game/cost/CostRemoveAnyCounter.java index bc0ef18dade..026601426d4 100644 --- a/forge-gui/src/main/java/forge/game/cost/CostRemoveAnyCounter.java +++ b/forge-gui/src/main/java/forge/game/cost/CostRemoveAnyCounter.java @@ -197,34 +197,6 @@ public class CostRemoveAnyCounter extends CostPartWithList { targetCard.subtractCounter(this.getCounter(), 1); } - - - /* (non-Javadoc) - * @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card) - */ - @Override - public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) { - final String amount = this.getAmount(); - final int c = AbilityUtils.calculateAmount(source, amount, ability); - final String type = this.getType(); - - List typeList = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), type.split(";"), ai, source); - List hperms = CardLists.filter(typeList, new Predicate() { - @Override - public boolean apply(final Card crd) { - for (final CounterType c1 : CounterType.values()) { - if (crd.getCounters(c1) >= c && ComputerUtil.isNegativeCounter(c1, crd)) { - return true; - } - } - return false; - } - }); - // Only find cards with enough negative counters - // TODO: add ai for Chisei, Heart of Oceans - return hperms.isEmpty() ? null : new PaymentDecision(hperms); - } - public T accept(ICostVisitor visitor) { return visitor.visit(this); } diff --git a/forge-gui/src/main/java/forge/game/cost/CostRemoveCounter.java b/forge-gui/src/main/java/forge/game/cost/CostRemoveCounter.java index 18fd93c9e88..cf3e0f1e8c1 100644 --- a/forge-gui/src/main/java/forge/game/cost/CostRemoveCounter.java +++ b/forge-gui/src/main/java/forge/game/cost/CostRemoveCounter.java @@ -221,7 +221,7 @@ public class CostRemoveCounter extends CostPartWithList { /** * @return the zone */ - private ZoneType getZone() { + public final ZoneType getZone() { return zone; } @@ -375,50 +375,6 @@ public class CostRemoveCounter extends CostPartWithList { return "CounterRemove"; } - /* (non-Javadoc) - * @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card) - */ - @Override - public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) { - final String amount = this.getAmount(); - Integer c = this.convertAmount(); - final String type = this.getType(); - - if (c == null) { - final String sVar = ability.getSVar(amount); - if (sVar.equals("XChoice")) { - return null; - } - if (amount.equals("All")) { - c = source.getCounters(this.counter); - } else { - c = AbilityUtils.calculateAmount(source, amount, ability); - } - } - - if (!this.payCostFromSource()) { - List typeList; - if (type.equals("OriginalHost")) { - typeList = Lists.newArrayList(ability.getOriginalHost()); - } else { - typeList = CardLists.getValidCards(ai.getCardsIn(this.getZone()), type.split(";"), ai, source); - } - for (Card card : typeList) { - if (card.getCounters(this.getCounter()) >= c) { - return new PaymentDecision(card); - } - } - return null; - } - - if (c > source.getCounters(this.getCounter())) { - System.out.println("Not enough " + this.counter + " on " + source.getName()); - return null; - } - this.cntRemoved = c; - return new PaymentDecision(source); - } - public T accept(ICostVisitor visitor) { return visitor.visit(this); } diff --git a/forge-gui/src/main/java/forge/game/cost/CostReturn.java b/forge-gui/src/main/java/forge/game/cost/CostReturn.java index 3a7c7897480..98b0a329a2e 100644 --- a/forge-gui/src/main/java/forge/game/cost/CostReturn.java +++ b/forge-gui/src/main/java/forge/game/cost/CostReturn.java @@ -20,7 +20,6 @@ package forge.game.cost; import java.util.ArrayList; import java.util.List; -import forge.ai.ComputerUtil; import forge.game.ability.AbilityUtils; import forge.game.card.Card; import forge.game.card.CardLists; @@ -154,27 +153,6 @@ public class CostReturn extends CostPartWithList { return false; } - /* - * (non-Javadoc) - * - * @see - * forge.card.cost.CostPart#decideAIPayment(forge.card.spellability.SpellAbility - * , forge.Card, forge.card.cost.Cost_Payment) - */ - @Override - public final PaymentDecision decideAIPayment(final Player ai, final SpellAbility ability, final Card source) { - if (this.payCostFromSource()) - return new PaymentDecision(source); - - Integer c = this.convertAmount(); - if (c == null) { - c = AbilityUtils.calculateAmount(source, this.getAmount(), ability); - } - - List res = ComputerUtil.chooseReturnType(ai, this.getType(), source, ability.getTargetCard(), c); - return res.isEmpty() ? null : new PaymentDecision(res); - } - /* (non-Javadoc) * @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card) */ diff --git a/forge-gui/src/main/java/forge/game/cost/CostReveal.java b/forge-gui/src/main/java/forge/game/cost/CostReveal.java index 0916be252c2..d885cb0b345 100644 --- a/forge-gui/src/main/java/forge/game/cost/CostReveal.java +++ b/forge-gui/src/main/java/forge/game/cost/CostReveal.java @@ -24,13 +24,11 @@ import java.util.List; import com.google.common.base.Predicate; import com.google.common.collect.Lists; -import forge.ai.AiController; import forge.game.ability.AbilityUtils; import forge.game.card.Card; import forge.game.card.CardLists; import forge.game.card.CardPredicates; import forge.game.player.Player; -import forge.game.player.PlayerControllerAi; import forge.game.spellability.SpellAbility; import forge.game.zone.ZoneType; import forge.gui.input.InputSelectCardsFromList; @@ -114,44 +112,6 @@ public class CostReveal extends CostPartWithList { return true; } - /* (non-Javadoc) - * @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card) - */ - @Override - public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) { - - final String type = this.getType(); - List hand = new ArrayList(ai.getCardsIn(ZoneType.Hand)); - - if (this.payCostFromSource()) { - if (!hand.contains(source)) { - return null; - } - return new PaymentDecision(source); - } - - if (this.getType().equals("Hand")) - return new PaymentDecision(new ArrayList(ai.getCardsIn(ZoneType.Hand))); - - if (this.getType().equals("SameColor")) { - return null; - } - - hand = CardLists.getValidCards(hand, type.split(";"), ai, source); - Integer c = this.convertAmount(); - if (c == null) { - final String sVar = ability.getSVar(this.getAmount()); - if (sVar.equals("XChoice")) { - c = hand.size(); - } else { - c = AbilityUtils.calculateAmount(source, this.getAmount(), ability); - } - } - - final AiController aic = ((PlayerControllerAi)ai.getController()).getAi(); - return new PaymentDecision(aic.getCardsToDiscard(c, type.split(";"), ability)); - } - /* * (non-Javadoc) * diff --git a/forge-gui/src/main/java/forge/game/cost/CostSacrifice.java b/forge-gui/src/main/java/forge/game/cost/CostSacrifice.java index dba749d8ee0..3346d9d720b 100644 --- a/forge-gui/src/main/java/forge/game/cost/CostSacrifice.java +++ b/forge-gui/src/main/java/forge/game/cost/CostSacrifice.java @@ -20,7 +20,6 @@ package forge.game.cost; import java.util.ArrayList; import java.util.List; -import forge.ai.ComputerUtil; import forge.game.ability.AbilityUtils; import forge.game.card.Card; import forge.game.card.CardLists; @@ -184,37 +183,6 @@ public class CostSacrifice extends CostPartWithList { return "Sacrificed"; } - /* (non-Javadoc) - * @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card) - */ - @Override - public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) { - - if (this.payCostFromSource()) { - return new PaymentDecision(source); - } - if (this.getAmount().equals("All")) { - /*List typeList = new ArrayList(activator.getCardsIn(ZoneType.Battlefield)); - typeList = CardLists.getValidCards(typeList, this.getType().split(";"), activator, source); - if (activator.hasKeyword("You can't sacrifice creatures to cast spells or activate abilities.")) { - typeList = CardLists.getNotType(typeList, "Creature"); - }*/ - // Does the AI want to use Sacrifice All? - return null; - } - - Integer c = this.convertAmount(); - if (c == null) { - if (ability.getSVar(this.getAmount()).equals("XChoice")) { - return null; - } - - c = AbilityUtils.calculateAmount(source, this.getAmount(), ability); - } - List list = ComputerUtil.chooseSacrificeType(ai, this.getType(), source, ability.getTargetCard(), c); - return new PaymentDecision(list); - } - // Inputs public T accept(ICostVisitor visitor) { return visitor.visit(this); diff --git a/forge-gui/src/main/java/forge/game/cost/CostTap.java b/forge-gui/src/main/java/forge/game/cost/CostTap.java index 2352a5ea4d2..f4fea259d32 100644 --- a/forge-gui/src/main/java/forge/game/cost/CostTap.java +++ b/forge-gui/src/main/java/forge/game/cost/CostTap.java @@ -101,13 +101,6 @@ public class CostTap extends CostPart { return true; } - /* (non-Javadoc) - * @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card) - */ - @Override - public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) { - return new PaymentDecision(0); - } public T accept(ICostVisitor visitor) { return visitor.visit(this); diff --git a/forge-gui/src/main/java/forge/game/cost/CostTapType.java b/forge-gui/src/main/java/forge/game/cost/CostTapType.java index 7bf184f8be6..4b631bd1e21 100644 --- a/forge-gui/src/main/java/forge/game/cost/CostTapType.java +++ b/forge-gui/src/main/java/forge/game/cost/CostTapType.java @@ -22,7 +22,6 @@ import java.util.List; import com.google.common.base.Predicate; -import forge.ai.ComputerUtil; import forge.game.ability.AbilityUtils; import forge.game.card.Card; import forge.game.card.CardLists; @@ -37,7 +36,7 @@ import forge.gui.input.InputSelectCardsFromList; */ public class CostTapType extends CostPartWithList { - private final boolean canTapSource; + public final boolean canTapSource; /** * Instantiates a new cost tap type. @@ -263,40 +262,6 @@ public class CostTapType extends CostPartWithList { return executePayment(ability, inp.getSelected()); } - /* (non-Javadoc) - * @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card) - */ - @Override - public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) { - final String amount = this.getAmount(); - Integer c = this.convertAmount(); - if (c == null) { - final String sVar = ability.getSVar(amount); - if (sVar.equals("XChoice")) { - List typeList = - CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), this.getType().split(";"), ability.getActivatingPlayer(), ability.getSourceCard()); - typeList = CardLists.filter(typeList, Presets.UNTAPPED); - c = typeList.size(); - source.setSVar("ChosenX", "Number$" + Integer.toString(c)); - } else { - c = AbilityUtils.calculateAmount(source, amount, ability); - } - } - if (this.getType().contains("sharesCreatureTypeWith") || this.getType().contains("withTotalPowerGE")) { - return null; - } - - List totap = ComputerUtil.chooseTapType(ai, this.getType(), source, !canTapSource, c); - - - if (totap == null) { - System.out.println("Couldn't find a valid card to tap for: " + source.getName()); - return null; - } - - return new PaymentDecision(totap); - } - /* (non-Javadoc) * @see forge.card.cost.CostPartWithList#executePayment(forge.card.spellability.SpellAbility, forge.Card) */ diff --git a/forge-gui/src/main/java/forge/game/cost/CostUnattach.java b/forge-gui/src/main/java/forge/game/cost/CostUnattach.java index e67aa2087c6..50f9617edaf 100644 --- a/forge-gui/src/main/java/forge/game/cost/CostUnattach.java +++ b/forge-gui/src/main/java/forge/game/cost/CostUnattach.java @@ -104,7 +104,7 @@ public class CostUnattach extends CostPartWithList { return false; } - private Card findCardToUnattach(final Card source, Player activator, SpellAbility ability) { + public Card findCardToUnattach(final Card source, Player activator, SpellAbility ability) { if (getType().equals("CARDNAME")) { if (source.isEquipping()) { return source; @@ -137,19 +137,7 @@ public class CostUnattach extends CostPartWithList { return "Unattached"; } - /* (non-Javadoc) - * @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card) - */ - @Override - public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) { - Card cardToUnattach = findCardToUnattach(source, (Player) ai, ability); - if (cardToUnattach == null) { - // We really shouldn't be able to get here if there's nothing to unattach - return null; - } - return new PaymentDecision(cardToUnattach); - } - + public T accept(ICostVisitor visitor) { return visitor.visit(this); } diff --git a/forge-gui/src/main/java/forge/game/cost/CostUntap.java b/forge-gui/src/main/java/forge/game/cost/CostUntap.java index 79b7843fcfc..63a9f5d3b91 100644 --- a/forge-gui/src/main/java/forge/game/cost/CostUntap.java +++ b/forge-gui/src/main/java/forge/game/cost/CostUntap.java @@ -92,14 +92,6 @@ public class CostUntap extends CostPart { return true; } - /* (non-Javadoc) - * @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card) - */ - @Override - public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) { - return new PaymentDecision(0); - } - /* (non-Javadoc) * @see forge.card.cost.CostPart#payAI(forge.card.cost.PaymentDecision, forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card) */ diff --git a/forge-gui/src/main/java/forge/game/cost/CostUntapType.java b/forge-gui/src/main/java/forge/game/cost/CostUntapType.java index 95e18aa718d..62a8bf6494e 100644 --- a/forge-gui/src/main/java/forge/game/cost/CostUntapType.java +++ b/forge-gui/src/main/java/forge/game/cost/CostUntapType.java @@ -18,7 +18,6 @@ package forge.game.cost; import java.util.List; -import forge.ai.ComputerUtil; import forge.game.ability.AbilityUtils; import forge.game.card.Card; import forge.game.card.CardLists; @@ -33,7 +32,7 @@ import forge.gui.input.InputSelectCardsFromList; */ public class CostUntapType extends CostPartWithList { - private final boolean canUntapSource; + public final boolean canUntapSource; /** * Instantiates a new cost untap type. @@ -173,39 +172,6 @@ public class CostUntapType extends CostPartWithList { return "Untapped"; } - /* (non-Javadoc) - * @see forge.card.cost.CostPart#decideAIPayment(forge.game.player.AIPlayer, forge.card.spellability.SpellAbility, forge.Card) - */ - @Override - public PaymentDecision decideAIPayment(Player ai, SpellAbility ability, Card source) { - final String amount = this.getAmount(); - Integer c = this.convertAmount(); - if (c == null) { - final String sVar = ability.getSVar(amount); - if (sVar.equals("XChoice")) { - List typeList = ai.getGame().getCardsIn(ZoneType.Battlefield); - typeList = CardLists.getValidCards(typeList, this.getType().split(";"), ai, ability.getSourceCard()); - if (!canUntapSource) { - typeList.remove(source); - } - typeList = CardLists.filter(typeList, Presets.TAPPED); - c = typeList.size(); - source.setSVar("ChosenX", "Number$" + Integer.toString(c)); - } else { - c = AbilityUtils.calculateAmount(source, amount, ability); - } - } - - List list = ComputerUtil.chooseUntapType(ai, this.getType(), source, canUntapSource, c); - - if (list == null) { - System.out.println("Couldn't find a valid card to untap for: " + source.getName()); - return null; - } - - return new PaymentDecision(list); - } - public T accept(ICostVisitor visitor) { return visitor.visit(this); } diff --git a/forge-gui/src/main/java/forge/game/cost/ICostVisitor.java b/forge-gui/src/main/java/forge/game/cost/ICostVisitor.java index 73688b648a1..f68a26498dd 100644 --- a/forge-gui/src/main/java/forge/game/cost/ICostVisitor.java +++ b/forge-gui/src/main/java/forge/game/cost/ICostVisitor.java @@ -2,162 +2,162 @@ package forge.game.cost; public interface ICostVisitor { - public T visit(CostGainControl costGainControl); - public T visit(CostChooseCreatureType costChooseCreatureType); - public T visit(CostDiscard costDiscard); - public T visit(CostDamage costDamage); - public T visit(CostDraw costDraw); - public T visit(CostExile costExile); - public T visit(CostExileAndPay costExileAndPay); - public T visit(CostExiledMoveToGrave costExiledMoveToGrave); - public T visit(CostFlipCoin costFlipCoin); - public T visit(CostMill costMill); - public T visit(CostAddMana costAddMana); - public T visit(CostPayLife costPayLife); - public T visit(CostGainLife costGainLife); - public T visit(CostPartMana costPartMana); - public T visit(CostPutCardToLib costPutCardToLib); - public T visit(CostTap costTap); - public T visit(CostSacrifice costSacrifice); - public T visit(CostReturn costReturn); - public T visit(CostReveal costReveal); - public T visit(CostRemoveAnyCounter costRemoveAnyCounter); - public T visit(CostRemoveCounter costRemoveCounter); - public T visit(CostPutCounter costPutCounter); - public T visit(CostUntapType costUntapType); - public T visit(CostUntap costUntap); - public T visit(CostUnattach costUnattach); - public T visit(CostTapType costTapType); + public T visit(CostGainControl cost); + public T visit(CostChooseCreatureType cost); + public T visit(CostDiscard cost); + public T visit(CostDamage cost); + public T visit(CostDraw cost); + public T visit(CostExile cost); + public T visit(CostExileAndPay cost); + public T visit(CostExiledMoveToGrave cost); + public T visit(CostFlipCoin cost); + public T visit(CostMill cost); + public T visit(CostAddMana cost); + public T visit(CostPayLife cost); + public T visit(CostGainLife cost); + public T visit(CostPartMana cost); + public T visit(CostPutCardToLib cost); + public T visit(CostTap cost); + public T visit(CostSacrifice cost); + public T visit(CostReturn cost); + public T visit(CostReveal cost); + public T visit(CostRemoveAnyCounter cost); + public T visit(CostRemoveCounter cost); + public T visit(CostPutCounter cost); + public T visit(CostUntapType cost); + public T visit(CostUntap cost); + public T visit(CostUnattach cost); + public T visit(CostTapType cost); public static class Base implements ICostVisitor { @Override - public T visit(CostGainControl costGainControl) { + public T visit(CostGainControl cost) { return null; } @Override - public T visit(CostChooseCreatureType costChooseCreatureType) { + public T visit(CostChooseCreatureType cost) { return null; } @Override - public T visit(CostDiscard costDiscard) { + public T visit(CostDiscard cost) { return null; } @Override - public T visit(CostDamage costDamage) { + public T visit(CostDamage cost) { return null; } @Override - public T visit(CostDraw costDraw) { + public T visit(CostDraw cost) { return null; } @Override - public T visit(CostExile costExile) { + public T visit(CostExile cost) { return null; } @Override - public T visit(CostExileAndPay costExileAndPay) { + public T visit(CostExileAndPay cost) { return null; } @Override - public T visit(CostExiledMoveToGrave costExiledMoveToGrave) { + public T visit(CostExiledMoveToGrave cost) { return null; } @Override - public T visit(CostFlipCoin costFlipCoin) { + public T visit(CostFlipCoin cost) { return null; } @Override - public T visit(CostMill costMill) { + public T visit(CostMill cost) { return null; } @Override - public T visit(CostAddMana costAddMana) { + public T visit(CostAddMana cost) { return null; } @Override - public T visit(CostPayLife costPayLife) { + public T visit(CostPayLife cost) { return null; } @Override - public T visit(CostGainLife costGainLife) { + public T visit(CostGainLife cost) { return null; } @Override - public T visit(CostPartMana costPartMana) { + public T visit(CostPartMana cost) { return null; } @Override - public T visit(CostPutCardToLib costPutCardToLib) { + public T visit(CostPutCardToLib cost) { return null; } @Override - public T visit(CostTap costTap) { + public T visit(CostTap cost) { return null; } @Override - public T visit(CostSacrifice costSacrifice) { + public T visit(CostSacrifice cost) { return null; } @Override - public T visit(CostReturn costReturn) { + public T visit(CostReturn cost) { return null; } @Override - public T visit(CostReveal costReveal) { + public T visit(CostReveal cost) { return null; } @Override - public T visit(CostRemoveAnyCounter costRemoveAnyCounter) { + public T visit(CostRemoveAnyCounter cost) { return null; } @Override - public T visit(CostRemoveCounter costRemoveCounter) { + public T visit(CostRemoveCounter cost) { return null; } @Override - public T visit(CostPutCounter costPutCounter) { + public T visit(CostPutCounter cost) { return null; } @Override - public T visit(CostUntapType costUntapType) { + public T visit(CostUntapType cost) { return null; } @Override - public T visit(CostUntap costUntap) { + public T visit(CostUntap cost) { return null; } @Override - public T visit(CostUnattach costUnattach) { + public T visit(CostUnattach cost) { return null; } @Override - public T visit(CostTapType costTapType) { + public T visit(CostTapType cost) { return null; } } diff --git a/forge-gui/src/main/java/forge/gui/deckchooser/DeckgenUtil.java b/forge-gui/src/main/java/forge/gui/deckchooser/DeckgenUtil.java index d042ed9363c..0641cb93052 100644 --- a/forge-gui/src/main/java/forge/gui/deckchooser/DeckgenUtil.java +++ b/forge-gui/src/main/java/forge/gui/deckchooser/DeckgenUtil.java @@ -9,8 +9,6 @@ import java.util.Map.Entry; import java.util.Random; import javax.swing.JList; -import javax.swing.JOptionPane; - import com.google.common.base.Predicate; import com.google.common.collect.Iterables;