Files
SoundGame/docs/design/13-playtest-criteria.md
T
xsl c8843233b0 research(new8/batch2): abyss + detective 迭代闭环收口——双双 R1-R2 连续达标裁定可交付
abyss《深海回音》:
- R1 补 synthesis(5/5 愿意玩 P0=0)+ 补录 R1 缺失裁决材料
- R2 十修全部现场坐实:F1 ping迟到/尾句保护首播制/链末看门狗不拆/回波静默一拍/dv4_dual扣账口播/crit水面变体/看门狗13s/震循环1.1s/震去重/状态链人数句
- 补录语音18段(flock串行,QC无离群);playtest 242→278
- 终裁:4/4 人设满分档,连续 2 轮达标 → 可交付 ✅

detective《雨夜专案》:
- R1 取证轮:补跑 live 两会话(认真新手33分钟全弧线/乱按200s三级保底抢救),5/5 愿意玩 P0=0
- R2 十一修全部坐实:intro完整落声/tut不被掐/按轴取句/人名指认/结案确认闸/指路句/选句记忆位/hint轻震/st_wrong当场记账/tut_skip补动词/L2疑点齐分支
- 补录+改词33条(29新增+4重录);playtest 265→279
- 终裁:6/6 愿意玩,连续 2 轮达标 → 可交付 ✅

公共:00-program 批次2进度账收账、13号文档 R2 断言关键词、gen_voice_dual 两游戏段、voice_text.json
验证:abyss 278/278 + detective 279/279 + guide 122/122 + check_all_assets 全项目全绿
2026-09-14 00:05:42 +08:00

