- Improved the implementation: clear the memory set for reentry-susceptible cards when starting to consider a new SA.

- Some more improvements in AiCardMemory.
This commit is contained in:
Agetian
2018-10-30 15:04:58 +03:00
parent 1ab9f2cae5
commit 0ab87d46b4
3 changed files with 30 additions and 3 deletions

View File

@@ -290,34 +290,54 @@ public class AiCardMemory {
} }
((PlayerControllerAi)ai.getController()).getAi().getCardMemory().rememberCard(c, set); ((PlayerControllerAi)ai.getController()).getAi().getCardMemory().rememberCard(c, set);
} }
public static void rememberCard(AiController aic, Card c, MemorySet set) {
aic.getCardMemory().rememberCard(c, set);
}
public static void forgetCard(Player ai, Card c, MemorySet set) { public static void forgetCard(Player ai, Card c, MemorySet set) {
if (!ai.getController().isAI()) { if (!ai.getController().isAI()) {
return; return;
} }
((PlayerControllerAi)ai.getController()).getAi().getCardMemory().forgetCard(c, set); ((PlayerControllerAi)ai.getController()).getAi().getCardMemory().forgetCard(c, set);
} }
public static void forgetCard(AiController aic, Card c, MemorySet set) {
aic.getCardMemory().forgetCard(c, set);
}
public static boolean isRememberedCard(Player ai, Card c, MemorySet set) { public static boolean isRememberedCard(Player ai, Card c, MemorySet set) {
if (!ai.getController().isAI()) { if (!ai.getController().isAI()) {
return false; return false;
} }
return ((PlayerControllerAi)ai.getController()).getAi().getCardMemory().isRememberedCard(c, set); return ((PlayerControllerAi)ai.getController()).getAi().getCardMemory().isRememberedCard(c, set);
} }
public static boolean isRememberedCard(AiController aic, Card c, MemorySet set) {
return aic.getCardMemory().isRememberedCard(c, set);
}
public static boolean isRememberedCardByName(Player ai, String name, MemorySet set) { public static boolean isRememberedCardByName(Player ai, String name, MemorySet set) {
if (!ai.getController().isAI()) { if (!ai.getController().isAI()) {
return false; return false;
} }
return ((PlayerControllerAi)ai.getController()).getAi().getCardMemory().isRememberedCardByName(name, set); return ((PlayerControllerAi)ai.getController()).getAi().getCardMemory().isRememberedCardByName(name, set);
} }
public static boolean isRememberedCardByName(AiController aic, String name, MemorySet set) {
return aic.getCardMemory().isRememberedCardByName(name, set);
}
public static void clearMemorySet(Player ai, MemorySet set) { public static void clearMemorySet(Player ai, MemorySet set) {
if (!ai.getController().isAI()) { if (!ai.getController().isAI()) {
return; return;
} }
((PlayerControllerAi)ai.getController()).getAi().getCardMemory().clearMemorySet(set); ((PlayerControllerAi)ai.getController()).getAi().getCardMemory().clearMemorySet(set);
} }
public static void clearMemorySet(AiController aic, MemorySet set) {
if (!isMemorySetEmpty(aic, set)) {
aic.getCardMemory().clearMemorySet(set);
}
}
public static boolean isMemorySetEmpty(Player ai, MemorySet set) { public static boolean isMemorySetEmpty(Player ai, MemorySet set) {
if (!ai.getController().isAI()) { if (!ai.getController().isAI()) {
return false; return false;
} }
return ((PlayerControllerAi)ai.getController()).getAi().getCardMemory().isMemorySetEmpty(set); return ((PlayerControllerAi)ai.getController()).getAi().getCardMemory().isMemorySetEmpty(set);
} }
public static boolean isMemorySetEmpty(AiController aic, MemorySet set) {
return aic.getCardMemory().isMemorySetEmpty(set);
}
} }

View File

@@ -646,6 +646,11 @@ public class AiController {
if (sa instanceof WrappedAbility) { if (sa instanceof WrappedAbility) {
return canPlaySa(((WrappedAbility) sa).getWrappedAbility()); return canPlaySa(((WrappedAbility) sa).getWrappedAbility());
} }
// When processing a new SA, clear the previously remembered cards that have been marked to avoid re-entry
// which might potentially cause a stack overflow.
AiCardMemory.clearMemorySet(this, AiCardMemory.MemorySet.MARKED_TO_AVOID_REENTRY);
if (sa.getApi() != null) { if (sa.getApi() != null) {
boolean canPlay = SpellApiToAi.Converter.get(sa.getApi()).canPlayAIWithSubs(player, sa); boolean canPlay = SpellApiToAi.Converter.get(sa.getApi()).canPlayAIWithSubs(player, sa);
if (!canPlay) { if (!canPlay) {

View File

@@ -1350,10 +1350,12 @@ public class ComputerUtil {
// Avoid re-entry for cards already being considered (e.g. in case the AI is considering // Avoid re-entry for cards already being considered (e.g. in case the AI is considering
// Convoke or Improvise for a Fog-like effect) // Convoke or Improvise for a Fog-like effect)
if (AiCardMemory.isRememberedCard(ai, c, AiCardMemory.MemorySet.MARKED_TO_AVOID_REENTRY)) { if (c.hasKeyword("Convoke") || c.hasKeyword("Improvise")) {
continue; if (AiCardMemory.isRememberedCard(ai, c, AiCardMemory.MemorySet.MARKED_TO_AVOID_REENTRY)) {
continue;
}
AiCardMemory.rememberCard(ai, c, AiCardMemory.MemorySet.MARKED_TO_AVOID_REENTRY);
} }
AiCardMemory.rememberCard(ai, c, AiCardMemory.MemorySet.MARKED_TO_AVOID_REENTRY);
if (!ComputerUtilCost.canPayCost(sa, ai)) { if (!ComputerUtilCost.canPayCost(sa, ai)) {
continue; continue;