ale-py
Advanced tools
| #include "ale_vector_python_interface.hpp" | ||
| #include <pybind11/pybind11.h> | ||
| #include <pybind11/stl.h> | ||
| #include <pybind11/stl/filesystem.h> | ||
| #include <pybind11/numpy.h> | ||
| #include <vector> | ||
| #include <cmath> | ||
| #include <map> | ||
| #include <tuple> | ||
| namespace py = pybind11; | ||
| // Function to add vector environment bindings to an existing module | ||
| void init_vector_module(py::module& m) { | ||
| // Define ALEVectorInterface class | ||
| py::class_<ale::vector::ALEVectorInterface>(m, "ALEVectorInterface") | ||
| .def(py::init<const fs::path, int, int, int, int, int, bool, int, bool, bool, bool, bool, int, float, bool, int, int, int>(), | ||
| py::arg("rom_path"), | ||
| py::arg("num_envs"), | ||
| py::arg("frame_skip") = 4, | ||
| py::arg("stack_num") = 4, | ||
| py::arg("img_height") = 84, | ||
| py::arg("img_width") = 84, | ||
| py::arg("maxpool") = true, | ||
| py::arg("noop_max") = 30, | ||
| py::arg("use_fire_reset") = true, | ||
| py::arg("episodic_life") = false, | ||
| py::arg("life_loss_info") = false, | ||
| py::arg("reward_clipping") = true, | ||
| py::arg("max_episode_steps") = 108000, | ||
| py::arg("repeat_action_probability") = 0.0f, | ||
| py::arg("full_action_space") = false, | ||
| py::arg("batch_size") = 0, | ||
| py::arg("num_threads") = 0, | ||
| py::arg("thread_affinity_offset") = -1) | ||
| .def("reset", [](ale::vector::ALEVectorInterface& self, const std::vector<int> reset_indices, const std::vector<int> reset_seeds) { | ||
| // Call C++ reset method with GIL released | ||
| py::gil_scoped_release release; | ||
| auto timesteps = self.reset(reset_indices, reset_seeds); | ||
| py::gil_scoped_acquire acquire; | ||
| // Get shape information | ||
| auto shape_info = self.get_observation_shape(); | ||
| int stack_num = std::get<0>(shape_info); | ||
| int height = std::get<1>(shape_info); | ||
| int width = std::get<2>(shape_info); | ||
| int num_envs = timesteps.size(); | ||
| // Create a single NumPy array for all observations | ||
| py::array_t<uint8_t> observations({num_envs, stack_num, height, width}); | ||
| auto observations_ptr = static_cast<uint8_t*>(observations.mutable_data()); | ||
| // Create arrays for info fields | ||
| py::array_t<int> env_ids(num_envs); | ||
| py::array_t<int> lives(num_envs); | ||
| py::array_t<int> frame_numbers(num_envs); | ||
| py::array_t<int> episode_frame_numbers(num_envs); | ||
| auto env_ids_ptr = static_cast<int*>(env_ids.mutable_data()); | ||
| auto lives_ptr = static_cast<int*>(lives.mutable_data()); | ||
| auto frame_numbers_ptr = static_cast<int*>(frame_numbers.mutable_data()); | ||
| auto episode_frame_numbers_ptr = static_cast<int*>(episode_frame_numbers.mutable_data()); | ||
| // Copy data from observations to NumPy arrays | ||
| size_t obs_size = stack_num * height * width; | ||
| for (int i = 0; i < num_envs; i++) { | ||
| const auto& timestep = timesteps[i]; | ||
| // Copy screen data | ||
| std::memcpy( | ||
| observations_ptr + i * obs_size, | ||
| timestep.observation.data(), | ||
| obs_size * sizeof(uint8_t) | ||
| ); | ||
| // Copy info fields | ||
| env_ids_ptr[i] = timestep.env_id; | ||
| lives_ptr[i] = timestep.lives; | ||
| frame_numbers_ptr[i] = timestep.frame_number; | ||
| episode_frame_numbers_ptr[i] = timestep.episode_frame_number; | ||
| } | ||
| // Create info dict | ||
| py::dict info; | ||
| info["env_id"] = env_ids; | ||
| info["lives"] = lives; | ||
| info["frame_number"] = frame_numbers; | ||
| info["episode_frame_number"] = episode_frame_numbers; | ||
| return py::make_tuple(observations, info); | ||
| }) | ||
| .def("send", [](ale::vector::ALEVectorInterface& self, const std::vector<int> action_ids, const std::vector<float> paddle_strengths) { | ||
| self.send(action_ids, paddle_strengths); | ||
| }) | ||
| .def("recv", [](ale::vector::ALEVectorInterface& self) { | ||
| auto timesteps = self.recv(); | ||
| py::gil_scoped_acquire acquire; | ||
| // Get shape information | ||
| auto shape_info = self.get_observation_shape(); | ||
| int stack_num = std::get<0>(shape_info); | ||
| int height = std::get<1>(shape_info); | ||
| int width = std::get<2>(shape_info); | ||
| int num_envs = timesteps.size(); | ||
| // Create NumPy arrays | ||
| py::array_t<uint8_t> observations({num_envs, stack_num, height, width}); | ||
| py::array_t<int> rewards(num_envs); | ||
| py::array_t<bool> terminations(num_envs); | ||
| py::array_t<bool> truncations(num_envs); | ||
| py::array_t<int> env_ids(num_envs); | ||
| py::array_t<int> lives(num_envs); | ||
| py::array_t<int> frame_numbers(num_envs); | ||
| py::array_t<int> episode_frame_numbers(num_envs); | ||
| // Get pointers to the arrays' data | ||
| auto observations_ptr = static_cast<uint8_t*>(observations.mutable_data()); | ||
| auto rewards_ptr = static_cast<int*>(rewards.mutable_data()); | ||
| auto terminations_ptr = static_cast<bool*>(terminations.mutable_data()); | ||
| auto truncations_ptr = static_cast<bool*>(truncations.mutable_data()); | ||
| auto env_ids_ptr = static_cast<int*>(env_ids.mutable_data()); | ||
| auto lives_ptr = static_cast<int*>(lives.mutable_data()); | ||
| auto frame_numbers_ptr = static_cast<int*>(frame_numbers.mutable_data()); | ||
| auto episode_frame_numbers_ptr = static_cast<int*>(episode_frame_numbers.mutable_data()); | ||
| // Copy data from observations to NumPy arrays | ||
| size_t obs_size = stack_num * height * width; | ||
| for (int i = 0; i < num_envs; i++) { | ||
| const auto& timestep = timesteps[i]; | ||
| // Copy screen data | ||
| std::memcpy( | ||
| observations_ptr + i * obs_size, | ||
| timestep.observation.data(), | ||
| obs_size * sizeof(uint8_t) | ||
| ); | ||
| // Copy other fields | ||
| rewards_ptr[i] = timestep.reward; | ||
| terminations_ptr[i] = timestep.terminated; | ||
| truncations_ptr[i] = timestep.truncated; | ||
| env_ids_ptr[i] = timestep.env_id; | ||
| lives_ptr[i] = timestep.lives; | ||
| frame_numbers_ptr[i] = timestep.frame_number; | ||
| episode_frame_numbers_ptr[i] = timestep.episode_frame_number; | ||
| } | ||
| // Create info dict | ||
| py::dict info; | ||
| info["env_id"] = env_ids; | ||
| info["lives"] = lives; | ||
| info["frame_number"] = frame_numbers; | ||
| info["episode_frame_number"] = episode_frame_numbers; | ||
| return py::make_tuple(observations, rewards, terminations, truncations, info); | ||
| }) | ||
| .def("get_action_set", &ale::vector::ALEVectorInterface::get_action_set) | ||
| .def("get_num_envs", &ale::vector::ALEVectorInterface::get_num_envs) | ||
| .def("get_observation_shape", &ale::vector::ALEVectorInterface::get_observation_shape); | ||
| } |
| #ifndef ALE_VECTOR_INTERFACE_HPP_ | ||
| #define ALE_VECTOR_INTERFACE_HPP_ | ||
| #include <string> | ||
| #include <vector> | ||
| #include <memory> | ||
| #include <random> | ||
| #include <filesystem> | ||
| #include <stdexcept> | ||
| #include "ale/vector/async_vectorizer.hpp" | ||
| #include "ale/vector/preprocessed_env.hpp" | ||
| #include "ale/vector/utils.hpp" | ||
| #include <pybind11/pybind11.h> | ||
| #include <pybind11/stl.h> | ||
| #include <pybind11/stl/filesystem.h> | ||
| #include <pybind11/numpy.h> | ||
| namespace py = pybind11; | ||
| void init_vector_module(py::module& m); | ||
| namespace fs = std::filesystem; | ||
| namespace ale { | ||
| namespace vector { | ||
| /** | ||
| * ALEVectorInterface provides a vectorized interface to the Arcade Learning Environment. | ||
| * It manages multiple Atari environments running in parallel and allows sending actions | ||
| * and receiving observations in batches. | ||
| */ | ||
| class ALEVectorInterface { | ||
| public: | ||
| /** | ||
| * Constructor | ||
| * | ||
| * @param rom_path Path to the ROM file | ||
| * @param num_envs Number of parallel environments | ||
| * @param frame_skip Number of frames to skip between agent decisions (default: 4) | ||
| * @param stack_num Number of frames to stack for observations (default: 4) | ||
| * @param img_height Height to resize frames to (default: 84) | ||
| * @param img_width Width to resize frames to (default: 84) | ||
| * @param maxpool If to maxpool over frames (default: true) | ||
| * @param noop_max Maximum number of no-ops to perform at reset (default: 30) | ||
| * @param fire_reset Whether to press FIRE during reset (default: true) | ||
| * @param episodic_life Whether to end episodes when a life is lost (default: false) | ||
| * @param max_episode_steps Maximum number of steps per episode (default: 108000) | ||
| * @param repeat_action_probability Probability of repeating the last action (default: 0.0f) | ||
| * @param full_action_space Whether to use the full action space (default: false) | ||
| * @param batch_size The number of environments to process in a batch (0 means use num_envs, default: 0) | ||
| * @param num_threads The number of worker threads to use (0 means use hardware concurrency, default: 0) | ||
| * @param seed Random seed (default: 0) | ||
| * @param thread_affinity_offset The CPU core offset for thread affinity (-1 means no affinity, default: -1) | ||
| */ | ||
| ALEVectorInterface( | ||
| const fs::path rom_path, | ||
| int num_envs, | ||
| int frame_skip = 4, | ||
| int stack_num = 4, | ||
| int img_height = 84, | ||
| int img_width = 84, | ||
| bool maxpool = true, | ||
| int noop_max = 30, | ||
| bool use_fire_reset = true, | ||
| bool episodic_life = false, | ||
| bool life_loss_info = false, | ||
| bool reward_clipping = true, | ||
| int max_episode_steps = 108000, | ||
| float repeat_action_probability = 0.0f, | ||
| bool full_action_space = false, | ||
| int batch_size = 0, | ||
| int num_threads = 0, | ||
| int thread_affinity_offset = -1 | ||
| ) : rom_path_(rom_path), | ||
| num_envs_(num_envs), | ||
| frame_skip_(frame_skip), | ||
| stack_num_(stack_num), | ||
| img_height_(img_height), | ||
| img_width_(img_width), | ||
| maxpool_(maxpool), | ||
| noop_max_(noop_max), | ||
| use_fire_reset_(use_fire_reset), | ||
| episodic_life_(episodic_life), | ||
| life_loss_info_(life_loss_info), | ||
| reward_clipping_(reward_clipping), | ||
| max_episode_steps_(max_episode_steps), | ||
| repeat_action_probability_(repeat_action_probability), | ||
| full_action_space_(full_action_space), | ||
| received_env_ids_(batch_size > 0 ? batch_size : num_envs) { | ||
| // Create environment factory | ||
| auto env_factory = [this](int env_id) { | ||
| return std::make_unique<PreprocessedAtariEnv>( | ||
| env_id, | ||
| rom_path_, | ||
| img_height_, | ||
| img_width_, | ||
| frame_skip_, | ||
| maxpool_, | ||
| stack_num_, | ||
| noop_max_, | ||
| use_fire_reset_, | ||
| episodic_life_, | ||
| life_loss_info_, | ||
| reward_clipping_, | ||
| max_episode_steps_, | ||
| repeat_action_probability_, | ||
| full_action_space_, | ||
| -1 | ||
| ); | ||
| }; | ||
| // Create vectorizer | ||
| vectorizer_ = std::make_unique<AsyncVectorizer>( | ||
| num_envs, | ||
| batch_size, | ||
| num_threads, | ||
| thread_affinity_offset, | ||
| env_factory | ||
| ); | ||
| // Initialize action set (assuming all environments have the same action set) | ||
| auto temp_env = env_factory(0); | ||
| action_set_ = temp_env->get_action_set(); | ||
| } | ||
| /** | ||
| * Reset all environments | ||
| * | ||
| * @param reset_indices Vector of environment indices to be reset | ||
| * @return Timesteps from all environments after reset | ||
| */ | ||
| std::vector<Timestep> reset(const std::vector<int> reset_indices, const std::vector<int> reset_seeds) { | ||
| vectorizer_->reset(reset_indices, reset_seeds); | ||
| return recv(); | ||
| } | ||
| /** | ||
| * Step environments with actions | ||
| * | ||
| * @param actions Vector of actions to take in environments | ||
| */ | ||
| void send(const std::vector<int>& action_ids, const std::vector<float>& paddle_strengths) { | ||
| if (action_ids.size() != paddle_strengths.size()) { | ||
| throw std::invalid_argument( | ||
| "The size of the action_ids is different from the paddle_strengths, action_ids length=" + std::to_string(action_ids.size()) | ||
| + ", paddle_strengths length=" + std::to_string(paddle_strengths.size())); | ||
| } | ||
| std::vector<ale::vector::EnvironmentAction> environment_actions; | ||
| environment_actions.resize(action_ids.size()); | ||
| for (int i = 0; i < action_ids.size(); i++) { | ||
| ale::vector::EnvironmentAction env_action; | ||
| env_action.env_id = received_env_ids_[i]; | ||
| env_action.action_id = action_ids[i]; | ||
| env_action.paddle_strength = paddle_strengths[i]; | ||
| environment_actions[i] = env_action; | ||
| } | ||
| vectorizer_->send(environment_actions); | ||
| } | ||
| /** | ||
| * Returns the environment's data for the environments | ||
| */ | ||
| std::vector<Timestep> recv() { | ||
| std::vector<Timestep> timesteps = vectorizer_->recv(); | ||
| for (int i = 0; i < timesteps.size(); i++) { | ||
| received_env_ids_[i] = timesteps[i].env_id; | ||
| } | ||
| return timesteps; | ||
| } | ||
| /** | ||
| * Get the available actions for the environments | ||
| * | ||
| * @return Vector of available actions | ||
| */ | ||
| const ActionVect& get_action_set() const { | ||
| return action_set_; | ||
| } | ||
| /** | ||
| * Get the number of environments | ||
| * | ||
| * @return Number of environments | ||
| */ | ||
| int get_num_envs() const { | ||
| return num_envs_; | ||
| } | ||
| /** | ||
| * Get the dimensions of the observation space | ||
| * | ||
| * @return Tuple of (stack_num, height, width) | ||
| */ | ||
| std::tuple<int, int, int> get_observation_shape() const { | ||
| return std::make_tuple(stack_num_, img_height_, img_width_); | ||
| } | ||
| private: | ||
| fs::path rom_path_; // Path to the ROM file | ||
| int num_envs_; // Number of parallel environments | ||
| int frame_skip_; // Number of frames to skip | ||
| int stack_num_; // Number of frames to stack | ||
| int img_height_; // Height of resized frames | ||
| int img_width_; // Width of resized frames | ||
| bool maxpool_; // If to maxpool over frames | ||
| int noop_max_; // Max no-ops on reset | ||
| bool use_fire_reset_; // Whether to fire on reset | ||
| bool episodic_life_; // End episode on life loss | ||
| bool life_loss_info_; // If to provide termination signal (but not reset) on life loss | ||
| bool reward_clipping_; // If to clip rewards between -1 and 1 | ||
| int max_episode_steps_; // Max steps per episode | ||
| float repeat_action_probability_; // Sticky actions probability | ||
| bool full_action_space_; // Use full action space | ||
| std::vector<int> received_env_ids_; // Vector of environment ids for the most recently received data | ||
| std::unique_ptr<AsyncVectorizer> vectorizer_; // Vectorizer | ||
| ActionVect action_set_; // Set of available actions | ||
| }; | ||
| } // namespace vector | ||
| } // namespace ale | ||
| #endif // ALE_VECTOR_INTERFACE_HPP_ |
Sorry, the diff of this file is too big to display
| """Vector environment for ALE.""" | ||
| from __future__ import annotations | ||
| from typing import Any | ||
| import ale_py | ||
| import gymnasium.vector.utils | ||
| import numpy as np | ||
| from ale_py import roms | ||
| from ale_py.env import AtariEnv | ||
| from gymnasium.core import ObsType | ||
| from gymnasium.spaces import Box, Discrete | ||
| from gymnasium.vector import VectorEnv | ||
| class AtariVectorEnv(VectorEnv): | ||
| """Vector environment implementation for ALE.""" | ||
| def __init__( | ||
| self, | ||
| game: str, | ||
| num_envs: int, | ||
| *, | ||
| batch_size: int = 0, | ||
| num_threads: int = 0, | ||
| thread_affinity_offset: int = -1, | ||
| max_num_frames_per_episode: int = 108000, | ||
| repeat_action_probability: float = 0.0, | ||
| full_action_space: bool = False, | ||
| continuous: bool = False, | ||
| continuous_action_threshold: float = 0.5, | ||
| # Preprocessing values | ||
| img_height: int = 84, | ||
| img_width: int = 84, | ||
| stack_num: int = 4, | ||
| frameskip: int = 4, | ||
| maxpool: bool = True, | ||
| noop_max: int = 30, | ||
| episodic_life: bool = False, | ||
| life_loss_info: bool = False, | ||
| reward_clipping: bool = True, | ||
| use_fire_reset: bool = True, | ||
| ): | ||
| """Constructor for vector environment. | ||
| Args: | ||
| game: ROM name | ||
| num_envs: Number of environments | ||
| batch_size: If to provide a batch of environments (in async mode) | ||
| num_threads: The number of threads to use for parallel environments | ||
| thread_affinity_offset: The CPU core offset for thread affinity (-1 means no affinity, default: -1) | ||
| max_num_frames_per_episode: Maximum number of steps per episode | ||
| repeat_action_probability: Repeat action probability for the sub-environments | ||
| full_action_space: If the environment should use the full action space | ||
| continuous: If to use the continuous action space | ||
| continuous_action_threshold: The continuous action threshold | ||
| img_height: The frame height | ||
| img_width: The ƒrame width | ||
| stack_num: The frame stack size | ||
| frameskip: The number of frame skips to use for each action | ||
| maxpool: If maxpool over subsequent frames | ||
| noop_max: If to use noop-max for the episode resets | ||
| episodic_life: If to terminate episodes on life losses | ||
| life_loss_info: If to provide a termination signal on life loss | ||
| reward_clipping: If to clip rewards between -1 and 1 | ||
| use_fire_reset: If to take fire action on reset if available | ||
| """ | ||
| self.ale = ale_py.ALEVectorInterface( | ||
| rom_path=roms.get_rom_path(game), | ||
| num_envs=num_envs, | ||
| frame_skip=frameskip, | ||
| stack_num=stack_num, | ||
| img_height=img_height, | ||
| img_width=img_width, | ||
| maxpool=maxpool, | ||
| noop_max=noop_max, | ||
| use_fire_reset=use_fire_reset, | ||
| episodic_life=episodic_life, | ||
| life_loss_info=life_loss_info, | ||
| reward_clipping=reward_clipping, | ||
| max_episode_steps=max_num_frames_per_episode, | ||
| repeat_action_probability=repeat_action_probability, | ||
| full_action_space=full_action_space, | ||
| batch_size=batch_size, | ||
| num_threads=num_threads, | ||
| thread_affinity_offset=thread_affinity_offset, | ||
| ) | ||
| self.continuous = continuous | ||
| self.continuous_action_threshold = continuous_action_threshold | ||
| self.map_action_idx = np.zeros((3, 3, 2), dtype=np.int32) | ||
| for h in (-1, 0, 1): | ||
| for v in (-1, 0, 1): | ||
| for f in (False, True): | ||
| self.map_action_idx[h, v, f] = AtariEnv.map_action_idx( | ||
| h, v, f | ||
| ).value | ||
| self.single_observation_space = Box( | ||
| shape=(stack_num, img_height, img_width), low=0, high=255, dtype=np.uint8 | ||
| ) | ||
| if self.continuous: | ||
| # Actions are radius, theta, and fire, where first two are the parameters of polar coordinates. | ||
| self.single_action_space = Box( | ||
| np.array([0.0, -np.pi, 0.0]).astype(np.float32), | ||
| np.array([1.0, np.pi, 1.0]).astype(np.float32), | ||
| ) | ||
| else: | ||
| self.single_action_space = Discrete(len(self.ale.get_action_set())) | ||
| self.batch_size = num_envs if batch_size == 0 else batch_size | ||
| self.num_envs = num_envs | ||
| self.observation_space = gymnasium.vector.utils.batch_space( | ||
| self.single_observation_space, self.batch_size | ||
| ) | ||
| self.action_space = gymnasium.vector.utils.batch_space( | ||
| self.single_action_space, self.batch_size | ||
| ) | ||
| def reset( | ||
| self, *, seed: int | None = None, options: dict[str, Any] | None = None | ||
| ) -> tuple[ObsType, dict[str, Any]]: | ||
| """Resets the sub-environments. | ||
| Args: | ||
| seed: Current unimplemented | ||
| options: Supports `reset_mask` that indicates what sub-environments should be reset | ||
| Returns: | ||
| Tuple of observations for the sub-environments and info on them. | ||
| """ | ||
| if options is None or "reset_mask" not in options: | ||
| reset_indices = np.arange(self.num_envs) | ||
| else: | ||
| reset_mask = options["reset_mask"] | ||
| assert isinstance(reset_mask, np.ndarray) and reset_mask.dtype == np.bool | ||
| reset_indices, _ = np.where(reset_mask) | ||
| if seed is None: | ||
| reset_seeds = np.full(len(reset_indices), -1) | ||
| elif isinstance(seed, int): | ||
| reset_seeds = np.arange(seed, seed + len(reset_indices)) | ||
| elif isinstance(seed, np.ndarray): | ||
| reset_seeds = seed | ||
| else: | ||
| raise TypeError("Unsupported seed type") | ||
| return self.ale.reset(reset_indices, reset_seeds) | ||
| def step( | ||
| self, actions: np.ndarray | ||
| ) -> tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray, dict[str, Any]]: | ||
| """Steps through the sub-environments for which the actions are taken, return arrays for the next observations, rewards, termination, truncation and info.""" | ||
| self.send(actions) | ||
| return self.ale.recv() | ||
| def send(self, actions: np.ndarray): | ||
| """Send the actions to the sub-environments.""" | ||
| if self.continuous: | ||
| assert isinstance(actions, np.ndarray) | ||
| assert actions.dtype == np.float32 | ||
| assert actions.shape == (self.batch_size, 2) | ||
| x = actions[0, :] * np.cos(actions[1, :]) | ||
| y = actions[0, :] * np.sin(actions[1, :]) | ||
| horizontal = -(x < self.continuous_action_threshold) + ( | ||
| x > self.continuous_action_threshold | ||
| ) | ||
| vertical = -(y < self.continuous_action_threshold) + ( | ||
| y > self.continuous_action_threshold | ||
| ) | ||
| fire = actions[1, :] > self.continuous_action_threshold | ||
| action_ids = self.map_action_idx[np.array([horizontal, vertical, fire])] | ||
| paddle_strength = actions[1, :] | ||
| self.ale.send(action_ids, paddle_strength) | ||
| else: | ||
| assert isinstance(actions, np.ndarray) | ||
| assert actions.dtype == np.int64 or actions.dtype == np.int32 | ||
| assert actions.shape == (self.batch_size,) | ||
| paddle_strength = np.ones(self.batch_size) | ||
| self.ale.send(actions, paddle_strength) | ||
| def recv( | ||
| self, | ||
| ) -> tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray, dict[str, Any]]: | ||
| """Receive the next observations, rewards, terminations, truncations and info from the sub-environments.""" | ||
| # The data will be of the batch_size, see `info["env_id"]` for the set of environments used. | ||
| return self.ale.recv() |
| ### GNU GENERAL PUBLIC LICENSE | ||
| Version 2, June 1991 | ||
| Copyright (C) 1989, 1991 Free Software Foundation, Inc. | ||
| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA | ||
| Everyone is permitted to copy and distribute verbatim copies | ||
| of this license document, but changing it is not allowed. | ||
| ### Preamble | ||
| The licenses for most software are designed to take away your freedom | ||
| to share and change it. By contrast, the GNU General Public License is | ||
| intended to guarantee your freedom to share and change free | ||
| software--to make sure the software is free for all its users. This | ||
| General Public License applies to most of the Free Software | ||
| Foundation's software and to any other program whose authors commit to | ||
| using it. (Some other Free Software Foundation software is covered by | ||
| the GNU Lesser General Public License instead.) You can apply it to | ||
| your programs, too. | ||
| When we speak of free software, we are referring to freedom, not | ||
| price. Our General Public Licenses are designed to make sure that you | ||
| have the freedom to distribute copies of free software (and charge for | ||
| this service if you wish), that you receive source code or can get it | ||
| if you want it, that you can change the software or use pieces of it | ||
| in new free programs; and that you know you can do these things. | ||
| To protect your rights, we need to make restrictions that forbid | ||
| anyone to deny you these rights or to ask you to surrender the rights. | ||
| These restrictions translate to certain responsibilities for you if | ||
| you distribute copies of the software, or if you modify it. | ||
| For example, if you distribute copies of such a program, whether | ||
| gratis or for a fee, you must give the recipients all the rights that | ||
| you have. You must make sure that they, too, receive or can get the | ||
| source code. And you must show them these terms so they know their | ||
| rights. | ||
| We protect your rights with two steps: (1) copyright the software, and | ||
| (2) offer you this license which gives you legal permission to copy, | ||
| distribute and/or modify the software. | ||
| Also, for each author's protection and ours, we want to make certain | ||
| that everyone understands that there is no warranty for this free | ||
| software. If the software is modified by someone else and passed on, | ||
| we want its recipients to know that what they have is not the | ||
| original, so that any problems introduced by others will not reflect | ||
| on the original authors' reputations. | ||
| Finally, any free program is threatened constantly by software | ||
| patents. We wish to avoid the danger that redistributors of a free | ||
| program will individually obtain patent licenses, in effect making the | ||
| program proprietary. To prevent this, we have made it clear that any | ||
| patent must be licensed for everyone's free use or not licensed at | ||
| all. | ||
| The precise terms and conditions for copying, distribution and | ||
| modification follow. | ||
| ### TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION | ||
| **0.** This License applies to any program or other work which | ||
| contains a notice placed by the copyright holder saying it may be | ||
| distributed under the terms of this General Public License. The | ||
| "Program", below, refers to any such program or work, and a "work | ||
| based on the Program" means either the Program or any derivative work | ||
| under copyright law: that is to say, a work containing the Program or | ||
| a portion of it, either verbatim or with modifications and/or | ||
| translated into another language. (Hereinafter, translation is | ||
| included without limitation in the term "modification".) Each licensee | ||
| is addressed as "you". | ||
| Activities other than copying, distribution and modification are not | ||
| covered by this License; they are outside its scope. The act of | ||
| running the Program is not restricted, and the output from the Program | ||
| is covered only if its contents constitute a work based on the Program | ||
| (independent of having been made by running the Program). Whether that | ||
| is true depends on what the Program does. | ||
| **1.** You may copy and distribute verbatim copies of the Program's | ||
| source code as you receive it, in any medium, provided that you | ||
| conspicuously and appropriately publish on each copy an appropriate | ||
| copyright notice and disclaimer of warranty; keep intact all the | ||
| notices that refer to this License and to the absence of any warranty; | ||
| and give any other recipients of the Program a copy of this License | ||
| along with the Program. | ||
| You may charge a fee for the physical act of transferring a copy, and | ||
| you may at your option offer warranty protection in exchange for a | ||
| fee. | ||
| **2.** You may modify your copy or copies of the Program or any | ||
| portion of it, thus forming a work based on the Program, and copy and | ||
| distribute such modifications or work under the terms of Section 1 | ||
| above, provided that you also meet all of these conditions: | ||
| **a)** You must cause the modified files to carry prominent notices | ||
| stating that you changed the files and the date of any change. | ||
| **b)** You must cause any work that you distribute or publish, that in | ||
| whole or in part contains or is derived from the Program or any part | ||
| thereof, to be licensed as a whole at no charge to all third parties | ||
| under the terms of this License. | ||
| **c)** If the modified program normally reads commands interactively | ||
| when run, you must cause it, when started running for such interactive | ||
| use in the most ordinary way, to print or display an announcement | ||
| including an appropriate copyright notice and a notice that there is | ||
| no warranty (or else, saying that you provide a warranty) and that | ||
| users may redistribute the program under these conditions, and telling | ||
| the user how to view a copy of this License. (Exception: if the | ||
| Program itself is interactive but does not normally print such an | ||
| announcement, your work based on the Program is not required to print | ||
| an announcement.) | ||
| These requirements apply to the modified work as a whole. If | ||
| identifiable sections of that work are not derived from the Program, | ||
| and can be reasonably considered independent and separate works in | ||
| themselves, then this License, and its terms, do not apply to those | ||
| sections when you distribute them as separate works. But when you | ||
| distribute the same sections as part of a whole which is a work based | ||
| on the Program, the distribution of the whole must be on the terms of | ||
| this License, whose permissions for other licensees extend to the | ||
| entire whole, and thus to each and every part regardless of who wrote | ||
| it. | ||
| Thus, it is not the intent of this section to claim rights or contest | ||
| your rights to work written entirely by you; rather, the intent is to | ||
| exercise the right to control the distribution of derivative or | ||
| collective works based on the Program. | ||
| In addition, mere aggregation of another work not based on the Program | ||
| with the Program (or with a work based on the Program) on a volume of | ||
| a storage or distribution medium does not bring the other work under | ||
| the scope of this License. | ||
| **3.** You may copy and distribute the Program (or a work based on it, | ||
| under Section 2) in object code or executable form under the terms of | ||
| Sections 1 and 2 above provided that you also do one of the following: | ||
| **a)** Accompany it with the complete corresponding machine-readable | ||
| source code, which must be distributed under the terms of Sections 1 | ||
| and 2 above on a medium customarily used for software interchange; or, | ||
| **b)** Accompany it with a written offer, valid for at least three | ||
| years, to give any third party, for a charge no more than your cost of | ||
| physically performing source distribution, a complete machine-readable | ||
| copy of the corresponding source code, to be distributed under the | ||
| terms of Sections 1 and 2 above on a medium customarily used for | ||
| software interchange; or, | ||
| **c)** Accompany it with the information you received as to the offer | ||
| to distribute corresponding source code. (This alternative is allowed | ||
| only for noncommercial distribution and only if you received the | ||
| program in object code or executable form with such an offer, in | ||
| accord with Subsection b above.) | ||
| The source code for a work means the preferred form of the work for | ||
| making modifications to it. For an executable work, complete source | ||
| code means all the source code for all modules it contains, plus any | ||
| associated interface definition files, plus the scripts used to | ||
| control compilation and installation of the executable. However, as a | ||
| special exception, the source code distributed need not include | ||
| anything that is normally distributed (in either source or binary | ||
| form) with the major components (compiler, kernel, and so on) of the | ||
| operating system on which the executable runs, unless that component | ||
| itself accompanies the executable. | ||
| If distribution of executable or object code is made by offering | ||
| access to copy from a designated place, then offering equivalent | ||
| access to copy the source code from the same place counts as | ||
| distribution of the source code, even though third parties are not | ||
| compelled to copy the source along with the object code. | ||
| **4.** You may not copy, modify, sublicense, or distribute the Program | ||
| except as expressly provided under this License. Any attempt otherwise | ||
| to copy, modify, sublicense or distribute the Program is void, and | ||
| will automatically terminate your rights under this License. However, | ||
| parties who have received copies, or rights, from you under this | ||
| License will not have their licenses terminated so long as such | ||
| parties remain in full compliance. | ||
| **5.** You are not required to accept this License, since you have not | ||
| signed it. However, nothing else grants you permission to modify or | ||
| distribute the Program or its derivative works. These actions are | ||
| prohibited by law if you do not accept this License. Therefore, by | ||
| modifying or distributing the Program (or any work based on the | ||
| Program), you indicate your acceptance of this License to do so, and | ||
| all its terms and conditions for copying, distributing or modifying | ||
| the Program or works based on it. | ||
| **6.** Each time you redistribute the Program (or any work based on | ||
| the Program), the recipient automatically receives a license from the | ||
| original licensor to copy, distribute or modify the Program subject to | ||
| these terms and conditions. You may not impose any further | ||
| restrictions on the recipients' exercise of the rights granted herein. | ||
| You are not responsible for enforcing compliance by third parties to | ||
| this License. | ||
| **7.** If, as a consequence of a court judgment or allegation of | ||
| patent infringement or for any other reason (not limited to patent | ||
| issues), conditions are imposed on you (whether by court order, | ||
| agreement or otherwise) that contradict the conditions of this | ||
| License, they do not excuse you from the conditions of this License. | ||
| If you cannot distribute so as to satisfy simultaneously your | ||
| obligations under this License and any other pertinent obligations, | ||
| then as a consequence you may not distribute the Program at all. For | ||
| example, if a patent license would not permit royalty-free | ||
| redistribution of the Program by all those who receive copies directly | ||
| or indirectly through you, then the only way you could satisfy both it | ||
| and this License would be to refrain entirely from distribution of the | ||
| Program. | ||
| If any portion of this section is held invalid or unenforceable under | ||
| any particular circumstance, the balance of the section is intended to | ||
| apply and the section as a whole is intended to apply in other | ||
| circumstances. | ||
| It is not the purpose of this section to induce you to infringe any | ||
| patents or other property right claims or to contest validity of any | ||
| such claims; this section has the sole purpose of protecting the | ||
| integrity of the free software distribution system, which is | ||
| implemented by public license practices. Many people have made | ||
| generous contributions to the wide range of software distributed | ||
| through that system in reliance on consistent application of that | ||
| system; it is up to the author/donor to decide if he or she is willing | ||
| to distribute software through any other system and a licensee cannot | ||
| impose that choice. | ||
| This section is intended to make thoroughly clear what is believed to | ||
| be a consequence of the rest of this License. | ||
| **8.** If the distribution and/or use of the Program is restricted in | ||
| certain countries either by patents or by copyrighted interfaces, the | ||
| original copyright holder who places the Program under this License | ||
| may add an explicit geographical distribution limitation excluding | ||
| those countries, so that distribution is permitted only in or among | ||
| countries not thus excluded. In such case, this License incorporates | ||
| the limitation as if written in the body of this License. | ||
| **9.** The Free Software Foundation may publish revised and/or new | ||
| versions of the General Public License from time to time. Such new | ||
| versions will be similar in spirit to the present version, but may | ||
| differ in detail to address new problems or concerns. | ||
| Each version is given a distinguishing version number. If the Program | ||
| specifies a version number of this License which applies to it and | ||
| "any later version", you have the option of following the terms and | ||
| conditions either of that version or of any later version published by | ||
| the Free Software Foundation. If the Program does not specify a | ||
| version number of this License, you may choose any version ever | ||
| published by the Free Software Foundation. | ||
| **10.** If you wish to incorporate parts of the Program into other | ||
| free programs whose distribution conditions are different, write to | ||
| the author to ask for permission. For software which is copyrighted by | ||
| the Free Software Foundation, write to the Free Software Foundation; | ||
| we sometimes make exceptions for this. Our decision will be guided by | ||
| the two goals of preserving the free status of all derivatives of our | ||
| free software and of promoting the sharing and reuse of software | ||
| generally. | ||
| **NO WARRANTY** | ||
| **11.** BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO | ||
| WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. | ||
| EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR | ||
| OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY | ||
| KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE | ||
| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
| PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE | ||
| PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME | ||
| THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. | ||
| **12.** IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN | ||
| WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY | ||
| AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU | ||
| FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR | ||
| CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE | ||
| PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING | ||
| RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A | ||
| FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF | ||
| SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH | ||
| DAMAGES. | ||
| ### END OF TERMS AND CONDITIONS | ||
| ### How to Apply These Terms to Your New Programs | ||
| If you develop a new program, and you want it to be of the greatest | ||
| possible use to the public, the best way to achieve this is to make it | ||
| free software which everyone can redistribute and change under these | ||
| terms. | ||
| To do so, attach the following notices to the program. It is safest to | ||
| attach them to the start of each source file to most effectively | ||
| convey the exclusion of warranty; and each file should have at least | ||
| the "copyright" line and a pointer to where the full notice is found. | ||
| one line to give the program's name and an idea of what it does. | ||
| Copyright (C) yyyy name of author | ||
| This program is free software; you can redistribute it and/or | ||
| modify it under the terms of the GNU General Public License | ||
| as published by the Free Software Foundation; either version 2 | ||
| of the License, or (at your option) any later version. | ||
| This program is distributed in the hope that it will be useful, | ||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| GNU General Public License for more details. | ||
| You should have received a copy of the GNU General Public License | ||
| along with this program; if not, write to the Free Software | ||
| Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| Also add information on how to contact you by electronic and paper | ||
| mail. | ||
| If the program is interactive, make it output a short notice like this | ||
| when it starts in an interactive mode: | ||
| Gnomovision version 69, Copyright (C) year name of author | ||
| Gnomovision comes with ABSOLUTELY NO WARRANTY; for details | ||
| type `show w'. This is free software, and you are welcome | ||
| to redistribute it under certain conditions; type `show c' | ||
| for details. | ||
| The hypothetical commands \`show w' and \`show c' should show the | ||
| appropriate parts of the General Public License. Of course, the | ||
| commands you use may be called something other than \`show w' and | ||
| \`show c'; they could even be mouse-clicks or menu items--whatever | ||
| suits your program. | ||
| You should also get your employer (if you work as a programmer) or | ||
| your school, if any, to sign a "copyright disclaimer" for the program, | ||
| if necessary. Here is a sample; alter the names: | ||
| Yoyodyne, Inc., hereby disclaims all copyright | ||
| interest in the program `Gnomovision' | ||
| (which makes passes at compilers) written | ||
| by James Hacker. | ||
| signature of Ty Coon, 1 April 1989 | ||
| Ty Coon, President of Vice | ||
| This General Public License does not permit incorporating your program | ||
| into proprietary programs. If your program is a subroutine library, | ||
| you may consider it more useful to permit linking proprietary | ||
| applications with the library. If this is what you want to do, use the | ||
| [GNU Lesser General Public | ||
| License](https://www.gnu.org/licenses/lgpl.html) instead of this | ||
| License. |
+20
-35
| """Python module for interacting with ALE c++ interface and gymnasium wrapper.""" | ||
| import importlib.metadata as metadata | ||
| import os | ||
| import platform | ||
| import sys | ||
| import warnings | ||
@@ -26,33 +26,11 @@ | ||
| # Loading DLLs on Windows is kind of a disaster | ||
| # The best approach seems to be using LoadLibraryEx | ||
| # with user defined search paths. This kind of acts like | ||
| # $ORIGIN or @loader_path on Unix / macOS. | ||
| # The best approach seems to be using LoadLibraryEx with user defined search paths. | ||
| # This kind of acts like $ORIGIN or @loader_path on Unix / macOS. | ||
| # This way we guarantee we load OUR DLLs. | ||
| if sys.version_info.major == 3 and sys.version_info.minor >= 8: | ||
| os.add_dll_directory(packagedir) | ||
| else: | ||
| # TODO: Py38: Remove AddDllDirectory | ||
| kernel32 = ctypes.WinDLL("kernel32.dll", use_last_error=True) | ||
| if hasattr(kernel32, "AddDllDirectory"): | ||
| kernel32.AddDllDirectory(packagedir) | ||
| os.add_dll_directory(packagedir) | ||
| # TODO Py38: Once 3.7 is deprecated use importlib.metadata to parse | ||
| # version string from package. | ||
| try: | ||
| import importlib.metadata as metadata | ||
| except ImportError: | ||
| import importlib_metadata as metadata | ||
| try: | ||
| __version__ = metadata.version(__package__) | ||
| except metadata.PackageNotFoundError: | ||
| __version__ = "unknown" | ||
| __version__ = metadata.version(__package__) | ||
| # Import native shared library | ||
| from ale_py._ale_py import ( # noqa: E402 | ||
| SDL_SUPPORT, | ||
| Action, | ||
| ALEInterface, | ||
| ALEState, | ||
| LoggerMode, | ||
| ) | ||
| from ale_py._ale_py import SDL_SUPPORT, Action, ALEInterface, ALEState, LoggerMode | ||
@@ -63,11 +41,18 @@ __all__ = ["Action", "ALEInterface", "ALEState", "LoggerMode", "SDL_SUPPORT"] | ||
| try: | ||
| from ale_py.env import AtariEnv, AtariEnvStepMetadata | ||
| # As the vector interface is an optional cmake build, it's not assumed to exist | ||
| from ale_py._ale_py import ALEVectorInterface | ||
| __all__ += ["AtariEnv", "AtariEnvStepMetadata"] | ||
| __all__ += ["ALEVectorInterface"] | ||
| except ImportError: | ||
| pass | ||
| from ale_py.registration import register_v0_v4_envs, register_v5_envs | ||
| register_v0_v4_envs() | ||
| register_v5_envs() | ||
| except ImportError: | ||
| pass | ||
| from ale_py.env import AtariEnv, AtariEnvStepMetadata | ||
| from ale_py.vector_env import AtariVectorEnv | ||
| __all__ += ["AtariEnv", "AtariEnvStepMetadata", "AtariVectorEnv"] | ||
| from ale_py.registration import register_v0_v4_envs, register_v5_envs | ||
| register_v0_v4_envs() | ||
| register_v5_envs() |
+37
-2
@@ -0,3 +1,5 @@ | ||
| from __future__ import annotations | ||
| import os | ||
| from typing import List, Optional, overload | ||
| from typing import Any, Dict, List, Optional, Tuple, overload | ||
@@ -11,2 +13,3 @@ import numpy as np | ||
| "ALEInterface", | ||
| "ALEVectorInterface", | ||
| "ALEState", | ||
@@ -172,5 +175,37 @@ "LoggerMode", | ||
| def setString(self, key: str, value: str) -> None: ... | ||
| pass | ||
| class ALEVectorInterface: | ||
| def __init__( | ||
| self, | ||
| rom_path: os.PathLike, | ||
| num_envs: int, | ||
| frame_skip: int, | ||
| stack_num: int, | ||
| img_height: int, | ||
| img_width: int, | ||
| maxpool: bool, | ||
| noop_max: int, | ||
| use_fire_reset: bool, | ||
| episodic_life: bool, | ||
| life_loss_info: bool, | ||
| reward_clipping: bool, | ||
| max_episode_steps: int, | ||
| repeat_action_probability: float, | ||
| full_action_space: bool, | ||
| batch_size: int, | ||
| num_threads: int, | ||
| thread_affinity_offset: int, | ||
| ) -> None: ... | ||
| def reset( | ||
| self, reset_indices: np.ndarray, reset_seeds: np.ndarray | ||
| ) -> Tuple[np.ndarray, Dict[str, Any]]: ... | ||
| def send(self, action_idx: np.ndarray, paddle_strength: np.ndarray): ... | ||
| def recv( | ||
| self, | ||
| ) -> Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray, Dict[str, Any]]: ... | ||
| def get_action_set(self) -> List[Action]: ... | ||
| def get_num_envs(self) -> int: ... | ||
| def get_observation_shape(self) -> Tuple[int, int, int]: ... | ||
| SDL_SUPPORT: bool | ||
| __version__: str |
@@ -19,3 +19,2 @@ /* ***************************************************************************** | ||
| #include <sstream> | ||
| #include <optional> | ||
@@ -31,2 +30,7 @@ | ||
| #ifdef BUILD_VECTOR_LIB | ||
| #include "ale_vector_python_interface.hpp" | ||
| #endif | ||
| namespace py = pybind11; | ||
@@ -151,8 +155,6 @@ using namespace py::literals; | ||
| .def_static("isSupportedROM", &ale::ALEInterface::isSupportedROM) | ||
| .def("act", (ale::reward_t(ale::ALEPythonInterface::*)(uint32_t, float)) & | ||
| ale::ALEPythonInterface::act, | ||
| .def("act", &ale::ALEPythonInterface::act, | ||
| py::arg("action"), | ||
| py::arg("paddle_strength") = 1.0) | ||
| .def("act", (ale::reward_t(ale::ALEInterface::*)(ale::Action, float)) & | ||
| ale::ALEInterface::act, | ||
| .def("act", &ale::ALEInterface::act, | ||
| py::arg("action"), | ||
@@ -217,4 +219,9 @@ py::arg("paddle_strength") = 1.0) | ||
| .def_static("setLoggerMode", &ale::Logger::setMode); | ||
| // Initialize the vector module if it's enabled | ||
| #ifdef BUILD_VECTOR_LIB | ||
| init_vector_module(m); | ||
| #endif | ||
| } | ||
| #endif // __ALE_PYTHON_INTERFACE_HPP__ |
@@ -17,3 +17,10 @@ find_package(Python3 COMPONENTS Interpreter Development.Module REQUIRED) | ||
| add_library(ale-py MODULE ale_python_interface.cpp) | ||
| # If vector library is enabled, include the vector Python interface | ||
| if(BUILD_VECTOR_LIB) | ||
| add_library(ale-py MODULE ale_python_interface.cpp ale_vector_python_interface.cpp) | ||
| target_compile_definitions(ale-py PRIVATE BUILD_VECTOR_LIB) | ||
| else () | ||
| add_library(ale-py MODULE ale_python_interface.cpp) | ||
| endif() | ||
| # Depend on the ALE and pybind11 module | ||
@@ -20,0 +27,0 @@ target_link_libraries(ale-py PUBLIC ale ale-lib) |
+3
-2
@@ -400,6 +400,7 @@ """Gymnasium wrapper around the Arcade Learning Environment (ALE).""" | ||
| @staticmethod | ||
| @lru_cache(18) | ||
| def map_action_idx( | ||
| self, left_center_right: int, down_center_up: int, fire: bool | ||
| ) -> int: | ||
| left_center_right: int, down_center_up: int, fire: bool | ||
| ) -> ale_py.Action: | ||
| """Return an action idx given unit actions for underlying env.""" | ||
@@ -406,0 +407,0 @@ # no op and fire |
+49
-57
@@ -36,42 +36,2 @@ """Registration for Atari environments.""" | ||
| def _register_rom_configs( | ||
| roms: Sequence[str], | ||
| obs_types: Sequence[str], | ||
| configs: Sequence[EnvConfig], | ||
| prefix: str = "", | ||
| ): | ||
| if len(prefix) > 0 and prefix[-1] != "/": | ||
| prefix += "/" | ||
| for rom in roms: | ||
| for obs_type in obs_types: | ||
| for config in configs: | ||
| for flavour in config.flavours: | ||
| name = _rom_id_to_name(rom) | ||
| name = f"{name}-ram" if obs_type == "ram" else name | ||
| # Parse config kwargs | ||
| config_kwargs = ( | ||
| config.kwargs(rom) if callable(config.kwargs) else config.kwargs | ||
| ) | ||
| # Parse flavour kwargs | ||
| flavour_kwargs = ( | ||
| flavour.kwargs(rom) | ||
| if callable(flavour.kwargs) | ||
| else flavour.kwargs | ||
| ) | ||
| # Register the environment | ||
| gymnasium.register( | ||
| id=f"{prefix}{name}{flavour.suffix}-{config.version}", | ||
| entry_point="ale_py.env:AtariEnv", | ||
| kwargs=dict( | ||
| game=rom, | ||
| obs_type=obs_type, | ||
| **config_kwargs, | ||
| **flavour_kwargs, | ||
| ), | ||
| ) | ||
| def register_v0_v4_envs(): | ||
@@ -180,25 +140,57 @@ """Registers all v0 and v4 environments.""" | ||
| _register_rom_configs(legacy_games, obs_types, versions) | ||
| for rom in legacy_games: | ||
| for obs_type in obs_types: | ||
| for config in versions: | ||
| for flavour in config.flavours: | ||
| name = _rom_id_to_name(rom) | ||
| name = f"{name}-ram" if obs_type == "ram" else name | ||
| # Parse config kwargs | ||
| if callable(config.kwargs): | ||
| config_kwargs = config.kwargs(rom) | ||
| else: | ||
| config_kwargs = config.kwargs | ||
| # Parse flavour kwargs | ||
| if callable(flavour.kwargs): | ||
| flavour_kwargs = flavour.kwargs(rom) | ||
| else: | ||
| flavour_kwargs = flavour.kwargs | ||
| # Register the environment | ||
| gymnasium.register( | ||
| id=f"{name}{flavour.suffix}-{config.version}", | ||
| entry_point="ale_py.env:AtariEnv", | ||
| kwargs=dict( | ||
| game=rom, | ||
| obs_type=obs_type, | ||
| **config_kwargs, | ||
| **flavour_kwargs, | ||
| ), | ||
| ) | ||
| def register_v5_envs(): | ||
| """Register all v5 environments.""" | ||
| all_games = roms.get_all_rom_ids() | ||
| obs_types = ["rgb", "ram"] | ||
| # max_episode_steps is 108k frames which is 30 mins of gameplay. | ||
| # This corresponds to 108k / 4 = 27,000 steps | ||
| versions = [ | ||
| EnvConfig( | ||
| version="v5", | ||
| kwargs={ | ||
| "repeat_action_probability": 0.25, | ||
| "full_action_space": False, | ||
| "frameskip": 4, | ||
| "max_num_frames_per_episode": 108_000, | ||
| }, | ||
| flavours=[EnvFlavour("", {})], | ||
| for rom in all_games: | ||
| if rom in {"combat", "joust", "maze_craze", "warlords"}: | ||
| continue | ||
| name = _rom_id_to_name(rom) | ||
| # max_episode_steps is 108k frames which is 30 mins of gameplay. | ||
| # This corresponds to 108k / 4 = 27,000 steps | ||
| gymnasium.register( | ||
| id=f"ALE/{name}-v5", | ||
| entry_point="ale_py.env:AtariEnv", | ||
| vector_entry_point="ale_py.vector_env:AtariVectorEnv", | ||
| kwargs=dict( | ||
| game=rom, | ||
| repeat_action_probability=0.25, | ||
| full_action_space=False, | ||
| frameskip=4, | ||
| max_num_frames_per_episode=108_000, | ||
| ), | ||
| ) | ||
| ] | ||
| _register_rom_configs(all_games, obs_types, versions, prefix="ALE/") |
+6
-5
@@ -1,10 +0,10 @@ | ||
| Metadata-Version: 2.2 | ||
| Metadata-Version: 2.4 | ||
| Name: ale-py | ||
| Version: 0.10.2 | ||
| Version: 0.11.0 | ||
| Summary: The Arcade Learning Environment (ALE) - a platform for AI research. | ||
| Author: Marc G. Bellemare, Yavar Naddaf, Joel Veness, Michael Bowling | ||
| Maintainer-email: Farama Foundation <contact@farama.org>, Jesse Farebrother <jfarebro@cs.mcgill.ca> | ||
| License: GPLv2 | ||
| License-Expression: GPL-2.0-only | ||
| Project-URL: homepage, https://github.com/Farama-Foundation/Arcade-Learning-Environment | ||
| Project-URL: documentation, https://github.com/Farama-Foundation/Arcade-Learning-Environment/tree/master/docs | ||
| Project-URL: documentation, https://ale.farama.org | ||
| Project-URL: changelog, https://github.com/Farama-Foundation/Arcade-Learning-Environment/blob/master/CHANGELOG.md | ||
@@ -14,3 +14,2 @@ Keywords: reinforcement-learning,arcade-learning-environment,atari | ||
| Classifier: Intended Audience :: Science/Research | ||
| Classifier: License :: OSI Approved :: GNU General Public License v2 (GPLv2) | ||
| Classifier: Programming Language :: Python :: 3 | ||
@@ -34,2 +33,4 @@ Classifier: Programming Language :: Python :: 3.9 | ||
| Requires-Dist: gymnasium>=1.0.0; extra == "test" | ||
| Requires-Dist: opencv-python>=3.0; extra == "test" | ||
| Dynamic: license-file | ||
@@ -36,0 +37,0 @@ The Arcade Learning Environment |
+16
-13
@@ -1,16 +0,14 @@ | ||
| ale_py-0.10.2.dist-info/LICENSE.md,sha256=MVVce6oSrBFQvJpI-22FtV2c6hM2rjr6k9ZT9o_km7I,17879 | ||
| ale_py-0.10.2.dist-info/RECORD,, | ||
| ale_py-0.10.2.dist-info/WHEEL,sha256=HQquLNNRUomuzWueBNrqINFman-CGVesKQI-ZGwXyWQ,111 | ||
| ale_py-0.10.2.dist-info/top_level.txt,sha256=CjHTcYlCUfmSaCGbLLpKEKIY5hZteuawsHZy3TWVyNk,7 | ||
| ale_py-0.10.2.dist-info/METADATA,sha256=j-csKHreVCzaeuh_8irtWY_aoNvS82rKQ8jgkVlyJnA,8250 | ||
| ale_py/registration.py,sha256=J0MFENv_9VeG5-yly8azUEZNwUa0vOAQPLbeXET07l4,5806 | ||
| ale_py/ale_python_interface.hpp,sha256=AjDf0FfiDK1PlynWzKDPAesT7TWTEdm-5BFEr_ACvhw,9840 | ||
| ale_py/CMakeLists.txt,sha256=pNF-wcNWV3WHc2zRCJZz4f2yg_acaXkVqS1kpCbUgUY,2961 | ||
| ale_py/env.py,sha256=2hwDYyBDr_v_SfhOu45JbaynB0iPtGPsn1APxqMrHO4,19001 | ||
| ale_py/__init__.pyi,sha256=-9NyL8GXjJPNlqmGcoxMe4yE6Jx1fC2kKPv0b8vODcg,6959 | ||
| ale_py/_ale_py.cpython-310-darwin.so,sha256=FeCUsZu4Wr2c2qJxBpXSvOuQMAgbqWM8CavRhb9lY6o,2084016 | ||
| ale_py/__init__.py,sha256=46VRo5hRwmIRnvv-wY6CeTf7j3QMq7r-cJCpAizQAZA,2111 | ||
| ale_py/registration.py,sha256=rPYRnbcNlHmU-P_YeyLWsjUmGYrd7weMh-Di9wYU6RU,5699 | ||
| ale_py/ale_python_interface.hpp,sha256=N6QJrhVNCYDd_tvsFwterorv4KAwvv3qslj9dmlQYNc,9839 | ||
| ale_py/ale_vector_python_interface.hpp,sha256=Dhil_M9zT8QHLzzkJnc48EESPkAPg1J7rn1gWokod44,8446 | ||
| ale_py/CMakeLists.txt,sha256=WygrJIU5MUEUgZpOfG2MomlI7RtnKk6zvtL-MstGqPQ,3223 | ||
| ale_py/env.py,sha256=Z_logFOd_BzjK5h-0QZ0epwXZ7S_hso8VeLvQIkRudc,19023 | ||
| ale_py/__init__.pyi,sha256=lLoLLG3bdGV9oBYY01mZdsD66ZxUdByO_gFRuoujbgo,8092 | ||
| ale_py/vector_env.py,sha256=rlTLlp0iT86m_oYj72JyXa_IC8Af2dkZLv8D9KJlA84,7793 | ||
| ale_py/libSDL2-2.0.0.dylib,sha256=aebRM_pgqQ9CQ6T-EQ9WmdVuCPvGEnqKXKOE_5ixiZg,1701600 | ||
| ale_py/_ale_py.cpython-310-darwin.so,sha256=WEpTi0mi3UQBdeqOzZIu3IiNxW0gYDGWgQbjUz2JGRk,4226032 | ||
| ale_py/__init__.py,sha256=Mea4ro3Nae71zaV9x43nFEVL_y-4L2AgnMBixiHRdfM,1733 | ||
| ale_py/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 | ||
| ale_py/ale_python_interface.cpp,sha256=lb6y_ZP5lBAHOwrYYsTEtmnfv47QX_a3YcIa-KcDgwY,7494 | ||
| ale_py/libSDL2-2.0.dylib,sha256=QdVS6OyY4-jxd9FZBnYW7UV5Rcib6ppPOqUlLGgcLoM,1734168 | ||
| ale_py/ale_vector_python_interface.cpp,sha256=ObU5-82G133Qfwzb9dm6AcoyxZmWW8hmsMOV5bFQUWY,7306 | ||
| ale_py/roms/asterix.bin,sha256=thYdsFMNhEW17w6LcAUAUx6YCqEBhOUZY1XyenumCBk,8192 | ||
@@ -126,1 +124,6 @@ ale_py/roms/asteroids.bin,sha256=W6b5GFGyMxo3o_5qlQybRk_XZMsDWj0l1LQ4jpsmdo8,8192 | ||
| ale_py/roms/superman.bin,sha256=d9I_JpEhZmJyjrYwugk2OE6pSoHUEEdZLSf-4SIQsjM,4096 | ||
| ale_py-0.11.0.dist-info/RECORD,, | ||
| ale_py-0.11.0.dist-info/WHEEL,sha256=aLQNhEyIPdqpFq0FjR-ZWmft0NSZR99U8evwFcdNWHI,136 | ||
| ale_py-0.11.0.dist-info/top_level.txt,sha256=CjHTcYlCUfmSaCGbLLpKEKIY5hZteuawsHZy3TWVyNk,7 | ||
| ale_py-0.11.0.dist-info/METADATA,sha256=AC7rb954qOZmpilegWG5gRzBsT_IKZCvZSc-pY_eK4M,8205 | ||
| ale_py-0.11.0.dist-info/licenses/LICENSE.md,sha256=MVVce6oSrBFQvJpI-22FtV2c6hM2rjr6k9ZT9o_km7I,17879 |
+3
-2
| Wheel-Version: 1.0 | ||
| Generator: setuptools (75.8.0) | ||
| Generator: setuptools (79.0.1) | ||
| Root-Is-Purelib: false | ||
| Tag: cp310-cp310-macosx_10_15_x86_64 | ||
| Tag: cp310-cp310-macosx_13_0_arm64 | ||
| Generator: delocate 0.13.0 | ||
Sorry, the diff of this file is too big to display
-361
| ### GNU GENERAL PUBLIC LICENSE | ||
| Version 2, June 1991 | ||
| Copyright (C) 1989, 1991 Free Software Foundation, Inc. | ||
| 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA | ||
| Everyone is permitted to copy and distribute verbatim copies | ||
| of this license document, but changing it is not allowed. | ||
| ### Preamble | ||
| The licenses for most software are designed to take away your freedom | ||
| to share and change it. By contrast, the GNU General Public License is | ||
| intended to guarantee your freedom to share and change free | ||
| software--to make sure the software is free for all its users. This | ||
| General Public License applies to most of the Free Software | ||
| Foundation's software and to any other program whose authors commit to | ||
| using it. (Some other Free Software Foundation software is covered by | ||
| the GNU Lesser General Public License instead.) You can apply it to | ||
| your programs, too. | ||
| When we speak of free software, we are referring to freedom, not | ||
| price. Our General Public Licenses are designed to make sure that you | ||
| have the freedom to distribute copies of free software (and charge for | ||
| this service if you wish), that you receive source code or can get it | ||
| if you want it, that you can change the software or use pieces of it | ||
| in new free programs; and that you know you can do these things. | ||
| To protect your rights, we need to make restrictions that forbid | ||
| anyone to deny you these rights or to ask you to surrender the rights. | ||
| These restrictions translate to certain responsibilities for you if | ||
| you distribute copies of the software, or if you modify it. | ||
| For example, if you distribute copies of such a program, whether | ||
| gratis or for a fee, you must give the recipients all the rights that | ||
| you have. You must make sure that they, too, receive or can get the | ||
| source code. And you must show them these terms so they know their | ||
| rights. | ||
| We protect your rights with two steps: (1) copyright the software, and | ||
| (2) offer you this license which gives you legal permission to copy, | ||
| distribute and/or modify the software. | ||
| Also, for each author's protection and ours, we want to make certain | ||
| that everyone understands that there is no warranty for this free | ||
| software. If the software is modified by someone else and passed on, | ||
| we want its recipients to know that what they have is not the | ||
| original, so that any problems introduced by others will not reflect | ||
| on the original authors' reputations. | ||
| Finally, any free program is threatened constantly by software | ||
| patents. We wish to avoid the danger that redistributors of a free | ||
| program will individually obtain patent licenses, in effect making the | ||
| program proprietary. To prevent this, we have made it clear that any | ||
| patent must be licensed for everyone's free use or not licensed at | ||
| all. | ||
| The precise terms and conditions for copying, distribution and | ||
| modification follow. | ||
| ### TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION | ||
| **0.** This License applies to any program or other work which | ||
| contains a notice placed by the copyright holder saying it may be | ||
| distributed under the terms of this General Public License. The | ||
| "Program", below, refers to any such program or work, and a "work | ||
| based on the Program" means either the Program or any derivative work | ||
| under copyright law: that is to say, a work containing the Program or | ||
| a portion of it, either verbatim or with modifications and/or | ||
| translated into another language. (Hereinafter, translation is | ||
| included without limitation in the term "modification".) Each licensee | ||
| is addressed as "you". | ||
| Activities other than copying, distribution and modification are not | ||
| covered by this License; they are outside its scope. The act of | ||
| running the Program is not restricted, and the output from the Program | ||
| is covered only if its contents constitute a work based on the Program | ||
| (independent of having been made by running the Program). Whether that | ||
| is true depends on what the Program does. | ||
| **1.** You may copy and distribute verbatim copies of the Program's | ||
| source code as you receive it, in any medium, provided that you | ||
| conspicuously and appropriately publish on each copy an appropriate | ||
| copyright notice and disclaimer of warranty; keep intact all the | ||
| notices that refer to this License and to the absence of any warranty; | ||
| and give any other recipients of the Program a copy of this License | ||
| along with the Program. | ||
| You may charge a fee for the physical act of transferring a copy, and | ||
| you may at your option offer warranty protection in exchange for a | ||
| fee. | ||
| **2.** You may modify your copy or copies of the Program or any | ||
| portion of it, thus forming a work based on the Program, and copy and | ||
| distribute such modifications or work under the terms of Section 1 | ||
| above, provided that you also meet all of these conditions: | ||
| **a)** You must cause the modified files to carry prominent notices | ||
| stating that you changed the files and the date of any change. | ||
| **b)** You must cause any work that you distribute or publish, that in | ||
| whole or in part contains or is derived from the Program or any part | ||
| thereof, to be licensed as a whole at no charge to all third parties | ||
| under the terms of this License. | ||
| **c)** If the modified program normally reads commands interactively | ||
| when run, you must cause it, when started running for such interactive | ||
| use in the most ordinary way, to print or display an announcement | ||
| including an appropriate copyright notice and a notice that there is | ||
| no warranty (or else, saying that you provide a warranty) and that | ||
| users may redistribute the program under these conditions, and telling | ||
| the user how to view a copy of this License. (Exception: if the | ||
| Program itself is interactive but does not normally print such an | ||
| announcement, your work based on the Program is not required to print | ||
| an announcement.) | ||
| These requirements apply to the modified work as a whole. If | ||
| identifiable sections of that work are not derived from the Program, | ||
| and can be reasonably considered independent and separate works in | ||
| themselves, then this License, and its terms, do not apply to those | ||
| sections when you distribute them as separate works. But when you | ||
| distribute the same sections as part of a whole which is a work based | ||
| on the Program, the distribution of the whole must be on the terms of | ||
| this License, whose permissions for other licensees extend to the | ||
| entire whole, and thus to each and every part regardless of who wrote | ||
| it. | ||
| Thus, it is not the intent of this section to claim rights or contest | ||
| your rights to work written entirely by you; rather, the intent is to | ||
| exercise the right to control the distribution of derivative or | ||
| collective works based on the Program. | ||
| In addition, mere aggregation of another work not based on the Program | ||
| with the Program (or with a work based on the Program) on a volume of | ||
| a storage or distribution medium does not bring the other work under | ||
| the scope of this License. | ||
| **3.** You may copy and distribute the Program (or a work based on it, | ||
| under Section 2) in object code or executable form under the terms of | ||
| Sections 1 and 2 above provided that you also do one of the following: | ||
| **a)** Accompany it with the complete corresponding machine-readable | ||
| source code, which must be distributed under the terms of Sections 1 | ||
| and 2 above on a medium customarily used for software interchange; or, | ||
| **b)** Accompany it with a written offer, valid for at least three | ||
| years, to give any third party, for a charge no more than your cost of | ||
| physically performing source distribution, a complete machine-readable | ||
| copy of the corresponding source code, to be distributed under the | ||
| terms of Sections 1 and 2 above on a medium customarily used for | ||
| software interchange; or, | ||
| **c)** Accompany it with the information you received as to the offer | ||
| to distribute corresponding source code. (This alternative is allowed | ||
| only for noncommercial distribution and only if you received the | ||
| program in object code or executable form with such an offer, in | ||
| accord with Subsection b above.) | ||
| The source code for a work means the preferred form of the work for | ||
| making modifications to it. For an executable work, complete source | ||
| code means all the source code for all modules it contains, plus any | ||
| associated interface definition files, plus the scripts used to | ||
| control compilation and installation of the executable. However, as a | ||
| special exception, the source code distributed need not include | ||
| anything that is normally distributed (in either source or binary | ||
| form) with the major components (compiler, kernel, and so on) of the | ||
| operating system on which the executable runs, unless that component | ||
| itself accompanies the executable. | ||
| If distribution of executable or object code is made by offering | ||
| access to copy from a designated place, then offering equivalent | ||
| access to copy the source code from the same place counts as | ||
| distribution of the source code, even though third parties are not | ||
| compelled to copy the source along with the object code. | ||
| **4.** You may not copy, modify, sublicense, or distribute the Program | ||
| except as expressly provided under this License. Any attempt otherwise | ||
| to copy, modify, sublicense or distribute the Program is void, and | ||
| will automatically terminate your rights under this License. However, | ||
| parties who have received copies, or rights, from you under this | ||
| License will not have their licenses terminated so long as such | ||
| parties remain in full compliance. | ||
| **5.** You are not required to accept this License, since you have not | ||
| signed it. However, nothing else grants you permission to modify or | ||
| distribute the Program or its derivative works. These actions are | ||
| prohibited by law if you do not accept this License. Therefore, by | ||
| modifying or distributing the Program (or any work based on the | ||
| Program), you indicate your acceptance of this License to do so, and | ||
| all its terms and conditions for copying, distributing or modifying | ||
| the Program or works based on it. | ||
| **6.** Each time you redistribute the Program (or any work based on | ||
| the Program), the recipient automatically receives a license from the | ||
| original licensor to copy, distribute or modify the Program subject to | ||
| these terms and conditions. You may not impose any further | ||
| restrictions on the recipients' exercise of the rights granted herein. | ||
| You are not responsible for enforcing compliance by third parties to | ||
| this License. | ||
| **7.** If, as a consequence of a court judgment or allegation of | ||
| patent infringement or for any other reason (not limited to patent | ||
| issues), conditions are imposed on you (whether by court order, | ||
| agreement or otherwise) that contradict the conditions of this | ||
| License, they do not excuse you from the conditions of this License. | ||
| If you cannot distribute so as to satisfy simultaneously your | ||
| obligations under this License and any other pertinent obligations, | ||
| then as a consequence you may not distribute the Program at all. For | ||
| example, if a patent license would not permit royalty-free | ||
| redistribution of the Program by all those who receive copies directly | ||
| or indirectly through you, then the only way you could satisfy both it | ||
| and this License would be to refrain entirely from distribution of the | ||
| Program. | ||
| If any portion of this section is held invalid or unenforceable under | ||
| any particular circumstance, the balance of the section is intended to | ||
| apply and the section as a whole is intended to apply in other | ||
| circumstances. | ||
| It is not the purpose of this section to induce you to infringe any | ||
| patents or other property right claims or to contest validity of any | ||
| such claims; this section has the sole purpose of protecting the | ||
| integrity of the free software distribution system, which is | ||
| implemented by public license practices. Many people have made | ||
| generous contributions to the wide range of software distributed | ||
| through that system in reliance on consistent application of that | ||
| system; it is up to the author/donor to decide if he or she is willing | ||
| to distribute software through any other system and a licensee cannot | ||
| impose that choice. | ||
| This section is intended to make thoroughly clear what is believed to | ||
| be a consequence of the rest of this License. | ||
| **8.** If the distribution and/or use of the Program is restricted in | ||
| certain countries either by patents or by copyrighted interfaces, the | ||
| original copyright holder who places the Program under this License | ||
| may add an explicit geographical distribution limitation excluding | ||
| those countries, so that distribution is permitted only in or among | ||
| countries not thus excluded. In such case, this License incorporates | ||
| the limitation as if written in the body of this License. | ||
| **9.** The Free Software Foundation may publish revised and/or new | ||
| versions of the General Public License from time to time. Such new | ||
| versions will be similar in spirit to the present version, but may | ||
| differ in detail to address new problems or concerns. | ||
| Each version is given a distinguishing version number. If the Program | ||
| specifies a version number of this License which applies to it and | ||
| "any later version", you have the option of following the terms and | ||
| conditions either of that version or of any later version published by | ||
| the Free Software Foundation. If the Program does not specify a | ||
| version number of this License, you may choose any version ever | ||
| published by the Free Software Foundation. | ||
| **10.** If you wish to incorporate parts of the Program into other | ||
| free programs whose distribution conditions are different, write to | ||
| the author to ask for permission. For software which is copyrighted by | ||
| the Free Software Foundation, write to the Free Software Foundation; | ||
| we sometimes make exceptions for this. Our decision will be guided by | ||
| the two goals of preserving the free status of all derivatives of our | ||
| free software and of promoting the sharing and reuse of software | ||
| generally. | ||
| **NO WARRANTY** | ||
| **11.** BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO | ||
| WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. | ||
| EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR | ||
| OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY | ||
| KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE | ||
| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | ||
| PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE | ||
| PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME | ||
| THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. | ||
| **12.** IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN | ||
| WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY | ||
| AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU | ||
| FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR | ||
| CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE | ||
| PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING | ||
| RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A | ||
| FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF | ||
| SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH | ||
| DAMAGES. | ||
| ### END OF TERMS AND CONDITIONS | ||
| ### How to Apply These Terms to Your New Programs | ||
| If you develop a new program, and you want it to be of the greatest | ||
| possible use to the public, the best way to achieve this is to make it | ||
| free software which everyone can redistribute and change under these | ||
| terms. | ||
| To do so, attach the following notices to the program. It is safest to | ||
| attach them to the start of each source file to most effectively | ||
| convey the exclusion of warranty; and each file should have at least | ||
| the "copyright" line and a pointer to where the full notice is found. | ||
| one line to give the program's name and an idea of what it does. | ||
| Copyright (C) yyyy name of author | ||
| This program is free software; you can redistribute it and/or | ||
| modify it under the terms of the GNU General Public License | ||
| as published by the Free Software Foundation; either version 2 | ||
| of the License, or (at your option) any later version. | ||
| This program is distributed in the hope that it will be useful, | ||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| GNU General Public License for more details. | ||
| You should have received a copy of the GNU General Public License | ||
| along with this program; if not, write to the Free Software | ||
| Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
| Also add information on how to contact you by electronic and paper | ||
| mail. | ||
| If the program is interactive, make it output a short notice like this | ||
| when it starts in an interactive mode: | ||
| Gnomovision version 69, Copyright (C) year name of author | ||
| Gnomovision comes with ABSOLUTELY NO WARRANTY; for details | ||
| type `show w'. This is free software, and you are welcome | ||
| to redistribute it under certain conditions; type `show c' | ||
| for details. | ||
| The hypothetical commands \`show w' and \`show c' should show the | ||
| appropriate parts of the General Public License. Of course, the | ||
| commands you use may be called something other than \`show w' and | ||
| \`show c'; they could even be mouse-clicks or menu items--whatever | ||
| suits your program. | ||
| You should also get your employer (if you work as a programmer) or | ||
| your school, if any, to sign a "copyright disclaimer" for the program, | ||
| if necessary. Here is a sample; alter the names: | ||
| Yoyodyne, Inc., hereby disclaims all copyright | ||
| interest in the program `Gnomovision' | ||
| (which makes passes at compilers) written | ||
| by James Hacker. | ||
| signature of Ty Coon, 1 April 1989 | ||
| Ty Coon, President of Vice | ||
| This General Public License does not permit incorporating your program | ||
| into proprietary programs. If your program is a subroutine library, | ||
| you may consider it more useful to permit linking proprietary | ||
| applications with the library. If this is what you want to do, use the | ||
| [GNU Lesser General Public | ||
| License](https://www.gnu.org/licenses/lgpl.html) instead of this | ||
| License. |
Sorry, the diff of this file is too big to display
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.