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
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
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
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])
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
def setUp(self): super().setUp() self.players = [FakePlayer(i) for i in range(2)] self.state = CatanState(self.players)
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)
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__
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__