跳到正文

进化神器的选择遵循可复现的打乱序列。在记录的验证中,相同初始条件产生相同结果;游玩前固定的预测也与随后检查的结果吻合。候选列表、种植顺序与预览过程共同解释了这一现象。

本文的目录计数来自 4.2.4.399 版本,在 4.2.2 版本中捕获的计数均已注明。计算器使用 4.2.4 版本的植物数据;该数据由参考实现根据 Android 安装包生成,与 iOS 4.2.4.399 的声明一致。

选择背后的可重复序列

选择器建立有序候选列表,打乱整个列表,再取第一株植物。它使用库中的双参数 std::random_shuffle,背后的 mt19937 引擎从种子 5489 开始。捕获的原始输出与完整排列可以从该状态回放。11独立的 libc++ 打乱随机流导入的 __rs_get 与 __rs_default 符号标识双参数 std::random_shuffle。前向排列通过带拒绝采样的 uniform_int_distribution 取值。PlayCover 实时捕获记录了匹配种子 5489 的 mt19937 原始输出、完整排列与选择;宿主库检查属于独立证据。记录的 iPad 结果印证指定路线,但未识别 iPad 加载的库。进化与摩登传送门共享该库随机流。0x1009a92800x1001210440x10001bf38

引擎属于进程。完全重启游戏会让它回到初始序列。此前的打乱会推进其状态,包括神器界面上的进化神器预览。进入关卡也可能推进它:若关卡的波次列表包含生成墓碑的波次动作,关卡加载时会按波次顺序用同一引擎把每个动作的墓碑袋各打乱一次,计算器的关卡描述记录了这些墓碑袋的大小。22进入关卡时打乱墓碑袋在 4.2.4 可执行文件中,加载关卡会按波次顺序构建波次列表引用的每个生成墓碑的波次动作,并在与神器相同的引擎上,对一个把每个池条目按 Count 重复的向量执行库打乱。三次全新启动后的捕获完全匹配:黑暗时代第 21 关(墓碑袋 10、10、10)从偏移 0 消耗 42 次输出;黑暗时代第 19 关(墓碑袋 3、6、3)从偏移 0 消耗 10 次输出,在两次预览之后消耗 9 次;更早的黑暗时代第 4 关捕获(墓碑袋 3、3、4)消耗 8 次。重复声明的别名解析为第一个声明,未被任何波次引用的动作不会构建。这些进关之后的每次选择,包括一次涉及 4 个对象的气流水仙花行打乱,都与模型一致。重开此类关卡是否重复这些打乱尚未测量。0x101bc92fc0x1004009d0 在记录的检查中,没有此类动作的关卡在进入或重开时既未推进也未重置引擎,因此记录中的直接进关路线从预览及进关打乱结束后的状态开始。33捕获的预览结构与消耗量最初消耗为 50 的 4.2.2 版本 1 阶捕获记录了九次含 226 项的打乱,从偏移 0 开始消耗 2,874 次输出。后续两次消耗为 47 的 4.2.2 展示棋盘捕获保留了 153 次选择与 36,152 次输出,包括两次气流水仙花行打乱及植物添加顺序。其中一次记录全新启动后的混合路线;另一次从第 10–11 次预览开始,此前反馈已完成九次预览,其起始偏移由模型重建。实机检查区分了空莲叶与植物对象,并确认了行打乱中的拒绝采样。在测得的路线上,不含生成墓碑波次动作的关卡在进入与重开时均未消耗库输出;含有此类动作的关卡见注 25。0x1009a73800x1009a92800x1009a7138

伪随机算法本身可以正常发挥作用,而不暴露可预测的序列。这里的固定初始状态与共享预览历史,使记录中的结果能够事先复现。问题比偶尔连续得到同一种植物更具体。

预测结果或寻找种植方案 →

每株初始植物都有自己的候选列表

注册表的顺序很重要。PlantTypeOrder 中配置的名称在前,其余类型按所观察到的全新加载顺序排列。即使随机输出完全相同,按声明顺序打乱相同的一组植物,也可能选出不同结果。44注册表顺序与存活对象登记顺序注册表重建先添加 PlantTypeOrder 配置名称,再按无符号句柄顺序添加剩余弱句柄。在捕获的 4.2.2 版本全新加载中,尾部与声明顺序一致,全部 360 个启用条目匹配。存活槽分配器在头部插入,快照正向遍历。反转新种植物的顺序在前瞻验证中改变了目标遍历。移动、删除与恢复需要各自的登记历史。0x1000feec00x100100cd40x1036733f80x1036730300x1009a6b5c

