Browse Source

refact putable action/events/brain

Bastien Sevajol 9 years ago
parent
commit
168683a8cd

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

@@ -1,3 +1,6 @@
1
+from synergine.synergy.event.exception.ActionAborted import ActionException
2
+
3
+
1 4
 class MovementException(Exception):
2 5
     pass
3 6
 
@@ -59,5 +62,10 @@ class NearException(Exception):
59 62
 class NearFound(NearException):
60 63
     pass
61 64
 
65
+
62 66
 class NearNothingFound(NearException):
67
+    pass
68
+
69
+
70
+class CantFindWhereToPut(ActionException):
63 71
     pass

+ 1 - 0
intelligine/cst.py View File

@@ -9,6 +9,7 @@ COLONY = IncrementedNamedInt.get('intelligine.colony')
9 9
 TRANSPORTABLE = IncrementedNamedInt.get('intelligine.transportable')
10 10
 TRANSPORTER = IncrementedNamedInt.get('intelligine.transporter')
11 11
 CARRYING = IncrementedNamedInt.get('intelligine.carrying')
12
+CARRIED = IncrementedNamedInt.get('intelligine.carried')
12 13
 CANT_CARRY_STILL = IncrementedNamedInt.get('intelligine.cantcarry.still')
13 14
 CANT_PUT_STILL = IncrementedNamedInt.get('intelligine.cantput.still')
14 15
 ACTION_DIE = IncrementedNamedInt.get('intelligine.basebug.action.die')

+ 7 - 0
intelligine/sandbox/exploration/RocksConfiguration.py View File

@@ -1,3 +1,4 @@
1
+from intelligine.synergy.object.Food import Food
1 2
 from synergine.synergy.collection.Configuration import Configuration
2 3
 from intelligine.synergy.object.Rock import Rock
3 4
 import pytmx
@@ -30,4 +31,10 @@ class RocksConfiguration(Configuration):
30 31
                         rock.set_position((0, xi, yi))
31 32
                         rocks.append(rock)
32 33
 
34
+        #  TEST
35
+        food1 = Food(collection, context)
36
+        food1.set_position((0, 0, 0))
37
+        food1.is_takable = lambda: False
38
+        rocks.append(food1)
39
+
33 40
         return rocks

+ 8 - 2
intelligine/simulation/object/brain/AntBrain.py View File

@@ -1,22 +1,25 @@
1 1
 from intelligine.simulation.object.brain.Brain import Brain
2 2
 from intelligine.simulation.object.brain.part.move.AntMoveBrainPart import AntMoveBrainPart
3 3
 from intelligine.cst import MOVE_MODE, MOVE_MODE_EXPLO, MOVE_MODE_GOHOME, PHEROMON_DIR_HOME, PHEROMON_DIR_EXPLO, \
4
-    BRAIN_PART_TAKE
4
+    BRAIN_PART_TAKE, BRAIN_PART_PUT
5 5
 from intelligine.cst import PHEROMONE_SEARCHING
6 6
 from intelligine.cst import BRAIN_PART_MOVE
7
-from intelligine.simulation.object.brain.part.take.AntTakeBrainPart import AntTakeBrainPart
7
+from intelligine.simulation.object.brain.part.transport.AntPutBrainPart import AntPutBrainPart
8
+from intelligine.simulation.object.brain.part.transport.AntTakeBrainPart import AntTakeBrainPart
8 9
 
9 10
 
10 11
 class AntBrain(Brain):
11 12
 
12 13
     _brain_part_move_class = AntMoveBrainPart
13 14
     _brain_part_take_class = AntTakeBrainPart
15
+    _brain_part_put_class = AntPutBrainPart
14 16
 
15 17
     def __init__(self, context, host):
16 18
         super().__init__(context, host)
17 19
         # TODO: Gerer les BrainPart avec un dictionnaire ?
18 20
         self._set_brain_part(BRAIN_PART_MOVE, self._get_move_brain_part_instance())
