# Fate Core

The `@randsum/games/fate` subpath provides mechanics for [Fate Core](https://www.evilhat.com/home/fate-core/), a tabletop RPG that rolls four Fate dice (`4dF`), adds a skill rating, and reads the total off the Fate ladder.

[Official Site](https://www.evilhat.com/home/fate-core/)

## Installation

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

<CodeExample code={`// Roll 4dF with no skill modifier
const { result, total } = roll()
console.log(total)  // -4 to +4
console.log(result) // e.g. 'mediocre'`} />

<CodeExample code={`// Add a skill rating (a rung on the Fate ladder, -2 to +5)
roll(3)             // scalar overload: skill of +3
roll({ modifier: 3 }) // object overload: the same roll`} />

<CodeExample code={`const { result } = roll({ modifier: 4 })

switch (result) {
  case 'legendary':
  case 'epic':
  case 'fantastic':
    // A standout success
    break
  case 'superb':
  case 'great':
  case 'good':
    // A solid success
    break
  default:
    // Fair and below
    break
}`} />

## API

### `roll(modifier?: number)` / `roll(input?: { modifier?: number })`

**Input:**

| Parameter | Type | Description |
|---|---|---|
| `modifier` | `number` (optional) | Skill rating — a rung on the Fate ladder (`-2` to `+5`), added to the 4dF total |

**Returns:** `GameRollResult` with:

| Property | Type | Description |
|---|---|---|
| `result` | `FateRollResult` | The ladder rung the total lands on |
| `total` | `number` | The 4dF total plus the skill modifier |
| `rolls` | `RollRecord[]` | Raw dice data from the core roller (each Fate die is `-1`, `0`, or `+1`) |

## The Fate ladder

Fate dice are six-sided dice with two `+` faces, two blank faces, and two `−` faces, read as `+1`, `0`, and `−1`. Four of them (`4dF`) sum to a total between `-4` and `+4`. Add your skill rating and read the result off the ladder:

| Total | Rung |
|---|---|
| +8 or more | `legendary` |
| +7 | `epic` |
| +6 | `fantastic` |
| +5 | `superb` |
| +4 | `great` |
| +3 | `good` |
| +2 | `fair` |
| +1 | `average` |
| 0 | `mediocre` |
| -1 | `poor` |
| -2 or less | `terrible` |

The open-ended `legendary` and `terrible` rungs absorb any total beyond the ends of the ladder.

## Error handling

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

- **`ValidationError`** (from `@randsum/roller`) — the skill modifier is out of range (`-2` to `+5`) or not finite
- **`SchemaError`** (from `@randsum/games/fate`) — game-specific issues like an unmatched ladder rung

<CodeExample code={`try {
  roll(99)
} catch (error) {
  if (error instanceof ValidationError) {
    // Out-of-range skill rating (must be -2 to +5)
    console.log(error.code)    // 'VALIDATION_ERROR'
  } else if (error instanceof SchemaError) {
    // Game-specific error
    console.log(error.code)    // 'NO_TABLE_MATCH'
  }
}`} />

## Types

<CodeExample code={``} />

## Schema

This game is powered by a `.randsum.json` spec that defines the dice pool, the ladder outcomes, and validation rules. 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)