185 lines
6.9 KiB
Python
185 lines
6.9 KiB
Python
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()
|