反棋(自殺棋)是改了兩條規則的國際象棋:能吃子就必須吃;把自己所有棋子都送掉的一方獲勝;王只是普通棋子。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。我想看到它,這篇文章也會如實寫明。