class_docstr: Stores multi-agent episode data.
  
  The central attribute of the class is the timestep mapping
  `global_t_to_local_t` that maps the global (environment)
  timestep to the local (agent) timesteps.
  
  The `MultiAgentEpisode` is based on the `SingleAgentEpisode`s
  for each agent, stored in `MultiAgentEpisode.agent_episodes`.
class_docstr_tok: ["Stores","multi-agent","episode","data",".","The","central","attribute","of","the","class","is","the","timestep","mapping","`","global_t_to_local_t","`","that","maps","the","global","(","environment",")","timestep","to","the","local","(","agent",")","timesteps",".","The","`","MultiAgentEpisode","`","is","based","on","the","`","SingleAgentEpisode","`","s","for","each","agent",",","stored","in","`","MultiAgentEpisode.agent_episodes","`","."]
docstr: Returns a successor episode chunk (of len=0) continuing from this Episode.
  
  The successor will have the same ID as `self` and starts at the timestep where
  it's predecessor `self` left off. The current observations and infos
  are carried over from the predecessor as initial observations/infos.
  
  Returns: A MultiAgentEpisode starting at the timestep where its predecessor
      stopped.
code: def cut(self) -> "MultiAgentEpisode":
      """Returns a successor episode chunk (of len=0) continuing from this Episode.
  
      The successor will have the same ID as `self` and starts at the timestep where
      it's predecessor `self` left off. The current observations and infos
      are carried over from the predecessor as initial observations/infos.
  
      Returns: A MultiAgentEpisode starting at the timestep where its predecessor
          stopped.
      """
      assert not self.is_done
  
      successor = MultiAgentEpisode(
          id_=self.id_,
          agent_ids=self._agent_ids,
          agent_episode_ids={
              agent_id: agent_eps.id_
              for agent_id, agent_eps in self.agent_episodes.items()
          },
          terminateds=self.is_terminated,
          truncateds=self.is_truncated,
          t_started=self.t,
      )
  
      for agent_id, agent_eps in self.agent_episodes.items():
          # Call the `SingleAgentEpisode.create_successor` method for
          # all agents that are still alive.
          if not agent_eps.is_done and agent_eps.observations:
              # Build a successor for each agent that is not done, yet.
              successor.agent_episodes[agent_id] = agent_eps.cut()
              # Record the initial observation in the global timestep mapping.
              successor.global_t_to_local_t[agent_id] = _IndexMapping(
                  [self.global_t_to_local_t[agent_id][-1]]
              )
          # For agents that are done or have no observation yet, create empty
          # instances.
          else:
              successor.agent_episodes[agent_id] = SingleAgentEpisode(
                  id_=agent_eps.id_,
                  terminated=agent_eps.is_terminated,
                  truncated=agent_eps.is_truncated,
              )
              successor.global_t_to_local_t[agent_id] = _IndexMapping()
  
      # Copy the agent buffers to the successor. These remain the same as
      # no agent has stepped, yet.
      successor._copy_buffer(self)
  
      # Build the global action timestep mapping for buffered actions.
      # Note, this mapping tracks orhpane actions in the episode before and
      # gives it a timestep `successor.t`, i.e. calling `get_actions(indices=0)`
      # will return these orphane actions from the predecessor.
      # TODO (simon): This might lead to information loss when concatenating.
      # as the action was made before when the agent had its last observation.
      # This observation might help to avoid the loss.
      successor.global_actions_t = (
          self._generate_action_timestep_mappings()
      )
  
      # Add the not-yet recorded partial rewards for each agent.
      # TODO (simon): Check, if get_rewards can help here (with global_ts=False)
      successor = self._add_partial_rewards(successor)
  
      # Return the successor.
      return successor
  
imports: from collections import defaultdict
  from queue import Queue
  from typing import Any, Dict, List, Optional, Set, Union
  import uuid
  import numpy
  from ray.rllib.env.single_agent_episode import SingleAgentEpisode
  from ray.rllib.policy.sample_batch import MultiAgentBatch
  from ray.rllib.utils.typing import MultiAgentDict
label_desc: Use image node_id 14 for calling the MultiAgentEpisode obj's underlying member method code with example usage: obj.cut() and returns: successor