コード例 #1
0
ファイル: env.py プロジェクト: sumeetpathania/DDQN
class RocketEnv():
    def __init__(self):
        self.max_num_enemies = 20
        self.max_clouds = 6
        self.enemy_timer = 1
        self.cloud_timer = 1

        self.state_size = self.max_num_enemies * 2 + 2
        high = np.array([np.inf] * self.state_size)
        self.observation_space = spaces.Box(-high, high)
        self.action_space = spaces.Discrete(5)
        self._max_episode_steps = np.inf

    def reset(self):
        '''reset the environment, called at the beginning of each episode
        :return curr_state (1d array): current state'''
        pygame.init()
        self.done = False

        # Clock for framerate
        self.clock = pygame.time.Clock()

        # screen
        self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))

        # Create custom events for adding a new enemy and cloud
        self.ADDENEMY = pygame.USEREVENT + 1
        pygame.time.set_timer(self.ADDENEMY, self.enemy_timer)
        self.ADDCLOUD = pygame.USEREVENT + 1
        pygame.time.set_timer(self.ADDCLOUD, self.cloud_timer)

        # Create our 'player'
        self.player = Player()

        # Create groups to hold enemy sprites, cloud sprites, and all sprites
        self.enemies = pygame.sprite.Group()
        self.clouds = pygame.sprite.Group()
        self.all_sprites = pygame.sprite.Group()
        self.all_sprites.add(self.player)

        curr_state = self.__get_curr_state()
        return curr_state

    def step(self, action):
        '''step on action
        :param action (int): action chosen by the agent
        :return state (1d array): current state after taking action
        :return reward (float): constant reward of 1
        :return done (bool): if the episode is finished
        :return info (dict): empty dict
        '''
        if self.done:
            raise TypeError(
                'Unable to step on action since episode is done.. Call reset() to start new episode'
            )

        for event in pygame.event.get():
            # Should we add a new enemy?
            if event.type == self.ADDENEMY:
                # Create the new enemy, and add it to our sprite groups
                if len(self.enemies) < self.max_num_enemies:
                    new_enemy = Enemy()
                    self.enemies.add(new_enemy)
                    self.all_sprites.add(new_enemy)

            # adding a new cloud
            if event.type == self.ADDCLOUD:
                if len(self.clouds) < self.max_clouds:
                    new_cloud = Cloud()
                    self.clouds.add(new_cloud)
                    self.all_sprites.add(new_cloud)

        # Update position of rocket player with action taken
        self.player.update(action)

        # Update the position of our enemies and clouds
        self.enemies.update()
        self.clouds.update()

        # background colour
        self.screen.fill((135, 206, 235))

        # Draw all our sprites
        for entity in self.all_sprites:
            self.screen.blit(entity.surf, entity.rect)

        # Check if any enemies have collided with the player
        if pygame.sprite.spritecollideany(self.player, self.enemies):
            # If so, remove the player
            self.player.kill()
            self.done = True

        # Ensure we maintain a 30 frames pe second rate
        #self.clock.tick(1000)

        curr_state = self.__get_curr_state()
        reward = 1
        info = {}
        return curr_state, reward, self.done, info

    def render(self):
        '''display the enviroment'''
        pygame.display.flip()
        self.clock.tick(27)

    def __get_curr_state(self):
        '''get current state of the environment
        :return state (1d array): state vector stacked of rocket and enemy positions'''
        all_pos = np.zeros((self.max_num_enemies + 1, 2))
        rocket_pos = self.player.get_position()
        all_pos[0] = rocket_pos
        idx = 1
        for enemy in self.enemies:
            all_pos[idx] = enemy.get_position()
            idx += 1
            if idx > self.max_num_enemies + 1:
                raise ValueError(
                    'Implementation error: too many enemies {} for env state vector'
                    .format(idx))

        state = all_pos.flatten()
        if len(state) != self.state_size:
            raise ValueError(
                'Implementation Error: env state vector of size {} does not match state size {}'
                .format(len(all_pos), self.state_size))

        return state

    def close(self):
        pygame.display.flip()
        print('closing RocketEnv')
        time.sleep(0.5)
        pygame.quit()