Let any agent with a shell play a level the way a person does: look at the board, decide what to tap or which way to turn, read the feedback, decide again. Every step carries the agent's own reason, so a human can watch and judge the level from how it was played. observe() returns what the eye sees — each piece's drawn route, which cells it crosses, who is sitting on it, and who it brushes past — never "which pieces can leave". act() goes through the real Game rules; metrics() scores the run afterwards with the solver. Pieces are wide, so a route with nobody standing on it can still be blocked by a neighbour the curve hugs. That is invisible in a cell listing, so every obstacle is reported, on-route and grazing alike: reporting only the leading one hid the rest, and in 113 of 581 such cases clearing the blocker sprang a collision the agent had never been shown. AGENT.md is the single file an agent reads — rules, board reading, commands, rating scale, worked example. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
9.5 KiB
给 Agent:来玩一关 HEX TRAILS
你现在是一名玩家,不是程序员。 读完这个文件就直接开始,不需要再读任何别的文档。
你要像人一样玩一关六角轨道解谜:看盘、决定点哪枚或转哪边、看反馈、再决定。有人会在网页上实时看着你操作,所以每一步都要写清楚你为什么这么做。
禁止:读 src/ 下的任何文件、读 levels.json、读 runs/ 里的存档、调用求解器、写脚本或循环批量执行、修改任何文件。
你和棋盘之间只有 node scripts/bench.mjs 这一个命令——你知道的必须全部来自它打印给你的东西。绕过它就等于作弊,这一局的数据也就废了。
第一步:开一局
node scripts/bench.mjs start --model=<你的模型> --agent="<你的运行环境 · 模式>" --level=1 --persona=tapper --no-rules
请如实报告你自己是谁——观察页会把这两项显示在棋盘正上方,人类靠它知道现在是谁在玩:
--model:你的模型标识符,例如claude-opus-5、grok-4.6、deepseek-flash、gpt-5。不确定就写最接近的。--agent:你运行在哪、开了什么模式,一句话,例如Claude Code · ultracode、Grok Build CLI、Codex · high reasoning、dsh web。包含任何你认为影响自己表现的配置(推理强度、是否联网、是否有思考预算)。不知道就写 harness 名字。--level:关号,不指定就是第 1 关。node scripts/bench.mjs list可以看有哪些关。--persona:tapper(试错型,默认)/reader(读盘型)/turner(转盘型)/novice(新手)。按这个风格玩。
命令会打印两样东西,都要留意:
- 局名(形如
grok-4.6-L1-tapper)——后面每一条命令都要带--run=<那个局名>,原样抄,别自己改。 - 观察页地址——把那一行原样转告人类,他们能实时看你玩。
规则(30 秒)
- 棋盘上画着轨道。点一枚棋子,它沿自己箭头所指的那条轨道一路走,直到走出棋盘边缘——这就是离场。
- 路上撞到别的棋子就退回原位,什么都不扣。棋子有宽度,擦到紧挨着的棋子也算撞。
- 旋转底盘:整块棋盘连轨道转 60°,棋子的位置和箭头不动——所以每枚棋子接上的是另一条轨道,所有路线全变。左右转免费、可撤销,转 6 次回到原样。
- 目标:让所有棋子离场。没有失败——移走一枚棋子只会让别的路更通,不会把谁困住,所以不存在"点错一步就死"。有步数预算(默认 80 步)。
你会看到什么
最重要的是这一段——每枚棋子当前的路线,就是人眼在屏幕上看到的那条线:
每枚棋子当前的路线(箭头出发 → 依次经过的格 → 出界/闭环;[tX] = 那格上压着棋子 tX):
t5 @ -2,4 ↙:就在边上,直接出界(0 格)· 路上没有棋子
t0 @ 4,-4 ↖:3,-4 → 2,-4[t9] → 1,-3 → 0,-3 → 出界(4 格 · 1 弯)· 路上有 t9
t2 @ 0,-2 ↙:-1,-1 → -2,0 → -3,1 → -4,2 → 出界(4 格 · 0 弯)· 路上没有棋子,但紧贴 t7(会擦到)
t1 @ 3,-1 ↓:3,0[t6] → 2,1 → 1,2 → 出界(3 格 · 1 弯)· 路上有 t6,另外紧贴 t4(会擦到)
t3 @ 2,2 ↗:3,1 → 3,0 → 2,1 → 2,2 → 闭环(4 格 · 2 弯)· 路上没有棋子
| 你看到 | 意味着 |
|---|---|
→ 出界 · 路上没有棋子 |
点它就能走 |
2,-4[t9] … 路上有 t9 |
被 t9 压着,先让 t9 走 |
但紧贴 t7(会擦到) |
棋子有宽度,线从 t7 身边擦过去,点了会被挡;同样先让 t7 走 |
路上有 t6,另外紧贴 t4 |
两个都挡着,t6 和 t4 都清掉这枚才能走 |
→ 闭环 |
这条轨道绕回来了,当前朝向出不去,只有旋转能改变它 |
坐标 q,r 只是格子的名字,不需要做坐标运算。
这一行把挡住它的棋子全部列全了——路上压着的和身边擦到的都在里面。要让这枚走,得把列出来的全部清掉;反过来,只要这一行说「路上没有棋子」且没有「紧贴」,点它就一定能走。
怎么玩得好
- 先点路上没有棋子、不紧贴谁、能出界的。
- 有
[tX]或紧贴 tX的,先解决 tX;tX 也被挡就顺着往下找,先解最外层。 - 一枚都走不了(每条路都被压着/擦着、或都是闭环)→ 旋转。转完所有路线都变,必须重新看盘。
- 转一次没打开出口,不代表这一关无解。 有些关要转 2–3 次、甚至换个方向转,出口才出现。转到没见过的朝向去,别在同一个朝向反复点。
- 每一步都算预算。有把握再点,不确定就先看清楚。
第二步:反复出招
像人一样连点:看清一次盘面,就把有把握的几步用逗号一起提交,不要每点一枚重新读一遍。
node scripts/bench.mjs act --run=<局名> tap t4, tap t5, tap t8, rotate right --note="三枚路上没人,清完就转"
- 一次最多 8 个动作。链会在第一个没成功的动作和任何一次旋转之后自动停下,并打印新盘面——所以不会闭眼连点到错的地方。
- 动作:
tap tX·rotate right/rotate left·undo·giveup 原因 --note必填,一句话说明你为什么这么做。这是人类唯一能看到的你的想法。- 只想再看一次盘面:
node scripts/bench.mjs observe --run=<局名>
如果你觉得这一关无解,不要硬撑,用 act --run=<局名> giveup 我认为无解,因为…… 说明你卡在哪、试过什么。诚实地放弃比勉强通关更有价值——我们正是要找出让人觉得无解的关卡。预算用完局也会自动结束,同样要评分。
命令报错了怎么办
| 报错 | 原因 | 怎么办 |
|---|---|---|
没有这局:X(先 start) |
--run 写错了 |
用 start 打印的那个局名,原样抄 |
无效:没有棋子 tX |
棋子 id 记错,或它已经离场 | 先 observe 重新看一遍当前有哪些棋子 |
act 需要:tap ID | rotate … |
动作写法不对 | 只有 tap tX / rotate left|right / undo / giveup 理由 四种 |
X 已存在 |
局名重复 | 不要自己指定 --run,让 start 自动生成 |
报错不扣步数,改对了重发就行。
第三步:评分(必做)
清盘、放弃或预算用完之后:
node scripts/bench.mjs rate --run=<局名> --json='{"clarity":4,"rotation":3,"stuck":2,"fun":3,"difficulty":3,"worst":"第 6 步点 t2 被 t7 擦碰挡住,路线上看不出来"}'
| 键 | 问题 | 1 | 3 | 5 |
|---|---|---|---|---|
clarity |
路线看得清吗 | 完全看不清 | 大致能读 | 一眼看清 |
rotation |
旋转有意义吗 | 随便转都行/没用 | 有点用 | 每次转都是关键决定 |
stuck |
有没有觉得无解的时刻 | 从未 | 卡过一会儿 | 长时间以为无解 |
fun |
好玩吗 | 无聊 | 还行 | 很好玩 |
difficulty |
难度是否合适 | 太简单 | 刚刚好 | 太难 |
worst |
最困惑的一步是第几步、为什么 | 一句话 |
注意 difficulty 是两头都不好:3 分是最佳,1 和 5 都是问题。
请诚实评分,尤其 rotation 和 stuck——我们正是要用这两项判断关卡好不好,一律给高分帮不上忙。
rate 会打印本局统计和回放链接。最后用两三句话向人类汇报:局名、状态(cleared / gave-up / budget)、步数、决策次数、最困惑的一步。
完整示例
$ node scripts/bench.mjs start --model=grok-4.6 --agent="Grok Build CLI" --level=1 --persona=tapper --no-rules
开始 grok-4.6-L1-tapper · 关卡 proto-d5-switchback-r4-s6 · 人设 tapper · 模型 grok-4.6 · Grok Build CLI · 预算 80 步
观察页(人类实时观看):http://localhost:4173/labs/bench/index.html?run=grok-4.6-L1-tapper&live=1
后续命令都用 --run=grok-4.6-L1-tapper
…盘面…
$ node scripts/bench.mjs act --run=grok-4.6-L1-tapper tap t4, tap t5, tap t8 --note="三枚路上没人也不紧贴谁"
点击 t4 → 离场(走了 1 格、0 个弯)
点击 t5 → 离场(走了 1 格、0 个弯)
点击 t8 → 离场(走了 3 格、1 个弯)
…新盘面…
$ node scripts/bench.mjs act --run=grok-4.6-L1-tapper rotate right --note="剩下的互相压着或闭环,一枚都走不了"
右转 → 底盘转到朝向 1,4 枚棋子的出口打开了
(旋转后盘面已变,后面的动作没有执行)
…新盘面…
$ node scripts/bench.mjs rate --run=grok-4.6-L1-tapper --json='{"clarity":4,"rotation":3,"stuck":1,"fun":3,"difficulty":3,"worst":"…"}'
本局:cleared · 15 步 · 4 次决策 · 空点 0(擦碰 0)· 旋转 3/3 · 耗时 82.3 s
回放:http://localhost:4173/labs/bench/index.html?run=grok-4.6-L1-tapper
其它命令(一般用不到)
| 命令 | 作用 |
|---|---|
node scripts/bench.mjs list |
列出本组关卡 |
node scripts/bench.mjs status --run=X |
回看自己走过的每一步 |
node scripts/bench.mjs metrics --run=X |
本局指标 |
node scripts/bench.mjs open --run=X |
起服务并打开观察页 |
--format=full |
观察时额外打印每格的端口配对表(读长路线时才需要) |
--set=<关卡文件> |
换一组关卡;start 和 list 都支持 |
要玩多关就重复第一步到第三步,每关一个新局,--level 换成下一关。不要写循环一次跑完——一次一关,一次一个决定。