目录

经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)

  1. 设定要出普僵
  2. 产生一个0~4的伪随机整数(后文详解),若等于0则设定要出读报,否则设定要出路障3)
  3. 轮数<8,则设定剩余出怪类型数为轮数+1,否则设定剩余出怪类型数为9
  4. 产生一个0~33的伪随机整数,若未设定要出此类僵尸且没有禁止出此类僵尸4),则设定要出此类僵尸并进入第5步,否则重复第4步
  5. 若第4步中已设定要出的僵尸类型数等于第3步的剩余出怪类型数,则进入第6步,否则重复第4步
  6. 忽略摇旗、僵博,即强制设为false5)

轮数

轮数即选卡时已完成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数:

出怪选行

不要强行认字

理解以下内容需要一定的数学知识。

出怪行信息

对于第i行,有权重、上次选择、上上次选择三个信息。

权重用于计算出怪内容,之前出怪用于计算出怪概率。

作如下定义:

LastPickediSecondLastPickedi的初始值为0。

某一行出怪时

又称第j行插入事件

为了避免某行僵尸过多,当某一行出怪,游戏会减少该行出怪的概率,提高其他行的出怪概率(设想一下,如果让一个人将一堆金币平均分给几个人,但是这几个人没有顺序,也只能抽取,那么这个发金币的人肯定更倾向于发给金币更少的人)

执行第j行插入事件时,会发生如下变化:

  1. ∀i∈[1,6],如果Weighti>0,则LastPickediSecondLastPickedi均增加1
  2. LastPickedj的值赋给SecondLastPickedj
  3. LastPickedj设为0

计算示例

示例结果

用文字语言来解释的话,即如果某一行发生出怪,则所有行的上次和上上次被选取增加1,然后本行距离上次被选取(即当次选取)为0,上上次被选取改为上次被选取。

如按(3,4,1,2,5,1)的行顺序出怪后,结果如右(不考虑第6行)。

选取某次出怪的行

又称抽取行事件

将受到LastPickediSecondLastPickedi影响后的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行出怪;当所有行权重相等,且均未出过怪的时候,每行出怪概率相等,符合基本的要求。

合法行

对于一种僵尸,如果僵尸出现在这行是符合游戏规则的,那么这行对于这种僵尸就是合法行。

通常地,如果满足下列任意条件,那么该行不合法:

  1. 行大于6或者小于1
  2. 无草皮之地关卡外的裸地行
  3. 非泳池浓雾关卡(包含无草皮之地)的第6行
  4. 无草皮之地关卡的第1行与第5行

特别地,对于一些僵尸,有额外的不合法判定方法:

  1. 高地行11)类型对冰车僵尸与雪橇队僵尸不合法
  2. 水路对普僵、旗帜、路障、铁桶、潜水、海豚、气球、植物僵尸以外的僵尸不合法
  3. 水路(波数小于5)对海豚、潜水以外的僵尸不合法(谁笑到最后关卡的波数需加上10*轮数)
  4. 非水路对于海豚僵尸与潜水僵尸不合法
  5. 冰道消失倒计时为0的行(冰道长度为0,但是倒计时不为0不算,是合法的),雪橇小队僵尸不合法
  6. 非无尽关卡的第1行对于白眼、红眼不合法
  7. 非后院场合,上下有任意一行不满足如下条件的对舞王僵尸不合法
    1. 为草地
    2. 行不大于6且不小于1

注:无草皮之地的裸地对舞王僵尸合法。

选取出怪行的流程

对于选择僵尸出怪的行,游戏将依次计算钉耙、行类型、保护传送门、隐形食脑者、最后一波、推车、权重,最后得出结果。

对于选取好的僵尸,选取出怪行按以下操作:

先依次计算每行的权重,对于第$i$行,流程如下:

  1. 若该行对于该僵尸类型不合法,令$Weight_i=0$并结束本行运算;
  2. 若为保护传送门关卡则进行以下计算:
    1. 若本行有传送门且传送门目标传送门距离小推车最近距离小于5(若没有小推车,则判断是否小于10),令$Weight_i=0.01$并结束本行运算;
    2. 若本行有传送门且不满足上述距离关系,令$Weight_i=1$并结束本行运算;
    3. 若本行无传送门,令$Weight_i=0.2$并结束本行运算。
  3. 若为隐形食脑者关卡,当前波数小于等于3且$i=5$,令$Weight_i=0$并结束本行运算;
  4. 若本关不为无限波数关卡(包含老虎机,宝石迷阵,看星星,宝石迷阵转转看,坚果保龄球艺术锦标赛,种太阳花的艺术,松鼠),且当本次出怪为最后一波时,令$Weight_i=1$并结束本行运算;
  5. 定义整数$MowerTest$ = 当前波数 - 第$i$行上次丢车的波数;
  6. 若$MowerTest \le 1$,则令$Weight_i=0.01$并结束本行运算;
  7. 若$1<MowerTest \le 2$,则令$Weight_i=0.50$并结束本行运算。

所有行计算完毕后,按抽取行原则选取行,然后插入行并返回结果行。

实验数据

游戏的一次实验可以证明该理论的准确性。

我们固定每次的LastPickedSecondPicked,然后抽取一亿次出怪行,统计并分析数据可得:

行数 权重 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

因此,在作全局分析时,可以忽略LastPickedSecondPicked带来的影响。

推论3:在样本量足够大的情况下,LastPickediSecondLastPickedi仅与行被选中的顺序有关

推论2被验证后,推论3是显然的。

3)
此处读报和路障中未被选中者,仍有可能在后面的步骤中被选中,因而“读报路障不同出”系谣言
4)
伴舞/鸭子/雪橇/雪人/小鬼、植物僵尸、黑夜的冰车、非后院的潜水/海豚、屋顶的舞王/矿工、轮数<2时的冰车/白眼、轮数<5时的红眼
5)
若均未选中,为常规“11怪”;若选中其一,为“10怪”;若均选中,为“9怪”
6)
普僵与鸭子计一种,不计旗帜(固定生成)、雪人(极小概率随机生成)
9)
以内存值为准,实际有调整的标于备注
11)
正式版废除了高地行,故无需考虑;高低行在游戏中行类型为3
12)
即栈位