def __init__(self): super(DoomDefendCenterEnv, self).__init__() package_directory = os.path.dirname(os.path.abspath(__file__)) self.loader = Loader() self.game = DoomGame() self.game.load_config( os.path.join(package_directory, 'assets/defend_the_center.cfg')) self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) self.game.set_doom_scenario_path( self.loader.get_scenario_path('defend_the_center.wad')) self.screen_height = 480 # Must match .cfg file self.screen_width = 640 # Must match .cfg file self.game.set_window_visible(False) self.viewer = None self.game.init() self.game.new_episode() # 3 allowed actions [0, 13, 14] (must match .cfg file) self.action_space = spaces.HighLow(np.matrix([[0, 1, 0]] * 3)) self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3)) self._seed()
def __init__(self, level): self.previous_level = -1 self.level = level self.game = DoomGame() self.loader = Loader() self.doom_dir = os.path.dirname(os.path.abspath(__file__)) self._mode = 'algo' # 'algo' or 'human' self.no_render = False # To disable double rendering in human mode self.viewer = None self.is_initialized = False # Indicates that reset() has been called self.curr_seed = 0 self.lock = (DoomLock()).get_lock() self.action_space = spaces.MultiDiscrete([[0, 1]] * 38 + [[-10, 10]] * 2 + [[-100, 100]] * 3) self.allowed_actions = list(range(NUM_ACTIONS)) self.screen_height = 480 self.screen_width = 640 self.screen_resolution = ScreenResolution.RES_640X480 self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3)) self._seed() self._configure()
def _load_level(self): # Closing if is_initialized if self.is_initialized: self.is_initialized = False self.game.close() self.game = DoomGame() # Loading Paths if not self.is_initialized: self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) # Common settings self._closed = False self.game.load_config( os.path.join(self.doom_dir, 'assets/%s' % DOOM_SETTINGS[self.level][CONFIG])) self.game.set_doom_scenario_path( self.loader.get_scenario_path(DOOM_SETTINGS[self.level][SCENARIO])) if DOOM_SETTINGS[self.level][MAP] != '': self.game.set_doom_map(DOOM_SETTINGS[self.level][MAP]) self.game.set_doom_skill(DOOM_SETTINGS[self.level][DIFFICULTY]) self.previous_level = self.level self.allowed_actions = DOOM_SETTINGS[self.level][ACTIONS] self.game.set_screen_resolution(self.screen_resolution) # Algo mode if 'human' != self.mode: self.game.set_window_visible(False) self.game.set_mode(Mode.PLAYER) self.no_render = False self.game.init() self._start_episode() self.is_initialized = True return self.game.get_state().image_buffer.copy() # Human mode else: self.game.add_game_args('+freelook 1') self.game.set_window_visible(True) self.game.set_mode(Mode.SPECTATOR) self.no_render = True self.game.init() self._start_episode() self.is_initialized = True self._play_human_mode() return np.zeros(shape=self.observation_space.shape, dtype=np.uint8)
def __init__(self, level): utils.EzPickle.__init__(self) self.previous_level = -1 self.level = level self.game = DoomGame() self.loader = Loader() self.doom_dir = os.path.dirname(os.path.abspath(__file__)) self.mode = 'fast' # 'human', 'fast' or 'normal' self.no_render = False # To disable double rendering in human mode self.viewer = None self.is_initialized = False # Indicates that reset() has been called self.curr_seed = 0 self.action_space = spaces.MultiDiscrete([[0, 1]] * 38 + [[-10, 10]] * 2 + [[-100, 100]] * 3) self.allowed_actions = list(range(NUM_ACTIONS)) self._seed() self._configure()
def __init__(self): super(DoomDefendLineEnv, self).__init__() package_directory = os.path.dirname(os.path.abspath(__file__)) self.loader = Loader() self.game = DoomGame() self.game.load_config( os.path.join(package_directory, 'assets/defend_the_line.cfg')) self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) self.game.set_doom_scenario_path( self.loader.get_scenario_path('defend_the_line.wad')) self.screen_height = 480 # Must match .cfg file self.screen_width = 640 # Must match .cfg file self.game.set_window_visible(False) self.viewer = None self._seed() self.game.init() self.game.new_episode()
def __init__(self): package_directory = os.path.dirname(os.path.abspath(__file__)) self.loader = Loader() self.game = DoomGame() self.game.load_config( os.path.join(package_directory, 'assets/predict_position.cfg')) self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) self.game.set_doom_scenario_path( self.loader.get_scenario_path('predict_position.wad')) self.game.set_doom_map('map01') self.screen_height = 480 # Must match .cfg file self.screen_width = 640 # Must match .cfg file self.game.set_window_visible(False) self.viewer = None self.game.init() self.game.new_episode() self._seed()
def __init__(self): package_directory = os.path.dirname(os.path.abspath(__file__)) self.loader = Loader() self.game = DoomGame() self.game.load_config( os.path.join(package_directory, 'assets/deadly_corridor.cfg')) self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) self.game.set_doom_scenario_path( self.loader.get_scenario_path('deadly_corridor.wad')) self.screen_height = 480 # Must match .cfg file self.screen_width = 640 # Must match .cfg file # action indexes are [0, 9, 10, 12, 13, 14] self.action_space = doom_spaces.HighLow(np.matrix([[0, 1, 0]] * 6)) self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3)) self.game.set_window_visible(False) self.viewer = None self.game.init() self.game.new_episode()
def __init__(self, level): utils.EzPickle.__init__(self) self.previous_level = -1 self.level = level self.game = DoomGame() self.loader = Loader() self.doom_dir = os.path.dirname(os.path.abspath(__file__)) self.mode = 'fast' # 'human', 'fast' or 'normal' self.no_render = False # To disable double rendering in human mode self.viewer = None self.is_initialized = False # Indicates that reset() has been called self.find_new_level = False # Indicates that we need a level change self.curr_seed = 0 self.screen_height = 480 self.screen_width = 640 self.action_space = spaces.HighLow( np.matrix([[0, 1, 0]] * 38 + [[-10, 10, 0]] * 2 + [[-100, 100, 0]] * 3, dtype=np.int8)) self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3)) self.allowed_actions = list(range(NUM_ACTIONS))
def __init__(self): package_directory = os.path.dirname(os.path.abspath(__file__)) self.loader = Loader() self.game = DoomGame() self.game.load_config( os.path.join(package_directory, 'assets/basic.cfg')) self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) self.game.set_doom_scenario_path( self.loader.get_scenario_path('basic.wad')) self.game.set_doom_map('map01') self.screen_height = 480 # Must match .cfg file self.screen_width = 640 # Must match .cfg file # 3 allowed actions [0, 9, 10] (must match .cfg file) self.action_space = doom_spaces.HighLow(np.matrix([[0, 1, 0]] * 3)) self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3)) self.game.set_window_visible(False) self.viewer = None self.sleep_time = 0.02857 # 35 fps = 0.02857 sleep between frames self.game.init() self.game.new_episode()
def __init__(self): super(DoomDefendLineEnv, self).__init__() package_directory = os.path.dirname(os.path.abspath(__file__)) self.loader = Loader() self.game = DoomGame() self.game.load_config(os.path.join(package_directory, 'assets/defend_the_line.cfg')) self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) self.game.set_doom_scenario_path(self.loader.get_scenario_path('defend_the_line.wad')) self.screen_height = 480 # Must match .cfg file self.screen_width = 640 # Must match .cfg file self.game.set_window_visible(False) self.viewer = None self._seed() self.game.init() self.game.new_episode()
def __init__(self, level): utils.EzPickle.__init__(self) self.previous_level = -1 self.level = level self.game = DoomGame() self.loader = Loader() self.doom_dir = os.path.dirname(os.path.abspath(__file__)) self.mode = 'fast' # 'human', 'fast' or 'normal' self.no_render = False # To disable double rendering in human mode self.viewer = None self.is_initialized = False # Indicates that reset() has been called self.curr_seed = 0 self.action_space = spaces.HighLow( np.matrix([[0, 1, 0]] * 38 + [[-10, 10, 0]] * 2 + [[-100, 100, 0]] * 3, dtype=np.int8)) self.allowed_actions = list(range(NUM_ACTIONS)) self._configure()
def __init__(self): package_directory = os.path.dirname(os.path.abspath(__file__)) self.loader = Loader() self.game = DoomGame() self.game.load_config(os.path.join(package_directory, 'assets/predict_position.cfg')) self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) self.game.set_doom_scenario_path(self.loader.get_scenario_path('predict_position.wad')) self.game.set_doom_map('map01') self.screen_height = 480 # Must match .cfg file self.screen_width = 640 # Must match .cfg file self.game.set_window_visible(False) self.viewer = None self.game.init() self.game.new_episode() self._seed()
def __init__(self): package_directory = os.path.dirname(os.path.abspath(__file__)) self.loader = Loader() self.game = DoomGame() self.game.load_config(os.path.join(package_directory, 'assets/my_way_home.cfg')) self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) self.game.set_doom_scenario_path(self.loader.get_scenario_path('my_way_home.wad')) self.screen_height = 480 # Must match .cfg file self.screen_width = 640 # Must match .cfg file # 3 allowed actions [12, 13, 14] (must match .cfg file) self.action_space = doom_spaces.HighLow(np.matrix([[0, 1, 0]] * 3)) self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3)) self.game.set_window_visible(False) self.viewer = None self.game.init() self.game.new_episode()
def __init__(self): super(DoomCorridorEnv, self).__init__() package_directory = os.path.dirname(os.path.abspath(__file__)) self.loader = Loader() self.game = DoomGame() self.game.load_config(os.path.join(package_directory, 'assets/deadly_corridor.cfg')) self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) self.game.set_doom_scenario_path(self.loader.get_scenario_path('deadly_corridor.wad')) self.screen_height = 480 # Must match .cfg file self.screen_width = 640 # Must match .cfg file # action indexes are [0, 9, 10, 12, 13, 14] self.action_space = spaces.HighLow(np.matrix([[0, 1, 0]] * 6)) self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3)) self.game.set_window_visible(False) self.viewer = None self.game.init() self.game.new_episode()
def _load_level(self): # Closing if is_initialized if self.is_initialized: self.is_initialized = False self.game.close() self.game = DoomGame() # Loading Paths if not self.is_initialized: self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) # Common settings self._closed = False self.game.load_config(os.path.join(self.doom_dir, 'assets/%s' % DOOM_SETTINGS[self.level][CONFIG])) self.game.set_doom_scenario_path(self.loader.get_scenario_path(DOOM_SETTINGS[self.level][SCENARIO])) if DOOM_SETTINGS[self.level][MAP] != '': self.game.set_doom_map(DOOM_SETTINGS[self.level][MAP]) self.game.set_doom_skill(DOOM_SETTINGS[self.level][DIFFICULTY]) self.previous_level = self.level self.allowed_actions = DOOM_SETTINGS[self.level][ACTIONS] self.game.set_screen_resolution(self.screen_resolution) # Algo mode if 'human' != self.mode: self.game.set_window_visible(False) self.game.set_mode(Mode.PLAYER) self.no_render = False self.game.init() self._start_episode() self.is_initialized = True return self.game.get_state().image_buffer.copy() # Human mode else: self.game.add_game_args('+freelook 1') self.game.set_window_visible(True) self.game.set_mode(Mode.SPECTATOR) self.no_render = True self.game.init() self._start_episode() self.is_initialized = True self._play_human_mode() return np.zeros(shape=self.observation_space.shape, dtype=np.uint8)
def __init__(self): super(DoomTakeCoverEnv, self).__init__() package_directory = os.path.dirname(os.path.abspath(__file__)) self.loader = Loader() self.game = DoomGame() self.game.load_config(os.path.join(package_directory, 'assets/take_cover.cfg')) self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) self.game.set_doom_scenario_path(self.loader.get_scenario_path('take_cover.wad')) self.game.set_doom_map('map01') self.screen_height = 480 # Must match .cfg file self.screen_width = 640 # Must match .cfg file # 2 allowed actions [9, 10] (must match .cfg file) self.action_space = spaces.HighLow(np.matrix([[0, 1, 0]] * 2)) self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3)) self.game.set_window_visible(False) self.viewer = None self.game.init() self.game.new_episode()
class DoomBasicEnv(doom_env.DoomEnv): """ ------------ Training Mission 1 - Basic ------------ This map is rectangular with gray walls, ceiling and floor. You are spawned in the center of the longer wall, and a red circular monster is spawned randomly on the opposite wall. You need to kill the monster (one bullet is enough). Allowed actions: [0] - ATTACK - Shoot weapon - Values 0 or 1 [9] - MOVE_RIGHT - Move to the right - Values 0 or 1 [10] - MOVE_LEFT - Move to the left - Values 0 or 1 Note: see controls.md for details Rewards: +101 - Killing the monster - 5 - Missing a shot - 1 - Several times per second - Kill the monster faster! Goal: 10 points Kill the monster in 3 secs with 1 shot Ends when: - Monster is dead - Player is dead - Timeout (10 seconds - 350 frames) ----------------------------------------------------- """ def __init__(self): super(DoomBasicEnv, self).__init__() package_directory = os.path.dirname(os.path.abspath(__file__)) self.loader = Loader() self.game = DoomGame() self.game.load_config( os.path.join(package_directory, 'assets/basic.cfg')) self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) self.game.set_doom_scenario_path( self.loader.get_scenario_path('basic.wad')) self.game.set_doom_map('map01') self.screen_height = 480 # Must match .cfg file self.screen_width = 640 # Must match .cfg file self.game.set_window_visible(False) self.viewer = None self.game.init() self.game.new_episode() self._seed() def _seed(self, seed=None): np_random, seed1 = seeding.np_random(seed) # Derive a random seed. seed2 = seeding.hash_seed(seed1 + 1) % 2**32 self.game.set_seed(seed2) # 3 allowed actions [0, 9, 10] (must match .cfg file) self.action_space = spaces.HighLow(np.matrix([[0, 1, 0]] * 3), np_random=np_random) self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3), np_random=np_random) return [seed1, seed2]
class DoomEnv(gym.Env, utils.EzPickle): metadata = {'render.modes': ['human', 'rgb_array'], 'video.frames_per_second': 35} def __init__(self, level): utils.EzPickle.__init__(self) self.previous_level = -1 self.level = level self.game = DoomGame() self.loader = Loader() self.doom_dir = os.path.dirname(os.path.abspath(__file__)) self.mode = 'fast' # 'human', 'fast' or 'normal' self.no_render = False # To disable double rendering in human mode self.viewer = None self.is_initialized = False # Indicates that reset() has been called self.curr_seed = 0 self.action_space = spaces.HighLow( np.matrix([[0, 1, 0]] * 38 + [[-10, 10, 0]] * 2 + [[-100, 100, 0]] * 3, dtype=np.int8)) self.allowed_actions = list(range(NUM_ACTIONS)) self._seed() self._configure() def _configure(self, screen_resolution=ScreenResolution.RES_640X480): # Often agents end up downsampling the observations. Configuring Doom to # return a smaller image yields significant (~10x) speedups if screen_resolution == ScreenResolution.RES_640X480: self.screen_height = 480 self.screen_width = 640 self.screen_resolution = ScreenResolution.RES_640X480 elif screen_resolution == ScreenResolution.RES_160X120: self.screen_height = 120 self.screen_width = 160 self.screen_resolution = ScreenResolution.RES_160X120 self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3)) def _load_level(self): # Closing if is_initialized if self.is_initialized: self.is_initialized = False self.game.close() self.game = DoomGame() # Loading Paths if not self.is_initialized: self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) # Common settings self._closed = False self.game.load_config(os.path.join(self.doom_dir, 'assets/%s' % DOOM_SETTINGS[self.level][CONFIG])) self.game.set_doom_scenario_path(self.loader.get_scenario_path(DOOM_SETTINGS[self.level][SCENARIO])) if DOOM_SETTINGS[self.level][MAP] != '': self.game.set_doom_map(DOOM_SETTINGS[self.level][MAP]) self.game.set_doom_skill(DOOM_SETTINGS[self.level][DIFFICULTY]) self.previous_level = self.level self.allowed_actions = DOOM_SETTINGS[self.level][ACTIONS] self.game.set_screen_resolution(self.screen_resolution) # Algo mode if 'human' != self.mode: self.game.set_window_visible(False) self.game.set_mode(Mode.PLAYER) self.no_render = False self.game.init() self._start_episode() self.is_initialized = True return self.game.get_state().image_buffer.copy() # Human mode else: self.game.add_game_args('+freelook 1') self.game.set_window_visible(True) self.game.set_mode(Mode.SPECTATOR) self.no_render = True self.game.init() self._start_episode() self.is_initialized = True self._play_human_mode() return np.zeros(shape=self.observation_space.shape, dtype=np.uint8) def _start_episode(self): if self.curr_seed > 0: self.game.set_seed(self.curr_seed) self.curr_seed = 0 self.game.new_episode() return def _play_human_mode(self): while not self.game.is_episode_finished(): self.game.advance_action() state = self.game.get_state() total_reward = self.game.get_total_reward() info = self._get_game_variables(state.game_variables) info["TOTAL_REWARD"] = round(total_reward, 4) print('===============================') print('State: #' + str(state.number)) print('Action: \t' + str(self.game.get_last_action()) + '\t (=> only allowed actions)') print('Reward: \t' + str(self.game.get_last_reward())) print('Total Reward: \t' + str(total_reward)) print('Variables: \n' + str(info)) sleep(0.02857) # 35 fps = 0.02857 sleep between frames print('===============================') print('Done') return def _step(self, action): if NUM_ACTIONS != len(action): logger.warn('Doom action list must contain %d items. Padding missing items with 0' % NUM_ACTIONS) old_action = action action = [0] * NUM_ACTIONS for i in range(len(old_action)): action[i] = old_action[i] # action is a list of numbers but DoomGame.make_action expects a list of ints if len(self.allowed_actions) > 0: list_action = [int(action[action_idx]) for action_idx in self.allowed_actions] else: list_action = [int(x) for x in action] try: reward = self.game.make_action(list_action) state = self.game.get_state() info = self._get_game_variables(state.game_variables) info["TOTAL_REWARD"] = round(self.game.get_total_reward(), 4) if self.game.is_episode_finished(): is_finished = True return np.zeros(shape=self.observation_space.shape, dtype=np.uint8), reward, is_finished, info else: is_finished = False return state.image_buffer.copy(), reward, is_finished, info except doom_py.vizdoom.ViZDoomIsNotRunningException: return np.zeros(shape=self.observation_space.shape, dtype=np.uint8), 0, True, {} def _reset(self): if self.is_initialized and not self._closed: self._start_episode() return self.game.get_state().image_buffer.copy() else: return self._load_level() def _render(self, mode='human', close=False): if close: if self.viewer is not None: self.viewer.close() self.viewer = None # If we don't None out this reference pyglet becomes unhappy return try: if 'human' == mode and self.no_render: return state = self.game.get_state() img = state.image_buffer # VizDoom returns None if the episode is finished, let's make it # an empty image so the recorder doesn't stop if img is None: img = np.zeros(shape=self.observation_space.shape, dtype=np.uint8) if mode == 'rgb_array': return img elif mode is 'human': from gym.envs.classic_control import rendering if self.viewer is None: self.viewer = rendering.SimpleImageViewer() self.viewer.imshow(img) if 'normal' == self.mode: sleep(0.02857) # 35 fps = 0.02857 sleep between frames except doom_py.vizdoom.ViZDoomIsNotRunningException: pass # Doom has been closed def _close(self): self.game.close() def _seed(self, seed=None): self.curr_seed = seeding.hash_seed(seed) % 2 ** 32 return [self.curr_seed] def _get_game_variables(self, state_variables): info = { "LEVEL": self.level } if state_variables is None: return info info['KILLCOUNT'] = state_variables[0] info['ITEMCOUNT'] = state_variables[1] info['SECRETCOUNT'] = state_variables[2] info['FRAGCOUNT'] = state_variables[3] info['HEALTH'] = state_variables[4] info['ARMOR'] = state_variables[5] info['DEAD'] = state_variables[6] info['ON_GROUND'] = state_variables[7] info['ATTACK_READY'] = state_variables[8] info['ALTATTACK_READY'] = state_variables[9] info['SELECTED_WEAPON'] = state_variables[10] info['SELECTED_WEAPON_AMMO'] = state_variables[11] info['AMMO1'] = state_variables[12] info['AMMO2'] = state_variables[13] info['AMMO3'] = state_variables[14] info['AMMO4'] = state_variables[15] info['AMMO5'] = state_variables[16] info['AMMO6'] = state_variables[17] info['AMMO7'] = state_variables[18] info['AMMO8'] = state_variables[19] info['AMMO9'] = state_variables[20] info['AMMO0'] = state_variables[21] return info
def _load_level(self): # Closing if is_initialized if self.is_initialized: self.is_initialized = False self.game.close() self.game = DoomGame() # Customizing level if getattr(self, '_customize_game', None) is not None and callable( self._customize_game): self.level = -1 self._customize_game() else: # Loading Paths if not self.is_initialized: self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) # Common settings self.game.load_config( os.path.join(self.doom_dir, 'assets/%s' % DOOM_SETTINGS[self.level][CONFIG])) self.game.set_doom_scenario_path( self.loader.get_scenario_path( DOOM_SETTINGS[self.level][SCENARIO])) if DOOM_SETTINGS[self.level][MAP] != '': if RANDOMIZE_MAPS > 0 and 'labyrinth' in DOOM_SETTINGS[ self.level][CONFIG].lower(): if 'fix' in DOOM_SETTINGS[self.level][SCENARIO].lower(): # mapId = 'map%02d'%np.random.randint(1, 23) mapId = 'map%02d' % np.random.randint(4, 8) else: mapId = 'map%02d' % np.random.randint( 1, RANDOMIZE_MAPS + 1) print( '\t=> Special Config: Randomly Loading Maps. MapID = ' + mapId) self.game.set_doom_map(mapId) else: print('\t=> Default map loaded. MapID = ' + DOOM_SETTINGS[self.level][MAP]) self.game.set_doom_map(DOOM_SETTINGS[self.level][MAP]) self.game.set_doom_skill(DOOM_SETTINGS[self.level][DIFFICULTY]) self.allowed_actions = DOOM_SETTINGS[self.level][ACTIONS] self.game.set_screen_resolution(self.screen_resolution) self.previous_level = self.level self._closed = False # Algo mode if 'human' != self._mode: if NO_MONSTERS: print('\t=> Special Config: Monsters Removed.') self.game.add_game_args('-nomonsters 1') self.game self.game.set_window_visible(False) self.game.set_mode(Mode.PLAYER) self.no_render = False try: with self.lock: self.game.init() except (ViZDoomUnexpectedExitException, ViZDoomErrorException): raise error.Error( 'VizDoom exited unexpectedly. This is likely caused by a missing multiprocessing lock. ' + 'To run VizDoom across multiple processes, you need to pass a lock when you configure the env ' + '[e.g. env.configure(lock=my_multiprocessing_lock)], or create and close an env ' + 'before starting your processes [e.g. env = gym.make("DoomBasic-v0"); env.close()] to cache a ' + 'singleton lock in memory.') self._start_episode() self.is_initialized = True return self.game.get_state().image_buffer.copy() # Human mode else: if NO_MONSTERS: print('\t=> Special Config: Monsters Removed.') self.game.add_game_args('-nomonsters 1') self.game.add_game_args('+freelook 1') self.game.set_window_visible(True) self.game.set_mode(Mode.SPECTATOR) self.no_render = True with self.lock: self.game.init() self._start_episode() self.is_initialized = True self._play_human_mode() return np.zeros(shape=self.observation_space.shape, dtype=np.uint8)
class DoomCorridorEnv(doom_env.DoomEnv): """ ------------ Training Mission 2 - Corridor ------------ This map is designed to improve your navigation. There is a vest at the end of the corridor, with 6 enemies (3 groups of 2). Your goal is to get to the vest as soon as possible, without being killed. Allowed actions: [0] - ATTACK - Shoot weapon - Values 0 or 1 [9] - MOVE_RIGHT - Move to the right - Values 0 or 1 [10] - MOVE_LEFT - Move to the left - Values 0 or 1 [12] - MOVE_FORWARD - Move forward - Values 0 or 1 [13] - TURN_RIGHT - Turn right - Values 0 or 1 [14] - TURN_LEFT - Turn left - Values 0 or 1 Note: see controls.md for details Rewards: + dX - For getting closer to the vest - dX - For getting further from the vest -100 - Penalty for being killed Goal: 1,270 points Reach the vest (try also killing guards, rather than just running) Ends when: - Player touches vest - Player is dead - Timeout (1 minutes - 2,100 frames) ----------------------------------------------------- """ def __init__(self): super(DoomCorridorEnv, self).__init__() package_directory = os.path.dirname(os.path.abspath(__file__)) self.loader = Loader() self.game = DoomGame() self.game.load_config(os.path.join(package_directory, 'assets/deadly_corridor.cfg')) self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) self.game.set_doom_scenario_path(self.loader.get_scenario_path('deadly_corridor.wad')) self.screen_height = 480 # Must match .cfg file self.screen_width = 640 # Must match .cfg file # action indexes are [0, 9, 10, 12, 13, 14] self.action_space = spaces.HighLow(np.matrix([[0, 1, 0]] * 6)) self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3)) self.game.set_window_visible(False) self.viewer = None self.game.init() self.game.new_episode()
class DoomDefendLineEnv(doom_env.DoomEnv): """ ------------ Training Mission 4 - Defend the Line ------------ This map is designed to teach you how to kill and how to stay alive. Your ammo will automatically replenish. You are only rewarded for kills, so figure out how to stay alive. The map is a rectangle with monsters in the middle. Monsters will respawn with additional health when killed. Kill as many as you can before they kill you. This map is harder than the previous. Allowed actions: [0] - ATTACK - Shoot weapon - Values 0 or 1 [13] - TURN_RIGHT - Turn right - Values 0 or 1 [14] - TURN_LEFT - Turn left - Values 0 or 1 Note: see controls.md for details Rewards: + 1 - Killing the monster - 1 - Penalty for being killed Goal: 25 points Kill 25 monsters Ends when: - Player is dead - Timeout (60 seconds - 2100 frames) ----------------------------------------------------- """ def __init__(self): super(DoomDefendLineEnv, self).__init__() package_directory = os.path.dirname(os.path.abspath(__file__)) self.loader = Loader() self.game = DoomGame() self.game.load_config( os.path.join(package_directory, 'assets/defend_the_line.cfg')) self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) self.game.set_doom_scenario_path( self.loader.get_scenario_path('defend_the_line.wad')) self.screen_height = 480 # Must match .cfg file self.screen_width = 640 # Must match .cfg file self.game.set_window_visible(False) self.viewer = None self._seed() self.game.init() self.game.new_episode() def _seed(self, seed=None): np_random, seed1 = seeding.np_random(seed) # Derive a random seed. seed2 = seeding.hash_seed(seed1 + 1) % 2**32 self.game.set_seed(seed2) # 3 allowed actions [0, 13, 14] (must match .cfg file) self.action_space = spaces.HighLow(np.matrix([[0, 1, 0]] * 3), np_random=np_random) self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3), np_random=np_random) return [seed1, seed2]
class DoomDeathmatchEnv(doom_env.DoomEnv): """ ------------ Final Mission - Deathmatch ------------ Kill as many monsters as possible without being killed. Allowed actions: ALL Note: see controls.md for details Rewards: +1 - Killing a monster Goal: 25 points Kill 25 monsters without being killed Ends when: - Player is dead - Timeout (3 minutes - 6,300 frames) ----------------------------------------------------- """ def __init__(self): super(DoomDeathmatchEnv, self).__init__() package_directory = os.path.dirname(os.path.abspath(__file__)) self.loader = Loader() self.game = DoomGame() self.game.load_config(os.path.join(package_directory, 'assets/deathmatch.cfg')) self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) self.game.set_doom_scenario_path(self.loader.get_scenario_path('deathmatch.wad')) self.screen_height = 480 # Must match .cfg file self.screen_width = 640 # Must match .cfg file # 41 allowed actions (must match .cfg file) self.action_space = spaces.HighLow(np.matrix([[0, 1, 0]] * 37 + [[0, 10, 0]] * 5)) self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3)) self.game.set_window_visible(False) self.viewer = None self.game.init() self.game.new_episode()
def _load_level(self): # Closing if is_initialized if self.is_initialized: self.is_initialized = False self.game.close() self.game = DoomGame() # Customizing level if getattr(self, '_customize_game', None) is not None and callable(self._customize_game): self.level = -1 self._customize_game() else: # Loading Paths if not self.is_initialized: self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) # Common settings self.game.load_config(os.path.join(self.doom_dir, 'assets/%s' % DOOM_SETTINGS[self.level][CONFIG])) self.game.set_doom_scenario_path(self.loader.get_scenario_path(DOOM_SETTINGS[self.level][SCENARIO])) if DOOM_SETTINGS[self.level][MAP] != '': self.game.set_doom_map(DOOM_SETTINGS[self.level][MAP]) self.game.set_doom_skill(DOOM_SETTINGS[self.level][DIFFICULTY]) self.allowed_actions = DOOM_SETTINGS[self.level][ACTIONS] self.game.set_screen_resolution(self.screen_resolution) self.previous_level = self.level self._closed = False # Algo mode if 'human' != self._mode: self.game.set_window_visible(False) self.game.set_mode(Mode.PLAYER) self.no_render = False try: with self.lock: self.game.init() except (ViZDoomUnexpectedExitException, ViZDoomErrorException): raise error.Error( 'VizDoom exited unexpectedly. This is likely caused by a missing multiprocessing lock. ' + 'To run VizDoom across multiple processes, you need to pass a lock when you configure the env ' + '[e.g. env.configure(lock=my_multiprocessing_lock)], or create and close an env ' + 'before starting your processes [e.g. env = gym.make("DoomBasic-v0"); env.close()] to cache a ' + 'singleton lock in memory.') self._start_episode() self.is_initialized = True return self.game.get_state().image_buffer.copy() # Human mode else: self.game.add_game_args('+freelook 1') self.game.set_window_visible(True) self.game.set_mode(Mode.SPECTATOR) self.no_render = True with self.lock: self.game.init() self._start_episode() self.is_initialized = True self._play_human_mode() return np.zeros(shape=self.observation_space.shape, dtype=np.uint8)
class DoomDeathmatchEnv(doom_env.DoomEnv): """ ------------ Final Mission - Deathmatch ------------ Kill as many monsters as possible without being killed. Allowed actions: ALL Note: see controls.md for details Rewards: +1 - Killing a monster Goal: 25 points Kill 25 monsters without being killed Ends when: - Player is dead - Timeout (3 minutes - 6,300 frames) ----------------------------------------------------- """ def __init__(self): super(DoomDeathmatchEnv, self).__init__() package_directory = os.path.dirname(os.path.abspath(__file__)) self.loader = Loader() self.game = DoomGame() self.game.load_config( os.path.join(package_directory, 'assets/deathmatch.cfg')) self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) self.game.set_doom_scenario_path( self.loader.get_scenario_path('deathmatch.wad')) self.screen_height = 480 # Must match .cfg file self.screen_width = 640 # Must match .cfg file # 41 allowed actions (must match .cfg file) self.action_space = spaces.HighLow( np.matrix([[0, 1, 0]] * 36 + [[0, 10, 0]] * 5)) self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3)) self.game.set_window_visible(False) self.viewer = None self.game.init() self.game.new_episode()
def _load_level(self): # Closing if is_initialized if self.is_initialized: self.is_initialized = False self.game.close() self.game = DoomGame() # Customizing level if getattr(self, '_customize_game', None) is not None and callable(self._customize_game): self.level = -1 self._customize_game() else: # Loading Paths if not self.is_initialized: self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) # Common settings self.game.load_config(os.path.join(self.doom_dir, 'assets/%s' % DOOM_SETTINGS[self.level][CONFIG])) if self.level == 9 or self.level == 10: # Load modified wad. self.game.set_doom_scenario_path(os.path.join('/opt/app/takecover_variants/assets', DOOM_SETTINGS[self.level][SCENARIO])) else: self.game.set_doom_scenario_path(self.loader.get_scenario_path(DOOM_SETTINGS[self.level][SCENARIO])) if DOOM_SETTINGS[self.level][MAP] != '': self.game.set_doom_map(DOOM_SETTINGS[self.level][MAP]) self.game.set_doom_skill(DOOM_SETTINGS[self.level][DIFFICULTY]) self.allowed_actions = DOOM_SETTINGS[self.level][ACTIONS] self.game.set_screen_resolution(self.screen_resolution) self.previous_level = self.level self._closed = False # Algo mode if 'human' != self._mode: self.game.set_window_visible(False) self.game.set_mode(Mode.PLAYER) self.no_render = False try: with self.lock: self.game.init() except (ViZDoomUnexpectedExitException, ViZDoomErrorException): raise error.Error( 'VizDoom exited unexpectedly. This is likely caused by a missing multiprocessing lock. ' + 'To run VizDoom across multiple processes, you need to pass a lock when you configure the env ' + '[e.g. env.configure(lock=my_multiprocessing_lock)], or create and close an env ' + 'before starting your processes [e.g. env = gym.make("DoomBasic-v0"); env.close()] to cache a ' + 'singleton lock in memory.') self._start_episode() self.is_initialized = True return self.game.get_state().image_buffer.copy() # Human mode else: self.game.add_game_args('+freelook 1') self.game.set_window_visible(True) self.game.set_mode(Mode.SPECTATOR) self.no_render = True with self.lock: self.game.init() self._start_episode() self.is_initialized = True self._play_human_mode() return np.zeros(shape=self.observation_space.shape, dtype=np.uint8)
class DoomHealthGatheringEnv(doom_env.DoomEnv): """ ------------ Training Mission 5 - Health Gathering ------------ This map is a guide on how to survive by collecting health packs. It is a rectangle with green, acidic floor which hurts the player periodically. There are also medkits spread around the map, and additional kits will spawn at interval. Allowed actions: [12] - MOVE_FORWARD - Move forward - Values 0 or 1 [13] - TURN_RIGHT - Turn right - Values 0 or 1 [14] - TURN_LEFT - Turn left - Values 0 or 1 Note: see controls.md for details Rewards: + 1 - Several times per second - Survive as long as possible -100 - Death penalty Goal: 1000 points Stay alive long enough to reach 1,000 points (~ 30 secs) Ends when: - Player is dead - Timeout (60 seconds - 2,100 frames) ----------------------------------------------------- """ def __init__(self): super(DoomHealthGatheringEnv, self).__init__() package_directory = os.path.dirname(os.path.abspath(__file__)) self.loader = Loader() self.game = DoomGame() self.game.load_config( os.path.join(package_directory, 'assets/health_gathering.cfg')) self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) self.game.set_doom_scenario_path( self.loader.get_scenario_path('health_gathering.wad')) self.game.set_doom_map('map01') self.screen_height = 480 # Must match .cfg file self.screen_width = 640 # Must match .cfg file self.game.set_window_visible(False) self.viewer = None self.game.init() self.game.new_episode() # 3 allowed actions [12, 13, 14] (must match .cfg file) self.action_space = spaces.HighLow(np.matrix([[0, 1, 0]] * 3)) self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3)) self._seed() def _seed(self, seed=None): seed = seeding.hash_seed(seed) % 2**32 self.game.set_seed(seed) return [seed]
class DoomTakeCoverEnv(doom_env.DoomEnv): """ ------------ Training Mission 8 - Take Cover ------------ This map is to train you on the damage of incoming missiles. It is a rectangular map with monsters firing missiles and fireballs at you. You need to survive as long as possible. Allowed actions: [9] - MOVE_RIGHT - Move to the right - Values 0 or 1 [10] - MOVE_LEFT - Move to the left - Values 0 or 1 Note: see controls.md for details Rewards: + 1 - Several times per second - Survive as long as possible Goal: 750 points Survive for ~ 20 seconds Ends when: - Player is dead (one or two fireballs should be enough to kill you) - Timeout (60 seconds - 2,100 frames) ----------------------------------------------------- """ def __init__(self): super(DoomTakeCoverEnv, self).__init__() package_directory = os.path.dirname(os.path.abspath(__file__)) self.loader = Loader() self.game = DoomGame() self.game.load_config( os.path.join(package_directory, 'assets/take_cover.cfg')) self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) self.game.set_doom_scenario_path( self.loader.get_scenario_path('take_cover.wad')) self.game.set_doom_map('map01') self.screen_height = 480 # Must match .cfg file self.screen_width = 640 # Must match .cfg file # 2 allowed actions [9, 10] (must match .cfg file) self.action_space = spaces.HighLow(np.matrix([[0, 1, 0]] * 2)) self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3)) self.game.set_window_visible(False) self.viewer = None self.game.init() self.game.new_episode()
class DoomBasicEnv(doom_env.DoomEnv): """ ------------ Training Mission 1 - Basic ------------ This map is rectangular with gray walls, ceiling and floor. You are spawned in the center of the longer wall, and a red circular monster is spawned randomly on the opposite wall. You need to kill the monster (one bullet is enough). Allowed actions: [0] - ATTACK - Shoot weapon - Values 0 or 1 [9] - MOVE_RIGHT - Move to the right - Values 0 or 1 [10] - MOVE_LEFT - Move to the left - Values 0 or 1 Note: see controls.md for details Rewards: +101 - Killing the monster - 5 - Missing a shot - 1 - Several times per second - Kill the monster faster! Goal: 10 points Kill the monster in 3 secs with 1 shot Ends when: - Monster is dead - Player is dead - Timeout (10 seconds - 350 frames) ----------------------------------------------------- """ def __init__(self): super(DoomBasicEnv, self).__init__() package_directory = os.path.dirname(os.path.abspath(__file__)) self.loader = Loader() self.game = DoomGame() self.game.load_config(os.path.join(package_directory, 'assets/basic.cfg')) self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) self.game.set_doom_scenario_path(self.loader.get_scenario_path('basic.wad')) self.game.set_doom_map('map01') self.screen_height = 480 # Must match .cfg file self.screen_width = 640 # Must match .cfg file # 3 allowed actions [0, 9, 10] (must match .cfg file) self.action_space = spaces.HighLow(np.matrix([[0, 1, 0]] * 3)) self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3)) self.game.set_window_visible(False) self.viewer = None self.game.init() self.game.new_episode()
class DoomDefendCenterEnv(doom_env.DoomEnv): """ ------------ Training Mission 3 - Defend the Center ------------ This map is designed to teach you how to kill and how to stay alive. You will also need to keep an eye on your ammunition level. You are only rewarded for kills, so figure out how to stay alive. The map is a circle with monsters in the middle. Monsters will respawn with additional health when killed. Kill as many as you can before you run out of ammo. Allowed actions: [0] - ATTACK - Shoot weapon - Values 0 or 1 [13] - TURN_RIGHT - Turn right - Values 0 or 1 [14] - TURN_LEFT - Turn left - Values 0 or 1 Note: see controls.md for details Rewards: + 1 - Killing the monster - 1 - Penalty for being killed Goal: 10 points Kill 10 monsters (you have 26 ammo) Ends when: - Player is dead - Timeout (60 seconds - 2100 frames) ----------------------------------------------------- """ def __init__(self): super(DoomDefendCenterEnv, self).__init__() package_directory = os.path.dirname(os.path.abspath(__file__)) self.loader = Loader() self.game = DoomGame() self.game.load_config( os.path.join(package_directory, 'assets/defend_the_center.cfg')) self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) self.game.set_doom_scenario_path( self.loader.get_scenario_path('defend_the_center.wad')) self.screen_height = 480 # Must match .cfg file self.screen_width = 640 # Must match .cfg file self.game.set_window_visible(False) self.viewer = None self.game.init() self.game.new_episode() # 3 allowed actions [0, 13, 14] (must match .cfg file) self.action_space = spaces.HighLow(np.matrix([[0, 1, 0]] * 3)) self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3)) self._seed() def _seed(self, seed=None): seed = seeding.hash_seed(seed) % 2**32 self.game.set_seed(seed) return [seed]
class DoomEnv(gym.Env, utils.EzPickle): metadata = { 'render.modes': ['human', 'rgb_array'], 'video.frames_per_second': 35 } def __init__(self, level): utils.EzPickle.__init__(self) self.previous_level = -1 self.level = level self.game = DoomGame() self.loader = Loader() self.doom_dir = os.path.dirname(os.path.abspath(__file__)) self.mode = 'fast' # 'human', 'fast' or 'normal' self.no_render = False # To disable double rendering in human mode self.viewer = None self.is_initialized = False # Indicates that reset() has been called self.find_new_level = False # Indicates that we need a level change self.curr_seed = 0 self.screen_height = 480 self.screen_width = 640 self.action_space = spaces.HighLow( np.matrix([[0, 1, 0]] * 38 + [[-10, 10, 0]] * 2 + [[-100, 100, 0]] * 3, dtype=np.int8)) self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3)) self.allowed_actions = list(range(NUM_ACTIONS)) def _load_level(self): # Closing if is_initialized if self.is_initialized: self.is_initialized = False self.game.close() self.game = DoomGame() # Loading Paths if not self.is_initialized: self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) # Common settings self._closed = False self.game.load_config( os.path.join(self.doom_dir, 'assets/%s' % DOOM_SETTINGS[self.level][CONFIG])) self.game.set_doom_scenario_path( self.loader.get_scenario_path(DOOM_SETTINGS[self.level][SCENARIO])) if DOOM_SETTINGS[self.level][MAP] != '': self.game.set_doom_map(DOOM_SETTINGS[self.level][MAP]) self.game.set_doom_skill(DOOM_SETTINGS[self.level][DIFFICULTY]) self.previous_level = self.level self.allowed_actions = DOOM_SETTINGS[self.level][ACTIONS] # Algo mode if 'human' != self.mode: self.game.set_window_visible(False) self.game.set_mode(Mode.PLAYER) self.no_render = False self.game.init() self._start_episode() self.is_initialized = True return self.game.get_state().image_buffer.copy() # Human mode else: self.game.add_game_args('+freelook 1') self.game.set_window_visible(True) self.game.set_mode(Mode.SPECTATOR) self.no_render = True self.game.init() self._start_episode() self.is_initialized = True self._play_human_mode() return np.zeros(shape=self.observation_space.shape, dtype=np.uint8) def _start_episode(self): if self.curr_seed > 0: self.game.set_seed(self.curr_seed) self.curr_seed = 0 self.game.new_episode() return def _play_human_mode(self): while not self.game.is_episode_finished(): self.game.advance_action() state = self.game.get_state() total_reward = self.game.get_total_reward() info = self._get_game_variables(state.game_variables) info["TOTAL_REWARD"] = round(total_reward, 4) print('===============================') print('State: #' + str(state.number)) print('Action: \t' + str(self.game.get_last_action()) + '\t (=> only allowed actions)') print('Reward: \t' + str(self.game.get_last_reward())) print('Total Reward: \t' + str(total_reward)) print('Variables: \n' + str(info)) sleep(0.02857) # 35 fps = 0.02857 sleep between frames print('===============================') print('Done') return def _step(self, action): if NUM_ACTIONS != len(action): logger.warn( 'Doom action list must contain %d items. Padding missing items with 0' % NUM_ACTIONS) old_action = action action = [0] * NUM_ACTIONS for i in range(len(old_action)): action[i] = old_action[i] # action is a list of numbers but DoomGame.make_action expects a list of ints if len(self.allowed_actions) > 0: list_action = [ int(action[action_idx]) for action_idx in self.allowed_actions ] else: list_action = [int(x) for x in action] try: reward = self.game.make_action(list_action) state = self.game.get_state() info = self._get_game_variables(state.game_variables) info["TOTAL_REWARD"] = round(self.game.get_total_reward(), 4) if self.game.is_episode_finished(): is_finished = True return np.zeros(shape=self.observation_space.shape, dtype=np.uint8), reward, is_finished, info else: is_finished = False return state.image_buffer.copy(), reward, is_finished, info except doom_py.vizdoom.ViZDoomIsNotRunningException: return np.zeros(shape=self.observation_space.shape, dtype=np.uint8), 0, True, {} def _reset(self): if self.is_initialized and not self._closed: self._start_episode() return self.game.get_state().image_buffer.copy() else: return self._load_level() def _render(self, mode='human', close=False): if close: if self.viewer is not None: self.viewer.close() self.viewer = None # If we don't None out this reference pyglet becomes unhappy return try: if 'human' == mode and self.no_render: return state = self.game.get_state() img = state.image_buffer # VizDoom returns None if the episode is finished, let's make it # an empty image so the recorder doesn't stop if img is None: img = np.zeros(shape=self.observation_space.shape, dtype=np.uint8) if mode == 'rgb_array': return img elif mode is 'human': from gym.envs.classic_control import rendering if self.viewer is None: self.viewer = rendering.SimpleImageViewer() self.viewer.imshow(img) if 'normal' == self.mode: sleep(0.02857) # 35 fps = 0.02857 sleep between frames except doom_py.vizdoom.ViZDoomIsNotRunningException: pass # Doom has been closed def _close(self): self.game.close() def _seed(self, seed=None): self.curr_seed = seeding.hash_seed(seed) % 2**32 return [self.curr_seed] def _get_game_variables(self, state_variables): info = {} info["LEVEL"] = self.level if state_variables is None: return info info['KILLCOUNT'] = state_variables[0] info['ITEMCOUNT'] = state_variables[1] info['SECRETCOUNT'] = state_variables[2] info['FRAGCOUNT'] = state_variables[3] info['HEALTH'] = state_variables[4] info['ARMOR'] = state_variables[5] info['DEAD'] = state_variables[6] info['ON_GROUND'] = state_variables[7] info['ATTACK_READY'] = state_variables[8] info['ALTATTACK_READY'] = state_variables[9] info['SELECTED_WEAPON'] = state_variables[10] info['SELECTED_WEAPON_AMMO'] = state_variables[11] info['AMMO1'] = state_variables[12] info['AMMO2'] = state_variables[13] info['AMMO3'] = state_variables[14] info['AMMO4'] = state_variables[15] info['AMMO5'] = state_variables[16] info['AMMO6'] = state_variables[17] info['AMMO7'] = state_variables[18] info['AMMO8'] = state_variables[19] info['AMMO9'] = state_variables[20] info['AMMO0'] = state_variables[21] return info
class DoomDefendLineEnv(doom_env.DoomEnv): """ ------------ Training Mission 4 - Defend the Line ------------ This map is designed to teach you how to kill and how to stay alive. Your ammo will automatically replenish. You are only rewarded for kills, so figure out how to stay alive. The map is a rectangle with monsters in the middle. Monsters will respawn with additional health when killed. Kill as many as you can before they kill you. This map is harder than the previous. Allowed actions: [0] - ATTACK - Shoot weapon - Values 0 or 1 [13] - TURN_RIGHT - Turn right - Values 0 or 1 [14] - TURN_LEFT - Turn left - Values 0 or 1 Note: see controls.md for details Rewards: + 1 - Killing the monster - 1 - Penalty for being killed Goal: 25 points Kill 25 monsters Ends when: - Player is dead - Timeout (60 seconds - 2100 frames) ----------------------------------------------------- """ def __init__(self): super(DoomDefendLineEnv, self).__init__() package_directory = os.path.dirname(os.path.abspath(__file__)) self.loader = Loader() self.game = DoomGame() self.game.load_config(os.path.join(package_directory, 'assets/defend_the_line.cfg')) self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) self.game.set_doom_scenario_path(self.loader.get_scenario_path('defend_the_line.wad')) self.screen_height = 480 # Must match .cfg file self.screen_width = 640 # Must match .cfg file # 3 allowed actions [0, 13, 14] (must match .cfg file) self.action_space = spaces.HighLow(np.matrix([[0, 1, 0]] * 3)) self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3)) self.game.set_window_visible(False) self.viewer = None self.game.init() self.game.new_episode()
class DoomEnv(gym.Env): metadata = {'render.modes': ['human', 'rgb_array'], 'video.frames_per_second': 35} def __init__(self, level): self.previous_level = -1 self.level = level self.game = DoomGame() self.loader = Loader() self.doom_dir = os.path.dirname(os.path.abspath(__file__)) self._mode = 'algo' # 'algo' or 'human' self.no_render = False # To disable double rendering in human mode self.viewer = None self.is_initialized = False # Indicates that reset() has been called self.curr_seed = 0 self.lock = (DoomLock()).get_lock() self.action_space = spaces.MultiDiscrete([[0, 1]] * 38 + [[-10, 10]] * 2 + [[-100, 100]] * 3) self.allowed_actions = list(range(NUM_ACTIONS)) self.screen_height = 480 self.screen_width = 640 self.screen_resolution = ScreenResolution.RES_640X480 self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3)) self._seed() self._configure() def _configure(self, lock=None, **kwargs): if 'screen_resolution' in kwargs: logger.warn('Deprecated - Screen resolution must now be set using a wrapper. See documentation for details.') # Multiprocessing lock if lock is not None: self.lock = lock def _load_level(self): # Closing if is_initialized if self.is_initialized: self.is_initialized = False self.game.close() self.game = DoomGame() # Customizing level if getattr(self, '_customize_game', None) is not None and callable(self._customize_game): self.level = -1 self._customize_game() else: # Loading Paths if not self.is_initialized: self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) # Common settings self.game.load_config(os.path.join(self.doom_dir, 'assets/%s' % DOOM_SETTINGS[self.level][CONFIG])) self.game.set_doom_scenario_path(self.loader.get_scenario_path(DOOM_SETTINGS[self.level][SCENARIO])) if DOOM_SETTINGS[self.level][MAP] != '': self.game.set_doom_map(DOOM_SETTINGS[self.level][MAP]) self.game.set_doom_skill(DOOM_SETTINGS[self.level][DIFFICULTY]) self.allowed_actions = DOOM_SETTINGS[self.level][ACTIONS] self.game.set_screen_resolution(self.screen_resolution) self.previous_level = self.level self._closed = False # Algo mode if 'human' != self._mode: self.game.set_window_visible(False) self.game.set_mode(Mode.PLAYER) self.no_render = False try: with self.lock: self.game.init() except (ViZDoomUnexpectedExitException, ViZDoomErrorException): raise error.Error( 'VizDoom exited unexpectedly. This is likely caused by a missing multiprocessing lock. ' + 'To run VizDoom across multiple processes, you need to pass a lock when you configure the env ' + '[e.g. env.configure(lock=my_multiprocessing_lock)], or create and close an env ' + 'before starting your processes [e.g. env = gym.make("DoomBasic-v0"); env.close()] to cache a ' + 'singleton lock in memory.') self._start_episode() self.is_initialized = True return self.game.get_state().image_buffer.copy() # Human mode else: self.game.add_game_args('+freelook 1') self.game.set_window_visible(True) self.game.set_mode(Mode.SPECTATOR) self.no_render = True with self.lock: self.game.init() self._start_episode() self.is_initialized = True self._play_human_mode() return np.zeros(shape=self.observation_space.shape, dtype=np.uint8) def _start_episode(self): if self.curr_seed > 0: self.game.set_seed(self.curr_seed) self.curr_seed = 0 self.game.new_episode() return def _play_human_mode(self): while not self.game.is_episode_finished(): self.game.advance_action() state = self.game.get_state() total_reward = self.game.get_total_reward() info = self._get_game_variables(state.game_variables) info["TOTAL_REWARD"] = round(total_reward, 4) print('===============================') print('State: #' + str(state.number)) print('Action: \t' + str(self.game.get_last_action()) + '\t (=> only allowed actions)') print('Reward: \t' + str(self.game.get_last_reward())) print('Total Reward: \t' + str(total_reward)) print('Variables: \n' + str(info)) sleep(0.02857) # 35 fps = 0.02857 sleep between frames print('===============================') print('Done') return def _step(self, action): if NUM_ACTIONS != len(action): logger.warn('Doom action list must contain %d items. Padding missing items with 0' % NUM_ACTIONS) old_action = action action = [0] * NUM_ACTIONS for i in range(len(old_action)): action[i] = old_action[i] # action is a list of numbers but DoomGame.make_action expects a list of ints if len(self.allowed_actions) > 0: list_action = [int(action[action_idx]) for action_idx in self.allowed_actions] else: list_action = [int(x) for x in action] try: reward = self.game.make_action(list_action) state = self.game.get_state() info = self._get_game_variables(state.game_variables) info["TOTAL_REWARD"] = round(self.game.get_total_reward(), 4) if self.game.is_episode_finished(): is_finished = True return np.zeros(shape=self.observation_space.shape, dtype=np.uint8), reward, is_finished, info else: is_finished = False return state.image_buffer.copy(), reward, is_finished, info except doom_py.vizdoom.ViZDoomIsNotRunningException: return np.zeros(shape=self.observation_space.shape, dtype=np.uint8), 0, True, {} def _reset(self): if self.is_initialized and not self._closed: self._start_episode() image_buffer = self.game.get_state().image_buffer if image_buffer is None: raise error.Error( 'VizDoom incorrectly initiated. This is likely caused by a missing multiprocessing lock. ' + 'To run VizDoom across multiple processes, you need to pass a lock when you configure the env ' + '[e.g. env.configure(lock=my_multiprocessing_lock)], or create and close an env ' + 'before starting your processes [e.g. env = gym.make("DoomBasic-v0"); env.close()] to cache a ' + 'singleton lock in memory.') return image_buffer.copy() else: return self._load_level() def _render(self, mode='human', close=False): if close: if self.viewer is not None: self.viewer.close() self.viewer = None # If we don't None out this reference pyglet becomes unhappy return try: if 'human' == mode and self.no_render: return state = self.game.get_state() img = state.image_buffer # VizDoom returns None if the episode is finished, let's make it # an empty image so the recorder doesn't stop if img is None: img = np.zeros(shape=self.observation_space.shape, dtype=np.uint8) if mode == 'rgb_array': return img elif mode is 'human': from gym.envs.classic_control import rendering if self.viewer is None: self.viewer = rendering.SimpleImageViewer() self.viewer.imshow(img) except doom_py.vizdoom.ViZDoomIsNotRunningException: pass # Doom has been closed def _close(self): # Lock required for VizDoom to close processes properly with self.lock: self.game.close() def _seed(self, seed=None): self.curr_seed = seeding.hash_seed(seed) % 2 ** 32 return [self.curr_seed] def _get_game_variables(self, state_variables): info = { "LEVEL": self.level } if state_variables is None: return info info['KILLCOUNT'] = state_variables[0] info['ITEMCOUNT'] = state_variables[1] info['SECRETCOUNT'] = state_variables[2] info['FRAGCOUNT'] = state_variables[3] info['HEALTH'] = state_variables[4] info['ARMOR'] = state_variables[5] info['DEAD'] = state_variables[6] info['ON_GROUND'] = state_variables[7] info['ATTACK_READY'] = state_variables[8] info['ALTATTACK_READY'] = state_variables[9] info['SELECTED_WEAPON'] = state_variables[10] info['SELECTED_WEAPON_AMMO'] = state_variables[11] info['AMMO1'] = state_variables[12] info['AMMO2'] = state_variables[13] info['AMMO3'] = state_variables[14] info['AMMO4'] = state_variables[15] info['AMMO5'] = state_variables[16] info['AMMO6'] = state_variables[17] info['AMMO7'] = state_variables[18] info['AMMO8'] = state_variables[19] info['AMMO9'] = state_variables[20] info['AMMO0'] = state_variables[21] return info
class DoomDefendCenterEnv(doom_env.DoomEnv): """ ------------ Training Mission 3 - Defend the Center ------------ This map is designed to teach you how to kill and how to stay alive. You will also need to keep an eye on your ammunition level. You are only rewarded for kills, so figure out how to stay alive. The map is a circle with monsters in the middle. Monsters will respawn with additional health when killed. Kill as many as you can before you run out of ammo. Allowed actions: [0] - ATTACK - Shoot weapon - Values 0 or 1 [13] - TURN_RIGHT - Turn right - Values 0 or 1 [14] - TURN_LEFT - Turn left - Values 0 or 1 Note: see controls.md for details Rewards: + 1 - Killing the monster - 1 - Penalty for being killed Goal: 10 points Kill 10 monsters (you have 26 ammo) Ends when: - Player is dead - Timeout (60 seconds - 2100 frames) ----------------------------------------------------- """ def __init__(self): super(DoomDefendCenterEnv, self).__init__() package_directory = os.path.dirname(os.path.abspath(__file__)) self.loader = Loader() self.game = DoomGame() self.game.load_config(os.path.join(package_directory, 'assets/defend_the_center.cfg')) self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) self.game.set_doom_scenario_path(self.loader.get_scenario_path('defend_the_center.wad')) self.screen_height = 480 # Must match .cfg file self.screen_width = 640 # Must match .cfg file self.game.set_window_visible(False) self.viewer = None self.game.init() self.game.new_episode() # 3 allowed actions [0, 13, 14] (must match .cfg file) self.action_space = spaces.HighLow(np.matrix([[0, 1, 0]] * 3)) self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3)) self._seed() def _seed(self, seed=None): seed = seeding.hash_seed(seed) % 2**32 self.game.set_seed(seed) return [seed]
class DoomPredictPositionEnv(doom_env.DoomEnv): """ ------------ Training Mission 7 - Predict Position ------------ This map is designed to train you on using a rocket launcher. It is a rectangular map with a monster on the opposite side. You need to use your rocket launcher to kill it. The rocket adds a delay between the moment it is fired and the moment it reaches the other side of the room. You need to predict the position of the monster to kill it. Allowed actions: [0] - ATTACK - Shoot weapon - Values 0 or 1 [13] - TURN_RIGHT - Turn right - Values 0 or 1 [14] - TURN_LEFT - Turn left - Values 0 or 1 Note: see controls.md for details Rewards: + 1 - Killing the monster -0.0001 - Several times per second - Kill the monster faster! Goal: 0.5 point Kill the monster Hint: Missile launcher takes longer to load. You must wait a good second after the game starts before trying to fire it. Ends when: - Monster is dead - Out of missile (you only have one) - Timeout (20 seconds - 700 frames) ----------------------------------------------------- """ def __init__(self): package_directory = os.path.dirname(os.path.abspath(__file__)) self.loader = Loader() self.game = DoomGame() self.game.load_config( os.path.join(package_directory, 'assets/predict_position.cfg')) self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) self.game.set_doom_scenario_path( self.loader.get_scenario_path('predict_position.wad')) self.game.set_doom_map('map01') self.screen_height = 480 # Must match .cfg file self.screen_width = 640 # Must match .cfg file # 3 allowed actions [0, 13, 14] (must match .cfg file) self.action_space = doom_spaces.HighLow(np.matrix([[0, 1, 0]] * 3)) self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3)) self.game.set_window_visible(False) self.viewer = None self.game.init() self.game.new_episode()
class DoomHealthGatheringEnv(doom_env.DoomEnv): """ ------------ Training Mission 5 - Health Gathering ------------ This map is a guide on how to survive by collecting health packs. It is a rectangle with green, acidic floor which hurts the player periodically. There are also medkits spread around the map, and additional kits will spawn at interval. Allowed actions: [12] - MOVE_FORWARD - Move forward - Values 0 or 1 [13] - TURN_RIGHT - Turn right - Values 0 or 1 [14] - TURN_LEFT - Turn left - Values 0 or 1 Note: see controls.md for details Rewards: + 1 - Several times per second - Survive as long as possible -100 - Death penalty Goal: 1000 points Stay alive long enough to reach 1,000 points (~ 30 secs) Ends when: - Player is dead - Timeout (60 seconds - 2,100 frames) ----------------------------------------------------- """ def __init__(self): super(DoomHealthGatheringEnv, self).__init__() package_directory = os.path.dirname(os.path.abspath(__file__)) self.loader = Loader() self.game = DoomGame() self.game.load_config(os.path.join(package_directory, 'assets/health_gathering.cfg')) self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) self.game.set_doom_scenario_path(self.loader.get_scenario_path('health_gathering.wad')) self.game.set_doom_map('map01') self.screen_height = 480 # Must match .cfg file self.screen_width = 640 # Must match .cfg file # 3 allowed actions [12, 13, 14] (must match .cfg file) self.action_space = spaces.HighLow(np.matrix([[0, 1, 0]] * 3)) self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3)) self.game.set_window_visible(False) self.viewer = None self.game.init() self.game.new_episode()
class DoomTakeCoverEnv(doom_env.DoomEnv): """ ------------ Training Mission 8 - Take Cover ------------ This map is to train you on the damage of incoming missiles. It is a rectangular map with monsters firing missiles and fireballs at you. You need to survive as long as possible. Allowed actions: [9] - MOVE_RIGHT - Move to the right - Values 0 or 1 [10] - MOVE_LEFT - Move to the left - Values 0 or 1 Note: see controls.md for details Rewards: + 1 - Several times per second - Survive as long as possible Goal: 750 points Survive for ~ 20 seconds Ends when: - Player is dead (one or two fireballs should be enough to kill you) - Timeout (60 seconds - 2,100 frames) ----------------------------------------------------- """ def __init__(self): super(DoomTakeCoverEnv, self).__init__() package_directory = os.path.dirname(os.path.abspath(__file__)) self.loader = Loader() self.game = DoomGame() self.game.load_config(os.path.join(package_directory, 'assets/take_cover.cfg')) self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) self.game.set_doom_scenario_path(self.loader.get_scenario_path('take_cover.wad')) self.game.set_doom_map('map01') self.screen_height = 480 # Must match .cfg file self.screen_width = 640 # Must match .cfg file # 2 allowed actions [9, 10] (must match .cfg file) self.action_space = spaces.HighLow(np.matrix([[0, 1, 0]] * 2)) self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3)) self.game.set_window_visible(False) self.viewer = None self.game.init() self.game.new_episode()
class DoomMyWayHomeEnv(doom_env.DoomEnv): """ ------------ Training Mission 6 - My Way Home ------------ This map is designed to improve navigational skills. It is a series of interconnected rooms and 1 corridor with a dead end. Each room has a separate color. There is a green vest in one of the room. The vest is always in the same room. Player must find the vest. Allowed actions: [12] - MOVE_FORWARD - Move forward - Values 0 or 1 [13] - TURN_RIGHT - Turn right - Values 0 or 1 [14] - TURN_LEFT - Turn left - Values 0 or 1 Note: see controls.md for details Rewards: + 1 - Finding the vest -0.0001 - Several times per second - Find the vest quick! Goal: 0.50 point Find the vest Ends when: - Vest is found - Timeout (2 minutes - 4,200 frames) ----------------------------------------------------- """ def __init__(self): super(DoomMyWayHomeEnv, self).__init__() package_directory = os.path.dirname(os.path.abspath(__file__)) self.loader = Loader() self.game = DoomGame() self.game.load_config( os.path.join(package_directory, 'assets/my_way_home.cfg')) self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) self.game.set_doom_scenario_path( self.loader.get_scenario_path('my_way_home.wad')) self.screen_height = 480 # Must match .cfg file self.screen_width = 640 # Must match .cfg file self.game.set_window_visible(False) self.viewer = None self.game.init() self.game.new_episode() self._seed() def _seed(self, seed=None): np_random, seed1 = seeding.np_random(seed) # Derive a random seed. seed2 = seeding.hash_seed(seed1 + 1) % 2**32 self.game.set_seed(seed2) # 3 allowed actions [12, 13, 14] (must match .cfg file) self.action_space = spaces.HighLow(np.matrix([[0, 1, 0]] * 3), np_random=np_random) self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3), np_random=np_random) return [seed1, seed2]
class DoomPredictPositionEnv(doom_env.DoomEnv): """ ------------ Training Mission 7 - Predict Position ------------ This map is designed to train you on using a rocket launcher. It is a rectangular map with a monster on the opposite side. You need to use your rocket launcher to kill it. The rocket adds a delay between the moment it is fired and the moment it reaches the other side of the room. You need to predict the position of the monster to kill it. Allowed actions: [0] - ATTACK - Shoot weapon - Values 0 or 1 [13] - TURN_RIGHT - Turn right - Values 0 or 1 [14] - TURN_LEFT - Turn left - Values 0 or 1 Note: see controls.md for details Rewards: + 1 - Killing the monster -0.0001 - Several times per second - Kill the monster faster! Goal: 0.5 point Kill the monster Hint: Missile launcher takes longer to load. You must wait a good second after the game starts before trying to fire it. Ends when: - Monster is dead - Out of missile (you only have one) - Timeout (20 seconds - 700 frames) ----------------------------------------------------- """ def __init__(self): package_directory = os.path.dirname(os.path.abspath(__file__)) self.loader = Loader() self.game = DoomGame() self.game.load_config(os.path.join(package_directory, 'assets/predict_position.cfg')) self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) self.game.set_doom_scenario_path(self.loader.get_scenario_path('predict_position.wad')) self.game.set_doom_map('map01') self.screen_height = 480 # Must match .cfg file self.screen_width = 640 # Must match .cfg file # 3 allowed actions [0, 13, 14] (must match .cfg file) self.action_space = doom_spaces.HighLow(np.matrix([[0, 1, 0]] * 3)) self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3)) self.game.set_window_visible(False) self.viewer = None self.game.init() self.game.new_episode()
class DoomMyWayHomeEnv(doom_env.DoomEnv): """ ------------ Training Mission 6 - My Way Home ------------ This map is designed to improve navigational skills. It is a series of interconnected rooms and 1 corridor with a dead end. Each room has a separate color. There is a green vest in one of the room. The vest is always in the same room. Player must find the vest. Allowed actions: [12] - MOVE_FORWARD - Move forward - Values 0 or 1 [13] - TURN_RIGHT - Turn right - Values 0 or 1 [14] - TURN_LEFT - Turn left - Values 0 or 1 Note: see controls.md for details Rewards: + 1 - Finding the vest -0.0001 - Several times per second - Find the vest quick! Goal: 0.50 point Find the vest Ends when: - Vest is found - Timeout (2 minutes - 4,200 frames) ----------------------------------------------------- """ def __init__(self): super(DoomMyWayHomeEnv, self).__init__() package_directory = os.path.dirname(os.path.abspath(__file__)) self.loader = Loader() self.game = DoomGame() self.game.load_config(os.path.join(package_directory, 'assets/my_way_home.cfg')) self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) self.game.set_doom_scenario_path(self.loader.get_scenario_path('my_way_home.wad')) self.screen_height = 480 # Must match .cfg file self.screen_width = 640 # Must match .cfg file self.game.set_window_visible(False) self.viewer = None self.game.init() self.game.new_episode() self._seed() def _seed(self, seed=None): np_random, seed1 = seeding.np_random(seed) # Derive a random seed. seed2 = seeding.hash_seed(seed1 + 1) % 2**32 self.game.set_seed(seed2) # 3 allowed actions [12, 13, 14] (must match .cfg file) self.action_space = spaces.HighLow(np.matrix([[0, 1, 0]] * 3), np_random=np_random) self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3), np_random=np_random) return [seed1, seed2]
class DoomEnv(gym.Env): metadata = {'render.modes': ['human', 'rgb_array'], 'video.frames_per_second': 35} def __init__(self, level): self.previous_level = -1 self.level = level self.game = DoomGame() self.loader = Loader() self.doom_dir = os.path.dirname(os.path.abspath(__file__)) self._mode = 'algo' # 'algo' or 'human' self.no_render = False # To disable double rendering in human mode self.viewer = None self.is_initialized = False # Indicates that reset() has been called self.curr_seed = 0 self.lock = (DoomLock()).get_lock() self.action_space = spaces.MultiDiscrete([[0, 1]] * 38 + [[-10, 10]] * 2 + [[-100, 100]] * 3) self.allowed_actions = list(range(NUM_ACTIONS)) self.screen_height = 480 self.screen_width = 640 self.screen_resolution = ScreenResolution.RES_640X480 self.observation_space = spaces.Box(low=0, high=255, shape=(self.screen_height, self.screen_width, 3)) self._seed() self._configure() def _configure(self, lock=None, **kwargs): if 'screen_resolution' in kwargs: logger.warn('Deprecated - Screen resolution must now be set using a wrapper. See documentation for details.') # Multiprocessing lock if lock is not None: self.lock = lock def _load_level(self): # Closing if is_initialized if self.is_initialized: self.is_initialized = False self.game.close() self.game = DoomGame() # Customizing level if getattr(self, '_customize_game', None) is not None and callable(self._customize_game): self.level = -1 self._customize_game() else: # Loading Paths if not self.is_initialized: self.game.set_vizdoom_path(self.loader.get_vizdoom_path()) self.game.set_doom_game_path(self.loader.get_freedoom_path()) # Common settings self.game.load_config(os.path.join(self.doom_dir, 'assets/%s' % DOOM_SETTINGS[self.level][CONFIG])) if self.level == 9 or self.level == 10: # Load modified wad. self.game.set_doom_scenario_path(os.path.join('/opt/app/takecover_variants/assets', DOOM_SETTINGS[self.level][SCENARIO])) else: self.game.set_doom_scenario_path(self.loader.get_scenario_path(DOOM_SETTINGS[self.level][SCENARIO])) if DOOM_SETTINGS[self.level][MAP] != '': self.game.set_doom_map(DOOM_SETTINGS[self.level][MAP]) self.game.set_doom_skill(DOOM_SETTINGS[self.level][DIFFICULTY]) self.allowed_actions = DOOM_SETTINGS[self.level][ACTIONS] self.game.set_screen_resolution(self.screen_resolution) self.previous_level = self.level self._closed = False # Algo mode if 'human' != self._mode: self.game.set_window_visible(False) self.game.set_mode(Mode.PLAYER) self.no_render = False try: with self.lock: self.game.init() except (ViZDoomUnexpectedExitException, ViZDoomErrorException): raise error.Error( 'VizDoom exited unexpectedly. This is likely caused by a missing multiprocessing lock. ' + 'To run VizDoom across multiple processes, you need to pass a lock when you configure the env ' + '[e.g. env.configure(lock=my_multiprocessing_lock)], or create and close an env ' + 'before starting your processes [e.g. env = gym.make("DoomBasic-v0"); env.close()] to cache a ' + 'singleton lock in memory.') self._start_episode() self.is_initialized = True return self.game.get_state().image_buffer.copy() # Human mode else: self.game.add_game_args('+freelook 1') self.game.set_window_visible(True) self.game.set_mode(Mode.SPECTATOR) self.no_render = True with self.lock: self.game.init() self._start_episode() self.is_initialized = True self._play_human_mode() return np.zeros(shape=self.observation_space.shape, dtype=np.uint8) def _start_episode(self): if self.curr_seed > 0: self.game.set_seed(self.curr_seed) self.curr_seed = 0 self.game.new_episode() return def _play_human_mode(self): while not self.game.is_episode_finished(): self.game.advance_action() state = self.game.get_state() total_reward = self.game.get_total_reward() info = self._get_game_variables(state.game_variables) info["TOTAL_REWARD"] = round(total_reward, 4) print('===============================') print('State: #' + str(state.number)) print('Action: \t' + str(self.game.get_last_action()) + '\t (=> only allowed actions)') print('Reward: \t' + str(self.game.get_last_reward())) print('Total Reward: \t' + str(total_reward)) print('Variables: \n' + str(info)) sleep(0.02857) # 35 fps = 0.02857 sleep between frames print('===============================') print('Done') return def _step(self, action): if NUM_ACTIONS != len(action): logger.warn('Doom action list must contain %d items. Padding missing items with 0' % NUM_ACTIONS) old_action = action action = [0] * NUM_ACTIONS for i in range(len(old_action)): action[i] = old_action[i] # action is a list of numbers but DoomGame.make_action expects a list of ints if len(self.allowed_actions) > 0: list_action = [int(action[action_idx]) for action_idx in self.allowed_actions] else: list_action = [int(x) for x in action] try: reward = self.game.make_action(list_action) state = self.game.get_state() info = self._get_game_variables(state.game_variables) info["TOTAL_REWARD"] = round(self.game.get_total_reward(), 4) if self.game.is_episode_finished(): is_finished = True return np.zeros(shape=self.observation_space.shape, dtype=np.uint8), reward, is_finished, info else: is_finished = False return state.image_buffer.copy(), reward, is_finished, info except doom_py.vizdoom.ViZDoomIsNotRunningException: return np.zeros(shape=self.observation_space.shape, dtype=np.uint8), 0, True, {} def _reset(self): if self.is_initialized and not self._closed: self._start_episode() image_buffer = self.game.get_state().image_buffer if image_buffer is None: raise error.Error( 'VizDoom incorrectly initiated. This is likely caused by a missing multiprocessing lock. ' + 'To run VizDoom across multiple processes, you need to pass a lock when you configure the env ' + '[e.g. env.configure(lock=my_multiprocessing_lock)], or create and close an env ' + 'before starting your processes [e.g. env = gym.make("DoomBasic-v0"); env.close()] to cache a ' + 'singleton lock in memory.') return image_buffer.copy() else: return self._load_level() def _render(self, mode='human', close=False): if close: if self.viewer is not None: self.viewer.close() self.viewer = None # If we don't None out this reference pyglet becomes unhappy return try: if 'human' == mode and self.no_render: return state = self.game.get_state() img = state.image_buffer # VizDoom returns None if the episode is finished, let's make it # an empty image so the recorder doesn't stop if img is None: img = np.zeros(shape=self.observation_space.shape, dtype=np.uint8) if mode == 'rgb_array': return img elif mode is 'human': from gym.envs.classic_control import rendering if self.viewer is None: self.viewer = rendering.SimpleImageViewer() self.viewer.imshow(img) except doom_py.vizdoom.ViZDoomIsNotRunningException: pass # Doom has been closed def _close(self): # Lock required for VizDoom to close processes properly with self.lock: self.game.close() def _seed(self, seed=None): self.curr_seed = seeding.hash_seed(seed) % 2 ** 32 return [self.curr_seed] def _get_game_variables(self, state_variables): info = { "LEVEL": self.level } if state_variables is None: return info info['KILLCOUNT'] = state_variables[0] info['ITEMCOUNT'] = state_variables[1] info['SECRETCOUNT'] = state_variables[2] info['FRAGCOUNT'] = state_variables[3] info['HEALTH'] = state_variables[4] info['ARMOR'] = state_variables[5] info['DEAD'] = state_variables[6] info['ON_GROUND'] = state_variables[7] info['ATTACK_READY'] = state_variables[8] info['ALTATTACK_READY'] = state_variables[9] info['SELECTED_WEAPON'] = state_variables[10] info['SELECTED_WEAPON_AMMO'] = state_variables[11] info['AMMO1'] = state_variables[12] info['AMMO2'] = state_variables[13] info['AMMO3'] = state_variables[14] info['AMMO4'] = state_variables[15] info['AMMO5'] = state_variables[16] info['AMMO6'] = state_variables[17] info['AMMO7'] = state_variables[18] info['AMMO8'] = state_variables[19] info['AMMO9'] = state_variables[20] info['AMMO0'] = state_variables[21] return info