19 21
         self._set_brain_part(BRAIN_PART_TAKE, self._get_take_brain_part_instance())
22
+        self._set_brain_part(BRAIN_PART_PUT, self._get_put_brain_part_instance())
20 23
         self._movement_mode = MOVE_MODE_EXPLO
21 24
         self._distance_from_objective = 0  # TODO rename: distance_since_objective
22 25
         self._pheromone_searching = PHEROMON_DIR_EXPLO
@@ -27,6 +30,9 @@ class AntBrain(Brain):
27 30
     def _get_take_brain_part_instance(self):
28 31
         return self._brain_part_take_class()
29 32
 
33
+    def _get_put_brain_part_instance(self):
34
+        return self._brain_part_put_class()
35
+
30 36
     def switch_to_mode(self, mode):
31 37
         self._movement_mode = mode
32 38
         self._update_pheromone_gland(mode)

+ 9 - 9
intelligine/simulation/object/brain/part/move/AntMoveBrainPart.py View File

@@ -47,15 +47,15 @@ class AntMoveBrainPart(MoveBrainPart):
47 47
         super().done(obj, context)
48 48
         self._appose_pheromone(obj)
49 49
 
50
-        # TEST: le temps de tout tester
51
-        if obj.get_position() == obj.get_colony().get_start_position() and obj.is_carrying():
52
-            obj_transported = obj.get_carried()
53
-            obj_transported.set_carried_by(None)
54
-            obj.put_carry(obj_transported, (-1, 0, 0))
55
-            obj.get_brain().switch_to_mode(MOVE_MODE_EXPLO)
56
-            context.metas.collections.add_remove(obj.get_id(),
57
-                                                 COL_TRANSPORTER_NOT_CARRYING,
58
-                                                 COL_TRANSPORTER_CARRYING)
50
+        # # TEST: le temps de tout tester
51
+        # if obj.get_position() == obj.get_colony().get_start_position() and obj.is_carrying():
52
+        #     obj_transported = obj.get_carried()
53
+        #     obj_transported.set_carried_by(None)
54
+        #     obj.put_carry(obj_transported, (-1, 0, 0))
55
+        #     obj.get_brain().switch_to_mode(MOVE_MODE_EXPLO)
56
+        #     context.metas.collections.add_remove(obj.get_id(),
57
+        #                                          COL_TRANSPORTER_NOT_CARRYING,
58
+        #                                          COL_TRANSPORTER_CARRYING)
59 59
 
60 60
     @staticmethod
61 61
     def _appose_pheromone(obj):

+ 0 - 10
intelligine/simulation/object/brain/part/take/TakeBrainPart.py View File

@@ -1,10 +0,0 @@
1
-from intelligine.simulation.object.brain.part.BrainPart import BrainPart
2
-
3
-
4
-class TakeBrainPart(BrainPart):
5
-
6
-    _take = {}
7
-
8
-    @classmethod
9
-    def can_take(cls, context, object_to_take_id):
10
-        return False

+ 57 - 0
intelligine/simulation/object/brain/part/transport/AntPutBrainPart.py View File

