NHEMO — NetHack Expert Machine Operator
An automated NetHack 3.6.x player that reads the terminal screen, parses the game state, and makes decisions — just like a human player would, but faster and without getting distracted.
MVP goal: a bot that consistently reaches Minetown as a dwarven Valkyrie.
What NHEMO can do right now
NHEMO v0.1.0 covers dungeon exploration through level 4 of the workflow:
| Capability | Status |
|---|---|
| Connect to a live NetHack session via PTY | done |
| Read and parse the terminal screen | done |
| Navigate without walking into walls | done |
| Open and kick locked doors | done |
| Explore rooms systematically (A* pathfinding) | done |
| Descend stairs across multiple dungeon levels | done |
| Detect hunger and eat food from inventory | done |
| Monitor HP and wait in place to heal | done |
What it cannot do yet: fight monsters (it will flee or die), pick up items, remember previously visited levels, use knowledge about monsters or items, or consult an LLM. See CHANGELOG.md for a full capability breakdown by version.
Requirements
- Python 3.12+
- NetHack 3.6.x — the real ELF binary, not a shell wrapper.
Typical paths:
/usr/lib/nethack/nethack(Arch),/usr/games/nethack(Debian/Ubuntu)
Important: NHEMO must point at the actual setgid binary. Shell wrappers like
/usr/bin/nethackoverrideNETHACKOPTIONSand break the custom configuration.
Installation
pip install nhemo
# or, with uv:
uv add nhemo
Configuration
Create a config.yaml in your working directory before running:
nethack:
binary_path: "/usr/lib/nethack/nethack" # adjust for your distro
playground_dir: "/var/games/nethack"
player:
role: "Valkyrie"
race: "Dwarf"
alignment: "Neutral"
gender: "Female"
llm:
mode: "offline"
A fully annotated example with every available option is at
config.yaml.example.
Quick Start
# 30-turn smoke test
python -m nhemo
# Watch the bot play live
python -m nhemo --turns 500 --watch
# Slower watch mode, easier to follow
python -m nhemo --turns 500 --watch --delay 0.5
Watch mode display
Running with --watch renders the NetHack screen live, followed by NHEMO's
status line and a persistent message log:
This door is locked. <- row 0: game message
<- rows 1-21: dungeon map
--------
|....#.|
|......|
|......|
|......|
----.--- +
## @
# ##
...
-------.-------- #----.-
|..............| #|....|
|......$........#####|"....### ----------
|..............| #.....|#############..$$.....|
|..............|`####------ ##### |........|
---------------- ######|.<......|
----------
NHEMO the Stripling St:16 Dx:14 Co:17 In:8 Wi:12 Ch:8 Lawful
Dlvl:1 $:0 HP:18(18) Pw:1(1) AC:6 Xp:1/0 T:118
NHEMO turn 321 action: ---
-- message log --------------------------------------------------
t 314: This door is locked.
t 315: This door is locked.
t 316: This door is locked.
> t 321: This door is locked. <- most recent (bold >)
Observability
Logging
# Verbose per-turn decisions
python -m nhemo --turns 200 --watch --log-level DEBUG
# Capture to file (logging goes to stderr, safe to combine with --watch)
python -m nhemo --turns 500 --log-level DEBUG 2>nhemo_debug.log
| Level | What you see |
|---|---|
WARNING (default) |
Parse failures, bot stuck and giving up |
INFO |
Level transitions, doors opened, stairs descended, food eaten |
DEBUG |
Every turn: position, visited tile count, chosen action and phase |
Decision event log
python -m nhemo --turns 200 --log-events /tmp/events.jsonl
Each turn emits one JSON line:
{"turn":42,"screen_mode":"NORMAL","action":"MOVE_E","phase":"pathfind","pos":[12,40],"hp":15,"max_hp":19,"dlvl":"Dlvl:3"}
Flags combine freely:
python -m nhemo --turns 500 --watch --log-events /tmp/events.jsonl --log-level DEBUG 2>nhemo_debug.log
How it works
NHEMO never reads NetHack's internals — it sees only what a human player sees on a terminal. Under the hood it has four layers: a PTY screen reader, a parser that turns raw screen output into structured game state, a behavior-tree decision engine, and a future LLM consultation layer.
Curious about the architecture? See CONTRIBUTING.md for the component overview, module breakdown, and design documents.
Roadmap
| Phase | Target |
|---|---|
| V5–V7 | Combat, item management, SQLite persistence, knowledge base |
| V8–V9 | LLM integration, full data-driven behavior tree |
| V10 | MVP: consistent Minetown arrival as dwarven Valkyrie |
| V11+ | Mines End, Sokoban, shop interaction, quest completion, ascension |
Contributing
See CONTRIBUTING.md.
License
Copyright (C) 2025 Javier Novoa C.
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
See LICENSE for the full text.
Metadata
Release files for nhemo 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| nhemo-0.1.2.tar.gz | 63.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| nhemo-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 131.6 kB
Release files / nhemo-0.1.2.tar.gz
| Download URL | nhemo-0.1.2.tar.gz |
|---|---|
| Size | 63.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
01929c23ad58b3ec966559c77d4cff44a7ff2b33e9fb323da4e8e9ccd04222d3
|
|
BLAKE2b-256 checksum How to use checksums |
55f38acb586f7a519d16d3d10542e0cc8c5502860dd56c30716b14784cdd168b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / nhemo-0.1.2-py3-none-any.whl
| Download URL | nhemo-0.1.2-py3-none-any.whl |
|---|---|
| Size | 68.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
762f6a64d42bda755b1c2a168f6fe3f99a6e0249b5a746ff2915f2da67e26c04
|
|
BLAKE2b-256 checksum How to use checksums |
d7dcd941280516f0d34863f79327d80105170093816197c8f4568725736eddcb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|