mirror of
https://github.com/magefree/mage.git
synced 2025-12-20 02:30:08 -08:00
AI: improved stability:
- fixed game errors with source related filters (related to #13713); - fixed game freeze in hand's cards selection (related to #13290); - fixed game freeze in target amount selection with X=0 (related to #13290);
This commit is contained in:
parent
e8342e1f11
commit
6ad2cdaa78
5 changed files with 38 additions and 55 deletions
|
|
@ -692,7 +692,7 @@ public class ComputerPlayer extends PlayerImpl {
|
|||
|| target.getOriginalTarget() instanceof TargetCardInHand) {
|
||||
isAddedSomething = false;
|
||||
if (outcome.isGood()) {
|
||||
// good
|
||||
// good - choose max possible
|
||||
Cards cards = new CardsImpl(possibleTargets);
|
||||
List<Card> cardsInHand = new ArrayList<>(cards.getCards(game));
|
||||
while (!target.isChosen(game)
|
||||
|
|
@ -703,36 +703,42 @@ public class ComputerPlayer extends PlayerImpl {
|
|||
if (target.canTarget(abilityControllerId, card.getId(), source, game) && !target.contains(card.getId())) {
|
||||
target.addTarget(card.getId(), source, game);
|
||||
isAddedSomething = true;
|
||||
cardsInHand.remove(card);
|
||||
if (target.isChoiceCompleted(game)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
cardsInHand.remove(card);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// bad
|
||||
// bad - choose the lowest possible
|
||||
findPlayables(game);
|
||||
for (Card card : unplayable.values()) {
|
||||
if (target.isChosen(game)) {
|
||||
return isAddedSomething;
|
||||
}
|
||||
if (possibleTargets.contains(card.getId())
|
||||
&& target.canTarget(abilityControllerId, card.getId(), source, game)
|
||||
&& !target.contains(card.getId())) {
|
||||
target.addTarget(card.getId(), source, game);
|
||||
isAddedSomething = true;
|
||||
if (target.isChoiceCompleted(game)) {
|
||||
return true;
|
||||
if (target.isChosen(game)) {
|
||||
return isAddedSomething;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!hand.isEmpty()) {
|
||||
for (Card card : hand.getCards(game)) {
|
||||
if (target.isChosen(game)) {
|
||||
return isAddedSomething;
|
||||
}
|
||||
if (possibleTargets.contains(card.getId())
|
||||
&& target.canTarget(abilityControllerId, card.getId(), source, game)
|
||||
&& !target.contains(card.getId())) {
|
||||
target.addTarget(card.getId(), source, game);
|
||||
isAddedSomething = true;
|
||||
if (target.isChoiceCompleted(game)) {
|
||||
return true;
|
||||
if (target.isChosen(game)) {
|
||||
return isAddedSomething;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -854,39 +860,6 @@ public class ComputerPlayer extends PlayerImpl {
|
|||
if (target.getOriginalTarget() instanceof TargetPermanentOrPlayer) {
|
||||
List<Permanent> targets;
|
||||
TargetPermanentOrPlayer origTarget = ((TargetPermanentOrPlayer) target.getOriginalTarget());
|
||||
if (outcome.isGood()) {
|
||||
targets = threats(abilityControllerId, source, ((FilterPermanentOrPlayer) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets());
|
||||
} else {
|
||||
targets = threats(randomOpponentId, source, ((FilterPermanentOrPlayer) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets());
|
||||
}
|
||||
|
||||
if (targets.isEmpty()) {
|
||||
if (outcome.isGood()) {
|
||||
if (target.canTarget(abilityControllerId, getId(), source, game) && !target.contains(getId())) {
|
||||
return tryAddTarget(target, getId(), source, game);
|
||||
}
|
||||
} else if (target.canTarget(abilityControllerId, randomOpponentId, source, game) && !target.contains(randomOpponentId)) {
|
||||
return tryAddTarget(target, randomOpponentId, source, game);
|
||||
}
|
||||
}
|
||||
|
||||
if (targets.isEmpty() && target.isRequired(source)) {
|
||||
targets = game.getBattlefield().getActivePermanents(((FilterPermanentOrPlayer) origTarget.getFilter()).getPermanentFilter(), playerId, game);
|
||||
}
|
||||
for (Permanent permanent : targets) {
|
||||
List<UUID> alreadyTargeted = target.getTargets();
|
||||
if (target.canTarget(abilityControllerId, permanent.getId(), source, game) && !target.contains(permanent.getId())) {
|
||||
if (alreadyTargeted != null && !alreadyTargeted.contains(permanent.getId())) {
|
||||
return tryAddTarget(target, permanent.getId(), source, game);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (target.getOriginalTarget() instanceof TargetPlayerOrPlaneswalker
|
||||
|| target.getOriginalTarget() instanceof TargetOpponentOrPlaneswalker) {
|
||||
List<Permanent> targets;
|
||||
TargetPermanentOrPlayer origTarget = ((TargetPermanentOrPlayer) target.getOriginalTarget());
|
||||
|
||||
// TODO: in multiplayer game there many opponents - if random opponents don't have targets then AI must use next opponent, but it skips
|
||||
// (e.g. you randomOpponentId must be replaced by List<UUID> randomOpponents)
|
||||
|
|
@ -1239,6 +1212,7 @@ public class ComputerPlayer extends PlayerImpl {
|
|||
throw new IllegalStateException("Target wasn't handled in computer's chooseTarget method: " + target.getClass().getCanonicalName());
|
||||
} //end of chooseTarget method
|
||||
|
||||
@Deprecated // TODO: replace by source only version
|
||||
protected Card selectCard(UUID abilityControllerId, List<Card> cards, Outcome outcome, Target target, Game game) {
|
||||
return selectCardInner(abilityControllerId, cards, outcome, target, null, game);
|
||||
}
|
||||
|
|
@ -1279,6 +1253,10 @@ public class ComputerPlayer extends PlayerImpl {
|
|||
log.debug("chooseTarget: " + outcome.toString() + ':' + target.toString());
|
||||
}
|
||||
|
||||
if (target.getAmountRemaining() <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
UUID sourceId = source != null ? source.getSourceId() : null;
|
||||
|
||||
// sometimes a target selection can be made from a player that does not control the ability
|
||||
|
|
@ -2576,6 +2554,7 @@ public class ComputerPlayer extends PlayerImpl {
|
|||
tournament.submitDeck(playerId, deck);
|
||||
}
|
||||
|
||||
@Deprecated // TODO: replace by source only version
|
||||
public Card selectBestCard(List<Card> cards, List<ColoredManaSymbol> chosenColors) {
|
||||
return selectBestCardInner(cards, chosenColors, null, null, null);
|
||||
}
|
||||
|
|
@ -2623,14 +2602,6 @@ public class ComputerPlayer extends PlayerImpl {
|
|||
return bestCard;
|
||||
}
|
||||
|
||||
public Card selectWorstCard(List<Card> cards, List<ColoredManaSymbol> chosenColors) {
|
||||
return selectWorstCardInner(cards, chosenColors, null, null, null);
|
||||
}
|
||||
|
||||
public Card selectWorstCardTarget(List<Card> cards, List<ColoredManaSymbol> chosenColors, Target target, Ability targetingSource, Game game) {
|
||||
return selectWorstCardInner(cards, chosenColors, target, targetingSource, game);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param targetingSource null on non-target choice like choose and source on targeting choice like chooseTarget
|
||||
*/
|
||||
|
|
@ -3097,6 +3068,7 @@ public class ComputerPlayer extends PlayerImpl {
|
|||
return before != after;
|
||||
}
|
||||
|
||||
@Deprecated // TODO: replace by source only version
|
||||
private boolean selectPlayer(Outcome outcome, Target target, UUID abilityControllerId, UUID randomOpponentId, Game game, boolean required) {
|
||||
return selectPlayerInner(outcome, target, null, abilityControllerId, randomOpponentId, game, required);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -288,6 +288,10 @@ public final class SimulatedPlayerMCTS extends MCTSPlayer {
|
|||
|
||||
@Override
|
||||
public boolean chooseTargetAmount(Outcome outcome, TargetAmount target, Ability source, Game game) {
|
||||
if (target.getAmountRemaining() <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Set<UUID> possibleTargets = target.possibleTargets(playerId, source, game);
|
||||
if (possibleTargets.isEmpty()) {
|
||||
return !target.isRequired(source);
|
||||
|
|
|
|||
|
|
@ -1042,6 +1042,10 @@ public class HumanPlayer extends PlayerImpl {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (target.getAmountRemaining() <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (source == null) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue