示例#1
0
def create_and_run_game(num_rounds: int, player1: Player,
                        player2: Player) -> None:
    """Create and run a new (non-persistent) game between two computer strategies.
    """

    if isinstance(player1.strategy, LearningStrategy):
        player1 = get_trained_learner(player2, num_rounds)

    game = PDGame(num_rounds)

    for _ in range(0, game.num_rounds):
        game.is_p1_turn = True
        move1 = player1.make_move(game)
        game.is_p1_turn = False
        move2 = player2.make_move(game)

        round_results = resolve_points(move1, move2)
        player1.curr_points += round_results[0]
        player2.curr_points += round_results[1]

        game.decisions[game.curr_round] = (move1, move2)

        if isinstance(player1.strategy, LearningStrategy):
            player1.strategy.update_game_tree_after_round(game)

        game.curr_round += 1

    ai_vs_ai_summary_screen(game, player1, player2)
示例#2
0
def run_tournament(game: PDGame) -> None:
    """Run a tournament between all strategies.

    If <show_heatmap> is set, then display a heatmap that shows the match-ups
    between the strategies.
    """

    all_strategies = get_all_strategies()

    graph = WeightedGraph()
    for s1 in all_strategies:
        for s2 in all_strategies:
            new_game = PDGame(game.num_rounds)
            strategy1 = s1.__copy__()
            strategy2 = s2.__copy__()

            player1 = Player(strategy1, 1)
            player2 = Player(strategy2, 2)

            if isinstance(player1.strategy, LearningStrategy):
                player1 = get_trained_learner(player2, game.num_rounds)

            graph.add_vertex(player1.strategy.name)

            graph.add_vertex(player2.strategy.name)

            run_game(new_game, player1, player2)
            if strategy1.name == 'Learning Strategy' and strategy2.name == 'Learning Strategy':
                player1.curr_points, player2.curr_points = 0, 0

            graph.add_edge((player1.strategy.name, player1.curr_points),
                           (player2.strategy.name, player2.curr_points))

    display_heatmap(graph)
示例#3
0
def run_game(game: PDGame, player1: Player, player2: Player) -> None:
    """Run a game between two computer strategies.
    """
    for _ in range(0, int(game.num_rounds)):
        game.is_p1_turn = True
        move1 = player1.make_move(game)
        game.is_p1_turn = False
        move2 = player2.make_move(game)

        round_results = resolve_points(move1, move2)
        player1.curr_points += round_results[0]
        player2.curr_points += round_results[1]

        game.decisions[game.curr_round] = (move1, move2)

        if isinstance(player1.strategy, LearningStrategy):
            player1.strategy.update_game_tree_after_round(game)

        game.curr_round += 1
    def update_game_tree_after_game(self, game: PDGame) -> None:
        """Update game_tree to the latest information, as well as reset temp_tree.

        Run this after every game.
        """
        # updates the leaf representing the final round with the actual points gained
        self._temp_tree.avg_pts_gained = game.get_points_prev(1)
        # update avg_pts_gained for all nodes in the tree
        self._game_tree.update_after_game(game)
        # reset temp_tree
        self._temp_tree = self._game_tree
示例#5
0
def get_trained_learner(player2: Player, num_rounds: int) -> Player:
    """Return a "trained" Player using a LearningStrategy against another Player using
    a specific Strategy.

    Preconditions:
      - player2.player_num == 2
    """
    num_games = 300
    exploration_chance = 1.0

    learner = LearningStrategy(exploration_chance)
    learner_player = Player(learner, 1)

    for i in range(num_games):
        learner._exploration_chance = 1.0 - (i / num_games)
        game = PDGame(num_rounds)
        run_game(game, learner_player, player2)
        learner.update_game_tree_after_game(game)

        learner_player.curr_points = 0
        player2.curr_points = 0

    return learner_player
