- Better ranking system for damaging planeswalkers directly (accounts for loyalty and closeness to ultimate for now).

This commit is contained in:
Agetian
2018-04-16 21:31:49 +03:00
parent 3344453253
commit 2c9b23fc6d
2 changed files with 48 additions and 1 deletions

View File

@@ -9,6 +9,7 @@ import forge.game.GameObject;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.card.*; import forge.game.card.*;
import forge.game.cost.Cost; import forge.game.cost.Cost;
import forge.game.cost.CostRemoveCounter;
import forge.game.phase.PhaseHandler; import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType; import forge.game.phase.PhaseType;
import forge.game.player.Player; import forge.game.player.Player;
@@ -357,17 +358,54 @@ public class DamageDealAi extends DamageAiBase {
// Filter AI-specific targets if provided // Filter AI-specific targets if provided
killables = ComputerUtil.filterAITgts(sa, ai, new CardCollection(killables), true); killables = ComputerUtil.filterAITgts(sa, ai, new CardCollection(killables), true);
// We can kill a planeswalker, so go for it
if (pl.isOpponentOf(ai) && activator.equals(ai) && !killables.isEmpty()) { if (pl.isOpponentOf(ai) && activator.equals(ai) && !killables.isEmpty()) {
return ComputerUtilCard.getBestPlaneswalkerAI(killables); return ComputerUtilCard.getBestPlaneswalkerAI(killables);
} }
// We can hurt a planeswalker, so rank the one which is the best target
if (!hPlay.isEmpty() && pl.isOpponentOf(ai) && activator.equals(ai)) { if (!hPlay.isEmpty() && pl.isOpponentOf(ai) && activator.equals(ai)) {
return ComputerUtilCard.getBestPlaneswalkerAI(hPlay); return getBestPlaneswalkerToDamage(hPlay);
} }
return null; return null;
} }
private Card getBestPlaneswalkerToDamage(final List<Card> pws) {
Card bestTgt = null;
// As of right now, ranks planeswalkers by their Current Loyalty * 10 + Big buff if close to "Ultimate"
int bestScore = 0;
for (Card pw : pws) {
int curLoyalty = pw.getCounters(CounterType.LOYALTY);
int pwScore = curLoyalty * 10;
for (SpellAbility sa : pw.getSpellAbilities()) {
if (sa.hasParam("Ultimate")) {
int loyaltyCost = 0;
CostRemoveCounter remLoyalty = sa.getPayCosts().getCostPart(CostRemoveCounter.class);
if (remLoyalty != null) {
// if remLoyalty is null, generally there's an AddCounter<0/LOYALTY> cost, like for Gideon Jura.
loyaltyCost = remLoyalty.convertAmount();
}
if (loyaltyCost != 0 && loyaltyCost - curLoyalty <= 1) {
// Will ultimate soon
pwScore += 10000;
}
if (pwScore > bestScore) {
bestScore = pwScore;
bestTgt = pw;
}
}
}
}
return bestTgt;
}
private List<Card> getTargetableCards(Player ai, SpellAbility sa, Player pl, TargetRestrictions tgt, Player activator, Card source, Game game) { private List<Card> getTargetableCards(Player ai, SpellAbility sa, Player pl, TargetRestrictions tgt, Player activator, Card source, Game game) {
List<Card> hPlay = CardLists.getValidCards(game.getCardsIn(ZoneType.Battlefield), tgt.getValidTgts(), activator, source, sa); List<Card> hPlay = CardLists.getValidCards(game.getCardsIn(ZoneType.Battlefield), tgt.getValidTgts(), activator, source, sa);

View File

@@ -94,6 +94,15 @@ public class Cost implements Serializable {
return true; return true;
} }
public <T extends CostPart> T getCostPart(Class<T> costType) {
for (CostPart p : getCostParts()) {
if (costType.isInstance(p)) {
return (T)p;
}
}
return null;
}
/** /**
* Gets the cost parts. * Gets the cost parts.
* *