Skip to content

Commit

Permalink
Map species IDs and form names as Showdown expects
Browse files Browse the repository at this point in the history
  • Loading branch information
lhearachel committed Jun 6, 2024
1 parent 9614e26 commit 536f975
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 8 deletions.
3 changes: 3 additions & 0 deletions porydex.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from porydex.parse.learnsets import parse_level_up_learnsets, parse_teachable_learnsets
from porydex.parse.maps import parse_maps
from porydex.parse.moves import parse_moves
from porydex.parse.national_dex import parse_national_dex_enum
from porydex.parse.species import parse_species

def prepend_file(f, s: str):
Expand Down Expand Up @@ -65,6 +66,7 @@ def extract(args):
map_sections = parse_maps(expansion_data / 'region_map' / 'region_map_entries.h')
lvlup_learnsets = parse_level_up_learnsets(custom_headers / 'level_up_learnsets.h', move_names)
teach_learnsets = parse_teachable_learnsets(expansion_data / 'pokemon' / 'teachable_learnsets.h', move_names)
national_dex = parse_national_dex_enum(porydex.config.expansion / 'include' / 'constants' / 'pokedex.h')

species, learnsets = parse_species(
expansion_data / 'pokemon' / 'species_info.h',
Expand All @@ -75,6 +77,7 @@ def extract(args):
map_sections,
lvlup_learnsets,
teach_learnsets,
national_dex,
)
species_names = [mon['name'] for mon in sorted(species.values(), key=lambda m: m['num'])]
encounters = parse_encounters(expansion_data / 'wild_encounters.h', species_names)
Expand Down
7 changes: 6 additions & 1 deletion porydex/parse/form_tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,12 @@ def parse_table_decl(minimal: Decl, full: Decl) -> tuple[str, dict[int, str]]:
if not form_name_match:
result[val] = 'Base'
else:
result[val] = snake_to_kebab(form_name_match.group(2))
result[val] = snake_to_kebab(form_name_match.group(2)) \
.replace('Alolan', 'Alola') \
.replace('Galarian', 'Galar') \
.replace('Hisuian', 'Hisui') \
.replace('Paldean', 'Paldea') \
.replace('Gigantamax', 'Gmax')

return name, result

Expand Down
27 changes: 27 additions & 0 deletions porydex/parse/national_dex.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import pathlib
import re

def parse_national_dex_enum(fname: pathlib.Path) -> dict[str, int]:
ENUM_ENTRY_PATTERN = re.compile(r'(NATIONAL_DEX_\w+),')
enum_ctx = False
national_dex = {}
counter = 0
with open(fname, 'r', encoding='utf-8') as enum_file:
for line in enum_file:
line = line.strip()
if enum_ctx:
if line.startswith('};'):
enum_ctx = False
if national_dex:
break

match = ENUM_ENTRY_PATTERN.match(line)
if match:
national_dex[match.group(1)] = counter
counter = counter + 1

elif line.startswith('enum'):
enum_ctx = True

return national_dex

36 changes: 29 additions & 7 deletions porydex/parse/species.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,17 @@
from porydex.model import ExpansionEvoMethod, DAMAGE_TYPE, EGG_GROUP, BODY_COLOR, EVO_METHOD
from porydex.parse import load_truncated, extract_id, extract_int, extract_u8_str

EXPANSION_GEN9_START = 1289
VANILLA_GEN9_START = 906
EXPANSION_GEN9_OFFSET = EXPANSION_GEN9_START - VANILLA_GEN9_START

