Browse Source

- Add fly and make it more generic

rough-outline
Quildra 1 year ago
parent
commit
68c60ea300
  1. 24
      Routes/Red_Blue_Route.py
  2. 17
      Routes/pokemon_game_desc.py
  3. 42
      convert_to_pddl.py
  4. 7
      red_blue_goal_path.py

24
Routes/Red_Blue_Route.py

@ -1,6 +1,8 @@
import networkx as nx import networkx as nx
from networkx import Graph from networkx import Graph
from Routes.pokemon_game_desc import PokemonGameDesc
PALLET_TOWN = 'Pallet Town' PALLET_TOWN = 'Pallet Town'
VIRIDIAN_CITY = 'Viridian City' VIRIDIAN_CITY = 'Viridian City'
VIRIDIAN_FOREST = 'Viridian Forest' VIRIDIAN_FOREST = 'Viridian Forest'
@ -52,6 +54,21 @@ CUT = 'Cut'
SURF = 'Surf' SURF = 'Surf'
FLASH = 'Flash' FLASH = 'Flash'
STRENGTH = 'Strength' 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: def get_red_blue_route() -> Graph:
G = nx.Graph() G = nx.Graph()
@ -63,6 +80,10 @@ def get_red_blue_route() -> Graph:
{'condition': FLASH, 'required_conditions': [CUT]} {'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(PALLET_TOWN, node_type='location')
G.add_node(VIRIDIAN_CITY, node_type='location') G.add_node(VIRIDIAN_CITY, node_type='location')
G.nodes[VIRIDIAN_CITY]['grants_conditions'] = [ G.nodes[VIRIDIAN_CITY]['grants_conditions'] = [
@ -103,7 +124,8 @@ def get_red_blue_route() -> Graph:
G.add_node(VERMILLION_CITY, node_type='location') G.add_node(VERMILLION_CITY, node_type='location')
G.nodes[VERMILLION_CITY]['grants_conditions'] = [ G.nodes[VERMILLION_CITY]['grants_conditions'] = [
{'condition': BIKE_VOUCHER, 'required_conditions': []}, {'condition': BIKE_VOUCHER, 'required_conditions': []},
{'condition': THUNDER_BADGE, 'required_conditions': [CUT]} {'condition': THUNDER_BADGE, 'required_conditions': [CUT]},
{'condition': FLY_OUT_OF_BATTLE, 'required_conditions': [CUT]}
] ]
G.add_node(CELADON_CITY, node_type='location') G.add_node(CELADON_CITY, node_type='location')
G.nodes[CELADON_CITY]['grants_conditions'] = [ G.nodes[CELADON_CITY]['grants_conditions'] = [

17
Routes/pokemon_game_desc.py

@ -0,0 +1,17 @@
import networkx as nx
from typing import List, Set
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.graph: nx.Graph = nx.Graph()
__all__ = ["PokemonGameDesc"]

42
convert_to_pddl.py

@ -1,3 +1,8 @@
from Routes.pokemon_game_desc import PokemonGameDesc
def format_name(name): def format_name(name):
return name.replace(' ', '_').replace('.', '').replace("'", '') return name.replace(' ', '_').replace('.', '').replace("'", '')
@ -5,7 +10,7 @@ def generate_pddl_domain():
# Define the types, predicates, and action as shown above # Define the types, predicates, and action as shown above
domain_pddl = """ domain_pddl = """
(define (domain pokemon) (define (domain pokemon)
(:requirements :strips :typing :equality :quantified-preconditions :conditional-effects) (:requirements :strips :typing :equality :quantified-preconditions :conditional-effects :negative-preconditions)
(:types (:types
location location
condition condition
@ -18,6 +23,7 @@ def generate_pddl_domain():
(requires ?from ?to - location ?cond - condition) (requires ?from ?to - location ?cond - condition)
(requires_grant ?loc - location ?cond - condition ?req - condition) (requires_grant ?loc - location ?cond - condition ?req - condition)
(visited ?loc - location) (visited ?loc - location)
(is_town_or_city ?loc - location)
) )
(:action move (:action move
:parameters (?from ?to - location) :parameters (?from ?to - location)
@ -51,12 +57,27 @@ def generate_pddl_domain():
(has ?cond) (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: with open('pokemon_domain.pddl', 'w') as f:
f.write(domain_pddl) f.write(domain_pddl)
def generate_pddl_problem(G): def generate_pddl_problem(desc: PokemonGameDesc):
# Extract objects, init, and goal # Extract objects, init, and goal
locations = set() locations = set()
conditions = set() conditions = set()
@ -66,7 +87,7 @@ def generate_pddl_problem(G):
requires_grant = [] requires_grant = []
# Gather conditions from node grants and edge requirements # Gather conditions from node grants and edge requirements
for node, attrs in G.nodes(data=True): for node, attrs in desc.graph.nodes(data=True):
node_formatted = format_name(node) node_formatted = format_name(node)
locations.add(node_formatted) locations.add(node_formatted)
grants_conditions = attrs.get('grants_conditions', []) grants_conditions = attrs.get('grants_conditions', [])
@ -80,7 +101,7 @@ def generate_pddl_problem(G):
conditions.add(req_condition) conditions.add(req_condition)
requires_grant.append((node_formatted, condition, req_condition)) requires_grant.append((node_formatted, condition, req_condition))
for u, v, attrs in G.edges(data=True): for u, v, attrs in desc.graph.edges(data=True):
u_formatted = format_name(u) u_formatted = format_name(u)
v_formatted = format_name(v) v_formatted = format_name(v)
locations.update([u_formatted, v_formatted]) locations.update([u_formatted, v_formatted])
@ -102,6 +123,11 @@ def generate_pddl_problem(G):
requirements.append((u_formatted, v_formatted, cond_formatted)) requirements.append((u_formatted, v_formatted, cond_formatted))
requirements.append((v_formatted, u_formatted, cond_formatted)) # Reverse 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 # Prepare the PDDL problem file content
problem_pddl = "(define (problem pokemon_problem)\n" problem_pddl = "(define (problem pokemon_problem)\n"
problem_pddl += " (:domain pokemon)\n" problem_pddl += " (:domain pokemon)\n"
@ -114,7 +140,7 @@ def generate_pddl_problem(G):
# Initial state # Initial state
problem_pddl += " (:init\n" problem_pddl += " (:init\n"
problem_pddl += f" (at {format_name('New Bark Town')})\n" problem_pddl += f" (at {format_name(desc.starting_town)})\n"
for u, v in connections: for u, v in connections:
problem_pddl += f" (connected {u} {v})\n" problem_pddl += f" (connected {u} {v})\n"
for loc, cond in grants: for loc, cond in grants:
@ -123,13 +149,15 @@ def generate_pddl_problem(G):
problem_pddl += f" (requires {u} {v} {cond})\n" problem_pddl += f" (requires {u} {v} {cond})\n"
for loc, cond, req in requires_grant: for loc, cond, req in requires_grant:
problem_pddl += f" (requires_grant {loc} {cond} {req})\n" 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" problem_pddl += " )\n"
# Goal state # Goal state
badges = ['Zephyr Badge', 'Hive Badge', 'Plain Badge', 'Fog Badge', 'Storm Badge', 'Mineral Badge', 'Glacier Badge', 'Rising Badge'] badges = desc.badges
problem_pddl += " (:goal\n" problem_pddl += " (:goal\n"
problem_pddl += " (and\n" problem_pddl += " (and\n"
problem_pddl += f" (at {format_name('Indigo Plateau')})\n" problem_pddl += f" (at {format_name(desc.end_goal)})\n"
for badge in badges: for badge in badges:
problem_pddl += f" (has {format_name(badge)})\n" problem_pddl += f" (has {format_name(badge)})\n"
problem_pddl += " )\n" problem_pddl += " )\n"

7
red_blue_goal_path.py

@ -5,7 +5,7 @@ import heapq
from copy import deepcopy 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.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 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 from convert_to_pddl import generate_pddl_domain, generate_pddl_problem
class PlayerState: class PlayerState:
@ -180,4 +180,7 @@ if __name__ == "__main__":
print("No path found to fulfill all goals.") print("No path found to fulfill all goals.")
generate_pddl_domain() generate_pddl_domain()
generate_pddl_problem(G)
red_blue = get_red_blue_desc()
generate_pddl_problem(red_blue)

Loading…
Cancel
Save