changeset 109:48019afde338

Equipment purchasing and some toolbar tweaks.
author Jeremy Thurgood <firxen@gmail.com>
date Wed, 02 Sep 2009 18:46:10 +0000
parents 437cbd856a03
children f67f4dc1ef48
files gamelib/animal.py gamelib/buildings.py gamelib/equipment.py gamelib/gameboard.py
diffstat 4 files changed, 82 insertions(+), 31 deletions(-) [+]
line wrap: on
line diff
--- a/gamelib/animal.py	Wed Sep 02 18:42:00 2009 +0000
+++ b/gamelib/animal.py	Wed Sep 02 18:46:10 2009 +0000
@@ -9,6 +9,7 @@
 import tiles
 from misc import Position
 import sound
+import equipment
 
 class Animal(Sprite):
     """Base class for animals"""
@@ -49,7 +50,7 @@
         self.equipment.append(item)
 
     def weapons(self):
-        return [e for e in self.equipment if e.is_weapon]
+        return [e for e in self.equipment if equipment.is_weapon(e)]
 
     def covers(self, tile_pos):
         return tile_pos[0] == self.pos.x and tile_pos[1] == self.pos.y
--- a/gamelib/buildings.py	Wed Sep 02 18:42:00 2009 +0000
+++ b/gamelib/buildings.py	Wed Sep 02 18:46:10 2009 +0000
@@ -8,6 +8,7 @@
 class Building(Sprite):
     """Base class for buildings"""
 
+    IS_BUILDING = True
     GRASSLAND = tiles.REVERSE_TILE_MAP['grassland']
 
     def __init__(self, pos):
@@ -123,7 +124,7 @@
 
 def is_building(obj):
     """Return true if obj is a build class."""
-    return hasattr(obj, "NAME")
+    return getattr(obj, "IS_BUILDING", False) and hasattr(obj, "NAME")
 
 BUILDINGS = []
 for name in dir():
--- a/gamelib/equipment.py	Wed Sep 02 18:42:00 2009 +0000
+++ b/gamelib/equipment.py	Wed Sep 02 18:46:10 2009 +0000
@@ -4,27 +4,64 @@
 import sound
 
 class Equipment(object):
-    is_weapon = False
+    IS_EQUIPMENT = True
+
+    def __init__(self):
+        self._buy_price = self.BUY_PRICE
+        self._sell_price = self.SELL_PRICE
+        self._name = self.NAME
+
+    def buy_price(self):
+        return self._buy_price
+
+    def sell_price(self):
+        return self._sell_price
+
+    def name(self):
+        return self._name
 
 class Weapon(Equipment):
-    is_weapon = True
+    IS_WEAPON = True
 
     def in_range(self, gameboard, wielder, target):
         """Can the lucky wielder hit the potentially unlucky target with this?"""
-        return False
+        return wielder.pos.dist(target.pos) <= self.RANGE
 
     def hit(self, gameboard, wielder, target):
         """Is the potentially unlucky target actually unlucky?"""
-        return False
+        if hasattr(self, 'HIT_SOUND'):
+            sound.play_sound(self.HIT_SOUND)
+        roll = random.randint(1, 100)
+        return roll > self.BASE_HIT + self.RANGE_MODIFIER*wielder.pos.dist(target.pos)
+
+    def place(self, animal):
+        for eq in animal.equipment:
+            if self.NAME == eq.NAME:
+                return False
+        return True
 
 class Rifle(Weapon):
-    def in_range(self, gameboard, wielder, target):
-        """For now, we ignore terrain and just assume we can hit
-        anything that isn't too far away."""
-        return wielder.pos.dist(target.pos) <= 3
+    NAME = "rifle"
+    BUY_PRICE = 20
+    SELL_PRICE = 15
+
+    RANGE = 3
+    BASE_HIT = 50
+    RANGE_MODIFIER = 10
+    HIT_SOUND = "fire-rifle.ogg"
 
-    def hit(self, gameboard, wielder, target):
-        """Closer is more accurate."""
-        sound.play_sound("fire-rifle.ogg")
-        return random.randint(1, 100) > 60 + 10*wielder.pos.dist(target.pos)
+def is_equipment(obj):
+    """Return true if obj is a build class."""
+    return getattr(obj, "IS_EQUIPMENT", False) and hasattr(obj, "NAME")
+
+def is_weapon(obj):
+    return is_equipment(obj) and getattr(obj, 'IS_WEAPON', False)
 
