mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 19:28:01 +00:00
- A somewhat cleaner fix for Token AI that fully separates the logic for detecting and processing mixed player/planeswalker target lists.
This commit is contained in:
@@ -222,14 +222,29 @@ public abstract class SpellAbilityAi {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends GameEntity> T chooseSingleEntity(Player ai, SpellAbility sa, Collection<T> options, boolean isOptional, Player targetedPlayer) {
|
||||
T firstOption = Iterables.getFirst(options, null);
|
||||
boolean hasPlayer = false;
|
||||
boolean hasCard = false;
|
||||
boolean hasPlaneswalker = false;
|
||||
|
||||
if (firstOption instanceof Card) {
|
||||
return (T) chooseSingleCard(ai, sa, (Collection<Card>) options, isOptional, targetedPlayer);
|
||||
for (T ent : options) {
|
||||
if (ent instanceof Player) {
|
||||
hasPlayer = true;
|
||||
} else if (ent instanceof Card) {
|
||||
hasCard = true;
|
||||
if (((Card)ent).isPlaneswalker()) {
|
||||
hasPlaneswalker = true;
|
||||
}
|
||||
if (firstOption instanceof Player) {
|
||||
}
|
||||
}
|
||||
|
||||
if (hasPlayer && hasPlaneswalker) {
|
||||
return (T) chooseSinglePlayerOrPlaneswalker(ai, sa, (Collection<GameEntity>) options);
|
||||
} else if (hasCard) {
|
||||
return (T) chooseSingleCard(ai, sa, (Collection<Card>) options, isOptional, targetedPlayer);
|
||||
} else if (hasPlayer) {
|
||||
return (T) chooseSinglePlayer(ai, sa, (Collection<Player>) options);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -239,16 +254,20 @@ public abstract class SpellAbilityAi {
|
||||
}
|
||||
|
||||
protected Card chooseSingleCard(Player ai, SpellAbility sa, Iterable<Card> options, boolean isOptional, Player targetedPlayer) {
|
||||
System.err.println("Warning: default (ie. inherited from base class) implementation of chooseSingleEntity is used for " + this.getClass().getName() + ". Consider declaring an overloaded method");
|
||||
System.err.println("Warning: default (ie. inherited from base class) implementation of chooseSingleCard is used for " + this.getClass().getName() + ". Consider declaring an overloaded method");
|
||||
return Iterables.getFirst(options, null);
|
||||
|
||||
}
|
||||
|
||||
protected GameEntity chooseSinglePlayer(Player ai, SpellAbility sa, Iterable<Player> options) {
|
||||
System.err.println("Warning: default (ie. inherited from base class) implementation of chooseSingleEntity is used for " + this.getClass().getName() + ". Consider declaring an overloaded method");
|
||||
protected Player chooseSinglePlayer(Player ai, SpellAbility sa, Iterable<Player> options) {
|
||||
System.err.println("Warning: default (ie. inherited from base class) implementation of chooseSinglePlayer is used for " + this.getClass().getName() + ". Consider declaring an overloaded method");
|
||||
return Iterables.getFirst(options, null);
|
||||
}
|
||||
|
||||
protected GameEntity chooseSinglePlayerOrPlaneswalker(Player ai, SpellAbility sa, Iterable<GameEntity> options) {
|
||||
System.err.println("Warning: default (ie. inherited from base class) implementation of chooseSinglePlayerOrPlaneswalker is used for " + this.getClass().getName() + ". Consider declaring an overloaded method");
|
||||
return Iterables.getFirst(options, null);
|
||||
}
|
||||
|
||||
protected static boolean isUselessCreature(Player ai, Card c) {
|
||||
if (c == null) {
|
||||
|
||||
@@ -305,11 +305,30 @@ public class TokenAi extends SpellAbilityAi {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* @see forge.card.ability.SpellAbilityAi#chooseSinglePlayer(forge.game.player.Player, forge.card.spellability.SpellAbility, Iterable<forge.game.player.Player> options)
|
||||
*/
|
||||
@Override
|
||||
protected GameEntity chooseSinglePlayer(Player ai, SpellAbility sa, Iterable<Player> options) {
|
||||
protected Player chooseSinglePlayer(Player ai, SpellAbility sa, Iterable<Player> options) {
|
||||
// TODO: AILogic
|
||||
Combat combat = ai.getGame().getCombat();
|
||||
// TokenAttacking
|
||||
if (combat != null && sa.hasParam("TokenAttacking")) {
|
||||
Card attacker = spawnToken(ai, sa);
|
||||
for (Player p : options) {
|
||||
if (!ComputerUtilCard.canBeBlockedProfitably(p, attacker)) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Iterables.getFirst(options, null);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.ability.SpellAbilityAi#chooseSinglePlayerOrPlaneswalker(forge.game.player.Player, forge.card.spellability.SpellAbility, Iterable<forge.game.GameEntity> options)
|
||||
*/
|
||||
@Override
|
||||
protected GameEntity chooseSinglePlayerOrPlaneswalker(Player ai, SpellAbility sa, Iterable<GameEntity> options) {
|
||||
// TODO: AILogic
|
||||
Combat combat = ai.getGame().getCombat();
|
||||
// TokenAttacking
|
||||
@@ -323,8 +342,6 @@ public class TokenAi extends SpellAbilityAi {
|
||||
}
|
||||
// 2. Otherwise, go through the list of options one by one, choose the first one that can't be blocked profitably.
|
||||
Card attacker = spawnToken(ai, sa);
|
||||
// TODO: this list potentially includes planeswalkers represented as Card objects. This may need further improvement
|
||||
// (SpellAbilityAi::chooseSingleGameEntity normally expects the list of options to be of the same type).
|
||||
for (GameEntity p : options) {
|
||||
if (p instanceof Player && !ComputerUtilCard.canBeBlockedProfitably((Player)p, attacker)) {
|
||||
return p;
|
||||
|
||||
Reference in New Issue
Block a user