joriszwart.nl

Math

Game of Life and Death

Life is finite

Source code

// TODO wrap around

const canvas = document.querySelector('canvas')
const context = canvas.getContext('2d')
const [WIDTH, HEIGHT] = [canvas.width / 16, canvas.height / 16]

const grid = Array.from(Array(HEIGHT), row => Array(WIDTH).fill(false))
    .map(row => row.map(cell => Math.random() > .75 ? true : false))
const counts = Array.from(Array(HEIGHT), row => Array(WIDTH).fill(0))

const render = () => {
    grid.forEach((row, rowIndex) => {
        row.forEach((cell, cellIndex) => {
            if (cell) {
                context.fillStyle = '#4b4b4b'
                context.fillRect(cellIndex * 16, rowIndex * 16, 15, 15)
            }
        })
    })
}

const judge = () => {
    grid.forEach((row, rowIndex) => {
        row.forEach((_, cellIndex) => {
            // TODO use reduce to count cells?
            let count = 0
            for (let y = -1; y <= 1; y++) {
                for (let x = -1; x <= 1; x++) {
                    if (x != 0 || y != 0) {
                        if (grid[rowIndex + y] && grid[rowIndex + y][cellIndex + x]) {
                            count += grid[rowIndex + y][cellIndex + x] ? 1 : 0
                        }
                    }
                }
            }
            counts[rowIndex][cellIndex] = count
        })
    })
}

const evolve = () => {
    grid.forEach((row, rowIndex) => {
        row.forEach((cell, cellIndex) => {
            const count = counts[rowIndex][cellIndex]
            row[cellIndex] = cell && (count == 2 || count == 3) || !cell && count == 3
        })
    })
}

const fade = () => {
    context.globalCompositeOperation = 'source-over'
    context.globalAlpha = .8
    context.fillStyle = 'white'
    context.fillRect(0, 0, canvas.width, canvas.height)
    context.globalAlpha = 1
};

for (; ;) {
    fade()
    render()
    judge()
    evolve()
    await new Promise(resolve => setTimeout(resolve, 250))
}

Related