Browse Source

engulf: Search food is prior than explore

Bastien Sevajol 7 years ago
parent
commit
fb172365e8
3 changed files with 82 additions and 10 deletions
  1. 70 8
      sandbox/engulf/behaviour.py
  2. 2 2
      synergine2/simulation.py
  3. 10 0
      synergine2/xyz.py

+ 70 - 8
sandbox/engulf/behaviour.py View File

@@ -6,7 +6,8 @@ from sandbox.engulf.const import COLLECTION_GRASS
6 6
 from synergine2.simulation import SubjectBehaviour, SimulationMechanism, SimulationBehaviour, SubjectBehaviourSelector
7 7
 from synergine2.simulation import Event
8 8
 from synergine2.utils import ChunkManager
9
-from synergine2.xyz import ProximitySubjectMechanism, DIRECTIONS, DIRECTION_SLIGHTLY
9
+from synergine2.xyz import ProximitySubjectMechanism, DIRECTIONS, DIRECTION_SLIGHTLY, DIRECTION_FROM_NORTH_DEGREES, \
10
+    get_direction_from_north_degree
10 11
 from synergine2.xyz_utils import get_around_positions_of_positions, get_around_positions_of, get_position_for_direction
11 12
 
12 13
 
@@ -148,7 +149,19 @@ class SearchFood(SubjectBehaviour):
148 149
     use = [EatableDirectProximityMechanism]
149 150
 
150 151
     def run(self, data):
151
-        pass
152
+        if not data[EatableDirectProximityMechanism]:
153
+            return False
154
+
155
+        direction_degrees = [d['direction'] for d in data[EatableDirectProximityMechanism]]
156
+        return get_direction_from_north_degree(choice(direction_degrees))
157
+
158
+    def action(self, data) -> [Event]:
159
+        direction = data
160
+        position = get_position_for_direction(self.subject.position, direction)
161
+        self.subject.position = position
162
+        self.subject.previous_direction = direction
163
+
164
+        return [MoveTo(self.subject.id, position)]
152 165
 
153 166
 
154 167
 class Eat(SubjectBehaviour):
@@ -165,6 +178,9 @@ class Explore(SubjectBehaviour):
165 178
     """
166 179
     use = []
167 180
 
181
+    def run(self, data):
182
+        return True  # for now, want move every time
183
+
168 184
     def action(self, data) -> [Event]:
169 185
         direction = self.get_random_direction()
170 186
         position = get_position_for_direction(self.subject.position, direction)
@@ -173,9 +189,6 @@ class Explore(SubjectBehaviour):
173 189
 
174 190
         return [MoveTo(self.subject.id, position)]
175 191
 
176
-    def run(self, data):
177
-        return True  # for now, want move every time
178
-
179 192
     def get_random_direction(self):
180 193
         if not self.subject.previous_direction:
181 194
             return choice(DIRECTIONS)
@@ -194,6 +207,55 @@ class CellBehaviourSelector(SubjectBehaviourSelector):
194 207
 
195 208
     def reduce_behaviours(
196 209
         self,
197
-        behaviours: typing.Dict[typing.Type[SubjectBehaviour], dict],
198
-    ) -> typing.Dict[typing.Type[SubjectBehaviour], dict]:
199
-        return behaviours  # TODO: code it
210
+        behaviours: typing.Dict[typing.Type[SubjectBehaviour], object],
211
+    ) -> typing.Dict[typing.Type[SubjectBehaviour], object]:
212
+        reduced_behaviours = {}  # type: typing.Dict[typing.Type[SubjectBehaviour], object]
213
+
214
+        for behaviour_class, behaviour_data in behaviours.items():
215
+            if not self.behaviour_class_in_sublist(behaviour_class):
216
+                reduced_behaviours[behaviour_class] = behaviour_data
217
+            elif self.behaviour_class_is_prior(behaviour_class, behaviours):
218
+                reduced_behaviours[behaviour_class] = behaviour_data
219
+
220
+        return reduced_behaviours
221
+
222
+    def behaviour_class_in_sublist(self, behaviour_class: typing.Type[SubjectBehaviour]) -> bool:
223
+        for sublist in self.behaviour_hierarchy:
224
+            if behaviour_class in sublist:
225
+                return True
226
+        return False
227
+
228
+    def behaviour_class_is_prior(
229
+        self,
230
+        behaviour_class: typing.Type[SubjectBehaviour],
231
+        behaviours: typing.Dict[typing.Type[SubjectBehaviour], object],
232
+    ) -> bool:
233
+        for sublist in self.behaviour_hierarchy:
234
+            if behaviour_class in sublist:
235
+                behaviour_position = sublist.index(behaviour_class)
236
+                other_behaviour_top_position = self.get_other_behaviour_top_position(
237
+                    behaviour_class,
238
+                    behaviours,
239
+                    sublist,
240
+                )
241
+                if other_behaviour_top_position is not None and behaviour_position > other_behaviour_top_position:
242
+                    return False
243
+        return True
244
+
245
+    def get_other_behaviour_top_position(
246
+        self,
247
+        exclude_behaviour_class,
248
+        behaviours,
249
+        sublist,
250
+    ) -> typing.Union[None, int]:
251
+        position = None
252
+        for behaviour_class in behaviours.keys():
253
+            if behaviour_class != exclude_behaviour_class:
254
+                try:
255
+                    behaviour_position = sublist.index(behaviour_class)
256
+                except ValueError:
257
+                    pass
258
+                if position is None or behaviour_position < position:
259
+                    position = behaviour_position
260
+
261
+        return position

+ 2 - 2
synergine2/simulation.py View File

@@ -222,6 +222,6 @@ class SimulationBehaviour(BaseObject):
222 222
 class SubjectBehaviourSelector(BaseObject):
223 223
     def reduce_behaviours(
224 224
         self,
225
-        behaviours: typing.Dict[typing.Type[SubjectBehaviour], dict],
226
-    ) -> typing.Dict[typing.Type[SubjectBehaviour], dict]:
225
+        behaviours: typing.Dict[typing.Type[SubjectBehaviour], object],
226
+    ) -> typing.Dict[typing.Type[SubjectBehaviour], object]:
227 227
         raise NotImplementedError()

+ 10 - 0
synergine2/xyz.py View File

@@ -204,3 +204,13 @@ class XYZSubjects(Subjects):
204 204
 
205 205
 class Simulation(BaseSimulation):
206 206
     accepted_subject_class = XYZSubjects
207
+
208
+
209
+def get_direction_from_north_degree(degree: float):
210
+    for range, direction in DIRECTION_FROM_NORTH_DEGREES.items():
211
+        if range[0] <= degree <= range[1]:
212
+            return direction
213
+    raise Exception('Degree {} our of range ({})'.format(
214
+        degree,
215
+        DIRECTION_FROM_NORTH_DEGREES,
216
+    ))