反棋(自杀棋)是改了两条规则的国际象棋:能吃子就必须吃;把自己所有棋子都送掉的一方获胜;王只是普通棋子。Lichess 上可以下这个变体,它在 2016 年已被解决(马克·沃特金斯证明 1. e3 白方必胜)。

我把这两条规则搬到象棋棋盘上,先测量结果再谈设计。结论是和棋:黑方在开局有两步棋必须找到,红方不会走错,之后你必须送掉的那些棋子都待在九宫里,什么都够不到它们。其余每一种开局都会输,其中 63 种已被证明。

就我能查到的范围而言,这是第一份关于象棋棋盘上反棋的分析;最接近的先例是混合棋子的 Synochess 与 Empire 棋盘上的反棋,以及 5x5 将棋上的反棋。

由于这篇文章面向国际象棋玩家,记谱采用国际象棋式写法:R 车、H 马、E 象、A 士、K 将、C 炮、P 兵;纵线 a 到 i 从红方左侧数起,横线 1 到 10 从红方一侧数起,因此 1. Cxb10 表示炮吃掉 b10 上的任何棋子。一步指单方走的一着。

这盘棋

如果你没下过象棋,Mistboard 的规则页几分钟就能讲完。

这篇文章依据的每一盘棋都在下面的对局浏览器里:引擎以每着一百万、两百万和五百万节点自战的三盘;开局连锁 83 个终点各一盘;强引擎从随机开局迎战弱引擎的 20 盘天梯对局;以及 63 份证明各自的主变。它默认打开 2M 那盘,也是最该先看的一盘:强制开局,双方同步弃子,红方故意送掉最后几个可出击的子力,棋盘在第 35 步陷入死局。

黑方
红方

开局:黑方有两步棋必须找到

这盘棋的强制部分是一条四到五步长的连锁强制吃子,其中有三个分岔。两个属于黑方,都决定胜负;一个属于红方,无关紧要。下面所有棋盘都截自同一张表:连锁中的每一个局面、轮到走棋一方可选的每一种吃法,以及每种吃法通向何处。每一行的标签是双方接着都按连锁中的最佳吃法走时该吃法之后局面的价值;小字是其依据,能封闭的给出证明,不能的给出引擎的判定。把鼠标悬停在一行上可在棋盘上看到该吃法;点击即可沿它前进,走过一个终点后继续前进,就能看到随后的对局。

分岔 A:1. Cxb10 之后,黑方有两种吃法,其中一种会输

黑方
红方

红方第一着是炮吃马。两种选择互为镜像,就称之为 1. Cxb10。黑方必须吃子,有两种方式:用车吃回那门炮,或者用另一门炮轰向红方底线(炮吃子要恰好跳过一个棋子;这里的炮架是红方自己的 h3 炮)。自然的一着 1…Rxb10 会在 34 步内被强制击败,而且这一点已被证明。另一着 1…Cxh1 则站得住。

为什么车吃回会输

证明全在这里。证明凭证是一棵树:红方每一着只保留一步,黑方每一着则列出全部合法应着。这一份共有 1,864 个局面,控件全部收录。向前一步步走可跟随主变,关键的几步附有注释;或者在黑方任何一着处改选别的应着,沿它走下去。每一行都是合法着法,此外再无其他,而每一条路线都以红方无子可走告终。

1...Rxb10:完整证明
黑方,任意应着
红方,证明凭证

一着让对手恰好只剩一种吃法的静着,就是对手不得不走的一着。红方底线的棋子排成一列,黑方的车被迫吃掉送到面前的每一个,替红方清空队列。三十步之后红方一子不剩,赢了。一个只懂规则的校验器已重放了整棵树;控件里就是同一棵树。

所以黑方唯一的着法是 1…Cxh1。

分岔 B:1…Cxh1 之后,红方有两种应法,都站得住

黑方
红方

红方可以安静地用车吃炮,2. Rxh1,交换就此结束:2…Rxb10 是黑方唯一的吃法,连锁在第 4 步终止,轮到红方,棋盘上无子可吃。红方也可以继续开炮,2. Cxd10,同样站得住,并给黑方设下第二个陷阱。这是无关紧要的那个分岔。引擎从初始局面自战的对局在每一种预算下都选了 2. Rxh1。

