|  | @@ -2,9 +2,15 @@ from synergine.synergy.event.Action import Action
 | 
	
		
			
			| 2 | 2 |  from intelligine.synergy.event.move.MoveEvent import MoveEvent
 | 
	
		
			
			| 3 | 3 |  from random import randint, choice, randrange
 | 
	
		
			
			| 4 | 4 |  from xyzworld.cst import POSITION, POSITIONS
 | 
	
		
			
			| 5 |  | -from intelligine.cst import PREVIOUS_DIRECTION, BLOCKED_SINCE
 | 
	
		
			
			|  | 5 | +from intelligine.cst import PREVIOUS_DIRECTION, BLOCKED_SINCE, MOVE_MODE, MOVE_MODE_GOHOME, MOVE_MODE_EXPLO, \
 | 
	
		
			
			|  | 6 | +                            PHEROMON_DIR_EXPLO, PHEROMON_DIR_HOME, PHEROMON_DIRECTION, \
 | 
	
		
			
			|  | 7 | +    COL_TRANSPORTER_NOT_CARRYING, COL_TRANSPORTER_CARRYING
 | 
	
		
			
			| 6 | 8 |  from intelligine.synergy.event.move.direction import directions_same_level, directions_modifiers, directions_slighty
 | 
	
		
			
			| 7 |  | -from intelligine.core.exceptions import NoPheromoneMove
 | 
	
		
			
			|  | 9 | +from intelligine.core.exceptions import NoPheromoneMove, NoPheromone, BestPheromoneHere
 | 
	
		
			
			|  | 10 | +import operator
 | 
	
		
			
			|  | 11 | +from intelligine.simulation.pheromone.DirectionPheromone import DirectionPheromone
 | 
	
		
			
			|  | 12 | +from xyzworld.geometry import get_degree_from_north
 | 
	
		
			
			|  | 13 | +from intelligine.synergy.event.move.direction import get_direction_for_degrees, directions_opposites
 | 
	
		
			
			| 8 | 14 |  
 | 
	
		
			
			| 9 | 15 |  
 | 
	
		
			
			| 10 | 16 |  class MoveAction(Action):
 | 
	
	
		
			
			|  | @@ -12,28 +18,62 @@ class MoveAction(Action):
 | 
	
		
			
			| 12 | 18 |      _listen = MoveEvent
 | 
	
		
			
			| 13 | 19 |  
 | 
	
		
			
			| 14 | 20 |      def __init__(self, object_id, parameters):
 | 
	
		
			
			| 15 |  | -      super().__init__(object_id, parameters)
 | 
	
		
			
			| 16 |  | -      self._move_to_point = None
 | 
	
		
			
			| 17 |  | -      self._move_to_direction = None
 | 
	
		
			
			|  | 21 | +        super().__init__(object_id, parameters)
 | 
	
		
			
			|  | 22 | +        self._move_to_point = None
 | 
	
		
			
			|  | 23 | +        self._move_to_direction = None
 | 
	
		
			
			| 18 | 24 |  
 | 
	
		
			
			| 19 | 25 |      def prepare(self, context):
 | 
	
		
			
			| 20 |  | -      object_point = context.metas.value.get(POSITION, self._object_id)
 | 
	
		
			
			| 21 |  | -      try:
 | 
	
		
			
			| 22 |  | -          choosed_direction_name, choosed_direction_point = self._get_pheromone_direction_point(context, object_point)
 | 
	
		
			
			| 23 |  | -      except NoPheromoneMove:
 | 
	
		
			
			| 24 |  | -          choosed_direction_name, choosed_direction_point = self._get_random_direction_point(context, object_point)
 | 
	
		
			
			| 25 |  | -      if self._direction_point_is_possible(context, choosed_direction_point):
 | 
	
		
			
			| 26 |  | -        self._move_to_point = choosed_direction_point
 | 
	
		
			
			| 27 |  | -        self._move_to_direction = choosed_direction_name
 | 
	
		
			
			| 28 |  | -
 | 
	
		
			
			| 29 |  | -    def _get_random_direction_point(self, context, reference_point):
 | 
	
		
			
			| 30 |  | -        z, x, y = reference_point
 | 
	
		
			
			| 31 |  | -        direction_name = self._get_random_direction_name(context)
 | 
	
		
			
			| 32 |  | -        directions_modifier = directions_modifiers[direction_name]
 | 
	
		
			
			| 33 |  | -        new_position = (z + directions_modifier[0], x + directions_modifier[1], y + directions_modifier[2])
 | 
	
		
			
			| 34 |  | -        return (direction_name, new_position)
 | 
	
		
			
			|  | 26 | +        object_point = context.metas.value.get(POSITION, self._object_id)
 | 
	
		
			
			|  | 27 | +
 | 
	
		
			
			|  | 28 | +        try:
 | 
	
		
			
			|  | 29 | +            direction = self._get_direction_with_pheromones(context, object_point)
 | 
	
		
			
			|  | 30 | +        except NoPheromone:
 | 
	
		
			
			|  | 31 | +            direction = self._get_random_direction(context)
 | 
	
		
			
			|  | 32 | +
 | 
	
		
			
			|  | 33 | +        move_to_point = self._get_point_for_direction(object_point, direction)
 | 
	
		
			
			|  | 34 | +        if self._direction_point_is_possible(context, move_to_point):
 | 
	
		
			
			|  | 35 | +            self._move_to_point = move_to_point
 | 
	
		
			
			|  | 36 | +            self._move_to_direction = direction
 | 
	
		
			
			|  | 37 | +        else:
 | 
	
		
			
			|  | 38 | +            # TODO: mettre self._dont_move = True ?
 | 
	
		
			
			|  | 39 | +            pass
 | 
	
		
			
			|  | 40 | +
 | 
	
		
			
			|  | 41 | +    def _get_direction_with_pheromones(self, context, object_point):
 | 
	
		
			
			|  | 42 | +        # TODO: Placer directnement pheromone type dans les metas
 | 
	
		
			
			|  | 43 | +        object_movement_mode = context.metas.value.get(MOVE_MODE, self._object_id)
 | 
	
		
			
			|  | 44 | +        pheromone_type = DirectionPheromone.get_pheromone_type_for_move_mode(object_movement_mode)
 | 
	
		
			
			|  | 45 | +        try:
 | 
	
		
			
			|  | 46 | +            direction = self._get_pheromone_direction_for_point(context, object_point, pheromone_type)
 | 
	
		
			
			|  | 47 | +        except NoPheromone:
 | 
	
		
			
			|  | 48 | +            direction = self._get_direction_of_pheromone(context, object_point, pheromone_type)
 | 
	
		
			
			|  | 49 | +        return direction
 | 
	
		
			
			|  | 50 | +
 | 
	
		
			
			|  | 51 | +    @staticmethod
 | 
	
		
			
			|  | 52 | +    def _get_pheromone_direction_for_point(context, point, pheromone_type):
 | 
	
		
			
			|  | 53 | +        return DirectionPheromone.get_direction_for_point(context, point, pheromone_type)
 | 
	
		
			
			|  | 54 | +
 | 
	
		
			
			|  | 55 | +    @staticmethod
 | 
	
		
			
			|  | 56 | +    def _get_direction_of_pheromone(context, point, pheromone_type):
 | 
	
		
			
			|  | 57 | +        search_pheromone_distance = 1  # TODO: config
 | 
	
		
			
			|  | 58 | +        search_pheromone_in_points = context.get_arround_points_of(point, distance=search_pheromone_distance)
 | 
	
		
			
			|  | 59 | +        try:
 | 
	
		
			
			|  | 60 | +            # TODO: ? Avoir plutot un DirectionPheromone.get_best_pheromone_direction_in ?
 | 
	
		
			
			|  | 61 | +            best_pheromone_direction = DirectionPheromone.get_best_pheromone_direction_in(context,
 | 
	
		
			
			|  | 62 | +                                                                                          point,
 | 
	
		
			
			|  | 63 | +                                                                                          search_pheromone_in_points,
 | 
	
		
			
			|  | 64 | +                                                                                          pheromone_type)
 | 
	
		
			
			|  | 65 | +            return best_pheromone_direction
 | 
	
		
			
			|  | 66 | +        except NoPheromone as err:
 | 
	
		
			
			|  | 67 | +            raise err
 | 
	
		
			
			|  | 68 | +
 | 
	
		
			
			|  | 69 | +    # def _get_random_direction_point(self, context, reference_point):
 | 
	
		
			
			|  | 70 | +    #     z, x, y = reference_point
 | 
	
		
			
			|  | 71 | +    #     direction_name = self._get_random_direction_name(context)
 | 
	
		
			
			|  | 72 | +    #     directions_modifier = directions_modifiers[direction_name]
 | 
	
		
			
			|  | 73 | +    #     new_position = (z + directions_modifier[0], x + directions_modifier[1], y + directions_modifier[2])
 | 
	
		
			
			|  | 74 | +    #     return (direction_name, new_position)
 | 
	
		
			
			| 35 | 75 |  
 | 
	
		
			
			| 36 |  | -    def _get_random_direction_name(self, context):
 | 
	
		
			
			|  | 76 | +    def _get_random_direction(self, context):
 | 
	
		
			
			| 37 | 77 |          try:
 | 
	
		
			
			| 38 | 78 |              blocked_since = context.metas.value.get(BLOCKED_SINCE, self._object_id)
 | 
	
		
			
			| 39 | 79 |          except KeyError:
 | 
	
	
		
			
			|  | @@ -59,14 +99,45 @@ class MoveAction(Action):
 | 
	
		
			
			| 59 | 99 |  
 | 
	
		
			
			| 60 | 100 |          return direction_name
 | 
	
		
			
			| 61 | 101 |  
 | 
	
		
			
			| 62 |  | -    def _direction_point_is_possible(self, context, direction_point):
 | 
	
		
			
			|  | 102 | +    @staticmethod
 | 
	
		
			
			|  | 103 | +    def _get_point_for_direction(reference_point, direction):
 | 
	
		
			
			|  | 104 | +        # TODO: mettre une fonction cote direction.py pour appliquer le modifier.
 | 
	
		
			
			|  | 105 | +        z, x, y = reference_point
 | 
	
		
			
			|  | 106 | +        directions_modifier = directions_modifiers[direction]
 | 
	
		
			
			|  | 107 | +        return z + directions_modifier[0], x + directions_modifier[1], y + directions_modifier[2]
 | 
	
		
			
			|  | 108 | +
 | 
	
		
			
			|  | 109 | +    @staticmethod
 | 
	
		
			
			|  | 110 | +    def _direction_point_is_possible(context, direction_point):
 | 
	
		
			
			| 63 | 111 |          return context.position_is_penetrable(direction_point)
 | 
	
		
			
			| 64 | 112 |  
 | 
	
		
			
			| 65 | 113 |      def run(self, obj, context, synergy_manager):
 | 
	
		
			
			| 66 |  | -        if self._move_to_point is not None:
 | 
	
		
			
			|  | 114 | +        if self._move_to_point is not None and self._move_to_direction != 14: # TODO: il ne faut pas choisir une direction 14.
 | 
	
		
			
			| 67 | 115 |              obj.set_position(self._move_to_point)
 | 
	
		
			
			|  | 116 | +            #direction_from = directions_opposites[self._move_to_direction]
 | 
	
		
			
			|  | 117 | +            #obj.set_direction_from(direction_from)
 | 
	
		
			
			| 68 | 118 |              context.metas.value.set(PREVIOUS_DIRECTION, self._object_id, self._move_to_direction)
 | 
	
		
			
			| 69 | 119 |              context.metas.value.set(BLOCKED_SINCE, self._object_id, 0)
 | 
	
		
			
			|  | 120 | +            self._appose_pheromone(obj, context)
 | 
	
		
			
			|  | 121 | +
 | 
	
		
			
			|  | 122 | +            # TEST: le temps de tout tester
 | 
	
		
			
			|  | 123 | +            if self._move_to_point == (0, 5, 5) and obj.is_carrying():
 | 
	
		
			
			|  | 124 | +                obj_transported = obj.get_carried()
 | 
	
		
			
			|  | 125 | +                obj_transported.set_carried_by(None)
 | 
	
		
			
			|  | 126 | +                obj.put_carry(obj_transported, (-1, 0, 0))
 | 
	
		
			
			|  | 127 | +                obj.get_brain().switch_to_mode(MOVE_MODE_EXPLO)
 | 
	
		
			
			|  | 128 | +                context.metas.collections.add_remove(obj.get_id(),
 | 
	
		
			
			|  | 129 | +                    COL_TRANSPORTER_NOT_CARRYING, COL_TRANSPORTER_CARRYING)
 | 
	
		
			
			|  | 130 | +
 | 
	
		
			
			|  | 131 | +            # TMP: Devra etre un event et une action
 | 
	
		
			
			|  | 132 | +            # if self._move_to_point == (0, 5, 5):  # position de depart
 | 
	
		
			
			|  | 133 | +            #     if len(obj._carried):
 | 
	
		
			
			|  | 134 | +            #         obj_transported = obj.get_carried()
 | 
	
		
			
			|  | 135 | +            #         obj_transported.set_carried_by(None)
 | 
	
		
			
			|  | 136 | +            #         obj.put_carry(obj_transported, (-1, 5, 5))
 | 
	
		
			
			|  | 137 | +            #         context.metas.collections.add_remove(obj.get_id(), COL_TRANSPORTER_NOT_CARRYING, COL_TRANSPORTER_CARRYING)
 | 
	
		
			
			|  | 138 | +            #     obj.set_movement_mode(MOVE_MODE_EXPLO)
 | 
	
		
			
			|  | 139 | +
 | 
	
		
			
			|  | 140 | +
 | 
	
		
			
			| 70 | 141 |          else:
 | 
	
		
			
			| 71 | 142 |              try:
 | 
	
		
			
			| 72 | 143 |                  blocked_since = context.metas.value.get(BLOCKED_SINCE, self._object_id)
 | 
	
	
		
			
			|  | @@ -74,6 +145,66 @@ class MoveAction(Action):
 | 
	
		
			
			| 74 | 145 |                  blocked_since = 0
 | 
	
		
			
			| 75 | 146 |              context.metas.value.set(BLOCKED_SINCE, self._object_id, blocked_since+1)
 | 
	
		
			
			| 76 | 147 |  
 | 
	
		
			
			| 77 |  | -    def _get_pheromone_direction_point(self, context, object_point):
 | 
	
		
			
			|  | 148 | +    # def _get_pheromone_direction_point(self, context, object_point):
 | 
	
		
			
			|  | 149 | +    #     try:
 | 
	
		
			
			|  | 150 | +    #         blocked_since = context.metas.value.get(BLOCKED_SINCE, self._object_id)
 | 
	
		
			
			|  | 151 | +    #     except KeyError:
 | 
	
		
			
			|  | 152 | +    #         blocked_since = 0
 | 
	
		
			
			|  | 153 | +    #     if blocked_since > 3:
 | 
	
		
			
			|  | 154 | +    #         raise NoPheromoneMove()
 | 
	
		
			
			|  | 155 | +    #     # Si on explore, on cherche pheromone d'explo
 | 
	
		
			
			|  | 156 | +    #     # si on rentre a home, on cherche pheromone d'home...
 | 
	
		
			
			|  | 157 | +    #     # TODO: code arrache
 | 
	
		
			
			|  | 158 | +    #     object_movement_mode = context.metas.value.get(MOVE_MODE, self._object_id)
 | 
	
		
			
			|  | 159 | +    #     if object_movement_mode == MOVE_MODE_EXPLO:
 | 
	
		
			
			|  | 160 | +    #         pheromone_direction_type = PHEROMON_DIR_EXPLO
 | 
	
		
			
			|  | 161 | +    #     elif object_movement_mode == MOVE_MODE_GOHOME:
 | 
	
		
			
			|  | 162 | +    #         pheromone_direction_type = PHEROMON_DIR_HOME
 | 
	
		
			
			|  | 163 | +    #
 | 
	
		
			
			|  | 164 | +    #     sniff_points = context.get_arround_points_of(object_point, distance=0)
 | 
	
		
			
			|  | 165 | +    #     # Faire un compile des infos de pheromones
 | 
	
		
			
			|  | 166 | +    #
 | 
	
		
			
			|  | 167 | +    #     directions = {}
 | 
	
		
			
			|  | 168 | +    #     for sniff_point in sniff_points:
 | 
	
		
			
			|  | 169 | +    #         info = context.pheromones().get_info(sniff_point,
 | 
	
		
			
			|  | 170 | +    #                                              [PHEROMON_DIRECTION, pheromone_direction_type],
 | 
	
		
			
			|  | 171 | +    #                                              allow_empty=True,
 | 
	
		
			
			|  | 172 | +    #                                              empty_value={})
 | 
	
		
			
			|  | 173 | +    #         for direction in info:
 | 
	
		
			
			|  | 174 | +    #             if direction not in directions:
 | 
	
		
			
			|  | 175 | +    #                 directions[direction] = info[direction]
 | 
	
		
			
			|  | 176 | +    #             else:
 | 
	
		
			
			|  | 177 | +    #                 directions[direction] += info[direction]
 | 
	
		
			
			|  | 178 | +    #     if len(directions):
 | 
	
		
			
			|  | 179 | +    #         sorted_directions = sorted(directions.items(), key=operator.itemgetter(1))
 | 
	
		
			
			|  | 180 | +    #         sorted_directions.reverse()
 | 
	
		
			
			|  | 181 | +    #         #best_direction_name = sorted_directions[0][0]
 | 
	
		
			
			|  | 182 | +    #         best_direction_level = sorted_directions[0][1]
 | 
	
		
			
			|  | 183 | +    #         best_direction_names = [direction for direction in directions \
 | 
	
		
			
			|  | 184 | +    #                                if directions[direction] == best_direction_level]
 | 
	
		
			
			|  | 185 | +    #         # Si plusieurs best directions, choisir mm direction que la precedente
 | 
	
		
			
			|  | 186 | +    #         # si y a pas, au hasard.
 | 
	
		
			
			|  | 187 | +    #         last_dir_name = context.metas.value.get(PREVIOUS_DIRECTION, self._object_id)
 | 
	
		
			
			|  | 188 | +    #         if last_dir_name in best_direction_names:
 | 
	
		
			
			|  | 189 | +    #             direction_name = last_dir_name
 | 
	
		
			
			|  | 190 | +    #         else:
 | 
	
		
			
			|  | 191 | +    #             direction_name = choice(best_direction_names)
 | 
	
		
			
			|  | 192 | +    #
 | 
	
		
			
			|  | 193 | +    #         # DRY
 | 
	
		
			
			|  | 194 | +    #         z, x, y = object_point
 | 
	
		
			
			|  | 195 | +    #         directions_modifier = directions_modifiers[direction_name]
 | 
	
		
			
			|  | 196 | +    #         new_position = (z + directions_modifier[0], x + directions_modifier[1], y + directions_modifier[2])
 | 
	
		
			
			|  | 197 | +    #         return (direction_name, new_position)
 | 
	
		
			
			|  | 198 | +    #
 | 
	
		
			
			|  | 199 | +    #         pass
 | 
	
		
			
			|  | 200 | +    #     raise NoPheromoneMove()
 | 
	
		
			
			| 78 | 201 |  
 | 
	
		
			
			| 79 |  | -        raise NoPheromoneMove()
 | 
	
		
			
			|  | 202 | +    def _appose_pheromone(self, obj, context):
 | 
	
		
			
			|  | 203 | +        # TODO: Cette action de pheromone doit etre une surcharge de Move afin d'avoir une Action Move generique.
 | 
	
		
			
			|  | 204 | +        obj.get_brain().host_moved()
 | 
	
		
			
			|  | 205 | +        try:
 | 
	
		
			
			|  | 206 | +            DirectionPheromone.appose(context,
 | 
	
		
			
			|  | 207 | +                                      obj.get_position(),
 | 
	
		
			
			|  | 208 | +                                      obj.get_movement_pheromone_gland().get_movement_molecules())
 | 
	
		
			
			|  | 209 | +        except BestPheromoneHere as best_pheromone_here:
 | 
	
		
			
			|  | 210 | +            obj.get_brain().set_distance_from_objective(best_pheromone_here.get_best_distance())
 |