Two things, one of them a real bug. THE BUG: bakeTiles baked to a single global 'floor:tiles' and early-returned if that key existed. Textures outlive a scene, so the first venue you played baked the floor for every venue after it — you would survive a week at The Royal, get promoted, walk into Voltage and still be standing on the pub's carpet. It only shows on promotion, which is exactly the moment the venue ladder is supposed to pay off, and never in a dev route because those reload the page. The baked texture is now keyed per venue; verified by switching venues inside one session and watching the concrete arrive. MATERIALS: FloorLayout.materials names a generated plate per tile kind and the baker stamps it TINTED to the palette colour. The plate carries grain, the palette keeps hue — an untinted photo-real plate blows straight past the brightness band the whole room was tuned in, and darkness is the mechanic. Plates are 16x16, the game's own tile, because at that size "carpet" is structured noise, which is also what pub carpet looks like from head height. Ten of them: carpet, concrete, deck, parquet, looTile, paving, plaster, brick, timber, steel. No plate named, or art not landed, falls back to flat colour exactly as before. Wave 2 filler for the two spaces the review found genuinely empty — The Royal's central carpet (four props across ~500 tiles) and ROOM's east hall (~23% of its interior with no lights and three props) — plus the kit every real room has and no game room does: fire extinguishers, exit signs, CCTV, bins, a notice board, ceiling fans. Voltage gets the same pass; being the reference room is how it quietly missed the last one. The invariant caught a duplicate prop id I introduced while placing these, which is what it is for. Also relaxed one ROOM assertion that keyed on array order: it checked that the FIRST sodium light stands over the loading dock, which broke the moment the east hall legitimately burned the same colour. It now checks that one of them does. Gate: lint clean, tsc clean, 821 tests passing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
9.0 KiB
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 tovoid, 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):- every
AnchorKindhas ≥1 anchor, and every anchor is walkable; - all walkable tiles are mutually reachable (flood fill), except sealed
cubicle interiors, which must be reachable from their
StallDef.door; - every
POSTSentry is walkable and has a walkable neighbour (a post on a sealed tile freezes the player for the night — this has shipped twice); - every
PROBESentry has a walkable tile within reach; - no prop hangs off the grid.
- every
- Materials are grain, the palette is hue.
FloorLayout.materialsnames a generated plate per tile kind (tex_carpet,tex_concrete, …) and the baker stamps it tinted to the palette colour. That is deliberate: an untinted photo-real plate blows straight past the brightness band everything else was tuned in, and the room stops being dark. Plates are 16×16 — the game's tile — because at that size "carpet" is structured noise, which is also what pub carpet looks like from head height. No plate named, or art not landed: flat palette colour, exactly as before. - The baked floor is keyed per venue (
floor:tiles:<id>). Textures outlive a scene, so a single global key meant the first venue you played baked the floor for every venue after it — you would survive a week at The Royal, get promoted, and walk into Voltage still standing on the pub's carpet. It only shows on promotion, which is precisely when the ladder is supposed to pay off. - 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.