@swrpg-online/dice 0.0.0-development
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/LICENSE +21 -0
- package/README.md +136 -0
- package/dist/bundle.cjs.js +2 -0
- package/dist/bundle.cjs.js.map +1 -0
- package/dist/bundle.esm.js +2 -0
- package/dist/bundle.esm.js.map +1 -0
- package/dist/bundle.umd.js +2 -0
- package/dist/bundle.umd.js.map +1 -0
- package/dist/cli.d.ts +5 -0
- package/dist/cli.js +168 -0
- package/dist/dice.d.ts +16 -0
- package/dist/dice.js +695 -0
- package/dist/hints.d.ts +11 -0
- package/dist/hints.js +251 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +10 -0
- package/dist/pools.d.ts +32 -0
- package/dist/pools.js +53 -0
- package/dist/types.d.ts +60 -0
- package/dist/types.js +13 -0
- package/package.json +98 -0
package/dist/dice.js
ADDED
|
@@ -0,0 +1,695 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.roll = exports.DEFAULT_MAX_TOTAL_DICE = exports.DEFAULT_MAX_DICE_PER_TYPE = void 0;
|
|
4
|
+
const hints_1 = require("./hints");
|
|
5
|
+
// Default dice limits for performance and security
|
|
6
|
+
exports.DEFAULT_MAX_DICE_PER_TYPE = 100;
|
|
7
|
+
exports.DEFAULT_MAX_TOTAL_DICE = 500;
|
|
8
|
+
const rollDie = (sides) => Math.floor(Math.random() * sides) + 1;
|
|
9
|
+
const boostDieResult = (roll) => {
|
|
10
|
+
switch (roll) {
|
|
11
|
+
case 3:
|
|
12
|
+
return {
|
|
13
|
+
successes: 1,
|
|
14
|
+
failures: 0,
|
|
15
|
+
advantages: 0,
|
|
16
|
+
threats: 0,
|
|
17
|
+
triumphs: 0,
|
|
18
|
+
despair: 0,
|
|
19
|
+
lightSide: 0,
|
|
20
|
+
darkSide: 0,
|
|
21
|
+
};
|
|
22
|
+
case 4:
|
|
23
|
+
return {
|
|
24
|
+
successes: 1,
|
|
25
|
+
failures: 0,
|
|
26
|
+
advantages: 1,
|
|
27
|
+
threats: 0,
|
|
28
|
+
triumphs: 0,
|
|
29
|
+
despair: 0,
|
|
30
|
+
lightSide: 0,
|
|
31
|
+
darkSide: 0,
|
|
32
|
+
};
|
|
33
|
+
case 5:
|
|
34
|
+
return {
|
|
35
|
+
successes: 0,
|
|
36
|
+
failures: 0,
|
|
37
|
+
advantages: 2,
|
|
38
|
+
threats: 0,
|
|
39
|
+
triumphs: 0,
|
|
40
|
+
despair: 0,
|
|
41
|
+
lightSide: 0,
|
|
42
|
+
darkSide: 0,
|
|
43
|
+
};
|
|
44
|
+
case 6:
|
|
45
|
+
return {
|
|
46
|
+
successes: 0,
|
|
47
|
+
failures: 0,
|
|
48
|
+
advantages: 1,
|
|
49
|
+
threats: 0,
|
|
50
|
+
triumphs: 0,
|
|
51
|
+
despair: 0,
|
|
52
|
+
lightSide: 0,
|
|
53
|
+
darkSide: 0,
|
|
54
|
+
};
|
|
55
|
+
default:
|
|
56
|
+
return {
|
|
57
|
+
successes: 0,
|
|
58
|
+
failures: 0,
|
|
59
|
+
advantages: 0,
|
|
60
|
+
threats: 0,
|
|
61
|
+
triumphs: 0,
|
|
62
|
+
despair: 0,
|
|
63
|
+
lightSide: 0,
|
|
64
|
+
darkSide: 0,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
const setBackDieResult = (roll) => {
|
|
69
|
+
switch (roll) {
|
|
70
|
+
case 3:
|
|
71
|
+
case 4:
|
|
72
|
+
return {
|
|
73
|
+
successes: 0,
|
|
74
|
+
failures: 1,
|
|
75
|
+
advantages: 0,
|
|
76
|
+
threats: 0,
|
|
77
|
+
triumphs: 0,
|
|
78
|
+
despair: 0,
|
|
79
|
+
lightSide: 0,
|
|
80
|
+
darkSide: 0,
|
|
81
|
+
};
|
|
82
|
+
case 5:
|
|
83
|
+
case 6:
|
|
84
|
+
return {
|
|
85
|
+
successes: 0,
|
|
86
|
+
failures: 0,
|
|
87
|
+
advantages: 0,
|
|
88
|
+
threats: 1,
|
|
89
|
+
triumphs: 0,
|
|
90
|
+
despair: 0,
|
|
91
|
+
lightSide: 0,
|
|
92
|
+
darkSide: 0,
|
|
93
|
+
};
|
|
94
|
+
default:
|
|
95
|
+
return {
|
|
96
|
+
successes: 0,
|
|
97
|
+
failures: 0,
|
|
98
|
+
advantages: 0,
|
|
99
|
+
threats: 0,
|
|
100
|
+
triumphs: 0,
|
|
101
|
+
despair: 0,
|
|
102
|
+
lightSide: 0,
|
|
103
|
+
darkSide: 0,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
const abilityDieResult = (roll) => {
|
|
108
|
+
switch (roll) {
|
|
109
|
+
case 2:
|
|
110
|
+
case 3:
|
|
111
|
+
return {
|
|
112
|
+
successes: 1,
|
|
113
|
+
failures: 0,
|
|
114
|
+
advantages: 0,
|
|
115
|
+
threats: 0,
|
|
116
|
+
triumphs: 0,
|
|
117
|
+
despair: 0,
|
|
118
|
+
lightSide: 0,
|
|
119
|
+
darkSide: 0,
|
|
120
|
+
};
|
|
121
|
+
case 4:
|
|
122
|
+
return {
|
|
123
|
+
successes: 2,
|
|
124
|
+
failures: 0,
|
|
125
|
+
advantages: 0,
|
|
126
|
+
threats: 0,
|
|
127
|
+
triumphs: 0,
|
|
128
|
+
despair: 0,
|
|
129
|
+
lightSide: 0,
|
|
130
|
+
darkSide: 0,
|
|
131
|
+
};
|
|
132
|
+
case 5:
|
|
133
|
+
case 6:
|
|
134
|
+
return {
|
|
135
|
+
successes: 0,
|
|
136
|
+
failures: 0,
|
|
137
|
+
advantages: 1,
|
|
138
|
+
threats: 0,
|
|
139
|
+
triumphs: 0,
|
|
140
|
+
despair: 0,
|
|
141
|
+
lightSide: 0,
|
|
142
|
+
darkSide: 0,
|
|
143
|
+
};
|
|
144
|
+
case 7:
|
|
145
|
+
return {
|
|
146
|
+
successes: 1,
|
|
147
|
+
failures: 0,
|
|
148
|
+
advantages: 1,
|
|
149
|
+
threats: 0,
|
|
150
|
+
triumphs: 0,
|
|
151
|
+
despair: 0,
|
|
152
|
+
lightSide: 0,
|
|
153
|
+
darkSide: 0,
|
|
154
|
+
};
|
|
155
|
+
case 8:
|
|
156
|
+
return {
|
|
157
|
+
successes: 0,
|
|
158
|
+
failures: 0,
|
|
159
|
+
advantages: 2,
|
|
160
|
+
threats: 0,
|
|
161
|
+
triumphs: 0,
|
|
162
|
+
despair: 0,
|
|
163
|
+
lightSide: 0,
|
|
164
|
+
darkSide: 0,
|
|
165
|
+
};
|
|
166
|
+
default:
|
|
167
|
+
return {
|
|
168
|
+
successes: 0,
|
|
169
|
+
failures: 0,
|
|
170
|
+
advantages: 0,
|
|
171
|
+
threats: 0,
|
|
172
|
+
triumphs: 0,
|
|
173
|
+
despair: 0,
|
|
174
|
+
lightSide: 0,
|
|
175
|
+
darkSide: 0,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
const difficultyDieResult = (roll) => {
|
|
180
|
+
switch (roll) {
|
|
181
|
+
case 2:
|
|
182
|
+
return {
|
|
183
|
+
successes: 0,
|
|
184
|
+
failures: 1,
|
|
185
|
+
advantages: 0,
|
|
186
|
+
threats: 0,
|
|
187
|
+
triumphs: 0,
|
|
188
|
+
despair: 0,
|
|
189
|
+
lightSide: 0,
|
|
190
|
+
darkSide: 0,
|
|
191
|
+
};
|
|
192
|
+
case 3:
|
|
193
|
+
return {
|
|
194
|
+
successes: 0,
|
|
195
|
+
failures: 2,
|
|
196
|
+
advantages: 0,
|
|
197
|
+
threats: 0,
|
|
198
|
+
triumphs: 0,
|
|
199
|
+
despair: 0,
|
|
200
|
+
lightSide: 0,
|
|
201
|
+
darkSide: 0,
|
|
202
|
+
};
|
|
203
|
+
case 4:
|
|
204
|
+
case 5:
|
|
205
|
+
case 6:
|
|
206
|
+
return {
|
|
207
|
+
successes: 0,
|
|
208
|
+
failures: 0,
|
|
209
|
+
advantages: 0,
|
|
210
|
+
threats: 1,
|
|
211
|
+
triumphs: 0,
|
|
212
|
+
despair: 0,
|
|
213
|
+
lightSide: 0,
|
|
214
|
+
darkSide: 0,
|
|
215
|
+
};
|
|
216
|
+
case 7:
|
|
217
|
+
return {
|
|
218
|
+
successes: 0,
|
|
219
|
+
failures: 0,
|
|
220
|
+
advantages: 0,
|
|
221
|
+
threats: 2,
|
|
222
|
+
triumphs: 0,
|
|
223
|
+
despair: 0,
|
|
224
|
+
lightSide: 0,
|
|
225
|
+
darkSide: 0,
|
|
226
|
+
};
|
|
227
|
+
case 8:
|
|
228
|
+
return {
|
|
229
|
+
successes: 0,
|
|
230
|
+
failures: 1,
|
|
231
|
+
advantages: 0,
|
|
232
|
+
threats: 1,
|
|
233
|
+
triumphs: 0,
|
|
234
|
+
despair: 0,
|
|
235
|
+
lightSide: 0,
|
|
236
|
+
darkSide: 0,
|
|
237
|
+
};
|
|
238
|
+
default:
|
|
239
|
+
return {
|
|
240
|
+
successes: 0,
|
|
241
|
+
failures: 0,
|
|
242
|
+
advantages: 0,
|
|
243
|
+
threats: 0,
|
|
244
|
+
triumphs: 0,
|
|
245
|
+
despair: 0,
|
|
246
|
+
lightSide: 0,
|
|
247
|
+
darkSide: 0,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
const proficiencyDieResult = (roll) => {
|
|
252
|
+
switch (roll) {
|
|
253
|
+
case 2:
|
|
254
|
+
case 3:
|
|
255
|
+
return {
|
|
256
|
+
successes: 1,
|
|
257
|
+
failures: 0,
|
|
258
|
+
advantages: 0,
|
|
259
|
+
threats: 0,
|
|
260
|
+
triumphs: 0,
|
|
261
|
+
despair: 0,
|
|
262
|
+
lightSide: 0,
|
|
263
|
+
darkSide: 0,
|
|
264
|
+
};
|
|
265
|
+
case 4:
|
|
266
|
+
case 5:
|
|
267
|
+
return {
|
|
268
|
+
successes: 2,
|
|
269
|
+
failures: 0,
|
|
270
|
+
advantages: 0,
|
|
271
|
+
threats: 0,
|
|
272
|
+
triumphs: 0,
|
|
273
|
+
despair: 0,
|
|
274
|
+
lightSide: 0,
|
|
275
|
+
darkSide: 0,
|
|
276
|
+
};
|
|
277
|
+
case 6:
|
|
278
|
+
return {
|
|
279
|
+
successes: 0,
|
|
280
|
+
failures: 0,
|
|
281
|
+
advantages: 1,
|
|
282
|
+
threats: 0,
|
|
283
|
+
triumphs: 0,
|
|
284
|
+
despair: 0,
|
|
285
|
+
lightSide: 0,
|
|
286
|
+
darkSide: 0,
|
|
287
|
+
};
|
|
288
|
+
case 7:
|
|
289
|
+
case 8:
|
|
290
|
+
case 9:
|
|
291
|
+
return {
|
|
292
|
+
successes: 1,
|
|
293
|
+
failures: 0,
|
|
294
|
+
advantages: 1,
|
|
295
|
+
threats: 0,
|
|
296
|
+
triumphs: 0,
|
|
297
|
+
despair: 0,
|
|
298
|
+
lightSide: 0,
|
|
299
|
+
darkSide: 0,
|
|
300
|
+
};
|
|
301
|
+
case 10:
|
|
302
|
+
case 11:
|
|
303
|
+
return {
|
|
304
|
+
successes: 0,
|
|
305
|
+
failures: 0,
|
|
306
|
+
advantages: 2,
|
|
307
|
+
threats: 0,
|
|
308
|
+
triumphs: 0,
|
|
309
|
+
despair: 0,
|
|
310
|
+
lightSide: 0,
|
|
311
|
+
darkSide: 0,
|
|
312
|
+
};
|
|
313
|
+
case 12:
|
|
314
|
+
return {
|
|
315
|
+
successes: 0,
|
|
316
|
+
failures: 0,
|
|
317
|
+
advantages: 0,
|
|
318
|
+
threats: 0,
|
|
319
|
+
triumphs: 1,
|
|
320
|
+
despair: 0,
|
|
321
|
+
lightSide: 0,
|
|
322
|
+
darkSide: 0,
|
|
323
|
+
};
|
|
324
|
+
default:
|
|
325
|
+
return {
|
|
326
|
+
successes: 0,
|
|
327
|
+
failures: 0,
|
|
328
|
+
advantages: 0,
|
|
329
|
+
threats: 0,
|
|
330
|
+
triumphs: 0,
|
|
331
|
+
despair: 0,
|
|
332
|
+
lightSide: 0,
|
|
333
|
+
darkSide: 0,
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
};
|
|
337
|
+
const challengeDieResult = (roll) => {
|
|
338
|
+
switch (roll) {
|
|
339
|
+
case 2:
|
|
340
|
+
case 3:
|
|
341
|
+
return {
|
|
342
|
+
successes: 0,
|
|
343
|
+
failures: 1,
|
|
344
|
+
advantages: 0,
|
|
345
|
+
threats: 0,
|
|
346
|
+
triumphs: 0,
|
|
347
|
+
despair: 0,
|
|
348
|
+
lightSide: 0,
|
|
349
|
+
darkSide: 0,
|
|
350
|
+
};
|
|
351
|
+
case 4:
|
|
352
|
+
case 5:
|
|
353
|
+
return {
|
|
354
|
+
successes: 0,
|
|
355
|
+
failures: 2,
|
|
356
|
+
advantages: 0,
|
|
357
|
+
threats: 0,
|
|
358
|
+
triumphs: 0,
|
|
359
|
+
despair: 0,
|
|
360
|
+
lightSide: 0,
|
|
361
|
+
darkSide: 0,
|
|
362
|
+
};
|
|
363
|
+
case 6:
|
|
364
|
+
case 7:
|
|
365
|
+
return {
|
|
366
|
+
successes: 0,
|
|
367
|
+
failures: 0,
|
|
368
|
+
advantages: 0,
|
|
369
|
+
threats: 1,
|
|
370
|
+
triumphs: 0,
|
|
371
|
+
despair: 0,
|
|
372
|
+
lightSide: 0,
|
|
373
|
+
darkSide: 0,
|
|
374
|
+
};
|
|
375
|
+
case 8:
|
|
376
|
+
case 9:
|
|
377
|
+
return {
|
|
378
|
+
successes: 0,
|
|
379
|
+
failures: 1,
|
|
380
|
+
advantages: 0,
|
|
381
|
+
threats: 1,
|
|
382
|
+
triumphs: 0,
|
|
383
|
+
despair: 0,
|
|
384
|
+
lightSide: 0,
|
|
385
|
+
darkSide: 0,
|
|
386
|
+
};
|
|
387
|
+
case 10:
|
|
388
|
+
case 11:
|
|
389
|
+
return {
|
|
390
|
+
successes: 0,
|
|
391
|
+
failures: 0,
|
|
392
|
+
advantages: 0,
|
|
393
|
+
threats: 2,
|
|
394
|
+
triumphs: 0,
|
|
395
|
+
despair: 0,
|
|
396
|
+
lightSide: 0,
|
|
397
|
+
darkSide: 0,
|
|
398
|
+
};
|
|
399
|
+
case 12:
|
|
400
|
+
return {
|
|
401
|
+
successes: 0,
|
|
402
|
+
failures: 0,
|
|
403
|
+
advantages: 0,
|
|
404
|
+
threats: 0,
|
|
405
|
+
triumphs: 0,
|
|
406
|
+
despair: 1,
|
|
407
|
+
lightSide: 0,
|
|
408
|
+
darkSide: 0,
|
|
409
|
+
};
|
|
410
|
+
default:
|
|
411
|
+
return {
|
|
412
|
+
successes: 0,
|
|
413
|
+
failures: 0,
|
|
414
|
+
advantages: 0,
|
|
415
|
+
threats: 0,
|
|
416
|
+
triumphs: 0,
|
|
417
|
+
despair: 0,
|
|
418
|
+
lightSide: 0,
|
|
419
|
+
darkSide: 0,
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
};
|
|
423
|
+
const forceDieResult = (roll) => {
|
|
424
|
+
switch (roll) {
|
|
425
|
+
case 1:
|
|
426
|
+
case 2:
|
|
427
|
+
case 3:
|
|
428
|
+
case 4:
|
|
429
|
+
case 5:
|
|
430
|
+
return {
|
|
431
|
+
successes: 0,
|
|
432
|
+
failures: 0,
|
|
433
|
+
advantages: 0,
|
|
434
|
+
threats: 0,
|
|
435
|
+
triumphs: 0,
|
|
436
|
+
despair: 0,
|
|
437
|
+
lightSide: 1,
|
|
438
|
+
darkSide: 0,
|
|
439
|
+
};
|
|
440
|
+
case 6:
|
|
441
|
+
case 7:
|
|
442
|
+
return {
|
|
443
|
+
successes: 0,
|
|
444
|
+
failures: 0,
|
|
445
|
+
advantages: 0,
|
|
446
|
+
threats: 0,
|
|
447
|
+
triumphs: 0,
|
|
448
|
+
despair: 0,
|
|
449
|
+
lightSide: 2,
|
|
450
|
+
darkSide: 0,
|
|
451
|
+
};
|
|
452
|
+
case 8:
|
|
453
|
+
case 9:
|
|
454
|
+
case 10:
|
|
455
|
+
case 11:
|
|
456
|
+
return {
|
|
457
|
+
successes: 0,
|
|
458
|
+
failures: 0,
|
|
459
|
+
advantages: 0,
|
|
460
|
+
threats: 0,
|
|
461
|
+
triumphs: 0,
|
|
462
|
+
despair: 0,
|
|
463
|
+
lightSide: 0,
|
|
464
|
+
darkSide: 1,
|
|
465
|
+
};
|
|
466
|
+
case 12:
|
|
467
|
+
return {
|
|
468
|
+
successes: 0,
|
|
469
|
+
failures: 0,
|
|
470
|
+
advantages: 0,
|
|
471
|
+
threats: 0,
|
|
472
|
+
triumphs: 0,
|
|
473
|
+
despair: 0,
|
|
474
|
+
lightSide: 0,
|
|
475
|
+
darkSide: 2,
|
|
476
|
+
};
|
|
477
|
+
default:
|
|
478
|
+
return {
|
|
479
|
+
successes: 0,
|
|
480
|
+
failures: 0,
|
|
481
|
+
advantages: 0,
|
|
482
|
+
threats: 0,
|
|
483
|
+
triumphs: 0,
|
|
484
|
+
despair: 0,
|
|
485
|
+
lightSide: 0,
|
|
486
|
+
darkSide: 0,
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
};
|
|
490
|
+
const sumResults = (results, options) => {
|
|
491
|
+
const sums = results.reduce((acc, curr) => ({
|
|
492
|
+
successes: acc.successes + curr.successes,
|
|
493
|
+
failures: acc.failures + curr.failures,
|
|
494
|
+
advantages: acc.advantages + curr.advantages,
|
|
495
|
+
threats: acc.threats + curr.threats,
|
|
496
|
+
triumphs: acc.triumphs + curr.triumphs,
|
|
497
|
+
despair: acc.despair + curr.despair,
|
|
498
|
+
lightSide: acc.lightSide + (curr.lightSide || 0),
|
|
499
|
+
darkSide: acc.darkSide + (curr.darkSide || 0),
|
|
500
|
+
}), {
|
|
501
|
+
successes: 0,
|
|
502
|
+
failures: 0,
|
|
503
|
+
advantages: 0,
|
|
504
|
+
threats: 0,
|
|
505
|
+
triumphs: 0,
|
|
506
|
+
despair: 0,
|
|
507
|
+
lightSide: 0,
|
|
508
|
+
darkSide: 0,
|
|
509
|
+
});
|
|
510
|
+
let netSuccesses = 0;
|
|
511
|
+
let netFailures = 0;
|
|
512
|
+
if (sums.successes === sums.failures) {
|
|
513
|
+
netSuccesses = 0;
|
|
514
|
+
netFailures = 0;
|
|
515
|
+
}
|
|
516
|
+
else if (sums.successes > sums.failures) {
|
|
517
|
+
netSuccesses = sums.successes - sums.failures;
|
|
518
|
+
}
|
|
519
|
+
else {
|
|
520
|
+
netFailures = sums.failures - sums.successes;
|
|
521
|
+
}
|
|
522
|
+
const result = {
|
|
523
|
+
successes: netSuccesses,
|
|
524
|
+
failures: netFailures,
|
|
525
|
+
advantages: sums.advantages,
|
|
526
|
+
threats: sums.threats,
|
|
527
|
+
triumphs: sums.triumphs,
|
|
528
|
+
despair: sums.despair,
|
|
529
|
+
lightSide: sums.lightSide,
|
|
530
|
+
darkSide: sums.darkSide,
|
|
531
|
+
};
|
|
532
|
+
return result;
|
|
533
|
+
};
|
|
534
|
+
/**
|
|
535
|
+
* Rolls a dice pool and returns the results.
|
|
536
|
+
*
|
|
537
|
+
* @param pool - The dice pool to roll
|
|
538
|
+
* @param options - Optional roll configuration including dice limits
|
|
539
|
+
* @returns The roll results with detailed die information and summary
|
|
540
|
+
* @throws {Error} If dice counts exceed configured limits
|
|
541
|
+
*
|
|
542
|
+
* Default limits:
|
|
543
|
+
* - Max dice per type: 100 (configurable via options.maxDicePerType)
|
|
544
|
+
* - Max total dice: 500 (configurable via options.maxTotalDice)
|
|
545
|
+
*/
|
|
546
|
+
const roll = (pool, options) => {
|
|
547
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
548
|
+
const boostCount = (_a = pool.boostDice) !== null && _a !== void 0 ? _a : 0;
|
|
549
|
+
const abilityCount = (_b = pool.abilityDice) !== null && _b !== void 0 ? _b : 0;
|
|
550
|
+
const proficiencyCount = (_c = pool.proficiencyDice) !== null && _c !== void 0 ? _c : 0;
|
|
551
|
+
const setBackCount = (_d = pool.setBackDice) !== null && _d !== void 0 ? _d : 0;
|
|
552
|
+
const difficultyCount = (_e = pool.difficultyDice) !== null && _e !== void 0 ? _e : 0;
|
|
553
|
+
const challengeCount = (_f = pool.challengeDice) !== null && _f !== void 0 ? _f : 0;
|
|
554
|
+
const forceCount = (_g = pool.forceDice) !== null && _g !== void 0 ? _g : 0;
|
|
555
|
+
// Get limits from options or use defaults
|
|
556
|
+
const maxDicePerType = (_h = options === null || options === void 0 ? void 0 : options.maxDicePerType) !== null && _h !== void 0 ? _h : exports.DEFAULT_MAX_DICE_PER_TYPE;
|
|
557
|
+
const maxTotalDice = (_j = options === null || options === void 0 ? void 0 : options.maxTotalDice) !== null && _j !== void 0 ? _j : exports.DEFAULT_MAX_TOTAL_DICE;
|
|
558
|
+
// Ensure all dice counts are non-negative and apply per-type limits
|
|
559
|
+
const sanitizedPool = {
|
|
560
|
+
boostDice: Math.max(0, Math.min(boostCount, maxDicePerType)),
|
|
561
|
+
abilityDice: Math.max(0, Math.min(abilityCount, maxDicePerType)),
|
|
562
|
+
proficiencyDice: Math.max(0, Math.min(proficiencyCount, maxDicePerType)),
|
|
563
|
+
setBackDice: Math.max(0, Math.min(setBackCount, maxDicePerType)),
|
|
564
|
+
difficultyDice: Math.max(0, Math.min(difficultyCount, maxDicePerType)),
|
|
565
|
+
challengeDice: Math.max(0, Math.min(challengeCount, maxDicePerType)),
|
|
566
|
+
forceDice: Math.max(0, Math.min(forceCount, maxDicePerType)),
|
|
567
|
+
};
|
|
568
|
+
// Check if any dice counts exceeded the per-type limit
|
|
569
|
+
const exceedsPerTypeLimit = boostCount > maxDicePerType ||
|
|
570
|
+
abilityCount > maxDicePerType ||
|
|
571
|
+
proficiencyCount > maxDicePerType ||
|
|
572
|
+
setBackCount > maxDicePerType ||
|
|
573
|
+
difficultyCount > maxDicePerType ||
|
|
574
|
+
challengeCount > maxDicePerType ||
|
|
575
|
+
forceCount > maxDicePerType;
|
|
576
|
+
// Calculate total dice count
|
|
577
|
+
const totalDice = sanitizedPool.boostDice +
|
|
578
|
+
sanitizedPool.abilityDice +
|
|
579
|
+
sanitizedPool.proficiencyDice +
|
|
580
|
+
sanitizedPool.setBackDice +
|
|
581
|
+
sanitizedPool.difficultyDice +
|
|
582
|
+
sanitizedPool.challengeDice +
|
|
583
|
+
sanitizedPool.forceDice;
|
|
584
|
+
// Check total dice limit
|
|
585
|
+
if (totalDice > maxTotalDice) {
|
|
586
|
+
throw new Error(`Total dice count (${totalDice}) exceeds maximum allowed (${maxTotalDice}). ` +
|
|
587
|
+
`Please reduce the number of dice in your pool.`);
|
|
588
|
+
}
|
|
589
|
+
// Warn if per-type limits were exceeded (but continue with capped values)
|
|
590
|
+
if (exceedsPerTypeLimit && (options === null || options === void 0 ? void 0 : options.throwOnLimitExceeded)) {
|
|
591
|
+
const exceeded = [];
|
|
592
|
+
if (boostCount > maxDicePerType)
|
|
593
|
+
exceeded.push(`boost: ${boostCount}`);
|
|
594
|
+
if (abilityCount > maxDicePerType)
|
|
595
|
+
exceeded.push(`ability: ${abilityCount}`);
|
|
596
|
+
if (proficiencyCount > maxDicePerType)
|
|
597
|
+
exceeded.push(`proficiency: ${proficiencyCount}`);
|
|
598
|
+
if (setBackCount > maxDicePerType)
|
|
599
|
+
exceeded.push(`setback: ${setBackCount}`);
|
|
600
|
+
if (difficultyCount > maxDicePerType)
|
|
601
|
+
exceeded.push(`difficulty: ${difficultyCount}`);
|
|
602
|
+
if (challengeCount > maxDicePerType)
|
|
603
|
+
exceeded.push(`challenge: ${challengeCount}`);
|
|
604
|
+
if (forceCount > maxDicePerType)
|
|
605
|
+
exceeded.push(`force: ${forceCount}`);
|
|
606
|
+
throw new Error(`Dice counts exceed per-type limit (${maxDicePerType}): ${exceeded.join(", ")}. ` +
|
|
607
|
+
`Dice counts have been capped to the maximum.`);
|
|
608
|
+
}
|
|
609
|
+
const detailedResults = [];
|
|
610
|
+
// Roll boost dice
|
|
611
|
+
for (let i = 0; i < sanitizedPool.boostDice; i++) {
|
|
612
|
+
const roll = rollDie(6);
|
|
613
|
+
detailedResults.push({
|
|
614
|
+
type: "boost",
|
|
615
|
+
roll,
|
|
616
|
+
result: boostDieResult(roll),
|
|
617
|
+
});
|
|
618
|
+
}
|
|
619
|
+
// Roll ability dice
|
|
620
|
+
for (let i = 0; i < sanitizedPool.abilityDice; i++) {
|
|
621
|
+
const roll = rollDie(8);
|
|
622
|
+
detailedResults.push({
|
|
623
|
+
type: "ability",
|
|
624
|
+
roll,
|
|
625
|
+
result: abilityDieResult(roll),
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
// Roll proficiency dice
|
|
629
|
+
for (let i = 0; i < sanitizedPool.proficiencyDice; i++) {
|
|
630
|
+
const roll = rollDie(12);
|
|
631
|
+
detailedResults.push({
|
|
632
|
+
type: "proficiency",
|
|
633
|
+
roll,
|
|
634
|
+
result: proficiencyDieResult(roll),
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
// Roll setback dice
|
|
638
|
+
for (let i = 0; i < sanitizedPool.setBackDice; i++) {
|
|
639
|
+
const roll = rollDie(6);
|
|
640
|
+
detailedResults.push({
|
|
641
|
+
type: "setback",
|
|
642
|
+
roll,
|
|
643
|
+
result: setBackDieResult(roll),
|
|
644
|
+
});
|
|
645
|
+
}
|
|
646
|
+
// Roll difficulty dice
|
|
647
|
+
for (let i = 0; i < sanitizedPool.difficultyDice; i++) {
|
|
648
|
+
const roll = rollDie(8);
|
|
649
|
+
detailedResults.push({
|
|
650
|
+
type: "difficulty",
|
|
651
|
+
roll,
|
|
652
|
+
result: difficultyDieResult(roll),
|
|
653
|
+
});
|
|
654
|
+
}
|
|
655
|
+
// Roll challenge dice
|
|
656
|
+
for (let i = 0; i < sanitizedPool.challengeDice; i++) {
|
|
657
|
+
const roll = rollDie(12);
|
|
658
|
+
detailedResults.push({
|
|
659
|
+
type: "challenge",
|
|
660
|
+
roll,
|
|
661
|
+
result: challengeDieResult(roll),
|
|
662
|
+
});
|
|
663
|
+
}
|
|
664
|
+
// Roll force dice
|
|
665
|
+
for (let i = 0; i < sanitizedPool.forceDice; i++) {
|
|
666
|
+
const roll = rollDie(12);
|
|
667
|
+
detailedResults.push({
|
|
668
|
+
type: "force",
|
|
669
|
+
roll,
|
|
670
|
+
result: forceDieResult(roll),
|
|
671
|
+
});
|
|
672
|
+
}
|
|
673
|
+
const summary = sumResults(detailedResults.map((r) => r.result));
|
|
674
|
+
if (options === null || options === void 0 ? void 0 : options.hints) {
|
|
675
|
+
const applicableHints = hints_1.hints.filter((hint) => {
|
|
676
|
+
const { cost } = hint;
|
|
677
|
+
// For OR conditions: at least one option must be fully satisfied
|
|
678
|
+
// Each entry in cost represents an alternative way to pay for the hint
|
|
679
|
+
return Object.entries(cost).some(([symbol, required]) => {
|
|
680
|
+
const summaryKey = (symbol.toLowerCase() + "s");
|
|
681
|
+
const value = summary[summaryKey];
|
|
682
|
+
if (typeof value !== "number")
|
|
683
|
+
return false;
|
|
684
|
+
// Check if we have enough of this symbol type to afford the hint
|
|
685
|
+
return required !== undefined && required > 0 && value >= required;
|
|
686
|
+
});
|
|
687
|
+
});
|
|
688
|
+
summary.hints = applicableHints.map((hint) => `${(0, hints_1.hintCostDisplayText)(hint)} - ${hint.description}`);
|
|
689
|
+
}
|
|
690
|
+
return {
|
|
691
|
+
results: detailedResults,
|
|
692
|
+
summary: summary,
|
|
693
|
+
};
|
|
694
|
+
};
|
|
695
|
+
exports.roll = roll;
|
package/dist/hints.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type Symbol } from "./types";
|
|
2
|
+
export type CostType = {
|
|
3
|
+
[key in Symbol]?: number;
|
|
4
|
+
};
|
|
5
|
+
type Hint = {
|
|
6
|
+
description: string;
|
|
7
|
+
cost: CostType;
|
|
8
|
+
};
|
|
9
|
+
export declare const hints: Hint[];
|
|
10
|
+
export declare function hintCostDisplayText(hint: Hint): string;
|
|
11
|
+
export {};
|