move.py 5.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  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. subject=self.subject,
  57. )
  58. # Note: We are in process, move change will be lost
  59. new_path = move.path
  60. # move.path = []
  61. # new_path = move.path
  62. # for i in range(20):
  63. # move.path.append((
  64. # self.subject.position[0],
  65. # self.subject.position[1] + i,
  66. # ))
  67. next_move = move.path[move.path_progression + 1]
  68. # TODO: fin de path
  69. if not self.simulation.is_possible_position(next_move):
  70. # TODO: refaire le path
  71. new_path = ['...']
  72. return {
  73. 'new_path': new_path,
  74. }
  75. except IndexError: # TODO: Specialize ? No movement left
  76. return None
  77. except KeyError: # TODO: Specialize ? No MoveIntention
  78. return None
  79. class MoveEvent(Event):
  80. def __init__(
  81. self,
  82. subject_id: int,
  83. from_position: typing.Tuple[int, int],
  84. to_position: typing.Tuple[int, int],
  85. *args,
  86. **kwargs
  87. ):
  88. super().__init__(*args, **kwargs)
  89. self.subject_id = subject_id
  90. self.from_position = from_position
  91. self.to_position = to_position
  92. def repr_debug(self) -> str:
  93. return '{}: subject_id:{}, from_position:{} to_position: {}'.format(
  94. type(self).__name__,
  95. self.subject_id,
  96. self.from_position,
  97. self.to_position,
  98. )
  99. class MoveToBehaviour(SubjectBehaviour):
  100. use = [MoveToMechanism]
  101. move_to_mechanism = MoveToMechanism
  102. def run(self, data):
  103. # TODO: on fait vraiment rien ici ? Note: meme si il n'y a pas de new_path, l'action doit s'effectuer
  104. # du moment qu'il y a une intention de move
  105. move_to_data = data[self.move_to_mechanism.__name__]
  106. if move_to_data:
  107. return move_to_data
  108. return False
  109. def action(self, data) -> [Event]:
  110. # TODO: effectuer un move vers une nouvelle position ou faire progresser "l'entre-deux"
  111. new_path = data['new_path']
  112. try:
  113. # TODO: MoveToIntention doit être configurable
  114. move = self.subject.intentions.get(MoveToIntention)
  115. move = typing.cast(MoveToIntention, move)
  116. if new_path:
  117. move.path = new_path
  118. move.path_progression = -1
  119. # TODO: progression et lorsque "vraiment avance d'une case" envoyer le Move
  120. # pour le moment on move direct
  121. # TODO: fin de path
  122. move.path_progression += 1
  123. new_position = move.path[move.path_progression]
  124. previous_position = self.subject.position
  125. self.subject.position = new_position
  126. self.subject.intentions.set(move)
  127. return [MoveEvent(self.subject.id, previous_position, new_position)]
  128. except KeyError:
  129. # TODO: log ? Il devrait y avoir un move puisque data du run/mechanism !
  130. pass