Example #1
0
    def run_game(args):
        logger.info('| process {} spawned'.format(args.i_))
        seed = None
        p0 = Winner(id=0,
                    seed=seed,
                    timeout_seconds=args.time_seconds_,
                    weights=args.weights_)
        p1 = ExpectimaxWeightedProbabilitiesWithFilterPlayer(
            id=1, seed=seed, timeout_seconds=args.time_seconds_)
        p2 = RandomPlayer(id=2, seed=seed)
        p3 = RandomPlayer(id=3, seed=seed)
        # p3 = ExpectimaxWeightedProbabilitiesWithFilterPlayer(id=3, seed=seed, timeout_seconds=args.time_seconds_)
        state = CatanState([p0, p1, p2, p3], seed)
        count_moves = 0
        while not state.is_final():
            state.make_move(state.get_current_player().choose_move(state))
            state.make_random_move()
            count_moves += 1
        scores = state.get_scores_by_player()
        logger.info('| done iteration {}. scores: {}'.format(
            args.i_, {
                'p0  (new weights)': scores[p0],
                'p1': scores[p1],
                'p2': scores[p2],
                'p3': scores[p3]
            }))

        # TODO: change this block
        count_moves_factor = 1 * count_moves
        p0_factor = 10000 if (scores[p0] >= 10) else 0
        p_others_factor = (sum(scores.values()) - scores[p0]) * 0.2
        res = p0_factor - (p_others_factor * count_moves_factor)

        logger.info('| process {} done. res: {}'.format(args.i_, res))
        return res
Example #2
0
    def run_game(args):
        logger.info('| process {} spawned'.format(args.i_))
        seed = None
        p0 = ExpectimaxWeightedProbabilitiesPlayer(seed, args.time_seconds_,
                                                   args.weights_)
        p1 = ExpectimaxBaselinePlayer(seed, args.time_seconds_)
        state = CatanState([p0, p1], seed)
        count_moves = 0
        while not state.is_final():
            state.make_move(state.get_current_player().choose_move(state))
            state.make_random_move()
            count_moves += 1
        scores = state.get_scores_by_player()
        logger.info('| done iteration {}. scores: {}'.format(
            args.i_, {
                'p0  (new weights)': scores[p0],
                'p1': scores[p1]
            }))

        count_moves_factor = 1 * count_moves
        p0_factor = 10000 if (scores[p0] >= 10) else 0
        p1_factor = scores[p1] * 0.2
        res = p0_factor - (p1_factor * count_moves_factor)

        logger.info('| process {} done. res: {}'.format(args.i_, res))
        return res
Example #3
0
    def winning_heuristic(self, state: CatanState):
        """
        our heuristic for winning the game! it is composed of 3 different heuristics.
        :param state: the state of the game.
        :return: a heuristic score for this state.
        """
        self.scores_by_player = state.get_scores_by_player_indexed()
        my_score = self.scores_by_player[self.get_id()]
        if my_score >= 10:
            return inf
        max_score = max(self.scores_by_player)
        if max_score >= 10:
            return -inf
        if state.is_initialisation_phase():
            return self.heuristic_initialisation_phase(state)
        if self.in_first_phase():
            return self.heuristic_first_phase(state,
                                              self.winner_first_phase_weights)

        return self.heuristic_final_phase(state,
                                          self.winner_last_phase_weights)
def execute_game_given_monte_carlo_branching_factor(branching_factor):
    fileLogger.info('EXEC_GAME: branching_factor={}'.format(branching_factor))
    p0 = ExpectimaxBaselinePlayer(seed, timeout_seconds)  # RandomPlayer(seed)
    p1 = MonteCarloPlayer(seed, timeout_seconds, int(branching_factor))
    state = CatanState([p0, p1], seed)

    count_moves = 0
    while not state.is_final():
        count_moves += 1
        state.make_move(state.get_current_player().choose_move(state))
        state.make_random_move()

    p0_score = state.get_scores_by_player()[p0]
    p1_score = state.get_scores_by_player()[p1]
    count_moves_factor = 1 * count_moves
    p0_factor = p1_score * 0.2
    p1_factor = 1000 if (p1_score >= 10) else 0
    res = - p1_factor + (p0_factor * count_moves_factor)
    fileLogger.info('EXEC_GAME: p0_score={}, p1_score={}, count_moves={}, p0_factor={}, p1_factor={}, '
                    'count_moves_factor={}, res={}'.format(p0_score, p1_score, count_moves, p0_factor, p1_factor,
                                                           count_moves_factor, res))
    excel_data_grabber(p0_score, p1_score, count_moves, res, branching_factor)
    return res
Example #5
0
 def choose_move(self, state: CatanState):
     self.scores_by_player = state.get_scores_by_player_indexed()
     next_moves = state.get_next_moves()
     if len(next_moves) <= 1:
         return next_moves[0]
     if state.is_initialisation_phase():
         best_move, best_score = None, 0
         for move in next_moves:
             state.make_move(move)
             score = self.initialization_phase_heuaristic(state)
             state.unmake_move(move)
             if score > best_score:
                 best_move = move
                 best_score = score
         return best_move
     mcts = MCTS(MCTSNode(state), next_moves, self.exploration_param)
     mcts.do_n_rollouts(self.iterations)
     return mcts.choose().move
 def default_heuristic(self, state: CatanState):
     if state.is_initialisation_phase():
         return self._random_choice([i for i in range(10)])
     # as discussed with Shaul, this isn't zero-sum heuristic, but a max-gain approach where only own player's
     # value is is taken in account
     return float(state.get_scores_by_player()[self])
Example #7
0
def execute_game(plot_map=True):
    seed = None
    timeout_seconds = TIME_OUT
    p0 = Winner(id=0, seed=seed, timeout_seconds=timeout_seconds)
    p1 = ExpectimaxWeightedProbabilitiesWithFilterPlayer(id=1, seed=seed, timeout_seconds=timeout_seconds)
    p2 = RandomPlayer(id=2)
    p3 = RandomPlayer(id=3)
    players = [p0, p1, p2, p3]

    state = CatanState(players, seed)

    turn_count = 0
    score_by_player = state.get_scores_by_player_indexed()

    while not state.is_final():
        # noinspection PyProtectedMember
        logger.info('----------------------p{}\'s turn----------------------'.format(state._current_player_index))

        turn_count += 1
        robber_placement = state.board.get_robber_land()

        move = state.get_current_player().choose_move(state)
        assert not scores_changed(state, score_by_player, state.get_scores_by_player_indexed())
        state.make_move(move)
        state.make_random_move()

        score_by_player = state.get_scores_by_player_indexed()

        move_data = {k: v for k, v in move.__dict__.items() if (v and k != 'resources_updates') and not
        (k == 'robber_placement_land' and v == robber_placement) and not
                     (isinstance(v, dict) and sum(v.values()) == 0)}
        logger.info('| {}| turn: {:3} | move:{} |'.format(''.join('{} '.format(v) for v in score_by_player),
                                                          turn_count, move_data))
        if plot_map:
            image_name = 'turn_{}_scores_{}.png'.format(
                turn_count, ''.join('{}_'.format(v) for v in score_by_player))
            state.board.plot_map(image_name, state.current_dice_number)

    players_scores_by_names = {(k, v.__class__, v.expectimax_alpha_beta.evaluate_heuristic_value.__name__ if (
        isinstance(v, ExpectimaxBaselinePlayer)) else None): score_by_player[v.get_id()]
                               for k, v in locals().items() if v in players
                               }
    names = list(players_scores_by_names.keys())
    names.sort()

    fileLogger.info('\n' + '\n'.join(' {:80} : {} '.format(str(name), players_scores_by_names[name])
                                     for name in names) +
                    '\n turns it took: {}\n'.format(turn_count) + ('-' * 156))

    p0_type = type(p0).__name__
    p_others_type = type(p1).__name__
    global excel_file_name
    excel_file_name = '{}_vs_{}_timeout_{}_seed_{}.xlsx'.format(p0_type, p_others_type, timeout_seconds, seed,
                                                                int(time.time()))
    excel_data_grabber(score_by_player[0], score_by_player[1], score_by_player[2], score_by_player[3], turn_count,
                       p0_type, p_others_type)

    excel_output = ""
    for i in range(len(players)):
        player_output = str(players[i]) + "@" + str(score_by_player[i])
        excel_output += player_output + "\n"
    # fileLogger.info("|\n#" + str(turn_count) + "\n" + excel_output)

    if score_by_player[0] >= 10:
        return 1
    else:
        return 0
Example #8
0
 def setUp(self):
     super().setUp()
     self.players = [FakePlayer(i) for i in range(2)]
     self.state = CatanState(self.players)
