# HG changeset patch # User Jeremy Thurgood # Date 1258972222 0 # Node ID 96dbf2c8506e9649a3219d03011300ff74237744 # Parent fef4b1686d6cb8a6d617111f8216f1a85cc1fa04 Factor position cache out into its own class, make Position more useful. diff -r fef4b1686d6c -r 96dbf2c8506e gamelib/gameboard.py --- a/gamelib/gameboard.py Sun Nov 22 17:56:41 2009 +0000 +++ b/gamelib/gameboard.py Mon Nov 23 10:30:22 2009 +0000 @@ -40,6 +40,34 @@ elif e.type == MOUSEMOTION and self.gameboard.sprite_cursor: self.gameboard.update_sprite_cursor(e) + +class AnimalPositionCache(object): + def __init__(self, gameboard): + self.gameboard = gameboard + self.clear() + + def clear(self): + self._cache = {'chicken': {}, 'fox': {}} + + def _in_bounds(self, pos): + return self.gameboard.in_bounds(pos) + + def add(self, animal, animal_type): + if animal and self._in_bounds(animal.pos): + self._cache[animal_type][animal.pos] = animal + + def remove(self, pos, animal_type): + if pos in self._cache: + del self._cache[animal_type][pos] + + def update(self, old_pos, animal, animal_type): + self.remove(old_pos, animal_type) + self.add(animal, animal_type) + + def get(self, pos, animal_type): + return self._cache[animal_type].get(pos, None) + + class GameBoard(serializer.Simplifiable): GRASSLAND = tiles.REVERSE_TILE_MAP['grassland'] @@ -75,7 +103,7 @@ self.chickens = set() self.foxes = set() self.buildings = set() - self._pos_cache = { 'fox' : [], 'chicken' : []} + self._pos_cache = AnimalPositionCache(self) self.cash = 0 self.wood = 0 self.eggs = 0 @@ -188,7 +216,7 @@ self.tv.sun(True) self.reset_states() self.toolbar.start_day() - self._pos_cache = { 'fox' : [], 'chicken' : []} + self._pos_cache.clear() self.advance_day() self.clear_foxes() for chicken in self.chickens.copy(): @@ -621,42 +649,21 @@ def _cache_animal_positions(self): """Cache the current set of fox positions for the avoiding checks""" - w, h = self.tv.size - 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)] + self._pos_cache.clear() for fox in self.foxes: - self._add_to_pos_cache(fox, 'fox') + self._pos_cache.add(fox, 'fox') for chick in self.chickens: - self._add_to_pos_cache(chick, 'chicken') - - def _add_to_pos_cache(self, animal, cache_type): - if self.in_bounds(animal.pos): - self._pos_cache[cache_type][animal.pos.x][animal.pos.y][animal.pos.z] = animal + self._pos_cache.add(chick, 'chicken') - def _update_pos_cache(self, old_pos, animal, cache_type): - if self.in_bounds(old_pos) and self._pos_cache[cache_type]: - 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 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._pos_cache[cache_type][pos.x][pos.y][pos.z] - return None + def get_animal_at_pos(self, pos, animal_type): + return self._pos_cache.get(pos, animal_type) def chickens_scatter(self): """Chickens outside move around randomly a bit""" for chicken in [chick for chick in self.chickens if chick.outside()]: old_pos = chicken.pos chicken.move(self) - if chicken.pos != old_pos: - self._update_pos_cache(old_pos, chicken, 'chicken') + self._pos_cache.update(old_pos, chicken, 'chicken') def chickens_chop_wood(self): """Chickens with axes chop down trees near them""" @@ -670,8 +677,7 @@ fox.move(self) if not fox.safe: over = False - if fox.pos != old_pos: - self._update_pos_cache(old_pos, fox, 'fox') + self._pos_cache.update(old_pos, fox, 'fox') return over def foxes_attack(self): @@ -719,10 +725,10 @@ self.killed_foxes += 1 self.toolbar.update_fox_counter(self.killed_foxes) self.add_cash(self.level.sell_price_dead_fox) - self._update_pos_cache(fox.pos, None, 'fox') self.remove_fox(fox) def remove_fox(self, fox): + self._pos_cache.remove(fox.pos, 'fox') self.foxes.discard(fox) if fox.building: fox.building.remove_predator(fox) @@ -740,7 +746,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') + self._pos_cache.remove(chick.pos, 'chicken') def remove_building(self, building): if building in self.buildings: diff -r fef4b1686d6c -r 96dbf2c8506e gamelib/misc.py --- a/gamelib/misc.py Sun Nov 22 17:56:41 2009 +0000 +++ b/gamelib/misc.py Mon Nov 23 10:30:22 2009 +0000 @@ -9,7 +9,7 @@ import serializer class Position(serializer.Simplifiable): - """2D position / vector""" + """2D/3D position / vector. Assumed immutable.""" SIMPLIFY = ['x', 'y', 'z'] @@ -21,6 +21,9 @@ def to_tile_tuple(self): return self.x, self.y + def to_3d_tuple(self): + return self.x, self.y, self.z + def dist(self, b): """Gives the distance to another position""" @@ -38,8 +41,14 @@ def right_of(self, b): return self.x > b.x + def __hash__(self): + return hash(self.to_3d_tuple()) + def __eq__(self, b): - return self.x == b.x and self.y == b.y and self.z == b.z + return self.to_3d_tuple() == b.to_3d_tuple() + + def __str__(self): + return "" % (self.to_3d_tuple(),) def intermediate_positions(self, b): """Only operates in two dimensions.""" @@ -63,7 +72,7 @@ for item, weight in weightings: self.weightings.append((item, weight)) self.total += weight - + def choose(self): roll = random.uniform(0, self.total) for item, weight in self.weightings: