diff --git a/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java b/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java index 419f51f0bda..6e041ed57ac 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java @@ -1445,10 +1445,14 @@ public class ChangeZoneAi extends SpellAbilityAi { * @return a boolean. */ private static boolean knownOriginTriggerAI(final Player ai, final SpellAbility sa, final boolean mandatory) { - if ("DeathgorgeScavenger".equals(sa.getParam("AILogic"))) { + final String logic = sa.getParamOrDefault("AILogic", ""); + + if ("DeathgorgeScavenger".equals(logic)) { return SpecialCardAi.DeathgorgeScavenger.consider(ai, sa); - } else if ("ExtraplanarLens".equals(sa.getParam("AILogic"))) { + } else if ("ExtraplanarLens".equals(logic)) { return SpecialCardAi.ExtraplanarLens.consider(ai, sa); + } else if ("ExileCombatThreat".equals(logic)) { + return doExileCombatThreatLogic(ai, sa); } if (sa.getTargetRestrictions() == null) { @@ -1821,6 +1825,51 @@ public class ChangeZoneAi extends SpellAbilityAi { return true; } + public static boolean doExileCombatThreatLogic(final Player aiPlayer, final SpellAbility sa) { + final Combat combat = aiPlayer.getGame().getCombat(); + + if (combat == null) { + return false; + } + + Card choice = null; + int highestEval = -1; + if (combat.getAttackingPlayer().isOpponentOf(aiPlayer)) { + for (Card attacker : combat.getAttackers()) { + if (sa.canTarget(attacker) && attacker.canBeTargetedBy(sa)) { + int eval = ComputerUtilCard.evaluateCreature(attacker); + if (combat.isUnblocked(attacker)) { + eval += 100; // TODO: make this smarter + } + if (eval > highestEval) { + highestEval = eval; + choice = attacker; + } + } + } + } else { + // either the current AI player or one of its teammates is attacking, the opponent(s) are blocking + for (Card blocker : combat.getAllBlockers()) { + if (sa.canTarget(blocker) && blocker.canBeTargetedBy(sa)) { + if (blocker.getController().isOpponentOf(aiPlayer)) { // TODO: unnecessary sanity check? + int eval = ComputerUtilCard.evaluateCreature(blocker); + if (eval > highestEval) { + highestEval = eval; + choice = blocker; + } + } + } + } + } + + if (choice != null) { + sa.getTargets().add(choice); + return true; + } else { + return false; + } + } + private static CardCollection getSafeTargetsIfUnlessCostPaid(Player ai, SpellAbility sa, Iterable potentialTgts) { // Determines if the controller of each potential target can negate the ChangeZone effect // by paying the Unless cost. Returns the list of targets that can be saved that way. diff --git a/forge-gui/res/cardsfolder/upcoming/sigrid_god_favored.txt b/forge-gui/res/cardsfolder/upcoming/sigrid_god_favored.txt index f51ced7a2cf..e95549673a7 100644 --- a/forge-gui/res/cardsfolder/upcoming/sigrid_god_favored.txt +++ b/forge-gui/res/cardsfolder/upcoming/sigrid_god_favored.txt @@ -6,9 +6,10 @@ K:Flash K:First Strike K:Protection:Creature.God:Protection from God creatures T:Mode$ ChangesZone | ValidCard$ Card.Self | Destination$ Battlefield | Execute$ TrigChangeZone | TriggerDescription$ When CARDNAME enters the battlefield, exile up to one target attacking or blocking creature until NICKNAME leaves the battlefield. -SVar:TrigChangeZone:DB$ ChangeZone | Origin$ Battlefield | Destination$ Exile | ValidTgts$ Creature.attacking,Creature.blocking | AITgts$ Creature.OppCtrl+attacking,Creature.OppCtrl+blocking | TgtPrompt$ Select target attacking or blocking creature | TargetMin$ 0 | TargetMax$ 1 | ConditionPresent$ Card.Self | SubAbility$ DBEffect +SVar:TrigChangeZone:DB$ ChangeZone | Origin$ Battlefield | Destination$ Exile | ValidTgts$ Creature.attacking,Creature.blocking | AITgts$ Creature.OppCtrl+attacking,Creature.OppCtrl+blocking | TgtPrompt$ Select target attacking or blocking creature | TargetMin$ 0 | TargetMax$ 1 | ConditionPresent$ Card.Self | AILogic$ ExileCombatThreat | SubAbility$ DBEffect SVar:DBEffect:DB$ Effect | Triggers$ ComeBack | RememberObjects$ Targeted | ImprintCards$ Self | SVars$ TrigReturn,ExileSelf | ConditionPresent$ Card.Self | Duration$ Permanent | ForgetOnMoved$ Exile SVar:ComeBack:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | ValidCard$ Card.IsImprinted | Execute$ TrigReturn | TriggerZones$ Command | TriggerController$ TriggeredCardController | Static$ True | TriggerDescription$ Target creature is exiled until EFFECTSOURCE leaves the battlefield. SVar:TrigReturn:DB$ ChangeZoneAll | Origin$ Exile | Destination$ Battlefield | ChangeType$ Card.IsRemembered | SubAbility$ ExileSelf SVar:ExileSelf:DB$ ChangeZone | Origin$ Command | Destination$ Exile | Defined$ Self +SVar:AmbushAI:True Oracle:Flash\nFirst strike, protection from God creatures\nWhen Sigrid, God-Favored enters the battlefield, exile up to one target attacking or blocking creature until Sigrid leaves the battlefield.