Почему мой шахматный алгоритм производит, казалось бы, случайные ходы?

#python #chess #minimax #alpha-beta-pruning

#питон #шахматы #минимаксный #альфа-бета-обрезка

Вопрос:

Я использую простой алгоритм минимаксной / альфа-бета-обрезки для создания шахматного «ИИ», но он продолжает делать одни и те же ходы для начала, независимо от того, какой ход я делаю. Например, белые играют e4, черные (AI) играют a6, белые играют d4, черные играют Ra7, а затем перемещают ладью взад и вперед, что бы я ни делал. (глубина в настоящее время равна 2)

 def evaluate(set, to_move): # the "set" is the list i am working from - pop_board does not get committed to the board
    eval = 0
    for i in range(8):
        for x in range(8): # looping through the current grid
            if set[x][i] != "A":
                if not set[x][i].hidden:
                    if set[x][i].colour == "W":
                        final_pos(set[x][i]).count
                        if x < 4 and i <4 and x>3 and i>3: #if the piece is in the middle of the board
                            eval  = 50
                        if set[x][i].type == "P":
                            eval  = 100
                        elif set[x][i].type == "N" or set[x][i].type == "B":
                            eval  = 300
                        elif set[x][i].type == "R":
                            eval  = 500
                        elif set[x][i].type == "Q":
                            eval  = 900
                    if set[x][i].colour == "B":
                        if x < 4 and i <4 and x>3 and i>3: #if the piece is in the middle of the board
                            eval -= 50
                        if set[x][i].type == "P":
                            eval -= 100
                        elif set[x][i].type == "N" or set[x][i].type == "B":
                            eval -= 300
                        elif set[x][i].type == "R":
                            eval -= 500
                        elif set[x][i].type == "Q":
                            eval -= 900
    eval = eval * to_move
    return eval

def minimax(depth, board, moving, alpha, beta):
    best_move = None
    if depth == 0:
        return evaluate(board, moving), None
    max = -math.inf
    for i in getAllMoves(board): #gets a list of pieces
        for move in i[0]: #for every move in the piece's moves
            pop_board = copy.deepcopy(board) #deepcopying the board
            pop_board[move[0]][move[1]] = i[1] #making the move
            pop_board[i[1].x][i[1].y] = "A"
            score = -minimax( depth - 1, pop_board, moving*-1, -beta, -alpha)[0]#
            if score > max:
                best_move= i[1], move
                max = score
            if alpha >= beta:
                break
    return max, best_move
 

Комментарии:

1. К вашему сведению eval , это встроенное имя, и перезаписывать / скрывать встроенные модули — плохая практика. То же самое с max и set . Кроме того, вы еще не просмотрели код в отладчике , чтобы увидеть, что происходит?

2. Да, у меня есть. Кроме того, я изменил значения eval, max и set.

3. В этом случае я бы добавил в ваш пост больше информации о том, что вы обнаружили, проходя построчно, объясняя, где выполнение начинает отличаться от ваших ожиданий. Любая и вся информация, которую вы можете предоставить, полезна.

4. Как должен работать ваш алгоритм? Какие ходы вы ожидаете от него сыграть? Если у вас нет конкретной причины ожидать определенного результата, ваш вопрос звучит так: «Мой алгоритм хуже, чем я думал», и его улучшение выходит за рамки Stack Overflow .

5. Если я не ошибаюсь, условие x < 4 and i <4 and x>3 and i>3: никогда не выполняется, поэтому ваша evaluate функция просто возвращает общие значения фигур.

Ответ №1:

Похоже, что ваша программа воспроизводит первый ход, который она получает в вашем списке возможных ходов, т. Е. Она не находит лучшего хода при просмотре списка в вашей минимаксной функции.

Что эта строка делает в вашем коде? pop_board[i[1].x][i[1].y] = "A" В противном случае после быстрого просмотра код negamax выглядит нормально.

Поскольку он никогда не находит лучшего хода, я бы предположил, что вы получаете неправильную оценку от своей функции оценки. Сделайте несколько отпечатков и посмотрите, имеет ли это смысл.