@yipe/dice 0.2.17 โ 0.2.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +256 -35
- package/dist/builder/index.cjs +878 -11
- package/dist/builder/index.cjs.map +1 -1
- package/dist/builder/index.d.cts +23 -1
- package/dist/builder/index.d.ts +23 -1
- package/dist/builder/index.js +878 -12
- package/dist/builder/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -36,7 +36,9 @@ console.log("DPR:", attack.mean());
|
|
|
36
36
|
- **Composable API**: Build dice expressions, run queries, and analyze results in just a few lines.
|
|
37
37
|
- **TypeScript First**: Full type safety and developer experience.
|
|
38
38
|
|
|
39
|
-
## ๐
|
|
39
|
+
## ๐ Quick Start
|
|
40
|
+
|
|
41
|
+
### Installation
|
|
40
42
|
|
|
41
43
|
```bash
|
|
42
44
|
# Install with npm or yarn
|
|
@@ -45,6 +47,236 @@ npm install @yipe/dice
|
|
|
45
47
|
yarn add @yipe/dice
|
|
46
48
|
```
|
|
47
49
|
|
|
50
|
+
### Basic Usage
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
import { parse, DiceQuery } from "@yipe/dice";
|
|
54
|
+
|
|
55
|
+
const query = d20.plus(8).ac(16).onHit(d4.plus(4)).toQuery();
|
|
56
|
+
|
|
57
|
+
console.log("Hit chance:", query.probAtLeastOne(["hit", "crit"]));
|
|
58
|
+
console.log("Crit chance:", query.probAtLeastOne(["crit"]));
|
|
59
|
+
console.log("DPR:", query.mean());
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Output:**
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
Hit chance: 0.65
|
|
66
|
+
Crit chance: 0.05
|
|
67
|
+
DPR: 4.35
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## ๐ Development Setup
|
|
71
|
+
|
|
72
|
+
### Prerequisites
|
|
73
|
+
|
|
74
|
+
- **Node.js**: >= 18.17
|
|
75
|
+
- **Yarn**: 4.9.4 (specified in `packageManager`)
|
|
76
|
+
|
|
77
|
+
### Initial Setup
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# Clone the repository
|
|
81
|
+
git clone https://github.com/yipe/dice.git
|
|
82
|
+
cd dice
|
|
83
|
+
|
|
84
|
+
# Install dependencies
|
|
85
|
+
yarn install
|
|
86
|
+
|
|
87
|
+
# Build the project
|
|
88
|
+
yarn build
|
|
89
|
+
|
|
90
|
+
# Run tests
|
|
91
|
+
yarn test
|
|
92
|
+
|
|
93
|
+
# Run examples
|
|
94
|
+
yarn example
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Available Scripts
|
|
98
|
+
|
|
99
|
+
| Command | Purpose |
|
|
100
|
+
|---------|---------|
|
|
101
|
+
| `yarn build` | Compile TypeScript to JavaScript (outputs to `dist/`) |
|
|
102
|
+
| `yarn test` | Run test suite once |
|
|
103
|
+
| `yarn test:watch` | Run tests in watch mode |
|
|
104
|
+
| `yarn typecheck` | Type-check without emitting files |
|
|
105
|
+
| `yarn lint` | Run ESLint |
|
|
106
|
+
| `yarn example` | Run example scripts |
|
|
107
|
+
|
|
108
|
+
### Project Structure
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
src/
|
|
112
|
+
โโโ builder/ # Fluent API for building dice expressions
|
|
113
|
+
โ โโโ factory.ts # Factory functions (d20, d6, roll, etc.)
|
|
114
|
+
โ โโโ roll.ts # RollBuilder - core builder class
|
|
115
|
+
โ โโโ ac.ts # ACBuilder - attack roll builder
|
|
116
|
+
โ โโโ attack.ts # AttackBuilder - attack with damage
|
|
117
|
+
โ โโโ save.ts # SaveBuilder - saving throw builder
|
|
118
|
+
โ โโโ dc.ts # DCBuilder - difficulty check builder
|
|
119
|
+
โ โโโ ast.ts # AST generation and PMF conversion
|
|
120
|
+
โ โโโ nodes.ts # AST node type definitions
|
|
121
|
+
โโโ parser/ # String-based dice expression parser
|
|
122
|
+
โ โโโ parser.ts # Main parser implementation
|
|
123
|
+
โ โโโ dice.ts # Dice class (legacy parser representation)
|
|
124
|
+
โโโ pmf/ # Probability Mass Function core
|
|
125
|
+
โ โโโ pmf.ts # PMF class - core data structure
|
|
126
|
+
โ โโโ query.ts # DiceQuery - analysis interface
|
|
127
|
+
โ โโโ mixture.ts # Mixture operations
|
|
128
|
+
โโโ common/ # Shared utilities
|
|
129
|
+
โโโ types.ts # Type definitions
|
|
130
|
+
โโโ lru-cache.ts # LRU cache implementation
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## ๐ Architecture Overview
|
|
134
|
+
|
|
135
|
+
The library provides two parallel entry points for creating dice expressions:
|
|
136
|
+
|
|
137
|
+
### Entry Point 1: String Parser
|
|
138
|
+
|
|
139
|
+
Parses text expressions like `"(d20 + 8 AC 16) * (1d8 + 4) crit (2d8 + 4)"`:
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
String Expression
|
|
143
|
+
โ
|
|
144
|
+
โโ parse() โโโโโโโโโโโโโโโ
|
|
145
|
+
โ โ
|
|
146
|
+
โ โผ
|
|
147
|
+
โ parseExpression()
|
|
148
|
+
โ โ
|
|
149
|
+
โ โโ parseArgument() โโโบ Dice objects
|
|
150
|
+
โ โ
|
|
151
|
+
โ โโ parseOperation() โโโบ Dice operations
|
|
152
|
+
โ โ
|
|
153
|
+
โ โผ
|
|
154
|
+
โ Dice.toPMF() โโโบ PMF
|
|
155
|
+
โ โ
|
|
156
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Entry Point 2: Fluent Builder API
|
|
160
|
+
|
|
161
|
+
Type-safe builder pattern:
|
|
162
|
+
|
|
163
|
+
```
|
|
164
|
+
RollBuilder (d20, d6, roll(), etc.)
|
|
165
|
+
โ
|
|
166
|
+
โโ .plus() โโโบ RollBuilder
|
|
167
|
+
โโ .ac() โโโโโบ ACBuilder
|
|
168
|
+
โ โ
|
|
169
|
+
โ โโ .onHit() โโโบ AttackBuilder
|
|
170
|
+
โ โ
|
|
171
|
+
โ โโ .toQuery() โโโบ DiceQuery
|
|
172
|
+
โ โโ .pmf โโโโโโโโโโบ PMF
|
|
173
|
+
โ
|
|
174
|
+
โโ .toPMF() โโโบ PMF
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Core Class Flow
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
181
|
+
โ User Input Layer โ
|
|
182
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
|
|
183
|
+
โ String Parser โ Fluent Builder โ
|
|
184
|
+
โ parse("...") โ d20.plus(8).ac(16) โ
|
|
185
|
+
โโโโโโโโโโโโโโฌโโโโโโโโโโโโโดโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโ
|
|
186
|
+
โ โ
|
|
187
|
+
โผ โผ
|
|
188
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
189
|
+
โ Builder Layer โ
|
|
190
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
|
|
191
|
+
โ RollBuilder โโโบ ACBuilder โโโบ AttackBuilder โ
|
|
192
|
+
โ โ โ โ โ
|
|
193
|
+
โ โ โ โ โ
|
|
194
|
+
โ โโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโ โ
|
|
195
|
+
โ โ โ
|
|
196
|
+
โ โผ โ
|
|
197
|
+
โ astFromRollConfigs() โ
|
|
198
|
+
โ โ โ
|
|
199
|
+
โ โผ โ
|
|
200
|
+
โ ExpressionNode (AST) โ
|
|
201
|
+
โโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
202
|
+
โ
|
|
203
|
+
โผ
|
|
204
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
205
|
+
โ PMF Generation โ
|
|
206
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
|
|
207
|
+
โ pmfFromRollBuilder() โ
|
|
208
|
+
โ โ โ
|
|
209
|
+
โ โโ d20RollPMF() โโโบ PMF (for d20 rolls) โ
|
|
210
|
+
โ โโ diePMF() โโโโโโโบ PMF (for regular dice) โ
|
|
211
|
+
โ โโ combinePMFs() โโบ PMF (convolve multiple PMFs) โ
|
|
212
|
+
โโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
213
|
+
โ
|
|
214
|
+
โผ
|
|
215
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
216
|
+
โ Query & Analysis โ
|
|
217
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
|
|
218
|
+
โ DiceQuery โ
|
|
219
|
+
โ โ โ
|
|
220
|
+
โ โโ .mean() โโโโโโโโโโโโโบ Expected damage โ
|
|
221
|
+
โ โโ .variance() โโโโโโโโโบ Damage variance โ
|
|
222
|
+
โ โโ .probAtLeastOne() โโโบ Hit/crit probabilities โ
|
|
223
|
+
โ โโ .toChartSeries() โโโโโบ Chart data โ
|
|
224
|
+
โ โโ .combined โโโโโโโโโโโโบ Final PMF โ
|
|
225
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### PMF Data Structure
|
|
229
|
+
|
|
230
|
+
The `PMF` class is the core mathematical representation:
|
|
231
|
+
|
|
232
|
+
```
|
|
233
|
+
PMF
|
|
234
|
+
โโโ map: Map<number, Bin>
|
|
235
|
+
โ โโโ Bin
|
|
236
|
+
โ โโโ p: number (probability)
|
|
237
|
+
โ โโโ count: {...} (outcome counts: hit, crit, miss)
|
|
238
|
+
โ โโโ attr: {...} (damage attribution)
|
|
239
|
+
โโโ epsilon: number (probability threshold)
|
|
240
|
+
โโโ normalized: boolean (whether PMF sums to 1.0)
|
|
241
|
+
โโโ identifier: string (cache key / debug name)
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Main Flow Example
|
|
245
|
+
|
|
246
|
+
Here's how a simple attack flows through the system:
|
|
247
|
+
|
|
248
|
+
```
|
|
249
|
+
1. User creates: d20.plus(5).ac(15).onHit(d6.plus(2))
|
|
250
|
+
|
|
251
|
+
2. Builder chain:
|
|
252
|
+
RollBuilder(d20)
|
|
253
|
+
โ plus(5) โ RollBuilder(d20 + 5)
|
|
254
|
+
โ ac(15) โ ACBuilder(d20 + 5 AC 15)
|
|
255
|
+
โ onHit(...) โ AttackBuilder
|
|
256
|
+
|
|
257
|
+
3. AST generation:
|
|
258
|
+
RollConfig[] โ ExpressionNode
|
|
259
|
+
- DieNode (d20)
|
|
260
|
+
- ConstantNode (+5)
|
|
261
|
+
- D20RollNode (AC check)
|
|
262
|
+
- ConditionalNode (on hit)
|
|
263
|
+
|
|
264
|
+
4. PMF generation:
|
|
265
|
+
AST โ PMF operations
|
|
266
|
+
- d20RollPMF(rollType, rerollOne) โ PMF
|
|
267
|
+
- Conditional application โ PMF.branch()
|
|
268
|
+
- Damage PMF โ PMF
|
|
269
|
+
- Combine โ PMF (final result)
|
|
270
|
+
|
|
271
|
+
5. Query creation:
|
|
272
|
+
AttackBuilder.toQuery() โ DiceQuery
|
|
273
|
+
- singles: [PMF]
|
|
274
|
+
- combined: PMF (convolved)
|
|
275
|
+
|
|
276
|
+
6. Analysis:
|
|
277
|
+
DiceQuery.mean() โ 3.20 DPR
|
|
278
|
+
```
|
|
279
|
+
|
|
48
280
|
## ๐ฆ Core Concepts
|
|
49
281
|
|
|
50
282
|
| Concept | Description |
|
|
@@ -52,11 +284,12 @@ yarn add @yipe/dice
|
|
|
52
284
|
| **PMF** | Probability Mass Function. The core mathematical representation of outcomes. |
|
|
53
285
|
| **Query** | Runs calculations and scenarios over one or more PMFs. |
|
|
54
286
|
| **Parser** | Parses text-based dice expressions like `(d20 + 8 AC 16) * (1d4 + 4)`. |
|
|
55
|
-
| **
|
|
287
|
+
| **Builder**| Fluent TypeScript API for building dice expressions. |
|
|
288
|
+
| **AST** | Abstract Syntax Tree representing dice operations. |
|
|
56
289
|
|
|
57
|
-
## ๐ง
|
|
290
|
+
## ๐ง Usage Examples
|
|
58
291
|
|
|
59
|
-
|
|
292
|
+
### Basic Attack
|
|
60
293
|
|
|
61
294
|
```ts
|
|
62
295
|
import { parse, DiceQuery } from "@yipe/dice";
|
|
@@ -68,20 +301,23 @@ console.log("Crit chance:", query.probAtLeastOne(["crit"]));
|
|
|
68
301
|
console.log("DPR:", query.mean());
|
|
69
302
|
```
|
|
70
303
|
|
|
71
|
-
|
|
304
|
+
### String Parser
|
|
72
305
|
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
306
|
+
```ts
|
|
307
|
+
import { parse } from "@yipe/dice";
|
|
308
|
+
|
|
309
|
+
const pmf = parse("(d20 + 8 AC 16) * (1d8 + 4) crit (2d8 + 4)");
|
|
310
|
+
const query = new DiceQuery(pmf);
|
|
311
|
+
|
|
312
|
+
console.log("DPR:", query.mean());
|
|
77
313
|
```
|
|
78
314
|
|
|
79
|
-
|
|
315
|
+
### Sneak Attack (Conditional Damage)
|
|
80
316
|
|
|
81
317
|
Conditional damage ("once-per-turn damage riders") like Sneak Attack can be modeled easily:
|
|
82
318
|
|
|
83
319
|
```ts
|
|
84
|
-
import { DiceQuery } from "@yipe/dice";
|
|
320
|
+
import { DiceQuery, PMF, roll } from "@yipe/dice";
|
|
85
321
|
|
|
86
322
|
function sneakAttack() {
|
|
87
323
|
const attackPMF = d20.plus(8).ac(16).onHit(d4.plus(4)).pmf;
|
|
@@ -99,15 +335,13 @@ function sneakAttack() {
|
|
|
99
335
|
console.log("DPR with once-per-turn sneak attack: ", sneakAttack().mean());
|
|
100
336
|
```
|
|
101
337
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
You can generate full statistical distributions for visualization or reporting.
|
|
338
|
+
### Statistics and Charts
|
|
105
339
|
|
|
106
340
|
```ts
|
|
107
341
|
import { parse, DiceQuery } from "@yipe/dice";
|
|
108
342
|
|
|
109
|
-
const
|
|
110
|
-
console.table(
|
|
343
|
+
const query = parse("(d20 + 8 AC 16) * (1d4 + 4) crit (2d4 + 4)").toQuery();
|
|
344
|
+
console.table(query.toChartSeries());
|
|
111
345
|
```
|
|
112
346
|
|
|
113
347
|
**Output:**
|
|
@@ -128,17 +362,9 @@ console.table(query2.toChartSeries());
|
|
|
128
362
|
โโโโโโโโโโโดโโโโโดโโโโโโโโโโโ
|
|
129
363
|
```
|
|
130
364
|
|
|
131
|
-
## ๐ Project Structure
|
|
132
|
-
|
|
133
|
-
| File | Purpose |
|
|
134
|
-
| ----------- | ------------------------------------- |
|
|
135
|
-
| `src/` | Core Dice class and logic |
|
|
136
|
-
| `examples/` | Example scripts showing library usage |
|
|
137
|
-
| `tests/` | Comprehensive library tests |
|
|
138
|
-
|
|
139
365
|
## ๐งช Running Examples
|
|
140
366
|
|
|
141
|
-
This repository includes example scripts
|
|
367
|
+
This repository includes example scripts:
|
|
142
368
|
|
|
143
369
|
```bash
|
|
144
370
|
yarn example basic
|
|
@@ -147,7 +373,7 @@ yarn example sneakattack
|
|
|
147
373
|
yarn example misc
|
|
148
374
|
```
|
|
149
375
|
|
|
150
|
-
Here is the basic example:
|
|
376
|
+
Here is the basic example output:
|
|
151
377
|
|
|
152
378
|
```
|
|
153
379
|
% yarn example basic
|
|
@@ -217,10 +443,9 @@ Here is the basic example:
|
|
|
217
443
|
โ 13 โ 0.278% โ 0.278% โ 0.000% โ 0.000% โ
|
|
218
444
|
โ 14 โ 0.139% โ 0.139% โ 0.000% โ 0.000% โ
|
|
219
445
|
โโโโโโโโโโดโโโโโโโโโโดโโโโโโโโโดโโโโโโโโโดโโโโโโโโโโ
|
|
220
|
-
|
|
221
446
|
```
|
|
222
447
|
|
|
223
|
-
|
|
448
|
+
This enables rich statistics like "how much damage comes from crits vs hits".
|
|
224
449
|
|
|
225
450
|
## ๐งฑ Roadmap
|
|
226
451
|
|
|
@@ -247,13 +472,13 @@ cd dice
|
|
|
247
472
|
yarn install
|
|
248
473
|
```
|
|
249
474
|
|
|
250
|
-
Run tests
|
|
475
|
+
Run tests:
|
|
251
476
|
|
|
252
477
|
```bash
|
|
253
478
|
yarn test
|
|
254
479
|
```
|
|
255
480
|
|
|
256
|
-
Run examples
|
|
481
|
+
Run examples:
|
|
257
482
|
|
|
258
483
|
```bash
|
|
259
484
|
yarn example
|
|
@@ -273,8 +498,4 @@ Wizards of the Coast, Dungeons & Dragons, and their logos are trademarks of Wiza
|
|
|
273
498
|
|
|
274
499
|
Portions of this code are inspired by [dice.clockworkmod.com](https://github.com/koush/dice.clockworkmod.com) by Koushik Dutta (2013), licensed under the [Apache License 2.0](http://www.apache.org/licenses/LICENSE-2.0).
|
|
275
500
|
|
|
276
|
-
Initial [TypeScript port](https://github.com/loginName1/dice-calculator-ts) expertly created by [loginName1](https://github.com/loginName1).
|
|
277
|
-
|
|
278
|
-
```
|
|
279
|
-
|
|
280
|
-
```
|
|
501
|
+
Initial [TypeScript port](https://github.com/loginName1/dice-calculator-ts) expertly created by [loginName1](https://github.com/loginName1).
|