"AssertionError: push() expects move to be legal", showing a board that is not the one passed in

"AssertionError: push() expects move to be legal", showing a board that is not the one passed in

我正在尝试编写一个简单的国际象棋引擎,以寻找产生最大 material 优势的着法。但是,我 运行 遇到了一个奇怪的错误,它显示的板不是我传递给它的板。

我的代码:

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

如你所见,我的电子档棋子完全消失了,我的骑士已经取代了它倒下的战友。然而,这不是我传入方法的板子,如下图:

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

有什么想法吗?我不明白为什么要这样改板子。

您需要使用深拷贝来创建板的副本,否则您使用的是与之前相同的板。

from copy import deepcopy

newboard = deepcopy(board)

newboard = board 不会创建 board 的副本。您对 newboard 所做的任何更改都会影响 boardoldboard。解决方案是创建 board 的深层副本。

根据提问者的说法,这是通过以下方式完成的:

newboard = chess.Board(board.fen())

正如其他评论者所指出的,您正在制作 board 的浅表副本。

但是,Board 有一个 built-in copy method 比其他选择更快:

newboard = board.copy()
>>> board = chess.Board()
>>> %timeit new_board = chess.Board(board.fen())
275 µs ± 3.56 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
>>> %timeit import copy; new_board = copy.deepcopy(board)
24.8 µs ± 542 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
>>> %timeit new_board = board.copy()
16 µs ± 51.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

来自文档,方法:

Creates a copy of the board.

Defaults to copying the entire move stack. Alternatively, stack can be False, or an integer to copy a limited number of moves.

因此,在某些情况下,使用 stack 参数也会有所帮助。