SuperAPI AI 工具集

verifying-turn-based-games

测试与质量

查看项目

更新于 10-15 10:16

技能介绍

用途

本技能为双人、严格交替回合制游戏提供一套可复用的引擎接口契约与质量度量方法。它规定“做什么”(契约与指标定义),不规定语言、运行时、文件布局、构建系统、工具命令、创意或标签工作流、面向玩家的文档格式,也不生成引擎代码——这些属于项目本地选择。

适用范围

适用:双人、严格交替回合;完全或不完全信息;有限回合上限;通过显式种子实现确定性随机(无副作用随机)。

不适用(不要套用):同时行动、反应/打断窗口;3 人及以上;实时/非回合制;单人解谜。若目标游戏不符合适用范围,应停止并告知用户本技能不适用,而不是强行套用契约。

第一部分:引擎接口契约

引擎必须暴露以下纯函数(签名以 TypeScript 风格表示,可按宿主语言翻译):

  • init(config?: Config, seed?: number): State
  • step(state: State, action: Action): { state: State, reward?: number, done: boolean, info: object }
  • getLegalActions(state: State): Action[]
  • getObservation(state: State, playerId: PlayerId): State
  • getResult(state: State): { done: boolean, winners: PlayerId[], reason: string, scores?: Record<PlayerId, number> }
  • scoreState(state: State, playerId: PlayerId): number
  • replayLog(state: State): string
  • cloneState?(state: State): State

契约说明:

  • getLegalActions 与 step 隐式使用 state.currentPlayer。契约假设严格交替回合,不要扩展到同时行动。
  • state.history: Event[] 必须存在,且必须在 step 内追加。replayLog 是对 state.history 的纯格式化器,不需要外部收集器。
  • state.rngSeed 必须存在;step 内所有随机性都由它确定性派生。不得使用 Math.random()、读取时钟或其他副作用随机。
  • getObservation 返回同一 State 类型,将隐藏字段置空或掩码,而不是返回不同的观察类型。这样机器人可与引擎保持类型兼容。
  • getResult 取代更简单的 getWinner,使调用方能区分按生命值获胜、按牌库耗尽获胜、按回合上限平局等。reason 字符串为必需。
  • scoreState 是度量层(第二部分)所必需的。省略 scoreState 的引擎无法被本技能做质量评估。
  • 仅当 State 不是完全不可变时才需要 cloneState。若宿主语言保证不可变性(或使用结构共享),可省略。

必需不变量:

  • 无全局可变状态。
  • step 不修改其输入状态。分支搜索通过 step(cloneState(s), a) 或依赖不可变性。
  • 重放确定性:给定固定种子与固定动作序列,init 后重复 step 在多次运行中产生逐字节相同的状态。
  • 单一非法动作策略:在引擎中选定一种并记录——抛出异常、返回 { state: s, done: false, info: { illegal: true } } 且不改变状态、或自动跳过。不要混用策略。
  • Action 与 State 必须可 JSON 序列化(重放、持久化、搜索缓存都依赖此点)。

实现前检查清单:在编写引擎之前,规则文档必须明确:

  • State 的精确数据模型(turn、currentPlayer、公开棋盘、私有状态、rngSeed、history)
  • 所有终止条件及其优先级顺序,每个都带 reason 字符串
  • 每种动作类型的动作模式与前置条件
  • 当 getLegalActions 返回空时的跳过行为
  • 隐藏信息策略(getObservation 中哪些字段被置空)
  • 保证游戏长度有限的数值上限

若上述任一项未明确,不要开始引擎实现——先回到规则设计。

第二部分:质量度量方法

当引擎满足第一部分后,从两层评估质量。

当问题本身就是质量时运行第二部分:新规则集或重做规则集、明确的平衡性或机器人强度评估,或对 scoreState、动作合法性、机器人逻辑的改动。UI、措辞、渲染以及不触及规则语义的纯序列化改动只需第一部分契约检查——不要为它们重跑阶梯与指标套件。

A 层:胜率阶梯

在契约之上实现三种机器人:

  • 随机——从 getLegalActions 均匀采样
  • 基线——对 scoreState 做贪心 1 步 argmax
  • 强——对 scoreState 做浅层搜索(1–2 层前瞻)

每场对局测量 N ≥ 200 局,交换座位以控制先手优势。

指标与目标:

  • 基线对随机胜率:基线机器人对随机机器人获胜的比例,交换座位后取平均,目标 ≥ 0.65
  • 强对基线胜率:强机器人对基线机器人获胜的比例,交换座位后取平均,目标 ≥ 0.60
  • 先手优势:同一对局中两个座位之间的胜率差,目标 ≤ 0.10
  • 动作使用分布:每个机器人每种动作的使用率,无核心动作低于 0.05

B 层:体验指标

每局每回合对 scoreState 做快照。推导 WP(胜率)为 WP = sigmoid((score0 − score1) / T)。按游戏校准温度 T,使随机对强在终局时强的 WP 平均约为 0.9。

指标与目标:

  • 张力分数:WP 时间序列的标准差,目标 0.15–0.35
  • 领先易手次数:WP 跨越 0.5 的次数,目标每局 ≥ 2
  • 翻盘率:曾处于 WP ≤ 0.25 的玩家最终获胜的比例,目标 0.05–0.25
  • 平坦率:连续 ≥ 5 回合 |ΔWP| ≤ 0.03 的对局比例,目标 ≤ 0.20
  • 末段波动:最后 25% 回合中 WP 的标准差,目标 ≥ 0.8 × 张力分数
  • 决策密度:每回合不同合法动作的平均数量,依游戏而定;报告分布

失败模式检查清单:当指标未达标时,查找:

  • 退化强玩法——强机器人获胜但只使用 1–2 种不同动作
  • 死机制——某特定动作从未被任何机器人使用(被支配或成本过高)
  • 座位顺序翻转——交换座位后胜负完全反转(先手平衡被破坏)
  • 低影响循环——长对局被重复的近零 ΔWP 回合主导

改进循环纪律:

  • 单次实验中只改规则或只改机器人,绝不同时改。两者同时变动则归因失效。
  • 在重跑之前定义通过/失败阈值,而不是等数字出来后再定。
  • 保留每次实验的变更日志:假设 / 改动文件 / 前后指标 / 决策(采纳或回退)。