Powered by the Apocalypse
The @randsum/games/pbta subpath provides generic Powered by the Apocalypse (PbtA) mechanics that work with any PbtA game, including Dungeon World, Monster of the Week, Apocalypse World, Masks, and many others.
Official Site Apocalypse World by D. Vincent Baker
Installation
Section titled “Installation”bun add @randsum/gamesnpm install @randsum/gamesimport { roll } from '@randsum/games/pbta'
// Roll 2d6 + stat modifierconst result = roll({ stat: 2 })// result.result: 'strong_hit' | 'weak_hit' | 'miss'import { roll } from '@randsum/games/pbta'
// With forward and ongoing bonusesconst result = roll({stat: 1,forward: 1, // One-time bonusongoing: 0 // Persistent bonus})import { roll } from '@randsum/games/pbta'
// Roll with advantage (3d6, keep 2 highest)const result = roll({stat: 2,rollingWith: 'Advantage'})
// Roll with disadvantage (3d6, keep 2 lowest)const result2 = roll({stat: 2,rollingWith: 'Disadvantage'})import { roll } from '@randsum/games/pbta'
const { result, total } = roll({ stat: 2 })
switch (result) {case 'strong_hit': // 10+ total: complete success breakcase 'weak_hit': // 7-9 total: success with cost breakcase 'miss': // 6- total: failure break}roll(input: { stat: number, forward?: number, ongoing?: number, rollingWith?: 'Advantage' | 'Disadvantage' })
Section titled “roll(input: { stat: number, forward?: number, ongoing?: number, rollingWith?: 'Advantage' | 'Disadvantage' })”Input:
| Property | Type | Description |
|---|---|---|
stat | number | Stat modifier (-3 to 5) |
forward | number (optional) | One-time bonus (-5 to 5) |
ongoing | number (optional) | Persistent bonus (-5 to 5) |
rollingWith | 'Advantage' | 'Disadvantage' | undefined | Roll 3d6, keep 2 highest or lowest |
Returns: GameRollResult with:
| Property | Type | Description |
|---|---|---|
result | PbtaRollResult | 'strong_hit' | 'weak_hit' | 'miss' |
total | number | Sum of 2d6 + all modifiers |
rolls | RollRecord[] | Raw dice data from the core roller |
details | PbtaRollDetails | { stat, forward, ongoing, diceTotal } |
Outcomes
Section titled “Outcomes”| Outcome | Total | Description |
|---|---|---|
strong_hit | 10+ | Complete success |
weak_hit | 7-9 | Partial success, success with cost |
miss | 6- | Failure |
Compatible Systems
Section titled “Compatible Systems”This package works with any PbtA game, including:
- Apocalypse World — The original PbtA game
- Dungeon World — Fantasy dungeon crawling
- Monster of the Week — Urban fantasy monster hunting
- Masks — Teen superheroes
- The Sprawl — Cyberpunk missions
- Urban Shadows — Urban supernatural politics
- And many more
Error handling
Section titled “Error handling”Game roll() can throw two types of errors:
ValidationError(from@randsum/roller) — numeric input out of range or not finite (e.g.,stat: 99when max is 5)SchemaError(from@randsum/games/pbta) — game-specific issues like invalidrollingWithvalues
import { roll, SchemaError } from '@randsum/games/pbta'import { ValidationError } from '@randsum/roller'
try {roll({ stat: 99 })} catch (error) {if (error instanceof ValidationError) { // Out-of-range stat (must be -3 to 5) console.log(error.code) // 'VALIDATION_ERROR'} else if (error instanceof SchemaError) { // e.g., invalid rollingWith enum value console.log(error.code) // 'INVALID_INPUT_TYPE'}}import type { PbtaRollResult, PbtaRollDetails, GameRollResult, RollRecord } from '@randsum/games/pbta'import { SchemaError } from '@randsum/games/pbta'Schema
Section titled “Schema”This game is powered by a .randsum.json spec that defines the 2d6 resolution, stat/bonus ranges, and outcome tiers. The TypeScript code is generated from this spec at build time. See Schema Overview for how game specs work.