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.

Classic tty NetHack on a short terminal, then phonehack rising out of it: a Tourist, a herd of cats and the horde on the Plane of Fire

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.