Browse Source

Tools for pheromones

Bastien Sevajol 9 years ago
parent
commit
d988aa39a2

+ 8 - 0
intelligine/core/Context.py View File

@@ -1,10 +1,18 @@
1 1
 from xyzworld.Context import Context as XyzContext
2 2
 from intelligine.cst import IMPENETRABLE
3 3
 from xyzworld.cst import POSITIONS
4
+from intelligine.synergy.stigmergy.PheromonesManager import PheromonesManager
4 5
 
5 6
 
6 7
 class Context(XyzContext):
7 8
 
9
+    def __init__(self):
10
+        super().__init__()
11
+        self._pheromones = PheromonesManager(self)
12
+
13
+    def pheromones(self):
14
+        return self._pheromones
15
+
8 16
     def position_is_penetrable(self, position):
9 17
         objects_ids_on_this_point = self.metas.list.get(POSITIONS, position, allow_empty=True)
10 18
         for object_id_on_this_point in objects_ids_on_this_point:

+ 4 - 12
intelligine/display/Pygame.py View File

@@ -18,19 +18,11 @@ class Pygame(XyzPygame):
18 18
 
19 19
     def _display_pheromones(self, pheromones_positions, context):
20 20
         for point in pheromones_positions:
21
-            ######
22
-            # refact
23
-            point_pheromones_infos = context.metas.value.get(PHEROMON_INFOS, point, allow_empty=True,
21
+            exploration_info = context.pheromones().get_info(point,
22
+                                                             [PHEROMON_DIRECTION,
23
+                                                              PHEROMON_DIR_EXPLO],
24
+                                                             allow_empty=True,
24 25
                                                              empty_value={})
25
-            # TODO: Tout ca dans un get_pheromone_info(PHEROMON_DIRECTION, PHEROMON_DIR_EXPLO, direction)
26
-            #point_pheromones_infos={}
27
-            if PHEROMON_DIRECTION not in point_pheromones_infos:
28
-                point_pheromones_infos[PHEROMON_DIRECTION] = {}
29
-            direction_pheromone = point_pheromones_infos[PHEROMON_DIRECTION]
30
-            if PHEROMON_DIR_EXPLO not in direction_pheromone:
31
-                 direction_pheromone[PHEROMON_DIR_EXPLO] = {}
32
-            exploration_info = direction_pheromone[PHEROMON_DIR_EXPLO]
33
-            ########
34 26
 
35 27
             for direction in exploration_info:
36 28
                 intensity = exploration_info[direction]

BIN
intelligine/display/pygame/image/pheb.png View File


BIN
intelligine/display/pygame/image/phee.png View File


+ 11 - 0
intelligine/sandbox/exploration/ColonyConfiguration.py View File

@@ -0,0 +1,11 @@
1
+from intelligine.synergy.ColonyConfiguration import ColonyConfiguration
2
+from intelligine.synergy.object.ant.Ant import Ant
3
+
4
+
5
+class ColonyConfiguration(ColonyConfiguration):
6
+
7
+    _start_position = (0, 20, 20)
8
+    _ant_class = Ant
9
+    _ant_count = 2
10
+
11
+

+ 4 - 0
intelligine/sandbox/exploration/collections.py View File

@@ -0,0 +1,4 @@
1
+from intelligine.sandbox.exploration.ColonyConfiguration import ColonyConfiguration
2
+from intelligine.synergy.Colony import Colony
3
+
4
+collections = [Colony(ColonyConfiguration())]

+ 0 - 1
intelligine/synergy/event/move/direction.py View File

@@ -1,4 +1,3 @@
1
-
2 1
 """
3 2
 Directions identifiers 3D, central position is 14.
4 3
 niv -1:  1   2  3

+ 79 - 0
intelligine/synergy/event/pheromone/ApposeDirection.py View File

@@ -0,0 +1,79 @@
1
+from synergine.synergy.event.Action import Action
2
+from intelligine.synergy.event.pheromone.PheromoneEvent import PheromoneEvent
3
+from xyzworld.cst import POSITION
4
+from intelligine.cst import PHEROMON_DIRECTION, PHEROMON_DIR_EXPLO, PHEROMON_POSITIONS
5
+from xyzworld.geometry import get_direction_degrees, get_degree_from_north
6
+from intelligine.synergy.event.move.direction import get_direction_for_degrees, get_direction_opposite
7
+
8
+
9
+class ApposeDirection(Action):
10
+
11
+    _listen = PheromoneEvent
12
+
13
+    def prepare(self, context):
14
+        """
15
+        Recupere chaque coordonnees de points qui doivent etre update
16
+        pour ne pas avoir a e calculer dans le run
17
+        :param context:
18
+        :return:
19
+        """
20
+        object_point =  context.metas.value.get(POSITION, self._object_id)
21
+        distance = 1 # TODO: Config ?
22
+        self._parameters['concerned_points'] = context.get_arround_points_of(object_point, distance)
23
+
24
+    def run(self, obj, context, synergy_manager):
25
+        """
26
+        On effectue l'incrementation dans le process principal. Beaucoups plus lourd que de le faie dans les
27
+        process. Mais si on le fait dans les process on va rater des infos ...
28
+        met a jour les pts (incremente)
29
+        :param obj:
30
+        :param context:
31
+        :param synergy_manager:
32
+        :return:
33
+        """
34
+        # TODO: Remonter ca dans une objet
35
+
36
+        # a = get_direction_degrees((0, 0, 0), (0, -1, -1)) # 315
37
+        # a = get_direction_degrees((0, 0, 0), (0, 0, -1))  # 0
38
+        # a = get_direction_degrees((0, 0, 0), (0, 1, -1))  # 45
39
+        # a = get_direction_degrees((0, 0, 0), (0, -1, 0))  # 270
40
+        # a = get_direction_degrees((0, 0, 0), (0, 1, 0))   # 90
41
+        # a = get_direction_degrees((0, 0, 0), (0, -1, 1))  # 225
42
+        # a = get_direction_degrees((0, 0, 0), (0, 0, 1))   # 180
43
+        # a = get_direction_degrees((0, 0, 0), (0, 1, 1))   # 135
44
+
45
+        # a = get_degree_from_north((0, 0, 0), (0, -1, -1)) # 315
46
+        # a = get_degree_from_north((0, 0, 0), (0, 0, -1))  # 0
47
+        # a = get_degree_from_north((0, 0, 0), (0, 1, -1))  # 45
48
+        # a = get_degree_from_north((0, 0, 0), (0, -1, 0))  # 270
49
+        # a = get_degree_from_north((0, 0, 0), (0, 1, 0))   # 90
50
+        # a = get_degree_from_north((0, 0, 0), (0, -1, 1))  # 225
51
+        # a = get_degree_from_north((0, 0, 0), (0, 0, 1))   # 180
52
+        # a = get_degree_from_north((0, 0, 0), (0, 1, 1))   # 135
53
+        self._appose_pheromones(obj, context, synergy_manager)
54
+
55
+    def _appose_pheromones(self, obj, context, synergy_manager):
56
+        obj_position = obj.get_position()
57
+        obj_last_pheromon_position = obj.get_last_pheromone_point(PHEROMON_DIRECTION)
58
+        try:
59
+            direction_degrees = get_degree_from_north(obj_last_pheromon_position, obj_position)
60
+        except ZeroDivisionError:
61
+            return
62
+        direction = get_direction_for_degrees(direction_degrees)
63
+        from_direction = get_direction_opposite(direction)
64
+        depose_intensity = 1 # TODO: config
65
+
66
+        for affected_point in self._parameters['concerned_points']:
67
+            self._appose_pheromone(context, affected_point, direction, depose_intensity)
68
+            context.metas.list.add(PHEROMON_POSITIONS, PHEROMON_POSITIONS, affected_point, assert_not_in=False)
69
+
70
+        obj.set_last_pheromone_point(PHEROMON_DIRECTION, obj.get_position())
71
+
72
+    def _appose_pheromone(self, context, affected_point, direction, depose_intensity):
73
+        context.pheromones().increment(affected_point, [PHEROMON_DIRECTION,
74
+                                                        PHEROMON_DIR_EXPLO,
75
+                                                        direction], depose_intensity)
76
+
77
+
78
+
79
+

+ 26 - 0
intelligine/synergy/event/pheromone/DetermineDirection.py View File

@@ -0,0 +1,26 @@
1
+from synergine.synergy.event.Action import Action
2
+from intelligine.synergy.event.mind.PheromoneEvent import PheromoneEvent
3
+
4
+
5
+class DetermineDirection(Action):
6
+
7
+    _listen = PheromoneEvent
8
+
9
+    def prepare(self, context):
10
+        """
11
+        Recupere chaque coordonnees de points qui doivent etre update
12
+        pour ne pas avoir a e calculer dans le run
13
+        :param context:
14
+        :return:
15
+        """
16
+        pass
17
+
18
+    def run(self, obj, context, synergy_manager):
19
+        """
20
+        Met a jour la direction en cours de l'ant
21
+        :param obj:
22
+        :param context:
23
+        :param synergy_manager:
24
+        :return:
25
+        """
26
+        pass

+ 15 - 0
intelligine/synergy/event/pheromone/PheromoneEvent.py View File

@@ -0,0 +1,15 @@
1
+from synergine.synergy.event.Event import Event
2
+from intelligine.cst import COL_WALKER
3
+
4
+
5
+class PheromoneEvent(Event):
6
+    """
7
+    TODO: dissipation des infos de pheromones:
8
+          On doit manipuler l'environnement (pas des syn.obj.) car -= l'intensite d'un pt.
9
+    """
10
+
11
+    concern = COL_WALKER # Maybe more when more pheromones
12
+    _each_cycle = 2
13
+
14
+    def _object_match(self, object_id, context, parameters):
15
+        return True

+ 15 - 0
intelligine/synergy/object/ant/Pheromon.py View File

@@ -0,0 +1,15 @@
1
+from xyzworld.SynergyObject import SynergyObject as XyzSynergyObject
2
+
3
+
4
+class Pheromon(XyzSynergyObject):
5
+
6
+    def __init__(self, collection, context):
7
+        super().__init__(collection, context)
8
+        self._direction = None
9
+
10
+    # TODO: direction ailleurs non ?
11
+    def set_direction(self, direction):
12
+        self._direction = direction
13
+
14
+    def get_direction(self):
15
+        return self._direction

+ 50 - 0
intelligine/synergy/stigmergy/PheromonesManager.py View File

@@ -0,0 +1,50 @@
1
+from intelligine.cst import PHEROMON_INFOS
2
+
3
+
4
+class PheromonesManager():
5
+
6
+    def __init__(self, context):
7
+        self._context = context
8
+
9
+    def get_pheromones(self, position, prepare=[]):
10
+        point_pheromones = self._context.metas.value.get(PHEROMON_INFOS,
11
+                                                         position,
12
+                                                         allow_empty=True,
13
+                                                         empty_value={})
14
+        current_check = point_pheromones
15
+        for prepare_key in prepare:
16
+            if prepare_key not in current_check:
17
+                current_check[prepare_key] = {}
18
+            current_check = current_check[prepare_key]
19
+
20
+        return point_pheromones
21
+
22
+    def set_pheromones(self, position, pheromones):
23
+        self._context.metas.value.set(PHEROMON_INFOS, position, pheromones)
24
+
25
+    def get_info(self, position, address, allow_empty=False, empty_value=None):
26
+        pheromones = self.get_pheromones(position, address[:-1])
27
+
28
+        pheromone = pheromones
29
+        for key in address[:-1]:
30
+            pheromone = pheromone[key]
31
+
32
+        if address[-1] not in pheromone:
33
+            if allow_empty:
34
+              pheromone[address[-1]] = empty_value
35
+            else:
36
+                raise IndexError()
37
+
38
+        return pheromone[address[-1]]
39
+
40
+    def increment(self, position, address, increment_value):
41
+        pheromones = self.get_pheromones(position, address[:-1])
42
+
43
+        pheromone = pheromones
44
+        for key in address[:-1]:
45
+            pheromone = pheromone[key]
46
+
47
+        if address[-1] not in pheromone:
48
+            pheromone[address[-1]] = 0
49
+        pheromone[address[-1]] += increment_value
50
+        self.set_pheromones(position, pheromones)