// NEMOCITY — scripted mock petition feed (?mock=1 and the live "welcome build"). // Each script is a full petition lifecycle as SSE-shaped events with relative // delays (seconds of simTime). main.js stamps feature.t at apply time so // construction always starts "now"; world_delta features carry exact cells // (the engine isn't running in mock — these were placed by hand against the // genesis layout and do not collide with it or with each other). // // GENESIS_FEATURES mirrors the contract's genesis list verbatim — the fallback // when web/mock/world.json (generated later by tools/gen_web.py) is absent. const T0 = 1781222400; // CITY_EPOCH_S const colCells = (cx, z0, z1) => { const cells = []; for (let z = z0; z <= z1; z++) cells.push([cx, z]); return cells; }; const rowCells = (cz, x0, x1, skip = []) => { const cells = []; for (let x = x0; x <= x1; x++) if (!skip.includes(x)) cells.push([x, cz]); return cells; }; const seedOf = (i) => (2654435761 * (i + 1)) % 2147483647; let gi = 0; const G = (tool, args) => ({ id: `e_g${String(++gi).padStart(3, "0")}`, wish_id: "genesis", tool, args, seed: seedOf(gi), t: T0 + gi * 0.25, }); const GB = (kind, name, cx, cz, w, d, floors, hue, variant) => G("place_building", { kind, name, cx, cz, w, d, floors, hue, variant }); export const GENESIS_FEATURES = [ // roads first (every genesis footprint touches one) G("lay_road", { cells: colCells(0, -12, 12), klass: "avenue", name: "Main St" }), G("lay_road", { cells: rowCells(0, -12, 16, [8, 9]), klass: "avenue", name: "1st Ave" }), G("lay_road", { cells: [[8, 0], [9, 0]], klass: "street", name: "Old Bridge" }), G("lay_road", { cells: colCells(13, -6, 6), klass: "street", name: "River Rd" }), G("lay_road", { cells: rowCells(-5, -8, 0), klass: "street", name: "Elm St" }), G("lay_road", { cells: colCells(-5, -5, 3), klass: "street", name: "2nd St" }), // downtown GB("town_hall", "City Hall", -2, -3, 2, 2, 2, 44, 0), GB("office", "Meridian House", 1, -2, 1, 1, 5, 208, 1), GB("cafe", "Corner Cafe", 1, 1, 1, 1, 1, 35, 0), GB("market", "Main St Market", -1, 1, 1, 2, 1, 30, 2), GB("park", "Founders Park", -4, 1, 2, 2, 0, 110, 0), // Elm / 2nd St cluster GB("house", "Elm Cottage", -1, -6, 1, 1, 1, 18, 0), GB("house", "Gable House", -4, -6, 1, 1, 2, 26, 1), GB("house", "Second St House", -6, -4, 1, 1, 1, 350, 2), // east of the river: the bridge commute from day one GB("factory", "Riverside Works", 14, -3, 3, 2, 1, 28, 0), GB("warehouse", "East Storage", 14, 1, 2, 2, 1, 40, 1), GB("house", "River House", 14, 3, 1, 1, 1, 14, 0), GB("house", "Ferry Cottage", 14, -5, 1, 1, 2, 200, 1), G("note", { text: "Nemocity is listening. Ask for a building.", kind: "milestone" }), ]; // ------------------------------------------------------------------ scripts const WELCOME = { wish_id: "w_demo_cafe", match: "cafe|coffee|shop|store|bakery|restaurant|diner", events: [ { at: 0.0, ev: { type: "wish_started", wish_id: "w_demo_cafe", text: "a corner cafe where Main St meets 1st Ave" } }, { at: 2.6, ev: { type: "plan", wish_id: "w_demo_cafe", plan: { intent: "build", blurb: "A warm corner for the morning crowd. Permit granted.", buildings: [{ kind: "cafe", name: "Cafe Luna", near: "Main St and 1st Ave", floors: 1, hue: 35 }], decline_reason: null } } }, { at: 3.4, ev: { type: "tool_call", wish_id: "w_demo_cafe", call_index: 0, tool: "place_building", args: { kind: "cafe", name: "Cafe Luna", cx: 2, cz: 1, w: 1, d: 1, floors: 1, hue: 35, variant: 2 } } }, { at: 3.7, ev: { type: "world_delta", feature: { id: "e_demo_cafe", wish_id: "w_demo_cafe", tool: "place_building", args: { kind: "cafe", name: "Cafe Luna", cx: 2, cz: 1, w: 1, d: 1, floors: 1, hue: 35, variant: 2 }, seed: 1830293847 } } }, { at: 5.4, ev: { type: "wish_granted", wish_id: "w_demo_cafe", epoch: null, epitaph: "Cafe Luna opens where Main St meets 1st Ave — first coffee is on the mayor." } }, ], }; const APARTMENTS = { wish_id: "w_demo_apts", match: "apartment|home|house|housing|condo|famil|live|residen", events: [ { at: 0.0, ev: { type: "wish_started", wish_id: "w_demo_apts", text: "homes for the families moving in" } }, { at: 2.7, ev: { type: "plan", wish_id: "w_demo_apts", plan: { intent: "build", blurb: "Homes first — five floors of them, walking distance to the square.", buildings: [{ kind: "apartments", name: "Elm Court", near: "north end of Main St", floors: 5, hue: 18 }], decline_reason: null } } }, { at: 3.5, ev: { type: "tool_call", wish_id: "w_demo_apts", call_index: 0, tool: "place_building", args: { kind: "apartments", name: "Elm Court", cx: 1, cz: -8, w: 2, d: 2, floors: 5, hue: 18, variant: 1 } } }, { at: 3.8, ev: { type: "world_delta", feature: { id: "e_demo_apts", wish_id: "w_demo_apts", tool: "place_building", args: { kind: "apartments", name: "Elm Court", cx: 1, cz: -8, w: 2, d: 2, floors: 5, hue: 18, variant: 1 }, seed: 482919101 } } }, { at: 5.6, ev: { type: "wish_granted", wish_id: "w_demo_apts", epoch: null, epitaph: "Elm Court tops out at five floors — sixteen new households over Main St." } }, ], }; const PARK = { wish_id: "w_demo_park", match: "park|garden|green|playground|tree|lawn|plaza|square", events: [ { at: 0.0, ev: { type: "wish_started", wish_id: "w_demo_park", text: "a little park east of Main St" } }, { at: 2.6, ev: { type: "plan", wish_id: "w_demo_park", plan: { intent: "build", blurb: "Every block deserves shade. A green opens off Main St.", buildings: [{ kind: "park", name: "Juniper Green", near: "east of Main St", floors: null, hue: null }], decline_reason: null } } }, { at: 3.4, ev: { type: "tool_call", wish_id: "w_demo_park", call_index: 0, tool: "place_building", args: { kind: "park", name: "Juniper Green", cx: 3, cz: 3, w: 2, d: 2, floors: 0, hue: 110, variant: 0 } } }, { at: 3.7, ev: { type: "world_delta", feature: { id: "e_demo_park", wish_id: "w_demo_park", tool: "place_building", args: { kind: "park", name: "Juniper Green", cx: 3, cz: 3, w: 2, d: 2, floors: 0, hue: 110, variant: 0 }, seed: 99182447 } } }, { at: 4.6, ev: { type: "tool_call", wish_id: "w_demo_park", call_index: 1, tool: "lay_road", args: { cells: [[1, 3], [2, 3]], klass: "street", name: "Juniper Walk" } } }, { at: 4.9, ev: { type: "world_delta", feature: { id: "e_demo_parkrd", wish_id: "w_demo_park", tool: "lay_road", args: { cells: [[1, 3], [2, 3]], klass: "street", name: "Juniper Walk" }, seed: 77120993 } } }, { at: 6.6, ev: { type: "wish_granted", wish_id: "w_demo_park", epoch: null, epitaph: "Juniper Green opens at the end of a brand-new lane off Main St." } }, ], }; const TOWER = { wish_id: "w_demo_tower", match: "tower|skyscraper|office|highrise|high-rise|bank|glass|tall", events: [ { at: 0.0, ev: { type: "wish_started", wish_id: "w_demo_tower", text: "a glass tower for the downtown skyline" } }, { at: 2.8, ev: { type: "plan", wish_id: "w_demo_tower", plan: { intent: "build", blurb: "Downtown earns a crown — twelve floors by Founders Park.", buildings: [{ kind: "tower", name: "Nano Spire", near: "downtown", floors: 12, hue: 205 }], decline_reason: null } } }, { at: 3.5, ev: { type: "tool_call", wish_id: "w_demo_tower", call_index: 0, tool: "place_building", args: { kind: "tower", name: "Nano Spire", cx: -3, cz: 3, w: 2, d: 2, floors: 12, hue: 205, variant: 0 } } }, { at: 3.8, ev: { type: "world_delta", feature: { id: "e_demo_tower", wish_id: "w_demo_tower", tool: "place_building", args: { kind: "tower", name: "Nano Spire", cx: -3, cz: 3, w: 2, d: 2, floors: 12, hue: 205, variant: 0 }, seed: 555888221 } } }, { at: 4.7, ev: { type: "tool_call", wish_id: "w_demo_tower", call_index: 1, tool: "lay_road", args: { cells: [[-1, 3]], klass: "street", name: "Spire Ct" } } }, { at: 5.0, ev: { type: "world_delta", feature: { id: "e_demo_towerrd", wish_id: "w_demo_tower", tool: "lay_road", args: { cells: [[-1, 3]], klass: "street", name: "Spire Ct" }, seed: 31337077 } } }, // demand-driven infill: jobs outran housing — the engine adds ONE home { at: 6.2, ev: { type: "world_delta", feature: { id: "e_demo_infill", wish_id: "w_demo_tower", tool: "place_building", args: { kind: "house", name: "Garden Cottage", cx: -5, cz: 4, w: 1, d: 1, floors: 1, hue: 95, variant: 1 }, seed: 90210663 } } }, { at: 6.6, ev: { type: "world_delta", feature: { id: "e_demo_infillnote", wish_id: "w_demo_tower", tool: "note", args: { text: "New families are moving in.", kind: "infill" }, seed: 7 } } }, { at: 7.8, ev: { type: "wish_granted", wish_id: "w_demo_tower", epoch: null, epitaph: "Nano Spire tops out at twelve floors — the skyline finds its center." } }, ], }; export const SCRIPTS = [WELCOME, APARTMENTS, PARK, TOWER]; export { WELCOME }; // The traffic-fix beat: alert -> City Engineer reads telemetry -> ONE apply_fix. // The new avenue runs cz=-6 from Main St to River Rd, bridging the river at // (7,-6),(8,-6) — a believable second crossing north of the Old Bridge. const FIX_CELLS = [ [1, -6], [2, -6], [3, -6], [4, -6], [5, -6], [6, -6], [7, -6], [8, -6], [9, -6], [10, -6], [11, -6], [12, -6], ]; const FIX_DIAGNOSIS = "Old Bridge carries 3.1x its capacity at rush; every river crossing funnels into one street cell. A second crossing cuts the index 78 to 41."; export const FIX_SCRIPT = { wish_id: "w_demo_fix", match: "traffic|bridge|jam|congest|road", events: [ { at: 0.0, ev: { type: "traffic_alert", name: "Old Bridge" } }, // mock-only event type { at: 3.0, ev: { type: "wish_started", wish_id: "w_demo_fix", text: "Traffic fix — Old Bridge is over capacity" } }, { at: 6.2, ev: { type: "plan", wish_id: "w_demo_fix", plan: { diagnosis: FIX_DIAGNOSIS, choice: "F2", blurb: "Oak Ave opens a second crossing north of the Old Bridge." } } }, { at: 7.0, ev: { type: "tool_call", wish_id: "w_demo_fix", call_index: 0, tool: "apply_fix", args: { action: "new_road", cells: FIX_CELLS, klass: "avenue", name: "Oak Ave Bridge" } } }, { at: 7.3, ev: { type: "world_delta", feature: { id: "e_demo_fix", wish_id: "w_demo_fix", tool: "apply_fix", args: { action: "new_road", cells: FIX_CELLS, klass: "avenue", name: "Oak Ave Bridge", diagnosis: FIX_DIAGNOSIS, metrics_before: { traffic_index: 78, worst: "Old Bridge" }, metrics_predicted: { traffic_index: 41 } }, seed: 99182554 } } }, { at: 9.2, ev: { type: "wish_granted", wish_id: "w_demo_fix", epoch: null, epitaph: "Oak Ave opens a second river crossing — bridge load cut nearly in half." } }, ], };