第五章 程式改良與實驗數據
第二節 連五判別改良
在連五判別方面,原先 Ogemust 網站上的程式所使用的方法為對四個方向(垂 直、水平、左斜與右斜)皆作一次連五判別,雖然這個方法比較直覺且實作容易,
但由於連五判別相當頻繁,因此整個程式會花費相當多的時間在判別是否連五,
所以我著手對這個部分作出一些改良。
首先我們可以知道當一子落在盤面上時,會影響盤面是否連五的範圍為以此 子為中心的八個方向延伸四個空格,如圖 5-3 所示。
圖 5-3 當下走步之連五範圍
因此我們可以用 mask 的方式將連五範圍裡的位置取出並作連五判別即可,
顯然這種米字形範圍在實作上一定有相當的難度,所以我們必須用一些特別的方 法處理,然而在 Pradyumna Kannan 的論文[17]中有提到 Magic Move-Bitboard
Generation 這個神奇的方法,將 mask 出來的 bitboard 乘上一個 magic number 後再 向右 shift 數個 bits,而這些米字形的位置則會落在高位元區域,以西洋棋主教走
步產生為例(圖 5-4),圖中左邊為主教可走的九個位置,乘上中間的一個神奇數字 後,所有走步就如右邊所示皆集合在高位元區域,之後再向右 shift (64-(主教之走 步)),所得到的 64 位元整數即為 hash key,再到事先建好的 hash table 中找答案。
圖 5-5 為此方法的 pseudo code。
圖 5-4 Magic Move-Bitboard Generation 應用於西洋棋[4]
圖 5-5 The pseudo code of Magic Move-Bitboard Generation
從圖 5-5 中我們可以知道 moveDB 這個二維陣列的 hash table 所存放的值就 是當前某個兵種在 square 位置可移動到哪些地方,而 mask 與 magic 分別存放此 兵種在 square 位置的 mask bitboard 值與對應的 magic number。
然而在實作這個方法時遇到了兩個問題,其一為由於五子棋是八個方向都要 判別連五,因此 mask 出來的連五範圍最多有 27 個位置,故需要227容量大小的 table 存放,耗用太多的記憶體,所以我將水平垂直與斜線分開來處理,不過需要 多找一倍的 magic number 數量;再來遇到的問題是尋找 magic number 時 collision rate 很高,畢竟我希望找到的是 perfect hashing 的 magic number,因此為了降低 collision rate,以及發現五子棋 hash table 所需存放的值為是否連五,故若 mask 結 果為連五(以 F 表示),而 hash key 對應的值亦為 F(圖 5-6),則我視為沒有 collision,
反之亦然。附錄 B 列出所有位置的垂直水平方向的 Magic Numbers。附錄 C 列出 所有位置的斜線方向的 Magic Numbers。
圖 5-6 Magic Move-Bitboard Generation 應用於五子棋概念圖
接下來我們做實驗比較一下有使用 Magic Move-Bitboard Generation 及未使用 的效能相差多少,表 5-2 為八個測試盤面的改良前後時間比較。從表 5-2 可看出 使用 Magic Move-Bitboard Generation 方法的效能明顯優於 original,然而 Test7 及 Test8 盤面效能差於 original 的原因在於事先建 hash table 需耗時 1~2 秒,因此從 實驗結果來看,使用 Magic Move-Bitboard Generation 對於後續勝負問題的研究大 有裨益。
表 5-2 是否使用 Magic Move-Bitboard Generation 之時間(s)比較