Skip to main content

license pipelines coverage

nwn-dg

Neverwinter Nights (nwn) dungeon generator: cli & api.

nwn-dg lays out rooms and corridors on a grid, carves them into a connected maze, then maps every cell onto a real NWN tileset. The result can be written as a playable area file, as a preview image, or as json for a running server to consume through SetTileJson().

Work in progress: in alpha/beta stage. Please refer to file POC.md for more information.

Installation

You can install the latest version from PyPI package repository.

pipx install nwn-dg

Building the pycairo dependency requires the cairo development headers. On Debian, install them with apt-get install libcairo2-dev beforehand.

Writing binary .are files additionally requires nwn_gff, from the neverwinter.nim tools. It is only needed for --output-are. On Debian 12 (Bookworm) and later, it is packaged as neverwinter.nim in the unofficial nwn.ovh repository:

source /etc/os-release
sudo wget https://debian.nwn.ovh/sources.list.d/${VERSION_CODENAME}.sources -O /etc/apt/sources.list.d/nwn-ovh.sources
sudo wget https://debian.nwn.ovh/nwn-ovh-archive.gpg -O /usr/share/keyrings/nwn-ovh-archive.gpg
sudo apt-get update
sudo apt-get install -y neverwinter.nim

Usage

Command line interface

Generate a dungeon and write a preview image:

nwn-dg --output-tileset tdc01 mydungeon

A more complete run, writing the area, the tile json and the random seed:

nwn-dg --seed mydungeon.seed --output-seed \
       --output-png --output-are --output-tile-json \
       --output-tileset tdc01 \
       --png-axes-ids --png-axes-base 0 --png-tileset-idx \
       mydungeon

The positional argument is a base filepath; each output appends its own extension to it.

Map size, room count and corridor shape are set through the --map-* options; --map-door-entrance and --map-door-exits place the stairs, taking N, E, S, W or X for random, one letter per door. Run nwn-dg --help for the full list and current defaults.

Options documented as "may cause generation failure" constrain the generator enough that no valid dungeon may exist for a given seed. nwn-dg exits with an error rather than returning a broken map; retry with another seed or different options.

In order to test generated outputs, it's possible to create the are file, and to copy it to the module folder in your toolset profile hierarchy. When area is closed and re-opened it should have the proper new layout.

Api

The generator is also exposed over https, so a live module can request a fresh dungeon through NWNX_HTTPClient instead of shipping pre-generated files.

Start the server:

nwn-dg-api --port 8080

Serving over tls, which is what a module reaching an https:// url expects:

nwn-dg-api --port 8080 \
           --ssl-certfile ./ssl/localhost.crt \
           --ssl-keyfile ./ssl/localhost.key

A self-signed certificate is enough when the api and the game server sit on the same host. The docker image below ships with one already, so this step only applies to a bare install:

mkdir -p ./ssl
openssl req -new -x509 -days 365 -noenc \
        -out ./ssl/localhost.crt -keyout ./ssl/localhost.key

From a checkout, the launcher is ./bin/nwn-dg-api. Run nwn-dg-api --help for the full list of options.

Docker

The api also ships as a container image, which saves installing the cairo headers and comes with tls certificates already in place, so there is nothing to generate before the first run:

Registry Image
GitLab registry.gitlab.com/cappysan/apps/nwn-dg:latest
Docker Hub nwnovh/nwndg:latest

The server listens on port 443 inside the container; publish it on whatever the game server can reach:

docker run -d -p 443:443 nwnovh/nwndg:latest
docker run -d -p 443:443 registry.gitlab.com/cappysan/apps/nwn-dg:latest

The endpoint is then at https://localhost:8001/dungeon/tilejson, already over tls, with no --ssl-certfile or --ssl-keyfile to pass.

The bundled certificate is self-signed, so curl needs -k and the module must be told not to verify the peer. That is fine for an api reachable only from the game server; for anything exposed more widely, mount your own certificate and point the flags at it:

docker run -d -p 8001:8000 \
       -v ./ssl:/ssl:ro \
       nwnovh/nwndg:latest \
       --ssl-certfile /etc/ssl/fqdn.crt --ssl-keyfile /etc/ssl/fqdn.key

You can obtain free certificates via Let's Encrypt.

Endpoint

