From bdc11dd9e7c3a6ce82a4f1f7f9dbc5226ce26c86 Mon Sep 17 00:00:00 2001 From: Maxmtg Date: Sat, 18 May 2013 06:57:02 +0000 Subject: [PATCH] made a few methods with descriptive names to wrap that payManaCost with 5 parameters corrected the extra mana calculation for Nether Void and Spelltithe Enforcer --- res/cardsfolder/n/nether_void.txt | 2 +- res/cardsfolder/s/spelltithe_enforcer.txt | 2 +- .../forge/card/ability/ai/ChangeZoneAi.java | 23 ++++----- .../java/forge/game/ai/ComputerUtilCost.java | 31 ++++++------ .../java/forge/game/ai/ComputerUtilMana.java | 47 ++++++++----------- 5 files changed, 48 insertions(+), 57 deletions(-) diff --git a/res/cardsfolder/n/nether_void.txt b/res/cardsfolder/n/nether_void.txt index 1c47dbf5005..021bbda070e 100644 --- a/res/cardsfolder/n/nether_void.txt +++ b/res/cardsfolder/n/nether_void.txt @@ -4,7 +4,7 @@ Types:World Enchantment T:Mode$ SpellCast | ValidCard$ Card | ValidActivatingPlayer$ Player | TriggerZones$ Battlefield | Execute$ TrigCounter | TriggerDescription$ Whenever a player casts a spell, counter it unless its controller pays 3. SVar:TrigCounter:DB$ Counter | Cost$ 0 | UnlessCost$ 3 | Defined$ TriggeredSpellAbility | UnlessPayer$ TriggeredCardController SVar:RemRandomDeck:True -SVar:SpellsNeedExtraMana:3 +SVar:AI_SpellsNeedExtraMana:3 SVar:Picture:http://www.wizards.com/global/images/magic/general/nether_void.jpg Oracle:Whenever a player casts a spell, counter it unless its controller pays {3}. SetInfo:LEG Rare \ No newline at end of file diff --git a/res/cardsfolder/s/spelltithe_enforcer.txt b/res/cardsfolder/s/spelltithe_enforcer.txt index e2b3351db45..91658688e78 100644 --- a/res/cardsfolder/s/spelltithe_enforcer.txt +++ b/res/cardsfolder/s/spelltithe_enforcer.txt @@ -4,7 +4,7 @@ Types:Creature Elephant Wizard PT:3/3 T:Mode$ SpellCast | ValidCard$ Card | ValidActivatingPlayer$ Opponent | TriggerZones$ Battlefield | Execute$ TrigSac | TriggerDescription$ Whenever an opponent casts a spell, that player sacrifices a permanent unless he or she pays {1}. SVar:TrigSac:DB$ Sacrifice | Defined$ TriggeredCardController | SacValid$ Permanent | SacMessage$ Permanent | UnlessCost$ 1 | UnlessPayer$ TriggeredCardController -SVar:SpellsNeedExtraMana:1 +SVar:AI_SpellsNeedExtraMana:1 Opponent SVar:Picture:http://www.wizards.com/global/images/magic/general/spelltithe_enforcer.jpg Oracle:Whenever an opponent casts a spell, that player sacrifices a permanent unless he or she pays {1}. SetInfo:GPT Rare \ No newline at end of file diff --git a/src/main/java/forge/card/ability/ai/ChangeZoneAi.java b/src/main/java/forge/card/ability/ai/ChangeZoneAi.java index 61596f9523c..23c842a79fb 100644 --- a/src/main/java/forge/card/ability/ai/ChangeZoneAi.java +++ b/src/main/java/forge/card/ability/ai/ChangeZoneAi.java @@ -489,7 +489,6 @@ public class ChangeZoneAi extends SpellAbilityAi { * @return Card */ private static Card chooseCreature(final Player ai, List list) { - Card card = null; Combat combat = new Combat(); combat.initiatePossibleDefenders(ai); List attackers = ai.getOpponent().getCreaturesInPlay(); @@ -504,16 +503,14 @@ public class ChangeZoneAi extends SpellAbilityAi { for (Card c : list) { SpellAbility spell = c.getFirstSpellAbility(); spell.setActivatingPlayer(ai); - if (ComputerUtilMana.payManaCost(spell, ai, true, 0, false)) { - card = c; - break; - } + if (ComputerUtilMana.hasEnoughManaSourcesToCast(spell, ai)) + return c; } - } else { - // not urgent, get the largest creature possible - card = ComputerUtilCard.getBestCreatureAI(list); + return null; } - return card; + + // not urgent, get the largest creature possible + return ComputerUtilCard.getBestCreatureAI(list); } // ************************************************************************************* @@ -865,7 +862,7 @@ public class ChangeZoneAi extends SpellAbilityAi { System.out.println("5 Life or less, trying to find something castable."); CardLists.sortByCmcDesc(nonLands); for (Card potentialCard : nonLands) { - if (ComputerUtilMana.payManaCost(potentialCard.getFirstSpellAbility(), ai, true, 0, false)) { + if (ComputerUtilMana.hasEnoughManaSourcesToCast(potentialCard.getFirstSpellAbility(), ai)) { choice = potentialCard; break; } @@ -976,7 +973,7 @@ public class ChangeZoneAi extends SpellAbilityAi { System.out.println("5 Life or less, trying to find something castable."); CardLists.sortByCmcDesc(nonLands); for (Card potentialCard : nonLands) { - if (ComputerUtilMana.payManaCost(potentialCard.getFirstSpellAbility(), ai, true, 0, false)) { + if (ComputerUtilMana.hasEnoughManaSourcesToCast(potentialCard.getFirstSpellAbility(), ai)) { choice = potentialCard; break; } @@ -1210,7 +1207,7 @@ public class ChangeZoneAi extends SpellAbilityAi { for (Card cardInHand : hand) { final SpellAbility spell = cardInHand.getFirstSpellAbility(); spell.setActivatingPlayer(ai); - canCastSomething |= ComputerUtilMana.payManaCost(spell, ai, true, 0, false); + canCastSomething |= ComputerUtilMana.hasEnoughManaSourcesToCast(spell, ai); } if (!canCastSomething) { System.out.println("Pulling a land as there are none in hand, less than 4 on the board, and nothing in hand is castable."); @@ -1229,7 +1226,7 @@ public class ChangeZoneAi extends SpellAbilityAi { System.out.println("5 Life or less, trying to find something castable."); CardLists.sortByCmcDesc(fetchList); for (Card potentialCard : fetchList) { - if (ComputerUtilMana.payManaCost(potentialCard.getFirstSpellAbility(), ai, true, 0, false)) { + if (ComputerUtilMana.hasEnoughManaSourcesToCast(potentialCard.getFirstSpellAbility(), ai)) { c = potentialCard; break; } diff --git a/src/main/java/forge/game/ai/ComputerUtilCost.java b/src/main/java/forge/game/ai/ComputerUtilCost.java index dd8cb56b9d3..8dc760ae724 100644 --- a/src/main/java/forge/game/ai/ComputerUtilCost.java +++ b/src/main/java/forge/game/ai/ComputerUtilCost.java @@ -23,6 +23,7 @@ import forge.card.spellability.SpellAbility; import forge.game.player.Player; import forge.game.zone.ZoneType; import forge.util.MyRandom; +import forge.util.TextUtil; /** * TODO: Write javadoc for this type. @@ -346,25 +347,25 @@ public class ComputerUtilCost { // Check for stuff like Nether Void int extraManaNeeded = 0; if (sa instanceof Spell) { - for (Player opp : player.getOpponents()) { - for (Card c : opp.getCardsIn(ZoneType.Battlefield)) { - final String snem = c.getSVar("SpellsNeedExtraMana"); - if (!StringUtils.isBlank(snem)) { - try { - extraManaNeeded += Integer.parseInt(snem); - } catch (final NumberFormatException e) { - System.out.println("wrong SpellsNeedExtraMana SVar format on " + c); - } + for (Card c : player.getGame().getCardsIn(ZoneType.Battlefield)) { + final String snem = c.getSVar("AI_SpellsNeedExtraMana"); + if (!StringUtils.isBlank(snem)) { + String[] parts = TextUtil.split(snem, ' '); + boolean meetsRestriction = parts.length == 1 || player.isValid(parts[1], c.getController(), c); + if(!meetsRestriction) + continue; + + try { + extraManaNeeded += Integer.parseInt(snem); + } catch (final NumberFormatException e) { + System.out.println("wrong SpellsNeedExtraMana SVar format on " + c); } } } } - - if (!ComputerUtilMana.payManaCost(sa, player, true, extraManaNeeded, true)) { - return false; - } - - return CostPayment.canPayAdditionalCosts(sa.getPayCosts(), sa); + + return ComputerUtilMana.canPayManaCost(sa, player, extraManaNeeded) + && CostPayment.canPayAdditionalCosts(sa.getPayCosts(), sa); } // canPayCost() public static boolean willPayUnlessCost(SpellAbility sa, Player payer, SpellAbility ability, boolean alreadyPaid, List payers) { diff --git a/src/main/java/forge/game/ai/ComputerUtilMana.java b/src/main/java/forge/game/ai/ComputerUtilMana.java index e5bd2e9d86e..a666f4042d3 100644 --- a/src/main/java/forge/game/ai/ComputerUtilMana.java +++ b/src/main/java/forge/game/ai/ComputerUtilMana.java @@ -8,8 +8,6 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; -import org.apache.commons.lang3.StringUtils; - import com.google.common.base.Predicate; import forge.Card; import forge.CardLists; @@ -44,6 +42,19 @@ import forge.util.maps.TreeMapOfLists; */ public class ComputerUtilMana { + public static boolean canPayManaCost(final SpellAbility sa, final Player ai, final int extraMana) { + return payManaCost(sa, ai, true, extraMana, true); + } + + // Does not check if mana sources can be used right now, just checks for potential chance. + public static boolean hasEnoughManaSourcesToCast(final SpellAbility sa, final Player ai) { + return payManaCost(sa, ai, true, 0, false); + } + + public static boolean payManaCost(final Player ai, final SpellAbility sa) { + return payManaCost(sa, ai, false, 0, true); + } + /** *

