Files
SoundGame/docs/design/20-teahouse.md
T
xsl 1d59d22e53 docs(new8): 批次 2/3 策划全套落地(17-abyss/18-detective/19-cipher/20-teahouse 主设计+台词表,含 13 号断言登记)
- abyss:声呐双通道仲裁/氧气软失败经济 512 组合穷举/148 句;detective:证词矛盾数据单源推导/158 句;cipher:摩尔斯运行时合成/暴露度经济/139 句;teahouse:泡茶三步小局听觉分层/5 晚经济逐晚验算/163 句
- 全部内化批次 1 教训(教学承诺兑现/双轨看门狗/档位措辞真实/结算死窗/键盘变体标注)
2026-09-10 00:43:39 +08:00

528 lines
45 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.
# 20 · 《深夜茶馆》完整设计(teahouse / Late Night Teahouse)
> **给开发者的实现要点摘要**
> 1. 经营养成 RPG:核心动词=**泡茶**。一晚=3-5 位客人(本文定 4)≈13-17 分钟=单局;每位客人 2-4 分钟完整小循环(P3 三分钟颗粒)。泡茶小局三步:**左右滑选茶+单击选定 → 听水声双击提壶(候汤)→ 听滴答双击出汤(闷泡)**——时机步绑双击(即时,规避单击 300ms 延迟,dungeon 格挡先例),选茶步零豁免。
> 2. 手势宪法三件套全状态保留(上滑状态/下滑菜单/双击重听);**唯一豁免 E1=时机步双击≠重听**(重听职责由上滑状态链第一段「重播客人点单句」承接),E2=链播中单击=跳句(12 号既有口径),E3=BREW 态关长按快进。教学讲清。
> 3. **听觉分层铁律**(本作最大风险):注水/沸腾/滴答三重音**时间上串行不重叠**,任意时刻≤(1 条主操作音+BGM)=2 声流;语音只出现在步与步之间的静默点;滴答只在闷泡最后 ~2.5s 关键窗;BREW 时机窗内看门狗只发 earcon 不发语音。
> 4. 客人=声音群像:5 位弧线客人 NPC 平铺(5 音色,2 处与旁白同 speaker 已标风险)+3 位氛围客人**旁白转述零 NPC 句**。弧线 3 晚×3 方向(好/普通/错茶),结局按方向累计值三选一——**全部从数据单源推导**(点单句→茶参数→时机判定→三档结果→方向值),播报值=运行值。
> 5. 经济账目真实(radio rep 教训加倍):口碑/收入/房租/欠账每一档播报与累积值一一映射;错茶=免单(收入 0、口碑−1,无其他惩罚);房租不足=「贴钱记账」剧情挫折,**无 game over**。§7.5 有完整 5 晚剧本逐晚验算。
> 6. 随机性:N1-N5 剧本夜**固定客序**(连续剧结构);seed PRNG(mulberry32)只管 N6+ 氛围客轮换/口味与提示轮询。`opts.seed` 注入可复现。
> 7. 台词表 [20-teahouse-voice-ids.md](20-teahouse-voice-ids.md):旁白 98 ×2 性别 + NPC 平铺 65 = **163 句 ≤170 上限**;操作提示句键盘变体 `_k` 集中登记(V 组,`gesture.inputMode()` 选播)。CLOSE 结算链 800ms 手势死窗+链锁(dungeon H1 / detective VERDICT 同款)。
> 8. 规模对标 detective:单文件 game.js 预计 900-1100 行;bgm 3 + sfx ~26 + voice 261 条(×2 格式=522 文件)。断言清单住本文档 §11(13 号文档 §20/§21 先例登记)。
---
## 1. 概述
- **一句话**:你接手巷子深处一家亮到后半夜的小茶馆,客人的故事随你泡的茶展开——泡对了,暖的是人心;泡错了,故事照样走,只是方向不同。
- **题材**:经营养成。核心命题「茶是热的,夜是长的」——纯音频天然适合:茶的好坏本来就只能靠听(水声、滴答)与「尝」(客人的声音反应)来感知;经营账目是规整的听觉播报链;客人群像是本作最大资产(8 位客人=8 种声音人生)。
- **玩法定位**(方法论 §4.1 无现成行,状态层重点自定):**状态即节拍**(一晚=固定客序推进,永不迷失「接下来干嘛」)+ **听觉判定**(时机步靠耳朵)+ **账目真实**(经济播报与累积值单源)。
- **单局=一晚**:4 位客人,13-17 分钟(首晚含教学 17-20);章程 15-25 分钟区间达标。**一章=5 晚**(全部弧线收束);每客人 2-4 分钟= P3 自然切分颗粒,任意客人结算后存档退出、回来一句话接上。
- **无死亡无惩罚**:泡错茶=客人免单+吐槽+故事走涩向;房租不足=秦婶记账(贴钱营业),永远没有 game over。轻压力=经济账每晚都要对(口碑档/收入档/欠账)。
- **与现有 10 游戏的关系**:状态档位链承接 dungeon(上滑多段链);双轨看门狗承接 dungeon E0-1/E0-2;NPC 群像+签名 earcon 承接 detective(sig_* 前缀);时机判定承接 rpg 格挡(双击+前摇窗口);「声音演技弧线」承接 radio(多晚连续剧);经营元进度为本作新增系统(8 款新模式探索点)。
## 2. 手势映射与豁免登记
### 2.1 每晚开场(OPENING)
| 手势 | 首晚(含教学 DRILL) | 常规晚 |
|---|---|---|
| 单击 | 教学步骤作答(D1/D4) | 跳句(开场链可跳) |
| 双击 | 重听教学句 | 重听当前句 |
| 左滑/右滑 | D0 步作答;其余 error | error 震 |
| 上滑 | 状态链(D5 教后可用) | 状态链 |
| 下滑 | **跳过教学**(tut_skip;meta.drillDone) | 菜单 |
| 长按/松开 | error | error |
开场链:lamp_light(点灯 sfx)→ night_N(分档句)→(首晚 intro_1..3→DRILL)→ 1.5s 后门铃,自动进 SERVE。
### 2.2 堂前(SERVE:WELCOME/TALK/REACT 三个自动链子相位)
| 手势 | 链播中(进门/点单/反应) | 空闲(链完待自动转场间隙) |
|---|---|---|
| 单击 | **跳句**(12 号口径;关键句「不可跳」仅 res_* 结果句与 rent_*) | 提前切下一段(加速) |
| 双击 | **重听当前句**(宪法语义保留) | 重听末句 |
| 左滑/右滑 | 静默忽略(纯聆听保护,simon playback 先例) | 同左 |
| 上滑 | 状态链(queue 排队,链播完后续) | 状态链 |
| 下滑 | 菜单(打开即停链;关闭→**重播被停句**,storyline「节点不丢」先例) | 菜单 |
| 长按/松开 | 引擎快进(旁白 1.7×,不豁免)/ 恢复常速 | error |
### 2.3 泡茶小局(BREW:TEA 选茶 → WATER 候汤 → STEEP 闷泡三子相位)
| 手势 | TEA(选茶) | WATER(候汤) | STEEP(闷泡) |
|---|---|---|---|
| 左滑/右滑 | 换茶罐(循环):tea_jar sfx + 茶名句(含口诀) | error 震+`gd_invalid`(**不判错步**) | 同左 |
| 单击 | **选定此茶** → 自动进候汤(scoop sfx) | error 震+纠错(等时机) | 同左 |
| 双击 | 重听当前茶名句(宪法语义保留) | **提壶**(时机判定,即时) | **出汤**(时机判定,即时) |
| 上滑 | 状态链(**第一段=重播当前客人点单句**+sig,需求随时可查) | 同左(链排队;水声时间线**照走**,错过=真话归因「水滚老了」) | 同左 |
| 下滑 | 菜单(冻结全部计时) | 菜单(冻结水声时间线) | 菜单(冻结滴答) |
| 长按/松开 | error(E3:BREW 全态 `setRateBoostEnabled(false)`) | 同左 | 同左 |
菜单关闭恢复(A2 count-in 口径):TEA→重播当前茶名句;WATER→重播 `hint_water` 口诀;STEEP→重播当前茶名句;水声时间线从冻结点续走。
### 2.4 打烊(CLOSE)/ 标题(TITLE)
| 手势 | CLOSE(结算链) | CLOSE(链完) | TITLE |
|---|---|---|---|
| 单击 | **吞掉**(800ms 死窗+链锁,§4.4) | **睡下**→OPENING(night+1)(settle_night 承诺言行一致) | 继续(有档)/ 新店(无档) |
| 双击 | 吞掉 | 重听结算链 | 重听 continue_ask |
| 右滑 | 吞掉 | error | 重开新店:播 sys_reset_ask,**再右滑一次**确认(其余手势取消) |
| 上滑 | 吞掉 | 重听账目链(st_rep→st_purse→置办清单) | 店铺概况(口碑档→存款档→已置办句重播) |
| 下滑 | 吞掉 | 菜单(含「打烊置办」项) | 菜单 |
| 左滑/长按 | 吞掉 | error | error |
### 2.5 模态菜单(遵守 00 §5.2 全球约定,无豁免)
下滑呼出(停链/冻结计时)→ 单击循环切项 → 双击确认 → 上滑帮助 → 下滑关闭。选项:返回堂前 / **打烊置办**(仅 CLOSE;进二级列表同范式:茶柜/茶具/招牌/算了)/ 保存并回大厅 / 重新听帮助。
### 2.6 每状态手势映射总表(6 手势+长按松开,全状态覆盖)
| 手势 | TITLE | OPENING | SERVE | BREW-TEA | BREW-水 | BREW-闷 | CLOSE | MENU |
|---|---|---|---|---|---|---|---|---|
| 单击 | 继续/新店 | 作答/跳句 | 跳句/加速 | 选定茶 | error+纠错 | error+纠错 | 吞/睡下 | 循环切项 |
| 双击 | 重听 | 重听教学句 | 重听当前句 | 重听茶名句 | **提壶** | **出汤** | 吞/重听链 | 确认执行 |
| 左滑 | error | 教学指定/err | 忽略 | 上一罐 | error | error | 吞/err | 上一项 |
| 右滑 | reset(两次) | 教学指定/err | 忽略 | 下一罐 | error | error | 吞/err | 下一项 |
| 上滑 | 店铺概况 | 状态 | 状态链 | 状态(含需求) | 状态链 | 状态链 | 吞/账目链 | 帮助 |
| 下滑 | 菜单 | 菜单/跳教学 | 菜单 | 菜单(冻结) | 菜单(冻结) | 菜单(冻结) | 吞/菜单 | 关闭 |
| 长按 | error | error | 快进(引擎) | error | error | error | 吞/err | error |
| 长按松开 | — | — | 恢复常速 | — | — | — | — | — |
无效手势一律 error 震;full 档 `gd_invalid`(onceKey 同局 1 次);idle-only(引擎 guide 已实现)。
### 2.7 豁免登记(必须显式)
| # | 豁免条目 | 理由(先例) |
|---|---|---|
| E1 | BREW 时机步(候汤/闷泡)双击=提壶/出汤,非重听 | 即时判定绑双击规避单击 300ms 延迟(dungeon 战斗双击=格挡、rpg 前摇格挡同款);重听职责不缺位——上滑状态链第一段=重播客人点单句(含 sig),选茶步双击仍=重听茶名句。教学 D2/D3 讲清 |
| E2 | SERVE 链播中单击=跳句(非「确认」) | 12 号 §1 既有口径(rpg/storyline/escape 先例);关键句(res_*、rent_*)登记不可跳 |
| E3 | BREW 态 `setRateBoostEnabled(false)` | 长按在 BREW 是无效输入;防误触快进(dungeon/rhythm/space 对局期先例) |
无 immediateTap;tap 只用于非即时操作(选定/跳句/睡下/菜单)。
## 3. 核心动词:泡茶小局(信息设计)
### 3.1 三步手势序列规格
| 步 | 输入 | 选项数 | 音反馈 | 错误容限 | 时长 |
|---|---|---|---|---|---|
| ① 选茶 TEA | 左右滑循环+单击选定 | 茶柜 4 罐(扩容后 6) | 每次切换:tea_jar(0.3s)→ 茶名句(含该茶口诀,**知识随身播报**);选定:tea_scoop | 无限切换无时间压力;**选定后不可改**(错茶=故事走涩向+免单,无惩罚);上滑随时重听客人点单 | 8-25s |
| ② 候汤 WATER | **双击提壶** | 1(时机) | 水声时间线(见 3.2):细密气泡→将沸→滚透→滚老,单条 11s | 窗宽 ±1.5s(茶具升级 ±2.3s;首晚 ×1.3);早=「欠火」晚=「过老」均记偏**不终止流程**;无出手 t=11s 自动过老继续 | 11s 封顶 |
| ③ 闷泡 STEEP | **双击出汤** | 1(时机) | 注水 2s→舒展沙沙 2s→**静默**(仅 BGM)→目标前 2.5s 起 tick 滴答(窗内加速) | 窗宽 [目标−1.0, 目标+1.4]s(茶具 +0.8s;首晚 ×1.3);早=「涩」晚=「苦」记偏;无出手 +4s 自动出汤继续 | 9-21s |
- 判定与结果(**数据单源**,无独立状态):`{茶对错, 水档, 闷档}` → 茶错⇒res_wrong;茶对∧水 ok∧闷 ok⇒res_good;茶对∧任一偏⇒res_plain。三档结果→客人反应三方向(§6.4)。
- 每步结算即归因(真话律):`water_early/ok/late`、`steep_early/ok/late` 按真实时机选播;错手势(时机步内滑/单击)**不判错步**——只有时机本身决定品质,绝不报假归因。
### 3.2 水声时间线(声学编码,全在引擎能力内)
不用实时 WebAudio 节点(playtest mock 只覆盖 bufferSource/gain):全部=预生成 sfx one-shot + setTimeout 调度 + volume。
```
t=0 water_pour 注水 one-shot(2s)
t=2.0 boil_blip 单泡音起播:间隔 700ms(温水段)
t=3.5 ── 将沸窗开(绿茶/银针的提壶窗)── blip 间隔 350ms + boil_simmer 低鸣 one-shot 链
t=6.5 ── 滚透窗开(茉莉/铁观音/滇红/普洱的提壶窗)── boil_roar 连片 one-shot 链(2s/段)
t=9.5 窗闭:boil_over 剧烈嘶鸣(滚老)
t=11.0 无出手→自动过老,播 water_late,进闷泡
```
- 两窗共用一条时间线,茶种决定用哪扇窗(茶名句口诀即判据:「将沸就提」vs「滚透才冲」)。
- 闷泡时间线:pour(2s)→ steep_rustle 沙沙(2s)→ 静默(BGM only)→ 目标前 2.5s tick_slow 起(1s/拍)→ 入窗 tick_fast(0.6s/拍)→ 窗后 +4s 自动出汤。
- 目标闷时(自注水毕):快 7s(龙井/茉莉)/ 中 11s(铁观音/银针)/ 久 15s(滇红/普洱)。
### 3.3 听觉分层表(本作最大风险预防:并发声流 ≤2)
| 时刻 | 声流①(内容) | 声流②(床) | 语音 | 断言口径 |
|---|---|---|---|---|
| 客人进门/点单/反应 | —— | BGM serve | 客人句(1 条) | BGM+voice=2 ✓ |
| 选茶 | tea_jar/scoop one-shot(≤0.3s,串行于语音前) | BGM serve | 茶名句 | one-shot 与 voice 不叠(jar 先响完再播句) |
| 候汤 | boil_blip/roar 调度流 | BGM brew | **零语音**(设计禁止) | 水声期间 voice 播放事件=0 |
| 闷泡静默段 | 无 tick | BGM brew | 零语音 | 1 声流(最安静段=呼吸感) |
| 滴答关键窗 | tick 滴答 | BGM brew | **零语音**(看门狗也只发 earcon,§9.2) | tick 活跃窗内 voice 事件=0 |
| 打烊结算 | coin/lamp one-shot | BGM menu | 账目句链 | 串行 |
- 频带分离:沸腾=低频(150-500Hz 咕嘟)、滴答=高频木鱼(~880Hz 族)、人声=中频——即偶发瞬时叠听也不糊(Brewster 指南)。
- 滴答只在关键窗(需求原文兑现):静默闷泡段绝不加节拍器。
## 4. 状态机
### 4.1 状态列表
`TITLE / OPENING / SERVE / BREW / CLOSE` + `MENU`(挂起 overlay,记录返回态)。SERVE 子相位=WELCOME/TALK/REACT(自动链);BREW 子相位=TEA/WATER/STEEP;CLOSE 子相位=TALLY(链)/SHOP(菜单内置办)。
### 4.2 转移图
```
start ──> TITLE ──tap(有档)──> OPENING(night_N) ──自动──> SERVE(客人1)
│tap(无档) │
│右滑×2=重开新店(run+meta 清) │点单链完,自动
v v
(大厅) SERVE ⇄ BREW(每位客人一圈)
SERVE(末位客人反应毕) ──自动──> CLOSE(打烊链)
CLOSE ──tap──> OPENING(night+1) [N5 链含 chapter_end;N6+ 无尽营业]
任意正交态 ──下滑──> MENU ──关闭──> 原状态(SERVE 重播被停句;BREW 冻结后恢复)
```
### 4.3 语音链推进契约
- 客人链/结算链=onComplete 串行(句间 0.8s);单句 8s 无 onComplete(资产缺失)→ 告警续链(「屏蔽任意 voice 流程不卡死」契约)。
- 教学链 `_speakGuarded` 串行(radio/dungeon D0-1 同款,杜绝同 tick 双调度抢占)。
- CLOSE 结算链为**独占链**:链首停看门狗;链内不受理手势(§4.4)。
### 4.4 打烊死窗与链锁(dungeon H1 / detective VERDICT 内化)
- 进 CLOSE 即盖 `CLOSE_GRACE_MS=800` 死窗戳(touchstart+450ms 长按判定+300ms 双击窗 ≈750ms,800 全盖);死窗内一切手势吞掉(ghost 手势不算输入、不碰看门狗)。
- 链锁:close_open→账目句→(房租/欠账句)→(chapter_end)→settle_night 落声前,单击/右滑/长按一律吞掉;链完成后单击=睡下(settle_night「单击,睡下」言行一致——simon round1-live 教训)。双击=重听链仅链完成后受理。
## 5. 教学编排(DRILL,首晚寄生于第 1 位客人=老周①)
每步=一句短旁白→等待实操→反馈;做错重教同一步(**新短句 ≤2 次**)后自动演示通过;下滑=跳过(tut_skip),`meta.drillDone` 持久化。教学客老周①**明示茶名**(龙井)+首晚窗口 ×1.3 → 好茶近乎保送、账目照常(首胜≤3min,A5)。
| 步 | 旁白 | 等待动作 | 通过条件/反馈 |
|---|---|---|---|
| D0 | intro_1..3 + tut_d0 | 左滑或右滑任一 | tea_jar+茶名句;confirm 震。**首输入 ≈t+20s(<60s ✓)** |
| D1 | tut_tea | 单击 | tea_scoop → 自动坐水 |
| D2 | tut_water | 双击(将沸窗内) | water_ok(偏了也继续:water_early/late 真话归因+重教短句) |
| D3 | (水毕自动)tut_steep | 双击(滴答密时) | steep_ok(同上容错) |
| D4 | tut_serve | 单击 | pour_cup → 老周 r1 反应句。**首正反馈 ≈t+2.5-3min(≤3min ✓)** |
| D5 | tut_status | 上滑 | 状态链(st_guest→st_rep→st_purse) |
| D6 | (老周出门后)tut_done | — | 第 2 位客人门铃,自由营业 |
- 滚透窗(茉莉等 4 茶)不设专门教学步:靠茶名句口诀+hint_water+首晚宽窗自然过渡(知识单源=茶名句,承诺必兑现)。
- 教学无进展轨(E0-2 先例):30s earcon → 60s 短句 → **90s 自动替打当前步**(自动选定/提壶/出汤,演示通过不卡流程)。
## 6. 客人系统
### 6.1 客人档案 JSON 草案(数据单源:点单句→茶参数→判定→方向→结局)
```json
{
"schema": 1,
"teas": {
"longjing": { "name": "tea_longjing", "price": 6, "water": "simmer", "steep": "fast", "shelf": true },
"moli": { "name": "tea_moli", "price": 4, "water": "rolling", "steep": "fast", "shelf": true },
"tieguanyin": { "name": "tea_tieguanyin", "price": 8, "water": "rolling", "steep": "mid", "shelf": true },
"dianhong": { "name": "tea_dianhong", "price": 5, "water": "rolling", "steep": "long", "shelf": true },
"puer": { "name": "tea_puer", "price": 7, "water": "rolling", "steep": "long", "shelf": "cabinet" },
"yinzhen": { "name": "tea_yinzhen", "price": 10, "water": "simmer", "steep": "mid", "shelf": "cabinet" }
},
"arcGuests": [
{ "id": "zhou", "name": "老周", "sig": "sig_zhou",
"enter": "zhou_enter", "orders": ["zhou_o1", "zhou_o2", "zhou_o3"],
"teaByVisit": ["longjing", "dianhong", "longjing"],
"reactions": [["zhou_r1_good", "zhou_r1_plain", "zhou_r1_wrong"],
["zhou_r2_good", "zhou_r2_plain", "zhou_r2_wrong"], null],
"endings": ["zhou_e_a", "zhou_e_b", "zhou_e_c"] },
{ "id": "su", "name": "苏晚", "sig": "sig_su", "enter": "su_enter",
"orders": ["su_o1", "su_o2", "su_o3"],
"teaByVisit": ["dianhong", "moli", "dianhong"],
"reactions": [["su_r1_good","su_r1_plain","su_r1_wrong"],
["su_r2_good","su_r2_plain","su_r2_wrong"], null],
"endings": ["su_e_a", "su_e_b", "su_e_c"] },
{ "id": "shi", "name": "陈拾", "sig": "sig_shi", "enter": "shi_enter",
"orders": ["shi_o1", "shi_o2", "shi_o3"],
"teaByVisit": ["moli", "longjing", "yinzhen"],
"reactions": [["shi_r1_good","shi_r1_plain","shi_r1_wrong"],
["shi_r2_good","shi_r2_plain","shi_r2_wrong"], null],
"endings": ["shi_e_a", "shi_e_b", "shi_e_c"] },
{ "id": "bai", "name": "白老先生", "sig": "sig_bai", "enter": "bai_enter",
"orders": ["bai_o1", "bai_o2", "bai_o3"],
"teaByVisit": ["tieguanyin", "puer", "puer"],
"reactions": [["bai_r1_good","bai_r1_plain","bai_r1_wrong"],
["bai_r2_good","bai_r2_plain","bai_r2_wrong"], null],
"endings": ["bai_e_a", "bai_e_b", "bai_e_c"] },
{ "id": "he", "name": "何雨眠", "sig": "sig_he", "enter": "he_enter",
"orders": ["he_o1", "he_o2", "he_o3"],
"teaByVisit": ["longjing", "puer", "yinzhen"],
"reactions": [["he_r1_good","he_r1_plain","he_r1_wrong"],
["he_r2_good","he_r2_plain","he_r2_wrong"], null],
"endings": ["he_e_a", "he_e_b", "he_e_c"] }
],
"ambientGuests": [
{ "id": "postman", "order": "amb_1", "teaPool": ["moli"] },
{ "id": "embroider", "order": "amb_2", "teaPool": ["longjing"] },
{ "id": "drunk", "order": "amb_3", "teaPool": ["dianhong"] }
],
"nights": [
["zhou", "amb:postman", "su", "shi"],
["zhou", "bai", "he", "shi"],
["zhou", "su", "bai", "amb:drunk"],
["he", "shi", "su", "amb:postman"],
["bai", "he", "amb:embroider", "amb:postman"]
],
"nightsEndless": { "pool": ["amb:postman", "amb:embroider", "amb:drunk"], "size": 4 },
"economy": { "tipGood": 2, "rentEvery": 3, "rent": 20,
"repGain": { "good": 1, "plain": 0, "wrong": -1 },
"pay": { "good": "price+2", "plain": "price", "wrong": 0 },
"upgrades": [
{ "id": "cabinet", "voice": "upg_cabinet", "cost": 15 },
{ "id": "teaware", "voice": "upg_teaware", "cost": 12 },
{ "id": "sign", "voice": "upg_sign", "cost": 20, "repReq": 12 } ] }
}
```
- 氛围客人点单句由旁白转述(amb_1..3,句内已含茶名与参数暗示);判定同弧线客人(teaPool/口味由 seed 决定 N6+ 变体,N1-N5 用表内固定值)。
- **矩阵不变式(dev/playtest 双保险)**:每晚每位客人的点单句 ⇒ `(tea, water窗, steep窗)` 三元组与 `teas[teaByVisit[i]]` 严格一致;任何台词改稿若使点单句暗示的茶与 teaByVisit 不符,断言立即失败(防「文案事故变成归因假话」)。
### 6.2 弧线节点表(5 位客人 × 3 晚;方向值 好茶+1 / 普通 0 / 错茶−1)
| 客人 | 晚1 相遇 | 晚2 深入 | 晚3 收束(结局=按累计 sum) |
|---|---|---|---|
| 老周(修车师傅,儿子在外多年) | 点龙井去火;r1×3 | 点浓暖的(滇红);r2×3 起「儿子来电」话头 | 「头一回那盏再来一份」(龙井回环);sum≥2=A 父子回来帮工 / B 电话拌嘴日子照过 / C 关铺去投儿子 |
| 苏晚(夜班护士,去留抉择) | 点暖的不冲(滇红);r1×3 | 点香的(茉莉);r2×3 讲科室一夜 | 「还是头一回那种」(滇红回环);A 调白天班白天来 / B 再值一季看看 / C 递辞呈但记住这盏灯 |
| 陈拾(高三生,大考) | 点香提神不浓(茉莉);r1×3 | 点清火的(龙井);r2×3 问「还能考上吗」 | 「喝口金贵的犒劳自己」(银针,需茶柜);A 超常发挥请全馆 / B 听家里安排 / C 考砸但灯还亮着 |
| 白老先生(独居,老伴忌日) | 点刮油经泡的(铁观音);r1×3 | 点陈味(普洱,需茶柜);r2×3 忆四十年前一盏普洱 | 「就馋那口陈味」(普洱);A 搬棋盘天天来「当她在看着」 / B 空屋但有茶垫梦 / C 搬去养老院留壶给茶馆 |
| 何雨眠(夜班出租车司机,攒学费) | 点清口不浓(龙井);r1×3 | 点最浓的(普洱,需茶柜);r2×3 讲闺女照片贴方向盘 | 「一盏柔的收收心」(银针,需茶柜);A 学费齐了去看闺女 / B 差一点再跑一月 / C 退了夜班「这盏喝得最慢」 |
- 结局映射:`sum = Σ方向值(3 晚)`;`sum≥2 → A(暖);−1≤sum≤1 → B(平);sum≤−2 → C(涩)`。
- 茶柜锁与弧线的 roguelike 纹理:白老②③/何②③/陈③ 需要「茶柜扩容」解锁的普洱/银针——没置办的玩家必然错过好茶档,弧线自然走平/涩向(**这是经营决策的重量,不是 bug**;§7.5 剧本 B 验算)。全 A 路径可行性:N2 打烊置办茶柜(15 文)即解锁全部弧线茶(§7.5 剧本 A)。
- 晚 3 收束夜=「反应与结局合一」:结局句本身回应今晚的茶(A 段必有对茶的正面回应、C 段必有遗憾——见台词表 N 组)。
### 6.3 声音群像:区分度(本作最大资产风险,逐人标注)
| 角色 | speaker | instruct 常量 | 区分度风险 |
|---|---|---|---|
| 旁白(掌柜系统音) | female=Serena / male=Uncle_Fu | 见台词表头 | 基准 |
| 老周(58 修车师傅) | `Eric` | 沙哑洪亮的男声,修车铺老师傅,大嗓门,直爽热乎 | 低:与两侧旁白均不同 speaker |
| 苏晚(29 夜班护士) | `Vivian` | 轻柔平稳的女声,夜班护士,温和疲惫,吐字干净 | 低:同上 |
| 陈拾(17 高三生) | `Dylan` | 年轻清亮的男声,高三学生,紧张,语速快,有点怯 | 低:同上 |
| 白老先生(74) | `Uncle_Fu` | 苍老缓慢的男声,独居老先生,慢条斯理,带茶韵 | **中**:与 male 旁白同 speaker——靠 sig_bai 前缀+苍老腔 instruct+人称差(客人第一人称/旁白第三人称「客人」)+句间 0.6s;试听确认 |
| 何雨眠(36 的姐) | `Serena` | 低哑爽利的女声,夜班出租车司机,利落,带笑带倦 | **中**:与 female 旁白同 speaker——同上缓解;试听确认 |
| 氛围客人 ×3 | 旁白转述 | 同旁白 | 无(零 NPC 句,成本与风险双省) |
NPC 音色数=5 ≤6(radio/detective 满配先例);每位弧线客人**专属签名 earcon**(sig_*,0.3-0.5s)在进门句/状态链需求重播/反应句前必响——认人是「sig+speaker+instruct」三层冗余。
## 7. 经营数值(口碑/收入/房租经济表)
### 7.1 每晚事件表(N1-N5 剧本夜)
| 晚 | 客序 | 事件 |
|---|---|---|
| 1 | 老周①/邮差/苏晚①/陈拾① | 教学;首胜保送;无房租 |
| 2 | 老周②/白老①/何①/陈拾② | 普洱银针需求首次逼近(茶柜压力);打烊可置办 |
| 3 | 老周③/苏晚②/白老②/醉汉 | **房租夜①**(20 文);老周弧线收束 |
| 4 | 何②/陈拾③/苏晚③/邮差 | 苏晚/陈拾弧线收束 |
| 5 | 白老③/何③/绣娘/邮差 | **房租夜②**;白老/何收束;chapter_end |
N6+(无尽营业):4 席=氛围客轮换(seed 定序/口味),房租照收,经济维持。
### 7.2 累积公式
```
rep:初始 0,clamp ≥0。每客 good +1 / plain 0 / wrong −1。每晚 Δ∈[−4,+4]。
purse(存款):初始 0。CLOSE 时 income 计入 → 先还债(debt 清零播 debt_clear)→ 房租夜扣 rent
(不足 → 差额入 debt,播 rent_short + danger 签名)→ 可置办(不透支)。
income(当晚):Σ 每客 pay = good: 茶价+2 打赏 / plain: 茶价 / wrong: 0(免单)。
方向值(弧线):good +1 / plain 0 / wrong −1,sum 三晚 → 结局 A/B/C。
upgrades:cabinet 15(普洱+银针上柜)/ teaware 12(时机窗 +0.8s)/ sign 20(需 rep≥12,每晚结算 rep+1)。
```
### 7.3 档位播报措辞与账目一一映射(radio rep 教训:播报值=运行值,跨档才播、双向都播)
| 账本 | 档 | 阈值 | 播报句(id) | 措辞↔账目 |
|---|---|---|---|---|
| 口碑 rep | 1 冷清 | 0-4 | st_rep_1「口碑还没立起来」 | 「没立起来」=rep<5 |
| | 2 回头 | 5-11 | st_rep_2「有了回头客」 | 「回头客」=rep≥5 |
| | 3 名声 | 12-19 | st_rep_3「巷子口都在传」 | 「传」=rep≥12 |
| | 4 招牌 | ≥20 | st_rep_4「一盏难求」 | 「难求」=rep≥20 |
| 当晚收入 | 1 | <15 | close_coin_1「不到十五文」 | 与逐客 pay 之和相等 |
| | 2 | 15-24 | close_coin_2「十五到二十五文」 | 同上 |
| | 3 | ≥25 | close_coin_3「二十五文往上」 | 同上 |
| 存款 purse | 1 | <10 | st_purse_1「钱箱见底」 | 结算后实值 |
| | 2 | 10-24 | st_purse_2「周转得开」 | 同上 |
| | 3 | ≥25 | st_purse_3「手头宽裕」 | 同上 |
| 欠账 debt | — | >0 | st_debt_1「账上还欠着秦婶的钱」 | CLOSE 链内、还清播 debt_clear |
| 房租 | — | 每 3 晚 20 文 | rent_due→rent_ok / rent_short | 不足额=差额入账,**无 game over** |
### 7.4 店铺升级树(roguelike 跨晚进度,localStorage+服务器双存)
```
茶柜扩容 15 ──> 普洱(7文·滚·久)+白毫银针(10文·将沸·中)上柜 ──> 解锁白老②③/何②③/陈③ 的好茶路径
新茶具 12 ──> 候汤/闷泡窗各 +0.8s(容错拉满,P4)
立招牌 20(需 rep≥12 且 debt=0)──> 每晚结算 rep+1(口碑发酵)
```
### 7.5 完整 5 晚剧本验算(剧本 A「用心掌柜」——口碑/收入逐晚对账)
| 晚 | 逐客结果(茶·三档) | 逐客收入 | 当晚收入 | rep 流程(跨档播报点) | purse 流程 |
|---|---|---|---|---|---|
| 1 | 周好(龙井)/邮好(茉莉)/苏好(滇红)/陈好(茉莉) | 8/6/7/6 | 27(coin_3) | 0→4(无跨档) | 0→27 |
| 2 | 周普(滇红)/白好(铁观音)/何错(泡了茉莉)/陈好(龙井) | 5/10/0/8 | 23(coin_2) | 4→5(**st_rep_2**)→4(**st_rep_1**,何错跌回)→5(**st_rep_2**) | 27+23=50;置办茶柜 −15 → **35** |
| 3 | 周好(龙井)/苏好(茉莉)/白好(普洱)/醉普(滇红) | 8/6/9/5 | 28(coin_3) | 5→8;**老周 sum=+1+0+1=2 → 结局 A** | 35+28=63;房租 −20 → 43;置办茶具 −12 → **31** |
| 4 | 何好(普洱)/陈好(银针)/苏错(泡了龙井)/邮普(茉莉) | 9/12/0/4 | 25(coin_3) | 8→9→10→9(**st_rep_2**下沿内,不跨档)→9;陈 sum=3→A;苏 sum=+1+1−1=1→**B** | 31+25=**56** |
| 5 | 白好(普洱)/何好(银针)/绣普(龙井)/邮好(茉莉) | 9/12/6/6 | 33(coin_3) | 9→10→11→11→12(末客后**st_rep_3**);白 sum=3→A;何 sum=−1+1+1=1→**B** | 56+33=89;房租 −20 → 69;**立招牌 −20(rep=12 恰达标)→ 49** |
终局:rep 12(档3)/ purse 49 / 升级 3/3 / debt 0 / 结局 3A+2B;chapter_end → N6+ 无尽营业。
**对账断言**:每晚 close_coin 档=逐客 pay 之和所在档;每次 st_rep 播报时的 rep 实值=该档阈值区间;置办价=upg 表——playtest 锁定(假话即失败)。
### 7.6 剧本 B「贴钱营业」验算(欠账机制可达性)
N1-N3 全错(每客免单+rep−1,rep clamp 0):income 0/0/0,purse 0;N3 房租 20 > 0 → **rent_short+danger,debt=20**(贴钱营业,无 game over);无茶柜 → N4 何②/陈③必然错茶(普洱/银针缺位,弧线走涩向——经营决策的真实重量);N4 苏好+邮普 income 11 → 还债 11(debt 9);N5 绣普+邮好 income 12 → 还债 9(**debt_clear**)→ purse 3 → 房租 → debt 17。终局 rep 2(档1)、结局 2C+3B——**活着,且每一句播报与账本一致**。
## 8. 音频三层
### 8.1 BGM(3 首,Mureka instrumental,-20 LUFS,ogg+m4a,无缝循环)
| id | 状态映射 | Mureka prompt(英文) |
|---|---|---|
| bgm/menu | TITLE / MENU / CLOSE(结算 volume 0.5) | "Cozy late night tea house, soft guzheng and bamboo flute duet, warm kettle hum and faint vinyl crackle, intimate and unhurried, no drums, no vocals, seamless loop" |
| bgm/serve | OPENING / SERVE | "Gentle Chinese tea house evening theme, sparse pipa and soft erhu, distant crickets and quiet old-street ambience, warm storytelling mood, no vocals, seamless loop" |
| bgm/brew | BREW(三子相位) | "Minimalist zen tea brewing music, very sparse guqin notes over soft water ambience, meditative, wide and quiet dynamics, no vocals, seamless loop" |
切换全走引擎 crossfade;voice duck 20% 引擎自动。预算:3 曲 ×2 候选=6 任务 $0.18(上限 $2.00 内)。brew 曲**特意稀疏**——给操作音让频带(§3.3)。
### 8.2 SFX(~26 个;SA3=Stable Audio 3,SYN=程序合成;双格式、真峰值 ≤-3dBFS)
| 类别 | id | 方式 | 说明 |
|---|---|---|---|
| 进门 | `door_bell` | SA3 | 铜铃两响(0.5s,客人进门/出门) |
| | `steps_in` `steps_out` | SA3 | 布鞋脚步 1.2s(in 由远及近预 pan 派生,dungeon 工艺) |
| 客人签名 | `sig_zhou` | SYN | 扳手磕搪瓷缸一响 |
| | `sig_su` | SYN | 指尖叩桌面两下 |
| | `sig_shi` | SYN | 拉链+书本落桌 |
| | `sig_bai` | SYN | 棋子落木盘一响 |
| | `sig_he` | SYN | 车钥匙串抖两下 |
| 选茶 | `tea_jar` `tea_scoop` | SYN | 木罐启盖+茶叶沙沙 / 铜勺入壶 |
| 候汤 | `water_pour` | SA3 | 注水 one-shot 2s |
| | `boil_blip` `boil_simmer` `boil_roar` `boil_over` | SA3+SYN | 单泡/低鸣/连片滚沸/过老嘶鸣(one-shot 链调度,§3.2;**不用循环 sfx**——引擎 sfx 层无 loop) |
| | `kettle_lift` | SYN | 提壶离火蒸汽「呲」 |
| 闷泡 | `steep_rustle` | SYN | 干茶舒展沙沙(2s,低响度) |
| | `tick_slow` `tick_fast` | SYN | 木鱼滴答两档(880Hz 族;**只进关键窗**) |
| 上茶 | `pour_cup` | SA3 | 茶汤入盏+盏托轻磕 |
| 账目 | `coin_soft` `coin_stack` | SYN | 单枚铜钱/三枚铜钱落桌(plain/good);wrong=无币声(免单静默+反应句) |
| | `rep_chime` `rep_fall` | SYN | 上行/下行双音(口碑跨档瞬时标记,配合档句) |
| 仪式 | `lamp_light` `lamp_off` | SYN | 开灯「嗒」/熄灯(每晚开张与睡下) |
| | `shop_buy` `upg_install` | SYN | 算盘+钱柜抽屉 / 木工轻敲(置办) |
| 看门狗 | `turn_tick` | SYN | 880Hz 木鱼族轻响(无进展轨 L1,dungeon 配方自存一份) |
SA3 任务 ~10 个(door_bell/steps×2/water_pour/boil 家族 2 条/pour_cup);其余 SYN 兜底。
### 8.3 voice(163 句:旁白 98 ×2 性别 + NPC 平铺 65)
- **旁白**(系统/教学/状态/账目/氛围客转述):female=Serena / male=Uncle_Fu,instruct 全表统一(台词表头);数字全分档整句(st_guest 5 档/st_rep 4/st_purse 3/close_coin 3/night 6 档),无运行时拼接。
- **NPC 平铺**(弧线客人台词):5 speaker+instruct 恒定(§6.3 区分度表);不做双性别;落 `voice/` 根目录(引擎平铺回退命中)。台词全文、触发、键盘变体、多音字自查见 [20-teahouse-voice-ids.md](20-teahouse-voice-ids.md)。
- 声音演技核心:晚 3 结局句(A/B/C 三方向 ×5 客人)与晚 2 反应句的递进(故事感全在句内文本+标点引导,instruct 恒定)。
## 9. 向导层接入(engine/guide.js,不新增 earcon 词表)
### 9.1 状态签名(进入状态时播)
| 状态 | guide.state() | 时点 |
|---|---|---|
| TITLE / MENU / CLOSE 链 | `menu`(CLOSE 链完)| 进标题、开菜单、进结算 |
| OPENING / SERVE | `explore` | 开场、每位客人进门 |
| BREW | `battle` | 选茶步起(「小局起」的统一签名) |
| CLOSE 链内 | `settle` | 打烊链首 |
| danger | `danger` | rent_short 当刻(每欠账事件 1 次) |
choice 不使用(无抉择态,登记)。
### 9.2 turn cue 与看门狗(双轨——批次 1 教训固化)
| 等待点 | 机制 | at | say(full 档;第 2 级一律纯 nudge) |
|---|---|---|---|
| BREW 各子相位入口 | guide.turn | — | turn earcon + confirm 震 |
| SERVE 空闲 | 无操作轨 | [10s, 25s] | gd_serve / null |
| BREW-TEA | 无操作轨 | [12s, 30s] | gd_brew / null |
| **BREW-WATER/STEEP 时机窗内** | 只 earcon | [12s] | **语音一律不发**(§3.3 分层铁律;语音会占第 3 声流) |
| CLOSE 链完 | 无操作轨 | [15s, 35s] | gd_close / null |
| DRILL 每步 | 无进展轨 | [30/60/90s] | earcon→短句→自动替打(§5) |
### 9.3 无进展轨(营业态卡关三级——「乱按也要被营业」)
进展事件=客人相位推进(进门/点单/上茶/反应毕)/BREW 步骤推进/打烊/置办(`_progressTrack()` 挂点:各链 onComplete、判定函数、状态进入)。只由进展重置——乱按(狂切茶罐不听、反复开菜单)永远攒不满进展,三级必达:
- [45s] L1:turn_tick earcon(不占台词通道)→ [90s] L2:`hint_water`(泡茶口诀)/`gd_serve`(堂前)→ [150s] L3:**重播当前客人点单句**(BREW/堂前通用的真话提示——把线索原句还给玩家,不替选茶);L3 后每 150s 重复(每句全局限 2 次,之后静默)。
- 无操作轨与无进展轨并行取先到;两轨短句内容同级交叉登记防重复;纠错/提示 idle-only、过期丢弃(引擎已实现)。
## 10. 存档设计(跨晚进度)
```json
{
"schema": 1, "game": "teahouse", "updatedAt": 0,
"summary": "第3晚 · 客人2/4 · 口碑·有了回头客 · 存款35文 · 欠账0文",
"meta": { "drillDone": true, "nightsClosed": 2, "rep": 5, "purse": 35, "debt": 0,
"upgrades": ["cabinet"], "chapterEnd": false },
"run": { "night": 3, "guestIdx": 2,
"results": ["good", "plain"],
"incomeTonight": 5,
"guestStory": { "zhou": 1 },
"rentCharged": false }
}
```
- summary 生成规则:`第{night}晚 · 客人{guestIdx+1}/4 · 口碑·{rep 档名} · 存款{purse}文 · 欠账{debt}文`(打烊后 run 清空,summary=`第{nightsClosed}晚打烊 · 口碑·{档名} · 存款{purse}文`)。
- 保存时机:每客反应毕 / 打烊链完 / 置办后 / 菜单「保存并回大厅」。localStorage + PUT 服务器。
- 读取:有 run → TITLE 播 sys_continue_ask,单击继续 → **客人粒度恢复**(当前客人从进门链重放,已结算客人不重复)→ 局面复述链 `st_guest_n → st_rep → (BREW 则加 sig+点单句) → recap_go`,≤5s 回到可操作。右滑 ×2=重开新店(run+meta 清零,播 sys_reset_ask 二次确认)。
## 11. playtest 断言清单(登记 13 号文档新增 §teahouse;mock 对齐 web/rpg/test/playtest.mjs;一律 guide:'off')
**关键路径**(seed=42,N1-N3,≤120 手势;全章 N1-N5 ≤200):
1. 启动→TITLE(无档)→单击→OPENING(night_1):intro 三句+D0..D6 逐步 voice 序与 drillStep 递进;D2/D3 时机步双击;首晚窗口 ×1.3 断言;下滑跳过路径+meta.drillDone 二周目不再进。
2. **泡茶小局三步**:TEA 左右滑循环(wrap)+茶名句播报+单击选定→WATER 时间线(blip 间隔 700/350ms、roar 链、窗位=茶参数)→双击在窗内=water_ok/窗前=water_early/窗后=water_late;t=11s 无出手自动过老;STEEP tick 只在目标前 2.5s 起、窗内加速、同三档+超时自动出汤;判定三元组与 §3.1 映射(good/plain/wrong)逐组合注入验证(含「茶对双偏=plain」「茶错=wrong 即水闷全 ok」)。
3. **矩阵不变式**:全弧线客人×全部访问 → teaByVisit 与 teas 表参数一致;氛围客 teaPool 同;同 seed 两次构造 `run._schedule`(N6+ 轮换序)深相等。
4. **客人弧线三方向**:逐客注入三晚结果矩阵(全好/混合/全错)→ 结局句=A/B/C 与 sum 映射一致;反应句三方向与当晚结果一致(假话即失败);晚 3 结局句替换反应句路径。
5. **经济账目验算**:按 §7.5 剧本 A 逐晚走(茶种/时机注入)→ close_coin 档=逐客 pay 和;rep 跨档播报点与实值一致(含双向跌档);置办扣款与 upg 表;N3/N5 房租扣款;剧本 B:全错→免单→rent_short+danger+debt 流转+debt_clear+rep clamp 0。
6. **听觉分层**:WATER/STEEP 时机窗内 voice 播放事件=0(看门狗 suppressed 断言);语音 start 事件与 boil/tick 活跃区间零相交;语音只在步间静默点。
7. **打烊死窗+链锁**:进 CLOSE 同拍与 +300ms 各补一记在途 tap → 均被吞;结算链完整有序(close_open→coin→[rent]→[debt]→[chapter_end]→settle_night);链完成后单击=睡下→OPENING(night+1);N5 后 night_more+氛围客轮换。
8. **看门狗双轨**:SERVE 10s/25s、BREW-TEA 12s/30s;乱按 96s 零进展 → 45s earcon/90s 短句/150s 重播点单句;有真实进展零提示;BREW 时机窗内只 earcon 无语音。
9. **中断复述**:存档重进(客人粒度)→ sys_continue_ask→单击→复述链序 st_guest→st_rep→(BREW 加 sig+点单句)→recap_go;上滑同链可重放。
10. **E1 豁免**:BREW 时机步双击=提壶/出汤(非重听);选茶步双击=重听茶名句;上滑状态链第一段=sig+点单句重播;BREW 长按=error(rateLog 断言 E3)。
11. **菜单/置办/存档**:模态菜单循环-确认-关闭;CLOSE 菜单「打烊置办」二级列表;teaware 购后窗口 +0.8s 实测;sign 的 rep≥12 与 debt=0 门(upg_lock/upg_none 真话);「保存并回大厅」PUT data.summary 命中生成规则。
12. **键盘变体**:`settings.input='key'` 后播 sys_help_k/tut_water_k 等 V 组(inputMode 联动);'touch' 回基础句。
**边界断言**:
- 零惩罚:全 run 无 game over 路径;错茶免单但仍推进故事;rep clamp ≥0;purse 不透支。
- 归因真话:water/steep 三档句与注入时机严格对应;res_wrong 只在茶错时播;「没出手」归「水滚老了/闷过了」(真实:未操作)。
- SERVE 链播中单击=跳句(res_*/rent_* 不可跳)、双击=重听当前句、左右滑静默忽略;菜单关闭重播被停句。
- BREW 菜单冻结:水声时间线/滴答全停(快进虚拟时钟断言零调度);关闭恢复从冻结点续走+复述句。
- 屏蔽任意 voice 资产:链 8s 兜底推进,流程到打烊不死锁。
- guide=off:全静、零定时器;资产齐套:voice 双性别 id 集合一致+NPC 平铺存在+sfx/bgm 双格式。
- 首晚 FTUE:首输入 <60s(D0 ≈t+20s);首正反馈 ≤3min(D4 老周反应)。
**失败即不通过**:归因假话(档位句/结局句/反应句与数据实值不符);点单句与 teaByVisit 矛盾;同 seed 两次构造不一致;教学计入惩罚;CLOSE 链被手势截杀;时机窗内出现语音;免费重听(状态链)被收费或受限。
## 12. 节奏曲线(一晚/一弧线两级)
### 一晚(单局 13-17 分钟;首晚 17-20)
| 阶段 | 时长 | 内容 | 奖励点(≤60s 一个) |
|---|---|---|---|
| 开场 | 0:20-0:35 | 点灯+night 句(首晚 intro+教学) | — |
| 客人 ×4 | 各 2.5-4 分钟 | 进门 15s→点单 20s→泡茶 45-75s→反应 25s | 每步 water_ok/steep_ok 即时确认;res 三档;反应句+币声;口碑跨档 chime |
| 打烊 | 1:30 | 账目链→(房租/欠账)→(置办)→睡下 | 账目+置办+settle 钩子 |
- 每位客人=一个完整起承转合(P3 三分钟颗粒:任意客人结算后退出,回来一句话接上)。
- 紧张度曲线温和:泡茶小局是每 3 分钟一个的「微专注峰」(时机步),其余是聆听叙事谷——峰谷交替,不疲劳(P4)。
### 一条弧线(3 晚,跨局)
晚 1 相遇(立谜:他是谁/他要什么)→ 晚 2 深入(话头展开+方向累计)→ 晚 3 收束(结局三方向)。跨晚钩子=反应句留白(「儿子的事,改天再说吧」)+ 结算 settle_night「明晚,茶馆还等你开门」;5 晚后 chapter_end 收第一章,无尽营业+二周目变体空间(氛围客 seed 轮换)。
## 13. 自检清单
| # | 硬约束/教训 | 自检 |
|---|---|---|
| 1 | FTUE 首输入 <60s | D0 ≈t+20s ✓(§5) |
| 2 | 首正反馈 ≤3min | D4 老周反应 ≈t+2.5-3min(首晚宽窗保送好茶)✓ |
| 3 | 学习期零惩罚 | 首晚窗口 ×1.3+教学明示茶名;全域无 game over;错茶免单非死亡 ✓ |
| 4 | 失败三问归因+真话律 | 水闷各三档句按真实时机;res_wrong 只在茶错;「没出手」归「滚老/闷过」;§11 失败项锁定 ✓ |
| 5 | 手势宪法三件套不豁免 | 上滑状态/下滑菜单/双击重听全状态保留(时机步双击偏离=豁免 E1 登记+教学讲清+状态链承接重听)✓ |
| 6 | 教学承诺兑现 | tut_water/tut_steep 承诺的双击时机语义正片恒成立;settle_night「单击睡下」死窗+链锁后言行一致;upg 句报价=扣款 ✓ |
| 7 | 结算链完整 | CLOSE 800ms 死窗+链锁(dungeon H1 内化)✓(§4.4) |
| 8 | 档位措辞真实 | §7.3 表:每句措辞↔阈值区间一一映射;跨档双向播报;播报值=运行值(radio rep 教训+经营玩家对账最敏感)✓ |
| 9 | 经济账目验算 | §7.5 剧本 A 五晚逐晚验算(27/23/28/25/33 收入、rep 0→12、purse 0→49、3A+2B)+ §7.6 剧本 B 欠账可达 ✓ |
| 10 | 弧线三方向可走通 | sum 映射 A(≥2)/B(−1..1)/C(≤−2);每客注入全好/全错/混合三路径(§11.4);茶柜锁=设计内经营重量(剧本 A 证明全 A 可达)✓ |
| 11 | 听觉负荷(本作特有风险) | 三重音时间串行零重叠;语音只在步间;滴答只进关键窗;时机窗内看门狗只 earcon;频带分离;并发声流恒 ≤2(§3.3 表+断言 6)✓ |
| 12 | 信息密度 | 列表逐项预览(茶罐循环一次一罐一句);状态链 ≤4 段+需求重播;客人链句粒度可停可跳可重听 ✓ |
| 13 | 向导层 | 签名 5 态(choice 登记不用);双轨看门狗(乱按必被抢救+时机窗静默特例);提示 idle-only/queue/onceKey ✓(§9) |
| 14 | seed 可复现 | mulberry32+opts.seed;N1-N5 表驱动剧本夜;N6+ 轮换洗牌全 PRNG+深相等断言 ✓ |
| 15 | P1 视障 | 双击=即时时机键(读屏手速友好);状态链=需求+第几位+口碑+存款随时可查;账目真实;5 音色群像+sig 三层冗余认人;2.2× 语速引擎既有 ✓ |
| 16 | P3 通勤 | 每客人 2-4 分钟完整颗粒;中断复述「今晚第几位/口碑档」;菜单随时存档退出 ✓ |
| 17 | P4 工人 | 零新手势;时机窗 ±1.5s 宽+超时自动继续(绝不卡死不挨骂);错茶故事照样走 ✓ |
| 18 | P2 大学生 | 弧线三方向收集+章节完结+升级树+招牌追求(rep≥12)✓ |
| 19 | 台词规范 | 163 句 ≤170;全句 ≤40 字(实测 ≤36);数字全分档整句(guest 5/rep 4/purse 3/coin 3/night 6);「重新听」写法;同角色 speaker+instruct 恒定 ✓(台词表) |
| 20 | 键盘通道 | V 组 10 变体集中登记,inputMode() 选播;方向键/空格/回车全手势可达(§5.5 平行通道,游戏层零改动)✓ |
| 21 | 引擎能力边界 | 无实时节点(one-shot 链+setTimeout 调度);sfx 无 loop 需求(调度链实现);tap 延迟只用于非即时;资产缺失静默跳过+8s 兜底;30MB 预算内 ✓ |
| 22 | 密度下限(dungeon D0-3 教训) | 一晚=固定客序节拍器(结构性密度);营业态无进展轨兜底;客人间隙 1.2s 自动推进无真空 ✓ |