示例#1
0
def MinimaxPlayer(board_state, depth, player_minmax, plyr_id, eval_fn,
                  source_bot_id,
                  root):  # By default, 'p2' => MAX ; 'p1' => MIN
    ''' Minimax Player '''
    best_move = None
    game_over = False
    en_id = 1
    if plyr_id == 1:
        en_id = 2

    last_move_by = en_id
    win_status = engine.checkIfWon(board_state, last_move_by)
    if win_status == 'WC1-win' or win_status == 'WC2-win':
        game_over = True

    if depth == 0 or game_over:  # Evaluation of the board by the bot who's generating the move
        player_to_move = plyr_id
        score = Evaluate(board_state, eval_fn, player_to_move, source_bot_id)
        if game_over:  # If GAME OVER
            if last_move_by == source_bot_id:  # If the last move was played by the BOT, make its score INFINITY
                score += 100000
            else:  # Else make it -INFINITY
                score -= 100000
        return score, None

    else:
        available_moves = engine.getAvailableMoves(board_state)
        if player_minmax == 'MAX':  # BOT is MAXimizing
            best_score = -10000  # Lower limit, ideally -infinity
            for child in available_moves:
                board_state_copy = board_state.copy()
                board_state_copy[child[0], child[1]] = plyr_id
                score, _ = MinimaxPlayer(board_state_copy,
                                         depth - 1,
                                         'MIN',
                                         en_id,
                                         eval_fn,
                                         source_bot_id,
                                         root=False)
                if score > best_score:
                    best_score = score
                    if root:
                        best_move = child  # For the root node to select a move
                        print("[bots]best_score:", best_score, "best_move: ",
                              best_move)
        elif player_minmax == 'MIN':  # USER is MINimizing
            best_score = 10000  # Higher limit, ideally infinity
            for child in available_moves:
                board_state_copy = board_state.copy()
                board_state_copy[child[0], child[1]] = plyr_id
                score, _ = MinimaxPlayer(board_state_copy,
                                         depth - 1,
                                         'MAX',
                                         en_id,
                                         eval_fn,
                                         source_bot_id,
                                         root=False)
                if score < best_score:
                    best_score = score
    return [best_score, best_move]
示例#2
0
def updateTerminal(prev_move, player_to_move, game_status, search_time=None):
    clearMessage()
    renderBoard()

    if game_status[0] is None:
        game_status = 'Game in progress'
    elif game_status[0] == 'WC1-win' or game_status[0] == 'WC2-win':
        if game_status[1] == 'p1':
            game_status = "USER WINS!"
            dispMessage(1, "Game status: " + str(game_status))
            return
        elif game_status[1] == 'p2':
            game_status = "COMPUTER WINS!"
            dispMessage(1, "Game status: " + str(game_status))
            return

    last_move_by = ''
    if player_to_move == 'USER':
        last_move_by = 'COMPUTER'
    elif player_to_move == 'COMPUTER':
        last_move_by = 'USER'

    game_count_label.config(text=str(engine.getGameCount()))
    first_move = False
    if engine.getGameCount() == 0:
        first_move = True

    allowed_moves = engine.getAvailableMoves(board_state, first_move)
    if use_alt_coord:
        if prev_move:
            prev_move = def_to_alt_mapping[prev_move]
            prev_move = prev_move[0] + str(prev_move[1])
        allowed_moves_alt = []
        for am in allowed_moves:
            am_alt = def_to_alt_mapping[am]
            am_alt = am_alt[0] + str(am_alt[1])
            allowed_moves_alt.append(am_alt)
        allowed_moves = allowed_moves_alt

    dispMessage(1, "GAME STATUS: " + str(game_status))
    dispMessage(2, '')
    dispMessage(3, 'PLAYER-1 (USER): ' + player_colors[0])
    dispMessage(4, '')
    dispMessage(5, 'PLAYER-2 (COMPUTER): ' + player_colors[1])
    dispMessage(6, '')
    dispMessage(7, '-------------------------------')
    dispMessage(8, '')
    if prev_move:
        dispMessage(9, last_move_by + '\'s move: ' + str(prev_move))
        if search_time:
            dispMessage(10, "Search time: " + str(search_time))
    dispMessage(11, '')
    dispMessage(12, '')
    dispMessage(13, ">>> " + str(player_to_move) + "'s turn --")
    dispMessage(14, '')
    dispMessage(15, "Allowed moves: " + str(allowed_moves))
