Esempio n. 1
0
def ai_vs_ai(decorator1,
             decorator2,
             nr_of_games=100,
             karteninfos=karteninfoliste,
             shuffle=True):
    """function for simulating, evaluating and logging AI Battles based one determinized card lists


    :param decorator1:      the decorator function of the first AI
    :param decorator2:      the decorator function of the first AI
    :param nr_of_games:     the number of games that will be played, should be an even number, since after half the games
                            have been played, the beginning player is changed
    :param karteninfos:     list of card_informations for the game, the cardlist will be created from that list which has
                            the following form: ['WWSWK', 'WWSS', 'OOSSOOT', ...]
    :param shuffle:         boolean which ensures that the cardlist is beeing shuffled if True
    :return:                None
    """

    player1 = Player(1)
    player2 = Player(2)

    # dictionaries, um die Hyperparameter in die log-Dateien schreiben zu koennen
    dic1 = {}
    dic2 = {}

    func1 = decorator1(select_to_decorator[decorator1.__name__], dic1)
    func2 = decorator2(select_to_decorator[decorator2.__name__], dic2)

    next_player_to_player = {player1: player2, player2: player1}

    decorator_to_player = {player1: decorator1, player2: decorator2}
    function_to_player = {player1: func1, player2: func2}

    # allg_log_werte:
    first_half_1 = 0
    first_half_2 = 0
    second_half_1 = 0
    second_half_2 = 0

    first_half_draws = 0
    second_half_draws = 0

    p1_ort_meeples = 0
    p1_strasse_meeples = 0
    p1_wiese_meeple = 0
    p1_kloster_meeples = 0

    p2_ort_meeples = 0
    p2_strasse_meeples = 0
    p2_wiese_meeple = 0
    p2_kloster_meeples = 0

    allg_p1_orts_points = 0
    allg_p1_strassen_points = 0
    allg_p1_wiesen_points = 0
    allg_p1_kloester_points = 0

    allg_p2_orts_points = 0
    allg_p2_strassen_points = 0
    allg_p2_wiesen_points = 0
    allg_p2_kloester_points = 0

    p1_meeples_list_kloester = []
    p1_meeples_list_orte = []
    p1_meeples_list_strassen = []
    p1_meeples_list_wiesen = []
    p1_punkte_list_kloester = []
    p1_punkte_list_orte = []
    p1_punkte_list_strassen = []
    p1_punkte_list_wiesen = []

    p2_meeples_list_kloester = []
    p2_meeples_list_orte = []
    p2_meeples_list_strassen = []
    p2_meeples_list_wiesen = []
    p2_punkte_list_kloester = []
    p2_punkte_list_orte = []
    p2_punkte_list_strassen = []
    p2_punkte_list_wiesen = []

    p1_punkte = []
    p2_punkte = []

    allg_log = open('../simulations/auswertung', 'w+')
    allg_log.write(
        'Player1 spielt nach der {}-Taktik mit den Hyperparametern {} und Player2 nach der {}-Taktik mit den Hyperparametern {}.\n\n'
        .format(name_to_method[decorator1.__name__], dic1,
                name_to_method[decorator2.__name__], dic2))

    i = 0
    while i < nr_of_games:

        game_log = open('../simulations/game{}'.format(i), 'w+')

        # reset for new game
        player1.meeples = 7
        player2.meeples = 7
        player1.punkte = 0
        player2.punkte = 0

        player1.meeples_per_kloster = 0
        player1.meeples_per_wiese = 0
        player1.meeples_per_strasse = 0
        player1.meeples_per_ort = 0

        player2.meeples_per_kloster = 0
        player2.meeples_per_wiese = 0
        player2.meeples_per_strasse = 0
        player2.meeples_per_ort = 0

        player1.kloster_points = 0
        player1.wiesen_points = 0
        player1.strassen_points = 0
        player1.ort_points = 0

        player2.kloster_points = 0
        player2.wiesen_points = 0
        player2.strassen_points = 0
        player2.ort_points = 0

        # erstellt gemischte Kartenliste
        cardlist = create_kartenliste(karteninfos, shuffle)
        l = [c.info for c in cardlist]
        print(l)
        #cardlist = create_kartenliste(mcts_list, False)

        spiel = Spiel(cardlist, player1, player2)

        # starting player
        turn = player1 if i < int(nr_of_games / 2) else player2

        # root-nodes
        # falls beide Spieler UCT-Spieler sind, benoetigen beide eine root-node
        root_nodes = {}
        if decorator1.__name__ == 'uct_decorator':
            root_nodes.update({player1: Node(True, None, turn.nummer)})

        if decorator2.__name__ == 'uct_decorator':
            root_nodes.update({player2: Node(True, None, turn.nummer)})

        # falls kein Spieler ein UCT-Spieler ist, wird keine root-Node benoetigt, falls einer ein UCT-Spieler ist, wird
        # dessen root-Node als allgemeine root-node festgelegt
        if len(root_nodes) == 0:
            root_node = None
        elif len(root_nodes) == 1:
            root_node = list(root_nodes.values())[0]

        game_log.write(
            'Player1 spielt nach der {}-Taktik mit den Hyperparametern {} und Player2 nach der {}-Taktik mit den Hyperparametern {}.\n\n'
            .format(name_to_method[decorator1.__name__], dic1,
                    name_to_method[decorator2.__name__], dic2))
        game_log.write('Player{} beginnt das Spiel.\n\n'.format(turn.nummer))

        while len(spiel.cards_left) > 0:

            next_card = spiel.cards_left.pop(0)

            game_log.write('Neuer Zug:\n\n')
            game_log.write(
                'Aktuell hat Player1 {} Punkte und Player2 {} Punkte.\n\n'.
                format(player1.punkte, player2.punkte))
            game_log.write(
                'Player{0} zieht die Karte [{1}, {2}, {3}, {4}, {5}, {6}]'.
                format(turn.nummer, next_card.info[0], next_card.info[1],
                       next_card.info[2], next_card.info[3], next_card.mitte,
                       next_card.schild))
            game_log.write(
                '\nSie enthaelt folgende moegliche Meeplepositionen:')
            game_log.write('\nOrte: ')
            for o in next_card.orte:
                game_log.write("{}: {}  ".format(o.name, o.kanten))
            game_log.write('\nStrassen: ')
            for s in next_card.strassen:
                game_log.write("{}: {}  ".format(s.name, s.kanten))
            game_log.write('\nWiesen: ')
            for w in next_card.wiesen:
                game_log.write("{}: {}  ".format(w.name, w.ecken))

            pos = spiel.calculate_possible_actions(next_card, turn)

            if pos:
                # calculate next move according to the selection function (random/MC/MCTS)

                if len(root_nodes) < 2:
                    action, root_node = function_to_player[turn](
                        spiel, next_card, turn, pos, next_player_to_player,
                        root_node)
                else:
                    action, root_nodes[turn] = function_to_player[turn](
                        spiel, next_card, turn, pos, next_player_to_player,
                        root_nodes[turn])

                # root_node updaten
                # falls ueberhaupt ein mcts-spieler mitspielt
                if len(root_nodes) > 0:
                    # falls der turn-spieler kein mcts spieler ist
                    if decorator_to_player[turn].__name__ != 'uct_decorator':
                        # waehle die entprechend naechste Node als neue root_node
                        if root_node.children:
                            for child in root_node.children:

                                # wenn die action von der child-node der gespielten entspricht
                                if action[3] == None:
                                    if child.action == (action[0], action[1],
                                                        action[2], None,
                                                        None):  ###
                                        root_node = child
                                        root_node.parent = None
                                        break
                                elif action[3] == 'k':
                                    if child.action == (action[0], action[1],
                                                        action[2], 'k',
                                                        1):  ###
                                        root_node = child
                                        root_node.parent = None
                                        break
                                else:
                                    if child.action == (action[0], action[1],
                                                        action[2],
                                                        action[3].id,
                                                        action[3].name):  ###
                                        root_node = child
                                        root_node.parent = None
                                        break

                    # another player made the first move of the game, or the node has no visits yet
                        else:
                            p_num = 1 if turn.nummer == 2 else 2

                            if action[3] == None:
                                mcts_action = (action[0], action[1], action[2],
                                               None, None)
                            elif action[3] == 'k':
                                mcts_action = (action[0], action[1], action[2],
                                               'k', 1)
                            else:
                                mcts_action = (action[0], action[1], action[2],
                                               action[3].id, action[3].name)

                            root_node = Node(True, mcts_action, p_num, None)

                    else:
                        # falls es genau zwei uct-Spieler gibt, muss der Gegner updaten. Gibt es nur einen UCT-Spieler,
                        # ansonsten hat der UCT-Spieler die root-Node bereits upgedatet
                        if len(root_nodes) == 2:
                            # der Gegner muss seine Node um die Aktion updaten, die der turn-Spieler gerade gespielt hat
                            if root_nodes[
                                    next_player_to_player[turn]].children:
                                for child in root_nodes[
                                        next_player_to_player[turn]].children:

                                    # wenn die action von der child-node der gespielten entspricht

                                    if action[3] == None:
                                        mcts_action = (action[0], action[1],
                                                       action[2], None, None)
                                    elif action[3] == 'k':
                                        mcts_action = (action[0], action[1],
                                                       action[2], 'k', 1)
                                    else:
                                        mcts_action = (action[0], action[1],
                                                       action[2], action[3].id,
                                                       action[3].name)

                                    if child.action == mcts_action:  ###
                                        root_nodes[next_player_to_player[
                                            turn]] = child
                                        break

                            # another player made the first move of the game, or the node has no visits yet
                            else:
                                p_num = 1 if turn.nummer == 2 else 2

                                if action[3] == None:
                                    mcts_action = (action[0], action[1],
                                                   action[2], None, None)
                                elif action[3] == 'k':
                                    mcts_action = (action[0], action[1],
                                                   action[2], 'k', 1)
                                else:
                                    mcts_action = (action[0], action[1],
                                                   action[2], action[3].id,
                                                   action[3].name)

                                root_nodes[next_player_to_player[turn]] = Node(
                                    True, mcts_action, p_num, None)

                spiel.make_action(turn, next_card, action[0], action[1],
                                  action[2], action[3])

                if action[3] is not None and action[3] != 'k':
                    # action_ausgabe = 'k' if mcts.root.action[2] == 'k' else mcts.root.action[2]
                    game_log.write(
                        "\n\nPlayer{} setzt einen Meeple auf {}{}.".format(
                            turn.nummer, action[3].id, action[3].name))
                elif action[3] == 'k':
                    game_log.write(
                        "\nPlayer{} setzt einem Meeple auf das Kloster.".
                        format(turn.nummer))
                else:
                    game_log.write("\nPlayer{} setzt keinen Meeple.".format(
                        turn.nummer))

                game_log.write(
                    "\nPlayer{} setzt die Karte an ({}, {}) und rotiert sie {} mal\n\n"
                    .format(turn.nummer, action[0], action[1], action[2]))
                turn = next_player_to_player[turn]

            else:
                game_log.write(
                    '\nEs gibt fuer diese Kerte keine Anlegestellt.\n\n')
                print(i,
                      'Es gibt in diesem Spiel mal keine Anlegemoeglichkeit')
                continue

        spiel.final_evaluate()

        p1_punkte.append(player1.punkte)
        p2_punkte.append(player2.punkte)

        game_log.write(
            'Das Spiel ist vorbei. Player1 hat {} und Player2 {} Punkte.'.
            format(player1.punkte, player2.punkte))
        game_log.write(
            '\n\nDie Punkte von Player1 verteilen sich dabei wie folgt:\n\n{} Kloester:\t{}\n\n{} Orte:\t\t{}\n\n{} Strassen:\t{}\n\n{} Wiesen:\t{}'
            .format(player1.meeples_per_kloster, player1.kloster_points,
                    player1.meeples_per_ort, player1.ort_points,
                    player1.meeples_per_strasse, player1.strassen_points,
                    player1.meeples_per_wiese, player1.wiesen_points))
        game_log.write(
            '\n\nDie Punkte von Player2 verteilen sich dabei wie folgt:\n\n{} Kloester:\t{}\n\n{} Orte:\t\t{}\n\n{} Strassen:\t{}\n\n{} Wiesen:\t{}'
            .format(player2.meeples_per_kloster, player2.kloster_points,
                    player2.meeples_per_ort, player2.ort_points,
                    player2.meeples_per_strasse, player2.strassen_points,
                    player2.meeples_per_wiese, player2.wiesen_points))
        game_log.close()

        # allg log:

        allg_log.write(
            f'\n\nSpiel {i}: Spieler1 hat {player1.punkte} und Spieler2 hat {player2.punkte} Punkte.'
        )
        allg_log.write(
            '\n\nDie Punkte von Player1 verteilen sich dabei wie folgt:\n\n{} Kloester:\t{}\n\n{} Orte:\t\t{}\n\n{} Strassen:\t{}\n\n{} Wiesen:\t{}'
            .format(player1.meeples_per_kloster, player1.kloster_points,
                    player1.meeples_per_ort, player1.ort_points,
                    player1.meeples_per_strasse, player1.strassen_points,
                    player1.meeples_per_wiese, player1.wiesen_points))
        allg_log.write(
            '\n\nDie Punkte von Player2 verteilen sich dabei wie folgt:\n\n{} Kloester:\t{}\n\n{} Orte:\t\t{}\n\n{} Strassen:\t{}\n\n{} Wiesen:\t{}'
            .format(player2.meeples_per_kloster, player2.kloster_points,
                    player2.meeples_per_ort, player2.ort_points,
                    player2.meeples_per_strasse, player2.strassen_points,
                    player2.meeples_per_wiese, player2.wiesen_points))

        allg_log_werte = 0
        if i < int(nr_of_games / 2):
            if player1.punkte > player2.punkte:
                first_half_1 += 1
            elif player2.punkte > player1.punkte:
                first_half_2 += 1
            else:
                first_half_draws += 1
        else:
            if player1.punkte > player2.punkte:
                second_half_1 += 1
            elif player2.punkte > player1.punkte:
                second_half_2 += 1
            else:
                second_half_draws += 1
        # allg daten

        #meeples
        #player1
        p1_ort_meeples += player1.meeples_per_ort
        p1_meeples_list_orte.append(player1.meeples_per_ort)

        p1_strasse_meeples += player1.meeples_per_strasse
        p1_meeples_list_strassen.append(player1.meeples_per_strasse)

        p1_wiese_meeple += player1.meeples_per_wiese
        p1_meeples_list_wiesen.append(player1.meeples_per_wiese)

        p1_kloster_meeples += player1.meeples_per_kloster
        p1_meeples_list_kloester.append(player1.meeples_per_kloster)

        #player2
        p2_ort_meeples += player2.meeples_per_ort
        p2_meeples_list_orte.append(player2.meeples_per_ort)

        p2_strasse_meeples += player2.meeples_per_strasse
        p2_meeples_list_strassen.append(player2.meeples_per_strasse)

        p2_wiese_meeple += player2.meeples_per_wiese
        p2_meeples_list_wiesen.append(player2.meeples_per_wiese)

        p2_kloster_meeples += player2.meeples_per_kloster
        p2_meeples_list_kloester.append(player2.meeples_per_kloster)

        #punkte
        #player1
        allg_p1_orts_points += player1.ort_points
        p1_punkte_list_orte.append(player1.ort_points)

        allg_p1_strassen_points += player1.strassen_points
        p1_punkte_list_strassen.append(player1.strassen_points)

        allg_p1_wiesen_points += player1.wiesen_points
        p1_punkte_list_wiesen.append(player1.wiesen_points)

        allg_p1_kloester_points += player1.kloster_points
        p1_punkte_list_kloester.append(player1.kloster_points)

        #player2
        allg_p2_orts_points += player2.ort_points
        p2_punkte_list_orte.append(player2.ort_points)

        allg_p2_strassen_points += player2.strassen_points
        p2_punkte_list_strassen.append(player2.strassen_points)

        allg_p2_wiesen_points += player2.wiesen_points
        p2_punkte_list_wiesen.append(player2.wiesen_points)

        allg_p2_kloester_points += player2.kloster_points
        p2_punkte_list_kloester.append(player2.kloster_points)

        i += 1

    allg_log.write('\n\n\nAllgemeine Auswertung:\n\n\n')
    allg_log.write(
        f'Spieler1 hat in der ersten Haelfte {first_half_1} Spiele gewonnen, Player2 {first_half_2} und {first_half_draws} Spiele endeten Unentschieden.'
    )
    allg_log.write(
        f'Spieler1 hat in der zweiten Haelfte {second_half_1} Spiele gewonnen, Player2 {second_half_2} und {second_half_draws} Spiele endeten Unentschieden.'
    )

    allg_log.write(
        '\n\nPlayer1 hat durchschnittlich folgende Zahl von Meeples auf die folgenden Gebiete gesetzt:\n\n'
    )
    allg_log.write(f'Orte:\t\t{p1_ort_meeples/nr_of_games}\n')
    allg_log.write(f'Strassen:\t{p1_strasse_meeples/nr_of_games}\n')
    allg_log.write(f'Kloester:\t{p1_kloster_meeples/nr_of_games}\n')
    allg_log.write(f'Wiesen:\t\t{p1_wiese_meeple/nr_of_games}\n\n')

    allg_log.write(
        'Player2 hat durchschnittlich folgende Zahl von Meeples auf die folgenden Gebiete gesetzt:\n\n'
    )
    allg_log.write(f'Orte:\t\t{p2_ort_meeples/nr_of_games}\n')
    allg_log.write(f'Strassen:\t{p2_strasse_meeples/nr_of_games}\n')
    allg_log.write(f'Kloester:\t{p2_kloster_meeples/nr_of_games}\n')
    allg_log.write(f'Wiesen:\t\t{p2_wiese_meeple/nr_of_games}\n\n')

    allg_log.write(
        'Player1 hat in den Spielen durchschnittlich folgende Punktzahlen mit den folgenden Gebieten gemacht:\n\n'
    )
    allg_log.write(f'Orte:\t\t{allg_p1_orts_points/nr_of_games}\n')
    allg_log.write(f'Strassen:\t{allg_p1_strassen_points/nr_of_games}\n')
    allg_log.write(f'Kloester:\t{allg_p1_kloester_points/nr_of_games}\n')
    allg_log.write(f'Wiesen:\t\t{allg_p1_wiesen_points/nr_of_games}\n\n')

    allg_log.write(
        'Player2 hat in den Spielen durchschnittlich folgende Punktzahlen mit den folgenden Gebieten gemacht:\n\n'
    )
    allg_log.write(f'Orte:\t\t{allg_p2_orts_points/nr_of_games}\n')
    allg_log.write(f'Strassen:\t{allg_p2_strassen_points/nr_of_games}\n')
    allg_log.write(f'Kloester:\t{allg_p2_kloester_points/nr_of_games}\n')
    allg_log.write(f'Wiesen:\t\t{allg_p2_wiesen_points/nr_of_games}\n')

    try:
        allg_log.write(
            '\nDas entspricht den folgenden Durchschnittswerten fuer Punkte pro feature-meeple:\n'
        )
        allg_log.write('\nPlayer1:\n\n')
        allg_log.write(
            f'{allg_p1_orts_points/p1_ort_meeples} Punkte pro Orts-Meeple\n')
        allg_log.write(
            f'{allg_p1_strassen_points/p1_strasse_meeples} Punkte pro Strassen-Meeple\n'
        )
        allg_log.write(
            f'{allg_p1_wiesen_points/p1_wiese_meeple} Punkte pro Wiesen-Meeple\n'
        )
        allg_log.write(
            f'{allg_p1_kloester_points/p1_kloster_meeples} Punkte pro Kloster-Meeple\n\n'
        )

        allg_log.write('Player2:\n\n')
        allg_log.write(
            f'{allg_p2_orts_points/p2_ort_meeples} Punkte pro Orts-Meeple\n')
        allg_log.write(
            f'{allg_p2_strassen_points/p2_strasse_meeples} Punkte pro Strassen-Meeple\n'
        )
        allg_log.write(
            f'{allg_p2_wiesen_points/p2_wiese_meeple} Punkte pro Wiesen-Meeple\n'
        )
        allg_log.write(
            f'{allg_p2_kloester_points/p2_kloster_meeples} Punkte pro Kloster-Meeple\n'
        )

    except ZeroDivisionError:
        print("Error: Division durch 0")

    allg_log.write('\nDie einzelnen Spielwerte noch mal in Listen:\n')
    allg_log.write(
        'Die von Player1 gesetzen Meeples auf die jeweiligen Gebiete:\n\n')
    allg_log.write(f'Orte1 = {p1_meeples_list_orte}\n')
    allg_log.write(f'Strassen1 = {p1_meeples_list_strassen}\n')
    allg_log.write(f'Wiesen1 = {p1_meeples_list_wiesen}\n')
    allg_log.write(f'Kloester1 = {p1_meeples_list_kloester}\n\n')
    allg_log.write(
        'Die von Player2 gesetzen Meeples auf die jeweiligen Gebiete:\n\n')
    allg_log.write(f'Orte2 = {p2_meeples_list_orte}\n')
    allg_log.write(f'Strassen2 = {p2_meeples_list_strassen}\n')
    allg_log.write(f'Wiesen2 = {p2_meeples_list_wiesen}\n')
    allg_log.write(f'Kloester2 = {p2_meeples_list_kloester}\n\n')

    allg_log.write('Die von Player1 bekommenen Punkte mit den Gebieten:\n\n')
    allg_log.write(f'Orte1_punkte = {p1_punkte_list_orte}\n')
    allg_log.write(f'Strassen1_punkte = {p1_punkte_list_strassen}\n')
    allg_log.write(f'Wiesen1_punkte = {p1_punkte_list_wiesen}\n')
    allg_log.write(f'Kloester1_punkte = {p1_punkte_list_kloester}\n\n')

    allg_log.write('Die von Player2 bekommenen Punkte mit den Gebieten:\n\n')
    allg_log.write(f'Orte2_punkte = {p2_punkte_list_orte}\n')
    allg_log.write(f'Strassen2_punkte = {p2_punkte_list_strassen}\n')
    allg_log.write(f'Wiesen2_punkte = {p2_punkte_list_wiesen}\n')
    allg_log.write(f'Kloester2_punkte = {p2_punkte_list_kloester}\n\n')

    allg_log.write(f'Player1_ergebnisse = {p1_punkte}')
    allg_log.write(f'\nPlayer2_ergebnisse = {p2_punkte}')

    allg_log.close()
Esempio n. 2
0
    def test1(self):
        spiel = Spiel_class.Spiel(Kartenliste)
        player1 = Player(1)
        player2 = Player(2)

        k1 = Card('O', 'W', 'W', 'O', 'O')
        spiel.make_action(player2, k1, 1, 0, 0, k1.orte[0])

        x, y = player1.punkte, player2.punkte

        spiel.final_evaluate()

        self.assertEqual(player1.punkte, 0)
        self.assertEqual(player2.punkte, 2)

        player1.punkte, player2.punkte = x, y

        k2 = Card('O', 'W', 'W', 'W')
        spiel.make_action(player1, k2, 2, 0, 1, k2.orte[0])

        x, y = player1.punkte, player2.punkte

        spiel.final_evaluate()

        self.assertEqual(player1.punkte, 1)
        self.assertEqual(player2.punkte, 2)

        player1.punkte, player2.punkte = x, y

        k3 = Card('O', 'O', 'S', 'O', 'O', True)
        spiel.make_action(player2, k3, 1, 1, 2, k3.strassen[0])

        x, y = player1.punkte, player2.punkte

        spiel.final_evaluate()

        self.assertEqual(player1.punkte, 1)
        self.assertEqual(player2.punkte, 5)

        player1.punkte, player2.punkte = x, y

        k4 = Card('S', 'O', 'S', 'S', 'G')
        wiese = None
        for w in k4.wiesen:
            if w.ecken == [5, 6]:
                wiese = w
                break

        spiel.make_action(player1, k4, 3, 0, 2, wiese)

        x, y = player1.punkte, player2.punkte

        spiel.final_evaluate()

        self.assertEqual(player1.punkte, 7)
        self.assertEqual(player2.punkte, 5)

        player1.punkte, player2.punkte = x, y

        k5 = Card('O', 'W', 'W', 'O', 'O')
        spiel.make_action(player2, k5, 2, 1, 0, k5.wiesen[0])

        x, y = player1.punkte, player2.punkte

        spiel.final_evaluate()

        self.assertEqual(player1.punkte, 7)
        self.assertEqual(player2.punkte, 9)

        player1.punkte, player2.punkte = x, y

        #display_spielbrett_dict(spiel.cards_set)

        k6 = Card('W', 'W', 'S', 'S')
        spiel.make_action(player1, k6, 3, 1, 3, k6.strassen[0])

        x, y = player1.punkte, player2.punkte

        spiel.final_evaluate()

        self.assertEqual(player1.punkte, 9)
        self.assertEqual(player2.punkte, 9)

        player1.punkte, player2.punkte = x, y