John looked at R41's proof shots and named three faults. All three are fixed, at zero draw cost, and every lane corrected somebody's numbers on the way — including its own. E-LOOK (§42.1+§42.2a) — THE PREMISE WAS WRONG. "The pub props have no texture" (my brief, quoting E's own R41 note) is false: all 37 carry COLOR_0 and three.js renders it. The colour was BLEACHED — jukebox at saturation 0.02, 15 assets under 0.05; what the source library called colour was baked AO. So the fix was a palette imposed on colour already present, in place: 46 assets, draw delta +0 and tri delta +0 on every one, proved the honest way — the concatenated POSITION/NORMAL/TEXCOORD/index bytes are sha1-identical to R41, so footprints and origins provably did not move. (A first-pass bbox check ignored node rotations and "found" 3 phantom violations; thrown out for the byte comparison.) The banquette was 1990s office teal and went burgundy; the beer umbrella was white and went brewery green. THE DECK, diagnosed before being touched: 7 greys, chassis 0.05 luminance on a 0.033 bench = 1.21:1, and the one high-contrast feature was INSIDE-OUT (white ring around a dark disc; a turntable is a dark record on a light platter). Now Technics silver at 6.74:1, black vinyl, red start/stop. Node contract re-read from the shipped GLB: 4/4 + 1/1 PASS. Filed to R43, not fixed: deck_1200_rigged has NO PLINTH (bottom 43mm of 119mm lost to R41 join damage). E-CAST (§42.3) — 19 of 24 ship. Rejected: comical_luchador_01 (Mixamo Ch43, purple mask reading EL CHUPACABRA, identified from the file's own material name), a 3-heads-tall cartoon child, a robed wuxia elder, a WW2 infantryman — and dj_phrtt_01, AN UNCLOTHED BODY whose only texture is a bare-skin atlas, which was in the DEFAULT crowd and live on the depot. It is the R41 deny-list's failure class through a different door: an innocent name from another pipeline. Only rendering all 24 and LOOKING found it. Ruling 2 (prefer CC0) was REFUSED ON MEASUREMENT: Quaternius is 25 nodes / 23 joints and ZERO of 64 canonical tracks bind — it would have loaded silently and never animated. Replacements came from Mixamo's Ch## pool, filtered to the contract-clean 65-bone family (candidates ran 65..99 bones; named characters carry facial/hair bones). THE LICENCE GAP WAS UNREAD, NOT MISSING: every source FBX carries ApplicationVendor "Mixamo, Inc." internally. Adobe royalty-free, no attribution owed. B's amber rows are now real. B (§42.5) — MY ASSIGNED FIX WAS USELESS AND B PROVED IT. document.fonts.ready shipped, then measured: the atlas canvases are already byte-identical across boots, the game ships NO webfonts (document.fonts.size === 0), and ready fires 50ms BEFORE the first fillText. The real cause of unreproducible bookmarks is the wall-clock CROWD — 983 changed px of 921,600, ALL in the pedestrian band; 0 px with the crowd out. New DBG.freeze() takes stable bookmarks 2/5 -> 5/5. Also found: ?pop=0 boots 140 citizens (0 is falsy against the default). THE BENCH: D's filing correct on both counts. Front-vs-road 90.0deg -> 0.0deg, min=med=max over 60/60 instances; the streetlight arm now reaches 1.05m over the road where it reached 0.00. Both used a base yaw that pointed +Z down the street while their own comments claimed otherwise — the side term was already right, which is why it survived 41 rounds of reading. Also: on any box with CDN access 9 of 60 benches are the depot GLB, 90deg out from the house law — normalised at the geometry, once, at load. benchStops(plan) exported as one truth. C (§42.2b) — 122 vs 123 WAS THE CAMERA ASPECT, and nobody was wrong. Draw counts are post-frustum-cull and the sweep camera inherits the window aspect: 1.25->116, 1.60->122 (C's harness), 1.778->123 (F's), 2.37->124. Pinned MEASURE_ASPECT=16/9 with a 1.25 control. E's "keep the bench dark" advice was measured and declined with reason (deck-vs-bench was already 4.73:1, over threshold). "Reads as a black box" is a claim about pixels, so C measured pixels: near-black in the booth crop 57.5% -> 26.7%, distinct colours 228 -> 389. Bench rebuilt 3->7 boxes with an open record bay; headphones on the mixer; faceDoor aims booths at the player's entry — alignment within 45deg went 49% -> 92%. Two bugs found by looking: a fitting could be planted INSIDE A WALL (0.77m of a 0.86m half-depth in plaster), and every booth part sat 25mm sunk into its own worktop. D (§42.4) — five swaps IN PLACE at the same index (pickRig indexes these arrays and pedIndex is in the identity signature and the impostor atlas; removal would renumber the town). Identity signature pre- vs post-swap: 0 differing lines of 150 — who each citizen is did not move, only which body they wear. dj_phrtt_01 verified gone AT THE WIRE, not from source: a fresh default boot fetches 32 ped GLBs, none retired. THE CONTROL ARM FOUND A 41-ROUND-OLD BUG: the ped being RETIRED, comical_boy_01, binds only 3,132 of 3,460 tracks — six thumb bones lack the mixamorig prefix. It had been silently dropping six tracks per clip since it shipped. Testing the thing being thrown away found it. Imported B's benchStops mid-round: sitters now 0.0deg to the road, signatures byte-identical across the rewire. Corrected F's filing: the browse smoke was flaky-by-construction (a 16-25s race against a live sim), not deterministically red. F (§42.6) — qa.sh --strict 24 passed / 0 failed / 0 warn / 0 skipped. New Gate 11: period law (0/5 banned; CONTROL: R41's roster trips all five) and roster licence (24/24, 0 unverified; CONTROL: an amber row turns 20 red). r41_shots.py promoted warn -> strict. R41'S BYTE-HASH BAN IS REVERSED AND ITS STATED REASON WITHDRAWN AS WRONG. A gate may pin a hash under five in-run assertions (classic+flags boot, freeze().stillLive all-false, a second freeze removing 0 draws, settle until DBG.info() stops changing, hash with the dbg panel hidden): 5/5 bookmarks now pin to one sha256 over 3 fresh boots. Two findings got it there — the chunk streamer (a fixed settle is a bet on load) and the fps readout, which with everything else frozen was the last thing moving at 53-62 px. ?pop=0 fixed (Number.isFinite) — a no-op for 35 rounds. Three red flags_check gates fixed. Street: noon 282 · NIGHT 291/300 — the nine-draw margin INTACT, every R41 row reproducing to the digit. Interior at pinned 16:9: 123 @ dept/auto, margin 227. selfcheck 157,647/157,647, 0x5f76e76 unmoved. No tag — John's playtest rules the epoch. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
207 lines
18 KiB
Markdown
207 lines
18 KiB
Markdown
# PROCITY
|
||
|
||
A standalone, procedurally generated, fully walkable 90s-Australian shopping town — every
|
||
building enterable (the Vuntra City trick), every interior seeded and themed: record stores,
|
||
op shops, toy shops, book barns, video rental, pawnbrokers, milk bars, market stalls. Built on
|
||
the proven house stack (three.js r175 vendored, plain JS, no build step) and the asset DNA of
|
||
90sDJsim + thriftgod. v1 is the *system*; the GODVERSE/BaseGod real-item content plugs in later.
|
||
|
||
## Run
|
||
|
||
```
|
||
cd web && python3 -m http.server 8130
|
||
# http://localhost:8130 (game shell — Lane B)
|
||
# http://localhost:8130/map.html (2D plan debugger — Lane A)
|
||
```
|
||
|
||
## The manual — how to play (private test)
|
||
|
||
Click **START** to lock the mouse. Then:
|
||
|
||
| input | does |
|
||
|---|---|
|
||
| **W A S D** + mouse | walk / look (first person) |
|
||
| walk into a shop door | enter the interior (open shops only — check the hours tooltip) |
|
||
| **E** (inside a shop) | open the crate at a record bin — then it's cursor-driven: click sleeves to riffle, click BUY |
|
||
| **E** (at the counter) · **C** (anywhere) · **SLEEP** (bottom bar) | sell a find to the keeper (he pays under the **guide band**, never over) · open THE CRATE — your collection, in shops too now · sleep = save, the day advances, stock rotates |
|
||
| read the **guide** stamp on every price card | the 90s price-guide band ("guide $8–24"). An item **asking under its band is a gem** — buy it, sell it to a keeper, pocket the margin. Bought slots stay gone for the day (the bin remembers) |
|
||
| **☆ WANT IT** on a pull card | start hunting it — keepers gossip ("saw one in Castlemaine"), and buying one clears the hunt. **Switching towns costs a day** — the 23 towns are a map now, not a dropdown |
|
||
| **⚖ LIST** in the crate | consign a find to **GodBay** — the auction hammers overnight (sleep or ride somewhere). One hammer per item, ever: keeper cash now, or the gavel tomorrow |
|
||
| wake up (sleep or arrive) | **the morning paper** rides the wake/arrival toast: "⚖ SOLD 'Milk Bar Dreams' — hammer $8, $7 after fees" (or "PASSED IN — it comes home"). The news is a toast, never saved — the ledger is your cash and crate |
|
||
| click a book spine / toy box | pull-and-buy card (real price stickers in godverse shops) |
|
||
| walk out the door / **Esc** | leave the shop (Esc also frees the mouse anywhere) |
|
||
| **F2** | **credits & licences** — what PROCITY is built from and what each source asks for in return (R41). On a real-map boot the HUD link itself carries the obligation: `© OpenStreetMap contributors · credits (F2)` |
|
||
| **M** | 2D town map (street only) |
|
||
| **[** / **]** | step time of day back / forward · **T** pauses the clock |
|
||
| **P** | capture screenshots (street) |
|
||
| HUD dropdown (top-left) | switch towns — synthetic, fixtures, 23 real AU towns, godverse |
|
||
|
||
Worth trying: `?classic=1` (the original v2 town, byte-identical forever) · `?noassets=1`
|
||
(zero-network boot) · `?stock=real` in a godverse town (Monster Robot Party's actual crate) ·
|
||
`?seed=<n>` (any number = a different town). Night is when the gigs happen — step time with `]`.
|
||
|
||
## Read first
|
||
|
||
- **`docs/CITY_SPEC.md`** — the treaty: schema, units, seeds, budgets, file ownership.
|
||
- **`docs/V7_THE_GAME.md`** — the CURRENT epoch (ratified): persistence, the collection, the
|
||
gem thrill. `docs/V6_LIVING_STREET.md` runs in parallel (mocap NPCs, footpaths, cars).
|
||
- **`docs/THE_FRONTIER.md`** — the honest map of what is not figured out yet.
|
||
- **`docs/RESEARCH.md`** — what the parent repos already solved, with exact paths to port from.
|
||
|
||
## The lanes (parallel Opus 4.8 sessions)
|
||
|
||
Each lane is a self-contained prompt. To run one, start an Opus session in this repo and say:
|
||
**"Read docs/LANES/LANE_X_….md and execute it."** A–E are parallel-safe (disjoint files,
|
||
standalone test pages); F integrates after they land.
|
||
|
||
| lane | mission | owns |
|
||
|---|---|---|
|
||
| [A — CITYGEN](docs/LANES/LANE_A_CITYGEN.md) | seed → CityPlan data (streets, blocks, lots, shops) + 2D map | `js/citygen`, `js/core/registry.js`, `map.html` |
|
||
| [B — STREETSCAPE](docs/LANES/LANE_B_STREETSCAPE.md) | chunk-streamed instanced 3D town + game shell | `index.html`, `js/world` |
|
||
| [C — INTERIORS](docs/LANES/LANE_C_INTERIORS.md) | every door opens: seeded themed shop interiors | `js/interiors`, `interior_test.html` |
|
||
| [D — CITIZENS](docs/LANES/LANE_D_CITIZENS.md) | rigged-near / impostor-far NPCs + shopkeepers | `js/citizens`, `citizens_test.html`, `models/` |
|
||
| [E — ASSETS](docs/LANES/LANE_E_ASSETS.md) | audit ultra's library, normalize GLBs, skins, manifest | `pipeline/`, `assets/` |
|
||
| [F — INTEGRATION](docs/LANES/LANE_F_INTEGRATION.md) | wire A–E into one seed-to-town game + QA gates | (after A–E) |
|
||
|
||
## Already in the repo
|
||
|
||
- `web/vendor/` — three.js r175 + addons (vendored from 90sDJsim; no CDN at runtime).
|
||
- `web/assets/gen/` — 69 generated texture skins (25 shopfront facades, 10 skies, 10 grounds,
|
||
8 wallpapers, 16 interior surfaces) inherited from thriftgod + 90sDJsim, style-locked.
|
||
- `web/js/core/` — frozen shared modules: `prng.js` (seeded-everything law), `loaders.js`
|
||
(fail-soft promise-cached GLB/texture + 3GOD depot), `canvas.js` (text planes).
|
||
|
||
## House laws (short form — CITY_SPEC has the fine print)
|
||
|
||
Seeded everything, `Math.random` banned in gen code · the game must run with zero assets ·
|
||
instancing from day one · canvas text, no font files · characters = shared base rigs + one
|
||
clip bank, canonical sources live outside this repo · 🟢 web-ok licensing only.
|
||
|
||
## v3.1 — THE FLIP: the town shows its best by default
|
||
|
||
The Friday-night layer soaked through alpha, beta, and the v3.0 release — so **v3.1 flips it on by
|
||
default**, and the mature v2 flags flip with it. Boot the plain URL and each town seeds **2–4 venues**
|
||
(pub, band room, RSL) with a **full seeded week of gigs**, town-wide **posters**, and a Friday night that
|
||
reads: a **4-piece band** (trio + a **seated drummer**) with real instruments, a mixed **crowd**, an
|
||
outdoor **queue**, a per-venue **cover charge**, muffled **gig spill** + **walla and applause**,
|
||
town-wide **streetlamp pools**, and **identity continuity** — the ped you followed in is in the crowd.
|
||
Plus **weather**, the **tram**, and the parallax interior-**window shader**, all live by default.
|
||
|
||
**The covenant moved, it didn't disappear.** `?classic=1` boots the **exact v2 town** — byte-identical
|
||
forever (synthetic golden `0x3fa36874`, zero gig layer, zero fetch delta). That is the new frozen
|
||
regression target; the default boot is deterministic to the gig golden `0xb1d48ea1`. Asset-free
|
||
(`?noassets=1`) composes with the default boot and stays silent-and-fine.
|
||
|
||
**Flags** — the four headliners are **ON by default**, each with a `=0` opt-out; `?classic=1` is the
|
||
master off:
|
||
|
||
| flag | default | what |
|
||
|---|---|---|
|
||
| `?classic=1` | off | **the exact v2 boot** — all four below off, byte-identical to the frozen baseline |
|
||
| `?gigs=0` | **on** | the gig district — venues, week schedule, band/crowd/queue, cover, posters, night pass |
|
||
| `?weather=0` · `?tram=0` · `?winmap=0` | **on** | seeded weather · the tram loop · the parallax interior-window shader |
|
||
| `?roster=v1` · `?pop=N` | stream | chunk-streamed citizen density is the baseline; `?roster=v1` restores the fixed roster. **`?pop=0` means zero as of R42** — the shell read `parseInt(…) \|\| 140` and `0` is falsy, so for 35 rounds every "town frozen" measurement in this project booted 140 citizens. For a genuinely still frame use `?dbg=1` + **`DBG.freeze()`**, which also covers the streamed roster (it ignores `target` entirely) and returns `stillLive` naming every other wall-clock mover in the scene |
|
||
| `?dig=0` · `?stock=real` | dig on | crate-riffle on record bins · real GODVERSE sleeves in the stock — and, since R41, the **op-shop wardrobe**: 52 named 1990s Australian garment layers on the clothes rails and shelves, one 246 KB atlas, one material, and it costs *fewer* draws and 11 fewer textures than the procedural canvas it replaces. Opt-in: a default boot still builds the canvas, byte-identically |
|
||
| `?clips=0` | **library on** | turns the R41 **motion library** off and nothing else — 46 Mixamo clips in 6 grouped GLBs (2 fetched at boot, 3 on first demand, 1 never). With it off the crowd is 99.3% walking on one clip; with it on, 78.1% walking, 9.5% sitting on a real bench, 7.1% leaning on a shopfront, 20 distinct clips in play. `?classic=1` is a bad control for this (it also changes the ped pool, the fog and half the shell) which is exactly why this flag exists |
|
||
| `?verge=0` | **off** | reverts the ground to the **pre-kerb-ruling** geometry (bitumen painted to the full corridor). John's v8 ruling made the band between kerb and shopfront **footpath** — 9 m on the synthetic town's 28 m main, **7 m** on a real 24 m main, and **3 m** on the `side`@12 edge that is 72% of the corpus. The flag stays forever as the gate's falsifiability control: the poster-clearance leg is asserted to FAIL under it, at exactly 14 posters standing on road paint. `?classic=1` forces the ruling off — the covenanted town keeps its paint |
|
||
| `?r=N` · `?shadows=0\|1` | auto | streaming radius and the sun-shadow pass. **Auto is load-bearing**: a big town (>120 shops or >200 street edges) gets radius 2 with shadows off. A `?r=` **above** auto is a DIAGNOSTIC boot and declares its own law (R40): `?r=3` measures **382 noon / 391 night** draws at 45–48 live chunks — structural, not fat — so it boots under a pinned **≤420** ceiling (`PROCITY.budget`, console-warned, gated by `tools/qa/r40_lane_b.py`), tri law unchanged. Not a supported boot |
|
||
| `?live=1` · `?live=<url>` | **off** | **tier 2** — live stock from the GODVERSE server (sold-in-the-real-shop means gone in the game). Opt-in by design: absent ⇒ byte-identical to tier 1, and the game never asks a question it has no reason to expect an answer to |
|
||
| `?noassets=1` · `?plansrc=osm` · `?mute=1` · `?dbg=1` | off | asset-free (zero network) · OSM plan source · silence · the `window.DBG` capture/soak harness |
|
||
| `?plansrc=osm&town=<key>` | — | boot a **real Australian town**: fixtures `melbourne`/`katoomba`/`silverton`, or a real OSM cache `bendigo_real`/`castlemaine_real`/`fremantle_real`/`katoomba_real`/`newtown_real` (ODbL, `web/assets/towns/SOURCES.md`). **REAL ROADS:** a cache with `roads[]` (schema v2) builds the CityPlan street graph from the town's **actual OSM streets**; without `roads[]` a cache marches onto synthetic avenues. Or just **pick a town from the HUD selector** — no URL needed |
|
||
|
||
## v4.0 — THE REAL MAP: the towns *are* the product
|
||
|
||
**23 real Australian towns — 1,210 real shops, every state and territory — on their actual streets.** Not
|
||
"inspired by": Fitzroy's shops sit on Fitzroy's roads, at their real positions, because the pipeline eats
|
||
OpenStreetMap and marches it through the same CityPlan contract the procedural town uses. **Pick one from
|
||
the in-HUD selector and walk it.** Everything built across v1–v3 comes along unchanged — the venues and their
|
||
seeded week of gigs, the 4-piece band with the seated drummer, the crowd that follows you into the pub, the
|
||
interiors behind every door, weather, the tram — because they all hang off the plan contract and never had
|
||
to know the geography got real.
|
||
|
||
The towns run from **meccas** (Fitzroy, 160 shops) to the **thin tail** (12), at real retail density: the
|
||
secondhand heroes keep their footfall while the street around them gets ~4× busier — texture, never a
|
||
takeover. Venues bias to the retail heart. The tram only runs where it fronts a real high street (elsewhere
|
||
it was honestly "a highway bus", so it's fenced). Everything stays **deterministic from the seed**, silent
|
||
under `?noassets=1`, and **`?classic=1` still boots the exact v2 town, byte-identical forever** (`0x3fa36874`).
|
||
|
||
**The tour:** [`docs/shots/release_v4/contact.html`](docs/shots/release_v4/) — the Fremantle hero, the
|
||
Fitzroy mecca, the thin tail (labelled honestly: the floor is shops-per-street-metre, and Toowoomba is
|
||
below it), the synthetic control, and the `?classic=1` covenant made visible. Charter:
|
||
[`docs/V4_REAL_MAP.md`](docs/V4_REAL_MAP.md) · data + licences (ODbL):
|
||
[`web/assets/towns/SOURCES.md`](web/assets/towns/SOURCES.md).
|
||
|
||
## v5.0-alpha — THE FIRST REAL CRATE: the shops get real too
|
||
|
||
**v4 made the towns real. v5 makes the shops real** — and the first one is standing.
|
||
|
||
Boot `?plansrc=osm&town=redhill_godverse&stock=real`, walk down **Musgrave Road** into **Monster Robot
|
||
Party** (147 Musgrave Rd, Red Hill, Brisbane — a real record shop), and riffle its crate. The records in
|
||
it are **that shop's real stock**: 120 real records off its real point-of-sale, real covers, real titles,
|
||
real prices. Buy one and the wallet debits what the sticker says. It's gone for the session and back next
|
||
boot — because until the live tier lands, the crate is a **file**, not a shop's ledger.
|
||
|
||
**Stock is a data tier now**, exactly like assets — each rung fully playable, each degrading softly to
|
||
the one below, so the game never depends on a server to be a game:
|
||
|
||
| tier | what | deterministic? |
|
||
|---|---|---|
|
||
| **0 · parody** | seeded canvas sleeves (v1) — any boot, always works | yes — the QA baseline |
|
||
| **1 · static real** | per-shop atlases baked from the shop's own POS | yes — atlases are files |
|
||
| **2 · live GODVERSE** | `?live=1` — live stock off the real till: **sell a record in the shop and it's gone from the game crate** | **no — by design** |
|
||
|
||
**The offline law:** the server enriches, never gates. `?noassets=1` still fetches **zero bytes** and plays
|
||
silent-and-fine; a shop whose atlas is missing falls soft to parody rather than borrowing someone else's
|
||
crate; and **`?classic=1` still boots the exact v2 town, byte-identical forever** (`0x3fa36874`). The
|
||
world stays seeded and golden-gated — only the *stock inside it* is data.
|
||
|
||
**Provenance:** item photos are each shop's own product shots, 🟢 in-house — **flagged before any public
|
||
or commercial release**, and every atlas carries that flag where the QA gate must print it. Real titles
|
||
and artists are an in-house amendment to the no-real-trademarks law, on the same footing. **Nothing an
|
||
in-game purchase does touches real inventory** — v5.0 ships sell-sandboxed by ruling; a real reservation
|
||
tier is chartered for v5.x, not assumed. Charter: [`docs/V5_REAL_SHOP.md`](docs/V5_REAL_SHOP.md) ·
|
||
economy design: [`docs/G3_ECONOMY_DESIGN.md`](docs/G3_ECONOMY_DESIGN.md).
|
||
| `?seed=N` | `20261990` | town seed |
|
||
|
||
**Release tour:** [`docs/shots/release_v3_1/contact.html`](docs/shots/release_v3_1/) — the money shots on
|
||
the default boot, plus a `?classic=1` before/after. **QA:** `tools/qa.sh --strict` (classic regression +
|
||
default-boot gate + smokes + no-giants) `--soak` (the full-week soak) `--matrix` (the town matrix)
|
||
`--tour` (R42's paired before/after proof shots); the seated drummer passes the no-giants gate at the
|
||
seated stature band `[0.9,1.5] m`.
|
||
|
||
**Two laws about the cast, as of R42** (`tools/qa/r42_roster.mjs`, both controls demonstrated every
|
||
run): **PROCITY is 1990s Australia** — no fantasy, superhero, luchador, anime or medieval body ships,
|
||
gated by name against `PED_NAMES` rather than a directory listing; and **every shipped ped carries a
|
||
real `credits.json` row** — an `unverified` licence on a body is a red gate, not a note. The R42 audit
|
||
retired five bodies on those two laws, including one nobody had looked at since R36. Screenshot
|
||
byte-hashes are pinnable again (R41's ban is reversed): the condition is *nothing in frame runs on
|
||
wall-clock time*, asserted via `DBG.freeze().stillLive` — see `docs/shots/laneF_r42/README.md`.
|
||
|
||
## v7.0 — THE GAME: you're a crate-digger in 90s Australia
|
||
|
||
v4 made the towns real, v5 made the shops real — **v7 makes it a game.** Boot the plain URL on a
|
||
fresh browser and you arrive HUNTING: the splash names a seeded first want and your pocket money
|
||
("You're hunting HILLS HOIST — $191 in your pocket"), three toast-beats walk you through the first
|
||
dig, and from there the loop is live:
|
||
|
||
**dig** (E at a record bin — the crate riffle) → **read the guide** (every price card carries a 90s
|
||
price-guide band; an item asking *under* its band is a gem, and spotting one is the whole skill) →
|
||
**☆ WANT** what you're hunting (keepers gossip seeded rumors — "saw one in Castlemaine") →
|
||
**travel** (switching towns costs a day; the 23 towns are a strategy map) → sell to the **keeper**
|
||
(instant cash, always under guide — the no-pump law) or **⚖ LIST on GodBay** (a seeded offline
|
||
auction that hammers overnight; one hammer per item, ever — no retry farm) → **SLEEP** (= save; the
|
||
day advances, parody/mint stock rotates per (shop, day), bought slots come back) → wake to **the
|
||
morning paper** ("⚖ SOLD — hammer $22, $19 after fees"). Repeat, richer and one gem wiser.
|
||
|
||
The machinery under it: a versioned localStorage save carrying THE DELTA ONLY (cash · collection ·
|
||
day · town · wants · pulls · listings — the world always regenerates from seed, so a corrupt save
|
||
can cost you your stuff, never the town), JSON export/import for moving machines, and an economy
|
||
fenced by gates: sell < guide-band structurally, auction EV ≈ 0.8×mid (random flips bleed; only
|
||
finds profit), save/load byte-determinism, rotation seeded by (citySeed, shop, day).
|
||
|
||
**`?classic=1` still boots the pure v2 town — zero save, zero game DOM, zero Storage calls,
|
||
instrumented every run** — and `?game=0` opts out of the layer on any boot. Charter:
|
||
[`docs/V7_THE_GAME.md`](docs/V7_THE_GAME.md) (ratified 2026-07-17, risk verdicts appended at the
|
||
close) · economy: [`docs/G3_ECONOMY_DESIGN.md`](docs/G3_ECONOMY_DESIGN.md) · the tour (day one to
|
||
first gem, 6 frames, no staging): [`docs/shots/v7_tour/`](docs/shots/v7_tour/).
|