摘要

结论先行:只用玩家可见信息的一步行动包搜索 Public Quick(本地预览辅助),在严格 4 秒的实时执行路径上,对英雄无敌三式规则 AI(H3)在 64 个从未用过的来源、128 局中 98 胜 30 负,来源差 +0.531,95% 区间 [0.359, 0.688],通过事先冻结的门槛;随后经真实 Arena 路径在另外 32 个新来源上复核为 +0.531 [0.313, 0.719]。它已作为 Arena 的可选 AI 交付,默认仍是 v59。

问题来自 s41:研究搜索 quick 对两个规则 AI 都领先约 0.67,但它读取对手的隐藏构筑。信息消融显示,去掉对手法术书与装备/技能状态后它仍领先,但这种“从真实状态删字段”的做法不能保证没有间接泄漏。我们先证明“严格重演公开历史”不可行(中位 4 个动作就断),再改为只从当前公开观察构造一个可搜索的局面,并用玩家指向目标时看到的攻击预览校准伤害。

边界同样明确:攻击预览来自本地 Simulator,还没与正式游戏客户端核对;+0.531 是整套系统(包括 H3 不使用的悬停预览)的优势,不能全部归给搜索;对手先验是“没有未见过的法术和装备”,对局记录显示它比 H3 更常被范围法术成片命中。

问题

s41 留下一个落差:读取特权信息的研究搜索 quick(只展开己方当前这一次行动、depth=1)对 v59 和 H3 都约 −0.67。两轮信息消融(0074、0075)把对手法术书、对手装备与英雄技能状态从搜索世界里删去后,quick 对 H3 仍约 +0.56–0.61,说明优势主要来自“把当前每个合法动作在规则引擎里真实结算一次再比较”,而不是偷看。

但这类“遮蔽世界”仍从真实状态出发。审阅指出一个具体泄漏:公开防御 20 可能由“隐藏技能 +4、隐藏装备 −4”合成,逐项删除时两项都会改变公开读数而被保留,搜索仍然知道对手有哪些隐藏来源。正式的公平搜索必须在源码层面只接收公开输入。

方法

第一次尝试:先验世界重演公开历史(0077)。 己方用真实构筑;对手只用公开英雄身份与公开部队,不带技能、装备与天赋,法术只取已被施放而公开的;开局用已有的公开残差拟合对齐可见数值;然后把公开动作历史逐个在这个世界里按语义重演。40 局 381 个决策点里,只有 57 点能重演到决策点,中位 4 个动作就断。断点几乎都是对手用到了先验没有的能力:同一回合第二次施法(奇术)、英雄攻击、单位技能,或隐藏装备改变了先攻顺序。结论:这条路线不可行。

改为公开根节点快照(0078)。 不重演历史,只把当前公开观察写进一个合法局面:

  • 模板:上面那个公开开局世界;
  • 覆盖:每个兵组的位置、数量、当前总生命、每只生命、剩余反击、是否已等待、可见状态(对手来源的状态只公开效果数值),行动队列、场地效果、待放置法术、己方集能与技能冷却、英雄 HUD;战斗中召唤或镜像出的兵组按公开卡面与兵种目录新建;
  • 校验:用引擎自身的状态来源校验做判据。法术状态的施放法强、持续时间修正、对手法术等级,只在“能复现公开参数”的范围里搜索;修不好的状态丢弃;
  • 对齐:迭代调整兵组的基础攻防与伤害上下限,使卡面上的实际值与公开值一致。

在 381 个开发决策点上,迭代到快照能构造 347 个(91%),其中 311 个的合法动作与真实公开菜单完全一致。

一个关键发现:卡面看不到的伤害修正。 快照与真实状态的攻击预览一开始只有 32.5% 相同。逐项核对后,差异不在卡面数值,而在单位层面的伤害修正(例如防守方的“基础攻击承受修正”、攻击方被对手削弱的输出修正),它们由对手的隐藏技能和装备设定,卡面上不显示。但玩家在游戏里把鼠标停在目标上能看到攻击预览——这是公开信息。把“快照预览与悬停预览之差”折算成该目标的承受修正,一个参数就能把最小伤害、最大伤害和击杀数三项同时复现 96.4%。注意这是在同一批预览上拟合,不是独立预测;它只作为搜索内部的近似,不当作推断出的敌方属性。

决策与执行。 决策核心只接收 JSON 形式的公开输入:公开观察、公开菜单、公开历史摘要(对手本回合施法次数)和本步当前行动单位对每个敌方目标的悬停预览,外加公开开局观察与己方构筑。它构造快照、逐目标校准,然后在快照与公开菜单都合法的动作里用 quick 选择;快照构造失败时由 H3 接手。实时执行沿用 Arena 的结构:每步一个新进程,4 秒从被调用时算起,先给出 H3 的选择、再给出 Public Quick 的选择,截止前收到的最后一个为准。

实验设置

  • 开局:镜像竞技场开局(双方同一份启发式选秀构筑,每方 1 名英雄、7 个兵组),20 回合,双输规则,规则版本 v453。对手先验不使用“镜像”这一生成器知识。
  • 开发:0079 在 8 个开发来源上检查能否稳定打完、回退多少、耗时多少;0080 在开发来源上做一次有界的耗时修复与复测。
  • 评测(0076 阶段二,运行前冻结):64 个全新来源 71000–71063,每来源 Public Quick 执蓝、执红各一局对 H3;主指标为来源差(候选两局得分和 − 1),来源自助法 95% 区间,下界 > 0 才算通过;同时报告合法性、严格重放、遗留进程、每步耗时、采用比例与按“是否出现召唤”分层的胜负。
  • 生产复核(0081):移入生产模块、接入 Arena 实时 worker 后,在另外 32 个全新来源上再打 64 局。

