规则

走一枚棋子。它从落点攻击到的每一个敌方棋子都会加入你方。棋子永远不会被吃掉,所以 32 枚棋子整局都留在棋盘上;一步攻击到对方将帅的棋即获胜。

楚 河 漢 界Mistboard
0 / 1
  1. 红方走棋。d1 上的车什么也没有攻击。两个黑卒站在第四横线上,正是它要去的地方。
  2. 1
  3. 两个卒都换了阵营。没有吃子,也没有棋子离开棋盘,所以一步棋就让红方多出两子、黑方少了两子。

在演示棋盘上的规则。圆圈标出这步棋转化的棋子。

停在原地的攻击不起作用。只有走动的那枚棋子会转化对方,所以已经瞄着某枚棋子的车必须再走一步才能拿下它。威胁只能靠走棋来制造。

它对象棋做了什么

永远没有残局。 没有兑子,局面不会简化,残局库也不可能存在,因为子力从不减少。象棋的残局理论,也就是象棋理论的大部分,完全用不上。

炮永远不会变弱。 象棋的炮需要炮架才能吃子,所以在象棋里它会随着棋盘变空而变弱。这里棋盘从不变空,炮在对局后段和第 3 步时一样危险。

仕和相什么也守不住。 它们存在是为了防吃子,而这里没有吃子。它们仍能挡住线路、给炮当炮架,但它们被设计出来要做的事都没有了。

对局很短,没有人和棋。 下面 54 盘引擎对局中,一半在第 28 步前结束。没有一盘是和棋,6,000 盘均匀随机合法着法的对局也没有一盘和棋。没有子力可兑,也没有残局可磨,每一盘都会分出胜负。

约 28% 的合法着法当场就输。 这是引擎对局中 1,696 个局面的平均值。中位局面有 10% 的着法会输,平均值是由少数非常尖锐的局面拉高的。这个比例从对局前五分之一的 24% 升到最后五分之一的 37%,所以不存在可以安心出子的平静开局阶段。

设计:四个决定

将帅仍然不能照面。 象棋禁止两个将帅在同一条直线上中间无子相隔,我们保留了这条规则。另一种做法是把白脸将变成胜利条件,但它行不通:只有走动的棋子才会转化,所以打开这条线并不能取胜,结果将帅相对而立,对局却继续,直到有人把将帅沿着这条线挪一步去领取胜利。

保留这条禁令没有代价,还带来了象棋没有的东西。被钉在将帅线上的棋子无法被移走,因为这里没有任何东西能移走棋子;转化它也不能解开牵制,因为转化是原地变色。你可以赢得这枚棋子,却仍然动不了它,直到一方的将帅离开这条线。

仕和相受它们所在的区域约束,不论归谁所有。 被转化的仕站在敌方九宫里。如果受原主人的九宫约束,它会永远冻结在那里;受它所在的九宫约束,它就能继续行棋,从内部发动攻击。从初始局面看两种理解是一样的,因为每个仕都从自己的九宫出发。

兵卒受其主人约束。 兵卒的前进方向必须跟随它现在的主人,否则被转化的兵卒会永远背离新的阵营前进。把这两条规则弄反,会悄无声息地毁掉这个游戏。

和棋需要进度计数。 没有吃子,几乎每一步都可以撤回,仅靠三次重复局面不够。计数在仅有的两种不可撤回的事件上清零:一次转化,或一步兵卒走动。

我们如何测试

现有的引擎都下不了这个棋。Pikafish 和 Fairy-Stockfish 都内置了吃子规则,而 Fairy-Stockfish 唯一的转化机制是像黑白棋那样翻转被落子包围的棋子,那是另一条规则。所以我们用 Rust 写了一个:带置换表的 alpha-beta 搜索、主要变例搜索、后期着法缩减,以及针对转化的静态搜索。它的子力价值是用逻辑回归在自对弈结果上拟合出来的,并在对抗中胜过了我们手工挑选的价值。

我们不公布拟合出的数值。早先用四分之一数据做的一次拟合中,有好几个数值后来符号反转,这样的噪声是一张子力价值表承受不了的。排序保留了下来:仕和相几乎一文不值,而这本来就可以从无需防守推出。

