-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsimulation.py
75 lines (61 loc) · 2.43 KB
/
simulation.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
from typing import Any, Tuple
from abc import ABC, abstractmethod
import numpy as np
import pygame
class InitialStateRule(ABC):
@abstractmethod
def rule(self, size: Tuple[int, int]) -> np.ndarray:
pass
class UpdateRule(ABC):
@abstractmethod
def update(self, current_state: np.ndarray) -> np.ndarray:
pass
class RandomInit(InitialStateRule):
def __init__(self, p: float = 0.5) -> None:
self.p = p
def rule(self, size) -> np.ndarray:
return np.random.choice([0, 1], size=size, p=[1 - self.p, self.p])
class ConwayUpdate(UpdateRule):
def update(self, current_state: np.ndarray) -> np.ndarray:
neighbors_count = sum(np.roll(np.roll(current_state, i, 0), j, 1)
for i in (-1, 0, 1) for j in (-1, 0, 1)
if (i != 0 or j != 0))
return (neighbors_count == 3) | (current_state & (neighbors_count == 2))
class SimulationModel:
def __init__(self,
size: Tuple[int, int],
init_rule: InitialStateRule,
sim_rule: UpdateRule
) -> None:
self.size = size
self.init_rule = init_rule
self.sim_rule = sim_rule
self.state = init_rule.rule(size)
def update(self) -> None:
self.state = self.sim_rule.update(self.state)
class SimulationView:
def __init__(self, window_size: Tuple[int, int]) -> None:
self.window_size = window_size
self.screen: pygame.surface.Surface = pygame.display.set_mode(window_size)
self.clock: pygame.time.Clock = pygame.time.Clock()
def draw(self, state: np.ndarray) -> None:
pygame.surfarray.blit_array(self.screen, state * 0xFFFFFF)
pygame.display.flip()
class SimulationController:
def __init__(self, model: SimulationModel, view: SimulationView) -> None:
self.model = model
self.view = view
pygame.init()
self.clock: pygame.time.Clock = pygame.time.Clock()
def handle_events(self) -> bool:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
return False # Sets is_running to False
return True
def update(self) -> None:
self.model.update()
self.view.draw(self.model.state)
self.clock.tick(10)
def close(self) -> None:
pygame.quit()