diff --git a/docs/LANES/LANE_B_NOTES.md b/docs/LANES/LANE_B_NOTES.md index 397106a..d657c08 100644 --- a/docs/LANES/LANE_B_NOTES.md +++ b/docs/LANES/LANE_B_NOTES.md @@ -77,10 +77,20 @@ Measured live, both towns, fresh boot then a 900 m walk through the real rAF loo | | synthetic | katoomba_real | |---|---|---| -| fresh boot | 0/493 shops · 1/22 segs · frame **240 m** · lot **20.97×41.16 px** | 0/72 shops · 0/993 segs · frame **240 m** · lot **29.4×39.2 px** | +| fresh boot | 4/493 shops · 1/22 segs · frame **240 m** · lot **20.97×41.16 px** | 4/72 shops · 1/993 segs · frame **240 m** · lot **29.4×39.2 px** | | after 900 m | 113/493 shops · 7 segs · frame 515 m · **9.77×19.18 px** | 34/72 shops · 18 segs · frame 965 m · **7.31×9.75 px** | | the shipped map | — · frame 965 m · 5.22×10.24 px | — · frame **4,984 m** · **1.42×1.89 px** | +*(Fresh boot reads 4 shops rather than 0 because the `+sin` fix below landed: you now start standing in +front of four shopfronts instead of behind them. **On katoomba that fresh-boot map draws 3,478 pixels +of shop colour — against HEAD's ZERO for the entire town.** Four shops you can read beat seventy-two +you cannot see.)* + +**One harness assertion of mine is wrong and F should not inherit it:** `r39_verify.py`'s fog arm +asserts *more shop-colour pixels after the walk*, which only holds at a fixed zoom — after 900 m on +katoomba the frame has grown to 965 m, so 34 shops draw 1,902 px where 4 drew 3,478. The honest +assertion is the **shop count** (4 → 34, already checked separately), or px-per-known-shop. + **The frame is the shops you have stood in front of, plus where you are standing — NOT the streets you have walked**, and that was a real correction to my own first cut. An edge is drawn as the whole node-to-node line, and the synthetic's main street is one ~400 m edge, so stepping onto it at spawn @@ -115,7 +125,25 @@ synthetic, 40.3% katoomba, 43.4% bowral, 43.5% fitzroy** — and on a shopper's refuses **0–2**, which is exactly the shape you want: free where a shopper stands, decisive behind the buildings. -### THE SIGN WAS WRONG AND IT IS THE SHELL'S, NOT MINE — a finding, held, not fixed +### THE SIGN WAS WRONG — the FOURTH instance of the −Z/+Z confusion *(Fable ruled: landed, `1b7fa5f`)* + +**The lineage, because the next lane to touch a heading should find it.** Every time, the rule is the +same: **the rig/pose convention is local −Z, the visible front is local +Z**, and every time it +survived because *the thing checking it shared a convention with the thing that was wrong.* + +| round | where | what it did | how it was caught | +|---|---|---|---| +| **R13** | Lane C's pose `ry` vs Lane D's rig | the band played 180° off; settled with `RY_FLIP = π` (`ROUND13_INSTRUCTIONS:26-28`) | another lane's mesh looked wrong | +| **R15** | `buildPosters` item 1, `lot + (−sin, −cos)·d/2` | the venue's own frontage poster on the **back wall** — measured **15.9 m from the street facade, 0.07 m from the back** | a screenshot of the pub | +| **R27** | real-town shopfronts | **dot = −1.000 exactly** on 35/35 redhill and 72/72 katoomba lots — every real shop had faced the paddock since v1. `CITY_SPEC:71` says the facade is −Z, `CITY_SPEC:335` says +Z; the two generators each implemented one half (`ROUND27_INSTRUCTIONS:169` already named it *"the same −Z/+Z species as R13's RY_FLIP and R15's posters"*) | standing on Musgrave Road and looking | +| **R39** | `index.html:428` patronage door points · `:500` the R32 spawn | Lane D's peds ducked into the back fence and **every non-classic boot since R32 opened behind the shop row** | the fog: my probe copied the shell's sign and read 4 shops known / 1,231 in-radius rejections | + +Four instances, four rounds apart, and each one was found by a *picture* or by a consumer with a +different convention — never by a metric. That is the entry worth keeping: **a heading has no +falsifiable arm inside the file that computes it.** If you write one, check it against +`buildings.js`'s `toWorld` and take the screenshot. + +### The R39 instance, measured My first cut copied `index.html`'s own front-normal and the walk read **4 shops known and 1,231 in-radius rejections** on the synthetic — the fog hiding the town from a player standing in front of it. The geometry says the shell is wrong: @@ -123,25 +151,50 @@ The geometry says the shell is wrong: - `buildings.js:410-416, :583-597` build the facade, the door and the `doorRect` at local **+Z** — `lot + (sin ry, cos ry)·d/2`. `minimap.js`'s front-edge tick has always been drawn at local +Z. `dbg.js:53` says it in words: *"Front normal = local +Z rotated by lot.ry"*, `fx = Math.sin(ry)`. -- `index.html:384` (Lane D's patronage door points) and `index.html:450` (`doorOf`, the R32 cluster-pose - spawn) use **`(−sin ry, −cos ry)`** — the back of the building. +- `index.html:428` (Lane D's patronage door points, since R8) and `index.html:500` (`doorOf`, the R32 + cluster-pose spawn) used **`(−sin ry, −cos ry)`** — the back of the building. **Both now `+sin/+cos`.** - Measured against each lot's **own `frontEdge`**: the +sin point is **0.00 m** from the kerb on the synthetic and −1.50 m on katoomba (i.e. on the kerb line, where a facade belongs); the −sin point is **15.25 m / 12.50 m** the wrong side of it. **493 of 493 and 72 of 72 shops agree.** -- The consequence, measured at the shipped spawn on four towns: **0 of the 1–3 shops within 25 m are in - front of you.** At the corrected spawn: **all of them are** (synthetic 4/4, katoomba 4/4, bowral 4/4, - fitzroy 1/1). R32's own comment says the spawn stands *"ON the footpath door-line"*; the code stands - in the back lane, and the fresh-boot fog map is the picture of it — one street, its yards, no shops. -- **And in a picture, live, both towns** (`spawn-*-SHIPPED.png` vs `spawn-*-FRONT-NORMAL.png`): the - shipped spawn stands on a footpath facing an empty plaza and a retaining wall with **not one shopfront - in frame**, and the fog reports **0 shops known after 2.5 s of standing there**; recompute the same - pose with `+sin` and the player is **under a shop awning with the sign at their shoulder**, **4 shops - known**. Same on katoomba_real: 0 → 4. -**I did not fix it.** It is a two-character change in my own file, but it moves the default boot's -opening pose for every gate and screenshot in the project, mid-round, with three lanes in the tree and -Lane F gating at the close. The patch is `+Math.sin` / `+Math.cos` at `index.html:384-385` and `:450`. -**Fable's call.** +**THE PATRONAGE DOOR POINT — is it on the footpath?** (in the verge band per `registry.js`'s own +`roadWidth`/`vergeBand` split, outside the carriageway, outside every lot): + +| town | shipped | **fixed** | median distance from the street centreline | +|---|---|---|---| +| synthetic | **0 / 493** | **427 / 493** | 26.22 m → **9.40 m** (carriageway edge 5 m, facade 14 m) | +| katoomba_real | **0 / 72** | **67 / 72** | 19.10 m → **3.90 m** | +| fitzroy_real | **0 / 139** | **139 / 139** | 19.10 m → **3.90 m** | +| bowral_real | **0 / 30** | **28 / 30** | 21.10 m → **5.90 m** | + +Not one door point in the corpus was on a footpath. Lane D's peds have been ducking into the back +fence since R8. (The residue — 31 synthetic / 5 katoomba / 2 bowral — are corner lots whose front +point lands inside a *neighbouring* lot; that class is pre-existing and **14 fewer** than before.) + +**THE SPAWN — booted code on both sides**, `:8702` serving the fog commit, `:8701` the fix, nothing +monkey-patched: + +| | shipped | fixed | +|---|---|---| +| synthetic | (25.5, −17.9) · 3 shops within 25 m, **0 in front**, **0 discovered** | (6.1, −19.8) · 4 within 25 m, **4 in front**, **4 discovered** | +| katoomba_real | (−219.0, −471.3) · 3 within 25 m, **0 in front**, **0 discovered** | (−200.0, −474.4) · 4 within 25 m, **4 in front**, **4 discovered** | + +**And the picture, which is the whole argument** (`docs/shots/laneB_r39/sign-*`): the shipped katoomba +boot opens **standing in a paddock facing the blank back wall of a building** — which is the R31 +playtest's own complaint, *"faced dirt and building-backs"*, the complaint R32 was written to fix and, +because of the sign, never did. The fixed boot opens on the footpath under the awnings with the +shopfronts and their signage running away down Katoomba Street. + +**NO GOLDEN MOVES, plainly: `SPAWN` and the patronage points are RUNTIME POSE, computed in the shell +from a plan it never writes to.** Lane A's selfcheck run either side of the change: +**fingerprint `0x5f76e76` → `0x5f76e76`**, 157,647/157,647 checks. `?classic=1` is untouched by +construction — it never enters the branch and keeps the frozen (−96, 9, looking east) pose forever. + +**→ LANE F, two gates photograph this pose and need re-baselining:** the **R32 cluster-pose spawn** +gate and the **R35 first-five-minutes** smoke. Both are correct to move — the pose they baselined is +the defect. The falsifiable arm to gate on instead, which needs no picture: at the spawn, **the count +of shops within 25 m that are in front of the player must be > 0** (it was 0 on 4 of 4 towns before, +4 of 4 after), and it goes red the moment the sign flips back. ### The save shape, and its bound `known` — OPTIONAL, absent until something is learned, so a save that predates R39 stays valid forever diff --git a/docs/shots/laneB_r39/README.md b/docs/shots/laneB_r39/README.md index 1f7c64a..4f5ae91 100644 --- a/docs/shots/laneB_r39/README.md +++ b/docs/shots/laneB_r39/README.md @@ -13,5 +13,11 @@ both sides. Every number behind these pictures is in `docs/LANES/LANE_B_NOTES.md | `fog-01-before-katoomba_real.png` | **R39, fresh boot** — the 240 m frame, a shop lot at 29.4×39.2 px | | `fog-02-after-katoomba_real.png` | **R39, after 900 m** — 34 shops on **Katoomba Street**, with **Edwards Street** running off it (Lane A's address layer) | | `map-classic.png` | `?classic=1` — the pre-R39 map, hash-identical to HEAD's | -| `spawn-*-SHIPPED.png` | the default boot's spawn pose today: a footpath facing a plaza, **not one shopfront in frame**, 0 shops discovered | -| `spawn-*-FRONT-NORMAL.png` | the same pose recomputed with the front normal `buildings.js`/`dbg.js`/`minimap.js` all use: **under the awning, sign at your shoulder**, 4 shops discovered | +| `sign-*-BEFORE.png` | the default boot's spawn **as shipped since R32**: synthetic — a footpath facing a plaza with not one shopfront in frame; katoomba — **standing in a paddock facing the blank back wall of a building**. 3 shops within 25 m, **0 of them in front of you**, 0 discovered | +| `sign-*-AFTER.png` | the same code with the front normal corrected (`+sin`): **on the footpath under the awnings, signage down the strip**, 4 shops within 25 m, **4 in front**, 4 discovered | + +The `sign-*` pair is **booted code on both sides** — two port-isolated no-store servers, `:8702` +serving the fog commit (old sign) and `:8701` the fix. Nothing is monkey-patched. + +Katoomba's BEFORE is the R31 playtest's own complaint, verbatim — *"faced dirt and building-backs"* — +which R32 was written to fix and, because of the sign, never did. diff --git a/docs/shots/laneB_r39/sign-katoomba-AFTER.png b/docs/shots/laneB_r39/sign-katoomba-AFTER.png new file mode 100644 index 0000000..f1ce657 Binary files /dev/null and b/docs/shots/laneB_r39/sign-katoomba-AFTER.png differ diff --git a/docs/shots/laneB_r39/sign-katoomba-BEFORE.png b/docs/shots/laneB_r39/sign-katoomba-BEFORE.png new file mode 100644 index 0000000..1f16830 Binary files /dev/null and b/docs/shots/laneB_r39/sign-katoomba-BEFORE.png differ diff --git a/docs/shots/laneB_r39/sign-synthetic-AFTER.png b/docs/shots/laneB_r39/sign-synthetic-AFTER.png new file mode 100644 index 0000000..441904a Binary files /dev/null and b/docs/shots/laneB_r39/sign-synthetic-AFTER.png differ diff --git a/docs/shots/laneB_r39/sign-synthetic-BEFORE.png b/docs/shots/laneB_r39/sign-synthetic-BEFORE.png new file mode 100644 index 0000000..393eddd Binary files /dev/null and b/docs/shots/laneB_r39/sign-synthetic-BEFORE.png differ diff --git a/docs/shots/laneB_r39/spawn-katoomba-FRONT-NORMAL.png b/docs/shots/laneB_r39/spawn-katoomba-FRONT-NORMAL.png deleted file mode 100644 index 5e910d1..0000000 Binary files a/docs/shots/laneB_r39/spawn-katoomba-FRONT-NORMAL.png and /dev/null differ diff --git a/docs/shots/laneB_r39/spawn-katoomba-SHIPPED.png b/docs/shots/laneB_r39/spawn-katoomba-SHIPPED.png deleted file mode 100644 index 56862ce..0000000 Binary files a/docs/shots/laneB_r39/spawn-katoomba-SHIPPED.png and /dev/null differ diff --git a/docs/shots/laneB_r39/spawn-synthetic-FRONT-NORMAL.png b/docs/shots/laneB_r39/spawn-synthetic-FRONT-NORMAL.png deleted file mode 100644 index f7d8b01..0000000 Binary files a/docs/shots/laneB_r39/spawn-synthetic-FRONT-NORMAL.png and /dev/null differ diff --git a/docs/shots/laneB_r39/spawn-synthetic-SHIPPED.png b/docs/shots/laneB_r39/spawn-synthetic-SHIPPED.png deleted file mode 100644 index 560f61d..0000000 Binary files a/docs/shots/laneB_r39/spawn-synthetic-SHIPPED.png and /dev/null differ diff --git a/web/index.html b/web/index.html index 33f5d7a..27f6619 100644 --- a/web/index.html +++ b/web/index.html @@ -422,10 +422,16 @@ if (!rosterV1) { } // [Lane F R8 — Lane D patronage] shop door points per chunk (facade normal → the street), fed once to the // sim so streamed peds can duck into open shops they pass. Computed from the plan (sim stays graph-only). + // [Lane B R39 — THE SIGN, fixed] This read `(-sin ry, -cos ry)` since R8 and that is the BACK of the + // building. `buildShopfront` puts the facade, the door and the doorRect at local +Z (buildings.js:410-416, + // :583-597 — `toWorld(lot,0,0,d/2)` = `lot + (sin ry, cos ry)·d/2`); dbg.js:53 says it in words; minimap.js + // has always drawn its front-edge tick there. Measured against each lot's OWN frontEdge: the +sin point is + // 0.00 m from the kerb on the synthetic and −1.50 m on katoomba_real, the −sin point is 15.25 m / 12.50 m + // the wrong side, and the front wins on 493/493 and 72/72 shops. Peds were ducking into the back fence. const shopsByChunk = new Map(); for (const s of plan.shops) { const l = plan.lots.find((x) => x.id === s.lot); if (!l) continue; - const ry = l.ry || 0, fx = -Math.sin(ry), fz = -Math.cos(ry); + const ry = l.ry || 0, fx = Math.sin(ry), fz = Math.cos(ry); const x = l.x + fx * (l.d / 2 + 0.6), z = l.z + fz * (l.d / 2 + 0.6); const k = citizens.chunkKeyAt(x, z); if (!shopsByChunk.has(k)) shopsByChunk.set(k, []); @@ -484,6 +490,12 @@ const queueCountOf = (id) => { const q = venueQueues && venueQueues.get(id); ret // (a point every shop already computes for patronage — known walkable), looking down the strip toward // the cluster's heart. Deterministic (pure plan math, no draws — no stream moves), and ?classic=1 // keeps the frozen pose forever (the covenant is a POSE here, not just a plan). +// [Lane B R39 — THE SIGN, fixed] R32's comment above is exactly right and the code below contradicted +// it: `-Math.sin(ry)` put the "footpath door-line" 15 m THROUGH the building, so every non-classic boot +// since R32 has opened standing behind the shop row. Measured at the shipped pose on four towns, **0 of +// the 1–3 shops within 25 m were in front of the player**; with the sign the geometry actually uses, all +// of them are (synthetic 4/4, katoomba 4/4, bowral 4/4, fitzroy 1/1). Runtime pose only — SPAWN never +// touches the plan, so no golden moves and `?classic=1` keeps the frozen (-96, 9) pose regardless. let SPAWN = { x: -96, z: 9, yaw: -Math.PI / 2 }; if (!CLASSIC && plan.shops && plan.shops.length >= 2) { // main-street shop doors only (block kind — both generators stamp it); every-door fallback @@ -491,7 +503,7 @@ if (!CLASSIC && plan.shops && plan.shops.length >= 2) { const doorOf = (s) => { const l = plan.lots.find((x) => x.id === s.lot); if (!l) return null; const ry = l.ry || 0; - return { x: l.x - Math.sin(ry) * (l.d / 2 + 2.6), z: l.z - Math.cos(ry) * (l.d / 2 + 2.6), block: l.block }; + return { x: l.x + Math.sin(ry) * (l.d / 2 + 2.6), z: l.z + Math.cos(ry) * (l.d / 2 + 2.6), block: l.block }; }; let doors = plan.shops.map(doorOf).filter(Boolean); const ms = doors.filter((d) => msBlocks.has(d.block));