- Basic AI upgrade to check for possible animated creatures (ie. manlands) before deciding attackers

This commit is contained in:
excessum
2014-04-01 14:50:54 +00:00
parent fb9d515404
commit e0b93081c2
2 changed files with 284 additions and 1 deletions

View File

@@ -20,13 +20,17 @@ package forge.ai;
import com.google.common.base.Predicate;
import com.google.common.collect.Lists;
import forge.ai.ability.AnimateAi;
import forge.game.GameEntity;
import forge.game.ability.ApiType;
import forge.game.card.Card;
import forge.game.card.CardFactory;
import forge.game.card.CardLists;
import forge.game.card.CounterType;
import forge.game.combat.Combat;
import forge.game.combat.CombatUtil;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.trigger.Trigger;
import forge.game.trigger.TriggerType;
import forge.game.zone.ZoneType;
@@ -82,7 +86,23 @@ public class AiAttackController {
this.oppList = Lists.newArrayList();
this.oppList.addAll(this.defendingOpponent.getCreaturesInPlay());
this.myList = ai.getCreaturesInPlay();
Predicate<Card> canAnimate = new Predicate<Card>() {
@Override
public boolean apply(Card c) {
return !c.isCreature() && !c.isPlaneswalker();
}
};
for (Card c : CardLists.filter(this.defendingOpponent.getCardsIn(ZoneType.Battlefield), canAnimate)) {
for (SpellAbility sa : c.getSpellAbilities()) {
if (sa.getApi() == ApiType.Animate) {
if (ComputerUtilCost.canPayCost(sa, this.defendingOpponent)) {
Card animatedCopy = CardFactory.getCard(c.getPaperCard(), this.defendingOpponent);
AnimateAi.becomeAnimated(animatedCopy, sa);
this.oppList.add(animatedCopy);
}
}
}
}
this.attackers = new ArrayList<Card>();
for (Card c : myList) {

View File

@@ -4,18 +4,28 @@ import com.google.common.collect.Iterables;
import forge.ai.SpellAbilityAi;
import forge.game.Game;
import forge.game.ability.AbilityFactory;
import forge.game.ability.AbilityUtils;
import forge.game.card.Card;
import forge.game.card.CardLists;
import forge.game.card.CardPredicates;
import forge.game.card.CardUtil;
import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.replacement.ReplacementEffect;
import forge.game.replacement.ReplacementHandler;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.game.staticability.StaticAbility;
import forge.game.trigger.Trigger;
import forge.game.trigger.TriggerHandler;
import forge.game.zone.ZoneType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* <p>
@@ -196,4 +206,257 @@ public class AnimateAi extends SpellAbilityAi {
return false;
}
public static void becomeAnimated(Card source, SpellAbility sa) {
//duplicating AnimateEffect.resolve
final Game game = sa.getActivatingPlayer().getGame();
final Map<String, String> svars = source.getSVars();
final long timestamp = game.getNextTimestamp();
// AF specific sa
int power = -1;
if (sa.hasParam("Power")) {
power = AbilityUtils.calculateAmount(source, sa.getParam("Power"), sa);
}
int toughness = -1;
if (sa.hasParam("Toughness")) {
toughness = AbilityUtils.calculateAmount(source, sa.getParam("Toughness"), sa);
}
final ArrayList<String> types = new ArrayList<String>();
if (sa.hasParam("Types")) {
types.addAll(Arrays.asList(sa.getParam("Types").split(",")));
}
final ArrayList<String> removeTypes = new ArrayList<String>();
if (sa.hasParam("RemoveTypes")) {
removeTypes.addAll(Arrays.asList(sa.getParam("RemoveTypes").split(",")));
}
// allow ChosenType - overrides anything else specified
if (types.contains("ChosenType")) {
types.clear();
types.add(source.getChosenType());
}
final ArrayList<String> keywords = new ArrayList<String>();
if (sa.hasParam("Keywords")) {
keywords.addAll(Arrays.asList(sa.getParam("Keywords").split(" & ")));
}
final ArrayList<String> removeKeywords = new ArrayList<String>();
if (sa.hasParam("RemoveKeywords")) {
removeKeywords.addAll(Arrays.asList(sa.getParam("RemoveKeywords").split(" & ")));
}
final ArrayList<String> hiddenKeywords = new ArrayList<String>();
if (sa.hasParam("HiddenKeywords")) {
hiddenKeywords.addAll(Arrays.asList(sa.getParam("HiddenKeywords").split(" & ")));
}
// allow SVar substitution for keywords
for (int i = 0; i < keywords.size(); i++) {
final String k = keywords.get(i);
if (svars.containsKey(k)) {
keywords.add(svars.get(k));
keywords.remove(k);
}
}
// colors to be added or changed to
String tmpDesc = "";
if (sa.hasParam("Colors")) {
final String colors = sa.getParam("Colors");
if (colors.equals("ChosenColor")) {
tmpDesc = CardUtil.getShortColorsString(source.getChosenColor());
} else {
tmpDesc = CardUtil.getShortColorsString(new ArrayList<String>(Arrays.asList(colors.split(","))));
}
}
final String finalDesc = tmpDesc;
// abilities to add to the animated being
final ArrayList<String> abilities = new ArrayList<String>();
if (sa.hasParam("Abilities")) {
abilities.addAll(Arrays.asList(sa.getParam("Abilities").split(",")));
}
// replacement effects to add to the animated being
final ArrayList<String> replacements = new ArrayList<String>();
if (sa.hasParam("Replacements")) {
replacements.addAll(Arrays.asList(sa.getParam("Replacements").split(",")));
}
// triggers to add to the animated being
final ArrayList<String> triggers = new ArrayList<String>();
if (sa.hasParam("Triggers")) {
triggers.addAll(Arrays.asList(sa.getParam("Triggers").split(",")));
}
// static abilities to add to the animated being
final ArrayList<String> stAbs = new ArrayList<String>();
if (sa.hasParam("staticAbilities")) {
stAbs.addAll(Arrays.asList(sa.getParam("staticAbilities").split(",")));
}
// sVars to add to the animated being
final ArrayList<String> sVars = new ArrayList<String>();
if (sa.hasParam("sVars")) {
sVars.addAll(Arrays.asList(sa.getParam("sVars").split(",")));
}
//duplicating AnimateEffectBase.doAnimate
boolean removeSuperTypes = false;
boolean removeCardTypes = false;
boolean removeSubTypes = false;
boolean removeCreatureTypes = false;
if (sa.hasParam("OverwriteTypes")) {
removeSuperTypes = true;
removeCardTypes = true;
removeSubTypes = true;
removeCreatureTypes = true;
}
if (sa.hasParam("KeepSupertypes")) {
removeSuperTypes = false;
}
if (sa.hasParam("KeepCardTypes")) {
removeCardTypes = false;
}
if (sa.hasParam("RemoveSuperTypes")) {
removeSuperTypes = true;
}
if (sa.hasParam("RemoveCardTypes")) {
removeCardTypes = true;
}
if (sa.hasParam("RemoveSubTypes")) {
removeSubTypes = true;
}
if (sa.hasParam("RemoveCreatureTypes")) {
removeCreatureTypes = true;
}
if ((power != -1) || (toughness != -1)) {
source.addNewPT(power, toughness, timestamp);
}
if (!types.isEmpty() || !removeTypes.isEmpty() || removeCreatureTypes) {
source.addChangedCardTypes(types, removeTypes, removeSuperTypes, removeCardTypes, removeSubTypes,
removeCreatureTypes, timestamp);
}
source.addChangedCardKeywords(keywords, removeKeywords, sa.hasParam("RemoveAllAbilities"), timestamp);
for (final String k : hiddenKeywords) {
source.addHiddenExtrinsicKeyword(k);
}
source.addColor(finalDesc, !sa.hasParam("OverwriteColors"), true);
//back to duplicating AnimateEffect.resolve
//TODO will all these abilities/triggers/replacements/etc. lead to memory leaks or unintended effects?
// remove abilities
final ArrayList<SpellAbility> removedAbilities = new ArrayList<SpellAbility>();
boolean clearAbilities = sa.hasParam("OverwriteAbilities");
boolean clearSpells = sa.hasParam("OverwriteSpells");
boolean removeAll = sa.hasParam("RemoveAllAbilities");
if (clearAbilities || clearSpells || removeAll) {
for (final SpellAbility ab : source.getSpellAbilities()) {
if (removeAll || (ab.isAbility() && clearAbilities)
|| (ab.isSpell() && clearSpells)) {
source.removeSpellAbility(ab);
removedAbilities.add(ab);
}
}
}
// give abilities
final ArrayList<SpellAbility> addedAbilities = new ArrayList<SpellAbility>();
if (abilities.size() > 0) {
for (final String s : abilities) {
final String actualAbility = source.getSVar(s);
final SpellAbility grantedAbility = AbilityFactory.getAbility(actualAbility, source);
addedAbilities.add(grantedAbility);
source.addSpellAbility(grantedAbility);
}
}
// Grant triggers
final ArrayList<Trigger> addedTriggers = new ArrayList<Trigger>();
if (triggers.size() > 0) {
for (final String s : triggers) {
final String actualTrigger = source.getSVar(s);
final Trigger parsedTrigger = TriggerHandler.parseTrigger(actualTrigger, source, false);
addedTriggers.add(source.addTrigger(parsedTrigger));
}
}
// give replacement effects
final ArrayList<ReplacementEffect> addedReplacements = new ArrayList<ReplacementEffect>();
if (replacements.size() > 0) {
for (final String s : replacements) {
final String actualReplacement = source.getSVar(s);
final ReplacementEffect parsedReplacement = ReplacementHandler.parseReplacement(actualReplacement, source, false);
addedReplacements.add(source.addReplacementEffect(parsedReplacement));
}
}
// suppress triggers from the animated card
final ArrayList<Trigger> removedTriggers = new ArrayList<Trigger>();
if (sa.hasParam("OverwriteTriggers") || removeAll) {
final List<Trigger> triggersToRemove = source.getTriggers();
for (final Trigger trigger : triggersToRemove) {
trigger.setSuppressed(true);
removedTriggers.add(trigger);
}
}
// give static abilities (should only be used by cards to give
// itself a static ability)
if (stAbs.size() > 0) {
for (final String s : stAbs) {
final String actualAbility = source.getSVar(s);
source.addStaticAbility(actualAbility);
}
}
// give sVars
if (sVars.size() > 0) {
for (final String s : sVars) {
String actualsVar = source.getSVar(s);
String name = s;
if (actualsVar.startsWith("SVar:")) {
actualsVar = actualsVar.split("SVar:")[1];
name = actualsVar.split(":")[0];
actualsVar = actualsVar.split(":")[1];
}
source.setSVar(name, actualsVar);
}
}
// suppress static abilities from the animated card
final ArrayList<StaticAbility> removedStatics = new ArrayList<StaticAbility>();
if (sa.hasParam("OverwriteStatics") || removeAll) {
final ArrayList<StaticAbility> staticsToRemove = source.getStaticAbilities();
for (final StaticAbility stAb : staticsToRemove) {
stAb.setTemporarilySuppressed(true);
removedStatics.add(stAb);
}
}
// suppress static abilities from the animated card
final ArrayList<ReplacementEffect> removedReplacements = new ArrayList<ReplacementEffect>();
if (sa.hasParam("OverwriteReplacements") || removeAll) {
for (final ReplacementEffect re : source.getReplacementEffects()) {
re.setTemporarilySuppressed(true);
removedReplacements.add(re);
}
}
}
}