changeset 764:a8510f4e2ea1 pyntnclick

Conditionally add things based on state.
author Jeremy Thurgood <firxen@gmail.com>
date Sat, 26 Jan 2013 15:24:56 +0200
parents afe7b1cb16c0
children a35f5364437d
files gamelib/scenes/bridge.py gamelib/scenes/crew_quarters.py gamelib/scenes/cryo.py gamelib/scenes/engine.py gamelib/scenes/machine.py gamelib/scenes/mess.py pyntnclick/scenewidgets.py pyntnclick/state.py
diffstat 8 files changed, 81 insertions(+), 43 deletions(-) [+]
line wrap: on
line diff
--- a/gamelib/scenes/bridge.py	Sat Jan 26 13:24:01 2013 +0200
+++ b/gamelib/scenes/bridge.py	Sat Jan 26 15:24:56 2013 +0200
@@ -8,9 +8,9 @@
 
 from pyntnclick.cursor import CursorSprite
 from pyntnclick.state import Scene, Item, Thing, Result
-from pyntnclick.scenewidgets import (InteractNoImage, InteractRectUnion,
-                                  InteractImage, InteractAnimated,
-                                  GenericDescThing)
+from pyntnclick.scenewidgets import (
+    InteractNoImage, InteractRectUnion, InteractImage, InteractAnimated,
+    GenericDescThing, TakeableThing)
 
 from gamelib.scenes.game_constants import PLAYER_ID
 from gamelib.scenes.game_widgets import Door, BaseCamera, make_jim_dialog
@@ -176,8 +176,8 @@
     CURSOR = CursorSprite('stethoscope.png')
 
 
-class StethoscopeThing(Thing):
-    "Stehoscope on the doctor"
+class StethoscopeThing(TakeableThing):
+    "Stethoscope on the doctor"
 
     NAME = 'bridge.stethoscope'
 
@@ -186,13 +186,13 @@
     }
 
     INITIAL = 'stethoscope'
+    ITEM = 'stethoscope'
 
     def get_description(self):
         return "A stethoscope hangs from the neck of the skeleton."
 
     def interact_without(self):
-        self.game.add_inventory_item('stethoscope')
-        self.scene.remove_thing(self)
+        self.take()
         # Fill in the doctor's rect
         self.scene.doctor.rect.append(self.rect)
         return Result("You pick up the stethoscope and verify that the"
@@ -221,7 +221,7 @@
                       " successfully avoid disaster.")
 
 
-class SuperconductorThing(Thing):
+class SuperconductorThing(TakeableThing):
     "Superconductor from the massage chair."
 
     NAME = 'bridge.superconductor'
@@ -231,12 +231,12 @@
     }
 
     INITIAL = 'superconductor'
+    ITEM = 'superconductor'
 
     def interact_without(self):
-        self.game.add_inventory_item('superconductor')
         self.game.scenes['bridge'].things['bridge.massagechair_base'] \
                           .set_data('contains_superconductor', False)
