changeset 401:7405f7db469f

Tweak fox attack logic - we no longer ignore chickens we accidently step on
author Neil Muller <drnlmuller@gmail.com>
date Wed, 18 Nov 2009 15:54:31 +0000
parents d146b7bb9b99
children 3a469d46b820
files gamelib/animal.py gamelib/gameboard.py
diffstat 2 files changed, 34 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/gamelib/animal.py	Tue Nov 17 22:22:47 2009 +0000
+++ b/gamelib/animal.py	Wed Nov 18 15:54:31 2009 +0000
@@ -388,8 +388,10 @@
 
     def attack(self, gameboard):
         """Attack a chicken"""
-        if self.closest and self.closest.pos == self.pos:
-            self._catch_chicken(self.closest, gameboard)
+        chicken = gameboard.get_animal_at_pos(self.pos, 'chicken')
+        if chicken:
+            # Always attack a chicken we step on, even if not hunting
+            self._catch_chicken(chicken, gameboard)
 
     def _catch_chicken(self, chicken, gameboard):
         """Catch a chicken"""
@@ -403,7 +405,7 @@
         if new_pos == self.pos:
             # We're not moving, so we can skip all the checks
             return new_pos
-        blocked = gameboard.is_fox_at_pos(new_pos)
+        blocked = gameboard.get_animal_at_pos(new_pos, 'fox') is not None
         if not blocked and new_pos.z == self.pos.z:
             # We're only worried about loops when not on a ladder
             blocked = new_pos in self.last_steps
@@ -423,7 +425,7 @@
             final_pos = None
             min_cost = 1000
             for poss in moves:
-                if gameboard.is_fox_at_pos(poss):
+                if gameboard.get_animal_at_pos(poss, 'fox'):
                     continue # blocked
                 cost = self._cost_tile(poss, gameboard)
                 if cost < min_cost:
--- a/gamelib/gameboard.py	Tue Nov 17 22:22:47 2009 +0000
+++ b/gamelib/gameboard.py	Wed Nov 18 15:54:31 2009 +0000
@@ -292,7 +292,7 @@
         self.chickens = set()
         self.foxes = set()
         self.buildings = []
-        self._fox_pos_cache = []
+        self._pos_cache = { 'fox' : [], 'chicken' : []}
         self.cash = 0
         self.eggs = 0
         self.days = 0
@@ -367,13 +367,14 @@
         self.tv.sun(False)
         self.reset_states()
         self.toolbar.update_fin_tool(self.day)
-        self._cache_fox_positions()
+        self._cache_animal_positions()
 
     def start_day(self):
         self.day, self.night = True, False
         self.tv.sun(True)
         self.reset_states()
         self.toolbar.update_fin_tool(self.day)
+        self._pos_cache = { 'fox' : [], 'chicken' : []}
 
     def in_bounds(self, pos):
         """Check if a position is within the game boundaries"""
@@ -804,25 +805,35 @@
             self.chickens_attack()
         return over
 
-    def _cache_fox_positions(self):
+    def _cache_animal_positions(self):
         """Cache the current set of fox positions for the avoiding checks"""
         w, h = self.tv.size
-        self._fox_pos_cache = [[[False for z in range(5)] for y in range(h)]
+        self._pos_cache['fox'] = [[[None for z in range(5)] for y in range(h)]
                 for x in range(w)] # NB: Assumes z in [0, 4]
+        self._pos_cache['chicken'] = [[[None for z in range(5)] for y in range(h)]
+                for x in range(w)]
         for fox in self.foxes:
-            if self.in_bounds(fox.pos):
-                self._fox_pos_cache[fox.pos.x][fox.pos.y][fox.pos.z] = True
+            self._add_to_pos_cache(fox, 'fox')
+        for chick in self.chickens:
+            self._add_to_pos_cache(chick, 'chicken')
+
+    def _add_to_pos_cache(self, animal, cache_type):
+        self._pos_cache[cache_type][animal.pos.x][animal.pos.y][animal.pos.z] = animal
 
-    def _update_fox_pos_cache(self, old_pos, new_pos):
-        if self.is_fox_at_pos(old_pos):
-            self._fox_pos_cache[old_pos.x][old_pos.y][old_pos.z] = False
-        if new_pos and self.in_bounds(new_pos):
-            self._fox_pos_cache[new_pos.x][new_pos.y][new_pos.z] = True
+    def _update_pos_cache(self, old_pos, animal, cache_type):
+        if self.in_bounds(old_pos):
+            self._pos_cache[cache_type][old_pos.x][old_pos.y][old_pos.z] = None
+        if animal:
+            pos = animal.pos
+            if self.in_bounds(pos):
+                self._pos_cache[cache_type][pos.x][pos.y][pos.z] = animal
 
-    def is_fox_at_pos(self, pos):
+    def get_animal_at_pos(self, pos, cache_type):
+        if not self._pos_cache[cache_type]:
+            return None # We don't maintain the cache during the day
         if self.in_bounds(pos):
-            return self._fox_pos_cache[pos.x][pos.y][pos.z]
-        return False
+            return self._pos_cache[cache_type][pos.x][pos.y][pos.z]
+        return None
 
     def foxes_move(self):
         over = True
@@ -832,7 +843,7 @@
             if not fox.safe:
                 over = False
             if fox.pos != old_pos:
-                self._update_fox_pos_cache(old_pos, fox.pos)
+                self._update_pos_cache(old_pos, fox, 'fox')
         return over
 
     def foxes_attack(self):
@@ -894,7 +905,7 @@
         self.killed_foxes += 1
         self.toolbar.update_fox_counter(self.killed_foxes)
         self.add_cash(self.level.sell_price_dead_fox)
-        self._update_fox_pos_cache(fox.pos, None)
+        self._update_pos_cache(fox.pos, None, 'fox')
         self.remove_fox(fox)
 
     def remove_fox(self, fox):
@@ -915,6 +926,7 @@
         self.toolbar.update_chicken_counter(len(self.chickens))
         if chick in self.tv.sprites and chick.outside():
             self.tv.sprites.remove(chick)
+        self._update_pos_cache(chick.pos, None, 'chicken')
 
     def remove_building(self, building):
         if building in self.buildings: