- Bristling Hydra AI: teach the AI to use a ping activation to save the hydra from death.

This commit is contained in:
Agetian
2017-08-25 10:57:12 +00:00
parent 8280401e10
commit 909b8e7127
3 changed files with 42 additions and 15 deletions

View File

@@ -45,6 +45,7 @@ public class AiCardMemory {
private final Set<Card> memAttachedThisTurn; private final Set<Card> memAttachedThisTurn;
private final Set<Card> memAnimatedThisTurn; private final Set<Card> memAnimatedThisTurn;
private final Set<Card> memBouncedThisTurn; private final Set<Card> memBouncedThisTurn;
private final Set<Card> memActivatedThisTurn;
public AiCardMemory() { public AiCardMemory() {
this.memMandatoryAttackers = new HashSet<>(); this.memMandatoryAttackers = new HashSet<>();
@@ -52,6 +53,7 @@ public class AiCardMemory {
this.memAttachedThisTurn = new HashSet<>(); this.memAttachedThisTurn = new HashSet<>();
this.memAnimatedThisTurn = new HashSet<>(); this.memAnimatedThisTurn = new HashSet<>();
this.memBouncedThisTurn = new HashSet<>(); this.memBouncedThisTurn = new HashSet<>();
this.memActivatedThisTurn = new HashSet<>();
} }
/** /**
@@ -65,6 +67,7 @@ public class AiCardMemory {
ATTACHED_THIS_TURN, ATTACHED_THIS_TURN,
ANIMATED_THIS_TURN, ANIMATED_THIS_TURN,
BOUNCED_THIS_TURN, BOUNCED_THIS_TURN,
ACTIVATED_THIS_TURN,
//REVEALED_CARDS // stub, not linked to AI code yet //REVEALED_CARDS // stub, not linked to AI code yet
} }
@@ -80,6 +83,8 @@ public class AiCardMemory {
return memAnimatedThisTurn; return memAnimatedThisTurn;
case BOUNCED_THIS_TURN: case BOUNCED_THIS_TURN:
return memBouncedThisTurn; return memBouncedThisTurn;
case ACTIVATED_THIS_TURN:
return memActivatedThisTurn;
//case REVEALED_CARDS: //case REVEALED_CARDS:
// return memRevealedCards; // return memRevealedCards;
default: default:
@@ -253,6 +258,7 @@ public class AiCardMemory {
clearMemorySet(MemorySet.ATTACHED_THIS_TURN); clearMemorySet(MemorySet.ATTACHED_THIS_TURN);
clearMemorySet(MemorySet.ANIMATED_THIS_TURN); clearMemorySet(MemorySet.ANIMATED_THIS_TURN);
clearMemorySet(MemorySet.BOUNCED_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. // Static functions to simplify access to AI card memory of a given AI player.

View File

@@ -1435,20 +1435,28 @@ public class ComputerUtil {
} }
objects = canBeTargeted; objects = canBeTargeted;
} }
if (saviourApi == ApiType.Pump || saviourApi == ApiType.PumpAll) { SpellAbility saviorWithSubs = saviour;
toughness = saviour.hasParam("NumDef") ? while (saviorWithSubs != null) {
AbilityUtils.calculateAmount(saviour.getHostCard(), saviour.getParam("NumDef"), saviour) : 0; ApiType curApi = saviorWithSubs.getApi();
final List<String> keywords = saviour.hasParam("KW") ? if (curApi == ApiType.Pump || curApi == ApiType.PumpAll) {
Arrays.asList(saviour.getParam("KW").split(" & ")) : new ArrayList<String>(); toughness = saviorWithSubs.hasParam("NumDef") ?
if (keywords.contains("Indestructible")) { AbilityUtils.calculateAmount(saviorWithSubs.getHostCard(), saviorWithSubs.getParam("NumDef"), saviour) : 0;
grantIndestructible = true; final List<String> keywords = saviorWithSubs.hasParam("KW") ?
} Arrays.asList(saviorWithSubs.getParam("KW").split(" & ")) : new ArrayList<String>();
if (keywords.contains("Hexproof") || keywords.contains("Shroud")) { if (keywords.contains("Indestructible")) {
grantShroud = true; 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) { if (saviourApi == ApiType.PutCounter || saviourApi == ApiType.PutCounterAll) {
if (saviour.getParam("CounterType").equals("P1P1")) { if (saviour.getParam("CounterType").equals("P1P1")) {
toughness = AbilityUtils.calculateAmount(saviour.getHostCard(), saviour.getParam("CounterNum"), saviour); toughness = AbilityUtils.calculateAmount(saviour.getHostCard(), saviour.getParam("CounterNum"), saviour);
@@ -1588,9 +1596,11 @@ public class ComputerUtil {
// Destroy => regeneration/bounce/shroud // Destroy => regeneration/bounce/shroud
else if ((threatApi == ApiType.Destroy || threatApi == ApiType.DestroyAll) else if ((threatApi == ApiType.Destroy || threatApi == ApiType.DestroyAll)
&& (((saviourApi == ApiType.Regenerate || saviourApi == ApiType.RegenerateAll) && (((saviourApi == ApiType.Regenerate || saviourApi == ApiType.RegenerateAll)
&& !topStack.hasParam("NoRegen")) || saviourApi == ApiType.ChangeZone && !topStack.hasParam("NoRegen")) || saviourApi == ApiType.ChangeZone
|| saviourApi == ApiType.Pump || saviourApi == ApiType.PumpAll || 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) { for (final Object o : objects) {
if (o instanceof Card) { if (o instanceof Card) {
final Card c = (Card) o; final Card c = (Card) o;
@@ -1604,7 +1614,9 @@ public class ComputerUtil {
continue; 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) if ((tgt == null && !grantIndestructible)
|| (!grantShroud && !grantIndestructible)) { || (!grantShroud && !grantIndestructible)) {
continue; continue;

View File

@@ -249,6 +249,15 @@ public class CountersPutAi extends SpellAbilityAi {
return true; 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()) { } 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 // outside of combat, this logic only works if the relevant AI profile option is enabled
// and if there is enough energy saved // and if there is enough energy saved