def __reset(self, state: SimState) -> None: if self.get_grid() is not None: self.get_grid().remove_listeners() new_grid = Grid(self.__scheduler) new_grid.reset(state) self.set_grid(new_grid) total_count = 0 for row in range(self.__grid.get_size()): for col in range(self.__grid.get_size()): if self.__grid.get_agent(GridPos(uint(row), uint(col))) is not None: total_count += 1 state.set_beginning_total_count(total_count)
def _draw_tiles(self, grid: Grid): if not self._grid_rect: self._setup_grid(grid) utils.draw_rounded_rect(self.window, theme.GRID_COLOR, self._grid_rect, border_radius=8) x, y = self._grid_rect.topleft for i in range(self._grid_rows): rect = None x = self._grid_rect.left for j in range(self._grid_cols): color = theme.CELL_COLOR tile = grid.get_cell(Position(j, i)) text = None rect = Rect(x + self._grid_spacing, y + self._grid_spacing, self._tile_side, self._tile_side) if tile: color = theme.TILE_COLOR_BASE text = theme.H2_FONT.render(str(tile.value), True, theme.COLOR_DARK) utils.draw_rounded_rect(self.window, color, rect, 4) if text: text_x = rect.left + (rect.width - text.get_width()) // 2 text_y = rect.top + (rect.height - text.get_height()) // 2 self.window.blit(text, (text_x, text_y)) x = rect.right y = rect.bottom pygame.display.update()
def test_signal_is_only_add_once(): grid = Grid(10, 10) grid.add_signal(Signal(True, Vector(2, 3))) assert len(grid.signals) == 1 grid.add_signal(Signal(True, Vector(2, 3))) assert len(grid.signals) == 1
def create(self, n=None): """ Create the population. Return nothing Create n Individual prey instances and store in self.individuals Create ecosystem Grid instance and store in self.grid. """ if n == None: n = self.nIndiv self.deathCount = 0 # everyone is alive at the beginning of the simulation self.ecoTime = 0 # ecological time set to zero at beginning of simulation self.ecologyShortHistory = np.empty([0, 4]) self.explorationShortHistory = np.empty([0, 4]) self.grid = Grid(dim=self.gridSize, init=self.initRes) self.individuals = [] for i in range(n): self.individuals.append(Ind(m=self.gridSize, v=self.v))
def test_grid_knows_own_dimensions(self): self.grid = Grid(dim=4, init=2) assert self.grid.dimension == 4
def test_resources_grid_gets_correct_initial_value(self): self.grid = Grid(dim=10, init=2) for cell in np.nditer(self.grid.resources): assert pytest.approx(cell) == 2
def test_resources_get_initialized(self): self.grid = Grid(dim=10, init=2) assert hasattr(self.grid, "initialResources") assert self.grid.initialResources is not None assert type(self.grid.initialResources) is int assert self.grid.initialResources > 0
def test_cell_resource_sharing_correct_format(self): self.grid = Grid(dim=10, init=2) assert self.grid.share.dtype == np.float32
def test_grid_has_cell_resource_sharing_info(self): self.dimension = 10 self.grid = Grid(dim=self.dimension, init=2) assert hasattr(self.grid, "share") assert type(self.grid.share) is np.ndarray assert self.grid.share.shape == (self.dimension, self.dimension)
def test_grid_has_cell_resources_info(self): self.dimension = 10 self.grid = Grid(dim=self.dimension, init=2) assert hasattr(self.grid, "resources") assert type(self.grid.resources) is np.ndarray assert self.grid.resources.shape == (self.dimension, self.dimension)
def __get_sut(self) -> Grid: return Grid(Scheduler())
def calc_effective_reproduction_number( grid: Grid, remove_probability=0.6, infection_probability=0.2, infection_radius=1, infection_metric=EnvironmentMetric.MANHATTAN ) -> float: """ Calculate the effective reproduction number R """ mean_infection_duration = 1 / remove_probability size = grid.get_size() infection_env_size = infection_radius * 2 + 1 # Find all infected cells infection_counts = [] for row in range(size): for column in range(size): agent = grid.get_agent(GridPos(np.uint(row), np.uint(column))) if agent is not None and agent.state() is AgentState.INFECTIVE: # Is an infected cell -> Count number of infectable (susceptible) cells in the near environment infectable_count = 0 if infection_metric == EnvironmentMetric.MANHATTAN: for r in range(0, infection_env_size): offset = abs(infection_radius - r) check_row = row - infection_radius + r for c in range(offset, infection_env_size - offset): check_column = column - infection_radius + c if check_row < 0 or check_column < 0 or check_row >= size or check_column >= size: continue other_agent = grid.get_agent(GridPos(np.uint(check_row), np.uint(check_column))) if other_agent is not None and other_agent.state() is AgentState.SUSCEPTIBLE: infectable_count += 1 elif infection_metric == EnvironmentMetric.EUCLIDEAN: for r in range(0, infection_env_size): check_row = row - infection_radius + r for c in range(0, infection_env_size): check_column = column - infection_radius + c if check_row < 0 or check_column < 0 or check_row >= size or check_column >= size: continue distance = np.round( np.sqrt((infection_radius - r) ** 2 + (infection_radius - c) ** 2)) if distance > 0 and distance <= infection_radius: other_agent = grid.get_agent(GridPos(np.uint(check_row), np.uint(check_column))) if other_agent is not None and other_agent.state() is AgentState.SUSCEPTIBLE: infectable_count += 1 # Check how many people already have been infected by the person already_infected_count = agent.infected_count() # Check how many days the agent is already infected already_infected_time = agent.sick_days() # Estimate how many more days the agent will be infected infection_time_estimate = max(round(mean_infection_duration - already_infected_time), 1) # The agent will live at least one more day # Estimate how many more people are going to be infected by that agent infection_estimate = infection_time_estimate * infectable_count * infection_probability # Sum up all the actual and estimated infection by that agent total_estimated_infections = already_infected_count + infection_estimate infection_counts.append(total_estimated_infections) return np.array(infection_counts).mean() if len(infection_counts) > 0 else 0
def __init__(self, params: Namespace): self._grid = Grid(width=params.width, height=params.height) self._start_tiles = params.start_tiles self._merged_total = 0 self._params = params
class Logic: def __init__(self, params: Namespace): self._grid = Grid(width=params.width, height=params.height) self._start_tiles = params.start_tiles self._merged_total = 0 self._params = params @property def grid(self) -> Grid: return self._grid @property def start_tiles(self) -> int: return self._start_tiles @property def merged_total(self) -> int: return self._merged_total def random_tile(self) -> Optional[Tile]: """Produce a new ``Tile`` with random value and position. If there are no empty cells in the grid returns ``None``. :return: Tile object or None if no available cells found. """ if self._grid.has_available_cells(): value = 4 if random.random() < 0.1 else 2 return Tile(self._grid.get_empty_cell(), value) def save_state(self) -> LogicState: return LogicState(grid=self._grid, params=self._params, merged_total=self.merged_total) def load_state(self, state: LogicState): class InvalidStateException(Exception): pass try: self._start_tiles = state.params.start_tiles self._merged_total = state.merged_total self._params = state.params self._grid = state.grid except AttributeError as e: raise InvalidStateException(f"Logic state is corrupted! {e}") def setup(self) -> bool: """Clears the grid and inserts ``start_tiles`` number of tiles. :return: bool False if couldn't insert the number of tiles given, True otherwise """ self._merged_total = 0 self._grid.empty() for _ in range(self._start_tiles): if not self.insert_random_tile(): return False return True def insert_random_tile(self): # todo: add a docstring tile = self.random_tile() if tile: self._grid.insert_tile(tile) return True return False def moves_available(self): """Pretty expensive check""" for direction in Direction: for tile in self._grid.tiles: if self._farthest_position(tile, direction) != tile.position: return True if self._is_merge_available(tile, direction): return True return False def move(self, direction: Direction): """Moves all the tiles in the given direction and merges them if needed. :param direction: :return: None """ # Remove tiles metadata from the previous move self._clean_tiles_metadata() for position in self._traversals(direction): tile = self._grid.get_cell(position) if not tile: continue # Move the tile to the farthest empty position before the first obstacle self._move_tile(tile, self._farthest_position(tile, direction)) # If the nearest obstacle in that direction is a tile # check for merge and merge if possible if self._is_merge_available(tile, direction): closest = self._next_merge(tile, direction) merged = self._merge_tiles(tile, closest) self._merged_total += merged.value self.insert_random_tile() def _next_merge(self, tile: Tile, direction: Direction) -> Optional[Tile]: # TODO: add a docstring position = _next_position(tile.position, direction) if self._grid.is_within(position) and self._grid.is_cell_filled( position): candidate = self._grid.get_cell(position) if candidate.value == tile.value and not candidate.merged_from: return candidate def _is_merge_available(self, tile: Tile, direction: Direction) -> bool: return self._next_merge(tile, direction) is not None def _farthest_position(self, tile: Tile, direction: Direction) -> Position: """Returns ``Position`` object of the farthest position before the first obstacle. :param direction: direction towards the destination position :return: Position object """ current = tile.position position = _next_position(current, direction) while self._grid.is_within(position) and self._grid.is_cell_empty( position): current = position position = _next_position(current, direction) return current def _move_tile(self, tile: Tile, position: Position): self._grid.remove_tile(tile) tile.save_position() tile.position = position self._grid.insert_tile(tile) def _clean_tiles_metadata(self): for tile in self._grid.tiles: tile.merged_from = None def _merge_tiles(self, a: Tile, b: Tile): """Replaces tiles in the grid with a new ``Tile`` object at `b`'s position. The merged tile's value is a sum of `a` and `b` values. :param a: first Tile :param b: second Tile :return: new Tile object """ merged = Tile(b.position, a.value + b.value) merged.merged_from = [a, b] self._grid.remove_tile(a) self._grid.insert_tile(merged) return merged def _traversals(self, direction: Direction) -> Iterator[Position]: """Get positions to travers in the given direction. Positions are sorted in the bottommost or rightmost order for vertical or horizontal directions accordingly. :param direction: the direction to travers :return: iterator that yields Position objects representing nodes to travers in the given direction. """ xs = list(range(self._grid.width)) ys = list(range(self._grid.height)) if direction.value.x == 1: xs.reverse() if direction.value.y == 1: ys.reverse() for x, y in product(xs, ys): yield Position(x, y)
def test_add_signal_adds_a_signal_to_the_grid(): grid = Grid(10, 10) grid.add_signal(Signal(True, Vector(2, 3))) assert Signal(True, Vector(2, 3)) in grid.signals
def get_grid(self, tvd_name: str) -> Grid: """Получить граф указанного ТВД кампании""" xgml = Xgml(tvd_name, self._config.mgen) xgml.parse(self.get_file(tvd_name)) return Grid(tvd_name, xgml.nodes, xgml.edges, self._config.mgen)