diff --git a/ChangeLog b/ChangeLog deleted file mode 100644 index 0ede910..0000000 --- a/ChangeLog +++ /dev/null @@ -1,56 +0,0 @@ -June 22nd, 2015. ALE 0.5.0. - * Added action_repeat_stochasticity. - * Added sound playback, visualization. - * Added screen/sound recording ability. - * CMake now available. - * Incorporated Benjamin Goodrich's Python interface. - * Some game fixes. - * Added examples for shared library, Python, fifo, RL-Glue interfaces. - * Incorporated Java agent into main repository. - * Removed internal controller, now superseded by shared library interface. - * Better ALEInterface. - * Many other changes. - -February 15th, 2015. ALE 0.5dev. - * Removed the following command-line flags: 'output_file', 'system_reset_steps', 'use_environment_distribution', 'backward_compatible_save', internal agent flags - * The flag 'use_starting_actions' was removed and internally its value is always 'true'. - * The flag 'disable_color_averaging' was renamed to 'color_averaging' and FALSE is its default value. - -April 28th, 2014. ALE 0.4.4. - * Fixed a memory issue in ALEScreen. - -April 26th, 2014. Bug fix (Mayank Daswani). - * Fixed issues with frame numbers not being correctly updated. - * Fixed a bug where total reward was not properly reported under frame skipping. - -January 7th, 2013. ALE 0.4.3. - * Fixed a bug with ALEState's m_frame_number. - -June 12th, 2013. ALE 0.4.2. - * Modified StellaEnvironment save/load interface to provide additional flexibility. - * Series of bug fixes from Matthew Hausknecht and community. - -May 24th, 2013. Bug fix to ALE 0.4.1. - * Fixed RL-Glue syntax from OBSERVATION to OBSERVATIONS. Thanks to Angus MacIsaac for picking this bug up. - -May 22nd, 2013. ALE 0.4.1. - * Added frame skipping support directly in StellaEnvironment. - * Reverted default number of episodes to 10. - -April 22nd, 2013. ALE 0.4.0. - * RL-Glue support - * Shared library interface - * Simpler direct environment interfacing - * Improved environment handling - * Improved environment customization - * Better documentation - -October 3rd, 2012. Moving to GITHub. - -August 7th, 2012. ALE 0.3.1. - * Fixed frames per episode cap for FIFO agents, added functionality to - limit the total number of frames per run for FIFO agents. - -July 22nd, 2012. ALE 0.3. - * Initial ALE release. - diff --git a/README-ale.md b/README-ale.md index 6031d27..edee571 100644 --- a/README-ale.md +++ b/README-ale.md @@ -1,23 +1,119 @@ -(Contents from [https://github.com/bbitmaster/ale_python_interface](https://github.com/bbitmaster/ale_python_interface)) +[![Build Status](https://travis-ci.org/mgbellemare/Arcade-Learning-Environment.svg?branch=master)](https://travis-ci.org/mgbellemare/Arcade-Learning-Environment) -# Arcade-Learning-Environment +# The Arcade Learning Environment -The Arcade Learning Environment (ALE) -- a platform for AI research. +The Arcade Learning Environment (ALE) is a simple object-oriented framework that allows researchers and hobbyists to develop AI agents for Atari 2600 games. It is built on top of the Atari 2600 emulator [Stella](https://stella-emu.github.io/) and separates the details of emulation from agent design. This [video](https://www.youtube.com/watch?v=nzUiEkasXZI) depicts over 50 games currently supported in the ALE. -For more details and installation instructions, see the [website](http://www.arcadelearningenvironment.org) and [manual](doc/manual/manual.pdf). To ask questions and discuss, please join the [ALE-users group](https://groups.google.com/forum/#!forum/arcade-learning-environment). +For an overview of our goals for the ALE read [The Arcade Learning Environment: An Evaluation Platform for General Agents](http://www.jair.org/papers/paper3912.html). If you use ALE in your research, we ask that you please cite this paper in reference to the environment (BibTeX entry at the end of this document). Also, if you have any questions or comments about the ALE, please contact us through our [mailing list](https://groups.google.com/forum/#!forum/arcade-learning-environment). -## Citing ALE -If ALE helps in your research, please cite the following: +Feedback and suggestions are welcome and may be addressed to any active member of the ALE team. - @article{bellemare13arcade, - author = {{Bellemare}, M.~G. and {Naddaf}, Y. and {Veness}, J. and {Bowling}, M.}, - title = {The Arcade Learning Environment: An Evaluation Platform for General Agents}, - journal = {Journal of Artificial Intelligence Research}, - year = "2013", - month = "jun", - volume = "47", - pages = "253--279", - } +### Features +- Object-oriented framework with support to add agents and games. +- Emulation core uncoupled from rendering and sound generation modules for fast emulation with minimal library dependencies. +- Automatic extraction of game score and end-of-game signal for more than 50 Atari 2600 games. +- Multi-platform code (compiled and tested under OS X and several Linux distributions, with Cygwin support). +- Communication between agents and emulation core can be accomplished through pipes, allowing for cross-language development (sample Java code included). +- Python development is supported through ctypes. +- Agents programmed in C++ have access to all features in the ALE. +- Visualization tools. + +## Quick start + + +Install main dependences: +``` +sudo apt-get install libsdl1.2-dev libsdl-gfx1.2-dev libsdl-image1.2-dev cmake +``` + +Compilation: + +``` +$ mkdir build && cd build +$ cmake -DUSE_SDL=ON -DUSE_RLGLUE=OFF -DBUILD_EXAMPLES=ON .. +$ make -j 4 +``` + +To install python module: + +``` +$ pip install . +or +$ pip install --user . +``` + +Getting the ALE to work on Visual Studio requires a bit of extra wrangling. You may wish to use IslandMan93's [Visual Studio port of the ALE.](https://github.com/Islandman93/Arcade-Learning-Environment) + +For more details and installation instructions, see the [manual](doc/manual/manual.pdf). To ask questions and discuss, please join the [ALE-users group](https://groups.google.com/forum/#!forum/arcade-learning-environment). + +## ALE releases + +Releases before v.0.5 are available for download in our previous [website](http://www.arcadelearningenvironment.org/). For the latest releases, please check our releases [page](https://github.com/mgbellemare/Arcade-Learning-Environment/releases). + +## List of command-line parameters + +Execute ./ale -help for more details; alternatively, see documentation +available at http://www.arcadelearningenvironment.org. + +``` +-random_seed [n] -- sets the random seed; defaults to the current time + +-game_controller [fifo|fifo_named] -- specifies how agents interact + with the ALE; see Java agent documentation for details + +-config [file] -- specifies a configuration file, from which additional + parameters are read + +-run_length_encoding [false|true] -- determine whether run-length encoding is + used to send data over pipes; irrelevant when an internal agent is + being used + +-max_num_frames_per_episode [n] -- sets the maximum number of frames per + episode. Once this number is reached, a new episode will start. Currently + implemented for all agents when using pipes (fifo/fifo_named) + +-max_num_frames [n] -- sets the maximum number of frames (independent of how + many episodes are played) +``` + + +## Citing The Arcade Learning Environment + + +If you use the ALE in your research, we ask that you please cite the following. + +*M. G. Bellemare, Y. Naddaf, J. Veness and M. Bowling. The Arcade Learning Environment: An Evaluation Platform for General Agents, Journal of Artificial Intelligence Research, Volume 47, pages 253-279, 2013.* + +In BibTeX format: + +``` +@Article{bellemare13arcade, + author = {{Bellemare}, M.~G. and {Naddaf}, Y. and {Veness}, J. and {Bowling}, M.}, + title = {The Arcade Learning Environment: An Evaluation Platform for General Agents}, + journal = {Journal of Artificial Intelligence Research}, + year = "2013", + month = "jun", + volume = "47", + pages = "253--279", +} +``` + + +If you use the ALE with sticky actions (flag `repeat_action_probability`), or if you use the different game flavours (mode and difficulty switches), we ask you that you also cite the following: + +*M. C. Machado, M. G. Bellemare, E. Talvitie, J. Veness, M. J. Hausknecht, M. Bowling. Revisiting the Arcade Learning Environment: Evaluation Protocols and Open Problems for General Agents, CoRR abs/1709.06009, 2017.* + +In BibTex format: + +``` +@Article{machado17arcade, + author = {Marlos C. Machado and Marc G. Bellemare and Erik Talvitie and Joel Veness and Matthew J. Hausknecht and Michael Bowling}, + title = {Revisiting the Arcade Learning Environment: Evaluation Protocols and Open Problems for General Agents}, + journal = {CoRR}, + volume = {abs/1709.06009}, + year = {2017} +} +``` diff --git a/atari_py/ale_c_wrapper.h b/atari_py/ale_c_wrapper.h index cf01cc1..78f658d 100644 --- a/atari_py/ale_c_wrapper.h +++ b/atari_py/ale_c_wrapper.h @@ -20,9 +20,25 @@ extern "C" { int act(ALEInterface *ale,int action){return ale->act((Action)action);} bool game_over(ALEInterface *ale){return ale->game_over();} void reset_game(ALEInterface *ale){ale->reset_game();} - void getLegalActionSet(ALEInterface *ale,int *actions){ + void getAvailableModes(ALEInterface *ale,int *availableModes) { + ModeVect modes_vect = ale->getAvailableModes(); + for(unsigned int i = 0; i < ale->getAvailableModes().size(); i++){ + availableModes[i] = modes_vect[i]; + } + } + int getAvailableModesSize(ALEInterface *ale) {return ale->getAvailableModes().size();} + void setMode(ALEInterface *ale, int mode) {ale->setMode(mode);} + void getAvailableDifficulties(ALEInterface *ale,int *availableDifficulties) { + DifficultyVect difficulties_vect = ale->getAvailableDifficulties(); + for(unsigned int i = 0; i < ale->getAvailableDifficulties().size(); i++){ + availableDifficulties[i] = difficulties_vect[i]; + } + } + int getAvailableDifficultiesSize(ALEInterface *ale) {return ale->getAvailableDifficulties().size();} + void setDifficulty(ALEInterface *ale, int difficulty) {ale->setDifficulty(difficulty);} + void getLegalActionSet(ALEInterface *ale,int *actions) { ActionVect action_vect = ale->getLegalActionSet(); - for(unsigned int i = 0;i < ale->getLegalActionSet().size();i++){ + for(unsigned int i = 0; i < ale->getLegalActionSet().size(); i++){ actions[i] = action_vect[i]; } } @@ -58,9 +74,10 @@ extern "C" { size_t screen_size = w*h; pixel_t *ale_screen_data = ale->getScreen().getArray(); - ale->theOSystem->colourPalette().applyPaletteRGB(output_buffer, ale_screen_data, screen_size); + ale->theOSystem->colourPalette().applyPaletteRGB(output_buffer, ale_screen_data, screen_size ); } + void getScreenRGB2(ALEInterface *ale, unsigned char *output_buffer){ size_t w = ale->getScreen().width(); size_t h = ale->getScreen().height(); @@ -76,6 +93,7 @@ extern "C" { } } + void getScreenGrayscale(ALEInterface *ale, unsigned char *output_buffer){ size_t w = ale->getScreen().width(); size_t h = ale->getScreen().height(); diff --git a/atari_py/ale_interface/CMakeLists.txt b/atari_py/ale_interface/CMakeLists.txt index dfeb319..1e9a406 100644 --- a/atari_py/ale_interface/CMakeLists.txt +++ b/atari_py/ale_interface/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required (VERSION 2.6) project(ale) -set(ALEVERSION "0.5") +set(ALEVERSION "0.6") option(USE_SDL "Use SDL" OFF) @@ -10,7 +10,7 @@ option(BUILD_CPP_LIB "Build C++ Shared Library" OFF) option(BUILD_CLI "Build ALE Command Line Interface" OFF) option(BUILD_C_LIB "Build ALE C Library (needed for Python interface)" ON) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -O3 -fomit-frame-pointer -D__STDC_CONSTANT_MACROS") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fPIC -O3 -fomit-frame-pointer -D__STDC_CONSTANT_MACROS") add_definitions(-DHAVE_INTTYPES) set(LINK_LIBS z) @@ -28,8 +28,9 @@ if(USE_SDL) list(APPEND LINK_LIBS ${SDL_LIBRARY} ${SDL_MAIN_LIBRARY}) else() MESSAGE("SDL 1.2 not found: You may need to manually edit CMakeLists.txt or run \"cmake -i\" to specify your SDL path.") - # Uncomment below to specify the path to your SDL library. Run "locate libSDL" if unsure. + # Uncomment below to specify the path to your SDL library and header file. Run "locate libSDL" and "locate SDL.h" if unsure. # link_directories(path_to_your_SDL) + # include_directories(path_to_your_SDL_header) if(APPLE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -framework Cocoa") list(APPEND LINK_LIBS sdl sdlmain) @@ -127,10 +128,15 @@ include_directories( ${SOURCE_DIR}/external/TinyMT ) +if(NOT BUILD_CPP_LIB AND BUILD_EXAMPLES) + set(BUILD_CPP_LIB ON) + MESSAGE("Enabling C++ library to support examples.") +endif() + if(BUILD_CPP_LIB) add_library(ale-lib SHARED ${SOURCE_DIR}/ale_interface.cpp ${SOURCES}) set_target_properties(ale-lib PROPERTIES OUTPUT_NAME ale) - set_target_properties(ale-lib PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) + set_target_properties(ale-lib PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) if(UNIX) install(TARGETS ale-lib DESTINATION ${LIB_INSTALL_DIR}) @@ -141,7 +147,7 @@ endif() if(BUILD_CLI) add_executable(ale-bin ${SOURCE_DIR}/main.cpp ${SOURCE_DIR}/ale_interface.cpp ${SOURCES}) set_target_properties(ale-bin PROPERTIES OUTPUT_NAME ale) - set_target_properties(ale-bin PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) + set_target_properties(ale-bin PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) if(UNIX) install(TARGETS ale-bin DESTINATION ${BIN_INSTALL_DIR}) @@ -152,7 +158,7 @@ endif() if(BUILD_C_LIB) add_library(ale-c-lib SHARED ${CMAKE_CURRENT_SOURCE_DIR}/../ale_c_wrapper.cpp ${SOURCE_DIR}/ale_interface.cpp ${SOURCES}) set_target_properties(ale-c-lib PROPERTIES OUTPUT_NAME ale_c) - set_target_properties(ale-c-lib PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) + set_target_properties(ale-c-lib PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) if(UNIX) install(TARGETS ale-c-lib DESTINATION ${LIB_INSTALL_DIR}) @@ -164,25 +170,34 @@ if(BUILD_EXAMPLES) # Shared library example. link_directories(${CMAKE_CURRENT_SOURCE_DIR}) add_executable(sharedLibraryInterfaceExample ${CMAKE_CURRENT_SOURCE_DIR}/doc/examples/sharedLibraryInterfaceExample.cpp) - set_target_properties(sharedLibraryInterfaceExample PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/doc/examples) + set_target_properties(sharedLibraryInterfaceExample PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc/examples) set_target_properties(sharedLibraryInterfaceExample PROPERTIES OUTPUT_NAME ${PROJECT_NAME}-sharedLibraryInterfaceExample) + target_link_libraries(sharedLibraryInterfaceExample ale) target_link_libraries(sharedLibraryInterfaceExample ${LINK_LIBS}) add_dependencies(sharedLibraryInterfaceExample ale-lib) # Fifo interface example. link_directories(${CMAKE_CURRENT_SOURCE_DIR}) + add_executable(fifoInterfaceExample ${CMAKE_CURRENT_SOURCE_DIR}/doc/examples/fifoInterfaceExample.cpp) - set_target_properties(fifoInterfaceExample PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/doc/examples) + set_target_properties(fifoInterfaceExample PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc/examples) set_target_properties(fifoInterfaceExample PROPERTIES OUTPUT_NAME ${PROJECT_NAME}-fifoInterfaceExample) target_link_libraries(fifoInterfaceExample ale) target_link_libraries(fifoInterfaceExample ${LINK_LIBS}) add_dependencies(fifoInterfaceExample ale-lib) + add_executable(sharedLibraryInterfaceWithModesExample ${CMAKE_CURRENT_SOURCE_DIR}/doc/examples/sharedLibraryInterfaceWithModesExample.cpp) + set_target_properties(sharedLibraryInterfaceWithModesExample PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc/examples) + set_target_properties(sharedLibraryInterfaceWithModesExample PROPERTIES OUTPUT_NAME ${PROJECT_NAME}-sharedLibraryInterfaceWithModesExample) + target_link_libraries(sharedLibraryInterfaceWithModesExample ale) + target_link_libraries(sharedLibraryInterfaceWithModesExample ${LINK_LIBS}) + add_dependencies(sharedLibraryInterfaceWithModesExample ale-lib) + # Example showing how to record an Atari 2600 video. if (USE_SDL) add_executable(videoRecordingExample ${CMAKE_CURRENT_SOURCE_DIR}/doc/examples/videoRecordingExample.cpp) - set_target_properties(videoRecordingExample PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/doc/examples) + set_target_properties(videoRecordingExample PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc/examples) set_target_properties(videoRecordingExample PROPERTIES OUTPUT_NAME ${PROJECT_NAME}-videoRecordingExample) target_link_libraries(videoRecordingExample ale) target_link_libraries(videoRecordingExample ${LINK_LIBS}) @@ -192,14 +207,14 @@ endif() if(USE_RLGLUE) add_executable(RLGlueAgent ${CMAKE_CURRENT_SOURCE_DIR}/doc/examples/RLGlueAgent.c) - set_target_properties(RLGlueAgent PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/doc/examples) + set_target_properties(RLGlueAgent PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc/examples) set_target_properties(RLGlueAgent PROPERTIES OUTPUT_NAME ${PROJECT_NAME}-RLGlueAgent) target_link_libraries(RLGlueAgent rlutils) target_link_libraries(RLGlueAgent rlagent) target_link_libraries(RLGlueAgent rlgluenetdev) add_executable(RLGlueExperiment ${CMAKE_CURRENT_SOURCE_DIR}/doc/examples/RLGlueExperiment.c) - set_target_properties(RLGlueExperiment PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/doc/examples) + set_target_properties(RLGlueExperiment PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc/examples) set_target_properties(RLGlueExperiment PROPERTIES OUTPUT_NAME ${PROJECT_NAME}-RLGlueExperiment) target_link_libraries(RLGlueExperiment rlutils) target_link_libraries(RLGlueExperiment rlexperiment) diff --git a/atari_py/ale_interface/src/ale_interface.cpp b/atari_py/ale_interface/src/ale_interface.cpp index 6218316..a57c489 100644 --- a/atari_py/ale_interface/src/ale_interface.cpp +++ b/atari_py/ale_interface/src/ale_interface.cpp @@ -27,33 +27,49 @@ * * The shared library interface. **************************************************************************** */ + #include "ale_interface.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include +#include + +#include "common/ColourPalette.hpp" +#include "common/Constants.h" +#include "emucore/Console.hxx" +#include "emucore/Props.hxx" +#include "environment/ale_screen.hpp" +#include "games/RomSettings.hpp" -using namespace std; using namespace ale; + // Display ALE welcome message std::string ALEInterface::welcomeMessage() { std::ostringstream oss; - oss << "A.L.E: Arcade Learning Environment (version " - << Version << ")\n" - << "[Powered by Stella]\n" - << "Use -help for help screen."; + oss << "A.L.E: Arcade Learning Environment (version " << Version << ")\n" + << "[Powered by Stella]\n" << "Use -help for help screen."; return oss.str(); } void ALEInterface::disableBufferedIO() { setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stdin, NULL, _IONBF, 0); - cin.rdbuf()->pubsetbuf(0,0); - cout.rdbuf()->pubsetbuf(0,0); - cin.sync_with_stdio(); - cout.sync_with_stdio(); + std::cin.rdbuf()->pubsetbuf(0, 0); + std::cout.rdbuf()->pubsetbuf(0, 0); + std::cin.sync_with_stdio(); + std::cout.sync_with_stdio(); } -void ALEInterface::createOSystem(std::auto_ptr &theOSystem, - std::auto_ptr &theSettings) { +void ALEInterface::createOSystem(std::unique_ptr &theOSystem, + std::unique_ptr &theSettings) { #if (defined(WIN32) || defined(__MINGW32__)) theOSystem.reset(new OSystemWin32()); theSettings.reset(new SettingsWin32(theOSystem.get())); @@ -65,36 +81,65 @@ void ALEInterface::createOSystem(std::auto_ptr &theOSystem, theOSystem->settings().loadConfig(); } -void ALEInterface::loadSettings(const string& romfile, - std::auto_ptr &theOSystem) { +void ALEInterface::checkForUnsupportedRom(std::unique_ptr& theOSystem) { + const Properties properties = theOSystem->console().properties(); + const std::string md5 = properties.get(Cartridge_MD5); + bool found = false; + std::ifstream ss("md5.txt"); + std::string item; + while (!found && std::getline(ss, item)) { + if (!item.compare(0, md5.size(), md5)) { + const std::string rom_candidate = item.substr(md5.size() + 1); + found = true; + } + } + if (!found) { + // If the md5 doesn't match our master list, warn the user. + Logger::Warning << std::endl; + Logger::Warning << "WARNING: Possibly unsupported ROM: mismatched MD5." << std::endl; + Logger::Warning << "Cartridge_MD5: " << md5 << std::endl; + const std::string name = properties.get(Cartridge_Name); + Logger::Warning << "Cartridge_name: " << name << std::endl; + Logger::Warning << std::endl; + } +} + +void ALEInterface::loadSettings(const std::string& romfile, + std::unique_ptr &theOSystem) { // Load the configuration from a config file (passed on the command // line), if provided - string configFile = theOSystem->settings().getString("config", false); + std::string configFile = theOSystem->settings().getString("config", false); - if (!configFile.empty()) + if (!configFile.empty()) { theOSystem->settings().loadConfig(configFile.c_str()); + } theOSystem->settings().validate(); theOSystem->create(); // Attempt to load the ROM - if (romfile == "" || !FilesystemNode::fileExists(romfile)) { - Logger::Error << "No ROM File specified or the ROM file was not found." - << std::endl; + if (romfile == "") { + Logger::Error << "No ROM File specified." << std::endl; + exit(1); + } else if (!FilesystemNode::fileExists(romfile)) { + Logger::Error << "ROM file " << romfile << " not found." << std::endl; exit(1); } else if (theOSystem->createConsole(romfile)) { + checkForUnsupportedRom(theOSystem); Logger::Info << "Running ROM file..." << std::endl; theOSystem->settings().setString("rom_file", romfile); } else { + Logger::Error << "Unable to create console for " << romfile << std::endl; exit(1); } - // Must force the resetting of the OSystem's random seed, which is set before we change - // choose our random seed. - Logger::Info << "Random seed is " << theOSystem->settings().getInt("random_seed") << std::endl; +// Must force the resetting of the OSystem's random seed, which is set before we change +// choose our random seed. + Logger::Info << "Random seed is " + << theOSystem->settings().getInt("random_seed") << std::endl; theOSystem->resetRNGSeed(); - string currentDisplayFormat = theOSystem->console().getFormat(); + std::string currentDisplayFormat = theOSystem->console().getFormat(); theOSystem->colourPalette().setPalette("standard", currentDisplayFormat); } @@ -111,13 +156,14 @@ ALEInterface::ALEInterface(bool display_screen) { this->setBool("display_screen", display_screen); } -ALEInterface::~ALEInterface() {} +ALEInterface::~ALEInterface() { +} // Loads and initializes a game. After this call the game should be // ready to play. Resets the OSystem/Console/Environment/etc. This is // necessary after changing a setting. Optionally specify a new rom to // load. -void ALEInterface::loadROM(string rom_file = "") { +void ALEInterface::loadROM(std::string rom_file = "") { assert(theOSystem.get()); if (rom_file.empty()) { rom_file = theOSystem->romFile(); @@ -129,9 +175,13 @@ void ALEInterface::loadROM(string rom_file = "") { environment->reset(); #ifndef __USE_SDL if (theOSystem->p_display_screen != NULL) { - Logger::Error << "Screen display requires directive __USE_SDL to be defined." << endl; - Logger::Error << "Please recompile this code with flag '-D__USE_SDL'." << endl; - Logger::Error << "Also ensure ALE has been compiled with USE_SDL active (see ALE makefile)." << endl; + Logger::Error + << "Screen display requires directive __USE_SDL to be defined." << std::endl; + Logger::Error << "Please recompile this code with flag '-D__USE_SDL'." + << std::endl; + Logger::Error + << "Also ensure ALE has been compiled with USE_SDL active (see ALE makefile)." + << std::endl; exit(1); } #endif @@ -156,32 +206,31 @@ float ALEInterface::getFloat(const std::string& key) { } // Set the value of a setting. -void ALEInterface::setString(const string& key, const string& value) { +void ALEInterface::setString(const std::string& key, const std::string& value) { assert(theSettings.get()); assert(theOSystem.get()); theSettings->setString(key, value); theSettings->validate(); } -void ALEInterface::setInt(const string& key, const int value) { +void ALEInterface::setInt(const std::string& key, const int value) { assert(theSettings.get()); assert(theOSystem.get()); theSettings->setInt(key, value); theSettings->validate(); } -void ALEInterface::setBool(const string& key, const bool value) { +void ALEInterface::setBool(const std::string& key, const bool value) { assert(theSettings.get()); assert(theOSystem.get()); theSettings->setBool(key, value); theSettings->validate(); } -void ALEInterface::setFloat(const string& key, const float value) { +void ALEInterface::setFloat(const std::string& key, const float value) { assert(theSettings.get()); assert(theOSystem.get()); theSettings->setFloat(key, value); theSettings->validate(); } - // Resets the game, but not the full system. void ALEInterface::reset_game() { environment->reset(); @@ -193,8 +242,8 @@ bool ALEInterface::game_over() const { } // The remaining number of lives. -const int ALEInterface::lives() { - if (!romSettings.get()){ +int ALEInterface::lives() { + if (!romSettings.get()) { throw std::runtime_error("ROM not set"); } return romSettings->lives(); @@ -217,10 +266,47 @@ reward_t ALEInterface::act(Action action) { return reward; } +// Returns the vector of modes available for the current game. +// This should be called only after the rom is loaded. +ModeVect ALEInterface::getAvailableModes() { + return romSettings->getAvailableModes(); +} + +// Sets the mode of the game. +// The mode must be an available mode. +// This should be called only after the rom is loaded. +void ALEInterface::setMode(game_mode_t m) { + //We first need to make sure m is an available mode + ModeVect available = romSettings->getAvailableModes(); + if(find(available.begin(), available.end(), m) != available.end()) { + environment->setMode(m); + } else { + throw std::runtime_error("Invalid game mode requested"); + } +} + +//Returns the vector of difficulties available for the current game. +//This should be called only after the rom is loaded. +DifficultyVect ALEInterface::getAvailableDifficulties() { + return romSettings->getAvailableDifficulties(); +} + +// Sets the difficulty of the game. +// The difficulty must be an available mode. +// This should be called only after the rom is loaded. +void ALEInterface::setDifficulty(difficulty_t m) { + DifficultyVect available = romSettings->getAvailableDifficulties(); + if(find(available.begin(), available.end(), m) != available.end()) { + environment->setDifficulty(m); + } else { + throw std::runtime_error("Invalid difficulty requested"); + } +} + // Returns the vector of legal actions. This should be called only // after the rom is loaded. ActionVect ALEInterface::getLegalActionSet() { - if (!romSettings.get()){ + if (!romSettings.get()) { throw std::runtime_error("ROM not set"); } return romSettings->getAllActions(); @@ -229,7 +315,7 @@ ActionVect ALEInterface::getLegalActionSet() { // Returns the vector of the minimal set of actions needed to play // the game. ActionVect ALEInterface::getMinimalActionSet() { - if (!romSettings.get()){ + if (!romSettings.get()) { throw std::runtime_error("ROM not set"); } return romSettings->getMinimalActionSet(); @@ -252,26 +338,28 @@ const ALEScreen& ALEInterface::getScreen() { //This method should receive an empty vector to fill it with //the grayscale colours -void ALEInterface::getScreenGrayscale(std::vector& grayscale_output_buffer){ +void ALEInterface::getScreenGrayscale( + std::vector& grayscale_output_buffer) { size_t w = environment->getScreen().width(); size_t h = environment->getScreen().height(); - size_t screen_size = w*h; - + size_t screen_size = w * h; + pixel_t *ale_screen_data = environment->getScreen().getArray(); - theOSystem->colourPalette().applyPaletteGrayscale(grayscale_output_buffer, ale_screen_data, screen_size); + theOSystem->colourPalette().applyPaletteGrayscale(grayscale_output_buffer, + ale_screen_data, screen_size); } //This method should receive a vector to fill it with //the RGB colours. The first positions contain the red colours, //followed by the green colours and then the blue colours -void ALEInterface::getScreenRGB(std::vector& output_rgb_buffer){ +void ALEInterface::getScreenRGB(std::vector& output_rgb_buffer) { size_t w = environment->getScreen().width(); size_t h = environment->getScreen().height(); - size_t screen_size = w*h; + size_t screen_size = w * h; pixel_t *ale_screen_data = environment->getScreen().getArray(); - theOSystem->colourPalette().applyPaletteRGB(output_rgb_buffer, ale_screen_data, screen_size * 3); + theOSystem->colourPalette().applyPaletteRGB(output_rgb_buffer, ale_screen_data, screen_size); } // Returns the current RAM content @@ -305,12 +393,12 @@ void ALEInterface::restoreSystemState(const ALEState& state) { return environment->restoreSystemState(state); } -void ALEInterface::saveScreenPNG(const string& filename) { - +void ALEInterface::saveScreenPNG(const std::string& filename) { ScreenExporter exporter(theOSystem->colourPalette()); exporter.save(environment->getScreen(), filename); } -ScreenExporter *ALEInterface::createScreenExporter(const std::string &filename) const { - return new ScreenExporter(theOSystem->colourPalette(), filename); +ScreenExporter *ALEInterface::createScreenExporter( + const std::string &filename) const { + return new ScreenExporter(theOSystem->colourPalette(), filename); } diff --git a/atari_py/ale_interface/src/ale_interface.hpp b/atari_py/ale_interface/src/ale_interface.hpp index 997a3e4..5e2fec3 100644 --- a/atari_py/ale_interface/src/ale_interface.hpp +++ b/atari_py/ale_interface/src/ale_interface.hpp @@ -45,7 +45,7 @@ #include #include -static const std::string Version = "0.5.1"; +static const std::string Version = "0.6.0"; /** This class interfaces ALE with external code for controlling agents. @@ -87,6 +87,33 @@ class ALEInterface { // Resets the game, but not the full system. void reset_game(); + // Returns the vector of modes available for the current game. + // This should be called only after the rom is loaded. + ModeVect getAvailableModes(); + + // Sets the mode of the game. + // The mode must be an available mode (otherwise it throws an exception). + // This should be called only after the rom is loaded. + void setMode(game_mode_t m); + + //Returns the vector of difficulties available for the current game. + //This should be called only after the rom is loaded. Notice + // that there are 2 levers, the right and left switches. They + // are not tied to any specific player. In Venture, for example, + // we have the following interpretation for the difficulties: + // Skill Switch + // Level Setting + // 1 left B/right B + // 2 left B/right A + // 3 left A/right B + // 4 left A/right A + DifficultyVect getAvailableDifficulties(); + + // Sets the difficulty of the game. + // The difficulty must be an available mode (otherwise it throws an exception). + // This should be called only after the rom is loaded. + void setDifficulty(difficulty_t m); + // Returns the vector of legal actions. This should be called only // after the rom is loaded. ActionVect getLegalActionSet(); @@ -99,7 +126,7 @@ class ALEInterface { int getFrameNumber(); // The remaining number of lives. - const int lives(); + int lives(); // Returns the frame number since the start of the current episode int getEpisodeFrameNumber() const; @@ -150,20 +177,23 @@ class ALEInterface { ScreenExporter *createScreenExporter(const std::string &path) const; public: - std::auto_ptr theOSystem; - std::auto_ptr theSettings; - std::auto_ptr romSettings; - std::auto_ptr environment; + std::unique_ptr theOSystem; + std::unique_ptr theSettings; + std::unique_ptr romSettings; + std::unique_ptr environment; int max_num_frames; // Maximum number of frames for each episode public: // Display ALE welcome message static std::string welcomeMessage(); static void disableBufferedIO(); - static void createOSystem(std::auto_ptr &theOSystem, - std::auto_ptr &theSettings); + static void createOSystem(std::unique_ptr &theOSystem, + std::unique_ptr &theSettings); static void loadSettings(const std::string& romfile, - std::auto_ptr &theOSystem); + std::unique_ptr &theOSystem); + + private: + static void checkForUnsupportedRom(std::unique_ptr& theOSystem); }; #endif diff --git a/atari_py/ale_interface/src/common/Constants.h b/atari_py/ale_interface/src/common/Constants.h index 0918c2a..3a37fa3 100644 --- a/atari_py/ale_interface/src/common/Constants.h +++ b/atari_py/ale_interface/src/common/Constants.h @@ -79,6 +79,14 @@ std::string action_to_string(Action a); // Define datatypes typedef std::vector ActionVect; +// mode type +typedef unsigned game_mode_t; +typedef std::vector ModeVect; + +// difficulty type +typedef unsigned difficulty_t; +typedef std::vector DifficultyVect; + // reward type for RL interface typedef int reward_t; diff --git a/atari_py/ale_interface/src/common/SoundNull.hxx b/atari_py/ale_interface/src/common/SoundNull.hxx index ecb6d88..adc964b 100644 --- a/atari_py/ale_interface/src/common/SoundNull.hxx +++ b/atari_py/ale_interface/src/common/SoundNull.hxx @@ -41,7 +41,7 @@ class SoundNull : public Sound using the object. */ SoundNull(OSystem* osystem); - + /** Destructor */ @@ -54,7 +54,7 @@ class SoundNull : public Sound @param enable Either true or false, to enable or disable the sound system @return Whether the sound system was enabled or disabled */ - void setEnabled(bool enable) { } + void setEnabled(bool) { } /** The system cycle counter is being adjusting by the specified amount. Any @@ -62,14 +62,14 @@ class SoundNull : public Sound @param amount The amount the cycle counter is being adjusted by */ - void adjustCycleCounter(Int32 amount) { } + void adjustCycleCounter(Int32) { } /** Sets the number of channels (mono or stereo sound). @param channels The number of channels */ - void setChannels(uInt32 channels) { } + void setChannels(uInt32) { } /** Sets the display framerate. Sound generation for NTSC and PAL games @@ -77,7 +77,7 @@ class SoundNull : public Sound @param framerate The base framerate depending on NTSC or PAL ROM */ - void setFrameRate(uInt32 framerate) { } + void setFrameRate(uInt32) { } /** Initializes the sound device. This must be called before any @@ -103,7 +103,7 @@ class SoundNull : public Sound @param state Mutes sound if true, unmute if false */ - void mute(bool state) { } + void mute(bool) { } /** Reset the sound device. @@ -117,7 +117,7 @@ class SoundNull : public Sound @param value The value to save into the register @param cycle The system cycle at which the register is being updated */ - void set(uInt16 addr, uInt8 value, Int32 cycle) { } + void set(uInt16, uInt8, Int32) { } /** Sets the volume of the sound device to the specified level. The @@ -126,7 +126,7 @@ class SoundNull : public Sound @param percent The new volume percentage level for the sound device */ - void setVolume(Int32 percent) { } + void setVolume(Int32) { } /** Adjusts the volume of the sound device based on the given direction. @@ -134,7 +134,7 @@ class SoundNull : public Sound @param direction Increase or decrease the current volume by a predefined amount based on the direction (1 = increase, -1 =decrease) */ - void adjustVolume(Int8 direction) { } + void adjustVolume(Int8) { } /** * Tells the sound engine to record one frame's worth of sound. diff --git a/atari_py/ale_interface/src/common/display_screen.h b/atari_py/ale_interface/src/common/display_screen.h index ffe4abd..60910de 100644 --- a/atari_py/ale_interface/src/common/display_screen.h +++ b/atari_py/ale_interface/src/common/display_screen.h @@ -68,7 +68,7 @@ class DisplayScreen { /** A dummy class that simply ignores display events. */ class DisplayScreen { public: - DisplayScreen(MediaSource* mediaSource, Sound* sound, ColourPalette &palette) {} + DisplayScreen(MediaSource*, Sound*, ColourPalette &) {} void display_screen() {} bool manual_control_engaged() { return false; } Action getUserAction() { return UNDEFINED; } diff --git a/atari_py/ale_interface/src/common/module.mk b/atari_py/ale_interface/src/common/module.mk new file mode 100644 index 0000000..7e977a4 --- /dev/null +++ b/atari_py/ale_interface/src/common/module.mk @@ -0,0 +1,17 @@ +MODULE := src/common + +MODULE_OBJS := \ + src/common/SoundNull.o \ + src/common/SoundSDL.o \ + src/common/SoundExporter.o \ + src/common/display_screen.o \ + src/common/ColourPalette.o \ + src/common/ScreenExporter.o \ + src/common/Constants.o \ + src/common/Log.o + +MODULE_DIRS += \ + src/common + +# Include common rules +include $(srcdir)/common.rules diff --git a/atari_py/ale_interface/src/controllers/ale_controller.hpp b/atari_py/ale_interface/src/controllers/ale_controller.hpp index 8491741..56b68fd 100644 --- a/atari_py/ale_interface/src/controllers/ale_controller.hpp +++ b/atari_py/ale_interface/src/controllers/ale_controller.hpp @@ -22,6 +22,8 @@ #include "../emucore/m6502/src/System.hxx" #include "../environment/stella_environment.hpp" +#include + class ALEController { public: ALEController(OSystem * osystem); @@ -40,7 +42,7 @@ class ALEController { protected: OSystem* m_osystem; - std::auto_ptr m_settings; + std::unique_ptr m_settings; StellaEnvironment m_environment; }; diff --git a/atari_py/ale_interface/src/controllers/module.mk b/atari_py/ale_interface/src/controllers/module.mk new file mode 100644 index 0000000..6363a6c --- /dev/null +++ b/atari_py/ale_interface/src/controllers/module.mk @@ -0,0 +1,12 @@ +MODULE := src/controllers + +MODULE_OBJS := \ + src/controllers/ale_controller.o \ + src/controllers/fifo_controller.o \ + src/controllers/rlglue_controller.o \ + +MODULE_DIRS += \ + src/controllers + +# Include common rules +include $(srcdir)/common.rules diff --git a/atari_py/ale_interface/src/emucore/Control.cxx b/atari_py/ale_interface/src/emucore/Control.cxx index 61984ad..314f743 100644 --- a/atari_py/ale_interface/src/emucore/Control.cxx +++ b/atari_py/ale_interface/src/emucore/Control.cxx @@ -26,14 +26,14 @@ Controller::Controller(Jack jack, const Event& event, Type type) myType(type) { } - + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Controller::~Controller() { } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const Controller::Type Controller::type() +Controller::Type Controller::type() { return myType; } diff --git a/atari_py/ale_interface/src/emucore/Control.hxx b/atari_py/ale_interface/src/emucore/Control.hxx index 1b3a542..07a0bb2 100644 --- a/atari_py/ale_interface/src/emucore/Control.hxx +++ b/atari_py/ale_interface/src/emucore/Control.hxx @@ -87,7 +87,7 @@ class Controller @param type The type for this controller */ Controller(Jack jack, const Event& event, Type type); - + /** Destructor */ @@ -96,7 +96,7 @@ class Controller /** Returns the type of this controller. */ - const Type type(); + Type type(); /** Inform this controller about the current System. diff --git a/atari_py/ale_interface/src/emucore/FSNode.hxx b/atari_py/ale_interface/src/emucore/FSNode.hxx index b05f8f7..3a59c77 100644 --- a/atari_py/ale_interface/src/emucore/FSNode.hxx +++ b/atari_py/ale_interface/src/emucore/FSNode.hxx @@ -1,8 +1,8 @@ //============================================================================ // -// SSSS tt lll lll -// SS SS tt ll ll -// SS tttttt eeee ll ll aaaa +// SSSS tt lll lll +// SS SS tt ll ll +// SS tttttt eeee ll ll aaaa // SSSS tt ee ee ll ll aa // SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" // SS SS tt ee ll ll aa aa @@ -47,8 +47,8 @@ * And if we ever want to support devices with no FS in the classical sense (Palm...), * we can build upon this. */ - -/* + +/* * TODO - Instead of starting with getRoot(), we should rather add a getDefaultDir() * call that on Unix might return the current dir or the users home dir... * i.e. the root dir is usually not the best starting point for browsing. @@ -120,10 +120,8 @@ class AbstractFilesystemNode { std::string first = displayName(); std::string second = node.displayName(); - std::transform( - first.begin(), first.end(), first.begin(), (int(*)(int)) tolower); - std::transform( - second.begin(), second.end(), second.begin(), (int(*)(int)) tolower); + std::transform(first.begin(), first.end(), first.begin(), (int(*)(int)) tolower); + std::transform(second.begin(), second.end(), second.begin(), (int(*)(int)) tolower); return first < second; } @@ -157,7 +155,7 @@ class AbstractFilesystemNode virtual AbstractFilesystemNode *parent() const = 0; /** - * This method is a rather ugly hack which is used internally by the + * This method is a rather ugly hack which is used internally by the * actual node implementions to wrap up raw nodes inside FilesystemNode * objects. We probably want to get rid of this eventually and replace it * with a cleaner / more elegant solution, but for now it works. diff --git a/atari_py/ale_interface/src/emucore/OSystem.hxx b/atari_py/ale_interface/src/emucore/OSystem.hxx index 4eca7d6..2315627 100644 --- a/atari_py/ale_interface/src/emucore/OSystem.hxx +++ b/atari_py/ale_interface/src/emucore/OSystem.hxx @@ -223,8 +223,8 @@ class OSystem /** Get the maximum dimensions of a window for the video hardware. */ - const uInt32 desktopWidth() const { return myDesktopWidth; } - const uInt32 desktopHeight() const { return myDesktopHeight; } + uInt32 desktopWidth() const { return myDesktopWidth; } + uInt32 desktopHeight() const { return myDesktopHeight; } /** Get the supported fullscreen resolutions for the video hardware. @@ -410,7 +410,7 @@ class OSystem */ //ALE virtual void stateChanged(EventHandler::State state); - + protected: /** Query the OSystem video hardware for resolution information. @@ -434,7 +434,7 @@ class OSystem void setConfigFile(const std::string& file) { myConfigFile = file; } - + protected: // Pointer to the EventHandler object //ALE EventHandler* myEventHandler; @@ -455,10 +455,10 @@ class OSystem // Pointer to the (currently defined) Console object Console* myConsole; - + // Random number generator shared across the emulator's components Random myRandGen; - + // Pointer to the Menu object //ALE Menu* myMenu; @@ -476,7 +476,7 @@ class OSystem // Pointer to the AI object //ALE AIBase *aiBase; - + // Maximum dimensions of the desktop area uInt32 myDesktopWidth, myDesktopHeight; @@ -515,7 +515,7 @@ class OSystem // The font object to use for the console/debugger //ALE GUI::Font* myConsoleFont; - + public: //ALE // Time per frame for a video update, based on the current framerate uInt32 myTimePerFrame; @@ -536,7 +536,7 @@ class OSystem //ALE static uInt32 ourGUIColors[kNumUIPalettes][kNumColors-256]; public: DisplayScreen* p_display_screen; //MHAUSKN - + private: ColourPalette m_colour_palette; diff --git a/atari_py/ale_interface/src/emucore/Random.cxx b/atari_py/ale_interface/src/emucore/Random.cxx index 6f3075e..462509a 100644 --- a/atari_py/ale_interface/src/emucore/Random.cxx +++ b/atari_py/ale_interface/src/emucore/Random.cxx @@ -21,9 +21,9 @@ #include "Serializer.hxx" #include "Deserializer.hxx" -// TODO(mgb): bring this include in once we switch to C++11. -// #include -#include "TinyMT/tinymt32.h" +// This uses C++11. +#include +#include // A static Random object for compatibility purposes. Don't use this. Random Random::s_random; @@ -31,7 +31,7 @@ Random Random::s_random; // Implementation of Random's random number generator wrapper. class Random::Impl { - typedef tinymt32_t randgen_t; + typedef std::mt19937 randgen_t; public: @@ -56,32 +56,25 @@ class Random::Impl { Random::Impl::Impl() { // Initialize seed to time - //seed((uInt32) time(NULL)); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void Random::Impl::seed(uInt32 value) { m_seed = value; - // TODO(mgb): this is the C++11 variant. - // rndGenerator.seed(ourSeed); - tinymt32_init(&m_randgen, m_seed); + m_randgen.seed(m_seed); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt32 Random::Impl::next() { - // TODO(mgb): C++11 - // return rndGenerator(); - return static_cast(tinymt32_generate_uint32(&m_randgen)); + return m_randgen(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - double Random::Impl::nextDouble() { - // TODO(mgb): C++11 - // return rndGenerator() / double(rndGenerator.max() + 1.0); - return tinymt32_generate_32double(&m_randgen); + return m_randgen() / double(m_randgen.max() + 1.0); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -121,26 +114,20 @@ Random& Random::getInstance() { } bool Random::saveState(Serializer& ser) { + // The mt19937 object's serialization of choice is into a string. + std::ostringstream oss; + oss << m_pimpl->m_randgen; - // Serialize the TinyMT state - for (int i = 0; i < 4; i++) - ser.putInt(m_pimpl->m_randgen.status[i]); - // These aren't really needed, but we serialize them anyway - ser.putInt(m_pimpl->m_randgen.mat1); - ser.putInt(m_pimpl->m_randgen.mat2); - ser.putInt(m_pimpl->m_randgen.tmat); + ser.putString(oss.str()); return true; } bool Random::loadState(Deserializer& deser) { + // Deserialize into a string. + std::istringstream iss(deser.getString()); - // Deserialize the TinyMT state - for (int i = 0; i < 4; i++) - m_pimpl->m_randgen.status[i] = deser.getInt(); - m_pimpl->m_randgen.mat1 = deser.getInt(); - m_pimpl->m_randgen.mat2 = deser.getInt(); - m_pimpl->m_randgen.tmat = deser.getInt(); + iss >> m_pimpl->m_randgen; return true; } diff --git a/atari_py/ale_interface/src/emucore/Random.hxx b/atari_py/ale_interface/src/emucore/Random.hxx index 6410983..4aef44e 100644 --- a/atari_py/ale_interface/src/emucore/Random.hxx +++ b/atari_py/ale_interface/src/emucore/Random.hxx @@ -77,8 +77,7 @@ class Random private: - // Actual rng (implementation hidden away from the header to avoid depending on - // tinymt). + // Actual rng (implementation hidden away from the header to avoid depending on rng libraries). class Impl; Impl *m_pimpl; diff --git a/atari_py/ale_interface/src/emucore/m6502/module.mk b/atari_py/ale_interface/src/emucore/m6502/module.mk new file mode 100644 index 0000000..9361d5b --- /dev/null +++ b/atari_py/ale_interface/src/emucore/m6502/module.mk @@ -0,0 +1,15 @@ +MODULE := src/emucore/m6502 + +MODULE_OBJS := \ + src/emucore/m6502/src/Device.o \ + src/emucore/m6502/src/M6502.o \ + src/emucore/m6502/src/M6502Low.o \ + src/emucore/m6502/src/M6502Hi.o \ + src/emucore/m6502/src/NullDev.o \ + src/emucore/m6502/src/System.o + +MODULE_DIRS += \ + src/emucore/m6502/src + +# Include common rules +include $(srcdir)/common.rules diff --git a/atari_py/ale_interface/src/emucore/module.mk b/atari_py/ale_interface/src/emucore/module.mk new file mode 100644 index 0000000..d290639 --- /dev/null +++ b/atari_py/ale_interface/src/emucore/module.mk @@ -0,0 +1,56 @@ +MODULE := src/emucore + +MODULE_OBJS := \ + src/emucore/AtariVox.o \ + src/emucore/Booster.o \ + src/emucore/Cart2K.o \ + src/emucore/Cart3F.o \ + src/emucore/Cart3E.o \ + src/emucore/Cart4A50.o \ + src/emucore/Cart4K.o \ + src/emucore/CartAR.o \ + src/emucore/CartCV.o \ + src/emucore/Cart.o \ + src/emucore/CartDPC.o \ + src/emucore/CartE0.o \ + src/emucore/CartE7.o \ + src/emucore/CartF4.o \ + src/emucore/CartF4SC.o \ + src/emucore/CartF6.o \ + src/emucore/CartF6SC.o \ + src/emucore/CartF8.o \ + src/emucore/CartF8SC.o \ + src/emucore/CartFASC.o \ + src/emucore/CartFE.o \ + src/emucore/CartMB.o \ + src/emucore/CartMC.o \ + src/emucore/CartUA.o \ + src/emucore/Cart0840.o \ + src/emucore/Console.o \ + src/emucore/Control.o \ + src/emucore/Deserializer.o \ + src/emucore/Driving.o \ + src/emucore/Event.o \ + src/emucore/FSNode.o \ + src/emucore/Joystick.o \ + src/emucore/Keyboard.o \ + src/emucore/M6532.o \ + src/emucore/MD5.o \ + src/emucore/MediaSrc.o \ + src/emucore/OSystem.o \ + src/emucore/Paddles.o \ + src/emucore/Props.o \ + src/emucore/PropsSet.o \ + src/emucore/Random.o \ + src/emucore/Serializer.o \ + src/emucore/Settings.o \ + src/emucore/SpeakJet.o \ + src/emucore/Switches.o \ + src/emucore/TIA.o \ + src/emucore/TIASnd.o \ + +MODULE_DIRS += \ + src/emucore + +# Include common rules +include $(srcdir)/common.rules diff --git a/atari_py/ale_interface/src/emucore/rsynth/module.mk b/atari_py/ale_interface/src/emucore/rsynth/module.mk new file mode 100644 index 0000000..b1ad52a --- /dev/null +++ b/atari_py/ale_interface/src/emucore/rsynth/module.mk @@ -0,0 +1,16 @@ +MODULE := src/emucore/rsynth + +MODULE_OBJS := \ + src/emucore/rsynth/darray.o \ + src/emucore/rsynth/elements.o \ + src/emucore/rsynth/holmes.o \ + src/emucore/rsynth/opsynth.o \ + src/emucore/rsynth/phones.o \ + src/emucore/rsynth/phtoelm.o \ + src/emucore/rsynth/trie.o + +MODULE_DIRS += \ + src/emucore/rsynth + +# Include common rules +include $(srcdir)/common.rules diff --git a/atari_py/ale_interface/src/emucore/unzip.c b/atari_py/ale_interface/src/emucore/unzip.c deleted file mode 100644 index 7e4344e..0000000 --- a/atari_py/ale_interface/src/emucore/unzip.c +++ /dev/null @@ -1,1273 +0,0 @@ -/* unzip.c -- IO on .zip files using zlib - Version 0.15 beta, Mar 19th, 1998, - - Read unzip.h for more info -*/ - - -#include -#include -#include -#include - -#include "unzip.h" - -#ifdef STDC -# include -# include -# include -#endif -#ifdef NO_ERRNO_H - extern int errno; -#else -# include -#endif - -#ifndef local -# define local static -#endif -/* compile with -Dlocal if your debugger can't find static symbols */ - - - -#if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) && \ - !defined(CASESENSITIVITYDEFAULT_NO) -#define CASESENSITIVITYDEFAULT_NO -#endif - - -#ifndef UNZ_BUFSIZE -#define UNZ_BUFSIZE (16384) -#endif - -#ifndef UNZ_MAXFILENAMEINZIP -#define UNZ_MAXFILENAMEINZIP (256) -#endif - -#ifndef ALLOC -# define ALLOC(size) (malloc(size)) -#endif -#ifndef TRYFREE -# define TRYFREE(p) {if (p) free(p);} -#endif - -#define SIZECENTRALDIRITEM (0x2e) -#define SIZEZIPLOCALHEADER (0x1e) - - -/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ - -#ifndef SEEK_CUR -#define SEEK_CUR 1 -#endif - -#ifndef SEEK_END -#define SEEK_END 2 -#endif - -#ifndef SEEK_SET -#define SEEK_SET 0 -#endif - -const char unz_copyright[] = - " unzip 0.15 Copyright 1998 Gilles Vollant "; - -/* unz_file_info_interntal contain internal info about a file in zipfile*/ -typedef struct unz_file_info_internal_s -{ - uLong offset_curfile;/* relative offset of local header 4 bytes */ -} unz_file_info_internal; - - -/* file_in_zip_read_info_s contain internal information about a file in zipfile, - when reading and decompress it */ -typedef struct -{ - char *read_buffer; /* internal buffer for compressed data */ - z_stream stream; /* zLib stream structure for inflate */ - - uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ - uLong stream_initialised; /* flag set if stream structure is initialised*/ - - uLong offset_local_extrafield;/* offset of the local extra field */ - uInt size_local_extrafield;/* size of the local extra field */ - uLong pos_local_extrafield; /* position in the local extra field in read*/ - - uLong crc32; /* crc32 of all data uncompressed */ - uLong crc32_wait; /* crc32 we must obtain after decompress all */ - uLong rest_read_compressed; /* number of byte to be decompressed */ - uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/ - FILE* file; /* io structore of the zipfile */ - uLong compression_method; /* compression method (0==store) */ - uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ -} file_in_zip_read_info_s; - - -/* unz_s contain internal information about the zipfile -*/ -typedef struct -{ - FILE* file; /* io structore of the zipfile */ - unz_global_info gi; /* public global information */ - uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ - uLong num_file; /* number of the current file in the zipfile*/ - uLong pos_in_central_dir; /* pos of the current file in the central dir*/ - uLong current_file_ok; /* flag about the usability of the current file*/ - uLong central_pos; /* position of the beginning of the central dir*/ - - uLong size_central_dir; /* size of the central directory */ - uLong offset_central_dir; /* offset of start of central directory with - respect to the starting disk number */ - - unz_file_info cur_file_info; /* public info about the current file in zip*/ - unz_file_info_internal cur_file_info_internal; /* private info about it*/ - file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current - file if we are decompressing it */ -} unz_s; - - -/* =========================================================================== - Read a byte from a gz_stream; update next_in and avail_in. Return EOF - for end of file. - IN assertion: the stream s has been sucessfully opened for reading. -*/ - - -local int unzlocal_getByte(FILE* fin, int* pi) -{ - unsigned char c; - int err = fread(&c, 1, 1, fin); - if (err==1) - { - *pi = (int)c; - return UNZ_OK; - } - else - { - if (ferror(fin)) - return UNZ_ERRNO; - else - return UNZ_EOF; - } -} - - -/* =========================================================================== - Reads a long in LSB order from the given gz_stream. Sets -*/ -local int unzlocal_getShort (FILE* fin,uLong* pX) -{ - uLong x ; - int i = 0; - int err; - - err = unzlocal_getByte(fin,&i); - x = (uLong)i; - - if (err==UNZ_OK) - err = unzlocal_getByte(fin,&i); - x += ((uLong)i)<<8; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; -} - -local int unzlocal_getLong (FILE* fin,uLong* pX) -{ - uLong x ; - int i = 0; - int err; - - err = unzlocal_getByte(fin,&i); - x = (uLong)i; - - if (err==UNZ_OK) - err = unzlocal_getByte(fin,&i); - x += ((uLong)i)<<8; - - if (err==UNZ_OK) - err = unzlocal_getByte(fin,&i); - x += ((uLong)i)<<16; - - if (err==UNZ_OK) - err = unzlocal_getByte(fin,&i); - x += ((uLong)i)<<24; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; -} - - -/* My own strcmpi / strcasecmp */ -local int strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2) -{ - for (;;) - { - char c1=*(fileName1++); - char c2=*(fileName2++); - if ((c1>='a') && (c1<='z')) - c1 -= 0x20; - if ((c2>='a') && (c2<='z')) - c2 -= 0x20; - if (c1=='\0') - return ((c2=='\0') ? 0 : -1); - if (c2=='\0') - return 1; - if (c1c2) - return 1; - } -} - - -#ifdef CASESENSITIVITYDEFAULT_NO -#define CASESENSITIVITYDEFAULTVALUE 2 -#else -#define CASESENSITIVITYDEFAULTVALUE 1 -#endif - -#ifndef STRCMPCASENOSENTIVEFUNCTION -#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal -#endif - -/* - Compare two filename (fileName1,fileName2). - If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) - If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi - or strcasecmp) - If iCaseSenisivity = 0, case sensitivity is defaut of your operating system - (like 1 on Unix, 2 on Windows) - -*/ -extern int ZEXPORT unzStringFileNameCompare - (const char* fileName1, const char* fileName2, int iCaseSensitivity) -{ - if (iCaseSensitivity==0) - iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; - - if (iCaseSensitivity==1) - return strcmp(fileName1,fileName2); - - return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); -} - -#define BUFREADCOMMENT (0x400) - -/* - Locate the Central directory of a zipfile (at the end, just before - the global comment) -*/ -local uLong unzlocal_SearchCentralDir(FILE* fin) -{ - unsigned char* buf; - uLong uSizeFile; - uLong uBackRead; - uLong uMaxBack=0xffff; /* maximum size of global comment */ - uLong uPosFound=0; - - if (fseek(fin,0,SEEK_END) != 0) - return 0; - - - uSizeFile = ftell( fin ); - - if (uMaxBack>uSizeFile) - uMaxBack = uSizeFile; - - buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); - if (buf==NULL) - return 0; - - uBackRead = 4; - while (uBackReaduMaxBack) - uBackRead = uMaxBack; - else - uBackRead+=BUFREADCOMMENT; - uReadPos = uSizeFile-uBackRead ; - - uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? - (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); - if (fseek(fin,uReadPos,SEEK_SET)!=0) - break; - - if (fread(buf,(uInt)uReadSize,1,fin)!=1) - break; - - for (i=(int)uReadSize-3; (i--)>0;) - if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && - ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) - { - uPosFound = uReadPos+i; - break; - } - - if (uPosFound!=0) - break; - } - TRYFREE(buf); - return uPosFound; -} - -/* - Open a Zip file. path contain the full pathname (by example, - on a Windows NT computer "c:\\test\\zlib109.zip" or on an Unix computer - "zlib/zlib109.zip". - If the zipfile cannot be opened (file don't exist or in not valid), the - return value is NULL. - Else, the return value is a unzFile Handle, usable with other function - of this unzip package. -*/ -extern unzFile ZEXPORT unzOpen(const char *path) -{ - unz_s us; - unz_s *s; - uLong central_pos,uL; - FILE * fin ; - - uLong number_disk; /* number of the current dist, used for - spaning ZIP, unsupported, always 0*/ - uLong number_disk_with_CD; /* number the the disk with central dir, used - for spaning ZIP, unsupported, always 0*/ - uLong number_entry_CD; /* total number of entries in - the central dir - (same than number_entry on nospan) */ - - int err=UNZ_OK; - - if (unz_copyright[0]!=' ') - return NULL; - - fin=fopen(path,"rb"); - if (fin==NULL) - return NULL; - - central_pos = unzlocal_SearchCentralDir(fin); - if (central_pos==0) - err=UNZ_ERRNO; - - if (fseek(fin,central_pos,SEEK_SET)!=0) - err=UNZ_ERRNO; - - /* the signature, already checked */ - if (unzlocal_getLong(fin,&uL)!=UNZ_OK) - err=UNZ_ERRNO; - - /* number of this disk */ - if (unzlocal_getShort(fin,&number_disk)!=UNZ_OK) - err=UNZ_ERRNO; - - /* number of the disk with the start of the central directory */ - if (unzlocal_getShort(fin,&number_disk_with_CD)!=UNZ_OK) - err=UNZ_ERRNO; - - /* total number of entries in the central dir on this disk */ - if (unzlocal_getShort(fin,&us.gi.number_entry)!=UNZ_OK) - err=UNZ_ERRNO; - - /* total number of entries in the central dir */ - if (unzlocal_getShort(fin,&number_entry_CD)!=UNZ_OK) - err=UNZ_ERRNO; - - if ((number_entry_CD!=us.gi.number_entry) || - (number_disk_with_CD!=0) || - (number_disk!=0)) - err=UNZ_BADZIPFILE; - - /* size of the central directory */ - if (unzlocal_getLong(fin,&us.size_central_dir)!=UNZ_OK) - err=UNZ_ERRNO; - - /* offset of start of central directory with respect to the - starting disk number */ - if (unzlocal_getLong(fin,&us.offset_central_dir)!=UNZ_OK) - err=UNZ_ERRNO; - - /* zipfile comment length */ - if (unzlocal_getShort(fin,&us.gi.size_comment)!=UNZ_OK) - err=UNZ_ERRNO; - - if ((central_pospfile_in_zip_read!=NULL) - unzCloseCurrentFile(file); - - fclose(s->file); - TRYFREE(s); - return UNZ_OK; -} - - -/* - Write info about the ZipFile in the *pglobal_info structure. - No preparation of the structure is needed - return UNZ_OK if there is no problem. */ -extern int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info* pglobal_info) -{ - unz_s* s; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - *pglobal_info=s->gi; - return UNZ_OK; -} - - -/* - Translate date/time from Dos format to tm_unz (readable more easilty) -*/ -local void unzlocal_DosDateToTmuDate (uLong ulDosDate, tm_unz* ptm) -{ - uLong uDate; - uDate = (uLong)(ulDosDate>>16); - ptm->tm_mday = (uInt)(uDate&0x1f) ; - ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; - ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; - - ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); - ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; - ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; -} - -/* - Get Info about the current file in the zipfile, with internal only info -*/ -local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file, - unz_file_info *pfile_info, - unz_file_info_internal - *pfile_info_internal, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize)); - -local int unzlocal_GetCurrentFileInfoInternal - ( unzFile file, - unz_file_info *pfile_info, - unz_file_info_internal *pfile_info_internal, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize) -{ - unz_s* s; - unz_file_info file_info; - unz_file_info_internal file_info_internal; - int err=UNZ_OK; - uLong uMagic; - long lSeek=0; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (fseek(s->file,s->pos_in_central_dir+s->byte_before_the_zipfile,SEEK_SET)!=0) - err=UNZ_ERRNO; - - - /* we check the magic */ - if (err==UNZ_OK) - { - if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK) - err=UNZ_ERRNO; - else if (uMagic!=0x02014b50) - err=UNZ_BADZIPFILE; - } - - if (unzlocal_getShort(s->file,&file_info.version) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&file_info.version_needed) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&file_info.flag) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&file_info.compression_method) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(s->file,&file_info.dosDate) != UNZ_OK) - err=UNZ_ERRNO; - - unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); - - if (unzlocal_getLong(s->file,&file_info.crc) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(s->file,&file_info.compressed_size) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(s->file,&file_info.uncompressed_size) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&file_info.size_filename) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&file_info.size_file_extra) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&file_info.size_file_comment) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&file_info.disk_num_start) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&file_info.internal_fa) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(s->file,&file_info.external_fa) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(s->file,&file_info_internal.offset_curfile) != UNZ_OK) - err=UNZ_ERRNO; - - lSeek+=file_info.size_filename; - if ((err==UNZ_OK) && (szFileName!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_filename0) && (fileNameBufferSize>0)) - if (fread(szFileName,(uInt)uSizeRead,1,s->file)!=1) - err=UNZ_ERRNO; - lSeek -= uSizeRead; - } - - - if ((err==UNZ_OK) && (extraField!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_file_extrafile,lSeek,SEEK_CUR)==0) - lSeek=0; - else - err=UNZ_ERRNO; - } - if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) - if (fread(extraField,(uInt)uSizeRead,1,s->file)!=1) - err=UNZ_ERRNO; - lSeek += file_info.size_file_extra - uSizeRead; - } - else - lSeek+=file_info.size_file_extra; - - - if ((err==UNZ_OK) && (szComment!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_file_commentfile,lSeek,SEEK_CUR)==0) - lSeek=0; - else - err=UNZ_ERRNO; - } - if ((file_info.size_file_comment>0) && (commentBufferSize>0)) - if (fread(szComment,(uInt)uSizeRead,1,s->file)!=1) - err=UNZ_ERRNO; - lSeek+=file_info.size_file_comment - uSizeRead; - } - else - lSeek+=file_info.size_file_comment; - - if ((err==UNZ_OK) && (pfile_info!=NULL)) - *pfile_info=file_info; - - if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) - *pfile_info_internal=file_info_internal; - - return err; -} - - - -/* - Write info about the ZipFile in the *pglobal_info structure. - No preparation of the structure is needed - return UNZ_OK if there is no problem. -*/ -extern int ZEXPORT unzGetCurrentFileInfo - ( unzFile file, - unz_file_info *pfile_info, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize - ) -{ - return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL, - szFileName,fileNameBufferSize, - extraField,extraFieldBufferSize, - szComment,commentBufferSize); -} - -/* - Set the current file of the zipfile to the first file. - return UNZ_OK if there is no problem -*/ -extern int ZEXPORT unzGoToFirstFile (unzFile file) -{ - int err=UNZ_OK; - unz_s* s; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - s->pos_in_central_dir=s->offset_central_dir; - s->num_file=0; - err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - s->current_file_ok = (err == UNZ_OK); - return err; -} - - -/* - Set the current file of the zipfile to the next file. - return UNZ_OK if there is no problem - return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. -*/ -extern int ZEXPORT unzGoToNextFile (unzFile file) -{ - unz_s* s; - int err; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (!s->current_file_ok) - return UNZ_END_OF_LIST_OF_FILE; - if (s->num_file+1==s->gi.number_entry) - return UNZ_END_OF_LIST_OF_FILE; - - s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + - s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; - s->num_file++; - err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - s->current_file_ok = (err == UNZ_OK); - return err; -} - - -/* - Try locate the file szFileName in the zipfile. - For the iCaseSensitivity signification, see unzipStringFileNameCompare - - return value : - UNZ_OK if the file is found. It becomes the current file. - UNZ_END_OF_LIST_OF_FILE if the file is not found -*/ -extern int ZEXPORT unzLocateFile - ( unzFile file, - const char *szFileName, - int iCaseSensitivity - ) -{ - unz_s* s; - int err; - - - uLong num_fileSaved; - uLong pos_in_central_dirSaved; - - - if (file==NULL) - return UNZ_PARAMERROR; - - if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) - return UNZ_PARAMERROR; - - s=(unz_s*)file; - if (!s->current_file_ok) - return UNZ_END_OF_LIST_OF_FILE; - - num_fileSaved = s->num_file; - pos_in_central_dirSaved = s->pos_in_central_dir; - - err = unzGoToFirstFile(file); - - while (err == UNZ_OK) - { - char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; - unzGetCurrentFileInfo(file,NULL, - szCurrentFileName,sizeof(szCurrentFileName)-1, - NULL,0,NULL,0); - if (unzStringFileNameCompare(szCurrentFileName, - szFileName,iCaseSensitivity)==0) - return UNZ_OK; - err = unzGoToNextFile(file); - } - - s->num_file = num_fileSaved ; - s->pos_in_central_dir = pos_in_central_dirSaved ; - return err; -} - - -/* - Read the local header of the current zipfile - Check the coherency of the local header and info in the end of central - directory about this file - store in *piSizeVar the size of extra info in local header - (filename and size of extra field data) -*/ -local int unzlocal_CheckCurrentFileCoherencyHeader - ( unz_s* s, - uInt* piSizeVar, - uLong *poffset_local_extrafield, - uInt *psize_local_extrafield - ) -{ - uLong uMagic,uData,uFlags; - uLong size_filename; - uLong size_extra_field; - int err=UNZ_OK; - - *piSizeVar = 0; - *poffset_local_extrafield = 0; - *psize_local_extrafield = 0; - - if (fseek(s->file,s->cur_file_info_internal.offset_curfile + - s->byte_before_the_zipfile,SEEK_SET)!=0) - return UNZ_ERRNO; - - - if (err==UNZ_OK) - { - if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK) - err=UNZ_ERRNO; - else if (uMagic!=0x04034b50) - err=UNZ_BADZIPFILE; - } - - if (unzlocal_getShort(s->file,&uData) != UNZ_OK) - err=UNZ_ERRNO; -/* - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) - err=UNZ_BADZIPFILE; -*/ - if (unzlocal_getShort(s->file,&uFlags) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&uData) != UNZ_OK) - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) - err=UNZ_BADZIPFILE; - - if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && - (s->cur_file_info.compression_method!=Z_DEFLATED)) - err=UNZ_BADZIPFILE; - - if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* date/time */ - err=UNZ_ERRNO; - - if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* crc */ - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && - ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size compr */ - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && - ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size uncompr */ - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && - ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - - if (unzlocal_getShort(s->file,&size_filename) != UNZ_OK) - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) - err=UNZ_BADZIPFILE; - - *piSizeVar += (uInt)size_filename; - - if (unzlocal_getShort(s->file,&size_extra_field) != UNZ_OK) - err=UNZ_ERRNO; - *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + - SIZEZIPLOCALHEADER + size_filename; - *psize_local_extrafield = (uInt)size_extra_field; - - *piSizeVar += (uInt)size_extra_field; - - return err; -} - -/* - Open for reading data the current file in the zipfile. - If there is no error and the file is opened, the return value is UNZ_OK. -*/ -extern int ZEXPORT unzOpenCurrentFile (unzFile file) -{ - int err=UNZ_OK; - int Store; - uInt iSizeVar; - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - uLong offset_local_extrafield; /* offset of the local extra field */ - uInt size_local_extrafield; /* size of the local extra field */ - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (!s->current_file_ok) - return UNZ_PARAMERROR; - - if (s->pfile_in_zip_read != NULL) - unzCloseCurrentFile(file); - - if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar, - &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) - return UNZ_BADZIPFILE; - - pfile_in_zip_read_info = (file_in_zip_read_info_s*) - ALLOC(sizeof(file_in_zip_read_info_s)); - if (pfile_in_zip_read_info==NULL) - return UNZ_INTERNALERROR; - - pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE); - pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; - pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; - pfile_in_zip_read_info->pos_local_extrafield=0; - - if (pfile_in_zip_read_info->read_buffer==NULL) - { - TRYFREE(pfile_in_zip_read_info); - return UNZ_INTERNALERROR; - } - - pfile_in_zip_read_info->stream_initialised=0; - - if ((s->cur_file_info.compression_method!=0) && - (s->cur_file_info.compression_method!=Z_DEFLATED)) - err=UNZ_BADZIPFILE; - Store = s->cur_file_info.compression_method==0; - - pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; - pfile_in_zip_read_info->crc32=0; - pfile_in_zip_read_info->compression_method = - s->cur_file_info.compression_method; - pfile_in_zip_read_info->file=s->file; - pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; - - pfile_in_zip_read_info->stream.total_out = 0; - - if (!Store) - { - pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; - pfile_in_zip_read_info->stream.zfree = (free_func)0; - pfile_in_zip_read_info->stream.opaque = (voidpf)0; - - err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); - if (err == Z_OK) - pfile_in_zip_read_info->stream_initialised=1; - /* windowBits is passed < 0 to tell that there is no zlib header. - * Note that in this case inflate *requires* an extra "dummy" byte - * after the compressed stream in order to complete decompression and - * return Z_STREAM_END. - * In unzip, i don't wait absolutely Z_STREAM_END because I known the - * size of both compressed and uncompressed data - */ - } - pfile_in_zip_read_info->rest_read_compressed = - s->cur_file_info.compressed_size ; - pfile_in_zip_read_info->rest_read_uncompressed = - s->cur_file_info.uncompressed_size ; - - - pfile_in_zip_read_info->pos_in_zipfile = - s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + - iSizeVar; - - pfile_in_zip_read_info->stream.avail_in = (uInt)0; - - - s->pfile_in_zip_read = pfile_in_zip_read_info; - return UNZ_OK; -} - - -/* - Read bytes from the current file. - buf contain buffer where data must be copied - len the size of buf. - - return the number of byte copied if somes bytes are copied - return 0 if the end of file was reached - return <0 with error code if there is an error - (UNZ_ERRNO for IO error, or zLib error for uncompress error) -*/ -extern int ZEXPORT unzReadCurrentFile - ( unzFile file, - voidp buf, - unsigned len - ) -{ - int err=UNZ_OK; - uInt iRead = 0; - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - - if (pfile_in_zip_read_info->read_buffer == NULL) - return UNZ_END_OF_LIST_OF_FILE; - if (len==0) - return 0; - - pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; - - pfile_in_zip_read_info->stream.avail_out = (uInt)len; - - if (len>pfile_in_zip_read_info->rest_read_uncompressed) - pfile_in_zip_read_info->stream.avail_out = - (uInt)pfile_in_zip_read_info->rest_read_uncompressed; - - while (pfile_in_zip_read_info->stream.avail_out>0) - { - if ((pfile_in_zip_read_info->stream.avail_in==0) && - (pfile_in_zip_read_info->rest_read_compressed>0)) - { - uInt uReadThis = UNZ_BUFSIZE; - if (pfile_in_zip_read_info->rest_read_compressedrest_read_compressed; - if (uReadThis == 0) - return UNZ_EOF; - if (fseek(pfile_in_zip_read_info->file, - pfile_in_zip_read_info->pos_in_zipfile + - pfile_in_zip_read_info->byte_before_the_zipfile,SEEK_SET)!=0) - return UNZ_ERRNO; - if (fread(pfile_in_zip_read_info->read_buffer,uReadThis,1, - pfile_in_zip_read_info->file)!=1) - return UNZ_ERRNO; - pfile_in_zip_read_info->pos_in_zipfile += uReadThis; - - pfile_in_zip_read_info->rest_read_compressed-=uReadThis; - - pfile_in_zip_read_info->stream.next_in = - (Bytef*)pfile_in_zip_read_info->read_buffer; - pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; - } - - if (pfile_in_zip_read_info->compression_method==0) - { - uInt uDoCopy,i ; - if (pfile_in_zip_read_info->stream.avail_out < - pfile_in_zip_read_info->stream.avail_in) - uDoCopy = pfile_in_zip_read_info->stream.avail_out ; - else - uDoCopy = pfile_in_zip_read_info->stream.avail_in ; - - for (i=0;istream.next_out+i) = - *(pfile_in_zip_read_info->stream.next_in+i); - - pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, - pfile_in_zip_read_info->stream.next_out, - uDoCopy); - pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; - pfile_in_zip_read_info->stream.avail_in -= uDoCopy; - pfile_in_zip_read_info->stream.avail_out -= uDoCopy; - pfile_in_zip_read_info->stream.next_out += uDoCopy; - pfile_in_zip_read_info->stream.next_in += uDoCopy; - pfile_in_zip_read_info->stream.total_out += uDoCopy; - iRead += uDoCopy; - } - else - { - uLong uTotalOutBefore,uTotalOutAfter; - const Bytef *bufBefore; - uLong uOutThis; - int flush=Z_SYNC_FLUSH; - - uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; - bufBefore = pfile_in_zip_read_info->stream.next_out; - - /* - if ((pfile_in_zip_read_info->rest_read_uncompressed == - pfile_in_zip_read_info->stream.avail_out) && - (pfile_in_zip_read_info->rest_read_compressed == 0)) - flush = Z_FINISH; - */ - err=inflate(&pfile_in_zip_read_info->stream,flush); - - uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; - uOutThis = uTotalOutAfter-uTotalOutBefore; - - pfile_in_zip_read_info->crc32 = - crc32(pfile_in_zip_read_info->crc32,bufBefore, - (uInt)(uOutThis)); - - pfile_in_zip_read_info->rest_read_uncompressed -= - uOutThis; - - iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); - - if (err==Z_STREAM_END) - return (iRead==0) ? UNZ_EOF : iRead; - if (err!=Z_OK) - break; - } - } - - if (err==Z_OK) - return iRead; - return err; -} - - -/* - Give the current position in uncompressed data -*/ -extern z_off_t ZEXPORT unztell (unzFile file) -{ - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - return (z_off_t)pfile_in_zip_read_info->stream.total_out; -} - - -/* - return 1 if the end of file was reached, 0 elsewhere -*/ -extern int ZEXPORT unzeof (unzFile file) -{ - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - if (pfile_in_zip_read_info->rest_read_uncompressed == 0) - return 1; - else - return 0; -} - - - -/* - Read extra field from the current file (opened by unzOpenCurrentFile) - This is the local-header version of the extra field (sometimes, there is - more info in the local-header version than in the central-header) - - if buf==NULL, it return the size of the local extra field that can be read - - if buf!=NULL, len is the size of the buffer, the extra header is copied in - buf. - the return value is the number of bytes copied in buf, or (if <0) - the error code -*/ -extern int ZEXPORT unzGetLocalExtrafield - ( unzFile file, - voidp buf, - unsigned len - ) -{ - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - uInt read_now; - uLong size_to_read; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - size_to_read = (pfile_in_zip_read_info->size_local_extrafield - - pfile_in_zip_read_info->pos_local_extrafield); - - if (buf==NULL) - return (int)size_to_read; - - if (len>size_to_read) - read_now = (uInt)size_to_read; - else - read_now = (uInt)len ; - - if (read_now==0) - return 0; - - if (fseek(pfile_in_zip_read_info->file, - pfile_in_zip_read_info->offset_local_extrafield + - pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0) - return UNZ_ERRNO; - - if (fread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1) - return UNZ_ERRNO; - - return (int)read_now; -} - -/* - Close the file in zip opened with unzipOpenCurrentFile - Return UNZ_CRCERROR if all the file was read but the CRC is not good -*/ -extern int ZEXPORT unzCloseCurrentFile (unzFile file) -{ - int err=UNZ_OK; - - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - - if (pfile_in_zip_read_info->rest_read_uncompressed == 0) - { - if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) - err=UNZ_CRCERROR; - } - - - TRYFREE(pfile_in_zip_read_info->read_buffer); - pfile_in_zip_read_info->read_buffer = NULL; - if (pfile_in_zip_read_info->stream_initialised) - inflateEnd(&pfile_in_zip_read_info->stream); - - pfile_in_zip_read_info->stream_initialised = 0; - TRYFREE(pfile_in_zip_read_info); - - s->pfile_in_zip_read=NULL; - - return err; -} - - -/* - Get the global comment string of the ZipFile, in the szComment buffer. - uSizeBuf is the size of the szComment buffer. - return the number of byte copied or an error code <0 -*/ -extern int ZEXPORT unzGetGlobalComment - ( unzFile file, - char *szComment, - uLong uSizeBuf - ) -{ - unz_s* s; - uLong uReadThis ; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - - uReadThis = uSizeBuf; - if (uReadThis>s->gi.size_comment) - uReadThis = s->gi.size_comment; - - if (fseek(s->file,s->central_pos+22,SEEK_SET)!=0) - return UNZ_ERRNO; - - if (uReadThis>0) - { - *szComment='\0'; - if (fread(szComment,(uInt)uReadThis,1,s->file)!=1) - return UNZ_ERRNO; - } - - if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) - *(szComment+s->gi.size_comment)='\0'; - return (int)uReadThis; -} diff --git a/atari_py/ale_interface/src/emucore/unzip.h b/atari_py/ale_interface/src/emucore/unzip.h deleted file mode 100644 index 755600b..0000000 --- a/atari_py/ale_interface/src/emucore/unzip.h +++ /dev/null @@ -1,282 +0,0 @@ -/* unzip.h -- IO for uncompress .zip files using zlib - Version 0.15 beta, Mar 19th, 1998, - - Copyright (C) 1998 Gilles Vollant - - This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g - WinZip, InfoZip tools and compatible. - Encryption and multi volume ZipFile (span) are not supported. - Old compressions used by old PKZip 1.x are not supported - - THIS IS AN ALPHA VERSION. AT THIS STAGE OF DEVELOPPEMENT, SOMES API OR STRUCTURE - CAN CHANGE IN FUTURE VERSION !! - I WAIT FEEDBACK at mail info@winimage.com - Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution - - Condition of use and distribution are the same than zlib : - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - -*/ -/* for more info about .ZIP format, see - ftp://ftp.cdrom.com/pub/infozip/doc/appnote-970311-iz.zip - PkWare has also a specification at : - ftp://ftp.pkware.com/probdesc.zip */ - -#ifndef _unz_H -#define _unz_H - -/* Gentoo removed OF from their copy of zconf.h - * (https://bugs.gentoo.org/show_bug.cgi?id=383179) */ -/* but our copy of minizip needs it. */ -#ifndef OF -#define OF(args) args -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef _ZLIB_H -#include -#endif - -#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) -/* like the STRICT of WIN32, we define a pointer that cannot be converted - from (void*) without cast */ -typedef struct TagunzFile__ { int unused; } unzFile__; -typedef unzFile__ *unzFile; -#else -typedef voidp unzFile; -#endif - - -#define UNZ_OK (0) -#define UNZ_END_OF_LIST_OF_FILE (-100) -#define UNZ_ERRNO (Z_ERRNO) -#define UNZ_EOF (0) -#define UNZ_PARAMERROR (-102) -#define UNZ_BADZIPFILE (-103) -#define UNZ_INTERNALERROR (-104) -#define UNZ_CRCERROR (-105) - -/* tm_unz contain date/time info */ -typedef struct tm_unz_s -{ - uInt tm_sec; /* seconds after the minute - [0,59] */ - uInt tm_min; /* minutes after the hour - [0,59] */ - uInt tm_hour; /* hours since midnight - [0,23] */ - uInt tm_mday; /* day of the month - [1,31] */ - uInt tm_mon; /* months since January - [0,11] */ - uInt tm_year; /* years - [1980..2044] */ -} tm_unz; - -/* unz_global_info structure contain global data about the ZIPfile - These data comes from the end of central dir */ -typedef struct unz_global_info_s -{ - uLong number_entry; /* total number of entries in - the central dir on this disk */ - uLong size_comment; /* size of the global comment of the zipfile */ -} unz_global_info; - - -/* unz_file_info contain information about a file in the zipfile */ -typedef struct unz_file_info_s -{ - uLong version; /* version made by 2 bytes */ - uLong version_needed; /* version needed to extract 2 bytes */ - uLong flag; /* general purpose bit flag 2 bytes */ - uLong compression_method; /* compression method 2 bytes */ - uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ - uLong crc; /* crc-32 4 bytes */ - uLong compressed_size; /* compressed size 4 bytes */ - uLong uncompressed_size; /* uncompressed size 4 bytes */ - uLong size_filename; /* filename length 2 bytes */ - uLong size_file_extra; /* extra field length 2 bytes */ - uLong size_file_comment; /* file comment length 2 bytes */ - - uLong disk_num_start; /* disk number start 2 bytes */ - uLong internal_fa; /* internal file attributes 2 bytes */ - uLong external_fa; /* external file attributes 4 bytes */ - - tm_unz tmu_date; -} unz_file_info; - -extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, - const char* fileName2, - int iCaseSensitivity)); -/* - Compare two filename (fileName1,fileName2). - If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) - If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi - or strcasecmp) - If iCaseSenisivity = 0, case sensitivity is defaut of your operating system - (like 1 on Unix, 2 on Windows) -*/ - - -extern unzFile ZEXPORT unzOpen OF((const char *path)); -/* - Open a Zip file. path contain the full pathname (by example, - on a Windows NT computer "c:\\zlib\\zlib111.zip" or on an Unix computer - "zlib/zlib111.zip". - If the zipfile cannot be opened (file don't exist or in not valid), the - return value is NULL. - Else, the return value is a unzFile Handle, usable with other function - of this unzip package. -*/ - -extern int ZEXPORT unzClose OF((unzFile file)); -/* - Close a ZipFile opened with unzipOpen. - If there is files inside the .Zip opened with unzOpenCurrentFile (see later), - these files MUST be closed with unzipCloseCurrentFile before call unzipClose. - return UNZ_OK if there is no problem. */ - -extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, - unz_global_info *pglobal_info)); -/* - Write info about the ZipFile in the *pglobal_info structure. - No preparation of the structure is needed - return UNZ_OK if there is no problem. */ - - -extern int ZEXPORT unzGetGlobalComment OF((unzFile file, - char *szComment, - uLong uSizeBuf)); -/* - Get the global comment string of the ZipFile, in the szComment buffer. - uSizeBuf is the size of the szComment buffer. - return the number of byte copied or an error code <0 -*/ - - -/***************************************************************************/ -/* Unzip package allow you browse the directory of the zipfile */ - -extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); -/* - Set the current file of the zipfile to the first file. - return UNZ_OK if there is no problem -*/ - -extern int ZEXPORT unzGoToNextFile OF((unzFile file)); -/* - Set the current file of the zipfile to the next file. - return UNZ_OK if there is no problem - return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. -*/ - -extern int ZEXPORT unzLocateFile OF((unzFile file, - const char *szFileName, - int iCaseSensitivity)); -/* - Try locate the file szFileName in the zipfile. - For the iCaseSensitivity signification, see unzStringFileNameCompare - - return value : - UNZ_OK if the file is found. It becomes the current file. - UNZ_END_OF_LIST_OF_FILE if the file is not found -*/ - - -extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, - unz_file_info *pfile_info, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize)); -/* - Get Info about the current file - if pfile_info!=NULL, the *pfile_info structure will contain somes info about - the current file - if szFileName!=NULL, the filemane string will be copied in szFileName - (fileNameBufferSize is the size of the buffer) - if extraField!=NULL, the extra field information will be copied in extraField - (extraFieldBufferSize is the size of the buffer). - This is the Central-header version of the extra field - if szComment!=NULL, the comment string of the file will be copied in szComment - (commentBufferSize is the size of the buffer) -*/ - -/***************************************************************************/ -/* for reading the content of the current zipfile, you can open it, read data - from it, and close it (you can close it before reading all the file) - */ - -extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); -/* - Open for reading data the current file in the zipfile. - If there is no error, the return value is UNZ_OK. -*/ - -extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); -/* - Close the file in zip opened with unzOpenCurrentFile - Return UNZ_CRCERROR if all the file was read but the CRC is not good -*/ - - -extern int ZEXPORT unzReadCurrentFile OF((unzFile file, - voidp buf, - unsigned len)); -/* - Read bytes from the current file (opened by unzOpenCurrentFile) - buf contain buffer where data must be copied - len the size of buf. - - return the number of byte copied if somes bytes are copied - return 0 if the end of file was reached - return <0 with error code if there is an error - (UNZ_ERRNO for IO error, or zLib error for uncompress error) -*/ - -extern z_off_t ZEXPORT unztell OF((unzFile file)); -/* - Give the current position in uncompressed data -*/ - -extern int ZEXPORT unzeof OF((unzFile file)); -/* - return 1 if the end of file was reached, 0 elsewhere -*/ - -extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, - voidp buf, - unsigned len)); -/* - Read extra field from the current file (opened by unzOpenCurrentFile) - This is the local-header version of the extra field (sometimes, there is - more info in the local-header version than in the central-header) - - if buf==NULL, it return the size of the local extra field - - if buf!=NULL, len is the size of the buffer, the extra header is copied in - buf. - the return value is the number of bytes copied in buf, or (if <0) - the error code -*/ - -#ifdef __cplusplus -} -#endif - -#endif /* _unz_H */ diff --git a/atari_py/ale_interface/src/environment/ale_screen.hpp b/atari_py/ale_interface/src/environment/ale_screen.hpp index 9fe2c60..ebb9a0d 100644 --- a/atari_py/ale_interface/src/environment/ale_screen.hpp +++ b/atari_py/ale_interface/src/environment/ale_screen.hpp @@ -18,7 +18,8 @@ #ifndef __ALE_SCREEN_HPP__ #define __ALE_SCREEN_HPP__ -#include +#include +#include #include #include diff --git a/atari_py/ale_interface/src/environment/ale_state.cpp b/atari_py/ale_interface/src/environment/ale_state.cpp index b8fbc70..3df56e1 100644 --- a/atari_py/ale_interface/src/environment/ale_state.cpp +++ b/atari_py/ale_interface/src/environment/ale_state.cpp @@ -12,9 +12,12 @@ #include "ale_state.hpp" #include "../emucore/m6502/src/System.hxx" #include "../emucore/Event.hxx" +#include "../emucore/Deserializer.hxx" +#include "../emucore/Serializer.hxx" #include "../common/Constants.h" -using namespace std; +#include "../games/RomSettings.hpp" +#include #include /** Default constructor - loads settings from system */ @@ -22,15 +25,19 @@ ALEState::ALEState(): m_left_paddle(PADDLE_DEFAULT_VALUE), m_right_paddle(PADDLE_DEFAULT_VALUE), m_frame_number(0), - m_episode_frame_number(0) { + m_episode_frame_number(0), + m_mode(0), + m_difficulty(0) { } -ALEState::ALEState(const ALEState &rhs, std::string serialized): +ALEState::ALEState(const ALEState &rhs, const std::string &serialized): m_left_paddle(rhs.m_left_paddle), m_right_paddle(rhs.m_right_paddle), m_frame_number(rhs.m_frame_number), m_episode_frame_number(rhs.m_episode_frame_number), - m_serialized_state(serialized) { + m_serialized_state(serialized), + m_mode(rhs.m_mode), + m_difficulty(rhs.m_difficulty) { } ALEState::ALEState(const std::string &serialized) { @@ -39,6 +46,8 @@ ALEState::ALEState(const std::string &serialized) { this->m_right_paddle = des.getInt(); this->m_frame_number = des.getInt(); this->m_episode_frame_number = des.getInt(); + this->m_mode = des.getInt(); + this->m_difficulty = des.getInt(); this->m_serialized_state = des.getString(); } @@ -65,8 +74,10 @@ void ALEState::load(OSystem* osystem, RomSettings* settings, std::string md5, co // Copy over other member variables m_left_paddle = rhs.m_left_paddle; m_right_paddle = rhs.m_right_paddle; - m_episode_frame_number = rhs.m_episode_frame_number; m_frame_number = rhs.m_frame_number; + m_episode_frame_number = rhs.m_episode_frame_number; + m_mode = rhs.m_mode; + m_difficulty = rhs.m_difficulty; } ALEState ALEState::save(OSystem* osystem, RomSettings* settings, std::string md5, @@ -102,6 +113,8 @@ std::string ALEState::serialize() { ser.putInt(this->m_right_paddle); ser.putInt(this->m_frame_number); ser.putInt(this->m_episode_frame_number); + ser.putInt(this->m_mode); + ser.putInt(this->m_difficulty); ser.putString(this->m_serialized_state); return ser.get_str(); @@ -259,6 +272,20 @@ void ALEState::applyActionPaddles(Event* event, int player_a_action, int player_ } } +void ALEState::pressSelect(Event* event) { + resetKeys(event); + event->set(Event::ConsoleSelect, 1); +} + +void ALEState::setDifficultySwitches(Event* event, unsigned int value) { + // The difficulty switches stay in their position from time step to time step. + // This means we don't call resetKeys() when setting their values. + event->set(Event::ConsoleLeftDifficultyA, value & 1); + event->set(Event::ConsoleLeftDifficultyB, !(value & 1)); + event->set(Event::ConsoleRightDifficultyA, (value & 2) >> 1); + event->set(Event::ConsoleRightDifficultyB, !((value & 2) >> 1)); +} + void ALEState::setActionJoysticks(Event* event, int player_a_action, int player_b_action) { // Reset keys resetKeys(event); @@ -448,20 +475,21 @@ void ALEState::setActionJoysticks(Event* event, int player_a_action, int player_ break; case RESET: event->set(Event::ConsoleReset, 1); - ale::Logger::Info << "Sending Reset..." << endl; + ale::Logger::Info << "Sending Reset..." << std::endl; break; default: - ale::Logger::Error << "Invalid Player B Action: " << player_b_action << endl; + ale::Logger::Error << "Invalid Player B Action: " << player_b_action << std::endl; exit(-1); } } /* *************************************************************************** Function resetKeys - Unpresses all control-relavant keys + Unpresses all control-relevant keys * ***************************************************************************/ void ALEState::resetKeys(Event* event) { event->set(Event::ConsoleReset, 0); + event->set(Event::ConsoleSelect, 0); event->set(Event::JoystickZeroFire, 0); event->set(Event::JoystickZeroUp, 0); event->set(Event::JoystickZeroDown, 0); @@ -476,6 +504,9 @@ void ALEState::resetKeys(Event* event) { // also reset paddle fire event->set(Event::PaddleZeroFire, 0); event->set(Event::PaddleOneFire, 0); + + // Set the difficulty switches accordingly for this time step. + setDifficultySwitches(event, m_difficulty); } bool ALEState::equals(ALEState &rhs) { @@ -483,5 +514,7 @@ bool ALEState::equals(ALEState &rhs) { rhs.m_left_paddle == this->m_left_paddle && rhs.m_right_paddle == this->m_right_paddle && rhs.m_frame_number == this->m_frame_number && - rhs.m_episode_frame_number == this->m_episode_frame_number); + rhs.m_episode_frame_number == this->m_episode_frame_number && + rhs.m_mode == this->m_mode && + rhs.m_difficulty == this->m_difficulty); } diff --git a/atari_py/ale_interface/src/environment/ale_state.hpp b/atari_py/ale_interface/src/environment/ale_state.hpp index 9dee5bc..6dfc7a5 100644 --- a/atari_py/ale_interface/src/environment/ale_state.hpp +++ b/atari_py/ale_interface/src/environment/ale_state.hpp @@ -21,9 +21,10 @@ #include "../emucore/OSystem.hxx" #include "../emucore/Event.hxx" #include -#include "../games/RomSettings.hpp" #include "../common/Log.hpp" +class RomSettings; + #define PADDLE_DELTA 23000 // MGB Values taken from Paddles.cxx (Stella 3.3) - 1400000 * [5,235] / 255 #define PADDLE_MIN 27450 @@ -36,7 +37,7 @@ class ALEState { public: ALEState(); // Makes a copy of this state, also storing emulator information provided as a string - ALEState(const ALEState &rhs, std::string serialized); + ALEState(const ALEState &rhs, const std::string &serialized); // Restores a serialized ALEState ALEState(const std::string &serialized); @@ -50,6 +51,9 @@ class ALEState { void resetPaddles(Event*); + //Apply the special select action + void pressSelect(Event* event_obj); + /** Applies paddle actions. This actually modifies the game state by updating the paddle * resistances. */ void applyActionPaddles(Event* event_obj, int player_a_action, int player_b_action); @@ -57,14 +61,29 @@ class ALEState { void setActionJoysticks(Event* event_obj, int player_a_action, int player_b_action); void incrementFrame(int steps = 1); - + void resetEpisodeFrameNumber(); - + //Get the frames executed so far - const int getFrameNumber() const { return m_frame_number; } + int getFrameNumber() const { return m_frame_number; } //Get the number of frames executed this episode. - const int getEpisodeFrameNumber() const { return m_episode_frame_number; } + int getEpisodeFrameNumber() const { return m_episode_frame_number; } + + /** set the difficulty according to the value. + * If the first bit is 1, then it will put the left difficulty switch to A (otherwise leave it on B) + * If the second bit is 1, then it will put the right difficulty switch to A (otherwise leave it on B) + */ + void setDifficulty(unsigned int value) { m_difficulty = value; } + + // Returns the current difficulty setting. + unsigned int getDifficulty() const { return m_difficulty; } + + //Save the current mode we are supposed to be in. + void setCurrentMode(game_mode_t value) { m_mode = value; } + + //Get the current mode we are in. + game_mode_t getCurrentMode() const { return m_mode; } std::string serialize(); @@ -94,7 +113,10 @@ class ALEState { /** Calculates the Paddle resistance, based on the given x val */ int calcPaddleResistance(int x_val); - + + /** Applies the current difficulty setting, which is effectively part of the action */ + void setDifficultySwitches(Event* event_obj, unsigned int value); + private: int m_left_paddle; // Current value for the left-paddle int m_right_paddle; // Current value for the right-paddle @@ -104,8 +126,10 @@ class ALEState { std::string m_serialized_state; // The stored environment state, if this is a saved state + game_mode_t m_mode; //The current mode we are in + difficulty_t m_difficulty; //The current difficulty we are in + }; #endif // __ALE_STATE_HPP__ - diff --git a/atari_py/ale_interface/src/environment/module.mk b/atari_py/ale_interface/src/environment/module.mk new file mode 100644 index 0000000..c35a5ab --- /dev/null +++ b/atari_py/ale_interface/src/environment/module.mk @@ -0,0 +1,12 @@ +MODULE := src/environment + +MODULE_OBJS := \ + src/environment/ale_state.o \ + src/environment/stella_environment.o \ + src/environment/phosphor_blend.o \ + +MODULE_DIRS += \ + src/environment + +# Include common rules +include $(srcdir)/common.rules diff --git a/atari_py/ale_interface/src/environment/stella_environment.cpp b/atari_py/ale_interface/src/environment/stella_environment.cpp index 83a065a..656da96 100644 --- a/atari_py/ale_interface/src/environment/stella_environment.cpp +++ b/atari_py/ale_interface/src/environment/stella_environment.cpp @@ -74,12 +74,16 @@ void StellaEnvironment::reset() { noopSteps = 60; emulate(PLAYER_A_NOOP, PLAYER_B_NOOP, noopSteps); - // reset for n steps - emulate(RESET, PLAYER_B_NOOP, m_num_reset_steps); + // Reset the emulator + softReset(); // reset the rom (after emulating, in case the NOOPs led to reward) m_settings->reset(); + // Apply mode that was previously defined, then soft reset with this mode + m_settings->setMode(m_state.getCurrentMode(), m_osystem->console().system(), getWrapper()); + softReset(); + // Apply necessary actions specified by the rom itself ActionVect startingActions = m_settings->getStartingActions(); for (size_t i = 0; i < startingActions.size(); i++){ @@ -169,6 +173,15 @@ reward_t StellaEnvironment::act(Action player_a_action, Action player_b_action) return sum_rewards; } +/** This functions emulates a push on the reset button of the console */ +void StellaEnvironment::softReset() { + emulate(RESET, PLAYER_B_NOOP, m_num_reset_steps); + + // Reset previous actions to NOOP for correct action repeating + m_player_a_action = PLAYER_A_NOOP; + m_player_b_action = PLAYER_B_NOOP; +} + /** Applies the given actions (e.g. updating paddle positions when the paddle is used) * and performs one simulation step in Stella. */ reward_t StellaEnvironment::oneStepAct(Action player_a_action, Action player_b_action) { @@ -195,6 +208,25 @@ bool StellaEnvironment::isTerminal() const { m_state.getEpisodeFrameNumber() >= m_max_num_frames_per_episode)); } +void StellaEnvironment::pressSelect(size_t num_steps) { + m_state.pressSelect(m_osystem->event()); + for (size_t t = 0; t < num_steps; t++) { + m_osystem->console().mediaSource().update(); + } + processScreen(); + processRAM(); + emulate(PLAYER_A_NOOP, PLAYER_B_NOOP); + m_state.incrementFrame(); +} + +void StellaEnvironment::setDifficulty(difficulty_t value) { + m_state.setDifficulty(value); +} + +void StellaEnvironment::setMode(game_mode_t value) { + m_state.setCurrentMode(value); +} + void StellaEnvironment::emulate(Action player_a_action, Action player_b_action, size_t num_steps) { Event* event = m_osystem->event(); @@ -233,6 +265,10 @@ const ALEState& StellaEnvironment::getState() const { return m_state; } +std::unique_ptr StellaEnvironment::getWrapper() { + return std::unique_ptr(new StellaEnvironmentWrapper(*this)); +} + void StellaEnvironment::processScreen() { if (m_colour_averaging) { // Perform phosphor averaging; the blender stores its result in the given screen diff --git a/atari_py/ale_interface/src/environment/stella_environment.hpp b/atari_py/ale_interface/src/environment/stella_environment.hpp index 9125d80..398ec3b 100644 --- a/atari_py/ale_interface/src/environment/stella_environment.hpp +++ b/atari_py/ale_interface/src/environment/stella_environment.hpp @@ -18,20 +18,20 @@ #ifndef __STELLA_ENVIRONMENT_HPP__ #define __STELLA_ENVIRONMENT_HPP__ -#include "ale_state.hpp" -#include "ale_screen.hpp" #include "ale_ram.hpp" +#include "ale_screen.hpp" +#include "ale_state.hpp" #include "phosphor_blend.hpp" -#include "../emucore/OSystem.hxx" +#include "stella_environment_wrapper.hpp" #include "../emucore/Event.hxx" +#include "../emucore/OSystem.hxx" #include "../games/RomSettings.hpp" -#include "../common/ScreenExporter.hpp" +#include "../common/Constants.h" #include "../common/Log.hpp" +#include "../common/ScreenExporter.hpp" #include - -// This defines the number of "random" environments -#define NUM_RANDOM_ENVIRONMENTS (500) +#include class StellaEnvironment { public: @@ -64,6 +64,24 @@ class StellaEnvironment { */ reward_t act(Action player_a_action, Action player_b_action); + /** This functions emulates a push on the reset button of the console */ + void softReset(); + + /** Keep pressing the console select button for a given amount of time*/ + void pressSelect(size_t num_steps = 1); + + /** Set the difficulty according to the value. + * If the first bit is 1, then it will put the left difficulty switch to A (otherwise leave it on B) + * If the second bit is 1, then it will put the right difficulty switch to A (otherwise leave it on B) + * + * This change takes effect at the immediate next time step. + */ + void setDifficulty(difficulty_t value); + + /** Set the game mode according to the value. The new mode will not take effect until reset() is + * called */ + void setMode(game_mode_t value); + /** Returns true once we reach a terminal state */ bool isTerminal() const; @@ -78,6 +96,9 @@ class StellaEnvironment { int getFrameNumber() const { return m_state.getFrameNumber(); } int getEpisodeFrameNumber() const { return m_state.getEpisodeFrameNumber(); } + /** Returns a wrapper providing #include-free access to our methods. */ + std::unique_ptr getWrapper(); + private: /** This applies an action exactly one time step. Helper function to act(). */ reward_t oneStepAct(Action player_a_action, Action player_b_action); @@ -114,7 +135,7 @@ class StellaEnvironment { int m_max_num_frames_per_episode; // Maxmimum number of frames per episode size_t m_frame_skip; // How many frames to emulate per act() float m_repeat_action_probability; // Stochasticity of the environment - std::auto_ptr m_screen_exporter; // Automatic screen recorder + std::unique_ptr m_screen_exporter; // Automatic screen recorder // The last actions taken by our players Action m_player_a_action, m_player_b_action; diff --git a/atari_py/ale_interface/src/environment/stella_environment_wrapper.cpp b/atari_py/ale_interface/src/environment/stella_environment_wrapper.cpp new file mode 100644 index 0000000..0509e02 --- /dev/null +++ b/atari_py/ale_interface/src/environment/stella_environment_wrapper.cpp @@ -0,0 +1,18 @@ +#include "stella_environment.hpp" +#include "stella_environment_wrapper.hpp" + +StellaEnvironmentWrapper::StellaEnvironmentWrapper(StellaEnvironment &environment) : + m_environment(environment) { +} + +reward_t StellaEnvironmentWrapper::act(Action player_a_action, Action player_b_action) { + return m_environment.act(player_a_action, player_b_action); +} + +void StellaEnvironmentWrapper::softReset() { + m_environment.softReset(); +} + +void StellaEnvironmentWrapper::pressSelect(size_t num_steps) { + m_environment.pressSelect(num_steps); +} diff --git a/atari_py/ale_interface/src/environment/stella_environment_wrapper.hpp b/atari_py/ale_interface/src/environment/stella_environment_wrapper.hpp new file mode 100644 index 0000000..f21ae9c --- /dev/null +++ b/atari_py/ale_interface/src/environment/stella_environment_wrapper.hpp @@ -0,0 +1,38 @@ +/* ***************************************************************************** + * A.L.E (Arcade Learning Environment) + * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and + * the Reinforcement Learning and Artificial Intelligence Laboratory + * Released under the GNU General Public License; see License.txt for details. + * + * Based on: Stella -- "An Atari 2600 VCS Emulator" + * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team + * + * ***************************************************************************** + * stella_environment_wrapper.hpp + * + * Method wrapper for StellaEnvironment. + * + **************************************************************************** */ + +#ifndef __STELLA_ENVIRONMENT_WRAPPER_HPP__ +#define __STELLA_ENVIRONMENT_WRAPPER_HPP__ + +#include "../common/Constants.h" + +class StellaEnvironment; + +class StellaEnvironmentWrapper { + // A wrapper for actions within the StellaEnvironment. + // Allows us to call environment methods without requiring to #include + // stella_environment.hpp. + public: + StellaEnvironmentWrapper(StellaEnvironment &environment); + reward_t act(Action player_a_action, Action player_b_action); + void softReset(); + void pressSelect(size_t num_steps = 1); + + StellaEnvironment &m_environment; +}; + +#endif // __STELLA_ENVIRONMENT_WRAPPER_HPP__ + diff --git a/atari_py/ale_interface/src/external/module.mk b/atari_py/ale_interface/src/external/module.mk new file mode 100644 index 0000000..9e25b44 --- /dev/null +++ b/atari_py/ale_interface/src/external/module.mk @@ -0,0 +1,10 @@ +MODULE := src/external + +MODULE_OBJS := \ + src/external/TinyMT/tinymt32.o \ + +MODULE_DIRS += \ + src/external/TinyMT + +# Include common rules +include $(srcdir)/common.rules diff --git a/atari_py/ale_interface/src/games/RomSettings.cpp b/atari_py/ale_interface/src/games/RomSettings.cpp index a4d91e3..b8cd949 100644 --- a/atari_py/ale_interface/src/games/RomSettings.cpp +++ b/atari_py/ale_interface/src/games/RomSettings.cpp @@ -17,6 +17,9 @@ */ #include "RomSettings.hpp" +RomSettings::RomSettings() {} + + bool RomSettings::isLegal(const Action& a) const { return true; } @@ -42,5 +45,20 @@ ActionVect RomSettings::getAllActions() { } ActionVect RomSettings::getStartingActions() { - return ActionVect(); + return ActionVect(); } + +ModeVect RomSettings::getAvailableModes() { + return ModeVect(1, 0); +}; + +void RomSettings::setMode(game_mode_t m, System&, std::unique_ptr) { + //By default, 0 is the only available mode + if(m != 0) { + throw std::runtime_error("This mode is not currently available for this game"); + } +} + +DifficultyVect RomSettings::getAvailableDifficulties() { + return DifficultyVect(1, 0); +}; diff --git a/atari_py/ale_interface/src/games/RomSettings.hpp b/atari_py/ale_interface/src/games/RomSettings.hpp index a7b096c..479801c 100644 --- a/atari_py/ale_interface/src/games/RomSettings.hpp +++ b/atari_py/ale_interface/src/games/RomSettings.hpp @@ -34,19 +34,26 @@ #define __ROMSETTINGS_HPP__ #include +#include +#include + #include "../common/Constants.h" #include "../emucore/Serializer.hxx" #include "../emucore/Deserializer.hxx" +#include "../environment/stella_environment_wrapper.hpp" class System; - // rom support interface -struct RomSettings { +class RomSettings { + +public: + RomSettings(); + virtual ~RomSettings() {} // reset - virtual void reset() = 0; + virtual void reset(){}; // is end of game virtual bool isTerminal() const = 0; @@ -76,7 +83,7 @@ struct RomSettings { virtual bool isLegal(const Action &a) const; // Remaining lives. - virtual const int lives() { return isTerminal() ? 0 : 1; } + virtual int lives() { return isTerminal() ? 0 : 1; } // Returns a restricted (minimal) set of actions. If not overriden, this is all actions. virtual ActionVect getMinimalActionSet(); @@ -87,6 +94,19 @@ struct RomSettings { // Returns a list of actions that are required to start the game. // By default this is an empty list. virtual ActionVect getStartingActions(); + + // Returns a list of mode that the game can be played in. + // By default, there is only one available mode. + virtual ModeVect getAvailableModes(); + + // Set the mode of the game. The given mode must be + // one returned by the previous function. + virtual void setMode(game_mode_t, System &system, + std::unique_ptr environment); + + // Returns a list of difficulties that the game can be played in. + // By default, there is only one available difficulty. + virtual DifficultyVect getAvailableDifficulties(); }; diff --git a/atari_py/ale_interface/src/games/RomUtils.cpp b/atari_py/ale_interface/src/games/RomUtils.cpp index ad629f0..1c70184 100644 --- a/atari_py/ale_interface/src/games/RomUtils.cpp +++ b/atari_py/ale_interface/src/games/RomUtils.cpp @@ -29,7 +29,6 @@ int readRam(const System* system, int offset) { return sys->peek((offset & 0x7F) + 0x80); } - /* extracts a decimal value from a byte */ int getDecimalScore(int index, const System* system) { diff --git a/atari_py/ale_interface/src/games/Roms.cpp b/atari_py/ale_interface/src/games/Roms.cpp index ad49e44..42aa32a 100644 --- a/atari_py/ale_interface/src/games/Roms.cpp +++ b/atari_py/ale_interface/src/games/Roms.cpp @@ -10,7 +10,6 @@ * ***************************************************************************** */ #include "Roms.hpp" -#include "RomSettings.hpp" #include "RomUtils.hpp" // include the game implementations @@ -35,12 +34,15 @@ #include "supported/CrazyClimber.hpp" #include "supported/Defender.hpp" #include "supported/DemonAttack.hpp" +#include "supported/DonkeyKong.hpp" #include "supported/DoubleDunk.hpp" #include "supported/ElevatorAction.hpp" #include "supported/Enduro.hpp" #include "supported/FishingDerby.hpp" #include "supported/Freeway.hpp" +#include "supported/Frogger.hpp" #include "supported/Frostbite.hpp" +#include "supported/Galaxian.hpp" #include "supported/Gopher.hpp" #include "supported/Gravitar.hpp" #include "supported/Hero.hpp" @@ -49,9 +51,15 @@ #include "supported/JourneyEscape.hpp" #include "supported/Kaboom.hpp" #include "supported/Kangaroo.hpp" +#include "supported/Koolaid.hpp" +#include "supported/KeystoneKapers.hpp" +#include "supported/Kingkong.hpp" #include "supported/Krull.hpp" #include "supported/KungFuMaster.hpp" +#include "supported/LaserGates.hpp" +#include "supported/LostLuggage.hpp" #include "supported/MontezumaRevenge.hpp" +#include "supported/MrDo.hpp" #include "supported/MsPacman.hpp" #include "supported/NameThisGame.hpp" #include "supported/Phoenix.hpp" @@ -64,12 +72,16 @@ #include "supported/RoadRunner.hpp" #include "supported/RoboTank.hpp" #include "supported/Seaquest.hpp" +#include "supported/SirLancelot.hpp" #include "supported/Skiing.hpp" #include "supported/Solaris.hpp" #include "supported/SpaceInvaders.hpp" #include "supported/StarGunner.hpp" #include "supported/Tennis.hpp" +#include "supported/Tetris.hpp" #include "supported/TimePilot.hpp" +#include "supported/Turmoil.hpp" +#include "supported/Trondead.hpp" #include "supported/Tutankham.hpp" #include "supported/UpNDown.hpp" #include "supported/Venture.hpp" @@ -102,12 +114,15 @@ static const RomSettings *roms[] = { new CrazyClimberSettings(), new DefenderSettings(), new DemonAttackSettings(), + new DonkeyKongSettings(), new DoubleDunkSettings(), new ElevatorActionSettings(), new EnduroSettings(), new FishingDerbySettings(), new FreewaySettings(), + new FroggerSettings(), new FrostbiteSettings(), + new GalaxianSettings(), new GopherSettings(), new GravitarSettings(), new HeroSettings(), @@ -116,9 +131,15 @@ static const RomSettings *roms[] = { new JourneyEscapeSettings(), new KaboomSettings(), new KangarooSettings(), + new KoolaidSettings(), + new KeystoneKapersSettings(), + new KingkongSettings(), new KrullSettings(), new KungFuMasterSettings(), + new LaserGatesSettings(), + new LostLuggageSettings(), new MontezumaRevengeSettings(), + new MrDoSettings(), new MsPacmanSettings(), new NameThisGameSettings(), new PhoenixSettings(), @@ -131,12 +152,16 @@ static const RomSettings *roms[] = { new RoadRunnerSettings(), new RoboTankSettings(), new SeaquestSettings(), + new SirLancelotSettings(), new SkiingSettings(), new SolarisSettings(), new SpaceInvadersSettings(), new StarGunnerSettings(), new TennisSettings(), + new TetrisSettings(), new TimePilotSettings(), + new TurmoilSettings(), + new TrondeadSettings(), new TutankhamSettings(), new UpNDownSettings(), new VentureSettings(), diff --git a/atari_py/ale_interface/src/games/Roms.hpp b/atari_py/ale_interface/src/games/Roms.hpp index 9b47b37..291fa58 100644 --- a/atari_py/ale_interface/src/games/Roms.hpp +++ b/atari_py/ale_interface/src/games/Roms.hpp @@ -12,12 +12,11 @@ #ifndef __ROMS_HPP__ #define __ROMS_HPP__ +#include "RomSettings.hpp" + #include #include -struct RomSettings; - - // looks for the RL wrapper corresponding to a particular rom title extern RomSettings *buildRomRLWrapper(const std::string &rom); diff --git a/atari_py/ale_interface/src/games/module.mk b/atari_py/ale_interface/src/games/module.mk new file mode 100644 index 0000000..1e2edd0 --- /dev/null +++ b/atari_py/ale_interface/src/games/module.mk @@ -0,0 +1,88 @@ +MODULE := src/games + +MODULE_OBJS := \ + src/games/Roms.o \ + src/games/RomSettings.o \ + src/games/RomUtils.o \ + src/games/supported/Adventure.o \ + src/games/supported/AirRaid.o \ + src/games/supported/Alien.o \ + src/games/supported/Amidar.o \ + src/games/supported/Assault.o \ + src/games/supported/Asterix.o \ + src/games/supported/Asteroids.o \ + src/games/supported/Atlantis.o \ + src/games/supported/BankHeist.o \ + src/games/supported/BattleZone.o \ + src/games/supported/BeamRider.o \ + src/games/supported/Berzerk.o \ + src/games/supported/Bowling.o \ + src/games/supported/Boxing.o \ + src/games/supported/Breakout.o \ + src/games/supported/Carnival.o \ + src/games/supported/Centipede.o \ + src/games/supported/ChopperCommand.o \ + src/games/supported/CrazyClimber.o \ + src/games/supported/Defender.o \ + src/games/supported/DemonAttack.o \ + src/games/supported/DonkeyKong.o \ + src/games/supported/DoubleDunk.o \ + src/games/supported/ElevatorAction.o \ + src/games/supported/Enduro.o \ + src/games/supported/FishingDerby.o \ + src/games/supported/Freeway.o \ + src/games/supported/Frogger.o \ + src/games/supported/Frostbite.o \ + src/games/supported/Galaxian.o \ + src/games/supported/Gopher.o \ + src/games/supported/Gravitar.o \ + src/games/supported/Hero.o \ + src/games/supported/IceHockey.o \ + src/games/supported/JamesBond.o \ + src/games/supported/JourneyEscape.o \ + src/games/supported/Kaboom.o \ + src/games/supported/Kangaroo.o \ + src/games/supported/Koolaid.o \ + src/games/supported/KeystoneKapers.o \ + src/games/supported/Kingkong.o \ + src/games/supported/Krull.o \ + src/games/supported/KungFuMaster.o \ + src/games/supported/LaserGates.o \ + src/games/supported/LostLuggage.o \ + src/games/supported/MontezumaRevenge.o \ + src/games/supported/MrDo.o \ + src/games/supported/MsPacman.o \ + src/games/supported/NameThisGame.o \ + src/games/supported/Phoenix.o \ + src/games/supported/Pitfall.o \ + src/games/supported/Pong.o \ + src/games/supported/Pooyan.o \ + src/games/supported/PrivateEye.o \ + src/games/supported/QBert.o \ + src/games/supported/RiverRaid.o \ + src/games/supported/RoadRunner.o \ + src/games/supported/RoboTank.o \ + src/games/supported/Seaquest.o \ + src/games/supported/SirLancelot.o \ + src/games/supported/Skiing.o \ + src/games/supported/Solaris.o \ + src/games/supported/SpaceInvaders.o \ + src/games/supported/StarGunner.o \ + src/games/supported/Tennis.o \ + src/games/supported/Tetris.o \ + src/games/supported/TimePilot.o \ + src/games/supported/Turmoil.o \ + src/games/supported/Tutankham.o \ + src/games/supported/Trondead.o \ + src/games/supported/UpNDown.o \ + src/games/supported/Venture.o \ + src/games/supported/VideoPinball.o \ + src/games/supported/WizardOfWor.o \ + src/games/supported/YarsRevenge.o \ + src/games/supported/Zaxxon.o \ + +MODULE_DIRS += \ + src/games + +# Include common rules +include $(srcdir)/common.rules diff --git a/atari_py/ale_interface/src/games/supported/Adventure.cpp b/atari_py/ale_interface/src/games/supported/Adventure.cpp index 5887f43..58b124d 100644 --- a/atari_py/ale_interface/src/games/supported/Adventure.cpp +++ b/atari_py/ale_interface/src/games/supported/Adventure.cpp @@ -53,10 +53,6 @@ void AdventureSettings::step(const System& system) { int player_status = readRam(&system, 0xE0); bool player_eaten = player_status == 2; - if (player_eaten) { - m_reward = -1; - } - m_terminal = player_eaten || chalice_in_yellow_castle; } @@ -65,7 +61,6 @@ bool AdventureSettings::isTerminal() const { return m_terminal; } -; /* get the most recently observed reward */ reward_t AdventureSettings::getReward() const { diff --git a/atari_py/ale_interface/src/games/supported/Adventure.hpp b/atari_py/ale_interface/src/games/supported/Adventure.hpp index ccfee50..faf4f65 100644 --- a/atari_py/ale_interface/src/games/supported/Adventure.hpp +++ b/atari_py/ale_interface/src/games/supported/Adventure.hpp @@ -24,7 +24,7 @@ * ***************************************************************************** */ #ifndef __ADVENTURE_HPP__ -#define ____ADVENTURE_HPP___HPP__ +#define __ADVENTURE_HPP__ #include "../RomSettings.hpp" @@ -63,7 +63,7 @@ class AdventureSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return 1; } + virtual int lives() { return 1; } private: diff --git a/atari_py/ale_interface/src/games/supported/AirRaid.cpp b/atari_py/ale_interface/src/games/supported/AirRaid.cpp index 3e7b251..5f88f61 100644 --- a/atari_py/ale_interface/src/games/supported/AirRaid.cpp +++ b/atari_py/ale_interface/src/games/supported/AirRaid.cpp @@ -101,3 +101,40 @@ ActionVect AirRaidSettings::getStartingActions() { startingActions.push_back(PLAYER_A_FIRE); return startingActions; } + + +// returns a list of mode that the game can be played in +ModeVect AirRaidSettings::getAvailableModes() { + ModeVect modes(getNumModes()); + for (unsigned int i = 0; i < modes.size(); i++) { + modes[i] = i + 1; + } + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void AirRaidSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + if(m == 0) { + m = 1; // the default mode is not valid in this game + } + if(m >= 1 && m <= getNumModes()) { + //open the mode selection panel + environment->pressSelect(20); + // read the mode we are currently in + unsigned char mode = readRam(&system, 0xAA); + // press select until the correct mode is reached + while (mode != m) { + // hold select button for 10 frames + environment->pressSelect(10); + mode = readRam(&system, 0xAA); + } + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } \ No newline at end of file diff --git a/atari_py/ale_interface/src/games/supported/AirRaid.hpp b/atari_py/ale_interface/src/games/supported/AirRaid.hpp index 4bd088f..042bd6a 100644 --- a/atari_py/ale_interface/src/games/supported/AirRaid.hpp +++ b/atari_py/ale_interface/src/games/supported/AirRaid.hpp @@ -34,6 +34,9 @@ class AirRaidSettings : public RomSettings { // the rom-name const char* rom() const { return "air_raid"; } + // get the available number of modes + unsigned int getNumModes() const { return 8; } + // create a new instance of the rom RomSettings* clone() const; @@ -49,7 +52,17 @@ class AirRaidSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - ActionVect getStartingActions(); + ActionVect getStartingActions(); + + + // returns a list of mode that the game can be played in + // in this game, there are 8 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); private: diff --git a/atari_py/ale_interface/src/games/supported/Alien.cpp b/atari_py/ale_interface/src/games/supported/Alien.cpp index 239bb03..63cdb36 100644 --- a/atari_py/ale_interface/src/games/supported/Alien.cpp +++ b/atari_py/ale_interface/src/games/supported/Alien.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 65, 118, 134 and 142 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -142,3 +142,41 @@ void AlienSettings::loadState(Deserializer & ser) { m_lives = ser.getInt(); } +// returns a list of mode that the game can be played in +ModeVect AlienSettings::getAvailableModes() { + ModeVect modes(getNumModes()); + for (unsigned int i = 0; i < modes.size(); i++) { + modes[i] = i; + } + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void AlienSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + if(m < getNumModes()) { + // read the mode we are currently in + unsigned char mode = readRam(&system, 0x81); + // press select until the correct mode is reached + while (mode != m) { + environment->pressSelect(); + mode = readRam(&system, 0x81); + } + //update the number of lives + int byte = readRam(&system, 0xC0); + byte = byte & 15; + m_lives = byte; + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } + +DifficultyVect AlienSettings::getAvailableDifficulties() { + DifficultyVect diff = {0, 1, 2, 3}; + return diff; +} diff --git a/atari_py/ale_interface/src/games/supported/Alien.hpp b/atari_py/ale_interface/src/games/supported/Alien.hpp index 5075fe0..300b3a0 100644 --- a/atari_py/ale_interface/src/games/supported/Alien.hpp +++ b/atari_py/ale_interface/src/games/supported/Alien.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 67 and 77 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class AlienSettings : public RomSettings { // the rom-name const char* rom() const { return "alien"; } + // get the available number of modes + unsigned int getNumModes() const { return 4; } + // create a new instance of the rom RomSettings* clone() const; @@ -64,7 +67,20 @@ class AlienSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return m_lives; } + virtual int lives() { return m_lives; } + + // list of modes that the game can be played in + // in this game, there are 4 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); + + // returns a list of difficulties that the game can be played in + // in this game, there are 4 available difficulties + DifficultyVect getAvailableDifficulties(); private: diff --git a/atari_py/ale_interface/src/games/supported/Amidar.cpp b/atari_py/ale_interface/src/games/supported/Amidar.cpp index 101e5ef..ada8182 100644 --- a/atari_py/ale_interface/src/games/supported/Amidar.cpp +++ b/atari_py/ale_interface/src/games/supported/Amidar.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 46, 91, 100 and 108 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -123,3 +123,8 @@ void AmidarSettings::loadState(Deserializer & ser) { m_lives = ser.getInt(); } +DifficultyVect AmidarSettings::getAvailableDifficulties() { + DifficultyVect diff = {0, 3}; + return diff; +} + diff --git a/atari_py/ale_interface/src/games/supported/Amidar.hpp b/atari_py/ale_interface/src/games/supported/Amidar.hpp index 7c3fa7a..03298a5 100644 --- a/atari_py/ale_interface/src/games/supported/Amidar.hpp +++ b/atari_py/ale_interface/src/games/supported/Amidar.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 67 and 74 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -64,7 +64,11 @@ class AmidarSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + // returns a list of difficulties that the game can be played in + // in this game, there are 2 available difficulties + DifficultyVect getAvailableDifficulties(); private: diff --git a/atari_py/ale_interface/src/games/supported/Assault.hpp b/atari_py/ale_interface/src/games/supported/Assault.hpp index 7c8bc9f..31033a6 100644 --- a/atari_py/ale_interface/src/games/supported/Assault.hpp +++ b/atari_py/ale_interface/src/games/supported/Assault.hpp @@ -64,7 +64,7 @@ class AssaultSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } private: diff --git a/atari_py/ale_interface/src/games/supported/Asterix.hpp b/atari_py/ale_interface/src/games/supported/Asterix.hpp index 7756d03..10d1f0e 100644 --- a/atari_py/ale_interface/src/games/supported/Asterix.hpp +++ b/atari_py/ale_interface/src/games/supported/Asterix.hpp @@ -60,14 +60,14 @@ class AsterixSettings : public RomSettings { // saves the state of the rom settings void saveState(Serializer & ser); - + // loads the state of the rom settings void loadState(Deserializer & ser); // Asterix requires the fire action to start the game ActionVect getStartingActions(); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } private: diff --git a/atari_py/ale_interface/src/games/supported/Asteroids.cpp b/atari_py/ale_interface/src/games/supported/Asteroids.cpp index b91cb9f..55fbaf2 100644 --- a/atari_py/ale_interface/src/games/supported/Asteroids.cpp +++ b/atari_py/ale_interface/src/games/supported/Asteroids.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 42 - 44, 92, 102 and 110 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -131,3 +131,39 @@ void AsteroidsSettings::loadState(Deserializer & ser) { m_lives = ser.getInt(); } +// returns a list of mode that the game can be played in +ModeVect AsteroidsSettings::getAvailableModes() { + ModeVect modes(getNumModes() - 1); + for (unsigned int i = 0; i < modes.size(); i++) { + modes[i] = i; + } + modes.push_back(0x80); //this is the "kids" mode + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void AsteroidsSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + if(m < 32 || m == 0x80) { + // read the mode we are currently in + unsigned char mode = readRam(&system, 0x80); + // press select until the correct mode is reached + while (mode != m) { + environment->pressSelect(2); + mode = readRam(&system, 0x80); + } + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } + +DifficultyVect AsteroidsSettings::getAvailableDifficulties() { + DifficultyVect diff = {0, 3}; + return diff; +} + diff --git a/atari_py/ale_interface/src/games/supported/Asteroids.hpp b/atari_py/ale_interface/src/games/supported/Asteroids.hpp index 5834e24..2707b60 100644 --- a/atari_py/ale_interface/src/games/supported/Asteroids.hpp +++ b/atari_py/ale_interface/src/games/supported/Asteroids.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 67 and 74 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class AsteroidsSettings : public RomSettings { // the rom-name const char* rom() const { return "asteroids"; } + // get the available number of modes + unsigned int getNumModes() const { return 33; } + // create a new instance of the rom RomSettings* clone() const; @@ -64,7 +67,20 @@ class AsteroidsSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + // returns a list of mode that the game can be played in + // in this game, there are 33 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); + + // returns a list of difficulties that the game can be played in + // in this game, there are 2 available difficulties + DifficultyVect getAvailableDifficulties(); private: diff --git a/atari_py/ale_interface/src/games/supported/Atlantis.cpp b/atari_py/ale_interface/src/games/supported/Atlantis.cpp index 080be66..ebd689a 100644 --- a/atari_py/ale_interface/src/games/supported/Atlantis.cpp +++ b/atari_py/ale_interface/src/games/supported/Atlantis.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 100, 110 and 118 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -128,3 +128,33 @@ void AtlantisSettings::loadState(Deserializer & ser) { m_lives = ser.getInt(); } +// returns a list of mode that the game can be played in +ModeVect AtlantisSettings::getAvailableModes() { + ModeVect modes(getNumModes()); + for (unsigned int i = 0; i < modes.size(); i++) { + modes[i] = i; + } + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void AtlantisSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + if(m < getNumModes()) { + // read the mode we are currently in + unsigned char mode = readRam(&system, 0x8D); + // press select until the correct mode is reached + while (mode != m) { + environment->pressSelect(2); + mode = readRam(&system, 0x8D); + } + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } + diff --git a/atari_py/ale_interface/src/games/supported/Atlantis.hpp b/atari_py/ale_interface/src/games/supported/Atlantis.hpp index 74ea60f..4f88521 100644 --- a/atari_py/ale_interface/src/games/supported/Atlantis.hpp +++ b/atari_py/ale_interface/src/games/supported/Atlantis.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 67 and 74 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class AtlantisSettings : public RomSettings { // the rom-name const char* rom() const { return "atlantis"; } + // get the available number of modes + unsigned int getNumModes() const { return 4; } + // create a new instance of the rom RomSettings* clone() const; @@ -64,7 +67,16 @@ class AtlantisSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + // returns a list of mode that the game can be played in + // in this game, there are 8 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); private: diff --git a/atari_py/ale_interface/src/games/supported/BankHeist.cpp b/atari_py/ale_interface/src/games/supported/BankHeist.cpp index 9960733..e76a678 100644 --- a/atari_py/ale_interface/src/games/supported/BankHeist.cpp +++ b/atari_py/ale_interface/src/games/supported/BankHeist.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 97, 107 and 115 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -130,3 +130,38 @@ void BankHeistSettings::loadState(Deserializer & ser) { m_lives = ser.getInt(); } +// returns a list of mode that the game can be played in +ModeVect BankHeistSettings::getAvailableModes() { + ModeVect modes(getNumModes()); + for (unsigned int i = 0; i < modes.size(); i++) { + modes[i] = i * 4; + } + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void BankHeistSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + if(m <= 28 && m % 4 == 0) { + // read the mode we are currently in + unsigned char mode = readRam(&system, 0x80); + // press select until the correct mode is reached + while (mode != m) { + // hold select button for 10 frames + environment->pressSelect(); + mode = readRam(&system, 0x80); + } + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } + +DifficultyVect BankHeistSettings::getAvailableDifficulties() { + DifficultyVect diff = {0, 1, 2, 3}; + return diff; +} diff --git a/atari_py/ale_interface/src/games/supported/BankHeist.hpp b/atari_py/ale_interface/src/games/supported/BankHeist.hpp index a9a6732..45da1a8 100644 --- a/atari_py/ale_interface/src/games/supported/BankHeist.hpp +++ b/atari_py/ale_interface/src/games/supported/BankHeist.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 67 and 74 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class BankHeistSettings : public RomSettings { // the rom-name const char* rom() const { return "bank_heist"; } + // get the available number of modes + unsigned int getNumModes() const { return 8; } + // create a new instance of the rom RomSettings* clone() const; @@ -64,7 +67,20 @@ class BankHeistSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + // returns a list of mode that the game can be played in + // in this game, there are 8 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); + + // returns a list of difficulties that the game can be played in + // in this game, there are 2 available difficulties + DifficultyVect getAvailableDifficulties(); private: diff --git a/atari_py/ale_interface/src/games/supported/BattleZone.cpp b/atari_py/ale_interface/src/games/supported/BattleZone.cpp index 9295bef..d1f9d70 100644 --- a/atari_py/ale_interface/src/games/supported/BattleZone.cpp +++ b/atari_py/ale_interface/src/games/supported/BattleZone.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 125, 135 and 143 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -143,3 +143,36 @@ void BattleZoneSettings::loadState(Deserializer & ser) { m_lives = ser.getInt(); } +// returns a list of mode that the game can be played in +ModeVect BattleZoneSettings::getAvailableModes() { + ModeVect modes(getNumModes()); + for (unsigned int i = 0; i < modes.size(); i++) { + modes[i] = i + 1; + } + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void BattleZoneSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + if(m == 0) { + m = 1; // the default mode is not valid here + } + if(m >= 1 && m <= 3) { + // read the mode we are currently in + unsigned char mode = readRam(&system, 0xA1); + // press select until the correct mode is reached + while (mode != m) { + environment->pressSelect(2); + mode = readRam(&system, 0xA1); + } + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } + diff --git a/atari_py/ale_interface/src/games/supported/BattleZone.hpp b/atari_py/ale_interface/src/games/supported/BattleZone.hpp index ce69431..ec2137e 100644 --- a/atari_py/ale_interface/src/games/supported/BattleZone.hpp +++ b/atari_py/ale_interface/src/games/supported/BattleZone.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 67 and 74 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class BattleZoneSettings : public RomSettings { // the rom-name const char* rom() const { return "battle_zone"; } + // get the available number of modes + unsigned int getNumModes() const { return 3; } + // create a new instance of the rom RomSettings* clone() const; @@ -64,7 +67,16 @@ class BattleZoneSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + // returns a list of mode that the game can be played in + // in this game, there are 3 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); private: diff --git a/atari_py/ale_interface/src/games/supported/BeamRider.cpp b/atari_py/ale_interface/src/games/supported/BeamRider.cpp index 5845d37..5c4deec 100644 --- a/atari_py/ale_interface/src/games/supported/BeamRider.cpp +++ b/atari_py/ale_interface/src/games/supported/BeamRider.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 54 - 63, 113, 122 and 130 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -136,3 +136,8 @@ ActionVect BeamRiderSettings::getStartingActions() { return startingActions; } +DifficultyVect BeamRiderSettings::getAvailableDifficulties() { + DifficultyVect diff = {0, 1}; + return diff; +} + diff --git a/atari_py/ale_interface/src/games/supported/BeamRider.hpp b/atari_py/ale_interface/src/games/supported/BeamRider.hpp index 99fa61c..b506ecb 100644 --- a/atari_py/ale_interface/src/games/supported/BeamRider.hpp +++ b/atari_py/ale_interface/src/games/supported/BeamRider.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 69 and 76 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -66,7 +66,11 @@ class BeamRiderSettings : public RomSettings { ActionVect getStartingActions(); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + // returns a list of difficulties that the game can be played in + // in this game, there are 2 available difficulties. + DifficultyVect getAvailableDifficulties(); private: diff --git a/atari_py/ale_interface/src/games/supported/Berzerk.cpp b/atari_py/ale_interface/src/games/supported/Berzerk.cpp index e6926fb..f6a468c 100644 --- a/atari_py/ale_interface/src/games/supported/Berzerk.cpp +++ b/atari_py/ale_interface/src/games/supported/Berzerk.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 44, 97, 107 and 115 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -130,3 +130,45 @@ void BerzerkSettings::loadState(Deserializer & ser) { m_lives = ser.getInt(); } +// returns a list of mode that the game can be played in +ModeVect BerzerkSettings::getAvailableModes() { + ModeVect modes(getNumModes() - 3); + for (unsigned int i = 0; i < modes.size(); i++) { + //this is 1-12 in Atari-decimal (0x01 ... 0x09 0x10 0x11 0x12) + modes[i] = i + 1; + } + modes.push_back(0x10); + modes.push_back(0x11); + modes.push_back(0x12); + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void BerzerkSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + if(m == 0) { + m = 1; // The mode 0, which is the default, is not available in this game. + } + if(m >= 1 && (m <= 9 || m == 0x10 || m == 0x11 || m == 0x12)) { + // we wait that the game is ready to change mode + for(unsigned int i = 0; i < 20; i++) { + environment->act(PLAYER_A_NOOP, PLAYER_B_NOOP); + } + // read the mode we are currently in + unsigned char mode = readRam(&system, 0x80); + // press select until the correct mode is reached + while (mode != m) { + environment->pressSelect(2); + mode = readRam(&system, 0x80); + } + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } + + diff --git a/atari_py/ale_interface/src/games/supported/Berzerk.hpp b/atari_py/ale_interface/src/games/supported/Berzerk.hpp index f0ff793..832d569 100644 --- a/atari_py/ale_interface/src/games/supported/Berzerk.hpp +++ b/atari_py/ale_interface/src/games/supported/Berzerk.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 67 and 74 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class BerzerkSettings : public RomSettings { // the rom-name const char* rom() const { return "berzerk"; } + // get the available number of modes + unsigned int getNumModes() const { return 12; } + // create a new instance of the rom RomSettings* clone() const; @@ -64,7 +67,17 @@ class BerzerkSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + // returns a list of mode that the game can be played in + // in this game, there are 12 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); + private: diff --git a/atari_py/ale_interface/src/games/supported/Bowling.cpp b/atari_py/ale_interface/src/games/supported/Bowling.cpp index d305243..177d928 100644 --- a/atari_py/ale_interface/src/games/supported/Bowling.cpp +++ b/atari_py/ale_interface/src/games/supported/Bowling.cpp @@ -98,3 +98,35 @@ void BowlingSettings::loadState(Deserializer & ser) { m_terminal = ser.getBool(); } +// returns a list of mode that the game can be played in +ModeVect BowlingSettings::getAvailableModes() { + ModeVect modes = {0, 2, 4}; + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void BowlingSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + if(m == 0 || m == 2 || m == 4) { + // read the mode we are currently in + unsigned char mode = readRam(&system, 2); + // press select until the correct mode is reached + while (mode != m) { + environment->pressSelect(2); + mode = readRam(&system, 2); + } + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } + +DifficultyVect BowlingSettings::getAvailableDifficulties() { + DifficultyVect diff = {0, 1}; + return diff; +} + diff --git a/atari_py/ale_interface/src/games/supported/Bowling.hpp b/atari_py/ale_interface/src/games/supported/Bowling.hpp index 721f0ed..e57d55c 100644 --- a/atari_py/ale_interface/src/games/supported/Bowling.hpp +++ b/atari_py/ale_interface/src/games/supported/Bowling.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The line 67 is based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class BowlingSettings : public RomSettings { // the rom-name const char* rom() const { return "bowling"; } + // get the available number of modes + unsigned int getNumModes() const { return 3; } + // create a new instance of the rom RomSettings* clone() const; @@ -65,7 +68,20 @@ class BowlingSettings : public RomSettings { void loadState(Deserializer & ser); // No lives in bowling! - virtual const int lives() { return 0; } + virtual int lives() { return 0; } + + // returns a list of mode that the game can be played in + // in this game, there are 3 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); + + // returns a list of difficulties that the game can be played in + // in this game, there are 2 available difficulties + DifficultyVect getAvailableDifficulties(); private: diff --git a/atari_py/ale_interface/src/games/supported/Boxing.cpp b/atari_py/ale_interface/src/games/supported/Boxing.cpp index 522709c..9b388c5 100644 --- a/atari_py/ale_interface/src/games/supported/Boxing.cpp +++ b/atari_py/ale_interface/src/games/supported/Boxing.cpp @@ -123,3 +123,7 @@ void BoxingSettings::loadState(Deserializer & ser) { m_terminal = ser.getBool(); } +DifficultyVect BoxingSettings::getAvailableDifficulties() { + DifficultyVect diff = {0, 1, 2, 3}; + return diff; +} diff --git a/atari_py/ale_interface/src/games/supported/Boxing.hpp b/atari_py/ale_interface/src/games/supported/Boxing.hpp index c0add39..6d5db32 100644 --- a/atari_py/ale_interface/src/games/supported/Boxing.hpp +++ b/atari_py/ale_interface/src/games/supported/Boxing.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The line 67 is based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -64,7 +64,11 @@ class BoxingSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return 0; } + virtual int lives() { return 0; } + + // returns a list of difficulties that the game can be played in + // in this game, there are 4 available difficulties + DifficultyVect getAvailableDifficulties(); private: diff --git a/atari_py/ale_interface/src/games/supported/Breakout.cpp b/atari_py/ale_interface/src/games/supported/Breakout.cpp index 10fb51f..1c89a8f 100644 --- a/atari_py/ale_interface/src/games/supported/Breakout.cpp +++ b/atari_py/ale_interface/src/games/supported/Breakout.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 61, 101, 113 and 122 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -120,3 +120,39 @@ void BreakoutSettings::loadState(Deserializer & ser) { m_lives = ser.getInt(); } +// returns a list of mode that the game can be played in +ModeVect BreakoutSettings::getAvailableModes() { + ModeVect modes(getNumModes()); + for (unsigned int i = 0; i < modes.size(); i++) { + modes[i] = i * 4; + } + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void BreakoutSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + if(m < getNumModes() * 4 && m % 4 == 0) { + // read the mode we are currently in + unsigned char mode = readRam(&system, 0xB2); + // press select until the correct mode is reached + while (mode != m) { + environment->pressSelect(); + mode = readRam(&system, 0xB2); + } + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } + + +DifficultyVect BreakoutSettings::getAvailableDifficulties() { + DifficultyVect diff = {0, 1}; + return diff; +} + diff --git a/atari_py/ale_interface/src/games/supported/Breakout.hpp b/atari_py/ale_interface/src/games/supported/Breakout.hpp index c229298..1c2fa66 100644 --- a/atari_py/ale_interface/src/games/supported/Breakout.hpp +++ b/atari_py/ale_interface/src/games/supported/Breakout.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 68 and 76 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class BreakoutSettings : public RomSettings { // the rom-name const char* rom() const { return "breakout"; } + // get the available number of modes + unsigned int getNumModes() const { return 12; } + // create a new instance of the rom RomSettings* clone() const; @@ -65,7 +68,20 @@ class BreakoutSettings : public RomSettings { void loadState(Deserializer & ser); // remaining lives - const int lives() { return isTerminal() ? 0 : m_lives; } + int lives() { return isTerminal() ? 0 : m_lives; } + + // returns a list of mode that the game can be played in + // in this game, there are 8 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); + + // returns a list of difficulties that the game can be played in + // in this game, there are 2 available difficulties + DifficultyVect getAvailableDifficulties(); private: diff --git a/atari_py/ale_interface/src/games/supported/Carnival.hpp b/atari_py/ale_interface/src/games/supported/Carnival.hpp index 6ee6fc2..b9662de 100644 --- a/atari_py/ale_interface/src/games/supported/Carnival.hpp +++ b/atari_py/ale_interface/src/games/supported/Carnival.hpp @@ -64,7 +64,7 @@ class CarnivalSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return 0; } + virtual int lives() { return 0; } private: diff --git a/atari_py/ale_interface/src/games/supported/Centipede.cpp b/atari_py/ale_interface/src/games/supported/Centipede.cpp index c3d628b..ba938aa 100644 --- a/atari_py/ale_interface/src/games/supported/Centipede.cpp +++ b/atari_py/ale_interface/src/games/supported/Centipede.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 59, 116, 126 and 134 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -134,3 +134,32 @@ void CentipedeSettings::loadState(Deserializer & ser) { m_lives = ser.getInt(); } +// returns a list of mode that the game can be played in +ModeVect CentipedeSettings::getAvailableModes() { + ModeVect modes = {0x16, 0x56}; + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void CentipedeSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + if (m == 0) { + m = 0x16; // The default mode doesn't work here. + } + if(m == 0x16 || m == 0x56) { + // read the mode we are currently in + unsigned char mode = readRam(&system, 0xA7); + // press select until the correct mode is reached + while (mode != m) { + environment->pressSelect(2); + mode = readRam(&system, 0xA7); + } + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } + diff --git a/atari_py/ale_interface/src/games/supported/Centipede.hpp b/atari_py/ale_interface/src/games/supported/Centipede.hpp index e8ed11e..21c7baf 100644 --- a/atari_py/ale_interface/src/games/supported/Centipede.hpp +++ b/atari_py/ale_interface/src/games/supported/Centipede.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 67 and 74 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class CentipedeSettings : public RomSettings { // the rom-name const char* rom() const { return "centipede"; } + // get the available number of modes + unsigned int getNumModes() const { return 2; } + // create a new instance of the rom RomSettings* clone() const; @@ -64,7 +67,16 @@ class CentipedeSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + // returns a list of mode that the game can be played in + // in this game, there are 8 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); private: diff --git a/atari_py/ale_interface/src/games/supported/ChopperCommand.cpp b/atari_py/ale_interface/src/games/supported/ChopperCommand.cpp index 015eab3..15d8f37 100644 --- a/atari_py/ale_interface/src/games/supported/ChopperCommand.cpp +++ b/atari_py/ale_interface/src/games/supported/ChopperCommand.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 42, 96, 106 and 114 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -56,13 +56,14 @@ void ChopperCommandSettings::step(const System& system) { // update terminal status m_lives = readRam(&system, 0xE4) & 0xF; m_terminal = (m_lives == 0); + m_is_started = (readRam(&system, 0xC2) == 1); } /* is end of game */ bool ChopperCommandSettings::isTerminal() const { - return m_terminal; + return (m_is_started && m_terminal); }; @@ -109,6 +110,7 @@ void ChopperCommandSettings::reset() { m_score = 0; m_terminal = false; m_lives = 3; + m_is_started = false; } @@ -129,3 +131,36 @@ void ChopperCommandSettings::loadState(Deserializer & ser) { m_lives = ser.getInt(); } + +// returns a list of mode that the game can be played in +ModeVect ChopperCommandSettings::getAvailableModes() { + ModeVect modes = {0, 2}; + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void ChopperCommandSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + if(m == 0 || m == 2) { + // read the mode we are currently in + unsigned char mode = readRam(&system, 0xE0); + // press select until the correct mode is reached + while (mode != m) { + environment->pressSelect(2); + mode = readRam(&system, 0xE0); + } + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } + +DifficultyVect ChopperCommandSettings::getAvailableDifficulties() { + DifficultyVect diff = {0, 1}; + return diff; +} + diff --git a/atari_py/ale_interface/src/games/supported/ChopperCommand.hpp b/atari_py/ale_interface/src/games/supported/ChopperCommand.hpp index b055aba..cfef0ab 100644 --- a/atari_py/ale_interface/src/games/supported/ChopperCommand.hpp +++ b/atari_py/ale_interface/src/games/supported/ChopperCommand.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 67 and 74 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class ChopperCommandSettings : public RomSettings { // the rom-name const char* rom() const { return "chopper_command"; } + // get the available number of modes + unsigned int getNumModes() const { return 2; } + // create a new instance of the rom RomSettings* clone() const; @@ -64,10 +67,24 @@ class ChopperCommandSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return m_lives; } + virtual int lives() { return m_lives; } + + // returns a list of mode that the game can be played in + // in this game, there are 2 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); + + // returns a list of difficulties that the game can be played in + // in this game, there are 2 available difficulties + DifficultyVect getAvailableDifficulties(); private: + bool m_is_started; bool m_terminal; reward_t m_reward; reward_t m_score; diff --git a/atari_py/ale_interface/src/games/supported/CrazyClimber.cpp b/atari_py/ale_interface/src/games/supported/CrazyClimber.cpp index 825d816..9d5eac1 100644 --- a/atari_py/ale_interface/src/games/supported/CrazyClimber.cpp +++ b/atari_py/ale_interface/src/games/supported/CrazyClimber.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 117, 126 and 124 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -124,3 +124,38 @@ void CrazyClimberSettings::loadState(Deserializer & ser) { m_lives = ser.getInt(); } +// returns a list of mode that the game can be played in +ModeVect CrazyClimberSettings::getAvailableModes() { + ModeVect modes(getNumModes()); + for (unsigned int i = 0; i < modes.size(); i++) { + modes[i] = i; + } + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void CrazyClimberSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + if(m < getNumModes()) { + // read the mode we are currently in + unsigned char mode = readRam(&system, 0x80); + // press select until the correct mode is reached + while (mode != m) { + environment->pressSelect(2); + mode = readRam(&system, 0x80); + } + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } + +DifficultyVect CrazyClimberSettings::getAvailableDifficulties() { + DifficultyVect diff = {0, 1}; + return diff; +} + diff --git a/atari_py/ale_interface/src/games/supported/CrazyClimber.hpp b/atari_py/ale_interface/src/games/supported/CrazyClimber.hpp index 4f6aa26..f1272cb 100644 --- a/atari_py/ale_interface/src/games/supported/CrazyClimber.hpp +++ b/atari_py/ale_interface/src/games/supported/CrazyClimber.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 67 and 74 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class CrazyClimberSettings : public RomSettings { // the rom-name const char* rom() const { return "crazy_climber"; } + // get the available number of modes + unsigned int getNumModes() const { return 4; } + // create a new instance of the rom RomSettings* clone() const; @@ -64,7 +67,20 @@ class CrazyClimberSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + // returns a list of mode that the game can be played in + // in this game, there are 4 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); + + // returns a list of difficulties that the game can be played in + // in this game, there are 2 available difficulties + DifficultyVect getAvailableDifficulties(); private: diff --git a/atari_py/ale_interface/src/games/supported/Defender.cpp b/atari_py/ale_interface/src/games/supported/Defender.cpp index 37c60c3..9d50ae3 100644 --- a/atari_py/ale_interface/src/games/supported/Defender.cpp +++ b/atari_py/ale_interface/src/games/supported/Defender.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 117, 126 and 134 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -134,3 +134,43 @@ void DefenderSettings::loadState(Deserializer & ser) { m_lives = ser.getInt(); } +// returns a list of mode that the game can be played in +ModeVect DefenderSettings::getAvailableModes() { + ModeVect modes(getNumModes() - 1); + for (unsigned int i = 0; i < modes.size(); i++) { + modes[i] = i + 1; + } + modes.push_back(16); //easy mode + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void DefenderSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + if(m == 0) { + m = 1; // The default mode (0) is not valid here. + } + if(m >= 1 && (m <= 9 || m == 16)) { + // read the mode we are currently in + unsigned char mode = readRam(&system, 0x9B); + // press select until the correct mode is reached + while (mode != m) { + environment->pressSelect(2); + mode = readRam(&system, 0x9B); + } + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } + +DifficultyVect DefenderSettings::getAvailableDifficulties() { + DifficultyVect diff = {0, 1}; + return diff; +} + + diff --git a/atari_py/ale_interface/src/games/supported/Defender.hpp b/atari_py/ale_interface/src/games/supported/Defender.hpp index 35b20ff..f264eab 100644 --- a/atari_py/ale_interface/src/games/supported/Defender.hpp +++ b/atari_py/ale_interface/src/games/supported/Defender.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 67 and 74 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class DefenderSettings : public RomSettings { // the rom-name const char* rom() const { return "defender"; } + // get the available number of modes + unsigned int getNumModes() const { return 10; } + // create a new instance of the rom RomSettings* clone() const; @@ -64,7 +67,20 @@ class DefenderSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + // returns a list of mode that the game can be played in + // in this game, there are 10 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); + + // returns a list of difficulties that the game can be played in + // in this game, there are 2 available difficulties + DifficultyVect getAvailableDifficulties(); private: diff --git a/atari_py/ale_interface/src/games/supported/DemonAttack.cpp b/atari_py/ale_interface/src/games/supported/DemonAttack.cpp index f985d8f..9d59475 100644 --- a/atari_py/ale_interface/src/games/supported/DemonAttack.cpp +++ b/atari_py/ale_interface/src/games/supported/DemonAttack.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 48, 89, 98 and 106 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -59,8 +59,10 @@ void DemonAttackSettings::step(const System& system) { // update terminal status int lives_displayed = readRam(&system, 0xF2); int display_flag = readRam(&system, 0xF1); - m_terminal = (lives_displayed == 0) && display_flag == 0xBD; + // for terminal checking, we must make sure that we do not detect incorrectly a level change as a game-over + m_terminal = (lives_displayed == 0) && display_flag == 0xBD && !m_level_change; m_lives = lives_displayed + 1; // Once we reach terminal, lives() will correctly return 0 + m_level_change = false; } @@ -102,6 +104,7 @@ void DemonAttackSettings::reset() { m_score = 0; m_terminal = false; m_lives = 4; + m_level_change = false; } @@ -121,3 +124,40 @@ void DemonAttackSettings::loadState(Deserializer & ser) { m_lives = ser.getInt(); } +// returns a list of mode that the game can be played in +ModeVect DemonAttackSettings::getAvailableModes() { + ModeVect modes = {1, 3, 5, 7}; + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void DemonAttackSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + if(m == 0) { + m = 1; // The default mode is not valid here + } + if(m == 1 || m == 3 || m == 5 || m == 7) { + // read the mode we are currently in + unsigned char mode = readRam(&system, 0xEA); + // press select until the correct mode is reached + while (mode != m) { + environment->pressSelect(1); + mode = readRam(&system, 0xEA); + } + m_level_change = true; + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } + +DifficultyVect DemonAttackSettings::getAvailableDifficulties() { + DifficultyVect diff = {0, 1}; + return diff; +} + + diff --git a/atari_py/ale_interface/src/games/supported/DemonAttack.hpp b/atari_py/ale_interface/src/games/supported/DemonAttack.hpp index 444e4a2..6fd9122 100644 --- a/atari_py/ale_interface/src/games/supported/DemonAttack.hpp +++ b/atari_py/ale_interface/src/games/supported/DemonAttack.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 67 and 74 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class DemonAttackSettings : public RomSettings { // the rom-name const char* rom() const { return "demon_attack"; } + // get the available number of modes + unsigned int getNumModes() const { return 8; } + // create a new instance of the rom RomSettings* clone() const; @@ -64,7 +67,20 @@ class DemonAttackSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + // returns a list of mode that the game can be played in + // in this game, there are 8 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); + + // returns a list of difficulties that the game can be played in + // in this game, there are 2 available difficulties + DifficultyVect getAvailableDifficulties(); private: @@ -72,6 +88,7 @@ class DemonAttackSettings : public RomSettings { reward_t m_reward; reward_t m_score; int m_lives; + bool m_level_change; }; #endif // __DEMONATTACK_HPP__ diff --git a/atari_py/ale_interface/src/games/supported/DonkeyKong.cpp b/atari_py/ale_interface/src/games/supported/DonkeyKong.cpp new file mode 100644 index 0000000..c3af6ec --- /dev/null +++ b/atari_py/ale_interface/src/games/supported/DonkeyKong.cpp @@ -0,0 +1,109 @@ +/* ***************************************************************************** + * A.L.E (Arcade Learning Environment) + * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and + * the Reinforcement Learning and Artificial Intelligence Laboratory + * Released under the GNU General Public License; see License.txt for details. + * + * Based on: Stella -- "An Atari 2600 VCS Emulator" + * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team + * + * ***************************************************************************** + */ +#include "DonkeyKong.hpp" + +#include "../RomUtils.hpp" + + +DonkeyKongSettings::DonkeyKongSettings() { + reset(); +} + + +/* create a new instance of the rom */ +RomSettings* DonkeyKongSettings::clone() const { + RomSettings* rval = new DonkeyKongSettings(); + *rval = *this; + return rval; +} + + +/* process the latest information from ALE */ +void DonkeyKongSettings::step(const System& system) { + // update the reward + int score = getDecimalScore(0x88, 0x87, &system); + score *= 100; + int reward = score - m_score; + m_reward = reward; + m_score = score; + + // update lives and terminal status + m_lives = readRam(&system, 0xA3); + m_terminal = (m_lives == 0) + && readRam(&system, 0x8F) == 0x03 + && readRam(&system, 0x8B) == 0x1F; +} + +/* is end of game */ +bool DonkeyKongSettings::isTerminal() const { + return m_terminal; +}; + + +/* get the most recently observed reward */ +reward_t DonkeyKongSettings::getReward() const { + return m_reward; +} + + +/* is an action part of the minimal set? */ +bool DonkeyKongSettings::isMinimal(const Action &a) const { + switch (a) { + case PLAYER_A_NOOP: + case PLAYER_A_FIRE: + case PLAYER_A_UP: + case PLAYER_A_RIGHT: + case PLAYER_A_LEFT: + case PLAYER_A_DOWN: + case PLAYER_A_UPRIGHT: + case PLAYER_A_UPLEFT: + case PLAYER_A_DOWNRIGHT: + case PLAYER_A_DOWNLEFT: + case PLAYER_A_UPFIRE: + case PLAYER_A_RIGHTFIRE: + case PLAYER_A_LEFTFIRE: + case PLAYER_A_DOWNFIRE: + case PLAYER_A_UPRIGHTFIRE: + case PLAYER_A_UPLEFTFIRE: + case PLAYER_A_DOWNRIGHTFIRE: + case PLAYER_A_DOWNLEFTFIRE: + return true; + default: + return false; + } +} + + +/* reset the state of the game */ +void DonkeyKongSettings::reset() { + m_reward = 0; + m_score = 0; + m_terminal = false; + m_lives = 2; +} + +/* saves the state of the rom settings */ +void DonkeyKongSettings::saveState(Serializer & ser) { + ser.putInt(m_reward); + ser.putInt(m_score); + ser.putBool(m_terminal); + ser.putInt(m_lives); +} + +// loads the state of the rom settings +void DonkeyKongSettings::loadState(Deserializer & ser) { + m_reward = ser.getInt(); + m_score = ser.getInt(); + m_terminal = ser.getBool(); + m_lives = ser.getInt(); +} + diff --git a/atari_py/ale_interface/src/games/supported/DonkeyKong.hpp b/atari_py/ale_interface/src/games/supported/DonkeyKong.hpp new file mode 100644 index 0000000..e485f41 --- /dev/null +++ b/atari_py/ale_interface/src/games/supported/DonkeyKong.hpp @@ -0,0 +1,63 @@ +/* ***************************************************************************** + * A.L.E (Arcade Learning Environment) + * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and + * the Reinforcement Learning and Artificial Intelligence Laboratory + * Released under the GNU General Public License; see License.txt for details. + * + * Based on: Stella -- "An Atari 2600 VCS Emulator" + * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team + * + * ***************************************************************************** + */ +#ifndef __DONKEYKONG_HPP__ +#define __DONKEYKONG_HPP__ + +#include "../RomSettings.hpp" + + +/* RL wrapper for DonkeyKong */ +class DonkeyKongSettings : public RomSettings { + + public: + + DonkeyKongSettings(); + + // reset + void reset(); + + // is end of game + bool isTerminal() const; + + // get the most recently observed reward + reward_t getReward() const; + + // the rom-name + // MD5 36b20c427975760cb9cf4a47e41369e4 + const char* rom() const { return "donkey_kong"; } + + // create a new instance of the rom + RomSettings* clone() const; + + // is an action part of the minimal set? + bool isMinimal(const Action& a) const; + + // process the latest information from ALE + void step(const System& system); + + // saves the state of the rom settings + void saveState(Serializer & ser); + + // loads the state of the rom settings + void loadState(Deserializer & ser); + + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + private: + bool m_terminal; + reward_t m_reward; + reward_t m_score; + int m_lives; +}; + +#endif // __DONKEYKONG_HPP__ + diff --git a/atari_py/ale_interface/src/games/supported/DoubleDunk.cpp b/atari_py/ale_interface/src/games/supported/DoubleDunk.cpp index d9b5b2e..dd8c7a3 100644 --- a/atari_py/ale_interface/src/games/supported/DoubleDunk.cpp +++ b/atari_py/ale_interface/src/games/supported/DoubleDunk.cpp @@ -116,3 +116,102 @@ ActionVect DoubleDunkSettings::getStartingActions() { startingActions.push_back(PLAYER_A_UPFIRE); return startingActions; } + +// returns a list of mode that the game can be played in +ModeVect DoubleDunkSettings::getAvailableModes() { + // this game has a menu that allows to define various yes/no options + // setting these options define in a way a different mode + // there are 4 relevant options, which makes 2^4=16 available modes + ModeVect modes(getNumModes()); + for (unsigned int i = 0; i < modes.size(); i++) { + modes[i] = i; + } + return modes; +} + +void DoubleDunkSettings::goDown(System &system, + std::unique_ptr &environment) { + // this game has a menu that allows to define various yes/no options + // this function goes to the next option in the menu + unsigned int previousSelection = readRam(&system, 0xB0); + while(previousSelection == readRam(&system, 0xB0)){ + environment->act(PLAYER_A_DOWN, PLAYER_B_NOOP); + environment->act(PLAYER_A_NOOP, PLAYER_B_NOOP); + } +} + +void DoubleDunkSettings::activateOption(System &system, unsigned int bitOfInterest, + std::unique_ptr &environment) { + // once we are at the proper option in the menu, + // if we want to enable it all we have to do is to go right + while((readRam(&system, 0x80) & bitOfInterest) != bitOfInterest) { + environment->act(PLAYER_A_RIGHT, PLAYER_B_NOOP); + environment->act(PLAYER_A_NOOP, PLAYER_B_NOOP); + } +} + +void DoubleDunkSettings::deactivateOption(System &system, unsigned int bitOfInterest, + std::unique_ptr &environment) { + // once we are at the proper optio in the menu, + // if we want to disable it all we have to do is to go left + while((readRam(&system, 0x80) & bitOfInterest) == bitOfInterest) { + environment->act(PLAYER_A_LEFT, PLAYER_B_NOOP); + environment->act(PLAYER_A_NOOP, PLAYER_B_NOOP); + } +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void DoubleDunkSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + if(m < getNumModes()) { + environment->pressSelect(); + + //discard the first two entries (irrelevant) + goDown(system, environment); + goDown(system, environment); + + //deal with the 3 points option + if(m & 1) { + activateOption(system, 0x08, environment); + } else { + deactivateOption(system, 0x08, environment); + } + + //deal with the 10 seconds option + goDown(system, environment); + if(m & 2) { + activateOption(system, 0x10, environment); + } else { + deactivateOption(system, 0x10, environment); + } + + //deal with the 3 seconds option + goDown(system, environment); + if(m & 4) { + activateOption(system, 0x04, environment); + } else { + deactivateOption(system, 0x04, environment); + } + + //deal with the foul option + goDown(system, environment); + if(m & 8) { + activateOption(system, 0x20, environment); + } else { + deactivateOption(system, 0x20, environment); + } + + //reset the environment to apply changes. + environment->softReset(); + //apply starting action + environment->act(PLAYER_A_UPFIRE, PLAYER_B_NOOP); + environment->act(PLAYER_A_NOOP, PLAYER_B_NOOP); + + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } + diff --git a/atari_py/ale_interface/src/games/supported/DoubleDunk.hpp b/atari_py/ale_interface/src/games/supported/DoubleDunk.hpp index c568c1b..3f2da25 100644 --- a/atari_py/ale_interface/src/games/supported/DoubleDunk.hpp +++ b/atari_py/ale_interface/src/games/supported/DoubleDunk.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The line 69 is based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class DoubleDunkSettings : public RomSettings { // the rom-name const char* rom() const { return "double_dunk"; } + // get the available number of modes + unsigned int getNumModes() const { return 16; } + // create a new instance of the rom RomSettings* clone() const; @@ -66,13 +69,38 @@ class DoubleDunkSettings : public RomSettings { ActionVect getStartingActions(); - virtual const int lives() { return 0; } + virtual int lives() { return 0; } + + // returns a list of mode that the game can be played in + // in this game, there are 16 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); + private: bool m_terminal; reward_t m_reward; reward_t m_score; + + // this game has a menu that allows to define various yes/no options + // this function goes to the next option in the menu + void goDown(System &system, + std::unique_ptr &environment); + + // once we are at the proper option in the menu, + // if we want to enable it all we have to do is to go right + void activateOption(System &system, unsigned int bitOfInterest, + std::unique_ptr &environment); + + // once we are at the proper optio in the menu, + // if we want to disable it all we have to do is to go left + void deactivateOption(System &system, unsigned int bitOfInterest, + std::unique_ptr &environment); }; #endif // __DOUBLEDUNK_HPP__ diff --git a/atari_py/ale_interface/src/games/supported/ElevatorAction.hpp b/atari_py/ale_interface/src/games/supported/ElevatorAction.hpp index 05c2a61..c9528ca 100644 --- a/atari_py/ale_interface/src/games/supported/ElevatorAction.hpp +++ b/atari_py/ale_interface/src/games/supported/ElevatorAction.hpp @@ -66,7 +66,7 @@ class ElevatorActionSettings : public RomSettings { ActionVect getStartingActions(); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } private: diff --git a/atari_py/ale_interface/src/games/supported/Enduro.hpp b/atari_py/ale_interface/src/games/supported/Enduro.hpp index 02420cf..dc1386e 100644 --- a/atari_py/ale_interface/src/games/supported/Enduro.hpp +++ b/atari_py/ale_interface/src/games/supported/Enduro.hpp @@ -66,7 +66,7 @@ class EnduroSettings : public RomSettings { ActionVect getStartingActions(); - virtual const int lives() { return 0; } + virtual int lives() { return 0; } private: diff --git a/atari_py/ale_interface/src/games/supported/FishingDerby.cpp b/atari_py/ale_interface/src/games/supported/FishingDerby.cpp index af87c76..942d4ad 100644 --- a/atari_py/ale_interface/src/games/supported/FishingDerby.cpp +++ b/atari_py/ale_interface/src/games/supported/FishingDerby.cpp @@ -41,7 +41,7 @@ void FishingDerbySettings::step(const System& system) { m_score = score; // update terminal status - int my_score_byte = readRam(&system, 0xBD); + int my_score_byte = readRam(&system, 0xBD); int my_oppt_score_byte = readRam(&system, 0xBE); m_terminal = my_score_byte == 0x99 || my_oppt_score_byte == 0x99; @@ -114,3 +114,9 @@ void FishingDerbySettings::loadState(Deserializer & ser) { m_terminal = ser.getBool(); } +DifficultyVect FishingDerbySettings::getAvailableDifficulties() { + DifficultyVect diff = {0, 1, 2, 3}; + return diff; +} + + diff --git a/atari_py/ale_interface/src/games/supported/FishingDerby.hpp b/atari_py/ale_interface/src/games/supported/FishingDerby.hpp index 1bcb439..2a79053 100644 --- a/atari_py/ale_interface/src/games/supported/FishingDerby.hpp +++ b/atari_py/ale_interface/src/games/supported/FishingDerby.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The line 67 is based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -64,7 +64,11 @@ class FishingDerbySettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return 0; } + virtual int lives() { return 0; } + + // returns a list of difficulties that the game can be played in + // in this game, there are 4 available difficulties + DifficultyVect getAvailableDifficulties(); private: diff --git a/atari_py/ale_interface/src/games/supported/Freeway.cpp b/atari_py/ale_interface/src/games/supported/Freeway.cpp index 3cce63b..e34246f 100644 --- a/atari_py/ale_interface/src/games/supported/Freeway.cpp +++ b/atari_py/ale_interface/src/games/supported/Freeway.cpp @@ -1,4 +1,6 @@ /* ***************************************************************************** + * The method lives() is based on Xitari's code, from Google Inc. + * * A.L.E (Arcade Learning Environment) * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and * the Reinforcement Learning and Artificial Intelligence Laboratory @@ -16,7 +18,9 @@ FreewaySettings::FreewaySettings() { - reset(); + m_reward = 0; + m_score = 0; + m_terminal = false; } @@ -58,7 +62,6 @@ reward_t FreewaySettings::getReward() const { return m_reward; } - /* is an action part of the minimal set? */ bool FreewaySettings::isMinimal(const Action &a) const { @@ -95,3 +98,38 @@ void FreewaySettings::loadState(Deserializer & ser) { m_terminal = ser.getBool(); } +// returns a list of mode that the game can be played in +ModeVect FreewaySettings::getAvailableModes() { + ModeVect modes(getNumModes()); + for (unsigned int i = 0; i < modes.size(); i++) { + modes[i] = i; + } + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void FreewaySettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + if(m < getNumModes()) { + // read the mode we are currently in + unsigned char mode = readRam(&system, 0x80); + // press select until the correct mode is reached + while (mode != m) { + environment->pressSelect(); + mode = readRam(&system, 0x80); + } + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } + +DifficultyVect FreewaySettings::getAvailableDifficulties() { + DifficultyVect diff = {0, 1}; + return diff; +} + diff --git a/atari_py/ale_interface/src/games/supported/Freeway.hpp b/atari_py/ale_interface/src/games/supported/Freeway.hpp index 6cf5bb0..59d6cd7 100644 --- a/atari_py/ale_interface/src/games/supported/Freeway.hpp +++ b/atari_py/ale_interface/src/games/supported/Freeway.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The line 67 is based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -27,6 +27,7 @@ #ifndef __FREEWAY_HPP__ #define __FREEWAY_HPP__ +#include "stella_environment_wrapper.hpp" #include "../RomSettings.hpp" @@ -49,6 +50,9 @@ class FreewaySettings : public RomSettings { // the rom-name const char* rom() const { return "freeway"; } + // get the available number of modes + unsigned int getNumModes() const { return 8; } + // create a new instance of the rom RomSettings* clone() const; @@ -64,10 +68,22 @@ class FreewaySettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return 0; } + virtual int lives() { return 0; } - private: + // returns a list of mode that the game can be played in + // in this game, there are 8 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); + // returns a list of difficulties that the game can be played in + // in this game, there are 2 available difficulties + DifficultyVect getAvailableDifficulties(); + + private: bool m_terminal; reward_t m_reward; reward_t m_score; diff --git a/atari_py/ale_interface/src/games/supported/Frogger.cpp b/atari_py/ale_interface/src/games/supported/Frogger.cpp new file mode 100644 index 0000000..6e8c449 --- /dev/null +++ b/atari_py/ale_interface/src/games/supported/Frogger.cpp @@ -0,0 +1,96 @@ +/* ***************************************************************************** + * A.L.E (Arcade Learning Environment) + * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and + * the Reinforcement Learning and Artificial Intelligence Laboratory + * Released under the GNU General Public License; see License.txt for details. + * + * Based on: Stella -- "An Atari 2600 VCS Emulator" + * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team + * + * ***************************************************************************** + */ +#include "Frogger.hpp" + +#include "../RomUtils.hpp" + +FroggerSettings::FroggerSettings() { + reset(); +} + +/* create a new instance of the rom */ +RomSettings* FroggerSettings::clone() const { + RomSettings* rval = new FroggerSettings(); + *rval = *this; + return rval; +} + + +/* process the latest information from ALE */ +void FroggerSettings::step(const System& system) { + // update the reward + int score = getDecimalScore(0xCE, 0xCC, &system); + int reward = score - m_score; + m_reward = reward; + m_score = score; + + // update terminal status + m_lives = readRam(&system, 0xD0); + m_terminal = readRam(&system, 0xD0) == 0xFF; +} + + +/* is end of game */ +bool FroggerSettings::isTerminal() const { + return m_terminal; +}; + + +/* get the most recently observed reward */ +reward_t FroggerSettings::getReward() const { + return m_reward; +} + +/* is an action part of the minimal set? */ +bool FroggerSettings::isMinimal(const Action &a) const { + switch (a) { + case PLAYER_A_NOOP: + case PLAYER_A_UP: + case PLAYER_A_RIGHT: + case PLAYER_A_LEFT: + case PLAYER_A_DOWN: + return true; + default: + return false; + } +} + + +/* reset the state of the game */ +void FroggerSettings::reset() { + m_reward = 0; + m_score = 0; + m_terminal = false; + m_lives = 4; +} + +/* saves the state of the rom settings */ +void FroggerSettings::saveState(Serializer & ser) { + ser.putInt(m_reward); + ser.putInt(m_score); + ser.putBool(m_terminal); + ser.putInt(m_lives); +} + +// loads the state of the rom settings +void FroggerSettings::loadState(Deserializer & ser) { + m_reward = ser.getInt(); + m_score = ser.getInt(); + m_terminal = ser.getBool(); + m_lives = ser.getInt(); +} + +ActionVect FroggerSettings::getStartingActions() { + ActionVect startingActions; + startingActions.push_back(RESET); + return startingActions; +} diff --git a/atari_py/ale_interface/src/games/supported/Frogger.hpp b/atari_py/ale_interface/src/games/supported/Frogger.hpp new file mode 100644 index 0000000..725bc36 --- /dev/null +++ b/atari_py/ale_interface/src/games/supported/Frogger.hpp @@ -0,0 +1,64 @@ +/* ***************************************************************************** + * A.L.E (Arcade Learning Environment) + * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and + * the Reinforcement Learning and Artificial Intelligence Laboratory + * Released under the GNU General Public License; see License.txt for details. + * + * Based on: Stella -- "An Atari 2600 VCS Emulator" + * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team + * + * ***************************************************************************** + */ +#ifndef __FROGGER_HPP__ +#define __FROGGER_HPP__ + +#include "../RomSettings.hpp" + + +/* RL wrapper for Frogger */ +class FroggerSettings : public RomSettings { + public: + FroggerSettings(); + + // reset + void reset(); + + // is end of game + bool isTerminal() const; + + // get the most recently observed reward + reward_t getReward() const; + + // the rom-name + // MD5 081e2c114c9c20b61acf25fc95c71bf4 + const char* rom() const { return "frogger"; } + + // create a new instance of the rom + RomSettings* clone() const; + + // is an action part of the minimal set? + bool isMinimal(const Action& a) const; + + // process the latest information from ALE + void step(const System& system); + + // saves the state of the rom settings + void saveState(Serializer & ser); + + // loads the state of the rom settings + void loadState(Deserializer & ser); + + // Frogger requires the RESET action to start the game + ActionVect getStartingActions(); + + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + private: + bool m_terminal; + reward_t m_reward; + reward_t m_score; + int m_lives; +}; + +#endif // __FROGGER_HPP__ + diff --git a/atari_py/ale_interface/src/games/supported/Frostbite.cpp b/atari_py/ale_interface/src/games/supported/Frostbite.cpp index 8cf0492..2439212 100644 --- a/atari_py/ale_interface/src/games/supported/Frostbite.cpp +++ b/atari_py/ale_interface/src/games/supported/Frostbite.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 61, 115, 123 and 131 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -133,3 +133,30 @@ void FrostbiteSettings::loadState(Deserializer & ser) { m_lives = ser.getInt(); } +// returns a list of mode that the game can be played in +ModeVect FrostbiteSettings::getAvailableModes() { + ModeVect modes = {0, 2}; + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void FrostbiteSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + if(m == 0 || m == 2) { + // read the mode we are currently in + unsigned char mode = readRam(&system, 0x80); + // press select until the correct mode is reached + while (mode != m) { + environment->pressSelect(1); + mode = readRam(&system, 0x80); + } + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } + diff --git a/atari_py/ale_interface/src/games/supported/Frostbite.hpp b/atari_py/ale_interface/src/games/supported/Frostbite.hpp index 0225e2a..d06b59f 100644 --- a/atari_py/ale_interface/src/games/supported/Frostbite.hpp +++ b/atari_py/ale_interface/src/games/supported/Frostbite.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 67 and 74 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class FrostbiteSettings : public RomSettings { // the rom-name const char* rom() const { return "frostbite"; } + // get the available number of modes + unsigned int getNumModes() const { return 2; } + // create a new instance of the rom RomSettings* clone() const; @@ -64,7 +67,17 @@ class FrostbiteSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + // returns a list of mode that the game can be played in + // in this game, there are 2 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); + private: diff --git a/atari_py/ale_interface/src/games/supported/Galaxian.cpp b/atari_py/ale_interface/src/games/supported/Galaxian.cpp new file mode 100644 index 0000000..147d562 --- /dev/null +++ b/atari_py/ale_interface/src/games/supported/Galaxian.cpp @@ -0,0 +1,154 @@ +/* ***************************************************************************** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * ***************************************************************************** + * A.L.E (Arcade Learning Environment) + * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and + * the Reinforcement Learning and Artificial Intelligence Laboratory + * Released under the GNU General Public License; see License.txt for details. + * + * Based on: Stella -- "An Atari 2600 VCS Emulator" + * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team + * + * ***************************************************************************** + */ +#include "Galaxian.hpp" + +#include "../RomUtils.hpp" + +ActionVect GalaxianSettings::actions; + +GalaxianSettings::GalaxianSettings() { + reset(); +} + + +/* create a new instance of the rom */ +RomSettings* GalaxianSettings::clone() const { + RomSettings* rval = new GalaxianSettings(); + *rval = *this; + return rval; +} + + +/* process the latest information from ALE */ +void GalaxianSettings::step(const System& system) { + // update the reward + int score = getDecimalScore(0xAE, 0xAD, 0xAC, &system); + // reward cannot get negative in this game. When it does, it means that the score has looped + // (overflow) + m_reward = score - m_score; + if(m_reward < 0) { + // 1000000 is the highest possible score + const int maximumScore = 1000000; + m_reward = (maximumScore - m_score) + score; + } + m_score = score; + + // update terminal and lives + // If bit 0x80 is on, then game is over + int some_byte = readRam(&system, 0xBF); + m_terminal = (some_byte & 0x80); + if (m_terminal) { + // Force lives to zero when the game is over since otherwise it would be left as 1 + m_lives = 0; + } else { + m_lives = readRam(&system, 0xB9) + 1; // 0xB9 keeps the number of lives shown below the screen + } +} + + +/* is end of game */ +bool GalaxianSettings::isTerminal() const { + return m_terminal; +}; + + +/* get the most recently observed reward */ +reward_t GalaxianSettings::getReward() const { + return m_reward; +} + + +/* is an action part of the minimal set? */ +bool GalaxianSettings::isMinimal(const Action &a) const { + switch (a) { + case PLAYER_A_NOOP: + case PLAYER_A_LEFT: + case PLAYER_A_RIGHT: + case PLAYER_A_FIRE: + case PLAYER_A_LEFTFIRE: + case PLAYER_A_RIGHTFIRE: + return true; + default: + return false; + } +} + + +/* reset the state of the game */ +void GalaxianSettings::reset() { + m_reward = 0; + m_score = 0; + m_terminal = false; + m_lives = 3; +} + + +/* saves the state of the rom settings */ +void GalaxianSettings::saveState(Serializer & ser) { + ser.putInt(m_reward); + ser.putInt(m_score); + ser.putBool(m_terminal); + ser.putInt(m_lives); +} + +// loads the state of the rom settings +void GalaxianSettings::loadState(Deserializer & ser) { + m_reward = ser.getInt(); + m_score = ser.getInt(); + m_terminal = ser.getBool(); + m_lives = ser.getInt(); +} + +// returns a list of mode that the game can be played in +ModeVect GalaxianSettings::getAvailableModes() { + ModeVect modes = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void GalaxianSettings::setMode(game_mode_t mode, System &system, + std::unique_ptr environment) { + + if (mode == 0) + mode = 1; + + if (mode >= 1 && mode <= 9) { + // press select until the correct mode is reached + while (mode != static_cast(readRam(&system, 0xB3))) { + environment->pressSelect(); + } + //reset the environment to apply changes. + environment->softReset(); + } else + { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } +} + + + + diff --git a/atari_py/ale_interface/src/games/supported/Galaxian.hpp b/atari_py/ale_interface/src/games/supported/Galaxian.hpp new file mode 100644 index 0000000..8360b7e --- /dev/null +++ b/atari_py/ale_interface/src/games/supported/Galaxian.hpp @@ -0,0 +1,95 @@ +/* ***************************************************************************** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * ***************************************************************************** + * A.L.E (Arcade Learning Environment) + * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and + * the Reinforcement Learning and Artificial Intelligence Laboratory + * Released under the GNU General Public License; see License.txt for details. + * + * Based on: Stella -- "An Atari 2600 VCS Emulator" + * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team + * + * ***************************************************************************** + */ +#ifndef __GALAXIAN_HPP__ +#define __GALAXIAN_HPP__ + +#include "../RomSettings.hpp" + + +// RL wrapper for Galaxian +class GalaxianSettings : public RomSettings { + + public: + + GalaxianSettings(); + + // reset + void reset(); + + // is end of game + bool isTerminal() const; + + // get the most recently observed reward + reward_t getReward() const; + + // the rom-name + const char* rom() const { return "galaxian"; } + + // create a new instance of the rom + RomSettings* clone() const; + + // is an action part of the minimal set? + bool isMinimal(const Action& a) const; + + // process the latest information from ALE + void step(const System& system); + + // saves the state of the rom settings + void saveState(Serializer & ser); + + // loads the state of the rom settings + void loadState(Deserializer & ser); + + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + // get the available number of modes + unsigned int getNumModes() const { return 9; } + + // returns a list of mode that the game can be played in + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t mode, System &system, + std::unique_ptr environment); + + // Returns a list of difficulties that the game can be played in. + // 2 difficulties: 0 is left B, 1 is left A + DifficultyVect getAvailableDifficulties() { return { 0, 1}; } + + + private: + + bool m_terminal; + reward_t m_reward; + reward_t m_score; + int m_lives; + + static ActionVect actions; +}; + +#endif // __GALAXIAN_HPP__ + diff --git a/atari_py/ale_interface/src/games/supported/Gopher.cpp b/atari_py/ale_interface/src/games/supported/Gopher.cpp index 85e1f72..00785a4 100644 --- a/atari_py/ale_interface/src/games/supported/Gopher.cpp +++ b/atari_py/ale_interface/src/games/supported/Gopher.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 61, 62, 105, 114 and 122 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -127,3 +127,36 @@ ActionVect GopherSettings::getStartingActions() { startingActions.push_back(PLAYER_A_FIRE); return startingActions; } + +// returns a list of mode that the game can be played in +ModeVect GopherSettings::getAvailableModes() { + ModeVect modes = {0, 2}; + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void GopherSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + if(m == 0 || m == 2) { + environment->softReset(); + // read the mode we are currently in + unsigned char mode = readRam(&system, 0xD3); + // press select until the correct mode is reached + while (mode != m) { + environment->pressSelect(5); + mode = readRam(&system, 0xD3); + } + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } + +DifficultyVect GopherSettings::getAvailableDifficulties() { + DifficultyVect diff = {0, 1}; + return diff; +} diff --git a/atari_py/ale_interface/src/games/supported/Gopher.hpp b/atari_py/ale_interface/src/games/supported/Gopher.hpp index 4fc443c..7ebf943 100644 --- a/atari_py/ale_interface/src/games/supported/Gopher.hpp +++ b/atari_py/ale_interface/src/games/supported/Gopher.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 70 and 77 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class GopherSettings : public RomSettings { // the rom-name const char* rom() const { return "gopher"; } + // get the available number of modes + unsigned int getNumModes() const { return 2; } + // create a new instance of the rom RomSettings* clone() const; @@ -67,7 +70,20 @@ class GopherSettings : public RomSettings { // Gopher requires the fire action to start the game ActionVect getStartingActions(); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + // returns a list of mode that the game can be played in + // in this game, there are 8 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); + + // returns a list of difficulties that the game can be played in + // in this game, there are 2 available difficulties + DifficultyVect getAvailableDifficulties(); private: diff --git a/atari_py/ale_interface/src/games/supported/Gravitar.cpp b/atari_py/ale_interface/src/games/supported/Gravitar.cpp index 4b3f783..d1ac437 100644 --- a/atari_py/ale_interface/src/games/supported/Gravitar.cpp +++ b/atari_py/ale_interface/src/games/supported/Gravitar.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 63, 116, 125 and 133 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -139,3 +139,49 @@ ActionVect GravitarSettings::getStartingActions() { startingActions.push_back(PLAYER_A_FIRE); return startingActions; } + +// returns a list of mode that the game can be played in +ModeVect GravitarSettings::getAvailableModes() { + ModeVect modes(getNumModes()); + for (unsigned int i = 0; i < modes.size(); i++) { + modes[i] = i; + } + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void GravitarSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + if(m < getNumModes()) { + // read the mode we are currently in + unsigned char mode = readRam(&system, 0x80); + // press select until the correct mode is reached + while (mode != m) { + // hold select button for 10 frames + environment->pressSelect(10); + mode = readRam(&system, 0x80); + } + + //update the number of lives + switch(m){ + case 0: + case 2: + m_lives = 6; + break; + case 1: + m_lives = 15; + break; + case 3: + m_lives = 100; + case 4: + m_lives = 25; + } + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } diff --git a/atari_py/ale_interface/src/games/supported/Gravitar.hpp b/atari_py/ale_interface/src/games/supported/Gravitar.hpp index 503f57c..3b584fc 100644 --- a/atari_py/ale_interface/src/games/supported/Gravitar.hpp +++ b/atari_py/ale_interface/src/games/supported/Gravitar.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 70 and 77 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class GravitarSettings : public RomSettings { // the rom-name const char* rom() const { return "gravitar"; } + // get the available number of modes + unsigned int getNumModes() const { return 5; } + // create a new instance of the rom RomSettings* clone() const; @@ -67,7 +70,16 @@ class GravitarSettings : public RomSettings { // Gravitar requires the fire action to start the game ActionVect getStartingActions(); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + // returns a list of mode that the game can be played in + // in this game, there are 5 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); private: diff --git a/atari_py/ale_interface/src/games/supported/Hero.cpp b/atari_py/ale_interface/src/games/supported/Hero.cpp index 1da2216..4f04693 100644 --- a/atari_py/ale_interface/src/games/supported/Hero.cpp +++ b/atari_py/ale_interface/src/games/supported/Hero.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 96, 106 and 114 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -129,3 +129,32 @@ void HeroSettings::loadState(Deserializer & ser) { m_lives = ser.getInt(); } +// returns a list of mode that the game can be played in +ModeVect HeroSettings::getAvailableModes() { + ModeVect modes(getNumModes()); + for (unsigned int i = 0; i < modes.size(); i++) { + modes[i] = i; + } + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void HeroSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + if(m < getNumModes()) { + // read the mode we are currently in + unsigned char mode = readRam(&system, 0x80); + // press select until the correct mode is reached + while (mode != m) { + environment->pressSelect(); + mode = readRam(&system, 0x80); + } + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } diff --git a/atari_py/ale_interface/src/games/supported/Hero.hpp b/atari_py/ale_interface/src/games/supported/Hero.hpp index d4a0ef8..1529bd7 100644 --- a/atari_py/ale_interface/src/games/supported/Hero.hpp +++ b/atari_py/ale_interface/src/games/supported/Hero.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 67 and 74 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class HeroSettings : public RomSettings { // the rom-name const char* rom() const { return "hero"; } + // get the available number of modes + unsigned int getNumModes() const { return 5; } + // create a new instance of the rom RomSettings* clone() const; @@ -64,7 +67,16 @@ class HeroSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + // returns a list of mode that the game can be played in + // in this game, there are 8 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); private: diff --git a/atari_py/ale_interface/src/games/supported/IceHockey.cpp b/atari_py/ale_interface/src/games/supported/IceHockey.cpp index 3cc29bd..0f6e6ef 100644 --- a/atari_py/ale_interface/src/games/supported/IceHockey.cpp +++ b/atari_py/ale_interface/src/games/supported/IceHockey.cpp @@ -115,3 +115,35 @@ void IceHockeySettings::loadState(Deserializer & ser) { m_terminal = ser.getBool(); } +// returns a list of mode that the game can be played in +ModeVect IceHockeySettings::getAvailableModes() { + ModeVect modes = {0, 2}; + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void IceHockeySettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + if(m == 0 || m == 2) { + // read the mode we are currently in + unsigned char mode = readRam(&system, 0x80); + // press select until the correct mode is reached + while (mode != m) { + environment->pressSelect(2); + mode = readRam(&system, 0x80); + } + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } + +DifficultyVect IceHockeySettings::getAvailableDifficulties() { + DifficultyVect diff = {0, 1, 2, 3}; + return diff; +} + diff --git a/atari_py/ale_interface/src/games/supported/IceHockey.hpp b/atari_py/ale_interface/src/games/supported/IceHockey.hpp index 2e2a68f..122bbe8 100644 --- a/atari_py/ale_interface/src/games/supported/IceHockey.hpp +++ b/atari_py/ale_interface/src/games/supported/IceHockey.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The line 67 is based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class IceHockeySettings : public RomSettings { // the rom-name const char* rom() const { return "ice_hockey"; } + // get the available number of modes + unsigned int getNumModes() const { return 2; } + // create a new instance of the rom RomSettings* clone() const; @@ -64,7 +67,20 @@ class IceHockeySettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return 0; } + virtual int lives() { return 0; } + + // returns a list of mode that the game can be played in + // in this game, there are 2 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); + + // returns a list of difficulties that the game can be played in + // in this game, there are 4 available difficulties + DifficultyVect getAvailableDifficulties(); private: diff --git a/atari_py/ale_interface/src/games/supported/JamesBond.cpp b/atari_py/ale_interface/src/games/supported/JamesBond.cpp index 2974aa7..1487421 100644 --- a/atari_py/ale_interface/src/games/supported/JamesBond.cpp +++ b/atari_py/ale_interface/src/games/supported/JamesBond.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 63, 64, 117, 126 and 134 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -134,3 +134,34 @@ void JamesBondSettings::loadState(Deserializer & ser) { m_lives = ser.getInt(); } + +// returns a list of mode that the game can be played in +ModeVect JamesBondSettings::getAvailableModes() { + ModeVect modes(getNumModes()); + for (unsigned int i = 0; i < modes.size(); i++) { + modes[i] = i; + } + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void JamesBondSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + if(m == 0 || m == 1) { + // read the mode we are currently in + unsigned char mode = readRam(&system, 0x8C); + // press select until the correct mode is reached + // in the welcome screen, the value of the mode is increased by 0x48 + while (mode != m && mode != m + 0x48) { + environment->pressSelect(20); + mode = readRam(&system, 0x8C); + } + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } diff --git a/atari_py/ale_interface/src/games/supported/JamesBond.hpp b/atari_py/ale_interface/src/games/supported/JamesBond.hpp index 7544ca7..f00aca0 100644 --- a/atari_py/ale_interface/src/games/supported/JamesBond.hpp +++ b/atari_py/ale_interface/src/games/supported/JamesBond.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 67 and 74 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class JamesBondSettings : public RomSettings { // the rom-name const char* rom() const { return "jamesbond"; } + // get the available number of modes + unsigned int getNumModes() const { return 2; } + // create a new instance of the rom RomSettings* clone() const; @@ -64,7 +67,16 @@ class JamesBondSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + // returns a list of mode that the game can be played in + // in this game, there are 2 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); private: diff --git a/atari_py/ale_interface/src/games/supported/JourneyEscape.cpp b/atari_py/ale_interface/src/games/supported/JourneyEscape.cpp index 2b72710..c659e79 100644 --- a/atari_py/ale_interface/src/games/supported/JourneyEscape.cpp +++ b/atari_py/ale_interface/src/games/supported/JourneyEscape.cpp @@ -1,4 +1,6 @@ /* ***************************************************************************** + * The method lives() is based on Xitari's code, from Google Inc. + * * A.L.E (Arcade Learning Environment) * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and * the Reinforcement Learning and Artificial Intelligence Laboratory @@ -116,4 +118,8 @@ ActionVect JourneyEscapeSettings::getStartingActions() { return startingActions; } +DifficultyVect JourneyEscapeSettings::getAvailableDifficulties() { + DifficultyVect diff = {0, 1}; + return diff; +} diff --git a/atari_py/ale_interface/src/games/supported/JourneyEscape.hpp b/atari_py/ale_interface/src/games/supported/JourneyEscape.hpp index 25220e2..088d39f 100644 --- a/atari_py/ale_interface/src/games/supported/JourneyEscape.hpp +++ b/atari_py/ale_interface/src/games/supported/JourneyEscape.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The line 70 is based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -67,7 +67,11 @@ class JourneyEscapeSettings : public RomSettings { // Journey Escape requires the fire action to start the game ActionVect getStartingActions(); - virtual const int lives() { return 0; } + virtual int lives() { return 0; } + + // returns a list of difficulties that the game can be played in + // in this game, there are 2 available difficulties + DifficultyVect getAvailableDifficulties(); private: diff --git a/atari_py/ale_interface/src/games/supported/Kangaroo.cpp b/atari_py/ale_interface/src/games/supported/Kangaroo.cpp index cc3f502..a2c9c18 100644 --- a/atari_py/ale_interface/src/games/supported/Kangaroo.cpp +++ b/atari_py/ale_interface/src/games/supported/Kangaroo.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 60, 113, 123 and 131 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -131,3 +131,31 @@ void KangarooSettings::loadState(Deserializer & ser) { m_lives = ser.getInt(); } +// returns a list of mode that the game can be played in +ModeVect KangarooSettings::getAvailableModes() { + ModeVect modes = {0, 1}; + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void KangarooSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + if( m == 0 || m == 1){ + // read the mode we are currently in + unsigned char mode = readRam(&system, 0xBA); + // press select until the correct mode is reached + //in the welcome screen, the value of the mode is increased by 0x80 + while(mode != m && mode != m + 0x80) { + environment->pressSelect(2); + mode = readRam(&system, 0xBA); + } + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } + diff --git a/atari_py/ale_interface/src/games/supported/Kangaroo.hpp b/atari_py/ale_interface/src/games/supported/Kangaroo.hpp index 9ee79b2..32a49dc 100644 --- a/atari_py/ale_interface/src/games/supported/Kangaroo.hpp +++ b/atari_py/ale_interface/src/games/supported/Kangaroo.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 67 and 74 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class KangarooSettings : public RomSettings { // the rom-name const char* rom() const { return "kangaroo"; } + // get the available number of modes + unsigned int getNumModes() const { return 2; } + // create a new instance of the rom RomSettings* clone() const; @@ -64,7 +67,16 @@ class KangarooSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + // returns a list of mode that the game can be played in + // in this game, there are 8 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); private: diff --git a/atari_py/ale_interface/src/games/supported/KeystoneKapers.cpp b/atari_py/ale_interface/src/games/supported/KeystoneKapers.cpp new file mode 100644 index 0000000..b5119fe --- /dev/null +++ b/atari_py/ale_interface/src/games/supported/KeystoneKapers.cpp @@ -0,0 +1,108 @@ +/* ***************************************************************************** + * A.L.E (Arcade Learning Environment) + * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and + * the Reinforcement Learning and Artificial Intelligence Laboratory + * Released under the GNU General Public License; see License.txt for details. + * + * Based on: Stella -- "An Atari 2600 VCS Emulator" + * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team + * + * ***************************************************************************** + */ +#include "KeystoneKapers.hpp" + +#include "../RomUtils.hpp" + + +KeystoneKapersSettings::KeystoneKapersSettings() { + reset(); +} + + +/* create a new instance of the rom */ +RomSettings* KeystoneKapersSettings::clone() const { + RomSettings* rval = new KeystoneKapersSettings(); + *rval = *this; + return rval; +} + + +/* process the latest information from ALE */ +void KeystoneKapersSettings::step(const System& system) { + // update the reward + int score = getDecimalScore(0x9C, 0x9B, &system); + int reward = score - m_score; + m_reward = reward; + m_score = score; + + m_lives = readRam(&system, 0x96); + m_terminal = (m_lives == 0) && readRam(&system, 0x88) == 0x00; +} + + +/* is end of game */ +bool KeystoneKapersSettings::isTerminal() const { + return m_terminal; +}; + + +/* get the most recently observed reward */ +reward_t KeystoneKapersSettings::getReward() const { + return m_reward; +} + + +/* is an action part of the minimal set? */ +bool KeystoneKapersSettings::isMinimal(const Action &a) const { + switch (a) { + case PLAYER_A_NOOP: + case PLAYER_A_FIRE: + case PLAYER_A_UP: + case PLAYER_A_RIGHT: + case PLAYER_A_LEFT: + case PLAYER_A_DOWN: + case PLAYER_A_UPRIGHT: + case PLAYER_A_UPLEFT: + case PLAYER_A_DOWNRIGHT: + case PLAYER_A_DOWNLEFT: + case PLAYER_A_UPFIRE: + case PLAYER_A_RIGHTFIRE: + case PLAYER_A_LEFTFIRE: + case PLAYER_A_DOWNFIRE: + return true; + default: + return false; + } +} + + +/* reset the state of the game */ +void KeystoneKapersSettings::reset() { + m_reward = 0; + m_score = 0; + m_terminal = false; + m_lives = 3; +} + +/* saves the state of the rom settings */ +void KeystoneKapersSettings::saveState(Serializer & ser) { + ser.putInt(m_reward); + ser.putInt(m_score); + ser.putBool(m_terminal); + ser.putInt(m_lives); +} + +// loads the state of the rom settings +void KeystoneKapersSettings::loadState(Deserializer & ser) { + m_reward = ser.getInt(); + m_score = ser.getInt(); + m_terminal = ser.getBool(); + m_lives = ser.getInt(); +} + +ActionVect KeystoneKapersSettings::getStartingActions() { + ActionVect startingActions; + startingActions.push_back(RESET); + return startingActions; +} + diff --git a/atari_py/ale_interface/src/games/supported/KeystoneKapers.hpp b/atari_py/ale_interface/src/games/supported/KeystoneKapers.hpp new file mode 100644 index 0000000..4385ba4 --- /dev/null +++ b/atari_py/ale_interface/src/games/supported/KeystoneKapers.hpp @@ -0,0 +1,65 @@ +/* ***************************************************************************** + * A.L.E (Arcade Learning Environment) + * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and + * the Reinforcement Learning and Artificial Intelligence Laboratory + * Released under the GNU General Public License; see License.txt for details. + * + * Based on: Stella -- "An Atari 2600 VCS Emulator" + * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team + * + * ***************************************************************************** + */ +#ifndef __KEYSTONEKAPERS_HPP__ +#define __KEYSTONEKAPERS_HPP__ + +#include "../RomSettings.hpp" + + +/* RL wrapper for KeystoneKapers */ +class KeystoneKapersSettings : public RomSettings { + + public: + KeystoneKapersSettings(); + + // reset + void reset(); + + // is end of game + bool isTerminal() const; + + // get the most recently observed reward + reward_t getReward() const; + + // the rom-name + // MD5 be929419902e21bd7830a7a7d746195d + const char* rom() const { return "keystone_kapers"; } + + // create a new instance of the rom + RomSettings* clone() const; + + // is an action part of the minimal set? + bool isMinimal(const Action& a) const; + + // process the latest information from ALE + void step(const System& system); + + // saves the state of the rom settings + void saveState(Serializer & ser); + + // loads the state of the rom settings + void loadState(Deserializer & ser); + + // Keystone Kapers requires the reset button to start the game + ActionVect getStartingActions(); + + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + private: + bool m_terminal; + reward_t m_reward; + reward_t m_score; + int m_lives; +}; + +#endif // __KEYSTONEKAPERS_HPP__ + diff --git a/atari_py/ale_interface/src/games/supported/Kingkong.cpp b/atari_py/ale_interface/src/games/supported/Kingkong.cpp new file mode 100644 index 0000000..30e0b01 --- /dev/null +++ b/atari_py/ale_interface/src/games/supported/Kingkong.cpp @@ -0,0 +1,113 @@ +/* ***************************************************************************** + * The lines 61, 102, 110 and 118 are based on Xitari's code, from Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * ***************************************************************************** + * A.L.E (Arcade Learning Environment) + * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and + * the Reinforcement Learning and Artificial Intelligence Laboratory + * Released under the GNU General Public License; see License.txt for details. + * + * Based on: Stella -- "An Atari 2600 VCS Emulator" + * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team + * + * ***************************************************************************** + */ +#include "Kingkong.hpp" + +#include "../RomUtils.hpp" + +KingkongSettings::KingkongSettings() { + reset(); +} + +/* create a new instance of the rom */ +RomSettings* KingkongSettings::clone() const { + RomSettings* rval = new KingkongSettings(); + *rval = *this; + return rval; +} + +/* process the latest information from ALE */ +void KingkongSettings::step(const System& system) { + // update the reward + int score = getDecimalScore(0x83, 0x82, &system); + int reward = score - m_score; + m_reward = reward; + m_score = score; + + // update terminal status + m_lives = readRam(&system, 0xEE); + m_terminal = (m_lives == 0); +} + +/* is end of game */ +bool KingkongSettings::isTerminal() const { + return m_terminal; +}; + + +/* get the most recently observed reward */ +reward_t KingkongSettings::getReward() const { + return m_reward; +} + + +/* is an action part of the minimal set? */ +bool KingkongSettings::isMinimal(const Action &a) const { + switch (a) { + case PLAYER_A_NOOP: + case PLAYER_A_FIRE: + case PLAYER_A_UP: + case PLAYER_A_RIGHT: + case PLAYER_A_LEFT: + case PLAYER_A_DOWN: + return true; + default: + return false; + } +} + + +/* reset the state of the game */ +void KingkongSettings::reset() { + m_reward = 0; + m_score = 0; + m_terminal = false; + m_lives = 3; +} + +/* saves the state of the rom settings */ +void KingkongSettings::saveState(Serializer & ser) { + ser.putInt(m_reward); + ser.putInt(m_score); + ser.putBool(m_terminal); + ser.putInt(m_lives); +} + +// loads the state of the rom settings +void KingkongSettings::loadState(Deserializer & ser) { + m_reward = ser.getInt(); + m_score = ser.getInt(); + m_terminal = ser.getBool(); + m_lives = ser.getInt(); +} + +ActionVect KingkongSettings::getStartingActions() { + ActionVect startingActions; + startingActions.push_back(RESET); + return startingActions; +} + + diff --git a/atari_py/ale_interface/src/games/supported/Kingkong.hpp b/atari_py/ale_interface/src/games/supported/Kingkong.hpp new file mode 100644 index 0000000..8462b5f --- /dev/null +++ b/atari_py/ale_interface/src/games/supported/Kingkong.hpp @@ -0,0 +1,77 @@ +/* ***************************************************************************** + * The lines 70 and 77 are based on Xitari's code, from Google Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * ***************************************************************************** + * A.L.E (Arcade Learning Environment) + * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and + * the Reinforcement Learning and Artificial Intelligence Laboratory + * Released under the GNU General Public License; see License.txt for details. + * + * Based on: Stella -- "An Atari 2600 VCS Emulator" + * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team + * + * ***************************************************************************** + */ +#ifndef __KINGKONG_HPP__ +#define __KINGKONG_HPP__ + +#include "../RomSettings.hpp" + +/* RL wrapper for Kingkong */ +class KingkongSettings : public RomSettings { + public: + KingkongSettings(); + + // reset + void reset(); + + // is end of game + bool isTerminal() const; + + // get the most recently observed reward + reward_t getReward() const; + + // the rom-name + const char* rom() const { return "king_kong"; } + + // create a new instance of the rom + RomSettings* clone() const; + + // is an action part of the minimal set? + bool isMinimal(const Action& a) const; + + // process the latest information from ALE + void step(const System& system); + + // saves the state of the rom settings + void saveState(Serializer & ser); + + // loads the state of the rom settings + void loadState(Deserializer & ser); + + // Kingkong requires the fire action to start the game + ActionVect getStartingActions(); + + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + private: + bool m_terminal; + reward_t m_reward; + reward_t m_score; + int m_lives; +}; + +#endif // __KINGKONG_HPP__ + diff --git a/atari_py/ale_interface/src/games/supported/Koolaid.cpp b/atari_py/ale_interface/src/games/supported/Koolaid.cpp new file mode 100644 index 0000000..9b118c0 --- /dev/null +++ b/atari_py/ale_interface/src/games/supported/Koolaid.cpp @@ -0,0 +1,101 @@ +/* ***************************************************************************** + * A.L.E (Arcade Learning Environment) + * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and + * the Reinforcement Learning and Artificial Intelligence Laboratory + * Released under the GNU General Public License; see License.txt for details. + * + * Based on: Stella -- "An Atari 2600 VCS Emulator" + * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team + * + * ***************************************************************************** + */ +#include "Koolaid.hpp" + +#include "../RomUtils.hpp" + + +KoolaidSettings::KoolaidSettings() { + + reset(); +} + + +/* create a new instance of the rom */ +RomSettings* KoolaidSettings::clone() const { + + RomSettings* rval = new KoolaidSettings(); + *rval = *this; + return rval; +} + + +/* process the latest information from ALE */ +void KoolaidSettings::step(const System& system) { + + // update the reward + int score = getDecimalScore(0x81, 0x80, &system); + score *= 100; + int reward = score - m_score; + m_reward = reward; + m_score = score; + + m_terminal = readRam(&system, 0xD1) == 0x80; +} + + +/* is end of game */ +bool KoolaidSettings::isTerminal() const { + + return m_terminal; +}; + + +/* get the most recently observed reward */ +reward_t KoolaidSettings::getReward() const { + + return m_reward; +} + + +/* is an action part of the minimal set? */ +bool KoolaidSettings::isMinimal(const Action &a) const { + + switch (a) { + case PLAYER_A_NOOP: + case PLAYER_A_UP: + case PLAYER_A_RIGHT: + case PLAYER_A_LEFT: + case PLAYER_A_DOWN: + case PLAYER_A_UPRIGHT: + case PLAYER_A_UPLEFT: + case PLAYER_A_DOWNRIGHT: + case PLAYER_A_DOWNLEFT: + return true; + default: + return false; + } +} + + +/* reset the state of the game */ +void KoolaidSettings::reset() { + + m_reward = 0; + m_score = 0; + m_terminal = false; +} + +/* saves the state of the rom settings */ +void KoolaidSettings::saveState(Serializer & ser) { + ser.putInt(m_reward); + ser.putInt(m_score); + ser.putBool(m_terminal); +} + +// loads the state of the rom settings +void KoolaidSettings::loadState(Deserializer & ser) { + m_reward = ser.getInt(); + m_score = ser.getInt(); + m_terminal = ser.getBool(); +} + diff --git a/atari_py/ale_interface/src/games/supported/Koolaid.hpp b/atari_py/ale_interface/src/games/supported/Koolaid.hpp new file mode 100644 index 0000000..f6377a1 --- /dev/null +++ b/atari_py/ale_interface/src/games/supported/Koolaid.hpp @@ -0,0 +1,63 @@ +/* ***************************************************************************** + * A.L.E (Arcade Learning Environment) + * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and + * the Reinforcement Learning and Artificial Intelligence Laboratory + * Released under the GNU General Public License; see License.txt for details. + * + * Based on: Stella -- "An Atari 2600 VCS Emulator" + * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team + * + * ***************************************************************************** + */ +#ifndef __KOOLAID_HPP__ +#define __KOOLAID_HPP__ + +#include "../RomSettings.hpp" + + +/* RL wrapper for Koolaid */ +class KoolaidSettings : public RomSettings { + + public: + + KoolaidSettings(); + + // reset + void reset(); + + // is end of game + bool isTerminal() const; + + // get the most recently observed reward + reward_t getReward() const; + + // the rom-name + const char* rom() const { return "koolaid"; } + + // create a new instance of the rom + RomSettings* clone() const; + + // is an action part of the minimal set? + bool isMinimal(const Action& a) const; + + // process the latest information from ALE + void step(const System& system); + + // saves the state of the rom settings + void saveState(Serializer & ser); + + // loads the state of the rom settings + void loadState(Deserializer & ser); + + virtual int lives() { return 0; } + + private: + + bool m_terminal; + reward_t m_reward; + reward_t m_score; +}; + +#endif // __KOOLAID_HPP__ + + diff --git a/atari_py/ale_interface/src/games/supported/Krull.hpp b/atari_py/ale_interface/src/games/supported/Krull.hpp index 12da53a..7af6a4c 100644 --- a/atari_py/ale_interface/src/games/supported/Krull.hpp +++ b/atari_py/ale_interface/src/games/supported/Krull.hpp @@ -64,7 +64,7 @@ class KrullSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } private: diff --git a/atari_py/ale_interface/src/games/supported/KungFuMaster.hpp b/atari_py/ale_interface/src/games/supported/KungFuMaster.hpp index e6f7bdf..e8c42ea 100644 --- a/atari_py/ale_interface/src/games/supported/KungFuMaster.hpp +++ b/atari_py/ale_interface/src/games/supported/KungFuMaster.hpp @@ -64,7 +64,7 @@ class KungFuMasterSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } private: diff --git a/atari_py/ale_interface/src/games/supported/LaserGates.cpp b/atari_py/ale_interface/src/games/supported/LaserGates.cpp new file mode 100644 index 0000000..bcbaf8c --- /dev/null +++ b/atari_py/ale_interface/src/games/supported/LaserGates.cpp @@ -0,0 +1,109 @@ +/* ***************************************************************************** + * A.L.E (Arcade Learning Environment) + * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and + * the Reinforcement Learning and Artificial Intelligence Laboratory + * Released under the GNU General Public License; see License.txt for details. + * + * Based on: Stella -- "An Atari 2600 VCS Emulator" + * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team + * + * ***************************************************************************** + */ +#include "LaserGates.hpp" + +#include "../RomUtils.hpp" + +LaserGatesSettings::LaserGatesSettings() { + reset(); +} + + +/* create a new instance of the rom */ +RomSettings* LaserGatesSettings::clone() const { + RomSettings* rval = new LaserGatesSettings(); + *rval = *this; + return rval; +} + + +/* process the latest information from ALE */ +void LaserGatesSettings::step(const System& system) { + // update the reward + int score = getDecimalScore(0x82, 0x81, 0x80, &system); + int reward = score - m_score; + m_reward = reward; + m_score = score; + + // update terminal status + m_terminal = readRam(&system, 0x83) == 0x00; +} + + +/* is end of game */ +bool LaserGatesSettings::isTerminal() const { + return m_terminal; +}; + + +/* get the most recently observed reward */ +reward_t LaserGatesSettings::getReward() const { + return m_reward; +} + + +/* is an action part of the minimal set? */ +bool LaserGatesSettings::isMinimal(const Action &a) const { + switch (a) { + case PLAYER_A_NOOP: + case PLAYER_A_FIRE: + case PLAYER_A_UP: + case PLAYER_A_RIGHT: + case PLAYER_A_LEFT: + case PLAYER_A_DOWN: + case PLAYER_A_UPRIGHT: + case PLAYER_A_UPLEFT: + case PLAYER_A_DOWNRIGHT: + case PLAYER_A_DOWNLEFT: + case PLAYER_A_UPFIRE: + case PLAYER_A_RIGHTFIRE: + case PLAYER_A_LEFTFIRE: + case PLAYER_A_DOWNFIRE: + case PLAYER_A_UPRIGHTFIRE: + case PLAYER_A_UPLEFTFIRE: + case PLAYER_A_DOWNRIGHTFIRE: + case PLAYER_A_DOWNLEFTFIRE: + return true; + default: + return false; + } +} + + +/* reset the state of the game */ +void LaserGatesSettings::reset() { + m_reward = 0; + m_score = 0; + m_terminal = false; +} + +/* saves the state of the rom settings */ +void LaserGatesSettings::saveState(Serializer & ser) { + ser.putInt(m_reward); + ser.putInt(m_score); + ser.putBool(m_terminal); +} + +// loads the state of the rom settings +void LaserGatesSettings::loadState(Deserializer & ser) { + m_reward = ser.getInt(); + m_score = ser.getInt(); + m_terminal = ser.getBool(); +} + +ActionVect LaserGatesSettings::getStartingActions() { + ActionVect startingActions; + startingActions.push_back(RESET); + return startingActions; +} + + diff --git a/atari_py/ale_interface/src/games/supported/LaserGates.hpp b/atari_py/ale_interface/src/games/supported/LaserGates.hpp new file mode 100644 index 0000000..b597342 --- /dev/null +++ b/atari_py/ale_interface/src/games/supported/LaserGates.hpp @@ -0,0 +1,63 @@ +/* ***************************************************************************** + * A.L.E (Arcade Learning Environment) + * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and + * the Reinforcement Learning and Artificial Intelligence Laboratory + * Released under the GNU General Public License; see License.txt for details. + * + * Based on: Stella -- "An Atari 2600 VCS Emulator" + * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team + * + * ***************************************************************************** + */ +#ifndef __LASERGATES_HPP__ +#define __LASERGATES_HPP__ + +#include "../RomSettings.hpp" + + +/* RL wrapper for Laser Gates */ +class LaserGatesSettings : public RomSettings { + public: + LaserGatesSettings(); + + // reset + void reset(); + + // is end of game + bool isTerminal() const; + + // get the most recently observed reward + reward_t getReward() const; + + // the rom-name + // MD5 1fa58679d4a39052bd9db059e8cda4ad + const char* rom() const { return "laser_gates"; } + + // create a new instance of the rom + RomSettings* clone() const; + + // is an action part of the minimal set? + bool isMinimal(const Action& a) const; + + // process the latest information from ALE + void step(const System& system); + + // saves the state of the rom settings + void saveState(Serializer & ser); + + // loads the state of the rom settings + void loadState(Deserializer & ser); + + // LaserGates requires the fire action to start the game + ActionVect getStartingActions(); + + virtual int lives() { return 0; } + + private: + bool m_terminal; + reward_t m_reward; + reward_t m_score; +}; + +#endif // __LASERGATES_HPP__ + diff --git a/atari_py/ale_interface/src/games/supported/LostLuggage.cpp b/atari_py/ale_interface/src/games/supported/LostLuggage.cpp new file mode 100644 index 0000000..bcff928 --- /dev/null +++ b/atari_py/ale_interface/src/games/supported/LostLuggage.cpp @@ -0,0 +1,120 @@ +/* ***************************************************************************** + * A.L.E (Arcade Learning Environment) + * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and + * the Reinforcement Learning and Artificial Intelligence Laboratory + * Released under the GNU General Public License; see License.txt for details. + * + * Based on: Stella -- "An Atari 2600 VCS Emulator" + * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team + * + * ***************************************************************************** + */ +#include "LostLuggage.hpp" + +#include "../RomUtils.hpp" + +LostLuggageSettings::LostLuggageSettings() { + reset(); +} + +/* create a new instance of the rom */ +RomSettings* LostLuggageSettings::clone() const { + RomSettings* rval = new LostLuggageSettings(); + *rval = *this; + return rval; +} + +/* process the latest information from ALE */ +void LostLuggageSettings::step(const System& system) { + // update the reward + int score = getDecimalScore(0x96, 0x95, 0x94, &system); + int reward = score - m_score; + m_reward = reward; + m_score = score; + + // update terminal status + m_lives = readRam(&system, 0xCA); + m_terminal = (m_lives == 0) + && readRam(&system, 0xC8) == 0x0A + && readRam(&system, 0xA5) == 0x00 + && readRam(&system, 0xA9) == 0x00; +} + +/* is end of game */ +bool LostLuggageSettings::isTerminal() const { + return m_terminal; +}; + + +/* get the most recently observed reward */ +reward_t LostLuggageSettings::getReward() const { + return m_reward; +} + + +/* is an action part of the minimal set? */ +bool LostLuggageSettings::isMinimal(const Action &a) const { + switch (a) { + case PLAYER_A_NOOP: + case PLAYER_A_UP: + case PLAYER_A_RIGHT: + case PLAYER_A_LEFT: + case PLAYER_A_DOWN: + case PLAYER_A_UPRIGHT: + case PLAYER_A_UPLEFT: + case PLAYER_A_DOWNRIGHT: + case PLAYER_A_DOWNLEFT: + return true; + default: + return false; + } +} + +bool LostLuggageSettings::isLegal(const Action &a) const { + switch (a) { + // Don't allow pressing 'fire' + case PLAYER_A_FIRE: + case PLAYER_A_UPFIRE: + case PLAYER_A_DOWNFIRE: + case PLAYER_A_LEFTFIRE: + case PLAYER_A_RIGHTFIRE: + case PLAYER_A_UPLEFTFIRE: + case PLAYER_A_UPRIGHTFIRE: + case PLAYER_A_DOWNLEFTFIRE: + case PLAYER_A_DOWNRIGHTFIRE: + return false; + default: + return true; + } +} + +/* reset the state of the game */ +void LostLuggageSettings::reset() { + m_reward = 0; + m_score = 0; + m_terminal = false; + m_lives = 3; +} + +/* saves the state of the rom settings */ +void LostLuggageSettings::saveState(Serializer & ser) { + ser.putInt(m_reward); + ser.putInt(m_score); + ser.putBool(m_terminal); + ser.putInt(m_lives); +} + +// loads the state of the rom settings +void LostLuggageSettings::loadState(Deserializer & ser) { + m_reward = ser.getInt(); + m_score = ser.getInt(); + m_terminal = ser.getBool(); + m_lives = ser.getInt(); +} + +ActionVect LostLuggageSettings::getStartingActions() { + ActionVect startingActions; + startingActions.push_back(RESET); + return startingActions; +} + diff --git a/atari_py/ale_interface/src/games/supported/LostLuggage.hpp b/atari_py/ale_interface/src/games/supported/LostLuggage.hpp new file mode 100644 index 0000000..f1ed845 --- /dev/null +++ b/atari_py/ale_interface/src/games/supported/LostLuggage.hpp @@ -0,0 +1,66 @@ +/* ***************************************************************************** + * A.L.E (Arcade Learning Environment) + * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and + * the Reinforcement Learning and Artificial Intelligence Laboratory + * Released under the GNU General Public License; see License.txt for details. + * + * Based on: Stella -- "An Atari 2600 VCS Emulator" + * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team + * + * ***************************************************************************** + */ +#ifndef __LOSTLUGGAGE_HPP__ +#define __LOSTLUGGAGE_HPP__ + +#include "../RomSettings.hpp" + +/* RL wrapper for Lost Luggage */ +class LostLuggageSettings : public RomSettings { + public: + LostLuggageSettings(); + + // reset + void reset(); + + // is end of game + bool isTerminal() const; + + // get the most recently observed reward + reward_t getReward() const; + + // the rom-name + // MD5 7c00e7a205d3fda98eb20da7c9c50a55 + const char* rom() const { return "lost_luggage"; } + + // create a new instance of the rom + RomSettings* clone() const; + + // is an action part of the minimal set? + bool isMinimal(const Action& a) const; + + // FIRE resets the game, prevent this + bool isLegal(const Action& a) const; + + // process the latest information from ALE + void step(const System& system); + + // saves the state of the rom settings + void saveState(Serializer & ser); + + // loads the state of the rom settings + void loadState(Deserializer & ser); + + // LostLuggage requires the fire action to start the game + ActionVect getStartingActions(); + + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + private: + bool m_terminal; + reward_t m_reward; + reward_t m_score; + int m_lives; +}; + +#endif // __LOSTLUGGAGE_HPP__ + diff --git a/atari_py/ale_interface/src/games/supported/MontezumaRevenge.hpp b/atari_py/ale_interface/src/games/supported/MontezumaRevenge.hpp index 4c54224..7c7c271 100644 --- a/atari_py/ale_interface/src/games/supported/MontezumaRevenge.hpp +++ b/atari_py/ale_interface/src/games/supported/MontezumaRevenge.hpp @@ -64,7 +64,7 @@ class MontezumaRevengeSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } private: diff --git a/atari_py/ale_interface/src/games/supported/MrDo.cpp b/atari_py/ale_interface/src/games/supported/MrDo.cpp new file mode 100644 index 0000000..5fc32e4 --- /dev/null +++ b/atari_py/ale_interface/src/games/supported/MrDo.cpp @@ -0,0 +1,111 @@ +/* ***************************************************************************** + * A.L.E (Arcade Learning Environment) + * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and + * the Reinforcement Learning and Artificial Intelligence Laboratory + * Released under the GNU General Public License; see License.txt for details. + * + * Based on: Stella -- "An Atari 2600 VCS Emulator" + * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team + * + * ***************************************************************************** + */ +#include "MrDo.hpp" + +#include "../RomUtils.hpp" + + +MrDoSettings::MrDoSettings() { + + reset(); +} + + +/* create a new instance of the rom */ +RomSettings* MrDoSettings::clone() const { + + RomSettings* rval = new MrDoSettings(); + *rval = *this; + return rval; +} + + +/* process the latest information from ALE */ +void MrDoSettings::step(const System& system) { + + // update the reward + int score = getDecimalScore(0x82, 0x83, &system); + score *= 10; + int reward = score - m_score; + m_reward = reward; + m_score = score; + + // update terminal status + m_lives = readRam(&system, 0xDB); + m_terminal = readRam(&system, 0xDA) == 0x40; +} + + +/* is end of game */ +bool MrDoSettings::isTerminal() const { + return m_terminal; +}; + + +/* get the most recently observed reward */ +reward_t MrDoSettings::getReward() const { + return m_reward; +} + + +/* is an action part of the minimal set? */ +bool MrDoSettings::isMinimal(const Action &a) const { + + switch (a) { + case PLAYER_A_NOOP: + case PLAYER_A_FIRE: + case PLAYER_A_UP: + case PLAYER_A_RIGHT: + case PLAYER_A_LEFT: + case PLAYER_A_DOWN: + case PLAYER_A_UPFIRE: + case PLAYER_A_RIGHTFIRE: + case PLAYER_A_LEFTFIRE: + case PLAYER_A_DOWNFIRE: + return true; + default: + return false; + } +} + + +/* reset the state of the game */ +void MrDoSettings::reset() { + + m_reward = 0; + m_score = 0; + m_terminal = false; + m_lives = 4; +} + +/* saves the state of the rom settings */ +void MrDoSettings::saveState(Serializer & ser) { + ser.putInt(m_reward); + ser.putInt(m_score); + ser.putBool(m_terminal); + ser.putInt(m_lives); +} + +// loads the state of the rom settings +void MrDoSettings::loadState(Deserializer & ser) { + m_reward = ser.getInt(); + m_score = ser.getInt(); + m_terminal = ser.getBool(); + m_lives = ser.getInt(); +} + +ActionVect MrDoSettings::getStartingActions() { + ActionVect startingActions; + startingActions.push_back(PLAYER_A_FIRE); + return startingActions; +} + diff --git a/atari_py/ale_interface/src/games/supported/MrDo.hpp b/atari_py/ale_interface/src/games/supported/MrDo.hpp new file mode 100644 index 0000000..01614b8 --- /dev/null +++ b/atari_py/ale_interface/src/games/supported/MrDo.hpp @@ -0,0 +1,66 @@ +/* ***************************************************************************** + * A.L.E (Arcade Learning Environment) + * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and + * the Reinforcement Learning and Artificial Intelligence Laboratory + * Released under the GNU General Public License; see License.txt for details. + * + * Based on: Stella -- "An Atari 2600 VCS Emulator" + * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team + * + * ***************************************************************************** + */ +#ifndef __MRDO_HPP__ +#define __MRDO_HPP__ + +#include "../RomSettings.hpp" + + +/* RL wrapper for MrDo */ +class MrDoSettings : public RomSettings { + + public: + + MrDoSettings(); + + // reset + void reset(); + + // is end of game + bool isTerminal() const; + + // get the most recently observed reward + reward_t getReward() const; + + // the rom-name + const char* rom() const { return "mr_do"; } + + // create a new instance of the rom + RomSettings* clone() const; + + // is an action part of the minimal set? + bool isMinimal(const Action& a) const; + + // process the latest information from ALE + void step(const System& system); + + // saves the state of the rom settings + void saveState(Serializer & ser); + + // loads the state of the rom settings + void loadState(Deserializer & ser); + + // Mr. Do requires the fire action to start the game + ActionVect getStartingActions(); + + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + private: + + bool m_terminal; + reward_t m_reward; + reward_t m_score; + int m_lives; +}; + +#endif // __MRDO_HPP__ + diff --git a/atari_py/ale_interface/src/games/supported/MsPacman.cpp b/atari_py/ale_interface/src/games/supported/MsPacman.cpp index 2ae0456..4b77499 100644 --- a/atari_py/ale_interface/src/games/supported/MsPacman.cpp +++ b/atari_py/ale_interface/src/games/supported/MsPacman.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 62, 106, 116 and 124 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -124,3 +124,50 @@ void MsPacmanSettings::loadState(Deserializer & ser) { m_lives = ser.getInt(); } +// returns a list of mode that the game can be played in +ModeVect MsPacmanSettings::getAvailableModes() { + ModeVect modes(getNumModes()); + for (unsigned int i = 0; i < modes.size(); i++) { + modes[i] = i; + } + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void MsPacmanSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + if(m < getNumModes()) { + if(m == 0) { //this is the standard variation of the game + // read the mode we are currently in + unsigned char mode = readRam(&system, 0x99); + // read the variation + unsigned char var = readRam(&system, 0xA1); + // press select until the correct mode is reached + while(mode != 1 || var != 1) { + // hold select button for 10 frames + environment->pressSelect(10); + mode = readRam(&system, 0x99); + var = readRam(&system, 0xA1); + } + } else { + // read the mode we are currently in + unsigned char mode = readRam(&system, 0x99); + // read the variation + unsigned char var = readRam(&system, 0xA1); + // press select until the correct mode is reached + while(mode != m || var != 0) { + // hold select button for 10 frames + environment->pressSelect(10); + mode = readRam(&system, 0x99); + var = readRam(&system, 0xA1); + } + } + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } diff --git a/atari_py/ale_interface/src/games/supported/MsPacman.hpp b/atari_py/ale_interface/src/games/supported/MsPacman.hpp index 655c873..93cf67c 100644 --- a/atari_py/ale_interface/src/games/supported/MsPacman.hpp +++ b/atari_py/ale_interface/src/games/supported/MsPacman.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 67 and 74 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class MsPacmanSettings : public RomSettings { // the rom-name const char* rom() const { return "ms_pacman"; } + // get the available number of modes + unsigned int getNumModes() const { return 4; } + // create a new instance of the rom RomSettings* clone() const; @@ -64,7 +67,16 @@ class MsPacmanSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + // returns a list of mode that the game can be played in + // in this game, there are 8 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); private: diff --git a/atari_py/ale_interface/src/games/supported/NameThisGame.cpp b/atari_py/ale_interface/src/games/supported/NameThisGame.cpp index 0da879c..88d6a1f 100644 --- a/atari_py/ale_interface/src/games/supported/NameThisGame.cpp +++ b/atari_py/ale_interface/src/games/supported/NameThisGame.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 57, 99, 107 and 115 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -115,3 +115,38 @@ void NameThisGameSettings::loadState(Deserializer & ser) { m_lives = ser.getInt(); } +// returns a list of mode that the game can be played in +ModeVect NameThisGameSettings::getAvailableModes() { + ModeVect modes = {0x08, 0x18, 0x28}; + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void NameThisGameSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + if(m == 0) { + m = 0x08; // the default mode is not valid here + } + if(m == 0x08 || m == 0x18 || m == 0x28) { + // read the mode we are currently in + unsigned char mode = readRam(&system, 0xDE); + // press select until the correct mode is reached + while (mode != m) { + environment->pressSelect(2); + mode = readRam(&system, 0xDE); + } + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } + +DifficultyVect NameThisGameSettings::getAvailableDifficulties() { + DifficultyVect diff = {0, 1}; + return diff; +} + diff --git a/atari_py/ale_interface/src/games/supported/NameThisGame.hpp b/atari_py/ale_interface/src/games/supported/NameThisGame.hpp index d5f2a1c..7342eef 100644 --- a/atari_py/ale_interface/src/games/supported/NameThisGame.hpp +++ b/atari_py/ale_interface/src/games/supported/NameThisGame.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 67 and 74 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class NameThisGameSettings : public RomSettings { // the rom-name const char* rom() const { return "name_this_game"; } + // get the available number of modes + unsigned int getNumModes() const { return 3; } + // create a new instance of the rom RomSettings* clone() const; @@ -64,7 +67,20 @@ class NameThisGameSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + // returns a list of mode that the game can be played in + // in this game, there are 3 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); + + // returns a list of difficulties that the game can be played in + // in this game, there are 2 available difficulties + DifficultyVect getAvailableDifficulties(); private: diff --git a/atari_py/ale_interface/src/games/supported/Phoenix.hpp b/atari_py/ale_interface/src/games/supported/Phoenix.hpp index 0253040..a5abc3a 100644 --- a/atari_py/ale_interface/src/games/supported/Phoenix.hpp +++ b/atari_py/ale_interface/src/games/supported/Phoenix.hpp @@ -64,7 +64,7 @@ class PhoenixSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } private: diff --git a/atari_py/ale_interface/src/games/supported/Pitfall.hpp b/atari_py/ale_interface/src/games/supported/Pitfall.hpp index 4b21131..8e5e88d 100644 --- a/atari_py/ale_interface/src/games/supported/Pitfall.hpp +++ b/atari_py/ale_interface/src/games/supported/Pitfall.hpp @@ -66,7 +66,7 @@ class PitfallSettings : public RomSettings { ActionVect getStartingActions(); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } private: diff --git a/atari_py/ale_interface/src/games/supported/Pong.cpp b/atari_py/ale_interface/src/games/supported/Pong.cpp index 3518cd4..b39526a 100644 --- a/atari_py/ale_interface/src/games/supported/Pong.cpp +++ b/atari_py/ale_interface/src/games/supported/Pong.cpp @@ -99,3 +99,38 @@ void PongSettings::loadState(Deserializer & ser) { m_terminal = ser.getBool(); } +// returns a list of mode that the game can be played in +ModeVect PongSettings::getAvailableModes() { + ModeVect modes(getNumModes()); + for (unsigned int i = 0; i < modes.size(); i++) { + modes[i] = i; + } + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void PongSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + if(m < getNumModes()) { + // read the mode we are currently in + unsigned char mode = readRam(&system, 0x96); + // press select until the correct mode is reached + while (mode != m) { + environment->pressSelect(2); + mode = readRam(&system, 0x96); + } + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } + +DifficultyVect PongSettings::getAvailableDifficulties() { + DifficultyVect diff = {0, 1}; + return diff; +} + diff --git a/atari_py/ale_interface/src/games/supported/Pong.hpp b/atari_py/ale_interface/src/games/supported/Pong.hpp index 94c9e97..5ea0ffd 100644 --- a/atari_py/ale_interface/src/games/supported/Pong.hpp +++ b/atari_py/ale_interface/src/games/supported/Pong.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The line 67 is based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class PongSettings : public RomSettings { // the rom-name const char* rom() const { return "pong"; } + // get the available number of modes + unsigned int getNumModes() const { return 2; } + // create a new instance of the rom RomSettings* clone() const; @@ -64,7 +67,20 @@ class PongSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return 0; } + virtual int lives() { return 0; } + + // returns a list of difficulties that the game can be played in + // in this game, there are 2 available difficulties + DifficultyVect getAvailableDifficulties(); + + // returns a list of mode that the game can be played in + // in this game, there are 2 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); private: diff --git a/atari_py/ale_interface/src/games/supported/Pooyan.cpp b/atari_py/ale_interface/src/games/supported/Pooyan.cpp index 39ce834..f3c628e 100644 --- a/atari_py/ale_interface/src/games/supported/Pooyan.cpp +++ b/atari_py/ale_interface/src/games/supported/Pooyan.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 61, 102, 110 and 118 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -118,3 +118,35 @@ void PooyanSettings::loadState(Deserializer & ser) { m_lives = ser.getInt(); } +// returns a list of mode that the game can be played in +ModeVect PooyanSettings::getAvailableModes() { + ModeVect modes = {0x0A, 0x1E, 0x32, 0x46}; + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void PooyanSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + + if (m == 0) { + m = 0x0A; // The default mode (0) is not valid here. + } + if(m == 0x0A || m == 0x1E || m == 0x32 || m == 0x46) { + environment->pressSelect(2); + // read the mode we are currently in + unsigned char mode = readRam(&system, 0xBD); + // press select until the correct mode is reached + while (mode != m) { + environment->pressSelect(2); + mode = readRam(&system, 0xBD); + } + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } + diff --git a/atari_py/ale_interface/src/games/supported/Pooyan.hpp b/atari_py/ale_interface/src/games/supported/Pooyan.hpp index 6a192af..0ff8a02 100644 --- a/atari_py/ale_interface/src/games/supported/Pooyan.hpp +++ b/atari_py/ale_interface/src/games/supported/Pooyan.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 67 and 74 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class PooyanSettings : public RomSettings { // the rom-name const char* rom() const { return "pooyan"; } + // get the available number of modes + unsigned int getNumModes() const { return 4; } + // create a new instance of the rom RomSettings* clone() const; @@ -64,7 +67,16 @@ class PooyanSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + // returns a list of mode that the game can be played in + // in this game, there are 4 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); private: diff --git a/atari_py/ale_interface/src/games/supported/PrivateEye.cpp b/atari_py/ale_interface/src/games/supported/PrivateEye.cpp index e38ab8c..d245647 100644 --- a/atari_py/ale_interface/src/games/supported/PrivateEye.cpp +++ b/atari_py/ale_interface/src/games/supported/PrivateEye.cpp @@ -115,3 +115,40 @@ ActionVect PrivateEyeSettings::getStartingActions() { startingActions.push_back(PLAYER_A_UP); return startingActions; } + +// returns a list of mode that the game can be played in +ModeVect PrivateEyeSettings::getAvailableModes() { + ModeVect modes(getNumModes()); + for (unsigned int i = 0; i < modes.size(); i++) { + modes[i] = i; + } + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void PrivateEyeSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + if(m < getNumModes()) { + // read the mode we are currently in + unsigned char mode = readRam(&system, 0x80); + // press select until the correct mode is reached + while (mode != m) { + environment->pressSelect(2); + mode = readRam(&system, 0x80); + } + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } + + +DifficultyVect PrivateEyeSettings::getAvailableDifficulties() { + DifficultyVect diff = {0, 1, 2, 3}; + return diff; +} + diff --git a/atari_py/ale_interface/src/games/supported/PrivateEye.hpp b/atari_py/ale_interface/src/games/supported/PrivateEye.hpp index 5af2c5c..cec9461 100644 --- a/atari_py/ale_interface/src/games/supported/PrivateEye.hpp +++ b/atari_py/ale_interface/src/games/supported/PrivateEye.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The line 69 is based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class PrivateEyeSettings : public RomSettings { // the rom-name const char* rom() const { return "private_eye"; } + // get the available number of modes + unsigned int getNumModes() const { return 5; } + // create a new instance of the rom RomSettings* clone() const; @@ -66,7 +69,20 @@ class PrivateEyeSettings : public RomSettings { ActionVect getStartingActions(); - virtual const int lives() { return 0; } + virtual int lives() { return 0; } + + // returns a list of mode that the game can be played in + // in this game, there are 5 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); + + // returns a list of difficulties that the game can be played in + // in this game, there are 4 available difficulties + DifficultyVect getAvailableDifficulties(); private: diff --git a/atari_py/ale_interface/src/games/supported/QBert.cpp b/atari_py/ale_interface/src/games/supported/QBert.cpp index 8897327..548c012 100644 --- a/atari_py/ale_interface/src/games/supported/QBert.cpp +++ b/atari_py/ale_interface/src/games/supported/QBert.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 57, 59, 115, 124 and 133 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -133,3 +133,8 @@ void QBertSettings::loadState(Deserializer & ser) { m_lives = ser.getInt(); } +DifficultyVect QBertSettings::getAvailableDifficulties() { + DifficultyVect diff = {0, 1}; + return diff; +} + diff --git a/atari_py/ale_interface/src/games/supported/QBert.hpp b/atari_py/ale_interface/src/games/supported/QBert.hpp index ccf1244..cdb98cc 100644 --- a/atari_py/ale_interface/src/games/supported/QBert.hpp +++ b/atari_py/ale_interface/src/games/supported/QBert.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 67 and 75 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -64,7 +64,11 @@ class QBertSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + // returns a list of difficulties that the game can be played in + // in this game, there are 2 available difficulties + DifficultyVect getAvailableDifficulties(); private: diff --git a/atari_py/ale_interface/src/games/supported/RiverRaid.cpp b/atari_py/ale_interface/src/games/supported/RiverRaid.cpp index 872f421..ebb83bd 100644 --- a/atari_py/ale_interface/src/games/supported/RiverRaid.cpp +++ b/atari_py/ale_interface/src/games/supported/RiverRaid.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 84 - 91 and 143 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -159,3 +159,9 @@ void RiverRaidSettings::loadState(Deserializer & ser) { m_terminal = ser.getBool(); m_lives_byte = ser.getInt(); } + +DifficultyVect RiverRaidSettings::getAvailableDifficulties() { + DifficultyVect diff = {0, 1}; + return diff; +} + diff --git a/atari_py/ale_interface/src/games/supported/RiverRaid.hpp b/atari_py/ale_interface/src/games/supported/RiverRaid.hpp index 4586971..812aa31 100644 --- a/atari_py/ale_interface/src/games/supported/RiverRaid.hpp +++ b/atari_py/ale_interface/src/games/supported/RiverRaid.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 68, 73 and 79 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -65,7 +65,11 @@ class RiverRaidSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : numericLives(); } + virtual int lives() { return isTerminal() ? 0 : numericLives(); } + + // returns a list of difficulties that the game can be played in + // in this game, there are 2 available difficulties + DifficultyVect getAvailableDifficulties(); private: diff --git a/atari_py/ale_interface/src/games/supported/RoadRunner.hpp b/atari_py/ale_interface/src/games/supported/RoadRunner.hpp index af576ed..d9fe7a0 100644 --- a/atari_py/ale_interface/src/games/supported/RoadRunner.hpp +++ b/atari_py/ale_interface/src/games/supported/RoadRunner.hpp @@ -64,7 +64,7 @@ class RoadRunnerSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } private: diff --git a/atari_py/ale_interface/src/games/supported/RoboTank.hpp b/atari_py/ale_interface/src/games/supported/RoboTank.hpp index af93525..3d800f3 100644 --- a/atari_py/ale_interface/src/games/supported/RoboTank.hpp +++ b/atari_py/ale_interface/src/games/supported/RoboTank.hpp @@ -64,7 +64,7 @@ class RoboTankSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } private: diff --git a/atari_py/ale_interface/src/games/supported/Seaquest.cpp b/atari_py/ale_interface/src/games/supported/Seaquest.cpp index 01a6915..d7513e9 100644 --- a/atari_py/ale_interface/src/games/supported/Seaquest.cpp +++ b/atari_py/ale_interface/src/games/supported/Seaquest.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 57, 110, 119 and 127 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -127,3 +127,7 @@ void SeaquestSettings::loadState(Deserializer & ser) { m_lives = ser.getInt(); } +DifficultyVect SeaquestSettings::getAvailableDifficulties() { + DifficultyVect diff = {0, 1}; + return diff; +} diff --git a/atari_py/ale_interface/src/games/supported/Seaquest.hpp b/atari_py/ale_interface/src/games/supported/Seaquest.hpp index 145c4f6..4d1a9cf 100644 --- a/atari_py/ale_interface/src/games/supported/Seaquest.hpp +++ b/atari_py/ale_interface/src/games/supported/Seaquest.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 67 and 74 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -64,7 +64,11 @@ class SeaquestSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + // returns a list of difficulties that the game can be played in + // in this game, there are 2 available difficulties + DifficultyVect getAvailableDifficulties(); private: diff --git a/atari_py/ale_interface/src/games/supported/SirLancelot.cpp b/atari_py/ale_interface/src/games/supported/SirLancelot.cpp new file mode 100644 index 0000000..a2d1580 --- /dev/null +++ b/atari_py/ale_interface/src/games/supported/SirLancelot.cpp @@ -0,0 +1,103 @@ +/* ***************************************************************************** + * A.L.E (Arcade Learning Environment) + * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and + * the Reinforcement Learning and Artificial Intelligence Laboratory + * Released under the GNU General Public License; see License.txt for details. + * + * Based on: Stella -- "An Atari 2600 VCS Emulator" + * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team + * + * ***************************************************************************** + */ +#include "SirLancelot.hpp" + +#include "../RomUtils.hpp" + + +SirLancelotSettings::SirLancelotSettings() { + reset(); +} + + +/* create a new instance of the rom */ +RomSettings* SirLancelotSettings::clone() const { + RomSettings* rval = new SirLancelotSettings(); + *rval = *this; + return rval; +} + + +/* process the latest information from ALE */ +void SirLancelotSettings::step(const System& system) { + // update the reward + int score = getDecimalScore(0xA0, 0x9F, 0x9E, &system); + int reward = score - m_score; + m_reward = reward; + m_score = score; + + // update terminal status + m_lives = readRam(&system, 0xA9); + m_terminal = (m_lives == 0) && readRam(&system, 0xA7) == 0xA0; +} + + +/* is end of game */ +bool SirLancelotSettings::isTerminal() const { + return m_terminal; +}; + + +/* get the most recently observed reward */ +reward_t SirLancelotSettings::getReward() const { + return m_reward; +} + + +/* is an action part of the minimal set? */ +bool SirLancelotSettings::isMinimal(const Action &a) const { + switch (a) { + case PLAYER_A_NOOP: + case PLAYER_A_FIRE: + case PLAYER_A_RIGHT: + case PLAYER_A_LEFT: + case PLAYER_A_RIGHTFIRE: + case PLAYER_A_LEFTFIRE: + return true; + default: + return false; + } +} + + +/* reset the state of the game */ +void SirLancelotSettings::reset() { + m_reward = 0; + m_score = 0; + m_terminal = false; + m_lives = 3; +} + +/* saves the state of the rom settings */ +void SirLancelotSettings::saveState(Serializer & ser) { + ser.putInt(m_reward); + ser.putInt(m_score); + ser.putBool(m_terminal); + ser.putInt(m_lives); +} + +// loads the state of the rom settings +void SirLancelotSettings::loadState(Deserializer & ser) { + m_reward = ser.getInt(); + m_score = ser.getInt(); + m_terminal = ser.getBool(); + m_lives = ser.getInt(); +} + +ActionVect SirLancelotSettings::getStartingActions() { + ActionVect startingActions; + startingActions.push_back(RESET); + startingActions.push_back(PLAYER_A_LEFT); + return startingActions; +} + + diff --git a/atari_py/ale_interface/src/games/supported/SirLancelot.hpp b/atari_py/ale_interface/src/games/supported/SirLancelot.hpp new file mode 100644 index 0000000..6eb5784 --- /dev/null +++ b/atari_py/ale_interface/src/games/supported/SirLancelot.hpp @@ -0,0 +1,64 @@ +/* ***************************************************************************** + * A.L.E (Arcade Learning Environment) + * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and + * the Reinforcement Learning and Artificial Intelligence Laboratory + * Released under the GNU General Public License; see License.txt for details. + * + * Based on: Stella -- "An Atari 2600 VCS Emulator" + * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team + * + * ***************************************************************************** + */ +#ifndef __SIRLANCELOT_HPP__ +#define __SIRLANCELOT_HPP__ + +#include "../RomSettings.hpp" + + +/* RL wrapper for Up N Down */ +class SirLancelotSettings : public RomSettings { + public: + SirLancelotSettings(); + + // reset + void reset(); + + // is end of game + bool isTerminal() const; + + // get the most recently observed reward + reward_t getReward() const; + + // the rom-name + // MD5 7ead257e8b5a44cac538f5f54c7a0023 + const char* rom() const { return "sir_lancelot"; } + + // create a new instance of the rom + RomSettings* clone() const; + + // is an action part of the minimal set? + bool isMinimal(const Action& a) const; + + // process the latest information from ALE + void step(const System& system); + + // saves the state of the rom settings + void saveState(Serializer & ser); + + // loads the state of the rom settings + void loadState(Deserializer & ser); + + // SirLancelot requires the reset+left action to start the game + ActionVect getStartingActions(); + + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + private: + bool m_terminal; + reward_t m_reward; + reward_t m_score; + int m_lives; +}; + +#endif // __SIRLANCELOT_HPP__ + diff --git a/atari_py/ale_interface/src/games/supported/Skiing.hpp b/atari_py/ale_interface/src/games/supported/Skiing.hpp index 8dde08e..e4c3688 100644 --- a/atari_py/ale_interface/src/games/supported/Skiing.hpp +++ b/atari_py/ale_interface/src/games/supported/Skiing.hpp @@ -68,7 +68,7 @@ class SkiingSettings : public RomSettings { ActionVect getStartingActions(); - virtual const int lives() { return 0; } + virtual int lives() { return 0; } private: diff --git a/atari_py/ale_interface/src/games/supported/Solaris.hpp b/atari_py/ale_interface/src/games/supported/Solaris.hpp index 3cb098e..732a111 100644 --- a/atari_py/ale_interface/src/games/supported/Solaris.hpp +++ b/atari_py/ale_interface/src/games/supported/Solaris.hpp @@ -64,7 +64,7 @@ class SolarisSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } private: diff --git a/atari_py/ale_interface/src/games/supported/SpaceInvaders.cpp b/atari_py/ale_interface/src/games/supported/SpaceInvaders.cpp index c3297c5..646d27a 100644 --- a/atari_py/ale_interface/src/games/supported/SpaceInvaders.cpp +++ b/atari_py/ale_interface/src/games/supported/SpaceInvaders.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 54 - 59, 100, 109 and 117 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -124,3 +124,37 @@ void SpaceInvadersSettings::loadState(Deserializer & ser) { m_lives = ser.getInt(); } +// returns a list of mode that the game can be played in +ModeVect SpaceInvadersSettings::getAvailableModes() { + ModeVect modes(getNumModes()); + for (unsigned int i = 0; i < modes.size(); i++) { + modes[i] = i; + } + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void SpaceInvadersSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + if(m < getNumModes()) { + // read the mode we are currently in + unsigned char mode = readRam(&system, 0xDC); + // press select until the correct mode is reached + while (mode != m) { + environment->pressSelect(2); + mode = readRam(&system, 0xDC); + } + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } + +DifficultyVect SpaceInvadersSettings::getAvailableDifficulties() { + DifficultyVect diff = {0, 1}; + return diff; +} \ No newline at end of file diff --git a/atari_py/ale_interface/src/games/supported/SpaceInvaders.hpp b/atari_py/ale_interface/src/games/supported/SpaceInvaders.hpp index a8d2b96..9d872d0 100644 --- a/atari_py/ale_interface/src/games/supported/SpaceInvaders.hpp +++ b/atari_py/ale_interface/src/games/supported/SpaceInvaders.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 67 and 74 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class SpaceInvadersSettings : public RomSettings { // the rom-name const char* rom() const { return "space_invaders"; } + // get the available number of modes + unsigned int getNumModes() const { return 16; } + // create a new instance of the rom RomSettings* clone() const; @@ -64,7 +67,21 @@ class SpaceInvadersSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + // returns a list of mode that the game can be played in + // in this game, there are 16 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); + + // returns a list of difficulties that the game can be played in + // in this game, there are 2 available difficulties + DifficultyVect getAvailableDifficulties(); + private: diff --git a/atari_py/ale_interface/src/games/supported/StarGunner.cpp b/atari_py/ale_interface/src/games/supported/StarGunner.cpp index 4bfb134..dd86bea 100644 --- a/atari_py/ale_interface/src/games/supported/StarGunner.cpp +++ b/atari_py/ale_interface/src/games/supported/StarGunner.cpp @@ -1,6 +1,5 @@ /* ***************************************************************************** - * The lines 71, 73, 126, 127, 135, 136, 144 and 145 are based on Xitari's code, - * from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -146,3 +145,32 @@ void StarGunnerSettings::loadState(Deserializer & ser) { m_game_started = ser.getBool(); } +// returns a list of mode that the game can be played in +ModeVect StarGunnerSettings::getAvailableModes() { + ModeVect modes(getNumModes()); + for (unsigned int i = 0; i < modes.size(); i++) { + modes[i] = i; + } + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void StarGunnerSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + if(m < getNumModes()) { + // read the mode we are currently in + unsigned char mode = readRam(&system, 0xF4); + // press select until the correct mode is reached + while (mode != m) { + environment->pressSelect(15); + mode = readRam(&system, 0xF4); + } + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } diff --git a/atari_py/ale_interface/src/games/supported/StarGunner.hpp b/atari_py/ale_interface/src/games/supported/StarGunner.hpp index d7cf46b..ac48669 100644 --- a/atari_py/ale_interface/src/games/supported/StarGunner.hpp +++ b/atari_py/ale_interface/src/games/supported/StarGunner.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 67, 74 and 75 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class StarGunnerSettings : public RomSettings { // the rom-name const char* rom() const { return "star_gunner"; } + // get the available number of modes + unsigned int getNumModes() const { return 4; } + // create a new instance of the rom RomSettings* clone() const; @@ -64,7 +67,16 @@ class StarGunnerSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + // returns a list of mode that the game can be played in + // in this game, there are 4 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); private: diff --git a/atari_py/ale_interface/src/games/supported/Tennis.cpp b/atari_py/ale_interface/src/games/supported/Tennis.cpp index e27cf9f..55e0429 100644 --- a/atari_py/ale_interface/src/games/supported/Tennis.cpp +++ b/atari_py/ale_interface/src/games/supported/Tennis.cpp @@ -129,3 +129,35 @@ void TennisSettings::loadState(Deserializer & ser) { m_prev_delta_score = ser.getInt(); } +// returns a list of mode that the game can be played in +ModeVect TennisSettings::getAvailableModes() { + ModeVect modes = {0, 2}; + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void TennisSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + if(m == 0 || m == 2) { + // read the mode we are currently in + unsigned char mode = readRam(&system, 0x80); + // press select until the correct mode is reached + while (mode != m) { + environment->pressSelect(2); + mode = readRam(&system, 0x80); + } + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } + +DifficultyVect TennisSettings::getAvailableDifficulties() { + DifficultyVect diff = {0, 1, 2, 3}; + return diff; +} + diff --git a/atari_py/ale_interface/src/games/supported/Tennis.hpp b/atari_py/ale_interface/src/games/supported/Tennis.hpp index b234213..e35a6a6 100644 --- a/atari_py/ale_interface/src/games/supported/Tennis.hpp +++ b/atari_py/ale_interface/src/games/supported/Tennis.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The line 67 is based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class TennisSettings : public RomSettings { // the rom-name const char* rom() const { return "tennis"; } + // get the available number of modes + unsigned int getNumModes() const { return 2; } + // create a new instance of the rom RomSettings* clone() const; @@ -64,7 +67,20 @@ class TennisSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return 0; } + virtual int lives() { return 0; } + + // returns a list of mode that the game can be played in + // in this game, there are 2 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); + + // returns a list of difficulties that the game can be played in + // in this game, there are 4 available difficulties + DifficultyVect getAvailableDifficulties(); private: diff --git a/atari_py/ale_interface/src/games/supported/Tetris.cpp b/atari_py/ale_interface/src/games/supported/Tetris.cpp new file mode 100644 index 0000000..6d8371a --- /dev/null +++ b/atari_py/ale_interface/src/games/supported/Tetris.cpp @@ -0,0 +1,130 @@ +/* ***************************************************************************** + * ALE support for Tetris https://github.com/udibr/tetris26 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * ***************************************************************************** + * A.L.E (Arcade Learning Environment) + * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and + * the Reinforcement Learning and Artificial Intelligence Laboratory + * Released under the GNU General Public License; see License.txt for details. + * + * Based on: Stella -- "An Atari 2600 VCS Emulator" + * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team + * + * ***************************************************************************** + */ +#include "Tetris.hpp" + +#include "../RomUtils.hpp" + + +TetrisSettings::TetrisSettings() { + + reset(); +} + + +/* create a new instance of the rom */ +RomSettings* TetrisSettings::clone() const { + + RomSettings* rval = new TetrisSettings(); + *rval = *this; + return rval; +} + + +/* process the latest information from ALE */ +void TetrisSettings::step(const System& system) { + + // update the reward + reward_t score = getDecimalScore(0x71, 0x72, &system); + if (score > m_score) { + m_reward = score - m_score; + } else { + m_reward = 0; + } + m_score = score; + + if (!m_started) { + m_started = true; + } + + int byte_val = readRam(&system, 0x73); + m_terminal = m_started && (byte_val & 0x80); + if (m_terminal) { + m_score = 0; + m_started = false; + } +} + + +/* is end of game */ +bool TetrisSettings::isTerminal() const { + + return m_terminal; +}; + + +/* get the most recently observed reward */ +reward_t TetrisSettings::getReward() const { + + return m_reward; +} + + +/* is an action part of the minimal set? */ +bool TetrisSettings::isMinimal(const Action &a) const { + + switch (a) { + case PLAYER_A_NOOP: + case PLAYER_A_FIRE: + case PLAYER_A_RIGHT: + case PLAYER_A_LEFT: + case PLAYER_A_DOWN: + return true; + default: + return false; + } +} + + +/* reset the state of the game */ +void TetrisSettings::reset() { + + m_reward = 0; + m_score = 0; + m_lives = 0; + m_terminal = false; + m_started = false; +} + + +/* saves the state of the rom settings */ +void TetrisSettings::saveState(Serializer & ser) { + ser.putInt(m_reward); + ser.putInt(m_score); + ser.putBool(m_terminal); + ser.putBool(m_started); + ser.putInt(m_lives); +} + +// loads the state of the rom settings +void TetrisSettings::loadState(Deserializer & ser) { + m_reward = ser.getInt(); + m_score = ser.getInt(); + m_terminal = ser.getBool(); + m_started = ser.getBool(); + m_lives = ser.getInt(); +} + diff --git a/atari_py/ale_interface/src/games/supported/Tetris.hpp b/atari_py/ale_interface/src/games/supported/Tetris.hpp new file mode 100644 index 0000000..509291b --- /dev/null +++ b/atari_py/ale_interface/src/games/supported/Tetris.hpp @@ -0,0 +1,78 @@ +/* ***************************************************************************** + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * ***************************************************************************** + * A.L.E (Arcade Learning Environment) + * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and + * the Reinforcement Learning and Artificial Intelligence Laboratory + * Released under the GNU General Public License; see License.txt for details. + * + * Based on: Stella -- "An Atari 2600 VCS Emulator" + * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team + * + * ***************************************************************************** + */ +#ifndef __TETRIS_HPP__ +#define __TETRIS_HPP__ + +#include "../RomSettings.hpp" + + +/* RL wrapper for Tetris */ +class TetrisSettings : public RomSettings { + + public: + + TetrisSettings(); + + // reset + void reset(); + + // is end of game + bool isTerminal() const; + + // get the most recently observed reward + reward_t getReward() const; + + // the rom-name + const char* rom() const { return "tetris"; } + + // create a new instance of the rom + RomSettings* clone() const; + + // is an action part of the minimal set? + bool isMinimal(const Action& a) const; + + // process the latest information from ALE + void step(const System& system); + + // saves the state of the rom settings + void saveState(Serializer & ser); + + // loads the state of the rom settings + void loadState(Deserializer & ser); + + // remaining lives + int lives() { return isTerminal() ? 0 : m_lives; } + + private: + + bool m_terminal; + bool m_started; + reward_t m_reward; + reward_t m_score; + int m_lives; +}; + +#endif // __TETRIS_HPP__ + diff --git a/atari_py/ale_interface/src/games/supported/TimePilot.cpp b/atari_py/ale_interface/src/games/supported/TimePilot.cpp index bafc9ce..7c2d61f 100644 --- a/atari_py/ale_interface/src/games/supported/TimePilot.cpp +++ b/atari_py/ale_interface/src/games/supported/TimePilot.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 64, 109, 117 and 125 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -125,3 +125,8 @@ void TimePilotSettings::loadState(Deserializer & ser) { m_lives = ser.getInt(); } + +DifficultyVect TimePilotSettings::getAvailableDifficulties() { + DifficultyVect diff = {0, 1, 2}; + return diff; +} diff --git a/atari_py/ale_interface/src/games/supported/TimePilot.hpp b/atari_py/ale_interface/src/games/supported/TimePilot.hpp index a9dfec5..f4735a3 100644 --- a/atari_py/ale_interface/src/games/supported/TimePilot.hpp +++ b/atari_py/ale_interface/src/games/supported/TimePilot.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 67 and 74 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -64,7 +64,11 @@ class TimePilotSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + // returns a list of difficulties that the game can be played in + // in this game, there are 3 available difficulties + DifficultyVect getAvailableDifficulties(); private: diff --git a/atari_py/ale_interface/src/games/supported/Trondead.cpp b/atari_py/ale_interface/src/games/supported/Trondead.cpp new file mode 100644 index 0000000..4ca5da7 --- /dev/null +++ b/atari_py/ale_interface/src/games/supported/Trondead.cpp @@ -0,0 +1,115 @@ +/* ***************************************************************************** + * A.L.E (Arcade Learning Environment) + * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and + * the Reinforcement Learning and Artificial Intelligence Laboratory + * Released under the GNU General Public License; see License.txt for details. + * + * Based on: Stella -- "An Atari 2600 VCS Emulator" + * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team + * + * ***************************************************************************** + */ +#include "Trondead.hpp" + +#include "../RomUtils.hpp" + + +TrondeadSettings::TrondeadSettings() { + + reset(); +} + + +/* create a new instance of the rom */ +RomSettings* TrondeadSettings::clone() const { + + RomSettings* rval = new TrondeadSettings(); + *rval = *this; + return rval; +} + + +/* process the latest information from ALE */ +void TrondeadSettings::step(const System& system) { + + // update the reward + int score = getDecimalScore(0xBF, 0xBE, 0xBD, &system); + int reward = score - m_score; + m_reward = reward; + m_score = score; + + // update terminal status + int hit_count = readRam(&system, 0xC8); + m_terminal = (hit_count == 5); // Five times hit + m_lives = 5 - hit_count; +} + + +/* is end of game */ +bool TrondeadSettings::isTerminal() const { + + return m_terminal; +}; + + +/* get the most recently observed reward */ +reward_t TrondeadSettings::getReward() const { + + return m_reward; +} + + +/* is an action part of the minimal set? */ +bool TrondeadSettings::isMinimal(const Action &a) const { + + switch (a) { + case PLAYER_A_NOOP: + case PLAYER_A_FIRE: + case PLAYER_A_UP: + case PLAYER_A_RIGHT: + case PLAYER_A_LEFT: + case PLAYER_A_DOWN: + case PLAYER_A_UPRIGHT: + case PLAYER_A_UPLEFT: + case PLAYER_A_DOWNRIGHT: + case PLAYER_A_DOWNLEFT: + case PLAYER_A_UPFIRE: + case PLAYER_A_RIGHTFIRE: + case PLAYER_A_LEFTFIRE: + case PLAYER_A_DOWNFIRE: + case PLAYER_A_UPRIGHTFIRE: + case PLAYER_A_UPLEFTFIRE: + case PLAYER_A_DOWNRIGHTFIRE: + case PLAYER_A_DOWNLEFTFIRE: + return true; + default: + return false; + } +} + + +/* reset the state of the game */ +void TrondeadSettings::reset() { + + m_reward = 0; + m_score = 0; + m_terminal = false; + m_lives = 5; +} + +/* saves the state of the rom settings */ +void TrondeadSettings::saveState(Serializer & ser) { + ser.putInt(m_reward); + ser.putInt(m_score); + ser.putBool(m_terminal); + ser.putInt(m_lives); +} + +// loads the state of the rom settings +void TrondeadSettings::loadState(Deserializer & ser) { + m_reward = ser.getInt(); + m_score = ser.getInt(); + m_terminal = ser.getBool(); + m_lives = ser.getInt(); +} + diff --git a/atari_py/ale_interface/src/games/supported/Trondead.hpp b/atari_py/ale_interface/src/games/supported/Trondead.hpp new file mode 100644 index 0000000..722f618 --- /dev/null +++ b/atari_py/ale_interface/src/games/supported/Trondead.hpp @@ -0,0 +1,63 @@ +/* ***************************************************************************** + * A.L.E (Arcade Learning Environment) + * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and + * the Reinforcement Learning and Artificial Intelligence Laboratory + * Released under the GNU General Public License; see License.txt for details. + * + * Based on: Stella -- "An Atari 2600 VCS Emulator" + * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team + * + * ***************************************************************************** + */ +#ifndef __TRONDEAD_HPP__ +#define __TRONDEAD_HPP__ + +#include "../RomSettings.hpp" + + +/* RL wrapper for Trondead */ +class TrondeadSettings : public RomSettings { + + public: + + TrondeadSettings(); + + // reset + void reset(); + + // is end of game + bool isTerminal() const; + + // get the most recently observed reward + reward_t getReward() const; + + // the rom-name + const char* rom() const { return "trondead"; } + + // create a new instance of the rom + RomSettings* clone() const; + + // is an action part of the minimal set? + bool isMinimal(const Action& a) const; + + // process the latest information from ALE + void step(const System& system); + + // saves the state of the rom settings + void saveState(Serializer & ser); + + // loads the state of the rom settings + void loadState(Deserializer & ser); + + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + private: + + bool m_terminal; + reward_t m_reward; + reward_t m_score; + int m_lives; +}; + +#endif // __TRONDEAD_HPP__ + diff --git a/atari_py/ale_interface/src/games/supported/Turmoil.cpp b/atari_py/ale_interface/src/games/supported/Turmoil.cpp new file mode 100644 index 0000000..f763865 --- /dev/null +++ b/atari_py/ale_interface/src/games/supported/Turmoil.cpp @@ -0,0 +1,118 @@ +/* ***************************************************************************** + * A.L.E (Arcade Learning Environment) + * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and + * the Reinforcement Learning and Artificial Intelligence Laboratory + * Released under the GNU General Public License; see License.txt for details. + * + * Based on: Stella -- "An Atari 2600 VCS Emulator" + * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team + * + * ***************************************************************************** + */ +#include "Turmoil.hpp" + +#include "../RomUtils.hpp" + + +TurmoilSettings::TurmoilSettings() { + + reset(); +} + + +/* create a new instance of the rom */ +RomSettings* TurmoilSettings::clone() const { + + RomSettings* rval = new TurmoilSettings(); + *rval = *this; + return rval; +} + + +/* process the latest information from ALE */ +void TurmoilSettings::step(const System& system) { + + // update the reward + int score = getDecimalScore(0x89, 0x8A, &system); + score += readRam(&system, 0xD3); + score *= 10; + int reward = score - m_score; + m_reward = reward; + m_score = score; + + // update terminal status + int lives_byte = readRam(&system, 0xB9); + m_terminal = (lives_byte == 0) && readRam(&system, 0xC5) == 0x01; + + m_lives = lives_byte; +} + + +/* is end of game */ +bool TurmoilSettings::isTerminal() const { + + return m_terminal; +}; + + +/* get the most recently observed reward */ +reward_t TurmoilSettings::getReward() const { + + return m_reward; +} + + +/* is an action part of the minimal set? */ +bool TurmoilSettings::isMinimal(const Action &a) const { + + switch (a) { + case PLAYER_A_NOOP: + case PLAYER_A_FIRE: + case PLAYER_A_UP: + case PLAYER_A_RIGHT: + case PLAYER_A_LEFT: + case PLAYER_A_DOWN: + case PLAYER_A_UPRIGHT: + case PLAYER_A_UPLEFT: + case PLAYER_A_DOWNRIGHT: + case PLAYER_A_DOWNLEFT: + case PLAYER_A_RIGHTFIRE: + case PLAYER_A_LEFTFIRE: + return true; + default: + return false; + } +} + + +/* reset the state of the game */ +void TurmoilSettings::reset() { + + m_reward = 0; + m_score = 0; + m_terminal = false; + m_lives = 4; +} + +/* saves the state of the rom settings */ +void TurmoilSettings::saveState(Serializer & ser) { + ser.putInt(m_reward); + ser.putInt(m_score); + ser.putBool(m_terminal); + ser.putInt(m_lives); +} + +// loads the state of the rom settings +void TurmoilSettings::loadState(Deserializer & ser) { + m_reward = ser.getInt(); + m_score = ser.getInt(); + m_terminal = ser.getBool(); + m_lives = ser.getInt(); +} + +ActionVect TurmoilSettings::getStartingActions() { + ActionVect startingActions; + startingActions.push_back(PLAYER_A_FIRE); + return startingActions; +} + diff --git a/atari_py/ale_interface/src/games/supported/Turmoil.hpp b/atari_py/ale_interface/src/games/supported/Turmoil.hpp new file mode 100644 index 0000000..004b21e --- /dev/null +++ b/atari_py/ale_interface/src/games/supported/Turmoil.hpp @@ -0,0 +1,69 @@ +/* ***************************************************************************** + * A.L.E (Arcade Learning Environment) + * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and + * the Reinforcement Learning and Artificial Intelligence Laboratory + * Released under the GNU General Public License; see License.txt for details. + * + * Based on: Stella -- "An Atari 2600 VCS Emulator" + * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team + * + * ***************************************************************************** + */ +#ifndef __TURMOIL_HPP__ +#define __TURMOIL_HPP__ + +#include "../RomSettings.hpp" + + +/* RL wrapper for Turmoil */ +class TurmoilSettings : public RomSettings { + + public: + + TurmoilSettings(); + + // reset + void reset(); + + // is end of game + bool isTerminal() const; + + // get the most recently observed reward + reward_t getReward() const; + + // the rom-name + // MD5 sum of ROM file: + // 7a5463545dfb2dcfdafa6074b2f2c15e Turmoil.bin + const char* rom() const { return "turmoil"; } + + // create a new instance of the rom + RomSettings* clone() const; + + // is an action part of the minimal set? + bool isMinimal(const Action& a) const; + + // process the latest information from ALE + void step(const System& system); + + // saves the state of the rom settings + void saveState(Serializer & ser); + + // loads the state of the rom settings + void loadState(Deserializer & ser); + + // Turmoil requires the fire action to start the game + ActionVect getStartingActions(); + + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + private: + + bool m_terminal; + reward_t m_reward; + reward_t m_score; + int m_lives; +}; + +#endif // __TURMOIL_HPP__ + + diff --git a/atari_py/ale_interface/src/games/supported/Tutankham.cpp b/atari_py/ale_interface/src/games/supported/Tutankham.cpp index a87b639..7c85c1a 100644 --- a/atari_py/ale_interface/src/games/supported/Tutankham.cpp +++ b/atari_py/ale_interface/src/games/supported/Tutankham.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 63, 106, 114 and 122 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -122,3 +122,29 @@ void TutankhamSettings::loadState(Deserializer & ser) { m_lives = ser.getInt(); } +// returns a list of mode that the game can be played in +ModeVect TutankhamSettings::getAvailableModes() { + ModeVect modes = {0, 4, 8, 12}; + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void TutankhamSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + if(m == 0 || m == 4 || m == 8 || m == 12) { + // read the mode we are currently in + unsigned char mode = readRam(&system, 0xAB); + // press select until the correct mode is reached + while (mode != m) { + environment->pressSelect(2); + mode = readRam(&system, 0xAB); + } + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } diff --git a/atari_py/ale_interface/src/games/supported/Tutankham.hpp b/atari_py/ale_interface/src/games/supported/Tutankham.hpp index 67b215a..e079cbf 100644 --- a/atari_py/ale_interface/src/games/supported/Tutankham.hpp +++ b/atari_py/ale_interface/src/games/supported/Tutankham.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 67 and 74 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class TutankhamSettings : public RomSettings { // the rom-name const char* rom() const { return "tutankham"; } + // get the available number of modes + unsigned int getNumModes() const { return 4; } + // create a new instance of the rom RomSettings* clone() const; @@ -64,7 +67,16 @@ class TutankhamSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal()? 0 : m_lives; } + virtual int lives() { return isTerminal()? 0 : m_lives; } + + // returns a list of mode that the game can be played in + // in this game, there are 4 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); private: diff --git a/atari_py/ale_interface/src/games/supported/UpNDown.cpp b/atari_py/ale_interface/src/games/supported/UpNDown.cpp index 57944f8..28be559 100644 --- a/atari_py/ale_interface/src/games/supported/UpNDown.cpp +++ b/atari_py/ale_interface/src/games/supported/UpNDown.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 61, 102, 110 and 118 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -124,4 +124,8 @@ ActionVect UpNDownSettings::getStartingActions() { return startingActions; } +DifficultyVect UpNDownSettings::getAvailableDifficulties() { + DifficultyVect diff = {0, 1, 2, 3}; + return diff; +} diff --git a/atari_py/ale_interface/src/games/supported/UpNDown.hpp b/atari_py/ale_interface/src/games/supported/UpNDown.hpp index ea2e548..2d337f5 100644 --- a/atari_py/ale_interface/src/games/supported/UpNDown.hpp +++ b/atari_py/ale_interface/src/games/supported/UpNDown.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 70 and 77 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -67,7 +67,11 @@ class UpNDownSettings : public RomSettings { // UpNDown requires the fire action to start the game ActionVect getStartingActions(); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + // returns a list of difficulties that the game can be played in + // in this game, there are 4 available difficulties + DifficultyVect getAvailableDifficulties(); private: diff --git a/atari_py/ale_interface/src/games/supported/Venture.cpp b/atari_py/ale_interface/src/games/supported/Venture.cpp index b19e229..b42652a 100644 --- a/atari_py/ale_interface/src/games/supported/Venture.cpp +++ b/atari_py/ale_interface/src/games/supported/Venture.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 63, 116, 124 and 132 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -132,3 +132,9 @@ void VentureSettings::loadState(Deserializer & ser) { m_lives = ser.getInt(); } + +DifficultyVect VentureSettings::getAvailableDifficulties() { + DifficultyVect diff = {0, 1, 2, 3}; + return diff; +} + diff --git a/atari_py/ale_interface/src/games/supported/Venture.hpp b/atari_py/ale_interface/src/games/supported/Venture.hpp index b1914b9..126ab9e 100644 --- a/atari_py/ale_interface/src/games/supported/Venture.hpp +++ b/atari_py/ale_interface/src/games/supported/Venture.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 67 and 74 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -64,7 +64,11 @@ class VentureSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + // returns a list of difficulties that the game can be played in + // in this game, there are 2 available difficulties + DifficultyVect getAvailableDifficulties(); private: diff --git a/atari_py/ale_interface/src/games/supported/VideoPinball.cpp b/atari_py/ale_interface/src/games/supported/VideoPinball.cpp index 99bd443..8f320f6 100644 --- a/atari_py/ale_interface/src/games/supported/VideoPinball.cpp +++ b/atari_py/ale_interface/src/games/supported/VideoPinball.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 60 - 65, 109, 117 and 125 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -125,3 +125,34 @@ void VideoPinballSettings::loadState(Deserializer & ser) { m_lives = ser.getInt(); } +// returns a list of mode that the game can be played in +ModeVect VideoPinballSettings::getAvailableModes() { + ModeVect modes = {0, 2}; + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void VideoPinballSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + if(m == 0 || m == 2) { + // read the mode we are currently in + unsigned char mode = readRam(&system, 0xC1); + // press select until the correct mode is reached + while (mode != m) { + environment->pressSelect(2); + mode = readRam(&system, 0xC1); + } + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } + +DifficultyVect VideoPinballSettings::getAvailableDifficulties() { + DifficultyVect diff = {0, 1}; + return diff; +} \ No newline at end of file diff --git a/atari_py/ale_interface/src/games/supported/VideoPinball.hpp b/atari_py/ale_interface/src/games/supported/VideoPinball.hpp index 541ba8b..21d218c 100644 --- a/atari_py/ale_interface/src/games/supported/VideoPinball.hpp +++ b/atari_py/ale_interface/src/games/supported/VideoPinball.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 67 and 74 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class VideoPinballSettings : public RomSettings { // the rom-name const char* rom() const { return "video_pinball"; } + // get the available number of modes + unsigned int getNumModes() const { return 2; } + // create a new instance of the rom RomSettings* clone() const; @@ -64,7 +67,20 @@ class VideoPinballSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + // returns a list of mode that the game can be played in + // in this game, there are 2 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); + + // returns a list of difficulties that the game can be played in + // in this game, there are 2 available difficulties + DifficultyVect getAvailableDifficulties(); private: diff --git a/atari_py/ale_interface/src/games/supported/WizardOfWor.cpp b/atari_py/ale_interface/src/games/supported/WizardOfWor.cpp index ca89ad5..16c32bc 100644 --- a/atari_py/ale_interface/src/games/supported/WizardOfWor.cpp +++ b/atari_py/ale_interface/src/games/supported/WizardOfWor.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 61, 63, 67, 112, 121 and 129 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -129,3 +129,8 @@ void WizardOfWorSettings::loadState(Deserializer & ser) { m_lives = ser.getInt(); } +DifficultyVect WizardOfWorSettings::getAvailableDifficulties() { + DifficultyVect diff = {0, 1}; + return diff; +} + diff --git a/atari_py/ale_interface/src/games/supported/WizardOfWor.hpp b/atari_py/ale_interface/src/games/supported/WizardOfWor.hpp index c5a4834..86f8f8c 100644 --- a/atari_py/ale_interface/src/games/supported/WizardOfWor.hpp +++ b/atari_py/ale_interface/src/games/supported/WizardOfWor.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 67 and 74 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -64,7 +64,11 @@ class WizardOfWorSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + // returns a list of difficulties that the game can be played in + // in this game, there are 2 available difficulties + DifficultyVect getAvailableDifficulties(); private: diff --git a/atari_py/ale_interface/src/games/supported/YarsRevenge.cpp b/atari_py/ale_interface/src/games/supported/YarsRevenge.cpp index 7312057..a04b1f8 100644 --- a/atari_py/ale_interface/src/games/supported/YarsRevenge.cpp +++ b/atari_py/ale_interface/src/games/supported/YarsRevenge.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 57, 58, 60, 113, 121 and 129 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -134,3 +134,37 @@ ActionVect YarsRevengeSettings::getStartingActions() { startingActions.push_back(PLAYER_A_FIRE); return startingActions; } + +// returns a list of mode that the game can be played in +ModeVect YarsRevengeSettings::getAvailableModes() { + ModeVect modes = {0, 0x20, 0x40, 0x60}; + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void YarsRevengeSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + if(m == 0 || m == 0x20 || m == 0x40 || m == 0x60) { + // enter in mode selection screen + environment->pressSelect(2); + // read the mode we are currently in + unsigned char mode = readRam(&system, 0xE3); + // press select until the correct mode is reached + while (mode != m) { + environment->pressSelect(); + mode = readRam(&system, 0xE3); + } + //reset the environment to apply changes. + environment->softReset(); + } + else { + throw std::runtime_error("This mode doesn't currently exist for this game"); + } + } + +DifficultyVect YarsRevengeSettings::getAvailableDifficulties() { + DifficultyVect diff = {0, 1}; + return diff; +} \ No newline at end of file diff --git a/atari_py/ale_interface/src/games/supported/YarsRevenge.hpp b/atari_py/ale_interface/src/games/supported/YarsRevenge.hpp index 98413d1..100c96f 100644 --- a/atari_py/ale_interface/src/games/supported/YarsRevenge.hpp +++ b/atari_py/ale_interface/src/games/supported/YarsRevenge.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 70 and 77 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class YarsRevengeSettings : public RomSettings { // the rom-name const char* rom() const { return "yars_revenge"; } + // get the available number of modes + unsigned int getNumModes() const { return 4; } + // create a new instance of the rom RomSettings* clone() const; @@ -67,7 +70,20 @@ class YarsRevengeSettings : public RomSettings { // Gopher requires the fire action to start the game ActionVect getStartingActions(); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + // returns a list of mode that the game can be played in + // in this game, there are 4 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); + + // returns a list of difficulties that the game can be played in + // in this game, there are 2 available difficulties + DifficultyVect getAvailableDifficulties(); private: diff --git a/atari_py/ale_interface/src/games/supported/Zaxxon.cpp b/atari_py/ale_interface/src/games/supported/Zaxxon.cpp index 3a7cc6c..4514780 100644 --- a/atari_py/ale_interface/src/games/supported/Zaxxon.cpp +++ b/atari_py/ale_interface/src/games/supported/Zaxxon.cpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 61, 63, 116, 124 and 132 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -132,3 +132,26 @@ void ZaxxonSettings::loadState(Deserializer & ser) { m_lives = ser.getInt(); } +// returns a list of mode that the game can be played in +ModeVect ZaxxonSettings::getAvailableModes() { + ModeVect modes = {0, 8, 16, 24}; + return modes; +} + +// set the mode of the game +// the given mode must be one returned by the previous function +void ZaxxonSettings::setMode(game_mode_t m, System &system, + std::unique_ptr environment) { + + // read the mode we are currently in + unsigned char mode = readRam(&system, 0x82); + // press select until the correct mode is reached + while (mode != m) { + // hold select button for 10 frames + environment->pressSelect(10); + mode = readRam(&system, 0x82); + } + //reset the environment to apply changes. + environment->softReset(); + } + diff --git a/atari_py/ale_interface/src/games/supported/Zaxxon.hpp b/atari_py/ale_interface/src/games/supported/Zaxxon.hpp index a1978ff..8087dbd 100644 --- a/atari_py/ale_interface/src/games/supported/Zaxxon.hpp +++ b/atari_py/ale_interface/src/games/supported/Zaxxon.hpp @@ -1,5 +1,5 @@ /* ***************************************************************************** - * The lines 67 and 74 are based on Xitari's code, from Google Inc. + * The method lives() is based on Xitari's code, from Google Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 @@ -49,6 +49,9 @@ class ZaxxonSettings : public RomSettings { // the rom-name const char* rom() const { return "zaxxon"; } + // get the available number of modes + unsigned int getNumModes() const { return 4; } + // create a new instance of the rom RomSettings* clone() const; @@ -64,7 +67,17 @@ class ZaxxonSettings : public RomSettings { // loads the state of the rom settings void loadState(Deserializer & ser); - virtual const int lives() { return isTerminal() ? 0 : m_lives; } + virtual int lives() { return isTerminal() ? 0 : m_lives; } + + // returns a list of mode that the game can be played in + // in this game, there are 4 available modes + ModeVect getAvailableModes(); + + // set the mode of the game + // the given mode must be one returned by the previous function + void setMode(game_mode_t, System &system, + std::unique_ptr environment); + private: diff --git a/atari_py/ale_interface/src/main.cpp b/atari_py/ale_interface/src/main.cpp index f634b55..bdd7416 100644 --- a/atari_py/ale_interface/src/main.cpp +++ b/atari_py/ale_interface/src/main.cpp @@ -36,8 +36,9 @@ #include "common/Constants.h" #include "ale_interface.hpp" -static std::auto_ptr theOSystem(NULL); -static std::auto_ptr theSettings(NULL); +// TODO(mgbellemare): Why are these static? +static std::unique_ptr theOSystem; +static std::unique_ptr theSettings; static ALEController* createController(OSystem* osystem, std::string type) { if(type.empty()){ @@ -77,7 +78,7 @@ int main(int argc, char* argv[]) { // Create the game controller std::string controller_type = theOSystem->settings().getString("game_controller"); - std::auto_ptr controller(createController(theOSystem.get(), controller_type)); + std::unique_ptr controller(createController(theOSystem.get(), controller_type)); controller->run(); diff --git a/atari_py/ale_interface/src/module.mk b/atari_py/ale_interface/src/module.mk new file mode 100644 index 0000000..eaf33fc --- /dev/null +++ b/atari_py/ale_interface/src/module.mk @@ -0,0 +1,11 @@ +MODULE := src/ + +MODULE_OBJS := \ + src/main.o \ + src/ale_interface.o + +MODULE_DIRS += \ + src/ + +# Include common rules +include $(srcdir)/common.rules diff --git a/atari_py/ale_interface/src/os_dependent/module.mk b/atari_py/ale_interface/src/os_dependent/module.mk new file mode 100644 index 0000000..d6adcef --- /dev/null +++ b/atari_py/ale_interface/src/os_dependent/module.mk @@ -0,0 +1,12 @@ +MODULE := src/os_dependent + +MODULE_OBJS := \ + src/os_dependent/FSNodePOSIX.o \ + src/os_dependent/OSystemUNIX.o \ + src/os_dependent/SettingsUNIX.o \ + +MODULE_DIRS += \ + src/os_dependent + +# Include common rules +include $(srcdir)/common.rules diff --git a/atari_py/ale_python_interface.py b/atari_py/ale_python_interface.py index 01fe094..a807c3f 100644 --- a/atari_py/ale_python_interface.py +++ b/atari_py/ale_python_interface.py @@ -12,10 +12,10 @@ if os.name == 'posix': ale_lib = cdll.LoadLibrary(os.path.join(os.path.dirname(__file__), - 'ale_interface/build/libale_c.so')) + 'ale_interface/libale_c.so')) else: ale_lib = cdll.LoadLibrary(os.path.join(os.path.dirname(__file__), - 'ale_interface/build/ale_c.dll')) + 'ale_interface/ale_c.dll')) ale_lib.ALE_new.argtypes = None ale_lib.ALE_new.restype = c_void_p @@ -45,6 +45,18 @@ ale_lib.game_over.restype = c_bool ale_lib.reset_game.argtypes = [c_void_p] ale_lib.reset_game.restype = None +ale_lib.getAvailableModes.argtypes = [c_void_p, c_void_p] +ale_lib.getAvailableModes.restype = None +ale_lib.getAvailableModesSize.argtypes = [c_void_p] +ale_lib.getAvailableModesSize.restype = c_int +ale_lib.setMode.argtypes = [c_void_p, c_int] +ale_lib.setMode.restype = None +ale_lib.getAvailableDifficulties.argtypes = [c_void_p, c_void_p] +ale_lib.getAvailableDifficulties.restype = None +ale_lib.getAvailableDifficultiesSize.argtypes = [c_void_p] +ale_lib.getAvailableDifficultiesSize.restype = c_int +ale_lib.setDifficulty.argtypes = [c_void_p, c_int] +ale_lib.setDifficulty.restype = None ale_lib.getLegalActionSet.argtypes = [c_void_p, c_void_p] ale_lib.getLegalActionSet.restype = None ale_lib.getLegalActionSize.argtypes = [c_void_p] @@ -157,6 +169,36 @@ def getMinimalActionSet(self): ale_lib.getMinimalActionSet(self.obj, as_ctypes(act)) return act + def getAvailableModes(self): + modes_size = ale_lib.getAvailableModesSize(self.obj) + modes = np.zeros((modes_size), dtype=np.intc) + ale_lib.getAvailableModes(self.obj, as_ctypes(modes)) + return modes + + def setMode(self, mode): + ale_lib.setMode(self.obj, int(mode)) + + def getAvailableDifficulties(self): + difficulties_size = ale_lib.getAvailableDifficultiesSize(self.obj) + difficulties = np.zeros((difficulties_size), dtype=np.intc) + ale_lib.getAvailableDifficulties(self.obj, as_ctypes(difficulties)) + return difficulties + + def setDifficulty(self, difficulty): + ale_lib.setDifficulty(self.obj, int(difficulty)) + + def getLegalActionSet(self): + act_size = ale_lib.getLegalActionSize(self.obj) + act = np.zeros((act_size), dtype=np.intc) + ale_lib.getLegalActionSet(self.obj, as_ctypes(act)) + return act + + def getMinimalActionSet(self): + act_size = ale_lib.getMinimalActionSize(self.obj) + act = np.zeros((act_size), dtype=np.intc) + ale_lib.getMinimalActionSet(self.obj, as_ctypes(act)) + return act + def getFrameNumber(self): return ale_lib.getFrameNumber(self.obj) @@ -206,7 +248,6 @@ def getScreenRGB(self, screen_data=None): ale_lib.getScreenRGB(self.obj, as_ctypes(screen_data[:])) return screen_data - def getScreenRGB2(self, screen_data=None): """This function fills screen_data with the data in RGB format. screen_data MUST be a numpy array of uint8. This can be initialized like so: diff --git a/atari_py/package_data.txt b/atari_py/package_data.txt index 7ef7864..7dddf3b 100644 --- a/atari_py/package_data.txt +++ b/atari_py/package_data.txt @@ -1,6 +1,5 @@ -ale_interface/build/libale_c.so -ale_interface/build/ale_c.dll -ale_interface/build/ale +ale_interface/libale_c.so +ale_interface/ale_c.dll ale_c_wrapper.cpp ale_c_wrapper.h ale_interface/CMakeLists.txt @@ -28,12 +27,14 @@ ale_interface/src/common/VideoModeList.hxx ale_interface/src/common/display_screen.cpp ale_interface/src/common/display_screen.h ale_interface/src/common/misc_tools.h +ale_interface/src/common/module.mk ale_interface/src/common/stella.png ale_interface/src/common/stella.xpm ale_interface/src/controllers/ale_controller.cpp ale_interface/src/controllers/ale_controller.hpp ale_interface/src/controllers/fifo_controller.cpp ale_interface/src/controllers/fifo_controller.hpp +ale_interface/src/controllers/module.mk ale_interface/src/controllers/rlglue_controller.cpp ale_interface/src/controllers/rlglue_controller.hpp ale_interface/src/emucore/AtariVox.cxx @@ -134,6 +135,7 @@ ale_interface/src/emucore/TIASnd.cxx ale_interface/src/emucore/TIASnd.hxx ale_interface/src/emucore/m6502/Copyright.txt ale_interface/src/emucore/m6502/License.txt +ale_interface/src/emucore/m6502/module.mk ale_interface/src/emucore/m6502/src/Device.cxx ale_interface/src/emucore/m6502/src/Device.hxx ale_interface/src/emucore/m6502/src/M6502.cxx @@ -154,6 +156,7 @@ ale_interface/src/emucore/m6502/src/System.hxx ale_interface/src/emucore/m6502/src/bspf/Copyright.txt ale_interface/src/emucore/m6502/src/bspf/License.txt ale_interface/src/emucore/m6502/src/bspf/src/bspf.hxx +ale_interface/src/emucore/module.mk ale_interface/src/emucore/rsynth/COPYING ale_interface/src/emucore/rsynth/Elements.def ale_interface/src/emucore/rsynth/PORTING @@ -163,6 +166,7 @@ ale_interface/src/emucore/rsynth/darray.h ale_interface/src/emucore/rsynth/elements.c ale_interface/src/emucore/rsynth/holmes.c ale_interface/src/emucore/rsynth/kmap +ale_interface/src/emucore/rsynth/module.mk ale_interface/src/emucore/rsynth/opsynth.c ale_interface/src/emucore/rsynth/phfeat.h ale_interface/src/emucore/rsynth/phones.c @@ -176,25 +180,28 @@ ale_interface/src/emucore/rsynth/trie.c ale_interface/src/emucore/rsynth/trie.h ale_interface/src/emucore/rsynth/useconfig.h ale_interface/src/emucore/stella.pro -ale_interface/src/emucore/unzip.c -ale_interface/src/emucore/unzip.h ale_interface/src/environment/ale_ram.hpp ale_interface/src/environment/ale_screen.hpp ale_interface/src/environment/ale_state.cpp ale_interface/src/environment/ale_state.hpp +ale_interface/src/environment/module.mk ale_interface/src/environment/phosphor_blend.cpp ale_interface/src/environment/phosphor_blend.hpp ale_interface/src/environment/stella_environment.cpp ale_interface/src/environment/stella_environment.hpp +ale_interface/src/environment/stella_environment_wrapper.cpp +ale_interface/src/environment/stella_environment_wrapper.hpp ale_interface/src/external/TinyMT/LICENSE.txt ale_interface/src/external/TinyMT/tinymt32.c ale_interface/src/external/TinyMT/tinymt32.h +ale_interface/src/external/module.mk ale_interface/src/games/RomSettings.cpp ale_interface/src/games/RomSettings.hpp ale_interface/src/games/RomUtils.cpp ale_interface/src/games/RomUtils.hpp ale_interface/src/games/Roms.cpp ale_interface/src/games/Roms.hpp +ale_interface/src/games/module.mk ale_interface/src/games/supported/Adventure.cpp ale_interface/src/games/supported/Adventure.hpp ale_interface/src/games/supported/AirRaid.cpp @@ -237,6 +244,8 @@ ale_interface/src/games/supported/Defender.cpp ale_interface/src/games/supported/Defender.hpp ale_interface/src/games/supported/DemonAttack.cpp ale_interface/src/games/supported/DemonAttack.hpp +ale_interface/src/games/supported/DonkeyKong.cpp +ale_interface/src/games/supported/DonkeyKong.hpp ale_interface/src/games/supported/DoubleDunk.cpp ale_interface/src/games/supported/DoubleDunk.hpp ale_interface/src/games/supported/ElevatorAction.cpp @@ -247,8 +256,12 @@ ale_interface/src/games/supported/FishingDerby.cpp ale_interface/src/games/supported/FishingDerby.hpp ale_interface/src/games/supported/Freeway.cpp ale_interface/src/games/supported/Freeway.hpp +ale_interface/src/games/supported/Frogger.cpp +ale_interface/src/games/supported/Frogger.hpp ale_interface/src/games/supported/Frostbite.cpp ale_interface/src/games/supported/Frostbite.hpp +ale_interface/src/games/supported/Galaxian.cpp +ale_interface/src/games/supported/Galaxian.hpp ale_interface/src/games/supported/Gopher.cpp ale_interface/src/games/supported/Gopher.hpp ale_interface/src/games/supported/Gravitar.cpp @@ -265,12 +278,24 @@ ale_interface/src/games/supported/Kaboom.cpp ale_interface/src/games/supported/Kaboom.hpp ale_interface/src/games/supported/Kangaroo.cpp ale_interface/src/games/supported/Kangaroo.hpp +ale_interface/src/games/supported/KeystoneKapers.cpp +ale_interface/src/games/supported/KeystoneKapers.hpp +ale_interface/src/games/supported/Kingkong.cpp +ale_interface/src/games/supported/Kingkong.hpp +ale_interface/src/games/supported/Koolaid.cpp +ale_interface/src/games/supported/Koolaid.hpp ale_interface/src/games/supported/Krull.cpp ale_interface/src/games/supported/Krull.hpp ale_interface/src/games/supported/KungFuMaster.cpp ale_interface/src/games/supported/KungFuMaster.hpp +ale_interface/src/games/supported/LaserGates.cpp +ale_interface/src/games/supported/LaserGates.hpp +ale_interface/src/games/supported/LostLuggage.cpp +ale_interface/src/games/supported/LostLuggage.hpp ale_interface/src/games/supported/MontezumaRevenge.cpp ale_interface/src/games/supported/MontezumaRevenge.hpp +ale_interface/src/games/supported/MrDo.cpp +ale_interface/src/games/supported/MrDo.hpp ale_interface/src/games/supported/MsPacman.cpp ale_interface/src/games/supported/MsPacman.hpp ale_interface/src/games/supported/NameThisGame.cpp @@ -295,6 +320,8 @@ ale_interface/src/games/supported/RoboTank.cpp ale_interface/src/games/supported/RoboTank.hpp ale_interface/src/games/supported/Seaquest.cpp ale_interface/src/games/supported/Seaquest.hpp +ale_interface/src/games/supported/SirLancelot.cpp +ale_interface/src/games/supported/SirLancelot.hpp ale_interface/src/games/supported/Skiing.cpp ale_interface/src/games/supported/Skiing.hpp ale_interface/src/games/supported/Solaris.cpp @@ -305,8 +332,14 @@ ale_interface/src/games/supported/StarGunner.cpp ale_interface/src/games/supported/StarGunner.hpp ale_interface/src/games/supported/Tennis.cpp ale_interface/src/games/supported/Tennis.hpp +ale_interface/src/games/supported/Tetris.cpp +ale_interface/src/games/supported/Tetris.hpp ale_interface/src/games/supported/TimePilot.cpp ale_interface/src/games/supported/TimePilot.hpp +ale_interface/src/games/supported/Trondead.cpp +ale_interface/src/games/supported/Trondead.hpp +ale_interface/src/games/supported/Turmoil.cpp +ale_interface/src/games/supported/Turmoil.hpp ale_interface/src/games/supported/Tutankham.cpp ale_interface/src/games/supported/Tutankham.hpp ale_interface/src/games/supported/UpNDown.cpp @@ -322,6 +355,7 @@ ale_interface/src/games/supported/YarsRevenge.hpp ale_interface/src/games/supported/Zaxxon.cpp ale_interface/src/games/supported/Zaxxon.hpp ale_interface/src/main.cpp +ale_interface/src/module.mk ale_interface/src/os_dependent/FSNodePOSIX.cxx ale_interface/src/os_dependent/FSNodeWin32.cxx ale_interface/src/os_dependent/OSystemUNIX.cxx @@ -332,6 +366,7 @@ ale_interface/src/os_dependent/SettingsUNIX.cxx ale_interface/src/os_dependent/SettingsUNIX.hxx ale_interface/src/os_dependent/SettingsWin32.cxx ale_interface/src/os_dependent/SettingsWin32.hxx +ale_interface/src/os_dependent/module.mk atari_ntsc_rgb_palette.h atari_roms/adventure.bin atari_roms/air_raid.bin diff --git a/win_build.sh b/win_build.sh index 493e7bc..4e62d12 100644 --- a/win_build.sh +++ b/win_build.sh @@ -9,7 +9,7 @@ mkdir -p atari_py/ale_interface/build cd atari_py/ale_interface/build cmake -DCMAKE_GENERATOR_PLATFORM=x64 .. cmake --build . -cp Debug/ale_c.dll . +cp Debug/ale_c.dll ../ cd ../../../ pip install wheel && pip wheel . -w wheelhouse --no-deps -vvv