<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <id>https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/</id>
    <title>EvoPolicyGym Blog</title>
    <updated>2026-08-11T00:00:00.000Z</updated>
    <generator>https://github.com/jpmonette/feed</generator>
    <link rel="alternate" href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/"/>
    <subtitle>EvoPolicyGym Blog</subtitle>
    <icon>https://linzwcs.github.io/EvoPolicyGym/zh-CN/favicon.svg</icon>
    <rights>Copyright © 2026 EvoPolicyGym contributors</rights>
    <entry>
        <title type="html"><![CDATA[感知还是规划？Crafter 中的 Policy 演化]]></title>
        <id>https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/crafter-policy-evolution/</id>
        <link href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/crafter-policy-evolution/"/>
        <updated>2026-08-11T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[一组 RGB 与局部符号化配对实验，揭示 Crafter Policy 演化中不同的感知与长程控制瓶颈。]]></summary>
        <content type="html"><![CDATA[<p>Crafter 是一款开放世界生存游戏。Agent 必须在探索、采集资源、对抗敌人和推进合成
科技树的同时维持生存。与目标短而明确的环境不同，Crafter 要求许多决策在数百步的
尺度上持续协调。</p>
<p>对于负责演化 Policy 的编程 Agent，这构成了两个相互交织的挑战：</p>
<ol>
<li class=""><strong>感知：</strong> 从 observation 中恢复附近地形、生物、背包与玩家状态。</li>
<li class=""><strong>长程控制：</strong> 把这些状态组织成涵盖生存、探索、战斗与发展的连贯策略。</li>
</ol>
<p>在本次实验中，我们尝试拆分这两种困难。GPT-5.6 Sol、Terra 与 Luna 面对相同的
Crafter 任务，但它们演化出的 Policy 分别接收原始 RGB observation，或同一可见
状态的局部符号化表示。</p>
<p>这一变化对 <strong>Sol 和 Terra</strong> 的影响非常显著，对 <strong>Luna</strong> 的影响则小得多。移除大部分
视觉识别工作之后，三种编程 Agent 所演化 Policy 的不同瓶颈也随之显现。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="作为-policy-演化环境的-crafter">作为 Policy 演化环境的 Crafter<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/crafter-policy-evolution/#%E4%BD%9C%E4%B8%BA-policy-%E6%BC%94%E5%8C%96%E7%8E%AF%E5%A2%83%E7%9A%84-crafter" class="hash-link" aria-label="作为 Policy 演化环境的 Crafter的直接链接" title="作为 Policy 演化环境的 Crafter的直接链接" translate="no">​</a></h2>
<p>Crafter 会为每个 Episode 程序化生成一个全新世界。玩家开局没有工具或资源，必须在
眼前的生存需求和长期发展之间取得平衡。</p>
<p>一个有能力的 Policy 需要协调多种行为：</p>
<ul>
<li class="">维持食物、饮水和生命；</li>
<li class="">探索最初完全未知的世界；</li>
<li class="">收集逐级提升的资源；</li>
<li class="">制作并放置工具与设施；</li>
<li class="">躲避或攻击危险生物；</li>
<li class="">保留足够的局部信息，以便重新找到有价值的地点。</li>
</ul>
<p>这些目标会相互竞争。探索带来发展机会，也让玩家暴露在更多危险之中。制作工具需要
资源，而资源可能远离安全区域。只关注眼前生存的 Policy 容易停滞；过度激进地推进
科技，又可能因为忽略基本需求而迅速崩溃。</p>
<p>因此，Crafter 检验的是编程 Agent 能否演化出一个<strong>协调一致的长程程序</strong>，而不只是
发现一条在局部有效的动作规则。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="rgb-与局部符号化-observation">RGB 与局部符号化 Observation<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/crafter-policy-evolution/#rgb-%E4%B8%8E%E5%B1%80%E9%83%A8%E7%AC%A6%E5%8F%B7%E5%8C%96-observation" class="hash-link" aria-label="RGB 与局部符号化 Observation的直接链接" title="RGB 与局部符号化 Observation的直接链接" translate="no">​</a></h2>
<p>两组条件使用相同的模拟器、程序化世界、Action 空间、reward metric、Episode pool
和评测配置。唯一发生变化的是 Policy 获得的 observation。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="rgb">RGB<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/crafter-policy-evolution/#rgb" class="hash-link" aria-label="RGB的直接链接" title="RGB的直接链接" translate="no">​</a></h3>
<p>RGB Policy 接收 Crafter 渲染得到的 <code>64 × 64 × 3</code> 画面。</p>
<p>它必须自行推断：</p>
<ul>
<li class="">颜色和纹理对应的地形；</li>
<li class="">sprite 对应的生物和物体；</li>
<li class="">HUD 中的背包与生命状态；</li>
<li class="">画面中的玩家位置和朝向；</li>
<li class="">光照变化下的有效状态，包括夜晚的昏暗画面。</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="局部符号化">局部符号化<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/crafter-policy-evolution/#%E5%B1%80%E9%83%A8%E7%AC%A6%E5%8F%B7%E5%8C%96" class="hash-link" aria-label="局部符号化的直接链接" title="局部符号化的直接链接" translate="no">​</a></h3>
<p>Symbolic Policy 得到的是<strong>同一局部区域</strong>的结构化信息：</p>
<ul>
<li class="">局部地形与实体 ID；</li>
<li class="">生命、食物、饮水、能量、资源和工具；</li>
<li class="">朝向、睡眠状态和日照强度。</li>
</ul>
<p>这种表示消除了大部分物体识别、HUD 读取和夜间视觉歧义。</p>
<p>但它<strong>不会</strong>暴露拥有特权的全局状态。Policy 依然无法获得全局语义地图、绝对坐标、
Environment seed、生物隐藏状态，以及局部 observation 之外的其他信息。</p>
<p>它仍然必须探索世界、记忆有用地点、处理碰撞、安排资源顺序、把握交互时机、对抗
敌人，并协调生存与发展。</p>
<p>因此，这组配对实验简化的是<strong>状态识别</strong>，同时保留了大部分<strong>长程决策问题</strong>。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="长程生存分">长程生存分<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/crafter-policy-evolution/#%E9%95%BF%E7%A8%8B%E7%94%9F%E5%AD%98%E5%88%86" class="hash-link" aria-label="长程生存分的直接链接" title="长程生存分的直接链接" translate="no">​</a></h2>
<p>Crafter 的 canonical score 主要围绕成就设计。在 Policy 演化场景中，我们还希望区分
两类 Policy：一种偶尔能够到达高级成就，另一种则能稳定存活，并在生存过程中持续
发展。</p>
<p>因此，我们采用 <strong>长程生存分（Long-Horizon Survival Score，LHS Score）</strong> 作为主要
Benchmark metric。</p>
<p>在每一步中，生存部分包含两个信号：</p>
<ul>
<li class="">角色保持存活所获得的 <strong>alive reward</strong>；</li>
<li class="">由生命、食物和饮水中的最弱一项决定的 <strong>vital-quality reward</strong>。</li>
</ul>
<p>选择最弱状态是一项有意的设计：如果 Policy 即将因缺水死亡，那么充足的食物和生命
不应抵消这一危险。</p>
<p>LHS 同时保留有上限的次要发展激励：</p>
<ul>
<li class="">首次解锁一项新成就；</li>
<li class="">实际恢复食物或饮水；</li>
<li class="">采集资源、战斗和种植等可重复生产行为。</li>
</ul>
<p>重复行为受滚动窗口额度约束，避免简单的采集或维护循环主导总分。</p>
<p>在跨 Episode 聚合时，LHS 会进一步强调鲁棒性。最终分数综合：</p>
<ul>
<li class="">平均健康生存 return；</li>
<li class="">对<strong>表现最弱的四分之一 Episodes</strong>额外加权；</li>
<li class="">有界的发展与维护 return。</li>
</ul>
<p>从概念上看：</p>
<p><code>LHS = 平均生存 + 弱尾部鲁棒性 + 有界发展</code></p>
<p>而不是只奖励表现最好的轨迹。</p>
<p>这意味着，少数成就丰富但迅速死亡的 Episodes 无法弥补脆弱的生存策略；与此同时，
Agent 仍然有动力越过被动生存，继续推进发展。</p>
<p>Canonical Crafter score 会作为科技树推进程度的独立诊断指标报告。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="实验">实验<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/crafter-policy-evolution/#%E5%AE%9E%E9%AA%8C" class="hash-link" aria-label="实验的直接链接" title="实验的直接链接" translate="no">​</a></h2>
<p>我们评测 GPT-5.6 <strong>Sol</strong>、<strong>Terra</strong> 和 <strong>Luna</strong>。</p>
<p>对于每一种编程 Agent，我们分别运行一条 RGB observation 和一条局部符号化
observation 下的 Policy 演化轨迹。六个 Runs 使用相同的长程生存目标。</p>
<p>每个 Run 结束时选出的候选 Policy，都会在 <strong>64 个 held-out Episodes</strong> 上进行最终
评测。</p>
<p>除 LHS 之外，我们还报告：</p>
<ul>
<li class="">平均和最长有效生存时间；</li>
<li class="">至少存活 300 步的 Episode 比例；</li>
<li class="">canonical Crafter score；</li>
<li class="">成就覆盖数。</li>
</ul>
<p>这些指标能够帮助我们区分平均鲁棒性、极长的单条轨迹和科技发展程度。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="结果">结果<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/crafter-policy-evolution/#%E7%BB%93%E6%9E%9C" class="hash-link" aria-label="结果的直接链接" title="结果的直接链接" translate="no">​</a></h2>
<p>简化感知对三种 Agent 的影响截然不同。</p>
<table><thead><tr><th>Agent</th><th style="text-align:right">LHS Score</th><th style="text-align:right">平均生存</th><th style="text-align:right">最长生存</th><th style="text-align:right">存活 ≥300</th><th style="text-align:right">Crafter C</th><th style="text-align:right">成就覆盖</th></tr></thead><tbody><tr><td><strong>Sol</strong></td><td style="text-align:right">5.70 → <strong>11.53</strong></td><td style="text-align:right">195 → <strong>316</strong></td><td style="text-align:right">401 → <strong>1043</strong></td><td style="text-align:right">3.1% → <strong>39.1%</strong></td><td style="text-align:right">3.91 → <strong>19.47</strong></td><td style="text-align:right">10 → <strong>18/22</strong></td></tr><tr><td><strong>Terra</strong></td><td style="text-align:right">4.58 → <strong>9.88</strong></td><td style="text-align:right">164 → <strong>291</strong></td><td style="text-align:right">288 → <strong>871</strong></td><td style="text-align:right">0.0% → <strong>31.2%</strong></td><td style="text-align:right">1.12 → <strong>11.31</strong></td><td style="text-align:right">5 → <strong>14/22</strong></td></tr><tr><td><strong>Luna</strong></td><td style="text-align:right">4.58 → <strong>4.97</strong></td><td style="text-align:right">164 → <strong>178</strong></td><td style="text-align:right">288 → <strong>401</strong></td><td style="text-align:right">0.0% → <strong>3.1%</strong></td><td style="text-align:right">1.12 → <strong>3.44</strong></td><td style="text-align:right">5 → <strong>11/22</strong></td></tr></tbody></table>
<p><em>每个单元格均为 RGB → 局部符号化 observation。</em></p>
<p>对于 <strong>Sol</strong>，LHS 从 5.70 提升到 11.53，平均生存时间从 195 步提高到 316 步，
held-out pool 中的最长轨迹则从 401 步增长到 <strong>1,043 步</strong>。</p>
<p><strong>Terra</strong> 的变化同样突出：LHS 增长一倍以上，平均生存增加 127 步，最长轨迹达到
<strong>871 步</strong>。</p>
<p><strong>Luna</strong> 的变化小得多。Symbolic observation 让成就覆盖数从 5 项显著增加到 11 项，
但平均生存只提高了 13 步，LHS 也仅提升约 8%。</p>
<p>这种差距在稳健的长程生存上尤其明显。采用 symbolic observation 后，Sol 有
<strong>39.1%</strong> 的 Episodes、Terra 有 <strong>31.2%</strong> 的 Episodes 至少存活 300 步，而 Luna
只有 <strong>3.1%</strong>。</p>
<p>因此，对 Sol 和 Terra 而言，简化感知不仅改变了最佳情况，也改变了更广泛的生存
分布。</p>
<p><em>Terra symbolic Run 在 Validation 中出现一次协议失败，在 held-out Assessment 中
出现一次 protocol error。按照 Benchmark 定义，失败的 held-out Episode 计零分；
在成功完成的 Episodes 中，其最短生存时间为 156 步。</em></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="同一个世界六种-policy">同一个世界，六种 Policy<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/crafter-policy-evolution/#%E5%90%8C%E4%B8%80%E4%B8%AA%E4%B8%96%E7%95%8C%E5%85%AD%E7%A7%8D-policy" class="hash-link" aria-label="同一个世界，六种 Policy的直接链接" title="同一个世界，六种 Policy的直接链接" translate="no">​</a></h2>
<p>聚合结果衡量的是 Policy 在不同程序化世界中的鲁棒性。为了更直观地观察行为差异，
我们还让六个最终 Policy 在同一个展示世界中运行。</p>
<p>先前选定的固定世界恰好更有利于 Luna。我们改用一个确定性的、独立于正式评测的
128-Episode 展示池重新选择：候选 Episode 必须全部正常完成，Sol 必须优于 RGB
条件下共用的 baseline，三种 symbolic Policy 的有效生存时间必须满足
Sol &gt; Terra &gt; Luna，而且每一级差距至少为 50 步。在合格 Episode 中，我们选择最接近相应 held-out 平均生存时间
的一项，而非差距最大的极端样本。由于筛选使用了 Policy 结果，这些 replay 仍然只是
<strong>定性展示</strong>，不能作为评测证据。</p>
<p>在 symbolic 条件中，Policy 仍然只接收结构化的局部 observation。GIF 中的 RGB
画面是面向人类观察者的确定性 replay：我们在相同世界中重放该 Policy 记录下来的
Actions，这些 RGB 帧从未作为 Policy 输入。六张 GIF 使用相同时间轴；较早结束的
Policy 会停留在终局画面。</p>
<table><thead><tr><th>Sol</th><th>Terra</th><th>Luna</th></tr></thead><tbody><tr><td><strong>RGB · 244 步</strong><br><img decoding="async" loading="lazy" alt="Sol RGB Policy 在同一个 Crafter 展示 Episode 中的表现" src="https://linzwcs.github.io/EvoPolicyGym/zh-CN/assets/images/crafter-lhs-sol-rgb-showcase-e8adea92aea6811e32f569bb232b7c1e.gif" width="260" height="290" class="img_ev3q"></td><td><strong>RGB · 162 步</strong><br><img decoding="async" loading="lazy" alt="Terra RGB Policy 在同一个 Crafter 展示 Episode 中的表现" src="https://linzwcs.github.io/EvoPolicyGym/zh-CN/assets/images/crafter-lhs-terra-rgb-showcase-0954f346051270b498d9e141ba3f6745.gif" width="260" height="290" class="img_ev3q"></td><td><strong>RGB · 162 步</strong><br><img decoding="async" loading="lazy" alt="Luna RGB Policy 在同一个 Crafter 展示 Episode 中的表现" src="https://linzwcs.github.io/EvoPolicyGym/zh-CN/assets/images/crafter-lhs-luna-rgb-showcase-fd68a4791e85813e8c8df544cc483bb3.gif" width="260" height="290" class="img_ev3q"></td></tr><tr><td><strong>Symbolic · 391 步</strong><br><img decoding="async" loading="lazy" alt="Sol 局部符号化 Policy 在同一个 Crafter 展示 Episode 中的表现" src="https://linzwcs.github.io/EvoPolicyGym/zh-CN/assets/images/crafter-lhs-sol-symbolic-showcase-50dca0304bccee927ddfbdd43858b515.gif" width="260" height="290" class="img_ev3q"></td><td><strong>Symbolic · 261 步</strong><br><img decoding="async" loading="lazy" alt="Terra 局部符号化 Policy 在同一个 Crafter 展示 Episode 中的表现" src="https://linzwcs.github.io/EvoPolicyGym/zh-CN/assets/images/crafter-lhs-terra-symbolic-showcase-5a4c375be1bc899f4e442f185b6905b5.gif" width="260" height="290" class="img_ev3q"></td><td><strong>Symbolic · 194 步</strong><br><img decoding="async" loading="lazy" alt="Luna 局部符号化 Policy 在同一个 Crafter 展示 Episode 中的表现" src="https://linzwcs.github.io/EvoPolicyGym/zh-CN/assets/images/crafter-lhs-luna-symbolic-showcase-65bcd4ebc957d559cc9f298afbd54a64.gif" width="260" height="290" class="img_ev3q"></td></tr></tbody></table>
<p>Symbolic 一行现在清楚呈现了聚合结果的方向：Sol 持续最久，Terra 居中，Luna 明显
更早结束。Terra RGB 和 Luna RGB 无法在同一个 Episode 上拉开差距，因为这两条 Run
都选择了字节完全相同的 packaged baseline；两张相同 replay 和 162 步结果是预期
现象。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="三种-agent三种瓶颈">三种 Agent，三种瓶颈<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/crafter-policy-evolution/#%E4%B8%89%E7%A7%8D-agent%E4%B8%89%E7%A7%8D%E7%93%B6%E9%A2%88" class="hash-link" aria-label="三种 Agent，三种瓶颈的直接链接" title="三种 Agent，三种瓶颈的直接链接" translate="no">​</a></h2>
<p>配对结果揭示了三种 Agent 各自不同的主要瓶颈。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="solrgb-下已能推进symbolic-再带来一次跃升">Sol：RGB 下已能推进，symbolic 再带来一次跃升<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/crafter-policy-evolution/#solrgb-%E4%B8%8B%E5%B7%B2%E8%83%BD%E6%8E%A8%E8%BF%9Bsymbolic-%E5%86%8D%E5%B8%A6%E6%9D%A5%E4%B8%80%E6%AC%A1%E8%B7%83%E5%8D%87" class="hash-link" aria-label="Sol：RGB 下已能推进，symbolic 再带来一次跃升的直接链接" title="Sol：RGB 下已能推进，symbolic 再带来一次跃升的直接链接" translate="no">​</a></h3>
<p>Sol 在 RGB 下已经超过 packaged baseline，使用 symbolic 输入后又进一步提升：LHS
从 <strong>5.70 提高到 11.53</strong>，平均生存从 <strong>195 步提高到 316 步</strong>，成就覆盖从
<strong>10/22 扩大到 18/22</strong>。它能够同时改进感知与控制，但更可靠的状态识别仍会带来
显著收益。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="terra感知是主要瓶颈">Terra：感知是主要瓶颈<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/crafter-policy-evolution/#terra%E6%84%9F%E7%9F%A5%E6%98%AF%E4%B8%BB%E8%A6%81%E7%93%B6%E9%A2%88" class="hash-link" aria-label="Terra：感知是主要瓶颈的直接链接" title="Terra：感知是主要瓶颈的直接链接" translate="no">​</a></h3>
<p>Terra 的 RGB Run 最终回退到原始 baseline；改用 symbolic 输入后，LHS 从
<strong>4.58 提高到 9.88</strong>，平均生存从 <strong>164 步提高到 291 步</strong>，成就覆盖从
<strong>5/22 扩大到 14/22</strong>。因此，视觉状态提取是这条 Run 中最主要的瓶颈。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="luna更准确的识别没有解决协调问题">Luna：更准确的识别没有解决协调问题<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/crafter-policy-evolution/#luna%E6%9B%B4%E5%87%86%E7%A1%AE%E7%9A%84%E8%AF%86%E5%88%AB%E6%B2%A1%E6%9C%89%E8%A7%A3%E5%86%B3%E5%8D%8F%E8%B0%83%E9%97%AE%E9%A2%98" class="hash-link" aria-label="Luna：更准确的识别没有解决协调问题的直接链接" title="Luna：更准确的识别没有解决协调问题的直接链接" translate="no">​</a></h3>
<p>Luna 在 RGB 下也回退到 baseline。Symbolic 输入虽然让成就覆盖从 <strong>5/22 扩大到
11/22</strong>，但 LHS 仅从 <strong>4.58 提高到 4.97</strong>，平均生存也只从 <strong>164 步提高到
178 步</strong>。其主要限制已不只是识别，而是长程行为协调。</p>
<p><strong>改变 observation 契约，会以根本不同的方式影响它们的 Policy 演化。</strong></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="这组消融实验告诉了我们什么">这组消融实验告诉了我们什么？<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/crafter-policy-evolution/#%E8%BF%99%E7%BB%84%E6%B6%88%E8%9E%8D%E5%AE%9E%E9%AA%8C%E5%91%8A%E8%AF%89%E4%BA%86%E6%88%91%E4%BB%AC%E4%BB%80%E4%B9%88" class="hash-link" aria-label="这组消融实验告诉了我们什么？的直接链接" title="这组消融实验告诉了我们什么？的直接链接" translate="no">​</a></h2>
<p>乍看之下，Crafter 似乎只有一个问题：演化出一个能在开放世界中生存并发展的 Policy。</p>
<p>配对实验表明，困难可能产生于不同阶段。</p>
<p>对于 <strong>Sol 和 Terra</strong>，局部视觉状态提取是挑战的重要组成部分。移除物体识别、HUD
读取和夜间视觉歧义后，其生存能力和科技推进都显著增强。</p>
<p>对于 <strong>Luna</strong>，感知只是问题的一部分。更清晰的状态信息带来了更广的发展，但演化
出的 Policy 仍然难以把这些能力转化为可靠的长程生存。</p>
<p>这正是我们希望 Crafter 这类环境能够揭示的差异。</p>
<p>最终的标量分数可以告诉我们哪个 Program 表现更好；而对 observation 接口进行受控
改变，还能进一步揭示 <strong>Policy 演化停止提升的位置</strong>。</p>
<p>因此，Crafter 评测的不只是编程 Agent 能否写出游戏 Policy。它还提供了一种方法，
帮助我们区分感知失败与长程规划、控制和程序协调失败。</p>
<p>这六个 Runs 是六条独立的 Policy 演化轨迹，而非重复统计实验；它们消耗的训练
Episodes 也不完全相同。因此，我们不会把结果解释为 Sol、Terra 与 Luna 的一般性
排名。</p>
<p>更窄、也更有信息量的结论是：</p>
<blockquote>
<p><strong>移除局部视觉识别，彻底改变了 Sol 和 Terra 所演化的 Policy，却只小幅改善了
Luna 的生存表现——这揭示了长程 Policy 演化背后不同的能力瓶颈。</strong></p>
</blockquote>]]></content>
        <author>
            <name>EvoPolicyGym contributors</name>
            <uri>https://github.com/Linzwcs/EvoPolicyGym</uri>
        </author>
        <category label="Benchmark" term="Benchmark"/>
        <category label="Crafter" term="Crafter"/>
        <category label="Experiment" term="Experiment"/>
        <category label="Policy Evolution" term="Policy Evolution"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[深入地下城：为 NetHack 构建探索系统]]></title>
        <id>https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/nethack-policy-evolution/</id>
        <link href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/nethack-policy-evolution/"/>
        <updated>2026-08-03T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[Coding Agent 如何将完整的 NetHack 轨迹转化为能够导航、处理障碍并向地下城深处推进的可执行 Policy。]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="nethack-是什么">NetHack 是什么？<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/nethack-policy-evolution/#nethack-%E6%98%AF%E4%BB%80%E4%B9%88" class="hash-link" aria-label="NetHack 是什么？的直接链接" title="NetHack 是什么？的直接链接" translate="no">​</a></h2>
