19 · 《暗码》(cipher) — 1940 密战叙事 RPG 设计文档
给开发的实现要点摘要
- 叙事模式(声命线范式,radio/abyss 同骨架):节点链 onComplete 串行 + seqToken 打断作废 + pendingChoice 缓存;复制
web/radio/(或 web/abyss/)结构起步,状态机 6 宏状态(INTRO/RX/DECODE/RELAY/NIGHT/ENDING + MENU 覆盖层)。
- 核心增量 = 电文解码小局嵌叙事(DECODE 态):摩尔斯音由运行时程序合成模块(
morse.js,guide earcon 同先例)直接排程 oscillator——不走音频文件(有损编码在 70-160ms 短音上有 ms 级抖动,毁时值精确);事件钩子供 playtest 固定字符断言。
- 手势:全局默认映射 + 唯一豁免 E1(DECODE 空闲长按=翻密码本求提示,与引擎快进时间互斥,detective E2 同款);菜单走 00 号 §5.2 模态约定。摩尔斯三层兜底:正常译(原速+候选对照)/ 慢放(双击第 2 次 0.5×)/ 提示直译(密码本 3 页,逐值账目)。
- 暴露度 = 步进隐藏资源(radio 口碑同型):译错 +1/封(教学封 T1 恒 0)、危险抉择 +1/+2;分档整句、跨档才播、上滑可查;档位措辞逐值为真(book_1..0 / exp 四档均按实数措辞)。
- 译错归因真话:教学封 T1 译错即时归因(真词字母的摩尔斯写死在句里)+ 无限重选零惩罚;正片 T2-T4 译错不揭穿(进入剧情误读分支),真相在尾声回响兑现(ep_* 与 flags 单源对应,detective 信息单源思想)。
- 台词依据 19-cipher-voice-ids.md(139 句:双性别 134 + 平铺 NPC 5);键盘变体 11 对
_k 集中标注;结算链 800ms 手势死窗(abyss/地下城 H1 同款)。
- 章程任务 N3(research/new8/00-program.md §2):单局 15-25 分钟、9 抉择点(4 译词 3 选 + 5 叙事 2 选)、4 结局、分支局部化。断言清单住本文档 §9;13 号文档已登记指针(§22)。
1. 概述
- 一句话:1940 年江城,你是电讯处的夜班报务员,也是「北风」安在敌台内部的一双耳朵——一晚四封密电过你的手,每个词怎么译、报不报、报给谁,都由你按下。
- 题材(声音即世界):谍战的本体就是听——摩尔斯的滴答是情报本身、报务员的「手法」是 fingerprint、电台静电是世界底色。「用耳朵当武器」与纯音频载体天然同构:视觉谍战需要的文件/密写/表情,在这里全部是声音。
- 单局:一个完整夜班(一条抉择路径)19-22 分钟;四封电文共享主干(截获→解码→处置→夜结算),分歧局部化在每封内部;9 个抉择点(4 译词 + 5 叙事,全部恒在),4 结局。
- 核心循环:截获(调谐+电文摩尔斯首播)→ 解码小局(听音辨词:候选对照/慢放/提示三层兜底)→ 译文揭晓(你的认知,对错不揭穿)→ 处置抉择(报北风/压日志/呈处长/亲自交接/反喂假电)→ 夜结算(暴露度跨档播报)→ 下一封。终局 p9 用「发最后一电」把整晚收在你的电键上。
- 与 radio/abyss 的差异点(骨架同、压力源不同):radio 零压力、abyss 资源稀缺(氧气);cipher 的压力 = 隐藏的怀疑账本(暴露度)+ 认知风险(你永远不确定自己译对了没有——译错不是失败,是走另一条真实存在的剧情)。全部宽限化:无倒计时、无中途死亡、软失败只损失「情报效果」不损失玩家已有物。
2. 摩尔斯解码小局(信息设计,本作核心差异层)
2.1 电码呈现规格
电码表(标准摩尔斯;本作 4 封电文只用到 13 个字母,模块内置全 A-Z 表,断言只锁用到的):
| 字母 |
码 |
字母 |
码 |
字母 |
码 |
字母 |
码 |
| A |
·− |
H |
···· |
O |
−−− |
T |
− |
| B |
−··· |
I |
·· |
P |
·−−· |
Y |
−·−− |
| D |
−·· |
L |
·−·· |
R |
·−· |
S |
··· |
| N |
−· |
|
|
|
|
|
|
时值与音色(运行时合成,web/cipher/morse.js):
| 参数 |
值 |
说明 |
| 单位 u |
原速 80ms(dit=1u 音、dah=3u 音、字内隙 1u、字母隙 3u) |
≈15 WPM 等效;u 是常量写死,不随 settings.speed(见边界表) |
| 慢放档 |
u=160ms(0.5×),字母隙加宽至 6u |
双击第 2 次触发;三层兜底第 2 层 |
| 候选对照档 |
u=110ms,字母隙 5u |
密码本「念给你听」的质感 |
| 音色 |
电文 750Hz / 候选 620Hz,正弦 + 5ms cos 边沿,gain 0.5 |
频率差 = 「电波里的」vs「密码本上的」,防听感混淆 |
| 首尾 |
lead-in 400ms 静音,结尾 400ms 静音 |
排程器自然包含 |
| 时长例 |
BAY 原速 ≈2.6s / HAND ≈2.8s / TOP ≈2.8s;慢放 ≈2× |
单次听觉负荷远低于 40s 红线 |
| 事件钩子 |
morse.play(word,{hz,unit}) 逐元素回调 `{type:'dit' |
'dah',letter}` |
- 为什么运行时合成而非 SA3/SYN 文件:①时值精确是玩法命根(H···· vs S··· 只差一个 80ms 的 dit,ogg/m4a 有损编码在短音上有数 ms 抖动与预卷,文件方案直接否决);②三档速度 × 双频率 × 13 字母的组合用文件不可维护;③零资产缺失风险。guide earcon(14 号裁定 3)运行时合成先例。
2.2 电文与候选设计表(信息单源:真词/候选/辨析位写死)
| 封 |
电文名 |
真词(义) |
候选(义) |
共享 |
辨析位 |
密码本提示揭示 |
| T1 |
船期 |
BAY(货船) |
DAY(客车)/ RAY(巡逻艇) |
_AY |
1:B(−···)/D(−··)/R(·−·) |
第 1 字母是 B,一长三短 |
| T2 |
名单 |
TOP(黑名单) |
TAP(窃听令)/ TIP(线人费) |
T_P |
2:O(−−−)/A(·−)/I(··) |
第 2 字母是 O,三长 |
| T3 |
交接 |
HAND(今夜交接) |
SAND(明晨交接)/ LAND(地点变更) |
_AND |
1:H(····)/S(···)/L(·−··) |
第 1 字母是 H,四短 |
| T4 |
处置令 |
SPY(内线确认) |
SAY(约谈)/ SLY(内部排查) |
S_Y |
2:P(·−−·)/A(·−)/L(·−··) |
第 2 字母是 P,短两长短 |
- 候选纪律:三候选等字母数、共享其余字母、唯一辨析位;提示揭示辨析位字母 ⟹ 候选唯一(每行验算成立,playtest 断言「提示流可全对」)。
- 难度曲线:T1(B/D 差一个尾 dit,教学期有慢放+免费提示兜底)→ T2(中间字母 O/A/I 时值差异大,最易)→ T3(H/S/L:H 与 S 只差一个 80ms 尾 dit,全作最狠听辨)→ T4(P/L 需听完整字母,中高)。曲线说明:难度=听辨精度,操作面恒定(左右滑+单击+双击)。
- 电文摩尔斯(固定字符断言对象):BAY=
−··· / ·− / −·−−;TOP=− / −−− / ·−−·;HAND=···· / ·− / −· / −··;SPY=··· / ·−−· / −·−−。
2.3 解码交互流(DECODE 态内)
- 三层兜底(成本递增的梯度,全部可独立走通,P3 嘈杂/P4 疲惫的双保险):
| 层 |
手段 |
成本 |
覆盖 |
| 1 正常译 |
原速电文 + 候选对照预听匹配 |
最快 |
安静环境/耳力好 |
| 2 慢放 |
双击第 2 次 0.5×,无限次免费 |
时间 |
通勤嘈杂听不清长短音(P3);无限兜底层 |
| 3 提示直译 |
密码本 3 页,每页直译 1 封的辨析位字母 |
资源(页) |
P4 保底:提示+候选对照 ⟹ 唯一解(§2.2 验算) |
- 教学期(T1):dv1_teach/dv1_teach2 先教「双击重听→再双击慢放」「左右滑候选、单击选定」;T1 判定有即时反馈(对=success 震+dv1_right;错=dv1_wrong 即时真话归因+无限重选,零惩罚)——正片 T2-T4 判定无对错反馈,直入剧情(译错是你不知道的分支)。教学承诺「练习有答案,正片靠耳朵」在 dv1_right 说破。
2.4 密码本机制(提示额度经济)
| 项 |
规则 |
| 页数 |
初始 3 页(叙事=北风给你的三页「电码补遗」);全局不再补页 |
| 兑换 |
DECODE 空闲长按(E1 豁免)或菜单「翻密码本」项(P4 冗余入口);消耗 1 页 → 播 hint_*(「第 N 个字母,是 ○」+ 摩尔斯口述),留在浏览态 |
| 教学免费 |
T1 第 1 次翻页不扣(hint_t1:「我教你一页」)——Prime→Teach 承诺兑现 |
| 账目真实 |
状态链随时可查:book_3「还剩三页」/ book_2「还剩两页」/ book_1「只剩最后一页」/ book_0「一页都不剩了」——逐值整句,不拼接 |
| 页数用尽 |
再翻 = error 震 + sfx/paper_page(翻空本声),无语音(零静默、不轰炸) |
| 与结局关系 |
页数不进结局判定(只换准确度);纯提示流(T1 免费+3 页)可全对(§5.5 剧本 E 验算) |
2.5 译错归因真话(detective 信息单源思想)
| 场景 |
播报 |
真话依据 |
| T1 译错(教学) |
dv1_wrong「不对。听清楚:B,一长,三短。」 |
真词字母的摩尔斯写死在句里,与 §2.2 电码表一致;无限重选零惩罚 |
| 正片译错 |
不揭穿:rev_* 按你选的候选播「你的认知」(rev_top/tap/tip…) |
旁白只说你以为的事;真词唯一、由数据表单源决定 |
| 后果分支 |
你的行动按认知展开(报错船期/留错时间/呈报错令);暴露度 +1 |
「译文进了纸面,与对家底档不符」——事件表单源(§5.2) |
| 真相揭晓 |
尾声 ep_hand_no「码头的灯,白亮了一夜」/ ep_spy_no「差的那三个字母,差了一整条命」 |
ep_* 由 flags(t3==hand 等)选播,播报=存储;禁止「运气不好」类假归因 |
3. 状态机
3.1 状态列表
| 状态 |
内容 |
BGM |
guide.state |
INTRO |
开场链:夜班开场 + 一句规矩 + 今晚目标 + 处长夜令 |
bgm/radio_room |
explore |
RX |
截获:引入句 + 调谐 + 电文摩尔斯首播(auto 链) |
bgm/radio_room(摩尔斯期间 −6dB) |
explore;摩尔斯首播后由 turn cue 承担 |
DECODE |
解码小局:浏览/确认/重听/慢放/提示(§2.3) |
同上 |
choice |
RELAY |
处置叙事:rev_* 揭晓链 + 后果 + 叙事抉择 p2/p4/p6/p8 |
bgm/radio_room;RELAY(4) 起 crossfade 至 bgm/closing |
explore;抉择点=choice |
NIGHT |
夜结算:n* 过渡句 + 暴露档位跨档播报(如有),auto ≤12s |
bgm/night |
settle |
ENDING |
结局链 + 尾声回响(epilogue),结算态 |
bgm/ending |
settle |
MENU |
模态覆盖层(任意叙事态下滑呼出,暂停一切链) |
bgm/radio_room 低响度淡入 |
menu |
- 附
ASK(存档询问态,radio 同款):单击=继续上次 / 右滑=新夜班;上滑/下滑/左滑/双击=无效(error 震+gd_invalid)。
3.2 转移图(文本)
- RX 首播链与 NIGHT 链
auto:true;DECODE 浏览为武装等待;RELAY 叙事节点链末等待单击(radio 实现核对 #1 同口径)。
- 判定出口(DECODE 第 2 击确认)、NIGHT 链、d9 结果链、e* 结局链入口处盖
_settleGraceUntil = now+800ms 手势死窗(dungeon H1/abyss 同款),窗内手势一律吞掉——揭晓与结算链完整播出。
- MENU 打开时
guide.disarm() + 取消一切看门狗/自动链 + 停摩尔斯排程;关闭后按原状态复述(L5 局面复述,radio closeMenu 先例)。
3.3 每状态手势映射(6+2 全覆盖)
| 手势 |
INTRO/RX |
DECODE 浏览 |
DECODE 确认 |
RELAY |
NIGHT |
ENDING |
MENU |
| 上滑 |
帮助+状态,随后重播当前段 |
状态链(prog_t→book 档→exp 档→sys_help,状态在前),留在浏览 |
同左 |
帮助+状态,随后重播当前节点 |
帮助+状态,自动链继续 |
帮助+状态(结局名+档) |
帮助(sys_help) |
| 下滑 |
模态菜单 |
模态菜单 |
模态菜单 |
模态菜单 |
模态菜单 |
模态菜单 |
关闭菜单 |
| 左滑 |
无效 → error 震+gd_invalid |
上一候选(循环,预听);首播中=beat 轻震(摩尔斯不可跳) |
取消确认,回浏览 |
抉择=左 |
无效 → gd_invalid |
无效 → gd_invalid |
无效 → error 震 |
| 右滑 |
无效 → gd_invalid |
下一候选(循环,预听) |
取消确认,回浏览 |
抉择=右 |
无效 → gd_invalid |
无效 → gd_invalid |
无效 → error 震 |
| 单击 |
播放中=跳过本句;链末=继续 |
进确认:cf_confirm + 电文重播 |
定下判定(800ms 死窗 → 揭晓链) |
播放中=跳过本句(p* 不可跳);链末=继续 |
跳过本句(自动链) |
再来一局(新夜班) |
循环切换选项 |
| 双击 |
重听当前段 |
重听电文(原速);第 2 次=慢放 0.5×(任何其他手势重置计数) |
同左(确认态保留) |
重听当前节点台词(含抉择提示) |
重听夜结算链 |
重听结局链 |
确认执行(菜单约定覆盖重听) |
| 长按 |
引擎接管:旁白临时 1.7×(12 号 §2.2,叙事类不豁免) |
空闲=翻密码本(E1 豁免);语音在播=引擎快进 |
同左 |
引擎快进 |
引擎快进 |
引擎快进 |
引擎快进(菜单语音) |
| 长按松开 |
引擎接管:恢复 settings.speed |
同左 |
同左 |
同左 |
同左 |
同左 |
同左 |
豁免登记(必须显式,仅 1 条):
| # |
豁免 |
理由(先例) |
| E1 |
DECODE 空闲长按 = 翻密码本求提示(核心资源动词快捷入口) |
绑定条件=无语音在播(!audio.isVoicePlaying()),与长按快进(仅在播时生效)时间互斥、零冲突(detective E2 同款);摩尔斯为 sfx 域不触发快进;菜单「翻密码本」提供冗余入口(P4 容错) |
- 其余全部符合宪法默认语义:单击=确认/继续(两段确认=确认的两击)、双击=重听(重听对象=电文)、左右滑=选择/移动、上滑=状态、下滑=菜单(00 号 §5.2 模态约定);菜单=单击循环+双击确认。
- 继承 radio G5 跳过公平契约原文:首播必完整(摩尔斯首播不可跳、p* 不可跳、链末关键句保护、ASK 恢复首句锁)、复播可即掐(锁不随复播重新武装、链中段句可跳、复播滑动照常预缓存)。
- 抉择 prompt(p2..p9)播放中单击不可跳(PROMPT_RE 门)+ beat 轻震(G4);左右滑缓存
pendingChoice 播完即生效(radio W2 契约)。
- 无效手势零静默:所有「无效」格 error 震 + gd_invalid(onceKey 同局限次,F1.4 idle-only)。
- 首播保护窗:电文摩尔斯首播发生在 RX 链尾、DECODE 入口前(§3.2),期间一切玩法手势(左右滑/单击/双击)= beat 轻震(G4),不判无效、不惩罚——摩尔斯走 sfx 域本无跳句通道,「不可跳」由构造保证;首播完 400ms 内 guide.turn + dv*_ask 落地,浏览武装。
3.4 摩尔斯/语音双通道仲裁(abyss 声呐双通道 R1-R5 同型)
- 通道定义:摩尔斯通道 = morse.js 的 osc 排程(电文+候选)+ sfx 层(静电/电键);语音通道 = voice 层(你+北风+处长)。BGM 第三层背景(voice 播时引擎 duck)。
- R1 摩尔斯不叠语音:摩尔斯排程只在
!audio.isVoicePlaying() 时起振;在播则挂队列表、voice onComplete/句间轮询补发(abyss sonarGate 同款)。候选预听链 = 候选摩尔斯 → 静默一拍(≥500ms)→ cand_* 词义句(给耳朵留对照时间)。
- R2 电文主导段(首播/重听/慢放):前景=摩尔斯,BGM dip;voice 只在摩尔斯结束后接播(dv*_ask 固定在首播后)。
- R3 BGM 退位:摩尔斯排程期间游戏层把 BGM 降 −6dB(abyss 远程脉冲垫先例),不消失(A2 无静默死局)。
- R4 危机拍优先:T4 揭晓 danger 拍(step_halt 前置 2s 渐强 + danger 签名 + danger 震);当前 voice 句播完后危机链才插续(radio C5/abyss D2 同款)。
- R5 摩尔斯可重听:DECODE 双击=重听电文(P1 关键线索可重听;第 2 次=慢放是本作对 R5 的加强)。
- 声流账:任意时刻 ≤2 条前景流(voice 串行 1 + 摩尔斯/信息音 1),BGM/amb 为背景层——ASA ≤2 约束 ✓。
引擎能力边界(对照 docs/web-engine-api.md):
| 能力 |
引擎现状 |
方案 |
| 摩尔斯精确时值 |
sfx 走文件(有损编码 ms 抖动) |
运行时 osc 模块(§2.1;guide earcon 先例),三档速度一个参数 |
| morse 与 voice 互让 |
❌ sfx 总线独立无 duck |
游戏层 morseGate 空闲门(R1) |
| BGM 手动 dip |
❌ 引擎只对 voice duck |
游戏层 gain:摩尔斯期间 −6dB(R3) |
| voice 运行时滤波 |
❌ |
不使用(detective 先例:区分度靠 speaker+instruct+语境;处长=当面训话不需滤波) |
| sfx 循环 |
❌ 即发即弃 |
游戏层 buffer.loop=true(amb_room/static_bed,radio _ringSrc 先例) |
| 变速不变调 |
✅ SoundTouch(仅 voice) |
摩尔斯不受 settings.speed/长按快进影响(u 恒定)——边界登记:P1 2.2× 档语速下电文仍原速,慢放兜底;列入 live 真人耳测项 |
4. 抉择树
4.1 全局骨架(四封电文共享主干,分歧局部化)
分支纪律:每封电文内部分支、夜结算时收敛;跨电文只传标量(expose、hints、4 个译文 flag、4 个抉择 flag),不生成组合节点。最坏路径与最好路径节点数同型。
4.2 分封结构(◆=抉择点,〔〕=条件差分)
4.3 分支局部化说明
- 跨电文状态全部是标量:
expose(int)、hints(int 0-3)、译文 flag t1..t4(每封所选候选 id;T1 恒真词)、抉择 flag p2..p9(左/右)。无任何「电文 i × 电文 j」组合节点。
- 条件差分全部是节点内选播(radio w1_say/w1_say2 先例):p4/p8/p9 的 known/blind 双提示(由 t2/t4 决定)、r3b_e_ok/no(由 t3 决定)、d9_send_e/caught_e(由 expose 档决定)、ep_* 8 句(由 4 组 flag 决定)。树形不变。
- 树规模:139 句台词、约 75 个节点;任一路径恒走 9 个抉择点(4 译词 + p2/p4/p6/p8/p9)——比 radio/abyss 更规整(无跳点路径),操作面完全恒定(P4)。
4.4 四结局达成条件
| 结局 |
条件 |
主题 |
开环钩子 |
| e1 最后一电 |
p9 前 expose ≤4 且 p9=左 |
警报发出、北风撤尽,你随挑水的队伍出城 |
「新的密码本,在城外渡口等我」 |
| e2 值完这个班 |
p9 前 expose ≤4 且 p9=右 |
平安交班,一切照旧——但北风的呼叫没人接 |
「下一次呼叫,你接不接?」 |
| e3 孤灯 |
p9 前 expose ≥5 且 p9=左 |
发报被测向,你拍了三遍警报,坐等门开;码头撤空 |
「审讯室的灯,也很亮」 |
| e4 长夜 |
p9 前 expose ≥5 且 p9=右 |
两点五十九分,脚步停在门口;最后一页密码进了炉子 |
「耳机里还有一封译不完的电文」 |
- 处置令的烈度随暴露档缩放(fiction 自洽):低暴露=处长没有足够把握(约谈/排查);高暴露=今夜三时收网。
- 尾声回响(P2):ep_lead 后逐封点名——药品(接住/白过江)、名单(少了一个人/多了红圈)、交接(上船/白亮一夜)、处置令(译对/差三个字母)——玩家每一封的译与错都被点名。
5. 数值设计
5.1 变量
| 变量 |
类型 |
初值 |
说明 |
expose(暴露度) |
int |
0 |
步进隐藏资源:译错/危险抉择累积,只涨不跌;档位句播报(§5.3) |
hints(密码本余页) |
int |
3 |
翻一页 −1;T1 首次免费(不扣);全局不补 |
t1..t4(译文) |
str |
null |
各封所选候选 id;T1 教学期恒收敛真词;t2/t3/t4 记玩家认知 |
p2/p4/p6/p8/p9 |
'L'/'R' |
null |
叙事抉择;派生 med_ok/mateListed/handOk/feed 等 flag |
endings{} / runs |
map/int |
— |
结局收集与重玩计数(存档展示用) |
5.2 暴露度累积事件表(单源,账目可验算)
| 事件 |
条件 |
Δexpose |
叙事依据(真话) |
| T1 译错 |
教学期无限重选,恒收敛 |
0 |
学习期零惩罚(A5) |
| T2/T3/T4 译错 |
选非真词(无论后续左右) |
+1/封 |
你的译文进了纸面(值机日志/呈报/交接条),与对家底档不符 |
| p2 右·压日志 |
T1 |
+1 |
值机日志少一封,晨检对不上号 |
| p4 左·暗处理 |
T2 |
+1 |
卷宗缺页/抽屉藏报,暗手的痕迹 |
| p6 左·亲自去 |
T3 |
+2 |
值班室空岗一刻钟,日志停了一行 |
| p8 左·反喂 |
T4 |
+2 |
拍假电的机器记录抹不掉(哪怕手法伪装了) |
| p9 左·发报 |
终局 |
+2(结局判定用 p9 前值) |
开机信号进了值机室的登记 |
- 上限:3(译错)+1+1+2+2 = 9(p9 前);下限 0。全对全保守 = 0(calm 档),符合「一晚干净值机」。
- 每次事件不播数字(隐藏资源);危机感由档位句+氛围音承载;状态链随时可查档位(radio 口碑同型)。
5.3 暴露度档位表(措辞逐值为真)
| 档 |
expose |
整句 |
真实性核验 |
| calm 平安 |
0 |
「这一晚,还没人看你第二眼。」 |
0 事件 ✓ |
| low 疑云 |
1-2 |
「处长端着茶,多看了你一眼。」 |
1-2 个纸面破绽=被注意 ✓ |
| mid 被盯 |
3-4 |
「走廊里的脚步声,慢了下来。」 |
3-4 个破绽=例行留意 ✓ |
| hot 危局 |
≥5 |
「门外,好像有人换了岗。」 |
≥5=行动级怀疑(与 p9 收网门 ≥5 一致)✓ |
- 跨档才播(挂 NIGHT 链尾);上滑状态链随时可查;hot 档各播报位附 warning 震(abyss oxy_crit/G2 同款)。
- p9 收网门 = hot 档阈值 5:档位句说的就是结局判定用的(radio rep_low/abyss floor(oxy/3) 教训内化——措辞与数值同一个源)。
5.4 密码本账(逐值整句)
| 余页 |
整句 |
| 3 |
「密码本,还剩三页。」 |
| 2 |
「密码本,还剩两页。」 |
| 1 |
「密码本,只剩最后一页。」 |
| 0 |
「密码本,一页都不剩了。」 |
5.5 暴露度与四结局验算(设计期穷举,playtest 剧本引用)
设 wrong = T2/T3/T4 译错封数(0-3),risk = 危险抉择分(p2右1 + p4左1 + p6左2 + p8左2,0-6):
- p9 前 expose = wrong + risk ∈ [0, 9];结局门:≤4 → e1/e2(p9 左/右);≥5 → e3/e4。
- 剧本 A(全对全右,p9 左):wrong=0,risk=0 → expose=0(calm)→ p9_known 左 → d9_send_e → e1;ep 全 ok(med_ok/list_no/hand_ok/spy_ok——p4 右呈报=名单进卷宗,ep_list_no 是呈报的真实代价)。
- 剧本 B(同 A,p9 右):expose=0 → e2(d9_sleep/d9_sleepe)。
- 剧本 C(全错全左,p9 左):wrong=3,risk=1+2+2=5 → expose=8(hot)→ p9_blind 左 → d9_caught_e(danger 拍)→ e3;逐检查点:NIGHT(1) 后 0(p2 左不加分)→ calm;NIGHT(2) 后 2(wrong T2=1 + p4 左=1)→ low;NIGHT(3) 后 4(+wrong T3 +p6 左 2)→ mid;签收前 8(+wrong T4 +p8 左 2)→ hot。跨档播报 3 次。
- 剧本 D(同 C,p9 右):expose=8 → e4。
- 剧本 E(提示流 P4):T1 免费提示(hints 3 不动)+ T2/T3/T4 各 1 页(3→2→1→0,book_2/1/0 逐值播出)→ 提示揭示辨析位 ⟹ 候选唯一 → 全对;全右 → expose=0 → e1/e2 任选。纯提示流可通关 ✓。
- 剧本 F(慢放流 P3):T2-T4 每封双击×2 慢放后译对,零提示 → 全对;expose=0。纯慢放可通关 ✓。
- 边界带验算:wrong=2 + risk=2(p2右+p4左)= 4 → 仍 e1/e2(宽容:两处失误不毁局,P4);wrong=1 + risk=4 = 5 → e3/e4(风险路径必热)。
6. 音频三层映射
6.1 BGM(状态→曲目,Mureka instrumental,4 首 ≈ $0.12;共性后缀 10 号 §8 照 radio 追加)
| 状态 |
曲目 |
切换 |
Mureka prompt 草稿(英文,seamless loop) |
| INTRO/RX/DECODE/RELAY/MENU |
bgm/radio_room |
开局淡入 800ms;MENU 低响度淡入 500ms;摩尔斯期间 −6dB(R3) |
"1940s late night wireless station room, warm tube radio hum, distant muffled swing jazz through a wall, rain on window, clock tick, smoky and quiet, no vocals, seamless loop, 60-90 seconds" |
| RELAY(4) 起(T4 高潮至签收) |
bgm/closing |
crossfade 800ms 进 |
"Tense noir waltz for a spy's last night, muted brushed drums, low strings, subtle telegraph tick rhythm, restrained dread, no vocals, seamless loop, 60-90 seconds" |
| NIGHT |
bgm/night |
crossfade 600ms 进;进下一 RX 淡回 600ms |
"Quiet night interlude, sparse felt piano over warm vinyl static and soft rain, lonely but safe, no drums, no vocals, seamless loop, 60-90 seconds" |
| ENDING |
bgm/ending |
d9 结果链播完后淡入 1500ms |
"Dawn after a long night of rain, warm strings and soft piano, exhausted hope, quiet resolution, no vocals, seamless loop, 60-90 seconds" |
bgm=0 时全部静默(引擎约定);menu 用同曲低响度(省 1 首,值班室同场景同构)。
6.2 SFX 清单(SA3=Stable Audio 3 / SYN=程序合成;one-shot 真峰值 ≤-3dBFS;amb 循环由游戏层 buffer.loop 实现)
| id |
用途 |
来源 |
prompt(英文)/ 合成参数 |
sfx/tune_seek |
调谐找频(每封 RX 起) |
SA3 |
"Hand turning a vintage radio tuning dial, static sweeps, faint morse ghost, 3 seconds" |
sfx/static_bed |
电台静电底噪 loop(RX/DECODE) |
SA3 |
"Shortwave radio static bed, soft crackle and hum, seamless loop" |
sfx/amb_room |
值班室 amb loop(挂钟+雨+暖炉) |
SA3 |
"1940s office night ambience, wall clock tick, rain on window, faint stove hum, seamless loop" |
sfx/paper_page |
密码本翻页(提示兑换/开局发本/页数用尽) |
SA3 |
"Thin paper page turn of a small codebook, dry, close" |
sfx/key_send |
你的电键拍发(p8 左反喂 / p9 左发报) |
SA3 |
"Vintage brass telegraph key sending morse, spring clatter and clicks, 4 seconds" |
sfx/pen_scratch |
处长记事笔(试探戏/呈报) |
SA3 |
"Fountain pen scratching on paper, short strokes, 2 seconds" |
sfx/tea_cup |
茶杯落桌(处长场标记音) |
SA3 |
"Tea cup set down on wooden desk, porcelain clink, soft" |
sfx/step_halt |
门外脚步停住(T4 danger 拍 / hot 档) |
SA3 |
"Footsteps in corridor stopping outside a door, heavy boots, tense, 4 seconds" |
sfx/lock_click |
门锁/枪机(e3/e4 链) |
SA3 |
"Door lock slowly turning, metal click, ominous, 2 seconds" |
sfx/dawn_bell |
黎明远钟(e1/e2 链) |
SA3 |
"Distant morning bell over light rain, calm after a long night, 4 seconds" |
sfx/ui_confirm / ui_menu |
菜单/确认(程序合成兜底) |
SYN |
同全局先例 |
| (摩尔斯) |
电文/候选/重听/慢放全部音 |
SYN 运行时模块 |
§2.1 时值表;零文件资产 |
- 预警窗纪律:T4 danger 拍 step_halt 前置 2s 渐强(L2),danger 签名与音效同窗(radio 刹车/abyss 滑坡先例);e3 链首 danger 签名一次。
- 承诺绑定:rx4_in 教「快手七的手法你听过」后,p9 左 d9_send 与 p8 左 r4a_feed 必播 key_send(§7.5 清单+断言)。
6.3 Voice 划分(详见 19-cipher-voice-ids.md)
| 组 |
声部 |
落位 |
数量 |
| 报务员(你)OP |
双性别(female=Serena / male=Uncle_Fu + OP instruct 常量) |
voice/female|male/ |
20 句 |
| 北风电台(上线联络+系统/向导)WIND |
双性别(female=Vivian / male=Dylan + WIND instruct 常量) |
voice/female|male/ |
114 句 |
| 处长 NPC |
平铺单音色(Eric),不做双性别 |
voice/ 根(平铺回退命中) |
5 句 |
- 人物账:有台词人物 = 你 + 北风(上线联络人,向导人设 L4,radio 导播同型)+ 处长(明线上级)——上级/联络人 ≤2 约束满足;另有 1 个无台词角色「快手七」(对家报务手,存在=电波里的手法音,abyss 小郑先例)。
- 合计 139 句(≤150 预算 ✓,含
_k 键盘变体 11 对);音频文件 = 134×2 + 5 = 273 条(×2 格式 = 546 文件)。
7. 向导层接入
7.1 状态签名 earcon / turn cue
| 时机 |
向导动作 |
说明 |
| INTRO 进入 |
guide.state('explore') |
叙事态签名 |
| DECODE 进入(首播后) |
guide.state('choice') + guide.turn({haptic:true}) |
摩尔斯首播完 → turn 签名+confirm 震=「轮到你选词」;dv*_ask 随后落地 |
| 每个叙事抉择 p* 起播 |
guide.state('choice') |
选项句本身即 turn cue(W2 契约零插播) |
| NIGHT 进入 |
guide.state('settle') |
夜结算签名 |
| ENDING 进入 |
guide.state('settle') |
同上 |
| MENU 打开 |
guide.state('menu') |
菜单签名 |
| T4 揭晓 danger 拍 / e3 链首 |
guide.state('danger') |
全游戏仅两处(step_halt 前置 2s 同窗 + danger 震) |
| 无效手势 |
guide.error({voice:'gd_invalid', onceKey}) |
error 震 + full 档语音,idle-only(F1.4) |
- earcon 词表:只用全项目统一 8 音中的 7 个(menu/explore/choice/settle/danger/turn/nudge),零新增;battle 不用。
7.2 看门狗双轨(radio F1 + dungeon E0-1 教训:乱按也要被抢救)
无操作轨(guide watchdog,任何手势复位;两级不同句、用尽即停、永不惩罚):
| 等待点 |
full 档 |
standard 档 |
级别内容 |
| DECODE 浏览无操作 |
[10, 25] |
[10, 25](onEscalate 游戏层补播) |
① gd_tune1「电文在等。左右滑,听候选词。」② gd_tune2「双击,把电文再听一遍。再双击,会放慢。」(必须不同句) |
| INTRO/RELAY 链末等待 |
[25, 50] |
[13, 30] |
① gd_continue ② gd_again(storyline F1.1 同款) |
| 抉择点 p* 播完无操作 |
[25, 50] |
[25, 50] |
重播当前 p* 提示句(13 号 §16 先例;空点单击=重挂计时) |
| ENDING 结算等待 |
[25, 50] |
[13, 30] |
gd_continue / gd_again |
无进展轨(游戏层计时,仅挂 DECODE 浏览一个可饿死点):
| 项 |
规则 |
| 进展定义 |
译词判定落定 / 叙事抉择结算 / 节点推进 / 翻密码本。无效手势与纯浏览(切候选/重听)不计进展——乱滑 96s 也必被抢救 |
| 阈值 |
60s → gd_prog1「光切词没有用。双击,先听电文。」;120s → gd_prog2「别急。停下来,把电文听完整。」;用尽即停(每封一轮) |
| 有真实进展 |
全程零 prog 播出(不误伤) |
| 双轨去重 |
两轨短句内容同级交叉登记;同一等待点先播过 gd_tune* 则无进展轨跳过同义级 |
- 向导插播一律
queue:true,绝不顶掉在播对白;error/watchdog 类语音 idle-only(在播则跳过且过期丢弃,F1.4)。
- 单句语音看门狗(资产缺失兜底):30s 超时且
isVoicePlaying()===false 才自动续链,长句续约不掐(radio N1 先例照抄)。
7.3 键盘变体机制(PC 键盘玩家)
- 运行时按
gesture.inputMode()(settings.input auto/touch/key)选 _k 变体资产:key → voice/<gender>/<id>_k.*,touch → 无后缀版;auto 跟随最近使用通道。_k 缺失回退无后缀版(check_all_assets 校验配对)。
- 变体清单(11 对,集中分组见 voice-ids §G0.a + M1):gd_brief / gd_continue / gd_again / gd_tune1 / gd_tune2 / sys_help / sys_menu / sys_skip / sys_continue_ask / dv1_teach2(首个候选导航绑定)/ p2(首个叙事抉择绑定)。
- 抉择提示 p4..p9 措辞统一「向左滑/向右滑」;键盘玩家由 p2_k 与 sys_help_k 完成首次绑定,后续语义不变。启动遮罩文案引擎自理,游戏零改动。
7.4 继承 radio/abyss 三轮验证机制(照抄不重设计)
| 机制 |
来源 |
落点 |
| 帮助链去重(同等待点第 2 次上滑只震+nudge) |
radio G1 |
_helpSeen 按等待点键控 |
| 状态链顺序「状态在前、帮助在后」 |
radio G6 |
prog_t → book 档 → exp 档 → sys_help |
| 空点确认轻震(不可跳上单击补 beat [8]) |
radio G4 |
p*/摩尔斯首播/链末句各 tap 屏蔽分支 |
| exp_hot 播报位附 warning 震 |
radio G2 / abyss |
全部 hot 出口(含上滑复听) |
| 菜单报名游戏侧排队零截断 |
radio 实现修复 #3 |
_menuQueue 排水 |
stop() 先 seqToken++ 作废在途链 + 停摩尔斯排程 |
radio 实现修复 #6 |
同款(摩尔斯句柄一并 stop) |
| 新局清 choiceArmed/pendingChoice/双击慢放计数 |
radio 实现修复 #7 |
newNight() |
| 长按误报无效(longpress 全状态合法) |
radio 实现修复 #2 |
仅 left/right(ASK 另含 up/down/doubletap)报无效 |
7.5 教学承诺清单(dungeon「铁器=楼梯」教训:每句承诺必须真实存在且可感知)
| 教学句 |
承诺 |
兑现点(断言锁定) |
| dv1_teach「先双击,把它重新听一遍」 |
双击=重听电文 |
DECODE 全程恒可用(原速) |
| gd_tune2/dv1_teach「再双击,会放慢」 |
第 2 次双击=慢放 0.5× |
慢放计数器任何封恒在;时值断言 u=160 |
| dv1_teach2「左右滑,听候选词。单击,选定一个」 |
候选预览/两段确认 |
全部 DECODE 恒同语义(含确认态取消) |
| hint_t1「我教你一页:第一个字母,是 B」 |
T1 提示免费 + 提示给辨析位字母 |
T1 翻页不扣;hint_* 与 §2.2 辨析位一致 |
| b_rule「规矩就一条:听不清,就再听一遍」 |
重听/慢放无限免费 |
全局无重听惩罚;慢放不限次 |
| b_goal「今晚频道里有四封密电」 |
恒 4 封 |
剧本 A 恰 4 封走完(断言) |
| b_chief「四封电文,一封都不许漏」 |
同上(明线口径) |
同一计数 |
| rx4_in「快手七的手法你听过」→r4a_feed「借快手七的手法」 |
提到发报必闻电键声 |
p8 左/p9 左必播 key_send(零漏播断言) |
| dv1_right「练习有答案」(正片无对错反馈) |
教学期即时反馈、正片不揭穿 |
T1 判定出口有反馈句;T2-T4 判定出口零对错语音(断言) |
8. 存档设计
8.1 进度 data 结构(PUT /api/progress {game:'cipher'})
- 写入时机:每封 RX 进入、译词判定落定后、每个抉择结算后、NIGHT 进入、ENDING 进入、菜单「保存并回大厅」。
- 断点续玩:读档 → sys_continue_ask(_k)(单击=继续上次 / 右滑=新夜班;两者 runs 均 +1,统一口径修 radio 遗留);继续 = 恢复 phase+node+全部数值并局面复述:RELAY 恢复=重播当前节点链;DECODE 恢复=prog_t → book 档 → gd_tune2 → 重挂浏览(自动预听当前候选,电文可双击重听)——一句话 ≤5s 回到可玩(L5);恢复首句受 F4 跳句锁(radio G5 例外条款)。
- summary 格式:进行中
第N封·<电文名> · 暴露:<档名:平安/疑云/被盯/危局> · 结局X/4;已收台 已收台·<结局名> · 结局X/4(大厅卡片直接显示,人话)。
9. playtest 断言清单(登记 13 号 §22 指针;settings.set({guide:'off'}) 纯玩法验证,向导行为住 guide.test)
关键路径(剧本 A:全对全右+p9 左 → e1,≤60 次手势):
- 遮罩点按 → INTRO 链(b_open 起,voice 层有播放记录)→ rx1_in → tune_seek → 摩尔斯固定字符断言:事件序列 == BAY 编码(
dah,dit,dit,dit / dit,dah / dit,dah,dah,dah),750Hz,u=80±5ms,BGM 同时段 −6dB(R3)→ dv1_teach → dv1_teach2 → dv1_ask → choiceArmed。
- DECODE 浏览:右滑 ×3 循环切换,每次预听 = 候选摩尔斯(620Hz,u=110,与 voice 零重叠——morseGate 断言)→ cand_* 词义句;双击 → 电文原速重播;再双击 → 慢放(u=160,字母隙 6u,750Hz);单击 → cf_confirm + 电文重播 → 单击 → 判定出口 800ms 死窗内注入在途 tap 被吞。
- T1 译对:dv1_right(success 震)→ RELAY:p2 左(pendingChoice 播完生效)→ r1a_send/r1a_e → n1 → NIGHT(expose=0 calm 档,零跨档播报)→ RX(2)。
- T2:摩尔斯==TOP 断言;译对 → rev_top → p4_known 播出(t2=='top')→ 右 → r2b_act → m2_chief → r2b_e → n2。
- T3:摩尔斯==HAND;译对 → rev_hand → p6 右 → r3b_e_ok(t3=='hand')→ n3。
- T4:摩尔斯==SPY;译对 → rev_spy(danger 拍断言:step_halt 前置 2s 渐强 + danger 签名 + danger 震)→ m4_chief_a/b → p8_known → 右 → r4b_act → m4_chief_c → r4b_e。
- 签收:g9_in → g9_knot → p9_known 左 → d9_send + key_send → pre=0 ≤4 → d9_send_e → ENDING(e1):e1_a/b + ep_lead + ep_med_ok/ep_list_no/ep_hand_ok/ep_spy_ok → 结算单击 → 新夜班回 INTRO(runs+1)。
边界断言:
- 四结局可达(含暴露度逐点验算):剧本 B(同 A,p9 右)→ e2;剧本 C(T2/T3/T4 全译错 + p4/p6/p8 全左):NIGHT(1) 后 expose=0(calm)/NIGHT(2) 后 2(low,跨档播 exp_low)/NIGHT(3) 后 4(mid)/签收前 8(hot,exp_hot+warning 震)→ p9_blind 左 → d9_caught_e → e3;剧本 D(同 C,p9 右)→ e4(lock_click 链)。各检查点档位句与 §5.3 区间一致。
- 三层兜底各自可走通:剧本 E(提示流)——T1 翻页免费(hints 仍 3),T2/T3/T4 各翻 1 页(book_2/1/0 逐值播出,逐页 −1 断言),按提示选定全对 → e1;第 4 封后页数 0 再长按 → error 震 + paper_page,无语音、零惩罚;剧本 F(慢放流)——每封双击×2 慢放后译对,零提示,全对(慢放不限次断言)。
- 摩尔斯正确性:四封电文事件序列逐元素 == §2.2 表(BAY/TOP/HAND/SPY);候选预听 == 所选候选编码;慢放时值 = 原速 2×(容差 ±5ms);settings.speed=2.2 会话下 u 仍 80ms(速度边界断言)。
- 译错归因真话:T1 错选 DAY/RAY → dv1_wrong 播出且句内字母/码与真词 B 一致 → 无限重选直至对(expose 零变化);剧本 C/D 的 ep_spy_no/ep_hand_no 与 t3/t4 flags 一致;正片判定出口零对错语音(教学承诺)。
- morseGate:全剧本转写断言——摩尔斯起振时刻与任一 voice 播放区间零重叠(排队语义:晚于在播句结束);候选词义句在候选摩尔斯结束后 ≥500ms 接播。
- 看门狗双轨:DECODE 快进 10s→gd_tune1、25s→gd_tune2(两级 id ≠,绝不逐字重播;两级后仅静电底噪);乱按 96s(每 2s 注入一次切候选滑动+双击重听):无操作轨零播出(被手势复位)+ 无进展轨 60s→gd_prog1、120s→gd_prog2;有真实进展(译词落定推进)全程零 prog 播出;RELAY 链末 25s/50s → gd_continue/gd_again;p* 播完 25s/50s 重播 p* 两次后静默;
guide=off 全程零定时器零向导事件。
- 键盘变体:settings.input='key' 会话播出 gd_brief_k/sys_help_k/gd_tune1_k/dv1_teach2_k/p2_k 且对应无后缀版零播出;'touch' 反之;'auto':keydown 后下一句用 _k。
- 中断复述:杀进程重进(存档 phase=DECODE, tel=3, hints=1)→ sys_continue_ask → 单击 → 恢复链 prog_t3 → book_1 → gd_tune2 → 浏览重挂 + 当前候选自动预听(电文双击可重听);恢复首句不可跳,第二句起可跳;右滑=新夜班(runs +1 口径同结算重开)。
- pendingChoice:p* 播放中左右滑 → 播完立即生效(不丢、不重复、连滑取最后一次)。
- p 不可跳*:p* 播放中单击 → 不跳句(PROMPT_RE 门)+ beat 轻震(G4)。
- idle-only:向导 gd_* 在对白在播时跳过且不占 onceKey(F1.4);queue 句排在当前句后零截断。
- 菜单:下滑开菜单 → 上滑帮助 → 双击「回到电波」→ phase/node 不变、原状态复述;单击循环顺序 = [回到电波, 翻密码本, 重新开始今晚, 保存并回大厅];菜单「翻密码本」确认 = 长按同效(回 DECODE 执行提示流程);确认回大厅 → sys_menu_lobby 播出且 PUT/localStorage 有最新 data。
- 资产缺失:屏蔽任意 voice 资产 → 30s 看门狗自动续链到结局不卡死;摩尔斯为运行时合成,屏蔽 sfx/bgm 全部不影响电文可听(模块零依赖断言)。
- 数字规范:prog_/book_/exp_* 全部整句字面量,静态审计无运行时拼接碎片。
失败即不通过:任何等待 >5s 无声(静默死局);无效手势零反馈;摩尔斯字符序列/时值与 §2.2 表不符;摩尔斯与语音重叠;结局计数与 §4.4 不符;档位句与 expose 实值不符;归因假话(dv1_wrong 字母错、ep_* 与 flags 不符)。
10. 节奏曲线(每封电文目标时长)
| 段 |
内容 |
目标时长 |
设计目标 |
| 开场 |
夜班开场 + 一句规矩 + 处长夜令 |
1-1.5 min |
首输入 <60s(INTRO 链 ~25s 后第一封电文首播,浏览滑动即首输入 ~t+45s);规矩一句讲完(P4) |
| T1 船期 |
教学封:两层重听教学 + 免费提示示范 + p2 |
3.5-4 min |
首个正反馈 ≤3min(译对 dv1_right ≈ t+2min);译错即时归因+无限重选零惩罚 |
| T2 名单 |
known/blind 差分首现 |
3-3.5 min |
「你不知道自己译没译对」的第一次心跳;呼吸口(听辨最易) |
| T3 交接 |
最狠听辨(H vs S 差一个 dit) |
3.5-4 min |
慢放价值兑现段(P3 嘈杂场景实测点);NIGHT(3) 档位句把压力可视化 |
| T4 处置令 |
高潮:danger 拍 + 处长试探 + 反喂 |
4-4.5 min |
紧张峰值但无倒计时(P4);bgm/closing 交叉淡入 |
| 签收+结局 |
心结 p9 + 发最后一电 + ep 点名 |
2.5-3 min |
整晚的「听」在你自己的电键上闭环(P2 回响);开环钩子拉下一局 |
- 合计 ≈ 19-22 min(15-25 达标);每 30-60s 一个反馈颗粒(候选预听/摩尔斯/揭晓句/结果句/档位句),无沉默尴尬期(P3)。
- 难度曲线 = 听辨精度(教学 B/D → 最易 O/A/I → 最狠 H/S → 中高 P/L)+ 认知重量(练手 → 名单有同伴 → 时间就是命 → 处置令是你),操作复杂度恒定(左右滑+单击+双击,永远如此)——P4「规则一遍听懂」由恒定操作面保证。
11. 自检清单(策划交付自验;☐ = 待开发/测试轮填)
| # |
硬约束/教训 |
落地 |
✓ |
| 1 |
FTUE 首输入 <60s |
INTRO 链 ~25s 后第一封首播,~t+45s 首次滑动(§10) |
☑ |
| 2 |
FTUE 首个正反馈 ≤3min |
译对 dv1_right ≈ t+2min(§10 T1) |
☑ |
| 3 |
学习期零惩罚 |
T1 译错无限重选零资源;DECODE 无超时惩罚;密码本 T1 免费 |
☑ |
| 4 |
失败三问归因+归因真话律 |
dv1_wrong 字母真话;正片不揭穿+ep_* 单源对应;§2.5 无假归因 |
☑ |
| 5 |
资源账目真实(radio rep_low 教训) |
book_1..0 逐值整句;exp 四档措辞逐值为真;档位阈值=收网门(§5.3/5.4) |
☑ |
| 6 |
手势宪法 6 手势默认语义,豁免显式登记 |
§3.3 全覆盖;唯一豁免 E1(长按=密码本,时间互斥 detective E2 同款);菜单 §5.2 模态 |
☑ |
| 7 |
长按显式登记 |
E1 在案(空闲=提示/在播=引擎快进,互斥);其余长按=快进不豁免 |
☑ |
| 8 |
向导:签名/turn cue/看门狗两级不同句 |
§7.1/7.2;gd_tune1≠gd_tune2;gd_continue→gd_again |
☑ |
| 9 |
看门狗双轨(dungeon E0-1/radio F1 教训) |
无操作轨+无进展轨;纯浏览不计进展,乱按 96s 必被抢救;有进展零打扰 |
☑ |
| 10 |
插播 queue 不顶对白;纠错 idle-only 过期丢弃 |
§7.2(F1.4 契约) |
☑ |
| 11 |
死亡/失败结算链完整(dungeon H1 教训) |
判定出口/NIGHT/d9/e* 链 800ms 手势死窗;seqToken+停摩尔斯(§3.2/7.4) |
☑ |
| 12 |
教学承诺兑现(dungeon「铁器=楼梯」教训) |
§7.5 九条承诺清单逐条绑兑现点+断言 |
☑ |
| 13 |
单次播报 ≤3 选项 |
译词恒 3 候选逐项预听(≤3 ✓);叙事抉择恒 2;菜单 4 项循环 |
☑ |
| 14 |
并发声流 ≤2 + 双通道仲裁 |
voice 串行+摩尔斯互斥(R1-R5,§3.4);断言零重叠 |
☑ |
| 15 |
earcon ≤7、统一词表、语义靠语音 |
只用统一 8 音中 7 个(battle 不用),零新增 |
☑ |
| 16 |
台词一句一文件 ≤40 字、数字分档整句、无运行时拼接 |
voice-ids 全表 ≤30 字(最长 p8_known);prog/book/exp 分档整句;句内数字汉字写死 |
☑ |
| 17 |
多音字规避/同 instruct 常量/无语速词 |
voice-ids 头部+文末自查(长/处/圈/卷/塞/着 试听项) |
☑ |
| 18 |
PC 键盘变体(提示句集中+标注) |
11 对 _k 集中分组(voice-ids §G0.a+M1);inputMode() 运行时选择 |
☑ |
| 19 |
P1:可打断/重听(含电文)/status key/不当白痴 |
跳句+双击(电文重听+慢放 R5)+上滑状态链+成功零补救教学 |
☑ |
| 20 |
P2:3 分钟见效/结局回响 |
~2min 首个「世界因你而动」(药船接应);ep 逐封点名+真词差分 |
☑ |
| 21 |
P3:3 分钟颗粒/中断复述/单手/嘈杂 |
一封=3-4min 完整段落+边界存档;重进一句话复述(含 DECODE 态);慢放无限=嘈杂兜底 |
☑ |
| 22 |
P4:一遍懂/容错/无高压倒计时/不骂人 |
一句规矩;无倒计时无死亡;译错也是剧情;操作面恒定;NPC 句 ≤23 字 |
☑ |
| 23 |
抉择树 4 结局可走通验算 |
§5.5 公式+剧本 A-D 逐检查点(e1/e2: wrong+risk≤4;e3/e4: ≥5) |
☑ |
| 24 |
单局 15-25 min |
§10 曲线 ≈19-22 min |
☑ |
| 25 |
分支不爆炸(radio 纪律) |
跨封仅标量(expose/hints/t1..t4/picks);~75 节点固定深度(§4.3) |
☑ |
| 26 |
台词 ≤150、上级/联络人 ≤2 |
139 句(双 134+NPC 5)/处长+北风两人(voice-ids 账目) |
☑ |
| 27 |
引擎边界诚实 |
§3.4 能力表:摩尔斯文件方案否决理由/滤波不使用/速度边界写明 |
☑ |
| 28 |
存档带 summary、断点续玩 |
§8:data+summary 格式、DECODE 态恢复、局面复述 |
☑ |
批 1 教训内化确认(5 条全落地)
| 教训 |
本作机制 |
断言 |
| 教学承诺必须兑现 |
§7.5 九条承诺清单(重听/慢放/候选/单击/免费页/四封/电键声/教学反馈边界) |
§9「摩尔斯正确性」「教学承诺」块 |
| 看门狗双轨 |
§7.2 无操作轨+无进展轨;纯浏览不复位进展轨 |
§9「看门狗双轨」块 |
| 档位措辞真实 |
§5.3 exp 四档逐值为真且阈值=收网门;§5.4 book 逐值 |
§9「档位句与实值一致」 |
| 失败结算链完整不被打断 |
800ms 死窗盖判定出口/NIGHT/d9/e*;seqToken+停摩尔斯 |
§9 关键路径 2 + 死窗断言 |
| PC 键盘操作提示 |
11 对 _k+inputMode() 选择+集中分组标注 |
§9「键盘变体」块 |
本作特有风险预防(摩尔斯听觉门槛)
| 风险 |
三层防线 |
验证 |
| P3 通勤嘈杂听不清长短音 |
①双击重听原速(无限)②再双击慢放 0.5×(无限、字母隙加倍)③密码本提示直译辨析位字母(3 页,T1 免费)——三层均可独立走通 |
§9 剧本 E/F + 三层兜底断言 |
| P1 视障玩家音频编码接受度高,但语速档位边界 |
摩尔斯不受 settings.speed 影响(u 恒定)——2.2× 档语速下电文仍原速,慢放兜底;边界登记 + live 真人耳测项(转写层测不了时值听感,methodology §5 2026-09 教训:媒体播放类必须真人耳测+引擎级断言) |
§9「摩尔斯正确性」速度边界断言 + live 轮清单 |
| 摩尔斯时值精度 |
运行时 osc 合成(文件方案否决:有损编码 ms 抖动);事件钩子逐元素断言 |
§9 固定字符断言 |
| 「不知道译对没译错」的认知焦虑 |
教学期说破「练习有答案,正片靠耳朵」;档位句+ep 回响给最终真相;译错零惩罚只是分支 |
§9「译错归因真话」 |
修订记录(开发/测试轮裁定,追加不改旧文)
| # |
裁定 |
依据与影响 |
| R1 |
SFX 全 SYN 兜底:§6.2 原标 SA3 的 10 件(tune_seek/static_bed/amb_room/paper_page/key_send/pen_scratch/tea_cup/step_halt/lock_click/dawn_bell)改程序合成(tools/gen_cipher_syn.py),仅 ui_confirm/ui_menu 按原计划 SYN |
与摩尔斯文件方案同型的短音 ms 抖动风险 + 管线一致 + 零成本;one-shot 真峰值 ≤-3dBFS 全过(实测 -3.3~-5.1dBFS),loop 2 件首尾 50ms 环形交叉淡化无缝(seam ≤0.01)。原 SA3 prompt 保留作听感设计参考。 |
| R2 |
p8_blind / p9_blind 条件笔误:19-cipher-voice-ids.md 表内「条件 t4≠top」实为 t4≠spy |
§4.2 抉择树(p8/p9 由 T4 译文 known/blind 差分)与 §9 断言均为 t4 维度;top 是 T2 的真词,显系复制笔误。实现按 t4==='spy' 选播。 |
| R3 |
§5.5 剧本 C 检查点算术以 §5.2 事件单源表为准:NIGHT(3) 后 expose=**5(hot 档)**而非 4/mid;签收前 8 ✓ |
单源表:T2-T4 译错各 +1、p6 左 +2。2+1+2=5 恰好达收网门(≥5),「跨档播报 3 次」表述作废,实为 2 次(calm→low 于 NIGHT(2)、low→hot 于 NIGHT(3),签收前 8 与 5 同档不重复播)。§9 断言按修正值实现(hot 档提前一夜可视化压力,戏剧效果不降反升)。 |
| R4 |
§5.5 剧本 A「全对全右」为措辞笔误:操作序以 §9 关键路径为准(p2 左 · p4 右 · p6 右 · p8 右 · p9 左) |
§5.5 自身给出的 risk=0 与 ep 点名组合(med_ok/list_no/hand_ok/spy_ok)只有该路径自洽;「全右」若按字面 p2 右则 risk=1、ep_med_no,矛盾。验算 expose=0 → e1 不受影响。 |
| R5 |
菜单低响度实现路径:§6.1「menu 用同曲低响度」经游戏层 _bgmBus 增益 0.4(与摩尔斯 −6dB dip 乘法复合) |
引擎约定「同一首重复 play 不重启」,play(opts.volume) 无法作用于在播 BGM;省一首成立(无 menu 专属曲目)。 |
| R6 |
d9_sleep 自动链(radio d9_face 同型) |
关机收束节奏与发报线对齐;p9 右的收束不因链末等待拖沓。 |
| R7 |
transcribe.mjs CLASS_NAME 追加 cipher 行(CipherGame) |
共享 harness 接线(check_all_assets 之外唯一跨游戏触碰点),hunt/teahouse 等泳道同款需求各自追加。 |
| R8 | R2 修复三件套(round1 synthesis F1-F3):① NIGHT 链首按上一封抉择垫纸面标记音(p2右/p4左→paper_page,p4右→pen_scratch,现有 sfx 零新增)——「世界因你而动」可感知化;② book_1(密码本只剩最后一页)各播报位到句附 warning 震(F2);③ 结算链尾新增结局计数分档整句 end_c1..end_c4(F3,+4 句 WIND,见 19b R2 增补) | 均不改树形/不加抉择点/不增人设;断言入 §9 清单(F1 纸面音有/无双向断言、F2 warning 震、F3 计数句)。 |