分岔 C:2. Cxd10 之后,黑方必须用将吃

黑方
红方

黑方再次有两种吃法,显而易见的那一种再次是输棋的。用将吃炮,2…Kxd10,站得住:接下来 3. Rxh1 是红方唯一的吃法,连锁在第 5 步终止,轮到黑方,与 2. Rxh1 之后的终点是同一类局面,只是换了一方走棋。继续开炮,2…Cxf1,则会输:红方用帅吃炮,3. Kxf1,黑方唯一的吃法是 3…Kxd10,连锁在第 6 步终止,轮到红方。从那里出发,红方在每着 100,000 节点下 38 步内以全灭取胜,每着一百万节点时亦然。

最后这一条是引擎的判定,不是证明。证明器在这里耗尽了预算,它是主变上唯一依赖搜索的终点。即便 2…Cxf1 真能站得住,上面的结论也不会改变:黑方只是多了第二种求和的方法,这盘棋依然是和棋。

2…Cxf1 之后红方有三种吃法,棋树的其余部分就在这里:

黑方
红方

取胜的着法是 3. Kxf1。另外两种让连锁继续,83 个终点里有 80 个在它们之下:3. Cxa10 通向 21 个终点,双方最佳着法下是和棋;3. Cxf10 通向 58 个,双方最佳着法下红方会输(黑方应以 3…Kxf10,再次用将吃炮,连锁在第 7 步终止,轮到黑方)。这两种吃法红方永远不必走,所以谁也不会被迫走进那 80 个终点;想看的话,浏览器可以走进去。

连锁之后:双方各自图什么

1. Cxb10 Cxh1 2. Rxh1 Rxb10 之后楚 河 漢 界1. Cxb10 Cxh1 2. Cxd10 Kxd10 3. Rxh1 之后楚 河 漢 界
存活下来的两个终点:左边走了四步,轮到红方;右边走了五步,轮到黑方,将已在 d10 吃掉炮。双方各 14 子,棋盘上无子可吃;引擎在三种预算下从这里出发的每一盘都是和棋。

这就是存活下来的两个终点:左边是 1. Cxb10 Cxh1 2. Rxh1 Rxb10 之后,轮到红方;右边是 2. Cxd10 Kxd10 3. Rxh1 之后,轮到黑方,子力相同,只是将在 d10 上,a10 的车还在原位。双方各 14 子,无子可吃,棋局就此展开。下面写的是引擎在三种预算下的对局所显示的东西。

你没法丢掉一个棋子,只能让它被吃掉。所以每一着都是一次奉送,而算数的是对手无法拒绝的那些:一着让对方恰好只剩一种吃法的静着。中局就是这类奉送的较量。

松动的车是个负担。把棋子放到它的路径上,它就必须一个个吃掉;车吃回正是这样输掉的。因此双方开局都改为送炮。在 2M 那盘里,3. Cb3 把黑方的炮架到 b1 的马上,接连三次吃子之后两辆车都松动了:十四步的强制吃子,子力同步消失。

或者打一场缓慢的兵战。在 5M 那盘里,谁都没有早早找到强制性的奉送,于是兵互相走进对方的路径,持续了一百步,成对被吃,途中还搭上了一个象和一个帅。下面这盘棋的注释逐次记录了这些交换。

黑方
红方
引擎自己的两盘对局,从强制部分结束的第 4 步打开。注释附在关键的几步上。

为什么是和棋,以及这个结论建立在什么之上

将和士永远不离开九宫,象永远不过河。在“输光所有棋子”的目标下,每方这五个棋子只能被走到它们跟前的敌方棋子吃掉,而双方都在设法摆脱恰恰是那些能走过去的棋子。

死局。一旦双方都没有了车、马、炮、兵,就再也不可能发生吃子。规则却不知道棋局已经结束。

死局楚 河 漢 界
引擎 2M 那盘的第 35 步。将帅和士仕永不离开九宫,象相永不过河,所以这里没有任何棋子能够到另一个棋子;按成文规则,棋局继续走到重复局面成和。

