青殳的博客

“只谈围棋”

前不久,我的一位室友突然开始对围棋感兴趣,寝室群也渐渐开始讨论围棋。这唤醒了我的一些尘封已久的记忆。我的父亲酷爱下棋,所以我小学时跟着学校的老师学过几年围棋,很可惜最后只有区区业余二段(三段定了三次都差一名,后面忙着升学的事情就没继续打了)。

学棋对我来说并不是一件一直都很快乐的事情,因为我是一个比较在乎输赢的人——尤其是和那些水平与我相近的人下棋的时候,毕竟跟高手过招我从来都是少输当赢——而我当然不可能在这样的对决中一直赢,输棋了难免会难受。但我觉得围棋这项运动本身,确实挺有意思的,它和每一项体育运动一样,充满激情和戏剧性,满足了我们这些普通人的英雄梦想。

所以,当我的室友唤醒我心中这部分记忆的时候,我终究还是按捺不住,打开野狐围棋,与 AI 和网友下上几盘过了把瘾。看到那熟悉的界面(这帮前端程序员在干嘛呢?十多年过去了网棋的界面没变过),我明白我终究还是回到了这黑白纵横的世界。

只不过,时代已经变了。面对如今光怪陆离的围棋世界,我忍不住想写些什么。

这篇文章分为四个部分,互相独立。第一部分简单介绍了围棋的规则,提供了简陋的新手教程,希望对有意入坑的人有所帮助;第二部分讲述了我在学围棋时的一些有趣的事情,权当笑谈;第三部分是我这两天在时隔十多年重新关注围棋之后受到的一些震撼,既关于 AI 对围棋的影响,又关于中国围棋的现状;最后一部分是个 bonus,讲述计算机形势判断和自动数目的算法,这一部分我本来想作为这篇文章的主体来写,但是在一定的调研之后发现这两个问题本身都没有特别完美的解法,不足以支持我写一篇完整的文章。

关于围棋的简单科普

相比象棋和国际象棋,围棋的规则是最简单的。

对局的双方共用一个 \\(19 \times 19\\) 的棋盘,一方执黑,一方执白,执黑者先下,之后轮流落子于格点处。

rule
知道我为啥要强调下在“格点处”而不是“格子里”吗?

若两颗同色棋子之间存在一系列依次在棋盘上相邻的同色棋子,则称这两颗棋子同属“一块”。一块棋的“气”为所有与之相邻的格点中尚未被棋子占领的格点个数。若一块棋的气减为 $0$,则需要立即将这块棋从棋盘上拿去,称为“提子”。若一次落子同时造成两块以上的棋气数为 $0$(由于下面的“禁入点”规则,不可能全为一色),则应当被提取的为落子方对方的棋子。

tz
黑棋下方框处,可将白棋提去

若一次落子造成落子所在的那块棋气数为 $0$,同时不会造成对手任意一块棋的气减至 $0$,则此棋无法成立,这个格点也被成为落子方的“禁入点”。

jrd
方框处为白棋的禁入点

不允许出现全局同形,即不允许对局的过程前后中出现全局完全相同的棋形。这一条规则主要用于“打劫”这一现象:

jie
若白棋走方框处吃掉黑棋的子(根据禁入点的定义,此时方框并不是白棋的禁入点),则由于禁止全局同形黑棋不可直接吃回来,而必须要在别处走至少一步再回来,这种情况称为“打劫”

上面所说的所有规则,对于人和机器来说,都一样容易理解,而围棋的对弈过程,确实也只需要用到这些规则,所以,要想写一个围棋对局软件是很简单的,但是接下来要讲的围棋的胜负判定规则就是对于人来说容易理解,而对于机器来说颇为费解的了。

根据 中国围棋竞赛规则,判断对局终止的条件是:

先由轮到着手的一方以简洁的语言表明“棋局结束”,“棋已下完”,对方予以回应,终局即告成立。

接下来是判断胜负的阶段,简单来说围棋的胜负取决于谁围成的“地盘”大。在这个过程中,首先要将“死棋”从棋盘上清除。而所谓死棋以及与之对应的活棋,如下定义

1、终局时,经双方确认,不能被提取的棋都是活棋。

2、终局时,经双方确认,能被提取的棋都是死棋。

