aboutsummaryrefslogtreecommitdiff
path: root/scripts/generate_map_img.py
blob: f4e2914868a8c5ebcb531d95c62e5a04a170cdea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#!/usr/bin/env python3
import argparse
import cv2
import pathlib
import numpy
import os
from typing import MutableMapping

MAP_ROOT = pathlib.Path(os.getcwd())
TILES_DIR = MAP_ROOT / '../assets/tiles'
SHOW_MAP = False

def get_tile_path(tile: str) -> pathlib.Path:
    """Return the corresponding image file name for a tile"""
    return TILES_DIR / f'{tile.lower().replace(" ", "_")}.png'

def read_map(map_path: pathlib.Path) -> MutableMapping:
    """Read and parse a map file"""
    map_definition = {'symbols': {}, 'rules': {}}
    with open(map_path, 'r') as map_file:
        lines = [l[:-1] for l in map_file.readlines()] # remove new lines

    # sections in map files are seperated by an empty line
    section_end = lines.index('')
    map_string = '\n'.join(lines[:section_end])
    lines = lines [section_end+1:] # consume map string

    section_end = lines.index('')
    for symbol_def in lines[:section_end]:
        symbol, tile = symbol_def.split(':=')
        symbol = symbol.strip()
        tile = tile.strip()
        map_definition['symbols'][symbol] = tile
    lines = lines[section_end + 1:] # consume symbol definitions

    # build up tiles
    tiles = []
    for line in map_string.splitlines():
        row = []
        for symbol in line:
            tile = "neutral"
            if symbol != ' ':
                if symbol not in map_definition['symbols']:
                    print(f'WARNING unknown symbol "{symbol}"')
                else:
                    tile = map_definition['symbols'][symbol]
            row.append(tile)
        tiles.append(row)

    map_definition['tiles'] = tiles

    for rule in lines:
        name, rule = symbol_def.split(':=')
        name = name.strip()
        rule = rule.strip()
        map_definition['rules'][name] = rule

    return map_definition


def generate_img(map_path: pathlib.Path):
    """Generate a image from a map file"""
    map_definition = read_map(map_path)

    tiles = map_definition['tiles']

    rows_imgs = []
    for i, row in enumerate(tiles):
        tile_imgs = []
        for j, tile in enumerate(row):
            # find the right street and rotation
            if tile == 'street':
                # check continuations
                left = j > 1 and row[j-1] == 'street'
                right = j < len(row) - 1 and row[j+1] == 'street'
                above = i > 1 and tiles[i-1][j] == 'street'
                below = i < len(tiles) - 1 and tiles[i+1][j] == 'street'

                connections = len([b for b in [left, right, above, below] if b == True])
                # straight lines
                if connections == 1 or (connections == 2 and ((left and right) or (above and below))):
                    tile_img = cv2.imread(str(get_tile_path('street')))
                    if above or below:
                        tile_img = numpy.rot90(tile_img)
                # elbow
                elif connections == 2:
                    # normal orientation above and right
                    tile_img = cv2.imread(str(get_tile_path('street_2')))
                    if right and below:
                        tile_img = numpy.rot90(tile_img, 3)
                    elif left and below:
                        tile_img = numpy.rot90(tile_img, 2)
                    elif above and left:
                        tile_img = numpy.rot90(tile_img)
                elif connections == 3:
                    # normal orientation left above right
                    tile_img = cv2.imread(str(get_tile_path('street_3')))
                    if above and right and below:
                        tile_img = numpy.rot90(tile_img, 3)
                    elif left and below and right:
                        tile_img = numpy.rot90(tile_img, 2)
                    elif below and left and above:
                        tile_img = numpy.rot90(tile_img)
                elif connections == 4:
                    tile_img = cv2.imread(str(get_tile_path('street_4')))
            else:
                tile_img = cv2.imread(str(get_tile_path(tile)))

            tile_imgs.append(tile_img)

        row_img = cv2.hconcat(tile_imgs)
        rows_imgs.append(row_img)

    map_img = cv2.vconcat(rows_imgs)
    if SHOW_MAP:
        cv2.imshow(f'{map_path.stem}.png', map_img)
        cv2.waitKey(0)
    cv2.imwrite(f'{map_path.stem}.png', map_img)

def main():
    """Generate map images from map files"""

    parser = argparse.ArgumentParser(description='generate latex standalone cards')
    parser.add_argument('map_input', help='map file or directory containing map files')
    parser.add_argument('--map-root', help='path to the map root directory')
    parser.add_argument('--show-map', help='show the generated map', action='store_true')

    args = parser.parse_args()

    if args.map_root:
        global MAP_ROOT
        MAP_ROOT = pathlib.Path(args.latex_root)
        global TILES_DIR
        TILES_DIR = MAP_ROOT / '../assets/tiles'

    if args.show_map:
        global SHOW_MAP
        SHOW_MAP = True

    map_path = pathlib.Path(args.map_input)
    map_files = [map_path]
    if map_path.is_dir():
        map_files = map_path.glob('*.map')

    for m in map_files:
        generate_img(m)

if __name__ == '__main__':
    main()