示例#6
0
def ai_vs_ai_summary_screen(game: PDGame, player1: Player,
                            player2: Player) -> None:
    """Displays the summary of the aftermath of an AI vs AI game.
    """
    root = Tk()

    strategy_1 = player1.strategy.name
    strategy_2 = player2.strategy.name

    root.resizable(False, False)
    root.title('AI vs. AI Summary')
    title_label = Label(root,
                        text=strategy_1 + ' vs. ' + strategy_2 +
                        ' AI Game Summary',
                        font='TkHeadingFont:')
    title_label.grid(row=1, column=2, pady=15)

    # interface_frame is high level frame
    interface_frame = Frame(root)
    interface_frame.grid(row=3, column=2)

    match_summary_label = Label(interface_frame, text='Match Summary')
    match_summary_label.grid(row=1, column=1)

    statistics = [
        'Starting game...', 'Finishing...', 'Reporting outcomes...',
        'Played a total of ' + str(game.num_rounds) + ' rounds.'
    ]

    winner = game.resolve_game(1, 2)

    player1_points = game.get_points_prev(1)
    player2_points = game.get_points_prev(2)

    statistics.append('Player 1 (' + str(strategy_1) + ') got: ' +
                      str(player1_points) + ' points.')
    statistics.append('Player 2 (' + str(strategy_2) + ') got: ' +
                      str(player2_points) + ' points.')

    if winner == 1:
        statistics.append('Player 1 won.')
    elif winner == 2:
        statistics.append('Player 2 won.')
    else:
        statistics.append('Both players tied.')

    # stats_so_far = StringVar(value=statistics)
    match_summary_log = Listbox(interface_frame, height=20, width=75)
    match_summary_log.grid(row=2, column=1)

    def insert_statistics() -> None:
        """Inserts string statistics into the match summary log."""
        for i in range(len(statistics)):
            match_summary_log.insert(i, statistics[i])

    decision_window = Frame(interface_frame, bd=2)
    decision_window.grid(row=2, column=2)

    make_decision_label = Label(decision_window,
                                text='Other Options',
                                font='TkHeadingFont:')
    make_decision_label.grid(row=1, column=2)

    exit_button = Button(
        decision_window,
        text='Go Back',
        command=lambda: destroy_and_open(root, draw_main_window))
    exit_button.grid(row=2, column=2, padx=10)

    insert_statistics()

    root.mainloop()
示例#7
0
def draw_battle_royale() -> None:
    """Draws the tournament interface."""
    root = Tk()

    # prevent window from being manually resized as it causes weird behaviour with labels
    root.resizable(False, False)

    root.title('AI Battle Royale')

    title_label = Label(root, text='AI Battle Royale', font='TkHeadingFont:')

    title_label.grid(row=1, column=2)

    instructions = Label(
        root,
        text='Here, you get to witness the various strategies '
        'face off against one another!',
        padx=30)

    instructions.grid(row=2, column=2)

    # input number of rounds
    input_frame = Frame(root)
    input_frame.grid(row=3, column=2)
    instructions2 = Label(input_frame, text='Number of rounds to be played: ')
    instructions2.grid(row=1, column=1)

    num_rounds_possible = [str(x) for x in range(10, 26)]
    num_rounds = StringVar(root)
    num_rounds.set(num_rounds_possible[0])
    input_field = ttk.Combobox(input_frame,
                               textvariable=num_rounds,
                               values=num_rounds_possible,
                               state='readonly')
    input_field.grid(row=2, column=1, pady=10)

    game = PDGame(int(num_rounds.get()))
    game.is_p1_turn = False

    def game_update_num_rounds(event=None) -> None:
        """Updates game.num_rounds to its latest value inputted by the user."""
        if event is None:
            pass
        game.num_rounds = int(num_rounds.get())

    input_field.bind('<<ComboboxSelected>>', game_update_num_rounds)

    # Back button
    back_button = Button(
        root,
        text='Back',
        command=lambda: destroy_and_open(root, draw_main_window))

    back_button.grid(row=6, column=0, padx=5)

    # start button
    start_button = Button(root,
                          text='Start!',
                          command=lambda: battle_royale_summary_screen(game),
                          padx=10,
                          pady=0)
    start_button.grid(row=6, column=2, pady=10)

    root.mainloop()
