nemocity / engine /genesis.py
AndresCarreon's picture
NEMOCITY v0 — mock backend, gradio 6.16.0 (pre-SSR)
d72231c verified
Raw
History Blame Contribute Delete
4.96 kB
"""NEMOCITY genesis — epoch 0, exactly as specified in ARCHITECTURE.md.
Roads, then buildings, then a note; all at t = CITY_EPOCH_S, wish_id
"genesis", seeds crc32-derived. These values are a cross-component contract
(web/mock/world.json is generated from this list); do NOT edit them.
Validity is asserted at import: every footprint on empty non-water in-bounds
cells, every building touching a road, bridge cells on water and nothing else.
"""
from __future__ import annotations
import copy
import zlib
from . import constants as C
def _seed(i: int) -> int:
return zlib.crc32(f"genesis:{i}".encode()) & 0x7FFFFFFF
def _ev(i: int, tool: str, args: dict) -> dict:
return {
"id": f"e_{i:06d}", "wish_id": "genesis", "tool": tool,
"args": args, "seed": _seed(i), "t": float(C.CITY_EPOCH_S),
}
def _col(cx: int, cz0: int, cz1: int) -> list[list[int]]:
return [[cx, cz] for cz in range(cz0, cz1 + 1)]
def _row(cz: int, cx0: int, cx1: int, skip: tuple[int, ...] = ()) -> list[list[int]]:
return [[cx, cz] for cx in range(cx0, cx1 + 1) if cx not in skip]
def _road(i: int, name: str, klass: str, cells: list[list[int]]) -> dict:
return _ev(i, "lay_road", {"cells": cells, "klass": klass, "name": name})
def _bld(i: int, kind: str, name: str, cx: int, cz: int, floors: int,
hue: int, variant: int) -> dict:
spec = C.BUILDINGS[kind]
return _ev(i, "place_building", {
"kind": kind, "name": name, "cx": cx, "cz": cz,
"w": spec["w"], "d": spec["d"], "floors": floors,
"hue": hue, "variant": variant,
})
GENESIS_FEATURES: list[dict] = [
# roads (1st Ave skips the river cells; the Old Bridge — street class, the
# bottleneck by design — carries the only crossing)
_road(0, "Main St", "avenue", _col(0, -12, 12)),
_road(1, "1st Ave", "avenue", _row(0, -12, 16, skip=(8, 9))),
_road(2, "Old Bridge", "street", [[8, 0], [9, 0]]),
_road(3, "River Rd", "street", _col(13, -6, 6)),
_road(4, "Elm St", "street", _row(-5, -8, 0)),
_road(5, "2nd St", "street", _col(-5, -5, 3)),
# downtown west of the river
_bld(6, "town_hall", "City Hall", -2, -3, 2, 44, 0),
_bld(7, "office", "Meridian Office", 1, -2, 5, 210, 3),
_bld(8, "cafe", "Corner Cafe", 1, 1, 1, 18, 1),
_bld(9, "market", "Main St Market", -1, 1, 1, 35, 2),
_bld(10, "park", "Founders Park", -4, 1, 0, 110, 0),
# Elm / 2nd St housing cluster
_bld(11, "house", "Elm Cottage", -1, -6, 2, 28, 4),
_bld(12, "house", "Rose Cottage", -4, -6, 1, 350, 5),
_bld(13, "house", "Sage House", -6, -4, 1, 95, 6),
# east of the river — jobs/homes that force bridge commutes from day one
_bld(14, "factory", "Riverside Works", 14, -3, 1, 24, 0),
_bld(15, "warehouse", "East Depot", 14, 1, 1, 210, 1),
_bld(16, "house", "Ferry House", 14, 3, 1, 205, 7),
_bld(17, "house", "River Cottage", 14, -5, 2, 16, 2),
_ev(18, "note", {"text": "Nemocity is listening. Ask for a building.",
"kind": "milestone"}),
]
def genesis_features() -> list[dict]:
"""Deep copy of the genesis event list (safe to mutate / load)."""
return copy.deepcopy(GENESIS_FEATURES)
def genesis_world():
"""A fresh World seeded with the genesis events."""
from .world import World
return World.load(genesis_features())
def _validate() -> None:
water = {
(cx, cz)
for cz in range(C.COORD_MIN, C.COORD_MAX + 1)
for cx in C.river_cols(cz)
}
road: set[tuple[int, int]] = set()
for ev in GENESIS_FEATURES:
if ev["tool"] != "lay_road":
continue
name = ev["args"]["name"]
for cx, cz in ev["args"]["cells"]:
assert C.COORD_MIN <= cx <= C.COORD_MAX and C.COORD_MIN <= cz <= C.COORD_MAX, \
f"genesis: road cell off-grid in {name}"
on_water = (cx, cz) in water
assert on_water == (name == "Old Bridge"), \
f"genesis: {name} cell ({cx},{cz}) water mismatch"
road.add((cx, cz))
occupied: set[tuple[int, int]] = set(road)
for ev in GENESIS_FEATURES:
if ev["tool"] != "place_building":
continue
a = ev["args"]
cells = [
(a["cx"] + dx, a["cz"] + dz)
for dx in range(a["w"]) for dz in range(a["d"])
]
for c in cells:
assert C.COORD_MIN <= c[0] <= C.COORD_MAX and C.COORD_MIN <= c[1] <= C.COORD_MAX, \
f"genesis: {a['name']} off-grid"
assert c not in water, f"genesis: {a['name']} on water at {c}"
assert c not in occupied, f"genesis: {a['name']} overlaps at {c}"
touches = any(
(cx + dx, cz + dz) in road
for cx, cz in cells
for dx, dz in ((0, -1), (1, 0), (0, 1), (-1, 0))
)
assert touches, f"genesis: {a['name']} touches no road"
occupied.update(cells)
_validate()