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

View File

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

View File

@@ -23,7 +23,6 @@ import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility;
import forge.game.phase.CombatUtil;
import forge.game.phase.Untap;
@@ -393,12 +392,5 @@ public final class CardPredicates {
return a.getCMC();
}
};
public static final Function<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.ability.AbilityUtils;
import forge.card.ability.ApiType;
import forge.card.mana.ManaCostBeingPaid;
import forge.card.spellability.AbilityManaPart;
import forge.card.spellability.SpellAbility;
import forge.game.player.Player;
@@ -99,29 +98,6 @@ public final class CardUtil {
return c.determineColor().toStringList();
}
// this function checks, if duplicates of a keyword are not necessary (like
// flying, trample, etc.)
/**
* <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>
* isStackingKeyword.
@@ -132,25 +108,12 @@ public final class CardUtil {
* @return a boolean.
*/
public static boolean isStackingKeyword(final String keyword) {
return !CardUtil.isNonStackingKeyword(keyword);
}
String kw = new String(keyword);
if (kw.startsWith("HIDDEN")) {
kw = kw.substring(7);
}
/**
* 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);
return !kw.startsWith("Protection") && !Constant.Keywords.NON_STACKING_LIST.contains(kw);
}
/**
@@ -432,35 +395,6 @@ public final class CardUtil {
return res;
}
/**
* Gets the convokable colors.
*
* @param cardToConvoke
* the card to convoke
* @param cost
* the cost
* @return the convokable colors
*/
public static ArrayList<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.
*

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -11,10 +11,10 @@ import forge.CardLists;
import forge.Singletons;
import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityAi;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.Cost;
import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilCombat;
import forge.game.ai.ComputerUtilCost;
import forge.game.ai.ComputerUtilMana;
@@ -96,7 +96,7 @@ public class DamageAllAi extends SpellAbilityAi {
}
// evaluate both lists and pass only if human creatures are more valuable
if ((CardFactoryUtil.evaluateCreatureList(computerList) + minGain) >= CardFactoryUtil
if ((ComputerUtilCard.evaluateCreatureList(computerList) + minGain) >= ComputerUtilCard
.evaluateCreatureList(humanList)) {
return false;
}
@@ -144,7 +144,7 @@ public class DamageAllAi extends SpellAbilityAi {
return true;
}
if (!computerList.isEmpty() && CardFactoryUtil.evaluateCreatureList(computerList) > CardFactoryUtil
if (!computerList.isEmpty() && ComputerUtilCard.evaluateCreatureList(computerList) > ComputerUtilCard
.evaluateCreatureList(humanList)) {
return false;
}
@@ -233,7 +233,7 @@ public class DamageAllAi extends SpellAbilityAi {
return true;
}
if (!computerList.isEmpty() && CardFactoryUtil.evaluateCreatureList(computerList) + 50 >= CardFactoryUtil
if (!computerList.isEmpty() && ComputerUtilCard.evaluateCreatureList(computerList) + 50 >= ComputerUtilCard
.evaluateCreatureList(humanList)) {
return false;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -74,52 +74,19 @@ public class ChooseCardEffect extends SpellAbilityEffect {
for (final Player p : tgtPlayers) {
if ((tgt == null) || p.canBeTargetedBy(sa)) {
for (int i = 0; i < validAmount; i++) {
if (p.isHuman()) {
final String choiceTitle = sa.hasParam("ChoiceTitle") ? sa.getParam("ChoiceTitle") : "Choose a card ";
Card o;
if (sa.hasParam("AtRandom")) {
o = Aggregates.random(choices);
} else if (sa.hasParam("Mandatory")) {
o = GuiChoose.one(choiceTitle, choices);
} else {
o = GuiChoose.oneOrNone(choiceTitle, choices);
}
if (o != null) {
chosen.add(o);
choices.remove(o);
} else {
break;
}
} else { // Computer
String logic = sa.getParam("AILogic");
Card choice = null;
if (logic == null) {
// Base Logic is choose "best"
choice = CardFactoryUtil.getBestAI(choices);
} else if ("WorstCard".equals(logic)) {
choice = CardFactoryUtil.getWorstAI(choices);
} else if (logic.equals("BestBlocker")) {
if (!CardLists.filter(choices, Presets.UNTAPPED).isEmpty()) {
choices = CardLists.filter(choices, Presets.UNTAPPED);
}
choice = CardFactoryUtil.getBestCreatureAI(choices);
} else if (logic.equals("Clone")) {
if (!CardLists.getValidCards(choices, "Permanent.YouDontCtrl,Permanent.nonLegendary", host.getController(), host).isEmpty()) {
choices = CardLists.getValidCards(choices, "Permanent.YouDontCtrl,Permanent.nonLegendary", host.getController(), host);
}
choice = CardFactoryUtil.getBestAI(choices);
} else if (logic.equals("Untap")) {
if (!CardLists.getValidCards(choices, "Permanent.YouCtrl,Permanent.tapped", host.getController(), host).isEmpty()) {
choices = CardLists.getValidCards(choices, "Permanent.YouCtrl,Permanent.tapped", host.getController(), host);
}
choice = CardFactoryUtil.getBestAI(choices);
}
if (choice != null) {
chosen.add(choice);
choices.remove(choice);
} else {
break;
}
Card c;
if (sa.hasParam("AtRandom")) {
c = Aggregates.random(choices);
} else {
c = p.getController().chooseSingleCardForEffect(choices, sa, sa.hasParam("ChoiceTitle") ? sa.getParam("ChoiceTitle") : "Choose a card ", !sa.hasParam("Mandatory"));
}
if (c != null) {
chosen.add(c);
choices.remove(c);
} else {
break;
}
}
host.setChosenCard(chosen);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -5,16 +5,12 @@ import java.util.List;
import forge.Card;
import forge.CardLists;
import forge.Singletons;
import forge.CardPredicates.Presets;
import forge.card.ability.SpellAbilityEffect;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.SpellAbility;
import forge.card.trigger.Trigger;
import forge.card.trigger.TriggerHandler;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
import forge.gui.GuiChoose;
import forge.gui.GuiDialog;
public class EncodeEffect extends SpellAbilityEffect {
@Override
@@ -43,10 +39,11 @@ public class EncodeEffect extends SpellAbilityEffect {
}
// Handle choice of whether or not to encoded
final StringBuilder sb = new StringBuilder();
sb.append("Do you want to exile " + host + " and encode it onto a creature you control?");
if (player.isHuman()
&& !GuiDialog.confirm(host, sb.toString())) {
if (!player.getController().confirmAction(sa, null, sb.toString())) {
return;
}
// Note: AI will always choose to encode
@@ -56,31 +53,8 @@ public class EncodeEffect extends SpellAbilityEffect {
Card movedCard = Singletons.getModel().getGame().getAction().moveTo(ZoneType.Exile, host);
// choose a creature
Card choice = null;
if (player.isHuman()) {
final String choiceTitle = "Choose a creature you control to encode ";
choice = GuiChoose.oneOrNone(choiceTitle, choices);
}
else { // Computer
// TODO: move this to AI method
String logic = sa.getParam("AILogic");
if (logic == null) {
// Base Logic is choose "best"
choice = CardFactoryUtil.getBestAI(choices);
} else if ("WorstCard".equals(logic)) {
choice = CardFactoryUtil.getWorstAI(choices);
} else if (logic.equals("BestBlocker")) {
if (!CardLists.filter(choices, Presets.UNTAPPED).isEmpty()) {
choices = CardLists.filter(choices, Presets.UNTAPPED);
}
choice = CardFactoryUtil.getBestCreatureAI(choices);
} else if (logic.equals("Clone")) {
if (!CardLists.getValidCards(choices, "Permanent.YouDontCtrl,Permanent.nonLegendary", host.getController(), host).isEmpty()) {
choices = CardLists.getValidCards(choices, "Permanent.YouDontCtrl,Permanent.nonLegendary", host.getController(), host);
}
choice = CardFactoryUtil.getBestAI(choices);
}
}
Card choice = player.getController().chooseSingleCardForEffect(choices, sa, "Choose a creature you control to encode ", true);
if (choice == null) {
return;
}

View File

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

View File

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

View File

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

View File

@@ -9,10 +9,10 @@ import forge.CardLists;
import forge.card.ability.AbilityFactory;
import forge.card.ability.AbilityUtils;
import forge.card.ability.SpellAbilityEffect;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.spellability.AbilitySub;
import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCard;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
import forge.gui.GuiChoose;
@@ -221,11 +221,11 @@ public class TwoPilesEffect extends SpellAbilityEffect {
break;
}
} else {
int cmc1 = CardFactoryUtil.evaluatePermanentList(new ArrayList<Card>(pile1));
int cmc2 = CardFactoryUtil.evaluatePermanentList(new ArrayList<Card>(pile2));
int cmc1 = ComputerUtilCard.evaluatePermanentList(new ArrayList<Card>(pile1));
int cmc2 = ComputerUtilCard.evaluatePermanentList(new ArrayList<Card>(pile2));
if (CardLists.getNotType(pool, "Creature").isEmpty()) {
cmc1 = CardFactoryUtil.evaluateCreatureList(new ArrayList<Card>(pile1));
cmc2 = CardFactoryUtil.evaluateCreatureList(new ArrayList<Card>(pile2));
cmc1 = ComputerUtilCard.evaluateCreatureList(new ArrayList<Card>(pile1));
cmc2 = ComputerUtilCard.evaluateCreatureList(new ArrayList<Card>(pile2));
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.spellability.SpellAbility;
import forge.card.spellability.Target;
import forge.game.ai.ComputerUtilCard;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
@@ -86,7 +87,7 @@ public class UntapEffect extends SpellAbilityEffect {
while ((list.size() != 0) && (count < num)) {
for (int i = 0; (i < list.size()) && (count < num); i++) {
final Card c = CardFactoryUtil.getBestLandAI(list);
final Card c = ComputerUtilCard.getBestLandAI(list);
c.untap();
list.remove(c);
count++;

View File

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

View File

@@ -18,17 +18,12 @@
package forge.card.cardfactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import com.esotericsoftware.minlog.Log;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
@@ -45,7 +40,6 @@ import forge.CounterType;
import forge.GameEntity;
import forge.Singletons;
import forge.card.CardCharacteristics;
import forge.card.CardType;
import forge.card.MagicColor;
import forge.card.ability.AbilityFactory;
import forge.card.ability.AbilityUtils;
@@ -71,8 +65,8 @@ import forge.card.trigger.TriggerHandler;
import forge.card.trigger.TriggerType;
import forge.control.input.Input;
import forge.game.GameState;
import forge.game.ai.AiAttackController;
import forge.game.ai.ComputerUtil;
import forge.game.ai.ComputerUtilCard;
import forge.game.ai.ComputerUtilCost;
import forge.game.event.TokenCreatedEvent;
import forge.game.phase.PhaseHandler;
@@ -85,7 +79,6 @@ import forge.game.zone.ZoneType;
import forge.gui.GuiChoose;
import forge.gui.match.CMatchUI;
import forge.util.Aggregates;
import forge.util.MyRandom;
import forge.view.ButtonUtil;
@@ -98,659 +91,6 @@ import forge.view.ButtonUtil;
* @version $Id$
*/
public class CardFactoryUtil {
private static Random random = MyRandom.getRandom();
/**
* <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>
* inputDestroyNoRegeneration.
@@ -3027,91 +2367,6 @@ public class CardFactoryUtil {
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>
* isMostProminentColor.
@@ -3153,96 +2408,6 @@ public class CardFactoryUtil {
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>
* makeToken.
@@ -3423,66 +2588,6 @@ public class CardFactoryUtil {
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>
@@ -4068,10 +3173,10 @@ public class CardFactoryUtil {
} else {
// AI choosing what to haunt
final List<Card> oppCreats = CardLists.filterControlledBy(creats, card.getController().getOpponent());
if (oppCreats.size() != 0) {
haunterDiesWork.setTargetCard(CardFactoryUtil.getWorstCreatureAI(oppCreats));
if (!oppCreats.isEmpty()) {
haunterDiesWork.setTargetCard(ComputerUtilCard.getWorstCreatureAI(oppCreats));
} else {
haunterDiesWork.setTargetCard(CardFactoryUtil.getWorstCreatureAI(creats));
haunterDiesWork.setTargetCard(ComputerUtilCard.getWorstCreatureAI(creats));
}
Singletons.getModel().getGame().getStack().add(haunterDiesWork);
}
@@ -4759,7 +3864,7 @@ public class CardFactoryUtil {
}
});
if (choices.size() != 0) {
ability.setTargetCard(CardFactoryUtil.getBestCreatureAI(choices));
ability.setTargetCard(ComputerUtilCard.getBestCreatureAI(choices));
if (ability.getTargetCard() != null) {
ability.setStackDescription("Put " + card.getCounters(CounterType.P1P1)

View File

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

View File

@@ -6,14 +6,13 @@ import java.util.List;
import com.google.common.collect.Lists;
import forge.Card;
import forge.CardColor;
import forge.CardLists;
import forge.CardPredicates;
import forge.CardUtil;
import forge.card.MagicColor;
import forge.card.ability.AbilityUtils;
import forge.card.ability.ApiType;
import forge.card.ability.effects.CharmEffect;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.Cost;
import forge.card.cost.CostPayment;
import forge.card.mana.ManaCostBeingPaid;
@@ -26,6 +25,7 @@ import forge.card.spellability.TargetSelection;
import forge.card.staticability.StaticAbility;
import forge.control.input.InputControl;
import forge.control.input.InputPayManaSimple;
import forge.game.ai.ComputerUtilCard;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
import forge.gui.GuiChoose;
@@ -196,7 +196,7 @@ public class GameActionPlay {
}
while (tapForConvoke != null && untappedCreats.size() != 0) {
final Card workingCard = (Card) tapForConvoke;
usableColors = CardUtil.getConvokableColors(workingCard, newCost);
usableColors = GameActionPlay.getConvokableColors(workingCard, newCost);
if (usableColors.size() != 0) {
String chosenColor = usableColors.get(0);
@@ -317,7 +317,7 @@ public class GameActionPlay {
}
}
if (chosen == null) {
chosen = CardFactoryUtil.getWorstCreatureAI(grave);
chosen = ComputerUtilCard.getWorstCreatureAI(grave);
}
if (chosen == null) {
@@ -503,4 +503,33 @@ public class GameActionPlay {
final String costCuttingGetMultiKickerManaCostPaidColored0) {
this.costCuttingGetMultiKickerManaCostPaidColored = costCuttingGetMultiKickerManaCostPaidColored0;
}
/**
* Gets the convokable colors.
*
* @param cardToConvoke
* the card to convoke
* @param cost
* the cost
* @return the convokable colors
*/
public static ArrayList<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.GameEntity;
import forge.Singletons;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.trigger.Trigger;
import forge.card.trigger.TriggerType;
import forge.game.GameState;
@@ -909,7 +908,7 @@ public class AiAttackController {
// see if the defending creature is of higher or lower
// value. We don't want to attack only to lose value
if (isWorthLessThanAllKillers && attacker.getSVar("SacMe").equals("")
&& CardFactoryUtil.evaluateCreature(defender) <= CardFactoryUtil.evaluateCreature(attacker)) {
&& ComputerUtilCard.evaluateCreature(defender) <= ComputerUtilCard.evaluateCreature(attacker)) {
isWorthLessThanAllKillers = false;
}
}

View File

@@ -596,7 +596,7 @@ public class AiController {
discardList.add(hand.get(0));
hand.remove(hand.get(0));
} else { //Discard worst card
Card worst = CardFactoryUtil.getWorstAI(hand);
Card worst = ComputerUtilCard.getWorstAI(hand);
discardList.add(worst);
hand.remove(worst);
}
@@ -606,14 +606,64 @@ public class AiController {
return discardList;
}
// These methods might be moved into matching SpellAbilityAi classes just without all these switches here
public Card chooseSingleCardForEffect(List<Card> options, SpellAbility sa, String title, boolean isOptional) {
ApiType api = sa.getApi();
if ( null == api ) {
throw new InvalidParameterException("SA is not api-based, this is not supported yet");
}
Card choice = null;
Card host = sa.getSourceCard();
String logic = sa.getParam("AILogic");
switch(api) {
case Bond: return CardFactoryUtil.getBestCreatureAI(options);
case Bond:
return ComputerUtilCard.getBestCreatureAI(options);
case ChooseCard:
if (logic == null) {
// Base Logic is choose "best"
choice = ComputerUtilCard.getBestAI(options);
} else if ("WorstCard".equals(logic)) {
choice = ComputerUtilCard.getWorstAI(options);
} else if (logic.equals("BestBlocker")) {
if (!CardLists.filter(options, Presets.UNTAPPED).isEmpty()) {
options = CardLists.filter(options, Presets.UNTAPPED);
}
choice = ComputerUtilCard.getBestCreatureAI(options);
} else if (logic.equals("Clone")) {
if (!CardLists.getValidCards(options, "Permanent.YouDontCtrl,Permanent.nonLegendary", host.getController(), host).isEmpty()) {
options = CardLists.getValidCards(options, "Permanent.YouDontCtrl,Permanent.nonLegendary", host.getController(), host);
}
choice = ComputerUtilCard.getBestAI(options);
} else if (logic.equals("Untap")) {
if (!CardLists.getValidCards(options, "Permanent.YouCtrl,Permanent.tapped", host.getController(), host).isEmpty()) {
options = CardLists.getValidCards(options, "Permanent.YouCtrl,Permanent.tapped", host.getController(), host);
}
choice = ComputerUtilCard.getBestAI(options);
}
return choice;
case Encode:
if (logic == null) {
// Base Logic is choose "best"
choice = ComputerUtilCard.getBestAI(options);
} else if ("WorstCard".equals(logic)) {
choice = ComputerUtilCard.getWorstAI(options);
} else if (logic.equals("BestBlocker")) {
if (!CardLists.filter(options, Presets.UNTAPPED).isEmpty()) {
options = CardLists.filter(options, Presets.UNTAPPED);
}
choice = ComputerUtilCard.getBestCreatureAI(options);
} else if (logic.equals("Clone")) {
if (!CardLists.getValidCards(options, "Permanent.YouDontCtrl,Permanent.nonLegendary", host.getController(), host).isEmpty()) {
options = CardLists.getValidCards(options, "Permanent.YouDontCtrl,Permanent.nonLegendary", host.getController(), host);
}
choice = ComputerUtilCard.getBestAI(options);
}
return choice;
default: throw new InvalidParameterException("AI chooseSingleCard does not know how to choose card for " + api);
}
}
@@ -627,12 +677,15 @@ public class AiController {
switch(api) {
case Discard:
if ( mode.equals("Random") ) { //
if ( mode.startsWith("Random") ) { //
// TODO For now AI will always discard Random used currently with: Balduvian Horde and similar cards
return true;
}
break;
case Encode:
return true;
default:
}
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(">")) {
final int amount = AbilityUtils.calculateAmount(source, unless, sa);
final int usableManaSources = CardFactoryUtil.getUsableManaSources(ai.getOpponent());
final int usableManaSources = ComputerUtilCard.getUsableManaSources(ai.getOpponent());
// If the Unless isn't enough, this should be less likely to be used
if (amount > usableManaSources) {
@@ -384,7 +384,7 @@ public class ComputerUtil {
if (landsInPlay.size() >= highestCMC
|| (landsInPlay.size() + landsInHand.size() > 6 && landsInHand.size() > 1)) {
// Don't need more land.
return CardFactoryUtil.getWorstLand(landsInHand);
return ComputerUtilCard.getWorstLand(landsInHand);
}
}
}
@@ -678,11 +678,11 @@ public class ComputerUtil {
Card c;
if (CardLists.getNotType(remaining, "Creature").size() == 0) {
c = CardFactoryUtil.getWorstCreatureAI(remaining);
c = ComputerUtilCard.getWorstCreatureAI(remaining);
} else if (CardLists.getNotType(remaining, "Land").size() == 0) {
c = CardFactoryUtil.getWorstLand(CardLists.filter(remaining, CardPredicates.Presets.LANDS));
c = ComputerUtilCard.getWorstLand(CardLists.filter(remaining, CardPredicates.Presets.LANDS));
} else {
c = CardFactoryUtil.getWorstPermanentAI(remaining, false, false, false, false);
c = ComputerUtilCard.getWorstPermanentAI(remaining, false, false, false, false);
}
final ArrayList<Card> auras = c.getEnchantedBy();

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

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) {
final int artsCnt = c.getRules().getEditionInfo(setCode3).getCopiesCount();
final String filename = CardUtil.buildIdealFilename(cardName, c.getArtIndex(), artsCnt);
final String filename = GuiDownloadPicturesLQ.buildIdealFilename(cardName, c.getArtIndex(), artsCnt);
String url = urlBase + setCode2 + "/" + Base64Coder.encodeString(filename, true);
cList.add(new DownloadObject(url, new File(this.picturesPath + File.separator + setCode3, filename)));