import { pairs } from '../util.js'; function mod(k, n) { return ((k % n) + n) % n; } function pos_wrap(lattice, x, y) { const height = lattice.length; const width = lattice[0].length; return [mod(x, width), mod(y, height)]; } function neighbors(lattice, x, y) { const offsets = [-1, 0, 1]; const positions = pairs(offsets, offsets) .filter(([dx, dy]) => dx !== 0 || dy !== 0) .map(([dx, dy]) => pos_wrap(lattice, x+dx, y+dy)); const neighbors = positions .map(([x, y]) => [x, y, lattice[y][x]]); return neighbors; } export const lattice_rules = { empty: (lattice, x, y) => { const num_active_neighbors = neighbors(lattice, x, y) .map(([x, y, cell]) => cell.type) .filter(type => type === 'mutable' || type === 'active') .length; if (num_active_neighbors === 3) { return { world_updates: [{ x, y, from: 'empty', to: 'active', flags: { emit: [0, 0, 0, 0, 0, 0, 0, 1] }, }]}; } }, active: (lattice, x, y) => { const num_active_neighbors = neighbors(lattice, x, y) .map(([x, y, cell]) => cell.type) .filter(type => type === 'mutable' || type === 'active') .length; const die = { world_updates: [{ x, y, from: 'active', to: 'empty', flags: { emit: [0, 0, 0, 0, 0, 0, 0, -1] }, }]}; if (num_active_neighbors < 2) { return die; } else if (num_active_neighbors > 3) { return die; } }, mutable: (lattice, x, y) => { const num_active_neighbors = neighbors(lattice, x, y) .map(([x, y, cell]) => cell.type) .filter(type => type === 'active') .length; if (num_active_neighbors > 0) { // become living cell return { world_updates: [{ x, y, from: 'empty', to: 'active', flags: { emit: [0, 0, 0, 0, 0, 0, 0, 1] }, }]}; } }, immutable: () => {}, flag: () => {}, };