2M 那盘在第 35 步走到这里,红方把最后三个可出击的子力送给黑方的车,随后在第 44 步以重复局面成和。

兵战的结局是双方各剩一辆车加九宫里的棋子,而这是一个你可以亲手验证的和棋。红方的棋子都离不开红方半边,所以没有任何东西够得着黑方的车;那辆车有红方棋子永远站不上去的线路,所以它永远不会被迫吃子;棋盘上无子可吃时任何着法都是合法的,所以想等的一方只要来回挪士,直到无吃子步数限制终止棋局。颜色对换也一样。

要取胜,你需要对手保留足够的可出击子力来吃光你的整个九宫,还要它被迫使用这些子力。这些子力由对手掌控:它可以把它们扔进你无法拒绝的吃子里,可以把它们停到一边,也可以干等。在每一盘引擎对局里,需要的时候三者之一总是在场;随机对弈中,3,000 盘里有四分之一陷入僵局。

这是证据,不是证明。搜索到每着五百万节点也没有从任何一个存活终点找到胜法;我没有证明从连锁能通向的每一个局面都存在这条退路,只证明了没有人找到过一个不存在退路的局面。标题就是这个判定加上这份棋盘几何,而不是一条定理。

能把它改成一盘像样的棋吗?

和棋源于一个事实:每方有五个棋子只能被对手宁愿扔掉的棋子吃掉。任何修补都必须改变这个事实、改变你必须输掉的东西,或者改变僵局的价值。我试了四种,用同样的检验、扫描、证明器和自战。没有一种成了像样的棋。

把每一个僵局判给子少的一方。这是 FICS 的困毙规则,推广到棋局停止的所有情形。此时靠弃子冻结棋盘只会把棋局送给更轻的一方。随机对弈的未决局面从 26% 降到 4%,且不偏向任何一方(红方 47.9%)。引擎对局则毫无变化:引擎不知道这条规则,同样的对局只是被重新计分,而这对该规则会催生出怎样的棋一无所言。要正经测试它,需要给 Fairy-Stockfish 打补丁让引擎为子数而战,再花一天下棋。我停在了这里。

改为输掉将而不是输光所有子。这是 1844 年的祖先 Codrus。目标总能沿着纵线够到,但那根杠杆仍在:弃掉可出击子力的一方永远不会被迫吃掉对方的将。它经由同样的两条开局路线成和,而且更快(28 个终点,25 个负局中 20 个已证明,三盘自战皆和)。

保留将的王者身份。这是 ICC 的 Losers 版本:将军和将死照旧,被将死或被吃到只剩光将即获胜。有胜负,但方向错了:黑方在一百万、两百万和五百万节点下都获胜,把它 16 个终点的连锁回推上去也是黑胜(13 个负局中 7 个已证明)。一次将军会暂停对方的吃子义务,而在我看过的每一条路线里,这个先手都落在后手一方。

放九宫里的棋子出来。这样做通过取消限制来拆除堡垒,也顺带拆掉了让这些棋子之所以是象棋棋子的大部分东西。我没有测量它;那已经是另一张棋盘了。

第一种是唯一既保住原貌又可能行得通的方案;僵局开关已经在内核里,想试的人可以试。

我是怎么检验的

三件工具,然后是它们产出的结果。

裁判、棋手和证明器

裁判是一个带有上述规则开关的象棋规则内核。我在 209 个局面上把它的着法生成与 Fairy-Stockfish 做了对比:零分歧。每一盘棋都由引擎提议着法、内核裁定、执行并终止棋局,所以引擎若悄悄按另一套规则下棋,整轮会中止,而不会留下一份其他棋的记录。

棋手是通过配置文件设定的 Fairy-Stockfish。它的评估从未学过这个目标,而且看得出来:十倍搜索对一倍搜索在这里只有 10 胜 4 负 6 和,而在普通象棋上是 20 比 0。这就是开局依赖证明而不依赖引擎的原因。

