L4 Operations
Git workflow
The repository's own rules are a short commit-message rule and an optional set of git hooks.
Pull requests follow the 50/72 rule: subject under 50 characters, blank line, body wrapped at 72 (Contributing.md). The DevTeam's optional setup (perl DEVEL/nhgitset.pl) installs hooks and the nhadd and nhcommit aliases that expand $NHDT-...$ header lines; nothing breaks if you skip them (DEVEL/Developer.txt). The hooks and nhsub are described in DEVEL/hooksdir/ and git_recipes.txt. The public repositories are on GitHub and SourceForge (README). Source files carry $NHDT-Date$ style header lines; do not hand-edit them.
Setup
A tty build needs a C compiler, make and, on Unix, a hints file; Lua is vendored.
The Unix route (sys/unix/NewInstall.unx):
cd sys/unix
sh setup.sh hints/linux.501 # or hints/macOS.501, hints/bsd.501
cd ../..
make all
make install
setup.sh writes Makefile, dat/Makefile, doc/Makefile, src/Makefile and util/Makefile. After a failed build, make spotless removes generated files. make install deletes and recreates the playground directory, so save the record, logfile and sysconf files first.
Interfaces are chosen on the make line: make WANT_WIN_TTY=1 WANT_WIN_CURSES=1 WANT_WIN_X11=1 all (sys/unix/README.hints). Windows: sys/windows/build-vs.txt, build-msys2.txt, build-nmake.txt. Other platforms: Porting, Cross-compiling, sys/*/Install.*. submodules/ is empty until the PDCurses submodules are fetched.
Testing
There is no unit-test suite; CI only builds, and the Lua tests run by hand in wizard mode.
- CI (
azure-pipelines.yml): Visual Studio and MinGW builds, Linux full and minimal builds, a macOS build, an MS-DOS cross-build, and the Guidebook. It builds; it does not run the game or the Lua tests (from reading the file, not from a CI run). - Lua tests (
test/README.md): build without DLB, install, copytest/*.luainto the playground, start in wizard mode and run#wizloadluaon a file. The tests check level scripting (test_des.lua,test_sel.lua), objects, shops and wishes. - Not covered by anything: combat and monster behaviour, save compatibility, the window ports' drawing.
sys/libnh/test/has tests for the library build.
Debugging
Wizard mode and a few build flags are the main tools.
- Wizard mode: start with
-D, allowed only for users in theWIZARDSline ofsysconf(doc/nethack.txt,sys/unix/sysconf). Explore mode is-X. - Wizard commands are in
src/wizcmds.c;sanity_check()runs each turn when the wizard-onlysanity_checkoption is set (it checks monsters, worn slots, vision blocking and level connectivity), and the debug fuzzer (#debugfuzzer,iflags.debug_fuzzer) drives the game with random input; commands that exit or block are flaggedNOFUZZERCMD. Whether the fuzzer runs in CI is unverified. impossible()reports internal inconsistencies without ending the game;panic()ends it. Therecoverutility rebuilds a game from level files after a crash (needsINSURANCE,include/config.h).- From Lua:
nh.debug_flagscan turn off monster generation and hunger (doc/lua.adoc). - Unverified: crash report and panic trace options (
NOCRASHREPORT,NOPANICTRACEappear in the CI file andutilmakefile).
Change recipes
Most changes touch a table plus one or two other places; the list below says which.
- Add a monster species: entry in
include/monsters.h(keep its class contiguous, fill indifficultyby hand, keep the dragon order); tile art inwin/share/monsters.txt(unverified that a missing tile fails the build); mention indat/data.baseif it has lore; fixes note indoc/fixes5-0-1.txt. - Add an object kind: entry in
include/objects.h(kinds are grouped by class; the position is theotyp, so insertion shifts later kinds and changes the meaning of old saves); checkobj_shuffle_rangeinsrc/o_init.cif it has a shuffled appearance; tile art inwin/share/objects.txt. - Add a command: row in
extcmdlist[]insrc/cmd.cand the handler. Decide the flags (IFBURIED,NOFUZZERCMD,AUTOCOMPLETE,CMD_M_PREFIX,WIZMODECMD) and returnECMD_TIMEwhen it takes time. The row's description feeds#?; whetherdat/hhanddat/cmdhelpalso need a line is unverified. Updatedoc/Guidebook.mn. - Add an option: entry in
include/optlist.h, a variable inflags(saved; may needEDITLEVELraised) oriflags, anoptfn_<name>()insrc/options.cunless it is a plain boolean, the short help,dat/opthelpand the Guidebooks. Check that its abbreviation does not shadow an existing option. Steps indoc/options.txt. - Add a special level: a Lua file in
dat/and an entry indat/dungeon.lua; if C code must recognise it, an entry inlevel_map[]insrc/dungeon.c; add the file toSPEC_LEVSinsys/unix/Makefile.topor it is not installed. A level may be flipped at random unless it setsnoflip. - Add a source file: list it in
sys/unix/Makefile.src(HACKCSRC, the object list and the dependency lines) and the other platform build files (sys/windows/, Xcode project); a file listed in only one build breaks the others. Also add it toFiles. - Add a window port: implement
struct window_procsperdoc/window.txt, give it awp_id ininclude/winprocs.h, and register it inwinchoices[]insrc/windows.c. - Add a saved global: put it in an
sv*group ininclude/decl.hand add a matching write and read insrc/save.candsrc/restore.c; the group alone saves nothing. RaiseEDITLEVELininclude/patchlevel.hif saved data changes shape. - Add a sound library or effect: see the Sound module; a library touches the enum, the registry,
src/mdlib.cand the build files. - Add a field to
struct monstorstruct obj: if it holds a timer, add it tomon_catchup_elapsed_time(); if it must not be copied on a split, add it tosplitobj; optional structures follow the recipes ininclude/mextra.handinclude/obj.h. - Record every player-visible fix in
doc/fixes5-0-1.txt.
Unverified: this list was derived from reading the Makefiles and headers, not from making the changes.
Deployment
Releases are source distributions made by the DevTeam; the repository has no release scripts.
sys/unix/Makefile.top has targets for building a distribution tree (package, distrib, manpages). Version numbers live in include/patchlevel.h and DEVEL/VERSION. Unverified: the DevTeam's actual release procedure is not documented in the repository.