之后,若一个空白格点及其通过一系列相邻空白格点所能到达的所有格点相邻的棋子均为同一颜色,则认为此格点受到此方控制。(原理上,开始数目之后不应该出现一个空白格点的控制权不明确的情况,这种情况一般被认为棋没有下完,当然,这也是由上面的终局规则人为地保证的)一方控制的格点个数和其棋子个数之和称为这一方的“目数”,最终“目数”较大的一方获胜。当然,由于黑棋先落子,有一定优势,所以实际上需要黑棋一方需要讲一部分目数补给白方,称为“贴目”。(贴目规则并非自古以来就有,而是逐渐形成的,最早,日本棋手本因坊秀策在实战发现通过一种极具防御性的下棋方式,可以极大提高黑棋的胜率,人们意识到黑棋先行棋的巨大优势,从而提出了贴目规则。贴目的数量并非一成不变,而是随着围棋的发展不断变化,总的来说是越来越大,目前这个数字定格在 $3.75$,即黑棋必须比白棋多 $7.5$ 目才能取胜。)

正是因为围棋的规则中有这两条需要人参与判定、没有严谨数学描述的规则存在,其终局和胜负判断并不是一件显然的事情。在这篇文章的最后,我会简单来讲讲自动数目的原理大致如何 —— 省流:目前没有完美的方法来数目,所以正式比赛从来都是人工数目的。

围棋的规则大致来说就是上面这些,但如果你只是知道这些规则,去看围棋的解说可能还是会对各种术语有些蒙,“靠”是什么意思,“双”又是什么意思,“挂角”是什么意思,“拆边”又是什么意思?之所以发明这些术语并不是为了装逼(但是如果你掌握这些术语,倒是可以在不会下棋的人面前装逼,所以还在等什么呢?赶紧学起来吧),而是围棋的棋盘太大了,相比于象棋的“炮八平五”,围棋的解说倘若说“黑棋第一步走在 D-4”,那就太考验人的想象力也太拗口了,远不如“黑棋星位占角”来的简洁明了。

在掌握这些术语之后,你可能还需要一些“套路”上的东西才能真正去下棋。不妨问问自己,在只知道规则的基础下,你第一步会走哪里?你可能会通过一些数学上的计算,认为将棋下在角落比下在边上更能围住地盘,而下在边上比下在中部更能围住地盘,所以你会选择下在角上,然而离边界具体多远呢?三格还是四格?在走完这手棋之后,后续如何进行防守和进攻?这些东西在围棋的历史发展中已经形成了一些固定的“套路”,围绕角部区域攻防的套路被称为“定式”,它们是历代棋手在对弈过程中形成的双方都认为比较均衡的开局下法。掌握这些定式,可以让你在开局不至于陷入不利的境地 —— 应该说定式的存在在一定程度上均衡了不同等级的棋手,如果没有定式,在布局上棋力的差距就会被无限放大。

除此之外还有一些套路。之前我们说过死棋和活棋的定义,那么如何保证自己的棋是活的呢?(或者用围棋的术语说,叫“做活”)你需要给一块棋做两个“眼”,眼的严谨定义并不简洁,简单来说,它是无论走多少步都是对方禁入点的格点。杀棋和做活是围棋的基本功,而相比布局,又容易训练的多,所以市面上往往会有专门的“死活题”教材,现在信息技术非常发达,也有许多在线的题库。初学者可以尝试从最简单的做起。

当你掌握了这些套路之后,就终于可以开始下棋了。但不论你是在现实中下棋还是在网络上下棋,都会马上遇到一个问题 —— 我应该和谁下?或者说,我的水平到底如何?在这里就不得不提一提围棋的等级制度了。

围棋的等级制度分为职业和业余两种。业余棋手的等级又分为“级”和“段”,“级“由大到小实力逐渐变强,一级最强,再之上则是段位,段位由小到大实力逐渐变强,最高为业余 7 段。职业段位与业余段位类似,从职业一段到职业九段逐渐增强。职业九段是棋手的最高等级,许多我们熟知的选手如中国的“捷豹”柯洁(就你的称号最离谱)、“古大力”古力、“聂旋风”聂卫平、“妖刀”马晓春,韩国的“申工智能”申真胥、“石佛”李昌镐就是职业九段的选手。

那么不同的等级之间是怎样晋升的呢?对于业余的选手来说,每年各地的棋协都会组织定段和定级比赛,在这个比赛中选手将会和与自己同段位的选手对弈,最终排名前列的选手将会获得下一级别的证书。而对于 25 岁以下的业余 5 段选手,国家每年会组织一次职业定段比赛,在这次比赛中名列前茅者将正式成为职业选手,授予职业一段。职业选手的晋级方式就要复杂的多,既有可以通过固定的围棋联赛积累等级分晋级,又可以凭借在重大比赛中出色的表现破格提拔,实际上现在不少职业九段的选手都是通过后一种方式晋级的。

