简介
随机性的奖励是所有赌博和游戏的核心,随机算法非常影响玩家的游戏体验。
举个经典的例子,暴击。假设现在拥有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人,把暴击打在敌人身上,获得对拼优势。许多年前某“国服第一蛮王”,就曾经利用这一对线技巧统治上路。
类似的,很多游戏的装备强化,先低等级强化几次,连续不失败,之后再去强化高等级的装备,也能有效提高强化效率。
抽卡玄学
很多卡牌类游戏都只公布了抽卡的概率,并未公布具体的算法,而抽卡的概率很有可能只是一个数学期望值,实际每一次抽卡的概率受伪随机算法影响有所波动。比如先在免费池子里,连续抽多少次没出货,再去氪金池子里抽。如果两个池子的概率是通用的,并且游戏抽卡采用了伪随机算法,那么有可能前面没出货的都算是垫刀。再或者平时抽卡如果连续没出货,就忍住不要继续抽,等到活动期间再进行抽卡,有更大的概率拿到期间限定的卡牌。这些都利用了伪随机算法的原理。
至于白天抽还是晚上抽,躺着抽还是站着抽,左手抽还是右手抽,那就是玄学了。
后记
玄不改非,氪不改命,请理性游戏。
参考文献
https://dota2.gamepedia.com/Random_distribution