pokemon/tools/parse/hidden_objects.py
2023-07-24 13:25:39 -07:00

82 lines
2.3 KiB
Python

from dataclasses import dataclass
from parse import number
from parse import map_header
def tokenize_label(line):
return line.split(':')[0].strip()
def tokenize_lines(lines):
for line in lines:
if line.strip().endswith(':'):
yield (tokenize_label(line),)
elif ('dw ' in line or 'db ' in line) and ' \\' not in line:
yield map_header.tokenize_line(line)
elif 'hidden_object' in line or 'hidden_text_predef' in line:
yield map_header.tokenize_line(line)
def flatten0(tokens):
stack = []
label = None
for t in tokens:
if len(t) == 1:
if label is not None:
yield (label, stack)
stack = []
label = None
assert label is None
label, = t
else:
stack.append(t)
@dataclass
class HiddenObject:
location: tuple[int, int]
item_id: str
object_routine: str
@dataclass
class HiddenObjects:
label: str
hidden_objects: HiddenObject
def flatten(f0):
for label, values in f0:
if values[0][0] in {"db", "dw"} and values[0][1] != ['-1']:
def vals():
for v in values:
assert len(v) == 2
v0, v1 = v
assert len(v1) == 1
if v0 in {"db", "dw"}:
yield v1[0]
yield label, list(vals())
else:
assert label.endswith("Objects"), name
def vals():
for value in values:
macro, args = value
if macro in {'hidden_object', 'hidden_text_predef'}:
yield args
else:
assert macro == 'db', macro
yield HiddenObjects(
label,
[
HiddenObject(
location=tuple(map(number.parse, [x, y])),
item_id=item_id,
object_routine=object_routine
)
for x, y, item_id, object_routine
in vals()
]
)
def parse(prefix):
path = prefix / "data/events/hidden_objects.asm"
with open(path) as f:
tokens = list(tokenize_lines(f.read().split('\n')))
return list(flatten(flatten0(tokens)))