From 01a279798bf814edd5f2d7acc4a3c6cf93c7746c Mon Sep 17 00:00:00 2001 From: Tim Evans Date: Mon, 20 Jul 2026 16:28:37 +0100 Subject: [PATCH] feat: Dee Sanction challenge/verdict rule-pack --- src/dice/rulepacks/dee-sanction.js | 14 ++++++++++++++ src/dice/rulepacks/index.js | 3 ++- tests/dice/dee-sanction.test.js | 22 ++++++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 src/dice/rulepacks/dee-sanction.js create mode 100644 tests/dice/dee-sanction.test.js diff --git a/src/dice/rulepacks/dee-sanction.js b/src/dice/rulepacks/dee-sanction.js new file mode 100644 index 0000000..60fe09f --- /dev/null +++ b/src/dice/rulepacks/dee-sanction.js @@ -0,0 +1,14 @@ +// The Dee Sanction: roll one Ability die (d4-d12). 3+ = success, 1-2 = Falter. +export const deeSanction = { + id: 'dee-sanction', + label: 'Dee Sanction (Challenge/Verdict)', + params: [], + interpret(results, params = {}) { + const value = results[0]?.value ?? 0; + const sides = results[0]?.sides ?? 0; + return { value, sides, success: value >= 3, falter: value <= 2 }; + }, + summary(v) { + return v.success ? `${v.value} → success` : `${v.value} → FALTER`; + }, +}; diff --git a/src/dice/rulepacks/index.js b/src/dice/rulepacks/index.js index 62b8391..8ae6def 100644 --- a/src/dice/rulepacks/index.js +++ b/src/dice/rulepacks/index.js @@ -2,8 +2,9 @@ import { yearZero } from './year-zero.js'; import { cocD100 } from './coc-d100.js'; import { vanityD6 } from './vanity-d6.js'; import { panicGlory } from './panic-glory.js'; +import { deeSanction } from './dee-sanction.js'; -const packs = new Map([[yearZero.id, yearZero], [cocD100.id, cocD100], [vanityD6.id, vanityD6], [panicGlory.id, panicGlory]]); +const packs = new Map([[yearZero.id, yearZero], [cocD100.id, cocD100], [vanityD6.id, vanityD6], [panicGlory.id, panicGlory], [deeSanction.id, deeSanction]]); export function getRulePack(id) { return packs.get(id) || null; } export function registerRulePack(pack) { packs.set(pack.id, pack); } diff --git a/tests/dice/dee-sanction.test.js b/tests/dice/dee-sanction.test.js new file mode 100644 index 0000000..bc7eabd --- /dev/null +++ b/tests/dice/dee-sanction.test.js @@ -0,0 +1,22 @@ +import { describe, it, expect } from 'vitest'; +import { deeSanction } from '../../src/dice/rulepacks/dee-sanction.js'; +import { getRulePack } from '../../src/dice/rulepacks/index.js'; + +const die = (sides, value) => [{ sides, value }]; + +describe('dee-sanction rule-pack', () => { + it('treats 3+ as success on any ability die', () => { + expect(deeSanction.interpret(die(8, 3)).success).toBe(true); + expect(deeSanction.interpret(die(12, 12)).success).toBe(true); + }); + it('treats 1-2 as a Falter', () => { + expect(deeSanction.interpret(die(8, 2)).falter).toBe(true); + expect(deeSanction.interpret(die(4, 1)).falter).toBe(true); + expect(deeSanction.interpret(die(8, 2)).success).toBe(false); + }); + it('summarises and is registered', () => { + expect(deeSanction.summary(deeSanction.interpret(die(6, 5)))).toBe('5 → success'); + expect(deeSanction.summary(deeSanction.interpret(die(6, 2)))).toBe('2 → FALTER'); + expect(getRulePack('dee-sanction')).toBe(deeSanction); + }); +});