Skip to content

The @randsum/games/salvageunion subpath provides mechanics for Salvage Union, a post-apocalyptic mech-based tabletop RPG that uses table-based d20 mechanics.

Terminal window
bun add @randsum/games
import { roll } from '@randsum/games/salvageunion'
// Roll on the Core Mechanic table
const result = roll('Core Mechanic')
import { roll } from '@randsum/games/salvageunion'
// Roll on a different table
const result = roll('Morale')
import { roll } from '@randsum/games/salvageunion'
const { result } = roll('Core Mechanic')
const { label, description, roll: rollValue } = result
console.log(`${rollValue} - ${label}`)
// e.g., "16 - Success"
console.log(description)
// e.g., "You have achieved your goal without any compromises."
import { roll } from '@randsum/games/salvageunion'
const { result } = roll('Core Mechanic')
// Access structured result data
switch (result.key) {
case 'nailed_it':
// Roll of 20 - exceptional success
break
case 'success':
// Roll of 11-19 - standard success
break
case 'tough_choice':
// Roll of 6-10 - success with complications
break
}

Input:

ParameterTypeDescription
tableNamestringTable to roll on (must be a valid table name from VALID_TABLE_NAMES)

Returns: GameRollResult with:

PropertyTypeDescription
resultSalvageunionRollResultTable result with metadata
totalnumberD20 roll result (1-20)
rollsRollRecord[]Raw dice data from the core roller

The SalvageunionRollResult interface includes:

PropertyTypeDescription
keystringInternal result identifier
labelstringHuman-readable result label
descriptionstringDetailed result description
tableRecord<string, unknown>Full table data
tableNamestringName of the table rolled
rollnumberD20 roll result (1-20)

The default Core Mechanic table uses these result tiers:

RollResult
20Nailed It — exceptional success
11-19Success — goal achieved without compromise
6-10Tough Choice — success with complications
2-5Failure
1Cascade Failure — critical failure

Use the VALID_TABLE_NAMES const tuple to get all available table names. This is generated from the spec at build time.

import { VALID_TABLE_NAMES } from '@randsum/games/salvageunion'
// VALID_TABLE_NAMES is a readonly tuple of all valid table name strings
// e.g. ['Core Mechanic', 'Group Initiative', 'Critical Injury', ...]

Passing an invalid table name throws a SchemaError:

import { roll, SchemaError } from '@randsum/games/salvageunion'
try {
roll('Not A Real Table')
} catch (error) {
if (error instanceof SchemaError) {
console.log(error.code) // 'NO_TABLE_MATCH'
console.log(error.message) // 'Invalid Salvage Union table name: "Not A Real Table"'
}
}
import type { SalvageunionRollResult, GameRollResult, RollRecord } from '@randsum/games/salvageunion'
import { VALID_TABLE_NAMES, ROLL_TABLE_ENTRIES, SchemaError } from '@randsum/games/salvageunion'

This game is powered by a .randsum.json spec that defines the d20 resolution, outcome tables, and table lookup logic. The TypeScript code is generated from this spec at build time. See Schema Overview for how game specs work.