mystnb/converters.py

90 lines
2.4 KiB
Python

import fxconv
import re
import os.path
def convert(input, output, params, target):
if params["type"] == "map":
convert_map(input, output, params, target)
else:
raise fxconv.FxconvError(f"unknown conversion {params['type']}")
sys.exit(1)
def convert_map(input, output, params, target):
TILE_AIR = 0
TILE_WALL = 1
TILE_START = 2
TILE_END = 3
TILE_KEY = 16
TILE_VDOOR = 24
TILE_HDOOR = 32
# Read input file
with open(input, "r") as fp:
tiles, cycles = fp.read().split("\n\n")
tiles = tiles.split("\n")
cycle_texts = [c for c in cycles.split("\n") if c]
w = max(len(t) for t in tiles)
h = len(tiles)
fog = 0
filename = os.path.splitext(os.path.basename(input))[0]
# Generate map contents
encoded_tiles = bytearray(w * h)
for (y, t) in enumerate(tiles):
for (x, c) in enumerate(t):
if c == " ":
tile = TILE_AIR
elif c == "#":
tile = TILE_WALL
elif c == "~":
tile = TILE_START
elif c == "@":
tile = TILE_END
elif ord("0") <= ord(c) <= ord("9"):
tile = TILE_KEY + int(c)
elif ord("a") <= ord(c) <= ord("z"):
tile = TILE_VDOOR + (ord(c) - ord("a"))
elif ord("A") <= ord(c) <= ord("Z"):
tile = TILE_HDOOR + (ord(c) - ord("A"))
else:
raise fxconv.FxconvError(f"unknown tile character {c}")
encoded_tiles[y*w + x] = tile
# Parse door cycles
RE_CYCLE = re.compile(r'^([a-zA-Z]):\s*([#.]+)$')
cycles = dict()
for c in cycle_texts:
m = re.match(RE_CYCLE, c)
if not m:
raise fxconv.FxconvError(f"cannot parse door cycle '{c}'")
cycles[m[1]] = m[2].encode("utf-8")
# Generate door cycle data
door_cycle = b""
door_cycle_index = bytearray(16)
for index, letter in enumerate("abcdefghABCDEFGH"):
door_cycle_index[index] = len(door_cycle)
if letter in cycles:
door_cycle += cycles[letter] + b" "
door_cycle = door_cycle + bytes(128 - len(door_cycle))
# Generate the structure
o = fxconv.ObjectData()
o += fxconv.u32(w) + fxconv.u32(h) + fxconv.u32(fog)
o += door_cycle + door_cycle_index
o += fxconv.ref(f"img_{filename}")
o += fxconv.ref(encoded_tiles)
fxconv.elf(o, output, "_" + params["name"], **target)