你復盤時可能遇過這種局面:棋盤很空,讀起來卻很慢;另一局已經擠成一團,關鍵點反而只剩兩三個。強引擎面對的也是同一件事。Rapfi 的論文把一個安靜的問題推到台前:棋力不只來自更大的網路,也來自對棋盤上反覆出現的局部形狀處理得更輕、更準。
快,常常從小範圍開始
五子棋的棋盤看起來是一個整體,計算時卻充滿局部。一個活三附近的四五個交叉點,會比遠處十幾個空點更急;一個衝四旁邊的防點,會直接改變下一手的生死。人類讀棋會自然縮小視野,引擎也在尋找類似的節省方式。
Rapfi 論文討論的方向,是把局部棋形編碼成更容易重複利用的形式。論文稱這種做法為 pattern codebook,並結合增量更新,減少每一步之後從頭計算的負擔;相關實驗與系統說明見 Rapfi 論文。它沒有把棋盤看粗;重點在於先整理那些經常重複的形狀。
局部形狀為什麼會反覆出現
五子棋的勝負條件很乾淨:連成五子。可是乾淨的規則會製造出大量相似的小形狀。活三、眠三、衝四、活四,這些名字背後都是局部空點、我方棋子、對方棋子的排列關係。
以活三為例。你在一條線上看到三顆連續的我方棋子,兩端都還空著,第一反應通常是檢查兩頭的延伸點。若旁邊還有一條斜線也正在成形,這個局部就不再只是一個三,它可能指向雙三、連續威脅,甚至禁手判斷。
這解釋了為什麼局部形狀值得被單獨看待。棋盤上許多點沒有同等價值,價值來自鄰近棋子的組合。把這些組合辨識得快,搜尋就少走很多空路。
速度藏在重複的形狀裡
增量更新像復盤時只改一處
落下一子後,整張棋盤都變了嗎?規則上變了,局部關係上只變了一圈。新子所在的橫、豎、兩條斜線會改變,遠處的形狀仍舊保持原樣。
增量更新抓住的就是這個事實。每下一手,只更新受影響的局部編碼和相關評估,保留其餘部分。對引擎設計者來說,這是一種很樸素的節制:少碰沒有變化的東西。
威脅空間搜尋早就提醒過我們
這種局部意識並不新。1993 年的 Victoria 程式在論文 Go-Moku Solved by New Search Techniques 中,把威脅空間搜尋和證明數搜尋結合起來,給出了自由規則五子棋的求解結果。它關心的核心也是威脅:哪些手會迫使對方回應,哪些分支可以暫時放下。
從 Victoria 到 Rapfi,技術材料換了很多,棋盤上的壓力點沒有消失。衝四要應,活四更急,雙威脅會壓縮選擇。引擎越強,越需要把這種強制性讀得穩定。
規則會改變形狀的重量
同一個棋形,在不同規則下可能有不同含義。連珠規則使用 15×15 棋盤,在交叉點落子,並對黑方的長連、雙三、雙四等設有禁手;基礎說明可見 Renju International Federation 規則頁。這會直接影響引擎對局部形狀的判斷。
舉個常見場景:黑棋看似能造出兩個活三,但在禁手規則下,這手可能不能下。對人來說,這是「漂亮手變成壞手」的瞬間;對引擎來說,這是局部編碼必須攜帶的規則語義。只辨識形狀還不夠,還要知道它在目前規則裡是否可用。
玩家能從引擎學到什麼
玩家當然不會在腦中維護碼本。可引擎的做法能提醒我們一件實用的小事:讀棋先讀變化處。上一手落在哪裡,哪四條線被改寫,哪裡多了一個缺口,哪裡少了一個氣口。
這比漫無目的地掃全盤更可靠。尤其在中盤,棋子密集,人的注意力很容易被遠處的形狀吸走。先沿最後一手做局部檢查,再把結果放回全盤,你會少漏一些直接威脅。
設計棋盤介面時也一樣。標記、提示、復盤工具若能圍繞最後一手附近展開,會更貼近真實讀棋路徑。好的輔助不必喧鬧,只要把剛剛改變的地方交代清楚。
先讀變化處,再讀全盤