import unittest from munch import Munch from mosfet.game import Game from mosfet.info import blocks from mosfet.path import Pathfinder class FakeChunks: def __init__(self, states): self.states = states def get_block_at(self, *position): return self.states.get(tuple(position)) class DoorNavigationTests(unittest.TestCase): @staticmethod def door_state(name, half='lower', opened=False, powered=False): data = blocks.MCD_BLOCKS[name] return next( state for state in range(data['minStateId'], data['maxStateId'] + 1) if blocks.PROPS[state].get('half') == half and blocks.PROPS[state].get('open') == str(opened).lower() and blocks.PROPS[state].get('powered') == str(powered).lower()) def test_pathfinder_treats_openable_doors_as_passable_but_not_iron(self): wooden = self.door_state('oak_door') iron = self.door_state('iron_door') opened_iron = self.door_state('iron_door', opened=True) positions = {(1, 64, 0): wooden, (2, 64, 0): iron, (3, 64, 0): opened_iron} g = Munch(chunks=FakeChunks(positions), crawling=False, unopenable_doors=set()) finder = Pathfinder(g) self.assertTrue(finder.bair((1, 64, 0))) self.assertFalse(finder.bair((2, 64, 0))) self.assertTrue(finder.bair((3, 64, 0))) g.unopenable_doors.add((1, 64, 0)) finder = Pathfinder(g) self.assertFalse(finder.bair((1, 64, 0))) def test_pressure_plate_opened_door_is_not_toggled_or_closed(self): door = (1, 64, 0) after = (2, 64, 0) closed = self.door_state('oak_door', powered=True) opened = self.door_state('oak_door', opened=True, powered=True) states = {door: closed} class FakeWorld: @staticmethod def block_at(*position): return states.get(tuple(position)) toggles = [] game = Game.__new__(Game) game.g = Munch( world=FakeWorld(), pos=(0.5, 64, 0.5), yaw=-90.0, path=[door, after], unopenable_doors=set(), look_at=None) game.door_navigation = None game._toggle_door = lambda position, state: toggles.append( (position, state)) self.assertTrue(game.handle_path_doors()) states[door] = opened # the bot steps on a pressure plate self.assertFalse(game.handle_path_doors()) self.assertEqual(game.door_navigation['phase'], 'crossing') self.assertFalse(game.door_navigation['opened_by_bot']) game.g.pos = (2.5, 64, 0.5) self.assertTrue(game.handle_path_doors()) self.assertEqual(game.door_navigation['phase'], 'turning_to_close') game.door_navigation['deadline'] = 0 self.assertTrue(game.handle_path_doors()) self.assertEqual(game.door_navigation['phase'], 'turning_back') self.assertEqual(toggles, []) states[door] = closed game.door_navigation['deadline'] = 0 self.assertFalse(game.handle_path_doors()) self.assertIsNone(game.door_navigation) def test_powered_door_is_left_to_pressure_plate_after_crossing(self): door = (1, 64, 0) after = (2, 64, 0) closed = self.door_state('oak_door', powered=False) powered_open = self.door_state('oak_door', opened=True, powered=True) released_closed = self.door_state('oak_door', powered=False) states = {door: closed} class FakeWorld: @staticmethod def block_at(*position): return states.get(tuple(position)) toggles = [] game = Game.__new__(Game) game.g = Munch( world=FakeWorld(), pos=(0.5, 64, 0.5), yaw=-90.0, path=[door, after], unopenable_doors=set(), look_at=None) game.door_navigation = None game._toggle_door = lambda position, state: toggles.append( (position, state)) game.handle_path_doors() game.door_navigation['deadline'] = 0 game.handle_path_doors() states[door] = powered_open game.handle_path_doors() game.g.pos = (2.5, 64, 0.5) self.assertTrue(game.handle_path_doors()) self.assertEqual(game.door_navigation['phase'], 'turning_to_close') game.door_navigation['deadline'] = 0 self.assertTrue(game.handle_path_doors()) self.assertEqual(game.door_navigation['phase'], 'turning_back') self.assertEqual(toggles, [(door, closed)]) states[door] = released_closed game.door_navigation['deadline'] = 0 self.assertFalse(game.handle_path_doors()) self.assertIsNone(game.door_navigation) def test_opens_door_before_crossing_and_closes_it_after(self): door = (1, 64, 0) after = (2, 64, 0) closed = self.door_state('oak_door', powered=False) opened = self.door_state('oak_door', opened=True, powered=False) states = {door: closed} class FakeWorld: @staticmethod def block_at(*position): return states.get(tuple(position)) @staticmethod def path_to_place(_start, _goal): return None toggles = [] game = Game.__new__(Game) game.g = Munch( world=FakeWorld(), pos=(0.5, 64, 0.5), yaw=-90.0, path=[door, after], unopenable_doors=set(), look_at=None) game.door_navigation = None game._toggle_door = lambda position, state: toggles.append( (position, state)) self.assertTrue(game.handle_path_doors()) self.assertEqual(game.door_navigation['phase'], 'checking') self.assertEqual(toggles, []) game.door_navigation['deadline'] = 0 self.assertTrue(game.handle_path_doors()) self.assertEqual(game.door_navigation['phase'], 'opening') self.assertEqual(toggles, [(door, closed)]) states[door] = opened self.assertFalse(game.handle_path_doors()) self.assertEqual(game.door_navigation['phase'], 'crossing') game.g.pos = (2.5, 64, 0.5) self.assertTrue(game.handle_path_doors()) self.assertEqual(game.door_navigation['phase'], 'turning_to_close') self.assertEqual(game.g.look_at, door) self.assertEqual(len(toggles), 1) game.door_navigation['deadline'] = 0 self.assertTrue(game.handle_path_doors()) self.assertEqual(game.door_navigation['phase'], 'closing') self.assertEqual(toggles[-1], (door, opened)) states[door] = closed self.assertTrue(game.handle_path_doors()) self.assertEqual(game.door_navigation['phase'], 'turning_back') self.assertEqual(game.g.look_at, (4, 64, 0)) game.door_navigation['deadline'] = 0 self.assertFalse(game.handle_path_doors()) self.assertIsNone(game.door_navigation) if __name__ == '__main__': unittest.main()