Example #9
0
class TestCatanState(TestCase):
    def setUp(self):
        super().setUp()
        self.players = [FakePlayer(i) for i in range(2)]
        self.state = CatanState(self.players)

    def test_is_final(self):
        self.assertFalse(self.state.is_final())

        for i in range(21, 26):
            self.state.board.set_location(self.players[0], i, Colony.City)

        self.assertTrue(self.state.is_final())

    def test_get_next_moves_given_resources_for_single_road(self):
        # given this board
        self.state.board.set_location(self.players[0], 0, Colony.Settlement)
        self.state.board.set_location(self.players[0], 7, Colony.Settlement)
        self.state.board.set_path(self.players[0], (3, 0), Road.Paved)
        self.state.board.set_path(self.players[0], (3, 7), Road.Paved)
        self.state.board.set_location(self.players[1], 39, Colony.Settlement)
        self.state.board.set_location(self.players[1], 40, Colony.Settlement)
        self.state.board.set_path(self.players[1], (39, 44), Road.Paved)
        self.state.board.set_path(self.players[1], (40, 44), Road.Paved)
        self.state.turns_count = 4

        # without resources, assert there's only the "no move" move
        moves = self.state.get_next_moves()
        self.assertEqual(len(moves), 1)
        move = moves[0]
        self.assertIsNone(move.development_card_to_be_exposed)
        self.assertDictEqual(move.paths_to_be_paved, {})
        self.assertListEqual(move.locations_to_be_set_to_settlements, [])
        self.assertListEqual(move.locations_to_be_set_to_cities, [])
        self.assertEqual(move.development_cards_to_be_purchased_count, 0)

        # add resources to pave road
        self.players[0].add_resources_and_piece_for_road()

        # assert only road paving in logical locations is possible
        moves = self.state.get_next_moves()
        self.assertEqual(len(moves), 4)
        expected_possible_roads = {(4, 0), (11, 7), (12, 7)}
        actual_possible_roads = set()
        for move in moves:
            self.assertIsNone(move.development_card_to_be_exposed)
            self.assertListEqual(move.locations_to_be_set_to_settlements, [])
            self.assertListEqual(move.locations_to_be_set_to_cities, [])
            self.assertEqual(move.development_cards_to_be_purchased_count, 0)
            if len(move.paths_to_be_paved) != 0:  # if not the "empty move"
                self.assertEqual(len(move.paths_to_be_paved), 1)
                actual_possible_roads.add(next(iter(move.paths_to_be_paved)))

        self.assertSetEqual(expected_possible_roads, actual_possible_roads)

    def test_get_next_moves_returns_only_moves_that_change_robber_placement_when_dice_roll_7(
            self):
        # given this board
        self.state.board.set_location(self.players[0], 0, Colony.Settlement)
        self.state.board.set_location(self.players[0], 7, Colony.Settlement)
        self.state.board.set_path(self.players[0], (3, 0), Road.Paved)
        self.state.board.set_path(self.players[0], (3, 7), Road.Paved)
        self.state.board.set_location(self.players[1], 50, Colony.Settlement)
        self.state.board.set_location(self.players[1], 42, Colony.Settlement)
        self.state.board.set_path(self.players[1], (50, 46), Road.Paved)
        self.state.board.set_path(self.players[1], (46, 42), Road.Paved)
        self.state.turns_count = 4

        # assert initial robber placement is on the desert land
        self.assertEqual(self.state.board.get_robber_land().resource, None)

        # roll 7
        roll_7 = RandomMove(7, self.state.probabilities_by_dice_values[7],
                            self.state)
        self.state.make_random_move(roll_7)

        # assert all next moves move the robber
        moves = self.state.get_next_moves()
        for move in moves:
            self.assertNotEqual(move.robber_placement_land,
                                self.state.board.get_robber_land())
            self.assertNotEqual(move.robber_placement_land, None)

        # make some move
        self.state.make_move(moves[0])

        # roll 7 again
        self.state.make_random_move(roll_7)

        # assert all next moves move the robber again
        for move in self.state.get_next_moves():
            self.assertNotEqual(move.robber_placement_land,
                                self.state.board.get_robber_land())
            self.assertNotEqual(move.robber_placement_land, None)

    def test_largest_army_is_updated(self):
        for i in range(6):
            if i % 2 == 1:
                # on player2 turn, don't do anything
                self.state.make_move(
                    CatanMove(self.state.board.get_robber_land()))
                continue

            # assert no-one has largest army yet
            player, threshold = self.state._get_largest_army_player_and_size()
            self.assertEqual(player, None)
            self.assertEqual(threshold, 2)

            # add knight dev-card
            self.players[0].add_unexposed_development_card(
                DevelopmentCard.Knight)

            # expose the knight card
            move = CatanMove(self.state.board.get_robber_land())
            move.development_card_to_be_exposed = DevelopmentCard.Knight
            self.state.make_move(move)

        player, threshold = self.state._get_largest_army_player_and_size()
        self.assertEqual(player, self.players[0])
        self.assertEqual(threshold, 3)

    def test_on_knight_card_exposure_players_drop_cards(self):
        robber_placement = self.state.board.get_robber_land()
        self.players[0].add_unexposed_development_card(DevelopmentCard.Knight)

        for move in self.state.get_next_moves():
            if move.development_card_to_be_exposed == DevelopmentCard.Knight:
                self.assertNotEqual(robber_placement,
                                    move.robber_placement_land)
            else:
                self.assertEqual(robber_placement, move.robber_placement_land)

    def test_on_road_building_exposure_player_paves_two_roads(self):
        # given this board
        player = self.players[0]
        self.state.board.set_location(player, 0, Colony.Settlement)
        self.state.board.set_location(player, 7, Colony.Settlement)
        self.state.board.set_path(player, (3, 0), Road.Paved)
        self.state.board.set_path(player, (3, 7), Road.Paved)
        # and player has road-building card
        player.add_unexposed_development_card(DevelopmentCard.RoadBuilding)

        # get all moves
        moves = self.state.get_next_moves()

        # remove the empty move
        moves = list(filter(CatanMove.is_doing_anything, moves))

        # assert moves expose the development-card, and pave two roads
        do_moves_expose_card = (
            m.development_card_to_be_exposed == DevelopmentCard.RoadBuilding
            for m in moves)
        self.assertTrue(all(do_moves_expose_card))

        do_moves_pave_two_roads = (len(m.paths_to_be_paved) == 2
                                   for m in moves)
        self.assertTrue(all(do_moves_pave_two_roads))

    def test_on_monopoly_exposed_players_give_resource(self):
        self.state.board.set_location(self.players[0], 0, Colony.Settlement)
        self.state.board.set_location(self.players[0], 7, Colony.Settlement)
        self.state.board.set_path(self.players[0], (3, 0), Road.Paved)
        self.state.board.set_path(self.players[0], (3, 7), Road.Paved)
        self.state.board.set_location(self.players[1], 39, Colony.Settlement)
        self.state.board.set_location(self.players[1], 40, Colony.Settlement)
        self.state.board.set_path(self.players[1], (39, 44), Road.Paved)
        self.state.board.set_path(self.players[1], (40, 44), Road.Paved)
        self.state.turns_count = 4

        # given player 0 has monopoly dev-card, and player 1 has 1 of each resource
        self.players[0].add_unexposed_development_card(
            DevelopmentCard.Monopoly)
        for resource in Resource:
            self.players[1].add_resource(resource)

        # get all moves
        moves = self.state.get_next_moves()

        # assert correct amount of moves and resources
        self.assertEqual(len(moves), len(Resource) + 1)
        self.assertEqual(self.players[0].get_resource_count(Resource(0)), 0)
        self.assertEqual(self.players[1].get_resource_count(Resource(0)), 1)

        # apply a move that uses monopoly card
        self.state.make_move(moves[1])
        self.state.make_random_move(RandomMove(7, 0.1, self.state))

        # assert cards were taken
        self.assertEqual(self.players[0].get_resource_count(Resource(0)), 1)
        self.assertEqual(self.players[1].get_resource_count(Resource(0)), 0)

        # remove the empty move

    def test_make_move(self):
        self.assertListEqual(
            self.state.board.get_locations_colonised_by_player(
                self.players[0]), [])

        self.players[0].add_resources_and_piece_for_settlement()
        move = CatanMove(self.state.board.get_robber_land())
        move.locations_to_be_set_to_settlements.append(0)
        self.state.make_move(move)

        self.assertListEqual(
            self.state.board.get_locations_colonised_by_player(
                self.players[0]), [0])

    def test_unmake_move(self):
        self.players[0].add_resources_and_piece_for_settlement()
        move = CatanMove(self.state.board.get_robber_land())
        move.locations_to_be_set_to_settlements.append(0)
        self.state.make_move(move)

        self.assertListEqual(
            self.state.board.get_locations_colonised_by_player(
                self.players[0]), [0])

        self.state.unmake_move(move)

    def test_get_current_player(self):
        self.assertEqual(self.state.get_current_player(), self.players[0])
        self.state.make_move(CatanMove(self.state.board.get_robber_land()))
        self.state.make_random_move()
        self.assertEqual(self.state.get_current_player(), self.players[1])
        self.state.make_move(CatanMove(self.state.board.get_robber_land()))
        self.state.make_random_move()
        self.assertEqual(self.state.get_current_player(), self.players[0])

    def test_throw_dice(self):
        self.state.board.set_location(self.players[0], 0, Colony.Settlement)
        self.state.board.set_location(self.players[0], 1, Colony.Settlement)
        self.state.board.set_path(self.players[0], (0, 4), Road.Paved)
        self.state.board.set_path(self.players[0], (4, 1), Road.Paved)
        self.state.board.set_location(self.players[1], 50, Colony.Settlement)
        self.state.board.set_location(self.players[1], 42, Colony.Settlement)
        self.state.board.set_path(self.players[1], (50, 46), Road.Paved)
        self.state.board.set_path(self.players[1], (46, 42), Road.Paved)
        self.state.turns_count = 4

        land_resource = self.state.board._lands[0].resource
        dice_value = self.state.board._lands[0].dice_value

        self.assertEqual(self.players[0].get_resource_count(land_resource), 0)
        roll_dice = RandomMove(
            dice_value, self.state.probabilities_by_dice_values[dice_value],
            self.state)
        self.state.make_random_move(roll_dice)
        self.assertEqual(self.players[0].get_resource_count(land_resource), 1)

    def test_unthrow_dice(self):
        self.state.board.set_location(self.players[0], 0, Colony.Settlement)
        self.state.board.set_location(self.players[0], 29, Colony.Settlement)
        self.state.board.set_path(self.players[0], (0, 4), Road.Paved)
        self.state.board.set_path(self.players[0], (29, 35), Road.Paved)
        self.state.board.set_location(self.players[1], 50, Colony.Settlement)
        self.state.board.set_location(self.players[1], 42, Colony.Settlement)
        self.state.board.set_path(self.players[1], (50, 46), Road.Paved)
        self.state.board.set_path(self.players[1], (46, 42), Road.Paved)
        self.state.turns_count = 4

        land_resource = self.state.board._lands[0].resource
        dice_value = self.state.board._lands[0].dice_value

        roll_dice = RandomMove(
            dice_value, self.state.probabilities_by_dice_values[dice_value],
            self.state)
        self.state.make_random_move(roll_dice)

        self.assertEqual(self.players[0].get_resource_count(land_resource), 1)

        self.state.unmake_random_move(roll_dice)

        self.assertEqual(self.players[0].get_resource_count(land_resource), 0)

    def test_get_all_possible_development_cards_purchase_options(self):
        purchase_count = 2
        options = self.state._get_all_possible_development_cards_purchase_options(
            purchase_count)

        # assert the number of options is (26 choose 2) (because there are 26 unexposed cards)
        number_of_cards_combinations = sum(
            1 for _ in combinations_with_replacement(DevelopmentCard,
                                                     purchase_count))
        self.assertEqual(len(options), number_of_cards_combinations)

        # assert all options are different
        for option1, option2 in combinations(options, 2):
            self.assertNotEqual(option1, option2)
            self.assertNotEqual(option1.purchased_cards_counters,
                                option2.purchased_cards_counters)

        # assert all probabilities are valid probabilities, and there are no moves where probability = 0
        for option in options:
            self.assertLess(option.probability, 1)
            self.assertGreater(option.probability, 0)

        # this assertion is just to make sure I'm testing the probability of the right options
        two_knights_counters = {
            card: purchase_count if card is DevelopmentCard.Knight else 0
            for card in DevelopmentCard
        }
        assert options[0].purchased_cards_counters == two_knights_counters

        # assert the probability is right, given no knight was exposed (there are 15 knight in total)
        two_knight_cards_expected_probability = (15 / 26) * (14 / 25)
        two_knight_cards_actual_probability = options[0].probability
        self.assertAlmostEqual(two_knight_cards_expected_probability,
                               two_knight_cards_actual_probability)

    def test_probability_calculation_given_card_used(self):
        # given this board
        self.state.board.set_location(self.players[0], 0, Colony.Settlement)
        self.state.board.set_location(self.players[0], 7, Colony.Settlement)
        self.state.board.set_path(self.players[0], (3, 0), Road.Paved)
        self.state.board.set_path(self.players[0], (3, 7), Road.Paved)
        self.state.board.set_location(self.players[1], 39, Colony.Settlement)
        self.state.board.set_location(self.players[1], 40, Colony.Settlement)
        self.state.board.set_path(self.players[1], (39, 44), Road.Paved)
        self.state.board.set_path(self.players[1], (40, 44), Road.Paved)
        self.state.turns_count = 4

        # buy two knight cards
        self.state.make_move(CatanMove(self.state.board.get_robber_land()))
        purchase_count = 2
        two_knight_cards_expected_probability = (15 / 26) * (14 / 25)
        two_knights_counters = {
            card: purchase_count if card is DevelopmentCard.Knight else 0
            for card in DevelopmentCard
        }
        self.state.make_random_move(
            RandomMove(
                2, two_knight_cards_expected_probability *
                self.state.probabilities_by_dice_values[2], self.state,
                two_knights_counters))

        # make empty move
        self.state.make_move(CatanMove(self.state.board.get_robber_land()))
        self.state.make_random_move(
            RandomMove(2, self.state.probabilities_by_dice_values[2],
                       self.state))

        # expose one knight
        move = CatanMove(self.state.board._lands[0])
        move.development_card_to_be_exposed = DevelopmentCard.Knight
        self.state.make_move(move)
        self.state.make_random_move(
            RandomMove(2, self.state.probabilities_by_dice_values[2],
                       self.state))

        # get all purchase options of two cards
        options = self.state._get_all_possible_development_cards_purchase_options(
            purchase_count)

        # assert the number of options is (25 choose 2) (because there are 25 unexposed cards)
        number_of_cards_combinations = sum(
            1 for _ in combinations_with_replacement(DevelopmentCard,
                                                     purchase_count))
        self.assertEqual(len(options), number_of_cards_combinations)

        # assert all options are different
        for option1, option2 in combinations(options, 2):
            self.assertNotEqual(option1, option2)
            self.assertNotEqual(option1.purchased_cards_counters,
                                option2.purchased_cards_counters)

        # assert all probabilities are valid probabilities, and there are no moves where probability = 0
        for option in options:
            self.assertLess(option.probability, 1)
            self.assertGreater(option.probability, 0)

        # this assertion is just to make sure I'm testing the probability of the right options
        assert options[0].purchased_cards_counters == two_knights_counters

        # assert the probability is right, given one knight was exposed
        two_knight_cards_expected_probability = (14 / 25) * (13 / 24)
        two_knight_cards_actual_probability = options[0].probability
        self.assertAlmostEqual(two_knight_cards_expected_probability,
                               two_knight_cards_actual_probability)

    def test_get_all_possible_trade_moves_empty_move_no_resources(self):
        empty_move = CatanMove(self.state.board.get_robber_land())
        moves = [empty_move]
        moves = self.state._get_all_possible_trade_moves(moves)
        assert moves == [empty_move]

    def test_get_all_possible_trade_moves_empty_move_not_enough_resources(
            self):
        empty_move = CatanMove(self.state.board.get_robber_land())
        moves = [empty_move]
        moves = self.state._get_all_possible_trade_moves(moves)
        assert moves == [empty_move]
        for _ in range(3):
            for resource in Resource:
                self.players[0].add_resource(resource)
            moves = self.state._get_all_possible_trade_moves(moves)
            assert moves == [empty_move]

    def test_get_all_possible_trade_moves_single_trade(self):
        empty_move = CatanMove(self.state.board.get_robber_land())
        moves = [empty_move]
        moves = self.state._get_all_possible_trade_moves(moves)
        assert moves == [empty_move]
        self.players[0].add_resource(Resource.Lumber, 4)
        moves = self.state._get_all_possible_trade_moves(moves)
        assert moves[0] == empty_move
        assert len(moves[1].resources_exchanges) == 1
        assert len(moves[2].resources_exchanges) == 1
        assert len(moves[3].resources_exchanges) == 1
        assert len(moves[4].resources_exchanges) == 1
        assert len(moves) == 5

    def test_get_all_possible_trade_moves_different_ratio_generic(self):
        empty_move = CatanMove(self.state.board.get_robber_land())
        moves = [empty_move]
        moves = self.state._get_all_possible_trade_moves(moves)
        assert moves == [empty_move]
        self.players[0].add_resource(Resource.Lumber, 2)
        moves = self.state._get_all_possible_trade_moves(moves)
        assert moves == [empty_move]
        self.players[0].add_resource(Resource.Lumber, 1)
        self.state.board._locations_by_harbors[Harbor.HarborGeneric].append(0)
        self.state.board.set_location(self.players[0], 0, Colony.Settlement)
        moves = self.state._get_all_possible_trade_moves(moves)
        assert moves[0] == empty_move
        assert len(moves[1].resources_exchanges) == 1
        assert len(moves[2].resources_exchanges) == 1
        assert len(moves[3].resources_exchanges) == 1
        assert len(moves[4].resources_exchanges) == 1
        assert len(moves) == 5

    def test_get_all_possible_trade_moves_different_ratio_non_generic(self):
        empty_move = CatanMove(self.state.board.get_robber_land())
        moves = [empty_move]
        moves = self.state._get_all_possible_trade_moves(moves)
        assert moves == [empty_move]
        self.players[0].add_resource(Resource.Lumber, 1)
        moves = self.state._get_all_possible_trade_moves(moves)
        assert moves == [empty_move]
        self.players[0].add_resource(Resource.Lumber, 1)
        self.state.board._locations_by_harbors[Harbor.HarborLumber].append(0)
        self.state.board.set_location(self.players[0], 0, Colony.Settlement)
        moves = self.state._get_all_possible_trade_moves(moves)
        assert moves[0] == empty_move
        assert len(moves[1].resources_exchanges) == 1
        assert len(moves[2].resources_exchanges) == 1
        assert len(moves[3].resources_exchanges) == 1
        assert len(moves[4].resources_exchanges) == 1
        assert len(moves) == 5

    def test_get_all_possible_development_cards_exposure_moves(self):
        self.state.board.set_location(self.players[0], 0, Colony.Settlement)
        self.state.board.set_location(self.players[0], 7, Colony.Settlement)
        self.state.board.set_path(self.players[0], (3, 0), Road.Paved)
        self.state.board.set_path(self.players[0], (3, 7), Road.Paved)
        self.state.board.set_location(self.players[1], 39, Colony.Settlement)
        self.state.board.set_location(self.players[1], 40, Colony.Settlement)
        self.state.board.set_path(self.players[1], (39, 44), Road.Paved)
        self.state.board.set_path(self.players[1], (40, 44), Road.Paved)
        self.state.turns_count = 4

        empty_move = CatanMove(self.state.board.get_robber_land())
        moves = [empty_move]
        moves = self.state._get_all_possible_development_cards_exposure_moves(
            moves)
        self.assertEqual(moves, [empty_move])
        self.players[0].add_unexposed_development_card(
            DevelopmentCard.RoadBuilding)
        self.players[0].add_unexposed_development_card(
            DevelopmentCard.YearOfPlenty)
        self.players[0].add_unexposed_development_card(
            DevelopmentCard.Monopoly)
        self.players[0].add_unexposed_development_card(DevelopmentCard.Knight)
        self.players[0].add_unexposed_development_card(
            DevelopmentCard.VictoryPoint)
        moves = self.state._get_all_possible_development_cards_exposure_moves(
            moves)
        self.assertEqual(moves[0], empty_move)
        all_dev_cards = [move.development_card_to_be_exposed for move in moves]
        for dev_card_type in DevelopmentCard:
            assert dev_card_type in all_dev_cards
        self.assertEqual(len(moves), 41)
        knight_dev_applied_moves = [
            move for move in moves
            if move.development_card_to_be_exposed == DevelopmentCard.Knight
        ]
        self.assertEqual(len(knight_dev_applied_moves), 18)
        y_o_p_dev_applied_moves = [
            move for move in moves if move.development_card_to_be_exposed ==
            DevelopmentCard.YearOfPlenty
        ]
        self.assertEqual(len(y_o_p_dev_applied_moves), 15)
        monopoly_dev_applied_moves = [
            move for move in moves
            if move.development_card_to_be_exposed == DevelopmentCard.Monopoly
        ]
        self.assertEqual(len(monopoly_dev_applied_moves), 5)

    def test_get_all_possible_path_moves(self):
        self.state.board.set_location(self.players[0], 0, Colony.Settlement)
        self.state.board.set_location(self.players[0], 7, Colony.Settlement)
        self.state.board.set_path(self.players[0], (3, 0), Road.Paved)
        self.state.board.set_path(self.players[0], (3, 7), Road.Paved)
        self.state.board.set_location(self.players[1], 39, Colony.Settlement)
        self.state.board.set_location(self.players[1], 40, Colony.Settlement)
        self.state.board.set_path(self.players[1], (39, 44), Road.Paved)
        self.state.board.set_path(self.players[1], (40, 44), Road.Paved)
        self.state.turns_count = 4

        empty_move = CatanMove(self.state.board.get_robber_land())
        moves = [empty_move]
        moves = self.state._get_all_possible_paths_moves(moves)
        self.assertEqual(moves, [empty_move])
        self.players[0].add_resource(Resource.Lumber)
        self.players[0].add_resource(Resource.Brick)

        # First player
        moves = [empty_move]
        moves = self.state._get_all_possible_paths_moves(moves)
        self.assertEqual(len(moves), 4)

        # move to next player
        self.state.make_move(empty_move)
        self.state.make_random_move(RandomMove(2, 0.1, self.state))

        self.players[1].add_resource(Resource.Lumber)
        self.players[1].add_resource(Resource.Brick)

        # Second player
        moves = [empty_move]
        moves = self.state._get_all_possible_paths_moves(moves)
        self.assertEqual(len(moves), 6)
