# Gymnasium Search Race
[![Build Python Package](https://github.com/Quentin18/gymnasium-search-race/actions/workflows/build.yml/badge.svg)](https://github.com/Quentin18/gymnasium-search-race/actions/workflows/build.yml)
[![Python](https://img.shields.io/pypi/pyversions/gymnasium-search-race.svg)](https://badge.fury.io/py/gymnasium-search-race)
[![PyPI](https://badge.fury.io/py/gymnasium-search-race.svg)](https://badge.fury.io/py/gymnasium-search-race)
[![PyPI Downloads](https://static.pepy.tech/badge/gymnasium-search-race)](https://pepy.tech/projects/gymnasium-search-race)
[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://pre-commit.com/)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![Imports: isort](https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat&labelColor=ef8336)](https://pycqa.github.io/isort/)
Gymnasium environments for
the [Search Race CodinGame optimization puzzle](https://www.codingame.com/multiplayer/optimization/search-race)
and [Mad Pod Racing CodinGame bot programming game](https://www.codingame.com/multiplayer/bot-programming/mad-pod-racing).
https://github.com/user-attachments/assets/766b4c79-1be7-48bd-a25b-2ff99de972f7
<table>
<tbody>
<tr>
<td>Action Space</td>
<td><code>Box([-1, 0], [1, 1], float64)</code></td>
</tr>
<tr>
<td>Observation Space</td>
<td><code>Box(-1, 1, shape=(8,), float64)</code></td>
</tr>
<tr>
<td>import</td>
<td><code>gymnasium.make("gymnasium_search_race:gymnasium_search_race/SearchRace-v2")</code></td>
</tr>
</tbody>
</table>
## Installation
To install `gymnasium-search-race` with pip, execute:
```bash
pip install gymnasium_search_race
```
From source:
```bash
git clone https://github.com/Quentin18/gymnasium-search-race
cd gymnasium-search-race/
pip install -e .
```
## Environment
### Action Space
The action is a `ndarray` with 2 continuous variables:
- The rotation angle between -18 and 18 degrees, normalized between -1 and 1.
- The thrust between 0 and 200, normalized between 0 and 1.
### Observation Space
The observation is a `ndarray` of 8 continuous variables:
- The x and y coordinates and the angle of the next 2 checkpoints relative to the car.
- The horizontal speed vx and vertical speed vy of the car.
The values are normalized between -1 and 1.
### Reward
- +1 when a checkpoint is visited.
- 0 otherwise.
### Starting State
The starting state is generated by choosing a random CodinGame test case.
### Episode End
The episode ends if either of the following happens:
1. Termination: The car visit all checkpoints before the time is out.
2. Truncation: Episode length is greater than 600.
### Arguments
- `laps`: number of laps. The default value is `3`.
- `car_max_thrust`: maximum thrust. The default value is `200`.
- `test_id`: test case id to generate the checkpoints (see
choices [here](https://github.com/Quentin18/gymnasium-search-race/tree/main/src/gymnasium_search_race/envs/maps)). The
default value is `None` which selects a test case randomly when the `reset` method is called.
```python
import gymnasium as gym
gym.make(
"gymnasium_search_race:gymnasium_search_race/SearchRace-v2",
laps=3,
car_max_thrust=200,
test_id=1,
)
```
### Version History
- v2: Update observation with relative positions and angles
- v1: Add boolean to indicate if the next checkpoint is the last checkpoint in observation
- v0: Initial version
## Discrete environment
The `SearchRaceDiscrete` environment is similar to the `SearchRace` environment except the action space is discrete.
```python
import gymnasium as gym
gym.make(
"gymnasium_search_race:gymnasium_search_race/SearchRaceDiscrete-v2",
laps=3,
car_max_thrust=200,
test_id=1,
)
```
### Action Space
There are 74 discrete actions corresponding to the combinations of angles from -18 to 18 degrees and thrust 0 and 200.
### Version History
- v2: Update observation with relative positions and angles
- v1: Add all angles in action space
- v0: Initial version
## Mad Pod Racing
### Runner
The `MadPodRacing` and `MadPodRacingDiscrete` environments can be used to train a runner for
the [Mad Pod Racing CodinGame bot programming game](https://www.codingame.com/multiplayer/bot-programming/mad-pod-racing).
They are similar to the `SearchRace` and `SearchRaceDiscrete` environments except the following differences:
- The maps are generated the same way Codingame generates them.
- The car position is rounded and not truncated.
```python
import gymnasium as gym
gym.make("gymnasium_search_race:gymnasium_search_race/MadPodRacing-v1")
gym.make("gymnasium_search_race:gymnasium_search_race/MadPodRacingDiscrete-v1")
```
https://github.com/user-attachments/assets/2e2a748d-5bd8-459a-8ac2-a8420bae33b9
### Blocker
The `MadPodRacingBlocker` and `MadPodRacingBlockerDiscrete` environments can be used to train a blocker for
the [Mad Pod Racing CodinGame bot programming game](https://www.codingame.com/multiplayer/bot-programming/mad-pod-racing).
```python
import gymnasium as gym
gym.make("gymnasium_search_race:gymnasium_search_race/MadPodRacingBlocker-v1")
gym.make("gymnasium_search_race:gymnasium_search_race/MadPodRacingBlockerDiscrete-v1")
```
https://github.com/user-attachments/assets/3c71a487-9ec1-49cd-9b8b-70f7984a809a
### Version History
- v1: Update observation with relative positions and angles and update maximum thrust
- v0: Initial version
## Usage
You can use [RL Baselines3 Zoo](https://github.com/DLR-RM/rl-baselines3-zoo) to train and evaluate agents:
```bash
pip install rl_zoo3
```
### Train an Agent
The hyperparameters are defined in `hyperparams/ppo.yml`.
To train a PPO agent for the Search Race game, execute:
```bash
python -m rl_zoo3.train \
--algo ppo \
--env gymnasium_search_race/SearchRaceDiscrete-v2 \
--tensorboard-log logs \
--eval-freq 20000 \
--eval-episodes 10 \
--gym-packages gymnasium_search_race \
--env-kwargs "laps:1000" \
--conf-file hyperparams/ppo.yml \
--progress
```
For the Mad Pod Racing game, you can add an opponent with the `opponent_path` argument:
```bash
python -m rl_zoo3.train \
--algo ppo \
--env gymnasium_search_race/MadPodRacingBlockerDiscrete-v1 \
--tensorboard-log logs \
--eval-freq 20000 \
--eval-episodes 10 \
--gym-packages gymnasium_search_race \
--env-kwargs "opponent_path:'rl-trained-agents/ppo/gymnasium_search_race-MadPodRacingDiscrete-v1_1/best_model.zip'" "laps:1000" \
--conf-file hyperparams/ppo.yml \
--progress
```
### Enjoy a Trained Agent
To see a trained agent in action on random test cases, execute:
```bash
python -m rl_zoo3.enjoy \
--algo ppo \
--env gymnasium_search_race/SearchRaceDiscrete-v2 \
--n-timesteps 1000 \
--deterministic \
--gym-packages gymnasium_search_race \
--load-best \
--progress
```
### Run Test Cases
To run test cases with a trained agent, execute:
```bash
python -m scripts.run_test_cases \
--path rl-trained-agents/ppo/gymnasium_search_race-SearchRaceDiscrete-v2_1/best_model.zip \
--env gymnasium_search_race:gymnasium_search_race/SearchRaceDiscrete-v2 \
--record-video \
--record-metrics
```
### Record a Video of a Trained Agent
To record a video of a trained agent on Mad Pod Racing, execute:
```bash
python -m scripts.record_video \
--path rl-trained-agents/ppo/gymnasium_search_race-MadPodRacingDiscrete-v1_1/best_model.zip \
--env gymnasium_search_race:gymnasium_search_race/MadPodRacingDiscrete-v1
```
For Mad Pod Racing Blocker, execute:
```bash
python -m scripts.record_video \
--path rl-trained-agents/ppo/gymnasium_search_race-MadPodRacingBlockerDiscrete-v1_1/best_model.zip \
--opponent-path rl-trained-agents/ppo/gymnasium_search_race-MadPodRacingDiscrete-v1_1/best_model.zip \
--env gymnasium_search_race:gymnasium_search_race/MadPodRacingBlockerDiscrete-v1
```
## Tests
To run tests, execute:
```bash
pytest
```
## Citing
To cite the repository in publications:
```bibtex
@misc{gymnasium-search-race,
author = {Quentin Deschamps},
title = {Gymnasium Search Race},
year = {2024},
publisher = {GitHub},
journal = {GitHub repository},
howpublished = {\url{https://github.com/Quentin18/gymnasium-search-race}},
}
```
## References
- [Gymnasium](https://github.com/Farama-Foundation/Gymnasium)
- [RL Baselines3 Zoo](https://github.com/DLR-RM/rl-baselines3-zoo)
- [Stable Baselines3](https://github.com/DLR-RM/stable-baselines3)
- [CGSearchRace](https://github.com/Illedan/CGSearchRace)
- [CSB-Runner-Arena](https://github.com/Agade09/CSB-Runner-Arena)
- [Coders Strikes Back by Magus](http://files.magusgeek.com/csb/csb_en.html)
### Assets
- https://www.flaticon.com/free-icon/space-ship_751036
- https://www.flaticon.com/free-icon/space-ship_784925
## Author
[Quentin Deschamps](mailto:quentindeschamps18@gmail.com)
Raw data
{
"_id": null,
"home_page": null,
"name": "gymnasium-search-race",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.10",
"maintainer_email": null,
"keywords": "Reinforcement Learning, game, RL, AI, gymnasium, pygame",
"author": null,
"author_email": "Quentin Deschamps <quentindeschamps18@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/12/87/34504f5c0f3e546e5bb00c7a4e5b3196b5782723fb2da9e4d7a6c43b56dc/gymnasium_search_race-4.0.0.tar.gz",
"platform": null,
"description": "# Gymnasium Search Race\n\n[![Build Python Package](https://github.com/Quentin18/gymnasium-search-race/actions/workflows/build.yml/badge.svg)](https://github.com/Quentin18/gymnasium-search-race/actions/workflows/build.yml)\n[![Python](https://img.shields.io/pypi/pyversions/gymnasium-search-race.svg)](https://badge.fury.io/py/gymnasium-search-race)\n[![PyPI](https://badge.fury.io/py/gymnasium-search-race.svg)](https://badge.fury.io/py/gymnasium-search-race)\n[![PyPI Downloads](https://static.pepy.tech/badge/gymnasium-search-race)](https://pepy.tech/projects/gymnasium-search-race)\n[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://pre-commit.com/)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)\n[![Imports: isort](https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat&labelColor=ef8336)](https://pycqa.github.io/isort/)\n\nGymnasium environments for\nthe [Search Race CodinGame optimization puzzle](https://www.codingame.com/multiplayer/optimization/search-race)\nand [Mad Pod Racing CodinGame bot programming game](https://www.codingame.com/multiplayer/bot-programming/mad-pod-racing).\n\nhttps://github.com/user-attachments/assets/766b4c79-1be7-48bd-a25b-2ff99de972f7\n\n<table>\n <tbody>\n <tr>\n <td>Action Space</td>\n <td><code>Box([-1, 0], [1, 1], float64)</code></td>\n </tr>\n <tr>\n <td>Observation Space</td>\n <td><code>Box(-1, 1, shape=(8,), float64)</code></td>\n </tr>\n <tr>\n <td>import</td>\n <td><code>gymnasium.make(\"gymnasium_search_race:gymnasium_search_race/SearchRace-v2\")</code></td>\n </tr>\n </tbody>\n</table>\n\n## Installation\n\nTo install `gymnasium-search-race` with pip, execute:\n\n```bash\npip install gymnasium_search_race\n```\n\nFrom source:\n\n```bash\ngit clone https://github.com/Quentin18/gymnasium-search-race\ncd gymnasium-search-race/\npip install -e .\n```\n\n## Environment\n\n### Action Space\n\nThe action is a `ndarray` with 2 continuous variables:\n\n- The rotation angle between -18 and 18 degrees, normalized between -1 and 1.\n- The thrust between 0 and 200, normalized between 0 and 1.\n\n### Observation Space\n\nThe observation is a `ndarray` of 8 continuous variables:\n\n- The x and y coordinates and the angle of the next 2 checkpoints relative to the car.\n- The horizontal speed vx and vertical speed vy of the car.\n\nThe values are normalized between -1 and 1.\n\n### Reward\n\n- +1 when a checkpoint is visited.\n- 0 otherwise.\n\n### Starting State\n\nThe starting state is generated by choosing a random CodinGame test case.\n\n### Episode End\n\nThe episode ends if either of the following happens:\n\n1. Termination: The car visit all checkpoints before the time is out.\n2. Truncation: Episode length is greater than 600.\n\n### Arguments\n\n- `laps`: number of laps. The default value is `3`.\n- `car_max_thrust`: maximum thrust. The default value is `200`.\n- `test_id`: test case id to generate the checkpoints (see\n choices [here](https://github.com/Quentin18/gymnasium-search-race/tree/main/src/gymnasium_search_race/envs/maps)). The\n default value is `None` which selects a test case randomly when the `reset` method is called.\n\n```python\nimport gymnasium as gym\n\ngym.make(\n \"gymnasium_search_race:gymnasium_search_race/SearchRace-v2\",\n laps=3,\n car_max_thrust=200,\n test_id=1,\n)\n```\n\n### Version History\n\n- v2: Update observation with relative positions and angles\n- v1: Add boolean to indicate if the next checkpoint is the last checkpoint in observation\n- v0: Initial version\n\n## Discrete environment\n\nThe `SearchRaceDiscrete` environment is similar to the `SearchRace` environment except the action space is discrete.\n\n```python\nimport gymnasium as gym\n\ngym.make(\n \"gymnasium_search_race:gymnasium_search_race/SearchRaceDiscrete-v2\",\n laps=3,\n car_max_thrust=200,\n test_id=1,\n)\n```\n\n### Action Space\n\nThere are 74 discrete actions corresponding to the combinations of angles from -18 to 18 degrees and thrust 0 and 200.\n\n### Version History\n\n- v2: Update observation with relative positions and angles\n- v1: Add all angles in action space\n- v0: Initial version\n\n## Mad Pod Racing\n\n### Runner\n\nThe `MadPodRacing` and `MadPodRacingDiscrete` environments can be used to train a runner for\nthe [Mad Pod Racing CodinGame bot programming game](https://www.codingame.com/multiplayer/bot-programming/mad-pod-racing).\nThey are similar to the `SearchRace` and `SearchRaceDiscrete` environments except the following differences:\n\n- The maps are generated the same way Codingame generates them.\n- The car position is rounded and not truncated.\n\n```python\nimport gymnasium as gym\n\ngym.make(\"gymnasium_search_race:gymnasium_search_race/MadPodRacing-v1\")\ngym.make(\"gymnasium_search_race:gymnasium_search_race/MadPodRacingDiscrete-v1\")\n```\n\nhttps://github.com/user-attachments/assets/2e2a748d-5bd8-459a-8ac2-a8420bae33b9\n\n### Blocker\n\nThe `MadPodRacingBlocker` and `MadPodRacingBlockerDiscrete` environments can be used to train a blocker for\nthe [Mad Pod Racing CodinGame bot programming game](https://www.codingame.com/multiplayer/bot-programming/mad-pod-racing).\n\n```python\nimport gymnasium as gym\n\ngym.make(\"gymnasium_search_race:gymnasium_search_race/MadPodRacingBlocker-v1\")\ngym.make(\"gymnasium_search_race:gymnasium_search_race/MadPodRacingBlockerDiscrete-v1\")\n```\n\nhttps://github.com/user-attachments/assets/3c71a487-9ec1-49cd-9b8b-70f7984a809a\n\n### Version History\n\n- v1: Update observation with relative positions and angles and update maximum thrust\n- v0: Initial version\n\n## Usage\n\nYou can use [RL Baselines3 Zoo](https://github.com/DLR-RM/rl-baselines3-zoo) to train and evaluate agents:\n\n```bash\npip install rl_zoo3\n```\n\n### Train an Agent\n\nThe hyperparameters are defined in `hyperparams/ppo.yml`.\n\nTo train a PPO agent for the Search Race game, execute:\n\n```bash\npython -m rl_zoo3.train \\\n --algo ppo \\\n --env gymnasium_search_race/SearchRaceDiscrete-v2 \\\n --tensorboard-log logs \\\n --eval-freq 20000 \\\n --eval-episodes 10 \\\n --gym-packages gymnasium_search_race \\\n --env-kwargs \"laps:1000\" \\\n --conf-file hyperparams/ppo.yml \\\n --progress\n```\n\nFor the Mad Pod Racing game, you can add an opponent with the `opponent_path` argument:\n\n```bash\npython -m rl_zoo3.train \\\n --algo ppo \\\n --env gymnasium_search_race/MadPodRacingBlockerDiscrete-v1 \\\n --tensorboard-log logs \\\n --eval-freq 20000 \\\n --eval-episodes 10 \\\n --gym-packages gymnasium_search_race \\\n --env-kwargs \"opponent_path:'rl-trained-agents/ppo/gymnasium_search_race-MadPodRacingDiscrete-v1_1/best_model.zip'\" \"laps:1000\" \\\n --conf-file hyperparams/ppo.yml \\\n --progress\n```\n\n### Enjoy a Trained Agent\n\nTo see a trained agent in action on random test cases, execute:\n\n```bash\npython -m rl_zoo3.enjoy \\\n --algo ppo \\\n --env gymnasium_search_race/SearchRaceDiscrete-v2 \\\n --n-timesteps 1000 \\\n --deterministic \\\n --gym-packages gymnasium_search_race \\\n --load-best \\\n --progress\n```\n\n### Run Test Cases\n\nTo run test cases with a trained agent, execute:\n\n```bash\npython -m scripts.run_test_cases \\\n --path rl-trained-agents/ppo/gymnasium_search_race-SearchRaceDiscrete-v2_1/best_model.zip \\\n --env gymnasium_search_race:gymnasium_search_race/SearchRaceDiscrete-v2 \\\n --record-video \\\n --record-metrics\n```\n\n### Record a Video of a Trained Agent\n\nTo record a video of a trained agent on Mad Pod Racing, execute:\n\n```bash\npython -m scripts.record_video \\\n --path rl-trained-agents/ppo/gymnasium_search_race-MadPodRacingDiscrete-v1_1/best_model.zip \\\n --env gymnasium_search_race:gymnasium_search_race/MadPodRacingDiscrete-v1\n```\n\nFor Mad Pod Racing Blocker, execute:\n\n```bash\npython -m scripts.record_video \\\n --path rl-trained-agents/ppo/gymnasium_search_race-MadPodRacingBlockerDiscrete-v1_1/best_model.zip \\\n --opponent-path rl-trained-agents/ppo/gymnasium_search_race-MadPodRacingDiscrete-v1_1/best_model.zip \\\n --env gymnasium_search_race:gymnasium_search_race/MadPodRacingBlockerDiscrete-v1\n```\n\n## Tests\n\nTo run tests, execute:\n\n```bash\npytest\n```\n\n## Citing\n\nTo cite the repository in publications:\n\n```bibtex\n@misc{gymnasium-search-race,\n author = {Quentin Deschamps},\n title = {Gymnasium Search Race},\n year = {2024},\n publisher = {GitHub},\n journal = {GitHub repository},\n howpublished = {\\url{https://github.com/Quentin18/gymnasium-search-race}},\n}\n```\n\n## References\n\n- [Gymnasium](https://github.com/Farama-Foundation/Gymnasium)\n- [RL Baselines3 Zoo](https://github.com/DLR-RM/rl-baselines3-zoo)\n- [Stable Baselines3](https://github.com/DLR-RM/stable-baselines3)\n- [CGSearchRace](https://github.com/Illedan/CGSearchRace)\n- [CSB-Runner-Arena](https://github.com/Agade09/CSB-Runner-Arena)\n- [Coders Strikes Back by Magus](http://files.magusgeek.com/csb/csb_en.html)\n\n### Assets\n\n- https://www.flaticon.com/free-icon/space-ship_751036\n- https://www.flaticon.com/free-icon/space-ship_784925\n\n## Author\n\n[Quentin Deschamps](mailto:quentindeschamps18@gmail.com)\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "A reinforcement learning environment for the Search Race CG puzzle based on Gymnasium",
"version": "4.0.0",
"project_urls": {
"Repository": "https://github.com/Quentin18/gymnasium-search-race"
},
"split_keywords": [
"reinforcement learning",
" game",
" rl",
" ai",
" gymnasium",
" pygame"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "ea90618a6e895dbacea1444aac7f695a08241349a0f8899d57b26b4a813add68",
"md5": "4521cc8f13380764e7f369b7a3d73c8d",
"sha256": "782cce06e391fb1ba39ecbae4bc61abc14845aae3f472aaa69c7fd0f1d52abde"
},
"downloads": -1,
"filename": "gymnasium_search_race-4.0.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "4521cc8f13380764e7f369b7a3d73c8d",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10",
"size": 422207,
"upload_time": "2025-01-24T22:34:05",
"upload_time_iso_8601": "2025-01-24T22:34:05.272174Z",
"url": "https://files.pythonhosted.org/packages/ea/90/618a6e895dbacea1444aac7f695a08241349a0f8899d57b26b4a813add68/gymnasium_search_race-4.0.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "128734504f5c0f3e546e5bb00c7a4e5b3196b5782723fb2da9e4d7a6c43b56dc",
"md5": "8d8880be2ddd629a6d5b7beef5bca851",
"sha256": "db3c6445d2eb97a3b440b0b276ede3a632e861540f91a6a6d4f7687cab1077d3"
},
"downloads": -1,
"filename": "gymnasium_search_race-4.0.0.tar.gz",
"has_sig": false,
"md5_digest": "8d8880be2ddd629a6d5b7beef5bca851",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10",
"size": 2773406,
"upload_time": "2025-01-24T22:34:07",
"upload_time_iso_8601": "2025-01-24T22:34:07.438824Z",
"url": "https://files.pythonhosted.org/packages/12/87/34504f5c0f3e546e5bb00c7a4e5b3196b5782723fb2da9e4d7a6c43b56dc/gymnasium_search_race-4.0.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-01-24 22:34:07",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "Quentin18",
"github_project": "gymnasium-search-race",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "gymnasium-search-race"
}