那对于初学者来说,应该去哪个级别切磋呢?我认为但凡会走定式的选手,在注册网棋帐号的时候都不要选太低的级别(比如 18 级),因为那里不是业余两三段的选手在炸鱼,就是五子棋选手,而应该根据自己死活题的水平选择对应的段位。顺便一提,一般来说“级”是没有证书的,所以一般人不会没事去打定级比赛,比如我在学棋差不多一年之后就直接定段了,没有经过定级的过程。不过也有一些地方有规定必须定级,我印象中上海就是如此,我父亲的一个老同学的儿子当时也在学棋,我已经打到二段了,他还在辛辛苦苦地定级……

学棋时的那些事情

我的围棋老师是一个外形很彪悍的业 5 大汉,很严厉,但正所谓严师出高徒,他的学生进步都比较快,他在地方上也是比较有名的围棋老师了。

当时我们校队训练的方式是先上课,再下巡回赛。上课的内容往往是先摆定式,讲一讲定式的一些变化和后续;然后再讲两道题,一般是死活题,偶尔也有官子;最后是最刺激的部分,老师会从校队成员周末下的网棋中选一盘进行复盘讲解,这个时候往往就是被抽中的同学的噩梦了,诸如“问题手”“俗不可耐”“臭不可闻”之类的话会响彻整个围棋教室。这也是为什么我小时候一直不愿意下网棋的原因,生怕上课的时候被拷打。所幸的是我在为数不多下棋的时候都下的还行,所以从来没被拷打过,与我形成鲜明对比的是另一个比我小一届的同学,他并不是棋不行,实际上他比我厉害,但他下的多,难免失误,不过他的心态一直很好,被批评的时候也是嘻皮笑脸的,大家都很喜欢他。

巡回赛会大致按照选手的水平分为两三个级别,每一个级别的选手在一轮巡回中都会和同一级别的其他选手各下一盘棋,最终按照积分晋级或者降级,就和足球联赛规则一样。由于人员变动(比方说偶尔有选手退出或加入),每个循环的人并不总是偶数,所以有时候一轮巡回赛会出现有人没有对手的情况,称为“轮空”。我最喜欢的就是轮空的时候,因为那样就可以去看别人下棋,还不用担心自己的联赛积分。由于我们当时又不少业余三段四段的选手,所以我一般是在中级别打循环,偶尔能够杀到高级别去,基本上也是一轮结束就以倒数第一的身份退回来,不过在高级别联赛中下棋总是很轻松,因为我不再那么担心输赢了,毕竟输了也不丢人。好像正是因为心态放松了,棋下的反而好了,有时候还能在高级别联赛中阻击一些高手。

课前课间的时候趁着老师不在,我们有时候会偷偷下两盘五子棋或者黑白棋,若被老师撞见,肯定少不了数落两句,然而真正被骂得最惨的还是那些斗棋子的人。当时由于学校比较有钱,给我们购置的棋子都是所谓的“云子”,云子的具体成分我也不清楚,像是某种半透明的矿石,其中黑子在灯光下会显现出墨绿色,很漂亮。云子很贵,而斗棋子的同学经常一不小心就会把棋子摔在地上。老师在苛斥两句“吊儿郎当”之余,也不忘吐槽学校浪费钱,其实正常下棋塑料棋子就足够了。

课后老师一般会布置几道死活题,印在讲义上发给我们。这套讲义最有意思的是每一页都有一小段连载的围棋历史故事,这些故事大多发生在日本,我也因此知道了各种“秀x”“x哉”“x策”,他们或是一时名士,或是得道高僧,但都酷爱下棋。这些故事看上去对学围棋没什么关系,但如果能用一些围棋之外的东西把孩子们的目光吸引到围棋上,不也是一种成功吗?有许多人反对纯粹为了乐的“寓教于乐”,我觉得对于围棋这种小众运动来说,推广和教育作为一先一后都是不可偏废的。这一点我想在第三部分再详细的聊。

