move.py 5.2KB

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