-        self.scene.remove_thing(self)
+        self.take()
         return (Result("The superconductor module unclips easily."),
                 make_jim_dialog(("Prisoner %s. That chair you've destroyed"
                                  " was property of the ship's captain. "
--- a/gamelib/scenes/crew_quarters.py	Sat Jan 26 13:24:01 2013 +0200
+++ b/gamelib/scenes/crew_quarters.py	Sat Jan 26 15:24:56 2013 +0200
@@ -2,8 +2,9 @@
 
 from pyntnclick.cursor import CursorSprite
 from pyntnclick.state import Scene, Item, Thing, Result
-from pyntnclick.scenewidgets import (InteractNoImage, InteractImage,
-                                  InteractAnimated, GenericDescThing)
+from pyntnclick.scenewidgets import (
+    InteractNoImage, InteractImage, InteractAnimated, GenericDescThing,
+    TakeableThing)
 
 from gamelib.scenes.game_constants import PLAYER_ID
 from gamelib.scenes.game_widgets import Door, BaseCamera, make_jim_dialog
@@ -187,7 +188,7 @@
     }
 
 
-class PosterThing(Thing):
+class PosterThing(TakeableThing):
     "A innocent poster on the wall"
 
     NAME = 'crew.poster'
@@ -197,10 +198,10 @@
     }
 
     INITIAL = 'poster'
+    ITEM = 'escher_poster'
 
     def interact_without(self):
-        self.game.add_inventory_item('escher_poster')
-        self.scene.remove_thing(self)
+        self.take()
         return Result("This poster will go nicely on your bedroom wall.")
 
     def get_description(self):
--- a/gamelib/scenes/cryo.py	Sat Jan 26 13:24:01 2013 +0200
+++ b/gamelib/scenes/cryo.py	Sat Jan 26 15:24:56 2013 +0200
@@ -4,9 +4,9 @@
 
 from pyntnclick.cursor import CursorSprite
 from pyntnclick.state import Scene, Item, CloneableItem, Thing, Result
-from pyntnclick.scenewidgets import (InteractNoImage, InteractRectUnion,
-                                  InteractImage, InteractAnimated,
-                                  GenericDescThing)
+from pyntnclick.scenewidgets import (
+    InteractNoImage, InteractRectUnion, InteractImage, InteractAnimated,
+    GenericDescThing, TakeableThing)
 
 from gamelib.scenes.game_constants import PLAYER_ID
 from gamelib.scenes.game_widgets import Door, make_jim_dialog
@@ -416,7 +416,7 @@
         return "A computer terminal, with some text on it."
 
 
-class TitaniumLegThing(Thing):
+class TitaniumLegThing(TakeableThing):
     "Triangle in the cryo room."
 
     NAME = "cryo.titanium_leg"
@@ -426,12 +426,12 @@
         }
 
     INITIAL = "leg"
+    ITEM = 'titanium_leg'
 
     def interact_without(self):
-        self.game.add_inventory_item('titanium_leg')
         self.game.scenes['cryo'].things['cryo.unit.1'].set_data(
                 'contains_titanium_leg', False)
-        self.scene.remove_thing(self)
+        self.take()
         return Result("The skeletal occupant of this cryo unit has an"
                 " artificial femur made of titanium. You take it.")
 
--- a/gamelib/scenes/engine.py	Sat Jan 26 13:24:01 2013 +0200
+++ b/gamelib/scenes/engine.py	Sat Jan 26 15:24:56 2013 +0200
@@ -2,9 +2,9 @@
 
 from pyntnclick.cursor import CursorSprite
 from pyntnclick.state import Scene, Item, Thing, Result
-from pyntnclick.scenewidgets import (InteractNoImage, InteractRectUnion,
-                                  InteractImage, InteractAnimated,
-                                  GenericDescThing)
+from pyntnclick.scenewidgets import (
+    InteractNoImage, InteractRectUnion, InteractImage, InteractAnimated,
+    GenericDescThing, TakeableThing)
 
 from gamelib.scenes.game_constants import PLAYER_ID
 from gamelib.scenes.game_widgets import Door, make_jim_dialog
@@ -68,12 +68,13 @@
                 (562, 422, 30, 31),
             )
         ))
