# Math Operators and Formulas

Important: Starting with version 5.7.1 PCGen has incorporated the JEP (Java Mathematical Expression Parser) library. This was done because the original code which has evolved over time is problematic due to its complexity and lack of documentation. The JEP library has a clearly defined grammar which is available on the web site. JEP supports user defined variables, constants, and functions. A number of common mathematical functions and constants are included. As a fall back, if the JEP parser fails to parse the function then the old code is called. At some point in the future the old code support will be dropped and all formulas must be in JEP syntax.

The library we are using to parse math expressions defines the syntax they want to test for string equality. If you are curious you can check out the JEP library at http://www.singularsys.com/jep/

To reverse the sign (go from positive number to negative) use -1*(). EXAMPLE:
BONUS:CHECKS|BASE.Will|CL/3 is a positive 1 at 3rd level and
BONUS:CHECKS|BASE.Will|-1*(CL/3) is a -1 at 3rd level.

PCGen *does* round each tag down rather than add the tags together and then round down. See example before 'Operators'

Using variables within JEP expressions

In most cases variables can be used directly in an expression, however there are some cases when you must use the var() function. This is because some variables can contain characters which are not valid JEP variables. For example the variable CL can be used in a formula without a problem but the variable CL=Fighter cannot be used because of the "=" symbol. In these cases you must use var("CL=Fighter") in the formula for it to parse correctly. The formal description of a JEP variable is "a letter followed by one or more letters and digits" where a letter is defined as: '$', '_', a-z and A-Z.

Examples of variables that may be used alone:

`CL, TL, ARMORACCHECK, BardicKnowledgeLevel, TirelessRage.`

Examples of variables that must be called with the getvar() function:

`var("CL=Fighter"), var("COUNT[FEATS]"), var("COUNT[FEATTYPE=type]").`

Consult the DEFINE page for the list of hard coded variables available for use in formulas.

Operator order of processing:

Anything within ()'s are done first, and processing is done left-to-right.

`2+(3*5+2)/2`

Would become 2+(15+2)/2 (3*5 replaced)

then 2+17/2 (15+2 replaced)

then 19/2 (2+17 replaced)

then 9 (result of 19/2, the .5 is dropped, see below.).

PCGen truncates (or rounds down to the nearest integer) the results of each formula, so 4/3 will return a 1 and 7/3 will return a 2 etc. If you need to truncate within the formula you can use the min(x,y) or max(x,y) and floor(a) or ceil(a) tags.

Operators

`2+1`

Addition (+).

`CL-1`

Subtraction (-) - would minus one from the Class Level.

`CL/2`

Division (/) - would divide the Class Level by two.

`CL*3`

Multiplication (*) - would multiply the Class Level by three.

`((CL+1)+(3*TL)/2)/4`

Parenthesis () nesting - the result of three multiplied by Total Level divided by two, plus Class Level + 1 is divided by four.

`CL%3`

The % performs a modulus... or is the remainder operator.

`would determine the remainder after performing an integer divide on the Class Level by three. If the class level was 7, the remainder is 1 ( 7 / 3 = 2 remainder 1 ... or alternately 2 * 3 + 1 = 7)`

Minimums and maximums

The min and max functions support 2 or more arguments, so you can compare 2, 3, 4 or more numbers or variables.

`min(a,b,c)`

Returns the lowest of 'a', 'b' or 'c'.

`max(a,b,c)`

Returns the highest of 'a', 'b' or 'c'.

Truncation, rounding up and down.

`floor(a)`

Returns the highest integer that is less than 'a'.

`ceil(a)`

Returns the lowest integer that is greater than 'a'.

Boolean operators

Boolean operators are also fully supported. Boolean expressions are evaluated to be either 1 or 0 (true or false respectively).

`CL==1`

Equal (==). Asks if Class Level is equal to 1.

`CL!=1`

Not Equal (!=). Asks if Class Level is not equal to 1.

`CL>1`

Greater than (>). Asks if Class Level is greater than 1.

`CL<1`

Less than (<). Asks if Class Level is less than 1.

`CL>=1`

Greater than or Equal (>=). Asks if Class Level is greater than or equal to 1.

`CL<=1`

Less than or Equal (<=). Asks if Class Level is less than or equal to 1.

