mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 12:48:00 +00:00
ChooseGenericEffectAi: add logic for Fabricate
in most cases it should prefer tokens if able
This commit is contained in:
@@ -1,10 +1,15 @@
|
||||
package forge.ai.ability;
|
||||
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.card.MagicColor;
|
||||
import forge.game.Game;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardUtil;
|
||||
import forge.game.card.CounterType;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.cost.Cost;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
@@ -43,8 +48,12 @@ public class ChooseGenericEffectAi extends SpellAbilityAi {
|
||||
@Override
|
||||
public SpellAbility chooseSingleSpellAbility(Player player, SpellAbility sa, List<SpellAbility> spells) {
|
||||
Card host = sa.getHostCard();
|
||||
final Game game = host.getGame();
|
||||
final Combat combat = game.getCombat();
|
||||
final String logic = sa.getParam("AILogic");
|
||||
if ("Random".equals(logic)) {
|
||||
if (logic == null) {
|
||||
return spells.get(0);
|
||||
} else if ("Random".equals(logic)) {
|
||||
return Aggregates.random(spells);
|
||||
} else if ("Phasing".equals(logic)) { // Teferi's Realm : keep aggressive
|
||||
List<SpellAbility> filtered = Lists.newArrayList(Iterables.filter(spells, new Predicate<SpellAbility>() {
|
||||
@@ -141,41 +150,41 @@ public class ChooseGenericEffectAi extends SpellAbilityAi {
|
||||
|
||||
//useless cards in hand
|
||||
if (imprinted.getName().equals("Bridge from Below") ||
|
||||
imprinted.getName().equals("Haakon, Stromgald Scourge")) {
|
||||
return allow;
|
||||
imprinted.getName().equals("Haakon, Stromgald Scourge")) {
|
||||
return allow;
|
||||
}
|
||||
|
||||
//bad cards when are thrown from the library to the graveyard, but Yixlid can prevent that
|
||||
if (!player.getGame().isCardInPlay("Yixlid Jailer") && (
|
||||
imprinted.getName().equals("Gaea's Blessing") ||
|
||||
imprinted.getName().equals("Narcomoeba"))) {
|
||||
return allow;
|
||||
imprinted.getName().equals("Gaea's Blessing") ||
|
||||
imprinted.getName().equals("Narcomoeba"))) {
|
||||
return allow;
|
||||
}
|
||||
|
||||
// milling against Tamiyo is pointless
|
||||
if (owner.isCardInCommand("Tamiyo, the Moon Sage emblem")) {
|
||||
return allow;
|
||||
return allow;
|
||||
}
|
||||
|
||||
// milling a land against Gitrog result in card draw
|
||||
if (imprinted.isLand() && owner.isCardInPlay("The Gitrog Monster")) {
|
||||
// try to mill owner
|
||||
if (owner.getCardsIn(ZoneType.Library).size() < 5) {
|
||||
return deny;
|
||||
}
|
||||
return allow;
|
||||
// try to mill owner
|
||||
if (owner.getCardsIn(ZoneType.Library).size() < 5) {
|
||||
return deny;
|
||||
}
|
||||
return allow;
|
||||
}
|
||||
|
||||
// milling a creature against Sidisi result in more creatures
|
||||
if (imprinted.isCreature() && owner.isCardInPlay("Sidisi, Brood Tyrant")) {
|
||||
return allow;
|
||||
return allow;
|
||||
}
|
||||
|
||||
//if Iona does prevent from casting, allow it to draw
|
||||
for (final Card io : player.getCardsIn(ZoneType.Battlefield, "Iona, Shield of Emeria")) {
|
||||
if (CardUtil.getColors(imprinted).hasAnyColor(MagicColor.fromName(io.getChosenColor()))) {
|
||||
return allow;
|
||||
}
|
||||
if (CardUtil.getColors(imprinted).hasAnyColor(MagicColor.fromName(io.getChosenColor()))) {
|
||||
return allow;
|
||||
}
|
||||
}
|
||||
|
||||
if (dmg == 0) {
|
||||
@@ -191,6 +200,57 @@ public class ChooseGenericEffectAi extends SpellAbilityAi {
|
||||
}
|
||||
// if unsure, random?
|
||||
return Aggregates.random(spells);
|
||||
} else if (logic.startsWith("Fabricate")) {
|
||||
final int n = Integer.valueOf(logic.substring("Fabricate".length()));
|
||||
SpellAbility counterSA = spells.get(0), tokenSA = spells.get(1);
|
||||
|
||||
// check for something which might prevent the counters to be placed on host
|
||||
if (!host.canReceiveCounters(CounterType.P1P1)) {
|
||||
return tokenSA;
|
||||
}
|
||||
|
||||
// if host would leave the play or if host is useless, create tokens
|
||||
if (host.hasSVar("EndOfTurnLeavePlay") || isUselessCreature(player, host)) {
|
||||
return tokenSA;
|
||||
}
|
||||
|
||||
// need a copy for one with extra +1/+1 counter boost,
|
||||
// without causing triggers to run
|
||||
final Card copy = CardUtil.getLKICopy(host);
|
||||
copy.setCounters(CounterType.P1P1, copy.getCounters(CounterType.P1P1) + n);
|
||||
copy.setZone(host.getZone());
|
||||
|
||||
// if host would put into the battlefield attacking
|
||||
if (combat != null && combat.isAttacking(host)) {
|
||||
final Player defender = combat.getDefenderPlayerByAttacker(host);
|
||||
if (!ComputerUtilCard.canBeBlockedProfitably(defender, copy)) {
|
||||
return counterSA;
|
||||
}
|
||||
return tokenSA;
|
||||
}
|
||||
|
||||
// TODO check for trigger to turn token ETB into +1/+1 counter for host
|
||||
// TODO check for trigger to turn token ETB into damage or life loss for opponent
|
||||
// in this cases Token might be prefered even if they would not survive
|
||||
final Card tokenCard = TokenAi.spawnToken(player, tokenSA, true);
|
||||
|
||||
// Token would not survive
|
||||
if (tokenCard.getNetToughness() < 1) {
|
||||
return counterSA;
|
||||
}
|
||||
|
||||
// evaluate Creature with +1/+1
|
||||
int evalCounter = ComputerUtilCard.evaluateCreature(copy);
|
||||
|
||||
final CardCollection tokenList = new CardCollection(host);
|
||||
for (int i = 0; i < n; ++i) {
|
||||
tokenList.add(TokenAi.spawnToken(player, tokenSA));
|
||||
}
|
||||
|
||||
// evaluate Host with Tokens
|
||||
int evalToken = ComputerUtilCard.evaluateCreatureList(tokenList);
|
||||
|
||||
return evalToken >= evalCounter ? tokenSA : counterSA;
|
||||
}
|
||||
return spells.get(0); // return first choice if no logic found
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user