七道目录筛选将 385 个植物定义缩减为 259 个。它们排除禁用类型、明确列出的别名、藤蔓类、英雄类型、parallel_ 类型、消耗型植物及神器结果黑名单。场景规则、关卡种子库禁用名单与源植物所在格的种植检查继续缩小列表。55七道目录筛选Enabled 默认为真。Enabled、四个硬编码别名、四个重写植物类、HeroProperties、parallel_ 前缀、IsConsumable 与 plantBlackList,将 385 个定义缩减为 259 个。导出数据保留筛选输入字段。成本、场景资格与逐格种植检查继续限制结果。场景虚函数对莲叶另有重写。0x1009a66400x1009a8b48

价格检查比较的是两个不同的量:

candidate declared cost>source effective cost.\text{candidate declared cost}>\text{source effective cost}.

源植物的有效价格可能包含等级调整、折扣及零下限。候选使用其声明的 Cost。因此,打折后的源植物可能变成标价低于其原始标价的植物。有效成本达到 500 或更高时,经过筛选的目录中没有更贵的候选,源植物保持不变。66源植物有效成本与候选声明成本源植物调用 PlantType 虚函数 +0x70,参数为 -2 和 0。基础路径应用模式价格、等级增量、折扣、倍率与零下限。候选直接读取 Cost 字段,要求 Cost > 源植物成本。筛选目录的最高值为 500,三个成员为 wintermelon、banana、cobcannon。空结果返回空句柄,逐植物流程不会创建移除特效。0x1009a88380x10183629c0x1009a8d840x1009a8f18

在计算器中,每株初始植物都带有自己的有效阳光成本。目标植物无需设置成本,因为候选按声明成本比较。有效成本落在相同两个候选成本之间的初始植物共用一个候选池,搜索把它们视为同一选项。其他成本档的植物为搜索提供更多选项,包括高于目标成本的档:它们的候选池无法变出目标,却能以不同的消耗量推进随机序列。搜索从最短的预览路线开始尝试。若它检查完上限内的所有路线仍未找到方案,且内存上限没有中止任何搜索,则这些路线和初始植物不存在方案。

格子条件同样重要。在 4.2.2 版本捕获的回忆之旅配置中,有效源成本为 0 时:

源植物所在格候选数
普通地面239
没有莲叶的干燥沙滩240
水面莲叶上233
被潮水覆盖且没有莲叶17

这些数量对应这一关卡与成本。干燥沙滩允许莲叶;站在莲叶上的植物使用莲叶的限制,无论沙滩是否被潮水覆盖,其中包括排除仙人掌。在该次捕获中,没有莲叶的被淹格子,其候选池与声明的 CanLiveOnWaves 标志吻合。装备水面或天空增益可以改变后一条规则。玉米加农炮与复活萝卜还有额外的战场前置条件,因此它们在全新普通布置中被排除,并不等于在所有情况下被禁用。77测得的格子候选池与潮水覆盖规则候选列表在打乱前被捕获。地面、沙滩、莲叶与栈道规则是在记录布置下测得的效果,并非对所有种植谓词的完整重建。分别在干燥沙滩与水面上的沙滩检查中,成本为 0 的莲叶候选池完全相同。仙人掌出现在地面池中,但在莲叶池中缺失;较早的回忆之旅关卡已禁用仙人掌,因此无法据此判断其莲叶资格。潮水覆盖规则允许 CanLiveOnWaves、挂件增益 17 或 40,或受支持的格子对象。捕获的无增益池遵循声明标志。玉米加农炮需要相邻玉米投手;复活萝卜需要有效的复活记录。0x1015976180x1013cd58c0x101afc2380x1020c1170

种植顺序把抽取结果对应到格子

主动技能收集与 3×3 区域重叠的合格植物。新登记的植物对象插入存活对象链表的头部,目标查询沿该链表正向遍历。因此,对于新种下的源植物,最后种下的会最先处理。4

在记录的埃及 13 关试验中,反转种植顺序也反转了各格获得的选择结果。这是登记顺序,并非从棋盘某个角落开始的固定扫描。移动或恢复已有植物时,需要知道其实际登记历史。

每株被处理的源植物都会消耗其自身候选列表完整打乱所需的输出。改变成本或格子条件,可能改变列表长度、结果及后续源植物继承的随机流位置。空列表会保留源植物,不消耗打乱输出。

预览推进同一随机流

