AssertionError: push() ожидает, что перемещение будет законным, показывая доску, которая не является той, что была передана

Я пытаюсь написать простой шахматный движок, который ищет ход, дающий наибольшее материальное преимущество. Однако я сталкиваюсь со странной ошибкой, которая показывает не ту доску, которую я передал.

Мой код:

def best_move(board):
    print(board)
    
    moves = board.legal_moves
    
    result = choice(list(moves))
    for i in moves:
        newboard = board
        newboard.push(i)
        
        oldboard = board
        oldboard.push(result)
        
        if material_count(newboard) > material_count(oldboard):
            result = i

    return result

Однако при запуске этой функции я получаю эту ошибку:

AssertionError: push() expects move to be pseudo-legal, but got g8h6 in rnbqkb1r/ppppnppp/8/8/3PP3/8/PPP2PPP/RNBQKBNR

Плата в сообщении об ошибке выглядит так:

r n b q k b . r
p p p p n p p p
. . . . . . . .
. . . . . . . .
. . . P P . . .
. . . . . . . .
P P P . . P P P
R N B Q K B N R

Как видите, моя пешка на вертикали e полностью исчезла, а мой конь занял место своего упавшего товарища. Однако это не та плата, которую я передал в свой метод, как показано ниже:

r n b q k b n r
p p p p . p p p
. . . . . . . .
. . . . p . . .
. . . P P . . .
. . . . . . . .
P P P . . P P P
R N B Q K B N R

Любые идеи? Я не понимаю, почему правление изменяется таким образом.


person aidenwilson    schedule 24.02.2021    source источник
comment
newboard = board не создает копию broad. Любые изменения, внесенные вами в newboard, повлияют как на board, так и на oldboard. Если вместо этого вы создадите глубокую копию board, это исправит ситуацию?   -  person Random Davis    schedule 25.02.2021
comment
@RandomDavis Большое спасибо! Можете ли вы опубликовать это как ответ, чтобы я мог его принять? Кроме того, вот как я сделал глубокую копию: newboard = chess.Board(board.fen()). Это правильный способ сделать это?   -  person aidenwilson    schedule 25.02.2021
comment
Я не знаю, как реализован конструктор Board, поэтому не могу сказать наверняка, что это сработает, но если он действительно работает, то я предполагаю, что это правильно.   -  person Random Davis    schedule 25.02.2021
comment
@RandomDavis круто! Кстати, не могли бы вы опубликовать ответ в этой теме, чтобы я его принял?   -  person aidenwilson    schedule 26.02.2021
comment
Хорошо, я отправил ответ, я пропустил, что вы спрашивали об этом раньше.   -  person Random Davis    schedule 26.02.2021


Ответы (2)


newboard = board не создает копию board. Любые изменения, внесенные вами в newboard, повлияют как на board, так и на oldboard. Решение состоит в том, чтобы вместо этого создать глубокую копию board.

По словам спрашивающего, это делается через:

newboard = chess.Board(board.fen())
person Random Davis    schedule 25.02.2021
comment
@eligolf Мой вопрос был не в том, как создать глубокую копию. Это было, почему код, показанный ниже, не работал, и как я могу это исправить? Ваш ответ также требовал импорта другой библиотеки, которую я не предпочел. - person aidenwilson; 26.02.2021

Вам нужно использовать глубокую копию, чтобы создать копию доски, иначе вы используете ту же доску, что и раньше.

from copy import deepcopy

newboard = deepcopy(board)
person eligolf    schedule 25.02.2021