我属于下棋特别慢的选手,一方面我的反应本来就慢,诸如口算比赛之类的我从来都是倒数水平,另一方面是我比较喜欢把变化算干净再下。不同围棋比赛在计时方面规则不同,有专门的快棋赛,对弈的双方往往十几秒就必须落子,但一般的比赛都会先给选手足够长的时间,等到选手用完了这些时间之后才进入到类似快棋赛的读秒阶段。我下棋慢的属性也经常被队友调侃,我的围棋老师有一次说我“慢条厮礼”,从此所有人都开始这么形容我,几乎每一场巡回赛我都是拖到最后一个数目的,这对和我对弈的人来说是一种莫大的折磨,以至于许多人一听说要跟我下棋,都会要求老师加钟。这也是我不怎么下网棋的一个原因——网棋对我来说太快了。这种“慢条厮礼”的风格多多少少也反映在我的其他事情上,我很喜欢把一件事情考虑的过分长远,想把所有的后果所有的可能统统算干净,然而人生比围棋复杂的多,很多时候我算不干净,就在犹犹豫豫中错过了许多机会。

我两次成功的定段都是在杭州的天元大厦,不得不说这个大厦的名字起得就很有围棋味 —— “天元”指围棋棋盘的正中心,也是中国棋协授予围棋选手的一个称号(与之并列的还有“名人”以及“棋圣”,这三个称号都是通过周期性擂台赛的方式决定的),这栋楼给我留下最深刻的印象是楼顶的旋转餐厅,不过我是肯定吃不起的。

定段比赛我印象最深刻的两件事情都有些阴暗。

第一次定二段的时候差了一名,结果我们发现“定段成功”的选手中有一位本来就是二段。这是因为定段比赛除了有让个人选手晋级的作用之外,它本身毕竟也是一个比赛,所以也有团体荣誉奖,利益驱使下就会有人扮猪吃老虎,到低段位来炸鱼,当时我们向组委会举报了这件事情,不过最后不了了之。

还有一次是遇到了比赛作弊的。那盘棋我在中盘的时候就吃定了对面的一条大龙,应该说已经胜券在握了。然而在别处走了二十来步之后,对面突然回去把棋救活了,本来对杀少一气的棋突然变成了多一气,我马上断定对面偷偷落子作弊了,否则之前为何放着大龙死活不管,而是去别处走一些小棋?当时我也是个爆脾气(现在也是),当场就叫来裁判,然而由于没有实际的证据,最后说到我语无伦次也无法让别人相信我。让我颇为暴躁的是当时聚集了一堆人,都在指责我无理取闹,可能他们无法相信一个最终在比赛中取得第四名成绩的选手会作弊吧。如果说我从这件事情中学到了什么,那就是正义和手段同样重要,有时候在理的人不一定能伸张正义,倘若当时我冷静一点,把事情的来龙去脉理清楚,会不会结果有所不同?然而似乎我就是不吃教训,后来我遇到了很多让我义愤填膺的事情,每次我都没办法很好地控制自己的情绪寻找理智的解决办法,往往一上头就什么离谱的事情都做得出来,小到任课老师大到学院领导都被我当面骂过一遍,让我的辅导员很头疼。而每次做完这些离谱的事情之后我想要解决的问题也没有任何转机,就像当年的作弊者,完全没有因为这件事情受到任何影响。

pkc
也许这才是正确的心态

围棋是少数男女比较平等的运动(可能智力运动相对来说都会平等一点),一般来说,有“女子围棋比赛”,但没有“男子围棋比赛”,也就是说虽然女性选手平均竞技水平可能不如男性选手,所以需要单独举办比赛进行照顾,但男性能参加的比赛,女性一样可以参加。中国历史上一共有 55 位职业九段选手,就有两位是女性,其中芮迺伟更是在国际大赛上战胜过彼时如日中天的“石佛”李昌镐。我们当时校队里也有不少女生,平时打巡回赛的时候我也与她们有不少交手。总的来说,我不觉得女性选手在围棋上和男性选手有什么不一样,只是学围棋的女生确实少。可能许多事情都是这样,社会观念投影到教育上导致男女呈现出一种结果上的不平等,而结果上的不平等反过来又加强于社会观念上,让人觉得“会不会男性/女性不适合做某件事情”,导致恶性循环。

大人,时代变了 —— 围棋和中国围棋的现状

AI 真的“杀死围棋”了吗

之前在柯洁视频的评论区看到一个有意思的评论:

自从有了绝艺之后,柯洁的粉丝中突然多了好多职业九段

