Spaces:
Runtime error
Runtime error
import numpy as np | |
from scipy import signal | |
from PIL import Image | |
from utils import generate_image_from_grid | |
class GameOfLife: | |
def __init__(self): | |
"""Initialize the game. | |
dim: dimensions of the board | |
p: probability of a cell being dead at init | |
seed: (optional) for reproducibility, set to None for a new random state | |
init_state: (optional) a np.array grid to start the game with | |
""" | |
self.kernel = [ | |
[1, 1, 1], | |
[1, 0, 1], | |
[1, 1, 1], | |
] | |
self.kernel = np.ones((3, 3)) | |
self.kernel[1, 1] = 0 | |
self.game_history = [] | |
self.state = None | |
self.step_counter = 0 | |
def set_random_state(self, dim=(100, 100), p=0.5, seed=None): | |
if seed: | |
np.random.seed(seed) | |
self.state = (np.random.random(dim) < p).astype("int") | |
self.game_history.append(self.state.copy()) | |
def set_empty_state(self, dim=(100, 100)): | |
self.state = np.zeros(dim) | |
self.game_history.append(self.state.copy()) | |
def set_state_from_array(self, array): | |
self.state = array.copy() | |
self.game_history.append(self.state.copy()) | |
def count_neighbors(self): | |
""" | |
Count the number of live neighbors each cell in self.state has with convolutions. | |
""" | |
self.neighbors = signal.convolve2d( | |
self.state, self.kernel, boundary="fill", fillvalue=0, mode="same" | |
).astype("int") | |
def place_blob(self, blob, i, j): | |
"""Place a blob at coordinates i,j | |
blob: ndarray of zeros and ones | |
i: int | |
j: int | |
""" | |
try: | |
self.state[i : i + blob.shape[0], j : j + blob.shape[1]] = blob | |
except: | |
print("Check bounds of box vs size of game!") | |
def step(self): | |
"""Update the game based on conway game of life rules""" | |
# Count the number of neighbors via convolution | |
self.count_neighbors() | |
# Copy of initial state | |
self.new_state = self.state | |
# Rebirth if cell is dead and has three live neighbors | |
self.new_state += np.logical_and(self.neighbors == 3, self.state == 0) | |
# Death if cell has less than 2 neighbors | |
self.new_state -= np.logical_and(self.neighbors < 2, self.state == 1) | |
# Death if cell has more than 3 neighbors | |
self.new_state -= np.logical_and(self.neighbors > 3, self.state == 1) | |
# Update game state | |
self.state = self.new_state | |
# Save state to history | |
self.game_history.append(self.state.copy()) | |
# Update step counter | |
self.step_counter += 1 | |
def generate_n_steps(self, n): | |
for _ in range(n): | |
self.step() | |
if np.array_equal(self.game_history[-1], self.game_history[-2]): | |
# If the game is stable, break | |
break | |
def generate_image(self, grid: np.array, img_size: int = 512) -> Image: | |
return generate_image_from_grid(grid, img_size) | |