From 68845a6558874e946c1399695c9544d38a9b2965 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Goul=C3=A3o?= Date: Mon, 1 May 2023 11:08:19 +0100 Subject: [PATCH 1/9] start docs website --- .github/workflows/build-docs.yml | 41 +++ doc/Changelog.md | 286 ------------------ doc/Exceptions.md | 14 - doc/Gym.md | 12 - doc/index.md | 77 ----- docs/.gitignore | 21 ++ docs/404.md | 7 + docs/README.md | 5 + docs/_scripts/ipynb_to_gallery.py | 62 ++++ docs/_scripts/move_404.py | 14 + docs/_static/img/favicon.png | Bin 0 -> 696 bytes docs/_static/img/vizdoom-black.svg | 147 +++++++++ docs/_static/img/vizdoom-github.png | Bin 0 -> 3283401 bytes docs/_static/img/vizdoom-white.svg | 147 +++++++++ .../api/configuration.md | 1 + doc/DoomGame.md => docs/api/doomGame.md | 119 +------- docs/api/exceptions.md | 15 + doc/Types.md => docs/api/types.md | 61 ++-- doc/Utilities.md => docs/api/utils.md | 23 +- docs/citation/index.md | 30 ++ docs/conf.py | 90 ++++++ doc/FAQ.md => docs/faq/index.md | 0 docs/index.md | 65 ++++ .../introduction/installation.md | 22 +- .../introduction/quickstart.md | 3 +- .../introduction/wrappers.md | 18 +- docs/make.bat | 35 +++ docs/release_notes/index.md | 8 + docs/requirements.txt | 5 + 29 files changed, 754 insertions(+), 574 deletions(-) create mode 100644 .github/workflows/build-docs.yml delete mode 100644 doc/Changelog.md delete mode 100644 doc/Exceptions.md delete mode 100644 doc/Gym.md delete mode 100644 doc/index.md create mode 100644 docs/.gitignore create mode 100644 docs/404.md create mode 100644 docs/README.md create mode 100644 docs/_scripts/ipynb_to_gallery.py create mode 100644 docs/_scripts/move_404.py create mode 100644 docs/_static/img/favicon.png create mode 100644 docs/_static/img/vizdoom-black.svg create mode 100644 docs/_static/img/vizdoom-github.png create mode 100644 docs/_static/img/vizdoom-white.svg rename doc/ConfigFile.md => docs/api/configuration.md (99%) rename doc/DoomGame.md => docs/api/doomGame.md (91%) create mode 100644 docs/api/exceptions.md rename doc/Types.md => docs/api/types.md (89%) rename doc/Utilities.md => docs/api/utils.md (78%) create mode 100644 docs/citation/index.md create mode 100644 docs/conf.py rename doc/FAQ.md => docs/faq/index.md (100%) create mode 100644 docs/index.md rename doc/Installation.md => docs/introduction/installation.md (90%) rename doc/Quickstart.md => docs/introduction/quickstart.md (91%) rename doc/Gymnasium.md => docs/introduction/wrappers.md (53%) create mode 100644 docs/make.bat create mode 100644 docs/release_notes/index.md create mode 100644 docs/requirements.txt diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml new file mode 100644 index 000000000..31c536079 --- /dev/null +++ b/.github/workflows/build-docs.yml @@ -0,0 +1,41 @@ +name: Build and Deploy Docs +on: + push: + branches: [master] + +permissions: + contents: write + +jobs: + docs: + name: Generate Website + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: '3.9' + + - name: Install docs dependencies + run: pip install -r docs/requirements.txt + + - name: Install ViZDoom + run: pip install -e . + + - name: Build + run: sphinx-build -b dirhtml -v docs _build + + - name: Move 404 + run: mv _build/404/index.html _build/404.html + + - name: Update 404 links + run: python docs/scripts/move404.py _build/404.html + + - name: Remove .doctrees + run: rm -r _build/.doctrees + + - name: Upload to GitHub Pages + uses: JamesIves/github-pages-deploy-action@v4 + with: + folder: _build \ No newline at end of file diff --git a/doc/Changelog.md b/doc/Changelog.md deleted file mode 100644 index 80b360dea..000000000 --- a/doc/Changelog.md +++ /dev/null @@ -1,286 +0,0 @@ -# Changelog - -## Changes in 1.1.14 - -#### Support for Apple Silicon -- Fixed building on Apple Silicon Macbooks. - -#### Gym -- OpenAI Gym environment wrappers were updated to the Gym v0.26 API version. - ---- - -## Changes in 1.1.13 - -#### Releases -- The pybind11 library and freedoom2.wad are now part of the source release instead of being downloaded during building. - -#### Consts -- Added new consts: `DEFAULT_FPS` (= `DEFAULT_TICRATE`), `DEFAULT_FRAMETIME_S` (= `1.0 / DEFAULT_TICRATE`), `DEFAULT_FRAMETIME_MS` (= `DEFAULT_FRAMETIME_S * 1000`); - ---- - -## Changes in 1.1.12 - -#### New OpenAI Gym wrapper -- Added a new wrapper for OpenAI Gym. - ---- - -## Changes in 1.1.11 - -#### Python -- Fixed issues with installing/building Python package. - ---- - -## Changes in 1.1.10 - -#### Python Bindings -- Fixed support for Python 3.10 -- Removed dependency on Numpy and simplified the process of building Windows wheels. - -#### Input/output -- Added support for tuples and ndarrays as arguments in many functions, where previously only lists were accepted. - ---- - -## Changes in 1.1.9 - -#### Audio buffer -- Added `audio_buffer` to `State` and related methods `is/setAudioBufferEnabled`, `get/setAudioSamplingRate`, `get/setAudioBufferSize`. - -#### Save/load methods -- Added `save` and `load` methods that allow saving/loading game to/from a file. - -#### Misc -- Added `viz_bots_path` CVAR that allows specifying path to custom bots configuration. - ---- - -## Changes in 1.1.8 - -#### Objects and sectors -- Added `is/setObjectsInfoEnabled`, `is/setSectorsInfoEnabled` methods to Python and C++ than enable information about all objects or/and sectors (map layout) present in the current episode/level. -- Added `objects` and `sectors` fields to `GameState` in Python and C++. - -#### Config files -- Added missing GameVariables introduced in 1.1.5 to Config parser. -- Added missing GameVariables introduced in 1.1.7 to Config parser. -- Added `objectsInfoEnabled/objects_info_enabled` - -#### Python, Java, Lua -- Dropped support for Python 2.7 -- Dropped support for Java bindings -- Dropped support for Lua/Torch bindings - ---- - -## Changes in 1.1.7 - -#### Python & Julia -- Added missing `is_multiplayer_game` method to Python and Julia binding. - -#### CVARS -- Added `VIEW_HEIGHT`, `CAMERA_POSITION_X`/`Y`/`Z`, `CAMERA_ANGLE`, `CAMERA_PITCH`, `CAMERA_ROLL` and `CAMERA_FOV` GameVariables. - ---- - -## Changes in 1.1.6 - -#### Julia specific -- Julia binding added. - -#### Server state -- Added `getServerState` method that returns `ServerState` object. - -#### Multiplayer -- Added timeout for network game synchronization controlled by `viz_connect_timeout` CVAR. -- Fixed `viz_spectator` CVAR. - -#### Python specific -- Added Python interpreter version check. - ---- - -## Changes in 1.1.5 - -#### Automap -- Added `viz_am_scale` CVAR (CVAR version of `am_scale` CCMD). -- Added `viz_am_center` CVAR (and `am_center` CCMD). - -#### Buttons and actions -- **Added `getButton` method.** - -#### Episode recording and replaying -- Added `isRecordingEpisode` and `isReplayingEpisode` methods. - -#### GameVariables -- **`KILLCOUNT` counts all kills, including multilayer kills.** -- **`HITCOUNT`, `HITS_TAKEN`, `DAMAGECOUNT`, `DAMAGE_TAKEN` game variables added.** - -#### Labels -- **Added appending "Dead" prefix to label's name when actor is a corpse.** -- **Added bounding box information to Label object in `x`, `y`, `width` and `height` fields.** -- **Added `objectAngle`, `objectPitch`, `objectRoll`, `objectVelocityX/Y/Z` fields to Label object.** - -#### Windows specific -- Fixed problem with building on Windows 8.1 and 10. -- Added scripts for downloading freedoom2.wad and assembling Python packages. - -#### Rendering -- Fixed minor rendering issue in depth and labels buffers. -- Fixed order of color values in `RGB/BGR` modes of `ScreenFormat`. - ---- - -## Changes in 1.1.4 - -#### Automap -- Added `am_scale` CCMD. - -#### Scenarios -- Fixed `KILLCOUNT` GameVariable for ChainsawMarine in `defend_the_center` and `deathmatch` scenarios. - -#### Python specific -- **Ported Python binding to pybind11 as a replacement for Boost.Python.** -- Fixed problems with `pip install` detecting Python interpreter, includes and libraries from different Python versions. - ---- - -## Changes in 1.1.3 - -#### Rendering options -- Added `setRenderScreenFlashes` and `setRenderAllFrames` methods. -- Added `viz_ignore_render_mode` CVAR which disables overriding rendering settings. - -#### GameVariables -- **Added `ANGLE`, `PITCH`, `ROLL`, `VELOCITY_X`/`Y`/`Z` GameVariables.** - -#### Missing config keys -- Added support for `DEATHCOUNT`, `USER31` - `USER60`, `PLAYER_NUMBER`, `PLAYER_COUNT`, `PLAYER1_FRAGCOUNT` - `PLAYER16_FRAGCOUNT`, `POSITION_X`/`Y`/`Z` GameVariables in the config file. -- Added support for `ALTATTACK` Button in the config file. - -#### Java specific -- Fixed `makeAction`. -- Added missing `POSITION_X`/`Y`/`Z` Game Variables. - -#### Python specific -- Added manual GIL management for better performance when used with Python threads. - -#### Windows specific -- Fixed building for Windows 10. - ---- - -## Changes in 1.1.2 - -#### Multiplayer -- Added `isMultiplayerGame` method. -- Added `viz_respawn_delay` CVAR, which allows controlling the delay between respawns in multiplayer game. -- Added `viz_spectator` CVAR which allows connecting to multiplayer game as a spectator. -- **Maximum number of connected players raised to 16, `PLAYER9_FRAGCOUNT` - `PLAYER16_FRAGCOUNT` GameVariables added.** - -#### Missing methods -- Added `isRunning`, `isDepthBufferEnabled`, `isLabelsBufferEnabled` and `isAutomapBufferEnabled` missing methods to Python and Lua bindings. - ---- - -## Changes in 1.1.1 - -#### GameState -- Added `tic` field. -- `GameVariable.DEATHCOUNT` fixed. - -#### Lua specific -- Fixed crash when calling `getState` in a terminal state. - -#### Python specific -- Fixed minor memory leak -- Fixed crash when calling `getState` in a terminal state. - ---- - -## Changes in 1.1.0 - -#### Buffers - -- Depth buffer is now a separate buffer in state and `ScreenFormat` values with it were removed - `is/setDepthBufferEnabled` added. -- Added in frame actors labeling feature -`is/setLabelsBufferEnabled` added. -- Added buffer with in game automap - `is/setAutomapBufferEnabled`, `setAutomapMode`, `setAutomapRoate`, `setAutomapRenderTextures`, `AutomapMode` enum added. - - -#### GameState - -- `getState` will now return `nullptr/null/None` if game is in the terminal state. -- `imageBuffer` renamed to `screenBuffer`. -- Added `depthBuffer`, `labelsBuffer` and `automapBuffer` and `labels` fields. - - -#### Rendering options - -- The option to use minimal hud instead of default full hud - `setRenderMinimalHud` added. -- The option to enable/disable effects that use sprites - `setRenderEffectsSprites` added. -- The option to enable/disable in game messages independently of the console output - `setRenderMessages` added. -- The option to enable/disable corpses - `setRenderCorpses` added. - - -#### Episode recording and replaying - -- The option to record and replay episodes, based on adapted ZDoom's demo mechanism - -recording `filePath` argument added to `newEpisode`, `replayEpisode` added. -- The option to replay demo from other players' perspective. - - -#### Ticrate - -- The option to set number of tics executed per second in ASNYC Modes. -- New `ticrate` optional argument in `doomTicsToMs`, `msToDoomTics`. -- `doomTicsToSec` and `secToDoomTics` added. - - -#### Paths - -- **Paths in config files are now relative to config file.** -- setting **vizdoom_path** and **doom_game_path** is no longer needed - they default to location(installation) of vizdoom.so. - - -#### Others - -- ZDoom engine updated to 2.8.1. -- **Basic support for multiplayer in PLAYER and SPECTATOR Modes.** -- Improved exceptions messages. -- Bugs associated with paths handling were fixed. -- Many minor bugs were fixed. -- Possibility to change scenario wad during runtime (only first map from WAD file). -- Added `viz_debug` CVAR to control some diagnostic messages. - - -#### C++ specific - -- A lot of overloaded methods turned into a methods with default arguments. -- `getState()` now returns `GameStatePtr (std::shared_ptr)` instead of `GameState`. -- Buffers are now copied. -- GameState's buffer has now `ImageBufferPtr (std::shared_ptr)` type - `Buffer (std::vector)`. -- GameState's gameVariables are now vector of doubles instead of ints. - - -#### Lua specific - -- Lua binding added. -- Support for LuaRocks installation for Linux and MacOS. - - -#### Java specific - -- GameState buffers type changed to byte[]. -- Performance improved. -- Java exceptions handling fixed. -- Few functions fixed. - - -#### Python specific - -- Consts added to Python. -- Aliases for `doom_fixed_to_double` - `doom_fixed_to_float` added. -- Support for pip installation for Linux and MacOS. diff --git a/doc/Exceptions.md b/doc/Exceptions.md deleted file mode 100644 index 8ff05215c..000000000 --- a/doc/Exceptions.md +++ /dev/null @@ -1,14 +0,0 @@ -# Exceptions -* FileDoesNotExistException - means that file specified as part of a configuration does not exist. - -* MessageQueueException/SharedMemoryException - means that communication with ViZDoom's instance failed. Usually, means a problem with permissions or system configuration. - -* SignalException - means that a signal was cached by ViZDoom's instance. - -* ViZDoomErrorException - means that an error in the ViZDoom engine occurred. - -* ViZDoomIsNotRunningException - means that called method cannot be used when ViZDoom instance is not running. - -* ViZDoomUnexpectedExitException - means that ViZDoom's instance was closed/terminated/killed from the outside. - -Most of the exceptions contain more information in "what()" message. diff --git a/doc/Gym.md b/doc/Gym.md deleted file mode 100644 index a7dfe5c3c..000000000 --- a/doc/Gym.md +++ /dev/null @@ -1,12 +0,0 @@ -# OpenAI Gym wrappers - -Installing ViZDoom with `pip install vizdoom[gym]` will include -Gym wrappers to interact with ViZDoom over Gym API. Note that Gym is deprecated in favour of Gymnasium and these wrappers will be removed in the future. - -These wrappers are under `gym_wrappers`, containing the basic environment and -few example environments based on the built-in scenarios. This environment -simply initializes ViZDoom with the settings from the scenario config files -and implements the necessary API to function as a Gym API. - -See following examples for use: - - `examples/python/gym_wrapper.py` for basic usage diff --git a/doc/index.md b/doc/index.md deleted file mode 100644 index b3772f085..000000000 --- a/doc/index.md +++ /dev/null @@ -1,77 +0,0 @@ -# ViZDoom -[http://vizdoom.cs.put.edu.pl](http://vizdoom.cs.put.edu.pl) - -ViZDoom allows developing AI **bots that play Doom using only the visual information** (the screen buffer). It is primarily intended for research in machine visual learning, and deep reinforcement learning, in particular. - -ViZDoom is based on [ZDoom](https://github.com/rheit/zdoom) to provide the game mechanics. - -## Features -- Multi-platform, -- API for Python, C++ and Julia -- Easy-to-create custom scenarios (visual editors, scripting language and examples available), -- Async and sync single-player and multi-player modes, -- Fast (up to 7000 fps in sync mode, single threaded), -- Lightweight (few MBs), -- Customizable resolution and rendering parameters, -- Access to the depth buffer (3D vision), -- Automatic labeling game objects visible in the frame, -- Off-screen rendering, -- Episodes recording, -- Time scaling in async mode. - -ViZDoom API is **reinforcement learning** friendly (suitable also for learning from demonstration, apprenticeship learning or apprenticeship via inverse reinforcement learning, etc.). - - -## Cite as -> M Wydmuch, M Kempka & W Jaśkowski, ViZDoom Competitions: Playing Doom from Pixels, IEEE Transactions on Games, in print, -[arXiv:1809.03470](https://arxiv.org/abs/1809.03470) -``` -@article{wydmuch2018vizdoom, - title={ViZDoom Competitions: Playing Doom from Pixels}, - author={Wydmuch, Marek and Kempka, Micha{\l} and Ja{\'s}kowski, Wojciech}, - journal={IEEE Transactions on Games}, - year={2018}, - publisher={IEEE} -} -``` -or - -> M. Kempka, M. Wydmuch, G. Runc, J. Toczek & W. Jaśkowski, ViZDoom: A Doom-based AI Research Platform for Visual Reinforcement Learning, IEEE Conference on Computational Intelligence and Games, pp. 341-348, Santorini, Greece, 2016 ([arXiv:1605.02097](http://arxiv.org/abs/1605.02097)) -``` -@inproceedings{Kempka2016ViZDoom, - author = {Micha{\l} Kempka and Marek Wydmuch and Grzegorz Runc and Jakub Toczek and Wojciech Ja\'skowski}, - title = {{ViZDoom}: A {D}oom-based {AI} Research Platform for Visual Reinforcement Learning}, - booktitle = {IEEE Conference on Computational Intelligence and Games}, - year = {2016}, - url = {http://arxiv.org/abs/1605.02097}, - address = {Santorini, Greece}, - Month = {Sep}, - Pages = {341--348}, - Publisher = {IEEE}, - Note = {The best paper award} -} -``` - -## Documentation - -Detailed description of all types and methods: - -- **[DoomGame](doc/DoomGame.md)** -- **[Types](doc/Types.md)** -- [Configuration files](doc/ConfigFile.md) -- [Exceptions](doc/Exceptions.md) -- [Utilities](doc/Utilities.md) - -Additional documents: - -- **[FAQ](doc/FAQ.md)** -- [Changelog](doc/Changelog.md) for 1.1.X version. - -Also full documentation of engine and ACS scripting language can be found on -[ZDoom Wiki](https://zdoom.org/wiki/). - -Useful parts: - -- [ZDoom Wiki: ACS (scripting language)](https://zdoom.org/wiki/ACS) -- [ZDoom Wiki: CVARs (console variables)](https://zdoom.org/wiki/CVARs) -- [ZDoom Wiki: CCMD (console commands)](https://zdoom.org/wiki/CCMDs) diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 000000000..5b8364a2d --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,21 @@ +.DS_Store +__pycache__ +.vscode/ +build/ +_build/ + +tutorials/**/*.pickle +tutorials/**/images/ +tutorials/**/*.rst +tutorials/**/*.ipynb +tutorials/**/*.zip +!tutorials/**/README.rst + +environments/**/list.html +environments/**/complete_list.html +environments/**/complete_list.md +environments/box2d/*.md +environments/classic_control/*.md +environments/mujoco/*.md +environments/third_party_environments/*.md +environments/toy_text/*.md diff --git a/docs/404.md b/docs/404.md new file mode 100644 index 000000000..87805720a --- /dev/null +++ b/docs/404.md @@ -0,0 +1,7 @@ +--- +hide-toc: true +--- + +# 404 - Page Not Found + +## The requested page could not be found. diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..41c50068c --- /dev/null +++ b/docs/README.md @@ -0,0 +1,5 @@ +# ViZDoom documentation + +This directory contains the documentation for ViZDOOm. + +For more information about how to contribute to the documentation go to our [CONTRIBUTING.md](https://github.com/Farama-Foundation/Celshast/blob/main/CONTRIBUTING.md) diff --git a/docs/_scripts/ipynb_to_gallery.py b/docs/_scripts/ipynb_to_gallery.py new file mode 100644 index 000000000..5580fef31 --- /dev/null +++ b/docs/_scripts/ipynb_to_gallery.py @@ -0,0 +1,62 @@ +"""Convert jupyter notebook to sphinx gallery notebook styled examples. + +Usage: python ipynb_to_gallery.py + +Dependencies: pypandoc, beautifulsoup4, numpy +install using `pip install pypandoc, beautifulsoup4, numpy` +""" +import json +import warnings + +import numpy as np +import pypandoc as pdoc +from bs4 import BeautifulSoup + +warnings.filterwarnings( + "ignore", + message="The input looks more like a filename than markup. You may want to open this file and pass the filehandle into Beautiful Soup", +) + + +def convert_ipynb_to_gallery(file_name): + python_file = "" + + nb_dict = json.load(open(file_name)) + cells = nb_dict["cells"] + + for i, cell in enumerate(cells): + if i == 0: + assert cell["cell_type"] == "markdown", "First cell has to be markdown" + + md_source = "".join(cell["source"]) + rst_source = pdoc.convert_text(md_source, "rst", "md") + python_file = '"""\n' + rst_source + '\n"""' + else: + if cell["cell_type"] == "markdown": + md_source = "".join(cell["source"]) + is_all_lines_html = np.all( + [ + bool(BeautifulSoup(line, "html.parser").find()) + for line in cell["source"] + ] + ) + if is_all_lines_html: + rst_source = pdoc.convert_text( + source=md_source, to="rst", format="html" + ) + else: + rst_source = pdoc.convert_text(md_source, "rst", "md") + commented_source = "\n".join(["# " + x for x in rst_source.split("\n")]) + python_file = python_file + "\n\n\n" + "# %%" + "\n" + commented_source + elif cell["cell_type"] == "code": + source = "".join(cell["source"]) + python_file = python_file + "\n" * 2 + source + + python_file = python_file.replace("\n%", "\n# %") + open(file_name.replace(".ipynb", ".py"), "w").write(python_file) + + +if __name__ == "__main__": + import sys + + convert_ipynb_to_gallery(sys.argv[-1]) diff --git a/docs/_scripts/move_404.py b/docs/_scripts/move_404.py new file mode 100644 index 000000000..b53bae55f --- /dev/null +++ b/docs/_scripts/move_404.py @@ -0,0 +1,14 @@ +import sys + +if __name__ == "__main__": + if len(sys.argv) < 2: + print("Provide a path") + filePath = sys.argv[1] + + with open(filePath, "r+") as fp: + content = fp.read() + content = content.replace('href="../', 'href="/').replace('src="../', 'src="/') + fp.seek(0) + fp.truncate() + + fp.write(content) diff --git a/docs/_static/img/favicon.png b/docs/_static/img/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..74a791bf3a67789b41a16e98a1a9c981be4473bf GIT binary patch literal 696 zcmV;p0!RIcP)LSoZp_D`yF4V1wSbs!9#&_rYUem#q zEol+@50sV`7j2*`rFGeb=pqOT(v1?8XEm?F!+H0*a1w^JXL;{A=U&eJe#PCHL{StA z?tUD2+TCZyWdVLjlH^Li-~VosFOvpEQ7oBRZ)RrZ?CR?3?j$kB*a7;$&#L;xBL+oL zd}L;Gz`N7a(@)lQy$rkrJQR^%-F;(zetvg*dwU4nQPnMgFm^v}W={cURMqObJ_B4* z)l;harn?V;4;L2~n@*>rz^NGHX@C?!M2<{NOz-?gNK`sHzVRWN-*jV8_g!Ns^?~?RMV@A%r>Lb_n4&U;&80 z<)SEh6XEuN%j4cck|e*o`;D?JpG(bbM?_u~krD7qmSqosr5NLdJkLJ>aQ8n{bqOHP z^S^+9MdWa+)w(0@PK@y?um&v8&d#o_tgO^L2Ai9k(`8u>fs4RURbLO|-j`!~i1b9{`u-UQgTd7h!Vz~rCL%Ay7~eQ39@o0=ehlcT>h=9Iy1U01 z4~fY4BJ!=fzg-lCnb}*wKOux`z)2DL#{b8hk6&QAH$g;hx%&xs?~2H^(P;Fr)oQIZ zP4nkyGj)340zHNcW2xw5C*%YZD)Zi>iV;BR;TG0*d@rfEI~&gFT&WoADCyTHwU zzkh3g@WJ00V>~V*3+;CMVpUb20JPif&#J0g25x6r_VpzH5reVGv%ven^FRgcq-lD7 eeSQ7@LGFLXUM>Cr%@d{o0000 + + + + + + + + diff --git a/docs/_static/img/vizdoom-github.png b/docs/_static/img/vizdoom-github.png new file mode 100644 index 0000000000000000000000000000000000000000..6dd7fa93aff5562cfcf7de25c47d76cb76af7931 GIT binary patch literal 3283401 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 + + + + + + + + diff --git a/doc/ConfigFile.md b/docs/api/configuration.md similarity index 99% rename from doc/ConfigFile.md rename to docs/api/configuration.md index 00bbbd854..e13b93d46 100644 --- a/doc/ConfigFile.md +++ b/docs/api/configuration.md @@ -1,4 +1,5 @@ # Configuration files + Instead of configuring the ViZDoom in code, you can load it from the configuration file(s). Each file is read sequentially, so multiple entries with the same key will overwrite previous entries. ## Format diff --git a/doc/DoomGame.md b/docs/api/doomGame.md similarity index 91% rename from doc/DoomGame.md rename to docs/api/doomGame.md index e53aa8bfa..73d02e03d 100644 --- a/doc/DoomGame.md +++ b/docs/api/doomGame.md @@ -1,123 +1,6 @@ # DoomGame -## [Flow control methods](#flow) -* [init](#init) -* [close](#close) -* [newEpisode](#newEpisode) -* [replayEpisode](#replayEpisode) -* [isRunning](#isRunning) -* [isMultiplayerGame](#isMultiplayerGame) -* [isRecordingEpisode](#isRecordingEpisode) -* [isReplayingEpisode](#isReplayingEpisode) -* [setAction](#setAction) -* [advanceAction](#advanceAction) -* [makeAction](#makeAction) -* [isNewEpisode](#isNewEpisode) -* [isEpisodeFinished](#isEpisodeFinished) -* [isPlayerDead](#isPlayerDead) -* [respawnPlayer](#respawnPlayer) -* [sendGameCommand](#sendGameCommand) -* [getState](#getState) -* [getServerState](#getServerState) -* [getLastAction](#getLastAction) -* [getEpisodeTime](#getEpisodeTime) -* [save](#save) -* [load](#load) - -## [Buttons settings methods](#buttons) -* [getAvailableButtons](#getAvailableButtons) -* [setAvailableButtons](#setAvailableButtons) -* [addAvailableButton](#addAvailableButton) -* [clearAvailableButtons](#clearAvailableButtons) -* [getAvailableButtonsSize](#getAvailableButtonsSize) -* [setButtonMaxValue](#setButtonMaxValue) -* [getButtonMaxValue](#getButtonMaxValue) -* [getButton](#getButton) - -## [GameVariables methods](#vars) -* [getAvailableGameVariables](#getAvailableGameVariables) -* [setAvailableGameVariables](#setAvailableGameVariables) -* [addAvailableGameVariable](#addAvailableGameVariable) -* [clearAvailableGameVariables](#clearAvailableGameVariables) -* [getAvailableGameVariablesSize](#getAvailableGameVariablesSize) -* [getGameVariable](#getGameVariable) - -## [Game Arguments methods](#args) -* [addGameArgs](#addGameArgs) -* [clearGameArgs](#clearGameArgs) - -## [Rewards methods](#rewards) -* [getLivingReward](#getLivingReward) -* [setLivingReward](#setLivingReward) -* [getDeathPenalty](#getDeathPenalty) -* [setDeathPenalty](#setDeathPenalty) -* [getLastReward](#getLastReward) -* [getTotalReward](#getTotalReward) - -## [General game configuration methods](#settings) -* [loadConfig](#loadConfig) -* [getMode](#getMode) -* [setMode](#setMode) -* [getTicrate](#getTicrate) -* [setTicrate](#setTicrate) -* [setViZDoomPath](#setViZDoomPath) -* [setDoomGamePath](#setDoomGamePath) -* [setDoomScenarioPath](#setDoomScenarioPath) -* [setDoomMap](#setDoomMap) -* [setDoomSkill](#setDoomSkill) -* [setDoomConfigPath](#setDoomConfigPath) -* [getSeed](#getSeed) -* [setSeed](#setSeed) -* [getEpisodeStartTime](#getEpisodeStartTime) -* [setEpisodeStartTime](#setEpisodeStartTime) -* [getEpisodeTimeout](#getEpisodeTimeout) -* [setEpisodeTimeout](#setEpisodeTimeout) - -## [Output/rendering setting methods](#rendering) -* [setScreenResolution](#setScreenResolution) -* [getScreenFormat](#getScreenFormat) -* [setScreenFormat](#setScreenFormat) -* [isDepthBufferEnabled](#isDepthBufferEnabled) -* [setDepthBufferEnabled](#setDepthBufferEnabled) -* [isLabelsBufferEnabled](#isLabelsBufferEnabled) -* [setLabelsBufferEnabled](#setLabelsBufferEnabled) -* [isAutomapBufferEnabled](#isAutomapBufferEnabled) -* [setAutomapBufferEnabled](#setAutomapBufferEnabled) -* [setAutomapMode](#setAutomapMode) -* [setAutomapRotate](#setAutomapRotate) -* [setAutomapRenderTextures](#setAutomapRenderTextures) -* [setRenderHud](#setRenderHud) -* [setRenderMinimalHud](#setRenderMinimalHud) -* [setRenderWeapon](#setRenderWeapon) -* [setRenderCrosshair](#setRenderCrosshair) -* [setRenderDecals](#setRenderDecals) -* [setRenderParticles](#setRenderParticles) -* [setRenderEffectsSprites](#setRenderEffectsSprites) -* [setRenderMessages](#setRenderMessages) -* [setRenderCorpses](#setRenderCorpses) -* [setRenderScreenFlashes](#setRenderScreenFlashes) -* [setRenderAllFrames](#setRenderAllFrames) -* [setWindowVisible](#setWindowVisible) -* [setConsoleEnabled](#setConsoleEnabled) -* [setSoundEnabled](#setSoundEnabled) -* [getScreenWidth](#getScreenWidth) -* [getScreenHeight](#getScreenHeight) -* [getScreenChannels](#getScreenChannels) -* [getScreenPitch](#getScreenPitch) -* [getScreenSize](#getScreenSize) -* [isObjectsInfoEnabled](#isObjectsInfoEnabled) -* [setObjectsInfoEnabled](#setObjectsInfoEnabled) -* [isSectorsInfoEnabled](#isSectorsInfoEnabled) -* [setSectorsInfoEnabled](#setSectorsInfoEnabled) -* [isAudioBufferEnabled](#isAudioBufferEnabled) -* [setAudioBufferEnabled](#setAudioBufferEnabled) -* [getAudioSamplingFreq](#getAudioSamplingFreq) -* [setAudioSamplingFreq](#setAudioSamplingFreq) -* [getAudioBufferSize](#getAudioBufferSize) -* [setAudioBufferSize](#setAudioBufferSize) - - -## Flow control methods: +## Flow control methods: --- ### `init` diff --git a/docs/api/exceptions.md b/docs/api/exceptions.md new file mode 100644 index 000000000..adaf06ac5 --- /dev/null +++ b/docs/api/exceptions.md @@ -0,0 +1,15 @@ +# Exceptions + +* `FileDoesNotExistException` - means that file specified as part of a configuration does not exist. + +* `MessageQueueException/SharedMemoryException` - means that communication with ViZDoom's instance failed. Usually, means a problem with permissions or system configuration. + +* `SignalException` - means that a signal was cached by ViZDoom's instance. + +* `ViZDoomErrorException` - means that an error in the ViZDoom engine occurred. + +* `ViZDoomIsNotRunningException` - means that called method cannot be used when ViZDoom instance is not running. + +* `ViZDoomUnexpectedExitException` - means that ViZDoom's instance was closed/terminated/killed from the outside. + +Most of the exceptions contain more information in "what()" message. diff --git a/doc/Types.md b/docs/api/types.md similarity index 89% rename from doc/Types.md rename to docs/api/types.md index 819c28ae0..c16051607 100644 --- a/doc/Types.md +++ b/docs/api/types.md @@ -1,22 +1,5 @@ # Types -* [Label](#label) -* [Object](#object) -* [Line](#line) -* [Sector](#sector) -* [GameState](#gamestate) -* [ServerState](#serverstate) -* [Enums](#enums) - * [Mode](#mode) - * [ScreenFormat](#screenformat) - * [ScreenResolution](#screenresolution) - * [AutomapMode](#automapmode) - * [GameVariable](#gamevariable) - * [Button](#button) - * [binary buttons](#binary-buttons) - * [delta buttons](#delta-buttons) - * [SamplingRate](#sampling-rate) - ## C++ only - `Buffer (std::vector)` @@ -80,7 +63,7 @@ Right now `Object` is only available to C++ and Python. Added in 1.1.8. See also: -- [`DoomGame: setObjectsInfoEnabled`](DoomGame.md#setSectorsInfoEnabled), +- [`DoomGame: setObjectsInfoEnabled`](./doomGame.md#setSectorsInfoEnabled), - [examples/python/objects_and_sectors.py](https://github.com/mwydmuch/ViZDoom/tree/master/examples/python/objects_and_sectors.py). @@ -125,7 +108,7 @@ Right now `Sector` is only available to C++ and Python. Added in 1.1.8. See also: -- [`DoomGame: setSectorsInfoEnabled`](DoomGame.md#setSectorsInfoEnabled), +- [`DoomGame: setSectorsInfoEnabled`](./doomGame.md#setSectorsInfoEnabled), - [examples/python/objects_and_sectors.py](https://github.com/mwydmuch/ViZDoom/tree/master/examples/python/objects_and_sectors.py). @@ -147,7 +130,7 @@ See also: **tic** - ingame time, 1 tic is 1/35 of second in the game world. Added in 1.1.1. See also: -- [`DoomGame: getState`](DoomGame.md#getState), +- [`DoomGame: getState`](./doomGame.md#getState), - [examples/python/basic.py](https://github.com/mwydmuch/ViZDoom/tree/master/examples/python/basic.py), - [examples/python/buffers.py](https://github.com/mwydmuch/ViZDoom/tree/master/examples/python/buffers.py). - [examples/python/audio_buffer.py](https://github.com/mwydmuch/ViZDoom/tree/master/examples/python/audio_buffer.py). @@ -192,10 +175,10 @@ In **ASYNC** modes the game progress with constant speed (default 35 tics per se All modes can be used in singleplayer and multiplayer. See also: -- [`DoomGame: getMode`](DoomGame.md#getMode), -- [`DoomGame: setMode`](DoomGame.md#setMode), -- [`DoomGame: getTicrate`](DoomGame.md#getTicrate), -- [`DoomGame: setTicrate`](DoomGame.md#setTicrate). +- [`DoomGame: getMode`](./doomGame.md#getMode), +- [`DoomGame: setMode`](./doomGame.md#setMode), +- [`DoomGame: getTicrate`](./doomGame.md#getTicrate), +- [`DoomGame: setTicrate`](./doomGame.md#setTicrate). --- @@ -226,8 +209,8 @@ In **GRAY8** and **DOOM_256_COLORS8** format **screenBuffer** and **automapBuffe **depthBuffer** and **lablesBuffer** always store single 8-bit values, so they always have [y, x] shape. See also: -- [`DoomGame: getScreenFormat`](DoomGame.md#getScreenFormat), -- [`DoomGame: setScreenFormat`](DoomGame.md#setScreenFormat), +- [`DoomGame: getScreenFormat`](./doomGame.md#getScreenFormat), +- [`DoomGame: setScreenFormat`](./doomGame.md#setScreenFormat), - [examples/python/buffers.py](https://github.com/mwydmuch/ViZDoom/tree/master/examples/python/buffers.py). @@ -274,9 +257,9 @@ Enum type that defines all supported resolutions - shapes of **screenBuffer**, * - **RES_1920X1080** (16:9) See also: -- [`DoomGame: setScreenResolution`](DoomGame.md#setScreenResolution), -- [`DoomGame: getScreenWidth`](DoomGame.md#getScreenWidth), -- [`DoomGame: getScreenHeight`](DoomGame.md#getScreenHeight). +- [`DoomGame: setScreenResolution`](./doomGame.md#setScreenResolution), +- [`DoomGame: getScreenWidth`](./doomGame.md#getScreenWidth), +- [`DoomGame: getScreenHeight`](./doomGame.md#getScreenHeight). --- @@ -290,7 +273,7 @@ Enum type that defines all **automapBuffer** modes. - **OBJECTS_WITH_SIZE** - In addition to the previous, all things are wrapped in a box showing their size. See also: -- [`DoomGame: setAutomapMode`](DoomGame.md#setAutomapMode), +- [`DoomGame: setAutomapMode`](./doomGame.md#setAutomapMode), - [examples/python/buffers.py](https://github.com/mwydmuch/ViZDoom/tree/master/examples/python/buffers.py). @@ -350,10 +333,10 @@ Other from 1 to 60 (global int 1-60) can be accessed as USER1 - USER60 GameVaria See also: - [ZDoom Wiki: ACS](http://zdoom.org/wiki/ACS), -- [`DoomGame: getAvailableGameVariables`](DoomGame.md#getAvailableGameVariables), -- [`DoomGame: setAvailableGameVariables`](DoomGame.md#setAvailableGameVariables), -- [`DoomGame: addAvailableGameVariable`](DoomGame.md#addAvailableGameVariable), -- [`DoomGame: getGameVariable`](DoomGame.md#getGameVariable), +- [`DoomGame: getAvailableGameVariables`](./doomGame.md#getAvailableGameVariables), +- [`DoomGame: setAvailableGameVariables`](./doomGame.md#setAvailableGameVariables), +- [`DoomGame: addAvailableGameVariable`](./doomGame.md#addAvailableGameVariable), +- [`DoomGame: getGameVariable`](./doomGame.md#getGameVariable), - [`Utilities: doomFixedToDouble`](Utilities.md#doomFixedToDouble), - [examples/python/basic.py](https://github.com/mwydmuch/ViZDoom/tree/master/examples/python/basic.py), - [examples/python/shaping.py](https://github.com/mwydmuch/ViZDoom/tree/master/examples/python/shaping.py). @@ -425,11 +408,11 @@ In case of **MOVE_FORWARD_BACKWARD_DELTA**, **MOVE_LEFT_RIGHT_DELTA**, **MOVE_UP See also: - [Doom Wiki: Map unit](https://doomwiki.org/wiki/Map_unit), -- [`DoomGame: getAvailableButtons`](DoomGame.md#getAvailableButtons), -- [`DoomGame: setAvailableButtons`](DoomGame.md#setAvailableButtons), -- [`DoomGame: addAvailableButton`](DoomGame.md#addAvailableButton), -- [`DoomGame: setButtonMaxValue`](DoomGame.md#setButtonMaxValue), -- [`DoomGame: getButtonMaxValue`](DoomGame.md#getButtonMaxValue), +- [`DoomGame: getAvailableButtons`](./doomGame.md#getAvailableButtons), +- [`DoomGame: setAvailableButtons`](./doomGame.md#setAvailableButtons), +- [`DoomGame: addAvailableButton`](./doomGame.md#addAvailableButton), +- [`DoomGame: setButtonMaxValue`](./doomGame.md#setButtonMaxValue), +- [`DoomGame: getButtonMaxValue`](./doomGame.md#getButtonMaxValue), - [examples/python/basic.py](https://github.com/mwydmuch/ViZDoom/tree/master/examples/python/basic.py), - [examples/python/delta_buttons.py](https://github.com/mwydmuch/ViZDoom/tree/master/examples/python/delta_buttons.py), - [GitHub issue: Angle changes by executing certain commands](https://github.com/mwydmuch/ViZDoom/issues/182). diff --git a/doc/Utilities.md b/docs/api/utils.md similarity index 78% rename from doc/Utilities.md rename to docs/api/utils.md index cec4b0156..390707aad 100644 --- a/doc/Utilities.md +++ b/docs/api/utils.md @@ -1,16 +1,7 @@ # Utilities -* [doomTicsToMs](#doomTicsToMs) -* [msToDoomTics](#msToDoomTics) -* [doomTicsToSec](#doomTicsToSec) -* [secToDoomTics](#secToDoomTics) -* [doomFixedToDouble](#doomFixedToDouble) -* [isBinaryButton](#isBinaryButton) -* [isDeltaButton](#isDeltaButton) - - --- -### `doomTicsToMs` +## `doomTicsToMs` | C++ | `double doomTicsToMs(double tics, unsigned int ticrate = 35)` | | :-- | :-- | @@ -22,7 +13,7 @@ Calculates how many tics will be made during given number of milliseconds. --- -### `msToDoomTics` +## `msToDoomTics` | C++ | `double msToDoomTics(double ms, unsigned int ticrate = 35)` | | :-- | :-- | @@ -34,7 +25,7 @@ Calculates the number of milliseconds that will pass during specified number of --- -### `doomTicsToSec` +## `doomTicsToSec` | C++ | `double doomTicsToSec(double tics, unsigned int ticrate = 35)` | | :-- | :-- | @@ -46,7 +37,7 @@ Calculates how many tics will be made during given number of seconds. --- -### `secToDoomTics` +## `secToDoomTics` | C++ | `double secToDoomTics(double sec, unsigned int ticrate = 35)` | | :-- | :-- | @@ -58,7 +49,7 @@ Calculates the number of seconds that will pass during specified number of tics. --- -### `doomFixedToDouble` +## `doomFixedToDouble` | C++ | `double doomFixedToDouble(int / double doomFixed)` | | :-- | :-- | @@ -74,7 +65,7 @@ Python aliases (added in 1.1): --- -### `isBinaryButton` +## `isBinaryButton` | C++ | `bool isBinaryButton(Button button)` | | :-- | :-- | @@ -84,7 +75,7 @@ Returns true if button is binary button. --- -### `isDeltaButton` +## `isDeltaButton` | C++ | `bool isDeltaButton(Button button)` | | :-- | :-- | diff --git a/docs/citation/index.md b/docs/citation/index.md new file mode 100644 index 000000000..dc6f39ad7 --- /dev/null +++ b/docs/citation/index.md @@ -0,0 +1,30 @@ +# Citation + +> M Wydmuch, M Kempka & W Jaśkowski, ViZDoom Competitions: Playing Doom from Pixels, IEEE Transactions on Games, in print, +[arXiv:1809.03470](https://arxiv.org/abs/1809.03470) +``` +@article{wydmuch2018vizdoom, + title={ViZDoom Competitions: Playing Doom from Pixels}, + author={Wydmuch, Marek and Kempka, Micha{\l} and Ja{\'s}kowski, Wojciech}, + journal={IEEE Transactions on Games}, + year={2018}, + publisher={IEEE} +} +``` +or + +> M. Kempka, M. Wydmuch, G. Runc, J. Toczek & W. Jaśkowski, ViZDoom: A Doom-based AI Research Platform for Visual Reinforcement Learning, IEEE Conference on Computational Intelligence and Games, pp. 341-348, Santorini, Greece, 2016 ([arXiv:1605.02097](http://arxiv.org/abs/1605.02097)) +``` +@inproceedings{Kempka2016ViZDoom, + author = {Micha{\l} Kempka and Marek Wydmuch and Grzegorz Runc and Jakub Toczek and Wojciech Ja\'skowski}, + title = {{ViZDoom}: A {D}oom-based {AI} Research Platform for Visual Reinforcement Learning}, + booktitle = {IEEE Conference on Computational Intelligence and Games}, + year = {2016}, + url = {http://arxiv.org/abs/1605.02097}, + address = {Santorini, Greece}, + Month = {Sep}, + Pages = {341--348}, + Publisher = {IEEE}, + Note = {The best paper award} +} +``` \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 000000000..673056055 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,90 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + +# -- Project information ----------------------------------------------------- +import os +from typing import Any, Dict + +import vizdoom + + +project = "ViZDoom" +copyright = "2023 Farama Foundation" +author = "Farama Foundation" + +# The full version, including alpha/beta/rc tags +# release = vizdoom.__version__ + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + "sphinx.ext.napoleon", + "sphinx.ext.doctest", + "sphinx.ext.autodoc", + "sphinx.ext.githubpages", + "myst_parser", + "sphinx_github_changelog", +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ["_templates"] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = [] + +# Napoleon settings +# napoleon_use_ivar = True +napoleon_use_admonition_for_references = True +# See https://github.com/sphinx-doc/sphinx/issues/9119 +napoleon_custom_sections = [("Returns", "params_style")] + +# Autodoc +autoclass_content = "both" +autodoc_preserve_defaults = True + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = "furo" +html_title = "ViZDoom Documentation" +html_baseurl = "https://vizdoom.farama.org" +html_copy_source = False +html_favicon = "_static/img/favicon.png" +html_theme_options = { + "light_logo": "img/vizdoom-black.svg", + "dark_logo": "img/vizdoom-white.svg", + "gtag": "G-6H9C8TWXZ8", + "description": "", + "image": "img/vizdoom-github.png", + "versioning": True, + "source_repository": "https://github.com/Farama-Foundation/ViZDoom/", + "source_branch": "master", + "source_directory": "docs/", +} + +html_static_path = ["_static"] +html_css_files = [] + +# -- Generate Changelog ------------------------------------------------- + +sphinx_github_changelog_token = os.environ.get("SPHINX_GITHUB_CHANGELOG_TOKEN") diff --git a/doc/FAQ.md b/docs/faq/index.md similarity index 100% rename from doc/FAQ.md rename to docs/faq/index.md diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 000000000..f6677bf10 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,65 @@ +--- +hide-toc: true +firstpage: +lastpage: +--- + +# ViZDoom allows developing AI bots that play Doom using only the visual information. + +```{figure} _static/REPLACE_ME.gif + :alt: ViZDoom + :width: 500 +``` + +**Basic example:** + +```{code-block} python + +import gymnasium as gym +env = gym.make("LunarLander-v2", render_mode="human") +observation, info = env.reset(seed=42) +for _ in range(1000): + action = env.action_space.sample() # this is where you would insert your policy + observation, reward, terminated, truncated, info = env.step(action) + + if terminated or truncated: + observation, info = env.reset() +env.close() +``` + +```{toctree} +:hidden: +:caption: Introduction + +introduction/quickstart +introduction/installation +introduction/wrappers +``` + +```{toctree} +:hidden: +:caption: API + +api/doomGame +api/configuration +api/exceptions +api/types +api/utils +``` + +```{toctree} +:hidden: +:caption: Others + +faq/index +citation/index +``` + +```{toctree} +:hidden: +:caption: Development + +Github +release_notes/index +Contribute to the Docs +``` diff --git a/doc/Installation.md b/docs/introduction/installation.md similarity index 90% rename from doc/Installation.md rename to docs/introduction/installation.md index e2faf7ba5..d85681153 100644 --- a/doc/Installation.md +++ b/docs/introduction/installation.md @@ -1,15 +1,17 @@ # Installation and building -* [Dependencies](#deps) - * [Linux](#linux_deps) - * [MacOS](#macos_deps) - * [Windows](#windows_deps) -* [Installation via pip](#pypi) -* [Building (not recommended)](#build) - * [Linux/MacOS](#linux_macos_build) - * [Windows](#windows_build) - * [Compilation output](#output) - * [Manual installation](#manual-install) +- [Installation and building](#installation-and-building) + - [ Dependencies](#-dependencies) + - [ Linux](#-linux) + - [ MacOS](#-macos) + - [ Building](#-building) + - [ Windows](#-windows) + - [ Installation via pip (recommended for Python users)](#-installation-via-pip-recommended-for-python-users) + - [ Building manually (not recommended)](#-building-manually-not-recommended) + - [ Linux / MacOS](#-linux--macos) + - [ Windows](#-windows-1) + - [ Compilation output](#-compilation-output) + - [ Manual installation](#-manual-installation) ## Dependencies diff --git a/doc/Quickstart.md b/docs/introduction/quickstart.md similarity index 91% rename from doc/Quickstart.md rename to docs/introduction/quickstart.md index 6ffea6c4a..1136d47ed 100644 --- a/doc/Quickstart.md +++ b/docs/introduction/quickstart.md @@ -2,7 +2,8 @@ > This guide can be a little bit outdated. -* [Quickstart for MacOS with Anaconda3](#quickstart_macos_anaconda) +- [Quickstart](#quickstart) + - [ Quickstart for MacOS and Anaconda3 (Python 3.6)](#-quickstart-for-macos-and-anaconda3-python-36) TODO: * Quickstart for Ubuntu diff --git a/doc/Gymnasium.md b/docs/introduction/wrappers.md similarity index 53% rename from doc/Gymnasium.md rename to docs/introduction/wrappers.md index a0c45d4c0..3c5e3e95e 100644 --- a/doc/Gymnasium.md +++ b/docs/introduction/wrappers.md @@ -1,4 +1,6 @@ -# Gymnasium wrappers +# Wrapper + +## Gymnasium wrappers Installing ViZDoom with `pip install vizdoom` will include Gymnasium wrappers to interact with ViZDoom over [Gymnasium API](https://gymnasium.farama.org/). @@ -11,3 +13,17 @@ and implements the necessary API to function as a Gymnasium API. See following examples for use: - `examples/python/gymnasium_wrapper.py` for basic usage - `examples/python/learning_stable_baselines.py` for example training with [stable-baselines3](https://github.com/DLR-RM/stable-baselines3/) (Update - Currently facing issues, to be fixed) + + +## OpenAI Gym wrappers + +Installing ViZDoom with `pip install vizdoom[gym]` will include +Gym wrappers to interact with ViZDoom over Gym API. Note that Gym is deprecated in favour of Gymnasium and these wrappers will be removed in the future. + +These wrappers are under `gym_wrappers`, containing the basic environment and +few example environments based on the built-in scenarios. This environment +simply initializes ViZDoom with the settings from the scenario config files +and implements the necessary API to function as a Gym API. + +See following examples for use: + - `examples/python/gym_wrapper.py` for basic usage diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 000000000..8084272b4 --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=_build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/release_notes/index.md b/docs/release_notes/index.md new file mode 100644 index 000000000..aac7a1432 --- /dev/null +++ b/docs/release_notes/index.md @@ -0,0 +1,8 @@ +# Release Notes + +```{eval-rst} +.. changelog:: + :github: https://github.com/Farama-Foundation/ViZDoom/releases + :pypi: https://pypi.org/project/vizdoom/ + :changelog-url: +``` \ No newline at end of file diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 000000000..2ae0c04f9 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,5 @@ +sphinx +sphinx-autobuild +myst-parser +git+https://github.com/Farama-Foundation/Celshast#egg=furo +sphinx_github_changelog From 12fb782981c2252000cf551c27ee222f0a88cc56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Goul=C3=A3o?= Date: Mon, 1 May 2023 11:12:31 +0100 Subject: [PATCH 2/9] fix build docs workflow --- .github/workflows/build-docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 31c536079..e3c94ee72 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -30,7 +30,7 @@ jobs: run: mv _build/404/index.html _build/404.html - name: Update 404 links - run: python docs/scripts/move404.py _build/404.html + run: python docs/_scripts/move404.py _build/404.html - name: Remove .doctrees run: rm -r _build/.doctrees From 7b4042c0c2f2658316fa9b9b8716d8b1e5949c49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Goul=C3=A3o?= Date: Mon, 1 May 2023 11:16:06 +0100 Subject: [PATCH 3/9] fix name move_404 --- .github/workflows/build-docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index e3c94ee72..7b6ddabc9 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -30,7 +30,7 @@ jobs: run: mv _build/404/index.html _build/404.html - name: Update 404 links - run: python docs/_scripts/move404.py _build/404.html + run: python docs/_scripts/move_404.py _build/404.html - name: Remove .doctrees run: rm -r _build/.doctrees From 7c77cf1d0e9b715329f9dd860c56d730485d59d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20Goul=C3=A3o?= Date: Mon, 1 May 2023 11:23:15 +0100 Subject: [PATCH 4/9] add github token to docs workflow --- .github/workflows/build-docs.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 7b6ddabc9..4991e8b2b 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -10,7 +10,8 @@ jobs: docs: name: Generate Website runs-on: ubuntu-latest - + env: + SPHINX_GITHUB_CHANGELOG_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 From d1e76554b4e17ef864745f36f16d81433e48bb4a Mon Sep 17 00:00:00 2001 From: Marek Wydmuch Date: Mon, 19 Jun 2023 19:12:45 +0200 Subject: [PATCH 5/9] Improve docs/api/doomGame.md --- docs/api/doomGame.md | 750 ++++++++++++++++++++++--------------------- 1 file changed, 377 insertions(+), 373 deletions(-) diff --git a/docs/api/doomGame.md b/docs/api/doomGame.md index c7ffb3e66..1efc6b18a 100644 --- a/docs/api/doomGame.md +++ b/docs/api/doomGame.md @@ -1,13 +1,18 @@ # DoomGame +DoomGame is the main object of the ViZDoom library, representing a single instance of the Doom game and providing the interface for a single agent/player to interact with the game. The object allows sending actions to the game, getting the game state, etc. + +Here we document all the methods of the DoomGame class and their Python bindings. + + ## Flow control methods: --- -### `init` +### `init` | C++ | `bool init()` | | :-- | :-- | -| Python | `bool init()` | +| Python | `init() -> bool` | Initializes ViZDoom game instance and starts a new episode. After calling this method, the first state from a new episode will be available. @@ -16,11 +21,11 @@ Init returns true when the game was started properly and false otherwise. --- -### `close` +### `close` -| C++ | `void close()` | -| :-- | :-- | -| Python | `void close()` | +| C++ | `void close()` | +| :-- | :-- | +| Python | `close() -> None` | Closes ViZDoom game instance. It is automatically invoked by the destructor. @@ -28,11 +33,11 @@ The game can be initialized again after being closed. --- -### `newEpisode` +### `newEpisode` | C++ | `void newEpisode(std::string recordFilePath = "")` | | :-- | :-- | -| Python | `void new_episode(str recordFilePath = "")` | +| Python | `new_episode(recordFilePath: str = "") -> None` | Changed in 1.1.0 @@ -45,11 +50,11 @@ Then the rest of the players must also call this method to start a new episode. --- -### `replayEpisode` +### `replayEpisode` | C++ | `void replayEpisode(std::string filePath, unsigned int player = 0)` | | :-- | :-- | -| Python | `void replay_episode(str filePath, int player = 0)` | +| Python | `replay_episode(filePath: str, player: int = 0) -> None` | Added in 1.1.0 @@ -59,26 +64,26 @@ After calling this method, the first state from the replay will be available. All rewards, variables, and states are available during the replaying episode. See also: -- [examples/python/record_episodes.py](https://github.com/mwydmuch/ViZDoom/tree/master/examples/python/record_episodes.py) -- [examples/python/record_multiplayer.py](https://github.com/mwydmuch/ViZDoom/tree/master/examples/python/record_multiplayer.py) +- [examples/python/record_episodes.py](https://github.com/Farama-Foundation/ViZDoom/tree/master/examples/python/record_episodes.py) +- [examples/python/record_multiplayer.py](https://github.com/Farama-Foundation/ViZDoom/tree/master/examples/python/record_multiplayer.py) --- -### `isRunning` +### `isRunning` -| C++ | `bool isRunning()` | -| :-- | :-- | -| Python | `bool is_running()` | +| C++ | `bool isRunning()` | +| :-- | :-- | +| Python | `is_running() -> bool` | Checks if the ViZDoom game instance is running. --- -### `isMultiplayerGame` +### `isMultiplayerGame` -| C++ | `bool isMultiplayerGame()` | -| :-- | :-- | -| Python | `bool is_multiplayer_game()` | +| C++ | `bool isMultiplayerGame()` | +| :-- | :-- | +| Python | `is_multiplayer_game() -> bool` | Added in 1.1.2 @@ -86,11 +91,11 @@ Checks if the game is in multiplayer mode. --- -### `isRecordingEpisode` +### `isRecordingEpisode` -| C++ | `bool isRecordingEpisode()` | -| :-- | :-- | -| Python | `bool is_recording_episode()` | +| C++ | `bool isRecordingEpisode()` | +| :-- | :-- | +| Python | `is_recording_episode() -> bool` | Added in 1.1.5 @@ -98,11 +103,11 @@ Checks if the game is in recording mode. --- -### `isReplayingEpisode` +### `isReplayingEpisode` -| C++ | `bool isReplayingEpisode()` | -| :-- | :-- | -| Python | `bool is_replaying_episode()` | +| C++ | `bool isReplayingEpisode()` | +| :-- | :-- | +| Python | `is_replaying_episode() -> bool` | Added in 1.1.5 @@ -110,11 +115,11 @@ Checks if the game is in replaying mode. --- -### `setAction` +### `setAction` -| C++ | `void setAction(std::vector const &actions)` | -| :-- | :-- | -| Python | `void set_action(list actions)` | +| C++ | `void setAction(std::vector const &actions)` | +| :-- | :-- | +| Python | `set_action(actions: list | tuple | ndarray [float]) -> None` | Sets the player's action for the next tics. Each value corresponds to a button specified with [`addAvailableButton`](#addAvailableButton) method @@ -122,11 +127,11 @@ or in the configuration file (in order of appearance). --- -### `advanceAction` +### `advanceAction` | C++ | `void advanceAction(unsigned int tics = 1, bool updateState = true)` | | :-- | :-- | -| Python | `void advance_action(int tics = 1, bool updateState = True)` | +| Python | `advance_action(tics: int = 1, updateState: bool = True) -> None` | Processes a specified number of tics. If `updateState` is set, the state will be updated after the last processed tic and a new reward will be calculated. @@ -135,11 +140,11 @@ If `updateState` is not set, the state will not be updated. --- -### `makeAction` +### `makeAction` | C++ | `double makeAction(std::vector const &actions, unsigned int tics = 1)` | | :-- | :-- | -| Python | `float make_action(list actions, int tics = 1)` | +| Python | `make_action(actions: list | tuple | ndarray [float], tics: int = 1) -> float` | Method combining usability of [`setAction`](#setAction), [`advanceAction`](#advanceAction) and [`getLastReward`](#getLastReward). Sets the player's action for the next tics, processes a specified number of tics, @@ -147,32 +152,32 @@ updates the state and calculates a new reward, which is returned. --- -### `isNewEpisode` +### `isNewEpisode` -| C++ | `bool isNewEpisode()` | -| :-- | :-- | -| Python | `bool is_new_episode()` | +| C++ | `bool isNewEpisode()` | +| :-- | :-- | +| Python | `is_new_episode() -> bool` | Returns true if the current episode is in the initial state - the first state, no actions were performed yet. --- -### `isEpisodeFinished` +### `isEpisodeFinished` -| C++ | `bool isEpisodeFinished()` | -| :-- | :-- | -| Python | `bool is_episode_finished()` | +| C++ | `bool isEpisodeFinished()` | +| :-- | :-- | +| Python | `is_episode_finished() -> bool` | Returns true if the current episode is in the terminal state (is finished). [`makeAction`](#makeAction) and [`advanceAction`](#advanceAction) methods will take no effect after this point (unless [`newEpisode`](#newEpisode) method is called). --- -### `isPlayerDead` +### `isPlayerDead` -| C++ | `bool isPlayerDead()` | -| :-- | :-- | -| Python | `bool is_player_dead()` | +| C++ | `bool isPlayerDead()` | +| :-- | :-- | +| Python | `is_player_dead() -> bool` | Returns true if the player is dead. In singleplayer, the player's death is equivalent to the end of the episode. @@ -180,11 +185,11 @@ In multiplayer, when the player is dead [`respawnPlayer`](#respawnPlayer) method --- -### `respawnPlayer` +### `respawnPlayer` -| C++ | `void respawnPlayer()` | -| :-- | :-- | -| Python | `void respawn_player()` | +| C++ | `void respawnPlayer()` | +| :-- | :-- | +| Python | `respawn_player() -> None` | This method respawns the player after death in multiplayer mode. After calling this method, the first state after the respawn will be available. @@ -194,11 +199,11 @@ See also: --- -### `sendGameCommand` +### `sendGameCommand` | C++ | `void sendGameCommand(std::string cmd)` | | :-- | :-- | -| Python | `void send_game_command(str cmd)` | +| Python | `send_game_command(cmd: str) -> None` | Sends the command to Doom console. It can be used for controlling the game, changing settings, cheats, etc. Some commands will be blocked in some modes. @@ -210,11 +215,11 @@ See also: --- -### `getState` +### `getState` | C++ | `GameStatePtr (std::shared_ptr) GameState getState()` | | :-- | :-- | -| Python | `GameState get_state()` | +| Python | `get_state() -> GameState` | Changed in 1.1.0 @@ -226,11 +231,11 @@ See also: --- -### `getServerState` +### `getServerState` | C++ | `ServerStatePtr (std::shared_ptr) ServerState getServerState()` | | :-- | :-- | -| Python | `ServerState get_state_state()` | +| Python | `get_state_state() -> ServerState` | Added in 1.1.6 @@ -241,11 +246,11 @@ See also: --- -### `getLastAction` +### `getLastAction` | C++ | `std::vector getLastAction()` | | :-- | :-- | -| Python | `list get_last_action()` | +| Python | `get_last_action() -> list` | Returns the last action performed. Each value corresponds to a button added with `[addAvailableButton](#addAvailableButton)` (in order of appearance). @@ -253,21 +258,21 @@ Most useful in `SPECTATOR` mode. --- -### `getEpisodeTime` +### `getEpisodeTime` | C++ | `unsigned int getEpisodeTime()` | | :-- | :-- | -| Python | `int get_episode_time()` | +| Python | `get_episode_time() -> int` | Returns number of current episode tic. --- -### `save` +### `save` | C++ | `void save(std::string filePath)` | | :-- | :-- | -| Python | `void save(str filePath)` | +| Python | `save(filePath: str) -> None` | Added in 1.1.9 @@ -275,11 +280,11 @@ Saves a game's internal state to the file using ZDoom's save game functionality. --- -### `load` +### `load` | C++ | `void load(std::string filePath)` | | :-- | :-- | -| Python | `void load(str filePath)` | +| Python | `load(filePath: str) -> None` | Added in 1.1.9 @@ -289,14 +294,14 @@ Loading the game state does not reset the current episode state, tic counter/time and total reward state keep their values. -## Buttons settings methods +## Buttons settings methods --- -### `getAvailableButtons` +### `getAvailableButtons` | C++ | `std::vector