zymera.worldgen
worldgen
WorldGen — Terrain and Spawn components (the un-baked halves of reset).
Two small protocols, each a family of frozen, hashable, trace-time-static dataclasses (the static-object rule, spec §3.0):
- :class:
Terrain—walls(key, h, w) -> (H, W) boolobstacle mask. Implementations: :class:OpenTerrain, :class:RandomWalls, :class:MapFile, :class:Rooms. - :class:
Spawn—positions(key, wall, n_agents) -> (N, 2) int32distinct free cells. Implementations: :class:ScatterSpawn, :class:ClusterSpawn, :class:FixedSpawn.
Parity lineage (bit-for-bit, gated by tests/test_worldgen.py):
RandomWalls ports v0 zymera.env._random_wall; ScatterSpawn ports
the v0 World.initial weighted-choice spawn; ClusterSpawn ports
examples/comm_coverage.py::CommCoverageEnv._cluster_spawn verbatim —
including its internal akey, ckey = split(key), the uniform tie-break
noise, and the lax.top_k overflow behaviour.
All methods are pure JAX (jit/vmap/scan-safe); h/w/n_agents are
static Python ints, only key/wall are traced.
Terrain
Bases: Protocol
Obstacle-mask generator. h/w are static; key may be ignored.
walls
walls(key, h, w)
Return an (H, W) bool mask — True where a wall blocks the cell.
Source code in zymera/worldgen.py
40 41 42 | |
Spawn
Bases: Protocol
Initial-position generator over a terrain's free cells.
positions
positions(key, wall, n_agents)
Return (N, 2) int32 (row, col) — distinct, free cells.
Source code in zymera/worldgen.py
48 49 50 | |
OpenTerrain
dataclass
OpenTerrain()
No obstacles — the all-False mask. Ignores the key.
RandomWalls
dataclass
RandomWalls(n_obstacles)
n_obstacles uniformly random wall cells, fresh each reset key.
v0 _random_wall verbatim: flat indices drawn by jax.random.choice
without replacement, then scattered into the mask. n_obstacles is
clamped to the cell count at trace time.
MapFile
dataclass
MapFile(cells)
A fixed map, stored as nested tuples so the component stays hashable (spec §3.0 — components that conceptually hold arrays store tuples and materialize inside methods). Ignores the key.
Build via :meth:from_string ('#' = wall, '.' = free,
whitespace-only rows skipped) or :meth:load (same format, from a file).
from_string
classmethod
from_string(s)
Parse a map drawing: '#' = wall, '.' = free; blank rows skipped.
Source code in zymera/worldgen.py
113 114 115 116 117 118 119 120 121 122 123 124 125 | |
load
classmethod
load(path)
Read :meth:from_string format from path.
Source code in zymera/worldgen.py
127 128 129 130 131 | |
Rooms
dataclass
Rooms(rooms=2, door_w=1)
rooms equal-width rooms separated by full-height vertical walls,
one door_w-tall door per wall at a key-driven row.
Deliberately simple (spec §3.1): wall i (of rooms - 1) sits at
column (i + 1) * w // rooms; the door's top row is drawn uniformly
from [0, h - door_w] per wall from the reset key. rooms=1 is the
open grid. Doors keep the free cells connected, so any spawn works.
ScatterSpawn
dataclass
ScatterSpawn()
Distinct free cells anywhere on the grid.
v0 World.initial verbatim: flat indices sampled without replacement,
weighted to free cells (wall cells get probability zero).
ClusterSpawn
dataclass
ClusterSpawn(radius)
N distinct free cells clustered within radius of a random interior
anchor.
v0 _cluster_spawn verbatim: akey, ckey = split(key); anchor drawn
from free ∩ interior cells; every cell scored
block-and-free (noise + 1) ≫ free (noise) ≫ wall (−1) with uniform
tie-break noise; lax.top_k takes the N best. Guarantees N distinct
cells and degrades gracefully when obstacles crowd the patch (overflow
spills to the highest-noise free cells anywhere on the grid).
FixedSpawn
dataclass
FixedSpawn(cells)
Spawn at explicit (row, col) cells, in order. Ignores the key.
Cells must be distinct; the first n_agents of them are used (so one
component can serve a ladder of team sizes). The caller is responsible
for the cells being free on the paired terrain — checked by tests, not
at trace time (the wall array is traced).