From 3482f66ce348d7dd0e5d2f72fa3ab370c5051b8c Mon Sep 17 00:00:00 2001 From: Florian Fischer Date: Mon, 13 Sep 2021 13:17:18 +0200 Subject: [maps] add new tyrant map, tiles and improve map generation script --- assets/tiles/gate.png | Bin 0 -> 8182 bytes assets/tiles/gate_wall_h.png | Bin 0 -> 10783 bytes assets/tiles/the_tyrant.png | 1 + assets/tiles/wall.png | Bin 0 -> 12302 bytes assets/tiles/wall_elbow_down.png | Bin 0 -> 10692 bytes assets/tiles/wall_elbow_up.png | Bin 0 -> 11108 bytes assets/tiles/wall_h.png | Bin 0 -> 7655 bytes data/cards/tyrant/enslaved_soul.yml | 14 +++ maps/Makefile | 11 +- maps/the-tyrant.yml | 27 +++++ scripts/generate_map_img.py | 205 +++++++++++++++++++++++++++--------- 11 files changed, 201 insertions(+), 57 deletions(-) create mode 100644 assets/tiles/gate.png create mode 100644 assets/tiles/gate_wall_h.png create mode 120000 assets/tiles/the_tyrant.png create mode 100644 assets/tiles/wall.png create mode 100644 assets/tiles/wall_elbow_down.png create mode 100644 assets/tiles/wall_elbow_up.png create mode 100644 assets/tiles/wall_h.png create mode 100644 data/cards/tyrant/enslaved_soul.yml create mode 100644 maps/the-tyrant.yml diff --git a/assets/tiles/gate.png b/assets/tiles/gate.png new file mode 100644 index 00000000..e54e670d Binary files /dev/null and b/assets/tiles/gate.png differ diff --git a/assets/tiles/gate_wall_h.png b/assets/tiles/gate_wall_h.png new file mode 100644 index 00000000..95c2b3e3 Binary files /dev/null and b/assets/tiles/gate_wall_h.png differ diff --git a/assets/tiles/the_tyrant.png b/assets/tiles/the_tyrant.png new file mode 120000 index 00000000..7f613e7b --- /dev/null +++ b/assets/tiles/the_tyrant.png @@ -0,0 +1 @@ +the_kraken.png \ No newline at end of file diff --git a/assets/tiles/wall.png b/assets/tiles/wall.png new file mode 100644 index 00000000..780fe311 Binary files /dev/null and b/assets/tiles/wall.png differ diff --git a/assets/tiles/wall_elbow_down.png b/assets/tiles/wall_elbow_down.png new file mode 100644 index 00000000..2511bbc5 Binary files /dev/null and b/assets/tiles/wall_elbow_down.png differ diff --git a/assets/tiles/wall_elbow_up.png b/assets/tiles/wall_elbow_up.png new file mode 100644 index 00000000..b9be431c Binary files /dev/null and b/assets/tiles/wall_elbow_up.png differ diff --git a/assets/tiles/wall_h.png b/assets/tiles/wall_h.png new file mode 100644 index 00000000..3d49ffcb Binary files /dev/null and b/assets/tiles/wall_h.png differ diff --git a/data/cards/tyrant/enslaved_soul.yml b/data/cards/tyrant/enslaved_soul.yml new file mode 100644 index 00000000..6077b928 --- /dev/null +++ b/data/cards/tyrant/enslaved_soul.yml @@ -0,0 +1,14 @@ +name: + en: Enslaved Soul + de: Versklavte Seele +type: unit +token: true +attack: 1 +movement: 1 +health: 1 +ai: + en: Wandering 3 + de: Wandelnd 3 +effect: + en: If Enslaved Soul gets targeted sacrifice it + de: Falls Versklavte Seele zu einem Ziel wird opfere sie diff --git a/maps/Makefile b/maps/Makefile index 98fac22e..9ed6dc36 100644 --- a/maps/Makefile +++ b/maps/Makefile @@ -1,20 +1,19 @@ -.PHONY: all clean - -.DEFAULT_GOAL = all - MAPS = $(shell find . -name "*.yml") VERBOSE = @ PNGS = $(MAPS:.yml=.png) +GENERATE_MAP_IMG=../scripts/generate_map_img.py + MAKEFILE_LIST = Makefile +.PHONY: all clean all: $(PNGS) -%.png : %.yml $(MAKEFILE_LIST) +%.png : %.yml $(MAKEFILE_LIST) $(GENERATE_MAP_IMG) @echo "generate map › $@" - $(VERBOSE) python3 ../scripts/generate_map_img.py $< + $(VERBOSE) $(GENERATE_MAP_IMG) $< clean: rm -f $(PNGS) diff --git a/maps/the-tyrant.yml b/maps/the-tyrant.yml new file mode 100644 index 00000000..49c1a0a3 --- /dev/null +++ b/maps/the-tyrant.yml @@ -0,0 +1,27 @@ +map: |1+ + HF HH H H + SSH HTWT HHH + SH$SSSG1GSSS$H + SHT H TGTH TGT + GTH H S HWS + SWWW H$ HFWWS + SSSWWWTGTWWW S + SSSSSSSSSSSS + S FS + SS S T HS + SFH $ SS + S S S + S S S + S + 0H 0H H0 + +symbols: + W: wall + G: gate + T: tower + H: house + F: farm + S: street + $: store + 1: the tyrant + 0: player spawn diff --git a/scripts/generate_map_img.py b/scripts/generate_map_img.py index ee30cd90..f3b3671d 100755 --- a/scripts/generate_map_img.py +++ b/scripts/generate_map_img.py @@ -1,22 +1,165 @@ #!/usr/bin/env python3 +"""Generate map images from map files""" import argparse -import cv2 import pathlib -import numpy import os -from typing import MutableMapping +from typing import Sequence, Tuple import yaml +import cv2 +import numpy + MAP_ROOT = pathlib.Path(os.getcwd()) TILES_DIR = MAP_ROOT / '../assets/tiles' SHOW_MAP = False +Row = Sequence[str] +Tiles = Sequence[Row] + 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 is_connected_to(tiles: Tiles, + x: int, + y: int, + kind=None) -> Tuple[bool, bool, bool, bool]: + is_kind = lambda tile: tile == kind if kind else tile != 'neutral' + row = tiles[y] + left = x > 0 and is_kind(row[x - 1]) + right = x < len(row) - 1 and is_kind(row[x + 1]) + above = y > 0 and is_kind(tiles[y - 1][x]) + below = y < len(tiles) - 1 and is_kind(tiles[y + 1][x]) + + return left, right, above, below + +def count_connections(left:bool , right:bool, above:bool, below:bool) -> int: + return len([b for b in [left, right, above, below] if b is True]) + + +def find_street_tile(tiles: Tiles, x: int, y: int): + # find street continuations + left, right, above, below = is_connected_to(tiles, x, y, kind='street') + + connections = count_connections(left, right, above, below) + + if connections == 0: + # This street is not connected to another street -> + # check any other non neutral tiles + left, right, above, below = is_connected_to(tiles, x, y, kind=None) + + connections = count_connections(left, right, above, below) + + # This street is not connected to anything. Seams odd! + # Use a 4 way street + if connections == 0: + tile_img = cv2.imread(str(get_tile_path('street_4'))) + + # straight lines + elif 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'))) + + return tile_img + + +def find_wall_tile(tiles: Sequence[Sequence[str]], x: int, y: int): + # find wall continuations + left, right, above, below = is_connected_to(tiles, x, y, kind='wall') + + connections = count_connections(left, right, above, below) + + if connections == 0: + # This wall is not connected to another wall -> + # check any other non neutral tiles + left, right, above, below = is_connected_to(tiles, x, y, kind=None) + + connections = count_connections(left, right, above, below) + + # This wall is not connected to anything. Seams odd! + # Use default horizontal wall + if connections == 0: + tile_img = cv2.imread(str(get_tile_path('wall'))) + + # straight walls + elif connections == 1 or (connections == 2 and ((left and right) or + (above and below))): + if above or below: + tile_img = cv2.imread(str(get_tile_path('wall_h'))) + else: + tile_img = cv2.imread(str(get_tile_path('wall'))) + + # elbow + elif connections == 2: + if above: + tile_img = cv2.imread(str(get_tile_path('wall_elbow_up'))) + else: + tile_img = cv2.imread(str(get_tile_path('wall_elbow_down'))) + + if left: + tile_img = cv2.flip(tile_img, 1) + + elif connections == 3 or connections == 4: + # We don't have wall tiles for those structures yet use default vertical wall + tile_img = cv2.imread(str(get_tile_path('wall'))) + + return tile_img + + +def find_gate_tile(tiles: Sequence[Sequence[str]], x: int, y: int): + # find wall continuations + left, right, above, below = is_connected_to(tiles, x, y, kind='wall') + + connections = count_connections(left, right, above, below) + + if connections == 0: + # This gate is not connected to a wall -> check towers next + left, right, above, below = is_connected_to(tiles, x, y, kind='tower') + + connections = count_connections(left, right, above, below) + + if connections == 0: + # If the gate is not connected to any fortification structure use default tile + return cv2.imread(str(get_tile_path('gate'))) + + # straight gates are the only special gates we have + if connections == 2 and ((left and right) or (above and below)): + if above or below: + tile_img = cv2.imread(str(get_tile_path('gate'))) + else: + tile_img = cv2.imread(str(get_tile_path('gate_wall_h'))) + + else: + tile_img = cv2.imread(str(get_tile_path('gate'))) + + return tile_img + + def generate_img(map_path: pathlib.Path): """Generate a image from a map file""" with open(map_path, 'r') as map_file: @@ -42,47 +185,16 @@ def generate_img(map_path: pathlib.Path): tiles.append(row) rows_imgs = [] - for i, row in enumerate(tiles): + for y, row in enumerate(tiles): tile_imgs = [] - for j, tile in enumerate(row): + for x, 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'))) + tile_img = find_street_tile(tiles, x, y) + elif tile == 'wall': + tile_img = find_wall_tile(tiles, x, y) + elif tile == 'gate': + tile_img = find_gate_tile(tiles, x, y) else: tile_img = cv2.imread(str(get_tile_path(tile))) @@ -98,9 +210,7 @@ def generate_img(map_path: pathlib.Path): cv2.imwrite(f'{map_path.stem}.png', map_img) -def main(): - """Generate map images from map files""" - +if __name__ == '__main__': parser = argparse.ArgumentParser( description='generate latex standalone cards') parser.add_argument('map_input', @@ -113,13 +223,10 @@ def main(): 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) @@ -129,7 +236,3 @@ def main(): for m in map_files: generate_img(m) - - -if __name__ == '__main__': - main() -- cgit v1.2.3