<p>NetHack 是一款回合制 Roguelike 游戏，舞台是一座程序生成的地下城。完整游戏要求
玩家深入地下城，取得 Amulet of Yendor，返回地面并完成 ascension。要实现这一
目标，远不只是赢下几场战斗：玩家需要探索未知布局、理解消息、管理资源、记住
重要位置，并在永久死亡的威胁下生存。</p>
<p>一个简化的推进循环如下：</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">探索当前地下城楼层</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        ↓</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">处理生物、障碍与资源</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        ↓</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">寻找向下的楼梯</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        ↓</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">下楼并重复这一过程</span><br></div></code></pre></div></div>
<p>每个 Episode 的具体情况都会变化。房间与走廊重新排列，物品和生物出现在不同
位置，而 Policy 每次只能看到当前楼层的一部分。一个局部看来合理的 Action，
可能浪费数百回合、消耗稀缺食物，或者让角色偏离原本要前往的路线。</p>
<p>这些特点使 NetHack 成为研究可执行策略的合适 Environment。Policy 必须将即时
反应、记忆和长期目标结合起来，同时能够判断游戏是否按预期响应了刚才的 Action。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="将-nethack-接入-evopolicygym">将 NetHack 接入 EvoPolicyGym<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/nethack-policy-evolution/#%E5%B0%86-nethack-%E6%8E%A5%E5%85%A5-evopolicygym" class="hash-link" aria-label="将 NetHack 接入 EvoPolicyGym的直接链接" title="将 NetHack 接入 EvoPolicyGym的直接链接" translate="no">​</a></h2>
<p>该 Benchmark 接入了 NLE 1.3.0 的 <code>NetHackScore-v0</code>，底层使用 NetHack 3.6.7。
Policy 接收终端地图的语义表示，以及状态值、当前消息、公开背包条目和输入模式。
它可以从 23 个 Actions 中选择，包括移动、奔跑、上下楼梯、等待、踢、进食、
搜索和处理消息提示。</p>
<p>这套 Action profile 有意比完整 NetHack 的命令集合更窄。在 5,000 步的 Episode
限制内，实验主要考察游戏前期的探索、障碍处理、生存与下楼推进，而不是完整
通关。</p>
<p>分数奖励 NetHack 认可的游戏进展，同时惩罚角色持续冻结在原地的重复步骤。它为
Agent 提供主要优化信号，而地下城深度、游戏分数和冻结步比例则用于解释这些分数
对应了怎样的行为。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="从完整轨迹中学习">从完整轨迹中学习<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/nethack-policy-evolution/#%E4%BB%8E%E5%AE%8C%E6%95%B4%E8%BD%A8%E8%BF%B9%E4%B8%AD%E5%AD%A6%E4%B9%A0" class="hash-link" aria-label="从完整轨迹中学习的直接链接" title="从完整轨迹中学习的直接链接" translate="no">​</a></h2>
<p>许多较弱的 NetHack Policy 并不会崩溃。它们会继续运行，却可能不断推撞一块
巨石、反复尝试穿过铁栏、在两个格子之间来回移动，或者站在楼梯上却不下楼。
聚合分数能说明 Policy 表现不佳，却不能指出行为究竟在哪里出了问题。</p>
<p>因此，每次训练 Submission 之后，Environment 都会返回所有评测 Episodes 的完整
Policy 可见轨迹。Agent 可以检查位置、Actions、消息、状态变化与重复状态，再将
这些模式对应回源代码。</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">提交可执行 Policy</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        ↓</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">检查完整训练轨迹</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        ↓</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">定位行为失败</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        ↓</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">重写记忆、寻路或交互规则</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        ↓</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">提交新的 Program</span><br></div></code></pre></div></div>
<p>Environment 提供证据，而不是诊断。选择检查哪些 Episodes、判断哪些模式值得关注，
仍然是 Coding Agent 工作的一部分。持久的改进保存在可执行 Program 中，而不是
模型权重或跨 Episode 继承的隐藏状态中。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="实验">实验<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/nethack-policy-evolution/#%E5%AE%9E%E9%AA%8C" class="hash-link" aria-label="实验的直接链接" title="实验的直接链接" translate="no">​</a></h2>
<p>我们让三个 GPT-5.6 模型变体——Luna、Terra 和 Sol——通过 Codex 运行。每个 Agent
都从同一个 packaged baseline 开始，并可以利用训练分数与轨迹改进它。实验关闭了
可选的 NetHack 优化 Skill，因此 Agent 必须自行形成分析与修改流程。</p>
<p>Baseline 已经能够进行简单的局部探索。它记录位置访问次数，通常优先选择访问较少
的相邻格子，在存在其他选择时避免立刻折返，定期搜索，踢开可见的关闭房门，并在
饥饿时吃掉可识别的食物。但它不会构建显式地图、规划前往远处目标的路线、记忆
失败的边，也不会把下楼作为一个持续目标。</p>
<table><thead><tr><th>设置</th><th>值</th></tr></thead><tbody><tr><td>Environment</td><td>NLE 1.3.0 · NetHack 3.6.7</td></tr><tr><td>任务</td><td><code>NetHackScore-v0</code> · 23 个 Actions</td></tr><tr><td>Episode 限制</td><td>5,000 个 Policy steps</td></tr><tr><td>训练额度</td><td>最多 128 个 Episodes</td></tr><tr><td>最终 Assessment</td><td>256 个 held-out Episodes</td></tr><tr><td>可选 NetHack Skill</td><td>关闭</td></tr></tbody></table>
<p>训练额度是上限，并不要求必须用完。Sol 使用了全部 128 个 Episodes，Terra 使用了
68 个，Luna 使用了 40 个，随后结束运行。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="结果">结果<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/nethack-policy-evolution/#%E7%BB%93%E6%9E%9C" class="hash-link" aria-label="结果的直接链接" title="结果的直接链接" translate="no">​</a></h2>
<p>Sol 在这次实验中产生了最强的最终 Policy。它的平均 Assessment return 为
<code>204.026</code>，平均游戏分数为 <code>208.230</code>，平均地下城深度为 <code>2.867</code>。其最深的
held-out Episode 到达了第 11 层。</p>
<table><thead><tr><th>Agent 路线</th><th style="text-align:right">使用的训练额度</th><th style="text-align:right">Submissions</th><th style="text-align:right">Assessment return</th><th style="text-align:right">平均游戏分数</th><th style="text-align:right">平均 / 最大深度</th><th style="text-align:right">冻结步</th></tr></thead><tbody><tr><td><strong>GPT-5.6 Sol + Codex</strong></td><td style="text-align:right">128 / 128</td><td style="text-align:right">8</td><td style="text-align:right"><strong>204.026</strong></td><td style="text-align:right"><strong>208.230</strong></td><td style="text-align:right"><strong>2.867 / 11</strong></td><td style="text-align:right"><strong>27.53%</strong></td></tr><tr><td>GPT-5.6 Terra + Codex</td><td style="text-align:right">68 / 128</td><td style="text-align:right">4</td><td style="text-align:right">80.237</td><td style="text-align:right">87.094</td><td style="text-align:right">1.082 / 4</td><td style="text-align:right">33.77%</td></tr><tr><td>GPT-5.6 Luna + Codex</td><td style="text-align:right">40 / 128</td><td style="text-align:right">4</td><td style="text-align:right">63.773</td><td style="text-align:right">70.777</td><td style="text-align:right">1.094 / 4</td><td style="text-align:right">35.75%</td></tr></tbody></table>
<p>三个最终选中的 Policy 都在 held-out Assessment 中完成了全部 Episodes，没有出现
Policy 执行失败。它们都没有完成 ascension。因此这些结果衡量的是游戏前期探索、
生存和地下城推进，而不是对完整 NetHack 的掌握。</p>
<p><img decoding="async" loading="lazy" alt="Sol 最终选择的 Policy 在一个 NetHack 训练 Episode 中的完整语义回放。回放覆盖
全部 1,269 个 Policy steps，到达地下城第 11 层，最高游戏分数为 860，最终以死亡
结束。" src="https://linzwcs.github.io/EvoPolicyGym/zh-CN/assets/images/nle-sol-policy-training-replay-124139790b64f4be4cf266da290d550a.gif" width="900" height="570" class="img_ev3q"></p>
<p><em>第 000008 次 Submission 的第 16 个训练 Episode。这段回放展示了 Agent 编写的
Policy 如何从第一次 observation 开始自主行动，直至 Episode 结束。它是一个具有
代表性的训练轨迹，不属于表格中报告的 held-out Assessment。</em></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="baseline-的能力边界">Baseline 的能力边界<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/nethack-policy-evolution/#baseline-%E7%9A%84%E8%83%BD%E5%8A%9B%E8%BE%B9%E7%95%8C" class="hash-link" aria-label="Baseline 的能力边界的直接链接" title="Baseline 的能力边界的直接链接" translate="no">​</a></h2>
<p>Baseline 能够回答一个有用的局部问题：</p>
<blockquote>
<p>哪一个可见的相邻格子访问次数最少？</p>
</blockquote>
<p>但它还无法回答更完整的导航问题：</p>
<blockquote>
<p>如何在一座充满不确定性的多层地下城中构建并维护一条路线？</p>
</blockquote>
<p>两者之间的差距，正是 Policy evolution 的主要机会。要超越 baseline，Policy
需要在一个位置离开屏幕后仍然保留相关知识，跨越多个房间追踪目标，并在 Action
失败后修改计划。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="sol-构建了怎样的策略">Sol 构建了怎样的策略？<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/nethack-policy-evolution/#sol-%E6%9E%84%E5%BB%BA%E4%BA%86%E6%80%8E%E6%A0%B7%E7%9A%84%E7%AD%96%E7%95%A5" class="hash-link" aria-label="Sol 构建了怎样的策略？的直接链接" title="Sol 构建了怎样的策略？的直接链接" translate="no">​</a></h2>
<p>Sol 将局部探索 baseline 转化为一个更有结构的导航系统。它的最终 Policy 结合了
三个相互增强的思路。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="持久的空间记忆">持久的空间记忆<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/nethack-policy-evolution/#%E6%8C%81%E4%B9%85%E7%9A%84%E7%A9%BA%E9%97%B4%E8%AE%B0%E5%BF%86" class="hash-link" aria-label="持久的空间记忆的直接链接" title="持久的空间记忆的直接链接" translate="no">​</a></h3>
<p>Policy 记录已经发现的地形、路线、目标和移动结果。它不再只是反复选择相邻格子，
而是能够利用先前的 observation，在已知房间和走廊中导航。角色离开当前位置后，
之前获得的信息仍然有用。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="目标导向的探索">目标导向的探索<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/nethack-policy-evolution/#%E7%9B%AE%E6%A0%87%E5%AF%BC%E5%90%91%E7%9A%84%E6%8E%A2%E7%B4%A2" class="hash-link" aria-label="目标导向的探索的直接链接" title="目标导向的探索的直接链接" translate="no">​</a></h3>
<p>Sol 将地下城推进变成了一个显式目标。当 Policy 已经知道向下楼梯的位置时，它会
保留这个目标、规划路线返回并使用楼梯；当还不知道楼梯位置时，它会寻找尚未探索
的空间，而不只是选择当前可见范围内访问最少的格子。</p>
<p>这使地下城深度不再只是 Episode 结束后观察到的指标，而成为写在可执行策略中的
目标。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="失败检测与恢复">失败检测与恢复<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/nethack-policy-evolution/#%E5%A4%B1%E8%B4%A5%E6%A3%80%E6%B5%8B%E4%B8%8E%E6%81%A2%E5%A4%8D" class="hash-link" aria-label="失败检测与恢复的直接链接" title="失败检测与恢复的直接链接" translate="no">​</a></h3>
<p>NetHack 中的移动可能因为墙壁、巨石、铁栏、生物、房门或对地图的过期理解而失败。
Sol 会将计划中的移动与下一个 observation 进行比较。如果预期的状态转移没有发生，
Policy 就可以把路线标记为阻塞、丢弃无效目标，并选择其他路径，而不是继续重复
同一个 Action。</p>
<p>最终得到的能力并不是一组互不相关的特殊处理，而是一个更通用的循环：观察结果、
更新内部地图，然后重新规划。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="agent-如何使用-environment-feedback">Agent 如何使用 Environment Feedback<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/nethack-policy-evolution/#agent-%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8-environment-feedback" class="hash-link" aria-label="Agent 如何使用 Environment Feedback的直接链接" title="Agent 如何使用 Environment Feedback的直接链接" translate="no">​</a></h2>
<p><strong>Luna——记住障碍。</strong> Luna 发现一些轨迹主要由反复撞击巨石或尝试穿过铁栏组成。
它加入了对失败方向的记忆，减少了对静态障碍的立即重试。</p>
<p><strong>Terra——摆脱循环并使用楼梯。</strong> Terra 引入了 anti-loop 行为和显式下楼逻辑。
最终选中的最强 candidate 来自一个较早的版本，这说明继续编辑并不一定会产生更好
的 Policy。</p>
<p><strong>Sol——将局部修复组织成导航系统。</strong> Sol 结合记忆路线、面向楼梯的推进、阻塞边
处理和目标恢复。它没有把每次失败都看作孤立补丁，而是通过位置、路线、目标和
移动结果的共享模型将这些经验连接起来。</p>
<p>在每个案例中，持久的结果都不是 Agent 对轨迹的解释。这些经验必须成为代码，才能
在 held-out evaluation 中独立接收 observations 并返回 Actions。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="发现与边界">发现与边界<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/nethack-policy-evolution/#%E5%8F%91%E7%8E%B0%E4%B8%8E%E8%BE%B9%E7%95%8C" class="hash-link" aria-label="发现与边界的直接链接" title="发现与边界的直接链接" translate="no">​</a></h2>
<p>完整语义轨迹足以让 Agent 定位行为失败并完成有效的 Policy 修改，不需要
Environment 预先编写诊断。这项实验也说明，解释 NetHack 行为需要多个指标：
return 用于排序 candidates，而深度、游戏分数和冻结步比例则揭示探索与推进的不同方面。</p>
<p>这些结果仍然只是初步研究。Agent 使用的训练额度并不相同，每条模型路线也只有
一次主要 Run。在最多 128 个 Episodes 的短训练上限下，Coding Agent 搜索可能因
随机性产生波动：相同 Environment 配置下，另一次 Terra Run 得分为 <code>49.464</code>，
而这里报告的结果为 <code>80.237</code>。</p>
<p>因此，表格应当被理解为这些 Agent 在对应 Runs 中构建出了更好的 NetHack Policy，
而不是 Luna、Terra 和 Sol 的普遍排名。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="代码与说明">代码与说明<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/nethack-policy-evolution/#%E4%BB%A3%E7%A0%81%E4%B8%8E%E8%AF%B4%E6%98%8E" class="hash-link" aria-label="代码与说明的直接链接" title="代码与说明的直接链接" translate="no">​</a></h2>
<ul>
<li class=""><a href="https://github.com/Linzwcs/EvoPolicyGym/tree/main/environments/nle/nethack" target="_blank" rel="noopener noreferrer" class="">NLE NetHack Benchmark</a></li>
<li class=""><a class="" href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/docs/evaluation/">Evaluation 与 Runs</a></li>
<li class=""><a class="" href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/docs/policy/">Policy 边界</a></li>
</ul>
<p>EvoPolicyGym adapter 使用 MIT 许可证。NLE 与 NetHack 是独立依赖，并分别受各自的
许可证约束。</p>]]></content>
        <author>
            <name>EvoPolicyGym contributors</name>
            <uri>https://github.com/Linzwcs/EvoPolicyGym</uri>
        </author>
        <category label="Benchmark" term="Benchmark"/>
        <category label="NetHack" term="NetHack"/>
        <category label="Experiment" term="Experiment"/>
        <category label="Policy Evolution" term="Policy Evolution"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[让 Coding Agent 编写打《小丑牌》的策略系统]]></title>
        <id>https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/balatro-policy-evolution/</id>
        <link href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/balatro-policy-evolution/"/>
        <updated>2026-07-29T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[我们接入了《小丑牌》环境，并比较Luna、Terra 与 Sol 在1024的环境交互budget下的策略优化结果引出的一些启发和思考。]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="小丑牌是什么">《小丑牌》是什么<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/balatro-policy-evolution/#%E5%B0%8F%E4%B8%91%E7%89%8C%E6%98%AF%E4%BB%80%E4%B9%88" class="hash-link" aria-label="《小丑牌》是什么的直接链接" title="《小丑牌》是什么的直接链接" translate="no">​</a></h2>
