# Roll

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.  `d`n 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 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. `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:

• ` 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.
Illegal expressions:
• `(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.

## Definitions

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

• `new char = 6 # sum max 3 in 4#d6`
• `plus1 = new char + 1`

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:

• `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.

• `mode`: view the current mode
• `help`: print a help message prompt.
• `quit` or `q`: quit
• `load filename`: load definitions from an external file.