Compare commits

...

11 Commits

  1. 15
      .vscode/launch.json
  2. 163
      Pokemon_Red_Route_Planner.py
  3. 377
      Routes/Gold_Silver_Route.py
  4. 228
      Routes/Red_Blue_Route.py
  5. 0
      Routes/__init__.py
  6. 152
      Routes/pokemon_game_desc.py
  7. 176
      convert_to_pddl.py
  8. 1
      downward
  9. 193
      red_blue_goal_path.py

15
.vscode/launch.json

@ -0,0 +1,15 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python Debugger: Current File",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal"
}
]
}

163
Pokemon_Red_Route_Planner.py

@ -0,0 +1,163 @@
import networkx as nx
from networkx import Graph
from pyvis.network import Network
import heapq
from copy import deepcopy
from Routes.Red_Blue_Route import CERULEAN_CAVE, PALLET_TOWN, get_red_blue_route
class PlayerState:
def __init__(self):
self.visited_nodes = {}
self.conditions_met = set()
self.goals = set() # Tracks unmet conditions required for future traversal
def find_optimal_path(G, start_node, end_node):
# Priority queue elements: (total_cost, current_node, player_state, path)
queue = []
initial_state = PlayerState()
heapq.heappush(queue, (0, start_node, [start_node], initial_state))
visited_states = {}
while queue:
total_cost, current_node, path , player_state= heapq.heappop(queue)
# If end node is reached
if current_node == end_node:
return path
if current_node in player_state.visited_nodes:
player_state.visited_nodes[current_node] += 1
else:
player_state.visited_nodes[current_node] = 1
# Visit the current node and update the player's state
visit_node(current_node, G, player_state)
# Explore neighbors
for neighbor in G.neighbors(current_node):
edge_attrs = G[current_node][neighbor]
if can_traverse(edge_attrs, player_state):
visit_count = player_state.visited_nodes.get(neighbor, 0)
edge_weight = max(1, visit_count)
# Apply weight reduction if this neighbor helps meet a goal
if any(condition in player_state.goals for condition in player_state.conditions_met):
edge_weight = max(1, edge_weight - 1) # Reduce weight to incentivize this path
new_total_cost = total_cost + edge_weight
# Copy path, but keep player_state as is (state should persist across paths)
new_path = path + [neighbor]
heapq.heappush(queue, (new_total_cost, neighbor, new_path, deepcopy(player_state)))
else:
unmet_conditions = edge_attrs.get('condition', [])
for condition in unmet_conditions:
if condition not in player_state.conditions_met:
player_state.goals.add(condition)
return None # No path found
def can_traverse(edge_attrs, player_state: PlayerState):
conditions = edge_attrs.get('condition')
if not conditions:
return True
return any(condition in conditions for condition in player_state.conditions_met)
def visit_node(node_name, G, player_state: PlayerState):
node_attrs = G.nodes[node_name]
grants_conditions = node_attrs.get('grants_conditions', [])
for grant in grants_conditions:
condition = grant['condition']
required_conditions = grant.get('required_conditions', [])
if all(cond in player_state.conditions_met for cond in required_conditions):
if condition not in player_state.conditions_met:
player_state.conditions_met.add(condition)
print(f"Condition '{condition}' granted upon visiting '{node_name}'.")
if condition in player_state.goals:
player_state.goals.remove(condition)
else:
print(f"Cannot obtain '{condition}' from '{node_name}' because required conditions are not met: {required_conditions}")
def get_available_moves(current_node, G, player_state):
available_moves = []
for neighbor in G.neighbors(current_node):
edge_attrs = G[current_node][neighbor]
if can_traverse(edge_attrs, player_state):
available_moves.append(neighbor)
return available_moves
def main():
player_state = {
'visited_nodes': set(),
'conditions_met': set()
}
G = get_red_blue_route()
net = Network(notebook=True)
optimal_path = find_optimal_path(G, PALLET_TOWN, CERULEAN_CAVE)
if optimal_path is None:
return
# Create a set of edges in the optimal path for quick lookup
optimal_edges = set(zip(optimal_path, optimal_path[1:]))
# Add nodes to the network
for node, attrs in G.nodes(data=True):
net.add_node(
node,
label=node,
title=f"Type: {attrs['node_type']}",
color='lightblue' if attrs['node_type'] == 'location' else 'lightgreen'
)
# Add edges, highlighting those in the optimal path
for source, target, attrs in G.edges(data=True):
condition = attrs['condition']
edge_label = f"Condition: {condition}" if condition else "No condition"
edge_color = 'blue' if (source, target) in optimal_edges else 'gray'
net.add_edge(
source,
target,
title=edge_label,
label=edge_label,
color=edge_color
)
net.show('optimal_pokemon_map.html')
net2 = Network(notebook=True)
# Add nodes with special styling for conditional grants
for node, attrs in G.nodes(data=True):
color = 'lightblue'
title = f"Type: {attrs.get('node_type', 'Unknown')}"
if 'grants_condition' in attrs:
title += f"<br>Grants: {attrs['grants_condition']}"
if 'required_conditions' in attrs:
title += f" (Requires: {attrs['required_conditions']})"
color = 'orange' # Highlight nodes with conditional grants
else:
color = 'green' # Nodes that grant conditions without prerequisites
net2.add_node(node, label=node, title=title, color=color)
# Add edges
for source, target, attrs in G.edges(data=True):
condition = attrs.get('condition')
edge_label = f"Condition: {condition}" if condition else "No condition"
color = 'red' if condition else 'gray'
net2.add_edge(source, target, title=edge_label, label=edge_label, color=color)
net2.show('pokemon_map_with_conditions.html')
if __name__ == "__main__":
try:
main()
finally:
pass

