转帖来源:http://war3.replays.net/bbs/htm_data/2/0609/866031.html
※
论
war3
中的随机数系统
※
(
重新编写版
)
英文版在
MYM
主页放出
感谢
ryanz9
翻译
|
感谢
rn_tl
纠错
已用红字修正
写在前面
:
最初的我,来
RN
只是为了下录像,当有一天
ShortRound
突然出现在
RN bbs
的时候,为了回帖,我拥有了自己在
RN
的第一个
id
。最初的时候,只回帖不发贴,灌了几百帖之后,我觉着应该写些什么有意义的东西了。于是大约两个月前,我在
Hum
区发了这篇文章,当时激起了激烈的讨论。前两天有人在综合区发过原文了,相信不少人也看过了,经过这段时间,我对原文有了一些改进,依照承诺发上来,主要是
做了一些内容上的补充更新和重新排版,更利于理解。
当然,还是那句话,其实这里面的部分结论只是我的猜测,而且验证起来也比较困难,所以算是抛砖引玉吧,欢迎大家一起讨论。
原贴地址
:http://war3.replays.net/bbs//htm_data/102/0607/727518.html
English Version
(
Translater & Rewriter
:
ryanz9
):
http://www.meetyourmakers.com/article/127.html
附
cga
转贴时的评论
:
国内某神秘达人对于
WAR3
游戏中的随机系统的解释,非常专业;建议各位读者看看,会得益不少
“
神秘达人
”
?呵呵,偷笑。
_________________________
Part 1:
关于攻击力的随机值问题
大家都知道,
war3
里面攻击力是有范围的,
DH
的闪避、
BM
的暴击等都是有概率的。所以在
war3
里,随时随地都是有随机事件发生的。但大家可能没注意过,攻击力的随机值是怎样产生的呢?是全范围内的等概率事件,还是如二项式曲线一样中间数值概率高、两边数值概率低?
正确的答案是这样的
:
1
、对于所有的法师、建筑、召唤生物等不可以升级攻击力的单位来说,分布是平均的,范围内所有数据产生的概率是一样的;
2
、对于
英雄
和所有可以升级攻击力的常规攻击单位来说,是中间的数值概率高,两边的概率低。
至于具体的原因和分布概率,请看下面详解。
大家应该都看过魔兽的中文帮助,细心的朋友可能发现了,有些版本的帮助中,对攻击力的数值的表述不是一个由下限到上限的具体数字范围,而是用的类似这样一个式子
A+BdC
(其中
ABC
均为自然数)。比如
0
攻
rm
吧,用前一种表述方法就是
18-24
,而用后一种表述方法则为
:16+2d4
。有人可能会问了,这种表述方法是什么意思呢?
这其实表示,
war3
中攻击力的概率分布使用的是
d&d
骰子系统。通俗一点的理解就是
:
任何兵种都是有一个基础攻击力数值
A
(比如
rm
就是
16
),
B
则代表骰子数量(比如
rm
就是
2
),
C
则代表骰子的面数(比如
rm
就是
4
,这里不一定是
6
啊,
war3
不是搓麻)。
rm
每攻击一次,系统就扔出两个
4
面的骰子(骰子扔出
1-4
的概率是相同的),假如扔出来的数值是
2
、
4
,那么这一次攻击的数值就是
16+2+4=22
。当然啦,当扔出的都是
1
时,就是最小值
18
,当都是
4
时,就是最大值
24
。
现在来研究一下攻击力分布概率的问题。继续拿
0
攻的
rm
举例,其他的兵种道理是一样的。
18
(
24
)
:1+1
(
4+4
)
一种可能性
概率
1/16
19
(
23
)
:1+2
、
2+1
(
3+4
、
4+3
)
两种可能性
概率
2/16
20
(
22
)
:1+3
、
2+2
、
3+1
(
2+4
、
3+3
、
4+2
)三种可能性
概率
3/16
21 :1+4
、
2+3
、
3+2
、
4+1
四种可能性
概率
4/16
可以看出来,越居中的数值随机出来的可能性越高,而两边的数值概率是对称的,距中心数值越远概率越低。
也许可能有人要问了,那
rm18-24
的攻击力为什么不能表示为
17+1d7
或者
15+3d3
呢?这两个式子也代表了
18-24
这个攻击范围啊?这是一个好问题,如果各位
war3er
看到这里能提出这个问题的话,说明你是个善于动脑、善于思考的人。
答案是这样的,大家想一下,
war3
对攻击力的升级是怎么实现的呢?很简单,就是加一个骰子。再拿
rm
举例,
0
攻的
rm
攻击力是
16+2d4
,
1
攻的
rm
攻击力是
19-28
,用先前的表示法就是
16+3d4
,正好是
B
值增加了一点。而如果是
17+1d7
或者
15+3d3
这两个式子的话,升一攻加一个骰子后变成
17+2d7
或者
15+4d3
,这分别对应于
19-31
、
19-27
,这与事实是不符的。同理,
2
攻
3
攻的
rm
的攻击力分别为
16+4d4
(
20-32
)、
16+5d4
(
21-36
)。
现在大家再看一下这个式子
:A+BdC
,升
1
、
2
、
3
级攻后
B
分别为
B+1
、
B+2
、
B+3
。
可以看出,
A
越大、
B
越小、
C
越大,那么升级攻后对攻击力的提升更加显著。下面列表看一下各族各个兵种的攻击力数值(召唤生物、法师没有列出,因为他们不能升级攻防,于本文没有讨论意义)
:
Hero:
PAL 22+2d5 BM 24+2d12 DH 22+2d12 DK 23+2d6
AM 19+2d4 FS 19+2d4 KOG 18+2d4 LICH 20+2d4
MK 24+2d6 TC 25+2d5 POM 19+2d5 DL 20+2d6
BMG 19+2d4 SH 20+2d4 WD 20+2d11 CL 26+2d4
DR 21+2d6 PD 22+2d6 FL 20+2d4 NAGA 22+2d6
BM 22+2d6 PL 26+2d6 GA 25+3d10 Tinker 22+2d4
HUM: ORC: NE: UD:
民兵
:11+1d2
大
G: 17+1d4 ac: 15+1d3
小
g: 10+2d2
fm: 11+1d2
猎头
: 22+1d5 ht: 15+1d3 zz: 25+1d6
rm: 16+2d4
粉碎者
:71+1d18
投刃车
: 35+1d18
天
g: 17+1d4
74: 25+2d5
狼骑
: 22+1d5
小鹿
: 16+1d3 60+1d10
破法
:12+1d3
飞龙
: 34+2d5 doc: 18+1d4
绞肉车
: 70+1d18
飞机
:6+1d2
蝙蝠
: 12+1d3
熊形态
: 26+3d6 abo: 32+1d7
13+1d2
牛头
: 29+1d7
角鹰
: 49+1d8 des: 18+1d3
小炮
:51+1d13
角鹰骑
: 15+1d3
冰龙
: 91+2d12
坦克
:44+1d11
精灵龙
: 13+1d3
骷髅
: 13+1d2
12+1d2
奇美拉
: 66+1d17
49: 44+1d11 44+1d11
61: 17+1d3
山岭
: 26+2d7
32+2d8
dot
鸟
: 34+1d7
关于此表的相关讨论
:
0
、关于英雄的攻击力
:A
即为初始的主要属性值,升级后
A
随主要属性值的增加而增加,而
B
和
C
不会改变;绝大部分
B=2
,其分布概率如
0
攻的
rm
;
C
值一般都在
4-6
之间,除了
BM
、
DH
、
WD
,由于拥有较高的敏捷值,他们三个也是
DPS
最高的英雄。还有一个不得不提醒大家注意的英雄
:GA
(地精炼金术士),唯一的
B=3
,
C
更是高得离谱,虽然攻速低了些,但配合化学狂暴和酸性炸弹,也可以提供非常高的攻击输出。下表列出了
BM
、
DH
和主升狂暴的
GA
的
DPS
,可见成长性还是相当好的,
Blizzcon
上
Zacard
在
TM
上打
Grubby
就是使用的
GA
,不过最后输了,不知道能不能发展出围绕它的相应战术。只可惜敏捷值太可怜了,
10
级也只有
4
点甲
-_-!
BM DH
狂暴
GA
Lv1 30.94 29.65 24.90
Lv3 33.90 30.92 41.23
Lv5 41.69 37.62 62.78
1
、可以看出,初级兵里
zz
的
A
、
C
值最高,所以也是初级兵力最贵的。
2
、
49
、奇美拉、小炮、三种
CAT
都符合
A
大、
B
小、
C
大的原则,也就是说,对于他们升攻对攻击力的提高是显著的。(这里要注明一下,如果从纯数学的角度计算,应该是
:A
越小、
B
越小、
C
越大则升攻后对攻击力的提升更加显著,有些朋友在回复中提到了这一点。这并不是笔误,我当是在写此文的时候考虑到这一点了,但我认为衡量一个单位的攻击力的高低是要综合考虑
A
与
C
的大小的,而
A
和
C
同时都很大的单位,其攻击力输出通常是可怖的,而且看我上面列的表格会发现,
A
小
C
大的单位几乎没有,所以我的结论也是依据这一点。)
3
、有一个不得不提的就是熊德,它是所有法师里(如果它算法师的话)唯一升级还会加攻击力的。而变形后的熊也比较特殊,它是唯一
B
值为
3
的,而
C
值也只有
6
,升攻对它的效果并不显著,只是因为
B
值较大,攻击力范围很大而已。
4
、对于争论较多的角鹰和天鬼,他们对空攻击力之比约为
4:5
,考虑到攻击间隔分别为
1.05
和
1.4
,
dps
之比约为
14:13
,再考虑到血量(按照
1
点护甲
=6%
血量,角鹰
525
,天鬼约
484
)和速度(角鹰
400
、天鬼
350
),纯对
PK
的话,角鹰强。
5
、对于
C
值小于
4
的(比如
des
、
61
),升攻对它们是没什么太大作用的。
6
、
UD
的绞肉车数据上并不逊于
ORC
的粉碎者,而且攻频还稍快(
4s
对
4.5s
),不过粉碎者有小范围的溅射;三本升级则各有所长。
对于这部分更多讨论可以参看
0imm
的帖子:
“
同样质疑下下攻击
※
关于
war3
中的随机数系统
※
”
http://war3.replays.net/bbs//htm_data/102/0607/729351.html
还有要强调的一点就是
:
对于
B=1
的兵种来说,升攻前因为只有一颗骰子,所以它们的攻击力概率分布是均匀的,当
B>1
后就符合前文所说的中间概率高,两边概率低的规律了。
_____________________________
Part 2:
论
Replay
重现随机事件的方法
这方面的内容,是有关
war3
本身程序原理的,我只是提出自己的一种假说而已,真正的答案可能要去问
war3
的设计者,写在这里是希望大家一起来参与讨论。
除了攻击力的随机值,
war3
中还存在大量的其他的随机事件,比如英雄的被动技能、
Miss
的产生,甚至包括出生点的确定、英雄的姓名、宝物的掉落也都是随机事件。在比赛中这些随机事件发生的时候,和攻击力的随机值的产生一样,只需要系统产生一个或多个随机数就可以了,但在播放
Replay
的时候,会怎样呢?
大家应该都用过
W3G Master
来查看
Replay
,从操作列表里我们可以看出
Replay
的工作原理:
rep
记录的是时间序列,即什么时间什么坐标的单位,以什么样的命令,指向目标坐标;而对于这个动作所造成的结果,是在播放
rep
时进行实时演算的。比如,坐标(
1
,
1
)的
fm
,以动作指令
“A”
,指向坐标(
3
,
3
)的
DH
;而对于这次攻击实际造成的伤害,
rep
里是不会、也没有必要、甚至是不能记录的。于是问题就产生了,由于随机系统的存在,每一次动作指令造成的结果是不确定的,
fm
可能给
dh
造成
8
点伤害,也可能被
dh
闪避掉,怎么才能保证播放
rep
时真实的重现当时的情况呢?
一种解释是
:
对于每一个动作,
rep
都记录下对应于它的随机数。
这种解释看似最方便直接,但仔细想想,又有不合理的地方,因为其数据量过于庞大了,要知道一次攻击通常都会产生不止一个随机数。我使用过
W3G Master
和
w3chart
这两款
Replay
分析软件,在操作列表里一共只有四项数据:玩家、时间、动作、坐标(我们常用的
W3G Master
把
“
动作
”
和
“
坐标
”
整合为
“
操作
”
),并没有
“
随机值
”
这项数据。如果
rep
真的记录了每次动作所对应的随机值的话,分析软件里为什么不列出来呢?是分析软件读不出
rep
中记录的随机数么?技术手段足以达到了;是分析软件读到了但没有列出此项数据么?完全没有必要。所以,真正的情况很可能是
:Replay
里并没有记录随机数。
依此,对于
Replay
的工作原理,我认为须遵循如下要素:
1
、必须能够真实的再现当时的情况,这一点毋庸置疑。
2
、数据量要尽量地少,能够用一个数干到的事情,绝不用三个数。这就像学
C
的时候老师说过:代码越精干越好,能够用少量代码完成的事情,绝不用大量的代码。
于是有人又提出这样一种解决办法
:
既然不记录每次动作对应的随机数,可以记录每次动作实际造成的结果。
这种解释也是有着明显缺陷的。首先,数据量并没有明显减少;其次,也是最重要的,这种方法并不能真实重现当时的情况。举个例子吧:升了一级跳劈的
BM
砍小
g
,一次攻击造成了
50
点伤害,于是系统记录下
50
这个数值。但在播放
rep
时,面对
50
这个数值,系统会产生混乱,因为它无法确定到底是
BM
随机到了
50
点的攻击力,还是随机到了
25
点攻击
+
跳劈,虽然结果相同,但在显示效果上跳劈和不跳劈还是有着明显区别的。
学过
basic
语言的可能都知道,调用随机函数
rand()
的时候,如果不指定随机种子的话,其产生的随机数列是不会改变的,也就是说不同的随机种子对应于不同的随机数列。
这里引用
祝蜚
在回帖中的一段话有助于理解
:“
计算机只能产生伪随机数,
C
语言中的随机数函数
rand()
,一个种子,只会产生一个固定的随机数数列,打个比方来说明这个问题
:
设种子为
1
,第一次调用
rand()
会得到
7
(这个
7
是我乱写的一个数字,并不是真的
rand
产生的,后同),第二次调用
rand()
会得到
9
,然后得到
225
、
159
、
6724......................
这样得到一个随机数列
7
、
9
、
225
、
159
、
6724.......
再第二次把种子设为
1
,运行
rand()
还是会得到
7
、
9
、
225
、
159
、
6724.......
这一个数列。
”
(抱歉我不是学计算机的,发贴前对于伪随机数这个概念并不是很明白,所以在之前的回复贴中有一些武断的言论,在此收回,各位见谅。)
这就好比等差数列,在通项公式已知的情况下,如果确定了首项,那么整个数列也就确定了,而且首项与整个数列之间是一一对应的。
依据这个原理,我认为是这样的,一次游戏开始前,
war3
先随机产生一个随机种子(相当于首项),而依据事先制订好的数据生成规则(就好比通项公式),可以利用这个种子生成一个随机数序列,而且这个种子和随机数列之间是唯一对应的。当一个随机事件产生的时候,系统就按照先后顺序分配事前已产生好的随机数。
rep
也只须记录这个随机种子,当播放
rep
的时候,系统根据记录的随机种子重新产生出这个随机数列,由于时间顺序是确定的,所以一个随机事件对应的随机数也是确定的,这样就可以真实的重现当时的情况,而且也可以大大的缩小数据量。
关于这部分,可以参考
biaika
的帖子
:“
质疑随机数系数一文
”
http://war3.replays.net/bbs//htm_data/102/0607/728790.html
biaika
对于我的理论理解有误,我和各位回复者作了比较详尽而形象的解释。
________________________________________________
最后,还想感谢一下之前对我这个帖子给予关注的各位
RNer
,人太多了恕我不能一一列举,你们的有见解的回复对我现在发这个帖有不小的帮助,所以还希望各位继续踊跃参与讨论。
综合区的帖总有一天要沉的,欢迎访问
魔兽图书馆
区镜像:
http://war3.replays.net/bbs/read.php?tid=867158
版权所有,转载请注明出处
shohit@Replays.Net
[
此贴被
shohit
在
2006-10-17 23:46
重新编辑
]