changeset 395:2d0ff46118e2

Basic support for z coordinate
author Neil Muller <drnlmuller@gmail.com>
date Thu, 12 Nov 2009 21:14:21 +0000
parents ad77b3b71b08
children 19e583e5cdc0
files gamelib/animal.py gamelib/animations.py gamelib/buildings.py gamelib/gameboard.py gamelib/misc.py
diffstat 5 files changed, 52 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/gamelib/animal.py	Thu Nov 12 15:19:12 2009 +0000
+++ b/gamelib/animal.py	Thu Nov 12 21:14:21 2009 +0000
@@ -26,17 +26,17 @@
         self.image_left = image_left.copy()
         self._image_right = image_right
         self.image_right = image_right.copy()
-        if hasattr(tile_pos, 'to_tuple'):
+        if hasattr(tile_pos, 'to_tile_tuple'):
             self.pos = tile_pos
         else:
-            self.pos = Position(tile_pos[0], tile_pos[1])
+            self.pos = Position(tile_pos[0], tile_pos[1], 0)
         self.equipment = []
         self.accoutrements = []
         self.abode = None
         self.facing = 'left'
 
     def loop(self, tv, _sprite):
-        ppos = tv.tile_to_view(self.pos.to_tuple())
+        ppos = tv.tile_to_view(self.pos.to_tile_tuple())
         self.rect.x = ppos[0]
         self.rect.y = ppos[1]
 
@@ -45,7 +45,7 @@
         if hasattr(self, 'DEATH_SOUND'):
             sound.play_sound(self.DEATH_SOUND)
         if hasattr(self, 'DEATH_ANIMATION'):
-            self.DEATH_ANIMATION(gameboard.tv, self.pos.to_tuple())
+            self.DEATH_ANIMATION(gameboard.tv, self.pos.to_tile_tuple())
         self._game_death(gameboard)
 
     def _game_death(self, gameboard):
@@ -274,7 +274,7 @@
 
     def _cost_tile(self, pos, gameboard):
         if gameboard.in_bounds(pos):
-            this_tile = gameboard.tv.get(pos.to_tuple())
+            this_tile = gameboard.tv.get(pos.to_tile_tuple())
             cost = self.costs.get(tiles.TILE_MAP[this_tile], 100)
         else:
             cost = 100 # Out of bounds is expensive
@@ -294,8 +294,8 @@
                 abs(start_pos.y - final_pos.y) < 2:
             # pgu gets this case wrong on occasion.
             return [final_pos]
-        start = start_pos.to_tuple()
-        end = final_pos.to_tuple()
+        start = start_pos.to_tile_tuple()
+        end = final_pos.to_tile_tuple()
         points = getline(start, end)
         points.remove(start) # exclude start_pos
         if end not in points:
@@ -307,6 +307,9 @@
         """Find the cheapest path to final_pos, and return the next step
            along the path."""
         # We calculate the cost of the direct path
+        if final_pos.z < self.pos.z:
+            # We need to try heading down.
+            return Position(self.pos.x, self.pos.y, self.pos.z - 1)
         direct_path = self._gen_path(self.pos, final_pos)
         min_cost = self._cost_path(direct_path, gameboard)
         min_path = direct_path
@@ -364,6 +367,13 @@
             # Caught a chicken
             self._catch_chicken(self.closest, gameboard)
             return self.pos
+        if self.closest.pos.to_tile_tuple() == self.pos.to_tile_tuple():
+            # Only differ in z, so next step is in z
+            if self.closest.pos.z < self.pos.z:
+                new_z = self.pos.z - 1
+            else:
+                new_z = self.pos.z + 1
+            return Position(self.pos.x, self.pos.y, new_z)
         return self._find_best_path_step(self.closest.pos, gameboard)
 
     def _catch_chicken(self, chicken, gameboard):
@@ -379,11 +389,17 @@
             # We're not moving, so we can skip all the checks
             return new_pos
         final_pos = new_pos
