跳到主要内容

深入地下城:为 NetHack 构建探索系统

· 阅读需 8 分钟
Research and engineering team

NetHack 是什么?​

NetHack 是一款回合制 Roguelike 游戏,舞台是一座程序生成的地下城。完整游戏要求 玩家深入地下城,取得 Amulet of Yendor,返回地面并完成 ascension。要实现这一 目标,远不只是赢下几场战斗:玩家需要探索未知布局、理解消息、管理资源、记住 重要位置,并在永久死亡的威胁下生存。

一个简化的推进循环如下:

探索当前地下城楼层
↓
处理生物、障碍与资源
↓
寻找向下的楼梯
↓
下楼并重复这一过程

每个 Episode 的具体情况都会变化。房间与走廊重新排列,物品和生物出现在不同 位置,而 Policy 每次只能看到当前楼层的一部分。一个局部看来合理的 Action, 可能浪费数百回合、消耗稀缺食物,或者让角色偏离原本要前往的路线。

这些特点使 NetHack 成为研究可执行策略的合适 Environment。Policy 必须将即时 反应、记忆和长期目标结合起来,同时能够判断游戏是否按预期响应了刚才的 Action。

将 NetHack 接入 EvoPolicyGym​

该 Benchmark 接入了 NLE 1.3.0 的 NetHackScore-v0,底层使用 NetHack 3.6.7。 Policy 接收终端地图的语义表示,以及状态值、当前消息、公开背包条目和输入模式。 它可以从 23 个 Actions 中选择,包括移动、奔跑、上下楼梯、等待、踢、进食、 搜索和处理消息提示。

这套 Action profile 有意比完整 NetHack 的命令集合更窄。在 5,000 步的 Episode 限制内,实验主要考察游戏前期的探索、障碍处理、生存与下楼推进,而不是完整 通关。

分数奖励 NetHack 认可的游戏进展,同时惩罚角色持续冻结在原地的重复步骤。它为 Agent 提供主要优化信号,而地下城深度、游戏分数和冻结步比例则用于解释这些分数 对应了怎样的行为。

从完整轨迹中学习​

许多较弱的 NetHack Policy 并不会崩溃。它们会继续运行,却可能不断推撞一块 巨石、反复尝试穿过铁栏、在两个格子之间来回移动,或者站在楼梯上却不下楼。 聚合分数能说明 Policy 表现不佳,却不能指出行为究竟在哪里出了问题。

因此,每次训练 Submission 之后,Environment 都会返回所有评测 Episodes 的完整 Policy 可见轨迹。Agent 可以检查位置、Actions、消息、状态变化与重复状态,再将 这些模式对应回源代码。

提交可执行 Policy
↓
检查完整训练轨迹
↓
定位行为失败
↓
重写记忆、寻路或交互规则
↓
提交新的 Program

Environment 提供证据,而不是诊断。选择检查哪些 Episodes、判断哪些模式值得关注, 仍然是 Coding Agent 工作的一部分。持久的改进保存在可执行 Program 中,而不是 模型权重或跨 Episode 继承的隐藏状态中。

实验​

我们让三个 GPT-5.6 模型变体——Luna、Terra 和 Sol——通过 Codex 运行。每个 Agent 都从同一个 packaged baseline 开始,并可以利用训练分数与轨迹改进它。实验关闭了 可选的 NetHack 优化 Skill,因此 Agent 必须自行形成分析与修改流程。

Baseline 已经能够进行简单的局部探索。它记录位置访问次数,通常优先选择访问较少 的相邻格子,在存在其他选择时避免立刻折返,定期搜索,踢开可见的关闭房门,并在 饥饿时吃掉可识别的食物。但它不会构建显式地图、规划前往远处目标的路线、记忆 失败的边,也不会把下楼作为一个持续目标。

设置值
EnvironmentNLE 1.3.0 · NetHack 3.6.7
任务NetHackScore-v0 · 23 个 Actions
Episode 限制5,000 个 Policy steps
训练额度最多 128 个 Episodes
最终 Assessment256 个 held-out Episodes
可选 NetHack Skill关闭

训练额度是上限,并不要求必须用完。Sol 使用了全部 128 个 Episodes,Terra 使用了 68 个,Luna 使用了 40 个,随后结束运行。

结果​

Sol 在这次实验中产生了最强的最终 Policy。它的平均 Assessment return 为 204.026,平均游戏分数为 208.230,平均地下城深度为 2.867。其最深的 held-out Episode 到达了第 11 层。

Agent 路线使用的训练额度SubmissionsAssessment return平均游戏分数平均 / 最大深度冻结步
GPT-5.6 Sol + Codex128 / 1288204.026208.2302.867 / 1127.53%
GPT-5.6 Terra + Codex68 / 128480.23787.0941.082 / 433.77%
GPT-5.6 Luna + Codex40 / 128463.77370.7771.094 / 435.75%

