GAMEASG-BENCH · PAPER WALKTHROUGH

如何验证一个游戏
真的做完了

从人类事先写好公开规格和隐藏检查,到评测器在浏览器中实际操作游戏,再到严格判断成品是否达到交付标准。

47完整浏览器游戏任务
336L1 源码检查
885L2 行为检查
55.3%最佳严格成功率
SPEC人类先写公开规格和隐藏检查
BUILDAgent 交付单页 index.html
VERIFY评测器准备场景、执行真实输入并判定结果
GameASG-Bench: Benchmarking Autonomous Software Generation for Game Development · arXiv:2609.21293
02 · MOTIVATION页面能打开,不代表游戏完成

常用指标往往只看到游戏的一小部分

01
成功加载能排除启动崩溃,无法证明交互和状态变化。
02
静态截图能看一帧布局,无法证明控制、动画和胜负流程。
03
源码关键词win、ammo 或 restart 可能只出现在注释里,相关代码也可能没有接到实际玩法。
04
Agent 自测容易只测试接口,漏掉真实鼠标或触摸输入,以及游戏按真实时钟自行推进的过程。

玩家输入要真正改变游戏状态,状态变化还要反映到画面、资源和胜负结果中。评测必须把这些环节连起来执行。

论文 §1、§2.3、§4.6。
03 · THE ORACLE PROBLEM如何为不同实现建立统一的判定依据

测试要能快速准备后期局面,又不能依赖某一种代码结构

完全按玩家路径从头玩

  • 到达后期局面太慢
  • 碰撞和时序难稳定复现
  • 失败后很难定位是哪项需求没实现
⇄

测试脚本直接读写实现细节

  • 会绑定变量名和对象结构
  • 换一种实现,同一测试就可能失效
  • 还可能绕过本该由玩家完成的操作
legal scenario(合法起点) → player-level action(玩家动作) →
stable snapshot(含义固定的状态摘要) → invariant(始终应成立的约束)
论文把这层约定称为 evaluation interface specification(评测接口规范)。
04 · RELATED WORK比较任务范围、状态准备与运行证据

和现有工作的关键区别:评测规则在生成前写好

工作
产物
状态准备
运行证据
评价方式
APPS / EvalPlus
函数
输入样例
返回值
预先定义测试
SWE-bench
仓库修改
仓库与 issue
项目测试
已有测试套件
WebGameBench
浏览器游戏
先准备游戏状态
真实浏览器交互
Agent 操作并判断
GameCraft-Bench
Godot 项目
可回放演示
回放与多模态证据
隐藏评分规则(rubric)
GameGen-Verifier
生成游戏
运行时注入状态
前置、交互、后置
从规格抽取检查点
GameXpert-Bench
生成与修复
生成后汇总事件
检查源码 + 实际操作
从多份成品汇总事件,并经人工审核形成评分规则
GameASG-Bench
单页浏览器游戏
预先声明合法场景
快照、真实输入、浏览器信号
规格和检查生成前固定
论文 §5.3。表内措辞按原文归纳。
05 · AUTHORSHIP AND VISIBILITYchecks.json / checks.js 到底是谁写的

人类写规格、检查与优先级,Agent 写游戏

文件
作者
生成时 Agent 能否看到
作用
target.md
人类开发者
可见,直接进入提示
工作区、交付协议、玩法简介
game-spec.md
人类开发者
可见
玩家可见的玩法,以及一局游戏至少要包含什么
tdd.md
人类开发者
可见
测试场景、动作、快照与拒绝规则
checks.json
人类开发者
隐藏
L1 静态检查
checks.js
人类开发者
隐藏
L2 浏览器行为检查
参考实现
作者团队
隐藏
人工确认合格,作为测试的正对照(positive control)
index.html
Coding Agent
Agent 自己生成
最终交付物
论文 §2.1、§3.2、§3.3、附录 B。P0/P1/P2 在人工测试编写阶段分配。
06 · ORIGINAL TABLE 1三份公开任务文档

Agent 既能看到玩法要求,也能看到评测接口规范

根据论文 Table 1 数据重绘的任务文档对照表
根据原论文 Table 1 数据重绘。三份文档 Agent 都能读取;承载模型与工具的 harness 只把 target.md 作为初始提示,其余两份由 Agent 自行打开。
根据原论文 Table 1 数据重绘。
07 · BENCHMARK CONSTRUCTION根据论文 §2、§3 与附录 B 重绘

