WUZIQI — Gomoku
好看,本身就是理由
← 返回博客

引擎 · 读形

把五子棋引擎变快的局部形状

Rapfi 的论文把一个安静的问题摆到台前:强棋不只靠更大的网络,也靠把棋盘上反复出现的局部形状处理得更轻、更准。

棋盘上的局部形状,常常比整盘扫描更接近一台引擎真正的工作方式。
棋盘上的局部形状,常常比整盘扫描更接近一台引擎真正的工作方式。

你复盘时可能遇到过这种局面:棋盘很空,读起来却很慢;另一局已经挤成一团,关键点反而只剩两三个。强引擎面对的也是同一件事。Rapfi 的论文把一个安静的问题摆到台前:棋力不只来自更大的网络,也来自对棋盘上反复出现的局部形状处理得更轻、更准。

快,常常从小范围开始

五子棋的棋盘看起来是一个整体,计算时却充满局部。一个活三附近的四五个交叉点,会比远处十几个空点更急;一个冲四旁边的防点,会直接改变下一手的生死。人类读棋会自然缩小视野,引擎也在寻找类似的节省方式。

Rapfi 论文讨论的方向,是把局部棋形编码成更容易复用的形式。论文称这种做法为 pattern codebook,并结合增量更新,减少每一步之后从头计算的负担;相关实验和系统说明见 Rapfi 论文。它没有把棋盘看粗;重点在于先整理那些经常重复的形状。

局部形状为什么会反复出现

五子棋的胜负条件很干净:连成五子。可干净的规则会制造出大量相似的小形状。活三、眠三、冲四、活四,这些名字背后都是局部空点、己子、对方棋子的排列关系。

以活三为例。你在一条线上看到三个连续己子,两端都还空,第一反应通常是检查两头的延伸点。若旁边还有一条斜线也在成形,这个局部就不再只是一个三,它可能指向双三、连续威胁,甚至禁手判断。

这解释了为什么局部形状值得被单独对待。棋盘上许多点没有同等价值,价值来自邻近棋子的组合。把这些组合识别得快,搜索就少走很多空路。

速度藏在重复的形状里

增量更新像复盘时只改一处

落下一子后,整张棋盘都变了吗?规则上变了,局部关系上只变了一圈。新子所在的横、竖、两条斜线会改变,远处的形状仍旧保持原样。

增量更新抓住的就是这个事实。每下一手,只更新受影响的局部编码和相关评估,保留其余部分。对引擎设计者来说,这是一种很朴素的节制:少碰没有变化的东西。

棋盘中心附近的局部形状示意,标出新落子影响的四个方向
一手棋通常只改动经过它的四个方向;局部更新把注意力留在这些线段上。

威胁空间搜索早就提醒过我们

这种局部意识并不新。1993 年的 Victoria 程序在论文 Go-Moku Solved by New Search Techniques 中,把威胁空间搜索和证明数搜索结合起来,给出了自由规则五子棋的求解结果。它关心的核心也是威胁:哪些手会迫使对方回应,哪些分支可以暂时放下。

从 Victoria 到 Rapfi,技术材料换了很多,棋盘上的压力点没有消失。冲四要应,活四更急,双威胁会压缩选择。引擎越强,越需要把这种强制性读得稳定。

试一局:复盘时只看最后一手经过的四条线。先标出新出现的活三、冲四和防点,再看全盘。这个顺序能帮你分清真正变动的区域。

规则会改变形状的重量

同一个棋形,在不同规则下可能有不同含义。连珠规则使用 15×15 棋盘,在交叉点落子,并对黑方的长连、双三、双四等设有禁手;基础说明可见 Renju International Federation 规则页。这会直接影响引擎对局部形状的判断。

举个常见场景:黑棋看似能造出两个活三,但在禁手规则下,这手可能不能下。对人来说,这是“漂亮手变成坏手”的瞬间;对引擎来说,这是局部编码必须携带的规则语义。只识别形状还不够,还要知道它在当前规则里是否可用。

玩家能从引擎学到什么

玩家当然不会在脑中维护码本。可引擎的做法能提醒我们一件实用的小事:读棋先读变化处。上一手落在哪里,哪四条线被改写,哪里多了一个缺口,哪里少了一个气口。

这比漫无目的地扫全盘更可靠。尤其在中盘,棋子密集,人的注意力很容易被远处的形状吸走。先沿最后一手做局部检查,再把结果放回全盘,你会少漏一些直接威胁。

设计棋盘界面时也一样。标记、提示、复盘工具若能围绕最后一手附近展开,会更贴近真实读棋路径。好的辅助不必喧闹,只要把刚刚改变的地方交代清楚。

先读变化处,再读全盘

读完了?打开 WUZIQI 试一局。