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 @property
def legend(self) -> str: def legend(self) -> str:
output = "" output = ""
locations = 0
for char in sorted(set(list(self.source_data)), key=str.lower): for char in sorted(set(list(self.source_data)), key=str.lower):
if char in self.tileset.config.legend: 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" 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 return output
def __str__(self) -> str: def __str__(self) -> str:

View File

@ -8,7 +8,7 @@ import typer
from rich.console import Console from rich.console import Console
from rich.logging import RichHandler from rich.logging import RichHandler
from tilemapper import battlemap from tilemapper import battlemap, converter
from tilemapper import tileset as _tileset from tilemapper import tileset as _tileset
app = typer.Typer() app = typer.Typer()
@ -46,9 +46,14 @@ def list():
print("\n".join(manager.available)) 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() @app.command()
def render( 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" 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), 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( 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, outfile: Union[Path, None] = None,
tileset: str = 'colorized' 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" "." = "ground"
"," = "grass" "," = "grass"
"_" = "water" "_" = "water"
"A" = "archway"
"H" = "portcullis"
"d" = "door, open" "d" = "door, open"
"D" = "door, closed" "D" = "door, closed"
"L" = "door, locked" "L" = "door, locked"
"S" = "door, secret" "S" = "door, secret"
"T" = "door, trapped"
"v" = "stairs, down" "v" = "stairs, down"
"^" = "stairs, up" "^" = "stairs, up"
"0" = "location 0" "0" = "location 0"
@ -28,9 +31,12 @@ class = "tilemapper.tileset.ColorizedTileSet"
[color_map] [color_map]
" " = "black" " " = "black"
"." = "white on grey58" "." = "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" "D" = "bold green on grey58"
"L" = "bold dark_red on grey58" "L" = "bold dark_red on grey58"
"T" = "bold dark_red on grey58"
"S" = "bold black on grey58" "S" = "bold black on grey58"
"v" = "bold steel_blue on grey3" "v" = "bold steel_blue on grey3"
"^" = "bold steel_blue on grey3" "^" = "bold steel_blue on grey3"