示例#3
0
def ABNegamaxPlayer(board_state, depth, alpha, beta, plyr_id, eval_fn,
                    source_bot_id, root):
    ''' Alpha-Beta Negamax Player '''
    best_move = None
    game_over = False

    en_id = 1
    if plyr_id == 1:
        en_id = 2

    last_move_by = en_id
    win_status = engine.checkIfWon(board_state, last_move_by)
    if win_status == 'WC1-win' or win_status == 'WC2-win':
        game_over = True

    if depth == 0 or game_over:  # Evaluation of the board by the bot who's generating the move
        player_to_move = plyr_id
        score = Evaluate(board_state, eval_fn, player_to_move, source_bot_id)
        if game_over:  # If GAME OVER
            if last_move_by == source_bot_id:  # If the last move was played by the BOT, make its score INFINITY
                score += 100000
            else:  # Else make it -INFINITY
                score -= 100000
        if player_to_move != source_bot_id:  # Eval score from the perspective of the MIN player at the leaf
            score = -score
        return score, None

    else:
        available_moves = engine.getAvailableMoves(board_state)
        best_score = -10000  # Lower limit, ideally -infinity
        for child in available_moves:
            board_state_copy = board_state.copy()
            board_state_copy[child[0],
                             child[1]] = plyr_id  # Current player makes a move
            score, _ = ABNegamaxPlayer(board_state_copy,
                                       depth - 1,
                                       -beta,
                                       -alpha,
                                       en_id,
                                       eval_fn,
                                       source_bot_id,
                                       root=False)
            score = -score
            if score > best_score:
                best_score = score
                best_move = child  # For the root node to select a move
                if root:
                    print("[bots]best_score:", best_score, "best_move: ",
                          best_move)
            alpha = max(alpha, best_score)
            if alpha >= beta:
                #print("[bots]Pruning @ depth: ", depth)
                break
    return [best_score, best_move]
示例#4
0
def renderBoard():
    state_dict = game_board.getCoordinates(board_state, player_colors)

    for color, coords in state_dict.items():
        for coord in coords:
            hex_grid.setCell(coord[0], coord[1], fill=color)

    available_moves = engine.getAvailableMoves(
        board_state)  # Highlight available moves
    for move in available_moves:
        hex_grid.setCell(move[0], move[1], fill='SpringGreen4')
示例#5
0
def _evalFn2(board_state, player_to_move, source_bot_id=2):
    ''' Checking if a player can win in one move and the risks of the opponent winning '''

    en_id = 1
    if source_bot_id == 1:
        en_id = 2

    bot_line_score, en_line_score = 0, 0
    bot_surr_score, en_surr_score = 0, 0

    available_moves = engine.getAvailableMoves(board_state)
    board_state_copy = board_state.copy()
    for move in available_moves:
        board_state_copy[
            move[0],
            move[1]] = source_bot_id  # Simulate a Bot's move (i.e. Player-2)
        status = engine.checkIfWon(board_state_copy,
                                   source_bot_id)  # Check if BOT has Won
        if status == 'WC2-win':
            bot_line_score += 10
        if status == 'WC1-win':
            bot_surr_score += 10

        board_state_copy[
            move[0], move[1]] = en_id  # Simulate a User's move (i.e. Player-1)
        status = engine.checkIfWon(board_state_copy,
                                   en_id)  # Check if USER has Won
        if status == 'WC2-win':
            en_line_score += 10
        if status == 'WC1-win':
            en_surr_score += 10

    if player_to_move == source_bot_id:  # If the player at leaf the leaf is BOT
        w1, w2 = 20, 20  # High +ve weights for the Bot's Scores
        w3, w4 = -1, -1  # Low -ve weights for the USER's scores
    elif player_to_move == en_id:  # Else if the player at the leaf is USER
        w1, w2 = 1, 1  # Low +ve weights for BOT's scores
        w3, w4 = -20, -20  # High -ve weights for USER's scores

    random_feature = np.random.random_integers(-5, 5)

    score = w1 * bot_line_score + w2 * bot_surr_score + w3 * en_line_score + w4 * en_surr_score + random_feature
    #print("score: ", score)
    return score
