phonehack
Table of Contents
phonehack is NetHack 5.0 rebuilt as a touch-native Android app. The unmodified NetHack core runs on-device; a Jetpack Compose UI drives it through a thin JNI shim and adds touch controls, an optional richer HUD, and an offline wiki.
What it is
- The real NetHack, on a phone. NetHack 5.0.0 (tag
NetHack-5.0.0_Released) compiled for Android with its own game logic intact - not a reimplementation. - Strictly non-cheating. The UI only ever surfaces what the player character could already perceive in the classic game. No hidden monster HP, to-hit rolls, trap locations, or unseen map. The combat feed, tile look-ups, and suggested actions are all gated on the core's own perception checks (see ARCHITECTURE).
- No telemetry, ads, or accounts. The app makes no background network calls. The single network path is a user-initiated wiki import from a URL you choose; everything else is fully offline.
- Open source. Per-component licensing summary below.
Design
- A clean, rebasable port. The native NetHack core is left untouched behind an
NGPL boundary. Integration goes through the shim windowport - the same
callback interface the official NetHack WebAssembly port uses - so our code
sits above the shim and the game sits below it. The carried patches
(
patches/) are build glue plus two tiny non-cheating event hooks; no game logic is edited. This keeps upstream bumps mechanical (see patches/README). Purist by default, extensible by choice. Every added UI layer is an individually-toggleable extension over the classic game. Three presets set them in bulk:
- Full - every HUD layer and touch affordance on.
- Classic - our overlays off, but the touch input aids kept (map taps, direction rose, haptics, control bars).
- Bare - Classic with the touch aids off too; on-screen control bars only.
The chrome also has a Feel: Bare Prompt (default, a spare shell) or TUI Frame (boxed terminal styling), orthogonal to the color theme.
- Two independent settings axes. NetHack's own rc options (autopickup, runmode, hilitepet, …) are one axis; our UI extensions are the other. They never bleed into each other. See ARCHITECTURE.
- A bundled offline wiki. The full build ships a compressed NetHackWiki snapshot browsable in-app with no network. The lean/F-Droid build omits it; you can import the same bundle later from a local zip or a URL.
Usage
Get it
- F-Droid - planned, not yet published. It will be the lean build (no bundled
wiki; import it in-app afterward). Reproducible-build metadata is already
staged (
fdroid/org.labich.phonehack.yml,fastlane/metadata/) and an offline build container proves the APK builds with no network access (build/container/). - Prebuilt APK download - TODO. No signed release is hosted yet; until one is, build it yourself (below). It is a single command.
- Build from source - the current path. One Gradle invocation produces a complete, installable APK:
git submodule update --init # pull the pinned NetHack core
cd android && ./gradlew assembleDebug # builds native libs + APK in one step
# APK: android/app/build/outputs/apk/debug/app-debug.apk
The Gradle build runs the native cross-compile automatically; it needs the Android NDK (version and overrides in BUILDING). Full flags, the partial/lean variants, and the test layers are there too.
Run it
Sideload the APK onto a device or emulator with adb:
adb install -r android/app/build/outputs/apk/debug/app-debug.apk
Then launch phonehack from the app drawer. On first run it unpacks the game data; after that it is fully offline. Backgrounding the app writes a blocking save checkpoint, so you can leave mid-game and resume from the start screen.
Play it
The start screen lists saved characters to Continue and a New game field. In game, the interaction model is:
- Move and travel. Tap a reachable tile to travel there; tap an adjacent tile to take one step. Drag to pan the map, pinch to zoom.
- Look things up. Long-press a map tile or an inventory item to open its offline-wiki article - the app never surfaces anything the classic game wouldn't show you.
- Run commands. The on-screen control bars carry the common keys and actions; Cmd opens a searchable palette that reaches every NetHack command by name, and xN repeats a command a chosen number of times.
- Aim. A direction rose answers "In what direction?" prompts; Fire and throw target the obvious foe directly when there is only one.
- Panels. Dedicated screens for the pack (rich inventory), Magic (spells and wands), Go to (travel to a remembered feature), the dungeon map/overview, and the player sheet (stats plus Enhance for weapon/spell skills).
- Tune it. Options holds the two settings axes - NetHack rc options and phonehack's own UI extensions - plus the Full/Classic/Bare presets, the Feel, and the color theme.
Everything phonehack adds is individually toggleable, so you can dial it from the full touch HUD down to a near-classic terminal and back.
Licensing
phonehack combines original code with separately-licensed upstreams. The dividing line is the JNI boundary: everything above it (our Kotlin/Compose app) is our original work; everything at or below it that touches NetHack internals stays under the NetHack General Public License.
| Component | Path | License |
|---|---|---|
| phonehack UI + build tooling (our code) | android/.../org/labich/phonehack/*.kt, build/* |
GPL-2.0-or-later |
| JNI shim (NetHack-derived) | android/app/src/main/cpp/nethack_jni.c |
NetHack GPL (NGPL) |
| NetHack patches | patches/*.patch |
NetHack GPL (NGPL) |
| NetHack core | upstream/ (submodule, tag NetHack-5.0.0_Released) |
NetHack GPL (NGPL) |
| Lua interpreter | third_party/lua-5.4.8/ |
MIT |
| NetHackWiki offline bundle (full build only) | android/app/src/wiki/assets/wiki/ |
CC-BY-SA-3.0 |
We do not sublicense NetHack: our own UI/tooling is GPL-2.0-or-later (chosen to
minimize friction with the older NGPL), and NetHack plus its derived glue are
redistributed under the NGPL verbatim. Full texts and the per-file plan are in
LICENSES/ and LICENSE.
Status
Rev0 - a fully playable sideloadable APK - is complete; the touch-UI and
extensions layer is in active development, backed by four test layers (a
JVM/Compose unit suite, an instrumented Compose smoke test, an off-device native
save-integrity harness, and an on-device end-to-end harness). The build history
and the running feature log live in CHANGELOG.org in the repository.
Documentation
- BUILDING.org - toolchain, Gradle flags, the native cross-compile, and how to run (and verify) each test layer.
- ARCHITECTURE.org - the shim boundary, the non-cheating invariant, the settings model, saves, and tests.
- patches/README.org - what each carried patch does and how to rebase the stack onto a new NetHack release.
CHANGELOG.org(repository only) - the port's build phases and notable shipped features.LICENSES/README.md- the full licensing map and SPDX plan.