-        blocked = final_pos in self.last_steps
-        moves = [Position(x, y) for x in range(self.pos.x-1, self.pos.x + 2)
-                for y in range(self.pos.y-1, self.pos.y + 2)
-                if Position(x,y) != self.pos and \
-                        Position(x, y) not in self.last_steps]
+        blocked = False # We don't worry about loops on ladders
+        if new_pos.z != self.pos.z:
+            # We can only move up and down a ladder
+            moves = [Position(self.pos.x, self.pos.y, z) for z
+                    in range(self.pos.z-1, self.pos.z + 2) if z >= 0]
+        else:
+            blocked = final_pos in self.last_steps
+            moves = [Position(x, y) for x in range(self.pos.x-1, self.pos.x + 2)
+                    for y in range(self.pos.y-1, self.pos.y + 2)
+                    if Position(x,y) != self.pos and
+                    Position(x, y) not in self.last_steps and self.pos.z == 0]
         for fox in gameboard.foxes:
             if fox is not self and fox.pos == final_pos:
                 blocked = True
@@ -405,7 +421,7 @@
             # No good choice, so stay put
             return self.pos
         if gameboard.in_bounds(final_pos):
-            this_tile = gameboard.tv.get(final_pos.to_tuple())
+            this_tile = gameboard.tv.get(final_pos.to_tile_tuple())
         else:
             this_tile = tiles.REVERSE_TILE_MAP['woodland']
         if tiles.TILE_MAP[this_tile] == 'broken fence' and self.hunting:
@@ -426,7 +442,7 @@
 
     def _make_hole(self, gameboard):
         """Make a hole in the fence"""
-        fence = gameboard.get_building(self.dig_pos.to_tuple())
+        fence = gameboard.get_building(self.dig_pos.to_tile_tuple())
         # Another fox could have made the same hole this turn
         if fence:
             fence.damage(gameboard.tv)
@@ -442,7 +458,7 @@
                 # Check the another fox hasn't dug a hole for us
                 # We're too busy digging to notice if a hole appears nearby,
                 # but we'll notice if the fence we're digging vanishes
-                this_tile = gameboard.tv.get(self.dig_pos.to_tuple())
+                this_tile = gameboard.tv.get(self.dig_pos.to_tile_tuple())
                 if tiles.TILE_MAP[this_tile] == 'broken fence':
                     self.tick = 0 
                 return
@@ -480,7 +496,7 @@
         """Setup dig parameters, to be overridden if needed"""
         self.tick = 0 # Costs us nothing to go through a fence.
         self.dig_pos = dig_pos
-        self.DIG_ANIMATION(gameboard.tv, dig_pos.to_tuple())
+        self.DIG_ANIMATION(gameboard.tv, dig_pos.to_tile_tuple())
         self._make_hole(gameboard)
 
 class GreedyFox(Fox):
@@ -513,7 +529,7 @@
 
     def _make_hole(self, gameboard):
         """The Rinkhals eats fences"""
-        fence = gameboard.get_building(self.dig_pos.to_tuple())
+        fence = gameboard.get_building(self.dig_pos.to_tile_tuple())
         if fence:
             fence.remove(gameboard.tv)
             gameboard.remove_building(fence)
--- a/gamelib/animations.py	Thu Nov 12 15:19:12 2009 +0000
+++ b/gamelib/animations.py	Thu Nov 12 21:14:21 2009 +0000
@@ -33,9 +33,9 @@
 class WeaponAnimation(Animation):
     def __init__(self, tv, wielder, layer='animations'):
         if wielder.facing == 'right':
-            Animation.__init__(self, tv, wielder.pos.to_tuple(), self.SEQUENCE_RIGHT, layer=layer)
+            Animation.__init__(self, tv, wielder.pos.to_tile_tuple(), self.SEQUENCE_RIGHT, layer=layer)
         else:
-            Animation.__init__(self, tv, wielder.pos.to_tuple(), self.SEQUENCE_LEFT, layer=layer)
+            Animation.__init__(self, tv, wielder.pos.to_tile_tuple(), self.SEQUENCE_LEFT, layer=layer)
 
 
 class MuzzleFlash(WeaponAnimation):
--- a/gamelib/buildings.py	Thu Nov 12 15:19:12 2009 +0000
+++ b/gamelib/buildings.py	Thu Nov 12 21:14:21 2009 +0000
@@ -36,7 +36,8 @@
 
     def get_pos(self):
         bpos = self.building.pos
