def test_switching_a_branch_changes_the_current_level_to_a_new_branch(): m = Map(level(1), 2, 2) second = flexmock(Level(2)) second.should_receive("change_branch_to").with_args("mines").once m.levels.add(second) m.current = second m.change_branch_to("mines")
def test_walking_down_a_single_level_in_the_same_branch_that_doesnt_exists(): m = Map(level(1), 1, 1) second = flexmock(Level(2)) flexmock(Level).new_instances(second).once m.current.should_receive("add_stairs").with_args(second, (1, 1)).once second.should_receive("add_stairs").with_args(m.current, (2, 2)).once m.travel_by_stairs(2, (2, 2)) assert m.current == second
def test_moving_up_stairs_to_an_unknown_level_creates_a_new_link_and_level(): m = Map(level(1), 5, 5) fifth = flexmock(Level(5)) fifth.should_receive("has_stairs_at").and_return(False).once fifth.should_receive("add_stairs").with_args(object, (5, 5)) m.current = fifth m.travel_by_stairs(4, (4, 4)) assert m.current.dlvl == 4 assert len(m.levels) == 2
def test_teleporting_to_an_undiscovered_level_doesnt_link(): m = Map(level(1), 1, 1) first = flexmock(Level(1)) m.current = first first.should_receive("add_stairs").never flexmock(Level).new_instances(flexmock(Level(5))).once m.travel_by_teleport(5, (5, 5)) assert m.current.dlvl == 5 assert len(m.levels) == 2
def test_traveling_down_when_a_link_doesnt_exist_creates_a_new_link_and_level(): m = Map(level(1), 1, 1) first = flexmock(Level(1)) first.should_receive("has_stairs_at").and_return(False).once first.should_receive("add_stairs").with_args(object, (1, 1)) m.current = first flexmock(Level).new_instances(flexmock(Level(5))).once m.travel_by_stairs(2, (2, 2)) assert len(m.levels) == 2
def test_moving_upstairs_from_to_a_known_level_that_isnt_yet_linked_with_the_current(): m = Map(level(1), 2, 2) first = flexmock(Level(1)) second = flexmock(Level(2)) m.levels = set([first, second]) m.current = second first.should_receive("add_stairs").with_args(second, (1, 1)).once second.should_receive("add_stairs").with_args(first, (2, 2)).once m.travel_by_stairs(1, (1, 1)) assert m.current.dlvl == 1
def test_traveling_down_an_existing_link_doesnt_create_a_new_link_or_level(): m = Map(level(1), 1, 1) second = Level(2) first = flexmock(Level(1)) first.should_receive("has_stairs_at").and_return(True).once first.should_receive("stairs_at").and_return(second) first.should_receive("add_stairs").never m.current = first m.travel_by_stairs(2, (2, 2)) assert m.current == second
def test_traveling_down_when_a_link_doesnt_exist_creates_a_new_link_and_level( ): m = Map(level(1), 1, 1) first = flexmock(Level(1)) first.should_receive("has_stairs_at").and_return(False).once first.should_receive("add_stairs").with_args(object, (1, 1)) m.current = first flexmock(Level).new_instances(flexmock(Level(5))).once m.travel_by_stairs(2, (2, 2)) assert len(m.levels) == 2
def test_moving_down_main_then_up_one_and_down_to_the_mines_before_mines_are_identified(): levels = level_chain(3, "main") m = Map(levels[-1], 3, 2) m.levels = set(levels) m.travel_by_stairs(2, (2, 3)) assert len(m.levels) == 3 m.move(4, 4) m.travel_by_stairs(3, (4, 4)) assert len(m.levels) == 4 m.change_branch_to("mines") assert len([l for l in m.levels if l.branch == "main"]) == 3 assert len([l for l in m.levels if l.branch == "mines"]) == 1
def test_walking_up_a_single_level_in_the_same_branch_that_already_exists(): first = level(1) m = Map(first, 1, 1) second = flexmock(Level(2)) second.should_receive("add_stairs").once first.should_receive("add_stairs").once flexmock(Level).new_instances(second).once # Travel down once to create the second level m.travel_by_stairs(2, (2, 2)) second.should_receive("has_stairs_at").and_return(True).once second.should_receive("stairs_at").and_return(first).once # Now traveling back up should go back to the first m.travel_by_stairs(1, (1, 1)) assert len(m.levels) == 2 assert m.current == first
def test_moving_upstairs_from_to_a_known_level_that_isnt_yet_linked_with_the_current( ): m = Map(level(1), 2, 2) first = flexmock(Level(1)) second = flexmock(Level(2)) m.levels = set([first, second]) m.current = second first.should_receive("add_stairs").with_args(second, (1, 1)).once second.should_receive("add_stairs").with_args(first, (2, 2)).once m.travel_by_stairs(1, (1, 1)) assert m.current.dlvl == 1
def test_moving_changes_current_position(): m = Map(level(1), 1, 1) m.move(5, 5) assert m.location == (5, 5)
def __init__(self): self.graph = Map(Level(1), 0, 0) self.level = 1 self.went_through_lvl_tel = False
def __init__(self, events): self.graph = Map(Level(1), 0, 0) self.level = 1 self.went_through_lvl_tel = False self.events = events
def test_moving_down_main_then_up_one_and_down_to_the_mines_before_mines_are_identified( ): levels = level_chain(3, "main") m = Map(levels[-1], 3, 2) m.levels = set(levels) m.travel_by_stairs(2, (2, 3)) assert len(m.levels) == 3 m.move(4, 4) m.travel_by_stairs(3, (4, 4)) assert len(m.levels) == 4 m.change_branch_to("mines") assert len([l for l in m.levels if l.branch == "main"]) == 3 assert len([l for l in m.levels if l.branch == "mines"]) == 1
class Dungeon: """ The dungeon keeps track of various dungeon states that are helpful to know. It remembers where shops are, remembers where it heard sounds and what they mean, and probably some other stuff that I'll think of in the future. """ def __init__(self, events): self.graph = Map(Level(1), 0, 0) self.level = 1 self.went_through_lvl_tel = False self.events = events def __getstate__(self): d = self.__dict__.copy() del d['events'] return d def listen(self): self.events.listen("level-changed", self._level_changed) self.events.listen("branch-changed", self._branch_changed) self.events.listen("feature-found", self._feature_found) self.events.listen("shop-entered", self._shop_entered) self.events.listen("level-teleported", self._level_teleported) self.events.listen("trap-door-fell", self._level_teleported) self.events.listen("moved", self._moved) def _moved(self, _, cursor): self.graph.move(*cursor) def _shop_entered(self, _, shop_type): if "shop" not in self.current_level().features: self.current_level().features.add("shop") self.current_level().shops.add(shops.types[shop_type]) def _branch_changed(self, _, branch): # I'm really reluctant to put logic in here, beyond just a basic event # handler. However, until Brain is refactored into some more meaningful # structure, there's a couple edge cases where a level can be detected # as "mines" even though it's clearly not the mines. # # Specifically: When in the upper levels of sokoban and traveling # downward. Mines obviously only exists off of "main" or "not sure", it # can never come out of "sokoban". Enforcing that here is the easiest # way to fix weird branching craziness. if branch == "mines" and \ self.current_level().branch not in ["main", "not sure"]: pass else: self.graph.change_branch_to(branch) def _feature_found(self, _, feature): self.current_level().features.add(feature) def _level_teleported(self, _): self.went_through_lvl_tel = True def _level_changed(self, _, level, from_pos, to_pos): if self.level == level: # This seems like it's probably an error. The brain, or whoever is # doing the even dispatching should know not to dispatch a level # change event when, in fact, we clearly have not changed levels. return if abs(self.level - level) > 1 or self.went_through_lvl_tel: self.graph.travel_by_teleport(level, to_pos) self.went_through_lvl_tel = False else: self.graph.travel_by_stairs(level, to_pos) # Update our current position self.level = level def current_level(self): """ Return the level that the player is currently on """ return self.graph.current
def fixed_graph(levels=None): if levels is None: levels = level_chain(5, "main") dmap = Map(levels[0], 0, 0) dmap.levels = set(levels) return dmap
def graph(levels=None): if levels is None: levels = level_chain(5, "main") dmap = Map(levels[0], 0, 0) dmap.levels = set(levels) return dmap
class Dungeon: """ The dungeon keeps track of various dungeon states that are helpful to know. It remembers where shops are, remembers where it heard sounds and what they mean, and probably some other stuff that I'll think of in the future. """ def __init__(self): self.graph = Map(Level(1), 0, 0) self.level = 1 self.went_through_lvl_tel = False def listen(self): dispatcher.add_event_listener("level-change", self._level_change_handler) dispatcher.add_event_listener("branch-change", self._branch_change_handler) dispatcher.add_event_listener("level-feature", self._level_feature_handler) dispatcher.add_event_listener("shop-type", self._shop_type_handler) dispatcher.add_event_listener("level-teleport", self._level_teleport_handler) dispatcher.add_event_listener("trap-door", self._level_teleport_handler) dispatcher.add_event_listener("move", self._map_move_handler) def _map_move_handler(self, _, cursor): self.graph.move(*cursor) def _shop_type_handler(self, _, shop_type): if "shop" not in self.current_level().features: self.current_level().features.add("shop") self.current_level().shops.add(shops.types[shop_type]) def _branch_change_handler(self, _, branch): # I'm really reluctant to put logic in here, beyond just a basic event # handler. However, until Brain is refactored into some more meaningful # structure, there's a couple edge cases where a level can be detected # as "mines" even though it's clearly not the mines. # # Specifically: When in the upper levels of sokoban and traveling # downward. Mines obviously only exists off of "main" or "not sure", it # can never come out of "sokoban". Enforcing that here is the easiest # way to fix weird branching craziness. if branch == "mines" and \ self.current_level().branch not in ["main", "not sure"]: pass else: self.graph.change_branch_to(branch) def _level_feature_handler(self, _, feature): self.current_level().features.add(feature) def _level_teleport_handler(self, _): self.went_through_lvl_tel = True def _level_change_handler(self, _, level, from_pos, to_pos): if self.level == level: # This seems like it's probably an error. The brain, or whoever is # doing the even dispatching should know not to dispatch a level # change event when, in fact, we clearly have not changed levels. return if abs(self.level - level) > 1 or self.went_through_lvl_tel: self.graph.travel_by_teleport(level, to_pos) self.went_through_lvl_tel = False else: self.graph.travel_by_stairs(level, to_pos) # Update our current position self.level = level def current_level(self): """ Return the level that the player is currently on """ return self.graph.current