From 8e54b0e7423df4ae57692d149a38739a23aad1fd Mon Sep 17 00:00:00 2001 From: Rob Schnautz Date: Sun, 24 Jun 2018 21:18:33 +0000 Subject: [PATCH 1/2] Reduce method call count. --- .../src/main/java/forge/ai/AiController.java | 124 ++++++++++-------- 1 file changed, 68 insertions(+), 56 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/AiController.java b/forge-ai/src/main/java/forge/ai/AiController.java index 3eed6899f30..b2b174bb0e7 100644 --- a/forge-ai/src/main/java/forge/ai/AiController.java +++ b/forge-ai/src/main/java/forge/ai/AiController.java @@ -127,10 +127,12 @@ public class AiController { private List getPossibleETBCounters() { CardCollection all = new CardCollection(player.getCardsIn(ZoneType.Hand)); - all.addAll(player.getCardsIn(ZoneType.Exile)); + CardCollectionView ccvPlayerLibrary = player.getCardsIn(ZoneType.Library); + + all.addAll(player.getCardsIn(ZoneType.Exile)); all.addAll(player.getCardsIn(ZoneType.Graveyard)); - if (!player.getCardsIn(ZoneType.Library).isEmpty()) { - all.add(player.getCardsIn(ZoneType.Library).get(0)); + if (!ccvPlayerLibrary.isEmpty()) { + all.add(ccvPlayerLibrary.get(0)); } for (final Player opp : player.getOpponents()) { @@ -153,32 +155,36 @@ public class AiController { // look for cards on the battlefield that should prevent the AI from using that spellability private boolean checkCurseEffects(final SpellAbility sa) { - for (final Card c : game.getCardsIn(ZoneType.Battlefield)) { + CardCollectionView ccvGameBattlefield = game.getCardsIn(ZoneType.Battlefield); + for (final Card c : ccvGameBattlefield) { if (c.hasSVar("AICurseEffect")) { final String curse = c.getSVar("AICurseEffect"); - final Card host = sa.getHostCard(); if ("NonActive".equals(curse) && !player.equals(game.getPhaseHandler().getPlayerTurn())) { return true; - } else if ("DestroyCreature".equals(curse) && sa.isSpell() && host.isCreature() - && !sa.getHostCard().hasKeyword(Keyword.INDESTRUCTIBLE)) { - return true; - } else if ("CounterEnchantment".equals(curse) && sa.isSpell() && host.isEnchantment() - && CardFactoryUtil.isCounterable(host)) { - return true; - } else if ("ChaliceOfTheVoid".equals(curse) && sa.isSpell() && CardFactoryUtil.isCounterable(host) - && host.getCMC() == c.getCounters(CounterType.CHARGE)) { - return true; - } else if ("BazaarOfWonders".equals(curse) && sa.isSpell() && CardFactoryUtil.isCounterable(host)) { - for (Card card : game.getCardsIn(ZoneType.Battlefield)) { - if (!card.isToken() && card.getName().equals(host.getName())) { - return true; - } - } - for (Card card : game.getCardsIn(ZoneType.Graveyard)) { - if (card.getName().equals(host.getName())) { - return true; - } - } + } else { + final Card host = sa.getHostCard(); + if ("DestroyCreature".equals(curse) && sa.isSpell() && host.isCreature() + && !host.hasKeyword(Keyword.INDESTRUCTIBLE)) { + return true; + } else if ("CounterEnchantment".equals(curse) && sa.isSpell() && host.isEnchantment() + && CardFactoryUtil.isCounterable(host)) { + return true; + } else if ("ChaliceOfTheVoid".equals(curse) && sa.isSpell() && CardFactoryUtil.isCounterable(host) + && host.getCMC() == c.getCounters(CounterType.CHARGE)) { + return true; + } else if ("BazaarOfWonders".equals(curse) && sa.isSpell() && CardFactoryUtil.isCounterable(host)) { + String hostName = host.getName(); + for (Card card : ccvGameBattlefield) { + if (!card.isToken() && card.getName().equals(hostName)) { + return true; + } + } + for (Card card : game.getCardsIn(ZoneType.Graveyard)) { + if (card.getName().equals(hostName)) { + return true; + } + } + } } } } @@ -186,13 +192,14 @@ public class AiController { } public boolean checkETBEffects(final Card card, final SpellAbility sa, final ApiType api) { - boolean rightapi = false; - if (card.isCreature() && game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.noCreatureETBTriggers)) { return api == null; } - + boolean rightapi = false; + String battlefield = ZoneType.Battlefield.toString(); + Player activatingPlayer = sa.getActivatingPlayer(); + // Trigger play improvements for (final Trigger tr : card.getTriggers()) { // These triggers all care for ETB effects @@ -202,21 +209,22 @@ public class AiController { continue; } - if (!params.get("Destination").equals(ZoneType.Battlefield.toString())) { + if (!params.get("Destination").equals(battlefield)) { continue; } if (params.containsKey("ValidCard")) { - if (!params.get("ValidCard").contains("Self")) { + String validCard = params.get("ValidCard"); + if (!validCard.contains("Self")) { continue; } - if (params.get("ValidCard").contains("notkicked")) { + if (validCard.contains("notkicked")) { if (sa.isKicked()) { continue; } - } else if (params.get("ValidCard").contains("kicked")) { - if (params.get("ValidCard").contains("kicked ")) { // want a specific kicker - String s = params.get("ValidCard").split("kicked ")[1]; + } else if (validCard.contains("kicked")) { + if (validCard.contains("kicked ")) { // want a specific kicker + String s = validCard.split("kicked ")[1]; if ("1".equals(s) && !sa.isOptionalCostPaid(OptionalCost.Kicker1)) continue; if ("2".equals(s) && !sa.isOptionalCostPaid(OptionalCost.Kicker2)) continue; } else if (!sa.isKicked()) { @@ -259,7 +267,7 @@ public class AiController { } if (sa != null) { - exSA.setActivatingPlayer(sa.getActivatingPlayer()); + exSA.setActivatingPlayer(activatingPlayer); } else { exSA.setActivatingPlayer(player); @@ -267,13 +275,11 @@ public class AiController { exSA.setTrigger(true); // for trigger test, need to ignore the conditions - if (exSA.getConditions() != null) { - SpellAbilityCondition cons = exSA.getConditions(); - if (cons.getIsPresent() != null) { - String pres = cons.getIsPresent(); - if ("Card.Self".equals(pres) || "Card.StrictlySelf".equals(pres)) { + SpellAbilityCondition cons = exSA.getConditions(); + if (cons != null) { + String pres = cons.getIsPresent(); + if (pres != null && pres.matches("Card\\.(Strictly)?Self")) { cons.setIsPresent(null); - } } } @@ -297,21 +303,22 @@ public class AiController { continue; } - if (!params.get("Destination").equals(ZoneType.Battlefield.toString())) { + if (!params.get("Destination").equals(battlefield)) { continue; } if (params.containsKey("ValidCard")) { - if (!params.get("ValidCard").contains("Self")) { + String validCard = params.get("ValidCard"); + if (!validCard.contains("Self")) { continue; } - if (params.get("ValidCard").contains("notkicked")) { + if (validCard.contains("notkicked")) { if (sa.isKicked()) { continue; } - } else if (params.get("ValidCard").contains("kicked")) { - if (params.get("ValidCard").contains("kicked ")) { // want a specific kicker - String s = params.get("ValidCard").split("kicked ")[1]; + } else if (validCard.contains("kicked")) { + if (validCard.contains("kicked ")) { // want a specific kicker + String s = validCard.split("kicked ")[1]; if ("1".equals(s) && !sa.isOptionalCostPaid(OptionalCost.Kicker1)) continue; if ("2".equals(s) && !sa.isOptionalCostPaid(OptionalCost.Kicker2)) continue; } else if (!sa.isKicked()) { // otherwise just any must be present @@ -327,7 +334,7 @@ public class AiController { if (exSA != null) { if (sa != null) { - exSA.setActivatingPlayer(sa.getActivatingPlayer()); + exSA.setActivatingPlayer(activatingPlayer); } else { exSA.setActivatingPlayer(player); @@ -375,8 +382,9 @@ public class AiController { if (landsInPlay.size() + landList.size() > max) { for (Card c : allCards) { for (SpellAbility sa : c.getSpellAbilities()) { - if (sa.getPayCosts() != null) { - for (CostPart part : sa.getPayCosts().getCostParts()) { + Cost payCosts = sa.getPayCosts(); + if (payCosts != null) { + for (CostPart part : payCosts.getCostParts()) { if (part instanceof CostDiscard) { return null; } @@ -390,10 +398,11 @@ public class AiController { landList = CardLists.filter(landList, new Predicate() { @Override public boolean apply(final Card c) { + CardCollectionView battlefield = player.getCardsIn(ZoneType.Battlefield); canPlaySpellBasic(c, null); - if (c.getType().isLegendary() && !c.getName().equals("Flagstones of Trokair")) { - final CardCollectionView list = player.getCardsIn(ZoneType.Battlefield); - if (Iterables.any(list, CardPredicates.nameEquals(c.getName()))) { + String name = c.getName(); + if (c.getType().isLegendary() && !name.equals("Flagstones of Trokair")) { + if (Iterables.any(battlefield, CardPredicates.nameEquals(name))) { return false; } } @@ -402,7 +411,7 @@ public class AiController { final FCollectionView spellAbilities = c.getSpellAbilities(); final CardCollectionView hand = player.getCardsIn(ZoneType.Hand); - CardCollection lands = new CardCollection(player.getCardsIn(ZoneType.Battlefield)); + CardCollection lands = new CardCollection(battlefield); lands.addAll(hand); lands = CardLists.filter(lands, CardPredicates.Presets.LANDS); int maxCmcInHand = Aggregates.max(hand, CardPredicates.Accessors.fnGetCmc); @@ -565,14 +574,17 @@ public class AiController { Collections.sort(all, saComparator); // put best spells first for (final SpellAbility sa : ComputerUtilAbility.getOriginalAndAltCostAbilities(all, player)) { - if (sa.getApi() == ApiType.Counter || sa.getApi() == exceptSA) { + ApiType saApi = sa.getApi(); + + if (saApi == ApiType.Counter || saApi == exceptSA) { continue; } sa.setActivatingPlayer(player); // TODO: this currently only works as a limited prediction of permanent spells. // Ideally this should cast canPlaySa to determine that the AI is truly able/willing to cast a spell, // but that is currently difficult to implement due to various side effects leading to stack overflow. - if (!ComputerUtil.castPermanentInMain1(player, sa) && sa.getHostCard() != null && !sa.getHostCard().isLand() && ComputerUtilCost.canPayCost(sa, player)) { + Card host = sa.getHostCard(); + if (!ComputerUtil.castPermanentInMain1(player, sa) && host != null && !host.isLand() && ComputerUtilCost.canPayCost(sa, player)) { if (sa instanceof SpellPermanent) { return sa; } From 426e452ab580c6a904faa04d70f4fed5baeca288 Mon Sep 17 00:00:00 2001 From: Rob Schnautz Date: Mon, 25 Jun 2018 21:56:24 +0000 Subject: [PATCH 2/2] convert tabs to spaces --- .../src/main/java/forge/ai/AiController.java | 76 +++++++++---------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/AiController.java b/forge-ai/src/main/java/forge/ai/AiController.java index b2b174bb0e7..e25246a8fbb 100644 --- a/forge-ai/src/main/java/forge/ai/AiController.java +++ b/forge-ai/src/main/java/forge/ai/AiController.java @@ -128,8 +128,8 @@ public class AiController { private List getPossibleETBCounters() { CardCollection all = new CardCollection(player.getCardsIn(ZoneType.Hand)); CardCollectionView ccvPlayerLibrary = player.getCardsIn(ZoneType.Library); - - all.addAll(player.getCardsIn(ZoneType.Exile)); + + all.addAll(player.getCardsIn(ZoneType.Exile)); all.addAll(player.getCardsIn(ZoneType.Graveyard)); if (!ccvPlayerLibrary.isEmpty()) { all.add(ccvPlayerLibrary.get(0)); @@ -155,36 +155,36 @@ public class AiController { // look for cards on the battlefield that should prevent the AI from using that spellability private boolean checkCurseEffects(final SpellAbility sa) { - CardCollectionView ccvGameBattlefield = game.getCardsIn(ZoneType.Battlefield); + CardCollectionView ccvGameBattlefield = game.getCardsIn(ZoneType.Battlefield); for (final Card c : ccvGameBattlefield) { if (c.hasSVar("AICurseEffect")) { final String curse = c.getSVar("AICurseEffect"); if ("NonActive".equals(curse) && !player.equals(game.getPhaseHandler().getPlayerTurn())) { return true; } else { - final Card host = sa.getHostCard(); - if ("DestroyCreature".equals(curse) && sa.isSpell() && host.isCreature() - && !host.hasKeyword(Keyword.INDESTRUCTIBLE)) { - return true; - } else if ("CounterEnchantment".equals(curse) && sa.isSpell() && host.isEnchantment() - && CardFactoryUtil.isCounterable(host)) { - return true; - } else if ("ChaliceOfTheVoid".equals(curse) && sa.isSpell() && CardFactoryUtil.isCounterable(host) - && host.getCMC() == c.getCounters(CounterType.CHARGE)) { - return true; - } else if ("BazaarOfWonders".equals(curse) && sa.isSpell() && CardFactoryUtil.isCounterable(host)) { - String hostName = host.getName(); - for (Card card : ccvGameBattlefield) { - if (!card.isToken() && card.getName().equals(hostName)) { - return true; - } - } - for (Card card : game.getCardsIn(ZoneType.Graveyard)) { - if (card.getName().equals(hostName)) { - return true; - } - } - } + final Card host = sa.getHostCard(); + if ("DestroyCreature".equals(curse) && sa.isSpell() && host.isCreature() + && !host.hasKeyword(Keyword.INDESTRUCTIBLE)) { + return true; + } else if ("CounterEnchantment".equals(curse) && sa.isSpell() && host.isEnchantment() + && CardFactoryUtil.isCounterable(host)) { + return true; + } else if ("ChaliceOfTheVoid".equals(curse) && sa.isSpell() && CardFactoryUtil.isCounterable(host) + && host.getCMC() == c.getCounters(CounterType.CHARGE)) { + return true; + } else if ("BazaarOfWonders".equals(curse) && sa.isSpell() && CardFactoryUtil.isCounterable(host)) { + String hostName = host.getName(); + for (Card card : ccvGameBattlefield) { + if (!card.isToken() && card.getName().equals(hostName)) { + return true; + } + } + for (Card card : game.getCardsIn(ZoneType.Graveyard)) { + if (card.getName().equals(hostName)) { + return true; + } + } + } } } } @@ -196,9 +196,9 @@ public class AiController { && game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.noCreatureETBTriggers)) { return api == null; } - boolean rightapi = false; - String battlefield = ZoneType.Battlefield.toString(); - Player activatingPlayer = sa.getActivatingPlayer(); + boolean rightapi = false; + String battlefield = ZoneType.Battlefield.toString(); + Player activatingPlayer = sa.getActivatingPlayer(); // Trigger play improvements for (final Trigger tr : card.getTriggers()) { @@ -214,7 +214,7 @@ public class AiController { } if (params.containsKey("ValidCard")) { - String validCard = params.get("ValidCard"); + String validCard = params.get("ValidCard"); if (!validCard.contains("Self")) { continue; } @@ -276,7 +276,7 @@ public class AiController { // for trigger test, need to ignore the conditions SpellAbilityCondition cons = exSA.getConditions(); - if (cons != null) { + if (cons != null) { String pres = cons.getIsPresent(); if (pres != null && pres.matches("Card\\.(Strictly)?Self")) { cons.setIsPresent(null); @@ -308,7 +308,7 @@ public class AiController { } if (params.containsKey("ValidCard")) { - String validCard = params.get("ValidCard"); + String validCard = params.get("ValidCard"); if (!validCard.contains("Self")) { continue; } @@ -382,7 +382,7 @@ public class AiController { if (landsInPlay.size() + landList.size() > max) { for (Card c : allCards) { for (SpellAbility sa : c.getSpellAbilities()) { - Cost payCosts = sa.getPayCosts(); + Cost payCosts = sa.getPayCosts(); if (payCosts != null) { for (CostPart part : payCosts.getCostParts()) { if (part instanceof CostDiscard) { @@ -398,9 +398,9 @@ public class AiController { landList = CardLists.filter(landList, new Predicate() { @Override public boolean apply(final Card c) { - CardCollectionView battlefield = player.getCardsIn(ZoneType.Battlefield); + CardCollectionView battlefield = player.getCardsIn(ZoneType.Battlefield); canPlaySpellBasic(c, null); - String name = c.getName(); + String name = c.getName(); if (c.getType().isLegendary() && !name.equals("Flagstones of Trokair")) { if (Iterables.any(battlefield, CardPredicates.nameEquals(name))) { return false; @@ -575,15 +575,15 @@ public class AiController { for (final SpellAbility sa : ComputerUtilAbility.getOriginalAndAltCostAbilities(all, player)) { ApiType saApi = sa.getApi(); - - if (saApi == ApiType.Counter || saApi == exceptSA) { + + if (saApi == ApiType.Counter || saApi == exceptSA) { continue; } sa.setActivatingPlayer(player); // TODO: this currently only works as a limited prediction of permanent spells. // Ideally this should cast canPlaySa to determine that the AI is truly able/willing to cast a spell, // but that is currently difficult to implement due to various side effects leading to stack overflow. - Card host = sa.getHostCard(); + Card host = sa.getHostCard(); if (!ComputerUtil.castPermanentInMain1(player, sa) && host != null && !host.isLand() && ComputerUtilCost.canPayCost(sa, player)) { if (sa instanceof SpellPermanent) { return sa;