From 5d86bd10cf0a302b80b4fb48cc4b92e2e6eea3e6 Mon Sep 17 00:00:00 2001 From: Richard Feistenauer Date: Sat, 5 Jan 2019 15:12:07 +0100 Subject: [PATCH] cell is now pure data class --- scripts/main_ui.py | 9 ++++---- src/cellular_automaton/ca_cell.py | 22 ++----------------- src/cellular_automaton/ca_display.py | 23 ++++++++++---------- src/cellular_automaton/ca_grid.py | 2 +- src/cellular_automaton/ca_rule.py | 3 +-- src/cellular_automaton/cellular_automaton.py | 2 +- 6 files changed, 22 insertions(+), 39 deletions(-) diff --git a/scripts/main_ui.py b/scripts/main_ui.py index e1f663b..0d5b4ba 100644 --- a/scripts/main_ui.py +++ b/scripts/main_ui.py @@ -10,21 +10,22 @@ from cellular_automaton.ca_cell_state import CellState class TestRule(Rule): - def evolve_cell(self, cell, neighbors, iteration_index): + def evolve_cell(self, cell, iteration_index): active = False + neighbors = cell.neighbours if cell.state is None: rand = random.randrange(0, 101, 1) if rand <= 99: cell.state = MyStatus(0) else: cell.state = MyStatus(1) - cell.set_for_redraw() + cell.is_set_for_redraw = True active = True elif len(neighbors) == 8: 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) if active: - cell.set_for_redraw() + cell.is_set_for_redraw = True return active @@ -43,5 +44,5 @@ if __name__ == "__main__": random.seed(1000) rule = TestRule() 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() diff --git a/src/cellular_automaton/ca_cell.py b/src/cellular_automaton/ca_cell.py index 4438133..9a610f5 100644 --- a/src/cellular_automaton/ca_cell.py +++ b/src/cellular_automaton/ca_cell.py @@ -1,25 +1,7 @@ class Cell: - def __init__(self, name: str, coordinate: list): + def __init__(self, name, coordinate: list): self.name = name self.coordinate = coordinate self.neighbours = [] self.state = None - self._dirty = 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 + self.is_set_for_redraw = False diff --git a/src/cellular_automaton/ca_display.py b/src/cellular_automaton/ca_display.py index 4e71171..23c5f70 100644 --- a/src/cellular_automaton/ca_display.py +++ b/src/cellular_automaton/ca_display.py @@ -26,12 +26,12 @@ class DisplayFor2D: self._surfaces_to_update = [] 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()) surface_pos = self._calculate_cell_position(cell) 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))) - cell.release_from_redraw() + cell.is_set_for_redraw = False def _calculate_cell_position(self, cell): return list(map(operator.mul, self.cell_size, cell.coordinate)) @@ -42,25 +42,26 @@ class DisplayFor2D: class PyGameFor2D: - def __init__(self, windows_size: list, cellular_automaton: CellularAutomaton): - self.window_size = windows_size + def __init__(self, windows_size: list, cellular_automaton: CellularAutomaton, ca_iterations_per_draw): + self._window_size = windows_size self._cellular_automaton = cellular_automaton + self._ca_steps_per_draw = ca_iterations_per_draw pygame.init() pygame.display.set_caption("Cellular Automaton") - self.screen = pygame.display.set_mode(self.window_size) - self.font = pygame.font.SysFont("monospace", 15) + self._screen = pygame.display.set_mode(self._window_size) + 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): - 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((310, 5), "Display: " + "{0:.4f}".format(time_ds_end - time_ca_end) + "s") def _write_text(self, pos, text, color=(0, 255, 0)): - label = self.font.render(text, 1, color) - update_rect = self.screen.blit(label, pos) + label = self._font.render(text, 1, color) + update_rect = self._screen.blit(label, pos) pygame.display.update(update_rect) def main_loop(self): @@ -68,7 +69,7 @@ class PyGameFor2D: while running: 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() self.ca_display._redraw_cellular_automaton() time_ds_end = time.time() diff --git a/src/cellular_automaton/ca_grid.py b/src/cellular_automaton/ca_grid.py index ad08cd8..d87bf39 100644 --- a/src/cellular_automaton/ca_grid.py +++ b/src/cellular_automaton/ca_grid.py @@ -72,7 +72,7 @@ class Grid: for cell in self._cells.values(): neighbours_coordinates = self._neighborhood.calculate_cell_neighbor_coordinates(cell.coordinate, 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): return self._cells[_join_coordinate(coordinate)] diff --git a/src/cellular_automaton/ca_rule.py b/src/cellular_automaton/ca_rule.py index 21c9801..7016ebb 100644 --- a/src/cellular_automaton/ca_rule.py +++ b/src/cellular_automaton/ca_rule.py @@ -7,10 +7,9 @@ class Rule: pass @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'. :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. :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. diff --git a/src/cellular_automaton/cellular_automaton.py b/src/cellular_automaton/cellular_automaton.py index d77fb0e..9aaa59c 100644 --- a/src/cellular_automaton/cellular_automaton.py +++ b/src/cellular_automaton/cellular_automaton.py @@ -55,7 +55,7 @@ class CellularAutomaton: def _evolve_cells(self, cells: list): 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: self.grid.set_cells_active([cell] + cell.neighbours)