class_docstr: An OpenSpiel RL environment loop.
  
  This takes `Environment` and list of `Actor` instances and coordinates their
  interaction. Agents are updated if `should_update=True`. This can be used as:
  
    loop = EnvironmentLoop(environment, actors)
    loop.run(num_episodes)
  
  A `Counter` instance can optionally be given in order to maintain counts
  between different Acme components. If not given a local Counter will be
  created to maintain counts between calls to the `run` method.
  
  A `Logger` instance can also be passed in order to control the output of the
  loop. If not given a platform-specific default logger will be used as defined
  by utils.loggers.make_default_logger. A string `label` can be passed to easily
  change the label associated with the default logger; this is ignored if a
  `Logger` instance is given.
class_docstr_tok: ["An","OpenSpiel","RL","environment","loop",".","This","takes","`","Environment","`","and","list","of","`","Actor","`","instances","and","coordinates","their","interaction",".","Agents","are","updated","if","`","should_update=True","`",".","This","can","be","used","as",":","loop","=","EnvironmentLoop","(","environment",",","actors",")","loop.run","(","num_episodes",")","A","`","Counter","`","instance","can","optionally","be","given","in","order","to","maintain","counts","between","different","Acme","components",".","If","not","given","a","local","Counter","will","be","created","to","maintain","counts","between","calls","to","the","`","run","`","method",".","A","`","Logger","`","instance","can","also","be","passed","in","order","to","control","the","output","of","the","loop",".","If","not","given","a","platform-specific","default","logger","will","be","used","as","defined","by","utils.loggers.make_default_logger",".","A","string","`","label","`","can","be","passed","to","easily","change","the","label","associated","with","the","default","logger",";","this","is","ignored","if","a","`","Logger","`","instance","is","given","."]
docstr: Run one episode.
  
  Each episode is a loop which interacts first with the environment to get an
  observation and then give that observation to the agent in order to retrieve
  an action.
  
  Returns:
    An instance of `loggers.LoggingData`.
docstr_tok: ["Run","one","episode",".","Each","episode","is","a","loop","which","interacts","first","with","the","environment","to","get","an","observation","and","then","give","that","observation","to","the","agent","in","order","to","retrieve","an","action",".","Returns",":","An","instance","of","`","loggers.LoggingData","`","."]
code: def run_episode(self) -> loggers.LoggingData:
      """Run one episode.
  
      Each episode is a loop which interacts first with the environment to get an
      observation and then give that observation to the agent in order to retrieve
      an action.
  
      Returns:
        An instance of `loggers.LoggingData`.
      """
      # Reset any counts and start the environment.
      start_time = time.time()
      episode_steps = 0
  
      # For evaluation, this keeps track of the total undiscounted reward
      # for each player accumulated during the episode.
      multiplayer_reward_spec = specs.BoundedArray(
          (self._environment.game.num_players(),),
          np.float32,
          minimum=self._environment.game.min_utility(),
          maximum=self._environment.game.max_utility(),
      )
      episode_return = tree.map_structure(
          _generate_zeros_from_spec, multiplayer_reward_spec
      )
  
      timestep = self._environment.reset()
  
      # Make the first observation.
      self._send_observation(timestep, self._environment.current_player)
  
      # Run an episode.
      while not timestep.last():
          # Generate an action from the agent's policy and step the environment.
          if self._environment.is_turn_based:
              action_list = [
                  self._get_action(
                      timestep, self._environment.current_player
                  )
              ]
          else:
              # FIXME: Support simultaneous move games.
              raise ValueError(
                  "Currently only supports sequential games."
              )
  
          timestep = self._environment.step(action_list)
  
          # Have the agent observe the timestep and let the actor update itself.
          self._send_observation(
              timestep, self._environment.current_player
          )
  
          # Book-keeping.
          episode_steps += 1
  
          # Equivalent to: episode_return += timestep.reward
          # We capture the return value because if timestep.reward is a JAX
          # DeviceArray, episode_return will not be mutated in-place. (In all other
          # cases, the returned episode_return will be the same object as the
          # argument episode_return.)
          episode_return = tree.map_structure(
              operator.iadd, episode_return, timestep.reward
          )
  
      # Record counts.
      counts = self._counter.increment(episodes=1, steps=episode_steps)
  
      # Collect the results and combine with counts.
      steps_per_second = episode_steps / (time.time() - start_time)
      result = {
          "episode_length": episode_steps,
          "episode_return": episode_return,
          "steps_per_second": steps_per_second,
      }
      result.update(counts)
      return result
  
imports: import operator
  import time
  from typing import Optional, Sequence
  from acme import core
  from acme.utils import counting
  from acme.utils import loggers
  from acme.wrappers import open_spiel_wrapper
  import dm_env
  from dm_env import specs
  import numpy
  import tree
  import pyspiel
label_desc: Use image node_id 5 for calling the OpenSpielEnvironmentLoop obj's underlying member method code with example usage: obj.run_episode() and returns: result