经OP鉴定,本词条内容清晰,排版优美,是值得参考的优秀范例。
本条目部分或全部内容搬运自外部资源。
遵守CC BY-SA 4.0协议,部分内容可能有所改动。
以下内容涉及较多精确数据,除非确信某处有误,否则请谨慎修改。
出怪机制
引用源
植僵百科知识:出怪规律本条目主要讲解生存无尽模式中僵尸的生成算法与随机原理。
出生点
出生点指僵尸生成时的x坐标。1)
僵尸 | 普通波出生点 | 旗帜波出生点 |
---|---|---|
旗帜 | - | 800 |
冰车 | 800~809 | |
投篮 | 825~834 | |
白眼、红眼 | 845~854 | |
撑杆 | 870~879 | |
雪橇 | 880~1030 | |
所有其他僵尸 | 780~819 | 820~859 |
出怪类型
出怪类型指本次选卡准许生成的僵尸种类。
准许
即使准许生成某僵尸,也不代表该僵尸一定会出现。例如,即便出怪类型中含有蹦极僵尸,也可能不生成蹦极,取决于生成时的随机结果。另有一部分僵尸无需准许亦能生成,如固定出现的旗帜僵尸、小概率随机出现的雪人僵尸。
出怪类型位于[[[6a9ec0]+768]+54d4]
开始的连续33个bool
类型的地址,true
代表准许,false
代表不准许。
出怪类型的决定方式如下2):
- 设定要出普僵
- 产生一个0~4的伪随机整数(后文详解),若等于0则设定要出读报,否则设定要出路障3)
- 若
轮数<8
,则设定剩余出怪类型数为轮数+1
,否则设定剩余出怪类型数为9 - 产生一个0~33的伪随机整数,若未设定要出此类僵尸且没有禁止出此类僵尸4),则设定要出此类僵尸并进入第5步,否则重复第4步
- 若第4步中已设定要出的僵尸类型数等于第3步的剩余出怪类型数,则进入第6步,否则重复第4步
- 忽略摇旗、僵博,即强制设为
false
5)
轮数
轮数即选卡时已完成flag数/2-1
。
随机数生成器算法为MT19937,种子由以下几个数值相加:
[[[6a9ec0] +82c] +20] // 用户序号 [[[6a9ec0] +768] +561c] // 出怪种子 [[[[6a9ec0] +768] +160] +6c] * 65 // 完成选卡次数 * 101 [[6a9ec0] +7f8] // 游戏模式
出怪概率
以下表格列出了不同轮数下,各僵尸出现在出怪类型中的概率,以及出怪类型中僵尸总数6)各取值的概率。7)
轮数=1
:
路障 | 读报 | 其他 | 2种 | 3种 | 4种 | |
---|---|---|---|---|---|---|
前院 | 82.67% | 30.67% | 13.33% | 0.95% | 24.76% | 74.29% |
后院 | 82.35% | 29.41% | 11.76% | 0.74% | 22.06% | 77.21% |
屋顶 | 83.08% | 32.31% | 15.38% | 1.28% | 28.21% | 70.51% |
轮数=2
:
路障 | 读报 | 其他 | 3种 | 4种 | 5种 | |
---|---|---|---|---|---|---|
白昼 | 83.53% | 34.12% | 17.65% | 2.21% | 30.88% | 66.91% |
黑夜 | 83.75% | 35.00% | 18.75% | 2.50% | 32.50% | 65.00% |
后院 | 83.16% | 32.63% | 15.79% | 1.75% | 28.07% | 70.18% |
屋顶 | 84.00% | 36.00% | 20.00% | 2.86% | 34.29% | 62.86% |
轮数=3
:
路障 | 读报 | 其他 | 4种 | 5种 | 6种 | |
---|---|---|---|---|---|---|
白昼 | 84.71% | 38.82% | 23.53% | 4.41% | 38.24% | 57.35% |
黑夜 | 85.00% | 40.00% | 25.00% | 5.00% | 40.00% | 55.00% |
后院 | 84.21% | 36.84% | 21.05% | 3.51% | 35.09% | 61.40% |
屋顶 | 85.33% | 41.33% | 26.67% | 5.71% | 41.90% | 52.38% |
轮数=4
:
路障 | 读报 | 其他 | 5种 | 6种 | 7种 | |
---|---|---|---|---|---|---|
白昼 | 85.88% | 43.53% | 29.41% | 7.35% | 44.12% | 48.53% |
黑夜 | 86.25% | 45.00% | 31.25% | 8.33% | 45.83% | 45.83% |
后院 | 85.26% | 41.05% | 26.32% | 5.85% | 40.94% | 53.22% |
屋顶 | 86.67% | 46.67% | 33.33% | 9.52% | 47.62% | 42.86% |
轮数=5
:
路障 | 读报 | 其他 | 6种 | 7种 | 8种 | |
---|---|---|---|---|---|---|
白昼 | 86.67% | 46.67% | 33.33% | 9.80% | 47.06% | 43.14% |
黑夜 | 87.06% | 48.24% | 35.29% | 11.03% | 48.53% | 40.44% |
后院 | 86.00% | 44.00% | 30.00% | 7.89% | 44.21% | 47.89% |
屋顶 | 87.50% | 50.00% | 37.50% | 12.50% | 50.00% | 37.50% |
轮数=6
:
路障 | 读报 | 其他 | 7种 | 8种 | 9种 | |
---|---|---|---|---|---|---|
白昼 | 87.78% | 51.11% | 38.89% | 13.73% | 50.33% | 35.95% |
黑夜 | 88.24% | 52.94% | 41.18% | 15.44% | 51.47% | 33.09% |
后院 | 87.00% | 48.00% | 35.00% | 11.05% | 47.89% | 41.05% |
屋顶 | 88.75% | 55.00% | 43.75% | 17.50% | 52.50% | 30.00% |
轮数=7
:
路障 | 读报 | 其他 | 8种 | 9种 | 10种 | |
---|---|---|---|---|---|---|
白昼 | 88.89% | 55.56% | 44.44% | 18.30% | 52.29% | 29.41% |
黑夜 | 89.41% | 57.65% | 47.06% | 20.59% | 52.94% | 26.47% |
后院 | 88.00% | 52.00% | 40.00% | 14.74% | 50.53% | 34.74% |
屋顶 | 90.00% | 60.00% | 50.00% | 23.33% | 53.33% | 23.33% |
轮数≥8
:
路障 | 读报 | 其他 | 9种 | 10种 | 11种 | |
---|---|---|---|---|---|---|
白天 | 90.00% | 60.00% | 50.00% | 23.53% | 52.94% | 23.53% |
黑夜 | 90.59% | 62.35% | 52.94% | 26.47% | 52.94% | 20.59% |
后院 | 89.00% | 56.00% | 45.00% | 18.95% | 52.11% | 28.95% |
屋顶 | 91.25% | 65.00% | 56.25% | 30.00% | 52.50% | 17.50% |
计算公式
设可出怪类型数是a
,剩余出怪类型数是b
,则:- 路障出现概率
0.8+0.2*b/a
- 读报出现概率
0.2+0.8*b/a
- 其他出现概率
b/a
僵尸种类数的三种情况概率分别为:
b*(b-1)/(a*(a-1))
b*(a-b)*2/(a*(a-1))
(a-b)*(a-b-1)/(a*(a-1))
轮数≥5
时,六大场地的a
值分别为18/17/20/20/16/16;轮数≥8
时,b
为9。
出怪列表
出怪列表决定了实际生成的僵尸的具体种类与个数,在选卡页面就已经确定。退出重进选卡页面会刷新出怪列表(所谓的无痕S/L)
完整的出怪列表长度20008),位于[[[6a9ec0]+768]+6b4]
开始的连续2000个int_32类型的地址,每50个为1波,总共记录40波。因此,每波至多生成50只僵尸。若出怪列表中留空,则对应波次会生成少于50只。
生存无尽模式中每轮仅20波,故只使用前1000个值。老虎机、宝石迷阵等无限出怪的模式中,第41波起会重复循环第40波的出怪。
每波僵尸刷新时,游戏会严格按照出怪列表预先设定的顺序依次生成对应僵尸。
生存无尽中,出怪列表的生成受以下因素影响:权重、级别、阶数、红眼数量上限。
权重
权重位于[0x0069da94 + i * 0x1c]
,游戏依此加权随机决定下一个要填入出怪列表的僵尸。
加权随机
即调整不同结果被随机到的概率。例如从箱中抽红球与黄球,若红球权重2,黄球权重1,等同于抽到红球的概率为3分之2,抽到黄球的概率为3分之1。
级别
每种僵尸的级别位于[0x0069da88 + i * 0x1c]
。
各僵尸级别与权重一览9):
序号 | 简称 | 级别 | 权重 | 备注 |
---|---|---|---|---|
0 | 普僵 | 1 | 4000 | 轮数=5 起每轮-180,轮数=25 起固定为400 |
1 | 旗帜 | 1 | 0 | 无需出怪类型准许亦可生成,每个旗帜波有且仅有一只 |
2 | 路障 | 2 | 4000 | 轮数=5 起每轮-150,轮数=25 起固定为1000 |
3 | 撑杆 | 2 | 2000 | |
4 | 铁桶 | 4 | 3000 | |
5 | 读报 | 2 | 1000 | |
6 | 铁门 | 4 | 3500 | |
7 | 橄榄 | 7 | 2000 | |
8 | 舞王 | 5 | 1000 | |
9 | 伴舞 | 1 | 0 | 衍生于舞王 |
10 | 鸭子 | 1 | 0 | 实际出现的鸭子僵尸为出现在水路的普僵/路障/铁桶自动转换而来 |
11 | 潜水 | 3 | 2000 | |
12 | 冰车 | 7 | 2000 | |
13 | 雪橇 | 3 | 2000 | |
14 | 海豚 | 3 | 1500 | |
15 | 小丑 | 3 | 1000 | |
16 | 气球 | 2 | 2000 | |
17 | 矿工 | 4 | 1000 | |
18 | 跳跳 | 4 | 1000 | |
19 | 雪人 | 4 | 1 | 无需出怪类型准许亦可生成,需已在冒险二周目4-10见到雪人 |
20 | 蹦极 | 3 | 1000 | 仅在旗帜波生成 |
21 | 梯子 | 4 | 1000 | |
22 | 投篮 | 5 | 1500 | |
23 | 白眼 | 10 | 1500 | |
24 | 小鬼 | 10 | 0 | 衍生于巨人 |
25 | 僵博 | 10 | 0 | |
26 | 豌豆 | 1 | 4000 | |
27 | 坚果 | 4 | 3000 | |
28 | 辣椒 | 3 | 1000 | |
29 | 机枪 | 3 | 2000 | |
30 | 窝瓜 | 3 | 2000 | |
31 | 高坚果 | 4 | 2000 | |
32 | 红眼 | 10 | 6000 | 非旗帜波调整为1000 |
每波所出僵尸的级别总和不超过该波级别上限。
级别上限
每波级别上限 =int(int((当前波数 + 已完成选卡数 * 每轮总波数) * 0.8) / 2) + 1
,旗帜波再* 2.5
并向零取整。
阶数
阶数决定了这个僵尸从第几波才会出现10)。
阶数 | 包含 | 限制 |
---|---|---|
一阶僵尸 | 普僵、路障、铁桶、读报、雪人 | 第1波开始就可以出现 |
二阶僵尸 | 撑杆、铁门、橄榄、舞王 | 至少从第5波开始才可以出现 |
三阶僵尸 | 潜水、海豚、冰车、小丑、气球、矿工、跳跳、梯子、投篮 | 至少从第10波开始才可以出现 |
四阶僵尸 | 白眼、红眼 | 至少从第15波开始才可以出现,轮数=9 起每轮-1,轮数=23 起固定为1 |
红眼数量上限
已生成的红眼总数达到红眼数量上限后,非旗帜波不再出红眼,立刻生效。
红眼数量上限初始为0,轮数=5
起每轮+1,轮数=54
起固定为50。
出怪难度饱和
出怪难度饱和指到达一定flags数后,游戏不再增加出怪算法难度的情况。该flags数阈值被称作“饱和f数”。
从不同角度可以得到不同的饱和f数:
- 第47f起,阶数不再起限制作用
- 第85f起,级别上限在统计意义上不再起限制作用
- 第109f起,红眼数量上限不再起限制作用
- 第126f起,级别上限在严格意义上不再起限制作用
出怪选行
引用源
出怪论:出怪的选行不要强行认字
理解以下内容需要一定的数学知识。出怪行信息
对于第i行,有权重、上次选择、上上次选择三个信息。
权重用于计算出怪内容,之前出怪用于计算出怪概率。
作如下定义:
- 将第i行权重定义为
Weighti
- 将第i行距离上次被选取定义为
LastPickedi
- 将第i行距离上上次被选取定义为
SecondLastPickedi
LastPickedi
和SecondLastPickedi
的初始值为0。
某一行出怪时
又称第j行插入事件。
为了避免某行僵尸过多,当某一行出怪,游戏会减少该行出怪的概率,提高其他行的出怪概率(设想一下,如果让一个人将一堆金币平均分给几个人,但是这几个人没有顺序,也只能抽取,那么这个发金币的人肯定更倾向于发给金币更少的人)
执行第j行插入事件时,会发生如下变化:
- ∀i∈[1,6],如果
Weighti>0
,则LastPickedi
和SecondLastPickedi
均增加1 - 将
LastPickedj
的值赋给SecondLastPickedj
- 将
LastPickedj
设为0
计算示例
用文字语言来解释的话,即如果某一行发生出怪,则所有行的上次和上上次被选取增加1,然后本行距离上次被选取(即当次选取)为0,上上次被选取改为上次被选取。
如按(3,4,1,2,5,1)的行顺序出怪后,结果如右(不考虑第6行)。
选取某次出怪的行
又称抽取行事件。
将受到LastPickedi
和SecondLastPickedi
影响后的Weighti
称之为平滑权重,记为SmoothWeighti
。
计算第i行的平滑权重的步骤如下: 1. 将第i行出怪权重在总权重的占比称之为,则有:
$$WeightP_i=\frac{Weight_i}{\sum_{j=1}^{6}Weight_j}$$
将LastPickedi
对结果的影响因子称为PLasti
,再将SecondLastPickedi
对结果的影响因子称为PSecondLasti
,通过查阅代码我们知道,它们的计算公式是:
$$PLast_i=\frac{6\times LastPicked_i\times WeightP_i+6\times WeightP_i-3}{4}$$ $$PSecondLast_i=\frac{SecondLastPicked_i\times WeightP_i+WeightP_i-1}{4}$$
最后获得平滑权重的计算公式如下:
$$SmoothWeight_i=\begin{cases}\begin{aligned} WeightP_i\times \min(\max(PLast_i+PSecondLast_i,0.01),100) & ,\quad WeightP_i\ge 10^{-6}\\\\ 0 & ,\quad WeightP_i<10^{-6} \end{aligned}\end{cases}$$
我们可以很轻易地得出,$SmoothWeight_i$的值在$Weight_i$不趋近于0的条件下,被限制在区间$[0.01,100]$内。
通过分析代码得知,游戏先生成一个$\left[0,\sum_{j=1}^{6}SmoothWeight_j\right)$范围内的随机数$RandNum$,然后令结果为第$i$行($i$为第一个使$\sum_{j=1}^{i}SmoothWeight_j\ge RandNum$的数,且当$\sum_{j=1}^{5}SmoothWeight_j<RandNum$时为6)。
由于$RandNum=0$(这导致抽到第一行的概率稍大)的概率趋近于0,再忽略$RandNum$无法取到$\sum_{j=1}^{6}SmoothWeight_j$(这有时会导致抽到第六行的概率稍小)造成的微小误差,我们可以得出,对于第$i$行,抽取到该行的概率$P_i$为:
$$P_i=\begin{cases}\begin{aligned} 0 & ,\quad \text{if}\ \ i\neq 6\ \ \text{and} \ \sum_{j=1}^{6}SmoothWeight_j=0\\\\ \frac{SmoothWeight_i}{\sum_{j=1}^{6}SmoothWeight_j} & ,\quad \text{if}\ \ i\neq 6\ \ \text{and} \ \sum_{j=1}^{6}SmoothWeight_j\neq 0\\\\ 1-\sum_{j=1}^{5}P_j & ,\quad \text{if}\ \ i=6 \end{aligned}\end{cases}$$
不难发现,在总权值为0的时候会在第6行出怪;如果前5行概率均为0的时候也会选择在第6行出怪;当所有行权重相等,且均未出过怪的时候,每行出怪概率相等,符合基本的要求。
合法行
对于一种僵尸,如果僵尸出现在这行是符合游戏规则的,那么这行对于这种僵尸就是合法行。
通常地,如果满足下列任意条件,那么该行不合法:
- 行大于6或者小于1
- 无草皮之地关卡外的裸地行
- 非泳池浓雾关卡(包含无草皮之地)的第6行
- 无草皮之地关卡的第1行与第5行
特别地,对于一些僵尸,有额外的不合法判定方法:
- 高地行11)类型对冰车僵尸与雪橇队僵尸不合法
- 水路对普僵、旗帜、路障、铁桶、潜水、海豚、气球、植物僵尸以外的僵尸不合法
- 水路(波数小于5)对海豚、潜水以外的僵尸不合法(谁笑到最后关卡的波数需加上10*轮数)
- 非水路对于海豚僵尸与潜水僵尸不合法
- 冰道消失倒计时为0的行(冰道长度为0,但是倒计时不为0不算,是合法的),雪橇小队僵尸不合法
- 非无尽关卡的第1行对于白眼、红眼不合法
- 非后院场合,上下有任意一行不满足如下条件的对舞王僵尸不合法
- 为草地
- 行不大于6且不小于1
注:无草皮之地的裸地对舞王僵尸合法。
选取出怪行的流程
对于选择僵尸出怪的行,游戏将依次计算钉耙、行类型、保护传送门、隐形食脑者、最后一波、推车、权重,最后得出结果。
对于选取好的僵尸,选取出怪行按以下操作:
- 若场上有钉耙,获取编号12)最小的钉耙并执行以下流程,否则跳过钉耙
- 钉耙所在行对于该僵尸类型是否合法,若不合法,则跳过钉耙
- 若钉耙和僵尸绑定过(即使曾经与之绑定的僵尸消失),则跳过钉耙
- 将钉耙标记为已绑定,插入钉耙行,返回钉耙行行直接结束出怪计算
先依次计算每行的权重,对于第$i$行,流程如下:
- 若该行对于该僵尸类型不合法,令$Weight_i=0$并结束本行运算;
- 若为保护传送门关卡则进行以下计算:
- 若本行有传送门且传送门目标传送门距离小推车最近距离小于5(若没有小推车,则判断是否小于10),令$Weight_i=0.01$并结束本行运算;
- 若本行有传送门且不满足上述距离关系,令$Weight_i=1$并结束本行运算;
- 若本行无传送门,令$Weight_i=0.2$并结束本行运算。
- 若为隐形食脑者关卡,当前波数小于等于3且$i=5$,令$Weight_i=0$并结束本行运算;
- 若本关不为无限波数关卡(包含老虎机,宝石迷阵,看星星,宝石迷阵转转看,坚果保龄球艺术锦标赛,种太阳花的艺术,松鼠),且当本次出怪为最后一波时,令$Weight_i=1$并结束本行运算;
- 定义整数$MowerTest$ = 当前波数 - 第$i$行上次丢车的波数;
- 若$MowerTest \le 1$,则令$Weight_i=0.01$并结束本行运算;
- 若$1<MowerTest \le 2$,则令$Weight_i=0.50$并结束本行运算。
所有行计算完毕后,按抽取行原则选取行,然后插入行并返回结果行。
实验数据
游戏的一次实验可以证明该理论的准确性。
我们固定每次的LastPicked
与SecondPicked
,然后抽取一亿次出怪行,统计并分析数据可得:
行数 | 权重 | LastPicked | SecondPicked | 平滑权重 | 概率 | 理论个数 | 实际个数 | 误差率 |
---|---|---|---|---|---|---|---|---|
1 | 1 | 0 | 0 | 0.0029 | 0.009 | 972095 | 972657 | +0.058% |
2 | 1 | 2 | 0 | 0.1168 | 0.386 | 38597896 | 38597762 | +0.000% |
3 | 1 | 2 | 3 | 0.1817 | 0.600 | 60041171 | 60042656 | +0.002% |
4 | 0.2 | 2 | 3 | 0.0006 | 0.002 | 194419 | 193522 | -0.461% |
5 | 0 | 2 | 3 | 0.0000 | 0.000 | 0 | 0 | +0.000% |
6 | 0.2 | 2 | 3 | 0.0006 | 0.002 | 194419 | 193403 | -0.523% |
可以发现误差足够小,则我们可以认为该理论可以准确预测僵尸出怪情况。
一些推论
推论1:僵尸没有可出行时出现在第六行
首先,当僵尸没有可选出怪行时,所有行的权重均赋值为0,故在抽取行时,所有行的平均权重均为0,按概率计算公式,有$P_6=1-\sum_{j=1}^{5}P_j$
所有行的权重为0,则有$P_1=P_2=P_3=P_4=P_5=0$
易得$P_6=1$
所以此时该僵尸一定会在6路出现。
推论2:在样本量足够大的情况下,平均概率仅与权重有关
在一次实验中,对于一亿次出怪,我们获得了这样一组数据:
行 | 权重 | WeightP | 个数 | 频率 |
---|---|---|---|---|
1 | 1.0 | 0.294 | 29549753 | 0.295 |
2 | 1.0 | 0.294 | 29548796 | 0.295 |
3 | 1.0 | 0.294 | 29550658 | 0.296 |
4 | 0.2 | 0.059 | 5675859 | 0.057 |
5 | 0.0 | 0.000 | 0 | 0.000 |
6 | 0.2 | 0.059 | 5674934 | 0.057 |
以频率估计概率,可以认为平均概率为WeightP
。
因此,在作全局分析时,可以忽略LastPicked
与SecondPicked
带来的影响。
推论3:在样本量足够大的情况下,LastPickedi
和SecondLastPickedi
仅与行被选中的顺序有关
推论2被验证后,推论3是显然的。
评论
这里为什么2~5行的
SecondLastPicked
都是0呢?不在本行出怪时不是应该都+1吗?辛苦了!
谢太宗认可。