NetHack 3D lets you play classic NetHack in a fully interactive 3D dungeon.
Play in browser: https://jamesiv4.github.io/nethack-3d/
Note: The macOS desktop build is packaged as an unsigned DMG from GitHub Actions.
On first launch, macOS may ask you to right-click the app and choose Open.
On iPhone/iPad, open the play link in Safari, tap the Share button, then tap Add to Home Screen.
Launch it from your Home Screen for a web app fullscreen experience.
- Download the latest Linux release from the Releases page.
- Copy
NetHack 3D <version>.AppImagefromrelease/to your Linux machine. - Add the AppImage directly to Steam using "Add Non-Steam Game to My Library".
- Keep Steam compatibility/proton disabled for this native Linux launch path.
- Linux launch option notes:
--windowed: launch in a normal framed window instead of fullscreen.--borderless: launch in a frameless non-fullscreen window that covers the display without using native fullscreen mode.
- Recommended Steam Input profile tweak: Set left trackpad to Left Joystick, and trackpad click to the A button. Movement and common actions are very simple this way!
| Combat in the Gnomish Mines | Shatter monsters into pieces! |
|---|---|
| Multiple tile sets | Beautiful UI |
- Play NetHack in a 3D dungeon view while keeping core game rules and depth.
- Not a reimagining or rework, this is authentic NetHack in a 3D engine.
- Choose between playing NetHack 5.0, NetHack 3.6.7, and Slash'Em, with separate save states for each.
- Mix and match gameplay modes: classic top-down or first-person (FPS) modes with 3D ASCII, graphical tiles, or Vulture graphics, plus a true terminal view.
- Combat feedback effects: Monsters dynamically shatter into bloody pieces, different every time.
- Full sound support. Monsters die with a satisfying crunch.
- Customize sound to your liking and create your own sound packs directly in-game.
- Play on the couch with full controller support. Radial wheel for actions, move confirmation for careful roguelike navigation.
- Scalable minimap for level awareness, with NetHack 3D and terminal color schemes, a viewport box, and drag-to-center camera navigation.
- Optional floating damage/heal numbers, status changes, XP, blood mist, blood splatter, and more.
- Camera panning, rotation, and zoom for close inspection or a whole-level overview.
- Crisp 3D ASCII monsters and items are supported in addition to tiles, with NetHack 3D, Classic, and Terminal color schemes.
- Terminal mode renders the active runtime's exact glyphs, colors, symbol set, and tty highlighting in a sharp, zoomable grid with a dedicated message-log gutter.
- Native pet, item-pile, and standout highlighting is supported, including an overhead heart marker for pets.
- Optional smooth creature movement in Tiles and 3D ASCII modes; Terminal mode keeps authentic immediate cell updates.
- Built-in graphical tilesets: Vulture tiles, Absurdly Evil, DawnHack, NetHack Modern, Nevanda, PixelHack, RZTiles, and Vanilla NetHack Tiles.
- Upload and manage your own custom tilesets directly in-game.
- Tileset background removal tools built-in.
- Dynamic lighting around the player.
- Full HUD with level, health, power, stats, armor, gold, hunger, experience, time, and dungeon branch and depth.
- Vulture tiles mode simulates the isometric Vulture graphics style but in full 3D, including FPS support.
- Live message log plus on-screen message popups.
- Full mobile touch support (or even in desktop if you want).
- Beautiful menus: item category headers, keyboard tips, multi-pickup selection, and menu paging.
- Fast character start: random hero or create a character (name, role, race, gender, alignment), saved for your next run too.
- Customize your NetHack initialization options: explore mode, autopickup, pet names, native highlighting, and other advanced settings.
- Save and load your game. Perfect for long runs.
- Autofill on extended commands with
#so advanced playstyles are easy to manage, plus all commands available via buttons on mobile. - Desktop-friendly controls: keyboard-first with mouse support for map interaction and camera control.
- Mobile-friendly controls: tap/swipe movement, quick actions, extended command sheet, mobile log view, and FPS touch-look/touch-run gestures.
- Inventory context actions for common item interactions without typing command sequences.
- Options to tweaks just about everything to your liking.
npm inpm run dev- Open
http://localhost:5173/
npm run dev- Start Vite dev server.npm run build- Build production bundles.npm run build:electron- Build bundles with Electron-safe relative asset paths.npm run preview- Preview production build locally.npm run electron:dev- Run Electron against the Vite dev server.npm run electron:pack:mac- Build an unpacked macOS app bundle torelease/for local testing.npm run electron:dist:mac- Build a macOS DMG torelease/(pass-- --universalto produce a universal macOS build).npm run electron:dist:win- Build and package a Windows NSIS.exeinstaller (x64) torelease/.npm run electron:dist:win:portable- Build and package portable Windows.exefiles for x64 and legacy x86 torelease/; the 32-bit artifact ends in-legacy-x86.exe.npm run electron:dist:linux:appimage- Build and package a Linux AppImage (x64) torelease/(uses WSL automatically on Windows, stages Linux runtime deps, and includes Linux icon assets).npm run electron:dist:all- Build Electron assets once, then package the Windows setup, x64 and legacy x86 portable executables, and Linux AppImage back to back.npm run electron:dist:all:parallel- Same as above, but packages Windows and Linux at the same time after the shared Electron build.npm run android:add- Create the native Android project with Capacitor (run once).npm run android:sync- Build web assets and sync them into the Android project.npm run android:open- Open the Android project in Android Studio.npm run android:run- Build web assets and run on a connected Android device/emulator.npm run updates:package- Createbuild/client-updates/manifest.json+ build payload fromdist/for in-app client updates.npm run update- Build + package the latest client-update payload in one command.npm run glyphs:generate- Regenerate glyph catalog from runtime artifacts.npm run glyphs:check- Verify checked-in glyph catalog is up to date.
- Startup update checks are enabled for packaged Electron and Capacitor Android clients.
- The app reads
build/client-updates/manifest.json(orVITE_NH3D_UPDATE_MANIFEST_URLwhen set), prompts users when updates are available, and can download/apply the latest packaged web build. - Update payloads are generated by
scripts/updates/prepare-client-update.mjs, which copiesdist/intobuild/client-updates/latest/(rolling state) and writes SHA-verified file metadata. - Update channel switches live in
scripts/updates/channel-config.json:- Set
requireClientUpgradetotrueto force a full native client upgrade warning while still allowing web build download. - Use
clientUpgradeMessagefor custom upgrade guidance text shown in the startup update dialog.
- Set
- Update packaging is intentional/manual:
- Run
npm run updatewhen you want to prepare and publish a new online update from current source.
- Run
- Main app bootstrap/debug helpers:
src/app.ts - React entry:
src/main.tsx - React UI shell:
src/ui/App.tsx - 3D engine and client-side interaction:
src/game/Nethack3DEngine.ts - Glyph catalog + behavior rules:
src/game/glyphs/* - Runtime worker bridge:
src/runtime/WorkerRuntimeBridge.ts - Worker runtime host:
src/runtime/runtime-worker.ts - NetHack callback adapter/state machine:
src/runtime/LocalNetHackRuntime.ts
- NetHack 3.6.7 to 5.0 tile-order translation logic is adapted from
horlogeislux/tileto370(MIT License).
- Push this repo to GitHub.
- In repository settings, go to
Settings > Pages. - Set
SourcetoGitHub Actions. - Ensure your deploy branch matches
.github/workflows/deploy-gh-pages.yml(mainby default). - Push to
main(or run the workflow manually).
The workflow builds with Vite and deploys the dist/ folder.
.github/workflows/build-macos-electron.ymlbuilds the macOS Electron app onmacos-latest.- Manual runs upload the generated DMG as a workflow artifact and will also publish it when a matching release tag already exists.
- Tag pushes like
1.2.2also upload the macOS DMG to the matching GitHub Release.
