diff --git a/docs/code_examples/parallel_rps.py b/docs/code_examples/parallel_rps.py index 383659666..bf634af10 100644 --- a/docs/code_examples/parallel_rps.py +++ b/docs/code_examples/parallel_rps.py @@ -1,6 +1,7 @@ import functools import gymnasium +import numpy as np from gymnasium.spaces import Discrete from pettingzoo import ParallelEnv @@ -9,7 +10,7 @@ ROCK = 0 PAPER = 1 SCISSORS = 2 -NONE = 3 +NO_MOVE = 3 MOVES = ["ROCK", "PAPER", "SCISSORS", "None"] NUM_ITERS = 100 REWARD_MAP = { @@ -83,6 +84,7 @@ def __init__(self, render_mode=None): @functools.lru_cache(maxsize=None) def observation_space(self, agent): # gymnasium spaces are defined and documented here: https://gymnasium.farama.org/api/spaces/ + # Discrete(4) means an integer in range(0, 4) return Discrete(4) # Action space should be defined here. @@ -128,7 +130,8 @@ def reset(self, seed=None, options=None): """ self.agents = self.possible_agents[:] self.num_moves = 0 - observations = {agent: NONE for agent in self.agents} + # the observations should be numpy arrays even if there is only one value + observations = {agent: np.array(NO_MOVE) for agent in self.agents} infos = {agent: {} for agent in self.agents} self.state = observations @@ -161,9 +164,11 @@ def step(self, actions): env_truncation = self.num_moves >= NUM_ITERS truncations = {agent: env_truncation for agent in self.agents} - # current observation is just the other player's most recent action + # Current observation is just the other player's most recent action + # This is converted to a numpy value of type int to match the type + # that we declared in observation_space() observations = { - self.agents[i]: int(actions[self.agents[1 - i]]) + self.agents[i]: np.array(actions[self.agents[1 - i]], dtype=np.int64) for i in range(len(self.agents)) } self.state = observations diff --git a/docs/content/basic_usage.md b/docs/content/basic_usage.md index 75110efce..ad7589919 100644 --- a/docs/content/basic_usage.md +++ b/docs/content/basic_usage.md @@ -148,5 +148,6 @@ In certain cases, separating agent from environment actions is helpful for study Environments are by default wrapped in a handful of lightweight wrappers that handle error messages and ensure reasonable behavior given incorrect usage (i.e. playing illegal moves or stepping before resetting). However, these add a very small amount of overhead. If you want to create an environment without them, you can do so by using the `raw_env()` constructor contained within each module: ``` python -env = knights_archers_zombies_v10.raw_env() +environment_parameters = {} # any parameters to pass to the environment +env = knights_archers_zombies_v10.raw_env(**environment_parameters) ``` diff --git a/docs/content/environment_tests.md b/docs/content/environment_tests.md index 369ffe98f..a7cfd1d46 100644 --- a/docs/content/environment_tests.md +++ b/docs/content/environment_tests.md @@ -80,10 +80,14 @@ render_test(env_func) The render test method takes in an optional argument `custom_tests` that allows for additional tests in non-standard modes. ``` python +from pettingzoo.test import render_test +from pettingzoo.butterfly import pistonball_v6 +env_func = pistonball_v6.env + custom_tests = { - "svg": lambda render_result: return isinstance(render_result, str) + "svg": lambda render_result: isinstance(render_result, str) } -render_test(env, custom_tests=custom_tests) +render_test(env_func, custom_tests=custom_tests) ``` ## Performance Benchmark Test diff --git a/docs/environments/atari.md b/docs/environments/atari.md index a00a55cfa..b3f31734e 100644 --- a/docs/environments/atari.md +++ b/docs/environments/atari.md @@ -121,7 +121,10 @@ env = supersuit.frame_stack_v1(env, 4) All the Atari environments have the following environment parameters: ``` python -.env(obs_type='rgb_image', full_action_space=True, max_cycles=100000, auto_rom_install_path=None) +# using space invaders as an example, but replace with any atari game +from pettingzoo.atari import space_invaders_v2 + +space_invaders_v2.env(obs_type='rgb_image', full_action_space=True, max_cycles=100000, auto_rom_install_path=None) ``` `obs_type`: There are three possible values for this parameter: diff --git a/docs/index.md b/docs/index.md index 154d283bf..d5d0694ba 100644 --- a/docs/index.md +++ b/docs/index.md @@ -78,11 +78,18 @@ The [AEC API](/api/aec/) supports sequential turn based environments, while the Environments can be interacted with using a similar interface to [Gymnasium](https://gymnasium.farama.org): ```python - from pettingzoo.butterfly import knights_archers_zombies_v10 - env = knights_archers_zombies_v10.env(render_mode="human") - env.reset(seed=42) - for agent in env.agent_iter(): - observation, reward, termination, truncation, info = env.last() - action = policy(observation, agent) - env.step(action) +from pettingzoo.butterfly import knights_archers_zombies_v10 +env = knights_archers_zombies_v10.env(render_mode="human") +env.reset(seed=42) + +for agent in env.agent_iter(): + observation, reward, termination, truncation, info = env.last() + + if termination or truncation: + action = None + else: + # this is where you would insert your policy + action = env.action_space(agent).sample() + + env.step(action) ``` diff --git a/docs/tutorials/custom_environment/index.md b/docs/tutorials/custom_environment/index.md index 77c9a8b5e..7799b3214 100644 --- a/docs/tutorials/custom_environment/index.md +++ b/docs/tutorials/custom_environment/index.md @@ -14,7 +14,7 @@ These tutorials walk you though the full process of creating a custom environmen 4. [Testing Your Environment](/tutorials/custom_environment/4-testing-your-environment.md) -For a simpler example environment, including both [AEC](/api/aec/) and [Parallel](/api/aec/) implementations, see our [Environment Creation](/content/environment_creation/) documentation. +For a simpler example environment, including both [AEC](/api/aec/) and [Parallel](/api/parallel/) implementations, see our [Environment Creation](/content/environment_creation/) documentation. ```{toctree} diff --git a/pettingzoo/atari/maze_craze/maze_craze.py b/pettingzoo/atari/maze_craze/maze_craze.py index 5c3b77a87..88cd4d710 100644 --- a/pettingzoo/atari/maze_craze/maze_craze.py +++ b/pettingzoo/atari/maze_craze/maze_craze.py @@ -85,7 +85,6 @@ """ import os -import warnings from glob import glob from pettingzoo.atari.base_atari_env import ( @@ -102,10 +101,6 @@ def raw_env(game_version="robbers", visibilty_level=0, **kwargs): - if game_version == "robbers" and visibilty_level == 0: - warnings.warn( - "maze_craze has different versions of the game via the `game_version` argument, consider overriding." - ) assert ( game_version in avaliable_versions ), f"`game_version` parameter must be one of {avaliable_versions.keys()}" diff --git a/pettingzoo/butterfly/knights_archers_zombies/knights_archers_zombies.py b/pettingzoo/butterfly/knights_archers_zombies/knights_archers_zombies.py index f81381a5c..0f21753e6 100644 --- a/pettingzoo/butterfly/knights_archers_zombies/knights_archers_zombies.py +++ b/pettingzoo/butterfly/knights_archers_zombies/knights_archers_zombies.py @@ -132,6 +132,7 @@ vector_state=True, use_typemasks=False, sequence_space=False, +) ``` `spawn_rate`: how many cycles before a new zombie is spawned. A lower number means zombies are spawned at a higher rate. diff --git a/pettingzoo/utils/deprecated_module.py b/pettingzoo/utils/deprecated_module.py index 423ac5e6b..49d7b4537 100644 --- a/pettingzoo/utils/deprecated_module.py +++ b/pettingzoo/utils/deprecated_module.py @@ -37,7 +37,17 @@ def deprecated_handler( # It wasn't able to find this module # You should do your deprecation notice here. if not is_env(env_name): - raise ImportError(f"cannot import name '{env_name}' from '{module_name}'") + # Although this seems like an import error, it needs to be an + # AttributeError because it is the failure to find the + # 'env_name' attribute in module_name. + # The distinction is important because this function is used in + # a __getattr__() function to get modules. Raising an error + # other than AttributeError will break the default value handling + # in a call like: getattr(obj, "key", default="value") + # Pytest uses that and will fail if this isn't an AttributeError + raise AttributeError( + f"cannot import name '{env_name}' from '{module_name}'" + ) name, version = env_name.rsplit("_v") for loader, alt_env_name, is_pkg in pkgutil.iter_modules(module_path): @@ -47,7 +57,7 @@ def deprecated_handler( if int(alt_version) > int(version): return DeprecatedModule(name, version, alt_version) else: - raise ImportError( + raise AttributeError( f"cannot import name '{env_name}' from '{module_name}'" ) diff --git a/pyproject.toml b/pyproject.toml index 5c59c9654..c0160ab17 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -43,14 +43,13 @@ mpe = ["pygame==2.3.0"] sisl = ["pygame==2.3.0", "pymunk==6.2.0", "box2d-py==2.3.5", "scipy>=1.4.1"] other = ["pillow>=8.0.1"] testing = [ - "pynput", - "pytest", - "AutoROM", - "pytest", - "pytest-cov", - "pytest-xdist", - "pre-commit", - "pytest-markdown-docs" + "pynput==1.7.6", + "pytest==8.0.0", + "AutoROM==0.6.1", + "pytest-cov==4.1.0", + "pytest-xdist==3.5.0", + "pre-commit==3.5.0", + "pytest-markdown-docs==0.5.0" ] all = [ "multi_agent_ale_py==0.1.11",