Create a gist now

Instantly share code, notes, and snippets.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""AD&D プールオブレイディアンス (FC) マップデータ画像化
マップデータ(0x400 Byte)から画像を生成する。
TODO:
データの意味が完全にわかってない。扉でないところが扉になったりする。
"""
import argparse
from PIL import Image, ImageDraw
MAP_COLS = 16
MAP_ROWS = 16
IMG_CELL_SIZE = (24, 24)
IMG_GRID_THICK = 1
IMG_WALL_THICK = 3
IMG_DOOR_WIDTH = 12
IMG_SIZE = (
MAP_COLS * IMG_CELL_SIZE[0] + (MAP_COLS-1) * IMG_GRID_THICK,
MAP_ROWS * IMG_CELL_SIZE[1] + (MAP_ROWS-1) * IMG_GRID_THICK
)
COLOR_CELL = (0x00, 0xA0, 0x00)
COLOR_GRID = (0x00, 0x00, 0x00)
COLOR_WALL = (0xFF, 0xFF, 0xFF)
COLOR_DOOR = (0xFF, 0x00, 0x00)
COLOR_EVENT = (0xFF, 0xFF, 0x00)
class Border:
def __init__(self, exists, passable):
self.exists = bool(exists)
self.passable = bool(passable)
class Cell:
def __init__(self, event, north, east, south, west):
self.event = event
self.north = north
self.east = east
self.south = south
self.west = west
class Map:
def __init__(self, cells):
self.cells = cells
def cell(self, col, row):
return self.cells[MAP_COLS*row + col]
def parse_map(buf):
size = MAP_COLS * MAP_ROWS
cells = [None] * size
for i in range(size):
b = buf[i::0x100]
# TODO: b[3] の各方角の2bitはそれぞれ別の役割があると思われるが未解析
# TODO: 壁がなくても b[3] で通過可能フラグが立ってる箇所もあるが詳細不明
event = b[2]
north = Border(b[0]&0xF0, b[3]&0b00000011)
east = Border(b[0]&0x0F, b[3]&0b00001100)
south = Border(b[1]&0xF0, b[3]&0b00110000)
west = Border(b[1]&0x0F, b[3]&0b11000000)
cells[i] = Cell(event, north, east, south, west)
return Map(cells)
def generate_img_hwall(border):
if not border.exists and not border.passable: return None
img_hwall = Image.new("RGB", (IMG_CELL_SIZE[0], IMG_WALL_THICK), COLOR_CELL)
draw = ImageDraw.Draw(img_hwall)
if border.exists:
draw.rectangle(((0,0), img_hwall.size), fill=COLOR_WALL)
if border.passable:
center_x = img_hwall.width // 2
door_w_half = IMG_DOOR_WIDTH // 2
draw.rectangle((
(center_x - door_w_half, 0),
(center_x + door_w_half, img_hwall.height)
), fill=COLOR_DOOR)
return img_hwall
def generate_img_vwall(border):
if not border.exists and not border.passable: return None
img_vwall = Image.new("RGB", (IMG_WALL_THICK, IMG_CELL_SIZE[1]), COLOR_CELL)
draw = ImageDraw.Draw(img_vwall)
if border.exists:
draw.rectangle(((0,0), img_vwall.size), fill=COLOR_WALL)
if border.passable:
center_y = img_vwall.height // 2
door_w_half = IMG_DOOR_WIDTH // 2
draw.rectangle((
(0, center_y - door_w_half),
(img_vwall.width, center_y + door_w_half)
), fill=COLOR_DOOR)
return img_vwall
def generate_img_cell(cell):
img_cell = Image.new("RGB", IMG_CELL_SIZE, COLOR_CELL)
draw = ImageDraw.Draw(img_cell)
img_north, img_south = map(generate_img_hwall, (cell.north, cell.south))
img_east, img_west = map(generate_img_vwall, (cell.east, cell.west))
if img_north:
img_cell.paste(img_north, (0, 0))
if img_south:
img_cell.paste(img_south, (0, img_cell.height - img_south.height))
if img_east:
img_cell.paste(img_east, (img_cell.width - img_east.width, 0))
if img_west:
img_cell.paste(img_west, (0, 0))
if cell.event:
center_x = img_cell.width // 2
center_y = img_cell.height // 2
str_event = "{:02x}".format(cell.event)
draw.text((center_x-6, center_y-5), str_event, fill=COLOR_EVENT)
return img_cell
def generate_img(map_):
img = Image.new("RGB", IMG_SIZE, COLOR_GRID)
for row in range(MAP_ROWS):
for col in range(MAP_COLS):
img_cell = generate_img_cell(map_.cell(col, row))
img.paste(img_cell, (
(IMG_CELL_SIZE[0] + IMG_GRID_THICK) * col,
(IMG_CELL_SIZE[1] + IMG_GRID_THICK) * row
))
return img
def parse_args():
ap = argparse.ArgumentParser()
ap.add_argument("in_", type=argparse.FileType("rb"))
ap.add_argument("out", type=argparse.FileType("xb"))
return ap.parse_args()
def main():
args = parse_args()
map_ = parse_map(args.in_.read())
img = generate_img(map_)
img.save(args.out)
if __name__ == "__main__": main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment