From 3ce3d70c623c8024e372fe23245fa532e15b538c Mon Sep 17 00:00:00 2001 From: Michael Kamensky Date: Mon, 5 Oct 2020 07:30:57 +0300 Subject: [PATCH] - Basic Witch's Vengeance AI, some refactoring in ChooseTypeAi. --- .../java/forge/ai/ability/ChooseTypeAi.java | 76 ++++++++++++------- .../res/cardsfolder/w/witchs_vengeance.txt | 2 +- 2 files changed, 48 insertions(+), 30 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/ability/ChooseTypeAi.java b/forge-ai/src/main/java/forge/ai/ability/ChooseTypeAi.java index 2f3b0c5b67a..cadfa5ee3ee 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ChooseTypeAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ChooseTypeAi.java @@ -2,25 +2,21 @@ package forge.ai.ability; import com.google.common.base.Predicates; import com.google.common.collect.Lists; -import forge.ai.AiCardMemory; -import forge.ai.ComputerUtilAbility; -import forge.ai.ComputerUtilCard; -import forge.ai.ComputerUtilMana; -import forge.ai.SpellAbilityAi; +import forge.ai.*; import forge.card.CardType; import forge.game.ability.AbilityUtils; -import forge.game.card.Card; -import forge.game.card.CardCollection; -import forge.game.card.CardCollectionView; -import forge.game.card.CardLists; -import forge.game.card.CardPredicates; +import forge.game.ability.ApiType; +import forge.game.card.*; import forge.game.keyword.Keyword; import forge.game.phase.PhaseType; import forge.game.player.Player; import forge.game.spellability.SpellAbility; import forge.game.zone.ZoneType; import forge.util.Aggregates; + +import java.util.HashSet; import java.util.List; +import java.util.Set; public class ChooseTypeAi extends SpellAbilityAi { @Override @@ -31,6 +27,8 @@ public class ChooseTypeAi extends SpellAbilityAi { if (ComputerUtilAbility.getAbilitySourceName(sa).equals("Mirror Entity Avatar")) { return doMirrorEntityLogic(aiPlayer, sa); } + } else if ("MostProminentOppControls".equals(sa.getParam("AILogic"))) { + return !chooseType(sa, aiPlayer.getOpponents().getCardsIn(ZoneType.Battlefield)).isEmpty(); } return doTriggerAINoCost(aiPlayer, sa, false); @@ -44,27 +42,11 @@ public class ChooseTypeAi extends SpellAbilityAi { return false; } - CardCollectionView otb = aiPlayer.getCardsIn(ZoneType.Battlefield); - List valid = Lists.newArrayList(CardType.getAllCreatureTypes()); - - String chosenType = ComputerUtilCard.getMostProminentType(otb, valid); + String chosenType = chooseType(sa, aiPlayer.getCardsIn(ZoneType.Battlefield)); if (chosenType.isEmpty()) { - // Account for the situation when only changelings are on the battlefield - boolean allChangeling = false; - for (Card c : otb) { - if (c.isCreature() && c.hasStartOfKeyword(Keyword.CHANGELING.toString())) { - chosenType = Aggregates.random(valid); // just choose a random type for changelings - allChangeling = true; - break; - } - } - - if (!allChangeling) { - // Still empty, probably no creatures on board - return false; - } + return false; } - + int maxX = ComputerUtilMana.determineMaxAffordableX(aiPlayer, sa); int avgPower = 0; @@ -127,4 +109,40 @@ public class ChooseTypeAi extends SpellAbilityAi { return true; } + private String chooseType(SpellAbility sa, CardCollectionView cards) { + Set valid = new HashSet<>(); + + if (sa.getSubAbility() != null && sa.getSubAbility().getApi() == ApiType.PumpAll + && sa.getSubAbility().isCurse() && sa.getSubAbility().hasParam("NumDef")) { + final SpellAbility pumpSa = sa.getSubAbility(); + final int defense = AbilityUtils.calculateAmount(sa.getHostCard(), pumpSa.getParam("NumDef"), pumpSa); + for (Card c : cards) { + if (c.isCreature() && c.getNetToughness() <= -defense) { + valid.addAll(c.getType().getCreatureTypes()); + } + } + } else { + valid.addAll(CardType.getAllCreatureTypes()); + } + + String chosenType = ComputerUtilCard.getMostProminentType(cards, valid); + if (chosenType.isEmpty()) { + // Account for the situation when only changelings are on the battlefield + boolean allChangeling = false; + for (Card c : cards) { + if (c.isCreature() && c.hasStartOfKeyword(Keyword.CHANGELING.toString())) { + chosenType = Aggregates.random(valid); // just choose a random type for changelings + allChangeling = true; + break; + } + } + + if (!allChangeling) { + // Still empty, probably no creatures on board + return ""; + } + } + + return chosenType; + } } diff --git a/forge-gui/res/cardsfolder/w/witchs_vengeance.txt b/forge-gui/res/cardsfolder/w/witchs_vengeance.txt index 25aae772654..f5f4cec1534 100644 --- a/forge-gui/res/cardsfolder/w/witchs_vengeance.txt +++ b/forge-gui/res/cardsfolder/w/witchs_vengeance.txt @@ -1,6 +1,6 @@ Name:Witch's Vengeance ManaCost:1 B B Types:Sorcery -A:SP$ ChooseType | Cost$ 1 B B | Defined$ You | Type$ Creature | AILogic$ MostProminentHumanControls | SubAbility$ DBPumpAll | SpellDescription$ Creatures of the creature type of your choice get -3/-3 until end of turn. +A:SP$ ChooseType | Cost$ 1 B B | Defined$ You | Type$ Creature | AILogic$ MostProminentOppControls | SubAbility$ DBPumpAll | SpellDescription$ Creatures of the creature type of your choice get -3/-3 until end of turn. SVar:DBPumpAll:DB$ PumpAll | ValidCards$ Creature.ChosenType | NumAtt$ -3 | NumDef$ -3 | IsCurse$ True Oracle:Creatures of the creature type of your choice get -3/-3 until end of turn.