840 lines
73 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 13 · 六游戏试玩通过标准(playtest criteria,无头测试 agent 断言检查单)
> **给测试 agent 的使用说明**:每游戏分三节——**关键路径**(从启动到通关/结算必须按序达成的事件序列,附最大手势/步数预算)、**边界断言**(必须显式验证的容错/保护行为)、**失败即不通过**。测试可用测试钩子(如直接读取 game 实例字段、快进计时器)模拟时间,但手势只能通过引擎回调注入(模拟真实判定路径)。语音缺失不应导致卡死(看门狗是各游戏的既定实现,属被测项)。
---
## 1. storyline《声命线》
**关键路径**(单结局线,≤40 次手势):
1. 启动遮罩点按 → 音频解锁 → `n00` 旁白开始(voice 层有播放记录)。
2. 沿任一抉择路径行进:每个抉择点断言 `pendingChoice/choiceArmed` 生效,左/右滑各至少使用一次。
3. 到达任一结局节点(4 结局之一)→ 结局语音链 → 结算态单击重开回 `n00`。
**边界断言**:
- 语音播放中双击 = 重听当前节点(同一 voice id 重播)。
- 下滑呼出菜单 → 返回剧情后节点不丢(mode 恢复,不重头)。
- 中途选择产生剧情标记:`n09` 右滑后 `knowTrap === true`、`n11` 左滑后 `companion === true`、`n18` 左滑后 `betrayed === true`(标记设置即断言;knowTrap 无下游消费是已知项,roadmap §2.2,不作为失败项)。
- 语音链看门狗:屏蔽某一 voice 资产时流程仍可推进到结局。
## 2. escape《暗室》
**关键路径**(引导 8 步 + 解谜链,≤80 次手势):
1. 启动 → GUIDE 进入(g0_intro 播放)→ 依次:单击(G0)→ 任意滑动(G1)→ 滑动 ×2(G2)→ 左滑(G3)→ 下滑(G4)→ 单击拾钥匙(G5,断言 `hasKey === true`)→ 双击(G6)→ 进入 PLAY(断言 `phase === 'PLAY'`,localStorage `soundgame.escape.guideDone === '1'`)。
2. PLAY 路径:(0,2)出发 → 右滑×2 到铁柜房 (2,1) → 双击开柜(`cabinetOpen === true && hasFuse === true`)→ 左滑×2+上滑到电箱房 (0,0) → 双修复电箱(`powerOn === true`)→ 右滑×2+下滑×2 到大门 (2,2) → 双击逃脱。
3. ENDING:断言 time_band 语音播出 + 单击重开回 PLAY。
**边界断言**:
- 引导期错手势:G3 右滑 → 播 guide_wrong_left;连错 3 次 → guide_blunt_left + warning 震动(监听 vibrate 调用)。
- 撞墙:PLAY 中 (0,0) 左滑 → wall 音效 + error 震动 + 位置不变。
- 卡关提示:计时器快进 60s/120s/180s → 依次播 stuck_*_1 / stuck_*_2 / stuck_*_3 + nav_*;任意进展事件后重置(`_stuckShown` 清空)。
- 单击检查 = 环境音先播、描述 800ms 后播(断言播放顺序)。
- 双击无目标兜底:播背包 + L2 明示,不崩。
## 3. simon《音序回响》
**关键路径**(教学 + 5 轮 + 复活耗尽,≤120 次手势):
1. 启动 → 0.5s 后教学 T0(t0_welcome 播放)→ T1-T6 每步:听到 tone → 做出对应手势(断言 `teachIdx` 递进)→ T7 → 进入第 1 轮。
2. 第 1-3 轮:playback 阶段手势被忽略(注入手势断言 sequence 不受影响)→ input 阶段按 `game.sequence` 原样复现 → `round` 递增。
3. 触发复活:第 4 轮故意答错 → 断言 `chances` 1→0、序列**不变**重播(`sequence` 引用值相等)→ 复现成功 → 第 4 轮完成时 chances 回 1(每 4 轮 +1)。
4. 主动重听:input 阶段且期望输入非 doubletap 时双击 → 断言 chances 减少、inputIdx 清零、序列重播。
5. 耗尽后再答错 → gameover → 断言 score_band 语音与 `round-1` 匹配 → 单击重开跳过教学直达第 1 轮。
**边界断言**:
- 无 BGM:全程无 bgm 层播放调用。
- 双击冲突(裁定①):期望输入恰为 doubletap 时双击 = 答题(inputIdx 前进),不触发重听。
- chances=0 时双击非期望手势:不判错(round 不变、inputIdx 不变)、播 chances_out。
- 序列约束:前 5 轮无三连同手势;全程无四连。
- 速度:第 1 轮 interval 700ms、第 12 轮起 420ms 下限。
## 4. rhythm《节拍行者》
**关键路径**(教学 + 曲目一通关 + 解锁,≤200 次手势):
1. 启动 → welcome → 教学 T1-T3:按 cues 的 expected 时刻(测试用 AudioContext 时钟对齐)做对应手势 → `tutorialDone === true` → 进曲目一 main。
2. 曲目一:按 `_cues` 全部应答(Perfect 精度注入)→ 结算 phase 'end' → 断言评级 S(全 Perfect)→ `grades.song1 === 's'`、`unlocked === 2`、unlock_song2 播报。
3. 结算单击 = 同曲再来一遍;右滑 = 下一首(已解锁 song2 进入 main)。
**边界断言**:
- tap 补偿:tap 音符以"回调时刻 -0.30s"判定(注入 tap 手势的实际回调延迟下仍判 Perfect)。
- Miss=无乐器音:窗口内做错手势 → 无 inst_* 播放 + error 震动 + combo 清零。
- 下滑折中:main 中无临近 down 音符时下滑 → 菜单(phase 'menu'、BGM 断点);有临近 down 应答音符时下滑 = 演奏判定,不开菜单。
- 菜单暂停恢复:关菜单后 cue.expected 平移、BGM 断点续播(断言 `_bgmT0` 平移量 = 暂停时长)。
- 教学失败 2 次 → retry_skip 跳过该步不卡死。
- **结算末位**:song3 结算页右滑 → 不播 song_locked(round3-4 裁定①的回归断言;修正落地前此断言预期失败,标记 known-issue)。
## 5. space《盲航》
**关键路径**(演练 + 保护期 + 坠毁,≤150 次手势):
1. 启动 → 演练 D1-D4:按 `DRILLS[d].dir` 同向滑 → `drillIdx` 递进 → D5 后进 playing(`drillDone === '1'`)。
2. 保护期(runStart 起 60s):等一颗陨石 → **不滑动任其撞** → 断言 `hits === 0`(训练护盾吸收)+ protect_<dir> 播报。
3. 第 20s:feature 阶段单击 → boost 生效(`boostUntil > now`);第 45s:双击 → 护盾(`shieldUpUntil > now`)。
4. 60s 后:保护解除播报;之后正常闪避 3 颗(同向滑,断言 dodges=3)→ 再任撞 3 次 → 坠毁 gameover。
5. 结算:time_/dodge_ 分档句与实际值匹配 → 单击重开。
**边界断言**:
- 演练做错:D1 右滑(应为左)→ drill_retry_left 重教 + 同一步重试;失败 2 次 → drill_moveon 带过。
- 保护期撞击方位归因:撞左来陨石播 protect_left(方向句与 ob.dir 一致)。
- 同向判定:撞击前 1.5s 内同向滑 = dodge(dodges+1);反向滑 ≠ dodge。
- 第 2 次被撞后追加 hit_last;hits===3 才 gameover。
- 下滑折中:下方有悬置陨石时下滑 = 闪避;无下方陨石时下滑 = 菜单(phase 'menu')。
- 护盾充能:doubletap 后 30s 内 shieldReadyAt 锁定,到时播 shield_ready。
- 里程碑:dodges=10 播 ms_10(测试可快进或直接设置 dodges 后触发一次 dodge)。
## 6. rpg《剑与声》(含 11 号文档重构项;重构未落地处标 known-issue)
**关键路径**(第一章通关,≤300 次手势):
1. 启动 → 无存档时序章 intro_1-3 → village;断言场景进入 = amb/desc 播报 + 选项可左右滑切换。
2. village:商店买铁剑(金币 50→断言不够 → 先调查/战斗攒钱或直接断言 shop_poor 播报路径);上滑状态播报链完整(st_lv→st_hp→st_gold→st_weapon→st_armor)。
3. path:investigate 一次性 +15 金(再次调查播 evt_nothing)。
4. stream:**教学战不败**——全程乱按/不动,断言玩家 HP 不低于 1(锁底);按 11 号文档重构后:四步教学(menu→attack→parry→defend)依次断言 teachStage 流转(重构落地前按现版两步 parry→attack 断言)。
5. hunter:talk_hunter → hunter_quest flag + potions+1 + shop_discount。
6. deepwood:山贼连战(两只依次上场,连战间不回血)→ enc_bandits_done。
7. gate:assault → elite 战 → boss1:黑风寨主(半血二阶段 ATK 12 + npc_boss1_2)→ 胜利 → evt_ch1_end → `chapters['2'] === 'open'`。
8. 存档断言:任一战斗结算后 PUT/localStorage 有最新 data(summary 含场景名与 Lv);杀进程重进 → sys_continue_ask → 单击继续落点正确。
**边界断言**:
- 格挡:前摇窗口内双击 → 伤害 ×0.3(`dmg` 断言或 HP 差值断言);窗口外双击 → error 震动不生效。
- 防御指令:当回合伤害 ×0.5。
- 逃跑:Lv<3 普通战 100% 成功(11 号文档;重构前现版为 flee 布尔,按现版断言 flee:true 必成);Boss 战下滑 → btl_noflee。
- 新手保护(11 号文档,known-issue 至重构落地):前 3 场前摇 1.5s、伤害 ×0.6;enc_boss1 恒标准档。
- 战败:HP≤0 → btl_lose → village 重生,等级/金币/flags 保留、非 Boss 遭遇重置。
- 菜单豁免:探索态下滑=菜单(左右滑+单击确认),战斗态下滑=逃跑。
- 看门狗:屏蔽任意 voice 资产,战斗与场景流转不卡死。
## 7. 全局通用断言(每游戏都跑)
1. 启动遮罩点按前无音频播放(引擎解锁语义)。
2. 全程无未捕获异常;资产缺失仅 console.error 不崩。
3. 设置边界:settings.voice 切换后下一句起用对应目录(voice 缓存键含性别);settings.bgm=0 时无 bgm 层加载;speed=1.7 时下一句 playbackRate 生效。
4. 双击=重听在其声明可用的阶段生效(escape 检查/simon 规则/rpg 场景 desc 等)。
5. 菜单约定(裁决②):适用游戏的模态菜单 = 单击循环 / 双击确认 / 上滑帮助 / 下滑关闭(RPG 豁免)。
---
## 8. round3 变更记录(simon 手势映射例外)
> round3 G5(research/04-playtests/round2/synthesis.md §2)改变了 simon 的**玩法**
> 手势映射(不是向导层断言):input 阶段双击永远=作答(第 6 音色),主动重听改绑
> 上滑。按本研究「playtest 断言零改动」红线的例外流程,本节只做追加记录 §3 受影响
> 断言的替换口径;§3 既有文字不回改,其余 5 个游戏断言零改动。
- §3 关键路径 4「主动重听:input 阶段且期望输入非 doubletap 时双击 → 断言 chances
减少、inputIdx 清零、序列重播」→ 替换为:**input 阶段上滑(且期望输入非 up)=
主动重听**,断言目标不变(chances 减少、inputIdx 清零、序列重播)。
- §3 边界「双击冲突(裁定①):期望输入恰为 doubletap 时双击 = 答题(inputIdx 前进),
不触发重听」→ 保留并强化为:**input 阶段双击永远=作答**——期望非 doubletap 时
照常判错(耗机会/死亡),不再触发重听。
- §3 边界「chances=0 时双击非期望手势:不判错(round 不变、inputIdx 不变)、播
chances_out」→ 替换为:**chances=0 时上滑非期望手势**,断言目标不变。
- 新增边界断言:期望输入恰为 up 时上滑=作答(六手势全是答题输入,00 号文档 §5.3
豁免同款);非输入阶段(gameover/菜单)上滑行为不变。
- 随上述改口的测试脚手架微调(非断言变更):两处「错手势注入」的取值从
`GESTURES.find(g => g !== exp && g !== 'doubletap')` 增加排除 `up`(round3 后
up=重听键,注入 up 会触发重听而非判错,与旧版注入 doubletap 需避开是同一道理)。
- 依据:docs/design/14-guide-layer.md「round3 v1.2」§8/G5;simon playtest 断言仅
上述 3 处改口(108 条总数不变),其余断言(含教学、复活、结算、菜单、序列约束、
速度下限)零改动。
---
## 9. round1-live 变更记录(simon 结算/菜单/反馈修正)
> 依据 research/04-playtests/live/round1/simon-guoguo.md(果果,10 岁 persona 全拟真
> 试玩)。按「playtest 断言零改动」红线的例外流程(§8 先例),本节只追加登记 §3
> 受影响断言的替换口径与新增断言;§3 既有文字不回改,其余 5 个游戏断言零改动。
- **结算屏单击改口(P0 言行不一)**:gameover 阶段单击**不再跳句**,无论语音是否
在播一律直接重开(_restart,跳过教学直达第 1 轮)——结算播报承诺「单击屏幕,
再来一局。」,单击必须言行一致。原「结算语音播放中单击=跳过本句(不重开)」
断言替换为:**结算语音链播放中单击 → 立即进入新局第 1 轮**(phase='announce'、
round=1、round_01 开播、结算链被打断)。无语音时单击重开的原断言不变。结算屏
上滑=重听规则、下滑=打开菜单,与 rules_prompt 播报一致,维持不变。
- **新增边界断言(P1 菜单导航静音)**:菜单内右滑=下一项、左滑=上一项(首项再
左滑回绕末项),切换即播报当前项(menu_restart/menu_home/menu_back);菜单内
下滑=关闭菜单回结算页(§7.5「下滑关闭」约定在 simon 的落地补全)。
- **新增边界断言(P1 未支持手势被吞)**:input 阶段 longpress → error 震动兜底,
不判错、不耗机会、不进重听(同时修复 TONE['longpress'] undefined 导致
audio.play(undefined) 抛 TypeError 的隐性崩溃——live 中"长按 9 秒零反馈"的
实际成因);longpressend(同一动作收尾)静默不重复反馈。
- **新增边界断言(P1 正反馈稀缺)**:每轮答对必播一句表扬——既有台词池
[voice/correct, voice/gd_clear] 按轮轮播(第 1 轮 correct、第 2 轮 gd_clear、
交替),替换原 G6「correct 每 4 轮一次 + gd_clear 每局限 1 次」口径;
gd_record 每局限 1 次、chance_plus 每 4 轮发放,均维持不变。
- **组合占用提示改口(P2 每轮必念)**:gd_occ_up/dt/both 改为**每局每种组合只在
首次出现轮播一次**;之后仅在玩家答错消耗机会重听时随 retry_use 链尾重播本轮
组合提示。替换原 H2「每轮序列播放完成后按序列播占用预告」口径。新增断言:
同一 gd_occ_* id 不在两个轮次开场重复播报;答错重听链尾重播当前组合提示
(序列含 up/doubletap 时计数 +1,不含时不变)。
- **guide.test.mjs G6 simon 段同步改口**:原「轮成功链尾播 gd_clear(每局 1 次)」
断言替换为「第 1 轮表扬 = correct」;「gd_clear 每局仅第 1 次轮成功播」替换为
「第 2 轮表扬轮播到 gd_clear」;gd_record 断言保留,但需等表扬+纪录两句链播完
再计数(链多句时立即计数会采到链中——一并修正原断言采样过早的时序问题)。
---
## 10. live round1 变更记录(storyline《声命线》老陈全拟真试玩修复)
> 依据:research/04-playtests/live/round1/storyline-laochen.md(P2-1 结局双击重听
> 失效 / P2-2 猎狗台词不认分支 / P2-3 静默无兜底 / P3-2 结局后状态播报滞后)。
> 本节只做追加;§1 既有断言与 §7 全局断言零改动,其余 5 游戏不受影响。
新增边界断言(storyline):
- **结局双击重听**:结局链播完(结算态 awaitingRestart)双击 → 结局语音重播;
重播期间单击 = 跳过本句(不触发重开,nodeId 不变);重播链播完回到结算态
(awaitingRestart === true),此后单击仍可重开。
- **分支台词条件**:`n15` 右滑(钢索)路径进 `n18` **不播** `n18_dog`(无涵洞经历,
台词「涵洞也拦不住你」不得出现,n18 只播抉择提示 p6);`n15` 左滑(涵洞)路径
照播 `n18_dog`。台词文本不变、不新增语音 id。
- **结局后状态播报**:结算态上滑 → help 后播**当前结局语音**(不再报 status3
「这是最后一段路了」);播完直接回结算态(不二次重播节点)。
- **静默兜底(standard 档)**:非抉择节点播完等待时,13s 无操作播 `gd_continue`、
30s 播 `gd_again`(复用向导层看门狗计时/复位;玩家手势后重置,下一等待点
重新挂载)。`guide=full` 节奏维持 [25s,50s] 不变(guide.test 锁定);
`guide=off` 不挂任何定时器(既定全静契约)。
---
## 11. live round1 变更记录(space《盲航》小赵全拟真试玩修复)
> 依据 research/04-playtests/live/round1/space-xiaozhao.md(P1×4 / P2×2)。只改
> 触发时机/判定逻辑,台词文本与语音 id 零变更。按 §8 先例只追加登记 §5 受影响
> 断言的替换口径与新增断言;§5 既有文字不回改,其余 5 个游戏断言零改动。
- §5 边界「同向判定:撞击前 1.5s 内同向滑 = dodge(dodges+1);反向滑 ≠ dodge」
→ 替换为:**同向滑判定窗口 = 呼啸全程**——陨石 spawn(呼啸响起)到撞击点
+250ms 宽限之间的同向滑均判 dodge;spawn 之前的同向滑不判(`ob.spawnAt`
下界)。新增回归断言:呼啸响起后 0.2s 内早滑(距撞击 >1.5s)也算躲开
(P1「早滑被静默吞掉」)。
- §5 边界「护盾充能:doubletap 后 30s 内 shieldReadyAt 锁定,到时播 shield_ready」
→ 替换为:doubletap 后 **15s** 内 shieldReadyAt 锁定,到时播 shield_ready
(queue 排队播,不顶 protect_end/归因句)。新增:充能中/未引入时双击 →
播 feat_shield_done 应答 + HEARTBEAT 震动(4s 去抖,连刷不重播)。
- 新增边界断言(P1 方向语音永远迟到):裸飞陨石 spawn 当刻 voice/dir_<dir>
与 whoosh 同窗播出(播放日志同一时刻),撞击前 500ms 的 loud 警报档不再带
方向呼喊;撞击点落在保护期内的陨石 spawn 时不播 dir_<dir>(protect_<dir>
长句教学优先)。
- 新增边界断言(P1 保护期断崖过渡):protect_end 后第 1~3 颗裸飞陨石逼近时长
固定 = PROTECT_APPROACH_MS(4.0s,不收缩),第 4 颗起 < 4.0s 接入难度曲线。
- 新增边界断言(P2 最后一命警告健壮性):hits===2 时 hit_<dir> 在播中被
dir_<dir> 呼喊打断,呼喊播完后 hit_last 仍自动接播(挂起 + 呼喊 onComplete
接力,不再整链静默丢失)。
- 新增边界断言(P2 feat 教学仅首局):同一 SpaceGame 实例第 2 局 advance 过
20s/45s 不进 feature phase、不播 feat_boost/feat_shield;双击护盾/单击加速
第 2 局开局即用(introDone 标记挂实例,不随 _resetRunState 重置)。
- 依据:round1-live 试玩报告问题清单 1/2/3/4/5/6;space playtest 其余断言零改动。
- 随上述改口的测试脚手架微调(非断言变更):dir 呼喊断言前补一次 `await tick()`
——round4 R1 活体复验追加修复「voice 播放安全门」(_playVoice 异步竞态:同 tick
第二个 play 漏杀前一个 → 双管线并播 + 节点泄漏;游戏层串行门 + 对局语音全量
prewarm 缓存热修复,引擎零改动),播放调用改为 microtask 落位,断言语义不变。
guide.test.mjs §⑨ G7 段同步改口为「呼喊与呼啸同窗、与 loud 警报错峰 ≥2s」。
---
## 12. round1-live 变更记录(escape《暗室》阿May全拟真试玩修复)
> 依据:research/04-playtests/live/round1/escape-amay.md(P1 三项:卡关提示失控 /
> 语音中单击吞检查 / 撞墙教学腔,唯一事实源)。本节只做**追加**,§2 既有文字不
> 回改;受影响断言的替换口径与新增断言登记如下,escape playtest 其余断言零改动。
- §2 边界「卡关提示:计时器快进 60s/120s/180s → 依次播 stuck_*_1 / stuck_*_2 /
stuck_*_3 + nav_*;任意进展事件后重置(`_stuckShown` 清空)」→ 替换为:**卡关
提示按"无操作时长"计时**——PLAY 阶段任何有效手势重置计时(`_lastActiveAt`);
连续无操作 60s/120s/180s → 依次播 L1(stuck_ask + stuck_*_1)/ L2(stuck_*_2)/
L3(stuck_*_3 + nav_*,此后每 60s 无操作重复);任意进展事件后 `_stuckShown`
清空(下一段静默期从 L1 重新分级)。三级阈值与分级内容不变(01 号文档 §3.2)。
- 新增边界断言(提示排队礼仪):卡关提示到点时若有语音在播,**只入待播队列,
等当前语音自然播完才播,绝不顶掉进行中的语音**(断言:在播句未被截断、提示
句开播时刻 ≥ 在播句开播时刻 + 其时长);待播期间玩家任何操作 → 该提示作废,
未播级别不计入 `_stuckShown`(下段静默期可重新触发)。测试允许用钩子直写
`_lastActiveAt` 并直调 `_checkStuck()` 模拟"语音播放中到点"。
- 新增边界断言(活跃免扰):PLAY 中每 ~25s 一个普通手势、持续 ~250s 且无任何
进展事件 → 全程零 stuck_* 播报;停止操作 60s 后 L1 如期而至(计时器仍武装)。
- §2 中"voice 播放中单击 = 跳过本句"的行为口径补全:可跳句播放中单击 = 跳过
本句(链播继续)**并补发检查**——环境音即时重播、检查描述进待播队列(链播
未完则排队,不顶句;链播已完则照常 800ms 后播)。不可跳句(关键获得/L3 带路)
播放中单击 = 忽略,原断言(不跳句、不触发检查)不变。
- §2 边界「撞墙」补充口径:PLAY 阶段撞墙 = wall 音效 + error 震动 + 位置不变 +
`voice/wall`("那边是墙,换个方向。"),**不再接播 guide_blunt_* 方位句**;
教学腔方位句(guide_blunt_*)仅限 GUIDE 阶段(G2/G3 纠错路径断言不变)。
- 移除向导 full 档「连续撞墙 ≥2 次 → 卡关阈值提前一级(L1 即刻/L2 60s/L3 120s)」
的 escape 接线(14 号文档 v1 裁定 5/§2 escape 行):该机制在"无操作时长"语义
下等价 L1 永触发,是 round1-live「机关枪提示边玩边扫射」的主因;`_wallBumps`
状态一并移除。web/harness/sessions/escape.mjs 剧本第 58-64 行相关旁白(连撞
两墙等提前提示)随本变更过时,剧本本身不断言、不影响运行。
---
## 13. round1-live 变更记录(rhythm《节拍行者》小江全拟真试玩修复)
> 依据 research/04-playtests/live/round1/rhythm-xiaojiang.md(P0×2 / P1×4 / P2×3)。
> 只改触发逻辑/判定参数/反馈音复用:台词文本与语音/音效资产零新增零变更
> (Miss 音 = 既有 inst_hat_l 以 playbackRate 0.5 降调复用;教学上/下滑步复用
> gd_answer「现在跟着我打」作引导句)。按 §8 先例只追加登记 §4 受影响断言的
> 替换口径与新增断言;§4 既有文字不回改,其余 5 个游戏断言零改动。
- §4 关键路径 1「教学 T1-T3」→ 替换为:**教学 5 步**(tut_1 单击 → tut_2 左右 →
上滑(gd_answer)→ 下滑(gd_answer)→ tut_3 三音带双击压轴)——上/下滑音色
教学补全(P3-11;tut_3「最后一句」台词保持为真,故上/下滑步插在其前)。
下滑步中临近 down 音符时下滑 = 演奏应答(不跳教学);远离时下滑 = 跳过教学
(原行为不变)。
- §4 边界「tap 补偿:回调时刻 -0.30s 判定」→ 替换为:**判定时刻 = 触摸时刻,
按手势补偿识别延迟**:immediateTap(index.html 已开启,按下即发 tap)下 tap
补偿 0(expected+0 注入判 Perfect);双击事件前 350ms 内无 tap 事件 → 闩锁
回退旧引擎行为(补偿 TAP_DELAY 0.30s,expected+0.30 注入判 Perfect;测试钩子
`game._immediateTap = false` 直接置位验证旧路径);滑动补偿 SWIPE_DELAY
0.15s、双击 DOUBLE_DELAY 0.20s(识别均在 touchend;expected+补偿 注入判
Perfect)。Miss 超时放宽 = 对应补偿 + 0.10s。
- §4 边界「Miss=无乐器音」→ 替换为:Miss 不播**该音符的**乐器音(错过=没出声
不变),但必播 **Miss 反馈音**(inst_hat_l 降调 0.5× 闷镲)+ error 震动
(P2-8 Miss 无声);长按 = 死输入同款反馈(Miss 音 + error 震动,不判定不
归属,P0-2 附项);longpressend 静默。
- 判定窗放宽(P2-10 / P0-1):PERFECT ±0.12 → **±0.15s**、GOOD ±0.25 →
**±0.35s**(吸收滑动/双击识别延迟与蓝牙余量);评级线不变(B≥0.70,与
grade_b 台词「超过七成」一致——窗口+补偿校准后真人认真打可达 B)。
- 新增边界断言(P0-2 下滑折中加宽):down 应答音符自其领奏响起(expected-4 拍)
至判定死线(expected+GOOD+SWIPE_DELAY+0.10)之间,下滑一律判演奏——慢滑
(识别 +0.35s)踩点下滑判 Good 不弹菜单;该窗口之外下滑才呼出菜单(不变)。
- 判定归属改口(密集谱防抢占):归属改为**同手势最近未判定音符优先**——同句
0.5 拍相邻的异手势音符(如 song2 第 7 句 down/up 相邻)不再被"最近归属"
跨手势偷走;无同手势在窗音符时,最近异手势音符落在错手势窗(GOOD 的一半)
内 = 窗口内做错动作 Miss(原"窗口内错手势判 Miss"语义保留,窗口收紧);
**tap 豁免异手势 Miss**(immediateTap 序曲 tap 防误判,真正错手势 tap 由该
音符超时自动 Miss 兜底,同样有 Miss 音)。
- 新增边界断言(P1-4 暂停真冻结):菜单开启 3s 期间无新 Miss(判定冻结)、无
新排程音符(谱面冻结);关菜单即停菜单语音链(isVoicePlaying === false,
菜单语音不骑恢复后的领奏——live「菜单不暂停」感知的主因)。
- 新增边界断言(P1-3 结算 BGM 状态管理):结算 menu pad(bgm/menu)只在语音链
末句(voice/restart)播完后起播(playLog 顺序断言),且只在仍处于结算态时
起播(重开/下一首后过期看门狗 fire 不得把 menu pad 漏进正片)。
- 新增边界断言(P1-5 回大厅):结算屏下滑 → 进 leaving 态 + 播确认语音
menu_lobby → 随后 window.location.href 置 '../'(真实跳转,不留尸体页面)。
- 新增边界断言(P3-12 零通过不夸):教学全程零通过(逐步失败 2 次跳过)收尾播
retry_skip 不播 tut_done;有任一步通过则照常播 tut_done。
- 新增边界断言(immediateTap 序曲 tap 治理):非演奏阶段(intro/select/menu/
end/leaving)tap 延迟 500ms 生效,期间任何其他手势到达即作废(防滑动/双击/
长按的序曲 tap 误触发选曲/重开/菜单项/跳句);演奏阶段(tut/main)tap 只
认领 tap 音符——应答 up/down 等音符前的序曲 tap 出声(kick)但不产生尝试
记录、不判 Miss、不抢占归属。
- 新增边界断言(滞留语音链看门狗作废,live 复验深挖):教学纠正链在播时下滑
跳教学(链被顶掉)→ 进入 main 后越过 10s 看门狗窗口,phase 保持 main 不被
拖回 tut。机制:`_speakGuarded` 看门狗只在"自己这条链仍是当前链"时可 fire
(语音链序号 `_voiceSeq`:任何更新的 _speak/_speakGuarded/_cleanup 都会作废
更旧的滞留看门狗)——否则滞留看门狗会把 onDone(如 _tutLead)砸进毫不相干
的相位(live 实测:纠正链被顶 10s 后游戏从 main 被拖回 tut,遗留的 mid_song
定时事件跨相位乱入)。
- P1-3 附记(证据保留):live 事件流中「重开后 track90 排程 0.5s 被 stop」实际
停的是结算 menu pad(sid 对得上);混音 40-120Hz 频段能量各局一致,track90
全程在播——「重开后 BGM 消失」是事件误读。真实缺陷 = 结算看门狗 10s 早火
(menu pad 骑语音链尾,报告 P3-15 同因)+ 过期 fire 无相位守卫,本条已修。
---
## 14. round1-live 变更记录(rpg《剑与声》小周全拟真试玩修复)
> 依据 research/04-playtests/live/round1/rpg-xiaozhou.md(P1 格挡与血量播报矛盾 /
> P2 闲置提示结算中插话被掐 / P2 回合提示口吃 / P2 教学"挡住了"与实际不符+重播 /
> P3 选项循环误选返回)。设计裁定:格挡**仍有擦伤**(05-rpg §2「减伤 70%」、
> 11-rpg-battle-rebalance §3「格挡成功 2-3 伤」),非全免伤——故修数值对齐设计 +
> 教学明说减伤经济 + 播报与战况匹配,不做格挡全免。台词文本与语音 id 零新增零
> 变更(TTS 环境缺失);只改触发逻辑/判定参数/选播既有句。按 §8 先例只追加登记
> §6 受影响断言的替换口径与新增断言;§6 既有文字不回改,其余 5 个游戏断言零改动。
- §6 关键路径 4(教学战四步)中 T1 播报口径改口:attack 步**不再播 tut_b3**
(其实录为旧两步教学"格挡→攻击"台词「挡住了!轮到你了。左右滑选攻击,单击
出剑。」,新顺序 T1 在格挡之前播「挡住了!」与实际不符),改播**重播既有
tut_battle_2**「左右滑切换招式,攻击、破空斩、防御、金疮药。单击,出手。」
(语义一致,不新增语音 id);tut_b3 资产保留但退出教学链(TTS 缺失不可重录,
列遗留)。原断言「T0 切换 2 次 → T1 attack(tut_b3)」替换为「T1 attack 重播
tut_battle_2(段内计数 ≥2)且教学全程 tut_b3 计数 = 0」。教学 8s 重复提示
补口径:挂载后玩家有任何操作则跳过本次重复提示(16s 兜底推进不变;
B1「全程不动 → tut_b0 重播 ≥2」断言不变)。
- §6 关键路径 4 的 T2 结算链改口:parry 步结算(成功/失败两路径)在 tut_b2b /
tut_b4 与 tut_b6 之间插播**既有 tut_battle_4**「没把握就防御,伤害减半。金疮药
可以回血。」——格挡体验点明说减伤经济(格挡≠免伤、防御减半、药回血;无
"格挡也有擦伤"原句资产,选播现有最近说明句,补录列遗留)。原断言
「tut_b4 → tut_b6 有序」替换为「tut_b4 → tut_battle_4 → tut_b6 有序」。配套:
该三句链真实时长 ~16s,兜底 10s→**20s**(原 10s 会在链中误触发进
PLAYER_SELECT、cmd 指令名拦腰顶断 tut_b6);defend 步教学看门狗改为**链播完
进回合时才挂载**(8s/16s 计时从玩家可操作起算,不再抢在 tut_b6 播完前跳步
——live 复验发现,本轮一并修复)。
- §6 边界「格挡:前摇窗口内双击 → 伤害 ×0.3」补充口径:擦伤在 ×0.3(四舍五入)
基础上**钳 1~3**——对齐 11 文档 §3「格挡成功 2-3 伤」(原实现无封顶,Boss
二阶段 base 12 单发擦伤可达 4;min 1 保住"擦伤必有"的设计痛感)。B3 既有
断言(base 4 → 1)不受影响。
- 新增边界断言(P1 全格挡不掉 low):Lv3+铁剑+皮甲标准出装 Boss 战全格挡打法
(每次前摇内双击、不喝药)→ 全部敌方攻击均被格挡且擦伤 ∈[1,3];全程**不播
st_hp_low**;战后血量比率 ≥0.3;全格挡可击杀 Boss。确定性探针:base 12 的
一刀被格挡 → 擦伤恒为 3。
- 新增边界断言(P2 闲置提示不顶断结算语音,guide=full):PLAYER_SELECT 闲置
30s → gd_stall 开播;其开播中玩家出手(击杀)→ 结算语音链首句
(btl_enemy_die)**queue:true 排队等 gd_stall 播完**,不拦腰顶断;无闲置提示
在播时击杀语音不排队(对照,默认顶句语义不变)。机制:看门狗 cond 增加
`!b.resolving`(回合结算中禁止插入)+ `_speak` 在向导句余波 6s 内首句排队。
- 新增边界断言(P2 指令名口吃):650ms 指令名定时器按 PLAYER_SELECT 代数
(selectSeq)作废旧回合滞留;同一指令名 1.2s 内已播过则跳过本次——折返滑回
攻击+滞留定时器 → cmd_attack 不双播;相邻两回合连进 → cmd_attack 只播一次。
- 新增边界断言(P3 返回项末位提示,guide=full):探索态右滑落到"返回"项
(各场景恒为末项)→ 报名 opt_back 后接播既有 gd_wrap_last「最后一个了。」
(每场景一次,与回绕提示共用 _wrapShown 去重;商店"离开"项同款,每次进商店
一次);序号播报无现成语音资产,按任务裁定做前者,不新增语音 id。
- 依据:round1-live 试玩报告问题清单 P1-2 / P2-1 / P2-2 / P2-3 / P3-3;rpg
playtest 断言 139 → 159(新增 20 条),其余断言零改动。
---
## 15. round2-live 变更记录(simon《音序回响》果果全拟真复测修复)
> 依据 research/04-playtests/live/round2/simon-guoguo.md(P1-N1 免费重听货不对板
> 冤死 / P2-N2 下滑首次进序列无提示 / P2-N3 菜单不教双击确认 / P2-N4 重播期手势
> 被吞 / P3-N5、N6)。台词文本与语音 id 零新增零变更(TTS 环境缺失);只改计数
> 逻辑。按 §8 先例只追加登记 §3 受影响断言的替换口径与新增断言;§3 既有文字不
> 回改,其余 5 个游戏断言零改动。
- **N1 修复:重听改两层账(规则级冤死根治)**。教学 gd_economy 承诺「免费机会
有两次,用完要扣一次机会」,旧实现免费第二次要打完第 4 轮才随 chances +1
发放——玩家第 1 次重听(chances 1→0)即听报「免费重听用完了」,第 2 次求
重听被拒,之后答错一题立即 game over("听 2 遍+错 1 题=死")。§3 关键路径 4
「主动重听 → 断言 chances 减少」口径改口为:**免费重听每局 2 次开局即给足
(`freeRelistens`,新实例字段,_beginGame 重置),主动重听(input 上滑)先耗
免费额度、不碰 chances;免费用尽后第 3 次起重听才扣 chances;免费与真机会
皆空时求重听 → 拒绝(error 震 + chances_out,不判错、不耗账)**。播报沿用
H3 既有句:免费 2→1 播 gd_chances_left1、1→0 播 gd_chances_left0;扣真机会
且扣空(chances→0)追加 chances_out 如实报。答错自动消耗路径(retry_use +
chances_out,只走 chances 机会账)与每 4 轮 chances +1(上限 2)均不变。
- §3 断言变更登记(simon playtest 123 → 132,净 +9):第 4 轮新增 1 条
「免费重听每局 2 次开局即给足(freeRelistens === 2)」;第 5 轮原 6 条
(「主动重听耗机会:chances 1→0」「播 relisten 并重播」「重听后输入进度
清零」「chances=0 上滑非期望:不判错」「chances=0 上滑播 chances_out」
「chances 不变(不为负)」)替换为 14 条四层账块——①第 1 次重听用免费额度
(free 2→1、chances 不动、播 relisten+gd_chances_left1、重播后 inputIdx 清零);
②第 2 次仍免费(free 1→0、chances 不动、播 gd_chances_left0);③第 3 次才
扣真机会(chances 1→0、追加 chances_out);④两账皆空拒绝重听(不判错、
两账不为负、播 chances_out)。链尾句断言一律在链播完(回到 input)后计数。
- guide.test.mjs 同步(121 → 122):⑧ G5 simon 段两处加测试钩子
`game.freeRelistens = 0`(免费层置空,专测扣真机会路径,断言文本零改动);
⑩a H3 段 5 条断言按两层账改口(旧钩子 `game.chances = 2` 模拟"免费第二次"
作废)——余量句改锚免费余量(free 2→1 播 left1、1→0 播 left0、chances 全程
不动),新增 1 条「免费重听每局 2 次开局即给足」;拒绝路径改用钩子
`game.chances = 0` 置空真机会后验证(两账皆空 → 拒绝 + chances_out)。
- **N3 菜单不教"双击确认"**:查 voice_text.json simon 条目无可复用操作法句
(rules_prompt「下滑,打开菜单」在菜单内语义相反、skip_hint/t6_double 语义
不符;rhythm/space 的 menu_main「菜单。单击切换选项,双击确认。」语义虽
与 simon 菜单完全一致,但引入属新增语音 id,本轮约束不允许)。**记遗留
(需要新台词)**;菜单手势语义不做任何改动。
### 遗留清单(round2-live simon,本轮不修)
1. **菜单操作教学句(N3,需要新台词)**:补录 simon 版 menu_main(参照
rhythm/space 既有句「菜单。单击切换选项,双击确认。」,与 simon 菜单语义
一致),进入菜单时链尾补播。
2. **大厅零反馈 / 误入其他游戏(复验项 7,跨游戏)**:web/index.html 大厅对
6 种手势全部零反馈、无回游戏路径;属跨游戏大厅问题且需要新台词(入口语音
+ 每步音效),本轮不修。
3. **N2 down 首次进序列无提示**:gd_occ_* 占用预告只覆盖双义手势 up/doubletap
(down 在 input 阶段无第二含义);要补"下"首次提示需新语音 id,列遗留。
4. **N4 序列重播期间手势被吞**:playback「纯聆听阶段手势静默忽略」是 02 §4.1
既定裁定且有断言锁定;加"等等哦"反馈需新音效/设计复议,列遗留。
5. **长按等未教手势只有震动没有语音(round1 复验项 3 遗留)**:需要新台词
("这个手势不算哦"类),TTS 环境缺失,列遗留。
6. **N5 每局"第一次提示"重新计算 / N6 序列"前缀+1"累加**:报告自评可接受 /
属玩法设计层面,本轮不处理。
---
## 16. round2-live 变更记录(storyline《声命线》老陈全拟真复测修复)
> 依据 research/04-playtests/live/round2/storyline-laochen.md(N1 冷启动 intro
> 末句被 30s 看门狗吃掉 / N2 钢索路径猎狗对峙戏整段失踪——round1 P2-2 修复
> 引入的回归 / N3 抉择节点无静默兜底 / N4 结局后上滑无进度播报)。台词文本与
> 语音 id 零新增零变更;引擎零改动(看门狗根因在 game.js 侧,用引擎公开
> `isVoicePlaying()` 判定)。按 §8 先例只追加登记 §10 受影响断言的替换口径与
> 新增断言;§10 既有文字不回改,其余 5 个游戏断言零改动。
- **§10「分支台词条件」断言翻案(N2,回归修复)**:恢复涵洞/钢索两条路径都播
`n18_dog`——round1 按 `!viaCulvert` 整段滤掉 n18_dog,钢索路径猎狗堵桥对峙戏
蒸发、p6 抉择(交出坐标还是拒绝)失去对手戏上下文,玩家裁定"比穿帮更糟"。
替换口径:**n15 右滑(钢索)路径进 n18 照播 `n18_dog` + 抉择提示 p6**;钢索
路径接受「涵洞也拦不住你」的轻微穿帮,标 known-issue 待 TTS 补录分支句后按
`viaCulvert` 选播(标记保留;不新增语音 id、台词文本不变)。
- **新增边界断言(N1 看门狗不误掐在播长语音)**:单句看门狗(VOICE_WATCHDOG_MS
30s)触发时先查引擎 `isVoicePlaying()`——为真(资产真实在播,自然播完必触发
onComplete)→ 续约再等一轮,不掐不告警;为假(资产缺失、引擎静默跳过)→ 照旧
告警自动续链(§1 不卡死契约与"屏蔽资产 30s 告警续链"断言均不变)。根因:冷启动
链为 intro+skip_hint,30s 固定阈值续链时 skip_hint 顶掉在播的 intro(71.7s,
2.2x 也需 32.6s),末句「现在,单击屏幕,睁开眼睛」被吃;菜单重开时链上无
下一句可顶故不咬人。常速下 e1/e2/e4(48~51s)越线风险同除。
- **新增边界断言(N3 抉择节点静默兜底)**:抉择提示(p*)播完 25s 完全无操作 →
重播当前 `voice/p*` 提示句(复用既有资产),50s 再复述一次后彻底静默(两级
上限,与继续节点同一礼仪);玩家任何手势复位(抉择等待态空点重新挂载 = 计时
重置;已缓存 pendingChoice 直接推进不挂);`guide=off` 不挂(全静契约)。
full/standard 档提示句均由游戏层播(p* 是剧情内容不是向导句)。与 14 号文档
「抉择态(p* 播完)不插语音不挂看门狗」裁定的兼容性:该裁定本义是"提示播完
立即可选、不插语音延迟抉择"(W2 契约,保留——choiceArmed 播完当刻即真、零
插播),本兜底只在 25s 完全无操作后复述提示本身,不延迟抉择;变更依据 =
round2 玩家复测证据(p6/p8 实测 35~39s 零提醒,抉择点最易漏听选项)。
- **N4 遗留(结局后上滑无进度播报)**:「已到达结局:XX」类播报需新语音资产,
受"不新增语音 id"约束本轮不修;现状(help + 重播当前结局语音)维持 §10 口径,
待 TTS 补录(如 status_end)后补办。
- 依据:round2-live 试玩报告 N1/N2/N3/N4;storyline playtest 断言相应新增/替换
(钢索 n18 翻案 1 条 + N1 长语音 6 条 + N3 抉择兜底 7 条),guide.test 全绿不变,
其余 5 个游戏断言零改动。
---
## 17. round2-live 变更记录(escape《暗室》阿May全拟真复测修复)
> 依据 research/04-playtests/live/round2/escape-amay.md(P1-新① 引导链断裂
> g1_move 永不播放 / P1-机关枪复验"部分修复" / P2-新② 逃脱台词开头丢失 /
> P3-新③「先跟我走」信息量为零)。台词文本与语音 id 零新增零变更;只改
> 触发逻辑与音效时序。按 §8 先例只追加登记 §2 受影响断言的替换口径与新增
> 断言;§2 既有文字不回改,其余 5 个游戏断言零改动。
- **P1-新① 引导链断裂修复:G0 干等"单击继续"却无人告知该手势(根因)**。
复盘 events/transcript:g0_intro 完整播完后游戏停在 G0 等单击,但全部语音
里没有一句说过"单击继续"——round1 靠解锁单击漏进游戏误推 G0→G1 被掩盖,
round1-live 修复解锁漏触后暴露为 intro 后 17~91s 死寂;玩家滑动只被
guide_offpath「先跟我走」拦回(不教方向),最后一次下滑触发跳过,8 步
引导整体蒸发(三次复现路径同因)。修复(web/escape/game.js):
① `_startGuide`:g0_intro 自然播完且 1.2s 内玩家未单击 → 自动
`_advance(1, [g1_move, skip_hint])`——**g1_move 必播**(台词零改动,
单击仍可随时立即推进);② G0 在 intro 播放中的滑动改为忽略(原拿
guide_offpath 顶掉开场白、且 intro 被打断后 onDone 不发、自动推进永不
挂载——死寂第二成因);③ **下滑跳过仅限答案不含滑动的步骤
(G0/G3/G5/G6)**:G1/G2 的正确答案是"任意滑动"(g1_move 原话「朝任意
方向滑一下」)、G4 的答案就是下滑——这些步骤下滑 = 作答不可跳过
(G4 既有裁定同逻辑扩展;13 号文档原"任何步骤下滑跳过、G4 除外"口径
就此改口)。§2 断言变更:关键路径 A 的 G0 段口径不变(单击仍即推 G1);
新增场景 A2「冷启动引导链」14 条——intro 播完零手势 1.2s 自动播
g1_move、intro 播放中滑动不顶开场白且 g1_move 仍自动播出、G1/G2 下滑
= 作答(不播 guide_skip)、零 G0 单击走完全链进 PLAY、G3 下滑仍跳过。
- **"卡关提示机关枪"复验翻案:计时器无 bug,stuck_key_2 来自双击兜底**。
逐秒复盘 round2 会话 transcript(t=556.9 重开 → 603.9 tap / **605.4
doubletap** / 607.1 swipeup → 608.0 stuck_key_2):该句是 `_useItem`
无目标兜底的设计内主动求提示(§3.2「双击无目标:先播背包,再播 L2 级
明示」——双击后 2.6s 链播,非 5s 轮询到点);`_restart`/`_enterPlay`/
`_resetState` 均重置 `_lastActiveAt`,`_checkStuck` 按"无操作时长"
(60/120/180s)分级,重开后 61s 无操作的 stuck_ask(t=670.1)触发正确。
代码零改动;新增场景 C4 冻结语义:重开后每秒操作 90s 零 stuck_*、停手
60s L1 如期(计时器仍武装)。live 复验口径:高频操作 90 秒零卡关提示
(双击兜底属主动求提示,不计入)。
- **P2-新② 逃脱台词开头丢失修复:音效后移避让(不改语音/不增 id)**。
根因:`_escape` 同帧并发 gate_open(2.8s 轰鸣)+ win_chime 与 escape
人声(14.92s),轰鸣恰好盖住头句「你扳动开关。电机轰鸣,」(三连复现
heard 均从「沉重的铁门缓缓升起」起)。修复:gate_open/win_chime 经
`_timer` 后移 2600ms(会话守卫,重开/停页即清)——人声头部(1.0x
≈2.4s、1.7x ≈1.4s)无遮挡进耳朵,轰鸣落在「电机轰鸣,铁门缓缓升起」
附近,声画同步反而更准。§2 关键路径断言替换口径:原「逃脱音效
gate_open + win_chime 各播 1 次(双击当下)」替换为「双击当下音效计数
= 0(人声头部 2.6s 无对撞)+ tick 2600ms 后各播 1 次」,断言条数 +1。
- **P3-新③「先跟我走」信息量为零**:受"不得改台词文本/不新增语音 id"
约束无法改写该句;本轮以 ①②③ 将其压缩为极小概率兜底(仅 intro 播完
后 1.2s 空档内的滑动可触发,自动推进到点即被 g1_move 顶掉),记遗留
(待 TTS 补录带方向的兜底句,如"等我说方向,先跟我走")。
- 依据:round2-live 试玩报告「如果只能改 3 件事」全部 3 条;escape
playtest 断言 121 → 140(新增 19 条:A2×14 + 逃脱音效时序×1 + C4×4),
既有 121 条语义零回改(仅逃脱音效 1 条按上条口径替换计时),其余 5 个
游戏断言零改动。
---
## 18. round2-live 变更记录(space《盲航》小赵全拟真复测修复)
> 依据 research/04-playtests/live/round2/space-xiaozhao.md(B1 高速段误暂停
> 两次复现 ta=664.99/1670.73 / B2 恢复后 3 秒暴毙 / B3 回大厅落无声死界面 /
> B4+A5② 警告与结算叠播 / B5+A5① 高速段最后一命警告缺席)。台词文本与语音 id
> 零新增零变更;只改触发逻辑与手势路由。按 §8 先例只追加登记受影响断言的
> 替换口径与新增断言;§2 既有文字不回改,其余 5 个游戏断言零改动。
- **B1(P1)高速撞击时偶发自动暂停跳菜单修复:下滑开菜单加判定冷静期**。
根因:旧折中仅"无下方陨石悬置时下滑=菜单"——高速段玩家在撞击瞬间
下滑躲避(陨石已判定出集合),被误判为开菜单(两次复现均为撞击后
0.13s/0.43s 的下滑)。修复(web/space/game.js):`_resolve` 任何结局都记
`_lastResolveAt`;`_onPlayGesture` 下滑在**最近一次判定(撞/躲/格挡/吸收)
后 800ms(MENU_CALM_MS)内一律按躲避意图忽略**,绝不开菜单;其余时刻
保留旧折中(无下方陨石悬置即可开菜单)——躲避手势永不误开菜单,
主动暂停可达性不变。
- **B2(P1)暂停恢复无缓冲修复:恢复后前 3 颗裸飞陨石回 4.0s 慢节奏**。
`_closeMenu` 重置 `_bareCount = 0`,复用保护期断崖过渡机制(4.0s 逼近 +
4.0s 刷怪间隔),首颗撞击点落在恢复后约 4.8s——与"保护期结束 3 颗慢过渡"
同款软重启,不再"继续飞行 = 3 秒暴毙"。
- **B3(P1)回大厅落无声死界面修复:rhythm round1 同款收尾流程**。
`_goHome` 重写:幂等 `_goingHome` 标记 → `leaving` 收尾态(停刷怪/BGM,
不再受理对局/菜单/结算手势,单击仍可跳确认句)→ `_speakGuarded` 播
menu_lobby 确认句(2s 看门狗兜底)→ `stop()` + 跳转大厅。旧版无确认
直接跳,跳转失败时 tap/滑动全无响应,纯听觉玩家被关黑屋。
- **B5/A5①(P1)高速段"最后一命"警告播不出修复:呼喊接力保留 + hit_last 在播期间呼喊抑制**。
根因:round4 R1 呼喊接力机制里,归因句被下一颗 spawn 呼喊顶断后由呼喊
onComplete 接播 hit_last,但接播本身无保护——高速段刷怪 1.2s/颗,hit_last
刚起播就被下一颗呼喊顶没(或致命撞击先至,链整体蒸发)。修复:新增
`_hitLastPlaying` 在播标记,hit_last 在播期间 spawn **不播方向呼喊**
(警告播完前不被顶断);归因在播期间呼喊保留生存优先级(顶断 → 呼喊播完
接力,round1 实测 0.8s 低延迟警告路径不变);链被菜单/分批引入旁白顶断时
恢复对局经 `_rearmRunTimers` 立即补播;里程碑与护盾不可用应答在链期间
改 queue 排队不顶链。链结束呼喊恢复。
- **B4/A5②(P2)死亡瞬间语音打架修复:坠毁即掐断警告链**。`_gameOver`
清 `_hitLastPending/_hitLastPlaying` 并 `stopVoice()`——旧版 hit_last/
gd_last_life 与 1.2s 后的结算 time_* 叠播互相掐(live ASR 实录混成一团),
现结算链在静音后干净开场。
- 遗留(本轮不改):A7 保护期归因长句每颗重播(P3 烦感已降)、A8
second_run_ask 仅页面进入时播(restart 路径不经过,设计内)、B6 保护期
时长恒定 60s 无缩水(报告按 shield_block 估算有误差)、B7 菜单选项播报
延迟感(voice 安全门串行代价,可接受)。
- 依据:round2-live 试玩报告「如果只能改 3 件事」全部 3 条 + B4/B5。
space playtest 断言 138 → 155:新增 17 条(hit_last 在播标记×2、接播期间
呼喊抑制×1、呼喊恢复×1、坠毁前警告在播×1、坠毁掐链×1、恢复缓冲×4、
误暂停守卫×2、回大厅收尾×5——含 leaving 态/确认句/播完前不跳转/滑动忽略/
跳过即走),替换 1 条(菜单下滑前提补"过冷静期"),hit_last 段既有
"呼喊顶断+接力"断言语义零回改;guide.test 全绿(space G7 呼喊断言
不受影响:该链路 hits=0)。
- **live 复验**(web/harness/live/out/space-20260901063255,LIVE_PORT=8140,
8128 被占按预案自起;voice=male/speed=1.35/bgm=1.0/guide=full 全拟真驱动):
① 误暂停守卫——判定(dodge)ta=6.28 后下滑落点 ta=6.76(Δ=0.48s<0.8s
冷静期)无 paused/bgm-menu;过冷静期 +0.9s 非下方悬置下滑正常开菜单
(paused ta=10.22),爬升段仍可开菜单(paused ta=82.65)。② 恢复缓冲——
恢复 ta=83.23 后首颗 +0.80s 刷出,前 3 颗逼近实测 4.00/4.00/4.00s、
刷怪间隔 4.00/4.00s,第 3 间隔起回曲线(2.68s)。③ 回大厅——双击确认后
menu_lobby 确认句起播(ta=118.94),随后探针在新文档重新就绪
(probe_ready t=12.3 ta=-0.882 = 跳转 '../' 成功)。④ 警告链——第 2 撞
ta=104.94 → spawn 呼喊顶断归因(生存优先级保留)→ 接力 hit_last
ta=105.61(+0.67s,与 round1 低速好评路径同型),在播 [105.61,107.42]
无 dir_* 插队;坠毁 ta=107.42 即掐(vend kill 同刻),crash 后 1.0s 零
新开语音,结算 time_3 于 +1.30s 干净开场,坠毁后无 hit_last/gd_last_life
迟到。复验驱动与探针脚本:web/harness/live/out/verify-space-r2.mjs、
probe-gohome.mjs(out/ 不入库)。
---
## 19. round2-live 变更记录(rpg《剑与声》小周全拟真复测修复)
> 依据 research/04-playtests/live/round2/rpg-xiaozhou.md(P1-2 复验「未修复·形式
> 改变」:格挡与受伤播报错误连线 / P1-新① 探索菜单语音播放中吞 tap / P2-新②
> 教学提示自动轮播互掐 / P2-新③ 杀敌瞬间腰斩回合提示音;P3 酌情)。设计依据:
> 11-rpg-battle-rebalance §3 + 05-rpg-addendum §1 受击行「血量档位降档时
> st_hp_mid/st_hp_low(降档才播,不每击都播)」——该播报本就是"受击(未格挡)"
> 的附属,不是血量变化的全局钩子。台词文本与语音 id 零新增零变更;只改触发
> 逻辑/排队语义。按 §8 先例只追加登记受影响断言的替换口径与新增断言;§6 与
> §14 既有文字不回改,其余 5 个游戏断言零改动。
- **P1-2 格挡受伤播报重连线(擦伤不触发 + 档位一致 + 同档节流)**。live 事件流
复盘:全程 20 次格挡成功、0 hurt 音效,st_hp_mid/low 却精确落在格挡音后
0.09s 播出(bandit 636.5s/841.2s、Boss 962.1s/984.0s)——根因:旧实现把降档
播报挂在"血量变化"上(bandBefore/bandAfter 跨档即播),格挡擦伤(1~3)跨档
同样触发,全格挡完胜被全程喊受伤,警报被驯化成背景音。逐秒重建血量轨迹另
证实:播报时刻档位本身正确(984.0s 时 7/28=0.25 确属 low),玩家感知"喊 low
实际 mid"来自胜利升级 +8 回血使旧播报变陈旧(997.1s 升级后 12/36=0.33)。
裁定(game.js `_enemyResolve`,注释明写):a) 格挡擦伤静默走血,**不触发**
任何受伤类播报(痛感由格挡音+confirm 震动承担,11 文档 §3"格挡成功 2-3 伤"
是技巧收益而非受伤警报);b) 只在实质受击(格挡失败/未格挡)时播,且播报档
= 结算后当前实际档——`b.hpBandVoice` 记"玩家最后被告知档"(开战=当前档),
比它差才播并同步(擦伤暗中跨档后,第一刀实质受击按当前实际档补播,绝不
错位);c) 节流:同档不重复喊(low 档内再受击不重播);喝药回血升档静默,
之后经中间档再次跌破视为新降档可重播一次(回血有 potion 音可感知,不属
"狼来了")。§14「新增边界断言(P1 全格挡不掉 low)」口径加强:全格挡
Boss 战不播 st_hp_low **也不播 st_hp_mid**(擦伤一律静默),该断言其余
部分(擦伤 ∈[1,3]、战后血量 ≥0.3、可击杀)不变。新增场景 B10 断言 13 条
(擦伤跨 0.7 边界零播报/被告知档不变、实击降档播 st_hp_mid 且与实际一致、
同档再击不重播、跌 low 播 st_hp_low、low 内再击不重播、回血直接跌回 low
不重播、回血经中间档再跌破=新降档重播一次)。
- **P1-新① 探索菜单语音播放中吞 tap(跳句 + 补发语义动作)**。live 证据:
1264.6s 选项报名开播 2.3s 时单击被整个吞掉(语音被掐、场景未切、死寂
72s);1370.1s「最后一个了。」开播 0.16s 时单击"返回"同样被吞;而战斗里
语音中单击有效(844.5s),规则必须一致。12 文档 §1 跳句惯例在 rpg 探索态
的口径补全:语音中单击**一律先跳句**;在播句为选项报名/边界提示
(`_exploreVoiceKind==='option'`)时单击同时**补发确认当前选项**;desc/
NPC/事件/状态链在播 = 只跳句不确认(A5/B6 契约不变)。实现要点:类别先
取样再 skipVoice——skipVoice 同步触发 onComplete 推进链(末句接播选项报名
会改写类别),跳句后读类别会把"跳 desc"误判成"确认选项"。新增场景 B11
断言 7 条(报名在播单击=跳句+进商店、desc 在播单击=只跳句场景不变、
gd_wrap_last 在播单击"返回"=跳句+回上一张图,guide=full 段)。P3-3②
「提示音播放期间 tap 被吞」随本条一并修复(同一路径)。
- **P2-新② 教学提示自动轮播互掐("播完再上"统一治理)**。live 证据:
333.09s tut_b0 自动重播播到 7.9s 处被游戏自己的 16s 兜底推进
(tut_battle_2)掐断——系统自己的提示链互相顶。裁定:自动轮播路径
(8s 重复提示 / 16s 兜底推进)一律"播完再上"——8s 重复提示到点遇语音
在播则跳过本次(不重播不顶句);16s 兜底到点遇语音在播则每 1.5s 重试、
等声道空出再推进(延后不死锁)。B1 既有断言不变(无语音占用时 8s 重播、
16s 兜底原样触发);新增场景 B12 断言 5 条(占用声道时重复提示跳过、
兜底延后且 teachStage 不变、声道空出后推进且推进语音开播时刻 ≥ 声道
空出时刻)。
- **P2-新③ 杀敌瞬间腰斩回合提示音(指令名礼让排队)**。live 证据:843.9s
「攻击。」开播 0.9s 被 btl_enemy_die 掐成残句。裁定:`_speak` 礼让规则
扩展(与 round1-live gd_stall 排队一脉相承)——刚开播的指令名
(cmd_* ≤1.2s 短句)还在播时(1.6s 余波窗),结算语音链首句 queue:true
排队等它播完(杀敌/半血/降档/教学推进链同受此规则);余波窗外恢复默认
顶句语义。B8 对照断言(无语音在播时击杀语音不排队)不受影响。新增场景
B13 断言 4 条(指令名开播 1.6s 内击杀语音 queue:true、排队后胜利链正常
走完不死锁)。
- **P3 酌情与遗留**:P3-1 商店折扣报价仍报原价("铁剑,一百金")、购后无
折后/余额播报——无折扣价目与余额整句资产,受"不得改台词文本、不新增
语音 id"约束无法修复,列遗留(同 tut_b3 先例,待 TTS 补录折扣价目句与
购后余额句;九折扣款 `shop_discount` 逻辑本身正确,A 场景断言覆盖)。
P3-2 前摇节奏"敌人等台词说完再出手"需教程明说:无现成教学句资产,列
遗留。P3-3① 左端反绕到末项无提示:round1-live 已落地"落到末项即播
(不分方向,每场景/每次进商店一次)"——167.4s 系同次进商店第二次落
末项被 `_wrapShown` 去重,属设计内防抖,维持不变。P1-1 NPC male 语音
资产缺失:资产层遗留(非代码),照旧列遗留。ASR 短句误识:备查非游戏
bug,不处理。
- 依据:round2-live 试玩报告 P1-2 复验 + 新发现问题 1/2/3 +「如果只能改
3 件事」全部 3 条;rpg playtest 断言 159 → 188(新增 29 条:B10×13 +
B11×7 + B12×5 + B13×4),既有 159 条语义零回改(§14 全格挡断言按上文
口径加强,不删减),其余 5 个游戏断言零改动。
---
## 15. round2-live 变更记录(rhythm《节拍行者》小江全拟真第 2 轮复测修复)
> 依据 research/04-playtests/live/round2/rhythm-xiaojiang.md(N1 immediateTap
> 爆音计入判定 / A2 正片踩点下滑弹菜单 / N2 菜单瞬穿 / A4 BGM 死亡)。选型
> 任务书方案 a:引擎 gesture.js 增加 `tapcancel` 事件(仅 immediateTap 模式
> 补发,其余 5 游戏零行为变化);rhythm 游戏层配套判定账簿与复活机制。
> 台词文本与音频资产零新增零变更。按 §8 先例只追加登记;§6/§13 既有文字
> 不回改。
- **事件流对质结论(A4 BGM 死亡 = 事件误读,§13 P1-3 附记结论成立)**:
round2 三个"BGM 排程 0.45s 即被 stop"现场(out/rhythm-20260901020139 ta
378.67/691.56、rhythm-20260901022139 ta 257.99)被 stop 的 sid 全部是
**结算/选曲的 menu pad**(引擎层 bgm/menu:sid 108/235/1),由 `_startSong`
的 `stopBgm(400)` 淡出停止(设计行为,防双 BGM 叠加);曲目 BGM track90
(sid 109/236/2)均按网格正常起播并持续到下一次菜单/结算。混音光谱对质:
retry 局 40-150Hz 低频段 RMS −21.47dB 与"玩家确认有 BGM"的教学后首进段
(−21.50dB)一致,menu pad 只有段 −31.84dB——**retry/选曲路径 BGM 实际
在播,"BGM 死亡"是 stop 事件的 sid 张冠李戴**。唯一真实的 BGM 中断是菜单
劫持连带(下滑误判弹菜单 → `_stopBgmSrc`),随正片下滑修复(下条)根治。
BGM 生命周期代码零改动。
- **N1(P0)immediateTap 爆音判定治理(引擎 tapcancel + 游戏判定账簿)**:
gesture.js immediateTap 模式补发 `tapcancel`——按下已发 tap 后,移动超
tapSlop 转滑动 / longpress 成立 / 触摸 cancel(含无 move 事件快滑在滑动
事件前补发)时各补发一次;双击序曲不发(归属由游戏按双击窗口处理)。
rhythm 新增序曲 tap 判定账簿 `_tapJudg`:演奏阶段(tut/main)每次 tap
判定(命中/自由演奏/教学尝试)记账;`tapcancel` 到达撤销最近 1 笔
(≤0.6s),`doubletap` 到达撤销最近 2 笔(≤0.5s)——声音已出收不回,
判定/统计回滚且不计 Miss;被误认领的命中撤销后音符回到未判定(真不接
由超时 Miss 兜底)。另:非演奏阶段的 500ms 延迟裁决 tap 由 tapcancel
提前作废(慢滑在裁决窗内超 slop 即撤,选曲慢滑不再误触发"选定曲目")。
- **超时 Miss 复活(N1 判定污染的事件流真凶之一)**:round2 事件流实证
miss 全部落在泵的超时死线(expected+GOOD+补偿+0.10)上而非序曲 tap 的
错手势认领——滑动识别 +0.3s/双击 +0.2s/触程余量仅 +0.10s,手势还在
路上时音符常先被拖死几十 ms。新增归属①′:同手势、超时类(kind=
timeout,错手势类不复活)、REVIVE_WINDOW_S 0.6s 内、补偿 dt ≤
REVIVE_DT_S 0.5s(GOOD 0.35 + 慢滑/慢双击补偿误差 0.15)→ `_reviveMiss`
回滚统计后按 dt 改判 Perfect/Good。tap 不参与复活(immediateTap 下
tap 识别零延迟,回调晚于死线 = 触摸本身已晚;且防双击序曲误复活)。
- **A2(P1)正片踩点下滑弹菜单续修**:§13 的 `_downNotePending` 窗口在
正片从未失效,但事件流 3/3 复现的时序是"超时 Miss 先于下滑回调 2~114ms"
——音符在滑动触程中已被泵拖死,回调时 `_downNotePending` 判假 → 弹菜单。
修复:down 音符刚被超时拖死(REVIVE_WINDOW_S 内)同样算"临近"——下滑
不弹菜单,先进复活改判(dt ≤ 0.5s)/ 超时差自由演奏 tom_lo;该期间下滑
豁免异手势 Miss(不顺杀邻音)。窗口过后(>0.6s)下滑呼出菜单的折中不变。
- **N2(P1)菜单去抖独占期**:菜单打开 1s(MENU_DEBOUNCE_MS)内不收任何
手势——演奏途中被弹菜单时,玩家已在路上的手势(双击确认/下滑关闭)
不得穿透菜单(实测 menu_main 说明语音 0.6s 未读完菜单即被"确认")。
配套:guide.test.mjs §⑥ G3 两处关菜单手势前补 1.05s 等待(行为变更的
既有断言适配,断言语义不变);rhythm playtest 场景 A/B 既有菜单用例
(开菜单后 2s/1.5s 才关)天然越过独占期,零改动。
- **新增断言(rhythm playtest 109 → 141,新增 32 条,既有零回改)**:
F3 教学 tapcancel 撤销序曲 tap 尝试记录;F1 正片 tapcancel 撤销序曲 tap
命中(音符回未判定、统计回滚、可重接 Good);F2 双击序曲 tap+tap+
doubletap 归属(双击改判 Perfect、序曲零 Miss、不误伤更早真实命中);
F2c 序曲 tap 误认领命中被双击撤销、撤销后真不接由超时 Miss 兜底;F4
上滑超时拖死(missKind=timeout)后慢滑回调复活改判 Good、Miss 统计
回滚;F5 正片 down 音符超时拖死后下滑不弹菜单且复活改判 Good 播
tom_lo;F5b 窗口内晚下滑(dt 超 0.5s)不弹菜单、Miss 维持、tom_lo
自由演奏;F5c 窗口过后下滑正常呼出菜单;F6 菜单 1s 去抖期(双击/下滑
不穿透、菜单语音不被掐)+ 期后双击正常确认恢复。
- **引擎回归**:gesture.js 改动 opt-in(immediateTap 默认 false 零行为
变化);6 个 playtest 全绿(escape 140 / rpg 188 / simon / space 152 /
storyline / rhythm 141)+ guide.test 122 断言全绿。
## 20. 新游戏登记:《不眠频率》(radio) 与《回声地窟》(dungeon)(new8 批次 1)
两款新 RPG 的断言清单与实现核对**住各自设计文档**(断言条目随轮次在原地维护):
- radio:[15-radio.md](15-radio.md) §测试(playtest 清单)+ 文末「实现核对」(193 断言逐条 ✅/合并/舍弃)。
要点:4 结局矩阵路径、pendingChoice 盲玩公平、C3 埋线索/C4 消费差分、rep 剧本验算、
RING 看门狗两级不同句(gd_ring1/gd_ring2)、模态菜单循环-确认-关闭不丢节点、中断复述、存档 schema。
- dungeon:[16-dungeon.md](16-dungeon.md) §测试 + 文末「实现核对」(1277 断言逐条)。
要点:固定 seed 网格复现+不变式、回声调度全扫描(echo_1..4 延迟/音量/材质/pan)、DRILL 九步、
学期零死、格挡 80%/逃跑必成挨一下/Boss 拒逃、死亡归因真话(3 死因矩阵)、元进度遗产解锁、
菜单暂停冻结、上滑 5 段状态链。
R1 起每轮的增量断言(修复回归)在各自设计文档的轮次小节追加,不在本文件重复。
## 23. new8 批次 2-4 六款新游戏断言登记(2026-09)
与 §20(radio/dungeon)同规:断言清单与实现核对**住各自设计文档**,随轮次原地维护;本文件只留指针。
- abyss《深海回音》:[17-abyss.md](17-abyss.md) §断言(剧本 A-F 六路径/氧气门三形态/sonarGate/死窗/双轨看门狗/中断复述/尾句保护首播制/链末看门狗不拆)
- detective《雨夜专案》:[18-detective.md](18-detective.md) §断言(seed 矛盾复现+矩阵不变式/指证三路径/评级账本/板导航/双轨/死窗/结案确认闸/选句记忆位/VERDICT 链锁实弹)
- cipher《暗码》:[19-cipher.md](19-cipher.md) §断言(摩尔斯固定字符逐元素/四结局矩阵/三层兜底/暴露度档位/morseGate)
- teahouse《深夜茶馆》:[20-teahouse.md](20-teahouse.md) §断言(泡茶三步时机窗/经济逐晚对账/弧线三方向/时机窗内 voice=0 分层)
- keeper《守塔人》:[21-keeper.md](21-keeper.md) §断言(时空签名教学-兑现/插叙触发回返/trust×truth 档位/4 结局)
- bridge《星环舰长》:[22-bridge.md](22-bridge.md) §断言(巡检节奏逐毫秒/危机×系统态矩阵/仲裁 7 场景/忠诚差分/评级验算/死窗)
## 21. 新游戏登记:《深海回音》(abyss)(new8 批次 2)
叙事款(radio 同骨架),断言清单与实现核对**住设计文档**(§20 先例):
- abyss:[17-abyss.md](17-abyss.md) §9(playtest 清单)。要点:四结局氧气剧本验算(lefts 公式 + 剧本 A-D 逐检查点
oxy 档位句)、第四潜氧气门三形态(双载/单载/取消)、氧气账目真实(floor(oxy/3) 档位、补给恰一次、mid-dive
floor 干涸链)、声呐双通道仲裁(echo/pipe_knock 与 voice 零重叠 + sonarGate 排队)、教学承诺兑现清单
(金属=钢板/单击=脉冲/四潜/氧气门/扣三格/敲管/补给)、看门狗双轨(乱按 96s 必被抢救 + 有进展零打扰)、
结算链 800ms 手势死窗(dungeon H1 内化)、键盘 _k 变体按 inputMode 选播、pendingChoice/p* 不可跳、
中断复述、存档 schema。**R2 增量(2026-09-13,round1 synthesis F1-F10)**:ping 即时性(gd 散句在播时单击先掐后响)、
尾句保护认实际链尾(dyn 档位句纳入)+ 签收链死窗、回波 wait=实长+静默一拍、dv4_dual/oxy_crit_deck/prog_saved1..5
新句断言、叙事尾句首播保护+复播可即掐(G5)、full 档链末看门狗 [13,30]、danger 震 1100ms、crit 震按档去重。
详见 [17-abyss.md](17-abyss.md) §12 修订记录。
## 22. 新游戏登记:《暗码》(cipher)(new8 批次 3)
叙事款(radio/abyss 同骨架 + 电文解码小局),断言清单与实现核对**住设计文档**(§21 先例):
- cipher:[19-cipher.md](19-cipher.md) §9(playtest 清单)。要点:**摩尔斯固定字符断言**(运行时 SYN 模块 `morse.js`
事件钩子,BAY/TOP/HAND/SPY 逐元素 + 时值容差 ±5ms + 三档速度 u=80/110/160;**不随 settings.speed 变**);
**三层兜底剧本各自走通**(纯耳朵剧本 A / 纯慢放剧本 F / 提示流剧本 E:T1 免费页 + 3 页逐值 book_2/1/0);
**译错归因真话**(T1 dv1_wrong 句内字母与真词一致 + 无限重选零惩罚;正片判定出口零对错语音;ep_* 与
t/picks flags 单源对应);**暴露度剧本验算**(剧本 A-D 逐 NIGHT 检查点档位句 = wrong+risk 公式,收网门=hot 档
阈值 5);四结局矩阵(expose 档 × p9);morseGate 零重叠(摩尔斯与任一 voice 区间);密码本页数账目(逐值
整句、页数 0 翻本=error 震+翻空本音零惩罚);看门狗双轨(纯浏览/重听不计进展,乱按 96s 必被抢救);
结算链 800ms 手势死窗(判定出口/NIGHT/d9/e*);键盘 _k 变体 11 对按 inputMode 选播;pendingChoice/p* 不可跳/
摩尔斯首播不可跳;中断复述(含 DECODE 态恢复链 prog_t→book 档→gd_tune2);存档 schema(summary 带
暴露档名)。
---
## 24. hunt《围猎》(联机切片;设计 [23-hunt.md](23-hunt.md),台词表 23b)
> 本作是首个联机游戏:断言分两侧——**服务器侧**(`web/server/test/` 新增 hunt-room 单测,直接 import 房间模块 + 假 WS 连接,固定 seed 复现)与**客户端侧**(`web/hunt/test/playtest.mjs`,mock 引擎 + mock transport 注入 ev/snap)。协议字段以 23 号文档 §6 为唯一契约。测试钩子可读 game 实例字段与房间实例字段;手势只经引擎回调注入。
**关键路径**(首局教学房 → 5 波 → 结算 → 排行榜,≤150 次手势):
1. 启动遮罩点按 → 音频解锁(此前零播放)→ TITLE;无存档单击 → 断言客户端发出 `join { room:"quick", teach:true, ver:1 }`。
2. **教学房**:注入 `joined`(phase:'teach',slot 0,roster 含 2 bot,seed=42)→ T0(intro_1→intro_2→tut_rule 有序)→ 单击 → T1(tut_attack + 注入 spawn 狼 N eta12)→ 先错向滑 W(断言 `act attack dir:W` → 注入 `ev miss` → atk_swish + error 震 + gd_idle 重教,怪物不受伤)→ 向 N 滑 → 断言发出 `act attack dir:N` → 注入 `ev kill` → tut_kill_ok;T2 单击 → `act callout` 发出 → 注入 bot help_ack(断言 `sfx/npc_yan_help_ack` 播放且 pan=该 bot 防区中心)→ tut_callout_ok;T3 双击 → `act skill` → 注入 `ev skill cleared=[2]` → tut_skill_cd;T4 上滑 → 状态链 4 段有序(hp_band→st_wave→team_3→kill_band)→ tut_breach→tut_done → 注入 `ev wave 1` 进 WAVE。**教学狼突入零惩罚**:注入教学波 breach → dur 不变。
3. **bot 补位**:非首局(tutDone=true)→ LOBBY(room_wait 播)→ 单击发 `act start` → 开局 roster ev 断言猎人总数 = max(3, 人类数)、bot 槽 char 齐全、bot greet 逐只间隔 ≥1.5s。
4. **5 波推进**(seed=42 服务器侧快进 tick):每波 spawn 事件数/型别/逼近时长与 23 §3.4 表逐波一致;方位分配 ∈ 各座位防区;狼击杀(滑向 → act → ev kill)断言归属 slot 与 kills 账;漏一只狼 → ev breach,dur -1,`breach` 播报 + hit 震;熊漏 → dur -2 + `breach_heavy`。
5. **终局**:注入 `ev end { win:true, dur:8, grade:"A", kills }` → 结算链有序(end_win→grade_a→kill_band_*→end_rank→end_again)→ 断言 PUT `/api/progress { game:"hunt" }` 且 `data.summary` 命中生成规则(`最佳评级A · 击杀14 · 营地余8 · 共N局`)、best 按"评级>耐久>击杀"序更新;单击 → 重新进匹配。失守路径(dur 归零):end_lose 首句、无 grade_*、无 end_rank、不写 best、runs+1。
**边界断言**:
- **断线转 bot**:关连接 30s(服务器侧快进)→ roster ev 该槽 bot=true 且 char 沿用 → 该槽开始产出 act(tick 内断言);剩余人类 ≥3 时改为槽位移除(roster 缩短)。
- **重连回槽**:断开 15s 内带 `resume` 重连 → joined 同 slot/seed/char + 紧随 snap 全量 → 客户端怪表与 snap 一致、net_back 播报、战斗续接;超 30s → err `room_gone` → net_gone → LOST。
- **旋风斩冷却**:放出后 8s 内双击 → 无 act 发出、播 threat_*(按内圈只数选档);冷却完成 → skill_ready(queue:true 不顶句);伪造 `act skill` 越冷却 → 服务器 err `skill_cd`。
- **出击冷却 2.5s**:冷却内滑 → 仅 error 震、零 act;伪造连发 → 服务器只裁决首发,其余 err `cooldown`。
- **支援呼喊 bot 补位**:呼喊后 10s 内,服务器侧断言补位 bot 的下一次 act.dir ∈ 呼喊者防区(偏置 ×2 生效),且 `help_ack` 恰播一次;呼喊节流 5s(连点只出一条 callout ev)。
- **听觉裁剪上限**:eta>6s 怪零 loop;任意时刻 loop ≤3 路且为 eta 最小 3 只(注入 5 只内圈怪断言);threat_* 选档只计 eta≤4 只数;状态链/威胁句无任何逐方位枚举(台词表结构保证)。
- **拥挤控制(R1-R8)**:第 5 波峰值剧本下断言——同刻 voice ≤1;同刻 `npc_*` ≤1 且 10s 窗 ≤2 条;旁白在播时喊话延迟 ≤2s 或丢弃;one-shot 定位音同刻 ≤2;breach/danger_low/wave 播报零丢失。
- **snap 兜底**:客户端随机丢弃 50% ev,仅凭 snap(2Hz)收敛 → 怪表与服务器真值一致(id 集合 + eta 偏差 ≤0.5s 校正)。
- **菜单不暂停(E3)**:菜单开着注入 breach → dur 照扣、菜单不收;菜单 3 项固定、单击循环/双击确认/下滑关闭。
- **学期零惩罚**:教学波 breach 不扣 dur;T1 做错 2 次自动放过不卡死。
- **结算死窗**:end 到达前后 800ms 内注入 tap → 被吞(不进 TITLE/不重开);死窗后单击正常再来一局。
- **屏蔽任意 voice 资产**:结算链/警报链照走完(看门狗兜底推进),不卡死。
- **资产齐套**:voice 双性别 60 句集合一致、key 变体 11 对 ⊆ 主集、`sfx/npc_*` 24 条双格式(assetExists 口径)。
- **opts.pan 回归**:无 pan 调用路径零 panner 节点(引擎行为不变);pan=-1/0.7/1 时 panner 值正确;老 Safari 无 createStereoPanner 静默降级。
**全局通用(§7 五条全跑,另加本作条目)**:
- 启动遮罩点按前零音频播放;遮罩手势不被游戏误收(引擎双保险)。
- **guide 三档**:full=签名+语音+震;standard 无向导语音;**off=全静且零看门狗定时器**(WAVE 30s 空闲零向导播放,内容层 loop/音效除外)。
- **震动语义**:逐条对照 23 §2 表——击杀 pickup / 挥空 error / 旋风斩 success / 突入 hit / 收到呼喊 warning / 耐久 ≤2 danger / 波次 heartbeat;手势本身震动由引擎内置承担,游戏层不重复(无双震)。
- 设置边界:speed 切换下一句生效;bgm=0 全程无 bgm 加载;voice 切换下一句用对应目录。
- 服务器不可达:TITLE 单击 → net_lost → net_gone → LOST 回大厅(明示失败,不静默死屏)。
**失败即不通过**:评级与 dur 不符(归因假话);服务器接受违规 act(冷却/方位/近战窗外命中);ev 与 snap 矛盾不收敛;bot 喊话压过/打断旁白(R1/R2 破);loop >3 路;教学狼扣耐久;失守局写入 best 排行榜。