def test_notify_player_placement_invalid_movement(self): state = self.setup() state = state.add_penguin(row=0, col=0, color="red") state = state.add_penguin(row=1, col=1, color="white") state = state.finalize() expected_action = Action(start=Coordinate(row=0, col=0), end=Coordinate(row=3, col=2), player_color="red") not_expected_action = Action(start=Coordinate(row=1, col=1), end=Coordinate(row=2, col=2), player_color="white") mocked_strategy_player1 = GenericStrategyComponent() mocked_strategy_player1.choose_action_from_state = MagicMock( return_value=expected_action) mocked_strategy_player2 = GenericStrategyComponent() mocked_strategy_player2.choose_action_from_state = MagicMock( return_value=not_expected_action) player_1_component = PlayerComponent(strategy=mocked_strategy_player1) player_2_component = PlayerComponent(strategy=mocked_strategy_player2) ref = Referee(players=[player_1_component, player_2_component], num_rows=4, num_cols=3) expected = state.kick_player(player_to_kick=state.current_player) ref.state = state ref.end_penguin_placement() ref.notify_players_movement() actual = ref.state self.assertTrue(actual.is_equal(expected))
def get_player_actions_from(self, player: Player) -> List[Action]: """ For the given player, find all possible moves for each of this players penguins. :param player: The player whose possible moves will be calculated. :return: List[Action] representing all possible moves for this Player's penguins """ if player is None: return None if player == 0: return None player_actions = [] for penguin in player.penguins: reachable_tiles = self.board.get_reachable_tiles( penguin.row, penguin.col, [ penguin for _, player in self.players.items() for penguin in player.penguins ]) potential_actions = [] for reachable_tile in reachable_tiles: potential_actions.append( Action(Coordinate(penguin.row, penguin.col), Coordinate(reachable_tile.row, reachable_tile.col), player.color)) player_actions.extend(potential_actions) return player_actions
def test_create_choose_action_base_case_no_children_for_maximizing_player( self): """ If the player has turns > 0 but has no children - end-game - then return the current's player's previous action """ state, *_ = self.setup() production_tree = GameStateTree(state, previous_action=None) expected = Action( player_color=production_tree.state.current_player.color, start=Coordinate(0, 0), end=Coordinate(1, 0)) production_tree.previous_action = expected actual = GenericStrategyComponent.choose_action(tree=production_tree, num_turns=2) self.assertEqual(expected, actual)
def test_create_choose_action_base_case_0_turns(self): """ If the player has 0 turns and it is the currents player turn, then the previous action is return. """ state, *_ = self.setup() production_tree = GameStateTree(state, previous_action=None) production_tree.get_children = MagicMock(return_value=None) expected = Action( player_color=production_tree.state.current_player.color, start=Coordinate(0, 0), end=Coordinate(1, 0)) production_tree.previous_action = expected actual = GenericStrategyComponent.choose_action(tree=production_tree, num_turns=0) self.assertEqual(expected, actual)
def test_create_choose_action_base_case_no_children_for_non_maximizing_player( self): """ If the player has turns > 0 but has no children - end-game - and this is not the maximizing player, then we return None. """ state, *_ = self.setup() production_tree = GameStateTree(state, previous_action=None) production_tree.get_children = MagicMock(return_value=[]) production_tree.previous_action = Action( player_color=production_tree.state.current_player.color, start=Coordinate(0, 0), end=Coordinate(1, 0)) expected = None _, actual = GenericStrategyComponent.minimax(tree=production_tree, num_rounds=2, maximizing_player=Player( "white", 0, 0, [])) self.assertEqual(expected, actual)
def test_create_choose_action_recursive_case_is_maximizing_twice(self): """ In a recursive case where 1 round is played and the all leave nodes are the maximizing players, the minimum of these leave nodes is return. """ state, *_ = self.setup() production_tree = GameStateTree(state, previous_action=None) expected = Action( player_color=production_tree.state.current_player.color, start=Coordinate(0, 0), end=Coordinate(1, 0)) children = [child for child in production_tree.get_children()] for idx, child in enumerate(children): second_players_children = [ second_players_child for second_players_child in child.get_children() ] for jdx, second_players_child in enumerate( second_players_children): if jdx == 1 and idx == 1: score = 0 child.previous_action = expected else: score = 10 modified_player = Player.from_dict({ **second_players_child.state.current_player._asdict(), **{ 'score': score } }) second_players_child.state.current_player = modified_player second_players_child.get_children = MagicMock(return_value=[]) second_players_child.state.check_any_player_can_move = MagicMock( return_value=False) production_tree.get_children = MagicMock(return_value=children) actual = GenericStrategyComponent.choose_action(tree=production_tree, num_turns=2) self.assertEqual(expected, actual)
def test_create_choose_action_recursive_case_is_maximizing_once(self): """ In a scenario where all the children of the maximizing player are leaves - aka end-games - than a tie-breaker decides which action to take. """ state, *_ = self.setup() production_tree = GameStateTree(state, previous_action=None) expected = Action( player_color=production_tree.state.current_player.color, start=Coordinate(0, 0), end=Coordinate(1, 0)) children = [child for child in production_tree.get_children()] for idx, child in enumerate(children): if idx == 1: child.previous_action = expected child.get_children = MagicMock(return_value=[]) production_tree.get_children = MagicMock(return_value=children) actual = GenericStrategyComponent.choose_action(tree=production_tree, num_turns=2) self.assertEqual(expected, actual)