diff --git a/convert_to_pddl.py b/convert_to_pddl.py new file mode 100644 index 0000000..5b856f0 --- /dev/null +++ b/convert_to_pddl.py @@ -0,0 +1,140 @@ +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) + (: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) + ) + (: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) + ) + ) + ) + """ + with open('pokemon_domain.pddl', 'w') as f: + f.write(domain_pddl) + +def generate_pddl_problem(G): + # 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 G.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 G.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 + connections.append((u_formatted, v_formatted)) + 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 + + # 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('New Bark 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" + problem_pddl += " )\n" + + # Goal state + badges = ['Zephyr Badge', 'Hive Badge', 'Plain Badge', 'Fog Badge', 'Storm Badge', 'Mineral Badge', 'Glacier Badge', 'Rising Badge'] + problem_pddl += " (:goal\n" + problem_pddl += " (and\n" + problem_pddl += f" (at {format_name('Indigo Plateau')})\n" + for badge in badges: + problem_pddl += f" (has {format_name(badge)})\n" + problem_pddl += " )\n" + problem_pddl += " )\n" + problem_pddl += ")\n" + + with open('pokemon_problem.pddl', 'w') as f: + f.write(problem_pddl) diff --git a/red_blue_goal_path.py b/red_blue_goal_path.py index 1b9ef34..21d0d86 100644 --- a/red_blue_goal_path.py +++ b/red_blue_goal_path.py @@ -6,6 +6,7 @@ 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_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_route +from convert_to_pddl import generate_pddl_domain, generate_pddl_problem class PlayerState: def __init__(self): @@ -177,3 +178,6 @@ if __name__ == "__main__": print("Optimal Path:", " -> ".join(optimal_path)) else: print("No path found to fulfill all goals.") + + generate_pddl_domain() + generate_pddl_problem(G)