377
Routes/Gold_Silver_Route.py

@ -0,0 +1,377 @@
import networkx as nx
from networkx import Graph
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 = "Gold_Silver"
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, PALLET_TOWN, VIRIDIAN_CITY, PEWTER_CITY, CERULEAN_CITY, SAFFRON_CITY, CELADON_CITY, VERMILION_CITY, FUCHSIA_CITY, CINNABAR_ISLAND]
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.must_visit = set([MT_MOON])
desc.starting_town = NEW_BARK_TOWN
desc.end_goal = MT_SILVER
desc.one_way_routes.append("Route_29 -> Route_46")
return desc
def get_gold_silver_route() -> Graph:
G = nx.Graph()
for i in range(1,46):
G.add_node(f'Route {i}', 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(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(SAFARI_ZONE, node_type='location')
G.add_node(TOHJO_FALLS, node_type='location')
G.add_node(POWER_PLANT, 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('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(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('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(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(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[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[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': []}
]
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

228
Routes/Red_Blue_Route.py

@ -0,0 +1,228 @@
import networkx as nx
from networkx import Graph
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_Blue"
desc.towns_and_cities = [PALLET_TOWN, VIRIDIAN_CITY, PEWTER_CITY, CERULEAN_CITY, SAFFRON_CITY, CELADON_CITY, VERMILLION_CITY, FUCHSIA_CITY, CINNABAR_ISLAND]
desc.badges = [BOULDER_BADGE, CASCADE_BADGE, THUNDER_BADGE, RAINBOW_BADGE, MARSH_BADGE, SOUL_BADGE, VOLCANO_BADGE, EARTH_BADGE]
desc.hms = [CUT, SURF, FLASH, STRENGTH, FLY]
desc.starting_town = PALLET_TOWN
desc.end_goal = CERULEAN_CAVE
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
Routes/__init__.py

152
Routes/pokemon_game_desc.py

@ -0,0 +1,152 @@
import heapq
import networkx as nx
from typing import List, Set
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
def heuristic(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 is_goal_state(state, goal_location, goals, required_nodes):
return (
state.location == goal_location and
goals.issubset(state.conditions) and
required_nodes.issubset(state.visited_required_nodes)
)
class PokemonGameDesc:
def __init__(self):
self.game_name: str = ""
self.towns_and_cities: Set[str] = set()
self.badges: Set[str] = set()
self.items: Set[str] = set()
self.hms: Set[str] = set()
self.starting_town: str
self.end_goal: str
self.flying_badge: str
self.additional_goals: List[str] = []
self.one_way_routes: List[str] = []
self.must_visit: Set[str] = set()
self.graph: nx.Graph = nx.Graph()
def astar_search(self):
from collections import deque
self.goals = set(self.badges + self.additional_goals)
# Priority queue for open states
open_list = []
heapq.heappush(open_list, (0, State(
location=self.starting_town,
conditions=frozenset(), # Start with no conditions
cost=0,
path=[self.starting_town],
visited_required_nodes=frozenset([self.starting_town]) if self.starting_town in self.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 is_goal_state(current_state, self.end_goal, self.goals, self.must_visit):
return 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.graph.neighbors(current_state.location):
edge_data = self.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.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.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 + heuristic(new_state, self.goals, self.must_visit)
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.towns_and_cities:
for fly_target in self.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.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.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 + heuristic(fly_state, self.goals, self.must_visit)
heapq.heappush(open_list, (estimated_total_cost, fly_state))
return None # No path found
__all__ = ["PokemonGameDesc"]

176
convert_to_pddl.py

@ -0,0 +1,176 @@
from Routes.pokemon_game_desc import PokemonGameDesc
def format_name(name):
return name.replace(' ', '_').replace('.', '').replace("'", '')
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('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'pokemon_problem_{desc.game_name}.pddl', 'w') as f:
f.write(problem_pddl)

1
downward

@ -0,0 +1 @@
Subproject commit c7d6a4d87a10a4c2857285c3b49a14e8d18717a2

193
red_blue_goal_path.py

@ -0,0 +1,193 @@
import networkx as nx
from networkx import Graph
from pyvis.network import Network
import heapq
from copy import deepcopy
from Routes.Gold_Silver_Route import CATCH_RED_GYRADOS, FOG_BADGE, GLACIER_BADGE, HIVE_BADGE, JOHTO_CHAMPION, MEDICINE, MINERAL_BADGE, NEW_BARK_TOWN, PLAIN_BADGE, RISING_BADGE, ROCK_SMASH, ROCKET_DEAFEATED, SS_AQUA, ZEPHYR_BADGE, get_gold_silver_desc, get_gold_silver_route
from Routes.Red_Blue_Route import ARCTICUNO, BOULDER_BADGE, CASCADE_BADGE, CERULEAN_CAVE, CHAMPION, CUT, FLASH, GIOVANNI_FIGHT, MARSH_BADGE, MEWTWO, MOLTRES, PALLET_TOWN, POKE_FLUTE, QUENCHED_THURST, RAINBOW_BADGE, SILPH_SCOPE, SOUL_BADGE, SS_ANNE_TICKET, THUNDER_BADGE, VOLCANO_BADGE, ZAPDOS, get_red_blue_desc, get_red_blue_route
from convert_to_pddl import generate_pddl_domain, generate_pddl_problem
class PlayerState:
def __init__(self):
self.visited_nodes = set() # Keeps track of nodes visited
self.conditions_met = set() # Tracks conditions the player has acquired
def has_condition(self, condition):
return condition in self.conditions_met
def add_condition(self, condition):
self.conditions_met.add(condition)
def find_path_to_goal(G, start_node, goal, player_state):
# Priority queue elements: (total_cost, current_node, path, state)
queue = []
initial_state = deepcopy(player_state)
heapq.heappush(queue, (0, start_node, [start_node], initial_state))
visited = set()
# Extract goal type and target
goal_type, target = goal
while queue:
total_cost, current_node, path, state = heapq.heappop(queue)
if current_node in visited:
continue
visited.add(current_node)
# Visit the current node and update the player's state if needed
new_state = deepcopy(state)
visit_node(current_node, G, new_state)
# Check if the goal condition is met
if goal_type == "condition" and target in new_state.conditions_met:
# Commit the updated state to the player state
player_state.visited_nodes = new_state.visited_nodes
player_state.conditions_met = new_state.conditions_met
return path
elif goal_type == "node" and current_node == target:
# Commit the updated state to the player state
player_state.visited_nodes = new_state.visited_nodes
player_state.conditions_met = new_state.conditions_met
return path
# Explore neighbors
for neighbor in G.neighbors(current_node):
edge_attrs = G[current_node][neighbor]
if can_traverse(edge_attrs, new_state):
edge_weight = edge_attrs.get('weight', 1)
new_total_cost = total_cost + edge_weight
new_path = path + [neighbor]
heapq.heappush(queue, (new_total_cost, neighbor, new_path, new_state))
return None # No path found to the goal
def find_optimal_path_with_goals(G, start_node, end_node, goals):
current_node = start_node
full_path = [start_node] # Start with the starting node in the path
player_state = PlayerState()
# Iterate through each goal to find paths in succession
for goal in goals:
path_to_goal = find_path_to_goal(G, current_node, goal, player_state)
if path_to_goal is None:
print(f"Failed to find a path to the goal: {goal}")
return None
# Extend the full path with all nodes in path_to_goal
# Avoid repeating the current_node, so exclude the first node
full_path.extend(path_to_goal[1:])
# Update current node to the goal's location
current_node = path_to_goal[-1]
# Finally, find the path to the end node
#path_to_end = find_path_to_goal(G, current_node, None, player_state)
#if path_to_end is None:
# print("Failed to find a path to the end node.")
# return None
# Extend the full path with all nodes in path_to_end, excluding the first node to avoid repetition
#full_path.extend(path_to_end[1:])
return full_path
def visit_node(node_name, G, player_state: PlayerState):
# Add the current node to the visited set
player_state.visited_nodes.add(node_name)
# Grant conditions or items found at this node
node_attrs = G.nodes[node_name]
grants_conditions = node_attrs.get('grants_conditions', [])
for grant in grants_conditions:
condition = grant['condition']
required_conditions = grant.get('required_conditions', [])
# Only add conditions if requirements are met
if all(cond in player_state.conditions_met for cond in required_conditions):
if not player_state.has_condition(condition):
player_state.add_condition(condition)
print(f"Condition '{condition}' granted upon visiting '{node_name}'.")
def can_traverse(edge_attrs, player_state: PlayerState):
# Check if the player meets all the conditions required to traverse this edge
conditions = edge_attrs.get('condition')
if not conditions:
return True
return all(condition in player_state.conditions_met for condition in conditions)
# Example usage
if __name__ == "__main__":
"""
G = get_red_blue_route()
# Define the ordered goals that the player must acquire
goals = [
("condition", BOULDER_BADGE),
("condition", CASCADE_BADGE),
("condition", SS_ANNE_TICKET),
("condition", CUT),
("condition", THUNDER_BADGE),
("condition", FLASH),
("condition", SILPH_SCOPE),
("condition", RAINBOW_BADGE),
("condition", QUENCHED_THURST),
("condition", POKE_FLUTE),
("condition", GIOVANNI_FIGHT),
("condition", MARSH_BADGE),
("condition", SOUL_BADGE),
("condition", VOLCANO_BADGE),
("condition", ARCTICUNO),
("condition", ZAPDOS),
("condition", MOLTRES),
("condition", CHAMPION),
("condition", MEWTWO)
]
# Find the optimal path while fulfilling goals in succession
optimal_path = find_optimal_path_with_goals(G, PALLET_TOWN, CERULEAN_CAVE, goals)
if optimal_path:
print("Optimal Path:", " -> ".join(optimal_path))
else:
print("No path found to fulfill all goals.")
G = get_gold_silver_route()
goals = [
("condition",ZEPHYR_BADGE),
("condition",HIVE_BADGE),
("condition",CUT),
("condition",PLAIN_BADGE),
("condition",FOG_BADGE),
("condition",ROCK_SMASH),
("condition",MEDICINE),
("condition",MINERAL_BADGE),
("condition",CATCH_RED_GYRADOS),
("condition",ROCKET_DEAFEATED),
("condition",GLACIER_BADGE),
("condition",RISING_BADGE),
("condition",JOHTO_CHAMPION),
("node",SS_AQUA)
]
optimal_path = find_optimal_path_with_goals(G, NEW_BARK_TOWN, SS_AQUA, goals)
if optimal_path:
print("Optimal Path:", " -> ".join(optimal_path))
else:
print("No path found to fulfill all goals.")
"""
generate_pddl_domain()
red_blue = get_red_blue_desc()
gold_silver = get_gold_silver_desc()
path, _, _ = red_blue.astar_search()
print(path)
path, _, _ = gold_silver.astar_search()
print(path)
#generate_pddl_problem(red_blue)
#generate_pddl_problem(gold_silver)
Loading…
Cancel
Save