示例#6
0
def _evalFn1(board_state, player_to_move, source_bot_id=2):
    ''' Checking if a player can win in one move '''

    en_id = 1
    if source_bot_id == 1:
        en_id = 2

    bot_line_score, en_line_score = 0, 0
    bot_surr_score, en_surr_score = 0, 0

    available_moves = engine.getAvailableMoves(board_state)

    if player_to_move == source_bot_id:  # If the player to move is the BOT (Player-2)
        for move in available_moves:
            board_state_copy = board_state.copy()
            board_state_copy[move[0], move[
                1]] = source_bot_id  # Simulate a Bot's move (i.e. Player-2)
            status = engine.checkIfWon(board_state_copy,
                                       source_bot_id)  # Check if Won
            if status == 'WC2-win':
                bot_line_score += 10

            if status == 'WC1-win':
                bot_surr_score += 10
        w1, w2 = 10, 10  # High weights for the Bot's Scores
        w3, w4 = -1, -1  # Low weights (Non-zero) for the Enemy's Scores

    if player_to_move == en_id:  # If the player to move is the USER (Player-1)
        for move in available_moves:
            board_state_copy = board_state.copy()
            board_state_copy[
                move[0],
                move[1]] = en_id  # Simulate a User's move (i.e. Player-1)
            status = engine.checkIfWon(board_state_copy, en_id)  # Check if Won
            if status == 'WC2-win':
                en_line_score += 10
            if status == 'WC1-win':
                en_surr_score += 10
        w1, w2 = 1, 1  # Low weights (Non-zero) for the Bot's Scores
        w3, w4 = -10, -10  # High weights for the Enemy's Scores

    score = w1 * bot_line_score + w2 * bot_surr_score + w3 * en_line_score + w4 * en_surr_score
    #print("score: ", score)
    return score
示例#7
0
def userMove():
    global board_state
    clearMessage()

    allowed_moves = engine.getAvailableMoves(board_state)
    user_move = user_ip.get()

    if not use_alt_coord:
        user_move = user_move.split(',')
        user_move = tuple([int(i) for i in user_move])
        if engine.getGameCount() > 0 and user_move not in allowed_moves:
            dispMessage(tk.END, "Invalid move! Try again")
            dispMessage(tk.END, "Available moves: " + str(allowed_moves))
            return
    else:
        user_move_a = user_move[0].upper()
        user_move_1 = int(user_move[1:])
        user_move = (user_move_a, user_move_1)
        user_move = alt_to_def_mapping[user_move]
        allowed_moves_alt = []
        for am in allowed_moves:
            am_alt = def_to_alt_mapping[am]
            am_alt = am_alt[0] + str(am_alt[1])
            allowed_moves_alt.append(am_alt)
        if engine.getGameCount() > 0 and user_move not in allowed_moves:
            dispMessage(tk.END, "Invalid move! Try again")
            dispMessage(tk.END, "Available moves: " + str(allowed_moves_alt))
            return

    board_state, result, game_count = engine.updateBoardState(user_move,
                                                              plyr_id=1)
    with open('engine/save_file',
              'wb') as file:  # Save the game state after user plays
        game_state = [board_state, player_colors, engine.getGameCount()]
        pickle.dump(game_state, file)

    updateTerminal(prev_move=user_move,
                   player_to_move='COMPUTER',
                   game_status=result)
    #allowed_moves = engine.getAvailableMoves(board_state, first_move='False')
    begin_search_btn.grid(row=19, column=24, sticky='w')
    enter_btn.grid_forget()