<p>《小丑牌》（Balatro）是一款围绕扑克牌型计分的 roguelike 牌组构筑游戏。玩家
从一副基础扑克牌开始一局 Run，通过出牌获得分数、通过商店强化构筑，最终击败
Ante 8 的 Boss Blind 完成通关。每局的抽牌、商店和奖励都会变化，失败后重新
开始一局。</p>
<p>一局游戏反复执行同一个循环：</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">选择 Blind → 出牌或弃牌 → 达到目标分数 → 结算金钱 → 商店构筑 → 下一个 Blind</span><br></div></code></pre></div></div>
<ul>
<li class=""><strong>关卡</strong>：一局分为 8 个 Ante，每个 Ante 包含 Small Blind、Big Blind 和
Boss Blind。Small Blind 与 Big Blind 可以跳过并换取 Tag；Boss Blind 会
加入一条改变本轮玩法的规则。</li>
<li class=""><strong>出牌</strong>：玩家每次从手牌中选择 1–5 张牌。对子、两对、顺子、同花等牌型决定
基础 Chips 和 Mult，计分牌与其他效果继续修改两者，这一手最终获得
<code>Chips × Mult</code> 分数。</li>
<li class=""><strong>过关</strong>：同一个 Blind 中，多次出牌的分数会累积。达到目标 Chips 后通过
Blind；出牌次数耗尽仍未达标则结束本局。</li>
<li class=""><strong>弃牌</strong>：discard 可以丢弃不需要的牌并抽取新牌，用有限次数改善后续手牌。</li>
<li class=""><strong>构筑</strong>：通过 Blind 后获得金钱并进入商店。Joker 改变计分方式，Planet
提升牌型等级，Tarot 和 Spectral 改造牌组，Voucher 与 Booster 提供长期
强化，reroll 用金钱刷新商店。</li>
</ul>
<p>游戏的核心是在当前过关与长期成长之间分配资源：选择哪一手牌、何时弃牌、购买和
排列哪些 Joker、是否保留现金、要不要跳过 Blind，以及怎样处理 Boss 规则。这些决策共同组成一套完整的《小丑牌》策略。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="小丑牌接入evopolicygym">《小丑牌》接入EvoPolicyGym<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/balatro-policy-evolution/#%E5%B0%8F%E4%B8%91%E7%89%8C%E6%8E%A5%E5%85%A5evopolicygym" class="hash-link" aria-label="《小丑牌》接入EvoPolicyGym的直接链接" title="《小丑牌》接入EvoPolicyGym的直接链接" translate="no">​</a></h2>
<p>在 EvoPolicyGym v0.3.0 中，我们以 vendored 方式接入了非官方 Balatro 引擎
<a href="https://github.com/TylerFlar/jackdaw-balatro" target="_blank" rel="noopener noreferrer" class="">Jackdaw</a>，并基于它实现了 Balatro
评测环境。</p>
<p>Policy每步可以获取公开 observation中包括：</p>
<ul>
<li class="">Ante、Blind、目标分数、剩余手数与弃牌次数；</li>
<li class="">手牌、Joker、Consumable、牌组公开统计和已有牌型等级；</li>
<li class="">当前商店、Booster、Voucher、Tag 与现金；</li>
<li class="">当前 phase 下严格枚举的合法 Actions；</li>
<li class="">可见对象在固定引擎版本中的规则说明。</li>
</ul>
<p>Policy 返回语义化 Action，例如出牌、弃牌、购买、出售、reroll、开包或调整
Joker 顺序。无效 Action 不会被环境“修好”，而是直接记为 Policy failure。
同一个 Episode 内可以保存状态，但每个新 Episode 都会创建全新的 Policy 实例。</p>
<p>最终policy得分由下面公式计算。</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">通过的 Blind 数 + 1000 × 是否通关</span><br></div></code></pre></div></div>
<p>每通过一个 Blind 得 1 分，完成整局额外获得 1000 分。这个设计一方面保留了
“通关”这一最终目标，另一方面让尚未通关的 Policy 仍能通过平均推进距离获得连续
反馈。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="简单介绍-evopolicygym-的评测流程">简单介绍 EvoPolicyGym 的评测流程<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/balatro-policy-evolution/#%E7%AE%80%E5%8D%95%E4%BB%8B%E7%BB%8D-evopolicygym-%E7%9A%84%E8%AF%84%E6%B5%8B%E6%B5%81%E7%A8%8B" class="hash-link" aria-label="简单介绍 EvoPolicyGym 的评测流程的直接链接" title="简单介绍 EvoPolicyGym 的评测流程的直接链接" translate="no">​</a></h2>
<p>在一次 EvoPolicyGym Run 中，Coding Agent 从初始 Program 出发，反复提交策略、
在训练 Episodes 上评测，并根据分数和 replay 继续优化。Agent 完成后，
Validation 选择最终 Program，Assessment 再使用 held-out test Episodes 得到
最终成绩。每次提交的 Program、反馈、replay 和优化记录都会保存在 Run 数据中。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="实验">实验<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/balatro-policy-evolution/#%E5%AE%9E%E9%AA%8C" class="hash-link" aria-label="实验的直接链接" title="实验的直接链接" translate="no">​</a></h2>
<p>我们比较 packaged baseline，以及 Luna、Terra、Sol 三个 Coding Agent 优化
Run 最终交接的 Program。三个 Agent 都从同一个 baseline 开始，使用相同的训练
Episode pool 和环境交互 budget。</p>
<p>Baseline 是一套确定性的扑克牌型策略。它会穷举手牌中所有 1–5 张组合，按照传统
牌型等级和牌面点数选择出牌；进入商店后购买第一张买得起的 Joker，开包时选择
第一张 Joker。它不使用 discard、Consumable 和 reroll，也不管理 Joker 组合与
经济。</p>
<p>Luna、Terra 和 Sol 的训练 Episode pool 与总 Episode budget 均为 1024。
优化结束后，我们冻结三个 Agent 最终选择的 Program，并在完全相同的 128 个
held-out test Episodes 上评测。四个 Program 的评测条件如下：</p>
<table><thead><tr><th>实验</th><th>Agent</th><th>Reasoning</th><th style="text-align:right">训练 Episode budget</th><th style="text-align:right">Test Episodes</th></tr></thead><tbody><tr><td>Packaged baseline</td><td>—</td><td>—</td><td style="text-align:right">0</td><td style="text-align:right">128</td></tr><tr><td>Luna</td><td><code>gpt-5.6-luna</code></td><td><code>xhigh</code></td><td style="text-align:right">1024</td><td style="text-align:right">128</td></tr><tr><td>Terra</td><td><code>gpt-5.6-terra</code></td><td><code>xhigh</code></td><td style="text-align:right">1024</td><td style="text-align:right">128</td></tr><tr><td>Sol</td><td><code>gpt-5.6-sol</code></td><td><code>xhigh</code></td><td style="text-align:right">1024</td><td style="text-align:right">128</td></tr></tbody></table>
<p>实验使用 Red Deck、White Stake，Run seed 为 <code>20260729</code>，单个 Episode 的超时
时间为 60 秒。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="实验结果">实验结果<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/balatro-policy-evolution/#%E5%AE%9E%E9%AA%8C%E7%BB%93%E6%9E%9C" class="hash-link" aria-label="实验结果的直接链接" title="实验结果的直接链接" translate="no">​</a></h2>
<p><img decoding="async" loading="lazy" alt="四个 Program 的 Balatro held-out test 结果。Sol 平均通过 10.45 个 Blind，
在 128 局中通关 5 次，最终均分 49.52。" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA5NjAgNDQyIiByb2xlPSJpbWciIGFyaWEtbGFiZWxsZWRieT0idGl0bGUgZGVzY3JpcHRpb24iPgogIDx0aXRsZSBpZD0idGl0bGUiPkJhbGF0cm8gaGVsZC1vdXQgdGVzdCByZXN1bHRzPC90aXRsZT4KICA8ZGVzYyBpZD0iZGVzY3JpcHRpb24iPkhvcml6b250YWwgYmFycyBjb21wYXJlIHRoZSBhdmVyYWdlIG51bWJlciBvZiBCbGluZHMgY2xlYXJlZCBieSBQYWNrYWdlZCBiYXNlbGluZSwgTHVuYSwgVGVycmEsIGFuZCBTb2wuIFNvbCBjbGVhcmVkIDEwLjQ1IEJsaW5kcyBvbiBhdmVyYWdlIGFuZCB3b24gNSBvZiAxMjggcnVucy48L2Rlc2M+CgogIDxnIGZvbnQtZmFtaWx5PSInQXZlbmlyIE5leHQnLCAnUGluZ0ZhbmcgU0MnLCAnTm90byBTYW5zIENKSyBTQycsIHNhbnMtc2VyaWYiPgogICAgPHRleHQgeD0iMTk2IiB5PSIyOCIgZmlsbD0iIzUwNTI0ZCIgZm9udC1zaXplPSIxMyI+5bmz5Z2H6YCa6L+HIEJsaW5kPC90ZXh0PgogICAgPHRleHQgeD0iNzU4IiB5PSIyOCIgZmlsbD0iIzUwNTI0ZCIgZm9udC1zaXplPSIxMyIgdGV4dC1hbmNob3I9Im1pZGRsZSI+6YCa5YWzPC90ZXh0PgogICAgPHRleHQgeD0iODg2IiB5PSIyOCIgZmlsbD0iIzUwNTI0ZCIgZm9udC1zaXplPSIxMyIgdGV4dC1hbmNob3I9ImVuZCI+5pyA57uI5Z2H5YiGPC90ZXh0PgoKICAgIDxnIHN0cm9rZT0iI2QzZDBjNyIgc3Ryb2tlLXdpZHRoPSIxIj4KICAgICAgPGxpbmUgeDE9IjE5NiIgeTE9IjQ4IiB4Mj0iMTk2IiB5Mj0iMzYwIi8+CiAgICAgIDxsaW5lIHgxPSIzNDkiIHkxPSI0OCIgeDI9IjM0OSIgeTI9IjM2MCIvPgogICAgICA8bGluZSB4MT0iNTAzIiB5MT0iNDgiIHgyPSI1MDMiIHkyPSIzNjAiLz4KICAgICAgPGxpbmUgeDE9IjY1NiIgeTE9IjQ4IiB4Mj0iNjU2IiB5Mj0iMzYwIi8+CiAgICA8L2c+CgogICAgPGcgZmlsbD0iIzhiOGU4NSIgZm9udC1zaXplPSIxMiI+CiAgICAgIDx0ZXh0IHg9IjE5NiIgeT0iMzg0IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj4wPC90ZXh0PgogICAgICA8dGV4dCB4PSIzNDkiIHk9IjM4NCIgdGV4dC1hbmNob3I9Im1pZGRsZSI+NDwvdGV4dD4KICAgICAgPHRleHQgeD0iNTAzIiB5PSIzODQiIHRleHQtYW5jaG9yPSJtaWRkbGUiPjg8L3RleHQ+CiAgICAgIDx0ZXh0IHg9IjY1NiIgeT0iMzg0IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj4xMjwvdGV4dD4KICAgIDwvZz4KCiAgICA8Zz4KICAgICAgPHRleHQgeD0iMjAiIHk9IjkyIiBmaWxsPSIjMTcxODE1IiBmb250LXNpemU9IjE1IiBmb250LXdlaWdodD0iNTAwIj5Tb2w8L3RleHQ+CiAgICAgIDxyZWN0IHg9IjE5NiIgeT0iNzMiIHdpZHRoPSI0NjAiIGhlaWdodD0iMjQiIHJ4PSI0IiBmaWxsPSIjZjRmNGYxIi8+CiAgICAgIDxyZWN0IHg9IjE5NiIgeT0iNzMiIHdpZHRoPSI0MDEiIGhlaWdodD0iMjQiIHJ4PSI0IiBmaWxsPSIjYzg0YjI3Ii8+CiAgICAgIDx0ZXh0IHg9IjYwOSIgeT0iOTEiIGZpbGw9IiMxNzE4MTUiIGZvbnQtc2l6ZT0iMTQiIGZvbnQtd2VpZ2h0PSI1MDAiPjEwLjQ1PC90ZXh0PgogICAgICA8Y2lyY2xlIGN4PSI3MjMiIGN5PSI4NCIgcj0iNSIgZmlsbD0iI2M4NGIyNyIvPgogICAgICA8dGV4dCB4PSI3NTgiIHk9IjkxIiBmaWxsPSIjMTcxODE1IiBmb250LXNpemU9IjE1IiBmb250LXdlaWdodD0iNTAwIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj41IC8gMTI4PC90ZXh0PgogICAgICA8dGV4dCB4PSI4ODYiIHk9IjkxIiBmaWxsPSIjMTcxODE1IiBmb250LXNpemU9IjE1IiBmb250LXdlaWdodD0iNTAwIiB0ZXh0LWFuY2hvcj0iZW5kIj40OS41MjwvdGV4dD4KICAgIDwvZz4KCiAgICA8Zz4KICAgICAgPHRleHQgeD0iMjAiIHk9IjE2OSIgZmlsbD0iIzE3MTgxNSIgZm9udC1zaXplPSIxNSIgZm9udC13ZWlnaHQ9IjUwMCI+VGVycmE8L3RleHQ+CiAgICAgIDxyZWN0IHg9IjE5NiIgeT0iMTUwIiB3aWR0aD0iNDYwIiBoZWlnaHQ9IjI0IiByeD0iNCIgZmlsbD0iI2Y0ZjRmMSIvPgogICAgICA8cmVjdCB4PSIxOTYiIHk9IjE1MCIgd2lkdGg9IjM0MSIgaGVpZ2h0PSIyNCIgcng9IjQiIGZpbGw9IiMxNzZiNmQiLz4KICAgICAgPHRleHQgeD0iNTQ5IiB5PSIxNjgiIGZpbGw9IiMxNzE4MTUiIGZvbnQtc2l6ZT0iMTQiIGZvbnQtd2VpZ2h0PSI1MDAiPjguODk8L3RleHQ+CiAgICAgIDx0ZXh0IHg9Ijc1OCIgeT0iMTY4IiBmaWxsPSIjOGI4ZTg1IiBmb250LXNpemU9IjE1IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIj4wIC8gMTI4PC90ZXh0PgogICAgICA8dGV4dCB4PSI4ODYiIHk9IjE2OCIgZmlsbD0iIzE3MTgxNSIgZm9udC1zaXplPSIxNSIgdGV4dC1hbmNob3I9ImVuZCI+OC44OTwvdGV4dD4KICAgIDwvZz4KCiAgICA8Zz4KICAgICAgPHRleHQgeD0iMjAiIHk9IjI0NiIgZmlsbD0iIzE3MTgxNSIgZm9udC1zaXplPSIxNSIgZm9udC13ZWlnaHQ9IjUwMCI+THVuYTwvdGV4dD4KICAgICAgPHJlY3QgeD0iMTk2IiB5PSIyMjciIHdpZHRoPSI0NjAiIGhlaWdodD0iMjQiIHJ4PSI0IiBmaWxsPSIjZjRmNGYxIi8+CiAgICAgIDxyZWN0IHg9IjE5NiIgeT0iMjI3IiB3aWR0aD0iMzAyIiBoZWlnaHQ9IjI0IiByeD0iNCIgZmlsbD0iIzE3NmI2ZCIvPgogICAgICA8dGV4dCB4PSI1MTAiIHk9IjI0NSIgZmlsbD0iIzE3MTgxNSIgZm9udC1zaXplPSIxNCIgZm9udC13ZWlnaHQ9IjUwMCI+Ny44NzwvdGV4dD4KICAgICAgPHRleHQgeD0iNzU4IiB5PSIyNDUiIGZpbGw9IiM4YjhlODUiIGZvbnQtc2l6ZT0iMTUiIHRleHQtYW5jaG9yPSJtaWRkbGUiPjAgLyAxMjg8L3RleHQ+CiAgICAgIDx0ZXh0IHg9Ijg4NiIgeT0iMjQ1IiBmaWxsPSIjMTcxODE1IiBmb250LXNpemU9IjE1IiB0ZXh0LWFuY2hvcj0iZW5kIj43Ljg3PC90ZXh0PgogICAgPC9nPgoKICAgIDxnPgogICAgICA8dGV4dCB4PSIyMCIgeT0iMzIzIiBmaWxsPSIjMTcxODE1IiBmb250LXNpemU9IjE1IiBmb250LXdlaWdodD0iNTAwIj5QYWNrYWdlZCBiYXNlbGluZTwvdGV4dD4KICAgICAgPHJlY3QgeD0iMTk2IiB5PSIzMDQiIHdpZHRoPSI0NjAiIGhlaWdodD0iMjQiIHJ4PSI0IiBmaWxsPSIjZjRmNGYxIi8+CiAgICAgIDxyZWN0IHg9IjE5NiIgeT0iMzA0IiB3aWR0aD0iMTQyIiBoZWlnaHQ9IjI0IiByeD0iNCIgZmlsbD0iIzhiOGU4NSIvPgogICAgICA8dGV4dCB4PSIzNTAiIHk9IjMyMiIgZmlsbD0iIzE3MTgxNSIgZm9udC1zaXplPSIxNCIgZm9udC13ZWlnaHQ9IjUwMCI+My43MDwvdGV4dD4KICAgICAgPHRleHQgeD0iNzU4IiB5PSIzMjIiIGZpbGw9IiM4YjhlODUiIGZvbnQtc2l6ZT0iMTUiIHRleHQtYW5jaG9yPSJtaWRkbGUiPjAgLyAxMjg8L3RleHQ+CiAgICAgIDx0ZXh0IHg9Ijg4NiIgeT0iMzIyIiBmaWxsPSIjMTcxODE1IiBmb250LXNpemU9IjE1IiB0ZXh0LWFuY2hvcj0iZW5kIj4zLjcwPC90ZXh0PgogICAgPC9nPgoKICAgIDxsaW5lIHgxPSIyMCIgeTE9IjQwNiIgeDI9Ijk0MCIgeTI9IjQwNiIgc3Ryb2tlPSIjZDNkMGM3IiBzdHJva2Utd2lkdGg9IjEiLz4KICAgIDx0ZXh0IHg9IjIwIiB5PSI0MzAiIGZpbGw9IiM4YjhlODUiIGZvbnQtc2l6ZT0iMTIiPjEyOCDkuKogaGVsZC1vdXQgdGVzdCBFcGlzb2RlcyDCtyBSZWQgRGVjayDCtyBXaGl0ZSBTdGFrZTwvdGV4dD4KICA8L2c+Cjwvc3ZnPgo=" width="960" height="442" class="img_ev3q"></p>
<p>Sol 是唯一实现可通关策略的模型：它平均通过 10.45 个 Blind，是 baseline 的
2.83 倍，并在 128 局中通关 5 次。Luna 和 Terra 的平均推进距离也超过 baseline
的两倍，但没有通关。减少早期错误可以走得更远，完成 Run 还需要一套连贯的长期
构筑策略。</p>
<p><img decoding="async" loading="lazy" alt="Sol 最终 Policy 在 Balatro held-out 测试中的一次获胜回放。回放从 Ante 1
推进到 Ante 9，通过 21 个 Blind，并以 1021 分完成 Run。" src="https://linzwcs.github.io/EvoPolicyGym/zh-CN/assets/images/balatro-sol-winning-replay-57c374eb48d7edff1a9115f4f3cd44b7.gif" width="960" height="540" class="img_ev3q"></p>
<p><em>来自同一组 128-Episode 测试的 held-out case index 41。画面由 Benchmark 的
语义 replay 几何化渲染，不包含 Balatro 官方游戏素材。</em></p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="baseline-的能力边界">Baseline 的能力边界<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/balatro-policy-evolution/#baseline-%E7%9A%84%E8%83%BD%E5%8A%9B%E8%BE%B9%E7%95%8C" class="hash-link" aria-label="Baseline 的能力边界的直接链接" title="Baseline 的能力边界的直接链接" translate="no">​</a></h2>
<p>Packaged baseline 会穷举当前手牌中所有 1–5 张组合，优先选择传统牌型等级和
牌面点数更高的组合；进入商店和开包后，则购买第一张满足条件的 Joker。</p>
<p>它解决了“当前哪组牌型更高”，却没有把实际得分、弃牌、Joker 组合、经济和 Boss
规则连接起来。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="sol-写出了什么策略">Sol 写出了什么策略<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/balatro-policy-evolution/#sol-%E5%86%99%E5%87%BA%E4%BA%86%E4%BB%80%E4%B9%88%E7%AD%96%E7%95%A5" class="hash-link" aria-label="Sol 写出了什么策略的直接链接" title="Sol 写出了什么策略的直接链接" translate="no">​</a></h2>
<p>Sol 建立了一个近似局面模型，再按游戏阶段执行相互配合的启发式策略。最终 Policy
的关键变化可以归纳为三个方面。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="估分与手牌规划">估分与手牌规划<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/balatro-policy-evolution/#%E4%BC%B0%E5%88%86%E4%B8%8E%E6%89%8B%E7%89%8C%E8%A7%84%E5%88%92" class="hash-link" aria-label="估分与手牌规划的直接链接" title="估分与手牌规划的直接链接" translate="no">​</a></h3>
<p>Sol 仍然穷举 1–5 张组合，但评价对象变成了预计的 <code>Chips × Mult</code>。估算同时考虑
牌型等级、计分牌、Enhancement、Edition、持有牌效果和 Joker 组合。</p>
<p>Policy 再结合当前目标分数、剩余手数和弃牌次数，决定立即出牌还是继续找牌。它会
保护具有持有价值的牌，也会在没有 discard 时用低价值牌换取新手牌。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="joker-构筑与经济管理">Joker 构筑与经济管理<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/balatro-policy-evolution/#joker-%E6%9E%84%E7%AD%91%E4%B8%8E%E7%BB%8F%E6%B5%8E%E7%AE%A1%E7%90%86" class="hash-link" aria-label="Joker 构筑与经济管理的直接链接" title="Joker 构筑与经济管理的直接链接" translate="no">​</a></h3>
<p>Sol 会估算 Joker 的价值，组合稳定的 Chips、Mult 和 X Mult，并根据效果依赖调整
顺序。槽位满时，只有候选 Joker 明显更强才会替换已有组件。</p>
<p>商店决策也与构筑相连：Policy 根据 Ante、现金和关键缺口决定购买、保留利息或
reroll。现金不再只影响当前商店，而是用于提升后续回合的强度。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="跨回合状态管理">跨回合状态管理<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/balatro-policy-evolution/#%E8%B7%A8%E5%9B%9E%E5%90%88%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86" class="hash-link" aria-label="跨回合状态管理的直接链接" title="跨回合状态管理的直接链接" translate="no">​</a></h3>
<p>Policy 会记录商店、开包、牌型和跳过 Blind 等状态，并根据 Boss 规则调整行为。
得分估算影响弃牌，弃牌影响过关概率，过关后的经济又改变下一轮构筑，这些决策
由此形成了一个完整循环。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="模型如何利用环境反馈">模型如何利用环境反馈<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/balatro-policy-evolution/#%E6%A8%A1%E5%9E%8B%E5%A6%82%E4%BD%95%E5%88%A9%E7%94%A8%E7%8E%AF%E5%A2%83%E5%8F%8D%E9%A6%88" class="hash-link" aria-label="模型如何利用环境反馈的直接链接" title="模型如何利用环境反馈的直接链接" translate="no">​</a></h2>
<p>在相同的 baseline、训练数据和 budget 下，Sol 是唯一完成 Run 的模型。它更有效
地利用了 replay 和分数反馈，把局部经验组织成涵盖出牌、构筑和经济的完整策略，
更像一名经验丰富的玩家。</p>
<p>Sol 的 Policy 也暴露了工程问题：约 1860 行逻辑集中在一个文件中，耦合度较高。
下一步是拆分策略模块，让它更容易测试、校准和继续优化。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="下一步可以做的工作">下一步可以做的工作<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/balatro-policy-evolution/#%E4%B8%8B%E4%B8%80%E6%AD%A5%E5%8F%AF%E4%BB%A5%E5%81%9A%E7%9A%84%E5%B7%A5%E4%BD%9C" class="hash-link" aria-label="下一步可以做的工作的直接链接" title="下一步可以做的工作的直接链接" translate="no">​</a></h2>
<p>第一个方向是 Skill。有效的 Skill 不只补充领域知识，还可以提供模块划分、replay
分析和测试方法。使用相同的 Agent 和 budget 对比有无 Skill，可以同时观察最终
得分与 Policy 的工程结构。</p>
<p>第二个方向是跨环境 RL。目标不是记住某个环境的规则，而是学习定位失败、提出假设、
设计实验和更新策略的方法，并将这种能力迁移到未见过的环境。</p>
<p>除此之外，在接入各个环境的过程中，我们发现了另一个有价值、但还欠研究的问题：
Agent 能否通过观察外部系统，自行构建适合训练和评测的环境？例如，Agent 能否
理解一款游戏的核心规则，实现一个行为等价的环境引擎，剥离美术、音频等与策略
无关的信息，只保留状态、动作和反馈？</p>
<p>这需要衡量 Agent 能否正确抽象状态、动作、反馈和评测规则。目前我们主要评测
Agent 使用环境优化策略的能力，对构建环境本身还缺少系统度量。如果 Agent 能做好
这一步，它构建的环境就可以接入 EvoPolicyGym，再由 Agent 继续优化其中的策略。
这种从观察、建模到优化的完整能力，将帮助未来的 Agent 更快适应新环境，并构建
有效的决策系统。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="代码与说明">代码与说明<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/balatro-policy-evolution/#%E4%BB%A3%E7%A0%81%E4%B8%8E%E8%AF%B4%E6%98%8E" class="hash-link" aria-label="代码与说明的直接链接" title="代码与说明的直接链接" translate="no">​</a></h2>
<ul>
<li class=""><a href="https://github.com/Linzwcs/EvoPolicyGym/tree/main/environments/jackdaw/balatro" target="_blank" rel="noopener noreferrer" class="">EvoPolicyGym Balatro Benchmark</a></li>
<li class=""><a href="https://github.com/Linzwcs/EvoPolicyGym" target="_blank" rel="noopener noreferrer" class="">EvoPolicyGym</a></li>
<li class=""><a href="https://huggingface.co/datasets/linzw/EvoPolicyGym-Exp-data/tree/main/v0.3.0/balatro" target="_blank" rel="noopener noreferrer" class="">Balatro 实验数据</a></li>
</ul>
<p>本 Benchmark 与 LocalThunk、Playstack 及 Balatro 官方项目无关联，也不包含官方
卡面、美术、音乐、字体或其他游戏资源。</p>]]></content>
        <author>
            <name>EvoPolicyGym contributors</name>
            <uri>https://github.com/Linzwcs/EvoPolicyGym</uri>
        </author>
        <category label="Benchmark" term="Benchmark"/>
        <category label="Balatro" term="Balatro"/>
        <category label="Experiment" term="Experiment"/>
        <category label="Policy Evolution" term="Policy Evolution"/>
    </entry>
    <entry>
        <title type="html"><![CDATA[EvoPolicyGym：让 Coding Agent 从环境反馈中构建策略系统]]></title>
        <id>https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/designing-evopolicygym/</id>
        <link href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/designing-evopolicygym/"/>
        <updated>2026-07-27T00:00:00.000Z</updated>
        <summary type="html"><![CDATA[为什么 EvoPolicyGym 使用交互式 Environment 与可执行 Program 研究和训练 Coding Agent。]]></summary>
        <content type="html"><![CDATA[<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="coding-agent-作为策略系统专家">Coding Agent 作为策略系统专家<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/designing-evopolicygym/#coding-agent-%E4%BD%9C%E4%B8%BA%E7%AD%96%E7%95%A5%E7%B3%BB%E7%BB%9F%E4%B8%93%E5%AE%B6" class="hash-link" aria-label="Coding Agent 作为策略系统专家的直接链接" title="Coding Agent 作为策略系统专家的直接链接" translate="no">​</a></h2>
<p>EvoPolicyGym 直接受到了 Jiayi Weng 的
<a href="https://trinkle23897.github.io/learning-beyond-gradients/#zh" target="_blank" rel="noopener noreferrer" class="">Learning Beyond Gradients</a>
启发。文章提出 <em>Heuristic Learning</em>：Coding Agent 吸收 reward、failure、test、
log 与 replay，再通过直接编辑软件系统来改进 programmatic policy。它让我们看到，
Agentic coding 本身可以成为一种学习过程，并且持续演化的状态能够明确保存在代码中。</p>
<p>EvoPolicyGym 从这个洞见出发，进一步思考如何让这一过程在不同交互式 Environment
中形成有界、可复现、可比较的评估方式。</p>
<p>在 EvoPolicyGym 的 Run 中，Coding Agent 扮演策略系统专家。它研究 Environment
及其交互接口，检查初始 Program，对有效行为形成判断，再把这些判断写成一个完整、
可执行的 Policy 系统。</p>
<p>这个系统可以组合领域知识、状态估计、规则、规划、搜索、记忆、算法或调优后的
参数。随着证据积累，Coding Agent 可以自由调整内部设计。它的责任，是将自己从
Environment 中学到的内容落实为能够独立决策的源代码。</p>
<p>编写与执行是两个清晰阶段。Evaluation 运行时，提交的 Policy 独立接收
observations 并产生 Actions。最终得到的是一个可以冻结、检查、重跑和比较的独立
策略系统。</p>
<p>Environment Feedback 构成了策略工程闭环：</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">研究 Environment</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    ↓</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">编写可执行 Policy 系统</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    ↓</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">提交并进行 Evaluation</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    ↓</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">分析 score、trace 与 artifacts</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">    ↓</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">诊断、重新设计并再次提交</span><br></div></code></pre></div></div>
<p>这就是 EvoPolicyGym 中 Autonomous Policy Evolution 的出发点：Coding Agent
贡献专家知识与软件工程能力，Environment 提供经验性证据，持续演化的 Program
记录最终形成的策略。核心问题是，Agent 能否把有限的 Environment Feedback
有效转化为更好的可执行决策系统。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="将专家与-policy-分开">将专家与 Policy 分开<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/designing-evopolicygym/#%E5%B0%86%E4%B8%93%E5%AE%B6%E4%B8%8E-policy-%E5%88%86%E5%BC%80" class="hash-link" aria-label="将专家与 Policy 分开的直接链接" title="将专家与 Policy 分开的直接链接" translate="no">​</a></h2>
<p>在 EvoPolicyGym 中，Coding Agent 与 Policy 承担不同角色。</p>
<p>Coding Agent 是外层策略工程师与优化器。它阅读任务说明和公开 Feedback，编辑
<code>workspace/program/</code>，并决定何时提交下一个候选。Policy 是内层决策系统。它
通过一个很小的 ABI 接收 observation，并在 Episode 运行时返回 Action。</p>
<p>Policy 可以在同一个 Episode 的多次 <code>act()</code> 调用之间保存状态。每个新 Episode
都会获得全新的进程和 Policy 实例，跨 Episode 的改进则由新的 Program 表达。</p>
<p>EvoPolicyGym 将学习放在 Episodes 之间的 Program 层。Episode-local state 支持
时序行为，Program revision 记录持续改进。每次变化都有可见的源码快照，也能与
对应的 Evaluation 证据建立清晰关系。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="让产物成为一等对象">让产物成为一等对象<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/designing-evopolicygym/#%E8%AE%A9%E4%BA%A7%E7%89%A9%E6%88%90%E4%B8%BA%E4%B8%80%E7%AD%89%E5%AF%B9%E8%B1%A1" class="hash-link" aria-label="让产物成为一等对象的直接链接" title="让产物成为一等对象的直接链接" translate="no">​</a></h2>
<p>Workspace 支持持续编写。每个被接受的 Submission 都会把当前源码树捕获为一个
不可变、内容寻址的 <code>Program</code>。Evaluation、Feedback 与 artifacts 都属于这个精确
快照，最终结果返回从已提交候选中选出的、由 Host 保留的 Program。</p>
<p>这样，一个 Run 就可以被理解为一系列明确的产物：</p>
<table><thead><tr><th>对象</th><th>职责</th></tr></thead><tbody><tr><td><code>Program</code></td><td>被评估的可执行 Policy 源码</td></tr><tr><td><code>Submission</code></td><td>一个不可变 Program、显式训练编号 selector 及其已提交 Feedback</td></tr><tr><td><code>Run</code></td><td>有界的提交序列与最终交接</td></tr><tr><td><code>Validation</code></td><td>Host 在候选之间进行选择</td></tr><tr><td><code>Assessment</code></td><td>在 held-out 数据上测量所选 Program</td></tr></tbody></table>
<p>Program 是持久结果，Agent transcript 与进程日志提供辅助诊断信息。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="让-benchmark-定义有用的-feedback">让 Benchmark 定义有用的 Feedback<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/designing-evopolicygym/#%E8%AE%A9-benchmark-%E5%AE%9A%E4%B9%89%E6%9C%89%E7%94%A8%E7%9A%84-feedback" class="hash-link" aria-label="让 Benchmark 定义有用的 Feedback的直接链接" title="让 Benchmark 定义有用的 Feedback的直接链接" translate="no">​</a></h2>
<p>不同 Environment 需要不同类型的证据。控制任务可能需要状态轨迹和终止原因；
卡牌游戏可能需要回合摘要、经济决策或紧凑 replay。</p>
<p>EvoPolicyGym 统一 Feedback 载体，每个 Benchmark 定义有用的领域内容。Feedback
始终包含一个标量 score，Benchmark 可以再加入有界的公开 values 与 artifacts。
Benchmark 同时拥有 Episode 规划、Environment 构造、Action 验证与评分语义。</p>
<p>Kernel 只拥有跨 Benchmark 必须一致的部分：预算、不可变 Submission、生命周期
顺序、发布、选择、记录与 Policy ABI。Environment packages 可以独立安装，并且
只依赖公开 authoring interface。</p>
<p>这种职责划分使项目能够像 Gym 一样形成环境生态，同时让 Kernel 保持稳定且
domain-independent。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="将证据访问视为实验条件">将证据访问视为实验条件<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/designing-evopolicygym/#%E5%B0%86%E8%AF%81%E6%8D%AE%E8%AE%BF%E9%97%AE%E8%A7%86%E4%B8%BA%E5%AE%9E%E9%AA%8C%E6%9D%A1%E4%BB%B6" class="hash-link" aria-label="将证据访问视为实验条件的直接链接" title="将证据访问视为实验条件的直接链接" translate="no">​</a></h2>
<p>Run 的 Submission 上限、总 Episode 预算、固定训练池大小与可选单次上限共同定义
实验条件。例如，16 次提交、48 个 Episode 单位与 96 个 Episode identity 的池，
表示 Agent 可以从更宽的集合中选择并观察总计 48 次；更大的池不会增加交互预算。</p>
<p>Host 会在 Agent 启动前构建这个编号池。每次 Submission 都指定一组非空、公开的
Run-local 编号。复用编号会保持其隐藏 Episode specification 与 Policy seed 不变，
因此两个不可变 Program 可以在配对证据上比较；但每次使用仍创建全新的
Environment 与 Policy runtime，并再次扣除预算。真实 seeds、scenarios 与池构建
过程仍由 Host 持有。</p>
<p>Evaluation 一旦开始，预留的 Episode 配额就会被消耗。Policy failure 与无效
Action 会作为观察到的行为被报告，从而保持提交 Program 的精确语义。Feedback
会把每个经过净化的 Episode 结果映射回公开编号，而不同 selector 之间的比较仍是
未配对证据。</p>
<p>Agent 利用公开的搜索 Feedback 决定下一次尝试什么。Agent 结束后，控制权回到
Host：私有 Validation 在交接的候选之间进行选择，held-out Assessment 测量最终
选中的 Program。优化 Feedback 在 <code>finish</code> 时关闭，选择和最终测量保留在 Host 侧。</p>
<p>将搜索、选择与最终测量分开，可以让报告结果更容易解释。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="保持-kernel-聚焦">保持 Kernel 聚焦<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/designing-evopolicygym/#%E4%BF%9D%E6%8C%81-kernel-%E8%81%9A%E7%84%A6" class="hash-link" aria-label="保持 Kernel 聚焦的直接链接" title="保持 Kernel 聚焦的直接链接" translate="no">​</a></h2>
<p>EvoPolicyGym 是一套职责聚焦的基础设施。</p>
<ul>
<li class="">Agent integration 只把 Host 拥有的任务翻译为 provider invocation。</li>
<li class="">Benchmark distribution 拥有领域语义、依赖、baseline、Feedback 与测试。</li>
<li class="">Kernel 拥有共享的 Evaluation 与 Program evolution 生命周期。</li>
<li class="">Policy 边界传输有界的公开 values。</li>
</ul>
<p>目前 Codex 是第一个受支持的 Coding Agent integration，本地进程是当前 active
backend。核心 contracts 保持 provider-independent 与 backend-independent，
让未来集成继续沿用 Program、Submission、Evaluation 与 Run 的语义。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="evopolicygym-支持什么">EvoPolicyGym 支持什么<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/designing-evopolicygym/#evopolicygym-%E6%94%AF%E6%8C%81%E4%BB%80%E4%B9%88" class="hash-link" aria-label="EvoPolicyGym 支持什么的直接链接" title="EvoPolicyGym 支持什么的直接链接" translate="no">​</a></h2>
<p>EvoPolicyGym 将可扩展的交互式 Environment、Coding Agent、版本化 Program 与
可验证的 Benchmark 证据连接起来。Agent 是研究与训练对象；Program 是它留下的
可执行证据。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="研究能够演化策略系统的-agent">研究能够演化策略系统的 Agent<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/designing-evopolicygym/#%E7%A0%94%E7%A9%B6%E8%83%BD%E5%A4%9F%E6%BC%94%E5%8C%96%E7%AD%96%E7%95%A5%E7%B3%BB%E7%BB%9F%E7%9A%84-agent" class="hash-link" aria-label="研究能够演化策略系统的 Agent的直接链接" title="研究能够演化策略系统的 Agent的直接链接" translate="no">​</a></h3>
<p>当 Environment、初始 Program、交互预算、Feedback 可见性与选择规则保持一致时，
重复 Runs 可以研究：</p>
<ul>
<li class="">**Agent capability：**相同条件下，哪个 Coding Agent 能编写出更好的 Policy
系统？</li>
<li class="">**Improvement efficiency：**Agent 使用多少 Environment 交互，才能产生稳定的
Program 改进？</li>
<li class="">**Feedback value：**哪些 trace、diagnostics、replay 或聚合信息最能促进有效修改？</li>
<li class="">**Evolution dynamics：**Program 的结构如何随 Submission 演化，哪些修改带来
持久收益？</li>
<li class="">**Selection validity：**Validation 选出的候选能否在 held-out Assessment 中
保持优势？</li>
<li class="">**Policy-system design：**不同 Agent 会将怎样的状态表示、规则、规划、记忆与
控制结构写入 Program？</li>
<li class="">**Scaling and generalization：**预算、profiles、seeds、任务复杂度与 Environment
families 变化时，这些结果如何变化？</li>
</ul>
<p>最终 score 测量 Agent 选择的产物，连续的不可变 Programs、Feedback、artifacts
与结果则解释 Agent 如何到达这个结果。</p>
<h3 class="anchor anchorTargetStickyNavbar_Vzrq" id="使用交互式-environment-训练-coding-agent">使用交互式 Environment 训练 Coding Agent<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/designing-evopolicygym/#%E4%BD%BF%E7%94%A8%E4%BA%A4%E4%BA%92%E5%BC%8F-environment-%E8%AE%AD%E7%BB%83-coding-agent" class="hash-link" aria-label="使用交互式 Environment 训练 Coding Agent的直接链接" title="使用交互式 Environment 训练 Coding Agent的直接链接" translate="no">​</a></h3>
<p>Environment 与 Benchmark 共同构成任务生成器、证据生成器与 verifier。Profiles、
scenarios 和 seeds 产生任务变化，Program Evaluation、公开 Feedback、diagnostics
与 held-out 结果提供训练信号。</p>
<p>同一套 Environment 生态可以支持：</p>
<ul>
<li class="">使用 Program Evaluation 和 held-out 表现作为可验证结果的 Coding Agent RL
与 RLVR；</li>
<li class="">从成功的长程 Agent trajectories 进行 SFT；</li>
<li class="">从可观察的 evolution records——任务上下文、公开 Feedback、代码修改、
Submissions 与结果——进行 Agent distillation；</li>
<li class="">根据最终产物和结果，对高质量 Agent trajectories 进行 rejection sampling；</li>
<li class="">跨任务 profiles 与难度进行 curriculum learning；</li>
<li class="">使用中间 failure、revision 与 Evaluation 进行 process supervision。</li>
</ul>
<p>一条 Agent evolution trajectory 覆盖完整任务：理解 Environment、编写 Program、
读取 Feedback、诊断行为、修改策略系统、提交候选并完成最终交接。这类长程记录可以
为 Coding Agent 与策略工程 Agent 提供训练材料。</p>
<div class="language-text codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-text codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><div class="token-line" style="color:#393A34"><span class="token plain">Environment + Benchmark</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        │</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        ▼</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">Agent 编写并持续修改 Program</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        │</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        ├── evolution trajectory ─────▶ Agent SFT / distillation</span><br></div><div class="token-line" style="color:#393A34"><span class="token plain">        └── evaluation outcomes ──────▶ Agent RL / RLVR</span><br></div></code></pre></div></div>
<p>Kernel 提供统一的任务、Evaluation、Run 与证据 contracts。Dataset exporter 和
训练系统可以将保留的 Agent trajectories 转换为 SFT、RL 与 distillation 数据，
再将训练完成的 Agent 交回 held-out Evaluation。这样，Environment catalog 既是
Agent Benchmark surface，也是可规模化的可验证长程经验来源。</p>
<h2 class="anchor anchorTargetStickyNavbar_Vzrq" id="继续阅读">继续阅读<a href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/blog/designing-evopolicygym/#%E7%BB%A7%E7%BB%AD%E9%98%85%E8%AF%BB" class="hash-link" aria-label="继续阅读的直接链接" title="继续阅读的直接链接" translate="no">​</a></h2>
<ul>
<li class=""><a class="" href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/docs/concepts/">核心概念 →</a></li>
<li class=""><a class="" href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/docs/evaluation/">Evaluation 与 Runs →</a></li>
<li class=""><a class="" href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/environments/">环境目录 →</a></li>
<li class=""><a class="" href="https://linzwcs.github.io/EvoPolicyGym/zh-CN/results/">Core16 结果 →</a></li>
<li class=""><a href="https://arxiv.org/abs/2607.02440" target="_blank" rel="noopener noreferrer" class="">论文 ↗</a></li>
</ul>]]></content>
        <author>
            <name>EvoPolicyGym contributors</name>
            <uri>https://github.com/Linzwcs/EvoPolicyGym</uri>
        </author>
        <category label="Design" term="Design"/>
        <category label="Motivation" term="Motivation"/>
        <category label="Architecture" term="Architecture"/>
    </entry>
</feed>