这里的“绝艺”,是国内的一款围棋 AI。现在如果在野狐上下棋,除了之前就有的“形势判断”功能之外,还有胜率计算功能,甚至对于一些高级的用户,还能给出 AI 判断下的落子选择。人们在评棋的时候的话术也逐渐发生了演变。以前我们会说“黑棋这手俗,亏了”,现在人们说的则是“绝艺认为这手棋将黑棋的胜率拉低了 20%”;以前我们会说“白棋这手是手筋,是妙手”,现在人们则说“这是绝艺给出的一选”。且不说一些完全不懂围棋的选手用绝艺“开挂”、不懂装懂的行为本身是否可耻,看着弹幕上随处可见的绝艺和 AI 胜率,我不由得感慨一句,时代真的变了。

AI 给围棋这项运动带来的影响主要体现在三个方面:

首先是关注度,从前都是 AI 要蹭体育运动的热度,当年“深蓝”击败国际象棋大师可能是 AI 在平常人视野中的第一次亮相。然而时过境迁,现在 AI 本身已经成为很火的东西了,以至于当 AlphaGo 战胜李世石之后,我感觉火的并不是 AlphaGo,而是围棋本身。而现在像绝艺这样的 AI 辅助系统能够把以往只有受过一定训练的棋手才能判断的“势”转化为所有人都能看懂的胜率,这无疑对围棋的普及是有利的。

其次是 AI 对围棋本身也产生了深远的影响。比如前文所提到的“定式”,其本身就是历代棋手在不断对弈的过程中形成的“套路”,并非围棋与生俱来的一部分,甚至直到近代,仍然有不少定式、变式层出不穷,比如著名的“芈式飞刀“,就是由中国的现役棋手芈昱廷九段提出的。而最近在看柯洁直播的时候,我有时候会看到一些从来没见过的定式,才知道这是“绝艺的招”。有人说 AI “杀死”了围棋,其实在我看来 AI 是在帮助围棋进步、加速围棋的发展,新的定式、新的布局,这都是 AI 馈赠给人类选手的礼物,我相信即使没有 AI,这些招法最终还是会被人类选手研究出来,只是那也许需要很多很多年的积累才行。

最后是 AI 对于围棋教育也产生了一定的变革。过去围棋的教育一直是传统的师傅带徒弟的模式,就好像武侠小说中的各种门派,一个好的老师对于选手的大局观培养是很有帮助的。而现在 AI 的出现让所有选手都拥有了一位好老师。即使对于顶尖职业选手,AI 也已经成为了他们日常训练中的一部分,比如韩国选手申真胥就被誉为“申工智能”,正是通过对 AI 招法的研究,申真胥在短期内进步神速,现在已经俨然是世界棋坛的第一第二。

所以,也许你在网上冲浪的时候会遇到不少诸如 “AI 害了围棋”“AI 让围棋变得无聊”之类的发言,但就从我,一个曾经的业余选手的角度来看,这些话并不对。作为围棋爱好者我们应该感到庆幸,因为围棋从来没有在哪个时代发展的如此迅速过,我们正在见证的进步很可能超过了过去所有时代的总和!

而至于 “在 AI 如此强大的今天下围棋是否还有意义”,则是另一个问题,但对这个问题我又有通用的答案,即我认为人类选手进行的任何运动都不会被 AI 取代。因为但凡是竞技性的运动,偶然性都是其观赏性的主要部分。也许今年世界杯的决赛重踢一百次,法国能赢八十次,但事实是阿根廷赢了,这就是奇迹,没有奇迹的历史,将是多么无聊!人和人的对局有意思的地方就在这里,哪怕只有 AI 认定的个位数的胜率,死拼到底依旧会有逆天改命的可能。

最后我想用高中同学曾经在作文里写的一段话结束这一段的讨论。那段时间 AlphaGo 刚刚击败柯洁,关于它的讨论甚嚣尘上,于是在一次考试中老师布置了一篇关于 AI 与人类棋手的作文。老师选取的范文题为“钢铁丛林中一颗会思想的苇草”,系班上的一位女同学所写,时隔多年我依旧记得它的结尾,只不过由于年代久远,具体的话已经忘却,只得凭借自己蹩脚的文字为她所表达的思想进行插值:“AlphaGo 输给了李世石,它回去之后在一夜之间和自己下了许多盘棋;柯洁输给了 AlphaGo,却流下了眼泪。这是柯洁输的原因,也是柯洁赢的地方。”也许人类棋手永远不能再次战胜 AI,但是人类的勇气、感性将被视为他最珍贵的东西,写进每一首赞歌之中。

