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.
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 3d6roll 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 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} | 
| dexp | d is the most important expression in
    Roll. dn means roll an  n-sided die and return the result.  For example,d6evaluates to any of the integers 1–6.  The
    expression afterdneed 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#d6rolls 3 six-sided dice
    and returns a bag containing the results; the expression3#(2#d6)is equivalent
    to6#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++d6returns the values from rolling 2 four-sided dice and one
        six-sided die, in no particular order. | 
| compareexp relop exp | Perform the specified comparison, returning 1 if true and 0 if false. | 
| sumexp | 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. | 
| countexp | Similar to sum, but it returns the number of elements in the subexpression. If the subexpression is an integer, it returns 1. | 
| minexpinexp | Given operands n  and
    b respectively, returns the least 
    n elements of b.  b
    must be a bag.  An example is min 2 (3#d6), which rolls
    3 six-sided dice and returns the two least values rolled. | 
| maxexpinexp | Like min, but selects the largest elements. | 
| letid=exp inexp | 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+xwill roll a six-sided
    die and double the result.  Notice that the d6 in this expression
    is evaluated only once. | 
| ifexp    relop   exp thenexp elseexp | Similar to the ML if/then/elseexpression.  If the condition is
    true, returns the result of evaluating the first expression, otherwise
    of the second expression. An example isif 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 inif (exp op exp) then
	.... | 
| filterexp 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 v for which (v1
 op
 v) holds.
    For example, the expression filter 4 < 5#d6rolls 5 six-sided dice and returns any values greater than
    4.  If the5#d6evaluated to {1,2,4,6,6}, the filter
    result would be {6, 6}. | 
Example expressions:
 d6  : Roll a 6 sided die
     2 # d6  : Roll two 6 sided dice
     d(d 6)  : Roll a 6 sided die to get 'n', and then role an
      'n' sided die
     d(sum(2#d6))  : Roll an 'n' sided die where n is the
    sum of two six-sided die rolls.
    if d6 < 4 then 4 else 2#d4 Roll a d6, and if that
    is less than 4 return 4, otherwise return a bag consisting of the results
    of rolling 2 d4's.max 2 in (3#d5) : Return the largest 2 values after
    rolling three five-sided dice. min 2 in (3#(if d6 < d6 then 1 else 2))  : Roll
    two dice. If the first is smaller, return 1 else 2. Do this three times
    and select the lowest two values.
(2#d6) # d6 : First argument to # must be an int.
    d(2#d6) : Argument to d should be an int.
    min 2 in 5 : Second argument to min should be a bag.
    min 2 in d5 : Second argument to min should be a bag.
    (2#d6) + (2#d6) : Cannot add two bags.
    let x = d6 in x + y : Unbound identifier y.
A definition can be introduced for later use. Defined names may be multipart identifiers:
attribute = sum max 3 in 4#d6new char = 6 # attributeplus1 = new char + 1
Each time a definition is used, its expression is evaluated anew, unlike
identifiers introduced using let.
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:
eval mode - evaluates the expression and returns a
    single result. This is the initial mode.
    dist mode - evaluates the expression, but this time
    instead of giving out a single result, returns all possible values of
    the expression, with their frequency distribution.sample mode - evaluates the expression multiple times
    and returns all of the results. Run with a large enough sample size, the
    frequency of certain results should approach those returned in
    dist mode.Additional commands:
mode: view the current mode
help: print a help message
prompt.
quit or q: quit
load filename: load definitions from an external file.