@@ -0,0 +1,57 @@
1
+from intelligine.core.exceptions import CantFindWhereToPut
2
+from intelligine.simulation.object.brain.part.transport.TakeBrainPart import TakeBrainPart
3
+from intelligine.cst import MOVE_MODE_EXPLO, MOVE_MODE, TYPE_RESOURCE_TRANSFORMABLE, TYPE, CARRIED, \
4
+    COL_TRANSPORTER_NOT_CARRYING, COL_TRANSPORTER_CARRYING
5
+from xyzworld.cst import POSITION, POSITIONS
6
+
7
+
8
+class AntPutBrainPart(TakeBrainPart):
9
+
10
+    # TODO: methode __nit_ pour la classe ?
11
+    _mode_matches = {
12
+        MOVE_MODE_EXPLO: [TYPE_RESOURCE_TRANSFORMABLE],
13
+    }
14
+
15
+    @classmethod
16
+    def can_put(cls, context, object_id, object_near_id):
17
+        object_carried_id = context.metas.value.get(CARRIED, object_id)
18
+        #  Pour le moment on considere qu'un objet peut-etre depose a cote d'un objet qui a un type identique
19
+        return cls._objects_have_same_type(context, object_carried_id, object_near_id)
20
+
21
+    @classmethod
22
+    def get_put_position(cls, context, object_id, object_near_id):
23
+        """
24
+        Maybe part "found available position arround" should be in other class.
25
+        :param context:
26
+        :param object_id:
27
+        :param object_near_id:
28
+        :return:
29
+        """
30
+        obj_near_position = context.metas.value.get(POSITION, object_near_id)
31
+        if cls._is_available_position(context, obj_near_position):
32
+            return obj_near_position
33
+
34
+        obj_transporter_position = context.metas.value.get(POSITION, object_id)
35
+        obj_transporter_around_positions = context.get_around_points_of_point(obj_transporter_position)
36
+        obj_near_around_positions = context.get_around_points_of_point(obj_near_position)
37
+
38
+        # For each position between target and current transporter
39
+        for pos_around_target in obj_near_around_positions:
40
+            if pos_around_target in obj_transporter_around_positions:
41
+                if cls._is_available_position(context, pos_around_target):
42
+                    return pos_around_target
43
+        raise CantFindWhereToPut()
44
+
45
+    @staticmethod
46
+    def _is_available_position(context, position):
47
+        # TODO: Pour le moment on ne regarde pas si ce sont tous des obj identique
48
+        count_obj_here = len(context.metas.list.get(POSITIONS, position, allow_empty=True))
49
+        # TODO: 5 est hardcode; de plus cette cntrainte (not brain) devrait dependre de l'objet, du contexte ...
50
+        if count_obj_here <= 5 and (context.position_is_penetrable(position) or position == (0, 0, 0)):  # TODO TEST !!!
51
+            return True
52
+        return False
53
+
54
+    def done(self, obj, puted_object, context):
55
+        # TODO: Depose au -1 pour des raisons de test. Plus tard ce sera des tas comme un autre !
56
+        puted_object.set_position((-1, 0, 0))
57
+        obj.get_brain().switch_to_mode(MOVE_MODE_EXPLO)

intelligine/simulation/object/brain/part/take/AntTakeBrainPart.py → intelligine/simulation/object/brain/part/transport/AntTakeBrainPart.py View File

@@ -1,4 +1,4 @@
1
-from intelligine.simulation.object.brain.part.take.TakeBrainPart import TakeBrainPart
1
+from intelligine.simulation.object.brain.part.transport.TakeBrainPart import TakeBrainPart
2 2
 from intelligine.synergy.object.ressource.Ressource import Resource
3 3
 from intelligine.cst import MOVE_MODE_EXPLO, MOVE_MODE, TYPE_RESOURCE_TRANSFORMABLE, \
4 4
     TYPE, MOVE_MODE_GOHOME, PHEROMON_DIR_EXPLO
@@ -6,24 +6,15 @@ from intelligine.cst import MOVE_MODE_EXPLO, MOVE_MODE, TYPE_RESOURCE_TRANSFORMA
6 6
 
7 7
 class AntTakeBrainPart(TakeBrainPart):
8 8
 
