# HG changeset patch # User Jeremy Thurgood # Date 1358706036 -7200 # Node ID ef4bda7d623d974b1929f2be492b196eed3f4b66 # Parent a453731e45311eb4959587348869ce4027997ee1 Better state and inventory management. diff -r a453731e4531 -r ef4bda7d623d gamelib/main.py --- a/gamelib/main.py Sun Jan 20 18:57:17 2013 +0200 +++ b/gamelib/main.py Sun Jan 20 20:20:36 2013 +0200 @@ -18,8 +18,8 @@ } START_SCREEN = 'menu' - def __init__(self): - super(SuspendedSentence, self).__init__(SSState) + def game_state(self): + return SSState() def game_constants(self): return SSConstants() diff -r a453731e4531 -r ef4bda7d623d gamelib/scenes/machine.py --- a/gamelib/scenes/machine.py Sun Jan 20 18:57:17 2013 +0200 +++ b/gamelib/scenes/machine.py Sun Jan 20 20:20:36 2013 +0200 @@ -180,21 +180,21 @@ else: welder_slot.set_data("contents", set()) welder_slot.update_contents() - if self.game.items["cryo_pipes_one"] in self.game.inventory: + if self.game.is_in_inventory("cryo_pipes_one"): self.game.replace_inventory_item("cryo_pipes_one", "cryo_pipes_two") return Result("With high-precision spitzensparken, you weld" " together a second pipe. You bundle the two" " pipes together.", soundfile='laser.ogg') - elif self.game.items["cryo_pipes_two"] in self.game.inventory: + elif self.game.is_in_inventory("cryo_pipes_two"): self.game.replace_inventory_item("cryo_pipes_two", "cryo_pipes_three") return Result("With high-precision spitzensparken, you create" " yet another pipe. You store it with the other" " two.", soundfile='laser.ogg') - elif self.game.items["cryo_pipes_three"] in self.game.inventory: + elif self.game.is_in_inventory("cryo_pipes_three"): # just for safety return None else: diff -r a453731e4531 -r ef4bda7d623d pyntnclick/gamescreen.py --- a/pyntnclick/gamescreen.py Sun Jan 20 18:57:17 2013 +0200 +++ b/pyntnclick/gamescreen.py Sun Jan 20 20:20:36 2013 +0200 @@ -115,14 +115,14 @@ self.up_button.enable() max_slot = (self.inv_offset + len(self.slots)) - if max_slot >= len(self.game.inventory): + if max_slot >= len(self.game.inventory()): self.down_button.disable() else: self.down_button.enable() @property def slot_items(self): - return self.game.inventory[self.inv_offset:][:len(self.slots)] + return self.game.inventory()[self.inv_offset:][:len(self.slots)] def mouse_down(self, event, widget): if event.button != 1: @@ -256,6 +256,9 @@ getattr(self, 'game_event_%s' % event_name, lambda d: None)(data) def game_event_restart(self, data): + self.reset_game(self.create_initial_state()) + + def reset_game(self, game_state=None): self._clear_all() self.game = self.create_initial_state() diff -r a453731e4531 -r ef4bda7d623d pyntnclick/main.py --- a/pyntnclick/main.py Sun Jan 20 18:57:17 2013 +0200 +++ b/pyntnclick/main.py Sun Jan 20 20:20:36 2013 +0200 @@ -45,7 +45,7 @@ RESOURCE_MODULE = 'data' SCENE_MODULE = 'gamelib.scenes' - def __init__(self, custom_data_cls=None): + def __init__(self): if self.INITIAL_SCENE is None: raise GameDescriptionError("A game must have an initial scene.") if not self.SCENE_LIST: @@ -58,7 +58,6 @@ self._scene_list = self.SCENE_LIST self._resource_module = self.RESOURCE_MODULE self._debug_rects = False - self._custom_data_cls = custom_data_cls self._screens = self.SCREENS.copy() self._screens['game'] = GameScreen self.resource = Resources(self._resource_module) @@ -70,14 +69,15 @@ def initial_state(self): """Create a copy of the initial game state.""" initial_state = state.Game(self) - if self._custom_data_cls: - initial_state.set_custom_data(self._custom_data_cls()) initial_state.set_debug_rects(self._debug_rects) for scene in self._scene_list: initial_state.load_scenes(scene) initial_state.change_scene(self._initial_scene) return initial_state + def game_state(self): + return state.GameState() + def game_constants(self): return GameConstants() diff -r a453731e4531 -r ef4bda7d623d pyntnclick/state.py --- a/pyntnclick/state.py Sun Jan 20 18:57:17 2013 +0200 +++ b/pyntnclick/state.py Sun Jan 20 20:20:36 2013 +0200 @@ -45,13 +45,19 @@ screen.end_game() -class GameState(dict): +class GameState(object): """This holds the serializable game state. Games wanting to do fancier stuff with the state should sub-class this and feed the subclass into GameDescription via the custom_data parameter.""" + def __init__(self): + self._game_state = {'inventories': {'main': []}} + + def __getitem__(self, key): + return self._game_state[key] + def get_all_gizmo_data(self, state_key): """Get all state for a gizmo - returns a dict""" return self[state_key] @@ -66,12 +72,15 @@ def initialize_state(self, state_key, initial_data): """Initialize a gizmo entry""" - if state_key not in self: - self[state_key] = {} + if state_key not in self._game_state: + self._game_state[state_key] = {} if initial_data: # deep copy of INITIAL_DATA allows lists, sets and # other mutable types to safely be used in INITIAL_DATA - self[state_key].update(copy.deepcopy(initial_data)) + self._game_state[state_key].update(copy.deepcopy(initial_data)) + + def inventory(self, name='main'): + return self['inventories'][name] class Game(object): @@ -92,16 +101,21 @@ # map of item name -> Item object self.items = {} # list of item objects in inventory - self.inventory = [] + self.current_inventory = 'main' # currently selected tool (item) self.tool = None # Global game data - self.data = GameState() + self.data = self.gd.game_state() # current scene self.current_scene = None # debug rects self.debug_rects = False + def inventory(self, name=None): + if name is None: + name = self.current_inventory + return self.data.inventory(name) + def set_custom_data(self, data_object): self.data = data_object @@ -143,16 +157,16 @@ ScreenEvent.post('game', 'inventory', None) def add_inventory_item(self, name): - self.inventory.append(self.items[name]) + self.inventory().append(self.items[name]) self._update_inventory() def is_in_inventory(self, name): if name in self.items: - return self.items[name] in self.inventory + return self.items[name] in self.inventory() return False def remove_inventory_item(self, name): - self.inventory.remove(self.items[name]) + self.inventory().remove(self.items[name]) # Unselect tool if it's removed if self.tool == self.items[name]: self.set_tool(None) @@ -161,8 +175,8 @@ def replace_inventory_item(self, old_item_name, new_item_name): """Try to replace an item in the inventory with a new one""" try: - index = self.inventory.index(self.items[old_item_name]) - self.inventory[index] = self.items[new_item_name] + index = self.inventory().index(self.items[old_item_name]) + self.inventory()[index] = self.items[new_item_name] if self.tool == self.items[old_item_name]: self.set_tool(self.items[new_item_name]) except ValueError: diff -r a453731e4531 -r ef4bda7d623d pyntnclick/tests/game_logic_utils.py --- a/pyntnclick/tests/game_logic_utils.py Sun Jan 20 18:57:17 2013 +0200 +++ b/pyntnclick/tests/game_logic_utils.py Sun Jan 20 20:20:36 2013 +0200 @@ -39,7 +39,7 @@ def clear_inventory(self): # Remove all items from the inventory, ensuring tool is set to None self.state.set_tool(None) - self.state.inventory = [] + self.state.inventory()[:] = [] def set_game_data(self, key, value, thing=None): gizmo = self.state.current_scene