@yipe/dice 0.4.0 → 0.6.0

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.
Files changed (61) hide show
  1. package/dist/builder/ac.d.ts +25 -0
  2. package/dist/builder/ac.d.ts.map +1 -0
  3. package/dist/builder/ast.d.ts +9 -0
  4. package/dist/builder/ast.d.ts.map +1 -0
  5. package/dist/builder/attack.d.ts +41 -0
  6. package/dist/builder/attack.d.ts.map +1 -0
  7. package/dist/builder/d20.d.ts +6 -0
  8. package/dist/builder/d20.d.ts.map +1 -0
  9. package/dist/builder/dc.d.ts +26 -0
  10. package/dist/builder/dc.d.ts.map +1 -0
  11. package/dist/builder/example.d.ts +356 -0
  12. package/dist/builder/example.d.ts.map +1 -0
  13. package/dist/builder/factory.d.ts +17 -0
  14. package/dist/builder/factory.d.ts.map +1 -0
  15. package/dist/builder/index.cjs +106 -0
  16. package/dist/builder/index.cjs.map +1 -1
  17. package/dist/builder/index.d.ts +8 -379
  18. package/dist/builder/index.d.ts.map +1 -0
  19. package/dist/builder/index.js +105 -1
  20. package/dist/builder/index.js.map +1 -1
  21. package/dist/builder/nodes.d.ts +61 -0
  22. package/dist/builder/nodes.d.ts.map +1 -0
  23. package/dist/builder/prob.d.ts +3 -0
  24. package/dist/builder/prob.d.ts.map +1 -0
  25. package/dist/builder/roll.d.ts +205 -0
  26. package/dist/builder/roll.d.ts.map +1 -0
  27. package/dist/builder/save.d.ts +19 -0
  28. package/dist/builder/save.d.ts.map +1 -0
  29. package/dist/builder/types.d.ts +66 -0
  30. package/dist/builder/types.d.ts.map +1 -0
  31. package/dist/common/bounce.d.ts +32 -0
  32. package/dist/common/bounce.d.ts.map +1 -0
  33. package/dist/common/errors.d.ts +26 -0
  34. package/dist/common/errors.d.ts.map +1 -0
  35. package/dist/common/lru-cache.d.ts +17 -0
  36. package/dist/common/lru-cache.d.ts.map +1 -0
  37. package/dist/common/types.d.ts +65 -0
  38. package/dist/common/types.d.ts.map +1 -0
  39. package/dist/index.d.ts +9 -111
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/parser/dice.d.ts +70 -0
  42. package/dist/parser/dice.d.ts.map +1 -0
  43. package/dist/parser/parser.d.ts +14 -0
  44. package/dist/parser/parser.d.ts.map +1 -0
  45. package/dist/pmf/mixture.d.ts +37 -0
  46. package/dist/pmf/mixture.d.ts.map +1 -0
  47. package/dist/pmf/pmf.d.ts +380 -0
  48. package/dist/pmf/pmf.d.ts.map +1 -0
  49. package/dist/{pmf-D5VRghZI.d.ts → pmf/query.d.ts} +6 -464
  50. package/dist/pmf/query.d.ts.map +1 -0
  51. package/package.json +16 -15
  52. package/.claude/worktrees/amazing-matsumoto-27220c/LICENSE +0 -21
  53. package/.claude/worktrees/amazing-matsumoto-27220c/README.md +0 -518
  54. package/.claude/worktrees/vibrant-lovelace-0cc9e7/LICENSE +0 -21
  55. package/.claude/worktrees/vibrant-lovelace-0cc9e7/README.md +0 -518
  56. package/.claude/worktrees/wizardly-mclean-e375de/LICENSE +0 -21
  57. package/.claude/worktrees/wizardly-mclean-e375de/README.md +0 -518
  58. package/CHANGELOG.md +0 -224
  59. package/dist/builder/index.d.cts +0 -379
  60. package/dist/index.d.cts +0 -111
  61. package/dist/pmf-D5VRghZI.d.cts +0 -1129
