The venue ladder has always listed four venues in data/venues.ts, but they shared ONE floor map and differed only by difficulty knobs — so a promotion you survived a whole week for looked exactly like the room you had just left. - venueMap.ts grows a FloorLayout contract (map + props + lights + posts + probes + palette) and the newGrid() primitives every room is painted with. Voltage stays IN venueMap rather than moving to layouts/, so the new rooms can import primitives from it without closing an import cycle. - Three new rooms in src/scenes/floor/layouts/: The Royal (horseshoe public bar, pool room, pokies corner, trough + two cubicles, a beer garden that is plainly the nicest room in the pub, and a DJ "corner" that is a folding table because this pub never built a booth), Elevate (open-air rooftop — most of the grid is sky, the DJ is on an unwalled plinth, you arrive by lift), ROOM (concrete warehouse, pillars you path around, central booth, loading-dock smoking area, twelve lights in the whole venue). - Nothing about a room is a module singleton any more. FloorView, sweep and FloorDemoScene take the layout; the door picks its street plate by venue id. - FloorDemoScene's six hardcoded station spots (TAPS_SPOT, DECKS_SPOT, ...) were Voltage's tile coordinates. At four venues a hardcoded (47,3) puts the bar shift inside The Royal's pool room, so each layout now names its own stations and the scene reads them from there. - tests/floor/layoutInvariants.ts is an executable rulebook: perimeter holds, every walkable tile reachable from the entry, anchors on walkable ground, posts not sealed (a post on a sealed tile freezes the player for the night — that has shipped twice), probes reachable, props on-grid. Proved against Voltage BEFORE the new rooms were authored against it. Dev route #floor:<venueId> boots the floor straight into one room, because otherwise seeing ROOM means surviving three weeks of the ladder. Gate: lint clean, build clean, 821 tests passing (was 784). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
138 lines
8.0 KiB
Markdown
138 lines
8.0 KiB
Markdown
# NOT TONIGHT — the four venues
|
||
|
||
*Written 2026-07-28. The venue ladder in `src/data/venues.ts` has always been
|
||
four venues; up to now they shared ONE floor map and differed only by difficulty
|
||
knobs. This document is the design contract for giving each its own room.*
|
||
|
||
## 0. Why bother
|
||
|
||
Design §6 sells the ladder as *promotion* — survive a week, get a better door.
|
||
But a promotion you cannot see is a number, not a reward. Walking into Elevate
|
||
and finding The Royal's carpet under your feet undoes the fiction the whole run
|
||
is built on. Each venue now has its own bar layout, its own dunnies, its own
|
||
smoking area and its own DJ booth, because those four things are exactly what a
|
||
bouncer actually learns about a room.
|
||
|
||
## 1. Shared contract (all four)
|
||
|
||
- **Grid is fixed at 80×45 tiles.** Venues differ by ARRANGEMENT, not extent —
|
||
the camera, minimap and bounds maths all key off `MAP_W`/`MAP_H`, and a
|
||
per-venue grid size would be a refactor with no visible payoff. A small venue
|
||
reads small by walling its unused grid to `void`, not by shrinking the array.
|
||
- **Every layout exports a `FloorLayout`**: `{ id, map, props, lights, posts,
|
||
probes }`. Nothing else may be a module singleton — that was the old shape and
|
||
it is what made four venues impossible.
|
||
- **Every layout must satisfy the same invariants** (`tests/floor/layouts.test.ts`):
|
||
1. every `AnchorKind` has ≥1 anchor, and every anchor is walkable;
|
||
2. all walkable tiles are mutually reachable (flood fill), except sealed
|
||
cubicle interiors, which must be reachable from their `StallDef.door`;
|
||
3. every `POSTS` entry is walkable and has a walkable neighbour (a post on a
|
||
sealed tile freezes the player for the night — this has shipped twice);
|
||
4. every `PROBES` entry has a walkable tile within reach;
|
||
5. no prop hangs off the grid.
|
||
- **Light signatures survive** (SPACES.md §1): bar = amber, dance = pulsing
|
||
pink on the real beat, DJ = deep blue, toilets = flickering green, smoking =
|
||
cool blue, entry = venue pink. A venue may add ONE signature colour of its
|
||
own — Elevate's skyline gold, ROOM's sodium orange — and no more, or the
|
||
navigate-by-glow rule stops working.
|
||
- **Darkness stays the mechanic.** No venue may be bright enough to scan from
|
||
the doorway.
|
||
|
||
## 2. The Royal — "a dive with a dance floor"
|
||
|
||
Licensed 80 · regulars and punters · nobody checks anything.
|
||
|
||
A suburban Australian pub that had a dance floor bolted on in about 2004 and has
|
||
not redecorated since. Patterned carpet, a horseshoe public bar, and the dance
|
||
floor is plainly the least important thing in the building.
|
||
|
||
| Space | What's in it |
|
||
|---|---|
|
||
| **Public bar** (horseshoe, west) | the long counter, taps, till, keg stack, a TV showing the footy, bar fridges |
|
||
| **Pool room** (north-west) | two pool tables, cue rack, a dartboard on the wall |
|
||
| **TAB / pokies corner** (north-east) | bank of poker machines, TAB screens, stools, its own miserable light |
|
||
| **Bistro** (centre-north) | bistro tables, bain-marie counter, the meat-raffle drum |
|
||
| **Dance floor** (south-east) | small, an afterthought, one mirror ball, a jukebox on the wall |
|
||
| **DJ corner** | not a booth — a folding table with a controller, beside the dance floor |
|
||
| **Dunnies** (east) | a stainless TROUGH, two cubicles (one out of order), one basin |
|
||
| **Beer garden** (south, open sky) | picnic tables, umbrellas, patio heater, butt bin — the smoking area, and the nicest room in the pub |
|
||
|
||
Light: warm amber everywhere, green cone over each pool table, the pokies' own
|
||
sickly blue, and the beer garden cool blue. No pink except the dance corner.
|
||
|
||
## 3. Voltage — "valley institution"
|
||
|
||
Licensed 110 · the tuning baseline · the inspector drinks here.
|
||
|
||
**This is the existing map and it does not change.** It is tuned under the
|
||
darkness sheet, its reachability is asserted, and every existing floor test
|
||
targets it. It stays the default layout and the reference for the other three.
|
||
|
||
## 4. Elevate — "rooftop, small room, big opinions"
|
||
|
||
Licensed 70 · influencers and owner's mates · every second person is a VIP.
|
||
|
||
The whole venue is outdoors, which makes the rain a design element rather than a
|
||
yard-only effect. Small footprint — a third of the grid is sky. You arrive by
|
||
lift, not off the street, so the entry is a lobby.
|
||
|
||
| Space | What's in it |
|
||
|---|---|
|
||
| **Lift lobby** (west) | lift doors, a rope line, the stamp podium, one mirror |
|
||
| **Cocktail bar** (north) | short backlit bar, no taps — bottles and a champagne bucket |
|
||
| **VIP booths** (east) | banquettes behind velvet rope posts, low tables |
|
||
| **Dance floor** (centre, small) | it is a terrace with a dance floor, not a club |
|
||
| **DJ plinth** | raised, open, no booth walls — the DJ is on display |
|
||
| **Toilets** (north-east) | two unisex cubicles, marble basin, enormous mirror |
|
||
| **Terrace edge** (south + east) | glass balustrade, planters, the city skyline beyond |
|
||
| **Smoking** | the whole roof is open air; a designated corner with a standing ash urn and heat lamps |
|
||
|
||
Light: warm amber bar, cool blue-white terrace, deep blue DJ, and the venue's
|
||
own signature — **skyline gold** spilling from the city card beyond the glass.
|
||
|
||
## 5. ROOM — "no sign, no socials"
|
||
|
||
Licensed 60 · heads and chancers · the board is the law.
|
||
|
||
A concrete warehouse. No branding anywhere, because branding is how you get
|
||
found. The sound system is the most expensive thing in the building by an order
|
||
of magnitude and everything else is borrowed.
|
||
|
||
| Space | What's in it |
|
||
|---|---|
|
||
| **Main floor** | concrete pillars, no booths, the crowd is the furniture |
|
||
| **The stacks** | Funktion-One-style speaker towers + subs — huge, four corners |
|
||
| **DJ booth** | low, central, facing the floor, no barrier — CDJs not turntables |
|
||
| **Bar** (west) | a plywood plank on scaffolding, cans only, no taps, no till |
|
||
| **Toilets** (north-east) | industrial, graffiti on every surface, three cubicles of which one works, a cracked basin, no mirror |
|
||
| **Loading dock** (south, open sky) | roller door, pallets, a wheelie bin — this is the smoking area |
|
||
| **Chill-out** (north-west) | two ruined couches under a single bulb |
|
||
| **The board** | the rule board that rewrites itself (`shuffleDressCode`) — a physical prop by the entry |
|
||
|
||
Light: almost none. Sodium orange over the loading dock (ROOM's signature),
|
||
one flickering green fluoro in the dunnies, strobes on the floor, and the
|
||
stacks' own power LEDs. This is the darkest venue in the game on purpose.
|
||
|
||
## 6. Prop vocabulary added for these rooms
|
||
|
||
Route per SPACES.md §"Prop pipeline": **[F]** = flux direct (flat things —
|
||
signage, boards, screens, backdrops); **[M]** = product shot → TRELLIS.2 →
|
||
Blender ortho render (things with volume). Rake follows the house rule —
|
||
**60° low and wide, ~76° tall**.
|
||
|
||
| Venue | Kinds |
|
||
|---|---|
|
||
| The Royal | `pokie`[M76] `tabBoard`[F] `bistroTable`[M60] `picnicTable`[M60] `trough`[M70] `keg`[M76] `dartboard`[F] `jukebox`[M76] `raffleDrum`[M60] `bainMarie`[M60] `tvSport`[F] `beerUmbrella`[M80] `ashtray`[M60] |
|
||
| Elevate | `cocktailBar`[M60] `banquette`[M60] `ropePost`[M76] `planter`[M60] `balustrade`[M76] `djPlinth`[M60] `marbleSink`[M70] `ashUrn`[M76] `champBucket`[M60] `loungeChair`[M60] `liftDoor`[F] `skylineCard`[F] |
|
||
| ROOM | `stackF1`[M76] `subBass`[M60] `plywoodBar`[M60] `rollerDoor`[F] `pallet`[M60] `wheelieBin`[M76] `oldCouch`[M60] `pillar`[M76] `ruleBoard`[F] `strobe`[M76] `smokeMachine`[M60] `cableSnake`[M60] `brokenBasin`[M70] `canStack`[M60] `cdj`[M60] |
|
||
| Staff (set dressing, all venues) | `staffBartender` `staffDj` `staffGlassie` `staffSecurity` — all [M76] |
|
||
|
||
Staff figures are PROPS, not patrons. The procedural dolls stay exactly as they
|
||
are: `dollPlan` draws the specific items the dress code convicts on, so
|
||
replacing patrons with pre-rendered art would make the convictions invisible
|
||
(recorded in LANEHANDOVER, FABLE-SOLO-23). A bartender who never moves is set
|
||
dressing and carries no mechanical weight, which is why she can be a sprite.
|
||
|
||
Street plates (door scene, one per venue, [F], 640×176):
|
||
`street:royal` `street:elevate` `street:room` — `street:backdrop` stays Voltage's.
|