在测量任何东西之前,先检查了规则。下面全部 54 盘引擎对局都能在 Mistboard 的 TypeScript 规则内核中重放,1,696 个局面中的每一个都得到相同的转化和相同数量的合法着法;本页的每一个棋盘也都经过这个内核。有三个结果不取决于引擎下得多好。

测试结果
均匀随机合法着法,6,000 局先手方 54.5%,无和棋
从初始局面做证明搜索,208 亿节点13 步之内没有强制胜
当场就输的合法着法,1,696 个局面平均 28%,中位数 10%

随机对弈已经偏向先手方。6,000 局中 54.5% 比五五开高出约七个标准误,所以在双方都还下不好之前,一步先手就已经有价值。

这个证明需要谨慎,因为普通搜索做不出证明。后期着法缩减会把靠后的着法搜得更浅,所以普通搜索没找到胜着,只说明它没有处处都看到。关闭缩减和静态搜索,并在杀棋阈值上以是或否来提问,搜索就证明了 13 步之内没有强制胜。这用了 208 亿个节点,约半小时。

我们还检查了引擎变强时 78% 是否会变化。从每步 30 万节点到 200 万节点,七倍的范围内,它几乎没有变化。

仅有稳定还不够。这项测量的早期版本用六步随机开局库来让对局多样化,得到 52.7%,并且在十倍的引擎强度范围内保持不变。它稳定,是因为开局库把要测量的那一步先手花掉了:六步随机着法在两个引擎走第一步之前就把优势丢掉了。坏掉的温度计在每个房间都显示室温。78% 不用开局库,对局的多样性来自评估抖动。

一步炮定胜负

先手方赢下 78% 的引擎对局,这是从初始局面测得的,不用开局库,红黑轮流先走。随后我们单独测量了红方全部 42 个合法的第一步,诊断的样子变了。

回合红方得分回合红方得分回合红方得分
c1a30.0%h1g325.0%a4a541.7%
e1e20.0%a1a327.1%g4g543.8%
g1i30.0%b3b227.1%b3b445.8%
b3a34.2%h3h229.2%b3b750.0%
b3c38.3%b3d329.2%d1e254.2%
h1i312.5%i4i529.2%e4e554.2%
h3f316.7%b3f333.3%a1a258.3%
b3g318.8%b1a335.4%h3h760.4%
h3c320.8%c1e335.4%h3h460.4%
i1i220.8%b3e335.4%b3b670.8%
h3g322.9%c4c535.4%f1e272.9%
i1i325.0%h3e337.5%h3h579.2%
h3i325.0%h3d339.6%b3b587.5%
g1e325.0%b1c341.7%h3h691.7%
全部 42 个合法的第一步,每个以每步 30 万节点下 24 盘引擎对局。按每一对列从上往下读,得分从低到高。

最好的两步是同一个想法,把炮升到第五或第六横线:h3h6 得 91.7%,b3b5 得 87.5%。得零分的三步是两步走到棋盘边上的相(c1a3 和 g1i3),以及帅从中路上一步(e1e2)。红方第一步的价值从零到 92% 不等,所以 78% 衡量的是一个总能找到强势开局的引擎。

楚 河 漢 界Mistboard
0 / 3
  1. 初始局面,红方走棋。
  2. 1
  3. 炮沿 b 线隔着黑方自己的炮打过去,把 b10 的马变了过来。它同时威胁 b5e5:以黑方 e7 的卒为炮架,将就在后面。黑方 38 种应着中有 32 种当场就输,而 b5e5 对每一种都能取胜。

  4. 1…
  5. 黑方以同样方式回应,把 h1 的马变过去。这步看起来很合理,但它就是那 32 种之一。

  6. 2
  7. 炮隔着 e7 的卒打向 e10 的将,对局结束。

红方胜
从初始局面开始。圆圈标出每步棋转化的棋子,最后一步标出它攻击的将。

象棋的炮和目标之间需要正好一枚棋子,而黑方的初始局面免费把这枚棋子摆在了恰好的位置。这个威胁之所以存在,是因为象棋的初始局面恰好落在本尼迪克特规则能利用的地方。

引擎下的每一盘棋