中国围棋的现状

围棋最近似乎在年轻人中很火,以至于我的室友这样以前从来没有听说过围棋的人也开始在网上和人下棋。这波围棋的热度我觉得少不了柯洁、连笑、战鹰等人在 b 站上宣传的功劳。但对这三人的批评声音从来没有停止过。有人说他们搞“抽象围棋”不好好下棋训练导致水平退步,有人说他们将围棋庸俗化,不利于围棋的正面宣传,也有人说他们在众人的拥护中失去了棋手的本心。

kj
柯洁怒斥“云围棋”玩家

但我个人觉得,宣传没有所谓的雅俗之分,尤其是宣传一项运动、一个兴趣爱好,最重要的还是把人吸引进来,不管以什么方式。柯洁曾经在直播中吐槽大部分来看他直播的人都不懂围棋,这可能是真的。但这难道不正好说明了这样的宣传的必要吗?一个下围棋、关注围棋的人不会不知道柯洁,而能够让围棋这项运动被更多“圈外人”知道,柯洁选择的方式又有何不可呢?

学棋的人很少。在这个义务教育阶段极其内卷的国家,可能学围棋的收益远不如其他“兴趣爱好”。就我个人而言,我后面不学了也很大程度上是因为要忙着搞小升初的事情。可以说,如果不是我父亲本身酷爱下棋的话,我不可能接触到围棋这项运动 —— 但我觉得围棋本身是很好玩的!许多人缺少的不就是一个接触围棋、了解围棋的契机吗?至于有没有兴趣、有没有天赋,那是后面的事情。

所以我觉得不管柯洁等人在 b 站上干什么,只要围绕围棋,就无可厚非。每个下棋的人都有不同的接触围棋的理由,对我来说是因为我的父亲;而对我的父亲来说,又是因为在中日赛场上大杀四方的聂卫平;对大部分人来说,可能是为了升学的便利。如果最后一个理由尚可成立的话,为什么不能是“我觉得俞俐均好看”或者是“我喜欢听捷豹扯皮”呢?正如择偶一般,最开始的时候人们往往被事物的表面所吸引,止步于肤浅的喜欢,之后才能逐渐深入。见色起意固然不可长久,然而如果没有这肤浅的喜欢,又怎么可能有后面的爱的深沉?

gl
古力老师的话,不无道理啊

我不知道现在学围棋的人还多不多,但我很高兴能看到越来越多的年轻人正在逐渐了解这项运动,中国围棋的现状不仅仅取决于国家队有多厉害,根本上还取决于人们对于这项运动的态度。也许等到这批年轻人成家立业、结婚生子,他们的下一代会就有更多的人学习围棋。对中国围棋来说,这是好事。

形势判断与自动点目到底是怎么做的?

前几天在野狐上下棋的时候,我发现野狐的形势判断功能有时候会出现误判,将一块棋的生死弄错,造成极大的出入。而由于野狐围棋在任何时候都是可以申请数目的,即使官子还没有收完,所以我就怀疑野狐的形势判断和自动点目是不是同一套系统,而连生死都能算错的一个系统又怎么可能用来判断比赛的胜负?

然而稍加思考之后我发现精确的数目并不是一件显然的事情。其中最麻烦的一步在与将死子从棋盘上清除。在第一部分我们介绍过,围棋对于死棋是没有数学化的定义的,而是基于对局双方的共识。这样不严谨的定义使得即使是人工点目,也有可能出现“错误”,比如双方一致认为某块棋是活棋,但实际上存在杀死这块棋的方法。当然,这种情况很少,而“错误”之所以打引号,是因为这样的结果是在规则允许范围之内的。

所以,本着“归约”的思想,我希望能在网上找到能判断死活的 AI,毕竟判断一块棋的生死,本质上就是判断是否存在先手做活的可能,而解决了生死问题,就能结局点目的问题。我的确找到了一些文章,比如 这篇(值得一提的是,这个作者是个中山大学的化学教授,文章应该是他退休之后发的,他还组织开发了一款叫做 HandTalk 的围棋 AI)。文章很长,具体细节我没看,直接跳到测试结果,发现它对于高级一点的死活题,正确率还是很低。

于是我得出了一个结论,想要精确地、形式化地点目,是不太可能的,因为它可以归约到死活题,而后者又是不太可解的。所以我们只能退而求其次,追求不完全精确的解法。只要我们保证程序在绝大部分情况下都是正确的就好了,而剩下的部分就算不正确也没关系,因为在实战中几乎不会碰到。

