Roll is an interactive dice language designed to help play games or to conduct experiments with probability. Roll is implemented as an interactive interpreter. Unlike most similar systems, Roll supports evaluation modes in which distributions can be computed exactly or approximated using random sampling.

The source code is available on Github.

Running Roll

The script roll runs the interpreter inside rlwrap to provide history and line editing. An initial expression or command may optionally be provided as a command-line argument, e.g.:

roll 3d6
roll load dnd.roll

If the command-line argument is an expression rather than a command, the interpreter merely prints the eval-mode result and immediately terminates without offering an interactive prompt.

The Roll language

The dice language is a functional language. Possible expressions exp include the following:

(any positive integer literal) Examples: 3, 5, 2.
(a literal bag of values) Examples: {3,4,2}, {1,2,3,4,5,6}, {}, {4}
d exp d is the most important expression in Roll.  dn means roll an n-sided die and return the result.  For example, d6 evaluates to any of the integers 1–6.  The expression after d need not be an integer, but it should evaluate to an integer; for example, d(d6) is a valid expression.  To compute this expression, the interpreter will roll a six-sided die to get a value n, then roll an n-sided die and return the result.
exp # exp # is the " repeat n times" operator. The interpreter evaluates the first expression to an integer n.  Then it evaluates the second expression n times and unions the results into a single bag of integers. For example, the expression 3#d6 rolls 3 six-sided dice and returns a bag containing the results; the expression 3#(2#d6) is equivalent to 6#d6.
exp + exp This expression acts differently depending on the results of the subexpressions.  If both of the operands are integers, it computes the sum of the two integers.  If one operand is an integer and the other is a bag, it adds the integer value to each element of the bag and returns the result. It is a run-time type error for both operands to be bags. In addition to +, the operators , *, /, and % (mod) are supported.
exp ++ exp Take the union of two subexpression results.  For example, 2#d4++d6 returns the values from rolling 2 four-sided dice and one six-sided die, in no particular order.
compare exp relop exp Perform the specified comparison, returning 1 if true and 0 if false.
sum exp If the subexpression is a bag, the result is to sum the elements of the bag.  If it is an integer, this expression returns that integer.  So, sum(3#d6) would return the sum of 3 six-sided dice.
count exp Similar to sum, but it returns the number of elements in the subexpression.  If the subexpression is an integer, it returns 1.
min exp in exp Given operands n and b respectively, returns the least n elements of bb must be a bag.  An example is min 2 (3#d6), which rolls 3 six-sided dice and returns the two least values rolled.
max exp in exp Like min, but selects the largest elements.
let id=exp in exp Binds the result of evaluating the first subexpression to the identifier id and uses the binding to evaluate the second subexpression.  Identifiers start with a letter and consist of letters, underscores, and primes.  For example, let x = d6 in x+x will roll a six-sided die and double the result.  Notice that the d6 in this expression is evaluated only once.
if exp relop exp
then exp
else exp
Similar to the ML if/then/else expression.  If the condition is true, returns the result of evaluating the first expression, otherwise of the second expression. An example is if d6 < 4 then d4 else d5, which rolls a 6-sided die; if the result is less than 4, then it rolls a 4-sided dice else rolls a 5-sided die. The list of relational operators is mentioned below. Relational operators relop may be any of <, <=, =, !=, >=, >   Note: since each element of the test is parsed separately, it is not possible to put parentheses around the comparison as in if (exp op exp) then ....
filter exp relop exp   A filter e1 op e2 evaluates e1 and e2 to get results v1 and v2. Value v1 must be an integer; v2 must be a bag.  Then the comparison (v1 op v) for each element v in bag v2 and the result is the bag with all elements for which (v1 op v) holds. For example, the expression filter 4 < 5#d6 rolls 5 six-sided dice and returns any values greater than 4.  If the 5#d6 evaluated to {1,2,4,6,6}, the filter result would be {6, 6}.

Example expressions:

Illegal expressions:


A definition can be introduced for later use. Defined names may be multipart identifiers:

Each time a definition is used, its expression is evaluated anew, unlike identifiers introduced using let.

Modes and Commands

Roll expressions are evaluated in the current mode. There are three different modes, eval, dist, and sample, each of which can be entered by using them as commands:

Additional commands: