Docs Design

Contents

M1 content: the Tideline pack

Status: spec for T6, 2026-09-30. Tideline is the first game made entirely from a Game Pack. Scope and acceptance: ROADMAP M1 and research/unspent-ortho-study.md §4. Document shapes: m1-player.md §13. Kit vocabulary: each kit's kit.json on main when T6 starts. This file fixes the content, so the pack reads as one game rather than six tracks' fixtures stitched together.

Numbers start from unspent-ortho's tuned values (src/content/tuning.gd, src/content/roster.gd, read-only) where they fit the slice, and are then held by Tideline's own playtests. The source of truth is the pack, never this file: once the pack exists, change numbers there.

Pack layout

examples/tideline/
  game.json                  game.tideline → tpl.action_survival@1, seed 7, 60 Hz
  brief.json                 the brief below
  theme/tideline.theme.json  style/tideline.style.json
  stats/tideline.stats.json  tuning/tideline.tune.json
  archetypes/{wanderer,sentry,campfire}.archetype.json
  items/{driftwood,stone,scrap,knife,lamp}.item.json
  recipes/campfire.recipe.json   loot/sentry_scrap.loot.json
  brains/sentry.sm.json          rules/tideline.rules.json
  worlds/tideline.worldgen.json  biomes/coast.biome.json
  models/{pine,boulder,driftwood,wreck,sentry,wanderer,campfire,lamp}.model.json
  sounds/…                       ui/{title,hud,carry,make}.screen.json
  input/ and camera/ come from the template unless overridden
  playtests/{proof.tour, proof.playtest.json, tactics.playtest.json, stealth.playtest.json,
             determinism.playtest.json}

As built (T6): the tuning file is tuning/tideline.tuning.json (the suffix comes from the schema); there is also archetypes/scrap_pile.archetype.json (the heap the sentry drops) and models/scrap.model.json; the slate apps ui.carry and ui.make and the UI sounds come from the template; playtests/ adds trading.playtest.json, poster.tour and web/ (the browser tours).

Brief

  • Pitch: you wake on a dark coast where a broken machine keeps its round. Gather, make fire, carry a lamp, and learn to beat the sentry by reading it, not by trading blows.
  • Pillars: night is really dark; the lamp is both safety and a beacon; tactics beat stats.
  • Core loop: explore → take (driftwood, stone) → make (campfire) → survive the night → read the sentry's tell → dodge → strike its back → take its scrap.
  • Scope caps: one region, one machine, one recipe, five items, about 10 minutes of play.

World (gen.tideline, biome.coast)

  • 192×192 tiles, chunks of 32. Sea along the south edge; a beach band 10–18 tiles deep (sand, then shingle); turf and heath above; a cliff band at least 2 levels high cutting across the middle with two ramps; one tarn on the heath; levels 0–6.
  • Props: driftwood on the beach (about 40), boulders on shingle and heath (about 60), pines on the heath in clusters (about 150, crowns over 3 units so they stipple), one wreck on the beach.
  • Named places: spawn (the beach, near the wreck), wreck, tarn, cliff_top, ramp_east, ramp_west, and the sentry's round: round_a to round_d on the heath, one of them past the cliff so the hunt has to route around it.
  • Takes (Biome props[].take): driftwood by hand, 20 world minutes, 3 stages, yields 1 driftwood a stage; boulder by hand, 30 minutes, yields 1 stone a stage, 2 stages; the wreck needs the knife, 40 minutes, yields 1 scrap, 2 stages.

Player (arch.wanderer)

  • Walk 3.4, run 5.4, crouch 1.8 tiles per second; steps one level, blocked by two; wading at 0.6× in water under 0.5 deep; deep water blocks.
  • Health 6 (cells on the HUD). Downed at 0: 4 world hours pass and the wanderer wakes at the last campfire, or at spawn.
  • Knife swing: windup 180 ms, active 120 ms, recovery 260 ms, reach 1.2, damage 1.
  • Dodge: 280 ms, i-frames 220 ms, cooldown 600 ms, 2.5 tiles.
  • Starts with the knife held and the lamp in the pack; carries 12 bulk (driftwood 2, stone 2, scrap 1, knife 1, lamp 1).
  • Loudness: run 10, walk 5, crouch 2, taking a prop 6 (tiles heard at).

The sentry (arch.sentry, sm.sentry)

  • Health 5. Plate on the front arc (180°): a hit rings and does nothing. The working part is on the back arc (120°): a hit does full damage.
  • Sight 12 tiles in a 100° cone by day; night shortens sight to 0.5× and cover by cover_at, but a lit lamp restores full sight to anyone who carries it. Hearing 8 tiles, unaffected by dark or cover. Suspicion rises 0.35 a second at the edge of sight and 1.0 a second in the open near it; noticed at 1.0; decays at 0.2 a second.
  • Bite: windup 540 ms (the tell: its lens brightens and it lowers), active 140 ms, recovery 700 ms (its back is open), cooldown 600 ms, reach 1.6, width 1.4, damage 2.
  • States: patrol (walks round_a to round_d at 2.2 tiles/s, lens a slow cold pulse) → notice (turns, holds 400 ms, calls) → hunt (routes to the target at 4.6 tiles/s, slower than a run, faster than a walk) → attack (in reach) → forget after 3 s without contact or 24 tiles from its round (tether), back to patrol.
  • On death: drops loot.sentry_scrap (2 scrap), goes dark, stays as a wreck prop.

Campfire (rcp.campfire, arch.campfire)

  • By hand, 3 driftwood + 2 stone, 30 world minutes; builds arch.campfire one tile in front.
  • Warm, unsteady light (radius 7); sets the wake point; the fire's light is not a lamp (it doesn't make the wanderer visible to the sentry beyond its own radius).

Time and look

  • Clock 1.4 world minutes per real second; the game starts at 16:30 so dusk arrives in about 8 minutes of play; night 20:00–05:30.
  • Style: MADE for land, wood, cloth; FOUND for the sentry and the wreck; palette of wet sand, shingle grey, heath olive, turf green, sea slate; lamp warm amber; machine lens cold cyan-white; night ambient low enough that a lamp-lit pool raises mean luma by at least 40% over the unlit frame.

Playtests

  • proof.tour: from the title, no cheats: new game; goto prop:driftwood and take ×3; take stone ×2; make the campfire (await made:rcp.campfire); hour 20; toggle the lamp (shot night-lamp with player,light:lamp); goto near the sentry's round (shot round with arch.sentry); await noticed:player; await tell:sentry.0; dodge; strike its back (await hit:sentry.0) until await killed:sentry.0; take the scrap; save; quit to the title; load; assert same-state.
  • tactics.playtest.json: 20 seeds; the tactics bot wins at least 80%; the trading bot loses at least 80% (A4).
  • stealth.playtest.json: notice distances in the A5 order.
  • determinism.playtest.json: seeds 1–5, world digests match across runs (and in the web build).

From docs/design/m1-tideline.md in the Gamewright repository.