m-chrzan.xyz
 aboutsummaryrefslogtreecommitdiff log msg author committer range

# dicebag

A dice expression parser and roller.

## Installation

```# in a local node_modules/
npm install --save dicebag
# globally, to use the CLI
npm install -g dicebag
```

## Command-line usage

```dicebag [-p] [<dice expression>]
```

If a dice expression is provided, prints the result of rolling those dice and exits. Otherwise, reads expressions from `stdin` in a loop.

• `-p` print dice pools (default behavior is to print the dice's sum)

### Examples

```\$ dicebag 1d6
1
\$ dicebag "2d8 + 1d4"
7
\$ dicebag -p "2d8 + 1d4"
[ 5, 3, 4 ]
```

## Library usage

```const { parse, pool, roll } = require('dicebag')
```

The API consists of three functions:

• `parse(diceExpression)` parses an expression into an object understood by the other two functions.
• `pool(dice)` rolls the dice and returns an array of their results.
• `roll(dice)` rolls the dice and returns their sum.

### Examples

```const d6 = parse('1d6')
roll(d6)   // 4
roll(d6)   // 5
pool(d6)   // [ 2 ]
const dice = parse('2d6 + 1d8')
roll(dice) // 10
pool(dice) // [ 1, 4, 7 ]
```

## Dice expressions

### Basics

Simple expressions involving standard dice notation as used in most roleplaying games are supported. You can do things like:

• `XdY`: rolls `X` `Y`-sided dice (`1d6` is a single 6-sided die, `2d4` is two 4-sided dice).
• `dX` is the same as `1dX` (so you can shorten `1d6` to `d6`).
• `dice +/- constant`: rolls the dice, adds/subtracts the constant.
• `dice +/- moreDice`: sums/takes the difference of the results of rolling `dice` and `moreDice`.
• `number K dice`: rolls the dice and keeps the `number` highest results. For example, `1K2d20` is the "rolling with advantage" mechanic from 5th Edition Dungeons and Dragons (roll two d20's, keep the highest).
• `number k dice`: like `K` but keeps the `number` lowest results. `1k2d20` is D&D5E's "disadvantage" mechanic.

### Full syntax and semantics

Note: this is still an early version. Syntax and semantics will be expanded in future versions. Backwards incompatible changes are possible.

The parser recognizes the following grammar:

```Die ::= <an integer>
| '(' Die ')'
| '[' Die ']'
| Die 'd' Die
| 'd' Die
| Die ' + ' Die
| Die ' - ' Die
| Die ' * ' Die
| Die ' / ' Die
| Die '+' Die
| Die '-' Die
| Die '*' Die
| Die '/' Die
| '-' Die
| Die 'E' Die
| Die 'e' Die
| Die 'K' Die
| Die 'k' Die
| Die 'A' Die
| Die 'a' Die
| Die 'T' Die
| Die 't' Die
| Die ' x ' Die
```

Semantics are defined in terms of the `pool` function.

• `N`, where `N` is an integer, is a die that always rolls a single value equal to `N`. `pool` returns an array containing just `N`.
• `DdE`, where `D` and `E` are dice expressions, is a die that rolls a number of dice equal to the result of rolling `D`, where each die has a number of sides equal to the result of rolling `E`. `pool` returns an array of `roll(D)` numbers, each between 1 and `roll(E)`. Note: if `D` or `E` evaluates to a negative number, the behavior is undefined.
• `dD` is equivalent to `1dD`.
• `D + E` appends the dice pool generated by `E` to the dice pool generated by `D`.
• `-D` returns the opposites of values generated by `D`.
• `D - E` is equivalent to `D + (-E)`.
• `D * E` generates a dicepool with a single value - the product of `roll(D)` and `roll(E)`.
• `D / E` generates a dicepool with a single value - the result of integer division of `roll(D)` by `roll(E)`.
• `D+E` is the additive bonus operation. For each die in `D`'s pool, the die is rolled and `roll(E)` is added to its result.
• `D-E` is equivalent to `D+(-E)`.
• `D*E` is like `D+E` but multiplies each die in `D`'s pool the result of rolling `E`.
• `D/E` is like `D+E` but performs integer division on each die in `D`'s pool by the result of rolling `E`.
• `DEF` (here `E` is the literal symbol `E`, `D` and `F` are dice expressions) is an "exploding die." First `D` is rolled. Now each die in the dice pool generated by `F` is rolled repeatedly until it rolls something less than the value rolled on `D`. The die's result is the sum of all those rolls. Note: this could lead to an infinite evaluation if `F` always rolls higher than a possible result of `D`.
• `DeF` is like `E`, but explodes on values less than what was rolled on `D`.
• `DKE` is the "keep highest" mechanic. First `D` is rolled. Now each die in the dice pool generated by `E` is rolled, and the resulting dice pool is composed of those dice that rolled highest, taking up to as many dice as the result of rolling `D`.
• `DkE` is the "keep lowest" mechanic. Like `K`, but selects the lowest rolling dice.
• `DAE` might roll some of the dice in `E`'s pool again. First `D` is rolled. Now each die in the dice pool generated by `E` is rolled repeatedly until it rolls something less than the value rolled on `D`. Each such roll is treated as a separate die, the results for each die are not accumulated like with exploding die. Note: this could lead to an infinite evaluation if `E` always rolls higher than a possible result of `D`.
• `DaE` is like `A`, but rolls again on values less than what was rolled on `D`.
• `DTE` applies a threshold to the dice in `E`'s pool. First `D` is rolled. Now when a die from `E`'s pool rolls below the value rolled on `D`, its value is 0, otherwise its value is 1.
• `DtE` is like `T` but dice with values higher than what was rolled on `D` are counted as 0's, the rest as 1's.
• `D x E` will repeatedly roll `D`. First `E` is rolled, then `D` is rolled as many times as the value rolled on `E`. The pools generated by `D` are concatenated to generate the new pool. Note: if `E` evaluates to a negative number, the behavior is undefined.
• `[D]` collects `D`'s dice pool - the generated dice pool contains a single element, the result of `roll(D)`.

• The binary arithmetic operations (`+`, `-`, `*`, `/`) are left associative.
• The binary arithmetic operations bind as expected (multiplication and division bind stronger than addition and subtraction).
• The bonus operations (`+`, `-`, `*`, `/`) are left associative. They bind stronger than arithmetic operations. `/` and `*` bind stronger than `+` and `-`.
• The die operations (`d`, `E`, `K`, etc.) are right associative (`1d2d3` is equivalent to `1d(2d3)`, use explicit parentheses if you need `(1d2)d3`).
• Die operations bind stronger than the binary arithmetic operations (`1d6 + 1d4` is equivalent to `(1d6) + (1d4)`) and the bonus operations.
• The repetition operation `x` is left assosiative. It binds stronger than the standard arithmetic operations, but weaker than the dice operations and the bonus operations.