mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 12:48:00 +00:00
cleanup of AbilityUtils.calculateAmount - if amount is pure integer, it's returned right away (that means no svars may be named after valid numbers)
former parseMath renamed and no longer returns an array of one string (just return the string)
This commit is contained in:
@@ -290,59 +290,69 @@ public class AbilityUtils {
|
||||
* @return a int.
|
||||
*/
|
||||
public static int calculateAmount(final Card card, String amount, final SpellAbility ability) {
|
||||
// amount can be anything, not just 'X' as long as sVar exists
|
||||
// return empty strings and constants
|
||||
if (StringUtils.isBlank(amount)) return 0;
|
||||
if (StringUtils.isNumeric(amount)) return Integer.parseInt(amount);
|
||||
|
||||
if (amount == null || amount.isEmpty()) {
|
||||
// Strip and save sign for calculations
|
||||
boolean startsWithPlus = amount.charAt(0) == '+';
|
||||
boolean startsWithMinus = amount.charAt(0) == '-';
|
||||
int multiplier = startsWithMinus ? -1 : 1;
|
||||
if(startsWithMinus || startsWithPlus )
|
||||
amount = amount.substring(1);
|
||||
|
||||
// These are some special cases - who is implementing them?
|
||||
if (amount.equals("ChosenX") || amount.equals("ChosenY")) {
|
||||
// isn't made yet
|
||||
return 0;
|
||||
}
|
||||
// cost hasn't been paid yet
|
||||
if (amount.startsWith("Cost")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If Amount is -X, strip the minus sign before looking for an SVar of
|
||||
// that kind
|
||||
int multiplier = 1;
|
||||
if (amount.startsWith("-")) {
|
||||
multiplier = -1;
|
||||
amount = amount.substring(1);
|
||||
} else if (amount.startsWith("+")) {
|
||||
amount = amount.substring(1);
|
||||
}
|
||||
|
||||
String svarval;
|
||||
// Try to fetch variable, try ability first, then card.
|
||||
String svarval = null;
|
||||
if (ability != null) {
|
||||
|
||||
svarval = ability.getSVar(amount);
|
||||
if (svarval.equals("")) {
|
||||
try {
|
||||
Integer.parseInt(amount);
|
||||
}
|
||||
catch (NumberFormatException ignored) {
|
||||
//If this is reached, amount wasn't an integer
|
||||
//Print a warning to console to help debug if an ability is not stolen properly.
|
||||
StringBuilder sb = new StringBuilder("WARNING:SVar fallback to Card (");
|
||||
sb.append(card.getName()).append(") and Ability(").append(ability.toString()).append(")");
|
||||
System.out.println(sb.toString());
|
||||
svarval = card.getSVar(amount);
|
||||
if (StringUtils.isBlank(svarval)) {
|
||||
if( ability != null) {
|
||||
System.err.printf("SVar '%s' not found in ability, fallback to Card (%s). Ability is (%s)%n", amount, card.getName(), ability);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
svarval = card.getSVar(amount);
|
||||
}
|
||||
|
||||
if (!svarval.equals("")) {
|
||||
final String[] calcX = svarval.split("\\$");
|
||||
if ((calcX.length == 1) || calcX[1].equals("none")) {
|
||||
// Nothing to do here if value is missing or blank
|
||||
if (StringUtils.isBlank(svarval)) {
|
||||
System.err.printf("SVar '%s' not defined in Card (%s)%n", amount, card.getName());
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (calcX[0].startsWith("Count")) {
|
||||
// Handle numeric constant coming in svar value
|
||||
if( StringUtils.isNumeric(svarval) )
|
||||
return multiplier * Integer.parseInt(svarval);
|
||||
|
||||
// Parse Object$Property string
|
||||
final String[] calcX = svarval.split("\\$");
|
||||
|
||||
// Incorrect parses mean zero.
|
||||
if ((calcX.length == 1) || calcX[1].equals("none"))
|
||||
return 0;
|
||||
|
||||
if (calcX[0].startsWith("Count"))
|
||||
return AbilityUtils.xCount(card, calcX[1], ability) * multiplier;
|
||||
} else if (calcX[0].startsWith("Number")) {
|
||||
|
||||
if (calcX[0].startsWith("Number"))
|
||||
return CardFactoryUtil.xCount(card, svarval) * multiplier;
|
||||
} else if (calcX[0].startsWith("SVar")) {
|
||||
|
||||
if (calcX[0].startsWith("SVar")) {
|
||||
final String[] l = calcX[1].split("/");
|
||||
final String[] m = CardFactoryUtil.parseMath(l);
|
||||
return CardFactoryUtil.doXMath(AbilityUtils.calculateAmount(card, l[0], ability), m, card)
|
||||
* multiplier;
|
||||
} else if (calcX[0].startsWith("PlayerCount")) {
|
||||
final String m = CardFactoryUtil.extractOperators(calcX[1]);
|
||||
return CardFactoryUtil.doXMath(AbilityUtils.calculateAmount(card, l[0], ability), m, card) * multiplier;
|
||||
}
|
||||
|
||||
if (calcX[0].startsWith("PlayerCount")) {
|
||||
final String hType = calcX[0].substring(11);
|
||||
final ArrayList<Player> players = new ArrayList<Player>();
|
||||
if (hType.equals("Players") || hType.equals("")) {
|
||||
@@ -366,7 +376,10 @@ public class AbilityUtils {
|
||||
players.remove(Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn());
|
||||
return CardFactoryUtil.playerXCount(players, calcX[1], card) * multiplier;
|
||||
}
|
||||
} else if (calcX[0].startsWith("Remembered")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (calcX[0].startsWith("Remembered")) {
|
||||
// Add whole Remembered list to handlePaid
|
||||
final List<Card> list = new ArrayList<Card>();
|
||||
if (card.getRemembered().isEmpty()) {
|
||||
@@ -393,7 +406,9 @@ public class AbilityUtils {
|
||||
}
|
||||
|
||||
return CardFactoryUtil.handlePaid(list, calcX[1], card) * multiplier;
|
||||
} else if (calcX[0].startsWith("Imprinted")) {
|
||||
}
|
||||
|
||||
if (calcX[0].startsWith("Imprinted")) {
|
||||
// Add whole Imprinted list to handlePaid
|
||||
final List<Card> list = new ArrayList<Card>();
|
||||
for (final Card c : card.getImprinted()) {
|
||||
@@ -401,7 +416,9 @@ public class AbilityUtils {
|
||||
}
|
||||
|
||||
return CardFactoryUtil.handlePaid(list, calcX[1], card) * multiplier;
|
||||
} else if (calcX[0].matches("Enchanted")) {
|
||||
}
|
||||
|
||||
if (calcX[0].matches("Enchanted")) {
|
||||
// Add whole Enchanted list to handlePaid
|
||||
final List<Card> list = new ArrayList<Card>();
|
||||
if (card.isEnchanting()) {
|
||||
@@ -411,7 +428,11 @@ public class AbilityUtils {
|
||||
}
|
||||
}
|
||||
return CardFactoryUtil.handlePaid(list, calcX[1], card) * multiplier;
|
||||
} else if (ability != null) {
|
||||
}
|
||||
|
||||
if (ability == null)
|
||||
return 0;
|
||||
|
||||
// Player attribute counting
|
||||
if (calcX[0].startsWith("TargetedPlayer")) {
|
||||
final ArrayList<Player> players = new ArrayList<Player>();
|
||||
@@ -506,7 +527,7 @@ public class AbilityUtils {
|
||||
// pulls Integer Values from Trigger objects
|
||||
final SpellAbility root = ability.getRootAbility();
|
||||
final String[] l = calcX[1].split("/");
|
||||
final String[] m = CardFactoryUtil.parseMath(l);
|
||||
final String m = CardFactoryUtil.extractOperators(calcX[1]);
|
||||
final int count = (Integer) root.getTriggeringObject(l[0]);
|
||||
|
||||
return CardFactoryUtil.doXMath(count, m, card) * multiplier;
|
||||
@@ -519,31 +540,15 @@ public class AbilityUtils {
|
||||
// pulls Integer Values from Replacement objects
|
||||
final SpellAbility root = ability.getRootAbility();
|
||||
final String[] l = calcX[1].split("/");
|
||||
final String[] m = CardFactoryUtil.parseMath(l);
|
||||
final String m = CardFactoryUtil.extractOperators(calcX[1]);
|
||||
final int count = (Integer) root.getReplacingObject(l[0]);
|
||||
|
||||
return CardFactoryUtil.doXMath(count, m, card) * multiplier;
|
||||
} else {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return CardFactoryUtil.handlePaid(list, calcX[1], card) * multiplier;
|
||||
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (amount.equals("ChosenX") || amount.equals("ChosenY")) {
|
||||
// isn't made yet
|
||||
return 0;
|
||||
}
|
||||
// cost hasn't been paid yet
|
||||
if (amount.startsWith("Cost")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Integer.parseInt(amount) * multiplier;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1231,7 +1236,7 @@ public class AbilityUtils {
|
||||
public static int xCount(final Card c, final String s, final SpellAbility sa) {
|
||||
|
||||
final String[] l = s.split("/");
|
||||
final String[] m = CardFactoryUtil.parseMath(l);
|
||||
final String expr = CardFactoryUtil.extractOperators(s);
|
||||
|
||||
final String[] sq;
|
||||
sq = l[0].split("\\.");
|
||||
@@ -1240,9 +1245,9 @@ public class AbilityUtils {
|
||||
// Count$Kicked.<numHB>.<numNotHB>
|
||||
if (sq[0].startsWith("Kicked")) {
|
||||
if (sa.isKicked()) {
|
||||
return CardFactoryUtil.doXMath(Integer.parseInt(sq[1]), m, c); // Kicked
|
||||
return CardFactoryUtil.doXMath(Integer.parseInt(sq[1]), expr, c); // Kicked
|
||||
} else {
|
||||
return CardFactoryUtil.doXMath(Integer.parseInt(sq[2]), m, c); // not Kicked
|
||||
return CardFactoryUtil.doXMath(Integer.parseInt(sq[2]), expr, c); // not Kicked
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1252,9 +1257,9 @@ public class AbilityUtils {
|
||||
final int lhs = calculateAmount(c, compString[1], sa);
|
||||
final int rhs = calculateAmount(c, compString[2].substring(2), sa);
|
||||
if (Expressions.compare(lhs, compString[2], rhs)) {
|
||||
return CardFactoryUtil.doXMath(Integer.parseInt(sq[1]), m, c);
|
||||
return CardFactoryUtil.doXMath(Integer.parseInt(sq[1]), expr, c);
|
||||
} else {
|
||||
return CardFactoryUtil.doXMath(Integer.parseInt(sq[2]), m, c);
|
||||
return CardFactoryUtil.doXMath(Integer.parseInt(sq[2]), expr, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -866,13 +866,9 @@ public class CardFactoryUtil {
|
||||
* an array of {@link java.lang.String} objects.
|
||||
* @return an array of {@link java.lang.String} objects.
|
||||
*/
|
||||
public static String[] parseMath(final String[] l) {
|
||||
final String[] m = { "none" };
|
||||
if (l.length > 1) {
|
||||
m[0] = l[1];
|
||||
}
|
||||
|
||||
return m;
|
||||
public static String extractOperators(final String expression) {
|
||||
String[] l = expression.split("/");
|
||||
return l.length > 1 ? l[1] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -889,20 +885,12 @@ public class CardFactoryUtil {
|
||||
* @return a int.
|
||||
*/
|
||||
public static int objectXCount(final ArrayList<Object> objects, final String s, final Card source) {
|
||||
if (objects.size() == 0) {
|
||||
if (objects.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
final String[] l = s.split("/");
|
||||
final String[] m = CardFactoryUtil.parseMath(l);
|
||||
|
||||
int n = 0;
|
||||
|
||||
if (s.startsWith("Amount")) {
|
||||
n = objects.size();
|
||||
}
|
||||
|
||||
return CardFactoryUtil.doXMath(n, m, source);
|
||||
int n = s.startsWith("Amount") ? objects.size() : 0;
|
||||
return CardFactoryUtil.doXMath(n, CardFactoryUtil.extractOperators(s), source);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -924,7 +912,7 @@ public class CardFactoryUtil {
|
||||
}
|
||||
|
||||
final String[] l = s.split("/");
|
||||
final String[] m = CardFactoryUtil.parseMath(l);
|
||||
final String m = CardFactoryUtil.extractOperators(s);
|
||||
|
||||
int n = 0;
|
||||
|
||||
@@ -1115,19 +1103,19 @@ public class CardFactoryUtil {
|
||||
*
|
||||
* @param c
|
||||
* a {@link forge.Card} object.
|
||||
* @param s
|
||||
* @param expression
|
||||
* a {@link java.lang.String} object.
|
||||
* @return a int.
|
||||
*/
|
||||
public static int xCount(final Card c, final String s) {
|
||||
public static int xCount(final Card c, final String expression) {
|
||||
int n = 0;
|
||||
|
||||
final Player cardController = c.getController();
|
||||
final Player oppController = cardController.getOpponent();
|
||||
final Player activePlayer = Singletons.getModel().getGame().getPhaseHandler().getPlayerTurn();
|
||||
|
||||
final String[] l = s.split("/");
|
||||
final String[] m = CardFactoryUtil.parseMath(l);
|
||||
final String[] l = expression.split("/");
|
||||
final String m = CardFactoryUtil.extractOperators(expression);
|
||||
|
||||
// accept straight numbers
|
||||
if (l[0].startsWith("Number$")) {
|
||||
@@ -2028,12 +2016,12 @@ public class CardFactoryUtil {
|
||||
return CardFactoryUtil.doXMath(n, m, c);
|
||||
}
|
||||
|
||||
private static int doXMath(final int num, final String m, final Card c) {
|
||||
if (m.equals("none")) {
|
||||
public static int doXMath(final int num, final String operators, final Card c) {
|
||||
if (operators == null || operators.equals("none")) {
|
||||
return num;
|
||||
}
|
||||
|
||||
final String[] s = m.split("\\.");
|
||||
final String[] s = operators.split("\\.");
|
||||
int secondaryNum = 0;
|
||||
|
||||
try {
|
||||
@@ -2092,27 +2080,6 @@ public class CardFactoryUtil {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* doXMath.
|
||||
* </p>
|
||||
*
|
||||
* @param num
|
||||
* a int.
|
||||
* @param m
|
||||
* an array of {@link java.lang.String} objects.
|
||||
* @param c
|
||||
* a {@link forge.Card} object.
|
||||
* @return a int.
|
||||
*/
|
||||
public static int doXMath(final int num, final String[] m, final Card c) {
|
||||
if (m.length == 0) {
|
||||
return num;
|
||||
}
|
||||
|
||||
return CardFactoryUtil.doXMath(num, m[0], c);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* handlePaid.
|
||||
@@ -2145,17 +2112,9 @@ public class CardFactoryUtil {
|
||||
|
||||
}
|
||||
if (string.startsWith("Valid")) {
|
||||
final String[] m = { "none" };
|
||||
|
||||
String valid = string.substring(6);
|
||||
final String[] l;
|
||||
l = valid.split("/"); // separate the specification from any math
|
||||
valid = l[0];
|
||||
if (l.length > 1) {
|
||||
m[0] = l[1];
|
||||
}
|
||||
final List<Card> list = CardLists.getValidCards(paidList, valid, source.getController(), source);
|
||||
return CardFactoryUtil.doXMath(list.size(), m, source);
|
||||
return CardFactoryUtil.doXMath(list.size(), CardFactoryUtil.extractOperators(valid), source);
|
||||
}
|
||||
|
||||
int tot = 0;
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
package forge.card.cost;
|
||||
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import forge.Card;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.game.GameState;
|
||||
@@ -120,12 +122,7 @@ public abstract class CostPart {
|
||||
* @return the integer
|
||||
*/
|
||||
public final Integer convertAmount() {
|
||||
Integer i = null;
|
||||
try {
|
||||
i = Integer.parseInt(this.getAmount());
|
||||
} catch (final NumberFormatException e) {
|
||||
}
|
||||
return i;
|
||||
return StringUtils.isNumeric(amount) ? Integer.parseInt(amount) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -209,7 +209,7 @@ public class CostPartMana extends CostPart {
|
||||
// if X cost is a defined value, other than xPaid
|
||||
if (!ability.getSVar("X").equals("Count$xPaid")) {
|
||||
// this currently only works for things about Targeted object
|
||||
manaToAdd = AbilityUtils.calculateAmount(source, "X", ability) * this.getAmountOfX();
|
||||
manaToAdd += AbilityUtils.calculateAmount(source, "X", ability) * this.getAmountOfX();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,16 +221,15 @@ public class CostPartMana extends CostPart {
|
||||
return false;
|
||||
}
|
||||
if (this.getAmountOfX() > 0) {
|
||||
if( !"X".equals(ability.getParam("Announce")) ) {
|
||||
if( !ability.isAnnouncing("X") ) {
|
||||
source.setXManaCostPaid(0);
|
||||
InputPayment inpPayment = new InputPayManaX(ability, this.getAmountOfX(), this.canXbe0());
|
||||
FThreads.setInputAndWait(inpPayment);
|
||||
if(!inpPayment.isPaid())
|
||||
return false;
|
||||
} else {
|
||||
String xVar = ability.getSVar("X");
|
||||
String xVal = xVar.split("\\$")[1];
|
||||
source.setXManaCostPaid(Integer.parseInt(xVal));
|
||||
int x = AbilityUtils.calculateAmount(source, ability.getSVar("X"), ability);
|
||||
source.setXManaCostPaid(x);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -158,8 +158,8 @@ public class HumanPlaySpellAbility {
|
||||
Integer value = ability.getActivatingPlayer().getController().announceRequirements(ability, aVar, ability.getPayCosts().getCostMana().canXbe0());
|
||||
if ( null == value )
|
||||
return false;
|
||||
ability.setSVar(aVar, "Number$" + value);
|
||||
ability.getSourceCard().setSVar(aVar, "Number$" + value);
|
||||
ability.setSVar(aVar, value.toString());
|
||||
ability.getSourceCard().setSVar(aVar, value.toString());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -23,6 +23,8 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import forge.Card;
|
||||
import forge.GameEntity;
|
||||
import forge.Singletons;
|
||||
@@ -35,6 +37,7 @@ import forge.card.mana.Mana;
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.game.player.AIPlayer;
|
||||
import forge.game.player.Player;
|
||||
import forge.util.TextUtil;
|
||||
|
||||
//only SpellAbility can go on the stack
|
||||
//override any methods as needed
|
||||
@@ -1741,4 +1744,18 @@ public abstract class SpellAbility implements ISpellAbility {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether variable was present in the announce list.
|
||||
*/
|
||||
public boolean isAnnouncing(String variable) {
|
||||
String announce = getParam("Announce");
|
||||
if (StringUtils.isBlank(announce)) return false;
|
||||
String[] announcedOnes = TextUtil.split(announce, ',');
|
||||
for(String a : announcedOnes) {
|
||||
if( a.trim().equalsIgnoreCase(variable))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,7 +281,7 @@ public class Target {
|
||||
*
|
||||
* @return the max targets
|
||||
*/
|
||||
public final String getMaxTargets() {
|
||||
private final String getMaxTargets() {
|
||||
return this.maxTargets;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user