@platonic-dice/core 2.0.2 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +54 -7
- package/dist/analyseModTest.d.ts +126 -0
- package/dist/analyseModTest.d.ts.map +1 -0
- package/dist/analyseModTest.js +181 -0
- package/dist/analyseTest.d.ts +101 -0
- package/dist/analyseTest.d.ts.map +1 -0
- package/dist/analyseTest.js +141 -0
- package/dist/entities/ModifiedTestConditions.d.ts +89 -0
- package/dist/entities/ModifiedTestConditions.d.ts.map +1 -0
- package/dist/entities/ModifiedTestConditions.js +265 -0
- package/dist/entities/index.d.ts +4 -1
- package/dist/entities/index.js +8 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -1
- package/dist/rollModTest.d.ts +72 -0
- package/dist/rollModTest.d.ts.map +1 -0
- package/dist/rollModTest.js +208 -0
- package/dist/rollTest.d.ts +21 -2
- package/dist/rollTest.d.ts.map +1 -1
- package/dist/rollTest.js +28 -6
- package/dist/utils/determineOutcome.d.ts.map +1 -1
- package/dist/utils/determineOutcome.js +26 -0
- package/dist/utils/index.d.ts +4 -1
- package/dist/utils/index.js +8 -0
- package/dist/utils/outcomeMapper.d.ts +29 -0
- package/dist/utils/outcomeMapper.d.ts.map +1 -0
- package/dist/utils/outcomeMapper.js +197 -0
- package/dist-types.d.ts +23 -1
- package/package.json +18 -3
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
export type TestTypeValue = import("./TestType").TestTypeValue;
|
|
2
|
+
export type DieTypeValue = import("./DieType").DieTypeValue;
|
|
3
|
+
export type RollModifierFunction = import("./RollModifier").RollModifierFunction;
|
|
4
|
+
export type RollModifierInstance = import("./RollModifier").RollModifierInstance;
|
|
5
|
+
export type BaseTestCondition = {
|
|
6
|
+
modifiedRange: {
|
|
7
|
+
min: number;
|
|
8
|
+
max: number;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
export type TargetConditions = BaseTestCondition & {
|
|
12
|
+
target: number;
|
|
13
|
+
};
|
|
14
|
+
export type WithinConditions = BaseTestCondition & {
|
|
15
|
+
min: number;
|
|
16
|
+
max: number;
|
|
17
|
+
};
|
|
18
|
+
export type SpecificListConditions = BaseTestCondition & {
|
|
19
|
+
values: number[];
|
|
20
|
+
};
|
|
21
|
+
export type SkillConditions = BaseTestCondition & {
|
|
22
|
+
target: number;
|
|
23
|
+
critical_success?: number;
|
|
24
|
+
critical_failure?: number;
|
|
25
|
+
};
|
|
26
|
+
export type Conditions = TargetConditions | SkillConditions | WithinConditions | SpecificListConditions;
|
|
27
|
+
export type ModifiedTestConditionsInstance = InstanceType<typeof ModifiedTestConditions>;
|
|
28
|
+
/**
|
|
29
|
+
* Represents a set of validated test conditions for modified rolls.
|
|
30
|
+
*
|
|
31
|
+
* This class is similar to {@link TestConditions} but validates numeric
|
|
32
|
+
* targets against the achievable range after applying a modifier.
|
|
33
|
+
*/
|
|
34
|
+
export class ModifiedTestConditions {
|
|
35
|
+
/**
|
|
36
|
+
* @param {TestTypeValue} testType - The test type.
|
|
37
|
+
* @param {Conditions} conditions - The test conditions object.
|
|
38
|
+
* @param {DieTypeValue} dieType - The base die type.
|
|
39
|
+
* @param {RollModifierFunction | RollModifierInstance} modifier - The modifier to apply.
|
|
40
|
+
* @throws {TypeError|RangeError} If the test type or conditions are invalid.
|
|
41
|
+
*/
|
|
42
|
+
constructor(testType: TestTypeValue, conditions: Conditions, dieType: DieTypeValue, modifier: RollModifierFunction | RollModifierInstance);
|
|
43
|
+
/** @type {TestTypeValue} */
|
|
44
|
+
testType: TestTypeValue;
|
|
45
|
+
/** @type {Conditions} */
|
|
46
|
+
conditions: Conditions;
|
|
47
|
+
/** @type {DieTypeValue} */
|
|
48
|
+
dieType: DieTypeValue;
|
|
49
|
+
/** @type {RollModifierInstance} */
|
|
50
|
+
modifier: RollModifierInstance;
|
|
51
|
+
/** @type {{ min: number, max: number }} */
|
|
52
|
+
modifiedRange: {
|
|
53
|
+
min: number;
|
|
54
|
+
max: number;
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Validates that the test conditions still conform to spec.
|
|
58
|
+
* @throws {TypeError} If the test conditions are invalid.
|
|
59
|
+
*/
|
|
60
|
+
validate(): void;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Validates test conditions against a modified range.
|
|
64
|
+
*
|
|
65
|
+
* @private
|
|
66
|
+
* @param {Conditions & Record<string, any>} c - Conditions with modifiedRange
|
|
67
|
+
* @param {TestTypeValue} testType
|
|
68
|
+
* @returns {boolean}
|
|
69
|
+
*/
|
|
70
|
+
export function areValidModifiedTestConditions(c: Conditions & Record<string, any>, testType: TestTypeValue): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* @typedef {import("./TestType").TestTypeValue} TestTypeValue
|
|
73
|
+
* @typedef {import("./DieType").DieTypeValue} DieTypeValue
|
|
74
|
+
* @typedef {import("./RollModifier").RollModifierFunction} RollModifierFunction
|
|
75
|
+
* @typedef {import("./RollModifier").RollModifierInstance} RollModifierInstance
|
|
76
|
+
*/
|
|
77
|
+
/**
|
|
78
|
+
* Computes the achievable range for a die + modifier combination.
|
|
79
|
+
*
|
|
80
|
+
* @private
|
|
81
|
+
* @param {DieTypeValue} dieType
|
|
82
|
+
* @param {RollModifierInstance} modifier
|
|
83
|
+
* @returns {{ min: number, max: number }}
|
|
84
|
+
*/
|
|
85
|
+
export function computeModifiedRange(dieType: DieTypeValue, modifier: RollModifierInstance): {
|
|
86
|
+
min: number;
|
|
87
|
+
max: number;
|
|
88
|
+
};
|
|
89
|
+
//# sourceMappingURL=ModifiedTestConditions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ModifiedTestConditions.d.ts","sourceRoot":"","sources":["../../src/entities/ModifiedTestConditions.js"],"names":[],"mappings":"4BAyBa,OAAO,YAAY,EAAE,aAAa;2BAClC,OAAO,WAAW,EAAE,YAAY;mCAChC,OAAO,gBAAgB,EAAE,oBAAoB;mCAC7C,OAAO,gBAAgB,EAAE,oBAAoB;;mBAsN5C;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE;;+BAI7B,iBAAiB,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE;+BACtC,iBAAiB,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE;qCAChD,iBAAiB,GAAG;IAAE,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE;8BACxC,iBAAiB,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAAE;yBAI5F,gBAAgB,GAAG,eAAe,GAAG,gBAAgB,GAAG,sBAAsB;6CAI9E,YAAY,CAAC,OAAO,sBAAsB,CAAC;AA1MxD;;;;;GAKG;AACH;IACE;;;;;;OAMG;IACH,sBANW,aAAa,cACb,UAAU,WACV,YAAY,YACZ,oBAAoB,GAAG,oBAAoB,EAmErD;IAVC,4BAA4B;IAC5B,UADW,aAAa,CACA;IACxB,yBAAyB;IACzB,YADW,UAAU,CACO;IAC5B,2BAA2B;IAC3B,SADW,YAAY,CACD;IACtB,mCAAmC;IACnC,UADW,oBAAoB,CACZ;IACnB,2CAA2C;IAC3C,eADW;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CACb;IAG5B;;;OAGG;IACH,iBASC;CACF;AAED;;;;;;;GAOG;AACH,kDAJW,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,YAChC,aAAa,GACX,OAAO,CAiFnB;AAtND;;;;;GAKG;AAEH;;;;;;;GAOG;AACH,8CAJW,YAAY,YACZ,oBAAoB,GAClB;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAgBxC"}
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @platonic-dice/core/src/entities/ModifiedTestConditions
|
|
3
|
+
* @description
|
|
4
|
+
* Represents test conditions for modified rolls, where the achievable range
|
|
5
|
+
* is determined by both the base die type and the applied modifier.
|
|
6
|
+
*
|
|
7
|
+
* Unlike {@link TestConditions}, this class validates targets against the
|
|
8
|
+
* **modified range** rather than just the base die faces.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* // D6 with +10 modifier can reach 11-16
|
|
12
|
+
* const conditions = new ModifiedTestConditions(
|
|
13
|
+
* TestType.AtLeast,
|
|
14
|
+
* { target: 15 },
|
|
15
|
+
* DieType.D6,
|
|
16
|
+
* (n) => n + 10
|
|
17
|
+
* );
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
const { isValidDieType } = require("./DieType");
|
|
21
|
+
const { isValidTestType } = require("./TestType");
|
|
22
|
+
const { normaliseRollModifier } = require("./RollModifier");
|
|
23
|
+
const { numSides } = require("../utils");
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @typedef {import("./TestType").TestTypeValue} TestTypeValue
|
|
27
|
+
* @typedef {import("./DieType").DieTypeValue} DieTypeValue
|
|
28
|
+
* @typedef {import("./RollModifier").RollModifierFunction} RollModifierFunction
|
|
29
|
+
* @typedef {import("./RollModifier").RollModifierInstance} RollModifierInstance
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Computes the achievable range for a die + modifier combination.
|
|
34
|
+
*
|
|
35
|
+
* @private
|
|
36
|
+
* @param {DieTypeValue} dieType
|
|
37
|
+
* @param {RollModifierInstance} modifier
|
|
38
|
+
* @returns {{ min: number, max: number }}
|
|
39
|
+
*/
|
|
40
|
+
function computeModifiedRange(dieType, modifier) {
|
|
41
|
+
const sides = numSides(dieType);
|
|
42
|
+
const minRoll = 1;
|
|
43
|
+
const maxRoll = sides;
|
|
44
|
+
|
|
45
|
+
// Apply modifier to both extremes
|
|
46
|
+
const minModified = modifier.apply(minRoll);
|
|
47
|
+
const maxModified = modifier.apply(maxRoll);
|
|
48
|
+
|
|
49
|
+
// Handle cases where modifier might reverse order (e.g., negative multipliers)
|
|
50
|
+
return {
|
|
51
|
+
min: Math.min(minModified, maxModified),
|
|
52
|
+
max: Math.max(minModified, maxModified),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Represents a set of validated test conditions for modified rolls.
|
|
58
|
+
*
|
|
59
|
+
* This class is similar to {@link TestConditions} but validates numeric
|
|
60
|
+
* targets against the achievable range after applying a modifier.
|
|
61
|
+
*/
|
|
62
|
+
class ModifiedTestConditions {
|
|
63
|
+
/**
|
|
64
|
+
* @param {TestTypeValue} testType - The test type.
|
|
65
|
+
* @param {Conditions} conditions - The test conditions object.
|
|
66
|
+
* @param {DieTypeValue} dieType - The base die type.
|
|
67
|
+
* @param {RollModifierFunction | RollModifierInstance} modifier - The modifier to apply.
|
|
68
|
+
* @throws {TypeError|RangeError} If the test type or conditions are invalid.
|
|
69
|
+
*/
|
|
70
|
+
constructor(testType, conditions, dieType, modifier) {
|
|
71
|
+
if (!isValidTestType(testType)) {
|
|
72
|
+
throw new TypeError(`Invalid test type: ${testType}`);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (!conditions || typeof conditions !== "object") {
|
|
76
|
+
throw new TypeError("conditions must be an object.");
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (!dieType) {
|
|
80
|
+
throw new TypeError("dieType is required.");
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (!modifier) {
|
|
84
|
+
throw new TypeError("modifier is required.");
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Normalize the modifier
|
|
88
|
+
const mod = normaliseRollModifier(modifier);
|
|
89
|
+
|
|
90
|
+
// Compute the achievable range with this modifier
|
|
91
|
+
const range = computeModifiedRange(dieType, mod);
|
|
92
|
+
|
|
93
|
+
// Validate conditions against the modified range
|
|
94
|
+
if (
|
|
95
|
+
!areValidModifiedTestConditions(
|
|
96
|
+
{ ...conditions, modifiedRange: range },
|
|
97
|
+
testType
|
|
98
|
+
)
|
|
99
|
+
) {
|
|
100
|
+
switch (testType) {
|
|
101
|
+
case "at_least":
|
|
102
|
+
case "at_most":
|
|
103
|
+
case "exact":
|
|
104
|
+
throw new RangeError(
|
|
105
|
+
`Invalid ${testType} condition for ${dieType} with modifier: target must be achievable (range: ${range.min}–${range.max}).`
|
|
106
|
+
);
|
|
107
|
+
case "within":
|
|
108
|
+
throw new RangeError(
|
|
109
|
+
`Invalid 'within' condition for ${dieType} with modifier: range must be achievable (${range.min}–${range.max}).`
|
|
110
|
+
);
|
|
111
|
+
case "in_list":
|
|
112
|
+
throw new RangeError(
|
|
113
|
+
`Invalid 'in_list' condition for ${dieType} with modifier: values must be achievable (${range.min}–${range.max}).`
|
|
114
|
+
);
|
|
115
|
+
case "skill":
|
|
116
|
+
throw new RangeError(
|
|
117
|
+
`Invalid 'skill' condition for ${dieType} with modifier: thresholds must be achievable (${range.min}–${range.max}).`
|
|
118
|
+
);
|
|
119
|
+
default:
|
|
120
|
+
throw new TypeError(`Unknown testType '${testType}'.`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** @type {TestTypeValue} */
|
|
125
|
+
this.testType = testType;
|
|
126
|
+
/** @type {Conditions} */
|
|
127
|
+
this.conditions = conditions;
|
|
128
|
+
/** @type {DieTypeValue} */
|
|
129
|
+
this.dieType = dieType;
|
|
130
|
+
/** @type {RollModifierInstance} */
|
|
131
|
+
this.modifier = mod;
|
|
132
|
+
/** @type {{ min: number, max: number }} */
|
|
133
|
+
this.modifiedRange = range;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Validates that the test conditions still conform to spec.
|
|
138
|
+
* @throws {TypeError} If the test conditions are invalid.
|
|
139
|
+
*/
|
|
140
|
+
validate() {
|
|
141
|
+
if (
|
|
142
|
+
!areValidModifiedTestConditions(
|
|
143
|
+
{ ...this.conditions, modifiedRange: this.modifiedRange },
|
|
144
|
+
this.testType
|
|
145
|
+
)
|
|
146
|
+
) {
|
|
147
|
+
throw new TypeError("Invalid modified test conditions.");
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Validates test conditions against a modified range.
|
|
154
|
+
*
|
|
155
|
+
* @private
|
|
156
|
+
* @param {Conditions & Record<string, any>} c - Conditions with modifiedRange
|
|
157
|
+
* @param {TestTypeValue} testType
|
|
158
|
+
* @returns {boolean}
|
|
159
|
+
*/
|
|
160
|
+
function areValidModifiedTestConditions(c, testType) {
|
|
161
|
+
if (!c.modifiedRange) return false;
|
|
162
|
+
|
|
163
|
+
const { min, max } = c.modifiedRange;
|
|
164
|
+
|
|
165
|
+
switch (testType) {
|
|
166
|
+
case "exact":
|
|
167
|
+
case "at_least":
|
|
168
|
+
case "at_most":
|
|
169
|
+
return (
|
|
170
|
+
typeof c.target === "number" &&
|
|
171
|
+
Number.isInteger(c.target) &&
|
|
172
|
+
c.target >= min &&
|
|
173
|
+
c.target <= max
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
case "within":
|
|
177
|
+
return (
|
|
178
|
+
typeof c.min === "number" &&
|
|
179
|
+
typeof c.max === "number" &&
|
|
180
|
+
Number.isInteger(c.min) &&
|
|
181
|
+
Number.isInteger(c.max) &&
|
|
182
|
+
c.min <= c.max &&
|
|
183
|
+
c.min >= min &&
|
|
184
|
+
c.max <= max
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
case "in_list":
|
|
188
|
+
return (
|
|
189
|
+
Array.isArray(c.values) &&
|
|
190
|
+
c.values.length > 0 &&
|
|
191
|
+
c.values.every(
|
|
192
|
+
(v) =>
|
|
193
|
+
typeof v === "number" && Number.isInteger(v) && v >= min && v <= max
|
|
194
|
+
)
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
case "skill":
|
|
198
|
+
// target is required
|
|
199
|
+
if (
|
|
200
|
+
typeof c.target !== "number" ||
|
|
201
|
+
!Number.isInteger(c.target) ||
|
|
202
|
+
c.target < min ||
|
|
203
|
+
c.target > max
|
|
204
|
+
) {
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// critical_success is optional but must be valid if present
|
|
209
|
+
if (c.critical_success !== undefined) {
|
|
210
|
+
if (
|
|
211
|
+
typeof c.critical_success !== "number" ||
|
|
212
|
+
!Number.isInteger(c.critical_success) ||
|
|
213
|
+
c.critical_success < min ||
|
|
214
|
+
c.critical_success > max ||
|
|
215
|
+
c.critical_success < c.target
|
|
216
|
+
) {
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// critical_failure is optional but must be valid if present
|
|
222
|
+
if (c.critical_failure !== undefined) {
|
|
223
|
+
if (
|
|
224
|
+
typeof c.critical_failure !== "number" ||
|
|
225
|
+
!Number.isInteger(c.critical_failure) ||
|
|
226
|
+
c.critical_failure < min ||
|
|
227
|
+
c.critical_failure > max ||
|
|
228
|
+
c.critical_failure > c.target
|
|
229
|
+
) {
|
|
230
|
+
return false;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return true;
|
|
235
|
+
|
|
236
|
+
default:
|
|
237
|
+
return false;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* @typedef {Object} BaseTestCondition
|
|
243
|
+
* @property {{ min: number, max: number }} modifiedRange
|
|
244
|
+
*/
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* @typedef {BaseTestCondition & { target: number }} TargetConditions
|
|
248
|
+
* @typedef {BaseTestCondition & { min: number, max: number }} WithinConditions
|
|
249
|
+
* @typedef {BaseTestCondition & { values: number[] }} SpecificListConditions
|
|
250
|
+
* @typedef {BaseTestCondition & { target: number, critical_success?: number, critical_failure?: number }} SkillConditions
|
|
251
|
+
*/
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* @typedef {TargetConditions | SkillConditions | WithinConditions | SpecificListConditions} Conditions
|
|
255
|
+
*/
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* @typedef {InstanceType<typeof ModifiedTestConditions>} ModifiedTestConditionsInstance
|
|
259
|
+
*/
|
|
260
|
+
|
|
261
|
+
module.exports = {
|
|
262
|
+
ModifiedTestConditions,
|
|
263
|
+
areValidModifiedTestConditions,
|
|
264
|
+
computeModifiedRange,
|
|
265
|
+
};
|
package/dist/entities/index.d.ts
CHANGED
|
@@ -10,7 +10,10 @@ import { isValidRollType } from "./RollType.js";
|
|
|
10
10
|
import { TestConditions } from "./TestConditions.js";
|
|
11
11
|
import { areValidTestConditions } from "./TestConditions.js";
|
|
12
12
|
import { normaliseTestConditions } from "./TestConditions.js";
|
|
13
|
+
import { ModifiedTestConditions } from "./ModifiedTestConditions.js";
|
|
14
|
+
import { areValidModifiedTestConditions } from "./ModifiedTestConditions.js";
|
|
15
|
+
import { computeModifiedRange } from "./ModifiedTestConditions.js";
|
|
13
16
|
import { TestType } from "./TestType.js";
|
|
14
17
|
import { isValidTestType } from "./TestType.js";
|
|
15
|
-
export { DieType, isValidDieType, Outcome, isValidOutcome, RollModifier, isValidRollModifier, normaliseRollModifier, RollType, isValidRollType, TestConditions, areValidTestConditions, normaliseTestConditions, TestType, isValidTestType };
|
|
18
|
+
export { DieType, isValidDieType, Outcome, isValidOutcome, RollModifier, isValidRollModifier, normaliseRollModifier, RollType, isValidRollType, TestConditions, areValidTestConditions, normaliseTestConditions, ModifiedTestConditions, areValidModifiedTestConditions, computeModifiedRange, TestType, isValidTestType };
|
|
16
19
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/entities/index.js
CHANGED
|
@@ -26,6 +26,11 @@ const {
|
|
|
26
26
|
areValidTestConditions,
|
|
27
27
|
normaliseTestConditions,
|
|
28
28
|
} = require("./TestConditions.js");
|
|
29
|
+
const {
|
|
30
|
+
ModifiedTestConditions,
|
|
31
|
+
areValidModifiedTestConditions,
|
|
32
|
+
computeModifiedRange,
|
|
33
|
+
} = require("./ModifiedTestConditions.js");
|
|
29
34
|
const { TestType, isValidTestType } = require("./TestType.js");
|
|
30
35
|
|
|
31
36
|
module.exports = {
|
|
@@ -41,6 +46,9 @@ module.exports = {
|
|
|
41
46
|
TestConditions,
|
|
42
47
|
areValidTestConditions,
|
|
43
48
|
normaliseTestConditions,
|
|
49
|
+
ModifiedTestConditions,
|
|
50
|
+
areValidModifiedTestConditions,
|
|
51
|
+
computeModifiedRange,
|
|
44
52
|
TestType,
|
|
45
53
|
isValidTestType,
|
|
46
54
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
declare const _exports: typeof import("./roll") & typeof import("./rollDice") & typeof import("./rollMod") & typeof import("./rollDiceMod") & typeof import("./rollTest") & typeof import("./entities") & {
|
|
1
|
+
declare const _exports: typeof import("./roll") & typeof import("./rollDice") & typeof import("./rollMod") & typeof import("./rollDiceMod") & typeof import("./rollTest") & typeof import("./rollModTest") & typeof import("./analyseTest") & typeof import("./analyseModTest") & typeof import("./entities") & {
|
|
2
2
|
default: any;
|
|
3
3
|
};
|
|
4
4
|
export = _exports;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.js"],"names":[],"mappings":"wBAyBU,cAAc,QAAQ,CAAC,GAChC,cAAuB,YAAY,CAAC,GACpC,cAAuB,WAAW,CAAC,GACnC,cAAuB,eAAe,CAAC,GACvC,cAAuB,YAAY,CAAC,GACpC,cAAuB,eAAe,CAAC,GACvC,cAAuB,eAAe,CAAC,GACvC,cAAuB,kBAAkB,CAAC,GAC1C,cAAuB,YAAY,CAAC,GACpC;IAAW,OAAO,EAAE,GAAG,CAAA;CAAE"}
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Re-exports all main rolling functions and modifiers.
|
|
6
6
|
*
|
|
7
7
|
* @example
|
|
8
|
-
* import { roll, rollMod, rollDice, rollDiceMod, rollTest } from "@platonic-dice/core";
|
|
8
|
+
* import { roll, rollMod, rollDice, rollDiceMod, rollTest, rollModTest } from "@platonic-dice/core";
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
// --- Core modules ---
|
|
@@ -14,6 +14,9 @@ const roll = require("./roll.js");
|
|
|
14
14
|
const rollMod = require("./rollMod.js");
|
|
15
15
|
const rollDiceMod = require("./rollDiceMod.js");
|
|
16
16
|
const rollTest = require("./rollTest.js");
|
|
17
|
+
const rollModTest = require("./rollModTest.js");
|
|
18
|
+
const analyseTest = require("./analyseTest.js");
|
|
19
|
+
const analyseModTest = require("./analyseModTest.js");
|
|
17
20
|
|
|
18
21
|
// --- Entities (public API) ---
|
|
19
22
|
const entities = require("./entities");
|
|
@@ -25,6 +28,9 @@ const entities = require("./entities");
|
|
|
25
28
|
* typeof import("./rollMod") &
|
|
26
29
|
* typeof import("./rollDiceMod") &
|
|
27
30
|
* typeof import("./rollTest") &
|
|
31
|
+
* typeof import("./rollModTest") &
|
|
32
|
+
* typeof import("./analyseTest") &
|
|
33
|
+
* typeof import("./analyseModTest") &
|
|
28
34
|
* typeof import("./entities") &
|
|
29
35
|
* { default: any }}
|
|
30
36
|
*/
|
|
@@ -35,6 +41,9 @@ module.exports = {
|
|
|
35
41
|
...rollDiceMod,
|
|
36
42
|
...entities,
|
|
37
43
|
...rollTest,
|
|
44
|
+
...rollModTest,
|
|
45
|
+
...analyseTest,
|
|
46
|
+
...analyseModTest,
|
|
38
47
|
default: undefined, // placeholder; will be overwritten
|
|
39
48
|
};
|
|
40
49
|
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
export type DieTypeValue = import("./entities/DieType").DieTypeValue;
|
|
2
|
+
export type OutcomeValue = import("./entities/Outcome").OutcomeValue;
|
|
3
|
+
export type RollTypeValue = import("./entities/RollType").RollTypeValue;
|
|
4
|
+
export type RollModifierFunction = import("./entities/RollModifier").RollModifierFunction;
|
|
5
|
+
export type RollModifierInstance = import("./entities/RollModifier").RollModifierInstance;
|
|
6
|
+
export type TestTypeValue = import("./entities/TestType").TestTypeValue;
|
|
7
|
+
export type TestConditionsInstance = import("./entities/TestConditions").TestConditionsInstance;
|
|
8
|
+
/**
|
|
9
|
+
* Rolls a die with a modifier and evaluates the modified result against test conditions.
|
|
10
|
+
*
|
|
11
|
+
* @function rollModTest
|
|
12
|
+
* @param {DieTypeValue} dieType - The type of die to roll (e.g., `DieType.D20`).
|
|
13
|
+
* @param {RollModifierFunction|RollModifierInstance} modifier - The modifier to apply to the roll.
|
|
14
|
+
* Can be either:
|
|
15
|
+
* - A function `(n: number) => number`
|
|
16
|
+
* - A {@link RollModifier} instance
|
|
17
|
+
* @param {TestConditionsInstance|{ testType: TestTypeValue, [key: string]: any }} testConditions
|
|
18
|
+
* Can be:
|
|
19
|
+
* - A `TestConditions` instance
|
|
20
|
+
* - A plain object `{ testType, ...conditions }`
|
|
21
|
+
* @param {RollTypeValue} [rollType=undefined] - Optional roll mode (`RollType.Advantage` or `RollType.Disadvantage`).
|
|
22
|
+
* @param {Object} [options={}] - Optional configuration.
|
|
23
|
+
* @param {boolean} [options.useNaturalCrits] - If true, natural max/min rolls on the die trigger
|
|
24
|
+
* critical success/failure (for Skill tests) or success/failure (for other test types).
|
|
25
|
+
* If undefined, defaults to true for Skill test type and false for all others.
|
|
26
|
+
* @returns {{ base: number, modified: number, outcome: OutcomeValue }}
|
|
27
|
+
* - `base`: The raw die roll
|
|
28
|
+
* - `modified`: The roll after applying the modifier
|
|
29
|
+
* - `outcome`: The success/failure result based on test conditions
|
|
30
|
+
* @throws {TypeError} If `dieType`, `modifier`, or `testConditions` are invalid.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* const result = rollModTest(
|
|
34
|
+
* DieType.D20,
|
|
35
|
+
* (n) => n + 2,
|
|
36
|
+
* { testType: TestType.AtLeast, target: 15 }
|
|
37
|
+
* );
|
|
38
|
+
* console.log(result); // { base: 14, modified: 16, outcome: "success" }
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* // With natural crits enabled (TTRPG style)
|
|
42
|
+
* const result = rollModTest(
|
|
43
|
+
* DieType.D20,
|
|
44
|
+
* (n) => n + 5,
|
|
45
|
+
* { testType: TestType.Skill, target: 15, critical_success: 25, critical_failure: 2 },
|
|
46
|
+
* undefined,
|
|
47
|
+
* { useNaturalCrits: true }
|
|
48
|
+
* );
|
|
49
|
+
* // If base roll is 20, outcome is always "critical_success"
|
|
50
|
+
* // If base roll is 1, outcome is always "critical_failure"
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* // With advantage - compares outcomes, not just base rolls
|
|
54
|
+
* const result = rollModTest(
|
|
55
|
+
* DieType.D20,
|
|
56
|
+
* (n) => n + 3,
|
|
57
|
+
* { testType: TestType.Skill, target: 12, critical_success: 20, critical_failure: 1 },
|
|
58
|
+
* RollType.Advantage
|
|
59
|
+
* );
|
|
60
|
+
* // Rolls twice, returns the result with the better outcome
|
|
61
|
+
*/
|
|
62
|
+
export function rollModTest(dieType: DieTypeValue, modifier: RollModifierFunction | RollModifierInstance, testConditions: TestConditionsInstance | {
|
|
63
|
+
testType: TestTypeValue;
|
|
64
|
+
[key: string]: any;
|
|
65
|
+
}, rollType?: RollTypeValue, options?: {
|
|
66
|
+
useNaturalCrits?: boolean | undefined;
|
|
67
|
+
}): {
|
|
68
|
+
base: number;
|
|
69
|
+
modified: number;
|
|
70
|
+
outcome: OutcomeValue;
|
|
71
|
+
};
|
|
72
|
+
//# sourceMappingURL=rollModTest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rollModTest.d.ts","sourceRoot":"","sources":["../src/rollModTest.js"],"names":[],"mappings":"2BAoCa,OAAO,oBAAoB,EAAE,YAAY;2BACzC,OAAO,oBAAoB,EAAE,YAAY;4BACzC,OAAO,qBAAqB,EAAE,aAAa;mCAC3C,OAAO,yBAAyB,EAAE,oBAAoB;mCACtD,OAAO,yBAAyB,EAAE,oBAAoB;4BACtD,OAAO,qBAAqB,EAAE,aAAa;qCAC3C,OAAO,2BAA2B,EAAE,sBAAsB;AAyBvE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,qCAlDW,YAAY,YACZ,oBAAoB,GAAC,oBAAoB,kBAIzC,sBAAsB,GAAC;IAAE,QAAQ,EAAE,aAAa,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,aAItE,aAAa,YAErB;IAA0B,eAAe;CAGzC,GAAU;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,YAAY,CAAA;CAAE,CAsHrE"}
|