mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 04:08:01 +00:00
Merge branch 'optimizing' into 'master'
Reduce method call count. See merge request core-developers/forge!672
This commit is contained in:
@@ -127,10 +127,12 @@ public class AiController {
|
|||||||
|
|
||||||
private List<SpellAbility> getPossibleETBCounters() {
|
private List<SpellAbility> getPossibleETBCounters() {
|
||||||
CardCollection all = new CardCollection(player.getCardsIn(ZoneType.Hand));
|
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));
|
all.addAll(player.getCardsIn(ZoneType.Graveyard));
|
||||||
if (!player.getCardsIn(ZoneType.Library).isEmpty()) {
|
if (!ccvPlayerLibrary.isEmpty()) {
|
||||||
all.add(player.getCardsIn(ZoneType.Library).get(0));
|
all.add(ccvPlayerLibrary.get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (final Player opp : player.getOpponents()) {
|
for (final Player opp : player.getOpponents()) {
|
||||||
@@ -153,30 +155,34 @@ public class AiController {
|
|||||||
|
|
||||||
// look for cards on the battlefield that should prevent the AI from using that spellability
|
// look for cards on the battlefield that should prevent the AI from using that spellability
|
||||||
private boolean checkCurseEffects(final SpellAbility sa) {
|
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")) {
|
if (c.hasSVar("AICurseEffect")) {
|
||||||
final String curse = c.getSVar("AICurseEffect");
|
final String curse = c.getSVar("AICurseEffect");
|
||||||
final Card host = sa.getHostCard();
|
|
||||||
if ("NonActive".equals(curse) && !player.equals(game.getPhaseHandler().getPlayerTurn())) {
|
if ("NonActive".equals(curse) && !player.equals(game.getPhaseHandler().getPlayerTurn())) {
|
||||||
return true;
|
return true;
|
||||||
} else if ("DestroyCreature".equals(curse) && sa.isSpell() && host.isCreature()
|
} else {
|
||||||
&& !sa.getHostCard().hasKeyword(Keyword.INDESTRUCTIBLE)) {
|
final Card host = sa.getHostCard();
|
||||||
return true;
|
if ("DestroyCreature".equals(curse) && sa.isSpell() && host.isCreature()
|
||||||
} else if ("CounterEnchantment".equals(curse) && sa.isSpell() && host.isEnchantment()
|
&& !host.hasKeyword(Keyword.INDESTRUCTIBLE)) {
|
||||||
&& CardFactoryUtil.isCounterable(host)) {
|
return true;
|
||||||
return true;
|
} else if ("CounterEnchantment".equals(curse) && sa.isSpell() && host.isEnchantment()
|
||||||
} else if ("ChaliceOfTheVoid".equals(curse) && sa.isSpell() && CardFactoryUtil.isCounterable(host)
|
&& CardFactoryUtil.isCounterable(host)) {
|
||||||
&& host.getCMC() == c.getCounters(CounterType.CHARGE)) {
|
return true;
|
||||||
return true;
|
} else if ("ChaliceOfTheVoid".equals(curse) && sa.isSpell() && CardFactoryUtil.isCounterable(host)
|
||||||
} else if ("BazaarOfWonders".equals(curse) && sa.isSpell() && CardFactoryUtil.isCounterable(host)) {
|
&& host.getCMC() == c.getCounters(CounterType.CHARGE)) {
|
||||||
for (Card card : game.getCardsIn(ZoneType.Battlefield)) {
|
return true;
|
||||||
if (!card.isToken() && card.getName().equals(host.getName())) {
|
} else if ("BazaarOfWonders".equals(curse) && sa.isSpell() && CardFactoryUtil.isCounterable(host)) {
|
||||||
return true;
|
String hostName = host.getName();
|
||||||
|
for (Card card : ccvGameBattlefield) {
|
||||||
|
if (!card.isToken() && card.getName().equals(hostName)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
for (Card card : game.getCardsIn(ZoneType.Graveyard)) {
|
||||||
for (Card card : game.getCardsIn(ZoneType.Graveyard)) {
|
if (card.getName().equals(hostName)) {
|
||||||
if (card.getName().equals(host.getName())) {
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -186,13 +192,14 @@ public class AiController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean checkETBEffects(final Card card, final SpellAbility sa, final ApiType api) {
|
public boolean checkETBEffects(final Card card, final SpellAbility sa, final ApiType api) {
|
||||||
boolean rightapi = false;
|
|
||||||
|
|
||||||
if (card.isCreature()
|
if (card.isCreature()
|
||||||
&& game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.noCreatureETBTriggers)) {
|
&& game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.noCreatureETBTriggers)) {
|
||||||
return api == null;
|
return api == null;
|
||||||
}
|
}
|
||||||
|
boolean rightapi = false;
|
||||||
|
String battlefield = ZoneType.Battlefield.toString();
|
||||||
|
Player activatingPlayer = sa.getActivatingPlayer();
|
||||||
|
|
||||||
// Trigger play improvements
|
// Trigger play improvements
|
||||||
for (final Trigger tr : card.getTriggers()) {
|
for (final Trigger tr : card.getTriggers()) {
|
||||||
// These triggers all care for ETB effects
|
// These triggers all care for ETB effects
|
||||||
@@ -202,21 +209,22 @@ public class AiController {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!params.get("Destination").equals(ZoneType.Battlefield.toString())) {
|
if (!params.get("Destination").equals(battlefield)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.containsKey("ValidCard")) {
|
if (params.containsKey("ValidCard")) {
|
||||||
if (!params.get("ValidCard").contains("Self")) {
|
String validCard = params.get("ValidCard");
|
||||||
|
if (!validCard.contains("Self")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (params.get("ValidCard").contains("notkicked")) {
|
if (validCard.contains("notkicked")) {
|
||||||
if (sa.isKicked()) {
|
if (sa.isKicked()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else if (params.get("ValidCard").contains("kicked")) {
|
} else if (validCard.contains("kicked")) {
|
||||||
if (params.get("ValidCard").contains("kicked ")) { // want a specific kicker
|
if (validCard.contains("kicked ")) { // want a specific kicker
|
||||||
String s = params.get("ValidCard").split("kicked ")[1];
|
String s = validCard.split("kicked ")[1];
|
||||||
if ("1".equals(s) && !sa.isOptionalCostPaid(OptionalCost.Kicker1)) continue;
|
if ("1".equals(s) && !sa.isOptionalCostPaid(OptionalCost.Kicker1)) continue;
|
||||||
if ("2".equals(s) && !sa.isOptionalCostPaid(OptionalCost.Kicker2)) continue;
|
if ("2".equals(s) && !sa.isOptionalCostPaid(OptionalCost.Kicker2)) continue;
|
||||||
} else if (!sa.isKicked()) {
|
} else if (!sa.isKicked()) {
|
||||||
@@ -259,7 +267,7 @@ public class AiController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sa != null) {
|
if (sa != null) {
|
||||||
exSA.setActivatingPlayer(sa.getActivatingPlayer());
|
exSA.setActivatingPlayer(activatingPlayer);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
exSA.setActivatingPlayer(player);
|
exSA.setActivatingPlayer(player);
|
||||||
@@ -267,13 +275,11 @@ public class AiController {
|
|||||||
exSA.setTrigger(true);
|
exSA.setTrigger(true);
|
||||||
|
|
||||||
// for trigger test, need to ignore the conditions
|
// for trigger test, need to ignore the conditions
|
||||||
if (exSA.getConditions() != null) {
|
SpellAbilityCondition cons = exSA.getConditions();
|
||||||
SpellAbilityCondition cons = exSA.getConditions();
|
if (cons != null) {
|
||||||
if (cons.getIsPresent() != null) {
|
String pres = cons.getIsPresent();
|
||||||
String pres = cons.getIsPresent();
|
if (pres != null && pres.matches("Card\\.(Strictly)?Self")) {
|
||||||
if ("Card.Self".equals(pres) || "Card.StrictlySelf".equals(pres)) {
|
|
||||||
cons.setIsPresent(null);
|
cons.setIsPresent(null);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,21 +303,22 @@ public class AiController {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!params.get("Destination").equals(ZoneType.Battlefield.toString())) {
|
if (!params.get("Destination").equals(battlefield)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params.containsKey("ValidCard")) {
|
if (params.containsKey("ValidCard")) {
|
||||||
if (!params.get("ValidCard").contains("Self")) {
|
String validCard = params.get("ValidCard");
|
||||||
|
if (!validCard.contains("Self")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (params.get("ValidCard").contains("notkicked")) {
|
if (validCard.contains("notkicked")) {
|
||||||
if (sa.isKicked()) {
|
if (sa.isKicked()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else if (params.get("ValidCard").contains("kicked")) {
|
} else if (validCard.contains("kicked")) {
|
||||||
if (params.get("ValidCard").contains("kicked ")) { // want a specific kicker
|
if (validCard.contains("kicked ")) { // want a specific kicker
|
||||||
String s = params.get("ValidCard").split("kicked ")[1];
|
String s = validCard.split("kicked ")[1];
|
||||||
if ("1".equals(s) && !sa.isOptionalCostPaid(OptionalCost.Kicker1)) continue;
|
if ("1".equals(s) && !sa.isOptionalCostPaid(OptionalCost.Kicker1)) continue;
|
||||||
if ("2".equals(s) && !sa.isOptionalCostPaid(OptionalCost.Kicker2)) continue;
|
if ("2".equals(s) && !sa.isOptionalCostPaid(OptionalCost.Kicker2)) continue;
|
||||||
} else if (!sa.isKicked()) { // otherwise just any must be present
|
} else if (!sa.isKicked()) { // otherwise just any must be present
|
||||||
@@ -327,7 +334,7 @@ public class AiController {
|
|||||||
|
|
||||||
if (exSA != null) {
|
if (exSA != null) {
|
||||||
if (sa != null) {
|
if (sa != null) {
|
||||||
exSA.setActivatingPlayer(sa.getActivatingPlayer());
|
exSA.setActivatingPlayer(activatingPlayer);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
exSA.setActivatingPlayer(player);
|
exSA.setActivatingPlayer(player);
|
||||||
@@ -375,8 +382,9 @@ public class AiController {
|
|||||||
if (landsInPlay.size() + landList.size() > max) {
|
if (landsInPlay.size() + landList.size() > max) {
|
||||||
for (Card c : allCards) {
|
for (Card c : allCards) {
|
||||||
for (SpellAbility sa : c.getSpellAbilities()) {
|
for (SpellAbility sa : c.getSpellAbilities()) {
|
||||||
if (sa.getPayCosts() != null) {
|
Cost payCosts = sa.getPayCosts();
|
||||||
for (CostPart part : sa.getPayCosts().getCostParts()) {
|
if (payCosts != null) {
|
||||||
|
for (CostPart part : payCosts.getCostParts()) {
|
||||||
if (part instanceof CostDiscard) {
|
if (part instanceof CostDiscard) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -390,10 +398,11 @@ public class AiController {
|
|||||||
landList = CardLists.filter(landList, new Predicate<Card>() {
|
landList = CardLists.filter(landList, new Predicate<Card>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(final Card c) {
|
public boolean apply(final Card c) {
|
||||||
|
CardCollectionView battlefield = player.getCardsIn(ZoneType.Battlefield);
|
||||||
canPlaySpellBasic(c, null);
|
canPlaySpellBasic(c, null);
|
||||||
if (c.getType().isLegendary() && !c.getName().equals("Flagstones of Trokair")) {
|
String name = c.getName();
|
||||||
final CardCollectionView list = player.getCardsIn(ZoneType.Battlefield);
|
if (c.getType().isLegendary() && !name.equals("Flagstones of Trokair")) {
|
||||||
if (Iterables.any(list, CardPredicates.nameEquals(c.getName()))) {
|
if (Iterables.any(battlefield, CardPredicates.nameEquals(name))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -402,7 +411,7 @@ public class AiController {
|
|||||||
final FCollectionView<SpellAbility> spellAbilities = c.getSpellAbilities();
|
final FCollectionView<SpellAbility> spellAbilities = c.getSpellAbilities();
|
||||||
|
|
||||||
final CardCollectionView hand = player.getCardsIn(ZoneType.Hand);
|
final CardCollectionView hand = player.getCardsIn(ZoneType.Hand);
|
||||||
CardCollection lands = new CardCollection(player.getCardsIn(ZoneType.Battlefield));
|
CardCollection lands = new CardCollection(battlefield);
|
||||||
lands.addAll(hand);
|
lands.addAll(hand);
|
||||||
lands = CardLists.filter(lands, CardPredicates.Presets.LANDS);
|
lands = CardLists.filter(lands, CardPredicates.Presets.LANDS);
|
||||||
int maxCmcInHand = Aggregates.max(hand, CardPredicates.Accessors.fnGetCmc);
|
int maxCmcInHand = Aggregates.max(hand, CardPredicates.Accessors.fnGetCmc);
|
||||||
@@ -565,14 +574,17 @@ public class AiController {
|
|||||||
Collections.sort(all, saComparator); // put best spells first
|
Collections.sort(all, saComparator); // put best spells first
|
||||||
|
|
||||||
for (final SpellAbility sa : ComputerUtilAbility.getOriginalAndAltCostAbilities(all, player)) {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
sa.setActivatingPlayer(player);
|
sa.setActivatingPlayer(player);
|
||||||
// TODO: this currently only works as a limited prediction of permanent spells.
|
// 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,
|
// 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.
|
// 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) {
|
if (sa instanceof SpellPermanent) {
|
||||||
return sa;
|
return sa;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user