Пример #1
0
    def render(self, grid: Grid, **kwargs: Any) -> None:
        horizontal_wall = "\u2501"
        vertical_wall = "\u2503"

        output = self.JUNCTIONS[12]
        for x in range(grid.columns - 1):
            output += (horizontal_wall * 3 + self.get_topmost_junction(
                cast(Cell, grid.cell_at(row=0, column=x))))
        output += horizontal_wall * 3 + self.JUNCTIONS[10] + "\n"

        for row in grid.each_row():
            top = vertical_wall
            bottom = self.get_leftmost_junction(row[0])
            for cell in row:
                body = grid.contents_of(cell)
                east_boundary = " " if cell.linked_to(
                    cell.east) else vertical_wall
                top += body + east_boundary
                south_boundary = "   " if cell.linked_to(
                    cell.south) else horizontal_wall * 3
                bottom += south_boundary + self.get_south_east_junction(cell)
            output += top + "\n"
            output += bottom + "\n"

        print(output)
def test_random_cell() -> None:
    grid = Grid(2, 2)

    for _ in range(100):
        assert grid.random_cell() in [
            Cell(0, 0), Cell(0, 1),
            Cell(1, 0), Cell(1, 1)
        ]
def test_constructor() -> None:
    grid = Grid(2, 2)
    assert grid.columns == 2
    assert grid.rows == 2

    grid = Grid(3, 3)
    assert grid.columns == 3
    assert grid.rows == 3
def test_constructor() -> None:
    grid = Grid(1, 1)
    assert grid.columns == 1
    assert grid.rows == 1

    grid = Grid(2, 2)
    assert grid.columns == 2
    assert grid.rows == 2
Пример #5
0
    def on(self, grid: Grid) -> None:
        if self.starting_cell is None:
            self.starting_cell = grid.random_cell()
        if not is_cell(self.starting_cell) or self.starting_cell not in grid:
            ValueError(
                "Starting point of the algorithm must be a valid cell in the grid"
            )

        # We'll use the list as a stack to do very easily any backtracking
        walked_path = []
        walked_path.append(self.starting_cell)

        while len(walked_path) > 0:
            current_cell = walked_path[-1]

            unvisited_neighbors = [
                neighbor for neighbor in current_cell.neighbors
                if len(neighbor.links) == 0
            ]
            if len(unvisited_neighbors) == 0:
                walked_path.pop()
            else:
                neighbor = choice(unvisited_neighbors)
                current_cell += neighbor
                walked_path.append(neighbor)
Пример #6
0
    def on(self, grid: Grid) -> None:
        if self.start is None:
            start = grid.randomCell()
        elif isCell(start) and start in grid:
            start = start
        else:
            ValueError(
                'The starting point of the algorithm must be a cell in the grid'
            )

        # We'll use the list as a stack to do any backtracking
        walked_path = []
        walked_path.append(start)

        while len(walked_path) > 0:
            current_cell = walked_path[-1]
            unvisited_neighbours = [
                n for n in current_cell.neighbours if n.nLinks == 0
            ]

            if len(unvisited_neighbours) == 0:
                walked_path.pop()
            else:
                neighbour = choice(unvisited_neighbours)
                current_cell += neighbour
                walked_path.append(neighbour)
            self.step()
