available_maps = [ # {'name': 'fork_corridor.wad', 'map': 'MAP01'}, # {'name': 'simple_corridor.wad', 'map': 'MAP01', 'cfg': 'training.cfg'}, # {'name': 'simple_corridor_distance.wad', 'map': 'MAP01', 'cfg': 'training.cfg'}, # {'name': 'my_way_home.wad', 'map': 'MAP01', 'cfg': 'my_way_home.cfg'}, # {'name': 'deadly_corridor.wad', 'map': 'MAP01', 'cfg': 'deadly_corridor.cfg'}, # {'name': 'basic.wad', 'map': 'map01', 'cfg': 'basic.cfg'}, # {'name': 't_corridor.wad', 'map': 'MAP01'}, # {'name': 'doom1_converted.wad', 'map': 'E1M1', 'cfg': 'training_fullmap.cfg'}, { 'name': 'doom1_e1m1_door1.wad', 'map': 'E1M1', 'cfg': 'training_fullmap.cfg' }, ] game = vzd.DoomGame() setup_game(game, choice(available_maps)) n_actions = game.get_available_buttons_size() actions = build_all_actions(n_actions) tf.config.experimental_run_functions_eagerly(False) # Run this many episodes frame_skip = 4 episodes = 10000 update_steps = 1000 resolution = (320, 240) dims = (resolution[1] // 4, resolution[0] // 4) frames_per_state = 4 account_time_reward = False account_dist_reward = False
def __init__(self, level, **kwargs): """ Base class for Gym interface for ViZDoom. Child classes are defined in vizdoom_env_definitions.py, that contain the level parameter and pass through any kwargs from gym.make() :param level: index of level in the CONFIGS list above :param kwargs: keyword arguments from gym.make(env_name_string, **kwargs) call. 'depth' will render the depth buffer and 'labels' will render the object labels and return it in the observation. Note that the observation will be a list with the screen buffer as the first element. If no kwargs are provided (or depth=False and labels=False) the observation will be of type np.ndarray. """ # parse keyword arguments self.depth = kwargs.get("depth", False) self.labels = kwargs.get("labels", False) self.position = kwargs.get("position", False) self.health = kwargs.get("health", False) # init game self.game = vzd.DoomGame() self.game.set_screen_resolution(vzd.ScreenResolution.RES_640X480) scenarios_dir = os.path.join(os.path.dirname(__file__), "scenarios") self.game.load_config(os.path.join(scenarios_dir, CONFIGS[level][0])) self.game.set_window_visible(False) self.game.set_depth_buffer_enabled(self.depth) self.game.set_labels_buffer_enabled(self.labels) self.game.clear_available_game_variables() if self.position: self.game.add_available_game_variable(vzd.GameVariable.POSITION_X) self.game.add_available_game_variable(vzd.GameVariable.POSITION_Y) self.game.add_available_game_variable(vzd.GameVariable.POSITION_Z) self.game.add_available_game_variable(vzd.GameVariable.ANGLE) if self.health: self.game.add_available_game_variable(vzd.GameVariable.HEALTH) self.game.init() self.state = None self.viewer = None self.action_space = spaces.Discrete(CONFIGS[level][1]) # specify observation space(s) list_spaces = [ spaces.Box( 0, 255, ( self.game.get_screen_height(), self.game.get_screen_width(), self.game.get_screen_channels(), ), dtype=np.uint8, ) ] if self.depth: list_spaces.append( spaces.Box( 0, 255, ( self.game.get_screen_height(), self.game.get_screen_width(), ), dtype=np.uint8, )) if self.labels: list_spaces.append( spaces.Box( 0, 255, ( self.game.get_screen_height(), self.game.get_screen_width(), ), dtype=np.uint8, )) if self.position: list_spaces.append(spaces.Box(-np.Inf, np.Inf, (4, 1))) if self.health: list_spaces.append(spaces.Box(0, np.Inf, (1, 1))) if len(list_spaces) == 1: self.observation_space = list_spaces[0] else: self.observation_space = spaces.Tuple(list_spaces)
def __init__( self, level, frame_skip=1, max_buttons_pressed=1, ): """ Base class for Gym interface for ViZDoom. Thanks to https://github.com/shakenes/vizdoomgym Child classes are defined in gym_env_defns.py, Arguments: level (str): path to the config file to load. Most settings should be set by this config file. frame_skip (int): how many frames should be advanced per action. 1 = take action on every frame. Default: 1. max_buttons_pressed (int): defines the number of binary buttons that can be selected at once. Default: 1. Should be >= 0. If < 0 a RuntimeError is raised. If == 0, the binary action space becomes MultiDiscrete([2] * num_binary_buttons) and [0, num_binary_buttons] number of binary buttons can be selected. If > 0, the binary action space becomes Discrete(n) and [0, max_buttons_pressed] number of binary buttons can be selected. This environment forces window to be hidden. Use `render()` function to see the game. Observations are dictionaries with different amount of entries, depending on if depth/label buffers were enabled in the config file (CHANNELS == 1 if GRAY8, else 3): "screen" = the screen image buffer (always available) in shape (HEIGHT, WIDTH, CHANNELS) "depth" = the depth image in shape (HEIGHT, WIDTH, 1), if enabled by the config file, "labels" = the label image buffer in shape (HEIGHT, WIDTH, 1), if enabled by the config file. For info on labels, access `env.state.labels` variable. "automap" = the automap image buffer in shape (HEIGHT, WIDTH, CHANNELS), if enabled by the config file "gamevariables" = all game variables, in the order specified by the config file Action space can be a single one of binary/continuous action space, or a Dict containing both. "binary": = MultiDiscrete([2] * num_binary_buttons): if max_buttons_pressed == 0 = Discrete(n): if max_buttons_pressed > 1 "continuous": = Box(float32.min, float32.max, (num_delta_buttons,), float32). """ self.frame_skip = frame_skip # init game self.game = vzd.DoomGame() self.game.load_config(level) self.game.set_window_visible(False) screen_format = self.game.get_screen_format() if screen_format != vzd.ScreenFormat.RGB24 and screen_format != vzd.ScreenFormat.GRAY8: warnings.warn( f"Detected screen format {screen_format.name}. Only RGB24 and GRAY8 are supported in the Gym" f" wrapper. Forcing RGB24.") self.game.set_screen_format(vzd.ScreenFormat.RGB24) self.state = None self.window_surface = None self.isopen = True self.channels = 3 if screen_format == vzd.ScreenFormat.GRAY8: self.channels = 1 self.depth = self.game.is_depth_buffer_enabled() self.labels = self.game.is_labels_buffer_enabled() self.automap = self.game.is_automap_buffer_enabled() # parse buttons defined by config file self.__parse_available_buttons() # check for valid max_buttons_pressed if max_buttons_pressed > self.num_binary_buttons > 0: warnings.warn( f"max_buttons_pressed={max_buttons_pressed} " f"> number of binary buttons defined={self.num_binary_buttons}. " f"Clipping max_buttons_pressed to {self.num_binary_buttons}.") max_buttons_pressed = self.num_binary_buttons elif max_buttons_pressed < 0: raise RuntimeError( f"max_buttons_pressed={max_buttons_pressed} < 0. Should be >= 0. " ) # specify action space(s) self.max_buttons_pressed = max_buttons_pressed self.action_space = self.__get_action_space() # specify observation space(s) self.observation_space = self.__get_observation_space() self.game.init()