def test_create_action_should_return_None_if_given_action_list_is_empty(self): player1 = Player(1, 0, 0, Direction.right, 2, True, "") player2 = Player(2, 0, 2, Direction.down, 3, True, "") players = [player1, player2] cells = [[Cell([player1]), Cell(), Cell()], [Cell(), Cell([player2]), Cell()], [Cell([player2]), Cell(), Cell()]] game = Game(3, 3, cells, players, 2, True, datetime.now()) sut = PathfindingAI(player1, 2, 10) actions = sut.find_actions_by_best_path_connection([], game) self.assertIsNone(actions)
def change_player_status_by_action(player: Player, action: Action): # noqa: C901 """Changes the direction of the player based on the action. Args: player: The player whose direction is to be changed. action: The Action to perform. """ if action == action.turn_left: if player.direction == Direction.up: player.direction = Direction.left elif player.direction == Direction.left: player.direction = Direction.down elif player.direction == Direction.down: player.direction = Direction.right elif player.direction == Direction.right: player.direction = Direction.up elif action == action.turn_right: if player.direction == Direction.up: player.direction = Direction.right elif player.direction == Direction.right: player.direction = Direction.down elif player.direction == Direction.down: player.direction = Direction.left elif player.direction == Direction.left: player.direction = Direction.up elif action == action.speed_up: player.speed += 1 elif action == action.slow_down: player.speed -= 1 if player.speed not in range(1, 11): raise PlayerSpeedNotInRangeException(player)
def test_copying_a_game_should_return_same_game_but_different_identity( self): player1 = Player(1, 1, 1, Direction.up, 0, True, "Name") player2 = Player(2, 1, 0, Direction.up, 0, True, "Name2") player3 = Player(3, 0, 0, Direction.up, 0, True, "Name3") players = [player1, player2, player3] cells = [[Cell([player3]), Cell([player2])], [Cell([]), Cell([player1])]] game = Game(2, 2, cells, players, 2, True, datetime.now()) result = game.copy() self.assertEqual(game, result) self.assertNotEqual(id(game), id(result))
def test_translate_cell_matrix_to_pathfinding_matrix_should_be_correct( self): player1 = Player(1, 0, 0, Direction.up, 1, True, "") player2 = Player(2, 0, 1, Direction.down, 3, True, "") players = [player1, player2] cells = [[Cell([player1]), Cell()], [Cell([player2]), Cell()], [Cell(), Cell()]] game = Game(2, 3, cells, players, 2, True, datetime.now()) expected_matrix = [[0, 1], [0, 1], [1, 1]] matrix = game.translate_cell_matrix_to_pathfinding_matrix() self.assertEqual(matrix, expected_matrix)
def test_create_action_should_return_action_with_best_connection(self): player1 = Player(1, 0, 0, Direction.down, 1, True, "") player2 = Player(2, 0, 2, Direction.down, 3, True, "") players = [player1, player2] cells = [[Cell([player1]), Cell(), Cell()], [Cell(), Cell([player2]), Cell()], [Cell([player2]), Cell(), Cell()]] game = Game(3, 3, cells, players, 2, True, datetime.now()) sut = PathfindingAI(player1, 2, 10) result = Value('i') sut.create_next_action(game, result) self.assertEqual(Action.turn_left, Action.get_by_index(result.value))
def test_raise_exception_for_winner_in_running_game(self): player = Player(1, 0, 0, Direction.up, 0, True, "Name") cells = [[Cell([player]), Cell()]] game = Game(2, 1, cells, [player], 1, True, datetime.now()) with self.assertRaises(Exception): game.get_winner()
def copy(self): """Creates an exact same copy of this game but all objects point to different memory locations. Returns: A copy of the game. """ players: List[Player] = [] for player in self.players: players.append( Player(player.id, player.x, player.y, player.direction, player.speed, player.active, player.name)) cells: List[List[Cell]] = [[Cell() for _ in range(self.width)] for _ in range(self.height)] for row in range(len(self.cells)): for col in range(len(self.cells[row])): if self.cells[row][col].players is not None: players_in_cell = [] for player in self.cells[row][col].players: for copied_player in players: if copied_player.id == player.id: players_in_cell.append(copied_player) cells[row][col].players = players_in_cell return Game(self.width, self.height, cells, players, self.you.id, self.running, self.deadline)
def test_get_random_free_cells_from_playground_should_return_correct_number_of_free_cells(self): player1 = Player(1, 0, 0, Direction.up, 1, True, "") player2 = Player(2, 0, 1, Direction.down, 3, True, "") players = [player1, player2] cells = [[Cell([player1]), Cell(), Cell()], [Cell([player2]), Cell(), Cell()], [Cell(), Cell(), Cell()]] count_free_cells = 5 game = Game(3, 3, cells, players, 2, True, datetime.now()) sut = PathfindingAI(player1, 2, count_free_cells) free_cells_xy = sut.get_random_free_cells_from_playground(game) self.assertEqual(len(free_cells_xy), count_free_cells) for (x, y) in free_cells_xy: self.assertTrue(game.cells[y][x].players is None)
def _create_game(self) -> None: height = randint(30, 70) width = randint(30, 70) player_count = randint(3, 6) players = [] occupied_coordinates = [] for i in range(1, player_count + 1): next_coordinate = (randint(0, width - 1), randint(0, height - 1)) while next_coordinate in occupied_coordinates: next_coordinate = (randint(0, width - 1), randint(0, height - 1)) occupied_coordinates.append(next_coordinate) player = Player(i, next_coordinate[0], next_coordinate[1], Direction.get_random_direction(), 1, True, str(i)) players.append(player) cells = [[Cell() for _ in range(width)] for _ in range(height)] for player in players: cells[player.y][player.x] = Cell([player]) self._game = Game(width, height, cells, players, 1, True, datetime.now() + timedelta(5, 15)) self._game_round = 0 self._ais = [] if self.__evaluation_type == 1: self.__generate_ais_for_first_evaluation(player_count, players) elif self.__evaluation_type == 2: self.__generate_ais_for_second_evaluation(player_count, players)
def test_get_information(self): player = Player(1, 0, 4, Direction.up, 1, True, "") sut = PathfindingAI(player, 2, 10) expected = "max_speed=2, count_paths_to_check=10" result = sut.get_information() self.assertEqual(expected, result)
def test_get_information(self): player = Player(1, 0, 4, Direction.up, 1, True, "") sut = NotKillingItselfAI(player, [], 3, 1, 3) expected = "max_speed=3, max_worse_distance=1, depth=3" result = sut.get_information() self.assertEqual(expected, result)
def setUp(self) -> None: player1 = Player(1, 0, 0, Direction.up, 1, True, "") player2 = Player(2, 0, 1, Direction.down, 3, True, "") players = [player1, player2] cells = [[Cell([player1]), Cell(), Cell(), Cell()], [Cell([player2]), Cell(), Cell(), Cell()], [Cell(), Cell(), Cell(), Cell()], [Cell(), Cell(), Cell(), Cell()]] self.game = Game(4, 4, cells, players, 2, True, datetime.now()) self.sut = PathfindingSearchTreeAI(player1, 2, 100, 2, 0.75) self.data_loader = JSONDataLoader()
def set_player_inactive(self, player: Player): """Sets a player inactive. Args: player: The player to be set inactive. """ if player in self.turn.playersWithPendingAction: self.turn.playersWithPendingAction.remove(player) player.active = False
def test_ai_should_choose_empty_list_with_depth_three_and_no_surviving_action(self): player1 = Player(1, 1, 2, Direction.up, 1, True, "") player2 = Player(2, 1, 1, Direction.down, 3, True, "") players = [player1, player2] cells = [[Cell(), Cell(), Cell(), Cell(), Cell()], [Cell([player2]), Cell([player2]), Cell([player2]), Cell(), Cell()], [Cell(), Cell([player1]), Cell(), Cell([player2]), Cell()], [Cell([player2]), Cell([player2]), Cell(), Cell([player2]), Cell()], [Cell(), Cell(), Cell([player2]), Cell(), Cell()]] time = datetime(2020, 10, 1, 12, 5, 13, 0, timezone.utc) game = Game(5, 5, cells, players, 2, True, time) game_service = GameService(game) sut = NotKillingItselfAI(player1, [], 3, 0, 3) actions: List[Action] = sut.find_surviving_actions(game_service, 3) self.assertTrue(len(actions) == 0)
def test_ai_should_choose_best_list_of_actions_by_depth(self): player1 = Player(1, 1, 2, Direction.up, 1, True, "") player2 = Player(2, 1, 1, Direction.down, 3, True, "") players = [player1, player2] cells = [[Cell(), Cell(), Cell(), Cell(), Cell()], [Cell([player2]), Cell([player2]), Cell([player2]), Cell(), Cell()], [Cell(), Cell([player1]), Cell(), Cell([player2]), Cell()], [Cell([player2]), Cell(), Cell(), Cell([player2]), Cell()], [Cell(), Cell(), Cell([player2]), Cell(), Cell()]] time = datetime(2020, 10, 1, 12, 5, 13, 0, timezone.utc) game = Game(5, 5, cells, players, 2, True, time) game_service = GameService(game) sut = NotKillingItselfAI(player1, [], 3, 0, 5) actions: List[Action] = sut.find_surviving_actions_with_best_depth(game_service) self.assertTrue(Action.turn_right in actions) self.assertTrue(len(actions) == 1)
def test_draws_all_players_correctly(self): player1 = Player(1, 0, 0, Direction.up, 1, True, "p1") player2 = Player(2, 0, 1, Direction.down, 3, True, "") cells = [[Cell([player1]), Cell([player1])], [Cell([player2]), Cell()]] game = Game(2, 2, cells, [player1, player2], 2, True, datetime.now()) expected_calls = [ call(ANY, (255, 61, 0), (0, 0, 10, 10)), call(ANY, (0, 0, 0), (2, 2, 6, 6)), call(ANY, (255, 61, 0), (11, 0, 10, 10)), call(ANY, (156, 204, 101), (0, 11, 10, 10)), call(ANY, (0, 0, 0), (4, 15, 2, 2)), call(ANY, (0, 0, 0), (11, 11, 10, 10)) ] self.sut.update(game) pygame_mock.init.assert_called_once() pygame_mock.draw.rect.assert_has_calls(expected_calls, any_order=False)
def test_ai_should_calc_action_with_max_distance(self): player1 = Player(1, 0, 4, Direction.up, 1, True, "") player2 = Player(2, 0, 1, Direction.down, 3, True, "") players = [player1, player2] cells = [[Cell(), Cell(), Cell(), Cell(), Cell()], [Cell([player2]), Cell(), Cell(), Cell(), Cell()], [Cell(), Cell(), Cell(), Cell(), Cell()], [Cell(), Cell(), Cell(), Cell(), Cell()], [Cell([player1]), Cell(), Cell(), Cell(), Cell()]] time = datetime(2020, 10, 1, 12, 5, 13, 0, timezone.utc) game = Game(5, 5, cells, players, 2, True, time) game_service = GameService(game) sut = NotKillingItselfAI(player1, [], 3, 0, 3) actions: List[Action] = sut.calc_action_with_max_distance_to_visited_cells(game_service, [Action.speed_up, Action.change_nothing, Action.turn_right]) self.assertTrue(Action.turn_right in actions) self.assertTrue(len(actions) == 1)
def test_ai_should_not_choose_speed_up_if_max_speed_is_allready_reached(self): MAX_SPEED = 3 player1 = Player(1, 0, 4, Direction.up, MAX_SPEED, True, "") player2 = Player(2, 0, 1, Direction.down, 3, True, "") players = [player1, player2] cells = [[Cell(), Cell(), Cell(), Cell(), Cell()], [Cell([player2]), Cell(), Cell(), Cell(), Cell()], [Cell(), Cell(), Cell(), Cell(), Cell()], [Cell(), Cell(), Cell(), Cell(), Cell()], [Cell([player1]), Cell(), Cell(), Cell(), Cell()]] time = datetime(2020, 10, 1, 12, 5, 13, 0, timezone.utc) game = Game(5, 5, cells, players, 2, True, time) game_service = GameService(game) sut = NotKillingItselfAI(player1, [], MAX_SPEED, 0, 3) actions: List[Action] = sut.find_surviving_actions(game_service, 1) self.assertTrue(Action.slow_down in actions) self.assertTrue(Action.turn_right in actions) self.assertTrue(len(actions) == 2)
def test_ai_should_choose_the_correct_list_of_actions_non_killing_itself(self): player1 = Player(1, 0, 1, Direction.up, 1, True, "") player2 = Player(2, 4, 4, Direction.down, 3, True, "") players = [player1, player2] cells = [[Cell(), Cell(), Cell(), Cell(), Cell()], [Cell([player1]), Cell(), Cell(), Cell(), Cell()], [Cell(), Cell(), Cell(), Cell(), Cell()], [Cell(), Cell(), Cell(), Cell(), Cell()], [Cell(), Cell(), Cell(), Cell(), Cell([player2])]] time = datetime(2020, 10, 1, 12, 5, 13, 0, timezone.utc) game = Game(5, 5, cells, players, 2, True, time) game_service = GameService(game) sut = NotKillingItselfAI(player1, [], 3, 0, 3) actions: List[Action] = sut.find_surviving_actions(game_service, 3) self.assertTrue(Action.change_nothing in actions) self.assertTrue(Action.turn_right in actions) self.assertTrue(len(actions) == 2)
def get_and_visit_cells(self, player: Player, action: Action) -> List[Tuple[int, int]]: """Simulation of a player performing an action. Args: player: The player who performs the action. action: The Action to perform. Returns: List of field coordinates that the player has visited. """ visited_cells = [] GameService.change_player_status_by_action(player, action) horizontal_multiplier, vertical_multiplier = GameService.get_horizontal_and_vertical_multiplier( player) for i in range(1, player.speed + 1): visited_cells.append((player.x + i * horizontal_multiplier, player.y + i * vertical_multiplier)) # Gap every sixth move, so take only first and last coordinate if self.turn.turn_ctr % 6 == 0 and len(visited_cells) > 1: visited_cells = [visited_cells[0], visited_cells[-1]] visited_cells_result = [] for (x, y) in visited_cells: if x not in range(self.game.width) or y not in range( self.game.height): self.set_player_inactive(player) break player.x = x player.y = y visited_cells_result.append((x, y)) if self.game.cells[y][x].players is None or len( self.game.cells[y][x].players) == 0: self.game.cells[y][x].players = [player] else: self.game.cells[y][x].players.append(player) return visited_cells_result
def load(self, game_data: str) -> Game: """See base class.""" json_data = json.loads(game_data) players = [] cells = [] for json_player in json_data["players"]: player = Player( int(json_player), int(json_data["players"][json_player]["x"]), int(json_data["players"][json_player]["y"]), Direction[json_data["players"][json_player]["direction"]], int(json_data["players"][json_player]["speed"]), json_data["players"][json_player]["active"], json_data["players"][json_player]["name"] if "name" in json_data["players"][json_player] else "") players.append(player) for json_row in json_data["cells"]: row = [] for json_cell in json_row: cell = Cell() if json_cell != 0: if json_cell == -1: # If there is a collision cell, it is not defined by which players this cell is occupied. # Therefore is it always filled with the first player so the cell is not empty. cell = Cell([players[0]]) else: for player in players: if player.id == json_cell: cell = Cell([player]) row.append(cell) cells.append(row) return Game( int(json_data["width"]), int(json_data["height"]), cells, players, int(json_data["you"]), json_data["running"], iso8601.parse_date(json_data["deadline"]) if json_data["running"] else None)
def setUp(self): self.player1 = Player(1, 2, 2, Direction.up, 1, True, "") self.player2 = Player(2, 1, 0, Direction.down, 3, True, "") self.players = [self.player1, self.player2] self.sut = Turn(self.players)
def test_update(self): player1 = Player(1, 0, 0, Direction.up, 1, True, "p1") player2 = Player(2, 0, 1, Direction.down, 3, False, "") cells = [[Cell([player1])], [Cell([player2])]] game = Game(1, 2, cells, [player1, player2], 2, False, datetime.now()) self.sut.update(game)