cover_image

垫刀与玄学:游戏中伪随机算法的原理

工程师加一 工程师加一
2021年09月27日 11:41

简介

随机性的奖励是所有赌博和游戏的核心,随机算法非常影响玩家的游戏体验。


举个经典的例子,暴击。假设现在拥有15%的暴击率,我们定义连续2次出现暴击为“欧洲暴击”,连续10次不暴击的概率为“非洲暴击”。如果使用真随机算法,欧洲暴击率2.25%,非洲暴击率接近20%。然而在游戏体验中,玩家觉得这样的欧洲暴击率和非洲暴击率都太高了。对手打出欧洲暴击,或者自己打出非洲暴击,都太影响游戏体验。于是游戏设计者就得改变随机性算法,保证暴击率不变的情况下,降低欧洲暴击率和非洲暴击率,以提高游戏体验。


本文介绍PRD伪随机算法。最近在做H5游戏相关的工作,计算部分就顺手用了JavaScript。


PRD算法

Pseudo Random Distribution,简称PRD算法,是目前最经典、最流行的伪随机算法,因为用于Dota2的暴击计算而广为人知。其原理为:第一次攻击给定一个暴击概率C,如果没有触发暴击,第二次的暴击率为C×2,第三次为C×3,以此类推,直到触发了暴击,则重新计算。用公式表示为:

P(N)=C×N

其中,N是攻击次数,P(N)是该次暴击率,C为常数。如果非洲人一直不暴击,P(N)会一直增加下去,直到超过100%,那就必定触发暴击了。这类似于游戏中的保底机制了,防止脸太黑时的游戏体验。


在上述公式中,对于某一暴击率P1,有对应的常数C1,使得最终P(N)的数学期望值与P1一致。要求出C的值并不容易,一般都是通过二分法求得一个近似值,存在一个表里,游戏直接查表获得,以提高运算速度。以下是官方给出的C值的表:

概率
C值
5%
0.38%
10%1.5%
15%3.2%
20%5.6%
25%8.5%
30%12%
35%16%
40%20%

45%

25%
50%30%
55%36%
60%42%
65%48%
70%57%
75%67%
80%75%
85%82%
90%89%
95%95%

这里我也给出用二分法求任意概率的C值的算法,以及任意C值求概率数学期望值的算法:https://github.com/oonne/test-pseudo-random-distribution。

注意上表,由二分法求得的C值,随着P值越大,精度越低,这是算法本身的问题。因此测试用例只写了20%以内的,精度达到0.1%。


虽然伪随机算法并未改变暴击的数学期望值,却改变了暴击的分布。上述源码也提供了测试脚本,你可以克隆下来,运行“node generatedAttack”,随机的生成1000次攻击,观察一下暴击的分布。可以看到欧洲暴击和非洲暴击的几率都显著下降了,游戏体验得以改善。下图是首次暴击的分布曲线:

图片

除了Dota2,其他游戏也有类似的伪随机算法,但原理大致相同,这里就不展开了。


伪随机算法的应用

暴击垫刀

LOL中的暴击采用了类似PRD的算法,但不完全一样,具体并未透露。效果是殊途同归的,每一次不暴击,都会增加下次暴击的概率。比如你使用上单蛮王,满怒35%暴击率,补兵连续三刀如果都不暴击,那么下一刀暴击的概率会远超你的暴击率。这时不要再A兵了,而是直接E上去A人,把暴击打在敌人身上,获得对拼优势。许多年前某“国服第一蛮王”,就曾经利用这一对线技巧统治上路。


类似的,很多游戏的装备强化,先低等级强化几次,连续不失败,之后再去强化高等级的装备,也能有效提高强化效率。


抽卡玄学

很多卡牌类游戏都只公布了抽卡的概率,并未公布具体的算法,而抽卡的概率很有可能只是一个数学期望值,实际每一次抽卡的概率受伪随机算法影响有所波动。比如先在免费池子里,连续抽多少次没出货,再去氪金池子里抽。如果两个池子的概率是通用的,并且游戏抽卡采用了伪随机算法,那么有可能前面没出货的都算是垫刀。再或者平时抽卡如果连续没出货,就忍住不要继续抽,等到活动期间再进行抽卡,有更大的概率拿到期间限定的卡牌。这些都利用了伪随机算法的原理。


至于白天抽还是晚上抽,躺着抽还是站着抽,左手抽还是右手抽,那就是玄学了。


后记

玄不改非,氪不改命,请理性游戏。


参考文献

  1. https://dota2.gamepedia.com/Random_distribution



图片


游戏开发 · 目录
下一篇位图字体的原理及应用
继续滑动看下一个
工程师加一
向上滑动看下一个