> ## 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.

# Arcade

> Eleven arcade classics rebuilt as quick pass/fail minigames.

Eleven arcade classics rebuilt as pass/fail minigames. Defaults live in `config/games/arcade.lua`.

<Info>
  Set an option once in `config/games/arcade.lua` to apply it server-wide, or pass it in a single call to change it just that once. Every game also accepts [shared options](/resources/awoken-minigames/configuration/overview#shared-options) like `canCancel`, `title` and `theme`.
</Info>

***

## Snake

Steer the snake with the arrow keys or WASD and eat pellets to grow. Reach the target length without hitting a wall or yourself.

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

| Option         | Default | Notes                                                     |
| -------------- | ------- | --------------------------------------------------------- |
| `gridSize`     | `16`    | Square board dimension in cells (`8`-`24`).               |
| `targetLength` | `10`    | Length required to win (start length is 3).               |
| `stepMs`       | `130`   | Ms per step at the start (lower = faster).                |
| `speedRamp`    | `4`     | Ms shaved off the step per pellet eaten.                  |
| `minStepMs`    | `70`    | Fastest the step is ever allowed to get.                  |
| `wrapWalls`    | `false` | `true` = edges wrap; `false` = walls are lethal.          |
| `timeLimit`    | `0`     | Ms to reach the target (`0` = no limit).                  |
| `canCancel`    | `true`  |                                                           |
| `autoStart`    | `false` | Shows a "press to start" gate. `true` starts immediately. |

```lua Presets theme={"dark"}
-- Tutorial
exports['awoken_minigames']:Snake({ gridSize = 12, targetLength = 6, stepMs = 170, wrapWalls = true, speedRamp = 0 })
-- Easy
exports['awoken_minigames']:Snake({ gridSize = 14, targetLength = 8, stepMs = 150 })
-- Standard
exports['awoken_minigames']:Snake({ gridSize = 16, targetLength = 10, stepMs = 130 })
-- Hard
exports['awoken_minigames']:Snake({ gridSize = 18, targetLength = 14, stepMs = 115, speedRamp = 6 })
-- Expert
exports['awoken_minigames']:Snake({ gridSize = 20, targetLength = 18, stepMs = 100, speedRamp = 6, minStepMs = 60 })
```

***

## Flappy

The bird keeps falling, so tap to flap and keep it up. Fly through the gaps in the pipes and pass the target number of them to win.

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

| Option        | Default | Notes                                                     |
| ------------- | ------- | --------------------------------------------------------- |
| `gravity`     | `1500`  | Downward acceleration, px/s^2.                            |
| `flapImpulse` | `430`   | Upward velocity applied on a flap, px/s.                  |
| `pipeGap`     | `150`   | Vertical gap between pipe columns, px.                    |
| `pipeSpeed`   | `165`   | Horizontal scroll speed, px/s.                            |
| `pipeSpacing` | `240`   | Horizontal distance between pipes, px.                    |
| `targetPipes` | `10`    | Gaps to pass to win.                                      |
| `timeLimit`   | `0`     | Ms budget (`0` = no limit).                               |
| `canCancel`   | `true`  |                                                           |
| `autoStart`   | `false` | Shows a "press to start" gate. `true` starts immediately. |

```lua Presets theme={"dark"}
-- Breezy
exports['awoken_minigames']:Flappy({ gravity = 1200, flapImpulse = 400, pipeGap = 185, pipeSpeed = 130, pipeSpacing = 280, targetPipes = 8 })
-- Classic (defaults)
exports['awoken_minigames']:Flappy({})
-- Tight Squeeze
exports['awoken_minigames']:Flappy({ gravity = 1700, flapImpulse = 450, pipeGap = 120, pipeSpeed = 200, pipeSpacing = 215, targetPipes = 12 })
-- Marathon
exports['awoken_minigames']:Flappy({ gravity = 1450, flapImpulse = 425, pipeGap = 155, pipeSpeed = 175, pipeSpacing = 245, targetPipes = 20 })
-- Frantic
exports['awoken_minigames']:Flappy({ gravity = 1800, flapImpulse = 460, pipeGap = 110, pipeSpeed = 220, pipeSpacing = 200, targetPipes = 15 })
```

<Tip>
  Change `pipeGap` to set the difficulty. If you raise `gravity`, raise `flapImpulse` to match, or the bird won't be able to climb.
</Tip>

***

## Stack

A block slides across the top of the tower. Tap to drop it - any part that hangs over the edge is sliced off, so blocks get smaller. Stack the target number to win.

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

| Option             | Default | Notes                                                                                                                                        |
| ------------------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `targetHeight`     | `12`    | Blocks to stack beyond the base to win (`3`-`40`).                                                                                           |
| `startWidth`       | `150`   | Initial block width, px (`40`-`220`).                                                                                                        |
| `blockSpeed`       | `150`   | Base horizontal slide speed, px/s (`30`-`400`).                                                                                              |
| `speedRamp`        | `8`     | Slide speed added per placed block, px/s (`0`-`40`).                                                                                         |
| `perfectTolerance` | `6`     | Alignment window for a 'perfect' drop, px (`1`-`20`).                                                                                        |
| `regrow`           | `0`     | Width a perfect drop claws back, px (`0`-`30`); `0` = perfect only avoids trimming (permanent erosion = the skill gate), above `0` = easier. |
| `timeLimit`        | `0`     | Ms budget (`0` = no limit).                                                                                                                  |
| `canCancel`        | `true`  |                                                                                                                                              |
| `autoStart`        | `false` | Shows a "press to start" gate. `true` starts immediately.                                                                                    |

```lua Presets theme={"dark"}
-- Relaxed
exports['awoken_minigames']:Stack({ targetHeight = 8, startWidth = 170, blockSpeed = 120, speedRamp = 5, perfectTolerance = 8, regrow = 10 })
-- Classic (defaults)
exports['awoken_minigames']:Stack({})
-- Tower
exports['awoken_minigames']:Stack({ targetHeight = 18, blockSpeed = 165, speedRamp = 7 })
-- Precise
exports['awoken_minigames']:Stack({ targetHeight = 15, blockSpeed = 200, speedRamp = 12, perfectTolerance = 3 })
-- Timed
exports['awoken_minigames']:Stack({ timeLimit = 30000 })
```

***

## Pong

Move the left paddle with the mouse or W/S to return the ball past the computer on the right. First side to the target score wins.

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

| Option         | Default | Notes                                                     |
| -------------- | ------- | --------------------------------------------------------- |
| `targetScore`  | `5`     | First side to this score wins (`1`-`15`).                 |
| `ballSpeed`    | `260`   | Starting ball speed, px/sec (`120`-`600`).                |
| `ballSpeedUp`  | `1.06`  | Speed multiplier per paddle hit (`1`-`1.4`).              |
| `paddleHeight` | `80`    | Paddle height in px (`40`-`140`).                         |
| `aiSpeed`      | `230`   | AI paddle max tracking speed, px/sec (`80`-`520`).        |
| `canCancel`    | `true`  |                                                           |
| `autoStart`    | `false` | Shows a "press to start" gate. `true` starts immediately. |

```lua Presets theme={"dark"}
-- Classic (defaults)
exports['awoken_minigames']:Pong({})
-- Quick Point
exports['awoken_minigames']:Pong({ targetScore = 3, ballSpeed = 320, ballSpeedUp = 1.08, aiSpeed = 260 })
-- Rally Master
exports['awoken_minigames']:Pong({ targetScore = 9, ballSpeed = 240, ballSpeedUp = 1.04, paddleHeight = 110, aiSpeed = 210 })
-- Sharpshooter
exports['awoken_minigames']:Pong({ ballSpeed = 300, ballSpeedUp = 1.09, paddleHeight = 55, aiSpeed = 250 })
-- Nightmare AI
exports['awoken_minigames']:Pong({ targetScore = 7, ballSpeed = 300, ballSpeedUp = 1.1, paddleHeight = 70, aiSpeed = 340, canCancel = false })
```

***

## Invaders

Move your ship along the bottom and shoot upward to clear the formation of enemies before any reach your row or time runs out.

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

| Option        | Default | Notes                                                     |
| ------------- | ------- | --------------------------------------------------------- |
| `rows`        | `4`     | Formation rows (`2`-`6`).                                 |
| `cols`        | `7`     | Formation columns (`3`-`10`).                             |
| `enemyStepMs` | `520`   | Ms between horizontal formation steps (`>= 60`).          |
| `descendStep` | `18`    | Px the formation drops each time it hits a wall.          |
| `bulletSpeed` | `7`     | Px per \~16ms frame the bullet travels upward.            |
| `timeLimit`   | `45000` | Ms to clear the sector (`0` = no limit).                  |
| `canCancel`   | `true`  |                                                           |
| `autoStart`   | `false` | Shows a "press to start" gate. `true` starts immediately. |

```lua Presets theme={"dark"}
-- Skirmish
exports['awoken_minigames']:Invaders({ rows = 2, cols = 4, enemyStepMs = 600, descendStep = 16, bulletSpeed = 8, timeLimit = 30000 })
-- Standard (defaults)
exports['awoken_minigames']:Invaders({})
-- Blitz
exports['awoken_minigames']:Invaders({ rows = 4, cols = 8, enemyStepMs = 300, descendStep = 24, bulletSpeed = 9, timeLimit = 35000 })
-- Onslaught
exports['awoken_minigames']:Invaders({ rows = 6, cols = 10, enemyStepMs = 460, descendStep = 20, timeLimit = 0 })
-- Marksman
exports['awoken_minigames']:Invaders({ rows = 5, cols = 6, enemyStepMs = 700, descendStep = 14, bulletSpeed = 4, timeLimit = 60000, canCancel = false })
```

***

## Crossy

Hop up the lanes one step at a time with the arrow keys or WASD, dodging the cars until you reach the row at the top.

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

| Option        | Default | Notes                                                     |
| ------------- | ------- | --------------------------------------------------------- |
| `lanes`       | `6`     | Road rows to cross (`2`-`12`).                            |
| `cols`        | `9`     | Grid width in cells (`5`-`15`).                           |
| `minCarSpeed` | `1.4`   | Slowest lane speed (cells/second).                        |
| `maxCarSpeed` | `3.2`   | Fastest lane speed (cells/second).                        |
| `density`     | `0.55`  | `0`-`1` traffic density per lane.                         |
| `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"}
-- Sunday Drive
exports['awoken_minigames']:Crossy({ lanes = 4, cols = 7, minCarSpeed = 0.9, maxCarSpeed = 1.8, density = 0.35 })
-- Standard (defaults)
exports['awoken_minigames']:Crossy({})
-- Rush Hour
exports['awoken_minigames']:Crossy({ lanes = 8, cols = 11, minCarSpeed = 2.4, maxCarSpeed = 4.5, density = 0.8 })
-- Time Attack
exports['awoken_minigames']:Crossy({ minCarSpeed = 1.8, maxCarSpeed = 3.6, density = 0.6, timeLimit = 20000 })
-- Gauntlet
exports['awoken_minigames']:Crossy({ lanes = 12, cols = 13, minCarSpeed = 2.8, maxCarSpeed = 5, density = 0.85, timeLimit = 30000, canCancel = false })
```

***

## Ascent

You bounce up off each platform automatically - steer left and right to land on the next one. Clear the target number of platforms without falling off the bottom.

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

| Option          | Default | Notes                                                     |
| --------------- | ------- | --------------------------------------------------------- |
| `gravity`       | `1400`  | Downward acceleration in px/s^2 (`200`-`4000`).           |
| `jumpImpulse`   | `720`   | Upward launch speed on landing, px/s (`300`-`1600`).      |
| `platformGap`   | `78`    | Vertical spacing between platforms, px (`40`-`160`).      |
| `platformWidth` | `84`    | Platform width, px (`40`-`200`).                          |
| `moveSpeed`     | `340`   | Horizontal steer speed, px/s (`100`-`900`).               |
| `targetHeight`  | `25`    | Platforms to clear to win (`3`-`500`).                    |
| `canCancel`     | `true`  |                                                           |
| `autoStart`     | `false` | Shows a "press to start" gate. `true` starts immediately. |

```lua Presets theme={"dark"}
-- Casual Climb
exports['awoken_minigames']:Ascent({ gravity = 1200, platformGap = 70, platformWidth = 100, moveSpeed = 320, targetHeight = 15 })
-- Standard (defaults)
exports['awoken_minigames']:Ascent({})
-- Tight Ledges
exports['awoken_minigames']:Ascent({ gravity = 1500, jumpImpulse = 760, platformGap = 90, platformWidth = 58, moveSpeed = 400 })
-- Heavy Gravity
exports['awoken_minigames']:Ascent({ gravity = 2200, jumpImpulse = 980, platformGap = 100, platformWidth = 80, moveSpeed = 460, targetHeight = 30 })
-- Marathon
exports['awoken_minigames']:Ascent({ jumpImpulse = 740, platformWidth = 90, moveSpeed = 360, targetHeight = 60 })
```

***

## Slipstream

Switch lanes to dodge oncoming traffic on a road that keeps speeding up. Survive the target distance to win.

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

| Option           | Default | Notes                                                     |
| ---------------- | ------- | --------------------------------------------------------- |
| `lanes`          | `4`     | Number of lanes (`3`-`6`).                                |
| `scrollSpeed`    | `180`   | Starting road speed in px/s (`60`-`600`).                 |
| `speedRamp`      | `8`     | Speed gained per second, px/s (`0`-`80`).                 |
| `spawnMs`        | `850`   | Obstacle spawn interval in ms (`250`-`3000`).             |
| `targetDistance` | `2600`  | Distance units to survive (`>= 200`).                     |
| `timeLimit`      | `0`     | Optional ms cap (`0` = distance only).                    |
| `canCancel`      | `true`  |                                                           |
| `autoStart`      | `false` | Shows a "press to start" gate. `true` starts immediately. |

```lua Presets theme={"dark"}
-- Cruise
exports['awoken_minigames']:Slipstream({ lanes = 3, scrollSpeed = 150, speedRamp = 5, spawnMs = 1000, targetDistance = 2000 })
-- City Run (defaults)
exports['awoken_minigames']:Slipstream({})
-- Rush Hour
exports['awoken_minigames']:Slipstream({ lanes = 5, scrollSpeed = 220, speedRamp = 12, spawnMs = 650, targetDistance = 3200 })
-- Gauntlet
exports['awoken_minigames']:Slipstream({ lanes = 6, scrollSpeed = 260, speedRamp = 16, spawnMs = 550, targetDistance = 4000 })
-- Sprint
exports['awoken_minigames']:Slipstream({ scrollSpeed = 240, speedRamp = 14, spawnMs = 700, targetDistance = 1500 })
```

***

## Breakout

Move the paddle with the arrows or A/D and launch the ball with Space. Bounce it up to break the wall of bricks - where it hits the paddle sets the angle, and the ball speeds up with each hit. Some bricks take two hits, missing the ball costs a life, and clearing every brick wins.

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

| Option             | Default | Notes                                                       |
| ------------------ | ------- | ----------------------------------------------------------- |
| `rows`             | `4`     | Brick rows (`1`-`6`).                                       |
| `cols`             | `7`     | Bricks per row (`3`-`10`).                                  |
| `ballSpeed`        | `280`   | Starting ball speed, px/s (`120`-`600`).                    |
| `ballSpeedUp`      | `1.04`  | Speed multiplier per paddle hit (`1`-`1.4`; `1` = no ramp). |
| `paddleWidth`      | `84`    | Paddle width, px (`40`-`200`).                              |
| `lives`            | `3`     | Balls you can lose before failing (`1`-`9`).                |
| `toughBrickChance` | `20`    | % of bricks needing two hits (`0`-`100`).                   |
| `timeLimit`        | `0`     | Ms budget (`0` = no limit).                                 |
| `canCancel`        | `true`  |                                                             |
| `autoStart`        | `false` | Shows a "press to start" gate. `true` starts immediately.   |

```lua Presets theme={"dark"}
-- Tutorial
exports['awoken_minigames']:Breakout({ rows = 2, cols = 5, paddleWidth = 120, lives = 5, toughBrickChance = 0, ballSpeed = 220, ballSpeedUp = 1 })
-- Easy
exports['awoken_minigames']:Breakout({ rows = 3, cols = 6, paddleWidth = 100, lives = 4, toughBrickChance = 10, ballSpeed = 250 })
-- Standard (defaults)
exports['awoken_minigames']:Breakout({})
-- Hard
exports['awoken_minigames']:Breakout({ rows = 5, cols = 9, paddleWidth = 66, lives = 2, toughBrickChance = 35, ballSpeed = 330, ballSpeedUp = 1.06 })
-- Expert
exports['awoken_minigames']:Breakout({ rows = 6, cols = 10, paddleWidth = 56, lives = 1, toughBrickChance = 45, ballSpeed = 360, ballSpeedUp = 1.07 })
-- Reinforced
exports['awoken_minigames']:Breakout({ rows = 3, cols = 7, toughBrickChance = 100, lives = 3 })
```

<Tip>
  Hit the ball with the edge of the paddle to angle it into new bricks - dead-centre hits just bounce it straight up and down.
</Tip>

***

## Stick It

A hub spins in the middle. Press Space or click to fire a pin into it, and it sticks wherever the hub is facing. Land the target number of pins to win - hit a pin that's already stuck and you lose. The hub can flip direction after any pin and can start with pins already in it, so the timing keeps changing.

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

| Option          | Default | Notes                                                                  |
| --------------- | ------- | ---------------------------------------------------------------------- |
| `pins`          | `8`     | Pins to land to win (`1`-`20`).                                        |
| `rotationSpeed` | `90`    | Hub rotation, degrees per second (`10`-`720`).                         |
| `reverseChance` | `40`    | % chance the hub reverses direction after each landed pin (`0`-`100`). |
| `startingPins`  | `2`     | Pins already in the hub at the start (`0`-`6`).                        |
| `timeLimit`     | `0`     | Ms budget (`0` = no limit).                                            |
| `canCancel`     | `true`  |                                                                        |
| `autoStart`     | `false` | Shows a "press to start" gate. `true` starts immediately.              |

```lua Presets theme={"dark"}
-- Tutorial
exports['awoken_minigames']:StickIt({ pins = 4, rotationSpeed = 55, reverseChance = 0, startingPins = 0 })
-- Easy
exports['awoken_minigames']:StickIt({ pins = 6, rotationSpeed = 70, reverseChance = 0, startingPins = 1 })
-- Standard (defaults)
exports['awoken_minigames']:StickIt({})
-- Hard
exports['awoken_minigames']:StickIt({ pins = 12, rotationSpeed = 130, reverseChance = 55, startingPins = 3 })
-- Expert
exports['awoken_minigames']:StickIt({ pins = 16, rotationSpeed = 165, reverseChance = 65, startingPins = 4 })
-- Metronome
exports['awoken_minigames']:StickIt({ pins = 10, rotationSpeed = 110, reverseChance = 0, startingPins = 2 })
```

<Tip>
  Set `reverseChance` to `0` and the hub spins at a steady rhythm players can zone out on. Raise it and the direction can flip after any pin, so they have to keep watching.
</Tip>

***

## Match It

A wheel in the middle is split into coloured wedges, and coloured tiles fly in from the edge one at a time. Turn the wheel with A/D or the arrows so the wedge facing the tile matches its colour. Matching a tile absorbs it; a wrong colour is a mistake. Match the target number of tiles to win.

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

| Option            | Default | Notes                                                     |
| ----------------- | ------- | --------------------------------------------------------- |
| `tiles`           | `8`     | Tiles to match to win (`1`-`20`).                         |
| `sectors`         | `4`     | Faces on the wheel (`2`-`6`); more = harder to line up.   |
| `tileSpeed`       | `90`    | Tile approach speed, px/s (`20`-`400`).                   |
| `spawnMs`         | `700`   | Ms between tiles (`150`-`5000`).                          |
| `mistakesAllowed` | `2`     | Wrong matches tolerated before failing.                   |
| `timeLimit`       | `0`     | Ms budget (`0` = no limit).                               |
| `canCancel`       | `true`  |                                                           |
| `autoStart`       | `false` | Shows a "press to start" gate. `true` starts immediately. |

```lua Presets theme={"dark"}
-- Tutorial
exports['awoken_minigames']:MatchIt({ tiles = 4, sectors = 2, tileSpeed = 55, mistakesAllowed = 4 })
-- Easy
exports['awoken_minigames']:MatchIt({ tiles = 6, sectors = 3, tileSpeed = 70, mistakesAllowed = 3 })
-- Standard (defaults)
exports['awoken_minigames']:MatchIt({})
-- Hard
exports['awoken_minigames']:MatchIt({ tiles = 12, sectors = 5, tileSpeed = 125, spawnMs = 520, mistakesAllowed = 1 })
-- Expert
exports['awoken_minigames']:MatchIt({ tiles = 14, sectors = 6, tileSpeed = 150, spawnMs = 450, mistakesAllowed = 0 })
-- Against the clock
exports['awoken_minigames']:MatchIt({ timeLimit = 30000 })
```

<Tip>
  `sectors` is the main difficulty dial - more wedges means further to turn and less time to react. Raise `tileSpeed` for pace, but `sectors` for real difficulty.
</Tip>
