other: reworked target selection (now it use same logic and methods in all places), fixed AI and selection freezes in some use cases (related to #13606, #11285)

This commit is contained in:
Oleg Agafonov 2025-05-07 17:34:36 +04:00
parent 62aa310a4f
commit a53eb66b58
10 changed files with 133 additions and 53 deletions

View file

@ -251,6 +251,7 @@ public class ComputerPlayer extends PlayerImpl {
for (Permanent permanent : targets) {
if (target.canTarget(abilityControllerId, permanent.getId(), source, game) && !target.getTargets().contains(permanent.getId())) {
// stop to add targets if not needed and outcome is no advantage for AI player
// TODO: need research and improve - is it good to check target.isChosen(game) instead return true?
if (target.getMinNumberOfTargets() == target.getTargets().size()) {
if (outcome.isGood() && hasOpponent(permanent.getControllerId(), game)) {
return true;
@ -2044,19 +2045,20 @@ public class ComputerPlayer extends PlayerImpl {
// we still use playerId when getting cards even if they don't control the search
List<Card> cardChoices = new ArrayList<>(cards.getCards(target.getFilter(), playerId, source, game));
while (!target.doneChoosing(game)) {
do {
Card card = selectCardTarget(abilityControllerId, cardChoices, outcome, target, source, game);
if (card != null) {
target.addTarget(card.getId(), source, game);
cardChoices.remove(card);
} else {
// We don't have any valid target to choose so stop choosing
return target.getTargets().size() >= target.getMinNumberOfTargets();
return target.isChosen(game);
}
// try to fill as much as possible for good effect (see while end) or half for bad (see if)
if (outcome == Outcome.Neutral && target.getTargets().size() > target.getMinNumberOfTargets() + (target.getMaxNumberOfTargets() - target.getMinNumberOfTargets()) / 2) {
return true;
return target.isChosen(game);
}
}
} while (target.getTargets().size() < target.getMaxNumberOfTargets());
return true;
}
@ -2075,19 +2077,20 @@ public class ComputerPlayer extends PlayerImpl {
}
List<Card> cardChoices = new ArrayList<>(cards.getCards(target.getFilter(), abilityControllerId, source, game));
while (!target.doneChoosing(game)) {
do {
Card card = selectCard(abilityControllerId, cardChoices, outcome, target, game);
if (card != null) {
target.add(card.getId(), game);
cardChoices.remove(card); // selectCard don't remove cards (only on second+ tries)
} else {
// We don't have any valid target to choose so stop choosing
return target.getTargets().size() >= target.getMinNumberOfTargets();
return target.isChosen(game);
}
// try to fill as much as possible for good effect (see while end) or half for bad (see if)
if (outcome == Outcome.Neutral && target.getTargets().size() > target.getMinNumberOfTargets() + (target.getMaxNumberOfTargets() - target.getMinNumberOfTargets()) / 2) {
return true;
return target.isChosen(game);
}
}
} while (target.getTargets().size() < target.getMaxNumberOfTargets());
return true;
}