diff --git a/data/platinum.py b/data/platinum.py index e2d5810f80d39f476ae35339e4e82bdd1528f898..9026f5942e6150a6fe892fa9c51a397b6330ae63 100644 --- a/data/platinum.py +++ b/data/platinum.py @@ -1,565 +1,674 @@ -LOCATIONS = { - 'poi': [ - ('places_of_interest', 'Places of Interest'), - ('pokecenters_1', 'Pokécenters 1'), - ('pokecenters_2', 'Pokécenters 2'), - ], - 'cities': [ - ('sandgem_jubilife', 'Sandgem/Jubilife'), - ('oreburgh', 'Oreburgh'), - ('floaroma', 'Floaroma'), - ('eterna', 'Eterna'), - ('hearthome', 'Hearthome'), - ('solaceon', 'Solaceon'), - ('veilstone', 'Veilstone'), - ('pastoria', 'Pastoria'), - ('celestic', 'Celestic'), - ('canalave', 'Canalave'), - ('snowpoint', 'Snowpoint'), - ('sunyshore', 'Sunyshore'), - ('fight_resort', 'Fight/Resort'), - ('survival', 'Survival Area'), - ], - 'hubs': [ - ('jubilife_tv', 'Jubilife TV'), - ('store', 'Department Store'), - ('galactic_eterna', 'Galactic Eterna'), - ('galactic_hq', 'Galactic HQ'), - ('old_chateau', 'Old Chateau'), - ('solaceon_ruins', 'Solaceon Ruins'), - ('pokemansion', 'Pokémon Mansion'), - ], - 'routes': [ - ('r208_forest_march', 'R208/Et.Forest/Marsh'), - ('r213_214_222', 'R213/R214/R222'), - ], - 'other': [ - ('mt_coronet', 'Mt Coronet'), - ('victory_road', 'Victory Road'), - ('iron_island', 'Iron Island'), - ('poketch_gts_gate', 'Pokétch/GTS/Oreb. Gate'), - ('surf_hub', 'Surf Hub'), - ] -} +from util.locations import Category, Location, Entrance -ENTRANCES = { - 'places_of_interest': [ - ('oreburgh_gym_interior', 'Oreburgh Gym Interior'), - ('eterna_gym_interior', 'Eterna Gym Interior'), - ('hearthome_gym_interior', 'Hearthome Gym Interior'), - ('veilstone_gym_interior', 'Veilstone Gym Interior'), - ('pastoria_gym_interior', 'Pastoria Gym Interior'), - ('canalave_gym_interior', 'Canalave Gym Interior'), - ('snowpoint_gym_interior', 'Snowpoint Gym Interior'), - ('sunyshore_gym_interior', 'Sunyshore Gym Interior'), - ('e4_aaron', 'E4 Aaron'), - ('e4_bertha', 'E4 Bertha'), - ('e4_flint', 'E4 Flint'), - ('e4_lucian', 'E4 Lucian'), - ('champion', 'Champion'), - ('dialga_palkia', 'Dialga/Palkia'), - ('cresselia', 'Cresselia'), - ('darkrai', 'Darkrai'), - ('heatran', 'Heatran'), - ('arceus', 'Arceus'), - ('azelf', 'Azelf'), - ('uxie', 'Uxie'), - ], - 'pokecenters_1': [ - ('sandgem_pc_w', 'Sandgem PC W'), - ('sandgem_pc_s', 'Sandgem PC S'), - ('sandgem_pc_e', 'Sandgem PC E'), - ('jubilife_pc_w', 'Jubilife PC W'), - ('jubilife_pc_s', 'Jubilife PC S'), - ('jubilife_pc_e', 'Jubilife PC E'), - ('oreburgh_pc_w', 'Oreburgh PC W'), - ('oreburgh_pc_s', 'Oreburgh PC S'), - ('oreburgh_pc_e', 'Oreburgh PC E'), - ('floaroma_pc_w', 'Floaroma PC W'), - ('floaroma_pc_s', 'Floaroma PC S'), - ('floaroma_pc_e', 'Floaroma PC E'), - ('eterna_pc_w', 'Eterna PC W'), - ('eterna_pc_s', 'Eterna PC S'), - ('eterna_pc_e', 'Eterna PC E'), - ('hearthome_pc_w', 'Hearthome PC W'), - ('hearthome_pc_s', 'Hearthome PC S'), - ('hearthome_pc_e', 'Hearthome PC E'), - ('solaceon_pc_w', 'Solaceon PC W'), - ('solaceon_pc_s', 'Solaceon PC S'), - ('solaceon_pc_e', 'Solaceon PC E'), - ('veilstone_pc_w', 'Veilstone PC W'), - ('veilstone_pc_s', 'Veilstone PC S'), - ('veilstone_pc_e', 'Veilstone PC E'), - ('pastoria_pc_w', 'Pastoria PC W'), - ('pastoria_pc_s', 'Pastoria PC S'), - ('pastoria_pc_e', 'Pastoria PC E'), - ], - 'pokecenters_2': [ - ('celestic_pc_w', 'Celestic PC W'), - ('celestic_pc_s', 'Celestic PC S'), - ('celestic_pc_e', 'Celestic PC E'), - ('canalave_pc_w', 'Canalave PC W'), - ('canalave_pc_s', 'Canalave PC S'), - ('canalave_pc_e', 'Canalave PC E'), - ('snowpoint_pc_w', 'Snowpoint PC W'), - ('snowpoint_pc_s', 'Snowpoint PC S'), - ('snowpoint_pc_e', 'Snowpoint PC E'), - ('sunyshore_pc_w', 'Sunyshore PC W'), - ('sunyshore_pc_s', 'Sunyshore PC S'), - ('sunyshore_pc_e', 'Sunyshore PC E'), - ('victory_road_pc_w', 'VR PC W'), - ('victory_road_pc_s', 'VR PC S'), - ('victory_road_pc_e', 'VR PC E'), - ('pokemon_league_up', 'League Up'), - ('pokemon_league_down', 'League Down'), - ('pokemon_league_n', 'League N'), - ('pokemon_league_s', 'League S'), - ('fight_area_pc_w', 'Fight Area PC W'), - ('fight_area_pc_s', 'Fight Area PC S'), - ('fight_area_pc_e', 'Fight Area PC E'), - ('survival_area_pc_w', 'Survival Area PC W'), - ('survival_area_pc_s', 'Survival Area PC S'), - ('survival_area_pc_e', 'Survival Area PC E'), - ('resort_area_pc_w', 'Resort Area PC W'), - ('resort_area_pc_s', 'Resort Area PC S'), - ('resort_area_pc_e', 'Resort Area PC E'), - ], - 'sandgem_jubilife': [ - ('verity_lakefront', 'Verity Lakefront'), - ('sandgem_sw', 'Sandgem SW'), - ('sandgem_s', 'Sandgem S'), - ('sandgem_mart', 'Sandgem Mart'), - ('sandgem_pokecenter', 'Sandgem Pokécenter'), - ('jubilife_pokecenter', 'Jubilife Pokécenter'), - ('jubilife_trainer_school', 'Jubilife Trainer School'), - ('jubilife_mart', 'Jubilife Mart'), - ('jubilife_s', 'Jubilife S'), - ('jubilife_sw', 'Jubilife SW'), - ('jubilife_ne', 'Jubilife NE'), - ('jubilife_gts', 'Jubilife GTS'), - ('jubilife_tv', 'Jubilife TV'), - ('jubilife_poketch_w', 'Jubilife Poketch W'), - ('jubilife_poketch_e', 'Jubilife Poketch E'), - ('jubilife_ravaged_path', 'Jubilife Ravaged Path'), - ('jubilife_oreburgh_gate', 'Jubilife Oreburgh Gate'), - ('jubilife_west_exit', 'Jubilife West Exit'), - ], - 'oreburgh': [ - ('oreburgh_gym', 'Oreburgh Gym'), - ('oreburgh_mart', 'Oreburgh Mart'), - ('oreburgh_pokecenter', 'Oreburgh Pokécenter'), - ('oreburgh_fossil_lab', 'Oreburgh Fossil Lab'), - ('oreburgh_mine', 'Oreburgh Mine'), - ('oreburgh_apartment_nw', 'Oreburgh Apartment NW'), - ('oreburgh_apartment_n', 'Oreburgh Apartment N'), - ('oreburgh_apartment_e', 'Oreburgh Apartment E'), - ('oreburgh_house_w', 'Oreburgh House W'), - ('oreburgh_house_c', 'Oreburgh House C'), - ('oreburgh_house_se', 'Oreburgh House SE'), - ('oreburgh_west_exit', 'Oreburgh West Exit'), - ('r206_cycle_path', 'R206 Cycle Path'), - ('r206_wayward_cave', 'R206 Wayward Cave'), - ('r206_wayward_cave_hidden', 'R206 Wayward Cave Hidden'), - ('r207_mt_coronet', 'R207 Mt Coronet'), - ], - 'floaroma': [ - ('floaroma_pokecenter', 'Floaroma Pokecenter'), - ('floaroma_mart', 'Floaroma Mart'), - ('floaroma_flower_shop', 'Floaroma Flower Shop'), - ('floaroma_nw', 'Floaroma NW'), - ('floaroma_se', 'Floaroma SE'), - ('floaroma_ravaged_path', 'Floaroma Ravaged Path'), - ('floaroma_meadow_entrance_floaroma', 'Meadow Entrance Floaroma'), - ('floaroma_meadow_exit_house', 'Meadow House'), - ('floaroma_meadow_exit_n', 'Meadow Exit N'), - ('floaroma_meadow_exit_s', 'Meadow Exit S'), - ('r205_ironworks', 'R205 Ironworks'), - ('floaroma_meadow_entrance_iron', 'R205 Meadow Entrance'), - ('r205_windworks', 'R205 Windworks'), - ('r205_eterna_forest', 'R205 Eterna Forest'), - ('r205_house', 'R205 House'), - ], - 'eterna': [ - ('eterna_pokecenter', 'Eterna Pokecenter'), - ('eterna_mart', 'Eterna Mart'), - ('eterna_gym', 'Eterna Gym'), - ('eterna_bike_shop', 'Eterna Bike Shop'), - ("eterna_spelunker's_house", "Spelunker's House"), - ('eterna_city_forest', 'Eterna City Forest'), - ('eterna_apartment', 'Eterna Apartment'), - ('eterna_galactic', 'Eterna Galactic Building'), - ('eterna_house_n', 'Eterna House N'), - ('eterna_house_s', 'Eterna House S'), - ('eterna_house_e', 'Eterna House E'), - ('eterna_mt_coronet', 'Eterna Mt Coronet'), - ('eterna_south_exit', 'Eterna South Exit'), - ], - 'hearthome': [ - ('hearthome_pokecenter', 'Hearthome Pokecenter'), - ('hearthome_mart', 'Hearthome Mart'), - ('hearthome_gym', 'Hearthome Gym'), - ('hearthome_contest', 'Hearthome Contest'), - ("hearthome_bebe's_house", "Bebe's house"), - ('hearthome_church', 'Hearthome Church'), - ('hearthome_poffin_house', 'Hearthome Poffin House'), - ('hearthome_fanclub', 'Hearthome Fanclub'), - ('hearthome_apartment_n', 'Hearthome Apartment N'), - ('hearthome_apartment_e', 'Hearthome Apartment E'), - ('hearthome_amity_square_west', 'Amity Square West'), - ('hearthome_amity_square_east', 'Amity Square East'), - ('hearthome_east_exit', 'Hearthome East Exit'), - ('hearthome_south_exit', 'Hearthome South Exit'), - ('hearthome_west_exit', 'Hearthome West Exit'), - ], - 'solaceon': [ - ('solaceon_pokecenter', 'Solaceon Pokecenter'), - ('solaceon_mart', 'Solaceon Mart'), - ('solaceon_daycare', 'Solaceon Daycare'), - ('solaceon_house_n', 'Solaceon House N'), - ('solaceon_house_ne', 'Solaceon House NE'), - ('solaceon_house_e', 'Solaceon House E'), - ('solaceon_house_c', 'Solaceon House C'), - ('solaceon_ruins', 'Solaceon Ruins'), - ('r209_lost_tower', 'R209 Lost Tower'), - ('r209_west_exit', 'R209 West Exit'), - ('r210_cafe_cabin', 'R210 Cafe Cabin'), - ('r215_east_exit', 'R215 East Exit'), - ], - 'veilstone': [ - ('veilstone_pokecenter', 'Veilstone Pokecenter'), - ('veilstone_mart', 'Veilstone Mart'), - ('veilstone_gym', 'Veilstone Gym'), - ('veilstone_casino', 'Veilstone Casino'), - ('veilstone_galactic_hq_1', 'Galactic HQ 1'), - ('veilstone_galactic_hq_2', 'Galactic HQ 2'), - ('veilstone_galactic_hq_3', 'Galactic HQ 3'), - ('veilstone_galactic_warehouse', 'Galactic Warehouse'), - ('veilstone_house_n', 'Veilstone House N'), - ('veilstone_house_ne', 'Veilstone House NE'), - ('veilstone_prize_exchange', 'Prize Exchange'), - ('veilstone_house_s', 'Veilstone House S'), - ('veilstone_house_sw', 'Veilstone House SW'), - ('veilstone_south_exit', 'Veilstone South Exit'), - ('veilstone_west_exit', 'Veilstone West Exit'), - ], - 'pastoria': [ - ('pastoria_pokecenter', 'Pastoria Pokecenter'), - ('pastoria_mart', 'Pastoria Mart'), - ('pastoria_gym', 'Pastoria Gym'), - ('pastoria_great_marsh', 'Pastoria Great Marsh'), - ('pastoria_house_ne', 'Pastoria House NE'), - ('pastoria_house_se', 'Pastoria House SE'), - ('pastoria_house_sw', 'Pastoria House SW'), - ('pastoria_house_n', 'Pastoria House N'), - ('pastoria_house_c', 'Pastoria House C'), - ('pastoria_east_exit', 'Pastoria East Exit'), - ('r212_move_tutor', 'R212 Move Tutor'), - ('r212_pokemon_mansion', 'R212 Pokemon Mansion'), - ('r212_north_exit', 'R212 North Exit'), - ], - 'celestic': [ - ('celestic_pokecenter', 'Celestic Pokecenter'), - ('celestic_ruins', 'Celestic Ruins'), - ('celestic_big_house', 'Celestic Big House'), - ('celestic_house_ne', 'Celestic House NE'), - ('celestic_house_nw', 'Celestic House NW'), - ('celestic_house_sw', 'Celestic House SW'), - ('celestic_mt_coronet', 'Celestic Mt Coronet'), - ("r210_grandma's_house", "R210 Grandma's House"), - ], - 'canalave': [ - ('canalave_pokecenter', 'Canalave Pokecenter'), - ('canalave_mart', 'Canalave Mart'), - ('canalave_gym', 'Canalave Gym'), - ('canalave_library', 'Canalave Library'), - ('canalave_house_e', 'Canalave House E'), - ('canalave_house_se', 'Canalave House SE'), - ('canalave_house_w', 'Canalave House W'), - ('canalave_house_sw', 'Canalave House SW'), - # ('canalave_iron_island?', 'Canalave Iron Island?'), - ('canalave_east_exit', 'Canalave East Exit'), - ], - 'snowpoint': [ - ('snowpoint_pokecenter', 'Snowpoint Pokecenter'), - ('snowpoint_mart', 'Snowpoint Mart'), - ('snowpoint_gym', 'Snowpoint Gym'), - ('snowpoint_house_nw', 'Snowpoint House NW'), - ('snowpoint_house_ne', 'Snowpoint House NE'), - ('snowpoint_temple', 'Snowpoint Temple'), - ('acuity_lakefront', 'Acuity Lakefront'), - ('r217_house_n', 'R217 House N'), - ('r217_house_w', 'R217 House W'), - ('r216_house_w', 'R216 House W'), - ('r216_mt_coronet', 'R216 Mt Coronet'), - ], - 'sunyshore': [ - ('sunyshore_pokecenter', 'Sunyshore Pokecenter'), - ('sunyshore_mart', 'Sunyshore Mart'), - ('sunyshore_gym', 'Sunyshore Gym'), - ('sunyshore_lighthouse', 'Sunyshore Lighthouse'), - ('sunyshore_market', 'Sunyshore Market'), - ('sunyshore_house_w', 'Sunyshore House W'), - ('sunyshore_house_n', 'Sunyshore House N'), - ('sunyshore_house_ne', 'Sunyshore House NE'), - ('sunyshore_house_e', 'Sunyshore House E'), - ('sunyshore_west_exit', 'Sunyshore West Exit'), - ], - 'fight_resort': [ - ('fight_area_pokecenter', 'Fight Area Pokecenter'), - ('fight_area_mart', 'Fight Area Mart'), - ('fight_area_s_house', 'Fight Area S House'), - ('fight_area_c_house', 'Fight Area C House'), - ('fight_area_north_exit', 'Fight Area North Exit'), - ('resort_area_pokecenter', 'Resort Area Pokecenter'), - ('resort_area_villa', 'Resort Area Villa'), - ('resort_area_ribbon_syndicate', 'Resort Area Ribbon Syndicate'), - ('resort_area_house', 'Resort Area House'), - ('r228_s_house', 'R228 S House'), - ('r228_c_house', 'R228 C House'), - ('r228_north_exit', 'R228 North Exit'), - ], - 'survival': [ - ('survival_area_pokecenter', 'Survival Area Pokecenter'), - ('survival_area_mart', 'Survival Area Mart'), - ('survival_area_n_house', 'Survival Area N House'), - ('survival_area_c_house', 'Survival Area C House'), - ('survival_area_s_house', 'Survival Area S House'), - ('r225_house', 'R225 House'), - ('r225_south_exit', 'R225 South Exit'), - ('r226_house', 'R226 House'), - ('r226_east_exit', 'R226 East Exit'), - ('r227_house', 'R227 House'), - ('r227_stark_mountain', 'R227 Stark Mountain'), - ], - 'jubilife_tv': [ - ('jubilife_tv_1f_up', 'TV 1F Up'), - ('jubilife_tv_1f_exit', 'TV 1F Exit'), - ('jubilife_tv_2f_n', 'TV 2F N'), - ('jubilife_tv_2f_up', 'TV 2F Up'), - ('jubilife_tv_2f_down', 'TV 2F Down'), - ('jubilife_tv_3f_nw', 'TV 3F NW'), - ('jubilife_tv_3f_n', 'TV 3F N'), - ('jubilife_tv_3f_up', 'TV 3F Up'), - ('jubilife_tv_3f_down', 'TV 3F Down'), - ('jubilife_tv_4f_down', 'TV 4F Down'), - ], - 'store': [ - ('department_store_b1f_up', 'Store B1F Up'), - ('department_store_1f_up', 'Store 1F Up'), - ('department_store_1f_down', 'Store 1F Down'), - ('department_store_1f_exit', 'Store 1F Exit'), - ('department_store_2f_up', 'Store 2F Up'), - ('department_store_2f_down', 'Store 2F Down'), - ('department_store_3f_up', 'Store 3F Up'), - ('department_store_3f_down', 'Store 3F Down'), - ('department_store_4f_up', 'Store 4F Up'), - ('department_store_4f_down', 'Store 4F Down'), - ('department_store_5f_down', 'Store 5F Down'), - ], - 'galactic_eterna': [ - ('galactic_eterna_1f_s', 'TG Eterna 1F Exit S'), - ('galactic_eterna_1f_nw', 'TG Eterna 1F NW'), - ('galactic_eterna_1f_stairs_n', 'TG Eterna 1F Stairs N'), - ('galactic_eterna_1f_stairs_ne', 'TG Eterna 1F Stairs NE'), - ('galactic_eterna_2f_w', 'TG Eterna 2F W'), - ('galactic_eterna_2f_n', 'TG Eterna 2F N'), - ('galactic_eterna_2f_e', 'TG Eterna 2F E'), - ('galactic_eterna_3f_w', 'TG Eterna 3F W'), - ('galactic_eterna_3f_n', 'TG Eterna 3F N'), - ('galactic_eterna_3f_e', 'TG Eterna 3F E'), - ], - 'galactic_hq': [ - ('galactic_warehouse_b2f_stairs_c', 'Warehouse Stairs C'), - ('galactic_warehouse_b2f_stairs_e', 'Warehouse Stairs E'), - ('galactic_warehouse_b2f_stairs_w', 'Warehouse Stairs W'), +INITIAL_LOCATION = Category('sandgem_jubilife', 'Sandgem/Jubilife', []) - ('galactic_hq_1f_south_stairs', 'HQ 1F A Stairs'), - ('galactic_hq_1f_south_entrance_e', 'HQ 1F A East Exit'), - ('galactic_hq_1f_south_entrance_w', 'HQ 1F A West Exit'), - - ('galactic_hq_1f_ne_stairs', 'HQ 1F B Stairs'), - ('galactic_hq_1f_ne_warp_e', 'HQ 1F B Warp E'), - ('galactic_hq_1f_ne_warp_w', 'HQ 1F B Warp W'), - - ('galactic_hq_2f_s_stairs', 'HQ 2F A Stairs'), - ('galactic_hq_2f_s_warp_c', 'HQ 2F A Warp C'), - ('galactic_hq_2f_s_warp_ne', 'HQ 2F A Warp NE'), - ('galactic_hq_2f_s_warp_se', 'HQ 2F A Warp SE'), - - ('galactic_hq_2f_nw_warp', 'HQ 2F B Warp'), - ('galactic_hq_2f_nw_up', 'HQ 2F B Up'), - ('galactic_hq_2f_nw_down', 'HQ 2F B Down'), - - ('galactic_hq_3f_warp_1', 'HQ 3F Warp W'), - ('galactic_hq_3f_warp_2', 'HQ 3F Warp C'), - ('galactic_hq_3f_warp_3', 'HQ 3F Warp E'), - ('galactic_hq_3f_stairs', 'HQ 3F Stairs'), - - ('galactic_hq_4f_stairs', 'HQ 4F Stairs'), - ('galactic_hq_4f_warp_n', 'HQ 4F Warp N'), - ('galactic_hq_4f_warp_ne', 'HQ 4F Warp NE'), - ('galactic_hq_4f_warp_se', 'HQ 4F Warp SE'), - ], - 'old_chateau': [ - ('old_chateau_n', 'OC Entrance N'), - ('old_chateau_e', 'OC Entrance E'), - ('old_chateau_s', 'OC Entrance S'), - ('old_chateau_w', 'OC Entrance W'), - ('old_chateau_c', 'OC Entrance C'), - - ('old_chateau_2f_room_1', 'OC 2F Room 1'), - ('old_chateau_2f_room_2', 'OC 2F Room 2'), - ('old_chateau_2f_room_3', 'OC 2F Room 3'), - ('old_chateau_2f_room_4', 'OC 2F Room 4'), - ('old_chateau_2f_room_5', 'OC 2F Room 5'), - ('old_chateau_2f_exit', 'OC 2F Exit'), - ], - 'solaceon_ruins': [ - ('solaceon_ruins_1f_nw', 'SR 1F NW'), - ('solaceon_ruins_1f_ne', 'SR 1F NE'), - ('solaceon_ruins_1f_se', 'SR 1F SE'), - ('solaceon_ruins_1f_exit', 'SR 1F Exit'), - - ('solaceon_ruins_b1f_nw', 'SR B1F NW'), - ('solaceon_ruins_b1f_ne', 'SR B1F NE'), - ('solaceon_ruins_b1f_se', 'SR B1F SE'), - ('solaceon_ruins_b1f_sw', 'SR B1F SW'), - - ('solaceon_ruins_b2f_nw', 'SR B2F NW'), - ('solaceon_ruins_b2f_ne', 'SR B2F NE'), - ('solaceon_ruins_b2f_se', 'SR B2F SE'), - ('solaceon_ruins_b2f_sw', 'SR B2F SW'), - - ('solaceon_ruins_b3f_a_nw', 'SR B3F A NW'), - ('solaceon_ruins_b3f_a_ne', 'SR B3F A NE'), - ('solaceon_ruins_b3f_a_se', 'SR B3F A SE'), - ('solaceon_ruins_b3f_a_sw', 'SR B3F A SW'), - - ('solaceon_ruins_b3f_b_nw', 'SR B3F B NW'), - ('solaceon_ruins_b3f_b_se', 'SR B3F B SE'), - ('solaceon_ruins_b3f_b_sw', 'SR B3F B SW'), - - ('solaceon_ruins_b4f_nw', 'SR B4F NW'), - ('solaceon_ruins_b4f_ne', 'SR B4F NE'), - ('solaceon_ruins_b4f_se', 'SR B4F SE'), - ('solaceon_ruins_b4f_sw', 'SR B4F SW'), - ], - 'pokemansion': [ - ('poke_mansion_s', 'Pokémansion S'), - ('poke_mansion_w', 'Pokémansion W'), - ('poke_mansion_e', 'Pokémansion E'), - ('poke_mansion_n', 'Pokémansion N'), - ('poke_mansion_room_1', 'Pokémansion Room 1'), - ('poke_mansion_room_2', 'Pokémansion Room 2'), - ('poke_mansion_room_3', 'Pokémansion Room 3'), - ('poke_mansion_room_4', 'Pokémansion Room 4'), - ], - 'r208_forest_march': [ - ('r208_forest_march_berry_house', 'R208 Berry House'), - ('r208_forest_march_208_east_exit', 'R208 East Exit'), - ('r208_forest_march_208_west_exit', 'R208 West Exit'), - ('r208_forest_march_chateau', 'Eterna Forest Old Chateau'), - ('r208_forest_march_forest_east_exit', 'Eterna Forest East Exit'), - ('r208_forest_march_forest_west_exit', 'Eterna Forest South Exit'), - ('r208_forest_march_marsh_s', 'Great Marsh S'), - ('r208_forest_march_marsh_n', 'Great Marsh N'), - ('r208_forest_march_marsh_up', 'Great Marsh Up'), - ], - 'r213_214_222': [ - ('r213_hotel', 'R213 Hotel'), - ('r213_house', 'R213 House'), - ('r213_west_exit', 'R213 West Exit'), - ('r214_maniac_tunnel', 'R214 Maniac Tunnel'), - ('r214_sendoff_spring', 'R214 Sendoff Spring'), - ('r214_north_exit', 'R214 North Exit'), - ('valor_lakefront', 'Valor Lakefront'), - ('hotel_grand_lake_nw', 'Hotel Grand Lake NW'), - ('hotel_grand_lake_n', 'Hotel Grand Lake N'), - ('hotel_grand_lake_ne', 'Hotel Grand Lake NE'), - ('hotel_grand_lake_w', 'Hotel Grand Lake W'), - ('hotel_grand_lake_e', 'Hotel Grand Lake E'), - ('hotel_grand_lake_se', 'Hotel Grand Lake SE'), - ('hotel_grand_lake_s', 'Hotel Grand Lake S'), - ('r222_house_w', 'R222 House W'), - ('r222_house_e', 'R222 House E'), - ('r222_east_exit', 'R222 East Exit'), - ], - 'mt_coronet': [ - ('mt_coronet_1f_a_north_stairs', 'Coronet 1F A North Stairs'), - ('mt_coronet_1f_a_east_exit', 'Coronet 1F A East Exit'), - ('mt_coronet_1f_a_south_exit', 'Coronet 1F A South Exit'), - ('mt_coronet_1f_a_west_exit', 'Coronet 1F A West Exit'), - - ('mt_coronet_1f_2_south_stairs', 'Coronet 1F B South Stairs'), - ('mt_coronet_1f_2_regice_cave', 'Coronet 1F B Regice Cave'), - ('mt_coronet_1f_2_west_exit', 'Coronet 1F B West Exit'), - - ('mt_coronet_1f_3_ne_stairs', 'Coronet 1F C NE Stairs'), - ('mt_coronet_1f_3_east_exit', 'Coronet 1F C East Exit'), - ('mt_coronet_1f_3_west_exit', 'Coronet 1F C West Exit'), - - ('mt_coronet_2f_s_stairs', 'Coronet 2F E Stairs'), - ('mt_coronet_2f_n_cave', 'Coronet 2F N Cave'), - ('mt_coronet_2f_sw_exit', 'Coronet 2F SW Exit'), - - ('mt_coronet_3f_east_stairs', 'Coronet 3F East Stairs'), - ('mt_coronet_3f_west_stairs', 'Coronet 3F West Stairs'), - ('mt_coronet_3f_west_exit', 'Coronet 3F West Exit'), - - ('mt_coronet_summit_nw_cave', 'Coronet Summit NW Cave'), - ('mt_coronet_summit_ne_cave', 'Coronet Summit NE Cave'), - ('mt_coronet_summit_e_cave', 'Coronet Summit E Cave'), - ('mt_coronet_summit_se_cave', 'Coronet Summit SE Cave'), - ('mt_coronet_summit_w_cave', 'Coronet Summit W Cave'), - ('mt_coronet_summit_nw_cave', 'Coronet Summit NW Cave'), - ], - 'victory_road': [ - ('victory_road_1f_nw_stairs', 'VR 1F NW Stairs'), - ('victory_road_1f_w_stairs', 'VR 1F W Stairs'), - ('victory_road_1f_sw_stairs', 'VR 1F SW Stairs'), - ('victory_road_1f_ne_stairs', 'VR 1F NE Stairs'), - ('victory_road_1f_e_stairs', 'VR 1F E Stairs'), - ('victory_road_1f_se_stairs', 'VR 1F SE Stairs'), - ('victory_road_1f_north_exit', 'VR 1F North Exit'), - ('victory_road_1f_south_exit', 'VR 1F South Exit'), - - ('victory_road_b1f_nw_stairs', 'VR B1F NW Stairs'), - ('victory_road_b1f_w_stairs', 'VR B1F W Stairs'), - ('victory_road_b1f_sw_stairs', 'VR B1F SW Stairs'), - ], - 'iron_island': [ - ('iron_island_exterior_entrance', 'Iron Island Exterior Entrance'), - ('iron_island_exterior_house', 'Iron Island Exterior House'), - ('iron_island_exterior_exit', 'Iron Island Exterior Exit'), - - ('iron_island_1f_w', 'Iron Island 1F W'), - ('iron_island_1f_e', 'Iron Island 1F E'), - ('iron_island_1f_exit', 'Iron Island 1F Exit'), - - ('iron_island_b1f_nw', 'Iron Island B1F NW'), - ('iron_island_b1f_sw', 'Iron Island B1F SW'), - ('iron_island_b1f_se', 'Iron Island B1F SE'), - - ('iron_island_b3f_nw', 'Iron Island B3F NW'), - ('iron_island_b3f_registeel', 'Iron Island B3F N'), - ('iron_island_b3f_se', 'Iron Island B3F SE'), - ], - 'poketch_gts_gate': [ - ('poketch_interior_sw', 'Poketch Interior SW'), - ('poketch_interior_se', 'Poketch Interior SE'), - ('poketch_interior_up', 'Poketch Interior Up'), - ('gts_1f_warp_w', 'GTS 1F Warp W'), - ('gts_1f_warp_e', 'GTS 1F Warp E'), - ('gts_1f_exit', 'GTS 1F Exit'), - ('oreburgh_gate_stairs', 'Oreburgh Gate Stairs'), - ('oreburgh_gate_east_exit', 'Oreburgh Gate East Exit'), - ('oreburgh_gate_west_exit', 'Oreburgh Gate West Exit'), - ], - 'surf_hub': [ - ('lake_verity', 'Lake Verity'), - ('lake_valor', 'Lake Valor'), - ('lake_acuity', 'Lake Acuity'), - ('r221_house', 'R221 House'), - ('r221_pal_park', 'R221 Pal Park'), - ], -} +CATEGORIES = [ + Category('poi', 'Places of Interest', [ + Location('oreburgh_gym_interior', 'Oreburgh Gym Interior', + [Entrance('oreburgh_gym_interior', 'Oreburgh Gym Interior')]), + Location('eterna_gym_interior', 'Eterna Gym Interior', + [Entrance('eterna_gym_interior', 'Eterna Gym Interior')]), + Location('hearthome_gym_interior', 'Hearthome Gym Interior', + [Entrance('hearthome_gym_interior', 'Hearthome Gym Interior')]), + Location('veilstone_gym_interior', 'Veilstone Gym Interior', + [Entrance('veilstone_gym_interior', 'Veilstone Gym Interior')]), + Location('pastoria_gym_interior', 'Pastoria Gym Interior', + [Entrance('pastoria_gym_interior', 'Pastoria Gym Interior')]), + Location('canalave_gym_interior', 'Canalave Gym Interior', + [Entrance('canalave_gym_interior', 'Canalave Gym Interior')]), + Location('snowpoint_gym_interior', 'Snowpoint Gym Interior', + [Entrance('snowpoint_gym_interior', 'Snowpoint Gym Interior')]), + Location('sunyshore_gym_interior', 'Sunyshore Gym Interior', + [Entrance('sunyshore_gym_interior', 'Sunyshore Gym Interior')]), + Location('e4_aaron', 'E4 Aaron', + [Entrance('e4_aaron', 'E4 Aaron')]), + Location('e4_bertha', 'E4 Bertha', + [Entrance('e4_bertha', 'E4 Bertha')]), + Location('e4_flint', 'E4 Flint', + [Entrance('e4_flint', 'E4 Flint')]), + Location('e4_lucian', 'E4 Lucian', + [Entrance('e4_lucian', 'E4 Lucian')]), + Location('champion', 'Champion', + [Entrance('champion', 'Champion')]), + Location('dialga_palkia', 'Dialga/Palkia', + [Entrance('dialga_palkia', 'Dialga/Palkia')]), + Location('cresselia', 'Cresselia', + [Entrance('cresselia', 'Cresselia')]), + Location('darkrai', 'Darkrai', + [Entrance('darkrai', 'Darkrai')]), + Location('heatran', 'Heatran', + [Entrance('heatran', 'Heatran')]), + Location('arceus', 'Arceus', + [Entrance('arceus', 'Arceus')]), + Location('azelf', 'Azelf', + [Entrance('azelf', 'Azelf')]), + Location('uxie', 'Uxie', + [Entrance('uxie', 'Uxie')]), + ]), + Category('pokecenters_1', 'Pokécenters 1', [ + Location('sandgem_pc', 'Sandgem PC', [ + Entrance('sandgem_pc_w', 'Sandgem PC W'), + Entrance('sandgem_pc_s', 'Sandgem PC S'), + Entrance('sandgem_pc_e', 'Sandgem PC E'), + ]), + Location('jubilife_pc', 'Jubilife PC', [ + Entrance('jubilife_pc_w', 'Jubilife PC W'), + Entrance('jubilife_pc_s', 'Jubilife PC S'), + Entrance('jubilife_pc_e', 'Jubilife PC E'), + ]), + Location('oreburgh_pc', 'Oreburgh PC', [ + Entrance('oreburgh_pc_w', 'Oreburgh PC W'), + Entrance('oreburgh_pc_s', 'Oreburgh PC S'), + Entrance('oreburgh_pc_e', 'Oreburgh PC E'), + ]), + Location('floaroma_pc', 'Floaroma PC', [ + Entrance('floaroma_pc_w', 'Floaroma PC W'), + Entrance('floaroma_pc_s', 'Floaroma PC S'), + Entrance('floaroma_pc_e', 'Floaroma PC E'), + ]), + Location('eterna_pc', 'Eterna PC', [ + Entrance('eterna_pc_w', 'Eterna PC W'), + Entrance('eterna_pc_s', 'Eterna PC S'), + Entrance('eterna_pc_e', 'Eterna PC E'), + ]), + Location('hearthome_pc', 'Hearthome PC', [ + Entrance('hearthome_pc_w', 'Hearthome PC W'), + Entrance('hearthome_pc_s', 'Hearthome PC S'), + Entrance('hearthome_pc_e', 'Hearthome PC E'), + ]), + Location('solaceon_pc', 'Solaceon PC', [ + Entrance('solaceon_pc_w', 'Solaceon PC W'), + Entrance('solaceon_pc_s', 'Solaceon PC S'), + Entrance('solaceon_pc_e', 'Solaceon PC E'), + ]), + Location('veilstone_pc', 'Veilstone PC', [ + Entrance('veilstone_pc_w', 'Veilstone PC W'), + Entrance('veilstone_pc_s', 'Veilstone PC S'), + Entrance('veilstone_pc_e', 'Veilstone PC E'), + ]), + Location('pastoria_pc', 'Pastoria PC', [ + Entrance('pastoria_pc_w', 'Pastoria PC W'), + Entrance('pastoria_pc_s', 'Pastoria PC S'), + Entrance('pastoria_pc_e', 'Pastoria PC E'), + ]), + ]), + Category('pokecenters_2', 'Pokécenters 2', [ + Location('celestic_pc', 'Celestic PC', [ + Entrance('celestic_pc_w', 'Celestic PC W'), + Entrance('celestic_pc_s', 'Celestic PC S'), + Entrance('celestic_pc_e', 'Celestic PC E'), + ]), + Location('canalave_pc', 'Canalave PC', [ + Entrance('canalave_pc_w', 'Canalave PC W'), + Entrance('canalave_pc_s', 'Canalave PC S'), + Entrance('canalave_pc_e', 'Canalave PC E'), + ]), + Location('snowpoint_pc', 'Snowpoint PC', [ + Entrance('snowpoint_pc_w', 'Snowpoint PC W'), + Entrance('snowpoint_pc_s', 'Snowpoint PC S'), + Entrance('snowpoint_pc_e', 'Snowpoint PC E'), + ]), + Location('sunyshore_pc', 'Sunyshore PC', [ + Entrance('sunyshore_pc_w', 'Sunyshore PC W'), + Entrance('sunyshore_pc_s', 'Sunyshore PC S'), + Entrance('sunyshore_pc_e', 'Sunyshore PC E'), + ]), + Location('victory_road_pc', 'VR PC', [ + Entrance('victory_road_pc_w', 'VR PC W'), + Entrance('victory_road_pc_s', 'VR PC S'), + Entrance('victory_road_pc_e', 'VR PC E'), + ]), + Location('pokemon_league_pc', 'League PC', [ + Entrance('pokemon_league_up', 'League PC Up'), + Entrance('pokemon_league_down', 'League PC Down'), + Entrance('pokemon_league_n', 'League PC N'), + Entrance('pokemon_league_s', 'League PC S'), + ]), + Location('fight_area_pc', 'Fight Area PC', [ + Entrance('fight_area_pc_w', 'Fight Area PC W'), + Entrance('fight_area_pc_s', 'Fight Area PC S'), + Entrance('fight_area_pc_e', 'Fight Area PC E'), + ]), + Location('survival_area_pc', 'Survival Area PC', [ + Entrance('survival_area_pc_w', 'Survival Area PC W'), + Entrance('survival_area_pc_s', 'Survival Area PC S'), + Entrance('survival_area_pc_e', 'Survival Area PC E'), + ]), + Location('resort_area_pc', 'Resort Area PC', [ + Entrance('resort_area_pc_w', 'Resort Area PC W'), + Entrance('resort_area_pc_s', 'Resort Area PC S'), + Entrance('resort_area_pc_e', 'Resort Area PC E'), + ]), + ]), + Category('sandgem_jubilife', 'Sandgem/Jubilife', [ + Location('sandgem_jubilife', 'Sandgem/Jubilife', [ + Entrance('verity_lakefront', 'Verity Lakefront'), + Entrance('sandgem_sw', 'Sandgem SW'), + Entrance('sandgem_s', 'Sandgem S'), + Entrance('sandgem_mart', 'Sandgem Mart'), + Entrance('sandgem_pokecenter', 'Sandgem Pokécenter'), + Entrance('jubilife_pokecenter', 'Jubilife Pokécenter'), + Entrance('jubilife_trainer_school', 'Jubilife Trainer School'), + Entrance('jubilife_mart', 'Jubilife Mart'), + Entrance('jubilife_s', 'Jubilife S'), + Entrance('jubilife_sw', 'Jubilife SW'), + Entrance('jubilife_ne', 'Jubilife NE'), + Entrance('jubilife_gts', 'Jubilife GTS'), + Entrance('jubilife_tv', 'Jubilife TV'), + Entrance('jubilife_poketch_w', 'Jubilife Poketch W'), + Entrance('jubilife_poketch_e', 'Jubilife Poketch E'), + Entrance('jubilife_ravaged_path', 'Jubilife Ravaged Path'), + Entrance('jubilife_oreburgh_gate', 'Jubilife Oreburgh Gate'), + Entrance('jubilife_west_exit', 'Jubilife West Exit'), + ]), + ]), + Category('oreburgh', 'Oreburgh', [ + Location('oreburgh', 'Oreburgh', [ + Entrance('oreburgh_gym', 'Oreburgh Gym'), + Entrance('oreburgh_mart', 'Oreburgh Mart'), + Entrance('oreburgh_pokecenter', 'Oreburgh Pokécenter'), + Entrance('oreburgh_fossil_lab', 'Oreburgh Fossil Lab'), + Entrance('oreburgh_mine', 'Oreburgh Mine'), + Entrance('oreburgh_apartment_nw', 'Oreburgh Apartment NW'), + Entrance('oreburgh_apartment_n', 'Oreburgh Apartment N'), + Entrance('oreburgh_apartment_e', 'Oreburgh Apartment E'), + Entrance('oreburgh_house_w', 'Oreburgh House W'), + Entrance('oreburgh_house_c', 'Oreburgh House C'), + Entrance('oreburgh_house_se', 'Oreburgh House SE'), + Entrance('oreburgh_west_exit', 'Oreburgh West Exit'), + Entrance('r206_cycle_path', 'R206 Cycle Path'), + Entrance('r206_wayward_cave', 'R206 Wayward Cave'), + Entrance('r206_wayward_cave_hidden', 'R206 Wayward Cave Hidden'), + Entrance('r207_mt_coronet', 'R207 Mt Coronet'), + ]), + ]), + Category('floaroma', 'Floaroma', [ + Location('floaroma', 'Floaroma', [ + Entrance('floaroma_pokecenter', 'Floaroma Pokecenter'), + Entrance('floaroma_mart', 'Floaroma Mart'), + Entrance('floaroma_flower_shop', 'Floaroma Flower Shop'), + Entrance('floaroma_nw', 'Floaroma NW'), + Entrance('floaroma_se', 'Floaroma SE'), + Entrance('floaroma_ravaged_path', 'Floaroma Ravaged Path'), + Entrance('floaroma_meadow_entrance_floaroma', 'Meadow Entrance Floaroma'), + Entrance('floaroma_meadow_exit_house', 'Meadow House'), + Entrance('floaroma_meadow_exit_n', 'Meadow Exit N'), + Entrance('floaroma_meadow_exit_s', 'Meadow Exit S'), + Entrance('r205_ironworks', 'R205 Ironworks'), + Entrance('floaroma_meadow_entrance_iron', 'R205 Meadow Entrance'), + Entrance('r205_windworks', 'R205 Windworks'), + Entrance('r205_eterna_forest', 'R205 Eterna Forest'), + Entrance('r205_house', 'R205 House'), + ]), + ]), + Category('eterna', 'Eterna', [ + Location('eterna', 'Eterna', [ + Entrance('eterna_pokecenter', 'Eterna Pokecenter'), + Entrance('eterna_mart', 'Eterna Mart'), + Entrance('eterna_gym', 'Eterna Gym'), + Entrance('eterna_bike_shop', 'Eterna Bike Shop'), + Entrance('eterna_spelunkers_house', 'Spelunker\'s House'), + Entrance('eterna_city_forest', 'Eterna City Forest'), + Entrance('eterna_apartment', 'Eterna Apartment'), + Entrance('eterna_galactic', 'Eterna Galactic Building'), + Entrance('eterna_house_n', 'Eterna House N'), + Entrance('eterna_house_s', 'Eterna House S'), + Entrance('eterna_house_e', 'Eterna House E'), + Entrance('eterna_mt_coronet', 'Eterna Mt Coronet'), + Entrance('eterna_south_exit', 'Eterna South Exit'), + ]), + ]), + Category('hearthome', 'Hearthome', [ + Location('hearthome', 'Hearthome', [ + Entrance('hearthome_pokecenter', 'Hearthome Pokecenter'), + Entrance('hearthome_mart', 'Hearthome Mart'), + Entrance('hearthome_gym', 'Hearthome Gym'), + Entrance('hearthome_contest', 'Hearthome Contest'), + Entrance('hearthome_bebes_house', 'Bebe\'s house'), + Entrance('hearthome_church', 'Hearthome Church'), + Entrance('hearthome_poffin_house', 'Hearthome Poffin House'), + Entrance('hearthome_fanclub', 'Hearthome Fanclub'), + Entrance('hearthome_apartment_n', 'Hearthome Apartment N'), + Entrance('hearthome_apartment_e', 'Hearthome Apartment E'), + Entrance('hearthome_amity_square_west', 'Amity Square West'), + Entrance('hearthome_amity_square_east', 'Amity Square East'), + Entrance('hearthome_east_exit', 'Hearthome East Exit'), + Entrance('hearthome_south_exit', 'Hearthome South Exit'), + Entrance('hearthome_west_exit', 'Hearthome West Exit'), + ]), + ]), + Category('solaceon', 'Solaceon', [ + Location('solaceon', 'Solaceon', [ + Entrance('solaceon_pokecenter', 'Solaceon Pokecenter'), + Entrance('solaceon_mart', 'Solaceon Mart'), + Entrance('solaceon_daycare', 'Solaceon Daycare'), + Entrance('solaceon_house_n', 'Solaceon House N'), + Entrance('solaceon_house_ne', 'Solaceon House NE'), + Entrance('solaceon_house_e', 'Solaceon House E'), + Entrance('solaceon_house_c', 'Solaceon House C'), + Entrance('solaceon_ruins', 'Solaceon Ruins'), + Entrance('r209_lost_tower', 'R209 Lost Tower'), + Entrance('r209_west_exit', 'R209 West Exit'), + Entrance('r210_cafe_cabin', 'R210 Cafe Cabin'), + Entrance('r215_east_exit', 'R215 East Exit'), + ]), + ]), + Category('veilstone', 'Veilstone', [ + Location('veilstone', 'Veilstone', [ + Entrance('veilstone_pokecenter', 'Veilstone Pokecenter'), + Entrance('veilstone_mart', 'Veilstone Mart'), + Entrance('veilstone_gym', 'Veilstone Gym'), + Entrance('veilstone_casino', 'Veilstone Casino'), + Entrance('veilstone_galactic_hq_1', 'Galactic HQ 1'), + Entrance('veilstone_galactic_hq_2', 'Galactic HQ 2'), + Entrance('veilstone_galactic_hq_3', 'Galactic HQ 3'), + Entrance('veilstone_galactic_warehouse', 'Galactic Warehouse'), + Entrance('veilstone_house_n', 'Veilstone House N'), + Entrance('veilstone_house_ne', 'Veilstone House NE'), + Entrance('veilstone_prize_exchange', 'Prize Exchange'), + Entrance('veilstone_house_s', 'Veilstone House S'), + Entrance('veilstone_house_sw', 'Veilstone House SW'), + Entrance('veilstone_south_exit', 'Veilstone South Exit'), + Entrance('veilstone_west_exit', 'Veilstone West Exit'), + ]), + ]), + Category('pastoria', 'Pastoria', [ + Location('pastoria', 'Pastoria', [ + Entrance('pastoria_pokecenter', 'Pastoria Pokecenter'), + Entrance('pastoria_mart', 'Pastoria Mart'), + Entrance('pastoria_gym', 'Pastoria Gym'), + Entrance('pastoria_great_marsh', 'Pastoria Great Marsh'), + Entrance('pastoria_house_ne', 'Pastoria House NE'), + Entrance('pastoria_house_se', 'Pastoria House SE'), + Entrance('pastoria_house_sw', 'Pastoria House SW'), + Entrance('pastoria_house_n', 'Pastoria House N'), + Entrance('pastoria_house_c', 'Pastoria House C'), + Entrance('pastoria_east_exit', 'Pastoria East Exit'), + Entrance('r212_move_tutor', 'R212 Move Tutor'), + Entrance('r212_pokemon_mansion', 'R212 Pokemon Mansion'), + Entrance('r212_north_exit', 'R212 North Exit'), + ]), + ]), + Category('celestic', 'Celestic', [ + Location('celestic', 'Celestic', [ + Entrance('celestic_pokecenter', 'Celestic Pokecenter'), + Entrance('celestic_ruins', 'Celestic Ruins'), + Entrance('celestic_big_house', 'Celestic Big House'), + Entrance('celestic_house_ne', 'Celestic House NE'), + Entrance('celestic_house_nw', 'Celestic House NW'), + Entrance('celestic_house_sw', 'Celestic House SW'), + Entrance('celestic_mt_coronet', 'Celestic Mt Coronet'), + Entrance('r210_grandmas_house', 'R210 Grandmas House'), + ]), + ]), + Category('canalave', 'Canalave', [ + Location('canalave', 'Canalave', [ + Entrance('canalave_pokecenter', 'Canalave Pokecenter'), + Entrance('canalave_mart', 'Canalave Mart'), + Entrance('canalave_gym', 'Canalave Gym'), + Entrance('canalave_library', 'Canalave Library'), + Entrance('canalave_house_e', 'Canalave House E'), + Entrance('canalave_house_se', 'Canalave House SE'), + Entrance('canalave_house_w', 'Canalave House W'), + Entrance('canalave_house_sw', 'Canalave House SW'), + Entrance('canalave_east_exit', 'Canalave East Exit'), + ]), + ]), + Category('snowpoint', 'Snowpoint', [ + Location('snowpoint', 'Snowpoint', [ + Entrance('snowpoint_pokecenter', 'Snowpoint Pokecenter'), + Entrance('snowpoint_mart', 'Snowpoint Mart'), + Entrance('snowpoint_gym', 'Snowpoint Gym'), + Entrance('snowpoint_house_nw', 'Snowpoint House NW'), + Entrance('snowpoint_house_ne', 'Snowpoint House NE'), + Entrance('snowpoint_temple', 'Snowpoint Temple'), + Entrance('acuity_lakefront', 'Acuity Lakefront'), + Entrance('r217_house_n', 'R217 House N'), + Entrance('r217_house_w', 'R217 House W'), + Entrance('r216_house_w', 'R216 House W'), + Entrance('r216_mt_coronet', 'R216 Mt Coronet'), + ]), + ]), + Category('sunyshore', 'Sunyshore', [ + Location('sunyshore', 'Sunyshore', [ + Entrance('sunyshore_pokecenter', 'Sunyshore Pokecenter'), + Entrance('sunyshore_mart', 'Sunyshore Mart'), + Entrance('sunyshore_gym', 'Sunyshore Gym'), + Entrance('sunyshore_lighthouse', 'Sunyshore Lighthouse'), + Entrance('sunyshore_market', 'Sunyshore Market'), + Entrance('sunyshore_house_w', 'Sunyshore House W'), + Entrance('sunyshore_house_n', 'Sunyshore House N'), + Entrance('sunyshore_house_ne', 'Sunyshore House NE'), + Entrance('sunyshore_house_e', 'Sunyshore House E'), + Entrance('sunyshore_west_exit', 'Sunyshore West Exit'), + ]), + ]), + Category('fight_resort', 'Fight/Resort', [ + Location('fight_resort', 'Fight/Resort', [ + Entrance('fight_area_pokecenter', 'Fight Area Pokecenter'), + Entrance('fight_area_mart', 'Fight Area Mart'), + Entrance('fight_area_s_house', 'Fight Area S House'), + Entrance('fight_area_c_house', 'Fight Area C House'), + Entrance('fight_area_north_exit', 'Fight Area North Exit'), + Entrance('resort_area_pokecenter', 'Resort Area Pokecenter'), + Entrance('resort_agroup-locations-together-that-you-can-reachrea_villa', 'Resort Area Villa'), + Entrance('resort_area_ribbon_syndicate', 'Resort Area Ribbon Syndicate'), + Entrance('resort_area_house', 'Resort Area House'), + Entrance('r228_s_house', 'R228 S House'), + Entrance('r228_c_house', 'R228 C House'), + Entrance('r228_north_exit', 'R228 North Exit'), + ]), + ]), + Category('survival', 'Survival', [ + Location('survival', 'Survival', [ + Entrance('survival_area_pokecenter', 'Survival Area Pokecenter'), + Entrance('survival_area_mart', 'Survival Area Mart'), + Entrance('survival_area_n_house', 'Survival Area N House'), + Entrance('survival_area_c_house', 'Survival Area C House'), + Entrance('survival_area_s_house', 'Survival Area S House'), + Entrance('r225_house', 'R225 House'), + Entrance('r225_south_exit', 'R225 South Exit'), + Entrance('r226_house', 'R226 House'), + Entrance('r226_east_exit', 'R226 East Exit'), + Entrance('r227_house', 'R227 House'), + Entrance('r227_stark_mountain', 'R227 Stark Mountain'), + ]), + ]), + Category('jubilife_tv', 'Jubilife TV', [ + Location('jubilife_tv', 'Jubilife TV', [ + Entrance('jubilife_tv_1f_up', 'TV 1F Up'), + Entrance('jubilife_tv_1f_exit', 'TV 1F Exit'), + Entrance('jubilife_tv_2f_n', 'TV 2F N'), + Entrance('jubilife_tv_2f_up', 'TV 2F Up'), + Entrance('jubilife_tv_2f_down', 'TV 2F Down'), + Entrance('jubilife_tv_3f_nw', 'TV 3F NW'), + Entrance('jubilife_tv_3f_n', 'TV 3F N'), + Entrance('jubilife_tv_3f_up', 'TV 3F Up'), + Entrance('jubilife_tv_3f_down', 'TV 3F Down'), + Entrance('jubilife_tv_4f_down', 'TV 4F Down'), + ]), + ]), + Category('department_store', 'Department Store', [ + Location('department_store', 'Department Store', [ + Entrance('department_store_b1f_up', 'Store B1F Up'), + Entrance('department_store_1f_up', 'Store 1F Up'), + Entrance('department_store_1f_down', 'Store 1F Down'), + Entrance('department_store_1f_exit', 'Store 1F Exit'), + Entrance('department_store_2f_up', 'Store 2F Up'), + Entrance('department_store_2f_down', 'Store 2F Down'), + Entrance('department_store_3f_up', 'Store 3F Up'), + Entrance('department_store_3f_down', 'Store 3F Down'), + Entrance('department_store_4f_up', 'Store 4F Up'), + Entrance('department_store_4f_down', 'Store 4F Down'), + Entrance('department_store_5f_down', 'Store 5F Down'), + ]), + ]), + Category('pokemansion', 'Pokémansion', [ + Location('pokemansion', 'Pokémansion', [ + Entrance('poke_mansion_s', 'Pokémansion S'), + Entrance('poke_mansion_w', 'Pokémansion W'), + Entrance('poke_mansion_e', 'Pokémansion E'), + Entrance('poke_mansion_n', 'Pokémansion N'), + Entrance('poke_mansion_room_1', 'Pokémansion Room 1'), + Entrance('poke_mansion_room_2', 'Pokémansion Room 2'), + Entrance('poke_mansion_room_3', 'Pokémansion Room 3'), + Entrance('poke_mansion_room_4', 'Pokémansion Room 4'), + ]), + ]), + Category('galactic_eterna', 'Galactic Eterna', [ + Location('galactic_eterna_1f', 'Galactic Eterna 1F', [ + Entrance('galactic_eterna_1f_s', 'TG Eterna 1F Exit S'), + Entrance('galactic_eterna_1f_nw', 'TG Eterna 1F NW'), + Entrance('galactic_eterna_1f_stairs_n', 'TG Eterna 1F Stairs N'), + Entrance('galactic_eterna_1f_stairs_ne', 'TG Eterna 1F Stairs NE'), + ]), + Location('galactic_eterna_2f', 'Galactic Eterna 2F', [ + Entrance('galactic_eterna_2f_w', 'TG Eterna 2F W'), + Entrance('galactic_eterna_2f_n', 'TG Eterna 2F N'), + Entrance('galactic_eterna_2f_e', 'TG Eterna 2F E'), + ]), + Location('galactic_eterna_3f', 'Galactic Eterna 3F', [ + Entrance('galactic_eterna_3f_w', 'TG Eterna 3F W'), + Entrance('galactic_eterna_3f_n', 'TG Eterna 3F N'), + Entrance('galactic_eterna_3f_e', 'TG Eterna 3F E'), + ]), + ]), + Category('galactic_hq', 'Galactic HQ', [ + Location('galactic_warehouse', 'Galactic Warehouse', [ + Entrance('galactic_warehouse_b2f_stairs_c', 'Warehouse Stairs C'), + Entrance('galactic_warehouse_b2f_stairs_e', 'Warehouse Stairs E'), + Entrance('galactic_warehouse_b2f_stairs_w', 'Warehouse Stairs W'), + ]), + Location('galactic_hq_1f_a', 'Galactic HQ 1F A', [ + Entrance('galactic_hq_1f_a_stairs', 'HQ 1F A Stairs'), + Entrance('galactic_hq_1f_a_entrance_e', 'HQ 1F A East Exit'), + Entrance('galactic_hq_1f_a_entrance_w', 'HQ 1F A West Exit'), + ]), + Location('galactic_hq_1f_b', 'Galactic HQ 1F B', [ + Entrance('galactic_hq_1f_b_stairs', 'HQ 1F B Stairs'), + Entrance('galactic_hq_1f_b_warp_e', 'HQ 1F B Warp E'), + Entrance('galactic_hq_1f_b_warp_w', 'HQ 1F B Warp W'), + ]), + Location('galactic_hq_2f_a', 'Galactic HQ 2F A', [ + Entrance('galactic_hq_2f_a_stairs', 'HQ 2F A Stairs'), + Entrance('galactic_hq_2f_a_warp_c', 'HQ 2F A Warp C'), + Entrance('galactic_hq_2f_a_warp_ne', 'HQ 2F A Warp NE'), + Entrance('galactic_hq_2f_a_warp_se', 'HQ 2F A Warp SE'), + ]), + Location('galactic_hq_2f_b', 'Galactic HQ 2F B', [ + Entrance('galactic_hq_2f_b_warp', 'HQ 2F B Warp'), + Entrance('galactic_hq_2f_b_up', 'HQ 2F B Up'), + Entrance('galactic_hq_2f_b_down', 'HQ 2F B Down'), + ]), + Location('galactic_hq_3f', 'Galactic HQ 3F', [ + Entrance('galactic_hq_3f_warp_1', 'HQ 3F Warp W'), + Entrance('galactic_hq_3f_warp_2', 'HQ 3F Warp C'), + Entrance('galactic_hq_3f_warp_3', 'HQ 3F Warp E'), + Entrance('galactic_hq_3f_stairs', 'HQ 3F Stairs'), + ]), + Location('galactic_hq_4f', 'Galactic HQ 4F', [ + Entrance('galactic_hq_4f_stairs', 'HQ 4F Stairs'), + Entrance('galactic_hq_4f_warp_n', 'HQ 4F Warp N'), + Entrance('galactic_hq_4f_warp_ne', 'HQ 4F Warp NE'), + Entrance('galactic_hq_4f_warp_se', 'HQ 4F Warp SE'), + ]), + ]), + Category('old_chateau', 'Old Chateau', [ + Location('old_chateau_1f', 'Old Chateau 1F', [ + Entrance('old_chateau_n', 'OC Entrance N'), + Entrance('old_chateau_e', 'OC Entrance E'), + Entrance('old_chateau_s', 'OC Entrance S'), + Entrance('old_chateau_w', 'OC Entrance W'), + Entrance('old_chateau_c', 'OC Entrance C'), + ]), + Location('old_chatea_2f', 'Old Chateau 2F', [ + Entrance('old_chateau_2f_room_1', 'OC 2F Room 1'), + Entrance('old_chateau_2f_room_2', 'OC 2F Room 2'), + Entrance('old_chateau_2f_room_3', 'OC 2F Room 3'), + Entrance('old_chateau_2f_room_4', 'OC 2F Room 4'), + Entrance('old_chateau_2f_room_5', 'OC 2F Room 5'), + Entrance('old_chateau_2f_exit', 'OC 2F Exit'), + ]), + ]), + Category('solaceon_ruins', 'Solaceon Ruins', [ + Location('solaceon_ruins_1f', 'Solaceon Ruins 1F', [ + Entrance('solaceon_ruins_1f_nw', 'SR 1F NW'), + Entrance('solaceon_ruins_1f_ne', 'SR 1F NE'), + Entrance('solaceon_ruins_1f_se', 'SR 1F SE'), + Entrance('solaceon_ruins_1f_exit', 'SR 1F Exit'), + ]), + Location('solaceon_ruins_b1f', 'Solaceon Ruins B1F', [ + Entrance('solaceon_ruins_b1f_nw', 'SR B1F NW'), + Entrance('solaceon_ruins_b1f_ne', 'SR B1F NE'), + Entrance('solaceon_ruins_b1f_se', 'SR B1F SE'), + Entrance('solaceon_ruins_b1f_sw', 'SR B1F SW'), + ]), + Location('solaceon_ruins_b2f', 'Solaceon Ruins B2F', [ + Entrance('solaceon_ruins_b2f_nw', 'SR B2F NW'), + Entrance('solaceon_ruins_b2f_ne', 'SR B2F NE'), + Entrance('solaceon_ruins_b2f_se', 'SR B2F SE'), + Entrance('solaceon_ruins_b2f_sw', 'SR B2F SW'), + ]), + Location('solaceon_ruins_b3f_a', 'Solaceon Ruins B3F A', [ + Entrance('solaceon_ruins_b3f_a_nw', 'SR B3F A NW'), + Entrance('solaceon_ruins_b3f_a_ne', 'SR B3F A NE'), + Entrance('solaceon_ruins_b3f_a_se', 'SR B3F A SE'), + Entrance('solaceon_ruins_b3f_a_sw', 'SR B3F A SW'), + ]), + Location('solaceon_ruins_b3f_b', 'Solaceon Ruins B3F B', [ + Entrance('solaceon_ruins_b3f_b_nw', 'SR B3F B NW'), + Entrance('solaceon_ruins_b3f_b_se', 'SR B3F B SE'), + Entrance('solaceon_ruins_b3f_b_sw', 'SR B3F B SW'), + ]), + Location('solaceon_ruins_b4f', 'Solaceon Ruins B4F', [ + Entrance('solaceon_ruins_b4f_nw', 'SR B4F NW'), + Entrance('solaceon_ruins_b4f_ne', 'SR B4F NE'), + Entrance('solaceon_ruins_b4f_se', 'SR B4F SE'), + Entrance('solaceon_ruins_b4f_sw', 'SR B4F SW'), + ]), + ]), + Category('r208_forest_marsh', 'R208/Et.Forest/Marsh', [ + Location('r208', 'Route 208', [ + Entrance('r208_berry_house', 'R208 Berry House'), + Entrance('r208_east_exit', 'R208 East Exit'), + Entrance('r208_west_exit', 'R208 West Exit'), + ]), + Location('eterna_forest', 'Eterna Forest', [ + Entrance('eterna_forest_chateau', 'Eterna Forest Old Chateau'), + Entrance('eterna_forest_east_exit', 'Eterna Forest East Exit'), + Entrance('eterna_forest_west_exit', 'Eterna Forest South Exit'), + ]), + Location('great_marsh', 'Great Marsh', [ + Entrance('great_marsh_s', 'Great Marsh S'), + Entrance('great_marsh_n', 'Great Marsh N'), + Entrance('great_marsh_up', 'Great Marsh Up'), + ]) + ]), + Category('r213_214_222', 'R213/R214/R222', [ + Location('r213', 'Route 213', [ + Entrance('r213_hotel', 'R213 Hotel'), + Entrance('r213_house', 'R213 House'), + Entrance('r213_west_exit', 'R213 West Exit'), + ]), + Location('r214_hotel_222', 'R214/222/Hotel', [ + Entrance('r214_maniac_tunnel', 'R214 Maniac Tunnel'), + Entrance('r214_sendoff_spring', 'R214 Sendoff Spring'), + Entrance('r214_north_exit', 'R214 North Exit'), + Entrance('valor_lakefront', 'Valor Lakefront'), + Entrance('hotel_grand_lake_nw', 'Hotel Grand Lake NW'), + Entrance('hotel_grand_lake_n', 'Hotel Grand Lake N'), + Entrance('hotel_grand_lake_ne', 'Hotel Grand Lake NE'), + Entrance('hotel_grand_lake_w', 'Hotel Grand Lake W'), + Entrance('hotel_grand_lake_e', 'Hotel Grand Lake E'), + Entrance('hotel_grand_lake_se', 'Hotel Grand Lake SE'), + Entrance('hotel_grand_lake_s', 'Hotel Grand Lake S'), + Entrance('r222_house_w', 'R222 House W'), + Entrance('r222_house_e', 'R222 House E'), + Entrance('r222_east_exit', 'R222 East Exit'), + ]) + ]), + Category('mt_coronet', 'Mt Coronet', [ + Location('mt_coronet_1f_a', 'Coronet 1F A', [ + Entrance('mt_coronet_1f_a_north_stairs', 'Coronet 1F A North Stairs'), + Entrance('mt_coronet_1f_a_east_exit', 'Coronet 1F A East Exit'), + Entrance('mt_coronet_1f_a_south_exit', 'Coronet 1F A South Exit'), + Entrance('mt_coronet_1f_a_west_exit', 'Coronet 1F A West Exit'), + ]), + Location('mt_coronet_1f_b', 'Coronet 1F B', [ + Entrance('mt_coronet_1f_b_south_stairs', 'Coronet 1F B South Stairs'), + Entrance('mt_coronet_1f_b_regice_cave', 'Coronet 1F B Regice Cave'), + Entrance('mt_coronet_1f_b_west_exit', 'Coronet 1F B West Exit'), + ]), + Location('mt_coronet_1f_c', 'Coronet 1F C', [ + Entrance('mt_coronet_1f_c_ne_stairs', 'Coronet 1F C NE Stairs'), + Entrance('mt_coronet_1f_c_east_exit', 'Coronet 1F C East Exit'), + Entrance('mt_coronet_1f_c_west_exit', 'Coronet 1F C West Exit'), + ]), + Location('mt_coronet_2f', 'Coronet 2F', [ + Entrance('mt_coronet_2f_s_stairs', 'Coronet 2F E Stairs'), + Entrance('mt_coronet_2f_n_cave', 'Coronet 2F N Cave'), + Entrance('mt_coronet_2f_sw_exit', 'Coronet 2F SW Exit'), + ]), + Location('mt_coronet_3f', 'Coronet 3F', [ + Entrance('mt_coronet_3f_east_stairs', 'Coronet 3F East Stairs'), + Entrance('mt_coronet_3f_west_stairs', 'Coronet 3F West Stairs'), + Entrance('mt_coronet_3f_west_exit', 'Coronet 3F West Exit'), + ]), + Location('mt_coronet_summit', 'Coronet Summit', [ + Entrance('mt_coronet_summit_nw_cave', 'Coronet Summit NW Cave'), + Entrance('mt_coronet_summit_ne_cave', 'Coronet Summit NE Cave'), + Entrance('mt_coronet_summit_e_cave', 'Coronet Summit E Cave'), + Entrance('mt_coronet_summit_se_cave', 'Coronet Summit SE Cave'), + Entrance('mt_coronet_summit_w_cave', 'Coronet Summit W Cave'), + Entrance('mt_coronet_summit_nw_cave', 'Coronet Summit NW Cave'), + ]), + ]), + Category('victory_road', 'Victory Road', [ + Location('victory_road_1f', 'Victory Road 1F', [ + Entrance('victory_road_1f_nw_stairs', 'VR 1F NW Stairs'), + Entrance('victory_road_1f_w_stairs', 'VR 1F W Stairs'), + Entrance('victory_road_1f_sw_stairs', 'VR 1F SW Stairs'), + Entrance('victory_road_1f_ne_stairs', 'VR 1F NE Stairs'), + Entrance('victory_road_1f_e_stairs', 'VR 1F E Stairs'), + Entrance('victory_road_1f_se_stairs', 'VR 1F SE Stairs'), + Entrance('victory_road_1f_north_exit', 'VR 1F North Exit'), + Entrance('victory_road_1f_south_exit', 'VR 1F South Exit'), + ]), + Location('victory_road_b1f', 'Victory Road B1F', [ + Entrance('victory_road_b1f_nw_stairs', 'VR B1F NW Stairs'), + Entrance('victory_road_b1f_w_stairs', 'VR B1F W Stairs'), + Entrance('victory_road_b1f_sw_stairs', 'VR B1F SW Stairs'), + ]), + ]), + Category('iron_island', 'Iron Island', [ + Location('iron_island_exterior', 'Iron Island Exterior', [ + Entrance('iron_island_exterior_entrance', 'Iron Island Exterior Entrance'), + Entrance('iron_island_exterior_house', 'Iron Island Exterior House'), + Entrance('iron_island_exterior_exit', 'Iron Island Exterior Exit'), + ]), + Location('iron_island_1f', 'Iron Island 1F', [ + Entrance('iron_island_1f_w', 'Iron Island 1F W'), + Entrance('iron_island_1f_e', 'Iron Island 1F E'), + Entrance('iron_island_1f_exit', 'Iron Island 1F Exit'), + ]), + Location('iron_island_b1f', 'Iron Island B1F', [ + Entrance('iron_island_b1f_nw', 'Iron Island B1F NW'), + Entrance('iron_island_b1f_sw', 'Iron Island B1F SW'), + Entrance('iron_island_b1f_se', 'Iron Island B1F SE'), + ]), + Location('iron_island_b3f', 'Iron Island B3F', [ + Entrance('iron_island_b3f_nw', 'Iron Island B3F NW'), + Entrance('iron_island_b3f_n', 'Iron Island B3F N'), + Entrance('iron_island_b3f_se', 'Iron Island B3F SE'), + ]), + ]), + Category('poketch_gts_gate', 'Pokétch/GTS/Oreb. Gate', [ + Location('poketch_interior', 'Poketch Interior', [ + Entrance('poketch_interior_sw', 'Poketch Interior SW'), + Entrance('poketch_interior_se', 'Poketch Interior SE'), + Entrance('poketch_interior_up', 'Poketch Interior Up'), + ]), + Location('gts_1f', 'GTS 1F', [ + Entrance('gts_1f_warp_w', 'GTS 1F Warp W'), + Entrance('gts_1f_warp_e', 'GTS 1F Warp E'), + Entrance('gts_1f_exit', 'GTS 1F Exit'), + ]), + Location('oreburgh_gate', 'Oreburgh Gate', [ + Entrance('oreburgh_gate_stairs', 'Oreburgh Gate Stairs'), + Entrance('oreburgh_gate_east_exit', 'Oreburgh Gate East Exit'), + Entrance('oreburgh_gate_west_exit', 'Oreburgh Gate West Exit'), + ]), + ]), + Category('surf_hub', 'Surf Hub', [ + Location('lake_verity', 'Lake Verity', + [Entrance('lake_verity', 'Lake Verity')]), + Location('lake_valor', 'Lake Valor', + [Entrance('lake_valor', 'Lake Valor')]), + Location('lake_acuity', 'Lake Acuity', + [Entrance('lake_acuity', 'Lake Acuity')]), + Location('r221', 'Route 221', [ + Entrance('r221_house', 'R221 House'), + Entrance('r221_pal_park', 'R221 Pal Park'), + ]), + ]), +] diff --git a/links/db.py b/links/db.py index d1dd9472cd8ba124f46dfbe6891572f550147a55..267e071db76df2239c67e519c12fa2232fb4b790 100644 --- a/links/db.py +++ b/links/db.py @@ -13,11 +13,11 @@ class Db: self._cursor.execute("INSERT INTO link VALUES (?, ?, ?, ?, ?)", (link.entrance, link.destination, link.one_way, block, link.note)) - def get(self, locations=None): - if locations is None: + def get(self, entrances=None): + if entrances is None: self._cursor.execute("SELECT * FROM link") else: - args = [locations[0] for locations in locations] + args = [entrance.key for entrance in entrances] self._cursor.execute('SELECT * FROM link WHERE entrance IN ({seq}) OR destination IN ({seq})' .format(seq=','.join(['?']*len(args))), args*2) diff --git a/links/link.py b/links/link.py index 30c5ffb9964bb31eae941c6219fa049b2a436073..5d161b51385b3eff9f4e6865b32c23ef4f060312 100644 --- a/links/link.py +++ b/links/link.py @@ -24,10 +24,10 @@ class Link: def has_note(self): return self.note is not None - def other(self, key): - if key not in self: - logging.error('Key %s was not found in link %s', key, self) - if key == self.entrance: + def other(self, entrance): + if entrance not in self: + logging.error('Key %s was not found in link %s', entrance, self) + if entrance == self.entrance: return self.destination return self.entrance diff --git a/links/linkmanager.py b/links/linkmanager.py index 31fd4faff490064faa16699cfbf2a1a64cd8d463..5bcdf6afeb1296963706e1f904541f9db380c165 100644 --- a/links/linkmanager.py +++ b/links/linkmanager.py @@ -1,14 +1,14 @@ from links.db import Db from links.link import Link +from util.locations import Category class LinkManager: - def __init__(self, locations, entrances, database: Db): - self.locations = locations - self.entrances = entrances + def __init__(self, categories, database: Db): + self.categories = categories - self.all_locations = flatten_dict(self.entrances) - self.all_keys = {x[0] for x in self.all_locations} + self.all_locations = flatten_dict(self.categories) + self.all_keys = {x.key for x in self.all_locations} self._db = database def add_link(self, link: Link): @@ -34,6 +34,6 @@ class LinkManager: raise ValueError(f'{link.destination} not in the known locations.') -def flatten_dict(d): - sublists = [d[x] for x in d.keys()] - return {i for sub in sublists for i in sub} +def flatten_dict(d: [Category]): + entrances = [loc.entrances for sub in d for loc in sub.locations] + return {i for sub in entrances for i in sub} diff --git a/main.py b/main.py index 07c9a94fe897ffd971e0d5e8ba7a03aaf799343e..61dc520c18c61527b7cc6e22201d7f616d53e81d 100644 --- a/main.py +++ b/main.py @@ -2,10 +2,10 @@ import sys import logging from os.path import join -from PySide6.QtCore import QCoreApplication, Qt, QTimer +from PySide6.QtCore import QCoreApplication, Qt from PySide6.QtWidgets import QApplication -from data.platinum import LOCATIONS, ENTRANCES +from data.platinum import CATEGORIES, INITIAL_LOCATION from pokerandom import PokeRandom from links.db import Db from timer import connect_shift @@ -20,8 +20,7 @@ if __name__ == '__main__': QCoreApplication.setAttribute(Qt.AA_UseHighDpiPixmaps) app = QApplication() with Db(database) as db: - pokerandom = PokeRandom(locations=LOCATIONS, initial_location=LOCATIONS['cities'][0], - entrances=ENTRANCES, db=db) + pokerandom = PokeRandom(categories=CATEGORIES, initial_location=INITIAL_LOCATION, db=db) timer = connect_shift(app, pokerandom.connections.show_double_connections, pokerandom.connections.hide_double_connections) diff --git a/pokerandom.py b/pokerandom.py index d1f9c592cc7dad371f00abb783c201af3b9a3b8a..f5c192d18f00ff82f8de86fae50fb975519d7e3b 100644 --- a/pokerandom.py +++ b/pokerandom.py @@ -5,22 +5,24 @@ from PySide6.QtWidgets import QWidget, QVBoxLayout, QGridLayout import widgets from links.link import Link from links.linkmanager import LinkManager +from util.locations import get_entrances_of_category, get_name_of_key, get_category_of_entrance, \ + get_location_of_entrance, get_entrances_of_location class PokeRandom(QWidget): - def __init__(self, locations, initial_location, entrances, db): + def __init__(self, categories, initial_location, db): super().__init__() self.setWindowTitle("Pokémon Platinum Randomizer Tracker") - self.link_manager = LinkManager(locations, entrances, db) - self.current_location = initial_location[0] - self.entrances = entrances + self.link_manager = LinkManager(categories, db) + self.current_location = initial_location + self.entrances = categories self._highlighting_entrances = [] self.locations = widgets.LocationGrid( - locations, on_click=self.set_current_location, on_enter=self.show_connections, - on_leave=self.hide_connections, get_parent=self.get_location_of_entrance, max_rows=15 + categories, on_click=self.set_current_location, on_enter=self.show_connections, + on_leave=self.hide_connections, get_parent=self.get_category_of_entrance, max_rows=15 ) self.connections = widgets.ConnectionGrid( self.entrances, on_click=self.select_connection, on_ctrl_click=self._change_location_by_entrance, @@ -51,12 +53,12 @@ class PokeRandom(QWidget): super(PokeRandom, self).setVisible(visible) def set_current_location(self, location): - self.current_location = location - self.image.set_image(location) + self.current_location = location.key + self.image.set_image(self.current_location) self.redraw_location() def redraw_location(self): - links = self.link_manager.get_links(self.entrances[self.current_location]) + links = self.link_manager.get_links(self.get_entrances_of_category()) self.locations.change_location(self.current_location, links) self.connections.set_buttons(self.current_location, links) @@ -67,37 +69,39 @@ class PokeRandom(QWidget): self.link_manager.add_link(Link(entrance, destination, one_way, block, note)) self.redraw_location() + def get_name_of_location(self, key): + return get_name_of_key(self.entrances, key) + def get_location_of_entrance(self, key): - for category, entrances in self.entrances.items(): - if key in [entrance[0] for entrance in entrances]: - return category + return get_location_of_entrance(self.entrances, key) - def get_name_of_location(self, key): - all_entrances = [self.entrances[x] for x in self.entrances.keys()] - flattened = [i for sub in all_entrances for i in sub] - try: - return [x[1] for x in flattened if key == x[0]][0] - except IndexError: - logging.error('Could not find key %s, when I really expected it.', key) + def get_category_of_entrance(self, key): + return get_category_of_entrance(self.entrances, key) - def show_connection(self, key): - destination = self._get_destination(key) + def show_connection(self, entrance): + destination = self._get_destination(entrance.key) - self.locations.show_destination(self.get_location_of_entrance(destination)) + self.locations.show_destination(self.get_category_of_entrance(destination)) self.connections.show_destination(destination) - def hide_connection(self, key): - destination = self._get_destination(key) + def hide_connection(self, entrance): + destination = self._get_destination(entrance.key) self.locations.set_buttons() self.connections.hide_destination(destination) - def show_connections(self, key): - self._highlighting_entrances = self.link_manager.get_links(self.entrances[key]) + def show_connections(self, category): + key = category.key + self._highlighting_entrances = self.link_manager.get_links(self.get_entrances_of_category(key)) for link in self._highlighting_entrances: - if self.get_location_of_entrance(link.entrance) == key: + if self.get_category_of_entrance(link.entrance).key == key: self.connections.show_destination(link.destination) - if self.get_location_of_entrance(link.destination) == key: + + destination = self.get_category_of_entrance(link.destination) + if destination is None: + return + + if destination.key == key: self.connections.show_destination(link.entrance) def hide_connections(self, key): @@ -125,15 +129,16 @@ class PokeRandom(QWidget): if destination is None: return + category = self.get_category_of_entrance(destination) location = self.get_location_of_entrance(destination) - destinations_of_destination = self.link_manager.get_links(self.entrances[location]) + destinations_of_destination = self.link_manager.get_links(self.get_entrances_of_location(location.key)) for link in destinations_of_destination: loc = link.destination if self.get_location_of_entrance(link.entrance) == location else link.entrance - self.locations.show_second_destination(self.get_location_of_entrance(loc)) + self.locations.show_second_destination(self.get_category_of_entrance(loc)) def _change_location_by_entrance(self, key): - location = self.get_location_of_entrance(key) + location = self.get_category_of_entrance(key) if location: self.set_current_location(location) @@ -141,5 +146,13 @@ class PokeRandom(QWidget): link = self.link_manager.get_link(key) return link.other(key) if link is not None else None + def get_entrances_of_category(self, key=None): + if key is None: + key = self.current_location + return get_entrances_of_category(self.entrances, key) + + def get_entrances_of_location(self, key): + return get_entrances_of_location(self.entrances, key) + def show_help(self): self.help.show() diff --git a/test/location_test.py b/test/location_test.py new file mode 100644 index 0000000000000000000000000000000000000000..53a661fd8c5555a856134eaa0e8688020cd012f2 --- /dev/null +++ b/test/location_test.py @@ -0,0 +1,116 @@ +import unittest + +from util.locations import Category, Location, Entrance, get_entrances_of_category, get_name_of_key, \ + get_category_of_entrance, get_location_of_entrance, get_entrances_of_location + +simple_categories = [ + Category('test', 'name', [ + Location('loc1', 'location 1', [ + Entrance('e1', 'E1'), + Entrance('e2', 'E2') + ]), + ]), +] + +medium_categories = [ + Category('test', 'name', [ + Location('loc1', 'location 1', [ + Entrance('e1', 'E1'), + Entrance('e2', 'E2') + ]), + Location('loc2', 'location 2', [ + Entrance('e12', 'E12') + ]) + ]) +] + +complex_categories = [ + Category('test', 'name', [ + Location('loc1', 'location 1', [ + Entrance('e1', 'E1'), + Entrance('e2', 'E2') + ]), + ]), + Category('second', 'Second', [ + Location('abc', 'ABC', [ + Entrance('entrance_1', 'Entrance 1'), + Entrance('entrance_2', 'Entrance 2') + ]), + Location('def', 'DEF', [ + Entrance('entrance_12', 'Entrance 12') + ]) + ]), + Category('third', 'Second', [ + Location('ghi', 'GHI', [ + Entrance('entrance_4', 'Entrance 4') + ]), + ]) +] + + +class TestGetKeysOfCategory(unittest.TestCase): + def test_first_category(self): + expected = [ + Entrance('e1', 'E1'), + Entrance('e2', 'E2'), + Entrance('e12', 'E12'), + ] + self.assertEqual(expected, list(get_entrances_of_category(medium_categories, 'test'))) + + def test_complex_category(self): + expected = [ + Entrance('entrance_1', 'Entrance 1'), + Entrance('entrance_2', 'Entrance 2'), + Entrance('entrance_12', 'Entrance 12'), + ] + self.assertEqual(expected, list(get_entrances_of_category(complex_categories, 'second'))) + + +class TestGetKeysOfLocation(unittest.TestCase): + def test_first_location(self): + expected = [ + Entrance('e1', 'E1'), + Entrance('e2', 'E2'), + ] + self.assertEqual(expected, list(get_entrances_of_location(medium_categories, 'loc1'))) + + def test_middle_location(self): + expected = [ + Entrance('entrance_1', 'Entrance 1'), + Entrance('entrance_2', 'Entrance 2') + ] + self.assertEqual(expected, list(get_entrances_of_location(complex_categories, 'abc'))) + + +class TestGetNameOfKey(unittest.TestCase): + def test_get_name_of_first_key(self): + expected = 'E1' + self.assertEqual(expected, get_name_of_key(simple_categories, 'e1')) + + def test_get_name_of_later_key(self): + expected = 'Entrance 12' + self.assertEqual(expected, get_name_of_key(complex_categories, 'entrance_12')) + + +class TestGetCategoryOfEntrance(unittest.TestCase): + def test_get_category_of_first_key(self): + expected = simple_categories[0] + self.assertEqual(expected, get_category_of_entrance(simple_categories, 'e1')) + + def test_get_category_of_later_key(self): + expected = complex_categories[1] + self.assertEqual(expected, get_category_of_entrance(complex_categories, 'entrance_12')) + + +class TestGetLocationOfEntrance(unittest.TestCase): + def test_get_location_of_first_key(self): + expected = simple_categories[0].locations[0] + self.assertEqual(expected, get_location_of_entrance(simple_categories, 'e1')) + + def test_get_location_of_later_key(self): + expected = complex_categories[1].locations[1] + self.assertEqual(expected, get_location_of_entrance(complex_categories, 'entrance_12')) + + +if __name__ == '__main__': + unittest.main() diff --git a/util/button.py b/util/button.py index ad327556a0a8b45ba0131264faf8cd724f430d28..1d9b2196c2c7a1d3ded3d942a22dbf8d3c3410c0 100644 --- a/util/button.py +++ b/util/button.py @@ -7,29 +7,27 @@ from util.blocked import Blocked class EntranceButton(QPushButton): - def __init__(self, key, name, on_click, on_ctrl_click=None, on_enter=None, on_leave=None, link=None, - get_location_name=None): - super().__init__(name) - self.key = key + def __init__(self, entrance, on_click, on_ctrl_click=None, on_enter=None, on_leave=None, link=None, text=None): + super().__init__(text or entrance.name) + self.entrance = entrance self.link = link self.on_click = on_click self.on_ctrl_click = on_ctrl_click self.on_enter = on_enter self.on_leave = on_leave - self.get_location_name = get_location_name - self.clicked.connect(lambda: self.call(key)) + self.clicked.connect(lambda: self.call(entrance)) self.draw() def mousePressEvent(self, e: QMouseEvent) -> None: if e.modifiers() == Qt.ControlModifier and self.on_ctrl_click is not None: - return self.on_ctrl_click(self.link.other(self.key)) + return self.on_ctrl_click(self.link.other(self.entrance.key)) super().mousePressEvent(e) - def call(self, key): - self.on_leave(key) - self.on_click(key) + def call(self, entrance): + self.on_leave(entrance) + self.on_click(entrance) def draw(self, active=False, selected=False): if selected: @@ -44,7 +42,7 @@ class EntranceButton(QPushButton): elif self.link.has_note: self.change_color(colors.note) else: - self.change_color(colors.existing_link, tooltip=self.get_location_name(self.link.other(self.key))) + self.change_color(colors.existing_link, tooltip=self.link.other(self.entrance.key)) def draw_blocked(self): if self.link.dead_end: @@ -79,16 +77,15 @@ class EntranceButton(QPushButton): def enterEvent(self, event: QEnterEvent) -> None: if self.on_enter: - self.on_enter(self.key) + self.on_enter(self.entrance) def leaveEvent(self, event: QEvent) -> None: if self.on_leave: - self.on_leave(self.key) + self.on_leave(self.entrance) def __repr__(self): - return f"" + return f"" -def create_button(key, name, on_click, *, on_ctrl_click=None, on_enter=None, on_leave=None, link=None, - get_location_name=None): - return EntranceButton(key, name, on_click, on_ctrl_click, on_enter, on_leave, link, get_location_name) +def create_button(entrance, on_click, *, on_ctrl_click=None, on_enter=None, on_leave=None, link=None, text=None): + return EntranceButton(entrance, on_click, on_ctrl_click, on_enter, on_leave, link, text) diff --git a/util/locations.py b/util/locations.py new file mode 100644 index 0000000000000000000000000000000000000000..9de06fab32c1022c1847492db1f3083d0d66f351 --- /dev/null +++ b/util/locations.py @@ -0,0 +1,79 @@ +class Category: + """ + A group of locations that together forms 1 unit, for example 'Places of Interest'. These are not necessarily + logically linked, but are grouped together for visual reasons. + """ + + def __init__(self, key, name, locations): + self.key = key + self.name = name + self.locations = locations + + +class Location: + """ + A logically connected group of entrances. From each of these entrances, you can warp + to every other entrance in-game. + """ + + def __init__(self, key, name, entrances): + self.key = key + self.name = name + self.entrances = entrances + + def __eq__(self, other): + return (isinstance(other, Location) + and self.key == other.key and self.name == other.name) + + +class Entrance: + def __init__(self, key, name): + self.key = key + self.name = name + + def __eq__(self, other): + return (isinstance(other, Entrance) + and self.key == other.key and self.name == other.name) + + def __hash__(self): + return hash((self.key, self.name)) + + +def get_entrances_of_category(categories, key): + category = [x for x in categories if x.key == key][0] + return _get_entrances_of_locations(category.locations) + + +def get_entrances_of_location(categories, key): + for category in categories: + for location in category.locations: + if location.key == key: + return _get_entrances_of_locations([location]) + + +def get_name_of_key(categories, key): + for category in categories: + for location in category.locations: + for entrance in location.entrances: + if entrance.key == key: + return entrance.name + + +def get_category_of_entrance(categories, key): + for category in categories: + for location in category.locations: + if key in [e.key for e in location.entrances]: + return category + + +def get_location_of_entrance(categories, key): + for category in categories: + for location in category.locations: + if key in [e.key for e in location.entrances]: + return location + + +def _get_entrances_of_locations(locations): + for loc in locations: + for entrance in loc.entrances: + yield entrance diff --git a/widgets/connectiongrid.py b/widgets/connectiongrid.py index 2d35a2e5d98ac5b8fc1d18af7f896fddd163ae5d..268deba1aa10d42ff2cbde252d5d30ede5f341db 100644 --- a/widgets/connectiongrid.py +++ b/widgets/connectiongrid.py @@ -3,6 +3,7 @@ from PySide6.QtWidgets import QGridLayout, QGroupBox, QApplication from util.button import create_button, EntranceButton from util.gridutils import compute_cols, divide_widgets_per_column, create_grid +from util.locations import get_entrances_of_category from util.widget import Widget @@ -65,28 +66,29 @@ class ConnectionGrid(QGroupBox): self.buttons.addWidget(widget.widget, row, column) def _create_widgets(self, location, links): - elements = self.elements[location] - for key, name in elements: - link = get_link_of_button(key, links) - name = self._create_name(key, name, link) - yield Widget(key, create_button(key, name, self.on_click, on_ctrl_click=self.on_ctrl_click, - on_enter=self.on_enter, on_leave=self.on_leave, link=link, - get_location_name=self.get_location_name)) - - def _create_name(self, key, name, link): + entrances = get_entrances_of_category(self.elements, location) + for entrance in entrances: + link = get_link_of_button(entrance.key, links) + name = self._create_name(entrance, link) + yield Widget(entrance.key, + create_button(entrance, self.on_click, on_ctrl_click=self.on_ctrl_click, + on_enter=self.on_enter, on_leave=self.on_leave, link=link, + text=name)) + + def _create_name(self, entrance, link): if not link or link.blocked: - return name + return entrance.name if link.has_note: - return f'{name} — {link.note}' + return f'{entrance.name} — {link.note}' - return f'{name} -> {self.get_location_name(link.other(key))}' + return f'{entrance.name} -> {self.get_location_name(link.other(entrance.key))}' def show_double_connections(self): w = QApplication.widgetAt(QCursor.pos(self.screen())) if type(w) is EntranceButton: - if not self.double_information == w.key: - self.double_information = w.key + if not self.double_information == w.entrance.key: + self.double_information = w.entrance.key self.show_double(self.double_information) else: self.double_information = None diff --git a/widgets/locationgrid.py b/widgets/locationgrid.py index 6a4ad743e0c66ab60b31171cf73838b874b569c0..c4b169c8f28bad4af2d3e2b8eecbe4e472bee746 100644 --- a/widgets/locationgrid.py +++ b/widgets/locationgrid.py @@ -10,7 +10,7 @@ class LocationGrid(QGroupBox): def __init__(self, elements, on_click, on_enter, on_leave, get_parent, max_rows): super().__init__() - self.elements = elements + self.categories = elements self.on_click = on_click self.on_enter = on_enter self.on_leave = on_leave @@ -31,18 +31,17 @@ class LocationGrid(QGroupBox): def set_buttons(self): self._clear_colors() - locations = [self.get_parent(link.entrance) - if self.get_parent(link.destination) == self.location else self.get_parent(link.destination) - for link in self.links] + categories = self._get_linked_categories() + categories = [category.key for category in categories if category] for widget in self.widgets: - if widget.key in locations: + if widget.key in categories: widget.widget.setPalette(colors.existing_link) - def show_destination(self, key): - if key is None: + def show_destination(self, category): + if category is None: return - widgets_to_change = [w for w in self.widgets if w.key == key] + widgets_to_change = [w for w in self.widgets if w.key == category.key] for widget in widgets_to_change: widget.widget.setPalette(colors.linked) @@ -63,9 +62,15 @@ class LocationGrid(QGroupBox): widget.widget.setPalette(colors.default) def _create_widgets(self): - for category in self.elements.keys(): - for location_key, location_name in self.elements[category]: - yield Widget(location_key, - create_button(location_key, location_name, self.on_click, - on_enter=self.on_enter, on_leave=self.on_leave)) - + for category in self.categories: + yield Widget(category.key, + create_button(category, self.on_click, + on_enter=self.on_enter, on_leave=self.on_leave)) + + def _get_linked_categories(self): + for link in self.links: + dest_parent = self.get_parent(link.destination) + if dest_parent and dest_parent.key == self.location: + yield self.get_parent(link.entrance) + else: + yield self.get_parent(link.destination) diff --git a/widgets/status.py b/widgets/status.py index 6d95afddf869d1e9b3ee7c6e20cc74e3efcda95e..523559bcd91e13b452fa3e769caff34c0e5f8c04 100644 --- a/widgets/status.py +++ b/widgets/status.py @@ -23,13 +23,13 @@ class Status(QGroupBox): self.layout.addWidget(self.one_way_widget, 1, 0) self.layout.addWidget(self.note, 0, 1) - def select_item(self, key): + def select_item(self, entrance): if self.entrance is None: - self.entrance = key - elif self.entrance == key: + self.entrance = entrance + elif self.entrance == entrance: return else: - self.save(destination=key, one_way=self.one_way) + self.save(destination=entrance, one_way=self.one_way) def cancel(self): self.entrance = None @@ -56,7 +56,8 @@ class Status(QGroupBox): self.note.clear() def save(self, *, destination=None, one_way=False, block=None, note=None): - self.add_link_callback(self.entrance, destination, one_way=one_way, block=block, note=note) + destination = destination.key if destination else None + self.add_link_callback(self.entrance.key, destination, one_way=one_way, block=block, note=note) self.cancel() @property @@ -81,5 +82,5 @@ class Status(QGroupBox): if value is None: self.entrance_widget.setText('Select a location') else: - self.entrance_widget.setText(f"Selected '{self.get_name_of_location(value)}'") + self.entrance_widget.setText(f"Selected '{value.name}'") self.selected_callback(value, selected=value is not None)