feat: Year-Zero rule-pack + rule-pack registry

This commit is contained in:
2026-07-20 13:52:41 +01:00
parent cf028e9a08
commit e9fa9366fa
3 changed files with 45 additions and 0 deletions
+6
View File
@@ -0,0 +1,6 @@
import { yearZero } from './year-zero.js';
const packs = new Map([[yearZero.id, yearZero]]);
export function getRulePack(id) { return packs.get(id) || null; }
export function registerRulePack(pack) { packs.set(pack.id, pack); }
+13
View File
@@ -0,0 +1,13 @@
export const yearZero = {
id: 'year-zero',
label: 'Year-Zero',
interpret(results) {
let successes = 0, ones = 0;
for (const r of results) {
if (r.value >= 10) successes += 2;
else if (r.value >= 6) successes += 1;
if (r.value === 1) ones += 1;
}
return { successes, ones, canPush: true, isCritical: successes >= 2 };
},
};
+26
View File
@@ -0,0 +1,26 @@
import { describe, it, expect } from 'vitest';
import { yearZero } from '../../src/dice/rulepacks/year-zero.js';
import { getRulePack, registerRulePack } from '../../src/dice/rulepacks/index.js';
describe('year-zero rule-pack', () => {
it('counts 6-9 as one success and 10+ as two', () => {
const v = yearZero.interpret([{ sides: 8, value: 8 }, { sides: 8, value: 4 }, { sides: 12, value: 11 }]);
expect(v.successes).toBe(3); // 8 -> 1, 4 -> 0, 11 -> 2
expect(v.isCritical).toBe(true);
});
it('reports ones for stress on a push', () => {
const v = yearZero.interpret([{ sides: 6, value: 1 }, { sides: 6, value: 1 }, { sides: 6, value: 6 }]);
expect(v.ones).toBe(2);
expect(v.successes).toBe(1);
expect(v.canPush).toBe(true);
});
it('is resolvable from the registry by id', () => {
expect(getRulePack('year-zero')).toBe(yearZero);
expect(getRulePack('nope')).toBe(null);
const custom = { id: 'x', label: 'X', interpret: () => ({}) };
registerRulePack(custom);
expect(getRulePack('x')).toBe(custom);
});
});