merge: 主角增益只续时不叠层批落籍(台账 102,让号注记)

冲突解式:与伏击退役/格面资源八型批(3468066)双向共存——
- status_effects.tres:attack_up/ac_up refresh(本批)+ ambush 删行/alert 进(八型批)
- 增益状态 v0.11(八型,原分支报 v0.8 旧基线编号顺延)/v0.12(本批续时)
- registry:alert 行 + attack_up/ac_up refresh 两行并存
- active.md 台账 101(伏击/八型)+102(本批,让号)
- 合并后冒烟 355 项 0 失败三闸全过
This commit is contained in:
DKChan committed 2026-09-20 04:16:58 +08:00
commit 867e12da3b
13 files changed
+1148 -37

No files matched your search

+51
View File
@@ -0,0 +1,51 @@
# 美术资源清单与缺口
> 目的:表现层升级批(棋盘/敌人/节点图从平面控件占位换贴图渲染)所需的全部美术资产的单一登记处——名字、要什么、风格要求、出法、状态。随批更新状态列,做完不删行、改状态。
> 关联:[04-美术音频方向](../gdd/04-美术音频方向.md) · [art-bible](art-bible.md)(色板/形状语言/图标键契约 §4.6/格子样张验收)· [战斗表现](../gdd/systems/战斗循环/战斗表现.md)(样张硬前置与输入清单)· [HUD框架](../gdd/systems/表现与支撑/HUD框架.md)
> 建立:2026-09-18(表现层升级批前置盘点)
## 风格基调(所有资产共用,细节以 art-bible 为准)
- **一句话**:轻快明亮的像素幻想冒险风,全年龄、非暗黑,角色 2~3 头身;明亮为皮、对比为骨。
- **数字可读性第一**:一切视觉让位雷图数字辨识;格内绘制优先级固定 数字 > 小人标记 > 旗 > 徽章 > 变异纹理 > 底色,任何元素不得遮挡数字。
- **危险双通道**:一切危险/奖励状态必须「形状 + 颜色」双通道冗余,色弱可辨;装饰不得伪装成逻辑差异。
- **换色板优先**:新关卡/新变异先做色板变体,不新增资产。
- **参考**(`design/art/references/` 有截图):Into the Breach 取网格信息分层与「预告画在目标格上」;Moonlighter 取暖砖质感;Peglin 取明快全年龄色彩。
- **音频**:未定稿,MVP 占位音效即可,不在本清单。
## 生产渠道分工
| 渠道 | 出什么 | 备注 |
|---|---|---|
| ✦ ComfyUI(用户自跑) | 角色、插画级素材 | 已有先例:`samples/hero-standing-pose.png` |
| ⚙ 脚本管线 | 图标、格面、样张类精度资产 | 已有先例:格子样张已过、砖面形态与色板冻结 |
## 通用规格纪律
- 全部尺寸依赖**分辨率档位**(固定几档、窗口不可调、格边长按档位计算——两档定值旧条款已裁决作废)。档位尚未拍板(建议 1280×800 + 1920×1080),**拍板前所有像素尺寸只给工作假设**,档位定稿批统一换算。
- 交付格式建议 PNG 透明底;动画用序列帧或精灵表(SpriteFrames),帧数规格随样张批定。
- 程序化占位是现行结构冻结条款:资产未就位的槽位保持占位渲染,不空窗。
## 清单
| 优先级 | 资产 | 要什么 | 风格与需求要点 | 出法 | 状态 |
|---|---|---|---|---|---|
| **P0** | 战斗一屏样张 2–3 版候选 | 按双舞台布局(战斗画面与扫雷图同屏常驻)出整屏候选图 | 锁四件事:角色剪影方向、动画方案、战斗空间、敌人层绘制优先级插入位置;顺带裁决**敌人卡形态**(卡片式 vs 站桩式)。验收标准已成文于战斗表现「一屏样张的验收标准」;格子部分按已冻结的砖面/色板出 | ⚙+✦ | 未开始(表现层升级批与终稿资产的硬前置) |
| P1 | 主角战斗小人 | 待机/攻击/受击三态起步 | 2~3 头身像素幻想、明亮暖色;与站姿样张(已有)同形象延续;尺寸随分辨率档位 | ✦ | 站姿样张已有,三态未做 |
| P1 | 六敌种形象 | 地精 / 熊地精 / 食人魔酋长 / 巨蜘蛛 / 兄弟精(= 熊地精变体:换色板+前后缀,不换词根)/ 蛛化卓尔精灵(Boss,大体型) | 敌种间**剪影可辨**(形状+色相双通道、映射按敌种全局恒定不重掷);Boss 体型差要一眼读出强度档;死亡禁瞬消(灰化+碎裂退场,语义已定稿) | ✦ | 未开始 |
| P2 | 意图准备动画三档 | ① 普通攻击 = 常态待机(待机即预示,无需独立资产);② 攻击技能 = 特殊准备动画(放光/高举武器);③ 重击与硬化类 = 蓄力动作或防御姿态 | **不显示文字与技能名**(2026-09-18 拍板,替代现文字徽标);每敌种一套还是通用骨架换色 → 样张批定;文档落点 = 战斗表现 + HUD框架(普攻零表示 → 常态即预示) | ✦ | 未开始(样张后终稿) |
| P2 | 格面资源图标 | 七型正负共 14 枚:增伤/护甲强化/恢复/爆裂粉尘/削弱/穿刺/魔法(负向:反噬/伏击加层/恢复反噬/削弱反噬/穿刺陷阱/魔法反噬等,负向现行 weight=0 仍需徽标用于踩雷反噬呈现) | 键契约已冻结(art-bible §4.6);不得压数字对比度;形状+颜色双通道 | ⚙ | 未开始(程序化占位可用) |
| P2 | 关卡节点图资产 | 四类节点图标(战斗/奖励/恢复/Boss)+ 行进器形象 | 方块地牢观感(关卡节点地图 v1.0 定稿语);节点类型形状可辨、已走/当前/可选三态 | ⚙/✦ | 未开始(正式 UI 设计未成文,占位够试玩) |
| P3 | 战斗演出起步三类 | 受击反馈 / 死亡表现 / 顺位标记 | 敌人系统登记的资产需求下限三类;死亡=灰化+碎裂退场;顺位标记保证攻击顺位可读 | ✦ | 未开始(样张后终稿) |
| P3 | 连锁坍塌显形演出 | 连锁展开触发的连锁演出 | 与音频方向同批配对登记;打磨项,文档标注排后 | ✦ | 未开始 |
| P3 | 雷/旗/数字格面像素化 | 覆尘砖/碎裂砖/巢穴雷格/旗的终稿质感 | 砖面形态与色板已冻结(格子样张已过),只差终稿精度渲染;打磨项排后 | ⚙ | 冻结形态已有,终稿未做 |
## 依赖关系
- P0 样张 → 一票否决后面所有终稿资产(意图动画/演出三类/敌人卡形态)。
- P1 角色 → 表现层升级批的开工前提(没贴图就没得挂)。
- 分辨率档位拍板 → 全部像素尺寸冻结。
## 更新纪律
状态列随批更新(未开始 / 候选已出 / 已裁决 / 已交付);新增资产行走本文修订;做完不删行。与 06-待办清单的联动:本文件是资产维度明细,06 只留指路存根。
-8
View File
@@ -143,14 +143,6 @@
### 增益状态
#### 叠层不续命的读感
**现状**:同种状态叠层只加层数、剩余次数不动("重复拿同款不续命")。旧体系把这条登记为试玩证伪项(配套教学口径"同轮拿满优于跨轮叠"),实测是否读得懂、要不要改成叠层顺带续命,尚未执行、尚未裁决
**归属**:增益状态(随批实测裁决)
**状态**:待办
#### 削弱档位的最终数值
**现状**:削弱取值域 [60,85] 与投值 −65 来自旧体系裁决;"标中旗必须比随便挖一格更值"的当量终值由[战斗结算](systems/战斗循环/战斗结算.md)与[地图战斗资源](systems/战斗循环/地图战斗资源.md)共裁,尚未闭合。**语义侧已定案(2026-09-18 盘问会话,结构修复批落地)**:削弱叠层改续时——同名重复授予只刷新剩余结算数、层数恒 1(结构性消饱和,×2 叠满池触底 ×0 的免伤轮从根杜绝);现行表值为临时值(provisional),duration 终值与当量锚复算归状态层重设计批
+11 -10
View File
@@ -8,7 +8,7 @@
战斗里有一类效果不在当场一次性用掉,而要管上几次结算:挖开安全格拿到的主角增益、标中旗带来的怪物削弱、踩雷喂给怪物的增强、标错旗招来的反噬,都是这类。本文把它们统称"状态":发给主角的有益效果叫增益(标错反噬的失衡是个例外——它是发给主角的减益),发给敌人的负面效果叫减益;惊动巢穴或反噬喂给怪物的增强同样是状态——几个方向共用一本账。
增益状态就是这本账:一个容器收下全部状态,用同一套规矩管理——发入、叠层(同一种效果重复拿到时层数加一)、衰减(每次结算后剩余次数减一,减到零效果消失)、清空(战斗结束全部清除)。没有它,几类效果得各写一套计时逻辑,结算明细也无法逐行指回"这效果是我哪步棋带来的"。容器管机制、不管数值从哪来:某个效果该多大,由各收益系统的表去定,容器只照章入账、按次衰减。
增益状态就是这本账:一个容器收下全部状态,用同一套规矩管理——发入、合并(同一种效果重复拿到时按表行策略处理:叠层加一,或只刷新剩余次数——读 `status_effects.tres` 逐行 stack_policy)、衰减(每次结算后剩余次数减一,减到零效果消失)、清空(战斗结束全部清除)。没有它,几类效果得各写一套计时逻辑,结算明细也无法逐行指回"这效果是我哪步棋带来的"。容器管机制、不管数值从哪来:某个效果该多大,由各收益系统的表去定,容器只照章入账、按次衰减。
## 系统范围
@@ -84,7 +84,7 @@
| 合并策略 | 重复授予时发生什么 | 说明 |
|---|---|---|
| 叠加 | 层数加一;剩余结算次数不动——只有首次授予定钟 | 现行内容行多数用叠加(逐行合并策略读 `status_effects.tres`) |
| 刷新 | 剩余结算次数重置为该实例首次授予时的初始值,层数不变 | 刷新类内容行已就位(增益技行 empower / fortify、削弱行 weaken——2026-09-18 续时定案;逐行读 `status_effects.tres`) |
| 刷新 | 剩余结算次数重置为该实例首次授予时的初始值,层数不变 | 刷新类内容行已就位——削弱行 weaken(2026-09-18 续时定案)、增益技行 empower / fortify、**主角增益行 attack_up / ac_up(2026-09-20 用户拍板「只续时不叠层」,全状态表增益/减益两侧合并语义就此统一为:主角可重复获取的增益与减益一律续时、不叠层)**;逐行读 `status_effects.tres` |
| 并存 | 新建一份独立实例,两份各算各的 | 同上 |
并存分支没有满层上限,但容器规模天然有界:实例数的上界就是受理过的授予数——多受理一份就多一份实例,多少份在授予那一刻就完全确定,不会无限膨胀。
@@ -97,7 +97,7 @@
### 剩余次数怎么倒数:按结算次数衰减
每个状态实例自带一个倒数计数——剩余结算次数(本文说的"衰减"就是它逐次递减、归零消失)。它不承诺"活几轮",而是数"经历过几次轮末结算":每轮结算先让状态起作用,随后计数减一,减到零状态即被移除。持续 1 的状态就是"一次性":在授予它的那轮结算里生效一次,轮末消失。MVP 时期六行内容均为一次性(削弱后改续时——见版本历史);跨轮持续的状态,寿命由表行初始值表达,给几就活几次结算。
每个状态实例自带一个倒数计数——剩余结算次数(本文说的"衰减"就是它逐次递减、归零消失)。它不承诺"活几轮",而是数"经历过几次轮末结算":每轮结算先让状态起作用,随后计数减一,减到零状态即被移除。持续 1 的状态就是"一次性":在授予它的那轮结算里生效一次,轮末消失。MVP 时期六行内容均为一次性(削弱后改续时——见版本历史;2026-09-20 起主角增益两行也走续时、duration 表值仍为 1——重复拿等于重新获得一次当轮增益);跨轮持续的状态,寿命由表行初始值表达,给几就活几次结算。
```
一轮结算:查询生效清单 → 逐行兑付(层数 × 行值)→ 轮末衰减(全部实例剩余次数 −1)→ 归零实例移除
@@ -115,7 +115,7 @@
### 幅度与量纲:容器只做加法,换算归结算
容器对每个状态只记两件数值的事:幅度(一个整数)和量纲(百分比还是固定值)。百分比量纲的叠层是纯加法——两层合计 = 2 × 单行幅度(读 `status_effects.tres` attack_up 行),不是 1.5 的平方;固定值量纲几层就乘几。
容器对每个状态只记两件数值的事:幅度(一个整数)和量纲(百分比还是固定值)。百分比量纲的叠层是纯加法——两层合计 = 2 × 单行幅度(叠层策略行,读 `status_effects.tres` 暴走 enrage 行),不是 1.5 的平方;固定值量纲几层就乘几。
**结论**:容器输出的有效值 = 层数 × 行值,原样给出、不封顶不保底;把百分比合计换算成乘数、并在 −100 个百分点处设地板,是[战斗结算](战斗结算.md)的消费侧规则——地板保证减益不会把属性打到绝对负值,最低压到"归零"为止。
@@ -128,7 +128,7 @@
| 例子 | 容器输出 | 消费侧读法 |
|---|---|---|
| 暴走叠两层 | +(2 × enrage 行幅度)(读表;越出单行取值域,原样输出) | 压在天花板 +100% 上:敌方输出乘区封顶 ×2(削弱已改续时——"叠两层压地板 −100% 归零"的读法随 2026-09-18 结构修复批退役,见版本历史) |
| 主角护甲强化叠两层 | 每层 +1 AC(读 ac_up 行)× 2 层 | 不经任何池:掷点判定阈值 = 主角基准(读 hero 表)+ 层数 |
| 主角护甲强化再拿一份 | 层数恒 1、剩余结算次数重置(refresh——2026-09-20 主角增益续时批) | 不经任何池:掷点判定阈值 = 主角基准(读 hero 表)+ 层数(现行 +1——上限 2 层叠读取法退役,局内可达 AC 上限 11) |
容器还有一条快照纪律:实例的幅度、初始次数、量纲在授予那一刻从表行拷贝。战斗中配置表即使被重载,已授予实例不受任何影响,只影响后续授予。
@@ -217,12 +217,12 @@ empower 与 fortify 是敌方技能池增益技在容器侧的数据落点(技
| sapped 幅度 | 百分比 [−100,100] 且非 0 | percent 行 magnitude | 乏力;雷格负向 weaken 型,进主角输出修正池(2026-09-15 格面资源批补登记) |
| empower 幅度 | 百分比 [−100,100] 且非 0 | percent 行 magnitude | 蓄力;敌方技能池增益技载体,进敌方输出修正池 |
| fortify 幅度 | 百分比 [−100,100] 且非 0 | percent 行 magnitude | 硬化;敌方技能池增益技载体,进**敌方防御池 enemy_defense**(负值 = 减伤方向——2026-09-18 符号纠正) |
| 初始剩余次数 | 整数 [1,99] | duration_settlements | 六行一次性语义;weaken 与 empower/fortify duration 读表(weaken 续时 = 2026-09-18 定案;empower/fortify = 1 个有效增益拍——先兑付后衰减含施放当轮);拉长 = 恢复跨轮延续、规划变简单 |
| 叠层上限 | 整数 [1,16] | max_stack | 仅叠加策略消费;刷新行层数恒 1——weaken 表值上限在续时语义下不消费(2026-09-18),empower/fortify ×1(冷却闸下不可能自叠加) |
| 初始剩余次数 | 整数 [1,99] | duration_settlements | 一次性语义行逐行读表;续时行 = weaken(2026-09-18 定案,duration 2)+ empower/fortify(1 个有效增益拍——先兑付后衰减含施放当轮)+ **attack_up / ac_up(2026-09-20 主角增益续时批,duration 表值 1 维持——续时语义在 dur=1 下表现为重复拿重置当轮倒数;跨轮延续随将来 duration 拉长自然显形,数值归状态层重设计批)**;拉长 = 恢复跨轮延续、规划变简单 |
| 叠层上限 | 整数 [1,16] | max_stack | 仅叠加策略消费;刷新行层数恒 1——weaken / attack_up / ac_up 表值上限在续时语义下不消费(2026-09-18 / 2026-09-20),empower/fortify ×1(冷却闸下不可能自叠加) |
非调参的冻结项:三类合并策略语义、两种量纲语义、来源类别枚举、"先兑付后衰减"时序、拒绝原子性、零随机——改动走本文修订流程,不走调参。
联动纪律:增伤与削弱是当量锚的两端;护甲强化与[难度曲线与Boss](../冒险循环/难度曲线与Boss.md)的承伤预期联动(掷点折扣轴——AC 行值变更须复算生存链区间);削弱改续时后"单轮层数上限受[行动经济](../排雷循环/行动经济.md)行动点约束"的联动随之失效(2026-09-18 续时定案——同名重复标中只刷新剩余次数、层数恒 1)。这些联动值禁止独立调参,修订须重跑锚对照并同步 registry。
联动纪律:增伤与削弱是当量锚的两端;护甲强化与[难度曲线与Boss](../冒险循环/难度曲线与Boss.md)的承伤预期联动(掷点折扣轴——AC 行值变更须复算生存链区间;2026-09-20 主角增益续时批后 ac_up 层数恒 1、局内可达 AC 上限 11,复算随调参批);削弱改续时后"单轮层数上限受[行动经济](../排雷循环/行动经济.md)行动点约束"的联动随之失效(2026-09-18 续时定案——同名重复标中只刷新剩余次数、层数恒 1;2026-09-20 起主角侧 attack_up / ac_up 同口径)。这些联动值禁止独立调参,修订须重跑锚对照并同步 registry。
## 验收标准
@@ -230,7 +230,7 @@ empower 与 fortify 是敌方技能池增益技在容器侧的数据落点(技
- 多向同构:主角侧增益与减益、敌方侧增强与削弱共用同一套受理、合并、倒数、清除语义,不存在第二套计时逻辑。
- 授予即生效:状态发入当轮结算即兑付第一次,无"待生效"中间态。
- 只记账不去重:同一事实被转化两次授予,入账两层——去重责任在战斗结算。
- 叠层不减钟:叠加只加层数,剩余次数保持首次授予定下的轨迹不变。
- 叠层不减钟:叠加策略行叠加只加层数,剩余次数保持首次授予定下的轨迹不变(刷新策略行则相反——层数不变、只重置剩余次数;两策略逐行读表)。
- 满层拒绝原子且留痕:叠满后再授予返回失败、容器逐字不变;结算明细多一行"奖励未生效"(含来源)。
- 先兑付后衰减:每轮结算恰做一次衰减,归零实例当轮移除;停手轮、弃图刷新轮照常衰减。
- 合成不收口:容器输出的有效值恒等于层数 × 行值,越出百分比域不封顶不保底;地板在战斗结算侧。
@@ -255,4 +255,5 @@ empower 与 fortify 是敌方技能池增益技在容器侧的数据落点(技
| v0.8 | 2026-09-17 | **数值纪律收口批:正文与调参表 knob 现行值改指路存根(事实源 `data/tables/*.tres` 与 registry),8 处失同步值修正**——幅度例"两层 +50% 合计 +100"改"2 × 单行幅度(读表)";削弱例"−130 个百分点"改"−(2 × weaken 行幅度)(读表)";护甲例"AC10 → AC12(期望减免 21.25% → 28.75%)"改"基准 AC(读 hero 表)+ 层数"、派生读数删除;状态行表"时限/合并"列 1 次/×2/×16/×1 字面量改读表措辞;defense_up 退役条目删"−30%"数值;"两行 duration = 2"改"duration 表值(读表)";empower"×2"幅度与调参表"AC10 → 11 → 12"、"2 次 = 1 个有效增益拍"同步指路化 |
| v0.9 | 2026-09-18 | **战斗数值结构修复批(2026-09-18 盘问会话用户拍板,与战斗结算 / registry / 切片代码同批)**:三行语义改写(数值全部 provisional 归状态层重设计批)——① off_guard(失衡)换装 AC 轴:unit percent→ac、退出 hero_defense 池(effect_pool_map 删键,池清空结构保留),状态行表与调参表同步,"标错反噬三池"措辞改"三行";② fortify(硬化)符号纠正:旧正值入池实际 ×2 翻倍与"硬化=减伤"语义相反,改负值后主角攻击折半(正负号语义成文:负值 = 减伤方向);③ weaken(削弱)叠层改续时:stack→refresh、duration 表值 2——同名重复授予只刷新剩余次数、层数恒 1,×2 叠满池触底 ×0 的免伤轮结构性根治;消费侧例子表"削弱叠两层压地板"改"暴走叠两层封顶 ×2"(削弱叠层读法退役);"叠层不续命"对削弱不再适用,行动经济联动句随之失效;调参表一次性/叠层上限两行措辞同步 |
| v0.10 | 2026-09-19 | **技能池新效应词汇批(用户拍板——设计权威 docs/proposal-status-vocabulary.md v1.0,与 敌人系统 / 战斗结算 / registry / 切片代码同批)**:off_guard(失衡)新增第二来源类别 = 敌方技能施放(妨害技"蛛网束缚"的容器落点——首实装于 L2 Boss 蛛化卓尔精灵池;duration 由技能行 buff_duration=2 覆盖 = 1 个有效结算,empower/fortify 同款口径);容器语义零改动——同构实例、side 路由照常,妨害技零新状态行(乏力 sapped 留作妨害第二词汇,暂无载体) |
| v0.8 | 2026-09-20 | **格面资源八型批(用户拍板——与敌人系统 / 战斗结算 / registry / 切片代码同批)**:① 状态行表 ambush 行 → alert 警觉行(敌方护甲等级 +1,ac 量纲,side-wide);② 标空旗路由措辞纠正(2026-09-15 极性矩阵后已无三选一反噬,本批顺手收口);③ 敌人系统的伏击量纲定义/上限锚义务面随伏击退役移除 |
| v0.11 | 2026-09-20 | **格面资源八型批(用户拍板——与敌人系统 / 战斗结算 / registry / 切片代码同批)**:① 状态行表 ambush 行 → alert 警觉行(敌方护甲等级 +1,ac 量纲,side-wide);② 标空旗路由措辞纠正(2026-09-15 极性矩阵后已无三选一反噬,本批顺手收口);③ 敌人系统的伏击量纲定义/上限锚义务面随伏击退役移除 |
| v0.12 | 2026-09-20 | **主角增益只续时不叠层批(用户拍板「主角的其实也一样,都是按照叙事的方式,不要有叠层;只续时不叠层,变相削弱主角性能可接受」;与 status_effects.tres / smoke / registry / 06 清单同批)**:① attack_up(增伤)/ ac_up(护甲强化)两行 stack_policy stack→refresh——重复授予层数恒 1、剩余结算次数重置,对齐削弱 2026-09-18 续时定案;至此主角可重复获取的增益与减益合并语义统一(叠层策略仅剩敌侧 alert / enrage / off_guard / sapped 等行);② duration 表值 1 与 max_stack 2 不动(refresh 下 max_stack 不消费——weaken 先例;dur=1 下续时表现为重复拿重置当轮倒数,跨轮延续随将来 duration 拉长自然显形,数值归状态层重设计批);③ 影响面:增伤不再 +100%(hero_offense 池单层封顶 +50)、护甲强化不再 +2 AC(局内可达 AC 上限 11,AC12 折扣档采样探针随行降为 AC11)、这两行不再可达满层拒绝行;④ 同名状态合并策略表/幅度量纲例子表/调参表两行/联动纪律句/验收"叠层不减钟"条改述;06 清单「叠层不续命的读感」条目解决移除;冒烟三闸全过(ac_up 行断言与 AC 探针改形,无净增断言) |
+2 -2
View File
@@ -128,8 +128,8 @@ entities:
stack_policy: enum {stack, refresh, independent}
max_stack: int [1,16](仅 stack 消费——refresh/independent 行内容约定恒 1,非校验项)
mvp_content:
attack_up: { display_name: 增伤, target_side: hero, unit: percent, duration_settlements: 1, max_stack: 2, stack_policy: stack, source_class: safe_cell, magnitude_ref: data/tables/status_effects.tres } # 2026-09-17 数值压缩批·文档同步:magnitude 从现行值列改指路存根(数值事实源 = data/tables/status_effects.tres);schema 字段保留以承载元数据
ac_up: { display_name: 护甲强化, target_side: hero, unit: ac, duration_settlements: 1, max_stack: 2, stack_policy: stack, source_class: safe_cell, magnitude_ref: data/tables/status_effects.tres } # 2026-09-16 护甲等级掷点批换装(原 defense_up 减伤 −30 percent ×2 层整行退役、无双轨——unit=ac 新量纲〔护甲等级阈值轴 [−20,20] 且非 0〕,不入 effect_pool_map 任何池,消费面 = 战斗结算掷点判定);2026-09-17 数值压缩批:magnitude 改指路存根
attack_up: { display_name: 增伤, target_side: hero, unit: percent, duration_settlements: 1, max_stack: 2, stack_policy: refresh, source_class: safe_cell, magnitude_ref: data/tables/status_effects.tres } # 2026-09-17 数值压缩批·文档同步:magnitude 从现行值列改指路存根(数值事实源 = data/tables/status_effects.tres);**2026-09-20 主角增益续时批:stack→refresh(层数恒 1、重复授予重置剩余结算数——max_stack 不消费)**
ac_up: { display_name: 护甲强化, target_side: hero, unit: ac, duration_settlements: 1, max_stack: 2, stack_policy: refresh, source_class: safe_cell, magnitude_ref: data/tables/status_effects.tres } # 2026-09-16 护甲等级掷点批换装(原 defense_up 减伤 −30 percent ×2 层整行退役、无双轨——unit=ac 新量纲〔护甲等级阈值轴 [−20,20] 且非 0〕,不入 effect_pool_map 任何池,消费面 = 战斗结算掷点判定);2026-09-17 数值压缩批:magnitude 改指路存根;**2026-09-20 主角增益续时批:stack→refresh(层数恒 1——局内可达 AC 上限 11,原 ×2 层叠读取法退役)**
alert: { display_name: 警觉(敌方护甲等级 +1), target_side: enemy, unit: ac, duration_settlements: 1, max_stack: 16, stack_policy: stack, source_class: mine_hit, magnitude_ref: data/tables/status_effects.tres } # 2026-09-20 格面资源八型批:ambush 行(flat 伏击)退役换装 alert 行——敌方护甲等级 +1/层(unit ac、target_side enemy、duration 1 结算、stack 16,side-wide 入增益状态容器),消费 = 战斗结算 _defender_ac 敌方侧 ac 型读法(本批接线);数值 provisional 归 难度曲线与Boss;原 ambush 行 2026-09-17 数值压缩批注记随行退役(留痕归 git)
weaken: { display_name: 削弱(标中旗 debuff), target_side: enemy, unit: percent, duration_settlements: 2, max_stack: 16, stack_policy: refresh, source_class: flag_hit, magnitude_ref: data/tables/status_effects.tres } # 2026-09-17 数值压缩批:magnitude 改指路存根;**2026-09-18 结构修复批:叠层改续时——stack→refresh · duration 1→2**〔同名重复授予只刷新剩余结算数、层数恒 1——结构性消饱和,×2 叠满池触底 ×0 免伤轮根治;表值上限 16 在续时语义下不消费;duration 终值 provisional 归 状态层重设计批〕
enrage: { display_name: 暴走(敌方增伤), target_side: enemy, unit: percent, duration_settlements: 1, max_stack: 16, stack_policy: stack, source_class: flag_miss, magnitude_ref: data/tables/status_effects.tres } # 2026-09-12 标错反噬批上线——三池之一(进 enemy_output 池);2026-09-17 数值压缩批:magnitude 改指路存根
@@ -0,0 +1,102 @@
# 提案:第三关内容批预案(幽暗地域深层)
> 日期:2026-09-20
> 性质:设计预案(只读提案,未拍板、未动任何表与代码,未提交 git)
> 依据:难度曲线与Boss 关间台阶纪律、分支节点图模板、甲效矩阵现行值、地形变异首批框架、06 待办清单关联条目
> 行值纪律:本文只给**候选锚点与取值域**供拍板;正式行值一律归 难度曲线与Boss 投值批落表(enemy/board_gen/skills/variation/level 各表),不在此双写。
## 0. 一句话结论
第三关建议定位为「幽暗地域最深层」:主题 = **灰矮人矿城**(DND 灰矮人 duergar,补上"重甲"这一档克制教学),新敌种灰矮人 + 钩爪恐魔,Boss 用专属妨害技首发第二妨害词汇(乏力);扫雷面加难走「板面加大 + 第三档伤害地形」,密度维持 0.25。**最关键的前置裁决不是怪物,而是玩家成长侧**——现行主角属性从第一关到第三关零成长(攻击恒表值、只有大奖励回血),按现行基线第三关必是红档;建议把已登记的「冒险内成长(GP + 商店房)」提案从 Alpha 提前,与第三关内容批**捆绑立项**。
## 1. 关卡定位与地域设定
| 项 | 现行前两关 | 第三关候选 |
|---|---|---|
| 层名 | 第一层·苔藓回廊 / 第二层·幽暗地域 | 第三层·**灰矮人矿城**(候选名,待拍板定名) |
| board_type 词表 | dungeon / underdark | 新增第三值:`deep_underdark`(显示名候选「灰矮人矿道」)——词表扩一位,走 棋盘生成 文档修订 |
| 设定锚 | 地精部族骚扰表层 → 幽暗地域(熊地精部族、蛛群、卓尔裔) | 幽暗地域更深处:灰矮人奴役史与矿城遗迹。灰矮人是 DND 幽暗地域经典种族(被夺心魔奴役出身的侏儒亚种),恰承载"重甲工匠"意象 |
| 敌种生态叙事 | 部族伏击手 + 蛛群 + 蛛化卓尔 | 矿城守军(灰矮人)+ 洞窟捕食者(钩爪恐魔)+ 矿城之主 |
主题备选(拍板点 1):
- **A. 灰矮人矿城(推荐)**:唯一能自然落地"重甲教学"的选项,见 §2 克制面论证。
- B. 蕈林(真菌洞窟,DND 蕈人/孢子意象):与第一关"苔藓"意象重复度高,且真菌系敌种偏轻甲,克制教学断档。
- C. 黑暗湖鱼蛙人(kuo-toa):群像好但主题自成一派,重甲面同样立不起来。
## 2. 怪物设计
### 2.1 新敌种两枚 + Boss 一枚(每节点恒单敌种,遵守"同深度混搭不做"现行约束)
| 敌种(候选键) | 显示名 | 定位 | 数量 | 护甲(候选) | 技能池轮廓(权重候选) |
|---|---|---|---|---|---|
| duergar | 灰矮人 | 单体重甲中坚(L2 熊地精生态位的关间台阶) | 1(小队行 [2,3]) | **heavy 重甲** | 普攻 6 / 蓄力 2 / 重击 2(复用共享技能行,零新行) |
| hook_horror | 钩爪恐魔 | 群行捕食者(沿袭巨蜘蛛的群行倾向形态) | 首遇位固定 2(教学位纪律),后续 [2,3] | **light 轻甲** | 普攻 6 / 撕咬 2 / 蓄力 1(复用 bite 共享行——lunge 已有兄弟精复用先例,合法) |
| duergar_king | 灰矮人石君王(候选名,待拍板) | Boss,本关最大单场消耗 | 1 | **heavy 重甲** | 普攻 6 / 重击 2 / **独占技「大地脉动」2**(新技能行,见 2.2) |
克制面交错论证(这是选灰矮人的核心理由):甲效矩阵现行值(settlement.tres)= 普通攻击克魔法甲、被重甲克(−1);魔法克重甲(+1);穿刺克魔法甲、被轻甲克。现行主角 attack_type = normal 且冒险内不可换——**若 L3 全场重甲,主角基础分量全程 −1,必成配置事故**。所以 L3 必须重轻错开:重甲灰矮人承担"重甲首次登台",轻甲钩爪恐魔保证穿刺/普通分量仍有用武之地,Boss 重甲收束教学梯度(轻甲→魔法甲→重甲,第三档在此补完)。配套联动见 §5-②。
### 2.2 关间台阶纪律的双半兑现
- **新敌种**:duergar / hook_horror 两枚 ✓
- **既有池新技能**:Boss 独占技「大地脉动」(新技能行)——0 伤害妨害技,对主角施加 **sapped 乏力**(hero_offense 负向池,状态行与 effect_pool_map 挂钩均已存在,属"第二妨害词汇首发";L2 批注记原文即留此口径)。每池妨害 ≤1 纪律由跨表校验自动覆盖。
### 2.3 数值台阶候选锚(全部 provisional,投值归 难度曲线与Boss)
现行参照:L2 熊地精 10 血 / 攻 2,猎群 5 血 ×[2,3],Boss 蛛化卓尔 58 血 / 攻 3(r_boss 锚口径)。
| 行 | 数量 | hp 候选锚 | atk 候选锚 | 说明 |
|---|---|---|---|---|
| 灰矮人(单) | 1 | 14–16(锚 15,≈L2 单体 ×1.5,落在关间倍率域 [1.3,1.6]) | 3 [2,4] | 重甲自带 −1 普攻惩罚,等效再硬一档 |
| 钩爪恐魔(群) | [2,3] | 5–6 | 2 [1,3] | 群行压力,单体质与 L2 猎群持平偏上 |
| 灰矮人石君王 | 1 | Σ普通战生命期望 × r_boss(域 [0.5,1.1],r 取 0.8 粗估 ≈ 70–80) | 3 [2,4](Boss 攻击基线 ≥ 本关普通战最高行的纪律兑现) | 按九节点图版 Σ 粗算,最终以行值批逐数闭合 |
敌方 AC(armor_class)行值:方向已由 2026-09-18 盘问会话拍板(杂鱼 0–5 轻压、精英/Boss 8–12 留掷点戏剧性),排期 = 验收读数重测后与曲线调参同批。L3 行是"首个带正式 AC 的新内容"还是"AC 0 先行、与既有行同批补"——建议后者(全表一次投值,L3 不单独先跑),待拍板。
## 3. 扫雷面难度提升
| 旋钮 | 现行 L2 | L3 候选 | 约束 |
|---|---|---|---|
| 板面 | 12×12 全关 | 战斗 13×13,**Boss 14×14**("Boss 板 = 本关最大板形"纪律兑现) | 03-内容规模"两档尺寸"条款需随批修订;格边长按分辨率档位自动缩,UI 框架不动 |
| 雷密度 | 0.25 | **维持 0.25**;0.27 上探作为备选杠杆 | 0.28 实测破推理率门槛有失败先例(board_gen.tres 批注),上探必须带生成验算;加难主杠杆让给板面与地形 |
| 可推理率目标 | 0.88 | 恒 0.88 | 0.85 绝对锚不许碰 |
| 地形变异 | 岩浆(伤害 2)+ 烬覆(遮数字) | 新一对:**落石**(伤害型,effect_value 候选 3,延续 1→2→3 关间递进)+ **矿尘**(信息型,遮数字) | 布量走既有公式 5% + per_level_bonus 2×2 = 9%;新增第三种 effect 型(如"数字误导")会威胁可推理率锚,**不进本批**,只留作远期候选 |
风险登记:L2 完美档 Boss 承伤 55.8% 已越 F4 带(≤50%,台账 96 登记,归曲线调参批)——L3 伤害地形 3 点会进一步加压,承伤带复算义务与该条目同批合并,本预案不单独拍值。
## 4. 节点图与冒险结构
- **图版零新结构**:复用第二关九节点网状图模板(03-内容规模扩展批流程原文:"不新造节点链结构"),六战斗 + Boss,奖励/恢复各 1;敌种按"重轻错开"填入六个战斗位(建议:0 灰矮人单〔首遇教学,固定 1 不加骰〕→ 1 钩爪群 → 4 钩爪群 → 5 灰矮人重装手 → 6 钩爪巢群 → 7 灰矮人小队)。
- **进入方式**:沿用第二关先例——测试直入口先行(首页"关卡 3 试玩"),正式三关序列推进已登记为 Alpha 验收条件,不在本批展开。连带问题:三关全进序列后整局通关率 = 三关连乘,现行第一关带 [10,25]% 下整局会塌到百分位以下——带的逐关重排归曲线调参批,本批只登记。
## 5. 主角属性提升(关键前置,用户预判正确)
用户判断"现行基线打不过第三关"成立,且不止打不过 Boss——按 L3 候选锚,第二关的输出/生存供给对灰矮人单体已经吃紧。成长侧现有三条登记在案的路:
| 路线 | 内容 | 与 L3 的关系 |
|---|---|---|
| A. GP + 商店房(06 在案提案,原排 Alpha) | 战斗掉落 + 格面枚举 GP,商店房节点买一次性属性提升(flat 档位) | **推荐提前,与 L3 捆绑立项**。它是唯一覆盖"关卡内+关卡间"中途成长的方案,动机原文就写着"怪物数值随进程抬升,主角属性应有对应提升";且第三关正是第一个让这个缺口变成红档的内容批 |
| B. 大奖励数值联动(在案义务) | 关卡大奖励上限提升/恢复比例按通关率带复算 | 无论选哪条路都必须随批做,但它只有血量轴,救不了输出轴(普通攻击 2 点打重甲 −1) |
| C. 永久强化数值批(元进度,在案) | 营地三柜台定价与数值铺量 | 依赖真人试玩 k 系数与换算率标定,排期在曲线调参之后,赶不上 L3;且跨局成长救不了单局内的成长体验 |
A 路线的连带裁决面(提案原文六开放问题照单):GP 格面进不进雷安同池、战斗掉落记账、**商店房 = 节点类型封闭枚举 +1(走文档修订)**、商品定价曲线、双币呈现、验收读数按"商店存在与否"分层。捆绑立项 = L3 内容批拆两个子批:L3-A 玩家成长批(GP/商店房/大奖励联动),L3-B 第三关内容批(敌种/板面/地形/行值),A 先行或同窗口。
## 6. 结构性联动清单(容易漏的)
1. **克制渠道前置**:重甲教学的另一面是"玩家得有魔法攻击可拿"——格面魔法矢(magic 型,克重甲 +1)权重与可得性要在 L3 板上成立;hero.attack_type 换型轴(营地)仍是休眠态,不依赖它。
2. **技能表新行**:大地脉动(妨害型,sapped 载荷,冷却候选 4)——skills.tres 加行 + registry 登记。
3. **词表扩位**:board_type +1(deep_underdark);variation.tres 两新行(unlock_level 3,board_types 交集);甲效矩阵零改动(三档值不动,只是重甲首次被消费)。
4. **跨表校验**:九节点 (3, node_depth) 在 enemy/board_gen 精确铺行,首遇位(3,0 固定 1)绿档断言随批。
5. **验收带**:L3 通关率带取值、形态带(教学位绿 + 中段黄 + Boss 黄不红)、承伤带复算——全部归曲线调参批,与「基线通关率越带」「L2 Boss 承伤越带」两在案条目合并窗口。
6. **06 待办挂接**:敌方 AC 投值批、魔法道具内容批(若 GP 立项,奖励节点/商店房两渠道分工要在魔法道具重定批里说清)。
## 7. 拍板点(建议一次过,5 项)
| # | 问题 | 推荐 | 备选 |
|---|---|---|---|
| 1 | L3 主题 | A 灰矮人矿城 | B 蕈林 / C 鱼蛙人湖区 |
| 2 | 玩家成长路线 | A GP+商店房提前与 L3 捆绑 | B 只调大奖励数值 / C 等永久强化 |
| 3 | Boss 妨害词汇 | sapped 乏力首发(大地脉动) | 复用 off_guard 失衡(与卓尔同词汇) |
| 4 | 扫雷加难主杠杆 | 板面 13×13/14×14 + 地形 3 点,密度维持 | 密度上探 0.27(需生成验算) |
| 5 | L3 进入方式 | 测试直入口先行(同 L2 先例) | 直接进正式序列并重排三关通关率带 |
拍板通过后的执行切分建议:先 L3-A 玩家成长批(GP/商店房定稿提案 + GDD 修订),再 L3-B 第三关内容批(行值 + 词表 + 校验 + 冒烟),曲线调参批统一收带。
@@ -0,0 +1,331 @@
# 调研:地图战斗资源·雷安同池现状与差异化/整体权重调整空间
> **性质**:研究报告——只读取证,不修改任何文件,不下设计结论。
> **日期**:2026-09-17
> **上游触发**:用户「棋盘格战斗资源拟重新设计」关注(06-待办清单既有语境)+ 行动经济表注记「保留标中旗正向兑付——雷格/安全格概率差异化设计的前提」(`data/tables/action_economy.tres:18-19`)。
> **纪律**:全文禁止「应该/建议/我推荐」;只呈现「现状 → 改这条会动什么 → 风险」链与「若决策方向是 X,则路径 Y」的条件映射。所有事实断言引用 §9 附录所列文件 + 行号;推演值(计算所得)显式标注〔推演〕。
---
## 1. 调研目标与方法
**目标**:盘点「地图战斗资源」系统的雷安同池现状(A 层)、按格型差异化的候选路径空间(B 层)、整体权重调整空间(C 层)、外部同类做法(D 层),为后续设计决策提供事实与权衡依据。
**方法**(四层):
| 层 | 手段 | 产出 |
|---|---|---|
| 事实层 | 逐文件读取 §9 清单全部文件 | 第 2、3 章现状盘点 |
| 关系层 | 全仓关键词检索:`雷安同池`(15 处,排除 archive)、`类型频次合计`、`_rollable_rows`、`roll_board`、`equivalence_supply` | 第 2 章 A3 证据链 |
| 推演层 | 权重敏感性计算、路径改动面推导 | 第 4、5 章(推演值标〔推演〕) |
| 对照层 | 外部案例联网核验两例(Peglin / Let's! Revolution!),其余为知识盘点并标注 | 第 6 章 |
**边界**:本报告不触 v0.4/v0.6 结构冻结项的任何现行文件;第 7 章只列冻结项当前状态。文档/代码如有不一致,只并列呈现、方向归用户拍板(先例:三种方向都出现过,不默认代码为准)。
---
## 2. 现状盘点·结构与通道(A1/A2/A3)
### 2.1 A1:reward 表 11 行逐行行值
事实源 = `prototypes/dungeon-sweeper-vertical-slice/data/tables/reward.tres`(行号指该文件):
| # | reward_id | cell_type | polarity | power | power_min/max | weight | stacks | effect_id | display_name | pool_tag | tier |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | attack_up | attack | positive | 0 | — | 20 | 1(缺省) | attack_up | 增伤 | cell | 2 |
| 2 | ac_up | defense | positive | 0 | — | 16 | 1(缺省) | ac_up | 护甲强化 | cell | 2 |
| 3 | spark_aoe | blast | positive | 1 | — | 16 | 1(缺省) | —(空) | 爆裂粉尘 | cell | 1 |
| 4 | heal_minor | heal | positive | 1 | [1,1] | 3 | 1(缺省) | —(空) | 急救敷料 | cell | 1 |
| 5 | weaken | weaken | positive | 0 | — | 12 | 1(缺省) | weaken | 削弱 | cell | 1 |
| 6 | enrage | attack | negative | 0 | — | 0 | 1(缺省) | enrage | 敌方暴走 | cell | 2 |
| 7 | off_guard | defense | negative | 0 | — | 0 | 1(缺省) | off_guard | 我方失衡 | cell | 2 |
| 8 | heal_backlash | heal | negative | 1 | — | 0 | 1(缺省) | —(空) | 反噬震荡 | cell | 1 |
| 9 | ambush_double | blast | negative | 0 | — | 0 | **2** | —(空) | 敌方伏击 | cell | 1 |
| 10 | sapped | weaken | negative | 0 | — | 0 | 1(缺省) | sapped | 我方乏力 | cell | 1 |
| 11 | clear_blast | blast | positive | 13 | [8,18] | 1 | 1(缺省) | —(空) | 清障炸药 | clear_default | 2 |
- 行 1–5 = 正向五行(#8-16、18-26、28-36、38-48、50-58);行 6–10 = 负向五行(#60-68、70-78、80-88、90-99、101-109);行 11 = 清图槽(#111-121)。
- `stacks` 仅 ambush_double 显式携带 2(#96);其余行无 `stacks` 键,缺省 1(schema `data/schemas/reward_table.gd:57`)。
- 区间字段仅 heal_minor [1,1](#44-45,定值占位——注释明言「区间字段保留 min=max=1 占位,量级再调时恢复区间结构」,`reward.tres:141-142`)与 clear_blast [8,18](#117-118)。
- 区间行 schema 约束:必成对、percent 行禁止、`power = (min+max)/2` 中点锚(`reward_table.gd:70-84`)。
### 2.2 A2:类型频次合计 67 的来源分解
类型频次 = cell 池正向行 weight 合计(`reward.tres:126,145`;GDD `design/gdd/systems/战斗循环/地图战斗资源.md:72,76`):
| 行 | weight | 占比〔推演〕 |
|---|---|---|
| attack_up(attack) | 20 | 29.9% |
| ac_up(defense) | 16 | 23.9% |
| spark_aoe(blast) | 16 | 23.9% |
| heal_minor(heal) | 3 | 4.5% |
| weaken(weaken) | 12 | 17.9% |
| **合计** | **67** | 100% |
- 历史:v0.6 批时合计 79(heal 15);v0.7 数值压缩批 heal 15→3,合计降至 67(`地图战斗资源.md:232-233`;`reward.tres:140-145`)。
- clear_blast weight=1 **不入**类型频次:`_rollable_rows()` 只收 `pool_tag == "cell"`(`core/reward_economy.gd:211`),清图槽走独立 `_pool_rows("clear_default")`(`reward_economy.gd:63`)。
- 频次涌现机制:每非封锁格独立 `weighted_pick`(`reward_economy.gd:66-67`),大数频率收敛于行权重比例;reward_expectation 实测即验证此涌现(`smoke/reward_expectation.gd:58-70`)。
### 2.3 A3:雷安同池证据链(精确行号)
三处声明 + 两处执行 + 测试断言,全链如下:
**声明① 代码头注释**:`core/reward_economy.gd:6`——「安全格与雷格一视同仁(同一类型池、同一权重分布——雷安同池);封锁格不入摇号清单」。
**声明② 数据注释段**:`data/tables/reward.tres:125`——「安全格与雷格同池同分布(雷安同池)」;连带语义在 `reward.tres:143-144`——「heal 权重下调同比例降低踩中 heal 型雷(反噬)的频率」(雷安同池的自动同侧效应,标注「结构冻结,自动同侧」)。
**声明③ GDD**:`design/gdd/systems/战斗循环/地图战斗资源.md:61`(摇号纪律表「雷安同池」行,含「分布按格型差异化若未来需要,走本文修订」的预留出口)、`:207`(结构冻结七项含雷安同池)、`:212`(验收标准「任何'按格型差异化分配'的分支不存在」)。
**执行① 摇号实现**:`reward_economy.gd` `roll_board`(36-81 行)——`_rollable_rows()`(207-213 行,211 行过滤 `pool_tag=cell & polarity=positive & weight>0`,**无任何格型参数**)产出的单一行集对全部 eligible 格逐一 `weighted_pick`(65-67 行,64 行行内注释「① 身份批:每非封锁格恰一类型身份(雷安同池——同一行集同一权重分布)」)。
**执行② 资格清单与揭示通道**:
- 资格清单构建:`core/battle_orchestrator.gd:140-151`——eligible = 全部安全格 + 全部雷格、各自剔除 R₀(144-150 行),安全格与雷格进**同一个数组**(140 行注释「资格格 = 全部非封锁格(安全格 + 雷格,雷安同池)」)。
- 揭示通道:`core/minesweeper_rules.gd` `cell_revealed` 信号(10 行);`_do_dig`(236-274 行)内雷格 emit `resource: true`(262-265 行)、安全格 emit `resource: true`(268-271 行),资格注释在 258-259 行(「chain/dig 恒 true——安全格与雷格一视同仁(雷格亦携带,负向兑付归 战斗结算 极性路由)」);initial 通道(封锁格)恒 `resource: false`(100-103 行)。
**测试断言**:`smoke/smoke_all.gd:1347`(chain/dig 揭示事件 resource 恒 true——「雷安同池」命名断言)、`:1349`(雷格揭示携带资源 ≥1)、`:1365-1367`(封锁格 R₀ 身份查询 = null;未开雷格身份恒可查);分布涌现实测 = `smoke/reward_expectation.gd:58-72`。
**同池的运行时含义**:格子的资源类型身份在 install 期摇定(雷格同样携带身份);格子的**极性不在资源内**,由「动作 × 格型」矩阵在结算期决定(开安全格/标中雷 = positive,开雷格/标错安全格 = negative)——路由执行 = `battle_orchestrator.gd:253-260`(`_grant_routed` → `polarity_row`),字典查询面 = `reward_economy.gd:165-172`。**因此「雷格 vs 安全格」的差异通道在现行架构里 = 极性通道,而非类型分布通道。**
---
## 3. 现状盘点·字典与同步状态(A4/A5/A6)
### 3.1 A4:五型 × 极性字典完整内容(10 行兑付语义)
字典完整性为加载前提:五型 × 正负缺任一行即加载致命(`reward_table.gd:92-96`;运行时缺行 `_fatal`:`reward_economy.gd:171`)。兑付分派:effect_id 非空 = percent 行进增益状态容器;空 = flat 行当场兑付(`battle_orchestrator.gd:264-269`)。幅度行值源 = `data/tables/status_effects.tres`(九行)。
| 类型 | 正向兑付语义(格面池行 → 效果行) | 负向兑付语义(字典行 → 效果行) |
|---|---|---|
| attack | attack_up → 增益状态 attack_up:+50 percent、hero_offense 池、dur 1、max 2(`status_effects.tres:8-15`) | enrage → 敌方暴走:+25 percent、enemy_output 池、max 16(`status_effects.tres:44-51`) |
| defense | ac_up → 护甲强化:+1 ac/层 ×2 层,**AC 掷点阈值轴、不入任何池**(`status_effects.tres:17-24`;`design/gdd/systems/战斗循环/增益状态.md:132,154`) | off_guard → 我方失衡:+25 percent、hero_defense 池(承伤加深)、max 16(`status_effects.tres:53-60`) |
| heal | heal_minor → flat 治疗定值 1(满血零兑付照旧,`地图战斗资源.md:112`) | heal_backlash → **主角直伤 1,不经增益状态**(`reward.tres:80-88`;`地图战斗资源.md:112`;量级锚待办见 `06-待办清单.md:329-335`) |
| blast | spark_aoe → flat 群伤 1,全体存活敌各一笔 | ambush_double → 伏击 +2 层(stacks=2,`reward.tres:96`),受敌人系统单轮伏击上限 advantage_per_round_cap 护栏、溢出记「溢出未生效」行(`敌人系统.md:254`;`战斗结算.md:142`;冒烟直验 `smoke_all.gd:1309-1321`) |
| weaken | weaken → 削弱:−65 percent、enemy_output 池(`status_effects.tres:35-42`) | sapped → 我方乏力:−25 percent、hero_offense 池(`status_effects.tres:62-69`;`增益状态.md:159,219`) |
负向行为纯字典不消费权重(`reward_economy.gd:208`);负向恒即时、无库存语义(`地图战斗资源.md:122-124`)。四池对称口径:敌打主角 = hero_defense × enemy_output,主角打敌 = hero_offense × enemy_defense(`增益状态.md:163`)。
### 3.2 A5:当前测试在跑的分布假设与等价性断言
| 工具 | 与奖励分布的关系 | 具体断言/口径 |
|---|---|---|
| `smoke/reward_expectation.gd` | **直接**:类型频次涌现实测(N=200 板/深度,9 行) | ① 类型频次应涌现自正向行权重——**但头注释(4 行)与尾注(71-72 行)仍写「heal 15 · 合计 79 · heal 19.0%」旧基准(v0.7 压缩批未同步,见 3.3)**;② 封锁格零泄漏 = R₀ 格 `is_mapped` 恒 false(52-57 行) |
| `smoke/smoke_all.gd` | **直接**:资源资格面 + 负向字典 | ① chain/dig 事件 resource 恒 true(1347 行)② initial 恒 false(1348 行)③ 雷格携带资源 ≥1(1349 行)④ R₀ 查询 null / 未开雷格可查(1365-1367 行)⑤ 负向五型逐型直验(1244-1321 行)——**1255-1256 行注记:heal 权重 15→3 后单板五型齐备不再必然(无 heal 板概率 ≈1/3),改 6 板扫描取第一块齐备板** |
| `smoke/monte_carlo.gd` | 间接消费 | 无同池断言;统计攻防 buff 授予数(28、64 行:attack_up/ac_up 计数)与每轮承伤 |
| `smoke/level_monte_carlo.gd` | 间接消费 | 「踩雷/战 = 每战斗负向兑付触发期望」(106 行口径);完美档零踩雷构造断言(107-109 行);F4 承伤带 / 通关率带读数出口 |
| `smoke/experiment_density.gd` | **零耦合** | FakeDB 只供 `resolve_board_gen`/`status_effect_row`(59-64 行)——不消费 reward 表,密度实验与奖励分布无关 |
| `smoke/auto_player.gd` | 等价性载体 | 「等价性证明:smoke_all 同种子回放断言(步骤流逐行相同)在重构后保持全绿」(7 行)——确定性回放是全部奖励读数的前提 |
**雷安同池等价性测试的现状归纳**:现无「安全格分布 == 雷格分布」的统计等价断言(如卡方检验);等价性以**结构断言**承载(同一行集、同一清单、resource 恒 true)+ **涌现实测**(类型频次不分格型统计)。若未来差异化落地,`reward_expectation.gd` 的频次统计(58-61 行按格聚合,不分公司 kind)需按格型拆列才可验证差异。
### 3.3 A6:registry 与 .tres 的同步状态(v0.7 指路化后)
**结论:数值本体已单源化(.tres),但派生快照仍有三处需随批同步,且已发现两处漏网。**
- registry `design/registry/entities.yaml:320`(reward_table.mvp_content):2026-09-17 数值压缩批「具体数值列(power/weight/power_min/power_max)**改指路存根**:现行行值读 `data/tables/reward.tres`」——但同段保留了「压缩后锚行快照」(spark_aoe power=1 / heal_minor [1,1] / clear_blast [8,18] 中点 13 / **类型频次合计 79→67**)。即现行形态 = **指路存根 + 锚行快照**混合:weight 再动时锚行快照即失同步,需按 doc-conventions §5① 双写失同步禁止条款随批更新(`docs/doc-conventions.md:68`)。
- GDD 调参表已指路化:`地图战斗资源.md:193-203` 现行值列全部为「见 `data/tables/reward.tres` + registry mvp_content」存根,表格只锁字段语义与取值域(v0.7 双写失同步收口,`地图战斗资源.md:233`)。
- **漏网实证①**:`smoke/reward_expectation.gd:4`(「heal 15 / weaken 12,合计 79」)与 `:71-72`(「heal 19.0%」等 79 基准百分比)——v0.7 压缩批只同步了 .tres/smoke_all/GDD/registry/06 清单,此文件注释未同步,现行实测输出与注释口径已不一致。
- **漏网实证②**:`core/reward_economy.gd:184`(tier_min_buff 注释「attack_up/defense_up」——defense_up 已于 2026-09-16 换装为 ac_up,`status_effects.tres:97-99`)。功能不受影响(判据按 effect_id 查表 target_side,见 5.3),注释文本过期。
---
## 4. 差异化路径对比(B1–B5)
**先行事实**:差异化在 GDD 侧已有预留出口——「分布按格型差异化若未来需要,走本文修订」(`地图战斗资源.md:61`);行动经济表注记已把「保留标中旗正向兑付」表述为「雷格/安全格概率差异化设计的前提」(`action_economy.tres:18-19`)。三条候选路径按「改动从表到逻辑递深」排列。
### 4.1 B1+B2+B3:三路径对比表
| 维度 | 路径甲:双池切分 | 路径乙:格型权重列 | 路径丙:修饰位摇后过滤 |
|---|---|---|---|
| **核心思路** | pool_tag 增值(`cell` / `mine_cell`),雷、安各持一套正向权重行集 | 同表每行增设可选列 `weight_mine`(缺省 = weight,向后兼容),摇号按格的雷/安身份选列 | 身份仍同池摇定;对雷格(或带变异标签的格)在身份批后追加一次重摇/替换 pass,修饰规则独立成表 |
| **schema 层变化** | `POOL_TAGS` 枚举增值 + `clear_<biome>` 预留拒绝逻辑并存(`reward_table.gd:15,43-47`);池空护栏拆为双池各 ≥1 活行(`reward_table.gd:97-99`);字典完整性校验轴扩为(池 × 类型 × 极性)(`reward_table.gd:86-96`) | 新增可选配对列校验(缺省回退 weight——区间字段「缺省 = 定值行向后兼容」同款先例,`reward_table.gd:70-84`);行数不变 | 修饰规则新表(或 board_gen 行加列);`BoardData.variants` 字段已在板契约存在(`core/board_data.gd:14`),若挂变异标签可零新表 |
| **数据层变化** | reward.tres 正向 5 行复制出雷池行集(行数 11→16+),或负向行侧挂雷池权重 | 11 行各加一列(或仅正向 5 行加),初值同构 = 零行为变更上线 | 新增修饰规则行(如「雷格 heal 重摇为 attack」);现有 11 行不动 |
| **逻辑层变化** | `_rollable_rows()` 分池双份(`reward_economy.gd:207-213`);eligible 清单需携带雷/安事实(现 `battle_orchestrator.gd:144-150` 构建时无 kind 字段——需分两组或加字段);`roll_board` 65-67 行按格取对应池 | `weighted_pick` 选列参数化(`reward_economy.gd:195-204` 纯函数面签名变化);`_pool_weight` 双轨(224-228 行) | `roll_board` ③ 段(区间 roll,70-77 行)后插修饰 pass;若重掷则 reward_roll 流取号序变化 |
| **B2 差异化粒度** | 按格型(雷/安)× 行——两池各自独立的 5 行权重面 | 同甲:按格型 × 行;单表内维护 | 最细:可按格型 / biome(`board_data.gd:15`)/ 变异标签(`board_data.gd:14`)/ 坐标任意轴组合——粒度过细时逐行归因复杂化 |
| **B3 回归面** | `reward.tres` · `reward_table.gd` · `reward_economy.gd` · `battle_orchestrator.gd` · `smoke_all.gd`(1347/1349/1365 断言重写)· `reward_expectation.gd`(频次统计需按格型拆列)· registry mechanics/mvp_content(`entities.yaml:318,320`)· GDD 冻结项修订 | 与甲同文件集,少 pool_tag 枚举扩散、多 `weighted_pick` 签名变化;equivalence_supply 活行口径需定义(取哪列,`reward_economy.gd:177-190`) | `reward_economy.gd` 确定性链 · 排雷玩法变异不变式 inv2a/inv2b(`minesweeper_rules.gd:124-137`)· 全部既有种子读数(修饰 pass 改变取号序则黄金向量全变) |
| **确定性/回放影响** | 取号次数不变(每格仍恰一次);同种子回放保持,但身份表内容随池权重变化 → 既有种子读数作废重测 | 同左 | 若修饰不额外取号(确定性映射)则取号序不变;若重摇则 reward_roll 流消耗序变化,同种子身份表全变 |
| **对账面(行动经济 F1)** | P(安全)/P(雷) 两侧类型分布分化 → 条款③挖掘风险不等式、条款⑤清图支配性需按侧重推(`design/gdd/systems/排雷循环/行动经济.md:110-128`) | 同左 | 同左(若修饰只动类型边际分布,等价于甲/乙的分布结果) |
| **B4 破冻结判定** | **破 v0.4 冻结**(雷安同池 + 验收标准 212 行),走 GDD 修订 | **同破**(结构上同为「按格型差异化分配」分支) | **实质等效于破**(「同一权重分布摇定」的字面保留、分布实质改变——212 行语义被绕过,需修订裁决其是否算差异化分支) |
### 4.2 B4:v0.4 + v0.6「结构冻结」项范围(改哪项算破冻结)
**v0.4 结构冻结七项**(`地图战斗资源.md:207`,改动走 GDD 修订流程、不走调参):
1. 五型封闭枚举(加第六型 = 修订文档,`:116`)
2. **雷安同池**(差异化三路径全部命中此项——`候选集合`节 :72-77 与验收标准 :212 同锚)
3. 极性矩阵(「动作 × 格型 → 符号」定义,`:90-100`)
4. 装板期预分配且无重摇(`:56-60`)
5. 负向恒即时无库存(`:122-124`)
6. 清图恒非空(`:136`;schema 护栏 `reward_table.gd:100-102`)
7. 除摇号外零随机(`:15,162`)
**v0.6 批内零改动承诺**(非长期冻结,是批次范围声明):「cell_type defense / 权重 16 / 档位 2 零改动(类型频次合计 79 不变)」(`reward.tres:133-135`;`地图战斗资源.md:232`)——v0.7 已改 heal 权重证明该承诺是批内性的;类型频次合计本身**不在冻结范围**(79→67 已发生,`地图战斗资源.md:233-234`)。
**冻结边界的现行口径**:权重数值 = 调参(provisional 归难度曲线与Boss,`地图战斗资源.md:157,187`);权重所附着的结构(单池、正向行集、极性字典五型×正负) = 冻结。「只调 weight 数值」永不破冻结;「让雷格与安全格读到不同权重/行集」必破第 2 项。
### 4.3 B5:旧提案「行权重 vs 类型权重」区分的可借鉴点
`design/research/proposal-reward-polarity-2026-09-13.md` 与差异化的四点衔接:
1. **「类型 = 行的家族属性,类型频次由行权重涌现」**(R1,`:20`)——差异化后若想分别控制雷、安两侧的类型频次,沿用该原则意味着两池各自维护行权重、频次各自涌现;若想直接以「类型频次」为调参对象(而非行权重),需新增类型→行的聚合换算层,proposal 当时明确放弃了这层(「难度曲线与Boss 调参对象 = 行权重」)。
2. **「roll 保持单段 weighted_pick 结构不动(不引入两段式)」**(R1 实现面钉死,`:20`)——该钉死与路径丙(摇后修饰 pass)的实现形态相悖;甲/乙保持单段摇号、只在入口分行集/分列,与该钉死兼容。
3. **`mine_cell` 池成案**:v3 §3 曾设计「pool_tag 新值 mine_cell;roll_board 批次扩雷格 roll(同一 scope 批内)」(`:49`)——路径甲在旧提案时代有完整 schema/批次设计先例;v4 用户裁决(2026-09-15)最终落地为「雷安一视同仁 + 可选类删除」(`:94`),`mine_cell` 随之搁置,**结构图纸仍在案可翻**。
4. **playtest 预注册指标**(§4,`:67-73`):路线选择率、图标误读率、类型选择性探测率三项可直接复用为差异化落地后的验收观测面(指标定义与「类型分布即先验信息是有意的规划素材」拍板——R3,`:29`——在差异化场景语义更强:两侧分布差值本身成为可读信息)。
---
## 5. 整体权重调整空间(C1–C5)
### 5.1 C1:权重敏感性——单行 ±25%/±50% 对类型频次的影响
**口径**〔推演〕:单行独立调整、其余四行不动;份额 = weight′/合计′。现行基准 67(`reward.tres:126,145`)。
| 调整行(现行 weight / 份额) | +25% | +50% | −25% | −50% |
|---|---|---|---|---|
| attack_up(20 / 29.9%) | 25 → 34.7%(+4.9pt,合计 72) | 30 → 39.0%(+9.1pt,合计 77) | 15 → 24.2%(−5.7pt,合计 62) | 10 → 17.5%(−12.3pt,合计 57) |
| ac_up(16 / 23.9%) | 20 → 28.2%(+4.3pt,合计 71) | 24 → 32.0%(+8.1pt,合计 75) | 12 → 19.0%(−4.8pt,合计 63) | 8 → 13.6%(−10.3pt,合计 59) |
| spark_aoe(16 / 23.9%) | 同 ac_up 对称 | 同上 | 同上 | 同上 |
| heal_minor(3 / 4.5%) | 3.75 → **非整数**(取 4 → 5.9%,合计 68) | 4.5 → **非整数**(取 4 → 5.9% 或 5 → 7.2%) | 2.25 → 取 2 → 3.0%(合计 66) | 1.5 → 取 1 → 1.5% 或取 2 → 3.0% |
| weaken(12 / 17.9%) | 15 → 21.4%(+3.5pt,合计 70) | 18 → 24.7%(+6.8pt,合计 73) | 9 → 14.1%(−3.9pt,合计 64) | 6 → 10.3%(−7.6pt,合计 58) |
**三点敏感性结论**〔推演〕:
1. **整数权重域的最小步长问题**:weight 域 [0,999](`reward_table.gd:53`),但 heal_minor 现值 3 的 ±25% 落非整数——小权重行(≤3)的可调粒度是 ±1(33%/50% 步长),做不了 ±25% 级别的细调。v0.7 的 15→3 实际步长就是 −80%。
2. **同池线性传导到负向字典命中率**:雷安同池下,踩雷格/标错格命中某型负向的频率 = 该型类型频次 × 格位雷概率——类型频次变多少,该型负向兑付频率同比例变。特例已由 v0.7 注记背书:「heal 权重下调同比例降低踩中 heal 型雷(反噬)的频率」(`reward.tres:143-144`)。
3. **五型齐备板概率对 heal 权重高度敏感**:单板无 heal 格概率 = (64/67)^非封锁格数〔推演〕。smoke_all 负向字典直验因此已改 6 板扫描(`smoke_all.gd:1255-1256,1284`——heal 权重若再降,该断言的扫描通过率继续下降;heal 3→2 时〔推演〕非封锁格 55 格的板无 heal 概率约 8%→19%,6 板扫描失败概率约 0→35% 量级)。
4. **全行同比例缩放 = 零频次影响**:份额不变,但 reward_roll 取号域宽度变化(`reward_economy.gd:67` 的 `randi_range(0, 合计−1)`)会改变同种子下各格摇中的 reward_id——「整体权重轴」调整若不动相对结构,频次读数不变而**既有种子读数仍作废**。
### 5.2 C2:区间行离散度对局体验影响
- **heal_minor [1,1]**:区间已塌缩为定值占位(`reward.tres:44-45,141-142`——「量级再调时恢复区间结构」)。重开区间掷点**零新机制**:schema 配对/中点锚校验在位(`reward_table.gd:70-84`)、身份批内追加取号实现在位(`reward_economy.gd:70-74`)、快照 power 覆盖授予链路在位(`battle_orchestrator.gd:259`)。重开的唯一变量 = 治疗量的局内方差。
- **clear_blast [8,18]**:现行区间跨度 10、中点 13、相对半宽 ≈38%〔推演〕;摇定时机 = 装板批尾、**每板恰一次**跨轮不变(`reward_economy.gd:68-69,75-77`),非每次清图重掷。波动影响的是「清图轮的斩杀线稳定性」(Boss 前最后一张板的清图奖励量级浮动),期望当量由中点锚锁定(行动经济条款①锚口径,`reward_table.gd:82-84`)。
- 区间行与定值行的并存先例:v0.7 压缩批同时动过两种形态([25,55]→[8,18] 与 [2,6]→[1,1],`reward.tres:138-142`)——「开不开区间」在现行 schema 里是行级自由度,不是机制级开关。
### 5.3 C3:tier_min_buff 当前算法与影响行
算法(`reward_economy.gd:177-190`):遍历 reward 全表,取 `pool_tag=cell & polarity=positive & effect_id≠""`(= percent 正向行)且其状态行 `target_side == "hero"` 的行集,`tier_min_buff = min(tier)`。
- **当前命中行**:attack_up(tier 2,状态行 target_side=hero,`status_effects.tres:10`)、ac_up(tier 2,target_side=hero,`status_effects.tres:19`)→ **tier_min_buff = 2**(registry 同值:`entities.yaml:320`「tier_min_buff = 2」)。weaken 虽是 percent 正向行但 target_side=enemy(`status_effects.tres:37`),被排除。
- **口径注记**:ac_up 是 AC 阈值轴行、不入任何池(`增益状态.md:132`),但判据只查 target_side 不查 unit——ac 行目前参与「我侧增益最低档」计算。该判据文本写于换装批之前(184 行注释仍称 defense_up,见 3.3 漏网②)。
- **影响面**:tier_min_buff 是「最低档安全格增益」的数据源——行动经济条款②「标中旗锚:标中旗的减益档位必须严格高于最低档安全格增益」(`行动经济.md:113`;`增益状态.md:165`)。凡 target_side=hero 的 percent 正向行 tier 变动,或未来 heal/blast 增挂 effect_id 行,都会改变该锚值。
- **消费方现状**:`equivalence_supply()` 在切片代码内**零调用**(全仓 grep 仅定义处 `reward_economy.gd:177`)——当量对账目前是文档层义务(战斗结算为唯一对账责任方,`战斗结算.md:103`),非运行时强制。
### 5.4 C4:equivalence_supply 当前活行清单与权值
活行 = `weight > 0` 全行投影(`reward_economy.gd:180-183`):attack_up 20 · ac_up 16 · spark_aoe 16 · heal_minor 3 · weaken 12 · clear_blast 1,共 **6 活行**;负向 5 行 weight=0 不入。对账锚关系:条款①单一当量(对照表载体归战斗结算,`战斗结算.md:103`)、条款②锚 = tier_min_buff(见 5.3)、条款③⑤不等式两侧的原材料 = 正向当量与惩罚当量(`行动经济.md:122-128`)。上游对账约束:关级通关恒等式「奖励输出占比 ∈ [15%, 40%]」(`难度曲线与Boss.md:100-104`)——活行权重/威力的单边移动必须走恒等式联合检算(`:153`)。
### 5.5 C5:调权重连带必动位置清单(当前实测)
v0.6 先例用「零改动」避开连带(`reward.tres:134`);v0.7 先例实动一处权重(heal 15→3),连带同步面实测如下——**第 4、5 项即该批漏网处**:
| # | 位置 | 性质 | 证据 |
|---|---|---|---|
| 1 | `data/tables/reward.tres` 行值 + 注释段合计数 | 数据本体 | `reward.tres:14-145`(注释段 137-145 记压缩前后值) |
| 2 | registry `entities.yaml` mvp_content 锚行快照 + 合计 | 派生快照 | `entities.yaml:320`(「79→67」已随批写) |
| 3 | GDD `地图战斗资源.md` 候选集合节合计 + v0.x 版本历史 | 派生快照 | `地图战斗资源.md:72,76`(67);`:232-234` |
| 4 | `smoke/reward_expectation.gd` 头注释与尾注基准值 | **漏网实证(现行过期)** | `reward_expectation.gd:4,71-72`(仍 79 基准) |
| 5 | `core/reward_economy.gd` 行内注释(行名引用) | **漏网实证(现行过期)** | `reward_economy.gd:184`(仍写 defense_up) |
| 6 | `smoke/smoke_all.gd` 五型齐备断言口径 | 随 heal 权重敏感 | `smoke_all.gd:1255-1256,1284` |
| 7 | 难度曲线恒等式与通关率带读数重跑 | 对账义务 | `难度曲线与Boss.md:100-104,115,153`;EV/读数重锚随批纪律先例 `:275` |
| 8 | 行动经济 F1 条款②③⑤重推 | 对账义务 | `行动经济.md:110-128` |
| 9 | doc-conventions §5 五步收口流程 | 流程义务 | `doc-conventions.md:68`(①双写失同步禁止⑤五步全收) |
---
## 6. 外部参考(D1–D2)
> 说明:D1/D2 案例中 Peglin 与 Let's! Revolution! 经联网核验(来源见 §9 附录);其余为知识盘点、未逐项联网核验,置信度逐条标注。本节只做事实盘点。
### 6.1 D1:雷格 vs 安全格差异化在其他游戏里的常见做法
| 做法 | 案例 | 与本项目结构的关系 |
|---|---|---|
| 格下内容物混布、**不分格型**同池 | Let's! Revolution!(2023,核验):雷图翻格 roguelite,格下混布金子/敌人/通路,挖到金子=收益、惊动敌人=战斗——极性由**内容物**决定,与本项目「极性由动作 × 格型决定」取向相反 | 与现行雷安同池同构度最高 |
| **按节点/格型分池**,每型独立奖励池 | Slay the Spire:地图节点分型(战斗/精英/商店/宝箱),各型独立掉落表(知识盘点) | 路径甲(双池切分)的同构先例——节点型 ≈ 格型 |
| 板内**位型差异化密度**(特殊位限量混布) | Peglin(2022,核验):板混布普通钉与特殊钉(暴击/刷新/爆炸/治疗钉),特殊钉有独立效果与生成控制 | 与「雷/安二值绑定」不同:特殊位是增量维度,不与「危险/安全」二值共轴 |
| **按格修饰位**改变产出 | Loop Hero:地形卡改变格子刷出的怪物与资源(知识盘点) | 路径丙(修饰位过滤)的同构先例 |
| 单池统一权重表 + 稀有度列 | Luck be a Landlord:符号池加权摇号(知识盘点) | 现行结构(单池行权重)的同类 |
| 无资源层 | 传统扫雷及其多数变体(知识盘点) | 差异化问题的空白基线 |
### 6.2 D2:同类「按格型差异化权重」做与不做的案例
- **做的**:Slay the Spire(节点型分池,路线规划 = 核心策略层);Peglin(特殊钉密度即难度旋钮);杀戮尖塔式「按节点类型选路」与本项目「未开格类型预读 → 读敌拍板」(proposal §4 指标,`:69-73`)在设计动机上同族。
- **不做的**:Let's! Revolution!(资源与危险混布、不按格型分权重——其策略素材来自数字推理而非分布先验);传统扫雷变体(无资源层可差异)。
- **中间态事实**:本次盘点未发现「同格型空间、雷格与安全格同池但权重不同」的知名先例——现有作品要么全同池(Let's! Revolution!),要么彻底按型分池(StS 节点)。中间态的体验先例缺口本身是一个待验证风险(无对照读数可借)。
---
## 7. 风险与冻结项(v0.4 + v0.6 拍板项当前状态)
### 7.1 冻结项清单与差异化/调权的关系
| v0.4 冻结项(`地图战斗资源.md:207`) | 纯调 weight 是否触碰 | 差异化三路径是否触碰 |
|---|---|---|
| 五型封闭枚举 | 否 | 甲/乙:否(类型集不变);丙:视修饰规则(若把某格摇成清单外类型则触碰) |
| **雷安同池** | 否 | **甲/乙/丙全部触碰**(见 4.1 B4 行) |
| 极性矩阵 | 否 | 否(三路径都不动「动作 × 格型 → 符号」) |
| 装板期预分配且无重摇 | 否 | 甲/乙:否;丙:若修饰 = 重摇则触碰第 4 项、若为确定性映射则不触碰 |
| 负向恒即时无库存 | 否 | 否 |
| 清图恒非空 | 否 | 否(clear_default 池在三路径中均不动) |
| 除摇号外零随机 | 否 | 丙:修饰 pass 若引入摇号外的随机即触碰;甲/乙:否 |
**综合判定**:整体权重调整(C 层)在现行冻结框架内是纯调参(provisional 归难度曲线与Boss,`地图战斗资源.md:157,187`),零破冻结;差异化(B 层三路径)必破 v0.4 冻结第 2 项、走 GDD 修订流程(`地图战斗资源.md:61` 预留出口即为此设)。
### 7.2 风险登记
1. **确定性读数作废风险**:任何 weight 变动(含同比例缩放)改变同种子身份表(5.1 结论 4)——冒烟 296 断言中依赖具体身份的用例、种子 421 等既有读数、验收批读数全部重测(先例纪律:`难度曲线与Boss.md:275`「行值零改动、重锚与权重投值随批合并」;上一轮换装/压缩批后「全部旧读数失效、验收读数另批重测」为既有惯例)。
2. **连带同步缺口风险**:v0.7 批实测漏网两处(3.3);doc-conventions §5① 已把三类同步定为完成判据(`doc-conventions.md:68`),但 §5 覆盖清单是**文档类**字段——smoke 脚本注释与 .gd 行内注释不在其列(第 4、5 项均属此类),流程上需扩充口径或另立检查项。
3. **对账耦合风险**:heal 权重与行动经济条款③⑤不等式、难度曲线恒等式 [15,40]% 带、通关率带三方耦合(5.4、5.5 #7/#8)——单动 heal 权重即触发三处对账义务(v0.7 已实测触发:`06-待办清单.md:331`「量级当量对账待难度曲线与Boss 调参批执行」)。
4. **差异化后信息面风险**:若雷、安分布分化且未开格类型可预读(待办 `地图战斗资源.md:180`;06 清单 `:323`),类型分布本身从「零信息」变为「雷/安属性的先验证据」——proposal R3 已拍板「类型分布即先验信息是有意的规划素材」(`:29`),差异化将该拍板的强度放大(分布差值成为可推理量),与排雷推理本征的边界需重新裁决。
5. **小权重行整数化风险**:heal_minor=3 已落入 ±25% 不可整调区间(5.1 结论 1)——后续任何以百分比为步长的 heal 调参都会遇到取整歧义。
6. **equivalence_supply 零消费方**:当量对账为文档层人工义务、无运行时守卫(5.3)——差异化若使两侧当量结构分化,人工对账的出错面扩大。
---
## 8. 后续设计决策待决项清单(用户拍板时须给出的输入)
1. **差异化的问题定义**:要区分的轴是什么——雷格 vs 安全格(分布差异化)?还是类型本身的出现频率(纯权重调整)?两者分属 B 层(破冻结、走修订)与 C 层(调参、零破冻结)。
2. **若决策方向是差异化**:粒度选择——甲(双池,行集独立)/ 乙(单池双列)/ 丙(修饰位,粒度最细)——三路径的取舍依据见 4.1 对比表;甲有 `mine_cell` 旧成案可翻(4.3)。
3. **若决策方向是差异化**:负向字典是否随差异化的分布侧联动(如某型在雷池权重为 0 时,其负向行仍须在字典内——字典完整性校验 `reward_table.gd:92-96` 不因权重为零而豁免)。
4. **若决策方向是纯权重调整**:调整的对账义务批次窗口——恒等式带 [15,40]%、通关率带、条款③⑤重推是否同批执行(7.2 风险 3)。
5. **heal 权重档位**:现行 3 的相邻整数档(2/4/5)各有不同离散后果(5.1 表)——取整规则(四舍五入/向下/手工指定)与档位粒度须明示。
6. **clear_blast 区间**:维持 [8,18]、收窄、或塌缩为定值(C2)——机制面三态零成本,属纯体验方差决策。
7. **tier_min_buff 口径**:ac 行(AC 阈值轴)是否应计入「我侧增益最低档」(5.3 口径注记)——影响行动经济条款②锚值。
8. **同步流程口径**:smoke 脚本注释与 .gd 行内注释是否纳入 doc-conventions §5 强制收口范围(7.2 风险 2——两处现行漏网皆属此类)。
---
## 9. 附录:必读资料引用表
| 文件(§3 清单) | 本报告引用的关键行 |
|---|---|
| `prototypes/dungeon-sweeper-vertical-slice/core/reward_economy.gd` | 6, 36-81(roll_board), 62-67, 70-77, 165-172(polarity_row), 177-190(equivalence_supply/tier_min_buff), 184, 195-213(weighted_pick/_rollable_rows) |
| `prototypes/dungeon-sweeper-vertical-slice/core/minesweeper_rules.gd` | 10(信号), 100-103(initial 通道), 124-137(不变式), 236-274(_do_dig), 258-259, 262-271(resource 通道) |
| `prototypes/dungeon-sweeper-vertical-slice/core/board_data.gd` | 14(variants), 15(biome), 81-86(safe_cells), 90-103(compute_r0) |
| `prototypes/dungeon-sweeper-vertical-slice/core/battle_orchestrator.gd` | 75, 131-161(_install_new_board/roll_board 调用), 166-178(facts 缓冲), 200-260(授予段/极性路由), 253-260, 264-269 |
| `prototypes/dungeon-sweeper-vertical-slice/data/schemas/reward_table.gd` | 13-16(枚举), 53-59(weight/stacks 域), 57, 70-84(区间/中点锚), 86-102(字典完整性/池护栏) |
| `prototypes/dungeon-sweeper-vertical-slice/data/tables/reward.tres` | #7-122(11 行), 124-145(注释段:同池声明 125 / 频次 126 / 换装 133-135 / 压缩批 137-145) |
| `prototypes/dungeon-sweeper-vertical-slice/data/tables/status_effects.tres` | #7-88(九行), 90-113(批注:减伤墙/换装/技能池/压缩) |
| `prototypes/dungeon-sweeper-vertical-slice/data/tables/board_gen.tres` | #7-139(12 行板参数), 141-154(调参登记) |
| `prototypes/dungeon-sweeper-vertical-slice/data/tables/action_economy.tres` | 7-14(行值), 16-23(AP 压速批注——差异化前提注记 18-19) |
| `prototypes/dungeon-sweeper-vertical-slice/smoke/reward_expectation.gd` | 4, 9, 21-72(频次实测/口径注——过期基准 4,71-72) |
| `prototypes/dungeon-sweeper-vertical-slice/smoke/monte_carlo.gd` | 8, 28, 54-68(读数口径) |
| `prototypes/dungeon-sweeper-vertical-slice/smoke/experiment_density.gd` | 59-69(FakeDB——零 reward 耦合) |
| `prototypes/dungeon-sweeper-vertical-slice/smoke/level_monte_carlo.gd` | 45-48, 100-109(带口径/完美档断言) |
| `prototypes/dungeon-sweeper-vertical-slice/smoke/level_autoplay.gd` | 18-21, 85-89(mine_hits 埋点), 122-191(双策略档驱动) |
| `prototypes/dungeon-sweeper-vertical-slice/smoke/smoke_all.gd` | 91, 1244-1321(负向字典直验——1255-1256, 1284), 1326-1367(资源面断言——1347,1349,1365-1367) |
| `prototypes/dungeon-sweeper-vertical-slice/smoke/auto_player.gd` | 7(同种子回放等价性), 31-48(完美策略档) |
| `design/gdd/systems/战斗循环/地图战斗资源.md` | 9, 52-61(摇号纪律——61 雷安同池行), 70-88(候选集合), 90-100(极性矩阵), 104-118(五型字典), 122-124(负向即时), 128-141(清图), 153, 157, 187, 191-205(调参表指路化), **207(结构冻结七项)**, 209-217(验收标准——212), 225-234(版本历史 v0.4-v0.8) |
| `design/gdd/systems/战斗循环/战斗结算.md` | 103(对账唯一责任方), 124(极性路由兑付), 142(伏击溢出), 146(标错类型化), 180(奖励定义分离) |
| `design/gdd/systems/战斗循环/增益状态.md` | 132, 138(九行), 154-161(状态行表), 163(四池对称), 165(当量锚), 214-221(调参表) |
| `design/gdd/systems/战斗循环/敌人系统.md` | 151(反灾难护栏), 254(advantage_per_round_cap) |
| `design/gdd/systems/冒险循环/难度曲线与Boss.md` | 9, 21, 35, 100-104(关级恒等式 [15,40]%), 115(通关率带), 153(联合检算), 174, 220-236(投值表), 255-257, 275(EV 重锚纪律) |
| `design/gdd/systems/排雷循环/行动经济.md` | 88, 106-118(五条款), 122-135(推导与锚表) |
| `design/research/proposal-reward-polarity-2026-09-13.md` | 20(R1 行权重/单段钉死), 29(R3 分布先验拍板), 44(雷池权重独立可调), 49(mine_cell 成案), 67-73(预注册指标), 89-98(v4 四点裁决) |
| `design/registry/entities.yaml` | 300-325(reward_table 条目——318 mechanics / 319 api / **320 mvp_content 指路存根+锚行快照**) |
| `design/gdd/06-待办清单.md` | 11, 125-131(连锁溢出), 133(充能归属), 315-319(功能道具渠道), 323(预读深度), 329-335(heal 量级锚), 409(大奖励联动) |
| `docs/doc-conventions.md` | 68(§5 数值纪律·强制收口五条款) |
| 外部(联网核验) | Peglin:[Peglin Wiki – Critical Peg](https://peglin.wiki.gg/wiki/Critical_Peg);Let's! Revolution!:[GameOrNought 评测](https://gameornought.wordpress.com/2023/07/19/lets-revolution-review/)、[Game Developer postmortem](https://www.gamedeveloper.com/production/prototyping-i-let-s-revolution-i-transforming-i-minesweeper-i-into-a-turn-based-strategy-roguelike)、[Steam 页面](https://store.steamcommunity.com/app/1966280) |
---
*报告完。全文未修改任何被引用文件;推演值均已标注〔推演〕;未含任何「应该/建议/推荐」式结论。*
+9 -1
View File
@@ -11,4 +11,12 @@
3. 玩家攻击和怪物攻击不对等
- 考虑引入命中(AC like),但是造成伤害的方式要区分开;
4. 每次开图就是开了片面积;
- 是否有生成图计算如此?
- 是否有生成图计算如此?
5. 现在还是不能开已经被标记为雷的安全格,或者说不能开被标记的格子这跟我们之前的设定是相悖的.你有个会话说是已经修复了,但其实并没有修复.你并没有对应的测试,我需要你补全对应的测试,并且修复这个 bug; 不要把原本的扫雷的规则观念带进来,我们这里是有魔改的
6. 第二关显示时,棋盘最底下会有一点显示不出来,也就是最下面一排的格子不是一个完整的正方形,会缺失 1/6 的高度。
你可以把棋盘下面预留一定的空间,大概是 1/4 方格的空间或者是一个固定的值,让棋盘的最底下不要贴着游戏的边框。
# 想法
1. 是否有可能将AP改成时间制? 但是这会让单回合上限无限拔高, 有点变态了
+92
View File
@@ -0,0 +1,92 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>迭代闭环仪表盘 · Dungeon Sweeper</title>
<style>
:root{--bg:#14161a;--card:#1d2026;--line:#2c3038;--tx:#d8dce3;--dim:#8b919c;
--acc:#5b9dd9;--warn:#d9a05b;--bad:#d95b6a;--ok:#6fbf7f;}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--tx);
font-family:"Segoe UI","Microsoft YaHei","PingFang SC",sans-serif;font-size:14px;line-height:1.6}
main{max-width:1080px;margin:0 auto;padding:24px 20px 60px}
h1{font-size:22px;margin:0 0 4px}
h2{font-size:17px;margin:36px 0 10px;padding-bottom:6px;border-bottom:1px solid var(--line)}
.meta{color:var(--dim);font-size:12.5px;margin-bottom:8px}
.grid{display:grid;grid-template-columns:1fr 1fr;gap:14px;align-items:start}
@media(max-width:800px){.grid{grid-template-columns:1fr}}
.card{background:var(--card);border:1px solid var(--line);border-radius:8px;padding:14px 16px}
.card h3{margin:0 0 8px;font-size:14px;color:var(--acc)}
.card ul{margin:0;padding-left:18px}
.card li{margin:3px 0}
table{width:100%;border-collapse:collapse;background:var(--card);
border:1px solid var(--line);border-radius:8px;overflow:hidden;font-size:13px}
th,td{padding:6px 10px;text-align:left;border-bottom:1px solid var(--line);vertical-align:top}
th{color:var(--dim);font-weight:600;background:#22252c}
tr:last-child td{border-bottom:none}
.dirty{color:var(--warn);font-weight:600}
.tag{display:inline-block;padding:0 8px;border-radius:10px;font-size:12px;margin-right:6px}
.tag.open{background:#2b3a4a;color:#9cc7ec}
.tag.partial{background:#463d2b;color:#e0c08a}
.tag.decided{background:#3a3350;color:#c3b3ec}
.tag.resolved{background:#3c2b30;color:#e0999f}
.stale{color:var(--bad);font-weight:600}
.ok{color:var(--ok)}
.dim{color:var(--dim)}
footer{margin-top:40px;color:var(--dim);font-size:12px;border-top:1px solid var(--line);padding-top:12px}
code{background:#262a31;padding:1px 5px;border-radius:4px;font-size:12.5px}
</style>
</head>
<body>
<main>
<h1>迭代闭环仪表盘</h1>
<div class="meta">阶段: Vertical Slice Implementation · 生成于 2026-09-19 05:34 · 只读视图,重跑 <code>python tools/loop_dashboard.py</code> 刷新</div>
<h2>当前状态快照(active.md)</h2>
<div class="card"><ul><li>**更新于**:2026-09-19(旗行为基线前置采集批:拔旗定价复核+插旗不可逆提案两条自 06 清单销项〔用户拍板标记完成〕,观测面以 07-体验验证清单⑧承接——纯日志侧零玩法改动,读数全部可由现役 JSONL 推导,随真人试玩批次 2 出基线、回流 Alpha 插旗提案评估;清单 55→53 条;台账 82)+(并行对答会话)技能池新效应词汇批四拍板落地:两词定案〔妨害技=新增第四技能类型、载荷复用乏力/失衡既有轴;必中附加分量=攻击基线×0.75 不吃骰不出暴击,替代&quot;固定值伤害&quot;〕、多段命中退役〔无防御磨损体系〕、实装面收窄=仅 L2 Boss 蛛化卓尔精灵、其余敌种不动;妨害首发轴待用户点选后出 proposal 一批执行(06 条目状态已更)</li><li>**在飞**:表现层升级批未启动(前置 = 美术清单 P0 样张 + 用户看图拍板敌人卡形态);两份美术清单合并待拍板;多批工作区未提交</li><li>**已完成**:06 待办清理批(清单 87→80 条;三裁决落地:变异死分支删/快照域进 Alpha 首批/未开格微光拍板;排雷玩法节新增禁拔旗提案登记)+ 冒险内成长提案登记批(GP 临时资源+商店房提案登记 06 清单关卡节点地图节,未评估;台账 74)</li><li>**已完成**:**数值语言拍板批(加法核,台账 75)**——全项目数值语言=小整数加法核(模板 C 骨架+模板 A 成长语言)成文 01-核心循环;甲效矩阵 percent→三档点数 +1/0/−1(pierce×heavy=0 用户拍板,今晨五档 percent 调参〔台账 71〕随批退役);增益池/AC 折扣档/暴击保留百分比+粒度口径成文;元进度/GP 投值语言锁 flat;冒烟 300 全绿+四探针 PASS+flat vs percent A/B(L1 逐值全同、L2 Boss 战基础攻击 +1 生效 hp+100 档 50→60%)</li><li>**已解锁可做**:验收读数重测批(结构修复批+调参批+换装批三次数值行为变更叠加,基线彻底归零须重测;击杀区间复算义务随批);敌方技能攻击类型轴(敌方攻击入矩阵消费面后主角 armor_type 轴才生效)</li><li>**阻塞等待**:曲线调参批(门 = 验收读数重测);状态层重设计批(临时值终值 + 池百分比量纲复核)</li><li>**锚点提交**:b51af08 结构修复批 · b7d1b56 收口杂项 · 0da19a5 场景一三落地 · a2fc39f 伤害道具+护甲重配 · c5c52b5 元进度定稿</li><li>**下一步顺序**:验收读数重测 → 状态层重设计批 → 曲线调参批 → 魔法道具内容批 → 表现层升级批(详见 production/roadmap.md)</li><li>**并行会话标旗**:本会话(数值语言批)改面 = 甲效矩阵 7 切片件+战斗结算 v0.16+难度曲线 v0.12+元进度 v1.1+01+registry+06 GP 注记一行;其余在飞改动(06 清理 143 行/board_data.gd/07/冒险结构/增益状态/战斗表现/行动经济/数据配置/设置与本地化/音频/battle.md/analyze_playtest.py)均非本批未碰;design/ 三未跟踪文件维持标旗</li></ul></div>
<h2>迭代闭环四问</h2>
<div class="grid">
<div class="card"><h3>① 什么在飞(git 未提交 12 + 未跟踪 8)</h3>
<table><tr><th>分组</th><th>文件数</th></tr><tr><td>切片代码</td><td>5</td></tr><tr><td>GDD 文档</td><td>3</td></tr><tr><td>数据表</td><td>2</td></tr><tr><td>其他</td><td>1</td></tr><tr><td>会话产物</td><td>1</td></tr></table>
<p class="dim" style="margin:8px 0 0">未跟踪: </p><ul><li>.zcode/plans/</li><li>design/art/asset-checklist.md</li><li>design/research/proposal-reward-cell-differentiation-2026-09-17.md</li><li>docs/proposal-status-vocabulary.md</li><li>production/loop-dashboard.html</li><li>production/qa/dashboard-preview.png</li><li>prototypes/dungeon-sweeper-vertical-slice/smoke/config_fatal_probe.gd.uid</li><li>tools/loop_dashboard.py</li></ul></div>
<div class="card"><h3>② 什么待拍板 / 待执行(06 清单 53 条)</h3>
<p>待办 44 · 部分收口 6 · 拍板待执行 3 ·
<span class="stale">解决态残留 0</span>(按「解决即移除」口径待清)</p>
<table><tr><th>循环</th><th>开放</th><th>总条数</th></tr><tr><td>排雷循环</td><td>9</td><td>9</td></tr><tr><td>战斗循环</td><td>22</td><td>22</td></tr><tr><td>冒险循环</td><td>12</td><td>12</td></tr><tr><td>表现与支撑</td><td>10</td><td>10</td></tr></table>
<p class="dim" style="margin:8px 0 0">完整清单见下方「待办清单全目」专区。</p></div>
<div class="card"><h3>③ 什么要人玩(07 体验验证 8 项)</h3>
<ul><li>① Boss 战节奏(最高优先)</li><li>② 削弱续时后的承伤压力</li><li>③ 增伤全段覆盖的数值手感</li><li>④ 乏力的可感知性</li><li>⑤ 失衡换轴的归因可读性(P2 关注)</li><li>⑥ 速杀退化预警(监控口径,2026-09-18 定案)</li><li>⑦ 刷新经济监控(日志先行,阈值等基线)</li><li>⑧ 旗行为基线监控(插旗提案评估前置采集,2026-09-19 拍板)</li></ul></div>
<div class="card"><h3>④ 验证是否落后于文档(失效面检测)</h3>
<p class="dim">07 头部批次来源: **战斗数值四连批**(2026-09-18 ~ 09-19,版本锚 = 战斗结算 v0.16 / 增益状态 v0.9 / 地图战斗资源 v0.11)——① 战斗数值结构修复批(乘区接线四件套 + 削弱续时,v0.14)→ ② 甲效矩阵用户</p>
<table><tr><th>文档</th><th>07 引用</th><th>现行版本</th><th>判定</th></tr><tr><td>战斗结算</td><td>v0.16</td><td>v0.16</td><td><span class="ok">一致</span></td></tr><tr><td>增益状态</td><td>v0.9</td><td>v0.9</td><td><span class="ok">一致</span></td></tr><tr><td>地图战斗资源</td><td>v0.11</td><td>v0.11</td><td><span class="ok">一致</span></td></tr></table>
<p class="ok">引用与现行版本一致。</p>
<h3 style="margin-top:12px">重测批义务(07 原文)</h3>
<ul><li>**Boss 战必须单独出列**(硬化行为变化——旧 Boss 承伤 84.8% 等读数全部作废)。</li><li>普通场承伤带、通关率基线全量重测(削弱续时 + 乘区接线 + 甲效量纲换装 + 充能退役 多变量叠加,禁与任何旧读数混算)。</li><li>旧读数作废清单:池触底免伤轮相关读数、硬化翻倍期全部战斗读数、乏力死效果期格面调研读数、充能期(三分量输出)全部战斗读数。</li><li>工具就位:`analyze_playtest.py`(反事实分析,吃新日志)、`level_monte_carlo`(MC 基线重跑)、JSONL 日志含池值与快照。</li></ul></div>
</div>
<h2>GDD 文档新鲜度(28 份,按改动时间)</h2>
<table><tr><th>文档</th><th>版本</th><th>版本日期</th><th>文件改动</th><th>标题</th></tr><tr><td colspan='5' class='dim' style='background:#22252c'>顶层文档(8)</td></tr><tr><td>06-待办清单 <span class="dirty">在飞</span></td><td>—</td><td class='dim'>—</td><td class='dim'>09-19 05:32</td><td class='dim'>06-待办清单</td></tr><tr><td>07-体验验证清单 <span class="dirty">在飞</span></td><td>—</td><td class='dim'>—</td><td class='dim'>09-19 05:32</td><td class='dim'>07-体验验证清单</td></tr><tr><td>01-核心循环</td><td>—</td><td class='dim'>—</td><td class='dim'>09-19 01:57</td><td class='dim'>核心循环</td></tr><tr><td>02-系统清单</td><td>v0.7</td><td class='dim'>2026-09-17</td><td class='dim'>09-18 18:44</td><td class='dim'>系统清单</td></tr><tr><td>03-内容规模</td><td>v0.3</td><td class='dim'>2026-09-17</td><td class='dim'>09-18 00:35</td><td class='dim'>内容规模</td></tr><tr><td>05-不做清单</td><td>—</td><td class='dim'>—</td><td class='dim'>09-17 01:25</td><td class='dim'>不做清单</td></tr><tr><td>00-游戏概念</td><td>—</td><td class='dim'>—</td><td class='dim'>09-16 00:41</td><td class='dim'>游戏概念</td></tr><tr><td>04-美术音频方向</td><td>—</td><td class='dim'>—</td><td class='dim'>09-14 21:40</td><td class='dim'>美术音频方向</td></tr></table>
<h2>待办清单全目(按循环)</h2>
<div class="grid"><div class='card'><h3>排雷循环 · 开放 9/9</h3><ul><li><span class="tag open">待办</span>行动经济 · 刷新经济性监控(基线后定阈值)</li><li><span class="tag open">待办</span>地形变异 · 首批变异类型(岩浆/冰冻)机制未定</li><li><span class="tag open">待办</span>地形变异 · 生成期布置的约束与参数未定稿</li><li><span class="tag open">待办</span>地形变异 · 全局作用域变异</li><li><span class="tag open">待办</span>地形变异 · 变异格对初始展开的影响语义</li><li><span class="tag open">待办</span>地形变异 · 显影尘效果重定</li><li><span class="tag open">待办</span>地形变异 · 地穴全图卷效果重定</li><li><span class="tag open">待办</span>地形变异 · 反制维度承载失义</li><li><span class="tag open">待办</span>地形变异 · 探宝罗盘效果重定——两方案评估(2026-09-19 立项)</li></ul></div><div class='card'><h3>战斗循环 · 开放 22/22</h3><ul><li><span class="tag open">待办</span>战斗结算 · 挖掘风险不等式对账破线</li><li><span class="tag open">待办</span>战斗结算 · 清图支配性保守地板缺口</li><li><span class="tag open">待办</span>敌人系统 · 单拍行为环的体验验证(改型:技能池节奏体验验证)</li><li><span class="tag open">待办</span>敌人系统 · 伏击量纲与上限的联动复核</li><li><span class="tag open">待办</span>敌人系统 · 零伤害 / 无威胁组合的跨字段护栏</li><li><span class="tag partial">部分收口</span>敌人系统 · 同深度第二敌种与精英 / Boss 编码位</li><li><span class="tag decided">拍板待执行</span>敌人系统 · 敌方护甲等级(armor_class)正式行值</li><li><span class="tag open">待办</span>敌人系统 · 技能池情境条件触发器</li><li><span class="tag open">待办</span>敌人系统 · 个体化变体池</li><li><span class="tag open">待办</span>敌人系统 · 全局特殊间隔旋钮</li><li><span class="tag decided">拍板待执行</span>敌人系统 · 技能池新效应词汇批</li><li><span class="tag open">待办</span>敌人系统 · 第二关技能池与投放</li><li><span class="tag open">待办</span>敌人系统 · 敌方技能图鉴 / 学习呈现</li><li><span class="tag open">待办</span>敌人系统 · Alpha:全怪物技能池数值验证与合理性设计</li><li><span class="tag open">待办</span>增益状态 · 叠层不续命的读感</li><li><span class="tag open">待办</span>增益状态 · 削弱档位的最终数值</li><li><span class="tag open">待办</span>增益状态 · 单体寻址的接口扩展位</li><li><span class="tag open">待办</span>增益状态 · 空刷新的可见性</li><li><span class="tag partial">部分收口</span>地图战斗资源 · heal 负向直伤的量级锚</li><li><span class="tag open">待办</span>地图战斗资源 · 雷格与安全格的资源分布差异化(Alpha 批)</li><li><span class="tag open">待办</span>地图战斗资源 · 冒险前资源配比预设(构筑提案)</li><li><span class="tag open">待办</span>战斗表现 · 敌人卡形态</li></ul></div><div class='card'><h3>冒险循环 · 开放 12/12</h3><ul><li><span class="tag decided">拍板待执行</span>关卡节点地图 · 首遇位教学敌可被棋盘火力一轮击杀</li><li><span class="tag partial">部分收口</span>关卡节点地图 · 切片行进代码与定稿的接口漂移</li><li><span class="tag open">待办</span>关卡节点地图 · 两关序列未生效</li><li><span class="tag open">待办</span>关卡节点地图 · 大奖励数值随难度曲线联动</li><li><span class="tag open">待办</span>关卡节点地图 · 冒险循环内成长提案(临时资源 GP + 商店房节点)</li><li><span class="tag open">待办</span>难度曲线与Boss · 基线通关率越带,加难杠杆扫描未执行</li><li><span class="tag open">待办</span>难度曲线与Boss · 完美策略档的结构性加难杠杆</li><li><span class="tag open">待办</span>难度曲线与Boss · 真人通关率标定</li><li><span class="tag open">待办</span>难度曲线与Boss · 区间平移换算率数值未定</li><li><span class="tag partial">部分收口</span>难度曲线与Boss · 三方向各自的解锁清单与定价</li><li><span class="tag partial">部分收口</span>难度曲线与Boss · 解锁注入的实现口径</li><li><span class="tag partial">部分收口</span>难度曲线与Boss · 解锁界面与钥石呈现的交互形态</li></ul></div><div class='card'><h3>表现与支撑 · 开放 10/10</h3><ul><li><span class="tag open">待办</span>HUD框架 · 未开格类型徽章呈现时机(2026-09-18 方向已拍板,待实施批)</li><li><span class="tag open">待办</span>HUD框架 · 分辨率档位与棋盘格边长口径</li><li><span class="tag open">待办</span>数据配置 · 变异表旧字段集是否沿用Line truncated
<h2>路线图(production/roadmap.md)</h2>
<div class="card"><ol><li>1. **技能池实施批(已落地,smoke 263 全绿;待一笔收编提交)**:批 1 核心机制 + 批 2 呈现替代 + 批 3 文档与 registry 已完成;收编提交后本站闭合。设计权威 = `docs/proposal-skill-pool.md`。</li><li>2. **验收批**(门 = 技能池批收编 + 工作区净 + smoke 全绿):按 `docs/acceptance-ap6-ac.md` v1.0 跑三数据源(蒙特卡洛双档 / 真人 3–5 局 / 日志分析器),无道具基线;产出判读结论与选档建议。</li><li>3. **难度曲线阶段二调参批**(门 = 验收读数):四级阶梯落档 + 三杠杆扫描(血量锚走廊 / 群战上探 / 注入衰减)+ 挖掘风险不等式与清图支配性两对账重跑 + AC 行值投值。</li><li>4. **第二关内容批**(门 = 调参行值):深度轴行值 D1–D4 填充 + 新内容投放(技能池定稿后 = 既有池新技能);填齐后两关序列生效。</li><li>5. **并行 / 后置轨道**:关卡节点地图 GDD 定稿批(已解锁,与在飞批零文件冲突);魔法道具内容批(排切片收尾后);真人通关率标定(挂 playtest 批);元进度定稿(排 Alpha 前收口——资源关系已裁统一钥石〔2026-09-17〕,剩解锁清单/定价与钥石产出细则)。</li></ol></div>
<h2>台账健康</h2>
<div class="card"><p>台账区(「Session Extract — /review-all-gdds 2026-09-14」之后)最新编号 <b>82</b>,下一编号建议 <b>83</b>;检出撞号 72, 75, 76, 77, 78(编号有效、历史不改写)。</p></div>
<h2>近期提交</h2>
<div class="card"><ul><li><code>e66d156</code> feat(slice): 充能退役+board_type 词表定稿+06 待办两轮清理批(2026-09-19 用户逐项拍板)——含并行会话未提交工作一并入库</li><li><code>03264bd</code> docs(gdd): 战斗数值四议题收口批——议题二/四登记补全+叠层调研报告(修复批 b51af08 的讨论场残留)——①06-待办关卡节点图节新增「首遇位教学敌可被棋盘火力一轮</li><li><code>b51af08</code> fix(slice): 战斗数值结构修复批——乘区接线四件套+削弱续时(2026-09-18 盘问会话用户拍板,直接执行)——①主角侧乘区接线:主角攻击 Σ三分量后 ×(100+h</li><li><code>b7d1b56</code> chore(session): 收口杂项批——Stop 守卫强判据升级(active.md 登记判据 mtime→内容哈希,touch/意外改时间不再蒙混;三态实测 0/2/0)+</li><li><code>0da19a5</code> feat(slice): 措辞收口+数值对齐+场景一/三拍板落地批——①registry 指路化收口:主角条目去 MVP 值改读 hero.tres、技能条目七行枚举(补收撕咬/毒</li></ul></div>
<footer>
数据源: production/session-state/active.md · production/roadmap.md · production/stage.txt ·
design/gdd/06-待办清单.md · design/gdd/07-体验验证清单.md · design/gdd/** · git status/log。
生成工具 tools/loop_dashboard.py;六处信息源格式变更时同步改解析约定(见工具头注)。
</footer>
</main>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 677 KiB

+5 -2
View File
@@ -12,7 +12,8 @@
## 当前状态快照(收口批先更新本节,再追加台账;≤10 行)
- **更新于**:2026-09-20(**伏击上限删除批 + 格面资源八型批**,独立 worktree 分支 ambush-cap-review-20260920,台账 101):用户三段拍板——①伏击单轮授予上限删除(反灾难护栏退役,一轮踩雷数由行动点天然封顶)→ 继而系统设计全字典对账后②伏击整体退役换装警觉(敌方全体护甲等级 +1,blast 负向)+新增 action 第 8 型(行动点下轮 ±1 排队)+护甲型数值对齐 ±1;冒烟 330 项 0 失败;分支未合 master;承伤/通关读数再度位移,归曲线调参批重投
- **更新于**:2026-09-20(**伏击上限删除批 + 格面资源八型批**,独立 worktree 分支 ambush-cap-review-20260920,台账 101):用户三段拍板——①伏击单轮授予上限删除(反灾难护栏退役,一轮踩雷数由行动点天然封顶)→ 继而系统设计全字典对账后②伏击整体退役换装警觉(敌方全体护甲等级 +1,blast 负向)+新增 action 第 8 型(行动点下轮 ±1 排队)+护甲型数值对齐 ±1;冒烟 330 项 0 失败;承伤/通关读数再度位移,归曲线调参批重投
- **更新于**:2026-09-20(**主角增益只续时不叠层批**,独立 worktree 分支 buff-refresh-20260920,台账 102〔登记时撞对方 101 号,顺延让号〕):用户拍板「主角的增益也一样,只续时不叠层,变相削弱主角性能可接受」——attack_up(增伤)/ ac_up(护甲强化)两行 stack_policy stack→refresh,对齐削弱 2026-09-18 续时定案;至此主角可重复获取的增益/减益合并语义统一(叠层仅剩敌侧行)。duration=1/max_stack=2 表值不动(refresh 下 max_stack 不消费;dur=1 下续时=重复拿重置当轮倒数,跨轮延续随 duration 拉长显形,数值归状态层重设计批)。影响面:增伤不再 +100%(池单层封顶 +50)、护甲强化不再 +2 AC(局内可达 AC 上限 11——AC12 采样探针随行降 AC11)、两行不再可达满层拒绝行。文档:增益状态 v0.12(合并策略表/例子表/调参表/联动纪律/验收条)+registry 两行+06「叠层不续命的读感」解决移除;冒烟三闸全过
- **更新于**:2026-09-20(**伤害下限全来源批**,独立 worktree 分支 damage-floor-20260920,台账 100):用户拍板「任何伤害取值域 [1,+∞),最小值一定是 1——不分敌我全来源」——①下限语义从"任何攻击落地"扩为"任何伤害落地":棋盘克制直伤(counter_component 增 landed_floor 参数,空桶恒 0 边界不变)+爆裂正向+负向反噬(穿刺陷阱/魔法反噬/heal 反噬)+地形变异 flat_damage 收进 damage_floor 闸,攻击双方原有闸不动;②取值域成文 [1,+∞) **不设上限**——06「零伤害/无威胁组合的跨字段护栏」整条解决移除(45→44 条):上界护栏半边随"不设上限"裁决、0 基线退化敌经下限自然消解;③现行表值零行为变更(贴底值 2−1=1 本就 ≥1),纯结构保证+调参防误配;④战斗结算 v0.19(版本号与未合并伏击分支撞号,合并时先落籍者为准顺延避让)+registry ac_roll+settlement_table.gd 注释;冒烟 352→355 项 0 失败三闸全过(+贴底/穿透/空桶三断言)
- **更新于**:2026-09-20(**敌人卡形态裁决收口批**,独立 worktree 分支 enemy-form-20260920,台账 99):用户看对照样张拍板**全站桩形态**——B 区主角与敌人均为无框立绘+底座(主角站桩、状态小图标挂血条正下方),英雄卡/敌人卡卡片式整体退役;06 清单「敌人卡形态」解决移除(清单 46→45 条);battle.md 回写(B 区行/组件表两行/线框图 B 区重绘/OQ4)+战斗表现 v0.4(相邻裁定改裁决已下+样张对照项解除)+HUD框架 v0.6(B 区行+敌人呈现义务行载体改立绘)+敌人系统一行+美术清单两处(对照义务解除,正式样张按站桩单版出样);对照样张存档 production/mockups/(双形态对照+定稿形态+HTML 源);纯文档零代码,冒烟不适用;表现层升级批的敌人卡形态前置就此解锁
- **更新于**:2026-09-20(**显影尘待办条目移除批**,独立 worktree 分支 probe-dust-todo-20260920,台账 98):用户拍板「显影尘效果重定」条目删除——辅助道具(魔法道具)统一在 Alpha 阶段重新设计,垂直切片期不需要相关内容;06 清单 47→46 条(解决即移除口径,去向=并入 Alpha 阶段魔法道具整体重设计);连带悬空指认清偿四处——06 反制条目合流从句改写、魔法道具.md 信息维度存根行、03-内容规模.md 待定句、registry aux_items 三处「魔法道具 待办」指针改指 Alpha 重设计(名称保留、六行登记不动;历史修订块豁免);地穴全图卷/探宝罗盘两条目未动(探宝罗盘已排 Alpha 在案)。纯文档零代码,冒烟不适用
@@ -261,4 +262,6 @@
100. **伤害下限全来源批(2026-09-20,本会话——用户在 06 清单三决断项呈报中对「零伤害/无威胁组合的跨字段护栏」直接给词表:「攻击伤害算到最后不能够是 0 或负数,取值范围 1 到 +∞,不管是角色对怪兽、怪兽对角色、还是其他所有造成的伤害,最小取值一定是 1」;worktree damage-floor-20260920)**:**盘点**——全伤害落点六类:主角攻击→敌(battle_orchestrator 战斗段)与敌方技能攻击→主角两路径 2026-09-16 掷点批已落 damage_floor 闸;棋盘克制直伤(pierce/magic 正向,DamageMath.counter_component 无下限——现值 2+(−1)=1 恰好贴底无结构保证)、爆裂正向、负向反噬(穿刺陷阱/魔法反噬/heal 反噬→主角)、地形变异 flat_damage 四类为表值直落无闸。**落地**——①counter_component 增第三参 landed_floor(缺省 0 保持旧签名行为;空桶〔点数≤0〕恒 0 边界不变——无伤害落地无下限可言,与"空桶不吃修正"拍板兼容);②battle_orchestrator 四落点全部 maxi(damage_floor, ·) 保底(blast 正向逐敌/穿刺魔法负向/heal 负向/地形变异);③apply_damage n≤0 拒绝语义保留作真 bug 兜底(闸后不可达)。**裁决面**——06 条目两个半边一并收口:上界护栏半边(基线×倍率上界 vs 主角生命上限)随「取值域 [1,+∞)」拍板裁决为**不设上限**;退化态半边(敌种行攻击基线 0 且上限 0 → 无威胁敌)经下限自然消解——0 基线攻击落地仍 ≥1,"无威胁敌"结构性不存在(内容调参禁区约束随之失去对象)。**现行表值零行为变更**(全部落点现值本就 ≥1),本批=结构保证+调参防误配(power 降档/克制修正域扩到 −3 时不再可能打出 0/负伤害)。**文档**——战斗结算 v0.19(判读口径/约束表/调参表/验收四处"任何攻击落地"改"任何来源的伤害落地"+取值域成文;版本号与未合并伏击分支撞号,合并时先落籍者为准顺延避让)+registry settlement_table.ac_roll 行同步+settlement_table.gd 两处注释+06 条目解决移除(45→44 条)。**验证**——冒烟 352→355 项 0 失败三闸全过(+counter_component 贴底/触底穿透/空桶三断言;新检出 worktree 需先 --editor --quit 刷类缓存);gdd_lint 不适用本批文件面。
101. **伏击上限删除批 + 格面资源八型批(2026-09-20,本会话——用户先拍板「单轮上限没必要,可以把它取消掉」;继而在奖励/惩罚镜像对账讨论中拍板:群伤负向换装「敌方护甲等级+1」(否决「怪物加一层减伤受伤−1」——加法核下退化)、新增行动点第 8 型、护甲型数值对齐 ±1;worktree ambush-cap-review-20260920,两笔提交 656f000 / 84a3364,未合 master)**:**批 1 上限删除**——enemy.tres 十二行 advantage_per_round_cap + 编排器截流 + 单位容器 F3 计划函数 + 溢出未生效行协议退役(行协议 10→9 类:唯一发射源=伏击截流;满层拒收走奖励未生效行,增益状态文档三处行名随代码对齐)+ 06「混编遭遇伏击上限取哪行」歧义连根消解;**批 2 八型**——①伏击整体退役:伤害公式拆伏击附加项、快照 ambush_layers 拆除、毒爆/效果行断言与伤害探针同步;②blast 负向 = enemy_alert 警觉(敌方全体护甲等级 +1/层、1 结算、side-wide 逐颗叠加无上限)——_defender_ac 敌方侧 ac 型状态读法本批接线;③第 8 型 action = ap_up 行动点(正向,下轮 AP+1,weight 6)/ ap_drain 迟滞(负向,−1)——action_economy 排队面 queue_ap_delta/pending_ap_delta 新增、notify_round_start 兑现(基线 6+净值、下限 0、兑现清零)、明细记 effect 行;④off_guard −2→−1;⑤文档同步 = 敌人系统 v0.12(伏击节退役改写)/战斗结算 v0.20/地图战斗资源 v0.14(八型字典十六格)/行动经济 v0.5(下轮行动点修正节+F1 条款 3 伏击暴露口径作废)/难度曲线与Boss v0.15/增益状态 v0.8/06 清单(伏击量纲条目随批解决删除+调参批数值点评登记)/registry 22 处/ux battle/关卡节点地图;⑥工具 = analyze_playtest M_AMB 归零保旧日志兼容、clear_dominance 伏击暴露模型转历史口径注记。**验证**——冒烟 330 项 0 失败三闸全过 + gdd_lint 与 master 基线一致(8 文件存量)。**遗留**——警觉/行动点数值 provisional、行动经济「满停一轮=一刷」节拍对账、增伤 50/25 等调参点评(06 已登记归曲线调参批);承伤/通关读数再度位移,07⑨ 真人批建议在终版规则上执行
101. **伏击上限删除批 + 格面资源八型批(2026-09-20,本会话——用户先拍板「单轮上限没必要,可以把它取消掉」;继而在奖励/惩罚镜像对账讨论中拍板:群伤负向换装「敌方护甲等级+1」(否决「怪物加一层减伤受伤−1」——加法核下退化)、新增行动点第 8 型、护甲型数值对齐 ±1;worktree ambush-cap-review-20260920,两笔提交 656f000 / 84a3364)**:**批 1 上限删除**——enemy.tres 十二行 advantage_per_round_cap + 编排器截流 + 单位容器 F3 计划函数 + 溢出未生效行协议退役(行协议 10→9 类:唯一发射源=伏击截流;满层拒收走奖励未生效行,增益状态文档三处行名随代码对齐)+ 06「混编遭遇伏击上限取哪行」歧义连根消解;**批 2 八型**——①伏击整体退役:伤害公式拆伏击附加项、快照 ambush_layers 拆除、毒爆/效果行断言与伤害探针同步;②blast 负向 = enemy_alert 警觉(敌方全体护甲等级 +1/层、1 结算、side-wide 逐颗叠加无上限)——_defender_ac 敌方侧 ac 型状态读法本批接线;③第 8 型 action = ap_up 行动点(正向,下轮 AP+1,weight 6)/ ap_drain 迟滞(负向,−1)——action_economy 排队面 queue_ap_delta/pending_ap_delta 新增、notify_round_start 兑现(基线 6+净值、下限 0、兑现清零)、明细记 effect 行;④off_guard −2→−1;⑤文档同步 = 敌人系统 v0.12(伏击节退役改写)/战斗结算 v0.20/地图战斗资源 v0.14(八型字典十六格)/行动经济 v0.5(下轮行动点修正节+F1 条款 3 伏击暴露口径作废)/难度曲线与Boss v0.15/增益状态 v0.11(格面八型行——原分支内报 v0.8 系旧基线编号,合并时顺延)/06 清单(伏击量纲条目随批解决删除+调参批数值点评登记)/registry 22 处/ux battle/关卡节点地图;⑥工具 = analyze_playtest M_AMB 归零保旧日志兼容、clear_dominance 伏击暴露模型转历史口径注记。**验证**——冒烟 330 项 0 失败三闸全过 + gdd_lint 与 master 基线一致(8 文件存量)。**遗留**——警觉/行动点数值 provisional、行动经济「满停一轮=一刷」节拍对账、增伤 50/25 等调参点评(06 已登记归曲线调参批);承伤/通关读数再度位移,07⑨ 真人批建议在终版规则上执行
102. **主角增益只续时不叠层批(2026-09-20,本会话——用户对「叠层不续命的读感」条目两轮澄清后拍板「主角的其实也一样,都是按照叙事的方式,不要有叠层。只续时不叠层;虽然变相削弱了主角的性能,但是我觉得是可以接受的」;worktree buff-refresh-20260920,登记撞对方 101 号顺延让号)**:**澄清前置**——用户先质疑该条目与记忆中的 buff 整改冲突,经 git/文档/表值三方核查确认:2026-09-16 敌人技能池批(empower/fortify)与 2026-09-18 结构修复批(weaken)的续时改型只覆盖敌方侧三行,主角侧 attack_up / ac_up 从未改过——条目背景澄清无误后用户直接给语义裁决。**落地**——① status_effects.tres 两行 stack_policy stack→refresh(duration_settlements=1 与 max_stack=2 表值不动:refresh 下层数恒 1、max_stack 不消费——weaken 先例;dur=1 下续时表现为重复拿重置当轮倒数,跨轮延续随将来 duration 拉长自然显形,数值归状态层重设计批);② 容器/消费侧零代码改动(refresh 容器既有,池与 AC 消费面按层数泛化读取)。**行为影响**——增伤不再 +100%(hero_offense 池单层封顶 +50)、护甲强化不再 +2 AC(局内可达 AC 上限 10+1=11)、两行不再可达满层拒绝行——用户已知悉接受削弱方向。**文档**——增益状态 v0.12(同名合并策略表刷新行内容行清单+幅度量纲例子表第二例改"护甲强化再拿一份"+调参表初始剩余次数/叠层上限两行+联动纪律句 AC 上限 11 注记+验收"叠层不减钟"条加策略限定+概览与衰减节两处叠层措辞)+registry attack_up/ac_up 两行+06 清单「叠层不续命的读感」解决移除。**验证**——冒烟三闸全过(ac_up 行断言 stack→refresh 改形、AC12 折扣档采样探针随行降为 AC11 单授——_ac12_tier_samples 更名 _ac11_tier_samples,无净增断言;与八型批伏击退役改动在合并后同套跑绿)。
@@ -11,7 +11,7 @@ rows = [{
"magnitude": 50,
"unit": "percent",
"duration_settlements": 1,
"stack_policy": "stack",
"stack_policy": "refresh",
"max_stack": 2
}, {
"effect_id": "ac_up",
@@ -20,7 +20,7 @@ rows = [{
"magnitude": 1,
"unit": "ac",
"duration_settlements": 1,
"stack_policy": "stack",
"stack_policy": "refresh",
"max_stack": 2
}, {
"effect_id": "weaken",
@@ -125,3 +125,8 @@ rows = [{
; ② ambush(伏击)行整体退役——群伤负向不再放大敌方伤害;③ 新增 alert(警觉:敌方护甲等级 +1,
; target_side enemy、unit ac、1 结算、stack 上限 16)——blast 型负向新载体,消费 = _defender_ac 敌方侧
; ac 型读法(本批新接线)。状态表九行→九行(伏击出、警觉进)。数值全部 provisional 归 难度曲线与Boss。
;
; 主角增益只续时不叠层批(2026-09-20 用户拍板「主角的其实也一样,都是按照叙事的方式,不要有叠层;只续时不叠层」——
; 对齐削弱 2026-09-18 续时定案):attack_up / ac_up 两行 stack_policy stack→refresh;
; duration_settlements=1 与 max_stack=2 表值不动(refresh 下层数恒 1、max_stack 不消费——weaken 先例;
; dur=1 下续时表现为重复拿重置当轮倒数,跨轮延续随将来 duration 拉长自然显形——数值归状态层重设计批)。
@@ -229,7 +229,7 @@ func _smoke_level() -> void:
# ---- 护甲等级掷点批·换装护栏(2026-09-16 用户拍板:百分比减伤行整体退役换装 AC,无双轨)----
# ① 换装在位:defense_up 状态行/池映射/奖励行三处全无残留,ac_up 三处就位(unit=ac ×2 层);
# ① 换装在位:defense_up 状态行/池映射/奖励行三处全无残留,ac_up 三处就位(unit=ac,2026-09-20 改只续时不叠层);
# ② 免伤墙归零护栏泛化保留(BUG-0003 事故类永久免疫):hero_defense 池任何 percent 行
# magnitude × max_stack > pool_clamp_lo——单效果叠满不可触池底(off_guard 已于 2026-09-18
# 结构修复批退离 hero_defense 池换装 AC 轴,池内现无 percent 行——本断言防未来负向行回归时静默造墙);
@@ -243,8 +243,8 @@ func _smoke_ac_swap_guard() -> void:
var ac_row: Dictionary = _db.status_effect_row("ac_up")
check(not ac_row.is_empty() and String(ac_row.get("target_side", "")) == "hero" \
and String(ac_row.get("unit", "")) == "ac" and int(ac_row.get("magnitude", 0)) == 1 \
and int(ac_row.get("max_stack", 0)) == 2 and String(ac_row.get("stack_policy", "")) == "stack",
"ac_up 行在位(hero · +1 ac · ×2 层 · stack——AC 阈值轴新量纲)")
and String(ac_row.get("stack_policy", "")) == "refresh",
"ac_up 行在位(hero · +1 ac · 只续时不叠层——2026-09-20 主角增益续时批)")
var ac_reward := {}
for row in _db.reward.rows:
if String(row.get("cell_type", "")) == "defense" and String(row.get("polarity", "")) == "positive":
@@ -327,16 +327,17 @@ func _smoke_armor_roll() -> void:
"削弱重复授予 → 层数保持 1、剩余结算数重置 2(续时语义——结构性消饱和)")
check(int(weaken_probe.get("pool", -999)) == int(_db.status_effect_row("weaken").magnitude),
"削弱单层池读数 = 行值(enemy_output 池单层贡献——×2 叠满触底 ×0 不可达,免伤轮根治)")
# ④ AC12 折扣档分布(行为面):ac_up ×2 逐轮授给(时效 1)→ Boss 行攻击拍逐拍判定
var tiers := _ac12_tier_samples()
# ④ AC11 折扣档分布(行为面):ac_up 逐轮授给(时效 1)→ Boss 行攻击拍逐拍判定
# (2026-09-20 主角增益续时批后 ac_up 层数恒 1——局内可达 AC 上限 10+1=11,探针随行下调)
var tiers := _ac11_tier_samples()
var tier_distinct := {}
var tiers_valid := true
for t in tiers:
tier_distinct[int(t)] = true
if not [100, 75, 50, 25].has(int(t)):
tiers_valid = false
check(tiers_valid and tiers.size() >= 3, "AC12 攻击拍逐拍判定(×%d 拍全部落档域 {100,75,50,25})" % tiers.size())
check(tier_distinct.size() >= 2, "折扣档实际流动(AC12 实测档位 %s——≥2 档可见)" % str(tier_distinct.keys()))
check(tiers_valid and tiers.size() >= 3, "AC11 攻击拍逐拍判定(×%d 拍全部落档域 {100,75,50,25})" % tiers.size())
check(tier_distinct.size() >= 2, "折扣档实际流动(AC11 实测档位 %s——≥2 档可见)" % str(tier_distinct.keys()))
# ⑤ 棋盘来源必中 + 吃掷点行留档(全战斗流扫描)
var run = _run_battle(1, 0)
var board_ok := true
@@ -399,9 +400,10 @@ func _weaken_refresh_probe() -> Dictionary:
return {}
# AC12 折扣档采样:每停手轮前直授 ac_up ×2(时效 1 逐轮衰减)——敌拍逐拍判定留档。
# 敌人技能池批:拍序改为摇号制,原 AC 批定影种子不再保证档位多样性——扫描种子取首个 ≥2 档样本集。
func _ac12_tier_samples() -> Array:
# AC11 折扣档采样:每停手轮前直授 ac_up ×1(时效 1 逐轮衰减)——敌拍逐拍判定留档。
# (2026-09-20 主角增益续时批:ac_up 只续时不叠层、层数恒 1——原 ×2 授给达 AC12 的采样随批降为 AC11;
# 敌人技能池批:拍序改为摇号制,原 AC 批定影种子不再保证档位多样性——扫描种子取首个 ≥2 档样本集。)
func _ac11_tier_samples() -> Array:
for seed_offset in range(20):
var rng = load("res://core/rng_service.gd").new()
rng.set_master_seed(20260917 + seed_offset)
@@ -413,8 +415,7 @@ func _ac12_tier_samples() -> Array:
var guard := 12
while settlement.battle_result == "" and guard > 0:
guard -= 1
for i in range(2):
settlement._status_effects.apply_effect("ac_up", {"source_class": "safe_cell", "origin_cell": Vector2i(0, 0), "round_index": settlement.round_index})
settlement._status_effects.apply_effect("ac_up", {"source_class": "safe_cell", "origin_cell": Vector2i(0, 0), "round_index": settlement.round_index})
settlement.minesweeper.settle_batch([{"action": "stop"}])
var tiers: Array = []
for row in rows:
+525
View File
@@ -0,0 +1,525 @@
#!/usr/bin/env python3
r"""loop_dashboard.py — 迭代闭环仪表盘生成器
用法:
python tools/loop_dashboard.py # 生成 production/loop-dashboard.html + 控制台摘要
python tools/loop_dashboard.py --open # 生成后用系统默认浏览器打开
python tools/loop_dashboard.py --out <path>
定位: 项目开发循环 = 「完善文档 → 更新垂直切片游玩体验 → 再完善文档」。
闭环状态分散在六处——active.md 快照节 / 台账 / GDD 版本史 / 06-待办清单 /
07-体验验证清单 / git 在飞改动——本工具把六处聚合成一个只读视图,每次迭代
收口后重跑一次即可看清: 走到哪了、什么在飞、什么待拍板、什么验证项已落后于文档改动。
只读工具: 不改任何被扫描的文件,产物只有仪表盘 HTML 本身。
解析约定(跟随仓库现行格式,格式变了这里要跟着改):
- active.md 台账区 = 文件最后一个二级标题之后(新条目追加在文件末尾)
- GDD 版本 = 「版本历史」表中版本号最大的一行(行按时间追加)
- 06-待办清单条目 = 四级标题,状态 = 其下「**状态**:」行
- 07-体验验证清单头部「当前批次来源」行内引用的 vX.Y 与 GDD 现行版本比对,
得出「体验验证清单落后于文档改动」的失效面
"""
import argparse
import html
import os
import re
import subprocess
import sys
from collections import Counter, OrderedDict
from datetime import datetime
from pathlib import Path
ROOT = Path(__file__).resolve().parent.parent
GDD_DIR = ROOT / "design" / "gdd"
ACTIVE_MD = ROOT / "production" / "session-state" / "active.md"
ROADMAP_MD = ROOT / "production" / "roadmap.md"
TODO_MD = GDD_DIR / "06-待办清单.md"
VERIFY_MD = GDD_DIR / "07-体验验证清单.md"
STAGE_TXT = ROOT / "production" / "stage.txt"
DEFAULT_OUT = ROOT / "production" / "loop-dashboard.html"
LOOP_ORDER = ["顶层文档", "排雷循环", "战斗循环", "冒险循环", "表现与支撑"]
# 状态分类前缀 → 桶。解决即移除(2026-09-18 新口径)下「已解决/已裁决」残留 = 清理债。
RESOLVED_PREFIX = ("已解决", "已裁决")
PARTIAL_PREFIX = ("部分收口", "部分清偿", "已部分收口", "已部分清偿")
OPEN_PREFIX = ("待办",)
DECIDED_PREFIX = ("方向已拍板", "已拍板")
# ---------------------------------------------------------------- git 侧
def git(args):
try:
return subprocess.run(
["git", "-c", "core.quotepath=false"] + args,
capture_output=True, text=True, encoding="utf-8", errors="replace",
cwd=ROOT, check=True,
).stdout
except (subprocess.CalledProcessError, FileNotFoundError):
return ""
def classify_path(rel: str):
rel = rel.replace("\\", "/")
if rel.startswith("design/gdd/"):
return "GDD 文档"
if rel.startswith("design/"):
return "设计侧其他(registry/ux/art/research)"
if rel.startswith("prototypes/"):
if rel.endswith(".gd"):
return "切片代码"
if rel.endswith(".tres"):
return "数据表"
return "切片其他"
if rel.startswith("tools/"):
return "工具"
if rel.startswith("production/"):
return "会话产物"
return "其他"
def scan_git():
dirty, untracked = [], []
for line in git(["status", "--porcelain"]).splitlines():
if not line.strip():
continue
state, path = line[:2], line[3:].strip().strip('"')
if state.startswith("??"):
untracked.append(path)
else:
dirty.append((state.strip() or "M", path))
log = [l for l in git(["log", "--oneline", "-5"]).splitlines() if l.strip()]
grouped = Counter(classify_path(p) for _, p in dirty)
gdd_dirty = [p for s, p in dirty if classify_path(p) == "GDD 文档"]
return {
"dirty": dirty, "untracked": untracked, "log": log,
"grouped": grouped, "gdd_dirty": gdd_dirty,
}
# ---------------------------------------------------------------- GDD 清单
VERSION_ROW_RE = re.compile(r"^\|\s*v?(\d+)\.(\d+)\s*\|\s*(\d{4}-\d{2}-\d{2})")
def parse_doc(path: Path):
try:
text = path.read_text(encoding="utf-8")
except UnicodeDecodeError:
text = path.read_text(encoding="utf-8", errors="replace")
title = next((l.lstrip("# ").strip() for l in text.splitlines() if l.startswith("# ")), path.stem)
rel = path.relative_to(ROOT).as_posix()
parts = path.relative_to(GDD_DIR).parts
group = parts[0] if len(parts) > 1 else "顶层文档"
version, vdate = None, None
in_hist = False
for line in text.splitlines():
if line.startswith("## "):
in_hist = "版本历史" in line
continue
if in_hist:
m = VERSION_ROW_RE.match(line)
if m:
v = (int(m.group(1)), int(m.group(2)))
if version is None or v > version:
version, vdate = v, m.group(3)
mtime = datetime.fromtimestamp(path.stat().st_mtime).strftime("%m-%d %H:%M")
return {
"path": rel, "name": path.stem, "title": title, "group": group,
"version": f"v{version[0]}.{version[1]}" if version else "—",
"vdate": vdate or "—", "mtime": mtime,
}
def scan_gdd(git_info):
dirty_set = {p.replace("\\", "/") for p in git_info["gdd_dirty"]}
docs = [parse_doc(p) for p in sorted(GDD_DIR.rglob("*.md"))]
for d in docs:
d["dirty"] = d["path"] in dirty_set
return docs
# ---------------------------------------------------------------- active.md
LEDGER_ENTRY_RE = re.compile(r"^(\d+)\.\s+\*\*")
def scan_active():
info = {"snapshot_lines": [], "updated_line": "", "next_line": "",
"entries": [], "collisions": [], "next_number": None, "tail_head": ""}
if not ACTIVE_MD.exists():
info["error"] = "active.md 不存在"
return info
lines = ACTIVE_MD.read_text(encoding="utf-8").splitlines()
# 快照节(标题带纪律后缀,按关键词匹配)
in_snap = False
for line in lines:
if line.startswith("## "):
in_snap = "当前状态快照" in line
if in_snap:
continue
if in_snap and line.strip():
info["snapshot_lines"].append(line.strip())
for ln in info["snapshot_lines"]:
if ln.startswith("- **更新于**"):
info["updated_line"] = ln
if ln.startswith("- **下一步顺序**"):
info["next_line"] = ln
# 台账区 = 最后一个二级标题之后
last_h2 = max((i for i, l in enumerate(lines) if l.startswith("## ")), default=-1)
tail = lines[last_h2 + 1:]
info["tail_head"] = lines[last_h2].lstrip("# ").strip() if last_h2 >= 0 else ""
numbers = []
for line in tail:
m = LEDGER_ENTRY_RE.match(line)
if m:
numbers.append(int(m.group(1)))
info["entries"] = numbers
seen = Counter(numbers)
info["collisions"] = sorted(n for n, c in seen.items() if c > 1)
if numbers:
info["next_number"] = max(numbers) + 1
return info
# ---------------------------------------------------------------- 06 待办清单
def scan_todo():
items = []
if not TODO_MD.exists():
return items
loop = system = ""
cur = None
for line in TODO_MD.read_text(encoding="utf-8").splitlines():
if line.startswith("## "):
loop, system = line.lstrip("# ").strip(), ""
elif line.startswith("### "):
system = line.lstrip("# ").strip()
elif line.startswith("#### "):
cur = {
"loop": loop, "system": system,
"title": line.lstrip("# ").strip(),
"status": "",
}
items.append(cur)
elif cur is not None and line.startswith("**状态**"):
cur["status"] = line.replace("**状态**", "").lstrip(":: ").strip()
cur = None
for it in items:
s = it["status"]
if s.startswith(RESOLVED_PREFIX):
it["bucket"] = "解决态残留"
elif s.startswith(PARTIAL_PREFIX):
it["bucket"] = "部分收口"
elif s.startswith(OPEN_PREFIX):
it["bucket"] = "待办"
elif s.startswith(DECIDED_PREFIX):
it["bucket"] = "拍板待执行"
else:
it["bucket"] = "其他"
return items
# ---------------------------------------------------------------- 07 体验验证清单
VERSION_REF_RE = re.compile(r"(战斗结算|增益状态|地图战斗资源|敌人系统|行动经济|棋盘生成|排雷玩法|难度曲线与Boss|元进度|关卡节点地图|HUD框架|战斗表现|数据配置|存档序列化|音频|教学引导|设置与本地化|地形变异|冒险结构|魔法道具)\s*(v\d+\.\d+)")
def scan_verify(docs):
info = {"items": [], "obligations": [], "source_line": "", "refs": [], "error": None}
if not VERIFY_MD.exists():
info["error"] = "07-体验验证清单.md 不存在"
return info
text = VERIFY_MD.read_text(encoding="utf-8")
lines = text.splitlines()
section = ""
for line in lines:
if line.startswith("## "):
section = line.lstrip("# ").strip()
continue
if line.startswith("### ") and "观测项" in section:
info["items"].append(line.lstrip("# ").strip())
elif line.startswith("- ") and "重测批义务" in section:
info["obligations"].append(line[2:].strip())
m = re.search(r"当前批次来源:(.+)", text)
if m:
info["source_line"] = m.group(1).strip()
by_name = {d["name"]: d for d in docs}
for name, ver in VERSION_REF_RE.findall(info["source_line"]):
cur = by_name.get(name)
info["refs"].append({
"doc": name, "ref": ver, "current": cur["version"] if cur else "?",
"stale": bool(cur and cur["version"] != "—" and cur["version"] != ver),
})
return info
# ---------------------------------------------------------------- 路线图
def scan_roadmap():
steps = []
if not ROADMAP_MD.exists():
return steps
in_route = False
for line in ROADMAP_MD.read_text(encoding="utf-8").splitlines():
if line.startswith("## "):
in_route = "路线图" in line and "维护" not in line
continue
if in_route and re.match(r"^\d+\.\s", line):
steps.append(line.strip())
return steps
# ---------------------------------------------------------------- 控制台摘要
def print_summary(stage, git_info, docs, active, todos, verify, out_path):
def p(s=""):
print(s)
p("═" * 62)
p(f"迭代闭环仪表盘 · {datetime.now().strftime('%Y-%m-%d %H:%M')} · 阶段: {stage}")
p("═" * 62)
if active.get("updated_line"):
p(active["updated_line"].lstrip("- "))
g = git_info["grouped"]
p(f"在飞改动: {len(git_info['dirty'])} 文件(" +
" / ".join(f"{k} {v}" for k, v in g.most_common()) +
f")+ 未跟踪 {len(git_info['untracked'])}")
dirty_docs = [d for d in docs if d["dirty"]]
versioned = [d for d in docs if d["version"] != "—"]
newest = max(versioned, key=lambda d: d["vdate"], default=None)
p(f"GDD: {len(docs)} 份,其中在飞 {len(dirty_docs)} 份"
+ (f";最近改版 {newest['name']} {newest['version']}({newest['vdate']})" if newest else ""))
buckets = Counter(t["bucket"] for t in todos)
p(f"待办清单: {len(todos)} 条(待办 {buckets.get('待办', 0)} / 部分收口 {buckets.get('部分收口', 0)}"
f" / 拍板待执行 {buckets.get('拍板待执行', 0)} / 解决态残留 {buckets.get('解决态残留', 0)}"
f"←按「解决即移除」口径应移除)")
p(f"体验验证: {len(verify['items'])} 项待真人观测")
if active["collisions"]:
p(f"台账: 最新编号 {active['entries'][-1]},下一编号建议 {active['next_number']}"
f"(撞号: {', '.join(str(n) for n in active['collisions'])})")
else:
p(f"台账: 最新编号 {active['entries'][-1] if active['entries'] else '—'},下一编号建议 {active['next_number']}")
stale = [r for r in verify["refs"] if r["stale"]]
if stale:
p("⚠ 07-体验验证清单引用版本已落后:")
for r in stale:
p(f" {r['doc']}: 07 引 {r['ref']} / 现行 {r['current']}")
if active.get("next_line"):
p(active["next_line"].lstrip("- "))
p(f"已生成: {out_path.relative_to(ROOT).as_posix()}")
p("═" * 62)
# ---------------------------------------------------------------- HTML
CSS = """
:root{--bg:#14161a;--card:#1d2026;--line:#2c3038;--tx:#d8dce3;--dim:#8b919c;
--acc:#5b9dd9;--warn:#d9a05b;--bad:#d95b6a;--ok:#6fbf7f;}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--tx);
font-family:"Segoe UI","Microsoft YaHei","PingFang SC",sans-serif;font-size:14px;line-height:1.6}
main{max-width:1080px;margin:0 auto;padding:24px 20px 60px}
h1{font-size:22px;margin:0 0 4px}
h2{font-size:17px;margin:36px 0 10px;padding-bottom:6px;border-bottom:1px solid var(--line)}
.meta{color:var(--dim);font-size:12.5px;margin-bottom:8px}
.grid{display:grid;grid-template-columns:1fr 1fr;gap:14px;align-items:start}
@media(max-width:800px){.grid{grid-template-columns:1fr}}
.card{background:var(--card);border:1px solid var(--line);border-radius:8px;padding:14px 16px}
.card h3{margin:0 0 8px;font-size:14px;color:var(--acc)}
.card ul{margin:0;padding-left:18px}
.card li{margin:3px 0}
table{width:100%;border-collapse:collapse;background:var(--card);
border:1px solid var(--line);border-radius:8px;overflow:hidden;font-size:13px}
th,td{padding:6px 10px;text-align:left;border-bottom:1px solid var(--line);vertical-align:top}
th{color:var(--dim);font-weight:600;background:#22252c}
tr:last-child td{border-bottom:none}
.dirty{color:var(--warn);font-weight:600}
.tag{display:inline-block;padding:0 8px;border-radius:10px;font-size:12px;margin-right:6px}
.tag.open{background:#2b3a4a;color:#9cc7ec}
.tag.partial{background:#463d2b;color:#e0c08a}
.tag.decided{background:#3a3350;color:#c3b3ec}
.tag.resolved{background:#3c2b30;color:#e0999f}
.stale{color:var(--bad);font-weight:600}
.ok{color:var(--ok)}
.dim{color:var(--dim)}
footer{margin-top:40px;color:var(--dim);font-size:12px;border-top:1px solid var(--line);padding-top:12px}
code{background:#262a31;padding:1px 5px;border-radius:4px;font-size:12.5px}
"""
def esc(s):
return html.escape(str(s))
def bucket_tag(bucket):
cls = {"待办": "open", "部分收口": "partial", "拍板待执行": "decided", "解决态残留": "resolved"}.get(bucket, "partial")
return f'<span class="tag {cls}">{esc(bucket)}</span>'
def render_html(stage, git_info, docs, active, todos, verify, roadmap, out_path):
now = datetime.now().strftime("%Y-%m-%d %H:%M")
buckets = Counter(t["bucket"] for t in todos)
dirty_docs = [d for d in docs if d["dirty"]]
stale_refs = [r for r in verify["refs"] if r["stale"]]
# 快照节
snap = "".join(f"<li>{esc(l.lstrip('- '))}</li>" for l in active["snapshot_lines"])
# 近期提交
commits = "".join(f"<li><code>{esc(l.split()[0])}</code> {esc(l[l.index(' ')+1:][:90])}</li>" for l in git_info["log"])
# 在飞分组
fly_rows = "".join(
f"<tr><td>{esc(k)}</td><td>{v}</td></tr>" for k, v in git_info["grouped"].most_common())
untracked = "".join(f"<li>{esc(u)}</li>" for u in git_info["untracked"]) or "<li class='dim'>无</li>"
# GDD 清单
doc_rows = []
for group in LOOP_ORDER:
group_docs = [d for d in docs if d["group"] == group]
if not group_docs:
continue
doc_rows.append(
f"<tr><td colspan='5' class='dim' style='background:#22252c'>{esc(group)}({len(group_docs)})</td></tr>")
for d in sorted(group_docs, key=lambda x: x["mtime"], reverse=True):
mark = ' <span class="dirty">在飞</span>' if d["dirty"] else ""
doc_rows.append(
f"<tr><td>{esc(d['name'])}{mark}</td>"
f"<td>{esc(d['version'])}</td><td class='dim'>{esc(d['vdate'])}</td>"
f"<td class='dim'>{esc(d['mtime'])}</td>"
f"<td class='dim'>{esc(d['title'][:40])}</td></tr>")
# 06 待办
todo_by_loop = OrderedDict((g, []) for g in LOOP_ORDER)
for t in todos:
todo_by_loop.setdefault(t["loop"], []).append(t)
todo_cards = []
for loop, items in todo_by_loop.items():
if not items:
continue
open_n = sum(1 for i in items if i["bucket"] in ("待办", "部分收口", "拍板待执行"))
lis = "".join(
f"<li>{bucket_tag(i['bucket'])}{esc(i['system'])} · {esc(i['title'][:46])}</li>"
for i in items if i["bucket"] != "解决态残留")
resolved = [i for i in items if i["bucket"] == "解决态残留"]
res_note = (f"<p class='dim' style='margin:8px 0 0'>另有 {len(resolved)} 条解决态残留"
f"(按「解决即移除」口径待清)</p>" if resolved else "")
todo_cards.append(
f"<div class='card'><h3>{esc(loop)} · 开放 {open_n}/{len(items)}</h3>"
f"<ul>{lis}</ul>{res_note}</div>")
resolved_all = [t for t in todos if t["bucket"] == "解决态残留"]
# 循环级计数(四问卡片②的汇总表)
loop_rows = ""
for loop, items in todo_by_loop.items():
if not items:
continue
open_n = sum(1 for i in items if i["bucket"] in ("待办", "部分收口", "拍板待执行"))
loop_rows += f"<tr><td>{esc(loop)}</td><td>{open_n}</td><td>{len(items)}</td></tr>"
# 07
verify_items = "".join(f"<li>{esc(i)}</li>" for i in verify["items"]) or "<li class='dim'>—</li>"
obligations = "".join(f"<li>{esc(o)}</li>" for o in verify["obligations"]) or "<li class='dim'>—</li>"
ref_rows = ""
for r in verify["refs"]:
verdict = '<span class="stale">已落后</span>' if r["stale"] else '<span class="ok">一致</span>'
ref_rows += (f"<tr><td>{esc(r['doc'])}</td><td>{esc(r['ref'])}</td><td>{esc(r['current'])}</td>"
f"<td>{verdict}</td></tr>")
if not ref_rows:
ref_rows = "<tr><td colspan='4' class='dim'>07 头部未解析出文档版本引用</td></tr>"
# 台账健康
if active["entries"]:
coll = (f"检出撞号 {', '.join(str(n) for n in active['collisions'])}(编号有效、历史不改写)"
if active["collisions"] else "无撞号")
ledger_html = (f"<p>台账区(「{esc(active['tail_head'])}」之后)最新编号 "
f"<b>{active['entries'][-1]}</b>,下一编号建议 <b>{active['next_number']}</b>;{esc(coll)}。</p>")
else:
ledger_html = "<p class='dim'>未解析出台账条目</p>"
# 路线图
route = "".join(f"<li>{esc(s)}</li>" for s in roadmap) or "<li class='dim'>—</li>"
return f"""<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>迭代闭环仪表盘 · Dungeon Sweeper</title>
<style>{CSS}</style>
</head>
<body>
<main>
<h1>迭代闭环仪表盘</h1>
<div class="meta">阶段: {esc(stage)} · 生成于 {now} · 只读视图,重跑 <code>python tools/loop_dashboard.py</code> 刷新</div>
<h2>当前状态快照(active.md)</h2>
<div class="card"><ul>{snap}</ul></div>
<h2>迭代闭环四问</h2>
<div class="grid">
<div class="card"><h3>① 什么在飞(git 未提交 {len(git_info['dirty'])} + 未跟踪 {len(git_info['untracked'])})</h3>
<table><tr><th>分组</th><th>文件数</th></tr>{fly_rows}</table>
<p class="dim" style="margin:8px 0 0">未跟踪: </p><ul>{untracked}</ul></div>
<div class="card"><h3>② 什么待拍板 / 待执行(06 清单 {len(todos)} 条)</h3>
<p>待办 {buckets.get('待办', 0)} · 部分收口 {buckets.get('部分收口', 0)} · 拍板待执行 {buckets.get('拍板待执行', 0)} ·
<span class="stale">解决态残留 {buckets.get('解决态残留', 0)}</span>(按「解决即移除」口径待清)</p>
<table><tr><th>循环</th><th>开放</th><th>总条数</th></tr>{"".join(loop_rows)}</table>
<p class="dim" style="margin:8px 0 0">完整清单见下方「待办清单全目」专区。</p></div>
<div class="card"><h3>③ 什么要人玩(07 体验验证 {len(verify['items'])} 项)</h3>
<ul>{verify_items}</ul></div>
<div class="card"><h3>④ 验证是否落后于文档(失效面检测)</h3>
<p class="dim">07 头部批次来源: {esc(verify['source_line'][:120])}</p>
<table><tr><th>文档</th><th>07 引用</th><th>现行版本</th><th>判定</th></tr>{ref_rows}</table>
{'<p class="stale">存在落后引用——07 观测项基于旧行为,验收读数以重测批义务为准。</p>' if stale_refs else '<p class="ok">引用与现行版本一致。</p>'}
<h3 style="margin-top:12px">重测批义务(07 原文)</h3>
<ul>{obligations}</ul></div>
</div>
<h2>GDD 文档新鲜度({len(docs)} 份,按改动时间)</h2>
<table><tr><th>文档</th><th>版本</th><th>版本日期</th><th>文件改动</th><th>标题</th></tr>{"".join(doc_rows)}</table>
<h2>待办清单全目(按循环)</h2>
<div class="grid">{"".join(todo_cards)}</div>
{'<div class="card" style="margin-top:14px"><h3>解决态残留(按「解决即移除」口径应从 06 移除,去向归台账与 git 历史)</h3><ul>' + "".join(f"<li>{esc(t['system'])} · {esc(t['title'])}</li>" for t in resolved_all) + '</ul></div>' if resolved_all else ''}
<h2>路线图(production/roadmap.md)</h2>
<div class="card"><ol>{route}</ol></div>
<h2>台账健康</h2>
<div class="card">{ledger_html}</div>
<h2>近期提交</h2>
<div class="card"><ul>{commits}</ul></div>
<footer>
数据源: production/session-state/active.md · production/roadmap.md · production/stage.txt ·
design/gdd/06-待办清单.md · design/gdd/07-体验验证清单.md · design/gdd/** · git status/log。
生成工具 tools/loop_dashboard.py;六处信息源格式变更时同步改解析约定(见工具头注)。
</footer>
</main>
</body>
</html>"""
def main():
if hasattr(sys.stdout, "reconfigure"):
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
ap = argparse.ArgumentParser(description="迭代闭环仪表盘生成器")
ap.add_argument("--out", default=str(DEFAULT_OUT))
ap.add_argument("--open", action="store_true", help="生成后用默认浏览器打开")
args = ap.parse_args()
stage = STAGE_TXT.read_text(encoding="utf-8").strip() if STAGE_TXT.exists() else "—"
git_info = scan_git()
docs = scan_gdd(git_info)
active = scan_active()
todos = scan_todo()
verify = scan_verify(docs)
roadmap = scan_roadmap()
out_path = Path(args.out)
out_path.write_text(
render_html(stage, git_info, docs, active, todos, verify, roadmap, out_path),
encoding="utf-8")
print_summary(stage, git_info, docs, active, todos, verify, out_path)
if args.open and sys.platform == "win32":
os.startfile(str(out_path)) # noqa: 仅 Windows 便捷入口
if __name__ == "__main__":
main()