但这样的结论其实让我有点失望,这也是为什么我本来想将这部分作为这篇文章的主要部分,最后却只能简单带过了。

Easy case: 形势判断

形势判断本身不需要太精确,因此相比自动数目要简单很多。其核心在与判断一颗棋子对于周围格点的影响,如果一方的影响显著大于另一方的影响,那么这个格点可以视作处于占优一方的控制下。形势判断就是统计双方控制的格点数目。

让我不太意外的是,涉及到围棋形势判断的许多文章和计算机视觉都有千丝万缕的联系。毕竟传统的 2D 视觉就是在处理二维、网格状结构的信息,围棋完美吻合这一点(这让我不禁想,或许现在来看直接拿个 CNN 跑一下也能搞一个形势判断的工具出来?)。在这里,我主要介绍 这篇工作(文章的作者整个 PhD 生涯都在搞围棋相关的研究,从形势判断搞到基于蒙特卡洛搜索的 AI,可以说是非常奇葩了……)

文章的思想很简单。我们首先考虑特殊情况,如果一块地确实被同色棋子围住了,那么形势判断工具应该要能正确判断这块地的归属(当然,形势判断不能满足于此,他还要能判断尚未被围住但几乎可以肯定将来会被围住的区域的归属)。这是可以直接用离散的算法来做的 —— 做一下洪水填充即可。然而,这样的算法是定性的,它没有办法量化一个格点受到的控制有多强。我们应该从定量的算法出发,让其拟合我们上面提到的特殊情况。

作者从别处获得了灵感,定义了算子 $E$(erosion) 和 $D$(dilation),若设棋盘上的所有格点构成集合 $\mathcal{G}$,记 $N(x), x \in \mathcal{G}$ 为所有与 $x$ 直接相邻的格点,并记:

$$N(X) = \bigcup_{x \in X} N(x)$$

此时算子 $E$ 和 $D$ 定义如下:

$$ \begin{aligned} D(X) &= N(X) \cup X \\ E(X) &= \mathcal{G} - (D(\mathcal{G} - X)) \end{aligned} $$

用通俗的语言来说,$D$ 算子将一个格点集合向外扩张了一圈,而 $E$ 算子则将格点集向内缩了一圈。

作者提出,我们可以使用 $E^n \circ D^n$ 来近似一块棋所控制的范围,他并没有给出这样做的里有,所以这样做的 insight 是什么?

首先是它对于特殊情况的拟合。实际上,它满足如下的结论:若 $Y$ 是棋子集合 $X$ 包围的区域,假设棋盘无限大(这是为了防止 $D$ “碰壁”),则:

$$\exist N \gt 0, s.t. \forall n \gt 0, Y \subset E^n \circ D^n(X)$$

证明也很显而易见,实际上,如果 $Y$ 中格点到 $X$ 的最大距离为 $L$,我们可以取 $N = L$ 让上面的包含关系成立:考虑集合 $D^n(X)$,它由所有到集合 $X$ 的距离不超过 $n$ 的格点组成,当 $n \ge L$ 的时候,自然有 $Y \subset D^n(X)$。再考虑集合 $\mathcal{G} - D^n(X)$,其中的格点到 $X$ 的距离都大于 $n$,由于 $Y$ 被 $X$ 包围,而 $Y \subset D^n(X)$ 隐含了 $Y \cap (\mathcal{G} - D^n(X)) = \emptyset$,故 $Y$ 中的格点和 $\mathcal{G} - D^n(X)$ 中的格点被 $X$ 隔开,二者之间的最短路径一定过 $X$,这意味着:

$$\forall y \in Y, d(y, \mathcal{G} - D^n(X)) \gt \min_{x \in X} d(x, \mathcal{G} - D^n) \ge n$$

(我之前没有给出“包围”的严谨定义,如果要给的话,上面的性质本身就可以作为定义)

最后,根据定义,注意到 $E^n \circ D^n(X) = \mathcal{G} - D^n(\mathcal{G} - D^n(X))$,后者是距离 $\mathcal{G} - D^n(X)$ 大于 $n$ 的格点集合,由我们在上面所证明的,$Y \subset \mathcal{G} - D^n(X)$。

不过,这个结论并没有说 $Y = E^n \circ D^n$,反例是很好构造的

result
n = 1 的情况下,中间的四个格点会被认为是黑棋势力范围

