Advanced Dice Formula
There are some advanced features that The Dicenomicon supports to make it even more powerful and useful. These include:
- Strings
- Lists
- Functions
- Conditional statements
- Roll References
- Parameters
- Local Variables
Strings
Besides being able to add/subtract/etc... numbers, The Dicenomicon can also work with (textual) string values. To add a string to a formula, tap on the “” key (opt-% in the numbers
keyboard). This will add an empty string - double tap on it to edit the value. Strings can be mixed with other values - by using the "+" operator, two strings will be concatenated together
(with a space between them). The "-" operator will concatenate them without the space. If one value is a string and the other isn't, it will be converted to a string - this is important because:
“Total =” + d6 + 1
won't work the way you'd expect it to, since it will first combine the string with the result of the d6 (via concatenation) and the result will be a string which will then get concatenated with the 1, resulting
in something like "Total = 4 1" instead of "Total = 5". So use parenthesis as needed:
“Total =” + (d6 + 1)
One other string operator is the "%" operator which is used to format a list. For example:
“Total = %1 (%2)” % (d6 + 1, d8 + 2)
will produce something like "Total = 5 (7)". Basically, any "%" found inside the string is used to get a value from the list and insert it in that particular place in the result. If there is no number after the "%"
it will take the next value. Use "%%" to insert a "%" into the resulting string.
Lists
One of the most powerful capabilities of The Dicenomicon is the ability to work with lists of values (and then have things apply to these values in parallel). A list is just a series of values separated by commas, but treated
as if it were a single value. All the basic operators can then be applied to the list:
(1, 2, 3) + (4, 5)
evaluates as "(5,7,3)" (values that don't exists in both lists just use the one list they do exist in). One important thing that lists can be used for is to example individual elements of a dice roll via the "@"
modifier (so "3d6@" is equivalent to "(d6, d6, d6)").
One of the interesting properities of lists is that they can contain either numeric values or string values - but not other lists. A list of lists is automatically "flattened" to a single list, so:
(1, (2, 3),((4, 5), 6))
is the same as "(1, 2, 3, 4, 5, 6)". This is extra important for the "subscript" (list element access) operator "[]" - so "(1,(2,3))[2]" is "2", not "(2,3)".
But what use are these lists? There are times you need to manipulate a bunch of values (such as individual die rolls) and expanding it manually would be difficult if not impossible (especially if it is a parameterized roll - see below).
So while it is easy to total the 3 highest of 4 six sided dice, what if you wanted display 3 highest of 2 six sided and 3 eight sided dice? One can use the "high#" formula (see below) with a list of values:
high3(2d6@,3d8@)
(or "sum(high3(2d6@,3d8@))" if you wanted their total)
Another important use for lists is to make simple tables. For example, you may have a "hit location" based on a d6. You can implement that via:
(“Head”, “Body”, “Left Arm”,
“Right Arm”, “Left Leg”,
“Right Leg”)[d6]
Note that the subscript can be a list, in which case it produces a list of those elements at those indices. So to simulate a d6 that
was labelled 1,1,1,2,2,3 and roll 5 of them you can do:
sum((1,1,1,2,2,3)[5d6@])
Functions
There are a wide range of built in functions that operate on lists. They are found by tapping on the "f(" key (alt "("). Double tapping on the formula will show the formula picker, with the large list of
functions. All functions operate on a list, and produce either a single value, or another list. Many functions also include a special constant values (for example "sum()" totals all the values to produce a single value
while "high#()" includes a constant value to indicate how many of the highest values of the list to return as a new list - simply typing the number while the formula token is highlighted will change it, just
like it does for things like target numbers in dice specifications). The full list of functions are:
- sum
- Returns the sum of all the elements
- sort
- Returns a list of all the elements, sorted lowest to highest
- reverse
- Returns a list of all the elements in opposite order
- rsort
- A combination of sort() and reverse(), returning a list of all elements sorted from highest to lowers
- sign
- Returnes a list of the sign of all the elemenets (all values less than zero become -1, values equal to zero become 0, and values greater than zero become 1)
- list
- Returns the original list of parameters (useful for making explicit lists)
- length
- Returns how many elements are in the list
- high#
- Returns a list of the N highest elements of the list
- low#
- Returns a list of the N lowest elements of the list
- first#
- Returns a list of the first N elements of the list
- last#
- Returns a list of the last N elements of the list
- ne#, eq#, lt#, gt#, le#, ge#
- Returns a list of the elements that are not equal to, equal to, less than, greater than, less than or equal to, or greater than or equal to, a given constant N.
- count#
- Returns how many elements in the list are equal to the constant values. Equivalent to "length(eq#(...))"
- max#
- Returns a list composed of the original elements, maxed out at the given constant. So "max4(1,6)" = "(1,4)"
- min#
- Returns a list composed of the original elements, limited at the given constant. So "min4(1,6)" = "(4,6)"
- anyof
- If any of the elements in the list are greater than zero (i.e., "true"), returns 1, otherwise returns 0.
- allof
- If all of the elements in the list are greater than zero (i.e., "true"), returns 1, otherwise returns 0.
- match
- Returns a list with two elements. All elements in the list are compared to each other, and all the "matches" are found. The first element is highest match, and the second element is how many elements matched that value.
- string
- Converts the list to a comma separated string
Conditionals
One imporant feature of formulas is to be able to evalate the result based on some condition. For example, if you roll a 17 or better, then you may want the formula to print out "Hit" otherwise "Miss".
To do this, one uses the "if" expression:
if d20 > 17 then
“Hit for” + d6 + “damage”
else
“Miss”
end
One important point of conditions is that all dice in both clauses are rolled regardless of the condition (otherwise the d20 would roll, and you'd have to wait for that to finish before it either rolled
a d6 or not - which would make "Roll References" (see below) impossible to use reliably).
If expresions work with lists as well, and will result in a list where the various elements are either the true or false conditions. So if the condition above were "(d20, d20, d20)" it would produce
a list of three values (either "Hit for ..." or "Miss"). These are also expressions, so can be used anywhere an expression is used (so you can add the result of an if expression to a value).
Roll References
There are times when you want to calculate more than one thing from a given roll, or re-examine the roll more than once in the expression.
For example, suppose you wanted to have a targetted roll (disregarding existing support for them) that rolled 5d10s, vs a target of 7, treating
9s and 10s as "two hits" and 1s as misses. To do this we'd have a roll of 5d10, and then we'd look through it several ways to get the result, first by
checking those greater than or equal to 7, and then adding in again the 9s and 10, and then subtracting the 1s. If you did:
5d10≥7 + 5d10≥9 - 5d10=1
it would roll 15 dice - not at all what you want. Instead, using the "$" die we can refer to a previous die roll:
5d10≥7 + $1≥9 - $1=1
The "$1" part refers to the first roll (NB: this factors in things such as open rolls, but you can change any modifiers, as seen above).
If we wanted to change it to only do the "botch" if no target rolls were made, we'd combine an if expression (in this case looking to see if
any hits were made, and if so, don't subtract anything):
5d10≥7 + $1≥9 - if $1≥7 then
0
else
$1=1
end
Parameters
All these expression capabilities, but going in an editing them to change "roll 4" to "roll 5" every time is a major pain. It would be
nice if there were some way to ask for these values when they were rolled, instead of having to edit them. With The Dicenomicon, values
like this can be "parameterized". Basically any constant value (excluding the number of sides on dice) can be marked as a parameter instead.
There are up to 4 parameters that can be used in a formula (#1, #2, #3, #4 - found by tapping the "alt" key on the numbers keyboard).
Once specified, double-tapping on the token will present a form to provide the prompt, default value for the parameter, and if the parameter
is positive, signed (positive or negative), or has an optional "half" value (used primarily in Champions).
So taking the example in Roll References, we can parameterize out the number of dice, target number, and bonus hit values:
#1d10≥#2 + $1≥#3 - if $1≥#2 then
0
else
$1=1
end
Parameter #1 would be the number of dice, #2 would be the target number, and #3 would be the bonus hit values. Then when this formula was
chosen, a form would be presented that can be used to quickly set the values.
Local Values
One last important feature is the ability to calculate a value and reuse it later - The Dicenomicon provides local variables (@1 .. @6) for
just this purpose. So suppose we want to resolve combat using a hit target and a hit bonus (with a natural 20 being a critical hit, and 1 being a botch):
@1 ← d20 + #2.
if $1 == 20 then
“Critical!”
else
if $1 = 1 then
“Botch!“
else
if @1 ≥ #1 then
“Hit!”
else
“Miss by ” + (#1 - @1)
end
end
end
We'll assume that #1 is the parameterized "to hit" value, #2 is the to hit bonus. Notice that we used the roll reference $1 to check for "natural" 20s and 1s
since the local variable included the bonus (so we had to look at the original roll value).