Files
gplan-2/reports/需求卡片-L1深度3混编-2026-11-04.md
T

24 KiB
Raw Blame History

需求卡片 · L1 深度 3 改地精+熊地精混编(大地精数据行退役)

来源:待办清单「L1 深度 3 改地精+熊地精混编(大地精数据行退役)」(2026-11-04 登记,文档设计已闭合+已写卡)(唯一事实源:体验验证清单.md ⑱「投放内容」段第 (1,3) 行条目——行序、行值取定与静态骰和在该段钉死;机制合法性见 design/gdd/systems/战斗循环/敌人系统.md v1.7 核心规则「行集构成纪律」条;投放记录与读数义务见 design/gdd/systems/冒险循环/难度曲线与Boss.md v1.3 混编注记段)

日期 2026-11-04 | 第 2 版(v1.1,2026-11-04 双审复核后改写)| 段位=写卡(第三段)| 开工门=用户发令 U0

一、目标与完成定义

把敌人表里未经过设计的大地精数据行(hobgoblin,坐标 (1, battle, 3))退役,同一坐标改为「熊地精 + 地精」两行混编:一只前排熊地精、一到两只地精。

覆盖面只说深度 3:深度带寻址是「取首个 ≥ 深度的带」,L1 的战斗带键只有 0/1/2/3/6(enemy.tres:10,35,60,84,109),所以 band 3 只覆盖深度 3;深度 4、5 落 band 6(单行熊地精 1–2 只 hp30/ac4),本批不碰也不该碰。

完成定义(五条全中才算完):① 敌人表不再有 hobgoblin 数据行,(1,battle,3) 是两行混编且行序为「熊地精在前」;② 两行行值逐字段等于既有 (1,battle,2) 与 (1,battle,0) 行;③ 深度 4/5 的落带结果与改动前一致(仍落 (1,battle,6));④ 全仓非历史面的 hobgoblin 残留清零(口径见 R10);⑤ 冒烟与单元闸全绿。

二、设计事实源

  • 行序 + 行值 + 数量取定:体验验证清单.md ⑱ 投放内容段第 (1,3) 条(「行值整行复用 (1,2) 熊地精(1 只 / hp22 / ac2)与 (1,0) 地精(1–2 只 / hp8 / ac0),零数值新增;静态最坏骰和 1+2=3;行序 = 熊地精在前」)
  • 混编合法性三条纪律:design/gdd/systems/战斗循环/敌人系统.md v1.7 核心规则「行集构成纪律」条
  • 投放记录与读数义务:design/gdd/systems/冒险循环/难度曲线与Boss.md v1.3 混编注记段(只给机制与义务,不给行序)
  • Alpha 零读数:design/engineering/process-conventions.md §3 第 5 条 Alpha 阶段口径段
  • 待办清单条目:待办清单.md「L1 深度 3 改地精+熊地精混编(大地精数据行退役)」条

三、现状事实(代码级,开工自行复核)

