Mercurial > rinkhals
comparison gamelib/gameboard.py @ 456:96dbf2c8506e
Factor position cache out into its own class, make Position more useful.
author | Jeremy Thurgood <firxen@gmail.com> |
---|---|
date | Mon, 23 Nov 2009 10:30:22 +0000 |
parents | 4bce845fbe6c |
children | fc648da2334c |
comparison
equal
deleted
inserted
replaced
455:fef4b1686d6c | 456:96dbf2c8506e |
---|---|
38 if e.type == MOUSEBUTTONDOWN: | 38 if e.type == MOUSEBUTTONDOWN: |
39 self.gameboard.use_tool(e) | 39 self.gameboard.use_tool(e) |
40 elif e.type == MOUSEMOTION and self.gameboard.sprite_cursor: | 40 elif e.type == MOUSEMOTION and self.gameboard.sprite_cursor: |
41 self.gameboard.update_sprite_cursor(e) | 41 self.gameboard.update_sprite_cursor(e) |
42 | 42 |
43 | |
44 class AnimalPositionCache(object): | |
45 def __init__(self, gameboard): | |
46 self.gameboard = gameboard | |
47 self.clear() | |
48 | |
49 def clear(self): | |
50 self._cache = {'chicken': {}, 'fox': {}} | |
51 | |
52 def _in_bounds(self, pos): | |
53 return self.gameboard.in_bounds(pos) | |
54 | |
55 def add(self, animal, animal_type): | |
56 if animal and self._in_bounds(animal.pos): | |
57 self._cache[animal_type][animal.pos] = animal | |
58 | |
59 def remove(self, pos, animal_type): | |
60 if pos in self._cache: | |
61 del self._cache[animal_type][pos] | |
62 | |
63 def update(self, old_pos, animal, animal_type): | |
64 self.remove(old_pos, animal_type) | |
65 self.add(animal, animal_type) | |
66 | |
67 def get(self, pos, animal_type): | |
68 return self._cache[animal_type].get(pos, None) | |
69 | |
70 | |
43 class GameBoard(serializer.Simplifiable): | 71 class GameBoard(serializer.Simplifiable): |
44 | 72 |
45 GRASSLAND = tiles.REVERSE_TILE_MAP['grassland'] | 73 GRASSLAND = tiles.REVERSE_TILE_MAP['grassland'] |
46 FENCE = tiles.REVERSE_TILE_MAP['fence'] | 74 FENCE = tiles.REVERSE_TILE_MAP['fence'] |
47 WOODLAND = tiles.REVERSE_TILE_MAP['woodland'] | 75 WOODLAND = tiles.REVERSE_TILE_MAP['woodland'] |
73 self.animal_to_place = None | 101 self.animal_to_place = None |
74 self.sprite_cursor = None | 102 self.sprite_cursor = None |
75 self.chickens = set() | 103 self.chickens = set() |
76 self.foxes = set() | 104 self.foxes = set() |
77 self.buildings = set() | 105 self.buildings = set() |
78 self._pos_cache = { 'fox' : [], 'chicken' : []} | 106 self._pos_cache = AnimalPositionCache(self) |
79 self.cash = 0 | 107 self.cash = 0 |
80 self.wood = 0 | 108 self.wood = 0 |
81 self.eggs = 0 | 109 self.eggs = 0 |
82 self.days = 0 | 110 self.days = 0 |
83 self.killed_foxes = 0 | 111 self.killed_foxes = 0 |
186 def start_day(self): | 214 def start_day(self): |
187 self.day, self.night = True, False | 215 self.day, self.night = True, False |
188 self.tv.sun(True) | 216 self.tv.sun(True) |
189 self.reset_states() | 217 self.reset_states() |
190 self.toolbar.start_day() | 218 self.toolbar.start_day() |
191 self._pos_cache = { 'fox' : [], 'chicken' : []} | 219 self._pos_cache.clear() |
192 self.advance_day() | 220 self.advance_day() |
193 self.clear_foxes() | 221 self.clear_foxes() |
194 for chicken in self.chickens.copy(): | 222 for chicken in self.chickens.copy(): |
195 chicken.start_day(self) | 223 chicken.start_day(self) |
196 self.toolbar.update_egg_counter(self.eggs) | 224 self.toolbar.update_egg_counter(self.eggs) |
619 self.chickens_attack() | 647 self.chickens_attack() |
620 return over | 648 return over |
621 | 649 |
622 def _cache_animal_positions(self): | 650 def _cache_animal_positions(self): |
623 """Cache the current set of fox positions for the avoiding checks""" | 651 """Cache the current set of fox positions for the avoiding checks""" |
624 w, h = self.tv.size | 652 self._pos_cache.clear() |
625 self._pos_cache['fox'] = [[[None for z in range(5)] for y in range(h)] | |
626 for x in range(w)] # NB: Assumes z in [0, 4] | |
627 self._pos_cache['chicken'] = [[[None for z in range(5)] for y in range(h)] | |
628 for x in range(w)] | |
629 for fox in self.foxes: | 653 for fox in self.foxes: |
630 self._add_to_pos_cache(fox, 'fox') | 654 self._pos_cache.add(fox, 'fox') |
631 for chick in self.chickens: | 655 for chick in self.chickens: |
632 self._add_to_pos_cache(chick, 'chicken') | 656 self._pos_cache.add(chick, 'chicken') |
633 | 657 |
634 def _add_to_pos_cache(self, animal, cache_type): | 658 def get_animal_at_pos(self, pos, animal_type): |
635 if self.in_bounds(animal.pos): | 659 return self._pos_cache.get(pos, animal_type) |
636 self._pos_cache[cache_type][animal.pos.x][animal.pos.y][animal.pos.z] = animal | |
637 | |
638 def _update_pos_cache(self, old_pos, animal, cache_type): | |
639 if self.in_bounds(old_pos) and self._pos_cache[cache_type]: | |
640 self._pos_cache[cache_type][old_pos.x][old_pos.y][old_pos.z] = None | |
641 if animal: | |
642 pos = animal.pos | |
643 if self.in_bounds(pos): | |
644 self._pos_cache[cache_type][pos.x][pos.y][pos.z] = animal | |
645 | |
646 def get_animal_at_pos(self, pos, cache_type): | |
647 if not self._pos_cache[cache_type]: | |
648 return None # We don't maintain the cache during the day | |
649 if self.in_bounds(pos): | |
650 return self._pos_cache[cache_type][pos.x][pos.y][pos.z] | |
651 return None | |
652 | 660 |
653 def chickens_scatter(self): | 661 def chickens_scatter(self): |
654 """Chickens outside move around randomly a bit""" | 662 """Chickens outside move around randomly a bit""" |
655 for chicken in [chick for chick in self.chickens if chick.outside()]: | 663 for chicken in [chick for chick in self.chickens if chick.outside()]: |
656 old_pos = chicken.pos | 664 old_pos = chicken.pos |
657 chicken.move(self) | 665 chicken.move(self) |
658 if chicken.pos != old_pos: | 666 self._pos_cache.update(old_pos, chicken, 'chicken') |
659 self._update_pos_cache(old_pos, chicken, 'chicken') | |
660 | 667 |
661 def chickens_chop_wood(self): | 668 def chickens_chop_wood(self): |
662 """Chickens with axes chop down trees near them""" | 669 """Chickens with axes chop down trees near them""" |
663 for chicken in [chick for chick in self.chickens if chick.outside()]: | 670 for chicken in [chick for chick in self.chickens if chick.outside()]: |
664 chicken.chop(self) | 671 chicken.chop(self) |
668 for fox in self.foxes: | 675 for fox in self.foxes: |
669 old_pos = fox.pos | 676 old_pos = fox.pos |
670 fox.move(self) | 677 fox.move(self) |
671 if not fox.safe: | 678 if not fox.safe: |
672 over = False | 679 over = False |
673 if fox.pos != old_pos: | 680 self._pos_cache.update(old_pos, fox, 'fox') |
674 self._update_pos_cache(old_pos, fox, 'fox') | |
675 return over | 681 return over |
676 | 682 |
677 def foxes_attack(self): | 683 def foxes_attack(self): |
678 for fox in self.foxes: | 684 for fox in self.foxes: |
679 fox.attack(self) | 685 fox.attack(self) |
717 | 723 |
718 def kill_fox(self, fox): | 724 def kill_fox(self, fox): |
719 self.killed_foxes += 1 | 725 self.killed_foxes += 1 |
720 self.toolbar.update_fox_counter(self.killed_foxes) | 726 self.toolbar.update_fox_counter(self.killed_foxes) |
721 self.add_cash(self.level.sell_price_dead_fox) | 727 self.add_cash(self.level.sell_price_dead_fox) |
722 self._update_pos_cache(fox.pos, None, 'fox') | |
723 self.remove_fox(fox) | 728 self.remove_fox(fox) |
724 | 729 |
725 def remove_fox(self, fox): | 730 def remove_fox(self, fox): |
731 self._pos_cache.remove(fox.pos, 'fox') | |
726 self.foxes.discard(fox) | 732 self.foxes.discard(fox) |
727 if fox.building: | 733 if fox.building: |
728 fox.building.remove_predator(fox) | 734 fox.building.remove_predator(fox) |
729 if fox in self.tv.sprites: | 735 if fox in self.tv.sprites: |
730 self.tv.sprites.remove(fox) | 736 self.tv.sprites.remove(fox) |
738 if chick.abode: | 744 if chick.abode: |
739 chick.abode.clear_occupant() | 745 chick.abode.clear_occupant() |
740 self.toolbar.update_chicken_counter(len(self.chickens)) | 746 self.toolbar.update_chicken_counter(len(self.chickens)) |
741 if chick in self.tv.sprites and chick.outside(): | 747 if chick in self.tv.sprites and chick.outside(): |
742 self.tv.sprites.remove(chick) | 748 self.tv.sprites.remove(chick) |
743 self._update_pos_cache(chick.pos, None, 'chicken') | 749 self._pos_cache.remove(chick.pos, 'chicken') |
744 | 750 |
745 def remove_building(self, building): | 751 def remove_building(self, building): |
746 if building in self.buildings: | 752 if building in self.buildings: |
747 self.buildings.discard(building) | 753 self.buildings.discard(building) |
748 self.tv.sprites.remove(building, layer='buildings') | 754 self.tv.sprites.remove(building, layer='buildings') |