import unittest from munch import Munch from mosfet.bot import ( look_direction_from_eye, navigation_look_target, update_pitch, update_yaw, ) from mosfet.vector import Point3D, Vector3D class LookDirection: def __init__(self, angle): self.angle = angle def length(self): return 2.0 def normalized(self): return self def angleDeg(self, _direction): return self.angle class TestFarmingPitch(unittest.TestCase): def test_aiming_at_a_same_level_crop_uses_eye_height_and_looks_down(self): player = Point3D((0.5, 64.0, 0.5)) crop_center = Point3D((1.5, 64.5, 1.5)) direction = look_direction_from_eye(player, crop_center) self.assertGreater(direction.y, 0) state = Munch(pitch=0.0) update_pitch(state, direction) self.assertGreater(state.pitch, 0.0) def test_pitch_never_looks_more_than_45_degrees_down(self): state = Munch(pitch=0.0) directly_below = LookDirection(0.0) for _ in range(8): update_pitch(state, directly_below) self.assertEqual(state.pitch, 45.0) def test_fixed_yaw_turn_returns_over_the_same_180_degree_arc(self): state = Munch(yaw=-90.0) no_look_direction = Vector3D((0.0, 0.0, 0.0)) for _ in range(6): update_yaw(state, no_look_direction, fixed_target=-270.0) self.assertEqual(state.yaw, -270.0) for _ in range(6): update_yaw(state, no_look_direction, fixed_target=-90.0) self.assertEqual(state.yaw, -90.0) def test_yaw_turns_across_wrap_without_unbounded_rotation(self): state = Munch(yaw=630.0) update_yaw(state, Vector3D((0, 0, -1))) self.assertEqual(state.yaw, -60.0) self.assertGreaterEqual(state.yaw, -180.0) self.assertLess(state.yaw, 180.0) def test_path_navigation_looks_at_the_block_above_its_waypoint(self): path = [(index, 64, 0) for index in range(6)] target = navigation_look_target(path) self.assertEqual(target.tuple(), (4, 65, 0)) self.assertEqual(navigation_look_target([(1, 64, 2)]).tuple(), (1, 65, 2)) self.assertIsNone(navigation_look_target([])) def test_pitch_tracks_look_target_instead_of_a_fixed_farming_angle(self): state = Munch(pitch=0.0) direction_to_crop = LookDirection(45.0) for _ in range(5): update_pitch(state, direction_to_crop) self.assertEqual(state.pitch, 45.0) # Looking level at another target pulls the pitch back toward zero. update_pitch(state, LookDirection(90.0)) self.assertEqual(state.pitch, 35.0) update_pitch(state, None) self.assertEqual(state.pitch, 25.0) if __name__ == '__main__': unittest.main()