~~SNIPPET_O1670878323~~snippet:通用排版~~ /* 以上为所有页面共用的排版格式,请勿删除。 */ ~~SNIPPET_C~~snippet:通用排版~~ ~~SNIPPET_O1714376231~~snippet:优秀条目~~ {{tag>[优秀条目]}} 经OP鉴定,本词条内容清晰,排版优美,是值得参考的优秀范例。 ~~SNIPPET_C~~snippet:优秀条目~~ ~~SNIPPET_O1714376231~~snippet:引自外部~~ {{tag>[引自外部]}} 本条目部分或全部内容搬运自外部资源。 遵守[[https://creativecommons.org/licenses/by-sa/4.0/deed.zh|CC BY-SA 4.0协议]],部分内容可能有所改动。 ~~SNIPPET_C~~snippet:引自外部~~ 以下内容涉及较多精确数据,除非确信某处有误,否则请**谨慎修改**。 ======出怪机制====== /* 使用时请取消勾选【保持同步】,否则无法输入内容! */ [[https://pvz.tools/wiki/#%E5%87%BA%E6%80%AA%E8%A7%84%E5%BE%8B|植僵百科知识:出怪规律]] 本条目主要讲解生存无尽模式中僵尸的生成算法与随机原理。 =====出生点===== 出生点指僵尸生成时的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]+54d4]%%''开始的连续33个''bool''类型的地址,''true''代表准许,''false''代表不准许。 出怪类型的决定方式如下(([[https://tieba.baidu.com/p/2316788883|出怪种子到出怪类型的算法和示例代码]])): - 设定要出普僵 - 产生一个0~4的伪随机整数(后文详解),若等于0则设定要出读报,否则设定要出路障((此处读报和路障中未被选中者,仍有可能在后面的步骤中被选中,因而“读报路障不同出”系谣言)) - 若''**轮数**<8'',则设定剩余出怪类型数为''轮数+1'',否则设定剩余出怪类型数为9 - 产生一个0~33的伪随机整数,若未设定要出此类僵尸且没有禁止出此类僵尸((伴舞/鸭子/雪橇/雪人/小鬼、植物僵尸、黑夜的冰车、非后院的潜水/海豚、屋顶的舞王/矿工、''轮数<2''时的冰车/白眼、''轮数<5''时的红眼)),则设定要出此类僵尸并进入第5步,否则重复第4步 - 若第4步中已设定要出的僵尸类型数等于第3步的剩余出怪类型数,则进入第6步,否则重复第4步 - 忽略摇旗、僵博,即强制设为''false''((若均未选中,为常规“11怪”;若选中其一,为“10怪”;若均选中,为“9怪”)) 轮数即''选卡时已完成flag数/2-1''。 随机数生成器算法为[[https://baike.baidu.com/item/%E6%A2%85%E6%A3%AE%E6%97%8B%E8%BD%AC%E7%AE%97%E6%B3%95|MT19937]],种子由以下几个数值相加: [[[6a9ec0] +82c] +20] // 用户序号 [[[6a9ec0] +768] +561c] // 出怪种子 [[[[6a9ec0] +768] +160] +6c] * 65 // 完成选卡次数 * 101 [[6a9ec0] +7f8] // 游戏模式 ===== 出怪概率 ===== 以下表格列出了不同轮数下,各僵尸出现在出怪类型中的概率,以及出怪类型中僵尸总数((普僵与鸭子计一种,不计旗帜(固定生成)、雪人(极小概率随机生成)))各取值的概率。(([[https://tieba.baidu.com/p/5714350581|无尽生存僵尸出现概率统计]])) ''轮数=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) 完整的出怪列表长度2000(([[https://tieba.baidu.com/p/2306159144|这两天研究了一下PVZ的出怪机制]])),位于''%%[[[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]%%''。 各僵尸级别与权重一览((以内存值为准,实际有调整的标于备注)): ^ 序号 ^ 简称 ^ 级别 ^ 权重 ^ 备注 | | 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''并向零取整。 ==== 阶数 ==== 阶数决定了这个僵尸从第几波才会出现(([[https://tieba.baidu.com/p/7861483105|【无尽开局出怪规律科普】你知道多少轮以后出怪饱和吗?]]))。 |<100% 5em>| ^ 阶数 ^ 包含 ^ 限制 | | 一阶僵尸 | 普僵、路障、铁桶、读报、雪人 | 第1波开始就可以出现 | | 二阶僵尸 | 撑杆、铁门、橄榄、舞王 | 至少从第5波开始才可以出现 | | 三阶僵尸 | 潜水、海豚、冰车、小丑、气球、矿工、跳跳、梯子、投篮 | 至少从第10波开始才可以出现 | | 四阶僵尸 | 白眼、红眼 | 至少从第15波开始才可以出现,''轮数=9''起每轮-1,''轮数=23''起固定为1 | ==== 红眼数量上限 ==== 已生成的红眼总数达到红眼数量上限后,非旗帜波不再出红眼,立刻生效。 红眼数量上限初始为0,''轮数=5''起每轮+1,''轮数=54''起固定为50。 ===== 出怪难度饱和 ===== 出怪难度饱和指到达一定flags数后,游戏不再增加出怪算法难度的情况。该flags数阈值被称作“饱和f数”。 从不同角度可以得到不同的饱和f数: * 第**47f**起,阶数不再起限制作用 * 第**85f**起,级别上限在统计意义上不再起限制作用 * 第**109f**起,红眼数量上限不再起限制作用 * 第**126f**起,级别上限在严格意义上不再起限制作用 ===== 出怪选行 ===== /* 使用时请取消勾选【保持同步】,否则无法输入内容! */ [[https://tieba.baidu.com/p/8048386143|出怪论:出怪的选行]] 理解以下内容需要一定的数学知识。 ==== 出怪行信息 ==== 对于第i行,有权重、上次选择、上上次选择三个信息。 权重用于计算出怪内容,之前出怪用于计算出怪概率。 作如下定义: * 将第i行权重定义为''Weighti'' * 将第i行距离上次被选取定义为''LastPickedi'' * 将第i行距离上上次被选取定义为''SecondLastPickedi'' ''LastPickedi''和''SecondLastPickedi''的初始值为0。 ==== 某一行出怪时 ==== 又称**第j行插入事件**。 为了避免某行僵尸过多,当某一行出怪,游戏会减少改行出怪的概率,提高其他行的出怪概率(设想一下,如果让一个人将一堆金币平均分给几个人,但是这几个人没有顺序,也只能抽取,那么这个发金币的人肯定更倾向于发给金币更少的人) 执行第j行插入事件时,会发生如下变化: - ∀i∈[1,6],如果''Weighti>0'',则''LastPickedi''和''SecondLastPickedi''均增加1 - 将''LastPickedj''的值赋给''SecondLastPickedj'' - 将''LastPickedj''设为0 === 计算示例 === [{{ :技术:pasted:20221219-172750.png?350|示例结果}}] 用文字语言来解释的话,即如果某一行发生出怪,则所有行的上次和上上次被选取增加1,然后本行距离上次被选取(即当次选取)为0,上上次被选取改为上次被选取。 如按(3,4,1,2,5,1)的行顺序出怪后,结果如右(不考虑第6行)。 ==== 选取某次出怪的行 ==== 又称**抽取行事件**。 将受到''LastPickedi''和''SecondLastPickedi''影响后的''Weighti''称之为平滑权重,记为''SmoothWeighti''。 计算第i行的平滑权重的步骤如下: 1. 将第i行出怪权重在总权重的占比称之为,则有: {{:技术:pasted:20221220-031546.png}} 将''LastPickedi''对结果的影响因子称为''PLasti'',再将''SecondLastPickedi''对结果的影响因子称为''PSecondLasti'',通过查阅代码我们知道,它们的计算公式是: {{:技术:pasted:20221220-031722.png}} 最后获得平滑权重的计算公式如下: {{:技术:pasted:20221220-031732.png}} {{:技术:pasted:20221220-031740.png}} {{:技术:pasted:20221220-031814.png}} {{:技术:pasted:20221220-031938.png}} 不难发现,在总权值为0的时候会在第6行出怪;如果前5行概率均为0的时候也会选择在第6行出怪;当所有行权重相等,且均未出过怪的时候,每行出怪概率相等,符合基本的要求。 ==== 合法行 ==== 对于一种僵尸,如果僵尸出现在这行是符合游戏规则的,那么这行对于这种僵尸就是合法行。 通常地,如果满足下列任意条件,那么该行不合法: - 行大于6或者小于1 - 无草皮之地关卡外的裸地行 - 非泳池浓雾关卡(包含无草皮之地)的第6行 - 无草皮之地关卡的第1行与第5行 特别地,对于一些僵尸,有额外的不合法判定方法: - 高地行((正式版废除了高地行,故无需考虑;高低行在游戏中行类型为3))类型对冰车僵尸与雪橇队僵尸不合法 - 水路对普僵、旗帜、路障、铁桶、潜水、海豚、气球、植物僵尸以外的僵尸不合法 - 水路(波数小于5)对海豚、潜水以外的僵尸不合法(谁笑到最后关卡的波数需加上10*轮数) - 非水路对于海豚僵尸与潜水僵尸不合法 - 冰道消失倒计时为0的行(冰道长度为0,但是倒计时不为0不算,是合法的),雪橇小队僵尸不合法 - 非无尽关卡的第1行对于白眼、红眼不合法 - 非后院场合,上下有任意一行不满足如下条件的对舞王僵尸不合法 - 为草地 - 行不大于6且不小于1 注:无草皮之地的裸地对舞王僵尸合法。 ==== 选取出怪行的流程 ==== 对于选择僵尸出怪的行,游戏将依次计算钉耙、行类型、保护传送门、隐形食脑者、最后一波、推车、权重,最后得出结果。 对于选取好的僵尸,选取出怪行按以下操作: * 若场上有钉耙,获取编号((即栈位))最小的钉耙并执行以下流程,否则跳过钉耙 * 钉耙所在行对于该僵尸类型是否合法,若不合法,则跳过钉耙 * 若钉耙和僵尸绑定过(即使曾经与之绑定的僵尸消失),则跳过钉耙 * 将钉耙标记为已绑定,插入钉耙行,返回钉耙行行直接结束出怪计算 先依次计算每行的权重,对于第i行,流程如下: {{:技术:pasted:20221220-032900.png}} 所有行计算完毕后,按抽取行原则选取行,然后插入行并返回结果行。 ==== 实验数据 ==== {{:技术:pasted:20221220-032909.png}} ==== 一些推论 ==== 推论1:僵尸没有可出行时出现在第六行 {{:技术:pasted:20221220-032938.png}} 推论2:在样本量足够大的情况下,平均概率仅与权重有关 {{:技术:pasted:20221220-032945.png}} 推论3:在样本量足够大的情况下,''LastPickedi''和''SecondLastPickedi''仅与行被选中的顺序有关 推论2被验证后,推论3是显然的。