# HG changeset patch # User Neil Muller # Date 1258472610 0 # Node ID 3294929223bd18bf02298b62b6eeeb658cbcc82e # Parent 082b1ea5f98d4247833404ede9cf0abdc55fb772 Cache fox positions to avoid a repeated loop diff -r 082b1ea5f98d -r 3294929223bd gamelib/animal.py --- a/gamelib/animal.py Mon Nov 16 15:27:36 2009 +0000 +++ b/gamelib/animal.py Tue Nov 17 15:43:30 2009 +0000 @@ -403,28 +403,28 @@ 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) + 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 final_pos = new_pos - 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 - if fox.pos in moves: - moves.remove(fox.pos) if blocked: - # find the cheapest point in moves to new_pos that's not blocked + 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: + 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] + # find the cheapest point in moves that's not blocked final_pos = None min_cost = 1000 for poss in moves: + if gameboard.is_fox_at_pos(poss): + continue # blocked cost = self._cost_tile(poss, gameboard) if cost < min_cost: min_cost = cost diff -r 082b1ea5f98d -r 3294929223bd gamelib/gameboard.py --- a/gamelib/gameboard.py Mon Nov 16 15:27:36 2009 +0000 +++ b/gamelib/gameboard.py Tue Nov 17 15:43:30 2009 +0000 @@ -292,6 +292,7 @@ self.chickens = set() self.foxes = set() self.buildings = [] + self._fox_pos_cache = [] self.cash = 0 self.eggs = 0 self.days = 0 @@ -366,6 +367,7 @@ self.tv.sun(False) self.reset_states() self.toolbar.update_fin_tool(self.day) + self._cache_fox_positions() def start_day(self): self.day, self.night = True, False @@ -802,12 +804,35 @@ self.chickens_attack() return over + def _cache_fox_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)] + for x in range(w)] # NB: Assumes z in [0, 4] + for fox in self.foxes: + if self.in_bounds(fox.pos): + self._fox_pos_cache[pos.x][pos.y][pos.z] = True + + 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 is_fox_at_pos(self, pos): + if self.in_bounds(pos): + return self._fox_pos_cache[pos.x][pos.y][pos.z] + return False + def foxes_move(self): over = True for fox in self.foxes: + old_pos = fox.pos fox.move(self) if not fox.safe: over = False + if fox.pos != old_pos: + self._update_fox_pos_cache(old_pos, fox.pos) return over def foxes_attack(self): @@ -869,6 +894,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.remove_fox(fox) def remove_fox(self, fox):