move.py 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. # coding: utf-8
  2. import typing
  3. from dijkstar import find_path
  4. from synergine2.config import Config
  5. from synergine2.simulation import SimulationBehaviour
  6. from synergine2.simulation import SubjectBehaviour
  7. from synergine2.simulation import SubjectMechanism
  8. from synergine2.simulation import Intention
  9. from synergine2.simulation import Simulation
  10. from synergine2.simulation import Event
  11. from synergine2_xyz.simulation import XYZSimulation
  12. class MoveToIntention(Intention):
  13. def __init__(self, move_to: typing.Tuple[int, int]) -> None:
  14. self.move_to = move_to
  15. self.path = [] # type: typing.List[typing.Tuple[int, int]]
  16. self.path_progression = -1 # type: int
  17. class RequestMoveBehaviour(SimulationBehaviour):
  18. move_intention_class = MoveToIntention
  19. @classmethod
  20. def merge_data(cls, new_data, start_data=None):
  21. # TODO: behaviour/Thing dedicated to Gui -> Simulation ?
  22. pass # This behaviour is designed to be launch by terminal
  23. def __init__(
  24. self,
  25. config: Config,
  26. simulation: Simulation,
  27. ):
  28. super().__init__(config, simulation)
  29. self.simulation = typing.cast(XYZSimulation, self.simulation)
  30. def run(self, data):
  31. # TODO: behaviour/Thing dedicated to Gui -> Simulation ?
  32. pass # This behaviour is designed to be launch by terminal
  33. def action(self, data) -> typing.List[Event]:
  34. subject_id = data['subject_id']
  35. move_to = data['move_to']
  36. try:
  37. subject = self.simulation.subjects.index[subject_id]
  38. subject.intentions.set(self.move_intention_class(move_to))
  39. except KeyError:
  40. # TODO: log error here
  41. pass
  42. return []
  43. class MoveToMechanism(SubjectMechanism):
  44. def run(self):
  45. # TODO: Si move to: Si nouveau: a*, si bloque, a*, sinon rien
  46. # TODO: pourquoi un mechanism plutot que dans run du behaviour ? faire en sorte que lorsque on calcule,
  47. # si un subject est déjà passé par là et qu'il va au même endroit, ne pas recalculer.
  48. try:
  49. # TODO: MoveToIntention doit être configurable
  50. move = self.subject.intentions.get(MoveToIntention)
  51. move = typing.cast(MoveToIntention, move)
  52. new_path = None
  53. if not move.path:
  54. # TODO: Must be XYZSimulation !
  55. start = '{}.{}'.format(*self.subject.position)
  56. end = '{}.{}'.format(*move.move_to)
  57. found_path = find_path(self.simulation.graph, start, end)
  58. move.path = []
  59. for position in found_path[0]:
  60. x, y = map(int, position.split('.'))
  61. move.path.append((x, y))
  62. # Note: We are in process, move change will be lost
  63. new_path = move.path
  64. # move.path = []
  65. # new_path = move.path
  66. # for i in range(20):
  67. # move.path.append((
  68. # self.subject.position[0],
  69. # self.subject.position[1] + i,
  70. # ))
  71. next_move = move.path[move.path_progression + 1]
  72. # TODO: fin de path
  73. if not self.simulation.is_possible_position(next_move):
  74. # TODO: refaire le path
  75. new_path = ['...']
  76. return {
  77. 'new_path': new_path,
  78. }
  79. except IndexError: # TODO: Specialize ? No movement left
  80. return None
  81. except KeyError: # TODO: Specialize ? No MoveIntention
  82. return None
  83. class MoveEvent(Event):
  84. def __init__(self, subject_id: int, position: tuple, *args, **kwargs):
  85. super().__init__(*args, **kwargs)
  86. self.subject_id = subject_id
  87. self.position = position
  88. def repr_debug(self) -> str:
  89. return '{}: subject_id:{}, position:{}'.format(
  90. type(self).__name__,
  91. self.subject_id,
  92. self.position,
  93. )
  94. class MoveToBehaviour(SubjectBehaviour):
  95. use = [MoveToMechanism]
  96. move_to_mechanism = MoveToMechanism
  97. def run(self, data):
  98. # TODO: on fait vraiment rien ici ? Note: meme si il n'y a pas de new_path, l'action doit s'effectuer
  99. # du moment qu'il y a une intention de move
  100. move_to_data = data[self.move_to_mechanism]
  101. if move_to_data:
  102. return move_to_data
  103. return False
  104. def action(self, data) -> [Event]:
  105. # TODO: effectuer un move vers une nouvelle position ou faire progresser "l'entre-deux"
  106. new_path = data['new_path']
  107. try:
  108. # TODO: MoveToIntention doit être configurable
  109. move = self.subject.intentions.get(MoveToIntention)
  110. move = typing.cast(MoveToIntention, move)
  111. if new_path:
  112. move.path = new_path
  113. move.path_progression = -1
  114. # TODO: progression et lorsque "vraiment avance d'une case" envoyer le Move
  115. # pour le moment on move direct
  116. # TODO: fin de path
  117. move.path_progression += 1
  118. new_position = move.path[move.path_progression]
  119. self.subject.position = new_position
  120. return [MoveEvent(self.subject.id, new_position)]
  121. except KeyError:
  122. # TODO: log ? Il devrait y avoir un move puisque data du run/mechanism !
  123. pass