import unittest from snakes.legacy.MasterSnake import MasterSnake from server.GameBoard import GameBoard class TestMasterSnake(unittest.TestCase): def setUp(self): self.snake = MasterSnake() self.game_data = { "board": { "height": 11, "width": 11, "snakes": [ { "id": "snake-1", "body": [ {"x": 0, "y": 0}, {"x": 1, "y": 0}, {"x": 2, "y": 0} ], "head": {"x": 2, "y": 1}, }, { "id": "snake-2", "body": [ {"x": 5, "y": 4}, {"x": 5, "y": 3}, {"x": 6, "y": 3}, {"x": 6, "y": 2} ], "head": {"x": 6, "y": 3}, } ], "food": [ { "x": 2, "y": 0 }, { "x": 10, "y": 8 }, { "x": 5, "y": 5 } ], }, "you": { "id": "snake-1", "body": [ {"x": 0, "y": 0}, {"x": 1, "y": 0}, {"x": 2, "y": 0} ], "head": {"x": 0, "y": 0}, } } def test_avoid_snake_body(self): snakes = self.game_data['board']['snakes'] board_width = self.game_data['board']['width'] board_height = self.game_data['board']['height'] safe_positions = self.snake.avoid_snake_body(snakes, board_width, board_height) self.assertIsInstance(safe_positions, list) self.assertTrue(all(isinstance(pos, dict) for pos in safe_positions)) self.assertTrue(all('x' in pos and 'y' in pos for pos in safe_positions)) def test_find_safe_positions(self): body_positions = {(0, 0), (1, 0), (2, 0), (5, 4), (5, 3), (6, 3), (6, 2)} safe_positions = self.snake.find_safe_positions(body_positions, 11, 11) self.assertNotIn({'x': 0, 'y': 0}, safe_positions) self.assertIn({'x': 10, 'y': 10}, safe_positions) def test_choose_move(self): board = GameBoard( game_id='test-game', width=11, height=11, ruleset={'name': 'standard', 'version': 'v1'}, source='test', map='standard', snake_class=self.snake, ) state = {**self.game_data, 'turn': 0} state['board'] = {**state['board'], 'hazards': []} board.read_game_data(state) move = board.snake_neat_make_a_move() self.assertEqual(move, 'up') self.assertEqual(len(self.snake.get_history()), 1) self.assertEqual(self.snake.get_history()[0]['turn'], 0) self.assertIsInstance(self.snake.get_history()[0]['data'], list) def test_move_towards(self): head = {'x': 0, 'y': 0} food = (5, 5) safe_positions = [{'x': 1, 'y': 0}, {'x': 0, 'y': 1}, {'x': 1, 'y': 1}] direction = self.snake.move_towards(head, food, safe_positions) self.assertIn(direction, ["up", "down", "left", "right"]) def test_find_path_to_food(self): path = self.snake.find_path_to_food(self.game_data) self.assertIsInstance(path, list) self.assertEqual(path[-1], (5, 5)) obstacles = { (part['x'], part['y']) for snake in self.game_data['board']['snakes'] for part in snake['body'] } previous = (0, 0) for position in path: self.assertNotIn(position, obstacles) self.assertEqual(abs(position[0] - previous[0]) + abs(position[1] - previous[1]), 1) previous = position def test_no_reachable_food(self): self.game_data['board']['food'] = [] self.assertIsNone(self.snake.find_path_to_food(self.game_data)) self.game_data['board']['food'] = [{'x': 1, 'y': 0}] self.assertIsNone(self.snake.find_path_to_food(self.game_data)) def test_flood_fill_normalizes_coordinate_dicts(self): start, reachable = self.snake.flood_fill( {'y': 0, 'x': 0}, [{'x': 0, 'y': 1}, {'x': 0, 'y': 2}, {'x': 4, 'y': 4}], ) self.assertEqual(start, (0, 0)) self.assertEqual(reachable, {(0, 0), (0, 1), (0, 2)}) def test_future_move_rejects_walls_bodies_and_small_regions(self): snakes = [{'body': [{'x': 0, 'y': 0}, {'x': 1, 'y': 0}, {'x': 2, 'y': 0}]}] safe = [{'x': 0, 'y': 1}, {'x': 0, 'y': 2}, {'x': 4, 'y': 4}] for position in ({'x': -1, 'y': 0}, {'x': 1, 'y': 0}, {'x': 4, 'y': 4}): with self.subTest(position=position): self.assertFalse(self.snake.is_future_move_safe(position, safe, snakes)) def test_avoid_dead_ends_prefers_connected_escape_region(self): head = {'x': 2, 'y': 2} safe = [{'x': 3, 'y': 2}, {'x': 2, 'y': 3}, {'x': 2, 'y': 4}, {'x': 2, 'y': 5}] snakes = [{'body': [{'x': 2, 'y': 2}, {'x': 2, 'y': 1}, {'x': 2, 'y': 0}]}] self.assertEqual(self.snake.avoid_dead_ends(head, 'right', safe, snakes), 'up') def test_find_direction(self): head = {'x': 0, 'y': 0} safe_positions = [{'x': 1, 'y': 0}, {'x': 0, 'y': 1}, {'x': 1, 'y': 1}] direction = self.snake.find_direction(head, safe_positions) self.assertIn(direction, ["up", "down", "left", "right"]) def test_avoid_dead_ends(self): head = {'x': 0, 'y': 0} move = "right" snakes = self.game_data['board']['snakes'] safe_positions = [{'x': 1, 'y': 0}, {'x': 0, 'y': 1}, {'x': 1, 'y': 1}] new_move = self.snake.avoid_dead_ends(head, move, safe_positions, snakes) self.assertEqual(new_move, 'up') if __name__ == '__main__': unittest.main()