结果

实验 来源 / 局 胜–负(双输) 来源差 [95% 区间] Public Quick 决定 每步最长
0079 开发(第 2 次) 8 / 16 16–0 开发来源,不作结论 95% 5.79 秒(进程内)
0076 阶段二 64 / 128 98–30 (0) +0.531 [0.359, 0.688] 88.5% 4.533 秒
0080 复测(开发,外部负载 / 受控压力) 16 / 32 ×2 29–3 / 29–3 开发来源,不作结论 90% 3.888 / 3.903 秒
0081 生产复核 32 / 64 49–14 (1) +0.531 [0.313, 0.719] 80.1% 3.776 秒
  • 阶段二按“该局是否出现召唤/镜像兵组”分层:出现的 64 局 47–17,未出现的 64 局 51–13。
  • 阶段二有 4 步超过 4.4 秒(当时另一会话的 CPU 压力与本运行占用同一批核);0080 修复后两种负载条件下 0 步超过 4.0 秒。
  • 未由 Public Quick 决定的步骤由 H3 接手:快照被引擎拒绝或到截止。全部实验 0 次退到公开菜单、0 次非法动作,所有对局严格重放一致。

讨论

搜索的价值在于“真实结算当前动作”。 遮蔽消融、严格重演失败和最终结果合起来说明:quick 的优势主要来自把每个当前合法动作在规则引擎里真实结算一次(反击、击杀、位移、状态),而一步搜索需要的只是“当前局面正确”,不需要知道对手的完整构筑。

为什么悬停预览这么关键。 对手的技能和装备有一大类只改伤害倍率,不改卡面。没有预览时快照算错的大多是这类伤害;有了预览,当前行动单位的普通攻击伤害几乎都能对上。这也意味着 +0.531 包含了 H3 不使用的信息,比较的是两套系统,而不只是搜索 vs 规则。

召唤一度是最大缺口。 第一版快照不支持战斗中生成的兵组,一旦对局出现召唤或镜像,剩下的决策全部回退 H3,这些对局的胜率明显更低;按兵种目录与公开卡面新建这些兵组后,Public Quick 的采用率从 53% 升到 95%。

局限与威胁

  • 信息边界只到“本地 UI 预览”:悬停预览由本地 Simulator 在真实状态上计算,没有与正式游戏客户端同状态对照;正式客户端能看到的预览范围与精度可能不同。
  • 对手先验是中性的:假设对手没有未见过的法术与装备。阶段二对局记录里,Public Quick 被同一次英雄施法同时命中多个兵组 107 次(≥3 组 87 次),H3 为 85 次(≥3 组 60 次),主要是黑洞、火球、雪崩——一步搜索不估计对手下一次范围法术。
  • 只对 H3:没有与原版 quick(特权)在同一批来源上配对,无法量化“只用公开信息”损失了多少;也没有与 v59 的新评测。
  • 镜像开局:双方构筑相同,非真实竞技场选兵分布。
  • 96.4% 是拟合率:在同一批预览上用一个参数复现,不是独立预测准确率;反击、法术、技能伤害仍是估计。
  • 耗时尾部受机器负载影响:到截止的比例在 0.55%–2.8% 之间,取决于同时运行的其它任务。

结论与后续

只用玩家可见信息、在 4 秒内交付的一步搜索,已经稳定强于目前最好的公开规则 AI;它以“公开信息 · 快速搜索(本地预览辅助)”作为 Arena 可选档位交付,等待试玩反馈。

后续按收益排序:

  1. 对手范围法术威胁(来自用户的对局笔记“布阵和走位要防黑洞、冰环、绝望”,以及上面的命中统计):用公开信息约束的先验估计对手下一次范围法术的损失。
  2. 借鉴开源 Heroes 3 引擎 VCMI 的战斗 AI:按“削减对方输出”评分,并沿行动顺序模拟“谁能打到谁”的交换,补上先攻争夺与反击。
  3. 正式客户端的悬停预览对照。
  4. 以 Public Quick 为教师的搜索蒸馏(s50),教师标签与 H3 回退分开。
  5. 长期:以关键事件(对手获得施法机会、核心兵组濒死、集能到门槛)而非固定层数决定搜索深度,按后果差异而非动作差异分叉。

复现

实验记录在仓库 game_ai/experiments/0076-live-budget-search、0077、0078、0079、0080、0081 的 README;设计与审阅取舍在 game_ai/docs/public-quick-v1-design-2026-10-15.md。

# 0076 阶段二(原型实时路径)
python devtools/game_friendly_run.py --cores 8 -- python -m game_ai.benchmarks.code.live_budget_0076 run OUT public-quick 71000 71063 --workers 4 --seconds 4
python -m game_ai.benchmarks.code.live_budget_0076 report OUT public-quick
# 0081 生产 Arena 路径
python devtools/game_friendly_run.py --cores 8 -- python -m game_ai.benchmarks.code.live_budget_0076 run OUT public_quick 71100 71131 --workers 4 --seconds 4
# 0078 快照探针(开发状态)
python -m game_ai.benchmarks.code.public_root_snapshot_0078 run OUT "local_data/game_ai/0075-quick-masked-world-ablation/run-2/games/708[01][0-9]-QP-*.json.gz" --every 10 --workers 6

生产代码:game_ai/src/olden_era_ai/strategy/public_quick.py;测试:game_ai/tests/test_public_quick_production.py、test_public_quick_0079.py、arena_app/tests/test_live_ai.py。

更新记录

  • 2026-10-15:首版。0076 阶段二、0080 耗时修复、0081 生产复核与 Arena 交付。