黑色背景上落下的三枚白色骰子

一个必然会被问到的问题

Factorio 是一个以确定性著称的游戏:同一份存档、同一串操作,跑出来的结果永远一致。但在 Space Age 资料片里,官方加入了「品质」机制——物品和建筑有等级之分,在制造机里放入品质模块,就有小概率产出更高品质的成品。玩家很快就开始追问那个经典问题:确定性游戏里的「随机」到底是怎么来的?

答案也很经典:它不是真的随机,而是伪随机。游戏内部跑着一个伪随机数生成器(PRNG),一个确定性算法,输出一串看起来毫无规律的数字序列。

把黑箱拆开之后

正常写代码的人把 PRNG 当黑箱用,这没有任何问题。但有人做了一件更有意思的事:把算法和内部状态都搞清楚。既然算法是确定性的、状态是有限的,那么在已知初始状态的前提下,你可以和游戏同步跑同一段运算,从而提前算出未来会发生哪些「随机」事件——比如哪一次合成会跳出高品质。

作者在 8 月写下的这篇《Reversing Factorio's RNG》,用线性代数级别的工具把这个过程推导出来,并在游戏里做了实现。前提只有一条:对线性代数有基础了解。

一个很有价值的后续更新

文章开头有一段坦白:这些实现被 Factorio 2.1 打破了。2.1 改变了 RNG 的使用方式,游戏内实现随之失效。但作者特意强调,关于 RNG 工作原理的理论部分依然成立,因为游戏用的还是同一个随机数生成器——变的只是调用方式,不是数学。

这段更新比正文更像一则工程寓言:底层原理稳定,上层实现会变。押注在调用细节上的方案会失效,理解原理的人可以重新写一遍。

给做产品的人的三点提醒

第一,别自造随机。用系统提供的加密级随机源,不要用时间戳当种子,也不要用语言内置的普通随机函数去做抽奖、掉率、验证码这类事。

第二,把随机当成可审计的流程。抽奖、概率掉落、盲盒这类业务,迟早要面对「为什么我没中」的追问。系统能不能复现、能不能解释,是合规能力的底线。

第三,理解对手的视角。对这个逆向者来说,官方把这类机制解释成「本质上就是统计」,逻辑上没问题;但在客户端里跑的随机数,只要算法和状态被看穿,就不再是概率问题,而是计算问题。

玩家研究游戏,是出于好奇;产品经理该知道这些,是出于责任。