Ejemplo n.º 1
0
 def __init__(self):
     # Initialize Pygame
     pygame.init()
     # Initialize display
     self.screen = pygame.display.set_mode(
         (settings.SCREEN_WIDTH, settings.SCREEN_HEIGHT),
         Escape.fullscreen())
     pygame.display.set_caption(settings.CAPTION)
     # Initialize Pygame interface
     self.pgi = PgInterface()
     # Initialize game
     self.game_status = "game in progress"
     tile_size = self.pgi.tile_side, self.pgi.tile_side
     wall_image = PgImage.load_crop(const.TEXTURE_ATLAS,
                                    const.CROP_WALL_POSITION,
                                    const.CROP_SIZE, tile_size)
     path_image = PgImage.load_crop(const.TEXTURE_ATLAS,
                                    const.CROP_PATH_POSITION,
                                    const.CROP_SIZE, tile_size)
     self.maze = Maze(wall_image, path_image)
     location = self.maze.location(const.MAZE_START)
     image = PgImage.load(const.MACGYVER_FILE, tile_size)
     self.macgyver = MacGyver(location, image)
     location = self.maze.location(const.MAZE_EXIT)
     image = PgImage.load(const.GUARDIAN_FILE, tile_size)
     self.guardian = Guardian(location, image)
     self.items = Items(self.maze.free_paths(), tile_size)
Ejemplo n.º 2
0
    def test_example_maze_from_instructions(self, example_maze):
        maze = Maze(num_rows=example_maze[0],
                    num_columns=example_maze[1],
                    cell_values=example_maze[2])
        maze.solve()

        assert maze.best_path == ['up', 'up', 'left']
Ejemplo n.º 3
0
def maze():
    width = None
    height = None
    try:
        width = int(request.args.get("height"))
        height = int(request.args.get("width"))
    except Exception as e:
        app.logger.error(
            'New maze attempted with invalid dimensions %s and %d at %s',
            width, height, str(datetime.today()))
    else:
        if width and height:
            environment = Maze(height, width)
            return jsonify({'maze': environment._json_repr()})
Ejemplo n.º 4
0
def maze():
    width = None
    height = None
    try:
        width = int(request.args.get("height"))
        height = int(request.args.get("width"))
    except Exception as e:
        app.logger.error(
            'New maze attempted with invalid dimensions %s and %d at %s',
            width,
            height,
            str(datetime.today()))
    else:
        if width and height:
            environment = Maze(height, width)
            return jsonify({'maze': environment._json_repr()})
Ejemplo n.º 5
0
def maze_solver(filepath: str) -> None:
    mazes = read_file(filepath=filepath)
    for index, item in enumerate(mazes, start=1):
        num_rows, num_columns, cell_values = item
        logging.debug('*' * 50)
        logging.debug(f'Processing maze: {index}')
        logging.debug('*' * 50)

        maze = Maze(num_rows=num_rows, num_columns=num_columns, cell_values=cell_values)
        maze.solve()

        logging.debug(f'Start position: {maze.start_position}')
        logging.debug(f'End position: {maze.end_position}')
        logging.debug(f'Mines located at: {maze.mines}')

        print(maze.best_path)
