摘要
SE(状态估计)会维护一条“减员时间线”:每个兵堆(一方的一种生物)在每次读到数量时记录一次,相邻读数之差就是减员。问题是:在一段训练录像(10 月 10 日 01:39)里,有一批兵堆在战斗中途被整堆消灭,从行动条(屏幕顶部按出手顺序排列的生物卡片)上消失了,又恰好没读到 Logs 战斗日志里的“被摧毁”行。于是时间线一直停在最后一个读数,直到结算画面才补 0——观世者、太阳圣盾晚了约 20 分钟。
本实验加了一条规则:当一个兵堆在若干次“完整读取”的行动条上都不再出现,就补一个条件性的 0 读数,并标明“已离开行动条,条件推断”。关键约束是绝不能把活着的兵堆判死。结果:01:39 局 10 堆得到这种终局读数,全部是真的消灭;结算对照从 2 行一致变为 12 行一致;在大量人为制造的“认错”扰动下,活堆被判死 0 次。
要回答的问题
兵堆离开行动条时,能否给出一个不会误杀活堆的条件性终局读数?什么样的行动条读取才足以说明“某堆不在了”?
数据与来源
- 两段用户选定的训练/开发录像(10 月 10 日 16:57、01:39)已有的行动条标注和保存的 App 请求;没有打开冻结或留出录像,保存请求只读。
- 行动条标注由模型目视给出(模型目视核对),不是用户审核。下面只报计数。
方法
先看行动条的事实。 行动条每张卡宽 108 像素、间距 110.7,两个回合之间有一个分隔。读取器只读当前回合(组 0)和下一回合(组 1)。统计标注发现:
| 16:57(79 个有行动条的时刻) | 01:39(117 个时刻) | |
|---|---|---|
| 组 0–1 共 12 张且有分隔(行动条被占满) | 45 次,全部看不到组 2 | 45 次,全部看不到组 2 |
| 组 0–1 ≤11 张且有分隔(下一回合在条内结束) | 0 次 | 69 次,全部能看到组 2 |
| 活着的堆不在组 0–1 里(堆·时刻) | 186/1046,全部在占满的时刻 | 25/781,全部在 12 张的时刻 |
| “≤11 张”时刻里活堆不在下一回合 | — | 0 |
结论:12 张 + 一个分隔就会占满行动条,下一回合可能延伸到屏幕外;但如果组 0–1 不到 12 张且读到分隔,下一回合整组都在条内,所有活着的堆都会出现在下一回合里。等待只在当前回合内重排,召唤物出现在下一回合,都不影响这一点。16:57 那局一直有 12 堆以上,从来没有这样的读取。
“完整读取”的条件:
- 读到当前回合和下一回合(恰好有分隔);
- 下一回合在条内结束:最后一张卡后面再放一张卡仍不超过 2031 像素(等价于组 0–1 ≤11 张),或者读到了组 2;
- 每张卡都有兵种和能对应到一方的颜色;同一回合里没有重复的(颜色, 兵种);
- 当前回合剩下的堆都在下一回合里(被窗口挡住或扫描截短时这条会不成立)。
判为离开: 某堆在最后一次出现之后,有 K=3 次完整读取都没有它,之后任何截图都不再出现它;它在行动条上至少出现过 SEEN=3 张截图;最后一次读数大于 0;之后没有“被摧毁”日志。满足时在第 3 次完整读取处加一个 0,减员区间是“上一次读到它 → 这次读取”。SE 每次都从整段历史重算,所以以后再读到它,这个 0 自然撤回。
结算画面: 先按不含这些 0 的读数对应结算卡片;如果对应上的卡片显示这堆活到了最后,就不加它的 0。留下的 0 让结算行从“缺终点”变为“一致”,并标明这一致依赖推断。
K 和 SEEN 怎么定。 真实数据里 K=1、2、3 判出的堆完全相同;K=4 时麒麟丢掉(它死后到结算只有 3 次完整读取)。SEEN=0 会多判 2 个从没上过行动条的“幻影堆”(数量牌身体候选认错兵种造成)。真实数据分不出 K,于是对 01:39 读取器的 117 个输出逐个人为制造错误、每个前缀重放一遍(相当于实时 SE 在那一帧的结论):
| 设置 | 单卡认错兵种(512 种) | 同一堆连续两次认错(499) | 扫描在下一回合中途断掉(237) |
|---|---|---|---|
| K=1, SEEN=3 | 100 种出误判 | 139 | 42 |
| K=2, SEEN=1 | 435(幻影) | 445 | 0 |
| K=2, SEEN=2 | 0 | 445 | 0 |
| K=2, SEEN=3 | 0 | 71 | 0 |
| K=3, SEEN=3(采用) | 0 | 0 | 0 |
| K=3, SEEN=4 | 0 | 0 | 0 |
读取器在 2071 张标注卡上兵种 0 错,所以采用能扛住同一堆连续两次认错的最小设置 K=3、SEEN=3。
设置
在保存请求上跑完整 SE,与改动前源码的输出逐字节比较。为避免工作目录不同导致头像参考路径不同、改变我方阵营判断,比较时把该路径固定为主仓库路径(不固定时结论相同)。
结果
01:39 局(554 帧,72 次完整读取): 10 堆得到离开行动条的终局读数,全部是真的消灭(结算参考都是 0,0 都放在标注最后一次看到它之后)。
| 兵堆 | 最后读数(画面秒) | 0 放在(画面秒) | 标注:最后看到 / 第一次不见 |
|---|---|---|---|
| 敌方观世者 | 551.8 | 1010.1 | 476.0 / 559.0 |
| 敌方太阳圣盾 | 551.8 | 1010.1 | 476.0 / 559.0 |
| 敌方圣殿狮鹫 | 785.5 | 1010.1 | 773.5 / 804.0 |
| 敌方驯鹰师 | 990.4 | 1123.3 | 1005.5 / 1010.5 |
| 敌方神化者 | 1101.0 | 1129.0 | 1115.0 / 1124.0 |
| 我方水泽精灵 | 1094.3 | 1129.0 | 1096.5 / 1103.5 |
| 我方羊人 | 1204.2 | 1210.9 | 1201.0 / 1214.5 |
| 敌方织光者 | 1206.8 | 1350.8 | 1329.5 / 1338.0 |
| 我方判官 | 1639.3 | 1696.3 | 1653.0 / 1659.0 |
| 我方麒麟 | 1777.4 | 1795.9 | 1784.0 / 标注到此为止 |
结算对照:改动前一致 2、缺终点 11、无法对应 1;改动后一致 12、缺终点 1、无法对应 1。剩下的缺终点是被结束战斗的最后一击打死的修道院长。原问题中“中途离开行动条的 8 堆”全部补上。整份 SE 结果只有减员部分不同。织光者有一段时间数量“1”一直没读出,但卡片一直在,所以没有被提前判死。
16:57 局(261 帧): 0 次完整读取,没有离开行动条的终局;整份 SE 结果与改动前逐字节相同。结算仍是一致 7、缺终点 6(都是最后一击打死的)、无法对应 1。
逐前缀重放(实时 SE 每一帧会给出的结论): 01:39 的保存请求、标注转成的读取、读取器输出三种序列,最终判消灭 10/11/11,误判、0 放在死亡之前、撤回全部为 0;16:57 三种序列都是 0 次完整读取。
审阅后的修正: 原版把 0 放在第一次完整读取上;外部审阅指出,如果一次认错恰好落在死亡之前的完整读取上,0 就会放在它还活着的帧上。在保存请求上逐卡制造认错(537 种)和连续两次认错(525 种)重放:
| 版本 | 单次认错:0 放在死亡之前 / 活堆被判死 | 连续两次认错:同左 |
|---|---|---|
| 0 放在第一次(审阅前) | 3 / 0 | 4 / 0 |
| 0 放在第 3 次(现在) | 0 / 0 | 0 / 0 |
审阅者报告的 3 例在旧版本上原样复现,改后为 0。同时修正了结算逻辑:原来误判的 0 会让结算行变成“不一致”、结算读数被丢掉,错的 0 永久留下。
测试与兼容: 新增 14 个 SE 测试(包括审阅后先写、在旧代码上失败的 3 个)和 2 个 App 测试。审阅后相关 140 个测试通过;整个 SE 测试集 3284 通过、52 跳过、1 预期失败、3 失败——这 3 个在改动前的源码上同样失败(工作目录缺数据文件),与本改动无关。App 中带这种推断的减员显示“已离开行动条,条件推断”;没有这种情况时输出与改动前逐字节相同。
失败与负结果
- 第一版把 0 放在第一次完整读取,在扰动下会把 0 放到死亡之前(3–4 例),已改。
- 早死的兵堆(场上还有 12 堆以上时)0 会放得很晚:观世者、太阳圣盾晚 451 秒,圣殿狮鹫晚 206 秒,只有区间起点是准的;其他堆比第一次不见晚 −4 到 +113 秒。
- 死后到战斗结束不足 3 次完整读取的兵堆拿不到这个 0,只能交给结算画面。
局限
- 只有一局有完整读取(10 堆);计数来自模型目视标注,不是准确率。
- 兵种被连续 3 次以上认错,或有让活堆暂时离开行动条的效果(控制、隐身、暂时离场),会误判;扰动重放假设认错相互独立,而状态染色、升级形态这类认错可能连续出现。
- 跳过回合的状态(如睡眠、石化、眩晕、致盲等 7 种)下行动条是否仍列出该堆,录像中没有核实;持续多回合的效果可能跨过 3 次完整读取。
- 读取器扫描停在下一回合最后一张卡上时,与“下一回合在条内结束”看起来一样,只靠“当前回合 ⊆ 下一回合”挡;用“看到第二个分隔”做条件需要先改视觉模块输出,没改。
- 召唤物到时消失也会离开行动条,会得到这个 0 并计入减员(这两局没出现)。
- 行动条几何常量只适用于 2560×1440 原生布局。App 还不显示减员的前提说明和结算行。
结论与下一步
“完整读取的行动条连续 3 次看不到 + 至少上过 3 次行动条”这条规则,在可用数据和大量扰动下都没有误杀活堆,并把中途消灭的兵堆从“结算才补 0”提前到战斗中。下一步可考虑让视觉模块把回合分隔信息传给 SE,用“看到第二个分隔”加强完整性判断,并在录像中核实跳过回合状态下的行动条表现。
Comments