AI: fixed game freeze on free cast of multiple cards (part of #13638, #13766);

refactor: fixed that TargetCard doesn't work with Zone.ALL;
This commit is contained in:
Oleg Agafonov 2025-06-29 14:36:54 +04:00
parent bfceb07c58
commit 450f7bd907
13 changed files with 257 additions and 38 deletions

View file

@ -1556,7 +1556,7 @@ public final class CardUtil {
return result;
}
private static boolean checkForPlayable(Cards cards, FilterCard filter, Ability source, Player player, Game game, SpellCastTracker spellCastTracker, boolean playLand) {
private static boolean cardsHasCastableParts(Cards cards, FilterCard filter, Ability source, Player player, Game game, SpellCastTracker spellCastTracker, boolean playLand) {
return cards
.getCards(game)
.stream()
@ -1580,19 +1580,40 @@ public final class CardUtil {
CardUtil.castSpellWithAttributesForFree(player, source, game, cards, filter);
return;
}
int spellsCast = 0;
int castCount = 0;
int maxCastCount = Integer.min(cards.size(), maxSpells);
cards.removeZone(Zone.STACK, game);
while (player.canRespond() && spellsCast < maxSpells && !cards.isEmpty()) {
if (CardUtil.castSpellWithAttributesForFree(player, source, game, cards, filter, spellCastTracker, playLand)) {
spellsCast++;
cards.removeZone(Zone.STACK, game);
} else if (!checkForPlayable(
cards, filter, source, player, game, spellCastTracker, playLand
) || !player.chooseUse(
Outcome.PlayForFree, "Continue casting spells?", source, game
)) {
if (!cardsHasCastableParts(cards, filter, source, player, game, spellCastTracker, playLand)) {
return;
}
while (player.canRespond()) {
boolean wasCast = CardUtil.castSpellWithAttributesForFree(player, source, game, cards, filter, spellCastTracker, playLand);
// nothing to cast
cards.removeZone(Zone.STACK, game);
if (cards.isEmpty() || !cardsHasCastableParts(cards, filter, source, player, game, spellCastTracker, playLand)) {
break;
}
if (wasCast) {
// no more tries to cast
castCount++;
if (castCount >= maxCastCount) {
break;
}
} else {
// player want to cancel
if (player.isComputer()) {
// AI can't choose good spell, so stop
break;
} else {
// Human can choose wrong spell part, so allow to continue
if (!player.chooseUse(Outcome.PlayForFree, "Continue casting spells?", source, game)) {
break;
}
}
}
}
}