From 8e02dcf05b88eedfa9ae963fe17c01918b40dcf8 Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Fri, 9 Oct 2026 03:58:50 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B8=85=E7=90=86:=20design/=E5=AD=98=E9=87=8F?= =?UTF-8?q?=E8=B6=85=E6=9C=9F=E6=89=B9=E2=80=94=E2=80=94=E5=88=A086?= =?UTF-8?q?=E4=BB=B6=EF=BC=88dev=E5=9B=9B=E7=BB=8411+qa=E8=AF=81=E6=8D=AE3?= =?UTF-8?q?9=3D=E5=8F=AA=E7=95=99=E6=9C=80=E6=96=B0=E8=A7=84=E9=A6=96?= =?UTF-8?q?=E8=B7=91+research=2034=EF=BC=89+=E5=BC=95=E7=94=A8=E6=94=B9?= =?UTF-8?q?=E5=86=9917=E5=A4=84/15=E6=96=87=E4=BB=B6+doc-conventions=20?= =?UTF-8?q?=C2=A711=E6=96=B0=E5=A2=9E=E8=AF=81=E6=8D=AE=E5=8F=AA=E7=95=99?= =?UTF-8?q?=E6=9C=80=E6=96=B0=EF=BC=88v13=EF=BC=89+=E7=BE=8E=E6=9C=AF?= =?UTF-8?q?=E5=AE=A1=E8=AE=A1=E6=8A=A5=E5=91=8A=E7=95=99=E7=BD=AE=E5=91=88?= =?UTF-8?q?=E6=8A=A5=EF=BC=88=E5=B7=A5=E4=BD=9C=E6=97=A5=E5=BF=97=20413?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- active.md | 2 + cleanup_batch.py | 142 + design/art/art-bible.md | 2 +- design/art/remote-gen-prompts.md | 2 +- ...005-save-contract-and-schema-versioning.md | 4 +- .../adr-0006-board-node2d-rendering.md | 2 +- .../board-node2d-migration-plan.md | 102 - .../code-architecture-review-2026-09-13.md | 132 - .../gdd-concept-map.architecture.json | 413 - design/dev/architecture/gdd-concept-map.html | 15051 --------------- ...concept-map.visual-check.1440x900.dark.png | Bin 139422 -> 0 bytes ...oncept-map.visual-check.1440x900.light.png | Bin 149314 -> 0 bytes ...oncept-map.visual-check.2048x1320.dark.png | Bin 175372 -> 0 bytes ...ncept-map.visual-check.2048x1320.light.png | Bin 186491 -> 0 bytes .../gdd-concept-map.visual-check.html | 32 - .../gdd-concept-map.visual-check.json | 548 - .../architecture/requirements-traceability.md | 60 - design/dev/doc-conventions.md | 2 + design/gdd/06-待办清单.md | 10 +- design/gdd/07-体验验证清单.md | 4 +- design/gdd/systems/冒险循环/关卡节点地图.md | 2 +- design/gdd/systems/冒险循环/难度曲线与Boss.md | 6 +- design/gdd/systems/排雷循环/地形变异.md | 2 +- design/gdd/systems/表现与支撑/HUD框架.md | 2 +- design/gdd/ux/battle.md | 2 +- design/gdd/ux/level-map.md | 2 +- .../iter15-2-curio-exit-report-2026-10-05.md | 61 - .../iter15-3-mibao-exit-report-2026-10-05.md | 88 - design/qa/iter16-ui-exit-report-2026-10-06.md | 125 - ...er16-ui-human-gate-checklist-2026-10-06.md | 57 - .../iter17-career-exit-report-2026-10-06.md | 61 - ...iter17-datadrive-exit-report-2026-10-06.md | 71 - .../iter17-enemy-L3-改前锚丢失-2026-10-07.md | 59 - .../qa/iter17-enemy-exit-report-2026-10-07.md | 62 - design/qa/iter17-enemy-人闸材料-2026-10-07.md | 36 - .../qa/iter17-pause-exit-report-2026-10-06.md | 81 - ...7-pause-human-gate-checklist-2026-10-06.md | 64 - .../iter18-career-exit-report-2026-10-07.md | 103 - .../qa/iter18-forge-exit-report-2026-10-07.md | 72 - .../iter18-mixenc-exit-report-2026-10-07.md | 132 - .../qa/iter18-seed-exit-report-2026-10-07.md | 110 - .../iter18-treefix-exit-report-2026-10-07.md | 76 - .../qa/m1-exit-gate-checklist-2026-09-28.md | 61 - .../qa/m2-exit-gate-checklist-2026-09-28.md | 58 - ...3-iter10-clear-rate-readings-2026-10-01.md | 71 - design/qa/m3-iter5-lever-scan-2026-09-28.md | 88 - .../qa/m3-iter5-rework-readings-2026-09-29.md | 50 - design/qa/m3-iter9-9a-checklist-2026-09-30.md | 54 - .../qa/m3-iter9-exit-checklist-2026-10-03.md | 40 - ...iter9-t17-fullflow-checklist-2026-10-01.md | 246 - design/qa/m3-iter9-t18-07-audit-2026-09-30.md | 23 - design/qa/m3-iter9-t8-rulings-2026-09-30.md | 40 - .../qa/m4-iter11-exit-package-2026-10-03.md | 100 - .../qa/m4iter12-t10-batch2-exit-2026-10-04.md | 34 - .../m4iter12-t7-batch1-readings-2026-10-04.md | 35 - .../m4iter14-gvar-exit-report-2026-10-04.md | 86 - .../m4iter14-gvar-t7b-readings-2026-10-05.md | 75 - .../m4iter14-mineq-exit-report-2026-10-05.md | 77 - ...iter14-skillpool-exit-report-2026-10-05.md | 44 - .../qa/numfix-newruler-readings-2026-10-01.md | 89 - .../qa/t17-defer-probe-evidence-20261002.md | 297 - .../t19-real-playtest-readings-2026-10-02.md | 39 - design/qa/test-perf-report-2026-10-02.md | 139 - .../ui-struct-probe-exit-report-2026-10-05.md | 61 - design/qa/中间产物死亡清单-2026-10-02.md | 54 - design/registry/entities.yaml | 2 +- .../MC成本调研与规制方案-2026-10-03.md | 225 - ...®¡原型v2落码-差异对照与改动计划-2026-10-04.md | 411 - .../alpha-acceptance-battle-screen.md | 81 - .../board-tile-vocab-plan-a-2026-09-26.md | 51 - .../game-architecture-2026-10-05.html | 15087 ---------------- .../game-architecture-2026-10-05.json | 73 - ...otype-report-minesweeper-battle-concept.md | 45 - ...guelike-difficulty-benchmark-2026-10-01.md | 178 - .../research/任务书-CI预接线批-2026-10-07.md | 107 - .../任务书-UI设计对齐批-2026-10-05.md | 472 - .../任务书-内容数据驱动扩展批-2026-10-06.md | 171 - .../任务书-初始展开收窄批-2026-10-04.md | 72 - ...务书-奇物词族对齐与渠道分离批-2026-10-05.md | 247 - .../任务书-提灯载体道具批-2026-10-07.md | 184 - .../任务书-敌人表行集多行批-2026-10-05.md | 206 - .../任务书-旧界面呈现断言回补批-2026-10-07.md | 114 - .../任务书-暂停层只读入口批-2026-10-05.md | 184 - ...»»务书-武器锻造系统设计提案批-2026-10-07.md | 84 - .../任务书-混编遭遇首批投放批-2026-10-07.md | 87 - .../任务书-生涯界面实装批-2026-10-07.md | 93 - .../任务书-生涯界面设计立项-2026-10-05.md | 223 - ...¡书-种子随机化与调试浮窗升级批-2026-10-07.md | 95 - .../任务书-秘宝代码词族对齐批-2026-10-05.md | 350 - .../任务书-自动化验收补齐批-2026-10-07.md | 97 - .../双层BD体系-整合定稿-2026-10-03.md | 347 - .../research/审查-地图战斗资源-2026-10-06.md | 148 - design/research/审查-奇物-2026-10-06.md | 209 - design/research/审查-总览-2026-10-06.md | 89 - design/research/审查-秘宝-2026-10-06.md | 135 - .../研究-内容数据驱动扩展架构-2026-10-06.md | 119 - .../综合-道具变异可选项菜单-2026-10-07.md | 82 - .../调研-roguelike道具玩法变异-2026-10-07.md | 348 - .../调研-全局作用域变异设计空间-2026-10-04.md | 335 - .../调研-扫雷类游戏玩法变异-2026-10-07.md | 221 - fix_refs2.py | 15 + game/README.md | 4 +- 102 files changed, 184 insertions(+), 40450 deletions(-) create mode 100644 cleanup_batch.py delete mode 100644 design/dev/architecture/board-node2d-migration-plan.md delete mode 100644 design/dev/architecture/code-architecture-review-2026-09-13.md delete mode 100644 design/dev/architecture/gdd-concept-map.architecture.json delete mode 100644 design/dev/architecture/gdd-concept-map.html delete mode 100644 design/dev/architecture/gdd-concept-map.visual-check.1440x900.dark.png delete mode 100644 design/dev/architecture/gdd-concept-map.visual-check.1440x900.light.png delete mode 100644 design/dev/architecture/gdd-concept-map.visual-check.2048x1320.dark.png delete mode 100644 design/dev/architecture/gdd-concept-map.visual-check.2048x1320.light.png delete mode 100644 design/dev/architecture/gdd-concept-map.visual-check.html delete mode 100644 design/dev/architecture/gdd-concept-map.visual-check.json delete mode 100644 design/dev/architecture/requirements-traceability.md delete mode 100644 design/qa/iter15-2-curio-exit-report-2026-10-05.md delete mode 100644 design/qa/iter15-3-mibao-exit-report-2026-10-05.md delete mode 100644 design/qa/iter16-ui-exit-report-2026-10-06.md delete mode 100644 design/qa/iter16-ui-human-gate-checklist-2026-10-06.md delete mode 100644 design/qa/iter17-career-exit-report-2026-10-06.md delete mode 100644 design/qa/iter17-datadrive-exit-report-2026-10-06.md delete mode 100644 design/qa/iter17-enemy-L3-改前锚丢失-2026-10-07.md delete mode 100644 design/qa/iter17-enemy-exit-report-2026-10-07.md delete mode 100644 design/qa/iter17-enemy-人闸材料-2026-10-07.md delete mode 100644 design/qa/iter17-pause-exit-report-2026-10-06.md delete mode 100644 design/qa/iter17-pause-human-gate-checklist-2026-10-06.md delete mode 100644 design/qa/iter18-career-exit-report-2026-10-07.md delete mode 100644 design/qa/iter18-forge-exit-report-2026-10-07.md delete mode 100644 design/qa/iter18-mixenc-exit-report-2026-10-07.md delete mode 100644 design/qa/iter18-seed-exit-report-2026-10-07.md delete mode 100644 design/qa/iter18-treefix-exit-report-2026-10-07.md delete mode 100644 design/qa/m1-exit-gate-checklist-2026-09-28.md delete mode 100644 design/qa/m2-exit-gate-checklist-2026-09-28.md delete mode 100644 design/qa/m3-iter10-clear-rate-readings-2026-10-01.md delete mode 100644 design/qa/m3-iter5-lever-scan-2026-09-28.md delete mode 100644 design/qa/m3-iter5-rework-readings-2026-09-29.md delete mode 100644 design/qa/m3-iter9-9a-checklist-2026-09-30.md delete mode 100644 design/qa/m3-iter9-exit-checklist-2026-10-03.md delete mode 100644 design/qa/m3-iter9-t17-fullflow-checklist-2026-10-01.md delete mode 100644 design/qa/m3-iter9-t18-07-audit-2026-09-30.md delete mode 100644 design/qa/m3-iter9-t8-rulings-2026-09-30.md delete mode 100644 design/qa/m4-iter11-exit-package-2026-10-03.md delete mode 100644 design/qa/m4iter12-t10-batch2-exit-2026-10-04.md delete mode 100644 design/qa/m4iter12-t7-batch1-readings-2026-10-04.md delete mode 100644 design/qa/m4iter14-gvar-exit-report-2026-10-04.md delete mode 100644 design/qa/m4iter14-gvar-t7b-readings-2026-10-05.md delete mode 100644 design/qa/m4iter14-mineq-exit-report-2026-10-05.md delete mode 100644 design/qa/m4iter14-skillpool-exit-report-2026-10-05.md delete mode 100644 design/qa/numfix-newruler-readings-2026-10-01.md delete mode 100644 design/qa/t17-defer-probe-evidence-20261002.md delete mode 100644 design/qa/t19-real-playtest-readings-2026-10-02.md delete mode 100644 design/qa/test-perf-report-2026-10-02.md delete mode 100644 design/qa/ui-struct-probe-exit-report-2026-10-05.md delete mode 100644 design/qa/中间产物死亡清单-2026-10-02.md delete mode 100644 design/research/MC成本调研与规制方案-2026-10-03.md delete mode 100644 design/research/UI重设计原型v2落码-差异对照与改动计划-2026-10-04.md delete mode 100644 design/research/alpha-acceptance-battle-screen.md delete mode 100644 design/research/board-tile-vocab-plan-a-2026-09-26.md delete mode 100644 design/research/game-architecture-2026-10-05.html delete mode 100644 design/research/game-architecture-2026-10-05.json delete mode 100644 design/research/prototype-report-minesweeper-battle-concept.md delete mode 100644 design/research/roguelike-difficulty-benchmark-2026-10-01.md delete mode 100644 design/research/任务书-CI预接线批-2026-10-07.md delete mode 100644 design/research/任务书-UI设计对齐批-2026-10-05.md delete mode 100644 design/research/任务书-内容数据驱动扩展批-2026-10-06.md delete mode 100644 design/research/任务书-初始展开收窄批-2026-10-04.md delete mode 100644 design/research/任务书-奇物词族对齐与渠道分离批-2026-10-05.md delete mode 100644 design/research/任务书-提灯载体道具批-2026-10-07.md delete mode 100644 design/research/任务书-敌人表行集多行批-2026-10-05.md delete mode 100644 design/research/任务书-旧界面呈现断言回补批-2026-10-07.md delete mode 100644 design/research/任务书-暂停层只读入口批-2026-10-05.md delete mode 100644 design/research/任务书-武器锻造系统设计提案批-2026-10-07.md delete mode 100644 design/research/任务书-混编遭遇首批投放批-2026-10-07.md delete mode 100644 design/research/任务书-生涯界面实装批-2026-10-07.md delete mode 100644 design/research/任务书-生涯界面设计立项-2026-10-05.md delete mode 100644 design/research/任务书-种子随机化与调试浮窗升级批-2026-10-07.md delete mode 100644 design/research/任务书-秘宝代码词族对齐批-2026-10-05.md delete mode 100644 design/research/任务书-自动化验收补齐批-2026-10-07.md delete mode 100644 design/research/双层BD体系-整合定稿-2026-10-03.md delete mode 100644 design/research/审查-地图战斗资源-2026-10-06.md delete mode 100644 design/research/审查-奇物-2026-10-06.md delete mode 100644 design/research/审查-总览-2026-10-06.md delete mode 100644 design/research/审查-秘宝-2026-10-06.md delete mode 100644 design/research/研究-内容数据驱动扩展架构-2026-10-06.md delete mode 100644 design/research/综合-道具变异可选项菜单-2026-10-07.md delete mode 100644 design/research/调研-roguelike道具玩法变异-2026-10-07.md delete mode 100644 design/research/调研-全局作用域变异设计空间-2026-10-04.md delete mode 100644 design/research/调研-扫雷类游戏玩法变异-2026-10-07.md create mode 100644 fix_refs2.py diff --git a/active.md b/active.md index a8ecd1a2..ee4f28b3 100644 --- a/active.md +++ b/active.md @@ -11,6 +11,7 @@ - **工程路线图**:`production/roadmap.md`(2026-09-17 建——里程碑时间线 + 路线图;实时状态看下方快照节) ## 当前状态快照(收口批先更新本节,再追加台账;≤10 行) +- **更新于**:2026-10-09(**design/ 存量超期清理批落籍 master**,用户逐类判决——QA 新立规「证据只留最新」,工作日志 413):删 86 件=dev 四组 11(concept-map 全家/迁移计划/评审/追溯矩阵,随批清 7 文件指路句)+qa 39(证据只留最新规首跑:保留 iter19 七件+迭代18目检总清单〔待人〕+ui-audit 树与报告=最新证据)+research 33 轨迹+3 未跟踪(任务书 17/审查四/奇物调研四〔用户点名核验:18 件框架已落 GDD v3.0〕/研究三/双层BD/MC成本/基准/UI对照/第三套架构图/旧杂件);引用改写 13 文件;doc-conventions §11 新增证据只留最新行(v13);**美术审计报告留置未删**(P0① art-bible 仍引用已丢失冻结样张+P0② 主角重产未登记——严重事项呈用户,待裁后处置)。 - **更新于**:2026-10-09(**design/ 结构问题三连修落籍 master**,用户三令直批——主区直接批纯文档+doc 工具扫描列表,零测试〔非 loop 批未点名〕,工作日志 412):①案甲 design/diagrams 消灭——gdd-architecture.html/json 迁 design/dev/architecture/(json 自引用随迁改正),熵增闸子目录越界红灯清零、白名单零改动;②旧档 GDD 引用全量摘除——design/archive/gdd-2026-09-14/(9f1507dc 已删)指涉 31 处/29 文件+代码头注与 schema 头注 13 文件+registry 评审日志死指路 5 处清零(「旧版参考」死链行 25 文件/CLAUDE.md 两处/02 旧代号句改写+旧骨架索引行摘〔版本行 v1.15〕/doc-conventions §9 列项删〔v12〕/code-conventions §1.4 头注示例换代/code+schema 头注十三文件同步换代/entities.yaml 五行历史注记化);③doc_link/doc_term_audit 扫描列表摘 design/ux 死路径(7f24b640 搬迁残留)。闸=熵增闸转绿+doc 三闸基线零新增;纯删行文件不加版本行(断链修复先例,本行即记录);并行未提交落文零吞并(选择性暂存)。 - **更新于**:2026-10-07(**天赋树货币甲案修复+卡③提案S2纠偏批落籍 master 3b86c9b**,worktree g-plan2-iter18-treefix 三提交 d7a6406/30154e5/129c21c+主区 merge --no-ff 零冲突,工作日志 396;零行为变更静态批):树全钥石单币落定(2026-10-07 用户裁「按甲方案修复完」——meta_tree.tres 脊柱 16 行 gp→keystone+schema 枚举 {keystone,free}+tree_buy 直走 spend_keystone+购买钮「购买 N 钥石」+meta.tres 陈旧注释订正,T8 双币骨架披露销账);卡③提案 v1.1 货币前提全案订正(5b/5c 换代钥石口径+修订记录);主区落籍闸=冒烟 834/0+probe_gate --click 全绿;MC 零跑静态论证 - **更新于**:2026-10-07(**迭代 18 四卡全部落籍+总收口**,goal 编排会话:③ de067ae〔台账 391〕/⑤ 0dbe3c3〔392〕/⑦ b91b973〔393〕/④ b98ea83〔394〕+总条 395;Wave 1 三卡并行+④ 硬等⑦落籍后串行;主区终态=冒烟 834/0〔本迭代 811→834〕+probe_gate 全绿+layout/tune exit0):**待用户三件**=①卡③ 提案 17 裁点盘问裁决(异步;design/qa/iter18-forge-exit-report-2026-10-07.md §四)②实机目检总清单(design/qa/迭代18-实机目检总清单-2026-10-07.md:⑤四项/⑦八项/④六项)③卡⑦代拍板追认六项+卡④追认十一项;卡⑤ MC 取证顺延 Alpha 收官 M4 数值批届时另令,M4 保持 Alpha 收官位未排期待发令 @@ -917,3 +918,4 @@ 406. **迭代 19 五卡 goal 总收口(2026-10-08,编排会话)**:五卡+尾裁微批全部落籍 master(卡⓪ 9160942/卡③ 568101b/卡② rebase 后合并/卡④ stash 避让合并/卡① rebase+CLAUDE.md stash 避让合并/微批 4a35046);六项用户裁决全落(卡④行字段按推荐全收/卡②甲修复批/卡①甲清障续跑/卡⓪甲 resume 受理/卡③甲 chickensoft/裁点②甲 ui_layout 入 CI=总收口批接线);新重闸口径主区首跑全量=冒烟 846/0 三闸过+probe_gate 默认/--click/--full 七探针全绿残留 0+render_gate 全绿(shot_checker A-D 过+fx 7 帧+board L1-L3+golden 0.00%×3)+run_all 18 套全绿;doc 三闸/熵增首跑翻出存量欠账 7 件〔gdd_lint 比例 3+熵增 diagrams+奇物双死链+拔旗术语旗;经 T0 基点复测确认非本迭代新增,仅数据配置 v0.4 历史行死链系卡①删件连带=已入 doc_link_known.txt 登记〕全部登记 06 交后续批;交付=design/qa/iter19-acceptance-package-2026-10-08.md(实机目检总清单+代拍板追认单八项);stage.txt 换代 M-4 Iteration 19 Closed;worktree 卡⓪①②③④+微批全部清场;并行会话共存记录=道具批 6e05446 与秘宝.md/CLAUDE.md 在飞 WIP 经三次 stash 避让零丢失。 411. **06-待办清单存量条目清理批(2026-10-09,用户令=「已完成的东西未从待办清单删除→删除修正完」〔本会话答复制证后当场授权〕;纯文档零代码零测试;.zcode 补丁法主区落盘未提交)**:按 06 头部「事项解决后从本清单移除(2026-09-18 口径,git 历史即留痕)」删已解决未移除条目九条——①render_gate 首跑 S1 存量红三件(用户 2026-10-08 裁甲清障 a623ec3 落籍+render_gate 转绿 golden 三连跑 0.00%,条目状态行未随批换代=本批清理成因)②内容数据驱动扩展批·迭代17头卡(e535436 已并 master,状态行「待合并」滞后;遗留两项去向=dig_charge 积点模判定边界随道具退役批删行消解+主动件 kind 词族改名呈报级存 exit report 与提交说明 a33ddaf)③菜单开局未传同调装配与局外树规则(✅9160942 落籍+遗留 resume tree_rules 随尾裁微批 768e366 闭环,双重完成)④关卡开场行攻血初始表值(卡⓪②随 9160942 已落「开场行改传生效值」,状态行「待开工」滞后)⑤奇物命名统一后续(未完四件全闭=⓪curio_* 已换代 adventure.tres curio_quota_* 实测/①relic→feat 随 6812ebb/②运行层 bonus_*→curio_* 随 8e2694d/③存档键按数据契约保留系 iter15③ 在册裁决)⑥挖掘风险不等式对账破线(条目自记 2026-10-05 正式收口,残留三面已迁 registry clause3_inequality+难度曲线联动表+6 行+δ 判读随 mineq exit report)⑦同深度第二敌种与精英/Boss 编码位(iter17 卡①已实施完成;遗留首批混编已随迭代18卡⑤落表+Boss 多行第二批义务登记 07「后续内容批义务」节)⑧UI 原型 demo 结构级差异三项(自记已全部落地 2026-10-06 UI 对齐批 2ca6288 链)⑨全屏 UI 审计差距清单(自记六项已闭环+遗留已判定归各自在册条目)。去向依据=各批台账与出口报告(git 历史留痕)。**保留面披露**:呈现层残余<4.5:1 文字位维持待办(其清单系 B 区站桩名行/敌顺位徽标/RAP 反馈行等 ui_contrast 测点对面外邻接位,非尾裁微批所修 7 项);生涯界面(期二/期三+P6 待点名)/武器锻造提案(17 裁点待人盘问)/解锁界面交互形态(待人闸目检)等待裁待人条目全数保留。本笔=台账 411。 412. **design/ 结构问题三连修(2026-10-09,用户三令:①diagrams 案甲 ②旧档引用摘除 ③ux 工具路径清理;主区直接批——worktree 合并被共同脏文件阻塞,改选择性暂存只落本批改动,并行未提交落文零吞并;台账号顺延 410/411 并行占用)**:①design/diagrams/ 消灭——gdd-architecture.html/json 两件 git mv 入 design/dev/architecture/(图像白名单既有合法区),json 内部自引用路径随迁改正,熵增闸「design/ 子目录越界」存量红灯清零、两处白名单零改动;②design/archive/gdd-2026-09-14/ 引用全量摘除(目录本体 9f1507dc 已删;引用面 31 处/29 文档+代码头注 10 文件+schema 头注 3 文件+entities.yaml 5 行):「旧版参考」blockquote 死链行 25 文件整行摘、CLAUDE.md 设计入口子句+Project Layout 行两处摘、02-系统清单「旧代号」句去归档指涉+旧骨架索引参考行整行摘(版本行 v1.15)、doc-conventions §9 归档列项删(版本行 v12)、code-conventions §1.4 头注示例 design/archive/... 换代 design/gdd/systems/ 现行路径、game/core+data/schemas 十三文件头注路径同步换代(a1/a2/a3/b1/b3/d2 六映射,注释层零行为)、entities.yaml 五行评审日志死指路改历史注记;③doc_link_audit.py/doc_term_audit.py DEFAULT_DIRS 摘 design/ux 死路径(7f24b640 design/ux→gdd/ux 搬迁残留,rglob 对不存在路径静默空扫)+docstring 口径句同步。**验证**=熵增闸 1 红→0;doc_link/doc_term/gdd_lint 对基线零新增。06「文档/结构闸存量欠账」节熵增 diagrams 条销号+归属句去 diagrams 尾巴;dev/architecture 旧 concept-map 8 件与 research/qa 存量超期=审计已呈报、用户示下次再议(未动))。 +413. **design/ 存量超期清理批(2026-10-09,用户逐类判决;QA 证据新立规=「证据类只保留最新迭代/最新一轮审计版本,新证据落位后删上一份,等人工检查的清单不受限」已落 doc-conventions §11 v13)**:①dev/architecture 四组 11 件删——gdd-concept-map 全家 8(2026-09 旧架构快照零引用,新架构图用户示另行生成)/board-node2d-migration-plan(迁移完成)/code-architecture-review/requirements-traceability(挂起标记过期:待的 ADR-0006/0007 均已落地);随批清 7 文件指路句(关卡节点地图/HUD框架/battle 版本行+adr-0005 两处+adr-0006+game README)。②qa 39 件删(新规首跑)——迭代 11-18 全部出口报告/读数/检查单+m1/m2 出口单+numfix/t17/t19/test-perf/ui-struct-probe+中间产物死亡清单本体(本批即其终局);保留=iter19 七件(最新迭代证据)/迭代18-实机目检总清单(待人)/ui-audit-2026-10-06 树 40 张+ui-audit-vs-demo 报告(最新 UI 审计证据)。③research 33 轨迹+3 未跟踪删——已落籍批任务书 17(含技能池批)/道具三层审查四件(三层重设计收口)/奇物调研底稿四件(**用户点名核验通过**:18 件专长框架已落 GDD 奇物.md v3.0 正主,全局作用域调研未决项由迭代14③落地批+06 登记承接)/研究三件/双层BD整合定稿(迭代12 落码)/MC成本调研(sim-data 规制落地)/roguelike-difficulty-benchmark(带值四带已裁)/UI落码对照(落码批收官)/game-architecture html+json(第三套架构图)/alpha-acceptance+prototype-report(M3 前旧件);保留=M4数值批任务书+A4 两件(冻结)+提案-武器锻造(17 裁点未闭)+UI预览demo三路对照(阶段1待办)+自造短语全量清单(待裁)+playnote(用户手迹)。④引用改写 13 文件(06 五处/07 三处/难度曲线两处/地形变异/HUD框架两处/关卡节点地图/battle/entities.yaml/art-bible/remote-gen-prompts/adr-0005/adr-0006/README——路径指涉统一改「(已退役,git 历史可查)」行内注记,零行数变化)。**A1 美术资产链路审计报告留置未删(用户严重事项条款)**:核验结论=§07 数值单点已吸收(art-bible v3.11)/描边已吸收(character-design §5.1 v1.9+06 复核钩子),但 **P0① 未吸收**——art-bible:68/:527+art-status-checklist:13 至今仍引用已丢失冻结样张 artwork/mockups/sample-batch-v3-final-2026-09-30.png(磁盘实测零命中,圣经冻结基准死指涉),**P0② 未登记**——主角棋盘小人未走像素管线(插值糊图)重产事项无 06 条目;待用户裁决(登记 06 处置或重产后再删报告)。**验证**=doc_link/doc_term/gdd_lint 对基线零新增+熵增闸 PASS;untracked 三件(技能池任务书/研究×2)主区磁盘删不入 git。 diff --git a/cleanup_batch.py b/cleanup_batch.py new file mode 100644 index 00000000..76dbdfcf --- /dev/null +++ b/cleanup_batch.py @@ -0,0 +1,142 @@ +# -*- coding: utf-8 -*- +# design/ 存量清理批:worktree 内执行(删件+引用改写+§11新规+台账413) +import pathlib, re, subprocess, sys + +ROOT = pathlib.Path('.') # worktree 根 + +# ---------- 1) 删除清单 ---------- +DEV = [ + 'design/dev/architecture/gdd-concept-map.html', + 'design/dev/architecture/gdd-concept-map.architecture.json','design/dev/architecture/gdd-concept-map.visual-check.html', + 'design/dev/architecture/gdd-concept-map.visual-check.json','design/dev/architecture/gdd-concept-map.visual-check.1440x900.dark.png', + 'design/dev/architecture/gdd-concept-map.visual-check.1440x900.light.png','design/dev/architecture/gdd-concept-map.visual-check.2048x1320.dark.png', + 'design/dev/architecture/gdd-concept-map.visual-check.2048x1320.light.png', + 'design/dev/architecture/board-node2d-migration-plan.md','design/dev/architecture/code-architecture-review-2026-09-13.md', + 'design/dev/architecture/requirements-traceability.md', +] +QA = ['design/qa/'+n for n in [ + 'iter15-2-curio-exit-report-2026-10-05.md','iter15-3-mibao-exit-report-2026-10-05.md','iter16-ui-exit-report-2026-10-06.md', + 'iter16-ui-human-gate-checklist-2026-10-06.md','iter17-career-exit-report-2026-10-06.md','iter17-datadrive-exit-report-2026-10-06.md', + 'iter17-enemy-L3-改前锚丢失-2026-10-07.md','iter17-enemy-exit-report-2026-10-07.md','iter17-enemy-人闸材料-2026-10-07.md', + 'iter17-pause-exit-report-2026-10-06.md','iter17-pause-human-gate-checklist-2026-10-06.md','iter18-career-exit-report-2026-10-07.md', + 'iter18-forge-exit-report-2026-10-07.md','iter18-mixenc-exit-report-2026-10-07.md','iter18-seed-exit-report-2026-10-07.md', + 'iter18-treefix-exit-report-2026-10-07.md','m1-exit-gate-checklist-2026-09-28.md','m2-exit-gate-checklist-2026-09-28.md', + 'm3-iter10-clear-rate-readings-2026-10-01.md','m3-iter5-lever-scan-2026-09-28.md','m3-iter5-rework-readings-2026-09-29.md', + 'm3-iter9-9a-checklist-2026-09-30.md','m3-iter9-exit-checklist-2026-10-03.md','m3-iter9-t17-fullflow-checklist-2026-10-01.md', + 'm3-iter9-t18-07-audit-2026-09-30.md','m3-iter9-t8-rulings-2026-09-30.md','m4-iter11-exit-package-2026-10-03.md', + 'm4iter12-t10-batch2-exit-2026-10-04.md','m4iter12-t7-batch1-readings-2026-10-04.md','m4iter14-gvar-exit-report-2026-10-04.md', + 'm4iter14-gvar-t7b-readings-2026-10-05.md','m4iter14-mineq-exit-report-2026-10-05.md','m4iter14-skillpool-exit-report-2026-10-05.md', + 'numfix-newruler-readings-2026-10-01.md','t17-defer-probe-evidence-20261002.md','t19-real-playtest-readings-2026-10-02.md', + 'test-perf-report-2026-10-02.md','ui-struct-probe-exit-report-2026-10-05.md','中间产物死亡清单-2026-10-02.md', +]] +RES = ['design/research/'+n for n in [ + 'MC成本调研与规制方案-2026-10-03.md','UI重设计原型v2落码-差异对照与改动计划-2026-10-04.md','alpha-acceptance-battle-screen.md', + 'board-tile-vocab-plan-a-2026-09-26.md','game-architecture-2026-10-05.html','game-architecture-2026-10-05.json', + 'prototype-report-minesweeper-battle-concept.md','roguelike-difficulty-benchmark-2026-10-01.md', + '任务书-CI预接线批-2026-10-07.md','任务书-UI设计对齐批-2026-10-05.md','任务书-内容数据驱动扩展批-2026-10-06.md', + '任务书-初始展开收窄批-2026-10-04.md','任务书-奇物词族对齐与渠道分离批-2026-10-05.md','任务书-提灯载体道具批-2026-10-07.md', + '任务书-敌人表行集多行批-2026-10-05.md','任务书-旧界面呈现断言回补批-2026-10-07.md','任务书-暂停层只读入口批-2026-10-05.md', + '任务书-武器锻造系统设计提案批-2026-10-07.md','任务书-混编遭遇首批投放批-2026-10-07.md','任务书-生涯界面实装批-2026-10-07.md', + '任务书-生涯界面设计立项-2026-10-05.md','任务书-种子随机化与调试浮窗升级批-2026-10-07.md','任务书-秘宝代码词族对齐批-2026-10-05.md', + '任务书-自动化验收补齐批-2026-10-07.md','双层BD体系-整合定稿-2026-10-03.md', + '审查-地图战斗资源-2026-10-06.md','审查-奇物-2026-10-06.md','审查-总览-2026-10-06.md','审查-秘宝-2026-10-06.md', + '调研-roguelike道具玩法变异-2026-10-07.md','调研-全局作用域变异设计空间-2026-10-04.md','调研-扫雷类游戏玩法变异-2026-10-07.md', + '综合-道具变异可选项菜单-2026-10-07.md','研究-内容数据驱动扩展架构-2026-10-06.md', +]] +ALL = DEV + QA + RES +for f in ALL: + if (ROOT/f).exists(): + subprocess.run(['git', 'rm', '-q', f], check=True) +print('git rm ok:', len(ALL)) + +# ---------- 2) 引用改写(basename 级替换,行内零行数变化) ---------- +REWRITES = [ + ('iter16-ui-exit-report-2026-10-06.md', '迭代16出口报告(已退役,git 历史可查)'), + ('iter17-pause-human-gate-checklist-2026-10-06.md', '迭代17暂停层人闸清单(已退役,git 历史可查)'), + ('m3-iter5-lever-scan-2026-09-28.md', '迭代5杠杆扫描报告(已退役,git 历史可查)'), + ('UI重设计原型v2落码-差异对照与改动计划-2026-10-04.md', 'UI落码差异对照(已退役,git 历史可查)'), + ('任务书-UI设计对齐批-2026-10-05.md', 'UI对齐批任务书(已退役,git 历史可查)'), + ('m3-iter10-clear-rate-readings-2026-10-01.md', '迭代10通关率读数(已退役,git 历史可查)'), + ('t19-real-playtest-readings-2026-10-02.md', 'T19真人试玩读数(已退役,git 历史可查)'), + ('任务书-自动化验收补齐批-2026-10-07.md', '自动化验收补齐批任务书(已退役,git 历史可查)'), + ('roguelike-difficulty-benchmark-2026-10-01.md', '难度外部基准调研(已退役,git 历史可查)'), + ('调研-全局作用域变异设计空间-2026-10-04.md', '全局作用域设计空间调研(已退役,git 历史可查)'), + ('任务书-提灯载体道具批-2026-10-07.md', '提灯载体批任务书(已退役,git 历史可查)'), + ('board-tile-vocab-plan-a-2026-09-26.md', '高墙瓦片词表(已落码 board_world.gd 查表,文件已退役)'), + ('test-perf-report-2026-10-02.md', '性能实测报告(已退役,git 历史可查)'), + ('code-architecture-review-2026-09-13.md', '代码架构评审(已退役,git 历史可查)'), + ('requirements-traceability.md', '需求追溯矩阵(已退役,git 历史可查)'), + ('board-node2d-migration-plan.md', 'Node2D 迁移计划(已执行完毕,文件已退役)'), +] +TARGETS = [ + 'design/gdd/06-待办清单.md','design/gdd/07-体验验证清单.md', + 'design/gdd/systems/冒险循环/难度曲线与Boss.md','design/gdd/systems/排雷循环/地形变异.md', + 'design/gdd/systems/表现与支撑/HUD框架.md','design/gdd/systems/冒险循环/关卡节点地图.md','design/gdd/ux/battle.md', + 'design/registry/entities.yaml','design/art/art-bible.md','design/art/remote-gen-prompts.md', + 'design/dev/architecture/adr-0005-save-contract-and-schema-versioning.md', + 'design/dev/architecture/adr-0006-board-node2d-rendering.md','game/README.md', +] +total = 0 +for tf in TARGETS: + p = ROOT/tf; d = p.read_bytes(); orig = d; n = 0 + for basename, repl in REWRITES: + pat = re.compile(rb'[\w./\-\\]*' + re.escape(basename.encode())) + hits = pat.findall(d) + if hits: + d = pat.sub(repl.encode(), d); n += len(hits) + if d != orig: + p.write_bytes(d); total += n + print('rewrote %d ref(s) in %s' % (n, tf)) +print('ref rewrite total:', total) + +# ---------- 3) doc-conventions §11 新规 + v13 ---------- +p = ROOT/'design/dev/doc-conventions.md'; d = p.read_bytes() +if b'| v13 |' not in d: + anchor = '| 暂存地非档案库 | `design/research/` 与 `design/qa/` 是中间文档的暂存地,不是永久档案库;入此两处的文件默认按本节规则到期即死 |'.encode() + assert d.count(anchor) == 1 + i = d.find(anchor); j = d.find(b'\n', i) + nl = b'\r\n' if d[j-1:j] == b'\r' else b'\n' + row = ('| 证据只留最新(2026-10-09 用户立规) | 测试证据(出口报告/读数/截图/对比图)只保留最新一次迭代或最新一轮同类审计的版本——旧证据无参考作用,测试按状态不按历史;新证据落位后同批删除上一份;等人工检查的清单不受此限,过人闸后按本行退役 |').encode() + nl + d = d[:j+1] + row + d[j+1:] + anchor2 = '| v12 | 2026-10-09'.encode() + i2 = d.find(anchor2); assert i2 != -1 + j2 = d.find(b'\n', i2) + nl2 = b'\r\n' if d[j2-1:j2] == b'\r' else b'\n' + j2 += 1 + row2 = ('| v13 | 2026-10-09 | §11 新增「证据只留最新」行(2026-10-09 用户立规——qa 存量清理批随批落文):测试证据只保留最新迭代/最新一轮审计版本,新证据落位即删上一份;待人清单过闸后同规退役 |').encode() + nl2 + d = d[:j2] + row2 + d[j2:] + p.write_bytes(d) +print('doc-conventions ok') + +# ---------- 4) active.md:快照顶部更新行 + 台账 413 ---------- +p = ROOT/'active.md'; d = p.read_bytes() +if b'\n413. ' not in d and not d.startswith(b'413. '): + anchor = '## 当前状态快照(收口批先更新本节,再追加台账;≤10 行)'.encode() + assert d.count(anchor) == 1 + ai = d.find(anchor); aj = d.find(b'\n', ai) + 1 + top = ('- **更新于**:2026-10-09(**design/ 存量超期清理批落籍 master**,用户逐类判决——QA 新立规「证据只留最新」,工作日志 413):' + '删 86 件=dev 四组 11(concept-map 全家/迁移计划/评审/追溯矩阵,随批清 7 文件指路句)+qa 39(证据只留最新规首跑:保留 iter19 七件+迭代18目检总清单〔待人〕+ui-audit 树与报告=最新证据)+research 33 轨迹+3 未跟踪' + '(任务书 17/审查四/奇物调研四〔用户点名核验:18 件框架已落 GDD v3.0〕/研究三/双层BD/MC成本/基准/UI对照/第三套架构图/旧杂件);引用改写 13 文件;' + 'doc-conventions §11 新增证据只留最新行(v13);**美术审计报告留置未删**(P0① art-bible 仍引用已丢失冻结样张+P0② 主角重产未登记——严重事项呈用户,待裁后处置)。\n').encode() + d = d[:aj] + top + d[aj:] + lines = d.split(b'\n') + L413 = ('413. **design/ 存量超期清理批(2026-10-09,用户逐类判决;QA 证据新立规=「证据类只保留最新迭代/最新一轮审计版本,新证据落位后删上一份,等人工检查的清单不受限」已落 doc-conventions §11 v13)**:' + '①dev/architecture 四组 11 件删——gdd-concept-map 全家 8(2026-09 旧架构快照零引用,新架构图用户示另行生成)/board-node2d-migration-plan(迁移完成)/code-architecture-review/requirements-traceability(挂起标记过期:待的 ADR-0006/0007 均已落地);' + '随批清 7 文件指路句(关卡节点地图/HUD框架/battle 版本行+adr-0005 两处+adr-0006+game README)。' + '②qa 39 件删(新规首跑)——迭代 11-18 全部出口报告/读数/检查单+m1/m2 出口单+numfix/t17/t19/test-perf/ui-struct-probe+中间产物死亡清单本体(本批即其终局);' + '保留=iter19 七件(最新迭代证据)/迭代18-实机目检总清单(待人)/ui-audit-2026-10-06 树 40 张+ui-audit-vs-demo 报告(最新 UI 审计证据)。' + '③research 33 轨迹+3 未跟踪删——已落籍批任务书 17(含技能池批)/道具三层审查四件(三层重设计收口)/奇物调研底稿四件(**用户点名核验通过**:18 件专长框架已落 GDD 奇物.md v3.0 正主,全局作用域调研未决项由迭代14③落地批+06 登记承接)/研究三件/双层BD整合定稿(迭代12 落码)/MC成本调研(sim-data 规制落地)/roguelike-difficulty-benchmark(带值四带已裁)/UI落码对照(落码批收官)/game-architecture html+json(第三套架构图)/alpha-acceptance+prototype-report(M3 前旧件);' + '保留=M4数值批任务书+A4 两件(冻结)+提案-武器锻造(17 裁点未闭)+UI预览demo三路对照(阶段1待办)+自造短语全量清单(待裁)+playnote(用户手迹)。' + '④引用改写 13 文件(06 五处/07 三处/难度曲线两处/地形变异/HUD框架两处/关卡节点地图/battle/entities.yaml/art-bible/remote-gen-prompts/adr-0005/adr-0006/README——路径指涉统一改「(已退役,git 历史可查)」行内注记,零行数变化)。' + '**A1 美术资产链路审计报告留置未删(用户严重事项条款)**:核验结论=§07 数值单点已吸收(art-bible v3.11)/描边已吸收(character-design §5.1 v1.9+06 复核钩子),' + '但 **P0① 未吸收**——art-bible:68/:527+art-status-checklist:13 至今仍引用已丢失冻结样张 artwork/mockups/sample-batch-v3-final-2026-09-30.png(磁盘实测零命中,圣经冻结基准死指涉),' + '**P0② 未登记**——主角棋盘小人未走像素管线(插值糊图)重产事项无 06 条目;待用户裁决(登记 06 处置或重产后再删报告)。' + '**验证**=doc_link/doc_term/gdd_lint 对基线零新增+熵增闸 PASS;untracked 三件(技能池任务书/研究×2)主区磁盘删不入 git。').encode() + for i, ln in enumerate(lines): + if ln.startswith(b'412. '): + lines.insert(i+1, L413); break + else: + sys.exit('ledger 412 not found') + pathlib.Path('active.md').write_bytes(b'\n'.join(lines)) +print('active.md ok') +print('ALL DONE') diff --git a/design/art/art-bible.md b/design/art/art-bible.md index d5257b4c..d488d7e0 100644 --- a/design/art/art-bible.md +++ b/design/art/art-bible.md @@ -169,7 +169,7 @@ - **旗(封印印记)**:插旗动作的叙事呈现 = **封印**(玩家可见专名,术语定义见 registry terminology「封印」条;插旗动作面见《排雷玩法》)——旗 = 封印印记;封印色(§4.1,现行封印黑)与格内优先级栈位(§1.2)不变。封印特效(施印瞬间 + 印记常显形态)资产归清单 §4 演出类;旗印记纹理已落位、字形占位退役(迭代 9 卡⑬兑现;原 06 债务条目已收口移除)。←原一;P2;术语批 2026-09-25;封印紫批 2026-09-26;封印黑批 2026-09-28 - **可挖域接触带微光(交互反馈层,2026-09-25 用户拍板)**:挖掘期,英雄格周界与可挖域(概念见《排雷玩法》动作合法性节;呈现义务见《HUD框架》可挖域指示)的接触面画呼吸微光——正交邻墙=该侧整条边,斜向邻墙=共享角点+向两侧各延伸半条边;光只画英雄格(空间)一侧、不进墙格(与装饰变体零冲突,数字砖心不涉);微光=空间的灯光边界(画法口径)。色相=蓝族浅一档(§4.2 蓝条;与主角蓝框的分层归样张批);呼吸=§2.1 挖掘期唯一在动元素,减动效停格。角点为斜墙与正交墙共享、不逐格归因,逐格指认=悬停金框(呈现交互归《HUD框架》悬停指示域)。←§2.1;§4.2;P1 - **墙体**:圆角砌块堆叠,禁尖刺装饰——尖刺专属危险语义,装饰不得伪装逻辑差异。←原三 -- **高墙瓦片体系(2026-09-26 定稿,样张批追认)**:未挖格=**一整块 32×32 自含凸起岩体**(方案甲核心定义);素材语义名——未开格素材=**墙瓦片**,已开格素材=**地面瓦片**(术语 2026-09-26 用户立)。**边界=墨线纪律**:墙瓦片与相邻格分界一律 1px 深墨线、直线贴格边、零锯齿;墨线职责=分隔,不追求与地面融合(Tiny Dungeon 样图实证调研后否决出局——TD 拼块套不进方案甲自含岩体定义,2026-09-25 终局维持方案甲;记录=git 提交 70d2320)。**光照=单一北受光**:北缘=墨线内侧 1px 微亮棱(就地取色提亮,禁宽亮带);西/东缘=墨线后直进纹理、不加修饰;南缘=墨线+立面窄暗条(约 1/3 格高,横层理叠石、禁竖条纹栅栏感)。**凹角**:角点单像素落线;南立面侧凹角加 1px 立面收头——带身与转角竖线同列收尾,禁悬空、禁突出(v9.1/v9.2 两版返工实证)。现行定稿=`game/assets/art/board/terrain_*`(16 唯一墙瓦片+5 地面瓦片变体;词表与查表逻辑见 `design/research/board-tile-vocab-plan-a-2026-09-26.md`)。**高墙感 D 投影档+整板悬崖(样张 v2 定稿 2026-09-28,用户 2026-09-27 四变体挑档)**:南临空墙格=立面口沿高光 2px `Color8(196,172,132)`+双段暗带(0.16/0.25 格边,黑罩 α0.60/0.82);北邻墙地面格=三段渐隐投影(顶带 0.22 格边,α0.28 起);整板悬崖=板底/右侧 `DEPTH_PX 8px` 暗面+列分隔竖缝+岩层横纹+口沿高光+接触 AO+底线收边+悬浮影(游戏 `board_world.gd` 同款结构件,样张脚本与游戏渲染常量同源——机检 F7 承载)。←原三;台账 164;样张 v2 批 2026-09-28 +- **高墙瓦片体系(2026-09-26 定稿,样张批追认)**:未挖格=**一整块 32×32 自含凸起岩体**(方案甲核心定义);素材语义名——未开格素材=**墙瓦片**,已开格素材=**地面瓦片**(术语 2026-09-26 用户立)。**边界=墨线纪律**:墙瓦片与相邻格分界一律 1px 深墨线、直线贴格边、零锯齿;墨线职责=分隔,不追求与地面融合(Tiny Dungeon 样图实证调研后否决出局——TD 拼块套不进方案甲自含岩体定义,2026-09-25 终局维持方案甲;记录=git 提交 70d2320)。**光照=单一北受光**:北缘=墨线内侧 1px 微亮棱(就地取色提亮,禁宽亮带);西/东缘=墨线后直进纹理、不加修饰;南缘=墨线+立面窄暗条(约 1/3 格高,横层理叠石、禁竖条纹栅栏感)。**凹角**:角点单像素落线;南立面侧凹角加 1px 立面收头——带身与转角竖线同列收尾,禁悬空、禁突出(v9.1/v9.2 两版返工实证)。现行定稿=`game/assets/art/board/terrain_*`(16 唯一墙瓦片+5 地面瓦片变体;词表与查表逻辑见 `高墙瓦片词表(已落码 board_world.gd 查表,文件已退役)`)。**高墙感 D 投影档+整板悬崖(样张 v2 定稿 2026-09-28,用户 2026-09-27 四变体挑档)**:南临空墙格=立面口沿高光 2px `Color8(196,172,132)`+双段暗带(0.16/0.25 格边,黑罩 α0.60/0.82);北邻墙地面格=三段渐隐投影(顶带 0.22 格边,α0.28 起);整板悬崖=板底/右侧 `DEPTH_PX 8px` 暗面+列分隔竖缝+岩层横纹+口沿高光+接触 AO+底线收边+悬浮影(游戏 `board_world.gd` 同款结构件,样张脚本与游戏渲染常量同源——机检 F7 承载)。←原三;台账 164;样张 v2 批 2026-09-28 - **变异格形状通道**(双通道之"形",与色无关):底砖圆角外轮廓不变,砖面内缘绘一圈定宽专属几何纹带(纹带形全作不与他类共用),砖心留白予数字与旗;验收标准=**灰度截图下仍可分类**。种类清单 = 地形变异六类型已定稿(地形变异 GDD;荆棘丛/藤蔓缠绕/岩浆/烬覆/落石/矿尘):**纹带形按轴只分两种**——伤害轴(荆棘丛/岩浆/落石)= 刺/缺排斥形,信息轴(藤蔓缠绕/烬覆/矿尘)= 遮蔽/缠绕形;同轴跨图类型只做色板变体(§4.3 `variant_tint` 槽),不做新纹形。样张批增查:岩浆纹带橙红须与危险红互辨(变异格不是雷,色相邻近混淆风险);信息轴遮蔽呈现不得侵入数字字形占位区(§1.4 验收 1 延伸)。←原一(纹理位次第 4,让位于数字/小人/旗);原三 ### 3.3 UI 形状语法(方向指导,细则迁 §7.1) diff --git a/design/art/remote-gen-prompts.md b/design/art/remote-gen-prompts.md index 1cf7bf1c..aaad339d 100644 --- a/design/art/remote-gen-prompts.md +++ b/design/art/remote-gen-prompts.md @@ -81,7 +81,7 @@ Pixel art style. true pixel art game sprite drawn on a tiny 48x72 pixel canvas, **制式 = 拼表制正主(2026-10-06 用户拍板)——三步流程**: 1. **程序占位出样图**:现行程序化格面(占位在役)截一张作参考样图; 2. **整图生成**:开新对话,贴样图 + 发下方整段,一张 2×2 出全部瓦片变体(风格统一、一张管全族); -3. **裁切取用**:按 50% 坐标切图、每格内缩 2–3% 切掉可能的边框 → 统一降采样 → 成片瓦片 21 枚由程序从切出的材质合成(词表:design/research/board-tile-vocab-plan-a-2026-09-26.md)。 +3. **裁切取用**:按 50% 坐标切图、每格内缩 2–3% 切掉可能的边框 → 统一降采样 → 成片瓦片 21 枚由程序从切出的材质合成(词表:高墙瓦片词表(已落码 board_world.gd 查表,文件已退役))。 ``` Seamless tileable pixel art texture sheet for a dungeon board game, arranged as a clean 2x2 grid of four equal square quadrants filling the entire image edge to edge, with no gaps, no dividing lines, no borders, no frames, no grid lines, no labels and no text. Top-left quadrant: warm tan rock surface with subtle darker seams between stone patches and small lighter facets. Top-right quadrant: the same warm tan rock surface but with a few thin darker crack lines scattered across it. Bottom-left quadrant: the same warm tan rock surface but with a few tiny lighter stone speckles sparsely scattered. Bottom-right quadrant: dry dirt ground in a dark warm brown palette around #B39A78, clearly darker than the tan rock, with a few thin cracks and tiny pebble speckles, sparse. Every quadrant is a flat 2D top-down texture — not an object, no perspective — and each quadrant must wrap seamlessly at its own four edges. Uniform directionless lighting across all four quadrants, no vignette, no cast shadow, no bevel, no edge highlight anywhere. Warm tan-brown palette around #C9AF83 for the three rock quadrants. Clean retro pixel art look, limited palette, no gradients, no text, square image. diff --git a/design/dev/architecture/adr-0005-save-contract-and-schema-versioning.md b/design/dev/architecture/adr-0005-save-contract-and-schema-versioning.md index 7889ee5f..09672b47 100644 --- a/design/dev/architecture/adr-0005-save-contract-and-schema-versioning.md +++ b/design/dev/architecture/adr-0005-save-contract-and-schema-versioning.md @@ -24,7 +24,7 @@ Accepted(2026-09-12,solo 模式用户授权代决;轻量契约 ADR—— | **Depends On** | None | | **Enables** | D3 存档序列化(Alpha)——契约先行,实现期免重议 | | **Blocks** | None | -| **Ordering Note** | 清零 Foundation 层 TR 覆盖缺口(requirements-traceability.md 的最后两条 pending) | +| **Ordering Note** | 清零 Foundation 层 TR 覆盖缺口(需求追溯矩阵(已退役,git 历史可查) 的最后两条 pending) | ## Context @@ -101,4 +101,4 @@ Technical Setup → Pre-Production 门要求"Foundation 层需求 ADR 覆盖零 ## Related Decisions - ADR-0001(回放输入序列的载体)、ADR-0004(集成测试载体) -- docs/architecture/requirements-traceability.md(TR-d2-010 / TR-gc-002 覆盖闭合) +- 需求追溯矩阵(已退役,git 历史可查)(TR-d2-010 / TR-gc-002 覆盖闭合) diff --git a/design/dev/architecture/adr-0006-board-node2d-rendering.md b/design/dev/architecture/adr-0006-board-node2d-rendering.md index 7cb24d1a..4fb6fe1e 100644 --- a/design/dev/architecture/adr-0006-board-node2d-rendering.md +++ b/design/dev/architecture/adr-0006-board-node2d-rendering.md @@ -126,7 +126,7 @@ Phase B 届时将 BattleStageView 同构改造(PanelContainer → Control 壳 - 输入路径改 `_gui_input` 后现探针全走 `click_cell` 直调,公式换算无自动化覆盖 → 缓解:实施批增补 push_input 端到端输入探针(ADR-0003 已登记项,本批转义务) ## Migration Plan -Phase A(棋盘,实施另批):BoardView 内部重构 + 探针增补 + 冒烟全量回归 + 文档随批(HUD框架渲染注记/battle.md 实现注记/architecture.md 模块归属行)。Phase B(B 区舞台,后续批):同构复制 + 站桩精灵迁移 + 意图动画承载;开工前置 = 样张批冻结剪影与动画方案。战斗屏进度条退场的 GDD 修订面(HUD框架 四区表、关卡节点地图 节点链常显条款、battle.md 像素布局表与 28px 纵向空间再分配)随停点前移批(关卡画面成为常驻枢纽)落地,不随本批。工程细节见同目录 `board-node2d-migration-plan.md`。 +Phase A(棋盘,实施另批):BoardView 内部重构 + 探针增补 + 冒烟全量回归 + 文档随批(HUD框架渲染注记/battle.md 实现注记/architecture.md 模块归属行)。Phase B(B 区舞台,后续批):同构复制 + 站桩精灵迁移 + 意图动画承载;开工前置 = 样张批冻结剪影与动画方案。战斗屏进度条退场的 GDD 修订面(HUD框架 四区表、关卡节点地图 节点链常显条款、battle.md 像素布局表与 28px 纵向空间再分配)随停点前移批(关卡画面成为常驻枢纽)落地,不随本批。工程细节见同目录 `Node2D 迁移计划(已执行完毕,文件已退役)`。 ## Validation Criteria - 冒烟全量绿(现行基线不破);三探针(ui / ui_click / ui_layout)绿 diff --git a/design/dev/architecture/board-node2d-migration-plan.md b/design/dev/architecture/board-node2d-migration-plan.md deleted file mode 100644 index 0bc21664..00000000 --- a/design/dev/architecture/board-node2d-migration-plan.md +++ /dev/null @@ -1,102 +0,0 @@ -# 战斗棋盘 Node2D 渲染迁移方案(Phase A:仅棋盘) - -> 状态:**草稿待审**(2026-09-23 起草,board-node2d-plan-20260923 worktree)。 -> 上位裁决:ADR-0006(分工与形态)、用户 2026-09-23 拍板「Node2D 重构只迁战斗棋盘,开始菜单/各覆盖层保持 Control;战斗画面 Node 后续批完成」。 -> 本文档是 Phase A 实施批的工程方案;批准后实施批从本文开工,不再另起炉灶。 - -## 0. 一句话 - -把 D 区棋盘本体从「GridContainer + 逐格 Button」换成「Control 壳 + SubViewport + Node2D 世界」,BoardView 类名与公共面契约逐项保持——探针与组合根零改造,素材终稿到位后 1:1 换图零返工。 - -## 1. 目标形态(已与用户确认的三块模型) - -战斗屏 = 两块 Node2D 舞台 + 一层 Control 面板。术语校准:Godot 没有「Canvas」节点——面板层是 Control 树(常驻顶层与弹层经 CanvasLayer,现状已如此);Node2D 不参与 Control 容器布局,所以每块舞台包一个 Control 壳(SubViewportContainer)参与屏幕栅格布局,壳内才是 Node2D 世界。 - -``` -BattleScreen(Control 栅格;目标形态 = B/C/D 三区——进度条退场裁定见下) -├── B 战斗画面(Phase B 改造,本批不动) -│ ├── Node2D 舞台壳:主角/敌人站桩、意图动画、演出(后续批) -│ └── Control 半区:结算明细带、回合指示、战斗日志(永久 Control) -├── C 角色信息 .................. Control(不动) -└── D 扫雷图 - ├── AP 条、按钮组、toast .... Control(不动) - └── BoardView(本批改造对象) - └── SubViewportContainer(Control 壳,参与布局) - └── SubViewport(逻辑分辨率 = 格边长 × 板尺寸) - └── BoardWorld(Node2D) - └── CellUnit × N(Node2D,每格一个) -``` - -**进度条退场裁定(2026-09-23 用户)**:战斗画面不再有关卡进度条——战斗结束后返回关卡画面,节点链进度只留关卡画面。 - -**A 区代码命运(2026-09-23 追问裁定):退役,不迁移。关卡画面不重新实现。** - -- **关卡画面 = RouteOverlay 升级**:现役选路覆盖层已是整幅节点图 + 全套节点态语义(暗金已过/金当前/暗未达/亮金候选通道/紫赤 Boss 边(旗朱→紫赤 2026-09-26 封印紫批),与压缩条同一组 UiKit token)+ 候选按钮 + 放弃入口。停点前移批只改开合时机(关卡开始即开、战后返回即开)与流程接线(选路确认不再经兑付停点绕行),渲染本体零重写。 -- **LevelStripView 不迁移的理由**:它唯一的存在理由 = 战斗屏上看不到整图时的 28px 压缩常显替代面。地图页上压缩条冗余(整图即进度),战斗屏又已裁定零进度显示——迁过去没有消费者。其语义无独有资产(色板/节点态与 RouteOverlay 同族),单链退化渲染(全链横条)被整图布局天然取代。 -- **唯一继承面 = 逻辑层数据面**:runner 只读出口(`nodes()` / `visited_ids()` / 节点编号空间 / `next_candidates()`)零改动——压缩条与整图本来就消费同一份数据,这正是"退役不迁移"成立的根据。 - -排程事实与修订面: - -1. **A 区现状代码继续服役**:当前流程尚未倒置(冒险开局直进战斗,节点图是战后弹层),A 区顶栏是战斗过程中唯一的节点链可视面——先删会致盲。退场落地 = 停点前移批,届时四区→三区。 -2. **停点前移批的删除面清单**(退役随该批执行):`LevelStripView` 类、ui_assembler 组装行(:28)、main.gd `strip_view` 引用(:52 等)、ui_probe 两处断言(:77–78 节点条构建检查、:188 报告行)、battle.md A 区条款。 -3. **该批的 GDD 修订面**:HUD框架.md 四区结构表(含 B/C/D 是否重新编字母)、关卡节点地图.md 节点链常显条款(常显载体随进度条退役,由关卡画面本体承接)、battle.md 像素布局表(28px 纵向空间再分配)。 - -## 2. Phase A 范围(本批做) - -1. **BoardView 内部重构**(`presentation/views/board_view.gd`): - - 根仍是 Control(类名/extends 不变),子结构 GridContainer → SubViewportContainer + SubViewport + BoardWorld。 - - `_cells`:Vector2i → CellUnit(Node2D)字典,键面与现 Dict 同构(探针断言面,见 §4)。 - - CellUnit 内部固定叠层序:砖面底 < 变异纹带 < 数字/徽章 < 旗 < 焦点高亮——本批全程序化绘制(`_draw`),等价平移现行视觉;每个叠层留 `texture` 槽位(§8.2 暂定档 32×32),终稿纹理换入即用。 - - 现有行为逐项平移:呼吸微光(StyleBoxFlat 边框 → `_draw` 边框)、悬停反白、路径预览、危险红、双击 chord 检测、`set_desaturated`(ShaderMaterial 挂 BoardWorld 材质)。 -2. **输入换板**:BoardView 壳层 `_gui_input` 接鼠标 → 格坐标单点公式 `floor(local_pos / cell_edge)` → 复用现有 hover/click/chord/长按逻辑;`action_requested` 信号链不变。 -3. **`cell_size` 只读属性增补**:现私有名 `_cell`,ui_layout_probe `get("cell_size")` 读到 null——补只读属性,顺手修正。 -4. **push_input 端到端输入探针**(新增,ADR-0003 登记项转义务):合成鼠标事件经真实输入路径打 SubViewportContainer,验悬停/左键/右键/chord 四 case——现探针全走 `click_cell` 直调,公式换算无覆盖,这是唯一新增自动化面。 -5. **冒烟全量回归 + 文档随批**:HUD框架.md 渲染技术注记(v0.x 版本行)、battle.md 实现注记(格尺寸公式锚点不动)、architecture.md BoardView 形态行、ui_kit 同步面清点。 - -**不做**(明确出批):B 区舞台任何改动;素材终稿接入;格边长数值调整(归样张批);键盘寻格/无障碍(沿 ADR-0003 已接受口径)。 - -## 3. Phase B(2026-09-26 已落地——战斗舞台 Node2D 迁移批,台账 170-173) - -- BattleStageView 同构改造**已实施**:PanelContainer → Control 壳(类名/252px/树内位置不变)+ Node2D 舞台半区(SubViewportContainer/SubViewport/StageWorld)+ Control 文本半区(round_label/stage_center/log_view 三件保留);站桩 StandeeView(Control)退役删除,本体 = StandeeBody(Node2D 世界精灵,行为面 17 方法契约保持);slot_row+悬停 tooltip 保留 Control 载体挂壳层(伴随件容器 = enemy_box 语义改写)。 -- Phase A 交付的两挂点已被 Phase B 复用:set_world_font 字体显式注入(C6 判据=注入非空+has_char+宽度>0)与坐标空间分界纪律(世界=局部排布,壳层换算单点 world_to_shell)。 -- **样张硬前置改判(用户 2026-09-26 裁决①)**:样张批冻结只卡换皮/演出批(循环 2 前置),不卡结构迁移——本节原「Phase B 开工硬前置 = 样张批冻结」条款据此作废;ADR-0006「只卡换皮不卡开工」原则的落文位。 - -## 4. 探针与测量面(实证清单) - -| 探针/工具 | 耦合点(实证) | Phase A 处置 | -|---|---|---| -| ui_probe | `board_view._cells.is_empty()`(:73)、`_cells.size()` 对板宽高(:187)、`board()`/`set_desaturated()` | `_cells` 键面同构即绿,零改 | -| ui_click_probe | `click_cell(cell, button)` 直调(:257–277)、`_cells.is_empty()`(:97);**无合成鼠标事件**(grep parse_input_event/push_input 零命中) | 公共方法保留即绿,零改 | -| ui_layout_probe | `get("cell_size")`(:39,现读 null)、`board()` | 增补只读属性(§2.3) | -| smoke 行协议同步闸 | 战斗日志 9 类行格式化(smoke_all.gd:3325+)——**是日志行不是棋盘** | 零影响,全量回归覆盖 | -| MC / 模拟试玩 / verifier | core/ 逻辑层 | 零接触零影响 | - -## 5. 性能与预算 - -- draw calls:CellUnit 同材质 `_draw` 走 2D 批处理,144 格占位态预计个位数批次;预算 < 200 维持(HUD框架 引用值),实施批用 RenderingServer 实测数回填。 -- 进入战斗屏 500ms 可交互:SubViewport 创建在 `_ready` 一次完成,无逐帧重建;`set_cell_area`/`rebuild` 只重排子节点。 -- SubViewport 逻辑分辨率 = 格边长 × 板尺寸(≤ 36px × 14 格量级),渲染目标显存占用可忽略;低端机帧预算实施批实测。 - -## 6. 风险与对策 - -| 风险 | 对策 | -|---|---| -| SubViewport 内 Label 不继承主场景主题(数字/中文渲染空白或字体错) | 实施批第一小步先做 theme/字体显式注入挂点并用 CJK 冒烟验证——ADR-0006 Verification Required 项 | -| 45/36px 锚点 × 32px 格源非整倍缩放出现像素纹路 | 架构只保证 `set_cell_area` 单点可调;数值归样张批(圣经 §8.2 v1.9 注记①路线),本批不裁决 | -| `_gui_input` 与 toast/AP 条控件输入抢占 | D 区内部布局不变(Control 兄弟件照旧),棋盘壳是叶节点,抢占面与现 GridContainer 相同;探针四 case 覆盖 | -| 改造期行为漂移(呼吸微光/chord 时序等隐性手感) | 功能等价清单(ADR-0006 Validation)逐项人工核对 + 探针自动化面 | - -## 7. 排期与依赖 - -| 项 | 估时 | 依赖 | -|---|---|---| -| 本起草批(ADR-0006 + 本方案 + ADR-0003 注记) | 已完成,待审 | 无 | -| Phase A 实施批 | 1–2 天(含探针增补 + 冒烟回归 + 文档随批) | 本方案批准 | -| 样张批(素材侧,另线) | 未排 | 主角候选表态 + 复用批审阅 | -| Phase B 实施批 | 未排(同构复制,估时随 Phase A 实测修正) | Phase A 落地 + 样张批冻结 | - -与在飞批的关系:曲线调参双刀扫描(worktree hp-bonus-scan-20260923)与本批文件集零交集;UI 复用候选审阅是素材侧独立线,互不阻塞。 - -## 8. 验收(实施批完成定义) - -ADR-0006 Validation Criteria 全项:冒烟全量绿 + 三探针绿 + 新增 push_input 探针绿 + 功能等价清单逐项可验 + draw calls < 200 实测回填 + 两档分辨率装板校验(12×12 与 10×10 各验)。 diff --git a/design/dev/architecture/code-architecture-review-2026-09-13.md b/design/dev/architecture/code-architecture-review-2026-09-13.md deleted file mode 100644 index 69555a2b..00000000 --- a/design/dev/architecture/code-architecture-review-2026-09-13.md +++ /dev/null @@ -1,132 +0,0 @@ -# 代码架构审查报告 — 代码组织与封装 - -> 日期:2026-09-13 -> 载体:`game/`(9707 行 GDScript:core 12 文件 / data 11 / presentation 28 / smoke 10) -> 基线:`docs/architecture/architecture.md` v1.0 + ADR-0001~0005 + `docs/code-conventions.md` -> 触发:用户在 code-review 之后要求补充「代码组织问题 + 封装问题」专项审查 -> 审查方式:core/presentation 关键文件全读 + S1–S8 静态规则逐条 grep 验证 + 跨层引用面扫描 -> -> **Verdict: CONCERNS** — 分层纪律实测扎实(S1–S7 零违例、仅 2 处已登记例外),但封装收口存在 -> 一条系统性欠账:核心模块内部状态以公有字段暴露,呈现层已形成链式穿透的既成事实。 -> 原型期无害;是 ADR-0009「切片机制正式化批」应收口的主题。 - ---- - -## 1. 正面观察(实测合规项) - -| 规则 | 结论 | 证据 | -|---|---|---| -| S1/S2 零随机 | ✅ | core 内唯一 `RandomNumberGenerator.new` 在 rng_service.gd:76(所有者本体);`stream.randf()`(reward_supply_controller.gd:32)取号经 B4 注入封闭流 | -| S3 零表加载 | ✅ | core 内唯一 `load()` 在 config_db.gd:81(单点本体) | -| S4 core 零 UI | ✅ | core/ 无 Control/Node2D/.tscn 引用(grep 命中均为 `RewardSupplyController` 类名误报与注释) | -| S5 零裸引用 autoload | ✅ | core/ 内 ConfigDB/RngService 命中均为日志前缀字符串 | -| S6 core↔core 方法 Callable | ✅ | level_runner.gd:130-134 全部方法转发;lambda 仅用于 sort_custom(不捕获 self) | -| S7 编排唯一性 | ✅ | B2/B3/B4 调用面 core 内收口于 battle_orchestrator.gd;仅 level_runner.gd:112(grant_node_active,已登记接口漂移)与 :168(in_stock_count 只读)两处例外 | -| 呈现层零核心引用 | ✅ | 28 个视图/装配器文件中仅 main.gd(组合根)与 hud_presenter.gd(授权翻译点)触 core | -| 封装典范 | — | status_container / reward_supply_controller / b4.query_inventory():私有状态 + 投影查询 + 授予时快照;battle_orchestrator.diagnostic_snapshot()(:660)为「成文只读出口」正确先例 | - ---- - -## 2. 封装问题(按根因 → 表征排序) - -### E1(根因)编排器协作对象全公开,呈现层链式穿透已成既成事实 — P1 - -- **位置**:core/battle_orchestrator.gd:20-27(`var a1/a2/a3/b2/b3/b4` 全公有) -- **表征**:`b1.a2.board`、`b1.b2.hero.hp`、`b1.a3.phase` 式层层下钻——main.gd 18 处、hud_presenter.gd 15 处。 -- **影响**:组合根与 presenter 是授权翻译点,但访问形态是「恰好字段公开」而非「B1 提供成文读取面」。 - S7 只能做文件级扫描(防另写调用方),防不了呈现层意外调用写 API,也防不了读取路径随重构漂移。 -- **建议**:B1 补聚合呈现快照/查询面(`hud_state()` 一类,先例 = `diagnostic_snapshot()`); - a2–b4 下划线化后经命名代理暴露只读操作。 - -### E2(表征)视图绕过 A2 查询面直读原始状态字典 — P1 - -- **位置**:core/minesweeper_rules.gd:18-20(`board/revealed/flags` 公开可变); - presentation/views/board_view.gd:278、:303 直接 `_a2.revealed.get(c, {})` -- **矛盾点**:board_view.gd:7 头注自称「只读 A2 查询面」——直读 `.revealed` 恰是绕过查询面。 - B1 自身亦直读(battle_orchestrator.gd:565-569 `a2.board.width/height`)。 -- **建议**:`revealed/flags` 私有化;补 `reveal_record(c) -> Dictionary`、`board_dimensions()` 查询面。 - 调用点仅 B1 + board_view + main 三处,成本很低。 - -### E3(表征)B2 裸字典句柄跨模块传递,API 缺「含死亡残位」查询面 — P2 - -- **位置**:core/unit_container.gd:13-14(`hero/enemies` 公开;句柄 = Dictionary 本体,任何持有者可 - `u.hp = 999` 绕过 apply_damage) -- **现症**:hud_presenter.gd:78-79 为渲染死亡残位直读 `b1.b2.enemies` 原始数组—— - B2 的 `query_alive` 不含死亡单位,API 缺口迫使呈现层越界(B2 头注已登记此痛点)。 -- **建议**:短期补 `query_all_units()` 投影面把 presenter 需求收进 API; - 正式化(ADR-0007 两 face 归属裁决时)再决定是否升级 Unit 类型。 - -### E4 `db.hero` 表值运行时改写——测试覆盖通道用共享可变单例传参 — P2 - -- **位置**:presentation/main.gd:327-329、core/level_runner.gd:60-61,75-76 直接写 `db.hero.atk/max_hp`; - B2.spawn 经读表间接获得加成值 -- **前科**:双写叠加 6→18→54 教训、双基线同步义务(main.gd:187-189 注释)——纪律已成文但机制脆弱。 -- **建议**:切片保留;将「运行时表可变」登记进 ADR-0009 候选;正式化改参数传递(`spawn(atk_override=...)`)。 - -### E5 「只读」字段仅靠纪律,无机制约束 — P2 - -- **位置**:core/action_economy.gd:17-20(`phase/ap/rap/last_round_end` 架构文档定义为只读,实际公开可变); - core/rng_service.gd:19(`master_seed` 可绕过 set_master_seed 的计数器全零断言) -- **现状**:当前调用方全部合规(A2 经 try_spend/request_dig,B1 经 notify_*,呈现层只读)。 -- **建议**:下划线化 + 查询方法(`phase()/ap()/rap()`),趁调用方少时收口,成本极低。 - -### E6 小项 — P3 - -| 项 | 位置 | 说明 | -|---|---|---| -| 返回类型多态 | core/reward_economy.gd(grant/stock/use 失败返 `false`,query_* 返 `null`) | B1 消费处被迫 `if not (snap is Dictionary)`;统一 `null` 更符合 GDScript 惯例 | -| 泄漏原始表行 | core/reward_economy.gd:256-265 `equivalence_supply` 返回 `db.reward.rows` 行引用(可变) | 工具观测面,建议 `duplicate()` | -| BoardData 全公开 | core/board_data.gd:8-18「生成后不可变」仅靠注释;视图持板即可读全部雷位(当前未作弊) | 正式化时 duplicate 冻结或下划线化 + 访问器 | -| 成员声明位置 | core/action_economy.gd:121 `var _next_round_mode` 声明在中部、使用在前 | 集中到顶部 | - ---- - -## 3. 代码组织问题 - -### O1 main.gd 回涨至 667 行,再越 ~400 行审视线(规范 1.1)— P1 - -- **位置**:presentation/main.gd(667 行);ui_assembler.gd:3 自记「回涨 761 行触发审视线——拆出」历史 -- **增长主因**:调试模式(`_start_single/_start_debug_levels/_start_battle/_on_battle_finished` 的 - `_level_mode` 分支约 100+ 行)糊在组合根。 -- **建议**:照 tune_sim_controller.gd 先例把调试模式抽成独立控制器,组合根回到纯接线。 - -### O2 调试模式与 LevelRunner 平行实现,语义漂移风险 — P1 - -- **位置**:「库存跨战斗延续 + HP 携带 + 层级推进」存在两份实现——core/level_runner.gd(正式)与 - main.gd 调试分支(历史入口);`level_clear()` 调用时点已各有细节(main.gd:367,376 vs level_runner.gd:167)。 -- **建议**:调试两层模式直接复用 LevelRunner(其设计目标即此),或抽 `DebugBattleSession`。 - -### O3 B1 体量与纯函数沉淀 — P2 - -- **位置**:core/battle_orchestrator.gd 718 行(审视线超 300+); - 伤害公式族 `_resolve_damage/_charge_damage_component/_armor_effectiveness/_clamped_pool` - (约 80 行)为零状态纯算术。 -- **建议**:按规范 1.2 抽 `DamageMath` 静态宿主类;段序骨架不动、可回放承诺无风险。 -- **顺带**:core/board_generator.gd:50-55 对同一张合法板调用两次 `measure_inferability` - (全库最贵求解器)——合并为一次。 - -### O4 呈现层反向依赖 smoke 工具域 — P2 - -- **位置**:presentation/tune_sim_controller.gd:23 `load("res://smoke/level_autoplay.gd")`—— - UI 控制器依赖测试工具目录。 -- **建议**:「关卡自动模拟循环」上移为共享组件(core 或 lib),smoke 与 tune_sim 共同消费。 -- **顺带**:main.gd:106,188 与 tune_sim_controller.gd:23 用运行时字符串 `load()`, - 与 main.gd:16-19 的 `preload` 常量风格混用——统一 `preload`(编译期路径校验)。 - -### O5 头注溯源缺失(规范 1.4)— P3 - -core/ 12 文件中 4 个缺标准 `# 实现 GDD:...` 行: -`board_data.gd`(有 A1 描述但非标准格式)、`config_db.gd`、`rng_service.gd`、`reward_supply_controller.gd`。 - ---- - -## 4. 建议行动顺序 - -1. **P1 三连(合计约 2 天)**: - E2(A2 状态私有化 + 查询面)→ E1(B1 呈现快照面)→ O1+O2(调试模式抽离/复用 runner)。 - 完成后 board_view / hud_presenter / main 与 core 的接触面全部变为命名 API,封装收口完成。 -2. **P2 项并入 ADR-0009「切片机制正式化批」裁决**:E4 表值改写参数化、E3 单位句柄形态、 - O3 DamageMath 拆分、O4 模拟循环上移。 -3. **P3 顺手清**(头注补齐、返回值统一、声明位置、preload 统一)。 - -> 复审触发:P1 三连落地后重跑本审查核对接触面收口;ADR-0009 落定后正式工程骨架迁移前复核 E3/E4 裁决结果。 diff --git a/design/dev/architecture/gdd-concept-map.architecture.json b/design/dev/architecture/gdd-concept-map.architecture.json deleted file mode 100644 index f9400f15..00000000 --- a/design/dev/architecture/gdd-concept-map.architecture.json +++ /dev/null @@ -1,413 +0,0 @@ -{ - "schema_version": 1, - "diagram_type": "architecture", - "meta": { - "title": "Dungeon Sweeper · GDD 概念结构图", - "output": "docs/architecture/gdd-concept-map.html", - "quality_profile": "showcase", - "locale": "zh-CN", - "viewBox": [ - 1364, - 660 - ], - "views": [ - { - "id": "core-loop", - "label": "核心循环主链", - "focus": [ - "board-gen", - "minesweeper", - "action-economy", - "settlement", - "adventure", - "difficulty" - ], - "note": "主路径:新雷图 → 挖掘计费 → 轮末结算 → 关卡推进 → 难度抬升。" - }, - { - "id": "settlement-hub", - "label": "结算枢纽与红线", - "focus": [ - "settlement", - "enemy", - "status", - "rewards", - "hud" - ], - "note": "战斗结算是战斗域唯一调用方;呈现层只订阅结算步骤流。" - }, - { - "id": "foundation", - "label": "支撑底座", - "focus": [ - "data-config", - "board-gen", - "settlement", - "hud" - ], - "note": "ConfigDB 单点 + RngService 四流,被全部系统取用。" - } - ] - }, - "components": [ - { - "id": "board-gen", - "type": "backend", - "label": "棋盘生成", - "sublabel": "可推理·可通关", - "pos": [ - 50, - 300 - ], - "size": [ - 130, - 64 - ] - }, - { - "id": "minesweeper", - "type": "backend", - "label": "排雷玩法", - "sublabel": "挖格·插旗·连锁", - "pos": [ - 240, - 300 - ], - "size": [ - 136, - 64 - ] - }, - { - "id": "action-economy", - "type": "backend", - "label": "行动经济", - "sublabel": "AP 账本·停手/刷新", - "pos": [ - 436, - 300 - ], - "size": [ - 140, - 64 - ] - }, - { - "id": "settlement", - "type": "backend", - "label": "战斗结算", - "sublabel": "轮末编排·逐行兑现", - "pos": [ - 648, - 300 - ], - "size": [ - 156, - 72 - ] - }, - { - "id": "adventure", - "type": "backend", - "label": "冒险结构", - "sublabel": "关卡序列·大奖励", - "pos": [ - 952, - 300 - ], - "size": [ - 136, - 64 - ] - }, - { - "id": "difficulty", - "type": "backend", - "label": "难度曲线与Boss", - "sublabel": "期望值带·Dmax", - "pos": [ - 1152, - 300 - ], - "size": [ - 150, - 64 - ] - }, - { - "id": "aux-items", - "type": "backend", - "label": "魔法道具", - "sublabel": "显影·探测类", - "pos": [ - 240, - 140 - ], - "size": [ - 136, - 64 - ] - }, - { - "id": "enemy", - "type": "backend", - "label": "敌人系统", - "sublabel": "敌人数据·意图", - "pos": [ - 651, - 140 - ], - "size": [ - 150, - 64 - ] - }, - { - "id": "hud", - "type": "frontend", - "label": "HUD框架", - "sublabel": "呈现契约·布局", - "pos": [ - 244, - 470 - ], - "size": [ - 136, - 64 - ] - }, - { - "id": "data-config", - "type": "database", - "label": "数据配置", - "sublabel": "ConfigDB·RngService", - "pos": [ - 37, - 470 - ], - "size": [ - 156, - 64 - ] - }, - { - "id": "status", - "type": "backend", - "label": "增益状态", - "sublabel": "容器·叠层·衰减", - "pos": [ - 614, - 470 - ], - "size": [ - 130, - 64 - ] - }, - { - "id": "rewards", - "type": "backend", - "label": "地图战斗资源", - "sublabel": "格面资源·清图奖励", - "pos": [ - 776, - 470 - ], - "size": [ - 136, - 64 - ] - } - ], - "boundaries": [ - { - "kind": "region", - "label": "排雷循环", - "wraps": [ - "board-gen", - "minesweeper", - "action-economy", - "aux-items" - ] - }, - { - "kind": "region", - "label": "战斗循环", - "wraps": [ - "settlement", - "enemy", - "status", - "rewards" - ] - }, - { - "kind": "region", - "label": "冒险循环", - "wraps": [ - "adventure", - "difficulty" - ] - }, - { - "kind": "region", - "label": "表现与支撑", - "wraps": [ - "data-config", - "hud" - ] - } - ], - "connections": [ - { - "id": "gen-to-mines", - "from": "board-gen", - "to": "minesweeper", - "label": "生成雷图", - "variant": "emphasis" - }, - { - "id": "mines-to-ap", - "from": "minesweeper", - "to": "action-economy", - "label": "挖掘花费 AP", - "variant": "emphasis" - }, - { - "id": "ap-to-settle", - "from": "action-economy", - "to": "settlement", - "label": "round_end", - "variant": "emphasis" - }, - { - "id": "settle-to-enemy", - "from": "settlement", - "to": "enemy", - "label": "兑现敌人行动" - }, - { - "id": "settle-to-status", - "from": "settlement", - "to": "status", - "label": "兑现增益减益", - "fromSide": "bottom", - "toSide": "top", - "labelAt": [ - 679, - 447 - ] - }, - { - "id": "settle-to-rewards", - "from": "settlement", - "to": "rewards", - "label": "兑现格面奖励", - "fromSide": "bottom", - "toSide": "top" - }, - { - "id": "settle-to-adv", - "from": "settlement", - "to": "adventure", - "label": "结果推进关卡", - "variant": "emphasis" - }, - { - "id": "adv-to-diff", - "from": "adventure", - "to": "difficulty", - "label": "关卡定级", - "variant": "emphasis", - "labelDy": 14 - }, - { - "id": "diff-to-enemy", - "from": "difficulty", - "to": "enemy", - "label": "数值与 Boss Dmax" - }, - { - "id": "mines-to-aux", - "from": "minesweeper", - "to": "aux-items", - "label": "挖掘期使用" - }, - { - "id": "base-to-gen", - "from": "data-config", - "to": "board-gen", - "label": "种子与表值", - "labelAt": [ - 115, - 395 - ] - }, - { - "id": "base-to-settle", - "from": "data-config", - "to": "settlement", - "label": "RNG 流·表值", - "fromSide": "top", - "toSide": "bottom" - }, - { - "id": "settle-to-hud", - "from": "settlement", - "to": "hud", - "label": "结算步骤流", - "variant": "dashed", - "fromSide": "left", - "toSide": "top" - }, - { - "id": "adv-to-gen", - "from": "adventure", - "to": "board-gen", - "label": "推进下一关", - "variant": "dashed", - "fromSide": "bottom", - "toSide": "left", - "via": [ - [ - 1020, - 618 - ], - [ - 15, - 618 - ], - [ - 15, - 332 - ] - ] - } - ], - "cards": [ - { - "dot": "cyan", - "title": "核心循环", - "items": [ - "主路径:棋盘生成 → 挖掘计费 → 轮末结算 → 关卡推进 → 难度抬升", - "难度参数流入下一关雷图,虚线「推进下一关」闭合整局循环" - ] - }, - { - "dot": "emerald", - "title": "结算枢纽与架构红线", - "items": [ - "战斗结算是敌人系统、增益状态、地图战斗资源的唯一调用方", - "呈现层只订阅战斗结算步骤流,不直订排雷玩法事件" - ] - }, - { - "dot": "amber", - "title": "支撑底座与未上图", - "items": [ - "数据配置(ConfigDB + RngService 四流)被全部系统引用,图中只画主干两笔", - "未上图(已定稿):地形变异、存档序列化、战斗表现、音频、教学引导、设置与本地化", - "范围草案:关卡节点地图、元进度" - ] - } - ] -} diff --git a/design/dev/architecture/gdd-concept-map.html b/design/dev/architecture/gdd-concept-map.html deleted file mode 100644 index d5897a40..00000000 --- a/design/dev/architecture/gdd-concept-map.html +++ /dev/null @@ -1,15051 +0,0 @@ - - -
- - - -正在检查已编译语义
-没有匹配的节点
- -最多选择两种语义类型。选择一种可显示其真实流量;选择两种只比较直接编写的关系。
- -选择一种类型以检查其节点和相连关系。
-语义雷达需要更多地图可见空间。
-`(Z%yww6&prP{qJ+{L1rzFRH4qy1 zjElg(XgE8=oVNAx?%#vFvb=Y;vVxN@*RS!GC7 zdCz 8n(oh`aR9`0YCBs9iL8Fh PCT_Zy z3aN|QXgH@K1TQ2k?kxL_Gu;xs!Bw%vWfx-z%5h~DA?&}%muB}GhRyE+!=1Rpx20pW zM)SJ^5)CVCeCJ?}i;Hg;r7bG(ZI2MH!al4yEFovMiVxjsC$&268qh1gzPl0`NC?$S zTWyTZ$q6ocv0&&LMm!p I9sy2++>l_^c1Jo)gV09;tSk3)?`bZv2SZ zEjFplbohFc7%YT+M1JD_dK^&lMUROob^U3uHAuPZ{T Wp44hCF3OtDKyc3;P7 zwbfs-xCmxQxRxbAS0WM1|4CmZqo?ARZn45xksXRS)vbXQ|HWirC-$ePYp0o6nrkQa z`_Kd&A$2136@X=f>|Sv=-+*lBbPL_pthR+23A4!MkMgO{#6CasZ4UMmA?5X0muwft zS4ePHphBfWE@g?E#Tl`6umT-hnElA>#@zIF&)x#DKf<)cmgNNjBQ`~fjj!~Of;aGO zsySq&sU+`h@J7QlsKVs!Te%Q`TmwuFS)u>6nrA@uY`b1++3Cd4kuuEFTW4n9u-Mzm z3m(I4p@O!m)8iX-5@^%P?|2`RmVl} L*hdd=%TXjw` zSI1?cg-`>E7WwXmC2#pzP%TRz6lAcl9Ia=wx<5HFyXbZ^(MFk)hlHLgU+C}f)#<)G z0oN&*6jwe!0cO&QCw$oj_EyYkd(^CXZ4;X2R=?G>OrE}?FBYMFRdTxs<1L!Zr mE^6lpYLv^6^3-M%Yg9yF2gA3 ni$&LYho>bzXY>4sifr#S0@~=8g-*ka4Aud`kPI>ax&{GJpYyHNT4(Cgq7r zEJ;(}UM4jCxvC}{n9n4~%x=+{QZFb$4|@JbxbcRQ05c9Obki=rC+Y^fMOMn$5l0_X zv{AN+F%f6Nl0Er_rCDBx3kx uEV*Gyn?5%Qn~CctZSNdUl9n^*31=rP z_!u?nSIMtxR_j;*f=x*RuS7!$EDLdDs=9~%w%xkb0uO`|YWW2C!h%CX9Z-h3lTU8m zRb8D^R#sM<*OJ#*^k;QTG~`Rfp=~5ngyWPnn=}iHq$GcB1S!S~57Z&K7y0eEG OS zQNfu-F|m=wWhdXA&~x)Nr#Y%SRa-K%fAu@CT82hM7A{jOTsLQT9 +lLqawnq40CeTj^G{A$s_e8-TrHcHd?qWaSj?ad#Z<@YqIbVZ_x z2p8sE1(t_$3BR*``MpijMK71L`vn}aS7`Q_QAooud>pO10Qx}5#3X$j+2Ku^rjcJF z=@Dtz@{W?6OQ7|jtEyw>blm! N6F&$$kn)J-w0OnD9`KWJMba>;(-FA3mc=`v) dy_*!z^NY7CHHHkot$wxN$uN 7Qj*JdBkL4>{p08!w<>Q{G zlUegwyu~&}ZBx&-%S~^7-Y#UqV={DMzn$-z8OH rs_rx`;NP5eu-LvGL zs~2|^zTA6k(>`}aP}*wtG9_9HLz1@ttCrpt3@Zy3foV{m?c8|_5Zu&WGXrbAboz?B zyq{WO;@z5QPp=jo$@Ai+;&1tc2W{q{y=1x~R?l4p!?vxrflUh4@d8X2pHLkmP>gkM zPCj4lg
^Dv#7WO!2$)we&-uuxS&ex z$)ZBtS}(k^)e6AT!Et>5#^{M5gxEiH;l_AuVHYSxaxZMJt{|1_)f*zB+3An!j`aH3 zg&HO4dTZ;t>sDwX!HBaajYM{045#y4R}lUW#WT1j)qa_GfgL$r{D>YM9jk&z0DGR> z5e-dZG(iOE_%|?8^rkv&B=FwmEp#$;(1jXADi(YEKla`-EXuBJ8&;7J1O%iT1f)^A zrMtVOrMqQNx(1|`?(XgZN$IWuhLG;=;XS=>uls$z?fLip{I+lY;4IHrv*I|8b*z2g z7gNAs>d&Cv1kO`?&)p*r6R1#{aoZ!s-mjWS1L2IS+WoKyIOMSaBPw#qu!f0|yv3NT zlM;e`PaYD$V@=#XE)MK`zv6lJ^xfgXg+CG5&g{?AvZ6-m&lDTEzcJg+$c(YZH_Kn2 zN(6OZV&R6n_j7I-!L=CHSwc+xu?~$(Q4QWGTvGYrS3WMUQ?-c0Vz0ZNtSS? z3);1Mia_g9)akSw0?HI1W!LWL OV`=- ia554QLtX}}Up3h6hjs=` z4=1~9nBNW!#ftf RbFw1wLX;n5QTyP;btVFvlyqNgscC?-Ye*RWy zs5)IOr-cPuOw48-j?2v&J8PtU2ZfcFT?5%UwNRG{H(rjnPw2R`xpuZHS{?q p$H 4BA=(A>jW=%n-wq#ky_pqpS<8Q W!_%{9x^)Zcc^&mh z;-&NTx49w*Z1&dx{d2I`N>WpYf3U(Cd%Aa# ;i{dx+voTh&e9@Rv(O%D5`uj1{a|eew0fGzrIL2R z?!`bGZ2~=&>Q(Mc700$e13Y9w%29hVR?CP<=lmI##Y } ko;2qv5*o0XtPVwwk z+Oen(N*CXre ?xl0WuJjvBn$B(ioEeNI=aK+3 z0g{Celr$H|+~o@TcV1d>q&grqr@&7W$a6MWOnb+%Sx+CtUmvy`JSi|!%RtxSxOF)P z&F32x+g<(J#9_psF=g!*l-L7o? TgKx80*16Pz>ZW_2|3i3P#TKa++si z%Tx^d%8HrInMl)`^GygZ pp>Wt}_~ zP2a_)%w75in(3*c^Jf>dTL7tZzbZdlcz*}q#A6>5@O*3(R2R8TujN2H^a&FiN8EZ% z^*4P+V-DxYeibuPC>5m63cqX6UbeWuZo3yC#=-aQ<0x N#D+()$H`vr#C3kIiqH(6^E3OKrK%s^OnVE!dOwoUFJJ-4dA7tK z#FN|%*sz=iKHmMx95;Q#e?HQ(gFDcuRn2K`YLb)4qD4o?|4XcOn+|AFIgKzTP9G{H zBLk<)$T`f~la@-WNu3OLq0cKHxzAcmF^T4m`p6+^f =vnhROH6D}OdG!LpRv#v!Ys~SPzWZH| z*+aj3B;7LYJu`eNysv9((_>fVMR(KHQ&=7^!D&RDaK~sP&UrMg-b&P_pD*=i!L!G; zWMgHovgST2{6RH^y6ddEq40R(&O`=B z2)uX}@9|yM$5Y5gNqgns=oV@YFOyd{=lkr-cXq{Qa-gmXz1$IWgPG$&i&Z5ZPzkN7 zsZZ)qp9(7kEyWWyIyK8m9-Ud6Q8YZ-vO!0-vGp+GP#^XlBsv`e_yDzE7RP|m*Y~pJ z`ZdV>aC#ORvZX=x5Vx?q?2E1kdXw9ny277df)f{x&z$LgJvo{(F*(qF@4q0DQ-SGc zB2+S|gBJf 0@2y(|9*~(s1ubgl z92WPmEY!5z4C71z8MU*sQqaN<5&z|a79I=ScwMP>@M@p^EQ<8brZ=+5eQ-j^SUzGi z4(=4P=(nz5y1s5wpm4VpfVoJgNBV1IL`Klf;<}P@iiMexk&!tfA|k<$-wzJ#J7UQA z<&y}4_Ly-#so-Hc7%YuKY#+Dc^^A<}?M X zGnE4tPSJ&z;0!Xs@>r>hL}p0)@lPtMV&?-WO>j_fd;NBh6uH-!vW|ouQOCK<<`Az< zpc>&?yPv|WHRsIxJO`hP{q&d^na5n!pnIqT1o~mHKx^_k#o_wA2KNX8S+rN%@vb1` z`_7V*?(|ib!8LED0tEB;X6Q6y{>bC$Ii8IVhu@i1qzgg}&+LY?_dmWq?kev|T(Es9 z#$ a@t#FhRSV*3=4nNO9J6Z;#Ui<^3mTMN^s98g8*aEwetXEs^T*5W>XnPT z2h=&KE!S&R6vF=5prV$rPC})A-;K{+61TA9H`h`7sWY!&yhJ^1Zsa>i$a4rhGt0FX z41NXsFeULlU+c4y%g!k#BD2_SLcYpuc2KcfO0`3KqAZu~T@wSlpm!Dclju+!GHW(W zS5n*4E1C&65&;tGdncYWmdMDO;G=HPA|>#^L_Ax)TVdM6DkR6i*tIE?Pb!dmKgfCx zD^E-^Wni47c@w|61-%G?($?0yH 2p{0sq~x3SUDm>QOnbXxw>D4K z3*T3tgk kT2If2Gj8VwuVBx~v*A-|Y1maCi!{ zMW)e Q$;y?%j;YZHcZX-J-!zH0vvL%>oSlkwiS7_t zS$Kn$e~7Wr%AWRRbx8prIj{xl1fm19YA?|*vcNk;1N~ei^}=&^-2;{=b#dzeNe~@k z!BhxvNF!nrMATQ+Km9q`>tbnh$v{t(Xz(d)*T?-pz(9Y$)=#?z!y`UUvQ8$_x`eJD zd-^sFI=Jj5=sH7kP`LLAX)+J3XH-Z6^)xS4RXyqVmX4g>)dNEjQSIqY!I50Akzbna zaw{QNk7$S^{1fMLgA(iR5p{koJeMAwt118TwuDtS2?;D;Of9FIejybCGJkNNVD|7{ zfL#_%Erc{&{-yzUB{g{MgSjz@_-d=GohNUPqRDvI82lWiyU|#kbae9MU>jf!jI%d^ z!M=R9+E<0!=!83%M|W+p>m+1^Riua6q!X?mZCf6mR;QGA0>Iw{qL^WA5RIKf<-(np z<^N8E7iW~k^!cVVUY?<^dJJv~o|oKVmU0Ro)NYM7>p^@%Kxffe9`a~}E(jVNKP?3a z1T07tb}p!WQ`oH?FZ(<16P~GAAk_t(;OqHi!+H ~ z$UpbF>Iw~K@Oyn8`F)Z=7qv0mn!=*z#T3M|fbEc%h}!$rNK-_kU}0` +AD z`;rIDHkoeE* +T!-h@r80eB4)Mdm!kRC3BfbrDm{-kHjc$eCvKJMV z!0)_f4+Uc@nq|}DUPPnZjk>5SXL5mCSD*z>L0ad+4=dTnC8nk!eGMcR>-p +5BAsGmRcY=1Kmy~sL;F`Gc64T L HlEm6sbNC}GOaU(_BzzXEukuQ!xe|){P#CW z^ND4JAv1ycGkI%tWLQ(+$d{6u)vfoG)rBC<$lYY#;XgrVl=DPkId;y%F0cr#S29vK z0-bM_{_e4COl4x(dr!|=vl*YQYe Oe+3(NDDQ^>c^F};fO(N&EDT&}+aS@&CtzdCu zBCe62Oll!9hi|1#l0X}%ACuU-;S)T%`^^njCDbO-JnR}A$IJ8P{(37G%L#T=FlFq) z=HEs42_+9);rkr bpU}7%(!*;TO*SqNVPu_gRv4I( z_dEn_#QZX$zy$1wOe-ywN8WX~6cb@s(PXQksOU* !4LaO3Lr* zp?9x>SmMqhHmXvQWK`bAV=A%No=KbSu?zF@XmV6j*(zY!I`Poc(#-JXgmo$P`%kb~ z_toE|HHLyMlU%Oey%HflW(@^px^=k{<9BhjK?-?sr2OtQG_)85W6}1Jc~vY%Gcdap z-z$@|n9B$6%N;TBY4xeb fKdxqXs-@=`3dX?+=gm?nio8&e&&J8_eG|V$LnK@n(vjm5z4OQ7SF|Is^ z7UF$WXGk}nw! AGGSg!zhHDq4OWwqy59`3&MkPDZ<=kS#;=oD zHOvcRyZMQlIi(z>1F}ACPuPG5@E`~CQiwuUNUvJ#>X+l_>J8McsxCG3uOAlbBdj&? zrbSK*^W8v6<;m%7Q)w;giKv!wV0%3H8dW((h3jgBfAU9qc3t8rrnmk5F8Bij){=FT z2UT_kujrt*;N9KyT&CjrF=ZB3?(=0r0ItXA2kRnySxRG>M=*T~-|G1KU}$je|9L9q zHS@%of_h4hGqJ`w!$1&PVlnP0q;ebQL`2vIZUKaj>EKvr*(|8yXL~tkN%6o2TU@0C z9^EcErOsp2^W6lwFh}H~`cxDAF)2xx$Y%I0S$3wTiYEMQlbm;i02h}uce04nx=vTE z&4}5A!=QPra3)lx>|mU6ySWP2sA2+xwEWSW-AKKgC)}E|>ow6!vGuh=Vey;8!c%%-;Mr1Fgr&bO8fT!W~c5h 4n)`mvd#Tk_LX0yhf%nk^uV{{# z^HGC#)`AAwATnC-4T@cFLh| YN#;> zRJ^tPbi~4|lUiVk6C+#iD-;x3QLf(8@Vlg;n}z1^mUO63gun(^!W>oRuQ4zbpE@7h z%YT!cu4m4{mLxhw^g1U4cbS(s*Ay9=UdRR9ShcwC{tlaICp^%}BN0?g`Dx^Pq2TFB zV7D1tx$6vCtldb?3MfLM8h-tu#eZw0puv7Ayg#2Zlkl*8OVJ7=$}-~zccx!Py&cY{ zRZKxoSZzzbe3~~V7E*Mp6u-|5dK{93oI$7XqkI c1QF4V6_ zL^Lj@hLdv#E(=HOqTD*nYP&3_j$P)pKMW{nxcK3R=Ovj%Ta1hBE+93$pNM{AI(bv_ z)lNOdSgh+>v#iVyX~~g2!GNJ%Z#b_&CrzV?xB44iX7d*gxx&|0?)~{SZcor{i3-&< zbI6In;;GcZl1DMrQhBjO(jwrwIRcrV-&}F%>9E8*n%og(F|7d-=669KNl1I!P7e*b zceU7ph1D%Wajx_zHHk1SiDh&=29WhIg1V~=_h;*-XIRgO%z}+wJB_0s3+^M7N-#)& zGo1Iv(QPj|WO2V0YNXr9@YR^LBIVm4KKIz4Q?wQbCR&Wf co(k1Y_!|)RZQKt{m5t%lT?T*h!9 b)!v5*8`cY|hut}D6sS%s1aZ;7wlYJq3izZlKhN70f|<9WOele}!)E+3 zMtxrMs!FhSuU>u0R%Z5_ql=E!;fvmE*SA%6z^3 MSgo zeTb{Lu1iuK-k!wRip_VHHIO6Km`!D)Xrm5ek#uX+gqG>lB LQN$I=I79>UUa^P zKkSQ=^4-r!+)M8iLPVbfJ8vr+q!{DIdsh4EpsO#}zpt^pWZ8m$3jIj{^2nGUh%vZy z+ruo=ImHq~>h-||O5^4D)2xBqZ}kkb<=^4r1KVg7_LGUre)Vu?;`)06E|>au)CP}( znr_ZXKoTM0&C7!oO07*n5^v~1mdAq}E~%aL4g2qrmb&VR-_mE^b9P}3s&a_y9jqoW z+ARMFTH1OBZmnh6)$oWxVFSFIP5#;-GoA1$CJ`JQx{++_OZimC9M{=$y@rxpUc|zW zl!CDeDdUnkG0VftEmv1?gyOrvJ4}*93l`6n&bv?ibKVsx{hQ;N=o_r?J9B&cbPnXc zhsS2Q U%Ui0lOa?t~Ir+wX4eq#Vk{vt35XydCvxFcWRhw zQkQqc5kIz;0C~;*L$?&q^3vQl8>7Pfu8Leg0>m?&ucC?}O5$y8;*guZa1F+vMj(S% z=pF|s?QRUFCBdaaeo>$|KH{HSlZ}OM?|$bjwKTlYXj;IK`=;xsNNN&houXCvoyDm5 z+8vy)hq?S|YKf1=a{ SLm-|JBM4O#YF|1kXec^|LgR`H17Egu{)6H{3 z#eu?Kt2BXxn2?xYZZMLs)mdxx_!1K>&zcmxyxiu44J_&IzMd=X$go)T67CiR*F0o5 zXPIf|;mG9H3|cI0J_?*T?42X4ulU^V^a pWE9R5Msp} zJW%XnIl77ey55#>lz%7gPIPxh8vRQ3rV**WQ_4LuR^nntL0I{!s>`q5F6lL_7#Hl= ztD;V9rG7=8ODe?hX{xUKQ#IpRLVSD>J$?{;|I*D0o!zj(W2$(XA*IZ OvO3ieRP!pfRFL{I {Nk!`yXy_~Jzgfo0Gx zk>zL}seq@nu70*&LwT0*Pw>e&b;#sO!IB( !!uOet)q1s&2va zUVA!5Y{opGyRcj*U!7al6qc)-TqP*WNf(qQO{uG_{Fb~^Bxs#lDr(tvl85N`xt^GL z-u*a(Ok_R;rSz<=L~lUPf}<2N+z70du1R-EOU=Qu1;p)l?m(hNcV@)(V8-tDf!#9- zT4$=~WmTlnmsPZSCD>b20LEvXU}pO9$TM8g<}SZI6cV~&SHX#!pEKi4l8 z57(~U@vDcE89^_cnV~uurRsM~n$pqA#bGn{b&uo>AqvUYXQR;bA)1T`C!7o>qlKC+ z4Y?$imaBCB^|iHq*}I1;gsb82rUvd~nNNQ{5C-3G39}vwdrBMTo2fND)a%jto*gu& zrncT4 $5NEY-JF8E)Vb_Z;XSvjG+5XK1M3Fwo=^ja* zKpol*9v9Cl8d>^SZ2=gJ(bw0e-1^bxuRx+^Ib5M}she %! zLAL7b465<1S9rr+2EQz`Q#keR(~Y65#+XC-G{mfCh1d(d;cB+u!z0wopuvwmWaE2c z`OC&UjnVwR1AJG=#5i(tj9v~^?>IS4;1L2 q}OIhiJM5k(J*u|Vma~W_d^yv%V0<0;@?j1WdntQkj zd5lDzZ+f^hi=YB(^S}~6s{2u4ojiT9!PdJ56gxePTuCF9)3L(*6B&5%<>a>+hlP*B zI+s0`8%Cckw1iB dqgsdnxTSTHM2yTIPqy<+HL te?@IcbSS^Tr%XT0tpI<0%l)Q`NKVtDAgRx))HHi z$L7%d3!F##o4#nsNt5N4iqD7``w_&iS<{9c2fCHv_m bEXz!di|%{kx0EI+J3__Z)g2(BXP-Q`Ef+7? zt4~m5?*QcWXM|g?jEh+loU4bP2ty{X3kg+0>n;&^=J;%g@VkuV?o13WD$!)*cx<6{ zkz$?a27*(rC!*I~(Kam?W8{nEZO7mV57>KKsP5&4Uk=Q$_;Edx!$08nMs-?jkORyo zf(zrh9!Vc%6ya(P%t#TR+af;&6*af4I+)UlEjsu+-&Neg{U&N}49wWvyuTl%`F1xM z h_o5*;!I6=`G{E80nh5n(3BI;^{3=F6legAl>PNSxVCB?N gl*0Og1WJB9=+dypz2GU!7tP|AJG?F zQr=&XS)D#RVebDaO=a~H!}3gjtUt;A`()Hw;xJ50UH#q?{!F*@V!B6_iy=xGw~LQI z@`8&WtIu2+Qk(cEAsI2qM fsY`{b9MqD~f#{1j(l4@WDcb}jP}%8Ql}Mmc320QkqaHAaR3YEQH~#%4vb$L^ zN@?T6*}1 Uhy#;Y49M6rVN&GqjB^UgAcilhp}LHYHye8~1`T=lJ)6X1 zMiE>p4v<=ty*YHM{L_M9J13nK1it{|I;ZCxT&>(00nW k z*&MoUe}LLvyW}#dVA>0AIowFXS4wtOi#{|kGHmo*4^}w6cc q~xe`} uO `vX-?!r!+o5h@GYbOgxHj}cO9Y-A^p&L@@#P-E(@$f3x z@V#`*j4*D_f(W$8X4Ejm54yS?YaW{Pk)Q$>aTn ^HMPRmH>y#?b4(ENzbgDu(l*gRCJ*+JNmZPdm5pYB-@!V*be}_a1(qy zJGhB^tX1IEw1z{oS-Ixyg1R;2$fo&oOYNU!-OpKhIgI^?78mcE9ks+Q1y7x6Rd&c1 zE+L^p1!!soe9Hpfd`k+w!@M_ctFXUgb^_3F*I&6SIkLS}<>KbBrwdAKx27C}x!UuX za!Efp80jJ3jkSzb1MT0%k@*iP0A|IYImT5K2W;%v^c1=m{HD-R_o);F$DG>V-FU~Z zEC3ZmwvY|gb8-Aa8|DXLDzNJCak&mInGS81yqHW77qaf!ZSWM=>*q9{I522IpKEo4 zE=@X+3#}z@rTc9ZA0lM)HbvLUxT~w8I|CT^P}%%VWP-``n#LG>#q<+lFtuy_}mUR3FTKe_;};a z0Q*$!>pBqPn7`OFDO?eS;7Y}yD7}XHJ-QaV@+`n<&Cj?%Yh$C_g&7N_IKakz<0U)# zYDLoU+m)-fKddTq=zlW6X=!J}yM n1 zTDRd)%+q>HHBABRq<&dY516Zj@7*1y2-?g*05`6ijAa^HsGuAqnlo `XVN>nViJBo&epVH;+I~;?GEk_-}|$=Qa55kNw}D-r|P`+AnQemyKkaT-McEr zXKmMlA@nBj6SE-&t0e7g?@}hfPVm|`GUbYJ0_c=E!%Fk%+ItpmHENpb!YJ&VWT#km zSs=bYZIlL(H|P#$LNzpCpXWqOG(aT2uqMe~&C7!V%zO-BzZ`k*K;5MLX=(i;>jLqN zpBpf(Wd~)A{MMIjf}?$Rg;`bg7$j85yJPUp9=`_UloLM=H|*tBd`btB80F{_C^!ik zNme>7Uc}v^m!$E%U!=W+9?a-97=<4917assi(Qq?&F+V}tpof4%>c)h4tMM549CgF zs#yy&GZvlOlR%k c#@vAb1B7gb&bpf$GWGFYFjAr^qZ%_y3Nb=v_= zht(p|7x{{Ak5h{->i$_|O?-Vy4MhK!h6WeJ>zN&4i0fWfSXe^)ba!`<`yLkOZu90k zoipw&FzNfWG=CL0Cg(M+S410RU`q?$XI2$OIYu1twY-{Uv=-+?-_Zs@kihVqLWlW# zbivr_*NSdD!nuKQwFTtrbR(_nn2Hr}k%*>K38vlV7<$qDx}cGxwleEvUy U}eNrv8<-eEFURz)0V+mnx8kuwwkdA!J@f=oTEu-vxPEvhM*W0XM_7aW9!-{6q( z);v2LNrUgV9w{CX*E-w^@N_{zL2mm5?#CUMNk)bwIFtICzhtg@OBx{X|D*)~=4lxh zK KuTk82AKIfLlV bae(hnVs3jMrM$CzXs*z$kJJOU zCflwSy)N}{9}=%}1+MNzt@!(t8tH|ESQr`ksn@Bnd=!AGpwQhU`ulDzrCvZ|p~7*1 z>zXLWI~jZLIwtrk!VRNpSj>8n$Jor*(+8^kO-uLN7N3$Sw7p5g4T=UkzhjtgKoEdB z%Bdrh%)liP0I;WZ3e>Wm8TF=t^K9?|Ad#Y;643Y*1J0SUPO?tH8W=N9$Dy*B6d6Wc z_a$!@E wK?ap zwY}xE81@z?*`O?yB7V)WPqbRL1B{}b&6FS+NoHKkU&D-<8@Bq77t;aA=i6S>01C*A z33doSxPm`;J3N}NXNn-?9^AM#9lt?KP^r~Dm??wi9Tb6bIFEX~I0Vkw4{v|y-gifU z^0|bKJcQS+cw0wrZK}dBuY=S+)p=pw=ca>}n=+<0xwY6fce{I81Fl@4R}EtiZO01# z336W;qZHx-)a**Zy5S;i9l2=^>b&x^mh;) ~0b$?D`a$k@Z!alHi-qhV?I4}So9D&NRfVaZ zq5>n5F~}7l74$YC&inK{Ji*A})_BmSqV0O lyPa0iMY`yvGaNWH)4%vG7HVAoZ!SPkLbq>9wUg&Kg2y)Fx)k=~U|)|H zyn!rh!h185p|%pOe&ye~ 73h87C@E$2_mLJ z0qvqW=+#s5rx|{JwZ496Z7l_EXWaCk&L;@){4zsn#tyQHrm%n~+0xh&wc&1TB*u7b zP7zJFGFisS{P4b8`n9uQK{Q7GrHHe*%t0k)g2I6900(Pqs*@K3Wngf?-(QT06vG7c zOrbW&`@`W?HNcgJg>n^zK-&KpMue22qzsR)(b-*xwLgW10RItEAK$p=!A2h9dUM(x zlhI#-*UlF$;(&sRT0bR!*wEoS2@s~w57TFcVY!)LQ=%?W0h~dHLSOX&zO^W4B)t~^ zI2LvAD1IfUNTebOz;kcduEYZl<(TV;U2lTTXLkYigdSiWPUfqW6_{{z^>41c(q-zT zY(AY(eU{7zm_+~Z32cMP5oi8{?>0|Ln6G^1Ev#? NQ# z7_w^DYgwObd^uGIc?u+&A;AiJyP?&w*eA=x)ZirwlZYTx@>(VF4{AV|wm$i!EIYh< zB6H;<5MZdTBiV@MNB(&QAwaB4#RhZ%tZ-&Q%T9{KeqD3R1Y+YHYE>34E8GAXIw?V- zul7|5#j@Q0thXLVL>N6I^E-l n@&~DW8VNy@T$YRbmp%t zb5loei@y>AZ0O3g`PMQR(ew?#e4Yu1nrzL6T8C`#oO6GTce>Nt0D#rPs$K)SIefyi z_Lu1NoJ8Oaf=;X_g#;P|PoIAI)!ow|^Ol|kyF{jn>=hqLV9fl;y`t?hGQe1rXx&S) z5-WcIGB4s*!fGiQS3{%67jHwZbo`j>F9NwkVHW8TyHnW8vNr&p#iS;P?3y||TP_@x zbc^n@ld;MtPfzs-f~xV}@A9;Acj!;Z{S6az(-gPYdm3_8lHE@HUv;)h6uvVO*c^(= zCi)M_><4pRse!stKgU)ToIo4ISfrwFhVv(0iX1#$k_RB1zz7C6yB{3}c|5pDhs8|@ zT*$e(719*58nsdg$&ARQFoKsdA8TdghnhS)l~oi;x?Zt9&1)I&v@!90R^xcsb_(q3 zx$Ts*vNEzTxK1UUC=Ng`cX2OT>Nkoe;7_FIfz^7hn-b1K-JpQqvRiuPF~E;zD`Sx^ znVuk^esWD9Fsh+?9(-CITOF%fL~nO^J6)N_!9gYP=D7;`XM7!X;NZU3EovDd65_#u zfq>-0s0r~j4F)wY6@x53Nviv4VBGswdKtD?JVeAOBtlPN6wi qQ`%w~REDR9-8WClAuL4~1y4Ybv%7X? zWYFX3ESiVx`38cD9UA+4o@R=rtCqM)6aLFVwJrFr`O*osTjG1B$tt qkHYk?)lW0; ?Tw=1GFmEh-Mtdg%f*94&u`+jCOw#V1XtB2qNp9vkzJ=WDlnB9 z;)5h?y>^F=>ZT^%740M$&5YdFX(1e5`wm|oFvr96T{lC}iQVHW^D>^!!o3$tpP9eM zi?g&oW3(TXQf)kM$(Td~u|h>1r_Nj06LX)c?u5YVU^94y!%9>+IqSOh*}IYwUW87F zVy#kc0s)fGsCkm#l$VzPW{VnfG!yi^!8+xwMJ?BKLgkNS(DL%=)H$Fn!heAi;$`~) znBeehKyjj|2GB+U7JgKJ{D}>{)9#<9)Vkkf=mxB$U4t{gA>K0wxa3bw{;0N?;%I@| zEyx-kz&2+W$9Lg?& tjbF+ObH| zz!F0*Wop+U?tAVeV!=IJPpp`@1HS_W!$_o9vsK%$j5k}aySr8v5Pk>_NA;Bm%F5QS zn2mr`zf^_D=GB`n0RlNQUH9n=r&C{z7R@XH4#-9kyYPghOkSbmf!0X*k7hWYl^c7t z(?jLMQsTM|JU@8Wqgn`g;jTVso@4*v6zdhIU>!K2aB1@$Bsggz^J6%RG=3=>1{a|M zFFrf!*_rf#Cwu?9&t3RmI#wAy^;RfMaCP`8jaSccNQm&T@p^yAul`re=*fNH+D}G? zgyPoP+H8Q9Tw2>&+ugR&S}Fwy6(9mqNT^^MM^CH2N`y~7z241d`mplJA7G2nMk?uV z{iBHV F#&q~0Q)WR30 z3A3*qPxYVt_^Y$EqV^&Ei6Q`hZTB~EnV5oTBPIMf-~;$%RvEWWwVVijH=dH}K#BU0 znTV|6nXU!kKQlj;DHcqlCdz_4{<#u3Z;t~|7%ZMpmJ#;89iJ4o#v!5*10wolZF14C z+&v4gkH(0xmIRpI$CfW>Ye?8Ue^<7~6ZQArFPL4`rMfv-!n$>m3e#XfD omX(NDg1HGGl=i{;I9*V>woX#oxriwwu^@4feg!7pB*p`lJ}=(qP1g56 1mhl77=%fJ7uwez4 zT!u299Lm@Esg!|{<-dnU|3(3aDi=*R;j?mdv=Rd>Kjg?26b?XNV|#FrabVzYgFWGp zD1M2=ARx|VW2l*ZZD)W&(vI*P117p-LoL9UT%Mg>n) C5m@Pz$`4((pb7by=Qpi%O;>w zG$lDA9siZ` 6MgjFvT-(r-cOH@S1Y}rhCkP`$Dv_Q;)QBjqt@c8tj`_1?o(nS@be`_? zo`oCg)5iICjutEA=fAq|9guBdJ$O%CQp|vU8@j!{#;AqzX%}dJiS6hx52FH6Ikbq- zq0wLNr)}zJ-)E(#(M>gIR8X320t@P1svt@3uklVewIU2o7!s6xykRiDCV6;AJ 8ty?gbK4` zoJS0hu0X_!hf2F{j^nWlZBF(u17bi;j6bYMSItm&L4bB-?-_Es(uoMLJpGV4V;wk9 zmAD(zDaQD>Cm}z JT86Wd-B$=Uv zLxgWlknM99_ty@rSD)NOBy$R=y9pw9{yyv)d*(3AGVS#OakekjKjH9aeAaM(-Li5} zbce|P->W!K4YwoJHHhk#i95fp5(}XL@>{)nT2TP!R@2MI|84KDzqa7XZlpgcdQO#U z$@D9SCvIIyodS$czsi 8YN*lxfw(_2Qhkoj$ihipeRu;cYF@v zw^1o~gkX@ZjrIZkyr~<{NYZ&UqWhYG@Xw$Bewz;oe3HJdVSR)`(vj2&m}BH;l>h#i zXWMBv04e4EiN3_&qOrzIqs_YyD}TQNa>BrI?p?xPwErFLU_@^-(9`D_kf&O&|6ar) zupM!O20Z44{-1OE{(Q#1W#VuCv6SqNZhuGrhpsR1BtJkN>am0KKl i+*7NZ7l5{QSU?H>-xr|pNj-h?JnBQIH?yhq-&-j@ ze96aB2CM*2rt9C!lDWn>pWy)e{t-)@m~H=>_JR-NPk@u#E2&DbhDP&6PXAtfO{>iD zL4m^YNkL=zdkVk5rLTXQTRvYva(ww5<72dT0^6Z^$sW<`I6Xo%amv8hghkNLa7Gn* z!Pt@VpM4o`BeDy$Ru3#+-H${RbdFxT9pmf>)2Q%W>tw%vslvm9bziQPdGoee^WR*+ zF>A$XXNB2x uPp$o4Su2n47U zX$)wHiBbn?VD-Gx6Df60;2aEphFqY3!;tPMP%st!LpBd@fj+z^TDA<&@7HU_3^MXM ze@M*vnyUT28qN!l #R}}RC1rkJNex(381h7mWA{90kwo%}^$^zF`$8U-52e^D* z-Isqjp4Dux?i>vtS9&cre!9`=@Lm(^3E*>|ToQn3H;P{v?x!*6puZ~(Uk6}VFa4*6 zs|ONB!${TB*|E%5bZ!}k#xYfpvRvb2R7jW1I2d$<0CR%#9KxO~dOQi
SRYiOWe zyeE2dt$~UxOs#1j{$-^CR~Q3ixU*7V;E8BsLFGz`bw4tw1=K4=XWjzWpPWPR^=se1 zqYCIHA|w=&znuk0PWu2I`0uCV2=M9uet7~xe)jJmd-CL-?Ek;%pO*Q5*$|vhJMeQD^Gkyp)^mV9*xoVrY3-8{fhe5DIi;8a)#y46GTf7U;t=f7KPDVta;l&+?}m zgSsIB8Ce^5PREn%^6~T;CwD8B-KPosP2%$__)&s`DZuO*(0YHZBe|1|(`h7k11G)b z_`*XIka2RfVyR;iJD{~s@KpHE3=T2ZD3$HB2w&SM*=7ZYzeQl=$RRY$`* a&e^gS2_)I$~bJs<-Z`OHSZYe!g1w2wK$R wIb*cl5e!$KC9RFwd zTiu}6P4ui--V0n4RynKXe|`>;yXU|5%KOIx@G5@ed3DdC%yS*~tI)FswG%U$;CsMd zI|g(g2=n=0F;U>lwcsnB{|@$*D`1ZP`}yNe{y% %xqG z8yV13o(Zk;{#5hX(dQDFv*@gFcTB-V>7CY!LAI~gf*tx!cAtn^u_{_Zd!U~$1}Upg zwW5g9px-QyR=iAVCg_r!=7ap-SyJ&+%v*F)TlVwAUZ6>aoIPG;4%mYoN;egA(RziY z-gCcvJ(w%OE_#FS{EI!qMYVpE%u=I10(6Vhu=o9={%q0@_q5^OZS F%ygznkMmC{>eK+R9s8V$rE~mS`mm!Bi zxcRkAl#jlqO~y+vmXP a<>V%;<{Cj0F?n7wQ-Xy`# JVhnjYU&g>$(oI_5wVjl-?VHEpv)x6}_Ms1G z`A`=9R^S~N6$6BieNK^;b;~>n7NrH%Iy{eu0jUPZOooG`{Hz3VA?)0k^*6iDLN}uY zo1{0t-z7*64?-S}H0|%OItivz7TF~ivC?C#HyNm19-*6RHw(VDgPUB?vo0af0ZUdP z*+GBnuS= aMoaS#N z?@{BeMEfDw36eVW88qW~AtC5N2d(0y+)UO%Nk8yAeSFa2c}A)mvvpK$bX=q)uY>s0 zA2Z4l*`w}ecaFFEn%MaNko6Wobv41Z@FBQ+a1ZVW_uvF~OMnD|26uONcXyZI?(Pya zxRc=S|0dtP|9e%BqJXoRJw83FS9j02k&E8n8m*iTt*qNfPQr84;>Z_3r>VFw eOZ{A$KDERiE6{KATP_mWC}Xr12|9{#7Pj+!diMcg;Y@NS;*Z<-`eKp&|& zt;I}CFk1K5!xxtD;qRsF7fTvr_bYYLjjd1!(o!k9EFuo>wbp5;CIqkgnM;vTdmLsf zMAK!VqwvPy!@3VtGnRG-zHM_U;UVAcwbO`l%JS$b_1Rhs*&d08J4EREMQ6yB#koSZ zx&LU`!`dNG#wi5X=&@8KtKvfW-NgUZUX;LW{_?e S5> X7R6PNk`79Xixvm z{m}qzg9OFPg;!PW62Sz9PvI&u-By&1!3X_W_zOip9T0n#HLBfHbgi`%D0`<`w2JR{ zi@;2&3(J|(uEd8+AL=tk-p9yRAFGvADPzZjsq&_;OY(~-e!r9ghh7vsRaTA!v#8nQ zD)_BGB%~FAxr6Jh6}vBD)%67ufZGEkP%6@OvPMRs+w#MmwY%TPn~q#lwfH_{Nz-4b zEb*%6kxMA$vl<8_ THH)+7{@C~6(3a1OL5eSRM%bX zn5PM>i8VFhPBiS@nw^VS&mK^Zbp15bRczqNMJk{A%Zi>!J(8_FyTPhu38GQz2y7UJ zq`NcFuJ5qEL4uG2a4v)}Bs}5O$vE8Jl U zd*hQWB!^D6Z_tU?!}+cA9=d2PkC~vEnf}|7 b*)bpMClMx=cd9 z3!*2rZek*N7i0%eN(1lgtU;$APmiGfB$J??RsK6wKhk6=-0KD9m+$L2$1h}QbqE(j zj#+Zw&O!nR(A>^nL$FKE;mMzry-jHcXaJDjL8Ebd<22cj9{$Q)TNfz _&5Ew8rwi$N2E6kFdak9gv(iuf@=O9X;jz2)Bu_K=ScsnZ$>FcCLVs+| zZvPCuR%dCh7h7!M9#)h&o=MF2mE><<_A|RbCYIJFwcF>gUg^RXxu2D3s+Zv4O?3&M zwRRc%t;_LO+(#85R_UtO@>^In#bqTjzTDCIqVbE23fEi|q-LquKH_2LEuJzlW}ZM6 zEq<2j+bH57RDz?mjdu$`6KF@W;GlN|u1?i!-uMs-BNPMOY0EqU0h~khrvIh jKp_r5gyIb-UY K~~U=i`m!0d`8|=ql?pL_Ae?>q19==a3R04h 0MF*k`0u~Ucxr z1~3t?V)QdH;b;0bJ%t+(3WI zK7{aroC}-9SyIesUfxZXh~*ON+iXN=K!E^t{ZX`OaA|7Z+PND@*Ycx?(DZ`bFiZ_# zOEv`1^c!CQEDwO_J+!8csw($40<=aSVE7f8UF&fI$1~c$Z-+ zV`_1)CQs$^el{X@F$&-%Pxji&D!d{L+?HC=oGIk#+^uFgR4tCgN??u2 z+1n%wnglbTSb_hS3;2w>-46lWBqbi;^LmI1Yf#i$zx!fUc)mV5w_v|*NidSp($`ie zouD&B)wr1!U}wx+lf|$9 Z}fatyQ4WhGc~z=JAry?gq^E zXw)Gpb8;JJKB(^g$LMJok-;LvN&pZ;*|bWQq(2-lQt^fQ%@RoOES+
8!+~7)@-oOS(i()N<2%R;c`68P@0~s_noJ|G(uCNNnb<+ z;~WACNX({$(gI?222+X^mzDPo@?4g`7nw=vGu)p}{#{S`>+xEYqdz#!ZuIcEl#+mK z00Q(bxCeYOqfx4R+$>*l50TN#$vE^kEy9jEIrDRlZcC0U_ez#=iFD7P*x9#kciH$e zy!i }LW}t`8ZnI>#zl 2-Cig!WDz_<|76|CZx6r?9 zG{#fV{fe5d??!c=pyuycEd2W0U5cX#adP%CZg(uY()|Xz!39d_XVKZz$j0}V2)78) z){Co~Z3SjLzJ|WXEFfFth|o^D=`}op;ZBa;WZY397lPYePBo* ~v^!l;4T-+=+)achb*NI*B7x?0)^&PONw+akcw9=2En>BW!%KZEv=1M^%f zhh$37n{*KJbZi@7IM!382CKkE^w|#QBE@b=R-TOQ&l_>$T__<&^Vnx`Q;S%lx!K*m zqPMVvg`sWN5c=M%UoVnHhJ;<7&^)(i@ODzo;m2sFKyTC5c`0#-yEtXZ&jjYoJK1*T z1fJv(N7LS{N%EDbp9T-MtIN6Xp?!QqDUtSYp+Vl>P`xicxA$hSZXP7CjHb&Q2Qz_T zD43R|CLFS+&~dIl_pUg6HY^%i{i@Y_X^c6%Cz*dz){dK*J=HQ=x_ X2%@}1`1lX FT1S}Juv$XRmJ}S;3d2PW0rEr|O%D2&%q{#{QNDFs1lBuN6c319IN_MlzVccb zHxTf5txvC+Z)fj4^@_0!k=3kje!qIjRr|<%eTXQV;^T6`*>nDVzeamaq#q-E|BXQN zUhl15<_2hZ3ts!NcKhk^F}nKs@8usXF-zIF!gw+{SiAF;Hh4JljNv9(7|N7W!qvp^ zOb(Hb18@`Y6-2l)3)4T96z!_faZFwk7HQs_A+I{Oz~myCAtO)FwIBj%?+55meb?D= zB`VYj%Hk2^p*nxyli%@RPP)8*8mCCUCH`*Q@nfx2-vezyii?=NJjNO(7wrw~!G1q$ zRUk5Zp{!Ly>;z}D@5~odF8|Hp=oE>nJLAurFHS&|XXV$L$X{g9aJ8ukx9uLT7CE~N zg{B^z+1QW&kyuSvZ*53B&!ALddN$>k_vId6n+;a=Y_QJEWAiWGyHs}EZiqIRXXx)z zJcF%BbU8#LuD40CWa-xvz{0p=M(6eGHp$nw8Lu)SNp>VH5Y%0d%&+#(Zz m{fz=VSuwn+y(pdcM$G&wt$}gjh2WWB&PS)zL)g z2lO22hBrXzp5cGPd<=~I>-y4sdSz@2cjmt(U@ZM2C6n%Dx4W*j+xi07`QQ+#P*=w~ zI;Yu&ze;KBJsHMkisQel;JsP$iq9BremY@>a!$C|#zFLYrgwaZ-cwk0ciE% Cm#6z#;ExG2pM-W3F*HIq6rp8J70t$1AzL z;Bya`#PJ6-$gp^F<9^-V-JalKzkha T3^LCo5i!$(I?{8H=SJVi-NuRF^*UuAy z2X**xHXBaA)VfnreO8X%TAwuI9mE8B7BmNVlVt1u KOrR{a9CLXdL#LCL2r{INIp&l=PXi_w2K94lL!iuASVoe zHKAH|F4;0%UEKQz_ZP*kqOZYucp^P8A566+pzD92&*ULPT>EXhNCX_RywT>&Ab>T@ zW*E0Tz?*B}`6VRMQWs9R6aXkIk_jQI97k!g>^10DE$RU#bDQ0a1GmcJ2XLSc|Bl#X zZW9Rr)dT}m<2qM|e;s4n%*W1`Zy?Y8_|+it%G6V3@?wtRdFl7hyp#kU%IR%aG?06Um)B4M$JmcRpk{ZtZ@Np94T!G^ z(J~fPBo=Y3>-wQLSx@>Hh|w37@VvU#0JIk=Q)m}2zbt`xtaL(>xrY0M@xcNiL{HxL z%k>F`YFPhF119Eg1_LZHFF}O`GKo}IQEa?&3+w`gQD8xL_FI=kSAhfVEoh%VA*+ ZNTPvA{uB+EU30>y@-k!16`!YSBgUU>2ayF=OTIsIO(whDFxb)HU$c# zN6wjQ!f{stz{rn%+m6`4ycJuDL3&OxugpE#TKU{`A^i??=EN=d*y$#Voq#k7#&3JX zduvh0ySF*Il`M_S9?$~uG0sPKqDK@=70JbMMDXKZM}2=A&8 k@XfiRUt z77;mV&8keZd967Pp8JQTCDe&b$H7N>jbp*PptNg=-Y&Y^(XF`dQ>FX)4JS+qO=-#( zx@NTwU)c3tql6+UY`Ch$9d(hsAj5<-KAF<{1OgZ;7@=Mp1Q=>LZ2p(>(3etr?G9fH z+Zy*swaRflq9=Z1a*!q !cV8s*%^2bIYjw#D^8k^BCrb{aS3V0?OrmE{9aiC#>afC zz<4)i-J_aXAK;aWBGC{(F+`9+bzWZJCBB!}*qBz Q|CK z_OT5SaB#lc;JQhpIS`jNlyvn`vG9HQ#H{N&JS+2Anck6@o5nCNN$6UN)4{RBGF=Tb z=N+XQ&uJF#eSlLE62X*Ep;j# ^!`o8RJF+s6 I_YIu0>CHfH4b)%{T?zyqS#kj)tNUlDgDMK16v;%?yMuN=SIyYQg zO)<}1ixw{anmQ>?$Gt3pISa+@=OQR13GW|ImHc2U?mVBpI`1PN_Q#umGwgt^{q@ay zdS<|6WSrG$E&Q`&M%Ya_K~0VC=D0{8D@`Jz&ErYV@&2&=_wgf&6eq_AX#cfsO3)oD ze9Z@@(i%y1cDNZ$B-a3C@$JG#qum`GMY22(5nuJP_Vl `PG2ku(eBxAGw zMbEMO(Xqg1h#VWKsA9$K$EZXmz4jZD1wAg)F^7bNgjUoSGDBy_8$XM!?cym~xyf&h z@eXFh!_6=IdVF
ZYNt_S|G({7DP%cxGsys*a$$#(FJ}!x%Rql*n!t>3_L^ zTmhPQ-tP|T#_B!JM86=9?oOgT+kkV|M%FH`zYr X)?>2>#x~&8t$E*Th|LHC#zuy*~V<(;7K&})m#VVBF+#Z(O!ywSnD^;8~ULJ z-_aR-M2dqElya91TihEraoRnt-Pe6Ixi`3773~{_Lktadvp;zntikkqyejmPj>=Vp z-`00@jGD-BBzdA}+z6dR|2dPZb@dcv #L z-iD7IkTY&EK#1#HBKtV7Dw ^bP-shX9dI1 ~WBFpBeLXqC02a1UNU;?Bx#iMXmbz`*dU+6pe(*?L7P|@vNb^ zuyye40%wLS&&Q+CyIh6b-)Ugedy(&SH-)m=Jl0nu7x_;FFx9P5cF>fThJ^_PMH^{U zfJnt=)N@C!P^M0@6zrwBPyL+9Ov}W?FvQ#vtAOQg_$#!7Dp9Qj+e5Bgx`GoA+g*;~ zc{kU>Hb571^fFvKPrXu$T(_0M_@Z13W481 *hbROYi=K_mE|~JL@-FX;97d z!T*S6@Ri@5d=~)2-Vgui#ALYK>F8WAuwc4W!l?uqSGF^INA&Jz5Z Uj|^ zm5Zl24g(|Tz!7NsbYr)=Zgia1oAg_ V=oy(mS3*XAu`W~J`}34y?cthvMchl z=hd;M0Xnb67af4huLe)`+n@Uz>R#?2V?1z}^l;hCk?7l`{RJ*GMoKP=Do@<5JA`iW zz8kcC9_Z8ibyym v(p^++;Yojb0nt!r;qK> z8208U%ae6>2v1Ie;yDhqq1M+}T>RT5EHr(7{9YPW*I}2dSX1pa^O>TDTouXfr00I; zW_ZPGU0vHUbB9(F$9;Q Aq@7-5NR}Yu9D65LacPMw7u0*k~AX5y8ONfm?qad``jnYZq67g8ez2@wLCsceW*tx%t zo>Wl4pwKfhGBGkwcE;i?kVgVKRQgP8?19lZvtd3uV9~;S(|%rphQE(>Dt~1;2+95e zXVttwa78$IdpccJTz7YMKMQQkjt=YHbt?8$&*j>bs`hGXYF-)lpY!I^<@r{tBs(qK z8XYX1 G>8&}i+5~jIqlWPi4D>Fa0*bestZ%E9XNN_ X>YknwO+kj++$sGX?Cs2g`0uFqoXg0X3aMCD$RuY z 4;!&N4_g3^4y1O=MHwWh+P@6ZPP(vM)?Sb24eeP4Dc z@4x_BIwnh^g;;!HVd1(<6>atR_!!cytV#Wu3Yt=j)es9$4iElUio-&K3I&I+^A%>( z<>EnoD0NmU%G$1@i=V;FdMvnfH^dKYIfiMLo2xtYaLDj7CQGRZ i=ozFX$I@?=}*1KHJnoS!aJ3K=2b}|B!D{)?oijp!I5mnSu08Hl1;?4AT_jXh^5T zBE0)3ia~_8#L%MUsC%=UKB~H!%`2{-CPwFii}b)|YCL+4&EI>v*vUrDkn6U8A{Ncr zkxvpKL4=Os$+Z1+`*~s3ttTfZ2fyBRGRMO#p~dRfGp9R;p;wc{bdy`&ilt7$WW7vg z@ !8?#*EV`crt{j!?F20;vcgx1&L2~$LidgzbYC+DE{dG^v6*`~g zx!!a4Tc*{|0|Si;CQh_}luyfCi}Xg2<`1PuWFmpB_EcKeQ%ShF<4I(`A2Epu3+sK` z^)R36YV>@ra*1CZFWq-2Q$Jh@6F3{HlSxc3;`_&9>4K4_ #KyJ);)rDFmxH4VaFXOf6Yz^s2nt05#{!n-bP|wRLEtaUr@iny @n*Rh*_lzm}>2?*jjOK zGt=rk@d&&j5V1Ob{~lYu#k1$|(pcTSF?J7+?Qct(#A=h}9~e_}e$ZNOe!AXG-XI0E zV}3Lk(lqxB*qsV6zOSfTlq{R<$TqGz{|FH7yzHusGY&9Ti!31KQdLJebaSv2wsbb> z>y8)F?r#W>3@=PNLZ%p;L2L%ZtNO%lm=+Enl|#5Gu}tR{&xAH_1?&aF1^v~o#%+5l zT^gk8&8y9$0w5GDwCmeF53Z?3izCn>gN(l$Vr(=%InnExegG!UJG3_%(cV-vbfmaT z7-YhNl24dTf`bQU<~vA ~?l4Um&Er}u z9_Uo$@oVR+9Qz$@!`bWvqhn^C7fJnPI
48V(Fri5e8CHmL_HCJx$k zHTYBt(fFBg&CQ*QaPT%m)0KN_AgZ~Z?FJ!)1G)ak*3u{C!oF-}moGeAA%JHo`(22p z-As?mfI+=T0fu0G511} ;G}+U(Y3M9jYI|e>y18~ zN}YJtd#7t+b(vYmYoeQ|QI0C%ubm1sd6Vm7_eFm!9_8r1Gpa(eWW0Mjv*mL1PfVO9 zaNCzb1J&sqRu$Oyo(=7h)Kcdg)FUuL7LcrcUVeI|Jbx4gPuGNZ3;dXk+V|*eo1+P@ zOQVOv+!SZ^TCO!0E1rR?IaR7p6y9Nx+G-l>v?ixFdS0Av?DG_i-WEqW?bH0UAxTo% zQEwd2Gm6>|z6PH*?#>#a4$^3JD6$x62%h!}Y`GXlMP+Bwd=@mWxKE(dE51*l)q7Y~ zKG_J)$=m6NegeF4x`=B+PCB}}gOMQ{>2XTOW`CzEQ%DBzjUfT{rJe{F_3n!TH(Y6A zlFi1C%@>HTt$d|wAzG#YN=E~I5))QceOxH~@?xI!Vjfwdso+hZXiD*chv`MHSGs|S zUdt(X4u029Ph3-eY2(eG9xrm2|CCBRC?@GtN#Od^@#p>#sQ3vB+=x&i+krGW ApC-cA`#Zo|m_)9-` Oyr=|5F8BaX()Hkye;kOt}*hF z#p5oKE33Az{EdcU^N5Y;scUjcU(!*N9@~xjg!4wATPdGiv`i7W^{=z35`^7z^LItZ zBz4{mh6 Xf4RUN-YN~YgA#C&a@)GW8`H>peJf0?2-#i;;FXTc628LPa)OV|&My}i| ztGm}iA-o5Z5k@X_pQxhHEEeX==PyGv(_uTEzTze-eVY6#30#rHV|~{=mzOj%iNV|* z%r@oh1O;Wag;ex2KPkF~u79uLts3u;-h{0A@5zz?JkfJ60UvdZm-hl)B;-)2ZQV z4xTfuYGG^Nv ?B88p zw`qfHU9Z(qe+6 Z*x|4wh%Kiv?_vVHJk&(jGgoEOqNvdNa zJ9;E#k+BG&Py*7+?)k`h5~R9GbRfR^Q;zRX)>Ui~j^JA>Ka%=T2?8!Sv*4VJCjn@) z2+m3ea)>S=r4nasM6EtzSEWB9rP#=uv P*5MVITW0~Q2dY03B>NP{K27ov-`|p z>dxd>zL#-S) T2_s&`RZQp^TnF2bR-R3~&OJGgsr^q5zkcsrv zXo~KfqrB^;0ooh=fTjpI%w1vGqktSu|es!y&w$iz*gq} z?QuYz3kpWNxDpabq f&9NrBjbpe%3KnoHbCH2%FeKmnSH z&uIzN{)NShQZ7|6Ok=_cxJ|*nsZ5bYF^WWQl?9w(a3xmrGmG+Ek&Sys{UJ KaJyu=PEK+F-NLj=c_00^#>aQQ{l{gua%nT zivk&75dN9nrzw4;H$DiY0i~Z|c~CZ9;-1G>Ii4B9yt!k}W}PQUv`K5(X!rFs$jPdf zscN-E7Z(rV)$W_Gv=q3={?!|dx<2@oW< o$fFg?2IDW=Z++km6c`C@&A_c^C!5hg)AmHey&pVQRww<`{*0R%tS^+aOjbc zwc>aCxh&XMK+6;R?tJR`Tyc}&OMhX=6G!V`$tkT6_Uq7ByYUkXUWA+D>ED^_QcD3> zBfS=W(~CL!dl%T-QworG7s#sU%_I(dIZH gj=3`-}&O5L%`ww7l;<&7rGm_6 Tco55>+y6(Bkb+=nYSnm6o<7$CS)MV*=bKE$i~cZ_{#c2A|#D>Goj0f{oI* zaa&%;6aMRo)^G^}30K!nVaO6ro13dc2)`;6WO$B{t$^PRpRKnl;+S=sNS#XA>FTvB zrp@5L1)`9+Sihd0pEF{v)c@;^ZGB*Acn^@#g?nr=IqtPmMI|E4TnOJ?!*ua{BMX=A zpMGJ4ke(^{+&J^|=hf9^-eBbF?TQt=1!mlGqejWxTrn5{HK)3~)G$rG#Oqo7ctWT3 z=9nwHwA6NG^7Br>mlo%9zgM@Fhy55)FR6imaHKL7OTN!j&|ZJnfiQCj$W*B=V(j*U zp;iK1hS6HOT; ^L@p7XVLIRxT37zRHZ z(!-bWpTZT-!6zDRmKGsDyP3_sdZ9Y+!9~R!eKJ4