# 事实 位置
1 大地精行在役:(1,battle,3)、2–3 只、hp14、池 attack6/charge2/heavy2、light、ac2 game/data/tables/enemy.tres:82-105(行由 :81 的 }, { 打开、:106 的 }, { 收尾——删改必须连分隔符一起算)
2 前排取用行:熊地精 (1,battle,2) 1 只定值(无 unit_count_max)、hp22、ac2、池 attack6/charge2/heavy2 game/data/tables/enemy.tres:58-80
3 后排取用行:地精 (1,battle,0) 1–2 只、hp8、ac0、池 attack9/lunge1/desperate_guard1 game/data/tables/enemy.tres:7-31
4 深层熊地精 (1,battle,6) 1–2 只、hp30、ac4——深度 4/5 落这里,本批不取用 game/data/tables/enemy.tres:107-131
5 行集取首个 ≥ 深度的带 game/data/schemas/enemy_table.gd:196-204;game/core/config_db_resolver.gd:57-67
6 行集返回序 = 表文件行序 game/core/config_db_resolver.gd:92-98
7 默认单体目标取生成序最前;开战叙述取行集首行 game/core/unit_container.gd:358-363;game/core/battle_narrator.gd:69-78
8 敌人表共 28 行,键序逐行钉死;文件头注释也写「20 行带键行序/hobgoblin 留任」 game/tests/unit/data_config/table_structure_guard_test.gd:4;键序断言 :212-233;留任断言 :234-239
9 全深度 × 12 种子 spawn 扫描只按行集首行判定数量区间——单行成立,双行必红 game/tests/unit/battle_settlement/round_flow_skill_pool_test.gd:295-317(关键 :310-317:resolve_rowset(...)[0] 取首行后比较 [unit_count, unit_count_max])
10 池模板断言表逐键写死,含 1_battle_3_hobgoblin;同函数断言文案写「二十八行九种」 round_flow_skill_pool_test.gd:567-578、:611(函数 _smoke_skill_pool_data)
11 同文件另两处 hobgoblin 前提:注释 :1108「L1 depth 3(hobgoblin 行集 2-3 只)」、:711/:722「D3 大地精,多实例同种」「敌 hp 低(表值 6)」(后者已随表值失真) round_flow_skill_pool_test.gd:711,722,1108
12 _smoke_enemy_buff_targets_self 是种子搜索型用例:搜 1..N 号种子找「恰一次 charge 施放」,混编后只有熊地精带 charge round_flow_skill_pool_test.gd:1096-1136
13 混编注入段还原后硬编码「表回 28 行」 game/tests/unit/core/level_shop_economy_test.gd:727
14 混编定点断言先例(L2)写法可照抄 level_shop_economy_test.gd:623-636
15 个体池/个体 AC 对照用例以 depth 3 为「≥2 敌」夹具 game/tests/unit/battle_settlement/damage_controller_test.gd:412-440;game/tests/unit/presentation/battle_narrator_test.gd:108-121
16 行序/落带夹具用 hobgoblin 作合成行;该夹具不调 validate(),只注入 resolver game/tests/unit/core/config_db_resolver_test.gd:14-28、:40-46、:56-78
17 行集纪律用例用 hobgoblin 作「不相邻」样本 game/tests/unit/data_config/config_db_test.gd:220-230(_test_rowset_discipline)
18 表注四处含退役键:886-891(2026-09-24 实体名修正批整段)、906-918(2026-10-07 混编首批投放批)、920(N1 修批括注「改名大地精」)、929(hobgoblin 行为缺口行) game/data/tables/enemy.tres:886-891,906-918,920,929
19 静态闸按行号豁免 enemy.tres 三处,其中 FNR==891 落在上述 886-891 段内——删段后该豁免指向别的行,必须同步清 game/tests/static_scan.sh:145、豁免执行点 :194,218,221-222
20 术语审计注释里列了 hobgoblin,但该文件只扫 .md/.yaml、且跳过 #; 注释行,改动零行为影响 tools/doc_term_audit.py:144(匹配与扫描面 :146-147,166,214-219)

四、设计契约(🔴 违反=停机呈报)

  1. 🔴 行集构成纪律三条:行集内 enemy_id 唯一;同带键多行必须文件内相邻且行序=声明序=生成序;行集实例总数 ≤ 4、单行数量域 [1,3]。本批静态最坏骰和 = 熊地精 1 + 地精 2 = 3。
  2. 🔴 行值零新增:两行行值必须整行复制第 2、3 条现状事实里的行,不得改 hp/atk/池权重/ac;改了就是设计变更,停卡退回写卡段。
  3. 🔴 行序固定:熊地精行在前、地精行在后(依据 §二 第一条)。行序影响默认单体目标与开战叙述首行,不属实现面可调项。
  4. 🔴 不碰深度 4/5:(1,battle,6) 行一字段都不许动;目标句里没有「深度 3–5」这回事。
  5. 🔴 Alpha 零读数:本批不跑 MC、不采改前改后读数;实现报告注明「未取证」,读数义务归数值统一修正批。
  6. 🔴 禁碰敌种数据面与技能表:敌种名录表已随工程批退役(敌人系统.md 不再维护抄本),skills.tres 零改动。
  7. 🔴 禁改美术侧键集:tools/standee_asset_check.py 与 tools/path_check.py 的 ENEMY_KEYS 与本批无关,禁顺手改。

五、范围边界

做:敌人表删一行加两行+表注四处;七个测试文件换锚与补断言;tools/doc_term_audit.py 注释;static_scan.sh 一条失效豁免清理。

