開局:黑方有兩步棋必須找到

棋局中被強制的部分是一條四到五步長的吃子連鎖,主線上有三個分叉。兩個屬於黑方,都決定勝負。一個屬於紅方,並不決定勝負。第四個出現在黑方走出一著輸棋之後,樹的大部分都在它下面。紅方第一著是炮吃馬;兩種選擇互為映象,就稱之為 1. Cxb10。下面的棋盤裡,箭頭標出的是行棋方的每一種吃法。

分叉 A:輪到黑方楚 河 漢 界Mistboard
0 / 3

分叉 A。黑方必須吃子,有兩種走法:用車把炮吃回來,或者隔著紅方自己的 h3 炮,把另一門炮打進紅方底線。1...Rxb10 在 34 步內被強制擊敗,這一點已被證明。1...Cxh1 守得住。

1 / 4
分叉吃法最佳著法下下方終點已證明
分叉 A1... Cxh1和8262
分叉 A1... Rxb10紅方勝11
分叉 B2. Rxh1和10
分叉 B2. Cxd10和8162
分叉 C2... Cxf1紅方勝8062
分叉 C2... Kxd10和10
分叉 D3. Kxf1紅方勝10
分叉 D3. Cxf10黑方勝5844
分叉 D3. Cxa10和2118
四個分叉處的每一種吃法,其價值由連鎖的 83 個終點沿樹回推得出:在每個分叉,行棋方選擇對自己最有利的吃法。「已證明」一欄統計下方終點中有機器核驗證明的數量。

主線上有一個判斷只依賴搜尋。引擎在每著 100,000 節點下判定 2...Cxf1 會輸,在一百萬節點下也是如此,而證明器在它上面耗盡了預算。如果它確實守得住,黑方就多了一條和棋之路,棋局依然是和棋。

為什麼用車吃回會輸

證明憑證是一棵樹:紅方每一著只保留一著,黑方每一著保留所有合法應著。1...Rxb10 的那一份有 1,864 個局面。下面是它的主變。在紅方第一著自由著法處,黑方有 42 種合法應著,憑證對每一種都有應對。

楚 河 漢 界Mistboard
0 / 34
  1. 1
  2. 自然的吃回。從這裡起紅方必勝;證明憑證覆蓋 1,864 個局面。

  3. 2
  4. 3
  5. 紅方第一著自由著法是靜著:車走到 a2。黑方有 42 種合法應著,憑證對每一種都有應對。這是主變。

  6. 3…
  7. 4
  8. 車到 b2,b8 的炮此時正架在 b1 的馬上。黑方恰好只有一種合法著法。

  9. 4…
  10. 5
  11. 紅方必須吃炮。

  12. 5…
  13. 黑方必須吃車:整條 b 線都是空的。

  14. 6
  15. 一著靜著,讓黑方的車恰好只剩一種吃法:c1 的相。

  16. 6…
  17. 7
  18. 相走到 i3,進入車的射程;兩種應著,都在覆蓋之內。

  19. 8
  20. 9
  21. 10
  22. 11
  23. 12
  24. 13
  25. 14
  26. 15
  27. 16
  28. 17
  29. 紅方已無棋子,贏了。一路上黑方沒有一次吃子能夠拒絕。

證明 1...Rxb10 會輸的主變,共 34 步,關鍵步附有註釋。整棵樹在證據程式碼庫裡。

一著安靜的著法若讓對手只剩恰好一種吃法,那就是對手不得不走的著法。紅方底線的棋子變成一列隊伍,黑方的車被迫吃掉擺到面前的一切,就替紅方把這列隊伍清空。三十步之後紅方一子不剩,贏了。所以黑方唯一的著法是 1...Cxh1。

連鎖之後:雙方各圖什麼

2. Rxh1 Rxb10:輪到紅方楚 河 漢 界Mistboard2. Cxd10 Kxd10 3. Rxh1:輪到黑方楚 河 漢 界Mistboard
連鎖中存活下來的兩個終點。雙方各十四子,棋盤上無子可吃,棋局就此展開。

左邊是 1. Cxb10 Cxh1 2. Rxh1 Rxb10 之後,輪到紅方。右邊是 2. Cxd10 Kxd10 3. Rxh1 之後,輪到黑方,子力相同,只是將在 d10。引擎從這裡出發、在三種預算下的對局,顯示了中局在爭什麼。

你沒法主動丟子,只能讓對方吃掉。所以每一著都是一次奉送,真正起作用的是對手無法拒絕的奉送:一著安靜的著法,讓對手只剩恰好一種吃法。

