diff --git a/doc/DoomGame.md b/doc/DoomGame.md
index e53aa8bfa..e8ee8859b 100644
--- a/doc/DoomGame.md
+++ b/doc/DoomGame.md
@@ -530,7 +530,7 @@ See also:
## GameVariables methods
---
-### `getAvailableGameVariable`
+### `getAvailableGameVariables`
| C++ | `std::vector getAvailableGameVariables()` |
| :-- | :-- |
@@ -1542,11 +1542,11 @@ See also:
---
-### `getAudioSamplingRate`
+### `getAudioSamplingRate`
-| C++ | `SamplingRate getAudioSamplingRate()` |
+| C++ | `int getAudioSamplingRate()` |
| :-- | :-- |
-| Python | `SamplingRate get_audio_sampling_rate()` |
+| Python | `int get_audio_sampling_rate()` |
Added in 1.1.9
diff --git a/scripts/create_python_docstrings_from_docs.py b/scripts/create_python_docstrings_from_docs.py
new file mode 100755
index 000000000..481aa8197
--- /dev/null
+++ b/scripts/create_python_docstrings_from_docs.py
@@ -0,0 +1,87 @@
+#!/usr/bin/env python3
+
+import re
+
+
+FILES_TO_PARSE = [
+ {"filepath": "doc/DoomGame.md", "namespace": "DoomGamePython"},
+ {"filepath": "doc/Utilities.md"},
+]
+OUTPUT_FILE = "src/lib_python/ViZDoomDocstrings.h"
+RAW_STRING_ESCAPE_SEQ = "DOCSTRING"
+FUNCTION_HEADER_REGEX = r"^### *<\/a> *`([a-zA-Z]+)` *$"
+LINES_TO_IGNORE_REGEXES = [
+ r"---", # Lines
+ r"^\|.+\|$", # Tables
+ r"^See also:.*$", # See also
+ r"- \[.*\]\(.*\)", # List of links starting with -
+ r"\* \[.*\]\(.*\)", # List of links starting with *
+ r"^Added in .*$", # Added in annotations
+ r"^Changed in .*$", # Changed in annotations
+ r"^Deprecated since .*$", # Deprecated since annotations
+ r"^Removed in .*$", # Removed in annotations
+ r"^Config key: .*$", # Config annotations
+]
+
+
+if __name__ == "__main__":
+ with open(OUTPUT_FILE, "w") as output_file:
+ output_file.write(
+ """
+/*
+ This file is autogenerated by scripts/create_python_docstrings_from_docs.py
+ Do not edit it manually. Edit the Markdown files instead and regenerate it.
+*/
+
+#ifndef __VIZDOOM_DOCSTRINGS_H__
+#define __VIZDOOM_DOCSTRINGS_H__
+
+namespace vizdoom {{
+namespace docstrings {{
+
+"""
+ )
+
+ for file in FILES_TO_PARSE:
+ if "namespace" in file:
+ output_file.write(f"namespace {file['namespace']} {{\n\n")
+
+ with open(file["filepath"]) as f:
+ lines = f.readlines()
+
+ started = False
+ next_docstring = ""
+ for line in lines:
+ # If lines match pattern, extract the function name and arguments
+ match = re.match(FUNCTION_HEADER_REGEX, line)
+ if match:
+ if started:
+ next_docstring = next_docstring.strip()
+ next_docstring += f'){RAW_STRING_ESCAPE_SEQ}";\n\n'
+ output_file.write(next_docstring)
+
+ next_docstring = ""
+ function_name = match.group(1)
+ output_file.write(
+ f' const char *{function_name} = R"{RAW_STRING_ESCAPE_SEQ}('
+ )
+ started = True
+
+ elif started:
+ # Filter out some lines
+ if not any(re.match(r, line) for r in LINES_TO_IGNORE_REGEXES):
+ next_docstring += line
+
+ if started:
+ output_file.write(f'){RAW_STRING_ESCAPE_SEQ}";\n\n')
+
+ if "namespace" in file:
+ output_file.write(f"}} // namespace {file['namespace']}\n\n")
+
+ output_file.write(
+ """
+} // namespace docstrings
+} // namespace vizdoom
+#endif
+"""
+ )
diff --git a/src/lib_python/CMakeLists.txt b/src/lib_python/CMakeLists.txt
index f5b39194f..07d83e79b 100644
--- a/src/lib_python/CMakeLists.txt
+++ b/src/lib_python/CMakeLists.txt
@@ -42,6 +42,7 @@ configure_file(
)
set(VIZDOOM_PYTHON_SOURCES
+ ${VIZDOOM_PYTHON_SRC_DIR}/ViZDoomDocstrings.h
${VIZDOOM_PYTHON_SRC_DIR}/ViZDoomGamePython.h
${VIZDOOM_PYTHON_SRC_DIR}/ViZDoomGamePython.cpp
${VIZDOOM_PYTHON_SRC_DIR}/ViZDoomPythonModule.cpp)
diff --git a/src/lib_python/ViZDoomDocstrings.h b/src/lib_python/ViZDoomDocstrings.h
new file mode 100644
index 000000000..3343903cb
--- /dev/null
+++ b/src/lib_python/ViZDoomDocstrings.h
@@ -0,0 +1,413 @@
+
+/*
+ This file is autogenerated by scripts/create_python_docstrings_from_docs.py
+ Do not edit it manually. Edit the Markdown files instead and regenerate it.
+*/
+
+#ifndef __VIZDOOM_DOCSTRINGS_H__
+#define __VIZDOOM_DOCSTRINGS_H__
+
+#include
+
+namespace vizdoom {
+namespace docstrings {
+
+namespace DoomGamePython {
+
+ const char *init = R"DOCSTRING(Initializes ViZDoom game instance and starts a new episode.
+After calling this method, the first state from a new episode will be available.
+Some configuration options cannot be changed after calling this method.
+Init returns true when the game was started properly and false otherwise.)DOCSTRING";
+
+ const char *close = R"DOCSTRING(Closes ViZDoom game instance.
+It is automatically invoked by the destructor.
+The game can be initialized again after being closed.)DOCSTRING";
+
+ const char *newEpisode = R"DOCSTRING(Initializes a new episode. The state of an environment is completely restarted (all variables and rewards are reset to their initial values).
+After calling this method, the first state from the new episode will be available.
+If the `recordFilePath` is not empty, the new episode will be recorded to this file (as a Doom lump).
+
+In a multiplayer game, the host can call this method to finish the game.
+Then the rest of the players must also call this method to start a new episode.)DOCSTRING";
+
+ const char *replayEpisode = R"DOCSTRING(Replays a recorded episode from the given file using the perspective of the specified player.
+Players are numbered from 1, `player` equal to 0 results in replaying the demo using the perspective of the default player in the recording file.
+After calling this method, the first state from the replay will be available.
+All rewards, variables, and states are available during the replaying episode.)DOCSTRING";
+
+ const char *isRunning = R"DOCSTRING(Checks if the ViZDoom game instance is running.)DOCSTRING";
+
+ const char *isMultiplayerGame = R"DOCSTRING(Checks if the game is in multiplayer mode.)DOCSTRING";
+
+ const char *isRecordingEpisode = R"DOCSTRING(Checks if the game is in recording mode.)DOCSTRING";
+
+ const char *isReplayingEpisode = R"DOCSTRING(Checks if the game is in replaying mode.)DOCSTRING";
+
+ const char *setAction = R"DOCSTRING(Sets the player's action for the next tics.
+Each value corresponds to a button specified with [`addAvailableButton`](#addAvailableButton) method
+or in the configuration file (in order of appearance).)DOCSTRING";
+
+ const char *advanceAction = R"DOCSTRING(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.
+To get the new state, use `getState` and to get the new reward use `getLastReward`.
+If `updateState` is not set, the state will not be updated.)DOCSTRING";
+
+ const char *makeAction = R"DOCSTRING(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,
+updates the state and calculates a new reward, which is returned.)DOCSTRING";
+
+ const char *isNewEpisode = R"DOCSTRING(Returns true if the current episode is in the initial state - the first state, no actions were performed yet.)DOCSTRING";
+
+ const char *isEpisodeFinished = R"DOCSTRING(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).)DOCSTRING";
+
+ const char *isPlayerDead = R"DOCSTRING(Returns true if the player is dead.
+In singleplayer, the player's death is equivalent to the end of the episode.
+In multiplayer, when the player is dead [`respawnPlayer`](#respawnPlayer) method can be called.)DOCSTRING";
+
+ const char *respawnPlayer = R"DOCSTRING(This method respawns the player after death in multiplayer mode.
+After calling this method, the first state after the respawn will be available.)DOCSTRING";
+
+ const char *sendGameCommand = R"DOCSTRING(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.)DOCSTRING";
+
+ const char *getState = R"DOCSTRING(Returns [`GameState`](Types.md#gamestate) object with the current game state.
+If the current episode is finished, `nullptr/null/None` will be returned.)DOCSTRING";
+
+ const char *getServerState = R"DOCSTRING(Returns [`ServerState`](Types.md#serverstate) object with the current server state.)DOCSTRING";
+
+ const char *getLastAction = R"DOCSTRING(Returns the last action performed.
+Each value corresponds to a button added with `[addAvailableButton](#addAvailableButton)` (in order of appearance).
+Most useful in `SPECTATOR` mode.)DOCSTRING";
+
+ const char *getEpisodeTime = R"DOCSTRING(Returns number of current episode tic.)DOCSTRING";
+
+ const char *save = R"DOCSTRING(Saves a game's internal state to the file using ZDoom's save game functionality.)DOCSTRING";
+
+ const char *load = R"DOCSTRING(Loads a game's internal state from the file using ZDoom's load game functionality.
+A new state is available after loading.
+Loading the game state does not reset the current episode state,
+tic counter/time and total reward state keep their values.
+
+
+## Buttons settings methods)DOCSTRING";
+
+ const char *getAvailableButtons = R"DOCSTRING(Returns the list of available `Buttons`.)DOCSTRING";
+
+ const char *setAvailableButtons = R"DOCSTRING(Set given list of `Button`s (e.g. `TURN_LEFT`, `MOVE_FORWARD`) as available `Buttons`,)DOCSTRING";
+
+ const char *addAvailableButton = R"DOCSTRING(Add [`Button`](Types.md#button) type (e.g. `TURN_LEFT`, `MOVE_FORWARD`) to available `Buttons` and sets the maximum allowed, absolute value for the specified button.
+If the given button has already been added, it will not be added again, but the maximum value is overridden.)DOCSTRING";
+
+ const char *clearAvailableButtons = R"DOCSTRING(Clears all available `Buttons` added so far.)DOCSTRING";
+
+ const char *getAvailableButtonsSize = R"DOCSTRING(Returns the number of available `Buttons`.)DOCSTRING";
+
+ const char *setButtonMaxValue = R"DOCSTRING(Sets the maximum allowed absolute value for the specified button.
+Setting the maximum value to 0 results in no constraint at all (infinity).
+This method makes sense only for delta buttons.
+The constraints limit applies in all Modes.)DOCSTRING";
+
+ const char *getButtonMaxValue = R"DOCSTRING(Returns the maximum allowed absolute value for the specified button.)DOCSTRING";
+
+ const char *getButton = R"DOCSTRING(Returns the current state of the specified button (`ATTACK`, `USE` etc.).
+
+
+
+## GameVariables methods)DOCSTRING";
+
+ const char *getAvailableGameVariables = R"DOCSTRING(Returns the list of available `GameVariables`.)DOCSTRING";
+
+ const char *setAvailableGameVariables = R"DOCSTRING(Set list of [`GameVariable`](Types.md#gamevariable) as available `GameVariables` in the [`GameState`](Types.md#gamestate) returned by `getState` method.)DOCSTRING";
+
+ const char *addAvailableGameVariable = R"DOCSTRING(Adds the specified [`GameVariable`](Types.md#gamevariable) to the list of available game variables (e.g. `HEALTH`, `AMMO1`, `ATTACK_READY`) in the [`GameState`](Types.md#gamestate) returned by `getState` method.)DOCSTRING";
+
+ const char *clearAvailableGameVariables = R"DOCSTRING(Clears the list of available `GameVariables` that are included in the GameState returned by [`getState`](#getState) method.)DOCSTRING";
+
+ const char *getAvailableGameVariablesSize = R"DOCSTRING(Returns the number of available `GameVariables`.)DOCSTRING";
+
+ const char *getGameVariable = R"DOCSTRING(Returns the current value of the specified game variable (`HEALTH`, `AMMO1` etc.).
+The specified game variable does not need to be among available game variables (included in the state).
+It could be used for e.g. shaping. Returns 0 in case of not finding given `GameVariable`.
+
+
+
+## Game Arguments methods)DOCSTRING";
+
+ const char *addGameArgs = R"DOCSTRING(Adds a custom argument that will be passed to ViZDoom process during initialization.
+Useful for changing additional game settings.)DOCSTRING";
+
+ const char *clearGameArgs = R"DOCSTRING(Clears all arguments previously added with [`addGameArgs`](#addGameArgs) method.
+
+
+## Reward methods)DOCSTRING";
+
+ const char *getLivingReward = R"DOCSTRING(Returns the reward granted to the player after every tic.)DOCSTRING";
+
+ const char *setLivingReward = R"DOCSTRING(Sets the reward granted to the player after every tic. A negative value is also allowed.
+
+Default value: 0)DOCSTRING";
+
+ const char *getDeathPenalty = R"DOCSTRING(Returns the penalty for the player's death.)DOCSTRING";
+
+ const char *setDeathPenalty = R"DOCSTRING(Sets a penalty for the player's death. Note that in case of a negative value, the player will be rewarded upon dying.
+
+Default value: 0)DOCSTRING";
+
+ const char *getLastReward = R"DOCSTRING(Returns a reward granted after the last update of state.)DOCSTRING";
+
+ const char *getTotalReward = R"DOCSTRING(Returns the sum of all rewards gathered in the current episode.
+
+
+## General game setting methods)DOCSTRING";
+
+ const char *loadConfig = R"DOCSTRING(Loads configuration (resolution, available buttons, game variables etc.) from a configuration file.
+In case of multiple invocations, older configurations will be overwritten by the recent ones.
+Overwriting does not involve resetting to default values. Thus only overlapping parameters will be changed.
+The method returns true if the whole configuration file was correctly read and applied,
+false if the file contained errors.)DOCSTRING";
+
+ const char *getMode = R"DOCSTRING(Returns current mode.)DOCSTRING";
+
+ const char *setMode = R"DOCSTRING(Sets mode (`PLAYER`, `SPECTATOR`, `ASYNC_PLAYER`, `ASYNC_SPECTATOR`) in which the game will be running.
+
+Default value: `PLAYER`.)DOCSTRING";
+
+ const char *getTicrate = R"DOCSTRING(Returns current ticrate.)DOCSTRING";
+
+ const char *setTicrate = R"DOCSTRING(Sets ticrate for ASNYC Modes - number of logic tics executed per second.
+The default Doom ticrate is 35. This value will play a game at normal speed.
+
+Default value: 35 (default Doom ticrate).)DOCSTRING";
+
+ const char *setViZDoomPath = R"DOCSTRING(Sets path to the ViZDoom engine executable vizdoom.
+
+Default value: "{vizdoom.so location}/{vizdoom or vizdoom.exe (on Windows)}".)DOCSTRING";
+
+ const char *setDoomGamePath = R"DOCSTRING(Sets the path to the Doom engine based game file (wad format).
+If not used DoomGame will look for doom2.wad and freedoom2.wad (in that order) in the directory of ViZDoom's installation (where vizdoom.so/pyd is).
+
+Default value: "{vizdoom.so location}/{doom2.wad, doom.wad, freedoom2.wad or freedoom.wad}")DOCSTRING";
+
+ const char *setDoomScenarioPath = R"DOCSTRING(Sets the path to an additional scenario file (wad format).
+If not provided, the default Doom single-player maps will be loaded.
+
+Default value: "")DOCSTRING";
+
+ const char *setDoomMap = R"DOCSTRING(Sets the map name to be used.
+
+Default value: "map01", if set to empty "map01" will be used.)DOCSTRING";
+
+ const char *setDoomSkill = R"DOCSTRING(Sets Doom game difficulty level, which is called skill in Doom.
+The higher the skill, the harder the game becomes.
+Skill level affects monsters' aggressiveness, monsters' speed, weapon damage, ammunition quantities, etc.
+Takes effect from the next episode.
+
+- 1 - VERY EASY, “I'm Too Young to Die” in Doom.
+- 2 - EASY, “Hey, Not Too Rough" in Doom.
+- 3 - NORMAL, “Hurt Me Plenty” in Doom.
+- 4 - HARD, “Ultra-Violence” in Doom.
+- 5 - VERY HARD, “Nightmare!” in Doom.
+
+Default value: 3)DOCSTRING";
+
+ const char *setDoomConfigPath = R"DOCSTRING(Sets the path for ZDoom's configuration file.
+The file is responsible for the configuration of the ZDoom engine itself.
+If it does not exist, it will be created after the `vizdoom` executable is run.
+This method is not needed for most of the tasks and is added for the convenience of users with hacking tendencies.
+
+Default value: "", if left empty "_vizdoom.ini" will be used.)DOCSTRING";
+
+ const char *getSeed = R"DOCSTRING(Return ViZDoom's seed.)DOCSTRING";
+
+ const char *setSeed = R"DOCSTRING(Sets the seed of the ViZDoom's RNG that generates seeds (initial state) for episodes.
+
+Default value: randomized in constructor)DOCSTRING";
+
+ const char *getEpisodeStartTime = R"DOCSTRING(Returns start delay of every episode in tics.)DOCSTRING";
+
+ const char *setEpisodeStartTime = R"DOCSTRING(Sets start delay of every episode in tics.
+Every episode will effectively start (from the user's perspective) after the provided number of tics.
+
+Default value: 1)DOCSTRING";
+
+ const char *getEpisodeTimeout = R"DOCSTRING(Returns the number of tics after which the episode will be finished.)DOCSTRING";
+
+ const char *setEpisodeTimeout = R"DOCSTRING(Sets the number of tics after which the episode will be finished. 0 will result in no timeout.
+
+
+
+## Output/rendering setting methods)DOCSTRING";
+
+ const char *setScreenResolution = R"DOCSTRING(Sets the screen resolution. ZDoom engine supports only specific resolutions.
+Supported resolutions are part of ScreenResolution enumeration (e.g., `RES_320X240`, `RES_640X480`, `RES_1920X1080`).
+The buffers, as well as the content of ViZDoom's display window, will be affected.
+
+Default value: `RES_320X240`)DOCSTRING";
+
+ const char *getScreenFormat = R"DOCSTRING(Returns the format of the screen buffer and the automap buffer.)DOCSTRING";
+
+ const char *setScreenFormat = R"DOCSTRING(Sets the format of the screen buffer and the automap buffer.
+Supported formats are defined in `ScreenFormat` enumeration type (e.g. `CRCGCB`, `RGB24`, `GRAY8`).
+The format change affects only the buffers, so it will not have any effect on the content of ViZDoom's display window.
+
+Default value: `CRCGCB`)DOCSTRING";
+
+ const char *isDepthBufferEnabled = R"DOCSTRING(Returns true if the depth buffer is enabled.)DOCSTRING";
+
+ const char *setDepthBufferEnabled = R"DOCSTRING(Enables rendering of the depth buffer, it will be available in the state.
+Depth buffer will contain noise if `viz_nocheat` is enabled.
+
+Default value: false)DOCSTRING";
+
+ const char *isLabelsBufferEnabled = R"DOCSTRING(Returns true if the labels buffer is enabled.)DOCSTRING";
+
+ const char *setLabelsBufferEnabled = R"DOCSTRING(Enables rendering of the labels buffer, it will be available in the state with the vector of `Label`s.
+LabelsBuffer will contain noise if `viz_nocheat` is enabled.
+
+Default value: false)DOCSTRING";
+
+ const char *isAutomapBufferEnabled = R"DOCSTRING(Returns true if the automap buffer is enabled.)DOCSTRING";
+
+ const char *setAutomapBufferEnabled = R"DOCSTRING(Enables rendering of the automap buffer, it will be available in the state.
+
+Default value: false)DOCSTRING";
+
+ const char *setAutomapMode = R"DOCSTRING(Sets the automap mode (`NORMAL`, `WHOLE`, `OBJECTS`, `OBJECTS_WITH_SIZE`),
+which determines what will be visible on it.
+
+Default value: `NORMAL`)DOCSTRING";
+
+ const char *setAutomapRotate = R"DOCSTRING(Determine if the automap will be rotating with the player.
+If false, north always will be at the top of the buffer.
+
+Default value: false)DOCSTRING";
+
+ const char *setAutomapRenderTextures = R"DOCSTRING(Determine if the automap will be textured, showing the floor textures.
+
+Default value: true)DOCSTRING";
+
+ const char *setRenderHud = R"DOCSTRING(Determine if the hud will be rendered in the game.
+
+Default value: false)DOCSTRING";
+
+ const char *setRenderMinimalHud = R"DOCSTRING(Determine if the minimalistic version of the hud will be rendered instead of the full hud.
+
+Default value: false)DOCSTRING";
+
+ const char *setRenderWeapon = R"DOCSTRING(Determine if the weapon held by the player will be rendered in the game.
+
+Default value: true)DOCSTRING";
+
+ const char *setRenderCrosshair = R"DOCSTRING(Determine if the crosshair will be rendered in the game.
+
+Default value: false)DOCSTRING";
+
+ const char *setRenderDecals = R"DOCSTRING(Determine if the decals (marks on the walls) will be rendered in the game.
+
+Default value: true)DOCSTRING";
+
+ const char *setRenderParticles = R"DOCSTRING(Determine if the particles will be rendered in the game.
+
+Default value: true)DOCSTRING";
+
+ const char *setRenderEffectsSprites = R"DOCSTRING(Determine if some effects sprites (gun puffs, blood splats etc.) will be rendered in the game.
+
+Default value: true)DOCSTRING";
+
+ const char *setRenderMessages = R"DOCSTRING(Determine if in-game messages (information about pickups, kills, etc.) will be rendered in the game.
+
+Default value: false)DOCSTRING";
+
+ const char *setRenderCorpses = R"DOCSTRING(Determine if actors' corpses will be rendered in the game.
+
+Default value: true)DOCSTRING";
+
+ const char *setRenderScreenFlashes = R"DOCSTRING(Determine if the screen flash effect upon taking damage or picking up items will be rendered in the game.
+
+Default value: true)DOCSTRING";
+
+ const char *setRenderAllFrames = R"DOCSTRING(Determine if all frames between states will be rendered (when skip greater than 1 is used).
+Allows smooth preview but can reduce performance.
+It only makes sense to use it if the window is visible.
+
+Default value: false)DOCSTRING";
+
+ const char *setWindowVisible = R"DOCSTRING(Determines if ViZDoom's window will be visible.
+ViZDoom with window disabled can be used on Linux systems without X Server.
+
+Default value: false)DOCSTRING";
+
+ const char *setConsoleEnabled = R"DOCSTRING(Determines if ViZDoom's console output will be enabled.
+
+Default value: false)DOCSTRING";
+
+ const char *setSoundEnabled = R"DOCSTRING(Determines if ViZDoom's sound will be played.
+
+Default value: false)DOCSTRING";
+
+ const char *getScreenWidth = R"DOCSTRING(Returns game's screen width - width of all buffers.)DOCSTRING";
+
+ const char *getScreenHeight = R"DOCSTRING(Returns game's screen height - height of all buffers.)DOCSTRING";
+
+ const char *getScreenChannels = R"DOCSTRING(Returns number of channels in screen buffer and map buffer (depth and labels buffer always have one channel).)DOCSTRING";
+
+ const char *getScreenPitch = R"DOCSTRING(Returns size in bytes of one row in screen buffer and map buffer.)DOCSTRING";
+
+ const char *getScreenSize = R"DOCSTRING(Returns size in bytes of screen buffer and map buffer.)DOCSTRING";
+
+ const char *isObjectsInfoEnabled = R"DOCSTRING(Returns true if the objects information is enabled.)DOCSTRING";
+
+ const char *setObjectsInfoEnabled = R"DOCSTRING(Enables information about all objects present in the current episode/level.
+It will be available in the state.
+
+Default value: false)DOCSTRING";
+
+ const char *isSectorsInfoEnabled = R"DOCSTRING(Returns true if the information about sectors is enabled.)DOCSTRING";
+
+ const char *setSectorsInfoEnabled = R"DOCSTRING(Enables information about all sectors (map layout) present in the current episode/level.
+It will be available in the state.
+
+Default value: false)DOCSTRING";
+
+ const char *isAudioBufferEnabled = R"DOCSTRING(Returns true if the audio buffer is enabled.)DOCSTRING";
+
+ const char *setAudioBufferEnabled = R"DOCSTRING(Returns true if the audio buffer is enabled.
+
+Default value: false)DOCSTRING";
+
+ const char *getAudioSamplingRate = R"DOCSTRING(Returns the sampling rate of the audio buffer.)DOCSTRING";
+
+ const char *setAudioSamplingRate = R"DOCSTRING(Sets the sampling rate of the audio buffer.
+
+Default value: false)DOCSTRING";
+
+ const char *getAudioBufferSize = R"DOCSTRING(Returns the size of the audio buffer.)DOCSTRING";
+
+ const char *setAudioBufferSize = R"DOCSTRING()DOCSTRING";
+
+} // namespace DoomGamePython
+
+ const char *doomTicsToMs = R"DOCSTRING(Calculates how many tics will be made during given number of milliseconds.)DOCSTRING";
+
+ const char *msToDoomTics = R"DOCSTRING(Calculates the number of milliseconds that will pass during specified number of tics.)DOCSTRING";
+
+ const char *doomTicsToSec = R"DOCSTRING(Calculates how many tics will be made during given number of seconds.)DOCSTRING";
+
+ const char *secToDoomTics = R"DOCSTRING(Calculates the number of seconds that will pass during specified number of tics.)DOCSTRING";
+
+ const char *doomFixedToDouble = R"DOCSTRING(Converts Doom's fixed point numeral to a floating point value.
+
+- Types: `User variables` in `GameVariables`
+
+Python aliases (added in 1.1):
+`float doom_fixed_to_float(int / float doomFixed)`)DOCSTRING";
+
+ const char *isBinaryButton = R"DOCSTRING(Returns true if button is binary button.)DOCSTRING";
+
+ const char *isDeltaButton = R"DOCSTRING()DOCSTRING";
+
+
+} // namespace docstrings
+} // namespace vizdoom
+#endif
diff --git a/src/lib_python/ViZDoomPythonModule.cpp b/src/lib_python/ViZDoomPythonModule.cpp
index 5b812b420..bfb1bdf79 100644
--- a/src/lib_python/ViZDoomPythonModule.cpp
+++ b/src/lib_python/ViZDoomPythonModule.cpp
@@ -24,6 +24,7 @@
#include "ViZDoom.h"
#include "ViZDoomGamePython.h"
#include "ViZDoomVersion.h"
+#include "ViZDoomDocstrings.h"
#include
#include
@@ -75,11 +76,11 @@ PYBIND11_MODULE(vizdoom, vz){
#define ENUM_CLASS_VAL_2_PYT(c, v) .value( #v , c::v )
/* .value("VALUE", class::VALUE) */
- #define FUNC_2_PYT(f) vz.def( #f , f )
- /* vz.def("function", function) */
+ #define FUNC_2_PYT(n, f) vz.def( n , f , docstrings::f )
+ /* vz.def("name", function, docstrings::function) */
- #define CLASS_FUNC_2_PYT(c, f) .def( #f , &c::f )
- /* .def("function", &class::function) */
+ #define CLASS_FUNC_2_PYT(n, cf) .def( n , &cf , docstrings::cf )
+ /* .def("name", &class::function, docstrings::class::function) */
/* Consts */
@@ -611,148 +612,148 @@ PYBIND11_MODULE(vizdoom, vz){
pyb::class_(vz, "DoomGame")
.def(pyb::init<>())
- .def("init", &DoomGamePython::init)
- .def("load_config", &DoomGamePython::loadConfig)
- .def("close", &DoomGamePython::close)
- .def("is_running", &DoomGamePython::isRunning)
- .def("is_multiplayer_game", &DoomGamePython::isMultiplayerGame)
- .def("is_recording_episode", &DoomGamePython::isRecordingEpisode)
- .def("is_replaying_episode", &DoomGamePython::isReplayingEpisode)
- .def("new_episode", &DoomGamePython::newEpisode_)
- .def("new_episode", &DoomGamePython::newEpisode_str)
- .def("replay_episode", &DoomGamePython::replayEpisode_str)
- .def("replay_episode", &DoomGamePython::replayEpisode_str_int)
- .def("is_episode_finished", &DoomGamePython::isEpisodeFinished)
- .def("is_new_episode", &DoomGamePython::isNewEpisode)
- .def("is_player_dead", &DoomGamePython::isPlayerDead)
- .def("respawn_player", &DoomGamePython::respawnPlayer)
- .def("set_action", &DoomGamePython::setAction)
- .def("make_action", &DoomGamePython::makeAction_list)
- .def("make_action", &DoomGamePython::makeAction_list_int)
- .def("advance_action", &DoomGamePython::advanceAction_)
- .def("advance_action", &DoomGamePython::advanceAction_int)
- .def("advance_action", &DoomGamePython::advanceAction_int_bool)
- .def("save", &DoomGamePython::save)
- .def("load", &DoomGamePython::load)
-
- .def("get_state", &DoomGamePython::getState, pyb::return_value_policy::take_ownership)
- .def("get_server_state", &DoomGamePython::getServerState, pyb::return_value_policy::take_ownership)
-
- .def("get_game_variable", &DoomGamePython::getGameVariable)
- .def("get_button", &DoomGamePython::getButton)
-
- .def("get_living_reward", &DoomGamePython::getLivingReward)
- .def("set_living_reward", &DoomGamePython::setLivingReward)
-
- .def("get_death_penalty", &DoomGamePython::getDeathPenalty)
- .def("set_death_penalty", &DoomGamePython::setDeathPenalty)
-
- .def("get_last_reward", &DoomGamePython::getLastReward)
- .def("get_total_reward", &DoomGamePython::getTotalReward)
-
- .def("get_last_action", &DoomGamePython::getLastAction)
-
- .def("get_available_game_variables", &DoomGamePython::getAvailableGameVariables)
- .def("set_available_game_variables", &DoomGamePython::setAvailableGameVariables)
- .def("add_available_game_variable", &DoomGamePython::addAvailableGameVariable)
- .def("clear_available_game_variables", &DoomGamePython::clearAvailableGameVariables)
- .def("get_available_game_variables_size", &DoomGamePython::getAvailableGameVariablesSize)
-
- .def("get_available_buttons", &DoomGamePython::getAvailableButtons)
- .def("set_available_buttons", &DoomGamePython::setAvailableButtons)
- .def("add_available_button", &DoomGamePython::addAvailableButton_btn)
- .def("add_available_button", &DoomGamePython::addAvailableButton_btn_double)
- .def("clear_available_buttons", &DoomGamePython::clearAvailableButtons)
- .def("get_available_buttons_size", &DoomGamePython::getAvailableButtonsSize)
- .def("set_button_max_value", &DoomGamePython::setButtonMaxValue)
- .def("get_button_max_value", &DoomGamePython::getButtonMaxValue)
-
- .def("add_game_args", &DoomGamePython::addGameArgs)
- .def("clear_game_args", &DoomGamePython::clearGameArgs)
-
- .def("send_game_command", &DoomGamePython::sendGameCommand)
-
- .def("get_mode", &DoomGamePython::getMode)
- .def("set_mode", &DoomGamePython::setMode)
-
- .def("get_ticrate", &DoomGamePython::getTicrate)
- .def("set_ticrate", &DoomGamePython::setTicrate)
-
- .def("set_vizdoom_path", &DoomGamePython::setViZDoomPath)
- .def("set_doom_game_path", &DoomGamePython::setDoomGamePath)
- .def("set_doom_scenario_path", &DoomGamePython::setDoomScenarioPath)
- .def("set_doom_map", &DoomGamePython::setDoomMap)
- .def("set_doom_skill", &DoomGamePython::setDoomSkill)
- .def("set_doom_config_path", &DoomGamePython::setDoomConfigPath)
-
- .def("get_seed", &DoomGamePython::getSeed)
- .def("set_seed", &DoomGamePython::setSeed)
-
- .def("get_episode_start_time", &DoomGamePython::getEpisodeStartTime)
- .def("set_episode_start_time", &DoomGamePython::setEpisodeStartTime)
- .def("get_episode_timeout", &DoomGamePython::getEpisodeTimeout)
- .def("set_episode_timeout", &DoomGamePython::setEpisodeTimeout)
- .def("get_episode_time", &DoomGamePython::getEpisodeTime)
-
- .def("set_console_enabled",&DoomGamePython::setConsoleEnabled)
- .def("set_sound_enabled",&DoomGamePython::setSoundEnabled)
-
- .def("is_audio_buffer_enabled",&DoomGamePython::isAudioBufferEnabled)
- .def("set_audio_buffer_enabled",&DoomGamePython::setAudioBufferEnabled)
- .def("get_audio_sampling_rate",&DoomGamePython::getAudioSamplingRate)
- .def("set_audio_sampling_rate",&DoomGamePython::setAudioSamplingRate)
- .def("get_audio_buffer_size",&DoomGamePython::getAudioBufferSize)
- .def("set_audio_buffer_size",&DoomGamePython::setAudioBufferSize)
-
- .def("set_screen_resolution", &DoomGamePython::setScreenResolution)
- .def("set_screen_format", &DoomGamePython::setScreenFormat)
-
- .def("is_depth_buffer_enabled", &DoomGamePython::isDepthBufferEnabled)
- .def("set_depth_buffer_enabled", &DoomGamePython::setDepthBufferEnabled)
- .def("is_labels_buffer_enabled", &DoomGamePython::isLabelsBufferEnabled)
- .def("set_labels_buffer_enabled", &DoomGamePython::setLabelsBufferEnabled)
- .def("is_automap_buffer_enabled", &DoomGamePython::isAutomapBufferEnabled)
- .def("set_automap_buffer_enabled", &DoomGamePython::setAutomapBufferEnabled)
- .def("set_automap_mode", &DoomGamePython::setAutomapMode)
- .def("set_automap_rotate", &DoomGamePython::setAutomapRotate)
- .def("set_automap_render_textures", &DoomGamePython::setAutomapRenderTextures)
- .def("is_objects_info_enabled", &DoomGamePython::isObjectsInfoEnabled)
- .def("set_objects_info_enabled", &DoomGamePython::setObjectsInfoEnabled)
- .def("is_sectors_info_enabled", &DoomGamePython::isSectorsInfoEnabled)
- .def("set_sectors_info_enabled", &DoomGamePython::setSectorsInfoEnabled)
-
- .def("set_render_hud", &DoomGamePython::setRenderHud)
- .def("set_render_minimal_hud", &DoomGamePython::setRenderMinimalHud)
- .def("set_render_weapon", &DoomGamePython::setRenderWeapon)
- .def("set_render_crosshair", &DoomGamePython::setRenderCrosshair)
- .def("set_render_decals", &DoomGamePython::setRenderDecals)
- .def("set_render_particles", &DoomGamePython::setRenderParticles)
- .def("set_render_effects_sprites", &DoomGamePython::setRenderEffectsSprites)
- .def("set_render_messages", &DoomGamePython::setRenderMessages)
- .def("set_render_corpses", &DoomGamePython::setRenderCorpses)
- .def("set_render_screen_flashes", &DoomGamePython::setRenderScreenFlashes)
- .def("set_render_all_frames", &DoomGamePython::setRenderAllFrames)
- .def("set_window_visible", &DoomGamePython::setWindowVisible)
- .def("get_screen_width", &DoomGamePython::getScreenWidth)
- .def("get_screen_height", &DoomGamePython::getScreenHeight)
- .def("get_screen_channels", &DoomGamePython::getScreenChannels)
- .def("get_screen_size", &DoomGamePython::getScreenSize)
- .def("get_screen_pitch", &DoomGamePython::getScreenPitch)
- .def("get_screen_format", &DoomGamePython::getScreenFormat);
+ CLASS_FUNC_2_PYT("init", DoomGamePython::init)
+ CLASS_FUNC_2_PYT("load_config", DoomGamePython::loadConfig)
+ CLASS_FUNC_2_PYT("close", DoomGamePython::close)
+ CLASS_FUNC_2_PYT("is_running", DoomGamePython::isRunning)
+ CLASS_FUNC_2_PYT("is_multiplayer_game", DoomGamePython::isMultiplayerGame)
+ CLASS_FUNC_2_PYT("is_recording_episode", DoomGamePython::isRecordingEpisode)
+ CLASS_FUNC_2_PYT("is_replaying_episode", DoomGamePython::isReplayingEpisode)
+ .def("new_episode", &DoomGamePython::newEpisode_, docstrings::DoomGamePython::newEpisode)
+ .def("new_episode", &DoomGamePython::newEpisode_str, docstrings::DoomGamePython::newEpisode)
+ .def("replay_episode", &DoomGamePython::replayEpisode_str, docstrings::DoomGamePython::replayEpisode)
+ .def("replay_episode", &DoomGamePython::replayEpisode_str_int, docstrings::DoomGamePython::replayEpisode)
+ CLASS_FUNC_2_PYT("is_episode_finished", DoomGamePython::isEpisodeFinished)
+ CLASS_FUNC_2_PYT("is_new_episode", DoomGamePython::isNewEpisode)
+ CLASS_FUNC_2_PYT("is_player_dead", DoomGamePython::isPlayerDead)
+ CLASS_FUNC_2_PYT("respawn_player", DoomGamePython::respawnPlayer)
+ CLASS_FUNC_2_PYT("set_action", DoomGamePython::setAction)
+ .def("make_action", &DoomGamePython::makeAction_list, docstrings::DoomGamePython::makeAction)
+ .def("make_action", &DoomGamePython::makeAction_list_int, docstrings::DoomGamePython::makeAction)
+ .def("advance_action", &DoomGamePython::advanceAction_, docstrings::DoomGamePython::advanceAction)
+ .def("advance_action", &DoomGamePython::advanceAction_int, docstrings::DoomGamePython::advanceAction)
+ .def("advance_action", &DoomGamePython::advanceAction_int_bool, docstrings::DoomGamePython::advanceAction)
+ CLASS_FUNC_2_PYT("save", DoomGamePython::save)
+ CLASS_FUNC_2_PYT("load", DoomGamePython::load)
+
+ .def("get_state", &DoomGamePython::getState, pyb::return_value_policy::take_ownership, docstrings::DoomGamePython::getState)
+ .def("get_server_state", &DoomGamePython::getServerState, pyb::return_value_policy::take_ownership, docstrings::DoomGamePython::getServerState)
+
+ CLASS_FUNC_2_PYT("get_game_variable", DoomGamePython::getGameVariable)
+ CLASS_FUNC_2_PYT("get_button", DoomGamePython::getButton)
+
+ CLASS_FUNC_2_PYT("get_living_reward", DoomGamePython::getLivingReward)
+ CLASS_FUNC_2_PYT("set_living_reward", DoomGamePython::setLivingReward)
+
+ CLASS_FUNC_2_PYT("get_death_penalty", DoomGamePython::getDeathPenalty)
+ CLASS_FUNC_2_PYT("set_death_penalty", DoomGamePython::setDeathPenalty)
+
+ CLASS_FUNC_2_PYT("get_last_reward", DoomGamePython::getLastReward)
+ CLASS_FUNC_2_PYT("get_total_reward", DoomGamePython::getTotalReward)
+
+ CLASS_FUNC_2_PYT("get_last_action", DoomGamePython::getLastAction)
+
+ CLASS_FUNC_2_PYT("get_available_game_variables", DoomGamePython::getAvailableGameVariables)
+ CLASS_FUNC_2_PYT("set_available_game_variables", DoomGamePython::setAvailableGameVariables)
+ CLASS_FUNC_2_PYT("add_available_game_variable", DoomGamePython::addAvailableGameVariable)
+ CLASS_FUNC_2_PYT("clear_available_game_variables", DoomGamePython::clearAvailableGameVariables)
+ CLASS_FUNC_2_PYT("get_available_game_variables_size", DoomGamePython::getAvailableGameVariablesSize)
+
+ CLASS_FUNC_2_PYT("get_available_buttons", DoomGamePython::getAvailableButtons)
+ CLASS_FUNC_2_PYT("set_available_buttons", DoomGamePython::setAvailableButtons)
+ .def("add_available_button", &DoomGamePython::addAvailableButton_btn, docstrings::DoomGamePython::addAvailableButton)
+ .def("add_available_button", &DoomGamePython::addAvailableButton_btn_double, docstrings::DoomGamePython::addAvailableButton)
+ CLASS_FUNC_2_PYT("clear_available_buttons", DoomGamePython::clearAvailableButtons)
+ CLASS_FUNC_2_PYT("get_available_buttons_size", DoomGamePython::getAvailableButtonsSize)
+ CLASS_FUNC_2_PYT("set_button_max_value", DoomGamePython::setButtonMaxValue)
+ CLASS_FUNC_2_PYT("get_button_max_value", DoomGamePython::getButtonMaxValue)
+
+ CLASS_FUNC_2_PYT("add_game_args", DoomGamePython::addGameArgs)
+ CLASS_FUNC_2_PYT("clear_game_args", DoomGamePython::clearGameArgs)
+
+ CLASS_FUNC_2_PYT("send_game_command", DoomGamePython::sendGameCommand)
+
+ CLASS_FUNC_2_PYT("get_mode", DoomGamePython::getMode)
+ CLASS_FUNC_2_PYT("set_mode", DoomGamePython::setMode)
+
+ CLASS_FUNC_2_PYT("get_ticrate", DoomGamePython::getTicrate)
+ CLASS_FUNC_2_PYT("set_ticrate", DoomGamePython::setTicrate)
+
+ CLASS_FUNC_2_PYT("set_vizdoom_path", DoomGamePython::setViZDoomPath)
+ CLASS_FUNC_2_PYT("set_doom_game_path", DoomGamePython::setDoomGamePath)
+ CLASS_FUNC_2_PYT("set_doom_scenario_path", DoomGamePython::setDoomScenarioPath)
+ CLASS_FUNC_2_PYT("set_doom_map", DoomGamePython::setDoomMap)
+ CLASS_FUNC_2_PYT("set_doom_skill", DoomGamePython::setDoomSkill)
+ CLASS_FUNC_2_PYT("set_doom_config_path", DoomGamePython::setDoomConfigPath)
+
+ CLASS_FUNC_2_PYT("get_seed", DoomGamePython::getSeed)
+ CLASS_FUNC_2_PYT("set_seed", DoomGamePython::setSeed)
+
+ CLASS_FUNC_2_PYT("get_episode_start_time", DoomGamePython::getEpisodeStartTime)
+ CLASS_FUNC_2_PYT("set_episode_start_time", DoomGamePython::setEpisodeStartTime)
+ CLASS_FUNC_2_PYT("get_episode_timeout", DoomGamePython::getEpisodeTimeout)
+ CLASS_FUNC_2_PYT("set_episode_timeout", DoomGamePython::setEpisodeTimeout)
+ CLASS_FUNC_2_PYT("get_episode_time", DoomGamePython::getEpisodeTime)
+
+ CLASS_FUNC_2_PYT("set_console_enabled", DoomGamePython::setConsoleEnabled)
+ CLASS_FUNC_2_PYT("set_sound_enabled", DoomGamePython::setSoundEnabled)
+
+ CLASS_FUNC_2_PYT("is_audio_buffer_enabled", DoomGamePython::isAudioBufferEnabled)
+ CLASS_FUNC_2_PYT("set_audio_buffer_enabled", DoomGamePython::setAudioBufferEnabled)
+ CLASS_FUNC_2_PYT("get_audio_sampling_rate", DoomGamePython::getAudioSamplingRate)
+ CLASS_FUNC_2_PYT("set_audio_sampling_rate", DoomGamePython::setAudioSamplingRate)
+ CLASS_FUNC_2_PYT("get_audio_buffer_size", DoomGamePython::getAudioBufferSize)
+ CLASS_FUNC_2_PYT("set_audio_buffer_size", DoomGamePython::setAudioBufferSize)
+
+ CLASS_FUNC_2_PYT("set_screen_resolution", DoomGamePython::setScreenResolution)
+ CLASS_FUNC_2_PYT("set_screen_format", DoomGamePython::setScreenFormat)
+
+ CLASS_FUNC_2_PYT("is_depth_buffer_enabled", DoomGamePython::isDepthBufferEnabled)
+ CLASS_FUNC_2_PYT("set_depth_buffer_enabled", DoomGamePython::setDepthBufferEnabled)
+ CLASS_FUNC_2_PYT("is_labels_buffer_enabled", DoomGamePython::isLabelsBufferEnabled)
+ CLASS_FUNC_2_PYT("set_labels_buffer_enabled", DoomGamePython::setLabelsBufferEnabled)
+ CLASS_FUNC_2_PYT("is_automap_buffer_enabled", DoomGamePython::isAutomapBufferEnabled)
+ CLASS_FUNC_2_PYT("set_automap_buffer_enabled", DoomGamePython::setAutomapBufferEnabled)
+ CLASS_FUNC_2_PYT("set_automap_mode", DoomGamePython::setAutomapMode)
+ CLASS_FUNC_2_PYT("set_automap_rotate", DoomGamePython::setAutomapRotate)
+ CLASS_FUNC_2_PYT("set_automap_render_textures", DoomGamePython::setAutomapRenderTextures)
+ CLASS_FUNC_2_PYT("is_objects_info_enabled", DoomGamePython::isObjectsInfoEnabled)
+ CLASS_FUNC_2_PYT("set_objects_info_enabled", DoomGamePython::setObjectsInfoEnabled)
+ CLASS_FUNC_2_PYT("is_sectors_info_enabled", DoomGamePython::isSectorsInfoEnabled)
+ CLASS_FUNC_2_PYT("set_sectors_info_enabled", DoomGamePython::setSectorsInfoEnabled)
+
+ CLASS_FUNC_2_PYT("set_render_hud", DoomGamePython::setRenderHud)
+ CLASS_FUNC_2_PYT("set_render_minimal_hud", DoomGamePython::setRenderMinimalHud)
+ CLASS_FUNC_2_PYT("set_render_weapon", DoomGamePython::setRenderWeapon)
+ CLASS_FUNC_2_PYT("set_render_crosshair", DoomGamePython::setRenderCrosshair)
+ CLASS_FUNC_2_PYT("set_render_decals", DoomGamePython::setRenderDecals)
+ CLASS_FUNC_2_PYT("set_render_particles", DoomGamePython::setRenderParticles)
+ CLASS_FUNC_2_PYT("set_render_effects_sprites", DoomGamePython::setRenderEffectsSprites)
+ CLASS_FUNC_2_PYT("set_render_messages", DoomGamePython::setRenderMessages)
+ CLASS_FUNC_2_PYT("set_render_corpses", DoomGamePython::setRenderCorpses)
+ CLASS_FUNC_2_PYT("set_render_screen_flashes", DoomGamePython::setRenderScreenFlashes)
+ CLASS_FUNC_2_PYT("set_render_all_frames", DoomGamePython::setRenderAllFrames)
+ CLASS_FUNC_2_PYT("set_window_visible", DoomGamePython::setWindowVisible)
+ CLASS_FUNC_2_PYT("get_screen_width", DoomGamePython::getScreenWidth)
+ CLASS_FUNC_2_PYT("get_screen_height", DoomGamePython::getScreenHeight)
+ CLASS_FUNC_2_PYT("get_screen_channels", DoomGamePython::getScreenChannels)
+ CLASS_FUNC_2_PYT("get_screen_size", DoomGamePython::getScreenSize)
+ CLASS_FUNC_2_PYT("get_screen_pitch", DoomGamePython::getScreenPitch)
+ CLASS_FUNC_2_PYT("get_screen_format", DoomGamePython::getScreenFormat);
/* Utilities */
/*----------------------------------------------------------------------------------------------------------------*/
- vz.def("doom_tics_to_ms", doomTicsToMs);
- vz.def("ms_to_doom_tics", msToDoomTics);
- vz.def("doom_tics_to_sec", doomTicsToSec);
- vz.def("sec_to_doom_tics", secToDoomTics);
+ FUNC_2_PYT("doom_tics_to_ms", doomTicsToMs);
+ FUNC_2_PYT("ms_to_doom_tics", msToDoomTics);
+ FUNC_2_PYT("doom_tics_to_sec", doomTicsToSec);
+ FUNC_2_PYT("sec_to_doom_tics", secToDoomTics);
vz.def("doom_fixed_to_double", doomFixedToDouble_int);
vz.def("doom_fixed_to_double", doomFixedToDouble_double);
vz.def("doom_fixed_to_float", doomFixedToDouble_int);
vz.def("doom_fixed_to_float", doomFixedToDouble_double);
- vz.def("is_binary_button", isBinaryButton);
- vz.def("is_delta_button", isDeltaButton);
+ FUNC_2_PYT("is_binary_button", isBinaryButton);
+ FUNC_2_PYT("is_delta_button", isDeltaButton);
}
diff --git a/tests/test_docstrings.py b/tests/test_docstrings.py
new file mode 100755
index 000000000..f2e3709ef
--- /dev/null
+++ b/tests/test_docstrings.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python3
+
+import vizdoom as vzd
+
+
+def _check_object_docstrings(object):
+ object_methods = [
+ method_name
+ for method_name in dir(object)
+ if callable(getattr(object, method_name))
+ ]
+
+ for method in object_methods:
+ assert method.__doc__ is not None, f"Method {method} has no docstring"
+
+
+def test_docstrings():
+ _check_object_docstrings(vzd.DoomGame)
+
+
+if __name__ == "__main__":
+ test_docstrings()