示例#8
0
def draw_player_vs_ai() -> None:
    """Draws the Player vs. AI interface.
    """
    root = Tk()

    # prevent window from being manually resized as it causes weird behaviour with labels
    root.resizable(False, False)

    root.title('Player vs. AI')

    title_label = Label(root, text='Player vs. AI', font='TkHeadingFont:')

    title_label.grid(row=1, column=2)

    instructions = Label(
        root,
        text='Here, you can select a strategy to play against. Good luck!',
        padx=30)

    instructions.grid(row=2, column=2)

    # input number of rounds
    input_frame = Frame(root)
    input_frame.grid(row=3, column=2)
    instructions2 = Label(input_frame, text='Number of rounds to be played: ')
    instructions2.grid(row=1, column=1)

    num_rounds_possible = [str(x) for x in range(10, 26)]
    num_rounds = StringVar(root)
    num_rounds.set(num_rounds_possible[0])
    input_field = ttk.Combobox(input_frame,
                               textvariable=num_rounds,
                               values=num_rounds_possible,
                               state='readonly')
    input_field.grid(row=2, column=1, pady=10)

    def update_rounds(event=None) -> None:
        """Updates the PDGame num_rounds to the latest version from the dropmenu."""
        if event is None:
            pass
        game.num_rounds = int(num_rounds.get())

    input_field.bind('<<ComboboxSelected>>', update_rounds)

    # dropdown menus

    jesus = get_all_strategies()[0]
    lucifer = get_all_strategies()[1]
    tit_for_tat = get_all_strategies()[2]
    grim = get_all_strategies()[3]
    probability = get_all_strategies()[4]
    moody = get_all_strategies()[5]
    pavlov = get_all_strategies()[6]
    # initialize strategy info

    strategies = [
        jesus, lucifer, tit_for_tat, grim, probability, moody, pavlov
    ]
    strategy_names = [strategy.name for strategy in strategies]
    name_to_desc = {strategy.name: strategy.desc for strategy in strategies}

    # create dropdown menu frame

    dropdown_frame = Frame(root)
    dropdown_frame.grid(row=5, column=2)

    player2_selection = StringVar(root)

    # set initial menu selection to Jesus
    player2_selection.set(strategy_names[0])

    # set descriptions
    player2_desc = Label(dropdown_frame,
                         text=name_to_desc[player2_selection.get()])
    player2_desc.grid(row=2, column=3, padx=20)

    def change_description(event=None) -> None:
        """Updates the strategy descriptions to their latest state."""
        if event is None:
            pass
        player2_desc.configure(text=name_to_desc[player2_selection.get()])

        for strategy in strategies:
            if player2_selection.get() == strategy.name:
                player2.strategy = strategy.__copy__()

    # draw YOU label
    you_label = Label(dropdown_frame, text='You')
    you_label.grid(row=1, column=1)

    # draw right dropdown menu
    player2_menu = ttk.Combobox(dropdown_frame,
                                textvariable=player2_selection,
                                values=strategy_names,
                                state='readonly')
    player2_menu.bind('<<ComboboxSelected>>', change_description)

    player2_menu.grid(row=1, column=3)

    # draw the "VS"
    versus_label = Label(dropdown_frame, text='VS.', font='TkHeadingFont:')

    versus_label.grid(row=1, column=2, padx=15)

    # Back button
    back_button = Button(
        root,
        text='Back',
        command=lambda: destroy_and_open(root, draw_main_window))

    back_button.grid(row=6, column=0, padx=5)

    game = PDGame(num_rounds.get())
    game.is_p1_turn = False

    # default opponent to JesusStrategy
    player2 = Player(JesusStrategy(), 2)

    # start button
    start_button = Button(
        root,
        text='Start!',
        command=lambda: destroy_and_open(
            root, lambda: player_vs_ai_interface(game, player2)),
        padx=10,
        pady=0)
    start_button.grid(row=6, column=2, pady=10)

    root.mainloop()