一輛無人守護的車是負擔。在它的路徑上擺子,它就必須一個個吃掉;用車吃回之所以會輸,正是這個原因。所以雙方開局都改為送炮。在每著兩百萬節點的那一局裡,3. Cb3 給黑方的炮架到 b1 的馬上,隨後發生三次吃子,兩輛車都成了無人守護的子力。接下來是十四步被迫的吃子,雙方子力同步減少。

楚 河 漢 界Mistboard
0 / 44
  1. 1
  2. 炮隔著黑方的炮吃馬。紅方僅有的兩種合法著法就是這一著和它的映象。

  3. 1…
  4. 黑方放棄已被證明會輸的車吃回,改用另一門炮沿 h 線開火,以紅方的 h3 炮為炮架。唯一站得住的一著。

  5. 2
  6. 車吃炮。改走另一種炮吃法 2. Cxd10 同樣站得住。

  7. 2…
  8. 黑方唯一的合法著法。強制部分結束:雙方各十四子,輪到紅方,棋盤上無子可吃。

  9. 3
  10. 全域性第一著自由著法。紅方把最後一門炮放到 b3,充當黑方 b8 炮吃 b1 馬的炮架:一份黑方無法拒絕的奉送。

  11. 3…
  12. 唯一合法著法。

  13. 4
  14. 另一翼同樣的交換:車吃炮,接下來 Rxb3 將是被迫的應著。

  15. 4…
  16. 5
  17. 兩輛車如今都鬆動在底線上,除了吃子別無選擇。接下來十四步裡每輛車都只能吃子,雙方同步棄子。

  18. 5…
  19. 6
  20. 7
  21. 8
  22. 9
  23. 10
  24. 11
  25. 12
  26. 盛宴的最後一次吃子。雙方各五子:將、雙士、一象、一車。

  27. 12…
  28. 13
  29. 14
  30. 紅方扳動槓桿。相走到黑方車所在縱線上的 i3,黑方別無其他吃法:Rxi3 是被迫的。

  31. 14…
  32. 15
  33. 16
  34. 輪到車本身:Ri2,黑方必須吃掉。紅方再沒有能離開九宮的棋子了。

  35. 16…
  36. 17
  37. 仕走進車的路徑。黑方必須吃,紅方的另一隻仕必須吃回。

  38. 17…
  39. 18
  40. 紅方:帥和一仕。黑方:將、雙士、一象。棋盤上再沒有任何棋子能吃掉任何東西。

  41. 18…
  42. 19
  43. 20
  44. 21
  45. 22
  46. 局面第三次出現:重複局面成和。紅方子少卻無法送掉;黑方也無法迫使紅方吃任何東西。

引擎每著兩百萬節點的自戰對局,共 44 步。它實際是在另一翼開局的;這裡把對局映象顯示,讓縱線與上面的棋盤一致。

或者是一場緩慢的兵戰。在五百萬節點下,雙方早期都沒找到強制性的奉送,兵卒彼此走近,持續一百步,成對被吃掉,中途還搭進去一個象和一個將。

楚 河 漢 界Mistboard
0 / 131
  1. 1
  2. 2
  3. 和每盤棋一樣的四步強制著法。

  4. 3
  5. 4
  6. 5
  7. 6
  8. 雙方的車互吃對方的炮,紅方的車隨即也被吃掉:各剩十一子,棋局變成一場兵戰。

  9. 6…
  10. 7
  11. 8
  12. 紅方把兵送到 i5。黑方以 i6 的卒回應:現在紅方的兵必須吃它,黑方的車必須吃回。

  13. 8…
  14. 9
  15. 兩次被迫吃子,去掉兩個兵。這盤棋的餘下部分就是由這種交換構成的:一個兵走進另一個兵的路徑,吃子被迫發生,吃子者隨即被吃。

  16. 10
  17. 11
  18. 12
  19. 13
  20. 14
  21. 15
  22. 16
  23. 17
  24. 18
  25. 19
  26. 兵吃兵,再象吃兵。子力繼續成對消失,每一次吃子都是吃子方無法拒絕的。

  27. 20
  28. 21
  29. 22
  30. 23
  31. 24
  32. 25
  33. 26
  34. 27
  35. 28
  36. 29
  37. 30
  38. 31
  39. 32
  40. 33
  41. 34
  42. 35
  43. 36
  44. 37
  45. 38
  46. 39
  47. 40
  48. 41
  49. 42
  50. 43
  51. 44
  52. 45
  53. 黑方把象送進紅方最後一個兵的路徑,用它換得該兵落到 e8,車必須在那裡吃掉它。紅方再無兵。

  54. 45…
  55. 46
  56. 47
  57. 48
  58. 49
  59. 50
  60. 51
  61. 52
  62. 53
  63. 54
  64. 55
  65. 56
  66. 57
  67. 58
  68. 59
  69. 60
  70. 紅方把帥走進卒的路徑,黑方必須吃掉。按這些規則,這對紅方是進展;相吃回卒,棋盤上再無兵卒。

  71. 61
  72. 從這裡起,什麼都無法強迫。黑方的車停在 c 線上自己的象後面,所處線路紅方剩餘的棋子都夠不到;紅方的仕和相離不開自己的半邊;而任何一方的車都可以隨時扔掉。各剩五子,棋盤和只剩九宮棋子的那種局面一樣死。

  73. 62
  74. 63
  75. 64
  76. 65
  77. 66
  78. 局面第三次出現:重複局面成和,各剩五子,雙方來回挪動象和車。