示例#8
0
    def generateMove(self, board_state):
        ''' Bot algorithm selector '''
        available_moves = engine.getAvailableMoves(board_state)
        print("[bots]Available_moves: ", available_moves)
        # source_bot_id is for the Evaluation function to evaluate the board state for the bot that's generating the move (different bots in BvB mode)
        if self.bot == 'random':
            ''' Choice 1 - Random player '''
            bot_move = RandomPlayer(board_state)

        elif self.bot == 'minimax':
            ''' Choice 2 - Minimax '''
            score, bot_move = MinimaxPlayer(board_state,
                                            self.depth,
                                            player_minmax='MAX',
                                            plyr_id=self.bot_id,
                                            eval_fn=self.eval_fn,
                                            source_bot_id=self.bot_id,
                                            root=True)

        elif self.bot == 'ab-minimax':
            ''' Choice 3 - Minimax with Alpha-Beta prunings '''
            alpha, beta = -10000, 10000
            score, bot_move, _ = ABMinimaxPlayer(board_state,
                                                 None,
                                                 self.depth,
                                                 alpha,
                                                 beta,
                                                 player_minmax='MAX',
                                                 plyr_id=self.bot_id,
                                                 eval_fn=self.eval_fn,
                                                 source_bot_id=self.bot_id,
                                                 root=True,
                                                 ordered_children=None)

        elif self.bot == 'negamax':
            ''' Choice 4 - Negamax '''
            score, bot_move = NegamaxPlayer(board_state,
                                            self.depth,
                                            plyr_id=self.bot_id,
                                            eval_fn=self.eval_fn,
                                            source_bot_id=self.bot_id)

        elif self.bot == 'ab-negamax':
            ''' Choice 5 - Negamax with Alpha-Beta prunings '''
            alpha, beta = -10000, 10000
            score, bot_move = ABNegamaxPlayer(board_state,
                                              self.depth,
                                              alpha,
                                              beta,
                                              plyr_id=self.bot_id,
                                              eval_fn=self.eval_fn,
                                              source_bot_id=self.bot_id,
                                              root=True)

        elif self.bot == 'ab-negamax-TT':
            ''' Choice 6 - Alpha-Beta with TT '''
            alpha, beta = -10000, 10000
            score, bot_move, _ = ABNegamaxTTPlayer(board_state,
                                                   None,
                                                   self.depth,
                                                   alpha,
                                                   beta,
                                                   plyr_id=self.bot_id,
                                                   eval_fn=self.eval_fn,
                                                   source_bot_id=self.bot_id,
                                                   root=True,
                                                   ordered_children=None)

        elif self.bot == 'ab-minimax-ID':
            ''' Choice 7 - Alpha-Beta with Iterative Deepening and move ordering '''
            alpha, beta = -10000, 10000
            eval_info = None
            ordered_children = []

            def sortOnEvals(ei):
                return ei[1]

            T1 = time.time()
            for i_depth in range(1,
                                 self.ID_max_depth + 1):  # Iterative Deepening
                print("ID iter: ", i_depth)
                if i_depth == 1:
                    ordered_children = None
                score, bot_move, eval_info = ABMinimaxPlayer(
                    board_state,
                    None,
                    i_depth,
                    alpha,
                    beta,
                    player_minmax='MAX',
                    plyr_id=self.bot_id,
                    eval_fn=self.eval_fn,
                    source_bot_id=self.bot_id,
                    root=True,
                    ordered_children=ordered_children)
                T2 = time.time()
                if T2 - T1 >= self.ID_max_time:
                    break

                ordered_children = []  # Move ordering
                eval_info.sort(key=sortOnEvals, reverse=True)  #
                for ord_ch in eval_info:  #
                    ordered_children.append(ord_ch[0])  #

        elif self.bot == 'ab-negamax-TT-ID':
            ''' Choice 8 - Alpha-Beta negamax TT with Iterative Deepening and move ordering '''
            alpha, beta = -10000, 10000
            eval_info = None
            ordered_children = []

            def sortOnEvals(ei):
                return ei[1]

            T1 = time.time()
            for i_depth in range(1,
                                 self.ID_max_depth + 1):  # Iterative Deepening
                print("ID iter: ", i_depth)
                if i_depth == 1:
                    ordered_children = None
                score, bot_move, eval_info = ABNegamaxTTPlayer(
                    board_state,
                    None,
                    i_depth,
                    alpha,
                    beta,
                    plyr_id=self.bot_id,
                    eval_fn=self.eval_fn,
                    source_bot_id=self.bot_id,
                    root=True,
                    ordered_children=ordered_children)
                T2 = time.time()
                if T2 - T1 >= self.ID_max_time:
                    break

                ordered_children = []  # Move ordering
                eval_info.sort(key=sortOnEvals, reverse=True)  #
                for ord_ch in eval_info:  #
                    ordered_children.append(ord_ch[0])  #

        print("[bots]Computer's's move: ", bot_move, '\n')
        return bot_move
