Exemplo n.º 1
0
def create_random_maze(maze_card_factory=None):
    """ Generates a random maze state.
    Corners of the maze are fixed as corners
    """
    fixed_cards = {
        BoardLocation(0, 0): MazeCard(out_paths=MazeCard.CORNER, rotation=90),
        BoardLocation(0, 6): MazeCard(out_paths=MazeCard.CORNER, rotation=180),
        BoardLocation(6, 6): MazeCard(out_paths=MazeCard.CORNER, rotation=270),
        BoardLocation(6, 0): MazeCard(out_paths=MazeCard.CORNER, rotation=0)
    }

    if not maze_card_factory:
        maze_card_factory = MazeCardFactory()
    maze = Maze()

    def card_at(location):
        if location in fixed_cards:
            return maze_card_factory.create_instance(
                fixed_cards[location].out_paths,
                fixed_cards[location].rotation)
        return maze_card_factory.create_random_maze_card()

    for location in maze.maze_locations:
        maze[location] = card_at(location)
    return maze
Exemplo n.º 2
0
def test_maze_locations_returns_list_of_all_maze_locations_for_size_9():
    """ Test maze_locations """
    maze = Maze(maze_size=9)
    maze_locations = [location for location in maze.maze_locations]
    for row in range(maze.maze_size):
        for column in range(maze.maze_size):
            assert BoardLocation(row, column) in maze_locations
Exemplo n.º 3
0
def create_maze(maze_string, maze_card_factory=None):
    """ Reads a multi-line string representing a labyrinth configuration.
    Each maze card is a 3*3 substring of this multiline string. Walls are represented by '#',
    paths with '.'. After each field, there is one delimiter symbol, both horizontally and vertically.
    First line starts at index 1. """
    if not maze_card_factory:
        maze_card_factory = MazeCardFactory()

    maze = Maze()

    lines = maze_string.splitlines()[1:]
    maze_size = len(lines[0]) // 4
    maze = Maze(maze_size=maze_size)

    def field(row, col):
        row_lines = lines[row * 4:row * 4 + 3]
        field_lines = [row_line[col * 4:col * 4 + 3] for row_line in row_lines]
        return field_lines

    def create_maze_card(field):
        line_to_maze_card = {
            "###...###": (MazeCard.STRAIGHT, 90),
            "#.##.##.#": (MazeCard.STRAIGHT, 0),
            "#.##..###": (MazeCard.CORNER, 0),
            "####..#.#": (MazeCard.CORNER, 90),
            "###..##.#": (MazeCard.CORNER, 180),
            "#.#..####": (MazeCard.CORNER, 270),
            "#.##..#.#": (MazeCard.T_JUNCT, 0),
            "###...#.#": (MazeCard.T_JUNCT, 90),
            "#.#..##.#": (MazeCard.T_JUNCT, 180),
            "#.#...###": (MazeCard.T_JUNCT, 270),
            "#.#...#.#": (MazeCard.CROSS, 0)
        }
        line = "".join(field)
        try:
            maze_card_parameters = line_to_maze_card[line]
            return maze_card_factory.create_instance(*maze_card_parameters)
        except KeyError:
            return None

    for location in maze.maze_locations:
        maze[location] = create_maze_card(field(location.row, location.column))

    return maze
Exemplo n.º 4
0
def test_is_inside_returns_true_for_corner_location():
    """ Test is_inside """
    maze = Maze(maze_size=7)
    assert maze.is_inside(BoardLocation(maze.maze_size-1, maze.maze_size-1))
    assert maze.is_inside(BoardLocation(0, maze.maze_size-1))
    maze = Maze(maze_size=9)
    assert maze.is_inside(BoardLocation(maze.maze_size-1, 3))
    assert maze.is_inside(BoardLocation(4, maze.maze_size-1))
Exemplo n.º 5
0
def _dto_to_maze_cards_and_dictionary(maze_dto):
    leftover_card = None
    maze_card_by_id = {}
    maze_size = maze_dto[MAZE_SIZE]
    maze = Maze(maze_size=maze_size)
    for maze_card_dto in maze_dto[MAZE_CARDS]:
        maze_card, board_location = _dto_to_maze_card(maze_card_dto)
        if board_location is None:
            leftover_card = maze_card
        else:
            maze[board_location] = maze_card
        maze_card_by_id[maze_card.identifier] = maze_card
    return maze, leftover_card, maze_card_by_id
Exemplo n.º 6
0
def test_is_inside_returns_true_for_inside_location():
    """ Test is_inside """
    maze = Maze(maze_size=7)
    assert maze.is_inside(BoardLocation(3, 3))
    assert maze.is_inside(BoardLocation(1, 5))
    maze = Maze(maze_size=9)
    assert maze.is_inside(BoardLocation(7, 7))
    assert maze.is_inside(BoardLocation(7, 1))
