Beispiel #1
0
class Arkanoid:
    """The game for the machine learning mode
    """

    def __init__(self, fps: int, level: int, \
        record_progress: bool, one_shot_mode: bool):
        self._ml_name = "ml"
        self._ml_execute_time = 1.0 / fps
        self._frame_delayed = 0
        self._instruct_receiver = CommandReceiver( \
            GameInstruction, { "command": \
                [PlatformAction.MOVE_LEFT, PlatformAction.MOVE_RIGHT, PlatformAction.NONE], \
            }, GameInstruction(-1, PlatformAction.NONE))

        self._record_handler = get_record_handler(record_progress, { \
                "status": (GameStatus.GAME_OVER, GameStatus.GAME_PASS) \
            }, get_log_dir())
        self._one_shot_mode = one_shot_mode

        self._init_display()
        self._scene = gamecore.Scene(level, True)

    def _init_display(self):
        pygame.display.init()
        pygame.display.set_caption("Arkanoid")
        self._screen = pygame.display.set_mode(gamecore.scene_area_size)

    def game_loop(self):
        """The main loop of the game in machine learning mode

        The execution order in the loop:
        1. Send the SceneInfo to the machine learning process.
        2. Wait for the key frame (During this period, machine learning process can
           process the SceneInfo and generate the GameInstruction.)
        3. Check if there has a GameInstruction to receive. If it has, receive the
           instruction. Otherwise, generate a dummy one.
        4. Pass the GameInstruction to the game and update the scene (and frame no.)
        5. If the game is over or passed, send the SceneInfo containing the
           game status to the machine learning process, and reset the game.
        6. Back to 1.
        """

        keep_going = lambda: not quit_or_esc()

        comm.wait_ml_ready(self._ml_name)

        while keep_going():
            scene_info = self._scene.fill_scene_info_obj(SceneInfo())
            self._record_handler(scene_info)

            instruction = self._make_ml_execute(scene_info)
            game_status = self._scene.update(instruction.command)

            self._draw_scene()

            if game_status == GameStatus.GAME_OVER or \
               game_status == GameStatus.GAME_PASS:
                scene_info = self._scene.fill_scene_info_obj(SceneInfo())
                self._record_handler(scene_info)
                comm.send_to_ml(scene_info, self._ml_name)

                if self._one_shot_mode:
                    return

                self._scene.reset()
                self._frame_delayed = 0
                # Wait for ml process doing resetting jobs
                comm.wait_ml_ready(self._ml_name)

        pygame.quit()

    def _make_ml_execute(self, scene_info):
        """Send the scene_info to the ml process and wait for the instruction
        """
        comm.send_to_ml(scene_info, self._ml_name)
        time.sleep(self._ml_execute_time)
        instruction = self._instruct_receiver.recv(self._ml_name)

        if instruction.frame != -1 and \
           scene_info.frame - instruction.frame > self._frame_delayed:
            self._frame_delayed = scene_info.frame - instruction.frame
            print("Delayed {} frame(s)".format(self._frame_delayed))

        return instruction

    def _draw_scene(self):
        """Draw the scene to the display
        """
        self._screen.fill((0, 0, 0))
        self._scene.draw_gameobjects(self._screen)
        pygame.display.flip()