最强设置下的全部 54 盘对局,每步 200 万节点,未经挑选。红方先走 36 盘,赢 33 盘;黑方先走 18 盘,赢 13 盘。先手方赢了 46 盘,输掉的那 8 盘最值得打开看看。

全部 54 盘对局,每一盘都经规则内核重放。圆圈标出每步棋转化的棋子,最后一步标出它攻击的将。用方向键逐步浏览棋盘上的对局。

饼干规则

这 42 种开局之间的差距正是这个游戏可以挽救的原因,而修补办法已经存在。饼干规则像两个孩子分蛋糕:一个切,另一个挑。红方先走第一步,然后黑方选择继续执黑,还是接手红方的局面。当黑方可以直接拿走最强的开局时,走最强的开局就没有意义了。

于是红方被推向最接近均势的着法,42 步中有四步在那里。两步是炮放弃自己的最佳位置,另外两步是棋盘上最安静的出子着法。

楚 河 漢 界Mistboard
b3b4,45.8%。炮向前一步,还没到造成破坏的第五横线。
楚 河 漢 界Mistboard
b3b7,50.0%。炮一直打进去,立刻转化,放弃了持续的威胁。
楚 河 漢 界Mistboard
d1e2,54.2%。仕走到九宫中心出子。
楚 河 漢 界Mistboard
e4e5,54.2%。中兵:唯一一步不是败着的安静出子着法。

最接近均势的四个第一步,以及每一步之后红方的得分。

限定在其中一步上,对局就会接近 50%,因为红方再也无法利用这份优势。六贯棋(Hex)在每种棋盘大小下都被证明是先手胜,却因为换边规则而被竞技性地下着。

这四个数字各来自 24 盘对局:不足以在它们之间排名,但足以说明从 0% 到 92% 的差距是真实的。用足够的样本确认其中一步能稳定在 50% 附近,是尚待完成的工作。

饼干规则修正了公平性,而没有改变尖锐程度。当场就输的着法比例是规则本身的属性,所以它不会变。比赛变得均衡,却依然尖锐;人们是否想下这样的棋,胜率回答不了。

它目前处于什么水平

它还不能作为竞技游戏上线。先手方每四盘赢三盘,任何等级分阶梯都撑不住。

不公平不等于不能下。自杀棋已被证明是先手胜,却每天都有人下,因为那个证明走的是人类找不到的变化;六贯棋则在换边规则下照样被人下。这里的不同在于深度。这个 78% 依靠的是一步一句话就能说清的棋,把炮升到第五横线,而引擎每次都能找到它。没人够得着的已证胜局只是奇闻;一个能背下来的胜法就是整个游戏。

饼干规则之外,还有两个修补办法未经测试。把将帅标记出来、给防守方一步应对的机会,可以直接削弱炮的威胁。或者改动初始局面中的中兵,因为这个威胁之所以存在,只是因为黑方的卒恰好站在炮需要炮架的位置。

红方有强制胜吗?

上面的一切都是胜率,是关于两个特定引擎的陈述。这个游戏在完美对弈下是否先手胜,其答案不取决于任何东西下得多好。我们手里的是一个下界,13 步之内没有强制胜。这排除了廉价的胜法,而引擎对局中有一半在第 28 步前就结束了。

有两件事让这个问题比看起来更难。子力守恒,所以没有残局库可建,正向搜索也没有可以会合的中点。策略窃取也用不上:棋子只会移动,从不累积,所以先手方不能随便走一步再把它丢掉。有帮助的是对局短且总能分出胜负,是一棵浅而终局尖锐的树,而这正是证明数搜索擅长的形状。

下一级是 14 步。证明可以按红方 42 个第一步拆分并几乎无损地并行运行,因为既然没有强制胜,任何一个分支都不会剪掉另一个。拆到两步深,会得到 1,740 个独立任务,足以用上一个集群。证明数搜索把精力花在证明树最窄的部分,马克·沃特金斯正是用它解决了自杀棋,而我们还没有实现它。

弱解,或者通过我们没想到的论证得到的超弱解,也会顺带解决饼干规则的问题:已被证明的先手胜正是换边规则被发明出来要应对的情形。引擎、测试工具、54 盘对局和完整的开局表都在一个代码仓库里。

核对数据学习象棋