Files
ai-game-2/tools/kq4_room_navigator.py
2026-04-29 13:35:31 -07:00

91 lines
2.8 KiB
Python

#!/usr/bin/env python3
"""KQ4 Room Navigator — BFS pathfinding + MCP runtime navigation.
Uses file parsing to build a room adjacency graph, finds shortest paths via BFS,
then optionally uses the Godot MCP server (port 9090) to execute the navigation
step by step with click coordinates computed from TransitionPiece polygons.
Usage:
# Just print the path plan:
python tools/kq4_room_navigator.py --from kq4_001_beach --to kq4_092_lolottes_throne_room
# Navigate with MCP (game must be running):
python tools/kq4_room_navigator.py --from kq4_003_fountain_pool --to kq4_010_forest_path --navigate
# Just print graph summary:
python tools/kq4_room_navigator.py --summary
"""
import argparse
import json
import sys
import time
from pathlib import Path
# Add project root to path for imports
_project_root = Path(__file__).resolve().parent.parent
sys.path.insert(0, str(_project_root))
sys.path.insert(0, str(_project_root / "tools"))
sys.path.insert(0, str(_project_root / "scripts"))
from build_room_graph import (
NavigationStep,
build_graph,
find_path,
find_and_print_path,
)
BACKGROOM_PATH = "/root/Node2D/SceneViewport/background"
class NavigationError(Exception):
pass
def main() -> None:
parser = argparse.ArgumentParser(
description="KQ4 Room Navigator — plan and execute room-to-room navigation"
)
parser.add_argument("--from", dest="from_room", help="Starting room name (e.g., kq4_003_fountain_pool)")
parser.add_argument("--to", dest="to_room", help="Destination room name")
parser.add_argument("--summary", action="store_true", help="Print room graph summary")
args = parser.parse_args()
scenes_dir = _project_root / "scenes"
if not scenes_dir.exists():
print(f"ERROR: Scenes directory not found at {scenes_dir}", file=sys.stderr)
sys.exit(1)
graph = build_graph(scenes_dir)
if args.summary:
from build_room_graph import print_graph_summary
print_graph_summary(graph)
return
if not (args.from_room and args.to_room):
parser.print_help()
return
steps = find_path(graph, args.from_room, args.to_room)
if steps is None:
from build_room_graph import find_and_print_path
find_and_print_path(graph, args.from_room, args.to_room)
sys.exit(1)
# Print path plan
print(f"\nPath: {args.from_room}{args.to_room} ({len(steps)} steps)\n")
for i, step in enumerate(steps):
cx, cy = step.viewport_centroid()
coord_note = f" (click at: {cx:.0f}, {cy:.0f})" if step.polygon else ""
print(
f" {i + 1}. Click '{step.exit_node_name}' "
f"in {step.from_room}{step.to_room} [{step.label}]{coord_note}"
)
if __name__ == "__main__":
main()