示例#9
0
def ABNegamaxTTPlayer(board_state,
                      prev_move,
                      depth,
                      alpha,
                      beta,
                      plyr_id,
                      eval_fn,
                      source_bot_id,
                      root=True,
                      ordered_children=None):
    ''' Alpha-Beta Negamax Player with Transposition Table '''
    best_move = None
    game_over = False
    eval_info = []  # List to store the Eval scores or the children

    en_id = 1
    if plyr_id == 1:
        en_id = 2
    last_move_by = en_id

    old_alpha = alpha  # save original alpha value
    try:
        if not root:
            entry = engine.retrieveTTEntry(
                board_state)  # Transposition-table lookup
            if entry['depth'] >= depth:
                if entry['flag'] == 'Exact':
                    #print("TT-exact")
                    return entry['value'], None, None
                elif entry['flag'] == 'LowerBound':
                    alpha = max(alpha, entry['value'])
                    #print("TT-lower bound")
                elif entry['flag'] == 'UpperBound':
                    beta = min(beta, entry['value'])
                    #print("TT-upper bound")
                if alpha >= beta:
                    return entry['value'], None, None
    except:
        entry = {'value': None, 'flag': None, 'depth': None}

    win_status = engine.checkIfWon(board_state, last_move_by)
    if win_status == 'WC1-win' or win_status == 'WC2-win':
        game_over = True

    if depth == 0 or game_over:  # Evaluation of the board by the bot who's generating the move
        player_to_move = plyr_id
        score = Evaluate(board_state, eval_fn, player_to_move, source_bot_id)

        if game_over:  # If GAME OVER
            if last_move_by == source_bot_id:  # If the last move was played by the BOT, make its score INFINITY
                score += 100000
            else:  # Else make it -INFINITY
                score -= 100000

        if player_to_move != source_bot_id:  # Eval score from the perspective of the MIN player at the leaf
            score = -score

        return score, None, None

    best_score = -10000
    available_moves = engine.getAvailableMoves(board_state)
    children = available_moves

    if ordered_children is not None:
        children = ordered_children
    for child in children:
        board_state_copy = board_state.copy()
        board_state_copy[child[0], child[1]] = plyr_id
        score, _, _ = ABNegamaxTTPlayer(board_state_copy,
                                        child,
                                        depth - 1,
                                        -alpha,
                                        -beta,
                                        en_id,
                                        eval_fn,
                                        source_bot_id,
                                        root=False,
                                        ordered_children=None)
        score = -score
        eval_info.append([child, score])
        if score > best_score:
            best_score = score
            best_move = child
            if root:
                print("[bots]best_score:", best_score, "best_move: ",
                      best_move)
            if best_score >= alpha:
                alpha = best_score
            if best_score >= beta:
                #print("Pruning")
                break

    # Fail-low
    if best_score <= old_alpha:
        flag = 'UpperBound'
    # Fail-high
    elif best_score >= beta:
        flag = 'LowerBound'
    else:
        flag = 'Exact'

    TT_entry = {'value': best_score, 'flag': flag, 'depth': depth}
    engine.pushIntoTT(board_state, best_move, plyr_id, TT_entry)

    return best_score, best_move, eval_info
