在国际象棋编程中取消移动与抄板

时间:2012-07-26 11:55:29

标签: python chess

我正在创建一个国际象棋引擎。当我创建一个检查移动是否合法的函数时,首先我必须进行移动,然后检查移动是否让我的国王受到检查然后取消它。

在考虑如何制作一个取消移动的功能之后,我认为只需复制电路板并在复制的电路板上进行假设移动就更简单了,所以它根本不会改变原来的电路板结构

但我担心这可能是一个坏主意,因为当我到达AI部分时,因为我必须完全复制电路板,这可能会减慢我的引擎速度。是这样吗?你能否分享一下你对此的想法,因为我对算法复杂性和那种东西知之甚少。

谢谢。

2 个答案:

答案 0 :(得分:5)

正如你所说,复制整个电路板可能会使事情变得缓慢。我建议制作一个撤消列表,你可以在其中添加你所做的每一个动作的反向。然后撤消,只需重复弹出移动列表并应用它们直到列表为空。这样,您的AI可以通过使用带有maxdepth参数的简单递归函数来探索所有可能性。

回复:Bo的评论

我恭敬地不同意。

对于用低级语言编写的程序,电路板副本可能相当于一个memcpy,然后它可能会更快。但是对于面向对象的python程序,每个棋子有一个对象,加上元数据,完全独立的游戏状态副本几乎肯定比创建一个新的“撤消”对象并将其添加到列表要慢得多。

请注意,这与结构的大小无关,而且与复制该结构所需的操作数量有关。特别是在python中,函数调用会增加大量的开销。根据{{​​3}}回答(我自己),在CPython中实例化32个对象相当于83个函数调用,并且假设它们没有object以外的任何子类。然后是数据分配和复制。

如果电路板是一个16x16的numpy阵列,我同意电路板副本可能会更快。

答案 1 :(得分:4)

通常使用非制作方法,因为它避免了不必要的电路板复制。如果你想在你的Position课程中保留两种不同形式的作品,尤其如此;作为传统的8x8阵列和一组64位无符号整数(位板)。

您需要创建一个类来存储您的UnmakeMoveInfo

  • 移动的起源。
  • 之前的位置哈希。
  • 'halfmove clock'。
  • en-passant mask。
  • 被捕获的作品。
  • 以前的位置标记(check,ep_move,castling rights)。

这样您就可以获得取消移动所需的所有信息。