m-chrzan.xyz
aboutsummaryrefslogtreecommitdiff

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).

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 (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.