Example #10
0
def execute_game(plot_map=True):
    seed = None
    timeout_seconds = 5
    p0 = MonteCarloWithFilterPlayer(seed, timeout_seconds)
    p1 = ExpectimaxBaselinePlayer(seed, timeout_seconds)
    p2 = ExpectimaxBaselinePlayer(seed, timeout_seconds)
    p3 = ExpectimaxBaselinePlayer(seed, timeout_seconds)
    players = [p0, p1, p2, p3]

    state = CatanState(players, seed)

    turn_count = 0
    score_by_player = state.get_scores_by_player()
    if plot_map:
        state.board.plot_map('turn_{}_scores_{}.png'.format(
            turn_count,
            ''.join('{}_'.format(v) for v in score_by_player.values())))

    while not state.is_final():
        # noinspection PyProtectedMember
        logger.info(
            '----------------------p{}\'s turn----------------------'.format(
                state._current_player_index))

        turn_count += 1
        robber_placement = state.board.get_robber_land()

        move = state.get_current_player().choose_move(state)
        assert not scores_changed(state, score_by_player,
                                  state.get_scores_by_player())
        state.make_move(move)
        state.make_random_move()

        score_by_player = state.get_scores_by_player()

        move_data = {
            k: v
            for k, v in move.__dict__.items()
            if (v and k != 'resources_updates')
            and not (k == 'robber_placement_land' and v == robber_placement)
            and not (isinstance(v, dict) and sum(v.values()) == 0)
        }
        logger.info('| {}| turn: {:3} | move:{} |'.format(
            ''.join('{} '.format(v) for v in score_by_player.values()),
            turn_count, move_data))
        if plot_map:
            image_name = 'turn_{}_scores_{}.png'.format(
                turn_count,
                ''.join('{}_'.format(v) for v in score_by_player.values()))
            state.board.plot_map(image_name, state.current_dice_number)

    players_scores_by_names = {
        (k, v.__class__,
         v.expectimax_alpha_beta.evaluate_heuristic_value.__name__ if
         (isinstance(v, ExpectimaxBaselinePlayer)) else None):
        score_by_player[v]
        for k, v in locals().items() if v in players
    }
    fileLogger.info('\n' + '\n'.join(
        ' {:150} : {} '.format(str(name), score)
        for name, score in players_scores_by_names.items()) +
                    '\n turns it took: {}\n'.format(turn_count) + ('-' * 156))

    p0_type = type(p0).__name__
    p_others_type = type(p1).__name__
    global excel_file_name
    excel_file_name = '{}_vs_{}_timeout_{}_seed_{}.xlsx'.format(
        p0_type, p_others_type, timeout_seconds, seed, int(time.time()))
    excel_data_grabber(score_by_player[p0], score_by_player[p1],
                       score_by_player[p2], score_by_player[p3], turn_count,
                       p0_type, p_others_type)