现在,我们把双方的棋子都加进来考虑。此时 $D$ 算子在进行扩张的时候不仅仅会撞到棋盘的边缘,还有可能会撞到异色棋子控制的范围。一个显然的想法是将 $D$ 算子可扩张的格点集合改成所有还没有被控制的格点,但这样会有一个很明显的问题:可能有两块棋到一个格点的距离相同,但是其中一块棋的势力要强很多,原理上不应该让二者对这个格点拥有相同的影响。这归根到底是因为目前的算法只给每个已经被覆盖到的格点定性地赋予了两种颜色中的一种:白色、黑色,而没有定量分析这些颜色的深浅。我们需要定量地分析每种颜色对同一个格点造成的影响强弱。作者的解决办法也很简单:每个格子不仅有颜色,还有数值,数值越大,说明影响越强。而具体的更新策略为:在扩张阶段,对于每一个格点(包括无色和有色),如果相邻格点有色且颜色相同,则将这个格点的颜色设置为相邻格点的颜色,数值设定为相同颜色的相邻格点的数值和;而在收缩阶段,对于每一个有色格点,相邻格点每有一个颜色不同,则将数值减 1。这个算法相比之前的算法叠加了不同棋子对同一个格点的影响,更为准确合理,每个棋子对于其周围的点的影响将通过扩张阶段源源不断地向外界输送。最终,作者展示了用他的形势判断算法分析某一局对局的结果,我认为总的来说还是不错,但是对于左下角角部的估计略显保守了一点。

result
我觉得还行

值得一提的是,这篇文章通篇没有讲死活的判断,而在实际的形势判断中,这当然不可忽略。这就注定了这篇文章所讲述的方法往往只适用于开局时局面比较明朗的情况,到了中盘甚至收官阶段,其误差将会比较严重,真正的形势判断要更加复杂一点。

Rocky road: 自动点目

自动点目技术涉及到比赛的胜负,所以要更加精确一些。然而目前还没有任何能够形式化验证其正确性的代码,所以这里就不仔细讲其细节了,只是讲一下大致的思路。我在网上找了半天,似乎最新的文章是 这篇,我看它的结果感觉也还行。

之前说过,如果死子都已经从棋盘上清除,那么点目就变得很简单了。而死棋的定义又是“能够最终被提掉”的棋子。那么自动点目的一个很自然的做法是为对局的双方写一个简单的 AI,由这个 AI 走足够多的步数,直到所有死棋都被提掉为止。这种方法被称为“动态”数目,因为它需要改变棋局。这种方法的精度取决于 AI 是否智能,在这里不做讨论。

与之相对的是“静态”数目,即直接通过终局时的局面来判断。我引用的文章就是这一思路的代表。整个算法的细节非常多、非常复杂,有一万个特殊情况需要考虑,很不优美,所以具体的算法我就不讲了。其核心思想有俩:

  1. 除了直接相连的棋子,棋子之间也有间接的连接,比如尖或者双,虽然没有直接相邻,但由于同时有两个格点可以使之相连,另一方无法将其分开,这样的两块棋应该作为一个整体处理。算法的第一步就是将棋子划分成这样的部分。
  2. 一般来说一块棋需要两个眼才能存活,但是也会有一些棋因为势力范围很大以至于不需要两个眼别人也无法杀掉它(或者说,很容易就能作出两个眼来)。这个数目算法在判断生死上的精髓就是它根据眼位、气、控制范围(由之前提到的形势判断工具计算)给出了判断一块棋生死的一个估价函数(这个估价函数也很简单,就是所有因素的线性组合),然后依次从棋盘上提取“最死”的棋,重新计算剩下的棋子的估价函数,直到剩下的全部是活棋为止。

如果作者给出的测试结果是正确的话,这个算法的结果相当的好,除了一些极其复杂的双活无法判断之外,在测试的六百多局中完全正确。只是实现起来估计非常麻烦……

结语

在写这篇文章的前后,我在野狐上下了五六盘棋,深感棋力大不如前,现在面对野狐上 1 级的新手,也招架不住输了 4 目(对围棋来说 4 目已经有点多了)。我知道也许我去复习一下那些定式,再多下几盘棋,也许就能重新捡起这个爱好,但最终我还是没有这么做。正如我在自我介绍中曾说,人越长大,“身份”是会越来越少的,因为时间总是有限的,我已经没有那么多精力去尝试这尝试那的了。只是如果偶尔有比赛的话,还是会关注一下围棋。