import dataclasses from map.quest_map import MapEncounter, QuestMap, EncounterType, QuestPath from typing import List, Dict, Optional _ENCOUNTER_ICONS = { EncounterType.BATTLE_REGULAR: 'noun_Battle_3647629_cropped.png', EncounterType.BATTLE_ELITE: 'noun_Shield_3806325_cropped.png', EncounterType.BATTLE_BOSS: 'noun_dragon_3820621_cropped.png', EncounterType.TOWN_TAVERN: 'noun_Beer_3054928_cropped.png', EncounterType.TOWN_DOCKS: 'noun_Caravel_2421659_cropped.png', EncounterType.TOWN_MARKET: 'noun_Store_786819_cropped.png', EncounterType.TOWN_LIBRARY: 'noun_Library_3820590_cropped.png', EncounterType.TOWN_WORKSHOP: 'noun_cogs_442166_cropped.png', EncounterType.TOWN_TOWN_HALL: 'noun_brussels town hall_3284349_cropped.png', EncounterType.TOWN_TEMPLE: 'noun_temple_2382601_cropped.png', EncounterType.TOWN_REST: 'noun_Tent_3814999_cropped.png', EncounterType.TOWN_ROAD: 'noun_Hiking Trail_2686687_cropped.png', } _PATH_ICONS = { QuestPath.FORWARD: 'arrow_down.png', QuestPath.FORWARD_LEFT: 'arrow_down_left.png', QuestPath.FORWARD_RIGHT: 'arrow_down_right.png', } @dataclasses.dataclass(frozen=True) class RenderedElement: description: str src: str x: int y: int w: int h: int class RenderedEncounter(RenderedElement): pass class RenderedPath(RenderedElement): pass @dataclasses.dataclass(frozen=True) class RenderedMap: encounters: List[RenderedEncounter] paths: List[RenderedPath] def render_map(quest_map: QuestMap) -> RenderedMap: rendered_encounters = [] row: List[MapEncounter] for r, row in enumerate(quest_map.encounters): for c, encounter in enumerate(row): rendered_encounter = _render_encounter(r, c, encounter) if rendered_encounter is not None: rendered_encounters.append(rendered_encounter) rendered_paths = [] row: List[QuestPath] for r, row in enumerate(quest_map.paths): for c, path in enumerate(row): rendered_path = _render_path(r, c, path) if rendered_path is not None: rendered_paths.append(rendered_path) return RenderedMap(rendered_encounters, rendered_paths) _ENCOUNTER_W = 40 _ENCOUNTER_H = 40 _ARROW_W = 40 _ARROW_H = 20 _PADDING_W = 10 _PADDING_V = 5 _ENCOUNTER_COLUMN_W = _ENCOUNTER_W + _PADDING_W _PATH_COLUMN_W = _ARROW_W + _PADDING_W _COLUMN_W = _ENCOUNTER_COLUMN_W + _PATH_COLUMN_W _ROW_H = _ENCOUNTER_H + _PADDING_V + _ARROW_H + _PADDING_V def _render_encounter(r: int, c: int, encounter: MapEncounter) -> Optional[RenderedEncounter]: if encounter.type == EncounterType.INACCESSIBLE: return None icon = f'map/{_ENCOUNTER_ICONS[encounter.type]}' x = _COLUMN_W * c y = _ROW_H * r w = _ENCOUNTER_W h = _ENCOUNTER_H return RenderedEncounter( description=encounter.description, src=icon, x=x, y=y, w=w, h=h ) def _render_path(r: int, c: int, path: QuestPath) -> Optional[RenderedPath]: if path == QuestPath.NO_PATH: return None icon = f'map/{_PATH_ICONS[path]}' x = _ENCOUNTER_COLUMN_W * ((c + 1) // 2) + _PATH_COLUMN_W * (c // 2) y = (_ENCOUNTER_H + _PADDING_V) + _ROW_H * r w = _ARROW_W h = _ARROW_H return RenderedPath( description=path.description, src=icon, x=x, y=y, w=w, h=h )