mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 12:18:00 +00:00
- Bristling Hydra AI: teach the AI to use a ping activation to save the hydra from death.
This commit is contained in:
@@ -45,6 +45,7 @@ public class AiCardMemory {
|
||||
private final Set<Card> memAttachedThisTurn;
|
||||
private final Set<Card> memAnimatedThisTurn;
|
||||
private final Set<Card> memBouncedThisTurn;
|
||||
private final Set<Card> memActivatedThisTurn;
|
||||
|
||||
public AiCardMemory() {
|
||||
this.memMandatoryAttackers = new HashSet<>();
|
||||
@@ -52,6 +53,7 @@ public class AiCardMemory {
|
||||
this.memAttachedThisTurn = new HashSet<>();
|
||||
this.memAnimatedThisTurn = new HashSet<>();
|
||||
this.memBouncedThisTurn = new HashSet<>();
|
||||
this.memActivatedThisTurn = new HashSet<>();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,6 +67,7 @@ public class AiCardMemory {
|
||||
ATTACHED_THIS_TURN,
|
||||
ANIMATED_THIS_TURN,
|
||||
BOUNCED_THIS_TURN,
|
||||
ACTIVATED_THIS_TURN,
|
||||
//REVEALED_CARDS // stub, not linked to AI code yet
|
||||
}
|
||||
|
||||
@@ -80,6 +83,8 @@ public class AiCardMemory {
|
||||
return memAnimatedThisTurn;
|
||||
case BOUNCED_THIS_TURN:
|
||||
return memBouncedThisTurn;
|
||||
case ACTIVATED_THIS_TURN:
|
||||
return memActivatedThisTurn;
|
||||
//case REVEALED_CARDS:
|
||||
// return memRevealedCards;
|
||||
default:
|
||||
@@ -253,6 +258,7 @@ public class AiCardMemory {
|
||||
clearMemorySet(MemorySet.ATTACHED_THIS_TURN);
|
||||
clearMemorySet(MemorySet.ANIMATED_THIS_TURN);
|
||||
clearMemorySet(MemorySet.BOUNCED_THIS_TURN);
|
||||
clearMemorySet(MemorySet.ACTIVATED_THIS_TURN);
|
||||
}
|
||||
|
||||
// Static functions to simplify access to AI card memory of a given AI player.
|
||||
|
||||
@@ -1436,17 +1436,25 @@ public class ComputerUtil {
|
||||
objects = canBeTargeted;
|
||||
}
|
||||
|
||||
if (saviourApi == ApiType.Pump || saviourApi == ApiType.PumpAll) {
|
||||
toughness = saviour.hasParam("NumDef") ?
|
||||
AbilityUtils.calculateAmount(saviour.getHostCard(), saviour.getParam("NumDef"), saviour) : 0;
|
||||
final List<String> keywords = saviour.hasParam("KW") ?
|
||||
Arrays.asList(saviour.getParam("KW").split(" & ")) : new ArrayList<String>();
|
||||
SpellAbility saviorWithSubs = saviour;
|
||||
while (saviorWithSubs != null) {
|
||||
ApiType curApi = saviorWithSubs.getApi();
|
||||
if (curApi == ApiType.Pump || curApi == ApiType.PumpAll) {
|
||||
toughness = saviorWithSubs.hasParam("NumDef") ?
|
||||
AbilityUtils.calculateAmount(saviorWithSubs.getHostCard(), saviorWithSubs.getParam("NumDef"), saviour) : 0;
|
||||
final List<String> keywords = saviorWithSubs.hasParam("KW") ?
|
||||
Arrays.asList(saviorWithSubs.getParam("KW").split(" & ")) : new ArrayList<String>();
|
||||
if (keywords.contains("Indestructible")) {
|
||||
grantIndestructible = true;
|
||||
}
|
||||
if (keywords.contains("Hexproof") || keywords.contains("Shroud")) {
|
||||
grantShroud = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Consider pump in subabilities, e.g. Bristling Hydra hexproof subability
|
||||
saviorWithSubs = saviorWithSubs.getSubAbility();
|
||||
|
||||
}
|
||||
|
||||
if (saviourApi == ApiType.PutCounter || saviourApi == ApiType.PutCounterAll) {
|
||||
@@ -1590,7 +1598,9 @@ public class ComputerUtil {
|
||||
&& (((saviourApi == ApiType.Regenerate || saviourApi == ApiType.RegenerateAll)
|
||||
&& !topStack.hasParam("NoRegen")) || saviourApi == ApiType.ChangeZone
|
||||
|| saviourApi == ApiType.Pump || saviourApi == ApiType.PumpAll
|
||||
|| saviourApi == ApiType.Protection || saviourApi == null)) {
|
||||
|| saviourApi == ApiType.Protection || saviourApi == null
|
||||
|| saviorWithSubs.getApi() == ApiType.Pump
|
||||
|| saviorWithSubs.getApi() == ApiType.PumpAll)) {
|
||||
for (final Object o : objects) {
|
||||
if (o instanceof Card) {
|
||||
final Card c = (Card) o;
|
||||
@@ -1604,7 +1614,9 @@ public class ComputerUtil {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (saviourApi == ApiType.Pump || saviourApi == ApiType.PumpAll) {
|
||||
if (saviourApi == ApiType.Pump || saviourApi == ApiType.PumpAll
|
||||
|| saviorWithSubs.getApi() == ApiType.Pump
|
||||
|| saviorWithSubs.getApi() == ApiType.PumpAll) {
|
||||
if ((tgt == null && !grantIndestructible)
|
||||
|| (!grantShroud && !grantIndestructible)) {
|
||||
continue;
|
||||
|
||||
@@ -249,6 +249,15 @@ public class CountersPutAi extends SpellAbilityAi {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if (sa.getSubAbility() != null
|
||||
&& "Self".equals(sa.getSubAbility().getParam("Defined"))
|
||||
&& sa.getSubAbility().getParamOrDefault("KW", "").contains("Hexproof")
|
||||
&& !AiCardMemory.isRememberedCard(ai, source, AiCardMemory.MemorySet.ANIMATED_THIS_TURN)) {
|
||||
// Bristling Hydra: save from death using a ping activation
|
||||
if (ComputerUtil.predictThreatenedObjects(sa.getActivatingPlayer(), sa).contains(source)) {
|
||||
AiCardMemory.rememberCard(ai, source, AiCardMemory.MemorySet.ACTIVATED_THIS_TURN);
|
||||
return true;
|
||||
}
|
||||
} else if (ai.getCounters(CounterType.ENERGY) > ComputerUtilCard.getMaxSAEnergyCostOnBattlefield(ai) + sa.getPayCosts().getCostEnergy().convertAmount()) {
|
||||
// outside of combat, this logic only works if the relevant AI profile option is enabled
|
||||
// and if there is enough energy saved
|
||||
|
||||
Reference in New Issue
Block a user