m-chrzan.xyz
aboutsummaryrefslogtreecommitdiff
path: root/README.md
blob: e86867513c53050cb44a4922cad39b0fa1264882 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# 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 'd' Die
          | 'd' Die
          | Die ' + ' Die
          | Die ' - ' Die
          | Die '+' Die
          | '-' Die
          | Die 'E' Die
          | Die 'K' Die
          | Die 'k' 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` 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)`.
* `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`.
* `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.

Additionally:

* The binary arithmetic operations (` + `, ` - `) are left associative.
* The die operations (`d`, `E`, `K`, `k`) 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)`).