def test1(self): nodes1 = [Node(i, i) for i in range(20)] for i in range(20): nodes1[i].visits = i nodes2 = [Node(i, i) for i in range(20)] for i, j in enumerate(range(0, 40, 2)): nodes2[i].visits = j root1 = Node('root', 'root') root1.children = nodes1 root2 = Node('root', 'root') root2.children = nodes2 self.assertEqual(19, get_best_child((root1, root2)).status)
def player_vs_uct(): player1 = Player(1) player2 = Player(2, 'ai') #player1.punkte = 3 d = {player1: player2, player2: player1} #zum probieren #spiel = Spiel(create_kartenliste(determinized_short_karteninfoliste, False), player1, player2) spiel = Spiel(create_kartenliste(speed_test_karteninfoliste, False), player1, player2) #spiel = Spiel(create_kartenliste(test_karteninfolist, False), player1, player2) #['OSSW', 'WWSS', 'OSSW', 'WWSWK'] #select startspieler current_player = player2 #random.choice((player1, player2)) print('Der Startspieler ist Player{}'.format(current_player.nummer)) mcts = MCTS((player1, player2), spiel.play_random1v1, spiel.calculate_possible_actions) mcts.root = Node(True, None, current_player.nummer) game_is_running = True while game_is_running: print( '\n\nNEUER ZUG: Aktuell hat player1 {} Punkte und player2 {} Punkte.\n' .format(player1.punkte, player2.punkte)) display_spielbrett_dict(spiel.cards_set) current_card = spiel.cards_left[0] print('Die nachste Karte ist [{0}, {1}, {2}, {3}, {4}, {5}]'.format( current_card.info[0], current_card.info[1], current_card.info[2], current_card.info[3], current_card.mitte, current_card.schild)) draw_card(current_card) print('Sie enthält folgende moegliche Meeplepositionen:') print('Orte:') for o in current_card.orte: print(o.name, o.kanten) print('Strassen:') for s in current_card.strassen: print(s.name, s.kanten) print('Wiesen:') for w in current_card.wiesen: print(w.name, w.ecken) pos = spiel.calculate_possible_actions(current_card, current_player) # wenn es moegliche anlegestellenn (fuer den aktuellen Spieler) gibt, (es gibt fuer einen spieler auf jeden Fall # eine Anlegemoeglichkeit, wenn es fuer den anderen auch eine gibt) if pos: if current_player.art == 'human': #gib move ein inp = input('Bitte gib deine Aktion an:') inp_split = inp.split(' ') ungueltig = True action = None try: if inp_split[3][0] == 'o': o = [ a for a in current_card.orte if a.name == int(inp_split[3][1]) ] action = (int(inp_split[0]), int(inp_split[1]), int(inp_split[2]), o[0]) elif inp_split[3][0] == 's': s = [ a for a in current_card.strassen if a.name == int(inp_split[3][1]) ] action = (int(inp_split[0]), int(inp_split[1]), int(inp_split[2]), s[0]) elif inp_split[3][0] == 'w': w = [ a for a in current_card.wiesen if a.name == int(inp_split[3][1]) ] action = (int(inp_split[0]), int(inp_split[1]), int(inp_split[2]), w[0]) elif inp_split[3][0] == 'k': action = (int(inp_split[0]), int(inp_split[1]), int(inp_split[2]), 'k') else: action = (int(inp_split[0]), int(inp_split[1]), int(inp_split[2]), None) except IndexError or ValueError: print('ERROR CATCHED') # falls move unguelig: if action in pos: ungueltig = False while ungueltig: print("illegaler Move") inp = input('Bitte gib deine Aktion an:') inp_split = inp.split(' ') try: if inp_split[3][0] == 'o': o = [ a for a in current_card.orte if a.name == int(inp_split[3][1]) ] action = (int(inp_split[0]), int(inp_split[1]), int(inp_split[2]), o[0]) elif inp_split[3][0] == 's': s = [ a for a in current_card.strassen if a.name == int(inp_split[3][1]) ] action = (int(inp_split[0]), int(inp_split[1]), int(inp_split[2]), s[0]) elif inp_split[3][0] == 'w': w = [ a for a in current_card.wiesen if a.name == int(inp_split[3][1]) ] action = (int(inp_split[0]), int(inp_split[1]), int(inp_split[2]), w[0]) elif inp_split[3][0] == 'k': action = (int(inp_split[0]), int(inp_split[1]), int(inp_split[2]), 'k') else: action = (int(inp_split[0]), int(inp_split[1]), int(inp_split[2]), None) except IndexError or ValueError: pass if action in pos: ungueltig = False spiel.make_action(current_player, current_card, action[0], action[1], action[2], action[3]) # gespielte action formulieren if action[3]: lak_id = inp_split[3][0] lak_name = 1 if inp_split[3][0] == 'k' else action[3].name else: lak_id = None lak_name = None node_action = (action[0], action[1], action[2], lak_id, lak_name) # root anpassen # falls die aktuelle root_node bereits Kinder hat if mcts.root.children: for child in mcts.root.children: # wenn die action von der child-node der gespielten entspricht if child.action == node_action: ### mcts.root = child break # another player made the first move of the game, or the node has no visits yet else: p_num = 1 if current_player.nummer == 2 else 2 mcts.root = Node(True, node_action, p_num, mcts.root) # AI-PLayer else: #mcts.root = mcts.find_next_move(spiel) # erstelle Liste mit den root_nodes_kopien fuer welche die Trees aufgebaut wurden t_start = time.time() root_copies = [deepcopy(mcts.root) for i in range(4)] # multiprocessing pool = multiprocessing.Pool() roots = pool.starmap(calculate_tree, zip(root_copies, repeat(spiel, 4))) pool.close() pool.join() # ermittle die neue child-Node mcts.root = get_best_child(roots) t_ende = time.time() print( f'Es wurden {t_ende - t_start} Sekunden gebraucht, um die naechste Node auszurechnen.' ) # l_a_K auf die gespielt werden soll if mcts.root.action[3] is None: landschaft = None elif mcts.root.action[3] == 'k': landschaft = 'k' else: l_dict = { 'o': current_card.orte, 's': current_card.strassen, 'w': current_card.wiesen } landschaft = [ l for l in l_dict[mcts.root.action[3]] if l.name == mcts.root.action[4] ][0] spiel.make_action( current_player, current_card, mcts.root.action[0], mcts.root.action[1], mcts.root.action[2], landschaft) ####################################### # falls die AI-Aktion einen Meeple auf eine Landschaft (ausser Kloster) setzt if mcts.root.action[3] is not None: print("\nDie AI setzt einen Meeple auf {}{}.".format( mcts.root.action[3], mcts.root.action[4])) elif mcts.root.action[3] == 'k': print("\nDie AI setzt einem Meeple auf das Kloster.") else: print("\nDie AI setzt keinen Meeple.") print( "Die AI setzt die Karte an ({}, {}) und rotiert sie {} mal" .format(mcts.root.action[0], mcts.root.action[1], mcts.root.action[2])) # Vorbereitung fuer naechsten Zug # gesetzte Karte loeschen del spiel.cards_left[0] if len(spiel.cards_left) == 0: game_is_running = False # spieler wechseln current_player = d[current_player] # wenn es fuer die gezogene Karte keine Anlegestelle gibt else: print("ES GIBT FUER DIESE KARTE KEINE ANLEGESTELLE") # gesetzte Karte loeschen del spiel.cards_left[0] if len(spiel.cards_left) == 0: game_is_running = False spiel.final_evaluate() print("\nSpielende: Player1 hat {} Punkte, Player2 hat {} Punkte.".format( player1.punkte, player2.punkte))
def calculate_tree(root, global_spiel): """ :param root: :param global_spiel: :return: """ # start time replacement t = 0 t_end = 150 # loop as long as time is left: while t < t_end: # create new spiel entsprechend dem aktuellen Großen spiel = deepcopy(global_spiel) # erste Karte card = spiel.cards_left.pop(0) # selection # in select_next node die action der Node spielen und die Kartenlist updaten # startnode (aktuelle root-Node vom globalen Spiel) node = root # as long as there are known children, choose next child-node with uct # und spiele den Zug der gewaehlten Node while len(node.children) != 0: node = max(node.children, key=lambda nod: nod.calculate_UCT_value()) # wenn kein Meeple platziert wird if node.action[3] is None: landschaft = None elif node.action[3] == 'k': landschaft = 'k' else: l_dict = {'o': card.orte, 's': card.strassen, 'w': card.wiesen} landschaft = [ l for l in l_dict[node.action[3]] if l.name == node.action[4] ][0] spiel.make_action( spiel.player_to_playernumber[node.parent.player_number], card, node.action[0], node.action[1], node.action[2], landschaft) ###################### # naechste Karte ziehen if len(spiel.cards_left) > 0: card = spiel.cards_left.pop(0) # expansion if the choosen node does not represent an and-state of the game if node.status: for pos_act in spiel.calculate_possible_actions( card, spiel.player_to_playernumber[node.player_number] ): ################################## status = True if len(spiel.cards_left) > 0 else False # wenn die Aktion keine Maeepleplatzierung beinhlatet if pos_act[3] is None: node.children.append( Node(status, (pos_act[0], pos_act[1], pos_act[2], None, None), next_player_number[node.player_number], node)) elif pos_act[3] == 'k': node.children.append( Node(status, (pos_act[0], pos_act[1], pos_act[2], 'k', 1), next_player_number[node.player_number], node)) else: node.children.append( Node(status, (pos_act[0], pos_act[1], pos_act[2], pos_act[3].id, pos_act[3].name), next_player_number[node.player_number], node)) ###### # simulation # if there has been an expansion select next node at random, else evaluate instant choosen_node = node if len(node.children) > 0: choosen_node = random.choice(node.children) if choosen_node.action[3] is None: landschaft = None elif choosen_node.action[3] == 'k': landschaft = 'k' else: l_dict = {'o': card.orte, 's': card.strassen, 'w': card.wiesen} landschaft = [ l for l in l_dict[choosen_node.action[3]] if l.name == choosen_node.action[4] ][0] spiel.make_action( spiel.player_to_playernumber[ choosen_node.parent.player_number], card, choosen_node.action[0], choosen_node.action[1], choosen_node.action[2], landschaft) # naechste Karte ziehen # if len(spiel.cards_left) > 0: # card = spiel.cards_left.pop(0) winner = spiel.play_random1v1( spiel.player_to_playernumber[choosen_node.player_number], spiel.player_to_playernumber[next_player_number[ choosen_node.player_number]], random_card_draw=False) ################ # backprob #if winner == 0: # while choosen_node.parent is not None: # choosen_node.visits += 1 # choosen_node.wins += 0.5 # choosen_node = choosen_node.parent # for the root node: # choosen_node.visits += 1 # choosen_node.wins += 0.5 #else: # while choosen_node.parent is not None: # choosen_node.visits += 1 # if choosen_node.player_number != winner.nummer: # if the player for that choosen_node did not win # choosen_node.wins += 1 # choosen_node = choosen_node.parent # # for the root node: # choosen_node.visits += 1 # if choosen_node.player_number != winner.nummer: # choosen_node.wins += 1 while choosen_node.parent is not None: choosen_node.visits += 1 choosen_node.wins += spiel.player_to_playernumber[ choosen_node.parent. player_number].punkte - spiel.player_to_playernumber[ choosen_node.player_number].punkte choosen_node = choosen_node.parent # for root-node choosen_node.visits += 1 # current best node zum debuggen # print(t, "Aktuell praeferierte Aktion: ", self.root.get_best_child().action, "mit {}/{}".format(self.root.get_best_child().wins, self.root.get_best_child().visits)) #print(t) t += 1 print('ICH BIN SCHON FERTIG.') return root
def uct_vs_uct(counter): logfile = open('../log/logfile{}'.format(counter), 'w+') logfile.write('NEUES SPIEL') player1 = Player(1, 'ai') player2 = Player(2, 'ai') # player1.punkte = 3 d = {player1: player2, player2: player1} # zum probieren # von einer random-Kartenliste die ersten 10 Karten #spiel = Spiel(create_kartenliste(karteninfoliste)[:10], player1, player2) spiel = Spiel(create_kartenliste(determinized_karteninfoliste, False), player1, player2) # select startspieler current_player = random.choice([player1, player2]) mcts = MCTS((player1, player2)) mcts.root = Node(True, None, current_player.nummer) game_is_running = True while game_is_running: logfile.write("\n\n\nNEUER ZUG: Player{} ist am Zug\n".format( current_player.nummer)) logfile.write( 'Aktuell hat player1 {} Punkte und player2 {} Punkte.\n'.format( player1.punkte, player2.punkte)) #display_spielbrett_dict(spiel.cards_set) current_card = spiel.cards_left[0] print('\nDie nachste Karte ist [{0}, {1}, {2}, {3}, {4}, {5}]'.format( current_card.info[0], current_card.info[1], current_card.info[2], current_card.info[3], current_card.mitte, current_card.schild)) logfile.write( '\nDie nachste Karte ist [{0}, {1}, {2}, {3}, {4}, {5}]'.format( current_card.info[0], current_card.info[1], current_card.info[2], current_card.info[3], current_card.mitte, current_card.schild)) #draw_card(current_card) logfile.write('\nSie enthält folgende moegliche Meeplepositionen:') logfile.write('\nOrte: ') for o in current_card.orte: logfile.write("{}: {} ".format(o.name, o.kanten)) logfile.write('\nStrassen: ') for s in current_card.strassen: logfile.write("{}: {} ".format(s.name, s.kanten)) logfile.write('\nWiesen: ') for w in current_card.wiesen: logfile.write("{}: {} ".format(w.name, w.ecken)) pos = spiel.calculate_possible_actions(current_card, current_player) # wenn es moegliche anlegestellenn (fuer den aktuellen Spieler) gibt, (es gibt fuer einen spieler auf jeden Fall # eine Anlegemoeglichkeit, wenn es fuer den anderen auch eine gibt) if pos: if current_player.nummer == 1: #logfile.write('\nPlayer1 ist am Zug') mcts.root = mcts.find_next_move(spiel) # l_a_K auf die gespielt werden soll if mcts.root.action[3] is None: landschaft = None elif mcts.root.action[3] == 'k': landschaft = 'k' else: l_dict = { 'o': current_card.orte, 's': current_card.strassen, 'w': current_card.wiesen } landschaft = [ l for l in l_dict[mcts.root.action[3]] if l.name == mcts.root.action[4] ][0] spiel.make_action( current_player, current_card, mcts.root.action[0], mcts.root.action[1], mcts.root.action[2], landschaft) ####################################### if mcts.root.action[3] is not None: # action_ausgabe = 'k' if mcts.root.action[2] == 'k' else mcts.root.action[2] logfile.write( "\n\nDie AI setzt einen Meeple auf {}{}.".format( mcts.root.action[3], mcts.root.action[4])) elif mcts.root.action[3] == 'k': logfile.write( "\nDie AI setzt einem Meeple auf das Kloster.") else: logfile.write("\nDie AI setzt keinen Meeple.") logfile.write( "\nDie AI setzt die Karte an ({}, {}) und rotiert sie {} mal" .format(mcts.root.action[0], mcts.root.action[1], mcts.root.action[2])) # gesetzte Karte loeschen del spiel.cards_left[0] if len(spiel.cards_left) == 0: game_is_running = False # spieler wechseln current_player = d[current_player] else: # player2 #logfile.write('Player2 ist am Zug') mcts.root = mcts.find_next_move(spiel) # l_a_K auf die gespielt werden soll if mcts.root.action[3] is None: landschaft = None elif mcts.root.action[3] == 'k': landschaft = 'k' else: l_dict = { 'o': current_card.orte, 's': current_card.strassen, 'w': current_card.wiesen } landschaft = [ l for l in l_dict[mcts.root.action[3]] if l.name == mcts.root.action[4] ][0] spiel.make_action( current_player, current_card, mcts.root.action[0], mcts.root.action[1], mcts.root.action[2], landschaft) ####################################### if mcts.root.action[3] is not None: # action_ausgabe = 'k' if mcts.root.action[2] == 'k' else mcts.root.action[2] logfile.write( "\n\nDie AI setzt einen Meeple auf {}{}.".format( mcts.root.action[3], mcts.root.action[4])) elif mcts.root.action[2] == 'k': logfile.write( "\nDie AI setzt einem Meeple auf das Kloster.") else: logfile.write("\nDie AI setzt keinen Meeple.") logfile.write( "\nDie AI setzt die Karte an ({}, {}) und rotiert sie {} mal" .format(mcts.root.action[0], mcts.root.action[1], mcts.root.action[2])) # gesetzte Karte loeschen del spiel.cards_left[0] if len(spiel.cards_left) == 0: game_is_running = False # spieler wechseln current_player = d[current_player] else: print("ES GIBT FUER DIESE KARTE KEINE ANLEGESTELLE") # gesetzte Karte loeschen del spiel.cards_left[0] if len(spiel.cards_left) == 0: game_is_running = False spiel.final_evaluate() logfile.write( "\nSpielende: Player1 hat {} Punkte, Player2 hat {} Punkte.".format( player1.punkte, player2.punkte)) logfile.close()
def test_1(self): player1 = Player(1) player2 = Player(2, 'ai') d = {player1: player2, player2: player1} kartenliste = create_kartenliste(['SOWS', 'WWSS', 'SOSSG', 'OSSW', 'OOSOOT', 'OSSW', 'WWSWK', 'OSSW'], False) spiel = Spiel(kartenliste, player1, player2) mcts = MCTS([player1, player2]) mcts.root = Node(True, None, player1.nummer) current_player = player1 #display_spielbrett_dict(spiel.cards_set) # spiel geht los k1 = spiel.cards_left.pop(0) spiel.make_action(current_player, k1, 1, 0, 2, k1.orte[0]) # tree updaten mcts.root = Node(True, (1, 0, 2, 'o', 1), player2.nummer, mcts.root) current_player = d[current_player] #display_spielbrett_dict(spiel.cards_set) # AI Zug 1 proposed_node = mcts.find_next_move(spiel) spiel.make_action(current_player, spiel.cards_left[0], 0, 1, 0, spiel.cards_left[0].strassen[0]) for node in mcts.root.children: if node.action == (0, 1, 0, 's', 1): mcts.root = node break #print('\n', node.action) #print(node.wins,'/', node.visits) del spiel.cards_left[0] current_player = d[current_player] #display_spielbrett_dict(spiel.cards_set) self.assertEqual(7, player1.meeples) self.assertEqual(6, player2.meeples) # neuer human Zug k3 = spiel.cards_left.pop(0) wiese = None nr = None for w in k3.wiesen: if w.ecken == [5, 6]: wiese = w nr = w.name spiel.make_action(current_player, k3, 2, 0, 3, wiese) # tree updaten for node in mcts.root.children: if node.action == (2, 0, 3, 'w', nr): mcts.root = node current_player = d[current_player] #display_spielbrett_dict(spiel.cards_set) # AI Zug 2 proposed_node = mcts.find_next_move(spiel) wiese = None for w in spiel.cards_left[0].wiesen: if w.ecken == [4, 5, 7]: wiese = w spiel.make_action(current_player, spiel.cards_left[0], -1, 1, 0, wiese) for node in mcts.root.children: if node.action == (-1, 1, 0, 'w', 1): mcts.root = node #print('\n', node.action) #print(node.wins,'/', node.visits) del spiel.cards_left[0] current_player = d[current_player] #display_spielbrett_dict(spiel.cards_set) self.assertEqual(5, player2.meeples) self.assertEqual(6, player1.meeples) # neuer human Zug k5 = spiel.cards_left.pop(0) spiel.make_action(current_player, k5, 2, 1, 1, k5.orte[0]) # tree updaten for node in mcts.root.children: if node.action == (2, 1, 1, 'o', 1): mcts.root = node current_player = d[current_player] #display_spielbrett_dict(spiel.cards_set) # AI Zug 3 proposed_node = mcts.find_next_move(spiel) spiel.make_action(current_player, spiel.cards_left[0], -1, 2, 2, spiel.cards_left[0].orte[0]) for node in mcts.root.children: if node.action == (-1, 2, 2, 'o', 1): mcts.root = node # print('\n', node.action) # print(node.wins,'/', node.visits) del spiel.cards_left[0] current_player = d[current_player] #display_spielbrett_dict(spiel.cards_set) # neuer human Zug k7 = spiel.cards_left.pop(0) spiel.make_action(current_player, k7, 1, 1, 3, 'k') # tree updaten for node in mcts.root.children: #print(node.action) if node.action == (1, 1, 3, 'k', 1): mcts.root = node current_player = d[current_player] display_spielbrett_dict(spiel.cards_set) self.assertEqual(4, player1.punkte) self.assertEqual(4, player2.punkte) self.assertEqual(4, player1.meeples) self.assertEqual(5, player2.meeples) # AI Zug 4 for c in spiel.cards_left: print(c.matrix) proposed_node = mcts.find_next_move(spiel)
def human_vs_ai(decorator, karteninfos=karteninfoliste, shuffle=True, startspieler='human'): """ function for playing a game against any implemented AI as a human player, based on a determinized cardlist :param decorator: the decorator function of the AI player :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 :param startspieler: either 'human', or 'ai' for selecting the starting player :return: None The human player enters his commands via the python console: For every card that is drawn by the human player there are information printed to the console. One example might be: Die naechste Karte ist [S, O, S, S, G, False] Sie enthaelt folgende moegliche Meeplepositionen: Orte: 1 [1] Strassen: 1 [0] 2 [2] 3 [3] Wiesen: 1 [4] 2 [5, 6] 3 [7] Bitte gib deine Aktion an: To enter the command, one has to use the following format: x y (# of right-rotations) (letter for territory+# of territory) For example: 0 1 3 o1 This stands for the following action: - placing a meeple on the ort 1, which is located on the right side of the card - rotating the card three times to the right - placing the tile on the filed (0,1) """ player1 = Player(1) player2 = Player(2, 'ai') d = {player1: player2, player2: player1} spiel = Spiel(create_kartenliste(karteninfos, shuffle), player1, player2) # select startspieler current_player = player1 if startspieler == 'human' else player2 print('Der Startspieler ist {} und hat die Nummer {}'.format( current_player.art, current_player.nummer)) # the function that the AI uses for selecting it's next move dic1 = {} ai_select = decorator(select_to_decorator[decorator.__name__], dic1) # playing against an UCT-Player? uct_bool = True if select_to_decorator[ decorator.__name__] == uct_select else False root = Node(True, None, current_player.nummer) while len(spiel.cards_left) > 0: print( f'\n\nNEUER ZUG: Aktuell hat player1 {player1.punkte} Punkte und {player1.meeples} Meeples und player2 {player2.punkte} Punkte und {player2.meeples} Meeples.\n' ) display_spielbrett_dict(spiel.cards_set) current_card = spiel.cards_left.pop(0) print('Die nachste Karte ist [{0}, {1}, {2}, {3}, {4}, {5}]'.format( current_card.info[0], current_card.info[1], current_card.info[2], current_card.info[3], current_card.mitte, current_card.schild)) print('Sie enthält folgende moegliche Meeplepositionen:') print('Orte:') for o in current_card.orte: print(o.name, o.kanten) print('Strassen:') for s in current_card.strassen: print(s.name, s.kanten) print('Wiesen:') for w in current_card.wiesen: print(w.name, w.ecken) draw_card(current_card) pos = spiel.calculate_possible_actions(current_card, current_player) # wenn es moegliche anlegestellenn (fuer den aktuellen Spieler) gibt, (es gibt fuer einen spieler auf jeden Fall # eine Anlegemoeglichkeit, wenn es fuer den anderen auch eine gibt) if pos: if current_player.art == 'human': # gib move ein inp = input('Bitte gib deine Aktion an:') inp_split = inp.split(' ') ungueltig = True action = None try: if inp_split[3][0] == 'o': o = [ a for a in current_card.orte if a.name == int(inp_split[3][1]) ] action = (int(inp_split[0]), int(inp_split[1]), int(inp_split[2]), o[0]) elif inp_split[3][0] == 's': s = [ a for a in current_card.strassen if a.name == int(inp_split[3][1]) ] action = (int(inp_split[0]), int(inp_split[1]), int(inp_split[2]), s[0]) elif inp_split[3][0] == 'w': w = [ a for a in current_card.wiesen if a.name == int(inp_split[3][1]) ] action = (int(inp_split[0]), int(inp_split[1]), int(inp_split[2]), w[0]) elif inp_split[3][0] == 'k': action = (int(inp_split[0]), int(inp_split[1]), int(inp_split[2]), 'k') else: action = (int(inp_split[0]), int(inp_split[1]), int(inp_split[2]), None) except IndexError or ValueError: print('ERROR CATCHED') # falls move unguelig: if action in pos: ungueltig = False while ungueltig: print("illegaler Move") inp = input('Bitte gib deine Aktion an:') inp_split = inp.split(' ') try: if inp_split[3][0] == 'o': o = [ a for a in current_card.orte if a.name == int(inp_split[3][1]) ] action = (int(inp_split[0]), int(inp_split[1]), int(inp_split[2]), o[0]) elif inp_split[3][0] == 's': s = [ a for a in current_card.strassen if a.name == int(inp_split[3][1]) ] action = (int(inp_split[0]), int(inp_split[1]), int(inp_split[2]), s[0]) elif inp_split[3][0] == 'w': w = [ a for a in current_card.wiesen if a.name == int(inp_split[3][1]) ] action = (int(inp_split[0]), int(inp_split[1]), int(inp_split[2]), w[0]) elif inp_split[3][0] == 'k': action = (int(inp_split[0]), int(inp_split[1]), int(inp_split[2]), 'k') else: action = (int(inp_split[0]), int(inp_split[1]), int(inp_split[2]), None) except IndexError or ValueError: pass if action in pos: ungueltig = False spiel.make_action(current_player, current_card, action[0], action[1], action[2], action[3]) if uct_bool: # gespielte action formulieren if action[3]: lak_id = inp_split[3][0] lak_name = 1 if inp_split[3][0] == 'k' else action[ 3].name else: lak_id = None lak_name = None node_action = (action[0], action[1], action[2], lak_id, lak_name) # root anpassen # falls die aktuelle root_node bereits Kinder hat if root.children: for child in root.children: # wenn die action von der child-node der gespielten entspricht if child.action == node_action: root = child break # another player made the first move of the game, or the node has no visits yet else: root = Node(True, node_action, 2, None) # AI-PLayer else: action, root = ai_select(spiel, current_card, current_player, pos, d, root) spiel.make_action(current_player, current_card, action[0], action[1], action[2], action[3]) # falls die AI-Aktion einen Meeple auf eine Landschaft (ausser Kloster) setzt if action[3] == 'k': print("\nDie AI setzt einem Meeple auf das Kloster.") elif action[3] is not None: print("\nDie AI setzt einen Meeple auf {}{}.".format( action[3].id, action[3].name)) else: print("\nDie AI setzt keinen Meeple.") print( "Die AI rotiert die Karte {} mal und setzt sie an ({}, {}) " .format(action[2], action[0], action[1])) # spieler wechseln current_player = d[current_player] # wenn es fuer die gezogene Karte keine Anlegestelle gibt else: print("ES GIBT FUER DIESE KARTE KEINE ANLEGESTELLE") continue print( f'\nVor der finalen Auswertung hat Player1 {player1.punkte} und {player1.meeples} Meeples und Player2 {player2.punkte} Punkte und {player2.meeples} Meeples.' ) spiel.final_evaluate() print("\nSpielende: Player1 hat {} Punkte, Player2 hat {} Punkte.".format( player1.punkte, player2.punkte))
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()
def calculate_tree(root, global_spiel, next_card, t_end, rechenzeit, c): """ :param root: :param global_spiel: :return: """ t = 0 ende = t_end if t_end else time.time() + rechenzeit iterationen_bool = True if t_end else False while time_helper(iterationen_bool, t) < ende: # create new spiel entsprechend dem aktuellen Großen spiel = deepcopy(global_spiel) # nachste Karte #card = spiel.cards_left.pop(0) card = deepcopy(next_card) # selection # in select_next node die action der Node spielen und die Kartenlist updaten # startnode (aktuelle root-Node vom globalen Spiel) node = root # as long as there are known children, choose next child-node with uct # und spiele den Zug der gewaehlten Node while len(node.children) != 0: node = max(node.children, key=lambda nod: nod.calculate_UCT_value(c)) # wenn kein Meeple platziert wird if node.action[3] is None: landschaft = None elif node.action[3] == 'k': landschaft = 'k' else: l_dict = {'o': card.orte, 's': card.strassen, 'w': card.wiesen} landschaft = [ l for l in l_dict[node.action[3]] if l.name == node.action[4] ][0] spiel.make_action( spiel.player_to_playernumber[node.parent.player_number], card, node.action[0], node.action[1], node.action[2], landschaft) # naechste Karte ziehen if len(spiel.cards_left) > 0: card = spiel.cards_left.pop(0) # expansion if the choosen node does not represent an and-state of the game if node.status: for pos_act in spiel.calculate_possible_actions( card, spiel.player_to_playernumber[node.player_number]): status = True if len(spiel.cards_left) > 0 else False # wenn die Aktion keine Maeepleplatzierung beinhlatet if pos_act[3] is None: node.children.append( Node(status, (pos_act[0], pos_act[1], pos_act[2], None, None), dic1[node.player_number], node)) elif pos_act[3] == 'k': node.children.append( Node(status, (pos_act[0], pos_act[1], pos_act[2], 'k', 1), dic1[node.player_number], node)) else: node.children.append( Node(status, (pos_act[0], pos_act[1], pos_act[2], pos_act[3].id, pos_act[3].name), dic1[node.player_number], node)) # simulation # if there has been an expansion select next node at random, else evaluate instant choosen_node = node if len(node.children) > 0: choosen_node = random.choice(node.children) if choosen_node.action[3] is None: landschaft = None elif choosen_node.action[3] == 'k': landschaft = 'k' else: l_dict = {'o': card.orte, 's': card.strassen, 'w': card.wiesen} landschaft = [ l for l in l_dict[choosen_node.action[3]] if l.name == choosen_node.action[4] ][0] spiel.make_action( spiel.player_to_playernumber[ choosen_node.parent.player_number], card, choosen_node.action[0], choosen_node.action[1], choosen_node.action[2], landschaft) winner = spiel.play_random1v1( spiel.player_to_playernumber[choosen_node.player_number], spiel.player_to_playernumber[dic1[choosen_node.player_number]], random_card_draw=False) # backprob while choosen_node.parent is not None: choosen_node.visits += 1 choosen_node.wins += spiel.player_to_playernumber[ choosen_node.parent. player_number].punkte - spiel.player_to_playernumber[ choosen_node.player_number].punkte choosen_node = choosen_node.parent # for root-node choosen_node.visits += 1 #if t % 100 == 0: #print(t_end, t) t += 1 return root
def test_1(self): player1 = Player(1) player2 = Player(2, 'ai') d = {player1: player2, player2: player1} #zum probieren #spiel = Spiel(create_kartenliste(determinized_short_karteninfoliste, False), player1, player2) spiel = Spiel(create_kartenliste(determinized_karteninfoliste, False), player1, player2) #select startspieler current_player = player1 k1 = spiel.cards_left.pop(0) spiel.make_action(current_player, k1, 1, 0, 2, k1.orte[0]) self.assertEqual(70, len(spiel.cards_left)) self.assertEqual(player1.punkte, 4) self.assertEqual(player1.meeples, 7) k1 = spiel.cards_left.pop(0) wiese = None for w in k1.wiesen: if w.ecken == [4, 5, 6]: wiese = w break spiel.make_action(d[current_player], k1, 0, 1, 0, wiese) self.assertEqual(69, len(spiel.cards_left)) self.assertEqual(4, player1.punkte) self.assertEqual(7, player1.meeples) self.assertEqual(0, player2.punkte) self.assertEqual(6, player2.meeples) k1 = spiel.cards_left.pop(0) spiel.make_action(current_player, k1, 0, -1, 1, k1.orte[0]) self.assertEqual(68, len(spiel.cards_left)) self.assertEqual(4, player1.punkte) self.assertEqual(6, player1.meeples) self.assertEqual(0, player2.punkte) self.assertEqual(6, player2.meeples) k1 = spiel.cards_left.pop(0) spiel.make_action(d[current_player], k1, -1, 0, 2) self.assertEqual(67, len(spiel.cards_left)) self.assertEqual(4, player1.punkte) self.assertEqual(6, player1.meeples) self.assertEqual(0, player2.punkte) self.assertEqual(6, player2.meeples) k1 = spiel.cards_left.pop(0) spiel.make_action(current_player, k1, -1, -1, 3, k1.orte[0]) self.assertEqual(66, len(spiel.cards_left)) self.assertEqual(4, player1.punkte) self.assertEqual(5, player1.meeples) self.assertEqual(0, player2.punkte) self.assertEqual(6, player2.meeples) k1 = spiel.cards_left.pop(0) spiel.make_action(d[current_player], k1, 1, 1, 3, 'k') self.assertEqual(65, len(spiel.cards_left)) self.assertEqual(4, player1.punkte) self.assertEqual(5, player1.meeples) self.assertEqual(0, player2.punkte) self.assertEqual(5, player2.meeples) k1 = spiel.cards_left.pop(0) #display_spielbrett_dict(spiel.cards_set) spiel.make_action(current_player, k1, -1, 1, 0, k1.strassen[0]) self.assertEqual(64, len(spiel.cards_left)) self.assertEqual(4, player1.punkte) self.assertEqual(4, player1.meeples) self.assertEqual(0, player2.punkte) self.assertEqual(5, player2.meeples) k1 = spiel.cards_left.pop(0) wiese = None for w in k1.wiesen: if w.ecken == [7]: wiese = w break spiel.make_action(d[current_player], k1, -2, 0, 3, wiese) self.assertEqual(63, len(spiel.cards_left)) self.assertEqual(4, player1.punkte) self.assertEqual(4, player1.meeples) self.assertEqual(0, player2.punkte) self.assertEqual(4, player2.meeples) k1 = spiel.cards_left.pop(0) spiel.make_action(current_player, k1, 0, 2, 1, None) self.assertEqual(62, len(spiel.cards_left)) self.assertEqual(4, player1.punkte) self.assertEqual(4, player1.meeples) self.assertEqual(0, player2.punkte) self.assertEqual(4, player2.meeples) k1 = spiel.cards_left.pop(0) spiel.make_action(d[current_player], k1, 0, 3, 0, k1.orte[0]) self.assertEqual(61, len(spiel.cards_left)) self.assertEqual(4, player1.punkte) self.assertEqual(4, player1.meeples) self.assertEqual(0, player2.punkte) self.assertEqual(3, player2.meeples) k1 = spiel.cards_left.pop(0) spiel.make_action(current_player, k1, -2, -1, 0, None) self.assertEqual(60, len(spiel.cards_left)) self.assertEqual(11, player1.punkte) self.assertEqual(5, player1.meeples) self.assertEqual(0, player2.punkte) self.assertEqual(3, player2.meeples) k1 = spiel.cards_left.pop(0) spiel.make_action(d[current_player], k1, -1, 3, 0, None) self.assertEqual(59, len(spiel.cards_left)) self.assertEqual(11, player1.punkte) self.assertEqual(5, player1.meeples) self.assertEqual(0, player2.punkte) self.assertEqual(3, player2.meeples) self.assertEqual(len(spiel.alle_kloester), 1) self.assertEqual(len(spiel.alle_strassen), 8) self.assertEqual(len(spiel.alle_orte), 5) self.assertEqual(len(spiel.alle_wiesen), 8) k1 = spiel.cards_left.pop(0) spiel.make_action(current_player, k1, -1, -2, 3, k1.wiesen[0]) self.assertEqual(58, len(spiel.cards_left)) self.assertEqual(21, player1.punkte) self.assertEqual(5, player1.meeples) self.assertEqual(0, player2.punkte) self.assertEqual(3, player2.meeples) self.assertEqual(len(spiel.alle_kloester), 1) self.assertEqual(len(spiel.alle_strassen), 8) self.assertEqual(len(spiel.alle_orte), 6) self.assertEqual(len(spiel.alle_wiesen), 9) k1 = spiel.cards_left.pop(0) spiel.make_action(d[current_player], k1, 2, 1, 1, None) self.assertEqual(57, len(spiel.cards_left)) self.assertEqual(21, player1.punkte) self.assertEqual(5, player1.meeples) self.assertEqual(0, player2.punkte) self.assertEqual(3, player2.meeples) self.assertEqual(len(spiel.alle_kloester), 1) self.assertEqual(len(spiel.alle_strassen), 8) self.assertEqual(len(spiel.alle_orte), 6) self.assertEqual(len(spiel.alle_wiesen), 9) k1 = spiel.cards_left.pop(0) spiel.make_action(current_player, k1, -1, -3, 0, k1.orte[0]) self.assertEqual(56, len(spiel.cards_left)) self.assertEqual(21, player1.punkte) self.assertEqual(4, player1.meeples) self.assertEqual(0, player2.punkte) self.assertEqual(3, player2.meeples) self.assertEqual(len(spiel.alle_kloester), 1) self.assertEqual(len(spiel.alle_strassen), 8) self.assertEqual(len(spiel.alle_orte), 7) self.assertEqual(len(spiel.alle_wiesen), 10) k1 = spiel.cards_left.pop(0) ort = None for o in k1.orte: if o.kanten == [3]: ort = o break spiel.make_action(d[current_player], k1, -3, 0, 1, ort) self.assertEqual(55, len(spiel.cards_left)) self.assertEqual(21, player1.punkte) self.assertEqual(4, player1.meeples) self.assertEqual(0, player2.punkte) self.assertEqual(2, player2.meeples) self.assertEqual(len(spiel.alle_kloester), 1) self.assertEqual(len(spiel.alle_strassen), 8) self.assertEqual(len(spiel.alle_orte), 9) self.assertEqual(len(spiel.alle_wiesen), 10) k1 = spiel.cards_left.pop(0) spiel.make_action(current_player, k1, 0, -2, 0, None) self.assertEqual(54, len(spiel.cards_left)) self.assertEqual(27, player1.punkte) self.assertEqual(5, player1.meeples) self.assertEqual(0, player2.punkte) self.assertEqual(2, player2.meeples) self.assertEqual(len(spiel.alle_kloester), 1) self.assertEqual(len(spiel.alle_strassen), 8) self.assertEqual(len(spiel.alle_orte), 8) self.assertEqual(len(spiel.alle_wiesen), 11) k1 = spiel.cards_left.pop(0) spiel.make_action(d[current_player], k1, 3, 1, 1, None) self.assertEqual(53, len(spiel.cards_left)) self.assertEqual(27, player1.punkte) self.assertEqual(5, player1.meeples) self.assertEqual(0, player2.punkte) self.assertEqual(2, player2.meeples) self.assertEqual(len(spiel.alle_kloester), 1) self.assertEqual(len(spiel.alle_strassen), 8) self.assertEqual(len(spiel.alle_orte), 8) self.assertEqual(len(spiel.alle_wiesen), 11) k1 = spiel.cards_left.pop(0) spiel.make_action(current_player, k1, -2, 1, 0, 'k') self.assertEqual(52, len(spiel.cards_left)) self.assertEqual(27, player1.punkte) self.assertEqual(4, player1.meeples) self.assertEqual(0, player2.punkte) self.assertEqual(2, player2.meeples) self.assertEqual(len(spiel.alle_kloester), 2) self.assertEqual(len(spiel.alle_strassen), 8) self.assertEqual(len(spiel.alle_orte), 8) self.assertEqual(len(spiel.alle_wiesen), 11) mcts = MCTS((player1, player2), spiel.play_random1v1, spiel.calculate_possible_actions) mcts.root = Node(True, None, d[current_player].nummer) player1.art = 'human' player2.art = 'ai' current_player = d[current_player] game_is_running = True while game_is_running: print( '\n\nNEUER ZUG: Aktuell hat player1 {} Punkte und player2 {} Punkte.\n' .format(player1.punkte, player2.punkte)) display_spielbrett_dict(spiel.cards_set) current_card = spiel.cards_left[0] print( 'Die nachste Karte ist [{0}, {1}, {2}, {3}, {4}, {5}]'.format( current_card.info[0], current_card.info[1], current_card.info[2], current_card.info[3], current_card.mitte, current_card.schild)) draw_card(current_card) print('Sie enthält folgende moegliche Meeplepositionen:') print('Orte:') for o in current_card.orte: print(o.name, o.kanten) print('Strassen:') for s in current_card.strassen: print(s.name, s.kanten) print('Wiesen:') for w in current_card.wiesen: print(w.name, w.ecken) pos = spiel.calculate_possible_actions(current_card, current_player) # wenn es moegliche anlegestellenn (fuer den aktuellen Spieler) gibt, (es gibt fuer einen spieler auf jeden Fall # eine Anlegemoeglichkeit, wenn es fuer den anderen auch eine gibt) if pos: if current_player.art == 'human': #mache deinen move #gib move ein inp = input('Bitte gib deine Aktion an:') inp_split = inp.split(' ') ungueltig = True action = None try: if inp_split[3][0] == 'o': o = [ a for a in current_card.orte if a.name == int(inp_split[3][1]) ] action = (int(inp_split[0]), int(inp_split[1]), int(inp_split[2]), o[0]) elif inp_split[3][0] == 's': s = [ a for a in current_card.strassen if a.name == int(inp_split[3][1]) ] action = (int(inp_split[0]), int(inp_split[1]), int(inp_split[2]), s[0]) elif inp_split[3][0] == 'w': w = [ a for a in current_card.wiesen if a.name == int(inp_split[3][1]) ] action = (int(inp_split[0]), int(inp_split[1]), int(inp_split[2]), w[0]) elif inp_split[3][0] == 'k': action = (int(inp_split[0]), int(inp_split[1]), int(inp_split[2]), 'K') else: action = (int(inp_split[0]), int(inp_split[1]), int(inp_split[2]), None) except IndexError or ValueError: pass # falls move unguelig: if action in pos: ungueltig = False while ungueltig: print("illegaler Move") inp = input('Bitte gib deine Aktion an:') inp_split = inp.split(' ') try: if inp_split[3][0] == 'o': o = [ a for a in current_card.orte if a.name == int(inp_split[3][1]) ] action = (int(inp_split[0]), int(inp_split[1]), int(inp_split[2]), o[0]) elif inp_split[3][0] == 's': s = [ a for a in current_card.strassen if a.name == int(inp_split[3][1]) ] action = (int(inp_split[0]), int(inp_split[1]), int(inp_split[2]), s[0]) elif inp_split[3][0] == 'w': w = [ a for a in current_card.wiesen if a.name == int(inp_split[3][1]) ] action = (int(inp_split[0]), int(inp_split[1]), int(inp_split[2]), w[0]) elif inp_split[3][0] == 'k': action = (int(inp_split[0]), int(inp_split[1]), int(inp_split[2]), 'K') else: action = (int(inp_split[0]), int(inp_split[1]), int(inp_split[2]), None) except IndexError or ValueError: pass if action in pos: ungueltig = False spiel.make_action(current_card, (action[0], action[1]), action[2], current_player, action[3]) # root anpassen if mcts.root.children: for child in mcts.root.children: # wenn die action von der child-node der gespielten entspricht # wenn nicht none if action[3]: landschafts_name = 1 if inp_split[3][ 0] == 'k' else action[3].name landschafts_id = inp_split[3][0] else: landschafts_name = None landschafts_id = None if child.action == ((action[0], action[1]), action[2], landschafts_id, landschafts_name): ### mcts.root = child break else: #another player made the first move of the game if action[3]: landschafts_name = 1 if inp_split[3][ 0] == 'k' else action[3].name landschafts_id = inp_split[3][0] else: landschafts_name = None landschafts_id = None p_num = 1 if current_player.nummer == 2 else 2 mcts.root = Node(True, ((action[0], action[1]), action[2], landschafts_id, landschafts_name), p_num, mcts.root) #gesetzte Karte loeschen del spiel.cards_left[0] if len(spiel.cards_left) == 0: game_is_running = False #spieler wechseln current_player = d[current_player] else: # AI-PLayer mcts.root = mcts.find_next_move(spiel) # l_a_K auf die gespielt werden soll if mcts.root.action[2] is None: landschaft = None elif mcts.root.action[2] == 'k': landschaft = 'K' else: l_dict = { 'o': current_card.orte, 's': current_card.strassen, 'w': current_card.wiesen } landschaft = [ l for l in l_dict[mcts.root.action[2]] if l.name == mcts.root.action[3] ][0] spiel.make_action( current_card, mcts.root.action[0], mcts.root.action[1], current_player, landschaft) ####################################### if mcts.root.action[2] is not None: #action_ausgabe = 'K' if mcts.root.action[2] == 'k' else mcts.root.action[2] print("\nDie AI setzt einen Meeple auf {}{}.".format( mcts.root.action[2], mcts.root.action[3])) elif mcts.root.action[2] == 'k': print("\nDie AI setzt einem Meeple auf das Kloster.") else: print("\nDie AI setzt keinen Meeple.") print( "Die AI setzt die Karte an {} und rotiert sie {} mal". format(mcts.root.action[0], mcts.root.action[1])) # gesetzte Karte loeschen del spiel.cards_left[0] if len(spiel.cards_left) == 0: game_is_running = False # spieler wechseln current_player = d[current_player] else: continue spiel.final_evaluate() print("\nSpielende: Player1 hat {} Punkte, Player2 hat {} Punkte.". format(player1.punkte, player2.punkte))