Some of the following code is adapted from https://jakevdp.github.io/blog/2013/08/07/conways-game-of-life/
from time import sleep
from threading import Thread
import numpy as np
from ipycanvas import RoughCanvas, hold_canvas
def life_step(x):
"""Game of life step"""
nbrs_count = sum(
np.roll(np.roll(x, i, 0), j, 1)
for i in (-1, 0, 1)
for j in (-1, 0, 1)
if (i != 0 or j != 0)
)
return (nbrs_count == 3) | (x & (nbrs_count == 2))
def draw(x, canvas, color="black"):
with hold_canvas():
canvas.clear()
canvas.fill_style = "#FFF0C9"
canvas.stroke_style = "white"
canvas.fill_rect(0, 0, canvas.width, canvas.height)
canvas.fill_style = color
canvas.stroke_style = color
living_cells = np.where(x)
rects_x = living_cells[0] * n_pixels
rects_y = living_cells[1] * n_pixels
canvas.fill_rects(rects_x, rects_y, n_pixels)
canvas.stroke_rects(rects_x, rects_y, n_pixels)
glider_gun = [
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
0,
0,
0,
0,
0,
0,
1,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
1,
0,
0,
0,
0,
1,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
],
[
1,
1,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
1,
0,
0,
0,
1,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
],
[
1,
1,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
1,
0,
1,
1,
0,
0,
0,
0,
1,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
],
]
x = np.zeros((50, 70), dtype=bool)
x[1:10, 1:37] = glider_gun
n_pixels = 15
canvas = RoughCanvas(width=x.shape[1] * n_pixels, height=x.shape[0] * n_pixels)
canvas.fill_style = "#FFF0C9"
canvas.stroke_style = "white"
canvas.fill_rect(0, 0, canvas.width, canvas.height)
canvas
draw(x, canvas, "#5770B3")
class GameOfLife(Thread):
def __init__(self, x, canvas):
self.x = x
self.canvas = canvas
super(GameOfLife, self).__init__()
def run(self):
for _ in range(1_000):
self.x = life_step(self.x)
draw(self.x, self.canvas, "#5770B3")
sleep(0.1)
GameOfLife(x, canvas).start()