POST /dungeon/tilejson generates a dungeon and returns the same document as --output-tile-json, as the response body.

  • The request body must be sent as application/json; the schema in openapi.yml declares no other content type and anything else is rejected.
  • Keys are the cli long options without their leading --, so --map-width 21 becomes "map-width": 21.
  • An empty object generates a dungeon with every default.
  • File-writing output-* flags are ignored, since the endpoint returns the document rather than writing it; output-tileset is honoured and selects the tileset as it does on the command line.
curl -k -X POST https://localhost:8080/dungeon/tilejson \
     -H 'Content-Type: application/json' \
     -d '{"output-tileset": "tdm01", "map-width": 21, "map-height": 9}'

Passing seed reproduces an exact dungeon, the same way --seed does on the command line:

curl -k -X POST https://localhost:8080/dungeon/tilejson \
     -H 'Content-Type: application/json' \
     -d '{"output-tileset": "tdm01", "seed": "mydungeon"}'

-k is only needed for a self-signed certificate, which includes the one shipped in the docker image. On the module side, see POC examples/nwn_dg.nss for the matching request and the SetTileJson() call it feeds.

Outputs

Flag Extension Contents
--output-png .png Map preview, with optional room ids, axes and tile indexes
--output-are-json .are.json The area as json, ready for nwn_gff
--output-are .are Binary area file, converted with nwn_gff
--output-tile-json .tile.json Input for SetTileJson(), see below
--output-tree .tree.png Graph of connected rooms
--output-seed .seed Random state, for reproducing the exact same dungeon

--output-png and --output-are-json are on by default; the rest are off. Every flag has a --no- counterpart.

Reproducibility

--seed accepts either a seed value or a path to a .seed file, whose content restores the full random state. Combined with --output-seed, any dungeon can be regenerated byte for byte. The state is also embedded, base64 encoded, in the seed key of the tile json, so an area artifact is self-describing.

Tile json

--output-tile-json writes what a module needs to build the area at runtime and then populate it:

  • tiles — tile id and orientation per index, for SetTileJson()
  • rooms — per room: neighbouring rooms, the cells it owns, and its sills
  • transitions — stairs up and down, with orientation, the room they open onto, whether they are the dungeon entrance, and the walking distance to every room
  • paths — the longest routes through the dungeon, as room ids
  • cells — deadends, useful for treasure and traps

See POC examples/nwn_dg.nss for a proof-of-concept module script consuming it.

Demo

A working demo lives in ./example, showing the whole exchange: a module requesting a dungeon from the api and building the area from the response.

  • module — a standalone NWN module, playable as-is. It needs NWNXEE on the server, since the demo goes through NWNX_HTTPClient to reach the api and NWNX_Area_GetTileInfo to place the doors.
  • scripts — the NWScript sources the module runs, kept outside the module so they can be read and recompiled without unpacking it.

Point the module at a running api, either a bare nwn-dg-api or the docker image, and enter the area to have it regenerate itself.

Tilesets

Type Tileset
tdc01 Crypt
tdm01 Mines and Caverns
tds01 Sewers

See https://nwnlexicon.com/Tileset_resref.

Additional resources

License

This project is licensed under the MIT License - see the LICENSE file for details.

Locations

Metadata

Release files for nwn-dg 0.7.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for nwn-dg 0.7.3
File Size Uploaded
nwn_dg-0.7.3.tar.gz 163.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for nwn-dg 0.7.3
File Interpreter ABI Platform
nwn_dg-0.7.3-py3-none-any.whl Python 3 none any Details

Total release size: 343.8 kB

Release files / nwn_dg-0.7.3.tar.gz

Download URL nwn_dg-0.7.3.tar.gz
Size 163.4 kB
Tags Source
SHA-256 checksum
How to use checksums
a6e0caf66a28707ebdb443b2b75885881c975510544a3285fd5ee09269f153b9
BLAKE2b-256 checksum
How to use checksums
7ac793da492f02168dc4edbfcb68cb40b754c98b4ca64c2f2bc9106cf2fb5453
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.11.16

Release files / nwn_dg-0.7.3-py3-none-any.whl

Download URL nwn_dg-0.7.3-py3-none-any.whl
Size 180.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2ac2ba63ee3a5135d9c091003978178746cc0b0a916cbb56e198e03fb94e22d3
BLAKE2b-256 checksum
How to use checksums
c50fd0ae7fa53374b7be31362a65e044beb0cf41e37b7a78716a803a8db066db
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.11.16

Release history Release notifications | RSS feed

This release

0.7.3 This release

2 release files

0.7.2

2 release files

0.7.1

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.1

2 release files

0.3.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page