moved a lot of AI-used methods from CardFactoryUtil to ComputerUtilCard.java

switched Encode to getSingleCardForEffect
This commit is contained in:
Maxmtg
2013-02-25 21:00:06 +00:00
parent 8c5f8f16e2
commit 336b35ae24
64 changed files with 1306 additions and 1317 deletions

1
.gitattributes vendored
View File

@@ -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/AiInputCommon.java svneol=native#text/plain
src/main/java/forge/game/ai/ComputerUtil.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/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/ComputerUtilCombat.java -text
src/main/java/forge/game/ai/ComputerUtilCost.java -text src/main/java/forge/game/ai/ComputerUtilCost.java -text
src/main/java/forge/game/ai/ComputerUtilMana.java -text src/main/java/forge/game/ai/ComputerUtilMana.java -text

View File

@@ -27,8 +27,8 @@ import com.google.common.base.Predicates;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.game.ai.ComputerUtilCard;
import forge.game.player.Player; import forge.game.player.Player;
import forge.util.MyRandom; import forge.util.MyRandom;
@@ -74,13 +74,6 @@ public class CardLists {
return b.getNetCombatDamage() - a.getNetCombatDamage(); return b.getNetCombatDamage() - a.getNetCombatDamage();
} }
}; };
public static final Comparator<Card> EvaluateCreatureComparator = new Comparator<Card>() {
@Override
public int compare(final Card a, final Card b) {
return CardFactoryUtil.evaluateCreature(b) - CardFactoryUtil.evaluateCreature(a);
}
};
public static final Comparator<Card> CmcComparator = new Comparator<Card>() { public static final Comparator<Card> CmcComparator = new Comparator<Card>() {
@Override @Override
public int compare(final Card a, final Card b) { public int compare(final Card a, final Card b) {
@@ -131,7 +124,7 @@ public class CardLists {
* a {@link forge.CardList} object. * a {@link forge.CardList} object.
*/ */
public static void sortByEvaluateCreature(final List<Card> list) { public static void sortByEvaluateCreature(final List<Card> list) {
Collections.sort(list, EvaluateCreatureComparator); Collections.sort(list, ComputerUtilCard.EvaluateCreatureComparator);
} // sortByEvaluateCreature() } // sortByEvaluateCreature()
/** /**

View File

@@ -23,7 +23,6 @@ import com.google.common.base.Function;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.game.phase.CombatUtil; import forge.game.phase.CombatUtil;
import forge.game.phase.Untap; import forge.game.phase.Untap;
@@ -393,12 +392,5 @@ public final class CardPredicates {
return a.getCMC(); return a.getCMC();
} }
}; };
public static final Function<Card, Integer> fnEvaluateCreature = new Function<Card, Integer>() {
@Override
public Integer apply(Card a) {
return CardFactoryUtil.evaluateCreature(a);
}
};
} }
} }

View File

@@ -33,7 +33,6 @@ import forge.card.CardSplitType;
import forge.card.MagicColor; import forge.card.MagicColor;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.ApiType; import forge.card.ability.ApiType;
import forge.card.mana.ManaCostBeingPaid;
import forge.card.spellability.AbilityManaPart; import forge.card.spellability.AbilityManaPart;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.game.player.Player; import forge.game.player.Player;
@@ -99,29 +98,6 @@ public final class CardUtil {
return c.determineColor().toStringList(); return c.determineColor().toStringList();
} }
// this function checks, if duplicates of a keyword are not necessary (like
// flying, trample, etc.)
/**
* <p>
* isNonStackingKeyword.
* </p>
*
* @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);
}
/** /**
* <p> * <p>
* isStackingKeyword. * isStackingKeyword.
@@ -132,25 +108,12 @@ public final class CardUtil {
* @return a boolean. * @return a boolean.
*/ */
public static boolean isStackingKeyword(final String keyword) { public static boolean isStackingKeyword(final String keyword) {
return !CardUtil.isNonStackingKeyword(keyword); String kw = new String(keyword);
} if (kw.startsWith("HIDDEN")) {
kw = kw.substring(7);
}
/** return !kw.startsWith("Protection") && !Constant.Keywords.NON_STACKING_LIST.contains(kw);
* 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);
} }
/** /**
@@ -432,35 +395,6 @@ public final class CardUtil {
return res; return res;
} }
/**
* Gets the convokable colors.
*
* @param cardToConvoke
* the card to convoke
* @param cost
* the cost
* @return the convokable colors
*/
public static ArrayList<String> getConvokableColors(final Card cardToConvoke, final ManaCostBeingPaid cost) {
final ArrayList<String> usableColors = new ArrayList<String>();
if (cost.getColorlessManaAmount() > 0) {
usableColors.add("colorless");
}
for (final CardColor col : cardToConvoke.getColor()) {
for (final String strCol : col.toStringList()) {
if (strCol.equals("colorless")) {
continue;
}
if (cost.toString().contains(MagicColor.toShortString(strCol))) {
usableColors.add(strCol.toString());
}
}
}
return usableColors;
}
/** /**
* Gets the face down characteristic. * Gets the face down characteristic.
* *

View File

@@ -24,6 +24,7 @@ import forge.card.cost.Cost;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.card.staticability.StaticAbility; import forge.card.staticability.StaticAbility;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilMana; import forge.game.ai.ComputerUtilMana;
import forge.game.phase.CombatUtil; import forge.game.phase.CombatUtil;
import forge.game.phase.PhaseHandler; 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" // TODO If Not Mandatory, make sure the card is "good enough"
if (c.isCreature()) { if (c.isCreature()) {
final int eval = CardFactoryUtil.evaluateCreature(c); final int eval = ComputerUtilCard.evaluateCreature(c);
if (eval < 130) { if (eval < 130) {
return null; return null;
} }
@@ -119,7 +120,7 @@ public class AttachAi extends SpellAbilityAi {
return null; 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 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 list = CardLists.getNotType(list, type); // Filter out Basic Lands that have the
// same type as the changing type // 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. // 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 // 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) { if (c == null) {
return chooseLessPreferred(mandatory, list); 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 // If Mandatory (brought directly into play without casting) gotta
// choose something // choose something
@@ -361,7 +362,7 @@ public class AttachAi extends SpellAbilityAi {
final Card attachSource) { final Card attachSource) {
// AI For choosing a Card to Animate. // AI For choosing a Card to Animate.
// TODO Add some more restrictions for Reanimation Auras // 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 // If Mandatory (brought directly into play without casting) gotta
// choose something // choose something
@@ -406,7 +407,7 @@ public class AttachAi extends SpellAbilityAi {
return true; 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 // If Mandatory (brought directly into play without casting) gotta
// choose something // choose something
@@ -537,7 +538,7 @@ public class AttachAi extends SpellAbilityAi {
if ((prefList == null) || prefList.isEmpty()) { if ((prefList == null) || prefList.isEmpty()) {
prefList = new ArrayList<Card>(list); prefList = new ArrayList<Card>(list);
} else { } else {
c = CardFactoryUtil.getBestAI(prefList); c = ComputerUtilCard.getBestAI(prefList);
if (c != null) { if (c != null) {
return c; return c;
} }
@@ -559,7 +560,7 @@ public class AttachAi extends SpellAbilityAi {
}); });
} }
c = CardFactoryUtil.getBestAI(prefList); c = ComputerUtilCard.getBestAI(prefList);
if (c == null) { if (c == null) {
return chooseLessPreferred(mandatory, list); return chooseLessPreferred(mandatory, list);
@@ -602,7 +603,7 @@ public class AttachAi extends SpellAbilityAi {
//don't equip a worse creature //don't equip a worse creature
if (card.isEquipping()) { if (card.isEquipping()) {
Card oldTarget = card.getEquipping().get(0); Card oldTarget = card.getEquipping().get(0);
if (CardFactoryUtil.evaluateCreature(oldTarget) > CardFactoryUtil.evaluateCreature(newTarget)) { if (ComputerUtilCard.evaluateCreature(oldTarget) > ComputerUtilCard.evaluateCreature(newTarget)) {
return false; return false;
} }
} }
@@ -723,7 +724,7 @@ public class AttachAi extends SpellAbilityAi {
} }
}); });
return CardFactoryUtil.getBestAI(magnetList); return ComputerUtilCard.getBestAI(magnetList);
} }
int totToughness = 0; int totToughness = 0;
@@ -809,11 +810,11 @@ public class AttachAi extends SpellAbilityAi {
return !c.isCreature() || CombatUtil.canAttackNextTurn(c); return !c.isCreature() || CombatUtil.canAttackNextTurn(c);
} }
}); });
c = CardFactoryUtil.getBestAI(prefList); c = ComputerUtilCard.getBestAI(prefList);
} else { } else {
// If we grant abilities, we may want to put it on something Weak? // If we grant abilities, we may want to put it on something Weak?
// Possibly more defensive? // Possibly more defensive?
c = CardFactoryUtil.getWorstPermanentAI(prefList, false, false, false, false); c = ComputerUtilCard.getWorstPermanentAI(prefList, false, false, false, false);
} }
if (c == null) { if (c == null) {

View File

@@ -20,7 +20,6 @@ import forge.card.ability.AbilityUtils;
import forge.card.ability.ApiType; import forge.card.ability.ApiType;
import forge.card.ability.SpellAbilityAi; import forge.card.ability.SpellAbilityAi;
import forge.card.ability.effects.AttachEffect; import forge.card.ability.effects.AttachEffect;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.Cost; import forge.card.cost.Cost;
import forge.card.cost.CostDiscard; import forge.card.cost.CostDiscard;
import forge.card.cost.CostPart; import forge.card.cost.CostPart;
@@ -29,6 +28,7 @@ import forge.card.spellability.SpellAbility;
import forge.card.spellability.SpellPermanent; import forge.card.spellability.SpellPermanent;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.GlobalRuleChange; import forge.game.GlobalRuleChange;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilCombat; import forge.game.ai.ComputerUtilCombat;
import forge.game.ai.ComputerUtil; import forge.game.ai.ComputerUtil;
import forge.game.ai.ComputerUtilBlock; import forge.game.ai.ComputerUtilBlock;
@@ -507,7 +507,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
} }
} else { } else {
// not urgent, get the largest creature possible // not urgent, get the largest creature possible
card = CardFactoryUtil.getBestCreatureAI(list); card = ComputerUtilCard.getBestCreatureAI(list);
} }
return card; return card;
} }
@@ -730,7 +730,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
if (!threatenedTargets.isEmpty()) { if (!threatenedTargets.isEmpty()) {
// Choose "best" of the remaining to save // Choose "best" of the remaining to save
tgt.addTarget(CardFactoryUtil.getBestAI(threatenedTargets)); tgt.addTarget(ComputerUtilCard.getBestAI(threatenedTargets));
return true; return true;
} }
} }
@@ -762,7 +762,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
}); });
if (!aiPermanents.isEmpty()) { if (!aiPermanents.isEmpty()) {
// Choose "best" of the remaining to save // Choose "best" of the remaining to save
tgt.addTarget(CardFactoryUtil.getBestAI(aiPermanents)); tgt.addTarget(ComputerUtilCard.getBestAI(aiPermanents));
return true; return true;
} }
} }
@@ -839,15 +839,15 @@ public class ChangeZoneAi extends SpellAbilityAi {
Card choice = null; Card choice = null;
if (!list.isEmpty()) { 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 (destination.equals(ZoneType.Battlefield) || origin.equals(ZoneType.Battlefield)) {
if (mostExpensive.isCreature()) { if (mostExpensive.isCreature()) {
// if a creature is most expensive take the best one // if a creature is most expensive take the best one
if (destination.equals(ZoneType.Exile)) { if (destination.equals(ZoneType.Exile)) {
// If Exiling things, don't give bonus to Tokens // If Exiling things, don't give bonus to Tokens
choice = CardFactoryUtil.getBestCreatureAI(list); choice = ComputerUtilCard.getBestCreatureAI(list);
} else { } else {
choice = CardFactoryUtil.getBestCreatureToBounceAI(list); choice = ComputerUtilCard.getBestCreatureToBounceAI(list);
} }
} else { } else {
choice = mostExpensive; choice = mostExpensive;
@@ -870,7 +870,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
} else { } else {
// Get the best card in there. // Get the best card in there.
System.out.println("No creature and lots of life, finding something good."); System.out.println("No creature and lots of life, finding something good.");
choice = CardFactoryUtil.getBestAI(nonLands); choice = ComputerUtilCard.getBestAI(nonLands);
} }
} }
if (choice == null) { if (choice == null) {
@@ -879,7 +879,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
choice = list.get(0); choice = list.get(0);
} }
} else { } else {
choice = CardFactoryUtil.getBestAI(list); choice = ComputerUtilCard.getBestAI(list);
} }
} }
if (choice == null) { // can't find anything left if (choice == null) { // can't find anything left
@@ -957,12 +957,12 @@ public class ChangeZoneAi extends SpellAbilityAi {
Card choice = null; Card choice = null;
if (!list.isEmpty()) { 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))) { && (destination.equals(ZoneType.Battlefield) || origin.equals(ZoneType.Battlefield))) {
// if a creature is most expensive take the best // 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)) { } 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)) { } else if (destination.equals(ZoneType.Hand) || destination.equals(ZoneType.Library)) {
List<Card> nonLands = CardLists.getNotType(list, "Land"); List<Card> nonLands = CardLists.getNotType(list, "Land");
// Prefer to pull a creature, generally more useful for AI. // Prefer to pull a creature, generally more useful for AI.
@@ -981,7 +981,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
} else { } else {
// Get the best card in there. // Get the best card in there.
System.out.println("No creature and lots of life, finding something good."); System.out.println("No creature and lots of life, finding something good.");
choice = CardFactoryUtil.getBestAI(nonLands); choice = ComputerUtilCard.getBestAI(nonLands);
} }
} }
if (choice == null) { if (choice == null) {
@@ -990,7 +990,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
choice = list.get(0); choice = list.get(0);
} }
} else { } else {
choice = CardFactoryUtil.getBestAI(list); choice = ComputerUtilCard.getBestAI(list);
} }
} }
if (choice == null) { // can't find anything left 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)) { if (ZoneType.Exile.equals(destination) || origin.contains(ZoneType.Battlefield)) {
// Exiling or bouncing stuff // Exiling or bouncing stuff
if (player.isOpponentOf(ai)) { if (player.isOpponentOf(ai)) {
c = CardFactoryUtil.getBestAI(fetchList); c = ComputerUtilCard.getBestAI(fetchList);
} else { } else {
c = CardFactoryUtil.getWorstAI(fetchList); c = ComputerUtilCard.getWorstAI(fetchList);
} }
} else if (origin.contains(ZoneType.Library) } else if (origin.contains(ZoneType.Library)
&& (type.contains("Basic") || areAllBasics(type))) { && (type.contains("Basic") || areAllBasics(type))) {
@@ -1179,9 +1179,9 @@ public class ChangeZoneAi extends SpellAbilityAi {
c = chooseCreature(ai, fetchList); c = chooseCreature(ai, fetchList);
} else if (ZoneType.Battlefield.equals(destination) || ZoneType.Graveyard.equals(destination)) { } else if (ZoneType.Battlefield.equals(destination) || ZoneType.Graveyard.equals(destination)) {
if (!activator.equals(ai) && sa.hasParam("GainControl")) { if (!activator.equals(ai) && sa.hasParam("GainControl")) {
c = CardFactoryUtil.getWorstAI(fetchList); c = ComputerUtilCard.getWorstAI(fetchList);
} else { } else {
c = CardFactoryUtil.getBestAI(fetchList); c = ComputerUtilCard.getBestAI(fetchList);
} }
} else { } else {
// Don't fetch another tutor with the same name // Don't fetch another tutor with the same name
@@ -1222,7 +1222,7 @@ public class ChangeZoneAi extends SpellAbilityAi {
} else { } else {
// Get the best card in there. // Get the best card in there.
System.out.println("No creature and lots of life, finding something good."); 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); list = CardLists.getValidCards(list, sa.getParam("AttachedTo"), c.getController(), c);
} }
if (!list.isEmpty()) { if (!list.isEmpty()) {
final Card attachedTo = CardFactoryUtil.getBestAI(list); final Card attachedTo = ComputerUtilCard.getBestAI(list);
if (c.isEnchanting()) { if (c.isEnchanting()) {
// If this Card is already Enchanting something, need // If this Card is already Enchanting something, need
// to unenchant it, then clear out the commands // to unenchant it, then clear out the commands

View File

@@ -8,10 +8,10 @@ import forge.CardLists;
import forge.Singletons; import forge.Singletons;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityAi; import forge.card.ability.SpellAbilityAi;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.Cost; import forge.card.cost.Cost;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilCost; import forge.game.ai.ComputerUtilCost;
import forge.game.phase.PhaseType; import forge.game.phase.PhaseType;
import forge.game.player.AIPlayer; import forge.game.player.AIPlayer;
@@ -89,13 +89,13 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
computerType.clear(); computerType.clear();
} }
if ((CardLists.getNotType(humanType, "Creature").size() == 0) && (CardLists.getNotType(computerType, "Creature").size() == 0)) { 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)) { .evaluateCreatureList(humanType)) {
return false; return false;
} }
} // otherwise evaluate both lists by CMC and pass only if human } // otherwise evaluate both lists by CMC and pass only if human
// permanents are more valuable // permanents are more valuable
else if ((CardFactoryUtil.evaluatePermanentList(computerType) + 3) >= CardFactoryUtil else if ((ComputerUtilCard.evaluatePermanentList(computerType) + 3) >= ComputerUtilCard
.evaluatePermanentList(humanType)) { .evaluatePermanentList(humanType)) {
return false; return false;
} }
@@ -127,26 +127,26 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
if (sa.getParam("GainControl") != null) { if (sa.getParam("GainControl") != null) {
// Check if the cards are valuable enough // Check if the cards are valuable enough
if ((CardLists.getNotType(humanType, "Creature").size() == 0) && (CardLists.getNotType(computerType, "Creature").size() == 0)) { 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) { .evaluateCreatureList(humanType)) < 400) {
return false; return false;
} }
} // otherwise evaluate both lists by CMC and pass only if human } // otherwise evaluate both lists by CMC and pass only if human
// permanents are less valuable // permanents are less valuable
else if ((CardFactoryUtil.evaluatePermanentList(computerType) + CardFactoryUtil else if ((ComputerUtilCard.evaluatePermanentList(computerType) + ComputerUtilCard
.evaluatePermanentList(humanType)) < 6) { .evaluatePermanentList(humanType)) < 6) {
return false; return false;
} }
} else { } else {
// don't activate if human gets more back than AI does // 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 ((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)) { .evaluateCreatureList(humanType) + 100)) {
return false; return false;
} }
} // otherwise evaluate both lists by CMC and pass only if human } // otherwise evaluate both lists by CMC and pass only if human
// permanents are less valuable // permanents are less valuable
else if (CardFactoryUtil.evaluatePermanentList(computerType) <= (CardFactoryUtil else if (ComputerUtilCard.evaluatePermanentList(computerType) <= (ComputerUtilCard
.evaluatePermanentList(humanType) + 2)) { .evaluatePermanentList(humanType) + 2)) {
return false; return false;
} }
@@ -206,13 +206,13 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
// if only creatures are affected evaluate both lists and pass only // if only creatures are affected evaluate both lists and pass only
// if human creatures are more valuable // if human creatures are more valuable
if ((CardLists.getNotType(humanType, "Creature").isEmpty()) && (CardLists.getNotType(computerType, "Creature").isEmpty())) { if ((CardLists.getNotType(humanType, "Creature").isEmpty()) && (CardLists.getNotType(computerType, "Creature").isEmpty())) {
if (CardFactoryUtil.evaluateCreatureList(computerType) >= CardFactoryUtil if (ComputerUtilCard.evaluateCreatureList(computerType) >= ComputerUtilCard
.evaluateCreatureList(humanType)) { .evaluateCreatureList(humanType)) {
return false; return false;
} }
} // otherwise evaluate both lists by CMC and pass only if human } // otherwise evaluate both lists by CMC and pass only if human
// permanents are more valuable // permanents are more valuable
else if (CardFactoryUtil.evaluatePermanentList(computerType) >= CardFactoryUtil else if (ComputerUtilCard.evaluatePermanentList(computerType) >= ComputerUtilCard
.evaluatePermanentList(humanType)) { .evaluatePermanentList(humanType)) {
return false; return false;
} }
@@ -240,26 +240,26 @@ public class ChangeZoneAllAi extends SpellAbilityAi {
if (sa.getParam("GainControl") != null) { if (sa.getParam("GainControl") != null) {
// Check if the cards are valuable enough // Check if the cards are valuable enough
if ((CardLists.getNotType(humanType, "Creature").size() == 0) && (CardLists.getNotType(computerType, "Creature").size() == 0)) { 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) { .evaluateCreatureList(humanType)) < 1) {
return false; return false;
} }
} // otherwise evaluate both lists by CMC and pass only if human } // otherwise evaluate both lists by CMC and pass only if human
// permanents are less valuable // permanents are less valuable
else if ((CardFactoryUtil.evaluatePermanentList(computerType) + CardFactoryUtil else if ((ComputerUtilCard.evaluatePermanentList(computerType) + ComputerUtilCard
.evaluatePermanentList(humanType)) < 1) { .evaluatePermanentList(humanType)) < 1) {
return false; return false;
} }
} else { } else {
// don't activate if human gets more back than AI does // don't activate if human gets more back than AI does
if ((CardLists.getNotType(humanType, "Creature").isEmpty()) && (CardLists.getNotType(computerType, "Creature").isEmpty())) { if ((CardLists.getNotType(humanType, "Creature").isEmpty()) && (CardLists.getNotType(computerType, "Creature").isEmpty())) {
if (CardFactoryUtil.evaluateCreatureList(computerType) <= CardFactoryUtil if (ComputerUtilCard.evaluateCreatureList(computerType) <= ComputerUtilCard
.evaluateCreatureList(humanType)) { .evaluateCreatureList(humanType)) {
return false; return false;
} }
} // otherwise evaluate both lists by CMC and pass only if human } // otherwise evaluate both lists by CMC and pass only if human
// permanents are less valuable // permanents are less valuable
else if (CardFactoryUtil.evaluatePermanentList(computerType) <= CardFactoryUtil else if (ComputerUtilCard.evaluatePermanentList(computerType) <= ComputerUtilCard
.evaluatePermanentList(humanType)) { .evaluatePermanentList(humanType)) {
return false; return false;
} }

View File

@@ -9,9 +9,9 @@ import forge.Card;
import forge.CardLists; import forge.CardLists;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityAi; import forge.card.ability.SpellAbilityAi;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCard;
import forge.game.player.AIPlayer; import forge.game.player.AIPlayer;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
import forge.util.MyRandom; import forge.util.MyRandom;
@@ -39,19 +39,19 @@ public class ControlExchangeAi extends SpellAbilityAi {
return !vars.containsKey("RemAIDeck") && c.canBeTargetedBy(sa); return !vars.containsKey("RemAIDeck") && c.canBeTargetedBy(sa);
} }
}); });
object1 = CardFactoryUtil.getBestAI(list); object1 = ComputerUtilCard.getBestAI(list);
if (sa.hasParam("Defined")) { if (sa.hasParam("Defined")) {
object2 = AbilityUtils.getDefinedCards(sa.getSourceCard(), sa.getParam("Defined"), sa).get(0); object2 = AbilityUtils.getDefinedCards(sa.getSourceCard(), sa.getParam("Defined"), sa).get(0);
} else if (tgt.getMinTargets(sa.getSourceCard(), sa) > 1) { } else if (tgt.getMinTargets(sa.getSourceCard(), sa) > 1) {
List<Card> list2 = ai.getCardsIn(ZoneType.Battlefield); List<Card> list2 = ai.getCardsIn(ZoneType.Battlefield);
list2 = CardLists.getValidCards(list2, tgt.getValidTgts(), ai, sa.getSourceCard()); list2 = CardLists.getValidCards(list2, tgt.getValidTgts(), ai, sa.getSourceCard());
object2 = CardFactoryUtil.getWorstAI(list2); object2 = ComputerUtilCard.getWorstAI(list2);
tgt.addTarget(object2); tgt.addTarget(object2);
} }
if (object1 == null || object2 == null) { if (object1 == null || object2 == null) {
return false; return false;
} }
if (CardFactoryUtil.evaluateCreature(object1) > CardFactoryUtil.evaluateCreature(object2) + 40) { if (ComputerUtilCard.evaluateCreature(object1) > ComputerUtilCard.evaluateCreature(object2) + 40) {
tgt.addTarget(object1); tgt.addTarget(object1);
return MyRandom.getRandom().nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn()); return MyRandom.getRandom().nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
} }

View File

@@ -29,9 +29,9 @@ import forge.CardLists;
import forge.Singletons; import forge.Singletons;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityAi; import forge.card.ability.SpellAbilityAi;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCard;
import forge.game.phase.PhaseType; import forge.game.phase.PhaseType;
import forge.game.player.AIPlayer; import forge.game.player.AIPlayer;
import forge.game.player.Player; import forge.game.player.Player;
@@ -139,15 +139,15 @@ public class ControlGainAi extends SpellAbilityAi {
} }
if (hasCreature) { if (hasCreature) {
t = CardFactoryUtil.getBestCreatureAI(list); t = ComputerUtilCard.getBestCreatureAI(list);
} else if (hasArtifact) { } else if (hasArtifact) {
t = CardFactoryUtil.getBestArtifactAI(list); t = ComputerUtilCard.getBestArtifactAI(list);
} else if (hasLand) { } else if (hasLand) {
t = CardFactoryUtil.getBestLandAI(list); t = ComputerUtilCard.getBestLandAI(list);
} else if (hasEnchantment) { } else if (hasEnchantment) {
t = CardFactoryUtil.getBestEnchantmentAI(list, sa, true); t = ComputerUtilCard.getBestEnchantmentAI(list, sa, true);
} else { } else {
t = CardFactoryUtil.getMostExpensivePermanentAI(list, sa, true); t = ComputerUtilCard.getMostExpensivePermanentAI(list, sa, true);
} }
tgt.addTarget(t); tgt.addTarget(t);

View File

@@ -11,9 +11,9 @@ import forge.CardLists;
import forge.Singletons; import forge.Singletons;
import forge.CardPredicates.Presets; import forge.CardPredicates.Presets;
import forge.card.ability.SpellAbilityAi; import forge.card.ability.SpellAbilityAi;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCard;
import forge.game.phase.PhaseType; import forge.game.phase.PhaseType;
import forge.game.player.AIPlayer; import forge.game.player.AIPlayer;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
@@ -82,9 +82,9 @@ public class CopyPermanentAi extends SpellAbilityAi {
Card choice; Card choice;
if (!CardLists.filter(list, Presets.CREATURES).isEmpty()) { if (!CardLists.filter(list, Presets.CREATURES).isEmpty()) {
choice = CardFactoryUtil.getBestCreatureAI(list); choice = ComputerUtilCard.getBestCreatureAI(list);
} else { } else {
choice = CardFactoryUtil.getMostExpensivePermanentAI(list, sa, true); choice = ComputerUtilCard.getMostExpensivePermanentAI(list, sa, true);
} }
if (choice == null) { // can't find anything left if (choice == null) { // can't find anything left

View File

@@ -9,6 +9,7 @@ import forge.card.cost.Cost;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.card.spellability.TargetSelection; import forge.card.spellability.TargetSelection;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilCost; import forge.game.ai.ComputerUtilCost;
import forge.game.ai.ComputerUtilMana; import forge.game.ai.ComputerUtilMana;
import forge.game.player.AIPlayer; import forge.game.player.AIPlayer;
@@ -62,7 +63,7 @@ public class CounterAi extends SpellAbilityAi {
if (unlessCost != null && !unlessCost.endsWith(">")) { if (unlessCost != null && !unlessCost.endsWith(">")) {
// Is this Usable Mana Sources? Or Total Available Mana? // 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; int toPay = 0;
boolean setPayX = false; boolean setPayX = false;
if (unlessCost.equals("X") && source.getSVar(unlessCost).equals("Count$xPaid")) { if (unlessCost.equals("X") && source.getSVar(unlessCost).equals("Count$xPaid")) {
@@ -130,7 +131,7 @@ public class CounterAi extends SpellAbilityAi {
final Card source = sa.getSourceCard(); final Card source = sa.getSourceCard();
if (unlessCost != null) { if (unlessCost != null) {
// Is this Usable Mana Sources? Or Total Available Mana? // 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; int toPay = 0;
boolean setPayX = false; boolean setPayX = false;
if (unlessCost.equals("X") && source.getSVar(unlessCost).equals("Count$xPaid")) { if (unlessCost.equals("X") && source.getSVar(unlessCost).equals("Count$xPaid")) {

View File

@@ -25,7 +25,7 @@ import forge.Card;
import forge.CardLists; import forge.CardLists;
import forge.CounterType; 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) { if (killable.size() > 0) {
choice = CardFactoryUtil.getBestCreatureAI(killable); choice = ComputerUtilCard.getBestCreatureAI(killable);
} else { } else {
choice = CardFactoryUtil.getBestCreatureAI(list); choice = ComputerUtilCard.getBestCreatureAI(list);
} }
} else { } else {
// improve random choice here // improve random choice here
choice = CardFactoryUtil.getRandomCard(list); choice = ComputerUtilCard.getRandomCard(list);
} }
return choice; return choice;
} }
@@ -88,7 +88,7 @@ public abstract class CountersAi {
public static Card chooseBoonTarget(final List<Card> list, final String type) { public static Card chooseBoonTarget(final List<Card> list, final String type) {
Card choice; Card choice;
if (type.equals("P1P1")) { if (type.equals("P1P1")) {
choice = CardFactoryUtil.getBestCreatureAI(list); choice = ComputerUtilCard.getBestCreatureAI(list);
} else if (type.equals("DIVINITY")) { } else if (type.equals("DIVINITY")) {
final List<Card> boon = CardLists.filter(list, new Predicate<Card>() { final List<Card> boon = CardLists.filter(list, new Predicate<Card>() {
@Override @Override
@@ -96,12 +96,12 @@ public abstract class CountersAi {
return c.getCounters(CounterType.DIVINITY) == 0; return c.getCounters(CounterType.DIVINITY) == 0;
} }
}); });
choice = CardFactoryUtil.getMostExpensivePermanentAI(boon, null, false); choice = ComputerUtilCard.getMostExpensivePermanentAI(boon, null, false);
} else { } else {
// The AI really should put counters on cards that can use it. // The AI really should put counters on cards that can use it.
// Charge counters on things with Charge abilities, etc. Expand // Charge counters on things with Charge abilities, etc. Expand
// these above // these above
choice = CardFactoryUtil.getRandomCard(list); choice = ComputerUtilCard.getRandomCard(list);
} }
return choice; return choice;
} }

View File

@@ -8,9 +8,9 @@ import forge.CardLists;
import forge.CounterType; import forge.CounterType;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityAi; import forge.card.ability.SpellAbilityAi;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCard;
import forge.game.player.AIPlayer; import forge.game.player.AIPlayer;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
@@ -103,9 +103,9 @@ public class CountersMoveAi extends SpellAbilityAi {
else { else {
if (type.equals("M1M1")) { if (type.equals("M1M1")) {
choice = CardFactoryUtil.getWorstCreatureAI(list); choice = ComputerUtilCard.getWorstCreatureAI(list);
} else { } else {
choice = CardFactoryUtil.getRandomCard(list); choice = ComputerUtilCard.getRandomCard(list);
} }
} }
} else { } else {
@@ -115,9 +115,9 @@ public class CountersMoveAi extends SpellAbilityAi {
else { else {
if (type.equals("P1P1")) { if (type.equals("P1P1")) {
choice = CardFactoryUtil.getWorstCreatureAI(list); choice = ComputerUtilCard.getWorstCreatureAI(list);
} else { } else {
choice = CardFactoryUtil.getRandomCard(list); choice = ComputerUtilCard.getRandomCard(list);
} }
} }
} }

View File

@@ -12,11 +12,11 @@ import forge.CounterType;
import forge.Singletons; import forge.Singletons;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityAi; import forge.card.ability.SpellAbilityAi;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.Cost; import forge.card.cost.Cost;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.ai.ComputerUtil; import forge.game.ai.ComputerUtil;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilCost; import forge.game.ai.ComputerUtilCost;
import forge.game.ai.ComputerUtilMana; import forge.game.ai.ComputerUtilMana;
import forge.game.phase.PhaseType; import forge.game.phase.PhaseType;
@@ -279,9 +279,9 @@ public class CountersPutAi extends SpellAbilityAi {
else { else {
if (type.equals("M1M1")) { if (type.equals("M1M1")) {
choice = CardFactoryUtil.getWorstCreatureAI(list); choice = ComputerUtilCard.getWorstCreatureAI(list);
} else { } else {
choice = CardFactoryUtil.getRandomCard(list); choice = ComputerUtilCard.getRandomCard(list);
} }
} }
} else { } else {
@@ -291,9 +291,9 @@ public class CountersPutAi extends SpellAbilityAi {
else { else {
if (type.equals("P1P1")) { if (type.equals("P1P1")) {
choice = CardFactoryUtil.getWorstCreatureAI(list); choice = ComputerUtilCard.getWorstCreatureAI(list);
} else { } else {
choice = CardFactoryUtil.getRandomCard(list); choice = ComputerUtilCard.getRandomCard(list);
} }
} }
} }

View File

@@ -11,10 +11,10 @@ import forge.CardLists;
import forge.Singletons; import forge.Singletons;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityAi; import forge.card.ability.SpellAbilityAi;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.Cost; import forge.card.cost.Cost;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilCombat; import forge.game.ai.ComputerUtilCombat;
import forge.game.ai.ComputerUtilCost; import forge.game.ai.ComputerUtilCost;
import forge.game.ai.ComputerUtilMana; 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 // 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)) { .evaluateCreatureList(humanList)) {
return false; return false;
} }
@@ -144,7 +144,7 @@ public class DamageAllAi extends SpellAbilityAi {
return true; return true;
} }
if (!computerList.isEmpty() && CardFactoryUtil.evaluateCreatureList(computerList) > CardFactoryUtil if (!computerList.isEmpty() && ComputerUtilCard.evaluateCreatureList(computerList) > ComputerUtilCard
.evaluateCreatureList(humanList)) { .evaluateCreatureList(humanList)) {
return false; return false;
} }
@@ -233,7 +233,7 @@ public class DamageAllAi extends SpellAbilityAi {
return true; return true;
} }
if (!computerList.isEmpty() && CardFactoryUtil.evaluateCreatureList(computerList) + 50 >= CardFactoryUtil if (!computerList.isEmpty() && ComputerUtilCard.evaluateCreatureList(computerList) + 50 >= ComputerUtilCard
.evaluateCreatureList(humanList)) { .evaluateCreatureList(humanList)) {
return false; return false;
} }

View File

@@ -11,12 +11,12 @@ import forge.CardLists;
import forge.Singletons; import forge.Singletons;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityAi; import forge.card.ability.SpellAbilityAi;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.Cost; import forge.card.cost.Cost;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.card.spellability.TargetSelection; import forge.card.spellability.TargetSelection;
import forge.game.ai.ComputerUtil; import forge.game.ai.ComputerUtil;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilCombat; import forge.game.ai.ComputerUtilCombat;
import forge.game.ai.ComputerUtilCost; import forge.game.ai.ComputerUtilCost;
import forge.game.ai.ComputerUtilMana; import forge.game.ai.ComputerUtilMana;
@@ -165,7 +165,7 @@ public class DamageDealAi extends DamageAiBase {
Card targetCard; Card targetCard;
if (pl.isOpponentOf(ai) && (killables.size() > 0)) { if (pl.isOpponentOf(ai) && (killables.size() > 0)) {
targetCard = CardFactoryUtil.getBestCreatureAI(killables); targetCard = ComputerUtilCard.getBestCreatureAI(killables);
return targetCard; return targetCard;
} }
@@ -176,9 +176,9 @@ public class DamageDealAi extends DamageAiBase {
if (hPlay.size() > 0) { if (hPlay.size() > 0) {
if (pl.isOpponentOf(ai)) { if (pl.isOpponentOf(ai)) {
targetCard = CardFactoryUtil.getBestCreatureAI(hPlay); targetCard = ComputerUtilCard.getBestCreatureAI(hPlay);
} else { } else {
targetCard = CardFactoryUtil.getWorstCreatureAI(hPlay); targetCard = ComputerUtilCard.getWorstCreatureAI(hPlay);
} }
return targetCard; return targetCard;

View File

@@ -9,11 +9,11 @@ import forge.CardPredicates;
import forge.Singletons; import forge.Singletons;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityAi; import forge.card.ability.SpellAbilityAi;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.Cost; import forge.card.cost.Cost;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.ai.ComputerUtil; import forge.game.ai.ComputerUtil;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilCombat; import forge.game.ai.ComputerUtilCombat;
import forge.game.ai.ComputerUtilCost; import forge.game.ai.ComputerUtilCost;
import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseHandler;
@@ -113,7 +113,7 @@ public class DamagePreventAi extends SpellAbilityAi {
if (!threatenedTargets.isEmpty()) { if (!threatenedTargets.isEmpty()) {
// Choose "best" of the remaining to save // Choose "best" of the remaining to save
tgt.addTarget(CardFactoryUtil.getBestCreatureAI(threatenedTargets)); tgt.addTarget(ComputerUtilCard.getBestCreatureAI(threatenedTargets));
chance = true; chance = true;
} }
@@ -211,7 +211,7 @@ public class DamagePreventAi extends SpellAbilityAi {
return true; return true;
} }
tgt.addTarget(CardFactoryUtil.getCheapestPermanentAI(targetables, sa, true)); tgt.addTarget(ComputerUtilCard.getCheapestPermanentAI(targetables, sa, true));
return true; return true;
} }

View File

@@ -11,11 +11,11 @@ import forge.CardLists;
import forge.Singletons; import forge.Singletons;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityAi; import forge.card.ability.SpellAbilityAi;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.Cost; import forge.card.cost.Cost;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.SpellAbilityRestriction; import forge.card.spellability.SpellAbilityRestriction;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilCost; import forge.game.ai.ComputerUtilCost;
import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType; 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); tgt.addTarget(t);
list.remove(t); list.remove(t);
} }
@@ -242,9 +242,9 @@ public class DebuffAi extends SpellAbilityAi {
Card c; Card c;
if (CardLists.getNotType(pref, "Creature").size() == 0) { if (CardLists.getNotType(pref, "Creature").size() == 0) {
c = CardFactoryUtil.getBestCreatureAI(pref); c = ComputerUtilCard.getBestCreatureAI(pref);
} else { } else {
c = CardFactoryUtil.getMostExpensivePermanentAI(pref, sa, true); c = ComputerUtilCard.getMostExpensivePermanentAI(pref, sa, true);
} }
pref.remove(c); pref.remove(c);
@@ -261,9 +261,9 @@ public class DebuffAi extends SpellAbilityAi {
// keyword // keyword
Card c; Card c;
if (CardLists.getNotType(forced, "Creature").size() == 0) { if (CardLists.getNotType(forced, "Creature").size() == 0) {
c = CardFactoryUtil.getWorstCreatureAI(forced); c = ComputerUtilCard.getWorstCreatureAI(forced);
} else { } else {
c = CardFactoryUtil.getCheapestPermanentAI(forced, sa, true); c = ComputerUtilCard.getCheapestPermanentAI(forced, sa, true);
} }
forced.remove(c); forced.remove(c);

View File

@@ -12,13 +12,13 @@ import forge.CounterType;
import forge.Singletons; import forge.Singletons;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityAi; import forge.card.ability.SpellAbilityAi;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.Cost; import forge.card.cost.Cost;
import forge.card.cost.CostPart; import forge.card.cost.CostPart;
import forge.card.cost.CostSacrifice; import forge.card.cost.CostSacrifice;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.ai.ComputerUtil; import forge.game.ai.ComputerUtil;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilCost; import forge.game.ai.ComputerUtilCost;
import forge.game.player.AIPlayer; import forge.game.player.AIPlayer;
import forge.game.player.Player; import forge.game.player.Player;
@@ -130,11 +130,11 @@ public class DestroyAi extends SpellAbilityAi {
Card choice = null; Card choice = null;
// If the targets are only of one type, take the best // If the targets are only of one type, take the best
if (CardLists.getNotType(list, "Creature").isEmpty()) { if (CardLists.getNotType(list, "Creature").isEmpty()) {
choice = CardFactoryUtil.getBestCreatureAI(list); choice = ComputerUtilCard.getBestCreatureAI(list);
} else if (CardLists.getNotType(list, "Land").isEmpty()) { } else if (CardLists.getNotType(list, "Land").isEmpty()) {
choice = CardFactoryUtil.getBestLandAI(list); choice = ComputerUtilCard.getBestLandAI(list);
} else { } else {
choice = CardFactoryUtil.getMostExpensivePermanentAI(list, sa, true); choice = ComputerUtilCard.getMostExpensivePermanentAI(list, sa, true);
} }
if (choice == null) { // can't find anything left if (choice == null) { // can't find anything left
@@ -218,11 +218,11 @@ public class DestroyAi extends SpellAbilityAi {
} else { } else {
Card c; Card c;
if (CardLists.getNotType(preferred, "Creature").size() == 0) { if (CardLists.getNotType(preferred, "Creature").size() == 0) {
c = CardFactoryUtil.getBestCreatureAI(preferred); c = ComputerUtilCard.getBestCreatureAI(preferred);
} else if (CardLists.getNotType(preferred, "Land").size() == 0) { } else if (CardLists.getNotType(preferred, "Land").size() == 0) {
c = CardFactoryUtil.getBestLandAI(preferred); c = ComputerUtilCard.getBestLandAI(preferred);
} else { } else {
c = CardFactoryUtil.getMostExpensivePermanentAI(preferred, sa, false); c = ComputerUtilCard.getMostExpensivePermanentAI(preferred, sa, false);
} }
tgt.addTarget(c); tgt.addTarget(c);
preferred.remove(c); preferred.remove(c);
@@ -235,9 +235,9 @@ public class DestroyAi extends SpellAbilityAi {
} else { } else {
Card c; Card c;
if (CardLists.getNotType(list, "Creature").size() == 0) { if (CardLists.getNotType(list, "Creature").size() == 0) {
c = CardFactoryUtil.getWorstCreatureAI(list); c = ComputerUtilCard.getWorstCreatureAI(list);
} else { } else {
c = CardFactoryUtil.getCheapestPermanentAI(list, sa, false); c = ComputerUtilCard.getCheapestPermanentAI(list, sa, false);
} }
tgt.addTarget(c); tgt.addTarget(c);
list.remove(c); list.remove(c);

View File

@@ -8,10 +8,10 @@ import com.google.common.base.Predicate;
import forge.Card; import forge.Card;
import forge.CardLists; import forge.CardLists;
import forge.card.ability.SpellAbilityAi; import forge.card.ability.SpellAbilityAi;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.Cost; import forge.card.cost.Cost;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilCost; import forge.game.ai.ComputerUtilCost;
import forge.game.ai.ComputerUtilMana; import forge.game.ai.ComputerUtilMana;
import forge.game.player.AIPlayer; 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 // if only creatures are affected evaluate both lists and pass only if
// human creatures are more valuable // human creatures are more valuable
if ((CardLists.getNotType(humanlist, "Creature").size() == 0) && (CardLists.getNotType(computerlist, "Creature").size() == 0)) { 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()) { && !computerlist.isEmpty()) {
return false; return false;
} }
} // otherwise evaluate both lists by CMC and pass only if human } // otherwise evaluate both lists by CMC and pass only if human
// permanents are more valuable // permanents are more valuable
else if (CardFactoryUtil.evaluatePermanentList(computerlist) >= CardFactoryUtil.evaluatePermanentList(humanlist)) { else if (ComputerUtilCard.evaluatePermanentList(computerlist) >= ComputerUtilCard.evaluatePermanentList(humanlist)) {
return false; return false;
} }
return true; return true;
@@ -127,19 +127,19 @@ public class DestroyAllAi extends SpellAbilityAi {
// if only creatures are affected evaluate both lists and pass only if // if only creatures are affected evaluate both lists and pass only if
// human creatures are more valuable // human creatures are more valuable
if ((CardLists.getNotType(humanlist, "Creature").size() == 0) && (CardLists.getNotType(computerlist, "Creature").size() == 0)) { 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)) { .evaluateCreatureList(humanlist)) {
return false; return false;
} }
} // only lands involved } // only lands involved
else if ((CardLists.getNotType(humanlist, "Land").size() == 0) && (CardLists.getNotType(computerlist, "Land").size() == 0)) { 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)) { .evaluatePermanentList(humanlist)) {
return false; return false;
} }
} // otherwise evaluate both lists by CMC and pass only if human } // otherwise evaluate both lists by CMC and pass only if human
// permanents are more valuable // permanents are more valuable
else if ((CardFactoryUtil.evaluatePermanentList(computerlist) + 3) >= CardFactoryUtil else if ((ComputerUtilCard.evaluatePermanentList(computerlist) + 3) >= ComputerUtilCard
.evaluatePermanentList(humanlist)) { .evaluatePermanentList(humanlist)) {
return false; return false;
} }

View File

@@ -9,10 +9,10 @@ import forge.Card;
import forge.CardLists; import forge.CardLists;
import forge.Singletons; import forge.Singletons;
import forge.card.ability.SpellAbilityAi; import forge.card.ability.SpellAbilityAi;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.GameState; import forge.game.GameState;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilCombat; import forge.game.ai.ComputerUtilCombat;
import forge.game.phase.CombatUtil; import forge.game.phase.CombatUtil;
import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseHandler;
@@ -61,7 +61,7 @@ public class EffectAi extends SpellAbilityAi {
List<Card> list = game.getCombat().getAttackerList(); List<Card> list = game.getCombat().getAttackerList();
list = CardLists.getValidCards(list, tgt.getValidTgts(), sa.getActivatingPlayer(), sa.getSourceCard()); list = CardLists.getValidCards(list, tgt.getValidTgts(), sa.getActivatingPlayer(), sa.getSourceCard());
list = CardLists.getTargetableCards(list, sa); list = CardLists.getTargetableCards(list, sa);
Card target = CardFactoryUtil.getBestCreatureAI(list); Card target = ComputerUtilCard.getBestCreatureAI(list);
if (target == null) { if (target == null) {
return false; return false;
} }

View File

@@ -10,9 +10,9 @@ import forge.CardPredicates;
import forge.Singletons; import forge.Singletons;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityAi; import forge.card.ability.SpellAbilityAi;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilCombat; import forge.game.ai.ComputerUtilCombat;
import forge.game.phase.CombatUtil; import forge.game.phase.CombatUtil;
import forge.game.phase.PhaseType; import forge.game.phase.PhaseType;
@@ -86,7 +86,7 @@ public class MustBlockAi extends SpellAbilityAi {
if (list.isEmpty()) { if (list.isEmpty()) {
return false; return false;
} }
final Card blocker = CardFactoryUtil.getBestCreatureAI(list); final Card blocker = ComputerUtilCard.getBestCreatureAI(list);
if (blocker == null) { if (blocker == null) {
return false; return false;
} }

View File

@@ -9,10 +9,10 @@ import forge.CardLists;
import forge.Singletons; import forge.Singletons;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityAi; import forge.card.ability.SpellAbilityAi;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.Cost; import forge.card.cost.Cost;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilCost; import forge.game.ai.ComputerUtilCost;
import forge.game.player.AIPlayer; import forge.game.player.AIPlayer;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
@@ -62,7 +62,7 @@ public class PlayAi extends SpellAbilityAi {
if (cards.isEmpty()) { if (cards.isEmpty()) {
return false; return false;
} }
tgt.addTarget(CardFactoryUtil.getBestAI(cards)); tgt.addTarget(ComputerUtilCard.getBestAI(cards));
} else if (!sa.hasParam("Valid")) { } else if (!sa.hasParam("Valid")) {
cards = new ArrayList<Card>(AbilityUtils.getDefinedCards(sa.getSourceCard(), sa.getParam("Defined"), sa)); cards = new ArrayList<Card>(AbilityUtils.getDefinedCards(sa.getSourceCard(), sa.getParam("Defined"), sa));
if (cards.isEmpty()) { if (cards.isEmpty()) {

View File

@@ -11,11 +11,11 @@ import forge.Constant;
import forge.Singletons; import forge.Singletons;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityAi; import forge.card.ability.SpellAbilityAi;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.Cost; import forge.card.cost.Cost;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.GameState; import forge.game.GameState;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilCombat; import forge.game.ai.ComputerUtilCombat;
import forge.game.ai.ComputerUtilCost; import forge.game.ai.ComputerUtilCost;
import forge.game.phase.PhaseType; import forge.game.phase.PhaseType;
@@ -86,7 +86,7 @@ public class ProtectAi extends SpellAbilityAi {
// will the creature attack (only relevant for sorcery speed)? // will the creature attack (only relevant for sorcery speed)?
if (game.getPhaseHandler().getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS) if (game.getPhaseHandler().getPhase().isBefore(PhaseType.COMBAT_DECLARE_ATTACKERS)
&& game.getPhaseHandler().isPlayerTurn(ai) && game.getPhaseHandler().isPlayerTurn(ai)
&& CardFactoryUtil.doesCreatureAttackAI(ai, c)) { && ComputerUtilCard.doesCreatureAttackAI(ai, c)) {
return true; return true;
} }
@@ -241,7 +241,7 @@ public class ProtectAi extends SpellAbilityAi {
} }
} }
t = CardFactoryUtil.getBestCreatureAI(list); t = ComputerUtilCard.getBestCreatureAI(list);
tgt.addTarget(t); tgt.addTarget(t);
list.remove(t); list.remove(t);
} }
@@ -290,9 +290,9 @@ public class ProtectAi extends SpellAbilityAi {
Card c; Card c;
if (CardLists.getNotType(pref, "Creature").size() == 0) { if (CardLists.getNotType(pref, "Creature").size() == 0) {
c = CardFactoryUtil.getBestCreatureAI(pref); c = ComputerUtilCard.getBestCreatureAI(pref);
} else { } else {
c = CardFactoryUtil.getMostExpensivePermanentAI(pref, sa, true); c = ComputerUtilCard.getMostExpensivePermanentAI(pref, sa, true);
} }
pref.remove(c); pref.remove(c);
@@ -307,9 +307,9 @@ public class ProtectAi extends SpellAbilityAi {
Card c; Card c;
if (CardLists.getNotType(pref2, "Creature").size() == 0) { if (CardLists.getNotType(pref2, "Creature").size() == 0) {
c = CardFactoryUtil.getBestCreatureAI(pref2); c = ComputerUtilCard.getBestCreatureAI(pref2);
} else { } else {
c = CardFactoryUtil.getMostExpensivePermanentAI(pref2, sa, true); c = ComputerUtilCard.getMostExpensivePermanentAI(pref2, sa, true);
} }
pref2.remove(c); pref2.remove(c);
@@ -324,9 +324,9 @@ public class ProtectAi extends SpellAbilityAi {
Card c; Card c;
if (CardLists.getNotType(forced, "Creature").size() == 0) { if (CardLists.getNotType(forced, "Creature").size() == 0) {
c = CardFactoryUtil.getWorstCreatureAI(forced); c = ComputerUtilCard.getWorstCreatureAI(forced);
} else { } else {
c = CardFactoryUtil.getCheapestPermanentAI(forced, sa, true); c = ComputerUtilCard.getCheapestPermanentAI(forced, sa, true);
} }
forced.remove(c); forced.remove(c);

View File

@@ -11,13 +11,13 @@ import forge.Singletons;
import forge.CardPredicates.Presets; import forge.CardPredicates.Presets;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityAi; import forge.card.ability.SpellAbilityAi;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.Cost; import forge.card.cost.Cost;
import forge.card.cost.CostUtil; import forge.card.cost.CostUtil;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.SpellAbilityRestriction; import forge.card.spellability.SpellAbilityRestriction;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.ai.ComputerUtil; import forge.game.ai.ComputerUtil;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilCost; import forge.game.ai.ComputerUtilCost;
import forge.game.ai.ComputerUtilMana; import forge.game.ai.ComputerUtilMana;
import forge.game.phase.PhaseHandler; 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); tgt.addTarget(t);
list.remove(t); list.remove(t);
} }
@@ -303,9 +303,9 @@ public class PumpAi extends PumpAiBase {
Card c; Card c;
if (CardLists.getNotType(pref, "Creature").size() == 0) { if (CardLists.getNotType(pref, "Creature").size() == 0) {
c = CardFactoryUtil.getBestCreatureAI(pref); c = ComputerUtilCard.getBestCreatureAI(pref);
} else { } else {
c = CardFactoryUtil.getMostExpensivePermanentAI(pref, sa, true); c = ComputerUtilCard.getMostExpensivePermanentAI(pref, sa, true);
} }
pref.remove(c); pref.remove(c);
@@ -320,9 +320,9 @@ public class PumpAi extends PumpAiBase {
Card c; Card c;
if (CardLists.getNotType(forced, "Creature").size() == 0) { if (CardLists.getNotType(forced, "Creature").size() == 0) {
c = CardFactoryUtil.getWorstCreatureAI(forced); c = ComputerUtilCard.getWorstCreatureAI(forced);
} else { } else {
c = CardFactoryUtil.getCheapestPermanentAI(forced, sa, true); c = ComputerUtilCard.getCheapestPermanentAI(forced, sa, true);
} }
forced.remove(c); forced.remove(c);

View File

@@ -13,10 +13,10 @@ import forge.CardPredicates;
import forge.CardUtil; import forge.CardUtil;
import forge.Singletons; import forge.Singletons;
import forge.card.ability.SpellAbilityAi; import forge.card.ability.SpellAbilityAi;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.game.GameState; import forge.game.GameState;
import forge.game.ai.ComputerUtil; import forge.game.ai.ComputerUtil;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilCombat; import forge.game.ai.ComputerUtilCombat;
import forge.game.phase.Combat; import forge.game.phase.Combat;
import forge.game.phase.CombatUtil; import forge.game.phase.CombatUtil;
@@ -403,7 +403,7 @@ public abstract class PumpAiBase extends SpellAbilityAi {
&& phase.isPlayerTurn(ai) && phase.isPlayerTurn(ai)
&& SpellAbilityAi.isSorcerySpeed(sa) && SpellAbilityAi.isSorcerySpeed(sa)
&& attack > 0 && attack > 0
&& CardFactoryUtil.doesCreatureAttackAI(ai, c)) { && ComputerUtilCard.doesCreatureAttackAI(ai, c)) {
return true; return true;
} }

View File

@@ -10,9 +10,9 @@ import forge.Card;
import forge.CardLists; import forge.CardLists;
import forge.Singletons; import forge.Singletons;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilCombat; import forge.game.ai.ComputerUtilCombat;
import forge.game.ai.ComputerUtil; import forge.game.ai.ComputerUtil;
import forge.game.phase.CombatUtil; 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 // evaluate both lists and pass only if human creatures are more
// valuable // valuable
if ((CardFactoryUtil.evaluateCreatureList(comp) + 200) >= CardFactoryUtil.evaluateCreatureList(human)) { if ((ComputerUtilCard.evaluateCreatureList(comp) + 200) >= ComputerUtilCard.evaluateCreatureList(human)) {
return false; return false;
} }
return true; return true;

View File

@@ -27,11 +27,11 @@ import forge.CardPredicates;
import forge.Singletons; import forge.Singletons;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityAi; import forge.card.ability.SpellAbilityAi;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.Cost; import forge.card.cost.Cost;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.ai.ComputerUtil; import forge.game.ai.ComputerUtil;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilCombat; import forge.game.ai.ComputerUtilCombat;
import forge.game.ai.ComputerUtilCost; import forge.game.ai.ComputerUtilCost;
import forge.game.phase.PhaseType; import forge.game.phase.PhaseType;
@@ -132,7 +132,7 @@ public class RegenerateAi extends SpellAbilityAi {
if (!threatenedTargets.isEmpty()) { if (!threatenedTargets.isEmpty()) {
// Choose "best" of the remaining to regenerate // Choose "best" of the remaining to regenerate
tgt.addTarget(CardFactoryUtil.getBestCreatureAI(threatenedTargets)); tgt.addTarget(ComputerUtilCard.getBestCreatureAI(threatenedTargets));
chance = true; chance = true;
} }
} else { } 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; return true;
} }

View File

@@ -5,9 +5,9 @@ import forge.Card;
import forge.CardLists; import forge.CardLists;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityAi; import forge.card.ability.SpellAbilityAi;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilMana; import forge.game.ai.ComputerUtilMana;
import forge.game.player.AIPlayer; import forge.game.player.AIPlayer;
import forge.game.player.Player; import forge.game.player.Player;
@@ -128,7 +128,7 @@ public class SacrificeAi extends SpellAbilityAi {
List<Card> computerList = List<Card> computerList =
CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), valid.split(","), sa.getActivatingPlayer(), sa.getSourceCard()); CardLists.getValidCards(ai.getCardsIn(ZoneType.Battlefield), valid.split(","), sa.getActivatingPlayer(), sa.getSourceCard());
for (Card c : computerList) { for (Card c : computerList) {
if (!c.getSVar("SacMe").equals("") || CardFactoryUtil.evaluateCreature(c) <= 135) { if (!c.getSVar("SacMe").equals("") || ComputerUtilCard.evaluateCreature(c) <= 135) {
return true; return true;
} }
} }

View File

@@ -6,9 +6,9 @@ import java.util.Random;
import forge.Card; import forge.Card;
import forge.CardLists; import forge.CardLists;
import forge.card.ability.SpellAbilityAi; import forge.card.ability.SpellAbilityAi;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.Cost; import forge.card.cost.Cost;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilCost; import forge.game.ai.ComputerUtilCost;
import forge.game.ai.ComputerUtilMana; import forge.game.ai.ComputerUtilMana;
import forge.game.player.AIPlayer; 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 // if only creatures are affected evaluate both lists and pass only if
// human creatures are more valuable // human creatures are more valuable
if ((CardLists.getNotType(humanlist, "Creature").size() == 0) && (CardLists.getNotType(computerlist, "Creature").size() == 0)) { 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)) { .evaluateCreatureList(humanlist)) {
return false; return false;
} }
} // only lands involved } // only lands involved
else if ((CardLists.getNotType(humanlist, "Land").size() == 0) && (CardLists.getNotType(computerlist, "Land").size() == 0)) { 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)) { .evaluatePermanentList(humanlist)) {
return false; return false;
} }
} // otherwise evaluate both lists by CMC and pass only if human } // otherwise evaluate both lists by CMC and pass only if human
// permanents are more valuable // permanents are more valuable
else if ((CardFactoryUtil.evaluatePermanentList(computerlist) + 3) >= CardFactoryUtil else if ((ComputerUtilCard.evaluatePermanentList(computerlist) + 3) >= ComputerUtilCard
.evaluatePermanentList(humanlist)) { .evaluatePermanentList(humanlist)) {
return false; return false;
} }

View File

@@ -11,10 +11,10 @@ import forge.CardPredicates;
import forge.Singletons; import forge.Singletons;
import forge.CardPredicates.Presets; import forge.CardPredicates.Presets;
import forge.card.ability.SpellAbilityAi; import forge.card.ability.SpellAbilityAi;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.ai.ComputerUtil; import forge.game.ai.ComputerUtil;
import forge.game.ai.ComputerUtilCard;
import forge.game.phase.CombatUtil; import forge.game.phase.CombatUtil;
import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType; import forge.game.phase.PhaseType;
@@ -69,9 +69,9 @@ public abstract class TapAiBase extends SpellAbilityAi {
if (CardLists.getNotType(tapList, "Creature").size() == 0) { if (CardLists.getNotType(tapList, "Creature").size() == 0) {
// if only creatures take the best // if only creatures take the best
choice = CardFactoryUtil.getBestCreatureAI(tapList); choice = ComputerUtilCard.getBestCreatureAI(tapList);
} else { } else {
choice = CardFactoryUtil.getMostExpensivePermanentAI(tapList, sa, false); choice = ComputerUtilCard.getMostExpensivePermanentAI(tapList, sa, false);
} }
if (choice == null) { // can't find anything left if (choice == null) { // can't find anything left
@@ -179,9 +179,9 @@ public abstract class TapAiBase extends SpellAbilityAi {
Predicate<Card> findBlockers = CardPredicates.possibleBlockerForAtLeastOne(attackers); Predicate<Card> findBlockers = CardPredicates.possibleBlockerForAtLeastOne(attackers);
List<Card> creatureList = CardLists.filter(tapList, findBlockers); List<Card> creatureList = CardLists.filter(tapList, findBlockers);
if (!attackers.isEmpty() && !creatureList.isEmpty()) { if (!attackers.isEmpty() && !creatureList.isEmpty()) {
choice = CardFactoryUtil.getBestCreatureAI(creatureList); choice = ComputerUtilCard.getBestCreatureAI(creatureList);
} else if (sa.isTrigger()) { } else if (sa.isTrigger()) {
choice = CardFactoryUtil.getMostExpensivePermanentAI(tapList, sa, false); choice = ComputerUtilCard.getMostExpensivePermanentAI(tapList, sa, false);
} }
} else if (phase.isPlayerTurn(opp) } else if (phase.isPlayerTurn(opp)
@@ -194,12 +194,12 @@ public abstract class TapAiBase extends SpellAbilityAi {
return c.isCreature() && CombatUtil.canAttack(c, opp); return c.isCreature() && CombatUtil.canAttack(c, opp);
} }
}); });
choice = CardFactoryUtil.getBestCreatureAI(creatureList); choice = ComputerUtilCard.getBestCreatureAI(creatureList);
} else { // no creatures available } else { // no creatures available
choice = CardFactoryUtil.getMostExpensivePermanentAI(tapList, sa, false); choice = ComputerUtilCard.getMostExpensivePermanentAI(tapList, sa, false);
} }
} else { } else {
choice = CardFactoryUtil.getMostExpensivePermanentAI(tapList, sa, false); choice = ComputerUtilCard.getMostExpensivePermanentAI(tapList, sa, false);
} }
if (choice == null) { // can't find anything left if (choice == null) { // can't find anything left

View File

@@ -7,10 +7,10 @@ import forge.Card;
import forge.Singletons; import forge.Singletons;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityAi; import forge.card.ability.SpellAbilityAi;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.Cost; import forge.card.cost.Cost;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilMana; import forge.game.ai.ComputerUtilMana;
import forge.game.phase.PhaseType; import forge.game.phase.PhaseType;
import forge.game.player.AIPlayer; import forge.game.player.AIPlayer;
@@ -84,7 +84,7 @@ public class UnattachAllAi extends SpellAbilityAi {
//don't equip a worse creature //don't equip a worse creature
if (card.isEquipping()) { if (card.isEquipping()) {
Card oldTarget = card.getEquipping().get(0); Card oldTarget = card.getEquipping().get(0);
if (CardFactoryUtil.evaluateCreature(oldTarget) > CardFactoryUtil.evaluateCreature(newTarget)) { if (ComputerUtilCard.evaluateCreature(oldTarget) > ComputerUtilCard.evaluateCreature(newTarget)) {
return false; return false;
} }
} }

View File

@@ -9,10 +9,10 @@ import forge.Singletons;
import forge.CardPredicates.Presets; import forge.CardPredicates.Presets;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityAi; import forge.card.ability.SpellAbilityAi;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.Cost; import forge.card.cost.Cost;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilCost; import forge.game.ai.ComputerUtilCost;
import forge.game.player.AIPlayer; import forge.game.player.AIPlayer;
import forge.game.player.Player; import forge.game.player.Player;
@@ -148,14 +148,14 @@ public class UntapAi extends SpellAbilityAi {
} }
if (CardLists.getNotType(untapList, "Creature").size() == 0) { if (CardLists.getNotType(untapList, "Creature").size() == 0) {
choice = CardFactoryUtil.getBestCreatureAI(untapList); // if choice = ComputerUtilCard.getBestCreatureAI(untapList); // if
// only // only
// creatures // creatures
// take // take
// the // the
// best // best
} else { } else {
choice = CardFactoryUtil.getMostExpensivePermanentAI(untapList, sa, false); choice = ComputerUtilCard.getMostExpensivePermanentAI(untapList, sa, false);
} }
if (choice == null) { // can't find anything left if (choice == null) { // can't find anything left
@@ -267,13 +267,13 @@ public class UntapAi extends SpellAbilityAi {
} }
if (CardLists.getNotType(tapList, "Creature").size() == 0) { if (CardLists.getNotType(tapList, "Creature").size() == 0) {
choice = CardFactoryUtil.getBestCreatureAI(tapList); // if only choice = ComputerUtilCard.getBestCreatureAI(tapList); // if only
// creatures // creatures
// take // take
// the // the
// best // best
} else { } else {
choice = CardFactoryUtil.getMostExpensivePermanentAI(tapList, sa, false); choice = ComputerUtilCard.getMostExpensivePermanentAI(tapList, sa, false);
} }
if (choice == null) { // can't find anything left if (choice == null) { // can't find anything left

View File

@@ -13,11 +13,11 @@ import forge.Singletons;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityEffect; import forge.card.ability.SpellAbilityEffect;
import forge.card.ability.ai.ChangeZoneAi; import forge.card.ability.ai.ChangeZoneAi;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.AbilitySub; import forge.card.spellability.AbilitySub;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.SpellAbilityStackInstance; import forge.card.spellability.SpellAbilityStackInstance;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCard;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.zone.Zone; import forge.game.zone.Zone;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
@@ -403,7 +403,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
attachedTo = list.get(0); attachedTo = list.get(0);
} }
} else { // AI player } else { // AI player
attachedTo = CardFactoryUtil.getBestAI(list); attachedTo = ComputerUtilCard.getBestAI(list);
} }
if (tgtC.isAura()) { if (tgtC.isAura()) {
if (tgtC.isEnchanting()) { if (tgtC.isEnchanting()) {

View File

@@ -74,52 +74,19 @@ public class ChooseCardEffect extends SpellAbilityEffect {
for (final Player p : tgtPlayers) { for (final Player p : tgtPlayers) {
if ((tgt == null) || p.canBeTargetedBy(sa)) { if ((tgt == null) || p.canBeTargetedBy(sa)) {
for (int i = 0; i < validAmount; i++) { for (int i = 0; i < validAmount; i++) {
if (p.isHuman()) {
final String choiceTitle = sa.hasParam("ChoiceTitle") ? sa.getParam("ChoiceTitle") : "Choose a card "; Card c;
Card o; if (sa.hasParam("AtRandom")) {
if (sa.hasParam("AtRandom")) { c = Aggregates.random(choices);
o = Aggregates.random(choices); } else {
} else if (sa.hasParam("Mandatory")) { c = p.getController().chooseSingleCardForEffect(choices, sa, sa.hasParam("ChoiceTitle") ? sa.getParam("ChoiceTitle") : "Choose a card ", !sa.hasParam("Mandatory"));
o = GuiChoose.one(choiceTitle, choices); }
} else {
o = GuiChoose.oneOrNone(choiceTitle, choices); if (c != null) {
} chosen.add(c);
if (o != null) { choices.remove(c);
chosen.add(o); } else {
choices.remove(o); break;
} 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;
}
} }
} }
host.setChosenCard(chosen); host.setChosenCard(chosen);

View File

@@ -16,9 +16,9 @@ import forge.Singletons;
import forge.CardPredicates.Presets; import forge.CardPredicates.Presets;
import forge.card.CardRulesPredicates; import forge.card.CardRulesPredicates;
import forge.card.ability.SpellAbilityEffect; import forge.card.ability.SpellAbilityEffect;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCard;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
import forge.gui.GuiChoose; import forge.gui.GuiChoose;
@@ -90,9 +90,9 @@ public class ChooseCardNameEffect extends SpellAbilityEffect {
if (sa.hasParam("AILogic")) { if (sa.hasParam("AILogic")) {
final String logic = sa.getParam("AILogic"); final String logic = sa.getParam("AILogic");
if (logic.equals("MostProminentInComputerDeck")) { if (logic.equals("MostProminentInComputerDeck")) {
chosen = CardFactoryUtil.getMostProminentCardName(p.getCardsIn(ZoneType.Library)); chosen = ComputerUtilCard.getMostProminentCardName(p.getCardsIn(ZoneType.Library));
} else if (logic.equals("MostProminentInHumanDeck")) { } else if (logic.equals("MostProminentInHumanDeck")) {
chosen = CardFactoryUtil.getMostProminentCardName(p.getOpponent().getCardsIn(ZoneType.Library)); chosen = ComputerUtilCard.getMostProminentCardName(p.getOpponent().getCardsIn(ZoneType.Library));
} }
} else { } else {
List<Card> list = CardLists.filterControlledBy(Singletons.getModel().getGame().getCardsInGame(), p.getOpponent()); List<Card> list = CardLists.filterControlledBy(Singletons.getModel().getGame().getCardsInGame(), p.getOpponent());

View File

@@ -9,9 +9,9 @@ import forge.CardPredicates;
import forge.Constant; import forge.Constant;
import forge.Singletons; import forge.Singletons;
import forge.card.ability.SpellAbilityEffect; import forge.card.ability.SpellAbilityEffect;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCard;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
import forge.gui.GuiChoose; import forge.gui.GuiChoose;
@@ -69,36 +69,36 @@ public class ChooseColorEffect extends SpellAbilityEffect {
if (sa.hasParam("AILogic")) { if (sa.hasParam("AILogic")) {
final String logic = sa.getParam("AILogic"); final String logic = sa.getParam("AILogic");
if (logic.equals("MostProminentInHumanDeck")) { 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")) { } 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")) { } else if (logic.equals("MostProminentDualInComputerDeck")) {
List<String> prominence = CardFactoryUtil.getColorByProminence(CardLists.filterControlledBy(Singletons.getModel().getGame().getCardsInGame(), ai)); List<String> prominence = ComputerUtilCard.getColorByProminence(CardLists.filterControlledBy(Singletons.getModel().getGame().getCardsInGame(), ai));
chosen.add(prominence.get(0)); chosen.add(prominence.get(0));
chosen.add(prominence.get(1)); chosen.add(prominence.get(1));
} }
else if (logic.equals("MostProminentInGame")) { 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")) { else if (logic.equals("MostProminentHumanCreatures")) {
List<Card> list = opp.getCreaturesInPlay(); List<Card> list = opp.getCreaturesInPlay();
if (list.isEmpty()) { if (list.isEmpty()) {
list = CardLists.filter(CardLists.filterControlledBy(Singletons.getModel().getGame().getCardsInGame(), opp), CardPredicates.Presets.CREATURES); 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")) { 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")) { 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")) { else if (logic.equals("MostProminentPermanent")) {
final List<Card> list = Singletons.getModel().getGame().getCardsIn(ZoneType.Battlefield); final List<Card> list = Singletons.getModel().getGame().getCardsIn(ZoneType.Battlefield);
chosen.add(CardFactoryUtil.getMostProminentColor(list)); chosen.add(ComputerUtilCard.getMostProminentColor(list));
} }
else if (logic.equals("MostProminentAttackers")) { else if (logic.equals("MostProminentAttackers")) {
chosen.add(CardFactoryUtil.getMostProminentColor(Singletons.getModel().getGame().getCombat() chosen.add(ComputerUtilCard.getMostProminentColor(Singletons.getModel().getGame().getCombat()
.getAttackerList())); .getAttackerList()));
} }
else if (logic.equals("MostProminentKeywordInComputerDeck")) { else if (logic.equals("MostProminentKeywordInComputerDeck")) {

View File

@@ -14,6 +14,7 @@ import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.SpellAbilityStackInstance; import forge.card.spellability.SpellAbilityStackInstance;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilCombat; import forge.game.ai.ComputerUtilCombat;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
@@ -181,10 +182,10 @@ public class ChooseSourceEffect extends SpellAbilityEffect {
return ComputerUtilCombat.damageIfUnblocked(c, ai, Singletons.getModel().getGame().getCombat()) > 0; return ComputerUtilCombat.damageIfUnblocked(c, ai, Singletons.getModel().getGame().getCombat()) > 0;
} }
}); });
chosen.add(CardFactoryUtil.getBestCreatureAI(sourcesToChooseFrom)); chosen.add(ComputerUtilCard.getBestCreatureAI(sourcesToChooseFrom));
} }
} else { } else {
chosen.add(CardFactoryUtil.getBestAI(sourcesToChooseFrom)); chosen.add(ComputerUtilCard.getBestAI(sourcesToChooseFrom));
} }
} }
} }

View File

@@ -13,9 +13,9 @@ import forge.Constant;
import forge.Singletons; import forge.Singletons;
import forge.card.CardType; import forge.card.CardType;
import forge.card.ability.SpellAbilityEffect; import forge.card.ability.SpellAbilityEffect;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCard;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
import forge.gui.GuiChoose; import forge.gui.GuiChoose;
@@ -103,22 +103,22 @@ public class ChooseTypeEffect extends SpellAbilityEffect {
if (sa.hasParam("AILogic")) { if (sa.hasParam("AILogic")) {
final String logic = sa.getParam("AILogic"); final String logic = sa.getParam("AILogic");
if (logic.equals("MostProminentOnBattlefield")) { 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")) { else if (logic.equals("MostProminentComputerControls")) {
chosen = CardFactoryUtil.getMostProminentCreatureType(ai.getCardsIn(ZoneType.Battlefield)); chosen = ComputerUtilCard.getMostProminentCreatureType(ai.getCardsIn(ZoneType.Battlefield));
} }
else if (logic.equals("MostProminentHumanControls")) { 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)) { 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")) { 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")) { 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)) { if (!CardType.isACreatureType(chosen) || invalidTypes.contains(chosen)) {

View File

@@ -12,9 +12,9 @@ import forge.CardLists;
import forge.Singletons; import forge.Singletons;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityEffect; import forge.card.ability.SpellAbilityEffect;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCard;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.zone.PlayerZone; import forge.game.zone.PlayerZone;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
@@ -195,9 +195,9 @@ public class DigEffect extends SpellAbilityEffect {
chosen = GuiChoose.one(prompt + destZone2, valid); chosen = GuiChoose.one(prompt + destZone2, valid);
movedCards.remove(chosen); movedCards.remove(chosen);
} else { // Computer } else { // Computer
Card chosen = CardFactoryUtil.getBestAI(valid); Card chosen = ComputerUtilCard.getBestAI(valid);
if (sa.getActivatingPlayer().isHuman() && p.isHuman()) { if (sa.getActivatingPlayer().isHuman() && p.isHuman()) {
chosen = CardFactoryUtil.getWorstAI(valid); chosen = ComputerUtilCard.getWorstAI(valid);
} }
movedCards.remove(chosen); movedCards.remove(chosen);
} }
@@ -250,9 +250,9 @@ public class DigEffect extends SpellAbilityEffect {
changeNum = valid.size(); // always take all changeNum = valid.size(); // always take all
} }
for (j = 0; j < changeNum; j++) { for (j = 0; j < changeNum; j++) {
Card chosen = CardFactoryUtil.getBestAI(valid); Card chosen = ComputerUtilCard.getBestAI(valid);
if (sa.getActivatingPlayer().isHuman() && p.isHuman()) { if (sa.getActivatingPlayer().isHuman() && p.isHuman()) {
chosen = CardFactoryUtil.getWorstAI(valid); chosen = ComputerUtilCard.getWorstAI(valid);
} }
if (chosen == null) { if (chosen == null) {
break; break;

View File

@@ -15,6 +15,7 @@ import forge.card.ability.AbilityUtils;
import forge.card.cardfactory.CardFactoryUtil; import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCard;
import forge.game.player.AIPlayer; import forge.game.player.AIPlayer;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
@@ -109,9 +110,9 @@ public class DiscardEffect extends RevealEffectBase {
if (sa.hasParam("DiscardValid")) { if (sa.hasParam("DiscardValid")) {
final String validString = sa.getParam("DiscardValid"); final String validString = sa.getParam("DiscardValid");
if (validString.contains("Creature") && !validString.contains("nonCreature")) { if (validString.contains("Creature") && !validString.contains("nonCreature")) {
final Card c = CardFactoryUtil.getBestCreatureAI(goodChoices); final Card c = ComputerUtilCard.getBestCreatureAI(goodChoices);
if (c != null) { if (c != null) {
dChoices.add(CardFactoryUtil.getBestCreatureAI(goodChoices)); dChoices.add(ComputerUtilCard.getBestCreatureAI(goodChoices));
} }
} }
} }

View File

@@ -5,16 +5,12 @@ import java.util.List;
import forge.Card; import forge.Card;
import forge.CardLists; import forge.CardLists;
import forge.Singletons; import forge.Singletons;
import forge.CardPredicates.Presets;
import forge.card.ability.SpellAbilityEffect; import forge.card.ability.SpellAbilityEffect;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.trigger.Trigger; import forge.card.trigger.Trigger;
import forge.card.trigger.TriggerHandler; import forge.card.trigger.TriggerHandler;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
import forge.gui.GuiChoose;
import forge.gui.GuiDialog;
public class EncodeEffect extends SpellAbilityEffect { public class EncodeEffect extends SpellAbilityEffect {
@Override @Override
@@ -43,10 +39,11 @@ public class EncodeEffect extends SpellAbilityEffect {
} }
// Handle choice of whether or not to encoded // Handle choice of whether or not to encoded
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
sb.append("Do you want to exile " + host + " and encode it onto a creature you control?"); sb.append("Do you want to exile " + host + " and encode it onto a creature you control?");
if (player.isHuman() if (!player.getController().confirmAction(sa, null, sb.toString())) {
&& !GuiDialog.confirm(host, sb.toString())) {
return; return;
} }
// Note: AI will always choose to encode // 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); Card movedCard = Singletons.getModel().getGame().getAction().moveTo(ZoneType.Exile, host);
// choose a creature // choose a creature
Card choice = null; Card choice = player.getController().chooseSingleCardForEffect(choices, sa, "Choose a creature you control to encode ", true);
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);
}
}
if (choice == null) { if (choice == null) {
return; return;
} }

View File

@@ -9,11 +9,11 @@ import forge.Singletons;
import forge.card.MagicColor; import forge.card.MagicColor;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityEffect; import forge.card.ability.SpellAbilityEffect;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.AbilityManaPart; import forge.card.spellability.AbilityManaPart;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.GameActionUtil; import forge.game.GameActionUtil;
import forge.game.ai.ComputerUtilCard;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
import forge.gui.GuiChoose; import forge.gui.GuiChoose;
@@ -82,7 +82,7 @@ public class ManaEffect extends SpellAbilityEffect {
final String logic = sa.getParam("AILogic"); final String logic = sa.getParam("AILogic");
String chosen = Constant.Color.BLACK; String chosen = Constant.Color.BLACK;
if (logic.equals("MostProminentInComputerHand")) { if (logic.equals("MostProminentInComputerHand")) {
chosen = CardFactoryUtil.getMostProminentColor(activator.getCardsIn( chosen = ComputerUtilCard.getMostProminentColor(activator.getCardsIn(
ZoneType.Hand)); ZoneType.Hand));
} }
if (chosen.equals("")) { if (chosen.equals("")) {
@@ -141,7 +141,7 @@ public class ManaEffect extends SpellAbilityEffect {
final String logic = sa.getParam("AILogic"); final String logic = sa.getParam("AILogic");
String chosen = Constant.Color.BLACK; String chosen = Constant.Color.BLACK;
if (logic.equals("MostProminentInComputerHand")) { 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}); GuiChoose.one("Computer picked: ", new String[]{chosen});
abMana.setExpressChoice(MagicColor.toShortString(chosen)); abMana.setExpressChoice(MagicColor.toShortString(chosen));

View File

@@ -13,7 +13,6 @@ import forge.CardLists;
import forge.Singletons; import forge.Singletons;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityEffect; import forge.card.ability.SpellAbilityEffect;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.Cost; import forge.card.cost.Cost;
import forge.card.cost.CostPartMana; import forge.card.cost.CostPartMana;
import forge.card.cost.CostPart; import forge.card.cost.CostPart;
@@ -23,6 +22,7 @@ import forge.card.spellability.SpellAbility;
import forge.card.spellability.SpellAbilityRestriction; import forge.card.spellability.SpellAbilityRestriction;
import forge.game.GameState; import forge.game.GameState;
import forge.game.ai.ComputerUtil; import forge.game.ai.ComputerUtil;
import forge.game.ai.ComputerUtilCard;
import forge.game.player.AIPlayer; import forge.game.player.AIPlayer;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
@@ -126,7 +126,7 @@ public class PlayEffect extends SpellAbilityEffect {
return true; return true;
} }
}); });
tgtCard = CardFactoryUtil.getBestAI(tgtCards); tgtCard = ComputerUtilCard.getBestAI(tgtCards);
if (tgtCard == null) { if (tgtCard == null) {
return; return;
} }

View File

@@ -13,9 +13,9 @@ import forge.Command;
import forge.Singletons; import forge.Singletons;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityEffect; import forge.card.ability.SpellAbilityEffect;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCard;
import forge.game.player.Player; import forge.game.player.Player;
import forge.gui.GuiChoose; import forge.gui.GuiChoose;
@@ -124,7 +124,7 @@ public class ProtectEffect extends SpellAbilityEffect {
list = CardLists.filterControlledBy(Singletons.getModel().getGame().getCardsInGame(), ai.getOpponents()); list = CardLists.filterControlledBy(Singletons.getModel().getGame().getCardsInGame(), ai.getOpponents());
} }
if (!list.isEmpty()) { if (!list.isEmpty()) {
choice = CardFactoryUtil.getMostProminentColor(list); choice = ComputerUtilCard.getMostProminentColor(list);
} }
} }
} }

View File

@@ -9,10 +9,10 @@ import forge.CardLists;
import forge.card.ability.AbilityFactory; import forge.card.ability.AbilityFactory;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityEffect; import forge.card.ability.SpellAbilityEffect;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.AbilitySub; import forge.card.spellability.AbilitySub;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCard;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
import forge.gui.GuiChoose; import forge.gui.GuiChoose;
@@ -221,11 +221,11 @@ public class TwoPilesEffect extends SpellAbilityEffect {
break; break;
} }
} else { } else {
int cmc1 = CardFactoryUtil.evaluatePermanentList(new ArrayList<Card>(pile1)); int cmc1 = ComputerUtilCard.evaluatePermanentList(new ArrayList<Card>(pile1));
int cmc2 = CardFactoryUtil.evaluatePermanentList(new ArrayList<Card>(pile2)); int cmc2 = ComputerUtilCard.evaluatePermanentList(new ArrayList<Card>(pile2));
if (CardLists.getNotType(pool, "Creature").isEmpty()) { if (CardLists.getNotType(pool, "Creature").isEmpty()) {
cmc1 = CardFactoryUtil.evaluateCreatureList(new ArrayList<Card>(pile1)); cmc1 = ComputerUtilCard.evaluateCreatureList(new ArrayList<Card>(pile1));
cmc2 = CardFactoryUtil.evaluateCreatureList(new ArrayList<Card>(pile2)); cmc2 = ComputerUtilCard.evaluateCreatureList(new ArrayList<Card>(pile2));
System.out.println("value:" + cmc1 + " " + cmc2); System.out.println("value:" + cmc1 + " " + cmc2);
} }

View File

@@ -12,6 +12,7 @@ import forge.card.ability.SpellAbilityEffect;
import forge.card.cardfactory.CardFactoryUtil; import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target; import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCard;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
@@ -86,7 +87,7 @@ public class UntapEffect extends SpellAbilityEffect {
while ((list.size() != 0) && (count < num)) { while ((list.size() != 0) && (count < num)) {
for (int i = 0; (i < list.size()) && (count < num); i++) { for (int i = 0; (i < list.size()) && (count < num); i++) {
final Card c = CardFactoryUtil.getBestLandAI(list); final Card c = ComputerUtilCard.getBestLandAI(list);
c.untap(); c.untap();
list.remove(c); list.remove(c);
count++; count++;

View File

@@ -50,6 +50,7 @@ import forge.card.trigger.Trigger;
import forge.card.trigger.TriggerHandler; import forge.card.trigger.TriggerHandler;
import forge.control.input.Input; import forge.control.input.Input;
import forge.control.input.InputSelectManyCards; import forge.control.input.InputSelectManyCards;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilCombat; import forge.game.ai.ComputerUtilCombat;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.zone.PlayerZone; import forge.game.zone.PlayerZone;
@@ -190,7 +191,7 @@ public class CardFactoryCreatures {
} }
this.getTarget().resetTargets(); this.getTarget().resetTargets();
this.setTargetCard(CardFactoryUtil.getBestCreatureAI(targetables)); this.setTargetCard(ComputerUtilCard.getBestCreatureAI(targetables));
return true; return true;
} }
@@ -262,7 +263,7 @@ public class CardFactoryCreatures {
// Kill Wolves that can be killed first // Kill Wolves that can be killed first
if (wolvesLeft.size() > 0) { if (wolvesLeft.size() > 0) {
final Card best = CardFactoryUtil.getBestCreatureAI(wolvesLeft); final Card best = ComputerUtilCard.getBestCreatureAI(wolvesLeft);
best.addDamage(1, target); best.addDamage(1, target);
if ((ComputerUtilCombat.getDamageToKill(best) <= 0) || target.hasKeyword("Deathtouch")) { if ((ComputerUtilCombat.getDamageToKill(best) <= 0) || target.hasKeyword("Deathtouch")) {
wolvesLeft.remove(best); wolvesLeft.remove(best);

View File

@@ -18,17 +18,12 @@
package forge.card.cardfactory; package forge.card.cardfactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; 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.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
@@ -45,7 +40,6 @@ import forge.CounterType;
import forge.GameEntity; import forge.GameEntity;
import forge.Singletons; import forge.Singletons;
import forge.card.CardCharacteristics; import forge.card.CardCharacteristics;
import forge.card.CardType;
import forge.card.MagicColor; import forge.card.MagicColor;
import forge.card.ability.AbilityFactory; import forge.card.ability.AbilityFactory;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
@@ -71,8 +65,8 @@ import forge.card.trigger.TriggerHandler;
import forge.card.trigger.TriggerType; import forge.card.trigger.TriggerType;
import forge.control.input.Input; import forge.control.input.Input;
import forge.game.GameState; import forge.game.GameState;
import forge.game.ai.AiAttackController;
import forge.game.ai.ComputerUtil; import forge.game.ai.ComputerUtil;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilCost; import forge.game.ai.ComputerUtilCost;
import forge.game.event.TokenCreatedEvent; import forge.game.event.TokenCreatedEvent;
import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseHandler;
@@ -85,7 +79,6 @@ import forge.game.zone.ZoneType;
import forge.gui.GuiChoose; import forge.gui.GuiChoose;
import forge.gui.match.CMatchUI; import forge.gui.match.CMatchUI;
import forge.util.Aggregates; import forge.util.Aggregates;
import forge.util.MyRandom;
import forge.view.ButtonUtil; import forge.view.ButtonUtil;
@@ -98,659 +91,6 @@ import forge.view.ButtonUtil;
* @version $Id$ * @version $Id$
*/ */
public class CardFactoryUtil { public class CardFactoryUtil {
private static Random random = MyRandom.getRandom();
/**
* <p>
* getMostExpensivePermanentAI.
* </p>
*
* @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<Card> list, final SpellAbility spell, final boolean targeted) {
List<Card> all = list;
if (targeted) {
all = CardLists.filter(all, new Predicate<Card>() {
@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<Card> 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<Card> 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
/**
* <p>
* getCheapestCreatureAI.
* </p>
*
* @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<Card> list, final SpellAbility spell, final boolean targeted) {
list = CardLists.filter(list, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
return c.isCreature();
}
});
return CardFactoryUtil.getCheapestPermanentAI(list, spell, targeted);
}
/**
* <p>
* getCheapestPermanentAI.
* </p>
*
* @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<Card> list, final SpellAbility spell, final boolean targeted) {
List<Card> all = list;
if (targeted) {
all = CardLists.filter(all, new Predicate<Card>() {
@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;
}
/**
* <p>
* getBestLandAI.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @return a {@link forge.Card} object.
*/
public static Card getBestLandAI(final List<Card> list) {
final List<Card> land = CardLists.filter(list, CardPredicates.Presets.LANDS);
if (!(land.size() > 0)) {
return null;
}
// prefer to target non basic lands
final List<Card> 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<Card> 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.
/**
* <p>
* getBestEnchantmentAI.
* </p>
*
* @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<Card> list, final SpellAbility spell, final boolean targeted) {
List<Card> all = CardLists.filter(list, CardPredicates.Presets.ENCHANTMENTS);
if (targeted) {
all = CardLists.filter(all, new Predicate<Card>() {
@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.
/**
* <p>
* getBestArtifactAI.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @return a {@link forge.Card} object.
*/
public static Card getBestArtifactAI(final List<Card> list) {
List<Card> all = CardLists.filter(list, CardPredicates.Presets.ARTIFACTS);
if (all.size() == 0) {
return null;
}
// get biggest Artifact
return Aggregates.itemWithMax(all, CardPredicates.Accessors.fnGetCmc);
}
/**
* <p>
* doesCreatureAttackAI.
* </p>
*
* @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<Card> att = new AiAttackController(ai, ai.getOpponent()).getAttackers().getAttackers();
return att.contains(card);
}
/**
* <p>
* evaluateCreatureList.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @return a int.
*/
public static int evaluateCreatureList(final List<Card> list) {
int value = 0;
for (int i = 0; i < list.size(); i++) {
value += CardFactoryUtil.evaluateCreature(list.get(i));
}
return value;
}
/**
* <p>
* evaluatePermanentList.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @return a int.
*/
public static int evaluatePermanentList(final List<Card> list) {
int value = 0;
for (int i = 0; i < list.size(); i++) {
value += list.get(i).getCMC() + 1;
}
return value;
}
/**
* <p>
* evaluateCreature.
* </p>
*
* @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
/**
* <p>
* getBestAI.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @return a {@link forge.Card} object.
*/
public static Card getBestAI(final List<Card> 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<Card> list) {
List<Card> all = CardLists.filter(list, CardPredicates.Presets.CREATURES);
return Aggregates.itemWithMax(all, CardPredicates.Accessors.fnEvaluateCreature);
}
// This selection rates tokens higher
/**
* <p>
* getBestCreatureToBounceAI.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @return a {@link forge.Card} object.
*/
public static Card getBestCreatureToBounceAI(final List<Card> list) {
final int tokenBonus = 40;
List<Card> 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;
}
/**
* <p>
* getWorstAI.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @return a {@link forge.Card} object.
*/
public static Card getWorstAI(final List<Card> list) {
return CardFactoryUtil.getWorstPermanentAI(list, false, false, false, false);
}
// returns null if list.size() == 0
/**
* <p>
* getWorstCreatureAI.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @return a {@link forge.Card} object.
*/
public static Card getWorstCreatureAI(final List<Card> list) {
List<Card> all = CardLists.filter(list, CardPredicates.Presets.CREATURES);
// get smallest creature
return Aggregates.itemWithMin(all, CardPredicates.Accessors.fnEvaluateCreature);
}
/**
* <p>
* getWorstPermanentAI.
* </p>
*
* @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<Card> 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<Card> 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<Card>() {
@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);
}
/** /**
* <p> * <p>
* inputDestroyNoRegeneration. * inputDestroyNoRegeneration.
@@ -3027,91 +2367,6 @@ public class CardFactoryUtil {
return untap; return untap;
} }
/**
* <p>
* getMostProminentCardName.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @return a {@link java.lang.String} object.
*/
public static String getMostProminentCardName(final List<Card> list) {
if (list.size() == 0) {
return "";
}
final Map<String, Integer> map = new HashMap<String, Integer>();
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<String, Integer> entry : map.entrySet()) {
final String type = entry.getKey();
// Log.debug(type + " - " + entry.getValue());
if (max < entry.getValue()) {
max = entry.getValue();
maxName = type;
}
}
return maxName;
}
/**
* <p>
* getMostProminentCreatureType.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @return a {@link java.lang.String} object.
*/
public static String getMostProminentCreatureType(final List<Card> list) {
if (list.size() == 0) {
return "";
}
final Map<String, Integer> map = new HashMap<String, Integer>();
for (final Card c : list) {
final ArrayList<String> 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<String, Integer> entry : map.entrySet()) {
final String type = entry.getKey();
// Log.debug(type + " - " + entry.getValue());
if (max < entry.getValue()) {
max = entry.getValue();
maxType = type;
}
}
return maxType;
}
/** /**
* <p> * <p>
* isMostProminentColor. * isMostProminentColor.
@@ -3153,96 +2408,6 @@ public class CardFactoryUtil {
return true; return true;
} }
/**
* <p>
* getMostProminentColor.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @return a {@link java.lang.String} object.
*/
public static String getMostProminentColor(final List<Card> list) {
final Map<String, Integer> map = new HashMap<String, Integer>();
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<String, Integer> 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<String> getColorByProminence(final List<Card> list) {
final HashMap<String, Integer> counts = new HashMap<String, Integer>();
for (String color : Constant.Color.ONLY_COLORS) {
counts.put(color, 0);
}
for (Card c : list) {
List<String> colors = c.determineColor().toStringList();
for (String col : colors) {
if (counts.containsKey(col)) {
counts.put(col.toString(), counts.get(col.toString()) + 1);
}
}
}
ArrayList<String> res = new ArrayList<String>(counts.keySet());
Collections.sort(res, new Comparator<String>() {
@Override
public int compare(final String a, final String b) {
return counts.get(b) - counts.get(a);
}
});
return res;
}
/**
* <p>
* getUsableManaSources.
* </p>
*
* @param player
* a {@link forge.game.player.Player} object.
* @return a int.
*/
public static int getUsableManaSources(final Player player) {
List<Card> list = CardLists.filter(player.getCardsIn(ZoneType.Battlefield), new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
for (final SpellAbility am : c.getAIPlayableMana()) {
if (am.canPlay()) {
return true;
}
}
return false;
}
});
return list.size();
}
/** /**
* <p> * <p>
* makeToken. * makeToken.
@@ -3423,66 +2588,6 @@ public class CardFactoryUtil {
return neededDamage; return neededDamage;
} }
/**
* getWorstLand
* <p/>
* 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
* <p/>
* 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<Card> lands = player.getLandsInPlay();
return CardFactoryUtil.getWorstLand(lands);
} // end getWorstLand
/**
* <p>
* getWorstLand.
* </p>
*
* @param lands
* a {@link forge.CardList} object.
* @return a {@link forge.Card} object.
*/
public static Card getWorstLand(final List<Card> 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
/**
* <p>
* getRandomCard.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @return a {@link forge.Card} object.
*/
public static Card getRandomCard(final List<Card> list) {
if (list.size() == 0) {
return null;
}
final int index = CardFactoryUtil.random.nextInt(list.size());
return list.get(index);
}
/** /**
* <p> * <p>
@@ -4068,10 +3173,10 @@ public class CardFactoryUtil {
} else { } else {
// AI choosing what to haunt // AI choosing what to haunt
final List<Card> oppCreats = CardLists.filterControlledBy(creats, card.getController().getOpponent()); final List<Card> oppCreats = CardLists.filterControlledBy(creats, card.getController().getOpponent());
if (oppCreats.size() != 0) { if (!oppCreats.isEmpty()) {
haunterDiesWork.setTargetCard(CardFactoryUtil.getWorstCreatureAI(oppCreats)); haunterDiesWork.setTargetCard(ComputerUtilCard.getWorstCreatureAI(oppCreats));
} else { } else {
haunterDiesWork.setTargetCard(CardFactoryUtil.getWorstCreatureAI(creats)); haunterDiesWork.setTargetCard(ComputerUtilCard.getWorstCreatureAI(creats));
} }
Singletons.getModel().getGame().getStack().add(haunterDiesWork); Singletons.getModel().getGame().getStack().add(haunterDiesWork);
} }
@@ -4759,7 +3864,7 @@ public class CardFactoryUtil {
} }
}); });
if (choices.size() != 0) { if (choices.size() != 0) {
ability.setTargetCard(CardFactoryUtil.getBestCreatureAI(choices)); ability.setTargetCard(ComputerUtilCard.getBestCreatureAI(choices));
if (ability.getTargetCard() != null) { if (ability.getTargetCard() != null) {
ability.setStackDescription("Put " + card.getCounters(CounterType.P1P1) ability.setStackDescription("Put " + card.getCounters(CounterType.P1P1)

View File

@@ -25,10 +25,10 @@ import forge.CardLists;
import forge.CounterType; import forge.CounterType;
import forge.Singletons; import forge.Singletons;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.control.input.Input; import forge.control.input.Input;
import forge.game.GameState; import forge.game.GameState;
import forge.game.ai.ComputerUtilCard;
import forge.game.player.AIPlayer; import forge.game.player.AIPlayer;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
@@ -223,9 +223,9 @@ public class CostPutCounter extends CostPartWithList {
Card card = null; Card card = null;
if (this.getType().equals("Creature.YouCtrl")) { if (this.getType().equals("Creature.YouCtrl")) {
card = CardFactoryUtil.getWorstCreatureAI(typeList); card = ComputerUtilCard.getWorstCreatureAI(typeList);
} else { } else {
card = CardFactoryUtil.getWorstPermanentAI(typeList, false, false, false, false); card = ComputerUtilCard.getWorstPermanentAI(typeList, false, false, false, false);
} }
this.addToList(card); this.addToList(card);
} }

View File

@@ -6,14 +6,13 @@ import java.util.List;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import forge.Card; import forge.Card;
import forge.CardColor;
import forge.CardLists; import forge.CardLists;
import forge.CardPredicates; import forge.CardPredicates;
import forge.CardUtil;
import forge.card.MagicColor; import forge.card.MagicColor;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.ApiType; import forge.card.ability.ApiType;
import forge.card.ability.effects.CharmEffect; import forge.card.ability.effects.CharmEffect;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.Cost; import forge.card.cost.Cost;
import forge.card.cost.CostPayment; import forge.card.cost.CostPayment;
import forge.card.mana.ManaCostBeingPaid; import forge.card.mana.ManaCostBeingPaid;
@@ -26,6 +25,7 @@ import forge.card.spellability.TargetSelection;
import forge.card.staticability.StaticAbility; import forge.card.staticability.StaticAbility;
import forge.control.input.InputControl; import forge.control.input.InputControl;
import forge.control.input.InputPayManaSimple; import forge.control.input.InputPayManaSimple;
import forge.game.ai.ComputerUtilCard;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
import forge.gui.GuiChoose; import forge.gui.GuiChoose;
@@ -196,7 +196,7 @@ public class GameActionPlay {
} }
while (tapForConvoke != null && untappedCreats.size() != 0) { while (tapForConvoke != null && untappedCreats.size() != 0) {
final Card workingCard = (Card) tapForConvoke; final Card workingCard = (Card) tapForConvoke;
usableColors = CardUtil.getConvokableColors(workingCard, newCost); usableColors = GameActionPlay.getConvokableColors(workingCard, newCost);
if (usableColors.size() != 0) { if (usableColors.size() != 0) {
String chosenColor = usableColors.get(0); String chosenColor = usableColors.get(0);
@@ -317,7 +317,7 @@ public class GameActionPlay {
} }
} }
if (chosen == null) { if (chosen == null) {
chosen = CardFactoryUtil.getWorstCreatureAI(grave); chosen = ComputerUtilCard.getWorstCreatureAI(grave);
} }
if (chosen == null) { if (chosen == null) {
@@ -503,4 +503,33 @@ public class GameActionPlay {
final String costCuttingGetMultiKickerManaCostPaidColored0) { final String costCuttingGetMultiKickerManaCostPaidColored0) {
this.costCuttingGetMultiKickerManaCostPaidColored = 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<String> getConvokableColors(final Card cardToConvoke, final ManaCostBeingPaid cost) {
final ArrayList<String> usableColors = new ArrayList<String>();
if (cost.getColorlessManaAmount() > 0) {
usableColors.add("colorless");
}
for (final CardColor col : cardToConvoke.getColor()) {
for (final String strCol : col.toStringList()) {
if (strCol.equals("colorless")) {
continue;
}
if (cost.toString().contains(MagicColor.toShortString(strCol))) {
usableColors.add(strCol.toString());
}
}
}
return usableColors;
}
} }

View File

@@ -29,7 +29,6 @@ import forge.CardLists;
import forge.CounterType; import forge.CounterType;
import forge.GameEntity; import forge.GameEntity;
import forge.Singletons; import forge.Singletons;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.trigger.Trigger; import forge.card.trigger.Trigger;
import forge.card.trigger.TriggerType; import forge.card.trigger.TriggerType;
import forge.game.GameState; import forge.game.GameState;
@@ -909,7 +908,7 @@ public class AiAttackController {
// see if the defending creature is of higher or lower // see if the defending creature is of higher or lower
// value. We don't want to attack only to lose value // value. We don't want to attack only to lose value
if (isWorthLessThanAllKillers && attacker.getSVar("SacMe").equals("") if (isWorthLessThanAllKillers && attacker.getSVar("SacMe").equals("")
&& CardFactoryUtil.evaluateCreature(defender) <= CardFactoryUtil.evaluateCreature(attacker)) { && ComputerUtilCard.evaluateCreature(defender) <= ComputerUtilCard.evaluateCreature(attacker)) {
isWorthLessThanAllKillers = false; isWorthLessThanAllKillers = false;
} }
} }

View File

@@ -596,7 +596,7 @@ public class AiController {
discardList.add(hand.get(0)); discardList.add(hand.get(0));
hand.remove(hand.get(0)); hand.remove(hand.get(0));
} else { //Discard worst card } else { //Discard worst card
Card worst = CardFactoryUtil.getWorstAI(hand); Card worst = ComputerUtilCard.getWorstAI(hand);
discardList.add(worst); discardList.add(worst);
hand.remove(worst); hand.remove(worst);
} }
@@ -606,14 +606,64 @@ public class AiController {
return discardList; return discardList;
} }
// These methods might be moved into matching SpellAbilityAi classes just without all these switches here
public Card chooseSingleCardForEffect(List<Card> options, SpellAbility sa, String title, boolean isOptional) { public Card chooseSingleCardForEffect(List<Card> options, SpellAbility sa, String title, boolean isOptional) {
ApiType api = sa.getApi(); ApiType api = sa.getApi();
if ( null == api ) { if ( null == api ) {
throw new InvalidParameterException("SA is not api-based, this is not supported yet"); 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) { 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); default: throw new InvalidParameterException("AI chooseSingleCard does not know how to choose card for " + api);
} }
} }
@@ -627,12 +677,15 @@ public class AiController {
switch(api) { switch(api) {
case Discard: 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 // TODO For now AI will always discard Random used currently with: Balduvian Horde and similar cards
return true; return true;
} }
break; break;
case Encode:
return true;
default: default:
} }
String exMsg = String.format("AI confirmAction does not know what to decide about %s with %s mode.", api, mode); String exMsg = String.format("AI confirmAction does not know what to decide about %s with %s mode.", api, mode);

View File

@@ -172,7 +172,7 @@ public class ComputerUtil {
if (unless != null && !unless.endsWith(">")) { if (unless != null && !unless.endsWith(">")) {
final int amount = AbilityUtils.calculateAmount(source, unless, sa); 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 the Unless isn't enough, this should be less likely to be used
if (amount > usableManaSources) { if (amount > usableManaSources) {
@@ -384,7 +384,7 @@ public class ComputerUtil {
if (landsInPlay.size() >= highestCMC if (landsInPlay.size() >= highestCMC
|| (landsInPlay.size() + landsInHand.size() > 6 && landsInHand.size() > 1)) { || (landsInPlay.size() + landsInHand.size() > 6 && landsInHand.size() > 1)) {
// Don't need more land. // Don't need more land.
return CardFactoryUtil.getWorstLand(landsInHand); return ComputerUtilCard.getWorstLand(landsInHand);
} }
} }
} }
@@ -678,11 +678,11 @@ public class ComputerUtil {
Card c; Card c;
if (CardLists.getNotType(remaining, "Creature").size() == 0) { if (CardLists.getNotType(remaining, "Creature").size() == 0) {
c = CardFactoryUtil.getWorstCreatureAI(remaining); c = ComputerUtilCard.getWorstCreatureAI(remaining);
} else if (CardLists.getNotType(remaining, "Land").size() == 0) { } 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 { } else {
c = CardFactoryUtil.getWorstPermanentAI(remaining, false, false, false, false); c = ComputerUtilCard.getWorstPermanentAI(remaining, false, false, false, false);
} }
final ArrayList<Card> auras = c.getEnchantedBy(); final ArrayList<Card> auras = c.getEnchantedBy();

View File

@@ -29,7 +29,6 @@ import forge.CardLists;
import forge.CardPredicates; import forge.CardPredicates;
import forge.CounterType; import forge.CounterType;
import forge.GameEntity; import forge.GameEntity;
import forge.card.cardfactory.CardFactoryUtil;
import forge.game.phase.Combat; import forge.game.phase.Combat;
import forge.game.phase.CombatUtil; import forge.game.phase.CombatUtil;
import forge.game.player.Player; import forge.game.player.Player;
@@ -360,9 +359,9 @@ public class ComputerUtilBlock {
// destroyed // destroyed
killingBlockers = ComputerUtilBlock.getKillingBlockers(ai, attacker, safeBlockers, combat); killingBlockers = ComputerUtilBlock.getKillingBlockers(ai, attacker, safeBlockers, combat);
if (killingBlockers.size() > 0) { 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.")) { } 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); ComputerUtilBlock.getBlockedButUnkilled().add(attacker);
} }
} // no safe blockers } // no safe blockers
@@ -378,9 +377,9 @@ public class ComputerUtilBlock {
} }
// 4.Blockers that can destroy the attacker and are worth less // 4.Blockers that can destroy the attacker and are worth less
if (blocker == null && killingBlockers.size() > 0) { 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)) { .evaluateCreature(attacker)) {
blocker = worst; blocker = worst;
} }
@@ -471,7 +470,7 @@ public class ComputerUtilBlock {
&& !(c.hasKeyword("First Strike") || c.hasKeyword("Double Strike"))) { && !(c.hasKeyword("First Strike") || c.hasKeyword("Double Strike"))) {
return false; return false;
} }
return lifeInDanger || (CardFactoryUtil.evaluateCreature(c) + ComputerUtilBlock.getDiff()) < CardFactoryUtil return lifeInDanger || (ComputerUtilCard.evaluateCreature(c) + ComputerUtilBlock.getDiff()) < ComputerUtilCard
.evaluateCreature(attacker); .evaluateCreature(attacker);
} }
}); });
@@ -479,11 +478,11 @@ public class ComputerUtilBlock {
return combat; return combat;
} }
final Card leader = CardFactoryUtil.getBestCreatureAI(usableBlockers); final Card leader = ComputerUtilCard.getBestCreatureAI(usableBlockers);
blockGang.add(leader); blockGang.add(leader);
usableBlockers.remove(leader); usableBlockers.remove(leader);
absorbedDamage = ComputerUtilCombat.getEnoughDamageToKill(leader, attacker.getNetCombatDamage(), attacker, true); absorbedDamage = ComputerUtilCombat.getEnoughDamageToKill(leader, attacker.getNetCombatDamage(), attacker, true);
currentValue = CardFactoryUtil.evaluateCreature(leader); currentValue = ComputerUtilCard.evaluateCreature(leader);
for (final Card blocker : usableBlockers) { for (final Card blocker : usableBlockers) {
// Add an additional blocker if the current blockers are not // 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 currentDamage = ComputerUtilCombat.totalDamageOfBlockers(attacker, blockGang);
final int additionalDamage = ComputerUtilCombat.dealsDamageAsBlocker(attacker, blocker); final int additionalDamage = ComputerUtilCombat.dealsDamageAsBlocker(attacker, blocker);
final int absorbedDamage2 = ComputerUtilCombat.getEnoughDamageToKill(blocker, attacker.getNetCombatDamage(), attacker, true); 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) final int damageNeeded = ComputerUtilCombat.getDamageToKill(attacker)
+ ComputerUtilCombat.predictToughnessBonusOfAttacker(attacker, blocker, combat, false); + ComputerUtilCombat.predictToughnessBonusOfAttacker(attacker, blocker, combat, false);
if ((damageNeeded > currentDamage || CombatUtil.needsBlockers(attacker) > blockGang.size()) if ((damageNeeded > currentDamage || CombatUtil.needsBlockers(attacker) > blockGang.size())
@@ -499,7 +498,7 @@ public class ComputerUtilBlock {
// The attacker will be killed // The attacker will be killed
&& (absorbedDamage2 + absorbedDamage > attacker.getNetCombatDamage() && (absorbedDamage2 + absorbedDamage > attacker.getNetCombatDamage()
// only one blocker can be killed // only one blocker can be killed
|| currentValue + addedValue - 50 <= CardFactoryUtil.evaluateCreature(attacker) || currentValue + addedValue - 50 <= ComputerUtilCard.evaluateCreature(attacker)
// or attacker is worth more // or attacker is worth more
|| (lifeInDanger && ComputerUtilCombat.lifeInDanger(ai, combat))) || (lifeInDanger && ComputerUtilCombat.lifeInDanger(ai, combat)))
// or life is in danger // or life is in danger
@@ -545,7 +544,7 @@ public class ComputerUtilBlock {
ComputerUtilBlock.getPossibleBlockers(attacker, ComputerUtilBlock.getBlockersLeft(), combat, true), ComputerUtilBlock.getPossibleBlockers(attacker, ComputerUtilBlock.getBlockersLeft(), combat, true),
combat); combat);
if ((killingBlockers.size() > 0) && ComputerUtilCombat.lifeInDanger(ai, 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); combat.addBlocker(attacker, blocker);
currentAttackers.remove(attacker); currentAttackers.remove(attacker);
} }
@@ -579,7 +578,7 @@ public class ComputerUtilBlock {
chumpBlockers = ComputerUtilBlock chumpBlockers = ComputerUtilBlock
.getPossibleBlockers(attacker, ComputerUtilBlock.getBlockersLeft(), combat, true); .getPossibleBlockers(attacker, ComputerUtilBlock.getBlockersLeft(), combat, true);
if ((chumpBlockers.size() > 0) && ComputerUtilCombat.lifeInDanger(ai, combat)) { if ((chumpBlockers.size() > 0) && ComputerUtilCombat.lifeInDanger(ai, combat)) {
final Card blocker = CardFactoryUtil.getWorstCreatureAI(chumpBlockers); final Card blocker = ComputerUtilCard.getWorstCreatureAI(chumpBlockers);
combat.addBlocker(attacker, blocker); combat.addBlocker(attacker, blocker);
currentAttackers.remove(attacker); currentAttackers.remove(attacker);
ComputerUtilBlock.getBlockedButUnkilled().add(attacker); ComputerUtilBlock.getBlockedButUnkilled().add(attacker);
@@ -697,7 +696,7 @@ public class ComputerUtilBlock {
final int additionalDamage = ComputerUtilCombat.dealsDamageAsBlocker(attacker, blocker); final int additionalDamage = ComputerUtilCombat.dealsDamageAsBlocker(attacker, blocker);
if ((damageNeeded > currentDamage) if ((damageNeeded > currentDamage)
&& !(damageNeeded > (currentDamage + additionalDamage)) && !(damageNeeded > (currentDamage + additionalDamage))
&& ((CardFactoryUtil.evaluateCreature(blocker) + ComputerUtilBlock.getDiff()) < CardFactoryUtil && ((ComputerUtilCard.evaluateCreature(blocker) + ComputerUtilBlock.getDiff()) < ComputerUtilCard
.evaluateCreature(attacker)) && CombatUtil.canBlock(attacker, blocker, combat)) { .evaluateCreature(attacker)) && CombatUtil.canBlock(attacker, blocker, combat)) {
combat.addBlocker(attacker, blocker); combat.addBlocker(attacker, blocker);
ComputerUtilBlock.getBlockersLeft().remove(blocker); ComputerUtilBlock.getBlockersLeft().remove(blocker);

View File

@@ -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 {
/**
* <p>
* getMostExpensivePermanentAI.
* </p>
*
* @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<Card> list, final SpellAbility spell, final boolean targeted) {
List<Card> all = list;
if (targeted) {
all = CardLists.filter(all, new Predicate<Card>() {
@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.
/**
* <p>
* getBestArtifactAI.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @return a {@link forge.Card} object.
*/
public static Card getBestArtifactAI(final List<Card> list) {
List<Card> 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.
/**
* <p>
* getBestEnchantmentAI.
* </p>
*
* @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<Card> list, final SpellAbility spell, final boolean targeted) {
List<Card> all = CardLists.filter(list, CardPredicates.Presets.ENCHANTMENTS);
if (targeted) {
all = CardLists.filter(all, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
return c.canBeTargetedBy(spell);
}
});
}
// get biggest Enchantment
return Aggregates.itemWithMax(all, CardPredicates.Accessors.fnGetCmc);
}
/**
* <p>
* getBestLandAI.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @return a {@link forge.Card} object.
*/
public static Card getBestLandAI(final List<Card> list) {
final List<Card> land = CardLists.filter(list, CardPredicates.Presets.LANDS);
if (!(land.size() > 0)) {
return null;
}
// prefer to target non basic lands
final List<Card> 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<Card> 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
}
/**
* <p>
* getCheapestPermanentAI.
* </p>
*
* @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<Card> list, final SpellAbility spell, final boolean targeted) {
List<Card> all = list;
if (targeted) {
all = CardLists.filter(all, new Predicate<Card>() {
@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
/**
* <p>
* getCheapestCreatureAI.
* </p>
*
* @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<Card> list, final SpellAbility spell, final boolean targeted) {
list = CardLists.filter(list, new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
return c.isCreature();
}
});
return getCheapestPermanentAI(list, spell, targeted);
}
// returns null if list.size() == 0
/**
* <p>
* getBestAI.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @return a {@link forge.Card} object.
*/
public static Card getBestAI(final List<Card> 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<Card> list) {
List<Card> all = CardLists.filter(list, CardPredicates.Presets.CREATURES);
return Aggregates.itemWithMax(all, ComputerUtilCard.fnEvaluateCreature);
}
// This selection rates tokens higher
/**
* <p>
* getBestCreatureToBounceAI.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @return a {@link forge.Card} object.
*/
public static Card getBestCreatureToBounceAI(final List<Card> list) {
final int tokenBonus = 40;
List<Card> 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;
}
/**
* <p>
* getWorstAI.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @return a {@link forge.Card} object.
*/
public static Card getWorstAI(final List<Card> list) {
return ComputerUtilCard.getWorstPermanentAI(list, false, false, false, false);
}
// returns null if list.size() == 0
/**
* <p>
* getWorstCreatureAI.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @return a {@link forge.Card} object.
*/
public static Card getWorstCreatureAI(final List<Card> list) {
List<Card> all = CardLists.filter(list, CardPredicates.Presets.CREATURES);
// get smallest creature
return Aggregates.itemWithMin(all, ComputerUtilCard.fnEvaluateCreature);
}
/**
* <p>
* getWorstPermanentAI.
* </p>
*
* @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<Card> 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<Card> 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<Card>() {
@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<Card, Integer> fnEvaluateCreature = new Function<Card, Integer>() {
@Override
public Integer apply(Card a) {
return ComputerUtilCard.evaluateCreature(a);
}
};
public static final Comparator<Card> EvaluateCreatureComparator = new Comparator<Card>() {
@Override
public int compare(final Card a, final Card b) {
return ComputerUtilCard.evaluateCreature(b) - ComputerUtilCard.evaluateCreature(a);
}
};
/**
* <p>
* evaluateCreature.
* </p>
*
* @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
/**
* <p>
* evaluatePermanentList.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @return a int.
*/
public static int evaluatePermanentList(final List<Card> list) {
int value = 0;
for (int i = 0; i < list.size(); i++) {
value += list.get(i).getCMC() + 1;
}
return value;
}
/**
* <p>
* evaluateCreatureList.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @return a int.
*/
public static int evaluateCreatureList(final List<Card> list) {
int value = 0;
for (int i = 0; i < list.size(); i++) {
value += evaluateCreature(list.get(i));
}
return value;
}
/**
* <p>
* doesCreatureAttackAI.
* </p>
*
* @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<Card> att = new AiAttackController(ai, ai.getOpponent()).getAttackers().getAttackers();
return att.contains(card);
}
// may return null
/**
* <p>
* getRandomCard.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @return a {@link forge.Card} object.
*/
public static Card getRandomCard(final List<Card> 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<Card> 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<Card> 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;
}
/**
* <p>
* getMostProminentCardName.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @return a {@link java.lang.String} object.
*/
public static String getMostProminentCardName(final List<Card> list) {
if (list.size() == 0) {
return "";
}
final Map<String, Integer> map = new HashMap<String, Integer>();
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<String, Integer> entry : map.entrySet()) {
final String type = entry.getKey();
// Log.debug(type + " - " + entry.getValue());
if (max < entry.getValue()) {
max = entry.getValue();
maxName = type;
}
}
return maxName;
}
/**
* <p>
* getMostProminentCreatureType.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @return a {@link java.lang.String} object.
*/
public static String getMostProminentCreatureType(final List<Card> list) {
if (list.size() == 0) {
return "";
}
final Map<String, Integer> map = new HashMap<String, Integer>();
for (final Card c : list) {
final ArrayList<String> 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<String, Integer> entry : map.entrySet()) {
final String type = entry.getKey();
// Log.debug(type + " - " + entry.getValue());
if (max < entry.getValue()) {
max = entry.getValue();
maxType = type;
}
}
return maxType;
}
/**
* <p>
* getMostProminentColor.
* </p>
*
* @param list
* a {@link forge.CardList} object.
* @return a {@link java.lang.String} object.
*/
public static String getMostProminentColor(final List<Card> list) {
final Map<String, Integer> map = new HashMap<String, Integer>();
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<String, Integer> 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<String> getColorByProminence(final List<Card> list) {
final HashMap<String, Integer> counts = new HashMap<String, Integer>();
for (String color : Constant.Color.ONLY_COLORS) {
counts.put(color, 0);
}
for (Card c : list) {
List<String> colors = c.determineColor().toStringList();
for (String col : colors) {
if (counts.containsKey(col)) {
counts.put(col.toString(), counts.get(col.toString()) + 1);
}
}
}
ArrayList<String> res = new ArrayList<String>(counts.keySet());
Collections.sort(res, new Comparator<String>() {
@Override
public int compare(final String a, final String b) {
return counts.get(b) - counts.get(a);
}
});
return res;
}
/**
* <p>
* getUsableManaSources.
* </p>
*
* @param player
* a {@link forge.game.player.Player} object.
* @return a int.
*/
public static int getUsableManaSources(final Player player) {
List<Card> list = CardLists.filter(player.getCardsIn(ZoneType.Battlefield), new Predicate<Card>() {
@Override
public boolean apply(final Card c) {
for (final SpellAbility am : c.getAIPlayableMana()) {
if (am.canPlay()) {
return true;
}
}
return false;
}
});
return list.size();
}
/**
* <p>
* getWorstLand.
* </p>
*
* @param lands
* a {@link forge.CardList} object.
* @return a {@link forge.Card} object.
*/
public static Card getWorstLand(final List<Card> 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
}

View File

@@ -17,7 +17,6 @@ import forge.Singletons;
import forge.card.MagicColor; import forge.card.MagicColor;
import forge.card.ability.AbilityUtils; import forge.card.ability.AbilityUtils;
import forge.card.ability.ApiType; import forge.card.ability.ApiType;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.Cost; import forge.card.cost.Cost;
import forge.card.cost.CostPayment; import forge.card.cost.CostPayment;
import forge.card.mana.ManaCostBeingPaid; import forge.card.mana.ManaCostBeingPaid;
@@ -748,7 +747,7 @@ public class ComputerUtilMana {
} }
} }
// check if combo mana can produce most common color in hand // 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)); ZoneType.Hand));
if (!commonColor.isEmpty() && abMana.getComboColors().contains(MagicColor.toShortString(commonColor))) { if (!commonColor.isEmpty() && abMana.getComboColors().contains(MagicColor.toShortString(commonColor))) {
choice = MagicColor.toShortString(commonColor); choice = MagicColor.toShortString(commonColor);

View File

@@ -50,6 +50,7 @@ import forge.game.GameState;
import forge.game.GlobalRuleChange; import forge.game.GlobalRuleChange;
import forge.game.ai.ComputerUtil; import forge.game.ai.ComputerUtil;
import forge.game.ai.ComputerUtilBlock; import forge.game.ai.ComputerUtilBlock;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilCost; import forge.game.ai.ComputerUtilCost;
import forge.game.player.AIPlayer; import forge.game.player.AIPlayer;
import forge.game.player.Player; import forge.game.player.Player;
@@ -1573,7 +1574,7 @@ public class CombatUtil {
enchantment = ((Card) check); enchantment = ((Card) check);
} }
} else { } else {
enchantment = CardFactoryUtil.getBestEnchantmentAI(enchantments, this, false); enchantment = ComputerUtilCard.getBestEnchantmentAI(enchantments, this, false);
} }
if ((enchantment != null) && attacker.isInPlay()) { if ((enchantment != null) && attacker.isInPlay()) {
Singletons.getModel().getGame().getAction().changeZone(Singletons.getModel().getGame().getZoneOf(enchantment), Singletons.getModel().getGame().getAction().changeZone(Singletons.getModel().getGame().getZoneOf(enchantment),

View File

@@ -30,9 +30,9 @@ import forge.CardPredicates;
import forge.CounterType; import forge.CounterType;
import forge.GameEntity; import forge.GameEntity;
import forge.Singletons; import forge.Singletons;
import forge.card.cardfactory.CardFactoryUtil;
import forge.control.input.Input; import forge.control.input.Input;
import forge.game.GameState; import forge.game.GameState;
import forge.game.ai.ComputerUtilCard;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.zone.Zone; import forge.game.zone.Zone;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
@@ -246,7 +246,7 @@ public class Untap extends Phase {
artList = CardLists.filter(artList, Presets.ARTIFACTS); artList = CardLists.filter(artList, Presets.ARTIFACTS);
artList = CardLists.filter(artList, tappedCanUntap); artList = CardLists.filter(artList, tappedCanUntap);
if (artList.size() > 0) { if (artList.size() > 0) {
CardFactoryUtil.getBestArtifactAI(artList).untap(); ComputerUtilCard.getBestArtifactAI(artList).untap();
} }
} else { } else {
final Input target = new Input() { final Input target = new Input() {

View File

@@ -44,6 +44,7 @@ import forge.control.input.InputSelectManyCards;
import forge.game.GameActionUtil; import forge.game.GameActionUtil;
import forge.game.GameState; import forge.game.GameState;
import forge.game.ai.ComputerUtil; import forge.game.ai.ComputerUtil;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilCombat; import forge.game.ai.ComputerUtilCombat;
import forge.game.ai.ComputerUtilCost; import forge.game.ai.ComputerUtilCost;
import forge.game.ai.ComputerUtilMana; import forge.game.ai.ComputerUtilMana;
@@ -501,7 +502,7 @@ public class Upkeep extends Phase {
if (indestruct.size() > 0) { if (indestruct.size() > 0) {
game.getAction().destroyNoRegeneration(indestruct.get(0)); game.getAction().destroyNoRegeneration(indestruct.get(0));
} else if (targets.size() > 0) { } else if (targets.size() > 0) {
final Card target = CardFactoryUtil.getWorstCreatureAI(targets); final Card target = ComputerUtilCard.getWorstCreatureAI(targets);
if (null == target) { if (null == target) {
// must be nothing valid to destroy // must be nothing valid to destroy
} else { } else {
@@ -632,7 +633,7 @@ public class Upkeep extends Phase {
if (c.getController().isComputer()) { if (c.getController().isComputer()) {
target = GuiChoose.one("Select a card to sacrifice", playerLand); target = GuiChoose.one("Select a card to sacrifice", playerLand);
} else { } else {
target = CardFactoryUtil.getBestLandAI(playerLand); target = ComputerUtilCard.getBestLandAI(playerLand);
} }
game.getAction().sacrifice(target, null); game.getAction().sacrifice(target, null);
} // end resolve() } // end resolve()
@@ -1027,7 +1028,7 @@ public class Upkeep extends Phase {
for (int i = 0; i < num; i++) { for (int i = 0; i < num; i++) {
if (player.isComputer()) { 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 // try to find non creature cards without tap abilities
List<Card> betterList = CardLists.filter(list, new Predicate<Card>() { List<Card> betterList = CardLists.filter(list, new Predicate<Card>() {
@Override @Override

View File

@@ -25,10 +25,10 @@ import forge.Card;
import forge.CardLists; import forge.CardLists;
import forge.CardPredicates; import forge.CardPredicates;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility; import forge.card.spellability.SpellAbility;
import forge.game.GameState; import forge.game.GameState;
import forge.game.ai.AiController; import forge.game.ai.AiController;
import forge.game.ai.ComputerUtilCard;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
import forge.util.Aggregates; import forge.util.Aggregates;
import forge.util.MyRandom; import forge.util.MyRandom;
@@ -175,7 +175,7 @@ public class AIPlayer extends Player {
public final void sacrificePermanent(final String prompt, final List<Card> choices) { public final void sacrificePermanent(final String prompt, final List<Card> choices) {
if (choices.size() > 0) { if (choices.size() > 0) {
// TODO - this could probably use better AI // 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); game.getAction().sacrificeDestroy(c);
} }
} }

View File

@@ -53,6 +53,7 @@ import forge.control.input.InputPayManaExecuteCommands;
import forge.game.GameActionUtil; import forge.game.GameActionUtil;
import forge.game.GameState; import forge.game.GameState;
import forge.game.ai.ComputerUtil; import forge.game.ai.ComputerUtil;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilCost; import forge.game.ai.ComputerUtilCost;
import forge.game.event.SpellResolvedEvent; import forge.game.event.SpellResolvedEvent;
import forge.game.phase.PhaseType; import forge.game.phase.PhaseType;
@@ -901,9 +902,9 @@ public class MagicStack extends MyObservable {
// AI choosing what to haunt // AI choosing what to haunt
final List<Card> oppCreats = CardLists.filterControlledBy(creats, source.getController().getOpponents()); final List<Card> oppCreats = CardLists.filterControlledBy(creats, source.getController().getOpponents());
if (oppCreats.size() != 0) { if (oppCreats.size() != 0) {
haunterDiesWork.setTargetCard(CardFactoryUtil.getWorstCreatureAI(oppCreats)); haunterDiesWork.setTargetCard(ComputerUtilCard.getWorstCreatureAI(oppCreats));
} else { } else {
haunterDiesWork.setTargetCard(CardFactoryUtil.getWorstCreatureAI(creats)); haunterDiesWork.setTargetCard(ComputerUtilCard.getWorstCreatureAI(creats));
} }
this.add(haunterDiesWork); this.add(haunterDiesWork);
} }

View File

@@ -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);
}
} }

View File

@@ -71,7 +71,7 @@ public class GuiDownloadSetPicturesLQ extends GuiDownloader {
if (!foundSetImage) { if (!foundSetImage) {
final int artsCnt = c.getRules().getEditionInfo(setCode3).getCopiesCount(); 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); String url = urlBase + setCode2 + "/" + Base64Coder.encodeString(filename, true);
cList.add(new DownloadObject(url, new File(this.picturesPath + File.separator + setCode3, filename))); cList.add(new DownloadObject(url, new File(this.picturesPath + File.separator + setCode3, filename)));