def execute_game(i, iterations, plot_map=True):
    seed = None
    timeout_seconds = 5
    p0 = MCTSPlayer(0, iterations=iterations)
    p1 = RandomPlayer(1)
    p2 = RandomPlayer(2)
    p3 = RandomPlayer(3)
    players = [p0, p1, p2, p3]

    state = CatanState(players, seed)

    turn_count = 0
    score_by_player = state.get_scores_by_player_indexed()
    # if plot_map:
    #     state.board.plot_map('turn_{}_scores_{}.png'
    #                          .format(turn_count, ''.join('{}_'.format(v) for v in score_by_player.values())))

    while not state.is_final():
        # noinspection PyProtectedMember
        logger.info(
            '----------------------p{}\'s turn----------------------'.format(
                state._current_player_index))

        turn_count += 1
        robber_placement = state.board.get_robber_land()

        move = state.get_current_player().choose_move(state)
        assert not scores_changed(state, score_by_player,
                                  state.get_scores_by_player_indexed())
        state.make_move(move)
        state.make_random_move()

        score_by_player = state.get_scores_by_player_indexed()

        move_data = {
            k: v
            for k, v in move.__dict__.items()
            if (v and k != 'resources_updates')
            and not (k == 'robber_placement_land' and v == robber_placement)
            and not (isinstance(v, dict) and sum(v.values()) == 0)
        }
        logger.info('| {}| turn: {:3} | move:{} |'.format(
            ''.join('{} '.format(v) for v in score_by_player), turn_count,
            move_data))
        # if plot_map:
        #     image_name = 'turn_{}_scores_{}.png'.format(
        #         turn_count, ''.join('{}_'.format(v) for v in score_by_player))
        #     state.board.plot_map(image_name, state.current_dice_number)

    players_scores_by_names = {
        (k, v.__class__,
         v.expectimax_alpha_beta.evaluate_heuristic_value.__name__ if
         (isinstance(v, ExpectimaxBaselinePlayer)) else None):
        score_by_player[v.get_id()]
        for k, v in locals().items() if v in players
    }
    fileLogger.info('\n' + '\n'.join(
        ' {:80} : {} '.format(str(name), score)
        for name, score in players_scores_by_names.items()) +
                    '\n turns it took: {}\n'.format(turn_count) +
                    'game num: {}, num iterations: {}'.format(i, iterations) +
                    '\n' + ('-' * 156))

    p0_type = type(p0).__name__
    p_others_type = type(p1).__name__
