diff --git a/.gitattributes b/.gitattributes index 85fd804b05f..7349c6cc19e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -14096,6 +14096,7 @@ src/main/java/forge/game/ai/AiInputBlock.java -text src/main/java/forge/game/ai/AiInputCommon.java svneol=native#text/plain src/main/java/forge/game/ai/ComputerUtil.java svneol=native#text/plain src/main/java/forge/game/ai/ComputerUtilBlock.java svneol=native#text/plain +src/main/java/forge/game/ai/ComputerUtilCard.java -text src/main/java/forge/game/ai/ComputerUtilCombat.java -text src/main/java/forge/game/ai/ComputerUtilCost.java -text src/main/java/forge/game/ai/ComputerUtilMana.java -text diff --git a/src/main/java/forge/CardLists.java b/src/main/java/forge/CardLists.java index bf5e2b2a294..76de0698080 100644 --- a/src/main/java/forge/CardLists.java +++ b/src/main/java/forge/CardLists.java @@ -27,8 +27,8 @@ import com.google.common.base.Predicates; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.spellability.SpellAbility; +import forge.game.ai.ComputerUtilCard; import forge.game.player.Player; import forge.util.MyRandom; @@ -74,13 +74,6 @@ public class CardLists { return b.getNetCombatDamage() - a.getNetCombatDamage(); } }; - public static final Comparator EvaluateCreatureComparator = new Comparator() { - @Override - public int compare(final Card a, final Card b) { - return CardFactoryUtil.evaluateCreature(b) - CardFactoryUtil.evaluateCreature(a); - } - }; - public static final Comparator CmcComparator = new Comparator() { @Override public int compare(final Card a, final Card b) { @@ -131,7 +124,7 @@ public class CardLists { * a {@link forge.CardList} object. */ public static void sortByEvaluateCreature(final List list) { - Collections.sort(list, EvaluateCreatureComparator); + Collections.sort(list, ComputerUtilCard.EvaluateCreatureComparator); } // sortByEvaluateCreature() /** diff --git a/src/main/java/forge/CardPredicates.java b/src/main/java/forge/CardPredicates.java index 15cc1bc707f..0333251353d 100644 --- a/src/main/java/forge/CardPredicates.java +++ b/src/main/java/forge/CardPredicates.java @@ -23,7 +23,6 @@ import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.spellability.SpellAbility; import forge.game.phase.CombatUtil; import forge.game.phase.Untap; @@ -393,12 +392,5 @@ public final class CardPredicates { return a.getCMC(); } }; - - public static final Function fnEvaluateCreature = new Function() { - @Override - public Integer apply(Card a) { - return CardFactoryUtil.evaluateCreature(a); - } - }; } } diff --git a/src/main/java/forge/CardUtil.java b/src/main/java/forge/CardUtil.java index f7490b5af6f..8a2ed20dcd4 100644 --- a/src/main/java/forge/CardUtil.java +++ b/src/main/java/forge/CardUtil.java @@ -33,7 +33,6 @@ import forge.card.CardSplitType; import forge.card.MagicColor; import forge.card.ability.AbilityUtils; import forge.card.ability.ApiType; -import forge.card.mana.ManaCostBeingPaid; import forge.card.spellability.AbilityManaPart; import forge.card.spellability.SpellAbility; import forge.game.player.Player; @@ -99,29 +98,6 @@ public final class CardUtil { return c.determineColor().toStringList(); } - - // this function checks, if duplicates of a keyword are not necessary (like - // flying, trample, etc.) - /** - *

- * isNonStackingKeyword. - *

