我正在尝试编写一个简单的国际象棋引擎,寻找能产生最大物质优势的走法。然而,我遇到了一个奇怪的错误,该错误显示了一个不是我传递给它的板。我正在使用这个库:https://python-chess.readthedocs.io/en/latest/
我的代码:
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
有什么想法吗?我不明白为什么董事会要这样改变。
newboard = board
不会创建 board
的副本。您对 newboard
所做的任何更改都会影响 board
和 oldboard
。解决方案是创建 board
的深层副本。
根据提问者的说法,这是通过以下方式完成的:
newboard = chess.Board(board.fen())
您需要使用深复制来创建板的副本,否则您将使用与以前相同的板。
from copy import deepcopy
newboard = deepcopy(board)
正如其他评论者所指出的,您正在制作
board
的浅拷贝。
但是,Board 有一个 内置
copy
方法,比其他方法更快:
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)
从文档中,方法:
创建板的副本。
默认复制整个移动堆栈。或者,stack 可以是 False,或者是一个整数来复制有限数量的移动。
因此,在某些情况下使用
stack
参数也可能会有所帮助。