Пример #7
0
    def _render(grid: Grid, cell_size: int = 4, coloring: bool = False) -> Image:
        wall_color = (0, 0, 0)
        image_width = cell_size * grid.columns
        image_height = cell_size * grid.rows

        image = Image.new("RGBA", (image_width + 1, image_height + 1), (255, 255, 255))
        draw = ImageDraw.Draw(image)

        for draw_pass in range(2):
            for cell in grid.each_cell():
                x1 = cell.column * cell_size
                y1 = cell.row * cell_size
                x2 = (cell.column + 1) * cell_size
                y2 = (cell.row + 1) * cell_size

                if draw_pass == STEP_BACKGROUND and coloring:
                    if coloring:
                        color = cast(ColoredGrid, grid).background_color_for(cell)
                    else:
                        color = (255, 255, 255)
                    draw.rectangle((x1, y1, x2, y2), fill=color)
                else:
                    if not cell.north:
                        draw.line((x1, y1, x2, y1), fill=wall_color, width=1)
                    if not cell.west:
                        draw.line((x1, y1, x1, y2), fill=wall_color, width=1)
                    if not cell.linked_to(cell.east):
                        draw.line((x2, y1, x2, y2), fill=wall_color, width=1)
                    if not cell.linked_to(cell.south):
                        draw.line((x1, y2, x2, y2), fill=wall_color, width=1)

        return image
    def on(self, grid: Grid) -> None:
        unvisited = []
        for cell in grid.eachCell():
            unvisited.append(cell)

        first_cell = choice(unvisited)
        unvisited.remove(first_cell)

        while len(unvisited) > 0:
            # start a walk
            cell = choice(unvisited)
            path = [cell]

            while cell in unvisited:
                cell = cell.randomNeighbour()  # type: ignore
                try:
                    position = path.index(cell)
                    # already walked, perform loop-erase. e.g. 'A -> B -> C -> D -> B' becomes 'A -> B'
                    path = path[:position + 1]
                except ValueError:
                    path.append(cell)
                self.step()

            # Passage carving once has found a valid path
            for index in range(len(path) - 1):
                path[index] += (path[index + 1])
                unvisited.remove(path[index])
                self.step()
    def on(grid: Grid) -> Grid:
        unvisited = []
        for cell in grid.each_cell():
            unvisited.append(cell)

        first_cell = choice(unvisited)
        unvisited.remove(first_cell)

        while len(unvisited) > 0:
            # start a walk
            cell = choice(unvisited)
            path = [cell]

            while cell in unvisited:
                cell = choice(cell.neighbors)
                try:
                    position = path.index(cell)
                    # already walked, perform loop-erase. e.g. A -> B -> C -> D -> B   becomes A -> B
                    path = path[:position + 1]
                except ValueError:
                    path.append(cell)

            # Passage carving once has found a valid path
            for index in range(len(path) - 1):
                path[index].link(path[index + 1])
                unvisited.remove(path[index])

        return grid
Пример #10
0
    def render(self, grid: Grid, **kwargs: Any) -> None:
        output = '+' + '---+' * grid.cols + '\n'

        for row in grid.eachRow():
            top = '|'
            bottom = '+'
            for cell in row:
                # NOTE: Book here creates dummy (-1,-1) cell. Not doing it until needed
                body = grid.contents(cell)
                east_boundary = ' ' if cell & cell.east else '|'
                top += body + east_boundary
                south_boundary = '   ' if cell & cell.south else '---'
                corner = '+'
                bottom += south_boundary + corner
            output += top + '\n'
            output += bottom + '\n'

        print(output)
 def _rotate_cell_neighbors(new_cell: Cell, old_cell: Cell,
                            grid: Grid) -> None:
     for link in old_cell.links:
         row, column = Rotator._rotated_coordinates(link, grid)
         neighbor = grid.cell_at(row, column)
         if neighbor is None:
             raise IndexError("Cell not found at row {} column {}".format(
                 row, column))
         new_cell.link(neighbor)
 def _prepareLogGrid(self, grid: Grid) -> None:
     ''' Prepare the grid for logging the algorithm '''
     if not self.log: return
     # 'visit' : List of steps on which the cell was visited
     # 'links' : Directions of the links made by the cell (NOT to the cell)
     data = {'visit': [], 'links': []}  # type: Dict
     key = self.name  # type: str
     for cell in grid.eachCell():
         cell.data[key] = data
    def render(self, grid: Grid, **kwargs: Any) -> None:
        output = "+" + "---+" * grid.columns + "\n"

        for row in grid.each_row():
            top = "|"
            bottom = "+"
            for cell in row:
                # NOTE: Book here creates dummy (-1,-1) cell. Not doing it until needed
                body = grid.contents_of(cell)
                east_boundary = " " if cell.linked_to(cell.east) else "|"
                top += body + east_boundary
                south_boundary = "   " if cell.linked_to(cell.south) else "---"
                corner = "+"
                bottom += south_boundary + corner
            output += top + "\n"
            output += bottom + "\n"

        print(output)
