export type world = struct { dead: uint, alive: uint, rows: uint, cols: uint, cells: *[*]uint, }; fn cb(r: uint, c: uint) void; fn cell(w: *world, r: uint, c: uint) *uint = &w.cells[(r * w.rows) + c]; fn isalive(w: *world, r: uint, c: uint) bool = *cell(w, r, c) == w.alive; fn next(i: uint, n: uint) uint = (i + 1) & (n - 1); fn prev(i: uint, n: uint) uint = (i - 1) & (n - 1); fn live_neighbors(w: *world, r: uint, c: uint) uint = { const nc = next(c, w.cols); const pc = prev(c, w.cols); const nr = next(r, w.rows); const pr = prev(r, w.rows); let n = 0u; if (isalive(w, pr, pc)) n += 1; if (isalive(w, pr, c)) n += 1; if (isalive(w, pr, nc)) n += 1; if (isalive(w, r, pc)) n += 1; if (isalive(w, r, nc)) n += 1; if (isalive(w, nr, pc)) n += 1; if (isalive(w, nr, c)) n += 1; if (isalive(w, nr, nc)) n += 1; return n; }; fn live(w: *world, r: uint, c: uint) bool = { const ln = live_neighbors(w, r, c); return ln == 3 || (ln == 2 && isalive(w, r, c)); }; export fn mutate(w: *world) void = { for (let r = 0u; r < w.rows; r += 1) for (let c = 0u; c < w.cols; c += 1) *cell(w, r, c) = if (live(w, r, c)) { yield w.alive; } else { yield w.dead; }; };