import { resolveBoundaryCondition, resolveBoundaryIndex } from '../caRuntime.js' import type { Cells, SceneParams } from '../types.js' import { emptyCellsLike } from './cellGrid.js' function parseOuterTotalisticRule(ruleId: string) { const match = /^B([0-8]*)\/S([0-8]*)$/i.exec(ruleId) if (!match) return { birth: new Set([3]), survival: new Set([2, 3]) } return { birth: new Set(match[1].split('').map(Number)), survival: new Set(match[2].split('').map(Number)) } } export function stepOuterTotalistic2d(cells: Cells, settings: SceneParams) { const rule = parseOuterTotalisticRule(settings.simulation?.ruleId ?? 'B3/S23') const next = emptyCellsLike(cells) const height = cells.length const width = cells[0]?.length ?? 0 const boundary = resolveBoundaryCondition(settings.simulation?.grid) for (let y = 0; y < height; y += 1) { for (let x = 0; x < width; x += 1) { let neighbours = 0 for (let dy = -1; dy <= 1; dy += 1) { for (let dx = -1; dx <= 1; dx += 1) { if (dx === 0 && dy === 0) continue const rawX = x + dx const rawY = y + dy const nx = resolveBoundaryIndex(rawX, width, boundary) const ny = resolveBoundaryIndex(rawY, height, boundary) if (nx === null || ny === null) continue if (cells[ny][nx]) neighbours += 1 } } next[y][x] = cells[y][x] ? rule.survival.has(neighbours) : rule.birth.has(neighbours) } } return next }