`(CL>5)&&(TL>5)`

Boolean And (&&). Asks if Class Level and Total Level are greater than 5.

`(CL>5)||(TL>5)`

Boolean Or (||). Asks if Class Level or Total Level is greater than 5.

Boolean If operator

`if(x,y,z)`

The boolean if operator will return one of two results after evaluating a boolean. The variable x is a boolean result, 0 is false and anything not 0 is true. The variable y is the result returned if x is true, z is the result returned if x is false. Put another way, if x is true (not 0) then the result is y, if x is false (0) then the result is z.

Examples:

`if(CL<10,1,2)`

Asks if Class Level is less than 10 then returns 1 or else returns 2.

`if(CL>=4,10,0)`

Asks if Class Level is greater than or equal to 4 then returns 10 or else returns 0.

`if((CL>5)||(TL>5),2,-4)`

Asks if Class Level or Total Level is greater than 5 then returns 2 or else returns -4.

`if(STR,5,0)`

Asks if Strength modifier is greater than or less than 0 then returns 5 or else returns 0.

Random Number Generation

`roll("x")`

Variables Used (x): Formula

The formula used within the roll("x") function can use all the standard JEP operators and in addition it can take a dice expression in the form of xdx, for example 2d6, 1d20 and 3d4.

Warning: although the JEP function roll("x") can generate a random number in any formula that takes JEP there are few places in the program where this is actually useful. This is because the roll function will generate a new random number every time the formula is evaluated which happens many times while you use the program. So if you were to use roll("2d6") in a base attack bonus it would appear to add a number between 2 and 12 which would change frequently. Currently the QTY tag used FUNDS lines in Kit files is one of the few places this JEP operator functions in a useful way.

Examples:

`roll("3d6")`

Simulates rolling 3 six-sided dice.

`roll("1d20+10")`

Simulates rolling a twenty-sided die and adds 10.

The following functions are also supported within the roll function:

`min(v1,v2)`

e.g. min(4,7)

`max(v1,v2)`

e.g. min(4,7)

`pow(base, exponent)`

e.g. pow(10,2) = 100

`roll(times, sides)`

e.g. roll(3,6)

`roll(times, sides, [keep])`

e.g. roll(4,6,[2,3,4]), rolls 4 six-sided dice and keeps the 3 highest rolls

`roll(times, [sides])`

e.g. roll(1,[3,5,7,9]), rolls one 3, 5, 7 or 9 sided die, randomly selected

`roll(times, [sides], [keep])`

e.g. roll(3,[2,3,4,5,6],[2,3]), rolls three 2, 3, 4, 5, or 6 sided dice, randomly selected and keeps the highest 2

These are defined in pcgen/util/DiceExpressionFunctions.java. In order to use these with JEP they must be encapsulated in a roll("x") call.

e.g. `roll("roll(4,6,[2,3,4])")`

Class Level

`cl("x")`

Variables Used (x): Text (Class Name)

This function returns the number of level the PC has in the specified class. This replaces the old variable `CL=class name`.

Examples:

`cl("Bard")`

Returns the number of levels of Bard.

Skill Information

`skillinfo("x", "y")`

Variables Used (x): RANK (Property)

Variables Used (x): TOTALRANK (Property)

Variables Used (x): MODIFIER (Property)

Variables Used (x): TOTAL (Property)

Variables Used (y): Text (Skill name)

This function returns information about the skill specified.

RANK returns the number of ranks the PC has in the skill not including those gained from BONUS:SKILLRANK tags.

TOTALRANK returns the number of ranks the PC has in the skill including those gained from BONUS:SKILLRANK tags.

MODIFIER returns the total bonuses the PC has in the skill.

TOTAL returns the grand total in the skill from all ranks and bonuses.

Examples:

`skillinfo("RANK", "Hide")`

Returns the number of base ranks in Hide.

`skillinfo("TOTALRANK", "Climb")`

Returns the number ranks in Climb including those gained from BONUS:SKILLRANK tags.

`skillinfo("MODIFIER", "Bluff")`

Returns the total number of bonuses in Bluff.

`skillinfo("TOTAL", "Spellcraft")`

Returns the grand total in Spellcraft.

Character Bonus Information

`charbonusto("parameter 1", "parameter 2")`

