docstr: Base class for Gymnasium interface for ViZDoom. Thanks to https://github.com/shakenes/vizdoomgym
  Child classes are defined in gym_env_defns.py,
  
  Arguments:
      level (str): The path to the config file to load. Most settings should be set by this config file.
      frame_skip (int): The number of frames the will 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 ``n`` actions can be selected.
                                 ``n`` is equal to number of possible buttons combinations
                                 with the number of buttons pressed < ``max_buttons_pressed``.
      render_mode(Optional[str]): The render mode to use could be either "human" or "rgb_array"
  
  This environment forces the game window to be hidden. Use :meth:`render` function to see the game.
  
  Observations are dictionaries with different number 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) as `np.ndarray` in shape ``(HEIGHT, WIDTH, CHANNELS)``.
  - "depth": The depth image as ``np.ndarray`` in shape ``(HEIGHT, WIDTH, 1)``, if enabled by the config file.
  - "labels": The label image buffer as `np.ndarray` 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 as ``np.ndarray`` 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": Is ``MultiDiscrete([2] * num_binary_buttons)`` if :attr:`max_buttons_pressed` == 0
    or ``Discrete(num_binary_buttons + 1)`` if :attr:`max_buttons_pressed` >= 1.
  - "continuous": Is ``Box(float32.min, float32.max, (num_delta_buttons,), float32)``.
docstr_tok: ["Base","class","for","Gymnasium","interface","for","ViZDoom",".","Thanks","to","https",":","\/\/github.com\/shakenes\/vizdoomgym","Child","classes","are","defined","in","gym_env_defns.py",",","Arguments",":","level","(","str",")",":","The","path","to","the","config","file","to","load",".","Most","settings","should","be","set","by","this","config","file",".","frame_skip","(","int",")",":","The","number","of","frames","the","will","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","``","n","``","actions","can","be","selected",".","``","n","``","is","equal","to","number","of","possible","buttons","combinations","with","the","number","of","buttons","pressed","<","``","max_buttons_pressed","``",".","render_mode","(","Optional","[","str","]",")",":","The","render","mode","to","use","could","be","either","``","human","''","or","``","rgb_array","''","This","environment","forces","the","game","window","to","be","hidden",".","Use",":","meth",":","`","render","`","function","to","see","the","game",".","Observations","are","dictionaries","with","different","number","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",")","as","`","np.ndarray","`","in","shape","``","(","HEIGHT",",","WIDTH",",","CHANNELS",")","``",".","-","``","depth","''",":","The","depth","image","as","``","np.ndarray","``","in","shape","``","(","HEIGHT",",","WIDTH",",","1",")","``",",","if","enabled","by","the","config","file",".","-","``","labels","''",":","The","label","image","buffer","as","`","np.ndarray","`","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","as","``","np.ndarray","``","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","''",":","Is","``","MultiDiscrete","(","[","2","]","*","num_binary_buttons",")","``","if",":","attr",":","`","max_buttons_pressed","`","==","0","or","``","Discrete","(","num_binary_buttons","+","1",")","``","if",":","attr",":","`","max_buttons_pressed","`",">","=","1",".","-","``","continuous","''",":","Is","``","Box","(","float32.min",",","float32.max",",","(","num_delta_buttons",",",")",",","float32",")","``","."]
code: def __init__(
      self,
      level,
      frame_skip=1,
      max_buttons_pressed=1,
      render_mode: Optional[str] = None,
  ):
      """
      Base class for Gymnasium interface for ViZDoom. Thanks to https://github.com/shakenes/vizdoomgym
      Child classes are defined in gym_env_defns.py,
  
      Arguments:
          level (str): The path to the config file to load. Most settings should be set by this config file.
          frame_skip (int): The number of frames the will 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 ``n`` actions can be selected.
                                     ``n`` is equal to number of possible buttons combinations
                                     with the number of buttons pressed < ``max_buttons_pressed``.
          render_mode(Optional[str]): The render mode to use could be either "human" or "rgb_array"
  
      This environment forces the game window to be hidden. Use :meth:`render` function to see the game.
  
      Observations are dictionaries with different number 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) as `np.ndarray` in shape ``(HEIGHT, WIDTH, CHANNELS)``.
      - "depth": The depth image as ``np.ndarray`` in shape ``(HEIGHT, WIDTH, 1)``, if enabled by the config file.
      - "labels": The label image buffer as `np.ndarray` 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 as ``np.ndarray`` 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": Is ``MultiDiscrete([2] * num_binary_buttons)`` if :attr:`max_buttons_pressed` == 0
        or ``Discrete(num_binary_buttons + 1)`` if :attr:`max_buttons_pressed` >= 1.
      - "continuous": Is ``Box(float32.min, float32.max, (num_delta_buttons,), float32)``.
      """
      EzPickle.__init__(
          self, level, frame_skip, max_buttons_pressed, render_mode
      )
      self.frame_skip = frame_skip
      self.render_mode = render_mode
  
      # 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 Gymnasium"
              f" wrapper. Forcing RGB24."
          )
          self.game.set_screen_format(vzd.ScreenFormat.RGB24)
  
      self.state = None
      self.clock = 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()
  
imports: import itertools
  import warnings
  from typing import Optional
  import gymnasium
  import numpy
  import pygame
  from gymnasium.utils import EzPickle
  import vizdoom.vizdoom
label_desc: Use image node_id 1 to create a new VizdoomEnv object from inherited base classes: gym, EzPickle with example: obj = VizdoomEnv(level, frame_skip, max_buttons_pressed, render_mode)