Support for intrinsics.
authorNeil Moore <neil@s-z.org>
Thu, 29 May 2008 18:19:14 +0000 (14:19 -0400)
committerNeil Moore <neil@s-z.org>
Thu, 29 May 2008 18:19:14 +0000 (14:19 -0400)
New class thing.Intrinsic.
  Set thing.intrinsics of instances (will be externalized later).

Thing.unwield/place: return a boolean for success, can't place if
unwield failed.
  For future support of cursed items.

New material: lapis.
New items: helmet, mask, and "mask of water breathing"
New attribute "intrinsic" for wieldables.

Randomly generate masks of water breathing.

Each creature has a set of intrinsics and extrinsics (the latter from
worn equipment).
  Methods creature.gain_intr, creature.lose_intr.

Creatures can breathe water if they have "waterbreathing".

Creature.wield/unwield: gain/lose extrinsics.

Display instrinsics in stats panel.
  New method Player.format_intrinsics for support.

creature.py
items/items.itm
level.py
materials/materials.mtl
roguelike.py
thing.py

index 7f6bce6..ae3b055 100644 (file)
@@ -19,6 +19,7 @@
 
 import random
 
+import cacher
 import loc
 import thing
 import ui
@@ -33,9 +34,34 @@ class Creature(thing.Thing):
         self.hpmax = 10
         self.hp = self.hpmax
         self.oxygen = 10
+        
+        self.intrinsics = set()
+        self.extrinsics = set()
 
         self.inv = loc.Inventory(self)
         self.slots = { 'hand': None, 'arm': None, 'body': None, 'head': None }
+
+    def gain_intr(self, intrinsic, permanent = True):
+        if isinstance(intrinsic, thing.Intrinsic):
+            intrinsic = set((intrinsic,))
+        if isinstance(intrinsic, set):
+            if permanent:
+                self.intrinsics |= intrinsic
+            else:
+                self.extrinsics |= intrinsic
+        else:
+            raise Exception("Trying to gain non-intrinsic %s", intrinsic)
+    def lose_intr(self, intrinsic, permanent = True):
+        if isinstance(intrinsic, thing.Intrinsic):
+            intrinsic = set((intrinsic,))
+        if isinstance(intrinsic, set):
+            if permanent:
+                self.intrinsics -= intrinsic
+            else:
+                self.extrinsics -= intrinsic
+        else:
+            raise Exception("Trying to lose non-intrinsic %s", intrinsic)
+
     def holding(self, name):
         return self.slots[name]
     def is_wielding(self, item):
@@ -68,8 +94,8 @@ class Creature(thing.Thing):
 
     def can_breathe(self):
         if isinstance(self.location, loc.Water):
-            # Check for water breathing
-            return False
+            return thing.Intrinsic("waterbreathing") in (
+                    self.intrinsics | self.extrinsics)
         else:
             return True
 
@@ -125,6 +151,10 @@ class Creature(thing.Thing):
             self.unwield(self.holding(slot))
         self.slots[slot] = item
         item.wielded = (self, slot)
+        intrs = item.intrinsics()
+        if intrs:
+            self.gain_intr(set(intrs), permanent = False)
+            
         return True
 
     def unwield(self, item):
@@ -140,8 +170,18 @@ class Creature(thing.Thing):
 
         item.wielded = None
         self.slots[slot] = None
+        if item.intrinsics():
+            self.recompute_extrinsics()
         return True
 
+    def recompute_extrinsics(self):
+        self.extrinsics.clear()
+        for equip in self.slots.values():
+            if equip and equip.intrinsics():
+                self.gain_intr(set(equip.intrinsics()), permanent = False)
+
+
+
 class Player(Creature):
     def __init__(self, location=None):
         Creature.__init__(self, location)
@@ -150,3 +190,6 @@ class Player(Creature):
         return ("@", ui.Color(('Bright' if self.active else '') + 'Magenta').cp)
     def can_swim(self):
         return random.random() < .5
