diff --git a/scripts/main_ui.py b/scripts/main_ui.py index 24d5386..950c40d 100644 --- a/scripts/main_ui.py +++ b/scripts/main_ui.py @@ -1,8 +1,6 @@ #!/usr/bin/env python3 -import pygame import random -import time from cellular_automaton.cellular_automaton import CellularAutomaton from cellular_automaton.ca_rule import Rule @@ -11,75 +9,9 @@ from cellular_automaton.ca_display import PyGameFor2D from cellular_automaton.ca_cell_state import CellState -class WorldGeneratorWindow: - def __init__(self, windows_size: list, cellular_automaton: CellularAutomaton): - self.window_size = windows_size - self.grid_size = self.window_size.copy() - self.grid_size[1] -= 20 - - pygame.init() - pygame.display.set_caption("World Generator") - self.screen = pygame.display.set_mode(self.window_size) - - self._cellular_automaton = cellular_automaton - self.font = pygame.font.SysFont("monospace", 15) - - def set_cellular_automaton(self, cellular_automaton): - self._cellular_automaton = cellular_automaton - - def _display_cellular_automaton(self): - grid_dimension = self._cellular_automaton.grid.get_dimension() - - cell_size = [x / y for x, y in zip(self.grid_size, grid_dimension)] - - surfaces_to_update = [] - for cell in self._cellular_automaton.grid.get_cells().values(): - if not cell.is_set_for_redrawing(): - continue - cell_coordinate = cell.coordinate - status = cell.get_status_for_iteration(self._cellular_automaton.get_iteration_index()) - if status is None: - status = [0] - red = 0 - if status[0] >= 10: - red = 255 - cell_color = [red, 0, 0] - surface_pos = [x * y for x, y in zip(cell_size, cell_coordinate)] - surface_pos[1] += 20 - surfaces_to_update.append(self.screen.fill(cell_color, (surface_pos, cell_size))) - cell.release_from_redraw() - pygame.display.update(surfaces_to_update) - - def main_loop(self): - running = True - - while running: - time_ca_start = time.time() - self._cellular_automaton.evolve_x_times(10) - time_ca_end = time.time() - self._display_cellular_automaton() - time_ds_end = time.time() - self._print_process_duration(time_ca_end, time_ca_start, time_ds_end) - - for event in pygame.event.get(): - if event.type == pygame.QUIT: - running = False - - 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._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) - pygame.display.update(update_rect) - - class TestRule(Rule): def evolve_cell(self, cell, neighbors, iteration_index): active = False - last_iteration = iteration_index - 1 if cell.state is None: rand = random.randrange(0, 101, 1) if rand <= 99: @@ -89,8 +21,8 @@ class TestRule(Rule): cell.set_for_redraw() active = True elif len(neighbors) == 8: - left_neighbour_status = neighbors[3].state.get_status_of_iteration(last_iteration) - active = cell.state.set_status_of_iteration(left_neighbour_status, iteration_index) + left_neighbour_state = neighbors[3].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() return active @@ -108,7 +40,8 @@ class MyStatus(CellState): if __name__ == "__main__": + random.seed(1000) rule = TestRule() - ca = CellularAutomaton([400, 400], MooreNeighborhood(EdgeRule.IGNORE_EDGE_CELLS), rule) + ca = CellularAutomaton([500, 500], MooreNeighborhood(EdgeRule.IGNORE_EDGE_CELLS), rule) ca_window = PyGameFor2D([1000, 730], ca) ca_window.main_loop() diff --git a/src/cellular_automaton/ca_cell.py b/src/cellular_automaton/ca_cell.py index f1899e6..4438133 100644 --- a/src/cellular_automaton/ca_cell.py +++ b/src/cellular_automaton/ca_cell.py @@ -20,3 +20,6 @@ class Cell: def release_from_redraw(self): self._dirty = False + + def __str__(self): + return self.name diff --git a/src/cellular_automaton/ca_grid.py b/src/cellular_automaton/ca_grid.py index e2b6b6b..ad08cd8 100644 --- a/src/cellular_automaton/ca_grid.py +++ b/src/cellular_automaton/ca_grid.py @@ -31,19 +31,11 @@ class Grid: :param cells: A list of Cell objects, that shall be considered in the next evolution cycle. """ for cell in cells: - self._active_cells[cell.name] = cells + self._active_cells[cell.name] = cell def get_cell_and_neighbors(self, cell_name): cell = self._cells[cell_name] - neighbours = cell.neighbours - neighbour_objects = [] - for ne in neighbours: - neighbour_objects.append(self._cells[ne]) - - return [cell, neighbour_objects] - - def get_cell_by_coordinate(self, coordinate): - return self._cells[_join_coordinate(coordinate)] + return [cell, cell.neighbours] def get_dimension(self): return self._dimension @@ -76,20 +68,14 @@ class Grid: new_cod = coordinate + [cell_index] recursion_method(dimension_index + 1, new_cod) - def _set_cell_neighbours(self, dimension_index=0, coordinate=None): - """ Recursively steps down the dimensions to get the string instances for each cells neighbours. - :param dimension_index: The index indicating which dimension is currently traversed. - :param coordinate: The coordinate generated so far. - (each recursion adds one dimension to the coordinate. - """ - coordinate = _instantiate_coordinate_if_necessary(coordinate) + def _set_cell_neighbours(self): + 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))) - try: - self._recursive_step_down_dimensions(coordinate.copy(), dimension_index, self._set_cell_neighbours) - except IndexError: - neighbours_coordinates = self._neighborhood.calculate_cell_neighbor_coordinates(coordinate, self._dimension) - neighbour_names = [self._cells[_join_coordinate(nc)].name for nc in neighbours_coordinates] - self._cells[_join_coordinate(coordinate)].set_neighbours(neighbour_names) + def _get_cell_by_coordinate(self, coordinate): + return self._cells[_join_coordinate(coordinate)] def _instantiate_coordinate_if_necessary(coordinate): diff --git a/src/cellular_automaton/cellular_automaton.py b/src/cellular_automaton/cellular_automaton.py index b433bfe..d77fb0e 100644 --- a/src/cellular_automaton/cellular_automaton.py +++ b/src/cellular_automaton/cellular_automaton.py @@ -46,17 +46,16 @@ class CellularAutomaton: return False def _evolve_all_active_cells(self): - active_cells = self.grid.get_active_cell_names() + active_cells = self.grid.get_active_cells() self.grid.clear_active_cells() - self._evolve_cells(active_cells) + self._evolve_cells(active_cells.values()) def _is_evolution_finished(self): return len(self.grid.get_active_cell_names()) == 0 - def _evolve_cells(self, cell_names: list): - for cell_name in cell_names: - cell_info = self.grid.get_cell_and_neighbors(cell_name) - active = self.evolution_rule.evolve_cell(cell_info[0], cell_info[1], self.iteration) + def _evolve_cells(self, cells: list): + for cell in cells: + active = self.evolution_rule.evolve_cell(cell, cell.neighbours, self.iteration) if active: - self.grid.set_cells_active([cell_info[0]] + cell_info[1]) + self.grid.set_cells_active([cell] + cell.neighbours)