规则
走一枚棋子。它从落点攻击到的每一个敌方棋子都会加入你方。棋子永远不会被吃掉,所以 32 枚棋子整局都留在棋盘上;一步攻击到对方将帅的棋即获胜。
停在原地的攻击不起作用。只有走动的那枚棋子会转化对方,所以已经瞄着某枚棋子的车必须再走一步才能拿下它。威胁只能靠走棋来制造。
它对象棋做了什么
永远没有残局。 没有兑子,局面不会简化,残局库也不可能存在,因为子力从不减少。象棋的残局理论,也就是象棋理论的大部分,完全用不上。
炮永远不会变弱。 象棋的炮需要炮架才能吃子,所以在象棋里它会随着棋盘变空而变弱。这里棋盘从不变空,炮在对局后段和第 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 个合法的第一步,诊断的样子变了。
| 回合 | 红方得分 | 回合 | 红方得分 | 回合 | 红方得分 |
|---|---|---|---|---|---|
| c1a3 | 0.0% | h1g3 | 25.0% | a4a5 | 41.7% |
| e1e2 | 0.0% | a1a3 | 27.1% | g4g5 | 43.8% |
| g1i3 | 0.0% | b3b2 | 27.1% | b3b4 | 45.8% |
| b3a3 | 4.2% | h3h2 | 29.2% | b3b7 | 50.0% |
| b3c3 | 8.3% | b3d3 | 29.2% | d1e2 | 54.2% |
| h1i3 | 12.5% | i4i5 | 29.2% | e4e5 | 54.2% |
| h3f3 | 16.7% | b3f3 | 33.3% | a1a2 | 58.3% |
| b3g3 | 18.8% | b1a3 | 35.4% | h3h7 | 60.4% |
| h3c3 | 20.8% | c1e3 | 35.4% | h3h4 | 60.4% |
| i1i2 | 20.8% | b3e3 | 35.4% | b3b6 | 70.8% |
| h3g3 | 22.9% | c4c5 | 35.4% | f1e2 | 72.9% |
| i1i3 | 25.0% | h3e3 | 37.5% | h3h5 | 79.2% |
| h3i3 | 25.0% | h3d3 | 39.6% | b3b5 | 87.5% |
| g1e3 | 25.0% | b1c3 | 41.7% | h3h6 | 91.7% |
最好的两步是同一个想法,把炮升到第五或第六横线:h3h6 得 91.7%,b3b5 得 87.5%。得零分的三步是两步走到棋盘边上的相(c1a3 和 g1i3),以及帅从中路上一步(e1e2)。红方第一步的价值从零到 92% 不等,所以 78% 衡量的是一个总能找到强势开局的引擎。
象棋的炮和目标之间需要正好一枚棋子,而黑方的初始局面免费把这枚棋子摆在了恰好的位置。这个威胁之所以存在,是因为象棋的初始局面恰好落在本尼迪克特规则能利用的地方。
引擎下的每一盘棋
最强设置下的全部 54 盘对局,每步 200 万节点,未经挑选。红方先走 36 盘,赢 33 盘;黑方先走 18 盘,赢 13 盘。先手方赢了 46 盘,输掉的那 8 盘最值得打开看看。
饼干规则
这 42 种开局之间的差距正是这个游戏可以挽救的原因,而修补办法已经存在。饼干规则像两个孩子分蛋糕:一个切,另一个挑。红方先走第一步,然后黑方选择继续执黑,还是接手红方的局面。当黑方可以直接拿走最强的开局时,走最强的开局就没有意义了。
于是红方被推向最接近均势的着法,42 步中有四步在那里。两步是炮放弃自己的最佳位置,另外两步是棋盘上最安静的出子着法。
最接近均势的四个第一步,以及每一步之后红方的得分。
限定在其中一步上,对局就会接近 50%,因为红方再也无法利用这份优势。六贯棋(Hex)在每种棋盘大小下都被证明是先手胜,却因为换边规则而被竞技性地下着。
这四个数字各来自 24 盘对局:不足以在它们之间排名,但足以说明从 0% 到 92% 的差距是真实的。用足够的样本确认其中一步能稳定在 50% 附近,是尚待完成的工作。
饼干规则修正了公平性,而没有改变尖锐程度。当场就输的着法比例是规则本身的属性,所以它不会变。比赛变得均衡,却依然尖锐;人们是否想下这样的棋,胜率回答不了。
它目前处于什么水平
它还不能作为竞技游戏上线。先手方每四盘赢三盘,任何等级分阶梯都撑不住。
不公平不等于不能下。自杀棋已被证明是先手胜,却每天都有人下,因为那个证明走的是人类找不到的变化;六贯棋则在换边规则下照样被人下。这里的不同在于深度。这个 78% 依靠的是一步一句话就能说清的棋,把炮升到第五横线,而引擎每次都能找到它。没人够得着的已证胜局只是奇闻;一个能背下来的胜法就是整个游戏。
饼干规则之外,还有两个修补办法未经测试。把将帅标记出来、给防守方一步应对的机会,可以直接削弱炮的威胁。或者改动初始局面中的中兵,因为这个威胁之所以存在,只是因为黑方的卒恰好站在炮需要炮架的位置。
红方有强制胜吗?
上面的一切都是胜率,是关于两个特定引擎的陈述。这个游戏在完美对弈下是否先手胜,其答案不取决于任何东西下得多好。我们手里的是一个下界,13 步之内没有强制胜。这排除了廉价的胜法,而引擎对局中有一半在第 28 步前就结束了。
有两件事让这个问题比看起来更难。子力守恒,所以没有残局库可建,正向搜索也没有可以会合的中点。策略窃取也用不上:棋子只会移动,从不累积,所以先手方不能随便走一步再把它丢掉。有帮助的是对局短且总能分出胜负,是一棵浅而终局尖锐的树,而这正是证明数搜索擅长的形状。
下一级是 14 步。证明可以按红方 42 个第一步拆分并几乎无损地并行运行,因为既然没有强制胜,任何一个分支都不会剪掉另一个。拆到两步深,会得到 1,740 个独立任务,足以用上一个集群。证明数搜索把精力花在证明树最窄的部分,马克·沃特金斯正是用它解决了自杀棋,而我们还没有实现它。
弱解,或者通过我们没想到的论证得到的超弱解,也会顺带解决饼干规则的问题:已被证明的先手胜正是换边规则被发明出来要应对的情形。引擎、测试工具、54 盘对局和完整的开局表都在一个代码仓库里。