Slay the Spire 2 相關隨機性錯誤
Slay the Spire 2(beta 修補 v0.107.0)包含一個重大錯誤,導致不同的偽隨機數生成器(PRNG)之間存在相關性。這意味著一次隨機事件的輸出——例如 Neow 提供的遺物——可以用來預測未來隨機事件的結果,包括卡牌轉換、藥水掉落以及敵人目標選擇。
錯誤原因:C# System.Random 中的線性種子
Slay the Spire 2 嘗試透過使用多個不同的 RNG 實例,防止一個區域的隨機性(例如戰鬥)影響另一個區域(例如卡牌獎勵)。每個實例都以一個由特定字串雜湊後修改的種子初始化(例如 seed + hash("shuffle"))。
然而,遊戲使用了標準的 C# System.Random 類別。此類別使用的演算法在起始種子上是線性的。因此,兩個種子相差已知固定值的 RNG 產生的輸出也會以可預測、可利用的方式相差。由於遊戲的 RNG 偏移量是固定的,任何 RNG 的第一次輸出都能提供關於遊戲中所有其他 RNG 第一次輸出的資訊。
相關隨機性對遊戲的影響
這種相關性會產生系統性的偏差,影響遊戲體驗,且往往不易被玩家立即察覺。
Neow 的遺物與詛咒
可預測性在 Neow 最初提供的選項中最為明顯。例如,玩家在 Underdocks 行動中選擇 Neow's Bones 時,隨機得到的詛咒約有 54% 的機率是 Debt,而在 Overgrowth 行動中,同樣的遺物則有 73% 的機率給予 Writhe。
其他 Neow 遺物也顯示出偏差:
- Large Capsule:此遺物永遠不會是普通等級。在 Overgrowth 中約有 70% 為非凡、30% 為稀有;在 Underdocks 中約有 63% 為稀有、37% 為非凡。
- Leafy Poultice:第一次卡牌轉換僅限於角色 80 張卡牌池中的 22 種可能性。
- Hefty Tablet:第一次稀有卡牌選項在 Overgrowth 中僅有 11 種可能性,在 Underdocks 中僅有 3 種。
戰鬥與地圖事件
相關性延伸至戰鬥機制與特定地圖事件:
- 藥水掉落:第一次戰鬥掉落藥水的機率在 Underdocks 為 76%,而在 Overgrowth 只有 4%。
- 敵人目標:對於 Defect 角色,第一次在 Underdocks 的戰鬥中釋放的閃電球有 75% 的機率擊中左側敵人。
- 垃圾堆事件:在單人模式下,根據數學推導,無法從垃圾堆事件中取得卡牌 Rebound,因為行動 RNG 與事件 RNG 的相關性排除了該特定結果。
第 2、3 行動的可預測性
可預測性持續到後期行動。第 2 行動的 Doll Room 事件與 Neow 的初始選項高度相關。例如,若玩家在跑圖開始時抽到 Hefty Tablet,則「一個娃娃」選項有 91% 的機率是 Mr. Struggles。同樣地,Crystal Sphere 遺物箱的位置可以透過跑圖第一次戰鬥掉落的金幣數量來預測。
技術解決方案與建議
此問題根源於 PRNG 的選擇結構性缺陷。為了消除這種相關性,開發者可以拋棄 System.Random,改用非線性 PRNG。
推薦修正
- 實作非線性 PRNG:將
System.Random替換為現代演算法,如 PCG32,即可立即移除種子之間的線性相關性。 - 自訂實作:直接在遊戲程式碼中實作 PRNG,而非依賴 C# 標準函式庫,可確保不同平台(例如桌面與行動裝置)之間的種子保持一致,避免 Slay the Spire 1 中出現的版本特定種子漂移問題。
- 基於計數器的 RNG:使用基於計數器的隨機數生成器,可免除在載入存檔時手動「推進」 RNG 狀態的需求。
社群見解
技術觀察者指出,此問題產生的原因是遊戲在 Godot 引擎中使用了 C# System.Random,而 Godot 自身的 GDScript RNG 使用的是 PCG32,若採用後者本可完全避免此問題。其他開發者則強調,關鍵遊戲隨機生成器應始終視為遊戲程式碼,而非平台依賴的函式庫程式碼,以確保一致性與公平性。