規則
走一枚棋子。它從落點攻擊到的每一個敵方棋子都會加入你方。棋子永遠不會被喫掉,所以 32 枚棋子整局都留在棋盤上;一步攻擊到對方將帥的棋即獲勝。
停在原地的攻擊不起作用。只有走動的那枚棋子會轉化對方,所以已經瞄着某枚棋子的車必須再走一步才能拿下它。威脅只能靠走棋來製造。
它對象棋做了什麼
永遠沒有殘局。 沒有兌子,局面不會簡化,殘局庫也不可能存在,因爲子力從不減少。象棋的殘局理論,也就是象棋理論的大部分,完全用不上。
炮永遠不會變弱。 象棋的炮需要炮架才能喫子,所以在象棋裏它會隨着棋盤變空而變弱。這裏棋盤從不變空,炮在對局後段和第 3 步時一樣危險。
仕和相什麼也守不住。 它們存在是爲了防喫子,而這裏沒有喫子。它們仍能擋住線路、給炮當炮架,但它們被設計出來要做的事都沒有了。
對局很短,沒有人和棋。 下面 54 盤引擎對局中,一半在第 28 步前結束。沒有一盤是和棋,6,000 盤均勻隨機合法着法的對局也沒有一盤和棋。沒有子力可兌,也沒有殘局可磨,每一盤都會分出勝負。
約 28% 的合法着法當場就輸。 這是引擎對局中 1,696 個局面的平均值。中位局面有 10% 的着法會輸,平均值是由少數非常尖銳的局面拉高的。這個比例從對局前五分之一的 24% 升到最後五分之一的 37%,所以不存在可以安心出子的平靜開局階段。
設計:四個決定
將帥仍然不能照面。 象棋禁止兩個將帥在同一條直線上中間無子相隔,我們保留了這條規則。另一種做法是把白臉將變成勝利條件,但它行不通:只有走動的棋子纔會轉化,所以打開這條線並不能取勝,結果將帥相對而立,對局卻繼續,直到有人把將帥沿着這條線挪一步去領取勝利。
保留這條禁令沒有代價,還帶來了象棋沒有的東西。被釘在將帥線上的棋子無法被移走,因爲這裏沒有任何東西能移走棋子;轉化它也不能解開牽制,因爲轉化是原地變色。你可以贏得這枚棋子,卻仍然動不了它,直到一方的將帥離開這條線。
仕和相受它們所在的區域約束,不論歸誰所有。 被轉化的仕站在敵方九宮裏。如果受原主人的九宮約束,它會永遠凍結在那裏;受它所在的九宮約束,它就能繼續行棋,從內部發動攻擊。從初始局面看兩種理解是一樣的,因爲每個仕都從自己的九宮出發。
兵卒受其主人約束。 兵卒的前進方向必須跟隨它現在的主人,否則被轉化的兵卒會永遠背離新的陣營前進。把這兩條規則弄反,會悄無聲息地毀掉這個遊戲。
和棋需要進度計數。 沒有喫子,幾乎每一步都可以撤回,僅靠三次重複局面不夠。計數在僅有的兩種不可撤回的事件上清零:一次轉化,或一步兵卒走動。
我們如何測試
現有的引擎都下不了這個棋。Pikafish 和 Fairy-Stockfish 都內置了喫子規則,而 Fairy-Stockfish 唯一的轉化機制是像黑白棋那樣翻轉被落子包圍的棋子,那是另一條規則。所以我們用 Rust 寫了一個:帶置換表的 alpha-beta 搜索、主要變例搜索、後期着法縮減,以及針對轉化的靜態搜索。它的子力價值是用邏輯迴歸在自對弈結果上擬合出來的,並在對抗中勝過了我們手工挑選的價值。
我們不公佈擬合出的數值。早先用四分之一數據做的一次擬閤中,有好幾個數值後來符號反轉,這樣的噪聲是一張子力價值表承受不了的。排序保留了下來:仕和相幾乎一文不值,而這本來就可以從無需防守推出。
在測量任何東西之前,先檢查了規則。下面全部 54 盤引擎對局都能在 Mistboard 的 TypeScript 規則內核中重放,1,696 個局面中的每一個都得到相同的轉化和相同數量的合法着法;本頁的每一個棋盤也都經過這個內核。有三個結果不取決於引擎下得多好。
| 測試 | 結果 |
|---|---|
| 均勻隨機合法着法,6,000 局 | 先手方 54.5%,無和棋 |
| 從初始局面做證明搜索,208 億節點 | 13 步之內沒有強制勝 |
| 當場就輸的合法着法,1,696 個局面 | 平均 28%,中位數 10% |
隨機對弈已經偏向先手方。6,000 局中 54.5% 比五五開高出約七個標準誤,所以在雙方都還下不好之前,一步先手就已經有價值。
這個證明需要謹慎,因爲普通搜索做不出證明。後期着法縮減會把靠後的着法搜得更淺,所以普通搜索沒找到勝着,只說明它沒有處處都看到。關閉縮減和靜態搜索,並在殺棋閾值上以是或否來提問,搜索就證明了 13 步之內沒有強制勝。這用了 208 億個節點,約半小時。
我們還檢查了引擎變強時 78% 是否會變化。從每步 30 萬節點到 200 萬節點,七倍的範圍內,它幾乎沒有變化。
僅有穩定還不夠。這項測量的早期版本用六步隨機開局庫來讓對局多樣化,得到 52.7%,並且在十倍的引擎強度範圍內保持不變。它穩定,是因爲開局庫把要測量的那一步先手花掉了:六步隨機着法在兩個引擎走第一步之前就把優勢丟掉了。壞掉的溫度計在每個房間都顯示室溫。78% 不用開局庫,對局的多樣性來自評估抖動。
一步炮定勝負
先手方贏下 78% 的引擎對局,這是從初始局面測得的,不用開局庫,紅黑輪流先走。隨後我們單獨測量了紅方全部 42 個合法的第一步,診斷的樣子變了。
| 回合 | 紅方得分 | 回合 | 紅方得分 | 回合 | 紅方得分 |
|---|---|---|---|---|---|
| c1a3 | 0.0% | h1g3 | 25.0% | a4a5 | 41.7% |
| e1e2 | 0.0% | a1a3 | 27.1% | g4g5 | 43.8% |
| g1i3 | 0.0% | b3b2 | 27.1% | b3b4 | 45.8% |
| b3a3 | 4.2% | h3h2 | 29.2% | b3b7 | 50.0% |
| b3c3 | 8.3% | b3d3 | 29.2% | d1e2 | 54.2% |
| h1i3 | 12.5% | i4i5 | 29.2% | e4e5 | 54.2% |
| h3f3 | 16.7% | b3f3 | 33.3% | a1a2 | 58.3% |
| b3g3 | 18.8% | b1a3 | 35.4% | h3h7 | 60.4% |
| h3c3 | 20.8% | c1e3 | 35.4% | h3h4 | 60.4% |
| i1i2 | 20.8% | b3e3 | 35.4% | b3b6 | 70.8% |
| h3g3 | 22.9% | c4c5 | 35.4% | f1e2 | 72.9% |
| i1i3 | 25.0% | h3e3 | 37.5% | h3h5 | 79.2% |
| h3i3 | 25.0% | h3d3 | 39.6% | b3b5 | 87.5% |
| g1e3 | 25.0% | b1c3 | 41.7% | h3h6 | 91.7% |
最好的兩步是同一個想法,把炮升到第五或第六橫線:h3h6 得 91.7%,b3b5 得 87.5%。得零分的三步是兩步走到棋盤邊上的相(c1a3 和 g1i3),以及帥從中路上一步(e1e2)。紅方第一步的價值從零到 92% 不等,所以 78% 衡量的是一個總能找到強勢開局的引擎。
象棋的炮和目標之間需要正好一枚棋子,而黑方的初始局面免費把這枚棋子擺在了恰好的位置。這個威脅之所以存在,是因爲象棋的初始局面恰好落在本尼迪克特規則能利用的地方。
引擎下的每一盤棋
最強設置下的全部 54 盤對局,每步 200 萬節點,未經挑選。紅方先走 36 盤,贏 33 盤;黑方先走 18 盤,贏 13 盤。先手方贏了 46 盤,輸掉的那 8 盤最值得打開看看。
餅乾規則
這 42 種開局之間的差距正是這個遊戲可以挽救的原因,而修補辦法已經存在。餅乾規則像兩個孩子分蛋糕:一個切,另一個挑。紅方先走第一步,然後黑方選擇繼續執黑,還是接手紅方的局面。當黑方可以直接拿走最強的開局時,走最強的開局就沒有意義了。
於是紅方被推向最接近均勢的着法,42 步中有四步在那裏。兩步是炮放棄自己的最佳位置,另外兩步是棋盤上最安靜的出子着法。
最接近均勢的四個第一步,以及每一步之後紅方的得分。
限定在其中一步上,對局就會接近 50%,因爲紅方再也無法利用這份優勢。六貫棋(Hex)在每種棋盤大小下都被證明是先手勝,卻因爲換邊規則而被競技性地下着。
這四個數字各來自 24 盤對局:不足以在它們之間排名,但足以說明從 0% 到 92% 的差距是真實的。用足夠的樣本確認其中一步能穩定在 50% 附近,是尚待完成的工作。
餅乾規則修正了公平性,而沒有改變尖銳程度。當場就輸的着法比例是規則本身的屬性,所以它不會變。比賽變得均衡,卻依然尖銳;人們是否想下這樣的棋,勝率回答不了。
它目前處於什麼水準
它還不能作爲競技遊戲上線。先手方每四盤贏三盤,任何等級分階梯都撐不住。
不公平不等於不能下。自殺棋已被證明是先手勝,卻每天都有人下,因爲那個證明走的是人類找不到的變化;六貫棋則在換邊規則下照樣被人下。這裏的不同在於深度。這個 78% 依靠的是一步一句話就能說清的棋,把炮升到第五橫線,而引擎每次都能找到它。沒人夠得着的已證勝局只是奇聞;一個能背下來的勝法就是整個遊戲。
餅乾規則之外,還有兩個修補辦法未經測試。把將帥標記出來、給防守方一步應對的機會,可以直接削弱炮的威脅。或者改動初始局面中的中兵,因爲這個威脅之所以存在,只是因爲黑方的卒恰好站在炮需要炮架的位置。
紅方有強制勝嗎?
上面的一切都是勝率,是關於兩個特定引擎的陳述。這個遊戲在完美對弈下是否先手勝,其答案不取決於任何東西下得多好。我們手裏的是一個下界,13 步之內沒有強制勝。這排除了廉價的勝法,而引擎對局中有一半在第 28 步前就結束了。
有兩件事讓這個問題比看起來更難。子力守恆,所以沒有殘局庫可建,正向搜索也沒有可以會合的中點。策略竊取也用不上:棋子只會移動,從不累積,所以先手方不能隨便走一步再把它丟掉。有幫助的是對局短且總能分出勝負,是一棵淺而終局尖銳的樹,而這正是證明數搜索擅長的形狀。
下一級是 14 步。證明可以按紅方 42 個第一步拆分並幾乎無損地並行運行,因爲既然沒有強制勝,任何一個分支都不會剪掉另一個。拆到兩步深,會得到 1,740 個獨立任務,足以用上一個集羣。證明數搜索把精力花在證明樹最窄的部分,馬克·沃特金斯正是用它解決了自殺棋,而我們還沒有實現它。
弱解,或者通過我們沒想到的論證得到的超弱解,也會順帶解決餅乾規則的問題:已被證明的先手勝正是換邊規則被髮明出來要應對的情形。引擎、測試工具、54 盤對局和完整的開局表都在一個代碼倉庫裏。