def move_tile_on_grid(self, tile: Tile, coordinates: Coordinates): if self.tiles_from_index.get(tile.get_id()) is None: raise TileNotExistsException("tile: (" + str(tile) + ") was not added") tile_on_coordinates = self.get_tile_from_grid(coordinates) if tile_on_coordinates is not None: if tile_on_coordinates.id != tile.id: raise TileTakenException( tile_on_coordinates, f"there is already tile: ({str(tile)}) on {str(coordinates)}" ) # else it means we move to same tile we were on previous_coordinates = self.coordinates_from_index.get(tile.get_id()) if previous_coordinates is None: raise TileNotExistsException("tile: (" + str(tile) + ") did not have coordinates") self.coordinates_from_index[tile.get_id()] = coordinates.copy() self.tile_grid[ previous_coordinates.get_array_index()] = BaseGrid.empty_tile_id self.tile_grid[coordinates.get_array_index()] = tile.get_id() self.tiles_from_index[tile.get_id()] = tile if tile.get_type() == TileType.BLOCK: self.block_tile_grid[ previous_coordinates.get_array_index()] = False self.block_tile_grid[coordinates.get_array_index()] = True
def pop_tile_from_grid(self, coordinates: Coordinates) -> Union[Tile, None]: tile_index = self.tile_grid[coordinates.get_array_index()] if tile_index is None: return None self.coordinates_from_index.pop(tile_index) self.tile_grid[coordinates.get_array_index()] = BaseGrid.empty_tile_id tile = self._get_tile_from_index(tile_index) if tile.get_type() == TileType.BLOCK: self.block_tile_grid[coordinates.get_array_index()] = False return tile
def add_tile_to_grid(self, tile: Tile, coordinates: Coordinates): if self.tiles_from_index.get(tile.get_id()) is None: self.add_new_tile(tile) else: tile_coordinates = self.coordinates_from_index.get(tile.get_id()) if tile_coordinates is not None: raise AddDuplicateTileError("tile " + str(tile) + " already exists on " + str(tile_coordinates)) tile_on_coordinates = self.get_tile_from_grid(coordinates) if tile_on_coordinates is not None: raise TileTakenException( tile_on_coordinates, f"there is already tile: ({str(tile)}) on {str(coordinates)}") self.tile_grid[coordinates.get_array_index()] = tile.get_id() self.coordinates_from_index[tile.get_id()] = coordinates if tile.get_type() == TileType.BLOCK: self.block_tile_grid[coordinates.get_array_index()] = True
def get_tile_from_source(self, coordinates: Coordinates) -> Tile: try: tile_index = self.tile_grid[coordinates.get_array_index()] except IndexError as e: raise OutOfBoundCoordinatesError(e.args) tile = self._get_tile_from_index(tile_index) if tile is None: raise TileNotExistsException("tile index: (" + str(tile_index) + ") did not have tile") if tile.get_type() != TileType.SOURCE: raise TileNotSourceError(tile, "tile: (" + str(tile) + ") is not source") return Tile(TileType.BLOCK)
def _split_goal(self): if self.is_splitted: return self.edges: List[GridEdge] = list() width = self.goal_building.width height = self.goal_building.height # first add elements that are not on diagonals # test_array = np.zeros((width, height), dtype=int) edge_block_counts = np.zeros( 4, dtype=int) # how many blocks each edge have assigned raising_diag_grid = np.zeros((width, height), dtype=bool) # True if diag on field decreasing_diag_grid = np.zeros((width, height), dtype=bool) if width == 1 or height == 1: raise ValueError("goal_building should be at least 3x3") if (width % 2 == 1) and (height % 2 == 1): mid_block_x = width // 2 mid_block_y = height // 2 mid_block_pos = (mid_block_x, mid_block_y) decreasing_diag_grid[mid_block_pos] = True raising_diag_grid[mid_block_pos] = True # D 0 R # 0 RD 0 # R 0 D decreasing_diag_left_pos = Coordinates(mid_block_x - 1, mid_block_y + 1) decreasing_diag_grid[ decreasing_diag_left_pos.get_array_index()] = True decreasing_diag_right_pos = Coordinates(mid_block_x + 1, mid_block_y - 1) decreasing_diag_grid[ decreasing_diag_right_pos.get_array_index()] = True raising_diag_left_pos = Coordinates(mid_block_x - 1, mid_block_y - 1) raising_diag_grid[raising_diag_left_pos.get_array_index()] = True raising_diag_right_pos = Coordinates(mid_block_x + 1, mid_block_y + 1) raising_diag_grid[raising_diag_right_pos.get_array_index()] = True else: # D R # R D left_x = width // 2 - 1 if height % 2 == 0: down_y = height // 2 - 1 else: down_y = height // 2 decreasing_diag_left_pos = Coordinates(left_x, down_y + 1) decreasing_diag_grid[ decreasing_diag_left_pos.get_array_index()] = True decreasing_diag_right_pos = Coordinates(left_x + 1, down_y) decreasing_diag_grid[ decreasing_diag_right_pos.get_array_index()] = True raising_diag_left_pos = Coordinates(left_x, down_y) raising_diag_grid[raising_diag_left_pos.get_array_index()] = True raising_diag_right_pos = Coordinates(left_x + 1, down_y + 1) raising_diag_grid[raising_diag_right_pos.get_array_index()] = True top_right_corner_walker = ToCornerWalker(raising_diag_grid, x_direction=Direction.RIGHT, y_direction=Direction.UP, pos=raising_diag_right_pos, width=width, height=height) top_right_corner_walker.update_diag_to_corner() down_right_corner_walker = ToCornerWalker( decreasing_diag_grid, x_direction=Direction.RIGHT, y_direction=Direction.DOWN, pos=decreasing_diag_right_pos, width=width, height=height) down_right_corner_walker.update_diag_to_corner() down_left_corner_walker = ToCornerWalker(raising_diag_grid, x_direction=Direction.LEFT, y_direction=Direction.DOWN, pos=raising_diag_left_pos, width=width, height=height) down_left_corner_walker.update_diag_to_corner() top_left_corner_walker = ToCornerWalker(decreasing_diag_grid, x_direction=Direction.LEFT, y_direction=Direction.UP, pos=decreasing_diag_left_pos, width=width, height=height) top_left_corner_walker.update_diag_to_corner() both_diags = (raising_diag_grid + 2 * decreasing_diag_grid) # now we want to create lines for each edge: edge_builds: List[EdgeBuild] = [ EdgeBuild(width, height, direction.get_opposite()) for direction in Direction ] edge_num = -1 for direction in Direction: edge_num += 1 direction: Direction = direction if direction.is_x_axis(): # for x axis we have y axis length amount of lines edge_len = height opposite_len = width else: edge_len = width opposite_len = height # for each line for i in range(edge_len): # if direction = UP # we would have something like this: # if rising then last index if direction == Direction.LEFT: line_scan_coordinate = Coordinates(0, i) elif direction == Direction.UP: line_scan_coordinate = Coordinates(i, opposite_len - 1) elif direction == Direction.RIGHT: line_scan_coordinate = Coordinates(opposite_len - 1, i) else: # DOWN line_scan_coordinate = Coordinates(i, 0) edge_builds[edge_num].add_line_start(line_scan_coordinate) for j in range(opposite_len): diag_tile = both_diags[ line_scan_coordinate.get_array_index()] if diag_tile: if diag_tile != 10 and self.goal_building.grid[ line_scan_coordinate.get_array_index()]: both_diags[ line_scan_coordinate.get_array_index()] = 10 # TODO: decide where this tile goes # decide_later.append(block_line, coordinate, edge_set) something like this # for now lets just add to first that got this edge_builds[edge_num].block_lines[(i, j)] = True edge_block_counts[edge_num] += 1 break if self.goal_building.grid[ line_scan_coordinate.get_array_index()]: edge_builds[edge_num].block_lines[(i, j)] = True edge_block_counts[edge_num] += 1 line_scan_coordinate = line_scan_coordinate.create_neighbour_coordinate( direction.get_opposite()) edge_num = -1 for direction in Direction: edge_num += 1 edge_build = edge_builds[edge_num] lines: List[LineToMiddle] = list() for i in range(edge_build.length): line = LineToMiddle(edge_build.line_starts[i], direction.get_opposite(), edge_build.block_lines[i]) lines.append(line) edge = GridEdge(self.robot_coordinates, self.source_positions, edge_build.length, lines) self.edges.append(edge)
def get_tile_from_grid(self, coordinates: Coordinates) -> Tile: try: tile_index = self.tile_grid[coordinates.get_array_index()] except IndexError as e: raise OutOfBoundCoordinatesError(e.args) return self._get_tile_from_index(tile_index)