三个最终选中的 Policy 都在 held-out Assessment 中完成了全部 Episodes,没有出现 Policy 执行失败。它们都没有完成 ascension。因此这些结果衡量的是游戏前期探索、 生存和地下城推进,而不是对完整 NetHack 的掌握。

Sol 最终选择的 Policy 在一个 NetHack 训练 Episode 中的完整语义回放。回放覆盖
全部 1,269 个 Policy steps,到达地下城第 11 层,最高游戏分数为 860,最终以死亡
结束。

第 000008 次 Submission 的第 16 个训练 Episode。这段回放展示了 Agent 编写的 Policy 如何从第一次 observation 开始自主行动,直至 Episode 结束。它是一个具有 代表性的训练轨迹,不属于表格中报告的 held-out Assessment。

Baseline 的能力边界​

Baseline 能够回答一个有用的局部问题:

哪一个可见的相邻格子访问次数最少?

但它还无法回答更完整的导航问题:

如何在一座充满不确定性的多层地下城中构建并维护一条路线?

两者之间的差距,正是 Policy evolution 的主要机会。要超越 baseline,Policy 需要在一个位置离开屏幕后仍然保留相关知识,跨越多个房间追踪目标,并在 Action 失败后修改计划。

Sol 构建了怎样的策略?​

Sol 将局部探索 baseline 转化为一个更有结构的导航系统。它的最终 Policy 结合了 三个相互增强的思路。

持久的空间记忆​

Policy 记录已经发现的地形、路线、目标和移动结果。它不再只是反复选择相邻格子, 而是能够利用先前的 observation,在已知房间和走廊中导航。角色离开当前位置后, 之前获得的信息仍然有用。

目标导向的探索​

Sol 将地下城推进变成了一个显式目标。当 Policy 已经知道向下楼梯的位置时,它会 保留这个目标、规划路线返回并使用楼梯;当还不知道楼梯位置时,它会寻找尚未探索 的空间,而不只是选择当前可见范围内访问最少的格子。

这使地下城深度不再只是 Episode 结束后观察到的指标,而成为写在可执行策略中的 目标。

失败检测与恢复​

NetHack 中的移动可能因为墙壁、巨石、铁栏、生物、房门或对地图的过期理解而失败。 Sol 会将计划中的移动与下一个 observation 进行比较。如果预期的状态转移没有发生, Policy 就可以把路线标记为阻塞、丢弃无效目标,并选择其他路径,而不是继续重复 同一个 Action。

最终得到的能力并不是一组互不相关的特殊处理,而是一个更通用的循环:观察结果、 更新内部地图,然后重新规划。

Agent 如何使用 Environment Feedback​

Luna——记住障碍。 Luna 发现一些轨迹主要由反复撞击巨石或尝试穿过铁栏组成。 它加入了对失败方向的记忆,减少了对静态障碍的立即重试。

Terra——摆脱循环并使用楼梯。 Terra 引入了 anti-loop 行为和显式下楼逻辑。 最终选中的最强 candidate 来自一个较早的版本,这说明继续编辑并不一定会产生更好 的 Policy。

Sol——将局部修复组织成导航系统。 Sol 结合记忆路线、面向楼梯的推进、阻塞边 处理和目标恢复。它没有把每次失败都看作孤立补丁,而是通过位置、路线、目标和 移动结果的共享模型将这些经验连接起来。

在每个案例中,持久的结果都不是 Agent 对轨迹的解释。这些经验必须成为代码,才能 在 held-out evaluation 中独立接收 observations 并返回 Actions。

发现与边界​

完整语义轨迹足以让 Agent 定位行为失败并完成有效的 Policy 修改,不需要 Environment 预先编写诊断。这项实验也说明,解释 NetHack 行为需要多个指标: return 用于排序 candidates,而深度、游戏分数和冻结步比例则揭示探索与推进的不同方面。

这些结果仍然只是初步研究。Agent 使用的训练额度并不相同,每条模型路线也只有 一次主要 Run。在最多 128 个 Episodes 的短训练上限下,Coding Agent 搜索可能因 随机性产生波动:相同 Environment 配置下,另一次 Terra Run 得分为 49.464, 而这里报告的结果为 80.237。

因此,表格应当被理解为这些 Agent 在对应 Runs 中构建出了更好的 NetHack Policy, 而不是 Luna、Terra 和 Sol 的普遍排名。

代码与说明​

EvoPolicyGym adapter 使用 MIT 许可证。NLE 与 NetHack 是独立依赖,并分别受各自的 许可证约束。