示例#9
0
def draw_ai_vs_ai() -> None:
    """Draws the AI vs. AI interface."""
    root = Tk()

    # prevent window from being manually resized as it causes weird behaviour with labels
    root.resizable(False, False)

    root.title('AI vs. AI')

    title_label = Label(root, text='AI vs. AI', font='TkHeadingFont:')

    title_label.grid(row=1, column=2)

    instructions = Label(
        root,
        text='Here, you can select two AI strategies and '
        'pit them against each other to see who reigns supreme!',
        padx=30)

    instructions.grid(row=2, column=2)

    # input number of rounds
    input_frame = Frame(root)
    input_frame.grid(row=3, column=2)
    instructions2 = Label(input_frame, text='Number of rounds to be played: ')
    instructions2.grid(row=1, column=1)

    num_rounds_possible = [str(x) for x in range(10, 26)]
    num_rounds = StringVar(root)
    num_rounds.set(num_rounds_possible[0])
    input_field = ttk.Combobox(input_frame,
                               textvariable=num_rounds,
                               values=num_rounds_possible,
                               state='readonly')
    input_field.grid(row=2, column=1, pady=10)

    game = PDGame(int(num_rounds.get()))
    game.is_p1_turn = False

    def game_update_rounds() -> None:
        """Updates the game's num_rounds to the latest choice made by the user."""
        game.num_rounds = int(num_rounds.get())

    input_field.bind('<<ComboboxSelected>>', game_update_rounds())

    # Matchup label
    matchup_label = Label(root, text='Matchup: ')
    matchup_label.grid(row=4, column=2, pady=15)

    # dropdown menus
    jesus = get_all_strategies()[0]
    lucifer = get_all_strategies()[1]
    tit_for_tat = get_all_strategies()[2]
    grim = get_all_strategies()[3]
    probability = get_all_strategies()[4]
    moody = get_all_strategies()[5]
    pavlov = get_all_strategies()[6]
    learning = get_all_strategies()[7]

    # initialize strategy info
    strategies_1 = [
        jesus, lucifer, tit_for_tat, grim, probability, moody, pavlov, learning
    ]
    strategies_2 = strategies_1[:7]
    strategy_names = [strategy.name for strategy in strategies_1]
    strategy_names_2 = [strategy.name for strategy in strategies_2]
    name_to_desc = {strategy.name: strategy.desc for strategy in strategies_1}

    # create dropdown menu frame
    dropdown_frame = Frame(root)
    dropdown_frame.grid(row=5, column=2)

    player1_selection, player2_selection = StringVar(root), StringVar(root)

    # set initial menu selection to Jesus
    player1_selection.set(strategy_names[0])
    player2_selection.set(strategy_names[0])

    # set descriptions
    player1_desc = Label(dropdown_frame,
                         text=name_to_desc[player1_selection.get()])
    player2_desc = Label(dropdown_frame,
                         text=name_to_desc[player2_selection.get()])
    player1_desc.grid(row=2, column=1, padx=20)
    player2_desc.grid(row=2, column=3, padx=20)

    def change_strategy(event=None) -> None:
        """Updates the strategy descriptions to their latest state
        and updates the strategies accordingly."""
        if event is None:
            pass
        player1_desc.configure(text=name_to_desc[player1_selection.get()])
        player2_desc.configure(text=name_to_desc[player2_selection.get()])

        for strategy in strategies_1:
            if player1_selection.get() == strategy.name:
                player1.strategy = strategy.__copy__()
            if player2_selection.get() == strategy.name:
                player2.strategy = strategy.__copy__()

    # draw left dropdown menu
    player1_menu = ttk.Combobox(dropdown_frame,
                                textvariable=player1_selection,
                                values=strategy_names,
                                state='readonly')
    player1_menu.bind('<<ComboboxSelected>>', change_strategy)
    player1_menu.grid(row=1, column=1)

    # draw right dropdown menu
    player2_menu = ttk.Combobox(dropdown_frame,
                                textvariable=player2_selection,
                                values=strategy_names_2,
                                state='readonly')
    player2_menu.bind('<<ComboboxSelected>>', change_strategy)
    player2_menu.grid(row=1, column=3)

    # draw the "VS"
    versus_label = Label(dropdown_frame, text='VS.', font='TkHeadingFont:')
    versus_label.grid(row=1, column=2, padx=30)

    # Back button
    back_button = Button(
        root,
        text='Back',
        command=lambda: destroy_and_open(root, draw_main_window))
    back_button.grid(row=6, column=0, padx=5)

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

    change_strategy()

    # start button
    start_button = Button(root,
                          text='Start!',
                          command=lambda: destroy_and_open(
                              root, lambda: create_and_run_game(
                                  int(num_rounds.get()), player1, player2)),
                          padx=10)

    start_button.grid(row=6, column=2, pady=10)

    root.mainloop()