added some extra typehinting
This commit is contained in:
63
conway.py
63
conway.py
@@ -3,6 +3,8 @@ from collections import namedtuple
|
|||||||
from math import floor
|
from math import floor
|
||||||
import pygame
|
import pygame
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
|
||||||
CellStates = Enum("CellStates", ("ALIVE", "DEAD")) #using enum for possible iterations on cellular automata
|
CellStates = Enum("CellStates", ("ALIVE", "DEAD")) #using enum for possible iterations on cellular automata
|
||||||
XYPair = namedtuple("XYPair", "x y")
|
XYPair = namedtuple("XYPair", "x y")
|
||||||
@@ -38,48 +40,47 @@ class Cell:
|
|||||||
calculate_spacing(self.position.y, self.dimensions.y, padding.y))
|
calculate_spacing(self.position.y, self.dimensions.y, padding.y))
|
||||||
|
|
||||||
def __init__(self, position: XYPair, dimensions: XYPair, render_info: Render_Info, state: CellStates=CellStates.DEAD) -> None:
|
def __init__(self, position: XYPair, dimensions: XYPair, render_info: Render_Info, state: CellStates=CellStates.DEAD) -> None:
|
||||||
self.crowding_number = 0
|
self.crowding_number: int = 0
|
||||||
|
self.position: XYPair = position
|
||||||
self.position = position
|
self.dimensions: XYPair = dimensions
|
||||||
self.dimensions = dimensions
|
self.state: CellStates = state
|
||||||
self.state = state
|
self.click_state: CellStates = None
|
||||||
self.click_state = None
|
self.screen_position: XYPair = self.calculate_screen_position(render_info)
|
||||||
self.screen_position = self.calculate_screen_position(render_info)
|
self.image: pygame.Surface = pygame.Surface(self.dimensions)
|
||||||
self.image = pygame.Surface(self.dimensions)
|
|
||||||
self.image.fill(Colors.GRAY.value)
|
self.image.fill(Colors.GRAY.value)
|
||||||
self.rect = pygame.Rect(self.screen_position.x,
|
self.rect = pygame.Rect(self.screen_position.x,
|
||||||
self.screen_position.y,
|
self.screen_position.y,
|
||||||
self.dimensions.x,
|
self.dimensions.x,
|
||||||
self.dimensions.y)
|
self.dimensions.y)
|
||||||
|
|
||||||
def set_state(self, state: CellStates):
|
def set_state(self, state: CellStates) -> None:
|
||||||
self.state = state
|
self.state = state
|
||||||
self.image.fill(self.PALETTE_MAP[self.state])
|
self.image.fill(self.PALETTE_MAP[self.state])
|
||||||
|
|
||||||
def set_crowding_number(self, n: int):
|
def set_crowding_number(self, n: int) -> None:
|
||||||
self.crowding_number = n
|
self.crowding_number = n
|
||||||
|
|
||||||
def update_state(self):
|
def update_state(self) -> None:
|
||||||
if self.crowding_number < 2 or self.crowding_number >= 4:
|
if self.crowding_number < 2 or self.crowding_number >= 4:
|
||||||
self.set_state(CellStates.DEAD)
|
self.set_state(CellStates.DEAD)
|
||||||
if self.crowding_number == 3:
|
if self.crowding_number == 3:
|
||||||
self.set_state(CellStates.ALIVE)
|
self.set_state(CellStates.ALIVE)
|
||||||
|
|
||||||
def draw(self, screen):
|
def draw(self, screen: pygame.Surface) -> None:
|
||||||
screen.blit(self.image, self.rect)
|
screen.blit(self.image, self.rect)
|
||||||
|
|
||||||
class Board:
|
class Board:
|
||||||
|
|
||||||
def __init__(self, dimensions: XYPair, evolution_time, render_info: Render_Info):
|
def __init__(self, dimensions: XYPair, evolution_time, render_info: Render_Info) -> None:
|
||||||
screen_dimenions = render_info.screen_dimensions
|
screen_dimenions: XYPair = render_info.screen_dimensions
|
||||||
self.evolution_time = evolution_time
|
self.evolution_time: int = evolution_time
|
||||||
self.clock = 0
|
self.clock: int = 0
|
||||||
padding = render_info.padding
|
padding: XYPair = render_info.padding
|
||||||
#calculate cell dimensions once instead of x*y times
|
#calculate cell dimensions once instead of x*y times
|
||||||
cell_dimensions = XYPair(screen_dimenions.x/dimensions.x - 2*padding.x,
|
cell_dimensions = XYPair(screen_dimenions.x/dimensions.x - 2*padding.x,
|
||||||
screen_dimenions.y/dimensions.y - 2*padding.y)
|
screen_dimenions.y/dimensions.y - 2*padding.y)
|
||||||
self.dimensions = dimensions
|
self.dimensions: XYPair = dimensions
|
||||||
self.matrix = [[Cell(XYPair(x,y), cell_dimensions, render_info) for x in range(dimensions.x)] for y in range(dimensions.y)]
|
self.matrix: List[List[Cell]] = [[Cell(XYPair(x,y), cell_dimensions, render_info) for x in range(dimensions.x)] for y in range(dimensions.y)]
|
||||||
|
|
||||||
def normalize_submatrix_point(self, p: XYPair) -> XYPair:
|
def normalize_submatrix_point(self, p: XYPair) -> XYPair:
|
||||||
|
|
||||||
@@ -92,12 +93,12 @@ class Board:
|
|||||||
|
|
||||||
return XYPair(normalize(p.x, self.dimensions.x), normalize(p.y, self.dimensions.y))
|
return XYPair(normalize(p.x, self.dimensions.x), normalize(p.y, self.dimensions.y))
|
||||||
|
|
||||||
def get_submatrix(self, center: XYPair, extents: XYPair):
|
def get_submatrix(self, center: XYPair, extents: XYPair) -> List[List[Cell]]:
|
||||||
start_point = self.normalize_submatrix_point(XYPair(center.x - extents.x, center.y - extents.y))
|
start_point = self.normalize_submatrix_point(XYPair(center.x - extents.x, center.y - extents.y))
|
||||||
end_point = self.normalize_submatrix_point(XYPair(center.x + extents.x, center.y + extents.y))
|
end_point = self.normalize_submatrix_point(XYPair(center.x + extents.x, center.y + extents.y))
|
||||||
return [row[start_point.x:end_point.x+1] for row in self.matrix[start_point.y:end_point.y+1]]
|
return [row[start_point.x:end_point.x+1] for row in self.matrix[start_point.y:end_point.y+1]]
|
||||||
|
|
||||||
def calculate_crowding_number(self, center: XYPair, extents: XYPair):
|
def calculate_crowding_number(self, center: XYPair, extents: XYPair) -> int:
|
||||||
submatrix = self.get_submatrix(center, extents)
|
submatrix = self.get_submatrix(center, extents)
|
||||||
#flattened_submatrix removes the center point because it does not contribute to the crowding number
|
#flattened_submatrix removes the center point because it does not contribute to the crowding number
|
||||||
#if syntax is confusing, it just unrolls the 2d list and removes the cell in the center
|
#if syntax is confusing, it just unrolls the 2d list and removes the cell in the center
|
||||||
@@ -105,36 +106,36 @@ class Board:
|
|||||||
living_cells = map(lambda cell: cell.state == CellStates.ALIVE, flattened_submatrix)
|
living_cells = map(lambda cell: cell.state == CellStates.ALIVE, flattened_submatrix)
|
||||||
return sum(living_cells)
|
return sum(living_cells)
|
||||||
|
|
||||||
def fill_crowding(self):
|
def fill_crowding(self) -> None:
|
||||||
for row in self.matrix:
|
for row in self.matrix:
|
||||||
for cell in row:
|
for cell in row:
|
||||||
cell.set_crowding_number(
|
cell.set_crowding_number(
|
||||||
self.calculate_crowding_number(cell.position, XYPair(1,1))
|
self.calculate_crowding_number(cell.position, XYPair(1,1))
|
||||||
)
|
)
|
||||||
|
|
||||||
def evolve_state(self):
|
def evolve_state(self) -> None:
|
||||||
#calculate crowding numbers before updating any state, otherwise you'll be unhappy
|
#calculate crowding numbers before updating any state, otherwise you'll be unhappy
|
||||||
self.fill_crowding()
|
self.fill_crowding()
|
||||||
for row in self.matrix:
|
for row in self.matrix:
|
||||||
for cell in row:
|
for cell in row:
|
||||||
cell.update_state()
|
cell.update_state()
|
||||||
|
|
||||||
def set_state(self, p: XYPair, state: CellStates):
|
def set_state(self, p: XYPair, state: CellStates) -> None:
|
||||||
self.matrix[p.y][p.x].set_state(state)
|
self.matrix[p.y][p.x].set_state(state)
|
||||||
|
|
||||||
def draw(self, screen):
|
def draw(self, screen: pygame.Surface) -> None:
|
||||||
for row in self.matrix:
|
for row in self.matrix:
|
||||||
for cell in row:
|
for cell in row:
|
||||||
cell.draw(screen)
|
cell.draw(screen)
|
||||||
|
|
||||||
def tick_clock(self, dt):
|
def tick_clock(self, dt: int) -> None:
|
||||||
self.clock += dt
|
self.clock += dt
|
||||||
if self.clock >= self.evolution_time:
|
if self.clock >= self.evolution_time:
|
||||||
self.evolve_state()
|
self.evolve_state()
|
||||||
self.clock = 0
|
self.clock = 0
|
||||||
|
|
||||||
def handle_click(self, mouse_pos, render_info):
|
def handle_click(self, mouse_pos, render_info: Render_Info) -> None:
|
||||||
|
|
||||||
def pixel_to_index(x, w, p):
|
def pixel_to_index(x, w, p):
|
||||||
return floor((x - p)/(w + 2*p))
|
return floor((x - p)/(w + 2*p))
|
||||||
|
|
||||||
@@ -158,15 +159,15 @@ class Board:
|
|||||||
self.matrix[y][x].set_state(self.click_state)
|
self.matrix[y][x].set_state(self.click_state)
|
||||||
|
|
||||||
|
|
||||||
def reset_click(self):
|
def reset_click(self) -> None:
|
||||||
self.click_state = None
|
self.click_state = None
|
||||||
|
|
||||||
def reset(self):
|
def reset(self) -> None:
|
||||||
for row in self.matrix:
|
for row in self.matrix:
|
||||||
for cell in row:
|
for cell in row:
|
||||||
cell.set_state(CellStates.DEAD)
|
cell.set_state(CellStates.DEAD)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self) -> None:
|
||||||
lines = []
|
lines = []
|
||||||
str_buffer = ''
|
str_buffer = ''
|
||||||
lines.append('-'*(self.dimensions.x+2))
|
lines.append('-'*(self.dimensions.x+2))
|
||||||
|
|||||||
Reference in New Issue
Block a user