Skip to content

NetHackLearningEnvironment

Dennis Lee edited this page Sep 14, 2026 · 1 revision

title: NetHack Learning Environment (NLE) radar_quadrant: Tools radar_ring: Assess radar_position: inner

NetHack Learning Environment (NLE)

The NetHack Learning Environment (NLE) is a research harness, originally built by Meta AI (FAIR), for running reinforcement-learning agents against the roguelike game NetHack. It is installed with pip install nle (latest release v1.3.0) and exposes the game as a Gymnasium environment. It bundles NetHack version 3.6.7, a materially older version than the current standalone NetHack release (5.0.0) -- the two are unrelated programs that happen to share ancestry, not interchangeable installs. Installing NLE does not touch, replace, or otherwise interact with a standalone NetHack install on the same machine; the two coexist with no shared code path.

Radar Assessment

Anyone building an agent to actually play NetHack faces a basic design choice: read the game by capturing and parsing its terminal screen, or read it through a purpose-built API. NLE takes the second path. It patches the NetHack game engine itself so that each step returns the game's internal state directly as structured data, rather than a block of text that then has to be re-interpreted.

Reading the environment's source confirms the shape of that data. Each observation is a dictionary containing, among other fields, glyphs (a grid of the dungeon's visual symbols as numeric codes), blstats (the player's stats line: health, hunger, position, and similar), message (the game's current text message), and a family of inv_* arrays covering inventory letters, item classes, and item descriptions. A raw terminal rendering (tty_chars, tty_colors, tty_cursor) is also available for anyone who wants it, but it sits alongside the structured fields rather than being the only option. This means an agent can act on "what item is in slot b" or "what is my current hit-point total" as a direct array lookup, with no screen-scraping or text-parsing step in between.

The alternative some agent-building efforts reach for -- capturing a terminal session (for example with tmux) and parsing the resulting text -- carries gaps this closes. A captured screen has to be re-interpreted for meaning (the same symbol can represent different things depending on context), gives no natural signal for when the game has finished rendering a turn versus a mid-render or prompt state, and provides no episode or reward structure, seeding, or reproducibility controls of its own. It is also bound to real terminal rendering speed, where NLE runs the game as an in-process library at the throughput reinforcement-learning training needs. The one place terminal capture still wins is generality: it needs no patched engine or build toolchain, so it works against any text-based game, not only ones with a research API like NLE's.

NLE runs the game as a single in-process library rather than a separate program it talks to. NetHack's own game loop is compiled directly into a private shared library, with its usual terminal input/output swapped for a custom handoff that suspends the loop mid-turn and hands control to Python, then resumes it with the next action, using the same lightweight coroutine-switching mechanism (fcontext) end to end. There is no second "NetHack process" and no message-passing between two programs, which is what makes NLE fast enough for reinforcement-learning-scale stepping. It also means a crash inside the game engine takes the whole Python process down with it, and that a running episode cannot be paused and resumed the way an ordinary saved NetHack game can: NLE exposes no save/resume call today, and starting a new episode always begins a fresh game rather than checking for an existing save. NetHack's own save-and-restore logic already exists in the vendored source, so adding this is a contained change, not a rewrite, but it has not been verified end to end. Misuse of the API fails loudly rather than corrupting state silently: calling step before reset, or passing an oversized configuration string, raises a catchable error back in Python instead of crashing or producing a bad observation. Each Python environment instance also runs its own private copy of the library rather than sharing one, since NetHack keeps all its state in global variables, so running many environments in parallel means many small (roughly 1 MB) file copies rather than one shared process.

Beyond the harness mechanism, NLE deliberately changes a handful of NetHack's own gameplay behaviors to make runs reproducible for training and evaluation, which is worth knowing when comparing results to a human game or to plain NetHack: it lets a run fix the two random-number generators that separately drive gameplay outcomes and display-only randomness, optionally isolate dungeon-layout generation into its own seed so the same dungeon appears regardless of what the agent does beforehand, and optionally freeze real-world time-based effects (moon phase, Friday the 13th, day/night, midnight) that ordinarily depend on the wall-clock date rather than gameplay. None of this is available, or needed, in a normal human game of NetHack, where such variance is part of the game.

Configuration also works differently from standalone NetHack. A normal install reads player preferences from a ~/.nethackrc file at startup. NLE has no such file: options are instead passed as a Python list when the environment is constructed, and if none are given it falls back to a fixed built-in preset. That preset turns off bones files (the remains of a previous death that a normal game can load into a new one) and switches off the animation delay that has no purpose without a terminal to render to, among other defaults chosen for automated play rather than a person sitting at a keyboard. Save and lock files also live in a separate directory by default (~/nethackdir.nle, distinct from wherever a standalone install keeps its saves), so the two can run side by side, even under the same player name, without one's lock files blocking the other. That directory is treated as disposable scratch space rather than a real save: NLE typically starts each new episode fresh rather than preserving state between runs.

NLE originates from a NeurIPS 2020 paper and was maintained by Meta AI under facebookresearch/nle. That original repository is now archived. Development has moved to a community-maintained fork, NetHack-LE/nle, which as of September 2026 is actively pushed to and carries the same open issue count as the archived original, indicating continuity of maintenance rather than a stalled fork. Anyone adopting NLE today should point at the NetHack-LE/nle fork, not the archived Meta AI original.

The practical implication for an agent-building effort: if the goal is a NetHack-playing agent, NLE is the established foundation to build on rather than writing a custom terminal-capture layer. It gives frame-by-frame structured state for free, has an existing ecosystem (a language wrapper that turns observations into text, and a bundled large-scale dataset of recorded play), and its use in multiple published papers signals a shared, comparable interface for the research and hobbyist community. It has not yet been used first-hand in this radar owner's own work, which is why it sits at Assess rather than Trial.

A separate route worth naming: an agent's actions do not have to come from a trained model at all. Each observation can be converted to a text description (via the language wrapper) and handed one turn at a time to a general-purpose coding assistant with terminal access, such as Claude Code run in headless mode under an existing subscription, to choose the next move. Wiring this up is a shell-out per step -- print mode with a single-word response and no tool permissions needed for a text-in, text-out choice -- rather than a training integration: no API key, model training, or reward function required. The real constraint is throughput, not code: a subscription-backed call carries several seconds of latency and is bound by the plan's own rolling usage limits, so a NetHack episode running into the thousands of turns realistically caps this at a single watched playthrough, not anything resembling reinforcement-learning-scale stepping.

References

Clone this wiki locally