# Daggerheart

The `@randsum/games/daggerheart` subpath provides mechanics for [Daggerheart](https://www.darringtonpress.com/daggerheart), a fantasy tabletop RPG featuring the unique hope and fear dice system.

[Official Site](https://www.darringtonpress.com/daggerheart)

## Installation

<CodeExample lang="bash" code={`bun add @randsum/games`} />
  <CodeExample lang="bash" code={`npm install @randsum/games`} />
  ## Usage

<CodeExample code={`// Basic roll with modifier
const result = roll({ modifier: 5 })`} />

<CodeExample code={`// Roll with advantage (adds a d6)
roll({
  modifier: 5,
  rollingWith: 'Advantage'
})

// Roll with disadvantage (subtracts a d6)
roll({
  modifier: -2,
  rollingWith: 'Disadvantage'
})`} />

<CodeExample code={`// Amplify hope die (d12 becomes d20)
roll({
  amplifyHope: true,
  modifier: 2
})

// Amplify fear die
roll({
  amplifyFear: true,
  modifier: 3
})

// Amplify both
roll({
  amplifyHope: true,
  amplifyFear: true,
  modifier: 4
})`} />

<CodeExample code={`const { result, total, details } = roll({ modifier: 3 })
// result: 'hope' | 'fear' | 'critical hope'
// details: { hope, fear, extraDie, modifier }

const { hope, fear, extraDie, modifier } = details`} />

## API

### `roll(input?: { modifier?: number, rollingWith?: 'Advantage' | 'Disadvantage', amplifyHope?: boolean, amplifyFear?: boolean })`

**Input:**

| Property | Type | Description |
|---|---|---|
| `modifier` | `number` (optional) | Modifier added to the total |
| `rollingWith` | `'Advantage' \| 'Disadvantage' \| undefined` | Adds or subtracts a d6 |
| `amplifyHope` | `boolean` | Use d20 instead of d12 for hope die |
| `amplifyFear` | `boolean` | Use d20 instead of d12 for fear die |

**Returns:** `GameRollResult` with:

| Property | Type | Description |
|---|---|---|
| `result` | `DaggerheartRollResult` | `'hope' \| 'fear' \| 'critical hope'` |
| `total` | `number` | Sum of all dice + modifier |
| `details` | `DaggerheartRollDetails` | Detailed breakdown (see below) |
| `rolls` | `RollRecord[]` | Raw dice data from the core roller |

## Outcomes

The result type is determined by comparing the Hope and Fear die values:

| Condition | Outcome |
|---|---|
| Hope > Fear | Hope (positive narrative outcome) |
| Fear > Hope | Fear (negative narrative outcome) |
| Hope === Fear | Critical Hope |

The total (sum of all dice + modifier) determines mechanical success or failure.

## Details Object

The `details` object provides full visibility into each component:

- `hope` -- Hope die result and whether it was amplified
- `fear` -- Fear die result and whether it was amplified
- `extraDie` -- Advantage/disadvantage die result (if applicable)
- `modifier` -- Applied modifier value

## Error handling

Game `roll()` can throw two types of errors:

- **`ValidationError`** (from `@randsum/roller`) -- numeric input out of range or not finite (e.g., `modifier: Infinity`)
- **`SchemaError`** (from `@randsum/games/daggerheart`) -- game-specific issues like invalid `rollingWith` values

<CodeExample code={`try {
  roll({ modifier: Infinity })
} catch (error) {
  if (error instanceof ValidationError) {
    // Non-finite modifier value
    console.log(error.code)    // 'VALIDATION_ERROR'
  } else if (error instanceof SchemaError) {
    // e.g., invalid rollingWith enum value
    console.log(error.code)    // 'INVALID_INPUT_TYPE'
  }
}`} />

## Types

<CodeExample code={``} />

## Schema

This game is powered by a `.randsum.json` spec that defines the duality dice, amplification rules, and outcome logic. The TypeScript code is generated from this spec at build time. See [Schema Overview](https://randsum.dev/games/schema/overview/) for how game specs work.

## Links

- [npm package](https://www.npmjs.com/package/@randsum/games)
- [Source code](https://github.com/RANDSUM/randsum/tree/main/packages/games)