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 种。

战斗和地图事件

关联延伸到战斗机制和特定地图事件:

  • Potion Drops:第一次战斗掉落药水的概率在 Underdocks 为 76%,而在 Overgrowth 仅为 4%。
  • Enemy Targeting:对于 Defect,第一次闪电球在 Underdocks 的首次战斗中有 75% 的概率击中左侧敌人。
  • Trash Heap Event:在单人模式下,数学上不可能从 Trash Heap 事件中获得卡牌 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,本可以完全避免此问题。其他开发者强调,关键游戏随机生成器应始终视为游戏代码,而非平台依赖的库代码,以确保一致性和公平性。

SUMMARY: Slay the Spire 2 (v0.107.0) suffers from correlated randomness due to the linear nature of C# System.Random, allowing players to predict game events based on initial seed information.

TITLE: Slay the Spire 2 Correlated Randomness Bug

Sources