Пример #14
0
 def on(self, grid: Grid) -> None:
     for cell in grid.each_cell():
         neighbors = []
         if cell.north:
             neighbors.append(cell.north)
         if cell.east:
             neighbors.append(cell.east)
         if len(neighbors) > 0:
             neighbor = choice(neighbors)
             cell += neighbor
 def on(grid: Grid) -> Grid:
     for cell in grid.each_cell():
         neighbors = []
         if cell.north:
             neighbors.append(cell.north)
         if cell.east:
             neighbors.append(cell.east)
         if len(neighbors) > 0:
             cell.link(choice(neighbors))
     return grid
Пример #16
0
    def on(self, grid: Grid) -> None:
        current_cell = grid.random_cell()
        unvisited_count = grid.size - 1

        while unvisited_count > 0:
            neighbor = current_cell.random_neighbour()
            if neighbor is None:
                raise ValueError("Aldous-Broder algorithm needs all cells to have at least one neighbor")
            if len(neighbor.links) == 0:
                current_cell += neighbor
                unvisited_count -= 1
            current_cell = neighbor
Пример #17
0
    def on(self, grid: Grid) -> None:
        current_cell: Optional[Cell] = grid.random_cell()

        while current_cell is not None:
            unvisited_neighbors = [neighbor for neighbor in current_cell.neighbors if len(neighbor.links) == 0]
            if len(unvisited_neighbors) > 0:
                # as int as there are unvisited paths, walk them
                neighbor = choice(unvisited_neighbors)
                current_cell += neighbor
                current_cell = neighbor
            else:
                # enter hunt mode, find first unvisited cell near any visited cell
                current_cell = None

                for cell in grid.each_cell():
                    visited_neighbors = [neighbor for neighbor in cell.neighbors if len(neighbor.links) > 0]
                    if len(cell.links) == 0 and len(visited_neighbors) > 0:
                        current_cell = cast(Cell, cell)  # outside of Mypy it's a mere assignment
                        neighbor = choice(visited_neighbors)
                        current_cell += neighbor
                        break
Пример #18
0
def test_cell_access_using_operator_overloads() -> None:
    grid = Grid(2, 2)

    assert grid[0, 0] == Cell(0, 0)
    assert grid[0, 1] == Cell(0, 1)
    assert grid[1, 0] == Cell(1, 0)
    assert grid[1, 1] == Cell(1, 1)

    assert grid[-1, 0] is None
    assert grid[0, -1] is None
    assert grid[4, 0] is None
    assert grid[0, 4] is None
    def _render(grid: Grid, cell_size: int=4, coloring: bool=False) -> Image:
        ''' Rendering core '''
        wall_color = (0, 0, 0)
        image = Image.new('RGBA', (cell_size * grid.cols + 1, cell_size * grid.rows + 1), (255, 255, 255))
        draw = ImageDraw.Draw(image)

        for draw_pass in range(2):
            for cell in grid.eachCell():
                x1 = cell.col * cell_size
                y1 = cell.row * cell_size
                x2 = (cell.col + 1) * cell_size
                y2 = (cell.row + 1) * cell_size

                if draw_pass == 0:
                    color = grid.color(cell) if coloring else (255, 255, 255)  # type: ignore
                    draw.rectangle((x1, y1, x2, y2), fill=color)
                else:
                    if not cell.north:        draw.line((x1, y1, x2, y1), fill=wall_color, width=1)
                    if not cell.west:         draw.line((x1, y1, x1, y2), fill=wall_color, width=1)
                    if not cell & cell.east:  draw.line((x2, y1, x2, y2), fill=wall_color, width=1)
                    if not cell & cell.south: draw.line((x1, y2, x2, y2), fill=wall_color, width=1)
        return image
