working fast cellular automaton
This commit is contained in:
parent
390c95df30
commit
bad67211ec
@ -2,64 +2,96 @@
|
|||||||
|
|
||||||
import pygame
|
import pygame
|
||||||
import random
|
import random
|
||||||
|
import time
|
||||||
|
|
||||||
from cellular_automaton.cellular_automaton import CellularAutomaton
|
from cellular_automaton.cellular_automaton import CellularAutomaton
|
||||||
from cellular_automaton.ca_cell import CACell
|
from cellular_automaton.ca_rule import Rule
|
||||||
from cellular_automaton.ca_grid import CAGrid
|
from cellular_automaton.ca_neighborhood import MooreNeighborhood, EdgeRule
|
||||||
from cellular_automaton.ca_rule import CARule
|
|
||||||
|
|
||||||
|
|
||||||
class WorldGeneratorWindow:
|
class WorldGeneratorWindow:
|
||||||
def __init__(self, windows_size):
|
def __init__(self, windows_size: list, cellular_automaton: CellularAutomaton):
|
||||||
self.window_size = windows_size
|
self.window_size = windows_size
|
||||||
|
self.grid_size = self.window_size.copy()
|
||||||
|
self.grid_size[1] -= 20
|
||||||
|
|
||||||
pygame.init()
|
pygame.init()
|
||||||
pygame.display.set_caption("World Generator")
|
pygame.display.set_caption("World Generator")
|
||||||
pygame.display.set_mode(self.window_size)
|
self.screen = pygame.display.set_mode(self.grid_size)
|
||||||
|
|
||||||
def display_cellular_automaton(self, cellular_automaton_instance):
|
self._cellular_automaton = cellular_automaton
|
||||||
pass
|
self.font = pygame.font.SysFont("monospace", 15)
|
||||||
|
|
||||||
|
def set_cellular_automaton(self, cellular_automaton):
|
||||||
|
self._cellular_automaton = cellular_automaton
|
||||||
|
|
||||||
def main():
|
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_active_cells().values():
|
||||||
|
if not cell.dirty:
|
||||||
|
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)))
|
||||||
|
pygame.display.update(surfaces_to_update)
|
||||||
|
|
||||||
|
def main_loop(self):
|
||||||
running = True
|
running = True
|
||||||
pygame.init()
|
|
||||||
pygame.display.set_caption("minimal program")
|
|
||||||
|
|
||||||
screen = pygame.display.set_mode((1000, 730))
|
|
||||||
image = pygame.image.load("../images/map.png")
|
|
||||||
screen.blit(image, (0, 0))
|
|
||||||
screen.set_at((50, 60), [50, 0, 0])
|
|
||||||
screen.set_at((50, 61), [50, 0, 0])
|
|
||||||
screen.set_at((51, 60), [50, 0, 0])
|
|
||||||
screen.set_at((51, 61), [50, 0, 0])
|
|
||||||
pygame.display.flip()
|
|
||||||
|
|
||||||
while running:
|
while running:
|
||||||
for x in range(0, 1000):
|
time_ca_start = time.time()
|
||||||
for y in range(0, 700):
|
self._cellular_automaton.evolve()
|
||||||
screen.set_at((x, y), [random.randrange(0, 255), random.randrange(0, 255), random.randrange(0, 255)])
|
time_ca_end = time.time()
|
||||||
pygame.display.flip()
|
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():
|
for event in pygame.event.get():
|
||||||
if event.type == pygame.QUIT:
|
if event.type == pygame.QUIT:
|
||||||
running = False
|
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")
|
||||||
|
|
||||||
class TestRule(CARule):
|
def _write_text(self, pos, text, color=(0, 255, 0)):
|
||||||
def evolve_cell(self, cell, neighbors):
|
label = self.font.render(text, 1, color)
|
||||||
if neighbors[1][0] != 0:
|
update_rect = self.screen.blit(label, pos)
|
||||||
return [1]
|
pygame.display.update(update_rect)
|
||||||
else:
|
|
||||||
return [0]
|
|
||||||
|
class TestRule(Rule):
|
||||||
|
def evolve_cell(self, cell, neighbors, iteration_index):
|
||||||
|
last_iteration = iteration_index - 1
|
||||||
|
if cell.get_status_for_iteration(last_iteration) is None:
|
||||||
|
rand = random.randrange(0, 101, 1)
|
||||||
|
if rand <= 99:
|
||||||
|
rand = 0
|
||||||
|
cell.set_status_for_iteration([rand], iteration_index)
|
||||||
|
cell.set_status_for_iteration([rand], iteration_index + 1)
|
||||||
|
if rand != 0:
|
||||||
|
cell.dirty = True
|
||||||
|
elif len(neighbors) == 8:
|
||||||
|
left_neighbour_status = neighbors[3].get_status_for_iteration(last_iteration)
|
||||||
|
cell.set_status_for_iteration(left_neighbour_status, iteration_index)
|
||||||
|
return cell.dirty
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
|
||||||
dim = [200, 500]
|
|
||||||
ca = CellularAutomaton(2)
|
|
||||||
|
|
||||||
new_grid = CAGrid(dim)
|
|
||||||
new_grid.set_cell_by_coordinate([1, 1], CACell([1]))
|
|
||||||
rule = TestRule()
|
rule = TestRule()
|
||||||
|
ca = CellularAutomaton([500, 500], MooreNeighborhood(EdgeRule.IGNORE_EDGE_CELLS), rule, thread_count=1)
|
||||||
|
ca_window = WorldGeneratorWindow([1000, 730], ca)
|
||||||
|
ca_window.main_loop()
|
||||||
|
@ -1,7 +1,26 @@
|
|||||||
class Cell:
|
class Cell:
|
||||||
def __init__(self, name: str):
|
def __init__(self, name: str, coordinate: list):
|
||||||
self.name = name
|
self.name = name
|
||||||
|
self.coordinate = coordinate
|
||||||
self.neighbours = []
|
self.neighbours = []
|
||||||
|
self._status = [None, None]
|
||||||
|
self.dirty = False
|
||||||
|
|
||||||
def set_neighbours(self, neighbours: list):
|
def set_neighbours(self, neighbours: list):
|
||||||
self.neighbours = neighbours
|
self.neighbours = neighbours
|
||||||
|
|
||||||
|
def set_status_for_iteration(self, new_status, iteration):
|
||||||
|
""" Will set the new status for Iteration.
|
||||||
|
:param new_status: The new status to set.
|
||||||
|
:param iteration: Uses the iteration index, to differ between current and next state.
|
||||||
|
"""
|
||||||
|
self._status[iteration % 2] = new_status
|
||||||
|
|
||||||
|
self.dirty = self._status[0] != self._status[1]
|
||||||
|
|
||||||
|
def get_status_for_iteration(self, iteration):
|
||||||
|
""" Will return the status for the iteration.
|
||||||
|
:param iteration: Uses the iteration index, to differ between current and next state.
|
||||||
|
:return The status for this iteration.
|
||||||
|
"""
|
||||||
|
return self._status[iteration % 2]
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
|
import sys
|
||||||
|
|
||||||
from cellular_automaton.ca_cell import Cell
|
from cellular_automaton.ca_cell import Cell
|
||||||
from cellular_automaton.ca_neighborhood import CellularAutomatonNeighborhood
|
from cellular_automaton.ca_neighborhood import Neighborhood
|
||||||
|
|
||||||
|
|
||||||
class Grid:
|
class Grid:
|
||||||
def __init__(self, dimension: list, neighborhood: CellularAutomatonNeighborhood):
|
def __init__(self, dimension: list, neighborhood: Neighborhood):
|
||||||
self._dimension = dimension
|
self._dimension = dimension
|
||||||
self._cells = {}
|
self._cells = {}
|
||||||
self._neighborhood = neighborhood
|
self._neighborhood = neighborhood
|
||||||
@ -11,15 +13,22 @@ class Grid:
|
|||||||
self._create_cells()
|
self._create_cells()
|
||||||
self._set_cell_neighbours()
|
self._set_cell_neighbours()
|
||||||
|
|
||||||
self._active_cells = {}
|
self._active_cells = self._cells.copy()
|
||||||
self.set_all_cells_active()
|
self._set_all_cells_active()
|
||||||
|
|
||||||
def set_all_cells_active(self):
|
def get_names_of_active_cells(self):
|
||||||
for cell_key in self._cells:
|
return list(self._active_cells.keys())
|
||||||
self._active_cells[cell_key] = 1
|
|
||||||
|
|
||||||
def get_active_cells(self):
|
def get_active_cells(self):
|
||||||
return self._active_cells.keys()
|
return self._active_cells
|
||||||
|
|
||||||
|
def clear_active_cells(self):
|
||||||
|
self._active_cells.clear()
|
||||||
|
|
||||||
|
def set_cell_and_neighbours_active(self, cell_info: list):
|
||||||
|
self._active_cells[cell_info[0].name] = cell_info[0]
|
||||||
|
for neighbour in cell_info[1]:
|
||||||
|
self._active_cells[neighbour.name] = neighbour
|
||||||
|
|
||||||
def get_cell_and_neighbors(self, cell_name):
|
def get_cell_and_neighbors(self, cell_name):
|
||||||
cell = self._cells[cell_name]
|
cell = self._cells[cell_name]
|
||||||
@ -30,6 +39,15 @@ class Grid:
|
|||||||
|
|
||||||
return [cell, neighbour_objects]
|
return [cell, neighbour_objects]
|
||||||
|
|
||||||
|
def get_cell_by_coordinate(self, coordinate):
|
||||||
|
return self._cells[_join_coordinate(coordinate)]
|
||||||
|
|
||||||
|
def get_dimension(self):
|
||||||
|
return self._dimension
|
||||||
|
|
||||||
|
def _set_all_cells_active(self):
|
||||||
|
for cell_key, cell in self._cells.items():
|
||||||
|
self._active_cells[cell_key] = cell
|
||||||
|
|
||||||
def _create_cells(self, dimension_index=0, coordinate=None):
|
def _create_cells(self, dimension_index=0, coordinate=None):
|
||||||
""" Recursively steps down the dimensions to create cells in n dimensions and adds them to a dict.
|
""" Recursively steps down the dimensions to create cells in n dimensions and adds them to a dict.
|
||||||
@ -37,13 +55,13 @@ class Grid:
|
|||||||
:param coordinate: The coordinate generated so far.
|
:param coordinate: The coordinate generated so far.
|
||||||
(each recursion adds one dimension to the coordinate.
|
(each recursion adds one dimension to the coordinate.
|
||||||
"""
|
"""
|
||||||
coordinate = self.instantiate_coordinate_if_necessary(coordinate)
|
coordinate = _instantiate_coordinate_if_necessary(coordinate)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self._recursive_step_down_dimensions(coordinate, dimension_index, self._create_cells)
|
self._recursive_step_down_dimensions(coordinate, dimension_index, self._create_cells)
|
||||||
except IndexError:
|
except IndexError:
|
||||||
coordinate_string = '-'.join(coordinate)
|
coordinate_string = _join_coordinate(coordinate)
|
||||||
self._cells[coordinate_string] = Cell(coordinate_string)
|
self._cells[coordinate_string] = Cell(coordinate_string, coordinate)
|
||||||
|
|
||||||
def _recursive_step_down_dimensions(self, coordinate, dimension_index, recursion_method):
|
def _recursive_step_down_dimensions(self, coordinate, dimension_index, recursion_method):
|
||||||
""" For the range of the current dimension, recalls the recursion method.
|
""" For the range of the current dimension, recalls the recursion method.
|
||||||
@ -52,14 +70,8 @@ class Grid:
|
|||||||
:param recursion_method: The method to call for recursion.
|
:param recursion_method: The method to call for recursion.
|
||||||
"""
|
"""
|
||||||
for cell_index in range(self._dimension[dimension_index]):
|
for cell_index in range(self._dimension[dimension_index]):
|
||||||
coordinate.append(cell_index)
|
new_cod = coordinate + [cell_index]
|
||||||
recursion_method(dimension_index + 1, coordinate.copy())
|
recursion_method(dimension_index + 1, new_cod)
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def instantiate_coordinate_if_necessary(coordinate):
|
|
||||||
if coordinate is None:
|
|
||||||
coordinate = []
|
|
||||||
return coordinate
|
|
||||||
|
|
||||||
def _set_cell_neighbours(self, dimension_index=0, coordinate=None):
|
def _set_cell_neighbours(self, dimension_index=0, coordinate=None):
|
||||||
""" Recursively steps down the dimensions to get the string instances for each cells neighbours.
|
""" Recursively steps down the dimensions to get the string instances for each cells neighbours.
|
||||||
@ -67,12 +79,30 @@ class Grid:
|
|||||||
:param coordinate: The coordinate generated so far.
|
:param coordinate: The coordinate generated so far.
|
||||||
(each recursion adds one dimension to the coordinate.
|
(each recursion adds one dimension to the coordinate.
|
||||||
"""
|
"""
|
||||||
coordinate = self.instantiate_coordinate_if_necessary(coordinate)
|
coordinate = _instantiate_coordinate_if_necessary(coordinate)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self._recursive_step_down_dimensions(coordinate, dimension_index, self._set_cell_neighbours)
|
self._recursive_step_down_dimensions(coordinate.copy(), dimension_index, self._set_cell_neighbours)
|
||||||
except IndexError:
|
except IndexError:
|
||||||
neighbours_coordinates = self._neighborhood.get_neighbor_coordinates(coordinate, self._dimension)
|
neighbours_coordinates = self._neighborhood.get_neighbor_coordinates(coordinate, self._dimension)
|
||||||
neighbour_names = [self._cells['-'.join(nc)].name for nc in neighbours_coordinates]
|
neighbour_names = [self._cells[_join_coordinate(nc)].name for nc in neighbours_coordinates]
|
||||||
self._cells['-'.join(coordinate)].set_neighbours(neighbour_names)
|
self._cells[_join_coordinate(coordinate)].set_neighbours(neighbour_names)
|
||||||
|
|
||||||
|
# def __sizeof__(self):
|
||||||
|
# size = 0
|
||||||
|
# for cell in self._cells.values():
|
||||||
|
# size += sys.getsizeof(cell)
|
||||||
|
# size += sys.getsizeof(self._dimension) + sys.getsizeof(self._cells) + sys.getsizeof(self._active_cells)
|
||||||
|
|
||||||
|
# return size
|
||||||
|
|
||||||
|
|
||||||
|
def _instantiate_coordinate_if_necessary(coordinate):
|
||||||
|
if coordinate is None:
|
||||||
|
coordinate = []
|
||||||
|
return coordinate
|
||||||
|
|
||||||
|
|
||||||
|
def _join_coordinate(coordinate):
|
||||||
|
return '-'.join(str(x) for x in coordinate)
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ class EdgeRule(Enum):
|
|||||||
FIRST_AND_LAST_CELL_OF_DIMENSION_ARE_NEIGHBORS = 2
|
FIRST_AND_LAST_CELL_OF_DIMENSION_ARE_NEIGHBORS = 2
|
||||||
|
|
||||||
|
|
||||||
class CellularAutomatonNeighborhood:
|
class Neighborhood:
|
||||||
def __init__(self, neighbors: list, edge_rule: EdgeRule):
|
def __init__(self, neighbors: list, edge_rule: EdgeRule):
|
||||||
self._neighbors = neighbors
|
self._neighbors = neighbors
|
||||||
self.edge_rule = edge_rule
|
self.edge_rule = edge_rule
|
||||||
@ -18,7 +18,9 @@ class CellularAutomatonNeighborhood:
|
|||||||
|
|
||||||
def get_neighbor_coordinates(self, cell_coordinate, dimensions):
|
def get_neighbor_coordinates(self, cell_coordinate, dimensions):
|
||||||
self.dimensions = dimensions
|
self.dimensions = dimensions
|
||||||
if not self._does_ignore_edge_cell_rule_apply(cell_coordinate):
|
if self._does_ignore_edge_cell_rule_apply(cell_coordinate):
|
||||||
|
return []
|
||||||
|
else:
|
||||||
return self._apply_edge_rule_to_neighbours_of(cell_coordinate)
|
return self._apply_edge_rule_to_neighbours_of(cell_coordinate)
|
||||||
|
|
||||||
def _does_ignore_edge_cell_rule_apply(self, coordinate):
|
def _does_ignore_edge_cell_rule_apply(self, coordinate):
|
||||||
@ -37,6 +39,7 @@ class CellularAutomatonNeighborhood:
|
|||||||
for neighbour in self._neighbors:
|
for neighbour in self._neighbors:
|
||||||
if not self._does_ignore_edge_cell_neighbours_rule_apply(neighbour, cell_coordinate):
|
if not self._does_ignore_edge_cell_neighbours_rule_apply(neighbour, cell_coordinate):
|
||||||
remaining_neighbours.append(self._calculate_neighbour_coordinate(neighbour, cell_coordinate))
|
remaining_neighbours.append(self._calculate_neighbour_coordinate(neighbour, cell_coordinate))
|
||||||
|
return remaining_neighbours
|
||||||
|
|
||||||
def _does_ignore_edge_cell_neighbours_rule_apply(self, neighbour, cell_coordinate):
|
def _does_ignore_edge_cell_neighbours_rule_apply(self, neighbour, cell_coordinate):
|
||||||
if self.edge_rule == EdgeRule.IGNORE_MISSING_NEIGHBORS_OF_EDGE_CELLS:
|
if self.edge_rule == EdgeRule.IGNORE_MISSING_NEIGHBORS_OF_EDGE_CELLS:
|
||||||
@ -47,18 +50,20 @@ class CellularAutomatonNeighborhood:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def _calculate_neighbour_coordinate(self, neighbour, cell_coordinate):
|
def _calculate_neighbour_coordinate(self, neighbour, cell_coordinate):
|
||||||
|
new_coordinate = []
|
||||||
for rel_nd, cd, d in zip(neighbour, cell_coordinate, self.dimensions):
|
for rel_nd, cd, d in zip(neighbour, cell_coordinate, self.dimensions):
|
||||||
nd = cd + rel_nd
|
nd = cd + rel_nd
|
||||||
if nd < 0:
|
if nd < 0:
|
||||||
nd = d - 1
|
nd = d - 1
|
||||||
elif nd >= d:
|
elif nd >= d:
|
||||||
nd = 0
|
nd = 0
|
||||||
return nd
|
new_coordinate.append(nd)
|
||||||
|
return new_coordinate
|
||||||
|
|
||||||
|
|
||||||
class MooreNeighborhood(CellularAutomatonNeighborhood):
|
class MooreNeighborhood(Neighborhood):
|
||||||
def __init__(self, edge_rule: EdgeRule):
|
def __init__(self, edge_rule: EdgeRule):
|
||||||
super().__init__([[-1, -1], [0, -1], [1, -1],
|
super().__init__([[-1, -1], [0, -1], [1, -1],
|
||||||
[-1, 0], [0, 0], [1, 0],
|
[-1, 0], [1, 0],
|
||||||
[-1, 1], [0, 1], [1, 1]],
|
[-1, 1], [0, 1], [1, 1]],
|
||||||
edge_rule)
|
edge_rule)
|
||||||
|
@ -1,9 +1,18 @@
|
|||||||
from cellular_automaton.ca_cell import Cell
|
from cellular_automaton.ca_cell import Cell
|
||||||
|
from abc import abstractmethod
|
||||||
|
|
||||||
|
|
||||||
class Rule:
|
class Rule:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def evolve_cell(self, cell: Cell, neighbours: list):
|
@abstractmethod
|
||||||
pass
|
def evolve_cell(self, cell: Cell, neighbours: list, 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.
|
||||||
|
"""
|
||||||
|
return False
|
||||||
|
@ -3,13 +3,15 @@ import time
|
|||||||
|
|
||||||
from cellular_automaton.ca_grid import Grid
|
from cellular_automaton.ca_grid import Grid
|
||||||
from cellular_automaton.ca_rule import Rule
|
from cellular_automaton.ca_rule import Rule
|
||||||
|
from cellular_automaton.ca_neighborhood import Neighborhood
|
||||||
|
|
||||||
|
|
||||||
class CellularAutomaton:
|
class CellularAutomaton:
|
||||||
def __init__(self, dimension: list, rule_: Rule=None, thread_count: int=4):
|
def __init__(self, dimension: list, neighborhood: Neighborhood, rule_: Rule=None, thread_count: int=4):
|
||||||
self.grid = Grid(dimension)
|
self.grid = Grid(dimension, neighborhood)
|
||||||
self._rule = rule_
|
self._rule = rule_
|
||||||
self._thread_count = thread_count
|
self._thread_count = thread_count
|
||||||
|
self._iteration = 0
|
||||||
|
|
||||||
def set_rule(self, rule: Rule):
|
def set_rule(self, rule: Rule):
|
||||||
self._rule = rule
|
self._rule = rule
|
||||||
@ -17,13 +19,28 @@ class CellularAutomaton:
|
|||||||
def set_thread_count(self, thread_count: int):
|
def set_thread_count(self, thread_count: int):
|
||||||
self._thread_count = thread_count
|
self._thread_count = thread_count
|
||||||
|
|
||||||
|
def get_iteration_index(self):
|
||||||
|
return self._iteration
|
||||||
|
|
||||||
def evolve(self):
|
def evolve(self):
|
||||||
|
if self._all_cells_are_inactive():
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
self._iteration += 1
|
||||||
|
self._delegate_evolve_to_threads()
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _delegate_evolve_to_threads(self):
|
||||||
cell_lists_for_threats = self.create_cell_lists_for_threads()
|
cell_lists_for_threats = self.create_cell_lists_for_threads()
|
||||||
|
self.grid.clear_active_cells()
|
||||||
threads = self._start_treads_to_evolve_grid(cell_lists_for_threats)
|
threads = self._start_treads_to_evolve_grid(cell_lists_for_threats)
|
||||||
self._wait_for_all_threads_to_finish(threads)
|
self._wait_for_all_threads_to_finish(threads)
|
||||||
|
|
||||||
|
def _all_cells_are_inactive(self):
|
||||||
|
return len(self.grid.get_names_of_active_cells()) == 0
|
||||||
|
|
||||||
def create_cell_lists_for_threads(self):
|
def create_cell_lists_for_threads(self):
|
||||||
active_cells = self.grid.get_active_cells()
|
active_cells = self.grid.get_names_of_active_cells()
|
||||||
cell_count_per_thread = int(len(active_cells) / self._thread_count)
|
cell_count_per_thread = int(len(active_cells) / self._thread_count)
|
||||||
return self.divide_active_cells(cell_count_per_thread, active_cells)
|
return self.divide_active_cells(cell_count_per_thread, active_cells)
|
||||||
|
|
||||||
@ -35,7 +52,7 @@ class CellularAutomaton:
|
|||||||
def _start_treads_to_evolve_grid(self, cell_lists_for_threats):
|
def _start_treads_to_evolve_grid(self, cell_lists_for_threats):
|
||||||
threads = []
|
threads = []
|
||||||
for t in range(self._thread_count):
|
for t in range(self._thread_count):
|
||||||
new_thread = _EvolutionThread(self.grid, self._rule, cell_lists_for_threats[t])
|
new_thread = _EvolutionThread(self.grid, self._rule, cell_lists_for_threats[t], self._iteration)
|
||||||
threads.append(new_thread)
|
threads.append(new_thread)
|
||||||
new_thread.start()
|
new_thread.start()
|
||||||
return threads
|
return threads
|
||||||
@ -50,17 +67,22 @@ class CellularAutomaton:
|
|||||||
|
|
||||||
|
|
||||||
class _EvolutionThread(threading.Thread):
|
class _EvolutionThread(threading.Thread):
|
||||||
def __init__(self, grid: Grid, rule: Rule, cell_list: list):
|
def __init__(self, grid: Grid, rule: Rule, cell_list: list, iteration: int):
|
||||||
super(_EvolutionThread, self).__init__()
|
super(_EvolutionThread, self).__init__()
|
||||||
self._grid = grid
|
self._grid = grid
|
||||||
self._rule = rule
|
self._rule = rule
|
||||||
self._cell_list = cell_list
|
self._cell_list = cell_list
|
||||||
self._next_state = []
|
self._next_state = []
|
||||||
self._finished = False
|
self._finished = False
|
||||||
|
self._iteration = iteration
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
for cell in self._cell_list:
|
for cell in self._cell_list:
|
||||||
self._rule.evolve_cell(*self._grid.get_cell_and_neighbors(cell))
|
cell_info = self._grid.get_cell_and_neighbors(cell)
|
||||||
|
active = self._rule.evolve_cell(cell_info[0], cell_info[1], self._iteration)
|
||||||
|
|
||||||
|
if active:
|
||||||
|
self._grid.set_cell_and_neighbours_active(cell_info)
|
||||||
self._finished = True
|
self._finished = True
|
||||||
|
|
||||||
def get_new_cell_states(self):
|
def get_new_cell_states(self):
|
||||||
|
Loading…
Reference in New Issue
Block a user