Files
minecraft-bot/tests/test_door_navigation.py
T

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()