INTERACTIVE PAPER DECK26 页交互图解:从评测规则到真实输入检查 展开阅读
GameASG-Bench 要回答一个具体问题:模型通过编码工具根据需求做出的游戏,能否让玩家真正完成要求的操作和流程?作者用 47 个浏览器游戏测试这件事。最佳配置通过了大多数单项检查,但只有 26 个游戏通过全部必需检查。
论文把通过框架读写文件、调用工具并生成代码的模型系统称为 Coding Agent,下文简称 Agent。作者把检查分成两层:L1 读取源码,检查语法和接口声明等条件;L2 在浏览器中运行游戏,实际操作并检查行为。P0、P1、P2 是另一套标签,分别表示运行前提、核心需求和扩展能力,不能与 L1/L2 混为一谈。
1. Motivation:游戏能打开,为什么仍不算做完
能启动、能返回测试状态,还不足以证明玩家操作有效。 论文中的 Diner Dasher 是餐厅服务游戏:GPT-6-Astra 生成的版本能打开,通过了源码检查、运行前提和扩展能力检查;评测器把托盘里的正确餐点拖给顾客后,订单和收入却都没有变化。真实鼠标和触摸两条路径都失败了。来源是论文 §4.6、Table 9 和 Appendix A.1,后文会沿着官方检查说明它怎样被判为失败。
小游戏也需要输入、角色状态、画面、资源和胜负流程协同工作。例如,扣弹药的函数可能写对了,但开火按键没有调用它;移动代码也可能只改变测试接口里的坐标,没有改变实际渲染的角色。函数测试和源码扫描很难单独证明这些环节已经接通。
评测器还必须适应不同实现。同一项需求可以用数组、对象或不同事件处理方式实现,测试不能绑定某个内部变量名。让测试每次从开局重新玩到后期,又会花费很长时间。作者因此要求游戏提供一个公开测试接口:评测器用它准备局面、执行约定的玩法动作并读取状态,再按需加入真实键鼠、画面变化和浏览器报错等证据。
2. Related Work:同样测游戏,判分依据有何不同
本文的重点是让同一套预先写好的检查适用于不同代码实现。 它沿用软件测试中的公开行为规范和隐藏断言,并把这套分工放进完整游戏生成任务。
APPS、EvalPlus 主要检查边界明确的程序题;SWE-bench 检查已有仓库的修复。WebGen-Bench、E2EDev 等将对象扩展到完整应用。GameGPT、Play2Code、ALIVE 等则研究协作、试玩或执行反馈怎样改善游戏生成。与 GameASG-Bench 最接近的是下面四种游戏评测设计。
| 工作 | Agent 交付与可见输入 | 如何取得判分证据 | 与本文的主要区别 |
|---|---|---|---|
| WebGameBench | 根据规格生成浏览器游戏 | 按规格指导浏览器交互;允许先准备候选状态,再执行用户动作 | 本文提前规定场景、动作、状态字段和不应被破坏的条件,并固定可执行检查 |
| GameCraft-Bench | 完整 Godot 项目,以及可重放的演示 | 演示含场景初始化;隐藏评分规则检查回放证据 | 本文交付单个 HTML,由评测器运行 L1/L2 检查,而非只看 Agent 提交的演示 |
| GameGen-Verifier | 根据规格生成游戏 | 将需求拆成前置条件、交互和后置条件,再向每份实现注入运行状态 | 本文让 Agent 主动实现公开接口,场景含义在生成前就确定 |
| GameXpert-Bench | 生成、修复及迭代改进游戏 | 生成赛道汇总已完成产物中的事件,经人工审核形成共享评分规则,再检查代码和实时交互 | 本文的规格和检查在生成前定稿,不随候选实现调整 |
这个区别不意味着其他工作“都不测真实操作”。WebGameBench 和 GameGen-Verifier 也会准备状态、执行交互。本文要解决的是不同实现怎样接受一致的检查,以及检查里的每条失败怎样对应一项公开需求。比较依据为论文 §5.3;这里没有把各 benchmark 的不同分数当成可直接横比的能力排名。
3. Benchmark / Protocol:从公开规格走到一条真实判定
人类写需求和检查,Agent 写游戏,评测器运行隐藏检查。 这三种责任必须分开,才能读懂数据是怎么来的、失败又是在哪里发生的。
3.1 任务来源和纳入范围
每个任务都必须包含一个完整、可在限时浏览器测试中跑完的玩法循环:玩家输入改变状态,产生可观察的进展或胜负,并能重新开始。依赖后端、账号、外部数据库、付费或私有资产,以及无法在有限测试时间里观察结果的多人系统被排除。最终任务集覆盖 12 类游戏,其中 32 个是 2D,15 个是 3D。47 题在所有报告实验中共用,论文没有另外划出训练集。
3.2 三份公开文档和两份隐藏检查
任务作者在生成前人工写好并固定玩法规格、评测接口规范、L1/L2 检查和 P0/P1/P2 优先级。这些材料不会根据 Agent 提交的代码临时改写。负责启动模型会话、管理上下文和提供工具的运行框架称为 harness。它只把 target.md 直接传入提示词;另外两份文档放在工作区,由 Agent 读取。
target.md 直接进入初始提示。文件名并不代表来源:它们由任务作者编写,不是 Agent 完成游戏后自动生成的报告。| 材料 | 来源与可见性 | 具体用途 |
|---|---|---|
target.md | 人类任务作者;Agent 可见 | 工作区规则、交付要求和简短玩法说明 |
game-spec.md | 人类任务作者;Agent 可见 | 玩家操作、玩法机制、反馈、胜负和重启 |
tdd.md | 人类任务作者;Agent 可见 | 测试怎样加载局面、执行动作、读取状态;非法动作应拒绝什么、哪些值应保持不变 |
checks.json | 人类任务作者;对 Agent 隐藏 | 声明 L1 的结构或语法检查、正则断言和禁止出现的源码写法 |
checks.js | 人类任务作者;对 Agent 隐藏 | 用 JavaScript 实现 L2 的浏览器操作和行为判断 |
| 参考实现 | 作者团队提供;不交给 Agent | 人类先独立试玩确认合格,再用同一套自动测试验收 |
论文说清了人工编写和参考实现验证,但没有报告标注者人数、标注者之间的一致率或系统性的错误实现测试。不能把“人工写好检查”进一步理解成已经量化了测试的误杀和漏判率。
3.3 Agent 交付什么,接口怎样工作
Agent 在全新工作区和会话里生成 index.html。官方 README 进一步说明:自写 HTML、CSS 和 JavaScript 都要包含在该文件里,允许的第三方库可以使用稳定 CDN 地址;评测不提供本地配套资产。因此,“单文件交付”不等于完全禁止第三方网络库。
生成与评测在两个隔离容器里运行。进入评测前,系统要求生成进程正常退出,index.html 是普通文件、不是符号链接、非空且含 </html>。通过预检后,HTML 和检查脚本才以只读方式交给评测容器。
公开接口统一叫 window.__gameTest,但场景、动作和返回字段由各任务的 tdd.md 决定。下面是接口形状示意,不是可直接运行的 JavaScript:
1 | window.__gameTest |
getSnapshot 返回 JSON 状态摘要,论文称为 snapshot,例如弹药、角色位置和胜负状态。它必须报告实际游戏使用的状态,不能另外维护一套专供测试的假数据。loadScenario 可以调整位置和资源,直接准备一个正常游玩也能到达的局面;但不能在加载时提前打中敌人、完成上菜或判定胜负。
3.4 一次 L2 检查怎样执行
L1 先检查 HTML 及其内联或直接链接的本地脚本。正则匹配只能证明要求的源码模式出现过,甚至可能匹配到注释;它不能证明玩法有效。L1 失败不会阻止 L2 执行,报告仍可区分源码条件失败和运行行为失败。
L2 在无界面 Chromium 浏览器中执行 checks.js。每条 L2 检查都新建一个页面,加载游戏、准备场景、执行动作、观察结果;完成或超时后关闭页面,再运行下一条。检查可以调用公开接口,也可以发送真实鼠标、键盘或触摸输入。浏览器观测代码记录动画帧、输入监听器、Canvas/WebGL 绘制和运行异常,具体检查再选用相关信号。
“画面确实更新”与“画面内容正确”仍是不同判断。一次 Canvas 绘制或一个版本计数增加,不能单独证明弹丸打中了正确敌人。每条检查究竟要求哪些证据,要看它自己的布尔条件,而不能把整个评测器拥有的信号都当作该条已经用过。
3.5 真实 case:Diner Dasher 的鼠标上菜
这条 case 延续开头的失败样例。来源是人类作者写的 官方 checks.js 中 p1-real-mouse-drag-correct-serve,以及论文 Appendix A.1。
评测器先加载 tray_with_correct_item:托盘里放着能满足当前顾客订单的餐点,但尚未完成上菜。随后从 snapshot 读取餐点和顾客在屏幕上的矩形边界,取各自中心作为拖拽起点和终点。坐标来自当前游戏,不是写死的像素常量。
浏览器按下鼠标左键,分 6 次移动到顾客中心,每次等待 40 ms,最后松开并等 250 ms。之后再读取状态和画面摘要。官方检查依次要求:
- 已完成订单项数、当日收入、已服务顾客数中至少一个增加。
- 如果订单项的
served计数增加,托盘餐点数量还必须减少。 - 只有前后 Canvas hash 都可读时,才检查画面摘要或
renderRevision至少一个改变。Canvas hash 是画面像素的摘要;renderRevision是游戏报告的渲染变化计数。
checks.js 第 552–581 行。下面节选 JavaScript/Chromium 检查的核心判断,辅助函数来自官方脚本,节选本身不是独立可运行程序:
1 | const beforeScore = moneyToday(setup); |
论文里的 GPT-6-Astra + Codex CLI 提交在鼠标和触摸两条上菜检查中都没有产生服务进度,因此 P1 失败。它通过了 L1、P0、P2,仍不满足核心需求。这是公开的真实失败记录;上面的图是根据规则绘制,不是模型运行截图。
3.6 再核对一条官方检查:Armor Alley 持续射击
Armor Alley 是横向卷轴直升机战术游戏。公开玩法规格要求按住时消耗弹药并产生可见弹丸,松开后停止;tdd.md 定义 holdFire 动作及 air_attack_with_targets 场景。场景应有可用武器和可攻击目标,不能提前记录命中或伤害。
隐藏的 checks.json 用正则确认四个接口方法的源码声明;真正的射击检查位于 checks.js 的 p1-keyboard-sustained-fire-release。该条先核对必要状态字段、正在游玩、尚无胜负、直升机已升空;它并未在前置谓词里逐项检查有弹药和可攻击目标。接着执行下面的真实按键序列。代码按官方逻辑节选,省去驱动器和通用数值辅助函数;运行环境是 JavaScript/Chromium,不是独立可运行样例。
1 | const before = setup.snap; |
rev(...) 读取游戏报告的变化计数:projectiles 表示弹丸变化,combat 表示战斗变化。按住期间,四种证据只要有一种成立就通过;松开后,弹丸数量最多增加 1 或弹丸变化计数不变,两者也只需成立其一。
这里有个容易误读的辅助函数。官方 game.wait 的执行顺序是先调用游戏的 input({type:'wait'})、保存它返回的快照,再让浏览器等待,最后返回此前保存的快照:
1 | async wait(durationMs = 250) { |
因此 afterRelease 不是自然等待 550 ms 后重新读取的状态。按下、松开和最初的等待是真实浏览器操作,但最后一份观察还经过公开 wait 动作。不能把这条描述成完全不调用测试接口的自然时间测试。依据官方文件第 149–153、435–457 行。
按该布尔规则做一个说明性计算:假设按住后弹药从 20 降到 18,即使当前弹丸数没增加,第一项也成立;松开后的两份观察若弹丸数相同,第二项成立。反过来,如果四种开火证据都没有变化,检查立即 FAIL。这些数字只是演算,不是作者公开的模型日志;该条本身也不要求一定命中敌人。
这条还暴露了公开规格与隐藏输入的不一致:game-spec.md 只要求按住/松开开火,tdd.md 只定义 holdFire,两者都没有规定必须使用 Space 键。某个提交即使完整实现了公开要求,只要使用了其他开火键,仍会被这条隐藏检查判为失败。真实按键检查的按键映射也应该进入公开规格。
3.7 从单条 PASS 汇总到完整成功
每条 L2 返回 PASS、FAIL 或 NOT_APPLICABLE。后者表示不适用,在适用检查的分母中排除。主指标叫 strict task success,下文称“完整通过”:一个任务只有在交付有效、评测完成,并且全部 L1 和所有适用的 L2 P0/P1 都通过时才记为 1;否则记为 0。P2 单独报告,不参与这项判定。
s_g = delivery_g × evaluation_g × ∏ pass(g,c), c ∈ L1_g ∪ applicable L2(P0,P1)_g
StrictSuccess = (Σ s_g) / 47
没有交付、评测未完成或任一必需检查失败,都记为 0;全部 47 个计划任务仍在分母里。
部分通过率采用不同口径:平均 L1 和总体 L2 是先算每个完成评测任务的检查通过率,再对任务取平均;P0/P1/P2 则汇总所有完成评测任务中的适用检查,以通过项数除以总项数。因此,93.2% 表示平均 L2 通过率,并非 93.2% 的任务完整通过。26/47 × 100 = 55.319…%,按表格精度就是 55.3%。
当前 runner 没有禁止 P1 返回 NOT_APPLICABLE,而计分又会忽略这类检查。也就是说,本应验收的某条核心需求可能被排除,而没有阻止整题通过。这个限制来自论文 §2.4,不是仅凭“隐藏测试”就能消除的问题。
3.8 测试本身怎样验证
任务作者对 47 份参考实现先做人类独立检查,确认真实操作、核心状态、胜负、重启及接口与画面的一致性,再运行同一套自动测试。全部参考实现通过 L1 和适用的 P0/P1,它们是 positive controls,即已知应通过的正确样例。
这只能证明测试能接受这些正确实现。论文没有报告系统性的 mutation testing,也就是故意向正确代码注入缺陷再检查能否发现。因此,测试到底会漏掉多少种错误、接口快照和画面证据能否被同时伪造,仍不能由这 47 个正样例量化。
4. Experiments:高单项分数为何掩盖整题失败
最强配置也只完整通过了 26/47;L1 高分主要说明源码条件容易满足。 论文比较九种模型与 harness 组合,每个“任务 × 配置”只运行一次,从空白工作区开始。统一使用 1280×800 的无界面 Chromium。harness 版本是 Claude Code 2.1.206、Codex CLI 0.153.4。
4.1 九种完整配置的主结果
RQ1 使用各模型可用的最高推理强度和全部工具,九种配置都交付并完成评测。论文把“模型 + harness”称为 agent stack,强调成品来自模型、上下文管理和工具环境共同作用。
九种配置的 L1 均值在 97.7% 至 99.6%,完整成功数却从 7/47 到 26/47。GPT-5.6-Sol 的平均 L2 为 91.3%,高于 Claude-Opus-5 的 90.4%,完整成功数反而是 21 对 24。错误散落在不同游戏里,还是集中在少数游戏里,会改变整题结果。
Table 4 也没有显示文件越大或 token 用量越高,就越容易完成更多任务。这里的 token 是模型处理的文本单位;不同供应商的输入、缓存和推理计费口径也需要随配置一起读,不能只拿一个输出长度解释能力。
4.2 工具和轮次:更多任务先获得了交付机会
RQ2–RQ4 共用 DeepSeek-V4-Flash + Claude Code、最高推理强度、全部工具和名义 120 轮作为基线。轮次是框架允许的模型交互上限,不等于浏览器操作次数。官方 README 的默认单次生成时限为 3,600 秒、一次新会话尝试;这是代码默认值,不据此推断所有论文运行都用了相同实际时长。
工具消融依次为无工具的序列化 API、只读写文件、文件加 node --check 语法检查、完整工具。完整成功数分别是 7、6、9、18,分母均为 47。语法检查从 6 增到 9,但 P1 通过率反而从 66.2% 降到 63.4%,再次说明两种指标不等价。
完整工具增加了多种能力,没有单独隔离浏览器工具的贡献。附录能展示某次浏览器运行怎样暴露 Canvas 错误或输入坐标错误,但不能由此算出浏览器本身贡献了多少总提升。
轮次上限为 30、60、120 时,完成评测的任务数依次是 10、32、47,完整成功数是 7、13、18。按全部 47 题算,成功率提高;只看已完成评测的子集,则是 7/10 = 70.0%、13/32 = 40.6%、18/47 = 38.3%。后一组下降不能解读成“更多轮次让模型变差”:不同上限下进入评测的任务集合不同。
4.3 推理强度和 harness:只有一次运行,别把一题差距当定律
Low、High、Maximum 的完整成功数为 7、19、18;P1 通过率为 71.7%、82.7%、86.7%。High 用的内部推理 token 比 Maximum 少 26.9%,多完成一题。它说明这批运行里存在成本与整题结果的折中,没有建立“High 总比 Maximum 好”的稳定规律。
换 harness 后,DeepSeek-V4-Flash 在 Claude Code 和 Codex CLI 下都成功 18/47,但只有 10 题重合,各有 8 题独有成功,另有 21 题双方都失败。系统指令、上下文、工具格式、执行方式和模型接口协议同时变化,不能把差别只归因于某一个功能。
资源、工具、轮次和 harness 的完整数据根据原论文 Tables 4 至 8 重绘
4.4 另一种真实失败:接口自测与自然运行没有接上
Turbo Smash Beast 中,DeepSeek-V4-Flash + Claude Code 生成的代码在 reset 或 loadScenario 后开启 test mode,关闭了随真实时间推进的仿真。Agent 的接口自测会手动推进时间,而真实驾驶自测从一个新打开的页面开始,两条测试都没触发“先加载场景,再真实驾驶”的组合。
官方 p1-real-hold-accelerates 先加载 readyUnlockedLevel,在游戏区内按住鼠标,350 ms 后取中间状态,再保持按下并等待 450 ms 取最终状态,最后松开。检查要求输入被识别为持续按下,速度依次上升,前进进度和运动变化计数增加,速度 HUD 也增加。注意第二段等待时鼠标仍按着,不是先松开再滑行。
论文里的错误实现加载场景后停止自动更新,真实等待无法产生这些变化。来源是 Appendix A.1 和官方 checks.js 第 845–870 行。它与 Armor Alley 最后调用 wait 接口的检查不同:这条加速观察确实使用两段真实等待和之后的新快照。
5. Discussion:先补哪些能改变结论的实验
最值得补的是评测可靠性和可归因的对照。 论文没有单独的未来工作章节;以下是基于结果提出的分析,不是作者已经验证的方法。
首先,用明确有错的实现检查测试本身。可以分别断开真实输入、伪造 snapshot、让场景加载冻结时钟、只支持某个按键,再看哪些检查能发现。公开按键要求和 P1 的 NOT_APPLICABLE 规则也应一并修正,否则分数会混入规格不一致和测试漏判。
其次,把工具或 harness 的变化拆开,并重复同一配置。完整工具相对受限工具高分,但增加的不止浏览器;High 与 Maximum 只差一题;两套 harness 同分却成功不同任务。只有固定其他条件、逐项改动并重跑,才能判断某种修复或执行策略是否稳定有效。
如果进一步研究“将执行反馈用于训练”,应把可见训练测试和最终隐藏检查分开。模型可能学会迎合接口和已知断言,却没有改善真实游戏;需要用新的场景、错误实现对照和真实输入一起验收。这个建议是从本文的检查边界推导的,不是论文训练实验的结论。
6. Conclusion:这是需求验收,不是完整游戏质量排名
GameASG-Bench 把“完整成功”定义得比平均检查分数严格。 人类提前写好玩法、接口和隐藏检查;Agent 交付游戏;评测器准备合法局面、操作并观察。最佳平均 L2 通过率为 93.2%,完整成功率为 26/47 = 55.3%,这是这篇论文最清楚的实验证据。
它没有量化所有错误实现的漏判率,也不覆盖后端、大规模多人服务或完整游戏内容与体验。接口状态、版本计数和画面信号能提供互补证据,但具体检查仍可能较宽松。Armor Alley 的 Space 映射和最后的 wait 快照顺序,说明读者需要核对真实脚本,不能只读流程图就默认每个步骤都完美实现。
每种配置只运行一次,排名和一题的差距都带有未估计的随机波动。使用这套 benchmark 时,应该同时报告有效交付、完成评测、适用检查通过率和完整成功数,并明确模型、harness、工具权限、预算与代码版本。
论文:GameASG-Bench。代码核对版本:6427cb6。原论文分发许可未确认允许直接复用图像,因此本文保留其全部 1 张 Figure、9 张 Table 的数据重绘,另画流程和真实 case,不使用原论文像素。
留言