Skip to main content

Dragoman

Translate maps between Open Doctrines (.odmap) and Greater Diplomacy 5 (map directories), in both directions, losing as little as the two formats allow — and nothing at all on a round trip.

A dragoman was the interpreter attached to an embassy: the person through whom two powers who shared no language could nonetheless sign something. This is that, for map files.

pip install open-dragoman

dragoman convert 1914.odmap base_maps/1914 --to gd5
dragoman convert base_maps/GD4 gd4.odmap   --to odmap
dragoman roundtrip 1914.odmap              # prove nothing was lost
import dragoman

dragoman.convert("1914.odmap", "base_maps/1914", to="gd5")

world = dragoman.load("1914.odmap")
print(world.name, len(world.provinces), "provinces")

Read the wiki → — what it is, how to use it, what every message means, and what it cannot do.

Status

Every map both games ship round-trips without losing a single modelled field:

Suite Result
Greater Diplomacy 5 maps (12 base maps + 16 scenarios) 28 / 28
Open Doctrines maps (5 scenarios + the world map) 6 / 6
Unit tests (raster, scripts, ABI, versioning, round trip) 5 / 5

Verified against Open Doctrines and against GitGetGot415/Greater-Diplomacy-5. Reproduce with python3 tools/conformance.py <directory of maps>.

Converted maps have also been played in both games, not merely loaded by this library. Open Doctrines' world map converted to GD5 boots through GD5's own Controller and Map state with all 23 screens, its flags drawn, its oceans navigable and every province centre inside its own province; a GD5 map converted to Open Doctrines plays five AI turns under OpenDoctrines --simulate. Nearly everything this library gets right, it gets right because somebody opened the result in the game and looked at it — the flag encoding, the ocean, the political layer's colour key and the province-border fill were all found that way.

One thing crossing to Open Doctrines still needs a human: GD5 starts its nations with an empty stockpile and Open Doctrines expects a starting endowment, so a converted map bankrupts its world on the first turn unless treasuries are set. Reported as od.treasury rather than guessed at.

What "lossless" means here

The two games are not the same game, so a straight translation always loses something: Open Doctrines models a province's population, its port and its ethnic minorities, and GD5 has no field for any of them; GD5 models terrain, province adjacency, unit rosters and research, and Open Doctrines has no field for those.

Dragoman writes the difference down. Everything the destination cannot hold goes into a sidecar beside the map — dragoman_sidecar/ in a GD5 directory, dragoman/ inside a .odmap archive. Both games read a fixed list of filenames and ignore everything else, so the sidecar is invisible to them and costs the converted map nothing.

The result:

  • Converting one way is as faithful as the target format permits, and every approximation is reported by a stable code you can act on.
  • Converting back restores what the target could not hold. A → B → A keeps every province, nation, relation, claim, core, script and carried file, and the province raster hashes identical.

dragoman roundtrip <map> asserts exactly that. Pass --no-sidecar for a smaller, genuinely lossy conversion — the round trip then fails, on purpose.

Not promised: byte-identical container files. Two zip archives holding identical members are different files, because deflate is not reproducible across implementations, and Open Doctrines packs with Python's zlib while this packs with miniz. Every file inside is preserved exactly.

What crosses

Open Doctrines Greater Diplomacy 5
Province raster provinces.png, id packed big-endian id_map.png, id packed little-endian
Province identity preserved exactly — the rasters differ only by swapping red and blue
Owner, name, claims
Cores ✅ (carried)
Sea provinces — (synthesised for GD5)
Population, ports, fortification — (carried)
Minorities, political compass, policies — (carried)
Terrain, adjacency, province centres — (derived from the raster)
Units, buildings, research, factions — (armies carried)
Flags a PNG in the archive raw 60x40 pixels, base64
Relations ally, non-aggression, guarantee war and alliance only (rest carried)
Scripts imperative #OD/MapEngine/1 declarative scripted events

Adjacency and centroids are computed from the province raster when converting to GD5, since Open Doctrines derives both at load and never stores them. The centroid finder deliberately handles crescent-shaped provinces, whose mean pixel falls outside themselves.

Full field-by-field detail: docs/mapping.md.

Scripts

Open Doctrines' scripting is imperative and line-based, with loops and waitUntil suspension points. GD5's is a list of declarative events, each a set of conditions and a set of actions. The overlap is the shape both express: a gate, and things that happen when it opens.