预览在神器界面的展示棋盘上执行同一个施放过程,中心为 4-2。1 阶预览先在第 3–5 列、第 1–3 行种下九株向日葵。它们的实际阳光消耗会影响结果:在捕获的 4.2.2 数据中,消耗 50 对应 226 项进化候选,全新启动后的首次预览消耗 2,874 次输出;消耗 47 则对应 243 项候选和 3,115 次输出。在计算器中,预览向日葵的消耗与关内原植物的消耗分开设置。3

4 阶预览先在第 3 列种下三株向日葵,按新到旧的顺序进化,再为每株选择下方的莲叶,并在第 4–5 列逐列向下选择六株额外生成植物。捕获的 4.2.2 生成池有 55 项;单项莲叶选择不消耗输出。放置按选择的逆序执行,先出现的莲叶可能拒绝选中的替换植物,留下空莲叶。后续展示棋盘捕获已记录这些格子与植物添加顺序。

放置气流水仙花还会用同一个引擎打乱本行的植物对象。计数不含莲叶,包含气流水仙花自身,并反映此前已移除的原植物与已放置的新植物。拒绝采样可能额外消耗输出,因此计算器回放这次打乱,而不是加上固定偏移。预览的结束位置包含这些效果;关内施放报告的结束位置只涵盖选择阶段,因为后续效果和其他事件还需要完整的关卡状态。3

记录中的前瞻验证涵盖反转种植顺序的埃及 13 关、埃及 8 关的预览路线、回忆之旅与潘妮追击中的指定结果,以及混合的 1 阶/4 阶预览序列。记录区分直接捕获的选择与反馈的结果;确认某株指定植物并不能证明所有未记录格子的结果。88前瞻验证确认了什么埃及 13 关反转种植顺序的试验在游玩前完成预测,并进行了仪器捕获。埃及 8 关、回忆之旅与潘妮追击保存的预测随后反馈为匹配;保留的结论针对指定格子。混合 1 阶/4 阶预览预测也反馈为匹配。这些不同于事后回放,不能证明任意路线、Android 或关卡内更高品阶的主动技能。0x1009a8b480x1009a9280

pvzreport/evolution-artifact 仓库 提供参考实现、关卡输入及记录的候选列表测试数据。网页计算器支持 1 阶与 4 阶预测和方案搜索、有序预览路线、候选池查看、上游全部 16 个关卡预设,以及未来世界无尽挑战预设。方案搜索按三种路线类型之一规划完全重启后运行的预览,并接续已完成的预览,返回最短的路线,其次是种植源植物最少的方案。自定义关卡描述可提供世界、尺寸、格子状态、种子库禁用名单与进关时打乱的墓碑袋。复现计算还需要一致的预览经历与源植物有效成本。

选择结果与替换植物是两个步骤

选择后创建的延迟特效携带选定类型、格子与原植物等级。在动画事件触发时,代码先移除旧植物,再检查替换植物能否种下。最终检查失败会跳过添加,且不会恢复源植物。99延后替换与不同的检查条件特效保存格位置、替换类型、动画名、原等级与旧植物弱引用。loop 事件先标记并杀死旧植物,再检查替换位置。选择时豁免阻止原因 79,最终检查不豁免任何原因。失败会跳过 AddPlant,此路径没有回滚。这一顺序来自原生指令追踪;选择器捕获未记录后续插入回调。其他源植物状态不通过该特效复制;AddPlant 可以从战场或存档取得新状态。0x1009a841c0x1009a981c0x1009a9b4c0x1009a9b8c

选择阶段豁免阻止原因 79,最终检查则不豁免。等待特效期间,战场状态也可能改变。空候选列表是另一种情况:它不创建移除特效,会保留原植物。

更高品阶还有其他规则

2 阶倍率读取函数使用含 26 个名称的 TargetablePlantTypes 白名单,描述却表达为 300 阳光门槛。十一种符合门槛的普通植物不在名单中。读取函数的成员检查与它最终如何影响植物属性,是两个不同的证据问题。1010三条独立被动路径两个 2 阶倍率读取函数查询含 26 项的 TargetablePlantTypes 白名单。3 阶计时器每次到期更新只推进一个间隔,并在行 0–4 中抽取。4 阶在延后移除之前扫描空格,选择 Cost <= 100 的植物。其等级归约从 1 开始取最小值,因此普通正值卡包等级无法将它提高。报告追踪的是倍率读取函数;通向最终植物数值的调用方需要另行对应。0x1009a77280x1009a78c00x1009a75d00x1009a6d1c0x1009a90b0

