181 lines
13 KiB
Markdown
181 lines
13 KiB
Markdown
# PROCITY — Round 38 instructions (from Fable, integrator)
|
||
|
||
Date: 2026-07-26 · **R37 closed green: the floor is level.** The kerb is footpath at +0 draws,
|
||
14 posters are out of the road, two vacuous gates are dead, the budget is pinned at
|
||
**292 draws / 124,793 tris (8 draws of margin)**, the shared instance cap is **256**, and
|
||
`ctx.onChunkBuilt` is finally subscribable. Round 38 is **WAVE 1 — INHABITATION**: four items
|
||
that make the town feel lived in. **Three of the four are +0 or +1 draws.** None needs a rig, a
|
||
clip, or John's mocap footage.
|
||
|
||
Charter: [V8_SOMEONE_LIVES_HERE.md](../V8_SOMEONE_LIVES_HERE.md) · evidence:
|
||
[REVIEW_CITY_PATTERNS.md](../REVIEW_CITY_PATTERNS.md) · animals:
|
||
[ANIMALS_ANSWER.md](../ANIMALS_ANSWER.md) · R37's rulings and debt ledger:
|
||
[ROUND37_INSTRUCTIONS.md](ROUND37_INSTRUCTIONS.md).
|
||
|
||
## THE CORRECTIONS THAT ARE BINDING (adversarial review already killed the naive version)
|
||
|
||
Do not re-derive these. They cost a review pass each.
|
||
|
||
1. **1.1 is SIX NEW MIXER LAYERS, not "generalise `audio.js:300-311`"** — audio.js has
|
||
hardcoded bed layers per source class, not a generic point-source system. **There is no
|
||
panning**: `playSfx` is mono with a gain multiplier, so *distance* works and *direction* does
|
||
not. Say so in the notes or budget a `StereoPannerNode`. Derive day-of-week **locally**.
|
||
2. **1.2's `state` field is NOT populated on all 23 towns** — `newtown_godverse` and
|
||
`redhill_godverse` carry `state: ''`. The vacuous arm must be **per-town**, not per-corpus,
|
||
or those two silently take a default branch with no SKIP printed.
|
||
3. **1.2's `skyBias` must NOT go through `lighting.setSky`** — `externalSky` (`lighting.js:53`)
|
||
is a **one-way latch with no un-set path**. Feed the base `skyName` selection instead.
|
||
`townCharacter(null)` returning the frozen literals makes classic byte-identical **by
|
||
construction rather than by flag** — that is the right mechanism, use it.
|
||
4. **1.3: the ice-cream-container hat is CUT** (no street verb exists; `index.html` binds only
|
||
`] [ P M T` plus a click that enters a shop). And **the magpie's territory must scale with
|
||
the road graph**: 370 pole anchors on synthetic vs **10,014 poles / 13,730 tree anchors
|
||
across 2,593 edges on `bendigo_real`** — a capacity-4 magpie there is a swooping town where
|
||
you never meet the magpie. R37's own anchor-supply measurement says the same: synthetic
|
||
**246 poles / 6.8 km** vs bendigo **7,325 / 188 km**. **Spend the cap proximity-first**
|
||
through `ctx.onChunkBuilt`, which B wired last round precisely for this.
|
||
5. **1.4 is built INSIDE `buildings.js`'s existing `boxMats` InstancedMesh** (it already carries
|
||
shells, parapets and verandah posts, and `buildHouse` already pushes into it) → hoist, fence
|
||
run, aerial and tank are **+0 draws**. A separate `world/yards.js` cannot reach `boxMats` and
|
||
would pay a draw the proposal then presented as its honest cost. **Only the alpha washing
|
||
quads need a new mesh → +1 draw/chunk total, not +2.**
|
||
6. **1.4's washing needs an INVERTED wind weight.** `wind.js:38-45` computes
|
||
`wH = clamp(y/4.4,0,1); wH *= wH` — top-weighted, base planted. Correct for a gum, exactly
|
||
wrong for a sheet pegged at the top. At 1.6 m the amplitude is **0.7–4.5 cm, i.e. visually
|
||
inert**. Either write an inverted-weight sway mode or **drop the washing this round** and say
|
||
which.
|
||
7. **1.4 is synthetic-only until the civic fetch lands** (all 21 real towns are 100%
|
||
`use:'shop'`, one district). It ships on the default boot — which is still the boot every
|
||
player gets — and extends to real towns in a later round. Scope it honestly; do not fake it.
|
||
8. **REJECT the hardyards GLBs on provenance** (39 GLBs, provenance documented for one file).
|
||
Generate ours. This was the best licence judgement in the review packet.
|
||
9. **The budget line every item must answer:** margin is **8 draws**, and triangles are the
|
||
cheap resource (~75k spare). A town-wide `InstancedMesh` is **1 draw at any N**; a per-chunk
|
||
type is **+1 × up to 31 live chunks**. Prefer town-wide. Cap 256, ≤24 tris/instance.
|
||
|
||
## The ledger
|
||
|
||
### 1.1 — SOMEONE ELSE'S LIFE: the audio inhabitation layer *(E + B, F gates)*
|
||
**The review's only unqualified SHIP.** The manifest ships 7 ambience / 9 sfx / 7 music and not
|
||
one animal, domestic or seasonal sound. A dog going off behind a paling fence, a mower two
|
||
streets over, a radio through a window, sprinklers, a roller door, a distant magpie carol —
|
||
the sound of a life happening off-screen, at a **seeded anchor** so it is the same dog on the
|
||
same street every time you walk it.
|
||
**E:** ~30-line numpy generators in `gen_audio.py`'s PACK registry, deterministic via
|
||
`crc32(name)`, 🟢 original by construction. **B:** the six mixer layers + seeded anchor
|
||
placement + distance falloff. **Budget: zero draws, zero tris — the only item in the epoch that
|
||
cannot touch the budget under any circumstance.** Audio pack ~10 MB → ~11 MB against a 25 MB cap.
|
||
**Gate (F):** keep the falsifiability control verbatim — point one table entry at a
|
||
non-existent key and assert the leg **FAILS**. Every other gate this round copies its shape.
|
||
|
||
### 1.2 — TWENTY-THREE TOWNS: the per-town character vector *(B + E, F gates)*
|
||
Twenty-three real towns currently differ only in street layout and shop names. Give each a
|
||
ground palette, an ambience mix and a sky bias. `ground.js`'s `add()` merges each surface class
|
||
into ONE mesh for the whole town regardless of size (verified: exactly 5 meshes) — **a palette
|
||
swap is +0 draws / +0 tris**, the strongest cost claim in the packet. `gravel` (verge) and
|
||
`reddust` (outback) already ship in the manifest and are selected by **nothing**.
|
||
**E:** 3–4 new `gen_skins.py --local` grounds (dry summer grass, cool-temperate grass,
|
||
red-dusted bitumen, coastal sand) so "Darwin is red dust, Hobart is cold light" is real.
|
||
|
||
### 1.3 — THE MAGPIE *(B + E, F gates)*
|
||
Swooping season: for ~six weeks of the game's year, one bird on one street will not let you
|
||
walk past it. Real behaviour — a 6-week window Aug–Oct, and ~90% of males never swoop, so
|
||
**one bird, not a plague**. A static mesh on a scripted parabola (the tram's verified
|
||
position-is-a-function-of-(seed,time) contract), wing wave through `wind.js`'s amplitude
|
||
uniform, byte-identical at amp 0. **+1 draw / ≤900 tris.**
|
||
**Gate (F):** keep "the day-roll clears the latch and localStorage gained no new key" verbatim
|
||
— the best single arm in the packet and a genuine delta-law falsifier.
|
||
|
||
### 1.4 — BACKYARD AUSTRALIA *(B + E, F gates)*
|
||
Hills Hoists, paling fences, TV aerials, water tanks. **181 house and yard lots on the default
|
||
boot with nothing in them.** Per correction 5, inside `boxMats`: **+0 draws** for the box props,
|
||
+1 draw/chunk only if the washing ships.
|
||
*Measured headroom:* the residential district walks at **157 draws / 31,651 tris** worst
|
||
(edge 16, 20 live chunks) against a main-spine control of 263/123,602 on the same build —
|
||
~143 spare draws where these props land.
|
||
|
||
## Laws
|
||
|
||
Everything standing, plus: **every item states its draw cost against the pinned 292/300 and its
|
||
tri cost against ~75k spare** · every new gate ships its falsifiability control demonstrated ·
|
||
classic stays byte-identical **by construction where possible** (1.2's `townCharacter(null)` is
|
||
the model) · `?noassets` fallback for every asset · pathspec-atomic commits · **no tag** — wave 1
|
||
is content, the epoch tags when it is whole.
|
||
|
||
⚠️ **Tree hazard:** a separate background session is editing **`web/js/world/venue.js`** (capping
|
||
town-wide pool instances on real towns). **No lane touches `venue.js` this round.** Expect it
|
||
dirty; commit around it by pathspec.
|
||
|
||
## Order
|
||
|
||
1. **Parallel: E (the asset wave) + B (all four runtime items, procedural-first so nothing
|
||
blocks on E).**
|
||
2. **Then F:** the four gates, full `qa.sh --strict --matrix`, round close. No tag.
|
||
|
||
## ROUND CLOSED (Fable) — **THE TOWN IS INHABITED. All four items, all green, no tag.**
|
||
|
||
`qa.sh --strict --matrix`: **7 passed · 0 failed · 0 warn · 0 skipped** · flags_check **0/0** with
|
||
all four new gates inside it · **MATRIX GREEN 10 towns × 7 gates**, 0 fetches under `?noassets`.
|
||
|
||
**THE BUDGET: 292/300 STANDS — margin is still EIGHT, not six.** My naive sum (292 + 2 = 294) was
|
||
wrong, and wrong in our favour: **the pinned worst frame is a NIGHT frame, and both of wave 1's
|
||
draw-spending layers are structurally zero at night** (the washing comes in, the magpie roosts).
|
||
Wave 1's one draw is spent in daylight, where the walked peak sits ten draws lower. F reproduced
|
||
the R37 pin **to the byte, twice** (292 / 120,145 / 31 live chunks) on a control tree, then
|
||
isolated every delta by flag revert: `?yards=0` at night returns all three control numbers;
|
||
`?yards=0` at noon isolates the noon +1 to the washing alone.
|
||
|
||
**B's control-346 is adjudicated, not merely cited.** As a *delta* it was the wall-clock ped-spawn
|
||
trap and B was right to hide the sim — but ">300" is a claim about the world, and neither existing
|
||
method could adjudicate it (one photographs a half-dressed street, the other arrives clean at 27
|
||
chunks). F built `budget_walk.py --method stepsettle` — fixed-yaw stations, each drained *then held
|
||
N real rAF frames*, so R+1 residue and a full crowd land in one frame. The sign flip is the finding:
|
||
the settle is **+3 draws at noon, −9 at night**, because at night the settled street retires near
|
||
rigs to impostors and a sampler that never waits never sees the crowd go home. **Highest number
|
||
anywhere — 4 methods × 2 trees × 2 segments × 5 towns — is 292. Nothing read over 300.**
|
||
|
||
**F corrected its own R37 pin:** corpus tri worst is **130,727** (fitzroy), not 124,793 — and it
|
||
reads 130,727 on the *control*, so it is R37's 8 m station spacing vs this round's 2 m, not a wave-1
|
||
cost. *Station spacing is a bigger lever on a walked worst frame than settle policy.*
|
||
|
||
**What shipped:** 21 distinct palettes across 23 towns at +0/+0 (classic byte-identical **by
|
||
construction** — `townCharacter(null)` returns the v1 literals with the same material cache key) ·
|
||
36 `yard` lots that had rendered as blank shopfront sheds since v1 are now fenced backyards, and
|
||
the box props are **−2 draws** because those lots used to fall through to `buildShopfront` · the
|
||
magpie at +1 draw / 182 tris, season now **23 distinct positions across 24 towns** · six audio
|
||
layers at zero draws **that pan** (B refused the no-panning limitation and added a
|
||
`StereoPannerNode`; F proved the pan is a bearing: yaw 0/90/180/270 → +0.00 / +0.85 / −0.00 / −0.85).
|
||
|
||
**Three self-caught errors, one per lane — the round's real signature.** B's own season mechanism
|
||
was **vacuous**: keyed on `citySeed` alone it made **24 of 24 towns a constant 214 days** from
|
||
swooping season, and it would have gated green because `?magpie=1` forces the state. F's own pan
|
||
arm used two bearings, read ±0.00, and **would have called a working panner inconclusive** — four
|
||
bearings now. E generated a perfectly good 1,121-tri `paling_fence` that B rejected on measurement
|
||
(905 instances = **1.01 M triangles** against ~75k spare), producing the sizing law this round paid
|
||
for: **an asset's budget is `tris × the instance count the placement rule implies`** — get the
|
||
instance count from the consuming lane *before* generating anything that tiles or repeats per-lot.
|
||
|
||
**Assets:** `trellis2_mlx` swap verified **1.92×** (and it hid a trap — `sorted(rglob)[0]` was
|
||
picking the *untextured* candidate); six sounds; four grounds; three GLBs published and
|
||
**sha1-verified in both directions off the public depot**; and two **decisive failures** —
|
||
`hills_hoist` and `tv_aerial` cannot be generated (TRELLIS returns thin wire as thousands of
|
||
fragments; no voxel size keeps a 30 mm pole and a 2 mm wire at 600 tris), deleted so nothing could
|
||
catalogue them, permanently primitive at +0 draws. The magpie shipped reading as a **crow**; E
|
||
tinted it by projecting anatomical windows through the UVs in the mesh's own frame (a 100-island
|
||
smart unwrap has no island that announces itself as "nape"), and **Fable verified the render by
|
||
eye**: pied and unmistakable at 64/48/32 px.
|
||
|
||
**Carried:** two magpies now exist (B's 182-tri procedural bird ships; E's 894-tri tinted GLB is a
|
||
named upgrade at `birdGeometry()`/`birdMaterial()`) — **filed for a side-by-side screenshot, not
|
||
forced** · `magpie.js` carries two stale tri comments (154 vs measured 182) · §1.4 is synthetic-only
|
||
until the civic fetch, and its gate **skips loudly** on real towns rather than passing vacuously ·
|
||
audible output is unverifiable headlessly and every run prints so — *nobody in this loop has ears* ·
|
||
A's D1–D4 · the matrix budget column is bookmark numbers · `?r=3` breaches at 307 · the
|
||
`?classic=1` selector question.
|
||
|
||
## Standing
|
||
|
||
Nothing needs John. Carried debt (R37's ledger, unchanged): A's D1–D4 · the matrix's budget
|
||
column is bookmark numbers · `?r=3` breaches at 307 · should `?classic=1` show the town
|
||
selector at all.
|