FAQ
- Why use wrapping indexes in count_neighbors?
- Neighbor positions are computed with modulo so the grid edges wrap around like a torus.
- How is the next generation computed?
- Each step counts living neighbours and applies the standard rules to produce a new grid.
- What does the frame function record?
- It snapshots the entire grid each step so the evolution can be replayed.
simulation.py
Conway's Game of Life
This simulation generates successive frames of Conway's Game of Life on a rectangular grid. Each cell is either alive or dead and evolves according to the standard rules of the game.
from tys import progress, frame, probe
import random
Run the Game of Life simulation.
def simulate(cfg: dict):
rows = cfg["rows"]
cols = cfg["cols"]
steps = cfg["steps"]
chance = cfg.get("initial_chance", 0.2)
grid = [[1 if random.random() < chance else 0 for _ in range(cols)] for _ in range(rows)]
probe("alive", 0, sum(sum(row) for row in grid))
def count_neighbors(r: int, c: int) -> int:
total = 0
for dr in (-1, 0, 1):
for dc in (-1, 0, 1):
if dr == 0 and dc == 0:
continue
rr = (r + dr) % rows
cc = (c + dc) % cols
total += grid[rr][cc]
return total
for step in range(steps):
frame(step, grid)
new_grid = [[0] * cols for _ in range(rows)]
for r in range(rows):
for c in range(cols):
n = count_neighbors(r, c)
if grid[r][c]:
new_grid[r][c] = 1 if n in (2, 3) else 0
else:
new_grid[r][c] = 1 if n == 3 else 0
grid = new_grid
alive = sum(sum(row) for row in grid)
probe("alive", step + 1, alive)
progress(int(100 * (step + 1) / steps))
frame(steps, grid)
alive = sum(sum(row) for row in grid)
return {"alive": alive}
def requirements():
return {
"builtin": ["micropip", "pyyaml"],
"external": []
}
Default.yaml
rows: 80
cols: 80
steps: 60
initial_chance: 0.3
Charts (Default)
Final Frame (Default)
Final Results (Default)
Metric | Value |
---|---|
alive | 705.00 |