You feel a wrenching sensation.
Play now at nethack.games
NetHack is a 46-year-old roguelike: 442,901 lines of C and Lua that have accumulated layers of intricate and ingenious gameplay rules. It is famous for permadeath: one little mistake can be fatal, and there is no taking it back. This does make it fun, but it can also be a hard game to walk into cold, a game you can only learn by dying, and dying, and dying…
The Teleport edition is designed as a sandbox for learning and exploring the game without permadeath. It is a port of NetHack to JavaScript that runs directly in the browser and plays bit-exactly like the original. But what we’ve added here are some new tools for learning:
Since it has no permadeath, nethack.games will never be a replacement for nethack.alt.org. Here high scores are not authoritative, and savescumming is totally allowed. You can use it to make your own speedrun, to learn how to play, or test a strategy.
Go to nethack.games to play in any browser; there is nothing to install and no account to make. Start a game, share a link to play with someone, and open the companion when you want to look something up.
The hamburger menu (☰) also runs a few other programs from the same era:
hack — Jay Fenlason’s Hack (1982)rogue — Michael Toy’s Rogue (1980)basic — BASIC interpreterlogo — Logo turtle graphicsI have been porting NetHack to JavaScript with a swarm of AI coding agents, as best I know how. The reason is that I do not know whether AI agents can reproduce a 442,901-line C and Lua codebase faithfully, bugs and all, and I wanted to find out.
The work is checked by deterministic replay: record a C NetHack session under a fixed PRNG seed, capturing every random number call, game event, and screen; replay the same keystrokes in JavaScript under the same seed; and compare the three, step for step. Where they diverge, I find the first divergence, read the C, and fix the JavaScript. The engine now matches most of the recorded sessions exactly. The commit timeline tracks parity across every commit.
This is my second attempt. An earlier one, Menace, taught me a lot about the codebase and about working with agents; AGENTS.md is where I wrote down what I learned — commit discipline, debugging techniques, and the ways agents tend to go wrong.
Teleport also runs as a public contest on the same question. Fork teleport-contest and write your own JavaScript port of NetHack, by any method. Every push is scored against public sessions in your own GitHub Actions, and an official judge re-scores all forks against the full public and held-out suite every two hours, updating the leaderboard.
js/modal_guard.js)
enforces C’s single-threaded contract — game code cannot fire during a
modal waitSee docs/DECISIONS.md for the full design rationale.
# Serve locally (no build step needed)
python3 -m http.server 8080
open http://localhost:8080
# Check JS-vs-C parity (three-channel report)
node scripts/pes-report.mjs
# Record a C reference session
cd test/comparison/c-harness && bash setup.sh
python3 run_session.py --seed 42| Document | Contents |
|---|---|
| docs/DECISIONS.md | Design decisions with rationale |
| multiplayer/README.md | Running the multiplayer relay + client |
| docs/SESSION_FORMAT.md | Session file format reference |
| docs/LORE.md | Porting lessons and debugging techniques |
| docs/CODEMATCH.md | Function-by-function C-to-JS porting tracker |
| docs/EVENTS.md | Game event logging system |
| docs/CONVENTIONS.md | C-to-JS translation conventions |
| docs/GAMESTATE.md | Global game state structure |
| docs/MONSTERS.md | Monster system architecture |
| docs/COMBAT.md | Combat system porting notes |
| docs/VISION.md | Vision and line-of-sight system |
| yendorbound/README.md | The Yendorbound Agent: autonomous NetHack play, architecture, and evaluation |
| AGENTS.md | Agent instructions and methodology |
modal_guard.js throws if game code fires during a modal
wait.NetHack is distributed under the NetHack General Public License. This JavaScript port is a derivative work under the same license.