from dataclasses import dataclass from parse import number from parse.map_header import tokenize_line @dataclass class ObjectEvent: location: tuple[int, int] sprite_id: str movement: str range_or_direction: str text_id: str items_id_or_trainer_id_or_pokemon_id: str = None trainer_number_or_pokemon_level: str = None @dataclass class WarpEvent: location: tuple[int, int] destination_map: str destination_warp_id: str @dataclass class BgEvent: location: tuple[int, int] sign_id: str @dataclass class Object: label: str warp_events: list object_events: list bg_events: list def tokenize_label(line): return ('label', line.split(':')[0].strip()) def tokenize_event(line): return list(tokenize_line(line)) def tokenize_lines(lines): for line in lines: if "_event " in line: yield tokenize_event(line) elif ':' in line: yield tokenize_label(line) def flatten(tokens): label = None warp_events = [] object_events = [] bg_events = [] for token_name, args in tokens: location = lambda : list(map(number.parse, args[0:2])) if token_name == 'label': assert label is None label = token_name elif token_name == 'object_event': event = ObjectEvent( location(), *(args[2:]) ) object_events.append(event) elif token_name == 'warp_event': destination_map, destination_warp_id = args[2:] event = WarpEvent( location(), destination_map, number.parse(destination_warp_id) ) warp_events.append(event) elif token_name == 'bg_event': event = BgEvent( location(), *(args[2:]) ) bg_events.append(event) else: assert False, (token_name, args) assert label is not None return Object( label=label, warp_events = warp_events, object_events = object_events, bg_events = bg_events, ) def parse(path): with open(path) as f: tokens = tokenize_lines(f.read().split('\n')) return flatten(tokens) def parse_all(prefix): base_path = prefix / 'data/maps/objects' paths = (p for p in base_path.iterdir() if p.is_file()) return [parse(path) for path in paths]