text: import gym
  import numpy as np
  from gym import spaces
  from gym.utils import seeding
  from pettingzoo.utils.env import ParallelEnv
  from pettingzoo.utils import wrappers
  from copy import deepcopy
  
  
  def make_env(raw_env):
      def env(**kwargs):
          env = raw_env(**kwargs)
          env = wrappers.AssertOutOfBoundsWrapper(env)
          backup_policy = "taking zero action (no movement, communication 0)"
          env = wrappers.NanNoOpWrapper(env, 4, backup_policy)
          env = wrappers.OrderEnforcingWrapper(env)
          return env
      return env
  
  
  class ParallelBox2dEnv(ParallelEnv):
      def __init__(self, env_id, max_frames, obs_add_step=False, env_configs=None):
          super(ParallelBox2dEnv, self).__init__()
  
          if env_configs is None:
              env_configs = dict()
          self.env = gym.make(env_id, **env_configs)
          self.max_frames = max_frames
  
          self.np_random = None
          self.seed()
  
          self.obs_add_step = obs_add_step
  
          self.num_agents = 1
          self.agents = [0]
          self.action_spaces = [self._action_space]
          self.observation_spaces = [self.get_observation_space()]
          self.input_structures = [self._input_structure]
  
          self.steps = 0
  
      def seed(self, seed=None):
          self.np_random, seed = seeding.np_random(seed)
          self.env.np_random = self.np_random
  
      @property
      def _action_space(self):
          return self.env.action_space
  
      def get_observation_space(self):
          obs_space = deepcopy(self.env.observation_space)
          assert isinstance(obs_space, spaces.Box)
          if self.obs_add_step:
              assert len(obs_space.shape) == 1
              obs_space.shape = (obs_space.shape[0] + 1,)
              obs_space.low = np.concatenate(([0.], obs_space.low))
              obs_space.high = np.concatenate(([1.], obs_space.low))
          return obs_space
  
      @property
      def _input_structure(self):
          raise NotImplementedError
  
      def process_obs(self, obs):
          if self.obs_add_step:
              obs = np.concatenate(([self.steps / self.max_frames], obs))
          return obs
  
      def reset(self):
          self.steps = 0
          return [self.process_obs(self.env.reset())]
  
      def step(self, actions):
          # print("env actions", actions)
          self.steps += 1
          observation, reward, done, info = self.env.step(actions[0])
          if self.steps >= self.max_frames:
              done = True
          else:
              done = False
          # print(observation)
          return [self.process_obs(observation)], [reward], [done], [info]
  
      def render(self, mode="human"):
          self.env.render(mode=mode)
  