一個帶精確殘局的搜尋引擎
MistyJungleFlip 是 alpha-beta 搜尋,配手工評估函式,沒有神經網路:評估值由子力加機動性構成,另有一個小小的厭和項。棋力由節點預算而非時鐘決定,因此同一局面在任何機器上都回傳同一著法,測出的差距屬於引擎而不是硬體。
翻棋是機會節點。它的價值是所有仍蓋著的動物的平均值,並用 star-minimax,即機會節點版的 alpha-beta 進行剪枝。殘局則來自精確殘局庫,從每個終局局面往回推解出。每個條目儲存雙方最佳著法下的結果,以及到達該結果的距離。
凡有精確答案之處,都拿來核對
自我對弈只能測出兩個版本哪個更強,測不出它們是否下得好:同一引擎的兩個副本共享同樣的盲點。所以著法品質改為對照殘局庫來評分。在最多五子的殘局中,引擎選出最優著法的比例為 99% 到 100%;失誤都是搜尋深度問題,更深的搜尋就解決了。基於殘局庫建構的前向求解器能涵蓋仍有棋子蓋著的五子和六子中局;在其中 200 個局面上,引擎每次都走出了最優著法。
這種涵蓋到精確計算的邊界為止,也就是接近終局處。翻棋發生的開局階段太大,無法求解,所以這裡的一切都沒有驗證引擎的開局水準。
512 倍的搜尋量,大約只值 242 Elo
為了在沒有精確答案的情況下衡量開局,四個副本分別每著搜尋 1k、8k、64k 和 512k 節點,進行成對換色的循環賽,每個配對 120 局。擬合出的等級分為 +0、+89、+153 和 +242。每 8 倍的台階值 64 到 89 Elo,且在高端趨於平坦:320k 到 640k 節點只值 6 Elo。在國際象棋裡,512 倍的算力值好幾百分。
爆冷比等級分所暗示的更常見。搜尋量多 8 倍的引擎會輸掉 37% 到 40% 的對局;多 512 倍的輸掉 23%。翻棋自身決定的對局足夠多,更多搜尋也補不上這個差距。
唯一的大台階在最底部。1k 節點的搜尋約 99% 地戰勝隨機走子(各檔位共 800 局中隨機方 0 勝),差距接近 850 Elo。從隨機到完美的距離裡,約 80% 就在這一步上,即從隨便走子到開始搜尋。調評估函式毫無作用:更好的子力價值、鼠與象的專項、厭和項,在成對自我對弈中全都沒有變化。
完美對完美是和棋
足夠小的版本可以徹底解出。兩子和四子的版本,開局時所有棋子都蓋著,按完整規則下到終局,在雙方最佳著法下都是和棋:兩個完美棋手無法戰勝彼此。哪怕從開局解一個六子遊戲,也已超過 4000 萬個不同局面,正是這道牆讓十六子的完整遊戲無法企及,所以完整遊戲未被證明。
這仍能給那 23% 定位。完美對完美是和棋。完美對遠弱的棋手幾乎必勝:隨機走子方 800 局全敗。兩個接近的棋手處在中間,差距落在變異數之內,由翻棋來決定。
殘局庫能走多遠
這些表涵蓋每個子數下所有完全翻開的局面,不計 40 個半回合的無進展規則。
| 子數 | 局面數 | 最長必勝 | 建構 |
|---|---|---|---|
| 2 | 28,800 | 9 著 | 瞬間 |
| 3 | 190 萬 | 21 著 | 2 秒 |
| 4 | 7900 萬 | 41 著 | 200 秒 |
| 5 | 23 億 | 63 著 | 筆電上 4 小時,2.8 GB |
| 6 | 460 億 | 未建構 | 數天,約 140 GB 記憶體 |
六子表可以在租用的伺服器上建構,但毫無增益:五子的涵蓋已經能給每一個進入表中的殘局評分。再往前,完整求解就意味著要解開局,而開局是一棵翻棋樹:十六個不同棋子以隨機順序翻開,可達狀態在 10¹¹ 量級以上。
最初的表裡沒有距離這一欄。它們只存勝、和、負,這足以給著法評分,卻不足以收官。在一盤自我對弈中,引擎有一虎一鼠對孤象,按表是必勝(鼠三著內困住象,因為象不能吃鼠)。連續八回合,它走出按表評為最優的著法,卻毫無進展,因為每一步取勝著法得分相同,直到重複規則判為和棋。存入距離後,3 著取勝優於 9 著取勝:引擎選最短的必勝路線,並把必敗局面盡量拖長,那個殘局以鼠三著吃象告終。國際象棋的殘局庫,例如 Syzygy,附帶距離也是同樣的原因。
棋力體現在平均值上,而不在單局上
翻翻棋裡棋力是真實存在的:242 Elo 的階梯是真實差距,在長期對抗中更強的引擎會贏。但發牌和翻棋決定了任一局中相當大的一部分,所以哪怕強得多的棋手也常常落敗,一局結果幾乎說明不了誰更強。還缺的測量是對強人類棋手的等級分,這是唯一不依賴引擎或其求解器的檢驗。
本站的對局覆盤把每一次翻子拆成決定和運氣,讓你看清自己的對局裡哪部分是哪一種。規則頁上的二十盤引擎對局是電腦自我對弈,引擎原始碼在 GitHub 上。