3 阶有定时生成植物的路径。4 阶在变换选择之后进行第二轮选择:在源植物仍占据格子时,按先沿列向下、再向右的顺序遍历裁剪到棋盘内的 3×3 区域。空格选择声明成本不超过 100 的合格额外植物。已占用的海岸或水面格可以选择在源植物下添加莲叶;这个单候选池不消耗随机输出。随后,特效按选择顺序的反序执行。先添加的莲叶可能阻止替换植物放置,同一格中的第二株莲叶也会被拒绝。计算器已建模这些选择与放置结果。11114 阶选择与放置冲突十三次 4.2.2 普通关卡捕获保留了 100 次选择和 10,437 次选择阶段随机输出,涵盖空区域、混合区域、棋盘边缘、墓碑、海盗木板、水面与莲叶。大多数偏移是在事后为回放重建的;两次沙滩补充试验使用游玩前固定的预测路线。补充记录显示植物添加顺序与选择顺序相反,并记录了已占用海岸格中的莲叶、重复莲叶被拒绝,以及支撑莲叶出现后仙人掌替换被拒绝的情况。放置比较排除了地形发生变化的格子。两次补充捕获还记录到选择结束后的额外随机输出,因此选择结束位置不能确定下一次施放的状态。黑暗时代第 4 天捕获的创建请求传入等级 -1;最终植物等级仍未确定。0x1009a6d1c0x1009a90b00x1009a841c0x1009a9b8c

追踪到的额外植物等级归约从 1 开始取最小值,但仅凭该步骤不能确定最终生成的植物等级。捕获的创建请求还传入过 -1。最终等级、定时被动生成,以及特效期间的地形变化均不在计算器的模型内。

进化神器参考页保留声明的公式与植物名单。

恢复不可预测的选择

游戏应当为进化神器的选择使用操作系统提供的随机性。

注释

