两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 |
技术:出怪机制 [2022/12/20 03:30] – OTZzzz | 技术:出怪机制 [2025/02/22 19:23] (当前版本) – [选取出怪行的流程] 111.16.87.152 |
---|
/* 以上为所有页面共用的排版格式,请勿删除噢。 */ | /* 以上为所有页面共用的排版格式,请勿删除噢。 */ |
~~SNIPPET_C~~snippet:通用排版~~ | ~~SNIPPET_C~~snippet:通用排版~~ |
| |
| |
| ~~SNIPPET_O1741900321~~snippet:优秀条目~~ |
| {{tag>[优秀条目]}} |
| <WRAP center round tip note> |
| 经OP鉴定,本词条内容清晰,排版优美,是值得参考的优秀范例。 |
| </WRAP> |
| ~~SNIPPET_C~~snippet:优秀条目~~ |
| |
| |
~~SNIPPET_O1741900321~~snippet:引自外部~~ | ~~SNIPPET_O1741900321~~snippet:引自外部~~ |
本条目主要讲解生存无尽模式中僵尸的生成算法与随机原理。 | 本条目主要讲解生存无尽模式中僵尸的生成算法与随机原理。 |
| |
| =====出生点===== |
| |
| 出生点指僵尸生成时的x坐标。(([[https://crescb.com/timespace/ts/index.html|现代遗留问题清算——这个世界的时空。]])) |
| |
| ^ 僵尸 ^ 普通波出生点 ^ 旗帜波出生点 ^ |
| | 旗帜 | - | 800 | |
| | 冰车 | 800~809 || |
| | 投篮 | 825~834 || |
| | 白眼、红眼 | 845~854 || |
| | 撑杆 | 870~879 || |
| | 雪橇 | 880~1030 || |
| | 所有其他僵尸 | 780~819 | 820~859 | |
===== 出怪类型 ===== | ===== 出怪类型 ===== |
| |
[[[6a9ec0] +768] +561c] // 出怪种子 | [[[6a9ec0] +768] +561c] // 出怪种子 |
[[[[6a9ec0] +768] +160] +6c] * 65 // 完成选卡次数 * 101 | [[[[6a9ec0] +768] +160] +6c] * 65 // 完成选卡次数 * 101 |
[[6a9ec0] +7f8] // [[教程:名词大全#序号-2|游戏模式]] | [[6a9ec0] +7f8] // 游戏模式 |
</code> | </code> |
| |
===== 出怪概率 ===== | ===== 出怪概率 ===== |
| |
以下表格列出了不同轮数下,各僵尸出现在出怪类型中的概率,以及出怪类型中僵尸总数((普僵与鸭子计一种,不计旗帜(固定生成)、雪人(极小概率随机生存)))各取值的概率。(([[https://tieba.baidu.com/p/5714350581|无尽生存僵尸出现概率统计]])) | 以下表格列出了不同轮数下,各僵尸出现在出怪类型中的概率,以及出怪类型中僵尸总数((普僵与鸭子计一种,不计旗帜(固定生成)、雪人(极小概率随机生成)))各取值的概率。(([[https://tieba.baidu.com/p/5714350581|无尽生存僵尸出现概率统计]])) |
| |
''轮数=1'': | ''轮数=1'': |
* ''b*(a-b)*2/(a*(a-1))'' | * ''b*(a-b)*2/(a*(a-1))'' |
* ''(a-b)*(a-b-1)/(a*(a-1))'' | * ''(a-b)*(a-b-1)/(a*(a-1))'' |
六大场地的''a''值分别为18/17/20/20/16/16,''b''值在''轮数≥8''时取值为9。 | ''轮数≥5''时,六大场地的''a''值分别为18/17/20/20/16/16;''轮数≥8''时,''b''为9。 |
</callout> | </callout> |
| |
^ 序号 ^ 简称 ^ 级别 ^ 权重 ^ 备注 | | ^ 序号 ^ 简称 ^ 级别 ^ 权重 ^ 备注 | |
| 0 | 普僵 | 1 | 4000 | ''轮数=5''起每轮-180,''轮数=25''起固定为400 | | | 0 | 普僵 | 1 | 4000 | ''轮数=5''起每轮-180,''轮数=25''起固定为400 | |
| 1 | 旗帜 | 1 | 0 | 在旗帜波固定出现,不参与随机过程 | | | 1 | 旗帜 | 1 | 0 | 无需出怪类型准许亦可生成,每个旗帜波有且仅有一只 | |
| 2 | 路障 | 2 | 4000 | ''轮数=5''起每轮-150,''轮数=25''起固定为1000 | | | 2 | 路障 | 2 | 4000 | ''轮数=5''起每轮-150,''轮数=25''起固定为1000 | |
| 3 | 撑杆 | 2 | 2000 | | | | 3 | 撑杆 | 2 | 2000 | | |
| |
从不同角度可以得到不同的饱和f数: | 从不同角度可以得到不同的饱和f数: |
* 第47f起,阶数不再起限制作用 | * 第**47f**起,阶数不再起限制作用 |
* 第85f起,级别上限在统计意义上不再起限制作用 | * 第**85f**起,级别上限在统计意义上不再起限制作用 |
* 第109f起,红眼数量上限不再起限制作用 | * 第**109f**起,红眼数量上限不再起限制作用 |
* 第126f起,级别上限在严格意义上不再起限制作用 | * 第**126f**起,级别上限在严格意义上不再起限制作用 |
| |
| |
又称**第j行插入事件**。 | 又称**第j行插入事件**。 |
| |
为了避免某行僵尸过多,当某一行出怪,游戏会减少改行出怪的概率,提高其他行的出怪概率<wrap lo>(设想一下,如果让一个人将一堆金币平均分给几个人,但是这几个人没有顺序,也只能抽取,那么这个发金币的人肯定更倾向于发给金币更少的人)</wrap> | 为了避免某行僵尸过多,当某一行出怪,游戏会减少该行出怪的概率,提高其他行的出怪概率<wrap lo>(设想一下,如果让一个人将一堆金币平均分给几个人,但是这几个人没有顺序,也只能抽取,那么这个发金币的人肯定更倾向于发给金币更少的人)</wrap> |
| |
执行第j行插入事件时,会发生如下变化: | 执行第j行插入事件时,会发生如下变化: |
1. 将第i行出怪权重在总权重的占比称之为,则有: | 1. 将第i行出怪权重在总权重的占比称之为,则有: |
| |
{{:技术:pasted:20221220-031546.png}} | $$WeightP_i=\frac{Weight_i}{\sum_{j=1}^{6}Weight_j}$$ |
| |
将''LastPicked<fs x-small>i</fs>''对结果的影响因子称为''PLast<fs x-small>i</fs>'',再将''SecondLastPicked<fs x-small>i</fs>''对结果的影响因子称为''PSecondLast<fs x-small>i</fs>'',通过查阅代码我们知道,它们的计算公式是: | 将''LastPicked<fs x-small>i</fs>''对结果的影响因子称为''PLast<fs x-small>i</fs>'',再将''SecondLastPicked<fs x-small>i</fs>''对结果的影响因子称为''PSecondLast<fs x-small>i</fs>'',通过查阅代码我们知道,它们的计算公式是: |
| |
{{:技术:pasted:20221220-031722.png}} | $$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}$$ |
| |
最后获得平滑权重的计算公式如下: | 最后获得平滑权重的计算公式如下: |
| |
{{:技术:pasted:20221220-031732.png}} | $$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}$$ |
| |
{{:技术:pasted:20221220-031740.png}} | 我们可以很轻易地得出,$SmoothWeight_i$的值在$Weight_i$不趋近于0的条件下,被限制在区间$[0.01,100]$内。 |
| |
{{:技术:pasted:20221220-031814.png}} | 通过分析代码得知,游戏先生成一个$\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)。 |
| |
{{:技术:pasted:20221220-031938.png}} | 由于$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行出怪;当所有行权重相等,且均未出过怪的时候,每行出怪概率相等,符合基本的要求。 | 不难发现,在总权值为0的时候会在第6行出怪;如果前5行概率均为0的时候也会选择在第6行出怪;当所有行权重相等,且均未出过怪的时候,每行出怪概率相等,符合基本的要求。 |
- 无草皮之地关卡外的裸地行 | - 无草皮之地关卡外的裸地行 |
- 非泳池浓雾关卡(包含无草皮之地)的第6行 | - 非泳池浓雾关卡(包含无草皮之地)的第6行 |
- 无草地之地关卡的第1行与第5行 | - 无草皮之地关卡的第1行与第5行 |
| |
特别地,对于一些僵尸,有额外的不合法判定方法: | 特别地,对于一些僵尸,有额外的不合法判定方法: |
* 将钉耙标记为已绑定,插入钉耙行,返回钉耙行行直接结束出怪计算 | * 将钉耙标记为已绑定,插入钉耙行,返回钉耙行行直接结束出怪计算 |
| |
先依次计算每行的权重,对于第i行,流程如下: | 先依次计算每行的权重,对于第$i$行,流程如下: |
| |
{{:技术:pasted:20221220-032900.png}} | |
| |
| - 若该行对于该僵尸类型不合法,令$Weight_i=0$并结束本行运算; |
| - 若为保护传送门关卡则进行以下计算: |
| - 若本行有传送门且传送门目标传送门距离小推车最近距离小于5(若没有小推车,则判断是否小于10),令$Weight_i=0.01$并结束本行运算; |
| - 若本行有传送门且不满足上述距离关系,令$Weight_i=1$并结束本行运算; |
| - 若本行无传送门,令$Weight_i=0.2$并结束本行运算。 |
| - 若为隐形食脑者关卡,当前波数小于等于3且$i=6$,令$Weight_i=0$并结束本行运算; |
| - 若本关不为无限波数关卡(包含老虎机,宝石迷阵,看星星,宝石迷阵转转看,坚果保龄球艺术锦标赛,种太阳花的艺术,松鼠),且当本次出怪为最后一波时,令$Weight_i=1$并结束本行运算; |
| - 定义整数$MowerTest$ = 当前波数 - 第$i$行上次丢车的波数; |
| - 若$MowerTest \le 1$,则令$Weight_i=0.01$并结束本行运算; |
| - 若$1<MowerTest \le 2$,则令$Weight_i=0.50$并结束本行运算; |
| - 若上述条件均不满足,令$Weight_i=1$并结束本行运算。 |
所有行计算完毕后,按抽取行原则选取行,然后插入行并返回结果行。 | 所有行计算完毕后,按抽取行原则选取行,然后插入行并返回结果行。 |
| |
| ==== 实验数据 ==== |
| |
{{:技术:pasted:20221220-032909.png}} | 游戏的一次实验可以证明该理论的准确性。 |
| |
| 我们固定每次的''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:僵尸没有可出行时出现在第六行 | **推论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:在样本量足够大的情况下,平均概率仅与权重有关** |
| |
| 在一次实验中,对于一亿次出怪,我们获得了这样一组数据: |
| |
{{:技术:pasted:20221220-032938.png}} | ^ 行 ^ 权重 ^ 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 | |
| |
推论2:在样本量足够大的情况下,平均概率仅与权重有关 | 以频率估计概率,可以认为平均概率为''WeightP''。 |
| |
{{:技术:pasted:20221220-032945.png}} | 因此,在作全局分析时,可以忽略''LastPicked''与''SecondPicked''带来的影响。 |
| |
推论3:在样本量足够大的情况下,''LastPicked<fs x-small>i</fs>''和''SecondLastPicked<fs x-small>i</fs>''仅与行被选中的顺序有关 | **推论3:在样本量足够大的情况下,''LastPicked<fs x-small>i</fs>''和''SecondLastPicked<fs x-small>i</fs>''仅与行被选中的顺序有关** |
| |
推论2被验证后,推论3是显然的。 | 推论2被验证后,推论3是显然的。 |