Beispiel #2
0
class Snake:
    """
    The game execution manager
    """

    def __init__(self, fps, one_shot_mode, record_progress):
        self._init_pygame()

        self._scene = Scene()

        self._ml_name = "ml"
        self._ml_execution_time = 1 / fps
        self._frame_delayed = 0
        self._cmd_receiver = CommandReceiver(
            GameCommand, {
                "command": SnakeAction,
            }, GameCommand(-1, SnakeAction.NONE))

        self._one_shot_mode = one_shot_mode
        self._record_handler = get_record_handler(record_progress, "ml")

    def _init_pygame(self):
        """
        Initialize the required pygame module
        """
        pygame.display.init()
        pygame.display.set_caption("Snake")
        self._screen = pygame.display.set_mode(
            (Scene.area_rect.width, Scene.area_rect.height + 25))

        pygame.font.init()
        self._font = pygame.font.Font(None, 22)
        self._font_pos = (1, Scene.area_rect.width + 5)

    def game_loop(self):
        """
        The game execution loop
        """
        # Wait for the ml process
        comm.wait_ml_ready(self._ml_name)

        while not quit_or_esc():
            # Generate the scene information
            scene_info = self._scene.get_scene_info()

            # Send the scene information to the ml process
            # and wait the command sent from it
            command = self._make_ml_execute(scene_info)

            # Record the scene information
            scene_info.command = command
            self._record_handler(scene_info)

            # Update the scene
            game_status = self._scene.update(command)

            # If the game is over, reset the scene or
            # quit the game loop if one shot mode is set.
            if game_status == GameStatus.GAME_OVER:
                # Send the scene info with the game over status
                # and record that scene info
                scene_info = self._scene.get_scene_info()
                comm.send_to_ml(scene_info, self._ml_name)
                self._record_handler(scene_info)

                if self._one_shot_mode:
                    return

                self._scene.reset()
                self._frame_delayed = 0

                # Wait for the ml process for the next round
                comm.wait_ml_ready(self._ml_name)

            # Draw the scene to the display
            self._draw_scene()

    def _make_ml_execute(self, scene_info):
        """
        Send the scene info to the ml process and receive the command from it

        The method will wait the ml process to execute the command for a period
        which is decided by the `_ml_execution_time`.
        If the ml process can't send the command in time,
        the method will return a default command.
        """
        comm.send_to_ml(scene_info, self._ml_name)
        time.sleep(self._ml_execution_time)
        game_cmd = self._cmd_receiver.recv(self._ml_name)

        # Check and update the frame delayed
        if (game_cmd.frame != -1 and
            scene_info.frame - game_cmd.frame > self._frame_delayed):
            self._frame_delayed = scene_info.frame - game_cmd.frame

        return game_cmd.command

    def _draw_scene(self):
        """
        Draw the scene to the display
        """
        self._screen.fill((50, 50, 50))
        self._screen.fill((0, 0, 0), Scene.area_rect)
        self._scene.draw_gameobjects(self._screen)

        # Draw score
        font_surface = self._font.render(
            "Score: {}, Frame delayed: {}".format(self._scene.score, self._frame_delayed),
            True, (255, 255, 255))
        self._screen.blit(font_surface, self._font_pos)

        pygame.display.flip()
Beispiel #3
0
class Arkanoid:
    """
    The game for the machine learning mode
    """

    def __init__(self, fps: int, difficulty, level: int, \
        record_progress: bool, one_shot_mode: bool):
        self._ml_name = "ml"
        self._ml_execute_time = 1.0 / fps
        self._frame_delayed = 0
        self._cmd_receiver = CommandReceiver( \
            GameCommand, {
                "command": PlatformAction
            }, GameCommand(-1, PlatformAction.NONE))

        self._record_handler = get_record_handler(record_progress, \
            "ml_" + str(difficulty) + "_" + str(level))
        self._one_shot_mode = one_shot_mode

        self._scene = Scene(difficulty, level)
        self._screen = Screen(Scene.area_rect.size, self._scene.draw_gameobjects)

    def game_loop(self):
        """
        The main loop of the game in machine learning mode

        The execution order in the loop:
        1. Send the SceneInfo to the machine learning process.
        2. Wait for the key frame (During this period, machine learning process can
           process the SceneInfo and generate the GameInstruction.)
        3. Check if there has a command to receive. If it has, receive the
           command. Otherwise, generate a dummy one.
        4. Pass the command received to the game and update the scene.
        5. If the game is over or passed, send the SceneInfo containing the
           game status to the machine learning process, and reset the game.
        6. Back to 1.
        """
        comm.wait_ml_ready(self._ml_name)

        while not quit_or_esc():
            scene_info = self._scene.get_scene_info()
            command = self._make_ml_execute(scene_info)

            scene_info.command = command
            self._record_handler(scene_info)

            game_status = self._scene.update(command)

            self._screen.update(self._scene.catch_ball_times)

            if game_status == GameStatus.GAME_OVER or \
               game_status == GameStatus.GAME_PASS:
                scene_info = self._scene.get_scene_info()
                self._record_handler(scene_info)
                comm.send_to_ml(scene_info, self._ml_name)

                print(game_status.value)

                if self._one_shot_mode:
                    return

                self._scene.reset()
                self._frame_delayed = 0
                # Wait for ml process doing resetting jobs
                comm.wait_ml_ready(self._ml_name)

    def _make_ml_execute(self, scene_info):
        """
        Send the scene_info to the ml process and wait for the instruction
        """
        comm.send_to_ml(scene_info, self._ml_name)
        time.sleep(self._ml_execute_time)
        game_cmd = self._cmd_receiver.recv(self._ml_name)

        if game_cmd.frame != -1 and \
           scene_info.frame - game_cmd.frame > self._frame_delayed:
            self._frame_delayed = scene_info.frame - game_cmd.frame
            print("Delayed {} frame(s)".format(self._frame_delayed))

        return game_cmd.command