Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 122 additions & 0 deletions game_of_life.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import itertools
import random
import sys
import time
from typing import List

import pygame

from pharmacontroller import SCREEN_SIZE, PharmaScreen

Grid = type(List[List[int]])


def is_valid_index(row: int, column: int) -> bool:
"""
Check if the given row and column are valid indices.

Args:
row (int): The row index.
column (int): The column index.

Returns:
True if the indices are valid, false otherwise.
"""
conditions = (
0 <= row < SCREEN_SIZE,
0 <= column < SCREEN_SIZE,
PharmaScreen.is_drawable(row, column),
)
return all(conditions)


def generate_grid() -> Grid:
"""
Generate a grid without any living cells.

Returns:
The grid state.
"""
return [[0 for _ in range(SCREEN_SIZE)] for _ in range(SCREEN_SIZE)]


def get_neighbors(grid: Grid, row: int, column: int) -> List[int]:
"""
Get the neighbors of the cell at the given row and column.

Args:
grid (numpy.ndarray): The grid state.
row (int): The row of the cell.
column (int): The column of the cell.

Returns:
The list of neighbors.
"""
neighbors = []

# Iterate over the 3x3 grid around the cell
for i, j in itertools.product(range(-1, 2), repeat=2):
# Ignore current cell
if i == 0 and j == 0:
continue

# Get the new row and column
new_row = row + i
new_column = column + j

# Ignore out of bounds cells
if not is_valid_index(new_row, new_column):
continue

neighbors.append(grid[new_row][new_column])

return neighbors


def next_generation(grid: Grid) -> Grid:
"""
Generate the next generation of the grid.

Returns:
The next generation of the grid.
"""
new_grid = generate_grid()

for row, column in itertools.product(range(SCREEN_SIZE), range(SCREEN_SIZE)):
neighbors = get_neighbors(grid, row, column)
alive_neighbors = sum(neighbors)
cell = grid[row][column]

if cell == 1:
if alive_neighbors < 2 or alive_neighbors > 3:
new_grid[row][column] = 0 # Cell dies of underpopulation or overpopulation
else:
new_grid[row][column] = 1 # Cell survives
else:
if alive_neighbors == 3:
new_grid[row][column] = 1 # Cell is born (good population)

return new_grid


if __name__ == "__main__":
pygame.init()
screen = PharmaScreen(color_scale=False)

grid = generate_grid()

for _ in range(500):
grid[random.randrange(SCREEN_SIZE)][random.randrange(SCREEN_SIZE)] = 1

running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()

grid = next_generation(grid)
screen.set_image(grid)

# Leave time to contemplate life
time.sleep(0.1)
3 changes: 2 additions & 1 deletion pharmacontroller.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ def __init__(self, color_scale=True, server_ip='192.168.10.10'):
self.fps = FPS_8COLOR if color_scale else FPS_2COLOR
self.font = pygame.font.SysFont(None, 24)

def is_drawable(self, row: int, col: int) -> bool:
@staticmethod
def is_drawable(row: int, col: int) -> bool:
"""
Returns whether the given coordinates match an actual LED on the screen.
"""
Expand Down
4 changes: 2 additions & 2 deletions snake.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def update(self, pressed_keys):
new_head = (self.tail[0][0] + to_add[0], self.tail[0][1] + to_add[1])

# Wall collision
if not PharmaScreen.is_drawable(None, new_head[0], new_head[1]) or new_head in self.tail[1:]:
if not PharmaScreen.is_drawable(new_head[0], new_head[1]) or new_head in self.tail[1:]:
self.has_lost = True
return False

Expand Down Expand Up @@ -94,7 +94,7 @@ def update_apple(self):
avaiable_cells = []
for x in range(48):
for y in range(48):
if PharmaScreen.is_drawable(None, x, y) and (x, y) not in self.tail :
if PharmaScreen.is_drawable(x, y) and (x, y) not in self.tail :
avaiable_cells.append((x, y))
self.apple = random.choice(avaiable_cells)
return True
Expand Down