Pokemon Emerald: Rework tags/dynamically create item and location groups (#3263)
* Pokemon Emerald: Rework location tags to categories * Pokemon Emerald: Rework item tags, automatically create item/location groups * Pokemon Emerald: Move item and location groups to data.py, add some regional location groups * Map Regions * Pokemon Emerald: Fix up location groups * Pokemon Emerald: Move groups to their own file * Pokemon Emerald: Add meta groups for location groups * Pokemon Emerald: Fix has_group using updated item group name * Pokemon Emerald: Add sanity check for maps in location groups * Pokemon Emerald: Remove missed use of location.tags * Pokemon Emerald: Reclassify white and black flutes * Pokemon Emerald: Update changelog * Pokemon Emerald: Adjust changelog --------- Co-authored-by: Tsukino <16899482+Tsukino-uwu@users.noreply.github.com>
This commit is contained in:
parent
91185f4f7c
commit
6f2464d4ad
|
@ -2,6 +2,7 @@
|
|||
|
||||
### Features
|
||||
|
||||
- Added many new item and location groups.
|
||||
- Added a Swedish translation of the setup guide.
|
||||
- The client communicates map transitions to any trackers connected to the slot.
|
||||
- Added the player's Normalize Encounter Rates option to slot data for trackers.
|
||||
|
|
|
@ -15,11 +15,11 @@ import settings
|
|||
from worlds.AutoWorld import WebWorld, World
|
||||
|
||||
from .client import PokemonEmeraldClient # Unused, but required to register with BizHawkClient
|
||||
from .data import LEGENDARY_POKEMON, MapData, SpeciesData, TrainerData, data as emerald_data
|
||||
from .items import (ITEM_GROUPS, PokemonEmeraldItem, create_item_label_to_code_map, get_item_classification,
|
||||
offset_item_value)
|
||||
from .locations import (LOCATION_GROUPS, PokemonEmeraldLocation, create_location_label_to_id_map,
|
||||
create_locations_with_tags, set_free_fly, set_legendary_cave_entrances)
|
||||
from .data import LEGENDARY_POKEMON, MapData, SpeciesData, TrainerData, LocationCategory, data as emerald_data
|
||||
from .groups import ITEM_GROUPS, LOCATION_GROUPS
|
||||
from .items import PokemonEmeraldItem, create_item_label_to_code_map, get_item_classification, offset_item_value
|
||||
from .locations import (PokemonEmeraldLocation, create_location_label_to_id_map, create_locations_by_category,
|
||||
set_free_fly, set_legendary_cave_entrances)
|
||||
from .opponents import randomize_opponent_parties
|
||||
from .options import (Goal, DarkCavesRequireFlash, HmRequirements, ItemPoolType, PokemonEmeraldOptions,
|
||||
RandomizeWildPokemon, RandomizeBadges, RandomizeHms, NormanRequirement)
|
||||
|
@ -133,9 +133,10 @@ class PokemonEmeraldWorld(World):
|
|||
|
||||
@classmethod
|
||||
def stage_assert_generate(cls, multiworld: MultiWorld) -> None:
|
||||
from .sanity_check import validate_regions
|
||||
from .sanity_check import validate_regions, validate_group_maps
|
||||
|
||||
assert validate_regions()
|
||||
assert validate_group_maps()
|
||||
|
||||
def get_filler_item_name(self) -> str:
|
||||
return "Great Ball"
|
||||
|
@ -237,24 +238,32 @@ class PokemonEmeraldWorld(World):
|
|||
|
||||
def create_regions(self) -> None:
|
||||
from .regions import create_regions
|
||||
regions = create_regions(self)
|
||||
all_regions = create_regions(self)
|
||||
|
||||
tags = {"Badge", "HM", "KeyItem", "Rod", "Bike", "EventTicket"} # Tags with progression items always included
|
||||
# Categories with progression items always included
|
||||
categories = {
|
||||
LocationCategory.BADGE,
|
||||
LocationCategory.HM,
|
||||
LocationCategory.KEY,
|
||||
LocationCategory.ROD,
|
||||
LocationCategory.BIKE,
|
||||
LocationCategory.TICKET
|
||||
}
|
||||
if self.options.overworld_items:
|
||||
tags.add("OverworldItem")
|
||||
categories.add(LocationCategory.OVERWORLD_ITEM)
|
||||
if self.options.hidden_items:
|
||||
tags.add("HiddenItem")
|
||||
categories.add(LocationCategory.HIDDEN_ITEM)
|
||||
if self.options.npc_gifts:
|
||||
tags.add("NpcGift")
|
||||
categories.add(LocationCategory.GIFT)
|
||||
if self.options.berry_trees:
|
||||
tags.add("BerryTree")
|
||||
categories.add(LocationCategory.BERRY_TREE)
|
||||
if self.options.dexsanity:
|
||||
tags.add("Pokedex")
|
||||
categories.add(LocationCategory.POKEDEX)
|
||||
if self.options.trainersanity:
|
||||
tags.add("Trainer")
|
||||
create_locations_with_tags(self, regions, tags)
|
||||
categories.add(LocationCategory.TRAINER)
|
||||
create_locations_by_category(self, all_regions, categories)
|
||||
|
||||
self.multiworld.regions.extend(regions.values())
|
||||
self.multiworld.regions.extend(all_regions.values())
|
||||
|
||||
# Exclude locations which are always locked behind the player's goal
|
||||
def exclude_locations(location_names: List[str]):
|
||||
|
@ -325,21 +334,21 @@ class PokemonEmeraldWorld(World):
|
|||
# Filter progression items which shouldn't be shuffled into the itempool.
|
||||
# Their locations will still exist, but event items will be placed and
|
||||
# locked at their vanilla locations instead.
|
||||
filter_tags = set()
|
||||
filter_categories = set()
|
||||
|
||||
if not self.options.key_items:
|
||||
filter_tags.add("KeyItem")
|
||||
filter_categories.add(LocationCategory.KEY)
|
||||
if not self.options.rods:
|
||||
filter_tags.add("Rod")
|
||||
filter_categories.add(LocationCategory.ROD)
|
||||
if not self.options.bikes:
|
||||
filter_tags.add("Bike")
|
||||
filter_categories.add(LocationCategory.BIKE)
|
||||
if not self.options.event_tickets:
|
||||
filter_tags.add("EventTicket")
|
||||
filter_categories.add(LocationCategory.TICKET)
|
||||
|
||||
if self.options.badges in {RandomizeBadges.option_vanilla, RandomizeBadges.option_shuffle}:
|
||||
filter_tags.add("Badge")
|
||||
filter_categories.add(LocationCategory.BADGE)
|
||||
if self.options.hms in {RandomizeHms.option_vanilla, RandomizeHms.option_shuffle}:
|
||||
filter_tags.add("HM")
|
||||
filter_categories.add(LocationCategory.HM)
|
||||
|
||||
# If Badges and HMs are set to the `shuffle` option, don't add them to
|
||||
# the normal item pool, but do create their items and save them and
|
||||
|
@ -347,17 +356,17 @@ class PokemonEmeraldWorld(World):
|
|||
if self.options.badges == RandomizeBadges.option_shuffle:
|
||||
self.badge_shuffle_info = [
|
||||
(location, self.create_item_by_code(location.default_item_code))
|
||||
for location in [l for l in item_locations if "Badge" in l.tags]
|
||||
for location in [l for l in item_locations if emerald_data.locations[l.key].category == LocationCategory.BADGE]
|
||||
]
|
||||
if self.options.hms == RandomizeHms.option_shuffle:
|
||||
self.hm_shuffle_info = [
|
||||
(location, self.create_item_by_code(location.default_item_code))
|
||||
for location in [l for l in item_locations if "HM" in l.tags]
|
||||
for location in [l for l in item_locations if emerald_data.locations[l.key].category == LocationCategory.HM]
|
||||
]
|
||||
|
||||
# Filter down locations to actual items that will be filled and create
|
||||
# the itempool.
|
||||
item_locations = [location for location in item_locations if len(filter_tags & location.tags) == 0]
|
||||
item_locations = [location for location in item_locations if emerald_data.locations[location.key].category not in filter_categories]
|
||||
default_itempool = [self.create_item_by_code(location.default_item_code) for location in item_locations]
|
||||
|
||||
# Take the itempool as-is
|
||||
|
@ -366,7 +375,8 @@ class PokemonEmeraldWorld(World):
|
|||
|
||||
# Recreate the itempool from random items
|
||||
elif self.options.item_pool_type in (ItemPoolType.option_diverse, ItemPoolType.option_diverse_balanced):
|
||||
item_categories = ["Ball", "Heal", "Candy", "Vitamin", "EvoStone", "Money", "TM", "Held", "Misc", "Berry"]
|
||||
item_categories = ["Ball", "Healing", "Rare Candy", "Vitamin", "Evolution Stone",
|
||||
"Money", "TM", "Held", "Misc", "Berry"]
|
||||
|
||||
# Count occurrences of types of vanilla items in pool
|
||||
item_category_counter = Counter()
|
||||
|
@ -436,25 +446,26 @@ class PokemonEmeraldWorld(World):
|
|||
|
||||
# Key items which are considered in access rules but not randomized are converted to events and placed
|
||||
# in their vanilla locations so that the player can have them in their inventory for logic.
|
||||
def convert_unrandomized_items_to_events(tag: str) -> None:
|
||||
def convert_unrandomized_items_to_events(category: LocationCategory) -> None:
|
||||
for location in self.multiworld.get_locations(self.player):
|
||||
if location.tags is not None and tag in location.tags:
|
||||
assert isinstance(location, PokemonEmeraldLocation)
|
||||
if location.key is not None and emerald_data.locations[location.key].category == category:
|
||||
location.place_locked_item(self.create_event(self.item_id_to_name[location.default_item_code]))
|
||||
location.progress_type = LocationProgressType.DEFAULT
|
||||
location.address = None
|
||||
|
||||
if self.options.badges == RandomizeBadges.option_vanilla:
|
||||
convert_unrandomized_items_to_events("Badge")
|
||||
convert_unrandomized_items_to_events(LocationCategory.BADGE)
|
||||
if self.options.hms == RandomizeHms.option_vanilla:
|
||||
convert_unrandomized_items_to_events("HM")
|
||||
convert_unrandomized_items_to_events(LocationCategory.HM)
|
||||
if not self.options.rods:
|
||||
convert_unrandomized_items_to_events("Rod")
|
||||
convert_unrandomized_items_to_events(LocationCategory.ROD)
|
||||
if not self.options.bikes:
|
||||
convert_unrandomized_items_to_events("Bike")
|
||||
convert_unrandomized_items_to_events(LocationCategory.BIKE)
|
||||
if not self.options.event_tickets:
|
||||
convert_unrandomized_items_to_events("EventTicket")
|
||||
convert_unrandomized_items_to_events(LocationCategory.TICKET)
|
||||
if not self.options.key_items:
|
||||
convert_unrandomized_items_to_events("KeyItem")
|
||||
convert_unrandomized_items_to_events(LocationCategory.KEY)
|
||||
|
||||
def pre_fill(self) -> None:
|
||||
# Badges and HMs that are set to shuffle need to be placed at
|
||||
|
|
|
@ -117,6 +117,21 @@ class ItemData(NamedTuple):
|
|||
tags: FrozenSet[str]
|
||||
|
||||
|
||||
class LocationCategory(IntEnum):
|
||||
BADGE = 0
|
||||
HM = 1
|
||||
KEY = 2
|
||||
ROD = 3
|
||||
BIKE = 4
|
||||
TICKET = 5
|
||||
OVERWORLD_ITEM = 6
|
||||
HIDDEN_ITEM = 7
|
||||
GIFT = 8
|
||||
BERRY_TREE = 9
|
||||
TRAINER = 10
|
||||
POKEDEX = 11
|
||||
|
||||
|
||||
class LocationData(NamedTuple):
|
||||
name: str
|
||||
label: str
|
||||
|
@ -124,6 +139,7 @@ class LocationData(NamedTuple):
|
|||
default_item: int
|
||||
address: Union[int, List[int]]
|
||||
flag: int
|
||||
category: LocationCategory
|
||||
tags: FrozenSet[str]
|
||||
|
||||
|
||||
|
@ -431,6 +447,7 @@ def _init() -> None:
|
|||
location_json["default_item"],
|
||||
[location_json["address"]] + [j["address"] for j in alternate_rival_jsons],
|
||||
location_json["flag"],
|
||||
LocationCategory[location_attributes_json[location_name]["category"]],
|
||||
frozenset(location_attributes_json[location_name]["tags"])
|
||||
)
|
||||
else:
|
||||
|
@ -441,6 +458,7 @@ def _init() -> None:
|
|||
location_json["default_item"],
|
||||
location_json["address"],
|
||||
location_json["flag"],
|
||||
LocationCategory[location_attributes_json[location_name]["category"]],
|
||||
frozenset(location_attributes_json[location_name]["tags"])
|
||||
)
|
||||
new_region.locations.append(location_name)
|
||||
|
@ -948,6 +966,7 @@ def _init() -> None:
|
|||
evo_stage_to_ball_map[evo_stage],
|
||||
data.locations[dex_location_name].address,
|
||||
data.locations[dex_location_name].flag,
|
||||
data.locations[dex_location_name].category,
|
||||
data.locations[dex_location_name].tags
|
||||
)
|
||||
|
||||
|
|
|
@ -52,49 +52,49 @@
|
|||
"ITEM_HM_CUT": {
|
||||
"label": "HM01 Cut",
|
||||
"classification": "PROGRESSION",
|
||||
"tags": ["HM", "Unique"],
|
||||
"tags": ["HM", "HM01", "Unique"],
|
||||
"modern_id": 420
|
||||
},
|
||||
"ITEM_HM_FLY": {
|
||||
"label": "HM02 Fly",
|
||||
"classification": "PROGRESSION",
|
||||
"tags": ["HM", "Unique"],
|
||||
"tags": ["HM", "HM02", "Unique"],
|
||||
"modern_id": 421
|
||||
},
|
||||
"ITEM_HM_SURF": {
|
||||
"label": "HM03 Surf",
|
||||
"classification": "PROGRESSION",
|
||||
"tags": ["HM", "Unique"],
|
||||
"tags": ["HM", "HM03", "Unique"],
|
||||
"modern_id": 422
|
||||
},
|
||||
"ITEM_HM_STRENGTH": {
|
||||
"label": "HM04 Strength",
|
||||
"classification": "PROGRESSION",
|
||||
"tags": ["HM", "Unique"],
|
||||
"tags": ["HM", "HM04", "Unique"],
|
||||
"modern_id": 423
|
||||
},
|
||||
"ITEM_HM_FLASH": {
|
||||
"label": "HM05 Flash",
|
||||
"classification": "PROGRESSION",
|
||||
"tags": ["HM", "Unique"],
|
||||
"tags": ["HM", "HM05", "Unique"],
|
||||
"modern_id": 424
|
||||
},
|
||||
"ITEM_HM_ROCK_SMASH": {
|
||||
"label": "HM06 Rock Smash",
|
||||
"classification": "PROGRESSION",
|
||||
"tags": ["HM", "Unique"],
|
||||
"tags": ["HM", "HM06", "Unique"],
|
||||
"modern_id": 425
|
||||
},
|
||||
"ITEM_HM_WATERFALL": {
|
||||
"label": "HM07 Waterfall",
|
||||
"classification": "PROGRESSION",
|
||||
"tags": ["HM", "Unique"],
|
||||
"tags": ["HM", "HM07", "Unique"],
|
||||
"modern_id": 737
|
||||
},
|
||||
"ITEM_HM_DIVE": {
|
||||
"label": "HM08 Dive",
|
||||
"classification": "PROGRESSION",
|
||||
"tags": ["HM", "Unique"],
|
||||
"tags": ["HM", "HM08", "Unique"],
|
||||
"modern_id": null
|
||||
},
|
||||
|
||||
|
@ -375,169 +375,169 @@
|
|||
"ITEM_POTION": {
|
||||
"label": "Potion",
|
||||
"classification": "FILLER",
|
||||
"tags": ["Heal"],
|
||||
"tags": ["Healing"],
|
||||
"modern_id": 17
|
||||
},
|
||||
"ITEM_ANTIDOTE": {
|
||||
"label": "Antidote",
|
||||
"classification": "FILLER",
|
||||
"tags": ["Heal"],
|
||||
"tags": ["Healing"],
|
||||
"modern_id": 18
|
||||
},
|
||||
"ITEM_BURN_HEAL": {
|
||||
"label": "Burn Heal",
|
||||
"classification": "FILLER",
|
||||
"tags": ["Heal"],
|
||||
"tags": ["Healing"],
|
||||
"modern_id": 19
|
||||
},
|
||||
"ITEM_ICE_HEAL": {
|
||||
"label": "Ice Heal",
|
||||
"classification": "FILLER",
|
||||
"tags": ["Heal"],
|
||||
"tags": ["Healing"],
|
||||
"modern_id": 20
|
||||
},
|
||||
"ITEM_AWAKENING": {
|
||||
"label": "Awakening",
|
||||
"classification": "FILLER",
|
||||
"tags": ["Heal"],
|
||||
"tags": ["Healing"],
|
||||
"modern_id": 21
|
||||
},
|
||||
"ITEM_PARALYZE_HEAL": {
|
||||
"label": "Paralyze Heal",
|
||||
"classification": "FILLER",
|
||||
"tags": ["Heal"],
|
||||
"tags": ["Healing"],
|
||||
"modern_id": 22
|
||||
},
|
||||
"ITEM_FULL_RESTORE": {
|
||||
"label": "Full Restore",
|
||||
"classification": "FILLER",
|
||||
"tags": ["Heal"],
|
||||
"tags": ["Healing"],
|
||||
"modern_id": 23
|
||||
},
|
||||
"ITEM_MAX_POTION": {
|
||||
"label": "Max Potion",
|
||||
"classification": "FILLER",
|
||||
"tags": ["Heal"],
|
||||
"tags": ["Healing"],
|
||||
"modern_id": 24
|
||||
},
|
||||
"ITEM_HYPER_POTION": {
|
||||
"label": "Hyper Potion",
|
||||
"classification": "FILLER",
|
||||
"tags": ["Heal"],
|
||||
"tags": ["Healing"],
|
||||
"modern_id": 25
|
||||
},
|
||||
"ITEM_SUPER_POTION": {
|
||||
"label": "Super Potion",
|
||||
"classification": "FILLER",
|
||||
"tags": ["Heal"],
|
||||
"tags": ["Healing"],
|
||||
"modern_id": 26
|
||||
},
|
||||
"ITEM_FULL_HEAL": {
|
||||
"label": "Full Heal",
|
||||
"classification": "FILLER",
|
||||
"tags": ["Heal"],
|
||||
"tags": ["Healing"],
|
||||
"modern_id": 27
|
||||
},
|
||||
"ITEM_REVIVE": {
|
||||
"label": "Revive",
|
||||
"classification": "FILLER",
|
||||
"tags": ["Heal"],
|
||||
"tags": ["Healing"],
|
||||
"modern_id": 28
|
||||
},
|
||||
"ITEM_MAX_REVIVE": {
|
||||
"label": "Max Revive",
|
||||
"classification": "FILLER",
|
||||
"tags": ["Heal"],
|
||||
"tags": ["Healing"],
|
||||
"modern_id": 29
|
||||
},
|
||||
"ITEM_FRESH_WATER": {
|
||||
"label": "Fresh Water",
|
||||
"classification": "FILLER",
|
||||
"tags": ["Heal"],
|
||||
"tags": ["Healing"],
|
||||
"modern_id": 30
|
||||
},
|
||||
"ITEM_SODA_POP": {
|
||||
"label": "Soda Pop",
|
||||
"classification": "FILLER",
|
||||
"tags": ["Heal"],
|
||||
"tags": ["Healing"],
|
||||
"modern_id": 31
|
||||
},
|
||||
"ITEM_LEMONADE": {
|
||||
"label": "Lemonade",
|
||||
"classification": "FILLER",
|
||||
"tags": ["Heal"],
|
||||
"tags": ["Healing"],
|
||||
"modern_id": 32
|
||||
},
|
||||
"ITEM_MOOMOO_MILK": {
|
||||
"label": "Moomoo Milk",
|
||||
"classification": "FILLER",
|
||||
"tags": ["Heal"],
|
||||
"tags": ["Healing"],
|
||||
"modern_id": 33
|
||||
},
|
||||
"ITEM_ENERGY_POWDER": {
|
||||
"label": "Energy Powder",
|
||||
"classification": "FILLER",
|
||||
"tags": ["Heal"],
|
||||
"tags": ["Healing"],
|
||||
"modern_id": 34
|
||||
},
|
||||
"ITEM_ENERGY_ROOT": {
|
||||
"label": "Energy Root",
|
||||
"classification": "FILLER",
|
||||
"tags": ["Heal"],
|
||||
"tags": ["Healing"],
|
||||
"modern_id": 35
|
||||
},
|
||||
"ITEM_HEAL_POWDER": {
|
||||
"label": "Heal Powder",
|
||||
"classification": "FILLER",
|
||||
"tags": ["Heal"],
|
||||
"tags": ["Healing"],
|
||||
"modern_id": 36
|
||||
},
|
||||
"ITEM_REVIVAL_HERB": {
|
||||
"label": "Revival Herb",
|
||||
"classification": "FILLER",
|
||||
"tags": ["Heal"],
|
||||
"tags": ["Healing"],
|
||||
"modern_id": 37
|
||||
},
|
||||
"ITEM_ETHER": {
|
||||
"label": "Ether",
|
||||
"classification": "FILLER",
|
||||
"tags": ["Heal"],
|
||||
"tags": ["Healing"],
|
||||
"modern_id": 38
|
||||
},
|
||||
"ITEM_MAX_ETHER": {
|
||||
"label": "Max Ether",
|
||||
"classification": "FILLER",
|
||||
"tags": ["Heal"],
|
||||
"tags": ["Healing"],
|
||||
"modern_id": 39
|
||||
},
|
||||
"ITEM_ELIXIR": {
|
||||
"label": "Elixir",
|
||||
"classification": "FILLER",
|
||||
"tags": ["Heal"],
|
||||
"tags": ["Healing"],
|
||||
"modern_id": 40
|
||||
},
|
||||
"ITEM_MAX_ELIXIR": {
|
||||
"label": "Max Elixir",
|
||||
"classification": "FILLER",
|
||||
"tags": ["Heal"],
|
||||
"tags": ["Healing"],
|
||||
"modern_id": 41
|
||||
},
|
||||
"ITEM_LAVA_COOKIE": {
|
||||
"label": "Lava Cookie",
|
||||
"classification": "FILLER",
|
||||
"tags": ["Heal"],
|
||||
"tags": ["Healing"],
|
||||
"modern_id": 42
|
||||
},
|
||||
"ITEM_BERRY_JUICE": {
|
||||
"label": "Berry Juice",
|
||||
"classification": "FILLER",
|
||||
"tags": ["Heal"],
|
||||
"tags": ["Healing"],
|
||||
"modern_id": 43
|
||||
},
|
||||
"ITEM_SACRED_ASH": {
|
||||
"label": "Sacred Ash",
|
||||
"classification": "USEFUL",
|
||||
"tags": ["Heal"],
|
||||
"tags": ["Healing"],
|
||||
"modern_id": 44
|
||||
},
|
||||
|
||||
|
@ -736,19 +736,19 @@
|
|||
},
|
||||
"ITEM_BLACK_FLUTE": {
|
||||
"label": "Black Flute",
|
||||
"classification": "FILLER",
|
||||
"classification": "USEFUL",
|
||||
"tags": ["Misc"],
|
||||
"modern_id": 68
|
||||
},
|
||||
"ITEM_WHITE_FLUTE": {
|
||||
"label": "White Flute",
|
||||
"classification": "FILLER",
|
||||
"classification": "USEFUL",
|
||||
"tags": ["Misc"],
|
||||
"modern_id": 69
|
||||
},
|
||||
"ITEM_HEART_SCALE": {
|
||||
"label": "Heart Scale",
|
||||
"classification": "FILLER",
|
||||
"classification": "USEFUL",
|
||||
"tags": ["Misc"],
|
||||
"modern_id": 93
|
||||
},
|
||||
|
@ -757,37 +757,37 @@
|
|||
"ITEM_SUN_STONE": {
|
||||
"label": "Sun Stone",
|
||||
"classification": "USEFUL",
|
||||
"tags": ["EvoStone"],
|
||||
"tags": ["Evolution Stone"],
|
||||
"modern_id": 80
|
||||
},
|
||||
"ITEM_MOON_STONE": {
|
||||
"label": "Moon Stone",
|
||||
"classification": "USEFUL",
|
||||
"tags": ["EvoStone"],
|
||||
"tags": ["Evolution Stone"],
|
||||
"modern_id": 81
|
||||
},
|
||||
"ITEM_FIRE_STONE": {
|
||||
"label": "Fire Stone",
|
||||
"classification": "USEFUL",
|
||||
"tags": ["EvoStone"],
|
||||
"tags": ["Evolution Stone"],
|
||||
"modern_id": 82
|
||||
},
|
||||
"ITEM_THUNDER_STONE": {
|
||||
"label": "Thunder Stone",
|
||||
"classification": "USEFUL",
|
||||
"tags": ["EvoStone"],
|
||||
"tags": ["Evolution Stone"],
|
||||
"modern_id": 83
|
||||
},
|
||||
"ITEM_WATER_STONE": {
|
||||
"label": "Water Stone",
|
||||
"classification": "USEFUL",
|
||||
"tags": ["EvoStone"],
|
||||
"tags": ["Evolution Stone"],
|
||||
"modern_id": 84
|
||||
},
|
||||
"ITEM_LEAF_STONE": {
|
||||
"label": "Leaf Stone",
|
||||
"classification": "USEFUL",
|
||||
"tags": ["EvoStone"],
|
||||
"tags": ["Evolution Stone"],
|
||||
"modern_id": 85
|
||||
},
|
||||
|
||||
|
@ -1215,7 +1215,7 @@
|
|||
"ITEM_KINGS_ROCK": {
|
||||
"label": "King's Rock",
|
||||
"classification": "USEFUL",
|
||||
"tags": ["Held"],
|
||||
"tags": ["Held", "Evolution Stone"],
|
||||
"modern_id": 221
|
||||
},
|
||||
"ITEM_SILVER_POWDER": {
|
||||
|
@ -1245,13 +1245,13 @@
|
|||
"ITEM_DEEP_SEA_TOOTH": {
|
||||
"label": "Deep Sea Tooth",
|
||||
"classification": "USEFUL",
|
||||
"tags": ["Held"],
|
||||
"tags": ["Held", "Evolution Stone"],
|
||||
"modern_id": 226
|
||||
},
|
||||
"ITEM_DEEP_SEA_SCALE": {
|
||||
"label": "Deep Sea Scale",
|
||||
"classification": "USEFUL",
|
||||
"tags": ["Held"],
|
||||
"tags": ["Held", "Evolution Stone"],
|
||||
"modern_id": 227
|
||||
},
|
||||
"ITEM_SMOKE_BALL": {
|
||||
|
@ -1287,7 +1287,7 @@
|
|||
"ITEM_METAL_COAT": {
|
||||
"label": "Metal Coat",
|
||||
"classification": "USEFUL",
|
||||
"tags": ["Held"],
|
||||
"tags": ["Held", "Evolution Stone"],
|
||||
"modern_id": 233
|
||||
},
|
||||
"ITEM_LEFTOVERS": {
|
||||
|
@ -1299,7 +1299,7 @@
|
|||
"ITEM_DRAGON_SCALE": {
|
||||
"label": "Dragon Scale",
|
||||
"classification": "USEFUL",
|
||||
"tags": ["Held"],
|
||||
"tags": ["Held", "Evolution Stone"],
|
||||
"modern_id": 235
|
||||
},
|
||||
"ITEM_LIGHT_BALL": {
|
||||
|
@ -1401,7 +1401,7 @@
|
|||
"ITEM_UP_GRADE": {
|
||||
"label": "Up-Grade",
|
||||
"classification": "USEFUL",
|
||||
"tags": ["Held"],
|
||||
"tags": ["Held", "Evolution Stone"],
|
||||
"modern_id": 252
|
||||
},
|
||||
"ITEM_SHELL_BELL": {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,721 @@
|
|||
from typing import Dict, Set
|
||||
|
||||
from .data import LocationCategory, data
|
||||
|
||||
|
||||
# Item Groups
|
||||
ITEM_GROUPS: Dict[str, Set[str]] = {}
|
||||
|
||||
for item in data.items.values():
|
||||
for tag in item.tags:
|
||||
if tag not in ITEM_GROUPS:
|
||||
ITEM_GROUPS[tag] = set()
|
||||
ITEM_GROUPS[tag].add(item.label)
|
||||
|
||||
# Location Groups
|
||||
_LOCATION_GROUP_MAPS = {
|
||||
"Abandoned Ship": {
|
||||
"MAP_ABANDONED_SHIP_CAPTAINS_OFFICE",
|
||||
"MAP_ABANDONED_SHIP_CORRIDORS_1F",
|
||||
"MAP_ABANDONED_SHIP_CORRIDORS_B1F",
|
||||
"MAP_ABANDONED_SHIP_DECK",
|
||||
"MAP_ABANDONED_SHIP_HIDDEN_FLOOR_CORRIDORS",
|
||||
"MAP_ABANDONED_SHIP_HIDDEN_FLOOR_ROOMS",
|
||||
"MAP_ABANDONED_SHIP_ROOMS2_1F",
|
||||
"MAP_ABANDONED_SHIP_ROOMS2_B1F",
|
||||
"MAP_ABANDONED_SHIP_ROOMS_1F",
|
||||
"MAP_ABANDONED_SHIP_ROOMS_B1F",
|
||||
"MAP_ABANDONED_SHIP_ROOM_B1F",
|
||||
"MAP_ABANDONED_SHIP_UNDERWATER1",
|
||||
"MAP_ABANDONED_SHIP_UNDERWATER2",
|
||||
},
|
||||
"Aqua Hideout": {
|
||||
"MAP_AQUA_HIDEOUT_1F",
|
||||
"MAP_AQUA_HIDEOUT_B1F",
|
||||
"MAP_AQUA_HIDEOUT_B2F",
|
||||
},
|
||||
"Battle Frontier": {
|
||||
"MAP_ARTISAN_CAVE_1F",
|
||||
"MAP_ARTISAN_CAVE_B1F",
|
||||
"MAP_BATTLE_FRONTIER_BATTLE_ARENA_BATTLE_ROOM",
|
||||
"MAP_BATTLE_FRONTIER_BATTLE_ARENA_CORRIDOR",
|
||||
"MAP_BATTLE_FRONTIER_BATTLE_ARENA_LOBBY",
|
||||
"MAP_BATTLE_FRONTIER_BATTLE_DOME_BATTLE_ROOM",
|
||||
"MAP_BATTLE_FRONTIER_BATTLE_DOME_CORRIDOR",
|
||||
"MAP_BATTLE_FRONTIER_BATTLE_DOME_LOBBY",
|
||||
"MAP_BATTLE_FRONTIER_BATTLE_DOME_PRE_BATTLE_ROOM",
|
||||
"MAP_BATTLE_FRONTIER_BATTLE_FACTORY_BATTLE_ROOM",
|
||||
"MAP_BATTLE_FRONTIER_BATTLE_FACTORY_LOBBY",
|
||||
"MAP_BATTLE_FRONTIER_BATTLE_FACTORY_PRE_BATTLE_ROOM",
|
||||
"MAP_BATTLE_FRONTIER_BATTLE_PALACE_BATTLE_ROOM",
|
||||
"MAP_BATTLE_FRONTIER_BATTLE_PALACE_CORRIDOR",
|
||||
"MAP_BATTLE_FRONTIER_BATTLE_PALACE_LOBBY",
|
||||
"MAP_BATTLE_FRONTIER_BATTLE_PIKE_CORRIDOR",
|
||||
"MAP_BATTLE_FRONTIER_BATTLE_PIKE_LOBBY",
|
||||
"MAP_BATTLE_FRONTIER_BATTLE_PIKE_ROOM_FINAL",
|
||||
"MAP_BATTLE_FRONTIER_BATTLE_PIKE_ROOM_NORMAL",
|
||||
"MAP_BATTLE_FRONTIER_BATTLE_PIKE_ROOM_WILD_MONS",
|
||||
"MAP_BATTLE_FRONTIER_BATTLE_PIKE_THREE_PATH_ROOM",
|
||||
"MAP_BATTLE_FRONTIER_BATTLE_PYRAMID_FLOOR",
|
||||
"MAP_BATTLE_FRONTIER_BATTLE_PYRAMID_LOBBY",
|
||||
"MAP_BATTLE_FRONTIER_BATTLE_PYRAMID_TOP",
|
||||
"MAP_BATTLE_FRONTIER_BATTLE_TOWER_BATTLE_ROOM",
|
||||
"MAP_BATTLE_FRONTIER_BATTLE_TOWER_CORRIDOR",
|
||||
"MAP_BATTLE_FRONTIER_BATTLE_TOWER_ELEVATOR",
|
||||
"MAP_BATTLE_FRONTIER_BATTLE_TOWER_LOBBY",
|
||||
"MAP_BATTLE_FRONTIER_BATTLE_TOWER_MULTI_BATTLE_ROOM",
|
||||
"MAP_BATTLE_FRONTIER_BATTLE_TOWER_MULTI_CORRIDOR",
|
||||
"MAP_BATTLE_FRONTIER_BATTLE_TOWER_MULTI_PARTNER_ROOM",
|
||||
"MAP_BATTLE_FRONTIER_EXCHANGE_SERVICE_CORNER",
|
||||
"MAP_BATTLE_FRONTIER_LOUNGE1",
|
||||
"MAP_BATTLE_FRONTIER_LOUNGE2",
|
||||
"MAP_BATTLE_FRONTIER_LOUNGE3",
|
||||
"MAP_BATTLE_FRONTIER_LOUNGE4",
|
||||
"MAP_BATTLE_FRONTIER_LOUNGE5",
|
||||
"MAP_BATTLE_FRONTIER_LOUNGE6",
|
||||
"MAP_BATTLE_FRONTIER_LOUNGE7",
|
||||
"MAP_BATTLE_FRONTIER_LOUNGE8",
|
||||
"MAP_BATTLE_FRONTIER_LOUNGE9",
|
||||
"MAP_BATTLE_FRONTIER_MART",
|
||||
"MAP_BATTLE_FRONTIER_OUTSIDE_EAST",
|
||||
"MAP_BATTLE_FRONTIER_OUTSIDE_WEST",
|
||||
"MAP_BATTLE_FRONTIER_POKEMON_CENTER_1F",
|
||||
"MAP_BATTLE_FRONTIER_POKEMON_CENTER_2F",
|
||||
"MAP_BATTLE_FRONTIER_RANKING_HALL",
|
||||
"MAP_BATTLE_FRONTIER_RECEPTION_GATE",
|
||||
"MAP_BATTLE_FRONTIER_SCOTTS_HOUSE",
|
||||
"MAP_BATTLE_PYRAMID_SQUARE01",
|
||||
"MAP_BATTLE_PYRAMID_SQUARE02",
|
||||
"MAP_BATTLE_PYRAMID_SQUARE03",
|
||||
"MAP_BATTLE_PYRAMID_SQUARE04",
|
||||
"MAP_BATTLE_PYRAMID_SQUARE05",
|
||||
"MAP_BATTLE_PYRAMID_SQUARE06",
|
||||
"MAP_BATTLE_PYRAMID_SQUARE07",
|
||||
"MAP_BATTLE_PYRAMID_SQUARE08",
|
||||
"MAP_BATTLE_PYRAMID_SQUARE09",
|
||||
"MAP_BATTLE_PYRAMID_SQUARE10",
|
||||
"MAP_BATTLE_PYRAMID_SQUARE11",
|
||||
"MAP_BATTLE_PYRAMID_SQUARE12",
|
||||
"MAP_BATTLE_PYRAMID_SQUARE13",
|
||||
"MAP_BATTLE_PYRAMID_SQUARE14",
|
||||
"MAP_BATTLE_PYRAMID_SQUARE15",
|
||||
"MAP_BATTLE_PYRAMID_SQUARE16",
|
||||
},
|
||||
"Birth Island": {
|
||||
"MAP_BIRTH_ISLAND_EXTERIOR",
|
||||
"MAP_BIRTH_ISLAND_HARBOR",
|
||||
},
|
||||
"Contest Hall": {
|
||||
"MAP_CONTEST_HALL",
|
||||
"MAP_CONTEST_HALL_BEAUTY",
|
||||
"MAP_CONTEST_HALL_COOL",
|
||||
"MAP_CONTEST_HALL_CUTE",
|
||||
"MAP_CONTEST_HALL_SMART",
|
||||
"MAP_CONTEST_HALL_TOUGH",
|
||||
},
|
||||
"Dewford Town": {
|
||||
"MAP_DEWFORD_TOWN",
|
||||
"MAP_DEWFORD_TOWN_GYM",
|
||||
"MAP_DEWFORD_TOWN_HALL",
|
||||
"MAP_DEWFORD_TOWN_HOUSE1",
|
||||
"MAP_DEWFORD_TOWN_HOUSE2",
|
||||
"MAP_DEWFORD_TOWN_POKEMON_CENTER_1F",
|
||||
"MAP_DEWFORD_TOWN_POKEMON_CENTER_2F",
|
||||
},
|
||||
"Ever Grande City": {
|
||||
"MAP_EVER_GRANDE_CITY",
|
||||
"MAP_EVER_GRANDE_CITY_CHAMPIONS_ROOM",
|
||||
"MAP_EVER_GRANDE_CITY_DRAKES_ROOM",
|
||||
"MAP_EVER_GRANDE_CITY_GLACIAS_ROOM",
|
||||
"MAP_EVER_GRANDE_CITY_HALL1",
|
||||
"MAP_EVER_GRANDE_CITY_HALL2",
|
||||
"MAP_EVER_GRANDE_CITY_HALL3",
|
||||
"MAP_EVER_GRANDE_CITY_HALL4",
|
||||
"MAP_EVER_GRANDE_CITY_HALL5",
|
||||
"MAP_EVER_GRANDE_CITY_HALL_OF_FAME",
|
||||
"MAP_EVER_GRANDE_CITY_PHOEBES_ROOM",
|
||||
"MAP_EVER_GRANDE_CITY_POKEMON_CENTER_1F",
|
||||
"MAP_EVER_GRANDE_CITY_POKEMON_CENTER_2F",
|
||||
"MAP_EVER_GRANDE_CITY_POKEMON_LEAGUE_1F",
|
||||
"MAP_EVER_GRANDE_CITY_POKEMON_LEAGUE_2F",
|
||||
"MAP_EVER_GRANDE_CITY_SIDNEYS_ROOM",
|
||||
},
|
||||
"Fallarbor Town": {
|
||||
"MAP_FALLARBOR_TOWN",
|
||||
"MAP_FALLARBOR_TOWN_BATTLE_TENT_BATTLE_ROOM",
|
||||
"MAP_FALLARBOR_TOWN_BATTLE_TENT_CORRIDOR",
|
||||
"MAP_FALLARBOR_TOWN_BATTLE_TENT_LOBBY",
|
||||
"MAP_FALLARBOR_TOWN_COZMOS_HOUSE",
|
||||
"MAP_FALLARBOR_TOWN_MART",
|
||||
"MAP_FALLARBOR_TOWN_MOVE_RELEARNERS_HOUSE",
|
||||
"MAP_FALLARBOR_TOWN_POKEMON_CENTER_1F",
|
||||
"MAP_FALLARBOR_TOWN_POKEMON_CENTER_2F",
|
||||
},
|
||||
"Faraway Island": {
|
||||
"MAP_FARAWAY_ISLAND_ENTRANCE",
|
||||
"MAP_FARAWAY_ISLAND_INTERIOR",
|
||||
},
|
||||
"Fiery Path": {"MAP_FIERY_PATH"},
|
||||
"Fortree City": {
|
||||
"MAP_FORTREE_CITY",
|
||||
"MAP_FORTREE_CITY_DECORATION_SHOP",
|
||||
"MAP_FORTREE_CITY_GYM",
|
||||
"MAP_FORTREE_CITY_HOUSE1",
|
||||
"MAP_FORTREE_CITY_HOUSE2",
|
||||
"MAP_FORTREE_CITY_HOUSE3",
|
||||
"MAP_FORTREE_CITY_HOUSE4",
|
||||
"MAP_FORTREE_CITY_HOUSE5",
|
||||
"MAP_FORTREE_CITY_MART",
|
||||
"MAP_FORTREE_CITY_POKEMON_CENTER_1F",
|
||||
"MAP_FORTREE_CITY_POKEMON_CENTER_2F",
|
||||
},
|
||||
"Granite Cave": {
|
||||
"MAP_GRANITE_CAVE_1F",
|
||||
"MAP_GRANITE_CAVE_B1F",
|
||||
"MAP_GRANITE_CAVE_B2F",
|
||||
"MAP_GRANITE_CAVE_STEVENS_ROOM",
|
||||
},
|
||||
"Jagged Pass": {"MAP_JAGGED_PASS"},
|
||||
"Lavaridge Town": {
|
||||
"MAP_LAVARIDGE_TOWN",
|
||||
"MAP_LAVARIDGE_TOWN_GYM_1F",
|
||||
"MAP_LAVARIDGE_TOWN_GYM_B1F",
|
||||
"MAP_LAVARIDGE_TOWN_HERB_SHOP",
|
||||
"MAP_LAVARIDGE_TOWN_HOUSE",
|
||||
"MAP_LAVARIDGE_TOWN_MART",
|
||||
"MAP_LAVARIDGE_TOWN_POKEMON_CENTER_1F",
|
||||
"MAP_LAVARIDGE_TOWN_POKEMON_CENTER_2F",
|
||||
},
|
||||
"Lilycove City": {
|
||||
"MAP_LILYCOVE_CITY",
|
||||
"MAP_LILYCOVE_CITY_CONTEST_HALL",
|
||||
"MAP_LILYCOVE_CITY_CONTEST_LOBBY",
|
||||
"MAP_LILYCOVE_CITY_COVE_LILY_MOTEL_1F",
|
||||
"MAP_LILYCOVE_CITY_COVE_LILY_MOTEL_2F",
|
||||
"MAP_LILYCOVE_CITY_DEPARTMENT_STORE_1F",
|
||||
"MAP_LILYCOVE_CITY_DEPARTMENT_STORE_2F",
|
||||
"MAP_LILYCOVE_CITY_DEPARTMENT_STORE_3F",
|
||||
"MAP_LILYCOVE_CITY_DEPARTMENT_STORE_4F",
|
||||
"MAP_LILYCOVE_CITY_DEPARTMENT_STORE_5F",
|
||||
"MAP_LILYCOVE_CITY_DEPARTMENT_STORE_ELEVATOR",
|
||||
"MAP_LILYCOVE_CITY_DEPARTMENT_STORE_ROOFTOP",
|
||||
"MAP_LILYCOVE_CITY_HARBOR",
|
||||
"MAP_LILYCOVE_CITY_HOUSE1",
|
||||
"MAP_LILYCOVE_CITY_HOUSE2",
|
||||
"MAP_LILYCOVE_CITY_HOUSE3",
|
||||
"MAP_LILYCOVE_CITY_HOUSE4",
|
||||
"MAP_LILYCOVE_CITY_LILYCOVE_MUSEUM_1F",
|
||||
"MAP_LILYCOVE_CITY_LILYCOVE_MUSEUM_2F",
|
||||
"MAP_LILYCOVE_CITY_MOVE_DELETERS_HOUSE",
|
||||
"MAP_LILYCOVE_CITY_POKEMON_CENTER_1F",
|
||||
"MAP_LILYCOVE_CITY_POKEMON_CENTER_2F",
|
||||
"MAP_LILYCOVE_CITY_POKEMON_TRAINER_FAN_CLUB",
|
||||
},
|
||||
"Littleroot Town": {
|
||||
"MAP_INSIDE_OF_TRUCK",
|
||||
"MAP_LITTLEROOT_TOWN",
|
||||
"MAP_LITTLEROOT_TOWN_BRENDANS_HOUSE_1F",
|
||||
"MAP_LITTLEROOT_TOWN_BRENDANS_HOUSE_2F",
|
||||
"MAP_LITTLEROOT_TOWN_MAYS_HOUSE_1F",
|
||||
"MAP_LITTLEROOT_TOWN_MAYS_HOUSE_2F",
|
||||
"MAP_LITTLEROOT_TOWN_PROFESSOR_BIRCHS_LAB",
|
||||
},
|
||||
"Magma Hideout": {
|
||||
"MAP_MAGMA_HIDEOUT_1F",
|
||||
"MAP_MAGMA_HIDEOUT_2F_1R",
|
||||
"MAP_MAGMA_HIDEOUT_2F_2R",
|
||||
"MAP_MAGMA_HIDEOUT_2F_3R",
|
||||
"MAP_MAGMA_HIDEOUT_3F_1R",
|
||||
"MAP_MAGMA_HIDEOUT_3F_2R",
|
||||
"MAP_MAGMA_HIDEOUT_3F_3R",
|
||||
"MAP_MAGMA_HIDEOUT_4F",
|
||||
},
|
||||
"Marine Cave": {
|
||||
"MAP_MARINE_CAVE_END",
|
||||
"MAP_MARINE_CAVE_ENTRANCE",
|
||||
"MAP_UNDERWATER_MARINE_CAVE",
|
||||
},
|
||||
"Mauville City": {
|
||||
"MAP_MAUVILLE_CITY",
|
||||
"MAP_MAUVILLE_CITY_BIKE_SHOP",
|
||||
"MAP_MAUVILLE_CITY_GAME_CORNER",
|
||||
"MAP_MAUVILLE_CITY_GYM",
|
||||
"MAP_MAUVILLE_CITY_HOUSE1",
|
||||
"MAP_MAUVILLE_CITY_HOUSE2",
|
||||
"MAP_MAUVILLE_CITY_MART",
|
||||
"MAP_MAUVILLE_CITY_POKEMON_CENTER_1F",
|
||||
"MAP_MAUVILLE_CITY_POKEMON_CENTER_2F",
|
||||
},
|
||||
"Meteor Falls": {
|
||||
"MAP_METEOR_FALLS_1F_1R",
|
||||
"MAP_METEOR_FALLS_1F_2R",
|
||||
"MAP_METEOR_FALLS_B1F_1R",
|
||||
"MAP_METEOR_FALLS_B1F_2R",
|
||||
"MAP_METEOR_FALLS_STEVENS_CAVE",
|
||||
},
|
||||
"Mirage Tower": {
|
||||
"MAP_MIRAGE_TOWER_1F",
|
||||
"MAP_MIRAGE_TOWER_2F",
|
||||
"MAP_MIRAGE_TOWER_3F",
|
||||
"MAP_MIRAGE_TOWER_4F",
|
||||
},
|
||||
"Mossdeep City": {
|
||||
"MAP_MOSSDEEP_CITY",
|
||||
"MAP_MOSSDEEP_CITY_GAME_CORNER_1F",
|
||||
"MAP_MOSSDEEP_CITY_GAME_CORNER_B1F",
|
||||
"MAP_MOSSDEEP_CITY_GYM",
|
||||
"MAP_MOSSDEEP_CITY_HOUSE1",
|
||||
"MAP_MOSSDEEP_CITY_HOUSE2",
|
||||
"MAP_MOSSDEEP_CITY_HOUSE3",
|
||||
"MAP_MOSSDEEP_CITY_HOUSE4",
|
||||
"MAP_MOSSDEEP_CITY_MART",
|
||||
"MAP_MOSSDEEP_CITY_POKEMON_CENTER_1F",
|
||||
"MAP_MOSSDEEP_CITY_POKEMON_CENTER_2F",
|
||||
"MAP_MOSSDEEP_CITY_SPACE_CENTER_1F",
|
||||
"MAP_MOSSDEEP_CITY_SPACE_CENTER_2F",
|
||||
"MAP_MOSSDEEP_CITY_STEVENS_HOUSE",
|
||||
},
|
||||
"Mt. Chimney": {
|
||||
"MAP_MT_CHIMNEY",
|
||||
"MAP_MT_CHIMNEY_CABLE_CAR_STATION",
|
||||
},
|
||||
"Mt. Pyre": {
|
||||
"MAP_MT_PYRE_1F",
|
||||
"MAP_MT_PYRE_2F",
|
||||
"MAP_MT_PYRE_3F",
|
||||
"MAP_MT_PYRE_4F",
|
||||
"MAP_MT_PYRE_5F",
|
||||
"MAP_MT_PYRE_6F",
|
||||
"MAP_MT_PYRE_EXTERIOR",
|
||||
"MAP_MT_PYRE_SUMMIT",
|
||||
},
|
||||
"Navel Rock": {
|
||||
"MAP_NAVEL_ROCK_B1F",
|
||||
"MAP_NAVEL_ROCK_BOTTOM",
|
||||
"MAP_NAVEL_ROCK_DOWN01",
|
||||
"MAP_NAVEL_ROCK_DOWN02",
|
||||
"MAP_NAVEL_ROCK_DOWN03",
|
||||
"MAP_NAVEL_ROCK_DOWN04",
|
||||
"MAP_NAVEL_ROCK_DOWN05",
|
||||
"MAP_NAVEL_ROCK_DOWN06",
|
||||
"MAP_NAVEL_ROCK_DOWN07",
|
||||
"MAP_NAVEL_ROCK_DOWN08",
|
||||
"MAP_NAVEL_ROCK_DOWN09",
|
||||
"MAP_NAVEL_ROCK_DOWN10",
|
||||
"MAP_NAVEL_ROCK_DOWN11",
|
||||
"MAP_NAVEL_ROCK_ENTRANCE",
|
||||
"MAP_NAVEL_ROCK_EXTERIOR",
|
||||
"MAP_NAVEL_ROCK_FORK",
|
||||
"MAP_NAVEL_ROCK_HARBOR",
|
||||
"MAP_NAVEL_ROCK_TOP",
|
||||
"MAP_NAVEL_ROCK_UP1",
|
||||
"MAP_NAVEL_ROCK_UP2",
|
||||
"MAP_NAVEL_ROCK_UP3",
|
||||
"MAP_NAVEL_ROCK_UP4",
|
||||
},
|
||||
"New Mauville": {
|
||||
"MAP_NEW_MAUVILLE_ENTRANCE",
|
||||
"MAP_NEW_MAUVILLE_INSIDE",
|
||||
},
|
||||
"Oldale Town": {
|
||||
"MAP_OLDALE_TOWN",
|
||||
"MAP_OLDALE_TOWN_HOUSE1",
|
||||
"MAP_OLDALE_TOWN_HOUSE2",
|
||||
"MAP_OLDALE_TOWN_MART",
|
||||
"MAP_OLDALE_TOWN_POKEMON_CENTER_1F",
|
||||
"MAP_OLDALE_TOWN_POKEMON_CENTER_2F",
|
||||
},
|
||||
"Pacifidlog Town": {
|
||||
"MAP_PACIFIDLOG_TOWN",
|
||||
"MAP_PACIFIDLOG_TOWN_HOUSE1",
|
||||
"MAP_PACIFIDLOG_TOWN_HOUSE2",
|
||||
"MAP_PACIFIDLOG_TOWN_HOUSE3",
|
||||
"MAP_PACIFIDLOG_TOWN_HOUSE4",
|
||||
"MAP_PACIFIDLOG_TOWN_HOUSE5",
|
||||
"MAP_PACIFIDLOG_TOWN_POKEMON_CENTER_1F",
|
||||
"MAP_PACIFIDLOG_TOWN_POKEMON_CENTER_2F",
|
||||
},
|
||||
"Petalburg City": {
|
||||
"MAP_PETALBURG_CITY",
|
||||
"MAP_PETALBURG_CITY_GYM",
|
||||
"MAP_PETALBURG_CITY_HOUSE1",
|
||||
"MAP_PETALBURG_CITY_HOUSE2",
|
||||
"MAP_PETALBURG_CITY_MART",
|
||||
"MAP_PETALBURG_CITY_POKEMON_CENTER_1F",
|
||||
"MAP_PETALBURG_CITY_POKEMON_CENTER_2F",
|
||||
"MAP_PETALBURG_CITY_WALLYS_HOUSE",
|
||||
},
|
||||
"Petalburg Woods": {"MAP_PETALBURG_WOODS"},
|
||||
"Route 101": {"MAP_ROUTE101"},
|
||||
"Route 102": {"MAP_ROUTE102"},
|
||||
"Route 103": {"MAP_ROUTE103"},
|
||||
"Route 104": {
|
||||
"MAP_ROUTE104",
|
||||
"MAP_ROUTE104_MR_BRINEYS_HOUSE",
|
||||
"MAP_ROUTE104_PRETTY_PETAL_FLOWER_SHOP",
|
||||
},
|
||||
"Route 105": {
|
||||
"MAP_ISLAND_CAVE",
|
||||
"MAP_ROUTE105",
|
||||
"MAP_UNDERWATER_ROUTE105",
|
||||
},
|
||||
"Route 106": {"MAP_ROUTE106"},
|
||||
"Route 107": {"MAP_ROUTE107"},
|
||||
"Route 108": {"MAP_ROUTE108"},
|
||||
"Route 109": {
|
||||
"MAP_ROUTE109",
|
||||
"MAP_ROUTE109_SEASHORE_HOUSE",
|
||||
},
|
||||
"Route 110": {
|
||||
"MAP_ROUTE110",
|
||||
"MAP_ROUTE110_SEASIDE_CYCLING_ROAD_NORTH_ENTRANCE",
|
||||
"MAP_ROUTE110_SEASIDE_CYCLING_ROAD_SOUTH_ENTRANCE",
|
||||
},
|
||||
"Trick House": {
|
||||
"MAP_ROUTE110_TRICK_HOUSE_CORRIDOR",
|
||||
"MAP_ROUTE110_TRICK_HOUSE_END",
|
||||
"MAP_ROUTE110_TRICK_HOUSE_ENTRANCE",
|
||||
"MAP_ROUTE110_TRICK_HOUSE_PUZZLE1",
|
||||
"MAP_ROUTE110_TRICK_HOUSE_PUZZLE2",
|
||||
"MAP_ROUTE110_TRICK_HOUSE_PUZZLE3",
|
||||
"MAP_ROUTE110_TRICK_HOUSE_PUZZLE4",
|
||||
"MAP_ROUTE110_TRICK_HOUSE_PUZZLE5",
|
||||
"MAP_ROUTE110_TRICK_HOUSE_PUZZLE6",
|
||||
"MAP_ROUTE110_TRICK_HOUSE_PUZZLE7",
|
||||
"MAP_ROUTE110_TRICK_HOUSE_PUZZLE8",
|
||||
},
|
||||
"Route 111": {
|
||||
"MAP_DESERT_RUINS",
|
||||
"MAP_ROUTE111",
|
||||
"MAP_ROUTE111_OLD_LADYS_REST_STOP",
|
||||
"MAP_ROUTE111_WINSTRATE_FAMILYS_HOUSE",
|
||||
},
|
||||
"Route 112": {
|
||||
"MAP_ROUTE112",
|
||||
"MAP_ROUTE112_CABLE_CAR_STATION",
|
||||
},
|
||||
"Route 113": {
|
||||
"MAP_ROUTE113",
|
||||
"MAP_ROUTE113_GLASS_WORKSHOP",
|
||||
},
|
||||
"Route 114": {
|
||||
"MAP_DESERT_UNDERPASS",
|
||||
"MAP_ROUTE114",
|
||||
"MAP_ROUTE114_FOSSIL_MANIACS_HOUSE",
|
||||
"MAP_ROUTE114_FOSSIL_MANIACS_TUNNEL",
|
||||
"MAP_ROUTE114_LANETTES_HOUSE",
|
||||
},
|
||||
"Route 115": {"MAP_ROUTE115"},
|
||||
"Route 116": {
|
||||
"MAP_ROUTE116",
|
||||
"MAP_ROUTE116_TUNNELERS_REST_HOUSE",
|
||||
},
|
||||
"Route 117": {
|
||||
"MAP_ROUTE117",
|
||||
"MAP_ROUTE117_POKEMON_DAY_CARE",
|
||||
},
|
||||
"Route 118": {"MAP_ROUTE118"},
|
||||
"Route 119": {
|
||||
"MAP_ROUTE119",
|
||||
"MAP_ROUTE119_HOUSE",
|
||||
"MAP_ROUTE119_WEATHER_INSTITUTE_1F",
|
||||
"MAP_ROUTE119_WEATHER_INSTITUTE_2F",
|
||||
},
|
||||
"Route 120": {
|
||||
"MAP_ANCIENT_TOMB",
|
||||
"MAP_ROUTE120",
|
||||
"MAP_SCORCHED_SLAB",
|
||||
},
|
||||
"Route 121": {
|
||||
"MAP_ROUTE121",
|
||||
},
|
||||
"Route 122": {"MAP_ROUTE122"},
|
||||
"Route 123": {
|
||||
"MAP_ROUTE123",
|
||||
"MAP_ROUTE123_BERRY_MASTERS_HOUSE",
|
||||
},
|
||||
"Route 124": {
|
||||
"MAP_ROUTE124",
|
||||
"MAP_ROUTE124_DIVING_TREASURE_HUNTERS_HOUSE",
|
||||
"MAP_UNDERWATER_ROUTE124",
|
||||
},
|
||||
"Route 125": {
|
||||
"MAP_ROUTE125",
|
||||
"MAP_UNDERWATER_ROUTE125",
|
||||
},
|
||||
"Route 126": {
|
||||
"MAP_ROUTE126",
|
||||
"MAP_UNDERWATER_ROUTE126",
|
||||
},
|
||||
"Route 127": {
|
||||
"MAP_ROUTE127",
|
||||
"MAP_UNDERWATER_ROUTE127",
|
||||
},
|
||||
"Route 128": {
|
||||
"MAP_ROUTE128",
|
||||
"MAP_UNDERWATER_ROUTE128",
|
||||
},
|
||||
"Route 129": {
|
||||
"MAP_ROUTE129",
|
||||
"MAP_UNDERWATER_ROUTE129",
|
||||
},
|
||||
"Route 130": {"MAP_ROUTE130"},
|
||||
"Route 131": {"MAP_ROUTE131"},
|
||||
"Route 132": {"MAP_ROUTE132"},
|
||||
"Route 133": {"MAP_ROUTE133"},
|
||||
"Route 134": {
|
||||
"MAP_ROUTE134",
|
||||
"MAP_UNDERWATER_ROUTE134",
|
||||
"MAP_SEALED_CHAMBER_INNER_ROOM",
|
||||
"MAP_SEALED_CHAMBER_OUTER_ROOM",
|
||||
"MAP_UNDERWATER_SEALED_CHAMBER",
|
||||
},
|
||||
"Rustboro City": {
|
||||
"MAP_RUSTBORO_CITY",
|
||||
"MAP_RUSTBORO_CITY_CUTTERS_HOUSE",
|
||||
"MAP_RUSTBORO_CITY_DEVON_CORP_1F",
|
||||
"MAP_RUSTBORO_CITY_DEVON_CORP_2F",
|
||||
"MAP_RUSTBORO_CITY_DEVON_CORP_3F",
|
||||
"MAP_RUSTBORO_CITY_FLAT1_1F",
|
||||
"MAP_RUSTBORO_CITY_FLAT1_2F",
|
||||
"MAP_RUSTBORO_CITY_FLAT2_1F",
|
||||
"MAP_RUSTBORO_CITY_FLAT2_2F",
|
||||
"MAP_RUSTBORO_CITY_FLAT2_3F",
|
||||
"MAP_RUSTBORO_CITY_GYM",
|
||||
"MAP_RUSTBORO_CITY_HOUSE1",
|
||||
"MAP_RUSTBORO_CITY_HOUSE2",
|
||||
"MAP_RUSTBORO_CITY_HOUSE3",
|
||||
"MAP_RUSTBORO_CITY_MART",
|
||||
"MAP_RUSTBORO_CITY_POKEMON_CENTER_1F",
|
||||
"MAP_RUSTBORO_CITY_POKEMON_CENTER_2F",
|
||||
"MAP_RUSTBORO_CITY_POKEMON_SCHOOL",
|
||||
},
|
||||
"Rusturf Tunnel": {"MAP_RUSTURF_TUNNEL"},
|
||||
"Safari Zone": {
|
||||
"MAP_ROUTE121_SAFARI_ZONE_ENTRANCE",
|
||||
"MAP_SAFARI_ZONE_NORTH",
|
||||
"MAP_SAFARI_ZONE_NORTHEAST",
|
||||
"MAP_SAFARI_ZONE_NORTHWEST",
|
||||
"MAP_SAFARI_ZONE_REST_HOUSE",
|
||||
"MAP_SAFARI_ZONE_SOUTH",
|
||||
"MAP_SAFARI_ZONE_SOUTHEAST",
|
||||
"MAP_SAFARI_ZONE_SOUTHWEST",
|
||||
},
|
||||
"Seafloor Cavern": {
|
||||
"MAP_SEAFLOOR_CAVERN_ENTRANCE",
|
||||
"MAP_SEAFLOOR_CAVERN_ROOM1",
|
||||
"MAP_SEAFLOOR_CAVERN_ROOM2",
|
||||
"MAP_SEAFLOOR_CAVERN_ROOM3",
|
||||
"MAP_SEAFLOOR_CAVERN_ROOM4",
|
||||
"MAP_SEAFLOOR_CAVERN_ROOM5",
|
||||
"MAP_SEAFLOOR_CAVERN_ROOM6",
|
||||
"MAP_SEAFLOOR_CAVERN_ROOM7",
|
||||
"MAP_SEAFLOOR_CAVERN_ROOM8",
|
||||
"MAP_SEAFLOOR_CAVERN_ROOM9",
|
||||
"MAP_UNDERWATER_SEAFLOOR_CAVERN",
|
||||
},
|
||||
"Shoal Cave": {
|
||||
"MAP_SHOAL_CAVE_HIGH_TIDE_ENTRANCE_ROOM",
|
||||
"MAP_SHOAL_CAVE_HIGH_TIDE_INNER_ROOM",
|
||||
"MAP_SHOAL_CAVE_LOW_TIDE_ENTRANCE_ROOM",
|
||||
"MAP_SHOAL_CAVE_LOW_TIDE_ICE_ROOM",
|
||||
"MAP_SHOAL_CAVE_LOW_TIDE_INNER_ROOM",
|
||||
"MAP_SHOAL_CAVE_LOW_TIDE_LOWER_ROOM",
|
||||
"MAP_SHOAL_CAVE_LOW_TIDE_STAIRS_ROOM",
|
||||
},
|
||||
"Sky Pillar": {
|
||||
"MAP_SKY_PILLAR_1F",
|
||||
"MAP_SKY_PILLAR_2F",
|
||||
"MAP_SKY_PILLAR_3F",
|
||||
"MAP_SKY_PILLAR_4F",
|
||||
"MAP_SKY_PILLAR_5F",
|
||||
"MAP_SKY_PILLAR_ENTRANCE",
|
||||
"MAP_SKY_PILLAR_OUTSIDE",
|
||||
"MAP_SKY_PILLAR_TOP",
|
||||
},
|
||||
"Slateport City": {
|
||||
"MAP_SLATEPORT_CITY",
|
||||
"MAP_SLATEPORT_CITY_BATTLE_TENT_BATTLE_ROOM",
|
||||
"MAP_SLATEPORT_CITY_BATTLE_TENT_CORRIDOR",
|
||||
"MAP_SLATEPORT_CITY_BATTLE_TENT_LOBBY",
|
||||
"MAP_SLATEPORT_CITY_HARBOR",
|
||||
"MAP_SLATEPORT_CITY_HOUSE",
|
||||
"MAP_SLATEPORT_CITY_MART",
|
||||
"MAP_SLATEPORT_CITY_NAME_RATERS_HOUSE",
|
||||
"MAP_SLATEPORT_CITY_OCEANIC_MUSEUM_1F",
|
||||
"MAP_SLATEPORT_CITY_OCEANIC_MUSEUM_2F",
|
||||
"MAP_SLATEPORT_CITY_POKEMON_CENTER_1F",
|
||||
"MAP_SLATEPORT_CITY_POKEMON_CENTER_2F",
|
||||
"MAP_SLATEPORT_CITY_POKEMON_FAN_CLUB",
|
||||
"MAP_SLATEPORT_CITY_STERNS_SHIPYARD_1F",
|
||||
"MAP_SLATEPORT_CITY_STERNS_SHIPYARD_2F",
|
||||
},
|
||||
"Sootopolis City": {
|
||||
"MAP_CAVE_OF_ORIGIN_1F",
|
||||
"MAP_CAVE_OF_ORIGIN_B1F",
|
||||
"MAP_CAVE_OF_ORIGIN_ENTRANCE",
|
||||
"MAP_SOOTOPOLIS_CITY",
|
||||
"MAP_SOOTOPOLIS_CITY_GYM_1F",
|
||||
"MAP_SOOTOPOLIS_CITY_GYM_B1F",
|
||||
"MAP_SOOTOPOLIS_CITY_HOUSE1",
|
||||
"MAP_SOOTOPOLIS_CITY_HOUSE2",
|
||||
"MAP_SOOTOPOLIS_CITY_HOUSE3",
|
||||
"MAP_SOOTOPOLIS_CITY_HOUSE4",
|
||||
"MAP_SOOTOPOLIS_CITY_HOUSE5",
|
||||
"MAP_SOOTOPOLIS_CITY_HOUSE6",
|
||||
"MAP_SOOTOPOLIS_CITY_HOUSE7",
|
||||
"MAP_SOOTOPOLIS_CITY_LOTAD_AND_SEEDOT_HOUSE",
|
||||
"MAP_SOOTOPOLIS_CITY_MART",
|
||||
"MAP_SOOTOPOLIS_CITY_MYSTERY_EVENTS_HOUSE_1F",
|
||||
"MAP_SOOTOPOLIS_CITY_MYSTERY_EVENTS_HOUSE_B1F",
|
||||
"MAP_SOOTOPOLIS_CITY_POKEMON_CENTER_1F",
|
||||
"MAP_SOOTOPOLIS_CITY_POKEMON_CENTER_2F",
|
||||
"MAP_UNDERWATER_SOOTOPOLIS_CITY",
|
||||
},
|
||||
"Southern Island": {
|
||||
"MAP_SOUTHERN_ISLAND_EXTERIOR",
|
||||
"MAP_SOUTHERN_ISLAND_INTERIOR",
|
||||
},
|
||||
"S.S. Tidal": {
|
||||
"MAP_SS_TIDAL_CORRIDOR",
|
||||
"MAP_SS_TIDAL_LOWER_DECK",
|
||||
"MAP_SS_TIDAL_ROOMS",
|
||||
},
|
||||
"Terra Cave": {
|
||||
"MAP_TERRA_CAVE_END",
|
||||
"MAP_TERRA_CAVE_ENTRANCE",
|
||||
},
|
||||
"Trainer Hill": {
|
||||
"MAP_TRAINER_HILL_2F",
|
||||
"MAP_TRAINER_HILL_3F",
|
||||
"MAP_TRAINER_HILL_4F",
|
||||
"MAP_TRAINER_HILL_ELEVATOR",
|
||||
"MAP_TRAINER_HILL_ENTRANCE",
|
||||
"MAP_TRAINER_HILL_ROOF",
|
||||
},
|
||||
"Verdanturf Town": {
|
||||
"MAP_VERDANTURF_TOWN",
|
||||
"MAP_VERDANTURF_TOWN_BATTLE_TENT_BATTLE_ROOM",
|
||||
"MAP_VERDANTURF_TOWN_BATTLE_TENT_CORRIDOR",
|
||||
"MAP_VERDANTURF_TOWN_BATTLE_TENT_LOBBY",
|
||||
"MAP_VERDANTURF_TOWN_FRIENDSHIP_RATERS_HOUSE",
|
||||
"MAP_VERDANTURF_TOWN_HOUSE",
|
||||
"MAP_VERDANTURF_TOWN_MART",
|
||||
"MAP_VERDANTURF_TOWN_POKEMON_CENTER_1F",
|
||||
"MAP_VERDANTURF_TOWN_POKEMON_CENTER_2F",
|
||||
"MAP_VERDANTURF_TOWN_WANDAS_HOUSE",
|
||||
},
|
||||
"Victory Road": {
|
||||
"MAP_VICTORY_ROAD_1F",
|
||||
"MAP_VICTORY_ROAD_B1F",
|
||||
"MAP_VICTORY_ROAD_B2F",
|
||||
},
|
||||
}
|
||||
|
||||
_LOCATION_CATEGORY_TO_GROUP_NAME = {
|
||||
LocationCategory.BADGE: "Badges",
|
||||
LocationCategory.HM: "HMs",
|
||||
LocationCategory.KEY: "Key Items",
|
||||
LocationCategory.ROD: "Fishing Rods",
|
||||
LocationCategory.BIKE: "Bikes",
|
||||
LocationCategory.TICKET: "Tickets",
|
||||
LocationCategory.OVERWORLD_ITEM: "Overworld Items",
|
||||
LocationCategory.HIDDEN_ITEM: "Hidden Items",
|
||||
LocationCategory.GIFT: "NPC Gifts",
|
||||
LocationCategory.BERRY_TREE: "Berry Trees",
|
||||
LocationCategory.TRAINER: "Trainers",
|
||||
LocationCategory.POKEDEX: "Pokedex",
|
||||
}
|
||||
|
||||
LOCATION_GROUPS: Dict[str, Set[str]] = {group_name: set() for group_name in _LOCATION_CATEGORY_TO_GROUP_NAME.values()}
|
||||
for location in data.locations.values():
|
||||
# Category groups
|
||||
LOCATION_GROUPS[_LOCATION_CATEGORY_TO_GROUP_NAME[location.category]].add(location.label)
|
||||
|
||||
# Tag groups
|
||||
for tag in location.tags:
|
||||
if tag not in LOCATION_GROUPS:
|
||||
LOCATION_GROUPS[tag] = set()
|
||||
LOCATION_GROUPS[tag].add(location.label)
|
||||
|
||||
# Geographic groups
|
||||
if location.parent_region != "REGION_POKEDEX":
|
||||
map_name = data.regions[location.parent_region].parent_map.name
|
||||
for group, maps in _LOCATION_GROUP_MAPS.items():
|
||||
if map_name in maps:
|
||||
if group not in LOCATION_GROUPS:
|
||||
LOCATION_GROUPS[group] = set()
|
||||
LOCATION_GROUPS[group].add(location.label)
|
||||
break
|
||||
|
||||
# Meta-groups
|
||||
LOCATION_GROUPS["Cities"] = {
|
||||
*LOCATION_GROUPS.get("Littleroot Town", set()),
|
||||
*LOCATION_GROUPS.get("Oldale Town", set()),
|
||||
*LOCATION_GROUPS.get("Petalburg City", set()),
|
||||
*LOCATION_GROUPS.get("Rustboro City", set()),
|
||||
*LOCATION_GROUPS.get("Dewford Town", set()),
|
||||
*LOCATION_GROUPS.get("Slateport City", set()),
|
||||
*LOCATION_GROUPS.get("Mauville City", set()),
|
||||
*LOCATION_GROUPS.get("Verdanturf Town", set()),
|
||||
*LOCATION_GROUPS.get("Fallarbor Town", set()),
|
||||
*LOCATION_GROUPS.get("Lavaridge Town", set()),
|
||||
*LOCATION_GROUPS.get("Fortree City", set()),
|
||||
*LOCATION_GROUPS.get("Mossdeep City", set()),
|
||||
*LOCATION_GROUPS.get("Sootopolis City", set()),
|
||||
*LOCATION_GROUPS.get("Pacifidlog Town", set()),
|
||||
*LOCATION_GROUPS.get("Ever Grande City", set()),
|
||||
}
|
||||
|
||||
LOCATION_GROUPS["Dungeons"] = {
|
||||
*LOCATION_GROUPS.get("Petalburg Woods", set()),
|
||||
*LOCATION_GROUPS.get("Rusturf Tunnel", set()),
|
||||
*LOCATION_GROUPS.get("Granite Cave", set()),
|
||||
*LOCATION_GROUPS.get("Fiery Path", set()),
|
||||
*LOCATION_GROUPS.get("Meteor Falls", set()),
|
||||
*LOCATION_GROUPS.get("Jagged Pass", set()),
|
||||
*LOCATION_GROUPS.get("Mt. Chimney", set()),
|
||||
*LOCATION_GROUPS.get("Abandoned Ship", set()),
|
||||
*LOCATION_GROUPS.get("New Mauville", set()),
|
||||
*LOCATION_GROUPS.get("Mt. Pyre", set()),
|
||||
*LOCATION_GROUPS.get("Seafloor Cavern", set()),
|
||||
*LOCATION_GROUPS.get("Sky Pillar", set()),
|
||||
*LOCATION_GROUPS.get("Victory Road", set()),
|
||||
}
|
||||
|
||||
LOCATION_GROUPS["Routes"] = {
|
||||
*LOCATION_GROUPS.get("Route 101", set()),
|
||||
*LOCATION_GROUPS.get("Route 102", set()),
|
||||
*LOCATION_GROUPS.get("Route 103", set()),
|
||||
*LOCATION_GROUPS.get("Route 104", set()),
|
||||
*LOCATION_GROUPS.get("Route 105", set()),
|
||||
*LOCATION_GROUPS.get("Route 106", set()),
|
||||
*LOCATION_GROUPS.get("Route 107", set()),
|
||||
*LOCATION_GROUPS.get("Route 108", set()),
|
||||
*LOCATION_GROUPS.get("Route 109", set()),
|
||||
*LOCATION_GROUPS.get("Route 110", set()),
|
||||
*LOCATION_GROUPS.get("Route 111", set()),
|
||||
*LOCATION_GROUPS.get("Route 112", set()),
|
||||
*LOCATION_GROUPS.get("Route 113", set()),
|
||||
*LOCATION_GROUPS.get("Route 114", set()),
|
||||
*LOCATION_GROUPS.get("Route 115", set()),
|
||||
*LOCATION_GROUPS.get("Route 116", set()),
|
||||
*LOCATION_GROUPS.get("Route 117", set()),
|
||||
*LOCATION_GROUPS.get("Route 118", set()),
|
||||
*LOCATION_GROUPS.get("Route 119", set()),
|
||||
*LOCATION_GROUPS.get("Route 120", set()),
|
||||
*LOCATION_GROUPS.get("Route 121", set()),
|
||||
*LOCATION_GROUPS.get("Route 122", set()),
|
||||
*LOCATION_GROUPS.get("Route 123", set()),
|
||||
*LOCATION_GROUPS.get("Route 124", set()),
|
||||
*LOCATION_GROUPS.get("Route 125", set()),
|
||||
*LOCATION_GROUPS.get("Route 126", set()),
|
||||
*LOCATION_GROUPS.get("Route 127", set()),
|
||||
*LOCATION_GROUPS.get("Route 128", set()),
|
||||
*LOCATION_GROUPS.get("Route 129", set()),
|
||||
*LOCATION_GROUPS.get("Route 130", set()),
|
||||
*LOCATION_GROUPS.get("Route 131", set()),
|
||||
*LOCATION_GROUPS.get("Route 132", set()),
|
||||
*LOCATION_GROUPS.get("Route 133", set()),
|
||||
*LOCATION_GROUPS.get("Route 134", set()),
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
"""
|
||||
Classes and functions related to AP items for Pokemon Emerald
|
||||
"""
|
||||
from typing import Dict, FrozenSet, Optional
|
||||
from typing import Dict, FrozenSet, Set, Optional
|
||||
|
||||
from BaseClasses import Item, ItemClassification
|
||||
|
||||
|
@ -46,30 +46,6 @@ def create_item_label_to_code_map() -> Dict[str, int]:
|
|||
return label_to_code_map
|
||||
|
||||
|
||||
ITEM_GROUPS = {
|
||||
"Badges": {
|
||||
"Stone Badge", "Knuckle Badge",
|
||||
"Dynamo Badge", "Heat Badge",
|
||||
"Balance Badge", "Feather Badge",
|
||||
"Mind Badge", "Rain Badge",
|
||||
},
|
||||
"HMs": {
|
||||
"HM01 Cut", "HM02 Fly",
|
||||
"HM03 Surf", "HM04 Strength",
|
||||
"HM05 Flash", "HM06 Rock Smash",
|
||||
"HM07 Waterfall", "HM08 Dive",
|
||||
},
|
||||
"HM01": {"HM01 Cut"},
|
||||
"HM02": {"HM02 Fly"},
|
||||
"HM03": {"HM03 Surf"},
|
||||
"HM04": {"HM04 Strength"},
|
||||
"HM05": {"HM05 Flash"},
|
||||
"HM06": {"HM06 Rock Smash"},
|
||||
"HM07": {"HM07 Waterfall"},
|
||||
"HM08": {"HM08 Dive"},
|
||||
}
|
||||
|
||||
|
||||
def get_item_classification(item_code: int) -> ItemClassification:
|
||||
"""
|
||||
Returns the item classification for a given AP item id (code)
|
||||
|
|
|
@ -1,59 +1,17 @@
|
|||
"""
|
||||
Classes and functions related to AP locations for Pokemon Emerald
|
||||
"""
|
||||
from typing import TYPE_CHECKING, Dict, Optional, FrozenSet, Iterable
|
||||
from typing import TYPE_CHECKING, Dict, Optional, Set
|
||||
|
||||
from BaseClasses import Location, Region
|
||||
|
||||
from .data import BASE_OFFSET, NATIONAL_ID_TO_SPECIES_ID, POKEDEX_OFFSET, data
|
||||
from .data import BASE_OFFSET, NATIONAL_ID_TO_SPECIES_ID, POKEDEX_OFFSET, LocationCategory, data
|
||||
from .items import offset_item_value
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from . import PokemonEmeraldWorld
|
||||
|
||||
|
||||
LOCATION_GROUPS = {
|
||||
"Badges": {
|
||||
"Rustboro Gym - Stone Badge",
|
||||
"Dewford Gym - Knuckle Badge",
|
||||
"Mauville Gym - Dynamo Badge",
|
||||
"Lavaridge Gym - Heat Badge",
|
||||
"Petalburg Gym - Balance Badge",
|
||||
"Fortree Gym - Feather Badge",
|
||||
"Mossdeep Gym - Mind Badge",
|
||||
"Sootopolis Gym - Rain Badge",
|
||||
},
|
||||
"Gym TMs": {
|
||||
"Rustboro Gym - TM39 from Roxanne",
|
||||
"Dewford Gym - TM08 from Brawly",
|
||||
"Mauville Gym - TM34 from Wattson",
|
||||
"Lavaridge Gym - TM50 from Flannery",
|
||||
"Petalburg Gym - TM42 from Norman",
|
||||
"Fortree Gym - TM40 from Winona",
|
||||
"Mossdeep Gym - TM04 from Tate and Liza",
|
||||
"Sootopolis Gym - TM03 from Juan",
|
||||
},
|
||||
"Trick House": {
|
||||
"Trick House Puzzle 1 - Item",
|
||||
"Trick House Puzzle 2 - Item 1",
|
||||
"Trick House Puzzle 2 - Item 2",
|
||||
"Trick House Puzzle 3 - Item 1",
|
||||
"Trick House Puzzle 3 - Item 2",
|
||||
"Trick House Puzzle 4 - Item",
|
||||
"Trick House Puzzle 6 - Item",
|
||||
"Trick House Puzzle 7 - Item",
|
||||
"Trick House Puzzle 8 - Item",
|
||||
"Trick House Puzzle 1 - Reward",
|
||||
"Trick House Puzzle 2 - Reward",
|
||||
"Trick House Puzzle 3 - Reward",
|
||||
"Trick House Puzzle 4 - Reward",
|
||||
"Trick House Puzzle 5 - Reward",
|
||||
"Trick House Puzzle 6 - Reward",
|
||||
"Trick House Puzzle 7 - Reward",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
VISITED_EVENT_NAME_TO_ID = {
|
||||
"EVENT_VISITED_LITTLEROOT_TOWN": 0,
|
||||
"EVENT_VISITED_OLDALE_TOWN": 1,
|
||||
|
@ -80,7 +38,7 @@ class PokemonEmeraldLocation(Location):
|
|||
game: str = "Pokemon Emerald"
|
||||
item_address: Optional[int]
|
||||
default_item_code: Optional[int]
|
||||
tags: FrozenSet[str]
|
||||
key: Optional[str]
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
|
@ -88,13 +46,13 @@ class PokemonEmeraldLocation(Location):
|
|||
name: str,
|
||||
address: Optional[int],
|
||||
parent: Optional[Region] = None,
|
||||
key: Optional[str] = None,
|
||||
item_address: Optional[int] = None,
|
||||
default_item_value: Optional[int] = None,
|
||||
tags: FrozenSet[str] = frozenset()) -> None:
|
||||
default_item_value: Optional[int] = None) -> None:
|
||||
super().__init__(player, name, address, parent)
|
||||
self.default_item_code = None if default_item_value is None else offset_item_value(default_item_value)
|
||||
self.item_address = item_address
|
||||
self.tags = tags
|
||||
self.key = key
|
||||
|
||||
|
||||
def offset_flag(flag: int) -> int:
|
||||
|
@ -115,16 +73,14 @@ def reverse_offset_flag(location_id: int) -> int:
|
|||
return location_id - BASE_OFFSET
|
||||
|
||||
|
||||
def create_locations_with_tags(world: "PokemonEmeraldWorld", regions: Dict[str, Region], tags: Iterable[str]) -> None:
|
||||
def create_locations_by_category(world: "PokemonEmeraldWorld", regions: Dict[str, Region], categories: Set[LocationCategory]) -> None:
|
||||
"""
|
||||
Iterates through region data and adds locations to the multiworld if
|
||||
those locations include any of the provided tags.
|
||||
"""
|
||||
tags = set(tags)
|
||||
|
||||
for region_name, region_data in data.regions.items():
|
||||
region = regions[region_name]
|
||||
filtered_locations = [loc for loc in region_data.locations if len(tags & data.locations[loc].tags) > 0]
|
||||
filtered_locations = [loc for loc in region_data.locations if data.locations[loc].category in categories]
|
||||
|
||||
for location_name in filtered_locations:
|
||||
location_data = data.locations[location_name]
|
||||
|
@ -144,9 +100,9 @@ def create_locations_with_tags(world: "PokemonEmeraldWorld", regions: Dict[str,
|
|||
location_data.label,
|
||||
location_id,
|
||||
region,
|
||||
location_name,
|
||||
location_data.address,
|
||||
location_data.default_item,
|
||||
location_data.tags
|
||||
location_data.default_item
|
||||
)
|
||||
region.locations.append(location)
|
||||
|
||||
|
|
|
@ -6,7 +6,8 @@ from typing import TYPE_CHECKING, Callable, Dict
|
|||
from BaseClasses import CollectionState
|
||||
from worlds.generic.Rules import add_rule, set_rule
|
||||
|
||||
from .data import NATIONAL_ID_TO_SPECIES_ID, NUM_REAL_SPECIES, data
|
||||
from .data import LocationCategory, NATIONAL_ID_TO_SPECIES_ID, NUM_REAL_SPECIES, data
|
||||
from .locations import PokemonEmeraldLocation
|
||||
from .options import DarkCavesRequireFlash, EliteFourRequirement, NormanRequirement, Goal
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
@ -23,7 +24,7 @@ def set_rules(world: "PokemonEmeraldWorld") -> None:
|
|||
state.has(hm, world.player) and state.has_all(badges, world.player)
|
||||
else:
|
||||
hm_rules[hm] = lambda state, hm=hm, badges=badges: \
|
||||
state.has(hm, world.player) and state.has_group_unique("Badges", world.player, badges)
|
||||
state.has(hm, world.player) and state.has_group_unique("Badge", world.player, badges)
|
||||
|
||||
def has_acro_bike(state: CollectionState):
|
||||
return state.has("Acro Bike", world.player)
|
||||
|
@ -236,11 +237,11 @@ def set_rules(world: "PokemonEmeraldWorld") -> None:
|
|||
if world.options.norman_requirement == NormanRequirement.option_badges:
|
||||
set_rule(
|
||||
get_entrance("MAP_PETALBURG_CITY_GYM:2/MAP_PETALBURG_CITY_GYM:3"),
|
||||
lambda state: state.has_group_unique("Badges", world.player, world.options.norman_count.value)
|
||||
lambda state: state.has_group_unique("Badge", world.player, world.options.norman_count.value)
|
||||
)
|
||||
set_rule(
|
||||
get_entrance("MAP_PETALBURG_CITY_GYM:5/MAP_PETALBURG_CITY_GYM:6"),
|
||||
lambda state: state.has_group_unique("Badges", world.player, world.options.norman_count.value)
|
||||
lambda state: state.has_group_unique("Badge", world.player, world.options.norman_count.value)
|
||||
)
|
||||
else:
|
||||
set_rule(
|
||||
|
@ -1506,7 +1507,7 @@ def set_rules(world: "PokemonEmeraldWorld") -> None:
|
|||
if world.options.elite_four_requirement == EliteFourRequirement.option_badges:
|
||||
set_rule(
|
||||
get_entrance("REGION_EVER_GRANDE_CITY_POKEMON_LEAGUE_1F/MAIN -> REGION_EVER_GRANDE_CITY_POKEMON_LEAGUE_1F/BEHIND_BADGE_CHECKERS"),
|
||||
lambda state: state.has_group_unique("Badges", world.player, world.options.elite_four_count.value)
|
||||
lambda state: state.has_group_unique("Badge", world.player, world.options.elite_four_count.value)
|
||||
)
|
||||
else:
|
||||
set_rule(
|
||||
|
@ -1659,7 +1660,8 @@ def set_rules(world: "PokemonEmeraldWorld") -> None:
|
|||
# Add Itemfinder requirement to hidden items
|
||||
if world.options.require_itemfinder:
|
||||
for location in world.multiworld.get_locations(world.player):
|
||||
if location.tags is not None and "HiddenItem" in location.tags:
|
||||
assert isinstance(location, PokemonEmeraldLocation)
|
||||
if location.key is not None and data.locations[location.key].category == LocationCategory.HIDDEN_ITEM:
|
||||
add_rule(
|
||||
location,
|
||||
lambda state: state.has("Itemfinder", world.player)
|
||||
|
|
|
@ -5,8 +5,6 @@ duplicate claims and give warnings for unused and unignored locations or warps.
|
|||
import logging
|
||||
from typing import List
|
||||
|
||||
from .data import load_json_data, data
|
||||
|
||||
|
||||
_IGNORABLE_LOCATIONS = frozenset({
|
||||
"HIDDEN_ITEM_TRICK_HOUSE_NUGGET", # Is permanently mssiable and has special behavior that sets the flag early
|
||||
|
@ -247,12 +245,29 @@ _IGNORABLE_WARPS = frozenset({
|
|||
})
|
||||
|
||||
|
||||
def validate_group_maps() -> bool:
|
||||
from .data import data
|
||||
from .groups import _LOCATION_GROUP_MAPS
|
||||
|
||||
failed = False
|
||||
|
||||
for group_name, map_set in _LOCATION_GROUP_MAPS.items():
|
||||
for map_name in map_set:
|
||||
if map_name not in data.maps:
|
||||
failed = True
|
||||
logging.error("Pokemon Emerald: Map named %s in location group %s does not exist", map_name, group_name)
|
||||
|
||||
return not failed
|
||||
|
||||
|
||||
def validate_regions() -> bool:
|
||||
"""
|
||||
Verifies that Emerald's data doesn't have duplicate or missing
|
||||
regions/warps/locations. Meant to catch problems during development like
|
||||
forgetting to add a new location or incorrectly splitting a region.
|
||||
"""
|
||||
from .data import load_json_data, data
|
||||
|
||||
extracted_data_json = load_json_data("extracted_data.json")
|
||||
error_messages: List[str] = []
|
||||
warn_messages: List[str] = []
|
||||
|
|
Loading…
Reference in New Issue