Poppable.
[koperkapel.git] / koperkapel / world.py
index b0e3debfd16d830ee8d030aee2aa2eb4e5be8a3a..a07b719a41a79e5882d8fcb7b2da03dfdb8bb7b9 100644 (file)
@@ -1,6 +1,7 @@
 """ World and player state. """
 
 from .scenes.base import WorldEvent
+from .roaches import build_roach
 
 
 class World:
@@ -20,51 +21,68 @@ class World:
     def _build_initial_state(self):
         state = {}
         state["roaches"] = [
-            self._build_roach("roachel", smart=True),
-            self._build_roach("roeginald", strong=True),
-            self._build_roach("roichard", fast=True),
-            self._build_roach("roupert"),
-        ]
-        state["serums"] = [
-            "smart", "strong", "fast",
+            build_roach(self, "roupert"),
         ]
+        state["serums"] = []
         state["vehicles"] = {
             "current": "walking",
-            "available": ["walking"],
+            "walking": {
+                "seating": [
+                    "roachel", None, "roeginald",
+                    None, None, None,
+                ]
+            },
+            "robot": {"seating": []},
+            "roomba": {"seating": []},
+            "quadcopter": {"seating": []},
+        }
+        state["weapons"] = {
+            "current": "spit",
         }
         state["level"] = {
             "name": "level1",
         }
         return state
 
-    def _build_roach(self, name, health=5, **kw):
-        roach = {
-            "name": name,
-            "health": health,
-        }
-        roach.update(kw)
-        return roach
+    def _get_obj(self, name):
+        parts = name.split(".")
+        obj = self._state
+        for p in parts[:-1]:
+            if isinstance(obj, dict):
+                obj = obj[p]
+            elif isinstance(obj, list):
+                obj = obj[int(p)]
+            else:
+                raise KeyError("%r not found in world" % (name,))
+        return obj, parts[-1]
+
+    def _apply_set(self, action, updates):
+        for name, value in updates.items():
+            obj, key = self._get_obj(name)
+            obj[key] = value
 
-    def _apply_set(self, updates):
+    def _apply_append(self, action, updates):
         for name, value in updates.items():
-            parts = name.split(".")
-            obj = self._state
-            for p in parts[:-1]:
-                if isinstance(obj, dict):
-                    obj = obj[p]
-                elif isinstance(obj, list):
-                    obj = obj[int(p)]
-                else:
-                    raise KeyError("%r not found in world" % (name,))
-            obj[parts[-1]] = value
+            obj, key = self._get_obj(name)
+            obj.append(value)
+
+    def _apply_pop(self, action, updates):
+        for name, pos in updates.items():
+            obj, key = self._get_obj(name)
+            obj.pop(pos)
+
+    def _apply_reset(self, action):
+        self._state = self._build_initial_state()
+
+    def _apply_unknown(self, action, *args, **kw):
+        raise ValueError("Unknown world event action: %r" % (action,))
 
     def proxy(self):
         return WorldDictProxy(self._state)
 
     def apply_event(self, action, *args, **kw):
-        if action == "set":
-            return self._apply_set(*args, **kw)
-        raise ValueError("Unknown world event action: %r" % (action,))
+        handler = getattr(self, "_apply_%s" % (action,))
+        return handler(action, *args, **kw)
 
 
 def _maybe_subproxy(proxy, name, value):
@@ -94,8 +112,8 @@ class WorldBaseProxy:
             "_events": _events,
         })
 
-    def _record_change(self, fullname, value):
-        self._events.append(WorldEvent("set", {
+    def _record_change(self, fullname, value, action="set"):
+        self._events.append(WorldEvent(action, {
             fullname: value
         }))
 
@@ -107,10 +125,6 @@ class WorldBaseProxy:
 class WorldDictProxy(WorldBaseProxy):
     """ World dictionary proxy that records changes and produces events. """
 
-    def items(self):
-        return (
-            (k, _maybe_subproxy(self, k, v)) for k, v in self._state.items())
-
     def __setattr__(self, name, value):
         self._top._record_change("%s%s" % (self._prefix, name), value)
 
@@ -119,6 +133,16 @@ class WorldDictProxy(WorldBaseProxy):
         value = self._state.get(name)
         return _maybe_subproxy(self, name, value)
 
+    def __setitem__(self, name, value):
+        return self.__setattr__(name, value)
+
+    def __getitem__(self, name):
+        return self.__getattr__(name)
+
+    def items(self):
+        return (
+            (k, _maybe_subproxy(self, k, v)) for k, v in self._state.items())
+
 
 class WorldListProxy(WorldBaseProxy):
     """ World list proxy that records changes and produces events. """
@@ -128,3 +152,15 @@ class WorldListProxy(WorldBaseProxy):
 
     def __getitem__(self, index):
         return _maybe_subproxy(self, index, self._state[index])
+
+    def __len__(self):
+        return len(self._state)
+
+    def __bool__(self):
+        return bool(self._state)
+
+    def append(self, value):
+        self._top._record_change(self._prefix, value, action="append")
+
+    def pop(self, pos=0):
+        self._top._record_change(self._prefix, pos, action="pop")