Example #1
0
 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)
Example #2
0
    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()
Example #3
0
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)
Example #11
0
 def __get_sut(self) -> Grid:
     return Grid(Scheduler())
Example #12
0
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
Example #13
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
Example #14
0
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)
Example #15
0
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
Example #16
0
 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)