diff --git a/web/world/js/tests/a.test.js b/web/world/js/tests/a.test.js index 4c808a0..fba1915 100644 --- a/web/world/js/tests/a.test.js +++ b/web/world/js/tests/a.test.js @@ -234,11 +234,11 @@ export default async function run(t) { // --- anchors ------------------------------------------------------------- - t.test('yard offers 11 anchors: 3 house, 5 tree, 3 post', () => { + t.test('yard offers 12 anchors: 3 house, 5 tree, 4 post', () => { const by = (type) => world.anchors.filter((a) => a.type === type).length; assertEq(by('house'), 3, 'house anchors'); assertEq(by('tree'), dressed ? 5 : 2, 'tree anchors (branch_anchor_* arrive with dress())'); - assertEq(by('post'), 3, 'post anchors — p3 added, SPRINT3 decision 2'); + assertEq(by('post'), 4, 'post anchors — p3 (SPRINT3 dec 2), p4 (SPRINT6 gate 1)'); const ids = world.anchors.map((a) => a.id); assertEq(new Set(ids).size, ids.length, `anchor ids not unique: ${ids}`); }); diff --git a/web/world/js/world.js b/web/world/js/world.js index ab6acdf..e0622fb 100644 --- a/web/world/js/world.js +++ b/web/world/js/world.js @@ -270,10 +270,32 @@ export function createWorld(scene, opts = {}) { // 6 m bed with it costs you a sail the storm will take. Full shade is meant to // be the expensive answer; the small quads buy survival and pay in patchy // shade. That IS the design (DESIGN.md, "big flat low vs small twisted steep"). + // SPRINT6 gate 1: p4 is the ONE close anchor the balance pass allows, and its + // position is measured rather than guessed. + // + // The wild night had no winnable line because every anchor near the bed — + // p1/p2/p3 — is SOUTH of it, and nothing stands north short of the house 10 m + // away. So covering rigs had to span the yard and died, while rigs small + // enough to survive sat beside the bed instead of over it. + // + // p4 supplies the missing north-west corner. Swept its position against the + // smallest quad that covers 90% of the bed: + // (-2.2, -1.2) → 44.4 m² ← breaks the tradeoff (see below) + // (-3.2, -1.2) → 48.6 m² ← here + // (-3.2, -2.0) → 51.7 m² + // (-4.2, -3.0) → 60.0 m² + // beyond ~z=-4 → 63.5 m², i.e. too far away to matter at all + // Full coverage costs 63.5 m² without it. At (-3.2,-1.2) that drops to 48.6 — + // a real new option, 23% cheaper — while still costing you a bigger sail than + // the 23-38 m² rigs that survive on their own. Pulling it in to (-2.2,-1.2) + // would put full coverage at 44.4 m², INSIDE the survivable band, which + // collapses DESIGN.md's central tension: covering the bed has to cost risk. + // a.test.js asserts that >45 m² floor, so moving this post inward goes red. const postSpecs = [ { id: 'p1', x: -4.5, z: 5.5, h: 4.0 }, { id: 'p2', x: 4.0, z: 6.0, h: 4.0 }, { id: 'p3', x: 0, z: 7.0, h: 4.0 }, + { id: 'p4', x: -3.2, z: -1.2, h: 4.0 }, ]; const RAKE = (8 * Math.PI) / 180; for (const spec of postSpecs) {