测试在模型生成前就已经固定

STEP 1人工选题

完整可玩循环,能在有限时长的浏览器测试中运行并观察结果。

STEP 2写公开规格

target、game spec 和 TDD 共同定义任务。

STEP 3写隐藏检查

生成开始前写好 checks.json、checks.js,并为每项检查标出 P0/P1/P2。

STEP 4验证参考实现

人工操作并跑自动检查,确认核心玩法和评测接口符合规格。

STEP 5Agent 生成

每次使用全新的工作区副本和 Agent 会话,只能读取公开文档。

STEP 6独立评测

先检查 index.html 是否有效,再运行 L1、L2 并判断任务是否完整通过。

这 47 个参考实现就是正对照(positive controls):先由人确认合格,再验证自动测试不会误判它们。
本页为二次重绘,不是论文原图。来源:论文 §2.1、§3.1 至 §3.3、§4.1、附录 B。
08 · EXECUTION BOUNDARY生成和评测互相隔离

Agent 看得到公开规范,看不到隐藏检查

生成容器

read-only: target.md read-only: game-spec.md read-only: tdd.md read-write: workspace/
  • 每次从原始任务文件开始
  • 每次新建 Agent 会话
  • Agent 看不到 checks.* 和评测脚本
→

评测容器

read-only: index.html read-only: checks.json read-only: checks.js read-only: runners/
  • 先检查 index.html 是否为有效交付
  • 再执行 L1 与 L2
  • 记录每项结果,并判断任务是否完整通过
论文 §4.1、附录 B。生成过程必须正常结束;index.html 必须是非空的普通文件,不能是符号链接,并且包含 </html>。
09 · PUBLIC TEST CONTRACT接口名统一;场景、动作和字段由每个任务自己定义

四个固定方法,把测试接到游戏真正使用的状态上

window.__gameTest = {
  reset(options),
  loadScenario(name, options),
  input(action),
  getSnapshot()
}

		// 返回可序列化为 JSON 的状态摘要
		// 接口读写的是实际驱动画面的同一份状态
reset清除上一局状态和临时效果,回到初始局面。
loadScenario载入一个正常游玩也能到达的合法局面,但不能在载入时就完成待测动作或直接给出胜负。
input执行玩家级动作,例如生产单位、暂停和选择目标。
getSnapshot用固定字段返回评测关心的状态摘要,不要求暴露程序内部的对象和函数。
论文 §2.2。方法名统一,场景、动作与快照字段由任务定义。
10 · PREPARE, ACT, OBSERVE快速进入后期局面,但不跳过真正的玩家操作

测试可以摆好战场,仍要由玩家动作触发结果

PREPARE

合法前置状态

可以调整资源和位置,快速来到待测局面;但游戏在载入后不能已经结束,待测行为也不能已经发生。

→
ACT

玩家级动作

调用公开接口执行“生产单位”“选择目标”等玩家动作,或直接发送鼠标、键盘与触摸事件。

→
OBSERVE

结果与约束

检查胜负、资源和 HUD 是否按预期变化,revision(游戏报告的变化计数)是否递增,以及本不该变化的字段是否保持不变。

禁止:直接设好胜负,或靠改血量、坐标伪造待测结果;用固定快照替代真实游戏状态;让测试接口报告的状态与玩家实际看到的状态不一致。
论文 §2.2;Armor Alley tdd.md 的 scenario setup(场景准备)与 interface integrity(接口状态必须对应真实玩法)约束。
11 · REAL CHECKS.JSONArmor Alley 字段节选;正则表达式在图中缩写

这条 L1 检查只确认源码里出现了四个接口方法

{
  "id": "p0-contract-methods-reset-input-snapshot",
  "level": "P0",
  "type": "regex_all",
  "patterns": [
    "... reset ...",
    "... input ...",
    "... getSnapshot ...",
    "... loadScenario ..."
  ],
  "fix_hint":
    "Define reset, loadScenario, input,
     and getSnapshot on window.__gameTest."
}
由人类编写checks.json 在生成前完成,并且不会挂载到生成容器。
允许多种写法整份 checks.json 用多组正则兼容方法简写、对象属性赋值和 Object.assign 等声明方式。
L1 只能证明代码里出现过注释或字符串也可能被正则命中,所以 L1 不能证明玩法真的可用。
官方仓库 tests/armor-alley/checks.json;论文 §2.3、§3.2。
12 · REAL CHECKS.JSL2 把规格写成可执行步骤