Example #12
0
def execute_game(plot_map=True):
    seed = None
    p0 = MonteCarloWithFilterPlayer(seed)
    p1 = RandomPlayer(seed)
    players = [p0, p1]

    state = CatanState(players, seed)

    turn_count = 0
    score_by_player = state.get_scores_by_player()
    if plot_map:
        state.board.plot_map('turn_{}_scores_{}.png'.format(
            turn_count,
            ''.join('{}_'.format(v) for v in score_by_player.values())))

    while not state.is_final():
        # noinspection PyProtectedMember
        logger.info(
            '----------------------p{}\'s turn----------------------'.format(
                state._current_player_index))

        turn_count += 1
        robber_placement = state.board.get_robber_land()

        move = state.get_current_player().choose_move(state)
        assert not scores_changed(state, score_by_player,
                                  state.get_scores_by_player())
        state.make_move(move)
        state.make_random_move()

        score_by_player = state.get_scores_by_player()

        move_data = {
            k: v
            for k, v in move.__dict__.items()
            if (v and k != 'resources_updates')
            and not (k == 'robber_placement_land' and v == robber_placement)
            and not (isinstance(v, dict) and sum(v.values()) == 0)
        }
        logger.info('| {}| turn: {:3} | move:{} |'.format(
            ''.join('{} '.format(v) for v in score_by_player.values()),
            turn_count, move_data))
        if plot_map and (turn_count == 4 or turn_count % 50 == 0):
            image_name = 'turn_4_scores_{}.png'.format(
                turn_count,
                ''.join('{}_'.format(v) for v in score_by_player.values()))
            state.board.plot_map(image_name, state.current_dice_number)

    if plot_map:
        state.board.plot_map('turn_{}_scores_{}.png'.format(
            turn_count,
            ''.join('{}_'.format(v) for v in score_by_player.values())))

    players_scores_by_names = {(k, v.__class__): score_by_player[v]
                               for k, v in locals().items() if v in players}
    fileLogger.info('\n' + '\n'.join(
        ' {:150} : {} '.format(str(name), score)
        for name, score in players_scores_by_names.items()) +
                    '\n turns it took: {}\n'.format(turn_count) + ('-' * 156))

    p0_type = type(p0).__name__
    p_others_type = type(p1).__name__