Ejemplo n.º 6
0
    def __init__(self):
        self.width = 1920  # Set screen width
        self.height = 1080  # Set screen height
        self.cell_size = 4  # Determine the size of a cell on screen

        self.title = "Maze Solver"
        # Create a new game of life that will fit inside our window
        self.maze = Maze(self.width // (self.cell_size * 2),
                         self.height // (self.cell_size * 2))
        self.generator = DepthFirstSearchGenerator(self.maze)

        t = self.maze.get_tile(0, 0)
        t.add_path((0, 1))
        t.add_path((1, 0))

        self.solver = BreadthFirstSolver(self.maze)
        self.skip = False
        self.solving = False
        self.tracing = False
Ejemplo n.º 7
0
class Screen:
    def __init__(self):
        self.width = 1920  # Set screen width
        self.height = 1080  # Set screen height
        self.cell_size = 4  # Determine the size of a cell on screen

        self.title = "Maze Solver"
        # Create a new game of life that will fit inside our window
        self.maze = Maze(self.width // (self.cell_size * 2),
                         self.height // (self.cell_size * 2))
        self.generator = DepthFirstSearchGenerator(self.maze)

        t = self.maze.get_tile(0, 0)
        t.add_path((0, 1))
        t.add_path((1, 0))

        self.solver = BreadthFirstSolver(self.maze)
        self.skip = False
        self.solving = False
        self.tracing = False

    def draw_tile(self, surface, tile, x, y):
        if tile.get_status() == Cell.ANALYZING:
            colour = (255, 0, 0)
        elif tile.get_status() == Cell.FOLLOWING:
            colour = (0, 255, 0)
        else:
            colour = (255, 255, 255)

        pygame.draw.rect(surface, colour,
                         (self.cell_size * x, self.cell_size * y,
                          self.cell_size, self.cell_size))

        if tile.get_status() == Cell.FOLLOWING:
            route = tile.get_route()
            pygame.draw.rect(surface, colour,
                             (self.cell_size * (x + route[0]), self.cell_size *
                              (y + route[1]), self.cell_size, self.cell_size))
        else:
            for path in tile.get_paths():
                pygame.draw.rect(
                    surface, colour,
                    (self.cell_size * (x + path[0]), self.cell_size *
                     (y + path[1]), self.cell_size, self.cell_size))

    def render(self):
        # Create blank surface and fill with white
        surface = pygame.Surface((self.width, self.height))

        for y in range(1, (self.maze.get_height() * 2), 2):
            for x in range(1, (self.maze.get_width() * 2), 2):
                tile = self.maze.get_tile(x // 2, y // 2)
                if len(tile.get_paths()) > 0:
                    self.draw_tile(surface, tile, x, y)

        return surface

    def update(self):
        if self.tracing:
            if self.skip:
                self.solver.trace_path()
                self.skip = False
            else:
                self.solver.trace_path_step()
        elif self.solving:
            if self.skip:
                self.solver.solve()
                self.skip = False
                self.solving = True
            else:
                self.tracing = not self.solver.step()
        else:
            if self.skip:
                self.generator.generate()
                self.skip = False
            else:
                self.solving = not self.generator.step()

    def __game_loop(self):
        clock = pygame.time.Clock()
        pygame.mouse.set_visible(False)

        while True:
            # Regulate framerate
            clock.tick(60)

            # Check for any useful events
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    self.quit()  # player has quit the game
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_SPACE:
                        self.skip = True
                    elif event.key == pygame.K_ESCAPE:
                        self.quit()

            self.update()

            # Display the game state
            render = self.render()
            self.screen.blit(render, (0, 0))
            pygame.display.flip()

    def __initialize_display(self):
        self.screen = pygame.display.set_mode((self.width, self.height))
        pygame.display.set_caption(self.title)

    def run(self):
        self.__initialize_display()
        self.__game_loop()

    def quit(self):
        exit()
Ejemplo n.º 8
0
class Escape:
    """

    The Escape object initializes and runs the game.

    Class attributes:
        dirty_rects (list [pygame.Rects]): List of Rects used to update the
        altered areas of the screen.

    Attributes:
        screen (pygame.Surface): The display Surface.
        pgi (pginterface.PgInterface): The Pygame interface.
        game_status (str): The status of the game.
            {"game in progress", "game won", "game lost", "game over",
             "game canceled"}
        maze (maze.Maze): Represents the labyrinth.
        macgyver (macgyver.MacGyver): Represents MacGyver.
        guardian (guardian.Guardian): Represents the Guardian.
        items (items.Items): Handles with items.
    """
    dirty_rects = []

    def __init__(self):
        # Initialize Pygame
        pygame.init()
        # Initialize display
        self.screen = pygame.display.set_mode(
            (settings.SCREEN_WIDTH, settings.SCREEN_HEIGHT),
            Escape.fullscreen())
        pygame.display.set_caption(settings.CAPTION)
        # Initialize Pygame interface
        self.pgi = PgInterface()
        # Initialize game
        self.game_status = "game in progress"
        tile_size = self.pgi.tile_side, self.pgi.tile_side
        wall_image = PgImage.load_crop(const.TEXTURE_ATLAS,
                                       const.CROP_WALL_POSITION,
                                       const.CROP_SIZE, tile_size)
        path_image = PgImage.load_crop(const.TEXTURE_ATLAS,
                                       const.CROP_PATH_POSITION,
                                       const.CROP_SIZE, tile_size)
        self.maze = Maze(wall_image, path_image)
        location = self.maze.location(const.MAZE_START)
        image = PgImage.load(const.MACGYVER_FILE, tile_size)
        self.macgyver = MacGyver(location, image)
        location = self.maze.location(const.MAZE_EXIT)
        image = PgImage.load(const.GUARDIAN_FILE, tile_size)
        self.guardian = Guardian(location, image)
        self.items = Items(self.maze.free_paths(), tile_size)

    @staticmethod
    def fullscreen():
        '''

        Returns the pygame flag for the selected fullscreen or windowed mode.

            Returns:
                fullscreen (int):
                If fullscreen mode is selected, returns the pygame fullscreen
                flag. If windowed mode is selected, returns 0.
        '''
        if settings.FULLSCREEN:
            fullscreen = pygame.FULLSCREEN
        else:
            fullscreen = 0
        return fullscreen

    @staticmethod
    def command(key):
        '''

        Returns the command corresponding to the keyboard key pressed by the
        player.

            Args:
                key (int): The key pressed by the player.

            Returns:
                command (str): The command corresponding to the keyboard key
                pressed by the player.
        '''
        hotkeys = {
            "move left": pygame.K_LEFT,
            "move right": pygame.K_RIGHT,
            "move up": pygame.K_UP,
            "move down": pygame.K_DOWN,
            "exit game": pygame.K_ESCAPE,
            "validate": pygame.K_SPACE
        }
        command = "unknown"
        for kb_command in hotkeys:
            if key == hotkeys[kb_command]:
                command = kb_command
                break
        return command

    def destination(self, command):
        '''

        Returns the coordinates of the destination corresponding to MacGyver's
        move.

            Args:
                command (string): The command is MacGyver's move action.

            Returns:
                x_coordinate (tuple), y_coordinate (tuple):
                The coordinates of the destination corresponding to MacGyver's
                move.
        '''
        x_coordinate, y_coordinate = self.macgyver.position
        if command == "move left":
            x_coordinate -= 1
        elif command == "move right":
            x_coordinate += 1
        elif command == "move up":
            y_coordinate -= 1
        elif command == "move down":
            y_coordinate += 1
        return x_coordinate, y_coordinate

    def display_maze_panel(self):
        '''Update and displays the maze panel.'''
        self.pgi.blit_maze_panel(self.maze, self.macgyver, self.guardian,
                                 self.items)
        self.screen.blit(self.pgi.maze_panel, self.pgi.maze_rect)
        pygame.display.update(self.pgi.maze_rect)

    def update_sprite(self, origin, destination):
        '''

        Update MacGyver's sprite.

        This method blits a path image at the source and destination positions
        in the labyrinth translated to the screen. MacGyver's image is then
        blited at destination position in the labyrinth translated to the
        screen unless game is lost. If game is lost, it's the Guardian's image
        which is blited. The dirty rects are updated for both blits.

            Args:
                origin (tuples): MacGyver's current coordinates in the
                    labyrinth.
                destination (tuples): Coordinates of the destination of
                    MacGyver's move in the labyrinth.
        '''
        # Blit a path at origin
        rect = self.pgi.abs_translate(origin)
        self.screen.blit(self.maze.path_image, rect)
        self.dirty_rects.append(rect)
        # Blit a path at destination
        rect = self.pgi.abs_translate(destination)
        self.screen.blit(self.maze.path_image, rect)
        # Blit character at destination
        if self.game_status != "game lost":
            image = self.macgyver.image
        else:
            image = self.guardian.image
        self.screen.blit(image, rect)
        self.dirty_rects.append(rect)

    def update_backpack_bar(self):
        '''Update the backpack bar and the dirty rects.'''
        self.pgi.blit_backpack_bar(self.items.backpack)
        self.screen.blit(self.pgi.backpack_bar, self.pgi.backpack_rect)
        self.dirty_rects.append(self.pgi.backpack_rect)

    def update_log_bar(self, message):
        '''

        Update the log bar with a message and the dirty rects.

            Args:
                message (str): The message to be displayed in the log bar.

        '''
        self.pgi.blit_log_bar(message)
        self.screen.blit(self.pgi.log_bar, self.pgi.log_rect)
        self.dirty_rects.append(self.pgi.log_rect)

    def update_ending_screen(self, ending, message):
        '''

        Updates the ending screen.

        This method clears the log bar and updates the maze panel as
        background with the ending text and message writed on it. The dirty
        rects are updated.

            Args:
                ending (str): The ending text to be displayed.
                message (str): The message to be displayed at the end of the
                    ending text.

        '''
        # Clear logs
        self.pgi.clear_log_bar()
        self.screen.blit(self.pgi.log_bar, self.pgi.log_rect)
        self.dirty_rects.append(self.pgi.log_rect)
        # Display ending screen
        # Update text background
        self.pgi.maze_panel = self.screen.subsurface(self.pgi.maze_rect)
        self.pgi.maze_panel = self.pgi.maze_panel.convert()
        # Blit background and text
        self.pgi.blit_ending_screen(ending, message)
        self.screen.blit(self.pgi.maze_panel, self.pgi.maze_rect)
        self.dirty_rects.append(self.pgi.maze_rect)

    def display_dirty_rects(self):
        '''Display all the altered parts of the screen.'''
        pygame.display.update(self.dirty_rects)
        self.dirty_rects.clear()

    def move(self, destination):
        '''

        Moves MacGyver to destination and perform his actions.

        This method moves Macgyver to his destination.
        If there is an item at destination, MacGyver gets it, and if MacGyver
        has tree items, he crafts the syringe and the other items are lost.
        In theese cases, the back pack bar and the log bar are updated.
        If the Guardian is at destination, the game status is updated.
        The MacGyver's sprite is then updated and the command line interface
        is printed if needed.
        If game is ending, the ending screen is updated and printed on the
        command line interface if needed.

            Args:
                destination (tuples): Coordinates of the destination of
                    MacGyver in the labyrinth.
        '''
        origin = self.macgyver.position
        self.macgyver.move(destination)
        for item in self.items.materials:
            if destination == item.position:
                self.items.pick_up(item)
                if self.items.items_in_backpack >= 3:
                    self.items.craft()
                    message = "MacGyver got {} and crafted {}.".format(
                        item.description, self.items.syringe.description)
                else:
                    message = "MacGyver got {}.".format(item.description)
                self.update_log_bar(message)
                self.update_backpack_bar()
        if destination == self.guardian.position:
            if self.items.syringe in self.items.backpack:
                self.game_status = "game won"
            else:
                self.game_status = "game lost"
        self.update_sprite(origin, destination)
        if settings.CLI_DISPLAY:
            CliDisplay.print_interface(self.maze.zones, self.macgyver.position,
                                       self.items.backpack,
                                       self.items.materials)
        if self.game_status in ["game won", "game lost"]:
            ending = settings.ENDINGS[self.game_status]
            message = "Press SPACE bar or ESCAPE to quit."
            self.update_ending_screen(ending, message)
            if settings.CLI_DISPLAY:
                CliDisplay.print_ending(settings.CAPTION,
                                        settings.ENDINGS[self.game_status])

    def run(self):
        '''

        Runs the game.

        This method displays the labyrinth and print the command line
        interface if needed. An event loop is then processed until game is
        over or canceled. On a keydown event, the key pressed gives a command
        who is processed. If the player tries to move and there is no
        collision detected, MacGyver moves to his destination. Finally, all
        the altered parts of the screen are displayed.

        '''
        # Display all the maze and all the sprites
        self.display_maze_panel()
        if settings.CLI_DISPLAY:
            CliDisplay.print_interface(self.maze.zones, self.macgyver.position,
                                       self.items.backpack,
                                       self.items.materials)
        # Event loop
        while self.game_status not in ["game canceled", "game over"]:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    self.game_status = "game canceled"
                elif event.type == pygame.KEYDOWN:
                    command = self.command(event.key)
                    if command == "exit game" and \
                            self.game_status not in ["game won", "game lost"]:
                        self.game_status = "game canceled"
                    elif command in ["exit game", "validate"] and \
                            self.game_status in ["game won", "game lost"]:
                        self.game_status = "game over"
                    elif command.startswith("move") and \
                            self.game_status == "game in progress":
                        destination = self.destination(command)
                        if not self.maze.collision_detected(destination):
                            # MacGyver moves
                            self.move(destination)
                            # Display all the altered parts of the screen
                            self.display_dirty_rects()
        if settings.CLI_DISPLAY and self.game_status == "game canceled":
            CliDisplay.print_ending(settings.CAPTION,
                                    settings.ENDINGS[self.game_status])
Ejemplo n.º 9
0
 def test_small_maze(self):
     maze = Maze(2, 2)
     assert True