9
-    # TODO: methode __nit_ pour la classe ?
10
-    _take = {
9
+    # TODO: methode __nit_ pour la classe ? vt mieux surcharger !
10
+    _mode_matches = {
11 11
         MOVE_MODE_EXPLO: [TYPE_RESOURCE_TRANSFORMABLE],
12 12
     }
13 13
 
14 14
     @classmethod
15 15
     def can_take(cls, context, object_id, object_to_take_id):
16
-        if not cls._object_is_takable_type(context, object_id, object_to_take_id):
17
-            return False
18
-        return True
19
-
20
-    @classmethod
21
-    def _object_is_takable_type(cls, context, object_id, object_to_take_id):
22
-        move_mode = context.metas.value.get(MOVE_MODE, object_id)
23
-        for takable_type in cls._take[move_mode]:
24
-            if context.metas.list.have(TYPE, takable_type, object_to_take_id, allow_empty=True):
25
-                return True
26
-        return False
16
+        # Pour le moment si le type de l'objet fait partie des types admis pour le mode courant du porteur, c'est bon.
17
+        return cls._match_with_mode(context, object_id, object_to_take_id)
27 18
 
28 19
     def done(self, obj, take_object, context):
29 20
         # TODO: Ranger ca ? Truc plus dynamique/configurable ?

+ 8 - 0
intelligine/simulation/object/brain/part/transport/PutBrainPart.py View File

@@ -0,0 +1,8 @@
1
+from intelligine.simulation.object.brain.part.transport.TransportBrainPart import TransportBrainPart
2
+
3
+
4
+class PutBrainPart(TransportBrainPart):
5
+
6
+    @classmethod
7
+    def can_put(cls, context, object_to_take_id):
8
+        raise NotImplementedError()

+ 8 - 0
intelligine/simulation/object/brain/part/transport/TakeBrainPart.py View File

@@ -0,0 +1,8 @@
1
+from intelligine.simulation.object.brain.part.transport.TransportBrainPart import TransportBrainPart
2
+
3
+
4
+class TakeBrainPart(TransportBrainPart):
5
+
6
+    @classmethod
7
+    def can_take(cls, context, object_to_take_id):
8
+        raise NotImplementedError()

+ 26 - 0
intelligine/simulation/object/brain/part/transport/TransportBrainPart.py View File

@@ -0,0 +1,26 @@
1
+from intelligine.cst import MOVE_MODE, TYPE
2
+from intelligine.simulation.object.brain.part.BrainPart import BrainPart
3
+
4
+
5
+class TransportBrainPart(BrainPart):
6
+
7
+    _mode_matches = {}
8
+
9
+    @classmethod
10
+    def _match_with_mode(cls, context, object_id, concerned_object_id):
11
+        move_mode = context.metas.value.get(MOVE_MODE, object_id)
12
+        for takable_type in cls._mode_matches[move_mode]:
13
+            if context.metas.list.have(TYPE, concerned_object_id, takable_type, allow_empty=True):
14
+                return True
15
+        return False
16
+
17
+    @classmethod
18
+    def _objects_have_same_type(cls, context, object_carried_id, object_to_put_id):
19
+        # BUG: On considere ici que c une liste de type pour obj. J'ai fait l'inverse.
20
+        # Une listde de objid pour un type.
21
+        # TODO: Il faut inverser !
22
+        object_carried_types = context.metas.list.get(TYPE, object_carried_id)
23
+        for object_carried_type in object_carried_types:
24
+            if context.metas.list.have(TYPE, object_to_put_id, object_carried_type):
25
+                return True
26
+        return False

+ 5 - 31
intelligine/synergy/event/transport/PutableAction.py View File

@@ -1,9 +1,7 @@
1 1
 from intelligine.synergy.event.move.MoveAction import MoveAction
2 2
 from synergine.synergy.event.Action import Action
3 3
 from intelligine.synergy.event.transport.PutableEvent import PutableEvent
4
-from intelligine.cst import CANT_CARRY_STILL
5
-from xyzworld.cst import POSITIONS
6
-from synergine.synergy.event.exception.ActionAborted import ActionAborted
4
+from intelligine.cst import CANT_CARRY_STILL, BRAIN_PART_PUT
7 5
 
8 6
 
9 7
 class PutableAction(Action):
@@ -14,37 +12,13 @@ class PutableAction(Action):
14 12
     def __init__(self, object_id, parameters):
15 13
         super().__init__(object_id, parameters)
16 14
 
17
-    def prepare(self, context):
18
-        pass
19
-
20 15
     def run(self, obj, context, synergy_manager):
21
-        # TODO: DEV
22
-        obj_id_transportable = self._parameters['objects_ids_transportable'][0]
23
-        obj_transportable = synergy_manager.get_map().get_object(obj_id_transportable)
24
-        # TODO: Cette logique de calcul cote process!
25
-        position_to_put = self._get_position_to_put(context, obj, obj_transportable)
26
-        # TODO: Doit etre du meme type que ce qui est transporte !
16
+        position_to_put = self._parameters[PutableEvent.PARAM_PUT_TO]
27 17
         obj_transported = obj.get_carried()
18
+
28 19
         obj_transported.set_carried_by(None)
20
+        #  TODO: re controle de si posable ? (5 max etc)
29 21
         obj.put_carry(obj_transported, position_to_put)
30 22
         context.metas.value.set(CANT_CARRY_STILL, obj.get_id(), 5)
31 23
 
32
-    def _get_position_to_put(self, context, obj, obj_transportable):
33
-        obj_transportable_pos = obj_transportable.get_position()
34
-        if self._is_available_position(context, obj_transportable_pos):
35
-            return obj_transportable_pos
36
-        poss_around_target = context.get_around_points_of_point(obj_transportable_pos)
37
-        poss_around_obj = context.get_around_points_of_point(obj.get_position())
38
-        # For each position between target and current transporter
39
-        for pos_around_target in poss_around_target:
40
-            if pos_around_target in poss_around_obj:
41
-                if self._is_available_position(context, pos_around_target):
42
-                    return pos_around_target
43
-        raise ActionAborted()
44
-
45
-    def _is_available_position(self, context, position):
46
-        # TODO: Pour le moment on ne regarde pas si ce sont tous des oeufs
47
-        count_obj_here = len(context.metas.list.get(POSITIONS, position, allow_empty=True))
48
-        if count_obj_here <= 5 and context.position_is_penetrable(position):
49
-            return True
50
-        return False
24
+        obj.get_brain().get_part(BRAIN_PART_PUT).done(obj, obj_transported, context)

+ 53 - 5
intelligine/synergy/event/transport/PutableEvent.py View File

@@ -1,13 +1,61 @@
1
+from intelligine.core.exceptions import NearNothingFound, CantFindWhereToPut
2
+from intelligine.synergy.event.src.NearEvent import NearEvent
1 3
 from synergine.core.exceptions import NotConcernedEvent
2
-from intelligine.synergy.event.transport.TakeableEvent import TakeableEvent
3
-from intelligine.cst import CANT_PUT_STILL, COL_TRANSPORTER_CARRYING
4
+from intelligine.cst import CANT_PUT_STILL, COL_TRANSPORTER_CARRYING, TRANSPORTABLE, BRAIN_SCHEMA, BRAIN_PART_PUT
5
+from xyzworld.mechanism.ArroundMechanism import ArroundMechanism
4 6
 
5 7
 
6
-class PutableEvent(TakeableEvent):
8
+class PutableEvent(NearEvent):
9
+    """
10
+    TODO: Refactorise with TakableEvent
11
+    """
7 12
 
13
+    PARAM_PUT = 'put'
14
+    PARAM_PUT_TO = 'put_to'
8 15
     concern = COL_TRANSPORTER_CARRYING
16
+    _near_name = 'objects_ids_putable'
17
+    _near_map = lambda self, near_object_id, context: context.metas.states.have(near_object_id, TRANSPORTABLE)
18
+
19
+    def __init__(self, actions):
20
+        super().__init__(actions)
21
+        self._mechanism = ArroundMechanism
9 22
 
10 23
     def _prepare(self, object_id, context, parameters={}):
11
-        if context.metas.value.get(CANT_PUT_STILL, object_id, allow_empty=True):
24
+        if not self._can_put(object_id, context):
25
+            raise NotConcernedEvent()
26
+
27
+        try:
28
+            self.map(context, parameters, stop_at_first=True)
29
+        except NearNothingFound:
30
+            raise NotConcernedEvent()
31
+
32
+        object_near_id = parameters[self._near_name][0]
33
+        brain_part = self._get_brain_part(object_id, context)
34
+
35
+        if not brain_part.can_put(context, object_id, object_near_id):
12 36
             raise NotConcernedEvent()
13
-        return super()._prepare(object_id, context, parameters)
37
+
38
+        try:
39
+            put_position = brain_part.get_put_position(context, object_id, object_near_id)
40
+        except CantFindWhereToPut:
41
+            raise NotConcernedEvent()
42
+
43
+        parameters[self.PARAM_PUT] = parameters[self._near_name][0]
44
+        parameters[self.PARAM_PUT_TO] = put_position
45
+        return parameters
46
+
47
+    @staticmethod
48
+    def _can_put(object_id, context):
49
+        return not context.metas.value.get(CANT_PUT_STILL, object_id, allow_empty=True)
50
+
51
+    @staticmethod
52
+    def _get_brain_part(object_id, context):
53
+        # TODO: refatc au dessus ?
54
+        object_brain_schema = context.metas.value.get(BRAIN_SCHEMA, object_id)
55
+        return object_brain_schema[BRAIN_PART_PUT]
56
+
57
+    @staticmethod
58
+    def _object_can_put(object_id, context, object_to_put_id):
59
+        object_brain_schema = context.metas.value.get(BRAIN_SCHEMA, object_id)
60
+        object_take_brain_part = object_brain_schema[BRAIN_PART_PUT]
61
+        return object_take_brain_part.can_put(context, object_id, object_to_put_id)

+ 1 - 1
intelligine/synergy/object/Food.py View File

@@ -6,7 +6,7 @@ class Food(Resource):
6 6
 
7 7
     def __init__(self, collection, context):
8 8
         super().__init__(collection, context)
9
-        context.metas.list.add(TYPE, TYPE_RESOURCE_TRANSFORMABLE, self.get_id())
9
+        context.metas.list.add(TYPE, self.get_id(), TYPE_RESOURCE_TRANSFORMABLE)
10 10
         # TODO: ?? TRANSPORTABLE ne devrait pas ette du cote de Transportable ?
11 11
         context.metas.states.add(self.get_id(), TRANSPORTABLE)
12 12
 

+ 3 - 1
intelligine/synergy/object/ant/Ant.py View File

@@ -4,7 +4,7 @@ from intelligine.synergy.object.Bug import Bug
4 4
 from intelligine.cst import CARRYING, TRANSPORTER, ATTACKER, \
5 5
                             COL_TRANSPORTER, COL_TRANSPORTER_NOT_CARRYING, \
6 6
                             COL_FIGHTER, MOVE_MODE_EXPLO, MOVE_MODE_GOHOME, \
7
-                            PHEROMON_DIR_EXPLO, LAST_PHERMONES_POINTS
7
+                            PHEROMON_DIR_EXPLO, LAST_PHERMONES_POINTS, CARRIED
8 8
 from intelligine.synergy.object.Food import Food
9 9
 from intelligine.simulation.object.pheromone.MovementPheromoneGland import MovementPheromoneGland
10 10
 from intelligine.simulation.object.brain.AntBrain import AntBrain
@@ -44,6 +44,8 @@ class Ant(Bug):
44 44
     def carry(self, obj):
45 45
         self._carried.append(obj)
46 46
         self._context.metas.states.add(self.get_id(), CARRYING)
47
+        #  TODO: On gere une liste de carried (mais pas juste la dessous). Ne gerer qu'un objet carried ?
48
+        self._context.metas.value.set(CARRIED, self.get_id(), obj.get_id())
47 49
         # TODO: pour le moment hardcode
48 50
         if isinstance(obj, Food):
49 51
             self.get_brain().switch_to_mode(MOVE_MODE_GOHOME)