donjon.sh converter

Initial implementation of a basic tool that converts an exported
donjon.sh dungeon json file to a text dungeon suitable for rendering by
the tilemapper.

Polymorphic definitions are discarded; all rooms are squared.
This commit is contained in:
evilchili 2025-08-17 12:04:31 -07:00
parent 1f3c467348
commit cdbb233622
4 changed files with 77 additions and 4 deletions

View File

@ -108,9 +108,21 @@ class BattleMap(BattleMapType):
@property
def legend(self) -> str:
output = ""
locations = 0
for char in sorted(set(list(self.source_data)), key=str.lower):
if char in self.tileset.config.legend:
if char in '0123456789':
locations = max(locations, int(char))
output += f"{char} - {self.tileset.config.legend[char]}\n"
if locations:
location_key = "1" if locations == 1 else f"1-{locations}"
output += f"{location_key} - location"
width = len(location_key)
justified = ""
for line in output.splitlines():
(key, sep, desc) = line.partition(" - ")
justified += f"{key.rjust(width, ' ')}{sep}{desc}\n"
output = "".join(justified)
return output
def __str__(self) -> str:

View File

@ -8,7 +8,7 @@ import typer
from rich.console import Console
from rich.logging import RichHandler
from tilemapper import battlemap
from tilemapper import battlemap, converter
from tilemapper import tileset as _tileset
app = typer.Typer()
@ -46,9 +46,14 @@ def list():
print("\n".join(manager.available))
@app.command()
def convert(source: typer.FileText = typer.Argument(help="The donjon.sh .json file to import")):
print(converter.convert_donjon(source.read()))
@app.command()
def render(
source: Path = typer.Option(
source: typer.FileText = typer.Argument(
help="The battle map text file to load.", default=INSTALL_DIR / "examples" / "five_room_dungeon.txt"
),
outfile: Path = typer.Option(help="The file to create. If not specified, print to STDOUT", default=None),
@ -64,7 +69,7 @@ def render(
def render_map(
source: Path = INSTALL_DIR / "examples" / "five_room_dungeon.txt",
source: typer.FileText = INSTALL_DIR / "examples" / "five_room_dungeon.txt",
outfile: Union[Path, None] = None,
tileset: str = 'colorized'
):

View File

@ -0,0 +1,50 @@
from types import SimpleNamespace
from collections import defaultdict
import json
terrain_map = {
"0": " ", # nothing
"16": " ", # perimeter
"4": ".",
"4194308": "v", # stair_down
"8388612": "^", # stair_up
"13107": "d", # door
"26214": "L", # door, locked
"52429": "T", # door, trapped
"10485": "S", # door, secret
"65540": "A", # arch
"20971": "H", # portcullis
"82208": "1",
"83886": "2",
"8556": "3",
"87241": "4",
"88919": "5",
"90597": "6",
"92274": "7",
"93952": "8",
"95630": "9",
"80530": "0",
}
def get_char(key: str, default: str = None) -> str:
return terrain_map.get(key) or terrain_map.get(key[:5]) or terrain_map.get(key[:4]) or default
def convert_donjon(source: str) -> str:
src = SimpleNamespace(**json.loads(source))
textmap = ""
for y in range(len(src.cells)):
row = src.cells[y]
for x in range(len(row)):
char = get_char(str(row[x]), default=".")
if not char:
raise Exception(f"{textmap}\nMissing value {row[x]} at ({y}, {x})")
textmap += char
textmap += "\n"
return textmap

View File

@ -8,10 +8,13 @@ class = "tilemapper.tileset.ColorizedTileSet"
"." = "ground"
"," = "grass"
"_" = "water"
"A" = "archway"
"H" = "portcullis"
"d" = "door, open"
"D" = "door, closed"
"L" = "door, locked"
"S" = "door, secret"
"T" = "door, trapped"
"v" = "stairs, down"
"^" = "stairs, up"
"0" = "location 0"
@ -28,9 +31,12 @@ class = "tilemapper.tileset.ColorizedTileSet"
[color_map]
" " = "black"
"." = "white on grey58"
"d" = "bold cyan on grey58"
"A" = "bold green on grey58"
"H" = "bold green on grey58"
"d" = "bold green on grey58"
"D" = "bold green on grey58"
"L" = "bold dark_red on grey58"
"T" = "bold dark_red on grey58"
"S" = "bold black on grey58"
"v" = "bold steel_blue on grey3"
"^" = "bold steel_blue on grey3"