证明器接受一个局面和一个断言(“从这里红方必胜”),构造一棵树:红方每一轮保留一步取胜着法,黑方每一轮走任何应着都会输,一直到内核判定棋局结束的局面。若这棵树能封闭,该断言就是关于规则的事实,无论任何引擎怎么想。它采用标准方法证明数搜索,设有 60 步截断,截断按攻方负计,因此证明永远不能靠它撑住。每份证明都保存为一份证明凭证,即一个嵌套的着法列表,另有一个独立的校验器只负责对照内核重放凭证,别的什么都不做。

扫描:连锁终点谁先走谁赢

我最初写规则时,把黑方的应着当成了强制的,以为每盘棋都以同样的四次吃子开始。错了。黑方的另一门炮可以借红方自己的 h3 炮为架吃掉 h1 的马,由此引发一条连锁:每一门炮落在一个炮架旁边、后面有目标,对方的炮再沿自己的底线回应,直到某一门炮落在车能够到的位置才停止。我让内核走遍每一条分支:605 个局面,166 个终点,深度在第 4 到第 18 步之间,其中 72 个在第 14 步,且有 130 个终点至少已有一方的将被吃掉。撇开镜像不计,有 83 个互不相同。

我让引擎从每一个终点各下一盘,双方每着 100,000 节点。83 盘中有 70 盘在随后 14 到 36 步内结束,一方不断送子,另一方被迫吃掉,赢家就是在终点处拥有第一着自由着法的一方,70 盘里有 66 盘如此。其余 13 盘陷入僵局,按成文规则算和棋。

终点所在步数 谁先走 终点数 红胜 黑胜 僵局
4 红方 2 1 0 1
5 黑方 1 0 0 1
6 到 12 交替 14 8 6 0
14 红方 36 36 0 0
15 黑方 5 0 4 1
16 红方 15 8 1 6
17 黑方 6 0 6 0
18 红方 4 0 0 4

所以在连锁内部,每一次在吃法之间的选择,实际上都是在选择连锁终止时由谁先走。以每着一百万节点重跑一遍:十一个判定有变动,六个僵局变成了胜局,两个胜局拖得更长,三个僵局仍是僵局,没有任何胜局换了赢家。

这有多可信:100,000 节点是很廉价的搜索,而引擎在这个目标上很弱,所以扫描只是找出候选,本身不能定论。它的胜局站住了:预算增至十倍时没有任何一局换边,70 局里有 63 局随后不靠引擎得到了证明。它的僵局则是较弱的证据:僵局只说明引擎没找到胜法,13 局中有 6 局在一百万节点下变成了胜局。真正要紧的两个僵局是存活下来的终点,它们在一百万节点下仍是僵局,在从初始局面出发、最高每着五百万节点的每一盘里也是如此。疑问就集中在这里,而讲为什么是和棋的那一节说的正是这件事。

证明,以及那张表

从 70 个有胜负的终点各自出发,预算为一百万个局面:63 个封闭,7 个耗尽预算,没有一个被推翻。证明的中位数是 19 个局面,即一条守方每一着都被迫的单线;最大的是车吃回那份的 1,864 个。校验器通过了全部 63 份。

于是每个终点都有了一个价值,开局一节里的那张表就是这些价值沿连锁回推的结果:在每个分岔处,轮到走棋的一方选择对自己最有利的子树对应的吃法。两个终点存活下来;其余每一个都位于某个分岔之下,而在那个分岔处对方本可以改选一条胜路。这张表按 100k 扫描计分;改按 1M 扫描计分,初始局面八步之内没有任何价值发生变化。

证据

上面的一切都在同一个仓库里:三份 Fairy-Stockfish 变体配置、开局连锁的全部 166 个终点、每个终点在每种预算下的一盘引擎对局、每一份证明凭证、规则内核,以及一个从文件夹直接打开的对局浏览器。npm run verify 只对照规则重放每一份凭证,几秒钟完成,报告 63、63、20 和 7 份有效;README 里有用 Fairy-Stockfish 可执行文件复现扫描与证明的四条命令。

如果你能给出第三条存活的开局、任何一份凭证里的防守,或者从四步强制着法之后的局面出发任何一方的胜法,请去那里提一个 issue。我想看到它,这篇文章也会如实写明。