X-Git-Url: https://git.ctpug.org.za/?a=blobdiff_plain;f=koperkapel%2Fworld.py;h=1558917b56628ec339e2c37d8ec5fa777b1688c4;hb=14578588930d015178af547be9a15896d75229c6;hp=8a4af23d1407a08c32c02aef57eb9d493deed882;hpb=55ff545e2629cc15b03ec582ee4c1edf1244432d;p=koperkapel.git diff --git a/koperkapel/world.py b/koperkapel/world.py index 8a4af23..1558917 100644 --- a/koperkapel/world.py +++ b/koperkapel/world.py @@ -1,5 +1,8 @@ """ World and player state. """ +from .scenes.base import WorldEvent +from .roaches import build_roach + class World: """ World and player state. """ @@ -18,37 +21,140 @@ class World: def _build_initial_state(self): state = {} state["roaches"] = [ - self._build_roach("roachel", intelligence=3), - self._build_roach("roeginald", strength=3), - self._build_roach("roichard", quickness=3), + build_roach(self, "roupert"), + ] + state["serums"] = [ + "smart", "strong", "fast", ] + state["vehicles"] = { + "current": "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, **kw): - attributes = { - "intelligence": 1, - "strength": 1, - "quickness": 1, - "health": 5, - } - attributes.update(kw) - return { - "name": name, - "attributes": attributes, - } + 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, updates): + def _apply_set(self, action, updates): for name, value in updates.items(): - parts = name.split(".") - obj = self._state - for p in parts[:-1]: - obj = obj[p] - obj[parts[-1]] = value + obj, key = self._get_obj(name) + obj[key] = value - def apply_event(self, action, *args, **kw): - if action == "set": - return self._apply_set(*args, **kw) + def _apply_append(self, action, updates): + for name, value in updates.items(): + obj, key = self._get_obj(name) + obj.append(value) + + 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): + handler = getattr(self, "_apply_%s" % (action,)) + return handler(action, *args, **kw) + + +def _maybe_subproxy(proxy, name, value): + """ Return a sub world proxy if appropriate. """ + if isinstance(value, dict): + prefix = "%s%s." % (proxy._prefix, name) + return WorldDictProxy(value, _prefix=prefix, _top=proxy._top) + elif isinstance(value, list): + prefix = "%s%s." % (proxy._prefix, name) + return WorldListProxy(value, _prefix=prefix, _top=proxy._top) + return value + + +class WorldBaseProxy: + """ Base for world proxies. """ + + def __init__(self, state, _prefix='', _top=None): + if _top is None: + _top = self + _events = [] + else: + _events = None + self.__dict__.update({ + "_state": state, + "_prefix": _prefix, + "_top": _top, + "_events": _events, + }) + + def _record_change(self, fullname, value, action="set"): + self._events.append(WorldEvent(action, { + fullname: value + })) + + def pop_events(self): + events, self._events = self._events, [] + return events + + +class WorldDictProxy(WorldBaseProxy): + """ World dictionary proxy that records changes and produces events. """ + + def __setattr__(self, name, value): + self._top._record_change("%s%s" % (self._prefix, name), value) + + def __getattr__(self, name): + # return None for attributes that don't exist + 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. """ + + def __setitem__(self, index, value): + self._top._record_change("%s%s" % (self._prefix, index), value) + + 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")