iT邦幫忙

2024 iThome 鐵人賽

DAY 6
1

群豪見他使得全然不成章法,身手又笨拙之極,無不捧腹大笑。
那挑菜漢子道:「有甚麼好笑?讓我來練練,借把劍來。」接了長劍在手,便即亂劈亂刺,出手極快,猶如發瘋一般,更引人狂笑不已。
令狐沖初時也是負手微笑,但看到十幾招時,不禁漸覺訝異......兩人的姿式固是難看之極,但劍招古樸渾厚,劍上的威力似乎只發揮得一二成,其餘的卻是蓄勢以待,深藏不露......

-- <笑傲江湖>,金庸著

卡斯鐵說:「這些生物體總是看起來前所未見,事實上都是同樣的東西。」
李厄說:「這只是您的猜測,其實我們對這一切一無所知。」

-- <瘟疫>,卡繆著,嚴慧瑩譯

今天跟各位讀者介紹 DeltaPahogen 專案中很重要(若不是最重要的話)的角色:隨機猴子。它是所有訓練的基準,也是打通系統與代理人溝通的重要元件。

它首先出現在 commit 09abac 裡面,作為一個打通流程的東西。後來在 commit 5ecd2e 當中具備一個純試誤代理人的行為:隨便選著點,錯了的話就將該著點座標從選項之中排除。

上述提到的第二個 commit 代表的故事,將在接下來的兩天介紹。

這樣還能出什麼 bug 呢?沒有程式碼或模組是孤島,就算一個客戶端程式可以持續沒有修正很長一段時間,但我們無法保證協定(protocol)本身也不會。現在的例子也類似,隨著遊戲系統以及遊戲伺服器端的持續調整,這些協定也在我沒有注意到的情況下飄移了。接下來就分享幾個蠢 bug,也許意義不在於描述這些應用的問題會有多麼困難,而在於指出一個事實,就是如果缺乏基本的審查與管理,那麼就算是這樣蠢的 bug 也會發生。回顧這兩個 bug 時也很慚愧地發現我當時沒有增加相對應的 unit test。

至於 print debug 痕跡,哈,留待日後有需要更有效率的 python 除錯時再改掉這個習慣吧。

非法羅盤座標?

說到整個疫途的遊戲引擎實作的難點,我無論如何不會說是羅盤座標的合法性判斷條件,因為這是規則書說得很清楚的事情。但是慚愧的是,我竟然在這個部份出了三次的 bug:最基本的還是很基本的粗心的 corner,且依序簡說。

最基本的是,一個座標的決策給到遊戲系統來,總該判斷一下邊界吧?

    pub fn is_valid(&self) -> bool {
        if self.x < -MAP_OFFSET.x
            || self.x > MAP_OFFSET.x
            || self.y < -MAP_OFFSET.y
            || self.y > MAP_OFFSET.y
        {
            return false;
        }
        return true;
    }

這個應該是在搬移 legacy code 的時候沒有成功搬移的結果,但在沒有大量運行(多樣組態、自動對局)之前也不容易抓出。

還是很基本的是,遊戲中的羅盤階段,合法範圍並非 5x5 的全部區域。對疫病方來說,可下的著點排除了四個角,對於醫療方(或封城時的疫病方)來說則只有內部的 3x3 九宮格。

疫病方的條件:

        let times = self.x * self.y;
        if times <= -MAP_OFFSET.x * MAP_OFFSET.y || times > MAP_OFFSET.x * MAP_OFFSET.y {
            return false;
        }

醫療、或封城時的疫病方,不在 is_valid 裡面判斷,而是存在於上一層

        if (g.lockdown() && g.turn == Camp::Plague) || g.turn == Camp::Doctor {
            // Plague cannot outbreak when lockdown
            if c.x < -1 || c.x > 1 || c.y < -1 || c.y > 1 {
                return Err("Ex01");
            }
        }

我們在這個系列不會特別介紹上述使用到的 Coord 結構,它只是很簡單地被用來表述 2D 座標資料。其實在我後來為了編碼盤面資訊而使用 Array 系列套件的時候,才意會到應該沒有必要自己實作,少學一套適當的 Rust 工具。

最後一個 corner 發生在前述的疫病方第二組條件 times > MAP_OFFSET.x * MAP_OFFSET.y,這會使得 (2,2) 座標沒有被這個條件排除。我在 commit 訊息當中紀錄這個尷尬的事實。應該要是大於等於(>=)才對。

無路可走!?

隨機猴子行為很單純,就是試,然後排除回報錯誤的著點。然而我在修復這個問題之前,偶爾還是會遇到代理人端發現自己沒有著手可下的狀況。這怎麼可能?

原來是編碼的調整造成的。在出現問題之前,隨機猴子以及我預期的 coord_client 客戶端都是在 [0,57) 的區間選擇,它對應到棋盤格 36 個,加上 5x5 羅盤排除了 4 個角的 21。這原本是沒有問題的。但是排除了四個角的 5x5 的格子,不是很容易對應 [36,57) 的值域到座標上,而我先前也的確沒有實作

目前狀況

今天也是除了簡單編輯文稿如上,就幾乎沒有產出。拼了一陣,終於是提了一個 commit,實作一個略具昨日提到的殘局譜生成器的雛型。

希望可以生成合用的、客觀可評斷優劣盤面的這殘局一手詰,來讓茫然的訓練旅途增添一些方向感。


上一篇
切入桌遊引擎的實作
下一篇
定義 `Action` 物件
系列文
DeltaPathogen:國產雙人不對稱抽象棋「疫途」之桌遊 AI 實戰30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言