mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-12 16:58:57 +00:00
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:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user