Merge pull request #3987 from Agetian/master

Further improve AI for Sakura-Tribe Elder and similar, fix Rampaging Geoderm AI missing a trigger.
This commit is contained in:
kevlahnota
2023-10-27 18:11:04 +08:00
committed by GitHub
3 changed files with 41 additions and 3 deletions

View File

@@ -359,8 +359,12 @@ public class ComputerUtilCost {
if (source.isCreature()) {
// e.g. Sakura Tribe-Elder
final boolean beforeNextTurn = ai.getGame().getPhaseHandler().is(PhaseType.END_OF_TURN) && ai.getGame().getPhaseHandler().getNextTurn().equals(ai);
final boolean inDanger = ComputerUtil.predictThreatenedObjects(ai, sourceAbility, true).contains(source);
if (!(inDanger || beforeNextTurn)) {
final boolean creatureInDanger = ComputerUtil.predictCreatureWillDieThisTurn(ai, source, sourceAbility);
final int lifeThreshold = (((PlayerControllerAi) ai.getController()).getAi().getIntProperty(AiProps.AI_IN_DANGER_THRESHOLD));
final boolean aiInDanger = ai.getLife() <= lifeThreshold && ai.canLoseLife() && !ai.cantLoseForZeroOrLessLife();
if (creatureInDanger) {
return true;
} else if (aiInDanger || !beforeNextTurn) {
return false;
}
}

View File

@@ -3,8 +3,15 @@ package forge.ai.ability;
import java.util.Map;
import com.google.common.base.Predicate;
import forge.ai.ComputerUtilCard;
import forge.ai.SpecialCardAi;
import forge.ai.SpellAbilityAi;
import forge.game.GameEntity;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardLists;
import forge.game.combat.Combat;
import forge.game.player.Player;
import forge.game.player.PlayerActionConfirmMode;
import forge.game.spellability.SpellAbility;
@@ -18,12 +25,39 @@ public class BranchAi extends SpellAbilityAi {
final String aiLogic = sa.getParamOrDefault("AILogic", "");
if ("GrislySigil".equals(aiLogic)) {
return SpecialCardAi.GrislySigil.consider(aiPlayer, sa);
} else if ("TgtAttacker".equals(aiLogic)) {
final Combat combat = aiPlayer.getGame().getCombat();
if (combat == null || combat.getAttackingPlayer() != aiPlayer) {
return false;
}
final CardCollection attackers = combat.getAttackers();
final CardCollection attackingBattle = CardLists.filter(attackers, new Predicate<Card>() {
@Override
public boolean apply(Card card) {
final GameEntity def = combat.getDefenderByAttacker(combat.getBandOfAttacker(card));
return def instanceof Card && ((Card)def).isBattle();
}
});
if (!attackingBattle.isEmpty()) {
sa.getTargets().add(ComputerUtilCard.getBestCreatureAI(attackingBattle));
} else {
sa.getTargets().add(ComputerUtilCard.getBestCreatureAI(attackers));
}
return sa.isTargetNumberValid();
}
// TODO: expand for other cases where the AI is needed to make a decision on a branch
return true;
}
@Override
protected boolean doTriggerAINoCost(Player aiPlayer, SpellAbility sa, boolean mandatory) {
return canPlayAI(aiPlayer, sa) || mandatory;
}
@Override
public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message, Map<String, Object> params) {
return true;

View File

@@ -5,7 +5,7 @@ PT:3/3
K:Trample
K:Haste
T:Mode$ AttackersDeclared | AttackingPlayer$ You | Execute$ TrigPump | TriggerZones$ Battlefield | TriggerDescription$ Whenever you attack, target attacking creature gets +1/+1 until end of turn. If it's attacking a battle, put a +1/+1 counter on it instead.
SVar:TrigPump:DB$ Branch | ValidTgts$ Creature.attacking | TgtPrompt$ Select target attacking creature | BranchConditionSVar$ X | TrueSubAbility$ PutCounter | FalseSubAbility$ Pump
SVar:TrigPump:DB$ Branch | ValidTgts$ Creature.attacking | TgtPrompt$ Select target attacking creature | BranchConditionSVar$ X | TrueSubAbility$ PutCounter | FalseSubAbility$ Pump | AILogic$ TgtAttacker
SVar:PutCounter:DB$ PutCounter | Defined$ Targeted | CounterType$ P1P1
SVar:Pump:DB$ Pump | Defined$ Targeted | NumAtt$ +1 | NumDef$ +1
SVar:X:Targeted$Valid Card.attackingBattle