Distance.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import numpy as np
  2. from heapq import *
  3. from Outils.Moteur_de_jeu.Pathfinding import cases_accessibles
  4. def length_path(start, target, parent) : # Jovian : 17 janvier 2017
  5. """ Construit et retourne la longueur du chemin solution.
  6. """
  7. i = 0
  8. x, y = target
  9. while (x, y) != start:
  10. x, y = parent[x, y]
  11. i += 1
  12. return i
  13. def distance_a_star( plateau ) : # Jovian : 17 janvier 2017
  14. """
  15. Calcule la distance entre deux cases tenant compte des barrières.
  16. Argument plateau : argument self de python.
  17. Argument hcap : valeur malus ajoutée si le pion est en contact avec une barrière.
  18. Retour :
  19. None si chemin inexistant.
  20. Int comptant le nombre de cases.
  21. Positions de départ exclue et d'arrivée inclue.
  22. """
  23. # Points
  24. xi, yi = plateau.pions[0]
  25. xf, yf = plateau.pions[1]
  26. # Variables
  27. open_set = []
  28. closed = np.zeros( (plateau.lg, plateau.ht), dtype = bool )
  29. parent = np.zeros( (plateau.lg, plateau.ht, 2), dtype = int )
  30. cost_so_far = np.ones((plateau.lg, plateau.ht)) * np.inf
  31. # Estimation distance restante
  32. def heuristic( z ):
  33. # Distance directe
  34. x, y = z
  35. dist = abs(y - yf) + abs(x - xf)
  36. return dist
  37. # Ajoute un élément qui sera traité plus tard
  38. def push(open_set, z):
  39. priority = cost_so_far[z] + heuristic(z)
  40. heappush(open_set, (priority, z) )
  41. # Retire la case potentiellement la plus proche
  42. def pop(open_set):
  43. _, current = heappop(open_set)
  44. return current
  45. # Initialisation
  46. start = xi, yi
  47. cost_so_far[start] = 0
  48. push(open_set, start)
  49. current = (0, 0)
  50. # Parcours
  51. while open_set != []:
  52. # Case (x, y) en cours de traitement
  53. current = pop(open_set)
  54. x, y = current
  55. # Si on a atteint l'arrivée
  56. if current == ( xf, yf ) :
  57. break
  58. # Si la case a déjà été vue
  59. if closed[current] :
  60. continue
  61. # On dit qu'on a traité cette case
  62. closed[current] = True
  63. # Parcours des voisins
  64. for neighbor in cases_accessibles(plateau, x, y ):
  65. # Voisin déjà traité
  66. if closed[neighbor]:
  67. continue
  68. new_cost_neighbor = cost_so_far[current] + 1
  69. # Si notre chemin est plus court pour accéder à cette case
  70. if new_cost_neighbor < cost_so_far[neighbor]:
  71. cost_so_far[neighbor] = new_cost_neighbor
  72. push(open_set, neighbor)
  73. parent[neighbor] = current
  74. # Fin de parcours
  75. if current == ( xf, yf ) :
  76. # Chemin abouti
  77. return length_path(start, current, parent)
  78. else :
  79. # Chemin inexistant
  80. return None