diff --git a/src/components/dice-tray.js b/src/components/dice-tray.js
index 141ff22..f080334 100644
--- a/src/components/dice-tray.js
+++ b/src/components/dice-tray.js
@@ -11,6 +11,7 @@ export class DiceTray extends HTMLElement {
this._systemId = 'year-zero';
this.rng = Math.random;
this.last = null;
+ this.params = {};
}
get sides() { return this._sides; }
set sides(v) { this._sides = Number(v); this.render(); }
@@ -24,7 +25,7 @@ export class DiceTray extends HTMLElement {
roll() {
const { results, total } = rollPool([{ sides: this._sides, count: this._count }], this.rng);
const pack = getRulePack(this._systemId);
- const verdict = pack ? pack.interpret(results) : null;
+ const verdict = pack ? pack.interpret(results, this.params) : null;
this.last = { results, total, verdict };
this.render();
this.dispatchEvent(new CustomEvent('rolled', { detail: this.last, bubbles: true }));
@@ -36,9 +37,9 @@ export class DiceTray extends HTMLElement {
const felt = this.last
? this.last.results.map((r) => `${r.value}`).join('')
: 'Tap Roll';
+ const pack = getRulePack(this._systemId);
const verdict = this.last?.verdict
- ? `${this.last.verdict.successes} success${this.last.verdict.successes === 1 ? '' : 'es'}` +
- (this.last.verdict.ones ? ` · ${this.last.verdict.ones} stress` : '')
+ ? (pack && pack.summary ? pack.summary(this.last.verdict) : '')
: '';
this.innerHTML = `
diff --git a/src/dice/rulepacks/index.js b/src/dice/rulepacks/index.js
index 32c6973..8432605 100644
--- a/src/dice/rulepacks/index.js
+++ b/src/dice/rulepacks/index.js
@@ -4,3 +4,6 @@ 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); }
+export function listRulePacks() {
+ return [...packs.values()].map((p) => ({ id: p.id, label: p.label }));
+}
diff --git a/src/dice/rulepacks/year-zero.js b/src/dice/rulepacks/year-zero.js
index 246a085..3c9e5fd 100644
--- a/src/dice/rulepacks/year-zero.js
+++ b/src/dice/rulepacks/year-zero.js
@@ -1,7 +1,8 @@
export const yearZero = {
id: 'year-zero',
label: 'Year-Zero',
- interpret(results) {
+ params: [],
+ interpret(results, params = {}) {
let successes = 0, ones = 0;
for (const r of results) {
if (r.value >= 10) successes += 2;
@@ -10,4 +11,8 @@ export const yearZero = {
}
return { successes, ones, canPush: true, isCritical: successes >= 2 };
},
+ summary(v) {
+ const base = `${v.successes} success${v.successes === 1 ? '' : 'es'}`;
+ return v.ones ? `${base} · ${v.ones} stress` : base;
+ },
};
diff --git a/tests/dice/rulepacks-registry.test.js b/tests/dice/rulepacks-registry.test.js
new file mode 100644
index 0000000..f84adc8
--- /dev/null
+++ b/tests/dice/rulepacks-registry.test.js
@@ -0,0 +1,9 @@
+import { describe, it, expect } from 'vitest';
+import { getRulePack, listRulePacks } from '../../src/dice/rulepacks/index.js';
+
+describe('rule-pack registry', () => {
+ it('lists registered packs as {id,label}', () => {
+ const packs = listRulePacks();
+ expect(packs.some((p) => p.id === 'year-zero' && typeof p.label === 'string')).toBe(true);
+ });
+});
diff --git a/tests/dice/year-zero.test.js b/tests/dice/year-zero.test.js
index 7d0971a..9c5b2e7 100644
--- a/tests/dice/year-zero.test.js
+++ b/tests/dice/year-zero.test.js
@@ -24,3 +24,15 @@ describe('year-zero rule-pack', () => {
expect(getRulePack('x')).toBe(custom);
});
});
+
+describe('year-zero contract v2', () => {
+ it('exposes an empty params list and a summary string', () => {
+ expect(yearZero.params).toEqual([]);
+ expect(yearZero.summary({ successes: 2, ones: 1 })).toBe('2 successes · 1 stress');
+ expect(yearZero.summary({ successes: 1, ones: 0 })).toBe('1 success');
+ });
+ it('interpret ignores a params argument', () => {
+ const v = yearZero.interpret([{ sides: 8, value: 8 }], { anything: true });
+ expect(v.successes).toBe(1);
+ });
+});