- * - * @param keyword - * a {@link java.lang.String} object. - * @return a boolean. - */ - public static boolean isNonStackingKeyword(final String keyword) { - String kw = new String(keyword); - if (kw.startsWith("HIDDEN")) { - kw = kw.substring(7); - } - if (kw.startsWith("Protection")) { - return true; - } - return Constant.Keywords.NON_STACKING_LIST.contains(kw); - } - /** *

* isStackingKeyword. @@ -132,25 +108,12 @@ public final class CardUtil { * @return a boolean. */ public static boolean isStackingKeyword(final String keyword) { - return !CardUtil.isNonStackingKeyword(keyword); - } - - /** - * Builds the ideal filename. - * - * @param cardName - * the card name - * @param artIndex - * the art index - * @param artIndexMax - * the art index max - * @return the string - */ - public static String buildIdealFilename(final String cardName, final int artIndex, final int artIndexMax) { - final String nn = artIndexMax > 1 ? Integer.toString(artIndex + 1) : ""; - final String mwsCardName = GuiDisplayUtil.cleanStringMWS(cardName); - // 3 letter set code with MWS filename format - return String.format("%s%s.full.jpg", mwsCardName, nn); + String kw = new String(keyword); + if (kw.startsWith("HIDDEN")) { + kw = kw.substring(7); + } + + return !kw.startsWith("Protection") && !Constant.Keywords.NON_STACKING_LIST.contains(kw); } /** @@ -432,35 +395,6 @@ public final class CardUtil { return res; } - /** - * 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; - } - /** * Gets the face down characteristic. * diff --git a/src/main/java/forge/card/ability/ai/AttachAi.java b/src/main/java/forge/card/ability/ai/AttachAi.java index 09f40c72ddf..d9110e95fb1 100644 --- a/src/main/java/forge/card/ability/ai/AttachAi.java +++ b/src/main/java/forge/card/ability/ai/AttachAi.java @@ -24,6 +24,7 @@ import forge.card.cost.Cost; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; import forge.card.staticability.StaticAbility; +import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilMana; import forge.game.phase.CombatUtil; import forge.game.phase.PhaseHandler; @@ -96,7 +97,7 @@ public class AttachAi extends SpellAbilityAi { // TODO If Not Mandatory, make sure the card is "good enough" if (c.isCreature()) { - final int eval = CardFactoryUtil.evaluateCreature(c); + final int eval = ComputerUtilCard.evaluateCreature(c); if (eval < 130) { return null; } @@ -119,7 +120,7 @@ public class AttachAi extends SpellAbilityAi { return null; } - return CardFactoryUtil.getWorstPermanentAI(list, true, true, true, false); + return ComputerUtilCard.getWorstPermanentAI(list, true, true, true, false); } /** @@ -136,7 +137,7 @@ public class AttachAi extends SpellAbilityAi { return null; } - return CardFactoryUtil.getBestAI(list); + return ComputerUtilCard.getBestAI(list); } /** @@ -174,7 +175,7 @@ public class AttachAi extends SpellAbilityAi { list = CardLists.getNotType(list, type); // Filter out Basic Lands that have the // same type as the changing type - final Card c = CardFactoryUtil.getBestAI(list); + final Card c = ComputerUtilCard.getBestAI(list); // TODO Port over some of the existing code, but rewrite most of it. // Ultimately, these spells need to be used to reduce mana base of a @@ -234,7 +235,7 @@ public class AttachAi extends SpellAbilityAi { } }); - final Card c = CardFactoryUtil.getBestAI(prefList); + final Card c = ComputerUtilCard.getBestAI(prefList); if (c == null) { return chooseLessPreferred(mandatory, list); @@ -333,7 +334,7 @@ public class AttachAi extends SpellAbilityAi { }); } - final Card c = CardFactoryUtil.getMostExpensivePermanentAI(betterList); + final Card c = ComputerUtilCard.getMostExpensivePermanentAI(betterList); // If Mandatory (brought directly into play without casting) gotta // choose something @@ -361,7 +362,7 @@ public class AttachAi extends SpellAbilityAi { final Card attachSource) { // AI For choosing a Card to Animate. // TODO Add some more restrictions for Reanimation Auras - final Card c = CardFactoryUtil.getBestCreatureAI(list); + final Card c = ComputerUtilCard.getBestCreatureAI(list); // If Mandatory (brought directly into play without casting) gotta // choose something @@ -406,7 +407,7 @@ public class AttachAi extends SpellAbilityAi { return true; } }); - chosen = CardFactoryUtil.getBestCreatureAI(creatures); + chosen = ComputerUtilCard.getBestCreatureAI(creatures); } } @@ -445,7 +446,7 @@ public class AttachAi extends SpellAbilityAi { } - final Card c = CardFactoryUtil.getBestAI(list); + final Card c = ComputerUtilCard.getBestAI(list); // If Mandatory (brought directly into play without casting) gotta // choose something @@ -537,7 +538,7 @@ public class AttachAi extends SpellAbilityAi { if ((prefList == null) || prefList.isEmpty()) { prefList = new ArrayList(list); } else { - c = CardFactoryUtil.getBestAI(prefList); + c = ComputerUtilCard.getBestAI(prefList); if (c != null) { return c; } @@ -559,7 +560,7 @@ public class AttachAi extends SpellAbilityAi { }); } - c = CardFactoryUtil.getBestAI(prefList); + c = ComputerUtilCard.getBestAI(prefList); if (c == null) { return chooseLessPreferred(mandatory, list); @@ -602,7 +603,7 @@ public class AttachAi extends SpellAbilityAi { //don't equip a worse creature if (card.isEquipping()) { Card oldTarget = card.getEquipping().get(0); - if (CardFactoryUtil.evaluateCreature(oldTarget) > CardFactoryUtil.evaluateCreature(newTarget)) { + if (ComputerUtilCard.evaluateCreature(oldTarget) > ComputerUtilCard.evaluateCreature(newTarget)) { return false; } } @@ -723,7 +724,7 @@ public class AttachAi extends SpellAbilityAi { } }); - return CardFactoryUtil.getBestAI(magnetList); + return ComputerUtilCard.getBestAI(magnetList); } int totToughness = 0; @@ -809,11 +810,11 @@ public class AttachAi extends SpellAbilityAi { return !c.isCreature() || CombatUtil.canAttackNextTurn(c); } }); - c = CardFactoryUtil.getBestAI(prefList); + c = ComputerUtilCard.getBestAI(prefList); } else { // If we grant abilities, we may want to put it on something Weak? // Possibly more defensive? - c = CardFactoryUtil.getWorstPermanentAI(prefList, false, false, false, false); + c = ComputerUtilCard.getWorstPermanentAI(prefList, false, false, false, false); } if (c == null) { diff --git a/src/main/java/forge/card/ability/ai/ChangeZoneAi.java b/src/main/java/forge/card/ability/ai/ChangeZoneAi.java index 3c7128df8bd..6e854c297f8 100644 --- a/src/main/java/forge/card/ability/ai/ChangeZoneAi.java +++ b/src/main/java/forge/card/ability/ai/ChangeZoneAi.java @@ -20,7 +20,6 @@ import forge.card.ability.AbilityUtils; import forge.card.ability.ApiType; import forge.card.ability.SpellAbilityAi; import forge.card.ability.effects.AttachEffect; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.cost.Cost; import forge.card.cost.CostDiscard; import forge.card.cost.CostPart; @@ -29,6 +28,7 @@ import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellPermanent; import forge.card.spellability.Target; import forge.game.GlobalRuleChange; +import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilCombat; import forge.game.ai.ComputerUtil; import forge.game.ai.ComputerUtilBlock; @@ -507,7 +507,7 @@ public class ChangeZoneAi extends SpellAbilityAi { } } else { // not urgent, get the largest creature possible - card = CardFactoryUtil.getBestCreatureAI(list); + card = ComputerUtilCard.getBestCreatureAI(list); } return card; } @@ -730,7 +730,7 @@ public class ChangeZoneAi extends SpellAbilityAi { if (!threatenedTargets.isEmpty()) { // Choose "best" of the remaining to save - tgt.addTarget(CardFactoryUtil.getBestAI(threatenedTargets)); + tgt.addTarget(ComputerUtilCard.getBestAI(threatenedTargets)); return true; } } @@ -762,7 +762,7 @@ public class ChangeZoneAi extends SpellAbilityAi { }); if (!aiPermanents.isEmpty()) { // Choose "best" of the remaining to save - tgt.addTarget(CardFactoryUtil.getBestAI(aiPermanents)); + tgt.addTarget(ComputerUtilCard.getBestAI(aiPermanents)); return true; } } @@ -839,15 +839,15 @@ public class ChangeZoneAi extends SpellAbilityAi { Card choice = null; if (!list.isEmpty()) { - final Card mostExpensive = CardFactoryUtil.getMostExpensivePermanentAI(list, sa, false); + final Card mostExpensive = ComputerUtilCard.getMostExpensivePermanentAI(list, sa, false); if (destination.equals(ZoneType.Battlefield) || origin.equals(ZoneType.Battlefield)) { if (mostExpensive.isCreature()) { // if a creature is most expensive take the best one if (destination.equals(ZoneType.Exile)) { // If Exiling things, don't give bonus to Tokens - choice = CardFactoryUtil.getBestCreatureAI(list); + choice = ComputerUtilCard.getBestCreatureAI(list); } else { - choice = CardFactoryUtil.getBestCreatureToBounceAI(list); + choice = ComputerUtilCard.getBestCreatureToBounceAI(list); } } else { choice = mostExpensive; @@ -870,7 +870,7 @@ public class ChangeZoneAi extends SpellAbilityAi { } else { // Get the best card in there. System.out.println("No creature and lots of life, finding something good."); - choice = CardFactoryUtil.getBestAI(nonLands); + choice = ComputerUtilCard.getBestAI(nonLands); } } if (choice == null) { @@ -879,7 +879,7 @@ public class ChangeZoneAi extends SpellAbilityAi { choice = list.get(0); } } else { - choice = CardFactoryUtil.getBestAI(list); + choice = ComputerUtilCard.getBestAI(list); } } if (choice == null) { // can't find anything left @@ -957,12 +957,12 @@ public class ChangeZoneAi extends SpellAbilityAi { Card choice = null; if (!list.isEmpty()) { - if (CardFactoryUtil.getMostExpensivePermanentAI(list, sa, false).isCreature() + if (ComputerUtilCard.getMostExpensivePermanentAI(list, sa, false).isCreature() && (destination.equals(ZoneType.Battlefield) || origin.equals(ZoneType.Battlefield))) { // if a creature is most expensive take the best - choice = CardFactoryUtil.getBestCreatureToBounceAI(list); + choice = ComputerUtilCard.getBestCreatureToBounceAI(list); } else if (destination.equals(ZoneType.Battlefield) || origin.equals(ZoneType.Battlefield)) { - choice = CardFactoryUtil.getMostExpensivePermanentAI(list, sa, false); + choice = ComputerUtilCard.getMostExpensivePermanentAI(list, sa, false); } else if (destination.equals(ZoneType.Hand) || destination.equals(ZoneType.Library)) { List nonLands = CardLists.getNotType(list, "Land"); // Prefer to pull a creature, generally more useful for AI. @@ -981,7 +981,7 @@ public class ChangeZoneAi extends SpellAbilityAi { } else { // Get the best card in there. System.out.println("No creature and lots of life, finding something good."); - choice = CardFactoryUtil.getBestAI(nonLands); + choice = ComputerUtilCard.getBestAI(nonLands); } } if (choice == null) { @@ -990,7 +990,7 @@ public class ChangeZoneAi extends SpellAbilityAi { choice = list.get(0); } } else { - choice = CardFactoryUtil.getBestAI(list); + choice = ComputerUtilCard.getBestAI(list); } } if (choice == null) { // can't find anything left @@ -1168,9 +1168,9 @@ public class ChangeZoneAi extends SpellAbilityAi { if (ZoneType.Exile.equals(destination) || origin.contains(ZoneType.Battlefield)) { // Exiling or bouncing stuff if (player.isOpponentOf(ai)) { - c = CardFactoryUtil.getBestAI(fetchList); + c = ComputerUtilCard.getBestAI(fetchList); } else { - c = CardFactoryUtil.getWorstAI(fetchList); + c = ComputerUtilCard.getWorstAI(fetchList); } } else if (origin.contains(ZoneType.Library) && (type.contains("Basic") || areAllBasics(type))) { @@ -1179,9 +1179,9 @@ public class ChangeZoneAi extends SpellAbilityAi { c = chooseCreature(ai, fetchList); } else if (ZoneType.Battlefield.equals(destination) || ZoneType.Graveyard.equals(destination)) { if (!activator.equals(ai) && sa.hasParam("GainControl")) { - c = CardFactoryUtil.getWorstAI(fetchList); + c = ComputerUtilCard.getWorstAI(fetchList); } else { - c = CardFactoryUtil.getBestAI(fetchList); + c = ComputerUtilCard.getBestAI(fetchList); } } else { // Don't fetch another tutor with the same name @@ -1222,7 +1222,7 @@ public class ChangeZoneAi extends SpellAbilityAi { } else { // Get the best card in there. System.out.println("No creature and lots of life, finding something good."); - c = CardFactoryUtil.getBestAI(fetchList); + c = ComputerUtilCard.getBestAI(fetchList); } } } @@ -1263,7 +1263,7 @@ public class ChangeZoneAi extends SpellAbilityAi { list = CardLists.getValidCards(list, sa.getParam("AttachedTo"), c.getController(), c); } if (!list.isEmpty()) { - final Card attachedTo = CardFactoryUtil.getBestAI(list); + final Card attachedTo = ComputerUtilCard.getBestAI(list); if (c.isEnchanting()) { // If this Card is already Enchanting something, need // to unenchant it, then clear out the commands diff --git a/src/main/java/forge/card/ability/ai/ChangeZoneAllAi.java b/src/main/java/forge/card/ability/ai/ChangeZoneAllAi.java index a355643ec1e..6a5869113cd 100644 --- a/src/main/java/forge/card/ability/ai/ChangeZoneAllAi.java +++ b/src/main/java/forge/card/ability/ai/ChangeZoneAllAi.java @@ -8,10 +8,10 @@ import forge.CardLists; import forge.Singletons; import forge.card.ability.AbilityUtils; import forge.card.ability.SpellAbilityAi; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.cost.Cost; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; +import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilCost; import forge.game.phase.PhaseType; import forge.game.player.AIPlayer; @@ -89,13 +89,13 @@ public class ChangeZoneAllAi extends SpellAbilityAi { computerType.clear(); } if ((CardLists.getNotType(humanType, "Creature").size() == 0) && (CardLists.getNotType(computerType, "Creature").size() == 0)) { - if ((CardFactoryUtil.evaluateCreatureList(computerType) + 200) >= CardFactoryUtil + if ((ComputerUtilCard.evaluateCreatureList(computerType) + 200) >= ComputerUtilCard .evaluateCreatureList(humanType)) { return false; } } // otherwise evaluate both lists by CMC and pass only if human // permanents are more valuable - else if ((CardFactoryUtil.evaluatePermanentList(computerType) + 3) >= CardFactoryUtil + else if ((ComputerUtilCard.evaluatePermanentList(computerType) + 3) >= ComputerUtilCard .evaluatePermanentList(humanType)) { return false; } @@ -127,26 +127,26 @@ public class ChangeZoneAllAi extends SpellAbilityAi { if (sa.getParam("GainControl") != null) { // Check if the cards are valuable enough if ((CardLists.getNotType(humanType, "Creature").size() == 0) && (CardLists.getNotType(computerType, "Creature").size() == 0)) { - if ((CardFactoryUtil.evaluateCreatureList(computerType) + CardFactoryUtil + if ((ComputerUtilCard.evaluateCreatureList(computerType) + ComputerUtilCard .evaluateCreatureList(humanType)) < 400) { return false; } } // otherwise evaluate both lists by CMC and pass only if human // permanents are less valuable - else if ((CardFactoryUtil.evaluatePermanentList(computerType) + CardFactoryUtil + else if ((ComputerUtilCard.evaluatePermanentList(computerType) + ComputerUtilCard .evaluatePermanentList(humanType)) < 6) { return false; } } else { // don't activate if human gets more back than AI does if ((CardLists.getNotType(humanType, "Creature").size() == 0) && (CardLists.getNotType(computerType, "Creature").size() == 0)) { - if (CardFactoryUtil.evaluateCreatureList(computerType) <= (CardFactoryUtil + if (ComputerUtilCard.evaluateCreatureList(computerType) <= (ComputerUtilCard .evaluateCreatureList(humanType) + 100)) { return false; } } // otherwise evaluate both lists by CMC and pass only if human // permanents are less valuable - else if (CardFactoryUtil.evaluatePermanentList(computerType) <= (CardFactoryUtil + else if (ComputerUtilCard.evaluatePermanentList(computerType) <= (ComputerUtilCard .evaluatePermanentList(humanType) + 2)) { return false; } @@ -206,13 +206,13 @@ public class ChangeZoneAllAi extends SpellAbilityAi { // if only creatures are affected evaluate both lists and pass only // if human creatures are more valuable if ((CardLists.getNotType(humanType, "Creature").isEmpty()) && (CardLists.getNotType(computerType, "Creature").isEmpty())) { - if (CardFactoryUtil.evaluateCreatureList(computerType) >= CardFactoryUtil + if (ComputerUtilCard.evaluateCreatureList(computerType) >= ComputerUtilCard .evaluateCreatureList(humanType)) { return false; } } // otherwise evaluate both lists by CMC and pass only if human // permanents are more valuable - else if (CardFactoryUtil.evaluatePermanentList(computerType) >= CardFactoryUtil + else if (ComputerUtilCard.evaluatePermanentList(computerType) >= ComputerUtilCard .evaluatePermanentList(humanType)) { return false; } @@ -240,26 +240,26 @@ public class ChangeZoneAllAi extends SpellAbilityAi { if (sa.getParam("GainControl") != null) { // Check if the cards are valuable enough if ((CardLists.getNotType(humanType, "Creature").size() == 0) && (CardLists.getNotType(computerType, "Creature").size() == 0)) { - if ((CardFactoryUtil.evaluateCreatureList(computerType) + CardFactoryUtil + if ((ComputerUtilCard.evaluateCreatureList(computerType) + ComputerUtilCard .evaluateCreatureList(humanType)) < 1) { return false; } } // otherwise evaluate both lists by CMC and pass only if human // permanents are less valuable - else if ((CardFactoryUtil.evaluatePermanentList(computerType) + CardFactoryUtil + else if ((ComputerUtilCard.evaluatePermanentList(computerType) + ComputerUtilCard .evaluatePermanentList(humanType)) < 1) { return false; } } else { // don't activate if human gets more back than AI does if ((CardLists.getNotType(humanType, "Creature").isEmpty()) && (CardLists.getNotType(computerType, "Creature").isEmpty())) { - if (CardFactoryUtil.evaluateCreatureList(computerType) <= CardFactoryUtil + if (ComputerUtilCard.evaluateCreatureList(computerType) <= ComputerUtilCard .evaluateCreatureList(humanType)) { return false; } } // otherwise evaluate both lists by CMC and pass only if human // permanents are less valuable - else if (CardFactoryUtil.evaluatePermanentList(computerType) <= CardFactoryUtil + else if (ComputerUtilCard.evaluatePermanentList(computerType) <= ComputerUtilCard .evaluatePermanentList(humanType)) { return false; } diff --git a/src/main/java/forge/card/ability/ai/ControlExchangeAi.java b/src/main/java/forge/card/ability/ai/ControlExchangeAi.java index c1d0aee63bd..8bddd66d1ac 100644 --- a/src/main/java/forge/card/ability/ai/ControlExchangeAi.java +++ b/src/main/java/forge/card/ability/ai/ControlExchangeAi.java @@ -9,9 +9,9 @@ import forge.Card; import forge.CardLists; import forge.card.ability.AbilityUtils; import forge.card.ability.SpellAbilityAi; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; +import forge.game.ai.ComputerUtilCard; import forge.game.player.AIPlayer; import forge.game.zone.ZoneType; import forge.util.MyRandom; @@ -39,19 +39,19 @@ public class ControlExchangeAi extends SpellAbilityAi { return !vars.containsKey("RemAIDeck") && c.canBeTargetedBy(sa); } }); - object1 = CardFactoryUtil.getBestAI(list); + object1 = ComputerUtilCard.getBestAI(list); if (sa.hasParam("Defined")) { object2 = AbilityUtils.getDefinedCards(sa.getSourceCard(), sa.getParam("Defined"), sa).get(0); } else if (tgt.getMinTargets(sa.getSourceCard(), sa) > 1) { List list2 = ai.getCardsIn(ZoneType.Battlefield); list2 = CardLists.getValidCards(list2, tgt.getValidTgts(), ai, sa.getSourceCard()); - object2 = CardFactoryUtil.getWorstAI(list2); + object2 = ComputerUtilCard.getWorstAI(list2); tgt.addTarget(object2); } if (object1 == null || object2 == null) { return false; } - if (CardFactoryUtil.evaluateCreature(object1) > CardFactoryUtil.evaluateCreature(object2) + 40) { + if (ComputerUtilCard.evaluateCreature(object1) > ComputerUtilCard.evaluateCreature(object2) + 40) { tgt.addTarget(object1); return MyRandom.getRandom().nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn()); } diff --git a/src/main/java/forge/card/ability/ai/ControlGainAi.java b/src/main/java/forge/card/ability/ai/ControlGainAi.java index 41da431040a..2d11c84248d 100644 --- a/src/main/java/forge/card/ability/ai/ControlGainAi.java +++ b/src/main/java/forge/card/ability/ai/ControlGainAi.java @@ -29,9 +29,9 @@ import forge.CardLists; import forge.Singletons; import forge.card.ability.AbilityUtils; import forge.card.ability.SpellAbilityAi; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; +import forge.game.ai.ComputerUtilCard; import forge.game.phase.PhaseType; import forge.game.player.AIPlayer; import forge.game.player.Player; @@ -139,15 +139,15 @@ public class ControlGainAi extends SpellAbilityAi { } if (hasCreature) { - t = CardFactoryUtil.getBestCreatureAI(list); + t = ComputerUtilCard.getBestCreatureAI(list); } else if (hasArtifact) { - t = CardFactoryUtil.getBestArtifactAI(list); + t = ComputerUtilCard.getBestArtifactAI(list); } else if (hasLand) { - t = CardFactoryUtil.getBestLandAI(list); + t = ComputerUtilCard.getBestLandAI(list); } else if (hasEnchantment) { - t = CardFactoryUtil.getBestEnchantmentAI(list, sa, true); + t = ComputerUtilCard.getBestEnchantmentAI(list, sa, true); } else { - t = CardFactoryUtil.getMostExpensivePermanentAI(list, sa, true); + t = ComputerUtilCard.getMostExpensivePermanentAI(list, sa, true); } tgt.addTarget(t); diff --git a/src/main/java/forge/card/ability/ai/CopyPermanentAi.java b/src/main/java/forge/card/ability/ai/CopyPermanentAi.java index 81aca01c518..f0c262920b7 100644 --- a/src/main/java/forge/card/ability/ai/CopyPermanentAi.java +++ b/src/main/java/forge/card/ability/ai/CopyPermanentAi.java @@ -11,9 +11,9 @@ import forge.CardLists; import forge.Singletons; import forge.CardPredicates.Presets; import forge.card.ability.SpellAbilityAi; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; +import forge.game.ai.ComputerUtilCard; import forge.game.phase.PhaseType; import forge.game.player.AIPlayer; import forge.game.zone.ZoneType; @@ -82,9 +82,9 @@ public class CopyPermanentAi extends SpellAbilityAi { Card choice; if (!CardLists.filter(list, Presets.CREATURES).isEmpty()) { - choice = CardFactoryUtil.getBestCreatureAI(list); + choice = ComputerUtilCard.getBestCreatureAI(list); } else { - choice = CardFactoryUtil.getMostExpensivePermanentAI(list, sa, true); + choice = ComputerUtilCard.getMostExpensivePermanentAI(list, sa, true); } if (choice == null) { // can't find anything left diff --git a/src/main/java/forge/card/ability/ai/CounterAi.java b/src/main/java/forge/card/ability/ai/CounterAi.java index 77f8bd40aae..3ceda11de74 100644 --- a/src/main/java/forge/card/ability/ai/CounterAi.java +++ b/src/main/java/forge/card/ability/ai/CounterAi.java @@ -9,6 +9,7 @@ import forge.card.cost.Cost; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; import forge.card.spellability.TargetSelection; +import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilCost; import forge.game.ai.ComputerUtilMana; import forge.game.player.AIPlayer; @@ -62,7 +63,7 @@ public class CounterAi extends SpellAbilityAi { if (unlessCost != null && !unlessCost.endsWith(">")) { // Is this Usable Mana Sources? Or Total Available Mana? - final int usableManaSources = CardFactoryUtil.getUsableManaSources(ai.getOpponent()); + final int usableManaSources = ComputerUtilCard.getUsableManaSources(ai.getOpponent()); int toPay = 0; boolean setPayX = false; if (unlessCost.equals("X") && source.getSVar(unlessCost).equals("Count$xPaid")) { @@ -130,7 +131,7 @@ public class CounterAi extends SpellAbilityAi { final Card source = sa.getSourceCard(); if (unlessCost != null) { // Is this Usable Mana Sources? Or Total Available Mana? - final int usableManaSources = CardFactoryUtil.getUsableManaSources(ai.getOpponent()); + final int usableManaSources = ComputerUtilCard.getUsableManaSources(ai.getOpponent()); int toPay = 0; boolean setPayX = false; if (unlessCost.equals("X") && source.getSVar(unlessCost).equals("Count$xPaid")) { diff --git a/src/main/java/forge/card/ability/ai/CountersAi.java b/src/main/java/forge/card/ability/ai/CountersAi.java index b3c96f09418..81a9bfbacb2 100644 --- a/src/main/java/forge/card/ability/ai/CountersAi.java +++ b/src/main/java/forge/card/ability/ai/CountersAi.java @@ -25,7 +25,7 @@ import forge.Card; import forge.CardLists; import forge.CounterType; -import forge.card.cardfactory.CardFactoryUtil; +import forge.game.ai.ComputerUtilCard; /** @@ -63,13 +63,13 @@ public abstract class CountersAi { } }); if (killable.size() > 0) { - choice = CardFactoryUtil.getBestCreatureAI(killable); + choice = ComputerUtilCard.getBestCreatureAI(killable); } else { - choice = CardFactoryUtil.getBestCreatureAI(list); + choice = ComputerUtilCard.getBestCreatureAI(list); } } else { // improve random choice here - choice = CardFactoryUtil.getRandomCard(list); + choice = ComputerUtilCard.getRandomCard(list); } return choice; } @@ -88,7 +88,7 @@ public abstract class CountersAi { public static Card chooseBoonTarget(final List list, final String type) { Card choice; if (type.equals("P1P1")) { - choice = CardFactoryUtil.getBestCreatureAI(list); + choice = ComputerUtilCard.getBestCreatureAI(list); } else if (type.equals("DIVINITY")) { final List boon = CardLists.filter(list, new Predicate() { @Override @@ -96,12 +96,12 @@ public abstract class CountersAi { return c.getCounters(CounterType.DIVINITY) == 0; } }); - choice = CardFactoryUtil.getMostExpensivePermanentAI(boon, null, false); + choice = ComputerUtilCard.getMostExpensivePermanentAI(boon, null, false); } else { // The AI really should put counters on cards that can use it. // Charge counters on things with Charge abilities, etc. Expand // these above - choice = CardFactoryUtil.getRandomCard(list); + choice = ComputerUtilCard.getRandomCard(list); } return choice; } diff --git a/src/main/java/forge/card/ability/ai/CountersMoveAi.java b/src/main/java/forge/card/ability/ai/CountersMoveAi.java index c4160b10c96..77519733d75 100644 --- a/src/main/java/forge/card/ability/ai/CountersMoveAi.java +++ b/src/main/java/forge/card/ability/ai/CountersMoveAi.java @@ -8,9 +8,9 @@ import forge.CardLists; import forge.CounterType; import forge.card.ability.AbilityUtils; import forge.card.ability.SpellAbilityAi; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; +import forge.game.ai.ComputerUtilCard; import forge.game.player.AIPlayer; import forge.game.player.Player; import forge.game.zone.ZoneType; @@ -103,9 +103,9 @@ public class CountersMoveAi extends SpellAbilityAi { else { if (type.equals("M1M1")) { - choice = CardFactoryUtil.getWorstCreatureAI(list); + choice = ComputerUtilCard.getWorstCreatureAI(list); } else { - choice = CardFactoryUtil.getRandomCard(list); + choice = ComputerUtilCard.getRandomCard(list); } } } else { @@ -115,9 +115,9 @@ public class CountersMoveAi extends SpellAbilityAi { else { if (type.equals("P1P1")) { - choice = CardFactoryUtil.getWorstCreatureAI(list); + choice = ComputerUtilCard.getWorstCreatureAI(list); } else { - choice = CardFactoryUtil.getRandomCard(list); + choice = ComputerUtilCard.getRandomCard(list); } } } diff --git a/src/main/java/forge/card/ability/ai/CountersPutAi.java b/src/main/java/forge/card/ability/ai/CountersPutAi.java index c53f6ec6cbb..18c0e4c67c3 100644 --- a/src/main/java/forge/card/ability/ai/CountersPutAi.java +++ b/src/main/java/forge/card/ability/ai/CountersPutAi.java @@ -12,11 +12,11 @@ import forge.CounterType; import forge.Singletons; import forge.card.ability.AbilityUtils; import forge.card.ability.SpellAbilityAi; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.cost.Cost; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; import forge.game.ai.ComputerUtil; +import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilCost; import forge.game.ai.ComputerUtilMana; import forge.game.phase.PhaseType; @@ -279,9 +279,9 @@ public class CountersPutAi extends SpellAbilityAi { else { if (type.equals("M1M1")) { - choice = CardFactoryUtil.getWorstCreatureAI(list); + choice = ComputerUtilCard.getWorstCreatureAI(list); } else { - choice = CardFactoryUtil.getRandomCard(list); + choice = ComputerUtilCard.getRandomCard(list); } } } else { @@ -291,9 +291,9 @@ public class CountersPutAi extends SpellAbilityAi { else { if (type.equals("P1P1")) { - choice = CardFactoryUtil.getWorstCreatureAI(list); + choice = ComputerUtilCard.getWorstCreatureAI(list); } else { - choice = CardFactoryUtil.getRandomCard(list); + choice = ComputerUtilCard.getRandomCard(list); } } } diff --git a/src/main/java/forge/card/ability/ai/DamageAllAi.java b/src/main/java/forge/card/ability/ai/DamageAllAi.java index e0cfcdd19a5..27477bb4c06 100644 --- a/src/main/java/forge/card/ability/ai/DamageAllAi.java +++ b/src/main/java/forge/card/ability/ai/DamageAllAi.java @@ -11,10 +11,10 @@ import forge.CardLists; import forge.Singletons; import forge.card.ability.AbilityUtils; import forge.card.ability.SpellAbilityAi; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.cost.Cost; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; +import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilCombat; import forge.game.ai.ComputerUtilCost; import forge.game.ai.ComputerUtilMana; @@ -96,7 +96,7 @@ public class DamageAllAi extends SpellAbilityAi { } // evaluate both lists and pass only if human creatures are more valuable - if ((CardFactoryUtil.evaluateCreatureList(computerList) + minGain) >= CardFactoryUtil + if ((ComputerUtilCard.evaluateCreatureList(computerList) + minGain) >= ComputerUtilCard .evaluateCreatureList(humanList)) { return false; } @@ -144,7 +144,7 @@ public class DamageAllAi extends SpellAbilityAi { return true; } - if (!computerList.isEmpty() && CardFactoryUtil.evaluateCreatureList(computerList) > CardFactoryUtil + if (!computerList.isEmpty() && ComputerUtilCard.evaluateCreatureList(computerList) > ComputerUtilCard .evaluateCreatureList(humanList)) { return false; } @@ -233,7 +233,7 @@ public class DamageAllAi extends SpellAbilityAi { return true; } - if (!computerList.isEmpty() && CardFactoryUtil.evaluateCreatureList(computerList) + 50 >= CardFactoryUtil + if (!computerList.isEmpty() && ComputerUtilCard.evaluateCreatureList(computerList) + 50 >= ComputerUtilCard .evaluateCreatureList(humanList)) { return false; } diff --git a/src/main/java/forge/card/ability/ai/DamageDealAi.java b/src/main/java/forge/card/ability/ai/DamageDealAi.java index 6003dd9834a..d5859a16105 100644 --- a/src/main/java/forge/card/ability/ai/DamageDealAi.java +++ b/src/main/java/forge/card/ability/ai/DamageDealAi.java @@ -11,12 +11,12 @@ import forge.CardLists; import forge.Singletons; import forge.card.ability.AbilityUtils; import forge.card.ability.SpellAbilityAi; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.cost.Cost; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; import forge.card.spellability.TargetSelection; import forge.game.ai.ComputerUtil; +import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilCombat; import forge.game.ai.ComputerUtilCost; import forge.game.ai.ComputerUtilMana; @@ -165,7 +165,7 @@ public class DamageDealAi extends DamageAiBase { Card targetCard; if (pl.isOpponentOf(ai) && (killables.size() > 0)) { - targetCard = CardFactoryUtil.getBestCreatureAI(killables); + targetCard = ComputerUtilCard.getBestCreatureAI(killables); return targetCard; } @@ -176,9 +176,9 @@ public class DamageDealAi extends DamageAiBase { if (hPlay.size() > 0) { if (pl.isOpponentOf(ai)) { - targetCard = CardFactoryUtil.getBestCreatureAI(hPlay); + targetCard = ComputerUtilCard.getBestCreatureAI(hPlay); } else { - targetCard = CardFactoryUtil.getWorstCreatureAI(hPlay); + targetCard = ComputerUtilCard.getWorstCreatureAI(hPlay); } return targetCard; diff --git a/src/main/java/forge/card/ability/ai/DamagePreventAi.java b/src/main/java/forge/card/ability/ai/DamagePreventAi.java index 42a542aa8c2..34907616167 100644 --- a/src/main/java/forge/card/ability/ai/DamagePreventAi.java +++ b/src/main/java/forge/card/ability/ai/DamagePreventAi.java @@ -9,11 +9,11 @@ import forge.CardPredicates; import forge.Singletons; import forge.card.ability.AbilityUtils; import forge.card.ability.SpellAbilityAi; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.cost.Cost; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; import forge.game.ai.ComputerUtil; +import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilCombat; import forge.game.ai.ComputerUtilCost; import forge.game.phase.PhaseHandler; @@ -113,7 +113,7 @@ public class DamagePreventAi extends SpellAbilityAi { if (!threatenedTargets.isEmpty()) { // Choose "best" of the remaining to save - tgt.addTarget(CardFactoryUtil.getBestCreatureAI(threatenedTargets)); + tgt.addTarget(ComputerUtilCard.getBestCreatureAI(threatenedTargets)); chance = true; } @@ -211,7 +211,7 @@ public class DamagePreventAi extends SpellAbilityAi { return true; } - tgt.addTarget(CardFactoryUtil.getCheapestPermanentAI(targetables, sa, true)); + tgt.addTarget(ComputerUtilCard.getCheapestPermanentAI(targetables, sa, true)); return true; } diff --git a/src/main/java/forge/card/ability/ai/DebuffAi.java b/src/main/java/forge/card/ability/ai/DebuffAi.java index 770a5a63294..6592bb7e6a6 100644 --- a/src/main/java/forge/card/ability/ai/DebuffAi.java +++ b/src/main/java/forge/card/ability/ai/DebuffAi.java @@ -11,11 +11,11 @@ import forge.CardLists; import forge.Singletons; import forge.card.ability.AbilityUtils; import forge.card.ability.SpellAbilityAi; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.cost.Cost; import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbilityRestriction; import forge.card.spellability.Target; +import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilCost; import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseType; @@ -164,7 +164,7 @@ public class DebuffAi extends SpellAbilityAi { } } - t = CardFactoryUtil.getBestCreatureAI(list); + t = ComputerUtilCard.getBestCreatureAI(list); tgt.addTarget(t); list.remove(t); } @@ -242,9 +242,9 @@ public class DebuffAi extends SpellAbilityAi { Card c; if (CardLists.getNotType(pref, "Creature").size() == 0) { - c = CardFactoryUtil.getBestCreatureAI(pref); + c = ComputerUtilCard.getBestCreatureAI(pref); } else { - c = CardFactoryUtil.getMostExpensivePermanentAI(pref, sa, true); + c = ComputerUtilCard.getMostExpensivePermanentAI(pref, sa, true); } pref.remove(c); @@ -261,9 +261,9 @@ public class DebuffAi extends SpellAbilityAi { // keyword Card c; if (CardLists.getNotType(forced, "Creature").size() == 0) { - c = CardFactoryUtil.getWorstCreatureAI(forced); + c = ComputerUtilCard.getWorstCreatureAI(forced); } else { - c = CardFactoryUtil.getCheapestPermanentAI(forced, sa, true); + c = ComputerUtilCard.getCheapestPermanentAI(forced, sa, true); } forced.remove(c); diff --git a/src/main/java/forge/card/ability/ai/DestroyAi.java b/src/main/java/forge/card/ability/ai/DestroyAi.java index f811857f4b8..c02550c868a 100644 --- a/src/main/java/forge/card/ability/ai/DestroyAi.java +++ b/src/main/java/forge/card/ability/ai/DestroyAi.java @@ -12,13 +12,13 @@ import forge.CounterType; import forge.Singletons; import forge.card.ability.AbilityUtils; import forge.card.ability.SpellAbilityAi; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.cost.Cost; import forge.card.cost.CostPart; import forge.card.cost.CostSacrifice; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; import forge.game.ai.ComputerUtil; +import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilCost; import forge.game.player.AIPlayer; import forge.game.player.Player; @@ -130,11 +130,11 @@ public class DestroyAi extends SpellAbilityAi { Card choice = null; // If the targets are only of one type, take the best if (CardLists.getNotType(list, "Creature").isEmpty()) { - choice = CardFactoryUtil.getBestCreatureAI(list); + choice = ComputerUtilCard.getBestCreatureAI(list); } else if (CardLists.getNotType(list, "Land").isEmpty()) { - choice = CardFactoryUtil.getBestLandAI(list); + choice = ComputerUtilCard.getBestLandAI(list); } else { - choice = CardFactoryUtil.getMostExpensivePermanentAI(list, sa, true); + choice = ComputerUtilCard.getMostExpensivePermanentAI(list, sa, true); } if (choice == null) { // can't find anything left @@ -218,11 +218,11 @@ public class DestroyAi extends SpellAbilityAi { } else { Card c; if (CardLists.getNotType(preferred, "Creature").size() == 0) { - c = CardFactoryUtil.getBestCreatureAI(preferred); + c = ComputerUtilCard.getBestCreatureAI(preferred); } else if (CardLists.getNotType(preferred, "Land").size() == 0) { - c = CardFactoryUtil.getBestLandAI(preferred); + c = ComputerUtilCard.getBestLandAI(preferred); } else { - c = CardFactoryUtil.getMostExpensivePermanentAI(preferred, sa, false); + c = ComputerUtilCard.getMostExpensivePermanentAI(preferred, sa, false); } tgt.addTarget(c); preferred.remove(c); @@ -235,9 +235,9 @@ public class DestroyAi extends SpellAbilityAi { } else { Card c; if (CardLists.getNotType(list, "Creature").size() == 0) { - c = CardFactoryUtil.getWorstCreatureAI(list); + c = ComputerUtilCard.getWorstCreatureAI(list); } else { - c = CardFactoryUtil.getCheapestPermanentAI(list, sa, false); + c = ComputerUtilCard.getCheapestPermanentAI(list, sa, false); } tgt.addTarget(c); list.remove(c); diff --git a/src/main/java/forge/card/ability/ai/DestroyAllAi.java b/src/main/java/forge/card/ability/ai/DestroyAllAi.java index 6722aceab89..750fe7cf689 100644 --- a/src/main/java/forge/card/ability/ai/DestroyAllAi.java +++ b/src/main/java/forge/card/ability/ai/DestroyAllAi.java @@ -8,10 +8,10 @@ import com.google.common.base.Predicate; import forge.Card; import forge.CardLists; import forge.card.ability.SpellAbilityAi; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.cost.Cost; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; +import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilCost; import forge.game.ai.ComputerUtilMana; import forge.game.player.AIPlayer; @@ -60,13 +60,13 @@ public class DestroyAllAi extends SpellAbilityAi { // if only creatures are affected evaluate both lists and pass only if // human creatures are more valuable if ((CardLists.getNotType(humanlist, "Creature").size() == 0) && (CardLists.getNotType(computerlist, "Creature").size() == 0)) { - if (CardFactoryUtil.evaluateCreatureList(computerlist) >= CardFactoryUtil.evaluateCreatureList(humanlist) + if (ComputerUtilCard.evaluateCreatureList(computerlist) >= ComputerUtilCard.evaluateCreatureList(humanlist) && !computerlist.isEmpty()) { return false; } } // otherwise evaluate both lists by CMC and pass only if human // permanents are more valuable - else if (CardFactoryUtil.evaluatePermanentList(computerlist) >= CardFactoryUtil.evaluatePermanentList(humanlist)) { + else if (ComputerUtilCard.evaluatePermanentList(computerlist) >= ComputerUtilCard.evaluatePermanentList(humanlist)) { return false; } return true; @@ -127,19 +127,19 @@ public class DestroyAllAi extends SpellAbilityAi { // if only creatures are affected evaluate both lists and pass only if // human creatures are more valuable if ((CardLists.getNotType(humanlist, "Creature").size() == 0) && (CardLists.getNotType(computerlist, "Creature").size() == 0)) { - if ((CardFactoryUtil.evaluateCreatureList(computerlist) + 200) >= CardFactoryUtil + if ((ComputerUtilCard.evaluateCreatureList(computerlist) + 200) >= ComputerUtilCard .evaluateCreatureList(humanlist)) { return false; } } // only lands involved else if ((CardLists.getNotType(humanlist, "Land").size() == 0) && (CardLists.getNotType(computerlist, "Land").size() == 0)) { - if ((CardFactoryUtil.evaluatePermanentList(computerlist) + 1) >= CardFactoryUtil + if ((ComputerUtilCard.evaluatePermanentList(computerlist) + 1) >= ComputerUtilCard .evaluatePermanentList(humanlist)) { return false; } } // otherwise evaluate both lists by CMC and pass only if human // permanents are more valuable - else if ((CardFactoryUtil.evaluatePermanentList(computerlist) + 3) >= CardFactoryUtil + else if ((ComputerUtilCard.evaluatePermanentList(computerlist) + 3) >= ComputerUtilCard .evaluatePermanentList(humanlist)) { return false; } diff --git a/src/main/java/forge/card/ability/ai/EffectAi.java b/src/main/java/forge/card/ability/ai/EffectAi.java index bd6ecf61f5d..7ee1bd9a0c7 100644 --- a/src/main/java/forge/card/ability/ai/EffectAi.java +++ b/src/main/java/forge/card/ability/ai/EffectAi.java @@ -9,10 +9,10 @@ import forge.Card; import forge.CardLists; import forge.Singletons; import forge.card.ability.SpellAbilityAi; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; import forge.game.GameState; +import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilCombat; import forge.game.phase.CombatUtil; import forge.game.phase.PhaseHandler; @@ -61,7 +61,7 @@ public class EffectAi extends SpellAbilityAi { List list = game.getCombat().getAttackerList(); list = CardLists.getValidCards(list, tgt.getValidTgts(), sa.getActivatingPlayer(), sa.getSourceCard()); list = CardLists.getTargetableCards(list, sa); - Card target = CardFactoryUtil.getBestCreatureAI(list); + Card target = ComputerUtilCard.getBestCreatureAI(list); if (target == null) { return false; } diff --git a/src/main/java/forge/card/ability/ai/MustBlockAi.java b/src/main/java/forge/card/ability/ai/MustBlockAi.java index a4067782a78..1777fee8fdf 100644 --- a/src/main/java/forge/card/ability/ai/MustBlockAi.java +++ b/src/main/java/forge/card/ability/ai/MustBlockAi.java @@ -10,9 +10,9 @@ import forge.CardPredicates; import forge.Singletons; import forge.card.ability.AbilityUtils; import forge.card.ability.SpellAbilityAi; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; +import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilCombat; import forge.game.phase.CombatUtil; import forge.game.phase.PhaseType; @@ -86,7 +86,7 @@ public class MustBlockAi extends SpellAbilityAi { if (list.isEmpty()) { return false; } - final Card blocker = CardFactoryUtil.getBestCreatureAI(list); + final Card blocker = ComputerUtilCard.getBestCreatureAI(list); if (blocker == null) { return false; } diff --git a/src/main/java/forge/card/ability/ai/PlayAi.java b/src/main/java/forge/card/ability/ai/PlayAi.java index 4068c8fddac..1302736e654 100644 --- a/src/main/java/forge/card/ability/ai/PlayAi.java +++ b/src/main/java/forge/card/ability/ai/PlayAi.java @@ -9,10 +9,10 @@ import forge.CardLists; import forge.Singletons; import forge.card.ability.AbilityUtils; import forge.card.ability.SpellAbilityAi; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.cost.Cost; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; +import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilCost; import forge.game.player.AIPlayer; import forge.game.zone.ZoneType; @@ -62,7 +62,7 @@ public class PlayAi extends SpellAbilityAi { if (cards.isEmpty()) { return false; } - tgt.addTarget(CardFactoryUtil.getBestAI(cards)); + tgt.addTarget(ComputerUtilCard.getBestAI(cards)); } else if (!sa.hasParam("Valid")) { cards = new ArrayList(AbilityUtils.getDefinedCards(sa.getSourceCard(), sa.getParam("Defined"), sa)); if (cards.isEmpty()) { diff --git a/src/main/java/forge/card/ability/ai/ProtectAi.java b/src/main/java/forge/card/ability/ai/ProtectAi.java index 87d97ba2178..507b60f36e8 100644 --- a/src/main/java/forge/card/ability/ai/ProtectAi.java +++ b/src/main/java/forge/card/ability/ai/ProtectAi.java @@ -11,11 +11,11 @@ import forge.Constant; import forge.Singletons; import forge.card.ability.AbilityUtils; import forge.card.ability.SpellAbilityAi; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.cost.Cost; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; import forge.game.GameState; +import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilCombat; import forge.game.ai.ComputerUtilCost; import forge.game.phase.PhaseType; @@ -86,7 +86,7 @@ public class ProtectAi extends SpellAbilityAi { // will the creature attack (only relevant for sorcery speed)? if (game.getPhaseHandler().getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS) && game.getPhaseHandler().isPlayerTurn(ai) - && CardFactoryUtil.doesCreatureAttackAI(ai, c)) { + && ComputerUtilCard.doesCreatureAttackAI(ai, c)) { return true; } @@ -241,7 +241,7 @@ public class ProtectAi extends SpellAbilityAi { } } - t = CardFactoryUtil.getBestCreatureAI(list); + t = ComputerUtilCard.getBestCreatureAI(list); tgt.addTarget(t); list.remove(t); } @@ -290,9 +290,9 @@ public class ProtectAi extends SpellAbilityAi { Card c; if (CardLists.getNotType(pref, "Creature").size() == 0) { - c = CardFactoryUtil.getBestCreatureAI(pref); + c = ComputerUtilCard.getBestCreatureAI(pref); } else { - c = CardFactoryUtil.getMostExpensivePermanentAI(pref, sa, true); + c = ComputerUtilCard.getMostExpensivePermanentAI(pref, sa, true); } pref.remove(c); @@ -307,9 +307,9 @@ public class ProtectAi extends SpellAbilityAi { Card c; if (CardLists.getNotType(pref2, "Creature").size() == 0) { - c = CardFactoryUtil.getBestCreatureAI(pref2); + c = ComputerUtilCard.getBestCreatureAI(pref2); } else { - c = CardFactoryUtil.getMostExpensivePermanentAI(pref2, sa, true); + c = ComputerUtilCard.getMostExpensivePermanentAI(pref2, sa, true); } pref2.remove(c); @@ -324,9 +324,9 @@ public class ProtectAi extends SpellAbilityAi { Card c; if (CardLists.getNotType(forced, "Creature").size() == 0) { - c = CardFactoryUtil.getWorstCreatureAI(forced); + c = ComputerUtilCard.getWorstCreatureAI(forced); } else { - c = CardFactoryUtil.getCheapestPermanentAI(forced, sa, true); + c = ComputerUtilCard.getCheapestPermanentAI(forced, sa, true); } forced.remove(c); diff --git a/src/main/java/forge/card/ability/ai/PumpAi.java b/src/main/java/forge/card/ability/ai/PumpAi.java index 85e1220b265..50f8b1ca376 100644 --- a/src/main/java/forge/card/ability/ai/PumpAi.java +++ b/src/main/java/forge/card/ability/ai/PumpAi.java @@ -11,13 +11,13 @@ import forge.Singletons; import forge.CardPredicates.Presets; import forge.card.ability.AbilityUtils; import forge.card.ability.SpellAbilityAi; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.cost.Cost; import forge.card.cost.CostUtil; import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbilityRestriction; import forge.card.spellability.Target; import forge.game.ai.ComputerUtil; +import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilCost; import forge.game.ai.ComputerUtilMana; import forge.game.phase.PhaseHandler; @@ -259,7 +259,7 @@ public class PumpAi extends PumpAiBase { } } - t = CardFactoryUtil.getBestAI(list); + t = ComputerUtilCard.getBestAI(list); tgt.addTarget(t); list.remove(t); } @@ -303,9 +303,9 @@ public class PumpAi extends PumpAiBase { Card c; if (CardLists.getNotType(pref, "Creature").size() == 0) { - c = CardFactoryUtil.getBestCreatureAI(pref); + c = ComputerUtilCard.getBestCreatureAI(pref); } else { - c = CardFactoryUtil.getMostExpensivePermanentAI(pref, sa, true); + c = ComputerUtilCard.getMostExpensivePermanentAI(pref, sa, true); } pref.remove(c); @@ -320,9 +320,9 @@ public class PumpAi extends PumpAiBase { Card c; if (CardLists.getNotType(forced, "Creature").size() == 0) { - c = CardFactoryUtil.getWorstCreatureAI(forced); + c = ComputerUtilCard.getWorstCreatureAI(forced); } else { - c = CardFactoryUtil.getCheapestPermanentAI(forced, sa, true); + c = ComputerUtilCard.getCheapestPermanentAI(forced, sa, true); } forced.remove(c); diff --git a/src/main/java/forge/card/ability/ai/PumpAiBase.java b/src/main/java/forge/card/ability/ai/PumpAiBase.java index 322243a0a4c..6d35c7e80b1 100644 --- a/src/main/java/forge/card/ability/ai/PumpAiBase.java +++ b/src/main/java/forge/card/ability/ai/PumpAiBase.java @@ -13,10 +13,10 @@ import forge.CardPredicates; import forge.CardUtil; import forge.Singletons; import forge.card.ability.SpellAbilityAi; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.spellability.SpellAbility; import forge.game.GameState; import forge.game.ai.ComputerUtil; +import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilCombat; import forge.game.phase.Combat; import forge.game.phase.CombatUtil; @@ -403,7 +403,7 @@ public abstract class PumpAiBase extends SpellAbilityAi { && phase.isPlayerTurn(ai) && SpellAbilityAi.isSorcerySpeed(sa) && attack > 0 - && CardFactoryUtil.doesCreatureAttackAI(ai, c)) { + && ComputerUtilCard.doesCreatureAttackAI(ai, c)) { return true; } diff --git a/src/main/java/forge/card/ability/ai/PumpAllAi.java b/src/main/java/forge/card/ability/ai/PumpAllAi.java index e650e579e9b..f1970c7e343 100644 --- a/src/main/java/forge/card/ability/ai/PumpAllAi.java +++ b/src/main/java/forge/card/ability/ai/PumpAllAi.java @@ -10,9 +10,9 @@ import forge.Card; import forge.CardLists; import forge.Singletons; import forge.card.ability.AbilityUtils; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; +import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilCombat; import forge.game.ai.ComputerUtil; import forge.game.phase.CombatUtil; @@ -106,7 +106,7 @@ public class PumpAllAi extends PumpAiBase { // evaluate both lists and pass only if human creatures are more // valuable - if ((CardFactoryUtil.evaluateCreatureList(comp) + 200) >= CardFactoryUtil.evaluateCreatureList(human)) { + if ((ComputerUtilCard.evaluateCreatureList(comp) + 200) >= ComputerUtilCard.evaluateCreatureList(human)) { return false; } return true; diff --git a/src/main/java/forge/card/ability/ai/RegenerateAi.java b/src/main/java/forge/card/ability/ai/RegenerateAi.java index 254bffdbff0..66c52f44c66 100644 --- a/src/main/java/forge/card/ability/ai/RegenerateAi.java +++ b/src/main/java/forge/card/ability/ai/RegenerateAi.java @@ -27,11 +27,11 @@ import forge.CardPredicates; import forge.Singletons; import forge.card.ability.AbilityUtils; import forge.card.ability.SpellAbilityAi; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.cost.Cost; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; import forge.game.ai.ComputerUtil; +import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilCombat; import forge.game.ai.ComputerUtilCost; import forge.game.phase.PhaseType; @@ -132,7 +132,7 @@ public class RegenerateAi extends SpellAbilityAi { if (!threatenedTargets.isEmpty()) { // Choose "best" of the remaining to regenerate - tgt.addTarget(CardFactoryUtil.getBestCreatureAI(threatenedTargets)); + tgt.addTarget(ComputerUtilCard.getBestCreatureAI(threatenedTargets)); chance = true; } } else { @@ -225,7 +225,7 @@ public class RegenerateAi extends SpellAbilityAi { } } - tgt.addTarget(CardFactoryUtil.getCheapestPermanentAI(targetables, sa, true)); + tgt.addTarget(ComputerUtilCard.getCheapestPermanentAI(targetables, sa, true)); return true; } diff --git a/src/main/java/forge/card/ability/ai/SacrificeAi.java b/src/main/java/forge/card/ability/ai/SacrificeAi.java index ddf6adc720c..8f04e0c08c8 100644 --- a/src/main/java/forge/card/ability/ai/SacrificeAi.java +++ b/src/main/java/forge/card/ability/ai/SacrificeAi.java @@ -5,9 +5,9 @@ import forge.Card; import forge.CardLists; import forge.card.ability.AbilityUtils; import forge.card.ability.SpellAbilityAi; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; +import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilMana; import forge.game.player.AIPlayer; import forge.game.player.Player; @@ -128,7 +128,7 @@ public class SacrificeAi extends SpellAbilityAi { List computerList = CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), valid.split(","), sa.getActivatingPlayer(), sa.getSourceCard()); for (Card c : computerList) { - if (!c.getSVar("SacMe").equals("") || CardFactoryUtil.evaluateCreature(c) <= 135) { + if (!c.getSVar("SacMe").equals("") || ComputerUtilCard.evaluateCreature(c) <= 135) { return true; } } diff --git a/src/main/java/forge/card/ability/ai/SacrificeAllAi.java b/src/main/java/forge/card/ability/ai/SacrificeAllAi.java index b56ad00ef08..b6fc3d3b307 100644 --- a/src/main/java/forge/card/ability/ai/SacrificeAllAi.java +++ b/src/main/java/forge/card/ability/ai/SacrificeAllAi.java @@ -6,9 +6,9 @@ import java.util.Random; import forge.Card; import forge.CardLists; import forge.card.ability.SpellAbilityAi; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.cost.Cost; import forge.card.spellability.SpellAbility; +import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilCost; import forge.game.ai.ComputerUtilMana; import forge.game.player.AIPlayer; @@ -55,19 +55,19 @@ public class SacrificeAllAi extends SpellAbilityAi { // if only creatures are affected evaluate both lists and pass only if // human creatures are more valuable if ((CardLists.getNotType(humanlist, "Creature").size() == 0) && (CardLists.getNotType(computerlist, "Creature").size() == 0)) { - if ((CardFactoryUtil.evaluateCreatureList(computerlist) + 200) >= CardFactoryUtil + if ((ComputerUtilCard.evaluateCreatureList(computerlist) + 200) >= ComputerUtilCard .evaluateCreatureList(humanlist)) { return false; } } // only lands involved else if ((CardLists.getNotType(humanlist, "Land").size() == 0) && (CardLists.getNotType(computerlist, "Land").size() == 0)) { - if ((CardFactoryUtil.evaluatePermanentList(computerlist) + 1) >= CardFactoryUtil + if ((ComputerUtilCard.evaluatePermanentList(computerlist) + 1) >= ComputerUtilCard .evaluatePermanentList(humanlist)) { return false; } } // otherwise evaluate both lists by CMC and pass only if human // permanents are more valuable - else if ((CardFactoryUtil.evaluatePermanentList(computerlist) + 3) >= CardFactoryUtil + else if ((ComputerUtilCard.evaluatePermanentList(computerlist) + 3) >= ComputerUtilCard .evaluatePermanentList(humanlist)) { return false; } diff --git a/src/main/java/forge/card/ability/ai/TapAiBase.java b/src/main/java/forge/card/ability/ai/TapAiBase.java index 2f8d3052d14..396a03f36e3 100644 --- a/src/main/java/forge/card/ability/ai/TapAiBase.java +++ b/src/main/java/forge/card/ability/ai/TapAiBase.java @@ -11,10 +11,10 @@ import forge.CardPredicates; import forge.Singletons; import forge.CardPredicates.Presets; import forge.card.ability.SpellAbilityAi; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; import forge.game.ai.ComputerUtil; +import forge.game.ai.ComputerUtilCard; import forge.game.phase.CombatUtil; import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseType; @@ -69,9 +69,9 @@ public abstract class TapAiBase extends SpellAbilityAi { if (CardLists.getNotType(tapList, "Creature").size() == 0) { // if only creatures take the best - choice = CardFactoryUtil.getBestCreatureAI(tapList); + choice = ComputerUtilCard.getBestCreatureAI(tapList); } else { - choice = CardFactoryUtil.getMostExpensivePermanentAI(tapList, sa, false); + choice = ComputerUtilCard.getMostExpensivePermanentAI(tapList, sa, false); } if (choice == null) { // can't find anything left @@ -179,9 +179,9 @@ public abstract class TapAiBase extends SpellAbilityAi { Predicate findBlockers = CardPredicates.possibleBlockerForAtLeastOne(attackers); List creatureList = CardLists.filter(tapList, findBlockers); if (!attackers.isEmpty() && !creatureList.isEmpty()) { - choice = CardFactoryUtil.getBestCreatureAI(creatureList); + choice = ComputerUtilCard.getBestCreatureAI(creatureList); } else if (sa.isTrigger()) { - choice = CardFactoryUtil.getMostExpensivePermanentAI(tapList, sa, false); + choice = ComputerUtilCard.getMostExpensivePermanentAI(tapList, sa, false); } } else if (phase.isPlayerTurn(opp) @@ -194,12 +194,12 @@ public abstract class TapAiBase extends SpellAbilityAi { return c.isCreature() && CombatUtil.canAttack(c, opp); } }); - choice = CardFactoryUtil.getBestCreatureAI(creatureList); + choice = ComputerUtilCard.getBestCreatureAI(creatureList); } else { // no creatures available - choice = CardFactoryUtil.getMostExpensivePermanentAI(tapList, sa, false); + choice = ComputerUtilCard.getMostExpensivePermanentAI(tapList, sa, false); } } else { - choice = CardFactoryUtil.getMostExpensivePermanentAI(tapList, sa, false); + choice = ComputerUtilCard.getMostExpensivePermanentAI(tapList, sa, false); } if (choice == null) { // can't find anything left diff --git a/src/main/java/forge/card/ability/ai/UnattachAllAi.java b/src/main/java/forge/card/ability/ai/UnattachAllAi.java index f6775d6f4e1..9878d54bb67 100644 --- a/src/main/java/forge/card/ability/ai/UnattachAllAi.java +++ b/src/main/java/forge/card/ability/ai/UnattachAllAi.java @@ -7,10 +7,10 @@ import forge.Card; import forge.Singletons; import forge.card.ability.AbilityUtils; import forge.card.ability.SpellAbilityAi; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.cost.Cost; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; +import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilMana; import forge.game.phase.PhaseType; import forge.game.player.AIPlayer; @@ -84,7 +84,7 @@ public class UnattachAllAi extends SpellAbilityAi { //don't equip a worse creature if (card.isEquipping()) { Card oldTarget = card.getEquipping().get(0); - if (CardFactoryUtil.evaluateCreature(oldTarget) > CardFactoryUtil.evaluateCreature(newTarget)) { + if (ComputerUtilCard.evaluateCreature(oldTarget) > ComputerUtilCard.evaluateCreature(newTarget)) { return false; } } diff --git a/src/main/java/forge/card/ability/ai/UntapAi.java b/src/main/java/forge/card/ability/ai/UntapAi.java index 677cca31b2a..d6a16eaea47 100644 --- a/src/main/java/forge/card/ability/ai/UntapAi.java +++ b/src/main/java/forge/card/ability/ai/UntapAi.java @@ -9,10 +9,10 @@ import forge.Singletons; import forge.CardPredicates.Presets; import forge.card.ability.AbilityUtils; import forge.card.ability.SpellAbilityAi; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.cost.Cost; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; +import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilCost; import forge.game.player.AIPlayer; import forge.game.player.Player; @@ -148,14 +148,14 @@ public class UntapAi extends SpellAbilityAi { } if (CardLists.getNotType(untapList, "Creature").size() == 0) { - choice = CardFactoryUtil.getBestCreatureAI(untapList); // if + choice = ComputerUtilCard.getBestCreatureAI(untapList); // if // only // creatures // take // the // best } else { - choice = CardFactoryUtil.getMostExpensivePermanentAI(untapList, sa, false); + choice = ComputerUtilCard.getMostExpensivePermanentAI(untapList, sa, false); } if (choice == null) { // can't find anything left @@ -267,13 +267,13 @@ public class UntapAi extends SpellAbilityAi { } if (CardLists.getNotType(tapList, "Creature").size() == 0) { - choice = CardFactoryUtil.getBestCreatureAI(tapList); // if only + choice = ComputerUtilCard.getBestCreatureAI(tapList); // if only // creatures // take // the // best } else { - choice = CardFactoryUtil.getMostExpensivePermanentAI(tapList, sa, false); + choice = ComputerUtilCard.getMostExpensivePermanentAI(tapList, sa, false); } if (choice == null) { // can't find anything left diff --git a/src/main/java/forge/card/ability/effects/ChangeZoneEffect.java b/src/main/java/forge/card/ability/effects/ChangeZoneEffect.java index 0d6654fe58f..8ac6861aad1 100644 --- a/src/main/java/forge/card/ability/effects/ChangeZoneEffect.java +++ b/src/main/java/forge/card/ability/effects/ChangeZoneEffect.java @@ -13,11 +13,11 @@ import forge.Singletons; import forge.card.ability.AbilityUtils; import forge.card.ability.SpellAbilityEffect; import forge.card.ability.ai.ChangeZoneAi; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.spellability.AbilitySub; import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbilityStackInstance; import forge.card.spellability.Target; +import forge.game.ai.ComputerUtilCard; import forge.game.player.Player; import forge.game.zone.Zone; import forge.game.zone.ZoneType; @@ -403,7 +403,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect { attachedTo = list.get(0); } } else { // AI player - attachedTo = CardFactoryUtil.getBestAI(list); + attachedTo = ComputerUtilCard.getBestAI(list); } if (tgtC.isAura()) { if (tgtC.isEnchanting()) { diff --git a/src/main/java/forge/card/ability/effects/ChooseCardEffect.java b/src/main/java/forge/card/ability/effects/ChooseCardEffect.java index 84d9df27378..578a6e08c0a 100644 --- a/src/main/java/forge/card/ability/effects/ChooseCardEffect.java +++ b/src/main/java/forge/card/ability/effects/ChooseCardEffect.java @@ -74,52 +74,19 @@ public class ChooseCardEffect extends SpellAbilityEffect { for (final Player p : tgtPlayers) { if ((tgt == null) || p.canBeTargetedBy(sa)) { for (int i = 0; i < validAmount; i++) { - if (p.isHuman()) { - final String choiceTitle = sa.hasParam("ChoiceTitle") ? sa.getParam("ChoiceTitle") : "Choose a card "; - Card o; - if (sa.hasParam("AtRandom")) { - o = Aggregates.random(choices); - } else if (sa.hasParam("Mandatory")) { - o = GuiChoose.one(choiceTitle, choices); - } else { - o = GuiChoose.oneOrNone(choiceTitle, choices); - } - if (o != null) { - chosen.add(o); - choices.remove(o); - } else { - break; - } - } else { // Computer - String logic = sa.getParam("AILogic"); - Card choice = null; - if (logic == null) { - // Base Logic is choose "best" - choice = CardFactoryUtil.getBestAI(choices); - } else if ("WorstCard".equals(logic)) { - choice = CardFactoryUtil.getWorstAI(choices); - } else if (logic.equals("BestBlocker")) { - if (!CardLists.filter(choices, Presets.UNTAPPED).isEmpty()) { - choices = CardLists.filter(choices, Presets.UNTAPPED); - } - choice = CardFactoryUtil.getBestCreatureAI(choices); - } else if (logic.equals("Clone")) { - if (!CardLists.getValidCards(choices, "Permanent.YouDontCtrl,Permanent.nonLegendary", host.getController(), host).isEmpty()) { - choices = CardLists.getValidCards(choices, "Permanent.YouDontCtrl,Permanent.nonLegendary", host.getController(), host); - } - choice = CardFactoryUtil.getBestAI(choices); - } else if (logic.equals("Untap")) { - if (!CardLists.getValidCards(choices, "Permanent.YouCtrl,Permanent.tapped", host.getController(), host).isEmpty()) { - choices = CardLists.getValidCards(choices, "Permanent.YouCtrl,Permanent.tapped", host.getController(), host); - } - choice = CardFactoryUtil.getBestAI(choices); - } - if (choice != null) { - chosen.add(choice); - choices.remove(choice); - } else { - break; - } + + Card c; + if (sa.hasParam("AtRandom")) { + c = Aggregates.random(choices); + } else { + c = p.getController().chooseSingleCardForEffect(choices, sa, sa.hasParam("ChoiceTitle") ? sa.getParam("ChoiceTitle") : "Choose a card ", !sa.hasParam("Mandatory")); + } + + if (c != null) { + chosen.add(c); + choices.remove(c); + } else { + break; } } host.setChosenCard(chosen); diff --git a/src/main/java/forge/card/ability/effects/ChooseCardNameEffect.java b/src/main/java/forge/card/ability/effects/ChooseCardNameEffect.java index 70403a1cdd6..6c2f15294c8 100644 --- a/src/main/java/forge/card/ability/effects/ChooseCardNameEffect.java +++ b/src/main/java/forge/card/ability/effects/ChooseCardNameEffect.java @@ -16,9 +16,9 @@ import forge.Singletons; import forge.CardPredicates.Presets; import forge.card.CardRulesPredicates; import forge.card.ability.SpellAbilityEffect; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; +import forge.game.ai.ComputerUtilCard; import forge.game.player.Player; import forge.game.zone.ZoneType; import forge.gui.GuiChoose; @@ -90,9 +90,9 @@ public class ChooseCardNameEffect extends SpellAbilityEffect { if (sa.hasParam("AILogic")) { final String logic = sa.getParam("AILogic"); if (logic.equals("MostProminentInComputerDeck")) { - chosen = CardFactoryUtil.getMostProminentCardName(p.getCardsIn(ZoneType.Library)); + chosen = ComputerUtilCard.getMostProminentCardName(p.getCardsIn(ZoneType.Library)); } else if (logic.equals("MostProminentInHumanDeck")) { - chosen = CardFactoryUtil.getMostProminentCardName(p.getOpponent().getCardsIn(ZoneType.Library)); + chosen = ComputerUtilCard.getMostProminentCardName(p.getOpponent().getCardsIn(ZoneType.Library)); } } else { List list = CardLists.filterControlledBy(Singletons.getModel().getGame().getCardsInGame(), p.getOpponent()); diff --git a/src/main/java/forge/card/ability/effects/ChooseColorEffect.java b/src/main/java/forge/card/ability/effects/ChooseColorEffect.java index 45e38746f71..5b03e7ba09e 100644 --- a/src/main/java/forge/card/ability/effects/ChooseColorEffect.java +++ b/src/main/java/forge/card/ability/effects/ChooseColorEffect.java @@ -9,9 +9,9 @@ import forge.CardPredicates; import forge.Constant; import forge.Singletons; import forge.card.ability.SpellAbilityEffect; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; +import forge.game.ai.ComputerUtilCard; import forge.game.player.Player; import forge.game.zone.ZoneType; import forge.gui.GuiChoose; @@ -69,36 +69,36 @@ public class ChooseColorEffect extends SpellAbilityEffect { if (sa.hasParam("AILogic")) { final String logic = sa.getParam("AILogic"); if (logic.equals("MostProminentInHumanDeck")) { - chosen.add(CardFactoryUtil.getMostProminentColor(CardLists.filterControlledBy(Singletons.getModel().getGame().getCardsInGame(), opp))); + chosen.add(ComputerUtilCard.getMostProminentColor(CardLists.filterControlledBy(Singletons.getModel().getGame().getCardsInGame(), opp))); } else if (logic.equals("MostProminentInComputerDeck")) { - chosen.add(CardFactoryUtil.getMostProminentColor(CardLists.filterControlledBy(Singletons.getModel().getGame().getCardsInGame(), ai))); + chosen.add(ComputerUtilCard.getMostProminentColor(CardLists.filterControlledBy(Singletons.getModel().getGame().getCardsInGame(), ai))); } else if (logic.equals("MostProminentDualInComputerDeck")) { - List prominence = CardFactoryUtil.getColorByProminence(CardLists.filterControlledBy(Singletons.getModel().getGame().getCardsInGame(), ai)); + List prominence = ComputerUtilCard.getColorByProminence(CardLists.filterControlledBy(Singletons.getModel().getGame().getCardsInGame(), ai)); chosen.add(prominence.get(0)); chosen.add(prominence.get(1)); } else if (logic.equals("MostProminentInGame")) { - chosen.add(CardFactoryUtil.getMostProminentColor(Singletons.getModel().getGame().getCardsInGame())); + chosen.add(ComputerUtilCard.getMostProminentColor(Singletons.getModel().getGame().getCardsInGame())); } else if (logic.equals("MostProminentHumanCreatures")) { List list = opp.getCreaturesInPlay(); if (list.isEmpty()) { list = CardLists.filter(CardLists.filterControlledBy(Singletons.getModel().getGame().getCardsInGame(), opp), CardPredicates.Presets.CREATURES); } - chosen.add(CardFactoryUtil.getMostProminentColor(list)); + chosen.add(ComputerUtilCard.getMostProminentColor(list)); } else if (logic.equals("MostProminentComputerControls")) { - chosen.add(CardFactoryUtil.getMostProminentColor(ai.getCardsIn(ZoneType.Battlefield))); + chosen.add(ComputerUtilCard.getMostProminentColor(ai.getCardsIn(ZoneType.Battlefield))); } else if (logic.equals("MostProminentHumanControls")) { - chosen.add(CardFactoryUtil.getMostProminentColor(ai.getOpponent().getCardsIn(ZoneType.Battlefield))); + chosen.add(ComputerUtilCard.getMostProminentColor(ai.getOpponent().getCardsIn(ZoneType.Battlefield))); } else if (logic.equals("MostProminentPermanent")) { final List list = Singletons.getModel().getGame().getCardsIn(ZoneType.Battlefield); - chosen.add(CardFactoryUtil.getMostProminentColor(list)); + chosen.add(ComputerUtilCard.getMostProminentColor(list)); } else if (logic.equals("MostProminentAttackers")) { - chosen.add(CardFactoryUtil.getMostProminentColor(Singletons.getModel().getGame().getCombat() + chosen.add(ComputerUtilCard.getMostProminentColor(Singletons.getModel().getGame().getCombat() .getAttackerList())); } else if (logic.equals("MostProminentKeywordInComputerDeck")) { diff --git a/src/main/java/forge/card/ability/effects/ChooseSourceEffect.java b/src/main/java/forge/card/ability/effects/ChooseSourceEffect.java index fd6746222c6..bdf3b618aae 100644 --- a/src/main/java/forge/card/ability/effects/ChooseSourceEffect.java +++ b/src/main/java/forge/card/ability/effects/ChooseSourceEffect.java @@ -14,6 +14,7 @@ import forge.card.cardfactory.CardFactoryUtil; import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbilityStackInstance; import forge.card.spellability.Target; +import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilCombat; import forge.game.player.Player; import forge.game.zone.ZoneType; @@ -181,10 +182,10 @@ public class ChooseSourceEffect extends SpellAbilityEffect { return ComputerUtilCombat.damageIfUnblocked(c, ai, Singletons.getModel().getGame().getCombat()) > 0; } }); - chosen.add(CardFactoryUtil.getBestCreatureAI(sourcesToChooseFrom)); + chosen.add(ComputerUtilCard.getBestCreatureAI(sourcesToChooseFrom)); } } else { - chosen.add(CardFactoryUtil.getBestAI(sourcesToChooseFrom)); + chosen.add(ComputerUtilCard.getBestAI(sourcesToChooseFrom)); } } } diff --git a/src/main/java/forge/card/ability/effects/ChooseTypeEffect.java b/src/main/java/forge/card/ability/effects/ChooseTypeEffect.java index 1c8f8ffacab..7bdccd516b3 100644 --- a/src/main/java/forge/card/ability/effects/ChooseTypeEffect.java +++ b/src/main/java/forge/card/ability/effects/ChooseTypeEffect.java @@ -13,9 +13,9 @@ import forge.Constant; import forge.Singletons; import forge.card.CardType; import forge.card.ability.SpellAbilityEffect; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; +import forge.game.ai.ComputerUtilCard; import forge.game.player.Player; import forge.game.zone.ZoneType; import forge.gui.GuiChoose; @@ -103,22 +103,22 @@ public class ChooseTypeEffect extends SpellAbilityEffect { if (sa.hasParam("AILogic")) { final String logic = sa.getParam("AILogic"); if (logic.equals("MostProminentOnBattlefield")) { - chosen = CardFactoryUtil.getMostProminentCreatureType(Singletons.getModel().getGame().getCardsIn(ZoneType.Battlefield)); + chosen = ComputerUtilCard.getMostProminentCreatureType(Singletons.getModel().getGame().getCardsIn(ZoneType.Battlefield)); } else if (logic.equals("MostProminentComputerControls")) { - chosen = CardFactoryUtil.getMostProminentCreatureType(ai.getCardsIn(ZoneType.Battlefield)); + chosen = ComputerUtilCard.getMostProminentCreatureType(ai.getCardsIn(ZoneType.Battlefield)); } else if (logic.equals("MostProminentHumanControls")) { - chosen = CardFactoryUtil.getMostProminentCreatureType(opp.getCardsIn(ZoneType.Battlefield)); + chosen = ComputerUtilCard.getMostProminentCreatureType(opp.getCardsIn(ZoneType.Battlefield)); if (!CardType.isACreatureType(chosen) || invalidTypes.contains(chosen)) { - chosen = CardFactoryUtil.getMostProminentCreatureType(CardLists.filterControlledBy(Singletons.getModel().getGame().getCardsInGame(), opp)); + chosen = ComputerUtilCard.getMostProminentCreatureType(CardLists.filterControlledBy(Singletons.getModel().getGame().getCardsInGame(), opp)); } } else if (logic.equals("MostProminentInComputerDeck")) { - chosen = CardFactoryUtil.getMostProminentCreatureType(CardLists.filterControlledBy(Singletons.getModel().getGame().getCardsInGame(), ai)); + chosen = ComputerUtilCard.getMostProminentCreatureType(CardLists.filterControlledBy(Singletons.getModel().getGame().getCardsInGame(), ai)); } else if (logic.equals("MostProminentInComputerGraveyard")) { - chosen = CardFactoryUtil.getMostProminentCreatureType(ai.getCardsIn(ZoneType.Graveyard)); + chosen = ComputerUtilCard.getMostProminentCreatureType(ai.getCardsIn(ZoneType.Graveyard)); } } if (!CardType.isACreatureType(chosen) || invalidTypes.contains(chosen)) { diff --git a/src/main/java/forge/card/ability/effects/DigEffect.java b/src/main/java/forge/card/ability/effects/DigEffect.java index c6841146d9a..fa4be8cc5ee 100644 --- a/src/main/java/forge/card/ability/effects/DigEffect.java +++ b/src/main/java/forge/card/ability/effects/DigEffect.java @@ -12,9 +12,9 @@ import forge.CardLists; import forge.Singletons; import forge.card.ability.AbilityUtils; import forge.card.ability.SpellAbilityEffect; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; +import forge.game.ai.ComputerUtilCard; import forge.game.player.Player; import forge.game.zone.PlayerZone; import forge.game.zone.ZoneType; @@ -195,9 +195,9 @@ public class DigEffect extends SpellAbilityEffect { chosen = GuiChoose.one(prompt + destZone2, valid); movedCards.remove(chosen); } else { // Computer - Card chosen = CardFactoryUtil.getBestAI(valid); + Card chosen = ComputerUtilCard.getBestAI(valid); if (sa.getActivatingPlayer().isHuman() && p.isHuman()) { - chosen = CardFactoryUtil.getWorstAI(valid); + chosen = ComputerUtilCard.getWorstAI(valid); } movedCards.remove(chosen); } @@ -250,9 +250,9 @@ public class DigEffect extends SpellAbilityEffect { changeNum = valid.size(); // always take all } for (j = 0; j < changeNum; j++) { - Card chosen = CardFactoryUtil.getBestAI(valid); + Card chosen = ComputerUtilCard.getBestAI(valid); if (sa.getActivatingPlayer().isHuman() && p.isHuman()) { - chosen = CardFactoryUtil.getWorstAI(valid); + chosen = ComputerUtilCard.getWorstAI(valid); } if (chosen == null) { break; diff --git a/src/main/java/forge/card/ability/effects/DiscardEffect.java b/src/main/java/forge/card/ability/effects/DiscardEffect.java index 3f2502fe574..858b59f6af0 100644 --- a/src/main/java/forge/card/ability/effects/DiscardEffect.java +++ b/src/main/java/forge/card/ability/effects/DiscardEffect.java @@ -15,6 +15,7 @@ import forge.card.ability.AbilityUtils; import forge.card.cardfactory.CardFactoryUtil; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; +import forge.game.ai.ComputerUtilCard; import forge.game.player.AIPlayer; import forge.game.player.Player; import forge.game.zone.ZoneType; @@ -109,9 +110,9 @@ public class DiscardEffect extends RevealEffectBase { if (sa.hasParam("DiscardValid")) { final String validString = sa.getParam("DiscardValid"); if (validString.contains("Creature") && !validString.contains("nonCreature")) { - final Card c = CardFactoryUtil.getBestCreatureAI(goodChoices); + final Card c = ComputerUtilCard.getBestCreatureAI(goodChoices); if (c != null) { - dChoices.add(CardFactoryUtil.getBestCreatureAI(goodChoices)); + dChoices.add(ComputerUtilCard.getBestCreatureAI(goodChoices)); } } } diff --git a/src/main/java/forge/card/ability/effects/EncodeEffect.java b/src/main/java/forge/card/ability/effects/EncodeEffect.java index 73203083412..f8f57be27fb 100644 --- a/src/main/java/forge/card/ability/effects/EncodeEffect.java +++ b/src/main/java/forge/card/ability/effects/EncodeEffect.java @@ -5,16 +5,12 @@ import java.util.List; import forge.Card; import forge.CardLists; import forge.Singletons; -import forge.CardPredicates.Presets; import forge.card.ability.SpellAbilityEffect; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.spellability.SpellAbility; import forge.card.trigger.Trigger; import forge.card.trigger.TriggerHandler; import forge.game.player.Player; import forge.game.zone.ZoneType; -import forge.gui.GuiChoose; -import forge.gui.GuiDialog; public class EncodeEffect extends SpellAbilityEffect { @Override @@ -43,10 +39,11 @@ public class EncodeEffect extends SpellAbilityEffect { } // Handle choice of whether or not to encoded + + final StringBuilder sb = new StringBuilder(); sb.append("Do you want to exile " + host + " and encode it onto a creature you control?"); - if (player.isHuman() - && !GuiDialog.confirm(host, sb.toString())) { + if (!player.getController().confirmAction(sa, null, sb.toString())) { return; } // Note: AI will always choose to encode @@ -56,31 +53,8 @@ public class EncodeEffect extends SpellAbilityEffect { Card movedCard = Singletons.getModel().getGame().getAction().moveTo(ZoneType.Exile, host); // choose a creature - Card choice = null; - if (player.isHuman()) { - final String choiceTitle = "Choose a creature you control to encode "; - choice = GuiChoose.oneOrNone(choiceTitle, choices); - } - else { // Computer - // TODO: move this to AI method - String logic = sa.getParam("AILogic"); - if (logic == null) { - // Base Logic is choose "best" - choice = CardFactoryUtil.getBestAI(choices); - } else if ("WorstCard".equals(logic)) { - choice = CardFactoryUtil.getWorstAI(choices); - } else if (logic.equals("BestBlocker")) { - if (!CardLists.filter(choices, Presets.UNTAPPED).isEmpty()) { - choices = CardLists.filter(choices, Presets.UNTAPPED); - } - choice = CardFactoryUtil.getBestCreatureAI(choices); - } else if (logic.equals("Clone")) { - if (!CardLists.getValidCards(choices, "Permanent.YouDontCtrl,Permanent.nonLegendary", host.getController(), host).isEmpty()) { - choices = CardLists.getValidCards(choices, "Permanent.YouDontCtrl,Permanent.nonLegendary", host.getController(), host); - } - choice = CardFactoryUtil.getBestAI(choices); - } - } + Card choice = player.getController().chooseSingleCardForEffect(choices, sa, "Choose a creature you control to encode ", true); + if (choice == null) { return; } diff --git a/src/main/java/forge/card/ability/effects/ManaEffect.java b/src/main/java/forge/card/ability/effects/ManaEffect.java index 81026b3124e..d75a2ccebfc 100644 --- a/src/main/java/forge/card/ability/effects/ManaEffect.java +++ b/src/main/java/forge/card/ability/effects/ManaEffect.java @@ -9,11 +9,11 @@ import forge.Singletons; import forge.card.MagicColor; import forge.card.ability.AbilityUtils; import forge.card.ability.SpellAbilityEffect; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.spellability.AbilityManaPart; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; import forge.game.GameActionUtil; +import forge.game.ai.ComputerUtilCard; import forge.game.player.Player; import forge.game.zone.ZoneType; import forge.gui.GuiChoose; @@ -82,7 +82,7 @@ public class ManaEffect extends SpellAbilityEffect { final String logic = sa.getParam("AILogic"); String chosen = Constant.Color.BLACK; if (logic.equals("MostProminentInComputerHand")) { - chosen = CardFactoryUtil.getMostProminentColor(activator.getCardsIn( + chosen = ComputerUtilCard.getMostProminentColor(activator.getCardsIn( ZoneType.Hand)); } if (chosen.equals("")) { @@ -141,7 +141,7 @@ public class ManaEffect extends SpellAbilityEffect { final String logic = sa.getParam("AILogic"); String chosen = Constant.Color.BLACK; if (logic.equals("MostProminentInComputerHand")) { - chosen = CardFactoryUtil.getMostProminentColor(act.getCardsIn(ZoneType.Hand)); + chosen = ComputerUtilCard.getMostProminentColor(act.getCardsIn(ZoneType.Hand)); } GuiChoose.one("Computer picked: ", new String[]{chosen}); abMana.setExpressChoice(MagicColor.toShortString(chosen)); diff --git a/src/main/java/forge/card/ability/effects/PlayEffect.java b/src/main/java/forge/card/ability/effects/PlayEffect.java index 44e03db2191..d9c5f8b3a7d 100644 --- a/src/main/java/forge/card/ability/effects/PlayEffect.java +++ b/src/main/java/forge/card/ability/effects/PlayEffect.java @@ -13,7 +13,6 @@ import forge.CardLists; import forge.Singletons; import forge.card.ability.AbilityUtils; import forge.card.ability.SpellAbilityEffect; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.cost.Cost; import forge.card.cost.CostPartMana; import forge.card.cost.CostPart; @@ -23,6 +22,7 @@ import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbilityRestriction; import forge.game.GameState; import forge.game.ai.ComputerUtil; +import forge.game.ai.ComputerUtilCard; import forge.game.player.AIPlayer; import forge.game.player.Player; import forge.game.zone.ZoneType; @@ -126,7 +126,7 @@ public class PlayEffect extends SpellAbilityEffect { return true; } }); - tgtCard = CardFactoryUtil.getBestAI(tgtCards); + tgtCard = ComputerUtilCard.getBestAI(tgtCards); if (tgtCard == null) { return; } diff --git a/src/main/java/forge/card/ability/effects/ProtectEffect.java b/src/main/java/forge/card/ability/effects/ProtectEffect.java index 2d511df754f..08737e0714f 100644 --- a/src/main/java/forge/card/ability/effects/ProtectEffect.java +++ b/src/main/java/forge/card/ability/effects/ProtectEffect.java @@ -13,9 +13,9 @@ import forge.Command; import forge.Singletons; import forge.card.ability.AbilityUtils; import forge.card.ability.SpellAbilityEffect; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; +import forge.game.ai.ComputerUtilCard; import forge.game.player.Player; import forge.gui.GuiChoose; @@ -124,7 +124,7 @@ public class ProtectEffect extends SpellAbilityEffect { list = CardLists.filterControlledBy(Singletons.getModel().getGame().getCardsInGame(), ai.getOpponents()); } if (!list.isEmpty()) { - choice = CardFactoryUtil.getMostProminentColor(list); + choice = ComputerUtilCard.getMostProminentColor(list); } } } diff --git a/src/main/java/forge/card/ability/effects/TwoPilesEffect.java b/src/main/java/forge/card/ability/effects/TwoPilesEffect.java index 80d33033e54..5c13c8b3d0c 100644 --- a/src/main/java/forge/card/ability/effects/TwoPilesEffect.java +++ b/src/main/java/forge/card/ability/effects/TwoPilesEffect.java @@ -9,10 +9,10 @@ import forge.CardLists; import forge.card.ability.AbilityFactory; import forge.card.ability.AbilityUtils; import forge.card.ability.SpellAbilityEffect; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.spellability.AbilitySub; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; +import forge.game.ai.ComputerUtilCard; import forge.game.player.Player; import forge.game.zone.ZoneType; import forge.gui.GuiChoose; @@ -221,11 +221,11 @@ public class TwoPilesEffect extends SpellAbilityEffect { break; } } else { - int cmc1 = CardFactoryUtil.evaluatePermanentList(new ArrayList(pile1)); - int cmc2 = CardFactoryUtil.evaluatePermanentList(new ArrayList(pile2)); + int cmc1 = ComputerUtilCard.evaluatePermanentList(new ArrayList(pile1)); + int cmc2 = ComputerUtilCard.evaluatePermanentList(new ArrayList(pile2)); if (CardLists.getNotType(pool, "Creature").isEmpty()) { - cmc1 = CardFactoryUtil.evaluateCreatureList(new ArrayList(pile1)); - cmc2 = CardFactoryUtil.evaluateCreatureList(new ArrayList(pile2)); + cmc1 = ComputerUtilCard.evaluateCreatureList(new ArrayList(pile1)); + cmc2 = ComputerUtilCard.evaluateCreatureList(new ArrayList(pile2)); System.out.println("value:" + cmc1 + " " + cmc2); } diff --git a/src/main/java/forge/card/ability/effects/UntapEffect.java b/src/main/java/forge/card/ability/effects/UntapEffect.java index ea90d524a74..a715fffef9e 100644 --- a/src/main/java/forge/card/ability/effects/UntapEffect.java +++ b/src/main/java/forge/card/ability/effects/UntapEffect.java @@ -12,6 +12,7 @@ import forge.card.ability.SpellAbilityEffect; import forge.card.cardfactory.CardFactoryUtil; import forge.card.spellability.SpellAbility; import forge.card.spellability.Target; +import forge.game.ai.ComputerUtilCard; import forge.game.player.Player; import forge.game.zone.ZoneType; @@ -86,7 +87,7 @@ public class UntapEffect extends SpellAbilityEffect { while ((list.size() != 0) && (count < num)) { for (int i = 0; (i < list.size()) && (count < num); i++) { - final Card c = CardFactoryUtil.getBestLandAI(list); + final Card c = ComputerUtilCard.getBestLandAI(list); c.untap(); list.remove(c); count++; diff --git a/src/main/java/forge/card/cardfactory/CardFactoryCreatures.java b/src/main/java/forge/card/cardfactory/CardFactoryCreatures.java index ae124bad3db..24b3c92438f 100644 --- a/src/main/java/forge/card/cardfactory/CardFactoryCreatures.java +++ b/src/main/java/forge/card/cardfactory/CardFactoryCreatures.java @@ -50,6 +50,7 @@ import forge.card.trigger.Trigger; import forge.card.trigger.TriggerHandler; import forge.control.input.Input; import forge.control.input.InputSelectManyCards; +import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilCombat; import forge.game.player.Player; import forge.game.zone.PlayerZone; @@ -190,7 +191,7 @@ public class CardFactoryCreatures { } this.getTarget().resetTargets(); - this.setTargetCard(CardFactoryUtil.getBestCreatureAI(targetables)); + this.setTargetCard(ComputerUtilCard.getBestCreatureAI(targetables)); return true; } @@ -262,7 +263,7 @@ public class CardFactoryCreatures { // Kill Wolves that can be killed first if (wolvesLeft.size() > 0) { - final Card best = CardFactoryUtil.getBestCreatureAI(wolvesLeft); + final Card best = ComputerUtilCard.getBestCreatureAI(wolvesLeft); best.addDamage(1, target); if ((ComputerUtilCombat.getDamageToKill(best) <= 0) || target.hasKeyword("Deathtouch")) { wolvesLeft.remove(best); diff --git a/src/main/java/forge/card/cardfactory/CardFactoryUtil.java b/src/main/java/forge/card/cardfactory/CardFactoryUtil.java index 5280c2b49d5..7108d26e104 100644 --- a/src/main/java/forge/card/cardfactory/CardFactoryUtil.java +++ b/src/main/java/forge/card/cardfactory/CardFactoryUtil.java @@ -18,17 +18,12 @@ package forge.card.cardfactory; import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Random; -import com.esotericsoftware.minlog.Log; import com.google.common.base.Predicate; -import com.google.common.base.Predicates; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; @@ -45,7 +40,6 @@ import forge.CounterType; import forge.GameEntity; import forge.Singletons; import forge.card.CardCharacteristics; -import forge.card.CardType; import forge.card.MagicColor; import forge.card.ability.AbilityFactory; import forge.card.ability.AbilityUtils; @@ -71,8 +65,8 @@ import forge.card.trigger.TriggerHandler; import forge.card.trigger.TriggerType; import forge.control.input.Input; import forge.game.GameState; -import forge.game.ai.AiAttackController; import forge.game.ai.ComputerUtil; +import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilCost; import forge.game.event.TokenCreatedEvent; import forge.game.phase.PhaseHandler; @@ -85,7 +79,6 @@ import forge.game.zone.ZoneType; import forge.gui.GuiChoose; import forge.gui.match.CMatchUI; import forge.util.Aggregates; -import forge.util.MyRandom; import forge.view.ButtonUtil; @@ -98,659 +91,6 @@ import forge.view.ButtonUtil; * @version $Id$ */ public class CardFactoryUtil { - private static Random random = MyRandom.getRandom(); - - /** - *

- * getMostExpensivePermanentAI. - *

- * - * @param list - * a {@link forge.CardList} object. - * @param spell - * a {@link forge.Card} object. - * @param targeted - * a boolean. - * @return a {@link forge.Card} object. - */ - public static Card getMostExpensivePermanentAI(final List list, final SpellAbility spell, final boolean targeted) { - List all = list; - if (targeted) { - all = CardLists.filter(all, new Predicate() { - @Override - public boolean apply(final Card c) { - return c.canBeTargetedBy(spell); - } - }); - } - - return CardFactoryUtil.getMostExpensivePermanentAI(all); - } - - /** - * getMostExpensivePermanentAI. - * - * @param all - * the all - * @return the card - */ - public static Card getMostExpensivePermanentAI(final List all) { - if (all.size() == 0) { - return null; - } - Card biggest = null; - biggest = all.get(0); - - int bigCMC = 0; - for (int i = 0; i < all.size(); i++) { - final Card card = all.get(i); - int curCMC = card.getCMC(); - - // Add all cost of all auras with the same controller - final List auras = CardLists.filterControlledBy(card.getEnchantedBy(), card.getController()); - curCMC += Aggregates.sum(auras, CardPredicates.Accessors.fnGetCmc) + auras.size(); - - if (curCMC >= bigCMC) { - bigCMC = curCMC; - biggest = all.get(i); - } - } - - return biggest; - } - - // for Sarkhan the Mad - /** - *

- * getCheapestCreatureAI. - *

- * - * @param list - * a {@link forge.CardList} object. - * @param spell - * a {@link forge.Card} object. - * @param targeted - * a boolean. - * @return a {@link forge.Card} object. - */ - public static Card getCheapestCreatureAI(List list, final SpellAbility spell, final boolean targeted) { - list = CardLists.filter(list, new Predicate() { - @Override - public boolean apply(final Card c) { - return c.isCreature(); - } - }); - return CardFactoryUtil.getCheapestPermanentAI(list, spell, targeted); - } - - /** - *

- * getCheapestPermanentAI. - *

- * - * @param list - * a {@link forge.CardList} object. - * @param spell - * a {@link forge.Card} object. - * @param targeted - * a boolean. - * @return a {@link forge.Card} object. - */ - public static Card getCheapestPermanentAI(final List list, final SpellAbility spell, final boolean targeted) { - List all = list; - if (targeted) { - all = CardLists.filter(all, new Predicate() { - @Override - public boolean apply(final Card c) { - return c.canBeTargetedBy(spell); - } - }); - } - if (all.size() == 0) { - return null; - } - - // get cheapest card: - Card cheapest = null; - cheapest = all.get(0); - - for (int i = 0; i < all.size(); i++) { - if (cheapest.getManaCost().getCMC() <= cheapest.getManaCost().getCMC()) { - cheapest = all.get(i); - } - } - - return cheapest; - - } - - /** - *

- * getBestLandAI. - *

- * - * @param list - * a {@link forge.CardList} object. - * @return a {@link forge.Card} object. - */ - public static Card getBestLandAI(final List list) { - final List land = CardLists.filter(list, CardPredicates.Presets.LANDS); - if (!(land.size() > 0)) { - return null; - } - - // prefer to target non basic lands - final List nbLand = CardLists.filter(land, Predicates.not(CardPredicates.Presets.BASIC_LANDS)); - - if (nbLand.size() > 0) { - // TODO - Rank non basics? - return Aggregates.random(nbLand); - } - - // if no non-basic lands, target the least represented basic land type - String sminBL = ""; - int iminBL = 20000; // hopefully no one will ever have more than 20000 - // lands of one type.... - int n = 0; - for (String name : Constant.Color.BASIC_LANDS) { - n = CardLists.getType(land, name).size(); - if ((n < iminBL) && (n > 0)) { - // if two or more are tied, only the - // first - // one checked will be used - iminBL = n; - sminBL = name; - } - } - if (iminBL == 20000) { - return null; // no basic land was a minimum - } - - final List bLand = CardLists.getType(land, sminBL); - - for (Card ut : Iterables.filter(bLand, CardPredicates.Presets.UNTAPPED)) { - return ut; - } - - - return Aggregates.random(bLand); // random tapped land of least represented type - } - - // The AI doesn't really pick the best enchantment, just the most expensive. - /** - *

- * getBestEnchantmentAI. - *

- * - * @param list - * a {@link forge.CardList} object. - * @param spell - * a {@link forge.Card} object. - * @param targeted - * a boolean. - * @return a {@link forge.Card} object. - */ - public static Card getBestEnchantmentAI(final List list, final SpellAbility spell, final boolean targeted) { - List all = CardLists.filter(list, CardPredicates.Presets.ENCHANTMENTS); - if (targeted) { - all = CardLists.filter(all, new Predicate() { - - @Override - public boolean apply(final Card c) { - return c.canBeTargetedBy(spell); - } - }); - } - - // get biggest Enchantment - return Aggregates.itemWithMax(all, CardPredicates.Accessors.fnGetCmc); - } - - // The AI doesn't really pick the best artifact, just the most expensive. - /** - *

- * getBestArtifactAI. - *

- * - * @param list - * a {@link forge.CardList} object. - * @return a {@link forge.Card} object. - */ - public static Card getBestArtifactAI(final List list) { - List all = CardLists.filter(list, CardPredicates.Presets.ARTIFACTS); - if (all.size() == 0) { - return null; - } - // get biggest Artifact - return Aggregates.itemWithMax(all, CardPredicates.Accessors.fnGetCmc); - } - - /** - *

- * doesCreatureAttackAI. - *

- * - * @param ai - * the AI player - * @param card - * a {@link forge.Card} object. - * @return a boolean. - */ - public static boolean doesCreatureAttackAI(final Player ai, final Card card) { - final List att = new AiAttackController(ai, ai.getOpponent()).getAttackers().getAttackers(); - - return att.contains(card); - } - - /** - *

- * evaluateCreatureList. - *

- * - * @param list - * a {@link forge.CardList} object. - * @return a int. - */ - public static int evaluateCreatureList(final List list) { - int value = 0; - for (int i = 0; i < list.size(); i++) { - value += CardFactoryUtil.evaluateCreature(list.get(i)); - } - - return value; - } - - /** - *

- * evaluatePermanentList. - *

- * - * @param list - * a {@link forge.CardList} object. - * @return a int. - */ - public static int evaluatePermanentList(final List list) { - int value = 0; - for (int i = 0; i < list.size(); i++) { - value += list.get(i).getCMC() + 1; - } - - return value; - } - - /** - *

- * evaluateCreature. - *

- * - * @param c - * a {@link forge.Card} object. - * @return a int. - */ - public static int evaluateCreature(final Card c) { - - int value = 100; - if (c.isToken()) { - value = 80; // tokens should be worth less than actual cards - } - int power = c.getNetCombatDamage(); - final int toughness = c.getNetDefense(); - for (String keyword : c.getKeyword()) { - if (keyword.equals("Prevent all combat damage that would be dealt by CARDNAME.") - || keyword.equals("Prevent all damage that would be dealt by CARDNAME.") - || keyword.equals("Prevent all combat damage that would be dealt to and dealt by CARDNAME.") - || keyword.equals("Prevent all damage that would be dealt to and dealt by CARDNAME.")) { - power = 0; - break; - } - } - value += power * 15; - value += toughness * 10; - value += c.getCMC() * 5; - - // Evasion keywords - if (c.hasKeyword("Flying")) { - value += power * 10; - } - if (c.hasKeyword("Horsemanship")) { - value += power * 10; - } - if (c.hasKeyword("Unblockable")) { - value += power * 10; - } else { - if (c.hasKeyword("You may have CARDNAME assign its combat damage as though it weren't blocked.")) { - value += power * 6; - } - if (c.hasKeyword("Fear")) { - value += power * 6; - } - if (c.hasKeyword("Intimidate")) { - value += power * 6; - } - if (c.hasStartOfKeyword("CARDNAME can't be blocked except by")) { - value += power * 5; - } - if (c.hasStartOfKeyword("CARDNAME can't be blocked by")) { - value += power * 2; - } - } - - // Other good keywords - if (power > 0) { - if (c.hasKeyword("Double Strike")) { - value += 10 + (power * 15); - } else if (c.hasKeyword("First Strike")) { - value += 10 + (power * 5); - } - if (c.hasKeyword("Deathtouch")) { - value += 25; - } - if (c.hasKeyword("Lifelink")) { - value += power * 10; - } - if (power > 1 && c.hasKeyword("Trample")) { - value += (power - 1) * 5; - } - if (c.hasKeyword("Vigilance")) { - value += (power * 5) + (toughness * 5); - } - if (c.hasKeyword("Wither")) { - value += power * 10; - } - if (c.hasKeyword("Infect")) { - value += power * 15; - } - value += c.getKeywordMagnitude("Rampage"); - if (c.hasKeyword("Whenever a creature dealt damage by CARDNAME this turn is " - + "put into a graveyard, put a +1/+1 counter on CARDNAME.")) { - value += 2; - } - if (c.hasKeyword("Whenever a creature dealt damage by CARDNAME this turn is " - + "put into a graveyard, put a +2/+2 counter on CARDNAME.")) { - value += 3; - } - } - - value += c.getKeywordMagnitude("Bushido") * 16; - value += c.getAmountOfKeyword("Flanking") * 15; - value += c.getAmountOfKeyword("Exalted") * 15; - value += c.getKeywordMagnitude("Annihilator") * 50; - - - // Defensive Keywords - if (c.hasKeyword("Reach") && !c.hasKeyword("Flying")) { - value += 5; - } - if (c.hasKeyword("CARDNAME can block creatures with shadow as though they didn't have shadow.")) { - value += 3; - } - - // Protection - if (c.hasKeyword("Indestructible")) { - value += 70; - } - if (c.hasKeyword("Prevent all damage that would be dealt to CARDNAME.")) { - value += 60; - } else if (c.hasKeyword("Prevent all combat damage that would be dealt to CARDNAME.")) { - value += 50; - } - if (c.hasKeyword("Hexproof")) { - value += 35; - } else if (c.hasKeyword("Shroud")) { - value += 30; - } - if (c.hasStartOfKeyword("Protection")) { - value += 20; - } - if (c.hasStartOfKeyword("PreventAllDamageBy")) { - value += 10; - } - value += c.getKeywordMagnitude("Absorb") * 11; - - // Bad keywords - if (c.hasKeyword("Defender") || c.hasKeyword("CARDNAME can't attack.")) { - value -= (power * 9) + 40; - } else if (c.getSVar("SacrificeEndCombat").equals("True")) { - value -= 40; - } - if (c.hasKeyword("CARDNAME can't block.")) { - value -= 10; - } else if (c.hasKeyword("CARDNAME attacks each turn if able.")) { - value -= 10; - } else if (c.hasKeyword("CARDNAME can block only creatures with flying.")) { - value -= toughness * 5; - } - - if (c.hasStartOfKeyword("When CARDNAME is dealt damage, destroy it.")) { - value -= (toughness - 1) * 9; - } - - if (c.hasKeyword("CARDNAME can't attack or block.")) { - value = 50 + (c.getCMC() * 5); // reset everything - useless - } - if (c.hasKeyword("CARDNAME doesn't untap during your untap step.")) { - if (c.isTapped()) { - value = 50 + (c.getCMC() * 5); // reset everything - useless - } else { - value -= 50; - } - } - if (c.hasKeyword("At the beginning of the end step, destroy CARDNAME.") - || c.hasKeyword("At the beginning of the end step, exile CARDNAME.") - || c.hasKeyword("At the beginning of the end step, sacrifice CARDNAME.")) { - value -= 50; - } else if (c.hasStartOfKeyword("Cumulative upkeep")) { - value -= 30; - } else if (c.hasStartOfKeyword("At the beginning of your upkeep, destroy CARDNAME unless you pay") - || c.hasStartOfKeyword("At the beginning of your upkeep, sacrifice CARDNAME unless you pay") - || c.hasStartOfKeyword("Upkeep:")) { - value -= 20; - } else if (c.hasStartOfKeyword("(Echo unpaid)")) { - value -= 10; - } - - if (c.hasStartOfKeyword("At the beginning of your upkeep, CARDNAME deals")) { - value -= 20; - } - if (c.hasStartOfKeyword("Fading")) { - value -= 20; - } - if (c.hasStartOfKeyword("Vanishing")) { - value -= 20; - } - if (c.getSVar("Targeting").equals("Dies")) { - value -= 25; - } - - for (final SpellAbility sa : c.getSpellAbilities()) { - if (sa.isAbility()) { - value += 10; - } - } - if (!c.getManaAbility().isEmpty()) { - value += 10; - } - - if (c.isUntapped()) { - value += 1; - } - - // paired creatures are more valuable because they grant a bonus to the other creature - if (c.isPaired()) { - value += 14; - } - - return value; - - } // evaluateCreature - - // returns null if list.size() == 0 - /** - *

- * getBestAI. - *

- * - * @param list - * a {@link forge.CardList} object. - * @return a {@link forge.Card} object. - */ - public static Card getBestAI(final List list) { - // Get Best will filter by appropriate getBest list if ALL of the list - // is of that type - if (CardLists.getNotType(list, "Creature").size() == 0) { - return CardFactoryUtil.getBestCreatureAI(list); - } - - if (CardLists.getNotType(list, "Land").size() == 0) { - return CardFactoryUtil.getBestLandAI(list); - } - - // TODO - Once we get an EvaluatePermanent this should call - // getBestPermanent() - return CardFactoryUtil.getMostExpensivePermanentAI(list); - } - - /** - * getBestCreatureAI. - * - * @param list - * the list - * @return the card - */ - public static Card getBestCreatureAI(final List list) { - List all = CardLists.filter(list, CardPredicates.Presets.CREATURES); - return Aggregates.itemWithMax(all, CardPredicates.Accessors.fnEvaluateCreature); - } - - // This selection rates tokens higher - /** - *

- * getBestCreatureToBounceAI. - *

- * - * @param list - * a {@link forge.CardList} object. - * @return a {@link forge.Card} object. - */ - public static Card getBestCreatureToBounceAI(final List list) { - final int tokenBonus = 40; - List all = CardLists.filter(list, CardPredicates.Presets.CREATURES); - Card biggest = null; // returns null if list.size() == 0 - int biggestvalue = 0; - int newvalue = 0; - - if (all.size() != 0) { - biggest = all.get(0); - - for (int i = 0; i < all.size(); i++) { - biggestvalue = CardFactoryUtil.evaluateCreature(biggest); - if (biggest.isToken()) { - biggestvalue += tokenBonus; // raise the value of tokens - } - newvalue = CardFactoryUtil.evaluateCreature(all.get(i)); - if (all.get(i).isToken()) { - newvalue += tokenBonus; // raise the value of tokens - } - if (biggestvalue < newvalue) { - biggest = all.get(i); - } - } - } - return biggest; - } - - /** - *

- * getWorstAI. - *

- * - * @param list - * a {@link forge.CardList} object. - * @return a {@link forge.Card} object. - */ - public static Card getWorstAI(final List list) { - return CardFactoryUtil.getWorstPermanentAI(list, false, false, false, false); - } - - // returns null if list.size() == 0 - /** - *

- * getWorstCreatureAI. - *

- * - * @param list - * a {@link forge.CardList} object. - * @return a {@link forge.Card} object. - */ - public static Card getWorstCreatureAI(final List list) { - List all = CardLists.filter(list, CardPredicates.Presets.CREATURES); - // get smallest creature - return Aggregates.itemWithMin(all, CardPredicates.Accessors.fnEvaluateCreature); - } - - /** - *

- * getWorstPermanentAI. - *

- * - * @param list - * a {@link forge.CardList} object. - * @param biasEnch - * a boolean. - * @param biasLand - * a boolean. - * @param biasArt - * a boolean. - * @param biasCreature - * a boolean. - * @return a {@link forge.Card} object. - */ - public static Card getWorstPermanentAI(final List list, final boolean biasEnch, final boolean biasLand, - final boolean biasArt, final boolean biasCreature) { - if (list.size() == 0) { - return null; - } - - if (biasEnch && Iterables.any(list, CardPredicates.Presets.ENCHANTMENTS)) { - return CardFactoryUtil.getCheapestPermanentAI(CardLists.filter(list, CardPredicates.Presets.ENCHANTMENTS), null, false); - } - - if (biasArt && Iterables.any(list, CardPredicates.Presets.ARTIFACTS)) { - return CardFactoryUtil.getCheapestPermanentAI(CardLists.filter(list, CardPredicates.Presets.ARTIFACTS), null, false); - } - - if (biasLand && Iterables.any(list, CardPredicates.Presets.LANDS)) { - return CardFactoryUtil.getWorstLand(CardLists.filter(list, CardPredicates.Presets.LANDS)); - } - - if (biasCreature && Iterables.any(list, CardPredicates.Presets.CREATURES)) { - return CardFactoryUtil.getWorstCreatureAI(CardLists.filter(list, CardPredicates.Presets.CREATURES)); - } - - List lands = CardLists.filter(list, CardPredicates.Presets.LANDS); - if (lands.size() > 6) { - return CardFactoryUtil.getWorstLand(lands); - } - - if ((CardLists.getType(list, "Artifact").size() > 0) || (CardLists.getType(list, "Enchantment").size() > 0)) { - return CardFactoryUtil.getCheapestPermanentAI(CardLists.filter(list, new Predicate() { - @Override - public boolean apply(final Card c) { - return c.isArtifact() || c.isEnchantment(); - } - }), null, false); - } - - if (CardLists.getType(list, "Creature").size() > 0) { - return CardFactoryUtil.getWorstCreatureAI(CardLists.getType(list, "Creature")); - } - - // Planeswalkers fall through to here, lands will fall through if there - // aren't very many - return CardFactoryUtil.getCheapestPermanentAI(list, null, false); - } - - /** *

* inputDestroyNoRegeneration. @@ -3027,91 +2367,6 @@ public class CardFactoryUtil { return untap; } - /** - *

- * getMostProminentCardName. - *

- * - * @param list - * a {@link forge.CardList} object. - * @return a {@link java.lang.String} object. - */ - public static String getMostProminentCardName(final List list) { - - if (list.size() == 0) { - return ""; - } - - final Map map = new HashMap(); - - for (final Card c : list) { - final String name = c.getName(); - Integer currentCnt = map.get(name); - map.put(name, currentCnt == null ? Integer.valueOf(1) : Integer.valueOf(1 + currentCnt)); - } // for - - int max = 0; - String maxName = ""; - - for (final Entry entry : map.entrySet()) { - final String type = entry.getKey(); - // Log.debug(type + " - " + entry.getValue()); - - if (max < entry.getValue()) { - max = entry.getValue(); - maxName = type; - } - } - return maxName; - } - - /** - *

- * getMostProminentCreatureType. - *

- * - * @param list - * a {@link forge.CardList} object. - * @return a {@link java.lang.String} object. - */ - public static String getMostProminentCreatureType(final List list) { - - if (list.size() == 0) { - return ""; - } - - final Map map = new HashMap(); - - for (final Card c : list) { - final ArrayList typeList = c.getType(); - - for (final String var : typeList) { - if (CardType.isACreatureType(var)) { - if (!map.containsKey(var)) { - map.put(var, 1); - } else { - map.put(var, map.get(var) + 1); - } - } - } - } // for - - int max = 0; - String maxType = ""; - - for (final Entry entry : map.entrySet()) { - final String type = entry.getKey(); - // Log.debug(type + " - " + entry.getValue()); - - if (max < entry.getValue()) { - max = entry.getValue(); - maxType = type; - } - } - - return maxType; - } - /** *

* isMostProminentColor. @@ -3153,96 +2408,6 @@ public class CardFactoryUtil { return true; } - /** - *

- * getMostProminentColor. - *

- * - * @param list - * a {@link forge.CardList} object. - * @return a {@link java.lang.String} object. - */ - public static String getMostProminentColor(final List list) { - - final Map map = new HashMap(); - - for (final Card c : list) { - for (final String color : CardUtil.getColors(c)) { - if (color.equals("colorless")) { - // nothing to do - } else if (!map.containsKey(color)) { - map.put(color, 1); - } else { - map.put(color, map.get(color) + 1); - } - } - } // for - - int max = 0; - String maxColor = ""; - - for (final Entry entry : map.entrySet()) { - final String color = entry.getKey(); - Log.debug(color + " - " + entry.getValue()); - - if (max < entry.getValue()) { - max = entry.getValue(); - maxColor = color; - } - } - - return maxColor; - } - - public static List getColorByProminence(final List list) { - final HashMap counts = new HashMap(); - for (String color : Constant.Color.ONLY_COLORS) { - counts.put(color, 0); - } - for (Card c : list) { - List colors = c.determineColor().toStringList(); - for (String col : colors) { - if (counts.containsKey(col)) { - counts.put(col.toString(), counts.get(col.toString()) + 1); - } - } - } - ArrayList res = new ArrayList(counts.keySet()); - Collections.sort(res, new Comparator() { - @Override - public int compare(final String a, final String b) { - return counts.get(b) - counts.get(a); - } - }); - - return res; - } - - /** - *

- * getUsableManaSources. - *

- * - * @param player - * a {@link forge.game.player.Player} object. - * @return a int. - */ - public static int getUsableManaSources(final Player player) { - List list = CardLists.filter(player.getCardsIn(ZoneType.Battlefield), new Predicate() { - @Override - public boolean apply(final Card c) { - for (final SpellAbility am : c.getAIPlayableMana()) { - if (am.canPlay()) { - return true; - } - } - return false; - } - }); - - return list.size(); - } - /** *

* makeToken. @@ -3423,66 +2588,6 @@ public class CardFactoryUtil { return neededDamage; } - /** - * getWorstLand - *

- * This function finds the worst land a player has in play based on: worst - * 1. tapped, basic land 2. tapped, non-basic land 3. untapped, basic land - * 4. untapped, non-basic land best - *

- * This is useful when the AI needs to find one of its lands to sacrifice - * - * @param player - * - AllZone.getHumanPlayer() or AllZone.getComputerPlayer() - * @return the worst land found based on the description above - */ - public static Card getWorstLand(final Player player) { - final List lands = player.getLandsInPlay(); - return CardFactoryUtil.getWorstLand(lands); - } // end getWorstLand - - /** - *

- * getWorstLand. - *

- * - * @param lands - * a {@link forge.CardList} object. - * @return a {@link forge.Card} object. - */ - public static Card getWorstLand(final List lands) { - Card worstLand = null; - int maxScore = 0; - // first, check for tapped, basic lands - for (Card tmp : lands) { - int score = tmp.isTapped() ? 2 : 0; - score += tmp.isBasicLand() ? 1 : 0; - if (score >= maxScore) { - worstLand = tmp; - maxScore = score; - } - } - return worstLand; - } // end getWorstLand - - // may return null - /** - *

- * getRandomCard. - *

- * - * @param list - * a {@link forge.CardList} object. - * @return a {@link forge.Card} object. - */ - public static Card getRandomCard(final List list) { - if (list.size() == 0) { - return null; - } - - final int index = CardFactoryUtil.random.nextInt(list.size()); - return list.get(index); - } /** *

@@ -4068,10 +3173,10 @@ public class CardFactoryUtil { } else { // AI choosing what to haunt final List oppCreats = CardLists.filterControlledBy(creats, card.getController().getOpponent()); - if (oppCreats.size() != 0) { - haunterDiesWork.setTargetCard(CardFactoryUtil.getWorstCreatureAI(oppCreats)); + if (!oppCreats.isEmpty()) { + haunterDiesWork.setTargetCard(ComputerUtilCard.getWorstCreatureAI(oppCreats)); } else { - haunterDiesWork.setTargetCard(CardFactoryUtil.getWorstCreatureAI(creats)); + haunterDiesWork.setTargetCard(ComputerUtilCard.getWorstCreatureAI(creats)); } Singletons.getModel().getGame().getStack().add(haunterDiesWork); } @@ -4759,7 +3864,7 @@ public class CardFactoryUtil { } }); if (choices.size() != 0) { - ability.setTargetCard(CardFactoryUtil.getBestCreatureAI(choices)); + ability.setTargetCard(ComputerUtilCard.getBestCreatureAI(choices)); if (ability.getTargetCard() != null) { ability.setStackDescription("Put " + card.getCounters(CounterType.P1P1) diff --git a/src/main/java/forge/card/cost/CostPutCounter.java b/src/main/java/forge/card/cost/CostPutCounter.java index cc67f55893e..5659db410c9 100644 --- a/src/main/java/forge/card/cost/CostPutCounter.java +++ b/src/main/java/forge/card/cost/CostPutCounter.java @@ -25,10 +25,10 @@ import forge.CardLists; import forge.CounterType; import forge.Singletons; import forge.card.ability.AbilityUtils; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.spellability.SpellAbility; import forge.control.input.Input; import forge.game.GameState; +import forge.game.ai.ComputerUtilCard; import forge.game.player.AIPlayer; import forge.game.player.Player; import forge.game.zone.ZoneType; @@ -223,9 +223,9 @@ public class CostPutCounter extends CostPartWithList { Card card = null; if (this.getType().equals("Creature.YouCtrl")) { - card = CardFactoryUtil.getWorstCreatureAI(typeList); + card = ComputerUtilCard.getWorstCreatureAI(typeList); } else { - card = CardFactoryUtil.getWorstPermanentAI(typeList, false, false, false, false); + card = ComputerUtilCard.getWorstPermanentAI(typeList, false, false, false, false); } this.addToList(card); } diff --git a/src/main/java/forge/game/GameActionPlay.java b/src/main/java/forge/game/GameActionPlay.java index 9e4cc5c75bd..ade428ec569 100644 --- a/src/main/java/forge/game/GameActionPlay.java +++ b/src/main/java/forge/game/GameActionPlay.java @@ -6,14 +6,13 @@ import java.util.List; import com.google.common.collect.Lists; import forge.Card; +import forge.CardColor; import forge.CardLists; import forge.CardPredicates; -import forge.CardUtil; import forge.card.MagicColor; import forge.card.ability.AbilityUtils; import forge.card.ability.ApiType; import forge.card.ability.effects.CharmEffect; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.cost.Cost; import forge.card.cost.CostPayment; import forge.card.mana.ManaCostBeingPaid; @@ -26,6 +25,7 @@ import forge.card.spellability.TargetSelection; import forge.card.staticability.StaticAbility; import forge.control.input.InputControl; import forge.control.input.InputPayManaSimple; +import forge.game.ai.ComputerUtilCard; import forge.game.player.Player; import forge.game.zone.ZoneType; import forge.gui.GuiChoose; @@ -196,7 +196,7 @@ public class GameActionPlay { } while (tapForConvoke != null && untappedCreats.size() != 0) { final Card workingCard = (Card) tapForConvoke; - usableColors = CardUtil.getConvokableColors(workingCard, newCost); + usableColors = GameActionPlay.getConvokableColors(workingCard, newCost); if (usableColors.size() != 0) { String chosenColor = usableColors.get(0); @@ -317,7 +317,7 @@ public class GameActionPlay { } } if (chosen == null) { - chosen = CardFactoryUtil.getWorstCreatureAI(grave); + chosen = ComputerUtilCard.getWorstCreatureAI(grave); } if (chosen == null) { @@ -503,4 +503,33 @@ public class GameActionPlay { final String costCuttingGetMultiKickerManaCostPaidColored0) { this.costCuttingGetMultiKickerManaCostPaidColored = costCuttingGetMultiKickerManaCostPaidColored0; } + + /** + * 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/AiAttackController.java b/src/main/java/forge/game/ai/AiAttackController.java index afb6dadc113..95ef4bc58c7 100644 --- a/src/main/java/forge/game/ai/AiAttackController.java +++ b/src/main/java/forge/game/ai/AiAttackController.java @@ -29,7 +29,6 @@ import forge.CardLists; import forge.CounterType; import forge.GameEntity; import forge.Singletons; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.trigger.Trigger; import forge.card.trigger.TriggerType; import forge.game.GameState; @@ -909,7 +908,7 @@ public class AiAttackController { // see if the defending creature is of higher or lower // value. We don't want to attack only to lose value if (isWorthLessThanAllKillers && attacker.getSVar("SacMe").equals("") - && CardFactoryUtil.evaluateCreature(defender) <= CardFactoryUtil.evaluateCreature(attacker)) { + && ComputerUtilCard.evaluateCreature(defender) <= ComputerUtilCard.evaluateCreature(attacker)) { isWorthLessThanAllKillers = false; } } diff --git a/src/main/java/forge/game/ai/AiController.java b/src/main/java/forge/game/ai/AiController.java index df943f0a37e..2b4b528a921 100644 --- a/src/main/java/forge/game/ai/AiController.java +++ b/src/main/java/forge/game/ai/AiController.java @@ -596,7 +596,7 @@ public class AiController { discardList.add(hand.get(0)); hand.remove(hand.get(0)); } else { //Discard worst card - Card worst = CardFactoryUtil.getWorstAI(hand); + Card worst = ComputerUtilCard.getWorstAI(hand); discardList.add(worst); hand.remove(worst); } @@ -606,14 +606,64 @@ public class AiController { return discardList; } + // These methods might be moved into matching SpellAbilityAi classes just without all these switches here public Card chooseSingleCardForEffect(List options, SpellAbility sa, String title, boolean isOptional) { ApiType api = sa.getApi(); if ( null == api ) { throw new InvalidParameterException("SA is not api-based, this is not supported yet"); } - + + Card choice = null; + Card host = sa.getSourceCard(); + String logic = sa.getParam("AILogic"); + switch(api) { - case Bond: return CardFactoryUtil.getBestCreatureAI(options); + case Bond: + return ComputerUtilCard.getBestCreatureAI(options); + + case ChooseCard: + if (logic == null) { + // Base Logic is choose "best" + choice = ComputerUtilCard.getBestAI(options); + } else if ("WorstCard".equals(logic)) { + choice = ComputerUtilCard.getWorstAI(options); + } else if (logic.equals("BestBlocker")) { + if (!CardLists.filter(options, Presets.UNTAPPED).isEmpty()) { + options = CardLists.filter(options, Presets.UNTAPPED); + } + choice = ComputerUtilCard.getBestCreatureAI(options); + } else if (logic.equals("Clone")) { + if (!CardLists.getValidCards(options, "Permanent.YouDontCtrl,Permanent.nonLegendary", host.getController(), host).isEmpty()) { + options = CardLists.getValidCards(options, "Permanent.YouDontCtrl,Permanent.nonLegendary", host.getController(), host); + } + choice = ComputerUtilCard.getBestAI(options); + } else if (logic.equals("Untap")) { + if (!CardLists.getValidCards(options, "Permanent.YouCtrl,Permanent.tapped", host.getController(), host).isEmpty()) { + options = CardLists.getValidCards(options, "Permanent.YouCtrl,Permanent.tapped", host.getController(), host); + } + choice = ComputerUtilCard.getBestAI(options); + } + return choice; + + case Encode: + if (logic == null) { + // Base Logic is choose "best" + choice = ComputerUtilCard.getBestAI(options); + } else if ("WorstCard".equals(logic)) { + choice = ComputerUtilCard.getWorstAI(options); + } else if (logic.equals("BestBlocker")) { + if (!CardLists.filter(options, Presets.UNTAPPED).isEmpty()) { + options = CardLists.filter(options, Presets.UNTAPPED); + } + choice = ComputerUtilCard.getBestCreatureAI(options); + } else if (logic.equals("Clone")) { + if (!CardLists.getValidCards(options, "Permanent.YouDontCtrl,Permanent.nonLegendary", host.getController(), host).isEmpty()) { + options = CardLists.getValidCards(options, "Permanent.YouDontCtrl,Permanent.nonLegendary", host.getController(), host); + } + choice = ComputerUtilCard.getBestAI(options); + } + return choice; + default: throw new InvalidParameterException("AI chooseSingleCard does not know how to choose card for " + api); } } @@ -627,11 +677,14 @@ public class AiController { switch(api) { case Discard: - if ( mode.equals("Random") ) { // + if ( mode.startsWith("Random") ) { // // TODO For now AI will always discard Random used currently with: Balduvian Horde and similar cards return true; } break; + + case Encode: + return true; default: } diff --git a/src/main/java/forge/game/ai/ComputerUtil.java b/src/main/java/forge/game/ai/ComputerUtil.java index 59328384aef..b593fd16ab9 100644 --- a/src/main/java/forge/game/ai/ComputerUtil.java +++ b/src/main/java/forge/game/ai/ComputerUtil.java @@ -172,7 +172,7 @@ public class ComputerUtil { if (unless != null && !unless.endsWith(">")) { final int amount = AbilityUtils.calculateAmount(source, unless, sa); - final int usableManaSources = CardFactoryUtil.getUsableManaSources(ai.getOpponent()); + final int usableManaSources = ComputerUtilCard.getUsableManaSources(ai.getOpponent()); // If the Unless isn't enough, this should be less likely to be used if (amount > usableManaSources) { @@ -384,7 +384,7 @@ public class ComputerUtil { if (landsInPlay.size() >= highestCMC || (landsInPlay.size() + landsInHand.size() > 6 && landsInHand.size() > 1)) { // Don't need more land. - return CardFactoryUtil.getWorstLand(landsInHand); + return ComputerUtilCard.getWorstLand(landsInHand); } } } @@ -678,11 +678,11 @@ public class ComputerUtil { Card c; if (CardLists.getNotType(remaining, "Creature").size() == 0) { - c = CardFactoryUtil.getWorstCreatureAI(remaining); + c = ComputerUtilCard.getWorstCreatureAI(remaining); } else if (CardLists.getNotType(remaining, "Land").size() == 0) { - c = CardFactoryUtil.getWorstLand(CardLists.filter(remaining, CardPredicates.Presets.LANDS)); + c = ComputerUtilCard.getWorstLand(CardLists.filter(remaining, CardPredicates.Presets.LANDS)); } else { - c = CardFactoryUtil.getWorstPermanentAI(remaining, false, false, false, false); + c = ComputerUtilCard.getWorstPermanentAI(remaining, false, false, false, false); } final ArrayList auras = c.getEnchantedBy(); diff --git a/src/main/java/forge/game/ai/ComputerUtilBlock.java b/src/main/java/forge/game/ai/ComputerUtilBlock.java index 576fd517e9b..de107e9b043 100644 --- a/src/main/java/forge/game/ai/ComputerUtilBlock.java +++ b/src/main/java/forge/game/ai/ComputerUtilBlock.java @@ -29,7 +29,6 @@ import forge.CardLists; import forge.CardPredicates; import forge.CounterType; import forge.GameEntity; -import forge.card.cardfactory.CardFactoryUtil; import forge.game.phase.Combat; import forge.game.phase.CombatUtil; import forge.game.player.Player; @@ -360,9 +359,9 @@ public class ComputerUtilBlock { // destroyed killingBlockers = ComputerUtilBlock.getKillingBlockers(ai, attacker, safeBlockers, combat); if (killingBlockers.size() > 0) { - blocker = CardFactoryUtil.getWorstCreatureAI(killingBlockers); + blocker = ComputerUtilCard.getWorstCreatureAI(killingBlockers); } else if (!attacker.hasKeyword("You may have CARDNAME assign its combat damage as though it weren't blocked.")) { - blocker = CardFactoryUtil.getWorstCreatureAI(safeBlockers); + blocker = ComputerUtilCard.getWorstCreatureAI(safeBlockers); ComputerUtilBlock.getBlockedButUnkilled().add(attacker); } } // no safe blockers @@ -378,9 +377,9 @@ public class ComputerUtilBlock { } // 4.Blockers that can destroy the attacker and are worth less if (blocker == null && killingBlockers.size() > 0) { - final Card worst = CardFactoryUtil.getWorstCreatureAI(killingBlockers); + final Card worst = ComputerUtilCard.getWorstCreatureAI(killingBlockers); - if ((CardFactoryUtil.evaluateCreature(worst) + ComputerUtilBlock.getDiff()) < CardFactoryUtil + if ((ComputerUtilCard.evaluateCreature(worst) + ComputerUtilBlock.getDiff()) < ComputerUtilCard .evaluateCreature(attacker)) { blocker = worst; } @@ -471,7 +470,7 @@ public class ComputerUtilBlock { && !(c.hasKeyword("First Strike") || c.hasKeyword("Double Strike"))) { return false; } - return lifeInDanger || (CardFactoryUtil.evaluateCreature(c) + ComputerUtilBlock.getDiff()) < CardFactoryUtil + return lifeInDanger || (ComputerUtilCard.evaluateCreature(c) + ComputerUtilBlock.getDiff()) < ComputerUtilCard .evaluateCreature(attacker); } }); @@ -479,11 +478,11 @@ public class ComputerUtilBlock { return combat; } - final Card leader = CardFactoryUtil.getBestCreatureAI(usableBlockers); + final Card leader = ComputerUtilCard.getBestCreatureAI(usableBlockers); blockGang.add(leader); usableBlockers.remove(leader); absorbedDamage = ComputerUtilCombat.getEnoughDamageToKill(leader, attacker.getNetCombatDamage(), attacker, true); - currentValue = CardFactoryUtil.evaluateCreature(leader); + currentValue = ComputerUtilCard.evaluateCreature(leader); for (final Card blocker : usableBlockers) { // Add an additional blocker if the current blockers are not @@ -491,7 +490,7 @@ public class ComputerUtilBlock { final int currentDamage = ComputerUtilCombat.totalDamageOfBlockers(attacker, blockGang); final int additionalDamage = ComputerUtilCombat.dealsDamageAsBlocker(attacker, blocker); final int absorbedDamage2 = ComputerUtilCombat.getEnoughDamageToKill(blocker, attacker.getNetCombatDamage(), attacker, true); - final int addedValue = CardFactoryUtil.evaluateCreature(blocker); + final int addedValue = ComputerUtilCard.evaluateCreature(blocker); final int damageNeeded = ComputerUtilCombat.getDamageToKill(attacker) + ComputerUtilCombat.predictToughnessBonusOfAttacker(attacker, blocker, combat, false); if ((damageNeeded > currentDamage || CombatUtil.needsBlockers(attacker) > blockGang.size()) @@ -499,7 +498,7 @@ public class ComputerUtilBlock { // The attacker will be killed && (absorbedDamage2 + absorbedDamage > attacker.getNetCombatDamage() // only one blocker can be killed - || currentValue + addedValue - 50 <= CardFactoryUtil.evaluateCreature(attacker) + || currentValue + addedValue - 50 <= ComputerUtilCard.evaluateCreature(attacker) // or attacker is worth more || (lifeInDanger && ComputerUtilCombat.lifeInDanger(ai, combat))) // or life is in danger @@ -545,7 +544,7 @@ public class ComputerUtilBlock { ComputerUtilBlock.getPossibleBlockers(attacker, ComputerUtilBlock.getBlockersLeft(), combat, true), combat); if ((killingBlockers.size() > 0) && ComputerUtilCombat.lifeInDanger(ai, combat)) { - final Card blocker = CardFactoryUtil.getWorstCreatureAI(killingBlockers); + final Card blocker = ComputerUtilCard.getWorstCreatureAI(killingBlockers); combat.addBlocker(attacker, blocker); currentAttackers.remove(attacker); } @@ -579,7 +578,7 @@ public class ComputerUtilBlock { chumpBlockers = ComputerUtilBlock .getPossibleBlockers(attacker, ComputerUtilBlock.getBlockersLeft(), combat, true); if ((chumpBlockers.size() > 0) && ComputerUtilCombat.lifeInDanger(ai, combat)) { - final Card blocker = CardFactoryUtil.getWorstCreatureAI(chumpBlockers); + final Card blocker = ComputerUtilCard.getWorstCreatureAI(chumpBlockers); combat.addBlocker(attacker, blocker); currentAttackers.remove(attacker); ComputerUtilBlock.getBlockedButUnkilled().add(attacker); @@ -697,7 +696,7 @@ public class ComputerUtilBlock { final int additionalDamage = ComputerUtilCombat.dealsDamageAsBlocker(attacker, blocker); if ((damageNeeded > currentDamage) && !(damageNeeded > (currentDamage + additionalDamage)) - && ((CardFactoryUtil.evaluateCreature(blocker) + ComputerUtilBlock.getDiff()) < CardFactoryUtil + && ((ComputerUtilCard.evaluateCreature(blocker) + ComputerUtilBlock.getDiff()) < ComputerUtilCard .evaluateCreature(attacker)) && CombatUtil.canBlock(attacker, blocker, combat)) { combat.addBlocker(attacker, blocker); ComputerUtilBlock.getBlockersLeft().remove(blocker); diff --git a/src/main/java/forge/game/ai/ComputerUtilCard.java b/src/main/java/forge/game/ai/ComputerUtilCard.java new file mode 100644 index 00000000000..ad45c964952 --- /dev/null +++ b/src/main/java/forge/game/ai/ComputerUtilCard.java @@ -0,0 +1,917 @@ +package forge.game.ai; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Random; + +import com.esotericsoftware.minlog.Log; +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.collect.Iterables; + +import forge.Card; +import forge.CardLists; +import forge.CardPredicates; +import forge.CardUtil; +import forge.Constant; +import forge.card.CardType; +import forge.card.spellability.SpellAbility; +import forge.game.player.Player; +import forge.game.zone.ZoneType; +import forge.util.Aggregates; +import forge.util.MyRandom; + +/** + * TODO: Write javadoc for this type. + * + */ +public class ComputerUtilCard { + + /** + *

+ * getMostExpensivePermanentAI. + *

+ * + * @param list + * a {@link forge.CardList} object. + * @param spell + * a {@link forge.Card} object. + * @param targeted + * a boolean. + * @return a {@link forge.Card} object. + */ + public static Card getMostExpensivePermanentAI(final List list, final SpellAbility spell, final boolean targeted) { + List all = list; + if (targeted) { + all = CardLists.filter(all, new Predicate() { + @Override + public boolean apply(final Card c) { + return c.canBeTargetedBy(spell); + } + }); + } + + return ComputerUtilCard.getMostExpensivePermanentAI(all); + } + + // The AI doesn't really pick the best artifact, just the most expensive. + /** + *

+ * getBestArtifactAI. + *

+ * + * @param list + * a {@link forge.CardList} object. + * @return a {@link forge.Card} object. + */ + public static Card getBestArtifactAI(final List list) { + List all = CardLists.filter(list, CardPredicates.Presets.ARTIFACTS); + if (all.size() == 0) { + return null; + } + // get biggest Artifact + return Aggregates.itemWithMax(all, CardPredicates.Accessors.fnGetCmc); + } + + // The AI doesn't really pick the best enchantment, just the most expensive. + /** + *

+ * getBestEnchantmentAI. + *

+ * + * @param list + * a {@link forge.CardList} object. + * @param spell + * a {@link forge.Card} object. + * @param targeted + * a boolean. + * @return a {@link forge.Card} object. + */ + public static Card getBestEnchantmentAI(final List list, final SpellAbility spell, final boolean targeted) { + List all = CardLists.filter(list, CardPredicates.Presets.ENCHANTMENTS); + if (targeted) { + all = CardLists.filter(all, new Predicate() { + + @Override + public boolean apply(final Card c) { + return c.canBeTargetedBy(spell); + } + }); + } + + // get biggest Enchantment + return Aggregates.itemWithMax(all, CardPredicates.Accessors.fnGetCmc); + } + + /** + *

+ * getBestLandAI. + *

+ * + * @param list + * a {@link forge.CardList} object. + * @return a {@link forge.Card} object. + */ + public static Card getBestLandAI(final List list) { + final List land = CardLists.filter(list, CardPredicates.Presets.LANDS); + if (!(land.size() > 0)) { + return null; + } + + // prefer to target non basic lands + final List nbLand = CardLists.filter(land, Predicates.not(CardPredicates.Presets.BASIC_LANDS)); + + if (nbLand.size() > 0) { + // TODO - Rank non basics? + return Aggregates.random(nbLand); + } + + // if no non-basic lands, target the least represented basic land type + String sminBL = ""; + int iminBL = 20000; // hopefully no one will ever have more than 20000 + // lands of one type.... + int n = 0; + for (String name : Constant.Color.BASIC_LANDS) { + n = CardLists.getType(land, name).size(); + if ((n < iminBL) && (n > 0)) { + // if two or more are tied, only the + // first + // one checked will be used + iminBL = n; + sminBL = name; + } + } + if (iminBL == 20000) { + return null; // no basic land was a minimum + } + + final List bLand = CardLists.getType(land, sminBL); + + for (Card ut : Iterables.filter(bLand, CardPredicates.Presets.UNTAPPED)) { + return ut; + } + + + return Aggregates.random(bLand); // random tapped land of least represented type + } + + /** + *

+ * getCheapestPermanentAI. + *

+ * + * @param list + * a {@link forge.CardList} object. + * @param spell + * a {@link forge.Card} object. + * @param targeted + * a boolean. + * @return a {@link forge.Card} object. + */ + public static Card getCheapestPermanentAI(final List list, final SpellAbility spell, final boolean targeted) { + List all = list; + if (targeted) { + all = CardLists.filter(all, new Predicate() { + @Override + public boolean apply(final Card c) { + return c.canBeTargetedBy(spell); + } + }); + } + if (all.size() == 0) { + return null; + } + + // get cheapest card: + Card cheapest = null; + cheapest = all.get(0); + + for (int i = 0; i < all.size(); i++) { + if (cheapest.getManaCost().getCMC() <= cheapest.getManaCost().getCMC()) { + cheapest = all.get(i); + } + } + + return cheapest; + + } + + // for Sarkhan the Mad + /** + *

+ * getCheapestCreatureAI. + *

+ * + * @param list + * a {@link forge.CardList} object. + * @param spell + * a {@link forge.Card} object. + * @param targeted + * a boolean. + * @return a {@link forge.Card} object. + */ + public static Card getCheapestCreatureAI(List list, final SpellAbility spell, final boolean targeted) { + list = CardLists.filter(list, new Predicate() { + @Override + public boolean apply(final Card c) { + return c.isCreature(); + } + }); + return getCheapestPermanentAI(list, spell, targeted); + } + + // returns null if list.size() == 0 + /** + *

+ * getBestAI. + *

+ * + * @param list + * a {@link forge.CardList} object. + * @return a {@link forge.Card} object. + */ + public static Card getBestAI(final List list) { + // Get Best will filter by appropriate getBest list if ALL of the list + // is of that type + if (CardLists.getNotType(list, "Creature").size() == 0) { + return ComputerUtilCard.getBestCreatureAI(list); + } + + if (CardLists.getNotType(list, "Land").size() == 0) { + return getBestLandAI(list); + } + + // TODO - Once we get an EvaluatePermanent this should call + // getBestPermanent() + return ComputerUtilCard.getMostExpensivePermanentAI(list); + } + + /** + * getBestCreatureAI. + * + * @param list + * the list + * @return the card + */ + public static Card getBestCreatureAI(final List list) { + List all = CardLists.filter(list, CardPredicates.Presets.CREATURES); + return Aggregates.itemWithMax(all, ComputerUtilCard.fnEvaluateCreature); + } + + // This selection rates tokens higher + /** + *

+ * getBestCreatureToBounceAI. + *

+ * + * @param list + * a {@link forge.CardList} object. + * @return a {@link forge.Card} object. + */ + public static Card getBestCreatureToBounceAI(final List list) { + final int tokenBonus = 40; + List all = CardLists.filter(list, CardPredicates.Presets.CREATURES); + Card biggest = null; // returns null if list.size() == 0 + int biggestvalue = 0; + int newvalue = 0; + + if (all.size() != 0) { + biggest = all.get(0); + + for (int i = 0; i < all.size(); i++) { + biggestvalue = ComputerUtilCard.evaluateCreature(biggest); + if (biggest.isToken()) { + biggestvalue += tokenBonus; // raise the value of tokens + } + newvalue = ComputerUtilCard.evaluateCreature(all.get(i)); + if (all.get(i).isToken()) { + newvalue += tokenBonus; // raise the value of tokens + } + if (biggestvalue < newvalue) { + biggest = all.get(i); + } + } + } + return biggest; + } + + /** + *

+ * getWorstAI. + *

+ * + * @param list + * a {@link forge.CardList} object. + * @return a {@link forge.Card} object. + */ + public static Card getWorstAI(final List list) { + return ComputerUtilCard.getWorstPermanentAI(list, false, false, false, false); + } + + // returns null if list.size() == 0 + /** + *

+ * getWorstCreatureAI. + *

+ * + * @param list + * a {@link forge.CardList} object. + * @return a {@link forge.Card} object. + */ + public static Card getWorstCreatureAI(final List list) { + List all = CardLists.filter(list, CardPredicates.Presets.CREATURES); + // get smallest creature + return Aggregates.itemWithMin(all, ComputerUtilCard.fnEvaluateCreature); + } + + /** + *

+ * getWorstPermanentAI. + *

+ * + * @param list + * a {@link forge.CardList} object. + * @param biasEnch + * a boolean. + * @param biasLand + * a boolean. + * @param biasArt + * a boolean. + * @param biasCreature + * a boolean. + * @return a {@link forge.Card} object. + */ + public static Card getWorstPermanentAI(final List list, final boolean biasEnch, final boolean biasLand, + final boolean biasArt, final boolean biasCreature) { + if (list.size() == 0) { + return null; + } + + if (biasEnch && Iterables.any(list, CardPredicates.Presets.ENCHANTMENTS)) { + return getCheapestPermanentAI(CardLists.filter(list, CardPredicates.Presets.ENCHANTMENTS), null, false); + } + + if (biasArt && Iterables.any(list, CardPredicates.Presets.ARTIFACTS)) { + return getCheapestPermanentAI(CardLists.filter(list, CardPredicates.Presets.ARTIFACTS), null, false); + } + + if (biasLand && Iterables.any(list, CardPredicates.Presets.LANDS)) { + return ComputerUtilCard.getWorstLand(CardLists.filter(list, CardPredicates.Presets.LANDS)); + } + + if (biasCreature && Iterables.any(list, CardPredicates.Presets.CREATURES)) { + return getWorstCreatureAI(CardLists.filter(list, CardPredicates.Presets.CREATURES)); + } + + List lands = CardLists.filter(list, CardPredicates.Presets.LANDS); + if (lands.size() > 6) { + return ComputerUtilCard.getWorstLand(lands); + } + + if ((CardLists.getType(list, "Artifact").size() > 0) || (CardLists.getType(list, "Enchantment").size() > 0)) { + return getCheapestPermanentAI(CardLists.filter(list, new Predicate() { + @Override + public boolean apply(final Card c) { + return c.isArtifact() || c.isEnchantment(); + } + }), null, false); + } + + if (CardLists.getType(list, "Creature").size() > 0) { + return getWorstCreatureAI(CardLists.getType(list, "Creature")); + } + + // Planeswalkers fall through to here, lands will fall through if there + // aren't very many + return getCheapestPermanentAI(list, null, false); + } + + public static final Function fnEvaluateCreature = new Function() { + @Override + public Integer apply(Card a) { + return ComputerUtilCard.evaluateCreature(a); + } + }; + public static final Comparator EvaluateCreatureComparator = new Comparator() { + @Override + public int compare(final Card a, final Card b) { + return ComputerUtilCard.evaluateCreature(b) - ComputerUtilCard.evaluateCreature(a); + } + }; + /** + *

+ * evaluateCreature. + *

+ * + * @param c + * a {@link forge.Card} object. + * @return a int. + */ + public static int evaluateCreature(final Card c) { + + int value = 100; + if (c.isToken()) { + value = 80; // tokens should be worth less than actual cards + } + int power = c.getNetCombatDamage(); + final int toughness = c.getNetDefense(); + for (String keyword : c.getKeyword()) { + if (keyword.equals("Prevent all combat damage that would be dealt by CARDNAME.") + || keyword.equals("Prevent all damage that would be dealt by CARDNAME.") + || keyword.equals("Prevent all combat damage that would be dealt to and dealt by CARDNAME.") + || keyword.equals("Prevent all damage that would be dealt to and dealt by CARDNAME.")) { + power = 0; + break; + } + } + value += power * 15; + value += toughness * 10; + value += c.getCMC() * 5; + + // Evasion keywords + if (c.hasKeyword("Flying")) { + value += power * 10; + } + if (c.hasKeyword("Horsemanship")) { + value += power * 10; + } + if (c.hasKeyword("Unblockable")) { + value += power * 10; + } else { + if (c.hasKeyword("You may have CARDNAME assign its combat damage as though it weren't blocked.")) { + value += power * 6; + } + if (c.hasKeyword("Fear")) { + value += power * 6; + } + if (c.hasKeyword("Intimidate")) { + value += power * 6; + } + if (c.hasStartOfKeyword("CARDNAME can't be blocked except by")) { + value += power * 5; + } + if (c.hasStartOfKeyword("CARDNAME can't be blocked by")) { + value += power * 2; + } + } + + // Other good keywords + if (power > 0) { + if (c.hasKeyword("Double Strike")) { + value += 10 + (power * 15); + } else if (c.hasKeyword("First Strike")) { + value += 10 + (power * 5); + } + if (c.hasKeyword("Deathtouch")) { + value += 25; + } + if (c.hasKeyword("Lifelink")) { + value += power * 10; + } + if (power > 1 && c.hasKeyword("Trample")) { + value += (power - 1) * 5; + } + if (c.hasKeyword("Vigilance")) { + value += (power * 5) + (toughness * 5); + } + if (c.hasKeyword("Wither")) { + value += power * 10; + } + if (c.hasKeyword("Infect")) { + value += power * 15; + } + value += c.getKeywordMagnitude("Rampage"); + if (c.hasKeyword("Whenever a creature dealt damage by CARDNAME this turn is " + + "put into a graveyard, put a +1/+1 counter on CARDNAME.")) { + value += 2; + } + if (c.hasKeyword("Whenever a creature dealt damage by CARDNAME this turn is " + + "put into a graveyard, put a +2/+2 counter on CARDNAME.")) { + value += 3; + } + } + + value += c.getKeywordMagnitude("Bushido") * 16; + value += c.getAmountOfKeyword("Flanking") * 15; + value += c.getAmountOfKeyword("Exalted") * 15; + value += c.getKeywordMagnitude("Annihilator") * 50; + + + // Defensive Keywords + if (c.hasKeyword("Reach") && !c.hasKeyword("Flying")) { + value += 5; + } + if (c.hasKeyword("CARDNAME can block creatures with shadow as though they didn't have shadow.")) { + value += 3; + } + + // Protection + if (c.hasKeyword("Indestructible")) { + value += 70; + } + if (c.hasKeyword("Prevent all damage that would be dealt to CARDNAME.")) { + value += 60; + } else if (c.hasKeyword("Prevent all combat damage that would be dealt to CARDNAME.")) { + value += 50; + } + if (c.hasKeyword("Hexproof")) { + value += 35; + } else if (c.hasKeyword("Shroud")) { + value += 30; + } + if (c.hasStartOfKeyword("Protection")) { + value += 20; + } + if (c.hasStartOfKeyword("PreventAllDamageBy")) { + value += 10; + } + value += c.getKeywordMagnitude("Absorb") * 11; + + // Bad keywords + if (c.hasKeyword("Defender") || c.hasKeyword("CARDNAME can't attack.")) { + value -= (power * 9) + 40; + } else if (c.getSVar("SacrificeEndCombat").equals("True")) { + value -= 40; + } + if (c.hasKeyword("CARDNAME can't block.")) { + value -= 10; + } else if (c.hasKeyword("CARDNAME attacks each turn if able.")) { + value -= 10; + } else if (c.hasKeyword("CARDNAME can block only creatures with flying.")) { + value -= toughness * 5; + } + + if (c.hasStartOfKeyword("When CARDNAME is dealt damage, destroy it.")) { + value -= (toughness - 1) * 9; + } + + if (c.hasKeyword("CARDNAME can't attack or block.")) { + value = 50 + (c.getCMC() * 5); // reset everything - useless + } + if (c.hasKeyword("CARDNAME doesn't untap during your untap step.")) { + if (c.isTapped()) { + value = 50 + (c.getCMC() * 5); // reset everything - useless + } else { + value -= 50; + } + } + if (c.hasKeyword("At the beginning of the end step, destroy CARDNAME.") + || c.hasKeyword("At the beginning of the end step, exile CARDNAME.") + || c.hasKeyword("At the beginning of the end step, sacrifice CARDNAME.")) { + value -= 50; + } else if (c.hasStartOfKeyword("Cumulative upkeep")) { + value -= 30; + } else if (c.hasStartOfKeyword("At the beginning of your upkeep, destroy CARDNAME unless you pay") + || c.hasStartOfKeyword("At the beginning of your upkeep, sacrifice CARDNAME unless you pay") + || c.hasStartOfKeyword("Upkeep:")) { + value -= 20; + } else if (c.hasStartOfKeyword("(Echo unpaid)")) { + value -= 10; + } + + if (c.hasStartOfKeyword("At the beginning of your upkeep, CARDNAME deals")) { + value -= 20; + } + if (c.hasStartOfKeyword("Fading")) { + value -= 20; + } + if (c.hasStartOfKeyword("Vanishing")) { + value -= 20; + } + if (c.getSVar("Targeting").equals("Dies")) { + value -= 25; + } + + for (final SpellAbility sa : c.getSpellAbilities()) { + if (sa.isAbility()) { + value += 10; + } + } + if (!c.getManaAbility().isEmpty()) { + value += 10; + } + + if (c.isUntapped()) { + value += 1; + } + + // paired creatures are more valuable because they grant a bonus to the other creature + if (c.isPaired()) { + value += 14; + } + + return value; + + } // evaluateCreature + + /** + *

+ * evaluatePermanentList. + *

+ * + * @param list + * a {@link forge.CardList} object. + * @return a int. + */ + public static int evaluatePermanentList(final List list) { + int value = 0; + for (int i = 0; i < list.size(); i++) { + value += list.get(i).getCMC() + 1; + } + + return value; + } + + /** + *

+ * evaluateCreatureList. + *

+ * + * @param list + * a {@link forge.CardList} object. + * @return a int. + */ + public static int evaluateCreatureList(final List list) { + int value = 0; + for (int i = 0; i < list.size(); i++) { + value += evaluateCreature(list.get(i)); + } + + return value; + } + + /** + *

+ * doesCreatureAttackAI. + *

+ * + * @param ai + * the AI player + * @param card + * a {@link forge.Card} object. + * @return a boolean. + */ + public static boolean doesCreatureAttackAI(final Player ai, final Card card) { + final List att = new AiAttackController(ai, ai.getOpponent()).getAttackers().getAttackers(); + + return att.contains(card); + } + + // may return null + /** + *

+ * getRandomCard. + *

+ * + * @param list + * a {@link forge.CardList} object. + * @return a {@link forge.Card} object. + */ + public static Card getRandomCard(final List list) { + if (list.size() == 0) { + return null; + } + + final int index = ComputerUtilCard.random.nextInt(list.size()); + return list.get(index); + } + + public static Random random = MyRandom.getRandom(); + /** + * getMostExpensivePermanentAI. + * + * @param all + * the all + * @return the card + */ + public static Card getMostExpensivePermanentAI(final List all) { + if (all.size() == 0) { + return null; + } + Card biggest = null; + biggest = all.get(0); + + int bigCMC = 0; + for (int i = 0; i < all.size(); i++) { + final Card card = all.get(i); + int curCMC = card.getCMC(); + + // Add all cost of all auras with the same controller + final List auras = CardLists.filterControlledBy(card.getEnchantedBy(), card.getController()); + curCMC += Aggregates.sum(auras, CardPredicates.Accessors.fnGetCmc) + auras.size(); + + if (curCMC >= bigCMC) { + bigCMC = curCMC; + biggest = all.get(i); + } + } + + return biggest; + } + + /** + *

+ * getMostProminentCardName. + *

+ * + * @param list + * a {@link forge.CardList} object. + * @return a {@link java.lang.String} object. + */ + public static String getMostProminentCardName(final List list) { + + if (list.size() == 0) { + return ""; + } + + final Map map = new HashMap(); + + for (final Card c : list) { + final String name = c.getName(); + Integer currentCnt = map.get(name); + map.put(name, currentCnt == null ? Integer.valueOf(1) : Integer.valueOf(1 + currentCnt)); + } // for + + int max = 0; + String maxName = ""; + + for (final Entry entry : map.entrySet()) { + final String type = entry.getKey(); + // Log.debug(type + " - " + entry.getValue()); + + if (max < entry.getValue()) { + max = entry.getValue(); + maxName = type; + } + } + return maxName; + } + + /** + *

+ * getMostProminentCreatureType. + *

+ * + * @param list + * a {@link forge.CardList} object. + * @return a {@link java.lang.String} object. + */ + public static String getMostProminentCreatureType(final List list) { + + if (list.size() == 0) { + return ""; + } + + final Map map = new HashMap(); + + for (final Card c : list) { + final ArrayList typeList = c.getType(); + + for (final String var : typeList) { + if (CardType.isACreatureType(var)) { + if (!map.containsKey(var)) { + map.put(var, 1); + } else { + map.put(var, map.get(var) + 1); + } + } + } + } // for + + int max = 0; + String maxType = ""; + + for (final Entry entry : map.entrySet()) { + final String type = entry.getKey(); + // Log.debug(type + " - " + entry.getValue()); + + if (max < entry.getValue()) { + max = entry.getValue(); + maxType = type; + } + } + + return maxType; + } + + /** + *

+ * getMostProminentColor. + *

+ * + * @param list + * a {@link forge.CardList} object. + * @return a {@link java.lang.String} object. + */ + public static String getMostProminentColor(final List list) { + + final Map map = new HashMap(); + + for (final Card c : list) { + for (final String color : CardUtil.getColors(c)) { + if (color.equals("colorless")) { + // nothing to do + } else if (!map.containsKey(color)) { + map.put(color, 1); + } else { + map.put(color, map.get(color) + 1); + } + } + } // for + + int max = 0; + String maxColor = ""; + + for (final Entry entry : map.entrySet()) { + final String color = entry.getKey(); + Log.debug(color + " - " + entry.getValue()); + + if (max < entry.getValue()) { + max = entry.getValue(); + maxColor = color; + } + } + + return maxColor; + } + + public static List getColorByProminence(final List list) { + final HashMap counts = new HashMap(); + for (String color : Constant.Color.ONLY_COLORS) { + counts.put(color, 0); + } + for (Card c : list) { + List colors = c.determineColor().toStringList(); + for (String col : colors) { + if (counts.containsKey(col)) { + counts.put(col.toString(), counts.get(col.toString()) + 1); + } + } + } + ArrayList res = new ArrayList(counts.keySet()); + Collections.sort(res, new Comparator() { + @Override + public int compare(final String a, final String b) { + return counts.get(b) - counts.get(a); + } + }); + + return res; + } + + /** + *

+ * getUsableManaSources. + *

+ * + * @param player + * a {@link forge.game.player.Player} object. + * @return a int. + */ + public static int getUsableManaSources(final Player player) { + List list = CardLists.filter(player.getCardsIn(ZoneType.Battlefield), new Predicate() { + @Override + public boolean apply(final Card c) { + for (final SpellAbility am : c.getAIPlayableMana()) { + if (am.canPlay()) { + return true; + } + } + return false; + } + }); + + return list.size(); + } + + /** + *

+ * getWorstLand. + *

+ * + * @param lands + * a {@link forge.CardList} object. + * @return a {@link forge.Card} object. + */ + public static Card getWorstLand(final List lands) { + Card worstLand = null; + int maxScore = 0; + // first, check for tapped, basic lands + for (Card tmp : lands) { + int score = tmp.isTapped() ? 2 : 0; + score += tmp.isBasicLand() ? 1 : 0; + if (score >= maxScore) { + worstLand = tmp; + maxScore = score; + } + } + return worstLand; + } // end getWorstLand + +} diff --git a/src/main/java/forge/game/ai/ComputerUtilMana.java b/src/main/java/forge/game/ai/ComputerUtilMana.java index 0f6bf5ad0b8..ef3de857485 100644 --- a/src/main/java/forge/game/ai/ComputerUtilMana.java +++ b/src/main/java/forge/game/ai/ComputerUtilMana.java @@ -17,7 +17,6 @@ import forge.Singletons; import forge.card.MagicColor; import forge.card.ability.AbilityUtils; import forge.card.ability.ApiType; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.cost.Cost; import forge.card.cost.CostPayment; import forge.card.mana.ManaCostBeingPaid; @@ -748,7 +747,7 @@ public class ComputerUtilMana { } } // check if combo mana can produce most common color in hand - String commonColor = CardFactoryUtil.getMostProminentColor(ai.getCardsIn( + String commonColor = ComputerUtilCard.getMostProminentColor(ai.getCardsIn( ZoneType.Hand)); if (!commonColor.isEmpty() && abMana.getComboColors().contains(MagicColor.toShortString(commonColor))) { choice = MagicColor.toShortString(commonColor); diff --git a/src/main/java/forge/game/phase/CombatUtil.java b/src/main/java/forge/game/phase/CombatUtil.java index c75c1f94427..246421679b5 100644 --- a/src/main/java/forge/game/phase/CombatUtil.java +++ b/src/main/java/forge/game/phase/CombatUtil.java @@ -50,6 +50,7 @@ import forge.game.GameState; import forge.game.GlobalRuleChange; import forge.game.ai.ComputerUtil; import forge.game.ai.ComputerUtilBlock; +import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilCost; import forge.game.player.AIPlayer; import forge.game.player.Player; @@ -1573,7 +1574,7 @@ public class CombatUtil { enchantment = ((Card) check); } } else { - enchantment = CardFactoryUtil.getBestEnchantmentAI(enchantments, this, false); + enchantment = ComputerUtilCard.getBestEnchantmentAI(enchantments, this, false); } if ((enchantment != null) && attacker.isInPlay()) { Singletons.getModel().getGame().getAction().changeZone(Singletons.getModel().getGame().getZoneOf(enchantment), diff --git a/src/main/java/forge/game/phase/Untap.java b/src/main/java/forge/game/phase/Untap.java index 6ed9b7d04e9..e207107b3b9 100644 --- a/src/main/java/forge/game/phase/Untap.java +++ b/src/main/java/forge/game/phase/Untap.java @@ -30,9 +30,9 @@ import forge.CardPredicates; import forge.CounterType; import forge.GameEntity; import forge.Singletons; -import forge.card.cardfactory.CardFactoryUtil; import forge.control.input.Input; import forge.game.GameState; +import forge.game.ai.ComputerUtilCard; import forge.game.player.Player; import forge.game.zone.Zone; import forge.game.zone.ZoneType; @@ -246,7 +246,7 @@ public class Untap extends Phase { artList = CardLists.filter(artList, Presets.ARTIFACTS); artList = CardLists.filter(artList, tappedCanUntap); if (artList.size() > 0) { - CardFactoryUtil.getBestArtifactAI(artList).untap(); + ComputerUtilCard.getBestArtifactAI(artList).untap(); } } else { final Input target = new Input() { diff --git a/src/main/java/forge/game/phase/Upkeep.java b/src/main/java/forge/game/phase/Upkeep.java index 0481dc4c38a..4f281ac14a8 100644 --- a/src/main/java/forge/game/phase/Upkeep.java +++ b/src/main/java/forge/game/phase/Upkeep.java @@ -44,6 +44,7 @@ import forge.control.input.InputSelectManyCards; import forge.game.GameActionUtil; import forge.game.GameState; import forge.game.ai.ComputerUtil; +import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilCombat; import forge.game.ai.ComputerUtilCost; import forge.game.ai.ComputerUtilMana; @@ -501,7 +502,7 @@ public class Upkeep extends Phase { if (indestruct.size() > 0) { game.getAction().destroyNoRegeneration(indestruct.get(0)); } else if (targets.size() > 0) { - final Card target = CardFactoryUtil.getWorstCreatureAI(targets); + final Card target = ComputerUtilCard.getWorstCreatureAI(targets); if (null == target) { // must be nothing valid to destroy } else { @@ -632,7 +633,7 @@ public class Upkeep extends Phase { if (c.getController().isComputer()) { target = GuiChoose.one("Select a card to sacrifice", playerLand); } else { - target = CardFactoryUtil.getBestLandAI(playerLand); + target = ComputerUtilCard.getBestLandAI(playerLand); } game.getAction().sacrifice(target, null); } // end resolve() @@ -1027,7 +1028,7 @@ public class Upkeep extends Phase { for (int i = 0; i < num; i++) { if (player.isComputer()) { - Card toTap = CardFactoryUtil.getWorstPermanentAI(list, false, false, false, false); + Card toTap = ComputerUtilCard.getWorstPermanentAI(list, false, false, false, false); // try to find non creature cards without tap abilities List betterList = CardLists.filter(list, new Predicate() { @Override diff --git a/src/main/java/forge/game/player/AIPlayer.java b/src/main/java/forge/game/player/AIPlayer.java index 5e10ae95d2f..066b2482a67 100644 --- a/src/main/java/forge/game/player/AIPlayer.java +++ b/src/main/java/forge/game/player/AIPlayer.java @@ -25,10 +25,10 @@ import forge.Card; import forge.CardLists; import forge.CardPredicates; -import forge.card.cardfactory.CardFactoryUtil; import forge.card.spellability.SpellAbility; import forge.game.GameState; import forge.game.ai.AiController; +import forge.game.ai.ComputerUtilCard; import forge.game.zone.ZoneType; import forge.util.Aggregates; import forge.util.MyRandom; @@ -175,7 +175,7 @@ public class AIPlayer extends Player { public final void sacrificePermanent(final String prompt, final List choices) { if (choices.size() > 0) { // TODO - this could probably use better AI - final Card c = CardFactoryUtil.getWorstPermanentAI(choices, false, false, false, false); + final Card c = ComputerUtilCard.getWorstPermanentAI(choices, false, false, false, false); game.getAction().sacrificeDestroy(c); } } diff --git a/src/main/java/forge/game/zone/MagicStack.java b/src/main/java/forge/game/zone/MagicStack.java index 6adbfd41294..ae0f536a52c 100644 --- a/src/main/java/forge/game/zone/MagicStack.java +++ b/src/main/java/forge/game/zone/MagicStack.java @@ -53,6 +53,7 @@ import forge.control.input.InputPayManaExecuteCommands; import forge.game.GameActionUtil; import forge.game.GameState; import forge.game.ai.ComputerUtil; +import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilCost; import forge.game.event.SpellResolvedEvent; import forge.game.phase.PhaseType; @@ -901,9 +902,9 @@ public class MagicStack extends MyObservable { // AI choosing what to haunt final List oppCreats = CardLists.filterControlledBy(creats, source.getController().getOpponents()); if (oppCreats.size() != 0) { - haunterDiesWork.setTargetCard(CardFactoryUtil.getWorstCreatureAI(oppCreats)); + haunterDiesWork.setTargetCard(ComputerUtilCard.getWorstCreatureAI(oppCreats)); } else { - haunterDiesWork.setTargetCard(CardFactoryUtil.getWorstCreatureAI(creats)); + haunterDiesWork.setTargetCard(ComputerUtilCard.getWorstCreatureAI(creats)); } this.add(haunterDiesWork); } diff --git a/src/main/java/forge/gui/download/GuiDownloadPicturesLQ.java b/src/main/java/forge/gui/download/GuiDownloadPicturesLQ.java index 9414c8846e8..f4ad0762fc2 100644 --- a/src/main/java/forge/gui/download/GuiDownloadPicturesLQ.java +++ b/src/main/java/forge/gui/download/GuiDownloadPicturesLQ.java @@ -107,4 +107,22 @@ public class GuiDownloadPicturesLQ extends GuiDownloader { } } + /** + * Builds the ideal filename. + * + * @param cardName + * the card name + * @param artIndex + * the art index + * @param artIndexMax + * the art index max + * @return the string + */ + public static String buildIdealFilename(final String cardName, final int artIndex, final int artIndexMax) { + final String nn = artIndexMax > 1 ? Integer.toString(artIndex + 1) : ""; + final String mwsCardName = GuiDisplayUtil.cleanStringMWS(cardName); + // 3 letter set code with MWS filename format + return String.format("%s%s.full.jpg", mwsCardName, nn); + } + } diff --git a/src/main/java/forge/gui/download/GuiDownloadSetPicturesLQ.java b/src/main/java/forge/gui/download/GuiDownloadSetPicturesLQ.java index fb27a498310..2265c423a80 100644 --- a/src/main/java/forge/gui/download/GuiDownloadSetPicturesLQ.java +++ b/src/main/java/forge/gui/download/GuiDownloadSetPicturesLQ.java @@ -71,7 +71,7 @@ public class GuiDownloadSetPicturesLQ extends GuiDownloader { if (!foundSetImage) { final int artsCnt = c.getRules().getEditionInfo(setCode3).getCopiesCount(); - final String filename = CardUtil.buildIdealFilename(cardName, c.getArtIndex(), artsCnt); + final String filename = GuiDownloadPicturesLQ.buildIdealFilename(cardName, c.getArtIndex(), artsCnt); String url = urlBase + setCode2 + "/" + Base64Coder.encodeString(filename, true); cList.add(new DownloadObject(url, new File(this.picturesPath + File.separator + setCode3, filename)));