不做:任何数值调整;敌种表/技能表;深度 4/5 的带位;立绘与美术面;Boss 多行第二批;读数与模拟;enemy.tres:920 的 N1 修批括注(见 §十一 T1 第 6 步说明)。

不收件去向:数值带位移读数 → 数值统一修正批;实机混编目检 → 体验验证清单.md ⑱(只登记,不阻塞合并)。

六、关联文档同步面(实现批禁写文档)

文档 关联点 同步义务
design/gdd/systems/冒险循环/难度曲线与Boss.md v1.3 混编注记段已写 (1,3) 投放记录 零动作(文档批已落文,commit 4aaa154e;行序表述由本批前置修复提交更正)
design/gdd/systems/战斗循环/敌人系统.md v1.7 缺口登记已删;敌种名录表已随工程批退役,行数据逐行读表 零动作(同上)
体验验证清单.md ⑱ L1 节点 3 目检三项 + 读数义务 零动作;实现报告抄录目检项
design/gdd/08-Alpha版本标准.md v1.26 混编行集状态行已补 (1,3) 零动作
game/tests/README.md 能力表 本批不改任何用例函数名,只改函数体内断言与夹具 零动作;若实现期必须改名,停卡退回写卡段(实现批禁写该文件)

七、文件结构图

路径 职责 改动类型 对照表行
game/data/tables/enemy.tres (1,3) 一行换两行;表注四处处置 行为改动 R1–R4、R9
game/tests/unit/data_config/table_structure_guard_test.gd 29 行键序、混编构成断言、骰和与行值复用断言、零残留断言、文件头注 行为改动(测试面) R1–R5、R10
game/tests/unit/battle_settlement/round_flow_skill_pool_test.gd 全域扫描口径改逐行求和;池模板两键;四处注释与文案 行为改动(测试面) R6、R7、R10
game/tests/unit/core/level_shop_economy_test.gd 混编注入段还原行数 28→29 行为改动(测试面) R8
game/tests/unit/core/config_db_resolver_test.gd 合成行换 giant_spider(不换 bugbear,避免与 band 0 同名) 非行为改动(夹具) R7
game/tests/unit/data_config/config_db_test.gd 「不相邻」样本换 giant_spider 非行为改动(夹具) R7
game/tests/unit/battle_settlement/damage_controller_test.gd depth 3 夹具注释改述 非行为改动(注释) —
game/tests/unit/presentation/battle_narrator_test.gd 同上 非行为改动(注释) —
game/tests/static_scan.sh 删失效的 FNR==891 豁免条目(对象已随表注删除) 非行为改动(闸件豁免维护) —
tools/doc_term_audit.py 注释里的敌种枚举 非行为改动(注释) —

无新增文件、类、公开方法。

八、落位与可复用性预检

  • 复用面:零新增文件/函数/数据件。两条新表行沿用既有字段集,整行复制既有行,不引入新字段或新默认值。
  • 唯一面:混编构成的事实只在两处——表行序与钉住它的断言;行值不在测试里复写(R4 比对两行相等,不写 22/8/权重字面量)。全域扫描的数量判据改为「逐行求和」,与 unit_container.gd:86-92 的 spawn 守卫同口径,不另立第二套口径。
  • 分层与交互面:零新增调用路径。运行时仍走 ConfigDb → EnemyTable.resolve_rowset() → ConfigDbResolver.resolve_enemy_rowset() → UnitContainer.spawn()(game/core/unit_container.gd:46),Core 零 UI、数值只读表、随机只在结算层(game/core/battle_orchestrator.gd:293-324)三条红线不变。

九、实现规范预算

零新增文件与新增成员,gdstyle 阈值不适用;本批触碰的测试文件不新增成员变量与公开方法。存量触面一查:static_scan.sh 只删一条豁免、不改扫描规则;S13 键在三处测试文件内均只降不升(只改断言文本,不增函数)。

十、拆分边界纪律

本卡不是拆分/收敛/重构类卡,条款不适用。

十一、任务卡

T1 · 敌人表换行与表注(估时 0.5 日)

