@swrpg-online/dice 0.9.0 → 1.0.4
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 +103 -8
- package/dist/cli.d.ts +4 -0
- package/dist/cli.js +130 -0
- package/dist/dice.d.ts +1 -1
- package/dist/dice.js +289 -51
- package/dist/index.d.ts +3 -3
- package/dist/pools.d.ts +1 -1
- package/dist/pools.js +4 -4
- package/dist/types.d.ts +1 -1
- package/package.json +24 -3
- package/.github/workflows/publish.yml +0 -31
- package/.husky/.skip-tests +0 -0
- package/.husky/pre-commit +0 -32
- package/.replit +0 -8
- package/coverage/clover.xml +0 -113
- package/coverage/coverage-final.json +0 -4
- package/coverage/lcov-report/base.css +0 -224
- package/coverage/lcov-report/block-navigation.js +0 -87
- package/coverage/lcov-report/dice.ts.html +0 -817
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +0 -146
- package/coverage/lcov-report/index.ts.html +0 -109
- package/coverage/lcov-report/pools.ts.html +0 -253
- package/coverage/lcov-report/prettify.css +0 -1
- package/coverage/lcov-report/prettify.js +0 -2
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +0 -196
- package/coverage/lcov.info +0 -246
- package/jest.config.js +0 -8
- package/src/dice.ts +0 -244
- package/src/index.ts +0 -8
- package/src/pools.ts +0 -56
- package/src/types.ts +0 -30
- package/tests/dice.test.ts +0 -351
- package/tests/pools.test.ts +0 -86
- package/tsconfig.json +0 -14
package/src/pools.ts
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { DicePool } from './types';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Creates a basic skill check dice pool
|
|
5
|
-
* @param ability Number of ability (green) dice
|
|
6
|
-
* @param proficiency Number of proficiency (yellow) dice
|
|
7
|
-
* @returns DicePool configured for a basic skill check
|
|
8
|
-
*/
|
|
9
|
-
export const createSkillCheck = (ability: number, proficiency: number): DicePool => ({
|
|
10
|
-
abilityDice: Math.max(0, ability),
|
|
11
|
-
proficiencyDice: Math.max(0, proficiency)
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Creates a combat check dice pool with optional boost die
|
|
16
|
-
* @param ability Number of ability (green) dice
|
|
17
|
-
* @param proficiency Number of proficiency (yellow) dice
|
|
18
|
-
* @param boost Number of boost (blue) dice
|
|
19
|
-
* @returns DicePool configured for a combat check
|
|
20
|
-
*/
|
|
21
|
-
export const createCombatCheck = (ability: number, proficiency: number, boost: number = 0): DicePool => ({
|
|
22
|
-
abilityDice: Math.max(0, ability),
|
|
23
|
-
proficiencyDice: Math.max(0, proficiency),
|
|
24
|
-
boostDice: Math.max(0, boost)
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Creates an opposed check dice pool
|
|
29
|
-
* @param ability Number of ability (green) dice
|
|
30
|
-
* @param proficiency Number of proficiency (yellow) dice
|
|
31
|
-
* @param difficulty Number of difficulty (purple) dice
|
|
32
|
-
* @param challenge Number of challenge (red) dice
|
|
33
|
-
* @returns DicePool configured for an opposed check
|
|
34
|
-
*/
|
|
35
|
-
export const createOpposedCheck = (
|
|
36
|
-
ability: number,
|
|
37
|
-
proficiency: number,
|
|
38
|
-
difficulty: number,
|
|
39
|
-
challenge: number = 0
|
|
40
|
-
): DicePool => ({
|
|
41
|
-
abilityDice: Math.max(0, ability),
|
|
42
|
-
proficiencyDice: Math.max(0, proficiency),
|
|
43
|
-
difficultyDice: Math.max(0, difficulty),
|
|
44
|
-
challengeDice: Math.max(0, challenge)
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Creates a difficulty check dice pool
|
|
49
|
-
* @param difficulty Number of difficulty (purple) dice
|
|
50
|
-
* @param challenge Number of challenge (red) dice
|
|
51
|
-
* @returns DicePool configured for a pure difficulty check
|
|
52
|
-
*/
|
|
53
|
-
export const createDifficultyPool = (difficulty: number, challenge: number = 0): DicePool => ({
|
|
54
|
-
difficultyDice: Math.max(0, difficulty),
|
|
55
|
-
challengeDice: Math.max(0, challenge)
|
|
56
|
-
});
|
package/src/types.ts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
export type DicePool = {
|
|
2
|
-
boostDice?: number;
|
|
3
|
-
abilityDice?: number;
|
|
4
|
-
proficiencyDice?: number;
|
|
5
|
-
setBackDice?: number;
|
|
6
|
-
difficultyDice?: number;
|
|
7
|
-
challengeDice?: number;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export type DiceResult = {
|
|
11
|
-
successes: number;
|
|
12
|
-
failures: number;
|
|
13
|
-
advantages: number;
|
|
14
|
-
threats: number;
|
|
15
|
-
triumphs: number;
|
|
16
|
-
despair: number;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export type DieType = 'boost' | 'ability' | 'proficiency' | 'setback' | 'difficulty' | 'challenge';
|
|
20
|
-
|
|
21
|
-
export type DetailedDieResult = {
|
|
22
|
-
type: DieType;
|
|
23
|
-
roll: number;
|
|
24
|
-
result: DiceResult;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
export type RollResult = {
|
|
28
|
-
results: DetailedDieResult[];
|
|
29
|
-
summary: DiceResult;
|
|
30
|
-
};
|
package/tests/dice.test.ts
DELETED
|
@@ -1,351 +0,0 @@
|
|
|
1
|
-
import { roll } from '../src/dice';
|
|
2
|
-
import { DicePool, RollResult } from '../src/types';
|
|
3
|
-
|
|
4
|
-
// Mock Math.random for deterministic tests
|
|
5
|
-
const mockMathRandom = (value: number) => {
|
|
6
|
-
const originalRandom = Math.random;
|
|
7
|
-
Math.random = jest.fn().mockReturnValue(value);
|
|
8
|
-
return () => {
|
|
9
|
-
Math.random = originalRandom;
|
|
10
|
-
};
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
describe('SWRPG Dice Rolling', () => {
|
|
14
|
-
afterEach(() => {
|
|
15
|
-
jest.restoreAllMocks();
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
describe('Detailed Roll Breakdown', () => {
|
|
19
|
-
test('returns detailed results for each die', () => {
|
|
20
|
-
const cleanup = mockMathRandom(0.5); // mid-range roll
|
|
21
|
-
const pool: DicePool = {
|
|
22
|
-
boostDice: 1,
|
|
23
|
-
abilityDice: 1
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
const result = roll(pool);
|
|
27
|
-
|
|
28
|
-
expect(result).toHaveProperty('results');
|
|
29
|
-
expect(result).toHaveProperty('summary');
|
|
30
|
-
expect(Array.isArray(result.results)).toBe(true);
|
|
31
|
-
expect(result.results).toHaveLength(2);
|
|
32
|
-
|
|
33
|
-
// Check structure of detailed results
|
|
34
|
-
result.results.forEach(dieResult => {
|
|
35
|
-
expect(dieResult).toHaveProperty('type');
|
|
36
|
-
expect(dieResult).toHaveProperty('roll');
|
|
37
|
-
expect(dieResult).toHaveProperty('result');
|
|
38
|
-
expect(['boost', 'ability']).toContain(dieResult.type);
|
|
39
|
-
expect(typeof dieResult.roll).toBe('number');
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
cleanup();
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
test('properly identifies die types', () => {
|
|
46
|
-
const cleanup = mockMathRandom(0.5);
|
|
47
|
-
const pool: DicePool = {
|
|
48
|
-
boostDice: 1,
|
|
49
|
-
abilityDice: 1,
|
|
50
|
-
proficiencyDice: 1,
|
|
51
|
-
setBackDice: 1,
|
|
52
|
-
difficultyDice: 1,
|
|
53
|
-
challengeDice: 1
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
const result = roll(pool);
|
|
57
|
-
const dieTypes = result.results.map(r => r.type);
|
|
58
|
-
|
|
59
|
-
expect(dieTypes).toContain('boost');
|
|
60
|
-
expect(dieTypes).toContain('ability');
|
|
61
|
-
expect(dieTypes).toContain('proficiency');
|
|
62
|
-
expect(dieTypes).toContain('setback');
|
|
63
|
-
expect(dieTypes).toContain('difficulty');
|
|
64
|
-
expect(dieTypes).toContain('challenge');
|
|
65
|
-
|
|
66
|
-
cleanup();
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
describe('Individual Die Results', () => {
|
|
71
|
-
describe('Boost Die (d6)', () => {
|
|
72
|
-
test.each([
|
|
73
|
-
[1, { successes: 0, failures: 0, advantages: 0, threats: 0, triumphs: 0, despair: 0 }],
|
|
74
|
-
[2, { successes: 0, failures: 0, advantages: 0, threats: 0, triumphs: 0, despair: 0 }],
|
|
75
|
-
[3, { successes: 1, failures: 0, advantages: 0, threats: 0, triumphs: 0, despair: 0 }],
|
|
76
|
-
[4, { successes: 1, failures: 0, advantages: 1, threats: 0, triumphs: 0, despair: 0 }],
|
|
77
|
-
[5, { successes: 0, failures: 0, advantages: 2, threats: 0, triumphs: 0, despair: 0 }],
|
|
78
|
-
[6, { successes: 0, failures: 0, advantages: 1, threats: 0, triumphs: 0, despair: 0 }]
|
|
79
|
-
])('face value %i should return correct results', (value, expected) => {
|
|
80
|
-
const cleanup = mockMathRandom((value - 1) / 6);
|
|
81
|
-
const pool: DicePool = { boostDice: 1 };
|
|
82
|
-
expect(roll(pool).summary).toEqual(expected);
|
|
83
|
-
cleanup();
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
describe('Ability Die (d8)', () => {
|
|
88
|
-
test.each([
|
|
89
|
-
[1, { successes: 0, failures: 0, advantages: 0, threats: 0, triumphs: 0, despair: 0 }],
|
|
90
|
-
[2, { successes: 1, failures: 0, advantages: 0, threats: 0, triumphs: 0, despair: 0 }],
|
|
91
|
-
[3, { successes: 1, failures: 0, advantages: 0, threats: 0, triumphs: 0, despair: 0 }],
|
|
92
|
-
[4, { successes: 2, failures: 0, advantages: 0, threats: 0, triumphs: 0, despair: 0 }],
|
|
93
|
-
[5, { successes: 0, failures: 0, advantages: 1, threats: 0, triumphs: 0, despair: 0 }],
|
|
94
|
-
[6, { successes: 0, failures: 0, advantages: 1, threats: 0, triumphs: 0, despair: 0 }],
|
|
95
|
-
[7, { successes: 1, failures: 0, advantages: 1, threats: 0, triumphs: 0, despair: 0 }],
|
|
96
|
-
[8, { successes: 0, failures: 0, advantages: 2, threats: 0, triumphs: 0, despair: 0 }]
|
|
97
|
-
])('face value %i should return correct results', (value, expected) => {
|
|
98
|
-
const cleanup = mockMathRandom((value - 1) / 8);
|
|
99
|
-
const pool: DicePool = { abilityDice: 1 };
|
|
100
|
-
expect(roll(pool).summary).toEqual(expected);
|
|
101
|
-
cleanup();
|
|
102
|
-
});
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
describe('Proficiency Die (d12)', () => {
|
|
106
|
-
test.each([
|
|
107
|
-
[1, { successes: 0, failures: 0, advantages: 0, threats: 0, triumphs: 0, despair: 0 }],
|
|
108
|
-
[2, { successes: 1, failures: 0, advantages: 0, threats: 0, triumphs: 0, despair: 0 }],
|
|
109
|
-
[3, { successes: 1, failures: 0, advantages: 0, threats: 0, triumphs: 0, despair: 0 }],
|
|
110
|
-
[4, { successes: 2, failures: 0, advantages: 0, threats: 0, triumphs: 0, despair: 0 }],
|
|
111
|
-
[5, { successes: 2, failures: 0, advantages: 0, threats: 0, triumphs: 0, despair: 0 }],
|
|
112
|
-
[6, { successes: 0, failures: 0, advantages: 1, threats: 0, triumphs: 0, despair: 0 }],
|
|
113
|
-
[7, { successes: 1, failures: 0, advantages: 1, threats: 0, triumphs: 0, despair: 0 }],
|
|
114
|
-
[8, { successes: 1, failures: 0, advantages: 1, threats: 0, triumphs: 0, despair: 0 }],
|
|
115
|
-
[9, { successes: 1, failures: 0, advantages: 1, threats: 0, triumphs: 0, despair: 0 }],
|
|
116
|
-
[10, { successes: 0, failures: 0, advantages: 2, threats: 0, triumphs: 0, despair: 0 }],
|
|
117
|
-
[11, { successes: 0, failures: 0, advantages: 2, threats: 0, triumphs: 0, despair: 0 }],
|
|
118
|
-
[12, { successes: 0, failures: 0, advantages: 0, threats: 0, triumphs: 1, despair: 0 }]
|
|
119
|
-
])('face value %i should return correct results', (value, expected) => {
|
|
120
|
-
const cleanup = mockMathRandom((value - 1) / 12);
|
|
121
|
-
const pool: DicePool = { proficiencyDice: 1 };
|
|
122
|
-
expect(roll(pool).summary).toEqual(expected);
|
|
123
|
-
cleanup();
|
|
124
|
-
});
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
describe('Setback Die (d6)', () => {
|
|
128
|
-
test.each([
|
|
129
|
-
[1, { successes: 0, failures: 0, advantages: 0, threats: 0, triumphs: 0, despair: 0 }],
|
|
130
|
-
[2, { successes: 0, failures: 0, advantages: 0, threats: 0, triumphs: 0, despair: 0 }],
|
|
131
|
-
[3, { successes: 0, failures: 1, advantages: 0, threats: 0, triumphs: 0, despair: 0 }],
|
|
132
|
-
[4, { successes: 0, failures: 1, advantages: 0, threats: 0, triumphs: 0, despair: 0 }],
|
|
133
|
-
[5, { successes: 0, failures: 0, advantages: 0, threats: 1, triumphs: 0, despair: 0 }],
|
|
134
|
-
[6, { successes: 0, failures: 0, advantages: 0, threats: 1, triumphs: 0, despair: 0 }]
|
|
135
|
-
])('face value %i should return correct results', (value, expected) => {
|
|
136
|
-
const cleanup = mockMathRandom((value - 1) / 6);
|
|
137
|
-
const pool: DicePool = { setBackDice: 1 };
|
|
138
|
-
expect(roll(pool).summary).toEqual(expected);
|
|
139
|
-
cleanup();
|
|
140
|
-
});
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
describe('Difficulty Die (d8)', () => {
|
|
144
|
-
test.each([
|
|
145
|
-
[1, { successes: 0, failures: 0, advantages: 0, threats: 0, triumphs: 0, despair: 0 }],
|
|
146
|
-
[2, { successes: 0, failures: 1, advantages: 0, threats: 0, triumphs: 0, despair: 0 }],
|
|
147
|
-
[3, { successes: 0, failures: 2, advantages: 0, threats: 0, triumphs: 0, despair: 0 }],
|
|
148
|
-
[4, { successes: 0, failures: 0, advantages: 0, threats: 1, triumphs: 0, despair: 0 }],
|
|
149
|
-
[5, { successes: 0, failures: 0, advantages: 0, threats: 1, triumphs: 0, despair: 0 }],
|
|
150
|
-
[6, { successes: 0, failures: 0, advantages: 0, threats: 1, triumphs: 0, despair: 0 }],
|
|
151
|
-
[7, { successes: 0, failures: 0, advantages: 0, threats: 2, triumphs: 0, despair: 0 }],
|
|
152
|
-
[8, { successes: 0, failures: 1, advantages: 0, threats: 1, triumphs: 0, despair: 0 }]
|
|
153
|
-
])('face value %i should return correct results', (value, expected) => {
|
|
154
|
-
const cleanup = mockMathRandom((value - 1) / 8);
|
|
155
|
-
const pool: DicePool = { difficultyDice: 1 };
|
|
156
|
-
expect(roll(pool).summary).toEqual(expected);
|
|
157
|
-
cleanup();
|
|
158
|
-
});
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
describe('Challenge Die (d12)', () => {
|
|
162
|
-
test.each([
|
|
163
|
-
[1, { successes: 0, failures: 0, advantages: 0, threats: 0, triumphs: 0, despair: 0 }],
|
|
164
|
-
[2, { successes: 0, failures: 1, advantages: 0, threats: 0, triumphs: 0, despair: 0 }],
|
|
165
|
-
[3, { successes: 0, failures: 1, advantages: 0, threats: 0, triumphs: 0, despair: 0 }],
|
|
166
|
-
[4, { successes: 0, failures: 2, advantages: 0, threats: 0, triumphs: 0, despair: 0 }],
|
|
167
|
-
[5, { successes: 0, failures: 2, advantages: 0, threats: 0, triumphs: 0, despair: 0 }],
|
|
168
|
-
[6, { successes: 0, failures: 0, advantages: 0, threats: 1, triumphs: 0, despair: 0 }],
|
|
169
|
-
[7, { successes: 0, failures: 0, advantages: 0, threats: 1, triumphs: 0, despair: 0 }],
|
|
170
|
-
[8, { successes: 0, failures: 1, advantages: 0, threats: 1, triumphs: 0, despair: 0 }],
|
|
171
|
-
[9, { successes: 0, failures: 1, advantages: 0, threats: 1, triumphs: 0, despair: 0 }],
|
|
172
|
-
[10, { successes: 0, failures: 0, advantages: 0, threats: 2, triumphs: 0, despair: 0 }],
|
|
173
|
-
[11, { successes: 0, failures: 0, advantages: 0, threats: 2, triumphs: 0, despair: 0 }],
|
|
174
|
-
[12, { successes: 0, failures: 0, advantages: 0, threats: 0, triumphs: 0, despair: 1 }]
|
|
175
|
-
])('face value %i should return correct results', (value, expected) => {
|
|
176
|
-
const cleanup = mockMathRandom((value - 1) / 12);
|
|
177
|
-
const pool: DicePool = { challengeDice: 1 };
|
|
178
|
-
expect(roll(pool).summary).toEqual(expected);
|
|
179
|
-
cleanup();
|
|
180
|
-
});
|
|
181
|
-
});
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
describe('Edge Cases', () => {
|
|
185
|
-
test('negative numbers default to 0', () => {
|
|
186
|
-
const pool: DicePool = {
|
|
187
|
-
boostDice: -1,
|
|
188
|
-
abilityDice: -2,
|
|
189
|
-
proficiencyDice: -1,
|
|
190
|
-
setBackDice: -3,
|
|
191
|
-
difficultyDice: -2,
|
|
192
|
-
challengeDice: -1
|
|
193
|
-
};
|
|
194
|
-
const expected = {
|
|
195
|
-
successes: 0,
|
|
196
|
-
failures: 0,
|
|
197
|
-
advantages: 0,
|
|
198
|
-
threats: 0,
|
|
199
|
-
triumphs: 0,
|
|
200
|
-
despair: 0
|
|
201
|
-
};
|
|
202
|
-
expect(roll(pool).summary).toEqual(expected);
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
test('undefined values default to 0', () => {
|
|
206
|
-
const pool: DicePool = {
|
|
207
|
-
boostDice: undefined,
|
|
208
|
-
abilityDice: undefined,
|
|
209
|
-
proficiencyDice: undefined,
|
|
210
|
-
setBackDice: undefined,
|
|
211
|
-
difficultyDice: undefined,
|
|
212
|
-
challengeDice: undefined
|
|
213
|
-
};
|
|
214
|
-
const expected = {
|
|
215
|
-
successes: 0,
|
|
216
|
-
failures: 0,
|
|
217
|
-
advantages: 0,
|
|
218
|
-
threats: 0,
|
|
219
|
-
triumphs: 0,
|
|
220
|
-
despair: 0
|
|
221
|
-
};
|
|
222
|
-
expect(roll(pool).summary).toEqual(expected);
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
test('empty pool returns zero results', () => {
|
|
226
|
-
const pool: DicePool = {};
|
|
227
|
-
const expected = {
|
|
228
|
-
successes: 0,
|
|
229
|
-
failures: 0,
|
|
230
|
-
advantages: 0,
|
|
231
|
-
threats: 0,
|
|
232
|
-
triumphs: 0,
|
|
233
|
-
despair: 0
|
|
234
|
-
};
|
|
235
|
-
expect(roll(pool).summary).toEqual(expected);
|
|
236
|
-
});
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
describe('Result Accumulation', () => {
|
|
240
|
-
test('successes and failures cancel out', () => {
|
|
241
|
-
// Mock to generate one success and one failure
|
|
242
|
-
const cleanup1 = mockMathRandom(1/8); // ability die success (face value 2)
|
|
243
|
-
const cleanup2 = mockMathRandom(1/8); // difficulty die failure (face value 2)
|
|
244
|
-
|
|
245
|
-
const pool: DicePool = {
|
|
246
|
-
abilityDice: 1,
|
|
247
|
-
difficultyDice: 1
|
|
248
|
-
};
|
|
249
|
-
|
|
250
|
-
const result = roll(pool);
|
|
251
|
-
expect(result.summary.successes).toBe(0);
|
|
252
|
-
expect(result.summary.failures).toBe(0);
|
|
253
|
-
|
|
254
|
-
cleanup1();
|
|
255
|
-
cleanup2();
|
|
256
|
-
});
|
|
257
|
-
|
|
258
|
-
test('advantages and threats accumulate independently', () => {
|
|
259
|
-
// Mock to generate advantages and threats
|
|
260
|
-
const cleanup1 = mockMathRandom(4/6); // boost die success + advantage
|
|
261
|
-
const cleanup2 = mockMathRandom(6/8); // difficulty die threat
|
|
262
|
-
|
|
263
|
-
const pool: DicePool = {
|
|
264
|
-
boostDice: 1,
|
|
265
|
-
difficultyDice: 1
|
|
266
|
-
};
|
|
267
|
-
|
|
268
|
-
const result = roll(pool);
|
|
269
|
-
expect(result.summary.advantages).toBeGreaterThan(0);
|
|
270
|
-
expect(result.summary.threats).toBeGreaterThan(0);
|
|
271
|
-
|
|
272
|
-
cleanup1();
|
|
273
|
-
cleanup2();
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
test('triumphs and despair count independently', () => {
|
|
277
|
-
// Mock to generate one triumph and one despair
|
|
278
|
-
const cleanup1 = mockMathRandom(11/12); // proficiency die triumph
|
|
279
|
-
const cleanup2 = mockMathRandom(11/12); // challenge die despair
|
|
280
|
-
|
|
281
|
-
const pool: DicePool = {
|
|
282
|
-
proficiencyDice: 1,
|
|
283
|
-
challengeDice: 1
|
|
284
|
-
};
|
|
285
|
-
|
|
286
|
-
const result = roll(pool);
|
|
287
|
-
expect(result.summary.triumphs).toBe(1);
|
|
288
|
-
expect(result.summary.despair).toBe(1);
|
|
289
|
-
|
|
290
|
-
cleanup1();
|
|
291
|
-
cleanup2();
|
|
292
|
-
});
|
|
293
|
-
});
|
|
294
|
-
|
|
295
|
-
describe('Complex Combinations', () => {
|
|
296
|
-
test('realistic skill check - standard difficulty', () => {
|
|
297
|
-
const pool: DicePool = {
|
|
298
|
-
abilityDice: 2,
|
|
299
|
-
proficiencyDice: 1,
|
|
300
|
-
difficultyDice: 2
|
|
301
|
-
};
|
|
302
|
-
|
|
303
|
-
const result = roll(pool);
|
|
304
|
-
|
|
305
|
-
// Verify result structure
|
|
306
|
-
expect(result.summary).toHaveProperty('successes');
|
|
307
|
-
expect(result.summary).toHaveProperty('failures');
|
|
308
|
-
expect(result.summary).toHaveProperty('advantages');
|
|
309
|
-
expect(result.summary).toHaveProperty('threats');
|
|
310
|
-
expect(result.summary).toHaveProperty('triumphs');
|
|
311
|
-
expect(result.summary).toHaveProperty('despair');
|
|
312
|
-
|
|
313
|
-
// Verify ranges
|
|
314
|
-
expect(result.summary.successes).toBeGreaterThanOrEqual(0);
|
|
315
|
-
expect(result.summary.failures).toBeGreaterThanOrEqual(0);
|
|
316
|
-
expect(result.summary.advantages).toBeGreaterThanOrEqual(0);
|
|
317
|
-
expect(result.summary.threats).toBeGreaterThanOrEqual(0);
|
|
318
|
-
expect(result.summary.triumphs).toBeGreaterThanOrEqual(0);
|
|
319
|
-
expect(result.summary.despair).toBeGreaterThanOrEqual(0);
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
test('opposed check - combat scenario', () => {
|
|
323
|
-
const pool: DicePool = {
|
|
324
|
-
abilityDice: 1,
|
|
325
|
-
proficiencyDice: 1,
|
|
326
|
-
boostDice: 1,
|
|
327
|
-
difficultyDice: 1,
|
|
328
|
-
challengeDice: 1,
|
|
329
|
-
setBackDice: 1
|
|
330
|
-
};
|
|
331
|
-
|
|
332
|
-
const result = roll(pool);
|
|
333
|
-
|
|
334
|
-
// Verify ranges
|
|
335
|
-
expect(result.summary.successes).toBeGreaterThanOrEqual(0);
|
|
336
|
-
expect(result.summary.failures).toBeGreaterThanOrEqual(0);
|
|
337
|
-
expect(result.summary.advantages).toBeGreaterThanOrEqual(0);
|
|
338
|
-
expect(result.summary.threats).toBeGreaterThanOrEqual(0);
|
|
339
|
-
expect(result.summary.triumphs).toBeGreaterThanOrEqual(0);
|
|
340
|
-
expect(result.summary.despair).toBeGreaterThanOrEqual(0);
|
|
341
|
-
|
|
342
|
-
// Check detailed results
|
|
343
|
-
expect(result.results).toHaveLength(6); // One result per die
|
|
344
|
-
result.results.forEach(dieResult => {
|
|
345
|
-
expect(dieResult).toHaveProperty('type');
|
|
346
|
-
expect(dieResult).toHaveProperty('roll');
|
|
347
|
-
expect(dieResult).toHaveProperty('result');
|
|
348
|
-
});
|
|
349
|
-
});
|
|
350
|
-
});
|
|
351
|
-
});
|
package/tests/pools.test.ts
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
createSkillCheck,
|
|
3
|
-
createCombatCheck,
|
|
4
|
-
createOpposedCheck,
|
|
5
|
-
createDifficultyPool
|
|
6
|
-
} from '../src/pools';
|
|
7
|
-
|
|
8
|
-
describe('Dice Pool Convenience Methods', () => {
|
|
9
|
-
describe('createSkillCheck', () => {
|
|
10
|
-
test('creates basic skill check pool', () => {
|
|
11
|
-
const pool = createSkillCheck(2, 1);
|
|
12
|
-
expect(pool).toEqual({
|
|
13
|
-
abilityDice: 2,
|
|
14
|
-
proficiencyDice: 1
|
|
15
|
-
});
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
test('creates pool with zero dice', () => {
|
|
19
|
-
const pool = createSkillCheck(0, 0);
|
|
20
|
-
expect(pool).toEqual({
|
|
21
|
-
abilityDice: 0,
|
|
22
|
-
proficiencyDice: 0
|
|
23
|
-
});
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
describe('createCombatCheck', () => {
|
|
28
|
-
test('creates combat check pool with boost', () => {
|
|
29
|
-
const pool = createCombatCheck(2, 1, 1);
|
|
30
|
-
expect(pool).toEqual({
|
|
31
|
-
abilityDice: 2,
|
|
32
|
-
proficiencyDice: 1,
|
|
33
|
-
boostDice: 1
|
|
34
|
-
});
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
test('creates combat check pool without boost', () => {
|
|
38
|
-
const pool = createCombatCheck(2, 1);
|
|
39
|
-
expect(pool).toEqual({
|
|
40
|
-
abilityDice: 2,
|
|
41
|
-
proficiencyDice: 1,
|
|
42
|
-
boostDice: 0
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
describe('createOpposedCheck', () => {
|
|
48
|
-
test('creates opposed check pool with challenge', () => {
|
|
49
|
-
const pool = createOpposedCheck(2, 1, 2, 1);
|
|
50
|
-
expect(pool).toEqual({
|
|
51
|
-
abilityDice: 2,
|
|
52
|
-
proficiencyDice: 1,
|
|
53
|
-
difficultyDice: 2,
|
|
54
|
-
challengeDice: 1
|
|
55
|
-
});
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
test('creates opposed check pool without challenge', () => {
|
|
59
|
-
const pool = createOpposedCheck(2, 1, 2);
|
|
60
|
-
expect(pool).toEqual({
|
|
61
|
-
abilityDice: 2,
|
|
62
|
-
proficiencyDice: 1,
|
|
63
|
-
difficultyDice: 2,
|
|
64
|
-
challengeDice: 0
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
describe('createDifficultyPool', () => {
|
|
70
|
-
test('creates difficulty pool with challenge', () => {
|
|
71
|
-
const pool = createDifficultyPool(2, 1);
|
|
72
|
-
expect(pool).toEqual({
|
|
73
|
-
difficultyDice: 2,
|
|
74
|
-
challengeDice: 1
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
test('creates difficulty pool without challenge', () => {
|
|
79
|
-
const pool = createDifficultyPool(2);
|
|
80
|
-
expect(pool).toEqual({
|
|
81
|
-
difficultyDice: 2,
|
|
82
|
-
challengeDice: 0
|
|
83
|
-
});
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
});
|
package/tsconfig.json
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "es2018",
|
|
4
|
-
"module": "commonjs",
|
|
5
|
-
"declaration": true,
|
|
6
|
-
"outDir": "./dist",
|
|
7
|
-
"strict": true,
|
|
8
|
-
"esModuleInterop": true,
|
|
9
|
-
"skipLibCheck": true,
|
|
10
|
-
"forceConsistentCasingInFileNames": true
|
|
11
|
-
},
|
|
12
|
-
"include": ["src/**/*"],
|
|
13
|
-
"exclude": ["node_modules", "**/*.test.ts"]
|
|
14
|
-
}
|