From 61ab65fad6046d913c314aaa94fa950818dc8490 Mon Sep 17 00:00:00 2001 From: Stephen Oman Date: Sun, 2 Feb 2025 10:54:28 +0000 Subject: [PATCH 01/13] rename nleobs to nletypes --- .github/workflows/lint_cc.yml | 2 +- doc/nle/ARCHITECTURE.md | 4 ++-- include/nle.h | 2 +- include/nledl.h | 2 +- include/{nleobs.h => nletypes.h} | 6 +++--- win/rl/winrl.cc | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) rename include/{nleobs.h => nletypes.h} (98%) diff --git a/.github/workflows/lint_cc.yml b/.github/workflows/lint_cc.yml index e903c6b78..7be8ff2c6 100644 --- a/.github/workflows/lint_cc.yml +++ b/.github/workflows/lint_cc.yml @@ -15,5 +15,5 @@ jobs: - uses: DoozyX/clang-format-lint-action@v0.12 with: source: win/rl src/nle.c sys/unix/nledl.c include/nle.h include/nledl.h - include/nleobs.h + include/nletypes.h clangFormatVersion: 12 diff --git a/doc/nle/ARCHITECTURE.md b/doc/nle/ARCHITECTURE.md index c29ee995e..b5af502cd 100644 --- a/doc/nle/ARCHITECTURE.md +++ b/doc/nle/ARCHITECTURE.md @@ -72,7 +72,7 @@ user. - **part of `libnethack.so`** - **key directories & files** [`src/nle.c`](https://github.com/heiner/nle/blob/main/src/nle.c), [`include/nle.h`](https://github.com/heiner/nle/blob/main/include/nle.h), -[`include/nleobs.h`](https://github.com/heiner/nle/blob/main/include/nleobs.h) +[`include/nletypes.h`](https://github.com/heiner/nle/blob/main/include/nletypes.h) * In our case the user “playing” the game is not a terminal, but ultimately a @@ -116,7 +116,7 @@ user.: * a struct that contains the stack type and the two contexts (`return_context`, `generator_context`) which are the user and nethack-stack contexts respectively. - * `nle_obs from include/nleobs.h` + * `nle_obs from include/nletypes.h` * a struct that contains the observations transferred between the two stacks/contexts diff --git a/include/nle.h b/include/nle.h index e18fe2bc0..c6ef990a0 100644 --- a/include/nle.h +++ b/include/nle.h @@ -7,7 +7,7 @@ #include -#include "nleobs.h" +#include "nletypes.h" /* TODO: Fix this. */ #undef SIG_RET_TYPE diff --git a/include/nledl.h b/include/nledl.h index b55bcac37..e5e53496e 100644 --- a/include/nledl.h +++ b/include/nledl.h @@ -7,7 +7,7 @@ #include -#include "nleobs.h" +#include "nletypes.h" typedef struct nledl_ctx { char dlpath[1024]; diff --git a/include/nleobs.h b/include/nletypes.h similarity index 98% rename from include/nleobs.h rename to include/nletypes.h index df84ca2fd..cf80ab947 100644 --- a/include/nleobs.h +++ b/include/nletypes.h @@ -1,6 +1,6 @@ -#ifndef NLEOBS_H -#define NLEOBS_H +#ifndef NLETYPES_H +#define NLETYPES_H #define NLE_MESSAGE_SIZE 256 #define NLE_BLSTATS_SIZE 27 @@ -100,4 +100,4 @@ typedef struct nle_settings { char ttyrecname[4096]; } nle_settings; -#endif /* NLEOBS_H */ +#endif /* NLETYPES_H */ diff --git a/win/rl/winrl.cc b/win/rl/winrl.cc index c3c04d99d..f3159ba44 100644 --- a/win/rl/winrl.cc +++ b/win/rl/winrl.cc @@ -20,7 +20,7 @@ extern "C" { } extern "C" { -#include "nleobs.h" +#include "nletypes.h" } #define USE_DEBUG_API 0 From 0899632265eb28b2822cc2a7580d49a18ad681a8 Mon Sep 17 00:00:00 2001 From: Stephen Oman Date: Wed, 5 Feb 2025 11:00:59 +0000 Subject: [PATCH 02/13] Move type definitions to nletypes.h --- CMakeLists.txt | 5 ++++- include/nle.h | 21 --------------------- include/nletypes.h | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 22 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e2e28d390..e418c3f73 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -139,7 +139,10 @@ target_link_libraries(nethack PUBLIC m fcontext bz2_static tmt) # dlopen wrapper library add_library(nethackdl STATIC "sys/unix/nledl.c") -target_include_directories(nethackdl PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) +target_include_directories( + nethackdl + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_CURRENT_SOURCE_DIR}/third_party/deboost.context/include) target_link_libraries(nethackdl PUBLIC dl) # rlmain C++ (test) binary diff --git a/include/nle.h b/include/nle.h index c6ef990a0..22f6419a4 100644 --- a/include/nle.h +++ b/include/nle.h @@ -13,27 +13,6 @@ #undef SIG_RET_TYPE #define SIG_RET_TYPE void (*)(int) -typedef struct TMT TMT; - -typedef struct nle_globals { - fcontext_stack_t stack; - fcontext_t returncontext; - fcontext_t generatorcontext; - - FILE *ttyrec; - TMT *vterminal; - char outbuf[BUFSIZ]; - char *outbuf_write_ptr; - char *outbuf_write_end; - -#ifdef NLE_BZ2_TTYRECS - void *ttyrec_bz2; -#endif - - boolean done; - nle_obs *observation; -} nle_ctx_t; - /* * Would like to annotate this with __thread, but that causes * the MacOS dynamic linker to not unload the library on dlclose(). diff --git a/include/nletypes.h b/include/nletypes.h index cf80ab947..7a8a756bb 100644 --- a/include/nletypes.h +++ b/include/nletypes.h @@ -2,6 +2,9 @@ #ifndef NLETYPES_H #define NLETYPES_H +#include +#include + #define NLE_MESSAGE_SIZE 256 #define NLE_BLSTATS_SIZE 27 #define NLE_PROGRAM_STATE_SIZE 6 @@ -45,6 +48,17 @@ /* #define NLE_ALLOW_SEEDING 1 */ /* Set in CMakeLists.txt if not disabled. */ /* #define NLE_USE_TILES 1 */ /* Set in CMakeLists.txt. */ +/* NetHack defines boolean as follows: + typedef xchar boolean; (global.h:80) + typedef schar xchar; (global.h:73) + typedef signed char schar; (config.h:420) + +So we'll do the same to avoid having to include all of NetHack's types +*/ +typedef signed char boolean; + +typedef struct TMT TMT; + typedef struct nle_observation { int action; int done; @@ -80,6 +94,25 @@ typedef struct { #endif } nle_seeds_init_t; +typedef struct nle_globals { + fcontext_stack_t stack; + fcontext_t returncontext; + fcontext_t generatorcontext; + + FILE *ttyrec; + TMT *vterminal; + char outbuf[BUFSIZ]; + char *outbuf_write_ptr; + char *outbuf_write_end; + +#ifdef NLE_BZ2_TTYRECS + void *ttyrec_bz2; +#endif + + boolean done; + nle_obs *observation; +} nle_ctx_t; + typedef struct nle_settings { /* * Path to NetHack's game files. From ab62465c423dc9f5f17a3be01de1fc6e514b9331 Mon Sep 17 00:00:00 2001 From: Stephen Oman Date: Thu, 13 Feb 2025 19:50:48 +0000 Subject: [PATCH 03/13] Add wheels fix to RNG branch (#49) --- .github/workflows/test_and_deploy.yml | 38 +++++++++++++++++---------- pyproject.toml | 6 +++-- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/.github/workflows/test_and_deploy.yml b/.github/workflows/test_and_deploy.yml index 2c384567c..96b08af28 100644 --- a/.github/workflows/test_and_deploy.yml +++ b/.github/workflows/test_and_deploy.yml @@ -115,21 +115,21 @@ jobs: build_wheels: name: Build wheels on Ubuntu needs: test_repo - runs-on: ubuntu-20.04 # Can be also run for macOS + runs-on: ${{ matrix.os }} # Can be also run for macOS + strategy: + matrix: + os: [ubuntu-latest, ubuntu-24.04-arm] steps: - uses: actions/checkout@v4 with: submodules: recursive - - name: Set up QEMU # Required for building manylinux aarch64 wheels on x86_64 - if: runner.os == 'Linux' - uses: docker/setup-qemu-action@v2 - with: - platforms: all - name: Build wheels if: github.event_name != 'release' uses: pypa/cibuildwheel@v2.19.2 # The main configuration is in pyproject.toml env: - CIBW_BUILD: "cp312-manylinux*" # Build only python 3.12 wheels for testing + # Build of cp312-manylinux_aarch64 wheels failing, so restrict + # to only building _x86_64 wheel + CIBW_BUILD: "cp312-manylinux_*" # Build only python 3.12 wheels for testing # Increase verbosity to see what's going on in the build in case of failure CIBW_BUILD_VERBOSITY: 3 CIBW_REPAIR_WHEEL_COMMAND_LINUX: > @@ -143,12 +143,12 @@ jobs: - name: Save wheels uses: actions/upload-artifact@v4 with: - name: python-wheels + name: python-wheels-${{ matrix.os }} path: ./wheelhouse/*.whl test_manylinux_3_12: name: Test manylinux wheel on Ubuntu w/ Py3.12 needs: build_wheels - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - name: Setup Python 3.12 env uses: actions/setup-python@v5 @@ -162,7 +162,7 @@ jobs: - name: Get wheels artifacts uses: actions/download-artifact@v4 with: - name: python-wheels + name: python-wheels-ubuntu-latest path: dist - name: Install from wheel # Install wheel mathcing the Python version and architecture run: | @@ -199,10 +199,15 @@ jobs: with: name: python-sdist path: dist - - name: Get wheels artifacts # Get wheels artifacts from the build_wheels job + - name: Get wheels artifacts # Get x86 wheels artifacts from the build_wheels job + uses: actions/download-artifact@v4 + with: + name: python-wheels-ubuntu-latest + path: dist + - name: Get wheels artifacts # Get aarch64 wheels artifacts from the build_wheels job uses: actions/download-artifact@v4 with: - name: python-wheels + name: python-wheels-ubuntu-24.04-arm path: dist - name: Report dist contents run: | @@ -240,10 +245,15 @@ jobs: with: name: python-sdist path: dist - - name: Get wheels artifacts # Get wheels artifacts from the build_wheels job + - name: Get wheels artifacts # Get x86 wheels artifacts from the build_wheels job + uses: actions/download-artifact@v4 + with: + name: python-wheels-ubuntu-latest + path: dist + - name: Get wheels artifacts # Get aarch64 wheels artifacts from the build_wheels job uses: actions/download-artifact@v4 with: - name: python-wheels + name: python-wheels-ubuntu-24.04-arm path: dist - name: Report dist contents run: | diff --git a/pyproject.toml b/pyproject.toml index bc06f322d..7ce4d46fd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,8 +56,10 @@ build = "cp{38,39,310,311,312}-manylinux*" # and install the dependencies using yum, as manylinux2014 image is CentOS 7-based before-all = "rm -rf {project}/build {project}/*.so {project}/CMakeCache.txt && yum install -y autoconf bison cmake flex git libtool" -# Only x86_64 and aarch64 (ARM) architectures are supported -archs = "x86_64 aarch64" +# Build for the architecure of the runner in the GitHub Actions workflow: +# ubuntu-20.04 -> x86_64 +# ubuntu-24.04-arm -> aarch64 +archs = "native" # Use manylinux2014 image for both x86_64 and aarch64 manylinux-x86_64-image = "manylinux2014" From 323cabd0d97ca436ee50ef77f8f30ea0dc05f1b2 Mon Sep 17 00:00:00 2001 From: Stephen Oman Date: Fri, 14 Feb 2025 16:26:45 +0000 Subject: [PATCH 04/13] Refactor RNG functions to new file structure --- include/nle.h | 3 --- include/nlernd.h | 17 +++++++++++++++ src/nle.c | 57 +++--------------------------------------------- src/nlernd.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 75 insertions(+), 57 deletions(-) create mode 100644 include/nlernd.h create mode 100644 src/nlernd.c diff --git a/include/nle.h b/include/nle.h index 22f6419a4..6c063fe40 100644 --- a/include/nle.h +++ b/include/nle.h @@ -23,7 +23,4 @@ nle_ctx_t *nle_start(nle_obs *, FILE *, nle_seeds_init_t *, nle_settings *); nle_ctx_t *nle_step(nle_ctx_t *, nle_obs *); void nle_end(nle_ctx_t *); -void nle_set_seed(nle_ctx_t *, unsigned long, unsigned long, boolean); -void nle_get_seed(nle_ctx_t *, unsigned long *, unsigned long *, boolean *); - #endif /* NLE_H */ diff --git a/include/nlernd.h b/include/nlernd.h new file mode 100644 index 000000000..88ecc88d5 --- /dev/null +++ b/include/nlernd.h @@ -0,0 +1,17 @@ +/* + +Set of functions to manipulate NetHack's Random Number Generators + +*/ + +#ifndef NLERND_H +#define NLERND_H + + +#include "nletypes.h" + + +void nle_set_seed(nle_ctx_t *, unsigned long, unsigned long, boolean); +void nle_get_seed(nle_ctx_t *, unsigned long *, unsigned long *, boolean *); + +#endif \ No newline at end of file diff --git a/src/nle.c b/src/nle.c index 933e958f2..b9e593ad5 100644 --- a/src/nle.c +++ b/src/nle.c @@ -14,6 +14,7 @@ #include "dlb.h" #include "nle.h" +#include "nlernd.h" #ifdef NLE_BZ2_TTYRECS #include @@ -31,6 +32,8 @@ extern int unixmain(int, char **); +extern nle_seeds_init_t *nle_seeds_init; + signed char vt_char_color_extract(TMTCHAR *c) { @@ -364,18 +367,6 @@ nle_spawn_monsters() return settings.spawn_monsters; } -nle_seeds_init_t *nle_seeds_init; - -/* See rng.c. */ -extern int FDECL(whichrng, (int FDECL((*fn), (int) ))); - -/* See hacklib.c. */ -extern int FDECL(set_random, (unsigned long, int FDECL((*fn), (int) ))); -/* An appropriate version of this must always be provided in - port-specific code somewhere. It returns a number suitable - as seed for the random number generator */ -extern unsigned long NDECL(sys_random_seed); - char * nle_getenv(const char *name) { @@ -399,23 +390,6 @@ nle_fopen_wizkit_file() return fmemopen(settings.wizkit, len, "r"); } -/* - * Initializes the random number generator. - * Originally in hacklib.c. - */ -void -init_random(int FDECL((*fn), (int) )) -{ -#ifdef NLE_ALLOW_SEEDING - if (nle_seeds_init) { - set_random(nle_seeds_init->seeds[whichrng(fn)], fn); - has_strong_rngseed = nle_seeds_init->reseed; - return; - } -#endif - set_random(sys_random_seed(), fn); -} - nle_ctx_t * nle_start(nle_obs *obs, FILE *ttyrec, nle_seeds_init_t *seed_init, nle_settings *settings_p) @@ -522,31 +496,6 @@ nle_end(nle_ctx_t *nle) free(nle); } -#ifdef NLE_ALLOW_SEEDING -void -nle_set_seed(nle_ctx_t *nle, unsigned long core, unsigned long disp, - boolean reseed) -{ - /* Keep up to date with rnglist[] in rnd.c. */ - set_random(core, rn2); - set_random(disp, rn2_on_display_rng); - - /* Determines logic in reseed_random() in hacklib.c. */ - has_strong_rngseed = reseed; -}; - -extern unsigned long nle_seeds[]; - -void -nle_get_seed(nle_ctx_t *nle, unsigned long *core, unsigned long *disp, - boolean *reseed) -{ - *core = nle_seeds[0]; - *disp = nle_seeds[1]; - *reseed = has_strong_rngseed; -} -#endif - /* From unixtty.c */ /* fatal error */ /*VARARGS1*/ diff --git a/src/nlernd.c b/src/nlernd.c new file mode 100644 index 000000000..30eb8661b --- /dev/null +++ b/src/nlernd.c @@ -0,0 +1,55 @@ +#include "nlernd.h" +#include "hack.h" + +/* See rng.c. */ +extern int FDECL(whichrng, (int FDECL((*fn), (int) ))); + +/* See hacklib.c. */ +extern int FDECL(set_random, (unsigned long, int FDECL((*fn), (int) ))); + +/* An appropriate version of this must always be provided in + port-specific code somewhere. It returns a number suitable + as seed for the random number generator */ +extern unsigned long NDECL(sys_random_seed); + +nle_seeds_init_t *nle_seeds_init; + +/* + * Initializes the random number generator. + * Originally in hacklib.c. + */ +void +init_random(int FDECL((*fn), (int) )) +{ +#ifdef NLE_ALLOW_SEEDING + if (nle_seeds_init) { + set_random(nle_seeds_init->seeds[whichrng(fn)], fn); + has_strong_rngseed = nle_seeds_init->reseed; + return; + } +#endif + set_random(sys_random_seed(), fn); +} + +void +nle_set_seed(nle_ctx_t *nle, unsigned long core, unsigned long disp, + boolean reseed) +{ + /* Keep up to date with rnglist[] in rnd.c. */ + set_random(core, rn2); + set_random(disp, rn2_on_display_rng); + + /* Determines logic in reseed_random() in hacklib.c. */ + has_strong_rngseed = reseed; +}; + +extern unsigned long nle_seeds[]; + +void +nle_get_seed(nle_ctx_t *nle, unsigned long *core, unsigned long *disp, + boolean *reseed) +{ + *core = nle_seeds[0]; + *disp = nle_seeds[1]; + *reseed = has_strong_rngseed; +} \ No newline at end of file From 04580a3348f2f20fafde0573efd976fe234cbdcc Mon Sep 17 00:00:00 2001 From: Stephen Oman Date: Sun, 23 Feb 2025 14:44:27 +0000 Subject: [PATCH 05/13] Move initial seed values into nle_settings --- .gitignore | 1 + include/nle.h | 2 +- include/nledl.h | 6 ++---- include/nletypes.h | 6 ++++++ src/nle.c | 8 +------- src/nlernd.c | 9 +++++---- sys/unix/nledl.c | 15 +++++++-------- sys/unix/rlmain.cc | 8 ++++---- win/rl/pynethack.cc | 20 ++++++++++---------- 9 files changed, 37 insertions(+), 38 deletions(-) diff --git a/.gitignore b/.gitignore index 97c052e6b..491094931 100644 --- a/.gitignore +++ b/.gitignore @@ -210,6 +210,7 @@ nle/nethackdir # CMake CMakeFiles CMakeCache.txt +CMakePresets.json # cibuildwheel wheelhouse/ \ No newline at end of file diff --git a/include/nle.h b/include/nle.h index 6c063fe40..af6683822 100644 --- a/include/nle.h +++ b/include/nle.h @@ -19,7 +19,7 @@ */ nle_ctx_t *current_nle_ctx; -nle_ctx_t *nle_start(nle_obs *, FILE *, nle_seeds_init_t *, nle_settings *); +nle_ctx_t *nle_start(nle_obs *, FILE *, nle_settings *); nle_ctx_t *nle_step(nle_ctx_t *, nle_obs *); void nle_end(nle_ctx_t *); diff --git a/include/nledl.h b/include/nledl.h index e5e53496e..bbd1babc9 100644 --- a/include/nledl.h +++ b/include/nledl.h @@ -17,12 +17,10 @@ typedef struct nledl_ctx { FILE *ttyrec; } nledl_ctx; -nledl_ctx *nle_start(const char *, nle_obs *, FILE *, nle_seeds_init_t *, - nle_settings *); +nledl_ctx *nle_start(const char *, nle_obs *, FILE *, nle_settings *); nledl_ctx *nle_step(nledl_ctx *, nle_obs *); -void nle_reset(nledl_ctx *, nle_obs *, FILE *, nle_seeds_init_t *, - nle_settings *); +void nle_reset(nledl_ctx *, nle_obs *, FILE *, nle_settings *); void nle_end(nledl_ctx *); void nle_set_seed(nledl_ctx *, unsigned long, unsigned long, char); diff --git a/include/nletypes.h b/include/nletypes.h index 7a8a756bb..1020490fc 100644 --- a/include/nletypes.h +++ b/include/nletypes.h @@ -3,6 +3,7 @@ #define NLETYPES_H #include +#include #include #define NLE_MESSAGE_SIZE 256 @@ -89,6 +90,7 @@ typedef struct { #ifdef NLE_ALLOW_SEEDING unsigned long seeds[2]; /* core, disp */ char reseed; /* boolean: use NetHack's anti-TAS reseed mechanism? */ + bool use_init_seeds; /* bool to tell NLE if seeds were provided */ #else int _dummy; /* empty struct has size 0 in C, size 1 in C++ */ #endif @@ -131,6 +133,10 @@ typedef struct nle_settings { * Filename for nle's ttyrec*.bz2. */ char ttyrecname[4096]; + + /* Initial seeds for the RNGs */ + nle_seeds_init_t initial_seeds; + } nle_settings; #endif /* NLETYPES_H */ diff --git a/src/nle.c b/src/nle.c index b9e593ad5..2c12b0493 100644 --- a/src/nle.c +++ b/src/nle.c @@ -32,8 +32,6 @@ extern int unixmain(int, char **); -extern nle_seeds_init_t *nle_seeds_init; - signed char vt_char_color_extract(TMTCHAR *c) { @@ -391,8 +389,7 @@ nle_fopen_wizkit_file() } nle_ctx_t * -nle_start(nle_obs *obs, FILE *ttyrec, nle_seeds_init_t *seed_init, - nle_settings *settings_p) +nle_start(nle_obs *obs, FILE *ttyrec, nle_settings *settings_p) { /* Set CO and LI to control ttyrec output size. */ CO = NLE_TERM_CO; @@ -401,7 +398,6 @@ nle_start(nle_obs *obs, FILE *ttyrec, nle_seeds_init_t *seed_init, settings = *settings_p; nle_ctx_t *nle = init_nle(ttyrec, obs); - nle_seeds_init = seed_init; nle->stack = create_fcontext_stack(STACK_SIZE); nle->generatorcontext = @@ -412,8 +408,6 @@ nle_start(nle_obs *obs, FILE *ttyrec, nle_seeds_init_t *seed_init, nle->generatorcontext = t.ctx; nle->done = (t.data == NULL); obs->done = nle->done; - nle_seeds_init = - NULL; /* Don't set to *these* seeds on subsequent reseeds, if any. */ if (nle->ttyrec) { if (obs->blstats) { diff --git a/src/nlernd.c b/src/nlernd.c index 30eb8661b..5a419f744 100644 --- a/src/nlernd.c +++ b/src/nlernd.c @@ -12,7 +12,8 @@ extern int FDECL(set_random, (unsigned long, int FDECL((*fn), (int) ))); as seed for the random number generator */ extern unsigned long NDECL(sys_random_seed); -nle_seeds_init_t *nle_seeds_init; +/* NLE settings contains the initial RNG seeds */ +extern nle_settings settings; /* * Initializes the random number generator. @@ -22,9 +23,9 @@ void init_random(int FDECL((*fn), (int) )) { #ifdef NLE_ALLOW_SEEDING - if (nle_seeds_init) { - set_random(nle_seeds_init->seeds[whichrng(fn)], fn); - has_strong_rngseed = nle_seeds_init->reseed; + if (settings.initial_seeds.use_init_seeds) { + set_random(settings.initial_seeds.seeds[whichrng(fn)], fn); + has_strong_rngseed = settings.initial_seeds.reseed; return; } #endif diff --git a/sys/unix/nledl.c b/sys/unix/nledl.c index 53de50263..bce3beb32 100644 --- a/sys/unix/nledl.c +++ b/sys/unix/nledl.c @@ -7,8 +7,7 @@ #include "nledl.h" void -nledl_init(nledl_ctx *nledl, nle_obs *obs, nle_seeds_init_t *seed_init, - nle_settings *settings) +nledl_init(nledl_ctx *nledl, nle_obs *obs, nle_settings *settings) { void *handle = dlopen(nledl->dlpath, RTLD_LAZY | RTLD_NOLOAD); if (handle) { @@ -28,9 +27,9 @@ nledl_init(nledl_ctx *nledl, nle_obs *obs, nle_seeds_init_t *seed_init, dlerror(); /* Clear any existing error */ - void *(*start)(nle_obs *, FILE *, nle_seeds_init_t *, nle_settings *); + void *(*start)(nle_obs *, FILE *, nle_settings *); start = dlsym(nledl->dlhandle, "nle_start"); - nledl->nle_ctx = start(obs, nledl->ttyrec, seed_init, settings); + nledl->nle_ctx = start(obs, nledl->ttyrec, settings); char *error = dlerror(); if (error != NULL) { @@ -65,14 +64,14 @@ nledl_close(nledl_ctx *nledl) nledl_ctx * nle_start(const char *dlpath, nle_obs *obs, FILE *ttyrec, - nle_seeds_init_t *seed_init, nle_settings *settings) + nle_settings *settings) { /* TODO: Consider getting ttyrec path from caller? */ struct nledl_ctx *nledl = malloc(sizeof(struct nledl_ctx)); nledl->ttyrec = ttyrec; strncpy(nledl->dlpath, dlpath, sizeof(nledl->dlpath)); - nledl_init(nledl, obs, seed_init, settings); + nledl_init(nledl, obs, settings); return nledl; }; @@ -93,7 +92,7 @@ nle_step(nledl_ctx *nledl, nle_obs *obs) * E.g., we could re-use the stack buffer and the nledl_ctx. */ void nle_reset(nledl_ctx *nledl, nle_obs *obs, FILE *ttyrec, - nle_seeds_init_t *seed_init, nle_settings *settings) + nle_settings *settings) { nledl_close(nledl); /* Reset file only if not-NULL. */ @@ -102,7 +101,7 @@ nle_reset(nledl_ctx *nledl, nle_obs *obs, FILE *ttyrec, // TODO: Consider refactoring nledl.h such that we expose this init // function but drop reset. - nledl_init(nledl, obs, seed_init, settings); + nledl_init(nledl, obs, settings); } void diff --git a/sys/unix/rlmain.cc b/sys/unix/rlmain.cc index c4efcf65f..79f7dcda9 100644 --- a/sys/unix/rlmain.cc +++ b/sys/unix/rlmain.cc @@ -47,7 +47,7 @@ play(nledl_ctx *nle, nle_obs *obs, nle_settings *settings) std::cout << std::endl; read(STDIN_FILENO, &obs->action, 1); if (obs->action == 'r') - nle_reset(nle, obs, nullptr, nullptr, settings); + nle_reset(nle, obs, nullptr, settings); nle = nle_step(nle, obs); } } @@ -78,7 +78,7 @@ randgame(nledl_ctx *nle, nle_obs *obs, const int no_episodes, for (int i = 0; i < no_episodes; ++i) { randplay(nle, obs); if (i < no_episodes - 1) - nle_reset(nle, obs, nullptr, nullptr, settings); + nle_reset(nle, obs, nullptr, settings); } } @@ -119,12 +119,12 @@ main(int argc, char **argv) ScopedTC tc; nledl_ctx *nle = - nle_start("libnethack.so", &obs, ttyrec.get(), nullptr, &settings); + nle_start("libnethack.so", &obs, ttyrec.get(), &settings); if (argc > 1 && argv[1][0] == 'r') { randgame(nle, &obs, 3, &settings); } else { play(nle, &obs, &settings); - nle_reset(nle, &obs, nullptr, nullptr, &settings); + nle_reset(nle, &obs, nullptr, &settings); play(nle, &obs, &settings); } nle_end(nle); diff --git a/win/rl/pynethack.cc b/win/rl/pynethack.cc index 8d045683e..1ff5cdd38 100644 --- a/win/rl/pynethack.cc +++ b/win/rl/pynethack.cc @@ -126,6 +126,8 @@ class Nethack if (found != std::string::npos && found + 1 < ttyrec.length()) strncpy(settings_.ttyrecname, &ttyrec.c_str()[found + 1], ttyrec.length() - found - 1); + + settings_.initial_seeds.use_init_seeds = false; } Nethack(std::string dlpath, std::string hackdir, @@ -275,10 +277,10 @@ class Nethack set_initial_seeds(unsigned long core, unsigned long disp, bool reseed) { #ifdef NLE_ALLOW_SEEDING - seed_init_.seeds[0] = core; - seed_init_.seeds[1] = disp; - seed_init_.reseed = reseed; - use_seed_init = true; + settings_.initial_seeds.seeds[0] = core; + settings_.initial_seeds.seeds[1] = disp; + settings_.initial_seeds.reseed = reseed; + settings_.initial_seeds.use_init_seeds = true; #else throw std::runtime_error("Seeding not enabled"); #endif @@ -344,14 +346,14 @@ class Nethack if (!ttyrec) strncpy(settings_.ttyrecname, "", sizeof(settings_.ttyrecname)); + bool *seeded = &(settings_.initial_seeds.use_init_seeds); if (!nle_) { nle_ = nle_start(dlpath_.c_str(), &obs_, ttyrec ? ttyrec : ttyrec_, - use_seed_init ? &seed_init_ : nullptr, &settings_); + &settings_); } else - nle_reset(nle_, &obs_, ttyrec, - use_seed_init ? &seed_init_ : nullptr, &settings_); - use_seed_init = false; + nle_reset(nle_, &obs_, ttyrec, &settings_); + *seeded = false; /* Once the seeds have been used, prevent them being reused. */ if (obs_.done) throw std::runtime_error("NetHack done right after reset"); @@ -360,8 +362,6 @@ class Nethack std::string dlpath_; nle_obs obs_; std::vector py_buffers_; - nle_seeds_init_t seed_init_; - bool use_seed_init = false; nledl_ctx *nle_ = nullptr; std::FILE *ttyrec_ = nullptr; nle_settings settings_; From ace3bf525392fd22e2f48a9c671b67f71ce51d67 Mon Sep 17 00:00:00 2001 From: Stephen Oman Date: Sun, 23 Feb 2025 19:14:18 +0000 Subject: [PATCH 06/13] Remove compile-time seeding directives --- CMakeLists.txt | 9 --------- include/nletypes.h | 5 ----- nle/tests/test_envs.py | 11 +---------- nle/tests/test_nethack.py | 5 ----- nle/tests/test_profile.py | 2 -- src/nlernd.c | 6 ++---- sys/unix/nledl.c | 2 -- win/rl/pynethack.cc | 19 ------------------- 8 files changed, 3 insertions(+), 56 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e418c3f73..9bfdcc61d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,15 +64,6 @@ add_compile_definitions( NOCWD_ASSUMPTIONS NLE_USE_TILES) -option(USE_SEEDING "Use seeding support in NLE" ON) - -if(USE_SEEDING) - add_compile_definitions(NLE_ALLOW_SEEDING) - message("Seeding enabled.") -else() - message("Seeding disabled.") -endif() - set(NLE_SRC ${nle_SOURCE_DIR}/src) set(NLE_INC ${nle_SOURCE_DIR}/include) set(NLE_DAT ${nle_SOURCE_DIR}/dat) diff --git a/include/nletypes.h b/include/nletypes.h index 1020490fc..0957747c2 100644 --- a/include/nletypes.h +++ b/include/nletypes.h @@ -46,7 +46,6 @@ #define NLE_BL_CONDITION 25 /* condition bit mask */ #define NLE_BL_ALIGN 26 -/* #define NLE_ALLOW_SEEDING 1 */ /* Set in CMakeLists.txt if not disabled. */ /* #define NLE_USE_TILES 1 */ /* Set in CMakeLists.txt. */ /* NetHack defines boolean as follows: @@ -87,13 +86,9 @@ typedef struct nle_observation { } nle_obs; typedef struct { -#ifdef NLE_ALLOW_SEEDING unsigned long seeds[2]; /* core, disp */ char reseed; /* boolean: use NetHack's anti-TAS reseed mechanism? */ bool use_init_seeds; /* bool to tell NLE if seeds were provided */ -#else - int _dummy; /* empty struct has size 0 in C, size 1 in C++ */ -#endif } nle_seeds_init_t; typedef struct nle_globals { diff --git a/nle/tests/test_envs.py b/nle/tests/test_envs.py index b81267ff5..f37197a91 100644 --- a/nle/tests/test_envs.py +++ b/nle/tests/test_envs.py @@ -259,8 +259,6 @@ def test_rollout_no_archive(self, env_name, rollout_len): def test_seed_interface_output(self, env_name, rollout_len): """Tests whether env.seed output can be reused correctly.""" - if not nethack.NLE_ALLOW_SEEDING: - return # Nothing to test. if env_name.startswith("NetHackChallenge"): pytest.skip("Not running seed test on NetHackChallenge") @@ -277,8 +275,6 @@ def test_seed_interface_output(self, env_name, rollout_len): def test_seed_rollout_seeded(self, env_name, rollout_len): """Tests that two seeded envs return same step data.""" - if not nethack.NLE_ALLOW_SEEDING: - return # Nothing to test. if env_name.startswith("NetHackChallenge"): pytest.skip("Not running seed test on NetHackChallenge") @@ -302,8 +298,6 @@ def test_seed_rollout_seeded(self, env_name, rollout_len): def test_seed_rollout_seeded_int(self, env_name, rollout_len): """Tests that two seeded envs return same step data.""" - if not nethack.NLE_ALLOW_SEEDING: - return # Nothing to test. if env_name.startswith("NetHackChallenge"): pytest.skip("Not running seed test on NetHackChallenge") @@ -468,9 +462,6 @@ def test_no_seed_setting(self): RuntimeError, match="NetHackChallenge doesn't allow seed changes" ): env.unwrapped.seed() + with pytest.raises(RuntimeError, match="Should not try changing seeds"): env.unwrapped.nethack.set_initial_seeds(0, 0, True) - - if not nethack.NLE_ALLOW_SEEDING: - with pytest.raises(RuntimeError, match="Seeding not enabled"): - env.unwrapped.nethack._pynethack.set_initial_seeds(0, 0, True) diff --git a/nle/tests/test_nethack.py b/nle/tests/test_nethack.py index 620a35665..16c0ee19c 100644 --- a/nle/tests/test_nethack.py +++ b/nle/tests/test_nethack.py @@ -119,8 +119,6 @@ def test_several_nethacks(self, game): game1.close() def test_set_initial_seeds(self): - if not nethack.NLE_ALLOW_SEEDING: - return # Nothing to test. game = nethack.Nethack(copy=True) game.set_initial_seeds(core=42, disp=666) obs0 = game.reset() @@ -135,9 +133,6 @@ def test_set_initial_seeds(self): game.close() def test_set_seed_after_reset(self, game): - if not nethack.NLE_ALLOW_SEEDING: - return # Nothing to test. - game.reset() # Could fail on a system without a good source of randomness: assert game.get_current_seeds()[2] is True diff --git a/nle/tests/test_profile.py b/nle/tests/test_profile.py index 897887d2c..c30e499bb 100644 --- a/nle/tests/test_profile.py +++ b/nle/tests/test_profile.py @@ -55,8 +55,6 @@ def test_run_1k_steps(self, observation_keys, benchmark): actions = np.random.choice(env.action_space.n, size=steps) def seed(): - if not nle.nethack.NLE_ALLOW_SEEDING: - return nonlocal seeds seeds += 1 env.unwrapped.seed(seeds, 2 * seeds) diff --git a/src/nlernd.c b/src/nlernd.c index 5a419f744..c15b24afa 100644 --- a/src/nlernd.c +++ b/src/nlernd.c @@ -22,14 +22,12 @@ extern nle_settings settings; void init_random(int FDECL((*fn), (int) )) { -#ifdef NLE_ALLOW_SEEDING if (settings.initial_seeds.use_init_seeds) { set_random(settings.initial_seeds.seeds[whichrng(fn)], fn); has_strong_rngseed = settings.initial_seeds.reseed; - return; + } else { + set_random(sys_random_seed(), fn); } -#endif - set_random(sys_random_seed(), fn); } void diff --git a/sys/unix/nledl.c b/sys/unix/nledl.c index bce3beb32..0f0b1a572 100644 --- a/sys/unix/nledl.c +++ b/sys/unix/nledl.c @@ -111,7 +111,6 @@ nle_end(nledl_ctx *nledl) free(nledl); } -#ifdef NLE_ALLOW_SEEDING void nle_set_seed(nledl_ctx *nledl, unsigned long core, unsigned long disp, char reseed) @@ -148,4 +147,3 @@ nle_get_seed(nledl_ctx *nledl, unsigned long *core, unsigned long *disp, */ get_seed(nledl->nle_ctx, core, disp, reseed); } -#endif diff --git a/win/rl/pynethack.cc b/win/rl/pynethack.cc index 1ff5cdd38..dfb3f0684 100644 --- a/win/rl/pynethack.cc +++ b/win/rl/pynethack.cc @@ -276,32 +276,23 @@ class Nethack void set_initial_seeds(unsigned long core, unsigned long disp, bool reseed) { -#ifdef NLE_ALLOW_SEEDING settings_.initial_seeds.seeds[0] = core; settings_.initial_seeds.seeds[1] = disp; settings_.initial_seeds.reseed = reseed; settings_.initial_seeds.use_init_seeds = true; -#else - throw std::runtime_error("Seeding not enabled"); -#endif } void set_seeds(unsigned long core, unsigned long disp, bool reseed) { -#ifdef NLE_ALLOW_SEEDING if (!nle_) throw std::runtime_error("set_seed called without reset()"); nle_set_seed(nle_, core, disp, reseed); -#else - throw std::runtime_error("Seeding not enabled"); -#endif } std::tuple get_seeds() { -#ifdef NLE_ALLOW_SEEDING if (!nle_) throw std::runtime_error("get_seed called without reset()"); std::tuple result; @@ -311,9 +302,6 @@ class Nethack &reseed); std::get<2>(result) = reseed; return result; -#else - throw std::runtime_error("Seeding not enabled"); -#endif } boolean @@ -448,13 +436,6 @@ PYBIND11_MODULE(_pynethack, m) mn.attr("NLE_BL_CONDITION") = py::int_(NLE_BL_CONDITION); mn.attr("NLE_BL_ALIGN") = py::int_(NLE_BL_ALIGN); - mn.attr("NLE_ALLOW_SEEDING") = -#ifdef NLE_ALLOW_SEEDING - true; -#else - false; -#endif - /* NetHack constants. */ mn.attr("ROWNO") = py::int_(ROWNO); mn.attr("COLNO") = py::int_(COLNO); From 0774fd26994a7dccdba75504960d2057337ba565 Mon Sep 17 00:00:00 2001 From: Stephen Oman Date: Sun, 23 Feb 2025 19:22:56 +0000 Subject: [PATCH 07/13] Remove temporary comment --- .github/workflows/test_and_deploy.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/test_and_deploy.yml b/.github/workflows/test_and_deploy.yml index 96b08af28..e8fd94e4b 100644 --- a/.github/workflows/test_and_deploy.yml +++ b/.github/workflows/test_and_deploy.yml @@ -127,8 +127,6 @@ jobs: if: github.event_name != 'release' uses: pypa/cibuildwheel@v2.19.2 # The main configuration is in pyproject.toml env: - # Build of cp312-manylinux_aarch64 wheels failing, so restrict - # to only building _x86_64 wheel CIBW_BUILD: "cp312-manylinux_*" # Build only python 3.12 wheels for testing # Increase verbosity to see what's going on in the build in case of failure CIBW_BUILD_VERBOSITY: 3 From c6e73f459ce567ced2ea7c4072f84d17e3767734 Mon Sep 17 00:00:00 2001 From: Stephen Oman Date: Sun, 23 Feb 2025 20:08:03 +0000 Subject: [PATCH 08/13] Add new files to C linter --- .github/workflows/lint_cc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint_cc.yml b/.github/workflows/lint_cc.yml index 7be8ff2c6..70590d54b 100644 --- a/.github/workflows/lint_cc.yml +++ b/.github/workflows/lint_cc.yml @@ -15,5 +15,5 @@ jobs: - uses: DoozyX/clang-format-lint-action@v0.12 with: source: win/rl src/nle.c sys/unix/nledl.c include/nle.h include/nledl.h - include/nletypes.h + include/nletypes.h include/nlernd.h src/nlernd.c clangFormatVersion: 12 From 6e425ca2d8520a5758ac5712abb7b1a80830cc4b Mon Sep 17 00:00:00 2001 From: Stephen Oman Date: Mon, 24 Feb 2025 11:55:42 +0000 Subject: [PATCH 09/13] Lock GitHub Actions ruff version to same as pre-commit --- .github/workflows/lint_python.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint_python.yml b/.github/workflows/lint_python.yml index 8db5dce92..881078fad 100644 --- a/.github/workflows/lint_python.yml +++ b/.github/workflows/lint_python.yml @@ -15,7 +15,7 @@ jobs: with: python-version: '3.12' - uses: actions/checkout@v4 - - run: pip install -q uv && uv pip install --system ruff isort + - run: pip install -q uv && uv pip install --system ruff==0.4.3 isort - run: ruff format --check --diff . - run: ruff check - run: isort -c --diff nle/ From e5cab8bc3e6f4ae807d4ca629803024e5617ff5d Mon Sep 17 00:00:00 2001 From: Stephen Oman Date: Mon, 24 Feb 2025 12:12:59 +0000 Subject: [PATCH 10/13] Pin Python version for clang linter --- .github/workflows/lint_cc.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/lint_cc.yml b/.github/workflows/lint_cc.yml index 70590d54b..d3ae5088a 100644 --- a/.github/workflows/lint_cc.yml +++ b/.github/workflows/lint_cc.yml @@ -11,6 +11,9 @@ jobs: name: clang-format runs-on: ubuntu-latest steps: + - uses: actions/setup-python@v5 + with: + python-version: '3.11' - uses: actions/checkout@v4 - uses: DoozyX/clang-format-lint-action@v0.12 with: From ae7684bd600a4070b07fd73ca93a7317e1569510 Mon Sep 17 00:00:00 2001 From: Stephen Oman Date: Mon, 24 Feb 2025 12:17:07 +0000 Subject: [PATCH 11/13] Switch to newer DoozyX/clang-format-lint-action to fix disutils issue --- .github/workflows/lint_cc.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/lint_cc.yml b/.github/workflows/lint_cc.yml index d3ae5088a..9726ca18b 100644 --- a/.github/workflows/lint_cc.yml +++ b/.github/workflows/lint_cc.yml @@ -11,11 +11,8 @@ jobs: name: clang-format runs-on: ubuntu-latest steps: - - uses: actions/setup-python@v5 - with: - python-version: '3.11' - uses: actions/checkout@v4 - - uses: DoozyX/clang-format-lint-action@v0.12 + - uses: DoozyX/clang-format-lint-action@v0.18.2 with: source: win/rl src/nle.c sys/unix/nledl.c include/nle.h include/nledl.h include/nletypes.h include/nlernd.h src/nlernd.c From 57cb5dac89a415e1313da32d5100ef2c46cc53b8 Mon Sep 17 00:00:00 2001 From: Stephen Oman Date: Mon, 24 Feb 2025 12:25:23 +0000 Subject: [PATCH 12/13] Linter format fixes --- include/nlernd.h | 2 -- include/nletypes.h | 8 ++++---- win/rl/pynethack.cc | 8 ++++---- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/include/nlernd.h b/include/nlernd.h index 88ecc88d5..1ddb896d8 100644 --- a/include/nlernd.h +++ b/include/nlernd.h @@ -7,10 +7,8 @@ Set of functions to manipulate NetHack's Random Number Generators #ifndef NLERND_H #define NLERND_H - #include "nletypes.h" - void nle_set_seed(nle_ctx_t *, unsigned long, unsigned long, boolean); void nle_get_seed(nle_ctx_t *, unsigned long *, unsigned long *, boolean *); diff --git a/include/nletypes.h b/include/nletypes.h index 0957747c2..4d7f72714 100644 --- a/include/nletypes.h +++ b/include/nletypes.h @@ -2,9 +2,9 @@ #ifndef NLETYPES_H #define NLETYPES_H -#include -#include #include +#include +#include #define NLE_MESSAGE_SIZE 256 #define NLE_BLSTATS_SIZE 27 @@ -46,13 +46,13 @@ #define NLE_BL_CONDITION 25 /* condition bit mask */ #define NLE_BL_ALIGN 26 -/* #define NLE_USE_TILES 1 */ /* Set in CMakeLists.txt. */ +/* #define NLE_USE_TILES 1 */ /* Set in CMakeLists.txt. */ /* NetHack defines boolean as follows: typedef xchar boolean; (global.h:80) typedef schar xchar; (global.h:73) typedef signed char schar; (config.h:420) - + So we'll do the same to avoid having to include all of NetHack's types */ typedef signed char boolean; diff --git a/win/rl/pynethack.cc b/win/rl/pynethack.cc index dfb3f0684..876edc1cf 100644 --- a/win/rl/pynethack.cc +++ b/win/rl/pynethack.cc @@ -336,12 +336,12 @@ class Nethack bool *seeded = &(settings_.initial_seeds.use_init_seeds); if (!nle_) { - nle_ = - nle_start(dlpath_.c_str(), &obs_, ttyrec ? ttyrec : ttyrec_, - &settings_); + nle_ = nle_start(dlpath_.c_str(), &obs_, + ttyrec ? ttyrec : ttyrec_, &settings_); } else nle_reset(nle_, &obs_, ttyrec, &settings_); - *seeded = false; /* Once the seeds have been used, prevent them being reused. */ + *seeded = false; /* Once the seeds have been used, prevent them being + reused. */ if (obs_.done) throw std::runtime_error("NetHack done right after reset"); From 3b8f69bf009d6140bd427be344fa1ce76fe03ccd Mon Sep 17 00:00:00 2001 From: Stephen Oman Date: Mon, 24 Feb 2025 12:43:45 +0000 Subject: [PATCH 13/13] Aaaarrgh, remove space before to make fussy Linter happy --- win/rl/pynethack.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/win/rl/pynethack.cc b/win/rl/pynethack.cc index 876edc1cf..8f7a71f8b 100644 --- a/win/rl/pynethack.cc +++ b/win/rl/pynethack.cc @@ -340,7 +340,7 @@ class Nethack ttyrec ? ttyrec : ttyrec_, &settings_); } else nle_reset(nle_, &obs_, ttyrec, &settings_); - *seeded = false; /* Once the seeds have been used, prevent them being + *seeded = false; /* Once the seeds have been used, prevent them being reused. */ if (obs_.done)