每条论断的依据:代码路径,以及追踪到它的原生地址。

  1. 1

    独立的 libc++ 打乱随机流

    导入的 __rs_get 与 __rs_default 符号标识双参数 std::random_shuffle。前向排列通过带拒绝采样的 uniform_int_distribution 取值。PlayCover 实时捕获记录了匹配种子 5489 的 mt19937 原始输出、完整排列与选择;宿主库检查属于独立证据。记录的 iPad 结果印证指定路线,但未识别 iPad 加载的库。进化与摩登传送门共享该库随机流。

    0x1009a92800x1001210440x10001bf38
  2. 2

    进入关卡时打乱墓碑袋

    在 4.2.4 可执行文件中,加载关卡会按波次顺序构建波次列表引用的每个生成墓碑的波次动作,并在与神器相同的引擎上,对一个把每个池条目按 Count 重复的向量执行库打乱。三次全新启动后的捕获完全匹配:黑暗时代第 21 关(墓碑袋 10、10、10)从偏移 0 消耗 42 次输出;黑暗时代第 19 关(墓碑袋 3、6、3)从偏移 0 消耗 10 次输出,在两次预览之后消耗 9 次;更早的黑暗时代第 4 关捕获(墓碑袋 3、3、4)消耗 8 次。重复声明的别名解析为第一个声明,未被任何波次引用的动作不会构建。这些进关之后的每次选择,包括一次涉及 4 个对象的气流水仙花行打乱,都与模型一致。重开此类关卡是否重复这些打乱尚未测量。

    0x101bc92fc0x1004009d0
  3. 3

    捕获的预览结构与消耗量

    最初消耗为 50 的 4.2.2 版本 1 阶捕获记录了九次含 226 项的打乱,从偏移 0 开始消耗 2,874 次输出。后续两次消耗为 47 的 4.2.2 展示棋盘捕获保留了 153 次选择与 36,152 次输出,包括两次气流水仙花行打乱及植物添加顺序。其中一次记录全新启动后的混合路线;另一次从第 10–11 次预览开始,此前反馈已完成九次预览,其起始偏移由模型重建。实机检查区分了空莲叶与植物对象,并确认了行打乱中的拒绝采样。在测得的路线上,不含生成墓碑波次动作的关卡在进入与重开时均未消耗库输出;含有此类动作的关卡见注 25。

    0x1009a73800x1009a92800x1009a7138
  4. 4

    注册表顺序与存活对象登记顺序

    注册表重建先添加 PlantTypeOrder 配置名称,再按无符号句柄顺序添加剩余弱句柄。在捕获的 4.2.2 版本全新加载中,尾部与声明顺序一致,全部 360 个启用条目匹配。存活槽分配器在头部插入,快照正向遍历。反转新种植物的顺序在前瞻验证中改变了目标遍历。移动、删除与恢复需要各自的登记历史。

    0x1000feec00x100100cd40x1036733f80x1036730300x1009a6b5c
  5. 5

    七道目录筛选

    Enabled 默认为真。Enabled、四个硬编码别名、四个重写植物类、HeroProperties、parallel_ 前缀、IsConsumable 与 plantBlackList,将 385 个定义缩减为 259 个。导出数据保留筛选输入字段。成本、场景资格与逐格种植检查继续限制结果。场景虚函数对莲叶另有重写。

    0x1009a66400x1009a8b48
  6. 6

    源植物有效成本与候选声明成本

    源植物调用 PlantType 虚函数 +0x70,参数为 -2 和 0。基础路径应用模式价格、等级增量、折扣、倍率与零下限。候选直接读取 Cost 字段,要求 Cost > 源植物成本。筛选目录的最高值为 500,三个成员为 wintermelon、banana、cobcannon。空结果返回空句柄,逐植物流程不会创建移除特效。

    0x1009a88380x10183629c0x1009a8d840x1009a8f18
  7. 7

    测得的格子候选池与潮水覆盖规则

    候选列表在打乱前被捕获。地面、沙滩、莲叶与栈道规则是在记录布置下测得的效果,并非对所有种植谓词的完整重建。分别在干燥沙滩与水面上的沙滩检查中,成本为 0 的莲叶候选池完全相同。仙人掌出现在地面池中,但在莲叶池中缺失;较早的回忆之旅关卡已禁用仙人掌,因此无法据此判断其莲叶资格。潮水覆盖规则允许 CanLiveOnWaves、挂件增益 17 或 40,或受支持的格子对象。捕获的无增益池遵循声明标志。玉米加农炮需要相邻玉米投手;复活萝卜需要有效的复活记录。

    0x1015976180x1013cd58c0x101afc2380x1020c1170
  8. 8

    前瞻验证确认了什么

    埃及 13 关反转种植顺序的试验在游玩前完成预测,并进行了仪器捕获。埃及 8 关、回忆之旅与潘妮追击保存的预测随后反馈为匹配;保留的结论针对指定格子。混合 1 阶/4 阶预览预测也反馈为匹配。这些不同于事后回放,不能证明任意路线、Android 或关卡内更高品阶的主动技能。

    0x1009a8b480x1009a9280
  9. 9

    延后替换与不同的检查条件

    特效保存格位置、替换类型、动画名、原等级与旧植物弱引用。loop 事件先标记并杀死旧植物,再检查替换位置。选择时豁免阻止原因 79,最终检查不豁免任何原因。失败会跳过 AddPlant,此路径没有回滚。这一顺序来自原生指令追踪;选择器捕获未记录后续插入回调。其他源植物状态不通过该特效复制;AddPlant 可以从战场或存档取得新状态。

    0x1009a841c0x1009a981c0x1009a9b4c0x1009a9b8c
  10. 10

    三条独立被动路径

    两个 2 阶倍率读取函数查询含 26 项的 TargetablePlantTypes 白名单。3 阶计时器每次到期更新只推进一个间隔,并在行 0–4 中抽取。4 阶在延后移除之前扫描空格,选择 Cost <= 100 的植物。其等级归约从 1 开始取最小值,因此普通正值卡包等级无法将它提高。报告追踪的是倍率读取函数;通向最终植物数值的调用方需要另行对应。

    0x1009a77280x1009a78c00x1009a75d00x1009a6d1c0x1009a90b0
  11. 11

    4 阶选择与放置冲突

    十三次 4.2.2 普通关卡捕获保留了 100 次选择和 10,437 次选择阶段随机输出,涵盖空区域、混合区域、棋盘边缘、墓碑、海盗木板、水面与莲叶。大多数偏移是在事后为回放重建的;两次沙滩补充试验使用游玩前固定的预测路线。补充记录显示植物添加顺序与选择顺序相反,并记录了已占用海岸格中的莲叶、重复莲叶被拒绝,以及支撑莲叶出现后仙人掌替换被拒绝的情况。放置比较排除了地形发生变化的格子。两次补充捕获还记录到选择结束后的额外随机输出,因此选择结束位置不能确定下一次施放的状态。黑暗时代第 4 天捕获的创建请求传入等级 -1;最终植物等级仍未确定。

    0x1009a6d1c0x1009a90b00x1009a841c0x1009a9b8c