def test_neighbors_setup_when_grid_is_created() -> None:
    grid = Grid(2, 2)

    assert grid.get_cell(0, 0).north is None  # type: ignore
    assert grid.get_cell(0, 0).south == Cell(1, 0)  # type: ignore
    assert grid.get_cell(0, 0).east == Cell(0, 1)  # type: ignore
    assert grid.get_cell(0, 0).west is None  # type: ignore

    assert grid.get_cell(0, 1).north is None  # type: ignore
    assert grid.get_cell(0, 1).south == Cell(1, 1)  # type: ignore
    assert grid.get_cell(0, 1).east is None  # type: ignore
    assert grid.get_cell(0, 1).west == Cell(0, 0)  # type: ignore

    assert grid.get_cell(1, 0).north == Cell(0, 0)  # type: ignore
    assert grid.get_cell(1, 0).south is None  # type: ignore
    assert grid.get_cell(1, 0).east == Cell(1, 1)  # type: ignore
    assert grid.get_cell(1, 0).west is None  # type: ignore

    assert grid.get_cell(1, 1).north == Cell(0, 1)  # type: ignore
    assert grid.get_cell(1, 1).south is None  # type: ignore
    assert grid.get_cell(1, 1).east is None  # type: ignore
    assert grid.get_cell(1, 1).west == Cell(1, 0)  # type: ignore
    def render(self, grid: Grid, **kwargs: Any) -> None:
        horizontal_wall = '\u2501'
        vertical_wall = '\u2503'

        output = self.JUNCTIONS[12]
        for x in range(grid.cols - 1):
            output += (horizontal_wall * 3 +
                       self.get_topmost_junction(cast(Cell, grid[0, x])))
        output += horizontal_wall * 3 + self.JUNCTIONS[10] + '\n'

        for row in grid.eachRow():
            top = vertical_wall
            bottom = self.get_leftmost_junction(row[0])
            for cell in row:
                body = grid.contents(cell)
                east_boundary = ' ' if cell & cell.east else vertical_wall
                top += body + east_boundary
                south_boundary = '   ' if cell & cell.south else horizontal_wall * 3
                bottom += south_boundary + self.get_south_east_junction(cell)
            output += top + '\n'
            output += bottom + '\n'

        print(output)
Пример #22
0
    def on(self, grid: Grid) -> Grid:
        grid_type = type(grid)

        # row i becomes col n-i when rotating 90 degrees clockwise
        rotated_grid = grid_type(rows=grid.cols, cols=grid.rows)

        for old_cell in grid.eachCell():
            row, column = self._rotated_coordinates(old_cell, rotated_grid)
            new_cell = rotated_grid[row, column]
            if new_cell is None:
                raise IndexError('Cell not found at row {} column {}'.format(
                    row, column))
            self._rotate_cell_neighbors(new_cell, old_cell, rotated_grid)

        return rotated_grid
Пример #23
0
    def on(grid: Grid) -> Grid:
        current_cell = grid.random_cell()  # type: Optional[Cell]

        while current_cell is not None:
            unvisited_neighbors = \
                [neighbor for neighbor in current_cell.neighbors if len(neighbor.links) == 0]

            if len(unvisited_neighbors) > 0:
                # as long as there are unvisited paths, walk them
                neighbor = choice(unvisited_neighbors)
                current_cell.link(neighbor)
                current_cell = neighbor
            else:
                # enter hunt mode, find first unvisited cell near any visited cell
                current_cell = None
                for cell in grid.each_cell():
                    visited_neighbors = [neighbor for neighbor in cell.neighbors if len(neighbor.links) > 0]
                    if len(cell.links) == 0 and len(visited_neighbors) > 0:
                        current_cell = cast(Cell, cell)
                        neighbor = choice(visited_neighbors)
                        current_cell.link(neighbor)
                        break

        return grid