This function returns the value of a call to PlayerCharacter.getTotalBonusTo(p1, p2). These values reflect bonuses applied to the parameter not the full value of that parameter. Thus `charbonusto("CHECKS", "REFLEX")` will return Reflex bonuses from a high Dexterity and other bonuses but not the full reflex save value.

parameter 1 is optional. If not present, will default to "PCLEVEL".

e.g. these two are equivalent:
charbonusto("PCLEVEL", "Cleric")
charbonusto("Cleric")

`charbonusto("PCLEVEL", "<class name>")` or `charbonusto("<class name>")`

Returns the number of bonus Spellcaster Levels to the class specified, which usually come from Prestige classes.

Other parameters include:

`charbonusto("STAT", "BASESPELLSTAT")`

`charbonusto("STAT", "BASESPELLSTAT;CLASS.Wizard")`

`charbonusto("STAT", "CAST.Arcane")`

`charbonusto("FEAT", "POOL")`

`charbonusto("VAR", "marshmellow")`

`charbonusto("CHECKS", "WILL")`

`charbonusto("TOHIT", "TOHIT")`

`charbonusto("DOMAIN", "NUMBER")`

`charbonusto("CASTERLEVEL", "Wizard")`

`charbonusto("HP", "ALTHP")`

`charbonusto("COMBAT", "BAB")`

`charbonusto("WEAPONPROF=Dagger", "PCSIZE")`

`charbonusto("WEAPONPROF=TYPE.Martial", "PCSIZE")`

Count Information

`count("parameter 1", "parameter 2", ...)`

This function returns the number of objects of the requested type. It is commonly used in output sheet FOR loops as the maximum value.

parameter 1 is required. It is the type of object to be counted. Different types of objects will require different numbers of following parameters

`count("ABILITIES", "<param=value>")`

Returns the number of abiltiies meeting the critieria. Allowed parameters are CATEGORY (the name of the category of abilities to be listed), VISIBILITY (ALL, HIDDEN, VISIBILE) and NATURE (ALL, VIRTUAL, AUTO or NORMAL)

Examples:

`count("ABILITIES","CATEGORY=FEAT","VISIBILITY=VISIBLE")` List all visible feat abilities.

*** New 5.11.X

Symbols Operators

The following symbol operators are explained below.

`%CHOICE`

What it does:

The %CHOICE will put the input from a CHOOSE tag into its place, can be used in math computations.

Example:

`SPROP:Unreliable (%CHOICE) <tab> CHOOSE:5%|10%|15%|20%|25%|30%|35%|40%|45%|50%|55%|60%|65%|70%|75%|80%|85%|90%|95%|100%`

Chooser to select the level of unreliablty.

`%LIST`

What it does:

The %LIST will put the input from a CHOOSE tag into its place, can not be used in math computations.

Example:

`CHOOSE:NUMCHOICES=1|FORTITUDE|REFLEX|WILL <tab> BONUS:CHECKS|%LIST|1`

`CHOOSE:NUMCHOICES=1|FORTITUDE|REFLEX|WILL, of which the selection is put into BONUS:CHECKS|%LIST|1`

`! (Not)`

What it does:

The NOT operator.

Example:

`BONUS:SKILL|Swim|1|!PRESKILL:1,Swim=1.`

`If the character has swim, add 1 to it, if not add 1 to swim.`

`% (Replacement/Substitution)`

What it does:

The Replacement/Substitution Operator, used in the SA: tag.

See the SA:tag for more information.

Example:

`CHOOSE:Acid|Cold|Electricity|Fire <tab> SA:Resistance to % 5|LIST`

`CHOOSE:Acid|Cold|Electricity|Fire, of which the selection is put into SA:Resistance to % 5|LIST`

Deprecated operators

The following operators are deprecated as of version 5.7.1. The syntax will be replaced with JEP syntax.

`((TL/3).TRUNC)*2`

Truncation - would divide TL by 3, truncate (or round down) and then multiply by 2.

Deprecated, use floor(a).

`2MIN4`

Minimum - would return 2 since it's taking the minimum of the two values (MIN is always between the values).

Deprecated, use min(a,b).

`2MAX4`

Maximum - would return 4 since it's the max of the two values (MAX is always between the values).

Deprecated, use max(a,b).