博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【转】 DOTA2中的伪随机及其lua实现
阅读量:6954 次
发布时间:2019-06-27

本文共 1966 字,大约阅读时间需要 6 分钟。

因为单纯的随机确实会影响到竞技性,所以dota2引入的是伪随机机制,在大量的技能中,比如说混沌的混乱之箭、剑圣的剑舞、冰女的冰霜领域之类的技能,都利用了伪随机机制。

而纯随机,或者标准正态分布并不会因为之前的结果影响此次技能的效果,因为他们的每次计算是互相独立的。
所以,从魔兽争霸3继承来的PRD(Pseudo Random Distribution)机制就被引入啦,具体的实现原理是这样的,每次的运行,都使用一个不断增加的概率来进行计算,如果这个事件一直触发不成功,那么概率就不断上升,直到事件发生为止。
要完成这个算法,要解决的问题就是,对于一个发生概率为p的事件,在我们第N次调用的时候,我们使用的概率是P(N) = c * N,P(1)显然要是一个小于p的数值,所以要解决的就是c这个数值,如何让整体的概率尽量接近于p。
这里要引入的是马尔可夫链公式,马尔可夫链的定义在可以看到。
简单来说,马尔可夫链就是描述了一种此次事件会受到之前N个状态的影响。具体的公式可以去百度百科看到。
回到dota2,比如我们对于一个触发概率为5%的暴击,那么第一次出现暴击的概率是c,第二次是2c,如果一直不发生,直到第N次,出现了(c*N)大于1了,那么这次暴击就必然发生了,而在中间的每一次,如果暴击发生了,那么我们就把随机概率重置为c。
因此,总体期望的计算公式就是

P = 1*c + 2*c(1-c) + 3*c(1-c)(1-2c)+....

其中P = 1/p,N=1/c(第N次必然发生),那么我们可以用2分法在(0,1)之间不断估算c,直到这个公式成立就行了。

具体的算法实现:

local function p_from_c(c)    -- 模拟N次随机,计算是否会在N次随机之后必然发生    local po, pb = 0, 0    local sumN = 0    local maxTries = math.ceil(1/c) -- P = 1*c + 2*c(1-c) + 3*c(1-c)(1-2c)+.... for n = 1, maxTries do po = math.min(1, c*n) * (1-pb) pb = pb + po sumN = sumN + n * po end return (1 / sumN) end function c_from_p(p) local cu = p local cl = 0.0 local cm local p1, p2 = 0, 1 while true do cm = (cu + cl) / 2 p1 = p_from_c(cm) if math.abs(p1 - p2) <= 0.000000001 then -- 如果发生的概率足够小,那么认为已经找到了对应的c break end if p1>p then cu = cm else cl = cm end p2 = p1 end return cm end

具体的使用上,我们需要在技能里面用个变量来储存连续失败的次数,之后随机的时候再使用伪随机数来计算发生的概率。

function my_ability:OnSpellStart()    if self.nFails == nil then self.nFails = 1 end local c = c_from_p(0.20) local success = RollPercentage(c*100*self.nFails) if success then -- 执行具体的操作 self.nFails = 1 else self.nFails = self.nFails + 1 end end

这个算法可能出现的问题:

  1. 在大概率事件的时候,不建议使用这个算法,因为如果一个70%的事件以57%的概率进行第一次计算的话,会出现很大的误差,基本上就是第一次57%,第二次100%。
  2. 如果事件出现的数量很少的话,比如说10%的事件整个游戏过程只会出现个三四次的话,那么就纯随机就好了。

当然,最适合的算法就是各种抽奖算法啦,能够稍微保护一下非酋的体验。

之前炉石不是有个更新说,新手的30包必定出橙嘛,就暴露了一个事实,无良暴雪一开始的开包就是纯随机的,有了这个更新才变成的伪随机,难怪我一直玩的是炉石稀有。

作者:XavierCHN
链接:https://www.jianshu.com/p/f9a1646a8f19
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

转载于:https://www.cnblogs.com/timeObjserver/p/9641025.html

你可能感兴趣的文章
saltstack jobs管理
查看>>
WebStorm设置Themes
查看>>
FTP连接时出现“227 Entering Passive Mode” 的解决方法
查看>>
以太网交换机如何工作以及MAC和PHY
查看>>
Ubuntu 设置定时crontab任务
查看>>
linux下test命令
查看>>
tshark可以实现命令行脚本分析流量
查看>>
单例模式的使用和继承
查看>>
LVM逻辑卷管理-软RAID磁盘阵列
查看>>
LVS的三种模式区别详解
查看>>
如何隐藏xendesktop登录时domain信息的输入
查看>>
Linux_MySQL二次整理(1)
查看>>
Linux内核LTS长期支持版生命周期
查看>>
VMware下的Linux中调整屏幕大小,分辨率问题,终于解决啦
查看>>
cxgrid打印
查看>>
必 备 习 题 集 ( 三 )
查看>>
citrix桌面发布方式
查看>>
HTTP协议详解(真的很经典)
查看>>
EMC销售部全球CTO Patricia Florissi:大数据不是炒作
查看>>
判断字符串是否是合法的ipv4地址
查看>>