cell is now pure data class
This commit is contained in:
parent
93c78f0aa5
commit
5d86bd10cf
@ -10,21 +10,22 @@ from cellular_automaton.ca_cell_state import CellState
|
|||||||
|
|
||||||
|
|
||||||
class TestRule(Rule):
|
class TestRule(Rule):
|
||||||
def evolve_cell(self, cell, neighbors, iteration_index):
|
def evolve_cell(self, cell, iteration_index):
|
||||||
active = False
|
active = False
|
||||||
|
neighbors = cell.neighbours
|
||||||
if cell.state is None:
|
if cell.state is None:
|
||||||
rand = random.randrange(0, 101, 1)
|
rand = random.randrange(0, 101, 1)
|
||||||
if rand <= 99:
|
if rand <= 99:
|
||||||
cell.state = MyStatus(0)
|
cell.state = MyStatus(0)
|
||||||
else:
|
else:
|
||||||
cell.state = MyStatus(1)
|
cell.state = MyStatus(1)
|
||||||
cell.set_for_redraw()
|
cell.is_set_for_redraw = True
|
||||||
active = True
|
active = True
|
||||||
elif len(neighbors) == 8:
|
elif len(neighbors) == 8:
|
||||||
left_neighbour_state = neighbors[0].state.get_status_of_iteration(iteration_index - 1)
|
left_neighbour_state = neighbors[0].state.get_status_of_iteration(iteration_index - 1)
|
||||||
active = cell.state.set_status_of_iteration(left_neighbour_state, iteration_index)
|
active = cell.state.set_status_of_iteration(left_neighbour_state, iteration_index)
|
||||||
if active:
|
if active:
|
||||||
cell.set_for_redraw()
|
cell.is_set_for_redraw = True
|
||||||
return active
|
return active
|
||||||
|
|
||||||
|
|
||||||
@ -43,5 +44,5 @@ if __name__ == "__main__":
|
|||||||
random.seed(1000)
|
random.seed(1000)
|
||||||
rule = TestRule()
|
rule = TestRule()
|
||||||
ca = CellularAutomaton([400, 400], MooreNeighborhood(EdgeRule.FIRST_AND_LAST_CELL_OF_DIMENSION_ARE_NEIGHBORS), rule)
|
ca = CellularAutomaton([400, 400], MooreNeighborhood(EdgeRule.FIRST_AND_LAST_CELL_OF_DIMENSION_ARE_NEIGHBORS), rule)
|
||||||
ca_window = PyGameFor2D([1000, 800], ca)
|
ca_window = PyGameFor2D([1000, 800], ca, 5)
|
||||||
ca_window.main_loop()
|
ca_window.main_loop()
|
||||||
|
@ -1,25 +1,7 @@
|
|||||||
class Cell:
|
class Cell:
|
||||||
def __init__(self, name: str, coordinate: list):
|
def __init__(self, name, coordinate: list):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.coordinate = coordinate
|
self.coordinate = coordinate
|
||||||
self.neighbours = []
|
self.neighbours = []
|
||||||
self.state = None
|
self.state = None
|
||||||
self._dirty = False
|
self.is_set_for_redraw = False
|
||||||
|
|
||||||
def set_neighbours(self, neighbours: list):
|
|
||||||
""" Set new cells as neighbour of this cell.
|
|
||||||
:param neighbours: A List of Cell names.
|
|
||||||
"""
|
|
||||||
self.neighbours = neighbours
|
|
||||||
|
|
||||||
def is_set_for_redrawing(self):
|
|
||||||
return self._dirty
|
|
||||||
|
|
||||||
def set_for_redraw(self):
|
|
||||||
self._dirty = True
|
|
||||||
|
|
||||||
def release_from_redraw(self):
|
|
||||||
self._dirty = False
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.name
|
|
||||||
|
@ -26,12 +26,12 @@ class DisplayFor2D:
|
|||||||
self._surfaces_to_update = []
|
self._surfaces_to_update = []
|
||||||
|
|
||||||
def _redraw_cell(self, cell):
|
def _redraw_cell(self, cell):
|
||||||
if cell.is_set_for_redrawing():
|
if cell.is_set_for_redraw:
|
||||||
cell_color = cell.state.get_state_draw_color(self._cellular_automaton.get_iteration_index())
|
cell_color = cell.state.get_state_draw_color(self._cellular_automaton.get_iteration_index())
|
||||||
surface_pos = self._calculate_cell_position(cell)
|
surface_pos = self._calculate_cell_position(cell)
|
||||||
surface_pos = list(map(operator.add, surface_pos, self.grid_pos))
|
surface_pos = list(map(operator.add, surface_pos, self.grid_pos))
|
||||||
self._surfaces_to_update.append(self.screen.fill(cell_color, (surface_pos, self.cell_size)))
|
self._surfaces_to_update.append(self.screen.fill(cell_color, (surface_pos, self.cell_size)))
|
||||||
cell.release_from_redraw()
|
cell.is_set_for_redraw = False
|
||||||
|
|
||||||
def _calculate_cell_position(self, cell):
|
def _calculate_cell_position(self, cell):
|
||||||
return list(map(operator.mul, self.cell_size, cell.coordinate))
|
return list(map(operator.mul, self.cell_size, cell.coordinate))
|
||||||
@ -42,25 +42,26 @@ class DisplayFor2D:
|
|||||||
|
|
||||||
|
|
||||||
class PyGameFor2D:
|
class PyGameFor2D:
|
||||||
def __init__(self, windows_size: list, cellular_automaton: CellularAutomaton):
|
def __init__(self, windows_size: list, cellular_automaton: CellularAutomaton, ca_iterations_per_draw):
|
||||||
self.window_size = windows_size
|
self._window_size = windows_size
|
||||||
self._cellular_automaton = cellular_automaton
|
self._cellular_automaton = cellular_automaton
|
||||||
|
self._ca_steps_per_draw = ca_iterations_per_draw
|
||||||
|
|
||||||
pygame.init()
|
pygame.init()
|
||||||
pygame.display.set_caption("Cellular Automaton")
|
pygame.display.set_caption("Cellular Automaton")
|
||||||
self.screen = pygame.display.set_mode(self.window_size)
|
self._screen = pygame.display.set_mode(self._window_size)
|
||||||
self.font = pygame.font.SysFont("monospace", 15)
|
self._font = pygame.font.SysFont("monospace", 15)
|
||||||
|
|
||||||
self.ca_display = DisplayFor2D([0, 30, windows_size[0], windows_size[1]-30], cellular_automaton, self.screen)
|
self.ca_display = DisplayFor2D([0, 30, windows_size[0], windows_size[1]-30], cellular_automaton, self._screen)
|
||||||
|
|
||||||
def _print_process_duration(self, time_ca_end, time_ca_start, time_ds_end):
|
def _print_process_duration(self, time_ca_end, time_ca_start, time_ds_end):
|
||||||
self.screen.fill([0, 0, 0], ((0, 0), (self.window_size[0], 30)))
|
self._screen.fill([0, 0, 0], ((0, 0), (self._window_size[0], 30)))
|
||||||
self._write_text((10, 5), "CA: " + "{0:.4f}".format(time_ca_end - time_ca_start) + "s")
|
self._write_text((10, 5), "CA: " + "{0:.4f}".format(time_ca_end - time_ca_start) + "s")
|
||||||
self._write_text((310, 5), "Display: " + "{0:.4f}".format(time_ds_end - time_ca_end) + "s")
|
self._write_text((310, 5), "Display: " + "{0:.4f}".format(time_ds_end - time_ca_end) + "s")
|
||||||
|
|
||||||
def _write_text(self, pos, text, color=(0, 255, 0)):
|
def _write_text(self, pos, text, color=(0, 255, 0)):
|
||||||
label = self.font.render(text, 1, color)
|
label = self._font.render(text, 1, color)
|
||||||
update_rect = self.screen.blit(label, pos)
|
update_rect = self._screen.blit(label, pos)
|
||||||
pygame.display.update(update_rect)
|
pygame.display.update(update_rect)
|
||||||
|
|
||||||
def main_loop(self):
|
def main_loop(self):
|
||||||
@ -68,7 +69,7 @@ class PyGameFor2D:
|
|||||||
|
|
||||||
while running:
|
while running:
|
||||||
time_ca_start = time.time()
|
time_ca_start = time.time()
|
||||||
self._cellular_automaton.evolve_x_times(5)
|
self._cellular_automaton.evolve_x_times(self._ca_steps_per_draw)
|
||||||
time_ca_end = time.time()
|
time_ca_end = time.time()
|
||||||
self.ca_display._redraw_cellular_automaton()
|
self.ca_display._redraw_cellular_automaton()
|
||||||
time_ds_end = time.time()
|
time_ds_end = time.time()
|
||||||
|
@ -72,7 +72,7 @@ class Grid:
|
|||||||
for cell in self._cells.values():
|
for cell in self._cells.values():
|
||||||
neighbours_coordinates = self._neighborhood.calculate_cell_neighbor_coordinates(cell.coordinate,
|
neighbours_coordinates = self._neighborhood.calculate_cell_neighbor_coordinates(cell.coordinate,
|
||||||
self._dimension)
|
self._dimension)
|
||||||
cell.set_neighbours(list(map(self._get_cell_by_coordinate, neighbours_coordinates)))
|
cell.neighbours = list(map(self._get_cell_by_coordinate, neighbours_coordinates))
|
||||||
|
|
||||||
def _get_cell_by_coordinate(self, coordinate):
|
def _get_cell_by_coordinate(self, coordinate):
|
||||||
return self._cells[_join_coordinate(coordinate)]
|
return self._cells[_join_coordinate(coordinate)]
|
||||||
|
@ -7,10 +7,9 @@ class Rule:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def evolve_cell(self, cell: Cell, neighbours: list, iteration_index: int):
|
def evolve_cell(self, cell: Cell, iteration_index: int):
|
||||||
""" Calculates and sets new state of 'cell'.
|
""" Calculates and sets new state of 'cell'.
|
||||||
:param cell: The cell to calculate new state for.
|
:param cell: The cell to calculate new state for.
|
||||||
:param neighbours: The neighbour cells of this cell.
|
|
||||||
:param iteration_index: The current iteration index, to choose the correct state.
|
:param iteration_index: The current iteration index, to choose the correct state.
|
||||||
:return: True if state changed, False if not.
|
:return: True if state changed, False if not.
|
||||||
A cells evolution will only be called if it or at least one of its neighbours has changed last iteration cycle.
|
A cells evolution will only be called if it or at least one of its neighbours has changed last iteration cycle.
|
||||||
|
@ -55,7 +55,7 @@ class CellularAutomaton:
|
|||||||
|
|
||||||
def _evolve_cells(self, cells: list):
|
def _evolve_cells(self, cells: list):
|
||||||
for cell in cells:
|
for cell in cells:
|
||||||
active = self.evolution_rule.evolve_cell(cell, cell.neighbours, self.iteration)
|
active = self.evolution_rule.evolve_cell(cell, self.iteration)
|
||||||
|
|
||||||
if active:
|
if active:
|
||||||
self.grid.set_cells_active([cell] + cell.neighbours)
|
self.grid.set_cells_active([cell] + cell.neighbours)
|
||||||
|
Loading…
Reference in New Issue
Block a user