> ## Documentation Index
> Fetch the complete documentation index at: https://docs.awokenlabs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Precision

> Seven steady-hand mouse-control games - Track, Trace, Cut, Calibrate, Waveform, Thread and Reach.

Seven games built around steady, accurate mouse control. Defaults live in `config/games/precision.lua`.

<Info>
  Set any option as a server-wide default in `config/games/precision.lua`, or pass it in a single call to change it just that once. Every game also accepts the [shared options](/resources/awoken-minigames/configuration/overview#shared-options) (`canCancel`, `title`, `theme`, ...) - see the [Overview](/resources/awoken-minigames/configuration/overview).
</Info>

***

## Track

A target dot drifts around the board. Keep your cursor near it to fill a lock meter; the meter slips back when you stray off it.

**Export:** `exports['awoken_minigames']:Track(opts)` - returns `true` only on a win.

| Option        | Default | Notes                                                            |
| ------------- | ------- | ---------------------------------------------------------------- |
| `targetSpeed` | `1.0`   | Drift speed of the target dot (`0.2`-`4`).                       |
| `catchRadius` | `70`    | How close (px) the cursor must be to lock on (`24`-`140`).       |
| `holdMs`      | `3000`  | Total in-range contact needed to win (ms).                       |
| `drainRate`   | `0.5`   | Fraction of fill speed the meter drains at off-target (`0`-`1`). |
| `timeLimit`   | `15000` | Ms to fill the meter (`0` = no limit).                           |
| `canCancel`   | `true`  |                                                                  |
| `autoStart`   | `false` | Shows a "press to start" gate. `true` starts immediately.        |

```lua Presets theme={"dark"}
-- Zen
exports['awoken_minigames']:Track({ targetSpeed = 0.7, catchRadius = 90, holdMs = 4000, drainRate = 0.2, timeLimit = 0 })
-- (defaults)
exports['awoken_minigames']:Track({})
-- Twitchy
exports['awoken_minigames']:Track({ targetSpeed = 2.2, catchRadius = 46, holdMs = 3500, drainRate = 0.7, timeLimit = 18000 })
-- Marathon
exports['awoken_minigames']:Track({ targetSpeed = 0.8, catchRadius = 80, holdMs = 6000, drainRate = 0.35, timeLimit = 30000 })
-- Sniper
exports['awoken_minigames']:Track({ targetSpeed = 3.0, catchRadius = 40, holdMs = 3000, drainRate = 0.85, timeLimit = 12000 })
```

<Tip>
  `drainRate` sets how much a slip costs: at `0` the meter only ever climbs, near `1` a slip loses ground almost as fast as you gained it.
</Tip>

***

## Trace

Drag along a drawn shape from start to end, staying on the line without straying off too many times or running out of time.

**Export:** `exports['awoken_minigames']:Trace(opts)` - returns `true` only on a win.

| Option      | Default    | Notes                                                     |
| ----------- | ---------- | --------------------------------------------------------- |
| `shape`     | `'circle'` | Outline to trace: `'circle'` \| `'star'` \| `'wave'`.     |
| `tolerance` | `22`       | How far off the line you can drift, px (`10`-`48`).       |
| `maxStrays` | `3`        | Times you may leave tolerance before failing.             |
| `timeLimit` | `30000`    | Ms to finish the trace (`0` = no limit).                  |
| `canCancel` | `true`     |                                                           |
| `autoStart` | `false`    | Shows a "press to start" gate. `true` starts immediately. |

```lua Presets theme={"dark"}
-- Warmup
exports['awoken_minigames']:Trace({ shape = 'star', tolerance = 34, maxStrays = 8, timeLimit = 0 })
-- Steady Loop
exports['awoken_minigames']:Trace({ shape = 'circle', tolerance = 28, maxStrays = 5, timeLimit = 0 })
-- Star Precision
exports['awoken_minigames']:Trace({ shape = 'star', tolerance = 18, maxStrays = 3, timeLimit = 30000 })
-- Wave Rider
exports['awoken_minigames']:Trace({ shape = 'wave', tolerance = 22, maxStrays = 3, timeLimit = 25000 })
-- Surgeon
exports['awoken_minigames']:Trace({ shape = 'circle', tolerance = 14, maxStrays = 1, timeLimit = 20000 })
```

***

## Cut

Hold and drag a blade along each dashed guide line, staying on the line across every segment without slipping off too many times.

**Export:** `exports['awoken_minigames']:Cut(opts)` - returns `true` only on a win.

| Option      | Default | Notes                                                     |
| ----------- | ------- | --------------------------------------------------------- |
| `segments`  | `3`     | Cut lines to complete in a row (`1`-`8`).                 |
| `tolerance` | `26`    | Px the blade may stray from the guide (`8`-`80`).         |
| `maxSlips`  | `4`     | Excursions beyond tolerance tolerated (`0`-`20`).         |
| `timeLimit` | `0`     | Ms budget across all cuts (`0` = no limit).               |
| `curviness` | `0.35`  | `0` = straight lines, `1` = gently bowed (`0`-`1`).       |
| `canCancel` | `true`  |                                                           |
| `autoStart` | `false` | Shows a "press to start" gate. `true` starts immediately. |

```lua Presets theme={"dark"}
-- Quick Single
exports['awoken_minigames']:Cut({ segments = 1, tolerance = 20, maxSlips = 1, timeLimit = 12000, curviness = 0 })
-- (defaults)
exports['awoken_minigames']:Cut({})
-- Surgeon
exports['awoken_minigames']:Cut({ segments = 4, tolerance = 16, maxSlips = 2, timeLimit = 30000, curviness = 0.25 })
-- Curved Blade
exports['awoken_minigames']:Cut({ segments = 3, tolerance = 30, maxSlips = 5, curviness = 0.9 })
-- Marathon
exports['awoken_minigames']:Cut({ segments = 6, tolerance = 24, maxSlips = 8, curviness = 0.4 })
```

***

## Calibrate

Drag a row of knobs to their hidden target values, guided only by a hot/cold indicator on each. Then hold them all in range at once for a moment to lock in.

**Export:** `exports['awoken_minigames']:Calibrate(opts)` - returns `true` only on a win.

| Option      | Default | Notes                                                            |
| ----------- | ------- | ---------------------------------------------------------------- |
| `knobs`     | `3`     | Rotary dials to align (`2`-`4`).                                 |
| `tolerance` | `7`     | Closeness (`0`-`100` units) needed to match a knob.              |
| `settleMs`  | `600`   | Hold every knob in range this long to lock in.                   |
| `timeLimit` | `45000` | Ms to calibrate them all (`0` = no limit).                       |
| `canCancel` | `true`  |                                                                  |
| `autoStart` | `true`  | Starts immediately. `false` shows a "press to start" gate first. |

```lua Presets theme={"dark"}
-- Quick Tune
exports['awoken_minigames']:Calibrate({ knobs = 2, tolerance = 9, settleMs = 500, timeLimit = 40000 })
-- (defaults)
exports['awoken_minigames']:Calibrate({})
-- Precision
exports['awoken_minigames']:Calibrate({ knobs = 4, tolerance = 5, settleMs = 700, timeLimit = 55000 })
-- Steady Hands
exports['awoken_minigames']:Calibrate({ tolerance = 6, settleMs = 1100, timeLimit = 50000 })
-- No Clock
exports['awoken_minigames']:Calibrate({ knobs = 4, tolerance = 6, timeLimit = 0 })
```

***

## Waveform

Adjust the wave's height, speed and (optionally) offset to match a target wave, then hold every setting on target for a moment to lock it in.

**Export:** `exports['awoken_minigames']:Waveform(opts)` - returns `true` only on a win.

| Option      | Default | Notes                                                     |
| ----------- | ------- | --------------------------------------------------------- |
| `params`    | `2`     | Tunable parameters: `2` = amp+freq, `3` = +phase.         |
| `tolerance` | `0.06`  | Closeness each parameter must reach (`0.01`-`0.25`).      |
| `settleMs`  | `700`   | Ms the match must be held to lock the signal.             |
| `timeLimit` | `30000` | Ms to lock the signal (`0` = no limit).                   |
| `canCancel` | `true`  |                                                           |
| `autoStart` | `false` | Shows a "press to start" gate. `true` starts immediately. |

```lua Presets theme={"dark"}
-- Quick Tune
exports['awoken_minigames']:Waveform({ tolerance = 0.09, settleMs = 500, timeLimit = 20000 })
-- (defaults)
exports['awoken_minigames']:Waveform({})
-- Phase Lock
exports['awoken_minigames']:Waveform({ params = 3, settleMs = 800, timeLimit = 40000 })
-- Precision
exports['awoken_minigames']:Waveform({ params = 3, tolerance = 0.035, settleMs = 1000, timeLimit = 45000 })
-- Zen
exports['awoken_minigames']:Waveform({ tolerance = 0.05, timeLimit = 0 })
```

<Tip>
  Every setting must sit on target at the same moment for the whole `settleMs`, so raising `params` to `3` adds a whole extra dial to hold steady - a bigger jump than it looks.
</Tip>

***

## Thread

Steer a dot from the bottom to the top through gaps in sliding walls. Touch any wall and the run ends. The walls speed up with each row you clear.

**Export:** `exports['awoken_minigames']:Thread(opts)` - returns `true` only on a win.

| Option         | Default | Notes                                                     |
| -------------- | ------- | --------------------------------------------------------- |
| `rows`         | `6`     | Wall rows to thread through (`1`-`12`).                   |
| `wallSpeedMin` | `70`    | Slowest gap slide speed (px/second, `10`-`600`).          |
| `wallSpeedMax` | `150`   | Fastest gap slide speed (px/second, `>= min`).            |
| `gapSize`      | `92`    | Gap width in px (`28`-`400`).                             |
| `moveSpeed`    | `240`   | Player dot steer speed (px/second, `60`-`600`).           |
| `timeLimit`    | `0`     | Ms to reach the top (`0` = no limit).                     |
| `canCancel`    | `true`  |                                                           |
| `autoStart`    | `false` | Shows a "press to start" gate. `true` starts immediately. |

```lua Presets theme={"dark"}
-- Gentle
exports['awoken_minigames']:Thread({ rows = 4, wallSpeedMin = 45, wallSpeedMax = 90, gapSize = 120, moveSpeed = 260 })
-- (defaults)
exports['awoken_minigames']:Thread({})
-- Weave
exports['awoken_minigames']:Thread({ rows = 8, wallSpeedMin = 110, wallSpeedMax = 210, gapSize = 70, moveSpeed = 280 })
-- Time Attack
exports['awoken_minigames']:Thread({ wallSpeedMin = 90, wallSpeedMax = 170, gapSize = 84, timeLimit = 18000 })
-- Needle
exports['awoken_minigames']:Thread({ rows = 10, wallSpeedMin = 130, wallSpeedMax = 240, gapSize = 54, moveSpeed = 300, timeLimit = 25000, canCancel = false })
```

***

## Reach

A randomly generated maze you can see only a few cells of at a time. Drag the token from start to goal without scraping the walls. A wall touch isn't instant failure - the token is pushed back, one mistake is counted, and `timePenalty` comes off the clock. The run keeps going until you run out of mistakes or time.

**Export:** `exports['awoken_minigames']:Reach(opts)` - returns `true` only on a win.

| Option            | Default | Notes                                                                                                               |
| ----------------- | ------- | ------------------------------------------------------------------------------------------------------------------- |
| `gridSize`        | `10`    | Maze size in cells per side (`5`-`20`). Below `16` the corridors are comfortable; at `20` it is deliberately tight. |
| `revealRadius`    | `3`     | How far you can see, in cells. `0` = no fog, the whole maze is visible.                                             |
| `timeLimit`       | `45000` | Ms to reach the goal (`0` = no limit).                                                                              |
| `mistakesAllowed` | `2`     | Wall touches tolerated before failing.                                                                              |
| `timePenalty`     | `3000`  | Ms knocked off the clock per wall touch.                                                                            |
| `canCancel`       | `true`  |                                                                                                                     |
| `autoStart`       | `false` | Shows a "press to start" gate. `true` starts immediately.                                                           |

```lua Presets theme={"dark"}
-- Tutorial
exports['awoken_minigames']:Reach({ gridSize = 7, revealRadius = 0, timeLimit = 0 })
-- Standard (defaults)
exports['awoken_minigames']:Reach({})
-- Hard
exports['awoken_minigames']:Reach({ gridSize = 14, revealRadius = 2, timeLimit = 60000, mistakesAllowed = 1 })
-- Expert
exports['awoken_minigames']:Reach({ gridSize = 16, revealRadius = 2, timePenalty = 6000 })
-- Lights on
exports['awoken_minigames']:Reach({ gridSize = 12, revealRadius = 0, timeLimit = 40000 })
```

<Tip>
  Keep the cursor close to the token and drag smoothly - fling it too fast and the token can skip across a wall and still bank a touch. The maze always has exactly one path from start to goal.
</Tip>