示例#10
0
def ABMinimaxPlayer(board_state,
                    prev_move,
                    depth,
                    alpha,
                    beta,
                    player_minmax,
                    plyr_id,
                    eval_fn,
                    source_bot_id,
                    root=True,
                    ordered_children=None):  # 'p2' => MAX ; 'p1' => MIN
    ''' Alpha-Beta Minimax Player '''

    best_move = None
    game_over = False

    en_id = 1
    if plyr_id == 1:
        en_id = 2

    last_move_by = en_id
    win_status = engine.checkIfWon(board_state, last_move_by)
    if win_status == 'WC1-win' or win_status == 'WC2-win':
        game_over = True

    if depth == 0 or game_over:  # Evaluation of the board by the bot who's generating the move
        player_to_move = plyr_id
        score = Evaluate(board_state, eval_fn, player_to_move, source_bot_id)
        if game_over:  # If GAME OVER
            if last_move_by == source_bot_id:  # If the last move was played by the BOT, make its score INFINITY
                score += 10000
            else:  # Else make it -INFINITY
                score -= 10000
        return score, None, None

    else:
        available_moves = engine.getAvailableMoves(board_state)
        children = available_moves
        eval_info = []  # List to store the Eval scores or the children
        if ordered_children is not None:
            children = ordered_children

        if player_minmax == 'MAX':  # BOT is MAXimizing
            best_score = -10000  # Lower limit, ideally -INFINITY
            for child in children:
                board_state_copy = board_state.copy()
                board_state_copy[child[0], child[
                    1]] = plyr_id  # plyr_id=2 for MAX player (BOT) by default(in Single Player mode)
                score, _, _ = ABMinimaxPlayer(board_state_copy,
                                              child,
                                              depth - 1,
                                              alpha,
                                              beta,
                                              'MIN',
                                              en_id,
                                              eval_fn,
                                              source_bot_id,
                                              root=False)
                eval_info.append([child, score])
                if score > best_score:
                    best_score = score
                    best_move = child  # For the ROOT node to select a move
                    if root:
                        print("[bots]best_score:", best_score, "best_move: ",
                              best_move)
                alpha = max(alpha, score)
                if beta <= alpha:
                    #print("[bots]Pruning @ depth: ", depth)
                    break
        elif player_minmax == 'MIN':  # USER is MINimizing
            best_score = 10000  # Higher limit, ideally infinity
            for child in children:
                board_state_copy = board_state.copy()
                board_state_copy[child[0], child[1]] = plyr_id
                score, _, _ = ABMinimaxPlayer(board_state_copy,
                                              child,
                                              depth - 1,
                                              alpha,
                                              beta,
                                              'MAX',
                                              en_id,
                                              eval_fn,
                                              source_bot_id,
                                              root=False)
                if score < best_score:
                    best_score = score
                beta = min(beta, score)
                if beta <= alpha:
                    #print("[bots]Pruning @ depth: ", depth)
                    break
    return best_score, best_move, eval_info
示例#11
0
def RandomPlayer(board_state):
    ''' Random Player '''
    available_moves = engine.getAvailableMoves(board_state)
    return random.choice(available_moves)