diff --git a/docs/api/cpp/doom_game.md b/docs/api/cpp/doom_game.md index 5a69c9fee..be1fd0830 100644 --- a/docs/api/cpp/doom_game.md +++ b/docs/api/cpp/doom_game.md @@ -1107,6 +1107,16 @@ See also: Note: added in 1.1.0. +--- +### `getViZDoomPath` + +| C++ | `std::string getViZDoomPath()` | +| :-- | :-- | +| Python | `get_vizdoom_path() -> str` | + +Returns the path to the ViZDoom engine executable vizdoom. + + --- ### `setViZDoomPath` @@ -1115,12 +1125,23 @@ Note: added in 1.1.0. | Python | `set_vizdoom_path(file_path: str) -> None` | Sets the path to the ViZDoom engine executable vizdoom. +We recommend not changing this path unless you know what you are doing. Default value: `/`. Config key: `ViZDoomPath`/`vizdoom_path` +--- +### `getDoomGamePath` + +| C++ | `std::string getDoomGamePath()` | +| :-- | :-- | +| Python | `get_doom_game_path() -> str` | + +Returns the path to the Doom engine based game file (wad format). + + --- ### `setDoomGamePath` @@ -1136,6 +1157,16 @@ Default value: `/ str` | + +Returns the path to the additional scenario file (wad format). + + --- ### `setDoomScenarioPath` @@ -1151,6 +1182,16 @@ Default value: `""` Config key: `DoomScenarioPath`/`doom_scenario_path` +--- +### `getDoomMap` + +| C++ | `std::string getDoomMap()` | +| :-- | :-- | +| Python | `get_doom_map() -> str` | + +Returns the map name to be used. + + --- ### `setDoomMap` @@ -1165,6 +1206,16 @@ Default value: `"map01"`, if set to empty `"map01"` will be used. Config key: `DoomMap`/`doom_map` +--- +### `getDoomSkill` + +| C++ | `unsigned int getDoomSkill()` | +| :-- | :-- | +| Python | `get_doom_skill() -> int` | + +Returns the Doom game difficulty level (skill). + + --- ### `setDoomSkill` @@ -1177,17 +1228,27 @@ 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. +- 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 Config key: `DoomSkill`/`doom_skill` +--- +### `getDoomConfigPath` + +| C++ | `std::string getDoomConfigPath()` | +| :-- | :-- | +| Python | `get_doom_config_path() -> str` | + +Returns the path for ZDoom's configuration file. + + --- ### `setDoomConfigPath` @@ -1282,6 +1343,34 @@ Default value: 0 Config key: `episodeTimeout`/`episode_timeout` +--- +### `isContinueOnMapExit` + +| C++ | `bool isContinueOnMapExit()` | +| :-- | :-- | +| Python | `is_continue_on_map_exit() -> bool` | + +Returns true if the game is set to continue on map exit. + +Note: added in 1.3.0. + + +--- +### `setContinueOnMapExit` + +| C++ | `void setContinueOnMapExit(bool continueOnMapExit)` | +| :-- | :-- | +| Python | `set_continue_on_map_exit(continue_on_map_exit: bool) -> None` | + +Sets whether the game should continue on map exit or consider it as the end of the episode. + +Default value: false + +Config key: `continueOnMapExit`/`continue_on_map_exit` + +Note: added in 1.3.0. + + ## Output/rendering setting methods diff --git a/docs/api/python/doom_game.md b/docs/api/python/doom_game.md index 5477133bb..8335e1394 100644 --- a/docs/api/python/doom_game.md +++ b/docs/api/python/doom_game.md @@ -1,7 +1,6 @@ # 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. - +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. The declarations of this class and its methods can be found in the `include/ViZDoomGame.h` header file. ```{eval-rst} @@ -117,11 +116,17 @@ DoomGame is the main object of the ViZDoom library, representing a single instan .. autofunction:: vizdoom.DoomGame.set_mode .. autofunction:: vizdoom.DoomGame.get_ticrate .. autofunction:: vizdoom.DoomGame.set_ticrate +.. autofunction:: vizdoom.DoomGame.get_vizdoom_path .. autofunction:: vizdoom.DoomGame.set_vizdoom_path +.. autofunction:: vizdoom.DoomGame.get_doom_game_path .. autofunction:: vizdoom.DoomGame.set_doom_game_path +.. autofunction:: vizdoom.DoomGame.get_doom_scenario_path .. autofunction:: vizdoom.DoomGame.set_doom_scenario_path +.. autofunction:: vizdoom.DoomGame.get_doom_map .. autofunction:: vizdoom.DoomGame.set_doom_map +.. autofunction:: vizdoom.DoomGame.get_doom_skill .. autofunction:: vizdoom.DoomGame.set_doom_skill +.. autofunction:: vizdoom.DoomGame.get_doom_config_path .. autofunction:: vizdoom.DoomGame.set_doom_config_path .. autofunction:: vizdoom.DoomGame.get_seed .. autofunction:: vizdoom.DoomGame.set_seed @@ -129,6 +134,8 @@ DoomGame is the main object of the ViZDoom library, representing a single instan .. autofunction:: vizdoom.DoomGame.set_episode_start_time .. autofunction:: vizdoom.DoomGame.get_episode_timeout .. autofunction:: vizdoom.DoomGame.set_episode_timeout +.. autofunction:: vizdoom.DoomGame.is_continue_on_map_exit +.. autofunction:: vizdoom.DoomGame.set_continue_on_map_exit ``` ## Output/rendering setting methods diff --git a/include/ViZDoomGame.h b/include/ViZDoomGame.h index d17b4ffa7..1e21f5982 100644 --- a/include/ViZDoomGame.h +++ b/include/ViZDoomGame.h @@ -163,12 +163,20 @@ namespace vizdoom { unsigned int getTicrate(); void setTicrate(unsigned int ticrate); + std::string getViZDoomPath(); void setViZDoomPath(std::string filePath); + std::string getDoomGamePath(); void setDoomGamePath(std::string filePath); + std::string getDoomScenarioPath(); void setDoomScenarioPath(std::string filePath); + std::string getDoomMap(); void setDoomMap(std::string map); + int getDoomSkill(); void setDoomSkill(int skill); + std::string getDoomConfigPath(); void setDoomConfigPath(std::string filePath); + bool isContinueOnMapExit(); + void setContinueOnMapExit(bool continueOnMapExit); unsigned int getSeed(); void setSeed(unsigned int seed); diff --git a/src/lib/ViZDoomConfigLoader.cpp b/src/lib/ViZDoomConfigLoader.cpp index b3caa1ae5..f8c690f43 100644 --- a/src/lib/ViZDoomConfigLoader.cpp +++ b/src/lib/ViZDoomConfigLoader.cpp @@ -783,6 +783,10 @@ namespace vizdoom { this->game->setAudioBufferEnabled(stringToBool(val)); continue; } + else if (key == "continue_on_map_exit" || key == "continueonmapexit") { + this->game->setContinueOnMapExit(stringToBool(val)); + continue; + } } catch (std::exception) { std::cerr << "WARNING! Loading config from: \"" << filePath << diff --git a/src/lib/ViZDoomConfigLoader.h b/src/lib/ViZDoomConfigLoader.h index ab7aa7187..ecabcdd35 100644 --- a/src/lib/ViZDoomConfigLoader.h +++ b/src/lib/ViZDoomConfigLoader.h @@ -1,6 +1,7 @@ /* Copyright (C) 2016 by Wojciech Jaśkowski, Michał Kempka, Grzegorz Runc, Jakub Toczek, Marek Wydmuch Copyright (C) 2017 - 2022 by Marek Wydmuch, Michał Kempka, Wojciech Jaśkowski, and the respective contributors + Copyright (C) 2023 - 2025 by Marek Wydmuch, Farama Foundation, and the respective contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/lib/ViZDoomController.cpp b/src/lib/ViZDoomController.cpp index ae5c01045..0432f7fcb 100644 --- a/src/lib/ViZDoomController.cpp +++ b/src/lib/ViZDoomController.cpp @@ -272,7 +272,6 @@ namespace vizdoom { void DoomController::tic(bool update) { if (this->doomRunning) { - if (this->isTicPossible()) { this->mapLastTic = this->gameState->MAP_TIC + 1; if (update) this->MQDoom->send(MSG_CODE_TIC_AND_UPDATE); @@ -522,8 +521,7 @@ namespace vizdoom { std::string DoomController::getConfigPath() { return this->configPath; } - void - DoomController::setConfigPath(std::string configPath) { if (!this->doomRunning) this->configPath = configPath; } + void DoomController::setConfigPath(std::string configPath) { if (!this->doomRunning) this->configPath = configPath; } int DoomController::getSkill() { return this->skill; } @@ -597,6 +595,14 @@ namespace vizdoom { return this->mapLastTic; } + bool DoomController::isContinueOnIntermission() const { + return this->continueOnIntermission; + } + + void DoomController::setContinueOnIntermission(bool continueOnIntermission) { + this->continueOnIntermission = continueOnIntermission; + } + void DoomController::setNoConsole(bool console) { if (!this->doomRunning) this->noConsole = console; } @@ -1227,25 +1233,47 @@ namespace vizdoom { // main wad if (this->iwadPath.length() == 0) { - std::string workingDoom2Path = "./doom2.wad"; - std::string workingDoomPath = "./doom.wad"; - std::string workingFreedoom2Path = "./freedoom2.wad"; - std::string workingFreedoomPath = "./freedoom.wad"; - std::string sharedDoom2Path = getThisSharedObjectPath() + "/doom2.wad"; - std::string sharedDoomPath = getThisSharedObjectPath() + "/doom.wad"; - std::string sharedFreedoom2Path = getThisSharedObjectPath() + "/freedoom2.wad"; - std::string sharedFreedoomPath = getThisSharedObjectPath() + "/freedoom.wad"; - - if (fileExists(workingDoom2Path)) this->iwadPath = workingDoom2Path; - else if (fileExists(sharedDoom2Path)) this->iwadPath = sharedDoom2Path; - else if (fileExists(workingFreedoom2Path)) this->iwadPath = workingFreedoom2Path; - else if (fileExists(sharedFreedoom2Path)) this->iwadPath = sharedFreedoom2Path; - else throw FileDoesNotExistException(workingDoom2Path - + " | " + workingFreedoom2Path - + " | " + sharedDoom2Path - + " | " + sharedFreedoom2Path); - } + // If no iwadPath is set, try to find default wads in the current directory or shared library directory + const std::vector wadNames = { + "doom2.wad", "DOOM2.WAD", "doom.wad", "DOOM.WAD", + "freedoom2.wad", "freedoom.wad" + }; + + std::string allWadsList = "<"; + for (int i = 0; i < wadNames.size(); ++i) { + const std::string &wadName = wadNames[i]; + std::string workingPath = "./" + wadName; + std::string sharedPath = getThisSharedObjectPath() + "/" + wadName; + allWadsList += wadName; + if (i < wadNames.size() - 1) allWadsList += " | "; + + if (fileExists(workingPath)) { + this->iwadPath = workingPath; + break; + } else if (fileExists(sharedPath)) { + this->iwadPath = sharedPath; + break; + } + } + if (this->iwadPath.length() == 0){ + // If no wad was found, throw an exception with the list of possible wads + allWadsList += ">"; + throw FileDoesNotExistException("./" + allWadsList + " or " + + getThisSharedObjectPath() + "/" + allWadsList); + } + } else if (!fileExists(this->iwadPath)) { + // If the iwadPath does not exist, check if it's filename and can be found in the library directory + if (this->iwadPath.find('/') == std::string::npos && this->iwadPath.find('\\') == std::string::npos) { + std::string sharedPath = getThisSharedObjectPath() + "/" + this->iwadPath; + std::string sharedPathCaps = getThisSharedObjectPath() + "/" + toUpper(this->iwadPath); + if (fileExists(sharedPath)) this->iwadPath = sharedPath; + else if (fileExists(sharedPathCaps)) this->iwadPath = sharedPathCaps; + else throw FileDoesNotExistException(this->iwadPath + + " or " + sharedPath + " or " + sharedPathCaps); + } + } + this->doomArgs.push_back("-iwad"); this->doomArgs.push_back(prepareWadFilePath(this->iwadPath)); diff --git a/src/lib/ViZDoomController.h b/src/lib/ViZDoomController.h index 0b3248634..b3070603e 100644 --- a/src/lib/ViZDoomController.h +++ b/src/lib/ViZDoomController.h @@ -155,6 +155,9 @@ namespace vizdoom { bool isMapTimeoutReached(); unsigned int getMapLastTic(); + bool isContinueOnIntermission() const; + void setContinueOnIntermission(bool continueOnIntermission); + void setNoConsole(bool console); void setNoSound(bool noSound); bool getNoSound() const; @@ -393,6 +396,7 @@ namespace vizdoom { std::string configPath; int skill; + bool continueOnIntermission; bool allowDoomInput; bool runDoomAsync; diff --git a/src/lib/ViZDoomGame.cpp b/src/lib/ViZDoomGame.cpp index c6682b816..bb5a1f390 100644 --- a/src/lib/ViZDoomGame.cpp +++ b/src/lib/ViZDoomGame.cpp @@ -552,19 +552,31 @@ namespace vizdoom { return this->doomController->getGameVariable(variable); } + std::string DoomGame::getViZDoomPath() { return this->doomController->getExePath(); } + void DoomGame::setViZDoomPath(std::string filePath) { this->doomController->setExePath(filePath); } + std::string DoomGame::getDoomGamePath() { return this->doomController->getIwadPath(); } + void DoomGame::setDoomGamePath(std::string filePath) { this->doomController->setIwadPath(filePath); } + std::string DoomGame::getDoomScenarioPath() { return this->doomController->getFilePath(); } + void DoomGame::setDoomScenarioPath(std::string filePath) { this->doomController->setFilePath(filePath); } + std::string DoomGame::getDoomMap() { return this->doomController->getMap(); } + void DoomGame::setDoomMap(std::string map) { this->doomController->setMap(map); if (this->isRunning()) this->resetState(); } + int DoomGame::getDoomSkill() { return this->doomController->getSkill(); } + void DoomGame::setDoomSkill(int skill) { this->doomController->setSkill(skill); } + std::string DoomGame::getDoomConfigPath() { return this->doomController->getConfigPath(); } + void DoomGame::setDoomConfigPath(std::string filePath) { this->doomController->setConfigPath(filePath); } unsigned int DoomGame::getSeed() { return this->doomController->getInstanceSeed(); } @@ -581,6 +593,10 @@ namespace vizdoom { unsigned int DoomGame::getEpisodeTime() { return this->doomController->getMapTic(); } + bool DoomGame::isContinueOnMapExit() { return this->doomController->isContinueOnIntermission(); } + + void DoomGame::setContinueOnMapExit(bool continueOnMapExit) { this->doomController->setContinueOnIntermission(continueOnMapExit); } + double DoomGame::getLivingReward() { return this->livingReward; } void DoomGame::setLivingReward(double livingReward) { this->livingReward = livingReward; } diff --git a/src/lib/ViZDoomPathHelpers.cpp b/src/lib/ViZDoomPathHelpers.cpp index 144ac274b..b4c0a07a2 100644 --- a/src/lib/ViZDoomPathHelpers.cpp +++ b/src/lib/ViZDoomPathHelpers.cpp @@ -1,6 +1,7 @@ /* Copyright (C) 2016 by Wojciech Jaśkowski, Michał Kempka, Grzegorz Runc, Jakub Toczek, Marek Wydmuch Copyright (C) 2017 - 2022 by Marek Wydmuch, Michał Kempka, Wojciech Jaśkowski, and the respective contributors + Copyright (C) 2023 - 2025 by Marek Wydmuch, Farama Foundation, and the respective contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -40,8 +41,19 @@ namespace vizdoom { namespace b = boost; + namespace bal = boost::algorithm; namespace bfs = boost::filesystem; + std::string toUpper(std::string str) { + bal::to_upper(str); + return str; + } + + std::string toLower(std::string str) { + bal::to_lower(str); + return str; + } + std::string fileExtension(std::string filePath) { bfs::path path(filePath); return path.extension().string(); diff --git a/src/lib/ViZDoomPathHelpers.h b/src/lib/ViZDoomPathHelpers.h index 3c83865b1..2e507c1d2 100644 --- a/src/lib/ViZDoomPathHelpers.h +++ b/src/lib/ViZDoomPathHelpers.h @@ -1,6 +1,8 @@ /* Copyright (C) 2016 by Wojciech Jaśkowski, Michał Kempka, Grzegorz Runc, Jakub Toczek, Marek Wydmuch Copyright (C) 2017 - 2022 by Marek Wydmuch, Michał Kempka, Wojciech Jaśkowski, and the respective contributors + Copyright (C) 2023 - 2025 by Marek Wydmuch, Farama Foundation, and the respective contributors + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -37,6 +39,10 @@ namespace vizdoom { + std::string toUpper(std::string str); + + std::string toLower(std::string str); + std::string fileExtension(std::string filePath); bool hasExtension(std::string filePath); diff --git a/src/lib_python/ViZDoomMethodsDocstrings.h b/src/lib_python/ViZDoomMethodsDocstrings.h index 919d18ea6..8a8a90ec5 100644 --- a/src/lib_python/ViZDoomMethodsDocstrings.h +++ b/src/lib_python/ViZDoomMethodsDocstrings.h @@ -477,12 +477,17 @@ See also: Note: added in 1.1.0.)DOCSTRING"; + const char *getViZDoomPath = R"DOCSTRING(Returns the path to the ViZDoom engine executable vizdoom.)DOCSTRING"; + const char *setViZDoomPath = R"DOCSTRING(Sets the path to the ViZDoom engine executable vizdoom. +We recommend not changing this path unless you know what you are doing. Default value: ``/``. Config key: ``ViZDoomPath``/``vizdoom_path``)DOCSTRING"; + const char *getDoomGamePath = R"DOCSTRING(Returns the path to the Doom engine based game file (wad format).)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 library/pyd is). @@ -490,6 +495,8 @@ Default value: ``/