鬥獸棋:古典搜尋勝過學習式評估
我打造了 MistyJungle,一個用 Rust 寫的古典鬥獸棋引擎,棋盤為 7×9,這個遊戲通常被稱為 Jungle 或 Animal Chess。你可以 在 Mistboard 上與 MistyJungle 對戰。它使用 alpha-beta 搜尋、手工評估、重複局面處理,而對戰版本中沒有任何神經網路。
成果範圍不大,但確實存在。對上我能執行的最強開源引擎,200 局中取得 W11-L2-D187,在一個偏和棋的遊戲裡約為 +16 Elo,而它的四子殘局著法與精確殘局庫一致,沒有任何勝/和/負的錯誤。我原本預期會有幫助的兩項升級,也就是學習式評估與搜尋葉節點的殘局庫,都沒有效果。是古典搜尋完成了工作。
我做了什麼
一個獨立的 Rust 引擎,帶有小型的 UCI 風格協定,可從命令列使用,也可透過 PyO3 從 Python 使用。強度由節點預算決定,而不是時鐘,所以同一個局面在任何機器上都會回傳同樣的著法。
技術堆疊很常規:帶迭代加深的 negamax alpha-beta、Zobrist 置換表、對吃子與進獸穴的靜態搜尋,以及搭配 PVS 與後期著法削減的 killer/history 著法排序,底下是評估子力、獸穴競速、陷阱、水域與機動性的手工評估。這些排序與剪枝的打磨,在固定節點預算下實測價值 +49 Elo。
在學習式修正能帶來任何東西之前,評估本身必須先精確。鬥獸棋子力權重很重,卻充滿尖銳的例外:鼠能制象、落入陷阱的棋子失去等級、踏進獸穴一步就結束棋局。
規格
雙方各有八隻動物在 7×9 的棋盤上,踏進對手獸穴或吃掉對方所有棋子即獲勝。規則因地區而異,所以確切的規則集很重要。我採用 2026 年 6 月版的 Mistboard/維基百科規則,其中狗高於狼(有些來源把兩者互換)。
吃子等級,由強到弱

