math/CellularAutomaton.js

import Grid from "./Grid.js";

/**
 * 2D grid CA
 * @see https://en.wikipedia.org/wiki/Cellular_automaton
 */
class CellularAutomaton {
    /**
     * @param {Grid} inputGrid 
     */
    constructor(inputGrid) {
        this.inputGrid = inputGrid;

        this.iterations = 10;
        this.bornList = [6, 7, 8];
        this.surviveList = [3, 4, 5, 6, 7, 8];
    }

    /**
     * Run the automaton the specified amount of iterations
     * @returns {Grid} the grid
     */
    run() {
        let cells = this.inputGrid;

        for (let index = 0; index < this.iterations; index++) {
            cells = this.apply(cells);
        }

        return cells;
    }

    apply(grid) {
        var newCells = new Grid(grid.w, grid.h, 0);

        grid.each((x, y, currentState) => {
            var nbhd = 0;

            nbhd += grid.get(y - 1, x - 1);
            nbhd += grid.get(y - 1, x);
            nbhd += grid.get(y - 1, x + 1);
            nbhd += grid.get(y, x - 1);
            nbhd += grid.get(y, x + 1);
            nbhd += grid.get(y + 1, x - 1);
            nbhd += grid.get(y + 1, x);
            nbhd += grid.get(y + 1, x + 1);

            var liveCondition =
                (currentState == 0 && this.bornList.indexOf(nbhd) > -1) ||
                (currentState == 1 && this.surviveList.indexOf(nbhd) > -1);

            newCells.set(y, x, liveCondition ? 1 : 0);
        });

        return newCells;
    }
}

export default CellularAutomaton