AntMoveBrainPart.py 8.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. from synergine.core.Core import Core
  2. from intelligine.shorcut.brain import get_brain_class
  3. from intelligine.simulation.object.brain.part.move.AntStar.ByPass import ByPass
  4. from intelligine.simulation.object.brain.part.move.AntStar.Host import Host
  5. from intelligine.simulation.object.brain.part.move.MoveBrainPart import MoveBrainPart
  6. from intelligine.synergy.event.move.direction import directions_modifiers, get_position_with_direction_decal
  7. from synergine_xyz.cst import POSITION
  8. from intelligine.core.exceptions import NoMolecule, ExplorationAlreadyResolved, MovementModeExpired
  9. from intelligine.cst import MOLECULE_SEARCHING, MODE_EXPLO, MODE_HOME, MODE, MODE_GOHOME, \
  10. EXPLORATION_VECTOR, MOLECULES_DIRECTION, PUT_FAIL_COUNT, MODE_GO_OUTSIDE, MOLECULE_SEARCHING_WAY, COL_PUT_OUTSIDE, \
  11. MODE_SEARCH_AROUND
  12. from intelligine.simulation.molecule.DirectionMolecule import DirectionMolecule
  13. class AntMoveBrainPart(MoveBrainPart):
  14. def __init__(self, host_brain):
  15. super().__init__(host_brain)
  16. self._exploration_vector = (0, 0)
  17. def _set_exploration_vector(self, new_vector):
  18. self._exploration_vector = new_vector
  19. self._context.metas.value.set(EXPLORATION_VECTOR,
  20. self._host_brain.get_host().get_id(),
  21. new_vector)
  22. @classmethod
  23. def get_direction(cls, context, object_id):
  24. move_mode = context.metas.value.get(MODE, object_id)
  25. if move_mode == MODE_GOHOME:
  26. try:
  27. return cls._get_direction_with_exploration_vector(context, object_id)
  28. except ExplorationAlreadyResolved:
  29. raise MovementModeExpired(mode=MODE_SEARCH_AROUND)
  30. else:
  31. try:
  32. return cls._get_direction_with_molecules(context, object_id)
  33. except NoMolecule:
  34. return super().get_direction(context, object_id)
  35. return super().get_direction(context, object_id)
  36. @classmethod
  37. def _get_direction_with_molecules(cls, context, object_id):
  38. object_point = context.metas.value.get(POSITION, object_id)
  39. molecule_type = context.metas.value.get(MOLECULE_SEARCHING, object_id)
  40. molecule_way = context.metas.value.get(MOLECULE_SEARCHING_WAY, object_id)
  41. try:
  42. direction = cls._get_molecule_direction_for_point(context, object_point, molecule_type, molecule_way)
  43. except NoMolecule:
  44. movement_mode = context.metas.value.get(MODE, object_id)
  45. if movement_mode == MODE_GO_OUTSIDE:
  46. raise
  47. if movement_mode == MODE_EXPLO:
  48. raise
  49. try:
  50. direction = cls._get_direction_of_molecule(context, object_point, molecule_type)
  51. except NoMolecule:
  52. raise
  53. return direction
  54. @staticmethod
  55. def _get_molecule_direction_for_point(context, point, molecule_type, molecule_way):
  56. return DirectionMolecule.get_direction_for_point(context, point, molecule_type, molecule_way)
  57. @staticmethod
  58. def _get_direction_of_molecule(context, point, molecule_type):
  59. search_molecule_in_points = context.get_around_points_of_point(point)
  60. try:
  61. best_molecule_direction = DirectionMolecule.get_best_molecule_direction_in(context,
  62. point,
  63. search_molecule_in_points,
  64. molecule_type)
  65. return best_molecule_direction
  66. except NoMolecule as err:
  67. raise err
  68. @classmethod
  69. def _get_direction_with_exploration_vector(cls, context, object_id):
  70. exploration_vector = context.metas.value.get(EXPLORATION_VECTOR, object_id)
  71. if exploration_vector == (0, 0):
  72. raise ExplorationAlreadyResolved()
  73. ant_star = cls._get_by_pass_brain(context, object_id)
  74. ant_star.advance()
  75. return ant_star.get_host().get_moved_to_direction()
  76. @classmethod
  77. def _get_by_pass_brain(cls, context, object_id):
  78. # We use an adaptation of AntStar
  79. exploration_vector = context.metas.value.get(EXPLORATION_VECTOR, object_id)
  80. home_vector = (-exploration_vector[0], -exploration_vector[1])
  81. ant_host = Host(context, object_id)
  82. return ByPass(ant_host, home_vector, context, object_id)
  83. def done(self):
  84. super().done()
  85. self._appose_molecule()
  86. self._check_context()
  87. self._apply_context()
  88. def _appose_molecule(self):
  89. if self._host.get_movement_molecule_gland().is_enabled():
  90. self._host.get_movement_molecule_gland().appose()
  91. def _check_context(self):
  92. """
  93. If was in exploration, and just found home smell;
  94. -> home mode (then, in this mode: no update vector, put food if food, etc)
  95. If was in home, and just loose home smell:
  96. -> exploration mode
  97. :param obj:
  98. :param context:
  99. :return:
  100. """
  101. movement_mode = self._host_brain.get_movement_mode()
  102. # TODO: Algo de depl. dans les brain part (ex. put)
  103. put_fail_count = self._context.metas.value.get(PUT_FAIL_COUNT, self._host.get_id(), allow_empty=True,
  104. empty_value=0)
  105. put_fail_count_max = Core.get_configuration_manager().get('ant.max_put_fail_count', 20)
  106. if movement_mode == MODE_GOHOME and self._on_home_smell(self._context, self._host.get_id()):
  107. self._arrived_at_home()
  108. if movement_mode == MODE_SEARCH_AROUND and self._on_home_smell(self._context, self._host.get_id()):
  109. self._arrived_at_home()
  110. elif movement_mode == MODE_HOME and not self._on_home_smell(self._context, self._host.get_id()):
  111. self._start_new_exploration()
  112. elif movement_mode == MODE_EXPLO and self._on_home_smell(self._context, self._host.get_id()):
  113. self._init_exploration_vector()
  114. elif movement_mode == MODE_HOME and put_fail_count >= put_fail_count_max:
  115. self._host.get_brain().switch_to_mode(MODE_GO_OUTSIDE)
  116. self._host._add_col(COL_PUT_OUTSIDE) # TODO: protege pas necessaire ?
  117. elif movement_mode == MODE_GO_OUTSIDE and not self._on_home_smell(self._context, self._host.get_id()):
  118. self._start_new_exploration()
  119. # TODO: sitch explo si rien a faire (rien a poser par exemple) et HOME
  120. @classmethod
  121. def _on_home_smell(cls, context, object_id):
  122. current_position = context.metas.value.get(POSITION, object_id)
  123. flavour = context.molecules().get_flavour(current_position)
  124. molecules = flavour.get_molecules_types(MOLECULES_DIRECTION)
  125. if not molecules:
  126. return False
  127. brain_class = get_brain_class(context, object_id)
  128. for smell_type in brain_class.get_home_smells():
  129. if smell_type in molecules:
  130. return True
  131. return False
  132. def _update_exploration_vector(self):
  133. just_move_vector = directions_modifiers[self._host_brain.get_host().get_previous_direction()]
  134. self._set_exploration_vector((self._exploration_vector[0] + just_move_vector[1],
  135. self._exploration_vector[1] + just_move_vector[2]))
  136. def _apply_context(self):
  137. movement_mode = self._host_brain.get_movement_mode()
  138. if movement_mode == MODE_EXPLO or movement_mode == MODE_GOHOME:
  139. self._update_exploration_vector()
  140. def _start_new_exploration(self):
  141. self._init_exploration_vector()
  142. self._host_brain.switch_to_mode(MODE_EXPLO)
  143. def _init_exploration_vector(self):
  144. # On vient de rentrer dans le monde exterieur, le vecteur de départ pointe vers la case précedente
  145. # qui est une case dans la forteresse.
  146. init_exploration_vector = get_position_with_direction_decal(self.get_host().get_previous_direction())
  147. self._set_exploration_vector(init_exploration_vector)
  148. def _arrived_at_home(self):
  149. self._host_brain.switch_to_mode(MODE_HOME)
  150. ant_star = self._get_by_pass_brain(self._context, self._host.get_id())
  151. ant_star.erase()