+EQUIPMENT = []
+for name in dir():
+    obj = eval(name)
+    try:
+        if is_equipment(obj):
+            EQUIPMENT.append(obj)
+    except TypeError:
+        pass
--- a/gamelib/gameboard.py	Wed Sep 02 18:42:00 2009 +0000
+++ b/gamelib/gameboard.py	Wed Sep 02 18:46:10 2009 +0000
@@ -23,16 +23,25 @@
         self.style.width, self.style.height = self.font.size(self.value)
         self.repaint()
 
+def mklabel(text="         ", color=constants.FG_COLOR):
+    return OpaqueLabel(text, color=color)
+
+def mkcountupdate(counter):
+    def update_counter(self, value):
+        getattr(self, counter).update_value("%s" % value)
+        self.repaint()
+    return update_counter
 
 class ToolBar(gui.Table):
     def __init__(self, gameboard, **params):
         gui.Table.__init__(self, **params)
         self.gameboard = gameboard
-        self.cash_counter = OpaqueLabel("Groats:                ", color=constants.FG_COLOR)
-        self.chicken_counter = OpaqueLabel("         ", color=constants.FG_COLOR)
-        self.killed_foxes = OpaqueLabel("         ", color=constants.FG_COLOR)
+        self.cash_counter = mklabel()
+        self.chicken_counter = mklabel()
+        self.killed_foxes = mklabel()
+        self.rifle_counter = mklabel()
 
-        self.add_counter(None, self.cash_counter)
+        self.add_counter(mklabel("Groats:"), self.cash_counter)
         self.add_counter(icons.CHKN_ICON, self.chicken_counter)
         self.add_counter(icons.KILLED_FOX, self.killed_foxes)
 
@@ -43,6 +52,8 @@
         self.add_tool_button("Buy fence", constants.TOOL_BUY_FENCE)
         for building_cls in buildings.BUILDINGS:
             self.add_tool_button("Buy %s" % (building_cls.NAME,), building_cls)
+        for equipment_cls in equipment.EQUIPMENT:
+            self.add_tool_button("Buy %s" % (equipment_cls.NAME,), equipment_cls)
         self.add_spacer()
         self.add_button("Finished Day", self.day_done)
 
@@ -50,17 +61,9 @@
         import engine
         pygame.event.post(engine.START_NIGHT)
 
-    def update_cash_counter(self, amount):
-        self.cash_counter.update_value("Groats: %s" % amount)
-        self.repaint()
-
-    def update_chicken_counter(self, number):
-        self.chicken_counter.update_value("  %s" % number)
-        self.repaint()
-
-    def update_fox_counter(self, number):
-        self.killed_foxes.update_value("  %s" % number)
-        self.repaint()
+    update_cash_counter = mkcountupdate('cash_counter')
+    update_fox_counter = mkcountupdate('killed_foxes')
+    update_chicken_counter = mkcountupdate('chicken_counter')
 
     def add_spacer(self, height=30):
         self.tr()
@@ -185,6 +188,8 @@
             self.sell_building(self.tv.screen_to_tile(e.pos))
         elif buildings.is_building(self.selected_tool):
             self.buy_building(self.tv.screen_to_tile(e.pos), self.selected_tool)
+        elif equipment.is_equipment(self.selected_tool):
+            self.buy_equipment(self.tv.screen_to_tile(e.pos), self.selected_tool)
 
     def get_chicken(self, tile_pos):
         for chick in self.chickens:
@@ -274,6 +279,15 @@
             self.add_cash(-building.buy_price())
             self.add_building(building)
 
+    def buy_equipment(self, tile_pos, equipment_cls):
+        chicken = self.get_chicken(tile_pos)
+        equipment = equipment_cls()
+        if chicken is None or self.cash < equipment.buy_price():
+            return
+        if equipment.place(chicken):
+            self.add_cash(-equipment.buy_price())
+            chicken.equip(equipment)
+
     def sell_building(self, tile_pos):
         if self.tv.get(tile_pos) == self.FENCE:
             return self.sell_fence(tile_pos)
@@ -390,8 +404,6 @@
                 if roll == 1:
                     # Create a chicken
                     chick = animal.Chicken((x, y))
-                    if random.randint(0, 1) == 0:
-                        chick.equip(equipment.Rifle())
                     self.add_chicken(chick)
             x += 1