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.
-pprint 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: rollsXY-sided dice (1d6is a single 6-sided die,2d4is two 4-sided dice).dXis the same as1dX(so you can shorten1d6tod6).dice +/- constant: rolls the dice, adds/subtracts the constant.dice +/- moreDice: sums/takes the difference of the results of rollingdiceandmoreDice.number K dice: rolls the dice and keeps thenumberhighest results. For example,1K2d20is the "rolling with advantage" mechanic from 5th Edition Dungeons and Dragons (roll two d20's, keep the highest).number k dice: likeKbut keeps thenumberlowest results.1k2d20is 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, whereNis an integer, is a die that always rolls a single value equal toN.poolreturns an array containing justN.DdE, whereDandEare dice expressions, is a die that rolls a number of dice equal to the result of rollingD, where each die has a number of sides equal to the result of rollingE.poolreturns an array ofroll(D)numbers, each between 1 androll(E). Note: ifDorEevaluates to a negative number, the behavior is undefined.dDis equivalent to1dD.D + Eappends the dice pool generated byEto the dice pool generated byD.-Dreturns the opposites of values generated byD.D - Eis equivalent toD + (-E).D * Egenerates a dicepool with a single value - the product ofroll(D)androll(E).D / Egenerates a dicepool with a single value - the result of integer division ofroll(D)byroll(E).D+Eis the additive bonus operation. For each die inD's pool, the die is rolled androll(E)is added to its result.D-Eis equivalent toD+(-E).D*Eis likeD+Ebut multiplies each die inD's pool the result of rollingE.D/Eis likeD+Ebut performs integer division on each die inD's pool by the result of rollingE.DEF(hereEis the literal symbolE,DandFare dice expressions) is an "exploding die." FirstDis rolled. Now each die in the dice pool generated byFis rolled repeatedly until it rolls something less than the value rolled onD. The die's result is the sum of all those rolls. Note: this could lead to an infinite evaluation ifFalways rolls higher than a possible result ofD.DeFis likeE, but explodes on values less than what was rolled onD.DKEis the "keep highest" mechanic. FirstDis rolled. Now each die in the dice pool generated byEis rolled, and the resulting dice pool is composed of those dice that rolled highest, taking up to as many dice as the result of rollingD.DkEis the "keep lowest" mechanic. LikeK, but selects the lowest rolling dice.DAEmight roll some of the dice inE's pool again. FirstDis rolled. Now each die in the dice pool generated byEis rolled repeatedly until it rolls something less than the value rolled onD. 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 ifEalways rolls higher than a possible result ofD.DaEis likeA, but rolls again on values less than what was rolled onD.DTEapplies a threshold to the dice inE's pool. FirstDis rolled. Now when a die fromE's pool rolls below the value rolled onD, its value is 0, otherwise its value is 1.DtEis likeTbut dice with values higher than what was rolled onDare counted as 0's, the rest as 1's.D x Ewill repeatedly rollD. FirstEis rolled, thenDis rolled as many times as the value rolled onE. The pools generated byDare concatenated to generate the new pool. Note: ifEevaluates to a negative number, the behavior is undefined.[D]collectsD's dice pool - the generated dice pool contains a single element, the result ofroll(D).
Additionally:
- 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 (1d2d3is equivalent to1d(2d3), use explicit parentheses if you need(1d2)d3). - Die operations bind stronger than the binary arithmetic operations
(
1d6 + 1d4is equivalent to(1d6) + (1d4)) and the bonus operations. - The repetition operation
xis left assosiative. It binds stronger than the standard arithmetic operations, but weaker than the dice operations and the bonus operations.