* payManaCost. @@ -62,7 +73,7 @@ public class ComputerUtilMana { * @return a boolean. * @since 1.0.15 */ - public static boolean payManaCost(final SpellAbility sa, final Player ai, final boolean test, final int extraMana, boolean checkPlayable) { + private static boolean payManaCost(final SpellAbility sa, final Player ai, final boolean test, final int extraMana, boolean checkPlayable) { ManaCostBeingPaid cost = ComputerUtilMana.calculateManaCost(sa, test, extraMana); final Card card = sa.getSourceCard(); @@ -363,18 +374,6 @@ public class ComputerUtilMana { } - /** - *

- * payManaCost. - *

- * - * @param sa - * a {@link forge.card.spellability.SpellAbility} object. - */ - public static boolean payManaCost(final Player ai, final SpellAbility sa) { - return payManaCost(sa, ai, false, 0, true); - } - /** * Find all mana sources. * @param manaAbilityMap @@ -634,17 +633,11 @@ public class ComputerUtilMana { * @since 1.0.15 */ public static int determineLeftoverMana(final SpellAbility sa, final Player player) { - - int xMana = 0; - - for (int i = 1; i < 99; i++) { - if (!payManaCost(sa, player, true, i, true)) { - break; - } - xMana = i; - } - - return xMana; + for (int i = 1; i < 100; i++) + if (!canPayManaCost(sa, player, i)) + return i - 1; + + return 99; } // Returns basic mana abilities plus "reflected mana" abilities @@ -655,7 +648,7 @@ public class ComputerUtilMana { * * @return a {@link java.util.ArrayList} object. */ - public static final ArrayList getAIPlayableMana(Card c) { + private static final ArrayList getAIPlayableMana(Card c) { final ArrayList res = new ArrayList(); for (final SpellAbility a : c.getManaAbility()) {