merge: 迭代17卡①敌人表行集多行批落籍(恰一敌种校验退役改行集构成纪律+行序相邻校验R6+resolver行集数组化+floor版退役〔工作日志312销号〕+spawn行集受理+实例总数≤4守卫+遭遇骰逐行各掷〔Q8,RNG扩签预批准〕+expect_pools三元键换代+混编正反断言六条+单测五条;GDD先行敌人系统v0.15/难度曲线与Boss v0.24;闸=冒烟811/0〔+6〕+run_all17套+probe_gate含click全绿+MC改前改后同seed0=83000配对40局/每腿660字段逐项零差异〔R1零漂移成立;改前锚经用户甲案批准补采,本批MC总量80超二档例外已裁〕;active.md与并行迭代18各批union解+台账预配号384撞号改登388〔384-387系并行会话先占〕;台账388;遗留=实机目检四项+代拍板九项追认归用户+Boss多行投放归迭代18卡⑤)
This commit is contained in:
commit
9cc4b8b404
20 files changed
+461
-142
No files matched your search
@@ -15,6 +15,7 @@
|
||||
- **更新于**:2026-10-07(**迭代18修正批落籍 master 3609624**,worktree g-plan2-iter18fix 单提交 b56531d+主区 merge --no-ff,工作日志 385;纯文档零代码零测试):用户令撤回越权编入——卡①奇物内容补全/卡②呈现优化移出迭代18〔仍在文档探讨探索阶段、上下文不足,不进实现〕退回06登记态;卡⑥M4数值批移出迭代18改「迭代19+」行〔暂不启动,保持Alpha收官位未排期待发令〕;迭代18现存四卡=③武器锻造提案/④生涯实装/⑤混编投放/⑦种子随机化+调试浮窗;06八处+07一处引用随迁
|
||||
- **更新于**:2026-10-07(**八敌立绘逐键定档 + 站桩方案二排版讨论批定稿落籍**(美术线自立批讨论稿;worktree D:/code/g-plan2-standee-tier 分支 art-standee-20261006 两提交 0aa85dd 主批 + 5953af3 并入 master 80 提交并解 06 冲突一处;纯文档 + tools/pixelize_candidates.py 常量表,**未出图未动引擎代码**,doc 三闸/冒烟未跑=讨论批两入口铁规;**分支未清**、留待阶段 1 任务书续用):①八敌站桩源档由「全敌共用 48」改**逐键定档**(STANDEE_TIER_H=地精36/巨蜘蛛38/灰矮人46/钩爪恐魔58/熊地精62/食人魔酋长74/蛛化卓尔90/灰矮人石君王94,主角 48 不变,显示一律 ×2 整数 NEAREST=72–188;旧 f_enemy=48/max_h 系数退役)②排版改**方案二**(B 区 252→270、C·D 548→530,扫雷盘 438×438 原尺寸不缩格子不变,压缩由面板空档吸收;立绘双脚落石台上缘、血条+状态/名字行落底排全场一线、大体档头部探顶压进光柱区、意图徽标改位〔探顶档压胸〕,「血条悬浮头顶+盒内居中」排式退役)③体量语义改**生物体型**(character-design §5.2,弃强度线性映射)+ 主角描边例外(§5.1 v1.9,深褐 40,19,13)+ 钩爪恐魔「宽≥高」豁免登记 ④**定值单点纪律**(art-bible §8 头注:数字定值只落 §4.1 主色板 + §8.2,其余章指路禁复述)+ 色板 48 色上限与新色近色门槛 RGB 三通道差 ≥8/255 ⑤§8.3 归档纪律(图片不入 git / 过程稿归档 / 主文档禁引 artwork 散路径)+ 三检查器挂点(色板检查器 / 路径核对器 / standee_asset_check 硬闸升级规格)⑥地形色值对齐 §4.1(岩石 #8B755B→#C9AF83、地面 #564232→#B39A78)+ 生图渠道改「远程对话式正主·本地 ComfyUI 备选」+ 瓦片改拼表制正主 ⑦asset-path-map 废路径更正(production/mockups→artwork/mockups)+ art-status-checklist 对账至 ✅4/◐8/⬜3。**阶段 1 两项待用户裁决**:本批是否编入 roadmap 迭代位(迭代 17/18 已在飞)还是维持美术线自立批不占迭代位;是否认可「先按新档产图、再动引擎代码」顺序——裁决后方动笔任务书)
|
||||
- **更新于**:2026-10-07(**迭代18卡⑦两裁点全裁+调试浮窗目标态落籍 master 49ee98f**,worktree g-plan2-seedrule 单提交 56d996c+主区 merge --no-ff,工作日志 384;纯文档零代码零测试):种子三裁=首次冒险维持固定/测试调试接口显式指定/种子不进玩家UI(玩家入口随机生成);卡⑦扩为种子随机化+调试浮窗升级双件——浮窗目标态=独立最高层浮窗〔对局中可开,修订迭代15卡①P3甲〕+DS_DEBUG=1 默认打开+当局数据只读区块〔种子唯一查看位〕;现行考证六点在册〔角标门控/1189门禁/非最高层/非默认开/无当局数据面〕;卡①落地门随卡⓪落籍〔e5354366〕自然解除
|
||||
- **更新于**:2026-10-07(**敌人表行集多行批实施完成**,迭代 17 卡①——worktree g-plan2-iter17-enemy 分支 iter17-enemy-20261007 基点 e535436,批内提交 a0b06b4/5b9cf59/18cdcb0/ab5ddad/8690230/bc73fa3/c583940+收口批,全部在 worktree 未合并,台账 388):敌人表同一坐标行集放开混编多种敌人(每行各自数量实例化+行集实例总数≤4 守卫+行序=文件序契约+行序相邻加载期校验兜底;含 Boss 行集 P4乙);floor 版解析退役全仓统走 ceil 行集数组(工作日志 312 销号);遭遇骰改逐行各掷(单行行集消费序/次数与既有逐位一致=零内容期随机流零变化);批中一次 L3 停机=卡⓪改前锚两份 jsonl 随其 worktree 删除丢失不可恢复→用户裁甲案(T0 现态补采改前锚 40 局+总量 80 局明示批准)后续起。闸=冒烟 811/0(基线 805/0,+6 混编断言)+run_all 17 套+probe_gate 含 click 全绿+doc 三闸/熵增存量红零新增+MC 改前改后 40 局同种子全字段零差异(零漂移铁证;补采锚 L1 口径读数 off 4/20·formed 16/20 与卡⓪出口报告逐位同值=等价旁证)。文档=敌人系统 v0.15/难度曲线与Boss v0.24/registry rowset_rule/06 状态行收口;出口报告+人闸材料落 design/qa/iter17-enemy-*-2026-10-07.md。**下一步待用户=实机目检四项+代拍板追认九项**,过闸后合并落 master;首个混编行内容投放归迭代 18 卡⑤。
|
||||
- **更新于**:2026-10-07(**迭代18增卡⑦新冒险种子随机化落籍 master 7a7d873**,worktree g-plan2-seedcard 单提交 997bcc9+主区 merge --no-ff,工作日志 382;纯文档零代码零测试):用户令——现状实查 main.gd:1210 种子框空硬编码 42=每次新冒险同种子全程复现;卡⑦=默认分支改随机生成+调试浮窗种子框保留手动覆盖,断点续玩/冒烟锚/⑥收官批三面零影响考证在册;裁点两项随任务书(首次冒险教学态是否随机/种子进 UI 展示位);⑥门改「内容卡①-⑤⑦出口」;下一步=迭代 18 任务书讨论
|
||||
- **更新于**:2026-10-06(**内容数据驱动扩展批实施完成落籍 master**(worktree iter17-dd 分支 iter17-dd-20261006,主区 merge --no-ff),工作日志 383〔预配号 381 撞号改登——381/382 系并行迭代 18 规划批与增卡⑦两批先落,先例同台账 374〕):迭代 17 卡⓪ 当日立项当日落地——T1 效果引擎框架+16 发射点(7d157b3)/T2 词汇落码(225765f)系前任完成,续跑会话接手 T3 断点三脏文件收口:T3 专长 27 行 triggers 全量迁移+旧 23 挂点枚举消亡+消费点拆除+文案入表+断言面随迁(e28a6cb,承接修正四处=perfect_defense 事实出域/has 算子语义/漏写 _harmful_adjacent/counter set 键 bool 吞零);T4+T5 秘宝六件按 id 硬编码清零(淬毒 clamp_bonus 模式路由/偏运经 reward_roll/晨令 round_start 订阅+when 行字段定影/惊巢 halve_pct/殉爆订阅开单/掘进蓄能受理闸 counter_spend 订阅)+令牌兑付 match 收敛进效果类型路由表(a33ddaf);闸=冒烟 800 项 0 失败+单元 17 套+探针闸含 click 全绿+MC 二档对拍 40 局同种子**逐位一致**(pre/post 锚 83000 段留盘 sim-data/);T7 文档换代=奇物 v2.8/秘宝 v1.0/敌人系统 v0.14+registry 两件+06 收口+roadmap 卡⓪行+出口报告(design/qa/iter17-datadrive-exit-report-2026-10-06.md);遗留人闸两项随报告(掘进蓄能模判定留编排器侧=词汇表边界/主动件 kind 词族全量 rename 不随批)+实机目检归用户。**下一步待用户=实机抽查**。
|
||||
- **更新于**:2026-10-06(**迭代18规划批落籍 master 018435e**,worktree g-plan2-iter18plan 单提交 0d80626+主区 merge --no-ff,工作日志 381;纯文档零代码零测试):用户令——M4 数值批移 Alpha 阶段最后=迭代 18 ⑥收官卡(门=内容卡①-⑤出口,内容补全先行、统一数值调整殿后)+五内容卡立项:①奇物内容补全·文档先行(charge 补件设计〔实查现恰 3 件〕+06 资源入池条收窄收口〔刷新件与门票实已随迭代 15②入池〕)/②呈现优化六件(与迭代 16 语义零重合=其 token 下游)/③武器锻造系统设计提案(06 新立专条)/④生涯实装(门=卡④提纲评审)/⑤混编遭遇首批投放(MC 取证顺延⑥收官批);06 七处+07 一处状态随迁;资产升档批优先级再降维持挂起;**下一步待用户=讨论迭代 18 各卡任务书**(B 文档批零代码成立、C 与迭代 16 零重合两问结论已呈报)
|
||||
@@ -885,3 +886,4 @@
|
||||
|
||||
386. **八敌立绘逐键定档 + 站桩方案二排版讨论批定稿落籍(2026-10-06/07,美术线自立批·讨论期只改文档;【台账预配号撞号处置】本会话在分支内记账时预配 385,并入 master 时发现 385 已被并行会话「迭代18修正批」占用(master 3609624,worktree g-plan2-iter18fix),故本条改登 **386**——先例=台账 374、383 同款撞号改登;worktree D:/code/g-plan2-standee-tier 分支 art-standee-20261006 两提交 0aa85dd + 5953af3,worktree 与分支**未清**(留待阶段 1 任务书续用——不同于既往收口即清的惯例,经用户令保留)**:源委 = 管线事实复盘(pixel-1 源 + dom_block_resize 派生可读性实测:24 糊/32 可读/48 清楚/64 细节完整)+ 用户三体型约束(钩爪恐魔>灰矮人、灰矮人<熊地精、食人魔酋长>熊地精)+ 定档总图用户确认;同日 playnote 立绘批评两条(像素粒度过低看不清 / 怪物大小比例不合理)经 06 冲突处置**明确记为已由本批承接兑现**(二者即本批之来由)。**八件改动**:①tools/pixelize_candidates.py 新增 STANDEE_TIER_H 逐键档表(地精36/巨蜘蛛38/灰矮人46/钩爪恐魔58/熊地精62/食人魔酋长74/蛛化卓尔90/灰矮人石君王94),旧 f_enemy=48/max_h 统一系数退役(它把普通怪压到 21–24px、全员低于可读门槛);SIZES 降级注释为「中间分辨率表」(决定中间图多细、不决定最终体量),纠注 ogre_chief=192 系分辨率选择非 Boss 档;派生管线锁 pixel-1 紧裁 → 等比缩至各自档高 → dom_block_resize(禁走 recon / 重跑 remove_bg——recon 会把同色大块抹成一坨,2026-10-06 已实测在册)②battle.md 区表 B 252→270、C·D 548→530(扫雷盘 438×438 原尺寸不缩、格子不变)+ 站桩组件改落影/落底盘排式 ③character-design.md v1.8/v1.9(体量语义改生物体型、§5.5 源档指路 §8.2、钩爪恐魔豁免、主角描边例外)④art-bible v3.7/v3.11(逐键定档表、方案二排版、归档纪律、检查器挂点、定值单点纪律、色板增量纪律双层门(48 色上限 + 近色 ≥8/255)、两笔资产契约收「19 徽章/6 纹带/舞台背景 0 张」缺口)⑤两份生图单(渠道定位更正、拼表制正主、地形四卡色值对齐 §4.1)⑥asset-path-map 废路径与 candidates 按需创建注、整理段入流 ⑦art-status-checklist 对账至 ✅4 / ◐8 / ⬜3(共 15 条) ⑧06 新登四条(站桩帧动画 Alpha 定版闸前 / 主角描边素材侧复核 / 3349 草稿 dry-run 整理 / 口号型条款机检化分章)。**合并处置**:本分支基底落后 master 80 提交(并行会话 iter17-enemy / uialign / 主区在飞),采用「分支内并入 master」而非直接动主区;唯一冲突 = 06-待办清单(master 侧加了「优先级再降 + playnote 批评」注记),解一处 = 两条注记并存并指明 playnote 批评已由本批承接。**未做**:重产新档素材、引擎代码实装、roadmap 迭代位登记(roadmap 只管批级序列与门、里程碑移动才更,本批尚未定迭代归属)、stage.txt(无阶段变更)。**待用户裁决两项**=①迭代位归属(编入迭代位 vs 维持美术自立批不排队)②「先产图后动码」顺序是否认可;裁决后由阶段 1「任务书-立绘定档与站桩重排实装批」承接 T0 代码级考证(standee_body.gd 立绘盒净高 96→纳 188、:237 scale、:195/:202 意图弹入 ×1.6 溢出、ui_struct_probe ⑥standee 断言族边界、ui_assembler 区高常量)→ U0 开工 → 阶段 2 重产 → 阶段 3 工具闸 → 阶段 4 实装 → 阶段 5 样张人闸。讨论批零闸门执行(两入口铁规:非 loop 批且用户未点名)。
|
||||
387. **迭代18四卡任务书起草完成(2026-10-07,用户令——纯文档零代码零测试;worktree g-plan2-iter18tb 分支 iter18-taskbooks-20261007 单提交 7688334,主区 merge --no-ff 78bf43c,worktree 与分支已清)**:四份任务书落 design/research/——⑦种子随机化与调试浮窗升级批 v1.0(考证 F1-F8:main.gd:1210 硬编码 42/断点回填 :447/ModalStack 登记末位已系 z 最高位〔「最高层」实际缺口=门禁+默认开+当局数据,非 z 序〕/ui_tune_probe 八段断言在册;实装级裁点 P1 遮挡语义〔荐甲维持登记制〕/P2 入口形态〔荐甲角标迁宿主〕/P3 默认打开〔荐甲启动即开〕/P4 当局数据字段〔荐甲六项〕/P5 首局种子值〔荐甲沿用 42〕待裁;估时勘误 1d→2.0d 含探针换代)/⑤混编遭遇首批投放批 v1.0(纯内容批零代码,前置=17卡①落籍〔worktree iter17-enemy 在飞〕,机制缺口=L3 停机禁本批补码;裁点 P1 首批投放方案〔荐甲=L2 单点试水巨蜘蛛+熊地精〕/P2 Boss 多行不入首批/P3 教学界保护〔荐甲=L1 d0-d2 零混编〕待裁;1.75d,MC 取证顺延 Alpha 收官批)/④生涯界面实装批 v1.0(范围=提纲期一:汇总页+主菜单入口〔ui_assembler.gd:149-156 装配点〕+终身计数域存档 v6〔现 v5 迁移链 save_manager.gd:53-57〕;总局数/通关局数现无数据源=F2 核心考证;裁点 P1 通关局数口径〔荐甲三关全通〕/P2 条目集〔荐甲六类九项〕/P3 模态登记序〔荐甲营地同档〕待裁;开工门=提纲评审+设计定稿;2.5d)/③武器锻造系统设计提案批 v1.0(提纲版零待裁点——设计裁点在提案产物内全备选呈裁;提案八节必答框架=武器实体化程度/攻击类型轴关系〔格面资源 pierce/magic 与武器类型的两轴共存〕/护甲实体化〔现役 AC 单值无类型实体〕/成长曲线定位/经济解锁/满级特效〔优先复用 EffectEngine 现役效果类型〕/provisional 数值框架〔终值归 Alpha 收官批〕/迁移面;1.5d 一轮呈裁基线)。取证方式=两 subagent 并行(生涯域+敌人域)+自查(ModalStack/ui_tune_probe/polarity 矩阵/forge 两源)。roadmap 四行挂任务书引用与估时换代。**下一步待用户=四份裁点裁决(⑦P1-P5/⑤P1-P3/④P1-P3)+生涯提纲评审(④的门)**。
|
||||
388. **敌人表行集多行批完成(2026-10-07,迭代 17 卡①——纯结构批零内容投放;worktree g-plan2-iter17-enemy 分支 iter17-enemy-20261007 基点 e535436,批内提交 a0b06b4(L3 停机报告)/5b9cf59(用户甲案裁决留痕)/18cdcb0(T0 基线回填+事实表 L2 修订)/ab5ddad(T1 组 A GDD)/8690230(T2 组 B)/bc73fa3(T3 组 C)/c583940(T4 组 D)+T7/T8 收口批,全部在 worktree 未合并)**:敌人表同一(关卡序号×节点深度)坐标行集放开混编多种敌人——「每行集恰一敌种」加载期校验退役,换行集构成纪律三条=①行集内 enemy_id 唯一(同敌种第二行仍 dup_key 拦)②同坐标多行必须文件内相邻且行序=声明序=生成序(行序即契约,加载期相邻校验兜底报 rowset_rule)③行集实例总数(各行骰后数量求和)≤4(常量 EnemyTable.ROWSET_INSTANCE_MAX,spawn 期守卫 fail-fast——骰后值加载期不可判);Boss 行集同样放开(P4 乙),Boss 混编叙述取首行 display_name 为知情代价登记。floor 版 resolve_rowset 退役全仓统走 resolver ceil 行集数组(P2 甲——工作日志 312 双算法待裁项销号;冒烟四调用点迁移,坐标全精确命中零行为差);spawn 行集受理逐行实例化(生成序=文件行序、handle_id 连续、难度修饰行集同乘);遭遇骰改逐行各掷(Q8 用户裁——先逐行数量骰再逐行 atk 骰,单行行集判定/开流/消费序/次数与既有逐位一致=零内容期随机流零变化;atk 区间逐行同构属「每行一骰」预批准语义内代拍板留痕)。批中一次 L3 停机=任务书预设复用的卡⓪改前锚两份 jsonl 随卡⓪ worktree 删除丢失(sim-data 数据件不入 git 无历史可回溯,全盘核查零命中)→用户裁甲案=T0 现态补采改前锚 40 局(等价性已证:6e7b5d1..e535436 间 core/data/MC 脚本零 diff+引擎确定性)、本批 MC 总量 80 局超二档字面上限经用户明示批准(后续批次不得援引)。闸=冒烟 811/0(基线 805/0,+6=混编运行面正反断言)+run_all 17 套(含新增行集纪律套:混编相邻合法/Boss 坐标混编合法/隔断 rowset_rule 定位坐标/dup_key 不回归/单行域闸不回归)+probe_gate 含 click 全绿(残留 Godot=0)+doc 三闸/熵增闸对基线零新增(存量=link 死链 4/lint 2/熵增 diagrams 1)+MC 改前改后 40 局同种子配对全字段(每腿 660 字段)零差异——零内容期行为零漂移铁证;补采锚 L1 口径读数 off 4/20·formed 16/20 与卡⓪出口报告逐位同值=补采锚与丢失锚等价的旁证。异常=L2 一次(expect_pools 三元键换代连续 3 轮红:坐标敌种映射臆断错 4 键+3_7 池值手抄错,第 4 轮离线解析 tres 全量对账收敛——教训=三元键换代先离线全量对账再落码)。文档=敌人系统 v0.15(行集构成纪律三条成文+开战生成节逐行实例化口径+F10 前提句去同种假设)/难度曲线与Boss v0.24(混编难度归属注记)/registry rowset_rule 换代/06 状态行收口/roadmap 卡①行换代;出口报告=design/qa/iter17-enemy-exit-report-2026-10-07.md(P4 乙两读数面登记——叙述取首行成立、遭遇骰首行区间面经 Q8 逐行骰消解);人闸材料=design/qa/iter17-enemy-人闸材料-2026-10-07.md(实机目检四项+代拍板追认九项);遗留=实机目检归用户+Boss 多行投放时 unlock_hp_pct 无闸面逐行复核义务(内容批)+damage_probe A1 红灯=基线既有(stash 对照实证,非本批)。**下一步待用户=实机目检+代拍板追认,过闸后合并落 master;首个混编行内容投放归迭代 18 卡⑤**。
|
||||
@@ -162,7 +162,7 @@
|
||||
|
||||
**归属**:随[关卡节点地图](systems/冒险循环/关卡节点地图.md)定稿改键一并裁决
|
||||
|
||||
**状态**:部分收口(2026-09-17)——同层多遭遇问题已由关卡节点地图 v1.0 的**节点编号升级**消解(`node_depth` 语义 = 关卡内唯一节点编号,同层不同节点各查各行,键结构零改动);**不设精英 / Boss 编码位**(Boss = 最大编号节点,精英 P2 内容承载)。剩余面继续待办并改归属:同场多敌种(同一编号行集多行)的行集校验放开 ——归属**敌人表行集多行批(战斗侧,排技能池实施批落地后)**(混编伏击上限取值口径面已随 2026-09-20 单轮上限删除消解)。**已编入 roadmap 迭代 17 卡①(2026-10-05——任务书已成文待 U0:design/research/任务书-敌人表行集多行批-2026-10-05.md;前置「技能池实施批落地」已于 2026-10-05 满足〔d3fa887〕,开工门已解,4 项裁点已全裁并经 2026-10-06 联审二裁修订:P1甲〔Q8/Q9 补全=每行一骰·RNG 扩签先报批·实例总数≤4〕/P2甲/P3丙〔改裁撤投放——首混编行连同 Boss 多行归后续内容批,投时 MC 取证先报批+难度带读数义务随批登记 07〕/P4乙 Boss 行亦放开·零内容投放不变)**
|
||||
**状态**:**已实施完成(2026-10-07,敌人表行集多行批——迭代 17 卡①;worktree g-plan2-iter17-enemy 分支 iter17-enemy-20261007,批内提交 ab5ddad(T1 组 A 文档)/8690230(T2)/bc73fa3(T3)/c583940(T4)+收口批,出口报告 design/qa/iter17-enemy-exit-report-2026-10-07.md;闸=冒烟 811/0+run_all 17 套+probe_gate 含 click 全绿+doc 三闸/熵增存量红零新增+MC 改前改后 40 局同种子全字段零差异)**——本条剩余面「同场多敌种(同一编号行集多行)的行集校验放开」已随批落地:敌人表行集构成纪律三条新口径成文(行集内 enemy_id 唯一 / 同坐标多行文件内相邻且行序 = 声明序 = 生成序 / 行集实例总数 ≤ 4),混编机制放开含 Boss 行集(P1 甲 + P4 乙用户裁 2026-10-06);设计权威 = [敌人系统](systems/战斗循环/敌人系统.md) v0.15「行集构成纪律」。**遗留面(不在本批,登记不销号)**:首个混编行连同 Boss 多行的**内容投放**归后续内容批——投时 MC 取证先报批 + 难度带读数义务(P3 丙裁,2026-10-06;登记 [07-体验验证清单](07-体验验证清单.md) 口径),投放时 Boss 多行须逐行人工复核「Boss 行带 unlock_hp_pct 可静默过校验」的无闸面(技能池构成纪律系文档登记非硬校验)。**不设精英 / Boss 编码位**维持(Boss = 最大编号节点,精英 P2 内容承载)。历史:同层多遭遇 2026-09-17 由关卡节点地图 v1.0 节点编号升级消解;混编伏击上限取值口径面随 2026-09-20 单轮上限删除消解;任务书 design/research/任务书-敌人表行集多行批-2026-10-05.md(v1.1,4 项裁点全裁)
|
||||
|
||||
|
||||
#### 技能池情境条件触发器
|
||||
|
||||
@@ -273,6 +273,8 @@ Boss 战的棋盘用本关最大板形(板形行值读棋盘参数表),板
|
||||
|
||||
敌人表行值(行集与坐标覆盖随批次扩展,行值读 `enemy.tres`——本文只登记行模板与坐标语义):
|
||||
|
||||
**混编行集难度归属注记(2026-10-07 行集多行批——机制放开、本批零投放)**:敌人表同一坐标允许多行混编多种敌种后,混编遭遇的难度 = 行集内各行值按既有口径独立生效再叠加(数量区间各行各掷、行集实例总数 ≤ 4),不引入新的难度轴或乘区;首个混编行连同 Boss 多行的实际投放归后续内容批,投时行值 provisional 归本文调参的既有口径不变,且投放批须附 MC 取证(先报批)与难度带读数。机制批次(本批)零内容投放、零数值变更。
|
||||
|
||||
| 坐标 | 敌种(数据键) | 生命 | 攻击(浮动区间) | 数量 | 技能池(权重) | 护甲 |
|
||||
|---|---|---|---|---|---|---|
|
||||
| 关卡序号 × 节点深度 | enemy_id + display_name | hp | atk / [atk_min, atk_max] | [unit_count, unit_count_max] | {skill_id: weight} | armor_type + armor_class |
|
||||
@@ -358,3 +360,4 @@ Boss 战的棋盘用本关最大板形(板形行值读棋盘参数表),板
|
||||
| v0.21 | 2026-09-30 | 普通档改带 L1 [35,55]/L2 [10,15]+带表与验收标准回写现行口径 |
|
||||
| v0.22 | 2026-10-03 | **商店定价公式换代(迭代 11 第②批 GP 商店房重构批——任务书 v1.3 P1 共享池/P4 ceil/P5 甲;06 条 2026-10-02 用户裁决)**:商店与 GP 经济杠杆节公式换代 = ceil(基价 × b^(关序−1) × A^(进店已购次数)),A/b provisional 投值 1.8/1.1(原 P5 甲 game-balancer 研究拍板改后置追认——零人工令);杠杆位表换货架基价四行+价格因子 A/b 两行;分层验收 defer 节补 v0.22 注记(shop=off=legacy 对照 off_n60 逐位 / shop=on 首锚 N=60 双策略带平移归调参批/终局池读数只测不判)。行值零结构改动(shop.tres 扩列不退役) |
|
||||
| v0.23 | 2026-10-05 | **挖掘风险不等式判式换代(迭代14②号卡 T3——与行动经济/战斗结算/registry 同批)**:调参联动表 +6 新增行(旗溢价三件套 δ↔p_perfect↔ap_per_round / η 读数画像联动扩员 / β 带端点↔D_ref↔max_hp↔AC 折算 / 直伤雷三行↔正向同轴行〔同轴镜像比入对账面〕/ clear_blast 区间↔p_perfect / 标中强化池权重〔形态 b 条件生效行〕);P1 后置「挖掘风险不等式与清图支配性对账重跑」行改判读回执(不等式半边收口=判式重立+β 带检算接替,残留 u=3 β=1.17 登记态;清图支配性维持);五条经济契约对账段换代 |
|
||||
| v0.24 | 2026-10-07 | **混编行集难度归属注记(敌人表行集多行批·组 A——与 敌人系统 v0.15 / registry / 06 清单同批)**:敌人表行值节新增混编行集难度归属注记——同一坐标多行混编后各行值按既有口径独立生效再叠加(数量区间各行各掷、行集实例总数 ≤ 4),不引入新难度轴或乘区;首个混编行连同 Boss 多行投放归后续内容批,投时行值 provisional 归本文调参口径不变+MC 取证先报批+难度带读数义务。本批零内容投放零数值变更 |
|
||||
@@ -63,16 +63,16 @@
|
||||
|
||||
两条不变式贯穿始终:血量恒在 0 与上限之间;战斗内敌人只减不增。举证:本节为状态语义,无计算。
|
||||
|
||||
### 开战生成:主角数据行与一场 1–3 个同敌种单位
|
||||
### 开战生成:主角数据行与一场 1–4 个敌人(行集可混编多种敌种)
|
||||
|
||||
战斗开始时,编排方给出遭遇坐标(关卡序号 + 节点深度),本系统据此在敌人表里精确匹配一种敌种,把本战实际数量的敌人生成出来——每场战斗 1 到 3 个敌人,全部同种同属性,来自同一行表值;战斗中敌人只减不增,不做召唤、增援、分裂。主角同时以当前血量入参生成,血量越界(高于上限或不超过 0)整单拒绝、不留半实例。
|
||||
战斗开始时,编排方给出遭遇坐标(关卡序号 + 节点深度),本系统据此在敌人表里取出该坐标的整个行集(一行或多行),把本战实际数量的敌人逐行生成出来——每行各按自己的数量行值实例化(单行 1 到 3 个),行集实例总数(各行开战骰后数量求和)不超过 4。同坐标多行即混编遭遇:各敌种同场上阵,生成序 = 表文件行序(行序即契约——目标顺位、摇号子流派生、开战叙述取首行都按它,加载期校验兜底:同坐标多行必须文件内相邻)。单行行集 = 既有形态:一场 1 到 3 个同种同属性敌人,来自同一行表值。战斗中敌人只减不增,不做召唤、增援、分裂。主角同时以当前血量入参生成,血量越界(高于上限或不超过 0)整单拒绝、不留半实例。
|
||||
|
||||
生成拿到的是当时的表值快照:开战那一刻把数值和池模板各抄一份,之后改表不影响已生成的单位。池模板快照成每实例自己的实例池(各技能冷却清零),此后各自独立摇号、互不干涉。若数量或攻击基线配成了区间,由战斗结算用封闭随机流在开战时掷定一次后传入确定值——本系统自身始终零随机;掷定后整场持久,攻击基线不逐拍重掷(数字要可读)。
|
||||
生成拿到的是当时的表值快照:开战那一刻把每行的数值和池模板各抄一份,之后改表不影响已生成的单位。池模板快照成每实例自己的实例池(各技能冷却清零),此后各自独立摇号、互不干涉。某行的数量或攻击基线若配成了区间,由战斗结算用封闭随机流在开战时**按行各掷定一次**(每行掷自己的区间;掷定次数随行数——单行行集的掷定次数与既有口径逐位一致,混编不新增随机源形态)后传入确定值——本系统自身始终零随机;掷定后整场持久,攻击基线不逐拍重掷(数字要可读)。
|
||||
|
||||
| 规则 | 含义 |
|
||||
|---|---|
|
||||
| 敌方效果对全体生效 | 场上敌人全同种,范围效果作用于所有存活敌人是天然兼容的默认;"只打某一个"的单体寻址暂不开放(见 P1) |
|
||||
| 每个坐标只出一种敌种 | 敌人表按(关卡序号 × 节点深度)存放,同一坐标的行集内敌种唯一,违规加载期报错止动;同关随深度换敌种合法 |
|
||||
| 敌方效果对全体生效 | 范围效果作用于所有存活敌人——混编放开后(2026-10-07 行集多行批)场上可多种敌种共存,结算语义按存活单位逐一生效、不依赖"场上全同种"前提;"只打某一个"的单体寻址暂不开放(见 P1) |
|
||||
| 行集构成纪律 | 敌人表按(关卡序号 × 节点深度)存放,同一坐标行集允许多行、允许不同敌种混编。纪律三条,违规加载期报错止动:①行集内 enemy_id 唯一(同一敌种在同行集仍只许一行);②同坐标多行必须表文件内相邻,行序 = 声明序 = 生成序(行序即契约);③行集实例总数(各行骰后数量求和)≤ 4,单行数量域 [1,3] 不变(UNIT_COUNT_MAX 语义 = 单种数)。行数不设上限;同关随深度换敌种合法 |
|
||||
| 主角数据行 | 主角战斗数值单独放一张全局单行表:生命上限、基础攻击力、护甲等级三字段(见调参表) |
|
||||
| 基础攻击恒存在 | 基础攻击不许配 0(配置为 0 加载期拒绝)——零基线乘任何百分比增益恒为零,"胜利路径恒有"的保障从数据层杜绝死锁 |
|
||||
| 先手攻击不是敌方技能拍 | 每次结算战斗段主角先手攻击顺位最前的存活敌人,这是固定动作;奖励侧的道具与增益是基础攻击之外的规划面伤害,归[地图战斗资源](地图战斗资源.md) |
|
||||
@@ -225,7 +225,7 @@ Boss 专属身份 = 专属池承载:独占技能 + 权重轮廓(**三代错
|
||||
|
||||
配置表共三张。数值纪律(2026-09-17 降级批定稿):**本文只锁字段、取值域与规则,行值一律读配置表(切片 `game/data/tables/` 的 enemy / skills / hero 表)与 [registry 的 enemy / hero / skill 条目](../../../registry/entities.yaml),不在本文登记具体数值——防双写失同步**;曲线调参所有权归[难度曲线与Boss](../冒险循环/难度曲线与Boss.md)。
|
||||
|
||||
敌人表(按关卡坐标存放,每坐标行集恰一敌种):
|
||||
敌人表(按关卡坐标存放,每坐标行集一行或多行——多行即混编遭遇,构成纪律见核心规则「行集构成纪律」;单行行集 = 既有形态):
|
||||
|
||||
| 参数 | 取值域 | 说明 |
|
||||
|---|---|---|
|
||||
@@ -260,11 +260,11 @@ Boss 专属身份 = 专属池承载:独占技能 + 权重轮廓(**三代错
|
||||
|
||||
各敌种行值、池权重与池 EV 读数(含闸长期速率实测)一律读配置表与调参日志,本文不登记具体数值;EV 重锚与权重投值归[难度曲线与Boss](../冒险循环/难度曲线与Boss.md)。
|
||||
|
||||
结构冻结(非调参项,修订走本文流程):技能类型枚举封闭、每池恰一普攻、每池增益 ≤1、死亡即不动手(摇定后兑现前死亡作废不进账)、每结算每存活敌恰行动一次、行序、先作用后推进、固定顺位、每坐标恰一敌种、零随机(本系统自身语义零随机不变——摇号与掷点随机一律在[战斗结算](战斗结算.md)结算换算层按封闭随机流掷定,可回放契约 = 同种子同输入逐位复现,单敌出招轨迹可独立复放)。联动纪律:技能倍率 × 攻击(伤害拍支配)、权重 × 冷却 × 保底(池节奏三联动)禁止独立调参,联调须重跑方向性预检并同步 registry(见待办)。
|
||||
结构冻结(非调参项,修订走本文流程):技能类型枚举封闭、每池恰一普攻、每池增益 ≤1、死亡即不动手(摇定后兑现前死亡作废不进账)、每结算每存活敌恰行动一次、行序、先作用后推进、固定顺位、**行集构成纪律(2026-10-07 行集多行批换代——原「每坐标恰一敌种」退役:行集内 enemy_id 唯一 + 同坐标多行文件内相邻且行序 = 声明序 = 生成序 + 行集实例总数 ≤ 4)**、零随机(本系统自身语义零随机不变——摇号与掷点随机一律在[战斗结算](战斗结算.md)结算换算层按封闭随机流掷定,可回放契约 = 同种子同输入逐位复现,单敌出招轨迹可独立复放)。联动纪律:技能倍率 × 攻击(伤害拍支配)、权重 × 冷却 × 保底(池节奏三联动)禁止独立调参,联调须重跑方向性预检并同步 registry(见待办)。
|
||||
|
||||
## 验收标准
|
||||
|
||||
- 开战生成:按遭遇坐标精确匹配一行,实例化数量与数值投影同行值快照;池模板快照成实例池且冷却全零;主角以血量入参,越界(高于上限或不超过 0)拒绝且不留半实例。
|
||||
- 开战生成:按遭遇坐标取出该坐标行集(一行或多行,逐行实例化——行序 = 文件序),实例化数量与数值投影同行值快照;行集实例总数(各行骰后)≤ 4;池模板快照成实例池且冷却全零;主角以血量入参,越界(高于上限或不超过 0)拒绝且不留半实例。
|
||||
- 摇号确定性:同种子回放逐位复现(步骤流与各实例摇定动作序列逐位相同);单敌轨迹独立复放——只喂该敌子流(scope = 生成序 × 派生向量 + 摇号序)即可逐位重建其出招序列、互不穿插。
|
||||
- 池节奏:中签率 = 权重 ÷ 可摇权重合计(排除冷却中技能后归一);施放后连续 N 拍不可摇中;连续 M 拍执行普攻 → 下拍必出特殊技(特殊技内按权重、不受冷却限制);同技能连发不可能;首轮摇号、每轮恰摇一次、轮内刷新不重摇。
|
||||
- 死亡即不动手:摇定后、兑现前被杀——本拍技能作废(零行动明细行),不进冷却、不进保底计数;行动完成后才死——已兑付已进账;对已死亡单位上报受击被拒绝且状态不变。
|
||||
@@ -273,7 +273,7 @@ Boss 专属身份 = 专属池承载:独占技能 + 权重轮廓(**三代错
|
||||
- 警觉授予:踩 N 颗雷叠 N 层、逐层直授无上限;敌方全体共享同一状态值(side-wide)。
|
||||
- 目标顺位:多敌时单体目标恒为生成序最前存活者,杀最前后顺延;杀至空返回空;单敌时顺位与范围效果重合。
|
||||
- 快照抗改表:实例化后修改敌人表,已生成单位的数值投影与实例池逐字不变;新实例才用新表值。
|
||||
- 表校验:越域值、池权重 ≤ 0、空池、普攻配倍率/冷却、池增益 > 1、skill_id 悬空、同坐标第二敌种均在加载期报错止动;域内合法极端(攻击基线 0)不拒;主角表恰一行、攻击配 0 拒绝。
|
||||
- 表校验:越域值、池权重 ≤ 0、空池、普攻配倍率/冷却、池增益 > 1、skill_id 悬空、行集构成违例(行集内同敌种第二行 / 同坐标多行不相邻)均在加载期报错止动;域内合法极端(攻击基线 0)不拒;主角表恰一行、攻击配 0 拒绝。
|
||||
- 零随机回放:同一动作与受击序列驱动两个独立实例,存活投影、逐实例摇定轨迹、顺位返回序列逐项相同。
|
||||
- 表实一致:三张配置表字段与 registry 的 enemy / hero / skill 条目逐字段一致。
|
||||
|
||||
@@ -285,6 +285,7 @@ Boss 专属身份 = 专属池承载:独占技能 + 权重轮廓(**三代错
|
||||
|
||||
| 版本 | 日期 | 改动 |
|
||||
|---|---|---|
|
||||
| v0.15 | 2026-10-07 | **行集混编口径批(敌人表行集多行批·组 A 先行——与 难度曲线与Boss / registry / 06 清单 / 切片代码同批)**:①「每个坐标只出一种敌种」规则改写为行集构成纪律三条(行集内 enemy_id 唯一 / 同坐标多行文件内相邻且行序 = 声明序 = 生成序 / 行集实例总数 ≤ 4〔= 各行骰后数量求和,行数不设上限,单行数量域 [1,3] 不变、UNIT_COUNT_MAX 语义改单种数〕)——同坐标多行混编合法(P1 甲 + P4 乙用户裁:Boss 行集同样放开);②开战生成节改「取出整个行集逐行实例化」口径(生成序 = 文件行序即契约)+ 区间掷定改按行各掷一次(单行行集掷定次数与既有逐位一致——零内容期随机流零变化);③「敌方效果对全体生效」前提句去同种假设(效果按存活单位逐一生效);④结构冻结「每坐标恰一敌种」换代、验收标准开战生成与表校验两条同步。知情代价登记:Boss 行集多行后开战叙述取首行 display_name、Boss 节点遭遇骰读首行数量区间(= 全行集骰域)——两读数面随批写出口报告。零内容投放(P3 丙):本批表内容不变,首个混编行归后续内容批 |
|
||||
| v0.1 | 2026-09-15 | 自归档 GDD 压缩改写 |
|
||||
| v0.2 | 2026-09-15 | 教学位掷骰口径自洽(随[难度曲线与Boss](../冒险循环/难度曲线与Boss.md)同批修订):unit_count 字段说明、地精敌种定位与现行行值句中"教学位固定 1 只/固定不掷"改为 ×[1,2] 开战掷定 |
|
||||
| v0.3 | 2026-09-15 | **护甲等级批(用户拍板登记,与战斗结算 / 难度曲线与Boss / registry 同批,不动代码)**:敌人表与主角表 schema 各增 armor_class(护甲等级)字段(取值域随掷点形式定稿,provisional);三敌种表补护甲等级列(行值未定);护甲等级(数值轴)与护甲类型(克制属性轴)命名区分成文;结构冻结清单"零随机"措辞按新口径修订——本系统自身语义零随机不变,掷点随机在战斗结算换算层按封闭随机流消费、可回放契约 = 同种子同输入逐位复现;待拍板新增"护甲等级行值未定"条目 |
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
# L3 停机报告——敌人表行集多行批改前锚丢失(迭代 17 卡①,2026-10-07)
|
||||
|
||||
状态:**L3 停机**。命中时机 = T0 开工序(MC 锚开工前核验步);本 worktree(g-plan2-iter17-enemy,分支 iter17-enemy-20261007,基点 e535436)**零改动、零提交、未跑任何测试**,等用户发令后恢复。
|
||||
|
||||
## 一、停机事实
|
||||
|
||||
任务书 MC 对拍方案预设「**改前锚免跑——直接复用卡⓪落盘的 post 锚**」两份文件:
|
||||
|
||||
- `sim-data/runsum_iter17dd_post_off_n20_20261006.jsonl`
|
||||
- `sim-data/runsum_iter17dd_post_formed_n20_20261006.jsonl`
|
||||
|
||||
(出处:卡⓪出口报告 design/qa/iter17-datadrive-exit-report-2026-10-06.md §三;seed0=83000、每档 20 局。)
|
||||
|
||||
**执行会话全盘核查结论:两份文件已不存在于本机任何位置,不可恢复。**核查留痕(全部在本报告落档前现场执行):
|
||||
|
||||
| # | 核查动作 | 结果 |
|
||||
|---|---|---|
|
||||
| 1 | 本 worktree sim-data/ 列目录 | 只有随 git 走的三件(README.md / analyze.py / growth_model.py),无任何锚文件 |
|
||||
| 2 | 主区 D:\code\g-plan2\sim-data\ 列目录 | 最新文件停在 2026-10-05(iter14 批锚),无任何 2026-10-06 件,无 iter17dd 字样 |
|
||||
| 3 | `git worktree list` | 卡⓪ worktree(iter17-dd-20261006)已在收口时删除,现存仅主区+本 worktree+standee-tier+uialign 四处 |
|
||||
| 4 | `find /d/code -name "runsum_iter17*"` 全盘搜 | 零命中 |
|
||||
| 5 | `grep -rl "83000"`(主区 sim-data + design/qa) | 仅命中卡⓪出口报告 md 本身(文字记载),无任何数据文件含该种子 |
|
||||
| 6 | 两仓内 `find -name "*.jsonl" -newermt 2026-10-06` | 零命中 |
|
||||
|
||||
**根因**:sim-data 数据件自 2026-10-03 起整目录不入 git(.gitignore 强制,语义=磁盘缓存层);卡⓪的两份改后锚只存在于卡⓪ worktree 的 sim-data/ 里,从未复制进主区;收口 `git worktree remove` 时随目录一并删除。锚文件无任何 git 历史可回溯(从未被提交过),也无回收站外副本。
|
||||
|
||||
## 二、等价性核验(任务书预设的那道闸——已通过,与本次停机无关)
|
||||
|
||||
任务书要求开工前先核验「game/ 下模拟相关路径在 6e7b5d1(卡⓪锚采样点)与 T0 基点 e535436 之间 diff 为空」。**核验通过**:`git diff 6e7b5d1..e535436 -- game/` 全部改动落在 presentation/(卡③暂停层)与 smoke 探针文件;`game/core/`、`game/data/` 与 MC 采集脚本 adventure_monte_carlo.gd 三者**零 diff**。若锚文件还在,复用是成立的。停机原因不是等价性破,而是**被复用的对象本身不存在**。
|
||||
|
||||
## 三、影响面
|
||||
|
||||
1. **MC 逐项对拍腿失据**:设计契约 R1(零内容期逐位零漂移)要求「冒烟 + MC 同种子逐项一致」。没有改前锚,T6 的改后锚没有比对对象,R1 的 MC 腿无法闭环。
|
||||
2. **决策窗口在写码之前**:改前锚必须在本批任何代码改动落地前采集(T2 起改 game/ 即破坏「改前」码态)。所以这个问题**不能拖到 T6 再说**,必须现在停。
|
||||
3. **恢复动作涉及随机数消耗预算**:补采改前锚 = 新增 40 局模拟(off/formed 各 20),使本批模拟总量从任务书字面预算「总量 40(二档贴边)」升到 80 局。消耗预算属用户保留裁决面(四档硬闸「超档停机呈报」+ 本任务书「禁静默自采」条款),执行会话不得自采。
|
||||
|
||||
## 四、备选方案(交用户裁决,含各自代价)
|
||||
|
||||
| 案 | 内容 | 代价 / 收益 |
|
||||
|---|---|---|
|
||||
| **甲(推荐)** | 批准在 T0 现态(e535436,一行未改)补采改前锚 40 局(off/formed 各 20,seed0=83000,命名建议 `runsum_iter17enemy_pre_*`),T6 再采改后锚 40 局照原计划执行 | 本批模拟总量 80 局、约 7 分钟,超任务书字面「总量 40」但与卡⓪批实际支出形态完全一致(卡⓪也是改前 40+改后 40);等价性已证(core/data/MC 脚本在两提交点零 diff + 引擎确定性),补采的改前锚与丢失的卡⓪锚在数学上必然逐位相同,等于零信息损失。会话累计时长 ≤20 分钟合规 |
|
||||
| 乙 | 只保 off 档配对(改前/改后各 20 局,总量 40=字面贴边),formed 档放弃 | 预算不超字面;代价=成型注入画像面(卡⓪迁移的 14 件专长秘宝注入行)失去对拍腿。本批改的是敌人表/spawn 面、对两档同等生效,off 腿已覆盖本批触碰路径,但「逐项一致」覆盖面收窄,需用户明示接受 |
|
||||
| 丙 | 放弃 MC 腿,R1 只靠冒烟全量断言 + 静态等价论证收口 | 最省;代价=设计契约 R1 的字面被破(契约明确要求 MC 同种子逐项一致),且开了「锚丢了就不拍」的先例,**不建议** |
|
||||
| 丁 | 用户本地另有备份(网盘/手工拷贝),恢复两份 iter17dd 文件到本 worktree sim-data/ 后按原方案继续 | 零新增消耗;前提是备份确实存在 |
|
||||
|
||||
## 五、恢复路径(任一案获批后)
|
||||
|
||||
1. worktree 仍在原位且干净(基点 e535436),后续会话从 T0 剩余步骤续起:基线重测回填(冒烟/run_all/探针/doc 三闸/熵增)+ §2 事实表逐条重核(此前只完成锚核验步)。
|
||||
2. 案甲获批时先补采改前锚再动任何代码;案丁获批时核验恢复文件的行数(每档 20 行纯 JSONL)与种子序(83000 起升序)后照原方案走。
|
||||
3. 任务书其余部分(已裁点、契约、任务卡)不受本停机影响,无需修订。
|
||||
|
||||
## 六、停机自检对照
|
||||
|
||||
- 触发条款:任务书「停机点」清单 MC 相关硬闸 + CLAUDE.md MC 触发细则「任务书预设步骤的前提消失时停问勿照字面执行」+ sim-data README 配套纪律①「档位上限=硬闸,超档停机呈报」。
|
||||
- 未越权动作自证:未采任何一局模拟、未跑任何测试、未改任何文件(本报告除外)、未动主区与兄弟 worktree。
|
||||
|
||||
## 七、用户裁决(2026-10-07,停机解除令)
|
||||
|
||||
**裁甲案**:批准在 T0 现态(e535436,零代码改动)补采改前锚 40 局(seed0=83000,off/formed 各 20,与丢失的卡⓪锚数学上逐位相同——等价性已证);T6 改后锚 40 局照原计划同 seed0 同格式配对。**本批 MC 总量 80 局经用户明示批准**(超二档字面上限的例外已裁,后续批次不得援引为本先例)。裁决后从 L3 停机点续起:T0 剩余步骤(基线重测回填+事实表重核+补采改前锚留盘)→ T1-T8 按原任务书不变执行。
|
||||
@@ -0,0 +1,62 @@
|
||||
# 出口报告——敌人表行集多行批(迭代 17 卡①,2026-10-07)
|
||||
|
||||
状态:**批内全部提交完成、重闸全绿;终态 = worktree(iter17-enemy-20261007 分支)全部提交,不合并,待用户验收后人闸/落籍**。
|
||||
执行事实源:[任务书-敌人表行集多行批-2026-10-05](../research/任务书-敌人表行集多行批-2026-10-05.md)(v1.1 + T0 实核修订);设计权威:[敌人系统](../gdd/systems/战斗循环/敌人系统.md) v0.15。
|
||||
批性质:纯结构批(P3 丙)——混编机制放开、零内容投放、表内容零变更、零数值变更。
|
||||
执行波折:开工 T0 锚核验步命中一次 L3 停机(改前锚文件丢失,报告 [iter17-enemy-L3-改前锚丢失-2026-10-07](iter17-enemy-L3-改前锚丢失-2026-10-07.md)),用户裁甲案(补采改前锚+总量 80 局明示批准)后续起,全批一次性走完无二次停机。
|
||||
|
||||
## 一、提交清单(worktree 内,按卡)
|
||||
|
||||
| 卡 | 提交 | 内容 |
|
||||
|---|---|---|
|
||||
| L3 停机 | `a0b06b4` | 改前锚丢失停机报告(四案呈报) |
|
||||
| L3 解除 | `5b9cf59` | 用户裁甲案留痕(补采改前锚 40 局+总量 80 局批准) |
|
||||
| T0 | `18cdcb0` | 基线重测回填(冒烟 805/0+run_all 17 套+探针含 click 全绿+doc 三闸/熵增存量红零新增)+§2 事实表 L2 修订(行号漂移 6 项如实改列,全不动摇结构)+改前锚补采落盘 |
|
||||
| T1(组 A) | `ab5ddad` | GDD 修订先行:敌人系统.md v0.15(开战生成节行集逐行实例化口径+行集构成纪律三条规则行+F10 前提句去同种假设+结构冻结/调参表/验收两条+版本历史)+难度曲线与Boss.md v0.24(混编难度归属注记)+entities.yaml rowset_rule 换代+06 状态行已实施完成 |
|
||||
| T2(组 B) | `8690230` | schema 与解析:enemy_table.gd 恰一敌种校验退役→行序相邻校验(rowset_rule 沿用)+UNIT_COUNT_MAX 单种数语义+floor 版 resolve_rowset 退役(P2 甲,工作日志 312 销号);config_db_resolver.resolve_enemy_rowset 行集数组化(ceil 命中坐标全部行,文件序;board_gen 单行通道不动);config_db.gd 门面同步;全仓消费点机械适配取首行(spawn/orchestrator/narrator/smoke 七处/config_db_test/两探针) |
|
||||
| T3(组 C) | `bc73fa3` | 生成与编排:spawn 行集受理(逐行实例化+生成序=文件行序+handle_id 连续;override 入参改逐行数组)+行集实例总数≤EnemyTable.ROWSET_INSTANCE_MAX=4 守卫 fail-fast+难度修饰行集同乘(F9);battle_orchestrator 遭遇骰逐行骰换代(Q8:每行各掷自己区间,先逐行数量骰后逐行 atk 骰;单行行集消费序/次数逐位一致=零内容期随机流零变化) |
|
||||
| T4(组 D) | `c583940` | 断言与探针:expect_pools 换 (L,D,enemy_id) 三元键+L2/L3 定点断言行集口径+双表精确行集契约文案(主段+两复述段)+混编运行面正反断言六条((1,5)/(1,6) 注入,避开全部扫描面,断言后还原)+config_db_test 行集纪律套五条(validate 正反:混编相邻合法/Boss 坐标混编合法/隔断 rowset_rule 定位坐标/dup_key 不回归/单行域闸不回归) |
|
||||
| T7 | 本报告同批 | 人闸材料 [iter17-enemy-人闸材料-2026-10-07](iter17-enemy-人闸材料-2026-10-07.md)(目检四项+代拍板追认九项) |
|
||||
| T8 | 本报告同批 | 收口五步:本报告+active.md 快照台账 384+roadmap 卡①行换代+06 状态行补提交号与闸读数 |
|
||||
|
||||
## 二、闸读数(T0 基线 → T6 批末,全绿)
|
||||
|
||||
| 闸 | T0 基线 | T6 批末 | 结论 |
|
||||
|---|---|---|---|
|
||||
| 冒烟(三闸) | 805 项 / 0 失败 | **811 项 / 0 失败**(净增 6=混编正反断言,T4 追认) | 绿 |
|
||||
| 单元 run_all | 17 套全绿 | **17 套全绿**(含新增行集纪律套内断言) | 绿 |
|
||||
| 探针闸(probe_gate --click) | 全绿·残留 Godot=0 | **全绿·残留 Godot=0**(ui_input/ui_struct/ui_contrast/click) | 绿 |
|
||||
| doc 三闸 | link 过(死链 4 存量)/lint 存量红 2/term 过(疑似现行 3 存量) | **link 过(死链 4)/lint 2/term 3——逐项同基线零新增** | 绿 |
|
||||
| 熵增闸 | 存量红 1(design/diagrams,前批遗留) | **同 1 处,零新增** | 绿 |
|
||||
| MC 二档对拍 | 见 §三 | **40 局同种子逐项零差异** | 绿 |
|
||||
| 附:两探针直跑 | — | skill_rhythm_probe 输出正常;damage_probe 7 项 1 失败=A1 攻击链健康,**stash 对照实证基线既有**(与本批零相关;探针非闸门工具,如实登记) | 存量 |
|
||||
|
||||
## 三、MC 锚与对拍结论(用户裁甲案,总量 80 局明示批准)
|
||||
|
||||
- **改前锚(补采)**:`sim-data/runsum_iter17enemy_pre_off_n20_20261007.jsonl` / `runsum_iter17enemy_pre_formed_n20_20261007.jsonl`——T0 现态(e535436,零代码改动)采集,seed0=83000、N=20/档、normal、route=min、attune=off、shop=off、feat=off/formed 同种子配对。
|
||||
- **改后锚**:`sim-data/runsum_iter17enemy_post_off_n20_20261007.jsonl` / `runsum_iter17enemy_post_formed_n20_20261007.jsonl`——T6 时点(c583940 代码态)同参数采集。
|
||||
- **等价性论证(补采改前锚 ≡ 丢失的卡⓪锚)**:①git diff 6e7b5d1(卡⓪锚采样点)..e535436 对 game/core+game/data+adventure_monte_carlo.gd **零 diff**(其间唯一 game/ 改动=presentation 卡③暂停层+冒烟探针,不触模拟);②引擎确定性(卡⓪出口报告实证同种子改前/改后 40 局逐位一致)→同代码态同种子必逐位复现;③旁证:补采锚 L1 条件口径读数 off 4/20(20%)、formed 16/20(80%)与卡⓪出口报告记载**逐位同值**。
|
||||
- **对拍结论:R1 成立——40 局(2×20)同种子配对、每局 RUNSUM 全字段(660 字段/腿)逐项零差异**(零内容期行为零漂移的 MC 面铁证)。
|
||||
- 档位合规:本批实采 80 局(pre 40+post 40)——**超二档字面上限(40)的例外经用户 2026-10-07 明示批准**(L3 报告 §七),后续批次不得援引本先例;会话时长远低于 20 分钟帽。
|
||||
|
||||
## 四、P4 乙两读数面登记(用户裁乙案 Boss 行集放开的知情代价)
|
||||
|
||||
1. **开战叙述取首行(成立,已落码+留痕)**:`battle_narrator.boss_name` 取行集**首个命中行**的 display_name——Boss 行集多行后 Boss 名显示取决于文件行序(R6 契约的呈现面后果),混编护卫行时 Boss 名可能显示为护卫名。零内容期(每坐标恰一行)行为不变。落位 8690230,人工复核义务归 Boss 多行内容投放批。
|
||||
2. **Boss 节点遭遇骰区间(经 Q8 演化,原登记形态已消解)**:任务书 P4 乙原登记「Boss 骰读首行 unit_count 区间 = 全行集骰域」——Q8 二裁(每行各掷自己的数量骰)与 T3 落码后,数量骰与 atk 骰均**逐行各掷**,不再存在「首行区间代全行集」的读数面;替代登记面 = **各行骰后数量求和受行集实例总数 ≤4 守卫约束**(spawn fail-fast),内容批投 Boss 多行时按此口径复核节奏。
|
||||
|
||||
## 五、代拍板记录(白名单内九项,详见人闸材料追认清单;全部 commit 留痕)
|
||||
|
||||
行集数组返回形态(Array[Dictionary]/空集=空数组/文件序)·行序违例类别沿用 rowset_rule+坐标定位文案·spawn 逐行数组入参(短数组缺省 -1/空数组全行定值)·atk 区间骰逐行同构(「每行一骰」语义内)·ROWSET_INSTANCE_MAX=4 落位 EnemyTable·Boss 混编叙述取首行·混编断言注入选点 (1,5)/(1,6)·expect_pools 三元键形态·断言数漂移 805→811 追认。
|
||||
|
||||
## 六、异常分级记录
|
||||
|
||||
- **L3 一次**(改前锚丢失,T0):停机呈报→用户裁甲案→解除。详见 L3 报告。
|
||||
- **L2 一次**(池模板键值换代连续 3 轮红,T4):第 1 轮 4 键坐标-敌种映射臆断错;第 2 轮补修 (3,4)/(3,6);第 3 轮定位 3_7 池值手抄错(第一次手写 expect_pools 块时误抄);第 4 轮以「离线解析 tres 全量对账」法收敛,811/0。教训已随 T4 commit 留痕:**三元键换代先离线全量对账再落码**。不动摇任务书结构,不阻断全批。
|
||||
- 事实表 L2 修订(T0):行号漂移 6 项(F2 调用点/F4/F5a/F5b 路径/expect_pools/F5f 处数),全部如实改列任务书 §2,零结构性差异。
|
||||
|
||||
## 七、遗留人闸项
|
||||
|
||||
1. **实机目检归用户**(人闸材料 §一四项,建议抽查项 1+3)。
|
||||
2. **代拍板九项追认**(人闸材料 §二)。
|
||||
3. **Boss 多行投放批义务**(不在本批):unlock_hp_pct 无闸面逐行人工复核+节奏重测+MC 取证先报批+难度带读数(06/07 在册)。
|
||||
4. damage_probe A1 失败 = 基线既有(前批遗留,归伤害数学相关批主自证),非本批引入。
|
||||
@@ -0,0 +1,35 @@
|
||||
# 人闸材料——敌人表行集多行批(迭代 17 卡①,2026-10-07)
|
||||
|
||||
状态:**批内全部提交完成、重闸全绿**;本文件 = 实机目检清单 + 代拍板追认清单,交用户人闸(交付不代执行)。
|
||||
|
||||
## 一、实机目检清单(用户亲手执行;本批纯结构批零内容投放,目检目标 = 无回归确认)
|
||||
|
||||
本批在零内容期(敌人表 19 行不变)行为逐位不变——冒烟 811 项、MC 40 局同种子全字段零差异已机检背书;实机目检只须确认运行面无肉眼可见回归,建议 10 分钟内过完:
|
||||
|
||||
| # | 检查项 | 操作 | 合格判据 |
|
||||
|---|---|---|---|
|
||||
| 1 | 普通战斗生成 | 开局打第一关任意战斗节点 | 敌人数量、血条、名称与改前一致;无多出/缺失的敌人 |
|
||||
| 2 | 数量区间节点 | 打带数量区间的节点(如教学位之外多数节点) | 敌人 1–3 只正常出现,无异动 |
|
||||
| 3 | Boss 战叙述与生成 | 打穿第一关 Boss(食人魔酋长) | Boss 名正常显示「食人魔酋长」;半血解锁技照常弹出 |
|
||||
| 4 | 加载无报错 | 正常启动进入第一关 | 无报错弹窗、无卡死(行集校验换代后的加载面回归) |
|
||||
|
||||
以上全过 = 人闸通过;任何一项异常 = 停机呈报,禁自行修。
|
||||
|
||||
## 二、代拍板追认清单(任务书 §八白名单内已决断项,请用户过目追认;不同意任何一项即回滚该项重议)
|
||||
|
||||
| # | 决断点 | 落法 | 落位提交 |
|
||||
|---|---|---|---|
|
||||
| 1 | 行集数组返回形态 | `Array[Dictionary]`(该坐标全部行、表文件行序=契约序);空集=空数组(`is_empty()` 兼容旧判空习惯) | 8690230(T2) |
|
||||
| 2 | 行序违例错误类别 | 沿用 `rowset_rule`(定位面不变),文案「同坐标多行必须文件内相邻(行序即契约)」并含坐标定位 | 8690230(T2) |
|
||||
| 3 | spawn 入参形态 | `unit_count_override/enemy_atk_override` 改逐行数组(下标=行序);短数组缺省 -1=该行行值路径;空数组=全行定值(旧调用点零适配) | bc73fa3(T3) |
|
||||
| 4 | atk 区间骰逐行同构 | 混编行集 atk 区间同样每行各掷(与数量骰同构,消费序=先逐行数量骰、再逐行 atk 骰)——判读为「每行一骰」预批准语义内的行字段区间骰逐行化,非新增随机源形态;单行行集消费序/次数与既有逐位一致 | bc73fa3(T3) |
|
||||
| 5 | 行集总数常量落位 | `EnemyTable.ROWSET_INSTANCE_MAX := 4`(与数量域常量同位单点收口);守卫在 spawn(骰后值加载期不可判) | bc73fa3(T3) |
|
||||
| 6 | Boss 混编叙述口径(P4 乙知情代价) | `battle_narrator.boss_name` 取行集**首行** display_name——Boss 行集混编护卫时 Boss 名可能显示为护卫名(取决于文件行序);零内容期行为不变;两读数面已写出口报告 | 8690230(T2) |
|
||||
| 7 | 混编断言注入选点 | (1,5)/(1,6)(L1 节点图与全部既有扫描面之外的新深度;新 L 值会被 ceil 封顶不可用);断言后还原表,19 行复核兜底 | c583940(T4) |
|
||||
| 8 | expect_pools 三元键形态 | `"L_D_enemy_id"` 字符串键逐行精确比对(19 行九种,与表内容离线对账) | c583940(T4) |
|
||||
| 9 | 冒烟断言数漂移追认 | 805→811(净增 6 = 混编运行面正反断言六条) | c583940(T4) |
|
||||
|
||||
## 三、遗留人闸项(呈报不停机级)
|
||||
|
||||
1. **实机目检归用户**(上表四项,建议抽查项 1+3 即可覆盖主要回归面)。
|
||||
2. **Boss 多行投放时的 unlock_hp_pct 无闸面**:技能池构成纪律(每池恰一普攻/增益 ≤1/unlock_hp_pct 仅 Boss 行)系文档登记非硬校验——Boss 行集多行放开后该无闸面扩大,后续内容批投放 Boss 多行时须逐行人工复核(已在 06-待办清单条目登记)。
|
||||
@@ -279,7 +279,7 @@ entities:
|
||||
hp: int [1,999](knob——难度修饰前基线;MVP 18 provisional 出处待查)
|
||||
atk: int [0,999](knob——attack 行为伤害基值;MVP 4 provisional 出处待查;0 合法不拒——2026-09-20 八型批去"纯伏击伤敌种"旧注)
|
||||
pool: Array of {skill_id, weight[, unlock_hp_pct]}(**2026-09-16 敌人技能池批——池模板**,定义层;weight ∈ (0,9999] knob、池内 skill_id 不重复;**unlock_hp_pct 可选 int [1,99]——2026-10-05 技能池执行批新增〔迭代14④〕:Boss 半血解锁门槛,缺省无字段=无门槛;锁定条目双面过滤不进可摇与保底集合、单向闩、解锁出一次归因行+一次性技能名 toast〔语义=敌人系统 意图呈现节;投放纪律=仅 Boss 行,不做跨表硬闸〕**;每池恰一行普通攻击 + 增益技 ≤1 + skill_id 悬空致命〔加载校验在 config_db.validate_skill_pool_links 跨表通道〕;实例池〔快照+冷却状态〕在 单位容器 spawn——三敌种建议池构成与权重不列于本 registry,读 data/tables/enemy.tres(provisional 归 难度曲线与Boss;EV 锚与含闸长期速率实测读数随验收批另测登记〔2026-09-18 指路化收口〕))。**历史(2026-09-16 退役)**:heavy_multiplier int [1,16](重击倍率归技能行 damage_mult)与 pattern StringList(行为环环数组)两字段随行为环整体退役——固定出招剧本废除
|
||||
rowset_rule: 每行集恰一敌种(行集内 enemy_id 唯一 = 表结构校验,违规加载期致命)——同层多遭遇已由节点编号消解(2026-09-17 关卡节点地图 v1.0:node_depth 语义 = 关卡内唯一节点编号,同层不同节点各查各行、键结构零改动);同场多敌种(同一编号行集多行)行集校验放开归 敌人表行集多行批(混编伏击上限取值口径随 2026-09-20 上限删除消解)(战斗侧,排技能池实施批落地后;06-待办清单 敌人系统节同名条目单点登记);精英/Boss 不设编码位——Boss = 最大编号节点(图唯一终点)、精英 P2 内容承载(强敌行集)。**精英怪设定登记(迭代 10 奖励重构批 P-D——实装随怪物批)**:与其他普通小怪同一立绘 + 附加特征标记 + 数值更强;视觉特征三件 = 名称前后缀(「精英·熊地精」式——沿用既有译名不换词根)+ 精英底座光环(程序化零立绘改动)+ 精英描边变色(色板合规与样张闸义务随实装批);掉落挂点 = 钥石 1 个(meta.tres boss_keystone 精英行随实装批落)
|
||||
rowset_rule: 行集构成纪律(**2026-10-07 行集多行批换代——原「每行集恰一敌种」退役**,违规一律加载期致命):①行集内 enemy_id 唯一(同坐标同敌种仍只许一行)②同坐标多行必须表文件内相邻且行序 = 声明序 = 生成序(行序即契约——resolver 返回序/开战叙述取首行/生成序全依赖文件行序)③行集实例总数(各行开战骰后数量求和)≤ 4(单行数量域 [1,3] 不变,UNIT_COUNT_MAX 语义 = 单种数)——同坐标多行混编合法(含 Boss 行集,P1 甲 + P4 乙用户裁 2026-10-06;本批零内容投放 P3 丙,首个混编行归后续内容批)——同层多遭遇已由节点编号消解(2026-09-17 关卡节点地图 v1.0:node_depth 语义 = 关卡内唯一节点编号,同层不同节点各查各行、键结构零改动);进度键解析全仓统一 ceil 版行集数组(原 EnemyTable.resolve_rowset floor 单行版同批退役——双算法销号,工作日志 312);精英/Boss 不设编码位——Boss = 最大编号节点(图唯一终点)、精英 P2 内容承载(强敌行集)。**精英怪设定登记(迭代 10 奖励重构批 P-D——实装随怪物批)**:与其他普通小怪同一立绘 + 附加特征标记 + 数值更强;视觉特征三件 = 名称前后缀(「精英·熊地精」式——沿用既有译名不换词根)+ 精英底座光环(程序化零立绘改动)+ 精英描边变色(色板合规与样张闸义务随实装批);掉落挂点 = 钥石 1 个(meta.tres boss_keystone 精英行随实装批落)
|
||||
mvp_content: **八敌种(2026-09-14 难度曲线与Boss 修订批转正 goblin / bugbear / ogre_chief 三敌种〔DND 更名批用户指令:grub→goblin / ambusher→bugbear / boss_guardian→ogre_chief〕;2026-09-17 分支节点图批新增 giant_spider / drider,本条 2026-09-18 补收编;2026-09-20 第三关内容批新增 duergar / hook_horror / duergar_king,本条随批补收编;敌人系统 物种集断言随批更新为 {goblin, bugbear, ogre_chief, giant_spider, drider, duergar, hook_horror, duergar_king})**:goblin(地精,armor=light)/ bugbear(熊地精,armor=ward)/ ogre_chief(食人魔酋长,armor=heavy)/ giant_spider(巨蜘蛛)/ drider(蛛化卓尔精灵,Boss = 最大编号节点图唯一终点)/ duergar(灰矮人,单体重甲中坚——重甲首次登台,armor=heavy)/ hook_horror(钩爪恐魔,群行捕食者,armor=light)/ duergar_king(灰矮人石君王,L3 Boss,重甲收束「轻甲→魔法甲→重甲」教学梯度)。技能池构成与权重、armor_type 行映射**不列于本 registry**——〔**2026-09-28 M-3 迭代 5 T4 AC 投值批→2026-09-29 返工批 U2 裁 v1 重投**:初版 Boss-only(杂鱼全 0·Boss 8/9/12)被 U2 推翻——终版 **v1 硬梯度**=杂鱼按 T4 报告 §一 软梯度恢复(0~5 带内)+重击手 8/重装手 9(逐行手设值,非精英编码位——解读 A 追认)+Boss 台阶 8/10/12;v1 中间态未入 git,杂鱼行按报告表值代拟恢复(台账 247);演化链与三版读数见 git 提交 8ffc555,裁断全录 git 提交 f9c1a8a;冒烟带宽断言随新形态更新(杂鱼 0~5·重击手/重装手 8~9·Boss 8~12 台阶)〕读 data/tables/enemy.tres(L3 行值语义:duergar 关间台阶 ≈L2 单体 ×1.5 落 [1.3,1.6] 域、hook_horror 复用 bite 共享技能行、两敌种首遇位〔节点 0/1〕固定数量不加骰、Boss 血 75 = Σ普通战生命期望 91 × r_boss≈0.82 provisional 锚;行值全 provisional 归 难度曲线与Boss)。**2026-09-17 数值压缩批·文档同步——hp/atk 等数值列改指路存根**:L1/L2 节点编号行集(D0–D8)共 12 行的 hp · atk · atk_min · atk_max · unit_count · unit_count_max · advantage_per_round_cap · armor_class 等现行值**不列于本 registry**——读 `data/tables/enemy.tres`(数值压缩批注释登记:`L1 D0 24/7 → 8/2`、`L1 D1 13/5 → 4/2`、`L1 D2 40/9 → 13/3`、`L1 D3 18/6 → 6/2`、`L1 D4 150/9 → 50/3` Boss、`L2 D0 30/7 → 10/2`、`L2 D1 15/5 → 5/2`、`L2 D4 14/5 → 5/2`、`L2 D5 38/8 → 13/3`、`L2 D6 12/4 → 4/1`、`L2 D7 13/5 → 4/2`、`L2 D8 175/8 → 58/3` drider);armor_type / armor_class / unit_count 区间 / 技能池权重 / advantage_per_round_cap 不压缩(相对轴与概率轴)。**2026-09-16 敌人技能池批**:行为环拍序列([attack] 单拍环 / [attack,charge,heavy] 三拍环 / [attack,attack,charge,heavy] 四拍环)与 heavy_multiplier=2 退役,改池模板 + 技能表共享技能行(重击倍率 2 = 技能行 damage_mult);出处 = 切片 enemy.tres(技能池批改型),曲线数值与池权重归 难度曲线与Boss
|
||||
load_bearing_rules: 多敌模型(1–3 同敌种单位,增益状态 单敌假设回验不成立——见 status_effect.single_enemy_assumption)· 行为环确定性轮转(零随机;先作用后推进;死亡即不动手——轮到前被杀本拍不打指针冻结;同步轮转定理)· 效果 side-wide(原伏击池 = side 共享、增益状态 零接口变更——伏击池随 2026-09-20 八型批退役,side-wide 承载改由增益状态 alert 行承接)· 行值快照抗热重载(增益状态 EC9 同款——池模板同在快照范围,实例池冷却全零起步)· **技能池摇号出招(2026-09-16 敌人技能池批改写——原"行为环确定性轮转/同步轮转定理"退役)**:每拍做什么 = 实例池权重摇号〔开轮时点,随机消费在 战斗结算 换算层 behavior_roll 封闭流;本系统语义零随机不变、单位容器收确定值〕;两道闸 = 全技能各自冷却 + 保底 M;死亡即不动手(摇定后兑现前死亡 → 本拍作废不进账);拍结构保留(每结算每存活敌恰行动一次/行序/先作用后推进)· 零随机零 UI 零事件订阅(排雷玩法 事件面不含 敌人系统——事实经 战斗结算 转化)
|
||||
settlement_obligations: 六项(敌人系统 GDD 门禁评审缺项即 blocking)——① 行动每结算恰一次(敌单位专属——主角无环)+ 结算内调用序成文 按摇定技能行兑现→apply_damage→commit_action〔2026-09-16 技能池批改型——原 query_attack→apply_damage→advance 随行为环退役〕 ② 雷→伏击恰一次转化 ③ clamp/负值/溢杀与死亡判定时机成文 ④ F1 条款 3 闭合对账(cap 表值 + 量纲 + 棋盘生成 actuals p10 非 target 参数)⑤ 默认目标消费与单体/AOE 分流 ⑥ 伏击 cap 溢出"溢出未生效"明细行协议。**履行回执(2026-09-10)**:六项已全数落位 战斗结算 GDD(Core Rules 5/6/9/10/12 + Formulas F3/F4——落位映射 = 战斗结算 AC 覆盖矩阵)。**2026-09-20 修订**:④⑥ 随伏击单轮上限删除(用户拍板)退役——对账面去 cap 表值、溢出行协议作废;八型批再修订(2026-09-20 格面资源八型批):② 雷→伏击恰一次转化改 雷→警觉恰一次转化
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
|
||||
## 2. 现状事实(代码级考证,2026-10-05 起草时点;T0 须自行复核)
|
||||
|
||||
> **T0 实核修订(2026-10-07,基点 e535436,L2 记录级——行号漂移不动摇结构)**:F1/F2 函数体/F6/F7/F11 主段/F8/F9 全部无漂移;漂移项如实改列——F2 冒烟四调用点现 = `smoke_all.gd:3534/3536/3566/3569`(卡③暂停层批 smoke_all 加行后移);F4 spawn 函数头现 = `unit_container.gd:42`(取行 :47、数量守卫 :66-69、难度修饰 :61-63 不变);F5 战前预取现 = `battle_orchestrator.gd:181`(遭遇骰 :182-193「数量骰先、atk 骰后」同 scope,spawn 调用 :196);battle_narrator.gd 实际路径 = `game/presentation/battle_narrator.gd`(boss_name 定义 :71、resolve :75、取名 :76——非 core/);config_db_test 现 = `:60`;expect_pools 段现 = `smoke_all.gd:3052-3084`(文案行 :3084);「smoke_all 十余处」实核 = 直接调用 7 处(ceil 3 处 :1997/:2311/:3239 + floor 4 处)另加跨表契约断言段 :294-311 与 :3518-3533/:3555-3564 两处复述段。补采改前锚 40 局已获用户批准落盘(L3 报告 §七,seed0=83000,`runsum_iter17enemy_pre_{off,formed}_n20_20261007.jsonl`)。
|
||||
|
||||
| # | 事实 | 读数 |
|
||||
|---|---|---|
|
||||
| F1 | 「每行集恰一敌种」校验位置 | `game/data/schemas/enemy_table.gd:108-112`——按 `(level_index, node_depth)` 聚合,行集内出现第二个 `enemy_id` 即报 `rowset_rule` 类错误,加载期致命中止 |
|
||||
|
||||
@@ -178,23 +178,45 @@ func begin_battle(enc: Dictionary) -> bool:
|
||||
# 2026-09-14 敌方攻击区间批扩展:行有 atk_min 时按 [atk_min, atk_max] 骰 spawn 期整战持久值
|
||||
# (每拍抖动否决——数字可读性锚;中点 = 行值)。encounter 封闭流恰一 scope(数量骰先、atk 骰后);
|
||||
# 挖掘决策域之外——P1 合规;敌人系统 零随机纪律保持(收 override 即确定值)。
|
||||
var erow_pre: Dictionary = db.resolve_enemy_rowset(int(enc.level_index), int(enc.node_depth))
|
||||
var roll_lo: int = int(erow_pre.get("unit_count", 1))
|
||||
var roll_hi: int = int(erow_pre.get("unit_count_max", roll_lo))
|
||||
var needs_count: bool = roll_hi > roll_lo
|
||||
var needs_atk: bool = erow_pre.has("atk_min")
|
||||
var rolled := roll_lo
|
||||
var rolled_atk := -1
|
||||
# 遭遇骰(难度曲线与Boss GDD Core Rule 8——2026-09-12 用户拍板):行有 unit_count_max 时按 [unit_count, max] 均匀骰;
|
||||
# 2026-09-14 敌方攻击区间批扩展:行有 atk_min 时按 [atk_min, atk_max] 骰 spawn 期整战持久值
|
||||
# (每拍抖动否决——数字可读性锚;中点 = 行值)。encounter 封闭流恰一 scope(数量骰先、atk 骰后);
|
||||
# 挖掘决策域之外——P1 合规;敌人系统 零随机纪律保持(收 override 即确定值)。
|
||||
# 逐行骰换代(2026-10-07 行集多行批 Q8 用户裁 + P1 补充):混编行集**每行各掷自己的区间骰**——
|
||||
# 先按行序逐行数量骰、再按行序逐行 atk 骰(单行行集 = 既有一次数量骰 + 一次 atk 骰,判定条件、
|
||||
# 开流条件、消费序、消费次数逐位一致——零内容期随机流零变化;区间宽度为零的行不掷 = 「定值不骰」
|
||||
# 既有口径;atk 区间逐行同构 = 行值语义完整,代拍板随批留痕:属「每行一骰」预批准语义内的
|
||||
# 行字段区间骰逐行化,非新增随机源形态)。
|
||||
var erowset_pre: Array = db.resolve_enemy_rowset(int(enc.level_index), int(enc.node_depth))
|
||||
if erowset_pre.is_empty():
|
||||
_fatal("敌人表 行集解析为空(%d,%d)" % [int(enc.level_index), int(enc.node_depth)])
|
||||
return false
|
||||
var count_overrides: Array = []
|
||||
var atk_overrides: Array = []
|
||||
var needs_count := false
|
||||
var needs_atk := false
|
||||
for r in erowset_pre:
|
||||
if int(r.get("unit_count_max", int(r.get("unit_count", 1)))) > int(r.get("unit_count", 1)):
|
||||
needs_count = true
|
||||
if r.has("atk_min"):
|
||||
needs_atk = true
|
||||
if needs_count or needs_atk:
|
||||
var estream: RandomNumberGenerator = rng.open_stream("encounter")
|
||||
if needs_count:
|
||||
rolled = roll_lo + estream.randi_range(0, roll_hi - roll_lo)
|
||||
for r in erowset_pre:
|
||||
var lo: int = int(r.get("unit_count", 1))
|
||||
var hi: int = int(r.get("unit_count_max", lo))
|
||||
count_overrides.append((lo + estream.randi_range(0, hi - lo)) if hi > lo else lo)
|
||||
if needs_atk:
|
||||
rolled_atk = int(erow_pre.atk_min) + estream.randi_range(0, int(erow_pre.atk_max) - int(erow_pre.atk_min))
|
||||
for r in erowset_pre:
|
||||
if r.has("atk_min"):
|
||||
atk_overrides.append(int(r.atk_min) + estream.randi_range(0, int(r.atk_max) - int(r.atk_min)))
|
||||
else:
|
||||
atk_overrides.append(-1)
|
||||
# E4 收口:加成经 encounter 显式携带(hero_atk/hero_max_hp;缺省 = 表值——冒烟/工具直呼路径)
|
||||
_hero_atk = int(enc.get("hero_atk", int(db.hero.atk)))
|
||||
if not _enemy_system.spawn(int(enc.level_index), int(enc.node_depth), int(enc.hero_hp), rolled,
|
||||
_hero_atk, int(enc.get("hero_max_hp", -1)), rolled_atk):
|
||||
if not _enemy_system.spawn(int(enc.level_index), int(enc.node_depth), int(enc.hero_hp), count_overrides,
|
||||
_hero_atk, int(enc.get("hero_max_hp", -1)), atk_overrides):
|
||||
_fatal("敌人系统 spawn 被拒")
|
||||
return false
|
||||
if not _install_new_board():
|
||||
|
||||
@@ -186,8 +186,8 @@ func resolve_board_gen(L: int, D: int) -> Dictionary:
|
||||
return _resolver.resolve_board_gen(L, D)
|
||||
|
||||
|
||||
func resolve_enemy_rowset(L: int, D: int) -> Dictionary:
|
||||
return _resolver.resolve_enemy_rowset(L, D)
|
||||
func resolve_enemy_rowset(L: int, D: int) -> Array[Dictionary]:
|
||||
return _resolver.resolve_enemy_rowset(L, D) # 行集数组形态(2026-10-07 行集多行批——原单行 Dictionary 退役)
|
||||
|
||||
|
||||
# 难度曲线与Boss DifficultyTable 消费面(敌人系统.spawn 调用):(L,D) 精确匹配修饰乘数,越域值 clamp(GDD Edge Case——组合事故非配置事故)
|
||||
|
||||
@@ -30,8 +30,11 @@ func resolve_board_gen(L: int, D: int) -> Dictionary:
|
||||
return _resolve_progress(_db.board_gen.rows, L, D, "board_gen")
|
||||
|
||||
|
||||
func resolve_enemy_rowset(L: int, D: int) -> Dictionary:
|
||||
return _resolve_progress(_db.enemy.rows, L, D, "enemy")
|
||||
func resolve_enemy_rowset(L: int, D: int) -> Array[Dictionary]:
|
||||
# 行集数组形态(2026-10-07 敌人表行集多行批——原单行 Dictionary 退役):ceil 命中 (l*,d*) 后
|
||||
# 返回该坐标全部行、按表文件行序(行序即契约——同坐标多行文件内相邻由 EnemyTable.validate 兜底)。
|
||||
# 空集表达 = 空数组(生产表下 ceil 命中坐标恒有行,空集仅表空时可达——validate 已拦)。
|
||||
return _resolve_progress(_db.enemy.rows, L, D, "enemy", true)
|
||||
|
||||
|
||||
# 难度曲线与Boss DifficultyTable 消费面(敌人系统.spawn 调用):(L,D) 精确匹配修饰乘数,越域值 clamp(GDD Edge Case——组合事故非配置事故)
|
||||
@@ -47,7 +50,7 @@ func resolve_difficulty_modifiers(L: int, D: int) -> Dictionary:
|
||||
return {}
|
||||
|
||||
|
||||
func _resolve_progress(rows: Array, L: int, D: int, table_id: String) -> Dictionary:
|
||||
func _resolve_progress(rows: Array, L: int, D: int, table_id: String, return_all := false) -> Variant:
|
||||
if L < 1 or D < 0:
|
||||
_db._fatal("request_oob", "%s 请求越域 (%d,%d)——进度坐标低于合法域(关卡序号≥1、节点深度≥0)" % [table_id, L, D])
|
||||
return {}
|
||||
@@ -94,6 +97,12 @@ func _resolve_progress(rows: Array, L: int, D: int, table_id: String) -> Diction
|
||||
_warn_dedup[dedup_key] = true
|
||||
var verb := "clamp 解析(超出最大行取最大值)" if missing.contains("clamp") else "ceil 解析(向上取整保证偏难)"
|
||||
_db.push_diag("warning", "resolve_" + missing, "%s 请求 (%d,%d) %s → (%d,%d) [%s]——2026-09-18 拍板" % [table_id, L, D, verb, l_star, d_star, missing])
|
||||
if return_all:
|
||||
var all_out: Array[Dictionary] = []
|
||||
for row in rows:
|
||||
if int(row.get("level_index", 0)) == l_star and int(row.get("node_depth", 0)) == d_star:
|
||||
all_out.append(row)
|
||||
return all_out
|
||||
for row in rows:
|
||||
if int(row.get("level_index", 0)) == l_star and int(row.get("node_depth", 0)) == d_star:
|
||||
return row
|
||||
|
||||
+63
-42
@@ -39,13 +39,18 @@ func _init(db_ref: ConfigDb) -> void:
|
||||
# 此前调用方写 db.hero 表值再由本类读表 = 共享可变单例传参(双写叠加 6→18→54 教训根源)。
|
||||
# enemy_atk_override(2026-09-14 敌方攻击区间批):遭遇骰同流的 spawn 期整战持久 roll 结果
|
||||
# (-1 = 表值定值路径;≥0 = 行值替换后再乘关卡 atk_mult)。敌人系统 零随机纪律保持。
|
||||
func spawn(level_index: int, node_depth: int, hero_hp: int, unit_count_override: int = -1,
|
||||
atk_override: int = -1, max_hp_override: int = -1, enemy_atk_override: int = -1) -> bool:
|
||||
# 行集受理换代(2026-10-07 行集多行批 P1 甲):unit_count_overrides / enemy_atk_overrides 改**逐行数组**
|
||||
# (下标=行集行序,长度短于行集时缺省 -1 = 该行行值路径;空数组 = 全行定值——旧调用点零适配)。
|
||||
# 逐行实例化、生成序 = 文件行序(行序即契约,敌人系统 v0.15);行集实例总数(各行传入数量求和)
|
||||
# ≤ ENEMY_ROWSET_INSTANCE_MAX 守卫 fail-fast。
|
||||
func spawn(level_index: int, node_depth: int, hero_hp: int, unit_count_overrides: Array = [],
|
||||
atk_override: int = -1, max_hp_override: int = -1, enemy_atk_overrides: Array = []) -> bool:
|
||||
if _spawned:
|
||||
push_warning("[敌人系统] Alive 相位重复 spawn(相位守卫)")
|
||||
return false
|
||||
var row: Dictionary = db.resolve_enemy_rowset(level_index, node_depth)
|
||||
if row.is_empty():
|
||||
# 行集数组口径(2026-10-07 行集多行批——resolver 返回该坐标全部行、文件序)
|
||||
var rowset: Array = db.resolve_enemy_rowset(level_index, node_depth)
|
||||
if rowset.is_empty():
|
||||
push_error("[敌人系统] 遭遇行解析失败/越域 (%d,%d)" % [level_index, node_depth])
|
||||
assert(false, "遭遇行悬空(R1 前置守卫)")
|
||||
return false
|
||||
@@ -57,48 +62,64 @@ func spawn(level_index: int, node_depth: int, hero_hp: int, unit_count_override:
|
||||
# max_hp = 生效上限(非入参 hero_hp)——2026-09-11 关卡扩展批修复:跨战斗携带 HP 时上限不得压扁
|
||||
# (恢复点/治疗包的满血守卫与治疗上限随之失效——切片登记接口语义澄清)
|
||||
_hero = {"hp": hero_hp, "max_hp": eff_max_hp, "atk": eff_atk, "is_hero": true, "alive": true, "display_name": "探险者", "enemy_id": "hero", "armor_type": String(db.hero.get("armor_type")) if db.hero.get("armor_type") else "light", "attack_type": String(db.hero.get("attack_type")) if db.hero.get("attack_type") else "normal"} # 护甲/攻击类型轴快照(2026-09-18 营地扩展前置批——可配置;甲效矩阵消费面)
|
||||
_enemies.clear() # 难度曲线与Boss DifficultyTable 修饰(2026-09-12 结构位兑现):施加于行值、行值快照之前——MVP 空表 = 恒 1.0 无行为(AC-10)
|
||||
_enemies.clear() # 难度曲线与Boss DifficultyTable 修饰(2026-09-12 结构位兑现):施加于行值、行值快照之前——MVP 空表 = 恒 1.0 无行为(AC-10);混编行集内全部敌种同乘((L,D) 精确匹配一次取值——F9 同乘不改变异,敌人系统 v0.15)
|
||||
var mod: Dictionary = db.resolve_difficulty_modifiers(level_index, node_depth)
|
||||
var hp_mult: float = float(mod.get("hp_mult", 1.0))
|
||||
var atk_mult: float = float(mod.get("atk_mult", 1.0))
|
||||
# unit_count_override ≥1 = 战斗结算 遭遇骰结果(敌人系统 零随机纪律——收到即确定值;-1 = 行值定值路径)
|
||||
# 数量域常量单点 = EnemyTable.UNIT_COUNT_MIN/MAX(2026-10-02 修复批——与表校验同源)
|
||||
var count: int = unit_count_override if unit_count_override >= 1 else int(row.unit_count)
|
||||
if count < EnemyTable.UNIT_COUNT_MIN or count > EnemyTable.UNIT_COUNT_MAX:
|
||||
push_warning("[敌人系统] 实例化数量越域: %d" % count)
|
||||
# 逐行数量定值(敌人系统 零随机纪律——骰定在 战斗结算 遭遇骰层按行完成,本层收确定值;
|
||||
# 行 i 数量 = overrides[i](≥1 时)否则该行 unit_count 行值)
|
||||
var per_row_counts: Array[int] = []
|
||||
var total_instances := 0
|
||||
for row_i in range(rowset.size()):
|
||||
var row_i_dict: Dictionary = rowset[row_i]
|
||||
var ovr: int = int(unit_count_overrides[row_i]) if row_i < unit_count_overrides.size() else -1
|
||||
var count: int = ovr if ovr >= 1 else int(row_i_dict.unit_count)
|
||||
if count < EnemyTable.UNIT_COUNT_MIN or count > EnemyTable.UNIT_COUNT_MAX:
|
||||
push_warning("[敌人系统] 行 %d 实例化数量越域(单种数域 [%d,%d]): %d" % [row_i, EnemyTable.UNIT_COUNT_MIN, EnemyTable.UNIT_COUNT_MAX, count])
|
||||
return false
|
||||
per_row_counts.append(count)
|
||||
total_instances += count
|
||||
# 行集实例总数守卫(行集构成纪律③——各行骰后数量求和 ≤4;骰后值加载期不可判,此处 fail-fast)
|
||||
if total_instances > EnemyTable.ROWSET_INSTANCE_MAX:
|
||||
push_warning("[敌人系统] 行集实例总数越域(≤%d): %d" % [EnemyTable.ROWSET_INSTANCE_MAX, total_instances])
|
||||
return false
|
||||
for i in range(count):
|
||||
var eff_row_atk: int = enemy_atk_override if enemy_atk_override >= 0 else int(row.atk)
|
||||
# 实例池快照(proposal §2.2:开战把模板快照一份,冷却全零——与"生成拿到当时的表值快照"同一条快照纪律)
|
||||
var pool_snap: Array[Dictionary] = []
|
||||
for entry in row.get("pool", []):
|
||||
var snap_entry := {
|
||||
"skill_id": String(entry.get("skill_id", "")),
|
||||
"weight": int(entry.get("weight", 0)),
|
||||
"cooldown_left": 0,
|
||||
}
|
||||
# Boss 半血解锁技(迭代14④ T3——unlock_hp_pct 随池模板快照进实例池;缺省无字段=无门槛;
|
||||
# unlocked=单向闩标记,初始锁定)
|
||||
if entry.has("unlock_hp_pct"):
|
||||
snap_entry["unlock_hp_pct"] = int(entry.get("unlock_hp_pct", 0))
|
||||
snap_entry["unlocked"] = false
|
||||
pool_snap.append(snap_entry)
|
||||
_enemies.append({
|
||||
"handle_id": i,
|
||||
"enemy_id": String(row.enemy_id),
|
||||
"display_name": String(row.display_name),
|
||||
"hp": maxi(1, int(round(float(row.hp) * hp_mult))),
|
||||
"max_hp": maxi(1, int(round(float(row.hp) * hp_mult))),
|
||||
"atk": maxi(0, int(round(float(eff_row_atk) * atk_mult))),
|
||||
"pool": pool_snap, # 实例池(模板快照 + 冷却状态——独立摇号互不干涉)
|
||||
"pending_skill": "", # 本拍摇定动作(开轮摇号写入;兑现前死亡 = 作废不 commit)
|
||||
"roll_seq": 0, # 单敌摇号拍序(诊断标签——并流后不参与派生,ADR-0007 裁丙 2026-09-27)
|
||||
"basic_streak": 0, # 保底计数:连续执行普攻的拍数(执行上报驱动)
|
||||
"armor_type": String(row.get("armor_type", "light")), # 护甲类型快照(克制矩阵消费面——战斗结算·战斗段;2026-09-15 命名统一批:light/ward/heavy)
|
||||
"armor_class": int(row.get("armor_class", 0)), # 护甲等级快照(掷点判定阈值基数——战斗结算·战斗段;2026-09-16 护甲等级掷点批)
|
||||
"alive": true,
|
||||
"is_hero": false,
|
||||
})
|
||||
var handle := 0
|
||||
for row_i in range(rowset.size()):
|
||||
var row: Dictionary = rowset[row_i]
|
||||
var eovr: int = int(enemy_atk_overrides[row_i]) if row_i < enemy_atk_overrides.size() else -1
|
||||
for i in range(per_row_counts[row_i]):
|
||||
var eff_row_atk: int = eovr if eovr >= 0 else int(row.atk)
|
||||
# 实例池快照(proposal §2.2:开战把模板快照一份,冷却全零——与"生成拿到当时的表值快照"同一条快照纪律)
|
||||
var pool_snap: Array[Dictionary] = []
|
||||
for entry in row.get("pool", []):
|
||||
var snap_entry := {
|
||||
"skill_id": String(entry.get("skill_id", "")),
|
||||
"weight": int(entry.get("weight", 0)),
|
||||
"cooldown_left": 0,
|
||||
}
|
||||
# Boss 半血解锁技(迭代14④ T3——unlock_hp_pct 随池模板快照进实例池;缺省无字段=无门槛;
|
||||
# unlocked=单向闩标记,初始锁定)
|
||||
if entry.has("unlock_hp_pct"):
|
||||
snap_entry["unlock_hp_pct"] = int(entry.get("unlock_hp_pct", 0))
|
||||
snap_entry["unlocked"] = false
|
||||
pool_snap.append(snap_entry)
|
||||
_enemies.append({
|
||||
"handle_id": handle,
|
||||
"enemy_id": String(row.enemy_id),
|
||||
"display_name": String(row.display_name),
|
||||
"hp": maxi(1, int(round(float(row.hp) * hp_mult))),
|
||||
"max_hp": maxi(1, int(round(float(row.hp) * hp_mult))),
|
||||
"atk": maxi(0, int(round(float(eff_row_atk) * atk_mult))),
|
||||
"pool": pool_snap, # 实例池(模板快照 + 冷却状态——独立摇号互不干涉)
|
||||
"pending_skill": "", # 本拍摇定动作(开轮摇号写入;兑现前死亡 = 作废不 commit)
|
||||
"roll_seq": 0, # 单敌摇号拍序(诊断标签——并流后不参与派生,ADR-0007 裁丙 2026-09-27)
|
||||
"basic_streak": 0, # 保底计数:连续执行普攻的拍数(执行上报驱动)
|
||||
"armor_type": String(row.get("armor_type", "light")), # 护甲类型快照(克制矩阵消费面——战斗结算·战斗段;2026-09-15 命名统一批:light/ward/heavy)
|
||||
"armor_class": int(row.get("armor_class", 0)), # 护甲等级快照(掷点判定阈值基数——战斗结算·战斗段;2026-09-16 护甲等级掷点批)
|
||||
"alive": true,
|
||||
"is_hero": false,
|
||||
})
|
||||
handle += 1
|
||||
_spawned = true
|
||||
_despawned = false
|
||||
return true
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
# VERTICAL SLICE - NOT FOR PRODUCTION
|
||||
# Validation Question: 玩家能否无指导在一场完整战斗中经历「开战→挖掘规划→轮末结算逐行兑现→胜/负」并逐行归因(P2)
|
||||
# Date: 2026-09-10
|
||||
# 数据配置 EnemyTable / HeroTable schema(敌人系统 回填值)。EnemyTable 键 (L,D,enemy_id),每行集恰一敌种;
|
||||
# 数据配置 EnemyTable / HeroTable schema(敌人系统 回填值)。EnemyTable 键 (L,D,enemy_id),行集可多行混编
|
||||
# (行集构成纪律 = 敌人系统 v0.15:行集内 enemy_id 唯一〔dup_key 拦〕/ 同坐标多行文件内相邻〔行序即契约,本表
|
||||
# validate 兜底〕/ 行集实例总数 ≤4 守卫在 单位容器 spawn〔骰后值,加载期不可判〕);
|
||||
# HeroTable 单行全局(Rule 4 豁免)。依据 design/gdd/systems/战斗循环/敌人系统.md Schema 节。
|
||||
# 敌人技能池批(2026-09-16 用户拍板,设计权威 proposal-skill-pool.md〔提案已吸收退役 git a6833b6a——现行事实源=敌人系统.md 技能池节〕 v1.0):pattern 行为环数组与
|
||||
# heavy_multiplier 退役,改池模板 pool = [{skill_id, weight}](定义层——实例池快照与冷却状态在 单位容器)。
|
||||
@@ -16,10 +18,17 @@ extends Resource
|
||||
const ARMOR_TYPES := ["light", "ward", "heavy"]
|
||||
|
||||
# 实例化数量域(2026-10-02 修复批 T2 魔法数结构化——数量域 [1,3] 双落点收口单点:
|
||||
# 本表 validate 与 单位容器 spawn 守卫共用;遭遇骰结果与行值 unit_count/unit_count_max 同域)
|
||||
# 本表 validate 与 单位容器 spawn 守卫共用;遭遇骰结果与行值 unit_count/unit_count_max 同域。
|
||||
# 2026-10-07 行集多行批:MAX 语义 = **单种数**(单行实例数上限),行集实例总数 ≤4 另由
|
||||
# spawn 期守卫承担——骰后值加载期不可判,双闸分工见 敌人系统 v0.15 行集构成纪律③)
|
||||
const UNIT_COUNT_MIN := 1
|
||||
const UNIT_COUNT_MAX := 3
|
||||
|
||||
# 行集实例总数上限(2026-10-07 行集多行批 P1 甲——行集构成纪律③:各行开战骰后数量求和 ≤4;
|
||||
# 「总数」= 实例数非行数〔Q9 二裁〕,行数不设上限。骰后值加载期不可判——守卫在 单位容器 spawn,
|
||||
# 常量单点在本表与数量域同位收口)
|
||||
const ROWSET_INSTANCE_MAX := 4
|
||||
|
||||
|
||||
func validate() -> Array:
|
||||
var errs: Array[Dictionary] = []
|
||||
@@ -27,7 +36,8 @@ func validate() -> Array:
|
||||
errs.append({"category": "empty_table", "message": "EnemyTable 为空"})
|
||||
return errs
|
||||
var seen := {}
|
||||
var rowset_species := {}
|
||||
var last_rk := ""
|
||||
var closed_rk := {}
|
||||
var anchor_ok := {}
|
||||
for row in rows:
|
||||
var L: int = int(row.get("level_index", 0))
|
||||
@@ -105,11 +115,16 @@ func validate() -> Array:
|
||||
var ac: int = int(row.get("armor_class", 0))
|
||||
if ac < 0 or ac > 999:
|
||||
errs.append({"category": "domain", "message": "%s armor_class 越域 [0,999]: %d" % [eid, ac]})
|
||||
# 每行集恰一敌种(行集内 enemy_id 唯一)
|
||||
# 行集构成纪律②(2026-10-07 行集多行批——行序即契约,敌人系统 v0.15):同坐标多行必须
|
||||
# 文件内相邻。迭代中记录上一行坐标;当前坐标曾出现过但 ≠ 上一行坐标 = 同坐标行被隔断,报错。
|
||||
# 原纪律「每行集恰一敌种」同批退役——同坐标多敌种混编合法;同坐标同敌种第二行仍由
|
||||
# dup_key 拦截(键含 enemy_id)。错误类别沿用 rowset_rule(定位面不变)。
|
||||
var rk := "%d_%d" % [L, D]
|
||||
if rowset_species.has(rk):
|
||||
errs.append({"category": "rowset_rule", "message": "(%d,%d) 行集出现第二敌种(每行集恰一敌种违例)" % [L, D]})
|
||||
rowset_species[rk] = eid
|
||||
if rk != last_rk:
|
||||
if closed_rk.has(rk):
|
||||
errs.append({"category": "rowset_rule", "message": "(%d,%d) 行集行序违例:同坐标多行必须文件内相邻(行序即契约——resolver 返回序/生成序/叙述取首行全依赖文件行序)" % [L, D]})
|
||||
closed_rk[rk] = true
|
||||
last_rk = rk
|
||||
anchor_ok[L] = anchor_ok.get(L, false) or D == 0
|
||||
for L in anchor_ok.keys():
|
||||
if not anchor_ok[L]:
|
||||
@@ -117,16 +132,6 @@ func validate() -> Array:
|
||||
return errs
|
||||
|
||||
|
||||
# R1:进度键 floor + 行集恰一敌种(实体键无歧义,悬空致命由调用方处理)
|
||||
func resolve_rowset(L: int, D: int) -> Dictionary:
|
||||
var best: Dictionary[String, Variant] = {}
|
||||
var best_l := -1
|
||||
var best_d := -1
|
||||
for row in rows:
|
||||
var rl: int = int(row.get("level_index", 0))
|
||||
var rd: int = int(row.get("node_depth", 0))
|
||||
if rl <= L and rd <= D and (rl > best_l or (rl == best_l and rd > best_d)):
|
||||
best.assign(row)
|
||||
best_l = rl
|
||||
best_d = rd
|
||||
return best
|
||||
# 进度键解析单点收口(2026-10-07 行集多行批 P2 甲——原 floor 语义 resolve_rowset 退役,全仓统走
|
||||
# ConfigDbResolver.resolve_enemy_rowset ceil 版行集数组:2026-09-18 用户拍板 ceil 保证偏难,
|
||||
# 双算法并存至本批销号〔工作日志 312 待裁项〕;原冒烟四调用点随批迁移,坐标全精确命中零行为差)。
|
||||
@@ -67,13 +67,17 @@ static func phase_text(round_index: int, battle_result: String, waiting: bool, b
|
||||
return "第 %d 轮 · 挖掘中%s" % [round_index, boss_tag]
|
||||
|
||||
|
||||
# Boss 名解析(runner Boss 节点 → enemy 表行名;缺省遗迹守卫)
|
||||
# Boss 名解析(runner Boss 节点 → enemy 表行名;缺省遗迹守卫)。
|
||||
# 行集多行后取**首行** display_name(2026-10-07 行集多行批——行序即契约的呈现面后果,
|
||||
# Boss 行集混编护卫时 Boss 名显示可能为护卫名,知情代价登记 敌人系统 v0.15 / 出口报告;
|
||||
# 零内容期每坐标恰一行,行为零变化)
|
||||
static func boss_name(runner, db) -> String:
|
||||
if runner != null:
|
||||
var node: Dictionary = runner.current_node()
|
||||
if String(node.get("type", "")) == "boss":
|
||||
var row: Dictionary = db.resolve_enemy_rowset(int(runner.level_row.level_index), int(node.get("node_depth", -1)))
|
||||
return String(row.get("display_name", ""))
|
||||
var rowset: Array = db.resolve_enemy_rowset(int(runner.level_row.level_index), int(node.get("node_depth", -1)))
|
||||
if not rowset.is_empty():
|
||||
return String(rowset[0].get("display_name", ""))
|
||||
return "遗迹守卫"
|
||||
|
||||
|
||||
|
||||
@@ -267,7 +267,7 @@ func _encounter_prediction(db, seed_val: int) -> Dictionary:
|
||||
if t != "battle" and t != "boss":
|
||||
continue
|
||||
var depth := int(node.get("node_depth", -1))
|
||||
var row: Dictionary = db.resolve_enemy_rowset(1, depth)
|
||||
var row: Dictionary = db.resolve_enemy_rowset(1, depth)[0] # 行集首行(行集多行批 T2 机械适配)
|
||||
var lo := int(row.get("unit_count", 1))
|
||||
var hi := int(row.get("unit_count_max", lo))
|
||||
var rolled := lo
|
||||
@@ -418,7 +418,7 @@ func _scan_spawns(db, seed0: int, n_seeds: int) -> Dictionary:
|
||||
bad += 1
|
||||
continue
|
||||
var n: int = settlement.presentation_snapshot().enemies.size()
|
||||
var row: Dictionary = db.resolve_enemy_rowset(1, int(depth))
|
||||
var row: Dictionary = db.resolve_enemy_rowset(1, int(depth))[0] # 行集首行(同上)
|
||||
var lo := int(row.get("unit_count", 1))
|
||||
var hi := int(row.get("unit_count_max", lo))
|
||||
if n < 1 or n < lo or n > hi:
|
||||
|
||||
@@ -13,8 +13,8 @@ func _initialize() -> void:
|
||||
var db = load("res://core/config_db.gd").new()
|
||||
db.load_tables("res://data/tables", false)
|
||||
|
||||
# ① 表侧
|
||||
var row = db.resolve_enemy_rowset(1, 1)
|
||||
# ① 表侧(2026-10-07 行集多行批 T2 机械适配——行集数组取首行,零内容期行为零变化)
|
||||
var row = db.resolve_enemy_rowset(1, 1)[0]
|
||||
print("[1] row(1,1) display=", row.get("display_name"), " unit_count=", row.get("unit_count"),
|
||||
" pool=", row.get("pool"))
|
||||
|
||||
|
||||
+86
-43
@@ -291,7 +291,8 @@ func _api_mark_node(_node: Dictionary, _info: Dictionary, seq: Array) -> void:
|
||||
func _smoke_adventure() -> void:
|
||||
print("--- 冒险结构验收(三关序列 · 大奖励 · 摘要五件事 · 账本封闭)---")
|
||||
var autoplay = load("res://smoke/level_autoplay.gd")
|
||||
# ① 表与覆盖义务(序列关数 = 行集关数;行集内每个战斗/Boss 节点跨表精确行——覆盖义务断言)
|
||||
# ① 表与覆盖义务(序列关数 = 行集关数;行集内每个战斗/Boss 节点跨表精确行集——覆盖义务断言;
|
||||
# 2026-10-07 行集多行批:「精确行」改「精确行集」口径——enemy 侧同坐标多行合法,坐标级键聚合天然兼容)
|
||||
check(int(_db.level.rows.size()) == 3, "序列关数 = 行集关数(三关正式序列生效)")
|
||||
var bg_keys := {}
|
||||
for row in _db.board_gen.rows:
|
||||
@@ -308,7 +309,7 @@ func _smoke_adventure() -> void:
|
||||
var key := "%d_%d" % [int(row.level_index), int(n.get("node_depth", -1))]
|
||||
if not bg_keys.has(key) or not en_keys.has(key):
|
||||
miss += 1
|
||||
check(miss == 0, "行集内每个战斗/Boss 节点在 board_gen + enemy 有精确行(缺失 %d)" % miss)
|
||||
check(miss == 0, "行集内每个战斗/Boss 节点在 board_gen + enemy 有精确行集(缺失 %d)" % miss)
|
||||
# ② 满配通关 + ④ 三层奖励兑付(三选一恰 2 次 · 回血封顶 · 钥石逐杀 · 候选零重复)
|
||||
var st: Dictionary = autoplay.run_adventure(_db, 42, 900, 400)
|
||||
var sum: Dictionary = st["summary"]
|
||||
@@ -1994,7 +1995,7 @@ func _smoke_difficulty_table() -> void:
|
||||
var enemy_system = load("res://core/unit_container.gd").new(_db)
|
||||
check(enemy_system.spawn(1, 0, int(_db.hero.max_hp)), "spawn 受理")
|
||||
var unit = enemy_system.all_enemies()[0]
|
||||
var d0: Dictionary = _db.resolve_enemy_rowset(1, 0)
|
||||
var d0: Dictionary = _db.resolve_enemy_rowset(1, 0)[0] # 行集数组口径取首行(零内容期每坐标恰一行,T2 机械适配)
|
||||
check(int(unit.hp) == int(d0.hp) and int(unit.atk) == int(d0.atk), "空表零修饰(hp=%d atk=%d = 行值 %d/%d)" % [int(unit.hp), int(unit.atk), int(d0.hp), int(d0.atk)])
|
||||
# ② 修饰行运行时注入(debug 通道——R3 override 同族):套乘生效于 hp/atk
|
||||
_db.difficulty.rows.append({"level_index": 1, "node_depth": 0, "hp_mult": 1.5, "atk_mult": 2.0})
|
||||
@@ -2308,7 +2309,7 @@ func _smoke_encounter_roll() -> void:
|
||||
scan_bad += 1
|
||||
continue
|
||||
var n: int = settlement_scan.presentation_snapshot().enemies.size()
|
||||
var erow2: Dictionary = _db.resolve_enemy_rowset(1, int(depth_v))
|
||||
var erow2: Dictionary = _db.resolve_enemy_rowset(1, int(depth_v))[0] # 行集首行(T2 机械适配)
|
||||
var lo2: int = int(erow2.get("unit_count", 1))
|
||||
var hi2: int = int(erow2.get("unit_count_max", lo2))
|
||||
if n < 1 or n < lo2 or n > hi2:
|
||||
@@ -3048,31 +3049,32 @@ func _smoke_skill_pool_data() -> void:
|
||||
var off_guard_row: Dictionary = _db.status_effect_row("off_guard")
|
||||
check(not off_guard_row.is_empty() and String(off_guard_row.target_side) == "hero" and String(off_guard_row.unit) == "ac",
|
||||
"失衡状态行(hero · ac 轴——妨害技落点,ConfigDB side 守卫正例)")
|
||||
# 行集键 = (level_index, node_depth)——分支节点图批起 bugbear 等敌种跨关异池,enemy_id 不再唯一
|
||||
# 行集键 = (level_index, node_depth, enemy_id)——分支节点图批起 bugbear 等敌种跨关异池,enemy_id 不再唯一;
|
||||
# 2026-10-07 行集多行批:同坐标混编多行后每行各一池,键升维到三元组(行序 = 文件序 = 契约序)
|
||||
var expect_pools := {
|
||||
"1_0": {"attack": 9, "lunge": 1},
|
||||
"1_1": {"attack": 9, "lunge": 1},
|
||||
"1_2": {"attack": 6, "charge": 2, "heavy": 2},
|
||||
"1_3": {"attack": 6, "charge": 2, "heavy": 2},
|
||||
"1_4": {"attack": 6, "heavy": 2, "harden": 2, "quake_smash": 2},
|
||||
"2_0": {"attack": 6, "lunge": 1, "heavy": 2},
|
||||
"2_1": {"attack": 6, "lunge": 1, "heavy": 2},
|
||||
"2_4": {"attack": 6, "bite": 2, "charge": 1},
|
||||
"2_5": {"attack": 5, "lunge": 2, "heavy": 2},
|
||||
"2_6": {"attack": 6, "bite": 2, "charge": 1},
|
||||
"2_7": {"attack": 6, "bite": 2, "charge": 1},
|
||||
"2_9": {"attack": 6, "heavy": 2, "venom_burst": 2, "web_snare": 2, "venom_curb": 2},
|
||||
"3_0": {"attack": 6, "charge": 2, "heavy": 2},
|
||||
"3_1": {"attack": 6, "bite": 2, "charge": 1},
|
||||
"3_4": {"attack": 6, "bite": 2, "charge": 1},
|
||||
"3_5": {"attack": 5, "lunge": 2, "heavy": 2},
|
||||
"3_6": {"attack": 6, "bite": 2, "charge": 1},
|
||||
"3_7": {"attack": 6, "charge": 2, "heavy": 2},
|
||||
"3_9": {"attack": 6, "heavy": 2, "earth_pulse": 2, "rockslide": 2},
|
||||
"1_0_goblin": {"attack": 9, "lunge": 1},
|
||||
"1_1_goblin": {"attack": 9, "lunge": 1},
|
||||
"1_2_bugbear": {"attack": 6, "charge": 2, "heavy": 2},
|
||||
"1_3_hobgoblin": {"attack": 6, "charge": 2, "heavy": 2},
|
||||
"1_4_ogre_chief": {"attack": 6, "heavy": 2, "harden": 2, "quake_smash": 2},
|
||||
"2_0_bugbear": {"attack": 6, "lunge": 1, "heavy": 2},
|
||||
"2_1_bugbear": {"attack": 6, "lunge": 1, "heavy": 2},
|
||||
"2_4_giant_spider": {"attack": 6, "bite": 2, "charge": 1},
|
||||
"2_5_bugbear": {"attack": 5, "lunge": 2, "heavy": 2},
|
||||
"2_6_giant_spider": {"attack": 6, "bite": 2, "charge": 1},
|
||||
"2_7_giant_spider": {"attack": 6, "bite": 2, "charge": 1},
|
||||
"2_9_drider": {"attack": 6, "heavy": 2, "venom_burst": 2, "web_snare": 2, "venom_curb": 2},
|
||||
"3_0_duergar": {"attack": 6, "charge": 2, "heavy": 2},
|
||||
"3_1_hook_horror": {"attack": 6, "bite": 2, "charge": 1},
|
||||
"3_4_hook_horror": {"attack": 6, "bite": 2, "charge": 1},
|
||||
"3_5_duergar": {"attack": 5, "lunge": 2, "heavy": 2},
|
||||
"3_6_hook_horror": {"attack": 6, "bite": 2, "charge": 1},
|
||||
"3_7_duergar": {"attack": 6, "charge": 2, "heavy": 2},
|
||||
"3_9_duergar_king": {"attack": 6, "heavy": 2, "earth_pulse": 2, "rockslide": 2},
|
||||
}
|
||||
var pools_ok := true
|
||||
for row in _db.enemy.rows:
|
||||
var rk := "%d_%d" % [int(row.level_index), int(row.node_depth)]
|
||||
var rk := "%d_%d_%s" % [int(row.level_index), int(row.node_depth), String(row.enemy_id)]
|
||||
if not expect_pools.has(rk):
|
||||
pools_ok = false
|
||||
continue
|
||||
@@ -3081,7 +3083,7 @@ func _smoke_skill_pool_data() -> void:
|
||||
got[String(entry.skill_id)] = int(entry.weight)
|
||||
if got != expect_pools[rk]:
|
||||
pools_ok = false
|
||||
check(pools_ok, "十九行池模板 = 建议池行值(L1 地精 9/1 · 熊地精 6/2/2 · 酋长 6/2/2;L2 熊地精 6/1/2 · 蜘蛛 6/2/1 · 重击手 5/2/2 · 蛛化卓尔精灵 6/2/2/2〔(2,9)——商店房批 Boss 重编号〕;L3 灰矮人 6/2/2 · 钩爪恐魔 6/2/1 · 重装手 5/2/2 · 石君王 6/2/2〔earth_pulse·(3,9)〕——全部 provisional;三 Boss 池尾 +1 门控条目〔quake_smash/venom_curb/rockslide 权重 2+unlock_hp_pct 50——迭代14④ T5〕)")
|
||||
check(pools_ok, "十九行九种池模板 = 建议池行值((L,D,enemy_id) 三元键逐行精确比对——2026-10-07 行集多行批口径;L1 地精 9/1 · 熊地精 6/2/2 · 酋长 6/2/2;L2 熊地精 6/1/2 · 蜘蛛 6/2/1 · 重击手 5/2/2 · 蛛化卓尔精灵 6/2/2/2〔(2,9)——商店房批 Boss 重编号〕;L3 灰矮人 6/2/2 · 钩爪恐魔 6/2/1 · 重装手 5/2/2 · 石君王 6/2/2〔earth_pulse·(3,9)〕——全部 provisional;三 Boss 池尾 +1 门控条目〔quake_smash/venom_curb/rockslide 权重 2+unlock_hp_pct 50——迭代14④ T5〕;混编行集同坐标多行各一池合法,零内容期每坐标仍恰一行)")
|
||||
var basic_count_ok := true
|
||||
for row in _db.enemy.rows:
|
||||
var n := 0
|
||||
@@ -3236,7 +3238,7 @@ func _smoke_skill_pool_death_void() -> void:
|
||||
for s in range(1, 400):
|
||||
var rg = load("res://core/rng_service.gd").new()
|
||||
rg.set_master_seed(s)
|
||||
var erow: Dictionary = _db.resolve_enemy_rowset(1, 2)
|
||||
var erow: Dictionary = _db.resolve_enemy_rowset(1, 2)[0] # 行集首行(T2 机械适配)
|
||||
var entries: Array = []
|
||||
for entry in erow.pool:
|
||||
entries.append({"skill_id": String(entry.skill_id), "weight": int(entry.weight)})
|
||||
@@ -3515,7 +3517,8 @@ func _smoke_level_graph() -> void:
|
||||
check(green_ok, "首遇位零踩雷:完美档 12 种子(节点 0 熊地精)恒零踩雷")
|
||||
check(green_wins >= 7, "首遇战胜局 ≥7/12(实际 %d——阶段拔高后锚行退出绿档,多数胜口径)" % green_wins)
|
||||
check(green_min_hp > 0, "首遇战胜后 HP 下探读数 %d(>0——绿档记录)" % green_min_hp)
|
||||
# ⑦ 跨表行完整:L2 每战斗/Boss 节点 (2, 编号) 在 board_gen 与 enemy 精确行(加载校验同款显式复述)
|
||||
# ⑦ 跨表行完整:L2 每战斗/Boss 节点 (2, 编号) 在 board_gen 与 enemy 精确行集(加载校验同款显式复述;
|
||||
# 2026-10-07 行集多行批:「精确行」口径改「精确行集」——enemy 侧同坐标多行合法,键聚合坐标级天然兼容)
|
||||
var bg_keys := {}
|
||||
for row in _db.board_gen.rows:
|
||||
bg_keys["%d_%d" % [int(row.level_index), int(row.node_depth)]] = true
|
||||
@@ -3530,12 +3533,21 @@ func _smoke_level_graph() -> void:
|
||||
var key := "2_%d" % int(node.node_depth)
|
||||
if not bg_keys.has(key) or not en_keys.has(key):
|
||||
cross_ok = false
|
||||
check(cross_ok, "跨表行完整:L2 全部战斗/Boss 节点在 board_gen + enemy 精确行(7 节点)")
|
||||
var l2_spider: Dictionary = _db.enemy.resolve_rowset(2, 4)
|
||||
check(String(l2_spider.get("enemy_id", "")) == "giant_spider", "巨蜘蛛首遇行集 (2,4) = giant_spider(固定 2 只——首遇教学位不加骰)")
|
||||
var l2_boss: Dictionary = _db.enemy.resolve_rowset(2, 9)
|
||||
check(String(l2_boss.get("enemy_id", "")) == "drider" and String(l2_boss.get("armor_type", "")) == "ward",
|
||||
"蛛化卓尔精灵 Boss 行集 (2,9) = drider(魔法甲——护甲类型重配批 2026-09-18:关卡 2 唯一非轻甲;商店房批重编号 (2,8)→(2,9))")
|
||||
check(cross_ok, "跨表行完整:L2 全部战斗/Boss 节点在 board_gen + enemy 精确行集(7 节点)")
|
||||
# ⑦a 定点:L2 首遇行集与 Boss 行集(2026-10-07 行集多行批口径——断言行集构成而非单行:
|
||||
# 零内容期每坐标恰一行 = 单元素行集;行序 = 文件序,首行即叙述取数面)
|
||||
var l2_spider_set: Array = _db.resolve_enemy_rowset(2, 4)
|
||||
var l2_spider_ids := {}
|
||||
for r in l2_spider_set:
|
||||
l2_spider_ids[String(r.get("enemy_id", ""))] = true
|
||||
check(l2_spider_ids.has("giant_spider") and l2_spider_ids.size() == 1 and l2_spider_set.size() == 1,
|
||||
"巨蜘蛛首遇行集 (2,4) = {giant_spider} 恰一行(固定 2 只——首遇教学位不加骰;行集口径断言——行集构成纪律下单行集 = 现行形态)")
|
||||
var l2_boss_set: Array = _db.resolve_enemy_rowset(2, 9)
|
||||
var l2_boss_ids := {}
|
||||
for r in l2_boss_set:
|
||||
l2_boss_ids[String(r.get("enemy_id", ""))] = true
|
||||
check(l2_boss_ids.has("drider") and l2_boss_ids.size() == 1 and String(l2_boss_set[0].get("armor_type", "")) == "ward",
|
||||
"蛛化卓尔精灵 Boss 行集 (2,9) = {drider} 恰一行且首行魔法甲(护甲类型重配批 2026-09-18:关卡 2 唯一非轻甲;商店房批重编号 (2,8)→(2,9);P4 乙 Boss 行集多行合法——零内容期仍单行)")
|
||||
# ---- 第三关内容批(2026-09-20)L3 灰矮人矿城断言段 ----
|
||||
# ⑧ L3 行集结构(复用 L2 九节点图模板——6 战 + Boss + 奖励 + 恢复,真实岔路 4 处)
|
||||
var l3 := {}
|
||||
@@ -3552,7 +3564,7 @@ func _smoke_level_graph() -> void:
|
||||
check(int(tcount3.battle) == 6 and int(tcount3.boss) == 1, "L3 普通战斗节点 = 6 + Boss 恒一(编号最大恒终点)")
|
||||
check(int(tcount3.reward) == 1 and int(tcount3.rest) == 1 and int(tcount3.shop) == 1, "L3 恢复节点 1(rest_heal_pct 行字段)+ 奖励节点 1(直通空态)+ 商店房节点 1(商店房批)")
|
||||
check(branch3 == 3, "L3 真实岔路 = %d 处(0→[1,2,3,4,5] · 2→[6,7] · 5→[6,7]——U2 返工批五岔环廊层宽 5)" % branch3)
|
||||
# ⑨ 跨表行完整:L3 每战斗/Boss 节点 (3, 编号) 在 board_gen 与 enemy 精确行(⑦ 的 bg_keys/en_keys 复用)
|
||||
# ⑨ 跨表行完整:L3 每战斗/Boss 节点 (3, 编号) 在 board_gen 与 enemy 精确行集(⑦ 的 bg_keys/en_keys 复用)
|
||||
var cross_ok3 := true
|
||||
for node in _level_active_nodes(3):
|
||||
var t3 := String(node.get("type", ""))
|
||||
@@ -3561,14 +3573,20 @@ func _smoke_level_graph() -> void:
|
||||
var key3 := "3_%d" % int(node.node_depth)
|
||||
if not bg_keys.has(key3) or not en_keys.has(key3):
|
||||
cross_ok3 = false
|
||||
check(cross_ok3, "跨表行完整:L3 全部战斗/Boss 节点在 board_gen + enemy 精确行(7 节点)")
|
||||
# ⑩ 定点:L3 首遇行集与 Boss 行集(克制面重轻错开——重甲灰矮人首次登台)
|
||||
var l3_lead: Dictionary = _db.enemy.resolve_rowset(3, 0)
|
||||
check(String(l3_lead.get("enemy_id", "")) == "duergar" and String(l3_lead.get("armor_type", "")) == "heavy",
|
||||
"灰矮人首遇行集 (3,0) = duergar(重甲首次登台——固定 1 只,首遇教学位不加骰)")
|
||||
var l3_king: Dictionary = _db.enemy.resolve_rowset(3, 9)
|
||||
check(String(l3_king.get("enemy_id", "")) == "duergar_king" and String(l3_king.get("armor_type", "")) == "heavy",
|
||||
"灰矮人石君王 Boss 行集 (3,9) = duergar_king(重甲收束「轻甲→魔法甲→重甲」教学梯度;商店房批重编号 (3,8)→(3,9))")
|
||||
check(cross_ok3, "跨表行完整:L3 全部战斗/Boss 节点在 board_gen + enemy 精确行集(7 节点)")
|
||||
# ⑩ 定点:L3 首遇行集与 Boss 行集(克制面重轻错开——重甲灰矮人首次登台;行集口径断言同 ⑦a)
|
||||
var l3_lead_set: Array = _db.resolve_enemy_rowset(3, 0)
|
||||
var l3_lead_ids := {}
|
||||
for r in l3_lead_set:
|
||||
l3_lead_ids[String(r.get("enemy_id", ""))] = true
|
||||
check(l3_lead_ids.has("duergar") and l3_lead_ids.size() == 1 and String(l3_lead_set[0].get("armor_type", "")) == "heavy",
|
||||
"灰矮人首遇行集 (3,0) = {duergar} 恰一行且首行重甲(重甲首次登台——固定 1 只,首遇教学位不加骰)")
|
||||
var l3_king_set: Array = _db.resolve_enemy_rowset(3, 9)
|
||||
var l3_king_ids := {}
|
||||
for r in l3_king_set:
|
||||
l3_king_ids[String(r.get("enemy_id", ""))] = true
|
||||
check(l3_king_ids.has("duergar_king") and l3_king_ids.size() == 1 and String(l3_king_set[0].get("armor_type", "")) == "heavy",
|
||||
"灰矮人石君王 Boss 行集 (3,9) = {duergar_king} 恰一行且首行重甲(重甲收束「轻甲→魔法甲→重甲」教学梯度;商店房批重编号 (3,8)→(3,9))")
|
||||
# ⑪ L3 成长代理档首遇绿档:模拟 GP 商店成长后的入关参数(atk_pct=200 / hp_pct=100)· 完美档多种子首遇战稳过
|
||||
# (零加成基线红档属预期——断言口径 = 成长代理档,非基线;跑法同 ⑥)
|
||||
var green3_ok := true
|
||||
@@ -3594,6 +3612,31 @@ func _smoke_level_graph() -> void:
|
||||
check(green3_ok, "L3 首遇位绿档:成长代理档口径(atk_pct=200/hp_pct=100)完美档 12 种子首遇战(节点 0 灰矮人)全胜且零踩雷")
|
||||
check(green3_min_hp > 0, "L3 首遇战胜后 HP 下探读数 %d(>0——绿档记录)" % green3_min_hp)
|
||||
|
||||
# ⑫ 混编行集运行面正反断言(2026-10-07 行集多行批——T4 组 D 新增):注入坐标 (1,5)/(1,6) =
|
||||
# L1 节点图与全部既有扫描面之外的新深度(ceil 请求命中注入行集——新 L 会被 ceil 封顶到 L3 不可用),
|
||||
# 断言后立即还原表,后续断言面零污染。R3 fail-fast 正反验证 + R6 行序运行面验证。
|
||||
var mix_row_a := {"level_index": 1, "node_depth": 5, "enemy_id": "goblin", "display_name": "地精", "unit_count": 1, "hp": 10, "atk": 2, "pool": [{"skill_id": "attack", "weight": 9}]}
|
||||
var mix_row_b := {"level_index": 1, "node_depth": 5, "enemy_id": "bugbear", "display_name": "熊地精", "unit_count": 2, "hp": 20, "atk": 3, "pool": [{"skill_id": "attack", "weight": 9}]}
|
||||
_db.enemy.rows.append(mix_row_a)
|
||||
_db.enemy.rows.append(mix_row_b)
|
||||
var mix_sys = load("res://core/unit_container.gd").new(_db)
|
||||
check(mix_sys.spawn(1, 5, int(_db.hero.max_hp)), "混编行集 spawn 受理((1,5) 双行 地精1+熊地精2——定值无区间路径,行集构成纪律放开面正向)")
|
||||
var mix_units: Array = mix_sys.all_enemies()
|
||||
check(mix_units.size() == 3, "混编实例总数 = 各行数量求和(1+2=3——行集实例总数 ≤4 守卫内)")
|
||||
check(String(mix_units[0].get("enemy_id")) == "goblin" and String(mix_units[1].get("enemy_id")) == "bugbear" and String(mix_units[2].get("enemy_id")) == "bugbear",
|
||||
"混编生成序 = 文件行序(行序即契约——地精在前熊地精在后,handle_id 跨行连续派发)")
|
||||
check(String(mix_units[0].get("display_name")) == "地精" and int(mix_units[1].get("hp")) == 20 and int(mix_units[1].get("atk")) == 3,
|
||||
"混编各行行值独立投影(display_name/hp/atk 按各自行值——同场不同种不同值)")
|
||||
_db.enemy.rows.append({"level_index": 1, "node_depth": 6, "enemy_id": "goblin", "display_name": "地精", "unit_count": 3, "hp": 10, "atk": 2, "pool": [{"skill_id": "attack", "weight": 9}]})
|
||||
_db.enemy.rows.append({"level_index": 1, "node_depth": 6, "enemy_id": "bugbear", "display_name": "熊地精", "unit_count": 3, "hp": 20, "atk": 3, "pool": [{"skill_id": "attack", "weight": 9}]})
|
||||
var over_sys = load("res://core/unit_container.gd").new(_db)
|
||||
check(not over_sys.spawn(1, 6, int(_db.hero.max_hp)), "行集实例总数守卫:两行各定值 3(总 6 > 4)spawn 被拒(行集构成纪律③——R3 fail-fast 运行面)")
|
||||
_db.enemy.rows.remove_at(_db.enemy.rows.size() - 1)
|
||||
_db.enemy.rows.remove_at(_db.enemy.rows.size() - 1)
|
||||
_db.enemy.rows.remove_at(_db.enemy.rows.size() - 1)
|
||||
_db.enemy.rows.remove_at(_db.enemy.rows.size() - 1)
|
||||
check(int(_db.enemy.rows.size()) == 19, "混编断言段注入行全量还原(表回 19 行——后续断言面零污染)")
|
||||
|
||||
|
||||
# 冒烟隔离用全新 RngService(同 master 种子——回放确定性纪律)
|
||||
func _fresh_rng(seed_val: int):
|
||||
|
||||
@@ -23,6 +23,7 @@ func _init() -> void:
|
||||
_test_shop_accessors(db)
|
||||
_test_meta_accessors(db)
|
||||
_test_manifest_dir_sync(db)
|
||||
_test_rowset_discipline()
|
||||
quit(Kit.finish("config_db_test"))
|
||||
|
||||
|
||||
@@ -56,8 +57,9 @@ func _test_progress_resolution(db) -> void:
|
||||
and int(got.get("node_depth", -99)) == int(probe_row.node_depth)
|
||||
and String(got.get("board_type", "")) == String(probe_row.get("board_type", "")))
|
||||
|
||||
# enemy 行集同通道:同 (L,D) 精确行存在(关卡节点地图 前置——battle 节点双表精确行契约)
|
||||
var en_got: Dictionary = db.resolve_enemy_rowset(int(probe_row.level_index), int(probe_row.node_depth))
|
||||
# enemy 行集同通道:同 (L,D) 行集数组非空(关卡节点地图 前置——battle 节点双表精确行集契约;
|
||||
# 2026-10-07 行集多行批 T2 机械适配——返回形态单行改行集数组,精确性断言换代随批 T4)
|
||||
var en_got: Array = db.resolve_enemy_rowset(int(probe_row.level_index), int(probe_row.node_depth))
|
||||
Kit.check("enemy 行集同坐标解析非空(双表精确行契约)", not en_got.is_empty())
|
||||
|
||||
# 深度 clamp:请求深度超最大行 → 取该关最大深度行 + 警告诊断一次(去重)
|
||||
@@ -190,3 +192,52 @@ func _test_manifest_dir_sync(db) -> void:
|
||||
if not disk_files.has(String(manifest[key])):
|
||||
synced = false
|
||||
Kit.check("TABLE_MANIFEST 与 data/tables 目录逐文件同步(无缺登/无悬登)", synced)
|
||||
|
||||
|
||||
# ---- 行集构成纪律(2026-10-07 敌人表行集多行批——EnemyTable.validate 正反验证;资源直构不碰生产表)----
|
||||
# 纪律三条(敌人系统 v0.15):①行集内 enemy_id 唯一(dup_key 既有通道)②同坐标多行文件内相邻
|
||||
# (rowset_rule——行序即契约,R6 加载期兜底)③行集实例总数 ≤4(骰后值运行面,spawn 守卫——冒烟侧验证)。
|
||||
|
||||
func _test_rowset_discipline() -> void:
|
||||
const EnemyTableScript := preload("res://data/schemas/enemy_table.gd")
|
||||
var mk_row := func(l: int, d: int, eid: String) -> Dictionary:
|
||||
return {"level_index": l, "node_depth": d, "enemy_id": eid, "display_name": eid + "名",
|
||||
"unit_count": 1, "hp": 10, "atk": 2, "pool": [{"skill_id": "attack", "weight": 9}]}
|
||||
# 正向:同坐标两行不同敌种(相邻)= 混编合法,validate 零错
|
||||
var t_mix = EnemyTableScript.new()
|
||||
t_mix.rows = [mk_row.call(1, 5, "goblin"), mk_row.call(1, 5, "bugbear")]
|
||||
var errs: Array = t_mix.validate()
|
||||
Kit.check("混编行集加载通过(同坐标两行不同敌种相邻——行集恰一敌种校验退役的正向面)", errs.is_empty())
|
||||
# 正向:Boss 坐标两行同构合法(P4 乙——Boss 行集校验同样放开,加载层无 Boss 单行硬闸)
|
||||
var t_boss = EnemyTableScript.new()
|
||||
t_boss.rows = [mk_row.call(2, 9, "drider"), mk_row.call(2, 9, "bugbear")]
|
||||
errs = t_boss.validate()
|
||||
Kit.check("Boss 坐标混编行集加载通过(P4 乙——Boss 多行合法,无硬闸)", errs.is_empty())
|
||||
# 负向:同坐标行不相邻 = rowset_rule 且报错定位到坐标(R6 行序纪律 + R3 错误类别可定位)
|
||||
var t_gap = EnemyTableScript.new()
|
||||
t_gap.rows = [mk_row.call(1, 5, "goblin"), mk_row.call(1, 9, "hobgoblin"), mk_row.call(1, 5, "bugbear")]
|
||||
errs = t_gap.validate()
|
||||
var gap_hit := false
|
||||
for e in errs:
|
||||
if String(e.get("category", "")) == "rowset_rule" and String(e.get("message", "")).contains("(1,5)"):
|
||||
gap_hit = true
|
||||
Kit.check("行序相邻校验:同坐标行被隔断报 rowset_rule 且定位坐标(R6——行序即契约加载期兜底)", gap_hit)
|
||||
# 负向:同敌种第二行仍被 dup_key 拦(键含 enemy_id——纪律①既有通道不回归)
|
||||
var t_dup = EnemyTableScript.new()
|
||||
t_dup.rows = [mk_row.call(1, 5, "goblin"), mk_row.call(1, 5, "goblin")]
|
||||
errs = t_dup.validate()
|
||||
var dup_hit := false
|
||||
for e in errs:
|
||||
if String(e.get("category", "")) == "dup_key":
|
||||
dup_hit = true
|
||||
Kit.check("行集内同敌种第二行仍被 dup_key 拦(纪律①——enemy_id 唯一)", dup_hit)
|
||||
# 负向:域校验不回归(单行 unit_count 越域仍拦——UNIT_COUNT_MAX 单种数语义下的同款域闸)
|
||||
var t_dom = EnemyTableScript.new()
|
||||
t_dom.rows = [mk_row.call(1, 5, "goblin")]
|
||||
t_dom.rows[0]["unit_count"] = 4
|
||||
errs = t_dom.validate()
|
||||
var dom_hit := false
|
||||
for e in errs:
|
||||
if String(e.get("category", "")) == "domain" and String(e.get("message", "")).contains("unit_count"):
|
||||
dom_hit = true
|
||||
Kit.check("单行数量域 [1,3] 域闸不回归(UNIT_COUNT_MAX 语义 = 单种数)", dom_hit)
|
||||
+1
-1
@@ -65,7 +65,7 @@
|
||||
| 迭代 15 | **③秘宝代码词族对齐批(2026-10-05 用户令编入本迭代)**:设计侧已完成(消歧更名批 `430419c`+`06e94b7`,26 个设计文档「魔法道具」→「**秘宝**」,同调位机制名保留不变),本批只做**代码侧对齐**、不做二次设计。内容:`aux_*`/`AuxItem*` 词族全族换词 **358 处 / 36 文件**(重灾 `adventure_runner.gd`79 / `level_runner.gd`27 / `bonus_interact_controller.gd`19 / `battle_orchestrator.gd`18 / `config_db.gd`14 / `main.gd`13),分五组落:**A 玩家可见文案(P0,5 处)**=`battle_narrator.gd:117-118` + `bonus_interact_controller.gd:76` + `hero_info_panel_view.gd:56`(槽位标题 `UiKit.label`)+ `:178`(tooltip)· B schema 与数据表(`aux_item_table.gd`/`aux_items.tres`/`aux_items.gd` 文件名+类名+`ConfigDB` 持有变量与访问器全链跟改,**须同步 Godot `.uid`/`.tscn` + `--import` 重刷类名缓存**——迭代 14.5 实证在册坑)· C 文档链接修复(含 `architecture.md` 两处既有断债顺带清偿)· D 中文注释层(**须分色**:`魔法矢`/`魔法反噬`/`魔法族`/`魔法护甲` 属敌方伤害护甲语汇🔴不动)· E 测试文件名+内部变量。**用户三项拍板**:全族彻底改(含数据表)· **断点存档键一律保留**(`bonus_aux_carry`/`aux_detail`/`aux_cleared`/`aux_cleared_last`/`aux_items` 断点数组/`attunement_charges` 共 34 处引用一字不改,破档即进度丢失)· registry 条目键 `aux_items` 不改(数据契约键)。设计事实源=`design/gdd/systems/排雷循环/秘宝.md` v0.9,任务书=`design/research/任务书-秘宝代码词族对齐批-2026-10-05.md`(T0-T9≈5.0d,**超软盒 3 日上限·知情预挂**:T7 段末闸后 L3 呈报切点不擅切;**三档降级面 G1/G2/G3 在册**〔G3 下限=仅组 A 完成〕;5 条设计契约含 5 条 🔴 停机级〔存档兼容零破坏/数值零漂移/schema 契约面零变更/零字段更名/核心层零 await〕;代拍板白名单 5 项;**C1/C2 已裁关闭·全改保一致·待裁点 0 项**)。**撞批已消解**:② 奇物批 2026-10-05 收口落库(合并 `c571af2`),并行风险解除,本批为迭代 15 唯一在途需求;**T0 须重取基线**(判式换代批 T5 读数 750/0、② 又动数据层,§1.2 的 747 为②前旧数禁沿用)并复核事实表。**✅ 裁决(用户 2026-10-05「全改保一致」)**:C1 `"aux_item"` 域串**照改**(实测连锁面收窄——`reward.tres` 已零 aux_item 数据行,池种随迭代 11 T7 退役;16 处字面量全在代码内闭合无存档依赖;唯一连锁项=`smoke_all.gd:3932` 断言须同步)· C2 `aux_items` 一名两义**拆分**(ConfigDB 持有变量+表注册键✅改 / 断点存档键+冒烟夹具🔴禁改——**「键名禁改」与「变量名禁改」是两回事**,禁改的只是落盘字面量)。新增**组 F**(分派语汇与域串 16 处),任务卡扩为 T0-T10≈5.5d。**开工门**:✅ 已无待裁点,可直接发 T0 | 卡③门:迭代 14 出口(**裁点已全决·可开工**) | 卡①已落籍(原估 0.5d);卡② ✅ 已全批落籍(2026-10-05 merge 3c6f2c9,台账 362——c571af2 文档+数据层之上的实施段全量补完);**卡③ ✅ 已全批落籍(2026-10-05,worktree m4iter15-mibao 九提交 b4b8bb3..收口笔,主区 merge --no-ff 哈希见台账/active.md 快照行;出口报告=[iter15-3-mibao-exit-report](design/qa/iter15-3-mibao-exit-report-2026-10-05.md))**:词族实数 364 处/36 文件全换尽(例外 43+2 处=存档键引号字面量+夹具,穷举在报告 §五);闸=冒烟 755/0+run_all 14/15(唯一红=②批遗留基线红 reward_overlay,对照零新增)+行为探针四件全绿+doc 三闸/熵增闸零新增+存档键六键普查零差异+MC 按 goal 令豁免(静态零漂移证明代);渲染像素五闸屏蔽挂账 07⑮;遗留=实机目检归用户(07⑮)+reward_overlay 基线红归②批处置 |
|
||||
| 迭代 16 | **UI 设计对齐批(2026-10-05 用户令:迭代 16 改编为 UI 优化需求实现,原四卡全数顺延迭代 17;美术线用户自理立规的例外面=本批只改 UI 设计代码、零美术资源改动)**:三路改进整合轴的代码侧落地——事实源=`design/research/UI预览demo三路改进整合对照-2026-10-04.md`(A 落码差异对照+OPT-A 机检+WB 变体三路整合,基线原型 v2.1)。**红线=不修改美术资源**:game/assets/art 与 artwork/ 均不动、不生新素材不重烘,只改 UI 设计代码(ui_kit 色板 token/字号档/布局纪律/对比度垫底/抖动呈现/panel_skinned 接线等)。无分歧可直接收项=对比度 7 处 FAIL 修法(血数 2.09→12.29 垫底等已复算)/站桩溢出 3.2px/4 处裸色收 ui_kit/status 图标 preload 违规/tg-* 类型色接线。**前置待裁=六分歧点**(①底色冷暖 ②棋盘格边长 32/44/45 ③字号档位 ④九宫格切片 ⑤圆角去留 ⑥图标尺寸解法,对照表 §三)+开放项(抖动范围/色板唯一来源,§五)。任务书=`design/research/任务书-UI设计对齐批-2026-10-05.md`(T0-T11≈7.25d,**超软盒 3d 预挂**,三段切分=段一 2.0d 无阻断〔T0-T4a〕/ 段二 4.0d 待裁〔T4b-T8〕/ 段三 1.0d 收口〔T9-T11〕;🔴 契约 7 条 R1-R7;无分歧收项 N1-N6 已逐处 file:line 考证;**待用户裁点 11 项**=六分歧 P1 底色冷暖/P2 棋盘格边长/P3 字号档位/P4 九宫格切片/P5 圆角去留/P6 图标尺寸解法 + 开放项 P7 色板唯一来源/P8 抖动范围/P9 §五 已决注销清单/P10 记忆态口径/P11 装饰 caption 豁免;**六分歧与开放项一律呈全备选案含淘汰依据**)。**事实校正(实查,2026-10-05)**:9 处色板漂移实测 4 已收 5 未收;`tg-*` 五族在 ui_kit 并不存在(以裸 Color8 内联于 bonus_pick_overlay/shop_overlay_view,缺第五族);panel_skinned 消费面实测 8 处+工厂 1 处;棋盘格边长=动态公式 clamp[26,46] 与 §8.1 锚点 45/36 三方互不等;手绘图标十枚 20×20 已入库,真问题转为 64×64 柜台四枚显示倍率;站桩溢出实机存在 1px 余量同型写法(standee_body.gd:476);demo 基线 md5 已再次漂移(实测 78ebbee0…)。状态=**任务书已起草(2026-10-05)+ 取向已定(2026-10-06)**:✅ P1=甲(维持暖化零改动)/ P2=丁(棋盘格边长零改动,46/45/44 不一致登记为已知偏差);✅ **其余八项取向已定**(用户采纳推荐)——**跟 demo**:P4 九宫格切片 8→16 / P7 五处色板向 demo / P10 记忆态纹理灰罩;**按条款解**:P3 字号立 FS_* 档(demo 34 处<14、54 处<16 不可跟)/ P6 图标显示档(demo 自身 0.3125× 违规)/ P8 抖动只做卡顶色带(demo 渐变+blur 违反像素纪律)/ P11 装饰 caption 12px 豁免;P5 两路同结论。**「以 demo 为准」三层优先级栈=任务书 §8.3**(①用户终裁>②冻结条款>③demo);三条结构级差异(卡片 232×352 / 商店全屏化 / 地图底栏合并)**不入本批、已登记 06 待立项**。估时 T0-T11≈**6.9d**(段一 2.15d 无阻断可发令 / 段二 3.75d / 段三 1.0d;三段同属一迭代、**只在段三末合并一次**);**拷打轮一 9 问已全部落地**(Q1 `panel_skinned` content margin clamp / Q2 不走独立样张闸改并进 T10 目检 / Q3 柜台图标统一 32px / Q4 商店补类型分族 / Q5 血数 11px 与装饰 caption 合并写一条豁免 / Q6 槽两态不新增通道 / Q7 一次合并 / Q8 已知偏差已登记 06 / Q9 demo 取值抄录表为唯一引用源)。**✅ 已全批落籍(2026-10-06 单会话,worktree g-plan2-iter16ui 分支 iter16-ui-20261005 十二提交 85ea024..T11 收口笔,主区 merge --no-ff 哈希见 active.md 快照行;出口报告=[iter16-ui-exit-report](design/qa/iter16-ui-exit-report-2026-10-06.md))**:T0-T10 全落(T10 人闸材料包=[iter16-ui-human-gate-checklist](design/qa/iter16-ui-human-gate-checklist-2026-10-06.md)——实机目检+代拍板追认八项归用户);闸=冒烟 782/0(断言数持平基线)+run_all 16 套全绿+探针五件全绿(新增 ui_contrast_probe 11 对测点+ui_struct⑥standee 断言族入默认段)+doc 三闸/熵增零新增+MC 零跑(纯呈现批——核心/数据层 diff=0 实证)+素材零触碰;T0 实机复算三处修法改向(意图徽标垫牌/槽位字深化/RAP 零改动——demo 口径在实机反向)+N4a 裸色实数 25 处/10 文件全收 ui_kit(任务书 5 处系漏记)+字号 107 位点归档 FS_* 六档;偏差八条在出口报告§汇总;遗留=06 新登记「呈现层残余 <4.5:1 文字位」一条(名行四墨/顺位徽标/RAP 反馈——批外邻接发现) | 迭代 15 出口 | 预算 T0-T11≈6.9d(三段切分)——**实际单会话一次跑完(2026-10-06)** |
|
||||
| 迭代 17 | **⓪内容数据驱动扩展批(2026-10-06 用户令插队为头卡——①-④卡顺延,其任务书与裁点状态原样保留)**:把内容效果行为从结算代码硬编码搬进数据行「订阅事件(on)+条件(when)+效果类型(do)」,通用解释器 EffectEngine 统一执行——完成后加「已有效果类型」的新专长/秘宝=纯改 `.tres` 零代码。裁决八条全落(R1 发布订阅同步 emit 确定性优先/R2 仅一个改写窗口不做拦截器链/R3 一事件多订阅+组合规则封冲突面/R4 旧 23 挂点枚举删除·2 个退化条件行/R5 现有实现全改造+06 在册只登记〔curio_roll/shop_purchase/gp_settle 三事件登记不实施〕/R6 框架先行发射点不论有无订阅者全埋/R7 一个迭代四模块垂直切一次合并/R8 术语纪律:事件=发布订阅 topic、效果类型=订阅后逻辑、组合规则=叠加规则,禁 hook/合并律等自造词)。词汇表定稿=**实施 16 事件**+效果类型 19 行 23(v1.1 扩 damage_mult/open_ticket 两型装下减半/开单现状)+组合规则 6;存档零改动;文案表值化随批(现有实现判据);luck_coin 经 reward_roll 迁移随批。任务书=`design/research/任务书-内容数据驱动扩展批-2026-10-06.md`(v1.1 2026-10-06 联审修订:level_clear 归登记不实施/对拍判据两套〔确定性复放与冒烟=逐位、MC 统计量=成型画像同带 m4iter12 口径〕/映射表五处语义修正/断言面随迁与订阅重建时机补列;T0-T7≈4.5d,零待裁点,🔴 契约 5 条含行为等价两套判据+护栏保留+确定性;停机点 S1 首流派对拍/S2 批末闸;开工门=U0) | 迭代 15 出口(已解) | T0-T7≈4.5d |**状态**:**已实施完成(2026-10-06,worktree iter17-dd 待合并)**——T1 效果引擎框架+16 发射点(7d157b3)/T2 词汇落码(225765f)/T3 专长 27 行迁移+旧挂点消亡(e28a6cb)/T4+T5 秘宝六件+令牌树收尾(a33ddaf);六闸全绿(冒烟 800 项 0 失败/单元 17 套/探针含 click/MC 二档对拍 40 局同种子逐位一致);出口报告 design/qa/iter17-datadrive-exit-report-2026-10-06.md,遗留人闸两项随报告 |
|
||||
| 迭代 17 | **①敌人表行集多行批(2026-10-05 用户令编入本迭代,纯功能与数值轴四卡之一)**:放开敌人表「同一(关卡序号 × 节点深度)行集恰一敌种」加载期校验(enemy_table.gd:108-112 考证在册),允许同场遭遇混编多种敌人——生成(unit_container spawn 行集受理)/编排(battle_orchestrator/narrator)/断言面全链接通 + GDD 结构冻结面修订先行(敌人系统.md:75/:263)。事实源=06「同深度第二敌种与精英/Boss 编码位」条剩余面(前半已由关卡节点地图 v1.0 消解);前置=技能池实施批已落籍(d3fa887)开工门已解。任务书=`design/research/任务书-敌人表行集多行批-2026-10-05.md`(**v1.1 2026-10-06 联审修订**:F7 勘误 19 行 9 敌种/P1 补遭遇骰交互〔每行一骰·RNG 扩签先报批〕与实例总数≤4 消歧/P3 改裁丙撤投放/新增契约 R6 混编行行序纪律/expect_pools 断言换代入组 D;T0-T8≈3.75d〔T5 撤投后,超软盒预挂,T4 末切分点〕;🔴 契约 6 条;**✅ 裁点全裁(2026-10-06 用户令:P1甲〔Q8/Q9 二裁补全〕/P2甲/P3丙〔Q3 二裁撤投放——一裁乙与首遇教学位纪律三面冲突〕/P4乙 Boss 行亦放开·知情代价六面在册);开工=U0**) | 迭代 15 出口 | T0-T8≈3.75d(超软盒预挂,T4 末切分点) |
|
||||
| 迭代 17 | **①敌人表行集多行批(2026-10-05 用户令编入本迭代,纯功能与数值轴四卡之一)**:放开敌人表「同一(关卡序号 × 节点深度)行集恰一敌种」加载期校验(enemy_table.gd:108-112 考证在册),允许同场遭遇混编多种敌人——生成(unit_container spawn 行集受理)/编排(battle_orchestrator/narrator)/断言面全链接通 + GDD 结构冻结面修订先行(敌人系统.md:75/:263)。事实源=06「同深度第二敌种与精英/Boss 编码位」条剩余面(前半已由关卡节点地图 v1.0 消解);前置=技能池实施批已落籍(d3fa887)开工门已解。任务书=`design/research/任务书-敌人表行集多行批-2026-10-05.md`(**v1.1 2026-10-06 联审修订**:F7 勘误 19 行 9 敌种/P1 补遭遇骰交互〔每行一骰·RNG 扩签先报批〕与实例总数≤4 消歧/P3 改裁丙撤投放/新增契约 R6 混编行行序纪律/expect_pools 断言换代入组 D;T0-T8≈3.75d〔T5 撤投后,超软盒预挂,T4 末切分点〕;🔴 契约 6 条;**✅ 裁点全裁(2026-10-06 用户令:P1甲〔Q8/Q9 二裁补全〕/P2甲/P3丙〔Q3 二裁撤投放——一裁乙与首遇教学位纪律三面冲突〕/P4乙 Boss 行亦放开·知情代价六面在册);开工=U0**) | 迭代 15 出口 | **✅ 已全批落码待人闸(2026-10-07,worktree g-plan2-iter17-enemy 分支 iter17-enemy-20261007 基点 e535436,批内提交 a0b06b4(L3 报告)/5b9cf59(甲案裁决)/18cdcb0(T0)/ab5ddad(T1)/8690230(T2)/bc73fa3(T3)/c583940(T4)+收口批;一次 L3 停机=卡⓪改前锚随 worktree 删除丢失不可恢复→用户裁甲案补采改前锚 40 局·总量 80 局明示批准;出口报告=[iter17-enemy-exit-report](design/qa/iter17-enemy-exit-report-2026-10-07.md))**:行集构成纪律三条落码(同坐标多行混编放开含 Boss 行集 P4乙+行序相邻加载校验 R6+实例总数≤4 spawn 守卫 P1甲)+floor 版解析退役全仓统走 ceil 行集数组(P2 甲,工作日志 312 销号)+spawn 行集受理逐行实例化+遭遇骰逐行各掷(Q8——单行行集消费序/次数逐位一致=零内容期随机流零变化)+断言面换代(expect_pools 三元键/双表精确行集契约/L2L3 定点行集口径)+混编正反断言十一条(冒烟六+单测五);文档=敌人系统 v0.15/难度曲线与Boss v0.24/registry/06 状态行;闸=冒烟 811/0(基线 805/0,+6 混编断言)+run_all 17 套+probe_gate 含 click 全绿+doc 三闸/熵增存量红零新增+MC 改前改后 40 局同种子全字段零差异(零漂移铁证;补采锚 L1 口径读数 off 4/20·formed 16/20 与卡⓪出口报告逐位同值=等价旁证);**人闸=实机目检四项+代拍板追认九项**(design/qa/iter17-enemy-人闸材料-2026-10-07.md。原估 T0-T8≈3.75d) |
|
||||
| 迭代 17 | **③暂停层只读入口批(2026-10-05 用户令编入本迭代)**:新增局内暂停层,承载钥石余额与解锁态(营地三柜台进度)只读查看——事实源=06「解锁界面与钥石呈现的交互形态(残余:暂停层只读入口)」条。考证在册:现行无暂停层;模态栈/设置面/调试浮窗三先例齐;UiKit 公共件(modal_shell/bcard/verb_button/徽章形制)与色板 token 单点现成;MetaProgression 只读访问器面齐全;战斗屏 GP/钥石已迁出=局内零查看入口正是本批由来。**美术红线:复用现行公共件与色板,零新素材零新色值(2026-10-05 用户立规)**。任务书=`design/research/任务书-暂停层只读入口批-2026-10-05.md`(T0-T5≈3.0d;🔴 契约 5 条含公共件单点/模态登记纪律;**✅ 裁点全裁(2026-10-06 用户令全按推荐:P1丁/P2甲/P3甲/P4甲);开工=U0**) | 迭代 15 出口 | **✅ 已全批落码待人闸(2026-10-06,worktree g-plan2-iter17-pause 分支 iter17-pause-20261006 两会话接力完成,提交 c08a901/fc9eb1e/d44fdd5+收口笔;出口报告=[iter17-pause-exit-report](design/qa/iter17-pause-exit-report-2026-10-06.md))**:暂停层本体+badge 工厂件收编(Q10 甲,营地钥石徽同步迁移观感零变化)+两屏常驻角标入口与 has_open 守卫+四探针断言(结构/点击/输入锁 case⑯/只读巡检/零动效契约/对比度对)+冒烟投影一致性 5 断言;闸=冒烟 788/0(基线 783/0)+run_all 17 套+probe_gate --click 全绿+doc 三闸零新增+MC 零跑(纯呈现零数值);存量移交=熵增闸 design/diagrams 越界(00712d5 总图批落籍漏步,主区同红)+06/07 gdd_lint 存量注记红(本批零触碰);**人闸=用户实机目检**(design/qa/iter17-pause-human-gate-checklist-2026-10-06.md,重点含排播排空副作用确认项 D2。原估 T0-T5≈3.0d 贴软盒内) |
|
||||
| 迭代 17 | **④生涯界面设计立项(2026-10-05 用户令编入本迭代;只做设计提纲不做实装)**:事实源=06「『生涯』界面——冒险中数据回看的唯一承接处」条(P-C7 裁:M9 已退役局内结算明细回看,历史数据现无承接面=用户知情裁决)。考证在册:回看退役已落码(battle_end_overlay/battle_log_view/ui_assembler 三处注记)+settlement_review_overlay.gd 遗留件在盘+跨局持久面=save v5 meta 域+recent_summaries 现役逐局留痕(cap=10,save_manager.gd SUMMARY_CAP——2026-10-06 联审勘误:原记「无历史冒险记录面」系事实错误;真实缺口=cap 扩容+用时埋点+总局数/通关局数 lifetime 计数域〔涉存档 schema〕+营地既有最近冒险清单的去留设计)。任务书形态=设计提纲版:信息架构+承载内容清单(跨局汇总/历史冒险回看/图鉴承接)+与既有界面关系+三期实装建议+待裁点,标注「实装批另行立项」。任务书=`design/research/任务书-生涯界面设计立项-2026-10-05.md`(**v1.1 2026-10-06 联审修订**:F4 改正 recent_summaries 现役/P2 甲口径重述=扩容+用时埋点/总局数通关局数标注涉 schema/营地清单去列入设计稿必答项/N 候选补「维持 10」;T0-T2≈1.25d 纯文档零测试;**✅ 裁点全裁(2026-10-06 用户令全按推荐:P0甲/P1甲/P2甲〔N 实装期定〕/P3甲/P4甲/P5甲);开工=U0**) | 迭代 15 出口 | ✅ **设计提纲已成文待用户评审(2026-10-06 卡④设计批完成,worktree iter17-career-20261006,纯文档零代码零测试)**:提纲=design/gdd/systems/跨局循环/生涯.md v0.1(范围草案——信息架构/承载内容清单/界面关系/分期建议/待裁点五节,P0-P5 已裁结论落文,新发现待裁点 P6 营地最近冒险条带去留随评审一并裁);02 根索引补行+06 状态行换代「设计提纲已成文待评审」。**人闸=用户评审提纲**;评审通过后期一/二/三实装批另行立项(不预占排期。原估 T0-T2≈1.25d 软盒内) |
|
||||
| 迭代 18 | **③武器锻造系统设计提案批(2026-10-06 用户令入迭代 18;纯文档零代码——提案源=playnote 2026-10-06)**:用户提案=攻击力提升改造为「武器锻造」——剑(普攻)锻造升级加攻击、满级附带额外效果;后续增列长枪/法杖,攻击类型分别走穿刺/魔法;护甲由轻甲起级(先只提 AC)→解锁重甲/魔法甲(基础 AC 各异、可续升、满级各带额外效果)——武器/护甲差异化。产出=系统设计提案文档(与奇物属性值提升分类/护甲克制轴/营地柜台/锻造经济边界对齐,数值框架 provisional 终值归 Alpha 收官 M4 数值批统一调整〔未排期〕),裁点呈用户裁决;实装批另行立项。06 已登记专条。任务书=`design/research/任务书-武器锻造系统设计提案批-2026-10-07.md`(提纲版 v1.0——设计裁点在提案产物内全备选呈裁,任务书零待裁点;开工=U0) | 无硬门 | T0-T2≈1.5d(一轮呈裁基线,盘问轮次扩展另计) |
|
||||
|
||||
Reference in new issue
Block a user