引擎每著五百萬節點的自戰對局,共 131 步,以同樣方式映象顯示。註釋跟隨著這些兌子。

然後九宮讓它成為和棋

要取勝,你必須送掉將、兩個士和兩個象,而它們誰都離不開家。每一個都只能被走到它跟前的敵方棋子吃掉,而雙方都在設法擺脫恰恰是那些棋子。一旦雙方都沒有了車、馬、炮、兵,就再也不可能發生吃子,規則把這判為和棋。

2M 對局第 35 步:死局楚 河 漢 界Mistboard
引擎每著兩百萬節點自戰的對局,第 35 步。棋盤上再沒有任何棋子能吃掉任何東西。

兩百萬節點那一局在第 35 步到達這裡,紅方把最後幾個可出擊的棋子餵給黑方的車,隨後在第 44 步重複局面成和。兵戰以雙方各餘一車加九宮棋子收場,這個和棋可以手算驗證。黑方的車停在紅方任何棋子都夠不到的線路上,所以永遠不會被迫吃子;任何一方的車都可以隨時扔掉;而棋盤上無子可吃時任何著法都合法,於是想等的一方就來回挪士,直到無吃子步數限制終結棋局。

要取勝,你需要對手保留足夠的出擊力量來吃光你整個九宮,並且被迫動用它。那股力量在對手手裡:他們可以把它扔進你無法拒絕的吃子裡,可以擱著不動,也可以等。在每一盤引擎對局裡,三者之一總在需要時出現;而在隨機對弈中,3,000 局裡有四分之一成了僵局。

這是和棋的證據,還不是證明。每著五百萬節點的搜尋在兩個存活局面裡都沒找到勝法。我們沒有證明從連鎖可能通向的每個局面都存在出路,只是說沒有任何搜尋找到過沒有出路的局面。標題說的就是這個判斷和這套幾何結構。

能把它改成一個能下的棋嗎?

和棋源於一個事實:每方五個棋子只能被對手寧願扔掉的棋子吃掉。修補方案要麼改變這一點,要麼改變你必須送掉的東西,要麼改變僵局的價值。我們試了四種,走的是同一套裁判、掃描、證明器和自戰流程。沒有一種做出了像樣的棋。

所有僵局都判給子少的一方。這是把 FICS 的困斃規則應用到棋局停下的任何情形,它把凍結的棋盤交給子力更少的一方。隨機對弈的未決比例從 26% 降到 4%,且沒有偏向(紅方 47.9%)。引擎對弈毫無變化:引擎不知道這條規則,所以還是同樣的對局,只是判法不同,這對該規則會造就的棋毫無說明力。要正經測試,需要給 Fairy-Stockfish 打補丁,讓引擎為子數而下。這是唯一一種既保留棋的辨識度又可能奏效的修補,僵局那個開關已經在核心裡,有人想試就能試。

只需送掉將,而不是全部。Codrus 是 1844 年的祖先,目標沿縱線總是夠得到,但拋掉可出擊棋子的一方仍然永遠不會被迫吃掉對方的將。它經由同樣的兩條開局變化成和,而且更快:28 個終點,25 個負局中有 20 個已被證明,三盤自戰和棋。

保留將的王者身份。Losers 是 ICC 的版本,保留將軍與將死,被將死或只剩光將的一方獲勝。它有勝負,但方向錯了:黑方在一百萬、兩百萬和五百萬節點下都獲勝,把它 16 個終點的連鎖回推,結果也是黑方,13 個負局中有 7 個已被證明。將軍會暫停吃子義務,而在我們看過的每一條變化裡,這個先手都落到後手一方。

放九宮裡的棋子出來。這是靠取消禁閉來消除堡壘,而讓這些棋子成為象棋棋子的大部分特徵也隨之消失。我們沒有測量它;那是另一張棋盤。

