摘要

在游戏里,生物的攻击/防御面板数值 = 生物基础值 + 英雄的攻击/防御 + 其他效果(技能、宝物、状态等)。所以当同一兵种的面板数值在两次截图之间变化时,第一步应当看看英雄的数值是不是也变了。用户发现:SE(状态估计:把读到的观察累积成对局状态和对手构筑的推断)在解释“生物攻击 19→21”时,完全没有使用已经从战斗 HUD 读出的英雄属性历史,而且也没有任何测试覆盖这种基本情况。

本实验先写场景测试复现问题,再让 SE 的历史解释消费已有的英雄 HUD 读数,分别给出“生物变化 = 英雄变化 + 其他净变化”。在一局对电脑录像的已保存输入上,修复后的说明变为“英雄攻击 12→14(+2);生物攻击变化 +2 = 英雄 +2 + 其他 0”,并清楚标出其中一端用了“回溯假设”。

说明:本实验目录只有重放和显示脚本;报告写在 state_estimation 模块的文档里,本文据此整理。

要回答的问题

  1. 生物属性历史解释为什么没有用上英雄 HUD?这是缺测试还是实现漏了?
  2. 怎样在不看未来、不挑数值凑答案的前提下,为两个面板时点各选一个英雄读数?

数据与来源

  • 场景测试:通过公开 SE 入口构造的合成场景(下表)。
  • 真实回放:一局用户对官方电脑 AI 的训练录像(10 月 9 日 08:38)中,已保存的 8 帧自动视觉结果。没有手工改数、没有加入用户参考答案、没有重新 OCR。
媒体时刻 已保存自动观察
76.18 秒 准备页英雄攻击 11
92.2 秒 真菌伊利亚德攻击 19、防御 17;这一帧没有英雄 HUD(战术布阵阶段,画面上本来就没有)
98.40 秒 英雄攻击 12、防御 6
223.8 秒 同帧英雄 14/6、生物 21/17;资料基础 6/11

方法

根因: 不仅是缺测试——历史算法只比较生物面板,没有消费已读出的英雄 HUD 历史;已有的“我方英雄变化”字段只表示准备页与首次 HUD 的比较,不能代替战斗中的历史。

修改: 从已有的战场英雄主体收集属性历史,按我方/敌方传给历史解释器;对同方同兵种的相邻面板,分别解释攻击/防御的“生物变化、英雄变化、其他净变化”。只沿用已有的“基础 + 英雄”口径,不新增伤害公式或规则。输出仍是已有推断栏里的条件说明,请求/结果格式、原始观察、攻击条件、技能候选都不变。

英雄读数的选择顺序(固定,不以拟合为目标):

  1. 早面板先用同帧值;否则用此前最近的可读 HUD,标为“延续假设”。
  2. 没有此前读数时,可用早面板之后、晚面板之前的第一条 HUD,标为“回溯假设”。
  3. 晚面板优先同帧;否则只用两面板之间的最新读数。
  4. 不用晚面板之后的未来读数,不把晚面板值同时填两端,不从准备页补战场属性。
  5. 两端英雄身份必须已读且一致;区间内读到另一个英雄身份就阻断分解。
  6. 两端实际选到同一条中间 HUD 时,不输出看似两次独立观察的数值分解。

设置

测试用单进程、限 8 核运行;Qt 界面在离屏模式下串行验证。

结果

先复现: 最先加入的 13 项场景测试,旧实现 12 项失败、1 项通过。

场景 应有行为
英雄 +2、生物 +2 英雄 +2,其他净变化 0
英雄 +2、生物 +3 剩 +1,不能全部归英雄
英雄不变、生物 +2 剩 +2
英雄 +2、生物不变 其他净变化 −2
防御变化 用英雄防御,不串攻击字段
两种己方生物分别 +2 分别关联,不串面板
缺同帧 HUD 明示回溯/延续,不改观察
先后 HUD 10、12,12 更吻合 仍按顺序选第一条,不挑值
区间内读到不同英雄 阻断
两端锚点是同一条 HUD 不输出数值分解

修复后相关五个 SE 测试文件 119 项通过;按审阅建议补“单 HUD 保护”和“基础属性不同”的负例后,同样五个文件 121 项通过(是后一次的总数,不与 119 相加)。App 攻击证据和敌方证据两组测试共 45 个用例点通过。

真实回放: 修复前后用公开入口重放同一个 8 帧请求,只有推断栏里的同一条历史说明改变;原始观察、8 条攻击记录及其条件、其他推断完全不变。修复后的说明:

  • 英雄攻击 12→14(+2);生物攻击变化 +2 = 英雄变化 +2 + 其他净变化 0;
  • 英雄来源是 98.40 秒 → 223.8 秒;回溯假设:98.40 秒的英雄攻击 12 在 92.2 秒也成立(那一帧没有读到)。

单次 SE 重放 1.709 秒(不是视频处理速度或整帧 p95)。App 已有的攻击证据页直接显示新的分解和假设,离屏截图已核对可读。

失败与负结果

  • 修复初测时有 2 项测试的文本断言自相矛盾,修正为“禁止数值分解,但不禁止明确的缺失提示”。
  • 第一次离屏渲染缺字体,脚本显式加载已有 Windows 字体后通过,没有改 App 字体或安装依赖。
  • 用户随后纠正:准备页已有的英雄基线不应因“没有同帧 HUD”就丢弃。这一点由后续另一个修复处理,本页保留这一轮的测量。

局限

  • 截图序列没有秒级时长或有效期,非同帧读数只是假设成立,不是已认证有效。
  • “其他净变化为 0”不代表没有其他效果,增益与减益可能抵消;算法没有把变化归给任何具体状态(如“升华”)。
  • 用户说“英雄 +2 导致生物 +2”只是用户陈述,算法没有把它当证据读取。
  • 用户手工对象绑定尚未被这条路径消费,不能声称会自动检出绑定冲突。
  • 软件测试不表示真实识别准确率;没有安装或启动用户 App,旧保存结果不会自动重算。

结论与下一步

修复让 SE 用上了已经读到的英雄 HUD 历史,并把每一处时序假设写在说明里。外部审阅认为根因必须同时承认实现漏消费和测试缺失;补充的两项保护已实现。下一步建议(当时尚未实施):用户回看已有分析时,可以显式让旧保存截图用当前 SE 重算,同时保留当时版本对照,不处理更多视频。