130 lines
4.1 KiB
Python
130 lines
4.1 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Test A* Pathfinding Implementation
|
|
==================================
|
|
|
|
Compares A* with Dijkstra and the existing find_path method.
|
|
"""
|
|
|
|
import mcrfpy
|
|
import sys
|
|
import time
|
|
|
|
print("A* Pathfinding Test")
|
|
print("==================")
|
|
|
|
# Create scene and grid
|
|
mcrfpy.createScene("astar_test")
|
|
grid = mcrfpy.Grid(grid_x=20, grid_y=20)
|
|
|
|
# Initialize grid - all walkable
|
|
for y in range(20):
|
|
for x in range(20):
|
|
grid.at(x, y).walkable = True
|
|
|
|
# Create a wall barrier with a narrow passage
|
|
print("\nCreating wall with narrow passage...")
|
|
for y in range(5, 15):
|
|
for x in range(8, 12):
|
|
if not (x == 10 and y == 10): # Leave a gap at (10, 10)
|
|
grid.at(x, y).walkable = False
|
|
print(f" Wall at ({x}, {y})")
|
|
|
|
print(f"\nPassage at (10, 10)")
|
|
|
|
# Test points
|
|
start = (2, 10)
|
|
end = (18, 10)
|
|
|
|
print(f"\nFinding path from {start} to {end}")
|
|
|
|
# Test 1: A* pathfinding
|
|
print("\n1. Testing A* pathfinding (compute_astar_path):")
|
|
start_time = time.time()
|
|
astar_path = grid.compute_astar_path(start[0], start[1], end[0], end[1])
|
|
astar_time = time.time() - start_time
|
|
print(f" A* path length: {len(astar_path)}")
|
|
print(f" A* time: {astar_time*1000:.3f} ms")
|
|
if astar_path:
|
|
print(f" First 5 steps: {astar_path[:5]}")
|
|
|
|
# Test 2: find_path method (which should also use A*)
|
|
print("\n2. Testing find_path method:")
|
|
start_time = time.time()
|
|
find_path_result = grid.find_path(start[0], start[1], end[0], end[1])
|
|
find_path_time = time.time() - start_time
|
|
print(f" find_path length: {len(find_path_result)}")
|
|
print(f" find_path time: {find_path_time*1000:.3f} ms")
|
|
if find_path_result:
|
|
print(f" First 5 steps: {find_path_result[:5]}")
|
|
|
|
# Test 3: Dijkstra pathfinding for comparison
|
|
print("\n3. Testing Dijkstra pathfinding:")
|
|
start_time = time.time()
|
|
grid.compute_dijkstra(start[0], start[1])
|
|
dijkstra_path = grid.get_dijkstra_path(end[0], end[1])
|
|
dijkstra_time = time.time() - start_time
|
|
print(f" Dijkstra path length: {len(dijkstra_path)}")
|
|
print(f" Dijkstra time: {dijkstra_time*1000:.3f} ms")
|
|
if dijkstra_path:
|
|
print(f" First 5 steps: {dijkstra_path[:5]}")
|
|
|
|
# Compare results
|
|
print("\nComparison:")
|
|
print(f" A* vs find_path: {'SAME' if astar_path == find_path_result else 'DIFFERENT'}")
|
|
print(f" A* vs Dijkstra: {'SAME' if astar_path == dijkstra_path else 'DIFFERENT'}")
|
|
|
|
# Test with no path (blocked endpoints)
|
|
print("\n4. Testing with blocked destination:")
|
|
blocked_end = (10, 8) # Inside the wall
|
|
grid.at(blocked_end[0], blocked_end[1]).walkable = False
|
|
no_path = grid.compute_astar_path(start[0], start[1], blocked_end[0], blocked_end[1])
|
|
print(f" Path to blocked cell: {no_path} (should be empty)")
|
|
|
|
# Test diagonal movement
|
|
print("\n5. Testing diagonal paths:")
|
|
diag_start = (0, 0)
|
|
diag_end = (5, 5)
|
|
diag_path = grid.compute_astar_path(diag_start[0], diag_start[1], diag_end[0], diag_end[1])
|
|
print(f" Diagonal path from {diag_start} to {diag_end}:")
|
|
print(f" Length: {len(diag_path)}")
|
|
print(f" Path: {diag_path}")
|
|
|
|
# Expected optimal diagonal path length is 5 moves (moving diagonally each step)
|
|
|
|
# Performance test with larger path
|
|
print("\n6. Performance test (corner to corner):")
|
|
corner_paths = []
|
|
methods = [
|
|
("A*", lambda: grid.compute_astar_path(0, 0, 19, 19)),
|
|
("Dijkstra", lambda: (grid.compute_dijkstra(0, 0), grid.get_dijkstra_path(19, 19))[1])
|
|
]
|
|
|
|
for name, method in methods:
|
|
start_time = time.time()
|
|
path = method()
|
|
elapsed = time.time() - start_time
|
|
print(f" {name}: {len(path)} steps in {elapsed*1000:.3f} ms")
|
|
|
|
print("\nA* pathfinding tests completed!")
|
|
print("Summary:")
|
|
print(" - A* pathfinding is working correctly")
|
|
print(" - Paths match between A* and Dijkstra")
|
|
print(" - Empty paths returned for blocked destinations")
|
|
print(" - Diagonal movement supported")
|
|
|
|
# Quick visual test
|
|
def visual_test(runtime):
|
|
print("\nVisual test timer fired")
|
|
sys.exit(0)
|
|
|
|
# Set up minimal UI for visual test
|
|
ui = mcrfpy.sceneUI("astar_test")
|
|
ui.append(grid)
|
|
grid.position = (50, 50)
|
|
grid.size = (400, 400)
|
|
|
|
mcrfpy.setScene("astar_test")
|
|
mcrfpy.setTimer("visual", visual_test, 100)
|
|
|
|
print("\nStarting visual test...") |