An Open Doctrines script written as top-level waitUntil stages becomes GD5 events, one stage at a time. A GD5 event becomes an entry script with a waitUntil and some set lines. Anything outside that overlap — a foreach over a country's provinces, conditions chained with XOR — is reported by name and carried unchanged rather than half-translated. GD5 event types this library has never heard of pass through untouched, so a GD5 → OD → GD5 trip is lossless even for conditions added to the game after this was written.

Details and the full vocabulary: docs/scripting.md.

Installing

pip install open-dragoman

The wheel carries the compiled library inside the package, so there is no compiler needed at install time and nothing to locate afterwards. You get both the Python API and a dragoman command.

Prebuilt binaries for people who want nothing to do with Python are attached to each release. The full set of options — release archives, source builds, CMake FetchContent — is on the Installing page.

Building from source

Needs CMake 3.16 and a C++17 compiler. There are no external dependencies — miniz, stb and nlohmann/json are vendored, all MIT or public domain.

cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
ctest --test-dir build --output-on-failure

This produces libdragoman.a, a shared libdragoman.{so,dylib,dll}, and the dragoman command line tool.

Using it from your language

The core is C++17 behind a flat C99 ABI, so anything with an FFI can call it. The whole interchange model is available as JSON through dg_world_to_json, which is how a binding reads or edits a map without needing an accessor per field.

  • C#include <dragoman/dragoman.h>, link dragoman. See bindings/c/example.c.
  • C++#include <dragoman/dragoman.hpp> for an RAII wrapper over the same ABI. See bindings/cpp/example.cpp.
  • Pythonpip install open-dragoman. Pure ctypes, and the wheel carries the library, so no compiler is needed at install time.
  • Anything else — Rust, Go, C#, Java, Lua and WebAssembly all bind the same header. docs/abi.md documents the contract.

Versioning

Two numbers that move for different reasons:

  • Library version (VERSION, semver) — the release. (Look in VERSION file to find current latest version).
  • ABI version (DRAGOMAN_ABI_VERSION) — bumped only when an existing symbol changes meaning, so a binding can refuse to load a library it cannot speak to without parsing semver.

The version lives in VERSION and is mirrored into the C header, the Python package and the CMake project. tools/check_version.py and tests/test_version.cpp both fail if any copy drifts, and CI runs them on every push. Details: docs/versioning.md.

Licence

Dragoman is MIT. It is an independent implementation written from observing both file formats; no code from either game is copied into it. Open Doctrines and Greater Diplomacy 5 remain under their own licences (Open Doctrines Non-Commercial, and GPL-3.0 respectively), and neither project's maps are redistributed here.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