-        self.add_thing(GenericDescThing('engine.engines', 8,
-            "The engines. They don't look like they are working.",
-            (
-                (342, 261, 109, 81),
-            )
-        ))
+        if not self.get_data('engine online'):
+            self.add_thing(GenericDescThing('engine.engines', 8,
+                "The engines. They don't look like they are working.",
+                (
+                    (342, 261, 109, 81),
+                )
+            ))
         self.add_thing(GenericDescThing('engine.laser_cutter', 9,
             "A burned-out laser cutter. It may be responsible for the"
             " hole in the floor.",
@@ -163,7 +164,7 @@
     CURSOR = CursorSprite('can_opener_cursor.png')
 
 
-class CanOpenerThing(Thing):
+class CanOpenerThing(TakeableThing):
     NAME = 'engine.canopener'
 
     INTERACTS = {
@@ -171,13 +172,13 @@
     }
 
     INITIAL = 'canopener'
+    ITEM = 'canopener'
 
     def get_description(self):
         return "A can opener. Looks like you won't be starving"
 
     def interact_without(self):
-        self.game.add_inventory_item('canopener')
-        self.scene.remove_thing(self)
+        self.take()
         return Result("You pick up the can opener. It looks brand new; "
                       "the vacuum has kept it in perfect condition.")
 
--- a/gamelib/scenes/machine.py	Sat Jan 26 13:24:01 2013 +0200
+++ b/gamelib/scenes/machine.py	Sat Jan 26 15:24:56 2013 +0200
@@ -2,8 +2,9 @@
 
 from pyntnclick.state import Scene, Item, Thing, Result
 from pyntnclick.cursor import CursorSprite
-from pyntnclick.scenewidgets import (InteractNoImage, InteractImage,
-                                  InteractAnimated, GenericDescThing)
+from pyntnclick.scenewidgets import (
+    InteractNoImage, InteractImage, InteractAnimated, GenericDescThing,
+    TakeableThing)
 
 from gamelib.scenes.game_widgets import Door
 
@@ -276,7 +277,7 @@
     CURSOR = CursorSprite('machete_cursor.png', 23, 1)
 
 
-class ManualThing(Thing):
+class ManualThing(TakeableThing):
 
     NAME = "machine.manual"
 
@@ -285,10 +286,10 @@
     }
 
     INITIAL = "manual"
+    ITEM = 'manual'
 
     def interact_without(self):
-        self.scene.remove_thing(self)
-        self.game.add_inventory_item("manual")
+        self.take()
         return Result("Ah! The ship's instruction manual. You'd feel better"
                       " if the previous owner wasn't lying next to it with a"
                       " gaping hole in his rib cage.")
--- a/gamelib/scenes/mess.py	Sat Jan 26 13:24:01 2013 +0200
+++ b/gamelib/scenes/mess.py	Sat Jan 26 15:24:56 2013 +0200
@@ -126,6 +126,9 @@
         'cans_available': 3,
     }
 
+    def should_add(self):
+        return self.get_data('cans_available') > 0
+
     def select_interact(self):
         return '%icans' % (self.get_data('cans_available'),)
 
--- a/pyntnclick/scenewidgets.py	Sat Jan 26 13:24:01 2013 +0200
+++ b/pyntnclick/scenewidgets.py	Sat Jan 26 15:24:56 2013 +0200
@@ -129,6 +129,29 @@
         return False
 
 
+class TakeableThing(Thing):
+    "Thing that can be taken."
+
+    INITIAL_DATA = {
+        'taken': False,
+    }
+
+    ITEM = None
+
+    def __init__(self):
+        # In case a subclass replaces INITIAL_DATA and breaks 'taken'.
+        assert self.INITIAL_DATA['taken'] in (True, False)
+        super(TakeableThing, self).__init__()
+
+    def should_add(self):
+        return not self.get_data('taken')
+
+    def take(self):
+        self.set_data('taken', True)
+        self.game.add_inventory_item(self.ITEM)
+        self.scene.remove_thing(self)
+
+
 class GenericDescThing(Thing):
     "Thing with an InteractiveUnionRect and a description"
 
--- a/pyntnclick/state.py	Sat Jan 26 13:24:01 2013 +0200
+++ b/pyntnclick/state.py	Sat Jan 26 15:24:56 2013 +0200
@@ -199,8 +199,13 @@
         self.gd = game.gd
         self.resource = self.gd.resource
         self.sound = self.gd.sound
+        self.set_state(self.game.data)
         self.setup()
 
+    def set_state(self, state):
+        """Hack to allow set_state() to be called before setup()."""
+        pass
+
     def setup(self):
         """Game developers should override this to do their setup.
 
@@ -260,16 +265,14 @@
         self.current_thing = None
         self._background = None
 
-    def set_game(self, game):
-        super(Scene, self).set_game(game)
-        self.set_state(game.data)
-
     def add_item(self, item):
         self.game.add_item(item)
 
     def add_thing(self, thing):
+        thing.set_game(self.game)
+        if not thing.should_add():
+            return
         self.things[thing.name] = thing
-        thing.set_game(self.game)
         thing.set_scene(self)
 
     def remove_thing(self, thing):
@@ -364,6 +367,9 @@
     def get_image(self, *image_name_fragments, **kw):
         return self.resource.get_image(*image_name_fragments, **kw)
 
+    def set_state(self, state):
+        return super(Scene, self).set_state(state)
+
 
 class InteractiveMixin(object):
     def is_interactive(self, tool=None):
@@ -437,6 +443,9 @@
         else:
             self.rect = [x.move(self.scene.OFFSET) for x in self.rect]
 
+    def should_add(self):
+        return True
+
     def set_scene(self, scene):
         assert self.scene is None
         self.scene = scene