File size: 18,239 Bytes
161d0a9 93a3c54 161d0a9 f0726aa 58e1249 f0726aa 58e1249 f0726aa d67855c fc6ce84 d67855c fc6ce84 d67855c fc6ce84 d67855c f0726aa 93a3c54 f0726aa 161d0a9 93a3c54 161d0a9 93a3c54 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 | # Arc roadmap
This is the living plan for the game's arcs (skins/backstories). It records the
design rules every arc must follow, what's already built, and the queue of
future arcs so we can pick up any of them later without re-deriving the idea.
Each arc is one self-contained `data/arcs/<id>.json` file plus a
`body[data-skin="<name>"]` block in `static/style.css`. See the README section
*Adding an arc* for the file schema. New arcs appear on the opening screen
automatically.
---
## Design rules (apply to every arc)
The mechanic is fixed: move through a place that should be identical each loop;
**turn back** if something changed, **go on** if nothing did; eight correct
calls in a row wins, one wrong call resets. What differs per arc is the story,
vocabulary, skin β and the *flavour* of the anomalies. Every arc must include:
1. **A strong motivation ("the hook").** A concrete in-world reason you're stuck
doing this, revealed in the intro β the equivalent of Stairway 8's
out-of-order elevator. Never "you are being tested" with no diegetic cause.
2. **An NPC.** A recurring character that is normally passive but can become the
anomaly β turning, watching, approaching, vanishing, duplicating. Every arc
needs its own recurring uncanny figure.
3. **A loop-aware NPC twist.** At least one NPC anomaly that breaks past physical
change into the uncanny: the character *acknowledges you* or the loop itself
(waves, beckons, mouths/says "again"). Property key convention: `knows` for
silent figures, `speaks` for ones that can talk.
4. **A psychological layer (`sense`).** A non-physical property whose baseline is
your ordinary state and whose anomalies are perceptual/emotional wrongness β
losing count, a calm that shouldn't be there, a conviction you're going the
wrong way. Anomalies beyond objects, per the "twists" requirement.
5. **Meta drift (free).** The engine already drifts the heading, wording, pacing,
weight, spacing and background every loop β no per-arc work needed, but keep
`title_variants` themed.
6. **Win-screen strings (in `meta`).** Three short, arc-flavoured lines the exit
screen needs, so the reward matches the place:
- `share_prompt` β the invitation above the share row, phrased for this arc's
exit (Hallway: *Leave the door open.*, Stairway: *Leave the door open
below.*, Coach: *Hold the doors.*).
- `attempt` β the "look back" line shown when the run took more than one try.
**Must contain the `{n}` placeholder** (the run count), spliced in front so
it localizes cleanly, e.g. *{n} times down this corridor, and this time it
opened.*
- `attempt_first` β the line for a clean first run (no placeholder), a small
reward for a flawless escape, e.g. *First time through, and the corridor let
you go.*
Keep anomalies *plausible*, never loud. One property mutates per anomalous loop,
and it is always among the details shown that loop (the engine guarantees this).
---
## Shared tuning (all arcs inherit this β do not re-tune per arc)
These curves are engine-wide, not per-arc. A new arc gets them for free; only
change them if you intend to change the feel of *every* arc.
### Difficulty ramp β `hallway.py`
The chance a loop contains an anomaly is a function of the player's level, so the
first stage after entering leans toward "nothing changed" (learn the baseline by
proceeding) and gets harder as you descend/advance:
```
anomaly_chance(level) = min(ANOMALY_MAX, ANOMALY_BASE + ANOMALY_STEP * level)
ANOMALY_BASE = 0.02 # level 0: VERY low, no baseline seen yet
ANOMALY_STEP = 0.076 # per level cleared (steep, to reach the cap by ~L7)
ANOMALY_MAX = 0.55 # capped so "always turn back" never wins
```
So the opening loop (level 0) is only ~2% (easy 1%, hard 3%), rising steeply to
the cap by around level 7 (normal 55%, easy 30%, hard 60%). The very-low opening
is deliberate: on your first loop you have no baseline, so being turned back
would be a coin flip you cannot win. It is not zero (a rare early jolt keeps the
place honest). Level resets to 0 on a wrong call, which re-eases the first stage,
intentional re-onboarding, not a bug. There is no level-0 floor (the low opening
is the point; levels 1+ ramp well clear of zero so "always continue" still
loses). Because content is *shown* fairly (the mutated property is always among
the details displayed), the ramp changes frequency, never fairness. Guard: keep
`ANOMALY_MAX β€ ~0.55` or turning back becomes dominant.
### Aggro-item / late reveal (`hallway.py`)
Each arc's `meta.late_props` names a couple of small, inconspicuous properties
(existing details, not new ones). Once per climb, `build()` may **hold some out**
of the early loops so they first surface mid-run. `mem.held` maps each held prop
to its reveal level:
```
reveal level β [2, GOAL-2] # ~level 2-6 at goal 8, never the last
hold: hard β always, 1 or 2 items (the "not everything up front" pressure)
normal β rare (~15%), a single item; rotation is the everyday replay hook
easy β never
```
Holding 1-2 items reliably is a **hard-mode** feature. Normal mode leans on the
ordinary fact that only 4-6 of ~9 details show each loop (and Act 2 touch
outcomes vary), so a normal player meets almost every encounter over a few runs
without ever being deliberately starved. Not showing everything every run is a
core principle and the replay hook.
Fairness guard (`mem.seen_props`): an anomaly may only land on a detail the
player has already seen at **baseline on an earlier loop**, so the held item is
never the change on the loop it first appears. Its debut is always a calm
baseline; only later can it move. This keeps a late arrival a memory test, never
pure luck, even at the last level (by then it is long established). Pick
`late_props` that are genuinely minor (a fixture, a small object), never the NPC
or the `sense`.
### Doubt prompt curve β `static/game.js`
The confidence prompt is not shown every turn. After a Go-on/Turn-back choice,
the chance it interrupts grows as you near the exit:
```
chance = min(0.85, 0.12 + level * (0.7 / goal)) # ~12% early β ~73% at level 7
```
- **Certain / Almost sure** (conf β₯ 3) β the choice commits and is judged.
- **Guessing / I think so** (conf β€ 2) β does *not* commit; returns you to the
scene for exactly **one** re-decide (the `hesitated` flag blocks a second
prompt that turn). The re-look is the only "reward" β no points, no safety net.
This is pure client-side UX: confidence never enters the server's correctness
formula (`correct = (choice == "back") == has_anomaly`). New arcs need no work to
inherit it.
### Session state β `app.py`
State is keyed by a client-echoed `sid` (X-Sid header), **not** the session
cookie, so an arc and its progress survive in a cross-site iframe (Spaces). Arcs
never need to touch this.
### Win screen & sharing β engine-wide
The exit screen is shared by every arc; an arc only fills in the three `meta`
strings above. The engine handles the rest:
- **Look back (fleeting run count).** A quiet toggle under "You're out." surfaces
the arc's `attempt` / `attempt_first` line, then fades after a few seconds and
reclaims its space so the eye settles on sharing or replaying. The run count is
a per-session counter in `PlayerMemory` (`attempts`, resets + 1), and the line
is localized server-side like win text.
- **Sharing.** One of eight cryptic "invitation" lines (shared UI strings
`share_1..8`) is chosen at random, with the arc's `share_prompt` above it.
Mobile-first: where a native share sheet exists it is the single button (it
reaches Instagram, Snapchat, X, Messages, everything); otherwise explicit X /
Facebook / LinkedIn links plus Copy link. The shared URL unfurls as the game's
own "8" Open Graph card (`static/img/og.png`).
New arcs inherit all of this for free once the three `meta` strings are set.
---
## Built
*These three are the only production arcs for the current phase. Everything in
"Planned", "Backlog", and "Brainstorm" below is idea-stage only β keep it out of
the live 3-arc game until an idea is deliberately promoted up into this table.*
| Arc | Hook | Loop unit | NPC (+ twist) | `sense` anomalies | Skin |
|-----|------|-----------|---------------|-------------------|------|
| **Hallway 8** (`hallway-eight`) | Locked in after hours; a sign points to the fire exit | corridor | man in grey suit (`knows`: turns/beckons/"again") | longer, forget, calm | cold teal |
| **Stairway 8** (`stairway8`) | Elevator out of order; descend on foot | landing | figure on the stairs below (`knows`: looks up, waves, ascends) | deeper, forget, wrong-way | emergency green |
| **Coach 8** (`coach8`) | Conductor sent you to coach 8; the train never reaches it | carriage | sleeping passenger (`speaks`: murmurs "again", "you were just here") | forget, calm, watched | cabin amber |
---
## Planned (not yet built)
Each entry is enough to implement directly. Ordered by how strong/fresh the loop
feels; pick any.
### Platform 8 (`platform8`) β the underpass
- **Hook:** last train of the night; the turnstiles are shut and a sign routes
you through the pedestrian underpass β FOLLOW SIGNS TO PLATFORM 8.
- **Loop unit:** identical tiled underpass segments. **Go on** = walk on /
**Turn back** = double back.
- **NPC:** a busker sitting against the wall with an open case. Twist (`knows`):
stops playing to watch you; case is suddenly empty/overfull; plays the same
bar as you pass "again."
- **Physical anomalies:** tiled advert, the drip-puddle, map's "YOU ARE HERE"
dot, poster date, platform number on the sign, tile colour, a pigeon.
- **`sense`:** the tunnel feels longer; you forget which platform you wanted; a
certainty you already caught the train.
- **Skin:** cold blue-white station tile (`--hue: 205`).
### Aisle 8 (`aisle8`) β locked in the supermarket
- **Hook:** you looked up and the shop had closed around you; the tannoy loops
"please proceed to checkout 8 to exit."
- **Loop unit:** identical grocery aisles. **Go on** = next aisle / **Turn
back** = previous aisle.
- **NPC:** a night-shift stocker with a trolley, back to you. Twist (`knows`):
turns and stares; trolley abandoned mid-aisle; softly says "again" over the
muzak.
- **Physical anomalies:** a shelf gap, a product facing the wrong way, a price
label, the end-cap promo, the muzak track, the abandoned trolley, floor sheen.
- **`sense`:** the aisle feels longer; you forget your list; a calm certainty
you've already paid.
- **Skin:** flat retail fluorescent, a touch too bright (`--hue: 60`, high L).
### Ward 8 (`ward8`) β the hospital at night
- **Hook:** visiting hours are over; the night sign says the way out is via Ward
8. *(Handle tone with care β dread, not gore.)*
- **Loop unit:** identical hospital corridors. **Go on** / **Turn back**.
- **NPC:** a patient in a gown standing in a doorway, or a nurse at the far
station. Twist (`knows`): the figure has moved to the next doorway; is facing
you; mouths "again."
- **Physical anomalies:** a gurney's position, the room-number plate, a
flickering "NIL BY MOUTH" sign, the hand-gel dispenser, a chart on a door,
distant monitor beeps, a wheelchair.
- **`sense`:** the corridor feels longer; you forget why you came; a wrong calm.
- **Skin:** pale clinical green-grey (`--hue: 160`, low sat).
### Level 8 (`level8`) β the underground car park
- **Hook:** your ticket says Level 8; the lift to the street is dead, so follow
the ramp up. (Ascending mirror of Stairway 8.)
- **Loop unit:** identical parking rows. **Go on** = up a ramp / **Turn back** =
back down.
- **NPC:** a figure between the parked cars, or someone sitting in a driver's
seat. Twist (`knows`): the seated figure's headlights flick on as you pass; it
has moved cars; it waves.
- **Physical anomalies:** a parked car's colour, the level number on the pillar,
a flickering strip light, the arrow painted on the floor, an oil stain, a
distant engine, a car alarm.
- **`sense`:** the level feels deeper; you forget where you parked; certainty
you're descending, not climbing.
- **Skin:** concrete grey with sodium-orange pools (`--hue: 30`, low L).
### Gate 8 (`gate8`) β the airport after the last flight
- **Hook:** you dozed off; the terminal's near-empty and the board shows one
route left β EXIT VIA GATE 8.
- **Loop unit:** identical concourse stretches / travelators. **Go on** /
**Turn back**.
- **NPC:** a lone cleaner with a floor-buffer, or a single seated passenger.
Twist (`knows`): stops buffing to watch; the seated passenger is gone/closer;
a gate announcement says your name.
- **Physical anomalies:** the gate number, a departures-board row, the duty-free
window display, an abandoned bag (unsettling), the announcement chime, a clock,
a potted plant.
- **`sense`:** the concourse feels longer; you forget your destination; a calm
that you've already boarded.
- **Skin:** glassy blue night-terminal (`--hue: 215`).
---
## Backlog ideas (thin β flesh out before building)
- **Museum after close** β galleries loop; NPC is a security guard or a statue
that isn't always in the same pose.
- **Motel corridor** β reach room 8 / the exit; NPC is someone at an ice machine.
- **Ferry decks** β climb decks to the exit; NPC a lone smoker at the rail;
motion + sea outside the windows.
---
## Brainstorm β later phases (idea-stage, NOT production)
Fresh settings that complement the transit/civic bias of the Planned queue: a
knowledge space, a money/dread space, a modern-tech space, a sacred space, and a
play-gone-wrong space β five different emotional registers, still melancholy
rather than violent. Each satisfies the design rules (hook, loop unit, NPC with
a loop-aware twist, physical anomalies, a `sense` property). Suggested skin hues
are candidates only; whichever get built must stay visually distinct from the
live blue/amber/green and from each other.
### Stacks 8 (`stacks8`) β the library at lockup
- **Hook:** the lights dropped to night mode while you read; a card says the way
out is past Aisle 8 of the stacks.
- **Loop unit:** identical rows of tall shelving. **Go on** = next aisle /
**Turn back**.
- **NPC:** a night librarian re-shelving from a trolley, back to you. Twist
(`knows`): stops, turns to watch, mouths "again". Or a reader asleep at a
carrel (`speaks`: "you already returned it").
- **Physical anomalies:** a book's spine title, a shelf gap, a volume shelved
upside-down or backwards, the aisle-number sign, a reading lamp on/off, the
step-stool moved.
- **`sense`:** the aisle feels longer; you forget which book you came for; a
wrong calm that you've already checked out.
- **Skin:** violet dusk through high windows (`--hue: ~275`). Books are an
unusually strong anomaly engine β probably the richest of these five.
### Vault 8 (`vault8`) β the bank vault, timelock running down
- **Hook:** your safe-deposit box is in aisle 8; the outer door is on a timelock
that reopens at dawn, so keep going.
- **Loop unit:** identical corridors of numbered brass boxes. **Go on** /
**Turn back**.
- **NPC:** a night guard on his rounds (`knows`: stops, watches, nearer) or a
customer at an open box who won't leave (`speaks`: "you were just here").
- **Physical anomalies:** a box number, a box door ajar, a dropped key on the
runner, the timelock clock's hands, the carpet runner's colour, a convex
security mirror's angle.
- **`sense`:** the vault feels deeper; you forget your box number; a calm that
you've already emptied it; wrong-way.
- **Skin:** crimson carpet + burnished brass (`--hue: ~350`).
### Data Hall 8 (`datahall8`) β the data-centre cold aisle at 3am
- **Hook:** the badge reader sent you to Hall 8 to reseat a server; the lift back
is locked to your card, so walk the aisle.
- **Loop unit:** identical rows of caged server racks. **Go on** / **Turn back**.
- **NPC:** a lone technician with a laptop cart far down the aisle (`knows`:
turns, watches, closer) β very modern loneliness.
- **Physical anomalies:** a rack's blinking-LED count, a cage door ajar, a coiled
cable on the floor, a KVM screen showing your own login, a warm aisle where it
should be cold, the hum's pitch.
- **`sense`:** the hall feels longer; you forget which rack; the hum stops (a
diegetic "wrong silence"); a wrong calm.
- **Skin:** indigo LED wash (`--hue: ~265`). The only contemporary/tech setting.
### Cloister 8 (`cloister8`) β the abbey at night
- **Hook:** locked in after the last visitors; complete the eighth circuit of the
cloister to reach the chapel door.
- **Loop unit:** identical vaulted arcades around a dark garth. **Go on** /
**Turn back**.
- **NPC:** a cowled figure with a taper at the far arcade (`knows`: turns, raises
a hand, nearer each loop, mouths "again").
- **Physical anomalies:** a wall sconce lit/dark, a carved boss or gargoyle, a
statue's pose out in the garth, a grave-slab inscription underfoot, the bell
(tolls once too many), a stained-glass panel.
- **`sense`:** the walk feels longer; you forget which office you came to pray; a
wrong serenity; wrong-way (the cloister circles anticlockwise now).
- **Skin:** candle-lit stone, very low saturation warm grey (`--hue: ~35`,
desaturated so it reads neutral, not Coach's amber).
### Midway 8 (`midway8`) β the shuttered funfair
- **Hook:** you stayed past closing; the only lit exit sign is down the midway,
past booth 8.
- **Loop unit:** identical stretches of game stalls and strung bulbs. **Go on** /
**Turn back**.
- **NPC:** a costumed mascot standing dead still by a stall. Twist (`knows`): it
has turned to face you; it's closer; its head is tilted. (Unsettling without
gore.)
- **Physical anomalies:** a prize wall, a strung bulb dark/lit, a carousel
horse's position, a ticket-booth number, the calliope music (loops backward),
a balloon snagged on a wire.
- **`sense`:** the midway feels longer; you forget which ride you were heading
to; a wrong festive calm; wrong-way.
- **Skin:** faded pink-and-gold neon (`--hue: ~320`).
|