象
獅
虎
豹
狼
狗
貓
鼠每種動物可以吃掉右邊的動物。鼠另外還能吃象。位於對手陷阱中的棋子等級視為零。
除了單純依等級吃子之外,還有三條規則賦予這個遊戲戰術性:
- 鼠能吃象,但只限陸上。最弱的棋子能吃掉最強的棋子。不過吃子不能跨越岸邊,所以游進水中的鼠除了另一隻鼠之外誰都吃不到。
- 獅與虎可以跳河。只有鼠能進入水域。大型貓科動物則可整條河跳到對岸,獅可橫向或縱向跳,虎只能縱向跳,除非有鼠待在水中阻擋跳躍。
- 落入陷阱的棋子失去等級。每個獸穴周圍的三格是陷阱。站在其中的敵方棋子等級降為零,因此任何棋子,甚至是鼠,都能吃掉它。
完整規則與可下的棋盤:mistboard.com/rules/jungle。
結果
在一個強引擎多半互相和棋的遊戲裡,取得了小幅優勢:
| 測試 | 結果 |
|---|---|
| 開源基準對局,200 局 | W11-L2-D187,約 +16 Elo |
| 搜尋打磨(排序、PVS、LMR) | +49 Elo,成對自我對戰,p = 0.008 |
| 四子殘局庫檢驗 | 779/800 相符,0 個勝和負矛盾 |
| 五子與六子 | 對上深 8 倍的搜尋達 >99%(代理指標,非證明) |
| 搜尋葉節點的殘局庫 | W37-L40-D3,約 -13 Elo |
| 殘差式神經評估 | 最佳約 -70 Elo |
那 +49 是最難測的一項。兩個實力相當的鬥獸棋引擎和棋太多,無法用勝率門檻判定,所以我採用成對、換邊的自我對戰(每個開局兩邊都下一次,新搜尋對舊搜尋),並對有勝負的對局做符號檢定。
資料
殘局與求解進度現況
小型殘局可以用逆向分析攻破,而它們是絕佳的評判者。Van Rijn 與 Vis 於 2013 年在萊頓解出四子,Bohrweg 在 2016 年達到七子(採用萊頓慣例,狗與狼互換)。我的引擎在 800 個局面中有 779 個與精確的四子著法相符,沒有任何勝和負矛盾,並在五子與六子時與深 8 倍的搜尋一致度超過 99%。
那個七子資料庫就是前沿,而再往上的牆是儲存空間,不是求解技術。問題出在棋盤:63 格對上翻棋鬥獸棋的 16 格,因此每多一個棋子就有約 60 個空格可站,而不是十來個,各層級的大小成長速度約快五倍。五子的翻棋鬥獸棋在我的筆電上只要 2.8 GB;五子的鬥獸棋則約需 7 TB。八子以上,也就是開局子力的一半,作為資料庫是遙不可及的,而完整十六子遊戲也沒有人做出前向證明。鬥獸棋已解到七子,之上仍未解決,而且很可能會維持這樣。
在搜尋葉節點載入殘局庫對棋力同樣沒有幫助(約 -13 Elo):在能塞得下的規模,搜尋本來就找得到答案;而真正會有幫助的規模則無法交付。翻棋鬥獸棋那次建置留下一個警示,同樣的實驗一開始讀起來是零效果,後來卻發現藏著一個錯誤:那些表只存勝/和/負而沒有距離,而只有勝和負的葉節點會讓引擎永遠守著已勝的殘局卻不把它下完,因為每個獲勝著法評分都一樣。把將死距離加進表中修好了那邊的收官。我的鬥獸棋葉節點探測同樣只有勝和負,所以那 -13 有一部分可能是同樣的效應,而不是殘局庫在葉節點沒用。這點未經測試;無論如何,交付的古典引擎都不含這個探測。
學習式評估
這一項卡在資料上,不是架構。一個殘差網路(手工評分加上有界的修正)隨著我修正標籤,從 -470 Elo 爬到約 -70 Elo,但始終沒贏過手工評估。標籤最弱的地方,正好就是網路最需要幫助的地方:和棋偏多的自我對戰對子力變化取樣不足,精確的殘局庫標籤只涵蓋小型殘局,而搜尋分數標籤大多只是教網路模仿它已經有的搜尋。
AlphaZero
仍是未完成的工作。我沒有跑完整的鬥獸棋 AZ 攀升。相鄰的暗棋 AZ 風險驗證未通過門檻,但那是不同的遊戲,並不能推翻 AZ 在鬥獸棋上的可行性,鬥獸棋其實是更友善的環境:確定性、完全資訊,沒有機率節點的揭示。我把它擱下,是因為便宜的那一階是負面結果,而古典引擎已經打贏了基準。
對局範例
這場比賽大多是和棋,但有勝負的對局顯示出優勢的形狀:先是獸穴壓力,子力其次。這些重播從接近轉化的地方開始,想看開局請往左拖。用 Tab 鍵切到棋盤,再用左右方向鍵逐著瀏覽。
MistyJungle(黑方)建立子力領先,最後以獅進入紅方獸穴收官:
另一局黑方獲勝,是較短的擠壓,在陷阱附近交換後最後一枚棋子抵達 d1:
一局紅方獲勝,顯示為什麼不能只數子力:MistyJungle 損失子力,卻贏得獸穴競速:
存下來最長的一勝,紅方磨了 283 著才抵達獸穴:
引擎每著 8M 節點的自我對戰,約每著五秒:一場長時間的均勢鬥爭,紅方守著一子優勢達四十著,然後轉化並把獅走進黑方獸穴:
更戲劇化的一局,同樣是 8M 節點的鏡像對局:紅方讓黑方保有象、獅、虎,子力落後十六點,卻仍然獲勝,靠的是在子力差距發揮作用之前先把鼠送進獸穴。這最清楚地說明了引擎實際在最佳化什麼:
結論
MistyJungle 是一個古典搜尋引擎,對我能執行的最強開源引擎擁有小幅、已實測的優勢。真正提升棋力的工作並不光鮮:正確的規則、固定預算的量測、換邊測試、搜尋打磨,以及殘局驗證。殘局庫是好的評判者,但在葉節點沒有幫助;神經網路的第一階輸給手工評估;而真正的 AlphaZero 攀升仍是未完成的工作。
資源:
- 在 Mistboard 上與 MistyJungle 對戰,或閱讀規則。
- misty-jungle:引擎本體,以 Rust 撰寫。
- Layheng-Hok/Jungle-Chess:我用作固定基準的開源引擎。
- Bagheera:萊頓的閉源引擎,以及我用來評分的殘局庫。
- 引擎系列更多內容:打造一個暗棋引擎,在中國暗棋上採用同樣的量測紀律。