pathfinding.py 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. import heapq
  2. grid.obstacles = [partner.pos]
  3. def is_passable(self, x, y):
  4. return self.at(x, y) in (FLOOR_CELL, "0", "1") and not (x, y) in self.obstacles
  5. class NoPathFound(Exception):
  6. pass
  7. class Node(tuple):
  8. def __new__(self, x, y, parent=None):
  9. n = tuple.__new__(self, (x, y))
  10. n.parent = parent
  11. n.cost = 0
  12. return n
  13. class NodesHeap():
  14. def __init__(self):
  15. self._lst = []
  16. def push(self, node, priority):
  17. heapq.heappush(self._lst, (priority, node))
  18. def pop(self):
  19. return heapq.heappop(self._lst)[1]
  20. class Pathfinder():
  21. @staticmethod
  22. def a_star(grid, origin, target):
  23. nodes = NodesHeap()
  24. origin = Node(*origin)
  25. nodes.push(origin, 0)
  26. while nodes:
  27. current = nodes.pop()
  28. if current == target:
  29. break
  30. for x, y in grid.neighbors(*current):
  31. node = Node(x, y, current)
  32. # get the moving cost to this node
  33. movingcost = grid.movingcost(*current, *node)
  34. if movingcost < 0:
  35. continue
  36. # cost of the node is the accumulated cost from origin
  37. node.cost = current.cost + movingcost
  38. # priority of the node is the sum of its cost and distance to target
  39. # (the lower the better)
  40. priority = node.cost + grid.geometry.manhattan(*node, *target)
  41. # (?) would it be necessary to check if there is already a
  42. # node with same coordinates and a lower priority?
  43. # append to the checked nodes list
  44. nodes.push(node, priority)
  45. else:
  46. # all the reachable nodes hve been checked, no way found to the target
  47. raise NoPathFound("no path were found to the targetted location {}".format(target))
  48. # build the result by going back up from target to origin
  49. result = [target]
  50. while current != origin:
  51. result.append(tuple(current))
  52. current = current.parent
  53. result.append(origin)
  54. result.reverse()
  55. return result