jpmschweitzer
5619218e31
feat(tooling): generate_atlas.py city + infrastructure pipeline and atlas DB index ( #832 )
...
Implements the Phase 3 atlas content generator per D-191 §3, §8, and §9.
Pipeline per body (terrain-aware, deterministic per seed + body):
1. Simulate terrain via planet_simulation.simulate().
2. Analyse continents (flood-fill), habitability (temp/moisture/slope +
coastal bonus), river mouths, and a terrain A* cost grid.
3. Place cities sequentially — capital first (habitability + river-mouth
bias), then corridor growth via multi-source Dijkstra, quadrant-spread
penalty after 2 cities in a quadrant, port-on-new-continent bonus at
cities 3–4. ±25% noise for seed variation.
4. Generate roads and railroads as an MST over city positions, with
A* paths on the terrain cost grid (rail follows roads where possible).
5. Place a transit POI at the capital (15% chance to scatter to a
secondary city).
Output (canonical markers.json schema, pixel space per D-191 §8):
- cities: {id, name, kind, center:[r,c], population}
- roads: {id, name, kind, path:[[r,c],...]}
- railroads: {id, name, kind, path:[[r,c],...]}
- pois: {id, name, kind, center:[r,c]}
- existing rivers/oceans/mountain_ranges preserved untouched.
City names are left empty for gemma_naming.py (#833 ). Body population is
split across cities with geometric decay (capital ~50%, each subsequent
city half the previous). The 6 hand-authored bodies (Lendel, Edict,
Vuurkloof, Røros, Cairnside, Estrade) are detected by existing
`cities` and skipped for regeneration; their markers are still synced
to the DB index below.
Atlas index in systems.db (new):
- atlas_body_grids, atlas_cities, atlas_roads, atlas_railroads,
atlas_pois, atlas_rivers, atlas_oceans, atlas_mountain_ranges
- Scalar metadata mirror of every markers.json — the implant atlas app
and development queries can lookup cities/POIs/features without
scanning 267 JSON files. Polyline geometry stays in the markers.json
files next to the heightmaps (used by the renderer); the DB only
stores filterable scalar fields plus `point_count` as a length proxy.
- Schema lives in server/data/systems-schema.sql; generate_atlas.py
mirrors the CREATE TABLE IF NOT EXISTS block so it runs against any
DB state (matches the economy-db importer pattern).
- Populated and refreshed on every run. Each body's rows are deleted
and reinserted deterministically — no stale state.
Also fixes a pre-existing WIP bug in the quadrant-saturation penalty
loop (a stray outer `for r in range(GRID_H)` with unreachable breaks
meant only the NW quadrant was ever checked).
Runtime: 280s for all 267 inhabited bodies on a single core. 265 bodies
updated this run, 6 hand-authored bodies synced to DB without
regeneration.
Atlas index after run:
atlas_cities 329 (15 hand-authored + 314 awaiting #833 )
atlas_roads 46
atlas_railroads 44
atlas_pois 287
atlas_rivers 2034
atlas_oceans 696
atlas_mountain_ranges 1953
atlas_body_grids 267
2026-04-15 08:46:55 +02:00
..
2026-04-06 17:10:35 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-14 16:07:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-14 16:07:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 18:51:33 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-14 16:07:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-14 16:07:20 +02:00
2026-04-06 16:27:33 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-10 22:21:52 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 18:51:33 +02:00
2026-04-06 22:55:20 +02:00
2026-04-06 22:55:20 +02:00
2026-04-06 22:55:20 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 17:10:35 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-06 18:51:33 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-06 22:55:20 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-15 08:46:55 +02:00
2026-04-04 13:13:31 +02:00
2026-03-16 01:24:13 +01:00
2026-04-05 09:35:56 +02:00
2026-03-16 22:12:48 +01:00
2026-03-16 22:08:53 +01:00
2026-03-16 22:12:19 +01:00
2026-04-05 09:36:31 +02:00
2026-03-14 21:22:36 +01:00
2026-03-16 08:53:18 +01:00