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> 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.
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user