@@ -1,518 +0,0 @@
1
- [![npm version](https://img.shields.io/npm/v/@yipe/dice.svg)](https://www.npmjs.com/package/@yipe/dice)
2
- [![License: MIT](https://img.shields.io/badge/License-MIT-007ec6.svg)](LICENSE)
3
- ![TypeScript](https://img.shields.io/badge/TypeScript-Ready-3178c6?logo=typescript)
4
- ![Size](https://img.shields.io/bundlephobia/minzip/@yipe/dice?logo=npm&logoColor=fff&label=Size)
5
- ![Dice](https://dprcalc.com/api/roll.svg)
6
-
7
- ![Last Commit](https://img.shields.io/github/last-commit/yipe/dice?logo=github)
8
- ![Dependencies](https://img.shields.io/librariesio/release/npm/@yipe/dice?logo=npm)
9
- [![GitHub issues](https://img.shields.io/github/issues/yipe/dice.svg?logo=github)](https://github.com/yipe/dice/issues)
10
- [![Build Status](https://github.com/yipe/dice/actions/workflows/ci.yml/badge.svg)](https://github.com/yipe/dice/actions)
11
- [![Tests](https://img.shields.io/badge/tests-passing-4c1.svg?logo=vitest&logoColor=white)](https://github.com/yipe/dice/actions/workflows/ci.yml)
12
-
13
- # 🎲 @yipe/dice
14
-
15
- A TypeScript library for **D&D 5e damage-per-round (DPR) calculations**, designed for players, Dungeon Masters, and developers who want to analyze combat mathematically.
16
-
17
- This library powers [dprcalc.com](https://dprcalc.com) and provides a precise, composable way to model dice rolls, attacks, and outcomes with probability mass functions (PMFs) — not just averages. This allows for rich charting and statistics with full outcome attribution. It provides two main entry points: a fluent typescript interface or a dice expression string.
18
-
19
- ```ts
20
- import { parse } from "@yipe/dice";
21
-
22
- const attack = parse("(d20 + 8 AC 16) * (1d8 + 4) crit (2d8 + 4)");
23
- console.log("DPR:", attack.mean());
24
-
25
- // or
26
-
27
- const attack = d20.plus(8).ac(16).onHit(d8.plus(4));
28
- console.log("DPR:", attack.mean());
29
- ```
30
-
31
- ## ✨ Features
32
-
33
- - **D&D 5e Focused**: Designed around 5e rules (2014 and 2024).
34
- - **Probability Mass Functions (PMF)**: Precise modeling of dice rolls and outcomes, not just averages.
35
- - **Complex Attack Expressions**: Supports crit ranges, advantage/disadvantage, conditional damage, rerolls, minimum damage, and more.
36
- - **Composable API**: Build dice expressions, run queries, and analyze results in just a few lines.
37
- - **TypeScript First**: Full type safety and developer experience.
38
-
39
- ## 🚀 Quick Start
40
-
41
- ### Installation
42
-
43
- ```bash
44
- # Install with npm or yarn
45
- npm install @yipe/dice
46
- # or
47
- yarn add @yipe/dice
48
- ```
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
-
280
- ## 📦 Core Concepts
281
-
282
- | Concept | Description |
283
- | ---------- | ---------------------------------------------------------------------------- |
284
- | **PMF** | Probability Mass Function. The core mathematical representation of outcomes. |
285
- | **Query** | Runs calculations and scenarios over one or more PMFs. |
286
- | **Parser** | Parses text-based dice expressions like `(d20 + 8 AC 16) * (1d4 + 4)`. |
287
- | **Builder**| Fluent TypeScript API for building dice expressions. |
288
- | **AST** | Abstract Syntax Tree representing dice operations. |
289
-
290
- ## 🧙 Usage Examples
291
-
292
- ### Basic Attack
293
-
294
- ```ts
295
- import { parse, DiceQuery } from "@yipe/dice";
296
-
297
- const query = d20.plus(8).ac(16).onHit(d4.plus(4)).toQuery();
298
-
299
- console.log("Hit chance:", query.probAtLeastOne(["hit", "crit"]));
300
- console.log("Crit chance:", query.probAtLeastOne(["crit"]));
301
- console.log("DPR:", query.mean());
302
- ```
303
-
304
- ### String Parser
305
-
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());
313
- ```
314
-
315
- ### Error Handling
316
-
317
- `parse()` throws a `DiceParseError` (a subclass of `Error`) for invalid input.
318
- Narrow with `instanceof` and inspect the offending `expression`:
319
-
320
- ```ts
321
- import { parse, DiceParseError } from "@yipe/dice";
322
-
323
- try {
324
- parse("d6@3");
325
- } catch (err) {
326
- if (err instanceof DiceParseError) {
327
- console.warn(`Bad dice expression: ${err.expression}`);
328
- }
329
- }
330
- ```
331
-
332
- ### Sneak Attack (Conditional Damage)
333
-
334
- Conditional damage ("once-per-turn damage riders") like Sneak Attack can be modeled easily:
335
-
336
- ```ts
337
- import { DiceQuery, PMF, roll } from "@yipe/dice";
338
-
339
- function sneakAttack() {
340
- const attackPMF = d20.plus(8).ac(16).onHit(d4.plus(4)).pmf;
341
- const sneakAttack = roll(3, d6);
342
- const attacks = new DiceQuery([attackPMF, attackPMF]);
343
- const [pHit, pCrit] = attacks.firstSuccessSplit(onAnyHit, onCritOnly);
344
- const sneakPMF = PMF.exclusive([
345
- [sneakAttack.pmf, pHit],
346
- [sneakAttack.doubleDice().pmf, pCrit],
347
- ]);
348
-
349
- return new DiceQuery([attackPMF, attackPMF, sneakPMF]);
350
- }
351
-
352
- console.log("DPR with once-per-turn sneak attack: ", sneakAttack().mean());
353
- ```
354
-
355
- ### Statistics and Charts
356
-
357
- ```ts
358
- import { parse, DiceQuery } from "@yipe/dice";
359
-
360
- const query = parse("(d20 + 8 AC 16) * (1d4 + 4) crit (2d4 + 4)").toQuery();
361
- console.table(query.toChartSeries());
362
- ```
363
-
364
- **Output:**
365
-
366
- ```
367
- ┌─────────┬────┬──────────┐
368
- │ (index) │ x │ y │
369
- ├─────────┼────┼──────────┤
370
- │ 0 │ 0 │ 0.35 │
371
- │ 1 │ 5 │ 0.15 │
372
- │ 2 │ 6 │ 0.153125 │
373
- │ 3 │ 7 │ 0.15625 │
374
- │ 4 │ 8 │ 0.159375 │
375
- │ 5 │ 9 │ 0.0125 │
376
- │ 6 │ 10 │ 0.009375 │
377
- │ 7 │ 11 │ 0.00625 │
378
- │ 8 │ 12 │ 0.003125 │
379
- └─────────┴────┴──────────┘
380
- ```
381
-
382
- ## 🧪 Running Examples
383
-
384
- This repository includes example scripts:
385
-
386
- ```bash
387
- yarn example basic
388
- yarn example stats
389
- yarn example sneakattack
390
- yarn example misc
391
- ```
392
-
393
- Here is the basic example output:
394
-
395
- ```
396
- % yarn example basic
397
-
398
- ┌────────────┐
399
- │ Summary │
400
- ├────────────┴─────────────────────────────────────────────┐
401
- │ Expression: (d20 + 5 AC 15) * (1d6+2) crit (2d6 + 2) │
402
- │ Success Chance: 0.55 │
403
- │ Expected DPR: 3.20 │
404
- └──────────────────────────────────────────────────────────┘
405
-
406
- ┌────────────┐
407
- │ PMF () │
408
- ├────────────┴───────────────────────────────────────────────────────────────────────────┐
409
- │ 0: █████████████████████████████████████████████████████████████████████████ 45.00% │
410
- │ 3: █████████████▌ 8.33% │
411
- │ 4: █████████████▋ 8.47% │
412
- │ 5: █████████████▉ 8.61% │
413
- │ 6: ██████████████▏ 8.75% │
414
- │ 7: ██████████████▍ 8.89% │
415
- │ 8: ██████████████▋ 9.03% │
416
- │ 9: █▎ 0.83% │
417
- │ 10: █▏ 0.69% │
418
- │ 11: ▉ 0.56% │
419
- │ 12: ▋ 0.42% │
420
- │ 13: ▍ 0.28% │
421
- │ 14: ▏ 0.14% │
422
- └────────────────────────────────────────────────────────────────────────────────────────┘
423
-
424
- ┌──────────────────┐
425
- │ CDF (): P(X ≤ x) │
426
- ├──────────────────┴─────────────────────────────────────────────────────────────────────┐
427
- │ 0: ████████████████████████████████▍ 45.00% │
428
- │ 1: ████████████████████████████████▍ 45.00% │
429
- │ 2: ████████████████████████████████▍ 45.00% │
430
- │ 3: ██████████████████████████████████████▍ 53.33% │
431
- │ 4: ████████████████████████████████████████████▌ 61.81% │
432
- │ 5: ██████████████████████████████████████████████████▋ 70.42% │
433
- │ 6: █████████████████████████████████████████████████████████▏ 79.17% │
434
- │ 7: ███████████████████████████████████████████████████████████████▍ 88.06% │
435
- │ 8: █████████████████████████████████████████████████████████████████████▉ 97.08% │
436
- │ 9: ██████████████████████████████████████████████████████████████████████▌ 97.92% │
437
- │ 10: ███████████████████████████████████████████████████████████████████████ 98.61% │
438
- │ 11: ███████████████████████████████████████████████████████████████████████▍ 99.17% │
439
- │ 12: ███████████████████████████████████████████████████████████████████████▋ 99.58% │
440
- │ 13: ███████████████████████████████████████████████████████████████████████▉ 99.86% │
441
- │ 14: ████████████████████████████████████████████████████████████████████████ 100.00% │
442
- └────────────────────────────────────────────────────────────────────────────────────────┘
443
-
444
- ┌──────────────────┐
445
- │ Outcome Table () │
446
- ├──────────────────┴───────────────────────────┐
447
- │ DAMAGE │ PERCENT │ Crit % │ Hit % │ Miss % │
448
- ├────────┼─────────┼────────┼────────┼─────────┤
449
- │ 0 │ 45.000% │ 0.000% │ 0.000% │ 45.000% │
450
- │ 3 │ 8.333% │ 0.000% │ 8.333% │ 0.000% │
451
- │ 4 │ 8.472% │ 0.139% │ 8.333% │ 0.000% │
452
- │ 5 │ 8.611% │ 0.278% │ 8.333% │ 0.000% │
453
- │ 6 │ 8.750% │ 0.417% │ 8.333% │ 0.000% │
454
- │ 7 │ 8.889% │ 0.556% │ 8.333% │ 0.000% │
455
- │ 8 │ 9.028% │ 0.694% │ 8.333% │ 0.000% │
456
- │ 9 │ 0.833% │ 0.833% │ 0.000% │ 0.000% │
457
- │ 10 │ 0.694% │ 0.694% │ 0.000% │ 0.000% │
458
- │ 11 │ 0.556% │ 0.556% │ 0.000% │ 0.000% │
459
- │ 12 │ 0.417% │ 0.417% │ 0.000% │ 0.000% │
460
- │ 13 │ 0.278% │ 0.278% │ 0.000% │ 0.000% │
461
- │ 14 │ 0.139% │ 0.139% │ 0.000% │ 0.000% │
462
- └────────┴─────────┴────────┴────────┴─────────┘
463
- ```
464
-
465
- This enables rich statistics like "how much damage comes from crits vs hits".
466
-
467
- ## 🧱 Roadmap
468
-
469
- - [ ] Create a **web playground** with live examples
470
- - [ ] Consider creating higher-level APIs: `Turn`, `Attack`, `DamageRider`
471
- - [ ] Add more comprehensive 5e rule examples
472
- - [ ] Performance improvements for DPR-only calculations
473
- - [ ] Multi-round and sustained vs nova simulations
474
- - [ ] Deeper integration with [dprcalc.com](https://dprcalc.com)
475
- - [ ] Blog posts and documentation
476
- - [ ] Grammar refinements and new YACC parsing
477
-
478
- ## 💬 Discuss
479
-
480
- Join our [Discord](https://dprcalc.com/discord) to discuss this library and more!
481
-
482
- ## 🤝 Contributing
483
-
484
- Clone the repo and install dependencies:
485
-
486
- ```bash
487
- git clone https://github.com/yipe/dice.git
488
- cd dice
489
- yarn install
490
- ```
491
-
492
- Run tests:
493
-
494
- ```bash
495
- yarn test
496
- ```
497
-
498
- Run examples:
499
-
500
- ```bash
501
- yarn example
502
- ```
503
-
504
- ## 📜 License
505
-
506
- 2025 MIT © [Michael Margolis](https://github.com/yipe)
507
-
508
- ## ⚖️ Legal / Trademarks
509
-
510
- Wizards of the Coast, Dungeons & Dragons, and their logos are trademarks of Wizards of the Coast LLC in the United States and other countries.
511
-
512
- © 2025 Wizards. All Rights Reserved.
513
-
514
- ## ❤️ Credits
515
-
516
- 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).
517
-
518
- Initial [TypeScript port](https://github.com/loginName1/dice-calculator-ts) expertly created by [loginName1](https://github.com/loginName1).
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 Michael Margolis
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.