Skip to content

Commit

Permalink
Update new Render API (#800)
Browse files Browse the repository at this point in the history
  • Loading branch information
younik authored Oct 1, 2022
1 parent 8e109b9 commit a74a933
Show file tree
Hide file tree
Showing 57 changed files with 681 additions and 246 deletions.
4 changes: 2 additions & 2 deletions docs/_scripts/generate_gif_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
def generate_data(nameline, module):
dir = f"frames/{nameline}/"
os.mkdir(dir)
env = module.env()
env = module.env(render_mode="rgb_array")
# env = gin_rummy_v0.env()
env.reset()
for step in range(100):
Expand All @@ -30,7 +30,7 @@ def generate_data(nameline, module):
if env.terminations[agent] or env.truncations[agent]:
env.reset()

ndarray = env.render(mode="rgb_array")
ndarray = env.render()
# tot_size = max(ndarray.shape)
# target_size = 500
# ratio = target_size / tot_size
Expand Down
23 changes: 18 additions & 5 deletions docs/code_examples/aec_rps.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import functools

import gym
import numpy as np
from gym.spaces import Discrete

Expand All @@ -25,15 +26,17 @@
}


def env():
def env(render_mode=None):
"""
The env function often wraps the environment in wrappers by default.
You can find full documentation for these methods
elsewhere in the developer documentation.
"""
env = raw_env()
internal_render_mode = render_mode if render_mode != "ansi" else "human"
env = raw_env(render_mode=internal_render_mode)
# This wrapper is only for environments which print results to the terminal
env = wrappers.CaptureStdoutWrapper(env)
if render_mode == "ansi":
env = wrappers.CaptureStdoutWrapper(env)
# this wrapper helps error handling for discrete action spaces
env = wrappers.AssertOutOfBoundsWrapper(env)
# Provides a wide vareity of helpful user errors
Expand All @@ -52,7 +55,7 @@ class raw_env(AECEnv):

metadata = {"render_modes": ["human"], "name": "rps_v2"}

def __init__(self):
def __init__(self, render_mode=None):
"""
The init method takes in environment arguments and
should define the following attributes:
Expand All @@ -71,6 +74,7 @@ def __init__(self):
self._observation_spaces = {
agent: Discrete(4) for agent in self.possible_agents
}
self.render_mode = render_mode

# this cache ensures that same space object is returned for the same agent
# allows action space seeding to work as expected
Expand All @@ -83,11 +87,17 @@ def observation_space(self, agent):
def action_space(self, agent):
return Discrete(3)

def render(self, mode="human"):
def render(self):
"""
Renders the environment. In human mode, it can print to terminal, open
up a graphical window, or open up some other display that a human can see and understand.
"""
if self.render_mode is None:
gym.logger.WARN(
"You are calling render method without specifying any render mode."
)
return

if len(self.agents) == 2:
string = "Current state: Agent1: {} , Agent2: {}".format(
MOVES[self.state[self.agents[0]]], MOVES[self.state[self.agents[1]]]
Expand Down Expand Up @@ -203,3 +213,6 @@ def step(self, action):
self.agent_selection = self._agent_selector.next()
# Adds .rewards to ._cumulative_rewards
self._accumulate_rewards()

if self.render_mode == "human":
self.render()
26 changes: 19 additions & 7 deletions docs/code_examples/parallel_rps.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import functools

import gym
from gym.spaces import Discrete

from pettingzoo import ParallelEnv
Expand All @@ -24,15 +25,17 @@
}


def env():
def env(render_mode=None):
"""
The env function often wraps the environment in wrappers by default.
You can find full documentation for these methods
elsewhere in the developer documentation.
"""
env = raw_env()
internal_render_mode = render_mode if render_mode != "ansi" else "human"
env = raw_env(render_mode=internal_render_mode)
# This wrapper is only for environments which print results to the terminal
env = wrappers.CaptureStdoutWrapper(env)
if render_mode == "ansi":
env = wrappers.CaptureStdoutWrapper(env)
# this wrapper helps error handling for discrete action spaces
env = wrappers.AssertOutOfBoundsWrapper(env)
# Provides a wide vareity of helpful user errors
Expand All @@ -41,20 +44,20 @@ def env():
return env


def raw_env():
def raw_env(render_mode=None):
"""
To support the AEC API, the raw_env() function just uses the from_parallel
function to convert from a ParallelEnv to an AEC env
"""
env = parallel_env()
env = parallel_env(render_mode=render_mode)
env = parallel_to_aec(env)
return env


class parallel_env(ParallelEnv):
metadata = {"render_modes": ["human"], "name": "rps_v2"}

def __init__(self):
def __init__(self, render_mode=None):
"""
The init method takes in environment arguments and should define the following attributes:
- possible_agents
Expand All @@ -66,6 +69,7 @@ def __init__(self):
self.agent_name_mapping = dict(
zip(self.possible_agents, list(range(len(self.possible_agents))))
)
self.render_mode = render_mode