Пример #24
0
 def on(self, grid: Grid) -> None:
     for row in grid.eachRow():
         run = []
         for cell in row:
             run.append(cell)
             at_eastern_boundary = cell.east is None
             at_northen_boundary = cell.north is None
             should_close_out = at_eastern_boundary or (not at_northen_boundary and randint(0, 1) == 0)
             if should_close_out:
                 member = choice(run)
                 if member.north:
                     member += member.north
                 run.clear()
             else:
                 cell += cell.east  # type: ignore # Made sure cell is not at eastern boundry
             self.step()
    def on(grid: Grid) -> Grid:
        current_cell = grid.random_cell()
        unvisited_count = grid.size - 1

        while unvisited_count > 0:
            neighbor = choice(current_cell.neighbors)
            if neighbor is None:
                raise ValueError(
                    "Aldous-Broder algorithm needs all cells to have at least one neighbor"
                )
            if len(neighbor.links) == 0:
                current_cell.link(neighbor)
                unvisited_count -= 1
            current_cell = neighbor

        return grid
Пример #26
0
    def on(self, grid: Grid) -> None:
        self._prepareLogGrid(grid)

        for cell in grid.eachCell():
            self._logVisit(cell)

            neighbours = []
            if cell.north: neighbours.append(cell.north)
            if cell.east:  neighbours.append(cell.east)

            if len(neighbours) > 0:
                neighbour = choice(neighbours)
                cell += neighbour
                self._logLink(cell, neighbour)

            self.step()
Пример #27
0
    def on(self, grid: Grid) -> None:
        for row in grid.each_row():
            run = []
            for cell in row:

                run.append(cell)
                at_eastern_boundary = cell.east is None
                at_northen_boundary = cell.north is None
                should_close_out = at_eastern_boundary or (not at_northen_boundary and randint(0, 1) == 0)
                if should_close_out:
                    member = choice(run)
                    if member.north:
                        member += member.north
                    run.clear()
                else:
                    cell += cast(Cell, cell.east)
 def on(grid: Grid) -> Grid:
     for row in grid.each_row():
         run = []
         for cell in row:
             run.append(cell)
             at_eastern_boundary = cell.east is None
             at_northen_boundary = cell.north is None
             should_close_out = at_eastern_boundary or (
                 not at_northen_boundary and randint(0, 1) == 0)
             if should_close_out:
                 member = choice(run)
                 if member.north:
                     member.link(member.north)
                 run.clear()
             else:
                 cell.link(cell.east)
     return grid
Пример #29
0
def test_cell_access() -> None:
    grid = Grid(2, 2)

    assert grid.cell_at(0, 0) == Cell(0, 0)
    assert grid.cell_at(0, 1) == Cell(0, 1)
    assert grid.cell_at(1, 0) == Cell(1, 0)
    assert grid.cell_at(1, 1) == Cell(1, 1)

    assert grid.cell_at(-1, 0) is None
    assert grid.cell_at(0, -1) is None
    assert grid.cell_at(4, 0) is None
    assert grid.cell_at(0, 4) is None
def test_cell_access() -> None:
    grid = Grid(2, 2)

    assert grid.get_cell(0, 0) == Cell(0, 0)  # type: ignore
    assert grid.get_cell(0, 1) == Cell(0, 1)  # type: ignore
    assert grid.get_cell(1, 0) == Cell(1, 0)  # type: ignore
    assert grid.get_cell(1, 1) == Cell(1, 1)  # type: ignore

    assert grid.get_cell(-1, 0) is None
    assert grid.get_cell(0, -1) is None
    assert grid.get_cell(4, 0) is None
    assert grid.get_cell(0, 4) is None