+    def format_intrinsics(self):
+        return " ".join([ intr.abbrev for intr in self.intrinsics ]
+                + [ "/" ] + [ extr.abbrev for extr in self.extrinsics ])
index 9b487d6..63ed869 100644 (file)
@@ -13,7 +13,8 @@ money {
 },
 
 wieldable {
-       slot: unspecified
+       slot: unspecified,
+       intrinsic: "",
 },
 
 weapon {
@@ -38,3 +39,19 @@ shield {
        material: wood,
        slot: arm,
 },
+
+helmet {
+       isa: armor,
+       slot: head,
+},
+
+mask {
+       isa: armor,
+       slot: head,
+},
+
+"mask of water breathing" {
+       isa: mask,
+       material: lapis,
+       intrinsic: "waterbreathing",
+},
index d5369ae..6be9176 100644 (file)
--- a/level.py
+++ b/level.py
@@ -422,17 +422,19 @@ class Level (object):
             raise Exception
 
     def randitems(self):
-        r = 1000*random.random()
-        if r >= 10:
+        r = 10000*random.random()
+        if r >= 100:
             return []
-        elif r >= 5:
+        elif r >= 50:
             return [ thing.ItemClass("gold piece")() ]
-        elif r >= 2:
+        elif r >= 20:
             return [ thing.ItemClass("gem")() ]
-        elif r >= 1:
+        elif r >= 10:
+            return [ thing.ItemClass("sword")() ]
+        elif r >= 2:
             return [ thing.ItemClass("shield")() ]
         else:
-            return [ thing.ItemClass("sword")() ]
+            return [ thing.ItemClass("mask of water breathing")() ]
 
     def loc(self, i, j):
         return self.grid[i][j]
index b1df59e..3e531c1 100644 (file)
@@ -8,4 +8,6 @@ wood (wooden): color=Brown
 
 gold (golden): color=Yellow
 
-stone (stone): color=Gray
+stone: color=Gray
+
+lapis: color=BrightBlue
index 5097b13..20cb5b4 100755 (executable)
@@ -56,8 +56,9 @@ class AppUI:
     def draw_stats(self):
         pl = self.player
         win = self.statpanel.window()
-        win.addstr(0, 1, "HP: %4d / %-4d   O2: %2d / 10"
-                % (pl.hp, pl.hpmax, pl.oxygen))
+        win.erase()
+        win.addstr(0, 1, "HP: %4d / %-4d   O2: %2d / 10   I/E: %s"
+                % (pl.hp, pl.hpmax, pl.oxygen, pl.format_intrinsics()))
         win.refresh()
 
 
index f928878..6ff6cd3 100644 (file)
--- a/thing.py
+++ b/thing.py
@@ -24,6 +24,21 @@ import cacher
 import loc
 import ui
 
+class Intrinsic:
+    __metaclass__ = cacher.FirstArg
+    
+    def __init__(self, name, description, abbrev, gain_msg, lose_msg):
+        self.name = name
+        self.description = description
+        self.abbrev = abbrev
+        self.gain_msg = gain_msg
+        self.lose_msg = lose_msg
+
+intrinsics = set((
+        Intrinsic("waterbreathing", "water breathing", "WB",
+            "You feel gilly", "You feel lungy"),
+        ))
+
 class Material(object):
     __metaclass__ = cacher.FirstArg
 
@@ -145,6 +160,7 @@ class Thing (object):
         self.location = location
         if location is not None:
             self.location.add(self)
+        return True
     def try_move(self, newloc):
         if newloc and newloc.can_hold(self):
             self.place(newloc)
@@ -155,6 +171,8 @@ class Thing (object):
 class Item(Thing):
     wielded = None
     slot = None
+    def intrinsics(self):
+        return [ Intrinsic(i) for i in self.intrinsic.split(" ") if i ]
     def is_item(self):
         return True
     def render(self, pic=None):
@@ -163,10 +181,11 @@ class Item(Thing):
         return self.slot is not None
     def place(self, location):
         if self.wielded:
-            self.unwield()
-        super(Item, self).place(location)
+            if not self.unwield():
+                return False
+        return super(Item, self).place(location)
     def unwield(self):
         if self.wielded:
             # Have the holder unwield it
-            self.wielded[0].unwield(self)
+            return self.wielded[0].unwield(self)