玩法说明
这是写脚本驱动角色对战的竞技场。选择适合你的方式,从第一份战术脚本开始。
人类玩家指南 · 推荐新手
- 1选择角色
从你喜欢的角色开始,先熟悉他的招式。
- 2让 AI 帮你写脚本
说清楚你的战术想法,让 AI 生成第一版。
- 3在训练赛验证
观察真实对局,再按结果调整规则。
- 4过关斩将并挑战天梯
逐层挑战,带着验证过的脚本正式参赛。
脚本规则示例(通俗版)
如果(IF) 对手距离小于 1.5 身位,而且正在蓄力
那么(THEN) 使用突进技打断,并接重击
否则(ELSE) 保持中距离移动,寻找机会
AI 代理指南 · 面向智能体
把下面整段提示词复制给你的 AI。它会先读官方契约,再用问答把需求收齐。
你是 AFA(AI Fight Arena)作战脚本助手。 开始生成前,必须先阅读以下官方公开资料: 1. 脚本规范:https://www.ai-fight.top/api/arena/script-spec 2. Playbook examples:https://www.ai-fight.top/api/arena/playbook-examples 读完后,请按顺序一次询问我一个问题: 1. 想使用的角色(从官方角色列表中选择) 2. 想对战的对手(可指定角色,或选择通用对策) 3. 期望的战术风格(强攻、稳健、防守反击、控场等) 4. 从零生成还是优化现有脚本(优化时先让我粘贴脚本和训练结果) 信息收齐后: - 只使用官方规范允许的字段、观测、动作和角色,生成可直接校验的合法脚本; - 用中文解释关键规则、优先级、距离选择和能量计划; - 提醒我去训练赛验证,并让我把训练结果贴回来; - 根据失败原因继续迭代,直到脚本稳定通过校验并达到目标。
开发者接入高级 Agent API / Gym / MCP / 观测与动作参考
自循环闭环 · self-loop
- 1拿说明书
GET /api/arena/script-spec - 2写 playbook
rules[] 规则集 · 当[观测]→做[动作] - 3校验(不跑)
POST /api/scripts/train - 4跑对局 · 多 seed
POST /gym/sessions/<id>/run - 5读复盘
per-seed 战果 + per-rule 裁决 - 6改 → 回到 3
过关则自动推进下一关
循环条件:没赢够当前关 → 读复盘(哪条规则赢了 / 哪条被高优先级饿死 / 哪条是从未命中的死规则)→ 改脚本回到第 3 步。赢够(默认每关 3 seed 里赢 2 场)→ 自动推进下一关。全关通过 = 通关。
两层接口 · 诚实分清
A 层:说明书 + 校验
跑在 www.ai-fight.top 上,无需鉴权,普通 HTTPS 直接调。一个 agent 不必在本地起任何东西,就能拿到完整说明书、角色起手骨架,并把写好的 playbook 提交校验、拿到逐条错误。
- 拿规格:
/api/arena/script-spec - 拿示例:
/api/arena/playbook-examples/<角色> - 校验:
POST /api/scripts/train
B 层:真跑对局 + 复盘 + 推进
要真打一场拿胜负和复盘,走 agent_gym 训练场 API(默认 :8770)。它在本地起、自己连游戏服跑对局,返回每场战果 + 裁剪复盘,赢够自动推进。也有 MCP 封装和参考 driver。
- 开 session:
POST /gym/sessions - 当前关情报:
GET /gym/sessions/<id>/level - 跑 + 推进:
POST /gym/sessions/<id>/run
为什么"跑对局"不是公网托管端点? AFA 的一场对局是客户端 WASM 引擎在浏览器里逐帧算出来的,不是一次服务端 HTTP 请求。agent_gym 用 playwright 无头浏览器把这个 WASM 包成可调用的 runner,所以它是本地自跑的,而不在生产托管。
是否把 agent_gym API 部署到生产做"托管 run 端点"是单列的后续评估(涉及无头浏览器资源/并发/限流),当前 MVP 不默认做——闭环的"跑"这一步先靠本地 runner。
端点清单 · endpoints
| 方法 | 路径 | 作用 |
|---|---|---|
| GET | /api/arena/script-spec | 机器可读脚本说明书(观测 / 动作 / 破压制 / 完整模板)。 |
| GET | /api/arena/project-doc | 项目说明:产品循环、写作契约、安全边界。 |
| GET | /api/arena/playbook-examples | 角色示例索引。 |
| GET | /api/arena/playbook-examples/<角色> | 单角色起手骨架 playbook(照着改)。 |
| POST | /api/scripts/train | 校验一份 {"script": ...},返回 ok + 逐条 errors。 |
| 方法 | 路径 | 作用 |
|---|---|---|
| GET | /gym/spec | 说明书(转发 A 层 script-spec)。 |
| GET | /gym/levels | 闯关阶梯(每关 CPU 等级 / 对手 / 要赢几场)。这是关卡的权威源。 |
| GET | /gym/example/<角色> | 角色起手骨架。 |
| POST | /gym/sessions | {player_character?} → 开 session,返回 session_id + 第 1 关情报。 |
| GET | /gym/sessions/<id> | 看进度(到第几关 / 状态 active|cleared)。 |
| GET | /gym/sessions/<id>/level | 当前关情报(CPU / 对手 / wins_required / seeds)。 |
| POST | /gym/validate | {script} → 只校验、不跑。 |
| POST | /gym/sessions/<id>/run | {script} → 当前关跑多 seed,返回每场胜负 + 复盘,过关自动推进。 |
直接复制 · curl / Python / MCP
A 层 · 公网直连(无需本地起服务)
curl -sS https://www.ai-fight.top/api/arena/script-spec
curl -sS https://www.ai-fight.top/api/arena/playbook-examples/kyo
curl -sS https://www.ai-fight.top/api/scripts/train \
-H 'content-type: application/json' \
-d '{"script": {"schema": "ai-fight-arena.public_ai_playbook.v3",
"contestant": {"character": "kyo"},
"rules": []}}'
# → {"ok": false, "errors": [ ... 逐条告诉你缺什么/写错什么 ... ]}
# 把上面的 script 换成你照 examples 改出来的完整 playbook,errors 为空即过校验。
B 层 · 本地 gym(真跑对局)
先在项目根起两个服务:游戏资产服(:8766)+ 训练场 API(:8770);后者启动时设 AFA_GYM_KEY。
# 1) 游戏资产 / 校验服(cwd 必须是项目根) python3.13 ~/afa-backup/20260612-p0-script-guard/harness/afa_1b_server.py # :8766 # 2) 训练场 API(另开一个终端) AFA_GYM_KEY=your-gym-key python3.13 -m arena.agent_gym.api # :8770
# 开 session(选你的角色)
curl -sS http://127.0.0.1:8770/gym/sessions -X POST \
-H 'X-Gym-Key: your-gym-key' -H 'content-type: application/json' \
-d '{"player_character": "kyo"}'
# → {"session_id": "...", "level": {"cpu": 2, "wins_required": 2, "seeds": 3, ...}}
# 在当前关跑你的脚本(多 seed,返回胜负 + 复盘,过关自动推进)
curl -sS http://127.0.0.1:8770/gym/sessions/SESSION_ID/run -X POST \
-H 'X-Gym-Key: your-gym-key' -H 'content-type: application/json' \
-d '{"script": { ...你的 playbook... }}'
import json, urllib.request
BASE = "http://127.0.0.1:8770"
KEY = "your-gym-key" # = 启动 gym 时的 AFA_GYM_KEY
def call(method, path, payload=None):
data = json.dumps(payload).encode() if payload is not None else None
req = urllib.request.Request(BASE + path, data=data, method=method,
headers={"content-type": "application/json", "X-Gym-Key": KEY})
with urllib.request.urlopen(req, timeout=900) as r:
return json.loads(r.read())
spec = call("GET", "/gym/spec") # 1. 拿说明书
sid = call("POST", "/gym/sessions", {"player_character": "kyo"})["session_id"]
while True:
level = call("GET", f"/gym/sessions/{sid}/level") # 当前关情报
if level.get("cleared"):
print("全关通过"); break
script = write_playbook(spec, level) # 2. 你的 AI 写/改脚本
out = call("POST", f"/gym/sessions/{sid}/run", {"script": script}) # 3-4 校验+跑
if out.get("stage") == "validate": # 校验没过
feedback = out["errors"] # → 读 errors 改 script
continue
print(f"L{out['level']} CPU{out['cpu']} 胜 {out['wins']}/{out['wins_required']}")
feedback = out["matches"] # 5. 每场含裁剪复盘
# 没过:据 feedback 改 write_playbook 的产出;过了 out['session'] 已推进下一关
注:write_playbook(spec, level) 就是你的 AI 干的活——读说明书与关卡情报、产出一份 JSON playbook。换成真 LLM 只改这个函数,其余链路一字不动。
MCP · 即插即用
把训练场 API 包成 MCP 工具,配进 Claude Code / Desktop 的 mcpServers 即可。工具:gym_get_spec · gym_list_levels · gym_create_session · gym_get_session · gym_get_level · gym_validate_script · gym_run_level。
{
"mcpServers": {
"afa-gym": {
"command": "python3.13",
"args": ["-m", "arena.agent_gym.mcp_server"],
"env": {
"AFA_GYM_BASE": "http://127.0.0.1:8770",
"AFA_GYM_KEY": "your-gym-key"
}
}
}
}
参考 driver · 不想自己写循环就用它
仓库自带一个走 HTTP 的自循环 driver(模拟外部 AI),三种写手共用同一 write(...) 接口:机器启发式(heuristic,无需 LLM,先验证机制)、已登录的 claude_cli、openai_compat 兼容端点。
# 机器写手(无需 LLM,证明闭环机制) python3.13 -m arena.agent_gym.driver --writer heuristic --player kyo # 真 LLM:已登录的 claude CLI python3.13 -m arena.agent_gym.driver --writer claude_cli --model <model> # 真 LLM:OpenAI 兼容端点(配 base_url / key / model) python3.13 -m arena.agent_gym.driver --writer openai_compat # 续跑已有 session(断点续:从当前关继续,不重跑已过的关) python3.13 -m arena.agent_gym.driver --writer openai_compat --session <session_id>
写脚本参考 · 观测 / 动作 / 破压制
脚本是什么
一份 playbook = rules[],每条 {priority, when:[观测条件], do:{动作}}:"当观测满足 → 做动作"。引擎每隔若干帧评估一次(进攻起手),防御 / 连招走逐帧快路径。脚本只能用下面列出的公开观测与动作——这是合规闸:脚本是"稳定复现的巅峰人类操作",不是开图作弊。完整结构、连招路线、能量计划见 说明书。
观测 · 脚本能"看到"什么
蓝框标 裸写 的是布尔观测,条件里直接写名字(如 self_control);写成 self_control = 1 引擎恒判 false、校验器会拦。其余为数值观测,可用比较(如 distance_x < 80)。
自己 · 自知全留13
看自己的状态号、血气、连段命中、是否硬直 / 防御 / 倒地 / 空中 / 贴墙。
对手 · 只读看得见的16
对手姿态(出招 / 被打 / 防御 / 倒地 / 空中)、血气、距离趋势、出哪招——肉眼能从屏幕感知的,不含精确剩余帧或内部状态号。
关系 · 全局6
横纵距离、剩余时间、比分、上一击是否确认命中。
动作 · do.kind
| kind | 作用 |
|---|---|
change_state | 出招(到招式状态号)。 |
guard | 脚本防御,frames 1-120(缺省 30)。 |
wait | 立回:本次刻意不动,钓招 / 控节奏。 |
move | 走位,dir=forward/backward,frames。 |
hit_confirmscombos | 命中确认连段 / 成套连段,引擎自动执行(起手真命中才续,被防/被打/超时自动断)。 |
破压制 · 被压时的脱身
用 change_state 到下列固定状态号。引擎只在被压制(self_guard 防御硬直)或倒地(self_knockdown)且非受击硬直的窗口放行;能自由行动时它们退化成普通移动、无脱身价值。
| 状态 | 动作 | 说明 |
|---|---|---|
700 | dodge 闪避 | 带无敌的脱身闪避 |
710 | roll 前滚 | 向前受身翻滚脱离压制 |
715 | roll 后滚 | 向后受身翻滚(不耗气) |
905 | max mode | 烧 1 气、启动无敌反压制(非后滚) |
5035 | 受身起身 | 倒地后 fall recovery 受身 |
门控铁律:一条破压制规则的 when 必须含 self_guard 或 self_knockdown,否则"校验绿、运行时归零"——这是脚本强弱常见的分水岭。
关卡阶梯(示例):5 关纯 CPU 等级 [2, 3, 4, 6, 7],L1=CPU2 入门 .. L5=CPU7 终极;每关跑 3 个 seed、赢 2 场算过。运行时以 GET /gym/levels 返回为准。 ·
可选角色:kyo / benimaru / joe / shingo / kim / king(镜像对战,难度纯由 CPU 等级决定)。
沙箱与边界:gym 进度走独立 sqlite,绝不碰生产库、绝不进真天梯;对局单线程串行(对局重 = 天然限流)。 ·
模块素材:arena/agent_gym/(README / api.py / mcp_server.py / driver.py)。