mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 10:48:00 +00:00
- Basic AI upgrade to check for possible animated creatures (ie. manlands) before deciding attackers
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user