behaviour.py 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. # coding: utf-8
  2. import random
  3. import time
  4. import typing
  5. from opencombat.const import COLLECTION_ALIVE
  6. from opencombat.simulation.base import AliveSubjectBehaviour
  7. from opencombat.simulation.event import NoLongerVisibleOpponent
  8. from opencombat.simulation.event import FireEvent
  9. from opencombat.simulation.event import DieEvent
  10. from opencombat.simulation.event import NewVisibleOpponent
  11. from opencombat.simulation.mechanism import OpponentVisibleMechanism
  12. from opencombat.user_action import UserAction
  13. from synergine2.simulation import Event
  14. # from synergine2_xyz.move.simulation import MoveToBehaviour as BaseMoveToBehaviour
  15. #
  16. #
  17. # class MoveToBehaviour(BaseMoveToBehaviour):
  18. # def is_terminated(self) -> bool:
  19. # return COLLECTION_ALIVE not in self.subject.collections
  20. #
  21. # def _can_move_to_next_step(self, move_to_data: dict) -> bool:
  22. # if move_to_data['gui_action'] == UserAction.ORDER_MOVE:
  23. # return time.time() - move_to_data['last_intention_time'] >= \
  24. # self.subject.walk_duration
  25. # if move_to_data['gui_action'] == UserAction.ORDER_MOVE_FAST:
  26. # return time.time() - move_to_data['last_intention_time'] >= \
  27. # self.subject.run_duration
  28. # if move_to_data['gui_action'] == UserAction.ORDER_MOVE_CRAWL:
  29. # return time.time() - move_to_data['last_intention_time'] >= \
  30. # self.subject.crawl_duration
  31. #
  32. # raise NotImplementedError(
  33. # 'Gui action {} unknown'.format(move_to_data['gui_action'])
  34. # )
  35. #
  36. # # FIXME remove this func when code with new move
  37. # def get_move_duration(self, move_to_data: dict) -> float:
  38. # if move_to_data['gui_action'] == UserAction.ORDER_MOVE:
  39. # return self.subject.walk_duration
  40. # if move_to_data['gui_action'] == UserAction.ORDER_MOVE_FAST:
  41. # return self.subject.run_duration
  42. # if move_to_data['gui_action'] == UserAction.ORDER_MOVE_CRAWL:
  43. # return self.subject.crawl_duration
  44. #
  45. # raise NotImplementedError(
  46. # 'Gui action {} unknown'.format(move_to_data['gui_action'])
  47. # )
  48. #
  49. # def finalize_event(self, move_to_data: dict, event: Event) -> None:
  50. # event.move_duration = self.get_move_duration(move_to_data)
  51. class LookAroundBehaviour(AliveSubjectBehaviour):
  52. """
  53. Behaviour who permit to reference visible things like enemies
  54. """
  55. visible_mechanism = OpponentVisibleMechanism
  56. use = [visible_mechanism]
  57. def __init__(self, *args, **kwargs) -> None:
  58. super().__init__(*args, **kwargs)
  59. self._seconds_frequency = float(self.config.resolve('game.look_around.frequency'))
  60. @property
  61. def seconds_frequency(self) -> typing.Optional[float]:
  62. return self._seconds_frequency
  63. def action(self, data) -> [Event]:
  64. new_visible_subject_events = []
  65. no_longer_visible_subject_events = []
  66. for no_longer_visible_subject_id in data['no_longer_visible_subject_ids']:
  67. no_longer_visible_subject_events.append(NoLongerVisibleOpponent(
  68. observer_subject_id=self.subject.id,
  69. observed_subject_id=no_longer_visible_subject_id,
  70. ))
  71. self.subject.visible_opponent_ids.remove(no_longer_visible_subject_id)
  72. for new_visible_subject_id in data['new_visible_subject_ids']:
  73. new_visible_subject_events.append(NewVisibleOpponent(
  74. observer_subject_id=self.subject.id,
  75. observed_subject_id=new_visible_subject_id,
  76. ))
  77. self.subject.visible_opponent_ids.append(new_visible_subject_id)
  78. return new_visible_subject_events + no_longer_visible_subject_events
  79. def run(self, data):
  80. visible_subjects = data[self.visible_mechanism]['visible_subjects']
  81. visible_subject_ids = [s.id for s in visible_subjects]
  82. new_visible_subject_ids = []
  83. no_longer_visible_subject_ids = []
  84. for subject_id in self.subject.visible_opponent_ids:
  85. if subject_id not in visible_subject_ids:
  86. no_longer_visible_subject_ids.append(subject_id)
  87. for subject in visible_subjects:
  88. if subject.id not in self.subject.visible_opponent_ids:
  89. new_visible_subject_ids.append(subject.id)
  90. return {
  91. 'new_visible_subject_ids': new_visible_subject_ids,
  92. 'no_longer_visible_subject_ids': no_longer_visible_subject_ids,
  93. }
  94. @disable_when(config_value('_runtime.placement_mode'))
  95. class EngageOpponent(AliveSubjectBehaviour):
  96. visible_mechanism = OpponentVisibleMechanism
  97. use = [visible_mechanism]
  98. def __init__(self, *args, **kwargs) -> None:
  99. super().__init__(*args, **kwargs)
  100. self._seconds_frequency = float(self.config.resolve('game.engage.frequency'))
  101. @property
  102. def seconds_frequency(self) -> typing.Optional[float]:
  103. return self._seconds_frequency
  104. def action(self, data) -> [Event]:
  105. kill = data['kill']
  106. target_subject_id = data['target_subject_id']
  107. target_subject = self.simulation.subjects.index[target_subject_id]
  108. target_position = data['target_position']
  109. events = list()
  110. events.append(FireEvent(
  111. shooter_subject_id=self.subject.id,
  112. target_position=target_position,
  113. ))
  114. # Must be check if target is not already dead (killed same cycle)
  115. if kill and COLLECTION_ALIVE in target_subject.collections:
  116. DieEvent.apply_subject_death(target_subject)
  117. events.append(DieEvent(
  118. shooter_subject_id=self.subject.id,
  119. shoot_subject_id=target_subject_id,
  120. ))
  121. return events
  122. def run(self, data):
  123. visible_subjects = data[self.visible_mechanism]['visible_subjects']
  124. if not visible_subjects:
  125. return
  126. # Manage selected target (can change, better visibility, etc ...)
  127. # Manage weapon munition to be able to fire
  128. # Manage fear/under fire ...
  129. # Manage weapon reload time
  130. # For dev fun, don't fire at random
  131. if random.randint(1, 3) == -1:
  132. # Executed but decided to fail
  133. self.last_execution_time = time.time()
  134. return False
  135. target_subject = random.choice(visible_subjects)
  136. kill = random.randint(0, 100) >= 75
  137. # Manage fire miss or touch (visibility, fear, opponent hiding, etc ...)
  138. return {
  139. 'kill': kill,
  140. 'target_subject_id': target_subject.id,
  141. 'target_position': target_subject.position,
  142. }