World API
The one object your step(world) is handed. This is all of
it; there is nothing else to learn.
Coordinates
Coordinates are 1-based and (1, 1) is the
bottom-left cell, with (world.width, world.height) at
the top-right. Y grows upward, the way it does in maths rather than the
way it does on most screens.
Reference
| API | meaning |
|---|---|
world.width, world.height | grid size in cells |
world.get(x, y) | True if an Ent is at (x, y), and False off the board |
world.set(x, y, alive=True) | place or remove one Ent (ignored off the board) |
world.in_bounds(x, y) | is (x, y) on the board? |
world.count | number of living Ents |
world.tick_count | ticks elapsed since the world was created |
world.rng | a random.Random; use this one for randomness |
world.state | a dict that survives between ticks and is saved in .grid files |
world.cells | the whole grid as a NumPy bool array, shape (width, height), indexed cells[x-1, y-1] with the y index growing upward |
world.neighbor_counts(wrap=False) | NumPy array of live-neighbour counts, 0 to 8. wrap=True wraps at the edges, whatever shape the world is |
world.set_many(cells, alive=True) | set an iterable of (x, y) at once |
world.blit_mask(mask, x0, y0, ...) | stamp a boolean mask onto the board |
world.clear() | empty the board |
Two ways to write a rule
Whole-grid. Operate on world.cells and
neighbor_counts() with NumPy. This is how every classic
cellular automaton is written, and it stays fast at any board size:
def step(world):
n = world.neighbor_counts()
world.cells[:] = (n == 3) | (world.cells & (n == 2))
One cell at a time. Use get and set
with ordinary Python. It is slower, but it is the natural way to write
anything with only a few moving parts, such as a walker:
def step(world):
x = world.state.setdefault("x", 1)
world.set(x, 1)
world.state["x"] = x + 1 if x < world.width else 1
Performance
- Rules written with NumPy and
neighbor_countsstay comfortable even on 2048×2048 boards. Conway takes roughly 2 ms per tick at 1000×1000. - Plain Python is fine up to around ten thousand
get/setcalls per tick. Good for walkers, too slow for scanning a big board cell by cell. - If the machine can't hit the speed you asked for, EntLab runs as fast as it can and shows the rate it is really managing, rather than quietly falling behind.
The browser build runs the same Python through WebAssembly. It is slower than the desktop app on heavy boards, but the code is the same, so a ruleset that works in one works in the other.
The .grid file
A saved world is a single JSON file holding the board (compressed),
the tick count, world.state, and the full source of the
ruleset it was running. That last part is what makes a world worth
sending to someone: they don't need your ruleset library, because the law
of nature travels inside the world.
Drag a .grid onto the window, on the desktop or in the
browser, to open it.