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 8000 inside the container; publish it on whatever
the game server can reach:
docker run -d -p 8001:8000 nwnovh/nwndg:latest
docker run -d -p 8001:8000 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 inopenapi.ymldeclares no other content type and anything else is rejected. - Keys are the cli long options without their leading
--, so--map-width 21becomes"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-tilesetis 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, forSetTileJson()rooms— per room: neighbouring rooms, the cells it owns, and its sillstransitions— stairs up and down, with orientation, the room they open onto, whether they are the dungeon entrance, and the walking distance to every roompaths— the longest routes through the dungeon, as room idscells— 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 throughNWNX_HTTPClientto reach the api andNWNX_Area_GetTileInfoto 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
- NWNXEE: https://nwnxee.github.io/unified/group__httpclient.html
- SetTileJson: https://nwnlexicon.com/index.php/SetTileJson
License
This project is licensed under the MIT License - see the LICENSE file for details.
Locations
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nwn_dg-0.7.2.tar.gz.
File metadata
- Download URL: nwn_dg-0.7.2.tar.gz
- Upload date:
- Size: 163.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.11.16
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
19b49ab65ee8530dbc23232da601620a7953ec63d3510be417922aa4d4fddfed
|
|
| MD5 |
a22b75a9d885783de867137ff1f83482
|
|
| BLAKE2b-256 |
1137d1e6a3a6d2776e01d0bd7fe9007830ba2db2f8a44b3b07a1b5a4b0835592
|
File details
Details for the file nwn_dg-0.7.2-py3-none-any.whl.
File metadata
- Download URL: nwn_dg-0.7.2-py3-none-any.whl
- Upload date:
- Size: 180.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.11.16
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
14aea2bb8475dc14161606912e5b73ba45a32c7ed2f5984ee8c9a6ab1bd2f929
|
|
| MD5 |
36569d6cf24bc4d2ec6d4fcce766111d
|
|
| BLAKE2b-256 |
ff1974d4f1d99d1a48f4bf1b3e50b6bf357a4a2ae56a3d4bac354117d1afbcb6
|