Exemplo n.º 7
0
def create_maze_and_leftover(size=7):
    """ Generates a random maze state with a given odd size.
    The layout rules of the original game are obeyed, with a few generalizations for sizes > 7.
    Corners of the maze are fixed as corners.
    All other fixed maze cards are t-junctions. If there is a fixed middle maze card (for size = 4k + 1), it is a cross.
    The trunk of a fixed t-junction points to the center,
    e.g. the t-junction at position (0, 2) is rotated by 90 degrees (pointing S).
    If the t-junction is placed on the diagonal, it behaves as if it were placed in
    a counter-clockwise position: (2, 2) points to W.
    For a size of 7 (original game), there are 16 fixed cards. 15 corners, 6 t-junctions, and 13 straights are then
    randomly placed on the board, with the last remaing card beeing returned as the leftover.
    The ratios are approximately kept for other sizes, rounding in favor of corners and then straights.
    """
    if _even(size) or not 2 < size < 32:
        raise InvalidSizeException(
            "Requested size {} is not an odd number between 2 and 32.".format(
                size))
    maze = Maze(maze_size=size)

    fixed_cards = _determine_fixed_cards(size)
    remaining = size * size + 1 - len(fixed_cards)
    free_cards_out_paths = _determine_free_cards_out_paths(remaining)
    card_factory = MazeCardFactory()
    free_cards = [
        card_factory.create_random_maze_card(out_paths=out_paths)
        for out_paths in free_cards_out_paths
    ]
    random.shuffle(free_cards)
    card_iter = iter(free_cards)

    for location in maze.maze_locations:
        if location in fixed_cards:
            maze[location] = card_factory.create_instance(
                fixed_cards[location].out_paths,
                fixed_cards[location].rotation)
        else:
            maze[location] = card_iter.__next__()

    leftover = card_iter.__next__()
    return maze, leftover
Exemplo n.º 8
0
def _determine_fixed_cards(size):
    """ Determines the locations, out paths and rotations for the fixed cards,
    according to the layout of the original game. The layout is generalized to arbitrary
    sizes.
    Returns a map from location to MazeCard. """
    maze = Maze(maze_size=size)
    border = size - 1
    center = border // 2
    fixed_corners = {
        BoardLocation(0, 0):
        MazeCard(out_paths=MazeCard.CORNER, rotation=90),
        BoardLocation(0, border):
        MazeCard(out_paths=MazeCard.CORNER, rotation=180),
        BoardLocation(border, border):
        MazeCard(out_paths=MazeCard.CORNER, rotation=270),
        BoardLocation(border, 0):
        MazeCard(out_paths=MazeCard.CORNER, rotation=0)
    }
    fixed_center = {}
    if border % 4 == 0:
        fixed_center[BoardLocation(
            center, center)] = MazeCard(out_paths=MazeCard.CROSS)
    fixed_locations = [
        location for location in maze.maze_locations
        if _even(location.column) and _even(location.row)
    ]
    fixed_t_juncts_locations = [
        location for location in fixed_locations
        if location not in fixed_corners and location not in fixed_center
    ]

    fixed_t_juncts = {
        location: MazeCard(out_paths=MazeCard.T_JUNCT,
                           rotation=_rotation_of_fixed_t_junct(location, size))
        for location in fixed_t_juncts_locations
    }
    fixed_cards = {**fixed_corners, **fixed_t_juncts, **fixed_center}
    return fixed_cards
Exemplo n.º 9
0
def test_maze_locations_returns_list_of_correct_size_for_size_9():
    """ Test maze_locations """
    maze = Maze(maze_size=9)
    maze_locations = [location for location in maze.maze_locations]
    assert len(maze_locations) == maze.maze_size * maze.maze_size
Exemplo n.º 10
0
def test_getter_returns_set_card():
    """ Tests setter and getter """
    maze = Maze()
    maze_card = MazeCard()
    maze[BoardLocation(1, 1)] = maze_card
    assert maze[BoardLocation(1, 1)] == maze_card
Exemplo n.º 11
0
def test_is_inside_returns_false_for_outside_locations():
    """ Test is_inside """
    maze = Maze(maze_size=7)
    assert not maze.is_inside(BoardLocation(-1, 4))
    assert not maze.is_inside(BoardLocation(maze.maze_size, 2))
    assert not maze.is_inside(BoardLocation(0, 14))
    assert not maze.is_inside(BoardLocation(14, -14))
    assert not maze.is_inside(BoardLocation(7, 7))
    maze = Maze(maze_size=9)
    assert not maze.is_inside(BoardLocation(14, -14))
    assert not maze.is_inside(BoardLocation(5, 9))
Exemplo n.º 12
0
def test_maze_locations_returns_list_in_ascending_order_for_size_9():
    """ Test maze_locations """
    maze = Maze(maze_size=9)
    maze_locations = [location for location in maze.maze_locations]
    _assert_sorted_board_locations(maze_locations)