一条 L2 检查写清操作、证据和失败条件

// GDD Coverage Map
M3 weapons
  → p1-keyboard-sustained-fire-release

// Rationality Map
real action:
  browser.keyDown / browser.keyUp
independent observation:
  ammo / projectile / combat revision
empty-shell failure:
  fire flag without projectile, cost,
  or release behavior

每个任务的人类作者事先写好 checks.js,用 JavaScript 描述这个游戏的场景、操作与 PASS/FAIL 条件。本文没有据此假定它完全没有使用模板。

Armor Alley 的 checks.js 有 814 行。它覆盖启动、飞行、武器、落地补给、生产、地面战争、雷达、暂停、胜负流程和 P2 扩展项。

官方 tests/armor-alley/checks.js;核对版本 6427cb6。左侧为 Coverage / Rationality Map 的解释性摘录,不是可运行代码。
13 · ARMOR ALLEY真实任务:直升机与地面战线

测试覆盖的是完整战斗循环

Armor Alley

玩家驾驶直升机侦察、攻击和投放士兵,同时花钱生产坦克、导弹车、运输车与步兵。

胜利:友方运输车到达敌方基地。失败:敌方运输车突破己方基地;在有限生命模式下,直升机生命耗尽、无法继续防守也会失败。
飞行

鼠标指针在直升机中心的哪一侧,直升机就持续向哪一侧加速;测试会分别检查四个方向。

武器

每种武器都要正确消耗弹药并产生可见效果;没有弹药或有效目标时,操作应被拒绝,也不能误扣其他资源。

经济

资金、生产队列和单位上限要与 HUD 同步;战斗结束后不能再下生产订单。

战场

地面单位要自主推进;碉堡、炮塔、空中障碍和雷达不能只是装饰。

降落整备

降落到安全区后,燃料、弹药和受损状态要逐步恢复;整备期间水平移动受限。

胜负与重启

胜负出现后,普通攻击和生产不能继续改变结果;重启要清空旧状态。

官方仓库 task/armor-alley/game-spec.md。
14 · ARMOR ALLEY TDD公开接口与隐藏测试的条件并不完全一致

场景只准备攻击条件,不提前产生射击结果

准备

loadScenario(
  "air_attack_with_targets"
)

tdd.md:
visibleTargets.length > 0

checks.js:
phase === "playing"
result === "none"
helicopter.airborne
→

操作

keyDown("Space")
wait 650 ms
snapshot held

keyUp("Space")
wait 300 ms
snapshot released
→

观察

按住期间:
弹丸数量 ↑
  或弹丸/战斗变化计数 ↑
  或弹药 ↓

松开之后:
  数量最多增加 1
  或弹丸变化计数不变
tdd.md 要求场景中有可攻击目标;这条 checks.js 实际只把 playing、尚未分出胜负和直升机已升空作为前置判断。通过后才按 Space;公开规格没规定必须用 Space,因此其他开火键可能遭到误判。
Armor Alley tdd.md 与 tests/armor-alley/checks.js。
15 · REAL BROWSER INPUT官方逻辑节选;省略通用辅助函数

浏览器实际收到 Space 的按下和松开事件

const before = setup.snap;

await browser.keyDown('Space');
await browser.sleep(650);
const held = await game.snapshot();

await browser.keyUp('Space');
await browser.sleep(300);
const released = await game.snapshot();
const afterRelease = await game.wait(550);

if (!grewWhileHeld)
  return FAIL('held fire did not create evidence');
if (!plateauAfterRelease)
  return FAIL('fire continued after release');