open_dragoman-0.3.1.tar.gz (459.3 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

open_dragoman-0.3.1-py3-none-win_amd64.whl (344.1 kB view details)

Uploaded Python 3Windows x86-64

open_dragoman-0.3.1-py3-none-win32.whl (318.2 kB view details)

Uploaded Python 3Windows x86

open_dragoman-0.3.1-py3-none-musllinux_1_2_x86_64.whl (3.3 MB view details)

Uploaded Python 3musllinux: musl 1.2+ x86-64

open_dragoman-0.3.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.1 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

open_dragoman-0.3.1-py3-none-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl (3.3 MB view details)

Uploaded Python 3manylinux: glibc 2.12+ i686manylinux: glibc 2.17+ i686

open_dragoman-0.3.1-py3-none-macosx_11_0_universal2.whl (2.3 MB view details)

Uploaded Python 3macOS 11.0+ universal2 (ARM64, x86-64)

File details

Details for the file open_dragoman-0.3.1.tar.gz.

File metadata

  • Download URL: open_dragoman-0.3.1.tar.gz
  • Upload date:
  • Size: 459.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for open_dragoman-0.3.1.tar.gz
Algorithm Hash digest
SHA256 f36f8b8ebf8c0d8804f788329922e3e2b210ff201399defa41adb76b57d95625
MD5 34b0216c6cc20e137403aef6fd25c5c6
BLAKE2b-256 3f557b1a73ce4ecbdf2c4908e38aabf93baf4aacbdb8c0240827c8b06aa95e78

See more details on using hashes here.

Provenance

The following attestation bundles were made for open_dragoman-0.3.1.tar.gz:

Publisher: wheels.yml on Pr1nted/dragoman

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file open_dragoman-0.3.1-py3-none-win_amd64.whl.

File metadata

  • Download URL: open_dragoman-0.3.1-py3-none-win_amd64.whl
  • Upload date:
  • Size: 344.1 kB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for open_dragoman-0.3.1-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 8db76720267d71f137c6d3dd51529c6246b38b6e021fec1540544fcd276d1f84
MD5 9440870a595146a63cd9e47dc0f4a25d
BLAKE2b-256 e9f199c838aa0b0b47537e03de78ad85efbe15875f35e49cebfe38c35883ed92

See more details on using hashes here.

Provenance

The following attestation bundles were made for open_dragoman-0.3.1-py3-none-win_amd64.whl:

Publisher: wheels.yml on Pr1nted/dragoman

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file open_dragoman-0.3.1-py3-none-win32.whl.

File metadata

  • Download URL: open_dragoman-0.3.1-py3-none-win32.whl
  • Upload date:
  • Size: 318.2 kB
  • Tags: Python 3, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for open_dragoman-0.3.1-py3-none-win32.whl
Algorithm Hash digest
SHA256 c469f28a70542023cd0b6f85b139aa88e1f6da4f0994b51b51b43e2df40c218d
MD5 6cb24b0e61bf944ba7999feee6a5f63f
BLAKE2b-256 f6b8c5b70136b24a4fbdef8b59f79484890c3421bbe6b2d8c6b4df28ac5f86b1

See more details on using hashes here.

Provenance

The following attestation bundles were made for open_dragoman-0.3.1-py3-none-win32.whl:

Publisher: wheels.yml on Pr1nted/dragoman

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file open_dragoman-0.3.1-py3-none-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for open_dragoman-0.3.1-py3-none-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 05cbfd36b03a9343e83474d4f1b5b388b510f944da8ecb2ab36208d4dc75de06
MD5 b1afe3ca9f996a68b6226ce621154ab0
BLAKE2b-256 0d28c84e15383e2baf15e120a088d0f136fd0dca945a92754164dbee8713f7c0

See more details on using hashes here.

Provenance

The following attestation bundles were made for open_dragoman-0.3.1-py3-none-musllinux_1_2_x86_64.whl:

Publisher: wheels.yml on Pr1nted/dragoman

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file open_dragoman-0.3.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for open_dragoman-0.3.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 b94cfd1b42789c023fb404f5b6bd9e5c951667ada0a9c4db63f3d3512e3f36f6
MD5 0df72f35f7fa05d51452e9cd12ff7539
BLAKE2b-256 37ea08622cdbc1fddbabade3b34dc3498807dfb412e315223d5b756bcc43cd09

See more details on using hashes here.

Provenance

The following attestation bundles were made for open_dragoman-0.3.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: wheels.yml on Pr1nted/dragoman

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file open_dragoman-0.3.1-py3-none-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for open_dragoman-0.3.1-py3-none-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 e7c151b5a222c027c7d16d6b7e3b31d628f8710003f362dc105b6708ad226b3a
MD5 d25d769e6fa72df9fea3edb21dfe88a6
BLAKE2b-256 9e3547f1a4dc0e4c68c6b9b2ff9e61713cf0e38b7b823dd184c4e65090147503

See more details on using hashes here.

Provenance

The following attestation bundles were made for open_dragoman-0.3.1-py3-none-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl:

Publisher: wheels.yml on Pr1nted/dragoman

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file open_dragoman-0.3.1-py3-none-macosx_11_0_universal2.whl.

File metadata

File hashes

Hashes for open_dragoman-0.3.1-py3-none-macosx_11_0_universal2.whl
Algorithm Hash digest
SHA256 a304b44764c0d9f26fcd17af55cb4d76cb95d08cd3bda7b55c97f14a55ac0d06
MD5 310c9fb7bdbe1f0c5c49edcd3c0ae405
BLAKE2b-256 ad87fceac3f7b4eafa3d6a63d9b4e83923f7ad692f0b87e1c0edb462d07b4537

See more details on using hashes here.

Provenance

The following attestation bundles were made for open_dragoman-0.3.1-py3-none-macosx_11_0_universal2.whl:

Publisher: wheels.yml on Pr1nted/dragoman

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.4.1

7 files

0.4.0

7 files

0.3.2

7 files

This release

0.3.1 This release

7 files

0.3.0

7 files

0.2.2

7 files

0.2.0

2 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