def parse_mon(struct_init: NamedInitializer,
ability_names: list[str],
item_names: list[str],
form_tables: dict[str, dict[int, str]],
level_up_learnsets: dict[str, dict[str, list[int]]],
teachable_learnsets: dict[str, list[str]]) -> tuple[dict, list, dict, list]:
teachable_learnsets: dict[str, dict[str, list[str]]],
national_dex: dict[str, int]) -> tuple[dict, list, dict, list]:
init_list = struct_init.expr.exprs
mon = {}
mon['num'] = extract_int(struct_init.name[0])
Expand Down Expand Up @@ -87,7 +92,7 @@ def parse_mon(struct_init: NamedInitializer,
male = 1 - female
mon['genderRatio'] = { 'M': male, 'F': female }
else:
mon['genderRatio'] = 'N'
mon['gender'] = 'N'
case 'eggGroups':
group_1 = extract_int(field_expr.exprs[0])
group_2 = extract_int(field_expr.exprs[1])
Expand Down Expand Up @@ -116,6 +121,8 @@ def parse_mon(struct_init: NamedInitializer,
if name == '??????????':
name = 'MissingNo.'
mon['name'] = name
case 'natDexNum':
mon['nationalDex'] = national_dex[extract_id(field_expr)]
case 'height':
# Stored in expansion as M * 10
mon['heightm'] = extract_int(field_expr) / 10
Expand All @@ -138,7 +145,14 @@ def parse_mon(struct_init: NamedInitializer,
if table_vals[0] != 'Base':
mon['baseForme'] = table_vals[0]

mon['formeOrder'] = [mon['name'] + (f'-{table_vals[i]}' if i > 0 else '') for i in range(len(table.keys()))]
# Ugly Urshifu hack
if mon['name'] == 'Urshifu':
mon['formeOrder'] = [mon['name'] + (f'-{table_vals[i].replace("-Style", "")}' if i > 0 else '') for i in range(len(table.keys()))]
else:
mon['formeOrder'] = [
mon['name'] + (f'-{table_vals[i]}' if i > 0 else '')
for i in range(len(table.keys()))
]

# ugly ogerpon tera forms hack
if mon['name'] == 'Ogerpon':
Expand All @@ -151,6 +165,9 @@ def parse_mon(struct_init: NamedInitializer,
# ugly ogerpon tera forms hack
if mon['name'] == 'Ogerpon' and mon['num'] not in table:
form_name = f'{table[mon["num"] - 4]}-Tera'
# ugly urshifu forms hack
elif mon['name'] == 'Urshifu':
form_name = table[mon['num']].replace('-Style', '')
else:
form_name = table[mon['num']]
mon['baseSpecies'] = mon['name']
Expand Down Expand Up @@ -297,14 +314,15 @@ def parse_species_data(species_data: ExprList,
forms: dict[str, dict[int, str]],
map_sections: list[str],
level_up_learnsets: dict[str, dict[str, list[int]]],
teachable_learnsets: dict[str, dict[str, list[str]]]) -> tuple[dict, dict]:
teachable_learnsets: dict[str, dict[str, list[str]]],
national_dex: dict[str, int]) -> tuple[dict, dict]:
# first pass: raw AST parse, build evolutions table
all_species_data = {}
all_learnsets = {}
key: str
for species_init in species_data:
try:
mon, evos, lvlup_learnset, teach_learnset = parse_mon(species_init, abilities, items, forms, level_up_learnsets, teachable_learnsets)
mon, evos, lvlup_learnset, teach_learnset = parse_mon(species_init, abilities, items, forms, level_up_learnsets, teachable_learnsets, national_dex)
all_species_data[mon['num']] = (mon, evos)

if 'name' not in mon or not mon['name']: # egg has no name nor learnset; don't try
Expand All @@ -328,6 +346,8 @@ def parse_species_data(species_data: ExprList,
for mon, _ in all_species_data.values():
if 'name' not in mon or not mon['name']: # egg has no name; don't try
continue
mon['num'] = mon['nationalDex']
del mon['nationalDex']
final_species[name_key(mon['name'])] = mon

return final_species, all_learnsets
Expand All @@ -339,7 +359,8 @@ def parse_species(fname: pathlib.Path,
forms: dict[str, dict[int, str]],
map_sections: list[str],
level_up_learnsets: dict[str, dict[str, list[int]]],
teachable_learnsets: dict[str, dict[str, list[str]]]) -> tuple[dict, dict]:
teachable_learnsets: dict[str, dict[str, list[str]]],
national_dex: dict[str, int]) -> tuple[dict, dict]:
species_data: ExprList
with yaspin(text=f'Loading species data: {fname}', color='cyan') as spinner:
species_data = load_truncated(fname, extra_includes=[
Expand All @@ -355,6 +376,7 @@ def parse_species(fname: pathlib.Path,
forms,
map_sections,
level_up_learnsets,
teachable_learnsets
teachable_learnsets,
national_dex,
)

0 comments on commit 536f975

Please sign in to comment.