return PASS('real key path creates and stops fire');
只认真实按键路径射击阶段只发送真实 Space 键。即使 input({type:'holdFire'}) 可用,也不能拿它替代键盘事件。
最后一份不是等待后的新快照game.wait(550) 先调用 input(wait) 保存返回状态,再自然等待,最后返回旧状态。不能解释为 550 ms 后重新取样。
多种等价证据弹丸数量、弹丸/战斗事件计数器(projectile/combat revision)或弹药减少,都可以作为已经开火的证据;测试不要求某一种内部数据结构。
官方仓库 tests/armor-alley/checks.js,p1-keyboard-sustained-fire-release。
16 · PASS AND FAIL同一需求的正向证据与停止条件

开始和停止各是一组 OR 条件,不能读成全部都要满足

按住期间

grewWhileHeld = projectileCount ↑ OR projectileRevision ↑ OR combatRevision ↑ OR ammo ↓

四种证据只要一种成立。比如弹药减少,即使当前弹丸数不增也能通过;这不等于测试要求一定命中或同时验证了视觉射击。

松开之后

plateauAfterRelease = count(afterRelease) ≤ count(released) + 1 OR projectileRevision remains unchanged

数量最多增加 1 或变化计数不变,只需其中之一。脚本没有说明 +1 的原因;且 afterRelease 来自 wait 接口返回值,不是自然等待后的新观察。

官方 checks.js 第 149–153、435–457 行。布尔条件保持原逻辑;数字推演只验证断言,不代表模型日志。
17 · ORIGINAL TABLE 2证据层和优先级是两套标签

336 个源码检查,885 个浏览器行为检查

根据论文 Table 2 数据重绘的检查数量表
根据原论文 Table 2 数据重绘。L1:43 项由工具完成的结构和语法检查、288 项正则断言、5 项 anti-pattern 规则(禁止出现的写法)。L2:P0 102 项、P1 534 项、P2 249 项。
根据原论文 Table 2 数据重绘。
18 · L2 EXECUTION每条检查使用一个新浏览器页面

快照、真实输入与渲染信号相互校验

PAGE新页面

加载提交的游戏,隔离上一条检查的状态。

RUN单条检查

准备场景、输入、等待、读取快照和渲染证据。

CLOSE关闭页面

完成或超时后销毁,再开始下一条。

评测程序(runner)会注入一个 browser hook(浏览器观测探针),记录动画帧、输入监听器、Canvas/WebGL 活动和运行时异常。

并非每条测试都同时看所有信号。snapshot 说明游戏自己报告了什么状态;真实输入确认玩家实际使用的操作路径可用;Canvas/WebGL 等渲染信号则确认画面确实在更新。

论文 §2.3。L1 失败不会阻止 L2 执行。
19 · STRICT TASK SUCCESS一道任务最终只记 0 或 1

全部必需检查通过,任务才记为成功

P0

启动、测试接口和最低运行条件。共 102 个 L2 检查。

P1

核心机制、交互、必须始终成立的约束,以及支持这些玩法的接口行为。共 534 个 L2 检查。

P2

高级机制与体验完整度。单独报告,不进入严格成功。

success = valid delivery × completed evaluation × all L1 pass × all applicable L2 P0/P1 pass

必需检查即使通过 39/40,整道任务仍记为失败。平均通过率能看出还差多少;strict task success(严格任务成功)只问这份游戏能否按要求交付。全部 47 个计划任务都在分母里。

论文 §2.4、公式 (1)。当前评测程序仍允许 P1 返回 NOT_APPLICABLE(不适用),并把该项排除在统计之外。
20 · ORIGINAL FIGURE 147 个任务的组成

12 类游戏,32 个 2D,15 个 3D

根据论文 Figure 1 数据重绘的任务分布图
根据原论文 Figure 1 数据重绘。图中的渲染技术只统计参考实现;Agent 生成的游戏可以使用其他技术。
根据原论文 Figure 1 数据重绘。论文只有这一张正式编号 Figure。
21 · ORIGINAL TABLE 39 种 agent stack(模型与编码工具的组合)

平均 L2 通过率达 93.2%,严格成功却只有 26/47

根据论文 Table 3 数据重绘的排行榜
根据原论文 Table 3 数据重绘。最佳配置的 L2 平均通过率达到 93.2%,但仍只有 26/47 个任务通过全部必需检查。每个任务在每种配置下只运行一次。
根据原论文 Table 3 数据重绘。GPT-6-Astra + Codex CLI:26/47,55.3%。
22 · ORIGINAL TABLE 4生成文件大小、token 用量与 API 成本

