【发布时间】:2021-11-21 03:34:07
【问题描述】:
我正在建立一个国际象棋评估数据库(本质上是从国际象棋位置到评估的地图),我想用它来为给定的位置提出一个好的举动。这个想法是做一种“静态”极小极大值,即:对于每个位置,如果子节点(下一层之后的位置)的评估不可用,则使用存储的评估,否则使用 max(白色移动)/min(黑色移动)子节点的评估(以相同的方式确定)。
问题当然是图中的循环,即重复位置。我无法理解如何处理这个问题而不会使它的效率无限降低。
到目前为止我探索的想法是:
- 假设在游戏中以少于当前评估的步数即可到达的任何位置的评估为 0。这是一个无效的假设,因为 - 例如 - 如果白方下 A,黑方可能不希望跟随 x,但如果白方下 B,则 y -> A -> x -> -B -> - y 可能是最好的线,导致与 A -> x 相同的位置,没有任何重复(-m 表示反向移动到 m 这里,小写:黑色移动,大写:白色移动)。
- 为到达位置的每种可能方式设置一个实例可解决循环问题,但这会在某些位置产生大量实例,因此不实用
- 从一个位置回到那个位置有一个循环这一事实并不意味着它是重复平局,因为播放重复线可能不是最佳选择
- 我已经尝试了几次循环迭代,看看整体评估是否会变得稳定。它没有,因为在某些情况下,假设重复是最好的线意味着它不再是 - 然后它回到平局作为后线等。
我知道国际象棋引擎使用转置表来检测之前已经到达的位置,但我相信这并不能解决我的问题,我实际上想知道它们是否存在问题:一个位置可能通过两个搜索树中的路径 - 其中一条路径之前经过相同的位置,因此它是重复的,而另一条路径没有这样做。那么路径 1 的评估必须是 0,但路径 2 的评估不一定是(路径 1 可能不是最好的线),所以换位表持有的评估可能是错误的,对吧?
我确信这个问题必须有一个“标准/最佳实践”的解决方案,但谷歌让我失望了。非常欢迎任何指针/想法!
【问题讨论】:
-
一个完整的棋盘配置可以用 32 个字节编码。是不是太过分了?
-
@YvesDaoust 编码的大小不是问题 - 如果需要,我可以接受 TB。如果您指的是我列出的“每种可能的方式都有一个实例” - 这个问题是算法需要枚举所有可能的方式,并且在性能方面会变得昂贵。例如,要到达每一方都将每个棋子向前移动两个区域的位置(移动之间没有中间),有 8!*8!,大约 16 亿个可能的移动命令。
-
最简单的解决方案:只存储位置,并将历史单独处理(作为哈希堆栈)
-
好吧,毕竟你真的需要关心循环吗?导致循环的移动比例是多少?我的猜测是这个分数是微不足道的。它们会导致差评吗? (即使程序自己玩,你也可以通过存储真正玩过的位置来避免拍序列。)
标签: algorithm graph-algorithm chess minimax