|  | @@ -1,8 +1,11 @@
 | 
	
		
			
			| 1 | 1 |  # coding: utf-8
 | 
	
		
			
			| 2 | 2 |  import typing
 | 
	
		
			
			|  | 3 | +from random import randint
 | 
	
		
			
			|  | 4 | +
 | 
	
		
			
			|  | 5 | +import time
 | 
	
		
			
			| 3 | 6 |  
 | 
	
		
			
			| 4 | 7 |  from synergine2.config import Config
 | 
	
		
			
			| 5 |  | -from synergine2.simulation import SimulationBehaviour
 | 
	
		
			
			|  | 8 | +from synergine2.simulation import SimulationBehaviour, Subject
 | 
	
		
			
			| 6 | 9 |  from synergine2.simulation import SubjectBehaviour
 | 
	
		
			
			| 7 | 10 |  from synergine2.simulation import SubjectMechanism
 | 
	
		
			
			| 8 | 11 |  from synergine2.simulation import Intention
 | 
	
	
		
			
			|  | @@ -12,10 +15,17 @@ from synergine2_xyz.simulation import XYZSimulation
 | 
	
		
			
			| 12 | 15 |  
 | 
	
		
			
			| 13 | 16 |  
 | 
	
		
			
			| 14 | 17 |  class MoveToIntention(Intention):
 | 
	
		
			
			| 15 |  | -    def __init__(self, move_to: typing.Tuple[int, int]) -> None:
 | 
	
		
			
			|  | 18 | +    def __init__(
 | 
	
		
			
			|  | 19 | +        self,
 | 
	
		
			
			|  | 20 | +        move_to: typing.Tuple[int, int],
 | 
	
		
			
			|  | 21 | +        start_time: float,
 | 
	
		
			
			|  | 22 | +    ) -> None:
 | 
	
		
			
			| 16 | 23 |          self.move_to = move_to
 | 
	
		
			
			| 17 | 24 |          self.path = []  # type: typing.List[typing.Tuple[int, int]]
 | 
	
		
			
			| 18 | 25 |          self.path_progression = -1  # type: int
 | 
	
		
			
			|  | 26 | +        self.last_intention_time = start_time
 | 
	
		
			
			|  | 27 | +        self.just_reach = False
 | 
	
		
			
			|  | 28 | +        self.initial = True
 | 
	
		
			
			| 19 | 29 |  
 | 
	
		
			
			| 20 | 30 |  
 | 
	
		
			
			| 21 | 31 |  class RequestMoveBehaviour(SimulationBehaviour):
 | 
	
	
		
			
			|  | @@ -44,7 +54,7 @@ class RequestMoveBehaviour(SimulationBehaviour):
 | 
	
		
			
			| 44 | 54 |  
 | 
	
		
			
			| 45 | 55 |          try:
 | 
	
		
			
			| 46 | 56 |              subject = self.simulation.subjects.index[subject_id]
 | 
	
		
			
			| 47 |  | -            subject.intentions.set(self.move_intention_class(move_to))
 | 
	
		
			
			|  | 57 | +            subject.intentions.set(self.move_intention_class(move_to, start_time=time.time()))
 | 
	
		
			
			| 48 | 58 |          except KeyError:
 | 
	
		
			
			| 49 | 59 |              # TODO: log error here
 | 
	
		
			
			| 50 | 60 |              pass
 | 
	
	
		
			
			|  | @@ -89,6 +99,9 @@ class MoveToMechanism(SubjectMechanism):
 | 
	
		
			
			| 89 | 99 |  
 | 
	
		
			
			| 90 | 100 |              return {
 | 
	
		
			
			| 91 | 101 |                  'new_path': new_path,
 | 
	
		
			
			|  | 102 | +                'last_intention_time': move.last_intention_time,
 | 
	
		
			
			|  | 103 | +                'just_reach': move.just_reach,
 | 
	
		
			
			|  | 104 | +                'initial': move.initial,
 | 
	
		
			
			| 92 | 105 |              }
 | 
	
		
			
			| 93 | 106 |  
 | 
	
		
			
			| 94 | 107 |          except IndexError:  # TODO: Specialize ? No movement left
 | 
	
	
		
			
			|  | @@ -97,7 +110,30 @@ class MoveToMechanism(SubjectMechanism):
 | 
	
		
			
			| 97 | 110 |              return None
 | 
	
		
			
			| 98 | 111 |  
 | 
	
		
			
			| 99 | 112 |  
 | 
	
		
			
			| 100 |  | -class MoveEvent(Event):
 | 
	
		
			
			|  | 113 | +class FinishMoveEvent(Event):
 | 
	
		
			
			|  | 114 | +    def __init__(
 | 
	
		
			
			|  | 115 | +        self,
 | 
	
		
			
			|  | 116 | +        subject_id: int,
 | 
	
		
			
			|  | 117 | +        from_position: typing.Tuple[int, int],
 | 
	
		
			
			|  | 118 | +        to_position: typing.Tuple[int, int],
 | 
	
		
			
			|  | 119 | +        *args,
 | 
	
		
			
			|  | 120 | +        **kwargs
 | 
	
		
			
			|  | 121 | +    ):
 | 
	
		
			
			|  | 122 | +        super().__init__(*args, **kwargs)
 | 
	
		
			
			|  | 123 | +        self.subject_id = subject_id
 | 
	
		
			
			|  | 124 | +        self.from_position = from_position
 | 
	
		
			
			|  | 125 | +        self.to_position = to_position
 | 
	
		
			
			|  | 126 | +
 | 
	
		
			
			|  | 127 | +    def repr_debug(self) -> str:
 | 
	
		
			
			|  | 128 | +        return '{}: subject_id:{}, from_position:{} to_position: {}'.format(
 | 
	
		
			
			|  | 129 | +            type(self).__name__,
 | 
	
		
			
			|  | 130 | +            self.subject_id,
 | 
	
		
			
			|  | 131 | +            self.from_position,
 | 
	
		
			
			|  | 132 | +            self.to_position,
 | 
	
		
			
			|  | 133 | +        )
 | 
	
		
			
			|  | 134 | +
 | 
	
		
			
			|  | 135 | +
 | 
	
		
			
			|  | 136 | +class StartMoveEvent(Event):
 | 
	
		
			
			| 101 | 137 |      def __init__(
 | 
	
		
			
			| 102 | 138 |          self,
 | 
	
		
			
			| 103 | 139 |          subject_id: int,
 | 
	
	
		
			
			|  | @@ -124,12 +160,30 @@ class MoveToBehaviour(SubjectBehaviour):
 | 
	
		
			
			| 124 | 160 |      use = [MoveToMechanism]
 | 
	
		
			
			| 125 | 161 |      move_to_mechanism = MoveToMechanism
 | 
	
		
			
			| 126 | 162 |  
 | 
	
		
			
			|  | 163 | +    def __init__(
 | 
	
		
			
			|  | 164 | +        self,
 | 
	
		
			
			|  | 165 | +        config: Config,
 | 
	
		
			
			|  | 166 | +        simulation: Simulation,
 | 
	
		
			
			|  | 167 | +        subject: Subject,
 | 
	
		
			
			|  | 168 | +    ) -> None:
 | 
	
		
			
			|  | 169 | +        super().__init__(config, simulation, subject)
 | 
	
		
			
			|  | 170 | +        self._duration = float(self.config.resolve('game.move.walk_ref_time'))
 | 
	
		
			
			|  | 171 | +
 | 
	
		
			
			| 127 | 172 |      def run(self, data):
 | 
	
		
			
			| 128 | 173 |          # TODO: on fait vraiment rien ici ? Note: meme si il n'y a pas de new_path, l'action doit s'effectuer
 | 
	
		
			
			| 129 | 174 |          # du moment qu'il y a une intention de move
 | 
	
		
			
			| 130 | 175 |          move_to_data = data[self.move_to_mechanism]
 | 
	
		
			
			| 131 | 176 |          if move_to_data:
 | 
	
		
			
			|  | 177 | +
 | 
	
		
			
			|  | 178 | +            if time.time() - move_to_data['last_intention_time'] >= self._duration:
 | 
	
		
			
			|  | 179 | +                move_to_data['reach_next'] = True
 | 
	
		
			
			|  | 180 | +            elif move_to_data['just_reach'] or move_to_data['initial']:
 | 
	
		
			
			|  | 181 | +                move_to_data['reach_next'] = False
 | 
	
		
			
			|  | 182 | +            else:
 | 
	
		
			
			|  | 183 | +                return False
 | 
	
		
			
			|  | 184 | +
 | 
	
		
			
			| 132 | 185 |              return move_to_data
 | 
	
		
			
			|  | 186 | +
 | 
	
		
			
			| 133 | 187 |          return False
 | 
	
		
			
			| 134 | 188 |  
 | 
	
		
			
			| 135 | 189 |      def action(self, data) -> [Event]:
 | 
	
	
		
			
			|  | @@ -144,16 +198,25 @@ class MoveToBehaviour(SubjectBehaviour):
 | 
	
		
			
			| 144 | 198 |                  move.path = new_path
 | 
	
		
			
			| 145 | 199 |                  move.path_progression = -1
 | 
	
		
			
			| 146 | 200 |  
 | 
	
		
			
			| 147 |  | -            # TODO: progression et lorsque "vraiment avance d'une case" envoyer le Move
 | 
	
		
			
			| 148 |  | -            # pour le moment on move direct
 | 
	
		
			
			| 149 |  | -            # TODO: fin de path
 | 
	
		
			
			| 150 |  | -            move.path_progression += 1
 | 
	
		
			
			| 151 |  | -            new_position = move.path[move.path_progression]
 | 
	
		
			
			| 152 | 201 |              previous_position = self.subject.position
 | 
	
		
			
			| 153 |  | -            self.subject.position = new_position
 | 
	
		
			
			|  | 202 | +            new_position = move.path[move.path_progression + 1]
 | 
	
		
			
			|  | 203 | +
 | 
	
		
			
			|  | 204 | +            if data['reach_next']:
 | 
	
		
			
			|  | 205 | +                # TODO: fin de path
 | 
	
		
			
			|  | 206 | +                move.path_progression += 1
 | 
	
		
			
			|  | 207 | +                self.subject.position = new_position
 | 
	
		
			
			|  | 208 | +                move.last_intention_time = time.time()
 | 
	
		
			
			|  | 209 | +                move.just_reach = True
 | 
	
		
			
			|  | 210 | +                event = FinishMoveEvent(self.subject.id, previous_position, new_position)
 | 
	
		
			
			|  | 211 | +            else:
 | 
	
		
			
			|  | 212 | +                move.just_reach = False
 | 
	
		
			
			|  | 213 | +                event = StartMoveEvent(self.subject.id, previous_position, new_position)
 | 
	
		
			
			|  | 214 | +
 | 
	
		
			
			|  | 215 | +            move.initial = False
 | 
	
		
			
			|  | 216 | +            # Note: Need to explicitly set to update shared data
 | 
	
		
			
			| 154 | 217 |              self.subject.intentions.set(move)
 | 
	
		
			
			| 155 | 218 |  
 | 
	
		
			
			| 156 |  | -            return [MoveEvent(self.subject.id, previous_position, new_position)]
 | 
	
		
			
			|  | 219 | +            return [event]
 | 
	
		
			
			| 157 | 220 |  
 | 
	
		
			
			| 158 | 221 |          except KeyError:
 | 
	
		
			
			| 159 | 222 |              # TODO: log ? Il devrait y avoir un move puisque data du run/mechanism !
 |