@dicelette/core 1.24.0 → 1.24.2
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/dist/index.d.mts +51 -142
- package/dist/index.d.ts +51 -142
- package/dist/index.js +867 -760
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +870 -744
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -2
package/dist/index.mjs
CHANGED
|
@@ -1,13 +1,104 @@
|
|
|
1
|
-
// src/
|
|
2
|
-
import {
|
|
3
|
-
function
|
|
4
|
-
if (
|
|
5
|
-
|
|
1
|
+
// src/engine.ts
|
|
2
|
+
import { NumberGenerator } from "@dice-roller/rpg-dice-roller";
|
|
3
|
+
function getEngineId(engine) {
|
|
4
|
+
if (engine === NumberGenerator.engines.nodeCrypto) return "nodeCrypto";
|
|
5
|
+
if (engine === NumberGenerator.engines.nativeMath) return "nativeMath";
|
|
6
|
+
if (engine === NumberGenerator.engines.browserCrypto) return "browserCrypto";
|
|
7
|
+
try {
|
|
8
|
+
const e = engine;
|
|
9
|
+
if (e && typeof e === "object") {
|
|
10
|
+
if (typeof e.name === "string" && e.name) return e.name;
|
|
11
|
+
if (e.constructor?.name) return e.constructor.name;
|
|
12
|
+
}
|
|
13
|
+
} catch {
|
|
14
|
+
}
|
|
15
|
+
return "unknown";
|
|
16
|
+
}
|
|
17
|
+
function getEngine(engine) {
|
|
18
|
+
switch (engine) {
|
|
19
|
+
case "nativeMath":
|
|
20
|
+
return NumberGenerator.engines.nativeMath;
|
|
21
|
+
case "browserCrypto":
|
|
22
|
+
return NumberGenerator.engines.browserCrypto;
|
|
23
|
+
case "nodeCrypto":
|
|
24
|
+
return NumberGenerator.engines.nodeCrypto;
|
|
25
|
+
default:
|
|
26
|
+
return NumberGenerator.engines.nativeMath;
|
|
27
|
+
}
|
|
6
28
|
}
|
|
7
29
|
|
|
8
|
-
// src/
|
|
9
|
-
|
|
10
|
-
|
|
30
|
+
// src/errors.ts
|
|
31
|
+
var DiceTypeError = class extends Error {
|
|
32
|
+
dice;
|
|
33
|
+
cause;
|
|
34
|
+
method;
|
|
35
|
+
constructor(dice, cause, method) {
|
|
36
|
+
super(dice);
|
|
37
|
+
this.name = "Invalid_Dice_Type";
|
|
38
|
+
this.dice = dice;
|
|
39
|
+
this.cause = cause;
|
|
40
|
+
this.method = method;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
var FormulaError = class extends Error {
|
|
44
|
+
formula;
|
|
45
|
+
cause;
|
|
46
|
+
method;
|
|
47
|
+
constructor(formula, cause, method) {
|
|
48
|
+
super(formula);
|
|
49
|
+
this.name = "Invalid_Formula";
|
|
50
|
+
this.formula = formula;
|
|
51
|
+
this.cause = cause;
|
|
52
|
+
this.method = method;
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
var MaxGreater = class extends Error {
|
|
56
|
+
name;
|
|
57
|
+
value;
|
|
58
|
+
max;
|
|
59
|
+
constructor(value, max) {
|
|
60
|
+
super(value.toString());
|
|
61
|
+
this.name = "Max_Greater";
|
|
62
|
+
this.value = value;
|
|
63
|
+
this.max = max;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
var EmptyObjectError = class extends Error {
|
|
67
|
+
name;
|
|
68
|
+
constructor() {
|
|
69
|
+
super();
|
|
70
|
+
this.name = "Empty_Object";
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
var TooManyDice = class extends Error {
|
|
74
|
+
name;
|
|
75
|
+
constructor() {
|
|
76
|
+
super();
|
|
77
|
+
this.name = "Too_Many_Dice";
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
var TooManyStats = class extends Error {
|
|
81
|
+
name;
|
|
82
|
+
constructor() {
|
|
83
|
+
super();
|
|
84
|
+
this.name = "Too_Many_Stats";
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
var NoStatisticsError = class extends Error {
|
|
88
|
+
name;
|
|
89
|
+
constructor() {
|
|
90
|
+
super();
|
|
91
|
+
this.name = "No_Statistics";
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
// src/interfaces/index.ts
|
|
96
|
+
var SortOrder = /* @__PURE__ */ ((SortOrder2) => {
|
|
97
|
+
SortOrder2["Ascending"] = "sa";
|
|
98
|
+
SortOrder2["Descending"] = "sd";
|
|
99
|
+
SortOrder2["None"] = "none";
|
|
100
|
+
return SortOrder2;
|
|
101
|
+
})(SortOrder || {});
|
|
11
102
|
|
|
12
103
|
// src/interfaces/constant.ts
|
|
13
104
|
var COMMENT_REGEX = /\s+(#|\/{2}|\[|\/\*)(?<comment>.*)/gi;
|
|
@@ -17,418 +108,231 @@ var SYMBOL_DICE = "&";
|
|
|
17
108
|
var DETECT_CRITICAL = /\{\*?c[fs]:([<>=]|!=)+(.+?)}/gim;
|
|
18
109
|
var OPTIONAL_COMMENT = /\s+(#|\/{2}|\[|\/\*)?(?<comment>.*)/gi;
|
|
19
110
|
|
|
111
|
+
// src/interfaces/zod.ts
|
|
112
|
+
import { z } from "zod";
|
|
113
|
+
var statisticValueSchema = z.object({
|
|
114
|
+
max: z.number().transform((val) => val === 0 ? void 0 : val).optional(),
|
|
115
|
+
min: z.number().transform(
|
|
116
|
+
(val) => Number.isNaN(Number.parseInt(val, 10)) ? void 0 : val
|
|
117
|
+
).optional(),
|
|
118
|
+
combinaison: z.string().transform((str) => str.trim() || void 0).optional(),
|
|
119
|
+
exclude: z.boolean().optional()
|
|
120
|
+
}).superRefine((data, ctx) => {
|
|
121
|
+
if (data.max !== void 0 && data.min !== void 0 && data.max <= data.min) {
|
|
122
|
+
ctx.addIssue({
|
|
123
|
+
code: "custom",
|
|
124
|
+
message: `Max_Greater; ${data.min}; ${data.max}`,
|
|
125
|
+
path: ["max"]
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
var statisticSchema = z.record(z.string(), statisticValueSchema).optional().refine((stats) => !stats || Object.keys(stats).length <= 25, {
|
|
130
|
+
message: "TooManyStats"
|
|
131
|
+
});
|
|
132
|
+
var criticalSchema = z.object({
|
|
133
|
+
success: z.string().or(z.number().min(0)).optional(),
|
|
134
|
+
failure: z.string().or(z.number().min(0)).optional()
|
|
135
|
+
}).transform((values) => {
|
|
136
|
+
if (values.success === "") values.success = void 0;
|
|
137
|
+
if (values.failure === "") values.failure = void 0;
|
|
138
|
+
if (values.failure === 0) values.failure = void 0;
|
|
139
|
+
if (values.success === 0) values.success = void 0;
|
|
140
|
+
values.success = Number.parseInt(values.success, 10);
|
|
141
|
+
values.failure = Number.parseInt(values.failure, 10);
|
|
142
|
+
return values;
|
|
143
|
+
});
|
|
144
|
+
var criticalValueSchema = z.object({
|
|
145
|
+
sign: z.enum(["<", ">", "<=", ">=", "!=", "=="]),
|
|
146
|
+
value: z.string(),
|
|
147
|
+
onNaturalDice: z.boolean().optional(),
|
|
148
|
+
affectSkill: z.boolean().optional()
|
|
149
|
+
});
|
|
150
|
+
var damageSchema = z.record(z.string(), z.string()).optional().refine((stats) => !stats || Object.keys(stats).length <= 25, {
|
|
151
|
+
message: "TooManyDice"
|
|
152
|
+
});
|
|
153
|
+
var customCriticalSchema = z.record(z.string(), criticalValueSchema).optional().refine((stats) => !stats || Object.keys(stats).length <= 22, {
|
|
154
|
+
message: "TooManyDice"
|
|
155
|
+
});
|
|
156
|
+
var templateSchema = z.object({
|
|
157
|
+
charName: z.boolean().optional(),
|
|
158
|
+
statistics: statisticSchema,
|
|
159
|
+
total: z.number().min(0).transform((val) => val === 0 ? void 0 : val).optional(),
|
|
160
|
+
forceDistrib: z.boolean().optional(),
|
|
161
|
+
diceType: z.string().optional(),
|
|
162
|
+
critical: criticalSchema.optional(),
|
|
163
|
+
customCritical: customCriticalSchema,
|
|
164
|
+
damage: damageSchema
|
|
165
|
+
});
|
|
166
|
+
|
|
20
167
|
// src/roll.ts
|
|
21
|
-
import { DiceRoller, NumberGenerator } from "@dice-roller/rpg-dice-roller";
|
|
168
|
+
import { DiceRoller as DiceRoller3, NumberGenerator as NumberGenerator7 } from "@dice-roller/rpg-dice-roller";
|
|
169
|
+
import { evaluate as evaluate8 } from "mathjs";
|
|
170
|
+
|
|
171
|
+
// src/dice/bulk.ts
|
|
172
|
+
import { DiceRoller as DiceRoller2, NumberGenerator as NumberGenerator6 } from "@dice-roller/rpg-dice-roller";
|
|
173
|
+
import { evaluate as evaluate6 } from "mathjs";
|
|
174
|
+
|
|
175
|
+
// src/dice/compare.ts
|
|
176
|
+
import { NumberGenerator as NumberGenerator3 } from "@dice-roller/rpg-dice-roller";
|
|
22
177
|
import { evaluate as evaluate2 } from "mathjs";
|
|
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
|
-
if (bulkProcessContent.match(/\d+?#(.*)/)) {
|
|
52
|
-
const diceArray = bulkProcessContent.split("#");
|
|
53
|
-
const numberOfDice = Number.parseInt(diceArray[0], 10);
|
|
54
|
-
let diceToRoll = diceArray[1].replace(COMMENT_REGEX, "");
|
|
55
|
-
const commentsMatch = diceArray[1].match(COMMENT_REGEX);
|
|
56
|
-
const comments = commentsMatch ? commentsMatch[2] : void 0;
|
|
57
|
-
let curlyCompare;
|
|
58
|
-
if (isCurlyBulk) {
|
|
59
|
-
const curlyCompareRegex = diceToRoll.match(SIGN_REGEX_SPACE);
|
|
60
|
-
if (curlyCompareRegex) {
|
|
61
|
-
const compareSign = curlyCompareRegex[0].match(SIGN_REGEX)?.[0];
|
|
62
|
-
const compareValue = curlyCompareRegex[2];
|
|
63
|
-
if (compareSign && compareValue) {
|
|
64
|
-
curlyCompare = {
|
|
65
|
-
sign: compareSign,
|
|
66
|
-
value: Number.parseInt(compareValue, 10)
|
|
67
|
-
};
|
|
68
|
-
diceToRoll = diceToRoll.replace(SIGN_REGEX_SPACE, "");
|
|
69
|
-
}
|
|
178
|
+
|
|
179
|
+
// src/utils.ts
|
|
180
|
+
import { evaluate } from "mathjs";
|
|
181
|
+
import "uniformize";
|
|
182
|
+
import { NumberGenerator as NumberGenerator2 } from "@dice-roller/rpg-dice-roller";
|
|
183
|
+
import { Random } from "random-js";
|
|
184
|
+
function escapeRegex(string) {
|
|
185
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
186
|
+
}
|
|
187
|
+
function standardizeDice(dice) {
|
|
188
|
+
return dice.replace(
|
|
189
|
+
/(\[[^\]]+])|([^[]+)/g,
|
|
190
|
+
(_match, insideBrackets, outsideText) => insideBrackets ? insideBrackets : outsideText.standardize().replaceAll("df", "dF")
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
function generateStatsDice(originalDice, stats, dollarValue) {
|
|
194
|
+
let dice = originalDice.standardize();
|
|
195
|
+
if (stats && Object.keys(stats).length > 0) {
|
|
196
|
+
const statKeys = Object.keys(stats);
|
|
197
|
+
const partsRegex = /(\[[^\]]+])|([^[]+)/g;
|
|
198
|
+
let result = "";
|
|
199
|
+
let match;
|
|
200
|
+
while ((match = partsRegex.exec(dice)) !== null) {
|
|
201
|
+
const insideBrackets = match[1];
|
|
202
|
+
const outsideText = match[2];
|
|
203
|
+
if (insideBrackets) {
|
|
204
|
+
result += insideBrackets;
|
|
205
|
+
continue;
|
|
70
206
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
trivialComparisonDetected = isTrivialComparison(
|
|
94
|
-
maxTotal,
|
|
95
|
-
minTotal,
|
|
96
|
-
activeCompare
|
|
97
|
-
);
|
|
207
|
+
if (!outsideText) {
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
const tokenRegex = /(\$?[\p{L}\p{N}_]+)/gu;
|
|
211
|
+
let lastIndex = 0;
|
|
212
|
+
let tokenMatch;
|
|
213
|
+
while ((tokenMatch = tokenRegex.exec(outsideText)) !== null) {
|
|
214
|
+
result += outsideText.slice(lastIndex, tokenMatch.index);
|
|
215
|
+
const token = tokenMatch[0];
|
|
216
|
+
const tokenStd = token.standardize();
|
|
217
|
+
const diceMatch = /^(\d*)d(.+)$/i.exec(tokenStd);
|
|
218
|
+
if (diceMatch) {
|
|
219
|
+
const diceCount = diceMatch[1] || "";
|
|
220
|
+
const afterD = diceMatch[2];
|
|
221
|
+
let foundStatAfterD = false;
|
|
222
|
+
for (const key of statKeys) {
|
|
223
|
+
const keyStd = key.standardize();
|
|
224
|
+
if (afterD === keyStd) {
|
|
225
|
+
result += `${diceCount}d${stats[key].toString()}`;
|
|
226
|
+
foundStatAfterD = true;
|
|
227
|
+
break;
|
|
228
|
+
}
|
|
98
229
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
rollInstance,
|
|
103
|
-
explodingSuccess.sign,
|
|
104
|
-
explodingSuccess.value
|
|
105
|
-
);
|
|
106
|
-
successCount += successesForRoll;
|
|
107
|
-
let formattedRollOutput = rollOutput.replace(
|
|
108
|
-
explodingSuccess.normalizedSegment,
|
|
109
|
-
explodingSuccess.originalSegment
|
|
110
|
-
).replace(/=\s*-?\d+(?:\.\d+)?$/, `= ${successesForRoll}`);
|
|
111
|
-
formattedRollOutput = formatOutput(formattedRollOutput, false);
|
|
112
|
-
results.push(formattedRollOutput);
|
|
113
|
-
} else {
|
|
114
|
-
const rollTotal = rollInstance.total;
|
|
115
|
-
const isSuccess = evaluate2(
|
|
116
|
-
`${rollTotal}${activeCompare.sign}${activeCompare.value}`
|
|
117
|
-
);
|
|
118
|
-
if (isSuccess) successCount++;
|
|
119
|
-
results.push(formatOutput(rollOutput, isSuccess));
|
|
230
|
+
if (foundStatAfterD) {
|
|
231
|
+
lastIndex = tokenRegex.lastIndex;
|
|
232
|
+
continue;
|
|
120
233
|
}
|
|
121
|
-
} catch (error) {
|
|
122
|
-
throw new DiceTypeError(diceToRoll, "roll", error);
|
|
123
234
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
"<<=": "<=",
|
|
138
|
-
"==": "=",
|
|
139
|
-
"!==": "!=",
|
|
140
|
-
"!!==": "="
|
|
141
|
-
};
|
|
142
|
-
const mappedSign = signMap[doubledSign];
|
|
143
|
-
const mappedValue = Number.parseFloat(valueStr);
|
|
144
|
-
if (mappedSign && !Number.isNaN(mappedValue)) {
|
|
145
|
-
const resultsString = replaceUnwantedText(results.join("; "));
|
|
146
|
-
const flatValues = resultsString.split(";").flatMap((segment) => extractValuesFromOutput(segment));
|
|
147
|
-
if (mappedSign === "!=") {
|
|
148
|
-
const equalsCount = flatValues.filter((val) => val === mappedValue).length;
|
|
149
|
-
successCount = flatValues.length - equalsCount;
|
|
150
|
-
} else {
|
|
151
|
-
successCount = flatValues.filter(
|
|
152
|
-
(val) => matchComparison(mappedSign, val, mappedValue)
|
|
153
|
-
).length;
|
|
235
|
+
let bestKey = null;
|
|
236
|
+
let bestScore = 0;
|
|
237
|
+
for (const key of statKeys) {
|
|
238
|
+
const keyStd = key.standardize();
|
|
239
|
+
if (tokenStd === keyStd) {
|
|
240
|
+
bestKey = key;
|
|
241
|
+
bestScore = 1;
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
const score = similarityScore(tokenStd, keyStd);
|
|
245
|
+
if (score > bestScore) {
|
|
246
|
+
bestScore = score;
|
|
247
|
+
bestKey = key;
|
|
154
248
|
}
|
|
155
249
|
}
|
|
250
|
+
if (bestKey && bestScore >= 0.6) {
|
|
251
|
+
const statValue = stats[bestKey];
|
|
252
|
+
result += statValue.toString();
|
|
253
|
+
} else {
|
|
254
|
+
result += token;
|
|
255
|
+
}
|
|
256
|
+
lastIndex = tokenRegex.lastIndex;
|
|
156
257
|
}
|
|
157
|
-
|
|
158
|
-
const finalDice2 = isCurlyBulk ? `{${diceToRoll}${curlyCompare?.sign}${curlyCompare?.value}}` : diceToRoll;
|
|
159
|
-
const resultOutput2 = replaceUnwantedText(results.join("; "));
|
|
160
|
-
const finalTotal = explodingSuccess ? resultOutput2.split(";").flatMap((segment) => extractValuesFromOutput(segment)).filter(
|
|
161
|
-
(val) => matchComparison(explodingSuccess.sign, val, explodingSuccess.value)
|
|
162
|
-
).length : successCount;
|
|
163
|
-
return {
|
|
164
|
-
dice: explodingSuccess ? diceDisplay : finalDice2,
|
|
165
|
-
result: resultOutput2,
|
|
166
|
-
comment: comments,
|
|
167
|
-
compare: isCurlyBulk ? void 0 : compare,
|
|
168
|
-
modifier: modificator,
|
|
169
|
-
total: finalTotal,
|
|
170
|
-
trivial: trivialComparisonDetected ? true : void 0
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
const roller2 = new DiceRoller();
|
|
174
|
-
NumberGenerator.generator.engine = engine;
|
|
175
|
-
for (let i = 0; i < numberOfDice; i++) {
|
|
176
|
-
try {
|
|
177
|
-
roller2.roll(diceToRoll);
|
|
178
|
-
} catch (error) {
|
|
179
|
-
throw new DiceTypeError(diceToRoll, "roll", error);
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
const finalDice = isCurlyBulk ? `{${diceToRoll}}` : diceToRoll;
|
|
183
|
-
return {
|
|
184
|
-
dice: finalDice,
|
|
185
|
-
result: replaceUnwantedText(roller2.output),
|
|
186
|
-
comment: comments,
|
|
187
|
-
compare: compare ? compare : void 0,
|
|
188
|
-
modifier: modificator,
|
|
189
|
-
total: roller2.total
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
const roller = new DiceRoller();
|
|
193
|
-
NumberGenerator.generator.engine = engine;
|
|
194
|
-
let diceWithoutComment = dice.replace(COMMENT_REGEX, "").trimEnd();
|
|
195
|
-
if (sort) diceWithoutComment = `${diceWithoutComment}${sort}`;
|
|
196
|
-
let diceRoll;
|
|
197
|
-
try {
|
|
198
|
-
diceRoll = roller.roll(diceWithoutComment);
|
|
199
|
-
} catch (error) {
|
|
200
|
-
throw new DiceTypeError(diceWithoutComment, "roll", error);
|
|
201
|
-
}
|
|
202
|
-
if (compare && diceRoll) {
|
|
203
|
-
const currentRoll = Array.isArray(diceRoll) ? diceRoll[0] : diceRoll;
|
|
204
|
-
const maxDiceValue = currentRoll.maxTotal;
|
|
205
|
-
const minDiceValue = currentRoll.minTotal;
|
|
206
|
-
const trivial = isTrivialComparison(maxDiceValue, minDiceValue, compare);
|
|
207
|
-
compare.trivial = trivial ? true : void 0;
|
|
208
|
-
}
|
|
209
|
-
const commentMatch = dice.match(COMMENT_REGEX);
|
|
210
|
-
const comment = commentMatch ? commentMatch[2] : void 0;
|
|
211
|
-
let rerollCount = 0;
|
|
212
|
-
let res;
|
|
213
|
-
if (pity && compare) {
|
|
214
|
-
const currentRoll = Array.isArray(diceRoll) ? diceRoll[0] : diceRoll;
|
|
215
|
-
const maxPossible = currentRoll ? currentRoll.maxTotal : null;
|
|
216
|
-
const isComparisonPossible = maxPossible === null || canComparisonSucceed(maxPossible, compare);
|
|
217
|
-
if (isComparisonPossible) {
|
|
218
|
-
let isFail = evaluate2(`${roller.total}${compare.sign}${compare.value}`);
|
|
219
|
-
if (!isFail) {
|
|
220
|
-
const maxReroll = 100;
|
|
221
|
-
while (!isFail && rerollCount < maxReroll) {
|
|
222
|
-
try {
|
|
223
|
-
res = roll(diceWithoutComment, engine, false);
|
|
224
|
-
} catch (error) {
|
|
225
|
-
throw new DiceTypeError(diceWithoutComment, "roll", error);
|
|
226
|
-
}
|
|
227
|
-
rerollCount++;
|
|
228
|
-
if (res && res.total !== void 0)
|
|
229
|
-
isFail = evaluate2(`${res.total}${compare.sign}${compare.value}`);
|
|
230
|
-
}
|
|
231
|
-
if (res) {
|
|
232
|
-
return {
|
|
233
|
-
...res,
|
|
234
|
-
dice,
|
|
235
|
-
comment,
|
|
236
|
-
compare,
|
|
237
|
-
modifier: modificator,
|
|
238
|
-
pityLogs: rerollCount,
|
|
239
|
-
trivial: res.trivial ?? (compare?.trivial ? true : void 0)
|
|
240
|
-
};
|
|
241
|
-
}
|
|
242
|
-
}
|
|
258
|
+
result += outsideText.slice(lastIndex);
|
|
243
259
|
}
|
|
260
|
+
dice = result;
|
|
244
261
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
const successes = countExplodingSuccesses(
|
|
248
|
-
diceRoll,
|
|
249
|
-
explodingSuccess.sign,
|
|
250
|
-
explodingSuccess.value
|
|
251
|
-
);
|
|
252
|
-
resultOutput = resultOutput.replace(/=\s*-?\d+(?:\.\d+)?$/, `= ${successes}`).replace(explodingSuccess.normalizedSegment, explodingSuccess.originalSegment);
|
|
253
|
-
return {
|
|
254
|
-
dice: diceDisplay,
|
|
255
|
-
result: resultOutput,
|
|
256
|
-
comment,
|
|
257
|
-
compare: compare ? compare : void 0,
|
|
258
|
-
modifier: modificator,
|
|
259
|
-
total: successes,
|
|
260
|
-
pityLogs: rerollCount > 0 ? rerollCount : void 0,
|
|
261
|
-
trivial: compare?.trivial ? true : void 0
|
|
262
|
-
};
|
|
263
|
-
}
|
|
264
|
-
return {
|
|
265
|
-
dice,
|
|
266
|
-
result: resultOutput,
|
|
267
|
-
comment,
|
|
268
|
-
compare: compare ? compare : void 0,
|
|
269
|
-
modifier: modificator,
|
|
270
|
-
total: roller.total,
|
|
271
|
-
pityLogs: rerollCount > 0 ? rerollCount : void 0,
|
|
272
|
-
trivial: compare?.trivial ? true : void 0
|
|
273
|
-
};
|
|
262
|
+
if (dollarValue) dice = dice.replaceAll(/\$\B/g, dollarValue);
|
|
263
|
+
return replaceFormulaInDice(dice);
|
|
274
264
|
}
|
|
275
|
-
function
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
if (dice.match(/\d+?#(.*?)/))
|
|
283
|
-
throw new DiceTypeError(
|
|
284
|
-
dice,
|
|
285
|
-
"noBulkRoll",
|
|
286
|
-
"bulk roll are not allowed in shared rolls"
|
|
287
|
-
);
|
|
288
|
-
const results = [];
|
|
289
|
-
const mainComment = /\s+#(?<comment>.*)/.exec(dice)?.groups?.comment?.trimEnd() ?? void 0;
|
|
290
|
-
const split = dice.split(";");
|
|
291
|
-
const displayDice = diceDisplay ?? explodingSuccessMain?.originalDice ?? split[0];
|
|
292
|
-
let diceMain = fixParenthesis(split[0]);
|
|
293
|
-
const commentsRegex = /\[(?<comments>.*?)\]/gi;
|
|
294
|
-
const comments = formatComment(diceMain);
|
|
295
|
-
const diceMainWithoutComments = diceMain.replace(commentsRegex, "").trim();
|
|
296
|
-
const toHideRegex = /\((?<dice>[^)]+)\)/;
|
|
297
|
-
const toHide = toHideRegex.exec(diceMainWithoutComments)?.groups;
|
|
298
|
-
let hidden = false;
|
|
299
|
-
if (toHide?.dice) {
|
|
300
|
-
diceMain = toHide.dice;
|
|
301
|
-
hidden = true;
|
|
302
|
-
} else if (toHide) {
|
|
303
|
-
diceMain = "1d1";
|
|
304
|
-
hidden = true;
|
|
305
|
-
} else {
|
|
306
|
-
diceMain = diceMainWithoutComments;
|
|
307
|
-
}
|
|
308
|
-
const rollBounds = getRollBounds(diceMain, engine);
|
|
309
|
-
let diceResult = roll(diceMain, engine, pity);
|
|
310
|
-
if (!diceResult || !diceResult.total) {
|
|
311
|
-
if (hidden) {
|
|
312
|
-
diceResult = roll(fixParenthesis(split[0]), engine, pity);
|
|
313
|
-
hidden = false;
|
|
314
|
-
} else return void 0;
|
|
315
|
-
}
|
|
316
|
-
if (!diceResult || !diceResult.total) return void 0;
|
|
317
|
-
if (explodingSuccessMain && diceResult.result) {
|
|
318
|
-
const values = extractValuesFromOutput(diceResult.result);
|
|
319
|
-
diceResult.total = values.filter(
|
|
320
|
-
(v) => matchComparison(explodingSuccessMain.sign, v, explodingSuccessMain.value)
|
|
321
|
-
).length;
|
|
322
|
-
}
|
|
323
|
-
let aggregatedCompare = diceResult.compare;
|
|
324
|
-
let hasTrivialComparison = diceResult.compare?.trivial === true;
|
|
325
|
-
results.push(`\u203B ${comments}${diceResult.result}`);
|
|
326
|
-
let total = diceResult.total;
|
|
327
|
-
diceResult.comment = mainComment;
|
|
328
|
-
if (!total) {
|
|
329
|
-
return {
|
|
330
|
-
dice: displayDice,
|
|
331
|
-
result: results.join(";"),
|
|
332
|
-
comment: mainComment,
|
|
333
|
-
compare: aggregatedCompare,
|
|
334
|
-
modifier: diceResult.modifier,
|
|
335
|
-
total,
|
|
336
|
-
trivial: hasTrivialComparison ? true : void 0
|
|
337
|
-
};
|
|
338
|
-
}
|
|
339
|
-
for (let element of split.slice(1)) {
|
|
340
|
-
const comment = formatComment(element);
|
|
341
|
-
element = element.replaceAll(commentsRegex, "").replaceAll(OPTIONAL_COMMENT, "").trim();
|
|
342
|
-
let toRoll = element.replace(SYMBOL_DICE, `${diceResult.total}`);
|
|
343
|
-
const compareRegex = toRoll.match(SIGN_REGEX_SPACE);
|
|
344
|
-
if (compareRegex) {
|
|
345
|
-
const compareResult = compareSignFormule(
|
|
346
|
-
toRoll,
|
|
347
|
-
compareRegex,
|
|
348
|
-
element,
|
|
349
|
-
diceResult,
|
|
350
|
-
engine,
|
|
351
|
-
pity,
|
|
352
|
-
rollBounds
|
|
353
|
-
);
|
|
354
|
-
toRoll = compareResult.dice;
|
|
355
|
-
results.push(compareResult.results);
|
|
356
|
-
if (!aggregatedCompare && compareResult.compare)
|
|
357
|
-
aggregatedCompare = compareResult.compare;
|
|
358
|
-
if (compareResult.trivial) hasTrivialComparison = true;
|
|
359
|
-
} else {
|
|
360
|
-
const { formule, diceAll } = replaceText(
|
|
361
|
-
element,
|
|
362
|
-
diceResult.total,
|
|
363
|
-
diceResult.dice
|
|
364
|
-
);
|
|
265
|
+
function replaceFormulaInDice(dice) {
|
|
266
|
+
const formula = /(?<formula>\{{2}(.+?)}{2})/gim;
|
|
267
|
+
let match;
|
|
268
|
+
let modifiedDice = dice;
|
|
269
|
+
while ((match = formula.exec(dice)) !== null) {
|
|
270
|
+
if (match.groups?.formula) {
|
|
271
|
+
const formulae = match.groups.formula.replaceAll("{{", "").replaceAll("}}", "");
|
|
365
272
|
try {
|
|
366
|
-
const
|
|
367
|
-
|
|
368
|
-
total += Number.parseInt(evaluated, 10);
|
|
273
|
+
const result = evaluate(formulae);
|
|
274
|
+
modifiedDice = modifiedDice.replace(match.groups.formula, result.toString());
|
|
369
275
|
} catch (error) {
|
|
370
|
-
|
|
371
|
-
if (evaluated) {
|
|
372
|
-
results.push(
|
|
373
|
-
`\u25C8 ${comment}${diceAll}: ${evaluated.result.split(":").slice(1).join(":")}`
|
|
374
|
-
);
|
|
375
|
-
if (!aggregatedCompare && evaluated.compare)
|
|
376
|
-
aggregatedCompare = evaluated.compare;
|
|
377
|
-
if (evaluated.compare?.trivial) hasTrivialComparison = true;
|
|
378
|
-
} else results.push(`\u25C8 ${comment}${diceAll}: ${formule} = ${evaluated}`);
|
|
379
|
-
total += evaluated?.total ?? 0;
|
|
276
|
+
throw new FormulaError(match.groups.formula, "replaceFormulasInDice", error);
|
|
380
277
|
}
|
|
381
278
|
}
|
|
382
279
|
}
|
|
383
|
-
|
|
384
|
-
results.shift();
|
|
385
|
-
return {
|
|
386
|
-
dice: displayDice,
|
|
387
|
-
result: results.join(";"),
|
|
388
|
-
comment: mainComment,
|
|
389
|
-
compare: hasTrivialComparison && aggregatedCompare ? { ...aggregatedCompare, trivial: true } : aggregatedCompare,
|
|
390
|
-
modifier: diceResult.modifier,
|
|
391
|
-
total,
|
|
392
|
-
trivial: hasTrivialComparison ? true : void 0
|
|
393
|
-
};
|
|
280
|
+
return cleanedDice(modifiedDice);
|
|
394
281
|
}
|
|
395
|
-
function
|
|
396
|
-
|
|
397
|
-
element,
|
|
398
|
-
diceResult.total ?? 0,
|
|
399
|
-
diceResult.dice
|
|
400
|
-
);
|
|
401
|
-
const validSign = res ? "\u2713" : "\u2715";
|
|
402
|
-
const invertedSign = res ? compareResult.compare.sign : inverseSign(compareResult.compare.sign);
|
|
403
|
-
let evaluateRoll;
|
|
404
|
-
try {
|
|
405
|
-
evaluateRoll = evaluate2(compareResult.dice);
|
|
406
|
-
return `${validSign} ${diceAll}: ${formule} = ${evaluateRoll}${invertedSign}${compareResult.compare?.value}`;
|
|
407
|
-
} catch (error) {
|
|
408
|
-
const evaluateRoll2 = roll(compareResult.dice, engine, pity);
|
|
409
|
-
if (evaluateRoll2)
|
|
410
|
-
return `${validSign} ${diceAll}: ${evaluateRoll2.result.split(":").splice(1).join(":")}`;
|
|
411
|
-
return `${validSign} ${diceAll}: ${formule} = ${evaluateRoll2}${invertedSign}${compareResult.compare?.value}`;
|
|
412
|
-
}
|
|
282
|
+
function cleanedDice(dice) {
|
|
283
|
+
return dice.replaceAll("+-", "-").replaceAll("--", "+").replaceAll("++", "+").replaceAll("=>", ">=").replaceAll("=<", "<=").trimEnd();
|
|
413
284
|
}
|
|
414
|
-
function
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
285
|
+
function isNumber(value) {
|
|
286
|
+
return value !== void 0 && (typeof value === "number" || !Number.isNaN(Number(value)) && typeof value === "string" && value.trim().length > 0);
|
|
287
|
+
}
|
|
288
|
+
function replaceExpByRandom(dice, engine = NumberGenerator2.engines.nodeCrypto) {
|
|
289
|
+
const diceRegex = /\{exp( ?\|\| ?(?<default>\d+))?}/gi;
|
|
290
|
+
return dice.replace(diceRegex, (_match, _p1, _p2, _offset, _string, groups) => {
|
|
291
|
+
const defaultValue = groups?.default;
|
|
292
|
+
return defaultValue ?? randomInt(1, 999, engine).toString();
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
function randomInt(min, max, engine = NumberGenerator2.engines.nodeCrypto, rng) {
|
|
296
|
+
if (!rng) rng = new Random(engine || void 0);
|
|
297
|
+
return rng.integer(min, max);
|
|
298
|
+
}
|
|
299
|
+
function levenshteinDistance(a, b) {
|
|
300
|
+
if (a === b) return 0;
|
|
301
|
+
const al = a.length;
|
|
302
|
+
const bl = b.length;
|
|
303
|
+
if (al === 0) return bl;
|
|
304
|
+
if (bl === 0) return al;
|
|
305
|
+
const v0 = new Array(bl + 1);
|
|
306
|
+
const v1 = new Array(bl + 1);
|
|
307
|
+
for (let i = 0; i <= bl; i++) v0[i] = i;
|
|
308
|
+
for (let i = 0; i < al; i++) {
|
|
309
|
+
v1[0] = i + 1;
|
|
310
|
+
for (let j = 0; j < bl; j++) {
|
|
311
|
+
const cost = a[i] === b[j] ? 0 : 1;
|
|
312
|
+
v1[j + 1] = Math.min(v1[j] + 1, v0[j + 1] + 1, v0[j] + cost);
|
|
425
313
|
}
|
|
314
|
+
for (let j = 0; j <= bl; j++) v0[j] = v1[j];
|
|
426
315
|
}
|
|
427
|
-
return
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
316
|
+
return v1[bl];
|
|
317
|
+
}
|
|
318
|
+
function similarityScore(a, b) {
|
|
319
|
+
const la = a.length;
|
|
320
|
+
const lb = b.length;
|
|
321
|
+
if (la === 0 && lb === 0) return 1;
|
|
322
|
+
const dist = levenshteinDistance(a, b);
|
|
323
|
+
const max = Math.max(la, lb);
|
|
324
|
+
return 1 - dist / max;
|
|
325
|
+
}
|
|
326
|
+
function createCriticalCustom(dice, customCritical, template, engine = NumberGenerator2.engines.nodeCrypto) {
|
|
327
|
+
const compareRegex = dice.match(SIGN_REGEX_SPACE);
|
|
328
|
+
let customDice = dice;
|
|
329
|
+
const compareValue = diceTypeRandomParse(customCritical.value, template, engine);
|
|
330
|
+
if (compareValue.includes("$"))
|
|
331
|
+
throw new DiceTypeError(compareValue, "createCriticalCustom");
|
|
332
|
+
const comparaison = `${customCritical.sign}${compareValue}`;
|
|
333
|
+
if (compareRegex) customDice = customDice.replace(SIGN_REGEX_SPACE, comparaison);
|
|
334
|
+
else customDice += comparaison;
|
|
335
|
+
return diceTypeRandomParse(customDice, template, engine);
|
|
432
336
|
}
|
|
433
337
|
|
|
434
338
|
// src/dice/compare.ts
|
|
@@ -462,18 +366,37 @@ function canComparisonFail(maxRollValue, compare, minRollValue = 1) {
|
|
|
462
366
|
return true;
|
|
463
367
|
}
|
|
464
368
|
}
|
|
465
|
-
function
|
|
466
|
-
if (
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
const
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
369
|
+
function rollCompare(value, engine = NumberGenerator3.engines.nodeCrypto, pity) {
|
|
370
|
+
if (isNumber(value)) return { value: Number.parseInt(value, 10) };
|
|
371
|
+
if (!value || typeof value === "string" && value.trim() === "") {
|
|
372
|
+
return { value: 0, diceResult: value };
|
|
373
|
+
}
|
|
374
|
+
const rollComp = roll(value, engine, pity);
|
|
375
|
+
if (!rollComp?.total) {
|
|
376
|
+
try {
|
|
377
|
+
return { value: evaluate2(value), diceResult: value };
|
|
378
|
+
} catch (error) {
|
|
379
|
+
return { value: 0, diceResult: value };
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
return {
|
|
383
|
+
dice: value,
|
|
384
|
+
value: rollComp.total,
|
|
385
|
+
diceResult: rollComp?.result
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
function getCompare(dice, compareRegex, engine = NumberGenerator3.engines.nodeCrypto, pity) {
|
|
389
|
+
if (dice.match(/((\{.*,(.*)+\}|([><=!]+\d+f))([><=]|!=)+\d+\}?)|\{(.*)(([><=]|!=)+).*\}/))
|
|
390
|
+
return { dice, compare: void 0 };
|
|
391
|
+
dice = dice.replace(SIGN_REGEX_SPACE, "");
|
|
392
|
+
let compare;
|
|
393
|
+
const calc = compareRegex[2];
|
|
394
|
+
const sign = calc.match(/[+-/*^]/)?.[0];
|
|
395
|
+
const compareSign = compareRegex[0].match(SIGN_REGEX)?.[0];
|
|
396
|
+
if (sign) {
|
|
397
|
+
const toCalc = calc.replace(SIGN_REGEX, "").replace(/\s/g, "").replace(/;(.*)/, "");
|
|
475
398
|
const rCompare = rollCompare(toCalc, engine, pity);
|
|
476
|
-
const total =
|
|
399
|
+
const total = evaluate2(rCompare.value.toString());
|
|
477
400
|
dice = dice.replace(SIGN_REGEX_SPACE, `${compareSign}${total}`);
|
|
478
401
|
compare = {
|
|
479
402
|
sign: compareSign,
|
|
@@ -515,11 +438,11 @@ function canComparisonSucceed(maxRollValue, compare, minRollValue) {
|
|
|
515
438
|
}
|
|
516
439
|
|
|
517
440
|
// src/dice/exploding.ts
|
|
518
|
-
import { evaluate as
|
|
441
|
+
import { evaluate as evaluate4 } from "mathjs";
|
|
519
442
|
|
|
520
443
|
// src/dice/signs.ts
|
|
521
|
-
import { NumberGenerator as
|
|
522
|
-
import { evaluate as
|
|
444
|
+
import { NumberGenerator as NumberGenerator4 } from "@dice-roller/rpg-dice-roller";
|
|
445
|
+
import { evaluate as evaluate3 } from "mathjs";
|
|
523
446
|
|
|
524
447
|
// src/dice/replace.ts
|
|
525
448
|
function replaceUnwantedText(dice) {
|
|
@@ -588,14 +511,14 @@ function inverseSign(sign) {
|
|
|
588
511
|
return "==";
|
|
589
512
|
}
|
|
590
513
|
}
|
|
591
|
-
function compareSignFormule(toRoll, compareRegex, element, diceResult, engine =
|
|
514
|
+
function compareSignFormule(toRoll, compareRegex, element, diceResult, engine = NumberGenerator4.engines.nodeCrypto, pity, rollBounds) {
|
|
592
515
|
let results = "";
|
|
593
516
|
let trivial = false;
|
|
594
517
|
const compareResult = getCompare(toRoll, compareRegex, engine);
|
|
595
518
|
const toCompare = `${compareResult.dice}${compareResult.compare?.sign}${compareResult.compare?.value}`;
|
|
596
519
|
let res;
|
|
597
520
|
try {
|
|
598
|
-
res =
|
|
521
|
+
res = evaluate3(toCompare);
|
|
599
522
|
} catch (error) {
|
|
600
523
|
res = roll(toCompare, engine, pity);
|
|
601
524
|
}
|
|
@@ -607,7 +530,7 @@ function compareSignFormule(toRoll, compareRegex, element, diceResult, engine =
|
|
|
607
530
|
} else if (res instanceof Object) {
|
|
608
531
|
const diceResult2 = res;
|
|
609
532
|
if (diceResult2.compare) {
|
|
610
|
-
const toEvaluate =
|
|
533
|
+
const toEvaluate = evaluate3(
|
|
611
534
|
`${diceResult2.total}${diceResult2.compare.sign}${diceResult2.compare.value}`
|
|
612
535
|
);
|
|
613
536
|
const sign = toEvaluate ? "\u2713" : "\u2715";
|
|
@@ -644,7 +567,7 @@ function normalizeExplodingSuccess(dice) {
|
|
|
644
567
|
let parsedValue = Number.parseFloat(valueStr);
|
|
645
568
|
if (Number.isNaN(parsedValue)) {
|
|
646
569
|
try {
|
|
647
|
-
parsedValue = Number.parseFloat(
|
|
570
|
+
parsedValue = Number.parseFloat(evaluate4(valueStr));
|
|
648
571
|
} catch (_error) {
|
|
649
572
|
parsedValue = 0;
|
|
650
573
|
}
|
|
@@ -679,7 +602,16 @@ function countExplodingSuccesses(diceRoll, sign, value) {
|
|
|
679
602
|
}
|
|
680
603
|
|
|
681
604
|
// src/dice/extract.ts
|
|
682
|
-
import { DiceRoller
|
|
605
|
+
import { DiceRoller, NumberGenerator as NumberGenerator5 } from "@dice-roller/rpg-dice-roller";
|
|
606
|
+
|
|
607
|
+
// src/dice/calculator.ts
|
|
608
|
+
import { evaluate as evaluate5 } from "mathjs";
|
|
609
|
+
function calculator(sign, value, total) {
|
|
610
|
+
if (sign === "^") sign = "**";
|
|
611
|
+
return evaluate5(`${total} ${sign} ${value}`);
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
// src/dice/extract.ts
|
|
683
615
|
function getModifier(dice) {
|
|
684
616
|
const modifier = dice.matchAll(/(\+|-|%|\/|\^|\*|\*{2})(\d+)/gi);
|
|
685
617
|
let modificator;
|
|
@@ -711,10 +643,10 @@ function extractValuesFromOutput(output) {
|
|
|
711
643
|
}
|
|
712
644
|
return values;
|
|
713
645
|
}
|
|
714
|
-
function getRollBounds(dice, engine =
|
|
646
|
+
function getRollBounds(dice, engine = NumberGenerator5.engines.nodeCrypto) {
|
|
715
647
|
try {
|
|
716
|
-
const roller = new
|
|
717
|
-
|
|
648
|
+
const roller = new DiceRoller();
|
|
649
|
+
NumberGenerator5.generator.engine = engine;
|
|
718
650
|
const rollResult = roller.roll(dice);
|
|
719
651
|
const instance = Array.isArray(rollResult) ? rollResult[0] : rollResult;
|
|
720
652
|
const { minTotal, maxTotal } = instance;
|
|
@@ -723,330 +655,543 @@ function getRollBounds(dice, engine = NumberGenerator4.engines.nodeCrypto) {
|
|
|
723
655
|
}
|
|
724
656
|
return void 0;
|
|
725
657
|
}
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
if (typeof e.name === "string" && e.name) return e.name;
|
|
737
|
-
if (e.constructor?.name) return e.constructor.name;
|
|
658
|
+
function setSortOrder(toRoll, sort) {
|
|
659
|
+
const sortRegex = /(sa|sd|s)/i;
|
|
660
|
+
if (sort && !toRoll.match(sortRegex)) {
|
|
661
|
+
const modifierComparisonRegex = /([+\-*/%^]\d+|([><=!]+\d+f)|([><=]|!=)+\d+)$/;
|
|
662
|
+
const match = toRoll.match(modifierComparisonRegex);
|
|
663
|
+
if (match) {
|
|
664
|
+
const index = match.index;
|
|
665
|
+
toRoll = `${toRoll.slice(0, index)}${sort}${toRoll.slice(index)}`;
|
|
666
|
+
} else {
|
|
667
|
+
toRoll += sort;
|
|
738
668
|
}
|
|
739
|
-
} catch {
|
|
740
669
|
}
|
|
741
|
-
return
|
|
670
|
+
return toRoll;
|
|
742
671
|
}
|
|
743
|
-
function
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
672
|
+
function prepareDice(diceInput) {
|
|
673
|
+
let dice = standardizeDice(replaceFormulaInDice(diceInput)).replace(/^\+/, "").replaceAll("=>", ">=").replaceAll("=<", "<=").trimStart();
|
|
674
|
+
dice = dice.replaceAll(DETECT_CRITICAL, "").trimEnd();
|
|
675
|
+
const explodingSuccess = normalizeExplodingSuccess(dice);
|
|
676
|
+
if (explodingSuccess) dice = explodingSuccess.dice;
|
|
677
|
+
let diceDisplay;
|
|
678
|
+
if (dice.includes(";")) {
|
|
679
|
+
const mainDice = dice.split(";")[0];
|
|
680
|
+
diceDisplay = explodingSuccess?.originalDice ?? mainDice;
|
|
681
|
+
} else {
|
|
682
|
+
diceDisplay = explodingSuccess?.originalDice ?? dice;
|
|
683
|
+
}
|
|
684
|
+
const curlyBulkMatch = dice.match(/^\{(\d+#.*)\}$/);
|
|
685
|
+
const isCurlyBulk = !!curlyBulkMatch;
|
|
686
|
+
const bulkContent = isCurlyBulk ? curlyBulkMatch[1] : "";
|
|
687
|
+
const isSharedRoll = dice.includes(";");
|
|
688
|
+
let isSharedCurly = false;
|
|
689
|
+
if (isSharedRoll && dice.match(/^\{.*;\s*.*\}$/)) {
|
|
690
|
+
dice = dice.slice(1, -1);
|
|
691
|
+
isSharedCurly = true;
|
|
692
|
+
diceDisplay = diceDisplay.slice(1);
|
|
753
693
|
}
|
|
694
|
+
let isSimpleCurly = false;
|
|
695
|
+
if (!isCurlyBulk && !isSharedRoll && dice.match(/^\{.*\}$/)) {
|
|
696
|
+
const innerContent = dice.slice(1, -1);
|
|
697
|
+
const hasModifiers = innerContent.match(/[+\-*/%^]/);
|
|
698
|
+
const hasComparison = innerContent.match(/(([><=!]+\d+f)|([><=]|!=)+\d+)/);
|
|
699
|
+
if (!(hasComparison && !hasModifiers)) {
|
|
700
|
+
dice = innerContent;
|
|
701
|
+
isSimpleCurly = true;
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
return {
|
|
705
|
+
dice,
|
|
706
|
+
diceDisplay,
|
|
707
|
+
explodingSuccess,
|
|
708
|
+
isSharedRoll,
|
|
709
|
+
isSharedCurly,
|
|
710
|
+
isCurlyBulk,
|
|
711
|
+
bulkContent,
|
|
712
|
+
isSimpleCurly
|
|
713
|
+
};
|
|
754
714
|
}
|
|
755
715
|
|
|
756
|
-
// src/
|
|
757
|
-
|
|
758
|
-
dice;
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
716
|
+
// src/dice/bulk.ts
|
|
717
|
+
function handleBulkRolls(dice, isCurlyBulk, bulkContent, compare, explodingSuccess, diceDisplay, engine, sort) {
|
|
718
|
+
const bulkProcessContent = isCurlyBulk ? bulkContent : dice;
|
|
719
|
+
const diceArray = bulkProcessContent.split("#");
|
|
720
|
+
const numberOfDice = Number.parseInt(diceArray[0], 10);
|
|
721
|
+
let diceToRoll = diceArray[1].replace(COMMENT_REGEX, "");
|
|
722
|
+
const commentsMatch = diceArray[1].match(COMMENT_REGEX);
|
|
723
|
+
const comments = commentsMatch ? commentsMatch[2] : void 0;
|
|
724
|
+
let curlyCompare;
|
|
725
|
+
if (isCurlyBulk) {
|
|
726
|
+
const curlyCompareRegex = diceToRoll.match(SIGN_REGEX_SPACE);
|
|
727
|
+
if (curlyCompareRegex) {
|
|
728
|
+
const compareSign = curlyCompareRegex[0].match(SIGN_REGEX)?.[0];
|
|
729
|
+
const compareValue = curlyCompareRegex[2];
|
|
730
|
+
if (compareSign && compareValue) {
|
|
731
|
+
curlyCompare = {
|
|
732
|
+
sign: compareSign,
|
|
733
|
+
value: Number.parseInt(compareValue, 10)
|
|
734
|
+
};
|
|
735
|
+
diceToRoll = diceToRoll.replace(SIGN_REGEX_SPACE, "");
|
|
736
|
+
}
|
|
737
|
+
}
|
|
767
738
|
}
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
739
|
+
diceToRoll = setSortOrder(diceToRoll, sort);
|
|
740
|
+
const activeCompare = compare || curlyCompare || (explodingSuccess ? { sign: explodingSuccess.sign, value: explodingSuccess.value } : void 0);
|
|
741
|
+
if (activeCompare) {
|
|
742
|
+
return handleBulkRollsWithComparison(
|
|
743
|
+
numberOfDice,
|
|
744
|
+
diceToRoll,
|
|
745
|
+
comments,
|
|
746
|
+
activeCompare,
|
|
747
|
+
explodingSuccess,
|
|
748
|
+
diceDisplay,
|
|
749
|
+
isCurlyBulk,
|
|
750
|
+
curlyCompare,
|
|
751
|
+
compare,
|
|
752
|
+
engine
|
|
753
|
+
);
|
|
779
754
|
}
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
this.value = value;
|
|
789
|
-
this.max = max;
|
|
755
|
+
const roller = new DiceRoller2();
|
|
756
|
+
NumberGenerator6.generator.engine = engine;
|
|
757
|
+
for (let i = 0; i < numberOfDice; i++) {
|
|
758
|
+
try {
|
|
759
|
+
roller.roll(diceToRoll);
|
|
760
|
+
} catch (error) {
|
|
761
|
+
throw new DiceTypeError(diceToRoll, "roll", error);
|
|
762
|
+
}
|
|
790
763
|
}
|
|
791
|
-
};
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
764
|
+
const finalDice = isCurlyBulk ? `{${diceToRoll}}` : diceToRoll;
|
|
765
|
+
const modificator = getModifier(dice);
|
|
766
|
+
return {
|
|
767
|
+
dice: finalDice,
|
|
768
|
+
result: replaceUnwantedText(roller.output),
|
|
769
|
+
comment: comments,
|
|
770
|
+
compare: compare ? compare : void 0,
|
|
771
|
+
modifier: modificator,
|
|
772
|
+
total: roller.total
|
|
773
|
+
};
|
|
774
|
+
}
|
|
775
|
+
function handleBulkRollsWithComparison(numberOfDice, diceToRoll, comments, activeCompare, explodingSuccess, diceDisplay, isCurlyBulk, curlyCompare, compare, engine) {
|
|
776
|
+
const results = [];
|
|
777
|
+
let successCount = 0;
|
|
778
|
+
const roller = new DiceRoller2();
|
|
779
|
+
NumberGenerator6.generator.engine = engine;
|
|
780
|
+
let trivialComparisonDetected = false;
|
|
781
|
+
const formatOutput = (output, addStar) => {
|
|
782
|
+
const formatted = addStar && isCurlyBulk ? output.replace(
|
|
783
|
+
/\[([^\]]+)\]/,
|
|
784
|
+
(_m, content) => `[${content.split(",").map((d) => `${d.trim()}*`).join(", ")}]`
|
|
785
|
+
) : output;
|
|
786
|
+
return curlyCompare ? formatted.replace(/^([^:]+):/, `$1${curlyCompare.sign}${curlyCompare.value}:`) : formatted;
|
|
787
|
+
};
|
|
788
|
+
for (let i = 0; i < numberOfDice; i++) {
|
|
789
|
+
try {
|
|
790
|
+
const individualRoll = roller.roll(diceToRoll);
|
|
791
|
+
const rollInstance = Array.isArray(individualRoll) ? individualRoll[0] : individualRoll;
|
|
792
|
+
if (!trivialComparisonDetected && activeCompare) {
|
|
793
|
+
const { maxTotal, minTotal } = rollInstance;
|
|
794
|
+
trivialComparisonDetected = isTrivialComparison(
|
|
795
|
+
maxTotal,
|
|
796
|
+
minTotal,
|
|
797
|
+
activeCompare
|
|
798
|
+
);
|
|
799
|
+
}
|
|
800
|
+
const rollOutput = rollInstance.output;
|
|
801
|
+
if (explodingSuccess) {
|
|
802
|
+
const successesForRoll = countExplodingSuccesses(
|
|
803
|
+
rollInstance,
|
|
804
|
+
explodingSuccess.sign,
|
|
805
|
+
explodingSuccess.value
|
|
806
|
+
);
|
|
807
|
+
successCount += successesForRoll;
|
|
808
|
+
let formattedRollOutput = rollOutput.replace(explodingSuccess.normalizedSegment, explodingSuccess.originalSegment).replace(/=\s*-?\d+(?:\.\d+)?$/, `= ${successesForRoll}`);
|
|
809
|
+
formattedRollOutput = formatOutput(formattedRollOutput, false);
|
|
810
|
+
results.push(formattedRollOutput);
|
|
811
|
+
} else {
|
|
812
|
+
const rollTotal = rollInstance.total;
|
|
813
|
+
const isSuccess = evaluate6(
|
|
814
|
+
`${rollTotal}${activeCompare.sign}${activeCompare.value}`
|
|
815
|
+
);
|
|
816
|
+
if (isSuccess) successCount++;
|
|
817
|
+
results.push(formatOutput(rollOutput, isSuccess));
|
|
818
|
+
}
|
|
819
|
+
} catch (error) {
|
|
820
|
+
throw new DiceTypeError(diceToRoll, "roll", error);
|
|
821
|
+
}
|
|
797
822
|
}
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
823
|
+
if (explodingSuccess) {
|
|
824
|
+
const signSource = explodingSuccess?.originalDice ?? diceDisplay;
|
|
825
|
+
const explodingMatch = signSource.match(EXPLODING_SUCCESS_REGEX);
|
|
826
|
+
if (explodingMatch) {
|
|
827
|
+
const [, doubledSignRaw, valueStr] = explodingMatch;
|
|
828
|
+
let doubledSign;
|
|
829
|
+
if (doubledSignRaw === "!!==") doubledSign = "==";
|
|
830
|
+
else if (doubledSignRaw === "!==") doubledSign = "!==";
|
|
831
|
+
else doubledSign = doubledSignRaw.replace(/^!/, "");
|
|
832
|
+
const signMap = {
|
|
833
|
+
">>": ">",
|
|
834
|
+
"<<": "<",
|
|
835
|
+
">=": ">=",
|
|
836
|
+
"<=": "<=",
|
|
837
|
+
"==": "=",
|
|
838
|
+
"!==": "!=",
|
|
839
|
+
"!!==": "="
|
|
840
|
+
};
|
|
841
|
+
const mappedSign = signMap[doubledSign];
|
|
842
|
+
const mappedValue = Number.parseFloat(valueStr);
|
|
843
|
+
if (mappedSign && !Number.isNaN(mappedValue)) {
|
|
844
|
+
const resultsString = replaceUnwantedText(results.join("; "));
|
|
845
|
+
const flatValues = resultsString.split(";").flatMap((segment) => extractValuesFromOutput(segment));
|
|
846
|
+
if (mappedSign === "!=") {
|
|
847
|
+
const equalsCount = flatValues.filter((val) => val === mappedValue).length;
|
|
848
|
+
successCount = flatValues.length - equalsCount;
|
|
849
|
+
} else {
|
|
850
|
+
successCount = flatValues.filter(
|
|
851
|
+
(val) => matchComparison(mappedSign, val, mappedValue)
|
|
852
|
+
).length;
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
}
|
|
804
856
|
}
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
857
|
+
if (compare && trivialComparisonDetected) compare.trivial = true;
|
|
858
|
+
const finalDice = isCurlyBulk ? `{${diceToRoll}${curlyCompare?.sign}${curlyCompare?.value}}` : diceToRoll;
|
|
859
|
+
const resultOutput = replaceUnwantedText(results.join("; "));
|
|
860
|
+
const finalTotal = explodingSuccess ? resultOutput.split(";").flatMap((segment) => extractValuesFromOutput(segment)).filter(
|
|
861
|
+
(val) => matchComparison(explodingSuccess.sign, val, explodingSuccess.value)
|
|
862
|
+
).length : successCount;
|
|
863
|
+
const modificator = getModifier(diceDisplay);
|
|
864
|
+
return {
|
|
865
|
+
dice: explodingSuccess ? diceDisplay : finalDice,
|
|
866
|
+
result: resultOutput,
|
|
867
|
+
comment: comments,
|
|
868
|
+
compare: isCurlyBulk ? void 0 : compare,
|
|
869
|
+
modifier: modificator,
|
|
870
|
+
total: finalTotal,
|
|
871
|
+
trivial: trivialComparisonDetected ? true : void 0
|
|
872
|
+
};
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
// src/dice/pity.ts
|
|
876
|
+
import { evaluate as evaluate7 } from "mathjs";
|
|
877
|
+
function handlePitySystem(dice, compare, diceRoll, roller, engine) {
|
|
878
|
+
const currentRoll = Array.isArray(diceRoll) ? diceRoll[0] : diceRoll;
|
|
879
|
+
const maxPossible = currentRoll ? currentRoll.maxTotal : null;
|
|
880
|
+
const isComparisonPossible = maxPossible === null || canComparisonSucceed(maxPossible, compare);
|
|
881
|
+
if (!isComparisonPossible) {
|
|
882
|
+
return { rerollCount: 0 };
|
|
811
883
|
}
|
|
812
|
-
};
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
constructor() {
|
|
816
|
-
super();
|
|
817
|
-
this.name = "No_Statistics";
|
|
884
|
+
let isFail = evaluate7(`${roller.total}${compare.sign}${compare.value}`);
|
|
885
|
+
if (isFail) {
|
|
886
|
+
return { rerollCount: 0 };
|
|
818
887
|
}
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
}
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
max: z.number().transform((val) => val === 0 ? void 0 : val).optional(),
|
|
833
|
-
min: z.number().transform(
|
|
834
|
-
(val) => Number.isNaN(Number.parseInt(val, 10)) ? void 0 : val
|
|
835
|
-
).optional(),
|
|
836
|
-
combinaison: z.string().transform((str) => str.trim() || void 0).optional(),
|
|
837
|
-
exclude: z.boolean().optional()
|
|
838
|
-
}).superRefine((data, ctx) => {
|
|
839
|
-
if (data.max !== void 0 && data.min !== void 0 && data.max <= data.min) {
|
|
840
|
-
ctx.addIssue({
|
|
841
|
-
code: "custom",
|
|
842
|
-
message: `Max_Greater; ${data.min}; ${data.max}`,
|
|
843
|
-
path: ["max"]
|
|
844
|
-
});
|
|
888
|
+
const maxReroll = 100;
|
|
889
|
+
let rerollCount = 0;
|
|
890
|
+
let res;
|
|
891
|
+
while (!isFail && rerollCount < maxReroll) {
|
|
892
|
+
try {
|
|
893
|
+
res = roll(dice, engine, false);
|
|
894
|
+
} catch (error) {
|
|
895
|
+
throw new DiceTypeError(dice, "roll", error);
|
|
896
|
+
}
|
|
897
|
+
rerollCount++;
|
|
898
|
+
if (res && res.total !== void 0) {
|
|
899
|
+
isFail = evaluate7(`${res.total}${compare.sign}${compare.value}`);
|
|
900
|
+
}
|
|
845
901
|
}
|
|
846
|
-
}
|
|
847
|
-
var statisticSchema = z.record(z.string(), statisticValueSchema).optional().refine((stats) => !stats || Object.keys(stats).length <= 25, {
|
|
848
|
-
message: "TooManyStats"
|
|
849
|
-
});
|
|
850
|
-
var criticalSchema = z.object({
|
|
851
|
-
success: z.string().or(z.number().min(0)).optional(),
|
|
852
|
-
failure: z.string().or(z.number().min(0)).optional()
|
|
853
|
-
}).transform((values) => {
|
|
854
|
-
if (values.success === "") values.success = void 0;
|
|
855
|
-
if (values.failure === "") values.failure = void 0;
|
|
856
|
-
if (values.failure === 0) values.failure = void 0;
|
|
857
|
-
if (values.success === 0) values.success = void 0;
|
|
858
|
-
values.success = Number.parseInt(values.success, 10);
|
|
859
|
-
values.failure = Number.parseInt(values.failure, 10);
|
|
860
|
-
return values;
|
|
861
|
-
});
|
|
862
|
-
var criticalValueSchema = z.object({
|
|
863
|
-
sign: z.enum(["<", ">", "<=", ">=", "!=", "=="]),
|
|
864
|
-
value: z.string(),
|
|
865
|
-
onNaturalDice: z.boolean().optional(),
|
|
866
|
-
affectSkill: z.boolean().optional()
|
|
867
|
-
});
|
|
868
|
-
var damageSchema = z.record(z.string(), z.string()).optional().refine((stats) => !stats || Object.keys(stats).length <= 25, {
|
|
869
|
-
message: "TooManyDice"
|
|
870
|
-
});
|
|
871
|
-
var customCriticalSchema = z.record(z.string(), criticalValueSchema).optional().refine((stats) => !stats || Object.keys(stats).length <= 22, {
|
|
872
|
-
message: "TooManyDice"
|
|
873
|
-
});
|
|
874
|
-
var templateSchema = z.object({
|
|
875
|
-
charName: z.boolean().optional(),
|
|
876
|
-
statistics: statisticSchema,
|
|
877
|
-
total: z.number().min(0).transform((val) => val === 0 ? void 0 : val).optional(),
|
|
878
|
-
forceDistrib: z.boolean().optional(),
|
|
879
|
-
diceType: z.string().optional(),
|
|
880
|
-
critical: criticalSchema.optional(),
|
|
881
|
-
customCritical: customCriticalSchema,
|
|
882
|
-
damage: damageSchema
|
|
883
|
-
});
|
|
884
|
-
|
|
885
|
-
// src/utils.ts
|
|
886
|
-
import { evaluate as evaluate6 } from "mathjs";
|
|
887
|
-
import "uniformize";
|
|
888
|
-
import { NumberGenerator as NumberGenerator6 } from "@dice-roller/rpg-dice-roller";
|
|
889
|
-
import { Random } from "random-js";
|
|
890
|
-
function escapeRegex(string) {
|
|
891
|
-
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
892
|
-
}
|
|
893
|
-
function standardizeDice(dice) {
|
|
894
|
-
return dice.replace(
|
|
895
|
-
/(\[[^\]]+])|([^[]+)/g,
|
|
896
|
-
(_match, insideBrackets, outsideText) => insideBrackets ? insideBrackets : outsideText.standardize().replaceAll("df", "dF")
|
|
897
|
-
);
|
|
902
|
+
return { rerollCount, result: res };
|
|
898
903
|
}
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
904
|
+
|
|
905
|
+
// src/roll.ts
|
|
906
|
+
function roll(dice, engine = NumberGenerator7.engines.nodeCrypto, pity, sort) {
|
|
907
|
+
if (sort === "none" /* None */) sort = void 0;
|
|
908
|
+
const prepared = prepareDice(dice);
|
|
909
|
+
if (!prepared.dice.includes("d")) return void 0;
|
|
910
|
+
if (prepared.isSharedRoll) {
|
|
911
|
+
return sharedRolls(
|
|
912
|
+
prepared.dice,
|
|
913
|
+
engine,
|
|
914
|
+
pity,
|
|
915
|
+
prepared.explodingSuccess,
|
|
916
|
+
prepared.diceDisplay,
|
|
917
|
+
prepared.isSharedCurly
|
|
918
|
+
);
|
|
919
|
+
}
|
|
920
|
+
let processedDice = fixParenthesis(prepared.dice);
|
|
921
|
+
const modificator = getModifier(processedDice);
|
|
922
|
+
const compareRegex = processedDice.match(SIGN_REGEX_SPACE);
|
|
923
|
+
let compare;
|
|
924
|
+
if (compareRegex && !prepared.isCurlyBulk) {
|
|
925
|
+
const compareResult = getCompare(processedDice, compareRegex, engine, pity);
|
|
926
|
+
processedDice = compareResult.dice;
|
|
927
|
+
compare = compareResult.compare;
|
|
928
|
+
}
|
|
929
|
+
let finalDiceDisplay = prepared.diceDisplay;
|
|
930
|
+
if (prepared.isSimpleCurly && !prepared.diceDisplay.startsWith("{")) {
|
|
931
|
+
finalDiceDisplay = `{${prepared.diceDisplay}}`;
|
|
932
|
+
}
|
|
933
|
+
const bulkProcessContent = prepared.isCurlyBulk ? prepared.bulkContent : processedDice;
|
|
934
|
+
if (bulkProcessContent.match(/\d+?#(.*)/)) {
|
|
935
|
+
return handleBulkRolls(
|
|
936
|
+
processedDice,
|
|
937
|
+
prepared.isCurlyBulk,
|
|
938
|
+
prepared.bulkContent,
|
|
939
|
+
compare,
|
|
940
|
+
prepared.explodingSuccess,
|
|
941
|
+
prepared.diceDisplay,
|
|
942
|
+
engine,
|
|
943
|
+
sort
|
|
944
|
+
);
|
|
945
|
+
}
|
|
946
|
+
const roller = new DiceRoller3();
|
|
947
|
+
NumberGenerator7.generator.engine = engine;
|
|
948
|
+
let diceWithoutComment = processedDice.replace(COMMENT_REGEX, "").trimEnd();
|
|
949
|
+
diceWithoutComment = setSortOrder(diceWithoutComment, sort);
|
|
950
|
+
let diceRoll;
|
|
951
|
+
try {
|
|
952
|
+
diceRoll = roller.roll(diceWithoutComment);
|
|
953
|
+
} catch (error) {
|
|
954
|
+
throw new DiceTypeError(diceWithoutComment, "roll", error);
|
|
955
|
+
}
|
|
956
|
+
if (compare && diceRoll) {
|
|
957
|
+
const currentRoll = Array.isArray(diceRoll) ? diceRoll[0] : diceRoll;
|
|
958
|
+
const trivial = isTrivialComparison(
|
|
959
|
+
currentRoll.maxTotal,
|
|
960
|
+
currentRoll.minTotal,
|
|
961
|
+
compare
|
|
962
|
+
);
|
|
963
|
+
compare.trivial = trivial ? true : void 0;
|
|
964
|
+
}
|
|
965
|
+
const commentMatch = processedDice.match(COMMENT_REGEX);
|
|
966
|
+
const comment = commentMatch ? commentMatch[2] : void 0;
|
|
967
|
+
let rerollCount = 0;
|
|
968
|
+
let pityResult;
|
|
969
|
+
if (pity && compare) {
|
|
970
|
+
const pityData = handlePitySystem(
|
|
971
|
+
diceWithoutComment,
|
|
972
|
+
compare,
|
|
973
|
+
diceRoll,
|
|
974
|
+
roller,
|
|
975
|
+
engine
|
|
976
|
+
);
|
|
977
|
+
rerollCount = pityData.rerollCount;
|
|
978
|
+
pityResult = pityData.result;
|
|
979
|
+
if (pityResult) {
|
|
980
|
+
return {
|
|
981
|
+
...pityResult,
|
|
982
|
+
dice: prepared.isSimpleCurly ? finalDiceDisplay : processedDice,
|
|
983
|
+
comment,
|
|
984
|
+
compare,
|
|
985
|
+
modifier: modificator,
|
|
986
|
+
pityLogs: rerollCount,
|
|
987
|
+
trivial: pityResult.trivial ?? (compare?.trivial ? true : void 0)
|
|
988
|
+
};
|
|
965
989
|
}
|
|
966
|
-
dice = result;
|
|
967
990
|
}
|
|
968
|
-
|
|
969
|
-
|
|
991
|
+
let resultOutput = replaceUnwantedText(roller.output);
|
|
992
|
+
if (prepared.explodingSuccess) {
|
|
993
|
+
const successes = countExplodingSuccesses(
|
|
994
|
+
diceRoll,
|
|
995
|
+
prepared.explodingSuccess.sign,
|
|
996
|
+
prepared.explodingSuccess.value
|
|
997
|
+
);
|
|
998
|
+
resultOutput = resultOutput.replace(/=\s*-?\d+(?:\.\d+)?$/, `= ${successes}`).replace(
|
|
999
|
+
prepared.explodingSuccess.normalizedSegment,
|
|
1000
|
+
prepared.explodingSuccess.originalSegment
|
|
1001
|
+
);
|
|
1002
|
+
return {
|
|
1003
|
+
dice: prepared.isSimpleCurly ? finalDiceDisplay : prepared.diceDisplay,
|
|
1004
|
+
result: resultOutput,
|
|
1005
|
+
comment,
|
|
1006
|
+
compare: compare ? compare : void 0,
|
|
1007
|
+
modifier: modificator,
|
|
1008
|
+
total: successes,
|
|
1009
|
+
pityLogs: rerollCount > 0 ? rerollCount : void 0,
|
|
1010
|
+
trivial: compare?.trivial ? true : void 0
|
|
1011
|
+
};
|
|
1012
|
+
}
|
|
1013
|
+
return {
|
|
1014
|
+
dice: prepared.isSimpleCurly ? finalDiceDisplay : processedDice,
|
|
1015
|
+
result: resultOutput,
|
|
1016
|
+
comment,
|
|
1017
|
+
compare: compare ? compare : void 0,
|
|
1018
|
+
modifier: modificator,
|
|
1019
|
+
total: roller.total,
|
|
1020
|
+
pityLogs: rerollCount > 0 ? rerollCount : void 0,
|
|
1021
|
+
trivial: compare?.trivial ? true : void 0
|
|
1022
|
+
};
|
|
970
1023
|
}
|
|
971
|
-
function
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
1024
|
+
function sharedRolls(dice, engine = NumberGenerator7.engines.nodeCrypto, pity, explodingSuccessMain, diceDisplay, isSharedCurly) {
|
|
1025
|
+
if (!explodingSuccessMain)
|
|
1026
|
+
explodingSuccessMain = normalizeExplodingSuccess(dice.split(";")[0] ?? dice);
|
|
1027
|
+
if (explodingSuccessMain) {
|
|
1028
|
+
dice = dice.replace(explodingSuccessMain.originalSegment, "!");
|
|
1029
|
+
}
|
|
1030
|
+
if (dice.match(/\d+?#(.*?)/))
|
|
1031
|
+
throw new DiceTypeError(
|
|
1032
|
+
dice,
|
|
1033
|
+
"noBulkRoll",
|
|
1034
|
+
"bulk roll are not allowed in shared rolls"
|
|
1035
|
+
);
|
|
1036
|
+
const results = [];
|
|
1037
|
+
const mainComment = /\s+#(?<comment>.*)/.exec(dice)?.groups?.comment?.trimEnd() ?? void 0;
|
|
1038
|
+
const split = dice.split(";");
|
|
1039
|
+
const displayDice = diceDisplay ?? explodingSuccessMain?.originalDice ?? split[0];
|
|
1040
|
+
let diceMain = fixParenthesis(split[0]);
|
|
1041
|
+
const commentsRegex = /\[(?<comments>.*?)\]/gi;
|
|
1042
|
+
const comments = formatComment(diceMain);
|
|
1043
|
+
const diceMainWithoutComments = diceMain.replace(commentsRegex, "").trim();
|
|
1044
|
+
const toHideRegex = /\((?<dice>[^)]+)\)/;
|
|
1045
|
+
const toHide = toHideRegex.exec(diceMainWithoutComments)?.groups;
|
|
1046
|
+
let hidden = false;
|
|
1047
|
+
if (toHide?.dice) {
|
|
1048
|
+
diceMain = toHide.dice;
|
|
1049
|
+
hidden = true;
|
|
1050
|
+
} else if (toHide) {
|
|
1051
|
+
diceMain = "1d1";
|
|
1052
|
+
hidden = true;
|
|
1053
|
+
} else {
|
|
1054
|
+
diceMain = diceMainWithoutComments;
|
|
1055
|
+
}
|
|
1056
|
+
const rollBounds = getRollBounds(diceMain, engine);
|
|
1057
|
+
let diceResult = roll(diceMain, engine, pity);
|
|
1058
|
+
if (!diceResult || !diceResult.total) {
|
|
1059
|
+
if (hidden) {
|
|
1060
|
+
diceResult = roll(fixParenthesis(split[0]), engine, pity);
|
|
1061
|
+
hidden = false;
|
|
1062
|
+
} else return void 0;
|
|
1063
|
+
}
|
|
1064
|
+
if (!diceResult || !diceResult.total) return void 0;
|
|
1065
|
+
if (explodingSuccessMain && diceResult.result) {
|
|
1066
|
+
const values = extractValuesFromOutput(diceResult.result);
|
|
1067
|
+
diceResult.total = values.filter(
|
|
1068
|
+
(v) => matchComparison(explodingSuccessMain.sign, v, explodingSuccessMain.value)
|
|
1069
|
+
).length;
|
|
1070
|
+
}
|
|
1071
|
+
let aggregatedCompare = diceResult.compare;
|
|
1072
|
+
let hasTrivialComparison = diceResult.compare?.trivial === true;
|
|
1073
|
+
results.push(`\u203B ${comments}${diceResult.result}`);
|
|
1074
|
+
let total = diceResult.total;
|
|
1075
|
+
diceResult.comment = mainComment;
|
|
1076
|
+
if (!total) {
|
|
1077
|
+
return {
|
|
1078
|
+
dice: displayDice,
|
|
1079
|
+
result: results.join(";"),
|
|
1080
|
+
comment: mainComment,
|
|
1081
|
+
compare: aggregatedCompare,
|
|
1082
|
+
modifier: diceResult.modifier,
|
|
1083
|
+
total,
|
|
1084
|
+
trivial: hasTrivialComparison ? true : void 0
|
|
1085
|
+
};
|
|
1086
|
+
}
|
|
1087
|
+
for (let element of split.slice(1)) {
|
|
1088
|
+
const comment = formatComment(element);
|
|
1089
|
+
element = element.replaceAll(commentsRegex, "").replaceAll(OPTIONAL_COMMENT, "").trim();
|
|
1090
|
+
let toRoll = element.replace(SYMBOL_DICE, `${diceResult.total}`);
|
|
1091
|
+
const compareRegex = toRoll.match(SIGN_REGEX_SPACE);
|
|
1092
|
+
if (compareRegex) {
|
|
1093
|
+
if (isSharedCurly) {
|
|
1094
|
+
const compareResult = compareSignFormule(
|
|
1095
|
+
toRoll,
|
|
1096
|
+
compareRegex,
|
|
1097
|
+
element,
|
|
1098
|
+
diceResult,
|
|
1099
|
+
engine,
|
|
1100
|
+
pity,
|
|
1101
|
+
rollBounds
|
|
1102
|
+
);
|
|
1103
|
+
const { diceAll } = replaceText(element, diceResult.total, diceResult.dice);
|
|
1104
|
+
let successCount = 0;
|
|
1105
|
+
try {
|
|
1106
|
+
const evaluated = evaluate8(toRoll);
|
|
1107
|
+
successCount = evaluated ? 1 : 0;
|
|
1108
|
+
} catch (error) {
|
|
1109
|
+
const evaluated = roll(toRoll, engine, pity);
|
|
1110
|
+
successCount = evaluated?.total ?? 0 ? 1 : 0;
|
|
1111
|
+
}
|
|
1112
|
+
results.push(`\u203B ${comment}${diceAll}: ${successCount}`);
|
|
1113
|
+
total += successCount;
|
|
1114
|
+
if (!aggregatedCompare && compareResult.compare)
|
|
1115
|
+
aggregatedCompare = compareResult.compare;
|
|
1116
|
+
if (compareResult.trivial) hasTrivialComparison = true;
|
|
1117
|
+
} else {
|
|
1118
|
+
const compareResult = compareSignFormule(
|
|
1119
|
+
toRoll,
|
|
1120
|
+
compareRegex,
|
|
1121
|
+
element,
|
|
1122
|
+
diceResult,
|
|
1123
|
+
engine,
|
|
1124
|
+
pity,
|
|
1125
|
+
rollBounds
|
|
1126
|
+
);
|
|
1127
|
+
toRoll = compareResult.dice;
|
|
1128
|
+
results.push(compareResult.results);
|
|
1129
|
+
if (!aggregatedCompare && compareResult.compare)
|
|
1130
|
+
aggregatedCompare = compareResult.compare;
|
|
1131
|
+
if (compareResult.trivial) hasTrivialComparison = true;
|
|
1132
|
+
}
|
|
1133
|
+
} else {
|
|
1134
|
+
const { formule, diceAll } = replaceText(
|
|
1135
|
+
element,
|
|
1136
|
+
diceResult.total,
|
|
1137
|
+
diceResult.dice
|
|
1138
|
+
);
|
|
978
1139
|
try {
|
|
979
|
-
const
|
|
980
|
-
|
|
1140
|
+
const evaluated = evaluate8(toRoll);
|
|
1141
|
+
results.push(`\u25C8 ${comment}${diceAll}: ${formule} = ${evaluated}`);
|
|
1142
|
+
total += Number.parseInt(evaluated, 10);
|
|
981
1143
|
} catch (error) {
|
|
982
|
-
|
|
1144
|
+
const evaluated = roll(toRoll, engine, pity);
|
|
1145
|
+
if (evaluated) {
|
|
1146
|
+
results.push(
|
|
1147
|
+
`\u25C8 ${comment}${diceAll}: ${evaluated.result.split(":").slice(1).join(":")}`
|
|
1148
|
+
);
|
|
1149
|
+
if (!aggregatedCompare && evaluated.compare)
|
|
1150
|
+
aggregatedCompare = evaluated.compare;
|
|
1151
|
+
if (evaluated.compare?.trivial) hasTrivialComparison = true;
|
|
1152
|
+
} else results.push(`\u25C8 ${comment}${diceAll}: ${formule} = ${evaluated}`);
|
|
1153
|
+
total += evaluated?.total ?? 0;
|
|
983
1154
|
}
|
|
984
1155
|
}
|
|
985
1156
|
}
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
const defaultValue = groups?.default;
|
|
998
|
-
return defaultValue ?? randomInt(1, 999, engine).toString();
|
|
999
|
-
});
|
|
1000
|
-
}
|
|
1001
|
-
function randomInt(min, max, engine = NumberGenerator6.engines.nodeCrypto, rng) {
|
|
1002
|
-
if (!rng) rng = new Random(engine || void 0);
|
|
1003
|
-
return rng.integer(min, max);
|
|
1157
|
+
if (hidden)
|
|
1158
|
+
results.shift();
|
|
1159
|
+
return {
|
|
1160
|
+
dice: displayDice,
|
|
1161
|
+
result: results.join(";"),
|
|
1162
|
+
comment: mainComment,
|
|
1163
|
+
compare: hasTrivialComparison && aggregatedCompare ? { ...aggregatedCompare, trivial: true } : aggregatedCompare,
|
|
1164
|
+
modifier: diceResult.modifier,
|
|
1165
|
+
total,
|
|
1166
|
+
trivial: hasTrivialComparison ? true : void 0
|
|
1167
|
+
};
|
|
1004
1168
|
}
|
|
1005
|
-
function
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
const
|
|
1012
|
-
const
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1169
|
+
function replaceInFormula(element, diceResult, compareResult, res, engine = NumberGenerator7.engines.nodeCrypto, pity) {
|
|
1170
|
+
const { formule, diceAll } = replaceText(
|
|
1171
|
+
element,
|
|
1172
|
+
diceResult.total ?? 0,
|
|
1173
|
+
diceResult.dice
|
|
1174
|
+
);
|
|
1175
|
+
const validSign = res ? "\u2713" : "\u2715";
|
|
1176
|
+
const invertedSign = res ? compareResult.compare.sign : inverseSign(compareResult.compare.sign);
|
|
1177
|
+
let evaluateRoll;
|
|
1178
|
+
try {
|
|
1179
|
+
evaluateRoll = evaluate8(compareResult.dice);
|
|
1180
|
+
return `${validSign} ${diceAll}: ${formule} = ${evaluateRoll}${invertedSign}${compareResult.compare?.value}`;
|
|
1181
|
+
} catch (error) {
|
|
1182
|
+
const evaluateRoll2 = roll(compareResult.dice, engine, pity);
|
|
1183
|
+
if (evaluateRoll2)
|
|
1184
|
+
return `${validSign} ${diceAll}: ${evaluateRoll2.result.split(":").splice(1).join(":")}`;
|
|
1185
|
+
return `${validSign} ${diceAll}: ${formule} = ${evaluateRoll2}${invertedSign}${compareResult.compare?.value}`;
|
|
1021
1186
|
}
|
|
1022
|
-
return v1[bl];
|
|
1023
|
-
}
|
|
1024
|
-
function similarityScore(a, b) {
|
|
1025
|
-
const la = a.length;
|
|
1026
|
-
const lb = b.length;
|
|
1027
|
-
if (la === 0 && lb === 0) return 1;
|
|
1028
|
-
const dist = levenshteinDistance(a, b);
|
|
1029
|
-
const max = Math.max(la, lb);
|
|
1030
|
-
return 1 - dist / max;
|
|
1031
|
-
}
|
|
1032
|
-
function createCriticalCustom(dice, customCritical, template, engine = NumberGenerator6.engines.nodeCrypto) {
|
|
1033
|
-
const compareRegex = dice.match(SIGN_REGEX_SPACE);
|
|
1034
|
-
let customDice = dice;
|
|
1035
|
-
const compareValue = diceTypeRandomParse(customCritical.value, template, engine);
|
|
1036
|
-
if (compareValue.includes("$"))
|
|
1037
|
-
throw new DiceTypeError(compareValue, "createCriticalCustom");
|
|
1038
|
-
const comparaison = `${customCritical.sign}${compareValue}`;
|
|
1039
|
-
if (compareRegex) customDice = customDice.replace(SIGN_REGEX_SPACE, comparaison);
|
|
1040
|
-
else customDice += comparaison;
|
|
1041
|
-
return diceTypeRandomParse(customDice, template, engine);
|
|
1042
1187
|
}
|
|
1043
1188
|
|
|
1044
1189
|
// src/verify_template.ts
|
|
1045
|
-
import { evaluate as
|
|
1190
|
+
import { evaluate as evaluate9 } from "mathjs";
|
|
1046
1191
|
import { Random as Random2 } from "random-js";
|
|
1047
1192
|
import "uniformize";
|
|
1048
|
-
import { NumberGenerator as
|
|
1049
|
-
function evalStatsDice(testDice, allStats, engine =
|
|
1193
|
+
import { NumberGenerator as NumberGenerator8 } from "@dice-roller/rpg-dice-roller";
|
|
1194
|
+
function evalStatsDice(testDice, allStats, engine = NumberGenerator8.engines.nodeCrypto, pity) {
|
|
1050
1195
|
let dice = testDice.trimEnd();
|
|
1051
1196
|
if (allStats && Object.keys(allStats).length > 0) {
|
|
1052
1197
|
const names = Object.keys(allStats);
|
|
@@ -1066,7 +1211,7 @@ function evalStatsDice(testDice, allStats, engine = NumberGenerator7.engines.nod
|
|
|
1066
1211
|
throw new DiceTypeError(dice, "evalStatsDice", error);
|
|
1067
1212
|
}
|
|
1068
1213
|
}
|
|
1069
|
-
function diceRandomParse(value, template, engine =
|
|
1214
|
+
function diceRandomParse(value, template, engine = NumberGenerator8.engines.nodeCrypto) {
|
|
1070
1215
|
if (!template.statistics) return replaceFormulaInDice(value.standardize());
|
|
1071
1216
|
value = value.standardize();
|
|
1072
1217
|
const statNames = Object.keys(template.statistics);
|
|
@@ -1088,7 +1233,7 @@ function diceRandomParse(value, template, engine = NumberGenerator7.engines.node
|
|
|
1088
1233
|
}
|
|
1089
1234
|
return replaceFormulaInDice(newDice);
|
|
1090
1235
|
}
|
|
1091
|
-
function diceTypeRandomParse(dice, template, engine =
|
|
1236
|
+
function diceTypeRandomParse(dice, template, engine = NumberGenerator8.engines.nodeCrypto) {
|
|
1092
1237
|
dice = replaceExpByRandom(dice);
|
|
1093
1238
|
if (!template.statistics) return dice;
|
|
1094
1239
|
const firstStatNotcombinaison = Object.keys(template.statistics).find(
|
|
@@ -1110,7 +1255,7 @@ function evalCombinaison(combinaison, stats) {
|
|
|
1110
1255
|
formula = formula.replace(regex, value.toString());
|
|
1111
1256
|
}
|
|
1112
1257
|
try {
|
|
1113
|
-
newStats[stat] =
|
|
1258
|
+
newStats[stat] = evaluate9(formula);
|
|
1114
1259
|
} catch (error) {
|
|
1115
1260
|
throw new FormulaError(stat, "evalCombinaison", error);
|
|
1116
1261
|
}
|
|
@@ -1124,7 +1269,7 @@ function evalOneCombinaison(combinaison, stats) {
|
|
|
1124
1269
|
formula = formula.replace(regex, value.toString());
|
|
1125
1270
|
}
|
|
1126
1271
|
try {
|
|
1127
|
-
return
|
|
1272
|
+
return evaluate9(formula);
|
|
1128
1273
|
} catch (error) {
|
|
1129
1274
|
throw new FormulaError(combinaison, "evalOneCombinaison", error);
|
|
1130
1275
|
}
|
|
@@ -1136,7 +1281,7 @@ function convertNumber(number) {
|
|
|
1136
1281
|
if (isNumber(number)) return Number.parseInt(number.toString(), 10);
|
|
1137
1282
|
return void 0;
|
|
1138
1283
|
}
|
|
1139
|
-
function verifyTemplateValue(template, verify = true, engine =
|
|
1284
|
+
function verifyTemplateValue(template, verify = true, engine = NumberGenerator8.engines.nodeCrypto) {
|
|
1140
1285
|
const parsedTemplate = templateSchema.parse(template);
|
|
1141
1286
|
const { success, failure } = parsedTemplate.critical ?? {};
|
|
1142
1287
|
const criticicalVal = {
|
|
@@ -1191,7 +1336,7 @@ function verifyTemplateValue(template, verify = true, engine = NumberGenerator7.
|
|
|
1191
1336
|
testStatCombinaison(statistiqueTemplate, engine);
|
|
1192
1337
|
return statistiqueTemplate;
|
|
1193
1338
|
}
|
|
1194
|
-
function testDiceRegistered(template, engine =
|
|
1339
|
+
function testDiceRegistered(template, engine = NumberGenerator8.engines.nodeCrypto) {
|
|
1195
1340
|
if (!template.damage) return;
|
|
1196
1341
|
if (Object.keys(template.damage).length === 0) throw new EmptyObjectError();
|
|
1197
1342
|
if (Object.keys(template.damage).length > 25) throw new TooManyDice();
|
|
@@ -1207,7 +1352,7 @@ function testDiceRegistered(template, engine = NumberGenerator7.engines.nodeCryp
|
|
|
1207
1352
|
}
|
|
1208
1353
|
}
|
|
1209
1354
|
}
|
|
1210
|
-
function testStatCombinaison(template, engine =
|
|
1355
|
+
function testStatCombinaison(template, engine = NumberGenerator8.engines.nodeCrypto) {
|
|
1211
1356
|
if (!template.statistics) return;
|
|
1212
1357
|
const onlycombinaisonStats = Object.fromEntries(
|
|
1213
1358
|
Object.entries(template.statistics).filter(
|
|
@@ -1233,7 +1378,7 @@ function testStatCombinaison(template, engine = NumberGenerator7.engines.nodeCry
|
|
|
1233
1378
|
formula = formula.replace(regex, randomStatValue.toString());
|
|
1234
1379
|
}
|
|
1235
1380
|
try {
|
|
1236
|
-
|
|
1381
|
+
evaluate9(formula);
|
|
1237
1382
|
} catch (e) {
|
|
1238
1383
|
error.push(stat);
|
|
1239
1384
|
}
|
|
@@ -1241,9 +1386,9 @@ function testStatCombinaison(template, engine = NumberGenerator7.engines.nodeCry
|
|
|
1241
1386
|
if (error.length > 0) throw new FormulaError(error.join(", "), "testStatCombinaison");
|
|
1242
1387
|
return;
|
|
1243
1388
|
}
|
|
1244
|
-
function generateRandomStat(total = 100, max, min, engine =
|
|
1389
|
+
function generateRandomStat(total = 100, max, min, engine = NumberGenerator8.engines.nodeCrypto) {
|
|
1245
1390
|
let randomStatValue = total + 1;
|
|
1246
|
-
const random = new Random2(engine ||
|
|
1391
|
+
const random = new Random2(engine || NumberGenerator8.engines.nodeCrypto);
|
|
1247
1392
|
while (randomStatValue >= total || randomStatValue === 0) {
|
|
1248
1393
|
if (max && min) randomStatValue = randomInt(min, max, engine, random);
|
|
1249
1394
|
else if (max) randomStatValue = randomInt(1, max, engine, random);
|
|
@@ -1256,7 +1401,6 @@ export {
|
|
|
1256
1401
|
COMMENT_REGEX,
|
|
1257
1402
|
DETECT_CRITICAL,
|
|
1258
1403
|
DiceTypeError,
|
|
1259
|
-
EXPLODING_SUCCESS_REGEX,
|
|
1260
1404
|
EmptyObjectError,
|
|
1261
1405
|
FormulaError,
|
|
1262
1406
|
MaxGreater,
|
|
@@ -1268,11 +1412,6 @@ export {
|
|
|
1268
1412
|
SortOrder,
|
|
1269
1413
|
TooManyDice,
|
|
1270
1414
|
TooManyStats,
|
|
1271
|
-
calculator,
|
|
1272
|
-
canComparisonFail,
|
|
1273
|
-
canComparisonSucceed,
|
|
1274
|
-
compareSignFormule,
|
|
1275
|
-
countExplodingSuccesses,
|
|
1276
1415
|
createCriticalCustom,
|
|
1277
1416
|
diceRandomParse,
|
|
1278
1417
|
diceTypeRandomParse,
|
|
@@ -1280,29 +1419,16 @@ export {
|
|
|
1280
1419
|
evalCombinaison,
|
|
1281
1420
|
evalOneCombinaison,
|
|
1282
1421
|
evalStatsDice,
|
|
1283
|
-
extractValuesFromOutput,
|
|
1284
|
-
fixParenthesis,
|
|
1285
|
-
formatComment,
|
|
1286
1422
|
generateRandomStat,
|
|
1287
1423
|
generateStatsDice,
|
|
1288
|
-
getCompare,
|
|
1289
1424
|
getEngine,
|
|
1290
1425
|
getEngineId,
|
|
1291
|
-
getModifier,
|
|
1292
|
-
getRollBounds,
|
|
1293
|
-
inverseSign,
|
|
1294
1426
|
isNumber,
|
|
1295
|
-
isTrivialComparison,
|
|
1296
|
-
matchComparison,
|
|
1297
|
-
normalizeExplodingSuccess,
|
|
1298
1427
|
randomInt,
|
|
1299
1428
|
replaceExpByRandom,
|
|
1300
1429
|
replaceFormulaInDice,
|
|
1301
1430
|
replaceInFormula,
|
|
1302
|
-
replaceText,
|
|
1303
|
-
replaceUnwantedText,
|
|
1304
1431
|
roll,
|
|
1305
|
-
rollCompare,
|
|
1306
1432
|
standardizeDice,
|
|
1307
1433
|
templateSchema,
|
|
1308
1434
|
testDiceRegistered,
|