From 19c07f5bef16893358d274bf34ee441020dfb133 Mon Sep 17 00:00:00 2001 From: Hans Mackowiak Date: Sun, 31 May 2020 14:22:25 +0000 Subject: [PATCH] Resolve "Avoid bad performance pattern involving Interger.parseInt" --- .../java/forge/ai/AiAttackController.java | 17 +- .../main/java/forge/ai/ComputerUtilCard.java | 15 +- .../java/forge/ai/ComputerUtilCombat.java | 334 +++++++----------- .../main/java/forge/ai/ComputerUtilCost.java | 8 +- .../src/main/java/forge/card/CardRules.java | 6 +- .../main/java/forge/game/CardTraitBase.java | 23 +- .../src/main/java/forge/game/ForgeScript.java | 7 +- .../main/java/forge/game/GameActionUtil.java | 10 +- .../ability/effects/ManaReflectedEffect.java | 6 +- .../game/ability/effects/RepeatEffect.java | 10 +- .../java/forge/game/card/CardProperty.java | 13 +- .../forge/game/replacement/ReplaceDamage.java | 8 +- .../game/replacement/ReplaceProduceMana.java | 9 +- .../spellability/SpellAbilityCondition.java | 9 +- .../SpellAbilityStackInstance.java | 1 - .../main/java/forge/game/trigger/Trigger.java | 14 +- .../game/trigger/TriggerChangesZone.java | 10 +- 17 files changed, 171 insertions(+), 329 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/AiAttackController.java b/forge-ai/src/main/java/forge/ai/AiAttackController.java index dbb8567af57..b3dc45e4999 100644 --- a/forge-ai/src/main/java/forge/ai/AiAttackController.java +++ b/forge-ai/src/main/java/forge/ai/AiAttackController.java @@ -24,6 +24,7 @@ import forge.ai.ability.AnimateAi; import forge.card.CardTypeView; import forge.game.GameEntity; import forge.game.ability.AbilityFactory; +import forge.game.ability.AbilityUtils; import forge.game.ability.ApiType; import forge.game.ability.effects.ProtectEffect; import forge.game.card.*; @@ -1135,7 +1136,6 @@ public class AiAttackController { // TODO Somehow subtract expected damage of other attacking creatures from enemy life total (how? other attackers not yet declared? Can the AI guesstimate which of their creatures will not get blocked?) if (attacker.getCurrentPower() * Integer.parseInt(attacker.getSVar("NonCombatPriority")) < ai.getOpponentsSmallestLifeTotal()) { // Check if the card actually has an ability the AI can and wants to play, if not, attacking is fine! - boolean wantability = false; for (SpellAbility sa : attacker.getSpellAbilities()) { // Do not attack if we can afford using the ability. if (sa.isAbility()) { @@ -1365,21 +1365,12 @@ public class AiAttackController { if (c.hasSVar("AIExertCondition")) { if (!c.getSVar("AIExertCondition").isEmpty()) { final String needsToExert = c.getSVar("AIExertCondition"); - int x = 0; - int y = 0; String sVar = needsToExert.split(" ")[0]; String comparator = needsToExert.split(" ")[1]; String compareTo = comparator.substring(2); - try { - x = Integer.parseInt(sVar); - } catch (final NumberFormatException e) { - x = CardFactoryUtil.xCount(c, c.getSVar(sVar)); - } - try { - y = Integer.parseInt(compareTo); - } catch (final NumberFormatException e) { - y = CardFactoryUtil.xCount(c, c.getSVar(compareTo)); - } + + int x = AbilityUtils.calculateAmount(c, sVar, null); + int y = AbilityUtils.calculateAmount(c, compareTo, null); if (Expressions.compare(x, comparator, y)) { shouldExert = true; } diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java index 3009dca985a..9d66fb23171 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCard.java @@ -1908,21 +1908,12 @@ public class ComputerUtilCard { } if (card.getSVar(needsToPlayVarName).length() > 0) { final String needsToPlay = card.getSVar(needsToPlayVarName); - int x = 0; - int y = 0; String sVar = needsToPlay.split(" ")[0]; String comparator = needsToPlay.split(" ")[1]; String compareTo = comparator.substring(2); - try { - x = Integer.parseInt(sVar); - } catch (final NumberFormatException e) { - x = CardFactoryUtil.xCount(card, card.getSVar(sVar)); - } - try { - y = Integer.parseInt(compareTo); - } catch (final NumberFormatException e) { - y = CardFactoryUtil.xCount(card, card.getSVar(compareTo)); - } + int x = AbilityUtils.calculateAmount(card, sVar, sa); + int y = AbilityUtils.calculateAmount(card, compareTo, sa); + if (!Expressions.compare(x, comparator, y)) { return AiPlayDecision.NeedsToPlayCriteriaNotMet; } diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java index baffff9cc5a..8e66d4a60d0 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCombat.java @@ -973,56 +973,39 @@ public class ComputerUtilCombat { } theTriggers.addAll(attacker.getTriggers()); for (final Trigger trigger : theTriggers) { - final Map trigParams = trigger.getMapParams(); final Card source = trigger.getHostCard(); if (!ComputerUtilCombat.combatTriggerWillTrigger(attacker, blocker, trigger, null)) { continue; } - Map abilityParams = null; - if (trigger.getOverridingAbility() != null) { - abilityParams = trigger.getOverridingAbility().getMapParams(); - } else if (trigParams.containsKey("Execute")) { - final String ability = source.getSVar(trigParams.get("Execute")); - abilityParams = AbilityFactory.getMapParams(ability); - } else { + SpellAbility sa = trigger.ensureAbility(); + if (sa == null) { continue; } - if (abilityParams.containsKey("AB") && !abilityParams.get("AB").equals("Pump")) { + if (!ApiType.Pump.equals(sa.getApi())) { continue; } - if (abilityParams.containsKey("DB") && !abilityParams.get("DB").equals("Pump")) { + + if (sa.usesTargeting()) { continue; } - if (abilityParams.containsKey("ValidTgts") || abilityParams.containsKey("Tgt")) { - continue; // targeted pumping not supported + + if (!sa.hasParam("NumAtt")) { + continue; } - final List list = AbilityUtils.getDefinedCards(source, abilityParams.get("Defined"), null); - if (abilityParams.containsKey("Defined") && abilityParams.get("Defined").equals("TriggeredBlocker")) { + + String defined = sa.getParam("Defined"); + final List list = AbilityUtils.getDefinedCards(source, defined, sa); + if ("TriggeredBlocker".equals(defined)) { list.add(blocker); } - if (list.isEmpty()) { - continue; - } if (!list.contains(blocker)) { continue; } - if (!abilityParams.containsKey("NumAtt")) { - continue; - } - String att = abilityParams.get("NumAtt"); - if (att.startsWith("+")) { - att = att.substring(1); - } - try { - power += Integer.parseInt(att); - } catch (final NumberFormatException nfe) { - // can't parse the number (X for example) - power += 0; - } + power += AbilityUtils.calculateAmount(source, sa.getParam("NumAtt"), sa, true); } if (withoutAbilities) { return power; @@ -1108,95 +1091,54 @@ public class ComputerUtilCombat { } theTriggers.addAll(attacker.getTriggers()); for (final Trigger trigger : theTriggers) { - final Map trigParams = trigger.getMapParams(); final Card source = trigger.getHostCard(); if (!ComputerUtilCombat.combatTriggerWillTrigger(attacker, blocker, trigger, null)) { continue; } - Map abilityParams = null; - if (trigger.getOverridingAbility() != null) { - abilityParams = trigger.getOverridingAbility().getMapParams(); - } else if (trigParams.containsKey("Execute")) { - final String ability = source.getSVar(trigParams.get("Execute")); - abilityParams = AbilityFactory.getMapParams(ability); - } else { + SpellAbility sa = trigger.ensureAbility(); + if (sa == null) { continue; } - String abType = ""; - if (abilityParams.containsKey("AB")) { - abType = abilityParams.get("AB"); - } else if (abilityParams.containsKey("DB")) { - abType = abilityParams.get("DB"); - } - // DealDamage triggers - if (abType.equals("DealDamage")) { - if (!abilityParams.containsKey("Defined") || !abilityParams.get("Defined").equals("TriggeredBlocker")) { - continue; - } - int damage = 0; - try { - damage = Integer.parseInt(abilityParams.get("NumDmg")); - } catch (final NumberFormatException nfe) { - // can't parse the number (X for example) + if (ApiType.DealDamage.equals(sa.getApi())) { + if (!"TriggeredBlocker".equals(sa.getParam("Defined"))) { continue; } + int damage = AbilityUtils.calculateAmount(source, sa.getParam("NumDmg"), sa); toughness -= predictDamageTo(blocker, damage, 0, source, false); - continue; - } + } else // -1/-1 PutCounter triggers - if (abType.equals("PutCounter")) { - if (!abilityParams.containsKey("Defined") || !abilityParams.get("Defined").equals("TriggeredBlocker")) { + if (ApiType.PutCounter.equals(sa.getApi())) { + if (!"TriggeredBlocker".equals(sa.getParam("Defined"))) { continue; } - if (!abilityParams.containsKey("CounterType") || !abilityParams.get("CounterType").equals("M1M1")) { + if (!"M1M1".equals(sa.getParam("CounterType"))) { continue; } - int num = 0; - try { - num = Integer.parseInt(abilityParams.get("CounterNum")); - } catch (final NumberFormatException nfe) { - // can't parse the number (X for example) - continue; - } - toughness -= num; - continue; - } + toughness -= AbilityUtils.calculateAmount(source, sa.getParam("CounterNum"), sa); + } else // Pump triggers - if (!abType.equals("Pump")) { - continue; - } - if (abilityParams.containsKey("ValidTgts") || abilityParams.containsKey("Tgt")) { - continue; // targeted pumping not supported - } - final List list = AbilityUtils.getDefinedCards(source, abilityParams.get("Defined"), null); - if (abilityParams.containsKey("Defined") && abilityParams.get("Defined").equals("TriggeredBlocker")) { - list.add(blocker); - } - if (list.isEmpty()) { - continue; - } - if (!list.contains(blocker)) { - continue; - } - if (!abilityParams.containsKey("NumDef")) { - continue; - } - - String def = abilityParams.get("NumDef"); - if (def.startsWith("+")) { - def = def.substring(1); - } - try { - toughness += Integer.parseInt(def); - } catch (final NumberFormatException nfe) { - // can't parse the number (X for example) + if (ApiType.Pump.equals(sa.getApi())) { + if (sa.usesTargeting()) { + continue; // targeted pumping not supported + } + final List list = AbilityUtils.getDefinedCards(source, sa.getParam("Defined"), null); + if ("TriggeredBlocker".equals(sa.getParam("Defined"))) { + list.add(blocker); + } + if (list.isEmpty() || !list.contains(blocker)) { + continue; + } + if (!sa.hasParam("NumDef")) { + continue; + } + toughness += AbilityUtils.calculateAmount(source, sa.getParam("NumDef"), sa, true); } } if (withoutAbilities) { @@ -1521,141 +1463,128 @@ public class ComputerUtilCombat { final CardCollectionView cardList = game.getCardsIn(ZoneType.Battlefield); for (final Card card : cardList) { for (final StaticAbility stAb : card.getStaticAbilities()) { - final Map params = stAb.getMapParams(); - if (!params.get("Mode").equals("Continuous")) { + if (!"Continuous".equals(stAb.getParam("Mode"))) { continue; } - if (params.containsKey("Affected") && params.get("Affected").contains("attacking")) { - final String valid = TextUtil.fastReplace(params.get("Affected"), "attacking", "Creature"); + if (!stAb.hasParam("Affected")) { + continue; + } + if (!stAb.hasParam("AddToughness")) { + continue; + } + String affected = stAb.getParam("Affected"); + String addT = stAb.getParam("AddToughness"); + if (affected.contains("attacking")) { + final String valid = TextUtil.fastReplace(affected, "attacking", "Creature"); if (!attacker.isValid(valid, card.getController(), card, null)) { continue; } - if (params.containsKey("AddToughness")) { - if (params.get("AddToughness").equals("X")) { - toughness += CardFactoryUtil.xCount(card, card.getSVar("X")); - } else if (params.get("AddToughness").equals("Y")) { - toughness += CardFactoryUtil.xCount(card, card.getSVar("Y")); - } else { - toughness += Integer.valueOf(params.get("AddToughness")); - } - } - } else if (params.containsKey("Affected") && params.get("Affected").contains("untapped")) { - final String valid = TextUtil.fastReplace(params.get("Affected"), "untapped", "Creature"); + toughness += AbilityUtils.calculateAmount(card, addT, stAb, true); + } else if (affected.contains("untapped")) { + final String valid = TextUtil.fastReplace(affected, "untapped", "Creature"); if (!attacker.isValid(valid, card.getController(), card, null) || attacker.hasKeyword(Keyword.VIGILANCE)) { continue; } // remove the bonus, because it will no longer be granted - if (params.containsKey("AddToughness")) { - toughness -= Integer.valueOf(params.get("AddToughness")); - } + toughness -= AbilityUtils.calculateAmount(card, addT, stAb, true); } } } } for (final Trigger trigger : theTriggers) { - final Map trigParams = trigger.getMapParams(); final Card source = trigger.getHostCard(); if (!ComputerUtilCombat.combatTriggerWillTrigger(attacker, blocker, trigger, combat)) { continue; } - Map abilityParams = null; - if (trigger.getOverridingAbility() != null) { - abilityParams = trigger.getOverridingAbility().getMapParams(); - } else if (trigParams.containsKey("Execute")) { - final String ability = source.getSVar(trigParams.get("Execute")); - abilityParams = AbilityFactory.getMapParams(ability); - } else { + SpellAbility sa = trigger.ensureAbility(); + if (sa == null) { continue; } + sa.setActivatingPlayer(source.getController()); - if (abilityParams.containsKey("ValidTgts") || abilityParams.containsKey("Tgt")) { + if (sa.usesTargeting()) { continue; // targeted pumping not supported } // DealDamage triggers - if ((abilityParams.containsKey("AB") && abilityParams.get("AB").equals("DealDamage")) - || (abilityParams.containsKey("DB") && abilityParams.get("DB").equals("DealDamage"))) { - if (!abilityParams.containsKey("Defined") || !abilityParams.get("Defined").equals("TriggeredAttacker")) { - continue; - } - int damage = 0; - try { - damage = Integer.parseInt(abilityParams.get("NumDmg")); - } catch (final NumberFormatException nfe) { - // can't parse the number (X for example) + if (ApiType.DealDamage.equals(sa.getApi())) { + if ("TriggeredAttacker".equals(sa.getParam("Defined"))) { continue; } + int damage = AbilityUtils.calculateAmount(source, sa.getParam("NumDmg"), sa); + toughness -= predictDamageTo(attacker, damage, 0, source, false); continue; - } + } else if (ApiType.Pump.equals(sa.getApi())) { - // Pump triggers - if (abilityParams.containsKey("AB") && !abilityParams.get("AB").equals("Pump") - && !abilityParams.get("AB").equals("PumpAll")) { - continue; - } - if (abilityParams.containsKey("DB") && !abilityParams.get("DB").equals("Pump") - && !abilityParams.get("DB").equals("PumpAll")) { - continue; - } - - if (abilityParams.containsKey("Cost")) { - SpellAbility sa = null; - if (trigger.getOverridingAbility() != null) { - sa = trigger.getOverridingAbility(); - } else { - final String ability = source.getSVar(trigParams.get("Execute")); - sa = AbilityFactory.getAbility(ability, source); + if (sa.hasParam("Cost")) { + if (!CostPayment.canPayAdditionalCosts(sa.getPayCosts(), sa)) { + continue; + } } - - sa.setActivatingPlayer(source.getController()); - if (!CostPayment.canPayAdditionalCosts(sa.getPayCosts(), sa)) { + if (!sa.hasParam("NumDef")) { continue; } - } - - List list = Lists.newArrayList(); - if (!abilityParams.containsKey("ValidCards")) { - list = AbilityUtils.getDefinedCards(source, abilityParams.get("Defined"), null); - } - if (abilityParams.containsKey("Defined") && abilityParams.get("Defined").equals("TriggeredAttacker")) { - list.add(attacker); - } - if (abilityParams.containsKey("ValidCards")) { - if (attacker.isValid(abilityParams.get("ValidCards").split(","), source.getController(), source, null) - || attacker.isValid(abilityParams.get("ValidCards").replace("attacking+", "").split(","), - source.getController(), source, null)) { + CardCollection list = AbilityUtils.getDefinedCards(source, sa.getParam("Defined"), sa); + if ("TriggeredAttacker".equals(sa.getParam("Defined"))) { list.add(attacker); } - } - if (list.isEmpty()) { - continue; - } - if (!list.contains(attacker)) { - continue; - } - if (!abilityParams.containsKey("NumDef")) { - continue; - } - - String def = abilityParams.get("NumDef"); - if (def.startsWith("+")) { - def = def.substring(1); - } - if (def.matches("[0-9][0-9]?") || def.matches("-" + "[0-9][0-9]?")) { - toughness += Integer.parseInt(def); - } else { - String bonus = source.getSVar(def); - if (bonus.contains("TriggerCount$NumBlockers")) { - bonus = TextUtil.fastReplace(bonus, "TriggerCount$NumBlockers", "Number$1"); - } else if (bonus.contains("TriggeredPlayersDefenders$Amount")) { // for Melee - bonus = TextUtil.fastReplace(bonus, "TriggeredPlayersDefenders$Amount", "Number$1"); + if (!list.contains(attacker)) { + continue; + } + + String def = sa.getParam("NumDef"); + if (def.startsWith("+")) { + def = def.substring(1); + } + if (def.matches("[0-9][0-9]?") || def.matches("-" + "[0-9][0-9]?")) { + toughness += Integer.parseInt(def); + } else { + String bonus = AbilityUtils.getSVar(sa, def); + if (bonus.contains("TriggerCount$NumBlockers")) { + bonus = TextUtil.fastReplace(bonus, "TriggerCount$NumBlockers", "Number$1"); + } else if (bonus.contains("TriggeredPlayersDefenders$Amount")) { // for Melee + bonus = TextUtil.fastReplace(bonus, "TriggeredPlayersDefenders$Amount", "Number$1"); + } + toughness += CardFactoryUtil.xCount(source, bonus); + } + } else if (ApiType.PumpAll.equals(sa.getApi())) { + + if (sa.hasParam("Cost")) { + if (!CostPayment.canPayAdditionalCosts(sa.getPayCosts(), sa)) { + continue; + } + } + + if (!sa.hasParam("ValidCards")) { + continue; + } + if (!sa.hasParam("NumDef")) { + continue; + } + if (!attacker.isValid(sa.getParam("ValidCards").replace("attacking+", "").split(","), source.getController(), source, sa)) { + continue; + } + + String def = sa.getParam("NumDef"); + if (def.startsWith("+")) { + def = def.substring(1); + } + if (def.matches("[0-9][0-9]?") || def.matches("-" + "[0-9][0-9]?")) { + toughness += Integer.parseInt(def); + } else { + String bonus = AbilityUtils.getSVar(sa, def); + if (bonus.contains("TriggerCount$NumBlockers")) { + bonus = TextUtil.fastReplace(bonus, "TriggerCount$NumBlockers", "Number$1"); + } else if (bonus.contains("TriggeredPlayersDefenders$Amount")) { // for Melee + bonus = TextUtil.fastReplace(bonus, "TriggeredPlayersDefenders$Amount", "Number$1"); + } + toughness += CardFactoryUtil.xCount(source, bonus); } - toughness += CardFactoryUtil.xCount(source, bonus); } } if (withoutAbilities) { @@ -1672,18 +1601,19 @@ public class ComputerUtilCombat { if (ability.usesTargeting() && !ability.canTarget(attacker)) { continue; } + if (ability.getPayCosts().hasTapCost() && !attacker.hasKeyword(Keyword.VIGILANCE)) { + continue; + } + if (!ComputerUtilCost.canPayCost(ability, attacker.getController())) { + continue; + } if (ability.getApi() == ApiType.Pump) { if (!ability.hasParam("NumDef")) { continue; } - if (!ability.getPayCosts().hasTapCost() && ComputerUtilCost.canPayCost(ability, attacker.getController())) { - int tBonus = AbilityUtils.calculateAmount(ability.getHostCard(), ability.getParam("NumDef"), ability); - if (tBonus > 0) { - toughness += tBonus; - } - } + toughness += AbilityUtils.calculateAmount(ability.getHostCard(), ability.getParam("NumDef"), ability, true); } else if (ability.getApi() == ApiType.PutCounter) { if (!ability.hasParam("CounterType") || !ability.getParam("CounterType").equals("P1P1")) { continue; @@ -1697,11 +1627,9 @@ public class ComputerUtilCombat { continue; } - if (!ability.getPayCosts().hasTapCost() && ComputerUtilCost.canPayCost(ability, attacker.getController())) { - int tBonus = AbilityUtils.calculateAmount(ability.getHostCard(), ability.getParam("CounterNum"), ability); - if (tBonus > 0) { - toughness += tBonus; - } + int tBonus = AbilityUtils.calculateAmount(ability.getHostCard(), ability.getParam("CounterNum"), ability); + if (tBonus > 0) { + toughness += tBonus; } } } diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilCost.java b/forge-ai/src/main/java/forge/ai/ComputerUtilCost.java index 78de56e6988..26fa41c1dd5 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilCost.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilCost.java @@ -467,9 +467,9 @@ public class ComputerUtilCost { if(!meetsRestriction) continue; - try { + if (StringUtils.isNumeric(parts[0])) { extraManaNeeded += Integer.parseInt(parts[0]); - } catch (final NumberFormatException e) { + } else { System.out.println("wrong SpellsNeedExtraMana SVar format on " + c); } } @@ -480,9 +480,9 @@ public class ComputerUtilCost { } final String snem = c.getSVar("SpellsNeedExtraManaEffect"); if (!StringUtils.isBlank(snem)) { - try { + if (StringUtils.isNumeric(snem)) { extraManaNeeded += Integer.parseInt(snem); - } catch (final NumberFormatException e) { + } else { System.out.println("wrong SpellsNeedExtraManaEffect SVar format on " + c); } } diff --git a/forge-core/src/main/java/forge/card/CardRules.java b/forge-core/src/main/java/forge/card/CardRules.java index a27b60adf2c..6cd5b4daaee 100644 --- a/forge-core/src/main/java/forge/card/CardRules.java +++ b/forge-core/src/main/java/forge/card/CardRules.java @@ -531,12 +531,10 @@ public final class CardRules implements ICardCharacteristics { public final ManaCostShard next() { final String unparsed = st.nextToken(); // System.out.println(unparsed); - try { - int iVal = Integer.parseInt(unparsed); - this.genericCost += iVal; + if (StringUtils.isNumeric(unparsed)) { + this.genericCost += Integer.parseInt(unparsed); return null; } - catch (NumberFormatException nex) { } return ManaCostShard.parseNonGeneric(unparsed); } diff --git a/forge-game/src/main/java/forge/game/CardTraitBase.java b/forge-game/src/main/java/forge/game/CardTraitBase.java index a62e5144c3a..1b6da08e1b8 100644 --- a/forge-game/src/main/java/forge/game/CardTraitBase.java +++ b/forge-game/src/main/java/forge/game/CardTraitBase.java @@ -5,7 +5,6 @@ import forge.card.mana.ManaAtom; import forge.game.ability.AbilityUtils; import forge.game.card.Card; import forge.game.card.CardCollection; -import forge.game.card.CardFactoryUtil; import forge.game.card.CardLists; import forge.game.card.CardUtil; import forge.game.card.CardView; @@ -271,13 +270,8 @@ public abstract class CardTraitBase extends GameObject implements IHasCardView { lifeCompare = params.get("LifeAmount"); } - int right = 1; final String rightString = lifeCompare.substring(2); - try { - right = Integer.parseInt(rightString); - } catch (final NumberFormatException nfe) { - right = CardFactoryUtil.xCount(this.getHostCard(), this.getHostCard().getSVar(rightString)); - } + int right = AbilityUtils.calculateAmount(getHostCard(), rightString, this); if (!Expressions.compare(life, lifeCompare, right)) { return false; @@ -314,13 +308,9 @@ public abstract class CardTraitBase extends GameObject implements IHasCardView { } list = CardLists.getValidCards(list, sIsPresent.split(","), this.getHostCard().getController(), this.getHostCard(), null); - int right = 1; + final String rightString = presentCompare.substring(2); - try { - right = Integer.parseInt(rightString); - } catch (final NumberFormatException nfe) { - right = CardFactoryUtil.xCount(this.getHostCard(), this.getHostCard().getSVar(rightString)); - } + int right = AbilityUtils.calculateAmount(getHostCard(), rightString, this); final int left = list.size(); if (!Expressions.compare(left, presentCompare, right)) { @@ -355,13 +345,8 @@ public abstract class CardTraitBase extends GameObject implements IHasCardView { list = CardLists.getValidCards(list, sIsPresent.split(","), this.getHostCard().getController(), this.getHostCard(), null); - int right = 1; final String rightString = presentCompare.substring(2); - try { - right = Integer.parseInt(rightString); - } catch (final NumberFormatException nfe) { - right = CardFactoryUtil.xCount(this.getHostCard(), this.getHostCard().getSVar(rightString)); - } + int right = AbilityUtils.calculateAmount(getHostCard(), rightString, this); final int left = list.size(); if (!Expressions.compare(left, presentCompare, right)) { diff --git a/forge-game/src/main/java/forge/game/ForgeScript.java b/forge-game/src/main/java/forge/game/ForgeScript.java index 057e55f203e..06a3d41adee 100644 --- a/forge-game/src/main/java/forge/game/ForgeScript.java +++ b/forge-game/src/main/java/forge/game/ForgeScript.java @@ -108,14 +108,9 @@ public class ForgeScript { } return false; } else if (property.startsWith("cmc")) { - int x; String rhs = property.substring(5); int y = cardState.getManaCost().getCMC(); - try { - x = Integer.parseInt(rhs); - } catch (final NumberFormatException e) { - x = AbilityUtils.calculateAmount(source, rhs, spellAbility); - } + int x = AbilityUtils.calculateAmount(source, rhs, spellAbility); return Expressions.compare(y, property, x); } else return cardState.getTypeWithChanges().hasStringType(property); diff --git a/forge-game/src/main/java/forge/game/GameActionUtil.java b/forge-game/src/main/java/forge/game/GameActionUtil.java index 28b6a51e0f3..68c756c804d 100644 --- a/forge-game/src/main/java/forge/game/GameActionUtil.java +++ b/forge-game/src/main/java/forge/game/GameActionUtil.java @@ -586,14 +586,8 @@ public final class GameActionUtil { // Mark SAs with subAbilities as undoable. These are generally things like damage, and other stuff // that's hard to track and remove sa.setUndoable(false); - } else { - try { - if ((sa.getParam("Amount") != null) && (amount != Integer.parseInt(sa.getParam("Amount")))) { - sa.setUndoable(false); - } - } catch (final NumberFormatException n) { - sa.setUndoable(false); - } + } else if ((sa.getParam("Amount") != null) && (amount != AbilityUtils.calculateAmount(sa.getHostCard(),sa.getParam("Amount"), sa))) { + sa.setUndoable(false); } final StringBuilder sb = new StringBuilder(); diff --git a/forge-game/src/main/java/forge/game/ability/effects/ManaReflectedEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ManaReflectedEffect.java index 3d19c777592..c5867722a2c 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ManaReflectedEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ManaReflectedEffect.java @@ -13,6 +13,8 @@ import forge.util.Localizer; import java.util.Collection; import java.util.List; +import org.apache.commons.lang3.StringUtils; + public class ManaReflectedEffect extends SpellAbilityEffect { /* (non-Javadoc) @@ -98,12 +100,12 @@ public class ManaReflectedEffect extends SpellAbilityEffect { if (amount == 0) { sb.append("0"); } else { - try { + if (StringUtils.isNumeric(baseMana)) { // if baseMana is an integer(colorless), just multiply amount // and baseMana final int base = Integer.parseInt(baseMana); sb.append(base * amount); - } catch (final NumberFormatException e) { + } else { for (int i = 0; i < amount; i++) { if (i != 0) { sb.append(" "); diff --git a/forge-game/src/main/java/forge/game/ability/effects/RepeatEffect.java b/forge-game/src/main/java/forge/game/ability/effects/RepeatEffect.java index e22f817af6e..eaed68ffe73 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/RepeatEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/RepeatEffect.java @@ -5,7 +5,6 @@ import forge.game.ability.AbilityUtils; import forge.game.ability.SpellAbilityEffect; import forge.game.card.Card; import forge.game.card.CardCollectionView; -import forge.game.card.CardFactoryUtil; import forge.game.card.CardLists; import forge.game.player.Player; import forge.game.spellability.AbilitySub; @@ -94,15 +93,8 @@ public class RepeatEffect extends SpellAbilityEffect { } list = CardLists.getValidCards(list, repeatPresent.split(","), sa.getActivatingPlayer(), sa.getHostCard(), sa); - int right; final String rightString = repeatCompare.substring(2); - try { // If this is an Integer, just parse it - right = Integer.parseInt(rightString); - } catch (final NumberFormatException e) { // Otherwise, grab it from - // the - // SVar - right = CardFactoryUtil.xCount(sa.getHostCard(), sa.getHostCard().getSVar(rightString)); - } + int right = AbilityUtils.calculateAmount(sa.getHostCard(), rightString, sa); final int left = list.size(); diff --git a/forge-game/src/main/java/forge/game/card/CardProperty.java b/forge-game/src/main/java/forge/game/card/CardProperty.java index 5d970215584..04000e8f769 100644 --- a/forge-game/src/main/java/forge/game/card/CardProperty.java +++ b/forge-game/src/main/java/forge/game/card/CardProperty.java @@ -1413,11 +1413,7 @@ public class CardProperty { rhs = property.substring(10); y = card.getNetPower() + card.getNetToughness(); } - try { - x = Integer.parseInt(rhs); - } catch (final NumberFormatException e) { - x = AbilityUtils.calculateAmount(source, rhs, spellAbility); - } + x = AbilityUtils.calculateAmount(source, rhs, spellAbility); if (!Expressions.compare(y, property, x)) { return false; @@ -1443,16 +1439,11 @@ public class CardProperty { // TODO get a working regex out of this pattern so the amount of // digits doesn't matter - int number; final String[] splitProperty = property.split("_"); final String strNum = splitProperty[1].substring(2); final String comparator = splitProperty[1].substring(0, 2); String counterType; - try { - number = Integer.parseInt(strNum); - } catch (final NumberFormatException e) { - number = CardFactoryUtil.xCount(source, source.getSVar(strNum)); - } + int number = AbilityUtils.calculateAmount(source, strNum, spellAbility); counterType = splitProperty[2]; final int actualnumber = card.getCounters(CounterType.getType(counterType)); diff --git a/forge-game/src/main/java/forge/game/replacement/ReplaceDamage.java b/forge-game/src/main/java/forge/game/replacement/ReplaceDamage.java index 2d8681ef508..f6eaa9325fe 100644 --- a/forge-game/src/main/java/forge/game/replacement/ReplaceDamage.java +++ b/forge-game/src/main/java/forge/game/replacement/ReplaceDamage.java @@ -20,7 +20,6 @@ package forge.game.replacement; import forge.game.ability.AbilityKey; import forge.game.ability.AbilityUtils; import forge.game.card.Card; -import forge.game.card.CardFactoryUtil; import forge.game.player.Player; import forge.game.spellability.SpellAbility; import forge.util.Expressions; @@ -97,12 +96,7 @@ public class ReplaceDamage extends ReplacementEffect { String full = getParam("DamageAmount"); String operator = full.substring(0, 2); String operand = full.substring(2); - int intoperand = 0; - try { - intoperand = Integer.parseInt(operand); - } catch (NumberFormatException e) { - intoperand = CardFactoryUtil.xCount(getHostCard(), getHostCard().getSVar(operand)); - } + int intoperand = AbilityUtils.calculateAmount(getHostCard(), operand, this); if (!Expressions.compare((Integer) runParams.get(AbilityKey.DamageAmount), operator, intoperand)) { return false; diff --git a/forge-game/src/main/java/forge/game/replacement/ReplaceProduceMana.java b/forge-game/src/main/java/forge/game/replacement/ReplaceProduceMana.java index 5eb37bf753c..5c95623af22 100644 --- a/forge-game/src/main/java/forge/game/replacement/ReplaceProduceMana.java +++ b/forge-game/src/main/java/forge/game/replacement/ReplaceProduceMana.java @@ -1,8 +1,8 @@ package forge.game.replacement; import forge.game.ability.AbilityKey; +import forge.game.ability.AbilityUtils; import forge.game.card.Card; -import forge.game.card.CardFactoryUtil; import forge.game.spellability.SpellAbility; import forge.util.Expressions; @@ -43,12 +43,7 @@ public class ReplaceProduceMana extends ReplacementEffect { String full = getParam("ManaAmount"); String operator = full.substring(0, 2); String operand = full.substring(2); - int intoperand = 0; - try { - intoperand = Integer.parseInt(operand); - } catch (NumberFormatException e) { - intoperand = CardFactoryUtil.xCount(getHostCard(), getHostCard().getSVar(operand)); - } + int intoperand = AbilityUtils.calculateAmount(getHostCard(), operand, this); int manaAmount = StringUtils.countMatches((String) runParams.get(AbilityKey.Mana), " ") + 1; if (!Expressions.compare(manaAmount, operator, intoperand)) { return false; diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbilityCondition.java b/forge-game/src/main/java/forge/game/spellability/SpellAbilityCondition.java index 1653c2066ca..219aceed181 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbilityCondition.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbilityCondition.java @@ -347,15 +347,8 @@ public class SpellAbilityCondition extends SpellAbilityVariables { list = CardLists.getValidCards(list, this.getIsPresent().split(","), sa.getActivatingPlayer(), sa.getHostCard(), sa); - int right; final String rightString = this.getPresentCompare().substring(2); - try { // If this is an Integer, just parse it - right = Integer.parseInt(rightString); - } catch (final NumberFormatException e) { // Otherwise, grab it from - // the - // SVar - right = CardFactoryUtil.xCount(host, host.getSVar(rightString)); - } + int right = AbilityUtils.calculateAmount(host, rightString, sa); final int left = list.size(); diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbilityStackInstance.java b/forge-game/src/main/java/forge/game/spellability/SpellAbilityStackInstance.java index 6a0b8b90de9..f0fe4a740b4 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbilityStackInstance.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbilityStackInstance.java @@ -194,7 +194,6 @@ public class SpellAbilityStackInstance implements IIdentifiable, IHasCardView { // Saved sub-SA needs to be reset on the way out if (subInstance != null) { ability.setSubAbility((AbilitySub) subInstance.getSpellAbility(true)); - ability.getSubAbility().setParent(ability); } // Set Cost specific things here diff --git a/forge-game/src/main/java/forge/game/trigger/Trigger.java b/forge-game/src/main/java/forge/game/trigger/Trigger.java index 03b98fc793a..2f39ff3b0e5 100644 --- a/forge-game/src/main/java/forge/game/trigger/Trigger.java +++ b/forge-game/src/main/java/forge/game/trigger/Trigger.java @@ -536,10 +536,10 @@ public abstract class Trigger extends TriggerReplacementBase { } super.changeText(); - ensureAbility(); + SpellAbility sa = ensureAbility(); - if (getOverridingAbility() != null) { - getOverridingAbility().changeText(); + if (sa != null) { + sa.changeText(); } } @@ -553,14 +553,14 @@ public abstract class Trigger extends TriggerReplacementBase { } super.changeTextIntrinsic(colorMap, typeMap); - ensureAbility(); + SpellAbility sa = ensureAbility(); - if (getOverridingAbility() != null) { - getOverridingAbility().changeTextIntrinsic(colorMap, typeMap); + if (sa != null) { + sa.changeTextIntrinsic(colorMap, typeMap); } } - private SpellAbility ensureAbility() { + public SpellAbility ensureAbility() { SpellAbility sa = getOverridingAbility(); if (sa == null && hasParam("Execute")) { sa = AbilityFactory.getAbility(getHostCard(), getParam("Execute")); diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerChangesZone.java b/forge-game/src/main/java/forge/game/trigger/TriggerChangesZone.java index 23b60327858..9a05067dcba 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerChangesZone.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerChangesZone.java @@ -148,17 +148,11 @@ public class TriggerChangesZone extends Trigger { return false; } - final Card card; - final int rightSide; - try { - card = (Card) runParams.get(AbilityKey.Card); - rightSide = Integer.parseInt(cond.substring(2)); - } catch (NumberFormatException | ClassCastException e) { - return false; - } + final Card card = (Card) runParams.get(AbilityKey.Card); if (card == null) { return false; } + final int rightSide = AbilityUtils.calculateAmount(getHostCard(), cond.substring(2), this); // need to check the ChangeZone LKI copy for damage, otherwise it'll return 0 for a new object in the new zone Card lkiCard = card.getGame().getChangeZoneLKIInfo(card);