# this cache ensures that same space object is returned for the same agent
# allows action space seeding to work as expected
Expand All @@ -78,11 +82,17 @@ def observation_space(self, agent):
def action_space(self, agent):
return Discrete(3)

def render(self, mode="human"):
def render(self):
"""
Renders the environment. In human mode, it can print to terminal, open
up a graphical window, or open up some other display that a human can see and understand.
"""
if self.render_mode is None:
gym.logger.WARN(
"You are calling render method without specifying any render mode."
)
return

if len(self.agents) == 2:
string = "Current state: Agent1: {} , Agent2: {}".format(
MOVES[self.state[self.agents[0]]], MOVES[self.state[self.agents[1]]]
Expand Down Expand Up @@ -157,4 +167,6 @@ def step(self, actions):
if env_truncation:
self.agents = []

if self.render_mode == "human":
self.render()
return observations, rewards, terminations, truncations, infos
2 changes: 1 addition & 1 deletion docs/content/basic_usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ PettingZoo models games as *Agent Environment Cycle* (AEC) games, and thus can s

`seed(seed=None)`: Reseeds the environment. `reset()` must be called after `seed()`, and before `step()`.

`render(mode='human')`: Displays a rendered frame from the environment, if supported. Alternate render modes in the default environments are `'rgb_array'` which returns a numpy array and is supported by all environments outside of classic, and `'ansi'` which returns the strings printed (specific to classic environments).
`render()`: Returns a rendered frame from the environment using render mode specified at initialization. In the case render mode is`'rgb_array'`, returns a numpy array, while with `'ansi'` returns the strings printed. There is no need to call `render()` with `human` mode.

`close()`: Closes the rendering window.

Expand Down
23 changes: 18 additions & 5 deletions pettingzoo/atari/base_atari_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ def __init__(
full_action_space=False,
env_name=None,
max_cycles=100000,
render_mode=None,
auto_rom_install_path=None,
):
"""Initializes the `ParallelAtariEnv` class.
Expand All @@ -56,6 +57,7 @@ def __init__(
full_action_space,
env_name,
max_cycles,
render_mode,
auto_rom_install_path,
)

Expand All @@ -75,6 +77,7 @@ def __init__(
"name": env_name,
"render_fps": 60,
}
self.render_mode = render_mode

multi_agent_ale_py.ALEInterface.setLoggerMode("error")
self.ale = multi_agent_ale_py.ALEInterface()
Expand Down Expand Up @@ -230,12 +233,24 @@ def step(self, action_dict):
}
infos = {agent: {} for agent in self.possible_agents if agent in self.agents}
self.agents = [agent for agent in self.agents if not terminations[agent]]

if self.render_mode == "human":
self.render()
return observations, rewards, terminations, truncations, infos

def render(self, mode="human"):
def render(self):
if self.render_mode is None:
gym.logger.WARN(
"You are calling render method without specifying any render mode."
)
return

assert (
self.render_mode in self.metadata["render_modes"]
), f"{self.render_mode} is not a valid render mode"
(screen_width, screen_height) = self.ale.getScreenDims()
image = self.ale.getScreenRGB()
if mode == "human":
if self.render_mode == "human":
import pygame

zoom_factor = 4
Expand All @@ -256,10 +271,8 @@ def render(self, mode="human"):
self._screen.blit(myImage, (0, 0))

pygame.display.flip()
elif mode == "rgb_array":
elif self.render_mode == "rgb_array":
return image
else:
raise ValueError("bad value for render mode")

def close(self):
if self._screen is not None:
Expand Down
23 changes: 17 additions & 6 deletions pettingzoo/butterfly/cooperative_pong/cooperative_pong.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ def __init__(
bounce_randomness=False,
max_reward=100,
off_screen_penalty=-10,
render_mode=None,
render_ratio=2,
kernel_window_length=2,
):
Expand Down Expand Up @@ -184,6 +185,7 @@ def __init__(
low=0, high=255, shape=((self.s_height, self.s_width, 3)), dtype=np.uint8
)

self.render_mode = render_mode
self.renderOn = False

# set speed
Expand Down Expand Up @@ -258,16 +260,24 @@ def enable_render(self):
self.renderOn = True
self.draw()

def render(self, mode="human"):
if not self.renderOn and mode == "human":
def render(self):
if self.render_mode is None:
gym.logger.WARN(
"You are calling render method without specifying any render mode."
)
return

if not self.renderOn and self.render_mode == "human":
# sets self.renderOn to true and initializes display
self.enable_render()

observation = np.array(pygame.surfarray.pixels3d(self.screen))
if mode == "human":
if self.render_mode == "human":
pygame.display.flip()
return (
np.transpose(observation, axes=(1, 0, 2)) if mode == "rgb_array" else None
np.transpose(observation, axes=(1, 0, 2))
if self.render_mode == "rgb_array"
else None
)

def observe(self):
Expand Down Expand Up @@ -357,6 +367,7 @@ def __init__(self, **kwargs):

self.seed()

self.render_mode = self.env.render_mode
self.agents = self.env.agents[:]
self.possible_agents = self.agents[:]
self._agent_selector = agent_selector(self.agents)
Expand Down Expand Up @@ -410,8 +421,8 @@ def state(self):
def close(self):
self.env.close()

def render(self, mode="human"):
return self.env.render(mode)
def render(self):
return self.env.render()

def step(self, action):
if (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@
import sys
from itertools import repeat

import gym
import numpy as np
import pygame
import pygame.gfxdraw
Expand Down Expand Up @@ -239,6 +240,7 @@ def __init__(
vector_state=True,
use_typemasks=False,
transformer=False,
render_mode=None,
):
EzPickle.__init__(
self,
Expand All @@ -255,6 +257,7 @@ def __init__(
vector_state,
use_typemasks,
transformer,
render_mode,
)
# variable state space
self.transformer = transformer
Expand All @@ -273,6 +276,7 @@ def __init__(
self.frames = 0
self.closed = False
self.has_reset = False
self.render_mode = render_mode
self.render_on = False

# Game Constants
Expand Down Expand Up @@ -765,6 +769,9 @@ def step(self, action):
self._accumulate_rewards()
self._deads_step_first()

if self.render_mode == "human":
self.render()

def enable_render(self):
self.WINDOW = pygame.display.set_mode([const.SCREEN_WIDTH, const.SCREEN_HEIGHT])
# self.WINDOW = pygame.Surface((const.SCREEN_WIDTH, const.SCREEN_HEIGHT))
Expand All @@ -788,16 +795,24 @@ def draw(self):
self.archer_list.draw(self.WINDOW)
self.knight_list.draw(self.WINDOW)

def render(self, mode="human"):
if not self.render_on and mode == "human":
def render(self):
if self.render_mode is None:
gym.logger.WARN(
"You are calling render method without specifying any render mode."
)
return

if not self.render_on and self.render_mode == "human":
# sets self.render_on to true and initializes display
self.enable_render()

observation = np.array(pygame.surfarray.pixels3d(self.WINDOW))
if mode == "human":
if self.render_mode == "human":
pygame.display.flip()
return (
np.transpose(observation, axes=(1, 0, 2)) if mode == "rgb_array" else None
np.transpose(observation, axes=(1, 0, 2))
if self.render_mode == "rgb_array"
else None
)

def close(self):
Expand Down
Loading

0 comments on commit a74a933

Please sign in to comment.