取用:无(首卡)。产出:(1,battle,3) 两行 + 清理后的表注,供 R1–R5、R9 读取。

  • 把 enemy.tres:81-106 整段(}, { + 大地精字段块 + }, {)替换为:}, { + 熊地精字段块 + }, { + 地精字段块 + }, {
  • 熊地精块字段:level_index: 1/row_kind: "battle"/depth_band: 3/enemy_id: "bugbear"/display_name: "熊地精"/unit_count: 1/(不写 unit_count_max)/hp: 22/atk: 1/atk_min: 0/atk_max: 2/pool: [attack 6, charge 2, heavy 2]/attack_type: "normal"/armor_type: "light"/armor_class: 2
  • 地精块字段:depth_band: 3/enemy_id: "goblin"/display_name: "地精"/unit_count: 1/unit_count_max: 2/hp: 8/atk: 1/atk_min: 0/atk_max: 2/pool: [attack 9, lunge 1, desperate_guard 1]/attack_type: "normal"/armor_type: "light"/armor_class: 0
  • 删表注段「实体名修正批(2026-09-24…)」整段(按文本锚点定位,不按行号)——该段全篇在讲大地精改名沿革,内容 git log 可考
  • 删表注句「hobgoblin 行为缺口行:无立绘、不在敌种表——留任在役,补齐三件套…」整句
  • 在下一行追加新注(; 顶格):「; (1,3) 大地精行 2026-11-04 用户裁退役,改地精+熊地精混编(行序熊地精在前、行值整行复用 (1,2)/(1,0)、静态骰和 3);沿革见 git 提交史」
  • 在「混编遭遇首批投放批(2026-10-07…)」段尾追加一行(不改原文):「; 2026-11-04 追加第二行:(1,3) 地精+熊地精(行序熊地精在前)」
  • 保留 :920 的 N1 修批括注原文(属带日期的历史裁决记录,且只含中文「大地精」、不含 hobgoblin 字面;R10 口径不覆盖它)
  • 回读:grep -n "hobgoblin" game/data/tables/enemy.tres 输出为空

T2 · 测试面换锚与补断言(估时 1.5 日)

取用:T1 的两行。产出:R1–R10 全绿。

  • table_structure_guard_test.gd:212-233:expect_keys 里 "1|battle|3|hobgoblin" 换成相邻两键 "1|battle|3|bugbear", "1|battle|3|goblin";行数 28→29(断言与文案同步)
  • table_structure_guard_test.gd:234-239:删「hobgoblin 留任随迁」断言块,替换为混编构成断言(R1–R4)
  • table_structure_guard_test.gd:4:文件头注「enemy 敌人表(20 行带键行序/hobgoblin 留任/三 Boss 行)」改为「(29 行带键行序/混编行集/三 Boss 行)」
  • round_flow_skill_pool_test.gd:310-317:把「resolve_rowset(...)[0] 取首行 + 比较 [unit_count, unit_count_max]」改为逐行求和:lo = Σ unit_count、hi = Σ unit_count_max,判 n ∈ [lo, hi] 且 n ≥ 1(与 unit_container.gd:86-92 守卫同口径)
  • round_flow_skill_pool_test.gd:567-578:"1_battle_3_hobgoblin": {"attack": 6, "charge": 2, "heavy": 2} 换成 "1_battle_3_bugbear": {"attack": 6, "charge": 2, "heavy": 2} + "1_battle_3_goblin": {"attack": 9, "lunge": 1, "desperate_guard": 1}(顺序按表行序)
  • round_flow_skill_pool_test.gd:611:断言文案「二十八行九种池模板」改「二十九行十种池模板」,其余描述不动
  • round_flow_skill_pool_test.gd:711,722,1108:注释改述为「depth 3 = 混编行集(熊地精 1 + 地精 1–2)」,删掉「多实例同种」「表值 6」两处已失真描述
  • level_shop_economy_test.gd:727:断言 28→29,文案「基线 20 行+覆盖 8 行」改「基线 21 行+覆盖 8 行」
  • config_db_resolver_test.gd:40-46:合成行 "hobgoblin" 换 "giant_spider";:56-78 三条断言的期望串同步(不改成 bugbear——该合成表 band 0 已有 bugbear,同名会削弱「按敌种可辨」的可读性)
  • config_db_test.gd:220-230:_test_rowset_discipline() 的「不相邻」样本 "hobgoblin" 换 "giant_spider"
  • damage_controller_test.gd:413 与 battle_narrator_test.gd:114:注释改「depth 3 = 混编行集(熊地精 1 + 地精 1–2,最少 2 只)」,断言零改动
  • static_scan.sh:145:删掉豁免条目里的 enemy.tres:891(该行已随表注删除;留着会误放别的行)
  • tools/doc_term_audit.py:144:注释里的敌种枚举去掉 hobgoblin
  • 回读:grep -rn "hobgoblin" game/data game/core game/presentation game/probe game/sim game/tests tools --include=*.gd --include=*.tres --include=*.py --include=*.sh 输出为空(不含 game/override.cfg,该文件是 worktree 派生的 gitignored 文件,路径里带本区目录名)
  • 跑 _smoke_enemy_buff_targets_self:种子搜索面随池构成变化,若 1..N 无命中 → 按 §十三 L3 呈报,禁放宽判据

T3 · 产出物落位(估时 0.5 日)

取用:T2 全绿。产出:两份报告。

  • 写 reports/iter<N>-实现报告-<日期>.md:各卡状态;实机目检总清单(抄 体验验证清单.md ⑱ 的 L1 节点 3 三项);实际对照表(R1–R10 逐行写测试文件:行+结果,process-conventions §3 第 14 条);遗留读数义务(Alpha 零读数、归数值统一修正批);实现决定记录
  • 写 reports/iter<N>-反哺点-<日期>.md:按 §六 逐条落点(预计零条,也写「零条」)
  • 核对 game/tests/README.md 能力表:用例函数名未变则零动作;若实现期不得不改名,停卡退回写卡段

估时合计 2.5 个工作日。

十二、验证闸(改动—验收对照表)

行 需求点 改动(文件:行/行为) 验收测试(名称+落点+尾缀) 层级 真实入口 判据绑定面 能力行
R1 行数与键序 enemy.tres:81-106 一行换两行 table_structure_guard_test.gd:_smoke_enemy_bands「敌人表 29 行且键序 = 覆盖表序((1,3) 两行相邻、熊地精在前)」〔L1混编 v1〕 单元 ConfigDb.load_tables() → EnemyTable.rows 遍历 rows 拼「关卡、行类、深度带、敌种」四段串逐行比对期望串 既有:表结构守卫:域校验/行序键/跨字段互锁/配额锚
R2 混编构成与行序 同上 同函数「(1,3) 行集恰两行、enemy_id 序列 == [bugbear, goblin]、首行即默认目标」〔L1混编 v2〕 单元 EnemyTable.resolve_rowset(1,3,"battle") → ConfigDbResolver.resolve_enemy_rowset(1,3,"battle") 返回数组长度与逐项 enemy_id 序列 既有:行集寻址、行序保序与难度乘数 clamp
R3 静态最坏骰和 同上 同函数「(1,3) Σ(unit_count_max,固定行缺省 unit_count) == 3」〔L1混编 v3〕 单元 同上 求和值与 4 比较(等于 3,不用 ≤) 既有:表结构守卫:域校验/行序键/跨字段互锁/配额锚
R4 行值整行复用 同上 同函数「(1,3) 两行逐字段 == (1,2) 与 (1,0) 行(hp/atk 区间/pool/ac/armor_type/attack_type)」〔L1混编 v4〕 单元 EnemyTable.rows 两行字段逐项比对,不写死数值字面量 既有:表结构守卫:域校验/行序键/跨字段互锁/配额锚
R5 零残留(数据与代码面) 表与七文件 同函数「表内 enemy_id 集合不含 hobgoblin」〔L1混编 v5〕+ T2 回读命令 单元 EnemyTable.rows 遍历 集合不含该字符串 既有:表结构守卫:域校验/行序键/跨字段互锁/配额锚
R6 混编下 spawn 数量全域内 round_flow_skill_pool_test.gd:310-317 口径改造 round_flow_skill_pool_test.gd:_smoke_encounter_roll(全深度×种子扫描段)「全深度 × 12 种子 spawn 数量 ∈ [Σunit_count, Σunit_count_max] 且 ≥1」 单元 BattleOrchestrator.begin_battle({"level_index":1,"node_depth":d}) → presentation_snapshot().enemies.size() 逐场数量与逐行求和区间比较 既有:行集寻址、行序保序与难度乘数 clamp
R7 双池各自独立 表两行 round_flow_skill_pool_test.gd:_smoke_skill_pool_data「(1,3) 两行池模板 == 熊地精池 attack6/charge2/heavy2 与地精池 attack9/lunge1/desperate_guard1」 单元 同上 断言表的键与权重逐项 既有:技能池数据面与回放独立
R8 注入段还原行数 level_shop_economy_test.gd:727 level_shop_economy_test.gd:_smoke_level_graph「混编断言段注入行全量还原(表回 29 行)」 单元 同套件既有注入/还原流程 rows.size() 与期望值比较 既有:关卡表消费侧校验与关卡推进
R9 深度 4/5 落带不变 表(不应改变) table_structure_guard_test.gd 补「(1,4) 与 (1,5) 的 battle 行集 == 单行 bugbear(band 6)」〔L1混编 v6〕 单元 EnemyTable.resolve_rowset(1,4/5,"battle") 返回数组长度与 enemy_id 序列、band 归属 既有:行集寻址、行序保序与难度乘数 clamp
R10 深度 3 最少 2 敌(回归护栏) 两处夹具注释 damage_controller_test.gd:_test_pool_consumption_per_unit 与 battle_narrator_test.gd:_test_snapshot_effects_per_unit 在混编行集下仍绿 单元 UnitContainer.spawn({"level_index":1,"node_depth":3}) 生成后 all_enemies().size() ≥ 2 既有:敌方增益自体落点与乘区池按个体

测试削弱申报:①table_structure_guard_test.gd:234-239 删除「hobgoblin 留任随迁」断言——钉的是已退役事实;②round_flow_skill_pool_test.gd:310-317 由「首行区间」改为「逐行求和区间」——原口径在双行行集下必红,新口径与 spawn 守卫同口径,不是放宽;③round_flow_skill_pool_test.gd:611 只改文案不改判据;④static_scan.sh 删一条针对已不存在行的豁免。除此外不删断言、不放宽阈值、不缩小扫描面。

判据绑定面说明:全部判据绑在表数据与解析返回序列上(数据改动的可观测提交面);R1–R4 的期望值从同表既有行推导,不写死字面量;不做注入破坏或回退取证(process-conventions §3 第 14 条口径)。

独立验收审计:入口=未参与本卡实现的会话或子代理,按上表逐行复核(判据是否绑在被改动的表数据与解析序列上、真实入口是否绕过改动点);报告文件 reports/iter<N>-验收审计-<日期>.md;未过不得合并。

闸口径:本批改动含 game/ 下行为载体,按域选档由闸脚本判定(卡内不列闸件名单)。里程碑出口跑一次全套;波内修复只做出红最小单元的最窄确认。

十三、异常分级

  • L1 自救:缩进/格式/语法类错误,直接改到绿。
  • L2 记录继续:断言写法等价改写(如求和改用循环)、注释措辞微调,记入实现报告「实现决定记录」。
  • L3 停机呈报:① spawn 抛行集越域警告;② 需要改数值才能过闸;③ 出现卡外第九个引用点;④ _smoke_enemy_buff_targets_self 种子搜索落空;⑤ 需要改 game/tests/README.md 或任何 design/ 文件;⑥ 机检预算互斥(本批零新增件,出现即判上游缺陷,停卡退回写卡段)。

十四、代拍板白名单

  1. 断言函数内的循环写法、局部变量命名、断言文案措辞。
  2. 注释改述的字面(不改语义)。
  3. expect_keys 与 expect_pools 数组的换行排版。
  4. 新表注的措辞(须含日期 2026-11-04 与「用户裁」字样)。 超清单必呈报。

十五、待裁点

零待裁点,开工门=用户发令 U0。已裁记录:① 数量、行值、行序(用户 2026-11-04 委托取定,落在 体验验证清单.md ⑱);② L1 首见混编可接受(用户 2026-11-04 判「无阻碍」);③ Alpha 零读数(用户 2026-11-04 裁,已落 process-conventions §3 第 5 条);④ 表注 886-891 整段删除(用户 2026-11-04 指令「文档与代码中的大地精描述要去掉」,与静态闸「历史原文不改」惯例冲突时以用户指令为准,代价=一条命名沿革注进 git log);⑤ 深度 4/5 不纳入本批(本次双审后订正目标句,不带设计增量)。