【问题标题】:"AssertionError: push() expects move to be legal", showing a board that is not the one passed in“AssertionError: push() 期望移动是合法的”,显示一个不是传入的棋盘
【发布时间】:2021-02-24 23:07:47
【问题描述】:

我正在尝试编写一个简单的国际象棋引擎,以寻找能产生最大物质优势的棋步。但是,我遇到了一个奇怪的错误,显示的板不是我传入的板。

我的代码:

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 不会创建broad 的副本。您对newboard 所做的任何更改都会影响boardoldboard。如果您改为创建 board 的深层副本,是否可以解决问题?
  • @RandomDavis 非常感谢!您可以将此作为答案发布,以便我接受吗?另外,这是我制作深拷贝的方式:newboard = chess.Board(board.fen())。这是正确的做法吗?
  • 我不知道Board的构造函数是如何实现的,所以我不能肯定它会起作用,但如果它真的起作用,那么我认为这是正确的。
  • @RandomDavis 太棒了!顺便说一句,你想在这个帖子上发布一个答案让我接受吗?
  • 好的,我发布了一个答案,我错过了你之前问过的问题。

标签: python chess python-chess


【解决方案1】:

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

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

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

【讨论】:

  • @eligolf 我的问题不是“你如何创建深度复制”。它是,“为什么下面显示的代码不起作用,我该如何解决?”您的回答还需要导入另一个我不喜欢的库。
【解决方案2】:

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

from copy import deepcopy

newboard = deepcopy(board)

【讨论】:

    【解决方案3】:

    正如其他评论者指出的那样,您正在制作 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)
    

    来自文档,方法:

    创建板的副本。

    默认复制整个移动堆栈。或者,stack 可以是 False,或者是一个整数来复制有限的移动次数。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-16
      • 2020-12-06
      • 2021-12-15
      • 1970-01-01
      相关资源
      最近更新 更多