163场对局,136个英雄,同一个英雄连续roll出5-6次——这位程序员决定用代码拆穿手游的"随机"谎言。
事情始于《英雄联盟手游》的ARAM模式。5v5随机英雄,不满意可以掷骰子重roll,骰子攒起来很慢,玩家用得抠抠搜搜。作者本来只是陪朋友入坑,结果越玩越不对劲:想要的英雄永远roll不到,买了皮肤的英雄更是像被系统拉黑。
免费游戏的套路他懂。留存率、日活、付费转化,这些指标背后藏着一堆"灰色心理学"。但当同一天内连续10-12局反复roll到同一个英雄时,他坐不住了——这已经不是运气差能解释的了。
163场数据的笨办法
没有抓包,没有逆向,就是最原始的笨功夫。每局开场截图记名字,Excel硬记163场,覆盖当时全英雄池136个角色。Wildcard机制(五选一特殊骰子)因为太难追踪,直接弃用,保证数据干净。
样本量够不够?统计学上136个选项、163次抽取,确实能说明一些问题。但真正的难题是:怎么定义"公平"?
作者用Go写了一个模拟器,按他理解的"良心做法"实现——密码学级随机数,每个英雄权重均等,纯纯的真随机。然后拿这个理想模型,对比自己的实际遭遇。
真随机会产生聚类,这是数学常识。蓝噪声(Blue Noise)刻意打散分布,看起来均匀;真随机反而会出现" streak"——连续几次抽到同一个,就像抛硬币连出五把正面。问题只在于:你的"随机"是真随机,还是假装随机的假把式?
图表里的猫腻
go-echarts生成的可视化一拉出来,味道就不对了。某些英雄的出场频率明显偏离理论值,而且偏的方向很"懂事"——作者熟练度低的、没皮肤的,反复横跳;买了限定皮的、苦练过的,仿佛被设置了冷却时间。
他特意检查了时间维度上的分布。真随机的聚类应该是散点式的、无规律的;但他的数据呈现出某种...节奏感。某些英雄在特定时段密集出现,又突然消失,像是有个调度表在背后。
这让人想起手游行业的公开秘密:动态难度调整(Dynamic Difficulty Adjustment)早已不是新闻。从《糖果传奇》到《FIFA Ultimate Team》,系统根据玩家状态实时调节"运气",让你输到想氪、赢到想肝,就是不会让你爽到想下线。
ARAM的随机池理论上对所有玩家一视同仁,但"随机"的定义权在开发商手里。权重可以调,伪随机算法可以埋,甚至你的历史行为数据——胜率、皮肤拥有率、在线时长——都可以喂进模型,输出一个"刚好让你不舒服"的结果。
代码不会撒谎,但算法会
作者把Go代码和完整数据集开源了。这不是什么惊天大瓜,没有起诉、没有官方回应,就是一个玩家用程序员的方式求证一个直觉。但163场的样本戳破了一层窗户纸:当你觉得"今天运气真差"时,可能有个推荐系统在默默工作。
免费游戏的商业模式决定了,"公平"从来不是最优解。最优解是那个让你既不退坑、又愿意掏钱的微妙平衡点。随机系统是这个平衡器的核心组件,它负责制造渴望(roll不到想要的)、制造惊喜(偶尔让你爽一把)、制造焦虑(骰子用完了好慌)。
作者最后说,他没打算继续追踪了。163场足够说明问题,再多也只是重复验证。而且说到底,知道真相之后,游戏还玩得下去吗?
这个问题,他留给了每一个曾在深夜骂过"这随机有毒"的玩家。
热门跟贴