文件更大、token 用得更多,并没有稳定对应更多成功任务

根据论文 Table 4 数据重绘的资源用量表
根据原论文 Table 4 数据重绘。Input tokens 合并了系统报告的 input、cache-read 和 cache-write 三项。表中这些资源量与完整通过的任务数没有稳定的对应关系。
根据原论文 Table 4 数据重绘;§4.2。
23 · ORIGINAL TABLES 5 AND 6DeepSeek-V4-Flash · Claude Code

完整工具提高整题成功;低轮数时完成评测的任务集合不同

根据论文 Table 5 数据重绘的工具消融表
根据 Table 5 数据重绘。无工具 / 文件 / 文件+语法 / 完整工具:7 / 6 / 9 / 18,均除以 47。文件+语法的 P1 反而低于文件条件。
根据论文 Table 6 数据重绘的轮次预算表
根据 Table 6 数据重绘。轮数上限为 30/60/120 时,分别只有 10/32/47 个任务完成评测。
Tables 5–6 重绘。30 轮 7/10、60 轮 13/32、120 轮 18/47 是不同完成子集;主指标始终除以 47,不能据条件分数下降推断多轮更差。
24 · ORIGINAL TABLES 7 AND 8同样是 18/47,成功的题目却不一样

High 比 Max 多成功 1 题;两个执行框架各成功 18 题,但共同成功的只有 10 题

根据论文 Table 7 数据重绘的推理强度表
根据 Table 7 数据重绘。High:19/47;Max:18/47。High 使用的 reasoning tokens(推理 token)比 Max 少 26.9%。
根据论文 Table 8 数据重绘的 harness 比较表
根据 Table 8 数据重绘。两种 harness(模型上下文与工具环境)各成功 18/47,但只有 10 题重合,各有 8 题独有成功、21 题都失败。
根据原论文 Tables 7、8 数据重绘。结果来自单次运行,不能据此建立稳定的绝对排名。
25 · ORIGINAL TABLE 9总榜看不到的具体失败

两类具体失败:真实拖拽无效,场景加载后游戏停住

根据论文 Table 9 数据重绘的失败案例表

Diner Dasher

GPT-6-Astra + Codex CLI
  1. 载入 tray_with_correct_item 场景,托盘上已有顾客点的餐。
  2. 从 snapshot 读取餐点和顾客的屏幕边界,以中心点作为拖拽起止位置。
  3. 分别发送真实鼠标与触摸拖拽。
  4. 两条路径下,服务进度和收入都没有增加。
L1、L2 P0/P2 通过,P1 核心交互失败。

Turbo Smash Beast

DeepSeek-V4-Flash + Claude Code
  1. reset 或 loadScenario 会打开 test mode(测试模式)。
  2. 该模式停掉了游戏按真实时钟自行推进的主循环。
  3. 加载 readyUnlockedLevel 后按住鼠标 350 ms 取样,仍按住再等 450 ms 取样;速度、进度与 HUD 本应上升。
接口自测会手动推进时间,真实驾驶自测从新页面开始;两条都没有覆盖“先加载场景,再等待游戏自行运行”。
根据原论文 Table 9 数据重绘;§4.6、附录 A.1。
26 · TAKEAWAYS读完后应该带走的判断

核心贡献:一条可重复执行的行为证据链

人类先写好公开的评测接口规范和隐藏检查,Agent 可以自由决定代码结构。评测器再把场景准备、真实输入、状态快照(snapshot)和渲染信号串起来,验证玩家操作是否真的引发规格要求的状态和画面变化。

93.2%最佳平均 L2
55.3%最佳严格成功率

适合回答

单页浏览器游戏是否满足一组预先写好的核心行为要求。

仍需谨慎

只有 47 题且每配置只跑一次;未报告系统性错误实现对照。还允许 P1 返回 NOT_APPLICABLE 并排除;Armor 的 Space 要求和 wait 快照顺序也有边界。

可迁移的方法

先准备合法起点,再执行玩家动作、读取结果,检查不应破坏的约束;同时用正确和刻意错误的实现检查测试本身。

论文 · 代码与 47 个任务 · 解读与重绘:ChrisDing Blog
封面 1 / 26