我們是怎麼核驗的

裁判是一個帶有上述規則開關的象棋規則核心。它的著法生成在 209 個局面上與 Fairy-Stockfish 一致,零處分歧。每一盤裡都由引擎提議,核心判定、執行並終止棋局,所以一個悄悄按不同規則下棋的引擎會讓整輪執行中止。

棋手是 Fairy-Stockfish,透過一個變體配置檔案設定。它的評估從未針對這個目標訓練過,結果也看得出來:十倍搜尋量對一倍搜尋量在這裡只贏到 10-4 帶 6 和,而在普通象棋上是 20-0。這就是開區域性分依靠證明的原因。

證明器接收一個局面和一個論斷,比如「紅方從此處必勝」,然後構建一棵樹:勝方每一手保留一著取勝著法,負方每一手保留所有合法應著,一直下到核心判定已經結束的局面。如果這棵樹閉合,這個論斷就是關於規則的事實,與任何引擎的看法無關。它採用證明數搜尋,設有 60 步截斷,截斷計為進攻方失敗,因此證明永遠不會依賴它。每個證明都儲存為一份證明憑證,另有一個獨立的校驗器只負責把憑證對照核心重放,別的什麼都不做。

掃描:連鎖終點誰先走誰贏

核心走遍了開局連鎖的每一個分支:605 個局面,166 個終點分佈在第 4 到第 18 步之間,其中 72 個在第 14 步,而且其中 130 個終點裡至少已有一方的將不在了。撇開映象,83 個互不相同。引擎從每個終點各下一局,每著 100,000 節點。83 局中有 70 局在再走 14 到 36 步內結束,而勝者就是在終點擁有第一著自由著法的一方,70 局裡有 66 局如此。另外 13 局成了僵局,按寫下的規則算和棋。

終點所在步數誰先走終點數紅方勝黑方勝僵局
4紅方2101
5黑方1001
6 到 12交替14860
14紅方363600
15黑方5041
16紅方15816
17黑方6060
18紅方4004
83 個不同終點各一盤引擎對局,雙方都是每著 100,000 節點。

所以在連鎖內部,每一次在吃法之間的選擇,實際上都是在選擇連鎖結束時誰先走。以每著一百萬節點重跑,十一個判斷髮生了變化:六個僵局變成勝局,兩個勝局耗時更長,三個僵局仍是僵局,沒有任何勝局換邊。

掃描只找出候選,本身不能定論。它的勝局站住了:在十倍預算下沒有一個換邊,70 箇中有 63 個隨後在不依賴引擎的情況下被證明。它的僵局是較弱的證據,因為 13 個裡有 6 個在一百萬節點下變成了勝局。真正要緊的兩個僵局是存活下來的終點,它們在一百萬節點下,以及從初始陣型出發、每著最高五百萬節點的每一盤對局中,都仍是僵局。

證明

從 70 個分出勝負的終點各自出發,預算為一百萬個局面:63 個證明閉合,7 個耗盡預算,沒有一個被推翻。證明的中位規模是 19 個局面,是一條單線,防守方的每個應著都是被迫的;最大的是車吃回那一支的 1,864 個局面。校驗器 63 個全部透過。分叉表就是這些價值從 100,000 節點掃描沿連鎖回推的結果;改用一百萬節點掃描評分,在距初始陣型八步以內沒有任何價值改變。

每一盤棋,逐步回放

本文依據的每一盤棋都在下面的檢視器裡:引擎每著一百萬、兩百萬和五百萬節點的自戰對局;開局連鎖 83 個終點各一盤;20 盤階梯對局,即強引擎從隨機開局對陣弱引擎;以及 63 個證明各自的主變。檢視器先打開 2M 那盤。列表裡的任何一盤都可以選。

全部 169 盤棋,每一盤都經規則內核重放。方向鍵可以逐步走棋盤上的這一盤。

我們發佈的是什麼,而不是一個對局頁面

上面的一切都在一個程式碼庫裡:規則核心,三段 Fairy-Stockfish 變體配置,開局連鎖的全部 166 個終點,每個終點在每種預算下各一盤引擎對局,每一份證明憑證,以及可以直接從該目錄開啟的對局瀏覽器。npm run verify 幾秒鐘內就把每一份憑證對照規則重放一遍,並報告 63、63、20 和 7 項有效;README 裡有四條命令,配合一個 Fairy-Stockfish 可執行檔案即可復現掃描與證明。

如果你能給出第三條存活的開局、任何一份憑證裡的防守,或者從上面的局面出發任何一方的勝法,請去那裡提一個 issue。本頁會如實寫明。

親自檢驗這些證明學習象棋