-        return (bpos[0] + self.offset[0], bpos[1] + self.offset[1])
+        return (bpos[0] + self.offset[0], bpos[1] + self.offset[1],
+                self.offset[2])
 
 class Floor(object):
     """A set of places within a building. Places on a
@@ -66,6 +67,7 @@
     MODIFY_GUN_RANGE = lambda s, x: -1
     BREAKABLE = False
     ABODE = False
+    FLOORS = None
 
     def __init__(self, pos):
         """Initial image, tile vid position, size and tile number for building."""
@@ -84,12 +86,12 @@
 
         self._floors = []
         if self.FLOORS:
-            for f in range(self.FLOORS):
+            for f, z in enumerate(self.FLOORS):
                 places = []
                 for j in range(self.size[1]):
                     row = []
                     for i in range(self.size[0]):
-                        row.append(Place(self, (i, j)))
+                        row.append(Place(self, (i, j, z)))
                     places.append(row)
                 floor = Floor("Floor %s" % (f+1,), places)
                 self._floors.append(floor)
@@ -288,7 +290,7 @@
     IMAGE = 'sprites/henhouse.png'
     SELECTED_IMAGE = 'sprites/select_henhouse.png'
     NAME = 'Henhouse'
-    FLOORS = 1
+    FLOORS = [0]
 
 class DoubleStoryHenHouse(HenHouse):
     """A double story hen house."""
@@ -300,7 +302,7 @@
     IMAGE = 'sprites/hendominium.png'
     SELECTED_IMAGE = 'sprites/select_hendominium.png'
     NAME = 'Hendominium'
-    FLOORS = 2
+    FLOORS = [0, 1]
 
 class GuardTower(Abode):
     """A GuardTower."""
@@ -312,7 +314,7 @@
     IMAGE = 'sprites/watchtower.png'
     SELECTED_IMAGE = 'sprites/select_watchtower.png'
     NAME = 'Watchtower'
-    FLOORS = 1
+    FLOORS = [2]
 
     MODIFY_GUN_RANGE = lambda s, x: (3*x)/2
     MODIFY_GUN_BASE_HIT = lambda s, x: x-5
@@ -336,7 +338,6 @@
     IMAGE_BROKEN = 'tiles/broken_fence.png'
     SELECTED_IMAGE_BROKEN = 'tiles/broken_fence.png'
     NAME = 'Fence'
-    FLOORS = 0
 
 
 def is_building(obj):
--- a/gamelib/gameboard.py	Thu Nov 12 15:19:12 2009 +0000
+++ b/gamelib/gameboard.py	Thu Nov 12 21:14:21 2009 +0000
@@ -776,8 +776,8 @@
         for fox in self.foxes.copy():
             # Any foxes that didn't make it to the woods are automatically
             # killed
-            if self.in_bounds(fox.pos) and self.tv.get(fox.pos.to_tuple()) \
-                    != self.WOODLAND:
+            if self.in_bounds(fox.pos) and \
+                    self.tv.get(fox.pos.to_tile_tuple()) != self.WOODLAND:
                 self.kill_fox(fox)
             else:
                 self.tv.sprites.remove(fox)
--- a/gamelib/misc.py	Thu Nov 12 15:19:12 2009 +0000
+++ b/gamelib/misc.py	Thu Nov 12 21:14:21 2009 +0000
@@ -8,23 +8,24 @@
 class Position(object):
     """2D position / vector"""
 
-    def __init__(self, x, y):
+    def __init__(self, x, y, z=0):
         self.x = x
         self.y = y
+        self.z = z
 
-    def to_tuple(self):
+    def to_tile_tuple(self):
         return self.x, self.y
 
     def dist(self, b):
         """Gives the distance to another position"""
 
-        return max(abs(self.x - b.x), abs(self.y - b.y))
+        return max(abs(self.x - b.x), abs(self.y - b.y), abs(self.z - b.z))
 
     def __sub__(self, b):
-        return Position(self.x - b.x, self.y - b.y)
+        return Position(self.x - b.x, self.y - b.y, self.z - b.z)
 
     def __add__(self, b):
-        return Position(self.x + b.x, self.y + b.y)
+        return Position(self.x + b.x, self.y + b.y, self.z + b.z)
 
     def left_of(self, b):
         return self.x < b.x
@@ -33,7 +34,7 @@
         return self.x > b.x
 
     def __eq__(self, b):
-        return self.x == b.x and self.y == b.y
+        return self.x == b.x and self.y == b.y and self.z == b.z
 
 class WeightedSelection(object):
     def __init__(self, weightings=None):