Compare commits
15 Commits
master
...
plan_gener
| Author | SHA1 | Date |
|---|---|---|
|
|
b0149dbcf0 | 1 year ago |
|
|
481e3cb9d2 | 1 year ago |
|
|
28913a5e5e | 1 year ago |
|
|
c955a02e33 | 1 year ago |
|
|
b70447246d | 1 year ago |
|
|
75b18649f2 | 1 year ago |
|
|
a4ee4e6810 | 1 year ago |
|
|
5ebbad4ba7 | 1 year ago |
|
|
6f5bfa1d47 | 1 year ago |
|
|
8d61be9c4f | 1 year ago |
|
|
1dab6466e8 | 1 year ago |
|
|
4746debb95 | 1 year ago |
|
|
7bcff6fc16 | 1 year ago |
|
|
b3cca80b73 | 1 year ago |
|
|
a2efb738a8 | 1 year ago |
23 changed files with 2486 additions and 121 deletions
@ -0,0 +1,458 @@ |
|||
from types import MethodType |
|||
import networkx as nx |
|||
from networkx import Graph |
|||
|
|||
from routes.game_world import RouteStage |
|||
from routes.pokemon_game_desc import PokemonGameDesc |
|||
|
|||
NEW_BARK_TOWN = 'New Bark Town' |
|||
CHERRYGROVE_CITY = 'Cherrygrove City' |
|||
VIOLET_CITY = 'Violet City' |
|||
SPROUT_TOWER = 'Sprout Tower' |
|||
RUINS_OF_ALPH = 'Ruins of Alph' |
|||
UNION_CAVE = 'Union Cave' |
|||
AZALEA_TOWN = 'Azalea Town' |
|||
SLOWPOKE_WELL = 'Slowpoke Well' |
|||
ILEX_FOREST = 'Ilex Forest' |
|||
GOLDENROD_CITY = 'Goldenrod City' |
|||
NATIONAL_PARK = 'National Park' |
|||
ECRUTEAK_CITY = 'Ecruteak City' |
|||
MOOMOO_FARM = 'MooMoo Farm' |
|||
OLIVINE_CITY = 'Olivine City' |
|||
CIANWOOD_CITY = 'Cianwood City' |
|||
MAHOGANY_TOWN = 'Mahogany Town' |
|||
LAKE_OF_RAGE = 'Lake of Rage' |
|||
TEAM_ROCKET_HQ = 'Team Rocket H.Q.' |
|||
ICE_PATH = 'Ice Path' |
|||
BLACKTHORN_CITY = 'Blackthorn City' |
|||
MT_MORTAR = 'Mt. Mortar' |
|||
TIN_TOWER = 'Tin Tower' |
|||
WHIRL_ISLANDS = 'Whirl Islands' |
|||
DARK_CAVE = 'Dark Cave' |
|||
VICTORY_ROAD = 'Victory Road' |
|||
INDIGO_PLATEAU = 'Indigo Plateau' |
|||
SS_AQUA = 'S.S. Aqua' |
|||
VERMILION_CITY = 'Vermilion City' |
|||
SAFFRON_CITY = 'Saffron City' |
|||
LAVENDER_TOWN = 'Lavender Town' |
|||
ROCK_TUNNEL = 'Rock Tunnel' |
|||
CERULEAN_CITY = 'Cerulean City' |
|||
CELADON_CITY = 'Celadon City' |
|||
FUCHSIA_CITY = 'Fuchsia City' |
|||
DIGLETTS_CAVE = "Diglett's Cave" |
|||
PEWTER_CITY = 'Pewter City' |
|||
MT_MOON = 'Mt. Moon' |
|||
VIRIDIAN_CITY = 'Viridian City' |
|||
PALLET_TOWN = 'Pallet Town' |
|||
CINNABAR_ISLAND = 'Cinnabar Island' |
|||
MT_SILVER = 'Mt. Silver' |
|||
SAFARI_ZONE = 'Safari Zone' |
|||
TOHJO_FALLS = 'Tohjo Falls' |
|||
POWER_PLANT = 'Power Plant' |
|||
LEAGUE_RECEPTION_GATE = 'League Reception Gate' |
|||
|
|||
CUT = 'Cut' |
|||
SURF = 'Surf' |
|||
FLASH = 'Flash' |
|||
STRENGTH = 'Strength' |
|||
ROCK_SMASH = 'Rock Smash' |
|||
WHIRLPOOL = 'Whirlpool' |
|||
WATERFALL = 'Waterfall' |
|||
|
|||
ZEPHYR_BADGE = 'Zephyr Badge' |
|||
HIVE_BADGE = 'Hive Badge' |
|||
PLAIN_BADGE = 'Plain Badge' |
|||
FOG_BADGE = 'Fog Badge' |
|||
STORM_BADGE = 'Storm Badge' |
|||
MINERAL_BADGE = 'Mineral Badge' |
|||
GLACIER_BADGE = 'Glacier Badge' |
|||
RISING_BADGE = 'Rising Badge' |
|||
|
|||
BOULDER_BADGE = 'Boulder Badge' |
|||
CASCADE_BADGE = 'Cascade Badge' |
|||
THUNDER_BADGE = 'Thunder Badge' |
|||
RAINBOW_BADGE = 'Rainbow Badge' |
|||
MARSH_BADGE = 'Marsh Badge' |
|||
SOUL_BADGE = 'Soul Badge' |
|||
VOLCANO_BADGE = 'Volcano Badge' |
|||
EARTH_BADGE = 'Earth Badge' |
|||
|
|||
SQUIRTBOTTLE = 'Squirt bottle' |
|||
MEDICINE = 'Medicine' |
|||
CATCH_RED_GYRADOS = 'Catch Red Gryados' |
|||
ROCKET_DEAFEATED = 'Rocket Defeated' |
|||
PKMN_WING = 'Gold Silver Wing' |
|||
JOHTO_CHAMPION = 'Johto Champion' |
|||
S_S_TICKET = 'S.S. Ticket' |
|||
WOKE_SNORLAX = 'Woke Snorlax' |
|||
EXPN_CARD = 'Expn card' |
|||
POWER_RESTORED = 'Power restored' |
|||
MACHINE_PART = 'Machine Part' |
|||
CLEFAIRY_DOLL = 'Clefairy Doll' |
|||
RAIL_PASS = 'Rail Pass' |
|||
MISTY_FOUND = 'Misty Found' |
|||
FLUTE_CHANNEL = 'Flute Channel' |
|||
ROUTE_28_UNLOCKED = 'Rotue 28 Unlocked' |
|||
POWER_PLANT_VISITED = 'POWER_PLANT_VISITED' |
|||
|
|||
FLY = 'Fly' |
|||
FLY_OUT_OF_BATTLE = 'Fly out of battle' |
|||
|
|||
def get_gold_silver_desc() -> PokemonGameDesc: |
|||
desc: PokemonGameDesc = PokemonGameDesc() |
|||
#desc.graph = get_gold_silver_route() |
|||
desc.game_name = "Crystal" |
|||
desc.towns_and_cities = [NEW_BARK_TOWN, CHERRYGROVE_CITY, VIOLET_CITY, AZALEA_TOWN, GOLDENROD_CITY, ECRUTEAK_CITY, OLIVINE_CITY, CIANWOOD_CITY, MAHOGANY_TOWN, BLACKTHORN_CITY] |
|||
#desc.badges = [ZEPHYR_BADGE, HIVE_BADGE, PLAIN_BADGE, FOG_BADGE, STORM_BADGE, MINERAL_BADGE, GLACIER_BADGE, RISING_BADGE, BOULDER_BADGE, CASCADE_BADGE, THUNDER_BADGE, RAINBOW_BADGE, MARSH_BADGE, SOUL_BADGE, VOLCANO_BADGE, EARTH_BADGE] |
|||
desc.hms = [CUT, SURF, FLASH, STRENGTH, FLY, WATERFALL, WHIRLPOOL] |
|||
desc.additional_goals = [WOKE_SNORLAX] |
|||
#desc.starting_town = NEW_BARK_TOWN |
|||
#desc.end_goal = MT_SILVER |
|||
#desc.must_visit = set([MT_MOON]) |
|||
desc.games_covered = ["Gold", "Silver", "Crystal"] |
|||
desc.file_name = "gold_silver_crystal_problem.pddl" |
|||
|
|||
desc.one_way_routes.append("Route_29 -> Route_46") |
|||
|
|||
stage: RouteStage = RouteStage( |
|||
"Johto", |
|||
get_johto_route(), |
|||
NEW_BARK_TOWN, |
|||
INDIGO_PLATEAU, |
|||
[ZEPHYR_BADGE, HIVE_BADGE, PLAIN_BADGE, FOG_BADGE, STORM_BADGE, MINERAL_BADGE, GLACIER_BADGE, RISING_BADGE], |
|||
set(), |
|||
[NEW_BARK_TOWN, CHERRYGROVE_CITY, VIOLET_CITY, AZALEA_TOWN, GOLDENROD_CITY, ECRUTEAK_CITY, OLIVINE_CITY, CIANWOOD_CITY, MAHOGANY_TOWN, BLACKTHORN_CITY] |
|||
) |
|||
desc.stages.append(stage) |
|||
|
|||
kanto_stage: RouteStage = RouteStage( |
|||
"Kanto", |
|||
nx.compose(get_johto_route(), get_kanto_route()), |
|||
NEW_BARK_TOWN, |
|||
MT_SILVER, |
|||
[BOULDER_BADGE, CASCADE_BADGE, THUNDER_BADGE, RAINBOW_BADGE, MARSH_BADGE, SOUL_BADGE, VOLCANO_BADGE, EARTH_BADGE], |
|||
set(), |
|||
[NEW_BARK_TOWN, CHERRYGROVE_CITY, VIOLET_CITY, AZALEA_TOWN, GOLDENROD_CITY, ECRUTEAK_CITY, OLIVINE_CITY, CIANWOOD_CITY, MAHOGANY_TOWN, BLACKTHORN_CITY, PALLET_TOWN, VIRIDIAN_CITY, PEWTER_CITY, CERULEAN_CITY, SAFFRON_CITY, CELADON_CITY, VERMILION_CITY, FUCHSIA_CITY, CINNABAR_ISLAND] |
|||
) |
|||
desc.stages.append(kanto_stage) |
|||
|
|||
return desc |
|||
|
|||
def get_johto_desc(): |
|||
desc: PokemonGameDesc = PokemonGameDesc() |
|||
#desc.graph = get_gold_silver_route() |
|||
desc.game_name = "Gold_Silver_Johto" |
|||
desc.towns_and_cities = [NEW_BARK_TOWN, CHERRYGROVE_CITY, VIOLET_CITY, AZALEA_TOWN, GOLDENROD_CITY, ECRUTEAK_CITY, OLIVINE_CITY, CIANWOOD_CITY, MAHOGANY_TOWN, BLACKTHORN_CITY] |
|||
#desc.badges = [ZEPHYR_BADGE, HIVE_BADGE, PLAIN_BADGE, FOG_BADGE, STORM_BADGE, MINERAL_BADGE, GLACIER_BADGE, RISING_BADGE] |
|||
desc.hms = [CUT, SURF, FLASH, STRENGTH, FLY, WATERFALL, WHIRLPOOL] |
|||
desc.additional_goals = [] |
|||
#desc.starting_town = NEW_BARK_TOWN |
|||
#desc.end_goal = INDIGO_PLATEAU |
|||
desc.must_visit = set() |
|||
desc.games_covered = ["Gold", "Silver", "Crystal"] |
|||
desc.file_name = "gold_silver_crystal_problem.pddl" |
|||
desc.one_way_routes.append("Route_29 -> Route_46") |
|||
|
|||
return desc |
|||
|
|||
def get_johto_route(): |
|||
G = nx.Graph() |
|||
for i in range(29,46): |
|||
G.add_node(f'Route {i}', node_type='route') |
|||
|
|||
G.add_node(f'Route 26', node_type='route') |
|||
G.add_node(f'Route 27', node_type='route') |
|||
G.add_node(f'Route 23', node_type='route') |
|||
|
|||
G.add_node(NEW_BARK_TOWN, node_type='location') |
|||
G.add_node(CHERRYGROVE_CITY, node_type='location') |
|||
G.add_node(VIOLET_CITY, node_type='location') |
|||
G.add_node(SPROUT_TOWER, node_type='location') |
|||
G.add_node(RUINS_OF_ALPH, node_type='location') |
|||
G.add_node(UNION_CAVE, node_type='location') |
|||
G.add_node(AZALEA_TOWN, node_type='location') |
|||
G.add_node(SLOWPOKE_WELL, node_type='location') |
|||
G.add_node(ILEX_FOREST, node_type='location') |
|||
G.add_node(GOLDENROD_CITY, node_type='location') |
|||
G.add_node(NATIONAL_PARK, node_type='location') |
|||
G.add_node(ECRUTEAK_CITY, node_type='location') |
|||
G.add_node(MOOMOO_FARM, node_type='location') |
|||
G.add_node(OLIVINE_CITY, node_type='location') |
|||
G.add_node(CIANWOOD_CITY, node_type='location') |
|||
G.add_node(MAHOGANY_TOWN, node_type='location') |
|||
G.add_node(LAKE_OF_RAGE, node_type='location') |
|||
G.add_node(TEAM_ROCKET_HQ, node_type='location') |
|||
G.add_node(ICE_PATH, node_type='location') |
|||
G.add_node(BLACKTHORN_CITY, node_type='location') |
|||
G.add_node(MT_MORTAR, node_type='location') |
|||
G.add_node(TIN_TOWER, node_type='location') |
|||
G.add_node(WHIRL_ISLANDS, node_type='location') |
|||
G.add_node(DARK_CAVE, node_type='location') |
|||
G.add_node(VICTORY_ROAD, node_type='location') |
|||
G.add_node(INDIGO_PLATEAU, node_type='location') |
|||
G.add_node(SAFARI_ZONE, node_type='location') |
|||
G.add_node(TOHJO_FALLS, node_type='location') |
|||
G.add_node(LEAGUE_RECEPTION_GATE, node_type='location') |
|||
|
|||
G.add_edge(NEW_BARK_TOWN, 'Route 29', condition=None) |
|||
G.add_edge(CHERRYGROVE_CITY, 'Route 29', condition=None) |
|||
G.add_edge(CHERRYGROVE_CITY, 'Route 30', condition=None) |
|||
G.add_edge('Route 31', 'Route 30', condition=None) |
|||
G.add_edge('Route 30', DARK_CAVE, condition=None) |
|||
G.add_edge('Route 31', VIOLET_CITY, condition=None) |
|||
G.add_edge(VIOLET_CITY, 'Route 32', condition=None) |
|||
G.add_edge(VIOLET_CITY, SPROUT_TOWER, condition=None) |
|||
G.add_edge('Route 32', RUINS_OF_ALPH, condition=None) |
|||
G.add_edge('Route 32', UNION_CAVE, condition=None) |
|||
G.add_edge(UNION_CAVE, 'Route 33', condition=None) |
|||
G.add_edge(UNION_CAVE, RUINS_OF_ALPH, condition=None) |
|||
G.add_edge('Route 33', AZALEA_TOWN, condition=None) |
|||
G.add_edge('Route 33', SLOWPOKE_WELL, condition=None) |
|||
G.add_edge(AZALEA_TOWN, ILEX_FOREST, condition=None) |
|||
G.add_edge(ILEX_FOREST, 'Route 34', condition=None) |
|||
G.add_edge(GOLDENROD_CITY, 'Route 34', condition=None) |
|||
G.add_edge(GOLDENROD_CITY, 'Route 35', condition=None) |
|||
G.add_edge(NATIONAL_PARK, 'Route 35', condition=None) |
|||
G.add_edge(NATIONAL_PARK, 'Route 36', condition=[SQUIRTBOTTLE]) |
|||
G.add_edge(VIOLET_CITY, 'Route 36', condition=None) |
|||
G.add_edge('Route 37', 'Route 36', condition=[SQUIRTBOTTLE]) |
|||
G.add_edge('Route 37', ECRUTEAK_CITY, condition=None) |
|||
G.add_edge('Route 38', ECRUTEAK_CITY, condition=None) |
|||
G.add_edge('Route 38', 'Route 39', condition=None) |
|||
G.add_edge('Route 39', OLIVINE_CITY, condition=None) |
|||
G.add_edge('Route 40', OLIVINE_CITY, condition=[SURF]) |
|||
G.add_edge(OLIVINE_CITY, SS_AQUA, condition=[S_S_TICKET]) |
|||
G.add_edge('Route 40', 'Route 41', condition=[SURF]) |
|||
G.add_edge('Route 40', WHIRL_ISLANDS, condition=[SURF, WHIRLPOOL]) |
|||
G.add_edge('Route 41', WHIRL_ISLANDS, condition=[SURF, WHIRLPOOL]) |
|||
G.add_edge('Route 41', CIANWOOD_CITY, condition=[SURF]) |
|||
G.add_edge('Route 47', CIANWOOD_CITY, condition=None) |
|||
G.add_edge('Route 47', 'Route 48', condition=None) |
|||
G.add_edge('Route 47', SAFARI_ZONE, condition=None) |
|||
G.add_edge('Route 42', ECRUTEAK_CITY, condition=None) |
|||
G.add_edge(ECRUTEAK_CITY, TIN_TOWER, condition=None) |
|||
G.add_edge('Route 42', MT_MORTAR, condition=[SURF, WATERFALL]) |
|||
G.add_edge('Route 42', MAHOGANY_TOWN, condition=[SURF]) |
|||
G.add_edge('Route 43', MAHOGANY_TOWN, condition=None) |
|||
G.add_edge('Route 43', LAKE_OF_RAGE, condition=None) |
|||
G.add_edge('Route 44', MAHOGANY_TOWN, condition=[ROCKET_DEAFEATED]) |
|||
G.add_edge(TEAM_ROCKET_HQ, MAHOGANY_TOWN, condition=[CATCH_RED_GYRADOS]) |
|||
G.add_edge('Route 44', ICE_PATH, condition=[STRENGTH]) |
|||
G.add_edge(BLACKTHORN_CITY, ICE_PATH, condition=[STRENGTH]) |
|||
G.add_edge('Route 45', BLACKTHORN_CITY, condition=None) |
|||
G.add_edge('Route 45', DARK_CAVE, condition=[SURF]) |
|||
G.add_edge('Route 45', 'Route 46', condition=None) |
|||
G.add_edge('Route 46', 'Route 29', condition=None) |
|||
G.add_edge('Route 46', DARK_CAVE, condition=[ROCK_SMASH]) |
|||
G.add_edge('Route 27', NEW_BARK_TOWN, condition=[SURF, WATERFALL, WHIRLPOOL]) |
|||
G.add_edge('Route 26', 'Route 27', condition=None) |
|||
G.add_edge('Route 27', TOHJO_FALLS, condition=None) |
|||
|
|||
G.add_edge(LEAGUE_RECEPTION_GATE, 'Route 26', condition=None) |
|||
#G.add_edge(LEAGUE_RECEPTION_GATE, 'Route 28', condition=[ROUTE_28_UNLOCKED]) |
|||
#G.add_edge(LEAGUE_RECEPTION_GATE, 'Route 22', condition=[WOKE_SNORLAX]) |
|||
G.add_edge(LEAGUE_RECEPTION_GATE, 'Route 23', condition=None) |
|||
|
|||
#G.add_edge('Route 28', MT_SILVER, condition=None) |
|||
G.add_edge('Route 23', VICTORY_ROAD, condition=[ZEPHYR_BADGE, HIVE_BADGE, PLAIN_BADGE, FOG_BADGE, STORM_BADGE, MINERAL_BADGE, GLACIER_BADGE, RISING_BADGE]) |
|||
G.add_edge(VICTORY_ROAD, INDIGO_PLATEAU, condition=None) |
|||
|
|||
#G.add_edge(SS_AQUA, VERMILION_CITY, condition=None) |
|||
|
|||
G.nodes[NEW_BARK_TOWN]['grants_conditions'] = [ |
|||
{'condition': S_S_TICKET, 'required_conditions': [JOHTO_CHAMPION]} |
|||
] |
|||
G.nodes[VIOLET_CITY]['grants_conditions'] = [ |
|||
{'condition': ZEPHYR_BADGE, 'required_conditions': []} |
|||
] |
|||
G.nodes[SPROUT_TOWER]['grants_conditions'] = [ |
|||
{'condition': FLASH, 'required_conditions': []} |
|||
] |
|||
G.nodes[AZALEA_TOWN]['grants_conditions'] = [ |
|||
{'condition': HIVE_BADGE, 'required_conditions': []} |
|||
] |
|||
G.nodes[ILEX_FOREST]['grants_conditions'] = [ |
|||
{'condition': CUT, 'required_conditions': []} |
|||
] |
|||
G.nodes[GOLDENROD_CITY]['grants_conditions'] = [ |
|||
{'condition': PLAIN_BADGE, 'required_conditions': []}, |
|||
{'condition': SQUIRTBOTTLE, 'required_conditions': []}, |
|||
{'condition': PKMN_WING, 'required_conditions': [GLACIER_BADGE]}, |
|||
] |
|||
G.nodes[ECRUTEAK_CITY]['grants_conditions'] = [ |
|||
{'condition': SURF, 'required_conditions': []}, |
|||
{'condition': FOG_BADGE, 'required_conditions': []} |
|||
] |
|||
G.nodes['Route 36']['grants_conditions'] = [ |
|||
{'condition': ROCK_SMASH, 'required_conditions': [SQUIRTBOTTLE]} |
|||
] |
|||
G.nodes[OLIVINE_CITY]['grants_conditions'] = [ |
|||
{'condition': MINERAL_BADGE, 'required_conditions': [MEDICINE]}, |
|||
{'condition': STRENGTH, 'required_conditions': []}, |
|||
] |
|||
G.nodes[CIANWOOD_CITY]['grants_conditions'] = [ |
|||
{'condition': STORM_BADGE, 'required_conditions': []}, |
|||
{'condition': MEDICINE, 'required_conditions': []}, |
|||
{'condition': FLY, 'required_conditions': [STORM_BADGE]}, |
|||
{'condition': FLY_OUT_OF_BATTLE, 'required_conditions': [STORM_BADGE]}, |
|||
] |
|||
G.nodes[MAHOGANY_TOWN]['grants_conditions'] = [ |
|||
{'condition': GLACIER_BADGE, 'required_conditions': [ROCKET_DEAFEATED]} |
|||
] |
|||
G.nodes[TEAM_ROCKET_HQ]['grants_conditions'] = [ |
|||
{'condition': ROCKET_DEAFEATED, 'required_conditions': []}, |
|||
{'condition': WHIRLPOOL, 'required_conditions': []} |
|||
] |
|||
G.nodes[LAKE_OF_RAGE]['grants_conditions'] = [ |
|||
{'condition': CATCH_RED_GYRADOS, 'required_conditions': []} |
|||
] |
|||
G.nodes[ICE_PATH]['grants_conditions'] = [ |
|||
{'condition': WATERFALL, 'required_conditions': []} |
|||
] |
|||
G.nodes[BLACKTHORN_CITY]['grants_conditions'] = [ |
|||
{'condition': RISING_BADGE, 'required_conditions': []} |
|||
] |
|||
G.nodes[INDIGO_PLATEAU]['grants_conditions'] = [ |
|||
{'condition': JOHTO_CHAMPION, 'required_conditions': []} |
|||
] |
|||
|
|||
return G |
|||
|
|||
def get_kanto_route(): |
|||
G = nx.Graph() |
|||
|
|||
for i in range(1,23): |
|||
G.add_node(f'Route {i}', node_type='route') |
|||
|
|||
G.add_node(SS_AQUA, node_type='location') |
|||
G.add_node(VERMILION_CITY, node_type='location') |
|||
G.add_node(SAFFRON_CITY, node_type='location') |
|||
G.add_node(LAVENDER_TOWN, node_type='location') |
|||
G.add_node(ROCK_TUNNEL, node_type='location') |
|||
G.add_node(CERULEAN_CITY, node_type='location') |
|||
G.add_node(CELADON_CITY, node_type='location') |
|||
G.add_node(FUCHSIA_CITY, node_type='location') |
|||
G.add_node(DIGLETTS_CAVE, node_type='location') |
|||
G.add_node(PEWTER_CITY, node_type='location') |
|||
G.add_node(MT_MOON, node_type='location') |
|||
G.add_node(VIRIDIAN_CITY, node_type='location') |
|||
G.add_node(PALLET_TOWN, node_type='location') |
|||
G.add_node(CINNABAR_ISLAND, node_type='location') |
|||
G.add_node(MT_SILVER, node_type='location') |
|||
G.add_node(POWER_PLANT, node_type='location') |
|||
|
|||
G.add_edge(LEAGUE_RECEPTION_GATE, 'Route 28', condition=[ROUTE_28_UNLOCKED]) |
|||
G.add_edge(LEAGUE_RECEPTION_GATE, 'Route 22', condition=[WOKE_SNORLAX]) |
|||
G.add_edge(LEAGUE_RECEPTION_GATE, 'Route 23', condition=None) |
|||
|
|||
G.add_edge('Route 28', MT_SILVER, condition=None) |
|||
G.add_edge('Route 23', VICTORY_ROAD, condition=[ZEPHYR_BADGE, HIVE_BADGE, PLAIN_BADGE, FOG_BADGE, STORM_BADGE, MINERAL_BADGE, GLACIER_BADGE, RISING_BADGE]) |
|||
|
|||
G.add_edge(SS_AQUA, VERMILION_CITY, condition=None) |
|||
G.add_edge(SAFFRON_CITY, GOLDENROD_CITY, condition=[POWER_RESTORED, RAIL_PASS]) |
|||
G.add_edge(DIGLETTS_CAVE, 'Route 11', condition=[WOKE_SNORLAX]) |
|||
|
|||
G.add_edge(PALLET_TOWN, 'Route 1', condition=None) |
|||
G.add_edge(PALLET_TOWN, 'Route 21', condition=[SURF]) |
|||
G.add_edge('Route 1', VIRIDIAN_CITY, condition=None) |
|||
G.add_edge(VIRIDIAN_CITY, 'Route 2', condition=None) |
|||
G.add_edge('Route 2', 'Viridian Forest', condition=None) |
|||
G.add_edge('Route 2', 'Route 3', condition=[CUT]) |
|||
G.add_edge('Viridian Forest', PEWTER_CITY, condition=None) |
|||
G.add_edge(PEWTER_CITY, 'Route 3', condition=None) |
|||
G.add_edge('Route 3', MT_MOON, condition=None) |
|||
G.add_edge(MT_MOON, 'Route 4', condition=None) |
|||
G.add_edge('Route 4', CERULEAN_CITY, condition=None) |
|||
G.add_edge(CERULEAN_CITY, 'Route 24', condition=None) |
|||
G.add_edge(CERULEAN_CITY, 'Route 9', condition=[CUT]) |
|||
G.add_edge(CERULEAN_CITY, 'Route 5', condition=None) |
|||
G.add_edge('Route 5', SAFFRON_CITY, condition=None) |
|||
G.add_edge(SAFFRON_CITY, 'Route 6', condition=None) |
|||
G.add_edge(SAFFRON_CITY, 'Route 7', condition=None) |
|||
G.add_edge(SAFFRON_CITY, 'Route 8', condition=None) |
|||
G.add_edge('Route 6', VERMILION_CITY, condition=None) |
|||
G.add_edge(VERMILION_CITY, 'Route 11', condition=None) |
|||
G.add_edge('Route 11', 'Route 12', condition=None) |
|||
G.add_edge('Route 11', DIGLETTS_CAVE, condition=None) |
|||
G.add_edge('Route 2', DIGLETTS_CAVE, condition=[CUT]) |
|||
G.add_edge('Route 12', 'Route 13', condition=None) |
|||
G.add_edge('Route 12', LAVENDER_TOWN, condition=None) |
|||
G.add_edge('Route 7', LAVENDER_TOWN, condition=None) |
|||
G.add_edge(LAVENDER_TOWN, 'Route 10', condition=None) |
|||
G.add_edge('Route 9', ROCK_TUNNEL, condition=[FLASH]) |
|||
G.add_edge('Route 10', ROCK_TUNNEL, condition=[FLASH]) |
|||
G.add_edge(CELADON_CITY, 'Route 8', condition=None) |
|||
G.add_edge(CELADON_CITY, 'Route 16', condition=None) |
|||
G.add_edge('Route 16', 'Route 17', condition=None) |
|||
G.add_edge('Route 17', 'Route 18', condition=None) |
|||
G.add_edge('Route 18', FUCHSIA_CITY, condition=None) |
|||
G.add_edge(FUCHSIA_CITY,'Route 19', condition=None) |
|||
G.add_edge(FUCHSIA_CITY,'Route 15', condition=None) |
|||
G.add_edge('Route 19', 'Seafoam Islands', condition=[SURF]) |
|||
G.add_edge('Seafoam Islands', 'Route 20', condition=[SURF]) |
|||
G.add_edge('Route 20', CINNABAR_ISLAND, condition=[SURF]) |
|||
G.add_edge('Route 21', CINNABAR_ISLAND, condition=[SURF]) |
|||
G.add_edge('Route 22', VIRIDIAN_CITY, condition=None) |
|||
G.add_edge(VICTORY_ROAD, INDIGO_PLATEAU, condition=None) |
|||
G.add_edge('Route 12', 'Route 13', condition=None) |
|||
G.add_edge('Route 13', 'Route 14', condition=None) |
|||
G.add_edge('Route 14', 'Route 15', condition=None) |
|||
G.add_edge('Route 24', 'Route 25', condition=None) |
|||
G.add_edge('Route 10', POWER_PLANT, condition=[SURF]) |
|||
G.add_edge('Route 5', 'Underground Path', condition=None) |
|||
G.add_edge('Underground Path', 'Route 6', condition=None) |
|||
|
|||
G.nodes[VERMILION_CITY]['grants_conditions'] = [ |
|||
{'condition': THUNDER_BADGE, 'required_conditions': []}, |
|||
{'condition': FLUTE_CHANNEL, 'required_conditions': [EXPN_CARD]}, |
|||
{'condition': CLEFAIRY_DOLL, 'required_conditions': [POWER_RESTORED]}, |
|||
] |
|||
G.nodes[SAFFRON_CITY]['grants_conditions'] = [ |
|||
{'condition': MARSH_BADGE, 'required_conditions': []}, |
|||
{'condition': RAIL_PASS, 'required_conditions': [CLEFAIRY_DOLL]}, |
|||
] |
|||
G.nodes[LAVENDER_TOWN]['grants_conditions'] = [ |
|||
{'condition': EXPN_CARD, 'required_conditions': [POWER_RESTORED]} |
|||
] |
|||
G.nodes[POWER_PLANT]['grants_conditions'] = [ |
|||
{'condition': POWER_PLANT_VISITED, 'required_conditions': []}, |
|||
{'condition': POWER_RESTORED, 'required_conditions': [MACHINE_PART]} |
|||
] |
|||
G.nodes[CERULEAN_CITY]['grants_conditions'] = [ |
|||
{'condition': CASCADE_BADGE, 'required_conditions': [MISTY_FOUND]}, |
|||
{'condition': MACHINE_PART, 'required_conditions': [POWER_PLANT_VISITED]} |
|||
] |
|||
G.nodes['Route 25']['grants_conditions'] = [ |
|||
{'condition': MISTY_FOUND, 'required_conditions': []} |
|||
] |
|||
G.nodes[CELADON_CITY]['grants_conditions'] = [ |
|||
{'condition': RAINBOW_BADGE, 'required_conditions': []} |
|||
] |
|||
G.nodes[FUCHSIA_CITY]['grants_conditions'] = [ |
|||
{'condition': SOUL_BADGE, 'required_conditions': []} |
|||
] |
|||
G.nodes['Route 11']['grants_conditions'] = [ |
|||
{'condition': WOKE_SNORLAX, 'required_conditions': [FLUTE_CHANNEL]} |
|||
] |
|||
G.nodes[PEWTER_CITY]['grants_conditions'] = [ |
|||
{'condition': BOULDER_BADGE, 'required_conditions': []}, |
|||
{'condition': PKMN_WING, 'required_conditions': []}, |
|||
] |
|||
G.nodes[VIRIDIAN_CITY]['grants_conditions'] = [ |
|||
{'condition': EARTH_BADGE, 'required_conditions': [VOLCANO_BADGE]}, |
|||
] |
|||
G.nodes[PALLET_TOWN]['grants_conditions'] = [ |
|||
{'condition': ROUTE_28_UNLOCKED, 'required_conditions': [BOULDER_BADGE, CASCADE_BADGE, THUNDER_BADGE, RAINBOW_BADGE, MARSH_BADGE, SOUL_BADGE, VOLCANO_BADGE, EARTH_BADGE]}, |
|||
] |
|||
G.nodes[CINNABAR_ISLAND]['grants_conditions'] = [ |
|||
{'condition': VOLCANO_BADGE, 'required_conditions': []}, |
|||
] |
|||
|
|||
return G |
|||
|
|||
def get_gold_silver_route() -> Graph: |
|||
|
|||
a = get_johto_route() |
|||
b = get_kanto_route() |
|||
|
|||
return a |
|||
@ -0,0 +1,239 @@ |
|||
import networkx as nx |
|||
from networkx import Graph |
|||
|
|||
from routes.game_world import RouteStage |
|||
from routes.pokemon_game_desc import PokemonGameDesc |
|||
|
|||
PALLET_TOWN = 'Pallet Town' |
|||
VIRIDIAN_CITY = 'Viridian City' |
|||
VIRIDIAN_FOREST = 'Viridian Forest' |
|||
PEWTER_CITY = 'Pewter City' |
|||
MT_MOON = 'Mt. Moon' |
|||
CERULEAN_CITY = 'Cerulean City' |
|||
POWER_PLANT = 'Power Plant' |
|||
SAFFRON_CITY = 'Saffron City' |
|||
CELADON_CITY = 'Celadon City' |
|||
CERULEAN_CAVE = 'Cerulean Cave' |
|||
VERMILLION_CITY = 'Vermillion City' |
|||
BILLS_HOUSE = 'Bill\'s House' |
|||
FUCHSIA_CITY = 'Fuchsia City' |
|||
SS_ANNE = 'S.S. Anne' |
|||
CINNABAR_ISLAND = 'Cinnabar Island' |
|||
SEAFOAM_ISLANDS ='Seafoam Islands' |
|||
VICTORY_ROAD = 'Victory Road' |
|||
INDIGO_PLATEAU = 'Indigo Plateau' |
|||
ROCK_TUNNEL = 'Rock Tunnel' |
|||
UNDERGROUND_PATH = 'Underground Path' |
|||
UNDERGROUND_PASSAGE = 'Underground Passage' |
|||
DIGLETT_CAVE = 'Diglett Cave' |
|||
POKEMON_TOWER = 'Pokemon Tower' |
|||
LAVENDER_TOWN = 'Lavender Town' |
|||
|
|||
BOULDER_BADGE = 'Boulder Badge' |
|||
CASCADE_BADGE = 'Cascade Badge' |
|||
THUNDER_BADGE = 'Thunder Badge' |
|||
RAINBOW_BADGE = 'Rainbow Badge' |
|||
MARSH_BADGE = 'Marsh Badge' |
|||
SOUL_BADGE = 'Soul Badge' |
|||
VOLCANO_BADGE = 'Volcano Badge' |
|||
EARTH_BADGE = 'Earth Badge' |
|||
|
|||
BIKE = 'Bike' |
|||
BIKE_VOUCHER = 'Bike Voucer' |
|||
SS_ANNE_TICKET = 'S.S. Anne Ticket' |
|||
QUENCHED_THURST = 'Quenched Thrust' |
|||
POKE_FLUTE = 'Poke Flute' |
|||
SILPH_SCOPE = 'Silph Scope' |
|||
GIOVANNI_FIGHT = 'Giovanni Fight' |
|||
CHAMPION = 'Champion' |
|||
MEWTWO = 'Mewtwo' |
|||
ARCTICUNO = 'Arcticuno' |
|||
ZAPDOS = 'Zapdos' |
|||
MOLTRES = 'Moltres' |
|||
|
|||
CUT = 'Cut' |
|||
SURF = 'Surf' |
|||
FLASH = 'Flash' |
|||
STRENGTH = 'Strength' |
|||
FLY = 'Fly' |
|||
|
|||
FLY_OUT_OF_BATTLE = 'Fly out of battle' |
|||
|
|||
def get_red_blue_desc() -> PokemonGameDesc: |
|||
desc: PokemonGameDesc = PokemonGameDesc() |
|||
#desc.graph = get_red_blue_route() |
|||
desc.game_name = "Red" |
|||
desc.towns_and_cities = [PALLET_TOWN, VIRIDIAN_CITY, PEWTER_CITY, CERULEAN_CITY, SAFFRON_CITY, CELADON_CITY, VERMILLION_CITY, FUCHSIA_CITY, CINNABAR_ISLAND] |
|||
desc.hms = [CUT, SURF, FLASH, STRENGTH, FLY] |
|||
desc.file_name = "red_blue_yellow_problem.pddl" |
|||
desc.games_covered = ["Red", "Blue", "Yellow"] |
|||
|
|||
stage: RouteStage = RouteStage( |
|||
"Kanto", |
|||
get_red_blue_route(), |
|||
PALLET_TOWN, |
|||
CERULEAN_CAVE, |
|||
[BOULDER_BADGE, CASCADE_BADGE, THUNDER_BADGE, RAINBOW_BADGE, MARSH_BADGE, SOUL_BADGE, VOLCANO_BADGE, EARTH_BADGE], |
|||
set(), |
|||
[PALLET_TOWN, VIRIDIAN_CITY, PEWTER_CITY, CERULEAN_CITY, SAFFRON_CITY, CELADON_CITY, VERMILLION_CITY, FUCHSIA_CITY, CINNABAR_ISLAND] |
|||
) |
|||
desc.stages.append(stage) |
|||
|
|||
return desc |
|||
|
|||
def get_red_blue_route() -> Graph: |
|||
G = nx.Graph() |
|||
|
|||
for i in range(1,25): |
|||
G.add_node(f'Route {i}', node_type='route') |
|||
|
|||
G.nodes['Route 2']['grants_conditions'] = [ |
|||
{'condition': FLASH, 'required_conditions': [CUT]} |
|||
] |
|||
|
|||
G.nodes['Route 16']['grants_conditions'] = [ |
|||
{'condition': FLY, 'required_conditions': [CUT]} |
|||
] |
|||
|
|||
G.add_node(PALLET_TOWN, node_type='location') |
|||
G.add_node(VIRIDIAN_CITY, node_type='location') |
|||
G.nodes[VIRIDIAN_CITY]['grants_conditions'] = [ |
|||
{'condition': EARTH_BADGE, 'required_conditions': [GIOVANNI_FIGHT]} |
|||
] |
|||
G.add_node(VIRIDIAN_FOREST, node_type='location') |
|||
G.add_node(PEWTER_CITY, node_type='location') |
|||
G.nodes[PEWTER_CITY]['grants_conditions'] = [ |
|||
{'condition': BOULDER_BADGE, 'required_conditions': []} |
|||
] |
|||
G.add_node(MT_MOON, node_type='location') |
|||
G.add_node(CERULEAN_CITY, node_type='location') |
|||
G.nodes[CERULEAN_CITY]['grants_conditions'] = [ |
|||
{'condition': CASCADE_BADGE, 'required_conditions': []}, |
|||
{'condition': BIKE, 'required_conditions': [BIKE_VOUCHER]}, |
|||
] |
|||
G.add_node(BILLS_HOUSE, node_type='location') |
|||
G.nodes[BILLS_HOUSE]['grants_conditions'] = [ |
|||
{'condition': SS_ANNE_TICKET, 'required_conditions': []} |
|||
] |
|||
G.add_node(POWER_PLANT, node_type='location') |
|||
G.nodes[POWER_PLANT]['grants_conditions'] = [ |
|||
{'condition': ZAPDOS, 'required_conditions': []} |
|||
] |
|||
G.add_node(SAFFRON_CITY, node_type='location') |
|||
G.nodes[SAFFRON_CITY]['grants_conditions'] = [ |
|||
{'condition': MARSH_BADGE, 'required_conditions': []}, |
|||
{'condition': GIOVANNI_FIGHT, 'required_conditions': []}, |
|||
] |
|||
G.add_node(SS_ANNE, node_type='location') |
|||
G.nodes[SS_ANNE]['grants_conditions'] = [ |
|||
{'condition': CUT, 'required_conditions': []} |
|||
] |
|||
G.add_node(CERULEAN_CAVE, node_type='location') |
|||
G.nodes[CERULEAN_CAVE]['grants_conditions'] = [ |
|||
{'condition': MEWTWO, 'required_conditions': []} |
|||
] |
|||
G.add_node(VERMILLION_CITY, node_type='location') |
|||
G.nodes[VERMILLION_CITY]['grants_conditions'] = [ |
|||
{'condition': BIKE_VOUCHER, 'required_conditions': []}, |
|||
{'condition': THUNDER_BADGE, 'required_conditions': [CUT]}, |
|||
{'condition': FLY_OUT_OF_BATTLE, 'required_conditions': [CUT]} |
|||
] |
|||
G.add_node(CELADON_CITY, node_type='location') |
|||
G.nodes[CELADON_CITY]['grants_conditions'] = [ |
|||
{'condition': QUENCHED_THURST, 'required_conditions': []}, |
|||
{'condition': RAINBOW_BADGE, 'required_conditions': []}, |
|||
{'condition': SILPH_SCOPE, 'required_conditions': []} |
|||
] |
|||
G.add_node(FUCHSIA_CITY, node_type='location') |
|||
G.nodes[FUCHSIA_CITY]['grants_conditions'] = [ |
|||
{'condition': SURF, 'required_conditions': []}, |
|||
{'condition': STRENGTH, 'required_conditions': []}, |
|||
{'condition': SOUL_BADGE, 'required_conditions': []}, |
|||
] |
|||
G.add_node(CINNABAR_ISLAND, node_type='location') |
|||
G.nodes[CINNABAR_ISLAND]['grants_conditions'] = [ |
|||
{'condition': VOLCANO_BADGE, 'required_conditions': []} |
|||
] |
|||
G.add_node(SEAFOAM_ISLANDS, node_type='location') |
|||
G.nodes[SEAFOAM_ISLANDS]['grants_conditions'] = [ |
|||
{'condition': ARCTICUNO, 'required_conditions': []} |
|||
] |
|||
G.add_node(VICTORY_ROAD, node_type='location') |
|||
G.nodes[VICTORY_ROAD]['grants_conditions'] = [ |
|||
{'condition': MOLTRES, 'required_conditions': []} |
|||
] |
|||
G.add_node(INDIGO_PLATEAU, node_type='location') |
|||
G.nodes[INDIGO_PLATEAU]['grants_conditions'] = [ |
|||
{'condition': CHAMPION, 'required_conditions': []} |
|||
] |
|||
G.add_node(ROCK_TUNNEL, node_type='location') |
|||
G.add_node(UNDERGROUND_PATH, node_type='location') |
|||
G.add_node(DIGLETT_CAVE, node_type='location') |
|||
G.add_node(POKEMON_TOWER, node_type='location') |
|||
G.nodes[POKEMON_TOWER]['grants_conditions'] = [ |
|||
{'condition': POKE_FLUTE, 'required_conditions': []} |
|||
] |
|||
G.add_node(LAVENDER_TOWN, node_type='location') |
|||
G.add_node(UNDERGROUND_PASSAGE, node_type='location') |
|||
|
|||
|
|||
G.add_edge('Pallet Town', 'Route 1', condition=None) |
|||
G.add_edge('Pallet Town', 'Route 21', condition=[SURF]) |
|||
G.add_edge('Route 1', 'Viridian City', condition=None) |
|||
G.add_edge('Viridian City', 'Route 2', condition=None) |
|||
G.add_edge('Route 2', 'Viridian Forest', condition=None) |
|||
G.add_edge('Route 2', 'Route 3', condition=[CUT]) |
|||
G.add_edge('Viridian Forest', 'Pewter City', condition=None) |
|||
G.add_edge('Pewter City', 'Route 3', condition=None) |
|||
G.add_edge('Route 3', 'Mt. Moon', condition=None) |
|||
G.add_edge('Mt. Moon', 'Route 4', condition=None) |
|||
G.add_edge('Route 4', 'Cerulean City', condition=None) |
|||
G.add_edge('Cerulean City', 'Route 24', condition=None) |
|||
G.add_edge('Cerulean City', 'Route 9', condition=[CUT]) |
|||
G.add_edge('Cerulean City', 'Route 5', condition=None) |
|||
G.add_edge('Route 5', 'Saffron City', condition=[QUENCHED_THURST]) |
|||
G.add_edge('Saffron City', 'Route 6', condition=[QUENCHED_THURST]) |
|||
G.add_edge('Saffron City', 'Route 7', condition=[QUENCHED_THURST]) |
|||
G.add_edge('Saffron City', 'Route 8', condition=[QUENCHED_THURST]) |
|||
G.add_edge('Route 6', 'Vermillion City', condition=None) |
|||
G.add_edge('Vermillion City', 'Route 11', condition=None) |
|||
G.add_edge('Vermillion City', SS_ANNE, condition=[SS_ANNE_TICKET]) |
|||
G.add_edge('Route 11', 'Route 12', condition=[POKE_FLUTE]) |
|||
G.add_edge('Route 11', DIGLETT_CAVE, condition=None) |
|||
G.add_edge('Route 2', DIGLETT_CAVE, condition=[CUT]) |
|||
G.add_edge('Route 12', 'Route 13', condition=None) |
|||
G.add_edge('Route 12', LAVENDER_TOWN, condition=None) |
|||
G.add_edge('Route 7', LAVENDER_TOWN, condition=None) |
|||
G.add_edge(LAVENDER_TOWN, 'Route 10', condition=None) |
|||
G.add_edge('Route 9', 'Rock Tunnel', condition=[FLASH]) |
|||
G.add_edge('Route 10', 'Rock Tunnel', condition=[FLASH]) |
|||
G.add_edge('Celadon City', 'Route 8', condition=None) |
|||
G.add_edge('Celadon City', 'Route 16', condition=None) |
|||
G.add_edge('Route 16', 'Route 17', condition=[POKE_FLUTE]) |
|||
G.add_edge('Route 17', 'Route 18', condition=[BIKE]) |
|||
G.add_edge('Route 18', 'Fuchsia City', condition=[BIKE]) |
|||
G.add_edge('Fuchsia City','Route 19', condition=None) |
|||
G.add_edge('Fuchsia City','Route 15', condition=None) |
|||
G.add_edge('Fuchsia City','Safari Zone', condition=None) |
|||
G.add_edge('Route 19', 'Seafoam Islands', condition=[SURF]) |
|||
G.add_edge('Seafoam Islands', 'Route 20', condition=[SURF]) |
|||
G.add_edge('Route 20', 'Cinnabar Island', condition=[SURF]) |
|||
G.add_edge('Route 21', 'Cinnabar Island', condition=[SURF]) |
|||
G.add_edge('Route 22', 'Viridian City', condition=None) |
|||
G.add_edge('Route 22', 'Route 23', condition=[SURF]) |
|||
G.add_edge('Route 23', 'Victory Road', condition=[BOULDER_BADGE, CASCADE_BADGE, THUNDER_BADGE, RAINBOW_BADGE, MARSH_BADGE, SOUL_BADGE, VOLCANO_BADGE, EARTH_BADGE]) |
|||
G.add_edge('Victory Road', 'Indigo Plateau', condition=None) |
|||
G.add_edge('Route 12', 'Route 13', condition=None) |
|||
G.add_edge('Route 13', 'Route 14', condition=None) |
|||
G.add_edge('Route 14', 'Route 15', condition=None) |
|||
G.add_edge('Route 24', 'Cerulean Cave', condition=[SURF, CHAMPION]) |
|||
G.add_edge('Route 24', 'Route 25', condition=None) |
|||
G.add_edge('Route 25', BILLS_HOUSE, condition=None) |
|||
G.add_edge('Route 10', 'Power Plant', condition=[SURF]) |
|||
G.add_edge('Route 5', 'Underground Path', condition=None) |
|||
G.add_edge('Underground Path', 'Route 6', condition=None) |
|||
G.add_edge(LAVENDER_TOWN, POKEMON_TOWER, condition=[SILPH_SCOPE]) |
|||
G.add_edge(UNDERGROUND_PASSAGE, 'Route 7', condition=None) |
|||
G.add_edge(UNDERGROUND_PASSAGE, 'Route 8', condition=None) |
|||
|
|||
return G |
|||
@ -0,0 +1,38 @@ |
|||
from typing import List, Set |
|||
import networkx as nx |
|||
|
|||
class GameWorld: |
|||
def __init__(self, graph: nx.Graph, start: str, end: str, goals: Set[str], must_visit: Set[str], initial_conditions: frozenset, towns_and_cities: Set[str]): |
|||
self.graph = graph |
|||
self.start = start |
|||
self.end = end |
|||
self.goals = goals |
|||
self.must_visit = must_visit |
|||
self.initial_conditions = initial_conditions |
|||
self.towns_and_cities = towns_and_cities |
|||
|
|||
class RouteStage: |
|||
def __init__(self, name: str, graph: nx.Graph, start: str, end: str, goals: Set[str], must_visit: Set[str], towns_and_cities: Set[str]): |
|||
self.name: str = name |
|||
self.graph: nx.Graph = graph # A function or class that returns a subgraph for this stage |
|||
self.start: str = start |
|||
self.end: str = end |
|||
self.goals: Set[str] = goals |
|||
self.must_visit: Set[str] = must_visit |
|||
self.towns_and_cities: Set[str] = towns_and_cities |
|||
|
|||
def create_world(self, previous_conditions=None): |
|||
# Combine initial_conditions with previous_conditions if needed |
|||
# previous_conditions are those acquired from the last stage. |
|||
#final_goals = self.goals.union(previous_conditions.get('badges', set())) if previous_conditions else self.goals |
|||
# Construct a GameWorld for this stage |
|||
world = GameWorld( |
|||
graph=self.graph, |
|||
start=self.start, |
|||
end=self.end, |
|||
goals=self.goals, |
|||
must_visit=self.must_visit, |
|||
initial_conditions=previous_conditions.get('conditions', frozenset()) if previous_conditions else frozenset(), |
|||
towns_and_cities = self.towns_and_cities |
|||
) |
|||
return world |
|||
@ -0,0 +1,20 @@ |
|||
from typing import List, Set |
|||
import networkx as nx |
|||
|
|||
from routes.game_world import RouteStage |
|||
|
|||
class PokemonGameDesc: |
|||
def __init__(self): |
|||
self.game_name: str = "" |
|||
self.towns_and_cities: Set[str] = set() |
|||
self.items: Set[str] = set() |
|||
self.hms: Set[str] = set() |
|||
self.flying_badge: str |
|||
self.additional_goals: List[str] = [] |
|||
self.one_way_routes: List[str] = [] |
|||
self.must_visit: Set[str] = set() |
|||
self.games_covered: List[str] = [] |
|||
self.file_name: str = "" |
|||
self.stages: List[RouteStage] = [] |
|||
|
|||
__all__ = ["PokemonGameDesc"] |
|||
@ -0,0 +1,37 @@ |
|||
import json |
|||
from typing import Set |
|||
|
|||
def determine_must_visit_locations(plan_json: dict, db_conn, game_name: str) -> Set[str]: |
|||
# Extract needed Pokemon, find their encounter locations via db, return that set. |
|||
# No route logic here, just data derivation. |
|||
|
|||
target = None |
|||
for game in plan_json: |
|||
if game["game_name"] == game_name: |
|||
target = game |
|||
break |
|||
|
|||
if not target: |
|||
return set() |
|||
|
|||
# gather up all the pokemon needed for say crystal and find all the encounter routes/locations |
|||
needed_locations = set() |
|||
|
|||
game_info = db_conn.get_game_id_by_name(game_name) |
|||
|
|||
for key in target["pokemon"]: |
|||
catch_stats = target["pokemon"][key] |
|||
rep = catch_stats["representative"] |
|||
rand = db_conn.get_encounters(rep, "random") |
|||
static = db_conn.get_encounters(rep, "static") |
|||
encounters = [] |
|||
encounters.extend(rand) |
|||
encounters.extend(static) |
|||
|
|||
for encounter in encounters: |
|||
if encounter["game_id"] != game_info["id"]: |
|||
continue |
|||
|
|||
encounter_data = json.loads(encounter["data"]) |
|||
needed_locations.add(encounter_data["location"].replace("*", "")) |
|||
return needed_locations |
|||
@ -0,0 +1,184 @@ |
|||
|
|||
from typing import List, Set |
|||
from routes.game_world import GameWorld |
|||
import heapq |
|||
import networkx as nx |
|||
|
|||
class RoutePlan: |
|||
def __init__(self, path: List[str], cost: int, conditions: Set[str]): |
|||
self.path = path |
|||
self.cost = cost |
|||
self.conditions = conditions |
|||
|
|||
FLY_OUT_OF_BATTLE = 'Fly out of battle' |
|||
|
|||
class State: |
|||
def __init__(self, location, conditions, cost, path, visited_required_nodes): |
|||
self.location = location |
|||
self.conditions = conditions # A frozenset of conditions |
|||
self.cost = cost |
|||
self.path = path # List of locations visited in order |
|||
self.visited_required_nodes = visited_required_nodes # A frozenset of required nodes visited |
|||
|
|||
def __lt__(self, other): |
|||
return self.cost < other.cost # For priority queue |
|||
|
|||
class RoutePlanner: |
|||
def __init__(self, world: GameWorld): |
|||
self.world: GameWorld = world |
|||
|
|||
def heuristic(self, state, goal_conditions, required_nodes): |
|||
# Since we don't have actual distances, we can use the number of badges remaining as the heuristic |
|||
remaining_conditions = goal_conditions - state.conditions |
|||
remaining_nodes = required_nodes - state.visited_required_nodes |
|||
return len(remaining_conditions) + len(remaining_nodes) |
|||
|
|||
def heuristic2(self, state, goal_conditions, end_goal, required_nodes, distances): |
|||
remaining_conditions = goal_conditions - state.conditions |
|||
remaining_nodes = required_nodes - state.visited_required_nodes |
|||
|
|||
# Find the shortest distance from current_state.location to any required node + eventually to the goal |
|||
# As a simple first step: take the minimum distance from the current node to any required node or the goal. |
|||
node_candidates = list(remaining_nodes) + [end_goal] |
|||
min_dist = float('inf') |
|||
for candidate in node_candidates: |
|||
d = distances.get((state.location, candidate), float('inf')) |
|||
if d < min_dist: |
|||
min_dist = d |
|||
|
|||
# If no must-visit nodes remain, just consider distance to the goal |
|||
if not remaining_nodes: |
|||
min_dist = distances.get((state.location, end_goal), float('inf')) |
|||
|
|||
# Combine with remaining conditions count as before |
|||
return len(remaining_conditions) + len(remaining_nodes) + (min_dist if min_dist != float('inf') else 0) |
|||
|
|||
|
|||
def is_goal_state(self, state, goal_location, goals, required_nodes): |
|||
return ( |
|||
state.location == goal_location and |
|||
goals.issubset(state.conditions) and |
|||
required_nodes.issubset(state.visited_required_nodes) |
|||
) |
|||
|
|||
def compute_shortest_path(self, graph, key_nodes): |
|||
distances = {} # distances[(u,v)] = shortest distance from u to v ignoring conditions |
|||
|
|||
for node in key_nodes: |
|||
dist_from_node = nx.single_source_shortest_path_length(graph, node) |
|||
for other in key_nodes: |
|||
distances[(node, other)] = dist_from_node.get(other, float('inf')) |
|||
|
|||
return distances |
|||
|
|||
def astar_search(self) -> RoutePlan: |
|||
from collections import deque |
|||
|
|||
self.goals = set(self.world.goals) |
|||
|
|||
key_nodes = [self.world.start, self.world.end] + list(self.world.towns_and_cities) |
|||
if len(self.world.must_visit) > 0: |
|||
key_nodes += list(self.world.must_visit) |
|||
distances = self.compute_shortest_path(self.world.graph, key_nodes) |
|||
|
|||
# Priority queue for open states |
|||
open_list = [] |
|||
heapq.heappush(open_list, (0, State( |
|||
location=self.world.start, |
|||
conditions=self.world.initial_conditions, # Start with no conditions |
|||
cost=0, |
|||
path=[self.world.start], |
|||
visited_required_nodes=frozenset([self.world.start]) if self.world.start in self.world.must_visit else frozenset() |
|||
))) |
|||
|
|||
# Closed set to keep track of visited states |
|||
closed_set = {} |
|||
|
|||
while open_list: |
|||
_, current_state = heapq.heappop(open_list) |
|||
|
|||
# Check if we've reached the goal location with all required conditions |
|||
if self.is_goal_state(current_state, self.world.end, self.goals, self.world.must_visit): |
|||
return RoutePlan(current_state.path, current_state.cost, current_state.conditions) |
|||
|
|||
# Check if we've already visited this state with equal or better conditions |
|||
state_key = (current_state.location, current_state.conditions, current_state.visited_required_nodes) |
|||
if state_key in closed_set and closed_set[state_key] <= current_state.cost: |
|||
continue # Skip this state |
|||
|
|||
closed_set[state_key] = current_state.cost |
|||
|
|||
# Expand neighbors via normal moves |
|||
for neighbor in self.world.graph.neighbors(current_state.location): |
|||
edge_data = self.world.graph.get_edge_data(current_state.location, neighbor) |
|||
edge_condition = edge_data.get('condition', []) |
|||
|
|||
if edge_condition is None: |
|||
edge_requires = set() |
|||
else: |
|||
edge_requires = set(edge_condition) |
|||
|
|||
# Check if we have the required conditions to traverse this edge |
|||
if not edge_requires.issubset(current_state.conditions): |
|||
continue # Can't traverse this edge |
|||
|
|||
# Update conditions based on grants at the neighbor node |
|||
neighbor_data = self.world.graph.nodes[neighbor] |
|||
new_conditions = set(current_state.conditions) |
|||
|
|||
# Check if the neighbor grants any conditions |
|||
grants = neighbor_data.get('grants_conditions', []) |
|||
for grant in grants: |
|||
required_for_grant = set(grant.get('required_conditions', [])) |
|||
if required_for_grant.issubset(new_conditions): |
|||
# We can acquire the condition |
|||
new_conditions.add(grant['condition']) |
|||
|
|||
# Update visited required nodes |
|||
new_visited_required_nodes = set(current_state.visited_required_nodes) |
|||
if neighbor in self.world.must_visit: |
|||
new_visited_required_nodes.add(neighbor) |
|||
|
|||
new_state = State( |
|||
location=neighbor, |
|||
conditions=frozenset(new_conditions), |
|||
cost=current_state.cost + 1, # Assuming uniform cost; adjust if needed |
|||
path=current_state.path + [neighbor], |
|||
visited_required_nodes=frozenset(new_visited_required_nodes) |
|||
) |
|||
|
|||
#estimated_total_cost = new_state.cost + self.heuristic(new_state, self.goals, self.world.must_visit) |
|||
estimated_total_cost = new_state.cost + self.heuristic2(new_state, self.goals, self.world.end, self.world.must_visit, distances) |
|||
|
|||
heapq.heappush(open_list, (estimated_total_cost, new_state)) |
|||
|
|||
# Expand neighbors via FLY if applicable |
|||
if FLY_OUT_OF_BATTLE in current_state.conditions and current_state.location in self.world.towns_and_cities: |
|||
for fly_target in self.world.towns_and_cities: |
|||
if fly_target != current_state.location and fly_target in current_state.path: |
|||
# You can fly to this location |
|||
new_conditions = set(current_state.conditions) |
|||
neighbor_data = self.world.graph.nodes[fly_target] |
|||
grants = neighbor_data.get('grants_conditions', []) |
|||
for grant in grants: |
|||
required_for_grant = set(grant.get('required_conditions', [])) |
|||
if required_for_grant.issubset(new_conditions): |
|||
new_conditions.add(grant['condition']) |
|||
|
|||
# Update visited required nodes |
|||
new_visited_required_nodes = set(current_state.visited_required_nodes) |
|||
if fly_target in self.world.must_visit: |
|||
new_visited_required_nodes.add(fly_target) |
|||
|
|||
fly_state = State( |
|||
location=fly_target, |
|||
conditions=frozenset(new_conditions), |
|||
cost=current_state.cost + 1, # Adjust cost if flying is different |
|||
path=current_state.path + [fly_target], |
|||
visited_required_nodes=frozenset(new_visited_required_nodes) |
|||
) |
|||
#estimated_total_cost = fly_state.cost + self.heuristic(fly_state, self.goals, self.world.must_visit) |
|||
estimated_total_cost = fly_state.cost + self.heuristic2(fly_state, self.goals, self.world.end, self.world.must_visit, distances) |
|||
heapq.heappush(open_list, (estimated_total_cost, fly_state)) |
|||
|
|||
return None # No path found |
|||
@ -0,0 +1,39 @@ |
|||
from PyQt6.QtCore import QObject, pyqtSignal, QRunnable |
|||
import json |
|||
|
|||
from cache import cache |
|||
from db import db |
|||
|
|||
from ui.workers.gather_evolutions_worker import GatherEvolutions |
|||
from utility.data import exclusive_choice_pokemon |
|||
from utility.functions import get_display_name, get_form_name, get_shiftable_forms, parse_pfic |
|||
|
|||
class GatherBabyStatusWorkerSignals(QObject): |
|||
finished = pyqtSignal(list) |
|||
|
|||
class GatherBabyStatusWorker(GatherEvolutions): |
|||
def __init__(self): |
|||
super().__init__() |
|||
self.signals = GatherBabyStatusWorkerSignals() |
|||
|
|||
def run(self): |
|||
try: |
|||
gathered_data = self.gather_baby_status(False) |
|||
self.signals.finished.emit(gathered_data) |
|||
except Exception as e: |
|||
print(f"Error gathering Pokémon home storage status: {e}") |
|||
|
|||
def gather_baby_status(self, force_refresh = False): |
|||
all_pokemon_forms = db.get_pokemon_home_list() |
|||
babys = [] |
|||
|
|||
for pokemon_form in all_pokemon_forms: |
|||
evolution_tree = self.gather_evolution_tree(pokemon_form, force_refresh) |
|||
if not evolution_tree: |
|||
continue |
|||
if evolution_tree["pokemon"] != pokemon_form["name"]: |
|||
continue |
|||
if evolution_tree["is_baby"]: |
|||
babys.append(pokemon_form["pfic"]) |
|||
|
|||
return babys |
|||
@ -0,0 +1,30 @@ |
|||
from PyQt6.QtCore import QObject, pyqtSignal, QRunnable |
|||
|
|||
from routes.Gold_Silver_Route import get_gold_silver_desc |
|||
from routes.Red_Blue_Route import get_red_blue_desc |
|||
from utility.convert_to_pddl import generate_pddl_domain, generate_pddl_problem |
|||
|
|||
class GeneratePDDLsWorkerSignals(QObject): |
|||
finished = pyqtSignal(list) |
|||
|
|||
class GeneratePDDLsWorker(QRunnable): |
|||
def __init__(self): |
|||
super().__init__() |
|||
self.signals = GeneratePDDLsWorkerSignals() |
|||
|
|||
def run(self): |
|||
try: |
|||
gathered_data = self.generate_PDDLs() |
|||
self.signals.finished.emit(gathered_data) |
|||
except Exception as e: |
|||
print(f"Error gathering Pokémon home storage status: {e}") |
|||
|
|||
def generate_PDDLs(self): |
|||
generate_pddl_domain() |
|||
red_blue = get_red_blue_desc() |
|||
gold_silver = get_gold_silver_desc() |
|||
|
|||
#generate_pddl_problem(red_blue) |
|||
#generate_pddl_problem(gold_silver) |
|||
|
|||
return [red_blue, gold_silver] |
|||
@ -0,0 +1,432 @@ |
|||
from PyQt6.QtCore import QObject, pyqtSignal, QRunnable |
|||
import json |
|||
|
|||
from cache import cache |
|||
from db import db |
|||
|
|||
from utility.data import exclusive_choice_pokemon |
|||
from utility.functions import get_shiftable_forms, get_shiftable_forms_bidirectional, parse_pfic, sanitize_filename |
|||
|
|||
class GeneratePlanWorkerSignals(QObject): |
|||
finished = pyqtSignal(list) |
|||
|
|||
class GeneratePlanWorker(QRunnable): |
|||
def __init__(self): |
|||
super().__init__() |
|||
self.signals = GeneratePlanWorkerSignals() |
|||
self.caught_pokemon = {} |
|||
self.group_plan = [] |
|||
self.game_plan = [] |
|||
|
|||
def run(self): |
|||
try: |
|||
gathered_data = self.generate_plan() |
|||
self.signals.finished.emit(gathered_data) |
|||
except Exception as e: |
|||
print(f"Error gathering Pokémon home storage status: {e}") |
|||
|
|||
def generate_plan(self): |
|||
generational_groups = [1, 2], [3, 4, 5], [6], [7], [8], [9] |
|||
|
|||
for group in generational_groups: |
|||
group_plan = self.plan_for_group(group) |
|||
self.group_plan.append(group_plan) |
|||
|
|||
for group in self.group_plan: |
|||
for game in group: |
|||
game_plan = self.plan_for_game(game, group[game]) |
|||
self.game_plan.append(game_plan) |
|||
|
|||
storable_in_home = db.get_pokemon_home_list() |
|||
|
|||
total_accounted_for = 0 |
|||
for entry in self.game_plan: |
|||
total_accounted_for += len(entry["pokemon_map"]) |
|||
|
|||
total_needed = len(storable_in_home) |
|||
|
|||
for home_pokemon in storable_in_home: |
|||
found = False |
|||
for game in self.game_plan: |
|||
if home_pokemon["pfic"] in game["pokemon_map"]: |
|||
found = True |
|||
break |
|||
if not found: |
|||
print(home_pokemon) |
|||
|
|||
return self.game_plan |
|||
|
|||
def plan_for_group(self, group): |
|||
group_plan = [] |
|||
needed_pokemon = set() |
|||
games_in_group = [] |
|||
game_pokemon = {} |
|||
|
|||
for generation in group: |
|||
games_in_group.extend(db.get_games_by_generation(generation)) |
|||
pokemon_in_generation = db.get_pokemon_by_generation(generation) |
|||
for pokemon in pokemon_in_generation: |
|||
pfic = pokemon["PFIC"] |
|||
|
|||
if pokemon["storable_in_home"] == False: |
|||
continue |
|||
|
|||
testing = [ |
|||
"0140-01-000-1", "0138-01-000-1", "0140-01-000-2", "0138-01-000-2", |
|||
"0141-01-000-1", "0139-01-000-1", "0141-01-000-2", "0139-01-000-2", |
|||
] |
|||
|
|||
#if pfic not in testing: |
|||
# continue |
|||
|
|||
if pokemon["gender_relevant"] or pokemon["PFIC"][-1] == '0' or not any(pokemon["PFIC"][:-1] == s[:-1] for s in needed_pokemon): |
|||
needed_pokemon.add(pfic) |
|||
|
|||
random = db.get_all_encounters("random") |
|||
static = db.get_all_encounters("static") |
|||
starter = db.get_all_encounters("starter") |
|||
encounters = [] |
|||
encounters.extend(random) |
|||
encounters.extend(static) |
|||
encounters.extend(starter) |
|||
|
|||
""" |
|||
def thingy(current_pfic): |
|||
evolution_chains = db.get_full_evolution_paths(current_pfic) |
|||
if evolution_chains and (len(evolution_chains["predecessors"]) > 0 or len(evolution_chains["successors"]) > 0): |
|||
for chains in evolution_chains["predecessors"]: |
|||
for evolved_pfic, method in chains: |
|||
if evolved_pfic in needed_pokemon: |
|||
game_pokemon[game['id']].add(evolved_pfic) |
|||
for shiftable_form in get_shiftable_forms_bidirectional(evolved_pfic): |
|||
game_pokemon[game['id']].add(shiftable_form["to_pfic"]) |
|||
game_pokemon[game['id']].add(shiftable_form["from_pfic"]) |
|||
|
|||
for chains in evolution_chains["successors"]: |
|||
for evolved_pfic, method in chains: |
|||
if evolved_pfic in needed_pokemon: |
|||
game_pokemon[game['id']].add(evolved_pfic) |
|||
for shiftable_form in get_shiftable_forms_bidirectional(evolved_pfic): |
|||
game_pokemon[game['id']].add(shiftable_form["to_pfic"]) |
|||
game_pokemon[game['id']].add(shiftable_form["from_pfic"]) |
|||
|
|||
for game in games_in_group: |
|||
game_pokemon[game['id']] = set() |
|||
for encounter in encounters: |
|||
current_pfic = encounter['PFIC'] |
|||
if game["id"] == encounter["game_id"]: |
|||
game_pokemon[game['id']].add(current_pfic) |
|||
for shiftable_form in get_shiftable_forms_bidirectional(current_pfic): |
|||
game_pokemon[game['id']].add(shiftable_form["to_pfic"]) |
|||
game_pokemon[game['id']].add(shiftable_form["from_pfic"]) |
|||
thingy(shiftable_form["from_pfic"]) |
|||
thingy(pfic) |
|||
""" |
|||
|
|||
for game in games_in_group: |
|||
game_pokemon[game['id']] = set() |
|||
for encounter in encounters: |
|||
if game["id"] == encounter["game_id"]: |
|||
current_pfic = encounter['PFIC'] |
|||
game_pokemon[game['id']].add(current_pfic) |
|||
evolution_chains = db.get_full_evolution_paths(current_pfic) |
|||
if evolution_chains and (len(evolution_chains["predecessors"]) > 0 or len(evolution_chains["successors"]) > 0): |
|||
for chains in evolution_chains["predecessors"]: |
|||
for evolved_pfic, method in chains: |
|||
if evolved_pfic in needed_pokemon: |
|||
game_pokemon[game['id']].add(evolved_pfic) |
|||
|
|||
for chains in evolution_chains["successors"]: |
|||
for evolved_pfic, method in chains: |
|||
if evolved_pfic in needed_pokemon: |
|||
game_pokemon[game['id']].add(evolved_pfic) |
|||
|
|||
selected_games = [] |
|||
catch_in_game = {} |
|||
remaining_pokemon = needed_pokemon.copy() |
|||
available_games = games_in_group.copy() |
|||
while remaining_pokemon: |
|||
cache = {} |
|||
for game in available_games: |
|||
cache[game['id']] = self.get_covered_pokemon(game, remaining_pokemon, game_pokemon[game['id']]) |
|||
|
|||
pokemon_covered = {} |
|||
if cache: |
|||
best_game = max(available_games, key=lambda g: len(cache[g["id"]])) |
|||
pokemon_covered = cache[best_game['id']] |
|||
|
|||
if not pokemon_covered: |
|||
print("No more Pokémon can be covered. Breaking loop.") |
|||
break |
|||
|
|||
selected_games.append(best_game) |
|||
catch_in_game[best_game["id"]] = pokemon_covered |
|||
remaining_pokemon -= pokemon_covered |
|||
|
|||
available_games.remove(best_game) |
|||
|
|||
for game in selected_games[:-1]: |
|||
|
|||
if game['id'] in cache and all(pokemon in cache[best_game['id']] |
|||
for pokemon in cache[game['id']] ): |
|||
selected_games.remove(game) |
|||
print(f"Removed {game['name']} as it's covered by {best_game['name']}") |
|||
|
|||
for game in selected_games: |
|||
file_name = sanitize_filename(game["name"]) |
|||
output_file = "./temp/"+file_name+".json" |
|||
with open(output_file, 'w', encoding='utf-8') as f: |
|||
temp = [] |
|||
for pfic in catch_in_game[game["id"]]: |
|||
deets = db.get_pokemon_details(pfic, ["pfic", "name", "form_name"]) |
|||
temp.append(deets) |
|||
temp.sort(key=lambda x: parse_pfic(x["pfic"])) |
|||
json.dump(temp, f, indent=4, ensure_ascii=False) |
|||
pass |
|||
|
|||
return catch_in_game |
|||
|
|||
def get_covered_pokemon(self, game, needed_pokemon, available_pokemon): |
|||
exclusive_groups = self.get_exclusive_groups(game['id']) |
|||
pokemon_covered = set() |
|||
|
|||
search_value = "0025-01-000-1" |
|||
|
|||
if search_value in needed_pokemon: |
|||
pass |
|||
|
|||
if search_value in available_pokemon: |
|||
pass |
|||
|
|||
evolution_paths = {} |
|||
evolution_predecessors = {} |
|||
temp_all_pokemon = needed_pokemon | available_pokemon |
|||
|
|||
for group in exclusive_groups: |
|||
for pfic in group: |
|||
temp_all_pokemon.add(pfic) |
|||
|
|||
all_pokemon = list(temp_all_pokemon) |
|||
all_pokemon.sort(key=lambda x: parse_pfic(x)) |
|||
|
|||
for pfic in all_pokemon: |
|||
chain = db.get_full_evolution_paths(pfic) |
|||
evolution_paths[pfic] = chain |
|||
|
|||
predecessors = set([pfic]) |
|||
if chain and chain.get("predecessors"): |
|||
for entry in chain["predecessors"]: |
|||
for evolved_pfic, _ in entry: |
|||
predecessors.add(evolved_pfic) |
|||
evolution_predecessors[pfic] = predecessors |
|||
|
|||
exclusive_group_predecessors = [] |
|||
for group in exclusive_groups: |
|||
group_pokemon = set() |
|||
for pfic in group: |
|||
group_pokemon.update(evolution_predecessors.get(pfic, set())) |
|||
exclusive_group_predecessors.append(group_pokemon) |
|||
|
|||
def record_pokemon(pfic, container, needed): |
|||
container.add(pfic) |
|||
evolution_chains = evolution_paths.get(pfic) |
|||
if evolution_chains and (evolution_chains.get("predecessors") or evolution_chains.get("successors")): |
|||
for chains in evolution_chains.get("predecessors", []): |
|||
for evolved_pfic, _ in chains: |
|||
if evolved_pfic in needed: |
|||
container.add(evolved_pfic) |
|||
for chains in evolution_chains.get("successors", []): |
|||
for evolved_pfic, _ in chains: |
|||
if evolved_pfic in needed: |
|||
container.add(evolved_pfic) |
|||
|
|||
pokemon_still_needed = list(needed_pokemon & available_pokemon) |
|||
pokemon_still_needed.sort(key=lambda x: parse_pfic(x)) |
|||
|
|||
for pfic in pokemon_still_needed: |
|||
if pfic in pokemon_covered: |
|||
continue |
|||
previous_evolutions = evolution_predecessors.get(pfic, set()) |
|||
is_exclusive = False |
|||
for group_pokemon in exclusive_group_predecessors: |
|||
if previous_evolutions & group_pokemon: |
|||
is_exclusive = True |
|||
if not pokemon_covered & group_pokemon: |
|||
record_pokemon(pfic, pokemon_covered, needed_pokemon) |
|||
break |
|||
if not is_exclusive: |
|||
record_pokemon(pfic, pokemon_covered, needed_pokemon) |
|||
|
|||
return pokemon_covered |
|||
|
|||
def get_exclusive_groups(self, game_id): |
|||
for data in exclusive_choice_pokemon: |
|||
if data["game_id"] == game_id: |
|||
return data["choices"] |
|||
return [] |
|||
|
|||
def plan_for_game(self, game_id, required_pokemon): |
|||
game = db.get_game_by_id(game_id) |
|||
game_plan = { |
|||
"game_name": game['name'], |
|||
"pokemon_to_catch": {}, |
|||
"pokemon_to_breed": {}, |
|||
"pokemon_map": {} |
|||
} |
|||
|
|||
print(f'Processing {game['name']}') |
|||
|
|||
random = db.get_all_encounters("random") |
|||
static = db.get_all_encounters("static") |
|||
starter = db.get_all_encounters("starter") |
|||
encounters = [] |
|||
encounters.extend(random) |
|||
encounters.extend(static) |
|||
encounters.extend(starter) |
|||
|
|||
encounters_in_game = {} |
|||
|
|||
for encounter in encounters: |
|||
if game["id"] == encounter["game_id"]: |
|||
encounters_in_game[encounter["PFIC"]] = encounter |
|||
|
|||
pokemon_to_catch = {} |
|||
pokemon_to_breed = {} |
|||
pokemon_map = {} |
|||
other_map = {} |
|||
|
|||
def record_catch(pfic, gender, to_get): |
|||
if pfic not in encounters_in_game: |
|||
pass |
|||
|
|||
if pfic not in pokemon_to_catch: |
|||
pokemon_to_catch[pfic] = {} |
|||
|
|||
data = pokemon_to_catch[pfic] |
|||
if gender not in data: |
|||
data[gender] = 1 |
|||
else: |
|||
data[gender] += 1 |
|||
|
|||
if to_get not in pokemon_map: |
|||
pokemon_map[to_get] = {} |
|||
|
|||
pokemon_map[to_get]["ByEvolving"] = pfic |
|||
if pfic not in other_map: |
|||
other_map[pfic] = {} |
|||
other_map[pfic]["EvolveTo"] = [] |
|||
other_map[pfic]["BreedFor"] = [] |
|||
other_map[pfic]["EvolveTo"].append(to_get) |
|||
|
|||
def record_breed(pfic, gender, to_get): |
|||
if pfic not in pokemon_to_breed: |
|||
pokemon_to_breed[pfic] = {} |
|||
|
|||
data = pokemon_to_breed[pfic] |
|||
if gender not in data: |
|||
data[gender] = 1 |
|||
else: |
|||
data[gender] += 1 |
|||
|
|||
if to_get not in pokemon_map: |
|||
pokemon_map[to_get] = {} |
|||
|
|||
pokemon_map[to_get]["ByBreeding"] = pfic |
|||
if pfic not in other_map: |
|||
other_map[pfic] = {} |
|||
other_map[pfic]["EvolveTo"] = [] |
|||
other_map[pfic]["BreedFor"] = [] |
|||
other_map[pfic]["BreedFor"].append(to_get) |
|||
|
|||
# TODO: Move this to a last pass |
|||
#if pfic not in pokemon_to_catch: |
|||
# record_catch(pfic, gender) |
|||
|
|||
def get_gender_string(value): |
|||
value_map = {"0": "Any", "1": "Male", "2": "Female"} |
|||
return value_map.get(str(value), "Unknown") |
|||
|
|||
missing_count = 0 |
|||
|
|||
required_pokemon_list = list(required_pokemon) |
|||
required_pokemon_list.sort(key=lambda x: parse_pfic(x)) |
|||
|
|||
for pfic in required_pokemon_list: |
|||
pokemon_data = db.get_pokemon_details(pfic) |
|||
evolution_chain = db.get_full_evolution_paths(pfic) |
|||
if evolution_chain and not any(evolution_chain["predecessors"]): |
|||
if pokemon_data["is_baby_form"]: |
|||
recorded = False |
|||
evolutions = db.get_evolution_graph(pfic) |
|||
for evolution in evolutions: |
|||
if evolution in encounters_in_game: |
|||
bucket = get_gender_string(0) |
|||
record_breed(evolution, bucket, pfic) |
|||
recorded = True |
|||
if not recorded: |
|||
if pfic in encounters_in_game: |
|||
bucket = get_gender_string(pfic[-1]) |
|||
record_catch(pfic, bucket, pfic) |
|||
else: |
|||
if pokemon_data["gender_relevant"]: |
|||
bucket = get_gender_string(pfic[-1]) |
|||
record_catch(pfic, bucket, pfic) |
|||
else: |
|||
shiftable_forms = get_shiftable_forms(pfic) |
|||
if len(shiftable_forms) > 0: |
|||
shiftable_pfic = shiftable_forms[0]["to_pfic"] |
|||
record_catch(shiftable_pfic, "Any", pfic) |
|||
else: |
|||
record_catch(pfic, "Any", pfic) |
|||
elif evolution_chain: |
|||
bucket = get_gender_string(0) |
|||
if pokemon_data["gender_relevant"]: |
|||
bucket = get_gender_string(pfic[-1]) |
|||
first_form = db.find_most_distant_predecessors(pfic) |
|||
if first_form: |
|||
first_form_pfic = first_form[0][0] |
|||
first_form_data = db.get_pokemon_details(first_form_pfic) |
|||
if first_form_data["is_baby_form"] == False: |
|||
shiftable_forms = get_shiftable_forms(first_form_pfic) |
|||
if len(shiftable_forms) > 0: |
|||
shiftable_pfic = shiftable_forms[0]["to_pfic"] |
|||
record_catch(shiftable_pfic, bucket, pfic) |
|||
else: |
|||
record_catch(first_form_pfic, bucket, pfic) |
|||
else: |
|||
recorded = False |
|||
evolutions = db.get_evolution_graph(first_form_pfic) |
|||
for evolution in evolutions: |
|||
if evolution in encounters_in_game: |
|||
record_catch(evolution, bucket, pfic) |
|||
recorded = True |
|||
if not recorded: |
|||
if first_form_pfic in encounters_in_game: |
|||
bucket = get_gender_string(pfic[-1]) |
|||
record_catch(first_form_pfic, bucket, pfic) |
|||
|
|||
total_catch = 0 |
|||
for sub_dict in pokemon_to_catch.values(): |
|||
total_catch += sum(sub_dict.values()) |
|||
|
|||
total_breed = 0 |
|||
for sub_dict in pokemon_to_breed.values(): |
|||
total_breed += sum(sub_dict.values()) |
|||
|
|||
all = total_catch + total_breed + missing_count |
|||
|
|||
sorted_keys = sorted(pokemon_to_catch.keys()) |
|||
|
|||
# Create a new dictionary with sorted keys |
|||
sorted_dict = {key: pokemon_to_catch[key] for key in sorted_keys} |
|||
game_plan["pokemon_to_catch"] = pokemon_to_catch |
|||
game_plan["pokemon_to_breed"] = pokemon_to_breed |
|||
game_plan["pokemon_map"] = pokemon_map |
|||
game_plan["other_map"] = other_map |
|||
|
|||
for required in required_pokemon: |
|||
if required not in pokemon_map: |
|||
pokemon_data = db.get_pokemon_details(required) |
|||
print(pokemon_data["name"]) |
|||
|
|||
return game_plan |
|||
@ -0,0 +1,81 @@ |
|||
import json |
|||
from PyQt6.QtCore import QObject, pyqtSignal, QRunnable |
|||
|
|||
from db import db |
|||
from routes.game_world import GameWorld |
|||
from routes.pokemon_game_desc import PokemonGameDesc |
|||
from routes.requirements import determine_must_visit_locations |
|||
from routes.route_planner import RoutePlanner |
|||
|
|||
class SolveRouteWorkerSignals(QObject): |
|||
finished = pyqtSignal(list) |
|||
|
|||
class SolveRouteWorker(QRunnable): |
|||
def __init__(self, initial_data: PokemonGameDesc): |
|||
super().__init__() |
|||
self.signals = SolveRouteWorkerSignals() |
|||
self.initial_data = initial_data |
|||
|
|||
def run(self): |
|||
try: |
|||
stage_results = [] |
|||
current_conditions = { |
|||
'badges': set(), |
|||
'conditions': frozenset() |
|||
} |
|||
|
|||
for i, stage in enumerate(self.initial_data.stages): |
|||
if i == 0: |
|||
world = stage.create_world() |
|||
else: |
|||
prev_result = stage_results[-1] |
|||
current_conditions['conditions'] = prev_result.conditions |
|||
#current_conditions['badges'] = prev_result.conditions.intersection(all_badges_set) # if badges are a subset of conditions |
|||
stage.start = prev_result.path[-1] # end of last path is start of this stage |
|||
world = stage.create_world(previous_conditions=current_conditions) |
|||
|
|||
# First route calculation |
|||
planner = RoutePlanner(world) |
|||
initial_plan = planner.astar_search() |
|||
|
|||
# Load plan.json and determine if more visits are needed |
|||
with open("./temp/plan.json", 'r', encoding='utf-8') as f: |
|||
plan_json = json.load(f) |
|||
|
|||
needed_locations = determine_must_visit_locations(plan_json, db, self.initial_data.game_name) |
|||
missing_locations = needed_locations - set(initial_plan.path) |
|||
for prev_stage in stage_results: |
|||
missing_locations = missing_locations - set(prev_stage.path) |
|||
|
|||
|
|||
# compare those to all the ones we visit in the generated route |
|||
|
|||
node_list = list(world.graph.nodes()) |
|||
|
|||
# add missing ones to the has_visited list and re-gen the problem, then run it again |
|||
nodes_to_visit = [] |
|||
for loc in missing_locations: |
|||
if loc in node_list: |
|||
nodes_to_visit.append(loc) |
|||
|
|||
print("Additional Nodes to Visit:", nodes_to_visit) |
|||
|
|||
result = None |
|||
if nodes_to_visit: |
|||
stage.must_visit = stage.must_visit.union(nodes_to_visit) |
|||
re_visisted = stage.create_world() |
|||
planner = RoutePlanner(re_visisted) |
|||
distances = planner.compute_shortest_path(re_visisted.graph, stage.must_visit) |
|||
result = planner.astar_search() |
|||
else: |
|||
result = initial_plan |
|||
|
|||
if result: |
|||
print(result.path) |
|||
|
|||
stage_results.append(result) |
|||
|
|||
self.signals.finished.emit(stage_results) |
|||
|
|||
except Exception as e: |
|||
print(f"Error: {e}") |
|||
@ -0,0 +1,212 @@ |
|||
import json |
|||
import re |
|||
import sys |
|||
from PyQt6.QtCore import QObject, pyqtSignal, QRunnable |
|||
import subprocess |
|||
import os |
|||
from db import db |
|||
|
|||
from routes.pokemon_game_desc import PokemonGameDesc |
|||
from utility.convert_to_pddl import format_name, generate_pddl_problem |
|||
|
|||
class SolvePDDLsWorkerSignals(QObject): |
|||
finished = pyqtSignal(list) |
|||
|
|||
class SolvePDDLsWorker(QRunnable): |
|||
def __init__(self, data: PokemonGameDesc): |
|||
super().__init__() |
|||
self.signals = SolvePDDLsWorkerSignals() |
|||
self.data = data |
|||
|
|||
def run(self): |
|||
try: |
|||
gathered_data = self.solve_PDDL(self.data) |
|||
self.signals.finished.emit(gathered_data) |
|||
except Exception as e: |
|||
print(f"Error gathering Pokémon home storage status: {e}") |
|||
|
|||
def solve_PDDL(self, data: PokemonGameDesc, game_name: str = ""): |
|||
if game_name == "": |
|||
game_name = "Crystal" |
|||
|
|||
route, _, _ = data.astar_search() |
|||
|
|||
locations = set(route) |
|||
|
|||
print("Unique locations visisted: ", locations) |
|||
|
|||
output_file = "./temp/plan.json" |
|||
plan = {} |
|||
with open(output_file, 'r', encoding='utf-8') as f: |
|||
plan = json.load(f) |
|||
|
|||
target = None |
|||
for game in plan: |
|||
if game["game_name"] == game_name: |
|||
target = game |
|||
break |
|||
|
|||
if not target: |
|||
return [] |
|||
|
|||
# gather up all the pokemon needed for say crystal and find all the encounter routes/locations |
|||
needed_locations = set() |
|||
|
|||
game_info = db.get_game_id_by_name(game_name) |
|||
|
|||
for key in target["pokemon"]: |
|||
catch_stats = target["pokemon"][key] |
|||
rep = catch_stats["representative"] |
|||
rand = db.get_encounters(rep, "random") |
|||
static = db.get_encounters(rep, "static") |
|||
encounters = [] |
|||
encounters.extend(rand) |
|||
encounters.extend(static) |
|||
|
|||
for encounter in encounters: |
|||
if encounter["game_id"] != game_info["id"]: |
|||
continue |
|||
|
|||
encounter_data = json.loads(encounter["data"]) |
|||
needed_locations.add(encounter_data["location"].replace("*", "")) |
|||
|
|||
# compare those to all the ones we visit in the generated route |
|||
missing_locations = needed_locations - locations |
|||
print("missing_locations:", missing_locations) |
|||
|
|||
node_list = list(data.graph.nodes()) |
|||
|
|||
# add missing ones to the has_visited list and re-gen the problem, then run it again |
|||
nodes_to_visit = [] |
|||
for loc in missing_locations: |
|||
if loc in node_list: |
|||
nodes_to_visit.append(loc) |
|||
|
|||
print("Additional Nodes to Visit:", nodes_to_visit) |
|||
|
|||
data.must_visit = data.must_visit | set(nodes_to_visit[0:2]) |
|||
|
|||
route, _, _ = data.astar_search() |
|||
|
|||
ordered_dict = dict.fromkeys(route) |
|||
unique_list = list(ordered_dict) |
|||
|
|||
return unique_list |
|||
|
|||
def solve_PDDL_old(self, data: PokemonGameDesc, game_name: str = ""): |
|||
if game_name == "": |
|||
game_name = "Crystal" |
|||
|
|||
plan_file_name = f'./{game_name.lower()}_sas_plan' |
|||
|
|||
if os.path.exists(os.path.abspath(plan_file_name)) == False: |
|||
self.generate_sas_plan(data) |
|||
|
|||
locations = set() |
|||
pattern = re.compile(r"\((?:move|fly)\s+(\w+)\s+(\w+)\)") |
|||
with open(plan_file_name, 'r') as f: |
|||
for line in f: |
|||
# Find all matches for move and fly actions |
|||
matches = pattern.findall(line) |
|||
for loc1, loc2 in matches: |
|||
# Add both locations to the set |
|||
locations.add(loc1) |
|||
locations.add(loc2) |
|||
|
|||
print("Unique locations visisted: ", locations) |
|||
|
|||
output_file = "./temp/plan.json" |
|||
plan = {} |
|||
with open(output_file, 'r', encoding='utf-8') as f: |
|||
plan = json.load(f) |
|||
|
|||
target = None |
|||
for game in plan: |
|||
if game["game_name"] == game_name: |
|||
target = game |
|||
break |
|||
|
|||
if not target: |
|||
return [] |
|||
|
|||
# gather up all the pokemon needed for say crystal and find all the encounter routes/locations |
|||
needed_locations = set() |
|||
|
|||
game_info = db.get_game_id_by_name(game_name) |
|||
|
|||
for key in target["pokemon"]: |
|||
catch_stats = target["pokemon"][key] |
|||
rep = catch_stats["representative"] |
|||
rand = db.get_encounters(rep, "random") |
|||
static = db.get_encounters(rep, "static") |
|||
encounters = [] |
|||
encounters.extend(rand) |
|||
encounters.extend(static) |
|||
|
|||
for encounter in encounters: |
|||
if encounter["game_id"] != game_info["id"]: |
|||
continue |
|||
|
|||
encounter_data = json.loads(encounter["data"]) |
|||
needed_locations.add(format_name(encounter_data["location"].replace("*", "")).lower()) |
|||
|
|||
# compare those to all the ones we visit in the generated route |
|||
missing_locations = needed_locations - locations |
|||
print("missing_locations:", missing_locations) |
|||
|
|||
node_list = list(data.graph.nodes()) |
|||
for i in range(len(node_list)): |
|||
node_list[i] = format_name(node_list[i]) |
|||
|
|||
# add missing ones to the has_visited list and re-gen the problem, then run it again |
|||
nodes_to_visit = [] |
|||
for loc in missing_locations: |
|||
if loc in node_list: |
|||
nodes_to_visit.append(loc) |
|||
|
|||
print("Additional Nodes to Visit:", nodes_to_visit) |
|||
|
|||
data.has_visited.extend(nodes_to_visit) |
|||
|
|||
generate_pddl_problem(data) |
|||
|
|||
self.generate_sas_plan(data) |
|||
|
|||
return [] |
|||
|
|||
def generate_sas_plan(self, data: PokemonGameDesc): |
|||
print("Starting fast-downward...") |
|||
try: |
|||
command_translate = [ |
|||
'python', |
|||
os.path.abspath('./downward/builds/release/bin/translate/translate.py'), |
|||
os.path.abspath('./temp/pokemon_domain.pddl'), |
|||
os.path.abspath(f'./temp/{data.file_name}'), |
|||
'--sas-file', |
|||
'output.sas' |
|||
] |
|||
|
|||
command_search = [ |
|||
os.path.abspath('./downward/builds/release/bin/downward.exe'), |
|||
'--search', |
|||
'astar(hmax())', |
|||
'--internal-plan-file', |
|||
'sas_plan' |
|||
] |
|||
|
|||
if os.path.exists(os.path.abspath('./output.sas')): |
|||
os.remove(os.path.abspath('./output.sas')) |
|||
|
|||
if os.path.exists(os.path.abspath('./sas_plan')): |
|||
os.remove(os.path.abspath('./sas_plan')) |
|||
|
|||
print("Command to be executed:", command_translate) |
|||
|
|||
ret = subprocess.run(command_translate, check=True) |
|||
|
|||
with open(f'./output.sas', 'r') as f: |
|||
print("Command to be executed:", command_translate) |
|||
ret = subprocess.run(command_search, check=True, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP, stdin=f) |
|||
except subprocess.CalledProcessError as e: |
|||
print(f"An error occurred: {e}") |
|||
print("fast-downward compelted") |
|||
@ -0,0 +1,176 @@ |
|||
|
|||
|
|||
from routes.pokemon_game_desc import PokemonGameDesc |
|||
|
|||
|
|||
def format_name(name): |
|||
return name.replace(' ', '_').replace('.', '').replace("'", '').lower() |
|||
|
|||
def generate_pddl_domain(): |
|||
# Define the types, predicates, and action as shown above |
|||
domain_pddl = """ |
|||
(define (domain pokemon) |
|||
(:requirements :strips :typing :equality :quantified-preconditions :conditional-effects :negative-preconditions) |
|||
(:types |
|||
location |
|||
condition |
|||
) |
|||
(:predicates |
|||
(at ?loc - location) |
|||
(connected ?from ?to - location) |
|||
(has ?cond - condition) |
|||
(grants ?loc - location ?cond - condition) |
|||
(requires ?from ?to - location ?cond - condition) |
|||
(requires_grant ?loc - location ?cond - condition ?req - condition) |
|||
(visited ?loc - location) |
|||
(is_town_or_city ?loc - location) |
|||
) |
|||
(:action move |
|||
:parameters (?from ?to - location) |
|||
:precondition (and |
|||
(at ?from) |
|||
(connected ?from ?to) |
|||
; Remove (not (visited ?to)) if re-visiting is allowed |
|||
; Universal preconditions for required conditions |
|||
(forall (?cond - condition) |
|||
(imply (requires ?from ?to ?cond) (has ?cond)) |
|||
) |
|||
) |
|||
:effect (and |
|||
(at ?to) |
|||
(not (at ?from)) |
|||
(visited ?to) |
|||
) |
|||
) |
|||
(:action acquire |
|||
:parameters (?loc - location ?cond - condition) |
|||
:precondition (and |
|||
(at ?loc) |
|||
(grants ?loc ?cond) |
|||
(not (has ?cond)) |
|||
; Universal preconditions for required grants |
|||
(forall (?req - condition) |
|||
(imply (requires_grant ?loc ?cond ?req) (has ?req)) |
|||
) |
|||
) |
|||
:effect (and |
|||
(has ?cond) |
|||
) |
|||
) |
|||
(:action fly |
|||
:parameters (?from ?to - location) |
|||
:precondition (and |
|||
(at ?from) |
|||
(has Fly) |
|||
(has Fly_out_of_battle) |
|||
(visited ?to) |
|||
(is_town_or_city ?to) |
|||
(not (at ?to)) ; Prevents flying to the current location |
|||
) |
|||
:effect (and |
|||
(at ?to) |
|||
(not (at ?from)) |
|||
) |
|||
) |
|||
) |
|||
""" |
|||
with open('./temp/pokemon_domain.pddl', 'w') as f: |
|||
f.write(domain_pddl) |
|||
|
|||
def generate_pddl_problem(desc: PokemonGameDesc): |
|||
# Extract objects, init, and goal |
|||
locations = set() |
|||
conditions = set() |
|||
connections = [] |
|||
grants = [] |
|||
requirements = [] |
|||
requires_grant = [] |
|||
|
|||
# Gather conditions from node grants and edge requirements |
|||
for node, attrs in desc.graph.nodes(data=True): |
|||
node_formatted = format_name(node) |
|||
locations.add(node_formatted) |
|||
grants_conditions = attrs.get('grants_conditions', []) |
|||
for grant in grants_conditions: |
|||
condition = format_name(grant['condition']) |
|||
conditions.add(condition) |
|||
grants.append((node_formatted, condition)) |
|||
required_conditions = grant.get('required_conditions', []) |
|||
for req in required_conditions: |
|||
req_condition = format_name(req) |
|||
conditions.add(req_condition) |
|||
requires_grant.append((node_formatted, condition, req_condition)) |
|||
|
|||
for u, v, attrs in desc.graph.edges(data=True): |
|||
u_formatted = format_name(u) |
|||
v_formatted = format_name(v) |
|||
locations.update([u_formatted, v_formatted]) |
|||
# Add both directions for bidirectional movement |
|||
if f'{u_formatted} -> {v_formatted}' not in desc.one_way_routes: |
|||
connections.append((u_formatted, v_formatted)) |
|||
if f'{v_formatted} -> {u_formatted}' not in desc.one_way_routes: |
|||
connections.append((v_formatted, u_formatted)) # Add reverse connection |
|||
|
|||
edge_condition = attrs.get('condition') |
|||
if edge_condition: |
|||
if isinstance(edge_condition, list): |
|||
for cond in edge_condition: |
|||
cond_formatted = format_name(cond) |
|||
conditions.add(cond_formatted) |
|||
requirements.append((u_formatted, v_formatted, cond_formatted)) |
|||
requirements.append((v_formatted, u_formatted, cond_formatted)) # Reverse |
|||
else: |
|||
cond_formatted = format_name(edge_condition) |
|||
conditions.add(cond_formatted) |
|||
requirements.append((u_formatted, v_formatted, cond_formatted)) |
|||
requirements.append((v_formatted, u_formatted, cond_formatted)) # Reverse |
|||
|
|||
conditions.add(format_name('Fly')) |
|||
conditions.add(format_name('Fly out of battle')) |
|||
|
|||
formatted_towns_and_cities = [format_name(town) for town in desc.towns_and_cities] |
|||
|
|||
# Prepare the PDDL problem file content |
|||
problem_pddl = "(define (problem pokemon_problem)\n" |
|||
problem_pddl += " (:domain pokemon)\n" |
|||
|
|||
# Objects |
|||
problem_pddl += " (:objects\n" |
|||
problem_pddl += " " + " ".join(sorted(locations)) + " - location\n" |
|||
problem_pddl += " " + " ".join(sorted(conditions)) + " - condition\n" |
|||
problem_pddl += " )\n" |
|||
|
|||
# Initial state |
|||
problem_pddl += " (:init\n" |
|||
problem_pddl += f" (at {format_name(desc.starting_town)})\n" |
|||
for u, v in connections: |
|||
problem_pddl += f" (connected {u} {v})\n" |
|||
for loc, cond in grants: |
|||
problem_pddl += f" (grants {loc} {cond})\n" |
|||
for u, v, cond in requirements: |
|||
problem_pddl += f" (requires {u} {v} {cond})\n" |
|||
for loc, cond, req in requires_grant: |
|||
problem_pddl += f" (requires_grant {loc} {cond} {req})\n" |
|||
for town in formatted_towns_and_cities: |
|||
problem_pddl += f" (is_town_or_city {town})\n" |
|||
problem_pddl += " )\n" |
|||
|
|||
# Goal state |
|||
badges = desc.badges |
|||
additional_conditions = desc.additional_goals |
|||
visited = desc.must_visit |
|||
problem_pddl += " (:goal\n" |
|||
problem_pddl += " (and\n" |
|||
problem_pddl += f" (at {format_name(desc.end_goal)})\n" |
|||
for badge in badges: |
|||
problem_pddl += f" (has {format_name(badge)})\n" |
|||
for cond in additional_conditions: |
|||
problem_pddl += f" (has {format_name(cond)})\n" |
|||
for location in visited: |
|||
problem_pddl += f" (visited {format_name(location)})\n" |
|||
problem_pddl += " )\n" |
|||
problem_pddl += " )\n" |
|||
problem_pddl += ")\n" |
|||
|
|||
with open(f'./temp/{desc.file_name}', 'w') as f: |
|||
f.write(problem_pddl) |
|||
Loading…
Reference in new issue