From 441111f49d39ad5a184eca51061882ff7c966dd9 Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Thu, 5 Nov 2026 08:32:36 +0800 Subject: [PATCH 01/10] =?UTF-8?q?=E5=B7=A5=E5=85=B7(=E4=B8=89=E5=85=B3?= =?UTF-8?q?=E8=89=B2=E7=9B=B8=E6=8A=BD=E6=B5=8B=20S1/S2):=20=E5=B9=B6?= =?UTF-8?q?=E5=88=97=E6=A0=B7=E5=9B=BE=E8=84=9A=E6=9C=AC=E8=90=BD=E5=9C=B0?= =?UTF-8?q?=E2=80=94=E2=80=94S1=20=E6=9C=BA=E6=A3=80=20D=20=E4=B8=89?= =?UTF-8?q?=E5=85=B3=20H2=20=E6=A7=BD=E5=85=A8=E8=BF=87(L=200.346/0.532/0.?= =?UTF-8?q?345)=E3=80=81S2=20=E6=A0=B7=E5=9B=BE=E6=9C=BA=E6=A3=80=2017=20?= =?UTF-8?q?=E9=A1=B9=E5=85=A8=E7=BB=BF(=E9=98=B6=E6=A2=AF=E5=8D=95?= =?UTF-8?q?=E8=B0=83=209=20=E7=BB=84=E3=80=81=E7=BB=84=E9=97=B4=20CR=20?= =?UTF-8?q?=E6=9C=80=E5=BC=B1=201.224=E2=89=A51.20=E3=80=81B/C=2045=20?= =?UTF-8?q?=E8=A1=8C=E9=9B=B6=E8=BF=9D=E4=BE=8B=E3=80=81=E7=81=B0=E5=BA=A6?= =?UTF-8?q?=E9=9B=B6=E5=BD=A9=E8=89=B2=E3=80=81=E5=9B=9B=E7=BC=98=E5=87=80?= =?UTF-8?q?=E7=A9=BA)=EF=BC=9B=E6=A8=A1=E5=9E=8B=E5=8F=A3=E5=BE=84?= =?UTF-8?q?=E8=AE=A2=E6=AD=A3=3Dshader=20=E7=B2=BE=E7=A1=AE=E5=90=88?= =?UTF-8?q?=E6=88=90(=E6=96=B9=E6=A1=88=200.49/0.51=20=E7=B3=BB=E5=8F=8D?= =?UTF-8?q?=E8=A7=A3=E8=BF=91=E4=BC=BC,ui=5Fkit=20=E5=A4=B4=E6=B3=A8?= =?UTF-8?q?=E6=98=8E=E6=96=87=E8=B7=9D=E7=A6=BB=E5=9C=BA=E9=9D=9E=E6=89=81?= =?UTF-8?q?=E5=B9=B3)=E3=80=81=E8=A1=A8=E4=BA=8C=E8=A1=8C=E6=95=B0?= =?UTF-8?q?=E8=AE=A2=E6=AD=A3=2090=20=E8=A1=8C=EF=BC=9B=E8=AF=BB=E6=95=B0?= =?UTF-8?q?=E8=A1=A8=E8=90=BD=20reports/?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- reports/读数-三关色相互辨抽测-2026-11-05.md | 186 ++++++++ tools/glow_discrimination_sheet.py | 444 ++++++++++++++++++++ 2 files changed, 630 insertions(+) create mode 100644 reports/读数-三关色相互辨抽测-2026-11-05.md create mode 100644 tools/glow_discrimination_sheet.py diff --git a/reports/读数-三关色相互辨抽测-2026-11-05.md b/reports/读数-三关色相互辨抽测-2026-11-05.md new file mode 100644 index 00000000..db50e709 --- /dev/null +++ b/reports/读数-三关色相互辨抽测-2026-11-05.md @@ -0,0 +1,186 @@ +# 读数:三关色相 × 五组微光互辨抽测(2026-11-05) + +> 接收方:待办清单「三关色相 × 五组微光互辨抽测——三关图类型色板终值冻结的前置抽测」条。 +> 执行依据:reports/提案-三关色相互辨抽测方案-2026-10-29.md(S1/S2 步)。 +> 样图:artwork/mockups/glow-discrimination-sheet-2026-11-05.png(不入 git)。 + +## 机检汇总 + +| 项 | 判定 | 说明 | +|---|---|---| +| D-dungeon | PASS | 铺底代表值门(L/饱和/禁入带;近色只报读数):RGB=(181, 155, 119) L=0.346 饱和=0.343 色相=34.8° 近色对=4(在役素材色,非新增) | +| D-underdark | PASS | 铺底代表值门(L/饱和/禁入带;近色只报读数):RGB=(186, 193, 210) L=0.532 饱和=0.114 色相=222.5° 近色对=4(在役素材色,非新增) | +| D-deep_underdark | PASS | 铺底代表值门(L/饱和/禁入带;近色只报读数):RGB=(150, 158, 186) L=0.345 饱和=0.194 色相=226.7° 近色对=9(在役素材色,非新增) | +| A-stair-dungeon-素砖 | PASS | 明度阶梯单调递减:165.242→145.992→130.196→114.266→92.362 | +| A-stair-dungeon-裂纹 | PASS | 明度阶梯单调递减:165.242→145.992→130.196→114.266→92.362 | +| A-stair-dungeon-碎石斑 | PASS | 明度阶梯单调递减:164.957→144.992→129.269→113.266→91.434 | +| A-stair-underdark-素砖 | PASS | 明度阶梯单调递减:161.080→141.829→125.179→109.389→87.485 | +| A-stair-underdark-裂纹 | PASS | 明度阶梯单调递减:164.152→144.902→129.106→112.461→90.557 | +| A-stair-underdark-碎石斑 | PASS | 明度阶梯单调递减:158.152→138.829→123.106→106.461→84.557 | +| A-stair-deep_underdark-素砖 | PASS | 明度阶梯单调递减:145.437→126.186→109.748→93.746→71.914 | +| A-stair-deep_underdark-裂纹 | PASS | 明度阶梯单调递减:147.509→128.259→112.536→95.818→73.986 | +| A-stair-deep_underdark-碎石斑 | PASS | 明度阶梯单调递减:142.509→123.186→106.748→90.746→68.914 | +| A-CR | PASS | 组间合成对比最弱对 ≥1.20(90 对):最弱 underdark/HEAL/PIERCE CR=1.224 | +| B | PASS | 格底-微光可辨底线(45 行三通道差不全<8):违例 0 行:无 | +| C | PASS | 绘制参数校准(45 行模型差≤±2/255):违例 0 行:无 | +| GRAY | PASS | 灰度副本段零彩色像素:命中 0 | +| EDGE | PASS | 四缘 10px 带内零内容像素:命中 0 | + +## S1 机检 D:铺底代表值(H2 槽)五门 + +| 关 | RGB | L(线性域) | 饱和 | 色相 | 近色对 | 判定 | +|---|---|---|---|---|---|---| +| dungeon | (181, 155, 119) | 0.346 | 0.343 | 34.8° | 4 | 过 | +| underdark | (186, 193, 210) | 0.532 | 0.114 | 222.5° | 4 | 过 | +| deep_underdark | (150, 158, 186) | 0.345 | 0.194 | 226.7° | 9 | 过 | + +## 表一 逐对表(45 行) + +| 关 | 底型 | 微光组 | 带内合成均值 | 格心素底均值 | 模型带内均值 | 模型差 | 三通道差 | 色相差° | 判定 | +|---|---|---|---|---|---|---|---|---|---| +| dungeon | 素砖 | BUFF | (193, 166, 76) | (145, 116, 84) | (193, 166, 76) | 0 | [48, 50, 8] | 17 | 过 | +| dungeon | 素砖 | HEAL | (126, 159, 76) | (145, 116, 84) | (126, 159, 75) | 1 | [19, 43, 8] | 69 | 过 | +| dungeon | 素砖 | PIERCE | (100, 140, 122) | (145, 116, 84) | (100, 140, 122) | 0 | [45, 24, 38] | 145 | 过 | +| dungeon | 素砖 | MAGIC | (135, 105, 145) | (145, 116, 84) | (135, 105, 145) | 0 | [10, 11, 61] | 139 | 过 | +| dungeon | 素砖 | AOE | (155, 76, 70) | (145, 116, 84) | (155, 76, 70) | 0 | [10, 40, 14] | 46 | 过 | +| dungeon | 裂纹 | BUFF | (193, 166, 76) | (143, 115, 83) | (193, 166, 76) | 0 | [50, 51, 7] | 17 | 过 | +| dungeon | 裂纹 | HEAL | (126, 159, 76) | (143, 115, 83) | (126, 159, 76) | 0 | [17, 44, 7] | 69 | 过 | +| dungeon | 裂纹 | PIERCE | (100, 140, 122) | (143, 115, 83) | (100, 140, 122) | 0 | [43, 25, 39] | 145 | 过 | +| dungeon | 裂纹 | MAGIC | (135, 105, 145) | (143, 115, 83) | (135, 105, 145) | 0 | [8, 10, 62] | 139 | 过 | +| dungeon | 裂纹 | AOE | (155, 76, 70) | (143, 115, 83) | (155, 76, 70) | 0 | [12, 39, 13] | 46 | 过 | +| dungeon | 碎石斑 | BUFF | (192, 166, 75) | (147, 118, 85) | (192, 166, 75) | 0 | [45, 48, 10] | 17 | 过 | +| dungeon | 碎石斑 | HEAL | (125, 158, 75) | (147, 118, 85) | (125, 159, 75) | 1 | [22, 40, 10] | 69 | 过 | +| dungeon | 碎石斑 | PIERCE | (99, 139, 122) | (147, 118, 85) | (99, 139, 122) | 0 | [48, 21, 37] | 145 | 过 | +| dungeon | 碎石斑 | MAGIC | (134, 104, 144) | (147, 118, 85) | (134, 104, 144) | 0 | [13, 14, 59] | 139 | 过 | +| dungeon | 碎石斑 | AOE | (154, 75, 70) | (147, 118, 85) | (154, 75, 70) | 0 | [7, 43, 15] | 46 | 过 | +| underdark | 素砖 | BUFF | (172, 164, 100) | (104, 110, 128) | (172, 164, 100) | 0 | [68, 54, 28] | 170 | 过 | +| underdark | 素砖 | HEAL | (105, 157, 100) | (104, 110, 128) | (105, 157, 100) | 0 | [1, 47, 28] | 119 | 过 | +| underdark | 素砖 | PIERCE | (78, 137, 147) | (104, 110, 128) | (78, 137, 147) | 0 | [26, 27, 19] | 42 | 过 | +| underdark | 素砖 | MAGIC | (114, 102, 169) | (104, 110, 128) | (114, 102, 169) | 0 | [10, 8, 41] | 33 | 过 | +| underdark | 素砖 | AOE | (134, 73, 94) | (104, 110, 128) | (134, 73, 95) | 1 | [30, 37, 34] | 126 | 过 | +| underdark | 裂纹 | BUFF | (175, 167, 104) | (113, 120, 137) | (175, 167, 104) | 0 | [62, 47, 33] | 170 | 过 | +| underdark | 裂纹 | HEAL | (108, 160, 104) | (113, 120, 137) | (108, 160, 104) | 0 | [5, 40, 33] | 119 | 过 | +| underdark | 裂纹 | PIERCE | (82, 141, 150) | (113, 120, 137) | (82, 141, 150) | 0 | [31, 21, 13] | 42 | 过 | +| underdark | 裂纹 | MAGIC | (117, 105, 173) | (113, 120, 137) | (117, 105, 173) | 0 | [4, 15, 36] | 33 | 过 | +| underdark | 裂纹 | AOE | (137, 76, 98) | (113, 120, 137) | (137, 76, 98) | 0 | [24, 44, 39] | 126 | 过 | +| underdark | 碎石斑 | BUFF | (169, 161, 98) | (124, 131, 149) | (169, 161, 98) | 0 | [45, 30, 51] | 170 | 过 | +| underdark | 碎石斑 | HEAL | (102, 154, 97) | (124, 131, 149) | (102, 154, 97) | 0 | [22, 23, 52] | 119 | 过 | +| underdark | 碎石斑 | PIERCE | (76, 135, 144) | (124, 131, 149) | (76, 135, 144) | 0 | [48, 4, 5] | 42 | 过 | +| underdark | 碎石斑 | MAGIC | (111, 99, 167) | (124, 131, 149) | (111, 99, 167) | 0 | [13, 32, 18] | 33 | 过 | +| underdark | 碎石斑 | AOE | (131, 70, 92) | (124, 131, 149) | (131, 70, 92) | 0 | [7, 61, 57] | 126 | 过 | +| deep_underdark | 素砖 | BUFF | (157, 148, 86) | (76, 80, 102) | (157, 148, 86) | 0 | [81, 68, 16] | 175 | 过 | +| deep_underdark | 素砖 | HEAL | (90, 141, 86) | (76, 80, 102) | (90, 141, 86) | 0 | [14, 61, 16] | 123 | 过 | +| deep_underdark | 素砖 | PIERCE | (64, 121, 133) | (76, 80, 102) | (64, 121, 133) | 0 | [12, 41, 31] | 47 | 过 | +| deep_underdark | 素砖 | MAGIC | (99, 86, 155) | (76, 80, 102) | (99, 86, 155) | 0 | [23, 6, 53] | 29 | 过 | +| deep_underdark | 素砖 | AOE | (119, 57, 81) | (76, 80, 102) | (119, 57, 81) | 0 | [43, 23, 21] | 122 | 过 | +| deep_underdark | 裂纹 | BUFF | (159, 150, 89) | (84, 89, 111) | (159, 150, 89) | 0 | [75, 61, 22] | 175 | 过 | +| deep_underdark | 裂纹 | HEAL | (92, 143, 89) | (84, 89, 111) | (92, 143, 89) | 0 | [8, 54, 22] | 123 | 过 | +| deep_underdark | 裂纹 | PIERCE | (66, 124, 136) | (84, 89, 111) | (66, 124, 136) | 0 | [18, 35, 25] | 47 | 过 | +| deep_underdark | 裂纹 | MAGIC | (101, 88, 158) | (84, 89, 111) | (101, 88, 158) | 0 | [17, 1, 47] | 29 | 过 | +| deep_underdark | 裂纹 | AOE | (121, 59, 84) | (84, 89, 111) | (121, 59, 84) | 0 | [37, 30, 27] | 122 | 过 | +| deep_underdark | 碎石斑 | BUFF | (154, 145, 84) | (91, 97, 121) | (154, 145, 83) | 1 | [63, 48, 37] | 175 | 过 | +| deep_underdark | 碎石斑 | HEAL | (87, 138, 83) | (91, 97, 121) | (87, 138, 83) | 0 | [4, 41, 38] | 123 | 过 | +| deep_underdark | 碎石斑 | PIERCE | (61, 118, 130) | (91, 97, 121) | (61, 118, 130) | 0 | [30, 21, 9] | 47 | 过 | +| deep_underdark | 碎石斑 | MAGIC | (96, 83, 152) | (91, 97, 121) | (96, 83, 152) | 0 | [5, 14, 31] | 29 | 过 | +| deep_underdark | 碎石斑 | AOE | (116, 54, 78) | (91, 97, 121) | (116, 54, 78) | 0 | [25, 43, 43] | 122 | 过 | + +## 表二 组间表(90 行) + +| 关 | 底型 | 组对 | 合成对比 | 灰度亮度a | 灰度亮度b | 判定 | +|---|---|---|---|---|---|---| +| dungeon | 素砖 | BUFF/HEAL | 1.270 | 165.242 | 145.992 | 过 | +| dungeon | 素砖 | BUFF/PIERCE | 1.583 | 165.242 | 130.196 | 过 | +| dungeon | 素砖 | BUFF/MAGIC | 1.979 | 165.242 | 114.266 | 过 | +| dungeon | 素砖 | BUFF/AOE | 2.510 | 165.242 | 92.362 | 过 | +| dungeon | 素砖 | HEAL/PIERCE | 1.247 | 145.992 | 130.196 | 过 | +| dungeon | 素砖 | HEAL/MAGIC | 1.559 | 145.992 | 114.266 | 过 | +| dungeon | 素砖 | HEAL/AOE | 1.977 | 145.992 | 92.362 | 过 | +| dungeon | 素砖 | PIERCE/MAGIC | 1.250 | 130.196 | 114.266 | 过 | +| dungeon | 素砖 | PIERCE/AOE | 1.585 | 130.196 | 92.362 | 过 | +| dungeon | 素砖 | MAGIC/AOE | 1.268 | 114.266 | 92.362 | 过 | +| dungeon | 裂纹 | BUFF/HEAL | 1.270 | 165.242 | 145.992 | 过 | +| dungeon | 裂纹 | BUFF/PIERCE | 1.583 | 165.242 | 130.196 | 过 | +| dungeon | 裂纹 | BUFF/MAGIC | 1.979 | 165.242 | 114.266 | 过 | +| dungeon | 裂纹 | BUFF/AOE | 2.510 | 165.242 | 92.362 | 过 | +| dungeon | 裂纹 | HEAL/PIERCE | 1.247 | 145.992 | 130.196 | 过 | +| dungeon | 裂纹 | HEAL/MAGIC | 1.559 | 145.992 | 114.266 | 过 | +| dungeon | 裂纹 | HEAL/AOE | 1.977 | 145.992 | 92.362 | 过 | +| dungeon | 裂纹 | PIERCE/MAGIC | 1.250 | 130.196 | 114.266 | 过 | +| dungeon | 裂纹 | PIERCE/AOE | 1.585 | 130.196 | 92.362 | 过 | +| dungeon | 裂纹 | MAGIC/AOE | 1.268 | 114.266 | 92.362 | 过 | +| dungeon | 碎石斑 | BUFF/HEAL | 1.282 | 164.957 | 144.992 | 过 | +| dungeon | 碎石斑 | BUFF/PIERCE | 1.598 | 164.957 | 129.269 | 过 | +| dungeon | 碎石斑 | BUFF/MAGIC | 2.001 | 164.957 | 113.266 | 过 | +| dungeon | 碎石斑 | BUFF/AOE | 2.536 | 164.957 | 91.434 | 过 | +| dungeon | 碎石斑 | HEAL/PIERCE | 1.247 | 144.992 | 129.269 | 过 | +| dungeon | 碎石斑 | HEAL/MAGIC | 1.561 | 144.992 | 113.266 | 过 | +| dungeon | 碎石斑 | HEAL/AOE | 1.979 | 144.992 | 91.434 | 过 | +| dungeon | 碎石斑 | PIERCE/MAGIC | 1.252 | 129.269 | 113.266 | 过 | +| dungeon | 碎石斑 | PIERCE/AOE | 1.587 | 129.269 | 91.434 | 过 | +| dungeon | 碎石斑 | MAGIC/AOE | 1.267 | 113.266 | 91.434 | 过 | +| underdark | 素砖 | BUFF/HEAL | 1.248 | 161.080 | 141.829 | 过 | +| underdark | 素砖 | BUFF/PIERCE | 1.549 | 161.080 | 125.179 | 过 | +| underdark | 素砖 | BUFF/MAGIC | 1.969 | 161.080 | 109.389 | 过 | +| underdark | 素砖 | BUFF/AOE | 2.637 | 161.080 | 87.485 | 过 | +| underdark | 素砖 | HEAL/PIERCE | 1.241 | 141.829 | 125.179 | 过 | +| underdark | 素砖 | HEAL/MAGIC | 1.577 | 141.829 | 109.389 | 过 | +| underdark | 素砖 | HEAL/AOE | 2.112 | 141.829 | 87.485 | 过 | +| underdark | 素砖 | PIERCE/MAGIC | 1.271 | 125.179 | 109.389 | 过 | +| underdark | 素砖 | PIERCE/AOE | 1.702 | 125.179 | 87.485 | 过 | +| underdark | 素砖 | MAGIC/AOE | 1.339 | 109.389 | 87.485 | 过 | +| underdark | 裂纹 | BUFF/HEAL | 1.245 | 164.152 | 144.902 | 过 | +| underdark | 裂纹 | BUFF/PIERCE | 1.524 | 164.152 | 129.106 | 过 | +| underdark | 裂纹 | BUFF/MAGIC | 1.952 | 164.152 | 112.461 | 过 | +| underdark | 裂纹 | BUFF/AOE | 2.612 | 164.152 | 90.557 | 过 | +| underdark | 裂纹 | HEAL/PIERCE | 1.224 | 144.902 | 129.106 | 过 | +| underdark | 裂纹 | HEAL/MAGIC | 1.567 | 144.902 | 112.461 | 过 | +| underdark | 裂纹 | HEAL/AOE | 2.097 | 144.902 | 90.557 | 过 | +| underdark | 裂纹 | PIERCE/MAGIC | 1.280 | 129.106 | 112.461 | 过 | +| underdark | 裂纹 | PIERCE/AOE | 1.713 | 129.106 | 90.557 | 过 | +| underdark | 裂纹 | MAGIC/AOE | 1.338 | 112.461 | 90.557 | 过 | +| underdark | 碎石斑 | BUFF/HEAL | 1.252 | 158.152 | 138.829 | 过 | +| underdark | 碎石斑 | BUFF/PIERCE | 1.538 | 158.152 | 123.106 | 过 | +| underdark | 碎石斑 | BUFF/MAGIC | 1.981 | 158.152 | 106.461 | 过 | +| underdark | 碎石斑 | BUFF/AOE | 2.658 | 158.152 | 84.557 | 过 | +| underdark | 碎石斑 | HEAL/PIERCE | 1.229 | 138.829 | 123.106 | 过 | +| underdark | 碎石斑 | HEAL/MAGIC | 1.583 | 138.829 | 106.461 | 过 | +| underdark | 碎石斑 | HEAL/AOE | 2.123 | 138.829 | 84.557 | 过 | +| underdark | 碎石斑 | PIERCE/MAGIC | 1.288 | 123.106 | 106.461 | 过 | +| underdark | 碎石斑 | PIERCE/AOE | 1.728 | 123.106 | 84.557 | 过 | +| underdark | 碎石斑 | MAGIC/AOE | 1.341 | 106.461 | 84.557 | 过 | +| deep_underdark | 素砖 | BUFF/HEAL | 1.265 | 145.437 | 126.186 | 过 | +| deep_underdark | 素砖 | BUFF/PIERCE | 1.585 | 145.437 | 109.748 | 过 | +| deep_underdark | 素砖 | BUFF/MAGIC | 2.040 | 145.437 | 93.746 | 过 | +| deep_underdark | 素砖 | BUFF/AOE | 2.734 | 145.437 | 71.914 | 过 | +| deep_underdark | 素砖 | HEAL/PIERCE | 1.253 | 126.186 | 109.748 | 过 | +| deep_underdark | 素砖 | HEAL/MAGIC | 1.613 | 126.186 | 93.746 | 过 | +| deep_underdark | 素砖 | HEAL/AOE | 2.162 | 126.186 | 71.914 | 过 | +| deep_underdark | 素砖 | PIERCE/MAGIC | 1.287 | 109.748 | 93.746 | 过 | +| deep_underdark | 素砖 | PIERCE/AOE | 1.725 | 109.748 | 71.914 | 过 | +| deep_underdark | 素砖 | MAGIC/AOE | 1.340 | 93.746 | 71.914 | 过 | +| deep_underdark | 裂纹 | BUFF/HEAL | 1.263 | 147.509 | 128.259 | 过 | +| deep_underdark | 裂纹 | BUFF/PIERCE | 1.562 | 147.509 | 112.536 | 过 | +| deep_underdark | 裂纹 | BUFF/MAGIC | 2.028 | 147.509 | 95.818 | 过 | +| deep_underdark | 裂纹 | BUFF/AOE | 2.720 | 147.509 | 73.986 | 过 | +| deep_underdark | 裂纹 | HEAL/PIERCE | 1.237 | 128.259 | 112.536 | 过 | +| deep_underdark | 裂纹 | HEAL/MAGIC | 1.606 | 128.259 | 95.818 | 过 | +| deep_underdark | 裂纹 | HEAL/AOE | 2.154 | 128.259 | 73.986 | 过 | +| deep_underdark | 裂纹 | PIERCE/MAGIC | 1.298 | 112.536 | 95.818 | 过 | +| deep_underdark | 裂纹 | PIERCE/AOE | 1.742 | 112.536 | 73.986 | 过 | +| deep_underdark | 裂纹 | MAGIC/AOE | 1.341 | 95.818 | 73.986 | 过 | +| deep_underdark | 碎石斑 | BUFF/HEAL | 1.268 | 142.509 | 123.186 | 过 | +| deep_underdark | 碎石斑 | BUFF/PIERCE | 1.593 | 142.509 | 106.748 | 过 | +| deep_underdark | 碎石斑 | BUFF/MAGIC | 2.055 | 142.509 | 90.746 | 过 | +| deep_underdark | 碎石斑 | BUFF/AOE | 2.753 | 142.509 | 68.914 | 过 | +| deep_underdark | 碎石斑 | HEAL/PIERCE | 1.256 | 123.186 | 106.748 | 过 | +| deep_underdark | 碎石斑 | HEAL/MAGIC | 1.620 | 123.186 | 90.746 | 过 | +| deep_underdark | 碎石斑 | HEAL/AOE | 2.170 | 123.186 | 68.914 | 过 | +| deep_underdark | 碎石斑 | PIERCE/MAGIC | 1.290 | 106.748 | 90.746 | 过 | +| deep_underdark | 碎石斑 | PIERCE/AOE | 1.728 | 106.748 | 68.914 | 过 | +| deep_underdark | 碎石斑 | MAGIC/AOE | 1.339 | 90.746 | 68.914 | 过 | + +--- + +机检 17 项,FAIL 0 项。 + +目检(S3)归用户:四条判据见方案 §2.2(逐对指认 45/45/灰度副本 45/45/相邻并列 36 对可辨/装饰不抢读)。 diff --git a/tools/glow_discrimination_sheet.py b/tools/glow_discrimination_sheet.py new file mode 100644 index 00000000..d80d8a1f --- /dev/null +++ b/tools/glow_discrimination_sheet.py @@ -0,0 +1,444 @@ +# 三关色相 × 五组微光互辨抽测——S1 取铺底值(机检 D)+ S2 出并列样图(机检 A/B/C)。 +# 执行依据:reports/提案-三关色相互辨抽测方案-2026-10-29.md(抽测任务=待办清单 +# 「三关色相 × 五组微光互辨抽测」条)。产物:并列样图(artwork/,不入 git)+逐对读数表(reports/)。 +# 口径出处(冲突时以 owner 为准): +# 微光色值与呈现参数 = game/presentation/views/ui_kit.gd TG_GLOW_*/TYPE_GLOW_*(v2 冻结); +# 合成公式 = game/presentation/views/cell_type_glow.gdshader(blend_mix 距离场柔光); +# 带域/格心取样 = game/probe/type_glow_shot_probe.gd(de<格边×0.125 / 内缩 20%); +# 硬指标门 = art-bible §4.1(L≥0.30 线性域 / 饱和≤0.55 / 避 300°–345°); +# 既有色板比对池 = game/tests/golden/palette_baseline/ 两张条带并集(palette_check.py 同源)。 +# 方案 §2.3 机检 C 口径订正:模型 0.49/0.51 是反解近似(ui_kit.gd 头注「模型域与实测的差 +# = shader 距离场权重非扁平混合」),比较对象改为 shader 精确合成模型(逐像素复刻),判据线 +# ±2/255 沿用在役值。 +# 方案 §7 表二行数笔误订正:表二实为 90 行(3 关 × 3 底型 × 10 组对),非 30 行。 +# +# 用法: +# python tools/glow_discrimination_sheet.py --art [--no-sheet] +# 输出: +# /glow-discrimination-sheet-2026-11-05.png(样图:正图段+灰度副本段+图例) +# reports/读数-三关色相互辨抽测-2026-11-05.md(逐对表 45 行+组间表 90 行+机检汇总) +import argparse +import math +import os +import sys + +from PIL import Image + +REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + +# ── ui_kit.gd 冻结常量(逐字转写,禁改值)── +GLOWS = [ + ("BUFF", (247, 223, 67)), # 通用增益·芥末黄 + ("HEAL", (104, 208, 66)), # 治疗·黄绿 + ("PIERCE", (48, 166, 166)), # 穿刺·青 + ("MAGIC", (123, 91, 214)), # 魔法·紫罗兰 + ("AOE", (166, 29, 55)), # 群伤·绯红 +] +GLOW_ALPHA = 170.0 / 255.0 +BAND_FRAC = 0.125 +SOFT = 0.55 +CORNER = 2.0 + +CELL = 45 # D 区实比格边 +BAND = CELL * BAND_FRAC # 5.625 +CORE_PAD = int(CELL * 0.20) # 格心内缩(探针 CORE_PAD_FRAC=0.20) + +# ── 三关铺底代表值 = 色表墙顶受光家族最亮槽 H2(tools/recolor_terrain_tiles.py PALETTES)── +H2_VALUES = { + "dungeon": (181, 155, 119), + "underdark": (186, 193, 210), + "deep_underdark": (150, 158, 186), +} +BOARD_TYPES = ["dungeon", "underdark", "deep_underdark"] +BASE_VARIANTS = [ # (底型名,瓦片件名后缀)——素砖 + 两种装饰变体(高墙瓦片词表在册件) + ("素砖", "terrain_wall_center"), + ("裂纹", "terrain_wall_center_crack"), + ("碎石斑", "terrain_wall_center_speckle"), +] + +TILE_DIR = os.path.join(REPO, "game", "assets", "art", "board") +BASELINE_DIR = os.path.join(REPO, "game", "tests", "golden", "palette_baseline") + +CHECKS = [] + + +def check(cid, name, ok, detail=""): + CHECKS.append((cid, name, bool(ok), detail)) + print("[%s] %s %s — %s%s" % ("PASS" if ok else "FAIL", cid, name, "✓" if ok else "✗", + (";" + detail) if detail else "")) + + +# ── 色彩数学 ── +def to_linear(v): + c = v / 255.0 + return c / 12.92 if c <= 0.04045 else ((c + 0.055) / 1.055) ** 2.4 + + +def rel_lum(rgb): + return 0.2126 * to_linear(rgb[0]) + 0.7152 * to_linear(rgb[1]) + 0.0722 * to_linear(rgb[2]) + + +def gray709(rgb): + return 0.2126 * rgb[0] + 0.7152 * rgb[1] + 0.0722 * rgb[2] + + +def hsv(rgb): + r, g, b = [v / 255.0 for v in rgb] + mx, mn = max(r, g, b), min(r, g, b) + d = mx - mn + if d == 0: + h = 0.0 + elif mx == r: + h = 60 * ((g - b) / d % 6) + elif mx == g: + h = 60 * ((b - r) / d + 2) + else: + h = 60 * ((r - g) / d + 4) + s = 0.0 if mx == 0 else d / mx + return h % 360, s + + +def wcag(c1, c2): + l1, l2 = rel_lum(c1), rel_lum(c2) + return (max(l1, l2) + 0.05) / (min(l1, l2) + 0.05) + + +def smoothstep(e0, e1, x): + t = max(0.0, min(1.0, (x - e0) / (e1 - e0))) + return t * t * (3.0 - 2.0 * t) + + +def glow_weight(px, py): + """shader 复刻:像素中心 (px,py) 的微光权重 = glow_alpha × a(d) × mask。""" + h = CELL / 2.0 + d = min(px, py, CELL - px, CELL - py) + r = min(CORNER, CELL * 0.25) + qx = abs(px - h) - (h - r) + qy = abs(py - h) - (h - r) + outside = math.hypot(max(qx, 0.0), max(qy, 0.0)) + min(max(qx, qy), 0.0) - r + mask = 1.0 - smoothstep(-1.0, 0.5, outside) + a = 0.0 + if d < BAND: + a = 1.0 - smoothstep(SOFT, 1.0, d / BAND) + return GLOW_ALPHA * a * mask + + +# ── 素材装载 ── +def load_tiles(): + tiles = {} + for bt in BOARD_TYPES: + for vn, stem in BASE_VARIANTS: + path = os.path.join(TILE_DIR, "%s_%s.png" % (stem, bt)) + if not os.path.exists(path): + print("[阻塞] 素材缺位:%s" % path, file=sys.stderr) + sys.exit(2) + img = Image.open(path).convert("RGB") + if img.size != (CELL, CELL): + img = img.resize((CELL, CELL), Image.NEAREST) + tiles[(bt, vn)] = img.load() + return tiles + + +# ── 带域/格心取样(探针口径)── +def band_pixels(): + """带域像素集(整数格坐标 de < 格边×0.125,type_glow_shot_probe 口径)。""" + return [(x, y) for x in range(CELL) for y in range(CELL) + if min(x, y, CELL - 1 - x, CELL - 1 - y) < BAND] + + +def core_pixels(): + """格心像素集(内缩 20%)。""" + return [(x, y) for x in range(CELL) for y in range(CELL) + if min(x, y, CELL - 1 - x, CELL - 1 - y) >= CELL * 0.20] + + +BAND_PX = band_pixels() +CORE_PX = core_pixels() + + +def mean_rgb(px, pts): + n = len(pts) + return tuple(round(sum(px[x, y][i] for x, y in pts) / n) for i in range(3)) + + +def model_band_mean(base_px, glow_rgb): + """shader 精确合成模型:逐像素 blend_mix 理论带内均值(独立实现路径)。""" + n = len(BAND_PX) + acc = [0.0, 0.0, 0.0] + for x, y in BAND_PX: + w = glow_weight(x + 0.5, y + 0.5) + b = base_px[x, y] + for i in range(3): + acc[i] += w * glow_rgb[i] + (1.0 - w) * b[i] + return tuple(round(v / n) for v in acc) + + +# ── 机检 D:铺底代表值五门 ── +def load_baseline_palette(): + cols = set() + for fn in ["ui_tokens.png", "art_snapshot.png"]: + p = os.path.join(BASELINE_DIR, fn) + img = Image.open(p).convert("RGB") + for x in range(img.width): + for y in range(img.height): + cols.add(img.getpixel((x, y))) + return sorted(cols) + + +def gate_d(tiles): + baseline = load_baseline_palette() + rows = [] + all_pass = True + for bt in BOARD_TYPES: + rgb = H2_VALUES[bt] + h, s = hsv(rgb) + lin = rel_lum(rgb) + l_ok = lin >= 0.30 + s_ok = s <= 0.55 + hue_ok = not (300.0 <= h <= 345.0) + # 近色门:三值=在役素材色(已在基线池内),palette_check 双门②只判新增色——报读数不判红 + near = [b for b in baseline if all(abs(rgb[i] - b[i]) < 8 for i in range(3))] + ok = l_ok and s_ok and hue_ok + all_pass = all_pass and ok + rows.append((bt, rgb, lin, s, h, len(near), ok)) + check("D-" + bt, "铺底代表值门(L/饱和/禁入带;近色只报读数)", ok, + "RGB=%s L=%.3f 饱和=%.3f 色相=%.1f° 近色对=%d(在役素材色,非新增)%s%s%s" + % (rgb, lin, s, h, len(near), + "" if l_ok else " [L红]", "" if s_ok else " [饱和红]", + "" if hue_ok else " [禁入带红]")) + # 语义检查=设计面人工核对(palette_check 同口径),打印读数不判红 + print(" [语义] %s=%s 环境域(不占红/金/蓝/紫赤/绿语义段)——人工核对" % (bt, rgb)) + # 渲染面带域均值 = 读数不判红(方案机检 D 只判槽值;本读数供观感定性参考) + for bt in BOARD_TYPES: + for vn, _ in BASE_VARIANTS: + m = mean_rgb(tiles[(bt, vn)], BAND_PX) + lin = rel_lum(m) + print(" [读数] 渲染面带域均值 %s/%s RGB=%s L=%.3f(不判红)" % (bt, vn, m, lin)) + return all_pass, rows + + +# ── 样图绘制 ── +PAGE_W, PAGE_H = 640, 1120 +MARGIN, HEAD, BLOCK_TITLE, GAP, LEGEND = 10, 60, 20, 30, 80 + + +def draw_sheet(out_path): + import argparse # noqa: F401 + from PIL import ImageDraw, ImageFont + img = Image.new("RGB", (PAGE_W, PAGE_H), (255, 255, 255)) + d = ImageDraw.Draw(img) + try: + f_zh = ImageFont.truetype("C:/Windows/Fonts/msyh.ttc", 13) + f_zh_s = ImageFont.truetype("C:/Windows/Fonts/msyh.ttc", 11) + except OSError: + f_zh = ImageFont.load_default() + f_zh_s = f_zh + + blocks = [] + y = MARGIN + HEAD + for bt in BOARD_TYPES: + d.text((MARGIN + 4, y + 3), "%s —— 列0=基准格,列1–5=五组微光(阶梯序)" % bt, fill=(0, 0, 0), font=f_zh) + y += BLOCK_TITLE + blocks.append((bt, y)) + y += 3 * CELL + + tiles = load_tiles() + # 画正图段 54 格 + cell_pngs = {} + for bt, y0 in blocks: + for ri, (vn, _) in enumerate(BASE_VARIANTS): + for ci, gname in enumerate(["BASE"] + [g[0] for g in GLOWS]): + base = tiles[(bt, vn)] + cell = Image.new("RGB", (CELL, CELL)) + cp = cell.load() + if gname == "BASE": + for x in range(CELL): + for yy in range(CELL): + cp[x, yy] = base[x, yy] + else: + glow = dict(GLOWS)[gname] + for x in range(CELL): + for yy in range(CELL): + w = glow_weight(x + 0.5, yy + 0.5) + b = base[x, yy] + cp[x, yy] = tuple(round(w * glow[i] + (1 - w) * b[i]) for i in range(3)) + gx = MARGIN + 170 + ci * CELL + gy = y0 + ri * CELL + img.paste(cell, (gx, gy)) + cell_pngs[(bt, vn, gname, "main")] = (gx, gy) + # 行标注 + for ri, (vn, _) in enumerate(BASE_VARIANTS): + d.text((MARGIN, y0 + ri * CELL + 16), vn, fill=(0, 0, 0), font=f_zh_s) + + # 灰度副本段(等幅面,正图段整段 Rec.709 去色) + main_top = MARGIN + HEAD + main_bot = y + gray_top = main_bot + GAP + for xx in range(MARGIN, PAGE_W - MARGIN): + for yy in range(main_top, main_bot): + r, g, b = img.getpixel((xx, yy)) + v = int(round(gray709((r, g, b)))) + img.putpixel((xx, gray_top + (yy - main_top)), (v, v, v)) + d.text((MARGIN + 4, gray_top - 2), "灰度副本段(Rec.709 去色——色弱通道目检面)", fill=(80, 80, 80), font=f_zh_s) + + # 图例段 + leg_y = gray_top + (main_bot - main_top) + 10 + d.text((MARGIN + 4, leg_y), "图例(五组冻结色值 ui_kit.gd TG_GLOW_*;阶梯序=合成空间亮度递减)", fill=(0, 0, 0), font=f_zh_s) + for i, (gn, rgb) in enumerate(GLOWS): + x0 = MARGIN + 170 + i * (CELL + 4) + d.rectangle([x0, leg_y + 18, x0 + CELL, leg_y + 18 + 28], fill=rgb, outline=(0, 0, 0)) + d.text((x0, leg_y + 48), gn, fill=(0, 0, 0), font=f_zh_s) + + img.save(out_path) + return img, cell_pngs, tiles, blocks, gray_top, main_top, main_bot + + +# ── 机检 A/B/C + 灰度/净空机检 ── +def run_checks(img, cell_pngs, tiles, blocks, gray_top, main_top, main_bot): + sheet_px = img.load() + table1 = [] # 45 行逐对表 + table2 = [] # 90 行组间表 + band_means = {} + fail_b, fail_c = [], [] + + for bt, y0 in blocks: + for vn, _ in BASE_VARIANTS: + # 列 0 基准格带域均值 = 该底型的模型底值 + gx0, gy0 = cell_pngs[(bt, vn, "BASE", "main")] + band_base = mean_rgb(tiles[(bt, vn)], BAND_PX) + for gi, (gname, glow) in enumerate(GLOWS): + gx, gy = cell_pngs[(bt, vn, gname, "main")] + px = tiles[(bt, vn)] + # 样图带内均值(样图渲染面读数) + n = len(BAND_PX) + acc = [0.0, 0.0, 0.0] + for x, yy in BAND_PX: + p = sheet_px[gx + x, gy + yy] + for i in range(3): + acc[i] += p[i] + band_mean = tuple(round(v / n) for v in acc) + core_mean = mean_rgb(px, CORE_PX) + model = model_band_mean(px, glow) + diff_model = max(abs(band_mean[i] - model[i]) for i in range(3)) + ch_diff = [abs(band_mean[i] - core_mean[i]) for i in range(3)] + b_ok = max(ch_diff) >= 8 + c_ok = diff_model <= 2 + if not b_ok: + fail_b.append("%s/%s/%s" % (bt, vn, gname)) + if not c_ok: + fail_c.append("%s/%s/%s" % (bt, vn, gname)) + hue_gap = abs(hsv(H2_VALUES[bt])[0] - hsv(glow)[0]) + hue_gap = min(hue_gap, 360 - hue_gap) + table1.append((bt, vn, gname, band_mean, core_mean, model, + diff_model, ch_diff, hue_gap, b_ok and c_ok)) + band_means[(bt, vn, gname)] = band_mean + + # 机检 A:组间表 90 行 + for bt, y0 in blocks: + for vn, _ in BASE_VARIANTS: + for i in range(len(GLOWS)): + for j in range(i + 1, len(GLOWS)): + a, b = band_means[(bt, vn, GLOWS[i][0])], band_means[(bt, vn, GLOWS[j][0])] + cr = wcag(a, b) + ok = cr >= 1.20 + table2.append((bt, vn, "%s/%s" % (GLOWS[i][0], GLOWS[j][0]), + cr, gray709(a), gray709(b), ok)) + stair_ok = True + for bt, y0 in blocks: + for vn, _ in BASE_VARIANTS: + seq = [gray709(band_means[(bt, vn, GLOWS[k][0])]) for k in range(len(GLOWS))] + mono = all(seq[k] > seq[k + 1] for k in range(len(seq) - 1)) + stair_ok = stair_ok and mono + check("A-stair-%s-%s" % (bt, vn[:4]), "明度阶梯单调递减", mono, + "→".join("%.3f" % v for v in seq)) + min_cr = min(t[3] for t in table2) + worst = min(table2, key=lambda t: t[3]) + check("A-CR", "组间合成对比最弱对 ≥1.20(90 对)", min_cr >= 1.20, + "最弱 %s/%s CR=%.3f" % (worst[0], worst[2], min_cr)) + check("B", "格底-微光可辨底线(45 行三通道差不全<8)", len(fail_b) == 0, + "违例 %d 行:%s" % (len(fail_b), ", ".join(fail_b[:6]) or "无")) + check("C", "绘制参数校准(45 行模型差≤±2/255)", len(fail_c) == 0, + "违例 %d 行:%s" % (len(fail_c), ", ".join(fail_c[:6]) or "无")) + + # 灰度段零彩色像素 + color_hit = 0 + for xx in range(MARGIN, PAGE_W - MARGIN): + for yy in range(gray_top + BLOCK_TITLE, gray_top + (main_bot - main_top)): + r, g, b = sheet_px[xx, yy] + if not (r == g == b): + color_hit += 1 + check("GRAY", "灰度副本段零彩色像素", color_hit == 0, "命中 %d" % color_hit) + + # 四缘净空(A5 同款) + edge_hit = 0 + for xx in range(PAGE_W): + for yy in range(PAGE_H): + if xx < MARGIN or xx >= PAGE_W - MARGIN or yy < MARGIN or yy >= PAGE_H - MARGIN: + if sheet_px[xx, yy] != (255, 255, 255): + edge_hit += 1 + check("EDGE", "四缘 10px 带内零内容像素", edge_hit == 0, "命中 %d" % edge_hit) + return table1, table2 + + +def write_report(table1, table2, d_rows): + rep = os.path.join(REPO, "reports", "读数-三关色相互辨抽测-2026-11-05.md") + lines = [ + "# 读数:三关色相 × 五组微光互辨抽测(2026-11-05)", + "", + "> 接收方:待办清单「三关色相 × 五组微光互辨抽测——三关图类型色板终值冻结的前置抽测」条。", + "> 执行依据:reports/提案-三关色相互辨抽测方案-2026-10-29.md(S1/S2 步)。", + "> 样图:artwork/mockups/glow-discrimination-sheet-2026-11-05.png(不入 git)。", + "", + "## 机检汇总", + "", + "| 项 | 判定 | 说明 |", + "|---|---|---|", + ] + for cid, name, ok, detail in CHECKS: + lines.append("| %s | %s | %s:%s |" % (cid, "PASS" if ok else "FAIL", name, detail)) + lines += ["", "## S1 机检 D:铺底代表值(H2 槽)五门", "", + "| 关 | RGB | L(线性域) | 饱和 | 色相 | 近色对 | 判定 |", "|---|---|---|---|---|---|---|"] + for bt, rgb, lin, s, h, near, ok in d_rows: + lines.append("| %s | %s | %.3f | %.3f | %.1f° | %d | %s |" % (bt, rgb, lin, s, h, near, "过" if ok else "红")) + lines += ["", "## 表一 逐对表(45 行)", "", + "| 关 | 底型 | 微光组 | 带内合成均值 | 格心素底均值 | 模型带内均值 | 模型差 | 三通道差 | 色相差° | 判定 |", + "|---|---|---|---|---|---|---|---|---|---|"] + for bt, vn, gn, bm, cm, md, dm, cd, hg, ok in table1: + lines.append("| %s | %s | %s | %s | %s | %s | %d | %s | %.0f | %s |" + % (bt, vn, gn, bm, cm, md, dm, cd, hg, "过" if ok else "红")) + lines += ["", "## 表二 组间表(90 行)", "", + "| 关 | 底型 | 组对 | 合成对比 | 灰度亮度a | 灰度亮度b | 判定 |", "|---|---|---|---|---|---|---|"] + for bt, vn, pair, cr, ga, gb, ok in table2: + lines.append("| %s | %s | %s | %.3f | %.3f | %.3f | %s |" % (bt, vn, pair, cr, ga, gb, "过" if ok else "红")) + n_fail = sum(1 for c in CHECKS if not c[2]) + lines += ["", "---", "", "机检 %d 项,FAIL %d 项。" % (len(CHECKS), n_fail), + "", "目检(S3)归用户:四条判据见方案 §2.2(逐对指认 45/45/灰度副本 45/45/相邻并列 36 对可辨/装饰不抢读)。", ""] + with open(rep, "w", encoding="utf-8") as f: + f.write("\n".join(lines)) + print("[报告] %s" % rep) + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("--art", default=os.path.join(REPO, "artwork", "mockups")) + ap.add_argument("--no-sheet", action="store_true") + args = ap.parse_args() + tiles = load_tiles() + print("== S1 机检 D:三关铺底代表值 ==") + d_ok, d_rows = gate_d(tiles) + if args.no_sheet: + return 0 if d_ok else 1 + os.makedirs(args.art, exist_ok=True) + out = os.path.join(args.art, "glow-discrimination-sheet-2026-11-05.png") + print("== S2 出并列样图 ==") + img, cell_pngs, tiles2, blocks, gray_top, main_top, main_bot = draw_sheet(out) + print("[样图] %s" % out) + t1, t2 = run_checks(img, cell_pngs, tiles2, blocks, gray_top, main_top, main_bot) + write_report(t1, t2, d_rows) + n_fail = sum(1 for c in CHECKS if not c[2]) + print("== 抽测机检完成:%d 项,FAIL %d ==" % (len(CHECKS), n_fail)) + return 0 if n_fail == 0 else 1 + + +if __name__ == "__main__": + sys.exit(main()) From 4a52d769ec6efc7a0ca606bcf35302e77053f25e Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Fri, 6 Nov 2026 00:02:40 +0800 Subject: [PATCH 02/10] =?UTF-8?q?=E6=8A=A5=E5=91=8A(=E6=95=88=E6=9E=9C?= =?UTF-8?q?=E9=80=9A=E9=81=93=E4=B8=8E=E4=BA=8B=E4=BB=B6=E8=AF=8D=E9=9B=B6?= =?UTF-8?q?=E7=8E=B0=E5=BD=B9=E6=99=AE=E6=9F=A5):=20=E5=9B=9B=E8=AF=8D?= =?UTF-8?q?=E8=A1=A8+schema=E6=97=A7=E8=AF=8D=E5=B1=82+channel=E5=9F=9F?= =?UTF-8?q?=E5=85=A8=E9=87=8F=E5=8F=96=E8=AF=81=E2=80=94=E2=80=94=E4=BA=8B?= =?UTF-8?q?=E4=BB=B6=E8=AF=8D=E9=9B=B6=E8=AE=A2=E9=98=854(armor=5Froll/rew?= =?UTF-8?q?ard=5Froll/treasure=5Fused/seal=5Fsettle,=E5=8F=91=E5=B0=84?= =?UTF-8?q?=E7=82=B9=E5=85=A8=E5=9C=A8=3D=E5=AE=8C=E6=95=B4=E7=A9=BA?= =?UTF-8?q?=E6=9E=B6=E5=AD=90)=E3=80=81=E6=95=88=E6=9E=9C=E8=AF=8D?= =?UTF-8?q?=E9=9B=B6=E4=BD=BF=E7=94=A810(=E7=A9=BA=E6=9E=B6=E5=AD=906/?= =?UTF-8?q?=E6=AD=BB=E8=AF=8D3/spike=E5=B2=97=E4=BD=8D=E9=94=99=E4=BD=8D)?= =?UTF-8?q?=E3=80=81schema=E6=97=A7=E8=AF=8D=E9=9B=B6=E8=A1=8C9(=E6=AD=BB?= =?UTF-8?q?=E8=AF=8D4/=E7=A9=BA=E6=9E=B6=E5=AD=905,ap=5Fcharge=5Fsafe?= =?UTF-8?q?=E5=9C=A8=E5=BD=B9)=E3=80=81=E4=BA=8B=E5=AE=9E=E8=AF=8D6/?= =?UTF-8?q?=E7=AE=97=E5=AD=90=E8=AF=8D7=E9=9B=B6=E8=A1=8C=E3=80=81?= =?UTF-8?q?=E5=8F=99=E8=BF=B0=E8=84=B1=E8=8A=825=E5=A4=84(=E6=8E=98?= =?UTF-8?q?=E8=BF=9B=E8=93=84=E8=83=BD/=E6=B7=B1=E6=8C=96=E9=92=BB?= =?UTF-8?q?=E5=A4=B4/=E7=88=86=E7=A0=B4=E5=B7=A5=E5=85=B5=E5=8C=85?= =?UTF-8?q?=E4=B8=89=E4=B8=93=E9=95=BF=E9=9B=B6=E5=9C=A8=E8=A1=A8=E8=80=8C?= =?UTF-8?q?=E6=B3=A8=E9=87=8A=E4=BD=9C=E5=9C=A8=E5=BD=B9=E5=8F=99=E8=BF=B0?= =?UTF-8?q?)=EF=BC=9B=E5=8E=9F=E5=AE=9E=E5=86=B54=E7=BB=84=E5=A4=8D?= =?UTF-8?q?=E6=A0=B8=E6=88=90=E7=AB=8B=EF=BC=9B=E8=A3=81=E5=86=B3=E7=82=B9?= =?UTF-8?q?=E6=B8=85=E5=8D=95A=E2=80=93G=E4=BE=9B=E9=80=90=E7=BB=84?= =?UTF-8?q?=E8=A3=81=E3=80=82=E6=8E=A5=E6=94=B6=E6=96=B9=3D=E5=BE=85?= =?UTF-8?q?=E5=8A=9E=E6=B8=85=E5=8D=95=E6=99=AE=E6=9F=A5=E6=9D=A1(?= =?UTF-8?q?=E5=86=99=E5=8D=A1=E8=BE=93=E5=85=A5=E5=90=88=E5=90=8C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../普查-效果通道与事件词零现役-2026-11-06.md | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 reports/普查-效果通道与事件词零现役-2026-11-06.md diff --git a/reports/普查-效果通道与事件词零现役-2026-11-06.md b/reports/普查-效果通道与事件词零现役-2026-11-06.md new file mode 100644 index 00000000..f83298b3 --- /dev/null +++ b/reports/普查-效果通道与事件词零现役-2026-11-06.md @@ -0,0 +1,113 @@ +# 普查:效果通道与事件词零现役(2026-11-06) + +> **接收方**:待办清单「效果通道与事件词的零现役普查」条——本报告是该条写卡段的输入合同。 +> **性质**:普查取证报告(只读扫描,零代码改动)。词表全集与引擎侧状态以 `game/core/effect_engine.gd` 现值为准;数据面使用统计按行结构键(`"on"`/`"kind"`/`"fact"`/`"op"`/`"channel"`)提取自 `game/data/tables/*.tres` 全域,不数裸词面(注释与载荷键不计)。 +> **判定口径**:引擎侧有发射点/消费分支 + 数据表零行 = **空架子**(架子完整等数据);引擎侧连消费分支都没有 = **死词**;词面在册但实际走别的通道 = **岗位错位**。 + +## 一、普查方法与范围 + +效果系统四词表封闭在 `effect_engine.gd` 常量:事件 `EVENTS`(21)/效果类型 `EFFECT_KINDS`(31)/事实 `FACTS`(18)/算子 `OPS`(13)。另扫两个邻接面:秘宝表 schema 旧词层(`treasure_item_table.gd` `EFFECT_KINDS` 旧词段 10 词,头注明文「旧词保留共存至迁移完成」)与效果参数 `channel` 域。数据面使用域 = feats/treasure_items 两表 trigger 行 + 天赋树规则合成行(`_push_tree_rule` 引擎内组装)+ 秘宝表 `effect_kinds`/主动件 `kind` 域。skills.tres(敌技)的 when/fact 走独立系统(消费端 `unit_container.gd`),不入本普查面。 + +## 二、六面清单 + +### 1. 事件词——零订阅 4 个(发射点全在,完整空架子) + +| 事件词 | 发射点 | 数据表订阅行 | 判定 | +|---|---|---|---| +| armor_roll | damage_controller.gd:296 | 0(feats 零订阅) | 空架子。**词两岗**:掷点流名岗在役(settlement.tres:59 `armor_roll_stream`),事件岗零使用 | +| reward_roll | battle_fx_host.gd:130 | 0 | 空架子 | +| treasure_used | reward_grant.gd:133 | 0 | 空架子 | +| seal_settle | grant_segment.gd:250 | 0 | 空架子 | + +其余 17 事件词订阅行在役(feats 1–11 行不等、treasure_items 1–2 行)。 + +### 2. 效果类型词(effect_engine 词表 31)——数据面零使用 10 个 + +| 词 | 消费分支 | 数据表行 | 判定 | +|---|---|---|---| +| add_ticket_rider | damage_controller.gd:399 | 0 | 空架子 | +| yield_mult | grant_segment.gd:118 | 0 | 空架子 | +| spawn_spell | grant_segment.gd:138 | 0 | 空架子 | +| apply_status | damage_controller.gd:429 | 0 | 空架子(另注意:状态施加在 damage_controller 有独立路径) | +| bias_rewards | battle_fx_host.gd:131 | 0 | 空架子 | +| counter_spend | action_economy.gd:115 + reward_grant.gd:135(两受理闸) | 0 | 空架子——见「叙述脱节」节:其服务对象掘进蓄能/深挖钻头两件专长零在表 | +| bias_wallet | 全域零字面 | 0 | 死词(词表头注称与 grant_gp「共享行拆型」,grant_gp 分支内亦无此词) | +| refresh_pick | 全域零字面 | 0 | 死词(ACTIVE_KINDS 在册,主动分发面亦零) | +| preview | 全域零字面 | 0 | 死词(同上) | +| spike | 独立 kind 零消费 | 0 | **岗位错位**:实走 `modify_ticket` `mode="spike"`(damage_controller.gd:312/:371,在役);独立 kind 词面在册——与迭代 53 清退批已核的「spike 承接句」同源 | + +其余 21 词数据面在役(feats 1–27 行);`damage_mult` 由天赋树规则合成行在役(effect_engine.gd:160)。 + +### 3. 秘宝表 schema 旧词层(10 词)——数据面在役 1、零行 9 + +| 旧词 | 消费点 | 数据表行 | 判定 | +|---|---|---|---| +| ap_charge_safe | —(常时参数注入面) | treasure_items.tres:62 | 在役 | +| mine_reveal | reward_grant.gd:147(主动分发判定) | 0 | 空架子(新旧词共存态:新词 reveal_tiles 同分支在役) | +| reward_preview | reward_grant.gd:151 | 0 | 空架子 | +| ap_grant | reward_grant.gd:153 | 0 | 空架子(数据面走新词形 `grant_ap`) | +| cell_removal | reward_grant.gd:160-161 | 0 | 空架子——原实况点名组 | +| bonus_refresh | adventure_runner/battle_orchestrator/refresh_bank | 0 | 空架子 | +| mine_hit_halve | 全域零文件命中 | 0 | 死词——原实况点名组 | +| reflect_damage | 全域零文件命中 | 0 | 死词。反弹 N 本由其 magnitude 承载(schema 注释),对应 `open_ticket` `channel="reflect"` 行族零表行(21 张表逐张核)——原实况点名组 | +| ap_rounds_front | 全域零文件命中 | 0 | 死词 | +| reward_weight_bias | 全域零文件命中 | 0 | 死词 | + +schema 头注「旧词保留共存至迁移完成」——迁移未完成态本身在册为债。 + +### 4. 事实词(FACTS 18)——数据面零使用 6 个 + +| 词 | 引擎侧 | 数据表行 | 判定 | +|---|---|---|---| +| is_first_dig_of_battle | 查询面在 | 0 | 裸预留 | +| terrain_kind | 载荷特判在(effect_engine.gd:322-331——敌技伤害载荷回落 null 判「不在场」) | 0 | 空架子(特判支撑、零表行) | +| target_armor_class | 查询面在 | 0 | 裸预留 | +| seals_count | 查询面在 | 0 | 裸预留 | +| nest_count | 查询面在 | 0 | 裸预留 | +| battle_index | 查询面在 | 0 | 裸预留 | + +其余 12 词在役(头注点名的用途专长——地质学家/边陲矿工/跳格采掘/破封一击/一滴不剩/背水/保险丝/弃图兑换等——逐个核在 feats.tres 在表)。 + +### 5. 算子词(OPS 13)——数据面零使用 7 个 + +| 词 | 引擎侧 | 数据表行 | 判定 | +|---|---|---|---| +| neq | 实现在(_cmp_ok) | 0 | 裸预留 | +| gt | 实现在(_cmp_ok) | 0 | 裸预留 | +| ends_with | 实现在(_ends_with_ok:312) | 0 | 空架子(头注称「对某甲族的泛条件」——无承载件) | +| has | 实现在(_has_ok:324) | 0 | 空架子 | +| mod_zero | 实现在(_counter_op_ok:335) | 0 | 空架子——见「叙述脱节」:头注称用途「掘进蓄能」,该专长零在表 | +| gte_ref | 实现在(_counter_op_ok:335) | 0 | 空架子——头注称用途「深挖钻头配额」,该专长零在表 | +| lt_ref | 实现在(_counter_op_ok:335) | 0 | 同上 | + +其余 6 算子在役(eq/gte/lte/lt/mod_eq/advantageous——mod_eq 双管镐、advantageous 淬毒刃纹均核在表)。 + +### 6. channel 域 + +数据面现值仅 `blast`(feats 2 行)。`open_ticket` `channel="reflect"` 反弹行族零表行。channel 值域未单点封闭(各消费分支自判值,无独立词表常量)——去留裁定时可一并裁是否收词表。 + +## 三、叙述脱节点(注释把不存在的专长写成在役叙述——spike 案同款误导航源) + +| 位置 | 叙述 | 事实 | +|---|---|---| +| effect_engine.gd OPS 头注 | mod_zero「掘进蓄能」、gte_ref/lt_ref「深挖钻头配额」 | 两专长 feats/treasure 零在表(grep 专名零命中) | +| effect_engine.gd EFFECT_KINDS 头注 | spike 独立 kind 在词表 | 实走 modify_ticket mode 通道(岗位错位) | +| reward_grant.gd:130 | 「counter_spend 订阅=掘进蓄能积点账本」 | 掘进蓄能零在表 | +| action_economy.gd:82 | 「深挖钻头付费开掘(dig_paid counter_spend 订阅施加面)」 | 深挖钻头零在表 | +| treasure_item_table.gd:20 | 「cell_removal = 爆破工兵包中立移除格」 | 爆破工兵包零在表 | + +## 四、裁决点清单(逐组裁:删/补内容接线/留作预留) + +| 组 | 内容 | 裁决选项 | +|---|---|---| +| A | 事件词 4:armor_roll(事件岗)/reward_roll/treasure_used/seal_settle | 删词+摘发射点,或补一件订阅专长 | +| B | 效果词空架子 6:add_ticket_rider/yield_mult/spawn_spell/apply_status/bias_rewards/counter_spend | 同上 | +| C | 效果词死词 3:bias_wallet/refresh_pick/preview | 删词(含 ACTIVE_KINDS 对应位) | +| D | spike 独立 kind | 删词面(mode 通道在役不动) | +| E | schema 旧词 9:死词 4 直删候选(mine_hit_halve/reflect_damage/ap_rounds_front/reward_weight_bias);空架子 5(mine_reveal/reward_preview/ap_grant/cell_removal/bonus_refresh)删或完成迁移 | 删词或接线;同批裁「迁移完成」口径 | +| F | 事实词 6/算子词 7:裸预留与空架子 | 删或留预留(预留需头注改述为「预留无承载件」) | +| G | 叙述脱节 5 处 | 随 A–F 同批订正注释 | + +## 五、与原实况登记 4 组的对应 + +原实况 4 组(cell_removal/mine_hit_halve/open_ticket reflect 行族/armor_roll 订阅)全部复核成立;普查扩面新增:事件词 3(reward_roll/treasure_used/seal_settle)、效果词 10、旧词层另 5、事实词 6、算子词 7、叙述脱节 5 处。 From 55f4de3ca45cf30ab89de8aa2bd50afd81abda31 Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Fri, 6 Nov 2026 00:08:18 +0800 Subject: [PATCH 03/10] =?UTF-8?q?iter53-=E5=8D=A11=EF=BC=9A=E5=8D=B7?= =?UTF-8?q?=E8=BD=B4=E8=A7=86=E5=8F=A3=E6=89=B9:=20=E5=85=B3=E5=8D=A1?= =?UTF-8?q?=E7=94=BB=E9=9D=A2=E8=A7=86=E5=8F=A3=E5=8C=96(level-map.md=20?= =?UTF-8?q?=E5=B8=83=E5=B1=80=E5=86=B3=E7=AD=965=E8=90=BD=E5=9C=B0)?= =?UTF-8?q?=E2=80=94=E2=80=94=E8=A7=86=E5=8F=A3=E6=89=BF=E8=BD=BD=E4=BB=B6?= =?UTF-8?q?/=E9=94=9A=E7=82=B9=E8=B7=9F=E9=9A=8F/=E5=B9=B3=E6=BB=91?= =?UTF-8?q?=E6=BB=9A=E5=8A=A8=E5=87=8F=E5=8A=A8=E6=95=88/=E6=8B=96?= =?UTF-8?q?=E6=8B=BD=E6=BB=9A=E8=BD=AE=E5=B9=B3=E7=A7=BB=E4=B8=8Eclamp/?= =?UTF-8?q?=E6=8C=87=E5=BC=95=E4=BB=B6/=E6=8E=A2=E9=92=8826=E6=96=AD?= =?UTF-8?q?=E8=A8=80/golden=E4=B8=A4Shot=E5=86=BB=E7=BB=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- design/art/art-bible.md | 4 +- design/art/camp-scene-prompts.md | 126 ++---- design/gdd/ux/camp.md | 4 +- game/data/schemas/level_gen_params.gd | 5 +- game/presentation/views/level_map_screen.gd | 142 ++++++- game/presentation/views/level_map_viewport.gd | 190 +++++++++ .../views/level_map_viewport.gd.uid | 1 + game/probe/level_map_shot_probe.gd | 91 ++++ game/probe/level_map_shot_probe.tscn | 6 + game/probe/level_map_viewport_probe.gd | 389 ++++++++++++++++++ game/probe/level_map_viewport_probe.gd.uid | 1 + game/probe/level_map_viewport_probe.tscn | 6 + game/probe/probe_ui_util.gd | 36 ++ game/probe/ui_input_probe.gd | 16 + game/tests/golden/README.md | 10 +- game/tests/golden/windows/lmap_boss.png | Bin 0 -> 215164 bytes game/tests/golden/windows/lmap_entry.png | Bin 0 -> 211513 bytes playnote.md | 31 +- tools/golden_baseline_refresh.sh | 31 ++ tools/probe_gate.sh | 6 + tools/render_gate.sh | 32 ++ 待办清单.md | 8 - 22 files changed, 983 insertions(+), 152 deletions(-) create mode 100644 game/presentation/views/level_map_viewport.gd create mode 100644 game/presentation/views/level_map_viewport.gd.uid create mode 100644 game/probe/level_map_shot_probe.gd create mode 100644 game/probe/level_map_shot_probe.tscn create mode 100644 game/probe/level_map_viewport_probe.gd create mode 100644 game/probe/level_map_viewport_probe.gd.uid create mode 100644 game/probe/level_map_viewport_probe.tscn create mode 100644 game/tests/golden/windows/lmap_boss.png create mode 100644 game/tests/golden/windows/lmap_entry.png diff --git a/design/art/art-bible.md b/design/art/art-bible.md index 53c21eb9..1ca77c1f 100644 --- a/design/art/art-bible.md +++ b/design/art/art-bible.md @@ -392,12 +392,12 @@ - **情绪与色域**:承载 §2.8——全作最暖:烛光黄 `#F6C667` × 木色 `#8A5A34`(§7.2),中等饱和,无棋盘式高对比。 - **场景构成**:一张可点击的营地场景图(1280×800,与工程档同幅面)。远景=天空与远山;中景=**独立成层的木围墙**(密排竖木桩、桩顶削尖、不透缝无横木)与**半开的营地大门**;近景=中央篝火、左侧锻炉铁砧、右侧帐篷与宝箱、帐篷旁的笔记本,另有木桩与挂在围墙上的布告板。**中景带自底部往上约 2/3 处起**;**近景物件可覆盖围墙,唯一例外=中间门洞必须留空、不被任何物件遮挡**。七个可点物件的功能绑定归 `camp.md`,本节只定画法。 - **图层拆分(10 张)**:场景按「远景/中景/近景要素各自成层」拆——`scene_camp_bg` 背景层(z0,不透明全幅)=天空+远山+整片地面+门洞内一条通向远处的小路;`scene_camp_wall` 围墙层(z1,透明底)=横贯全宽密排木桩墙(左右两段)+两根略高的门柱,**门洞处留透明缺口**透出背景层的小路;`scene_camp_board` 布告板(z2)、`scene_camp_gate` 门扇(z3)、`scene_camp_dummy` 木桩/`scene_camp_forge` 锻炉/`scene_camp_tent` 帐篷(z4)、`scene_camp_chest` 宝箱/`scene_camp_notebook` 笔记本(z5)、`scene_camp_campfire` 篝火(z6,最前)=八个物件层,各透明底单件一张。**帐篷**为承载件、不可点。围墙独立成层的好处:桩高可单独锁死、门洞做透明缺口、背景层不混入暖木色。提示词与坐标 = `camp-scene-prompts.md`,消费常量 = `asset-path-map`。 -- **交付形态**:**背景层 1 张(不透明全幅)+ 围墙层 1 张 + 八个物件层 = 10 张**,其中 9 张透明底、1 张不透明全幅 + 一份坐标表(贴图矩形/命中矩形/z 序)。背景层由**远景片 `bg_far`(2560×734)与地面片 `bg_floor`(2560×866)两片出图、按 y734 拼成一张**——整张一次出图时模型把远山挤到画面下半部,被围墙挡住后完全消失(实测三张里两张山体上缘落在墙顶以下)。接缝整条落在围墙背后,画面无接缝。**篝火例外**:命中矩形只取下半(火堆),上半(火焰)只作特效展示。围墙层落盘按细条裁,不做全幅(全幅约 3.9 MB 显存,细条约 0.35 MB);**实装落盘矩形 `(0, 203, 1280, 164)`、底锚 y367**(桩身 150px、门柱 164px 终稿锁定值,落带内〔围墙带 (0,203,1280,164)〕)。 +- **交付形态**:**背景层 1 张(不透明全幅)+ 围墙层 1 张 + 八个物件层 = 10 张**,其中 9 张透明底、1 张不透明全幅 + 一份坐标表(贴图矩形/命中矩形/z 序)。**篝火例外**:命中矩形只取下半(火堆),上半(火焰)只作特效展示。围墙层落盘按细条裁,不做全幅(全幅约 3.9 MB 显存,细条约 0.35 MB);**实装落盘矩形 `(0, 261, 1280, 49)`、底锚 y310**(Y 压缩按桩身 43px 终稿锁定值精确,落带内〔规划带 (0,240,1280,70)〕;备选 A′〔带高 70/桩身 62〕存档 artwork 同目录)。 - **色彩与氛围依据**:营地场景的冷暖分工(冷的大面积后退、暖的小面积前进)、空气透视三档与大面积用色规则 = `reports/提案-营地色彩与氛围脚本-2026-10-23.md`。本节不复述色值;新增环境色按 §4.1 场景环境子板条款登记(每屏一套、≤32 色、过 §4.2 语义检查与 RGB 三通道差 ≥8/255 两道门)。 - **交互四态(零新素材,全部程序化)**:悬停=**轮廓亮边 + 浮动**(浮动须整像素吸附);按下=位移 1px;**禁用/未解锁=降明度 + 去饱和**(§2 已缩窄至情绪域,状态表达不受限),**仅锻炉(锻造工坊)与宝箱(秘宝匣)两件会有此态**;已解锁=常态。 - **钥石余额**:常驻画面顶部的一行小 HUD 栏(高 48px,**浮层覆盖,不挤压画面**)。 - **事实源边界**:解锁条件/价格/存档写入归元进度 GDD 与 `MetaProgression`;素材命名与路径归 `asset-path-map`;清单登记归 `art-assets-checklist` §3.5。 -- **已裁(2026-11-01 用户裁)**:① **营地环境子板色值**——不前置拍板:量化场景实际用色后按 §4.1 场景环境子板条款登记(每屏一套、≤32 色、过 §4.2 语义检查与 RGB 三通道差 ≥8/255 两道门);② **门扇与门洞的高宽比例**——门扇贴图 240×138(锁定 240×147),随门洞 y283–367 压扁重画,坐标按门洞 x520–760 对齐;③ **帐篷的落地尺寸**——251×170 落位 (982, 335),上端遮住围墙下部。 +- **已裁(2026-11-01 用户裁)**:① **营地环境子板色值**——不前置拍板:量化场景实际用色后按 §4.1 场景环境子板条款登记(每屏一套、≤32 色、过 §4.2 语义检查与 RGB 三通道差 ≥8/255 两道门);② **门扇与门洞的高宽比例**——门扇 240×220 追认现值,坐标按门洞 x520–760 对齐(`camp-scene-prompts.md` §2.3);③ **帐篷的落地尺寸**——300×170 追认现值(各素材第一张样本稿已过审为终稿,重定即触发重出,不裁)。 ### 6.3 三关图类型色板候选(board_type 换挡方向) diff --git a/design/art/camp-scene-prompts.md b/design/art/camp-scene-prompts.md index 38e35f2e..a269ff63 100644 --- a/design/art/camp-scene-prompts.md +++ b/design/art/camp-scene-prompts.md @@ -1,9 +1,9 @@ # 营地场景 · 分层生图提示词卡 v1.5 > **性质**:营地场景图(1280×800,一张可点击场景图 + 十张分层:背景层 1 + 围墙层 1 + 八个物件层)的出图执行侧文件。**场景级资产,与角色级 [art-prompts](art-prompts.md) 并列,两文件互不覆盖**。 -> **依据**:色彩与氛围 = `reports/提案-营地色彩与氛围脚本-2026-10-23.md`(本卡不复述色值);坐标与层序 = 本卡 §2.3(运行期单一事实源 = `game/data/tables/camp_scene_layout.tres`);物件命名与消费链 = [asset-path-map](asset-path-map.md);画法与交付形态 = [art-bible](art-bible.md) §6.2。冲突时色彩以色彩脚本为准,画法以 art-bible 为准。 +> **依据**:色彩与氛围 = `reports/提案-营地色彩与氛围脚本-2026-10-23.md`(本卡不复述色值);坐标与层序 = `artwork/2026-10-23-营地场景/布局草案-1280x800.html`;物件命名与消费链 = [asset-path-map](asset-path-map.md);画法与交付形态 = [art-bible](art-bible.md) §6.2。冲突时色彩以色彩脚本为准,画法以 art-bible 为准。 > **边界**:只管营地场景图的分层出图。角色、图标、格面走 art-prompts.md 与脚本管线,不需要提示词。 -> **建立**:2026-10-25 · 状态:十条提示词成文(背景层 1 + 围墙层 1 + 八个物件层);2026-11-05 按地平线 y367 重排,背景层与围墙层待按 §4 新判据重出,门扇随门洞压扁重画 +> **建立**:2026-10-25 · 状态:十条提示词成文(背景层 1 + 围墙层 1 + 八个物件层),出图通道由作者自定 --- @@ -14,7 +14,7 @@ 3. **后处理**:脚本管线代跑——去底转透明、降采样到终稿尺寸(整数倍)、色板量化、四联底测试条。**背景层不去底(全幅不透明)**;围墙层与八个物件层去底转透明。后处理工具清单与用法见 [art-pipeline-tools](art-pipeline-tools.md)。 4. **转正**:终稿转入切片资产目录,按坐标表接线。 -**出图顺序(先锁后产,不能跳)**:概念脚本 → **本卡提示词** → 贴风格参考图**先出远景片 `bg_far` 1 张** → 作者确认风格前缀 → 才出地面片 `bg_floor`、围墙层与八个物件层。 +**出图顺序(先锁后产,不能跳)**:概念脚本 → **本卡提示词** → 贴风格参考图**先出背景层 `scene_camp_bg` 1 张** → 作者确认风格前缀 → 才扩产围墙层 `scene_camp_wall` 与八个物件层(共 9 张)。 --- @@ -43,57 +43,22 @@ Style reference: the attached images are this game's own finished pixel art and ### 2.1 背景层(`scene_camp_bg`,不可点,不透明全幅) -**产出方式**:分两片出图,后处理按 y734 拼成一张 2560×1600。接缝整条落在围墙层(406–734)背后,画面里看不见。 - -| 片 | 出图画布 | 终稿落位 | 内容 | -|---|---|---|---| -| 远景片 `bg_far` | 2560×734(3.5:1 超宽) | (0, 0, 1280, 367) | 天空+远山+草地+小路 | -| 地面片 `bg_floor` | 2560×866(3:1 超宽) | (0, 367, 1280, 433) | 营地内踩实裸土 | - -**为什么分两片**:整张一次出图时,模型按「构图好看」分配天地比例,山被挤到画面下半部——三张实测里两张的山体整段落在围墙后面(山体上缘 y280/y227,墙顶 217),远山等于消失。拆开后远景片的全部高度都归天空+山+草地,山才可能长到围墙之上。 - -#### 2.1.1 远景片(`bg_far`) - -**画布比例**:3.5:1 超宽。通道支持直接出 2560×734;不支持则按 3:2 出图后纵向压到 3.5:1,构图比例不变 -**分带(按画面高度)**: -- 天空 0–14% -- 远山 14–55%(**山体占 41%,硬指标**) -- 草地 55–100% -- 小路在草地内:从底边向上收窄,到山脚为止,**不越过山脚、不上探到天空** -**画什么**:天空、2–3 层远山、成片草地、草地中央一条土路 -**不画什么**:围墙、门柱、门扇、物件、角色、营地内地面(那是 §2.1.2);山与草地之间禁出现平直硬边 +**出图画布**:2560×1600(终稿 1280×800 的 2 倍,保证整数倍降采样) +**画什么**:天空、远山、整片地面、门洞位置一条通向远处的小路 +**不画什么**:木围墙、门柱、门扇、七个物件、角色、接地阴影——围墙与门柱是 §2.2 的独立层,门洞是它的透明缺口;小路在本层画好、透出来即可 ``` -Pixel art style. True pixel art game background, chunky square pixels, strict pixel grid, hard edges, no anti-aliasing, flat colors, limited palette about 20 colors, retro 16-bit look, Aseprite style, flat side view, orthographic, ULTRA WIDE horizontal composition, aspect ratio 3.5 to 1. This is the far view seen from inside a small adventurer camp, looking out. It contains ONLY three bands stacked top to bottom, plus one path. BAND 1 — SKY, from the top edge down to 14 percent of the frame height: pale cool off-white with a faint blue-grey tint, flat and empty, at most one or two extremely simple flat clouds, no sun. BAND 2 — DISTANT HILLS, from 14 percent down to 55 percent of the frame height: two or three overlapping layers of rolling hills in pale cool blue-grey-green, each farther layer lighter, cooler and lower in contrast. THE HILLS MUST FILL THIS ENTIRE BAND — the highest ridgeline reaches up to 14 to 20 percent of the frame height and the hill mass continues down to 55 percent; a low ridge hugging the bottom of the frame is WRONG. Silhouette edges are stepped in pixel blocks, no outline, no rim light. BAND 3 — MEADOW, from 55 percent down to the bottom edge: cool pale grey-green grass, flat and low contrast, marked only by a few simple flat grass tufts, no trees, no bushes. PATH — one dirt path in the meadow only: it starts at the bottom edge of the frame in the middle, about one fifth of the frame width there, runs straight up and narrows until it meets the hill foot at 55 percent, where it disappears; it must not go above the hill foot and must not reach the sky. COLOR: everything cool, pale, desaturated, low contrast, no warm, golden, amber or yellow anywhere. DO NOT ADD: any palisade wall, fence, gate, gate posts, tent, campfire, crate, barrel, prop, character, animal; any hard straight horizontal seam between sky, hills and meadow — the hill foot dissolves into the meadow through stepped intermediate tones; any outline or rim; trees, forests or dense vegetation; antialiasing, gradients, dithering, painterly strokes, 3D, realistic shading, glossy light, bloom, vignette, dark corners, night, sunset, sun; any text, letters, number, watermark, signature, logo, frame, border, UI element, icon, badge. +Pixel art style. True pixel art game background layer drawn with chunky square pixels, strict pixel grid alignment, hard edges, no anti-aliasing, no gradients, flat colors only, a limited palette of about 24 colors, retro 16-bit look, Aseprite style, all ages, flat side view, orthographic, no perspective distortion. Wide horizontal composition, 16:10 aspect ratio. This is the FAR BACKGROUND LAYER ONLY of a small adventurer camp: sky, distant hills and the whole ground. It must contain no palisade wall, no gate posts, no camp objects, no gate leaves, no characters and no drop shadows, because all of those are drawn as separate transparent layers on top of this one. COLOR SCRIPT — cool recedes, warm advances: the sky, the hills and the ground are all COOL, pale, desaturated and low in contrast; there is no warm accent anywhere in this layer, warm color belongs only to the separate object layers drawn on top. ATMOSPHERIC DEPTH: every plane that is farther away is lighter, closer to the value of the sky, cooler, lower in contrast and simpler in detail, while the nearest plane is the darkest and highest in contrast. SKY (top of frame): the lightest thing in the picture, flat pale cool off-white with a faint blue-grey tint, no yellow or cream tone, no sun anywhere; the very top strip of the frame, about one sixteenth of the frame height, stays completely calm and empty, reserved as clear space with nothing in it; at most one or two extremely simple flat low-contrast clouds. FAR DISTANCE: two or three layers of low rolling hill silhouettes in pale cool blue-grey, each farther layer lighter, cooler and lower in contrast than the one in front, fading towards the value of the sky, no trees, no individual foliage. HILLS TO GROUND: the hills fade gradually and smoothly down into the ground, with NO visible horizon line and NO distant ground band — the transition must not read as a separate horizontal stripe of a different color. GATE PATH: in the middle of the frame, between x=1040 and x=1520, one clearly visible dirt path runs from the ground at two thirds of the frame height measured from the bottom edge away into the distance between the hills, narrowing as it recedes, painted in a muted desaturated grey-brown earth tone, never golden or warm yellow; this path shows through the empty gate opening of the wall layer above. FOREGROUND GROUND: the darkest area of the picture, dry packed bare earth in a neutral desaturated grey-brown, never golden, amber or warm yellow, hard flat color blocks, hard edges, no gradient, no grass, no grass tufts, no weeds and no plants of any kind. The foreground ground is completely empty apart from the dirt path: no objects, no icons, no badges, no markers, no decorations of any kind. Do not add any of the following: realistic, photorealistic or 3D rendering; painterly brushwork, smooth anti-aliased lines, gradient or dithered shading, glossy highlights; black or heavy dark outlines; drop shadows, contact shadows or any shadow band; blur or compression artifacts; a vignette, dark corners, or any mood darkening; night, dusk, moon, stars, sunset or sunrise light; a sun or any light source drawn in the sky; a visible horizon line, a separate horizontal distant ground band or any distant grass strip below the hills; trees, forests or foliage in the distance; grass, grass tufts, weeds or plants in the foreground; a palisade wall, wooden fence, fence posts, gate posts or any wall structure; any warm, golden, amber or yellow cast on the sky, on the hills or on the ground; any camp object, furniture, crate, barrel, fire, tent or tool; any gate leaf, door panel or hinge; any purple or magenta anywhere; any text, letters, numbers, watermark, signature or logo; any frame, border, panel, arrow or UI element; any icon, badge, item tile, emblem, sign, marker or symbol anywhere in the frame; any characters, people, creatures or animals. ``` -#### 2.1.2 地面片(`bg_floor`) - -**画布比例**:3:1 超宽 -**内容**:营地内的踩实裸土,铺满整幅 -**硬指标**:**中线与左右两侧同色——没有任何路、小径、车辙**;明度 30%–45%;色相与远景片草地明显区分 -**不画什么**:草、植被、大石块、物件、天空、地平线、围墙、接缝线 - -``` -Pixel art style. True pixel art game ground texture, chunky square pixels, strict pixel grid, hard edges, no anti-aliasing, flat colors, limited palette about 12 colors, retro 16-bit look, Aseprite style, ULTRA WIDE horizontal composition, aspect ratio 3 to 1. This is the trodden floor INSIDE a small adventurer camp — bare packed dry earth filling the whole frame edge to edge, seen at a shallow angle from slightly above. MATERIAL: desaturated warm grey-brown, medium value, roughly 30 to 45 percent luminance, never dark, never muddy. TEXTURE: deliberate pixel clusters only — short paired scuff marks that read as dragged footprints, small scattered pebbles, beaten patches where feet have worn the ground smooth, occasional faint drag marks; density rises slightly toward the bottom edge and the middle stays calm and open. CRITICAL, NO PATH: there is no road, no trail, no track, no wheel rut and no worn strip anywhere in this image — the middle of the frame must look the same as the left and right edges, nothing leads anywhere. DO NOT ADD: grass, vegetation, plants, flowers, moss, lichen; rocks larger than a pebble; crates, sticks, bones, debris piles, tools; water, puddles; shadows of objects; sky, horizon, hills, wall, fence, gate, building; any line, seam, border or edge inside the frame; antialiasing, gradients, dithering, painterly strokes, 3D, realistic shading, glossy light, bloom, vignette, dark corners, warm golden cast; any text, letters, number, watermark, signature, logo, frame, border, UI element, icon, badge. -``` - -#### 2.1.3 拼接与后处理 - -1. 两片各缩放到终稿尺寸:远景片 1280×367、地面片 1280×433 -2. 按 y367 上下拼接成 1280×800 -3. 量化到营地环境子板(≤32 色) -4. 需要 2× 档时整数倍放大到 2560×1600 -5. 接缝不做过渡处理——它整条落在围墙(203–367)背后 - ### 2.2 围墙层(`scene_camp_wall`,不可点,透明底) -**出图画布**:2560×1600(与背景层同画布,门洞 x 坐标直接对齐);墙横贯画在出图 y406–734 这条带内(桩身 y434–734,门柱 y406–734),其余为纯色底 `#F2F2F2`。落盘由 S4 后处理裁成终稿外接矩形 `(0, 203, 1280, 164)` / 出图 `(0, 406, 2560, 328)` 的细条,**不做全幅 1280×800 落盘**(全幅约 3.9 MB 显存,细条约 0.35 MB)。 -**画什么**:横贯全宽的密排竖木桩墙(左右两段,桩身终稿 150 高)+ 两根略高的门柱(终稿 164 高),门洞处完全透明 +**出图画布**:2560×1600(与背景层同画布,门洞 x 坐标直接对齐);墙横贯画在出图 y480–620 这条**窄带**内,其余为纯色底 `#F2F2F2`。落盘由 S4 后处理裁成终稿外接矩形 `(0, 240, 1280, 70)` / 出图 `(0, 480, 2560, 140)` 的细条,**不做全幅 1280×800 落盘**(全幅约 3.9 MB 显存,细条约 0.35 MB)。 +**画什么**:横贯全宽的密排竖木桩墙(左右两段)+ 两根略高的门柱,门洞处完全透明 **不画什么**:天空、远山、地面、小路、门扇、七个物件、角色;门洞内不画任何东西,透出背景层的小路 ``` -Pixel art style. True pixel art game layer drawn with chunky square pixels, strict pixel grid alignment, hard edges, no anti-aliasing, no gradients, flat colors only, a limited palette of about 24 colors, retro 16-bit look, Aseprite style, all ages, flat side view, orthographic, no perspective distortion. Wide horizontal composition, 16:10 aspect ratio. This is the PALISADE WALL LAYER ONLY of a small adventurer camp, drawn on a plain flat uniform light grey #F2F2F2 background for easy keying. A wooden palisade wall runs straight across the full width of the frame, seen from the front, built from closely spaced vertical logs standing side by side with no gaps between them, every log cut to a sharp point at the top, a solid barrier with no horizontal rails, no see-through gaps, no ranch-style post-and-rail fence. The wall stands on the ground line at y=734 of 1600. The LOG BODIES, pointed tips included, rise 300 pixels above that base line — about nineteen percent of the total frame height — so it reads as a real barrier with presence, clearly taller than the gate opening cut into it, not a thin decorative strip. In the middle of the wall one wide gap holds two thick gate posts standing 28 pixels taller than the logs, and the entire opening between them is completely EMPTY — plain flat uniform light grey #F2F2F2 showing through, spanning x=1040 to x=1520 and rising from the base line y=734 up to y=566, no logs, no path, no ground, no scenery inside the opening, because the dirt path and the hills belong to the background layer below and the gate leaves are a separate object layer. The wall is painted in a muted greyed wood brown, with a thin warm cream outline around the whole silhouette, flat shading. Do not add any of the following: realistic, photorealistic or 3D rendering; painterly brushwork, smooth anti-aliased lines, gradient or dithered shading, glossy highlights; black or heavy dark outlines; drop shadows or contact shadows; blur or compression artifacts; a vignette or dark corners; any sky, hills, ground, grass, dirt path or scenery of any kind; any gate leaf, door panel or hinge; any camp object, furniture, crate, barrel, fire, tent or tool; any characters, people, creatures or animals; any purple or magenta anywhere; any text, letters, numbers, watermark, signature or logo; any frame, border, panel, arrow or UI element. +Pixel art style. True pixel art game layer drawn with chunky square pixels, strict pixel grid alignment, hard edges, no anti-aliasing, no gradients, flat colors only, a limited palette of about 24 colors, retro 16-bit look, Aseprite style, all ages, flat side view, orthographic, no perspective distortion. Wide horizontal composition, 16:10 aspect ratio. This is the PALISADE WALL LAYER ONLY of a small adventurer camp, drawn on a plain flat uniform light grey #F2F2F2 background for easy keying. A wooden palisade wall runs straight across the full width of the frame, seen from the front, built from closely spaced vertical logs standing side by side with no gaps between them, every log cut to a sharp point at the top, a solid barrier with no horizontal rails, no see-through gaps, no ranch-style post-and-rail fence. The wall is SHORT and LOW: including the pointed tips the whole band occupies only about one eighteenth of the total frame height, a thin horizontal strip, NOT a tall barrier; the logs stand only about one eighteenth of the total frame height above their base line. In the middle of the wall one wide gap holds two thick gate posts slightly taller than the wall, and the entire opening between them is completely EMPTY — plain flat uniform light grey #F2F2F2 showing through, no logs, no path, no ground, no scenery inside the opening, because the dirt path and the hills belong to the background layer below and the gate leaves are a separate object layer. The wall is painted in a muted greyed wood brown, with a thin warm cream outline around the whole silhouette, flat shading. Do not add any of the following: realistic, photorealistic or 3D rendering; painterly brushwork, smooth anti-aliased lines, gradient or dithered shading, glossy highlights; black or heavy dark outlines; drop shadows or contact shadows; blur or compression artifacts; a vignette or dark corners; any sky, hills, ground, grass, dirt path or scenery of any kind; any gate leaf, door panel or hinge; any camp object, furniture, crate, barrel, fire, tent or tool; any characters, people, creatures or animals; any purple or magenta anywhere; any text, letters, numbers, watermark, signature or logo; any frame, border, panel, arrow or UI element. ``` ### 2.3 出图画布上的坐标(终稿 ×2) @@ -101,17 +66,11 @@ Pixel art style. True pixel art game layer drawn with chunky square pixels, stri | 元素 | 终稿 1280×800 | 出图画布 2560×1600 | |---|---|---| | 顶栏 HUD 保留带 | y ≤ 48 | **y ≤ 96**(保持空旷) | -| 远景片 `bg_far` | y 0–367(高 367) | y 0–734(高 734,3.5:1) | -| 地面片 `bg_floor` | y 367–800(高 433) | y 734–1600(高 866,3:1) | -| 两片接缝 | **y 367**(落在围墙 203–367 背后) | **y 734**(落在围墙 406–734 背后) | -| 地平线(山脚/草地起点) | y 与两片接缝重合,墙背后不可见 | 同左 | -| 远山带 | y 51–202(画面 14%–55%,山体 41%) | y 103–403 | -| 草地带 | y 202–367 | y 403–734 | -| 围墙层外接矩形 | y 203–367(高 164) | y 406–734(高 328) | -| 围墙带(wall 层桩身) | y 217–367(**高 150px**) | y 434–734(**高 300px**) | -| 门柱(wall 层,略高) | y 203–367(高 164);x 500–520 / 760–780 | y 406–734;x 1000–1040 / 1520–1560 | -| 门洞(wall 层透明缺口) | y 283–367(高 84);x 520–760 | y 566–734(高 168);x 1040–1520 | -| 门洞内小路(画在远景片草地内) | x 520–760 穿门洞,自接缝 y367 向上收窄,到山脚 y202 消失 | x 1040–1520,自 y734 向上收窄,到 y403 消失 | +| 背景层 `scene_camp_bg` | 全幅 1280×800 | 全幅 2560×1600 | +| 围墙带(wall 层桩身) | y 267–310(**高 43px**) | y 534–620(**高 86px**) | +| 门柱(wall 层,略高) | y 240–310;x 500–520 / 760–780 | y 480–620;x 1000–1040 / 1520–1560 | +| 门洞(wall 层透明缺口) | x 520–760 | x 1040–1520 | +| 门洞内小路(画在 bg 层) | x 520–760,自 y310 向上收窄至远山 | x 1040–1520,自 y620 向上收窄至远山 | --- @@ -138,7 +97,7 @@ Do not add any of the following: realistic, photorealistic or 3D rendering; pain | 件 | z 序 | 终稿矩形 | 出图画布 | 正文 | |---|---|---|---|---| | 布告板 | 2 | 130×140 | 260×280 | §3.1 | -| 门扇 | 3 | 240×147 | 480×294 | §3.2 | +| 门扇 | 3 | 240×220 | 480×440 | §3.2 | | 木桩 | 4 | 120×180 | 240×360 | §3.3 | | 锻炉·铁砧 | 4 | 240×240 | 480×480 | §3.4 | | 帐篷 | 4(不可点) | 300×170 | 600×340 | §3.5 | @@ -146,7 +105,7 @@ Do not add any of the following: realistic, photorealistic or 3D rendering; pain | 笔记本 | 5 | 100×80 | 200×160 | §3.7 | | 篝火 | 6 | 160×160 | 320×320 | §3.8 | -**落位尺寸(2026-11-05 用户裁地平线 y367 重排后)**:布告板 130×121/门扇 240×138/木桩 120×180/锻炉 240×193/帐篷 251×170/宝箱 106×90/笔记本 100×66/篝火 160×149——贴图锚定=底中心(帐篷/锻炉/宝箱/篝火/笔记本)+顶锚(门扇悬挂/布告板挂墙);命中矩形按锁定值。八件只改落位,门扇另随门洞压扁重画(原 240×211 → 240×138),其余七件沿用现有终稿。 +**落位实测(锁定矩形 contain)**:布告板 130×121/门扇 240×211/木桩 120×180/锻炉 240×193/帐篷 251×170/宝箱 106×90/笔记本 100×66/篝火 160×149——贴图锚定=底中心(帐篷/锻炉/宝箱/篝火/笔记本)+顶锚(门扇悬挂/布告板挂墙);命中矩形按锁定值。换算式登记(源 2× 档→落位尺寸)存 artwork 工作区。 **3.1 布告板(→ 图鉴)** ``` @@ -155,7 +114,7 @@ A wooden notice board hung on a wall, with two or three blank pinned papers, no **3.2 门扇(→ 冒险)** ``` -Two wooden gate leaves hanging from their hinges, half open and tilted outward, each made of thick planks with a cross brace and dark iron fittings, seen from the front, the pair shown together as one single object; the pair together fills a WIDE LOW rectangle about 240 wide by 138 tall, so the leaves read as broad rather than tall, each leaf roughly twice as wide as it is high; wood brown #8A5A34 planks, dark iron fittings. +Two wooden gate leaves hanging from their hinges, half open and tilted outward, each made of thick planks with a cross brace and dark iron fittings, seen from the front, the pair shown together as one single object; wood brown #8A5A34 planks, dark iron fittings. ``` **3.3 木桩(→ 天赋树)** @@ -192,32 +151,17 @@ A campfire made of a ring of grey stones around crossed stacked logs with a warm ## 4. 验收(机检 + 目检) -**远景片 `bg_far`** -- 黄度 =(R+G)/2−B 分区取样:天空 ≤20、远山 ≤20、草地 ≤35 -- 冷色像素占比 ≥55%;禁出现任何暖色高饱和像素 -- 机检:**山体上缘 ≤ 画面高度 15%**(这是硬指标——山体上缘落得越低,被围墙挡住后越是什么都看不见) -- 机检:**山体占画面高度 ≥40%**(山体上缘到山脚) -- 机检:草地上限 ≤ 画面高度 55% -- 机检:山脚与草地交界处,上下各 8px 窄带的行均色差 ≤6/255(禁平直硬边;旧稿 y321 处约 37/255) -- 目检:顶部天空空旷、无太阳、云不超过两朵扁平简笔 -- 目检:小路只在草地内,从底边向上收窄到山脚为止,**不越过山脚、不上探到天空** -- 目检:无围墙、门柱、门扇、物件、角色 - -**地面片 `bg_floor`** -- 明度 **L 0.30–0.45**(相对亮度);整片低于 0.30 即判红(旧稿偏暗、观感发闷) -- 机检:画面中线 200px 带与左右各 250px 带的平均色差 ≤6/255(**营地内无路带**) -- 机检:与远景片草地的平均色 (R−B) 差 ≥10/255(两种材质色相可辨) -- 目检:禁出现草、植被、大石块、物件、水面;细节读作拖拽脚印/碎石/踩踏斑块,不是满屏噪点 - -**整图(两片拼接后)** -- 接缝 y367 落在围墙 203–367 背后,**画面里看不见接缝** -- 单张 ≤32 色(量化后) -- 全幅无任何独立物件/图标/徽章/标记 +**背景层 `scene_camp_bg`** +- 黄度 =(R+G)/2−B 分区取样:天空 ≤20、远山 ≤20、地面 ≤35 +- 冷色像素占比 ≥55%;本层不应出现任何暖色高饱和像素 +- 目检:顶部约 1/16 完全空旷;**无地平线、无远景地面带**(远山自然渐隐过渡到地面);不含围墙、门柱、门扇、物件、角色 +- 目检/机检:门洞 x1040–1520 处**有一条清晰可辨、向远处收窄的土路**(非纯色块),透出「出去即冒险」 +- 机检/目检:全幅**无任何独立物件/图标/徽章/标记**(前景地面除小路外全空);参考做法=中下方块区独立色数应≈邻区 **围墙层 `scene_camp_wall`** - 透明底 `#F2F2F2` 可去底、奶油描边闭合 -- **桩身 = 出图 y434–734(终稿 150px);门柱 y406–734(终稿 164px);外接矩形 (0,406,2560,328)。桩身超出下沿 y734 达 5px 以上即判红** -- 目检:密排竖木桩、桩顶削尖、不透缝、无横木;门洞 y566–734 / x1040–1520 **完全透明**(透出 bg 小路)、无门扇;桩身高度须明显大于门洞高度 +- **桩身高度 = 出图 y534–620(终稿 43px);门柱略高 y480–620。桩身超出围墙带下沿 y620 达 5px 以上即判红** +- 目检:密排竖木桩、桩顶削尖、不透缝、无横木;门洞 x1040–1520 **完全透明**(透出 bg 小路)、无门扇 - 单张色数 ≤32(量化后)、缩放为整数倍无拉伸痕迹 > **量化与缩放实况注记**:围墙层与八件已按营地主色板 **32 色重量化回写**(art-bible §4.1 子板行——违例对 0);落位缩放实况=源 2× 档经后处理换算为锁定矩形 contain(×0.1934–0.4404 非整数倍),「整数倍无拉伸痕迹」判据的机检面以落位实测尺寸与目检兜底执行。 @@ -231,16 +175,10 @@ A campfire made of a ring of grey stones around crossed stacked logs with a warm --- -## 5. 已裁(2026-11-05 用户裁;不再阻塞坐标表与定稿) +## 5. 已裁(2026-11-01 用户裁;不再阻塞坐标表与定稿) -1. **地平线与整体分带**:地平线定在终稿 y367(出图 y734);地面 433px、可见远景 217px(27%);围墙、门、布告板随之上调 -2. **围墙高度**:桩身 150(出图 300)、门柱 164(出图 328)、门洞 84(出图 168);墙高须大于门洞高 -3. **门扇尺寸**:贴图 240×138(锁定 240×147),随门洞压扁重画,坐标按门洞 x520–760 对齐 -4. **帐篷**:251×170 沿用现终稿,落位 (982, 335),遮住墙下部 32px(覆盖围墙可接受) -5. **笔记本**:随帐篷跟随,落在帐篷左下方外侧、两者不重叠——`x = 帐篷 x − 112`、`y = 帐篷底 + 10` -6. **宝箱离底**:贴图底 y744,距画面底 56px;其余物件同步上移 46px -7. **地面分两区**:营地外(y734 以上)=冷调灰绿草地+一条向远山收窄的土路;营地内(y734 至画面底)=踩实裸土、与草地异色相、无草无路无车辙;两区分界被围墙层完全遮住 -8. **背景层分两片出图**:远景片 `bg_far`(2560×734,天空 14%/远山 41%/草地 45%+小路)+ 地面片 `bg_floor`(2560×866 踩实裸土),后处理按 y734 拼成一张 2560×1600;接缝落在围墙 406–734 背后。分片理由=整张出图时模型把山挤到画面下半部,实测三张里两张山体整段被围墙遮没 -9. **布告板位置**:(845, 224, 130, 140),底 345 落在墙内,不再悬空 -10. **描边颜色**:奶油色追认——去底脚本「奶油描边膨胀 3px 当屏障」的技术前提随现值锁定(§1 注记同源);改深灰褐须换去底方案全量重出,不裁 -11. **营地环境子板色值**:不前置拍板——量化场景实际用色后按 art-bible §4.1 两道门登记(语义检查+RGB 三通道差 ≥8/255),本卡仍不复述色值 +1. **帐篷尺寸**:300×170 追认现值(各素材第一张样本稿已过审为终稿;重定即按比例重出、不裁) +2. **门扇高宽**:240×220 追认现值,坐标按门洞 x520–760 对齐(§2.3);围墙带桩身高 43px、门扇叠在门洞上的叠放关系随此锁定 +3. **布告板位置**:采纳建议值 `(845, 268, 130, 140)` 挂回围墙带;终值随坐标表(`camp_scene_layout.tres`)落盘 +4. **描边颜色**:奶油色追认——去底脚本「奶油描边膨胀 3px 当屏障」的技术前提随现值锁定(§1 注记同源);改深灰褐须换去底方案全量重出,不裁 +5. **营地环境子板色值**:不前置拍板——量化场景实际用色后按 art-bible §4.1 两道门登记(语义检查+RGB 三通道差 ≥8/255),本卡仍不复述色值 diff --git a/design/gdd/ux/camp.md b/design/gdd/ux/camp.md index a37ebf0e..991baf70 100644 --- a/design/gdd/ux/camp.md +++ b/design/gdd/ux/camp.md @@ -20,13 +20,13 @@ | 木桩 | 天赋树 | | | 布告板 | 奖励格图鉴 | 内容冻结未激活,点进看占位——**不是禁用态** | | 篝火 | 离开营地回主菜单 | **必须二次确认**;命中区只含火堆、不含火焰 | -| 帐篷 | — | 承载件,**不可点**;251×170 落位 (982, 335),上端遮住围墙下部;笔记本在其左下方外侧、两者不重叠 | +| 帐篷 | — | 承载件,**不可点**;落地尺寸与占位范围待作者重定(待裁口径见 art-bible §6.2) | 纵深=远景天空与远山/中景木围墙与营地大门/近景篝火与左右物件(作者纵深稿)。中景围墙是横贯全宽的密排竖木桩墙——木桩一根挨一根无缝、桩顶削尖、无横木,只在中段留缺口给大门。 **场景按要素分层(10 张)**:远景天空/远山/整片地面/门洞内的小路合成 `scene_camp_bg` 背景层(z0,不透明全幅);中景木围墙独立成 `scene_camp_wall` 围墙层(z1,透明底,门洞处留透明缺口);其余八个物件层各一张、由上往下叠。门洞是围墙层的透明缺口,透出背景层画的**一条通向远处的小路**,不可填死。 -**地平线在终稿 y367**(自画面底部往上约 46%),其上是天空与远山、其下整片地面;**中景围墙带 y203–367**,桩身 150、门柱 164;近景物件允许压住围墙(围墙不可点,z 序在近景物件之下),**唯一例外=中间门洞必须留空、不被任何物件遮挡**。围墙形态、门扇比例与帐篷尺寸的现行口径归 [art-bible](../../art/art-bible.md) §6.2,本 spec 不再复述。 +**中景带自画面底部往上约 2/3 处起**;近景物件允许压住围墙(围墙不可点,z 序在近景物件之下),**唯一例外=中间门洞必须留空、不被任何物件遮挡**。围墙形态、门扇比例与帐篷尺寸的现行口径归 [art-bible](../../art/art-bible.md) §6.2,本 spec 不再复述。 坐标草案与分层验收判据见 [camp-scene-prompts](../../art/camp-scene-prompts.md) §2.3/§4(10 张口径现行事实源);2026-10-22 美术方案讨论沿革查 git 提交史。 diff --git a/game/data/schemas/level_gen_params.gd b/game/data/schemas/level_gen_params.gd index 40563cc5..6bb36305 100644 --- a/game/data/schemas/level_gen_params.gd +++ b/game/data/schemas/level_gen_params.gd @@ -1,6 +1,7 @@ ## 关卡节点图参数档 schema(节点图生成器核心批 卡① T1):五旋钮+战斗保底+岔口去路数的行式数据表。 ## 键 = level_index(关卡行集单点),消费面经 ConfigDB.run.level_gen_params.row_by_level_index() 读取;生成器只吃参数档、不认关卡号(契约 6)。 -## 数值全 provisional(定值批落终值);域校验沿关卡节点图生成.md v1.1 调参表已锁条款——层深 L1≥6 递增增幅变大、 +## 数值全 provisional(定值批落终值);取值域与字段契约单点=本文件域校验(概念与设计意图指针= +## 关卡节点图生成.md v1.5 参数契约节)——层深 L1≥6 递增增幅变大、 ## 配比四类合计 1、出口 L1 恒 1/L2-L3 1-3、岔口去路数恒 2/3、战斗保底≥0。 class_name LevelGenParams extends Resource @@ -66,7 +67,7 @@ func _validate_row_shape(row: Dictionary, L: int, key: String, layers_by_level: var bd: float = float(row.get("branch_density", -1.0)) if bd < 0.0 or bd > 1.0: errs.append({"category": "domain", "message": "%s 分支密度 %f 越域 [0,1]" % [key, bd]}) - # 域并单点(关卡节点图生成.md v1.4 调参表——生成器侧域校验退役,唯此一处) + # 取值域单点=本文件域校验(概念与设计意图指针=关卡节点图生成.md v1.5 参数契约节) var ftw: float = float(row.get("fork_third_way_pct", -1.0)) if ftw < 0.0 or ftw > 100.0: errs.append({"category": "domain", "message": "%s fork_third_way_pct %f 越域 [0,100]" % [key, ftw]}) diff --git a/game/presentation/views/level_map_screen.gd b/game/presentation/views/level_map_screen.gd index fd0af5e7..c7ad7bf6 100644 --- a/game/presentation/views/level_map_screen.gd +++ b/game/presentation/views/level_map_screen.gd @@ -31,6 +31,8 @@ const SLOT_STEP_Y := 58 # 同层槽位纵向步距 const HIT_PAD := 6.0 # 图上命中外扩(指宽容差) const CONFIRM_WINDOW_S := 3.0 # 放弃确认态窗口(秒——超时回落) const COL_HP_BAR_BACK := UiKit.HP_BAR_BACK # 迷你血条深底(对暗面板可辨;值单点收 UiKit) +const DRAG_THRESHOLD := 8.0 # 拖动距离阈值(布局决策 5 provisional——超阈值进拖拽态,拖拽不触发选路) +const WHEEL_STEP := 60.0 # 滚轮横滚单档步进(provisional 实现期定值;方向映射=代拍板:下/右=向右前进向) ## 内部状态件(u2 子域拆件——契约 9 职责轴):_MapState=选路屏运行态与图绘制态(单一变化原因= ## 选路呈现)。layer_decor 域字典承载换层装饰三件(图标贴图/石纹面/tint 层号——装饰域归并形态)。 @@ -39,6 +41,7 @@ class _MapState extends RefCounted: var runner = null var title: Label var canvas: Control + var viewport: LevelMapViewport # 卷轴视口承载件(布局决策 5——画布宿主/裁切/clamp/跟随/指引) var level_label: Label var gp_value: Label var hp_value: Label @@ -54,6 +57,8 @@ class _MapState extends RefCounted: var _cand_ids: Array[int] = [] # 本停点候选 id 集(图上命中合法集;探针直读冻结——住宿主) var _content_size := Vector2(620, 240) # 图内容包络(open_choices 按图拟合——画布 min 尺寸随它;探针直读冻结) var _hover_id := -1 # 悬停预承诺候选(-1 = 无;探针直读冻结) +var _drag_active := false # 拖拽态(超阈值至抬杆——拖拽不触发选路,布局决策 5) +var _drag_press_pos := Vector2(-1, -1) # 拖距判定基准(按下点画布局部坐标;-1 = 无按下跟踪) var abandon_btn: Button # 放弃入口(可见性归组合根 set_abandon_available——只在冒险模式开;探针直读冻结) var status_badge: Button # 状态面板入口角标(顶栏 GP 徽右侧;连接归组合根;探针直读冻结) var _layout_cache := {"nodes": [], "canvas_size": Vector2.ZERO, "pos": {}} # 布局缓存(_layout 纯函数于 (nodes, canvas)——键=nodes 内容等价+画布尺寸,图态换代或画布尺寸变即自然失效;探针直读冻结) @@ -74,15 +79,15 @@ func _init() -> void: base.add_child(tex) _map.layer_decor.noise_rect = tex # 世界侧 tint 承载面(换层色板渐变挂点——§2.7 切片档) base.add_child(UiKit.vignette_rect()) - var center := CenterContainer.new() - center.set_anchors_preset(Control.PRESET_FULL_RECT) - base.add_child(center) - var box := VBoxContainer.new() - box.add_theme_constant_override("separation", 10) - center.add_child(box) - _build_top_bar(box) - _build_canvas(box) - _build_status_bar(box) + # 三段纵排页(布局决策 5 卷轴视口:顶栏/标题在上、图区视口扩张充盈、底栏在下—— + # 视口为窗口屏为框,画布随图生长可超屏) + var page := VBoxContainer.new() + page.set_anchors_preset(Control.PRESET_FULL_RECT) + page.add_theme_constant_override("separation", 10) + base.add_child(page) + _build_top_bar(page) + _build_canvas(page) + _build_status_bar(page) visible = false @@ -122,14 +127,21 @@ func _build_top_bar(box: VBoxContainer) -> void: box.add_child(_map.title) -## 节点图画布域(图上点击 = 唯一提交通道——布局决策 2;mouse_filter STOP 接悬停/点击) +## 节点图区(卷轴视口承载——布局决策 5):视口件为窗口(裁切/offset/clamp/跟随/指引), +## 画布为其子件;图上点击 = 唯一提交通道(布局决策 2),拖拽/滚轮判定留在画布 _gui_input +## (事件流同源——悬停/选路同源,视口件不做父子事件路由) func _build_canvas(box: VBoxContainer) -> void: _map.canvas = Control.new() _map.canvas.custom_minimum_size = Vector2(620, 240) _map.canvas.mouse_filter = Control.MOUSE_FILTER_STOP _map.canvas.draw.connect(_draw_graph.bind(_map.canvas)) _map.canvas.gui_input.connect(_on_canvas_input) - box.add_child(_map.canvas) + _map.canvas.mouse_exited.connect(_on_canvas_mouse_exited) + _map.viewport = LevelMapViewport.new() + _map.viewport.size_flags_horizontal = Control.SIZE_EXPAND_FILL + _map.viewport.size_flags_vertical = Control.SIZE_EXPAND_FILL + box.add_child(_map.viewport) + _map.viewport.setup(_map.canvas, _viewport_anchor, Vector2(1280, 800)) # 兜底尺寸=设计基座(实况窗口以布局为准) ## 底部状态栏域(合并单条:亮米面板一站读齐=头像+生命+属性+本关加成/流派件——demo ④; @@ -297,6 +309,9 @@ func open_choices(cands: Array, runner: LevelRunner) -> void: _fit_canvas(_map.runner.nodes()) _apply_level_tint(int(_map.runner.level_row.get("level_index", 0))) visible = true + # 视口锚定(布局决策 5):入口停点(尚无当前节点)=首锚即达;其余停点/兑付回图=平滑跟随 + # (停点切换与兑付确认回图——减动效开由视口件跳终态) + _map.viewport.reanchor(_map.runner.current_node_id() >= 0) if not was_visible: # 独立屏淡入(spec Transitions:约 200ms;alpha 淡入非明度变化——art-bible §2 明度恒定) modulate.a = 0.0 @@ -323,6 +338,7 @@ func _fit_canvas(nodes: Array) -> void: SLOT_BASE_Y + maxslot * SLOT_STEP_Y + NODE_HALF.y + 24.0) # +24 = 类型文字标签行 _content_size = _content_size.max(Vector2(620, 256)) # 下限(抬高容纳标签行) _map.canvas.custom_minimum_size = _content_size + _map.canvas.size = _content_size # 同帧收敛(视口锚点/包络数学与 _layout 同源读画布尺寸——容器延迟收敛不等锚点) # 换层色板渐变挂点(art-bible §2.7 下探过渡切片档——关卡结算确认→下一关→独立屏淡入链路上的 @@ -356,20 +372,70 @@ func apply_status(payload: Dictionary) -> void: # ---- 图上命中(布局决策 2——唯一提交通道;探针 press_candidate 同路径) ---- +# 拖拽与点击以拖动距离阈值区分(布局决策 5):按下起跟踪拖距,超阈值进拖拽态逐帧平移视口, +# 抬杆不提交;未超阈值的完整点击(按下→抬杆)=提交沿——命中候选即提交,语义零改动。 func _on_canvas_input(ev: InputEvent) -> void: if _map.runner == null or not visible: return - if ev is InputEventMouseMotion: - var nid := _candidate_at(ev.position) # gui_input 事件坐标 = 接收控件局部坐标(push_input 同成立) - if nid != _hover_id: - _hover_id = nid - _map.canvas.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND if nid >= 0 else Control.CURSOR_ARROW + if ev is InputEventMouseButton and ev.pressed and _wheel_pan_step(ev.button_index) != 0.0: + _map.viewport.pan_by(Vector2(_wheel_pan_step(ev.button_index), 0)) + elif ev is InputEventMouseMotion: + _on_canvas_motion(ev) + elif ev is InputEventMouseButton and ev.button_index == MOUSE_BUTTON_LEFT: + _on_canvas_click(ev) + + +## 悬停预承诺与拖拽态推进沿(画布局部坐标——gui_input 事件流同源) +func _on_canvas_motion(ev: InputEventMouseMotion) -> void: + if _drag_active: + _map.viewport.pan_by(ev.relative) # 拖拽态逐帧平移(视口件执行 clamp——本屏只判定) + return + if _drag_press_pos.x >= 0.0 and ev.position.distance_to(_drag_press_pos) >= DRAG_THRESHOLD: + _drag_active = true + _drag_press_pos = Vector2(-1, -1) + if _hover_id != -1: # 进拖拽态清悬停预承诺(拖拽非选路意图) + _hover_id = -1 + _map.canvas.mouse_default_cursor_shape = Control.CURSOR_ARROW _map.canvas.queue_redraw() - elif ev is InputEventMouseButton and ev.button_index == MOUSE_BUTTON_LEFT and ev.pressed: - var nid2 := _candidate_at(ev.position) - if nid2 >= 0: - _submit_choice(nid2) + _map.viewport.pan_by(ev.relative) # 跨阈值帧位移计入平移(拖距全长=平移全长) + return + var nid := _candidate_at(ev.position) # gui_input 事件坐标 = 接收控件局部坐标(push_input 同成立) + if nid != _hover_id: + _hover_id = nid + _map.canvas.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND if nid >= 0 else Control.CURSOR_ARROW + _map.canvas.queue_redraw() + + +## 点击沿与拖拽抬杆(未超阈值的完整点击=提交沿——布局决策 2 语义零改动) +func _on_canvas_click(ev: InputEventMouseButton) -> void: + if ev.pressed: + _drag_press_pos = ev.position + _drag_active = false + return + _drag_press_pos = Vector2(-1, -1) + if _drag_active: + _drag_active = false # 拖拽抬杆=平移结束,不触发选路提交(布局决策 5) + return + var nid2 := _candidate_at(ev.position) + if nid2 >= 0: + _submit_choice(nid2) + + +## 滚轮横滚步进(代拍板:下/右=向右前进向——视线移向深层,画布左移;上/左反向;非滚轮=0) +func _wheel_pan_step(button_index: int) -> float: + if button_index == MOUSE_BUTTON_WHEEL_DOWN or button_index == MOUSE_BUTTON_WHEEL_RIGHT: + return -WHEEL_STEP + if button_index == MOUSE_BUTTON_WHEEL_UP or button_index == MOUSE_BUTTON_WHEEL_LEFT: + return WHEEL_STEP + return 0.0 + + +## 拖距跟踪器生命周期清理(按下即武装——鼠标离画布且未入拖拽态时解除, +## 防丢失 release 沿后的残留 armed 态把后续 motion 误判成拖拽激活) +func _on_canvas_mouse_exited() -> void: + if not _drag_active: + _drag_press_pos = Vector2(-1, -1) # 候选命中:位置 = 布局公式(与 _draw_graph 同源),矩形 = 节点方块 + 外扩容差;非候选格不响应 @@ -413,6 +479,42 @@ func press_candidate(index: int) -> void: _submit_choice(nid) +# ---- 视口锚点(布局决策 5:当前节点居中;入口停点尚无当前节点=锚入口组包围盒居中) ---- + +## 锚点画布坐标提供方(构造注入视口件——本屏供数,视口件只消费) +func _viewport_anchor() -> Vector2: + if _map.runner == null: + return _content_size / 2.0 + var nodes: Array[Variant] = _map.runner.nodes() + var pos := _layout(nodes, _map.canvas) + var cur_id: int = _map.runner.current_node_id() + if cur_id < 0: + return _entry_group_center(nodes, pos) # 入口停点(尚未走出第一步) + var cur := _node_by_id(cur_id, nodes) + if cur.is_empty(): + return _content_size / 2.0 + return pos[cur] + + +func _entry_group_center(nodes: Array, pos: Dictionary) -> Vector2: + # 入口组 = 全部无入边节点(与 _assign_layers 入口判据同源);多入口取包围盒居中 + var inbound := {} + for node in nodes: + for tid in _out_ids(node, nodes): + inbound[tid] = true + var lo := Vector2(INF, INF) + var hi := Vector2(-INF, -INF) + for node in nodes: + if inbound.has(_id_of(node)): + continue + var p: Vector2 = pos[node] + lo = lo.min(p) + hi = hi.max(p) + if lo.x > hi.x: + return _content_size / 2.0 # 空图兜底(无入口——不达路径,防御位) + return (lo + hi) / 2.0 + + func _id_of(node: Dictionary) -> int: # 编号显示经行进器读面(编号空间解析单一出口——单链 = 下标 / 图 = node_depth) return _map.runner.node_id_of(node) diff --git a/game/presentation/views/level_map_viewport.gd b/game/presentation/views/level_map_viewport.gd new file mode 100644 index 00000000..70c5642e --- /dev/null +++ b/game/presentation/views/level_map_viewport.gd @@ -0,0 +1,190 @@ +## 卷轴视口承载件(level-map.md 布局决策 5——关卡画面选路屏):画布宿主与裁切、平移状态 +## 与 clamp、锚点跟随与平滑滚动、指引件(屏缘渐隐带+平移提示 chip)。 +## 纯呈现态:平移位置零核心写、不进存档(重进本屏按锚点规则重新定位);跟随只随停点切换/ +## 兑付回图发生(零自动推进)。拖拽/滚轮判定留画布 _gui_input(事件流同源——悬停/选路同源), +## 本件只管裁切/offset/clamp/跟随/指引;画布包络=画布实际尺寸(open_choices 拟合后同帧收敛)。 +class_name LevelMapViewport +extends Control + +const SCROLL_DUR := 0.3 # 平滑滚动时长(布局决策 5 provisional 0.3s 单段缓动) +const FADE_BAND_W := 70.0 # 屏缘渐隐带宽(布局决策 5/像素级判据②) +const CHIP_SIZE := Vector2(240, 30) # 平移提示 chip(像素级判据③——图区底部居中) +const CHIP_CORNER := 6 # chip 圆角(布局决策 5) +const CHIP_BOTTOM_GAP := 24.0 # chip 距视口底缘(效果图档同族取值) +const CHIP_TEXT := "◄ 拖拽画布 / 滚轮平移 ►" # 14px(FS_HINT 档——布局决策 5) +const EDGE_EPS := 0.5 # 包络边界判定容差(浮点平移累积) + +var _canvas: Control +var _anchor_provider: Callable # () -> Vector2 锚点画布坐标(screen 提供——当前节点/入口组) +var _viewport_size := Vector2.ZERO # 窗口尺寸兜底(setup 注入设计基座——实况窗口以控件 size 为准,布局晚于构造) +var _offset := Vector2.ZERO: # 画布左上角在视口件坐标系的位置(纯呈现态——直驱画布 position) + set(value): + _offset = value + if _canvas != null: + _canvas.position = _offset +var _view_tween: Tween +var _guided_visible := false # 指引件可见态(画布超窗才暗示——浅图无平移余量即隐藏) + + +## 一次交齐注入(code-conventions §1.6 拆分交接:画布宿主、锚点来源、窗口兜底尺寸) +func setup(canvas: Control, anchor_provider: Callable, viewport_size: Vector2) -> void: + _canvas = canvas + _anchor_provider = anchor_provider + _viewport_size = viewport_size + clip_contents = true + add_child(canvas) + _build_guidance() + + +func _notification(what: int) -> void: + # 窗口实况尺寸落定/变化即重锚(首开布局晚于 open_choices 的锚定——隐藏子树容器排序 + # 首个可见帧才传播,4.7 行为;实况窗口以本件 size 为准,落定即收敛锚点) + if what == NOTIFICATION_RESIZED and _canvas != null and _anchor_provider.is_valid(): + reanchor(false) + + +## 锚点跟随(布局决策 5:锚点居中;smooth=停点切换/兑付回图平滑滚动,减动效开=跳终态; +## 重入先杀在飞 tween 再建新——快速连续停点切换防叠加) +func reanchor(smooth: bool) -> void: + if _canvas == null or not _anchor_provider.is_valid(): + return + var target := _clamped_center_offset(_anchor_provider.call()) + _kill_scroll_tween() + if not smooth or ArmedTimer.motion_still(): + _offset = target + _sync_guidance() + return + _view_tween = create_tween() + _view_tween.tween_property(self, "_offset", target, UiKit.motion(SCROLL_DUR)) \ + .set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_OUT) + _sync_guidance() + + +## 手动平移(画布 _gui_input 判定后调用——拖拽沿逐帧/滚轮步进;纯呈现零核心写) +func pan_by(delta: Vector2) -> void: + if _canvas == null: + return + _kill_scroll_tween() + var win := _window_size() + _offset = Vector2( + _axis_pan_offset(_offset.x, delta.x, _canvas.size.x, win.x), + _axis_pan_offset(_offset.y, delta.y, _canvas.size.y, win.y)) + _sync_guidance() + + +## 视口中线的画布坐标(锚点居中判据投影面——浅图=画布中心,深图=夹紧域内当前注视点) +func viewport_center_canvas_pos() -> Vector2: + return _window_size() / 2.0 - _offset + + +## 视口是否钉在画布包络边界(任一超窗轴 offset 顶边——clamp 判据面) +func is_clamped_at_edge() -> bool: + var win := _window_size() + if _canvas == null: + return false + return _axis_at_edge(_offset.x, _canvas.size.x, win.x) \ + or _axis_at_edge(_offset.y, _canvas.size.y, win.y) + + +func _kill_scroll_tween() -> void: + if _view_tween != null and _view_tween.is_valid(): + _view_tween.kill() + _view_tween = null + + +## 单轴锚定 offset:画布不超窗=居中分支(夹紧域退化——布局决策 5); +## 超窗=锚点夹紧在画布包络内,锚点落视口中线(offset = 半窗 − 锚点) +func _axis_center_offset(anchor: float, canvas_len: float, half_win: float) -> float: + if canvas_len <= half_win * 2.0: + return half_win - canvas_len / 2.0 + return half_win - clampf(anchor, half_win, canvas_len - half_win) + + +func _clamped_center_offset(anchor: Vector2) -> Vector2: + var half := _window_size() / 2.0 + return Vector2( + _axis_center_offset(anchor.x, _canvas.size.x, half.x), + _axis_center_offset(anchor.y, _canvas.size.y, half.y)) + + +## 单轴平移收敛:居中轴零平移余量不动;超窗轴 offset 收敛在 [半窗−画布, 0](不出露屏底空档) +func _axis_pan_offset(cur: float, delta: float, canvas_len: float, win_len: float) -> float: + if canvas_len <= win_len: + return cur + return clampf(cur + delta, win_len - canvas_len, 0.0) + + +func _axis_at_edge(offset: float, canvas_len: float, win_len: float) -> bool: + if canvas_len <= win_len: + return false + return offset >= -EDGE_EPS or offset <= win_len - canvas_len + EDGE_EPS + + +## 实况窗口优先(容器布局晚于构造——注入值只兜构造帧数学) +func _window_size() -> Vector2: + if size.x > 0.0 and size.y > 0.0: + return size + return _viewport_size + + +## 指引件(布局决策 5/像素级判据②③):屏缘渐隐带盖在画布之上+图区底部居中提示 chip; +## 可见性=画布超窗(_sync_guidance 随锚定/平移刷新) +func _build_guidance() -> void: + var band_l := TextureRect.new() + band_l.name = "FadeL" + band_l.texture = _fade_gradient(false) + band_l.set_anchors_preset(Control.PRESET_LEFT_WIDE) + band_l.offset_right = FADE_BAND_W + band_l.expand_mode = TextureRect.EXPAND_IGNORE_SIZE + band_l.mouse_filter = Control.MOUSE_FILTER_IGNORE + add_child(band_l) + var band_r := TextureRect.new() + band_r.name = "FadeR" + band_r.texture = _fade_gradient(true) + band_r.set_anchors_preset(Control.PRESET_RIGHT_WIDE) + band_r.offset_left = -FADE_BAND_W + band_r.expand_mode = TextureRect.EXPAND_IGNORE_SIZE + band_r.mouse_filter = Control.MOUSE_FILTER_IGNORE + add_child(band_r) + var chip := PanelContainer.new() + chip.name = "PanHint" + chip.add_theme_stylebox_override("panel", + UiKit.panel_flat(UiKit.HP_BAR_BACK, UiKit.STONE, CHIP_CORNER, 1, Vector4(12, 5, 12, 5))) + chip.set_anchors_preset(Control.PRESET_CENTER_BOTTOM) + chip.offset_left = -CHIP_SIZE.x / 2.0 + chip.offset_right = CHIP_SIZE.x / 2.0 + chip.offset_top = -CHIP_SIZE.y - CHIP_BOTTOM_GAP + chip.offset_bottom = -CHIP_BOTTOM_GAP + chip.custom_minimum_size = CHIP_SIZE + chip.mouse_filter = Control.MOUSE_FILTER_IGNORE + var chip_label := UiKit.label(CHIP_TEXT, UiKit.FS_HINT, false, UiKit.WARM) + chip_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER + chip_label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER + chip.add_child(chip_label) + add_child(chip) + _sync_guidance() + + +## 屏缘渐隐渐变(色取屏底同族 BG_ROOT——代拍板:不透明端 0.9 单段衰减) +func _fade_gradient(transparent_at_left: bool) -> GradientTexture2D: + var grad := Gradient.new() + grad.offsets = PackedFloat32Array([0.0, 1.0]) + grad.colors = PackedColorArray([Color(UiKit.BG_ROOT, 0.9), Color(UiKit.BG_ROOT, 0.0)]) + var tex := GradientTexture2D.new() + tex.gradient = grad + tex.fill_from = Vector2(1, 0.5) if transparent_at_left else Vector2(0, 0.5) + tex.fill_to = Vector2(0, 0.5) if transparent_at_left else Vector2(1, 0.5) + tex.width = int(FADE_BAND_W) + return tex + + +func _sync_guidance() -> void: + var win := _window_size() + var over := _canvas != null and (_canvas.size.x > win.x or _canvas.size.y > win.y) + if over == _guided_visible: + return + _guided_visible = over + for nm in ["FadeL", "FadeR", "PanHint"]: + var node := get_node_or_null(NodePath(nm)) as Control + if node != null: + node.visible = over diff --git a/game/presentation/views/level_map_viewport.gd.uid b/game/presentation/views/level_map_viewport.gd.uid new file mode 100644 index 00000000..0e5acf00 --- /dev/null +++ b/game/presentation/views/level_map_viewport.gd.uid @@ -0,0 +1 @@ +uid://dgin6f6214cbg diff --git a/game/probe/level_map_shot_probe.gd b/game/probe/level_map_shot_probe.gd new file mode 100644 index 00000000..0f920158 --- /dev/null +++ b/game/probe/level_map_shot_probe.gd @@ -0,0 +1,91 @@ +# level_map_shot_probe.gd — 关卡画面视口 golden 采集探针(卷轴视口批 golden 扩项) +# 两 Shot 面(2026-11-05 用户裁:只对拍关卡最开始与关卡 Boss 节点,中间过程不对拍): +# lmap_entry.png = 入口停点(关卡最开始——锚点=入口组包围盒中心夹紧) +# lmap_boss.png = 中段停点锚定末列(Boss 紫赤描边列入屏——viewport_center 夹紧右缘) +# 采集确定性 = 固定种子单关直构(LevelRunner.start_level_external defer_entry / resume_state, +# 零 RNG 消耗路径)+ 探针隔离档(无断点、出厂设置 1280×800);运行=窗口化(--headless 禁—— +# 渲染闸机器面吃真实渲染帧)。截图经 user args 目录落盘,基线换代走 golden_baseline_refresh.sh --lmap。 +# 运行:Godot_console.exe --path game res://probe/level_map_shot_probe.tscn -- +extends Node + +const SEED_L3 := 910212 # 深图固定种子(与 level_map_viewport_probe 同源——图确定性承载) + +func _ready() -> void: + var args := OS.get_cmdline_user_args() + var out_dir := args[0] if args.size() > 0 else "user://" + await get_tree().process_frame + var host := Control.new() + add_child(host) + host.size = get_viewport().get_visible_rect().size + var screen = load("res://presentation/views/level_map_screen.gd").new() + screen.set_anchors_preset(Control.PRESET_FULL_RECT) + host.add_child(screen) + for i in range(6): + await get_tree().process_frame # 布局收敛(视口实况尺寸落定→resize 重锚) + # Shot①:入口停点(关卡最开始) + var runner = _make_runner(true, -1) + screen.open_choices(_cand_nodes(runner), runner) + await _settle() + _shot(out_dir, "lmap_entry.png") + # Shot②:中段停点锚定末列(布局 x 最深的有出边节点——id 不按深度排,锚定后 Boss 列入屏) + var boss_stop := _deepest_with_outs(screen, runner) + runner = _make_runner(false, boss_stop) + screen.open_choices(_cand_nodes(runner), runner) + await _settle() + _shot(out_dir, "lmap_boss.png") + print("[level_map_shot_probe] PASS — 两 Shot 落盘(entry+boss → %s)" % out_dir) + get_tree().quit(0) + + +func _settle() -> void: + for i in range(8): + await get_tree().process_frame + await get_tree().create_timer(0.5).timeout # 平滑滚动终态余量(reanchor tween 0.3s) + + +func _make_runner(entry: bool, node_id: int): + var rng = load("res://core/rng_service.gd").new() + rng.new_adventure(SEED_L3) + var runner = load("res://core/level_runner.gd").new(get_node("/root/ConfigDB"), rng) + var ok: bool + if entry: + ok = runner.start_level_external(3, Callable(runner, "rest_heal_amount"), true) + else: + ok = runner.start_level_external(3, Callable(runner, "rest_heal_amount"), + false, {"node_id": node_id, "visited_ids": [node_id]}) + if not ok: + push_error("[level_map_shot_probe] 状态注入失败(entry=%s node=%d)" % [str(entry), node_id]) + get_tree().quit(1) + return runner + + +func _cand_nodes(runner) -> Array: + var ids: Array = runner.next_candidate_ids() + var out: Array = [] + for node in runner.nodes(): + if ids.has(runner.node_id_of(node)): + out.append(node) + return out + + +func _deepest_with_outs(screen, runner) -> int: + var pos: Dictionary = screen.layout_probe(runner.nodes()) + var best := -1 + var best_x := -INF + for node in runner.nodes(): + if runner.node_out_ids(node).is_empty(): + continue + var x: float = pos[node].x + if x > best_x: + best_x = x + best = runner.node_id_of(node) + return best + + +func _shot(out_dir: String, fname: String) -> void: + DirAccess.make_dir_recursive_absolute(out_dir) # 落盘目录自建(save_png 对缺目录静默失败——刷新链不预建) + var img := get_viewport().get_texture().get_image() + var err := img.save_png(out_dir.path_join(fname)) + if err != OK: + push_error("[level_map_shot_probe] 截图落盘失败 %s(err=%d)" % [fname, err]) + get_tree().quit(1) diff --git a/game/probe/level_map_shot_probe.tscn b/game/probe/level_map_shot_probe.tscn new file mode 100644 index 00000000..d34d0546 --- /dev/null +++ b/game/probe/level_map_shot_probe.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3] + +[ext_resource type="Script" path="res://probe/level_map_shot_probe.gd" id="1"] + +[node name="LevelMapShotProbe" type="Node"] +script = ExtResource("1") diff --git a/game/probe/level_map_viewport_probe.gd b/game/probe/level_map_viewport_probe.gd new file mode 100644 index 00000000..6c1ede3a --- /dev/null +++ b/game/probe/level_map_viewport_probe.gd @@ -0,0 +1,389 @@ +# level_map_viewport_probe.gd — 卷轴视口行为探针(卷轴视口批 R1–R8 验收载体) +# 判的是 level-map.md 布局决策 5 的视口行为四条:浅图整幅居中无裁切(R1)、停点切换/兑付回图 +# 当前节点居中锚定——平滑滚动与减动效瞬切(R2/R7)、拖拽/滚轮手动平移与 clamp 包络—— +# 首末列可达(R3/R4/R5)、拖拽不触发选路提交(R6)、指引件可见性与几何(R8,像素级判据②③)。 +# 真实入口 = 合成拖拽沿/滚轮沿/点击沿经 push_input 进引擎输入管线打在真实画布 _gui_input 上 +# (probe_ui_util.push_drag_at/push_wheel_at/push_click_at);状态注入 = 直调核心层写口构造 +# 单关停点(LevelRunner.start_level_external——defer_entry=入口停点 / resume_state=断点续玩 +# 重建到任意停点,零 RNG 消耗;test-conventions §5.4 自动化测试直构口径),零 main 冒险流程 +# 依赖:真实屏 = LevelMapScreen 实例 + 真实单关 runner。 +# 运行:Godot_console.exe --headless --path . res://probe/level_map_viewport_probe.tscn +extends Node + +const ProbeUiUtil := preload("res://probe/probe_ui_util.gd") +const ViewportScript := preload("res://presentation/views/level_map_viewport.gd") + +const SEED_L1 := 910211 # 浅图停点种子(L1 单链——画布 846.5×256 全幅入窗) +const SEED_L3 := 910212 # 深图停点种子(L3 图——画布超 1280 窗宽,滚动视口生效面) + +var _problems: Array[String] = [] +var _checks := 0 +var _runner # 当前停点的单关 runner(open_choices 驱动随记——查证面共用) + + +func _check(desc: String, ok: bool) -> void: + _checks += 1 + if not ok: + _problems.append(desc) + + +func _ready() -> void: + await get_tree().process_frame + await get_tree().process_frame + var host := Control.new() + add_child(host) + host.size = get_viewport().get_visible_rect().size # 显式置底座(父非 Control 锚点不解析) + var screen = load("res://presentation/views/level_map_screen.gd").new() + screen.set_anchors_preset(Control.PRESET_FULL_RECT) + host.add_child(screen) + await get_tree().process_frame + await get_tree().process_frame # 布局收敛先行(视口实况窗口尺寸就位后再开停点——锚点数学以实况窗口为准) + + var vp = _find_viewport(screen) + if vp == null: + _problems.append("卷轴视口承载件未挂入关卡屏(LevelMapViewport 实例缺位)") + _finish() + return + + await _probe_shallow_no_crop(screen, vp) + await _probe_deep_entry_clamp(screen, vp) + await _probe_wheel_pan(screen, vp) + await _probe_drag_pan(screen, vp) + await _probe_clamp_bounds_and_columns(screen, vp) + await _probe_drag_no_submit(screen, vp) + await _probe_follow_anchor(screen, vp) + await _probe_smooth_scroll_reduced_motion(screen, vp) + await _probe_guidance_chrome(screen, vp) + await _probe_shallow_guidance_hidden(screen, vp) + _finish() + + +## R1 浅图整幅居中无裁切+画布入视口件承载(画布=视口首子件——setup 注入序) +func _probe_shallow_no_crop(screen, vp) -> void: + _runner = _make_runner_entry(1, SEED_L1) + screen.open_choices(_cand_nodes(_runner), _runner) + await get_tree().process_frame + await get_tree().process_frame + var canvas: Control = vp.get_child(0) as Control + if canvas == null: + _problems.append("R1 画布实例缺位(视口首子件非 Control)") + return + _check("R1 浅图画布全幅入窗(canvas=%s window=%s)〔卷轴批 V1〕" % [canvas.size, vp.size], + canvas.size.x <= vp.size.x + 0.5 and canvas.size.y <= vp.size.y + 0.5) + var want: Vector2 = (vp.size - canvas.size) / 2.0 + _check("R1 居中分支 offset 定位(want=%s got=%s)〔卷轴批 V1〕" % [want, canvas.position], + canvas.position.distance_to(want) <= 0.5) + _check("R1 画布矩形在窗内无裁切〔卷轴批 V1〕", vp.get_global_rect().encloses(canvas.get_global_rect())) + + +## R5 前置+深图入口停点:锚点=入口组包围盒中心夹紧(spec :101——多入口并列取包围盒居中) +func _probe_deep_entry_clamp(screen, vp) -> void: + _runner = _make_runner_entry(3, SEED_L3) + screen.open_choices(_cand_nodes(_runner), _runner) + await get_tree().process_frame + await get_tree().process_frame + var center: Vector2 = vp.viewport_center_canvas_pos() + var half: float = vp.size.x / 2.0 + var canvas_len: float = _canvas_len(screen) + _check("R5 入口锚定后视口中线在夹紧域内(center.x=%.1f ∈ [%.1f, %.1f])〔卷轴批 V5〕" % + [center.x, half, canvas_len - half], + center.x >= half - 0.5 and center.x <= canvas_len - half + 0.5) + # 入口停点候选 = 入口节点——包围盒中心夹紧即锚点(本档图入口分布跨图,中心落夹紧域) + var nodes: Array = _runner.nodes() + var pos: Dictionary = screen.layout_probe(nodes) + var ids: Array = _runner.next_candidate_ids() + var lo := INF + var hi := -INF + for node in nodes: + if ids.has(_runner.node_id_of(node)): + lo = minf(lo, pos[node].x) + hi = maxf(hi, pos[node].x) + var want: float = clampf((lo + hi) / 2.0, half, canvas_len - half) + _check("R5 入口组包围盒中心=锚点(bbox=%.1f center=%.1f want=%.1f)〔卷轴批 V5〕" % + [(lo + hi) / 2.0, center.x, want], absf(center.x - want) <= 0.5) + + +## R4 滚轮横滚移动视口(下=向右前进向——代拍板映射;窗内平移不钉边界,与 R5 两极 true 构成翻转) +func _probe_wheel_pan(screen, vp) -> void: + var before: float = vp.viewport_center_canvas_pos().x + var pos: Vector2 = vp.get_global_rect().get_center() + ProbeUiUtil.push_wheel_at(self, pos, true) + await get_tree().process_frame + await get_tree().process_frame + var after: float = vp.viewport_center_canvas_pos().x + _check("R4 滚轮下单档平移 +60(before=%.1f after=%.1f)〔卷轴批 V4〕" % [before, after], + absf(after - before - 60.0) <= 0.5) + _check("R4 窗内平移不钉边界(is_clamped_at_edge=false)〔卷轴批 V4〕", not vp.is_clamped_at_edge()) + ProbeUiUtil.push_wheel_at(self, pos, false) + await get_tree().process_frame + await get_tree().process_frame + _check("R4 滚轮上回移 −60〔卷轴批 V4〕", + absf(vp.viewport_center_canvas_pos().x - before) <= 0.5) + + +## R3 拖拽平移移动视口(窗内位移量=拖拽位移,无 clamp 干扰) +func _probe_drag_pan(screen, vp) -> void: + # 先滚入窗内区(两档 +120——避开左包络边界的 clamp 吸收),再拖拽核位移 + var pos: Vector2 = vp.get_global_rect().get_center() + ProbeUiUtil.push_wheel_at(self, pos, true) + ProbeUiUtil.push_wheel_at(self, pos, true) + await get_tree().process_frame + await get_tree().process_frame + var before: float = vp.viewport_center_canvas_pos().x + ProbeUiUtil.push_drag_at(self, pos, Vector2(-40, 0)) + await get_tree().process_frame + await get_tree().process_frame + var after: float = vp.viewport_center_canvas_pos().x + _check("R3 拖拽左移 −40 平移量逐位一致(画布随手——视线 +40,before=%.1f after=%.1f)〔卷轴批 V3〕" % [before, after], + absf(after - before - 40.0) <= 0.5) + # 复位到左包络边界,给后续探针稳定起点 + ProbeUiUtil.push_drag_at(self, pos, Vector2(2000, 0)) + await get_tree().process_frame + await get_tree().process_frame + + +## R5 clamp 边界与首末列可达(拖拽两极) +func _probe_clamp_bounds_and_columns(screen, vp) -> void: + var nodes: Array = _runner.nodes() + var pos: Dictionary = screen.layout_probe(nodes) + var first_node := _extreme_node(pos, nodes, true) + var last_node := _extreme_node(pos, nodes, false) + var vp_rect: Rect2 = vp.get_global_rect() + # 右极:拖拽超包络 → 视口钉左缘,首列(深度 0)入屏 + ProbeUiUtil.push_drag_at(self, vp_rect.get_center(), Vector2(2000, 0)) + await get_tree().process_frame + await get_tree().process_frame + var center: float = vp.viewport_center_canvas_pos().x + var half: float = vp.size.x / 2.0 + _check("R5 拖拽超包络收敛夹紧域(center.x=%.1f)〔卷轴批 V5〕" % center, + center >= half - 0.5 and center <= _canvas_len(screen) - half + 0.5) + _check("R5 右极视口钉边界(is_clamped_at_edge=true)〔卷轴批 V5〕", vp.is_clamped_at_edge()) + _check("R5 首列(深度 0)中心入屏〔卷轴批 V5〕", + vp_rect.has_point(_node_screen_pos(screen, pos, first_node))) + # 左极:反向超包络 → 视口钉右缘,末列(含 Boss 紫赤描边列)入屏 + ProbeUiUtil.push_drag_at(self, vp_rect.get_center(), Vector2(-2000, 0)) + await get_tree().process_frame + await get_tree().process_frame + _check("R5 左极视口钉边界(is_clamped_at_edge=true)〔卷轴批 V5〕", vp.is_clamped_at_edge()) + _check("R5 末列中心入屏(拖拽两极可达——布局决策 5)〔卷轴批 V5〕", + vp_rect.has_point(_node_screen_pos(screen, pos, last_node))) + + +## R6 拖拽不触发选路提交;阈值另一侧完整点击仍提交(提交语义零改动) +func _probe_drag_no_submit(screen, vp) -> void: + # 重建到中段可居中停点(候选=停点出边——候选节点居屏中可拖可达) + var stops := _centerable_stops(screen, vp) + if stops.size() < 3: + _problems.append("R6 可居中停点不足(=%d)" % stops.size()) + return + _runner = _make_runner_at_stop(3, SEED_L3, _runner.node_id_of(stops[0])) + screen.open_choices(_cand_nodes(_runner), _runner) + await get_tree().process_frame + await get_tree().process_frame + var nodes: Array = _runner.nodes() + var cands: Array = _runner.next_candidate_ids() + var target := {} + for node in nodes: + if cands.has(_runner.node_id_of(node)): + target = node + break + if target.is_empty(): + _problems.append("R6 候选节点缺位(候选=%s)" % str(cands)) + return + var gpos: Vector2 = _node_screen_pos(screen, screen.layout_probe(nodes), target) + var submitted: Array = [] + var on_route := func(nid: int) -> void: submitted.append(nid) + screen.route_chosen.connect(on_route) + ProbeUiUtil.push_drag_at(self, gpos, Vector2(120, 24)) + await get_tree().process_frame + await get_tree().process_frame + _check("R6 拖拽沿起止候选上方零提交(submitted=%s)〔卷轴批 V6〕" % str(submitted), submitted.is_empty()) + _check("R6 拖拽后本屏未关〔卷轴批 V6〕", screen.visible) + var gpos2: Vector2 = _node_screen_pos(screen, screen.layout_probe(nodes), target) # 拖拽平移后重算投影(画布随视口移动) + ProbeUiUtil.push_click_at(self, gpos2) + await get_tree().process_frame + await get_tree().process_frame + _check("R6 完整点击(未超阈值)仍提交选路——阈值区分另一侧〔卷轴批 V6〕", submitted.size() == 1) + screen.route_chosen.disconnect(on_route) + + +## R2 停点切换后当前节点居中(视口中线投影 x=640±2——视口满屏宽即屏中线) +func _probe_follow_anchor(screen, vp) -> void: + var stops := _centerable_stops(screen, vp) + if stops.size() < 3: + _problems.append("R2 可居中停点不足(=%d)" % stops.size()) + return + _runner = _make_runner_at_stop(3, SEED_L3, _runner.node_id_of(stops[1])) + screen.open_choices(_cand_nodes(_runner), _runner) + await get_tree().create_timer(0.6).timeout # 平滑滚动终态(0.3s 单段缓动+余量) + var sx: float = _node_screen_pos(screen, screen.layout_probe(_runner.nodes()), stops[1]).x + var want: float = vp.get_global_rect().get_center().x + _check("R2 停点切换后当前节点投影=视口中线(got=%.1f want=%.1f±2)〔卷轴批 V2〕" % [sx, want], + absf(sx - want) <= 2.0) + + +## R7 平滑滚动有 tween 中间帧;减动效开=位置即达(画布坐标域判定) +func _probe_smooth_scroll_reduced_motion(screen, vp) -> void: + var saved_scale: float = UiKit.motion_scale + UiKit.motion_scale = 1.0 + var stops := _centerable_stops(screen, vp) + if stops.size() < 3: + _problems.append("R7 可居中停点不足(=%d)" % stops.size()) + return + # 起点:锚在停点 A(画面已停稳) + _runner = _make_runner_at_stop(3, SEED_L3, _runner.node_id_of(stops[0])) + screen.open_choices(_cand_nodes(_runner), _runner) + await get_tree().create_timer(0.6).timeout + var start: float = vp.viewport_center_canvas_pos().x + # 停点切换 A→B(屏幕保持可见=兑付回图同路径)——平滑滚动 + var target_b: float = screen.layout_probe(_runner.nodes())[stops[1]].x + _runner = _make_runner_at_stop(3, SEED_L3, _runner.node_id_of(stops[1])) + screen.open_choices(_cand_nodes(_runner), _runner) + await get_tree().create_timer(0.05).timeout # 中间帧采样(300ms 单段缓动早段) + var mid: float = vp.viewport_center_canvas_pos().x + var total := absf(target_b - start) + _check("R7 平滑滚动中间帧在途中(start=%.1f mid=%.1f target=%.1f)〔卷轴批 V7〕" % [start, mid, target_b], + total > 4.0 and absf(mid - start) > 0.5 and absf(mid - target_b) > 0.5 + and (mid - start) * (target_b - start) > 0.0) # 同向在途 + await get_tree().create_timer(0.5).timeout + _check("R7 平滑滚动终态到位〔卷轴批 V7〕", + absf(vp.viewport_center_canvas_pos().x - target_b) <= 2.0) + # 减动效置位(UiKit.motion 通道单点——设置面开关写同一值):停点切换 B→C 位置即达 + UiKit.motion_scale = 0.5 + var target_c: float = screen.layout_probe(_runner.nodes())[stops[2]].x + _runner = _make_runner_at_stop(3, SEED_L3, _runner.node_id_of(stops[2])) + screen.open_choices(_cand_nodes(_runner), _runner) + await get_tree().process_frame + await get_tree().process_frame + _check("R7 减动效开=位置即达(got=%.1f target=%.1f)〔卷轴批 V7〕" % + [vp.viewport_center_canvas_pos().x, target_c], + absf(vp.viewport_center_canvas_pos().x - target_c) <= 2.0) + UiKit.motion_scale = saved_scale + + +## R8 指引件可见性与几何(深图超窗——像素级判据②③) +func _probe_guidance_chrome(screen, vp) -> void: + var band_l: Control = vp.get_node_or_null(NodePath("FadeL")) + var band_r: Control = vp.get_node_or_null(NodePath("FadeR")) + var chip: Control = vp.get_node_or_null(NodePath("PanHint")) + if band_l == null or band_r == null or chip == null: + _problems.append("R8 指引件缺位(FadeL/FadeR/PanHint)〔卷轴批 V8〕") + return + _check("R8 深图渐隐带可见〔卷轴批 V8〕", band_l.visible and band_r.visible) + _check("R8 渐隐带宽 70px(L=%.1f R=%.1f)〔卷轴批 V8〕" % [band_l.size.x, band_r.size.x], + absf(band_l.size.x - 70.0) <= 0.5 and absf(band_r.size.x - 70.0) <= 0.5) + _check("R8 平移提示 chip 可见且 240×30(size=%s)〔卷轴批 V8〕" % chip.size, + chip.visible and absf(chip.size.x - 240.0) <= 0.5 and absf(chip.size.y - 30.0) <= 0.5) + _check("R8 chip 图区底部居中(水平中线对窗中线±2)〔卷轴批 V8〕", + absf(chip.get_global_rect().get_center().x - vp.get_global_rect().get_center().x) <= 2.0) + + +## R8 浅图指引件隐藏(无暗示必要) +func _probe_shallow_guidance_hidden(screen, vp) -> void: + _runner = _make_runner_entry(1, SEED_L1) + screen.open_choices(_cand_nodes(_runner), _runner) + await get_tree().process_frame + await get_tree().process_frame + var band_l: Control = vp.get_node_or_null(NodePath("FadeL")) + var chip: Control = vp.get_node_or_null(NodePath("PanHint")) + _check("R8 浅图画布不超窗指引件隐藏〔卷轴批 V8〕", + band_l != null and not band_l.visible and chip != null and not chip.visible) + + +# ---- 驱动与查证工具(状态注入面——直调核心层写口) ---- + +## 入口停点 runner(defer_entry——选路态挂起、候选=入口节点) +func _make_runner_entry(level_index: int, seed_val: int): + var rng = load("res://core/rng_service.gd").new() + rng.new_adventure(seed_val) + var runner = load("res://core/level_runner.gd").new(get_node("/root/ConfigDB"), rng) + if not runner.start_level_external(level_index, Callable(runner, "rest_heal_amount"), true): + _problems.append("状态注入失败:start_level_external(%d, %d) 未受理" % [level_index, seed_val]) + return runner + + +## 中段停点 runner(断点续玩重建——图由种子+参数档重生成同图,零 RNG 消耗) +func _make_runner_at_stop(level_index: int, seed_val: int, node_id: int): + var rng = load("res://core/rng_service.gd").new() + rng.new_adventure(seed_val) + var runner = load("res://core/level_runner.gd").new(get_node("/root/ConfigDB"), rng) + if not runner.start_level_external(level_index, Callable(runner, "rest_heal_amount"), + false, {"node_id": node_id, "visited_ids": [node_id]}): + _problems.append("状态注入失败:断点停点 %d 未受理" % node_id) + return runner + + +func _cand_nodes(runner) -> Array: + var ids: Array = runner.next_candidate_ids() + var out: Array = [] + for node in runner.nodes(): + if ids.has(runner.node_id_of(node)): + out.append(node) + return out + + +## 深图可居中停点选取(有出边且画布 x 落在夹紧域内的节点——锚定不贴边、当前节点投影可居中; +## 按 x 降序去重取第 idx 个——同层同 x 只计一个,层距 122 保证停点间滚动位移充分) +func _centerable_stops(screen, vp) -> Array: + var nodes: Array = _runner.nodes() + var pos: Dictionary = screen.layout_probe(nodes) + var half: float = vp.size.x / 2.0 + var canvas_len: float = _canvas_len(screen) + var by_x_desc: Array = nodes.duplicate() + by_x_desc.sort_custom(func(a, b) -> bool: return pos[a].x > pos[b].x) + var picked: Array = [] + var seen_x := {} + for node in by_x_desc: + if _runner.node_out_ids(node).is_empty(): + continue + var x: float = pos[node].x + if x < half + 20.0 or x > canvas_len - half - 20.0 or seen_x.has(x): + continue + seen_x[x] = true + picked.append(node) + return picked + + +func _find_viewport(screen) -> Control: + return _find_by_script(screen, ViewportScript) + + +func _find_by_script(root: Node, script: Script) -> Control: + if root.get_script() == script: + return root as Control + for child in root.get_children(): + var found := _find_by_script(child, script) + if found != null: + return found + return null + + +func _canvas_len(screen) -> float: + return screen.canvas_probe()["min_size"].x # 画布包络宽(open_choices 拟合值——画布尺寸即它) + + +func _node_screen_pos(screen, pos: Dictionary, node: Dictionary) -> Vector2: + return screen.canvas_probe()["origin"] + pos[node] + + +func _extreme_node(pos: Dictionary, nodes: Array, first: bool) -> Dictionary: + var best := {} + var best_x := INF if first else -INF + for node in nodes: + var x: float = pos[node].x + if (first and x < best_x) or (not first and x > best_x): + best_x = x + best = node + return best + + +func _finish() -> void: + if _checks == 0: + _problems.append("零断言执行(断言数下限闸——三硬闸③)") + if _problems.is_empty(): + print("[level_map_viewport_probe] PASS — 卷轴视口行为断言全绿(%d 项)" % _checks) + get_tree().quit(0) + else: + for p in _problems: + printerr("[level_map_viewport_probe] FAIL — " + p) + get_tree().quit(1) diff --git a/game/probe/level_map_viewport_probe.gd.uid b/game/probe/level_map_viewport_probe.gd.uid new file mode 100644 index 00000000..06779e47 --- /dev/null +++ b/game/probe/level_map_viewport_probe.gd.uid @@ -0,0 +1 @@ +uid://cprbakccv06re diff --git a/game/probe/level_map_viewport_probe.tscn b/game/probe/level_map_viewport_probe.tscn new file mode 100644 index 00000000..5a3ee798 --- /dev/null +++ b/game/probe/level_map_viewport_probe.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3] + +[ext_resource type="Script" path="res://probe/level_map_viewport_probe.gd" id="1"] + +[node name="LevelMapViewportProbe" type="Node"] +script = ExtResource("1") diff --git a/game/probe/probe_ui_util.gd b/game/probe/probe_ui_util.gd index 2a33d2b3..d64ea998 100644 --- a/game/probe/probe_ui_util.gd +++ b/game/probe/probe_ui_util.gd @@ -141,6 +141,42 @@ static func push_click_at(main, pos: Vector2) -> void: main.get_viewport().push_input(up, true) +# 真输入拖拽沿(press→motion×steps→release 成对经 push_input 进引擎输入管线——卷轴视口批 +# R3/R5/R6 驱动沿;沿 push_click_at 同式。relative 按步显式置值——合成事件的位移量由事件 +# 自身承载,被测面按 relative 逐帧平移) +static func push_drag_at(main, pos: Vector2, delta: Vector2, steps: int = 4) -> void: + var down := InputEventMouseButton.new() + down.position = pos + down.global_position = pos + down.button_index = MOUSE_BUTTON_LEFT + down.pressed = true + main.get_viewport().push_input(down, true) + for i in range(1, steps + 1): + var cur := pos + delta * float(i) / float(steps) + var mv := InputEventMouseMotion.new() + mv.position = cur + mv.global_position = cur + mv.relative = delta / float(steps) + main.get_viewport().push_input(mv, true) + var up := InputEventMouseButton.new() + up.position = pos + delta + up.global_position = pos + delta + up.button_index = MOUSE_BUTTON_LEFT + up.pressed = false + main.get_viewport().push_input(up, true) + + +# 真输入滚轮沿(单档滚轮事件经 push_input——卷轴视口批 R4 驱动沿;方向映射在被测面, +# 本工具只发原始滚轮档) +static func push_wheel_at(main, pos: Vector2, wheel_down: bool = true) -> void: + var ev := InputEventMouseButton.new() + ev.position = pos + ev.global_position = pos + ev.button_index = MOUSE_BUTTON_WHEEL_DOWN if wheel_down else MOUSE_BUTTON_WHEEL_UP + ev.pressed = true + main.get_viewport().push_input(ev, true) + + # 营地经进档开层(卡② mn9 新路径——campbtn 已撤;槽模板注入隔离命名空间,防碰真实槽 # user://save_slot_N.json——真实档红线)。创建=激活=暂行开营地(卡③ Q3 乙落点); # 驱动后写盘目标=隔离槽文件(持久化断言读 user://_slot_1.json)。返回 false=新档钮缺失(驱动中断)。 diff --git a/game/probe/ui_input_probe.gd b/game/probe/ui_input_probe.gd index 65f89a51..e3ecde7c 100644 --- a/game/probe/ui_input_probe.gd +++ b/game/probe/ui_input_probe.gd @@ -87,6 +87,14 @@ func _ready() -> void: evf.position = fog_pos evf.global_position = fog_pos main.get_viewport().push_input(evf, true) + # 完整点击=press+release 成对(卷轴视口批阈值语义:拖距跟踪器由按下起武装, + # 单 press 沿会留 armed 态污染后续 motion 判定——判据语义不变:雾下点击零提交) + var evf2 := InputEventMouseButton.new() + evf2.button_index = MOUSE_BUTTON_LEFT + evf2.pressed = false + evf2.position = fog_pos + evf2.global_position = fog_pos + main.get_viewport().push_input(evf2, true) await get_tree().process_frame await get_tree().process_frame ro.route_chosen.disconnect(on_route) @@ -114,6 +122,14 @@ func _ready() -> void: evc.position = gpos evc.global_position = gpos main.get_viewport().push_input(evc, true) + # 完整点击=press+release 成对(卷轴视口批阈值语义:提交沿=未超阈值的抬杆—— + # 判据语义不变:图上真实点击提交选路;单 press 沿不再是提交沿) + var evr := InputEventMouseButton.new() + evr.button_index = MOUSE_BUTTON_LEFT + evr.pressed = false + evr.position = gpos + evr.global_position = gpos + main.get_viewport().push_input(evr, true) await get_tree().process_frame await get_tree().process_frame if main.ui.modals.run.level_screen.visible or main.run_scope.runner.awaiting_choice(): diff --git a/game/tests/golden/README.md b/game/tests/golden/README.md index 4dac9021..9936ab1d 100644 --- a/game/tests/golden/README.md +++ b/game/tests/golden/README.md @@ -4,11 +4,15 @@ `windows/` 与 `mac/` 子目录各持一套,平台内部照常严格比对,跨平台不互比; 平台选择实现单点 = `tools/gate_platform.sh` 的 `gate_platform_id`,比较器 `tools/golden_compare.py` 自动拼平台子目录)。本目录现持:`windows/`(棋盘三图 `board_L1_dungeon` / `board_L2_underdark` / -`board_L3_deep_underdark`,裁剪区 900×760 + 启动态菜单 `menu_boot`,全屏)、 -`level_map`(关卡画面全屏,历史基线留根——现行闸件未对拍它)、 +`board_L3_deep_underdark`,裁剪区 900×760 + 启动态菜单 `menu_boot`,全屏 + 关卡视口两 Shot +`lmap_entry` / `lmap_boss`——2026-11-05 用户裁两 Shot 面:只对拍关卡最开始(入口停点)与 +关卡 Boss 节点(末列锚定),中间过程不对拍)、 +`level_map`(关卡画面全屏,历史基线留根——现行闸件未对拍它,由两 Shot 面接替)、 `palette_baseline/`(色板基线,纯文件内容比对与平台无关)。 比对判据与工具见 `tools/golden_compare.py` -(逐像素灰度差 >16 的像素占比 ≤2%)。 +(逐像素灰度差 >16 的像素占比 ≤2%)。两 Shot 基线采集=`res://probe/level_map_shot_probe.tscn` +(固定种子单关直构——确定性采集),换代入口=`tools/golden_baseline_refresh.sh --lmap`; +他平台(mac)的关卡视口基线尚未冻结——渲染闸对本平台缺基线记 SKIP 不判红,冻结义务归批末呈报。 **未建锚面备案**:营地/设置/战斗三屏与战末结算/三选一/图例/调试浮窗四浮层无改前 golden 锚;这些呈现面的等价证据承载=现役探针/单元测试断言面+实机目检(体验验证清单 ㊵ 节)。 diff --git a/game/tests/golden/windows/lmap_boss.png b/game/tests/golden/windows/lmap_boss.png new file mode 100644 index 0000000000000000000000000000000000000000..90d14187a08518c536806be2f91f990a3d56b401 GIT binary patch literal 215164 zcmYg&by$;O`}XLN4(V39yGMh9AfgfiBLqZHx?>_pmXZ>NkXKe~zP~*J(?`}5V^(||q z240(76BU1CPQ#vlO~oWGx#72d*5|m2^a%|5wLM{1hen6-{ihj z;89XwJF>7v0>i4VrtSZPUilD#zJ+cc@pz>b=o`i6Opc>&kk zQ@p6}9ynp9)OMN);z=u`fw7j!t$sr}r}sWr>48EX6_$i+zJSFB(3NOWvY;^%=sM@d zOtnqdl2-zIEz(CYCa>yJ8jeGQi^LIcV{k$Q4K4v7Z(WqmJx%@g3#zgKtoK2%7B^0h z!o6^O7k{ykAAP`J8gvyF-Xwo^tCSPiox(y3(6Bk2#d#|alou!WCb9(2kaioVZ?|WJ zYg~S)s`+eKLv^!@CZ7g6Voz&#rDR~sa@z8K11bJPb&}YC6vYa?<~k&gpWSUggz>cj zb*CN&^Ueomlcz_Qt>&5svvRc@oqJslBb^ewq31b=P4k?c+HXLs1&Gk_%*|oM(lLhD zkOBl;09V}whDR#VYj}lg5d-(gxOx;{Q9dmc7bcH$mnc_qev%_DT#?ewE6VW#Lxa++ zR{CQ9P}k=RBPf1=i9dAHS-n+VmUy{M6MP*wYjpkAdao;&HH+%S=XWiF*Ap@xE`gcN zPfUvnd;gN+irH`?hMh=c$4&kGNI~u0YGvB2y_D1={E7K~Z3{UJctQGsRC>GjP43*;yGLR<0dkwKOM-sLv z&xR9FsN)1w&Zn{9?|p#M6c)yAz6y}ptO9l#Il!<6gNd;9W7I;@Oczo@cL^9T)t#9W zs=jJ`$U8DH_SVUafua~wzjM6Rb<|yk0)&sCh6P-0BkCw!gDr7n=~AQC{B-3;kL*EI zO@Axmd=dMVubs^&dO}N8?Q5ZHTh#mtJtUH&6uV}M?WqJx!$^+n2c{!|I@M;vSA%1vw6{(NcHp^wY`qXK9p-xB9J&#gFCHU59v=6oOlyrvYbv zpRo2zL^G%;J?a?D5tB}0gKn(Qw32Bb+L#^G=^ZS~-p76tMZXz2_0=xru|vy^i*YJJ zY7+YSLktm+y=eZlrMw+yxv}zHR*hx`+X-DM`pJT27X4duOmE}mJBL}G#QJ>g0|J`* z0Ig~?3=LVGIefw!vI?E#1h{~a7r^rBvPEy@6^lmkT)&E~l=fNjM(@4Nl!CEY zY4bl2)@gSXIZmYDSsMp5Tb;gNz9yWs;~8ztlIKu9z?K5tSa^t=J|D%FR->V_oWQir zDs&a-AVg285+1^X=VGN-+l1ox)c2|`rm4%le@bmQn`aP_Yc z`f9{ZRR%TV$+;XDO;>I^bng9vPPPX|~f z(4W<(k6lG{j2^9Zoi=t*TJ=VIEtVnIRX0v=cQhGQ)MiUwTQ8t?ll#k=-Qacc1|#o( zZ!u1AVMH?G5y6pnN{CqEr_>w1tdt*>2a8;TPLWm+^WO>k))o45tk!_fbx||16Qomb zboTfaqZD1aWIok1FA@IT_r^Hevp+BOCtXnmAJHDUV><>JOwcIx-XGmxUe2G{UVjx2 zzz@L(pDW(PW*vbQhk9vJ?cPr1jlQr}!++y}dhKN$d))QBEw9F$Ft~W~%;D z)+$}jy#D325;j}2EPq$@izaHNJyk&|2A+>^0v4*-s&Nh(Icn08T>P;S@f(A5 zK-;W4i9Irw8C1YXk&+lKYa%60i945);CI4UijCCLf~8pRpG?B7T+UNYX{e(>2A)2> ztc*jGzf&`l3=SvS z9sGr9=Gqn3|C)JYsPcGl+<{-;soxg<6>1#B1N4vh+JapApQSUHmFZVtsDa*>6CK8g zYvk~C>9EMzx*)^cFeUs$G$OoVE?z3*@6)l3AQ_%SO1eBsC@JpiFd&Cd2f`u$Qpsy2 ze7}uS&pDP85UKgk)n2N!N+-P3=Ch_aTR;n4C*pwZe%sAfW3z^SNB9Z zh_$qW)Q^q_r0+btcke`?zR13)_*;cl{Kql#2;UD`x@qDGb`KfG(W@YR6`nU^eUUy% zcgK>G_N|7Ae{M!iQcX`?@FR}XmewE;bZ zk0~vGR3VygR%;$&O+iOwraqr_I=;p0SBo=3Pp>zbUUy*qq_6FP0*ad&0A3M4^HTi^ zqUtOTBNQ-n=+p(irbFi01xA-P)c1+;^|Qer9X=C}k+SPTOK$!tcFr>f*$++6(UQL3 z7W{B=pVRR7EKKB8xxCKoi2Rlv96ltU(pa|EYQI3zTM%;hwEb}vWqLHjkB5}vDRjuu z*{JYL0cw%Bmkgq;BpzLs)sbg%rveYTA0|%oNM^#qxZ!EgrK=K*AX*b6h&ECq1 zHWdE_CwE%v)7hhfvRl3l&ldzH+An*{zjrYIT4f}}kXFpI@`uB>RLllTg1zatc!I3ijU>}})TsujSZ=FDI!%(eUQnl{gCeeb33{|PSKvMN(>aa> z$~}F<KCJN(Kvb{BHR)*c>1CO8!mypOD4 zX9OvJb7dMX$ne-n8pdH6=`Mr&lSk{>Ue5zuQGgO1QIF^)r}25$pd)SDr*&v3#0zJk zqJoE9$8iDKrDEw{;%1!Ef$a@KWA*~N3O!N)R4Jg57R9W@ySiUYl>HkcJrUlwLS@KC zML&Pto32BxaTl?-12R2#biciV>x^qucT8j)B;}~+DQo00_i6WoO|L1$iM0b(oro7J z#d-RWSMJoGbyO*U_mrVGpB0A&?9VkdhOAQtqluTh$ec5DZ#}b!FMh>YiOcWRxP1LW zq>G2AsrCDOS0laE7^X1ed5t%@#=Vm-(tam2ITau)eoc~wtS747^YNCv?nWLo=H}+F zVFD)lq=7v42>pKgz?^sX;j*r$-^Fq2j?ZLiUb>LT=8M?^&0>KGuH2Hpd8zq}iuRV< zpI7fRnlF2w+T=G0r=$$#a*`MGP!ZG6nB}Pp51%(fKS*cSPf_ES`mIWcY;P|Hu?G=P z2|FL;HgXYBr(3OoQ^+Hl__%s5SQN@av_Q*qzp3&kN_gftI9`q^2;(40Fl8+0UYJPN zsLoG*E-Ef+>}5LEtNr$?f@+Fc=e^RpE45Xi1dDP$#;V{q2?*1h;Qv!t@V7pI!Jkkn z2*rY@2hgKjy9j|}<2@P}*bRQM(fGG`+GQ3Zp`n$3L%e_X$eFVpf~l~T7}$`^#)GgY ztJ=7jOh2<0GS*13B@@4fj1C}TQ)lH0d;~!Na9ttG1x0e6wKb0#{k3bvIGp3zuIag3 z(-kNAeDR;9`2PAj=>Ev+W-1$qSxA1~k!!jqUl3`Oz(SJ|hta=SV{tfPikBT-p3a*ZD zhuc!dkO$@YZ_PDjhXzgW`-X?V&7Jd}qY(D&_7sd8W-2VMMXT1_QCOK6Y`M{0WaCD!s5rUun^UBARP#hQ^fNT9_A+4Im&-L%y-+A z0;8qDTqy5FhTCkGqwMeo&nV#9)IKTn%$ci7utwET(qnWb*p?+1I@UAZ0eBZAAmU3Ay5o39T6I<%(;7KBB%~kzgfg zjMpsp2K_kyIATp)(mbLj!xgBPJMy#~VS9~SaAknPT9wJH^7}4t$PxXQf%h9^`bO6S zPx{#{t1Hbg$XWXC!^Oy2`w-hg+VeP^An+|4Zb(8NfnRigG=d%F4fx}9_4c;yzd@Yv3 z(e~;HkArMRo+mBKxJpn#c~@XJ0oCidVSDRKAE7Bw&MQPBSlnRohkz!zw5^Bus^Ysr z8)*>&Ci=|@u)TkRD<$;9eZbF7nSamN$r~z_@CY#+LS|^YAELBB56Nn z1R|$AJScDw#t-t^A$10kwUU324S(M40JvgKW%C94#Zq$N>+Al5MhAQf2${cUY(Vrb z1TPVZ%r50{08T{!vW`O(q(?;ioC7xn!&x^vNA7z;VksE$ypP3#;>poM*4iuT=+C*ENg=X>TQN!x#mT(xg~BPH8tIw4-mxvDx3_h* zD?1tPhiMej-nxSou-f_PFDh>J8QdUN7(cHqIH~Tg-t*1qFC+)2x-pE4lJZmyc+$vbmLGDYRLAH;dGc z-le;ku;fNd0F7hgocP_Z#tYZ}z6}ydmP%kl)6?RVaT5q*3DP8&?l)P{>+R7~h&)mN zH+$0yS9htkgdzz)@hI z)^$2)_Uqg%X6P%C@38T>6zA_UUS5C22m#{STSFia%FWf9=jAJXu$iTR8F{$^odROx z0OB{VTuAvu^Y+7wyCds%PP^fhO|601h-@`noa|oFqjc~sA`r#GcNOA~VRRAq9$Ueh z?9EZXnEDEbpHGy)YnCY3ue86gY?&aQ|M-$|v>yjMSk-%V6s3t{20}DeV2Buid;0sF zWeN+CVmQ^ZL?)PE@;Oexnqcu+g2l-mtpeg+I53wN4yKxof!!v1bzl?Lj*r|IPuG4K zBaQ;JFU?DGF;I!5r`UL4G)|Kht?{~H{~GQ`+n3kj?1PpaC-dx#!j<~vE+D7xe=GKE zw&!_+GkSe%4W69>KP?t}H2B(}=#G%KeQ?+F>0a9xG94#xke78==Ys^p<5^JA(c@_vGZ^+0#yH=Rd}=X&x2l z!Rpj3xm4EIEcxxC7ujE68hZY6YCwpOISmXWj8vx<`x(VP;V8;kt#aM&a!S2LxUSB0 zqr!1w-q*S494yH~MG@{qw=HLXxC>xqFB;=v8$X&R%5|C&A8L5ch0Q!2DpC%mRS>iY zZk@r(FvVCUotWj_=XMej$e)~UJXPVlBHK9jpaPo1jMDb`vVz3xnR=V)9bF>4yeUwbc79eUd%$xh)E56N>j#`X_9j|_?Czr_NmQb8Xf zfFu`@B+Szkzdy-J3WhiTh%VeM8McbAs7@&iGF$@k_R2@_ytTze%Y}$=R?uOMwPUX} z?1BwVXh(S=S961*=#O>FO4H^@$qoqaydSA01FWkY`ru(~hdxk%42K*6C(=hA>SOEh zgRqx;;k$+CxoOE#?Z}sOM6={;Z(CEPsPE%q%|a%#y#@~{TPmz`8A+1KBK}qky~Q+O z5ccc8bTq?EUz&wOD@-0t3>--|1`?+!@pJA8bL|!xNV+F(eq$qhK`+wElYG*H3=+P` zrL@0CM04CIA8twi2|wEX%nN7wR;GX86McH)^AGl4^o?HddysCXq#Cl*pxjC`ZE*!~ z^0ulBV(IjHTM5%&5t~lwS@6f#Z&y9UX?8+?%-`xa)FAcpFL=Eb!J$E<^O+>j;Cd$r z@P%N*4xN=phbN=4rn5-HJ&p#SOgiFxT5JU5sFWC>wahqcng23q&ANP4F9kV#1C6xneZ;m56g8~#x{m4td zERQ$eEMAKC-tK1ATRtSa;;wlcKX3_qyX$azV;O?~2! zd`*WprZM*>%CPC{R5yFv($8i_4?kCFmvuq=zw592ik}!6_LdcHj}M{ESp@GMi3+UW z7jBgPJ;X0xzrrH(Dz3>r^jhckVOE>a<1}55XWpT?xmV_Dy_8ACfy(JLy~eqmiO)VS zUA%wQ63E}F)&&{=$3y$84h}HJBfr06p6a3WvwZqcJo zFiyK3>!?Vm|E^v*pZ~RBt=Kx$;nMFLtdH7&phgt*+s}qnT>q8$&-4bmA^tQXU^prGuyikPoz}5N#2*r6gq8NR8oTc8)4)1 z;!xyG>h(VV9+CUFp>kr4Qv8w2XVTCc_;fz*KHYWepX3@_N#3mZ#OXH7Ym2FYj+Zmg z^PV<+ZjHh)5q_V;0-_OVYq&P6sPmshp~io97ui*XJO%Y zsR-wLrS23D6FbbT%yug?w`~t#SN{0DDx^v@D0pDdW9FF8h84IAOw_+ud&kblL%?=% z|K+;=QIU`mPr~-X3bFLbAafm-nAm41=yCS=0NcY6-j!30!i4pZ)TkiCFP3aq8=@RS6cTOJ#rsp*2113?xgc^y?xQm=L-=N;I9*^uzV)+m6wJYv^ z>vivw$^o9%MMOE^3LF3B(NN$NmTnQfbKNoeoU2!Wmk+y~1Oh=fEAhhkM&RVx%)Yw4 zhMJf`Ck&WDbfK;g0QtXH4z+wD^@{{lzX4cdC=<9e8`Ml(@0tSD#W~BA3n>rbC;A>> z5c7{`$s2!uAuYZVfog0D#&WF7EstpsCz~;i@pCnHD`uTHssbvC0ugu8zN0Gb%qXY1ZPeZw?;tCI0PfF_`5falNxp3TNl? zkUp>?$|&siKA|7)l1-6fU;2II_3TwsgJO=dzZ?0CLO7Ov zqsjL+7qviry5@!BE1 )sYLwHu)JT@t)=!8fb1%*IO6yks{9@|6=_mBi>!fgA_k z6}}}vP0PKyw<((^un$pRJCj3JATdM(4#@WuBYpmD_EUadWi`>f``GYos!SBwKdjQP z0z0L4#1HzgAhd9!2x3s%sT5|V#3zE#iYF~yY=rWFmJSK8W%ew*5C4C&09U{0SMOjt z80#YTy@XfKOJMkR>_0hcxf=tbF`}UFW~u0AVK_5$(()9U_i(*kXIFocOuB5lI!>Ln zvhu3ZD4|~wo|)3!JsV}mVW9W5qUyDI?rh>YQ)0vWEXIW4V5D_E;qM)2y(AzcO!(U3$T z>-julsg=4FYCxaI>2-c-e+7Dwl7|hkf$jGo0c4nfxh3_yu0X3*ZfFOHK>Lg!IDy8? z|Lz~0?O$t~4uo6-s6^vCRy%+M3<1YKWLzT2c>MYf5^A%-g_QvYUae`PjeB=(lm{UG zGQU5R3G64@aWM93j;i~4y-xa>13f6tV@*}CEog1FevVR84dBh)*?AoS0p?0q|0!3K z9?_Q}rEpW|NoD9nyN^B3NGsx$|3A-EVCUlaH87rt5Sw*}89xA!W8}6(um4IOaKz;_ zf?c6lY7k!tU;+h*4@Gm&PPr%W_Z-IV>4i$K3ULV3`;koAF-q0ZqNt^OXFLRDO1W3- zTYf-{7#<+Pe0?}i1!iJ(RBt<_XorhblAJf7DO>D|JVT$X^C@bNG}LuJpYBpCHM-yT zQ&D+1+H3WJ@IL>9+mg28VWMbC*LF$d+Eddlw-8zrA@MLFp)m9MKI&XDJQJOl?JwLE zVqDj(xF^hK+@vT#nu}3y0P)IEN->Frh;E@_3OV;Yi4dcwgX2{E@f<&w;(i(6t^6{j zA!UDGI=VeV=Z$&vf@#O8$lc;f)D!v`s@rkc(!JpBCe`wAGGL@j5MPFWv(Ne}=-tRQ zLJB=5VAubb>(Ibf%@G#_CKVo3d;sZys8I8-p5&(aVug2Z-JqPJ_^HDBT zuAe{tI^;|YFf>0;`i|HI8}psYxbx+*pqAU>AgW{GVtWrNh9OT_tyZ8mo~n;0bFi3& z%I8RWJe+Tp0AFu9UQS8WAtzK|F(I&BqPBykXs;pcZe-v=3$sy z3jrg$=zrz#UzGYp4MzP3=KkM?gs(2@k5U`%2(oev!O1%U7t^&&L?dD3PSvq+nSl;x zmb6Zm;p45%iK2;(Dm7I>nzLb{XT^^slIh2OxSSfNK;1dbduN-xdQ*%X-*b)Mv8L%47eIyDtU#4CFpj-di!% zZ?LznT=hxGV31(A8E?MZH1%$`WlXrx)6AnAxO+L>E|xH{;`SRX(A>0ApWTtP>3#d$ zejyccQ^f6YLbqrNNmkbFX|?>tTJ~+56p#F(AY2I_vz5I8%gqn%jK|GlX}>OJVxHA} z^T);BWn><;WrQXb?$zF&c4Xx?_Ol)2V;sfIsfN*Dk{0GgSA0y2=FDuqF9(WY$qEnp zUyO>S@JKxA7pFQMlD|Ea7K+5k9TM2@H~Wogi4#wb&R1n{dFy0!eS6YvS;4iL*!gSS zFf@StH<9tb7q}lxP0N7~KtU&7a2VnqFigt3)fi6C)~8Lgja17=K}%YqL_MBxq@sZ9 z1`TWMBhK(fa{G@JvT0^pv`HkZXX;qRpwoTUm;*Nptn>qu|^@9Po7u+(A ztU$FQ-q}{R!Re{)xai@Vm&MKu5o#$#Ep(Mpe4HM9nNf(xR<_KE6ZvivR{MKJXIjAy z)^#LRxFVpSt3mMEPROnD%5;L1=GTXmrP*%A#+Dwd_2{mL3|B^Rs`=nF0*e>R(e!@D zCB-p&a*R#1E#~S(>gplYVi(*KrXWr82oWLkp{Ig zvjfmKGpX~o>(Dx`{pU?mK{1@Huwf492S#J}q7rIAX6NQRdQ%`a{wS#Rw1W-=*RfO@W;5&T#yLa0({Taj50FIk1 z!?g1l187)~4y6-!6kwBX;GZ{bY6meBTpokm12-k{UEI>dd@8iW4#K8Ucs%%GS+wn+ z-T!r9*Ds0b_6H#s^yuSr${2-HJC*^u>p;Wpf*8H@8tO1odR~^Tdxw>236{8H#|+%Y zeGc=NP&LLsTlr@+q!q98-w%aPH-+5><0hKc`e zB51LE-S>EDb<)}=P5@oBxAux-liS=PV#fDqDJ+QiD0_zZ%8<0*3FLH0!(XV%EOj|| zXrY`$;6mCk@qXs!Q9gu3qe7_kT!e;-mQXel33|dG8k3Bt9BqKq_IJl##4Ghh7$W## zuAwp72l0*6;;H!TfNzlJ^H`Wt5}eQR)9NMo#?|^IG_zLW-qLjgo#h>>*rmZT@CBp? zJcPSns6k2!!sA_`6pOX+=hOePN5_s9D)JCNi+b8fh5EU9n(En%qUZo3Er@EVW-mA* zxzQHlZbZHORRE=n%>j{sIcAEHxS;QCgpHj5KFoZDt_Rk3RBH8e7l|lIGMVOmugIh$ z%$05@(LO@;UHANktFM2<;NNJqXIm%V^0Fx4Tk2AdgITo}5n+{SztnoNvu(ryB>|>D z=H;ezSji~Mk$^J(?4Bb2>HX!>kr$f2dpAEkf_Hpp#ud2fyY)iooY6D0-{?1HITF&J zsO8?-qM1DZ@JovpIQ`B9bcDzz>c@qitws%>e_Q*!0$m{(6jJT*uR&$=VoN88Gre<$ zs|4@;8a#%D7~%t3Y%&cIfGs+2;Xc~Kqt%;CkZxedRn|yO-ryFgmZFmshUS$(5zTj8 zgAkq|8C&1k{*o_wewI*s16#-lZ1#Y4&QMkaSX%o46-M~{6aB;O6Dp@T6_oEjYpH8G z&Zp+7Y+H*9C_D4gl@ikTOBV$Tm`IqgBG-Ia0o8|ib+5a%gMqu!&owpnw-LFOY8E}C zd3R73EOTbp4htGu$C9@YaDF&l`mzFb%Rdk_7)8WPYUpCU2u*E2WQCp>P-) zsy?0wT>m%d^B*78C<5LXvp@;_^=+b$Bw&YU8;FNp=>wTXc}ZFgsRGPF447W9x99iT zdKR1oGQMg{oru6)<-4i*LhX>H?&0V+6Ql(JxQPZxfFd4}Mlf7e<@k=#OFKFfiFUhQ zl?l-&x>FMwxMbX|n#tQT)OT#L$ZKqGgxtO+k0ehNCZ)VLhn_BFQXhL421~B^toS8T z=J+;P=ug|yFxe*89e2q^c7DBP6|HqC2)luZVj(WjD#~8{&Eu88VK60YsPXp$Yf=Ss zwUE81OoqP<*oYw>9-VCUhL=&t%yaZf(Hb#y_^H$^rOFD__Kta5?tp3K)9GuSZE{SR zAr2xGFdCJgZt-oe#sv7#b?DNau#SOlPaoR^`$O>Zi1yy8+!*5%Y@N@Gj~&H*r7X}* zB5^dTIQ6uK>hj|+K;aa44UQ$mc^H8@`M-fLQMPdUU$8-v4v^r)2D4~@rBg8>MXAL4 z`R!Pl?An8xKvu~`5pKGqp!g6>?QS2cn+tcgGMZW2xN=o$x+DL7<308=229bVgocLq zu6}-e@a3_OB5OwzUFtNIF7P$)EnpffO}s3<$GF^{tV>zIwpOH@zz{uBs`O?m%8$W=9CG)soif7n*(2mziTqFSV&bZ zg>}x|oj@;ljIy)!p(|f^DkL##6{y*Ml>JDZuj9;F@4}ZHud5&9yeeC2vw8LIh%a;) z8HeFbF3$`~bFn*`GKm%HLWGHI(_t_9-%GDR%PN`^vs6%;GdrSp*ZZ>kf{i(^tcv

knDN+SuLzsSh~nt<;%Mb%R9n*e$uRG+YkGxFa-*c!;kzQ7LUZ0kyI;fIe5n~s z?Q-;itF3fJ_GcWJKEP4ff>HG4Zz94RBnN;Q4Ump4o?voPD_O8(<|I-pet2X#V`Llq zmz>B>mVsK5Bu$Z)ts04F9+f3<55eYB-Mbav?5|6Xk$+^86;3DrMVZaL^>uz9Db`Y1 zsgtJa^JSzUYZ#}d!t%uH^*P2X57xC<7LFM=)0<>N#=rA*Sfj`wZo>&L zbnFvK)78o1&DJQw)I!ds!*rK8aLK!;`tIXWjQy65eBZnIAZL^^eJH4f zNIf`8-0HH-Yf3ztceI39Twv+$&}OP!Jv3hLxzJ( z7Bkdc{9Sk1_?ftLgm%skjFE(-xj|v(-8Fb~S1l=t`+f0CC-}p(6OOJq&TD}zhEDZ) z&vihixHq84>yIblGrI3$Wr`vns}(0}CKyH7Uv1OeQhrf)4a+51WPc5-!FEMVITh@m z7AZwfS6@Smb8(8NfiiPe%Oaa*#(mfHJFLn3QM-Qf>C#kFCC)WOmPr#!vF&VWw(7)Y zl=KQlz1gV{WbE%OZuP9gkm0VyXV^{Bb`zXu8n}uXA0d6n7fkB4&9Msc2T$Gm$2sV% z0{?0#j35JZ0hyem|L;bI58y~{>|{7e9G(m1r>t1W7iV{Kma2W$4PmZFDreFFF}wHp z1rzBAv{6knx3*!p9C-oLXN5CT!nmESrYryL7)zRJwiwM}Ywp7&nU1tes4u=VJ!}S?aGhWQ+en-FkdaZP4tV4j5(oHPih!BU`%mT z;M#u7e{{>CqDOthH%AlXPVXfdEaI@>q+F5U1|eeqq$pfgD&X-(6^?qC^XdFi;M_4k zA6zkbTq(AsrQR-h*QPQ>YuYtiT)Udu<;D zc~d$)Z`G&7&`?KXhKaPf87(T<9ZrV)6fywPJWjPCi%43@SU&5nlYs;SZ!~vPk6S zpy6li?h`*zlIHnC`qL4&p3)p(W$g^dxKA>E=&aWh9uJ**BlipW<$8`a$+5#NmK3H;Rng0j2Gi~&gC~w@O9?olI(Js ztNxdVQu={Ru4y@+C7(-c|LwSo=VFKZ7Og*%{G>SieaoX$`opSBL?1!OA1|Pc`OiTE z3GmGBU38_QrDV-rseRK@0O`UFJITV;=pDkli_Ve z+jl>%<)%|2){N40@xkbwH&K$iWmf!2)!61WVs<3N|65vZ;9HwP7jY$)~;z(QQC&v7!uPyWBg0#hJNy!hZs zuQj8AC%9?-yVsx58hIV8_%Z%!bU1A{+vL(LtNj zwIP1NYjj?;3_f?T9ysHdz$m_3q2%(UbmiXx12B3O^T)WQ3ttC4b<@ObgW=YYrZMZg z>SSR*c2oRgC8c1;Xh=U4JpqnTgba^IZ?3|kqfKLa<>eDb?kzL8C)n-+DH_N+uRh$gS2g^6Vq%nEC3?a{+Lfe5bb2Ws;(2JxtQzp>bkLBAHqIdf zzI{tamr^mu+-iKlT3oNxd}h49dt2+R%xkE;RLLt!`|8Egr$bM0m4wLhXUkyZd$_k_ zjd!YHVR_}bUrTV(qn(XfJIKv4>tix9JSjCreop%OSIOIJpL3qKT+L#QG{tHA>5>WAf^5Q8$75kq#Rf6t03?#H6 z`rW&^ufIfJLYp(0mcr`O;$f0)d@vwefI+Ba>B|=d4sOIY2c@7B{bpRty)n@HiJeZf z_a_C?%cw^G%8`vAy^>mRc<*wbPZSXpyAJF8HxM6sTzD|+WzjkRg9m@un}>dB(GhQf z! zyCIp9&L}G8tt_qY7DJ`Iu&EW7evtic#6SOnQ+yc5@^MWnM zJ@2SoKiM{Vx;m^@RC1fF(#kQFu|St5ZPYggo^?oL@PdJXlayyH)jZp&H1pjPvijW? z8+6*Z)tzPkmSZD52^K-MuKtEwdLklS(-Da(9Z$BR94%iLr378S9%cV%&RW@kW|nj& zOX7@1_A%%h2gkmCTvfVrBJAzO$CaBncy!6(y)`(c`7=dpu45ZNBit^ow6QnxEgT_^ z=N$?>Jsgqf>-BD4z;X%YHy`&9$f9uqgHcDo7XNmquBnf}%8rP%q51OofG>Se?Q6Jz zt~B!LpVGv{l-*vz5yHg&k>-a-M8Mo7Y;XyJm@5w0ZzR5D6Te9;S&AZ#YGvyb|B>oskVx zjT>f3(Bb`6`7YRj!Zj#+;CB`EBXMCb(yd?Ibfi>PCAzQf=##WQ-j-c`JRO@RM%HOa zAJgU3!@>T*n6xv^N`$NSg(&i!4U5Q*J2qtM`s2F(WE+W>RfD}Hj7O4e=svHsnPg6( zHEZ27EQ!P^>6(y%o#W~+<3v~nUUu*VqD6jH?H#lV<7UWLD{kSImDTm7C|~}Jgzc)& z3=88ARq1a*>ChoT`2I10pIQ&AbZq=#oj_KNkI>XA>gQI>Kw=Xu5YPpk{w>^VdilAk zn2ZoH|Fiy+->`({$G8`oj?n+;<0e~vk2$`x19c5I-3B}=T%oUh3d(s-nSZf&1*WR? zuiIgEo=|y6#G#8rHR#`-n*AXC0M_Udcf=JrJ@J~hp!vv>&=Uu>`bPJ*5ZgTcx$04I zd!vF_I|M8=f953mOJ3bQk=B@#?RJd?@uE843#6CS5mo+q;J84u-LlSm`NmD>j6d@) zMAbt0)|gNxPn z0SZ6<`F<%YKz|3GvZ=8DOu5KDK3zdZ>>LsSc)U|Bv-K%SO}(!#*N~%Oz)qk3lKIQs z+}~|9&&LaMx$U@OHb^M@Zad0)JR-&N+j-y+g7?PPAOXV)xd!cHWS`$q7JT9qan;R} ztE_LGwr|Zf0>u;*JhNhb{aRfUeE-UMG>ClpgTZb47RJX+#YfaGVpC#V)X(5;@8{TJ z8Mx(3l96^N9jJ0Wy4>v2WKrk)^il1A7d6^|e{zt-|0aS_B1CM@C|7qrP+Yc=8~1hU z+%n7Rg_SM&+9-=whL*QDSBXgWGrg8KqY?+DPumjHt23NFZf`Y=`JlpWndroXYcap* zIo0aOy~c#=Q@F71SQ7b`o8{8XLa`<;N8TPcyoOQ}wKRR4oYdno7>~z=f~0lWkD)a@ z%+Q)_J&(VE6`hdP*1uTmoeyrfJKj|?Oi<$C4i^bZb@8#OJj;S&Sa1Kkq)O^!|*MUhRfz9j)xry+roLoNOZ#P}o&5Ez7o=c_2n%x;rFh#YCE@baK zx^Vdt`m<|xV0z+&<)G3sW7v*e5Gy;bMCJNXUoI{E7$$+)uo~2uC)!$JJWE@?OT^yT zegtt25VAhUs1vhG=bC1JO10Wzg}Q$Ckq`IF<%II=f1MhLl_}Z8*yneF$+Q+b`%r2R zK1U%)mU_%%keP{qv+~PHCj5a5x{@&AML1gd5rv{8@SnTd)mVH+Cv=<>$m@U!5nA-R z%X;Lc2Jyen9dd#HylPQ^Rf&|z!)+#DfT-i>S8#Y21t>YY{WU(W{=QAr2F5QnK; z-LVhf#1++@hwjD~Bab65KWU#^X*Lf_96x3eEMowgY9~1ehhn*j(ib+BvuiKI3( ze!O~zoFiVW3_0U+!Rdr9TA^nC?*txXXY+ux1|sY1+U#z6)4gOgBJPfk@9J;&He!cxUVT~w7wy#2=IvQJjU{dW zEzzRk<3lvc(g~jaeoi5%hiJX(<_M(x{+2MUghez`?)A4D5&k6LzyAwBG5d2B0pY}@ ze!L!lanQrLG3XqEtI*GJkZ*&@1b%mA3QL%XWew&apkwd?CqNhj@0J!Kq&yFw&pMR& zoWl?+tjr(z)dJW4%?<2%C z%p63-!L4)#ED2y%pCLVVDe z2zoO=()mu#6nXT6#+(CNu+r;fMdqW&Oy{a7?QoTYrri&XH=EQG$ z&;nQ0E6`xV4+VQ+QH0yZ#zf$pok$RyIGI|A0N5OV(PvQ|&*u7Ns^1;jyd%i}fB1Uq zuqdPGU37*9X+%;=5G5ofg#iR9rMp8wT0oE1#9 z=iKMse?Gp4nR#Zuwbx$z-D|z;-N}r?clB4y*`PNMZ33NSpbf!-WM15Qa-OO$w`{lw+j&8_1%e4vBMTNCLC_2o#2GM7*%EcO+ zc-^&r47)Bx2-hnz^I8?JCR~iZ#k%O3`ZO-}jPB;8RRSqv3VWh{5prNC@z&YOAuJTysK7pP=dTSH`v1h8`T)&r^ByQ~u`zLXK5XWq(be{b?Gj)OK?6jh8HDqFbuNdm8xj zx>!aE4&3`COYRtYh#Z=*ca>tG$lLFf_v}AS>I5i2Gz!TRvPku}k;xA$vXYzn`Cr;A zAv1j%t9>6zbqhX?u59jl*14+~O39gPXsGetyVWK=!|sFVhUVq=!ZaB2_835?wqZm6^U_`?;1?}AR{SLY<2U~k8mqB+c2=r{1nJ*_#S~;}ZYdnO zkFp1U_jDVz#EJD zQ`iD%`l+)H#XcERT^XibLDlhobirJr%A%e`>NYgH3G1J$Q&2_S4R229GNM&4;EZU#y|l*wdZz|UUExD) z?f=U+hP^~FzW+>!YQ9D1>rc%0Mu9Q(oQLl2o5&f6WDv27k9`{qUQ4=f{{d{HrWU8w zXeRQ$0_WQ8Ae&_1HQhyfA`ul8av_5u24chErarUTpX>eE{d_{2*GBg!hMNk|tHN57 z@X<@_do_7-zGj8MJ^diGdRDZq+TTe{jL_WJs^MZWcpw-#Do&!i9y`RgesFF@{nuR7 z`x$C!OWa!IGcgKOF`7B@1zqXwL-*69BVuUAvxCvoOa~SQsS-ku>0OB1-akXkoNP># z{qs-B4I@I-(C&i(24n(Ubt!cw%3gZhdj2e7l5Gq5`BBrg`Oxjx>O_(rS~IbZcy&aj zM-QQm2!)Q%9yw~RL;D*^2izTOY z^c3qF7HdyI>-(`t?81)muY7_YNq06H9p_n+` z+Hcy>LD!IXrV=9b?|4kV@SGd4a-NqtZo|`nyX_-p#EB&lAdUt;(B+x`pL=vfwIzD? z5R?x`@syG3+h}N9{Yp^?1F7xUuQIYxu7oGJ79fgb+WWiAH}_G0R&3M@WqnR-AGTeK z9QlxelUb5~(2vD}fp(Hj(@}W}XXVPM^U_SW@Hd;Lx7JxnJ2G9MaJRMRl22Lk!tf9F z_Z}5bBu%*M_)b)WKV-}fSsABQR?Ge6;4QNmR29&YgP<$k*Z z#nid2eV>cf4w%XSE}BS`%dV-?CT2t4S|yKe*vz^A5kMAcR67qVoH7a_SA*M03?;M* znKjeWOdf(_C{Ja62&~eFs`o%MUm|%{X;Cf0pQ%u)lBf2~E?fGqZl(viDP2%Q>^rwp z!a34w*Pe*@>vg|alpuo-a<6oQH$c7$Mm1Lj(ON#=rhqjL$I>x+JrZ_$70I51U=L%J z@AkS~xXC2$gr)TVzKlkg!ce4@kTX&SC;-X0zKbe9gVDDtm@u-kqFK|+IW|8!fZ?LBB8H&bmo~7nsss} zQ)@8hNe>M;^K&2g6n1MWZ|7aer=7Pow4$59{i(U>&Nnx-^H;{=C zA?OT#j#?~GgRI;l!w^q4PcTvZ6&=Cch1_N5CHvi4*dKRi;ik?+z-tzn9_YF+dN5X+ znJpIX818L-5fQO(kl^(|+||&3wg$mtJ|js%WM%cS@QY|0oj#X?*$2(;2VaIxs!XBJ z{QYnH1$I6_UgM~ypLU9`hT<~%isy8kzV-Y@8+M62&&@pPaqcyps=DgLbT)Kf3Df5k zcJ_ZX0RdXH5qmeh^>z$GsMsttrr;e61-kzGXLTnJnC7FoBG)evEQWr@;(yomQ=Yi} z(#p?!bj$MPivJV^JNg*sE@Sp?io!gh6K+Ny1U=gz%zIHj4NZb50;1X7&(#KS9MRia@r5r3#NO0#FLm~#xqQF2$o{EM%%BQ!M^sS(T7m^#ZrSroNshyirVFI}*E4kzx|!4aEuC6KV?m?45l~H#=(j(<7+kWJinE zQi_!oJq6W6E1u`5ep4sKv6XRQjD*^lYk(E3_aEwrb>mIx>-%?Wj5cxQqS+5wZZa~K zW`p!>jM`CF#28hn_w4-$WiMrf>cpGq*W@`yfCVepnvvU5s9v<|+vQG!`Fd zm_=39{lrGYzgD8tIp42{#4M#UiwWDc9#I~Oc#d1l)5$x)gQVz(aHU^`fycu@D-7zo zs$64UI_JN^g}TJA(?8ksD5u$UQ}*4oP$FO7>ZAs0l+ztcu$M_{1AHQ)qJalKzp#Lc z26s7OLX1y%EcDa|oPk4cAN$5fK&}2}DhNm5eX!=JIIoMJ)5xoRo@eEO-H;k+Y_riO z4fQ6t!jg!|3YW58xlxuYCsZH09JIwy@p$a9LR@rj%aka6@(PrWZ?@1WO0w7fR&hr* zYVzQraVg%1t!JIg{mf1Q3Iw0$+-*3w7|mRb?vdB%vZ+rjx<4w%Hv(c61b@$>iM2@T zedUs<8mA>Fwh2lpSVeCW2;rX@jBScIy(VkL1!z4BQ{cFYH$ujKv%^-^4x}ENccFj~ zT5N1-B?7S81JF?{q7L{Zx^EeqtgL^|R#{Z!_h;?tVXpTXH2PZdrnl-#LG#4==>U{? zj?s@N$9HoMj@Yt|;0(4*n`69p*4@ap#)r3TKz>et-fi`;wra$v*aYOb!8o))tg~(y zAZ3sKTXFyI`_Qsxi~J~d8q_FAzl#yA=>~uElt9!tVOXwO-RSEHkhRI-H;>U9w5T)V zC(r)=2-4ai8W@ zIjiPYMX3*o#lT#$Cm!{0SQL-5@5cf#A0(uU%Mx8hZVg_|3H1jA(V zk^_hkn9tzXS%qQp$m}pTiE`#&-Kzwr3(4v3K?+dWtq_&cdHbFb7bMt6mdZ3UBqa-HVAbk#hC z5JodTNaU~zhZ>7P3-cchR@|gLb-fbY&K#@Q0WM;RFVC;_uUZsh?X67oDqcP=?k1$! zNu(%Z%@OGnK1s)dN=eNvG_&_PH5tx)sOr8_r~p_|tHDN{z^`yxlr9N6;QXWmI6Hv} z-(9cew#x+;Vn(rQP&bOp5}E6{Y3X@bliL+c((#xP1()B6jLQX%ubns7?osc2FP;GP z;aC468+#6N-WwTg%!(3r_7mEf=)LTRw&O)62o}fnN)<&w=v0BAII^NCXRriEYzBY1f#*f zcKsASyPb0D0%q5rZ29in>)(HR3V2$_E(Og-mI%44ZQk#zJ7uW)|&$q z_nm}u!<4-sHyY2$e2WD;sr%o2nDHmzfAZau#MP@H=XgZkGyLtaHN%$aG`7|IU_G|V zj?W?s?tj`NPpfUFIWEVaBJV!R-qiFiJzts>*6UsinkuYL#ew1oyhO62xyl<*_A>~i z;Ce$I1+IkLlCEC=QB_@qJUn$;_I#uYxhJHyUFY>cHn#!jcSv8cZq*F<<1pS00>mKC z+rKvOn%Mi@SEw#AdzbrG#Lb^O)K7r{)6{FHhFmWMEFw3ZCKhrf;JJ2JczzW@GN&r_ zA_eDPwadBLPdl#S-n4%9KUk&{jKC{m{oi5D1Zt^IPCSh9e^rmdy)Sm<%3i@w-*G&+ z$%8&r#aezZS_Y0!KP}OD=BZWqsNK-e_6wGP(!KmhIYB0e3Aq+Xg`j#h7iAtFn?)J0 zihW=785HsCFl-_gG4bb)!FVnjA^He}&y*qo)}aa$wV2hi!8$AZD8x&Qp*=yIBC2A( zV>d)J@g5?aeoN(7{vcA!;9E`g^4c z&6Oj_bzhSkc&}9Ddn^{YR3!OUSrX0guGM(V=Ale!BH6%}B!`sv*Zzp>pfzPMlaPpk5M?E!-Z2|G5`C6lZIBiB~N+q?}qa-SpFI8H0-9y{Gl zdGf2xx&Iz$vAG@^QTO3@J7GadU9@cE`kU&YQ#mJ2$d_I>d*TtmKP>&ZZ7U4E9_)-O zur-zIFWG(DLo%GON++BX{iGxI)fvOGHwya|^uP@ylJ!v;RKR~`3Ike4!++lBFE^jQ zy;wB}{)Yk?eAkaW&q`u9X2+=D)0&L9n9Vood#C$HOLd67h4Y08e+E^_OBW+FM0Z;8 z2J^JRzhD4=F<vd zFWpO#U4i8BF#f*5=E0VA&I$ek*S+?EvL2o=ssB5WE9|=@fVVP@jBSh_~n>B znEIe>W`5T(Ps~lNV4y?OTe`usFJVd4eC3ZG!yg2`V%W?S=6Y20g$eZ zkTtWqQb`hXaP2BJl@2&}E1dWVeVWDFa;9E3jvPK#b~4dN-Pt);yl)E0sgjd-O*{P` zoEFvkeN|0}QLCvT*rrq$?pa$@YavDtm}jUqG@K;{_z@``c+#q(QmG>|(H{POtwha! z5Oia%9!!QAZF8X@1bNoEmOAT5GI(uEnDOSoE=7H}zr$!WVM|Bw@z0V0@(lhYlD9Q$ zy?c^?TpPTFM;0mCcKCLq>Shp>14X$Z?$=-ubgF=}=Y9z~2c7HHfiB6)uezyqpgoVv z=?hzXlav3WCa07Ue{Im{x%3_1iO-tq78?FaZo)kB{w*G7!s=)mSBiw|{q5`TnrX3) z(ZGlY`#G!ut$wozaH7Rw0gj(vk+_k(a{U2l9b6Z0ZvtIEfF~e)yqB{a)?aR7LOy!x zlOF&nvhPU_r>T%@CSYHs{hnAfJm~3b+uy&a)VK0m&Uy%DU?PuH--pbgS$!HHUJx%S z@m2)~j%6NDU7ql=RJ>r_;!iwao|5+mQpCqo!S}~kM8$|CBCSu|c>1mp&#C6^2$v9B zgo@?Ngd9$>7_r2y-s~&7Qp(_?M>Vqun`6qCDO-NB{QMPD9PODD_qBMDp7k2$qAB7( zb6T)hNM0xT3?+7a{^Nto@*Hb6BM4C=Mx5$l95!bp9-$eug;V2!Dn47Z8WYGU`BT^t z|8*1_*`uYOU>#h`-%rY7OA|NtR-(M-yA{~R_y#jTzB5-dosH#COw`&iwcMGHvgKSo z2>BB42@))I6@U(perp3KQR9-21vRi-e3}kE9xW;^=S_=-Ej9Ukn$^0Qcvi!hJRV^H z#g8P1_L3!r`#p-+G589>Mviqy#ntg1p;pKcKBCNrYG^;IdiE~^Skd_*0Oqm0Z71bA2N@zTY=){~x|YA1IidutQnZSA>d)4UINY-C{(>onn6Pg2CJAHGzKq2}i`UVk>CVK&p7FJgdYWH6_1 zBu<7*28#S*j|H{L`_nwdxMNqeoFipN**x^j{}d)KDn3m>ycPNOp|);_K6_UUPBfIT z^bG5fxURMTfQ%tz*Jw&nAUYh8L%>pUB8{9nu&+oN|8_=)MuX{Ff@<8p?Cd|Qn}Q#P zbes%KsYPsflOavqjtp4Q@#VO8Gg;R;j3zK4$J2mRT?j)^xRsv^TkD3Enb%G1G5&Ls z2DnZ%H#I#iHzR>R$yrG!#nh()cfu{W1=X91`pt<`n>`YLvTuhr48m$%xp?e9jUDi? zpj4jmu}L7mG&{fAr7yN~<^l^V#8s;u(Ni6%!)!_59f;MdjA8w;&)nGV7dCMA4U|@} zQ~c?g0J?ja(Yo4BJ}!XUN7tb-02cc%RqBk_xU_-pLD{;pW!xvEF`GvVgaMT3Is~-c z3OScGcnaN)zYa)8qvTQv@B8*mM&i;pqB8kVbdnBF|~Hey!Cbvkwzc zQ`f{&BrL|EIWn$+;#Dn$2zJz3hu>F~fZvIqU+)ys>Du9F>c0xpGA3 zY^wADF%rnH4EVFHtP{eb?@xBpTmK-LD#Aaw(JA0M^}X4JOS&;MGjb@g8v zl!_Pn=q+BIi|Eni#|a{$)Y&Z_x(}F5&bf~eYps_UPN8hAd;L&_wOYuLJTlftod{9o zmr^m3IHDi@S-pS4tzxUXanr{8?K?0yU)*_$8!v%1;iiI zo{l4`tlrrS(pbs@5p|TJc!yg?ctZ;LkM@xAq?;JPIX|!T{mpW;e&P8q|#&;wR7?+-^M<;uL!{heF~`_Wx*W#{xE)W z4}Y#ybmYr3JcYgm{ReL{Rz(ykJfK(E+|}hNN}L@?-k-I1`b2 z@-+8o`Js2w#lG^alEib(CBS$PzY5e+*J zpSjQ5(iD&cFmod4zVhhHF)8<3(OMc%Mal|2aSMlvfE{f5g!kyZ_cqlx0<@-!np8Ks zi%WDsSp)%QeF2v2aGM*!SeQo|hhoJ#4{}e0wkC_pXxXL$yF1{^10q~2BJBmrb*`jW zcm03U`yks>+2PQ`siS{Y2JL=yL0P#E19-_8#pj9GfQ22*twjzn+=WrxuymUmOpbh` zw{dY(I;U8eTwe~IgPftmfI|;Ha%Q5LYX{?o2PR`PW$+4x=uw~l>9UnBjZ%Dt-rBr< zD0yzy;2^?25`HH6k86w$7>0LM-~N*=>E^q8Q6J_e*#kqNsWI>jL8ZX~d_ymT7KApU z@8)E^u|YaShUve#0FR94z;XKR^tmZ5KeRtJN7Ws088ISGf=r}`Ab$S%@xDLn<53im zQpe_`RocKQgPAdo#CW*$rG~%yLtk`pM8Q{XEK2vyZEXC`iaMYe_;-OML%g*#f9a@I zX>)*vFY7WaE#|D%gab*uE!;0fQmv+2Sbp^wlgWCXFvO@Nni4#W5wFYA@afMzKW5C= z?qfe4W>Tq8St1kGBVPkMVK_p=%RRqvosiLI-L_c!IYe^VoPMGk3P z>`L)nd3|%r&?(1mkgoNbzSS6X|j%4jpj7Z6|3P_KV zdSXGxO>rJA%~&JBl|`AZ!UT*MeGZXCNtag)5C&9|4aOQRbPqPY+<57;b%IQFTHXVA zfZGXh0@kuAvM(2GhOB?J{ykx*-Id^lt`4PdN)_pneYeMoNX@HvO<_=msj`#TYsmns z>9S=MV&w#dEyQ<|o9d{3lL)zSh7UlIVTiv)Yn!U5W?vx`aA^vN`d|Nqc0q4d0m9u7 z2>NZ^xv0O48)#W4+&$R&+5nUh$Ogutd%#oF9RNTqCkn2f3dh|fJ-BYmOH*KzPM&O& z$t{J({tO}u11Wh(4F&-k=8^ZMe)jg6k|nq0t6}5;^u-p$@pt1vJ*|`4WjgMr=LM~T zI~-+55;BoECwjY_Hniu4N4#!(!CeQnfqTkEDi;l+_oprYlq25^^mi zXftT)z^@a`V{WmVT{PaShO%91^zBn)n)Ih8Jf1t-eRH1m>2FEgvrs*-*K%Qx(6z<0 z%dDb@j<_Q2INSH+iR9g@x)XF?7MV&~_2!=lF}yLi3wknrx-DBYO+vk|Dm0iCUx6w; zh~Xp95!hRIR<6sO8!3|>tE54tFh%oiE{R|?L|-{#KC9zsjSbAsvF`W4?Mker*V7e9 z!rfW&8LTR(JJw|xTD5~w(t!DQZ-mQRd?Y_ILi73oC#+|;*qGx*hBJu0>gH|}$2ti) zLV)!2$coD}r2JzvAUJ~47z4TB69G05P%;#72EBJfq6J$p{V&U)y=%bz+GbHM3LkQR zVR+*@1Ac#=ysl!{*;xg>j|CB+(E35Q1aOrEmkQ<6rV}1UFo4XuaJ zBaLo+Z`z`^ELeVg3a8ItDcetIS2BEA9T@CQMe;-UDlT$l0IMsZn#-kWb**L>0wVN+ zv=GUs`0S@-zdPjm`ExXd;DwQW3#(zUlp6$#i4UYtDMDPE!KZB+WM~PNk&4>nO&}|3 z!@q138A>(B3>i&p>rhc}OW3x=xfKahUD*6tTWKzlqSVQ8NB-yTYAf!skY&=NN;g-t z{-F7*KL2oVR9x`B-ELHdXKNYEY0X3?L0<^t<)B5Brx#6UR3S-xzE{|z?sb`I88<$u|9cjS$MnoVcK0LlS+0D4&l8>_;hAoIWd z+w>n(`UG_hj4IBVqRyZLruQ>IlqqlvbOUEp=vLHYT_Er((a{FbLonV0&~d=^h-3QhgU_am3dUki%;iS$9kR(aq%rsEo{jYH z!G20_83Lw&w2BTSRW#XZ4Awm4p4Uc&y=yuYK!^?5PmjD-KEr4#%vYh~DGG?GH9N?6 zKa6BHqaN|kOaTJ#LDY7^Cn6@}X|F+n6{BS;PBpGxxgB+_E|oWd+h+00QXqR9yM|EE z4_3M;@?pMl3B^%Y19iey{F1C6mI8R0p~pV5rmcOAKKbK|ONw%4U|^||BZXEK? z!hVgIRb%DZf48=@(=t_q7F3iIw@*e!B0rvjfIC-W=mW{?rAD@-t=ZztjpNhi6jF?5 zY&(DuN~qWx=}xgZg5Xh|UF5pk+CT?vjB#LM1Xx4v=E5fcq-o!PMmG#O0$q@}`TYE9 z|M>S;$%7}Ne29AQX#{Zm86e1qB1sXzzAg{|Aaj9BK>&&#&x5%v<|>6bPF&z77l^Fv zYk{o618`r`&hYc9d`U#8OHK}`nd}_0fp5T zWx48h8nvtpa?&duQV=zMwzDoucxoXreMI5LY~6n#xHISRoadog8E6nOEXe# zK;;cxXn1`e(EoG*h!O#Wx0V07`67DC!GuubKvgvC{69Uv7y${A5M~sdkvrqqFJCGg zYUPyxT?M4F_>`3@k*P!}stUhAjMP;a-|rPE!edY08?mhK<+1?+QCnB~q>r`xa|w4bcJ+U_0EJYug|8mjDw-(wCw%I&Hp{%Q{Rp6XSAaSpb@3sGmb zf?8RqL;$0pQX#Pm*dHVnZZ59x%bKal5sMA9$rrq6Vb87*IWNHJyj!0TdVpB=4$s3x zD4JIF3dy(gqwuTf0b}=Z;7AO{@qgIhf0-pV64)6XnoZ1z+LY6XujzzVNg5zmAC0gl zV;whmY`0_Zkmg-*R+TNOCr7>roE7;*f)P{!&$>9oEeUc(6-6{9vF<6yjB1<8|E%Uw{;o4M)5Jpj9;_E1qrN~JDf?M0vD z$*fJvQ`6*7Jwli1q{@#KA4)A1Uj}#nO3aPW0q=z@4v(Lc|KS@h$GmS}=NU=SkNrHi zUDe-tn+*t@Jw>=hLV{JtYag@sROpYMfxyDZ(iwN1DB$zX2zpUF8BRqD#jGXs1jEpj zZBrcR9#pr35N(J`Um9dKV0;sfSUYZWP~NNJs2jh%=0n+t%Y2%{@0$&q`22?r+0vbh z9eleQ|LY910ySUd`;D_8WX^VWu0oW(V4r?Q={i4Sr ztM$*z?gK8|NvTuZ2E@`T-CXyuSOLS4glBe-s5+1x5K_erRc)U1eVfb?U|adJ!rd04+fpeWnQ6h?bbd{u_q zCYcMZO1b=`K)*{TFJZOTiQt5%U-mY56+dJd<-!hfEP0Q_oiWP801&SD|K=DZ;$<2};zIVDdnESD60Qb&qMs zpmDK-yhEsHNZNr!)0k6D9g5u3Bqsp4i9ZSJM*9$-SyicA%R~&?k<@E=AWUc{iUIp* za}WD@pgk%2tKSXy^fT%+;e45$`f(jP@;GZ9j^OqJ%~@AOsXdU4y_Yx_7i8u|7(ewB z^i$RenLGL4?a2LVV0jU8B4k(P*zV(w+Vdy<^S26aQ7Myi$!(cqUA@U@DXLepu9{5H zKe@4gi}OnV=?a36RI2si?-&N5U#`0*jz5J+!_yeQkX9S%bEHo=M!Tm@2bR&A63eNG z5GPMv?!2jVW)oU^S(hUv3x*;3gh_un_$uALXlbVd1_L)U8xNPCJVYv+b-S|`3Z0~Q7J-M(D`AoiojLpb z$jJV~>6gil$gU%|^*(vnAC{09~(B{H=(x`!n~dk4xN%6`Tx%Iv2ZzMY#yJ{f_W$hlxB z8>^EbVDn4iStaM9_)-ntlkca|Xj3rpeXvrF&EU^l)`bl(9E;JB z&-O2E_ANpg`rb||Uj9{OACpLU@>5UXw1Q8$$3}NBiLO zk%qnJe>^ZWqvT4n9J{B-6u{>+v1n+9$Dz)e!idllR@6=g1U&KBT;L-o#qmP{t@ zYEc-}F&T5fU76TFT6<%i9SCD{|IT?QaJ-)I%I0sK^O}k4J*PVj5PjQ0fokNjvUr4g zGW@daDhpFVy)jVj6jlRTLokL%D{4*eC zK`BDM4?X3XAt2P###;ya(5UNIBQ)5zMceOo@i9Z6;(rk3)S$aA=R;zWJ&S82XkY1c zl%QJF*-v3F04PGKy`N`k)_(dN$@yyy-S|kVj-Ma!3k=M>B9r{ z749YOI{TsaGf$d_Zfa_0u|0a$7*hHL3kqUVwbmQw(U?<*?YB?#Zvtk8$0%gNJ!!BL zcd=N=%eh{2u(E&kns|}RzavHo-tAaG&|b2j<|z?RB=4C zd#bJb_^G!l#U(I@>a8lOEWq?J+Q@VLYd1gxdcs2;(Z)8V`}eOd=w;T`kl;i(vl+eo zyq%mOpXLjYHMbs3Q zQuG$%(=j~(qGM@K^*ijs^wQ!DFZq`gHKNSvK{6^K4X+2iLd&R;w3(%JO?we|Fq&!`L$1hDVxTL45Q}b zL`@QfBw6>8o=ZrDa|&R(joZzEKZp{~ujdMS@{Zh{NPPh+0@pVMgiJ`c8{AYB6s`GW z9v`XvG3UaBt{7||j4TPAcbTc#T&t%?`;Z`awqBsrkXtyYsq#SXUA$^3n;V#F0mbzgz;!PO*=~Xl?X#ZClG{e%xE1lq`v_>%d0+-%;BRj#L^xQD(|0)DPNb zDAUyl-SEGjmR1?cB{%6OW5&u(|DBCH1W!GL(onx2@+UkaKpY5~XVCC%tr6ep7;h#8 zL!)ywD$Wt48Hv8Z((Tx6J%F&TF+m(A+56QHCw$AXoCssSJau%Pbgz%v_za=Oz( zHKoYy4}WlNl7#;sL-TK>pmk5tS4JB+fIzY<_y?&aKzVq$Q7z7bqQcV;dZx2TG5e*^ zD|n{^B5XBZ=%|bh;9fOKygQZgkpoS%h5%9S7z#P@MFy*Btyw_Hne02<4-iBBo;4lK zs)RKz8~eA#a7dgsex?6sab-h^B3j?l&LU(zOVs3s3^5yhPvfsfT;1ug<8!}BQCpO!^jz086a|Q9UUvA)zq4~=cm6=zHhlA~8(1t9 z?}sn3=&JtDk=Xle-gk+Rkg2omeJM5uZNlwysS5K_*$3#OF6 zC(8$B#m%Bc8C_asJOHd-ZulWZoA$mAQYfDCwK+1%ES*nY^dK@47=p@EpEI9G5n{d&SbSE*W zz>Q)u>!DF_34ac&nt{F+c+c*PXUPEEbSYv3vys?%gO{1;VWf#Wm~P0#B;&asK@#fImEHrvfz0!3dZsFkvXcmOuD(*(67f%%R)&hCEL;LuN zVnd6YYtHl4pDMFab_r0O-vCB%C^bu~{<0rsR1@fD5ZAi=i&RM%=c|>U14W zc$w*py9?KE8?P=w_ED}nLZS1d8Qxz`TBSrSiGa}AfjHvdSKIf)<`qTtX~W@XXBzN5 zmF5{~0kybyfiDN=Lw}avQ@)lBH+KtYW-$`&EK%$BKoIWe^U#H-`V;11VNFWBP=u2x zDEzXV#N3b*uC+3JZG!y`UCbv9VNzaCkN2uQV>TLqRxwttJ2w`+N5tMCl(EA@VdEy$ zz{va8zQdD%VQnXb1GUtcq!TJd-NRJ$o=pR3b@gEs;fDDDv-LOO8P!NW4-?Kk|2h)J zHV!yZ2&1bj|GnD$_u_+#1wB7;;QCt%W4%dFb&+MV({*&s#?OCRqEp5D5?b@)P7;`4 zJ6Eo4-39VZAC-=>a|0B1NO7d|nNT2a!g}sSP6g8Ucko;9??Hd$656 zR{+@%ziFl@1t*?MINL7?>0ZdhL$t7S;-NA5>p}K-@E=TVTsH|aTWS^)Q>!TpdrJmn zssPytL}^scBHLv|Af7o%QsM4tb3R zM}V}jpufa6G~RpW<6llK#Q8UpnMPjrh=6e*toH`?;e8X$|Ahp0V$OjqUu=}2426`+ zBEN{~l2TGF%3f4Xd5-XP@2i8dJ}zWDO56fU^ykfk%ix`&v&_`doyPm`R(qq+jl~HF z%sLg_>sO(Xt|YB&rJcDqSrQgkoM|0v!y`W;IZtut-t7z=w?5sy=Qt~)Y zpALggB3Vzp@w*#>%YNEs%l=9a#$wUeD63ra@ziZC(3SloA1FGeP<~Pre3n;FG&0#e zi7P}wp8tN#r+3~y9ot_ZHQhW6jBU(pJGYbVqW>aGqr1$pqtxo^J40=SC|%XuVf7>R zuIh!HR)`X>yl4yJ{b3`k4W9HO@5nipng1r}m(JI*$`5dMqcz|9uPtZ8pgsLWK^`1{ zdx_Q^8+ya9h7%0xf$T_Nj<2sB%oJ@oXU9Wk+@!SK1W;Jk-LKsIQKHI#n^8rT*$DXk zx^k;LW`ik8WzGgk0xAlED$U8z>_D@CiHCc@qQf2p^uOTO(#!w2g*J3BrUEIwSxk~r z=o4{S6|3?%XIsZ=NUow5*VdhHa;FegiN*~^r}_H23)l%*c9S!$>~qAajn6%>#=?G| zJ=~(}mTTw>^yReV$~}_$)>`-Z8stzHkwoFD%&ct(YMP+jgK-hAm}#gkwN!3sJ-)fl zKMx6k%1JyP z=(G}&qBAtKz>Fd_twr&LlE2DODv*fKG>NfOh8|tyCs~K^9u~g!=^mw)>7A&1fenKn z=3HP7iBXdellx%6Bb|B71|2%Nq2mTE1mSnmh~nRdrZ~^A=C7)R^2X2GBA}{!e5hYM zAe+;Zrn;-hLabDZ-XCQ-G+@t5-HBFYhWsvs6S%`%{Pw}}{2Uj~xX>LJ(PmP)U=aXYqk+of1MtzgHl zJnwO9T#W?H5EFJ$731m(9P)YVraD&12>2QQc8Jx&xy({U?2g~_06UUce(@w#*4F)t z5Qio%=Az0vQ?k&b=xU~M3?+LWOlsT}U%erycnQ(pgEsc=BOY?Uc93i5#9Z;ZKyIfg z66FXNCOpV--jqGpAI?~b;$$~CQVxdoC1azEHUNI&8&MVmI1t1efCCIHVRYU=rL+DO zDq-iQlK-(QfbK!Efa-y4V3uSYI6#bi?FoXob!R=>f;LLLiKTwV4t86OQfj&X`0Ei< zQV3gKWV6@=#j`CEkPCHZ9`e@jXh2tXy=b}Pn!FYo;nprIg$!N;+F=Wk(&XFTLmAlo9+$f1j6B!ydH><(jztoa-%}d|I8&x9m7#8YRgd)j{03)juV_CLZZnol zMvGZ>?XPer>Ub{sqP&=KuTG;erfgDi+YJ4b7Uwb6Y|7usXCO;G4^ z6~rFUZ@HuU9bcek@^s)Q@U@^n*rrMTxrWHx>-(xwym8>M%YW{={(Bw#&rR6G7E}$T z%%D(ay~GZG#i{!Hl0yz7=0kluH;v`8GSc&1dho2HON@r)gcIh2!R)Q)3Z3hRd| z(qlZtNWohBe)q&_vM{|EU;mWEAGk(YYt!g=wc9mO1l;heuhKWFH2*F&yZNPQ<6Bm@ zsIPq4d8MxO&?dS=?f6Wl0#$yj#v!@7sQRg2!~g>BX3%!o%$UsoGGFsqXQ6 zS>DN%bXvONFcGurtrE@s5Ba-F66*?5Wc+>9?pIPNxM3gtKu!7(x&ZtXv%=TLNfi|7 zdjvrDbr4K?xBz;1QDfa#IKI9O-WoM~cXk^vn!=?bxA@`O?ZwB7tUyDgMMe^scA}&E&@WbCD73GUsE0Yf5AXV zF7N}PjA5$!CFa}OCei1(WkOnU)~1DB_woANF46dk8#S+-lHd3WU!E(9%ft;uy?;{* zQ=n6&V~Sn$dK8)V+fi~$b2vxk;}Qlaxi7uD)CahYC1ye{ z$IwcCxOQ~CImZ+6W)blWP(2zi4T6WncucRyR(f`3cDe7))4CJP8AIn+^_oP0HhoVs z=Am<%$y7Ea7ggGP)=G#}zfR)naE7}$? z9H7k(kL4P!Gc0KvpP(fvXWXZGoOt`eV*}<3=5qgIR)lJ&16`yX^{Atddou+++C`Vt|s-)6N*@r|GI9oMT)usFZgM_>C6orQ2B>s-xkA+glzN-?<8Qo*eJ_GlK% z^AUC~yY@prAEZ|xz@-SclUljPGA>o!(I$=C(4!B?VBaUPsy-q5z>V7B+k*AdZ%b>2 z2~8{iC83iJ@hXKkrPZw+y7%O;jsqnDE zD_sJ+uGrcMT9Fy7fjcjA%M)-O?X?ceJm+psIDEc{mPF%4u>aG$*?#m-j;sk94EVM!GIG zGlOK%>_`HVZ{Vy=Es;&yuSoIW)RGv=n48ta)mED0X{X|S6``3P@`nX_*hP{Da&`Vx z%JWTEYOnyEC%J+N)>*-_vBf7$*K%#_LqRoifm1#Nti&B7z;m6|{hM>MaKdyFx7z)I zIUN3iq6PJXo2dCh`_CP3^+Zus>q!%0C9|tMy-jb^o+j*NB}f7<2WFivZ1m8x-Jv4ze{kTA18 z730y@3VmD9K^`wk*h7}2*eN<5H1=?JtvY%uZPh%(cFHglYYD?aMph=TTi1bC-1?lO zrb-yz^UnLR_T>&+9d1ya_{KylJ4WF=ZRyxdnx}q8Kbt%lWjb|RTB91Zn6xcQZ#2@2x1_E1K&nYW>l0w zBgUDhOw>cBF#pGgr^01{8Lwi(U(BiP@i7yqxd!1%$qXb+jYU67F%DU}p>Un!4#gsA z#j?8vG3jcX8RP6yDiNP#i~F>zB6wbh!L5+KRIr466I?kx)z83I5vAWXn0mD^+#8dz zYdhCO&TGvyBHnb-qSbr6805Yw`#H>qn(5`yokh>~NI*1QFMX&v>);-)MbjKio~EB1 z0=C zZ!DjK*l%-k*G`nn^;QQlirbQ)UOKvB48#9HEdbTJ4QQNvL%K)a_ON?4#)O(pV_%`Q z;SB5JEuj8}I>z}jv~mjm%u3#hSv&pmN2_FdJzw1|R(W?7?G9(VhvFM8?J(*9Jn!Nd z9J$5TcCW-B^j&|e$KMTKo`=o7c;5y%uh6aX-Os@z!SSxOp~2N|Cn_}NJueYndV4F0 z60GA(S>}TKW(B9&eV4FXaLPK69)6t7GO(*qr@(1nv}{P@OFo4iJCTsKoHmdNmZ3i#@IZ$_=|0jizyB<1gm_UCxiaTxzwcG>BQgqd!32B-w7nel zl741p6E}1;+*i#xkA6$_K7{gq8ZCYO7|BoN4}2}`WcQg1_#ZuU_y55@Rr}7DgZ8wP z-nPBg9bXX-%%17KK>g^!j0-y?kt`r7jEntgD#IgS&vw@yv#dZ!5w$&6 z8zG-Q``+Y`g>e@y;X(h0l;BcjcN(kziOjhBH(Pu}RRW_GivwgR?@KWS-7oc{bT+i^FP}P&~PZ@^!V9K#=$dlv7UTm{2$w~sq84#bprQV zPF&hUC(3nGzg(caZVX5lYG(4l97LS}i#;eH>Hq7lupjWmG9+Jzu|rjT3^=cNiTZQq zq^b578^bIQd~@ztJzg5GU4?O=vfK32>+5Fi2!^Lfy~;FsiAh_%R1f4P8v#$$=9IRS178$36Aj*U8^m+Ofkg_w6YvQSU5vpjOeo z#jg3j&Bow8u}?&q8s?P5r#L#;c=@V%^d&4)FbM}EI_gtYfeS(9O;mWQ;V| z{QTm!UyHU7@6ou(Ew^lKhkJL>p}dsK>l*QWbqp>qVBGclCvV`lo0^mGp~QzT){0TV zFEV8eoT&M@0q5@rYp~pQiRs`4aav(=EY?N^vHD6ato5|c_yjj!Q$pY4Nw*+(@Dy@K zT_5~_2`Ijz_A#J1<^-m@3tH7{#}(>_`i*W@&WUbkzcCO}&7t!yHPB=}z!8&#g+e_7Gon>;bdYY1eKpsCWVaQzsadh4|_BB+bx=t?;eJ>Q`|}J-pH}+ zS4NxT_Bxe(m{vnO!1s&nR(+3%M;_6%WrdTZ`{%L1Y!~<7#v0XclaaY*}=M=GZom zi*G0zvs)43=EHkR*oRIrxQm8hd7+D#V;3?fP*a}6U)EomhQ=4D@>4U@G0QJ}XbO4{}*+^E5O9!?^wa&)qD>)j>h%MNb2(V?qn(c&A z0=5=%3;Sl0c>z|x&5E2jRgTJLV*vF<@Rfr`e+=Nmx&E8JM*s66;2wUuY+vA5B?%O; zk3pwx$8$?(QBc!dfT;jz%GTXuy$|%Wa0c!?vMN-)onh|STSKpp*k?l~xIxQzDkSe} z?D88v`x%-1%hY);k=Lu2!V#|Kaol%PYu0DurN&a3box#G9atnySBdzEe~9$pmh)gM zd4OsE#XG;XSIITx+C>CqvGjei7UDQQ5$t_$0wuSlRA;-PG@ak$)erCi@!Q{^lJ`xr zXEgDp;!YS>mk>Fja?CiqT`+e7=qlSAlFn`HK5)pNGJ30QAIuxG>os-PDI`xkt1 zkp*8WB?90CnH{i;T{QG5xHfudZ@*a%Q$N;90Qzgvgk^N`uRA%-1rG|$jLj}DG)KR> z9d%6vu;;Zv|LoJNikB|=XZ*1YaPn-fZ1|8krtn;L(LTf$nW@m(7Y08bXTTLkWm3=e zh7U_WF<9Wy$@me-yjiaOU77nvDSi&>a!frvk!^kXMf%ysT!z}%E$c>3>6lsj?q&Q? zSBAGM7vAP*$VL=*|5pK-pktDsZjLyJYYGK;AWH$YZ2=2Y;~=MLS@inYh+SybxRM5W zZW^JWZo^wI4NQMl^@Xp#`6e8Lno?6oRFWthi|Ox^_;rG$IsBVRc>-v$oxP> zJcgt;b3S@b+105+@!KZ&9ocvjv~f!l+D%ZyEP(yUXZ_*q+HP1RK)>@I)*Rs$Xp)K>&WyCr}k2OEG5+4HFmx&M6Q;0!AcUtQQ3}&jk+HWiXRB(T)A^ zNNTy9fY}zWU`Ny+^N$hbo1~^^C&o{i`b+<)qJ|6Sagq$hn@Jv?`yLnvIM(tW?msSw z-ws@F+MgV2|4N|<85h|lyN}IGOmhh_+s=D&m>{CPBo*9!ESfD7;B~Q%WnX#W?6n+5 z${A9)i#OL%$rR;@<2+8VI}dg?lYNgY{xf*ktno_jr+gy?zI>cKmdGZ))clq;0t$P0 z?J1#PWC(zO8UZB-?|>o+Ajc8hRnQE9A?VTu5Gd0KZ)5pXm|fH{Z`ej9q3e{z~9wQpPdt57a3?LiugQEeY4P< z^=@*AT!1%PXT3nSB(Jy!1vSnEVqtjz)5Mq_s2{vzK=1MxKbZaBY-s*1Q6M9 zk|qHN44-d6Grt(7zFKIl>JLXWwwqox<6nJcz@A9Y1wMUE{$q4^keGjHp0vjDRX$Pc zeRVh~p@J3$i>;O}ge^mk4y7Y@(O_IQj>NNI=geWQGVdT92o_Ex#o$`x>tWXQR+!2H zMC9J*nQpD_qG4>;CUfPlgW*5{o8W6u1da4*u}LS@68QMJkCQT0M^ih7<#%)sQ=HMOTkhD* zDpOGZ<8zz2`Zic3JYRZ{)J9hWKWID{3QRSS3P{>W0s^roP`)wX;N^Glm0s^B&^|2x zcu)WLZfcYOV4oDkK|z{#+ylH$R2V6bKQD!rAEU)$XZNG#=ND3szg0js;>XV$D;q0F z9mmA)GMit%Q6+q(n{*jjR54&KhsI?YAbLn*Y#>GQZEL+@S-*i;cM!nCMO-aAU_J)8uc52KCwCEm6qxrEa>dL%&$mlF0rEhv?41PQ z$fs4`j{-E;K)bsX1EeRM8yya09F}j}`YqD^zUb_za97K8F1rjW`C7HFK@p^(=ckhR z79O8>@)poTAmknN3LBKLJD)$wL~Bvo^+^x!j*~_D?|r)Af;%zJp}}fG5LD0LZ8uEG zIdVesaXdoq&^SPT4cwXu*Vb~{e0ewyOetNPm@#0x`oOkN=`V?0b0KHWh1Xd?VP=Z2 z0<1*dsLFX2W~(E-lgNeYP&u2JX=Ay?R~Ixqke!jOrpjWtaW!6M!hr+t%s|SFYTZ@v z{Q|T&k^nMe?mhs8Rt1XcNiLxND3K1lGIYhru^kKo zC-XCoX9@YXg7V+5q&|yswx5l;R%)K@@0EG+U?B+=W@6#<30t@G z!phHrpX{CBj;IOV2qR;SPzZ$leoB((9zyVmNyPC`U~E9^`z41}aQzU5Q?uY$N?y&% zi?A-SOM-+3Kg&l5y{v=_l;YkkKd)aYxKQ7etB?Q=Vo!iA@Mqcot%Q@{FCY6`1&hHa zdDq5#DFwLm*6EHjg|ZZ>?wHA(!-5dLI8etmF>o}}$f;MQ7Nb|0kc2fFYMACsX(fS5tHcL>IYf!#Wgd6wbEpphdreFYT z1r5#kEARp?!397;xoZ8LtG@ylAr0PgfRhRsJZq^eM)!7auTQJA%Rh0)u3urA_EvZo zbieIst{VjsMNpeG-q;LUgvI+Q?uU`#m_;b$83}hp zJR+=P@Yk&89lSMcoJEiUt7G^unroA)rSWlI{$r+Wa1@T9QHCzGhcfn|a4{_xdk@W_ zZ~`sht2ar86J?xWGoyg@C8Jc_6tdl0=2H-@%ZV5@BSQKkMGzJ~1;7F47+?=>Ic?Cm zYl0~}@Id__0m$V_Tsv}rk}C!(0WM0tLjX8GhWgpYd$Hh>2)#OfFc_dthd=bi2JgL%qrYtpCcmFf#*sZSY|TK)f<&LIcG^EPNa93U zam<-5$2x4|8^MJln62mf$9cWRD_}3)fRPI6-{&zXh7*q|OkJkS!J^6LR7RN|MF#;Z ziEC2Nas;c%Ri*?M5hTwTVKNaijQe4_UJbof;Jo~LrXdSrBY&&e+pfq36{V>YMY$8; zOvX8uHL1_&>m2Ut@xg2SRjIiUwOiA+1Hs#fv`lzY$`(`q2Oigu`i#4jX%bR^V_}IU^J8K=8*U!ea`XJ0dNdYlb=+kYb8~C&Bf!%sb`c@hHRe zoCEg0+#Vk@v%WaF8uF(`cjJUYBtf{7g60WHviUPh_OUchO81q611{#Ola`~*tU6q5 zmY$mZVIHd7S{A^aS$`oH08M`;D`euT6!>({WLaT>m_r7&R=X{>`kyVB*EN*dSS-RXNPH64a1G~iYjeEZB zc+(YIy=vVcn*)cWgLW-^nRl1qQ@##Y@M?p!KyxqCDgvF`5Dj=+xp0E#dU#&CY^&2!%HeWMG`qWF#W0`T%&msm;5p>PtG(L z<9_HrT0RM`pY-31z~AsHC8!wCPk{)a_r@P4(DCmA2GK5rUjxdE{pvfm@i|qIH(Pau zst4*7e+BSzUMWI0v*;rowkzGxj#F$pzxZwHaoN1wl4J@fP_ljy?v;$Ie2>s6vQT`z zxskU`@N#?M__$m)UP;qefqU6+tBf+zQsx=hbD#$I#hF-=+LUhP;B7Mo>GDx=Zgi5~ z|9z1YC3s7T2sishI;0aR$g@3nR`Q;qGZ2H)*V3SS>lt>P5AYeo^>eR(a~EKEru5zR z3US1FyA2z!P}C4Ax-{; z=v~M0tbmsrG%*&Q{f<1O!SW<+`7C)zUUh;zIrrzHNLmKdo`)+6x1_ngmw#wHO76)6 zm3<(PNZ!LB+SYciobRfT%#C`HB6K89bZ3jJ$(7@asKkzJ3Ej9ym;*&O>9;q8fri2o zxtFZlM8Z>&*u|dAc0W_|%W{G$ik=nIMJiB~_&%g^S5)H?D80IC6-q@ee1s*%$~Y=d z7bVZulPx3;U!HpW=c;i3RmAQU1hOu%)V=I~DTJPWelI}HV)}IMFmg?x`q7kmf(?ft z8GO3yQK4bN^Ao3iFzq9?h8DOknfeD#|L^h(`k~mzR)Y8m&2>`chOQzb1g5pw3*LkB z-L9e5AEG75Z=e^mudd(Gvsol<7!>>hx z-X9EyiY?EZrFLWdzhjM1`yI%+c9Y#B98iBPKr|dJKO!H8_318Sfwv!&z>lB4Az5hb z>T_Z89AvTL4~#A0)nz_h7U~V|#~pEr~#u3+r%T3B`874d|jW)%}?#_JRlD-kghZR?;U=_ zlZ|x_FW3WBLl|_@o2H{Ic%<2l!tH|6FeQ`&B%AZ`4vQKlp__xU0`D^vq?Doc-pm`G!bN{0(Jx9lKwd?@M!fQ#|^ALe&?3yDdus)nG&klSRN5|JDPr zS_2sVpDM6}5ul!jIhrJ*+fT4AUg;nxTckUCDy%2jsC}$`AtA?#NKd_+KYiH@>x+Z+ z^r}ZwhF`GjT<8ti;%8G+51E6po}%&_qvf%aj@s7ze$;r<5s_@a_^F;9ly?4`HlwyF z$VSuG!$2VfMixNB+UGg|)f@l7belN$n;>K|PI9zUH1Ic&$Y;pXG~)uvH$ z;gRPecB^bEg>`=MZcUi4swkrUrf|j-(b=;N(tK1qC~PU*6xS zFZ1{MBZ{Sw;z&vlt%5*hSsY9wV+f4TwE4B;Q2}N3v{cW(T!4FnN5(v3Q%6M=VoerP zwK9&*Af69~SJw=;g6n+A|FIH)*9x>a_2vx7l0`A&3+#(vmvH-ORepCs2CRg7U$s~2K;}VSr-K^X7%C{AWEP~}T;6gTnLQ8!S zvM)%n)$QxqYuCPq7z)Z+n2fbnh4+*^-IVk=Tj4fOFpb<0`i->K&^rM`1{(pNF!h%R76-8oJ^BFLN*xReZ+TZn!|JgPt9f{#s1 zl`feDwB0%$1Hf=;6|gUkcxD?rTheI7P<{^*(U61!gL zSY&N(@-M?|`LRnOGrTSvqP~Qvy)ZGN`);|A-G`sKYQ~Cs7j?TbFbPOzMBqEIBx7a6bd%-st7ny&_kY`E%t1Q4?pgRUCjWIEy8I63ww*C>O zi08Ie=!aFrK~!SKIbSd3wl8%u;{RSl04c3Eg}-5*cByPi_eT!h4192WG|t2pYh?CS zX1!B=g_f_T=}&ryjeiSwW`RpO)jErM1SMyZhqS%7$yf2X;bAQt_+&&Fn(C;$^=5-4 zds|0GNN}5iEfF>AW4AY1#_yTupgW{fIGs|2zy_v^c`-@!BKRB?w#m=|dqX|?@5m>oj5@Bm*0!IeKWZ3ZYm6Kfs zeY=G`UW-QhqWMk^mBP#lKVVB2M()cCFmS2;nYP zfAk*(U;SNlC0Og{e*6in>4I^9zSvI=1R#m}0TyqWr!w7yI;MjBO!P|-m#iL4jDR(6 zkzhV{rL^ya$$jV8yYckYzBI#F)4ho@z%ROneQeWZq7rU4^Rw*WYxik&JUAB8M5qzh zVyw(g-A^r}Y(DP1DEWDj>czD4?;88h84Vp~jM>e^3S!A=K_gT?!|wQKK@zvd2ZfW} zOXl-F*{BEI8zf$38DiD>)RFZ4mQsXM75++DMYMG!If4l|_@>z}7P@M#h-qxCUqDvy zTn&^8@^e2Cie?4gY@*s~#{d2}102z~EFUI0c!_Ffmfx-xBi4iabs43e#yvTHF1_Z1 z6en%VdOBGs=Ff|sv7CA>O8{8ZzsY+Ko7w_R>p{*2`hb4tUw;HRbNG*`g^FYJIwc-M z(u4+J`Ukoaz&)mzMBTvrmgnsQ24yoO8rTM>qU=)8w-1giiT>n#L-~TmKlJnHbf(QF zaq9C0M0CmGh-<9HGt71>lgSqBafYfq@f%!^Zh0S~*8)<07U60Oa9h|m5+ zWiA<8&YRbF2N!RWjFS?Ig(@g}`}ibxHWJEC6xKB~I@#q2bKMv3@ObI^$LMTOd)e|P zNoHS*Sy9%^ZDQp*mC${63oO2MEed~~#qtFoaLChHu5K0VP8b7l5D6pc5XR|$s4Z|R z1wdbbwNM@p%t=8c#dLJ$+cL`B@Z=O!hnZ=Ang9E!proSnX?DpsZnzV)dC!<*b6dr+ zV3450BG0;P&&hzXsVs*y;3gbjK!7*4l0TF9ZclieX}9p`2)UImWd_@m?rx;6cMF1x7yq^KkYZ z4+((B6~h$!H}&IxttXghi(Cf;gRo{*yWxX+`Lk1B;EZ+OpORh}ZKPQd(pWjA6qG+_ ziacu|QO;nIp7D0aGtuNK-z}u29&k$imcBIKFOcP9tOEj_9St)saT1ZbHK?q zjc;KwK7>Al??6yw+cy7&AFFZFea%<2N4Y`22I$V60+e};*z;=VrRmzrA{!5!P}L)Z zgb?9xiatJ#d1-~C`)9uci63^oEa!9nR%lB1jzo*tt-TA#mGLWT3Q$<*p4{`0Gk zY5N`?KzS;I1%+@PRhI>@Vmfv73KGFWx^agiQA@_6TmS@c`>#E6#P)w;(Cecl=f-u$ z$>S=|F*c@P9LicK34fu}RsB<5rZRxIG+h0UDnD-+vmZs3lXI;Z>N^*v;J&-!F>Rl{ ze^n(E1+ndilvj1%E zf1(edsI~HP4Dd=8=!M>BMV6OYv%k1{QSs$s(mU6j)Lg$yW1^DlBp*$%9r$I) z8)vl>7~bUpDveNG^!RU3JBNy|3qwJuND+i+wPpFha}8u8-0{r?B99%elQtVXM@-_C zt>~u*SVA@@9kYP}6f5Lfg#C{a${XMbR~z$0C%b(N+?$AQ&zJdh!S57u?8m^=~NP(RGoqegGBv^7ASh zUN~T;dLaT!5>|Lw35?{o_N|=BFpfy((@}JA>Jw7WeLp zYP)zPNzE1$o&MQxWo7pK*77O4>pkpzPp2e0n>4Wz1x@}31hL~hrLSXXO#<}U`UveT zCYWo=&WYHJW7wVylW)q@z8kREv+m2Kh_IBmlEJ2L_0Jk2J)f^Ra)0D|LiL!{E(5;g zrch-%<#Ms#2YHQwetDS zmfwuG3VV4xay%R}QuwTW1oQ&N-fU;?{T>afv1=@~StM%Eogkyik2S}q+1UIP0f)=(NP8g={e1;LzRB(QP@=_$JP(&K*k9fnf!hLF`5i>%fJY#a zXbs(;2sYt>I!B(sYOg>%yMP8XgY&l#Q0vR&HX*<@$aXT(LyDTwzY4Y`%HJ;R8G|%a z^xT=_5&m=g)tFQBb1)6g7C9>tT2~dIkta+~dW6~Yki>ph+Fe_;+KSHKulG1u@DP3{ z*og}ksviI9A+izj#K~O_Ph;eS; z%xz3%EBhr}8J<_VVag={7ZA*D2h#?l{0P8OV+>680XPpq zjFk!j=mMr+!QDa!QhUKEl7?CgW^y@R^L##C1bckji~i? zokj!?DhqypPu_AbD`z_~&$hfL{|w$a)Pi>RL&&asA6?4JN?^cxb9?T)eE_7EXK!~E z3M;rya;P0Ckv;^@xA}qBi!vZK`gIMx4Axkj03R6<{8i<+vi#tl|N8&;kyLxOUv!L| zlr|Z;?7ilJw=)THzC6bwq{%1QhJku#6%!)zL%h_)U{sTgUWQA=Y@H%(PiZOg|W)5Nv-5)2sx z`ye;c5)I^LO3dVCRB=TbJ33K@`(6{iip&FIHxNn7ls^LSueNEcD7VU1yDi)Z01D(1 z5j174^dx?sMq9kKasP-9-Mn3T)bFOal7@Aifi3;Fyg~~kavX>bp`Zr2z?JUxqmJtY z-ufQOL3*GygmEXVBLKALH&poxsLGtc>Y4UQlBV+&WxeEALPyP;kCUF@~@zGUqL-a*ZDzvVNa;>alhck9xMGI;EI?sptPp zGjwz32zKw79a229*$|lCu>!@!_OPQXmtMWEL1?a$@=-oHvKK67KstsuAGrj1OQCm& zg8aT*AFGuTK&&DHz|@ZcB5Pb|8d!C&NxbN}96 z;O4yLqW%&t9I7d`__!q=Qz0NS{PhANf7@c%j#6apIJgp~bHPfYP)^xQ7E;_uPRG2x z$7n30Xm?{Hi%fA<;}%UP8FqwaP@C8&gmn{y@Hu~^8(r#euX6V>s7-d91z%cPlr~cx z8Pi7<98t;h{PLGEQx`-~`d=U?x%6JIGR;@YG#?q7Qh}isi4reT#Uh__(`PJn*klbV zNS*(EL9MHxyxSz%-nbrIIZWrnKW?Q<`WuYbL)+=PX)psDe&xFeYP$;$D3xo7rvL>_ ztNGO#w1Zs{v*)g*vG4d^^NX;EQC-CyMRG&$XFn^-5KeCv3v78{9^s+42gXZlo#n`} zdM2XuHTQXurp9tlPKzsF*8FgFTqsMhGWBg~@G9L=G}#Vx49EeoYDjl;CV4JJkt7_x zFk`05(L=^v)6&u`R>r5o_HGD+W#z6$@m-0KFj#P_=%WyBTU*=jiDfsmH*+@`frH*= zk~i@JhBPs*e4Hj#{LehEYA95t>Z{<6(iLYV(9zx&lqIy)S9TBz<*JXB!&~J1&<$ls zewRFvdnHANCA2Bl&W;(sh_Um%2^Ac&35qXk5$on7{Tu#lSy}+C9cZlY{WlZxH=xnn zb8M1x9xRsJ6#k)AZ$f!TP&tUU-VJzWVq*V%qmlo&HrP_YcvqY*tcX$h%KshrryS+2 zLHC9idY*2*r?$p#Kj8bWfZfPUH5mmHLUAW{N8(2A00*-J8fg9!Xc#Jth(At^*ogp%Cc{ue*NZW7GeJ9_`U%584$9Fp)!N?@<1bAqnM0 zX>t+VQtXlg+kUtxPU-_P)ga>maZO(WSf(2d5J2&DLgWACnllZ73X$hkZFOa^s5T`P zQp5HY@cCkId^J+kGIjN(N@F?hQKROc8e-(r4{)5sv{fa>_*9o!&qW;{1R^W|%v#5} zriFJnw|5Z(Sec?Y(dsjlc^_V=05Frzjyp<*qVI>p&jP?lKIFlJ9=A5Uh~xtwlmdL${3Bg z$CC52^@%YU4}0AXLztiGwo!%*kDn$kSu%emsH{T8ExIoC_pwfL$?jF>%at{IR;cu> z4N8w&JOOSgO?AxIMt+XR#rIs|fp*sIJSrv8cC6L@JY0n{<>R=(gubD@N=&AkO->l4 zZ~kX%<@ssxsy5++7J zl?#srezdMt_@OFSa>FB_OWvMJV{0y(Pu!RB0kG%Xr#0wCB8s@%s}FYBBa871c9(K{ zQ9F!+g6ydPSBwkQHDo*^o_ifM>0f(WP1g-DU@@EpBd)*cqdb63X-mow|xKr!ZZ zNz!z%lxp9L0LRGLW+sz_aQbY5uiknylpFY0p0P6*L(x+8uU|WKOb&O*ZI0yPbl#OG z8O9dbl&tiZB)H0#c^FD|-y)l%wEwm!M%i}5Vic)$T{twE*GYK$aBqQFk?`FnO7Kiz zZ#clulG<8thP`U;g5VAOWw?qh_TG7pnXcKq5%lYbXX8DcOG$B{ZkOZgK?I>l_6G+={ z&j}atEJ!7=MD8*Dsny57ue#QA8QA=VWjtojCww)zT@olI=z3N}KJ5oFqo4?%oh>-% zoS6lC!VaGOTeMogg(P-x(yG* zjO_q$dLS*Me85q=-c>tzHp@6w{I^xPxWqmz1nMq8av0a}FvIPP7f6#N+BFX}7PEGz z1R>KqS_l3PSGI5wiVayx@Gx%E)SHX)`gB3JdZPaj*!vj)H+^vJbby4HzYmmE(Ea)+ z{)euDfxwLDX8H{X#C#SZxTPQvzb_k>6&p>PR-vwLzdPMmR;Y=c!SKQ%?kyG~@>QPl z=iO0UW;gbBBegs&mE))8_aPi)Y(_&|Dq&osQ7mGod;t~?!{q44_;1qj%y5ILSWcT5 zziP56bSA_X-Hae(@j^>HMx#&4N2K*RM`)0Zl**u|eg9~(g?&IqsGJwVTPgiM1nqv%CaAO@qyT(7Bdt;<(1IAZEoqF;3MtFMX=fZ2#xK97E(AAX z0ePO5PwT_fDc1)f8)TCwA*OPMk6r8kHKmgu>~=OR0hEjVx@JKByUEXct^+?Tkk%=$ zGUHdo&U624`p_Z2>L@rR$J#l=V!kInoJHL|sxUq-#e2g^sq||}#pzJICibB+fuU{h z{z=qQFJ|D@q*Fm0Aqy_<=yytTE5hwBdvU|bldp-${{#f0q&3_*+&KL4T0N-nxPyc{ za|K5$`4({GonOMAo$_7vYZju;_V6-}VCv{5vzz|z+&N}k<8V!7wHlv(Emmbd(-_{Y`yTNh^F8RJsGsU!kutvP{ySU^F?KH55iAAuGC zXFgF!+*3Iz61Jwt&&AX&VB|ePbIi$U9u@L!oOH zFWJ@>RCoJ=5YS#_3QOi$I1Tcs!LRl|$3hdanR||CZRwVKU9M7KT<)@Ju8_`MvaS06 za>F!(guk8Z8iM};`am1;7g>1${2Bz3=`EJgeyfV3?ayiG=Y%yER@~daur|^I4f-xd zQzBk`Mi`^1)2q-9uGMJ*iqD45HUzQW(JKs>r)5$eq&T?xlrQg$JzxGb-CmR&dtrC; zeQ*eN2ODX+eo%R5hsK3%UR=tRmYTHP5bX?&k{2{`o`p|-z?D}Rcb4Mx6GWdNI*p>p zCt_4|4q~5US`@A)%gR+d#@%j_4_E#$Nqfo(_5}BuOJo7t05vspGU)Wly~eNnJXpSJ zj^gSIvb~k?Q0w!^9gqb zAIzzw%@h1Q73q97wqnuCSV&1fjpNr5@Ct8*`?jR${3I)d2V5LaK7CLC`Yew|m1L#l@ zWwvc;$8W1$=g?jB__QQYe$9~nuc`P)K0xRR6C^xHbQ~^R9iut$8k=U-rZ?=AKiqL z@oeRvSPpYN&?*aLRfZR;cZ-*8pA}Fycx~x%Zx9T+?O4(n41141X|kT4+qsCJM(w$0 zkl7Xg0&7Lz&qFO{(gkMUN!T|c*!q_^8A-l9k=XNzpWvkVIWnNC)rW^MxQXRs&|^^h zdf{h_DtwA_XTg4@AYO{+q4(^{(l?mDLd(xlb&)u6&otjVKqd~_5#l?;lza=rg74t> zAdgi@-M&{Bg?%q)IA3u1pA+Q&=*jhNDhLI#8-&fN(U%;%r|%d)TG1?U!^lFMq%tK= zs)Q*r>HWSJzztY3rQH%v5W=3049jB@rL^7SycP4A$&lMm|iaDM;q>fmW~1t z!F7*p!BLTSlxD@H+0K&ofZjm0@TmKdLT?XQRk`H=ueO=kSN7N(-WYKLK;_8((tZ*v zGyKumDj+@A19%K!d0u_*{w|(G2at&lx=2hJi691pAA?0DPTBu#l7DfFe^p`faCu+E zy|1m--ltM5{m=Kryp3hgWb{;m=l9 z_NHJqj|93BQ}4GN3YwWeTD=u8G`4taC)q#goMB$v%<|`Qw{sxU0gxwLtIL5H+G<~? zAH#whqhjXf=H;Vy;u~9x%91B8VWgfz69%Trihrh=JK^@0b)$4|I)Fap$=J9-{r7J` z3u8wlFm8WX4W}*oK?m)^i-BJdzt6J&wG#i{{H_}&=O5m{wU(3q&o!Wm9A}qH`yxa0 zsI_@=kXIu`$$Til(XJu|il~%jAw8XTy@}Am8naU8hLa`f>JQB6Y(0DK9EcLL8ib{- zH`&T1QnyoVId&$;6#ro`y!Tj*ixko{a=T;zu=%){&VZ{3(Ls=<<#fyEKOhc1+_N2- zxff&^1-4uR<8(zrnurepz7Bo&?2ONOP&vVpoKRA3W(QJoXXTi(GA$68#wI)9m46*x z5GI$do;d3k1|5fQBb+0W5<5VyFNko;@ql0<=41?TTtfr7*RVTy(1E-gko671^Po?E zoeKt>shD?cI;(VW-&nzQ8Tr}9sn$*|Q27;erhHSsM*7XvAe#)vdFV;Uii7V9Qq$3T zW4M$_B2{UCgJ`wDzH1$K{zPtG9XRGEZNlF8^Sd|l&nt%$bgBon*f_6jj=i#vWWrgL z^XyI1QOt;jJr-PlKc63SNgtD=4uyv{-%pCJo_Z(})^Tx!*Zj^Q;QbLq@X+W*3?%z6swWx~w!Yd=zgMd5la0Oy*Q%FqhDCp#Ge1p?0UW zk+N{;ve4(bDra*t>A>DH`WI@?DYnNsXhrEGo7(5P;o(jrv#Jy%L`aB*G>H{JReOYM ziiG`2YCATur8aDl!ftUx*M{iXYpCb!;Qv%re7O7WtMCuVn8=z`R8!IV(ch znIDH+qS$uoyX^uFjx|4hU{z>9*OK#!!06ky&Oln zfOlRw-+KZb+`d{TxYY?7meaub^twe+Q|E>pr(?vn*3H6g*fk!Qt7zN@Y1r@8dDpQk z6y>o3)dzpMT=4Y^oCl5H2x6i2L*)McZYWw{H7Oxa#jZr?)*b(8_d5ka?_m8csavAl z_Rl3^#M5pN!6ufdv?NLs^sviu4n}ib=b6(96C1?k}&1I~6`ixvg36H%8?o^>}Bk;PR6|FQDmgq(!jd4Li=dS2=CtN(SBXVt~HKos5HC zTrpsdgAT_+U&xsWF_@7-Ff&$n<_<85Y5xfHNX`!wA>O!$4*s4Vm?Ml|5KWfQqQ6QoT0>8c(2Aod7|Tq6agu>9AnKiG0cFW*@QNPGX5irfjTSYjIK zuK8uu5?@46LvLw*Uu0{aLE+4BiZbIs?L05_L%#b5kHK%aE2c`RnBIZ0EuBH%;=M;* zFDd;`5gYu^q{ctW@jHhzXIUYJy4apw2^-KP>fjQMDxW9c1GIiXYWe@>cMr!MVw- zN{S!dJBdqOy^4jm#&q+5>20&^7Yr<$@Lc`_>k>GPJDI$78VT(6%dE_=MTLc03Aej* z?15CUeRIn0lwpZSIGj3@XucPTTAExr~trqYCe+;^ziHU zOGfsK!b4pe-p!7(zn*#s+;$)@hza)7z2O$lE%H9A{c2U@i(%0b*$}|hc+V+oLk@hggMUJ@1OR+6l}gJE>#mEi>vk(M2}1I_)jxs}hjtc1wt? zXWZ5co$u6bb|(VpZOR+%kH(oM-$ye9g*l!^LW<=mrs%DrBq4#cm?}1e%2D+KCw9hj zxXK96kvQgH+Yv2C4Qc?4vkyuG+_|=si3Vbra>lr8y8*Z$U~%QWurYv4Qkr9#4S42a zXK`HBjjZ~zy4&2YWeuR zQ`FfV>axLV(VB-2PuS?aSQ!^g1)Qg`V%O6(w1^q+Go5O@cXPR&W80!BV<2)o9ReB3$~%n#SC<^(;3?9!owuT_L?KotW6=|6%OC zqnhfv_0doiP`V;jdX)}>A|(hYO+cD}(xeIqC@mBrC@3JI_m0w}E4>G#cj+QRz)%FF zB(wk_`?v9ZzjN-n_ntfMKa6B&FvePIuQ}&4pZUzSelS6J;+`Bj`6?9dTdSah`N&1d zk3FoCWL$y|C(b)e6rj+MBr;lZTv$OufZnAU6_X+ z3^~xmKQXMp2+Z=R+=^PcP&eqJ_&cSpnCgS%{W%kS29y&4Nc=yy3K6)3z~~}yQ)f4J z*@yf?P4bBmLE1KMnWu}XO4R2{aF~+hn-_}7rDyv$65Aqzi|;$7IZaYJofxBpS_Sx6 zU))a0RTC^MRN7PVi*K{@lX8?XF|g-y!Zgc2f^cdY(8m(zgu|$ncJ6(u=IZax!}pbi z?|;?LyiY>9!}ew`k?nPxSQ{(pK7aMLYwjs$$(7r_@kh(hyyq{9r7x%@-jcVtNp^ph z$tZ;)@9_;CA&CaBOEfY;$$j0<78EQK%XBI~1!krpN4yu5-{E+bcNa_o^gXEW+!14( z=XeV>wRDX&;k=<>*ghR74ynPp|H&Y7OL;el_zoc`*TH(g5=cJ>8p?EsvB^1$JnOS5 zx^isruc!TMQUH_;j)q$Q8;yc7zzmkd{8%Q5U@&gw_bZeA!C?Qo)<>^-LT*WxM-dZc}-YgDo0Cf`#R9z!9cGlP#tW+$PQL!Vy^kf-?EPSK%WG^cJ4)R-$R3Tgj% z!Mp0$&-mkM7y-J*Y?;N_*YPsF&^)N`xJ_AB=EIPrP_O;5TlQJ;n+8k3SHZ5pZYl`# zalB5ici{4}P4i*68)pwQ#6HLQ^j?#I>+6^C_`Hu4&qnU+kDo5Xg4xAKtfO)G%%wAS z!VXU!&V|-6lZe76v+oA~hgTcM^LJ?&V#dGV^d3}F?aJZr9w+i;#RWzgVFZ|a0#aPN z*yuj~>uOnn%|p<|00m6vo(9+fL(nHC04@)DnGdoFK@&&sIo?CVl||One|L4n#PI?8 zZNhE|LH!i1=2gXy!n4KokJ_#zW<0s%3toe9O80@64AudsTGEn8d|t24^*-K`K9e%# zP|&w`n4|t?2}MDU{W?fkh#*JP{EKMbwcueS2~+l5*kwhD<4KNo{p81CO!mco)Av}$ zm<4yt)9?8g@Lo2apfk5PT2TGf!A|hsKMLpS;5Zz$$y0sR$!$K1Gho|DB&J}P7*YjCz1s4+L{y-g3Qa} zj|zggUK=CbFnGSI*D{M(Q%7m9Tt!EX`M7E6{Zg6?#*&jv)(?q(Njd^TtqV`e=}Bc) zEMEiq8Klc*WLXT{AH9el%-+0tZ{(H2ekpzYs786*D}IUIH^nwOq5X1x97=L6>`v^r z4ONAy_Am8O2EQsY*I^f=fj+hAQHT_^oma1_zloXZdY14#GyA;^VUMld9L;eu7>rWB zziZN?lhBz+3?=z?#(uj?dr33I>FnD#<{YQ=MPV^f%#3kEW!BkT%E{AzHuUI`D;}_v zB;+uFbGPdHch}$JL&M{sX+ZfifYfZ=OrWAW8_}=~@Fh*b#gf@7sh?jpMid@woo1%T zC7U~Qf7ADgf90#;5uaiQyz>&NW;{+GNsRrYEkQC>HJzILx{dMp)S$1p<9k3%e?Y&T zXJX!H!d6CX9gC&-qH(Hz<$KZ#T4@BQbcs=ES{^T{;MnA+ND*NrmQODD3E4(9-v{iT zzn6e3`5{Qp-Gs2bn-g@MgP(fSHs2$AMeLk+VbPZ1fS)9x6C6Ff4Tc78MS?q)1`TNb z&u4(vN7*;8P0<{|UX~B+-f?6?Zl@Im#MQ7o>>nYv7LmRAj4WB_$fzpA!}dWHi^S^X zf-V?~R&{eJM!?2*=L#;qweY)J{>eyu^^fIUOzL7wg8l5%i=O?YB+AuLUU8*|fiJ%? zm*ln!ZB`O7d`p99Ni!6M$qJgVnK<(9w*peySWk?A0((r&Ltb;8FwW0Y9b5r z-l*|OEi4O9LQNlBnTTJ2)zUv)@%MlEgvDlmyK?H;wtlM#(Rkc9U-zRa=FuH$`$W0SZ zkRzqFqo}?JRH$0)S9Llos{Zz{t>wGau}#15yCD=ZkaL)y{eio0U@G_;0J~w zDc()HEqd)rW%-`z+QF-B!ZRAu=VIS~>OkDICAZ5*7M%WkI$Jr5!+sa4w%=co(o($f zBLG#tN9jBI-LRKK1tN_`V<7r>rdu;2EWG^JJZ)?_TW}tZDcvjeSDEX@#G!^<3bq{J z4FJ?iQ#g{)z8x9c;sl7F%(2cu>&7S>8n_@yu%ZWd;#Qk70$}XI!8H+pUfn4%_?Q+A z@JSM&v)h-!$9KWbWcenx8gs{1CJ%`R?&5uMvO7$BZYt84_a&)Q319+p{pU|NRb8N; zdGUIfT*4&l*s&npchQ`xX=_DU*4&KhnOZj!@GNS$D&lxDr?UVxxP~tM_^inG{)5x2 zxzDv8_ivSm7%tVU$!y7dym>kIRJq}(7v&emlUYVKef$$O+uBWt)f7pbAD zou!|57RXXjGv9X!tsl(-iU~k3i{$J9PQj5C6=A?r2yk#D6L7SDlYmTM`ily(vyW`< zE_=L@DV$243*@kDFzcBEs$3t$7&RT-%qkSpA;xyAIXgdJQjR9)h#@Pi>5|o!3hqirq8_Bz0K#mtcm3pwrTVY5ep#2j&H zA=s~+)P`r3oxmzZt-T-`$Ub)kDgTTr=L#B_iNF9s;1&g4KqdI~4BP-Jz9_0|zu2Cp z^ZV{hTgQJ3wn3v<>^*w7c=eNtoe=1JR#lo zblJc^OCjY9{Vt+uF$@v4osiDTe(oSl{;9=AXv@Cekm=sj3Ie0tS0G3(3_9O-t6O+Q zm%tJ2&-^~@l??7Nzv@Gb2E z8@$Yxz_(v~;`i870z9-*19Mlm%S$09Dk0%+ z`0W~#8b`1&;9#At+N8r5`%{n#!*v!oqC#M5G|njCr0a+a;dzsnKBTT9k2=(%)|eIz zv|kS7TzDk=;b$ixbAxh;CNTI)CQqymJY>kHs{|%_1s|901N;eLO`tOg#au>#$B&2P%$hO(C8(yWv@*Bws zj8=wb+#qVG2&B1sz1*NvyDa8Pa2`)tgvlAd_2Wk0k}47nHjY^^QMvV)U*4J`cTr54w`M>Mi~ zpi4(oxJ}H)L5P;OxYB3o1w*36E>n$xnMy$kXTn5%-vA=opfd0vp%abof#v@fLeMVB> zhwKY)KyRzxynO?v*KRPzd0@DEv~YAf4JAIQzsBM35n>_puz(r7JPi7tkm}{t`mqfI zd^|VavuFf>&SC{MO0wWAkIqr)`3nP4MoutDh|>J7*3B(7TDiKr5HG(om};ca=cB-8 z8EDF=`ReX!WZ4prN55Oa6`lQ^gJuoLN7vl5Ca$CasztsYK~&@itw*&f7V~a7(>d9@ zKl92Olprlf6h#N?;t8-9%MxLY9=n%ftK*ev^uuW&92_+G1I%l=(5ta*Z!VsBDad$| zhA);_*Rt=_={m}^R{1_5c7CFlbuzD(Jo^Y&RJwzJ(iu1Tgbp}#Byv1c@7QRAmPiqV zqOV*9$_$;2tQv{R;$8Ad}H2zXZ+}+^=(3X&k&8 zu6140h&V`HeT^-AS6QB$!Ev zj3_PeLv;3(nH1t@5vgX{*f9tbiC&FJ+k~eU7S9I9%h_P5;l06r)Vm|EWu>P5yws*l zsqON9@;Mua*k8PTKlGu4!FB@c51Sg?Emu?sd}3P%CogacHIjVB7bSM5Fhd_kQ7(*JX;5&+ArS{!HcJ zm6*+-<+)J#djU*Ox1_!s&)C|vf1xaMPA`#)%FGgEDn^wiYlPQyO~(lje`)C)F`i~L zb(mphV?-B{Txdv~p3P+9;RaVg?y~uuI#&)pbkwhBZ4J?j{*pnFd`Psqe52*_aq#3> zJ;zC4x8UJ2zCG?`7wuia=(f4p?4MVmli5QU^DA--0y5K0ilN)!Z;^`|8RX z(kW_g-iv!g()mm4$%KmCA8`Ac*|5kQ|cGmrwB0PDG(Z;l-PCo|h=vZ_KZ zn(mMY_Bi9sriKPF1L79fH}0978Q)ozswJVh_rAPm&Vw?T{y6n^LS?QlU#HdCGNur9Futg$_uPH(VjdWo zZGPAW_mxNI6xsy~U5KRR**%Vk=~XogQkX{1ogPeoll_XQ(IZMPif}0NF0S^Rgny?b zI}CY4vh_*PGxw|m=RSNpGrpPd`F%?Sz{cG&*N(hYsLj!e@k3ri1F=j1iV@uSU|it< z!R6^MFna@Ex+)lEtnh!)J6vNS9pE{T9SE=RkiS2o$zMUHZDaG$KLVEKYkN^uV)0LJ zh~)cF>16|(n5!eYfnpZgW9&~LCpo~WRmOsHDa{#u>70Cao{X3DaCyfj)-=U|7<*~z zY&D=f6T2Mr(TGw^-L>~mz7cbuT>nTVjii}f=q8Zbu^x0P_Cr*tW#C!puhR5CuE3^C!P(^5ij{ei zlbch{O@kJ!sIqFz#t4ZpM2~m0M-8Q8$(oj&B{{A?O{69kw;7N>{JoU6kB)s| zZKY&`)401XE3-dwQ;k#|lDV1Q#2+-2Pd7d&Wv7{#EclR&e}w2J>B|Kq6uLBSV6$T} zH)im9_?FVi+kK7_VZ6UeTUI^4+aK-TGogzMoc9|<7>Fo z{uT~UTnkHbv-2PE7=^xPIF%uk?+W3qz>s`CT?xXBNfgk0PT<12a5U$Sf-xNDR3$14 zcmtoia2YU+H?Zoqs3f1Cd9e3V?#S5QL-^L+EWx21Gy1rekV{i9c}u%z)yFTj*KUq& zs2**PZB5w^YuwQEDzG}X;1!@qI9wJiC;$1|TAS{Nk&}h$We1hMx3t`;-OQT>trIt2 zKU@G7OjUd}1%=djc|R;)W#d_;trF9U=07#>N5KKAH8uif#!4=D`AW!m#J$?0E&qm~ z|7ZbT)F)|O9Gv8vyb;IjNuI{(7vUw7_sHGaOgv#a!TkisK^nZ``lF#O(MXJR7WNw8 z#M>gArU#67J+DZ}zCCVupl*ZsT5z@QW;p#coLs{5i?ChtaHA-mhQaa`^aTWr6E-~n zlo*bN@A!Mq;*d_PXkfG#g+n!4TF4UIe}Is359Gs-Doj$MfQ-81Vmt@dY~?PW$Kty# zh)Rc=-uLKM(xvcs@{HXVw5dy{%Xz=aENL6Fe0ELb(WXX}%oJaNuLEcGEyNF!s&C~q z5gyE;>hL*Z`~)csUu2tc)&wNkyO;j8v%-DYb5`Sxq;ThF^IlhYEBWNtz(Tl}(~GV4 z%2@xhk%)Qj!E6YZsJ6h`c)Xbkg}H|p4tX|*)S=O$FC}Oz=GjF zwUMbg9O!udu`1LzAN^?@0EXkJb6_#E3-=a|k}RR=N{xrdSC5+%%XHL%CpP74BGL2y z^f@IAMMB*Lm)AYCgdaBF4eE8;wI^l>@{Tol2dOxyqH0U+Yj2rRY zaPZja>ggZh+RQGo3d_I78&h5v5{% zRV3!}XpXaMQ$5&uJVrc_{L-k`-lxg3?!;GNIt?XY#|xR{s2f<5&uaYV$C*yzF^>I04NaZ7r8r-tbAp0m|;VVM#JbI?a>|dm<^7_*6=^Du!#oDbgF)?bPmm<2(g#%`9 zqFSVPf=w?Z74?h{4E#)+rT7_Ace^q=(Tp)=VRHtyb-l5q1!0`k*v0brLiS4i9p##$ zJ7aG+`M!B+dfrQ2ISX+3>;@h`X(yaT)&Ee89r9(|3-u5qFRP=_^##tW$=6wUj=r^Ab-*zM4h&mo0dSx;121I3__|Zt7y+3Ynt%2rEXm z+yg#h^S1vNFJs)^|&e7E}8NOkv5)#Mq->Fd71BT z{S{f))@F_G+r^OaOD#OqlpX7}U zbxYzQiztlA%|s~#2gN^?1XU?)M4bGr7W6PNv&5QGM2nlATVlZ#*uD6ho|FePm0a@Aq+pmB= zUanZ-(Ak4MvQ?wVT4Bwh|aUA+`{pQU@NHDAd zeq*rdeja1LLHA4Qe38%l&63HHK|#-w+?qea$+@x+JpNO&8P4g$OZH@3&%MfK&ZWc|mk|B6f&5HOKlRmS>-ex*6UZ45-0J zJRiGRyovwaXZt$JJ&1gH$a5;d;~ScH>+#{x(D%V#F$dnxJ|8=fhHK@!(2jaWJj1s` z(Y9}5)kF#4}-aYsi(T8MzjEed7u621YEHxQm-;-3jg4kH9v2zOqJi(*2eQP_lk zKI4Jo!)NHdSYjtiPx90?W(bx-??-x9r>Misz`|DDc(&WcCkblRlaf6}j;|+sZ4Q*p zqLvwGWS%d=tB^BjtE>i@>EEv0-zQIl@-68JOT+}_&04;m#HhDO1~BNH({>=cxYmt} zx$^HKH-m+y{9FtGmLUG~SUt=~7RVbAH@U6E=SZc3ZK~!sqVOO0uy}SEcyui+cwa`2 z%Jh=bPjixR=S$GByHjC2sM|jdbA{%A{{E9s&2|4l0un*chY4%P;d|L6N2`iA(U@mm zsjBU3YniOpkglITJzHU?ozQV7MxH(^v@Nw**zG5A+C_dl zD+LpK4wyX4(x7*Q1O#CBa5=0{p*ZGj@|o!xOUC|Et;%Tgg#AHH4Ehnas7Q~f;%#tZ zlF@I9bpBE54#<@vvrFb$1fp)DzN87$9<~n?>k&-3_iPZ0zi-YfecP#%ZLQD*Y?&F= zXTM4JkaK^95->!>#sc_!%FiXz63L8RL2`UT>z{C?wjP%#;~E1~2ybo@Sx^2H=d()|ps-DD{$)ffrj3{5+y-{t{e|+-^{orc!u@~Rk z?o4mk{^*CBiBe}`vz^U1Mi<7mbg`Se-kMn3bgU(XCpkG+@Obl{q*N+NVSi2#`6t`8 zf-YY5n6RmfpGTvg&61akNlSlaTM_`WaRE>Xu`-+C+PfNOqfhaU4;G4MGxjXHLy>b| zfoqarV=Yk+P!9qpAfE{c>jiVOIgql08z6vATd;1s1!5_vP!F&qxkv++?+juFD{1pG zm0wLx#u-EbiPTAs3=&~>CbCPulPlOV%g*^7KYLiGc^p^8{0KanGCFvO|*E-Db#I|d<2Zr$)Gy(vM& zc?A0>sX_z#;@~cZ&u9M)=;t~#WF*k|d*Eos6{LaSloH%3*1l^K1-dBGz7ZIoOv;?2 zvdQ6;(wA+sip>F}L6N|e_3!U&dX*57ey9Mm#VY@F#4qY-^BV%FgREU9K9|_va z)QNGIzUH0w2vTe0%6%W^PU{+NF+MtGPptHG;hv-15S6^0+ZB%QGwIE!@%pew2_aD??}FpNeFGb1voRw)iXD!Q~(>fMxO?!1g!+ z%)B`Ua}XePV@j|C!$dDu0E~suWGFKj)4$;RK@X3^y0{$TT3p`FdS-{X zW&8=_zFBUSxnj(mYvLvvM$z6X+vPVg)_2hSjfz7KSu||T$s85F*xJ&`&Lu!nX+`nK zfbO=|qcpiJe^oE6={k{%#7&Flmo%T~@)Dm;=`hEfSoXesbCrlMJl{vAvogA82uDdo zqgD57y0uF#KT3{NfsLW+QD?&q8BG@~{FTBY+e#Yqmhk(R2G-%T&{X@?Fm{mVyf{j< zK-br(len?C(;BAdTGtS*aNpT1dA|6RWLG^3P(WjR^L5EwrRd-8Id(kRP2oeO>;jn` z3Tp{v$v1w(q9yB>TEk%1@xmF1{+ze}q!d8wzm6Og`G0vZiUmv`vBzVIUgb>O4$Ig7 zQa3#g6+~NcWu92=<-6tKrjunN%`J&OQ7CE>`j5O}nS%p62em)1k*FDSOHgI*1&&Z} z2fCwsYbl#MDRLq-8Q1oI+xyXEm6&7_U2OPcoU0aFerXe8@FSJqs#S@KbJnCJ+5W4f zloHg@H;0&CMl2B_(*K>-PCQt?ukv83@M-d}(&b}&O%LkZq%Zu9 zHILqg+uKfUbQIuYnBhmswXI=inqz7Q-11o@q(mbybj5MJ) z#t{iQ-lMoRWwHB9D)y(zmYbSJzq?;+{nlkc3hR87WR!gUXO_@pQKi`wZ3<=G5Z;mB*wTfzuOlzWUCFsGL6$r*5U`DX>s+DXnsg2q|EDzst z#y8RI&AmYHG6%{CFSi>3+^g-y%(kvvQrrf#4KIF;8#rT2AH(564%|2GZRLvB(3n_d zGyC4^{KeYsHu*}T(7xDpy zU_1iXG730Kl!V-?n*6RB9?ugAE8H~QKfc_@wL|7X^tV6_K>xb-d90TEG8avWTj~y z8jECl?&`9|nN*DY(b2qS3|7Y*X^Cy=qhiVRTHh%>}&~ z&MjKnUFhO~2ipp%U0;77v@rvmgRuhQG?y1PKUZC-elFPDh1{iY%<*X%|HcslO8qMS zre=WF>=*$wEEZ7V3i+=Tfze+5RGNSU?+Om$)9}bCC4G2uLs-O+n8B$0CA9Ue%T#MZ`ZGkj-s@p5DjVr&%)fJ6Z ze#oloF^+dAh!c}mrpK@3mZvAC%+M17xXntn@Xzut65J!l#!$;`M>&w9lnjp9UpnE$zn zl8ZX=XJ6|NDUgcYUV1p}1Bx5<7Fbg#GE8LKQ2yo_%ydn_-H)a|1m1ep!nS*EX;ed+ zO8^Yv|KgeR;Dnm|Ye2vkP?`hkT#N{x^g*SoBJd%iIPk+8DCE^E1yX?aR=g_@_oLYI zKVq_DPBhBWh4E{`zU$84?r_|4y5=QR>seQcN!~R7@-|rQl7-KJanVUz>&0Qup22D= zJ=U`E)@kvWTw}eg6lPxqUXzlY+CkrELvhzsc$pV{eP7}FeGW)S=qQ(imHmoekQ3!_ z^@VWeG)(X-r7?32uv4lT9V#q(eAK_3*HWeP!g|N^^Ag+D@d!1i&e7_S@uMv{nEyi9 z<1s3exU-VFc_zX^$#jCMKM7cOsDg#?9}0U)fhS{!lXGyy)F9;Fk7(CwCO-?fr5PIj z#m~2eieRoJf^i=>_Z$B&a`7ktei4W}+IETmOgUK@>#TAmxFrbTv3jrd1}0PE6nlf< zhnh{YOCK1Xn-j7W3RQkg)W-sGIxZ2%a_(uhgGC?nGl2uPc1nIl>WrnIn9_E|INL&d z=FNj)5$&9&eCg&Z(ro%G)_p6f6Q^qnj*fksx2IkdT`gf-bHKYel?|>ZIZI^1d})_F zv-jA;y&(_FApIxM@nU(dEkET}YSWao_lo2vZ9zjc@wCL@ybm)Y(uS}VuMl*5;MK6~ z{vtk(`SMgrAN517Tq3B|Uf!8sl-}4N4BKLc@P@~*crPiL?!it z?QmR#IhEWSqiet(YExCY#D?W+!@-0sQ3KRphxCpP_nV0|w7+%%(al`%OXV^Hf$K51 zZxva;y%YK53Kv%yQM)|Znni*r|2SX$&23U%fqo6yg%#yyL%eLit7N*hRb{BroCYMv zU^-)^Z>vD524~(m&{yZZ(67Jbbic3hAmT1hljpbzn=*%~QPS_)$3n@kVIZv2!}5h znEt>&yza!~XTq>kX9V6k#Vh7j9Qc_%X48S=+_|-bL3QrG`ajZ!r<$GaA8$}g*z+j`U!|qZ)^00U_-UKq; zGnY{JJ?Pjzp=sz5JuK0R%5v(7MTO?9rHLbx%vEE5kt67*f*JO>>`bHDWRIAdly46r z25E^4*SSi$^tc0HwBMe$Tm<^{Qd`JO2H&_F3eNVeOKwQMxw%XEh%B}mD*}{Dj0cqI z>O0H2GW?tu#Yx)&MxS7vId^b+>}lGD(P>_*X|eP&nvAu#~3+Zp?q# z#{YCcnFNA@I-}pN$CXfT$Mvn5M3<5sxsOp#kB(xWdncHz+aI9kpIN3*D5pRw=|=9y zND{MZ3qJv`1UZXmL?&AkUozA2(gLN{lwKQX$ms=S*FnaeodWnq`P4OGt?5GbuE6YG5s2xK)0O{~SVsYW zGs@baf9DCvAB&@^RkCkN=`zFD#+`ck9Pg2Kh2KMIFa6=6mv4&$E~mZ!Rp0pi z!(=5f&-Ht)$%j9Z6DGYk5pMmv+E1SF3@ZCHJ;L@1Lf#1q@XC3U(mN_&B5qp{l&U8J zFMI;;FV^AwwzQg4$)K{#nUjbYBzmg9?_*^zQP_{(GfXB9$PK94qZgMkGprcs1A7VA z;}5&(*0OSYy!R`2sFuXr4vcZA-jQoSFPe)cG>Q+U&FK4>%;CWTI^j5QcjmMR#HUu^ z?V#x$Pv);mo#R({`FW8bNB$;3Jd*GQZ}O+H)%1>|P#$h@hg{QaN?5(%1>zTD zmWX{&mSucc`{Eq3GNA-;^0rrJQMHUWn3Yor_m_&Lb=Ibmd>l}HF;l}*z{k(?9?@Gf zjh}=26>M(?qVQTU5B{9wl6Opdm~}3#oJ6T^$@}2ZYSf%Z*Hs`zxsras@G_%**!~Df z;v3*vMQv7g6oKWT#t{ka6XM__u`3>F2tK0>k4ynduK#EOq;7pD>7!Y8@YI=xEV$V< zze>emxh2Bk_zyVGNT@q0ptXJ6sTx2Q9?MSb{s#E<4lLS%^9QCEq5za=5Af*v-_=0s ze+LUB$Xc+W0XDd^3VbDG{j@skjtj|%^`rM%V$s^xywbg;BHIt0vd@~c+QJ!+zW~qw z+kuOAq8#pREc_5cwdx!LeTY=q`(ARk%@z4OrKNEZlQ_OBR#J8HEN&%_TM8|Ozu&$$ ztwWyQHDZ6I-$me)caQ@AvPn)@+T^p(&`>(AFDnXUx7WaS2j1pDSUOyTVfJz^HDu(t zBIYeEt;$fx-D=htF> zuEQ->5M&adR1p30dEW)QKcHeZi~&?hKSTiaPClTN zw(}ATU?qs^1%%N$kF?UH*Vx$PLYc-lJBkxU^hIh*@;T|Ma(?Db)cS*$zTS?5{Dd`D zYbqCamT4+$t|lRxm@*9~;_ps%U-sWdw#00ES8HkN zqdv|UKg~}FZa+45U!kDukPnOLB?bmR3-{I0ttJi;|M%i ztgFcmNyAkgi2FR?>|_E&WVvfWEE&v>1p;s@DgGL}4sD>OOfQj)@_luuUHNA63lMoM z`E)yr6@^IFJ$#j%fpFtIV+PG(2W$g~P|5-S27dIi2}-@b>9)w;pnQa6Ucq=42S|asd(fl3 zcFQh#j)$i)0XfN)%fQQvzaI#smwAce1m#3DsrO1oW+L~S+2-p7Al`YP8l0ba^Ng_Y zICW67E9%Pc+5k@Y$WgHwp_C>B7O!v_B8k4KQ`OQ0Q#+O~ZhH%zj|8eeW+3nE^xi(O zrvWCjeq8oKfLA4A&dGWt_@c!@b)hIYta2v6inj-N0*cokgTH8iX4q%42V6_xCQ4y@ ztt^UH?f|GBWO;Mu$}WOKiM+b$wCd%XhGh-s7x8Ag^UfVMeUs!vk;vL?Zb5xey1xKU#zkl%)CeVC; zH%F7+Vp-d9mIOlyl=HhMLPX58{BNx((2GekMP2^3r|r7)SuOkQ<@T1ZRpiKn^?qgd zxH}wiIq!gM3*^a?RfHSF1w4~n!3?Y?AF4ARE1KVQW^_DdLus><_6 zBwIaD_S&?9b+2XO%H~9AUMF5*Y zZesN}o^1MsL|AQMCk&~5IBk7sscxPXWxU>ApOPN1VpVA{_C;wodf+plD z@R0UN{g@;%E&?)Zmp++~8S@t`Q!Fa&S z*{vV9h|A90YZng%zyC&Gz0J7sr>?jBDG}w)Q{N(Xo#r9A>g~*g zD-jp>zn{qc*-4Lw#7Yx7GbY>8TBHe_7KGN9+*6A~sA|HO88;(EDq!xsj}1Elj?PLP zEK*~Dga7RdJkRB)^{J7W$>-Ib#X-NalcQPxj9aq574er|xczyq;+e0j@_OTP-ht7= z(|az5Z`9iQtm}uGgQ95ZRLJEnEBc9Rzpk{#8EBS5)9#h$FrG%X2oa*$3Y`Y3ZwN2B z`-Iz-V$V*E{InLXg3G|zp8-NrfZNXyTrMkK_xIq?BA0bQ@&q0S{$CFu9)GJF#N(VK zXV{I-UxOd1G~1P){wb;sULihEcC@~;MO)8LB+pYe$ZjXztdkYU=v#BvNoXAA_Z%Qr zzbMDz^SRk_c&(58ZZe>|K=R1}z98BzMtOAAsZD!<5->$WkMn;e)1v?*-zO-xq+91z zxNfWixK2pZ1p!3D0)HU$ z4Ov4fu0p=4#LSmTIYA|Zr@U0T9@9*E-%I#Uq#_0zZrPmO#5eYE*r2(dn4hUyzwny3 zHde~{3J8O)J;=)h>G@=%Yx5rIe-cQA z3nr5J)_cR_=;Yq?MeXk=EWHtu}<#}*?$VUs;!42TD^8ft>#mjp3Hnh}}dV*Jg$@97Ec6fUz0`Sml z+fx-XALRcfnt8NmXO#o_*`Hss=kZu-R{TV1o9&I=&sI;IuL7-{Xlr>gf>?^*gPL8) zx{F+^x5{0mIw95$Y}}B$li{NNEGF9_dDuFuSHn;U3W!K%jR*} z!TMjLbdt%o3muWc!Cwp3uAMCWxh4F(#QNgFEEOI#6!jM>!EGs7!6-`uq7e{9MM*vf z(UT&Gr9gmntLHO#iqR1WVHB|ic%-CQmnAmlGGVwuc{dvCvJ_ALVB^toyW~MbB&?p- zWDB;OVFJ-gzD4$hS5j)xPQ2Z2bTd8>dB8T3Q&HRd1p;=bkTYL74iJc?S!@9`}zQ zzSYJm;)-$&(MUGxf;;Ozh!T@@eZQ17WtO5}~cc_IA{C^CHE@d6$tBcaIKsrY$wg0gF4`8BLU2NTc}1FDy?- zhrih&Hz3SsyMUK*m~*h;=?u8z+H0c4-$qXne8djkCC#cLNQ5a{sAO}*CW&{$Ul%Rz zERBoAlNxj&|HwRi`e6r;2} z;mnjoiFcG6Ggnf~=(HjXlEaDR;NiQeg>2;ecXRKqx%Q1ph1^y44<^dVk>&>pN`5&l zMbe=?1jr`!yQ7f}Z8BYR?6y|HP>s)J-HlSJ%UL0w6|stRP&5aR3T3$Dy!PQC58>>B z0dzOZlarPZ{bg~K@)jA`*|aL59XyW)IR5oyw+LYN83uOW06`)1F;RG4Fns)VY#>^K zwxs~ZP`R{0kKbXQVzd4=jIMV*tOgk>_=;ynEvGc~h4ilqzqG~N@O86y?Gx98&?iSg z8*ik!j0`H;+Wo#RqZ_VI9y=pz5@o4(bg&|*!GF3Qp~UiHvt5GQnWiFqk*!0X#v}dz z(Dl|)QFdM2@X*~L4FW1E-OYf62olmgAkqyY?GOq`BPER>(%m2op&;GeB_-W3%=KN| z_wzjO`+aMD|FBrs46N&%v-fZBv*Wj)>}`FPNtX8Z<{09Z{Qksxq)$#}Q3nbocpIZc z`Z^%t@^uBx1C6Vme9IA=FrlGsi4lAh4|89{p&oFt*w^{KJMklh`Gj5sfWZ>tC!WY% zJPBnmWuH^DxozR}B_TkzLxe6vBN5T=H%jN!pg&jz^5qQB0BHY{?f*v2q5$XLKzL05 z@ApqRblKD-WbBmU;i;F2QY`hR6G_E(UGvlymeeMDQ;(>9iO&@9WK7PdtwbK~w&;=% zJ2ZTjKPgt{!fQ#V<}}dp7ZU3VdoI2s5we$u=+m_m!2=npI(_fzQHEt&d?2T@i!>zp zv@Cd4AeSCL2PG?mR5k5ip(j7p4^Fjqk#SM^kKB2Zy#Y% zh)zMN&j$A{VX;97jJQt8p|CiXU%Y1Lzj(K;HB+gUI4(0nEZZ>SN(@B=BP7@X6U z&&&b&h6~$akJn07I{ba6qdoXFZDzh;pCp{Ko79ydH|bEPI5K#D<(m+S#slwaE-xyV zjspkc-dcb_4fa8Ri7t{gu=VVpP5D2v0P6u^n|8-nggs9xIY8~5cei;{?AEV0#76><&#>y_l{5(w@_OcMl zu3K*fIy+gh4&ksUJi>WXJ)xSV^)>I@=vTonQzc9{%w!i!t89Tv+OcT@l>Rd892)ms zY_FcBVKD}}%f1Gd&?gn$p63g1?*6QO8{vHDeOCG#@lmUXxYm!{EYb7 zd@z$esFRN;M@_fLy{Fukz^=mh0{!pqB#c zWVJF`mfuIcD*odv!ig^|%(y@F1UeMI#g}g)q@-_qmFKUd61r=NXlY?c?e$cmo7!Pn zo_}IpJkj$L!v88EQjLJ4zWy)R-taDNy$kz*&v?^lk~8iU~i!GULx?8lNLkUvUdMqJj4Ks)TUQUn5(WWWYf zLsL<-a`Lwnqa8lw3xh}NoH6_4%ohzv`uu+l2ACky8vLhZ9>7G^PaSJPM zpN?GW8BP=xzZOcK7z3Pa;{$%bkhz8fw=hmDyF?s%EdERD9mwl9Qm47PpTjgKvnB_t z$q4OwT#N18Rq8&OrrWiQlFp!c;91v)zDZxLNZn3U74M1Tyjl3%oDqcPM$D2?kxRQ( zhbUERxU&?n?B;&2_z+DV7>qet`_>XM&upy=aaHfd!5V3*YKm)xpuB zQbpL~WpM^-(K(u@`TsD{ffWWfT|gZw11xQhv{TVr1FFjIqSo}vVBPS)05h}(kMbRf z!4-Q|pudCiFAf2RIA^_mh?ubU5^Eq@bg)_UlPqIb<~p&wB8?Slvya0xK_x|2l++(I z#x-Ik{Y?D*N_zVv?XsZ9@cO}ync{0DBJ_mrHlpwSeoBwfHG$RN>+6E|un?-z%4;n0 zpmAH>O!t_oEGXME#ZGs`%@OQk{FoVA)`PoDv(kc5-Ocb!IiSh50{Sea8 zu1x;U%0hK22GO5(+dP^bQ|;b(O8teUTx;KU*BQRQ)g&FQGE>|8vtlFT!;Tz-7p>8( zsN*KW=KUa|dlDU->;|u9hjK#U6WXo9c~H7>rt8q3WT>a&M*8ggzZQd9+!M%ee&B0I zv1+6AL8qA%PW0RumJf!WL(`VPR$ag&tT4M}^^E&na`F(2>mS7P`X;ux<+-7z;+oy5)_qQUrnt2C+m zSnNT4R^v_^M<&UEZ@~-#u#UyzBLx4X+{{TH*2N!EQaR4~hrNB50w_8e3b_4X7tKo8 zq1Vge#2>2l{R6?gb6@{3*7|4Cxlwt^h0#XHp>{EVH1L}EzoZr*d{=U54qm}P_{r)+ z17!{O6w5PgAK3}J9S@J#$TQ)t84`>PxXA`4*NI^hwLHAknkilf~>|Qy<+1J8T z%&MrWcDSl%HQz1m1wtXMB|5qxr!V$|P%htO4;HgnM)~A^3@%2tphVkmVvtgX3bM<0_tr)zRK$Rdv@jD|VGuJJG z^v)>RRp3<+*o%%fUuF}EHm zN1d_twWmwq{HUTog`^#O>`vqXAL?qcC_NNUFwOf)0tKs5l#I_O8b!(1=5@(k;*b_D z^Z|u-@C27eN7}49(q}zoQ)&eaBPAz)Zq}Y3JIE-tN2Kr#3H(!5As9b$E@!J49Q!vl ziI@k&({#2dGqG&D$~?os>@fU(XQ#mfhho_9po!r^HL)c#{(XMr%i63cQF+bCH zJ!t+vO7vf!K8qpx2mz9INJ_2&*^3BpkR(t>PN2DO*0JosmPljpdEGf93Y3%-F|Y$WcE{4vrA~kPd2(GB zM=yIGEb}ux%pct-oeh1rG5UF?yE_*@AXS!m>p&?~z=LKYGh*Hew~4Y=uR~kp)**cT zzTW4On3&KvO|;7eD(w;YrPQUbhYDSbh-e{VGx=t;+2bfkQ(uxg6jN=r{N2?hH!?Zl zKF))T&?8U&2)T%Mo};Yqcro1%eB~b?ldDxWPnqZoP-GRz<{ifWs0{n5&o6w{-e# zuA~M*7h;Y!N@TddF`7_bf1s`M&Yd%GYAjxDa-b$>y!mZb^+>d_yIud&$3dC+MOSXD z&t4vc+OLl1J*@D7?FxibWPR?7=I}7d%bg=Ye=7E+k#auyfjbykcQNHZYJy^Ny(bZ1`Fjvt&r_z{HU(6q?7e41~!y?2!!il|*bXkA!MOXX{a;P^R^{grGsoL_8#3cnD zYCEAgALgD-7V|=3cgR+5#S=_}->vM9kSP!Ke3uT8FrmGpnm{br=GOhQ1$WEV8K_@| z?xnZBEGA)-N+P-L#5%Cl)N)C776Qo?7=LyPK24d|l$H>BaKzrnmPNZpF==20)4~=# zM%gON7y3SC6q-0PW*^?-*XLHme5ITuP0JJdP@>4}-YAMV_tDhG7@gqT#*1zX^tLdT zj8)0S^`^fsHb-)PT$WvnZC>ASYac&F+KZ5;Q=n`kzfB?Z=c6v|53OZ{Y5qtsp{Vov zfP+rNUMI+T^!ezH`)H}q3JIlLgXga`{hJj1XNlBnV0W5(nQXg2V~~S#fLaZKQZ65>xDR1_^VsXS2f~9 zn-L7)=xb!M*t?8I_6Jm&QU=eEUN6a&_NV91J1%K|gQoc}JFGL}Bs;0h51Otp6O8H`W(nCreunWIf)i(z&0qi(x z32LjO)2B>#aa7RL1?hbdUvjJ;kkgNcQ(YKfKMj`J&ii1zTLq^OQcS?ZniAQOtxK-& zb-X>@(e>#mwM?* zHfRw2>t95`JFDf$`A-P9*Lo2jpaN{)D4K|=ejHa1_r-D0pJo08_;m80ZYUNa)5&J> zVpTVNRW)*lnn6bm%64ZjO~D5=011xeKa>+{Q~%dp2lxtR1!tK={x;FX?=y;iJBXJ{ zg$Ta5p}5qeJ(T6H`J$?%c(617`r1h-4^r=y$`M3>a!3~NyD7?5!x&|B?tifEpr>O&UkDlJlM1(E66vr+aWzB~0h z)u2coigRKK`_2f$zx{`$lmyJD*n)}Yup<}&*mnRXW)*0`&w*Mb^GN&&`-q(--0A(9 zj>_I+l&Yp(K6ia+HD~jqR{V>m$pm^wC+7U#o%JR151Q^XEBxg9=e!za6vo95lQ0A5 zvkWs)5?{8lWvuyg7w(O}#2C(NO+Rr_L;p%1S=L`f7>4}?Y<1CG7Z&~UxrGJOTSHY^ z>^i_-?GUb17bL%zrt}3$ao?2$r7EaTWnj!cqdg&(d}y5_krQ=Gn0boFdQ|NWwwgc_ zWjvFOxV@^<6>a*?nIW1nZKrp&JuwNQg*8WrCqN{~HZ}ng9tCv)DqLI6YXF#Dj{?|U zBb|G}QwID!B7w$b=HGz-FGHmFbh2Pzi?U|aWclC5Z`W53%n+yJ&5tb>tWMo(m#Vhc z^ecFk9*%S6dp4YS=Q z{Tfp&dC7kBd&{n@vYy+Zc}Qp|o1sCvg?t!UT(MSkl}Tn;l{aB-&q{ph-^PBkn4z_D zahJ{6CNuYrdw2(;it@irS)%7zZ4rNg$ZyyAhxzNd)_<$8&~*UkWSXGZvn@|Ep@4}0 zIWM5xexU(8Zw$ch?m{~x^s#4EVtpITgBMi}BBZtuiW%(SR1OBbrH0lJ`wuqD`D z5|D=VD(l;Z7TrueWQR=k_D+ZwHYYm3R85Vw|1>ahNgu>y;)a!2z8L+k9wv$wg7Z5v z(N$56MRSBSXNV9FQ}e<-^Qgz|IvQ-w)wkWvSDX{2CVeK;kJg&5mUy9S7IH$oZsTXW z$MiNh@|GONn_yl9oAQ$k28CdyL}^4ey-G9_`D!GQ#b z4-iW-e1>mVt&t(0ocZ<@s^83(_A*>NP7ibbfT%G?F8#0uD-8uu&dGNkZ%jB1U_Ve< z-f#qfl@tHbSfK9;c*`-hqhXobAi92TmlZGENE_ND^7B*u^}@TOOJoXT`otX!2@c% z?R|Gf$l->9OE#G3EXHk1d2O>PoAYs*7?Id0HI6ev%n8r93p8(PFa)*Lc}Jl5Z%*P4 zm2&R%^S==nSQ}t&aM8nAN52;Nr~LB>jcSWHOIRByr~(y@y!_$r>iE> z$=g*`??L8P%v#ZNlax<_?-X0^tH%fKj%ex-O;2M~=vMH(rV{TB239sj^Gf7N2z{_bh33KtIBX&Xr)_c>(I6ow z(zPG&0d>3qH4e>HuJ79f@&`V|!RUXtlCcdgm#>M7+|+BH+s=dt{wfv$Ynl)=cR7N) zF2O0GNFXoQ^X?h=1wK@{J=hEX{NMwK+IfG+!1VkSFDg0OG!W`S$YPzAGa|biS){q) zpO$KbC(Tto$Y=Mup`}R~;$+G0L3&o9)96VxA&i2bFG~IW{H=rn*+S;s+Eg=fVMq6^ zxly1XIG|V3_y?q;EGi(lWbW@{36jCcHMT+VlgNGU=G}(DwXM~UCdt;5eaoGqeLLdW z%Y>p4Vd8FNANK2Hxfg~7DTkAbTD3hqboBgbkM@~edw$RL^t&IY$8Sm;lxJSIo^13) zMn=MrtgK63Yf+;xM;cu`3$|geC+%MtFwLBuNs<=I#3p_0o6f1v_!P;r{duRSz4`~- zDkhsLaKoyhz06kj=8;i>Z``wZN`;8`_S&m%q~{}*So-GcmLQ+Q8DDd9hb4wH<6e0( znib5gX-_L$#YDYYdUSt<*-V6%bl;$*oLzc5M+F%wVaWV@!UGe(%aGTC6lnjI&Xv@~ zFO=PaS@?EP`;z)r?}X<%i(mvW4nysVQQYE$p%j3zRoE$P0I>zPo8$IF9t+Kqmw3s8x4(0 z$lbsK{rllWw_jVNV%;XsXB@Ee66!mI_mt*c%fpXqiNk>ixI$}=LaNE3ZoR)q>`llg z+%E(C^_?+X7ySKY)xVLP+AH@`7kyJ*s(FfE_`0G(ll5&h=p;~(snO;^u$jZ=Lz|N) zU$^B5AJHl^7BDxC8A&t(_c^eAc1kh=gx|kbKaf%lL$O@L$mD_TmVCSss64v?#_#zL{=A7O1aT~lXs zp|1OV`~eXAl8BzRNY1hSFSVUcDu+V%1<`fBYPr?Ww-cG{^4?I?rL!-MXlor+Vke~W z*>U$P^tm3*YD)6d&P$6m5bI4STpq-i&N|3a0OLLI9}k-iSWAT>`8uzd4OUdtSV%(Qu}f0do8Xs!tll- zqide{vOBM?dp}TvZUjOzkJ0Qb{XUQ@;(b(GI6dT@7+zVe;qJ37(>6?Nyt>JIhWiAp z%-^aJ!#gU?zS@V(w=ZywL?IzwYdOR$MkaMKpJeKo_UZCM}FVsK) ziUN!mF;m53o#&uH@!Y?LG2{SLGN%aLFcfv@795N8wwx*l_ywK=nml-Kal3}8GCmRw zhUps)^(&a)Fi?Iy4VlaR(rLnLcuqmmHbBv=RC(I+D8b}vej`iFZB=2P^H!jKPTfbq zE%BAF$gJf4-!TuIun7HfGww|9 zmC-&KbVt$Qs2nY&DKXb1R!9Oa$W8D4pmE}jr3)DXEco7UizT3zlbGgCet?Ag*UkeL zzuDyhi)W|MhhZqA6PjbZ5#S5ytvX%~Few@02R?r!4`_90+-hxjUd?|UqAnXT6rsQR zl8ZLsW8nnVAVk#HTx9nt%426EE?`1mnU=UdPlP)qJ)* zOwBd&%fQCp;c4#&Qu&@JMqLY~J}kr9k5^Mo2}_6mXIc%@J1b)iXqND#<4rK&jEWQ9#GKq)TnMFz~>Uh z!1)iC&U`0*wW#Vde!S;Oaj<*Rf3Mb@I*e&ZZZ?M!6>Dj6Lo?iAVO^mMz5I{)_7zV24Wqunz#2zXZa>eQ*ozmcL*9&wlV+Zmy4e z_YjtnfP>NYJ5AnOC9~suI90sIZ{>0iUTL^(s^EKphxuk(RuMq*Li!5>qBcpC5I!ac z_Js|P^;K#ohm~1G8a>{>qrXM+irS>@3h+=IZs19oiIk} zBl$DjH!8M!z6nyFGO1z6G87fzA;T!fkOqiu(Zm3ezeVhbkiq6e-Pg`y{QxHH zmMhOs&r$8Xlj5G%f(LdJ=QIS>ONi7U2n{eVgtBncZY|&n&Vh%aHkV$VF1>vxAP<#Ts^OEQL-jKIWRtW)bPki?jZk6E!0$g1m?N zR8W9%a=dw!g@uX=JeD=qS`41Z`rVij(+zDuaz-ndOc(aR+FfN@G-=8JSZrlavrrGO zdEo5VS-y#&d}O`n0L7)8;h+7uQy-lB*I)>a&gjOB30N_m6gL$$)|?M$QHV`3_h-bL z6zh)XC^eh5KiMIAf)gwex1`Ypqu3wwc{p*BP@A<#lCJ+TtvW50d`d=&Ej%mbYmIwK zt+ba_SZ?eunW)ZqoKbcbeMF-8vXy0mCaUq4@Z}2!O0L#l(Y%AIQyu8vMe{u~KV$#8 zH5n|N#1B0`Pd|*ZC9}%P=gy>csV115oxak3<%BzG!GV2sT*DBB=)y4}IwIyT#YvQD zTSbNz&t2h^Za)8+HTZo2~|DZ<%Dvbr)lH{0DnjApW{9k~P2ZT4^-k1ka(snPo_XVo$)0>aY zF<fa;rFQYp;qJi& zVMFuc8N1pBz0c}{p8K_R*+C1lDD7BtBbz*JN@*Q>F3%j5&LQ$V-PJCKkM2P#1rqw= z&#zK~%+6p*pH7+j2Z_A?SeMKeb+XtdeGR9uE}pg%EL zSz3yTIPs!I*=Hbb>=Kdm77LL&2$Z`}!9ucy#vD1IG@n1!4?0Rwq_^xB_x^#4JNURm z&j?g<;1H)Px;CMy22AaTYjR9@S z6(*tW=?K{fxzU$$y$t1@%B$xcz#?H6P7>o^UBpw;tBgU>cTEpbl}sQG&*5-|1vhtS zM!l*8IOA*;S8l1jFU}vJ2iCatHEA74sFiQVZmhENK_-^bQhBLIvsasIh|z!XuXJgD zmgIDToKD(>3(=QipVkI4kbS(!dS+wAhV_@u+JbP}$YL`{1<~OMp-e(uJH&K2B>lSK z!-;r*BPHsQS5oysZ06gr?PD9}Eq+P*WcxYIM5#w>WBvS_28DjKMr+1_DQO(0)=j7j zO{+ISX;Md%@I8#y?`4aG^%+fbM8(h75WIkZC*ut*qsZR0Pt4vj^ylp%a_$2hXcWh& z)y2G34}y;X*>7*1N1%^D31B9@#mIrn{NK0;oNr}i+~(iIa24$s-S61i<^THQNMxQz zw5OH|$_{;XV+@@<<%%oz<%Sl@dP`%|L$nC$-3!;f(uX^<>y&x%2}Ii)eci=WzCOj| zs9;^PsZCW$Blz(YWwtR;qnKnl$Tdw|ZYCEoRLe05%`f(n=e`$sBW;`QQ{%ZO;x=T1 ze2IRQa_^Waxy$hH6X@88X1a-f-41W_UMsB{sq(A5xC_?PYSzEjcnzgyUF%uHeKH_# z6QS2_X(Sw8cx053d}&Q!VN5y~rHX!eld6cq5dIAWbkm@Zz&|Ve$43bL=g>Wu{#2>sO3IJ&?NO)qdX81OI{K_pVn~RL$SC-fjz5P9MK;zpt3@4&i zOM*P@`Tf)xgH39s8mg~V!GV5I&m4=c_n8t$Bqb14Bq4TQ6#r{>9hda*8QS+_O|QhQ zZBhPf%;NqDV+;fv>x!!goOz4J5P>20^+t}1`7e1mw0&(qX;Yp8Z9Z4jw>-z7`)W>l zn|udh|Fd)dDz?Z@78?FyQDT}Ka^^gvTA-aCpdspl((fqFLO5>%I%V+iP9#mJg(2T1 z<{syCPzjP&4C)4G;PO*F%u7$sV>+f@!w`;Lc<`Qna>m_fJOUDP)_+a zDe$-6bnDx<8Qp`+zALK=e>cTs+7=!DSV?hOz~RvSh9AG(`)`_SN%F2EBahL;e&|sg zd*tFS8%SG=p&F&);wt!2zVnSgp#}Z$ObJyYa2hpQqneXAGUm)|4_wd*=QYnU+x3zl zU?HV1ArEXwMxY{)VJMLSK%ZoicmysslmoCra{$#7=wxuM+$n7EWwF<}WD3{$h~O9GEgE*l2+zkydRLqRVU6dvMP|2=Dzf-F zAAQQSa}ahOBH1DCftL=%f5#4;5aJOMLnU+z^AdfY(;knznDxJ_KI)dh;C9rUmJpP~ zbt+!zHHQvWX3^VNy-C?mGZ!%$ar?3D?lVjiufO2`iv&N*{h%Q-L(YN^3eP|~|2QJi zM*~o;gI)Wpk3sj*ejPeQlu(rkANpI=`^yuxK`Z7Ea_6huogs`5Tz7B|@Dy}r{`-vj zRwRf3wScvkLa5N)KVsJZ_cfz1J@6;LUOM4qB%!zpt)lw#hi(EUxTQHoBcrp-$2^9` zXQ@pO-mwl?c3Udk@2aX5G5Kt)&Mt{Xnqgs~P{5}D-eh^$rOfwHX@dKWi7t{&aQIBn zL@vYEHNhkYCukYn;o7X+*VlKD&M9K^kz2K_uF-m9JL>)ZyY^R44cAp>c8?m1m5%2d zjgnt8LTV9dPMOC`3zrAt0QaOE9Ob@#gZ-^w8t)0s{PPcdx|hzXTA=s70;iD&BnCm7 zR1eDWfiUQ{*jY)WqzDgF}WaFJBMa@p1k zXx-=2L%#G0SdAIQ@hqi|GJ=_?bDC~oF-N`+jO1q#oK~6MC{4BEtdc65nDR7M) zUw1Xcnk(}c7sWeSA%b95GTA2`4#M=VE%1wuZ5B_~B_&#W2x-lz!iEW?tDF3brNC5@ zk&zgi1L2w#MuMi&iB$%WB0`c!H6H*s6Qv2^OE7go13q`9X4V7b%ijVDk=9osE5>jE1dWG(+j1+zQab&>85AmYN%Hc(#x|&uAF&_P2#cAyy!mT1d@?p0(kL2*a zu@aBC`ecyDx~DT0%Kbt4MYb}A{TN@R?Id8Z87Lt#Rn1 zS+JMNg<|95(%M$ORn`!T4fK$#3=N;MO2at!xH3(lFTm)>u{JMc^9-UDnfnvLk=q9U z@+2Z2H+yucR``A*0{Cl{`3PJ(bHEmSEIps}znBHTVT(Zdet-BM6vKG|e7X&#Q)kt; zH!C^2I-w7Z^%X8%Xr&HB*|PeV`LLV{L(WV22@^P@ULoX%!;zzA+$OKIRnDm&D9Qq9 zjkskrQo!m}!Nl%;O$)Asa&^61dWgySAST>qz59Sibn@^ghjBuGn11-LnWJ*xZxkEZ5!Z+ z=j)?@a6<}vz>JJ{*|W^ge}8qE+oDYB*gtJtZMGvr17$=2>5OkH`5HX0+1t$s0wQQA z8 z5Z6coE8O>MVS^7Xq!??#z#}NUXvzimWl9rfuA*|BL8g%&81B!*z)jBc7U|OQQ^5a* zTNpJXgx>yaKibGXj(!(CV}AgmSc8tEV1IC(ve?WLoc8=P&IVD%SJ%BUT++u*zDy%N z2DgEoWY(vaHl;GZE1ZuTTnRMFEc{K})2s=5nZ8EDG3*!m6~bQ8o^+MH5-47Vuhj}Jl;jq0;* z&Z(FbCxK?^U5J61`eo$69)U~$?D5W;^m6JJa7B`~rUoT59`LuhJwy&4P_!z(4 z@LiyJY0yKX;@GHFb@|Mu=wz$#*TkciD;oyE^SrqGjlp_0HL~SFKwPDbdo?F8c+1>! z^}G~&{AxOHojd#ZTQ|$hh>N4 zo4{4~rUR#-nm6iUu3M51Yc;=ErkqID5R$%zJ^S{0ri8-c3w^O&IW2@XOtH1aI3uFq zN*oO%`vZQz+S09!NcSG(FP*j&7T2zjapG{)H81|MSPzMA^B1neUF<=5a|tYa%4t$L zE6d9cz@PqMB{_;-d|XWVYp;)B&B;|wsE2n=Ydt+%vs?pSwzkB2VH7eqpEN4*1$o24 z{u^p|=^0h6{Ek>9vk3>l$JD;$5yx2M14UxRcm${cW4j`9pe!7q6z_gwjKD?pPN7_= z?nx*_@;1c2MYdr3s_z=-#2AbV&HrHv1kB_YhTQ)S@RO2--x3E}M!r!? zlPM8e7N+4sCr{?pc)6>M8_URKwZ`?TChp~Ooe9=2JPGNwi#(Gx;DRvs$47(&Ak`ix zmCiMWMvTZ+)P*Xx(P7YJVLXkjuUy&picVcg!ZozNd+i`*ZclV>JG9Y*V%ub5_5q3~ ze+Lq>_T1Y|iY23a;TGI~%y9uJt@XVXnC-_Fhmi3I5#z;V;Ch80sD6nCRytdNfj%%M z{_nL;0oY#hA54qS*@8BLkWh6UgmuOg<%PkLn=1DpMi)8Hc8OZN5BQn3vSft6DGSRt>F^cC9Z!!rE>4_o? zcOL;g^BP^Ot6R!30tI2Y%=vx6)I_5jXR)4m0xvtU1u2>eLVXLFMUU~In~k_|>;06u z(<-LT^FGY#kCs#0jc)IjFgaTJ?p?LI2X2yP3-ostD9>Xy@Yg!{2a~;9GymeE){yx) z$)I0|S^$4v+tV~@`&mMZM&Urz<9&)9hIS!gWpC8XfKAB<;7f$L^|}4*O~y*oO97w_Uz+##LZ|JDKkS&PRe!4d6-A(ekEkW^Vw3Tv)?P5`c!xT#wArF+NK zq_|wMW%74EhQ9pMnS9G4@8iw!XuW;MB5y8#?);l83X<;39K)IvfkB<=QlY0h6v9*< zMSFBl0TVaMypR*wWliA%pT5h1dMIEd)2^C;%MAQvcRio?PVV~keE8$^G(~nIHpdhn zue(FQ`Gvbp-s=sat^j|w4RTwr4{_NfFmXGdP`YTH>P+*tq+uqX%D*+H^x=Z*dsQki zE54@ZdyoK<+l>LyqeS1;#`BR->bi(#+DGRYXjm1V+qJtJaEHvf;ZR@(eLMOWpjzHo zdAh*da=_zq-QNje7;>Zug%dq4NdP>K=0jAsfu?R)L?5?Qh`RrE^yrcEbx8i|X-ep> z5AmLx`b$+H?N1|7@gzKP(|hmy*K;Oxq`a{o3wt=v!`)4I18RGCifiJ$l-^<+(R-5U z?$zpYE?fVB*d-HvL;zy*2d1tDgvOW{G;vF4`bpa$^RJ!l>eHfaA%|;w8tl|u{FE5>j%LW~Y77kmLq;?o4u2ZUI|x3ahq!6|b!w(X zh3>*)1FQmA+oZ*}s=glh#kUCn=VM2K(3=8*2ju2UIL?fiQ17<)kGc(-O%&b=Je+Jq zhM2Ubn&5!p<%U=w45h4TurKDKuph9sh1ZHt{`d)fSFsDTNG9^KBO%rty6cS z1MoT8pz!P-TDoZAX%B_^*b71iyY-P;#zFUyF~P;3ha3|*j*Gx+{v>MH-m z4xD=Ar@N66F{G=hQpB4btyGAAv`pXk1Yvu7z;w^He$!kGC6Wu6{F2NhVRrlTY*(Zo zEK5)26S_s*e2yV{xx2hV1VvsPwi-c+Azob<(s;~1L*1@BD4e6B=a~eM-zSnjko^Ix zhinTzS1@g$Eeb$VV3a?e^;3JF1Qq_0v}ro_9<@59-C9no7(qC2ZspZ+7Sp*sMzXdT zZ@qSuZ|Yg|PGRil!Q@KE$B4`R&DMY>>s5%hGF!tpa)<)H-5=A_b0JXgAZ>eD2!i~f^u31HuHULV!f|_X&`iVN?f3mIbL)Q&@%W+K zg<~R@N@O>8uSRs9A`*kYKjcfWwvPxnVJVB@>q6irjOoh9j|1E} zpEm32Bo%nS>qHg#UoQPXd6KB6e_z`x%AAvEIP_^21+<0%ZgZxg$=RQmv1Q$MoyQ<( z>jhu=yz5%z{YsnE-0Xt8y8+&k7>*^oE$u7%`(T1UQHO{y6c*MrKllC+$;*^fx1Mq@ zth#ZG!^QagLq?vf5nc0MIrV`k1S)l~x^2Ue?-#+q=g( zTU=j5iL_sVfAqT6%EEDMA%g?n+JqGXAh5U!p!3y-ov3yHt`|k@jp5_DpX$@XMT`eckFlOxE=Pmra)e!^_km|&{ zpnHUne1BVt2<6FYpwAzYjMU0!D&c&gU&09%6v!QN+dK;+i|590#rSM{lC=X{K9no> zf9Pa8P4k*5^$Irc=);I4=;{>Sf$OtbF;oDS&Z5@31lkPJRK^UtCNz0t|nACVN()iLhEUym%&4OOLPEF}H}~M(*&m zl0gnb4{paMA1ZE3jy`>LIMe}rs2~QVz4LI|K4$Ii_^ql5vs!M|=6&X@*Q|Izebo26 z`nj;NfmBJz-GaN@tX@sdNlVl(5T`jp-rM4yXfArB4FhE$ZXNio)UVpAH?m}&oFI^C z?#XC4g2(0eVAwU>w+HB{UQXh5gmtd~93s{9b4F(#u-L+CWCB`FS3HWyj`Y~}e%v() zl&uYamGZk?D?>BtV%r>C`^&beyd>c$M9nP)q-FJw#IrmteEOt_AtywOV@ey-=zsch?MSDVrFa?U zwIAXy__K7Y`!D4cb!Kxr^-xf$Lbc0vb<+#f8QDrB!6V!HlUoKtFucqy{E`D`OE`sZ z?RFU|yStbhUT;#~UM)qU@)q_LnKS2jscs2|7W6|lg-eWp4tEjVc6a)&abOSDN}}G3 zqC=XTEP!(eV8@lN0=@x<{}`=H|J(PFHpaVew4hRJH!Wyyf&BU(xDb~$DDbnb+3jU? zv90@_+>rh35Db~xdm(fn<#egj+O1VCfp1R>yX>8rRMo8;#i$^-&EUU&$BBvkc|nV& z|6V_S|D-pzlFa3c?B(|_rO^S(z1a?+iC0qi_YQawDknC+Y60V7bLi1;Dr*CDe;qxn zV7et}8mT>gopwoGldCR90L;Z$_G(=&aYvfG+g*e4VmexKA(Lf8QVL0+i?#xu!mF?p{{mTRid%;I)Sihg=cLE~~s`g9eM&tmojh2?IpS3@yvc*e7ZSJsm1 zm;hj%^3Xua-h)M#+$uo|uY6bRFI!K|gOCLGLJ#3GBh~X@PQ;8B7rBnknfJty{vn25!17GI6Ce%q$B;dKwcRnDr>Dz$~V-!l5uq5>yLS=v;w1O5) zvs5HONUnNTJrR=Nk6E-x#vwdFHWA>;e=B>rqzV3i+Sd?c@_xcnp|JZrfjDR;)wC01 zAAyXJLn!eVT0Z?fMS-A?;A^A7%8aE1sZdzOayi94$55G@pulNt6js#Zmyk71B1%*} zhR#XMA;JiJA5yyBch-afYZDwWk1-Kxt2g2p0&GJA#uklcb1cXM;SYdLK#KXEutUx8 zAi@my^B0~UACVy1*B$fN{4|^W0PHDXfSEF4@C_Ytfw>Q#(dspSfZOox3JnS|OQ|tpMPK5aMsXF*QHs3PtaJ-*I@#=Td-lgkTkTKBw4{@FMm}~$l3hy9;4SZ zSG`3Vk&e8%bRI>R(ab7yZorLBdA1b4?qT1K52nNI2XnngH0Oo)I_QgXlNElnuS8TMOPg(`fp3~FH}L! zCu6YQC#YRtgMaNP%Xl^(z?k}72Kk%+F^cbZ6=5lTkwZH0?v}tO`#flc7!&1g!Ivfo zL@dCkhP%y%e*$mLcx>c1U3~5X@e_#quWNcPo@~K1o-qvd(~h4$>5JNe2R*=9gPomF zw#lpzC-qy$w8OLFrwW0}qgh~Qjo-=E@`mwc?f zH>r=Db-qQ=_w!Lh}G`t+fGWljmH`$G2Up!ZRRORQwS8&3dPyUSuZgGeZQ7$7EP5S0Uh2+VF zxBKx*U_1r02NO;%DcLA244HP(!MrN>*(zQz6rIF9sdL1mPwt3R*9U^gDnDLRi$?Mv zJiN|&aP88piQ+4}`wPfX$kjnHK(va?rFQu{{m^~r>XXP1;>ni}zMFf|I-2d9(LwaI ztvmXp!puseRDv`+WxTfaH9eV;cct?3Y_3X@A` zZUjStve<7797AmU3pJB_iX{~)zr@i`ec9BPMOm831v5}fBx+~`?0+v;dH3K!=1#~ z|ID@CPuxdA>(j+BAZ}DF(Dc!LfqMtvt`iAG7Hqegb-N-jg`&C_B48;1FLzohN&(!! zwZ_QTO?96D)m_j{>^fTOR)O<~(^kE>+ueriOV`tp5pW7mIWUwZy1ld2B6loATZg}}N3Q;!bczP^j8y?mhtS<5v!cN}{;&?fz* z{}I9kL)Z~#0q0+_jz+EUQJXaHQLEu*)a|oOS&XZiyEyM{BwQ>~(Y8;oF)Y8J! zg0a=3vR{*q&X1j$84HTrOlys%7~_tmb5!cG4B?mhO-E~d_=~ZAMTh$U(C@gCgV~^R z;Id`och$5q`V~%m#2~mR9EW1UH|QyuCf2^NYX;pEEj~c;1zYO z)J||q2x&U$OWU`ls7eKUfD#d2e)>U~z!k67v3UiCk3qoX0YVfMTtjrzWk>!35Rcb7Sx|0ekASGA0|Uhs>t^hd)$$g1!oE)lvyxGnuP5Mk6k6o5H||c;osF zV-Mo_RqjbnfXp}p>i2im{UD@&aC zYWgg4c(}`Y`|)tw)9)YYiLC2Y&EfU?&@*x#;@kIhR7%ve)ZoSB#;a_LlXAQXQ_rl2 zMaLs^=Z0Utwq^|c)%=o}X4HPJI}w^DG#EMMLz1UsMDccaxm6F&nARN~#iaJQpy99b zc~t)moo|4gl+R|n^EV+%LE%@}Yk%{-&uY967EU}eenqR=+G5hW`D=%|Ic7W0B0+}0zFCL@f5>v_r*wH~8rZ(}mrTQ}xg%QC`I7Ulj2|f>%hX4CmD)E}_r$sfCF!n}zP<;0 zcSF{mfxwlk!A(OxuiBN&>g(I4aRWK-U6R1Od)$Vhs6BZFCymsU?)mwF!+pwM9hc?r zrT*1f`R|jgk_5^Mbi5!O_)#M0yGjx=U}~!@^xnYs?o7tLhR%dipzWLKU$QMkh3LRI z@_QHMD_%wg@F-q@!ffShn? zbXYz51EMm;=<7(;nOjW*{W_k8VzK^o=DD}KHrcF&-K?+fzTW%whC&Z7&Dh$qsqx1| z-{2d5(`ip~Z8UZ#*NXCfjI@~gGYH>!7qojRELooL=Boufrw4FJbWsfhZwIzPcmz+K z6wZMk^vfyhM!FEJci12#=@eZker0)l8`@ly=hr8}lip2)m&sj)yut$Ua><{YIZMP} z^zv|)HgCo5iV+dGt~Iw3PD?_$4e<>*ZhY>r3Jv)SzwYI^3w%8A{=%z>)>B3^=<)Jo={t%sl`#Yw%P)VYjsEDw4NtRRS6|R8Ei@BV6u{o zQ{uES-u>q0S(1hmDRm9fqc}8>^HtL!oKvq!OZTPcy9?b{_my5$+@!u?^(iAtbRxHi zieRxY5RV$8$rt?Fp;xy=jMF#>s9|06z}l_Ajo2~eEb$aig zGPM1HK{O9&!#{YffYUh0(T2_jgX$A`ePH_ zR>rT$r1v!^<2_C+F2{GQT!b0STJWXfHL8oeM$5ari#%tU%q+$q(rRdkon2b=hMj#M z-y@2TY${Z=&Nqb;_mFB@D8u^w-P4i{=qW9kqj}CTsA6l~Dbf{liTZfgrq@cJ37!{Rt&j@w~W78*F3L%&Qdw z0H*Env*+WHja?41pW0U&mzBHk<#pA5~QYZnRAf;8LX5i9Qb8Id7gE zxki}fR0%gySFbTjU)v3#<_=v)vlr5e4+n|j*5`CDSg3XYy@g^612GTWZN)P5Ij*b4 zlb|^iDmMvOV8s5Vg#w*gF4+$zjj*nDx|g1h`L03rmbgFP?pWoNA~fN&S`$!YR2Kw* zzEIx66DfLS(=}`H9r`g!v`jP?X#1%5Oqg*3{Cao|DY$S^OF3mjz&i5NP){n&7=;J+ z;Cs@2_~2OpmbsbI|Ps~Bo3GDWn2Sne1X7hcT;_6L-4CJXhD?% zia*?~Pms0uracL+uF0dyMBYl^1`DC}`3X0}LN7kWrO)C2tF<_^Yp(#% z^4;=l4R@t+h2H@=cH*RU(M@1-G-Cqty8PF#XW}`v24@#6dQdR`mD4i~2w~rNz5)BG z`9hy%pyxfC>5ZQc!C=cJE4sOl1A=57^k$|Ncf-I}!BFlIU73Qa-U5PFX-AQ!GU;Bt zCgfZTl)P6^@Xb$Eb96*IawpR7Ml9sY)J`}J_d38($mAqshc#+I`Ax`ZZr3I4iKI0X zlwr2so&WbB@0Mq$%|| zkrJak^vgZ;f~p?!*0%$Ey%OXsWV-xwlU(@TGMmv;&vv?+w=JWRa72`(4ibc`-JJy{ zaTv#XoadcmzdKNM4N@qdKz?RW3o1gwyH|mS*lXQwL9;}4EKf@_#+<$&G<>G?D?S-p z4huFrJ^XND8N8xqGk|VoV60`R6-}Do>gPp$?gI{+O_Nz~F-2*TN0UD4ypt3}x%azCJ@_ozION>CR!bq!l2rl(Ly}~$#;fSymFbD(oSdL|7;0~ntfnVizqAyq=F*sLz zCYDX8@p=7(nM)%2Q^ev>`nvlA^@XdiwrkT&F!M>JO%mb?vHnGmRTWZ(t4FUfk8Vk+ zC0|TRhKp>_e0WTJIKup9NxHyk}e?4ksVs zY9e%V6=#FgU!C*ofo3ZOo%wr40?M;SE~-VREJ)RYBTc984^#e}fGCiYq6WMgHxcC6 z&fYJO$))UpKNvoi1j!)X3D545poeyZ;yc2-ogf;rFCHP1CINv z5-;0c6p0sLnI7n~v!r|^Lz|1bYS%h}h+Nu($)VFlrH|`y2|8a_A@HgIDTcaF;AA9mIIG`O88xiOh}1+s}&!p(+&rb>d?rwAAi4RYsWY zhDLdx9FOtmF5_84_S}h7(xd0Hm4s(OI+8<#BKbYvT8;~lo5e{0*M%ps>{ezLD_3k- zutVqwO{N>pfRm%tbnw?&9aKn7H+w99qgoW0aEWa!tWM8_l!N+F%TLW*dNZgN%V_g-3PgEzjI~c_Z@H4;A^*`?kxTG$JIoHOmvHgIfN?20eQZ1)7g#hgWDkYm6ke!E0f0XI>k8C$%@XWsv1c61Hh^T9x zd=>7;9VuC2fiX)KZO>SVBaMs-#Sau07Y?5g{j+yY7EjjK^kj#$WK<#rj&+~{=X1YH zTmEjs7HHH13x3)^Daknr)VUaXUpg)W*PsSKcrY+K2tI>K(RU#;V0w4QLrL%)F(F^} z)X;X$g|F0qhn?jUE4{+ar$oeVU(I5jow@C{ewgfh6w0uKx!Q49a_WouAS2yN_qVT> zO_o_cfOI3npa<%K$D0xIZgDZ2jK7A@bDK?LIVsNsccF8VW9l-z4MIUPNXN`Y`YB!TwBgL_^WQ6S)>$2Qb^4;LMf*`Ve^2H123i=CW=m(~ zLh!L^3WK64Q#^$cEyLLl(MBtUq~0cWA5`020k7nXC*c2z!;`)9$n8Ok6ML3prtqlhN=ow*{4g{7BNS;?3{+&-%KHjY zbMlisNgby2U;0<7?&`wco#{DvdBX%3Me18c@odQTq2@n>-5|TTx(25+{d)*^hl;|v zc9_i$2o%kyM+kvqBbh{C`0mFGO+qo`Mb+UGGxpwd);ELut7xw#@K;l=S^J489SA~&R91)eE_x?r%zb&cDJizUYO=#8>;{4aw zp|tXlJP``5;)!VtYnu#G*$z+!eC8@J-qMg&$P;xPURz+p`3E|~K7dedeT33nC3C|9 zHj(agL$@e1A8J6|koF*_V(H{(zgLsEf|Oj_6M(c<(#*dC$bH)}MyD+4LC8vh2U8~B6?f-s{- z98u}p4fK@nYi`Yo*IqYO6rdpR);yzGtsT+VnLogTuV0}oHR*h(GX5>_bAwJE^GM;b z{n{O9W5s%-e!y?jUpKH{2ZAB}47KHm6PXXJB?ZU+AamL2l#lq(3)1a^R}J(|?395@ zr#wvMmoRG6R~1eK5mdW)up`v7{xkkisk+i(w)nR65sPn8dmCM}#}_1l@)6hTiAU4A zQmX^3pU?4Z8v*V%mS`Jvc2Y<{B8D-o43mNXLBZ`MOayPTwy*S$09x| zAVu)Kk66X)6|@#r$hV@dWw;BJ#85U$gRl|-b$NnXN2o97!EsxZi--Fm1K!L<&UYM9 zRz(!ad^^TGA5EL9OgFUcs00~JkSXFgk8FQrO<+is0Y?9-at6gxRAoW>k{qTlO0bwB z{rEZi&%(_Nx7XQ`7&oP^K}WLeej@4GlW~VPS$Im0KehM%cWAu50o(2)v&G1&_Jy4?fFZbOY#5{VTEl+W}47@|r{tT%nU6Nf*G3P2x z`R@YZaFdT>EjiTHWejDRP`}7Dh2DqR?528NoiL7@IA}?_0E0fR3zDz!``jOCqNqns z(fTr`hWWLfL${t&!`OSrw^QJ?^1zfQpbSpdi~b=#Dtu7di=Ne$AI1mjHNwKjas-sv zf5@u6PoFVHMRy)|xGu|-Kn)HYX;o_g>^)-$k6|E41_hmRFDQBEURVeHdsSjq`hTVI zW5X)-hm+&h0&L@D<{>3*=lP;+BcScO@bEresOXiZDQ zSh1%(hOnBjy)M@0IRRO z5p+Bel*T?*!AsWKMl+Z7V~mHwtX%sqP$&L>#TrdjJ-;yr#_Cv#F5!u+OR*akzu&MvuqQJg*b+RY{mh>83rsu{ED@`o3Dze z_;5}1T+?_E;ACvf1B z3<%hB%LBzftxLyhVk43|RDU*>0a_vyZl=*_THyyjZ3N0Bw$NfUe;`k7Q6wUoF39nz z2%%}QQ`+7ZSM|rngB~xj>eda4u)svozaPGb_r7zX(921nK7Qa|?>cS%MQR$hQ!8+; zbaNb~MizEM_B@K@Ic%01^-*2fX>UwxZ9gw}wRR;*de+SLY%%$Tb1C4|Xl!>tl_V8B z&Epyu2(?=6Ow%3iK*xr;pw!up#syTCTMJi^7If!5^0^xK@wNDG(Gq+;K-2Ei2)Ez) zGtKI)mY0^@?&Dkj5_?EYk^knebrwY1u)8=&ZdXYra&7a!2f93xxa`c_fO}uYcw78~ z|0`i#lM7vVHL={)dl%)irNBB-iRlAy7plFh>H8V4oZGKJf48TPcvmOfPwI2EYF|K_ zK-0C%zqyJ(=-<=f0`+oNMAch9kUf|65Zc2^$-zc5Sb4?*#nchTN+P;)i!?G$|u?zZ6AKy`boFM-+ z)aoR__|7~*VZW%0frgf#)#QZQ)Mdr`u8kQqqD7r~QS^u^b^!T2J0oma?hB^z`J`=jA3eqC=d{sf zO(CI#e^eX58S5$iA|Lz(%>wXb_(E#Yc)H-^ISMF8=L7#(q5lJ&cdW%B50Vr6tvwX) zq18_Jf4|Trd#H5V{>dd-U>W{FDjniF*H1Bd zqn7Gm>3LpjaeR_99d@K-jgD4H+IyZm6Fpds-XRM}}}FjS6ToU}3= zu$oS{2DUyqE38O~xXgbVS~FCj^#-=yI#r41(fkS$&hBWvy45dc)JGIdgk*ZQyAb{f z?>+*V*48pAAd&l%oQmd#l}qHz&a_!~7bOQdPE4D`kEy0>M}ZrBaDQOgX4hkst-Uq3 zwe8pbD=v~!nc!h*EA78;)@}giSg>Y`rTGN0yI^bckF!$>4RiUwvl9Tj z5(97&{?`Tg?FWr^Nti?yXAGHst}ffmQTI~+?rjnn8hxI_(p@*O4Gr(I>|NugPFg69_^Lgo@NW0da?C$I=Y4 zle;+M{f~7I186rA{Z!tMuf<6ax@q%28VD~Mdd|wLxZfhbYx7_|d11*fwY=5)Qd0F& zjJR(dp2haUnr-H&!|61FG#g}2_;LSYPl(}h#-*dQ=tg@!pmIqqTs`uU7=T%rqHPRa6Hw%d*Zmk|y zf*Zb(u#?ZC_{O!t{6OPS=w6y%`n|=sE;=GYBYXH_6~$i|J01O5QPi^HbCK=d)C~o& zN!_SlbAEpe9jAcdo$u&>twioKXj{zik*GNs_bLAJ z{Y*p`_ATUtSSdlId$Hb(hLZV^d4p=igYzYTL3nBm5oNFcM@8(y)3P}E3}M%Y-rvhO zLW*TT<8;8JRagfYQ_tJ%!mzYU-*D-!iO9*oE+)&){#mTbbm0hu7(oxQT<1r)7}I}vb(iY zncADFq!~_uamxs&rTnf+Wh<}60RzvcIe#FLbdGL4LU&rmY)%tHsi zF4ZGQ4Q}x684d`BRb1`o|7uW^i%QZMxbsZC&#`&n4*B;T6Q$Fu&~EVo^_%V9CaZme zkEmg#ukXv2kv3D%M#p6-yZN=s<}cife*IAJywRF|C8XPD)X-LT{-X&hHA_1yn+ZYnX@<`Cs-O>)T$IjE&th_1Q9p_Sx?!_$iaTD28(z!exM)FialChrzS-iT6&0?g?@m2JRhlIhHf{JkRA zpB!)1jlQp(AKB<2)Vp@K@nJ_t!p_Qr+PMVeX{fSuPgI2S-yNB~3YvbZe{|=!kM_@b^$lr-Yuxan#Y38p z?o!hFHLMQ$i3lZWNfuFQ6DN>Rio5DJx$nz1y-89%t5!$RMO5gk-i#0O*}e9~%)gDO zZsOgW(e{^UAm+@FVpJ#?774LCa(&xE=fGJv!O%^&IuVSwAErNm4mC_eb;kb`?$_Eq z`D8oXp`^JhlD1r5uzr01QBI`h5O($<0p8zsrYTAadGkJv#e3cOi-;H9e>B;ngDI+j ziT!6ugFi0!wv`x)R~P86@xNs9>I0^pNUtIPY%1dHV|zz^Q{0C>Lo9oUSkH^C%F(9U z92^BD*8tcF%g|;4kPUvHe4ho)$%1ZxMrQn*zXULzupD49znApweWb@PUdX0hm764H z=THr|za05c==uFzH$DMI+t^cg~L5^dYZ=)nG z=B9eIEOfRB0e?uH=^q0_t{VQ!7tiLWn0EoMeG;S&_uwr)uL)hn2=k!)Bgx+gsT+wN@B77pW!Do?n6R*#p)PjO3=9 z+QMS6lI%U7wb%f&#kDPdTAPIH@j{Y;vt3HuVc4dr6b25DM5SY9F0LZ)%H_Ua@kTYl z)=ncZt7N2D*vb4q*!#lq4@VN1-v*y!cT_nlTM<8vVkQ_^3_ z9#Cr=to~i+t%^yKf(Fq79>}h!2uR$0p%be7egzn=Q$9j%1=1IQ`twKC%j@b|*rykuQf|0s?VR@#OTLZCt zIbNje!|-UHvAV4b5mVd4kxvoMOYI7dhn7w~4#$jwFi9tV{F|5V6Gr9gDASAM=kWNi z?cX;V9d-adVMz+&-iptZFP{f)p>f~03v=n=Co{Use+}W3Ft6ztM4%^fo#5gqs&VD~ z{}I53JQEXVvYz=4XFc>B)f24g>*zW7>0W#; zc1xVpw3gx?om&68Q>L86&sviFH;T{JM16CRC4%v$ zsD+MPx6>8cKs*OCVz#UGjr_-NUmUVr%AqimIq`fSU!h2{wNA!?O69EVP@LzDm}8X8 zJvT?bwfoE{us+b!87JisFw*2Zh&*Ces+1=HMeyU?nD7w>;ZIQ z;A!FEp440wa@n%H)e(EP-{b0#wW8AwjXC>=YxU%N#h|r@b?AWG{vTAr)wAw zhVtJJsavbztBVsAjH3l2qymPUsg_gJ0`Q;$BH!hZb#gqVB3S*YZLu)vTD?w*&US9Dn@1np~c^F+!0wT(HPa?{e#Z^Q#N8*}Q_w7_f^wmB$M#4?%gLoge!56|a#wifd3&UdwlDLZ-GO@4U;*!}zICzzjw zsK8nbdRDn-5y797pMEbcGWTb<-QUaFrZYM&|5N1WGx-0{Vv`n4SQkWZ0*=F%B^6om zI8VwB@4b$=b;RZyP0u&z1rdmXWqr4%4+lI!FFbbJygVCT2ph8=I#YGzgo1x=d79z% zp)4pcqp(BbBC2U3&a5tQx=pO{*x@W>;4JQMjMsR7PDEm1=K0lOF<(cm-?7#~@30>k zA240Jw2B>yIom4c?W)3^B_4iZWY&`MuvL4o`2M{e#kvM5Ss$8c2-V5qjqJI{5edtLv7K^=@g9xlQSTF~J(3UE%Hg54CtYO-( zo?%3eae}Qc+)dvSdGxcjQ^ZVQr2>iegg16fBOhuO*oJtVSqbq!y*r|?HtRnAhVrQ+ zcAs_T#P8&n8R{gR@o>jl=CfPC1F%=q-F9aqB*jvF42);+IX^$QHMtK_)=2+x<&1#2 z6{p_O2d-s%MNkCmY7a@A&F#==x9Tb{1SH!Ab0Jb-pv+1|@(IX23GP8Oo#tl!{Pp8& z8{QU>_?17$tbbO#UTd_;4-Eq+yaLR5WPtU_gD}4NxZ#CM5u>KGmG9gMOZCIvlDM6a z+NEI`FGkgD$+$w9OJ|r+3nn?ytB-~yro3^LU&iBjSKNE+r_|Y(qsjm^p`S^WS^Gdf z$dGwRm1bE*7m@a2>DQ9HxZj34Md2hNaVDEM=f)*-pzW4WNLc!`;Zm>mQC(-W_bYv+ z{oe@Ip=)1Slr>_pDUYguSmw?q6qhyK{g2z#!*Zc6%xdJmwgwBlVo5{ZGNU0qt?B(G zznX5-161=ui2~=qYfF9Nz*ZC!#y4v`$&VvY*dhNI!)@jNG~f^mOG3N z8j-lk2&sK^U$>V-hw#Y)5*&_eE6r)3F*7fqmDy)Joa(tHklS&^vN#Vq*6&{P+BkVo zw-s&fg>%gbg8P6y&cpsxkULj&vUIV#w0;}z3%d5F)UILGP8MRDo9W9W0@zfu{b01b zMxBu7I1|wAFo>y2$n1cqoKcm`%A}St`5tP&o`mJ+WvlOyR>`a&#j6^TU32%Cf_8+u{6dvX!pp2xDo$$bco}x^bjnI!c z&!qK7nGK*^)8?RKSH?U>$M5Wn&m(iL6dX({J(v#DoxjNcbu5&PduZhEe*Q?@UHBkj z_aAfBeWjvk3pjT=`a|$w!<*w7xcz+5i+Na!0aU98p@Rm(ZI`cLLh}byh@gMUi#qD% zTWpIMS}s^PwQE{pX~OqJL04U7vks>)cPaVE&Zb@VfvNa&cqDEX!Ww!Fi0Cd2e5w+^ z`XvEt?ZW!|9V#QbQdRvZ|1nQhWyro^qzZr)0T|vb6K4UL9N$k?H8fl3F^Y-2$kt~X zMtOp@-3Byjtv3TUs>?fBfJOO4;gdo6+z&VRZX~#O&TM}tDA>h*;2<9?if87fJ$;%gZ=I6b5|0pckpW~=1{)Qw)Ozdz#tEP4HZu>i;?&RP&*)vd^r z#sqB8O%0CqTw>ioRETe391|dvuelV24Y>`8ML`$jSpgpFDNv|3r*$9OhFF|Xo2MTm?fJU^ zv>7?hUFB>bDb<>m4*zkJy)NvAFG^Zwx(DH09aA=RFap2sr;C`)sb7DoaC4d!?^Neh zx>0v*C8_G1{noD`Z>#zCQ6BE+fNKk}{eguPFX0+bJ)H3Nw<>40WXrR8ji#(fEdois z_fpuo_CLHG-NQBaZqe-&_Bm>5&Ovie^giII_#y99Q;WQYM8`N1!Z1s|;Lor7T;Qy_ zhqH@4`M4W_*G_fMA$qczp-Mk|cs_vLp?SBe?zCojXsw=d_B&`SOEYZj!yFCmQ8~!# zY`43e0tXe>pHPKu0DiI45EF519B2l?C^6jgOJA$i?!}fwswIe_yHJ-EBgAwJ9R0Cr zIS)wpkV+TfN9x0b;j4#>yoNZcucjJHH zbbdpW|M?Rbb!}O>4>5l0p=~??Om%);YF?DUwD-!ft~w2-XSG^Cd(#i{Cz1mtf5sS; zSLA2y&)s6N*t^d{A?NU;ig)S48DYZSNWvvQwA(F?o>b&zy2nStczHSY0fdIT2q=H$ z$7~Z2n?s@cD{J$kU&A>?OxwQ!=b?tt5@0i@5u*Gve#fXOfYTZfm-1`SdgT?koH@># zh^wc0C0%Q#kL&pZt|MJ;s(E9a{ou%3u!B8inHq~|654;!87y!?cb^1?a$c5^K5eii zF08VLY5`XBU@<$-XFRKJTuL)|Iu5?Ux|->&zH_KQ%Uc)OUFQpUwRTnGPbhiRHF5FN z@5%SqYrQ3gTpl5uO<>=GBcoT+s~Dm&MVi5(z~*N}->Utz9g)0s6GC+wB(+;LLvLOA z3|cmi95(M|KmRanfBVA*KuV7De?LxOS>7|2idX;qopx^T1&K;8?3V(Oo{D&^Goq_*&2@I#vQ4OC|ECa%W(O7F zjEZZs2j7-9$?t}_+TY?#L}A4jEHRmNX4vyn1VNzPm{G`Vg04*-$CZ(8$0$ zOiFCUT4(fNFZ=Jkub()^1+a*lj9g~JlxZ5<75+2+04^K@*F zQ8{-0D${>x`pR!x*B!agGX;h8;WCr7~`i8ctupxHQe5(!D|Dn|L zRdVlX2>Fhu zc-GX+akrN8A~!cVlt%R?#o3SZBeB8HJL?0LII*Bs(_0E;;dVunFFl!y0(ORSWGA$r zq!YS%5FMZ1kl$|>!?FL&7gKj>CtGs6%;6^{I8qaLE`egdtEbE0Ww+!7a_1Ci6wB4c zO`oz2B*Ha>xY6N=-9cA&`^!lk3%a8{h zU4n(p4jirm*OE0K6#Zb#=~mQA%9%Zan?cz>MM286>g?i6gGUmMai@oHGu78?NM0QK zPJF>J+zj~w17FaS1XCMvw2rd6#QT@lFUt?~7oZ8k;QN0v3tIq@rmvhbL;_*AEIFf< z6@FDwe3}TAfn9`Kw8GNk3RZOTbes}hkMdckPF+FBl%eyWq$ zR7K1aQoZxzp?tpURs(IEitQ5^HM+QQrp)CFB+9Cht0WF2JAUJiQA@k6{1<4)eYgNx zDlKq)?%4e-b-m126HPc}44fyWR?>2+HMzgGn#SVLIyOj$+&dc&65008T~QSx(Phf7 zx2Dsaj{MsjG*X_I-1+iezYAd#OZzw^FZoBdcehXNM8kaVU?3N{t2rpZ=!<^+;{7Mx zu>m?w6Hz*yvfbAUmgkG&ugo&Zf8vLLBh(P5c5wFW*B? z_umsjN0>QcSxQ0ENg%v=*|B;X*$IZ2>yyh8r#<^{Ay+UeF z&zoI`-6;*Yg9V7Yla}v2x9C@REb)+ssX$=f@=5V#nF>a;8_9qbiCi^@9 z2Cn7+!ylC0I7(8%2t!b;nWA`&IxMG%6QhH~8PbDDtRZrAuR-WyX#Z-d&vOA2T^__q z`O^HLPZvAz;pN82;HL)-kKda&v$rJH9luSl#^bk2Z&R*czA*95z7p)2CVKCPy2+y2 zM&~?vo9dmcuV`jHSL$rG8lYbV7$ zUV@P=Ux~VJH({Dw9MZ9PHgjK9KLui^aZ{1&$uWm)5wf918IdJ;tQH0ITCnMZGjatC(#}_q@m&ATO=NRf1Y$MM2OGWAOmbva>2>gTv4@N60folUV7CsAG zuC#>Yg`_Etib#Br5}W$L(`4gGBI)YZNTQ}b4XrL?)XizG2OZw2a*vo3Cp3t4=+o83N;`{S9$FQih$ z+s-U!6or-VuEa&oNO&}+=!CgUe~|Rgqdv<6`01>91rw;4j@Rh$=@UpcCQt+-@Iacc zX0?X^CuFLgrhbX<0fpHO@l`{>2n3j508VeN-<$w?7D0i7Qt*VuN3CnYw}02G!``vX z54_~Nyz4jNDl-^CCaC2`=o(z=lKa_=`86J0=!>D*F(1ueQ4-zW1UIKy-#-;T_ss16 zX|!%5nvDs2>r$nnTN4oXI76A;%PmUqh3#%{)=0u(wG4Q&khPICd)-sB_!hz%_U4mK zDqOLk?E2%I588xpqwY!*9!pp0B>h;HDNB;fy-hm)TdMe06l2qhtNu&rSQT6PI#!bJ z9D@7@Gu* z{U1AvoQu&fj<>(%8`Fx-s@Rr)xtp+(jsUefu2OC+srRTz^?>E2R zd#z9BM;G{;+`uN#qW=qpYIn}XT035a9v;TjdaC<{+o{;Ald7f>X^h&&(+o_|NOqjS zw;_|1Zt&0bZc|2F>iqXO1xOflD_6i?61)OBz8uQDR=`nc|B>Bu>UX(7K6K-RsS&aF zfCS~>BoZfe3#3Xwcw-$!%bL&qS>734wUY3Om0>s3nmkw(wz@{*lbgL^J_RhSyd~6^ z+6;U`tvr<=%3YD`dhJEwlmWpn4}m`rapuSn9s5E_$mEsdF)h&-0ZpArQ?~c(!n?>? z)}-fWYu4o6DTZo2g7n3Ot&`e_FokrBS@NyiA$a>|XQMEu{KQ~08V3dfDX%EOn7q@L zRkZ-q!72)Cg?o4wF~4(kP{>bj`r{nVutu$hdi?}8M6?IvtQ>X5e&nUvbT7!x_>+Fo znZ^-W>Ic4%>#D?KB(mr9R%_Nl7o}MIT?L+s1!H<05Q}~8Hd1X2bl;HoaqQ3BMT0=6 zI~GF0An)PKIz1#H3iCBF6xbh?5VHofd+pd_dT`KHf|`$D-UZ;*w6j)zknLBgh@hR> zlL$XwnCO3h`xvA?{!gEN;%0+D#nycsZuX!N2~Ic#VH3zru5y58pZ*VM)*rJ#V-w6; z7p6mIDdL7ItMc%XLGTn~gob9z722#R2p%FD{10!x7nZqS!xq_6{)HBnB=7BmQ|1IkY$&(mL7i;v%Lr=n@$NC+ zb2<%cW=hFZInqGS$@qOH0#UnC@%y0kuo+58^+Vz4Ud1)${zmCBj+c71P7<H zh40>L2>KNCOKGycMyd-bHyD!IE=RsMK7Ac`Sc8Zbyy+VhBoO&1=+HvFg@lyWv3`o@ z;qsY=@5)Q}gAxp|Xs+wq@(LChL(6AyDH&s?do32-7j_64u#P$}frF2w*5#Ue7AH1G z?24Ff>7ehstT-!T9B?waN+cd?=upo#Q1BhjlZlz`2C{iU|6?#HLKFFfP;96>+(*nR zArU;h1eX%N2KbVSU0o*Sn#9fa14s;TPO{h4W$1vHeqAD_#~yilrP!zc4xlE<0Q*0i z{{>qVgv)9-$)7GK>q|?8J-8C3pV&NLwjHJU{QYIq(o4D&5&abFbw8{%W}Oun;{;$D z1J77lxE2O3=Jzia4&yy>M7WM(fDAkbFBAMRNCdF5|8pMvh(zN{pGyow(GrMLM8uVY zSGCJ+34RptD_5jPg`n~ieA9Qy?~wQ-%2meZJpMi-DA8H|bHUEUU;Gqdy)|#+N>g&U zs9un;mQW-fcR%^)V51@um+~X>&I0xtSr?Zwav&ioM9|6o(X7{mUUB&BN?CREQFh$r zI=MrT$p^zfR-88(w6MgUEQ`Xca__ansuS~K3VM06Z2V*gN7NTlX`gPaI+`=@C}MU1 z#u|1zJY4I|Qn%91)1wF_Sxer*B}2Lk(N|w~?to5=Vp}3FNmTXOrQP=y%T_#j&se=I zl~XKhuE(*UwvOD0@%enet6I)mX-lF~=_BXc6z*8m% zOiDnm@M@2nX(oo!&|$JM?Fkgc(>=>GnZ3cSPZ^unbp+3247jc=h|s;E*!>G2gN*m{ z=If6MLSk!^K-?u2u+chmpj_@dcEi;gJf1oR5cj(mF>nW=S85uQCf~!%3e}t(|IU9X zCMIBsh@Tz?zp-_pi+}hl*5bwtdJP`w;0EJGN9@NeXY*1T=RC<&QgYo+N#*g&R%hlw)%OCK9<)Jp zW8{`nF2qybyK*%;_5Ry(zs@Lc$&RQ~%$jw^JfGB7AP6<%uNIa?5HB9B_2a1G=dXR! zr#E8P-2V2{-ElW~fq>;n;yV2;&QYsc>2zaX>@NdpWZiztRcHE};3n?0#YaZ|GJ3q* z>_YVlaft=@x5@sbYrKsqi|sx;y&0Q)K6TlM!JE8bb5J18{n=)=%c+t)yPbZ-PX^Ov zcT=t8B`}DL7@gjn{3teo-cCM^XVia`T^YFkB{4#iuvC!$i|Xtuu=$&<_xl9<_}`Do zcwYoROc8)$3BGUE&&h%t_ghv;a19vqI{RD3M^s|W*(E7^pPV@$bGv zJBYG?x-(SJ3;zoiD5t`j$F?2gYB8g;hxL434(pyUNhET+nFVE7-~E8DJ6;4lPoN=Q z2g_nlFZ^a>!5`yvrN^Ln?AV`Ez;Yd70QP=ebZNk(2JT~nShg{H5da3hv<>1GWK3;* zM)C;lIABu6$sJK5OE<-cXYvGD9UjU$-PU%IB_+TKFSdOAaR2Sw3IPsEMamIQlYG5k z3&8m?TW~q4Cb_|f@i*M}{C*NuHi*!1yo#!-f};6w&u<@I+==PtW58ZX7I)150?_a6 z)7~h2NX##7r~RhyM!aabZlT7?cI265G=BXJ36HsxhfeD)A{3|UHwq#-jn~dBwTd~q zA2XTcBv>-+DHv_Z-avV~x!Tlq(g{9Ry)mO{q0+p3ymAiZw`@8U-BF73lGFu5u-V5W zW>N(|e*77UE~$>aLHi|tB;vs81@2VIOxR<*&*n+0y~J4?wEI@Q=Q%+-^EKculuxuJ zja{;s{|g3NW3fQ2Jd|A1MbLrfJ5c!CAoCj-UyR@MZ_wyf8OroP#b#Kht%6#{}Zsx#r(*4sJh*Lm#HIGmLp6> z`R20Kc2dwFt#j(~=i1vv)OsKDukw%3KNQ@*B(;YPc9Tr)Fj%0D1v1%{+RvOEuzlXK zH|?CXHzR#W{G~=cU1+-;Pi5^KyPWPszZ~Y6^%BcKd492+&O$Wvg!=cvk4)vNW(Dl* zC`kVgUso9w)gNsK5D<`%kZuu>mXsP00i_Y88xfH1W+*{QLPDuQ6j12~iJ`khrD154 zW~dn$=Dy2+t@l2@H6LWnEO73eKR#Q?Vb(T+3x^xJ5UNv>ZvB2oCNL>`Jg70^} z?vjY<^gdaz4tKn;ugP*?N)3*cu&v-((r3vehTx;*k69nFbTOI?@7c!ZS`Qhhvy^j0D=+fA}o>jvnc!fW9vK4 zV~n*Sno9W_e||MVppYjnG0Qa;j}QC}-_}?k=v#<9g>&iQD#INnh9f;kK)FBGywLJcf4fw@SBQU7`zT?NR5zhh*TA z;gc?T$pakkNq4WH6&6c*g|#9LTam0hu?*J)$KyE`s%BhJ5kY0Ibp z-i6B@1VI(AOmvAMpvXqw@P#vC(|yIr61cbEz0r-H6uFRx0dL51Je_kwKWUS(a3;9B zNIXfqw_zvo*h#X{q;BKxkQA>+&v-*-9iSTXaxBJPpqlGRp1M7ku?Upzj%&5`S2eg8 z`G~L56!#6%fx1T~Lrxrncgj?c#D_Kd|V|sPN zRt{teU3iT$?GHHaDp#&)`Lo{4)`-7o{G+UtzHaJFtBR+zUE~v+hTe+yvE_f?soZd= zdc@4+wyxh!Yx`qh(ByDj3$~%ylG%~RM|?79^+tKVsx#)Z- z-b9Fv94W=ckF?<@ z$>1O^%iimT-|odW(%!}IG;0O@!Fhg=>Qfat=TxM_N3~*cT6?^C|Hsg@8f&Af)Mc#R z5L}p0WeFdCgj#?fY{q?qA1`rS* zEzhvKh|CiRIJS6rf|sdc>g>pu9%C~^O*E=(Sf()7pCdXIS@&m$F!Fa;Bd^q5Kt6#8 z=)2sH1xVz=nb@lmu;M@i9Ti^&St zf9hvH@TMGSv;@9wUsPgDLw6AND1Zu04;EKPaOmDgc%qrrSyB19Me{*e>xBdC&or7^ zYz%F`qZsz4;ASF$x(16vO$4X^S=j6=idS@LFNeFdAaOaRUc#$FLx@9B->vy$*(0x? zRYyzK)y!or?`KW!yRbgwd7bUOe*-C06%a}N9$rAba0f5WYQpM|-5sFb{4;Sb?{`C{ z5&HzJ1(liX2kiV0Eh3e9ybgEGeW$fm$({7v8>%MuDF$J|q4%mex2whGB=%L_+IAF(vD-WE{JhE#GH888g$Tc%&TMPO|7o_fnlu*1hqQfr+cbNWJEj?WaEY zD$|lMOh5a45Pq*N%IOS#ab+_c!iZu^wYb^kY{2ty(CPgaWQI-BomlcwaLsR2<&mkv z#z#IFcv|1ZS}lxfkYx7l zTHtz5w7_NkjF%S0{G;^Zn>Owimt;+qT%@X#6)jI<{c2*N=!>kUrU@JUW}z2D7Lsoz zC--n(TGh6gd1rl@$j+>Jae#(Mv=mD@3PkJ65M!a|H@nTC+rO#_K{#Gs=hgKES05wZ zfRMtgFBm}SVb!k-zO2Y52| z-vtg78d2`*%{0ok*`DYeT0D7MQ=`G0>I9(=`aC45mp?-ry~%ZE*jB?vGTOsRgEsnN zKjr3-9Ns}Wbfj-Q$y=?vW7>!>)@AK965TQAB4iQc>XH<)u#8O8v3lC5oC14dz7BP> zP9T%!1tBqO3QVkXENJB~b43A~iMrj!PxbNi;OSM)UAPY4c3Utq@Y9he$AGd+8xDDS zQF(DDsE#fuGMR{wJ_`LWQ*{alrHE};D`qgUETIkvptIJ2_jCEuvcg2iD|*TnL*g?y@M z7OdPP=W~*=(@H04T;m|D%wetUiTM&ya4OIVezCXS-N5m?+te<%PYOWH(FIr&w)WX?r^RM%6h4zMTUl;hMB4|Pd{j%L>?IsNG@>@)`uyO z3!#WzN7wQ|j08^`WOQl z1%sQq{pBwHCeXhLd;*isI-J}!o>%w+?{D|I7*o$llJNrYrJBWh=fE&2e0$Vg+JDI@ z@U#A34c~jal!iaeC_8=xFD7e$nvWDKx@9WhNx~alP`!|GaiUx>sXTAxb+`3)a-2rs zVrbzLkzwjSh{n#}yQSM6KLZ-b$#<+YO-kP3v!akicq7-Tw9kv#FWd660F9d64dAlE zzXW7L@jm{W!Zsb|k8GyG@%{$CJ&fbcJBck26*|FKtNz_Fzd$Q&AbnJpf`bgn0{j|4~`8O4=e@nBQ z?z`t2Cc{jUJ6Tlz3qtkmChyn%8>7EFB?Zt+Y(NbNW_Gx@n7i?rgaAU&W+61_gLVr# zfCh4M0ZB>A_%uCJeMH7jyl& zAh=%L<_fWR;V#YldFs^aWHI~NkWAJ{#b<)XJcp-vV*p!Avf(dZ?tdQ|le>9?AWmPV z{|+RMQ>MMZ6_Ye)2N%UxaSd1c0!cr1#fu{@6O#tFKp(8#O%x`L+VlJpe^ZYM0@fh~ z)+9`&xkU+up6NT^ZqY89dVJ7+n`bk?cB~U_!%&LOf=xZLC)lT`|2JjiN6(LaNQ9bE z;tASe2d9BW5PsJW(rx5E@EI(9XmxVI6h7|?b`pGq)pcB!PXe|WizO~U0;-7fZs6ne zw=D=xl=$-DC_vb60#KF%H{;Vo)pO3YcA)k**D1#5vap|#zc%1i0@g@>4?D=x<4mDHX{Pp`Xc@KPNBS%^0>=@fV887q24J=^dC__)$P7~vw@ z_tOR7tBXgLI0pVO`~f!AaX-B7pZ{J>;tl_sk0G}I z6wE}5S5LUA0yTeQ?%@jR+mBTLHq7(0;qiE^z|*&c<UHuicLhUT0^n#%j!#s$eDtO;6{XjQ1O=aFWM=)1YN^ z9yr2f@FE@iu_!3mA&jXG1G~bJe$*8)00~`g{}Iq?yN#`6jopBz(1sg)N=NyYWM~`% zOcc#HcPoJZ<-3^-a42o3Da#UFhmFSz0c^GRAD)n&3biX2>oeaD< zn7cYBzyF*hUvB)R2NOVZmQ(~byV#w9>$_~z#^ zG+5=f}T>*;m5cUh=gADGac@}XJD~Fs2}bR zJD>}%csl$~}E(WI#O@SlG==#V#<+kjChqap71us$>QUU6m9xfO(KpW4^*N4y;ay*lW2#}3jyFm zWFB6HbupCX0VH4(OB%=nVL9stNo(|JZ7|Hynx*-8Ot!%)5Juu}I zY6Am}a~f7;0r0;WeYJ-0cmMi?bGXVHtSuwCctW%pzI)M6{IHm6i2?W4{?w@5=*X}N zR*veSjr?lqZDW@q7!8&cJdi=sKn@UQ-XAUC42xff;l;1>og3pIx&^5(Io!||l={ce z!lAtp&amibq$b6kRH{7lor>cR_*=f6;k^S)or8a5?_9-}ZhkPRjmMrpPZ7iF%22!m zozKQH)%9szy#S)4Y&}uBSR~2N{fLD-ou?xJburf{P_pj%;S>g3RN52HwBWc+fNH+e z+!EXTEw7p6WAnOg?e13@Slyd{Js9W+ml=4+;;B8R(q4pV6G$rhgdiXN4vpAgIF+a0 z8hRkBATYenRQvST%sj#Nk9pi9UZYopjBF*!o1)GB@Yn22Hm1D|z>`XDPj89zSEAmkIl0(wHrxg>I+e=^-xNZ)kfYa8C9*7mvv;l`GiA16{^ zjjv5#2X%zk1V5x|1>Vy76uaJ1Vor{**{HM`dHzqcWF+QOjO+!8y>PiERC#V=f-A1` z=iqBQ@p*$vF@2ob3%@J9SDvK^H^J@`g7`&<>uJu zJ1EY)It@PSl;3y>{~hn3GR@I}+Zo&1d<~ASzsh&Wu=`^HHdlm|-j<8qa{i}(gX)tY z_s&ma*{OZIZoZ+(;1c_fG0$G7JFK2a%}@M3ct=5I1ji~{G>=b1V!+$3E(j_a5O;xJ z!Q=5=oCvKm*!+%JE^7L{t)bBo#W4!BRKrgZ>8|h{g#7T!D~BJ+QYP|Xx%%^$PK}uK zi+#?XrLQ1ByVb(X*HZJasu3vkB&~YEFlDgzck9a}m9@qi$z+MvPt(tW!yYxdU5Pgz zoe2*vc-@l!1NGQgJ24+LgWZg-=^r)Y-w9g$NGX{>tR(Qr>8=}mO1Aa2nVP3u^4yn% zqviIoh8_s!b9Zyz!r0gIL-j-0%!136hmB$pe_ay;>2eHUYAOl8Hk ziOR*kA{fS+taia((gIge9S%q2usU>-UzBV1l_?WJc?QcgE4|45G#VQ5%lDQRv$VIR zm`Su`C3R*^^us?^4|<1(2WkB}D>RzdoW}-JsU*FD*nWFzJlk?E6i@y5e)KPuwwxqc zpq--rv;3_N2DWr4gI>Hf7!TSXvmOizRx{lizI=<_n_A4qb}Ri(hpMc@w>}QQ5>X;S z4zRK|x^M3R!$SEFSTeq$tEVaDr@N|95ghFJEGyL}XjQXZ9=6 z2SQ7A)S5-iM&n~lDE3w8%n*Ddy}=UKqONv`Kr;Lc*(&5~Oo4HKG*vE<|9y4EiDpNe zOa9Kyqod|C`&od;afCRtiCBXbA=!3uB&zzk&bUfntO)zn6KBT0L|`iwu)+1ytY3r2 zBZ(5gf#8Js4j_!XJcY+i!&tE;zqSwujn1y0;GXmpMcAa(ra<`+T4oA3cY9xi=n+<@`gIcS#eerzQi}OVby0@CNT! z4PT@`VeYFA_}mji2F!61-kLEeh(0OeFY0!_^9zY={jsqM6Wry1P-$eweRuKv6BgP2 zqP=aE7ulH>PxPUohI2%78+9<)1r_NGpnD>R@h-(`--X%DH2QNr%6D=sYEyMI(|Qj( zzEl~q5=g2oRLXQptiR&L8Kt6;r+*}H%x+n*Rp8bWtnUB49O67P?U|q@OEb%`HdY^j zp!?F#QC|PjubFW!Qh}Fk6)sdbcpe?(rSya&Zr&#^@{^!u#~`%5=pG;o)P4ZC6%cbN zXm+}u3_v5u2im}lv4!#TQuA$h|5`ozN#X5=kytUF!|Z~<@cTC`$WpmFYANm zks5e^NoCdIrY;VrK4gB*adawD6({3N>aoc&OtD<4;t~Hmb#ow02%kSR)}{3@QB0JG zd&+cYb82Z1HSCx@}6Lm;ZLzv!hl>q z><<@U2`)`Nu0dvveWrX#7e=I`dq+St3U5-Q3;C-dxS*WK!gepMOx{)D7OR8ZZZYI> z?eRapF6FleHY9`vKX~CP{mjnW>b#}|ofLdiN!cJ*wu6GmbMdX8)!A->(p^I2&4-Q- zvrIcEHL4|5 zHQ(sIp3}*;i@GqOq*JkZYS2tr=F`Jz?R)}#>2h>)lLnTTUEc(_Xv-+Yo#BP!k$giOEm7rn1wP4AL%rG=>5I?^0cA& z6KCHYQl&HUc~@SBq8mO!uiSnMFxfyGjO_+mBD;|q*4=v9YH^4wHYa&i6GMr^3gP<| zCGkq04&!I<_o8n?XfZYX+8$OXFH9z!Nt=7AZ=0uvJ|)Sp8!T~ZcMhCut$Q|AW9Zk1 z|M!VCj5R`gzTb{xR>$r&FY11p)F(+Bl+3dA>~apYP$v0s8rIK%@owU>%M|$Wep*I%g+d z950UYh#iuDT9@pOLTvCfostbsu)ck^!HhZ8hXS`>vXsNkH9x4}bad{Srtf!wyv*Tq ztEb>$w2}mVp%JV)u2^;}M~?9a=HA-xlEZdyoBQt(GT0p+b|-W4O*2TF0|7v~GjXzo z0>SN1d>XlQ_EfnomAH>zCwWgYM;bVZK52S7=B1j6S>O!_|NQ$!ps;PI-X#3PsQyRD zJi4elwr$Bg(47B~KGWBq@?RB2X6N^4mo*%AP^01`L_4yvAHq++6`x9|3XNOBm2bMqk2-=d4A62`LMe6AdFsN#C`#Gkj= zh~YsLcM>vX43>>Q;XLb1T}7u9W)(~<8$HeQ>znn!paedCy~LBPi+^R13OxT3lgnqX z=lpSFEfXfDbyEYiBmHk?Nh==Au_Ytc^whd--%pqZyNZVoK_t~x5_HS?lLAbbGRO2b zFdhlc+CE#hn2@I_tH?I(_3jFfN>ryG?~f3bwF3`(!g z?MPX7qkDLfiAKPJd!Zote!w|#k-KQ(^$Ab!Tjqy*)XI-@RcdA(RPJf<3>@`Z8nnIW zZ8C<1x3YKNn~#WN3r`Cudi0s-l`+%ft! z++GuX16>ywjB*%wAXL$0c5^(=%IY|JaJ*0N180*RvCqluM)gO|#U1!z05(Y^kOZ;} zHcQF_0Ak^KOK(0fq2o>}6ufeh7oLi=sTiH!{`2(B{UX~rVa17TN z_@i(HZ8^JWw)CXU>;Rh@M+V54j9sK$Sp>XdK5 zR(xsb{?2FkG2?ho6g%dxH9~=&q8AprM?LUyn`hSim0aH0r*< z8Eo1xhW9J_0r&f1ka>{_UC6XKj6DBJ8k|r+%tyA9QMLlgkPaGnkU~Z1YJJlsYnCaT zOmgZ0AkdHkL}C!5SfIMp0eu7yi_+ZzR~b^|0}HynJ4m!TL6Pn;U{U=W0~iOK>SnE0 z@(%i8siqFB@$7##v#+PJdO*k0$kw{$rt z!J%3#$W!&5K%2&*DewhG1 zT7-_U%BH!oI3yt<%6Co0J3BUTI$c~E}nG#*6S(P44Wa_g1;58R;K zK^Iv*Ac$Sr^G8eM`wY`u-C53Y3y?n}JOCVctyLbt8(zmz`(*4|@MriGx)?9?#L1Hg zBsG5bK(gtZ_T5Ys5^yEv*w}M(*;Tj^b*CvAD-55x;BGmqpL!HlJHHB}Y&9ki+oy*S z_*+qfl)pA~t>>ce^s31?`tEgG)S{V4`Y7>!sbG|OWM2yq%}xZF_lpZ?5~JRIs$n?T zN{ksNbh_wz+CQFM?kqQR?&st#)jUkjoAdwo z_5x3^QrQxSwofAsJREUw8m)}ud*jvM@}!D$MY!Ype~Vca%l=^ptC=gez&K7tJhH^OQ%?kZT=DDGG6yJ_1=3NeiW4<+Au^yaF zlXQ$qE8>k`j+Cq!C}N&Aom(Cav<_OfT(SO24|l>P{}~0gK*_KTk^FbZ)^{-eR|?-a zX5s)y>q6Y%z1c8;J`{JXM@y8f;1{z~VK8C30&X6C@F60WE$D`W1J8cQfxY=D1$i{D zJkB&^>^PsKJCV}j;*df_mi5`zinS&ESp~Tn3%+grk_JiVZus)~qERaz`P;mPy!-iY zU0rRSt@#fjCTD0Wnz)n>ie^rk!X;?MC!V-;E_fneOuNU4r~K0zKyXKmANbq|d*F3N z!UUnh*MaRRnwOh{vb^ zjVBmn^(J8NbeQEIHUJGe+T8J6BTw!J4MrxNd@-4Q{4a-w`TO?>(q4NXrFQg zl|g(sW9LBLefX!8P}nLEqI-d6Rtv)3t`bpssoRoU_v(lgn}5Zsty++BJEq)LYEpGF zQ%WW+BzHMy2s%H@xU;ku)Ml#Mgz_;=c>yx-pGRu`kkyM%ark%>Dunaz)0S4eZH0X! z(#Py}X|WLck8}x}dF`%o;K~p96(%p>urv80_+vA5!sjHc3&E71Z_r~uDi5`&hWXuP zgds*iRf#hyi{(#yDCL@L^T>}7Bi#mSw!utNbVPxmkpGaLgIjRB1FUU{h{&xUBnWAm z+!VV4kvvf|B(&~jHX5O@9nyYWLHQhwwOTp}RwiMXUeu#ubaPEr@RD(EGy-tFvk5wd21y#OI}8&nI9zx^A#}&y?t4n2;aE8;T{*t3-kG+02w- z>zoS#-D^jM^fQbm$rIb1Ovl`dxWF&PACF42+PB0hoRO7{%++ zJ~Il;>HKpgItkyrEU#51{t=*IG#vv9agH$Foj zbC~$9ThK|hchlGc_5gAb?ySs zlzcmy%qkHYxW$S-mfOdNg!F16AjlJ41R3OT95*<@g=vVkDdM4LbW(V8?Mp4bSBhsmP8j9hqX)fs(TV;57oP)4czzg&Q>^Eg26 zGbq?`P5|9RR31O%i}{|v`r^G%@gUH83_u*;9~%LSl^r{$WeXKA;40oJ!Vl;X^U8cF4TX-z%0dd zieEHg*u!TxVF{Z6ULRl-a+S4)Y~QB$w0XZ)3*BKvuZjdH=3kYStP)$DYR6++fnt5IyFFc4E%S~+oK(Ru0ahGEYDSdI}Ft-mxgihC-NXNHyVpg9A# zP9b{uTXpuf_-ibyKhM9rm(hn;#63BX`8Ic}(X`a^U`u8(-OuKgXR7o2(ey~-dsRlH zhIEm*I|EMQ?|gRKJ%qS*e!dRZ6t))$ndg6^A7$O3{-~uhoYBD^945av{;B+QeYXsv z_sEH7zrHy4shj4mGDU19uEi=sdf}|)GcWhjWi7#{Jh7Slv0u_(pGQW_Iq%b!cMrf| z9;6-)w`YmQUM%II7GJ$^I;r&IfW(!yHYj_I$9MS+><$w@j*7V46O>qRJ7N@ojSl5U zs_Mg6oYj~5*ob`Oaqv5HXl%XJ@rw)sbp}KoZw-r!}2!Mv2K>;bqvV-Mi4(_4_w@QGX zwL-ft;NHm{)dYGy$E-E1S%fV35Zc9p#@}c3r30RQ#>zH{*R-fWJsj)#qYF{_SI5D?Qt0i1Y z-NM*qtKbW>rV)Nk(@OHi@Nk(oRpD_|>qHJe;QS@a!VP;zAMU+!3_TzWm=aeU1g;i= z3-u!!=oJ~d6WB7tgCI_RNJ}>GN8=UV3;$~I5W~z1d^I@w$CrwD6~FFYhV2dYuScDq zc4zwcQR3Ud{inD)P^qC^qh+!kY7PGc%2N#PMcD3r;c6J`rJ*(Q@vkwwiWYKs?l?Mr zCOwi^D5yNfv~E6e`{E8)-1}5Clzk2zaygIuGw3jV$2O2jsW0lCGRF~sc6?te_jkid zH}nBmTeJvNvo)@OBQD7ufcM*PAr*ExIFLjGO%_v_UtjPO8u-ySO|km`caQ*VHLtn7 z=jYJ4k{>^;Ks3=bBCafwwj%k!Cn+ZdG=lT77&F+H`ZA;a;E8^S3xdsbBcq?K2Z4SE ze+~QhO(p^Ztb$K-3}C2XZK`AQUI~9I{3M4{kLT=&a|2<7^Onq;WZ)YnYxFgtkR3WC zw>p>hJP2j)EDc*d#dV}=>!9-*TWJtim#}ydOyqbU{Z;+e3UKuX**OlNa*hZ^0)@l& z5LmH%)Oyb0NBGeo`j>wjy?^Va3fevY{FeN`Oy)zN4a3?LbSfIN&X!ja0<3N+hNioX zJDZiq_?cwZFK~#_D`HnDFZ(uH-@c7LtoFsb zm99^vZg;D0DvZ6w+n*uAq`DFu203^uVXRsM$RNu@8Nr36!KRjJH|(UR(t4Md+qDS-(|i`}X|aa<)$5K2 zhU`>~x@&h$e+dmw2A{lWulbVLl4a(G2?!4t$U0E&wpb`O%79`ysD_s|Hgx*qExJK2 z>h9c5th?-10J<|6PokghJMQbP3(YlH+Og=6y5fV6faTd)g55EY-H(*;B0?o$>cun#-ITIms_ zqcmY!ng318K28+G_snGJH@ycCD6B>waNWRt_64M4mcB>4Xt0=Z>99T+-P*2xYIn9F zHX?eDrS2y$fd0pKIrTs&2^j1CQ_onGzS!>=EHpX&(FOG zW*?4ze;emkNpqX_`QE-LLo|1H!jQEAJ4ejAJB1+7 zspH#IyShZdPSZ`E`F+ezQ#-C+&$rR<4&CNJ_8srv^y$tU6k6Qx$`8-XhRqy`;>v?f zGVyM>Naf50S050VD-L-fED6Xl>i*67d`CdQO%yMmdqLbf133zBD;6lhUy200R19$a z*YpIJc|Zi@5OY^=9U&DIc>%oTGCqjHsr|S#i+cQ|#3sy3<+M8+gZOd;(v^Y5HBCk! zSqwm`;&hJf%Lvj9LS!-TUwk1dO64QewCm_Yqm$E~H)2Z(Eu?@5d_~n^m~j~2vjK7P zcRC8ZGsY1kAi!3%T(&GMxrm#P8~&!{H&_dKvG?OwN6ckk+am+a7QSo4!U`d)bd~UJ zQO%SwjRK9dzEpcAYoYj#nlit4H_1~!5@6o&)F6>d;s~q|Bjo~Qij+5@L2cPgtq7oM z{!#FysQS*$95wrdi<=n#@4p+>3~+gS!3kv+vH4DWm=*kGrc43`^IR>1hbYT@x4t!j z6~Fa9jbH~8r*`7$A%m-&C$wjiM{{zkV8U_Ff~Cl$^wz($ZAtpp%ws`)OamebK-^MyQ;?ru_z`<8 zNM)3LzJ6K@#~^FaaFDV75wO!=13pcGgkxlpomQNdgQ#deB`RO-L`sUNcpg7E;CfDj zY2-&ItmGHzsV!Zx{tq3`Tm67ZXFc-r31arODP8!|GreCO_{stTbo7szX?eYi)g2 z1JQc_K8}H#Am%{+asGpurVk8U!6?`9#0-F~gU;}zee!KfA+xKxRhmJ~Fnv6&QlXv@ zSs<_7f?;5!p9ZF2<^12rx6+-ZQ^sb>ReuAV-|f^k&o#F^HOh3VmhD60tt?5s{w+{Y z|HvimmgrM+vU0k*XBm6snxF*J8wQ65>BVJC`L8n;zM^Q>fN$L<&q@wq9Gy4>-U!Ip zwHYw{c60?$W30}(pEz>mCN?9E5cFm!_LOecXVQvnCYhJpqqSPC)~~Vwp;W*Lhe*W0 zM08wm2oa1XhLLCR)7SkUxp7K-8U)_=m=sFT)J3@i$Uwp$Saa6$WT5H-eh;wtbW1!v z1KLV4laF)R7#FpaZhh&2{Zv$OpHxX7RPRJKbO@a1KGJ)BK)0t5{DvcvYl4Jx3KFR_ zb?olby+m4ZOsb(%p3ci^HXLiCrcbMA2#IK|=NPWj<>rSNl1}5@F39kktn6u#krOC5 ztzL&Ju6(lXA+;w8iREqG7;+lgzqmL4@>2c{G4mZ}Dxcn=ZaQ3(a%U3RlEw`O(VH0A z9k|y0K0g#q%TjzsN@%YW^1x#ixV_RP`PMgRVco%5FdryMm<(FfU4;p}8v)tCS|DYw z7j(rI;uzuyeS zuC~y2wQd5W9mYpSp4EwUz-d;+YiGRgxixRTdYYvDA$xK-6%%BtGGlVH!mgJ5V_oFr z5KS-1Vq0u3*O&WZH)sq==V=HrG*5m#!5jpy%9PvtFKH{WeCOI<&#SRY&2`)$ZW$nF z={sc)Jy!RL(TqC3G?=1Ffp6!P%nfg{Hy+^)I=!@=P0hP zMq=fpAbR7ordGYBcmruKN+kZfrdJ9eOJ!yXiS*tbty9air=BJ}?633w_v2RlU*zaj zyilJ0DA}abcX^e*#4fLIis2U>Z8YQ%@4`u59vnNN{M>~c&(Hjwt#Ck-;C4A2P#4$; zT3)SB<66J3o>>h|s+%&i7Wti9>J|d zCYgg2Pl(n#$O>N4$fzXs%RcZ#81?{}mkdPjxWR1$8n&!M5g>iTVdykABF;DP!7$_O zQ#ZmAs=8|8$0Sb*)R%J52$?4%AALawdxI;grgT{TmyE!AkScC!Tk+wMg*!92^6%tb=RZ*5hGwGC zujdB_M!g0;WZk}}qreVodMG%AiCbef?*!_+2_w+C{cl@K-c&y`0&ppKTB(M`KhyD} zSSs}#sokH}>8Z_j^pvbO9e6Wch~#y%Q+_LDvG9@PwYn;nxh%li$~+UV1C&bgkom59dIOEPlZy|~ z+>2bkgqegiDV-SN`p>?Ci{!h^jkiEHGL7L7AenUiWS~w=eR1dw?mNJ$4`8)PLbhGL`(?2`Ovv5A7@|K{N(Vt)Y z)kde}%P0D)$CL5HT*F*;<6cwl#>;eU)(wihnS0~Pk8O`;rNnlnNK)_zovc*xsAdDK zX$&&b3!4aoAFl#6)~?7lE@gHB@waH1>x0LS=o%%hL+?ZSr#e=gUQKz`lr9TtEx zi5f$ixEX|K^H?18rl%)dB?7%N9%%Lm@=f0r}5q2rVCb(`S z=VgQ^Y{CS3w8sL+GN;Va$O(cl+C=#8S0Y zfEw(Pt6ksthG@8$_r~L&don&8AYbUM?>iti+5qhO5yGEjfQEe^EXEQYSGM8WiZd zocl=?(jrxI@i?4^y-+DjasX*^=~GNk+oC}E|<_+7|AWfiy(D`uK^%0nZB|5FXR z5h!btm<9X<&j2^r7Kk>fQo~jHT)XRs)$JI>dss20r`OSwvIu~cqi}i9F%$aKqv*IK zta178y*&&F#xvRctA8X2Au0GFA<%*8$$xpkco#OIv98O(zQ#E&o|sVW8Q}bb?D4h^ z>yD7kcvfsR(LLM&{T0RO)r(y4?r5#TtYl>b0UAHzPEQg)7gKQ5;VjLBeM?k8X8@Dn*acC3NI| znAU!OGfBCl3Iu*c=9xSct>sd2?Jt=M?>(;C^XWwKg3HXywfG$+`!3Y$$77jd%<@V8eHktDj(z(%Ez} z6pRPR9%bQsoEpmkM&h^<41mc8rq?UWwvg4AZGTW!)FdaoJ=oY6b;7-Mdwc3a9RjER1{E>l%5&q(X|UZkv_Ik3yGtTN8Sf?q-7vFCi2e)aRP4OI!1AoofZvlm8cR(-D6yiCC@?$wRDITg)c#c>H~F24=I$O-d~vc$)S-!BfZva=9Nt zSGVu^M-+-UlYOfPsgTTN)>tTqbgRoGUKPeHKhwC|(-3_>~|m-hz$Lnyl_p7cUM z6!7_bQRQotiu%KsE4-r2JC>!rZ4I}`l_nX#<5v7z0lQ@KCGREAqt#v#|M5R0Y-%_> z8g(jsEzspux}!cwY#9#rzs7Y)dVZ7A`x4~c5|}nJk6NOe9|Um87I~Zpzxqa{t!~{J zp7mtFK@auPj;YKM+Bf6^sb~3$&iG)~I^eq#v$ve`q?p#kCDn7g2VpIb4G;>63H0ur zO&8@FAY1_qQ<``7nhE1)oo66%9`o*3xax#uF*WnBR0}iL>9%h@cCI?RokcyFCaI6| z9b{BEkEY%#ednefn2Ilu0FXTN9J#Xc7s?#Zwby>8)I1x`0&uL~b)tYznf=q!w>f_? zsq*{k+|`(#TA(P8$`gI7GlS1^-=6(IoaKuTY&la`#UDR~BgOESa7BT)VPTo7wZrI74C7)fcfW*8#k2RH3r;?jXWUoG?RRgyt1vTvGrZsfT7tL6jBmg-6 zHpZEjVee0aEM|O1PjbbJz*$8$=3j2(-b?o{yRiz8!OQX9 zEWcO_0U9HWRP5A6#3j4q)3Ua;kEGp+lRvO&&z5}a`NkkrHCocOIUij8_D;>R4q8F1 zLV){##gBk3hZGMS9m*v7IHjl2xvPvb7*e@WW%Dmwrsk_=-Ks{`AE%jZp!XL_QiC5Z;Rh&720Vi+e}4tOJT<=G(*_BHiolO9UibG)y`_?2C;+#)AG3D#Rm_G zo4hvITJV(aY1^CNr{L}nZz5BwC~@v==RJYcayBQ)<6Vq)jkYDH=bW*QF6cnksAHui8Z22mwXL{Z^Gb@f9f2CckBa}KGXY|BK=3|X9qU7I(kI) zm*+5dEG2S1LCWo9+0|P z?-?@<_o3e3(m~JqkVn^HYR|G0X3hyD%K~sd;K`A?$9#E_-fq}gMx`pGWEgOrBs~|0 zluHiPJT_tCE2og!Mbp6KI4%7w{moi@J;*#3FWq(YPTogE(3=p+11n!?*K@Z(N}@jP z8N(}=%0N&K!bYG$r=WZt!M#vGlGa4v;P8eLO$utFF|P-10Rxe1`9Paf)@WL*{2v)p*rH{W?) zhx3kY^YHPDd3OKVNv!OrCXRa4$$iKHX+)X6WxyuqDmlKycHs^vtCjjl|E-kF zR1dFxhoXnEW`V&ocOD>*L+95>BB<8kpo+)UB}p%=B=AN%U&WaaoWT(!P_cbKjyP(nohKHIl0eItsfQf_kOg2E$_H_U@d9z9otZ;gU!0AQ8MFL1_6J8lOG+?&; zybmDYI76GIog>|3Sg)hY9T_?tyYCeu39AWN$QDwK@2DUWwHnQ%0P>WW-+4APf#xRF zO2}+b&tPyB@vl6WGv1;EZJ-gsF$Co}bQ1h=F2wpprx}$R*V#AVBul2+t641!y(1Kw zZ!g*hB1;{+5+~~fYHDX+x@j-Ii2c^vGT@cQhMwI6=FSDDTGPlixLGe=z2|Op+qxBp zSzhILDzZ+`)!Sap2uyg+Eij!?eTguQ{vW#DI~vaJ3mYCKN)RoC=)FYmy>~(M2tssG zqn9vxNeB^9ql8FwqW2+sCq#)bN)SdDZOqL5-Ja+7eBZm)x86T2#*F1Y=j?s$YhUN= zeXNBapRM6JWk}r?c(Z~Hw$wX~&hYNEb#krA&R1HzDd#1s%mOv7DRUbU!T@4xu;Q_) zJ24sXUC)2OG{Aq)%iZeG7$yJri0zv1yS|I_&z&R1aiF;yYy>Za0CEDC=1v3+gA^Kh zMk>8%q&ZKd%KaYg&R&r&$oS|7@GlBs>A0nm8z`~9k#b^Vq9DWOeKVGs_mbUwd;cC2 za@~J?1xL!vta-lY80X%Lv-%nDHnxu!6|wm_*rBo2UIZ`dnra1@xyXJ!Nu$_zs@8*kW#Pn|4{aJvlM^3Lsxv`^^_q{vLDb9Rj z*TP`!sclQ$?um^UXyI#p13>FBDR2zyyBChxUeE1XtI%8q>=mz`piU4_Us&u$`-Op21#!-~QQKeKP;5udMu?0sE_RhNbQuaQ8~n9(i~-dLZ}@RveaH z6Ml3I|Kc;Z0CPt1{(Q9Z9D=m=w!)olr@rCfnkP1M=lwdSSV6XfV(`TmFO#uwYK!6? z9R2<*bQ;?C4m`JB(9nCXYmaScJyX?gU)Ncqi-DvKPPwm+)L0vp%{UjFc>QK_J!za1 z(!kTPkMgfs38PGuJ+Uw>lzNcrb@D9iR!_l*y!X<wS{A z-I^-s;w@h=%rOyPws2CAwdn@g@1E6y5C&d?srXEiY-r$R`7qN>X3SWtf;q%#M$cJ- z;k$vlDViwg?WBJ zYLZ6X(C(eHkRuO66ssG$?0se=ALWBbuEgGEw(p#)bD4scvUzI+dGHn*I$)iT(mBK$ z&Tu_-W5T{X)}_97!Krp%8Ul;pt*muW6jXfk$%{iE$`eac);fU|g(_{B1FQ&^FBtz} zD0n1xfr3i{gcH@Q!+g9OMAZF21CX|2;3+8IX{{IXnU~rcav@&P#v4$1O{WNw;)b6m zBXh2G9!Ao!)>axzX=u@v`TEEJ$8u98UXJ5ivPu$PnyR|}6B`~tNLL%a<;#26eB;F` z=}dc0EjKGES=|Gbv=82(e=K(N%&U2Cc<#x4cMkh=yUdB6ymmVq?#IMd_BvU3o@gnk z!1TJ8`IY9LXQpDiJMYhMC7A(D{wqPNg@~o5ETcao{uwo>&+^8MK`~d2ue13?}1R zHzj?=Qzf|UsY4R?;dXp)K`>oc1KYapNO9btXoeIyhA99I)4bZIZ7?z;r*f?-GN2EC zSX263SU(OZDzgXTeV_Uxd6}vc@vS_VdZ9Bkoia*k% z>`KpJkp@8yG$|LR(Ebh^G6cNpGyA-Og|vIOCeWgBGv~Trp2!b>u26b9+eA*r9>K+` ztNcxk-uCV;>yp88IHSedPT?wY_gQp%YS}qoGXg z=}!HEDfJ|G>S^cgALiOqZ?11U5>nqrO#XKkpi+xs%umOn{UBQ=wV#Uga9wvu#6$e2 zyk>Qv({pPj63A^1dCV{$p}$Ep^esHUi}b2J7f1ZlGJ@FFrS{of$H*c+r8v~;LJ6}o z#3ExYhlmcWBitiYHy>50G@JWIO=1vzs4Um;z7XAMy`m5vNtA$yUXRPoPA=dZ62;Tm zap{)&RSBiWaQUg|H)5|^vhq@v*YQ0|qH`y$ai{D3hb6LuQ*=Mz)nPouK52P{t@J3o z2XrVbE+GsTgi86%EbfQfpi9A!jG)rsbTzs&Wj;!gJy-OYx=VRCSj8e=e@9eut>6;v*xyv;~|3F&$DB6Er3a@aT5uTxAq?1(7gQcWKud#$_I@LysyN#ek;>5^9HiX`Jq=gU9T!2n2UM|2XnEf@L2} z%~5xs75mBsobgUfyb_9d>_)DNcezHW42reE3_#UUb3-&~1h*o1THEcivM058E&08& z1vT^a!;*@h#&l8y0A=bn|E{R>6<>17J)^rNn*}lqm;yGi;gId}jZUelhai5o@R$+5 z0{RQ@=O*+eSc~_MuxH8qG_&f%jXY*@BnH?Npr|CCY<#USe{r@qrnn)c4q4z~w?z0A z))_!5^^g$Xv>DScuDg_1kF-)uE`erW#lfb_v8@_e-?Nl z{jIfS41ZUGDSLh}t)Jc7iF#k{8R%#;b8H!B^NL{VyYSVUZeDD-w;|fNi8dHm14Ni+6lNAQUKJNT3O4 zUVRv~m2uwpB?KR$wMTGxGCpUA^{Vp0+Ha1!5q~d#rTSt=JGTZOGcGrlXWd!@R3%Wk zqwU}=uKPyR8jgxe9J(hyOx=PF~;y*utf1}=nKH*O!pE3jzl zn~ONJ;Wtz=G#rOSmIZ)2Jq%zg!D*g+o4e{?e;&ic zIQ2TYR(CDd6bq;he3v97nrZsWuRwH6v&;dA?(jovEWthut=5>5Ohwc1X8V0q%I3;f zj(G{j?K4d^v&a>*1CQD;R$ac2a*@* zk=+#d5hNp8^<(FjTvo4`PGFDEmtN>$hyLg{;`woSVred=-%XwJ z!BR_;%&Hfm<|6S)>7c2~N*^O;h6(ejMr4N7EE!em5LTp^bQPY54rR=E8BE?NJgY>FlHkYAd*k za@WU$sBZqI>XdUa+UqK#b>4>uu?WYnB)Q3v^q<(^E>&NLPlxR5iuC_J@xLcG)5_M| z=~`UdMIWYBF;q6CW5FSL{YKx-Q5OHPg>T7o+VgO>5&Mghx%*&OZl$&KJmsr)2{^&Z z^Jz|C;!aJrMszv9Yr`fVgI(=Gi?$xY-HP)4Uvreg-M`ansAtb?&L(cLNnY~zJJ|wQIffGyc=U6M@gv8_M!2j1`CNh*TB9ryxoa~wFI*Zl261?5~j10&X) zw=LTc`wa%Jokp0!FJ!MVT(3J=Djd1>cI)>dvZ1nUv9sU4lSt9zmVVF>uhg-ZYqzk=!903 zR|Mts);rYX4|ilhejCn+tx4*R{`$K*eWw0MH<^F_Ju;(*FWX&vlA?%zgm5U1#rKSi z4B}19yw&mMSMJKffb5mfCrbMy2>A*eer6FeV)#~R@pzlW*#J)tGA2@Idrjysyc*CR z`7tGK((#I=YeYCorTh{WiS;SmWdg9m+>2U$Qpp_3_XNi>RpBlFZi#%Nu|@Gm0SWxh zP2MH9k*H#8V%r#}hOvO7pDucqJ(1xQ7}fmh6@RQ|{mW*O=;x28by3kAQ_W7+eXtGO zIT(*z4Td59*bWKHbKeS7A($P2YFyu4d#dNW z*H18P>Ygxu=UguF-JV!x-^7_YszNuz{pmQR?8G2b|6!N@)AsR8h! z_Y-{fQg|EDrA_JeZM3Ywz~~?NS31EW=%9oO1|LfmbNu4c27v=LnU&<`PhR<<;H!IIzrl>$=>m1>1%e- z1r;|(Pog;SdN+xjch#<0+0*^{QT=88(df~El3GZgj0%o*mTz%x{TlNl$3p>waS>po={7z$HI`1^T!&VPLHO#SHqpn7&F^@i$8Fbi6i zF?#Yl%%0AqAJ}?ZsEWQ|M+WYF(_IGE2)lbrVdvwh2j+}5GlN{PGz@s~%)b!|01Hr{ zV7s7azwh%c`~`%4#a~zsX8Hv71LtHRc(zMF%dEjlcs$>yirEKvUexH4VvYz|@R8Uk zY=gC4%g3BaZ-?l`vH34XC32{@dpsd9)DXRM5;&>XEu8Wx`#@lz?!hG1?^~jQHjj>L z4oR&-_M&dTK7UJ37x!tYICHvy44dK$+jE&`i(`2azvGN1`x*_q`yObYw+-bDNwy0E zzfcy{BbRUnp$P>11@$NcS_c`(-4%ghSXwni;b%66yy>6d0*8zz7!Cw}7&Ox0aa&#q zCr4jj0A*M;)c`3H1JI&Q->Pk@|JAjqDS_&ydfC_-NVpj7YkM+fbn}gh%s!Sp*_f-Z zuJ3-ma4;=1Zq7NB&(!b8S9wn=P{6k_Ve19{5<65Ydb8L(O+uzI~rvC_#zE$2AL_%n@{=YMR=Q0p$BP1ql&s>>J2~Y1jr| z(D_-#4*Y9mCivJS?=DFNWCs`zzHLvz>8?5aD!#05>>G@0auwvbb_{Wz9 zHjMj{bm9-W0Q8}aPIcrZ<;IG0T?~NMe`Mf>(ZbZn?jEWt7S5}`_UIdQuU}3QdX>1r zBwKrW-V8U}S`>twaM(uHQ%VA;TdQ|oHeeW>4MX`mD={$Hu2&ca1kE7Sl3AgIJ-R6# zR-+IPE=f?yHEhFfN)E75zj^$@Y{5@}`PBtLiwTa$*)s^=mpkM*gF@<&io0s~h!4uk zu#Gd!E7PTb{UzMr+|;6J$d{L<{t@Kd*j6K*e+2_|LnMdwqz>W zR;aN3tFJzCj_&IbyJ%-Vxh%LegO5js71JDe?orY}gu5LC!t$k01;6u89De(LR*yrK z7G=N_iR0FU&Qh#t{sl`sh^*>mw)~Z%ArnC5T@AJ@-qysKe=d~J;#lsr4hCWZmQ_jA zQM7=Tti$nq@jFd~)nO`wq0RomwL%R*9)+uwi}YesiY%=x@vhrA@w=!;O-g?3kN$hu z!enC(*wERi0&nEAUITTa%q&x#DCipugKrS}8eqb-!?u6L!U=V)OuyD2#=pv~`2qzn zit+RFfMz%VM_vFt7{g;&T3K$@#eF1JM=Itp%3X>=iWxrwKf3i2JAurff46NP7n?3~ zBivf(_&aTc_7?`arxv5lFEkoLn}A~?q)--S*sQCnB6QQnwhmkf$ zK+OQ`y>?7Gjql%@6<~4(;5dUlP5*UdtV1Ad`zyHJQtbzkXH9yuT(Dk-T#Z65zYmvy zHbexXFLIw^_H@8FOqF}_`=@N%!WG_Ma;~(}S6^&iw$Uu@9b%=LW)o>_jJ?AvcQq>@ ztUJ^tTOhg4Hz!;osIrczIEC!=TF#e2zH>)->nHf=*!Iz91r~c=PvB`|XG~wn+a;a! zzq9yKM*a9vYPWbH6Q0_iI}`Zs>8pap#9qw;TzLk`?0lx7;=qPN7&E~9eVTlQaj{GY zO(6s?8vdfT+83nQ57S>8z`FAu`atv)il-|F-aG?rTvP*B24F8t=sXMosGk7^N6_S@ zs$7hv?RWi(r!VD8P6*8A8Gg~C?tl$>B_nEwpm5UFbnno1*Jj2&dhm~6!T}*quY24O z(36!zVDl_rx2q77S;=C8QswG!Wo?s)Fw>ou5z7|e414KXmZIbsHrZJBBW?^B*=eVY z&_%o5`B0$ANIS@cuxVz?W?kr*KW`9xy;bBZ{uuQhT0Z!lm4B^{1o4hK?gfQ5k6cDczeq8&V?Wap>D`#~ zPq0?IZ)86&M4TX8gkX(JS7Pt6)l$tD=(w;5Az~a$vYf|CwdKMmZI~Vz-GB5Hb{hy= z1GJjc1+h*Cw-g#^6}GQ3bCpgvT_V9t1RtR6eTo;OORiCwYw$BzO~?vEmdfW$#%+B&yEicecCk9aCsq7Hbb1||=mA+KGg#jhCQi@1Xf7cVi z)Q9MYqw+0@i=X$ot3C0Vu_R>I@#02cD(%ZWg zRS@ORsL$y~0qra?Q*yf;#{M3kow`#;Ol;#W$M!XXpobg;3j!MN2EUoQC;HL~W;7+>9qzEdKUd`~;_0h$9}nG({~p?MSQQ!x{a&dY`VzyGsEeWt zM;*&gQa{0b`7Q5_e(hQfnEwDSJK;de>g!!-j!_k9B7!%!^*- z3TsHC38*xS;!}Ad|N9jouhBCpkojRnzU8F7`VTwRq=dl^j*-d_nbX`0&%O{Ed$!cA zC?#RJ%h7jWO-c@gd)#xH@lVuxmxWtocx3nDu2Xh7Tp(&OMZ56ytK6IylYGA8P&Lgj&Bq@N!f8K(7! zsUZ5s72#)x$iSPsp>8}AD6O#qzu%b9WEHf^5#BiRdP-0F&ZA!Fw0Aw5NXkn+!LM8n zTnfWmfC--o|8E&xLwnU92J=hxvRE#81Ew3c$&8`?{vO1k2|>iSGOOPTxLR`E%n>0VS(?T^(LXU+Ncat_D^D7G~UU`vJzz+QlLb z&_^jo2{;RHlm_aOsnfx`DwRE!5vvGmrPdX`1*Q7ehBzES;I%yY9M8WAPbQhTj~2_J z8{|%52NRmG!Sh(b5!g$t)bNgV-H2Q7(nszSr>w&YcqTz>kp;ZLuWG0i__Yl`gEDoA zfVj`#f&7MQ#{_ntC|at!Zq6~1`BB?hTpNxV?vt}XA~51zoC-yRYS~j}n?Ftn)8Bon zjrqgfDuw9WC0_irCudCm1jpNsz5b#02W`=x!MNH#r!N;uy`y9__-3AaL~0T#oc!@3 z`?xo|PeC&$nGUa^8s?+*X9e>|mN@1fp^{c=Q>Ni+{<{v5D>Co&*w-gL8Yh%o19PpY zu!j9yU)-mCR!bcG^#>+L>W~z>>ayw$6Fjt!#z*mfnlv|gcu;#JcZ4+67k5hz2@REd zIB6>#I=NCro3F}XVy6d)lSzo5dF{KulglW@BHlO<<~OQ6xMZHBy?bXl~J^$UM7+iDFr z>-$DeMZc`U#gJN%|F{d&CZKp32;LODsCbcChXy8X0CAKc?COOE7mlxCrjHMj4_MUEg`+|FU#G$q;Vpi4q}!YC5J$nm}fIDobZfo z^7>uCSSo$SW_=X9_>3cAm7&N~+ACgvU9%LopC7PX2o*+;^m*UsoCaULeB8f@w6A*W zrb<8)G-c~snee`dU+yF4Baz104_W1_7rms45I!vC-{t|Iikv8hT?#FnvI6UD2!g4lr;CSVJOU$oX)ve}!{6ZA2JGwqg=k zA8Unv{kjb1Qa95J2h2x-U8Fg}e4NJJ;5PP(rx%2s#q~H;QbT~kCHUTjC=H@{yji$A zeX=5@ui$E@0D0A~BJSb3I3iBQESoKss4`N`s!=74r3bIuRrer_oVpuy|3t3cQ5z?= zyn_NeYo8Xn8h{{+k||#9i%xvzTxC)>n5Pd2BzIC_uON^o}0R2OXd3`wyM^RonLkA~U3&1jL_BMg_NlYsY#5tR*?PE9C zdEhZ-WuqDO+hCRHa=4(|2L0Zqp9!N1ocuY3$3S;%F8AL}Vs>j#yY6Atfd5VO162m} zHp+nH)Y8d2jbpp5niBIE`EK%$&FJ0E*>+KQ0fD>x+b`-yA3y0AjB`Txo864fPJK6$ ztVYacIA|9#TqB)Y2~YW1Qw8#0*Daqj{NyRV`}`e;RHO6QNV>z@!9wNQhtUFOHH|Lc zRal9maeoL5JYSm}?A0K!OXb6)&fkV~S7H_O{k^R<2LvGgz8vi~xSIT0c$+}v$)gxY z<5Dg=%V;wSF>eul+_xhd^%iqgQxGlOqN5npyneW%)0Me~-cmqs#T7KPy%AG4_3LG? zpxz3AgJr0fLs_5xCXms!th~`@JoNxZVko*H2}ZF zkrKv$^R|3R3T!AQ!u~?hx5G!hFodY40`%Y!408obg8!w2VZk<<0pf7f*FoTt2yCCA zXshLVvRDJ;!J6yQ|Dr<>6{aQ@0oyE?d5Cc~sqt7)Q~Tq|FmP?KHyYE}?_(Fi&Jy~u zWBb94sV^ds^oY;w4qD2#(9T z350C=^U-wU+aINxso588X-OV?>1_(%cTgqp3EzLu6w^m|*P%0lg(G`HMkZb>faFyk zUz@ahl1Y-HqX*Yp_oZG8}iH97xpgpVoGk2HzRg1zy`tBaPC z5K(dIwNzIC465O8z%}aK^m3y|8V z75M4oDhz21i-4Uxfcl;+8r~RYHAw8Cq3ESpX&^cccg}}jSl@7O^Oay!rDhN}2Of_o zbK!7CI4gFvrSrUv$XS|h(H=W{a4D?;v-3(yl!~^-&!~(Kk2^_5-*nf#7)pH{*!$Ia zcC%K`S$}v=uvSK@;N5kRu$JQdc5fyL**s`$F@vDp0 z7Y&|DPNyB4)Q4<%<+n^oujIGKpgMI_t$brYLj)zw@Ai~DcX(Yf&E$$HzG|K+cnzh! z;@y{YbDtdysFbNNSGqO~>~34`dhl=LfS&zy8Uf;9C{Tle_t;!+ z0(7uTU04$AtQm6$Q>A#+eyj<|U+w)flQp}}*Q@`;XEf#zx&8c{>CrY+Digm+GlpMX zvVPHE3sACeFdB7~$B|LG@8aTwwvPRER5hVc5YjN*7;_4mcxu zlR###bWc|3ap0G491aDLSaEs zDd@K-uS1*5epm#s4!bHiB7!0XS5ttmieRr4IOYQEVz&duz;Pg$KIl1IUjgX1L2fSk zPWGI6-2~~IsbV^{nWU(C70p=y(Ssa*d}}QXvbqe(Qn$g z*f5kOpLi-qYBAzZoF(gg82-Z%=Gpn_Xs)U>g;Cr2iQ@0Y*X+hls>B}8Vw^lw2I$LF zLhPsqVg3XTuM-)Cb_E_jxQ|pgbfS!MXJWLUvi52UMU?KG_j8rRbTN_Hr|;4?lUN^O&(}3 zO?e=f?FQA8zWFUMP4?I}-vXIPjny5NrV$YyAb4vf0V+FqCn+=~;)6*ti<$Q32iDHs zb?W3>vaiP7AamIV@sW<(^g65w-EHqiG&)P%20e1x-;8*n)oY1;f)#DBx823-Wg;u+?2>D4@U_MMrjP|RRckKFN=G&)&Am!J$M>Cqnm$B9<|4DFu0r3=`sGZ( z>hN;iZ$h~ZT$6CRR)=AQ?+npp3T~grUbt?WK4pq{r@$uQMmj*|H~lDA;`S#NmcG>M z>D{}>qkg+ItV&F&F4i$pA$g6|$MzESnA9c6=(oZ{8P+HP)|dpt!DlFqteoZnT-Oe| zi>CI;B2D2bq%|Ts^m6d^DG<<(RSVwn@_jqynqtbI{P0j5c&3a=SyPO^CIZz)^_s(c+KyPR-^*pdVn6G+z2GuswWM4GRqrn{H;5!?>$3x*@sa= z6Mi>M)3?JE6?HQS?mAy--Yeh{hw(w@7sakms;W*zM%H<>>&>NyUvTj zT2$T{28A2wH@SB4>-k8f7XQ2h;`d!Q>C|GK6)@QkLqPw2JA?n5KKwHQK*cH&uxi14 z@!EbvuKoRun7AWd>Zf#wKr0uXy;hRIo4++@q9g93DY>rAxAtKnB;Ad^nS+KCbApqL zxu>^ShYO87^1JH}x8$T}=(L>4MuIsOn^!U@2ez_fZEdHRQ?u%gRn_&kzSic&{64ju zkNnoQz!=R+KzSVsXN!wiTH=>I{kUFz^o$pQ1)+f0@vripJcicmTjnP`4IY-2vw7Kz z{c19d7GvMHv_#^n)gI!;M^_yVUfvg!zWf1CD0RLtNFQ80y%*KM{7n`;ltTV3eJ*}7j;rLMpf|HhlJ?bw!vIo1uJ@Uu= z{Np3MJ>FVyF%IdV|Nb_TfS^fKDB4fggM=J15-^5)_q(YJr`+`2%sN5*?IZ=I1Yy>` zh^~2c9&v?~kN(PB34q1e|eJ8q(MDo3L*2IAKsshY0k75}stVR-hUl1Z)mfOr~ ze&Bfgh+Mwn&*}N{qSW&TZ4imvzy4R5lkx0sf(rrQ zkPJg55-MTgoP1~`e{zAZ-6S4h_gUW9nqgp&5OynCnJ;lzL}s?g0qDi~jA8U@-an!A zyWUqlcDWYtp2(yP<|=%lNI@Q@ZwiX~-V)0#gGlRg1@HW9v<_;N;MFY@4faF|y2?To zU)M2$P`EE`HV_l|?d%YB2u^j|>DY<+y3HyQwk{`n{T`fno4|Yvj1G#(3NZiR>;$6# zJq|G;I%<;$jYPnzF1lvlUV1Wr>n36-4Aw3x(S(}swcnF{O?<5%YMYi^RiIHpoaQ(w z8_}Bm{F<+}pTXnRHjP@{xcF{aQ>NIO6ch1;vAcaL&q8Jba67dM%YwJA`wHCgw`f|^ zUo_V@sSVj|#k&nWUSl%&rif+rxpbSnY;e}^kNY*N%H13{re5IZ@rF0r26rA%Zo#Bj zZvIb5&>c+aJ%f^40r+c3MbGzOoQL|WK1WX$kpBsmz}PYnlzz>Fe0sUl+bz`2J+GbW zypNUZb4@OFz>T|19Wwh>P3D%^(8f5)!S0yvf!Ct{;#K1L(h)hs^pd=ARz<;N|Ab})Q_`_* zjHAAEn9+&X9Yn^%&$ZahKOeiTkpbHwQOuJCTuw2NajiqG@^J6L=D(wHg05L7fN+}h z%B3)%w1ZH8$qpcIDfu-%J=S!4quCg)0QiDoivqMbkF*LaV7?n9Xf2qUX6(e7d!ym6&F2(x z-o1o#Z9lq|VP4@3B+DGTIzcj)Bet9Y`3G08S09KjIFG#DgLx?Gv%mgPeSkSl42+=o z=JbfrQ-y9|_!+5I%3g+&~xGQ3n!k<7SNB>oLG)<6z8`W+tv4 z@nTxZGp$fO?#m4h4C+n;g|DFlG^ft5)mJ>`!xrkr(cj+Z4rW+bZCqr{$cX~h_pnmm z)J^}{n}ig5YTmj0g8a>hnFpB;=ol%pzmZ;}PZYQQ2ZDqD|6fD>>SIbKgNPp^M!TG| z4kJ}XAxz)z>S95SxSyyz0P>V0q`ev$wWxp5fA@QUaO-$c4KqR6{zXILoB&m&99net zUGtfv$XCLeV9;510r*~DNmTNS>m!ZqZ#c+SQ-MB^j)PN%QFC>6V(40 zPjCxHP;8S76fyzBAJqUQXtbbBKLokWRto|kzsZ?2O`%a3$rpS85hR$pV!QV z)k}x%^8CF#;xcy)WsgW#5nbt6A|aEV>$+0zHUPT~(9gS5u48RAFL5 zv=Fn#c;nOEUXQp;=3=>CA+d>tpuV?unKF)^k2ciWD{0!(X|+^U5}r8+U-*Ci(Yft3 zbz-B?NRgihUHS2SQaN8?T*N~@CS?N(1po7Zu)3ZzD5(|T4EjGlxPuLv9iJ6&0pbz8 zH@W~cKA*A1U73?`tDiKQn?>(Xh~g3UNRR*_5$zTgZB#vyyIu?4_rWR-KtoOG?o%Tjg1faXG;qQsp2zwa{`m_r!fxWG ziBN~?zxT-^SV)3r*Z24FgzU9==q7FRq8=1uMfyqR-*;27ER{}C6lU8Y^~Dy=*~ym^ z0QjDJE#+}2K82?Ogv*TcaD7Pa-c}^jDh?;+8QC##6rie8Ir)=P$%E{U z8iBA*H;qmJV}k?Tcn9w$i4`@ic+aH#HovT5>~$_sy2h%TiL>}NK7Fdc#k=RlG!6Qq zt;hGIp!^{BT+dG9!%qDq9XfY~Cu^L9aTMtMhn`#htI31$9ry&oVDrCHNv00qaw8`d z``D-f_6uVQ_ql*6vp(W%5}ow0n4z?mLD4UvY2l&AAk!Q9yrd-$=#bf2b z&aeY8>^%t|5%Y{U{P1<0}%XIk$&=9RrAsBk~%t;Jt4Jx;W&%_6b)Y1@l0^IfwUAk%RmH8R6_nItL!&& zomk%B@eMN(DWkzgC?t!J;Yj5E5 zWeWz(NCMG^J-R#4&mp6h{&{024Zq<|hB>Vy!nQPc5ePo2!@1J^gQcv;B*Z3E`l9_* z3Lxi*`6;&WjK*)9K6o$FPk7XU$axDfHxs;J1)P<^MAAh5_yWRs#L+*Nd^ z=Dhl^Hi1LC*^6l0$m-s6565E6DE*rKWkFW;FG_arhnMEgJD%dek76vINc#n^4V*{6 z;(9{fy;7#`M;{Lc`dPSZU z15*LTY)tMhp@=sB<_A+9*YErlv0rO-W!{mQY&Q{9;WTVnt_vc%M7};eZEygZ#F=s+ zd&WjObf3W*$}Dl~Rol=AlF4hAe;d(lJdhmNC%xp-C+{(F8#QBsEMza)q_Sv@@& zSZ%nwjCb8f8_A27s#L%44}P>b|3qY(pNLa`p3?4DY&Cp2icoU=t#kQ)530xxNm9a! zbSU>#B;Nm4CZ5M6Cv@}}wvi=ARlp z(0k9<6Jl!w*ZRq%#?0CIVz0r`{aQZ!)CJRCtsMlXT-?*3Q&oC|@i5_b$IYsE6kq7j z#!1^LhVjs3w?V&4!0uF~eFa(5{oHN@wUsR1 zEgi8spYEG&r}Jt~-wvK{(X{(7zOSCD?Tve~QT^P%)B)B<+#zNp5P z9oV+XeXSU@;C2j{4nD5RSV!7aj-0`*_Ws9|{zYcS2f7ZNvOUBE&TFZQ#!!`n9Zew%% z?Au-Kgt}Zmx2o?bEGEhj$zu{{&9apwTzQpW9wq~1nr10WwmR+yReGsvyvk`HGAfxGROCCiS&i6!b<`@Oea13`y#1+I zqogB5Ouw25zX6GsM}Zs7;FN)4c*m>zc&5uVq& z3L+DjSbHGcuwo@*>a^lUdeg8L4iopLlNfZBrT;Sd; z^vsz$LyIrmSTB5|&TQjXTaKQ)Fi?pUcr@hUC4=;I&lJ_i{(gAfT2SR6Z%*L&VxeK> zrIYES4H~ztAIjLA?$1Z6QzkRD&!H=8r4D)1RU7g2~>65IK4?%K-p zVny3shNc$B=FPu3CXDX?_7gzP#67(H3R<*x9SdL|8!kDvTDft}?Z5A1+J3{HCN5mU zTs@)iX2-OnojXo}8xsmWXx`FwnKhZvFniSV_#`EP+QnfO?V`xw@viSWY?`Xmtp;B+l4^yl1cTKOE(M!TZMdp#1-YH$|sC#^xT7 z$<&-GIt26c%lh_itUPcM`lK&`xo4HpO3zyKJkDOhzId8wb0W;AkQ+}4cDNnxCLzeR z{>Z9q;_3a5w@zul`*;elIM1BcuLnHk7vVcwdm_Xw@X*8w_szSA#Yoe=W`QDs=4=fa zv+E&jUqbDtW|Qr{!E;b6CjmVM&j;R&gB_P{p@Z8$sgKpVtJ*iqhR^&ZVl9wjn@S|< z9-X<|9|WED?^PMzx~F>gP6Rz}uv|#PufE;>*+rg5U4(qMBHI9j?RVtW#wET3`{vxT zz?MzrFJGM6)0OL|lvfDU()qT;avS3~FB^BU%zj+;_LHe(mfxBWY&RvRz0m`TuYgi5 zN{s*Wp#3l7X9Z*bLDPR!$NyhGPz~@{0Y9W$fu%FLT)9~RUz!Mg@G?2B!>zng`t0g} z0kZN9*(F8$p1-~Jj+>eh<_1M?Z39i%myKfz@?y4sy_ktQ-&FZQto{Em_LpH%zTMj} zJfxJggpvXxg0wUYAR^seLx+^Kh%g`_NH<8TAks*K$bfVs-5tWv9mAZ@$?v+Z|9!pp zy}kGId|~5^53`QrSZnQTUvcs(k!!q{E-P1(@-{87c0+3GvKe!9T_v*#@460_4T*d{ zwTY6+X@xlqyOhitb3HvJweCIfTMQ0AXq&xTE9s^EBzYv=WDyg#J~N^#Y7Z8@=irmM)pl12Hu3)o_}_07VL0XO{-m{=er(>Td;T zw9xzzX@oS_0SQxk8Y4x;(kH9#!Hj^}-bTq?&TDceWUvYXTLSAp01%|Lz-13b!gW@v z@vDSDHY?*lR1ZjixmcdAnBDlW$w+bsXf0M}UqQa^u?MjR)$r65vYd~Y=yb2|yfB^E z(Y-?vcxV@JRS=N0Xh3#6yU+7zOXf?4E#jq_mNlUlZMsLxxLW0YYE^XjSTQ z6dS1+tElcHNbOwYV5$j%6CEc2UH<**Z}SGIj4vW`dQm_19b22$KO*rcH-h2X z<5m~!MVFIuZ>>(sYzGZ0uFphdL|UP3?;6$-*$dg1n{FXf@X_+}8UM;=ruz>2_#kv# zO(U#F`?P`!QUY?X$|<*bRh%-QfgikheZxbu^$(PUNdtN60cw3t-c=&fZF!&Ba|aNS;7_zHNsI{ z;E$vh6nIoj?yS>M!nxqb^&&w1oS!ByNFx8UwX%vH+FdK?OGjDlxah_lWTp{MS`zZGG1IZ1yh zY9Odr2Xm+YaGKiVK~`k|3n+}~-qm8!;3>i~`kyDajygvJ=({n#9(1Fx^rvBB10Zu{Li1o&WyRyn&kJ2la9mKC^`(lxua;ajy-$QXj z@0hz&nD@-h3eL|fI=pJj<8qqa`mQdi&(H(ybgLaBE7C0P z`P=&SH5uS*F>5=vFEQu~Ee_ksN;y@z=j1^E;35JucT+*5FbYA}p2D*k^@$bDJpa z-dO{zhmDe>#_UTykprI!a0DGjbS(sEWG3}!Mk+Y*=8&uM-7v219s-)UD_J+^$d|bm5kK`6aYxlslJ& zqt;k6JL{?kg%whf0q^9^>#_V28>qTCc;giZlp!_L9qtVF0WqyPPMIB*c3^r0F)0Ni zVPGjV8KiV2sTyxp1!|Xvgp-v4ZmM0oxAY{5nE~zQ)uPpBB(S`+{gP-ld92FtON9PJ zQ4`)SQOo=dOAmBQ!#T-o&$M5)SX7tldFa788Mb7Z?s9 zY)-|&5}2SeAU>iDxQpDWL&9IWy}r@!ye(x1@dYDX>t3B+77~H-x|K2Ibv~L6?jz(T z(zqwRUP~vvqIF$#k6qP?BCxuEZmUP)o2Kw90b_sif~H)N7O$za%4)98rmA1FttR=*NG4|7eDUIZ0K2qQh_UDHG#-pXK1yKDR#>^+8VJ#?P|x zQzmniGBWWDp*rsRd@o&>kRbeZ9Q;S5+p^BOAL0ch?&q3h-RH}PFL};j2~be`4Jv%c zZWA;h6Ha6TaNfGAS?X(^9>#jKFxQmCHmFgcg#felfTYMsU(=EIOHrl3ONey0`oi{V z>zHS+8_8e!XPCnT_DMZ8tge^IL-FiEsXyyN3ZByCh6@p}ZdJEOnPKrejVJ$~5L=+Qs3 zP`kdIbeO1RLs3o8%+9lj`)4rSJe!I>y7f)vpv{A&AmJNw;O5=ha+v7ADWdqxhV>*s z@DCaW>c)XTa>DwEW4oXJ-=Bn>s8b1hCMF6FjMA?)8%zA2ogdff_h3{T%Hcd#fcKk; zaO*$|GIQ60EvJ6pkJN6R>`F6~_wb&1-tfrHT&-KX%ql7&$d1eoY?=s^{{GI^$xK_3 zzP%JB#WvhOC@pkFD!9e@d&<_$G^DGE=^X#?%RbISqF4L#t%z1p^wZZ`EmCNFrf+ly zA@D&PB?xgZ95W&Ph3J;*_hy=dvA2X=b{7S&B`V6oc3HTk12tf&Q&iGHfhYedZMr?8 zh56UF#O!|of2e*t%Lz|E_~n`GetXIHt$0)CV_X=+bMV8X-p{?O172~{ny*8JFziG1 z4LjWO8N;&tiApjHZrVP{BfKfi2V2O-zp@tDpBS{!L?z+U{K;#TY$qP(_~~2vy!P#9 z4CZGx&scDxExH|5rm8KCzOAn^zpP>0R5WkqGynK5_rW^7(gc_?-;SeT*RP2c!)$Nv0*&D%J zrP=IA5PO<}s;HHPgkQ@3drNP-L;fjmf^&n&!+V_&iQtBJyuy{A89p}L5z|ur{bqxi zIpplu`0J#&Oh|QKfBF&3z{-}OzzPWrWGM@jbIa`6Ike`B_D?en;~HluaXw0V`n^lW zlTc1tNt*ik=!*zG^7=7lCJpIkjtX?;pReuwDoH*)f2?X}Rj9EV%SKJ@A#&yl!8`Ig zv+9-C6s~xmDU!EzV* zRdxK^I;*QGiSYi6->zvf#aY$oYEPm*PVc4*5fYJyQZ?;7Ih6tY$Qu zEcGui7$GOO1Y>bD__A?u93zkIzi;?S6J>10)8(%#+kVGB3pz|xf zZv{|U3in%1ISAb_vJ&Yw^4u*Y@M0=jVo9p z0%q+%H~>1*bWp90c^c5dV8)T~79lX)luz^dyttVbS(Jz1W<8tkz?+cTR05Li$|fA~ z*9?vAJ&!)M68=59G@5eymP9LxU+=WxVfiy>=&P*+B2VRv1lpu{ih;Kr2BuZ2DCi9D zK%^J?t-0q^-oj5Xz+rkKArJzvE&A^@ww~Ruc^8FX7pyWsao)Y^uVsIbbL8<$uS>G< zyCj~0BpW&Qg-^xb1yX|?yF|w|4M4pT&)g20om+Ke#Fzvgf>HqUpfv_1qALS>btZvR z5LT`vpTNtJ(TPF)83}I4#&_~jG6_X&4}8BT3gXm3BsI!E)Kkc?KN@QIQ-ZTv7(Qvi zeJBFBMbA&Xi+jmW^Zfp6q!?+Sg@WkuV&U`fma|j?_09Y%sPT{ms!G@L*}Ql@wmhwk zlEf*_`@L^;*4q`+&uToWZ4w>T+E4+X|2V%#S<#u30Pn)#OguAur-3(88uV2>Se?+< zVE{YEGdR`ZEvTFYU;no#w}q3@quCMgNx0vD!@sJ-Cjt5^c!+R8(hzJ#Tl zM!{R4ci=N4L1csW1_%1;HaDK%9UqN{l0Cbu?ktUgOT0?j!n&x-fUu{SF72NN^}}fg z#Crj4i(TcwEkF~!eFf0n{v_NHOy#UNo_u5VZq26F-+5yZ=gH?j?Uy2-C z#62~mFG+;~WuJ00o~Zp4gE;NM|(WXG&4>x(QE z>Pq*pHSqSHDI0sVk|2*}rl*tqR3*T770@jlXgtXr0#WM|kim!0aE@v~NeQh7X9oLH z*RZGyx5-c$cQlv+t!KQOUzKCO+;p=%X^V4(fW0j5*wC95=G2oPQs1{wfEBnoLCD1? zbB+er6Q_%2=k4I?+bvzy5uD$jX!g3Po0Q}OH-NStUHbc1SdFVGunPVj!*+3$IlfD|Kl6=dt;!7RTvI#UhHoU`?=kTUu-V+xv|k&X6+7D7 z=tHxl7GP$UHx zU0diPf+oR`{?0&Abm?BCliMxaf|m+T0_kA2Y9E+v)ZGKMWzjVf35b{gj`f(XFAg66-hyRBeIX5jmS48fX14V$(zjlmDSdJ)BYpiD~kVtcugy!>zy&M|um{n2#_$Nb0MfpHL<37|^$?+fr~ z93e`~q%&L^100ADX+e46LtXzj54#t`+u0}QkstB&lTUtRUf(w? zxf`*1YJxnea|D@!{!9xkdrN+uanF7k1kH^k! zJ1iz5327==G#>MpeLqjW?Beq$X#6F?jT~#cZ|hGg@1_F^l{FIhfXQN1T0D*UL`J}q zWygNRQ_P+p@p7CjX|Ye)qTGlrHII~mB64#qfE_Z>whE__3!zQBC)n?Km@Sj^oB-6N2nQxm%Hnh2a zC6fp1pXj`;su1Fce8kRUwV$Ol^aDrKDk_{gaQHK$_1caO`I|o_&gj;bif*WM5*U4k zNLw%hbsquJ%A6W0rnFV4Zfh7aCPPp3IAXzI!v%f%!Xs1aXd|aM4#GjW?*iJ2Iid(|79@-v*`rFLUjl4t75QuUJ(pt9<{otBu>P(2+ovBO+v+sxI|x zPoqi0D|rkp%M(0r9x~QVXM}+%D!m9X6oX0r&59Obmv(vrhqlW)*%HlT*HMX_Kay0~ zpLU>RVF8fPT>4VuK;&aWM|}*jWPM{xT0bHpb14?Y8s(#_Pdb+-&&7KFj<{Yd-;J<2 zoLqsgdJoq5ZEdvlD?EP^X*M`5>9cEM9Md)bg4F5Sc^MiO7!Y?#YZ+HMWEDl|B^3yt zF#q`*D)5!Dq~L>tddwh@yLWozth zPEGvdAr-n~PYDc>Rr`ecIXmvvnY0R>?5D4$JL2px`Dx@ZGI0mSYDdNN^AWG5vrAJO z(+t;&BdaT)WJBoZ<9C`>&*>)Z&J2$DXFHF_m4|6XN5UB&CYVN$$5LHM6p4t#Ucygw zp$09phIv_aLb9Ih2D_NnS3Vm#7zEgR1FoC$L3#vPtyDmYFXOT6bbt=Sn-F++wTpRPo1F^-~!^wO(x zs!GZq)8T7Mye_6nc)P9%>$g5GPV^9MGIDhxJyVRO&ip$^B<-~$%}Q%;PhRop?9Jx_ z9tK#t;4!x)p{$12dzCC}U&@OTtS5$T!`x-BWDx0Zi`F*H%l$j=9r}KJgxC7*yGy(7 z&ur!uDr2YWLO~T5su!p({>86in)3dj5v?SCao<|b28OY_xQff=^N~UMIc+?CFWg^o z0D7!g{xcAc#KtEtZ%0VD-xA+ox!PTPX8BC^Q?aRVlcG!YA+Q(&NWv(CJC-5gnE!+S zZ@1Ve3JGw4#R@t6OIkPkRaR)$umLou|EogHhif(WBclARN9wt;+1R_WvE9O*IiJL^ zSf1+$6Nq(qi;y^B-RT=lBz@l3=YlHPe|9yWUqUS6D6mC%% zb$gErepsK3{vI>qEM|zGda6+g<*yM93kSX9?`$FQ#Nr&k_th$;DV45SD%Ulpu1D1~ zHB$cO6N@6Y8%_DYaPl8@3p_#lyq)=lntj}AbjZ_&FoBQ8-vcr0607+Ac@K{U%!ob( zu#M<8CxQ4ec?#7=^?`LpbwmHgzqdi`oqzrZ9Jk;(%*uB8%rfK+y$D+;tk9-GrYcm? z9FGmDtD`FqH#wcdX3j=VEaZX@~Dxt>wchB^AQKC;3Hg~ zsbPz_EztNv?vQiD?zW){R8QzFS$-Rxll*rHIF<*hFQylXKY3|Y>F1r^k)8RI(^XjgKWMsMIQ;4xj)rg!q@{6S>_iD$f~m?O?CXJi%+Ns z7OszotTW^HaQ2n*s=k+2D+zkOCvQFHiWC(y8((OwcLR$WUFyyUyMkfe);g>>+7}mDjEYkKQv4%5DsQ ze74fv&4Vqx5=-{{)80}wwLZ3*a?72BtneexzodH;*{T@o96e%$V)s2G$?|?8iG*aU z1@Fs^5BYcE2`(9EsJ(qGH+{qYR0Kk%i@GByyp$}K1$d#gmF`oNExz&}FUuP}Tm~^H z*z$(B-84|1LFm#|j>#S>=kYAqAOXJ%_AHYK0*UIY+deqlll|<#L(6dA=W#3sed&W) z;&Ag%WP@nAzHF}mYI9Z8c(|OeJQJViVc*?0lF4##UZVC2KfS&{ZZ5r7f-2ekpPRhX zHMy_D@^KD}=N|zj()MOjF1#e)_;Y>>7DgFrj2eCxJX310xBBb;osbrO0*hzd(N38{ z*rIVn&x^j9a00o}b5aCA`>eMp069B^5@Ct3d1i&Ac9jvz(u_c6&*m?|E^bpGCvphv z+XEUdoc=EtFc|<60_P1^j5KMGO@v2`>laBRN}N4VV*|=sRq`)cimt3bCT0XCt>xg$ z0IB`ZLJciU$Fq2O+=IWTg(18w>UI5Vv&<|G>qZZm413?)l@G|iDs+F?Bk1#k;xNYr zZ?EAs84+2LB(=Jq+z$w?P5jv`u|~q1r!ukOw_|MFWEV;PF8XQYHa!@O3flbK(Zek_ zcYtYr6j0_)7~{9CG>CZRoB`hmIS**LO&O9NsVR8fB(r65iblOOWLonPAlyDKu z-2vyf68{1%CEWF&TeqX3G|_f_l(yWlXZ*^|k)Ca_i2{HWrX13t;(08Dx{Ji69jw1SzwOU2e~x^LenMtkV9sw3--=Q$g>Ys$51xJpea9RUx}_#cjV+ zBOfN3%YF+uBOqf$Z>u zKkwqWQ9~yk`b&(CD6GD)Ni!{ZAmyT5+$ROD*1!`A`?;lcyfC3-fK*rGU5zi%P>0eSQX^Vn2mW7y*dUF1D6L!x(1*Le3jr?MdZ&egIT2`)NUBFA4~) z>2WM>)ZKh0<8HVv8iVhc_JV|ONuK`7OkVHEt?UAZzoY6u{@7AmpS~Dux&VYXL7ot9 z_b=rJxs9xUDKD6}dEh|)M3v~XNTDjFQO8fXl_JTc`sz6)kKzYU!xOMD-=m+&hJTdoPY|qLv&jCE zP7%Z*u9jU{GohYINB%`>5&G*@*tM8%2J1z)=k^#j@<-45v*gO6KcCNPQieiZS9Q&lnP?!UNqQ4M zs_BmPH*ypTM8OVSY+Iu>#8kF&kF&$Y)gJ#9;0{>itmv5<$~m9mKGTA~C3cL{RTFuX3b*#q90I=jMy6H}+c{1Md zJss{+T~uNHE0d2!^O$qms3|OBOzw2%ONkqMDS=}$nVAc7OS15pdL5aj-j|AI5D&8O zP(A)&5lEbt6jJ(;-EKX@JIZ*pnLWW_yv}%XEW=b9+Lv>n)o}VU`QA26rmwEU6oCck z4e|r`FBsb44)aHT52y3Dy^(=_7p@C2mn3*~2fG)-|0Wv27{Cu?hCd(~{|y|0fz!o8 zv^F>a`A#Z&=w^iV5-;LI(O9oA_iq=o-S%Hz<*b|;*yek~-{!42)ScrAqL>0(AgLit zvAs*~5xSo-m?)3zp3tZA#r_F3K_pc^oeCk1AIbH4vK6T2_cT)WeLF^<3vWnBR}_RY z73LG_ZAb$ABW1z zD5WK%FSzq%k)j7G6-y*d#W@Cm-FPW>2F-74PTx&<7(iO|k)aL2wy9n8ZEo_-W1#1j zXa%=*5OiL*y;Pu9-;NF21i)A>6fT6O0EgtrM?kTEh{C`9geI;Pa~q*aRxQ1${k{Zj zY^k+mC3UC<<&|bC*GK;}uK(t)_Na~(yS1?~$F#(H>?=g3YP(+`*@Q@_4KJLJ%8z{W z!S8Foazee2OLtU#d`$bD-(+T86E5(7-LradS+RM5A^1?}jxSPdE0qjZ8X96S?sSu? z)oau1J^!{jn*95KSJ*sx<=JK1<%imP<5Ai!yFO@W5L{kh9j%#m08V}Yh(MprbMXz- z(tC?Z;FLEU@b4sICF2M@#!DF>LeYPxjXn&z(uYPeLu5R3O?LLL8JO+KhT$^`f_+YhA^F|2cR14=(y-dSXLv&o$uWZ~XYl+gD)LvIiOX}ll ztuU_dpTd%`kW*BIMBq#VG1j7M0}Z&9HNc6QrQGD{hdzHPkR1$skNhol=U*5f1XH1x z|BTDH&A~Z>x#HSuiGRgsRR_TGRY5PY*3*zUpL6<=xWoXx2b$8kuPu*bUtafN=!o)= z4$r5ymy~U6lhoLCchcGPe$Uj2>c)RwM&SFJ>P^&Jot6m#g$TYANv-wzwm46+fz39P zy7Bb0D|;~SG}YrG@rlfi_l>#18z#Xcvl4-ylwS)YH74f&8h9Hj6=rjD#dXMe8SOGG zka(d-dh+>yn9e*!VJ%Pmq60h()(`^d{HHm+aLM2|`d`no>%EWu9k+lo8G*vYX8u&svE_+w02Li#dq7ql) zfcLw{aiu69c0I!S_w;Ti#(4=$hD+AJFUK?k=@YEi`mbhp!=z=tExXS&dw*^|W|rA> zsk9z<{`tE0i~2#$!j0XGaOvk|7}mJQ0RoGs1wrY*cXqT4>MGd8OojGY!nsKOVhVKK z(n+rWe=ZOyK&^UdnX+;#0CT^+d&wRNu9aM*T*KjhRu2kB)&!b zo=P^yw702r$ik3vm9gkH=9%pZnE_gb3pNuiLKw8V1#LXdI+YZGv* z4+c)PI7NUKY7k7q@nA9kA1{Hn6KLs__eY`U6vx_Zz-EP=X@|NZL?}(Uk+BoS(vd<2 zCHbkRR2wQd;P7FYWfF4=h9BhFl@&5uiWTH7(zfccm3Y4x`{0pxrn^63b_8(qMihOn zR=6Ot>j+}rMJ^Ip`akzffjdsqoqeEVL{Rd8^*KP`(^>FUQy_I^9YhR_6*doex`4!O zM7k=z9{QA~NA8%&Vm>Hi1zY9Kw3R7Zb(D!o?SM?i zJjap3`fwzP92~@Ep?;P_Wd^;kMO`%r`Bk#**d~p3##qw6SiG~zSjD#l8o$_Ju>Bhx zaS7~$zUzORD6>BRyps9aK1Ap2)ogF#bokVls9v>1jRKxSMb%#xE%i$TLu7k;fT4S9 zOj-OD2Si6}fut5Dp~#b>8E6+&Jy6RW-*AT|8^V#f(HC?^#Ah!t^rh0bB%#) zn*x8JmQbIUgWJ;T@CDXI<6xG+35I z=CtPFZ&%-vjubj3?rp}=NxmUNXFb@+ z9S@Ir4b7nMcv3$RdC4*UjoqgSd%o9O z+ch^F?++jl;Qe6+2mKc7>-~6s78=&>Xw@+3IJ!qtiOb3zmvGfgpqy+I;5|$yf;|}o z99K|q`Sy-CPlqf#e%w5{y7N#)TaE~WW2>;G{8jnvnfuKT#vgZ>G=%p~*>iY)Iv%S+ ziXyT5BTK4Cn7bpyd15Sg`tn;5S67v+%n7E8UKlyLo;oW6T1f4qRe=IZ|MBZqhu=4< z7dhZ4HbB3}cx4~O6S{i$5XuR~1IiQX+QHQ(=z6dM*9#y;!`NIS!2O_%5pD-cP)sO< z(gHaMxr~U3K5I*YP0JzDA#7}_2cb#~)&r2TvV1^*SlVSa0b^PvKFIIxMM$4#+-PA& z?`eA!4NG|Mk6D=O_ZRmbuJNuVr8J>)bmEJ|rST)A%9$K!FBdtV2-~lca$Vc~-(MgA zIKPPT3&`Rzy%)nk;GmThPAeEE*Zk-MSu8ahQtvKVrWh~A+-tCKnCSMZeT!mi_THFf|Lk|L6t`YF3F~GX`2i=RU3vr;Ti49#Nf==D1(_1cB-A4@_ zrCdy|T)>(=3_=+{06{$VeJ|vkztB8vX-S|;t2$MFQ3cLW-u<3hY*q?w#IAQ?bu-s1 zf_?AM9PxiVp<0^?W2S1M=U|M*hgfBAuJphAOi$w=Ep0?D1>I~~W{04T4}-d_dKc4e zJbF86@GI`ho{M1``M)u`^rE%C%PO48Lx2TmyH^EJ#{e(ZCv8N~lfB+3*ND~q3xpCK zFxy++_Zn563=$6HU5khCWD#^-GAwoZ0>(Le2rrzQ@m9MVD4i^z%_{GO$*p`Z)K~HI z=pego%6G*yDQPCdn0NVe7dgP;KH#N0bZl9~8+lji61m0l|UeFN(HXn8# zX$2R4UjlDO{jVmm2Sjy)Q{|5UCJX^9Ln@U~&yCjod%H=WV!rDCIfV7upeTN;cOvxq z4xv<=h*da$&@qC$q~|31zz3XL28wpxxp)aIfD$i0049$X-$e+I(JmC-Kz~uh*I+y+ zVydwj@lMU3g2)p$l-6z>1z`j#N7yQ7j?pTNU4Faz6ubU_E>JwB{YKxRC27qw>z+G% z^pWg{w)!S#8(Xh?-PtD|4#kV7ag*y5eB=l8auH*{$%c6Qc(X3wR zriV><-S0@Rqu&Ks>tUfp+4}n`q4vKFqB$=O?CVzHvY9{((CQD`pg%tUOGt1V{XmU^ zyWW0aO6~_OgG>41h%Tkm2*vkTqeVE{hMzd4o+`d13Z!J`zhO=NOkg5qAn6`blKgej zXsG&vHhtX8=L-bUf-yzi8SLo&p;&Odh82--Sx`9>XI$Lm;~rf7gpAw+7t@^8CE``l zS@cl<2*>bcQJP&UI5kjCsS+)ozcOE*5yp(m+YvtG+ldlgJvUeSea>Pk)I= zObo3aalClwgN8jhe+q7{Ysxj%1?U5H_l!Y%x5x$F1bt-jTwMzg2zW`JpHx*B5dC$B zja99IE_F1nfpqm7Rphbr+BYv;<&`WN-X=>je~02=VVSEeFC6| zfX!1CQO)EP4o2RV`=rBhU0H1(A9$PUSdBkfz0)3Jqv|uFYF-#1`)i!f{)4Vv8&+`X z-7hX5W_X9axX1V3Z4W^iZSKA)sMty-Up+pi=#L`BWEf=?v;3O4HXuHJ6G`uslVqK! zvvKzK=uw1sE;Dur>4UVFk84<)nCuudWAdxb4eKT3@~`oknL3$jw=YO?3QxsDq1Mn) zQp@bEHymiYMBxj4c3n~QX8R?~W*t=8V!s&RfDBY@@I-rnYqB2=%>-Pd0bFp-VwT2- zmy2q8!OZa)-gqUC9d^yme4M^uB6pDPuTTPigFkuICPKH5SLmQ+(z|kdSli9am=zSV zLKijL*oKeq8jOo#MA^)e)$0SL3tyhNWKLf(mtEbUM0$+S4j)BLo~=6sJxz8xh-1V) zb=McbsR>PUro=L-=zeRJ$F|P9W^_9Dl+W`9YVjv#1D2E1Q1!8ah2~kmJdU?Z7P%~O za#;hEK+`5n%v4ldAGz{V?@H^(G@|hc`;W2MIJt{>l+&)47wS*WmDz0Ii`gR#bR7&e zLqwdvv?#TA0i)c6`(Dh0r~QAoVgIN%zzURiS4qkZ`Ag5FE2sse`{8D-@!hrOT zrycLfWhU|qSUb~FFL6gG95u$btj}r={+dm*>JX{Ugw>SzrpFi695IJfidv_RBG7Dk zKpkAFn%G@T!!pG%lC-*dWZ^^bE7!m5Y;2-i1=&6J!Y@ki1bK%skutYWjU^8LeHG#O zIU4!PzR|l=wnBK5Cuk-;D7Y!C(Vr9jzBQ+l@q0xb#*g0}XFATqdl9bx@_oel@GD39(lAmKC_J{bb{NvkuC2|fDzw*nfetil)b?1m}xGoIB6R} zdn~b8u@=Up+f~Cwh@ORC3%AVVSo7WhXaw9svCxxA%(z9%c}FYrWfo6qk%NPXoA(#Y z@4XMWGF*D&@+ULN`5J1)UFbR*)xofQ;t1FFr-qVoUq>c|we zd1TU=gU9S0WZv}lMEXr;#W5KlWCL3*Ip;$Nz$cdm-{vqBUfw(XWK8b-L?nK@w)Ycl z^$(LYG&tUBe^*zG_je*aw?3m1D~!HFpR+zgSNqZuPxk%WL{*K{H#Zk*3;AZ>IIEsj zcw$N$A{m37DjZbdy`gV&yJ;mIud4^-(``okZL;I*B@a8Ij&tBrq|fc0mOQfghCBxQ zh%zX1c9Iz>2lMYdUR-}JBqlIC<9lDWWtHz4y{egzWC_o@`>qX>xTWsmoVVu}`no)R z;*CqCPO6-Yg17630bno`F?1)-v zZ_-=Ev5h+UvAIlo6f=hh+L*a3l&$}=SxRwk`;q+gdvkD5cxfso>2vAKhnS%r%!@29 zyj|W2qix%UmS6~tG5>ZdG+*b)RylrS(Q5c_RS~Jqi+!)_>LB>g4f=X942*n6CodPN zkSNz?z!_W~asMp9`Ntrz@qa!9M9{HMrfDHTygbUmh*LtORBmmL)ejU6fYa>>{n}!tJsdd(bdTALEzf0?wqg>i1TluN5``D01 zE)@l($$c&T$r)Q?ig)Va*5%ldpCrn5+yWdFRTX~N==fmYFva0Z4NucGoti(qNDUgX z<@v;4r?3!fV$8Z&f3bccT*VHHg-4O`g+#}ANL;wuJx+uae!5%IcOOBthcvNmDf(;8 z-3O%8@^$)M#O^Vgc%t_=H&H%l@F2Yq1rx6SSgl1+JE7%O#{kJOJeASk{da=ag7R?Y zi5zy^oU3yST~-Sfub1Bmnvqbb>aXr}%wGM1YS!7daBtCmlXuSQ>AIvzb#!2sc3|Np zuY9OZpA)N<|9$0k?mF#y9}+$TSzeCMLh|Aq@>~mI*WAUug0H%M@+N<&$#V1|O)T0CH!ndZAL5yMA-HtZs=AxJX3 zH!GnlTUb+Dty!QfkB&T?{6%(lmw*P-{dyEnwptT^Bn45D7#YEI@~)l++6&7mHZ7kn?8Zz_9%n6C6P@L z9VCWBOZ4;G-5FY!;yABSof|r;WY>=raTOJBw!Zk<1#KiPZ!mW^W0aUJ_!>%MV=&5| zG^@N1^H&Q2aclyWq?GY--k^C|U=t@&Ppm((zrMz5l$P^Lpe0IThbE|IIkvZ-vGj_m zU15pTJlp-+lqYfFyK2T(8Fjs1NRTuJp|w1-JTqU_&ZNjgeg(0w-DGn3$4yM6_-G=o zCc#GDDo;{PvnNuU>TZxby@M8*&ND`3bD?ja4c*|PB1qe$&|=?Y$EP>~Kh63Lbee}q zSK#M65WG<#;kA~olxd>U@)woYAVn!2+Cd!5^lWI*Ousj8gKHmDDObxSa0Y7a;)DMc z9^8T{fb((@zHpe&%XAIp=CC?BJbX;-;I&qlt{|8viof~d0(hfh4rwaU_a@Jy$FCf+ zTnP#6RqUOnEMk9?)uZR1li(#kaL)r3aqgeimPjnksmnhU+DfqV1yh`TiHYUrS6f9Nv?>jXWIA z8Ezww&+~pu00DYGsfq)ebSxs(2-TGqUdaq$-b!%Q2ymIFTG7ap#(Omx;f3=mxv~~x z!SN5$wu0ICG8M`EQr4CFzFEFnF{E5f+o43DreIZP4wc}4JuD8Kd61n_R!A7Pk0aFB zZABp=3bFHh(ZyEddY?DPiW9OF(s~eU#QI;D*{o|cU0WimY)a5I>3DyhU1^C;CH&R> zvuGL*3FPRU!}a{uH+H8yor!pOvB=P0AKVsBMv+;;}_-0M(BIBj~moh z*trj?^ctf-_L&M`)B+vMXzL60qsoKHWzcfHYX|Mutw{sT8Gs-LPtY>UztEW9C47X8 z(rUe3+-buJqv8I$FE~e)R#7B@zrJ52@(&_l-UG9WRZR;RX*GpVD#i=R`%#1yhM}Y@ z7Hf+NkIOF^HxU7l@hf<->MpMYa;+)lodAB%FB`>y!zu3-64=)Fy{R4f5AW&TJHpoe zM&hp8B-B6dct9f1Dw&Lu#`k79*T&Y8wy6ZiE{n>B?qbfSH{$|T!N-lLft|Og)AKFb zr%uJz^cijeAAii7Oqm@Jk5&6Cs_AD1lCHqQ0W)Ut6%_O-^j0T0+|cE{KIj}S=pl=vf1kS{0RDUv0gJW0p>?UPu~+1RU3Y{&5OAH?^Myof8bEIaBjxRbbdiM*1{crlLCgZ79YcIQzg!FIq2LNmIm|`yj8! z6w3vEE{t3JrxsvF|3@aOdc1C@u2$?oy%tOO0_NIu?GKQ2!n_P^c2O`eZoY)82k@ec z`kpv$0!o?SKKdO6AL^Ux8Hxk?V6=%|Ok|8gY*+SP5d-SsjRz-HFFrj%hh&MlUBAws zoDMUWk9qY@cQor9cztTfK)IRU&SOM?*?#Gx)!dFD@@j+*r~9jzGLL%%(;TL|e$3t6 zUm%~zOXT?yFN1#bGu71`e_v0#^x;K@3)S>gzw^NoBR9>_bcj%KpA%)tnfeV2P zZe5uOcrbm|CU04Qd$%z{4C+1@DgOLNtaw;3pooTju`9qd3{ZR+h`cJ%9nWAVlu$|; zaQx56OfZ zH4Gw?TA41mc=R!F;rkTjc?AmwF=*EjHE7VGr%hA=VmIZj;OVrwj06LKoVR9#&@6DE zDaj`A1J!ZCcnIYqEvuPUknEERsYpzTMRsn?HhfcD2~i*`Yy;i`9zqsBXpOHJ8vTX* z3XrtE4OqN|$0XKIw7n1h(2w;{@v-ORovwa~>)8X@NJ4ZO&? za@o}ks6>OnPdZ$_6lQ(Oj!HTh+dZSJ9sJYn`~D=wHoH$gPhO4iriOP3Y?&WfbgFBN z;{1S!(m_1Diw<&aMJ&#Zc|C^Hq9NhhULQvWXn&Y=HmGKP5L+aj&1*T_=l4Rxx>utQ zKO6(4|B8ZNqY=;kq4PkY>wf3Nrv?zB@skwXW{2LY=bPZ-1GJF!I~Rh@?{qZSy}LD( zqNIOr-ef<%P;&o)HBlSWTl)Fyz0KXjeBu_J_z_FCT^%NEMOmL9NN+~P*{glMz&Ob) zxwlu!#BJh>MIShjU>c;q-(UmB?Ngb$q$ZI6cFJioW>~(EM}Va>9RB~%_1)ogecjea zFVTq-JqV%&Axbz}^cKAnU35aC9zv9;QKKFSB6=qTNAD%kOQHtR%h4TYf7|u1JbB; z4h-@u3J(qZsTf;)d<7#H_YcV#r{&Tq8fcnW25>AKBN*OYoPJq+Ni93;qgqx@%~bcdE=Sxyo;UUoOnKiR!xnjJnZe z))T!Iw+oX@N*9Ba%i?d()yJfUlhu4;*Hj*6@erZZhAQyn_xtvqZV7}rR2osbKb>fF zZnLzf|2VZGKGs9r-#^%5{X_X5=GdG*q?l>aub^= z#pWUu!n;GF*92K3uMDhn-o7%s1J=f{*{}&#pmFrIF8+keYl5iA zw6_8kh_@0q{W_@DQiGnv6dN#p_xPe16XS<|gQDEOIX^oBiK`12SKy12gJoeZqA%mrBbBQA_GPqLx?`oCu1Lu?1nC1|75(W z!%EcmGfnsvz>z^mRpJQ6{2bx>rGWL5g1k*Rg6>k+I;4lv?XohpglT@F6{tzKIG9;4 z?3RJN$zA`GQ?}dhGiPV`0cN(C*=+COOYyVcQI2I;MP9GItCgL`UkLMsiWl~!O(t1U zR9%5$rQL_n7n%3dze1&y*cmnA8EqF zGPTt367?s29|;5OD@19^-LvEPo?XkYUZ z@r-7v%@;q3?0XM)eP;&0xelLxp`;hpQbaHp5t+lEW*Fq3u*VH~7-DK-pmn__=vwz= zb7!cAu(VTYIEH0sf!N2<|2OV1Qz zF$B9oMZ~A&7xkogH$V9{l0r_n_V4s%IRy5-mYphzlI9Z*#z$LcMP6`rflgWlOtG|> z{fCyeEQKo2!T7gbFV8RI z*E<=h19`u>rhaP@Rn-Q^3%bf}w%c{R`HqV%m2N=fSj+UFkugMR6sl`PS*fq_>;-OD z10lO4$46D_Vb!N;%3ZWRSabSVYXz;9%um(Gy}O_1nVq||#LZZC=A~Dx4XtxY9|tBr zI@W%eBQM{iK$wYjg4FGFm7jWH^1FOZ+27;`)tcIt7FpTmU`c4sXo+COQw(WsORiq6LxeWRAo&&X!8|Jbr|@aK5P1tE_=UkIxG-q!F4$ecy$ z#x^$~2=OY9l$^rgp)iSFOP(w-JJacn56+-t=Ogl{PftIOA9Wq3i#|rpd|KKpbO2Jb zzjaz#m~<|$7ka!Fj{&Go6_6w_j|IE}_}kl>;eV3Zf7W^FJrXSVSOy$K3H4@+A!X?? zy;F-0EzJz;1)gnN9@3!k)&Ya^hvNrFuyuOL8Pz!;e^dmCF-0C?zuvi2aJv7t?b>$Z)`R16tq3`iw8m#if>DOP8q#=@am+Ypxa@{v4Uwt3x=(zjt{eA5I`tFy^ zI0k~7CMIj$x<$x`YSI%6bIr%v`WhbN^?M2w(@Zu;@f{37g~J?NlSVn|=>Bsff0bi)&MwI=~($MLR*+yYJOT?3-b&w4G1@)IY<=UF0Xt9U6MqoC&9OAOP=zRoH!5%R+06ICn>Fm|!NiPH&ld!Z$W;{L;eR6i z9~faoo0D%G@}g!MiW$-cBT!}o0i&+ko7|&Iv^gay2>ix&*KI$Ck5G7xqaDlo)@K^>E8avk`zGKl1NmQ7}u}qc$jz$A3e%;+;{u zubA6s^RhEPOX)?u0F5&84%KmN$cWH79d$tX(C`2<2NKG2Y-$W#Ws}<&)#o#q^5=9z z!3qq{QN&E@khrOX%tz}V^=K2$@|jNvx?*|y+c?TO7vGfxl9y0%07)_SS=EUFFPMJwXyl@%`eys3rV9s zeZ1P-<}%HGnHrp&i&NjhY3T>rKhWyJ!n`|EWh36d9CVB2L)`9ayVzox+ecUY);_4i z`a!r&U(KI+tVMjO=o{`FB$4TPz95~%NR`CyuT9SzUgedNqZ4R!Jx}X=TyOowj!_3J zy(x+xH_yPYIG?#pTfL{0p5TPsu}jF{+AQt54ClaPeaM}c(~*?4YAcNCOC{;06ja2f z%)KsxK84r_i`qpfRW)dKYQEESGPbD}@(-!ENGN`vJ=s!3JN6C@CwGIY#Sjxc!-EB| zR%gKdEb16*OM`VO(v9<*%bAjMKXwOo#UAT^DXy^Ug5Fo$*=@Rq&x?JjwZ=>Z+abrD zDhYmav4h(MIzf+twRfTItjq;IG!L5jkNKEIu&UT&{Bh>&KE!^QGZ^-b-Ip+xe}g-- z$Nyb=SO{X<=^`u4oFsCt>~3Ox($g<}*e0qO8v@)U=ali+vfQRi=QXy|g(zN5^k8sg zJ(HeY4S#q>&zus*9nQG$$*zR(A6VksTzq$nljBMYTA8R78Y`B$@vQcm1dPd!ul^`< zUK`Vnxa91p{3w$jWmK)#JEsO_{#MKfbwOx*E*)O%j@YOFmPx9dp`%#Gh&ZWT_i+}L zm)hu|Ga4a!$1;-|(%>FGLNRMWStN;(rt79d*+grgpw*eAD!aqJTUQ48QZcO2ncBhT z$Y~Sc(qapF#EDX=9<@B3tDHJV<`Hc0b}&mACeR9x1y}?FnI%5I!}EBQ_`*2v~Pwba}vQ)`>_< zY5-441p7ZVh=SGsfgGjD!1gN-*w0GY2cMszyW9ol4(X)Jx|?*RG99u!{=Q zQw27-h2pFIv{(8`nX#Ukq9)1}SH&qK^=sAk8tjI(L(=?yw$h0bEt9Wp}kC!)1Y zlXrLSO4ZH)ZUJ#689DQJWq))i3VFW>2R7lb0(mojrt9B-xWl&nP-9c#q_|}JIQOjx zqs&$iydO7lShIUzeoQcklQG$sn1#6Udw`^{VOD3zNXoR&Tqhj=0{lB6G7E>hLzaeL z8~jLaf>le>F*bqVU~m;-Mc@971T#LKXfT!g2Oq5BV8N<;JRGBH8ABa3{iCwtRoHvA zc&FBi@tJ(2@!33U42_vHE)BuHLw0P>>nU1JkKQPorx%2p^+}W|WSNb&yzF>G zon`z_o7x5j=fy@$3D|~ZI8D>lC7i8tot#_*lT33Sum+5Xw|vGT`?{ljJa43-^mgCo zQ_h%;zp_KxAME9%vu4c=b*Wv*?pdL|jjOw3Pstp{Z>Vhi;xwITj8eJx582V}i;oYs zs#1ttm3Y5UVQy8g6|Pmqvv>yG|M~80RcKB7!1IVuW%y;0kMgT2VzT2ebr9QpgL2dO zzwFHz2!^$r%vRn;Rjb06r*e500&1NoyhF=zFK1@L38}&pb<1xQYlu^g`=D@6ISzO% z1?dlmyc6Q_QR29hP6IYZl-)>-M*-nmWX1YVP`Z2ld$R*lD4wNoD}}tgiye#51_tw8 z*|c^`Z-1{oSSix;J7cp!(xfbEQh)W~4#ix5)OLHr-E@2I^X&1H?%MO7K+_H02lu;y z9Vq$+k*Q}s^gC-SQQJ^w&C2n+L2h5^`-KM?ug)fO4RRE_P0LNz6AgS&&;8nQ83{3% z6YvJ5aXGq1&Wew@)A8+~?WMLxGi&c>i9UP?9tf8^4cI#cF5c8_J$YsIG17RRJ>siU zKF__Kasu%@3dZhTAQeW{fwl2G0KTmmDIa|xi zEO6n@Z09!ERuT3HwMGc5U|8-XzT=6AgpwXP*e4Q;(L9suxC?k-!RpFJp0`$Yh^3@A zl_aQ2Ce00y3x675n`M4bAU#-KGFL4ItlX~Ue?!ZEvN!lDFrK3?lS61G zo+g9;JRe7e#K*2-!n<-=t3+uG$fVyvHDpfd%m)Ye05+zz`di933iEKOFDfKARo7-5 zE!vElW#pMF*sm#k14g8DUZC4y7<5)!s?V_8MNha&#z`$E-vn>jyl#?3}Nn zkHW-XkJ}$kJYEspI{FhG>Dt6O*TrD{z+=3XRNJS4Q)pbXVCo>rHFH1q*U@Q?`#`OW z?aP(jjx&vA5p-T{B_ye$V`=`BzURR!7F&lc-&TaS-q8g-2%E)X<-#;IjQ~p#Z?U)!$0o=kQxS`c8<4pv zc9j-%LH@1rV?)Y|e0#@W&o0;-xa(`0NY~L@reOHYUR=X5^GgJelKv9HL-FgShT_MP zcm?V~#=|%2QLJfI3!K9pxNjw54RJ%Aw<)=p`7C$Lx9jw!y*TYxT7qB=dp80Xrg(`% zKS_mZeI`G7(sd`fbZ4brr_qEo)7N2WQe9A9EM@dKA062Hl}KBSz}DLuf{=1H2~Tcv z0yPIxUn<4A1;(<| zd*F&UEOfdE48`Ea&EvdeI;9O`&>)$sU9q#PUWRH=N<$rZk+Dvhqs07*R8v1Y4`a?- zM?$C~sR>7InO59~YBGobp*4jmVGR{J7|(9r{esB8zh$#YY3}z>jRkcB576x~M+qM{ z*QbLYQQ@b2)3m2A5v&be=r5D95PQ!W)(~Un&r@6!U_+y9d z1y;uybMbp3J$HP`8c6kZ%Aa?uM?YxbG_7XlGizn0jdrti=z0m82t1nIA2f` z_x-B(u@uAPyssg!^}4#yS4eJ<$@kXr6Vg1`>9mh z=+@%KkeB4=#2G;n-A^g}1G7D>Je)Dk5Jclm7(XdohCdQed4Me^);*o3mHpGP8y4D9 zgQ3=Wv!V154>4a^2 zV?xCS=H1(>uU`M*gueDpY>~iF=}+KizjVfh$l!};ki+5Q#nws0z6%X~+cB>wdK8@)w0kc5^5zI=D)lR8>sh3K`cQ&&q0v%YuXdYIl2$GRPI_rsr(`FuXx)7O4Pe#TWLN1Ih?zMb^XQ9)H_uQ^hr{UdXBw4}Q^+S|^a<8T2;vW8V zWuN6)=JJ$RNbu~w)_%!RqXsyF+R@_VW5mWfSn z4LdjFCM;BWo(T)}V$`DKg7opIWCfK|cBLeVrZ*QZ1fQb#qY=Zp*TdtaYo@A;i~_0W z4AW+s#-cZELY-H29@PiXWk`wvjaK{aT&Z|yv(2m`*kbA}E2l#b zZ8h&5``@#|28?fhAMqlS@WvNc7KpBfORpwf8-DwyOo*ON(BO@$|9Q+Z$Ju3p{ZWMK zqn%>d@vE?529r%V=yF2RJ*0ClN&D<`te~~O`t{0=K9glMP{SVblW3V3o%y8~L3bjI zR!Q5j{OMe@O*BoToUu+IxXgylt8$_;95QNs6at)9pS}Z@L?C(sKe(PMn^}OYT32(B z`tEmoLe>BKm;xAEvwdkta$>Ev9>`5z!xX;}JDH=f8jc^I&h)x$I4FZ3!HtM!bd zk7Op_if&E?9BQG?NJc+k8YM6)e?NLTU(Ajq1J*xoI_EQLU)uotddb|VihjA%f9Wh4 zn2(ic0Oux?)8VwT4xtc3T1rp$c|OUJR_)8mOg8$;vvXJDAufE9j@Aa0xFB_igy|vA z1tIoiPTxH6BYQ7}=C&rmGC%gy6DoeEg&npeAAwE0x70BE-hzTelHdVb48rHhK6Uz! z?H9HVlF@cHuDzD_qc2f$Q=&W{zh7Rxd#2TnzUqLLLYmsx=?Xx_PUn~y_^hukT!>E3xTv4x?WVY8zcaVM7PP~3@|dr-ci5-5PXA7c zEZjT;~W~Q0(>b6v3Y&r#=VU_a7~%=9w*S2~8+1 z>sg3P=?$7hXo9>9@AAH|ROAcm>AzzaScgh}1XiQu^`-GmnX-3V)f5iT@_^J%zxy(p zb@E7xN1c{u-~4)F`js2b#kP8I12Ym?%!5J3$iyVLJO_2Y=*svJs>9Guo50R3 zrvjQL2!!5sV{@O7Xgpht+ZOa5g4t_NX_i4_0gAnaN_;8vc^{nDC)8-XIE$(E-sRy) zUUnW+zMijwW6fh)9bV7dhB4llgfCt8{udX(I4$`D1#dykQwzWN{#DlHvk!(O<(nSpvg{e7Y0$%8%Qj#r+mHye8^s%}J z!env^)*Y`$fRH|R)DyfjwSr?tIKf*6DNUkqnUaaC0xu-SU0@8kZPM0w{1tOsy)!74 zpE~$WjyB(q(a~Dk{1Zw)VzIWdImCE1K8BEFpi zM9-9dRytTj*jY>+DZFGOe(soCKRO|oI+0|79zTx#Sn*cUb(L9ON=>fzL3wanz?Q1<4;GXMSm&XXdoYPJ10_e%6O1%j)Qt8wZ@Kaj+$Tve-t9s0COu zW5j%j;>bK3UKD`cgJoQP@HogcKhH`KMaS*K#{{*FS|N`E5R-(^xSNsmyKxn04Uji= zn<1DD_9A}XAjKsBIL#(76ODwX*BrUO0s_G|yxDUJ_^hJF3SCh2zoGE8gH?o>34PII z+77!U&^B6W-IK+3_wP~P&S$iGRJ#JsHfM5+j^P2d|=)nlx? z+aJQYDH&g(Eq9QTRG3x)dXu;==PtfqeH*0Kuo-+cluiwoip$T(hG4Zq`9uiavWZ5R zHD2<*?vX2A(J!(N#IQvfE{5c%tJxX<`pG-@ajVR-Z?4-qU?I?f2lZ6=YO626iQxW> z1o<1lG6$q?<9e@S!(VMyt%MPcuOK;Gn?Tft%_nS;(kOo&ZtWeEq|odaKE$G9fX~}|vchl~8%*$j{H5=h!jW2! zR9HXBUK?&3yE~ip<(($*r(+3}-OH(QctSvxBa?`SR_qI!DmX#t@s|NnWyV%W;JL^5 zUQ5jYRW<*TiGcFmM%BL-kX<`_N?_=2QzRh*J&|OdKLsny6Zn(nK@i4u+qA8a9Z75sE*jlT=0PI zC3rwGtI&BYip@GG9Z8{zCsQKa=-wI{8S0#Y`E6%9F%in-+V5p4K@AhZw5(*lsrORO zPRotDCkY!=_TW2vT54aUKG8vl0Ov4N^iJt`dH&)@dv+@jrUT!fjp842Zp^FuqhO

>qv;sGb6_029+)M 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 literal 0 HcmV?d00001 diff --git a/playnote.md b/playnote.md index 9f10c73c..764d2fe5 100644 --- a/playnote.md +++ b/playnote.md @@ -1,9 +1,15 @@ # 试玩问题记录 +- 一开始不能让角色的成长系数太高.比如在没经过升级之前,你的成长系数是跟不上关卡怪物难度提升的;但是后续能力解锁之后,成长系数才能匹配得上 + - UI优化,第二第三关的棋盘看着太累了;不知道是因为亮度还是对比度的原因,看着非常费劲,非常不舒服; - 第一关的第二个节点数值有问题 +- 现在的立绘太丑了,像素化的粒度太低了,导致根本看不清立绘; 看是否可以改回用较为高清的图片? +还有一个问题是大小的问题.我们或许可以调整一下不同怪物的大小,因为现在地精的图片看起来比熊地精还要大,这并不合理; + + - 修改地图的奖励类型 战斗节点增加不同的地图类型,比如有些图踩雷受到更多的伤害,有些图标雷可以造成更多的伤害,有些图伤害会减半需要凑更多清图奖励(这些都是暂时的设定) @@ -16,27 +22,10 @@ - 3选1奖励中有一个refresh,任何说明都没有,就一个refresh, 明显的一个问题物品,但是却没有处理; +- "奇物门票" 这他妈是专场门票,而且你他妈应该有一个更好的名称,而不是直接"门票"; 我真是操了你妈; +而且里面的解释非常弱智 + - 确认选择按钮旁边有一个"免费选择,点刷新不消耗AP" 我真是操你妈了,要你这种傻逼解释; 你他妈这是游戏的UI吗?设计像你妈坨屎; -- 封印回响这个专长描述也是错误的,怎么是本轮AC+1呢 - -## 2026-11-04 营地相关问题记录 - -1. 背景图存在着很多问题上半部分的内容太长了,我们应该预留更多的地面细节给我们的可点击的地方; -但是现在远景占据了太多的位置; -远景应该压缩到只有1/3的高度(现在占据了2/3) -近景的地面太朴素且太暗了; - -远景压缩之后,围墙,门,告示板记得也同步上调; - -2. 围墙贴图没对齐就算了, 过于矮? 高度应该>门 -3. 物品太靠下了; 整体可以往上调, 让最下面的宝箱和最底下保持着一个32px的距离 -4. 钥石说好是一条顶栏的,为什么现在是搞了一个类似浮动框的形式展示? - -为什么我设计定义的东西你没有进行实现,而且还自作主张地做了一个没有经过我同意的展示方式 -5. 点击大门开始新冒险,直接回到了开始菜单界面; -你是否真的做过完整的测试? -我这句话问了都白问,因为你做了完整的测试的话,就不可能会这么简单的逻辑闭环都没有完成 -6. 开始新冒险的是和否反过来了.否在左边,是在右边; 完全的反直觉; 完全的弱智 - +- 封印回响这个专长描述也是错误的,怎么是本轮AC+1呢 \ No newline at end of file diff --git a/tools/golden_baseline_refresh.sh b/tools/golden_baseline_refresh.sh index 422d5a4f..7aba1e93 100755 --- a/tools/golden_baseline_refresh.sh +++ b/tools/golden_baseline_refresh.sh @@ -5,6 +5,8 @@ # 缺位时先拷主区素材+导入边车再跑)。 # 模式: # --menu:shot_probe 启动态菜单整屏帧 → game/tests/golden/menu_boot.png。 +# --lmap:level_map_shot_probe 关卡视口两 Shot(入口停点+Boss 列锚定——2026-11-05 用户裁 +# 两 Shot 面)→ game/tests/golden//lmap_entry.png + lmap_boss.png。 # 全屏基线可行性前置已验证:菜单连续帧差 0.0000%/max_diff=0(光柱为 # 程序生成静态贴片、零动画着色器,全屏基线不抖动);采集确定性=探针隔离档(无断点+出厂 # 设置 1280×800),与 render_gate 的 shot_menu 对比段同源同帧。 @@ -21,6 +23,7 @@ MODE="board" for a in "$@"; do case "$a" in --menu) MODE="menu" ;; + --lmap) MODE="lmap" ;; *) if [ -z "$GAME" ]; then GAME="$a"; fi ;; esac done @@ -53,6 +56,34 @@ if [ "$MODE" = "menu" ]; then exit 0 fi +if [ "$MODE" = "lmap" ]; then + # 关卡视口两 Shot 面(卷轴视口批·2026-11-05 用户裁:只对拍关卡最开始与关卡 Boss 节点, + # 中间过程不对拍)——入口停点 + 末列 Boss 列锚定,两基线各存平台子目录。 + for a in assets/fonts/ui_font_fusion_pixel_zh_hans.ttf \ + assets/art/ui/button_stone.png \ + assets/art/ui/node_battle.png assets/art/ui/node_reward.png \ + assets/art/ui/node_rest.png assets/art/ui/node_boss.png \ + assets/art/ui/node_shop.png; do + if [ ! -f "$GAME/$a" ]; then + echo "[golden_refresh] 拒跑 — 关卡屏素材缺位: ${a}(S3 停机点口径:基线禁锚字形回退态,先补素材+导入边车)" + exit 1 + fi + done + gate_run_timeout 420 "$TMP/run.log" "$G" --path "$GAME_WIN" --quit-after 3000 res://probe/level_map_shot_probe.tscn -- "$TMP/shots" + st=$? + grep -E "\[level_map_shot_probe\]" "$TMP/run.log" | tail -3 + # 判定锚工件(同 menu——quit-after 与 quit(0) 竞速的 124 非真红):PASS 签名 + 双图非零。 + if ! grep -q "PASS — 两 Shot 落盘" "$TMP/run.log" || [ ! -s "$TMP/shots/lmap_entry.png" ] || [ ! -s "$TMP/shots/lmap_boss.png" ]; then + echo "[golden_refresh] FAIL — 关卡视口截图缺失或探针自检红(st=$st,见上)" + exit 1 + fi + mkdir -p "$REPO/game/tests/golden/$PLAT" + cp "$TMP/shots/lmap_entry.png" "$REPO/game/tests/golden/$PLAT/lmap_entry.png" || exit 1 + cp "$TMP/shots/lmap_boss.png" "$REPO/game/tests/golden/$PLAT/lmap_boss.png" || exit 1 + echo "[golden_refresh] 完成 — 关卡视口两 Shot 基线已代入 game/tests/golden/$PLAT/(提交说明须写明触发原因)" + exit 0 +fi + for a in assets/fonts/ui_font_fusion_pixel_zh_hans.ttf \ assets/art/board/seal_mark.png \ assets/art/character/character_hero_idle.png \ diff --git a/tools/probe_gate.sh b/tools/probe_gate.sh index d47b7af8..b54848ae 100755 --- a/tools/probe_gate.sh +++ b/tools/probe_gate.sh @@ -134,6 +134,12 @@ st=$? grep -E "PASS|FAIL|问题" "$TMP/uip.log" | head -12 verdict "ui_input_probe" "$TMP/uip.log" "$st" || _rc=1 +echo "======== level_map_viewport_probe(卷轴视口批 R1-R8) ========" +run_suite 120 "$TMP/lvp.log" res://probe/level_map_viewport_probe.tscn +st=$? +grep -E "PASS|FAIL" "$TMP/lvp.log" | head -12 +verdict "level_map_viewport_probe" "$TMP/lvp.log" "$st" || _rc=1 + echo "======== ui_struct_probe ========" run_suite 120 "$TMP/stp.log" res://probe/ui_struct_probe.tscn st=$? diff --git a/tools/render_gate.sh b/tools/render_gate.sh index 8e1a7b8a..d8bfb16f 100755 --- a/tools/render_gate.sh +++ b/tools/render_gate.sh @@ -165,6 +165,38 @@ else fi fi + +echo "======== 关卡视口 golden 逐像素(卷轴视口批——两 Shot 面:入口停点+Boss 列锚定)========" +LM="$TMP/lmapshots" +gate_run_timeout 360 "$TMP/lm.log" "$G" --path "$GAME_WIN" --quit-after 3000 res://probe/level_map_shot_probe.tscn -- "$LM" +st=$?; kill_orphans +grep -E "\[level_map_shot_probe\]" "$TMP/lm.log" | tail -3 +# 判定锚工件(同 fx/board——quit-after 竞速 124 非真红):PASS 签名 + 双图非零。 +if ! grep -q "PASS — 两 Shot 落盘" "$TMP/lm.log"; then + echo "[render_gate] FAIL — level_map_shot_probe 未干净完成(exit=${st})"; _rc=1 +fi +for b in lmap_entry.png lmap_boss.png; do + if [ ! -s "$LM/$b" ]; then echo "[render_gate] FAIL — 取证缺失/零字节: $b"; _rc=1; fi +done +scan_log "level_map_shot_probe" "$TMP/lm.log" +if [ "$_rc" -eq 0 ]; then + for b in lmap_entry.png lmap_boss.png; do + if [ ! -s "$GOLDEN/$b" ]; then + # 两 Shot 面(2026-11-05 用户裁)各平台独立冻结——本平台缺基线=未冻结态记 SKIP 不判红 + #(windows 先锚;他平台冻结义务归收尾呈报),已锚平台照常逐像素严判 + echo "[render_gate] SKIP — $GOLDEN/$b 基线缺失(本平台未冻结——跑 tools/golden_baseline_refresh.sh --lmap)" + else + LMG="$TMP/lmgolden" + mkdir -p "$LMG" + cp "$LM/$b" "$LMG/$b" + python3 tools/golden_compare.py "$REPO/game/tests/golden" "$LMG" "$b" | sed 's/^/[render_gate] /' + if [ "${PIPESTATUS[0]}" -ne 0 ]; then + echo "[render_gate] FAIL — 关卡视口 golden 超容差(S2 停机点口径:视口呈现换代=显式重制基线+呈报;超预期面=L3)"; _rc=1 + fi + fi + done +fi + echo "======== 残留检查(批末闸) ========" left="$(orphans | wc -l | tr -d ' ')" total="$(gate_godot_count_all)" diff --git a/待办清单.md b/待办清单.md index 4e6d90fb..73af9f33 100644 --- a/待办清单.md +++ b/待办清单.md @@ -257,11 +257,3 @@ **改动面**:游戏代码 **状态**:待执行 - -#### QA 覆盖总览面板与自动试玩扩展——自动发现测试验证缺漏(2026-11-05 登记,来源=会话提及) - -**实况**:方案全文=`D:\code\qa-harness-discussion\QA-Harness讨论结果-中间报告.md`(三批定案,全部三关试点):①探针存量 emit 真输入化(~40 处站点,承接上条)②B 覆盖总览面板+本体枚举器(六源回执明细化+能力清单提取+HTML 双击即开+游戏内容↔测试验证对账)③C 自动试玩扩展(auto_player 扩全动线全功能,异常上报含机器自填归因)。裁决在案勿重提:A 执行覆盖矩阵不做、D 缺口闸不做、变异测试禁入、归因登记不立独立制度。 - -**改动面**:游戏代码+工具代码+文档 - -**状态**:待执行 From 76a7067440be90f7708397c1a9487e27ed7f31c4 Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Fri, 6 Nov 2026 00:08:18 +0800 Subject: [PATCH 04/10] =?UTF-8?q?iter53-=E5=8D=A12=EF=BC=9A=E6=94=B9?= =?UTF-8?q?=E5=86=99=E6=97=8F=E6=B8=85=E9=80=80=E6=89=B9:=20=E5=9B=9B?= =?UTF-8?q?=E6=AE=B5=E9=9B=B6=E7=8E=B0=E5=BD=B9=E6=B3=A8=E5=86=8C=E6=AD=BB?= =?UTF-8?q?=E5=88=86=E6=94=AF=E6=91=98=E9=99=A4+=E8=AF=8D=E8=A1=A8?= =?UTF-8?q?=E6=94=B6=E7=AA=84spike=E4=B8=8Etrade=E5=8F=8C=E9=94=AE+?= =?UTF-8?q?=E8=B4=9F=E5=9F=9F=E6=8E=A2=E9=92=88=E4=B8=A4=E6=9E=9A+?= =?UTF-8?q?=E6=B3=A8=E9=87=8A=E9=9D=A2=E9=80=80=E5=BD=B9=E5=90=8D35?= =?UTF-8?q?=E5=A4=84=E6=B8=85=E9=9B=B6+=E7=8E=A9=E5=AE=B6=E5=8F=AF?= =?UTF-8?q?=E8=A7=81=E6=96=87=E6=A1=88=E4=B8=89=E5=A4=84=E4=B8=8Esim?= =?UTF-8?q?=E6=AD=BB=E5=8C=B9=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- game/core/action_economy.gd | 2 +- game/core/battle_orchestrator.gd | 4 +- game/core/damage_controller.gd | 85 +++++-------------- game/core/effect_engine.gd | 12 +-- game/core/reward_grant.gd | 12 +-- game/core/reward_roller.gd | 8 +- game/core/settlement/grant_segment.gd | 22 ++--- game/data/schemas/treasure_item_table.gd | 4 +- game/sim/adventure_monte_carlo.gd | 2 +- game/sim/level_autoplay.gd | 6 +- .../variant_placement_test.gd | 2 +- .../unit/core/meta_progression_forge_test.gd | 12 +-- .../data_config/effect_kind_retired_test.gd | 29 ++++++- 13 files changed, 89 insertions(+), 111 deletions(-) diff --git a/game/core/action_economy.gd b/game/core/action_economy.gd index 679302ef..6becbdfc 100644 --- a/game/core/action_economy.gd +++ b/game/core/action_economy.gd @@ -79,7 +79,7 @@ func try_spend(action_kind: String) -> bool: # 排雷玩法 挖掘专用:chain_size = 连锁附加格数(不含首格);clears_map = 本次动作后全图安全格开完。 -# 深挖钻头付费开掘(dig_paid counter_spend 订阅施加面):按序消耗族——AP 富余(≥基础+对价)时本动作付全价并积本轮付费计数(效果引擎 +# 付费开掘(dig_paid counter_spend 订阅施加面):按序消耗族——AP 富余(≥基础+对价)时本动作付全价并积本轮付费计数(效果引擎 # 计数器=授予段追加产出配额取数面);AP 不足全价时 fallback 降级只付基础 1 照常开格、不积计数 # ——持有钻头永不锁死普通挖格(散件保底 B-2)。 func request_dig(chain_size: int, clears_map: bool) -> bool: diff --git a/game/core/battle_orchestrator.gd b/game/core/battle_orchestrator.gd index 0aba641a..d30b320e 100644 --- a/game/core/battle_orchestrator.gd +++ b/game/core/battle_orchestrator.gd @@ -255,7 +255,7 @@ func begin_battle(enc: Dictionary) -> bool: _begin_battle_fx_state(enc) _begin_battle_attune_params(enc) _begin_battle_preview_economy(enc) - # 工兵晨令=round_start grant_ap(mode:queue) 订阅行承载(when round_index ≤ effective_rounds + # 晨间 AP=round_start grant_ap(mode:queue) 订阅行承载(when round_index ≤ effective_rounds # value_from 定影);round_start 发射先于行动经济轮切换=树规则 queue 型当轮入队当轮兑现 # (先手压制=首轮 AP+1 语义锚);计数器 round_start 重置点同点生效 round_index = 1 @@ -535,7 +535,7 @@ func _exit_distribution() -> void: if not _install_and_reset(): _fatal("换图编排失败") return - # 工兵晨令续队直调拆除(内容数据驱动扩展批 T4——round_start 订阅行承载,见 begin_battle 注) + # 晨间 AP 续队直调拆除(内容数据驱动扩展批 T4——round_start 订阅行承载,见 begin_battle 注) action_economy.notify_settlement_done(mode) # round_start 发射先于行动经济轮切换(queue 型 grant_ap 当轮入队当轮兑现——与首轮同口径) round_index += 1 diff --git a/game/core/damage_controller.gd b/game/core/damage_controller.gd index 4223ef42..2b32f298 100644 --- a/game/core/damage_controller.gd +++ b/game/core/damage_controller.gd @@ -106,7 +106,7 @@ func _per_value(name: String, payload: Dictionary) -> int: return 0 -# 巢穴控制数(fact nest_count 取数面——敌方名下 weaken 实例总数,猎巢人订阅面; +# 巢穴控制数(fact nest_count 取数面——敌方名下 weaken 实例总数,nest_count 订阅消费面; # 个体化后削弱为累加行、每体各持一条——总数 = 被削弱个体数) func _nest_count() -> int: var n := 0 @@ -135,7 +135,7 @@ func submit(t: Dictionary) -> int: # attack_commit 发射点(我方伤害单据开立入口; # 命中挂单据 context 随行——施加面在 _resolve_hero_attack 管线算术前逐族施加,开单时点=主角攻击 # 单恒为段内首单(结账现场与开单现场一致)。载荷 atk/target/matchup + 挖掘 streak 事实 -# (执拗订阅面)+巢穴控制数〔猎巢人〕) +# (开格 streak 订阅面)+巢穴控制数〔nest_count 订阅面〕) # spec 束必载键(缺载 assert——fail-fast):channel/base_value/target_rule/ri; # 可选键缺省=原形缺省:origin_cell=(-1,-1)/attack_type=""/rider=0/highlight=""/context={}。 # 返回单据字典九栏目+requires/source_unit 逐字不变(契约 8)。 @@ -247,9 +247,9 @@ func _resolve(t: Dictionary) -> void: # 主角先手攻击:掷点 → 折扣/暴击 → 克制点数 → hero_offense×enemy_defense 池乘区 → 下限 → 交付 # (attack_commit/clamp_check/armor_roll 订阅施加面:命中=开单入口随单 -# context 携带,按固定算序逐族施加——命中序=数据表声明序,确定性)。 +# context 携带,按固定算序逐族施加——命中序=数据表声明序,确定性;掷点折扣读数→克制点数两拍)。 # 四步分段:命中面(_hero_attack_ctx,目标/护甲/ -# 掷点/按序改写族四拍/克制点数) → 基值装配(_hero_attack_base_value,加法族/计数器施加/倍乘) → +# 掷点/掷点折扣读数/克制点数) → 基值装配(_hero_attack_base_value,加法族/计数器施加) → # 掷点兑现(_hero_attack_redeem,rolled/池乘/下限/rider/落地/击杀发射) → 交付(_hero_attack_deliver, # 状态施加/标签/明细行)。步骤间经 ctx/redemption 字典穿线——算序/取值固定(🔴 逐位一致契约)。 func _resolve_hero_attack(t: Dictionary) -> void: @@ -261,7 +261,7 @@ func _resolve_hero_attack(t: Dictionary) -> void: _hero_attack_deliver(t, ctx, redemption) -# 命中面(目标/护甲克制 matchup/armor_roll 发射→按序改写族四拍→克制点数读值+订阅改写; +# 命中面(目标/护甲克制 matchup/armor_roll 发射→掷点折扣读数→克制点数读值+订阅改写; # 后两步各由 _ctx_rewrites/_ctx_clamp_delta 承载)。返回穿线 ctx(空=目标不可达)。 # clamp_check 只在 _ctx_rewrites 内发射一次——_ctx_clamp_delta 消费同批命中(禁重复发射)。 func _hero_attack_ctx(t: Dictionary) -> Dictionary: @@ -278,54 +278,25 @@ func _hero_attack_ctx(t: Dictionary) -> Dictionary: return {"target": target, "armor": armor, "atk_type": atk_type, "ac_hits": (t.context.get("fx_attack_hits", []) as Array), "ac_payload": ac_payload, "roll_read": rewrites["roll_read"], "threshold": rewrites["threshold"], - "crit": rewrites["crit"], "discount": rewrites["discount"], - "spike_ready": rewrites["spike_ready"], "cdelta": cdelta} + "crit": rewrites["crit"], "discount": rewrites["discount"], "cdelta": cdelta} -# 按序改写族四拍+掷点快照(armor_roll 发射点在此):第一拍矿工重锤命中交换(正负双修原生形态: -# 命中判定减成 trade_hit 点〔更易命中〕换攻击增伤 trade_atk%——高 AC 负期望/低 AC 正期望; -# 改写位先于掷点折扣读数)→ 第二拍专注免掷骰恒定折扣(方差买断成期望——稳定器人格;roll 记 0 归因) -# → 第三拍满层必中(spike ready 时 discount 恒全额、暴击面走倍乘不加掷)→ 第四拍猎弱本能对轻甲敌折扣档改善 value 档 -# (对冲 pierce 列 L1 −1 开局罚;改善 = 折扣表向全额方向移档,nat 最大面/已全额不重复)。 -# clamp_check 同在此发射(唯一发射点——命中随返回值穿给 _ctx_clamp_delta)。 +# 掷点折扣读数+克制点数命中批(armor_roll 发射点在此):一拍护甲掷骰折扣读数(掷点对照 +# 防御阈值定折扣档——阈值=防御 AC+攻击加值,nat 面沿折扣表)→ 二拍 clamp_check 发射 +# (唯一发射点——命中随返回值穿给 _ctx_clamp_delta)。 func _ctx_rewrites(t: Dictionary, target: Dictionary, armor: String, matchup: String) -> Dictionary: - var ac_hits: Array[Variant] = (t.context.get("fx_attack_hits", []) as Array) var roll_read: Dictionary[Variant, Variant] = _armor_roll() var threshold: int = defender_ac(target) + int(db.combat.settlement.damage_roll.attack_bonus) - # armor_roll 发射点(敌护甲掷骰判定;免掷恒折扣订阅面) - var ar_hits := _fx_hits("armor_roll", {"target_ac": threshold, "roll": int(roll_read.roll)}) - var trade_hit := 0 - for h in ac_hits: - if String(h.get("kind", "")) == "modify_ticket" and int(h.get("trade_hit", 0)) > 0: - trade_hit += int(h.trade_hit) - if trade_hit > 0: - threshold = maxi(1, threshold - trade_hit) + # armor_roll 发射点(敌护甲掷骰判定——事件在册、现役零订阅行,发射面保留) + _fx_hits("armor_roll", {"target_ac": threshold, "roll": int(roll_read.roll)}) var crit: bool = bool(roll_read.crit) var discount: int = _roll_discount(int(roll_read.roll), threshold) - for h in ar_hits: - if String(h.get("kind", "")) == "modify_ticket" and String(h.get("mode", "")) == "armor_rewrite": - discount = int(h.get("value", 0)) - crit = false - roll_read["roll"] = 0 - var spike_ready := false - for h in ac_hits: - if String(h.get("kind", "")) == "modify_ticket" and String(h.get("mode", "")) == "spike": - spike_ready = true - discount = 100 var clamp_hits := _fx_hits("clamp_check", {"matchup": matchup}) - var shift := 0 - for h in clamp_hits: - if String(h.get("kind", "")) != "modify_ticket": - continue - if String(h.get("mode", "")) == "discount_shift": - shift += int(h.get("value", 0)) - if shift > 0 and armor == "light" and discount < 100: - discount = _discount_shift_up(discount, shift) return {"roll_read": roll_read, "threshold": threshold, "crit": crit, - "discount": discount, "spike_ready": spike_ready, "clamp_hits": clamp_hits} + "discount": discount, "clamp_hits": clamp_hits} -# 克制点数读值+订阅改写(魔网织者/湛蓝誓约/猎手刺剑 clamp_check modify delta——克制矩阵查表值 +# 克制点数读值+订阅改写(clamp_check 带模式行 modify delta——克制矩阵查表值 # 后的直调;hero_attack 与 board_typed 两消费面同享)。命中批由 _ctx_rewrites 单次发射后传入。 # 淬毒刃纹(行 triggers clamp_check # modify(mode:clamp_bonus) 订阅命中并入本处 delta 合计;mode 路由=主角攻击面专享, @@ -338,8 +309,8 @@ func _ctx_clamp_delta(atk_type: String, armor: String, clamp_hits: Array) -> int return cdelta -# 基值装配(基值+单位标记加伤+矿工重锤增伤面+加法族(attack_bonus/ -# value_counter 层值)+计数器施加(attack_commit 用后清零行——命中序=声明序)+spike 倍乘。 +# 基值装配(基值+单位标记加伤+加法族(attack_bonus/ +# value_counter 层值)+计数器施加(attack_commit 用后清零行——命中序=声明序)。 func _hero_attack_base_value(t: Dictionary, ctx: Dictionary) -> float: var ac_hits: Array[Variant] = ctx["ac_hits"] var ac_payload: Dictionary[Variant, Variant] = ctx["ac_payload"] @@ -347,10 +318,6 @@ func _hero_attack_base_value(t: Dictionary, ctx: Dictionary) -> float: # 单位标记加伤(处刑台 target_attack_bonus 挂单位字典 fx_atk_bonus 键; # 阈值沿发射点已写入,本处通用消费——对该敌伤害加算) base_value += float(int((ctx["target"] as Dictionary).get("fx_atk_bonus", 0))) - # 按序改写族第五拍:矿工重锤增伤面(交换的正向侧) - for h in ac_hits: - if String(h.get("kind", "")) == "modify_ticket" and int(h.get("trade_atk", 0)) > 0: - base_value *= 1.0 + float(int(h.trade_atk)) / 100.0 # 加法族:attack_bonus per 计数器层值(层数×value 加算)。 # value_counter 扩展〔疼痛记忆/弃图兑换/陷阱本能——rider 值=计数器账面, # 值读于施加时点=命中序先行 rider 后清零行〕 @@ -365,11 +332,6 @@ func _hero_attack_base_value(t: Dictionary, ctx: Dictionary) -> float: if String(h.get("kind", "")) == "counter_add": var set_v = h.get("set", null) _port.counter_add(String(h.get("counter_id", "")), int(h.get("value", 0)) if set_v == null else int(set_v), set_v != null) - # 任意真族:modify_ticket mode=spike 满层倍乘(强制必中已在折扣拍承载) - if ctx["spike_ready"]: - for h in ac_hits: - if String(h.get("kind", "")) == "modify_ticket" and String(h.get("mode", "")) == "spike": - base_value *= float(int(h.get("value", 1))) return base_value @@ -391,7 +353,7 @@ func _hero_attack_redeem(t: Dictionary, ctx: Dictionary, base_value: float) -> D var pooled: int = DamageMath.pool_damage(rolled, clamped_pool("hero_offense", StatusContainer.OWNER_HERO), clamped_pool("enemy_defense", StatusContainer.owner_key_for(target))) var landed: int = maxi(int(db.combat.settlement.damage_roll.damage_floor), pooled) # 加法族:英雄侧 rider(enemy_skill rider 对称位补齐口径)——后置必中附加,独立于掷点与乘区 - # (奥术余烬「普攻命中后恒定结算」语义);猎巢人巢控光环(per nest_count)/矿工的执拗开格加成 + # (普攻命中后恒定结算语义);巢控光环(per nest_count)/开格 streak 加成 # (per dig_streak、cap 封顶)同通道合计;档一质变 rider+1 / 档二(crit 时)rider 乘暴击倍率。 # rider 不改变下限语义(landed 含 rider 后不再过 floor)。 var hero_rider := int(_fact_or("rider_tier_bonus") or 0) # or 0=未绑缺省与 int(null) 缺省同值(int() 构造拒 null——端口缺省 null 面的空值合并) @@ -421,7 +383,7 @@ func _kill_effects(t: Dictionary, target: Dictionary) -> void: _port.reveal_effect() # 斩首学者——击杀揭示 1 格(端口路由宿主入队,授予段末兑付) -# 交付:即时执行族(碎甲震击打重甲附加「护甲裂解」——复用 off_guard,零新状态行; +# 交付:即时执行族(重甲附加「护甲裂解」——复用 off_guard,零新状态行; # apply_effect 域闭/重复授予由状态容器自行守卫)/标签装配/明细行发射/兑现登记。 func _hero_attack_deliver(t: Dictionary, ctx: Dictionary, redemption: Dictionary) -> void: var payload: Dictionary[Variant, Variant] = redemption["payload"] @@ -524,11 +486,11 @@ func _resolve_board_typed(t: Dictionary) -> void: var armor_b: String = String(target.get("armor_type", "light")) var atk_b: String = String(t.attack_type) # clamp_check 发射+施加(克制判定修正点棋盘面;与 hero_attack 同表同点: - # modify delta 订阅改写合计进克制点数;discount_shift 档位面属主角攻击专享,本面不施加) + # modify delta 订阅改写合计进克制点数;带模式行只施放于主角攻击面,本面不施加) var cdelta: int = _counter_delta(atk_b, armor_b) if atk_b != "": for h in _fx_hits("clamp_check", {"matchup": atk_b + "_vs_" + armor_b}): - # 无模式 delta 才入棋盘窗(mode 路由:clamp_bonus=主角攻击面专享、discount_shift=折扣档面) + # 无模式 delta 才入棋盘窗(mode 路由:带模式行=主角攻击面专享,棋盘窗只吃无模式 delta) if String(h.get("kind", "")) == "modify_ticket" and h.has("delta") and String(h.get("mode", "")) == "": cdelta += int(h.delta) var dealt: int = DamageMath.counter_component(int(t.base_value), cdelta, int(db.combat.settlement.damage_roll.damage_floor)) @@ -619,15 +581,6 @@ func _counter_delta(attack_type: String, armor: String) -> int: return int(row.get(armor, 0)) -# 折扣档改善(猎弱本能——折扣表向全额方向移 value 档;查不到当前档 = 不动防御口径) -func _discount_shift_up(discount: int, shift: int) -> int: - var tbl: Array[Variant] = db.combat.settlement.damage_roll.roll_tier_discounts - var idx := tbl.find(discount) - if idx < 0: - return discount - return int(tbl[mini(tbl.size() - 1, idx + shift)]) - - # 池内加算 → clamp [-100,+100](池间乘算归 DamageMath.pool_damage 调用侧); # 池按个体读(增益状态 v1.5):主角侧池传 OWNER_HERO,敌方侧池传被打者/施放者个体键—— # 乘区只合计该个体名下实例(B 敌的削弱不进 A 敌的账) diff --git a/game/core/effect_engine.gd b/game/core/effect_engine.gd index 33d3a725..56b9e75f 100644 --- a/game/core/effect_engine.gd +++ b/game/core/effect_engine.gd @@ -27,7 +27,7 @@ const MINE_EVENTS := ["dig_reveal", "dig_paid", "seal_hit", "mine_hit", "seal_se ## bias_rewards/preview。需求卡片标题计 23 系笔误,落码按行内容全收——commit 留痕) const EFFECT_KINDS := ["add_ticket_rider", "modify_ticket", "damage_mult", "open_ticket", "attack_bonus", "yield_mult", "spawn_spell", "grant_material", - "grant_ap", "grant_gp", "bias_wallet", "shield", "spike", "apply_status", "counter_add", + "grant_ap", "grant_gp", "bias_wallet", "shield", "apply_status", "counter_add", "counter_spend", "reveal_tiles", "remove_mines", "refresh_pick", "bias_rewards", "preview", # 六型效果(奇物.md 基础件表 27 件声明清单): @@ -61,8 +61,8 @@ const FACTS := ["matchup", "is_first_dig_of_battle", "terrain_kind", "target_arm "ap_exhausted_last", "hp_ratio", "amount", "ap_left", "pct", "battle_index"] # 关卡域战斗序(1 基,enc 携带;开局姿态组「每关首轮窗」条件面) -## when 算子词汇(封闭——fact 查询面落法:mod_zero=计数器取模判满〔掘进蓄能〕、 -## advantageous=克制矩阵正面判定〔淬毒刃纹〕、gte_ref/lt_ref=与另一计数器比较〔深挖钻头配额〕、 +## when 算子词汇(封闭——fact 查询面落法:mod_zero=计数器取模判满、 +## advantageous=克制矩阵正面判定〔淬毒刃纹〕、gte_ref/lt_ref=与另一计数器比较(计数器配额面)、 ## ends_with=后缀匹配〔对某甲族的泛条件〕、mod_eq=取模余数判定〔双管镐每第 2 次——value=模数 ## ref=余数;dispatch 预评估口径〔when 于命中前读计数器现值〕下「每第 N 次」系用 ref=N-1 表达〕。 ## 均系映射表现状条件装进 fact 的查询面落法,白名单覆盖) @@ -79,7 +79,7 @@ const WHEN_KEYS := ["fact", "op", "value", "id", "ref", "value_from"] ## axis=bonus_delta 加算区轴向) const DO_KEYS := ["kind", "value", "value_from", "delta", "delta_from", "mult", "mult_from", "cap", "cap_from", "cost_mult", "per", "divisor", "dtype", "mode", "channel", "counter_id", - "set", "status_id", "label", "fallback", "target_kinds", "trade_atk", "trade_hit", + "set", "status_id", "label", "fallback", "target_kinds", "value_event", "value_counter", "axis"] ## 主动件分发通道(不经事件订阅——刷新/显影/移除是玩家主动动作;use_treasure 按 kind 分发) @@ -154,7 +154,7 @@ func _push_tree_rule(rk: String, params: Dictionary[Variant, Variant]) -> void: "do": {"kind": "shield", "value": int(params["shield"])}}, {}) "sense_sharp": # 锋=踩中危险格伤害减半·每关限次——mine_hit 挂点现成(damage_mult 收集→halve_pct, - # 与惊巢反制同路径;伤害在结算战斗段末兑付,探索阶段零改动) + # 与挖掘惩罚减半同路径;伤害在结算战斗段末兑付,探索阶段零改动) _push_trigger("tree", rk, {"on": "mine_hit", "when": [{"fact": "counter", "id": "lvl_tree_sense_sharp_used", "op": "lt", "value": int(params["cap_per_level"])}], "do": {"kind": "damage_mult", "value": int(params["halve_pct"])}}, {}) @@ -449,7 +449,7 @@ static func _vtr_from_refs(rid: String, tr: Dictionary, row: Dictionary, errs: A ## 加法族(数值相加,可交换):add_ticket_rider、attack_bonus、grant_material、grant_ap、 ## counter_add、shield——发射点逐条累加收集器。 ## 乘法族(收集后一次施加,正负分桶):yield_mult、damage_mult。 -## 任意真族(任一命中即生效):spawn_spell、spike。 +## 任意真族(任一命中即生效):spawn_spell。 ## 按序改写族(收集→单点按声明序施加):modify_ticket 及一切改写窗口效果。 ## 按序消耗族(按订阅序消耗共享资源,耗尽即止;可选 fallback):counter_spend。 ## 即时执行族(每条命中各自执行一次,执行序=声明序):open_ticket、 diff --git a/game/core/reward_grant.gd b/game/core/reward_grant.gd index db957961..5fb230d6 100644 --- a/game/core/reward_grant.gd +++ b/game/core/reward_grant.gd @@ -1,5 +1,5 @@ ## 奖励授予件(自 battle_orchestrator 收编 grant 族):极性字典路由兑付(grant_routed——含封印溢价 -## 与惊巢反制减半)、三种行应用(flat 四分支/percent/gp)、伤害单据提交面(submit——案C 暂存闸承载)、 +## 与挖掘惩罚减半)、三种行应用(flat 四分支/percent/gp)、伤害单据提交面(submit——案C 暂存闸承载)、 ## 清图奖励与身份授予(完美封印第二份)、战斗内 GP 缓冲 escrow、秘宝使用四步编排(use_treasure—— ## 相位闸→校验→受理闸→逐 kind 应用→消耗)、揭示奖励兑付(reveal_redeem——fx_host flush 的兑付回调面)。 ## 生命周期=随编排器(编排器 _init 同建同灭,每战新建)。 @@ -127,7 +127,7 @@ func use_treasure(handle: int, target: Vector2i) -> Dictionary: return {"ok": true, "item_id": v.item_id, "resolved": v.resolved, "record": rec} -# 受理闸(treasure_used 发射+施加:counter_spend 订阅=掘进蓄能积点账本,积点不足拒绝零消耗。 +# 受理闸(treasure_used 发射+施加:counter_spend 订阅=付费积点账本,积点不足拒绝零消耗。 # 零 item_id 特判;拒绝文案读装配集积点进度——宿主 attune 读投影) func _charge_gate(v: Dictionary, target: Vector2i) -> Dictionary: var tu_hits := fx_host.fx_emit("treasure_used", {"item_id": String(v.item_id), "target": target}) @@ -180,13 +180,13 @@ func _safe_dig_open(v: Dictionary) -> Dictionary: return {} -# 爆破工兵包兑付(中立移除危险格:未揭示/无封印/是雷过滤归排雷玩法; +# 中立移除兑付(未揭示/无封印/是雷过滤归排雷玩法; # 邻接数字冻结零重算、清图分母零涉(危险格不入分母);空集拒绝零消耗—— # consume 之前 return(拒绝面注记扩「③内零消耗分支」),拒绝 reason 可呈现) func _cell_removal_open(v: Dictionary) -> Dictionary: var blasted: Array[Variant] = fx_host.minesweeper.remove_mines_in(v.resolved) if blasted.is_empty(): - return {"ok": false, "reason": "爆破工兵包:3×3 区域内无可移除危险格(须未揭示且未封印)"} + return {"ok": false, "reason": "中立移除:3×3 区域内无可移除危险格(须未揭示且未封印)"} return {} @@ -218,12 +218,12 @@ func grant_routed(snap: Dictionary, polarity: String, att: Dictionary) -> bool: row = row.duplicate() row["power"] = int(round(int(row.power) * prem_pct / 100.0)) row["premium_pct"] = prem_pct - # 惊巢反制(减半系数=mine_hit damage_mult 订阅命中〔行 value 50=减 50%,取整 ceil〕; + # 挖掘惩罚减半(减半系数=mine_hit damage_mult 订阅命中〔行 value 50=减 50%,取整 ceil〕; # duplicate 隔离——减半不回写极性字典) if halve_pct > 0 and polarity == "negative" and source_class == "mine_hit": row = row.duplicate() var half: int = int(ceil(float(int(row.power)) * float(100 - halve_pct) / 100.0)) - emit_cb.call({"type": "effect", "source_class": source_class, "origin_cell": cell}, ri, "惊巢反制——危险格挖掘惩罚减半(%d→%d)" % [int(row.power), half], 0, {"effect_id": "nest_counter"}) + emit_cb.call({"type": "effect", "source_class": source_class, "origin_cell": cell}, ri, "挖掘惩罚减半(%d→%d)" % [int(row.power), half], 0, {"effect_id": "nest_halve"}) row.power = half return _dispatch_row(row, att) diff --git a/game/core/reward_roller.gd b/game/core/reward_roller.gd index 57010bac..ac1f9e3b 100644 --- a/game/core/reward_roller.gd +++ b/game/core/reward_roller.gd @@ -1,4 +1,4 @@ -## 掷格件:装配期格面资源摇号——池行装配、区间行 roll、权重合成(偏运硬币/board_skew 两路投影)。 +## 掷格件:装配期格面资源摇号——池行装配、区间行 roll、权重合成(订阅加权/board_skew 两路投影)。 ## 自 RewardEconomy 迁出掷格面(architecture v1.29 轴戊②);受理账面(grant/身份查询/快照/retire/ ## polarity_row)留守 RewardEconomy——衔接面=格→奖励身份映射批束(本件产出、受理件接收)。 ## 取号流声明:roll 每批恰开一 reward_roll 流(scope=每次 install 批不变),体序=normalize(行主序 @@ -38,12 +38,12 @@ func _init(bundle: Dictionary) -> void: func roll(eligible: Array) -> Dictionary[Variant, Variant]: var list: Array[Dictionary] = _normalize_eligible(eligible) var stream: RandomNumberGenerator = rng.open_stream("reward_roll") # 恰一 scope 批(格批 + 清图批尾 + 区间行追加取号) - # reward_roll 发射归 BattleFxHost(偏运硬币 bias_rewards 订阅命中合计经注入查询口取回); + # reward_roll 发射归 BattleFxHost(bias_rewards 订阅命中合计经注入查询口取回); # 零命中/未接线=0=原行集零扰动 var luck_bias := 0 if luck_bias_query.is_valid(): luck_bias = luck_bias_query.call(list.size()) - var cell_rows: Array[Variant] = _biased_cell_rows(luck_bias) # cell 池正向行 weight>0(偏运硬币装配时稀有正向 kinds 权重 +N——池结构零触碰) + var cell_rows: Array[Variant] = _biased_cell_rows(luck_bias) # cell 池正向行 weight>0(订阅件装配时稀有正向 kinds 权重 +N——池结构零触碰) var clear_rows: Array[Variant] = _pool_rows("clear_default") # ① 身份批:每非封锁格恰一类型身份(雷安同池——同一行集同一权重分布) var draft := {} @@ -83,7 +83,7 @@ func _normalize_eligible(eligible: Array) -> Array[Dictionary]: return list -# 偏运硬币权重投影(底稿 §3:只动池内权重、雷安仍同池同分布;luck_bias=0 逐位返回原行集——off 态零扰动) +# 订阅加权权重投影(底稿 §3:只动池内权重、雷安仍同池同分布;luck_bias=0 逐位返回原行集——off 态零扰动) # 合成序:先经图级偏斜投影再叠件级加法——合成序锚=图级先、件级后 #(环境事实先定型、玩家构筑叠其上;两投影均为池内权重面,雷安同池与取号次数零变化) func _biased_cell_rows(bias: int) -> Array: diff --git a/game/core/settlement/grant_segment.gd b/game/core/settlement/grant_segment.gd index 1eee08d0..eb472a60 100644 --- a/game/core/settlement/grant_segment.gd +++ b/game/core/settlement/grant_segment.gd @@ -124,8 +124,8 @@ func _reveal_safe(evt: Dictionary, snap: Dictionary, ri: int) -> void: # dig_reveal 施加面(序=计数器〔连击计数——乘区收集后执行=本格兑付用旧值〕→ 揭示入队〔地质学家/ -# 跳格采掘 reveal_tiles 订阅面,授予段末统一掷格兑付〕→ 追加产出〔深挖钻头 v2 双份制:grant_material -# 命中=配额内追加第二份〕→ 奥术矢〔魔能共鸣——每战首次开安全格追加魔法矢;任意真族单次生效〕) +# 跳格采掘 reveal_tiles 订阅面,授予段末统一掷格兑付〕→ 追加产出〔双份制:grant_material +# 命中=配额内追加第二份〕→ 奥术矢(每战首次开安全格追加魔法矢;任意真族单次生效)) func _reveal_safe_apply(dr_hits: Array, evt: Dictionary, ri: int) -> void: for h in dr_hits: if String(h.get("kind", "")) == "counter_add": @@ -163,7 +163,7 @@ func _reveal_mine(evt: Dictionary, snap: Dictionary, ri: int) -> void: reward_grant.grant_routed(reward_grant.feat_yield_adjust(snap, false, 0, 0), "negative", {"source_class": "mine_hit", "cell": evt.cell, "ri": ri, "halve_pct": int(applied["halve_pct"])}) for h in mh_hits: if String(h.get("kind", "")) == "open_ticket" and String(h.get("channel", "")) == "reflect": - var nct := damage.open_ticket(DamageController.KIND_BOARD_BLAST, "attune_nest_counter", "惊巢反制·反弹", + var nct := damage.open_ticket(DamageController.KIND_BOARD_BLAST, "attune_nest_halve", "反弹伤害", {"channel": "board", "base_value": int(h.get("value", 0)), "target_rule": DamageController.TARGET_ALL_ALIVE, "ri": ri, "origin_cell": evt.cell}) reward_grant.submit(nct, false) @@ -229,7 +229,7 @@ func _terrain_batch(ri: int) -> void: # 封印判定批+战封印军规开单段(封印流:seal_judged 批后统一开单:轮末每面封印命中对最前存活敌 # 结算 board_typed 必中伤害〔复用零新配方;「封印所在巢穴敌」简化为 default_target 最前存活敌—— -# 台账披露待追认〕;完美布防=本轮封印批全中(hit>0 且 miss==0)时封印伤 ×mult——全对推理奖励)。 +# 台账披露待追认〕;封印全中倍率=本轮 hit>0 且 miss==0 时封印伤 ×mult——全对推理奖励)。 # 伤害单据案C 暂存战斗段末兑付。 func _seal_batch(ri: int) -> void: for evt in facts.seals: @@ -237,7 +237,7 @@ func _seal_batch(ri: int) -> void: _seal_strike_batch(ri) -# seal_settle 发射+施加(战封印 open_ticket + 完美布防 modify_ticket 改写窗口:封印伤基值×完美倍率后 +# seal_settle 发射+施加(战封印 open_ticket + 封印全中倍率 modify_ticket 改写窗口:封印伤基值×完美倍率后 # 逐封印开单) func _seal_strike_batch(ri: int) -> void: var fs_hits := 0 @@ -262,7 +262,7 @@ func _seal_strike_batch(ri: int) -> void: # 战封印军规基值决议(attack 通道 open_ticket 首命中取基值;seal_mult modify_ticket 连乘; -# 完美布防=miss==0 且 hit>0 时基值×倍率。空旗集=空字典〔不开单合法态〕) +# 封印全中倍率=miss==0 且 hit>0 时基值×倍率。空旗集=空字典〔不开单合法态〕) func _seal_strike_value(fs_fx: Array, fs_hits: int, fs_misses: int) -> Dictionary: var banner_hits: Array[Variant] = [] for h in fs_fx: @@ -276,11 +276,11 @@ func _seal_strike_value(fs_fx: Array, fs_hits: int, fs_misses: int) -> Dictionar if String(h.get("kind", "")) == "modify_ticket" and String(h.get("mode", "")) == "seal_mult": seal_mult *= maxi(1, int(h.get("value", 1))) if fs_misses == 0 and fs_hits > 0 and seal_mult > 1: - strike_value *= seal_mult # 完美布防:同轮全中封印伤倍增(全对推理奖励) + strike_value *= seal_mult # 封印全中:同轮全中封印伤倍增(全对推理奖励) return {"value": strike_value} -# round_end 发射+施加(每轮结算收口:熔火之躯反打单开立〔open_ticket 即时执行〕+积层清零〔counter_add +# round_end 发射+施加(每轮结算收口:轮末反打单开立〔open_ticket 即时执行〕+积层清零〔counter_add # set〕;停手侧 AP 已在 request_stop 记账,finish_round_stop 按转存率转存 RAP)+施加面:grant_gp〔爆破会计/收盘——escrow 战斗域 # 缓冲,随 gp_dropped 上抛〕/grant_ap mode:queue〔封印回响——返 1 AP 下轮,queue_ap_delta 通道与轮始 # 加成同面〕+段界收口(转存率入参、清图奖励、揭示兑付、段界结账) @@ -348,7 +348,7 @@ func _judge_seal(evt: Dictionary, ri: int) -> void: # 封印命中(资格以危险格实例为键去重——排雷玩法 诚实重复上报的对侧;seal_hit 发射序: -# 殉爆票据 → 施加面 → 雷区图谱额外兑付 → 基线正向兑付) +# 标中雷反打票据 → 施加面 → 标中雷额外兑付 → 基线正向兑付) func _judge_seal_hit(evt: Dictionary, ri: int) -> void: var cell: Vector2i = evt.cell if facts.seal_consumed.has(cell): @@ -359,7 +359,7 @@ func _judge_seal_hit(evt: Dictionary, ri: int) -> void: "terrain_kind": minesweeper.harmful_adjacent(cell)}) _seal_burst_tickets(fh_hits, cell, ri) _seal_hit_effects(fh_hits, cell, ri) - # 雷区图谱(封印流——标中雷额外获得一份格面资源:封印开始产出对标开格; + # 标中雷追加(封印流——标中雷额外获得一份格面资源:封印开始产出对标开格; # 复用 grant 单点,额外兑付走同一 grant_routed 正向路由) for h in fh_hits: if String(h.get("kind", "")) == "grant_material": @@ -370,7 +370,7 @@ func _judge_seal_hit(evt: Dictionary, ri: int) -> void: reward_grant.grant_routed(snap, "positive", {"source_class": "seal_hit", "cell": cell, "ri": ri, "highlight": "seal_hit"}) -# 标中殉爆票据(行 triggers open_ticket channel blast value_from magnitude——每标中一面封印全体存活敌 +# 标中雷反打票据(行 triggers open_ticket channel blast value_from magnitude——每标中一面封印全体存活敌 # 吃 N 群伤,无类型走 blast 通道;封印爆裂〔专长〕同面消费) func _seal_burst_tickets(fh_hits: Array, cell: Vector2i, ri: int) -> void: for h in DamageController.hits_of(fh_hits, "open_ticket"): diff --git a/game/data/schemas/treasure_item_table.gd b/game/data/schemas/treasure_item_table.gd index ceaeccf0..d4891c9f 100644 --- a/game/data/schemas/treasure_item_table.gd +++ b/game/data/schemas/treasure_item_table.gd @@ -17,7 +17,7 @@ const UNLOCK_COUNTER_KEYS := ["adventure_cleared", "boss_kill_count", "vision_us const DIMENSIONS := ["info", "risk", "action", "plan", "counter"] # enum 九 kind 全部条件触发/机制修正类;mine_reveal/ap_grant 语义不变。 -# cell_removal = 爆破工兵包中立移除格;mine_hit_halve 系固定 +# cell_removal = 中立移除危险格通道;mine_hit_halve 系固定 # 「减半」语义不消费 magnitude(反弹 N 由 reflect_damage 行 magnitude 承载)。 # 主动件 kind 词族(reveal_tiles/preview/grant_ap/remove_mines/ # refresh_pick——效果引擎 ACTIVE_KINDS 同名闭集);被动件不走 effect_kinds 词族 @@ -119,7 +119,7 @@ func _validate_row_head(row: Dictionary, iid: String) -> Array[Variant]: ## 订阅形态域:triggers 事件订阅行判据与行级触发词表校验(被动件形态;与 effect_kinds 互斥校验 ## 面=passive 行(单形态——效果行为只走订阅);active_charged 行两形合法并存 -## (effect_kinds=主动分发通道 + triggers=受理闸订阅,掘进蓄能先例)) +## (effect_kinds=主动分发通道 + triggers=受理闸订阅,积点解锁先例)) func _validate_row_triggers(row: Dictionary, iid: String) -> Array[Variant]: var errs: Array[Variant] = [] if row.has("triggers"): diff --git a/game/sim/adventure_monte_carlo.gd b/game/sim/adventure_monte_carlo.gd index a669679d..4c43b7f6 100644 --- a/game/sim/adventure_monte_carlo.gd +++ b/game/sim/adventure_monte_carlo.gd @@ -72,7 +72,7 @@ func _initialize() -> void: if attune_mode == "on": # 贪心画像:Slots=3(槽位判定源=树同调位节点点亮数,模拟画像=三节点 # 全点亮常量);装配序 = - # 表序 passive 优先至 Slots-1 + 首个 active(slots=3 → [淬毒刃纹, 标中殉爆, 掘进蓄能], + # 表序 passive 优先至 Slots-1 + 首个 active(slots=3 → 表序头三件占满示例, # provisional 画像归调参);Y = 营地升级 Lv1 表值 1。autoplay 默认不刷——Y 仅注入容量, # 刷新消费归玩家策略面(钓鱼归玩家)。 var slots: int = 3 diff --git a/game/sim/level_autoplay.gd b/game/sim/level_autoplay.gd index 13f34021..ec06dab9 100644 --- a/game/sim/level_autoplay.gd +++ b/game/sim/level_autoplay.gd @@ -411,14 +411,12 @@ static func _on_step_row(row: Dictionary, _runner, st: Dictionary, collect_rows: # 封印经济聚合(自结算流水聚合,零新随机源): # ⚠ 行侧判据考证实录:结算段对存续增益实例每轮复发行 effect 行且复用实例 source_class #(battle_orchestrator 状态列举行)——source_class=seal_hit 的行 ≠ 标中事件。事件行唯一判据 - # = 授予行专带 highlight="seal_hit"(实测 87 行 == 受理封印 87 动作,1:1 精确); - # 雷区图谱追加分grant 无高光,以 display_name 后缀补捕(计入事件与合计——同封印第二份兑付)。 + # = 授予行专带 highlight="seal_hit"(实测 87 行 == 受理封印 87 动作,1:1 精确)。 # 满层拒收行(reward_ineffective)零兑付不入。标空事件=归因行(type=seal_miss 每格恰一次); # 标空惩罚合计只入一次性兑付行(flat 直伤 damage/heal + gp_loss escrow 行)——sapped 授予行 # 与其状态复发行行侧不可区分不入合计(登记注记,判读侧按事件数补算)。 if row.source_class == "seal_hit" and row.type != "reward_ineffective": - if String(row.get("highlight", "")) == "seal_hit" \ - or String(row.get("display_name", "")).contains("雷区图谱"): + if String(row.get("highlight", "")) == "seal_hit": st.seal_hit += 1 st.seal_hit_gain += int(row.value) if row.type == "seal_miss": diff --git a/game/tests/unit/battle_settlement/variant_placement_test.gd b/game/tests/unit/battle_settlement/variant_placement_test.gd index 415c86de..620c3be3 100644 --- a/game/tests/unit/battle_settlement/variant_placement_test.gd +++ b/game/tests/unit/battle_settlement/variant_placement_test.gd @@ -236,7 +236,7 @@ func _smoke_global_variant() -> void: Kit.check("生存族下调:heal 4→3 / defense 11→7(v=30 构造例)", wmap.get("heal_minor", -1) == 3 and wmap.get("ac_up", -1) == 7) Kit.check("进攻族上浮:attack 14→15 / blast 16→18 / pierce 8→9 / magic 8→9(v=30 构造例,等比上浮守恒)", wmap.get("attack_up", -1) == 15 and wmap.get("spark_aoe", -1) == 18 and wmap.get("pierce_strike", -1) == 9 and wmap.get("magic_bolt", -1) == 9) eco.roller.board_skew = 30 - var combo_rows: Array = eco.roller._biased_cell_rows(2) # 件级加算 2=偏运硬币行 value(reward_roll bias_rewards 命中面同值) + var combo_rows: Array = eco.roller._biased_cell_rows(2) # 件级加算 2=订阅行 value(reward_roll bias_rewards 命中面同值) var cw := _rows_weight_map(combo_rows) Kit.check("合成序:图级偏斜先(乘法面)件级 luck_bias 后(加法 +2×四稀有类)——合计 77+8", eco.roller._pool_weight(combo_rows) == 77 + 4 * 2) Kit.check("合成序构造例:skew(heal 3)+2=5 / gp 2+2=4 / pierce 9+2=11 / magic 9+2=11(图级定型后玩家构筑叠加)", cw.get("heal_minor", -1) == 5 and cw.get("gp_coin", -1) == 4 and cw.get("pierce_strike", -1) == 11 and cw.get("magic_bolt", -1) == 11) diff --git a/game/tests/unit/core/meta_progression_forge_test.gd b/game/tests/unit/core/meta_progression_forge_test.gd index 7048c521..84bdd583 100644 --- a/game/tests/unit/core/meta_progression_forge_test.gd +++ b/game/tests/unit/core/meta_progression_forge_test.gd @@ -674,7 +674,7 @@ func _smoke_tree_rules() -> void: ctx_fz2.level_bucket = lvl_shared # 挂同一 level 桶引用(新形态跨战持久:无 export/seed,同字典即持久) Kit.check("锋:限次跨战持久(level 桶共享引用——替代旧副本搬运链)〔无状态化 V4〕", (fz2.dispatch(ctx_fz2, "mine_hit", {}, Callable()) as Array).is_empty()) - # 锋·惊巢反制效果行换代断言(迭代36 u13/wa12——_grant_routed 减半分支效果行=战斗日志 + # 锋·挖掘惩罚减半效果行换代断言(迭代36 u13/wa12——_grant_routed 减半分支效果行=战斗日志 # step_row 真实生产面;display_name 玩家可见,禁字「挖雷」由此行清零钉住) var orch_nc = load("res://core/battle_orchestrator.gd").new(_db, _fresh_rng(777003)) orch_nc.begin_battle({"level_index": 1, "node_depth": 0, "hero_hp": 40, "hero_atk": 8, "hero_max_hp": 40, @@ -687,17 +687,17 @@ func _smoke_tree_rules() -> void: # heal 负向行表值 power=6(极性字典行值——负向 power 走表值不走快照)→ halve 50% ceil=3 orch_nc.reward_grant().grant_routed({"cell_type": "heal", "power": 10}, "negative", {"source_class": "mine_hit", "cell": Vector2i.ZERO, "ri": 0, "halve_pct": 50}) - # 受理判据=惊巢反制效果行落 step_row(halve 分支先于 dispatch 发行——flat 行 _apply_flat_row 分派 + # 受理判据=减半效果行落 step_row(halve 分支先于 dispatch 发行——flat 行 _apply_flat_row 分派 # 恒返 false,返回值不承载受理语义;行发行即分支受理) var nc_hit := "" for r in nc_rows: - if String((r as Dictionary).get("display_name", "")).contains("惊巢反制"): + if String((r as Dictionary).get("display_name", "")).contains("挖掘惩罚减半"): nc_hit = String((r as Dictionary).get("display_name", "")) break - Kit.check("锋:惊巢反制 mine_hit 减半分支受理(wa12 前提——halve_pct=50 效果行落 step_row)〔wa12〕", + Kit.check("锋:挖掘惩罚减半 mine_hit 减半分支受理(wa12 前提——halve_pct=50 效果行落 step_row)〔wa12〕", nc_hit != "") - Kit.check("惊巢反制效果行==「惊巢反制——危险格挖掘惩罚减半(6→3)」零「挖雷」(u13 换代)〔wa12〕", - nc_hit == "惊巢反制——危险格挖掘惩罚减半(6→3)" and not nc_hit.contains("挖雷")) + Kit.check("减半效果行==「挖掘惩罚减半(6→3)」零「挖雷」(u13 换代)〔wa12〕", + nc_hit == "挖掘惩罚减半(6→3)" and not nc_hit.contains("挖雷")) # 守侧五场景(契约 12):编排 rig——begin_battle 携 sense_guard,授予段 _grant_seg._judge_seal 直注 var orch = load("res://core/battle_orchestrator.gd").new(_db, _fresh_rng(777001)) Kit.check("守侧 rig:战斗编排启动(tree_rules=sense_guard 携带)", diff --git a/game/tests/unit/data_config/effect_kind_retired_test.gd b/game/tests/unit/data_config/effect_kind_retired_test.gd index fe9819cb..a3b46a29 100644 --- a/game/tests/unit/data_config/effect_kind_retired_test.gd +++ b/game/tests/unit/data_config/effect_kind_retired_test.gd @@ -11,12 +11,33 @@ const Kit := preload("res://tests/unit/test_kit.gd") const SRC_DIR := "res://data/tables" const BAD_OVERFLOW_DIR := "user://effect_kind_fixture_overflow" const BAD_SEGMENTS_DIR := "user://effect_kind_fixture_segments" +const BAD_SPIKE_DIR := "user://effect_kind_fixture_spike" +const BAD_TRADEKEY_DIR := "user://effect_kind_fixture_tradekey" # 注入探针:死通道 do.kind(甲案摘名两族——各一探针行) const PROBE_OVERFLOW := ' {\n "feat_id": "kind_overflow_probe",\n "display_name": "通道探针·溢出",\n "rarity": "common",\n "triggers": [ { "on": "dig_reveal", "when": [], "do": { "kind": "overflow", "value": 50 } } ],\n "desc": "夹具探针——甲案退役词 overflow"\n},\n' const PROBE_SEGMENTS := ' {\n "feat_id": "kind_segments_probe",\n "display_name": "通道探针·连珠",\n "rarity": "common",\n "triggers": [ { "on": "dig_reveal", "when": [], "do": { "kind": "attack_segments", "cap": 2, "divisor": 3, "value": 0 } } ],\n "desc": "夹具探针——甲案退役词 attack_segments"\n},\n' +# 注入探针:改写族退役词(改写族清退批 T2)——spike kind 出域与 trade 键出域(各一探针行) +const PROBE_SPIKE_MODE := ' { + "feat_id": "kind_spike_probe", + "display_name": "词表探针·甲", + "rarity": "common", + "triggers": [ { "on": "dig_reveal", "when": [], "do": { "kind": "spike", "value": 2 } } ], + "desc": "夹具探针——改写族退役 kind spike" +}, +' +const PROBE_TRADE_KEY := ' { + "feat_id": "kind_tradekey_probe", + "display_name": "键闭探针·乙", + "rarity": "common", + "triggers": [ { "on": "dig_reveal", "when": [], "do": { "kind": "grant_ap", "trade_hit": 5, "value": 50 } } ], + "desc": "夹具探针——改写族退役 do 键 trade_hit" +}, +' + + func _inject(dir: String, probe: String) -> bool: var path := dir + "/feats.tres" var f := FileAccess.open(path, FileAccess.READ) @@ -65,5 +86,11 @@ func _init() -> void: if not _assert_rejected(BAD_SEGMENTS_DIR, PROBE_SEGMENTS, "effect_kind_retired_test/②attack_segments 出域"): quit(2) return - print("[effect_kind_retired_test] 双探针均正确拒绝(甲案词表退役——死通道误写加载致命)〔架构整改 V3〕") + if not _assert_rejected(BAD_SPIKE_DIR, PROBE_SPIKE_MODE, "effect_kind_retired_test/③词表闭面:kind=spike 出域拒绝"): + quit(2) + return + if not _assert_rejected(BAD_TRADEKEY_DIR, PROBE_TRADE_KEY, "effect_kind_retired_test/④do 键闭面:trade_hit 出域拒绝"): + quit(2) + return + print("[effect_kind_retired_test] 四探针均正确拒绝(甲案词表退役+改写族清退——退役词/键误写加载致命)〔架构整改 V3〕〔改写族清退 T2〕") quit(1) From c89e59febba85fd02e29d236350d4286b33dd778 Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Fri, 6 Nov 2026 00:08:18 +0800 Subject: [PATCH 05/10] =?UTF-8?q?iter53-=E6=94=B6=E5=B0=BE=EF=BC=9A?= =?UTF-8?q?=E8=BF=AD=E4=BB=A353=E4=BA=A7=E5=87=BA=E7=89=A9:=20=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=E6=8A=A5=E5=91=8A+=E5=8F=8D=E5=93=BA=E7=82=B9?= =?UTF-8?q?=E6=B8=85=E5=8D=9510=E6=9D=A1+=E7=8B=AC=E7=AB=8B=E9=AA=8C?= =?UTF-8?q?=E6=94=B6=E5=AE=A1=E8=AE=A1(=E9=80=9A=E8=BF=87)=EF=BC=9B?= =?UTF-8?q?=E5=B9=B6master(fd9c8ad9=20QA=20harness=20=E5=AE=9A=E6=A1=88?= =?UTF-8?q?=E7=99=BB=E8=AE=B0+=E8=90=A5=E5=9C=B0=E8=83=8C=E6=99=AF?= =?UTF-8?q?=E5=B1=82=E4=B8=A4=E6=89=B9,=E9=9B=B6=E4=BA=A4=E9=9B=86)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- design/art/art-bible.md | 4 +- design/art/camp-scene-prompts.md | 126 +++++++++++++++++++------- design/gdd/ux/camp.md | 4 +- playnote.md | 31 +++++-- reports/iter53-反哺点-2026-11-05.md | 21 +++++ reports/iter53-实现报告-2026-11-05.md | 80 ++++++++++++++++ reports/iter53-验收审计-2026-11-05.md | 122 +++++++++++++++++++++++++ 待办清单.md | 8 ++ 8 files changed, 350 insertions(+), 46 deletions(-) create mode 100644 reports/iter53-反哺点-2026-11-05.md create mode 100644 reports/iter53-实现报告-2026-11-05.md create mode 100644 reports/iter53-验收审计-2026-11-05.md diff --git a/design/art/art-bible.md b/design/art/art-bible.md index 1ca77c1f..53c21eb9 100644 --- a/design/art/art-bible.md +++ b/design/art/art-bible.md @@ -392,12 +392,12 @@ - **情绪与色域**:承载 §2.8——全作最暖:烛光黄 `#F6C667` × 木色 `#8A5A34`(§7.2),中等饱和,无棋盘式高对比。 - **场景构成**:一张可点击的营地场景图(1280×800,与工程档同幅面)。远景=天空与远山;中景=**独立成层的木围墙**(密排竖木桩、桩顶削尖、不透缝无横木)与**半开的营地大门**;近景=中央篝火、左侧锻炉铁砧、右侧帐篷与宝箱、帐篷旁的笔记本,另有木桩与挂在围墙上的布告板。**中景带自底部往上约 2/3 处起**;**近景物件可覆盖围墙,唯一例外=中间门洞必须留空、不被任何物件遮挡**。七个可点物件的功能绑定归 `camp.md`,本节只定画法。 - **图层拆分(10 张)**:场景按「远景/中景/近景要素各自成层」拆——`scene_camp_bg` 背景层(z0,不透明全幅)=天空+远山+整片地面+门洞内一条通向远处的小路;`scene_camp_wall` 围墙层(z1,透明底)=横贯全宽密排木桩墙(左右两段)+两根略高的门柱,**门洞处留透明缺口**透出背景层的小路;`scene_camp_board` 布告板(z2)、`scene_camp_gate` 门扇(z3)、`scene_camp_dummy` 木桩/`scene_camp_forge` 锻炉/`scene_camp_tent` 帐篷(z4)、`scene_camp_chest` 宝箱/`scene_camp_notebook` 笔记本(z5)、`scene_camp_campfire` 篝火(z6,最前)=八个物件层,各透明底单件一张。**帐篷**为承载件、不可点。围墙独立成层的好处:桩高可单独锁死、门洞做透明缺口、背景层不混入暖木色。提示词与坐标 = `camp-scene-prompts.md`,消费常量 = `asset-path-map`。 -- **交付形态**:**背景层 1 张(不透明全幅)+ 围墙层 1 张 + 八个物件层 = 10 张**,其中 9 张透明底、1 张不透明全幅 + 一份坐标表(贴图矩形/命中矩形/z 序)。**篝火例外**:命中矩形只取下半(火堆),上半(火焰)只作特效展示。围墙层落盘按细条裁,不做全幅(全幅约 3.9 MB 显存,细条约 0.35 MB);**实装落盘矩形 `(0, 261, 1280, 49)`、底锚 y310**(Y 压缩按桩身 43px 终稿锁定值精确,落带内〔规划带 (0,240,1280,70)〕;备选 A′〔带高 70/桩身 62〕存档 artwork 同目录)。 +- **交付形态**:**背景层 1 张(不透明全幅)+ 围墙层 1 张 + 八个物件层 = 10 张**,其中 9 张透明底、1 张不透明全幅 + 一份坐标表(贴图矩形/命中矩形/z 序)。背景层由**远景片 `bg_far`(2560×734)与地面片 `bg_floor`(2560×866)两片出图、按 y734 拼成一张**——整张一次出图时模型把远山挤到画面下半部,被围墙挡住后完全消失(实测三张里两张山体上缘落在墙顶以下)。接缝整条落在围墙背后,画面无接缝。**篝火例外**:命中矩形只取下半(火堆),上半(火焰)只作特效展示。围墙层落盘按细条裁,不做全幅(全幅约 3.9 MB 显存,细条约 0.35 MB);**实装落盘矩形 `(0, 203, 1280, 164)`、底锚 y367**(桩身 150px、门柱 164px 终稿锁定值,落带内〔围墙带 (0,203,1280,164)〕)。 - **色彩与氛围依据**:营地场景的冷暖分工(冷的大面积后退、暖的小面积前进)、空气透视三档与大面积用色规则 = `reports/提案-营地色彩与氛围脚本-2026-10-23.md`。本节不复述色值;新增环境色按 §4.1 场景环境子板条款登记(每屏一套、≤32 色、过 §4.2 语义检查与 RGB 三通道差 ≥8/255 两道门)。 - **交互四态(零新素材,全部程序化)**:悬停=**轮廓亮边 + 浮动**(浮动须整像素吸附);按下=位移 1px;**禁用/未解锁=降明度 + 去饱和**(§2 已缩窄至情绪域,状态表达不受限),**仅锻炉(锻造工坊)与宝箱(秘宝匣)两件会有此态**;已解锁=常态。 - **钥石余额**:常驻画面顶部的一行小 HUD 栏(高 48px,**浮层覆盖,不挤压画面**)。 - **事实源边界**:解锁条件/价格/存档写入归元进度 GDD 与 `MetaProgression`;素材命名与路径归 `asset-path-map`;清单登记归 `art-assets-checklist` §3.5。 -- **已裁(2026-11-01 用户裁)**:① **营地环境子板色值**——不前置拍板:量化场景实际用色后按 §4.1 场景环境子板条款登记(每屏一套、≤32 色、过 §4.2 语义检查与 RGB 三通道差 ≥8/255 两道门);② **门扇与门洞的高宽比例**——门扇 240×220 追认现值,坐标按门洞 x520–760 对齐(`camp-scene-prompts.md` §2.3);③ **帐篷的落地尺寸**——300×170 追认现值(各素材第一张样本稿已过审为终稿,重定即触发重出,不裁)。 +- **已裁(2026-11-01 用户裁)**:① **营地环境子板色值**——不前置拍板:量化场景实际用色后按 §4.1 场景环境子板条款登记(每屏一套、≤32 色、过 §4.2 语义检查与 RGB 三通道差 ≥8/255 两道门);② **门扇与门洞的高宽比例**——门扇贴图 240×138(锁定 240×147),随门洞 y283–367 压扁重画,坐标按门洞 x520–760 对齐;③ **帐篷的落地尺寸**——251×170 落位 (982, 335),上端遮住围墙下部。 ### 6.3 三关图类型色板候选(board_type 换挡方向) diff --git a/design/art/camp-scene-prompts.md b/design/art/camp-scene-prompts.md index a269ff63..38e35f2e 100644 --- a/design/art/camp-scene-prompts.md +++ b/design/art/camp-scene-prompts.md @@ -1,9 +1,9 @@ # 营地场景 · 分层生图提示词卡 v1.5 > **性质**:营地场景图(1280×800,一张可点击场景图 + 十张分层:背景层 1 + 围墙层 1 + 八个物件层)的出图执行侧文件。**场景级资产,与角色级 [art-prompts](art-prompts.md) 并列,两文件互不覆盖**。 -> **依据**:色彩与氛围 = `reports/提案-营地色彩与氛围脚本-2026-10-23.md`(本卡不复述色值);坐标与层序 = `artwork/2026-10-23-营地场景/布局草案-1280x800.html`;物件命名与消费链 = [asset-path-map](asset-path-map.md);画法与交付形态 = [art-bible](art-bible.md) §6.2。冲突时色彩以色彩脚本为准,画法以 art-bible 为准。 +> **依据**:色彩与氛围 = `reports/提案-营地色彩与氛围脚本-2026-10-23.md`(本卡不复述色值);坐标与层序 = 本卡 §2.3(运行期单一事实源 = `game/data/tables/camp_scene_layout.tres`);物件命名与消费链 = [asset-path-map](asset-path-map.md);画法与交付形态 = [art-bible](art-bible.md) §6.2。冲突时色彩以色彩脚本为准,画法以 art-bible 为准。 > **边界**:只管营地场景图的分层出图。角色、图标、格面走 art-prompts.md 与脚本管线,不需要提示词。 -> **建立**:2026-10-25 · 状态:十条提示词成文(背景层 1 + 围墙层 1 + 八个物件层),出图通道由作者自定 +> **建立**:2026-10-25 · 状态:十条提示词成文(背景层 1 + 围墙层 1 + 八个物件层);2026-11-05 按地平线 y367 重排,背景层与围墙层待按 §4 新判据重出,门扇随门洞压扁重画 --- @@ -14,7 +14,7 @@ 3. **后处理**:脚本管线代跑——去底转透明、降采样到终稿尺寸(整数倍)、色板量化、四联底测试条。**背景层不去底(全幅不透明)**;围墙层与八个物件层去底转透明。后处理工具清单与用法见 [art-pipeline-tools](art-pipeline-tools.md)。 4. **转正**:终稿转入切片资产目录,按坐标表接线。 -**出图顺序(先锁后产,不能跳)**:概念脚本 → **本卡提示词** → 贴风格参考图**先出背景层 `scene_camp_bg` 1 张** → 作者确认风格前缀 → 才扩产围墙层 `scene_camp_wall` 与八个物件层(共 9 张)。 +**出图顺序(先锁后产,不能跳)**:概念脚本 → **本卡提示词** → 贴风格参考图**先出远景片 `bg_far` 1 张** → 作者确认风格前缀 → 才出地面片 `bg_floor`、围墙层与八个物件层。 --- @@ -43,22 +43,57 @@ Style reference: the attached images are this game's own finished pixel art and ### 2.1 背景层(`scene_camp_bg`,不可点,不透明全幅) -**出图画布**:2560×1600(终稿 1280×800 的 2 倍,保证整数倍降采样) -**画什么**:天空、远山、整片地面、门洞位置一条通向远处的小路 -**不画什么**:木围墙、门柱、门扇、七个物件、角色、接地阴影——围墙与门柱是 §2.2 的独立层,门洞是它的透明缺口;小路在本层画好、透出来即可 +**产出方式**:分两片出图,后处理按 y734 拼成一张 2560×1600。接缝整条落在围墙层(406–734)背后,画面里看不见。 + +| 片 | 出图画布 | 终稿落位 | 内容 | +|---|---|---|---| +| 远景片 `bg_far` | 2560×734(3.5:1 超宽) | (0, 0, 1280, 367) | 天空+远山+草地+小路 | +| 地面片 `bg_floor` | 2560×866(3:1 超宽) | (0, 367, 1280, 433) | 营地内踩实裸土 | + +**为什么分两片**:整张一次出图时,模型按「构图好看」分配天地比例,山被挤到画面下半部——三张实测里两张的山体整段落在围墙后面(山体上缘 y280/y227,墙顶 217),远山等于消失。拆开后远景片的全部高度都归天空+山+草地,山才可能长到围墙之上。 + +#### 2.1.1 远景片(`bg_far`) + +**画布比例**:3.5:1 超宽。通道支持直接出 2560×734;不支持则按 3:2 出图后纵向压到 3.5:1,构图比例不变 +**分带(按画面高度)**: +- 天空 0–14% +- 远山 14–55%(**山体占 41%,硬指标**) +- 草地 55–100% +- 小路在草地内:从底边向上收窄,到山脚为止,**不越过山脚、不上探到天空** +**画什么**:天空、2–3 层远山、成片草地、草地中央一条土路 +**不画什么**:围墙、门柱、门扇、物件、角色、营地内地面(那是 §2.1.2);山与草地之间禁出现平直硬边 ``` -Pixel art style. True pixel art game background layer drawn with chunky square pixels, strict pixel grid alignment, hard edges, no anti-aliasing, no gradients, flat colors only, a limited palette of about 24 colors, retro 16-bit look, Aseprite style, all ages, flat side view, orthographic, no perspective distortion. Wide horizontal composition, 16:10 aspect ratio. This is the FAR BACKGROUND LAYER ONLY of a small adventurer camp: sky, distant hills and the whole ground. It must contain no palisade wall, no gate posts, no camp objects, no gate leaves, no characters and no drop shadows, because all of those are drawn as separate transparent layers on top of this one. COLOR SCRIPT — cool recedes, warm advances: the sky, the hills and the ground are all COOL, pale, desaturated and low in contrast; there is no warm accent anywhere in this layer, warm color belongs only to the separate object layers drawn on top. ATMOSPHERIC DEPTH: every plane that is farther away is lighter, closer to the value of the sky, cooler, lower in contrast and simpler in detail, while the nearest plane is the darkest and highest in contrast. SKY (top of frame): the lightest thing in the picture, flat pale cool off-white with a faint blue-grey tint, no yellow or cream tone, no sun anywhere; the very top strip of the frame, about one sixteenth of the frame height, stays completely calm and empty, reserved as clear space with nothing in it; at most one or two extremely simple flat low-contrast clouds. FAR DISTANCE: two or three layers of low rolling hill silhouettes in pale cool blue-grey, each farther layer lighter, cooler and lower in contrast than the one in front, fading towards the value of the sky, no trees, no individual foliage. HILLS TO GROUND: the hills fade gradually and smoothly down into the ground, with NO visible horizon line and NO distant ground band — the transition must not read as a separate horizontal stripe of a different color. GATE PATH: in the middle of the frame, between x=1040 and x=1520, one clearly visible dirt path runs from the ground at two thirds of the frame height measured from the bottom edge away into the distance between the hills, narrowing as it recedes, painted in a muted desaturated grey-brown earth tone, never golden or warm yellow; this path shows through the empty gate opening of the wall layer above. FOREGROUND GROUND: the darkest area of the picture, dry packed bare earth in a neutral desaturated grey-brown, never golden, amber or warm yellow, hard flat color blocks, hard edges, no gradient, no grass, no grass tufts, no weeds and no plants of any kind. The foreground ground is completely empty apart from the dirt path: no objects, no icons, no badges, no markers, no decorations of any kind. Do not add any of the following: realistic, photorealistic or 3D rendering; painterly brushwork, smooth anti-aliased lines, gradient or dithered shading, glossy highlights; black or heavy dark outlines; drop shadows, contact shadows or any shadow band; blur or compression artifacts; a vignette, dark corners, or any mood darkening; night, dusk, moon, stars, sunset or sunrise light; a sun or any light source drawn in the sky; a visible horizon line, a separate horizontal distant ground band or any distant grass strip below the hills; trees, forests or foliage in the distance; grass, grass tufts, weeds or plants in the foreground; a palisade wall, wooden fence, fence posts, gate posts or any wall structure; any warm, golden, amber or yellow cast on the sky, on the hills or on the ground; any camp object, furniture, crate, barrel, fire, tent or tool; any gate leaf, door panel or hinge; any purple or magenta anywhere; any text, letters, numbers, watermark, signature or logo; any frame, border, panel, arrow or UI element; any icon, badge, item tile, emblem, sign, marker or symbol anywhere in the frame; any characters, people, creatures or animals. +Pixel art style. True pixel art game background, chunky square pixels, strict pixel grid, hard edges, no anti-aliasing, flat colors, limited palette about 20 colors, retro 16-bit look, Aseprite style, flat side view, orthographic, ULTRA WIDE horizontal composition, aspect ratio 3.5 to 1. This is the far view seen from inside a small adventurer camp, looking out. It contains ONLY three bands stacked top to bottom, plus one path. BAND 1 — SKY, from the top edge down to 14 percent of the frame height: pale cool off-white with a faint blue-grey tint, flat and empty, at most one or two extremely simple flat clouds, no sun. BAND 2 — DISTANT HILLS, from 14 percent down to 55 percent of the frame height: two or three overlapping layers of rolling hills in pale cool blue-grey-green, each farther layer lighter, cooler and lower in contrast. THE HILLS MUST FILL THIS ENTIRE BAND — the highest ridgeline reaches up to 14 to 20 percent of the frame height and the hill mass continues down to 55 percent; a low ridge hugging the bottom of the frame is WRONG. Silhouette edges are stepped in pixel blocks, no outline, no rim light. BAND 3 — MEADOW, from 55 percent down to the bottom edge: cool pale grey-green grass, flat and low contrast, marked only by a few simple flat grass tufts, no trees, no bushes. PATH — one dirt path in the meadow only: it starts at the bottom edge of the frame in the middle, about one fifth of the frame width there, runs straight up and narrows until it meets the hill foot at 55 percent, where it disappears; it must not go above the hill foot and must not reach the sky. COLOR: everything cool, pale, desaturated, low contrast, no warm, golden, amber or yellow anywhere. DO NOT ADD: any palisade wall, fence, gate, gate posts, tent, campfire, crate, barrel, prop, character, animal; any hard straight horizontal seam between sky, hills and meadow — the hill foot dissolves into the meadow through stepped intermediate tones; any outline or rim; trees, forests or dense vegetation; antialiasing, gradients, dithering, painterly strokes, 3D, realistic shading, glossy light, bloom, vignette, dark corners, night, sunset, sun; any text, letters, number, watermark, signature, logo, frame, border, UI element, icon, badge. ``` +#### 2.1.2 地面片(`bg_floor`) + +**画布比例**:3:1 超宽 +**内容**:营地内的踩实裸土,铺满整幅 +**硬指标**:**中线与左右两侧同色——没有任何路、小径、车辙**;明度 30%–45%;色相与远景片草地明显区分 +**不画什么**:草、植被、大石块、物件、天空、地平线、围墙、接缝线 + +``` +Pixel art style. True pixel art game ground texture, chunky square pixels, strict pixel grid, hard edges, no anti-aliasing, flat colors, limited palette about 12 colors, retro 16-bit look, Aseprite style, ULTRA WIDE horizontal composition, aspect ratio 3 to 1. This is the trodden floor INSIDE a small adventurer camp — bare packed dry earth filling the whole frame edge to edge, seen at a shallow angle from slightly above. MATERIAL: desaturated warm grey-brown, medium value, roughly 30 to 45 percent luminance, never dark, never muddy. TEXTURE: deliberate pixel clusters only — short paired scuff marks that read as dragged footprints, small scattered pebbles, beaten patches where feet have worn the ground smooth, occasional faint drag marks; density rises slightly toward the bottom edge and the middle stays calm and open. CRITICAL, NO PATH: there is no road, no trail, no track, no wheel rut and no worn strip anywhere in this image — the middle of the frame must look the same as the left and right edges, nothing leads anywhere. DO NOT ADD: grass, vegetation, plants, flowers, moss, lichen; rocks larger than a pebble; crates, sticks, bones, debris piles, tools; water, puddles; shadows of objects; sky, horizon, hills, wall, fence, gate, building; any line, seam, border or edge inside the frame; antialiasing, gradients, dithering, painterly strokes, 3D, realistic shading, glossy light, bloom, vignette, dark corners, warm golden cast; any text, letters, number, watermark, signature, logo, frame, border, UI element, icon, badge. +``` + +#### 2.1.3 拼接与后处理 + +1. 两片各缩放到终稿尺寸:远景片 1280×367、地面片 1280×433 +2. 按 y367 上下拼接成 1280×800 +3. 量化到营地环境子板(≤32 色) +4. 需要 2× 档时整数倍放大到 2560×1600 +5. 接缝不做过渡处理——它整条落在围墙(203–367)背后 + ### 2.2 围墙层(`scene_camp_wall`,不可点,透明底) -**出图画布**:2560×1600(与背景层同画布,门洞 x 坐标直接对齐);墙横贯画在出图 y480–620 这条**窄带**内,其余为纯色底 `#F2F2F2`。落盘由 S4 后处理裁成终稿外接矩形 `(0, 240, 1280, 70)` / 出图 `(0, 480, 2560, 140)` 的细条,**不做全幅 1280×800 落盘**(全幅约 3.9 MB 显存,细条约 0.35 MB)。 -**画什么**:横贯全宽的密排竖木桩墙(左右两段)+ 两根略高的门柱,门洞处完全透明 +**出图画布**:2560×1600(与背景层同画布,门洞 x 坐标直接对齐);墙横贯画在出图 y406–734 这条带内(桩身 y434–734,门柱 y406–734),其余为纯色底 `#F2F2F2`。落盘由 S4 后处理裁成终稿外接矩形 `(0, 203, 1280, 164)` / 出图 `(0, 406, 2560, 328)` 的细条,**不做全幅 1280×800 落盘**(全幅约 3.9 MB 显存,细条约 0.35 MB)。 +**画什么**:横贯全宽的密排竖木桩墙(左右两段,桩身终稿 150 高)+ 两根略高的门柱(终稿 164 高),门洞处完全透明 **不画什么**:天空、远山、地面、小路、门扇、七个物件、角色;门洞内不画任何东西,透出背景层的小路 ``` -Pixel art style. True pixel art game layer drawn with chunky square pixels, strict pixel grid alignment, hard edges, no anti-aliasing, no gradients, flat colors only, a limited palette of about 24 colors, retro 16-bit look, Aseprite style, all ages, flat side view, orthographic, no perspective distortion. Wide horizontal composition, 16:10 aspect ratio. This is the PALISADE WALL LAYER ONLY of a small adventurer camp, drawn on a plain flat uniform light grey #F2F2F2 background for easy keying. A wooden palisade wall runs straight across the full width of the frame, seen from the front, built from closely spaced vertical logs standing side by side with no gaps between them, every log cut to a sharp point at the top, a solid barrier with no horizontal rails, no see-through gaps, no ranch-style post-and-rail fence. The wall is SHORT and LOW: including the pointed tips the whole band occupies only about one eighteenth of the total frame height, a thin horizontal strip, NOT a tall barrier; the logs stand only about one eighteenth of the total frame height above their base line. In the middle of the wall one wide gap holds two thick gate posts slightly taller than the wall, and the entire opening between them is completely EMPTY — plain flat uniform light grey #F2F2F2 showing through, no logs, no path, no ground, no scenery inside the opening, because the dirt path and the hills belong to the background layer below and the gate leaves are a separate object layer. The wall is painted in a muted greyed wood brown, with a thin warm cream outline around the whole silhouette, flat shading. Do not add any of the following: realistic, photorealistic or 3D rendering; painterly brushwork, smooth anti-aliased lines, gradient or dithered shading, glossy highlights; black or heavy dark outlines; drop shadows or contact shadows; blur or compression artifacts; a vignette or dark corners; any sky, hills, ground, grass, dirt path or scenery of any kind; any gate leaf, door panel or hinge; any camp object, furniture, crate, barrel, fire, tent or tool; any characters, people, creatures or animals; any purple or magenta anywhere; any text, letters, numbers, watermark, signature or logo; any frame, border, panel, arrow or UI element. +Pixel art style. True pixel art game layer drawn with chunky square pixels, strict pixel grid alignment, hard edges, no anti-aliasing, no gradients, flat colors only, a limited palette of about 24 colors, retro 16-bit look, Aseprite style, all ages, flat side view, orthographic, no perspective distortion. Wide horizontal composition, 16:10 aspect ratio. This is the PALISADE WALL LAYER ONLY of a small adventurer camp, drawn on a plain flat uniform light grey #F2F2F2 background for easy keying. A wooden palisade wall runs straight across the full width of the frame, seen from the front, built from closely spaced vertical logs standing side by side with no gaps between them, every log cut to a sharp point at the top, a solid barrier with no horizontal rails, no see-through gaps, no ranch-style post-and-rail fence. The wall stands on the ground line at y=734 of 1600. The LOG BODIES, pointed tips included, rise 300 pixels above that base line — about nineteen percent of the total frame height — so it reads as a real barrier with presence, clearly taller than the gate opening cut into it, not a thin decorative strip. In the middle of the wall one wide gap holds two thick gate posts standing 28 pixels taller than the logs, and the entire opening between them is completely EMPTY — plain flat uniform light grey #F2F2F2 showing through, spanning x=1040 to x=1520 and rising from the base line y=734 up to y=566, no logs, no path, no ground, no scenery inside the opening, because the dirt path and the hills belong to the background layer below and the gate leaves are a separate object layer. The wall is painted in a muted greyed wood brown, with a thin warm cream outline around the whole silhouette, flat shading. Do not add any of the following: realistic, photorealistic or 3D rendering; painterly brushwork, smooth anti-aliased lines, gradient or dithered shading, glossy highlights; black or heavy dark outlines; drop shadows or contact shadows; blur or compression artifacts; a vignette or dark corners; any sky, hills, ground, grass, dirt path or scenery of any kind; any gate leaf, door panel or hinge; any camp object, furniture, crate, barrel, fire, tent or tool; any characters, people, creatures or animals; any purple or magenta anywhere; any text, letters, numbers, watermark, signature or logo; any frame, border, panel, arrow or UI element. ``` ### 2.3 出图画布上的坐标(终稿 ×2) @@ -66,11 +101,17 @@ Pixel art style. True pixel art game layer drawn with chunky square pixels, stri | 元素 | 终稿 1280×800 | 出图画布 2560×1600 | |---|---|---| | 顶栏 HUD 保留带 | y ≤ 48 | **y ≤ 96**(保持空旷) | -| 背景层 `scene_camp_bg` | 全幅 1280×800 | 全幅 2560×1600 | -| 围墙带(wall 层桩身) | y 267–310(**高 43px**) | y 534–620(**高 86px**) | -| 门柱(wall 层,略高) | y 240–310;x 500–520 / 760–780 | y 480–620;x 1000–1040 / 1520–1560 | -| 门洞(wall 层透明缺口) | x 520–760 | x 1040–1520 | -| 门洞内小路(画在 bg 层) | x 520–760,自 y310 向上收窄至远山 | x 1040–1520,自 y620 向上收窄至远山 | +| 远景片 `bg_far` | y 0–367(高 367) | y 0–734(高 734,3.5:1) | +| 地面片 `bg_floor` | y 367–800(高 433) | y 734–1600(高 866,3:1) | +| 两片接缝 | **y 367**(落在围墙 203–367 背后) | **y 734**(落在围墙 406–734 背后) | +| 地平线(山脚/草地起点) | y 与两片接缝重合,墙背后不可见 | 同左 | +| 远山带 | y 51–202(画面 14%–55%,山体 41%) | y 103–403 | +| 草地带 | y 202–367 | y 403–734 | +| 围墙层外接矩形 | y 203–367(高 164) | y 406–734(高 328) | +| 围墙带(wall 层桩身) | y 217–367(**高 150px**) | y 434–734(**高 300px**) | +| 门柱(wall 层,略高) | y 203–367(高 164);x 500–520 / 760–780 | y 406–734;x 1000–1040 / 1520–1560 | +| 门洞(wall 层透明缺口) | y 283–367(高 84);x 520–760 | y 566–734(高 168);x 1040–1520 | +| 门洞内小路(画在远景片草地内) | x 520–760 穿门洞,自接缝 y367 向上收窄,到山脚 y202 消失 | x 1040–1520,自 y734 向上收窄,到 y403 消失 | --- @@ -97,7 +138,7 @@ Do not add any of the following: realistic, photorealistic or 3D rendering; pain | 件 | z 序 | 终稿矩形 | 出图画布 | 正文 | |---|---|---|---|---| | 布告板 | 2 | 130×140 | 260×280 | §3.1 | -| 门扇 | 3 | 240×220 | 480×440 | §3.2 | +| 门扇 | 3 | 240×147 | 480×294 | §3.2 | | 木桩 | 4 | 120×180 | 240×360 | §3.3 | | 锻炉·铁砧 | 4 | 240×240 | 480×480 | §3.4 | | 帐篷 | 4(不可点) | 300×170 | 600×340 | §3.5 | @@ -105,7 +146,7 @@ Do not add any of the following: realistic, photorealistic or 3D rendering; pain | 笔记本 | 5 | 100×80 | 200×160 | §3.7 | | 篝火 | 6 | 160×160 | 320×320 | §3.8 | -**落位实测(锁定矩形 contain)**:布告板 130×121/门扇 240×211/木桩 120×180/锻炉 240×193/帐篷 251×170/宝箱 106×90/笔记本 100×66/篝火 160×149——贴图锚定=底中心(帐篷/锻炉/宝箱/篝火/笔记本)+顶锚(门扇悬挂/布告板挂墙);命中矩形按锁定值。换算式登记(源 2× 档→落位尺寸)存 artwork 工作区。 +**落位尺寸(2026-11-05 用户裁地平线 y367 重排后)**:布告板 130×121/门扇 240×138/木桩 120×180/锻炉 240×193/帐篷 251×170/宝箱 106×90/笔记本 100×66/篝火 160×149——贴图锚定=底中心(帐篷/锻炉/宝箱/篝火/笔记本)+顶锚(门扇悬挂/布告板挂墙);命中矩形按锁定值。八件只改落位,门扇另随门洞压扁重画(原 240×211 → 240×138),其余七件沿用现有终稿。 **3.1 布告板(→ 图鉴)** ``` @@ -114,7 +155,7 @@ A wooden notice board hung on a wall, with two or three blank pinned papers, no **3.2 门扇(→ 冒险)** ``` -Two wooden gate leaves hanging from their hinges, half open and tilted outward, each made of thick planks with a cross brace and dark iron fittings, seen from the front, the pair shown together as one single object; wood brown #8A5A34 planks, dark iron fittings. +Two wooden gate leaves hanging from their hinges, half open and tilted outward, each made of thick planks with a cross brace and dark iron fittings, seen from the front, the pair shown together as one single object; the pair together fills a WIDE LOW rectangle about 240 wide by 138 tall, so the leaves read as broad rather than tall, each leaf roughly twice as wide as it is high; wood brown #8A5A34 planks, dark iron fittings. ``` **3.3 木桩(→ 天赋树)** @@ -151,17 +192,32 @@ A campfire made of a ring of grey stones around crossed stacked logs with a warm ## 4. 验收(机检 + 目检) -**背景层 `scene_camp_bg`** -- 黄度 =(R+G)/2−B 分区取样:天空 ≤20、远山 ≤20、地面 ≤35 -- 冷色像素占比 ≥55%;本层不应出现任何暖色高饱和像素 -- 目检:顶部约 1/16 完全空旷;**无地平线、无远景地面带**(远山自然渐隐过渡到地面);不含围墙、门柱、门扇、物件、角色 -- 目检/机检:门洞 x1040–1520 处**有一条清晰可辨、向远处收窄的土路**(非纯色块),透出「出去即冒险」 -- 机检/目检:全幅**无任何独立物件/图标/徽章/标记**(前景地面除小路外全空);参考做法=中下方块区独立色数应≈邻区 +**远景片 `bg_far`** +- 黄度 =(R+G)/2−B 分区取样:天空 ≤20、远山 ≤20、草地 ≤35 +- 冷色像素占比 ≥55%;禁出现任何暖色高饱和像素 +- 机检:**山体上缘 ≤ 画面高度 15%**(这是硬指标——山体上缘落得越低,被围墙挡住后越是什么都看不见) +- 机检:**山体占画面高度 ≥40%**(山体上缘到山脚) +- 机检:草地上限 ≤ 画面高度 55% +- 机检:山脚与草地交界处,上下各 8px 窄带的行均色差 ≤6/255(禁平直硬边;旧稿 y321 处约 37/255) +- 目检:顶部天空空旷、无太阳、云不超过两朵扁平简笔 +- 目检:小路只在草地内,从底边向上收窄到山脚为止,**不越过山脚、不上探到天空** +- 目检:无围墙、门柱、门扇、物件、角色 + +**地面片 `bg_floor`** +- 明度 **L 0.30–0.45**(相对亮度);整片低于 0.30 即判红(旧稿偏暗、观感发闷) +- 机检:画面中线 200px 带与左右各 250px 带的平均色差 ≤6/255(**营地内无路带**) +- 机检:与远景片草地的平均色 (R−B) 差 ≥10/255(两种材质色相可辨) +- 目检:禁出现草、植被、大石块、物件、水面;细节读作拖拽脚印/碎石/踩踏斑块,不是满屏噪点 + +**整图(两片拼接后)** +- 接缝 y367 落在围墙 203–367 背后,**画面里看不见接缝** +- 单张 ≤32 色(量化后) +- 全幅无任何独立物件/图标/徽章/标记 **围墙层 `scene_camp_wall`** - 透明底 `#F2F2F2` 可去底、奶油描边闭合 -- **桩身高度 = 出图 y534–620(终稿 43px);门柱略高 y480–620。桩身超出围墙带下沿 y620 达 5px 以上即判红** -- 目检:密排竖木桩、桩顶削尖、不透缝、无横木;门洞 x1040–1520 **完全透明**(透出 bg 小路)、无门扇 +- **桩身 = 出图 y434–734(终稿 150px);门柱 y406–734(终稿 164px);外接矩形 (0,406,2560,328)。桩身超出下沿 y734 达 5px 以上即判红** +- 目检:密排竖木桩、桩顶削尖、不透缝、无横木;门洞 y566–734 / x1040–1520 **完全透明**(透出 bg 小路)、无门扇;桩身高度须明显大于门洞高度 - 单张色数 ≤32(量化后)、缩放为整数倍无拉伸痕迹 > **量化与缩放实况注记**:围墙层与八件已按营地主色板 **32 色重量化回写**(art-bible §4.1 子板行——违例对 0);落位缩放实况=源 2× 档经后处理换算为锁定矩形 contain(×0.1934–0.4404 非整数倍),「整数倍无拉伸痕迹」判据的机检面以落位实测尺寸与目检兜底执行。 @@ -175,10 +231,16 @@ A campfire made of a ring of grey stones around crossed stacked logs with a warm --- -## 5. 已裁(2026-11-01 用户裁;不再阻塞坐标表与定稿) +## 5. 已裁(2026-11-05 用户裁;不再阻塞坐标表与定稿) -1. **帐篷尺寸**:300×170 追认现值(各素材第一张样本稿已过审为终稿;重定即按比例重出、不裁) -2. **门扇高宽**:240×220 追认现值,坐标按门洞 x520–760 对齐(§2.3);围墙带桩身高 43px、门扇叠在门洞上的叠放关系随此锁定 -3. **布告板位置**:采纳建议值 `(845, 268, 130, 140)` 挂回围墙带;终值随坐标表(`camp_scene_layout.tres`)落盘 -4. **描边颜色**:奶油色追认——去底脚本「奶油描边膨胀 3px 当屏障」的技术前提随现值锁定(§1 注记同源);改深灰褐须换去底方案全量重出,不裁 -5. **营地环境子板色值**:不前置拍板——量化场景实际用色后按 art-bible §4.1 两道门登记(语义检查+RGB 三通道差 ≥8/255),本卡仍不复述色值 +1. **地平线与整体分带**:地平线定在终稿 y367(出图 y734);地面 433px、可见远景 217px(27%);围墙、门、布告板随之上调 +2. **围墙高度**:桩身 150(出图 300)、门柱 164(出图 328)、门洞 84(出图 168);墙高须大于门洞高 +3. **门扇尺寸**:贴图 240×138(锁定 240×147),随门洞压扁重画,坐标按门洞 x520–760 对齐 +4. **帐篷**:251×170 沿用现终稿,落位 (982, 335),遮住墙下部 32px(覆盖围墙可接受) +5. **笔记本**:随帐篷跟随,落在帐篷左下方外侧、两者不重叠——`x = 帐篷 x − 112`、`y = 帐篷底 + 10` +6. **宝箱离底**:贴图底 y744,距画面底 56px;其余物件同步上移 46px +7. **地面分两区**:营地外(y734 以上)=冷调灰绿草地+一条向远山收窄的土路;营地内(y734 至画面底)=踩实裸土、与草地异色相、无草无路无车辙;两区分界被围墙层完全遮住 +8. **背景层分两片出图**:远景片 `bg_far`(2560×734,天空 14%/远山 41%/草地 45%+小路)+ 地面片 `bg_floor`(2560×866 踩实裸土),后处理按 y734 拼成一张 2560×1600;接缝落在围墙 406–734 背后。分片理由=整张出图时模型把山挤到画面下半部,实测三张里两张山体整段被围墙遮没 +9. **布告板位置**:(845, 224, 130, 140),底 345 落在墙内,不再悬空 +10. **描边颜色**:奶油色追认——去底脚本「奶油描边膨胀 3px 当屏障」的技术前提随现值锁定(§1 注记同源);改深灰褐须换去底方案全量重出,不裁 +11. **营地环境子板色值**:不前置拍板——量化场景实际用色后按 art-bible §4.1 两道门登记(语义检查+RGB 三通道差 ≥8/255),本卡仍不复述色值 diff --git a/design/gdd/ux/camp.md b/design/gdd/ux/camp.md index 991baf70..a37ebf0e 100644 --- a/design/gdd/ux/camp.md +++ b/design/gdd/ux/camp.md @@ -20,13 +20,13 @@ | 木桩 | 天赋树 | | | 布告板 | 奖励格图鉴 | 内容冻结未激活,点进看占位——**不是禁用态** | | 篝火 | 离开营地回主菜单 | **必须二次确认**;命中区只含火堆、不含火焰 | -| 帐篷 | — | 承载件,**不可点**;落地尺寸与占位范围待作者重定(待裁口径见 art-bible §6.2) | +| 帐篷 | — | 承载件,**不可点**;251×170 落位 (982, 335),上端遮住围墙下部;笔记本在其左下方外侧、两者不重叠 | 纵深=远景天空与远山/中景木围墙与营地大门/近景篝火与左右物件(作者纵深稿)。中景围墙是横贯全宽的密排竖木桩墙——木桩一根挨一根无缝、桩顶削尖、无横木,只在中段留缺口给大门。 **场景按要素分层(10 张)**:远景天空/远山/整片地面/门洞内的小路合成 `scene_camp_bg` 背景层(z0,不透明全幅);中景木围墙独立成 `scene_camp_wall` 围墙层(z1,透明底,门洞处留透明缺口);其余八个物件层各一张、由上往下叠。门洞是围墙层的透明缺口,透出背景层画的**一条通向远处的小路**,不可填死。 -**中景带自画面底部往上约 2/3 处起**;近景物件允许压住围墙(围墙不可点,z 序在近景物件之下),**唯一例外=中间门洞必须留空、不被任何物件遮挡**。围墙形态、门扇比例与帐篷尺寸的现行口径归 [art-bible](../../art/art-bible.md) §6.2,本 spec 不再复述。 +**地平线在终稿 y367**(自画面底部往上约 46%),其上是天空与远山、其下整片地面;**中景围墙带 y203–367**,桩身 150、门柱 164;近景物件允许压住围墙(围墙不可点,z 序在近景物件之下),**唯一例外=中间门洞必须留空、不被任何物件遮挡**。围墙形态、门扇比例与帐篷尺寸的现行口径归 [art-bible](../../art/art-bible.md) §6.2,本 spec 不再复述。 坐标草案与分层验收判据见 [camp-scene-prompts](../../art/camp-scene-prompts.md) §2.3/§4(10 张口径现行事实源);2026-10-22 美术方案讨论沿革查 git 提交史。 diff --git a/playnote.md b/playnote.md index 764d2fe5..9f10c73c 100644 --- a/playnote.md +++ b/playnote.md @@ -1,15 +1,9 @@ # 试玩问题记录 -- 一开始不能让角色的成长系数太高.比如在没经过升级之前,你的成长系数是跟不上关卡怪物难度提升的;但是后续能力解锁之后,成长系数才能匹配得上 - - UI优化,第二第三关的棋盘看着太累了;不知道是因为亮度还是对比度的原因,看着非常费劲,非常不舒服; - 第一关的第二个节点数值有问题 -- 现在的立绘太丑了,像素化的粒度太低了,导致根本看不清立绘; 看是否可以改回用较为高清的图片? -还有一个问题是大小的问题.我们或许可以调整一下不同怪物的大小,因为现在地精的图片看起来比熊地精还要大,这并不合理; - - - 修改地图的奖励类型 战斗节点增加不同的地图类型,比如有些图踩雷受到更多的伤害,有些图标雷可以造成更多的伤害,有些图伤害会减半需要凑更多清图奖励(这些都是暂时的设定) @@ -22,10 +16,27 @@ - 3选1奖励中有一个refresh,任何说明都没有,就一个refresh, 明显的一个问题物品,但是却没有处理; -- "奇物门票" 这他妈是专场门票,而且你他妈应该有一个更好的名称,而不是直接"门票"; 我真是操了你妈; -而且里面的解释非常弱智 - - 确认选择按钮旁边有一个"免费选择,点刷新不消耗AP" 我真是操你妈了,要你这种傻逼解释; 你他妈这是游戏的UI吗?设计像你妈坨屎; -- 封印回响这个专长描述也是错误的,怎么是本轮AC+1呢 \ No newline at end of file +- 封印回响这个专长描述也是错误的,怎么是本轮AC+1呢 + +## 2026-11-04 营地相关问题记录 + +1. 背景图存在着很多问题上半部分的内容太长了,我们应该预留更多的地面细节给我们的可点击的地方; +但是现在远景占据了太多的位置; +远景应该压缩到只有1/3的高度(现在占据了2/3) +近景的地面太朴素且太暗了; + +远景压缩之后,围墙,门,告示板记得也同步上调; + +2. 围墙贴图没对齐就算了, 过于矮? 高度应该>门 +3. 物品太靠下了; 整体可以往上调, 让最下面的宝箱和最底下保持着一个32px的距离 +4. 钥石说好是一条顶栏的,为什么现在是搞了一个类似浮动框的形式展示? + +为什么我设计定义的东西你没有进行实现,而且还自作主张地做了一个没有经过我同意的展示方式 +5. 点击大门开始新冒险,直接回到了开始菜单界面; +你是否真的做过完整的测试? +我这句话问了都白问,因为你做了完整的测试的话,就不可能会这么简单的逻辑闭环都没有完成 +6. 开始新冒险的是和否反过来了.否在左边,是在右边; 完全的反直觉; 完全的弱智 + diff --git a/reports/iter53-反哺点-2026-11-05.md b/reports/iter53-反哺点-2026-11-05.md new file mode 100644 index 00000000..b1c9eeef --- /dev/null +++ b/reports/iter53-反哺点-2026-11-05.md @@ -0,0 +1,21 @@ +# 迭代 53 反哺点清单(2026-11-05) + +- 接收方:[待办清单](../待办清单.md)(反哺点裁决后由文档批/工程批写入并把本清单条目清掉)。 +- 依据:`reports/iter53-实现报告-2026-11-05.md`;两卡「关联文档同步面」逐条落点如下。 + +| # | 落点(哪个文件哪一节) | 改成什么 | 依据 | +|---|---|---|---| +| 1 | `design/gdd/systems/跨局循环/锻造工坊.md` §满级特效扩展位——重甲反震候选条 | 实现前提句补一句:反弹伤害需新开消费点(本批摘 `spike` 词表位后彻底无位,候选=「需新代码」档) | 卡② §6 第 2 行;damage_controller.gd 摘除后 `open_ticket` reflect 通道为唯一反弹面且零现役表行 | +| 2 | `design/gdd/systems/战斗循环/增益状态.md`/`伤害与护甲.md` | 零命中备案——两文档叙述「按序改写族」的句子未挂退役件名,无需改动 | 卡② §6 机械面核对读数(40 名扫描两文件零命中) | +| 3 | `design/gdd/systems/冒险循环/奇物.md`、`systems/战斗循环/地图战斗资源.md`、`design/gdd/术语表.md`、`00-游戏概念.md`、`03-内容规模.md` | 各文仍提退役内容名的句子逐处换机制名(清退口径同卡② T3:只换名不换职责) | 卡② §5 去向表;40 名扫描命中所在(GDD 面不在本批可写域) | +| 4 | 结算明细标签是否入表(文案硬编码 `reward_grant.gd:226`) | 规范裁决点:玩家可见明细文案归属——维持代码硬编码 or 入数据表行;裁决后改对应规范文档 | 卡② §5 去向表末条;本批已把标签换代为「挖掘惩罚减半(%d→%d)」 | +| 5 | `tools/gate_platform.sh` `gate_run_timeout` | 修 Windows 恒 124 缺陷:`kf` 改「先赋路径、`rm -f` 后置守卫」(probe_gate.sh run_suite 同款正确写法);连带修 `golden_baseline_refresh.sh` 的 guard 子Shell kill 短路(7 分钟等待症状) | iter53 实现报告「遗留读数义务与发现呈报」第 1 条;实证=直接调用 4 秒返回 124、refresh 两次 7m1s | +| 6 | `game/tests/golden/mac/` | mac 侧补冻关卡视口两 Shot 基线(跑 `golden_baseline_refresh.sh --lmap`) | 渲染闸 lmap 段缺基线记 SKIP;windows 已冻结(6394abf7),mac 冻结后两平台同盯 | +| 7 | `game/tests/golden/README.md` §时效判定纪律 | 「基线冻结于 2026-09-30」句补 lmap 两 Shot 冻结日(2026-11-05)与两 Shot 面口径指针 | 本批 golden/README 台账已改现持清单,冻结纪律节的时间句留待文档批随批换代 | +| 8 | `game/tests/README.md` 能力行 :163(关卡画面视口平移) | 代表用例名 `_probe_clamp_bounds` 回表为落地名 `_probe_clamp_bounds_and_columns`(实现按卡 §8 对照表外的更 descriptive 名落地,回表归写卡段) | 验收审计 D1(建议级):名实回表义务 | +| 9 | 探针直读申报口径(test-conventions §8.2/§8.4 受控例外注记) | 「探针直读视口子件结构(`get_child(0)` 画布位、按名取指引子件 FadeL/FadeR/PanHint)」补进探针直读惯例的申报面注记 | 验收审计 D2(观察级):直读有注释理由、零风险,补成文口径 | +| 10 | `reports/iter53-实现报告-2026-11-05.md` 决定 3 | 已随本清单同批订正(case⑰→⑱ 笔误)——归档备查,无文档批动作 | 验收审计 D3 | + +## 零反哺备案 + +- 卡① `design/gdd/ux/level-map.md`:实现未发现 spec 缺口——布局决策 5 行为四条+像素级判据①–④+AC 260–271 全部有绿读数承载(实现报告对照表 R1–R9+golden 段)。 diff --git a/reports/iter53-实现报告-2026-11-05.md b/reports/iter53-实现报告-2026-11-05.md new file mode 100644 index 00000000..b86116fe --- /dev/null +++ b/reports/iter53-实现报告-2026-11-05.md @@ -0,0 +1,80 @@ +# 迭代 53 实现报告(2026-11-05) + +- 接收方:[待办清单](../待办清单.md)条目「超预算图策略升级路径——等比缩放与滚动视口两案待裁」(卡①卷轴视口批)+「damage_controller 按序改写族——内容孤儿机制与退役名注释层」(卡②改写族清退批)。 +- 需求卡片:`reports/需求卡片-卷轴视口批-2026-11-05.md`(验收档:中)+`reports/需求卡片-改写族孤儿机制与退役名清退批-2026-11-05.md`(验收档:中)。 +- 独立验收审计:`reports/iter53-验收审计-2026-11-05.md`(未参与实现的会话执行;两卡均按中档深度)。 +- 执行形态:整迭代单工作区(`g-plan2-iter53`,两卡均未声明可并行),卡序=卷轴视口 → 改写族清退。 + +## 各卡状态 + +| 卡 | 状态 | T 卡 | 凭据摘要 | +|---|---|---|---| +| 卡①卷轴视口批 | 完成(T0–T4 全收口+golden 扩项冻结) | T0 基线读数在案/T1–T3 实现波提交 c1043902/T4 指针反转 4e87a012/golden 扩项 6394abf7 | 新探针 26 断言全绿+探针族全绿+冒烟 15/0+S13 基线内 7 新增 0+渲染闸全绿(lmap 双图 changed=0.00%) | +| 卡②改写族清退批 | 完成(T0–T5 全收口) | T0 基线读数在案/T1 b5c21e3a/T2 1bd50304/T3+T4 并笔 ed793e8c | 三套件+四套窄测 exit=0+对拍六组逐字节 diff=0+四探针负域全拒+契约 1 三条 grep 全零+40 名注释面清零 | + +## 卡① 实际改动—验收对照表 + +| 需求点 | 改动(文件:行) | 验收测试(落点+尾缀) | 层级 | 真实入口 | 判据绑定面 | 结果 | +|---|---|---|---|---|---|---| +| R1 浅图整幅居中无裁切 | level_map_screen.gd 三段页承载+level_map_viewport.gd `_axis_center_offset` 居中分支 | `level_map_viewport_probe.gd:71/74/76`〔卷轴批 V1〕 | 探针 | `open_choices` 真实停点(L1 固定种子直构 runner) | 画布≤窗居中 offset 定位+画布矩形 encloses 于视口 | 绿 | +| R2 停点切换当前节点居中 x=640±2 | level_map_viewport.gd `reanchor`+screen `_viewport_anchor`/open_choices 接线 | `level_map_viewport_probe.gd:221`〔卷轴批 V2〕 | 探针 | 断点停点重建+真实 `open_choices` | 当前节点画布投影=视口中线±2 | 绿 | +| R3 拖拽平移 | screen `_on_canvas_motion` 拖拽态逐帧 `pan_by`(含激活帧位移) | `level_map_viewport_probe.gd:137`〔卷轴批 V3〕 | 探针 | `push_drag_at` 合成沿走 `push_input` | 视线位移=拖拽位移(40px 逐位) | 绿 | +| R4 滚轮横滚 | screen `_wheel_pan_step` 映射(下/右=前进向) | `level_map_viewport_probe.gd:114/116/120`〔卷轴批 V4〕 | 探针 | `push_wheel_at` 合成滚轮沿 | 单档 ±60 逐位+窗内不钉边界 | 绿 | +| R5 clamp 包络与首末列可达 | level_map_viewport.gd `_axis_pan_offset`/`is_clamped_at_edge` | `level_map_viewport_probe.gd:88/102/158/160/161/167/168`〔卷轴批 V5〕 | 探针 | 超包络拖拽沿两极 | 中线恒在夹紧域+两极 edge=true+首末列中心入屏+入口组包围盒锚点 | 绿 | +| R6 拖拽不触发选路 | screen `_on_canvas_click` 拖拽抬杆不提交 | `level_map_viewport_probe.gd:200/201/206`〔卷轴批 V6〕 | 探针 | 拖拽沿/完整点击沿起止候选上方 | `route_chosen` 零发射+屏未关;完整点击仍提交=1 | 绿 | +| R7 平滑滚动与减动效瞬切 | level_map_viewport.gd `reanchor(smooth)` tween `UiKit.motion(0.3)`+`ArmedTimer.motion_still` 跳终态 | `level_map_viewport_probe.gd:245/249/258`〔卷轴批 V7〕 | 探针 | 可见屏停点切换+`UiKit.motion_scale` 置位 | 平滑有 tween 中间帧(同向在途)+减动效即达 | 绿 | +| R8 指引件可见性与几何 | level_map_viewport.gd `_build_guidance`/`_sync_guidance` | `level_map_viewport_probe.gd:271–287`〔卷轴批 V8〕 | 探针 | 深图真实停点+浅图复验 | 渐隐带 70px+chip 240×30 居中可见;浅图隐藏 | 绿 | +| R9 schema 头注指针反转(非行为) | level_gen_params.gd:3-4/:66 头注 | 静态判据:grep「调参表」残留=0、「参数契约节」指向=2;`--check-only` 零错 | 静态 | — | 全仓无「域并单点=调参表」残留 | 绿 | +| golden 两 Shot 面(2026-11-05 用户裁) | level_map_shot_probe.gd+golden/windows/lmap_entry·lmap_boss+render_gate.sh 对拍段 | 渲染闸「关卡视口 golden 逐像素」段(changed=0.00% 双绿);重采集确定性=0.00% | golden | 窗口化真实渲染+固定种子 | 两 Shot 逐像素 ≤16 差/≤2% | 绿 | + +非行为改动行:无(R9 之外全部行为面;`.uid` 边车随新件入库)。 + +## 卡② 实际改动—验收对照表 + +| # | 需求点 | 改动(文件:行) | 验收测试(落点+尾缀) | 层级 | 真实入口 | 判据绑定面 | 结果 | +|---|---|---|---|---|---|---|---| +| R1 | 摘四段不可达改写分支 | damage_controller.gd(原 :297-302/:305-309/:310-314/:316-323/:350-353/:367-372/:623 全摘+spike_ready 键摘) | `damage_controller_test.gd`(exit=0);`roll_multiplier_test.gd`(exit=0);`round_flow_skill_pool_test.gd`(exit=0);dump_battle 六组改前改后逐字节比对 diff=0 | 单元+集成 | `BattleOrchestrator.begin_battle()` 全链 | step_row 流逐位=改前基线(L{1,2}×S{42,779401,779501});静态=契约 1 三条 grep 全零+摘后 `spike_ready` 零残留。观测面局限申报:零现役注册行使分支不可达,禁注入表行取证(卡 §8 申报在案) | 绿 | +| R2 | EFFECT_KINDS 摘 spike | effect_engine.gd:30 | `effect_kind_retired_test.gd:89`「effect_kind_retired_test/③词表闭面:kind=spike 出域拒绝」 | 单元(负面,独立进程) | `ConfigDB.load_tables()` → `validate_trigger_row` | do.kind=spike 行被拒+error 诊断在案+退出码 1(负面期望码) | 绿 | +| R3 | DO_KEYS 摘 trade_hit/trade_atk | effect_engine.gd:82 | `effect_kind_retired_test.gd:92`「effect_kind_retired_test/④do 键闭面:trade_hit 出域拒绝」 | 单元(负面,独立进程) | 同上 | 带 trade_hit 键 do 字典被拒+退出码 1 | 绿 | +| R4 | 注释面退役名清零(13 文件) | T3 35 处注释改写(对照卡 3.3 表逐处) | 静态判据:40 名全扫仅剩卡 §5 留底 3 行(treasure_items_test:31/33/35 StubDB 夹具名);宿主套件逐位不变(四套窄测 exit=0) | 静态(闸件扫描) | 宿主套件回归(改写面不进运行期) | 注释面命中 0+套件绿 | 绿 | +| R5 | 减半明细行去退役件名 | reward_grant.gd:226(标签→「挖掘惩罚减半(%d→%d)」+effect_id→nest_halve) | `meta_progression_forge_test.gd:694/697/699/700`(断言串随动,非空+等值+不含旧词强度不降) | 集成(信号采集) | 锻造锋线满级特效 → begin_battle → mine_hit 减半路径 → step_row | display_name==「挖掘惩罚减半(6→3)」+power 减半数值与发射次数逐字不变+grep nest_counter=0 | 绿 | +| R6 | 空集拒绝 reason 去退役件名 | reward_grant.gd:189(→「中立移除:…」) | 静态判据:grep 爆破工兵包 reward_grant.gd=0;`table_structure_guard_test.gd` exit=0 | 静态+单元 | 通道校验面(零现役行不可达) | grep 零命中+通道校验绿。观测面局限申报:reason 不可达,禁造行取证 | 绿 | +| R7 | 反弹明细标签去退役件名 | grant_segment.gd:166(标签→「反弹伤害」+归因串→attune_nest_halve;channel=="reflect" 判据与开单参数字典逐字不动) | 静态判据:grep 惊巢反制 game/=0、attune_nest_counter=0;`round_flow_skill_pool_test.gd` exit=0 | 静态+集成 | mine_hit 订阅施加链(reflect 行族零表行,今天不可达) | grep 零命中+发射面零变化回归。观测面局限申报:禁造行取证 | 绿 | +| R8 | sim 恒 false 匹配删除 | level_autoplay.gd(原 :415 注释+:421 contains(雷区图谱) 条件删,highlight==seal_hit 单判据保留) | 静态判据:grep 雷区图谱 game/=0;sim 驱动链套件绿(四套窄测含 autoplay 消费面 exit=0) | 静态+单元 | autoplay 驱动链(测量面) | grep 零命中+套件绿。观测面局限申报:恒 false 条件不可达 | 绿 | + +非行为改动行:T3 注释面 35 处(由 R4 行覆盖);契约 3 约束下 :226/:166 仅标签与归因串文本变动、取值/位序/载荷键逐字未动(R1 对拍 diff=0 为其逐位证据)。 + +## 读数义务对账(卡内 T 卡产出) + +- **卡①T0**:S13 基线无 `level_map_screen` 键(记「无键、按工具默认」);ui_struct_probe PASS 全屏结构断言零红;screen_flow_probe PASS;冒烟 15 项 0 失败。 +- **卡①T4 复跑**:S13 基线内 7 条、新增 0(`_on_canvas_input` 重构触发的 max-branches 新违规已拆 `_on_canvas_motion`/`_on_canvas_click`/`_wheel_pan_step` 归零);ui_struct_probe/screen_flow_probe 复跑绿(探针族全绿内含)。 +- **卡②T0**:契约 1 三条 grep——`game/data/tables/` 内 spike/armor_rewrite/discount_shift/trade_hit/trade_atk 全零(对照记录=feats.tres:855 clamp_bonus 现役一行);tree_rules 面零;effect_kinds 面 cell_removal 表面零(仅 schema 在册:treasure_item_table.gd:20/:26,本批不摘通道)。S13 四文件无登记键(damage_controller/effect_engine/reward_grant/level_autoplay 均按工具默认)。改前对拍基线六组落盘(L{1,2}×S{42,779401,779501})。改前断言串=「惊巢反制——危险格挖掘惩罚减半(6→3)」(:693/:698-701 现行文本抄录在案)。 +- **卡②T5**:改后对拍六组 diff=0;40 名全扫终读数=3 行留底夹具;R5–R8 静态 grep 全零;负域套件 exit=1(期望码)四探针全拒。 +- **存量触面 S13 对照**:damage_controller(分支数/函数长度随摘除下降,无新增键);effect_engine(常量字面量变短,方法数/成员数不变);reward_grant/level_autoplay(删文本与恒 false 条件)——S13 终读数=基线内 7、新增 0、恶化 0。 + +## 实机目检总清单(登记不阻塞) + +| 目检项 | 来源卡 | 承载 | +|---|---|---| +| 深度 13+ 图拖拽可达首末列、推进跟随方向感、chip 不碍选路 | 卡① | 窗口化实跑截图已冻结(golden/windows/lmap_entry·lmap_boss);真人试玩复核登记体验验证清单(归批后收尾) | +| 结算明细行减半标签「挖掘惩罚减半(6→3)」一眼可读、无退役件名突兀感 | 卡② | 实现报告登记;真人目检归体验验证清单(归批后收尾) | + +## 实现决定记录(超白名单/超卡片明列面逐条备案) + +1. **拖拽态成员落屏侧**(卡①§11 把 `_drag_active`/`_drag_accum` 枚举进视口件成员,§6 职责边界却写明视口件「只管裁切/offset/clamp/跟随」、拖拽判定留画布)——取 §6 职责边界优先:拖拽判定状态随输入处理落 screen(`_drag_active`/`_drag_press_pos`),视口件成员 6 个(≤8 达标)、公开方法 5 个(≤20 达标)。撤销方式=成员迁视口件+canvas 经方法驱动(纯结构搬移)。 +2. **open_choices 平滑判据=有无当前节点**(卡①§6 写「reanchor(false) 首锚」、T2 写「停点切换/回图接 reanchor(true)」,open_choices 同时承载两路径)——合并读法:入口停点(current_node_id<0)即达=首锚,其余停点/兑付回图平滑=跟随。R2/R7 断言均经此路径。 +3. **提交沿移至抬杆**(原提交在按下沿;布局决策 5 阈值区分语义下按下时无法预知是否成拖拽,R6 要求拖拽沿零发射)——完整点击(按下→未超阈值抬杆)提交、拖拽抬杆不提交;ui_input_probe case⑫/⑱ 补 release 沿适配(验收审计 D3 订正:原呈报误写⑰,实际落点两处)(判据语义「图上真实点击提交选路」不变,输入形态更完整)。 +4. **滚轮步进 60px、渐隐带色 BG_ROOT 不透明端 0.9、chip 底 HP_BAR_BACK/描边 STONE/文字 WARM、缓动 TRANS_CUBIC+EASE_OUT**——卡 §12 白名单 4/5/3 授权面内定值。 +5. **视口件 NOTIFICATION_RESIZED 即席重锚**——首开布局晚于 open_choices 锚定(隐藏子树容器排序首可见帧才传播,4.7 行为;实证=探针首跑 y 锚偏 88px),resize 即席 `reanchor(false)` 收敛;同时是窗口尺寸变化的正确行为。 +6. **_fit_canvas 画布尺寸同帧收敛**(`canvas.size = _content_size` 显式置)——视口锚点数学与 `_layout` 同源读画布尺寸,容器延迟收敛不等锚点。 +7. **mouse_exited 清拖距跟踪器**——按下即武装的跟踪器在丢失 release 沿(alt-tab 等)后残留会把后续 motion 误判为拖拽激活(ui_input_probe case⑰⑧ press-only 实证);非拖拽态离画布即解除。 +8. **卡②探针①注入 do.kind="spike"**(卡 T2 括注 kind=modify_ticket+mode=spike 形态)——括注形态无拒绝通道(`validate_trigger_row` 无 mode 值域检查,mode 属载荷字段非词表),按断言名「词表闭面:kind=spike 出域拒绝」与 R2 判据绑定面(effect_kinds 出域文案)的机制注入 kind 形态。 +9. **golden 两 Shot 面口径**(卡①现状事实写「本批不触渲染闸对拍」、批纪律 iter 4.4+test-conventions §8.2 要求扩项)——呈裁用户,2026-11-05 裁「只处理最初始的和最终的:关卡最开始+关卡 Boss 节点,中间过程不对拍」,按两 Shot 面扩项冻结。 +10. **卡② T3 与 T4 并笔提交**——卡 §10 白名单授权面。 + +## 遗留读数义务与发现呈报 + +1. **闸件缺陷呈报(工程批)**:`tools/gate_platform.sh` 的 `gate_run_timeout` 用 `mktemp` 造超时标志文件——mktemp 即建文件,末尾 `[ -f "$kf" ]` 在 Windows(Git Bash)恒真→**恒返回 124**。被各闸「判定锚工件而非退出码」口径掩住(菜单/棋盘 golden 段与本批 lmap 段均工件锚定,不受影响);`tools/golden_baseline_refresh.sh` 的 7 分钟等待症状(guard 子Shell `sleep 420` 未被 kill 短路)同根。修法=改 `kf="$TMP/..." ; rm -f "$kf"`(run_suite 同款,probe_gate.sh 已是正确写法)。本批不代修(闸件改动归工程批)。 +2. **mac 端关卡视口基线冻结义务**:`golden/mac/` 缺 lmap_entry/lmap_boss——渲染闸缺基线记 SKIP 不判红(windows 已锚即盯),mac 冻结归 mac 侧跑 `golden_baseline_refresh.sh --lmap`。 +3. **效果通道与事件词的零现役普查**——已在待办清单在册(卡② §5 去向),本批不扩。 +4. 卡① level-map.md 同步面:实现未发现 spec 缺口(布局决策 5 行为四条+像素级判据+AC 全部有绿读数承载),零反哺。 diff --git a/reports/iter53-验收审计-2026-11-05.md b/reports/iter53-验收审计-2026-11-05.md new file mode 100644 index 00000000..022f7813 --- /dev/null +++ b/reports/iter53-验收审计-2026-11-05.md @@ -0,0 +1,122 @@ +# 迭代 53 验收审计(2026-11-05) + +- 审计员:独立会话子代理——未参与本迭代任何实现、设计或写卡工作,只读证据做审计。 +- 审计对象:迭代 53 两张需求卡片——卡①卷轴视口批(`reports/需求卡片-卷轴视口批-2026-11-05.md`)+卡②改写族孤儿机制与退役名清退批(`reports/需求卡片-改写族孤儿机制与退役名清退批-2026-11-05.md`)+卡① golden 扩项(2026-11-05 用户裁两 Shot 面)。 +- 实现报告:`reports/iter53-实现报告-2026-11-05.md`(两卡「实际改动—验收对照表」为逐行核对基准)。 +- 验收档与实际执行深度:两卡均申报「中」档;本次按 test-conventions §8.7 中档执行——对照表逐行全量核对(两卡 R 行逐行)、判据绑定面抽查(超出下限)、测试削弱检查逐处、直查例外核对逐条、判据出处抽查 6 处。**最窄测试复跑=省略,该格写「合回后 CI 现查补记」**(合并尚未发生——本审计为合并前置闸,远端 CI 现查读数待合回落地后按 `tools/ci_check.sh <合并提交>` 补记;静态 grep/文件核对类检查由审计员当场重跑,不属省略面)。 +- 基线提交:`709d9a85..8b4399ad`(iter53 分支;7 笔实现笔 c1043902/4e87a012/b5c21e3a/1bd50304/ed793e8c/6394abf7/78e08234 + 1 笔并 master 8b4399ad)。工作树存在本机 Godot 导入元数据漂移(若干 `*.png.import` 未提交改动),不属提交面审计对象。 +- 审计动作面:`git diff 709d9a85..HEAD` 全量过目(37 文件);测试/探针/闸件改动逐 hunk 核对;契约 1 五词 grep、40 名退役名全扫、契约 5 残留 grep 由审计员当场重跑。 + +## 卡① 卷轴视口批(验收档:中|执行深度:中档) + +### 对照表逐行核对(全量) + +| 行 | 结论 | 依据(文件:行) | +|---|---|---| +| R1 浅图整幅居中无裁切 | 通过 | 断言在案且尾缀可 grep:`game/probe/level_map_viewport_probe.gd:71/74/76`〔卷轴批 V1〕;承载改造落地 `level_map_viewport.gd:30-36`(setup/clip_contents)+`level_map_screen.gd:134-145`(CenterContainer→视口件);真实入口=`open_choices` 真实停点(探针 :62-64,L1 固定种子直构 runner,start_level_external 注入)。运行读数=实现者「绿」在案;合回后 CI 现查补记 | +| R2 停点切换当前节点居中 x=640±2 | 通过 | 断言 `level_map_viewport_probe.gd:221`〔卷轴批 V2〕;断言钉屏空间投影(当前节点屏幕 x 对视口中心 ±2)——比卡面所写 `viewport_center_canvas_pos()` 调用更外层的真实观测,与 level-map.md:101/:154 判据①「居屏中线 x=640±2」同义,非削弱(观察 4);真实入口=断点停点重建+真实 `open_choices`(探针 :216-217)→ screen `reanchor` 接线 `level_map_screen.gd:312-315`+锚点提供方 :483-516。合回后 CI 现查补记 | +| R3 拖拽平移 | 通过 | 断言 `level_map_viewport_probe.gd:137`〔卷轴批 V3〕;真实输入沿=`ProbeUiUtil.push_drag_at`(`game/probe/probe_ui_util.gd:146-166`,press→motion×4→release 全经 `push_input`)打真实画布 `_gui_input`(`level_map_screen.gd:381-403` 拖拽态逐帧 `pan_by`)——**未绕过改动点**(探针全文零 `pan_by` 直调,grep 证);判据=视线位移=拖拽位移 40px 逐位。合回后 CI 现查补记 | +| R4 滚轮横滚 | 通过 | 断言 `level_map_viewport_probe.gd:114/116/120`〔卷轴批 V4〕;`push_wheel_at`(probe_ui_util.gd:168-176)经 `push_input`;映射 `_wheel_pan_step`(level_map_screen.gd:426-433,下/右=+60 前进向,代拍板白名单 5 授权)。合回后 CI 现查补记 | +| R5 clamp 包络与首末列可达 | 通过 | 断言 `level_map_viewport_probe.gd:88/102/158/160/161/167/168`〔卷轴批 V5〕;判据绑定 `viewport_center_canvas_pos()` 夹紧域(level_map_viewport.gd:76-77/:97-100/:111-114)+`is_clamped_at_edge()` 两极翻转(:81-86)+极值列入屏(:161-169,等价 spec 判据④);真实入口=超包络拖拽沿两极。合回后 CI 现查补记 | +| R6 拖拽不触发选路 | 通过 | 断言 `level_map_viewport_probe.gd:200/201/206`〔卷轴批 V6〕;**拖拽沿确从候选节点上方起沿**(:193 `gpos`=候选屏幕投影,:197 `push_drag_at(self, gpos, …)` 起点即候选);判据绑 `route_chosen` 发射面零计数(screen `route_chosen.emit` :465)+屏未关+阈值另一侧完整点击提交=1(:203-206,点击沿 press+release 成对经 push_input)。合回后 CI 现查补记 | +| R7 平滑滚动与减动效瞬切 | 通过 | 断言 `level_map_viewport_probe.gd:245/249/258`〔卷轴批 V7〕;tween 单段缓动 TRANS_CUBIC-EASE_OUT UiKit.motion(0.3)(level_map_viewport.gd:57-59);减动效走 `ArmedTimer.motion_still()`(armed_timer.gd:16-17=motion_scale<1)跳终态——探针置 `UiKit.motion_scale=0.5` 即设置面单点(settings_overlay.gd:96 同驱),判据同向在途+即达。合回后 CI 现查补记 | +| R8 指引件可见性与几何 | 通过 | 断言 `level_map_viewport_probe.gd:272-278`+浅图隐藏 :289〔卷轴批 V8〕;几何常量 FADE_BAND_W=70(level_map_viewport.gd:10)、CHIP_SIZE 240×30(:11)直挂 spec 判据②③;可见性=`_sync_guidance` 画布超窗判据(:181-191)。合回后 CI 现查补记 | +| R9 schema 头注指针反转(非行为) | 通过(静态重跑) | `level_gen_params.gd:3-4`+:70 反转落地;审计员重跑 grep:该文件「调参表」残留=0、「参数契约节」指向=2、`--check-only` 读数实现者在案。全仓唯一「调参表」残留=variation_table.gd:41(地形变异 v1.2 owner,不同文件不同域,不属本卡清退面) | +| golden 两 Shot 面(用户裁) | 通过 | `game/probe/level_map_shot_probe.gd`(PASS 签名 :36+落盘 fail-fast :89-91)+`game/tests/golden/windows/lmap_entry.png`/`lmap_boss.png` 已入库(6394abf7,Bin 215164/211513 字节)+`tools/render_gate.sh:168-197` 对拍段(PASS 签名+双图非零工件锚定+平台缺基线 SKIP 不判红)+`tools/golden_baseline_refresh.sh` --lmap 模式(:59-85,素材齐盘守卫)+`game/tests/golden/README.md` 台账随动;mac 缺基线义务已呈报(实现报告遗留 2+反哺点 6)。运行读数(changed=0.00% 双绿)=实现者在案;合回后 CI 现查补记 | + +卡①补充核对:26 断言计数属实(探针 26 处 `_check`+尾缀〔卷轴批 V1..V8〕27 行含 1 处缺位告警);`tools/probe_gate.sh:137-141` 注册新探针;ui_struct_probe 本批零改动(未触其结构断言面,卡①削弱申报该项落空=无事);实现报告实现决定 1-7(拖拽态落屏侧/open_choices 平滑判据/提交沿移抬杆/代拍板白名单定值/resize 即席重锚/_fit_canvas 同帧/mouse_exited 清跟踪器)均有代码承载且不越卡 §12 白名单;7 笔实现笔无一触碰 `design/`/两份根清单/`game/tests/README.md`(逐笔 name-only 核对)。 + +### 判据绑定面抽查(本卡抽 4 行,超中档下限 2 行) + +- R6(如上)——`route_chosen` 零发射+屏未关+完整点击仍提交,三面钉在「拖拽不提交/点击提交」的特有提交面上。 +- R2(如上)——当前节点屏空间投影=视口中线 ±2。 +- R5(如上)——夹紧域+两极 edge 翻转+极值列入屏。 +- R3(如上)——拖拽位移与视线位移逐位一致,且全程走引擎输入管线。 + +### 直查例外核对(逐条) + +| 直查行 | 申报状态 | 结论 | +|---|---|---| +| `level_map_viewport_probe.gd:67` `vp.get_child(0)`(取视口画布子件) | 探针内注释已给理由(「画布=视口首子件——setup 注入序」,:61),对照表/实现报告**未单列申报口径** | 缺漏(建议级,见末节 D2)——断言对象即承载结构本身,无公开可观测面可钉,风险零 | +| `level_map_viewport_probe.gd:266-268/:287-288` 按名取 FadeL/FadeR/PanHint | 同上——探针内注释在案,对照表未单列 | 缺漏(建议级,并入 D2)——R8 断言对象即指引子件结构本身 | +| screen 侧私有成员 | 新探针**未直读**任何 screen 私有成员(`_drag_active`/`_drag_press_pos` 零探针触达);既有「探针直读冻结」惯例面(level_map_screen.gd:39/:57-64)未扩 | 通过 | + +## 卡② 改写族孤儿机制与退役名清退批(验收档:中|执行深度:中档) + +### 对照表逐行核对(全量) + +| # | 结论 | 依据(文件:行) | +|---|---|---| +| R1 摘四段不可达改写分支 | 通过(静态面重跑一致;运行读数合回后 CI 现查补记) | diff 逐段核对:`damage_controller.gd` 命中侧交换/免掷覆盖/spike 置位/移档调用/增伤侧/spike 倍乘/`_discount_shift_up` 整函数全摘;`_ctx_rewrites` 返回键集={roll_read,threshold,crit,discount,clamp_hits}(:301-303)、`_hero_attack_ctx` 摘 spike_ready(:278-281)——与卡 T1 收窄键集逐字一致;armor_roll 发射点保留不接收返回值(:289-290,卡 3.6 口径);spike_ready/ar_hits/shift 残留 grep=0(审计员重跑)。六组逐字节对拍 diff=0 与三套件 exit=0=实现者读数在案;dump_battle 六组参数面(seed 42 默认+参数覆盖,dump_battle.gd:13/:21)核对成立 | +| R2 EFFECT_KINDS 摘 spike | 通过 | `effect_engine.gd:30` 词表摘名;断言 `effect_kind_retired_test.gd:89`「③词表闭面:kind=spike 出域拒绝」在案,沿既有 `_assert_rejected`/`_inject` 骨架(卡 T2 明示沿用);注入形态偏差(do.kind=spike,非卡 T2 括注 kind=modify_ticket+mode=spike)=实现决定 8 申报在案且经审计员核实——`validate_trigger_row`(effect_engine.gd:382-396)确无 mode 值域检查,括注形态无拒绝通道,实现口径与断言名/R2 判据绑定面(词表出域)一致。运行读数(负域套件 exit=1 四探针全拒)合回后 CI 现查补记 | +| R3 DO_KEYS 摘 trade_hit/trade_atk | 通过 | `effect_engine.gd:80-82` 摘两键;断言 `effect_kind_retired_test.gd:92`「④do 键闭面:trade_hit 出域拒绝」在案。运行读数合回后 CI 现查补记 | +| R4 注释面退役名清零 | 通过(40 名全扫审计员重跑) | 审计员自解析 `design/content-archive/道具退役素材库.md` 两表 40 名(41 减现役淬毒刃纹)重扫 `game/` 全域 .gd/.tres/.md/.tscn:命中仅 3 行=`treasure_items_test.gd:31/33/35` StubDB 夹具名——与卡 §5 留底申报逐行一致;契约 2 抽 4 处(grant_segment.gd:232「完美布防→封印全中倍率」、damage_controller.gd:109「猎巢人→nest_count 订阅消费面」、reward_grant.gd:130「掘进蓄能→付费积点账本」、grant_segment.gd:359「雷区图谱→标中雷追加」)——职责陈述(做什么/按什么序/取值从哪来)逐处保留,只换名;宿主套件绿=实现者读数,合回后 CI 现查补记 | +| R5 减半明细行去退役件名 | 通过 | `reward_grant.gd:226` 标签→「挖掘惩罚减半(%d→%d)」+effect_id→nest_halve;断言随动 `meta_progression_forge_test.gd:694/697/699-700`,强度三件(nc_hit 非空+等值「挖掘惩罚减半(6→3)」+零「挖雷」)与改前逐项对齐(基线 709d9a85:693-701 核对);grep nest_counter=0(审计员重跑)。合回后 CI 现查补记 | +| R6 空集拒绝 reason 去退役件名 | 通过(静态重跑) | `reward_grant.gd:189` reason 前缀→「中立移除:…」,`{"ok": false}` 形态未动(diff 核对);grep 爆破工兵包 game/=0(审计员重跑);观测面局限申报(reason 不可达、禁造行)在卡 §8/对照表一致在案 | +| R7 反弹明细标签去退役件名 | 通过(静态重跑) | `grant_segment.gd:165-166` 标签→「反弹伤害」+归因串→attune_nest_halve;**契约 3 逐字核对成立**:`channel=="reflect"` 判据、开单参数字典(channel/base_value/target_rule/ri/origin_cell)、`reward_grant.submit` 调用全未动(diff 对照基线 709d9a85:164-170);grep 惊巢反制/attune_nest_counter=0(审计员重跑)。运行读数合回后 CI 现查补记 | +| R8 sim 恒 false 匹配删除 | 通过(静态重跑) | `level_autoplay.gd:414-418` highlight=="seal_hit" 单判据保留、contains(雷区图谱) 条件与 :415 注释随删;grep 雷区图谱 game/=0(审计员重跑)。套件绿=实现者读数,合回后 CI 现查补记 | + +卡②补充核对(契约逐条):契约 1 三条 grep 审计员重跑全零——tables 五词 0、tree_rules 面 0、cell_removal 表面 0 仅 schema 在册(treasure_item_table.gd:20/:26);`feats.tres:855` clamp_bonus 现役一行对照记录与实现报告 T0 一致,表内现存 mode 值(queue/round/battle/clamp_bonus/refresh)零退役四模式。契约 5 禁留空壳——spike_ready/ar_hits/shift/_discount_shift_up 残留 grep 全零(审计员重跑)。契约 6 实现批禁写文档——7 笔实现笔 name-only 核对零触 design//待办清单/体验验证清单/game/tests/README.md。契约 7 零新增数值——diff 内零 .tres 表值改动。反哺点清单 7 条落点齐(含「明细标签是否入表」裁决点+增益状态/伤害与护甲零命中备案)。 + +### 判据绑定面抽查(本卡抽 3 行) + +- R2/R3(如上)——负域探针钉「退役词/键注入行→load_tables 拒绝+error 诊断≥1+进程退出码 1」;归属由夹具结构保证(copy_tables 全量现役表+唯一异常探针行)。观察 5:卡面写的「error 载荷含 effect_kinds 出域文案」未做逐字断言——沿用卡 T2 明示的既有骨架语义,非削弱。 +- R5(如上)——step_row display_name 等值断言+非空+零旧词,判据绑减半路径特有发射面。 +- R1 静态面(如上)——收窄键集逐字核对+摘除残留 grep,钉在「分支消亡」这一改动特有提交面。 + +### 测试削弱检查(逐处,两卡合并过目) + +`git diff 709d9a85..HEAD -- game/tests/ game/probe/` 全量 hunk 过目,共 5 文件: + +1. `effect_kind_retired_test.gd`:**纯新增**(两探针常量+两次 `_assert_rejected` 调用+PASS 文案随动);既有探针①②与 quit 语义零改动;`run_all.gd:195` 在册条目 expect=1/negative=true 未动。无削弱。 +2. `meta_progression_forge_test.gd`:恰 4 处期望串随 R5 换代(:694 匹配串/:697 描述/:699-700 等值串)+2 行注释(卡 3.3 表申报面)——断言强度逐项不降(非空+等值+不含旧词全保留),与卡 §8 削弱申报逐字吻合。无申报外削弱。 +3. `variant_placement_test.gd`:1 行注释(偏运硬币→订阅行,卡 3.3 表 :239 申报面),断言零改动。无削弱。 +4. `ui_input_probe.gd`:+16 行=case⑫断言段(图上命中提交沿)+case⑱ 雾段(雾下点击零提交)各补 release 沿——实现报告决定 3 申报在案;判据语义核对:雾段=零提交不变(且改为完整点击沿后更强)、命中段=提交沿随新语义移至抬杆(单 press 沿在新语义下不再是提交沿,不适配则必红——必要适配非放宽)。**呈报笔误**:申报写「case⑫⑰⑧」,实际落点两处、无 ⑰(case⑰ 未开格类型微光走 `_push_click` 既有成对沿,无需适配)(建议级 D3)。 +5. `ui_struct_probe.gd`:零改动——卡①「适配须保持语义」条款无事可核,非缺漏。 + +无申报外的断言删除、阈值放宽、扫描面缩小、换下层直调。 + +### 判据出处抽查(6 处,超下限 4 处) + +| 断言预期值 | 规格出处 | 独立可写出性 | +|---|---|---| +| 居中 ±2(探针 R2 :221) | level-map.md:101「屏中线 x=640±2」/:154 判据①/:269 | 能——规格句直接给出 640±2 | +| 渐隐带 70px(探针 R8 :273-274) | level-map.md:104/:154 判据②「屏缘两侧各 70px 渐隐带」 | 能 | +| chip 240×30(探针 R8 :275-276) | level-map.md:104/:154 判据③「240×30、圆角 6」 | 能 | +| 「挖掘惩罚减半(6→3)」(forge 测试 :699-700) | 卡② §8 R5 判据明文+reward_grant.gd:226 契约 3 边界;6→3 可由测试构造独立推出(heal 行 power=6×halve 50% ceil=3) | 能——预期值在卡内先行锁定,非镜像实现 | +| 拖拽阈值 8px(DRAG_THRESHOLD,level_map_screen.gd:34) | 卡① §12 白名单 2「8px 附近 provisional 区间内定值」授权;spec :103 明示阈值实现期定值 | 能——授权面在卡,值属 provisional 自主面 | +| golden 两 Shot 面 | 2026-11-05 用户裁决(实现报告决定 9 在案):只对拍关卡最开始+Boss 节点 | 能——裁决记录在实现报告与 golden/README 台账双在案 | + +六处均非「预期值只在实现里出现」的同义反复。 + +## 附加核对 + +- 能力行名实(game/tests/README.md:162-164 三行)::162 跟随行(_probe_follow_anchor/_probe_smooth_scroll_reduced_motion)与 :164 指引行(_probe_guidance_chrome)名实一致;**:163 平移行的 `_probe_clamp_bounds` 与落地名 `_probe_clamp_bounds_and_columns` 不一致**(建议级 D1——卡① §5「批末收尾核对表上名与落地一致(改名则回表)」未回表,反哺点清单亦未收录;实现批禁写 README,正确通道=回写卡段/反哺点)。 +- 负面套件在册:`game/tests/run_all.gd:195` effect_kind_retired_test expect=1/negative=true 登记在位,卡② T2 未动在册条目——一致。 +- S13 基线读数:`tools/gdstyle_baseline.txt` 恰 7 条且无本批触面键(level_map_screen/damage_controller/effect_engine/reward_grant/level_autoplay 均无键)——与实现报告 T0/T4 读数一致。 +- 闸件缺陷呈报核实(实现报告遗留 1):`tools/gate_platform.sh:37` `kf="$(mktemp …)"` 即建文件+:48 `[ -f "$kf" ]` 恒真→恒 124,呈报描述与代码相符;probe_gate.sh:97 `kf="$TMP/killed.$RANDOM"`(先赋路径不预建)为正确写法参照——呈报属实;该缺陷修法归工程批,本审计不裁定(不在验收对象内,已入反哺点 5)。 + +## 缺漏与观察清单 + +阻断级:无。 + +建议级(不阻断合并,归批后收尾/文档批): + +- D1:能力清单 `game/tests/README.md:163` 代表用例名 `_probe_clamp_bounds` ≠ 落地名 `_probe_clamp_bounds_and_columns`(卡① §5 名实核对义务未回表;反哺点清单漏收)。 +- D2:新探针对宿主内部结构的直查(`level_map_viewport_probe.gd:67` get_child(0)+:266-268/:287-288 按名取指引子件)未按 test-conventions §8.7 第 4 条在对照表逐条申报口径;探针内注释已给理由(断言对象=承载结构本身,无公开观测面),screen 侧既有「探针直读冻结」惯例未被动用、新私有成员零直读,风险零。 +- D3:实现报告/提交信息写「ui_input_probe case⑫⑰⑧ 补 release 沿」,实际落点为 case⑫断言段+case⑱雾段两处、无 ⑰——呈报笔误,判据语义已核保持。 + +观察(记录在案,不构成缺漏): + +- O1:R2 判据绑定面用屏空间投影而非卡面所写 `viewport_center_canvas_pos()` 调用——更外层真实观测,与 spec 判据①同义,非削弱;连带 `game/tests/README.md:162` 读面句与实况有轻微出入。 +- O2:卡② R2/R3 负域探针未逐字断言错误文案(沿用卡 T2 明示骨架语义;归属由夹具唯一异常行结构保证)。 +- O3:卡① T1 写「探针宿主沿组合根真实屏」、卡 §8 对照表写「场景探针实例化本屏」——卡内两处口径不一,实现取对照表口径且在对照表真实入口格如实呈现;`push_input` 真实输入管线口径照守(禁合成投喂的实质红线未破)。 +- O4:探针宿主直构 runner(start_level_external)属 test-conventions §5.4 自动化测试直构口径,探针头注已申报。 + +## 审计结论 + +**通过**(可合并;合并落地后按中档梯度以 `tools/ci_check.sh <合并提交>` 现查读数补记「最窄复跑」格——零触发或不可判不作绿证)。 + +- 卡①卷轴视口批(验收档:中):对照表 10 行全通过;绑定面抽查 4 行钉面成立;削弱零申报外;判据出处 4+ 处独立可写出;缺漏 3 项均建议级(D1 能力行名实回表、D2 直查申报口径补记、D3 呈报笔误)。 +- 卡②改写族清退批(验收档:中):对照表 8 行全通过;契约 1/2/3/5/6/7 审计员重跑/逐处核对全部成立;削弱恰为申报内 4 处期望串且强度不降;40 名扫描与卡 §5 留底逐行一致;无阻断项。 +- golden 扩项:两 Shot 面用户裁决在案、基线入库、闸件对拍段与台账齐;mac 冻结义务已呈报(反哺点 6)。 diff --git a/待办清单.md b/待办清单.md index 73af9f33..4e6d90fb 100644 --- a/待办清单.md +++ b/待办清单.md @@ -257,3 +257,11 @@ **改动面**:游戏代码 **状态**:待执行 + +#### QA 覆盖总览面板与自动试玩扩展——自动发现测试验证缺漏(2026-11-05 登记,来源=会话提及) + +**实况**:方案全文=`D:\code\qa-harness-discussion\QA-Harness讨论结果-中间报告.md`(三批定案,全部三关试点):①探针存量 emit 真输入化(~40 处站点,承接上条)②B 覆盖总览面板+本体枚举器(六源回执明细化+能力清单提取+HTML 双击即开+游戏内容↔测试验证对账)③C 自动试玩扩展(auto_player 扩全动线全功能,异常上报含机器自填归因)。裁决在案勿重提:A 执行覆盖矩阵不做、D 缺口闸不做、变异测试禁入、归因登记不立独立制度。 + +**改动面**:游戏代码+工具代码+文档 + +**状态**:待执行 From b4e6db2f8918927f5ec003d9495d1c92ae8c1192 Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Fri, 6 Nov 2026 00:33:47 +0800 Subject: [PATCH 06/10] =?UTF-8?q?=E6=8A=A5=E5=91=8A(=E6=95=88=E6=9E=9C?= =?UTF-8?q?=E9=80=9A=E9=81=93=E4=B8=8E=E4=BA=8B=E4=BB=B6=E8=AF=8D=E9=9B=B6?= =?UTF-8?q?=E7=8E=B0=E5=BD=B9=E6=99=AE=E6=9F=A5):=20=E5=8F=A3=E5=BE=84?= =?UTF-8?q?=E6=94=B6=E7=AA=84=E9=87=8D=E5=86=99=E2=80=94=E2=80=94=E5=9F=8B?= =?UTF-8?q?=E7=82=B9=E5=B1=82=E4=B8=8E=E5=86=85=E5=AE=B9=E5=B1=82=E4=B8=A4?= =?UTF-8?q?=E5=B1=82=E5=88=86=E5=BC=80=E5=88=A4=EF=BC=9B=E5=9B=9B=E8=AF=8D?= =?UTF-8?q?=E8=A1=A8+schema=E6=97=A7=E8=AF=8D=E5=B1=82=E5=85=A8=E9=83=A8?= =?UTF-8?q?=E5=B1=9E=E9=A2=84=E7=95=99=E5=9F=8B=E7=82=B9=E9=9D=A2=E8=AF=8D?= =?UTF-8?q?=E9=9D=A2=E5=85=A8=E4=BF=9D=E7=95=99=E9=9B=B6=E6=B8=85=E9=80=80?= =?UTF-8?q?=E9=A1=B9(=E6=9E=B6=E6=9E=84=E5=8E=9F=E5=88=99=3D=E8=AF=8D?= =?UTF-8?q?=E8=A1=A8=E5=85=88=E8=A1=8C=E5=86=85=E5=AE=B9=E5=90=8E=E6=8E=A5?= =?UTF-8?q?,effect=5Fengine=20=E5=A4=B4=E6=B3=A8=E6=98=8E=E6=96=87)?= =?UTF-8?q?=EF=BC=9B=E5=86=85=E5=AE=B9=E5=B1=82=E9=9B=B6=E5=AD=A4=E5=84=BF?= =?UTF-8?q?(=E6=95=B0=E6=8D=AE=E8=A1=8C=E5=85=A8=E9=83=A8=E5=9C=A8?= =?UTF-8?q?=E5=BD=B9)=EF=BC=9Bspawn=5Fspell=3D=E9=94=BB=E9=80=A0=E6=B3=95?= =?UTF-8?q?=E6=9D=96=E8=AE=BE=E8=AE=A1=E5=9C=A8=E5=86=8C=E5=BE=85=E6=8E=A5?= =?UTF-8?q?=E7=BA=BF=E3=80=81bias=5Frewards/counter=5Fspend=3D=E6=9E=B6?= =?UTF-8?q?=E6=9E=84=E5=9C=A8=E5=BD=B9=E6=9C=BA=E5=88=B6=E6=89=BF=E8=BD=BD?= =?UTF-8?q?=E4=BD=8D=E3=80=81=E6=97=A7=E8=AF=8D=E5=B1=82=3D=E8=BF=AD?= =?UTF-8?q?=E4=BB=A322=E7=A7=98=E5=AE=9D=E6=89=B9=E6=8D=A2=E4=BB=A3?= =?UTF-8?q?=E9=81=97=E7=95=99=E8=BF=81=E7=A7=BB=E5=B0=BE=E5=B7=B4(?= =?UTF-8?q?=E6=94=B6=E5=B0=BE=E5=BD=92=E7=94=A8=E6=88=B7=E5=8F=A6=E4=BB=A4?= =?UTF-8?q?)=EF=BC=9B=E5=94=AF=E4=B8=80=E5=AE=9E=E8=B4=A8=E5=8F=91?= =?UTF-8?q?=E7=8E=B0=3D=E5=8F=99=E8=BF=B0=E8=84=B1=E8=8A=825=E5=A4=84(?= =?UTF-8?q?=E6=8E=98=E8=BF=9B=E8=93=84=E8=83=BD/=E6=B7=B1=E6=8C=96?= =?UTF-8?q?=E9=92=BB=E5=A4=B4/=E7=88=86=E7=A0=B4=E5=B7=A5=E5=85=B5?= =?UTF-8?q?=E5=8C=85=E4=B8=89=E4=B8=93=E9=95=BF=E6=9C=AA=E5=85=A5=E8=A1=A8?= =?UTF-8?q?=E8=80=8C=E6=B3=A8=E9=87=8A=E4=BD=9C=E5=9C=A8=E5=BD=B9=E5=8F=99?= =?UTF-8?q?=E8=BF=B0,=E8=AE=A2=E6=AD=A3=E6=96=B9=E5=90=91=3D=E6=B3=A8?= =?UTF-8?q?=E6=98=8E=E9=A2=84=E7=95=99=E4=B8=8D=E5=8A=A8=E9=80=BB=E8=BE=91?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../普查-效果通道与事件词零现役-2026-11-06.md | 132 ++++++------------ 1 file changed, 46 insertions(+), 86 deletions(-) diff --git a/reports/普查-效果通道与事件词零现役-2026-11-06.md b/reports/普查-效果通道与事件词零现役-2026-11-06.md index f83298b3..43aaea90 100644 --- a/reports/普查-效果通道与事件词零现役-2026-11-06.md +++ b/reports/普查-效果通道与事件词零现役-2026-11-06.md @@ -1,113 +1,73 @@ # 普查:效果通道与事件词零现役(2026-11-06) -> **接收方**:待办清单「效果通道与事件词的零现役普查」条——本报告是该条写卡段的输入合同。 -> **性质**:普查取证报告(只读扫描,零代码改动)。词表全集与引擎侧状态以 `game/core/effect_engine.gd` 现值为准;数据面使用统计按行结构键(`"on"`/`"kind"`/`"fact"`/`"op"`/`"channel"`)提取自 `game/data/tables/*.tres` 全域,不数裸词面(注释与载荷键不计)。 -> **判定口径**:引擎侧有发射点/消费分支 + 数据表零行 = **空架子**(架子完整等数据);引擎侧连消费分支都没有 = **死词**;词面在册但实际走别的通道 = **岗位错位**。 +> **接收方**:待办清单「效果通道与事件词的零现役普查」条——本报告是该条的产出合同。 +> **性质**:普查取证报告(只读扫描,零代码改动)。 +> **普查结论**:效果系统内容层(数据行)**零孤儿**——全部在役;四张词表+秘宝表 schema 旧词层全部属**预留埋点面**,词面全部保留、零清退项(架构原则=词表先行、内容后接:加一件已有效果类型的专长/秘宝只写 .tres 数据行零代码,effect_engine.gd 头注明文);唯一实质发现=**注释叙述脱节 5 处**(第三节,订正建议)。 +> **普查口径**:埋点层(引擎侧封闭词表、发射点、消费分支、查询实现——动态配置可达的预留触发点)与内容层(哪件秘宝/专长经数据行声明使用)两层分开判;本报告只登记两层现状,不做埋点层去留裁决。 -## 一、普查方法与范围 +## 一、普查范围与方法 -效果系统四词表封闭在 `effect_engine.gd` 常量:事件 `EVENTS`(21)/效果类型 `EFFECT_KINDS`(31)/事实 `FACTS`(18)/算子 `OPS`(13)。另扫两个邻接面:秘宝表 schema 旧词层(`treasure_item_table.gd` `EFFECT_KINDS` 旧词段 10 词,头注明文「旧词保留共存至迁移完成」)与效果参数 `channel` 域。数据面使用域 = feats/treasure_items 两表 trigger 行 + 天赋树规则合成行(`_push_tree_rule` 引擎内组装)+ 秘宝表 `effect_kinds`/主动件 `kind` 域。skills.tres(敌技)的 when/fact 走独立系统(消费端 `unit_container.gd`),不入本普查面。 +效果系统四词表封闭在 `effect_engine.gd` 常量:事件 `EVENTS`(21)/效果类型 `EFFECT_KINDS`(31)/事实 `FACTS`(18)/算子 `OPS`(13)。邻接面:秘宝表 schema 旧词层(`treasure_item_table.gd` `EFFECT_KINDS` 旧词段 10 词)与效果参数 `channel` 域。数据面使用域 = feats/treasure_items 两表 trigger 行 + 天赋树规则合成行(引擎内组装)+ 秘宝表 `effect_kinds`/主动件 `kind` 域。skills.tres(敌技)的 when/fact 走独立系统(消费端 unit_container),不入本普查面。数据面统计按行结构键(`"on"`/`"kind"`/`"fact"`/`"op"`/`"channel"`)提取自 `game/data/tables/*.tres` 全域,不数注释里的裸词面。 -## 二、六面清单 +## 二、埋点台账(词面全部保留;下表只登记各词现状) -### 1. 事件词——零订阅 4 个(发射点全在,完整空架子) +### 1. 事件词(21) -| 事件词 | 发射点 | 数据表订阅行 | 判定 | -|---|---|---|---| -| armor_roll | damage_controller.gd:296 | 0(feats 零订阅) | 空架子。**词两岗**:掷点流名岗在役(settlement.tres:59 `armor_roll_stream`),事件岗零使用 | -| reward_roll | battle_fx_host.gd:130 | 0 | 空架子 | -| treasure_used | reward_grant.gd:133 | 0 | 空架子 | -| seal_settle | grant_segment.gd:250 | 0 | 空架子 | +| 现状 | 词 | 说明 | +|---|---|---| +| 订阅在役(17) | dig_reveal/dig_paid/seal_hit/mine_hit/attack_commit/clamp_check/kill/damage_taken/round_start/round_end/seal_settle 以外全表 | feats/treasure 数据行 1–11 行不等 | +| 预留(4) | armor_roll(事件岗)/reward_roll/treasure_used/seal_settle | 发射点全在役运行(damage_controller:296/battle_fx_host:130/reward_grant:133/grant_segment:250),等订阅内容接线。armor_roll 另有掷点流名岗在役(settlement.tres:59),事件岗与流名岗同词两用 | -其余 17 事件词订阅行在役(feats 1–11 行不等、treasure_items 1–2 行)。 +### 2. 效果类型词(effect_engine 词表 31) -### 2. 效果类型词(effect_engine 词表 31)——数据面零使用 10 个 +| 现状 | 词 | 说明 | +|---|---|---| +| 数据面在役(21) | counter_add/grant_ap/reveal_tiles/damage_reduce/grant_gp/grant_material/preview_area/remove_mines/ac_bonus/attack_bonus/shield/blast_scaled/heal/target_attack_bonus/bonus_delta/modify_ticket/open_ticket/forgive_seal_miss/grant_reserve_ap/apply_discount/mine_count_preview | feats 1–27 行不等;treasure 1–2 行 | +| 引擎内组装在役(1) | damage_mult | 天赋树规则合成行在用(effect_engine.gd:160) | +| 设计在册待接线(1) | spawn_spell | 锻造工坊.md:115 法杖路线「开局魔法矢」设计在册,等法杖实装接线 | +| 架构在役机制承载位(2) | bias_rewards/counter_spend | bias_rewards=偏运权重系统效果层承载(architecture.md「BattleFxHost」行:luck_bias_for 偏运合计查询口在役,零订阅时返回 0=原行集零扰动);counter_spend=受理闸模式(action_economy:115/reward_grant:135 两受理闸+交叉校验规则),为「积点足才受理」类效果预留 | +| 词表先行预留(7) | add_ticket_rider/yield_mult/apply_status/bias_wallet/refresh_pick/preview/spike(独立 kind 岗) | 消费分支或主动件分发位在(damage_controller:399/grant_segment:118、:429/battle_fx_host:131 等);spike 实走 modify_ticket 的 mode="spike" 通道(damage_controller:312、:371,在役),独立 kind 词面=同语义的预留位 | -| 词 | 消费分支 | 数据表行 | 判定 | -|---|---|---|---| -| add_ticket_rider | damage_controller.gd:399 | 0 | 空架子 | -| yield_mult | grant_segment.gd:118 | 0 | 空架子 | -| spawn_spell | grant_segment.gd:138 | 0 | 空架子 | -| apply_status | damage_controller.gd:429 | 0 | 空架子(另注意:状态施加在 damage_controller 有独立路径) | -| bias_rewards | battle_fx_host.gd:131 | 0 | 空架子 | -| counter_spend | action_economy.gd:115 + reward_grant.gd:135(两受理闸) | 0 | 空架子——见「叙述脱节」节:其服务对象掘进蓄能/深挖钻头两件专长零在表 | -| bias_wallet | 全域零字面 | 0 | 死词(词表头注称与 grant_gp「共享行拆型」,grant_gp 分支内亦无此词) | -| refresh_pick | 全域零字面 | 0 | 死词(ACTIVE_KINDS 在册,主动分发面亦零) | -| preview | 全域零字面 | 0 | 死词(同上) | -| spike | 独立 kind 零消费 | 0 | **岗位错位**:实走 `modify_ticket` `mode="spike"`(damage_controller.gd:312/:371,在役);独立 kind 词面在册——与迭代 53 清退批已核的「spike 承接句」同源 | +### 3. 事实词(FACTS 18) -其余 21 词数据面在役(feats 1–27 行);`damage_mult` 由天赋树规则合成行在役(effect_engine.gd:160)。 +| 现状 | 词 | +|---|---| +| 数据面在役(12) | matchup/counter/new_resource_type/is_edge_cell/is_blank_zero/dug_under_seal/ap_exhausted_last/hp_ratio/amount/ap_left/pct/round_index | +| 预留(6) | is_first_dig_of_battle/terrain_kind(载荷特判支撑在:effect_engine.gd:322-331)/target_armor_class/seals_count/nest_count/battle_index | -### 3. 秘宝表 schema 旧词层(10 词)——数据面在役 1、零行 9 +### 4. 算子词(OPS 13) -| 旧词 | 消费点 | 数据表行 | 判定 | -|---|---|---|---| -| ap_charge_safe | —(常时参数注入面) | treasure_items.tres:62 | 在役 | -| mine_reveal | reward_grant.gd:147(主动分发判定) | 0 | 空架子(新旧词共存态:新词 reveal_tiles 同分支在役) | -| reward_preview | reward_grant.gd:151 | 0 | 空架子 | -| ap_grant | reward_grant.gd:153 | 0 | 空架子(数据面走新词形 `grant_ap`) | -| cell_removal | reward_grant.gd:160-161 | 0 | 空架子——原实况点名组 | -| bonus_refresh | adventure_runner/battle_orchestrator/refresh_bank | 0 | 空架子 | -| mine_hit_halve | 全域零文件命中 | 0 | 死词——原实况点名组 | -| reflect_damage | 全域零文件命中 | 0 | 死词。反弹 N 本由其 magnitude 承载(schema 注释),对应 `open_ticket` `channel="reflect"` 行族零表行(21 张表逐张核)——原实况点名组 | -| ap_rounds_front | 全域零文件命中 | 0 | 死词 | -| reward_weight_bias | 全域零文件命中 | 0 | 死词 | +| 现状 | 词 | +|---|---| +| 数据面在役(6) | eq/gte/lte/lt/mod_eq(双管镐)/advantageous(淬毒刃纹) | +| 预留(7) | neq/gt/ends_with/has/mod_zero/gte_ref/lt_ref(实现函数全在:_cmp_ok/_ends_with_ok:312/_has_ok:324/_counter_op_ok:335) | -schema 头注「旧词保留共存至迁移完成」——迁移未完成态本身在册为债。 +### 5. 秘宝表 schema 旧词层(10)——旧目录换代遗留的迁移尾巴 -### 4. 事实词(FACTS 18)——数据面零使用 6 个 +历史(git 查证):这批词曾服务旧秘宝目录数据行,经「秘宝六件迁移+令牌兑付收敛」批(a33ddaf5)与迭代 22 秘宝批(48b06961,旧目录 12 行删除、新目录 12 行落表:晨操令/阔视野带/试炼镐/刷新练习/储备罐/巢穴预告/线香/双管装填/远程镐/刷新执照/天眼/信标网络)两轮换代后,数据行全用新词形,词面按 schema 头注「旧词保留共存至迁移完成」留下。 -| 词 | 引擎侧 | 数据表行 | 判定 | -|---|---|---|---| -| is_first_dig_of_battle | 查询面在 | 0 | 裸预留 | -| terrain_kind | 载荷特判在(effect_engine.gd:322-331——敌技伤害载荷回落 null 判「不在场」) | 0 | 空架子(特判支撑、零表行) | -| target_armor_class | 查询面在 | 0 | 裸预留 | -| seals_count | 查询面在 | 0 | 裸预留 | -| nest_count | 查询面在 | 0 | 裸预留 | -| battle_index | 查询面在 | 0 | 裸预留 | - -其余 12 词在役(头注点名的用途专长——地质学家/边陲矿工/跳格采掘/破封一击/一滴不剩/背水/保险丝/弃图兑换等——逐个核在 feats.tres 在表)。 - -### 5. 算子词(OPS 13)——数据面零使用 7 个 - -| 词 | 引擎侧 | 数据表行 | 判定 | -|---|---|---|---| -| neq | 实现在(_cmp_ok) | 0 | 裸预留 | -| gt | 实现在(_cmp_ok) | 0 | 裸预留 | -| ends_with | 实现在(_ends_with_ok:312) | 0 | 空架子(头注称「对某甲族的泛条件」——无承载件) | -| has | 实现在(_has_ok:324) | 0 | 空架子 | -| mod_zero | 实现在(_counter_op_ok:335) | 0 | 空架子——见「叙述脱节」:头注称用途「掘进蓄能」,该专长零在表 | -| gte_ref | 实现在(_counter_op_ok:335) | 0 | 空架子——头注称用途「深挖钻头配额」,该专长零在表 | -| lt_ref | 实现在(_counter_op_ok:335) | 0 | 同上 | - -其余 6 算子在役(eq/gte/lte/lt/mod_eq/advantageous——mod_eq 双管镐、advantageous 淬毒刃纹均核在表)。 +| 现状 | 词 | 说明 | +|---|---|---| +| 在役(1) | ap_charge_safe | treasure_items.tres:62 | +| 新旧词共存(3) | mine_reveal/reward_preview/ap_grant | 消费分发点在(reward_grant.gd:147/:151/:153);现役等价能力由新词形承载(雷区揭示→天眼、奖励预览→示警烟火类、行动点授予→新形) | +| 换代遗留(6) | mine_hit_halve(踩雷伤害减半)/reflect_damage(受击反弹伤害,对应 open_ticket channel="reflect" 行族)/ap_rounds_front(开局前几轮行动点加成)/cell_removal(爆破工兵包中立移除格——消费点在 reward_grant.gd:160-161)/reward_weight_bias(奖励摇号权重偏置)/bonus_refresh(换图刷新冒险加算区——消费面在 adventure_runner/battle_orchestrator/refresh_bank) | 旧内容已裁、通道位预留;「迁移完成」收尾是否执行=用户另行发令,本普查不动 | ### 6. channel 域 -数据面现值仅 `blast`(feats 2 行)。`open_ticket` `channel="reflect"` 反弹行族零表行。channel 值域未单点封闭(各消费分支自判值,无独立词表常量)——去留裁定时可一并裁是否收词表。 +数据面现值仅 `blast`(feats 2 行);`open_ticket` 反弹行族零行(预留)。channel 值域未单点封闭(各消费分支自判值)——是否收词表=日后的独立设计决定,本普查不动。 -## 三、叙述脱节点(注释把不存在的专长写成在役叙述——spike 案同款误导航源) +## 三、叙述脱节(唯一实质发现——注释把未入表的内容写成在役叙述) -| 位置 | 叙述 | 事实 | +订正方向:注释注明「预留、未设计入表」,不动任何代码逻辑与词表。执行通道与是否执行由用户发令。 + +| 位置 | 现行叙述 | 事实 | |---|---|---| -| effect_engine.gd OPS 头注 | mod_zero「掘进蓄能」、gte_ref/lt_ref「深挖钻头配额」 | 两专长 feats/treasure 零在表(grep 专名零命中) | -| effect_engine.gd EFFECT_KINDS 头注 | spike 独立 kind 在词表 | 实走 modify_ticket mode 通道(岗位错位) | +| effect_engine.gd OPS 头注 | mod_zero「掘进蓄能」、gte_ref/lt_ref「深挖钻头配额」 | 两专长 feats/treasure 零在表(专名 grep 零命中) | +| effect_engine.gd EFFECT_KINDS 头注 | spike 独立 kind 在词表 | 实走 modify_ticket mode="spike" 通道 | | reward_grant.gd:130 | 「counter_spend 订阅=掘进蓄能积点账本」 | 掘进蓄能零在表 | | action_economy.gd:82 | 「深挖钻头付费开掘(dig_paid counter_spend 订阅施加面)」 | 深挖钻头零在表 | | treasure_item_table.gd:20 | 「cell_removal = 爆破工兵包中立移除格」 | 爆破工兵包零在表 | -## 四、裁决点清单(逐组裁:删/补内容接线/留作预留) +## 四、义务出口 -| 组 | 内容 | 裁决选项 | -|---|---|---| -| A | 事件词 4:armor_roll(事件岗)/reward_roll/treasure_used/seal_settle | 删词+摘发射点,或补一件订阅专长 | -| B | 效果词空架子 6:add_ticket_rider/yield_mult/spawn_spell/apply_status/bias_rewards/counter_spend | 同上 | -| C | 效果词死词 3:bias_wallet/refresh_pick/preview | 删词(含 ACTIVE_KINDS 对应位) | -| D | spike 独立 kind | 删词面(mode 通道在役不动) | -| E | schema 旧词 9:死词 4 直删候选(mine_hit_halve/reflect_damage/ap_rounds_front/reward_weight_bias);空架子 5(mine_reveal/reward_preview/ap_grant/cell_removal/bonus_refresh)删或完成迁移 | 删词或接线;同批裁「迁移完成」口径 | -| F | 事实词 6/算子词 7:裸预留与空架子 | 删或留预留(预留需头注改述为「预留无承载件」) | -| G | 叙述脱节 5 处 | 随 A–F 同批订正注释 | - -## 五、与原实况登记 4 组的对应 - -原实况 4 组(cell_removal/mine_hit_halve/open_ticket reflect 行族/armor_roll 订阅)全部复核成立;普查扩面新增:事件词 3(reward_roll/treasure_used/seal_settle)、效果词 10、旧词层另 5、事实词 6、算子词 7、叙述脱节 5 处。 +本普查为待办清单该条的产出:内容层零孤儿、词面零清退项、零代码改动——该条不产生写卡需求;叙述订正 5 处是否执行由用户发令(执行时属注释修订,不改行为)。 From 515a50f896a8cd1bb3b92f19b054ffd77e888ce3 Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Fri, 6 Nov 2026 00:38:09 +0800 Subject: [PATCH 07/10] =?UTF-8?q?=E6=8A=A5=E5=91=8A(=E6=95=88=E6=9E=9C?= =?UTF-8?q?=E9=80=9A=E9=81=93=E4=B8=8E=E4=BA=8B=E4=BB=B6=E8=AF=8D=E9=9B=B6?= =?UTF-8?q?=E7=8E=B0=E5=BD=B9=E6=99=AE=E6=9F=A5):=20=E6=8C=89=E8=AF=BB?= =?UTF-8?q?=E8=80=85=E5=8A=A8=E4=BD=9C=E9=87=8D=E7=BB=84=E2=80=94=E2=80=94?= =?UTF-8?q?=E7=AC=AC=E4=B8=80=E8=8A=82=3D=E9=9C=80=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E8=A3=81=E6=96=AD=E7=9A=842=E4=BB=B6=E4=BA=8B(=E5=8F=99?= =?UTF-8?q?=E8=BF=B0=E8=AE=A2=E6=AD=A35=E5=A4=84=E5=81=9A=E4=B8=8D?= =?UTF-8?q?=E5=81=9A/=E6=97=A7=E8=AF=8D=E8=BF=81=E7=A7=BB=E6=94=B6?= =?UTF-8?q?=E5=B0=BE=E5=81=9A=E4=B8=8D=E5=81=9A=E4=BD=95=E6=97=B6=E5=81=9A?= =?UTF-8?q?)=E3=80=81=E7=AC=AC=E4=BA=8C=E8=8A=82=3D=E6=97=A0=E9=9C=80?= =?UTF-8?q?=E5=A4=84=E7=90=86=E9=A1=B9=E8=AE=A1=E6=95=B0=E5=AD=98=E6=A1=A3?= =?UTF-8?q?(=E9=A2=84=E7=95=99=E8=AF=8D=E9=9D=A2=E5=85=A8=E9=83=A8?= =?UTF-8?q?=E4=BF=9D=E7=95=99=E9=9B=B6=E8=A3=81=E5=86=B3=E7=82=B9)?= =?UTF-8?q?=E3=80=81=E7=AC=AC=E4=B8=89=E8=8A=82=3D=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E5=AD=98=E6=A1=A3=EF=BC=9B=E8=AF=8D=E8=A1=A8=E9=9D=A2=E5=8F=B0?= =?UTF-8?q?=E8=B4=A6=E4=BB=8E=E6=AD=A3=E6=96=87=E7=A7=BB=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../普查-效果通道与事件词零现役-2026-11-06.md | 92 +++++++------------ 1 file changed, 32 insertions(+), 60 deletions(-) diff --git a/reports/普查-效果通道与事件词零现役-2026-11-06.md b/reports/普查-效果通道与事件词零现役-2026-11-06.md index 43aaea90..72b524a2 100644 --- a/reports/普查-效果通道与事件词零现役-2026-11-06.md +++ b/reports/普查-效果通道与事件词零现役-2026-11-06.md @@ -1,73 +1,45 @@ # 普查:效果通道与事件词零现役(2026-11-06) > **接收方**:待办清单「效果通道与事件词的零现役普查」条——本报告是该条的产出合同。 -> **性质**:普查取证报告(只读扫描,零代码改动)。 -> **普查结论**:效果系统内容层(数据行)**零孤儿**——全部在役;四张词表+秘宝表 schema 旧词层全部属**预留埋点面**,词面全部保留、零清退项(架构原则=词表先行、内容后接:加一件已有效果类型的专长/秘宝只写 .tres 数据行零代码,effect_engine.gd 头注明文);唯一实质发现=**注释叙述脱节 5 处**(第三节,订正建议)。 -> **普查口径**:埋点层(引擎侧封闭词表、发射点、消费分支、查询实现——动态配置可达的预留触发点)与内容层(哪件秘宝/专长经数据行声明使用)两层分开判;本报告只登记两层现状,不做埋点层去留裁决。 +> **结论**:需要你处理的事只有 **2 件**(第一节);扫描面内其余全部属预留埋点,**全部保留、零处理项**(第二节只留计数供存档)。词表零改动、内容层零孤儿、零代码改动。 -## 一、普查范围与方法 +## 一、需要你裁断的两件事 -效果系统四词表封闭在 `effect_engine.gd` 常量:事件 `EVENTS`(21)/效果类型 `EFFECT_KINDS`(31)/事实 `FACTS`(18)/算子 `OPS`(13)。邻接面:秘宝表 schema 旧词层(`treasure_item_table.gd` `EFFECT_KINDS` 旧词段 10 词)与效果参数 `channel` 域。数据面使用域 = feats/treasure_items 两表 trigger 行 + 天赋树规则合成行(引擎内组装)+ 秘宝表 `effect_kinds`/主动件 `kind` 域。skills.tres(敌技)的 when/fact 走独立系统(消费端 unit_container),不入本普查面。数据面统计按行结构键(`"on"`/`"kind"`/`"fact"`/`"op"`/`"channel"`)提取自 `game/data/tables/*.tres` 全域,不数注释里的裸词面。 +### 1. 注释叙述订正 5 处——做不做 -## 二、埋点台账(词面全部保留;下表只登记各词现状) - -### 1. 事件词(21) - -| 现状 | 词 | 说明 | -|---|---|---| -| 订阅在役(17) | dig_reveal/dig_paid/seal_hit/mine_hit/attack_commit/clamp_check/kill/damage_taken/round_start/round_end/seal_settle 以外全表 | feats/treasure 数据行 1–11 行不等 | -| 预留(4) | armor_roll(事件岗)/reward_roll/treasure_used/seal_settle | 发射点全在役运行(damage_controller:296/battle_fx_host:130/reward_grant:133/grant_segment:250),等订阅内容接线。armor_roll 另有掷点流名岗在役(settlement.tres:59),事件岗与流名岗同词两用 | - -### 2. 效果类型词(effect_engine 词表 31) - -| 现状 | 词 | 说明 | -|---|---|---| -| 数据面在役(21) | counter_add/grant_ap/reveal_tiles/damage_reduce/grant_gp/grant_material/preview_area/remove_mines/ac_bonus/attack_bonus/shield/blast_scaled/heal/target_attack_bonus/bonus_delta/modify_ticket/open_ticket/forgive_seal_miss/grant_reserve_ap/apply_discount/mine_count_preview | feats 1–27 行不等;treasure 1–2 行 | -| 引擎内组装在役(1) | damage_mult | 天赋树规则合成行在用(effect_engine.gd:160) | -| 设计在册待接线(1) | spawn_spell | 锻造工坊.md:115 法杖路线「开局魔法矢」设计在册,等法杖实装接线 | -| 架构在役机制承载位(2) | bias_rewards/counter_spend | bias_rewards=偏运权重系统效果层承载(architecture.md「BattleFxHost」行:luck_bias_for 偏运合计查询口在役,零订阅时返回 0=原行集零扰动);counter_spend=受理闸模式(action_economy:115/reward_grant:135 两受理闸+交叉校验规则),为「积点足才受理」类效果预留 | -| 词表先行预留(7) | add_ticket_rider/yield_mult/apply_status/bias_wallet/refresh_pick/preview/spike(独立 kind 岗) | 消费分支或主动件分发位在(damage_controller:399/grant_segment:118、:429/battle_fx_host:131 等);spike 实走 modify_ticket 的 mode="spike" 通道(damage_controller:312、:371,在役),独立 kind 词面=同语义的预留位 | - -### 3. 事实词(FACTS 18) - -| 现状 | 词 | -|---|---| -| 数据面在役(12) | matchup/counter/new_resource_type/is_edge_cell/is_blank_zero/dug_under_seal/ap_exhausted_last/hp_ratio/amount/ap_left/pct/round_index | -| 预留(6) | is_first_dig_of_battle/terrain_kind(载荷特判支撑在:effect_engine.gd:322-331)/target_armor_class/seals_count/nest_count/battle_index | - -### 4. 算子词(OPS 13) - -| 现状 | 词 | -|---|---| -| 数据面在役(6) | eq/gte/lte/lt/mod_eq(双管镐)/advantageous(淬毒刃纹) | -| 预留(7) | neq/gt/ends_with/has/mod_zero/gte_ref/lt_ref(实现函数全在:_cmp_ok/_ends_with_ok:312/_has_ok:324/_counter_op_ok:335) | - -### 5. 秘宝表 schema 旧词层(10)——旧目录换代遗留的迁移尾巴 - -历史(git 查证):这批词曾服务旧秘宝目录数据行,经「秘宝六件迁移+令牌兑付收敛」批(a33ddaf5)与迭代 22 秘宝批(48b06961,旧目录 12 行删除、新目录 12 行落表:晨操令/阔视野带/试炼镐/刷新练习/储备罐/巢穴预告/线香/双管装填/远程镐/刷新执照/天眼/信标网络)两轮换代后,数据行全用新词形,词面按 schema 头注「旧词保留共存至迁移完成」留下。 - -| 现状 | 词 | 说明 | -|---|---|---| -| 在役(1) | ap_charge_safe | treasure_items.tres:62 | -| 新旧词共存(3) | mine_reveal/reward_preview/ap_grant | 消费分发点在(reward_grant.gd:147/:151/:153);现役等价能力由新词形承载(雷区揭示→天眼、奖励预览→示警烟火类、行动点授予→新形) | -| 换代遗留(6) | mine_hit_halve(踩雷伤害减半)/reflect_damage(受击反弹伤害,对应 open_ticket channel="reflect" 行族)/ap_rounds_front(开局前几轮行动点加成)/cell_removal(爆破工兵包中立移除格——消费点在 reward_grant.gd:160-161)/reward_weight_bias(奖励摇号权重偏置)/bonus_refresh(换图刷新冒险加算区——消费面在 adventure_runner/battle_orchestrator/refresh_bank) | 旧内容已裁、通道位预留;「迁移完成」收尾是否执行=用户另行发令,本普查不动 | - -### 6. channel 域 - -数据面现值仅 `blast`(feats 2 行);`open_ticket` 反弹行族零行(预留)。channel 值域未单点封闭(各消费分支自判值)——是否收词表=日后的独立设计决定,本普查不动。 - -## 三、叙述脱节(唯一实质发现——注释把未入表的内容写成在役叙述) - -订正方向:注释注明「预留、未设计入表」,不动任何代码逻辑与词表。执行通道与是否执行由用户发令。 +代码注释把三件**未设计入表**的专长(掘进蓄能/深挖钻头/爆破工兵包)写成了在役叙述,后来读代码或写卡的人会被误导(迭代 53 已发生过一次:spike 承接句按注释误判「零新代码」)。订正方式=把注释改成「预留、未设计入表」,不改任何逻辑。 | 位置 | 现行叙述 | 事实 | |---|---|---| -| effect_engine.gd OPS 头注 | mod_zero「掘进蓄能」、gte_ref/lt_ref「深挖钻头配额」 | 两专长 feats/treasure 零在表(专名 grep 零命中) | -| effect_engine.gd EFFECT_KINDS 头注 | spike 独立 kind 在词表 | 实走 modify_ticket mode="spike" 通道 | +| effect_engine.gd OPS 头注 | mod_zero「掘进蓄能」、gte_ref/lt_ref「深挖钻头配额」 | 两专长零在表 | +| effect_engine.gd EFFECT_KINDS 头注 | spike 独立 kind 在词表 | 实走 modify_ticket 的 mode 通道 | | reward_grant.gd:130 | 「counter_spend 订阅=掘进蓄能积点账本」 | 掘进蓄能零在表 | -| action_economy.gd:82 | 「深挖钻头付费开掘(dig_paid counter_spend 订阅施加面)」 | 深挖钻头零在表 | +| action_economy.gd:82 | 「深挖钻头付费开掘」 | 深挖钻头零在表 | | treasure_item_table.gd:20 | 「cell_removal = 爆破工兵包中立移除格」 | 爆破工兵包零在表 | -## 四、义务出口 +### 2. 秘宝表旧词「迁移完成」收尾——做不做、何时做 -本普查为待办清单该条的产出:内容层零孤儿、词面零清退项、零代码改动——该条不产生写卡需求;叙述订正 5 处是否执行由用户发令(执行时属注释修订,不改行为)。 +秘宝表 schema 词表里留着 9 个旧目录时代的词面(git 查证:迭代 22 秘宝批把旧目录 12 行全量换代成现役 12 件后,旧词面按 schema 自己注的「旧词保留共存至迁移完成」留下)。按关联效果列名: + +| 旧词承载的效果 | 类型 | +|---|---| +| 雷区揭示/奖励预览/行动点授予(3 个旧词形) | 新旧词共存——现役等价能力已由新词形承载 | +| 踩雷伤害减半/受击反弹伤害/开局前几轮行动点加成/爆破工兵包中立移除格/奖励摇号权重偏置/换图刷新加算区(6 个) | 旧内容已裁、通道位预留 | + +裁断点:这批「迁移完成」收尾要不要做、什么时候做。**词面现在不动**;收尾属于单独一批改动,做的时候再设计。 + +## 二、无需处理项汇总(零裁决点,计数存档) + +扫描面内以下词面全部判定**保留**(预留埋点——引擎架构=词表先行、内容后接,加一件已有效果类型的专长/秘宝只写数据行零代码): + +- **事件词预留 4**:armor_roll(事件岗)/reward_roll/treasure_used/seal_settle——发射点全在役运行,等订阅内容;armor_roll 另有掷点流名岗在役,同词两用。 +- **效果类型词预留 10**:spawn_spell(锻造工坊法杖设计在册待接线);bias_rewards/counter_spend(架构在役机制承载位——偏运合计查询口/受理闸模式);add_ticket_rider/yield_mult/apply_status/bias_wallet/refresh_pick/preview/spike 词面(预留位)。 +- **事实词预留 6**:is_first_dig_of_battle/terrain_kind(载荷特判支撑在)/target_armor_class/seals_count/nest_count/battle_index。 +- **算子词预留 7**:neq/gt/ends_with/has/mod_zero/gte_ref/lt_ref(实现函数全在)。 +- **channel 反弹行族**:open_ticket 反弹域零数据行(预留)。 + +其余全部事件词/效果词/事实词/算子词的数据面订阅行在役(feats/treasure 数据行+天赋树规则合成行),零孤儿。 + +## 三、普查方法(存档) + +四张词表封闭在 effect_engine.gd 常量:事件 21/效果类型 31/事实 18/算子 13;邻接面=秘宝表 schema 旧词层 10 词+channel 域。数据面使用按行结构键(`"on"`/`"kind"`/`"fact"`/`"op"`/`"channel"`)统计自 `game/data/tables/*.tres` 全域+天赋树规则合成行+秘宝表主动件域;注释裸词面不计。skills.tres(敌技)的 when/fact 走独立系统,不入本普查面。 From 111bf1bd1045e0bafb763ca5e29321bf159861bb Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Fri, 6 Nov 2026 00:48:30 +0800 Subject: [PATCH 08/10] =?UTF-8?q?=E6=B3=A8=E9=87=8A(=E5=8F=99=E8=BF=B0?= =?UTF-8?q?=E8=84=B1=E8=8A=82=E8=AE=A2=E6=AD=A3=C2=B7=E6=99=AE=E6=9F=A5?= =?UTF-8?q?=E6=89=B9=E6=89=A7=E8=A1=8C):=205=20=E5=A4=84=E6=8C=89=E3=80=8C?= =?UTF-8?q?=E9=A2=84=E7=95=99=E3=80=81=E6=9C=AA=E8=AE=BE=E8=AE=A1=E5=85=A5?= =?UTF-8?q?=E8=A1=A8=E3=80=8D=E5=8F=A3=E5=BE=84=E8=AE=A2=E6=AD=A3=E2=80=94?= =?UTF-8?q?=E2=80=94effect=5Fengine=20OPS=20=E5=A4=B4=E6=B3=A8=20mod=5Fzer?= =?UTF-8?q?o/gte=5Fref/lt=5Fref=20=E8=AE=BE=E6=83=B3=E7=94=A8=E9=80=94?= =?UTF-8?q?=E6=94=B9=E9=A2=84=E7=95=99=E6=B3=A8=E8=AE=B0=EF=BC=8BEFFECT=5F?= =?UTF-8?q?KINDS=20=E5=A4=B4=E6=B3=A8=E8=A1=A5=20spike=20=E7=8B=AC?= =?UTF-8?q?=E7=AB=8B=20kind=20=E5=B2=97=3D=E9=A2=84=E7=95=99=E5=AE=9E?= =?UTF-8?q?=E8=B5=B0=20modify=5Fticket=20mode=20=E9=80=9A=E9=81=93?= =?UTF-8?q?=E3=80=81reward=5Fgrant=20=5Fcharge=5Fgate=20=E5=A4=B4=E6=B3=A8?= =?UTF-8?q?=E6=8E=98=E8=BF=9B=E8=93=84=E8=83=BD=E5=8F=99=E8=BF=B0=E6=94=B9?= =?UTF-8?q?=E9=80=9A=E7=94=A8=E5=8F=97=E7=90=86=E9=97=B8+=E9=A2=84?= =?UTF-8?q?=E7=95=99=E6=B3=A8=E8=AE=B0=E3=80=81action=5Feconomy=20request?= =?UTF-8?q?=5Fdig=20=E5=A4=B4=E6=B3=A8=E6=B7=B1=E6=8C=96=E9=92=BB=E5=A4=B4?= =?UTF-8?q?=E5=8F=99=E8=BF=B0=E6=94=B9=E9=80=9A=E7=94=A8=E9=97=B8+?= =?UTF-8?q?=E9=A2=84=E7=95=99=E6=B3=A8=E8=AE=B0=E3=80=81treasure=5Fitem=5F?= =?UTF-8?q?table=20cell=5Fremoval=20=E7=88=86=E7=A0=B4=E5=B7=A5=E5=85=B5?= =?UTF-8?q?=E5=8C=85=E5=8F=99=E8=BF=B0=E6=94=B9=E9=A2=84=E7=95=99=E6=B3=A8?= =?UTF-8?q?=E8=AE=B0=EF=BC=9B=E9=9B=B6=E9=80=BB=E8=BE=91=E9=9B=B6=E8=AF=8D?= =?UTF-8?q?=E8=A1=A8=E6=94=B9=E5=8A=A8=E3=80=82=E5=BE=85=E5=8A=9E=E6=B8=85?= =?UTF-8?q?=E5=8D=95=E6=99=AE=E6=9F=A5=E6=9D=A1=E6=8E=A8=E8=BF=9B=EF=BC=9A?= =?UTF-8?q?=E6=99=AE=E6=9F=A5=E7=BB=93=E8=BD=AC=EF=BC=88=E6=8A=A5=E5=91=8A?= =?UTF-8?q?=E5=87=AD=E6=8D=AE+=E8=AE=A2=E6=AD=A3=E5=B7=B2=E6=89=A7?= =?UTF-8?q?=E8=A1=8C=EF=BC=89=EF=BC=8C=E9=81=97=E7=95=99=E6=97=A7=E8=AF=8D?= =?UTF-8?q?=E6=94=B6=E5=B0=BE=E5=BE=85=E8=A3=81=EF=BC=8C=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E5=BE=85=E5=86=99=E5=8D=A1=E2=86=92=E5=BE=85=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E3=80=82=E9=AA=8C=E8=AF=81=EF=BC=9A=E5=86=92=E7=83=9F=2015=20?= =?UTF-8?q?=E9=A1=B9=200=20=E5=A4=B1=E8=B4=A5=E4=B8=89=E9=97=B8=E5=85=A8?= =?UTF-8?q?=E8=BF=87=EF=BC=88worktree=20=E5=86=B7=E6=A3=80=E7=BC=BA=20.imp?= =?UTF-8?q?ort=20=E5=81=87=E7=BA=A2=E5=B7=B2=E7=BB=8F=E5=AF=BC=E5=85=A5?= =?UTF-8?q?=E6=B8=85=E5=81=BF=E2=80=94=E2=80=94=E5=9C=A8=E5=86=8C=E7=8E=AF?= =?UTF-8?q?=E5=A2=83=E5=9D=91=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- game/core/action_economy.gd | 4 ++-- game/core/effect_engine.gd | 7 ++++--- game/core/reward_grant.gd | 2 +- game/data/schemas/treasure_item_table.gd | 2 +- 待办清单.md | 6 ++++-- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/game/core/action_economy.gd b/game/core/action_economy.gd index 679302ef..b65ba993 100644 --- a/game/core/action_economy.gd +++ b/game/core/action_economy.gd @@ -79,9 +79,9 @@ func try_spend(action_kind: String) -> bool: # 排雷玩法 挖掘专用:chain_size = 连锁附加格数(不含首格);clears_map = 本次动作后全图安全格开完。 -# 深挖钻头付费开掘(dig_paid counter_spend 订阅施加面):按序消耗族——AP 富余(≥基础+对价)时本动作付全价并积本轮付费计数(效果引擎 +# 付费开掘通用闸(dig_paid counter_spend 订阅施加面):按序消耗族——AP 富余(≥基础+对价)时本动作付全价并积本轮付费计数(效果引擎 # 计数器=授予段追加产出配额取数面);AP 不足全价时 fallback 降级只付基础 1 照常开格、不积计数 -# ——持有钻头永不锁死普通挖格(散件保底 B-2)。 +# ——持有件永不锁死普通挖格(散件保底 B-2)。设想承载件「深挖钻头」未设计入表,通道位预留。 func request_dig(chain_size: int, clears_map: bool) -> bool: if _phase != Phase.ACTIVE: _reject("phase") diff --git a/game/core/effect_engine.gd b/game/core/effect_engine.gd index 33d3a725..a9831108 100644 --- a/game/core/effect_engine.gd +++ b/game/core/effect_engine.gd @@ -24,7 +24,8 @@ const MINE_EVENTS := ["dig_reveal", "dig_paid", "seal_hit", "mine_hit", "seal_se ## 效果类型词汇(解释器 switch 闭集——词表实数以 EFFECT_KINDS 常量为准,含共享行拆型: ## grant_gp/bias_wallet、counter_add/counter_spend、reveal_tiles/remove_mines/refresh_pick、 -## bias_rewards/preview。需求卡片标题计 23 系笔误,落码按行内容全收——commit 留痕) +## bias_rewards/preview。spike 独立 kind 岗=预留——实际语义走 modify_ticket mode="spike" 通道(在役)。 +## 需求卡片标题计 23 系笔误,落码按行内容全收——commit 留痕) const EFFECT_KINDS := ["add_ticket_rider", "modify_ticket", "damage_mult", "open_ticket", "attack_bonus", "yield_mult", "spawn_spell", "grant_material", "grant_ap", "grant_gp", "bias_wallet", "shield", "spike", "apply_status", "counter_add", @@ -61,8 +62,8 @@ const FACTS := ["matchup", "is_first_dig_of_battle", "terrain_kind", "target_arm "ap_exhausted_last", "hp_ratio", "amount", "ap_left", "pct", "battle_index"] # 关卡域战斗序(1 基,enc 携带;开局姿态组「每关首轮窗」条件面) -## when 算子词汇(封闭——fact 查询面落法:mod_zero=计数器取模判满〔掘进蓄能〕、 -## advantageous=克制矩阵正面判定〔淬毒刃纹〕、gte_ref/lt_ref=与另一计数器比较〔深挖钻头配额〕、 +## when 算子词汇(封闭——fact 查询面落法:mod_zero=计数器取模判满〔预留——设想用途「掘进蓄能」未设计入表〕、 +## advantageous=克制矩阵正面判定〔淬毒刃纹〕、gte_ref/lt_ref=与另一计数器比较〔预留——设想用途「深挖钻头」未设计入表〕、 ## ends_with=后缀匹配〔对某甲族的泛条件〕、mod_eq=取模余数判定〔双管镐每第 2 次——value=模数 ## ref=余数;dispatch 预评估口径〔when 于命中前读计数器现值〕下「每第 N 次」系用 ref=N-1 表达〕。 ## 均系映射表现状条件装进 fact 的查询面落法,白名单覆盖) diff --git a/game/core/reward_grant.gd b/game/core/reward_grant.gd index db957961..7d84273a 100644 --- a/game/core/reward_grant.gd +++ b/game/core/reward_grant.gd @@ -127,7 +127,7 @@ func use_treasure(handle: int, target: Vector2i) -> Dictionary: return {"ok": true, "item_id": v.item_id, "resolved": v.resolved, "record": rec} -# 受理闸(treasure_used 发射+施加:counter_spend 订阅=掘进蓄能积点账本,积点不足拒绝零消耗。 +# 受理闸(treasure_used 发射+施加:counter_spend 订阅=消耗型受理闸,积点不足拒绝零消耗;设想承载件「掘进蓄能」未设计入表,通道位预留。 # 零 item_id 特判;拒绝文案读装配集积点进度——宿主 attune 读投影) func _charge_gate(v: Dictionary, target: Vector2i) -> Dictionary: var tu_hits := fx_host.fx_emit("treasure_used", {"item_id": String(v.item_id), "target": target}) diff --git a/game/data/schemas/treasure_item_table.gd b/game/data/schemas/treasure_item_table.gd index ceaeccf0..362c5609 100644 --- a/game/data/schemas/treasure_item_table.gd +++ b/game/data/schemas/treasure_item_table.gd @@ -17,7 +17,7 @@ const UNLOCK_COUNTER_KEYS := ["adventure_cleared", "boss_kill_count", "vision_us const DIMENSIONS := ["info", "risk", "action", "plan", "counter"] # enum 九 kind 全部条件触发/机制修正类;mine_reveal/ap_grant 语义不变。 -# cell_removal = 爆破工兵包中立移除格;mine_hit_halve 系固定 +# cell_removal = 中立移除格通道(预留——设想承载件「爆破工兵包」未设计入表);mine_hit_halve 系固定 # 「减半」语义不消费 magnitude(反弹 N 由 reflect_damage 行 magnitude 承载)。 # 主动件 kind 词族(reveal_tiles/preview/grant_ap/remove_mines/ # refresh_pick——效果引擎 ACTIVE_KINDS 同名闭集);被动件不走 effect_kinds 词族 diff --git a/待办清单.md b/待办清单.md index 73af9f33..97207e4c 100644 --- a/待办清单.md +++ b/待办清单.md @@ -244,11 +244,13 @@ #### 效果通道与事件词的零现役普查(2026-11-05 登记,来源=审计发现) -**实况**:证据=四条 grep 读数:`cell_removal` 通道在册(`game/data/schemas/treasure_item_table.gd:26`;消费点 `game/core/reward_grant.gd:160-161`)而 `game/data/` 全域零数据行;`mine_hit_halve` 同形态(仅 schema 词表与注记在位);`open_ticket` 的 `channel="reflect"` 行族零表行(21 张 `.tres` 逐张 grep);`armor_roll` 在 `game/core/effect_engine.gd:13` 事件词表在册、发射点 `game/core/damage_controller.gd:296`,而 `game/data/tables/feats.tres` 零订阅行。形态与架构审查甲案已清的 overflow/attack_segments 死通道同族(判据出处=`design/engineering/code-conventions.md:15`、`design/engineering/test-conventions.md:116`)。本批(需求卡片-改写族孤儿机制与退役名清退批)只清其文案与归因串,通道与事件词本体去留待普查批整体裁。 +**实况**:普查报告 reports/普查-效果通道与事件词零现役-2026-11-06.md——结论=内容层零孤儿、四词表+秘宝表 schema 旧词层全部属预留埋点(词面全保留零清退项;架构原则=词表先行内容后接)。叙述脱节 5 处已按「预留、未设计入表」口径订正(2026-11-06 用户令直改,冒烟 15 项 0 失败三闸全过)。 + +**缺口**:唯一遗留待裁=秘宝表 schema 旧词面 9 个「迁移完成」收尾(做不做、何时做)。 **改动面**:游戏代码 -**状态**:待写卡 +**状态**:待执行 #### 测试面真输入化分期与存量断言逐条精锚(2026-11-05 登记,来源=批次移交) From 909a9709b4de16b27b6c9b771833995e079724e9 Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Fri, 6 Nov 2026 01:12:55 +0800 Subject: [PATCH 09/10] =?UTF-8?q?=E6=94=B6=E5=B0=BE(=E8=BF=AD=E4=BB=A353?= =?UTF-8?q?=E6=89=B9=E5=90=8E=E6=94=B6=E5=B0=BE)+CI=E8=BF=BD=E7=BB=BF?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D:=20=E5=8F=8D=E5=93=BA=E7=82=B9=E8=90=BD?= =?UTF-8?q?=E6=96=87(=E7=94=A8=E6=88=B7=E5=9B=9B=E7=82=B9=E8=A3=81?= =?UTF-8?q?=E5=86=B3=E5=9C=A8=E6=A1=88)=E2=80=94=E2=80=94=E5=8F=8D?= =?UTF-8?q?=E5=93=BA=E7=82=B93=20GDD=E9=80=80=E5=BD=B9=E5=90=8D=E6=B8=85?= =?UTF-8?q?=E9=80=80(=E6=9C=AF=E8=AF=AD=E8=A1=A8v1.27/=E5=9C=B0=E5=9B=BE?= =?UTF-8?q?=E6=88=98=E6=96=97=E8=B5=84=E6=BA=90v1.6=E6=8E=B7=E6=A0=BC?= =?UTF-8?q?=E4=BB=B6=E4=B8=A4=E8=B7=AF=E6=8A=95=E5=BD=B1=E6=8D=A2=E6=9C=BA?= =?UTF-8?q?=E5=88=B6=E5=90=8D=E8=AE=A2=E9=98=85=E5=8A=A0=E6=9D=83=E3=80=81?= =?UTF-8?q?00-=E6=B8=B8=E6=88=8F=E6=A6=82=E5=BF=B5=E5=88=A0=E6=97=A7?= =?UTF-8?q?=E5=85=AD=E8=A1=8C=E4=B8=93=E5=90=8D=E3=80=81=E5=A5=87=E7=89=A9?= =?UTF-8?q?=E4=B8=8E03-=E5=86=85=E5=AE=B9=E8=A7=84=E6=A8=A1=E9=80=80?= =?UTF-8?q?=E5=BD=B9=E8=AE=B0=E5=BD=95=E5=8F=A5=E4=BF=9D=E7=95=99=E4=B8=94?= =?UTF-8?q?=E5=90=8E=E8=80=85=E5=88=A0=E8=BF=87=E6=97=B6=E5=B0=BE=E5=8F=A5?= =?UTF-8?q?)+=E5=8F=8D=E5=93=BA=E7=82=B94=E8=A7=84=E8=8C=83=E5=8F=A5?= =?UTF-8?q?=E8=90=BD=E6=88=98=E6=96=97=E7=BB=93=E7=AE=97v1.8(=E6=98=8E?= =?UTF-8?q?=E7=BB=86=E6=96=87=E6=A1=88=3D=E6=95=B0=E6=8D=AE=E9=9D=A2?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E8=AF=BB=E8=A1=A8=E6=8B=BC=E8=A1=8C,?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E8=A3=81=E5=85=A5=E8=A1=A8)+=E5=8F=8D?= =?UTF-8?q?=E5=93=BA=E7=82=B97=20golden=E5=8F=B0=E8=B4=A6=E8=A1=A5lmap?= =?UTF-8?q?=E5=86=BB=E7=BB=93=E6=97=A5+=E5=8F=8D=E5=93=BA=E7=82=B98?= =?UTF-8?q?=E8=83=BD=E5=8A=9B=E8=A1=8C=E5=90=8D=E5=AE=9E=E5=9B=9E=E8=A1=A8?= =?UTF-8?q?=5Fand=5Fcolumns+=E5=8F=8D=E5=93=BA=E7=82=B99=20test-convention?= =?UTF-8?q?s=E6=8E=A2=E9=92=88=E7=9B=B4=E8=AF=BB=E5=8F=97=E6=8E=A7?= =?UTF-8?q?=E4=BE=8B=E5=A4=96=E6=B3=A8=E8=AE=B0;=20=E6=9C=AA=E5=86=B3?= =?UTF-8?q?=E8=BF=81=E8=B4=A6=E9=9D=A2(=E5=8F=8D=E5=93=BA=E7=82=B94?= =?UTF-8?q?=E6=96=B0=E7=AB=8B=E7=BB=93=E7=AE=97=E6=98=8E=E7=BB=86=E6=96=87?= =?UTF-8?q?=E6=A1=88=E5=85=A5=E8=A1=A8=E6=9D=A1=E7=9B=AE=E5=BE=85=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E8=AE=BE=E8=AE=A1/=E5=8F=8D=E5=93=BA=E7=82=B95?= =?UTF-8?q?=E9=97=B8=E6=9C=BA=E8=B6=85=E6=97=B6=E5=AE=88=E5=8D=AB=E7=BC=BA?= =?UTF-8?q?=E9=99=B7=E4=B8=8E=E5=8F=8D=E5=93=BA=E7=82=B96=20mac=E4=B8=A4Sh?= =?UTF-8?q?ot=E5=9F=BA=E7=BA=BF=E7=99=BB=E8=AE=B0=E5=BE=85=E6=89=A7?= =?UTF-8?q?=E8=A1=8C);=20=E4=BD=93=E9=AA=8C=E9=AA=8C=E8=AF=81=E6=B8=85?= =?UTF-8?q?=E5=8D=9552=E8=8A=82=E4=B8=A4=E7=9B=AE=E6=A3=80=E9=A1=B9+?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E6=8A=A5=E5=91=8A=E5=B9=B6=E5=85=A5=E5=AE=A1?= =?UTF-8?q?=E8=AE=A1=E7=BB=93=E8=AE=BA(=E9=80=9A=E8=BF=87=C2=B7D1/D2/D3?= =?UTF-8?q?=E5=8E=BB=E5=90=91=E5=9C=A8=E6=A1=88);=20=E5=90=B8=E6=94=B6?= =?UTF-8?q?=E5=8D=B3=E6=AD=BB=E9=80=80=E5=BD=B9=E4=BA=94=E4=BB=B6(?= =?UTF-8?q?=E5=8F=8D=E5=93=BA=E7=82=B9=E6=B8=85=E5=8D=95/=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=E6=8A=A5=E5=91=8A/=E9=AA=8C=E6=94=B6=E5=AE=A1?= =?UTF-8?q?=E8=AE=A1/=E4=B8=A4=E9=9C=80=E6=B1=82=E5=8D=A1=E7=89=87,?= =?UTF-8?q?=E9=80=80=E5=BD=B9=E5=AF=B9=E8=B4=A6=E6=89=BF=E6=8E=A5=E9=9D=A2?= =?UTF-8?q?=E6=A0=B8=E8=BF=87);=20roadmap=E8=BF=AD=E4=BB=A353=E8=A1=8C?= =?UTF-8?q?=E5=B7=B2=E5=AE=8C=E6=88=90+=E5=BD=93=E5=89=8D=E4=BD=8D?= =?UTF-8?q?=E6=8D=A2=E4=BB=A3(=E8=BF=AD=E4=BB=A31=E2=80=9353);=20CI?= =?UTF-8?q?=E8=BF=BD=E7=BA=A2=E4=BF=AE=E5=A4=8D:=20forge=5Ftable=5Ftest?= =?UTF-8?q?=E6=95=88=E6=9E=9C=E7=B1=BB=E5=9E=8B=E9=97=AD=E9=9B=8632?= =?UTF-8?q?=E2=86=9231(=E5=8D=A1=E2=91=A1=E6=91=98spike=E6=96=AD=E8=A8=80?= =?UTF-8?q?=E9=9A=8F=E5=8A=A8)+level=5Fmap=5Finfo=5Ffog=5Ftest=E5=B8=83?= =?UTF-8?q?=E5=B1=80=E7=BC=93=E5=AD=98=E6=8D=A2=E4=BB=A3=E6=96=AD=E8=A8=80?= =?UTF-8?q?=E7=AC=AC=E4=B8=89=E5=88=A4=E6=8D=AE=E7=AD=89=E5=BC=BA=E6=8D=A2?= =?UTF-8?q?=E9=94=AE(=E4=BD=8D=E7=BD=AE=E5=B7=AE=E5=89=8D=E6=8F=90?= =?UTF-8?q?=E9=9A=8F=E7=94=BB=E5=B8=83=E5=90=8C=E5=B8=A7=E6=94=B6=E6=95=9B?= =?UTF-8?q?=E5=A4=B1=E4=B9=89=E2=80=94=E2=80=94=E7=BC=93=E5=AD=98=E5=A4=B1?= =?UTF-8?q?=E6=95=88=E9=87=8D=E7=AE=97=E6=9C=AC=E8=BA=AB=E6=AD=A3=E5=B8=B8?= =?UTF-8?q?,=E6=8D=A2=E9=94=AE=3D=E9=87=8D=E7=AE=97=E5=AD=97=E5=85=B8?= =?UTF-8?q?=E9=94=AE=E6=95=B0=E6=81=B0=E4=B8=BA=E6=96=B0=E5=9B=BE=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E6=95=B0,=E5=90=8C=E4=B8=80=E6=80=A7=E5=88=A4?= =?UTF-8?q?=E6=8D=AE=E4=B8=8D=E5=8A=A8)+capability=5Faudit=E7=9C=9F?= =?UTF-8?q?=E5=AE=9E=E5=85=A5=E5=8F=A3=E9=94=9A=E9=9D=A2=E8=A1=A5probe=5Ff?= =?UTF-8?q?uncs(=E6=8E=A2=E9=92=88=E5=85=B1=E7=94=A8=E9=9D=A2func=E5=AE=9A?= =?UTF-8?q?=E4=B9=89,=E4=B8=8E=E4=BB=A3=E8=A1=A8=E7=94=A8=E4=BE=8BD?= =?UTF-8?q?=E8=A7=84=E5=88=99=E5=90=8C=E5=8F=A3=E5=BE=84=E4=B8=8D=E5=B1=9E?= =?UTF-8?q?=E6=94=BE=E5=AE=BD)+level=5Fmap=5Fshot=5Fprobe.gd.uid=E8=BE=B9?= =?UTF-8?q?=E8=BD=A6=E8=A1=A5=E5=85=A5=E5=BA=93+=E5=BE=85=E5=8A=9E?= =?UTF-8?q?=E6=B8=85=E5=8D=95QA=E6=9D=A1=E7=9B=AE=E8=A1=A5=E4=BB=93?= =?UTF-8?q?=E5=BA=93=E5=86=85=E8=AF=81=E6=8D=AE=E5=8F=A5(=E4=BF=AE?= =?UTF-8?q?=E6=B5=81=E6=B0=B4=E7=BA=BF=E9=97=B8run86=E8=B5=B7=E7=BA=A2)?= =?UTF-8?q?=E3=80=82=E9=AA=8C=E8=AF=81:=20=E4=B8=A4=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E5=A5=97=E4=BB=B6=E7=AA=84=E6=B5=8B=E7=BB=BF(forge=2042=20chec?= =?UTF-8?q?ks/fog=2021=20checks=E5=85=A8=E7=BB=BF)+=E6=B5=81=E6=B0=B4?= =?UTF-8?q?=E7=BA=BF=E9=97=B8PASS+=E8=83=BD=E5=8A=9B=E5=AE=A1=E8=AE=A1?= =?UTF-8?q?=E7=BA=A2=E9=A1=B90+--docs=E5=85=A8=E7=BB=BF(=E5=90=88=E5=9B=9E?= =?UTF-8?q?=E5=89=8D=E5=A4=8D=E8=B7=91=E5=87=AD=E6=8D=AE=E8=A7=81=E6=9C=AC?= =?UTF-8?q?=E7=AC=94=E5=90=8E=E7=BB=AD=E5=9B=9E=E6=89=A7)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- design/engineering/test-conventions.md | 2 +- design/gdd/00-游戏概念.md | 6 - design/gdd/03-内容规模.md | 2 +- design/gdd/systems/战斗循环/地图战斗资源.md | 4 +- design/gdd/systems/战斗循环/战斗结算.md | 4 +- design/gdd/术语表.md | 4 +- game/probe/level_map_shot_probe.gd.uid | 1 + game/tests/README.md | 2 +- game/tests/golden/README.md | 2 +- .../unit/data_config/forge_table_test.gd | 5 +- .../presentation/level_map_info_fog_test.gd | 7 +- reports/iter53-反哺点-2026-11-05.md | 21 -- reports/iter53-实现报告-2026-11-05.md | 80 ------ reports/iter53-验收审计-2026-11-05.md | 122 -------- reports/需求卡片-卷轴视口批-2026-11-05.md | 140 --------- ...片-改写族孤儿机制与退役名清退批-2026-11-05.md | 267 ------------------ roadmap.md | 6 +- tools/capability_audit.py | 14 +- 体验验证清单.md | 11 + 待办清单.md | 38 ++- 20 files changed, 68 insertions(+), 670 deletions(-) create mode 100644 game/probe/level_map_shot_probe.gd.uid delete mode 100644 reports/iter53-反哺点-2026-11-05.md delete mode 100644 reports/iter53-实现报告-2026-11-05.md delete mode 100644 reports/iter53-验收审计-2026-11-05.md delete mode 100644 reports/需求卡片-卷轴视口批-2026-11-05.md delete mode 100644 reports/需求卡片-改写族孤儿机制与退役名清退批-2026-11-05.md diff --git a/design/engineering/test-conventions.md b/design/engineering/test-conventions.md index c9eee8a7..68407268 100644 --- a/design/engineering/test-conventions.md +++ b/design/engineering/test-conventions.md @@ -77,7 +77,7 @@ ### 8.2 四层与真实入口 -- **单元**:不依赖场景树和真实宿主的纯逻辑;测试从领域类的对外方法进出,断言钉对外可观测面(返回值/信号/查询接口/落盘内容)。内部字段直查=受控例外:仅当该行为没有公开可观测面可钉时允许,对照表该行注明理由;存量不回头清扫,被批次触碰时顺带换代。 +- **单元**:不依赖场景树和真实宿主的纯逻辑;测试从领域类的对外方法进出,断言钉对外可观测面(返回值/信号/查询接口/落盘内容)。内部字段直查=受控例外:仅当该行为没有公开可观测面可钉时允许,对照表该行注明理由;存量不回头清扫,被批次触碰时顺带换代。探针直读视口承载子件结构(画布取视口首子件、渐隐带两片与平移提示子件按名取)属此类——断言对象即承载结构本身,无公开可观测面可钉,理由随对照表行申报。 - **接口**:模块边界的公开契约——数据表加载、存档与断点、事件载荷、命令接口;测试从公开入口进出。接口级断言随单元套件落(`unit/contracts/`),不另设承载目录。 - **集成**:跨宿主的接线、持久、生命周期——例如 LevelRunner 把 level_counters 传给 BattleOrchestrator、两场战斗共享同一个桶、断点续玩;测试必须实例化真实宿主链,禁止用裸 EffectEngine 代替。 - **探针/golden**:玩家可达性与观感;真实实例化场景、驱动真实输入。 diff --git a/design/gdd/00-游戏概念.md b/design/gdd/00-游戏概念.md index f695d80b..9b89a970 100644 --- a/design/gdd/00-游戏概念.md +++ b/design/gdd/00-游戏概念.md @@ -47,12 +47,6 @@ | 专名 | 是什么 | 出处条目 | |---|---|---| -| 显影尘 | 信息类秘宝 | aux_items | -| 工兵令 | 加行动点的秘宝 | aux_items | -| 探宝罗盘 | 预读奖励身份的秘宝 | aux_items | -| 探巢摆钟 | 探知巢穴位置的秘宝 | aux_items | -| 地穴全图卷 | 全图级稀有秘宝 | aux_items | -| 爆破工兵包 | 行动点 + 探巢的稀有秘宝 | aux_items | | 地精 / 熊地精 / 食人魔酋长 | 首发三敌种(末者为 Boss) | enemy | | 第一层 · 地精洞窟 | 首关层名 | level_table | | 封印 | 正式动作名(全库统一,非比喻、非呈现层别名)——对未开格实施封印,印记=封印印记 | terminology | diff --git a/design/gdd/03-内容规模.md b/design/gdd/03-内容规模.md index 1318120a..800a778d 100644 --- a/design/gdd/03-内容规模.md +++ b/design/gdd/03-内容规模.md @@ -38,7 +38,7 @@ MVP 不加新敌种,也不做同深度多敌种混搭;敌种扩容走 `enemy 目录(重设计 v1)已定稿 **12 件**(普通 7 / 优秀 3 / 稀有 2——代号制,正式命名归用户;数值全 provisional 归调参批),现行事实源=[秘宝](systems/跨局循环/秘宝.md)「目录(重设计 v1)」节。数据行随实装批落表(同调件数据表 = `data/tables/treasure_items.tres`),MVP 不新增。 -旧目录(旧 aux_items 六行:显影尘/工兵令/探宝罗盘/探巢摆钟/地穴全图卷/爆破工兵包,及过渡形态诸件)已全数退役、只作素材库(design/content-archive/道具退役素材库.md);旧行删除归实装批。 +旧目录(旧 aux_items 六行:显影尘/工兵令/探宝罗盘/探巢摆钟/地穴全图卷/爆破工兵包,及过渡形态诸件)已全数退役、留底 design/content-archive/道具退役素材库.md(数据表旧行已删净——treasure_items.tres 旧六名扫描零命中)。 ## 增益与状态 diff --git a/design/gdd/systems/战斗循环/地图战斗资源.md b/design/gdd/systems/战斗循环/地图战斗资源.md index 8d383c0d..556376d7 100644 --- a/design/gdd/systems/战斗循环/地图战斗资源.md +++ b/design/gdd/systems/战斗循环/地图战斗资源.md @@ -1,7 +1,7 @@ # 地图战斗资源 > 一句话:格面资源的产出、极性字典与清图奖励封装 -> 状态:已定稿;现行为 v1.5 +> 状态:已定稿;现行为 v1.6 ## 设计目的 @@ -96,7 +96,7 @@ - **档由两个参数定义:概率位 + 保底上限**。「永不保底」不单立规则——T4 的保底上限 = 0 即其统一表达;T1/T2 上限同为 0。 - **保底数量挂在型上、不挂在档上**:每个型各自登记「每板至少出几个」。档内登记保底的型数 ≤ 档上限 → 全部兑现;> 上限 → 每板从登记型中随机选定「上限」个兑现,其余型该板按普通概率出现、不保底。 -- **补签纪律**:执行序 = 装板摇号(含偏运硬币投影)→ 按上限定本期保底型集合 → 校验补签 → 板上全程只读。补签只改类型身份:危险格与安全格不动(补签格可为雷可为安全格,危险格与安全格同池不破)、不消费权重(补签不是一次取号)、清图判定不动、不泄露元信息(补签格与摇号格不可区分)。粒度 = 板,换板重新校验。 +- **补签纪律**:执行序 = 装板摇号(含订阅加权投影)→ 按上限定本期保底型集合 → 校验补签 → 板上全程只读。补签只改类型身份:危险格与安全格不动(补签格可为雷可为安全格,危险格与安全格同池不破)、不消费权重(补签不是一次取号)、清图判定不动、不泄露元信息(补签格与摇号格不可区分)。粒度 = 板,换板重新校验。 - **GP 数值锚**:以战斗结束 GP 奖励为锚——小 GP 袋 ≈ 其 1/10、大宝箱 ≈ 其 1 倍(具体数值归调参批)。 - 大宝箱为枚举新增(九型→十型走本文修订流程,不随手加行);微光归通用增益组(五色相不变,组内不细分正好容下)。 - **对外稀有度映射**(现行事实源=[核心循环](../../01-核心循环.md)「档位与获取规则」节):T1=普通 / T2=优秀 / T3=稀有 / T4=传说;任何概率提升禁止改变本档保底承诺(保底=承诺非概率)。 diff --git a/design/gdd/systems/战斗循环/战斗结算.md b/design/gdd/systems/战斗循环/战斗结算.md index 297f167a..3e0e9d6f 100644 --- a/design/gdd/systems/战斗循环/战斗结算.md +++ b/design/gdd/systems/战斗循环/战斗结算.md @@ -1,7 +1,7 @@ # 战斗结算 > 一句话:轮末结算的编排与逐行兑现 -> 状态:已定稿;现行为 v1.7 +> 状态:已定稿;现行为 v1.8 ## 设计目的 @@ -84,7 +84,7 @@ | 判定行 | 胜 / 负 / 继续各一行;终局判定行同时是胜负画面的数据锚 | | 高光行 | 完美封印成立时一行,只记实际有效兑付 | -每行还携带公共字段:来源类别、来源格、轮次、显示名、数值,以及可空的高光标记(用于强调封印标中、清图奖励这类值得高亮的结果)。奖励直伤行的数值字段沿用 `effectiveness` 键名、值为整数点数——键名与量纲是数据导出与分析工具的兼容契约,改动须连动分析工具面。没生效也要留痕:两类"未生效"行如实记录合法例外,呈现时聚合计数,不逐行刷屏。 +每行还携带公共字段:来源类别、来源格、轮次、显示名、数值,以及可空的高光标记(用于强调封印标中、清图奖励这类值得高亮的结果)。**显示名等玩家可见文案是数据面字段:文案值登记在数据表行,代码按来源类别与效果身份读表拼行,不在代码里写死文案字串**(2026-11-06 用户裁——文案归属数据表承载;承载表与字段形态归表结构设计段定,设计闭合后由实装批落表)。奖励直伤行的数值字段沿用 `effectiveness` 键名、值为整数点数——键名与量纲是数据导出与分析工具的兼容契约,改动须连动分析工具面。没生效也要留痕:两类"未生效"行如实记录合法例外,呈现时聚合计数,不逐行刷屏。 任何一行找不到来源即断言失败——宁可返回错误,也不让"合并到看不出来源"的呈现混过数据层。但有些行天然没有棋盘来源,断言为此留了两层豁免,豁免集合是封闭清单,改动同样走本文修订。 diff --git a/design/gdd/术语表.md b/design/gdd/术语表.md index fb63daa8..ffd8907d 100644 --- a/design/gdd/术语表.md +++ b/design/gdd/术语表.md @@ -1,7 +1,7 @@ # 术语表 > 全库专用术语的唯一对照表(2026-10-11 用户令建立)。规矩:新术语先登记本表、再在文档使用;退役词见文末对照表,文档正文一律使用现行词。文档中遇到看不懂的词,查本表。用词纪律(禁用词、替换值、豁免范围)见「用语规范」节。 -> 状态:**现行 v1.26**——2026-10-11 建立;历次升版明细见 git 提交史。 +> 状态:**现行 v1.27**——2026-10-11 建立;历次升版明细见 git 提交史。 ## 格与棋盘 @@ -95,7 +95,7 @@ | 术语 | 定义 | |---|---| | 效果端口件 | 战斗业务类(伤害管线/行动经济)唯一的效果发射出口:收事件与载荷、交效果引擎结算、取回命中批——业务类零引擎直连(机制归属见架构文档「战斗编排域拆件定稿」节轴戊;实现类 EffectPort) | -| 掷格件 | 装配期格面资源摇号的承载件:池行装配、区间行 roll、权重合成(偏运硬币/board_skew 两路投影);受理账面留守地图战斗资源件(机制归属同上;实现类 RewardRoller) | +| 掷格件 | 装配期格面资源摇号的承载件:池行装配、区间行 roll、权重合成(订阅加权/board_skew 两路投影);受理账面留守地图战斗资源件(机制归属同上;实现类 RewardRoller) | | `seal_missed` | 封印落空事件(旧名已换代):封印动作落在安全格上时发出,订阅面据此做限次与豁免判定 | | `forgive_seal_miss` | 本场首次封印落空豁免——专长「完美保险」的效果类型,`domain=battle` 首例;有效误标=误标总数 − 豁免数,豁免不改写误标账 | diff --git a/game/probe/level_map_shot_probe.gd.uid b/game/probe/level_map_shot_probe.gd.uid new file mode 100644 index 00000000..8e1aa67e --- /dev/null +++ b/game/probe/level_map_shot_probe.gd.uid @@ -0,0 +1 @@ +uid://j4ax48si4nq5 diff --git a/game/tests/README.md b/game/tests/README.md index 5c681ddb..62f9242a 100644 --- a/game/tests/README.md +++ b/game/tests/README.md @@ -160,7 +160,7 @@ tests/ | 四柜台拆解后五界面入口改挂与写口零回归 | 营地五界面 | 五界面意图信号 → `CampShopPresenter` → `MetaProgression.tree_buy()` 写口 | `forge_workbench_test.gd:_run`(承载类同迁断言十二项);`ui_click_probe.gd:_ready`(写口链段) | | 营地篝火回主菜单与笔记本改挂动线 | 营地交互流 | 笔记本命中区 → `CareerOverlay.open()`;篝火命中区 → ConfirmDialog 二次确认 → 主菜单 | `ui_struct_probe.gd:_ready`(career 段);`screen_flow_probe.gd:_ready`(篝火/开合段) | | 关卡画面视口跟随 | 关卡画面(选路枢纽) | 停点切换与兑付回图经真实屏流程;读面 `LevelMapViewport.viewport_center_canvas_pos()` | `level_map_viewport_probe.gd:_probe_follow_anchor`;`level_map_viewport_probe.gd:_probe_smooth_scroll_reduced_motion` | -| 关卡画面视口平移 | 关卡画面(选路枢纽) | 合成拖拽沿与滚轮沿经 `push_input`(`ProbeUiUtil.push_drag_at()`/`push_wheel_at()`) | `level_map_viewport_probe.gd:_probe_drag_pan`;`level_map_viewport_probe.gd:_probe_wheel_pan`;`level_map_viewport_probe.gd:_probe_clamp_bounds`;`level_map_viewport_probe.gd:_probe_drag_no_submit` | +| 关卡画面视口平移 | 关卡画面(选路枢纽) | 合成拖拽沿与滚轮沿经 `push_input`(`ProbeUiUtil.push_drag_at()`/`push_wheel_at()`) | `level_map_viewport_probe.gd:_probe_drag_pan`;`level_map_viewport_probe.gd:_probe_wheel_pan`;`level_map_viewport_probe.gd:_probe_clamp_bounds_and_columns`;`level_map_viewport_probe.gd:_probe_drag_no_submit` | | 关卡画面视口指引 | 关卡画面(选路枢纽) | 深图经 `LevelMapScreen.open_choices()` 真实停点 | `level_map_viewport_probe.gd:_probe_guidance_chrome` | | 营地图鉴占位挂起态与反参照结构纪律 | 营地场景视图 | 布告板命中区 → `CampSceneView._gui_input()`(object_pressed 信号) → 图鉴占位视图;营地根态场景树审计 | `ui_struct_probe.gd:_ready`(占位禁词/禁行段);`ui_struct_probe.gd:_ready`(结构禁词段) | | 营地刷新单口与场景根 HUD 同步 | 营地刷新总线 | 写口尾 → `CampRefreshBus.refresh()` → 现开界面刷新+场景根 HUD 刷新 | `ui_struct_probe.gd:_ready`(顶栏位段);`ui_click_probe.gd:_ready`(写口尾刷新段) | diff --git a/game/tests/golden/README.md b/game/tests/golden/README.md index 9936ab1d..8a4a183f 100644 --- a/game/tests/golden/README.md +++ b/game/tests/golden/README.md @@ -18,7 +18,7 @@ ## 时效判定纪律 -基线冻结于 2026-09-30。**判定先于动作**:每代换代面(视觉/素材/布局改动) +基线冻结于 2026-09-30;关卡视口两 Shot(lmap_entry/lmap_boss)冻结于 2026-11-05——两 Shot 面口径(只对拍入口停点与 Boss 节点)见上文现持清单行。**判定先于动作**:每代换代面(视觉/素材/布局改动) 跑批时先跑一次渲染闸看差异落不落在裁剪区与容差内—— - **判有效**(changed 远低于 2% 阈值):基线**留在位**,不得顺手重制; diff --git a/game/tests/unit/data_config/forge_table_test.gd b/game/tests/unit/data_config/forge_table_test.gd index 7bca3562..e26e7c61 100644 --- a/game/tests/unit/data_config/forge_table_test.gd +++ b/game/tests/unit/data_config/forge_table_test.gd @@ -212,9 +212,10 @@ func _test_negative_cases() -> void: # ---- V11:效果类型闭集零新增(满级特效本期不开新词)---- # 实数订正(L2 在册):卡片 F11「24 种」系设计文档事实快照, # 现行 31;本套件零扩签,钉现行数(将来任何加词即转红提示复核)。 +# 32→31:改写族清退批摘 spike(CI run 87 追绿——词表合法收窄的断言随动)。 func _test_effect_kinds_closed() -> void: - Kit.check("效果引擎效果类型闭集 32 种(甲案词表退役——overflow/attack_segments 摘名)〔锻造工坊批 V11〕", - EffectEngineScript.EFFECT_KINDS.size() == 32) + Kit.check("效果引擎效果类型闭集 31 种(甲案词表退役 overflow/attack_segments+改写族清退摘 spike)〔锻造工坊批 V11〕", + EffectEngineScript.EFFECT_KINDS.size() == 31) Kit.check("效果引擎事件词表在册 21 种(charge_full 位摘名——蓄力层删键批)〔锻造工坊批 V11〕", EffectEngineScript.EVENTS.size() == 21) diff --git a/game/tests/unit/presentation/level_map_info_fog_test.gd b/game/tests/unit/presentation/level_map_info_fog_test.gd index f3b2d0fe..4c4163fa 100644 --- a/game/tests/unit/presentation/level_map_info_fog_test.gd +++ b/game/tests/unit/presentation/level_map_info_fog_test.gd @@ -221,7 +221,10 @@ func _test_layout_cache(db) -> void: await process_frame # 换代图真实绘制路径重算(缓存随内容变失效重写) var pc1: Dictionary = screen.layout_probe(chain) var pc2: Dictionary = screen.layout_probe(chain) + # 第三判据原=新旧图 id0 位置差——改前靠容器延迟收敛的 origin 中间态偶然成立(换图首探针 + # 画布未及重排,origin≠0);视口化批画布同帧收敛(canvas.size 恒=内容包络)后两图 origin + # 恒等、id0 同层同槽位置恒等,前提失义。等强换键=重算字典键数恰为新图节点数(旧缓存 + # 63 键,换代不重算必不成立),同一性判据(核心失效重算面)不动。 Kit.check("布局缓存换代:新图查询返回新实例非旧缓存(失效重算生效)〔levelmap批 V2〕", - not is_same(p1, pc1) and is_same(pc1, pc2) - and (pc1[chain[0]] as Vector2) != (p1[nodes[0]] as Vector2)) + not is_same(p1, pc1) and is_same(pc1, pc2) and pc1.size() == chain.size()) screen.queue_free() diff --git a/reports/iter53-反哺点-2026-11-05.md b/reports/iter53-反哺点-2026-11-05.md deleted file mode 100644 index b1c9eeef..00000000 --- a/reports/iter53-反哺点-2026-11-05.md +++ /dev/null @@ -1,21 +0,0 @@ -# 迭代 53 反哺点清单(2026-11-05) - -- 接收方:[待办清单](../待办清单.md)(反哺点裁决后由文档批/工程批写入并把本清单条目清掉)。 -- 依据:`reports/iter53-实现报告-2026-11-05.md`;两卡「关联文档同步面」逐条落点如下。 - -| # | 落点(哪个文件哪一节) | 改成什么 | 依据 | -|---|---|---|---| -| 1 | `design/gdd/systems/跨局循环/锻造工坊.md` §满级特效扩展位——重甲反震候选条 | 实现前提句补一句:反弹伤害需新开消费点(本批摘 `spike` 词表位后彻底无位,候选=「需新代码」档) | 卡② §6 第 2 行;damage_controller.gd 摘除后 `open_ticket` reflect 通道为唯一反弹面且零现役表行 | -| 2 | `design/gdd/systems/战斗循环/增益状态.md`/`伤害与护甲.md` | 零命中备案——两文档叙述「按序改写族」的句子未挂退役件名,无需改动 | 卡② §6 机械面核对读数(40 名扫描两文件零命中) | -| 3 | `design/gdd/systems/冒险循环/奇物.md`、`systems/战斗循环/地图战斗资源.md`、`design/gdd/术语表.md`、`00-游戏概念.md`、`03-内容规模.md` | 各文仍提退役内容名的句子逐处换机制名(清退口径同卡② T3:只换名不换职责) | 卡② §5 去向表;40 名扫描命中所在(GDD 面不在本批可写域) | -| 4 | 结算明细标签是否入表(文案硬编码 `reward_grant.gd:226`) | 规范裁决点:玩家可见明细文案归属——维持代码硬编码 or 入数据表行;裁决后改对应规范文档 | 卡② §5 去向表末条;本批已把标签换代为「挖掘惩罚减半(%d→%d)」 | -| 5 | `tools/gate_platform.sh` `gate_run_timeout` | 修 Windows 恒 124 缺陷:`kf` 改「先赋路径、`rm -f` 后置守卫」(probe_gate.sh run_suite 同款正确写法);连带修 `golden_baseline_refresh.sh` 的 guard 子Shell kill 短路(7 分钟等待症状) | iter53 实现报告「遗留读数义务与发现呈报」第 1 条;实证=直接调用 4 秒返回 124、refresh 两次 7m1s | -| 6 | `game/tests/golden/mac/` | mac 侧补冻关卡视口两 Shot 基线(跑 `golden_baseline_refresh.sh --lmap`) | 渲染闸 lmap 段缺基线记 SKIP;windows 已冻结(6394abf7),mac 冻结后两平台同盯 | -| 7 | `game/tests/golden/README.md` §时效判定纪律 | 「基线冻结于 2026-09-30」句补 lmap 两 Shot 冻结日(2026-11-05)与两 Shot 面口径指针 | 本批 golden/README 台账已改现持清单,冻结纪律节的时间句留待文档批随批换代 | -| 8 | `game/tests/README.md` 能力行 :163(关卡画面视口平移) | 代表用例名 `_probe_clamp_bounds` 回表为落地名 `_probe_clamp_bounds_and_columns`(实现按卡 §8 对照表外的更 descriptive 名落地,回表归写卡段) | 验收审计 D1(建议级):名实回表义务 | -| 9 | 探针直读申报口径(test-conventions §8.2/§8.4 受控例外注记) | 「探针直读视口子件结构(`get_child(0)` 画布位、按名取指引子件 FadeL/FadeR/PanHint)」补进探针直读惯例的申报面注记 | 验收审计 D2(观察级):直读有注释理由、零风险,补成文口径 | -| 10 | `reports/iter53-实现报告-2026-11-05.md` 决定 3 | 已随本清单同批订正(case⑰→⑱ 笔误)——归档备查,无文档批动作 | 验收审计 D3 | - -## 零反哺备案 - -- 卡① `design/gdd/ux/level-map.md`:实现未发现 spec 缺口——布局决策 5 行为四条+像素级判据①–④+AC 260–271 全部有绿读数承载(实现报告对照表 R1–R9+golden 段)。 diff --git a/reports/iter53-实现报告-2026-11-05.md b/reports/iter53-实现报告-2026-11-05.md deleted file mode 100644 index b86116fe..00000000 --- a/reports/iter53-实现报告-2026-11-05.md +++ /dev/null @@ -1,80 +0,0 @@ -# 迭代 53 实现报告(2026-11-05) - -- 接收方:[待办清单](../待办清单.md)条目「超预算图策略升级路径——等比缩放与滚动视口两案待裁」(卡①卷轴视口批)+「damage_controller 按序改写族——内容孤儿机制与退役名注释层」(卡②改写族清退批)。 -- 需求卡片:`reports/需求卡片-卷轴视口批-2026-11-05.md`(验收档:中)+`reports/需求卡片-改写族孤儿机制与退役名清退批-2026-11-05.md`(验收档:中)。 -- 独立验收审计:`reports/iter53-验收审计-2026-11-05.md`(未参与实现的会话执行;两卡均按中档深度)。 -- 执行形态:整迭代单工作区(`g-plan2-iter53`,两卡均未声明可并行),卡序=卷轴视口 → 改写族清退。 - -## 各卡状态 - -| 卡 | 状态 | T 卡 | 凭据摘要 | -|---|---|---|---| -| 卡①卷轴视口批 | 完成(T0–T4 全收口+golden 扩项冻结) | T0 基线读数在案/T1–T3 实现波提交 c1043902/T4 指针反转 4e87a012/golden 扩项 6394abf7 | 新探针 26 断言全绿+探针族全绿+冒烟 15/0+S13 基线内 7 新增 0+渲染闸全绿(lmap 双图 changed=0.00%) | -| 卡②改写族清退批 | 完成(T0–T5 全收口) | T0 基线读数在案/T1 b5c21e3a/T2 1bd50304/T3+T4 并笔 ed793e8c | 三套件+四套窄测 exit=0+对拍六组逐字节 diff=0+四探针负域全拒+契约 1 三条 grep 全零+40 名注释面清零 | - -## 卡① 实际改动—验收对照表 - -| 需求点 | 改动(文件:行) | 验收测试(落点+尾缀) | 层级 | 真实入口 | 判据绑定面 | 结果 | -|---|---|---|---|---|---|---| -| R1 浅图整幅居中无裁切 | level_map_screen.gd 三段页承载+level_map_viewport.gd `_axis_center_offset` 居中分支 | `level_map_viewport_probe.gd:71/74/76`〔卷轴批 V1〕 | 探针 | `open_choices` 真实停点(L1 固定种子直构 runner) | 画布≤窗居中 offset 定位+画布矩形 encloses 于视口 | 绿 | -| R2 停点切换当前节点居中 x=640±2 | level_map_viewport.gd `reanchor`+screen `_viewport_anchor`/open_choices 接线 | `level_map_viewport_probe.gd:221`〔卷轴批 V2〕 | 探针 | 断点停点重建+真实 `open_choices` | 当前节点画布投影=视口中线±2 | 绿 | -| R3 拖拽平移 | screen `_on_canvas_motion` 拖拽态逐帧 `pan_by`(含激活帧位移) | `level_map_viewport_probe.gd:137`〔卷轴批 V3〕 | 探针 | `push_drag_at` 合成沿走 `push_input` | 视线位移=拖拽位移(40px 逐位) | 绿 | -| R4 滚轮横滚 | screen `_wheel_pan_step` 映射(下/右=前进向) | `level_map_viewport_probe.gd:114/116/120`〔卷轴批 V4〕 | 探针 | `push_wheel_at` 合成滚轮沿 | 单档 ±60 逐位+窗内不钉边界 | 绿 | -| R5 clamp 包络与首末列可达 | level_map_viewport.gd `_axis_pan_offset`/`is_clamped_at_edge` | `level_map_viewport_probe.gd:88/102/158/160/161/167/168`〔卷轴批 V5〕 | 探针 | 超包络拖拽沿两极 | 中线恒在夹紧域+两极 edge=true+首末列中心入屏+入口组包围盒锚点 | 绿 | -| R6 拖拽不触发选路 | screen `_on_canvas_click` 拖拽抬杆不提交 | `level_map_viewport_probe.gd:200/201/206`〔卷轴批 V6〕 | 探针 | 拖拽沿/完整点击沿起止候选上方 | `route_chosen` 零发射+屏未关;完整点击仍提交=1 | 绿 | -| R7 平滑滚动与减动效瞬切 | level_map_viewport.gd `reanchor(smooth)` tween `UiKit.motion(0.3)`+`ArmedTimer.motion_still` 跳终态 | `level_map_viewport_probe.gd:245/249/258`〔卷轴批 V7〕 | 探针 | 可见屏停点切换+`UiKit.motion_scale` 置位 | 平滑有 tween 中间帧(同向在途)+减动效即达 | 绿 | -| R8 指引件可见性与几何 | level_map_viewport.gd `_build_guidance`/`_sync_guidance` | `level_map_viewport_probe.gd:271–287`〔卷轴批 V8〕 | 探针 | 深图真实停点+浅图复验 | 渐隐带 70px+chip 240×30 居中可见;浅图隐藏 | 绿 | -| R9 schema 头注指针反转(非行为) | level_gen_params.gd:3-4/:66 头注 | 静态判据:grep「调参表」残留=0、「参数契约节」指向=2;`--check-only` 零错 | 静态 | — | 全仓无「域并单点=调参表」残留 | 绿 | -| golden 两 Shot 面(2026-11-05 用户裁) | level_map_shot_probe.gd+golden/windows/lmap_entry·lmap_boss+render_gate.sh 对拍段 | 渲染闸「关卡视口 golden 逐像素」段(changed=0.00% 双绿);重采集确定性=0.00% | golden | 窗口化真实渲染+固定种子 | 两 Shot 逐像素 ≤16 差/≤2% | 绿 | - -非行为改动行:无(R9 之外全部行为面;`.uid` 边车随新件入库)。 - -## 卡② 实际改动—验收对照表 - -| # | 需求点 | 改动(文件:行) | 验收测试(落点+尾缀) | 层级 | 真实入口 | 判据绑定面 | 结果 | -|---|---|---|---|---|---|---|---| -| R1 | 摘四段不可达改写分支 | damage_controller.gd(原 :297-302/:305-309/:310-314/:316-323/:350-353/:367-372/:623 全摘+spike_ready 键摘) | `damage_controller_test.gd`(exit=0);`roll_multiplier_test.gd`(exit=0);`round_flow_skill_pool_test.gd`(exit=0);dump_battle 六组改前改后逐字节比对 diff=0 | 单元+集成 | `BattleOrchestrator.begin_battle()` 全链 | step_row 流逐位=改前基线(L{1,2}×S{42,779401,779501});静态=契约 1 三条 grep 全零+摘后 `spike_ready` 零残留。观测面局限申报:零现役注册行使分支不可达,禁注入表行取证(卡 §8 申报在案) | 绿 | -| R2 | EFFECT_KINDS 摘 spike | effect_engine.gd:30 | `effect_kind_retired_test.gd:89`「effect_kind_retired_test/③词表闭面:kind=spike 出域拒绝」 | 单元(负面,独立进程) | `ConfigDB.load_tables()` → `validate_trigger_row` | do.kind=spike 行被拒+error 诊断在案+退出码 1(负面期望码) | 绿 | -| R3 | DO_KEYS 摘 trade_hit/trade_atk | effect_engine.gd:82 | `effect_kind_retired_test.gd:92`「effect_kind_retired_test/④do 键闭面:trade_hit 出域拒绝」 | 单元(负面,独立进程) | 同上 | 带 trade_hit 键 do 字典被拒+退出码 1 | 绿 | -| R4 | 注释面退役名清零(13 文件) | T3 35 处注释改写(对照卡 3.3 表逐处) | 静态判据:40 名全扫仅剩卡 §5 留底 3 行(treasure_items_test:31/33/35 StubDB 夹具名);宿主套件逐位不变(四套窄测 exit=0) | 静态(闸件扫描) | 宿主套件回归(改写面不进运行期) | 注释面命中 0+套件绿 | 绿 | -| R5 | 减半明细行去退役件名 | reward_grant.gd:226(标签→「挖掘惩罚减半(%d→%d)」+effect_id→nest_halve) | `meta_progression_forge_test.gd:694/697/699/700`(断言串随动,非空+等值+不含旧词强度不降) | 集成(信号采集) | 锻造锋线满级特效 → begin_battle → mine_hit 减半路径 → step_row | display_name==「挖掘惩罚减半(6→3)」+power 减半数值与发射次数逐字不变+grep nest_counter=0 | 绿 | -| R6 | 空集拒绝 reason 去退役件名 | reward_grant.gd:189(→「中立移除:…」) | 静态判据:grep 爆破工兵包 reward_grant.gd=0;`table_structure_guard_test.gd` exit=0 | 静态+单元 | 通道校验面(零现役行不可达) | grep 零命中+通道校验绿。观测面局限申报:reason 不可达,禁造行取证 | 绿 | -| R7 | 反弹明细标签去退役件名 | grant_segment.gd:166(标签→「反弹伤害」+归因串→attune_nest_halve;channel=="reflect" 判据与开单参数字典逐字不动) | 静态判据:grep 惊巢反制 game/=0、attune_nest_counter=0;`round_flow_skill_pool_test.gd` exit=0 | 静态+集成 | mine_hit 订阅施加链(reflect 行族零表行,今天不可达) | grep 零命中+发射面零变化回归。观测面局限申报:禁造行取证 | 绿 | -| R8 | sim 恒 false 匹配删除 | level_autoplay.gd(原 :415 注释+:421 contains(雷区图谱) 条件删,highlight==seal_hit 单判据保留) | 静态判据:grep 雷区图谱 game/=0;sim 驱动链套件绿(四套窄测含 autoplay 消费面 exit=0) | 静态+单元 | autoplay 驱动链(测量面) | grep 零命中+套件绿。观测面局限申报:恒 false 条件不可达 | 绿 | - -非行为改动行:T3 注释面 35 处(由 R4 行覆盖);契约 3 约束下 :226/:166 仅标签与归因串文本变动、取值/位序/载荷键逐字未动(R1 对拍 diff=0 为其逐位证据)。 - -## 读数义务对账(卡内 T 卡产出) - -- **卡①T0**:S13 基线无 `level_map_screen` 键(记「无键、按工具默认」);ui_struct_probe PASS 全屏结构断言零红;screen_flow_probe PASS;冒烟 15 项 0 失败。 -- **卡①T4 复跑**:S13 基线内 7 条、新增 0(`_on_canvas_input` 重构触发的 max-branches 新违规已拆 `_on_canvas_motion`/`_on_canvas_click`/`_wheel_pan_step` 归零);ui_struct_probe/screen_flow_probe 复跑绿(探针族全绿内含)。 -- **卡②T0**:契约 1 三条 grep——`game/data/tables/` 内 spike/armor_rewrite/discount_shift/trade_hit/trade_atk 全零(对照记录=feats.tres:855 clamp_bonus 现役一行);tree_rules 面零;effect_kinds 面 cell_removal 表面零(仅 schema 在册:treasure_item_table.gd:20/:26,本批不摘通道)。S13 四文件无登记键(damage_controller/effect_engine/reward_grant/level_autoplay 均按工具默认)。改前对拍基线六组落盘(L{1,2}×S{42,779401,779501})。改前断言串=「惊巢反制——危险格挖掘惩罚减半(6→3)」(:693/:698-701 现行文本抄录在案)。 -- **卡②T5**:改后对拍六组 diff=0;40 名全扫终读数=3 行留底夹具;R5–R8 静态 grep 全零;负域套件 exit=1(期望码)四探针全拒。 -- **存量触面 S13 对照**:damage_controller(分支数/函数长度随摘除下降,无新增键);effect_engine(常量字面量变短,方法数/成员数不变);reward_grant/level_autoplay(删文本与恒 false 条件)——S13 终读数=基线内 7、新增 0、恶化 0。 - -## 实机目检总清单(登记不阻塞) - -| 目检项 | 来源卡 | 承载 | -|---|---|---| -| 深度 13+ 图拖拽可达首末列、推进跟随方向感、chip 不碍选路 | 卡① | 窗口化实跑截图已冻结(golden/windows/lmap_entry·lmap_boss);真人试玩复核登记体验验证清单(归批后收尾) | -| 结算明细行减半标签「挖掘惩罚减半(6→3)」一眼可读、无退役件名突兀感 | 卡② | 实现报告登记;真人目检归体验验证清单(归批后收尾) | - -## 实现决定记录(超白名单/超卡片明列面逐条备案) - -1. **拖拽态成员落屏侧**(卡①§11 把 `_drag_active`/`_drag_accum` 枚举进视口件成员,§6 职责边界却写明视口件「只管裁切/offset/clamp/跟随」、拖拽判定留画布)——取 §6 职责边界优先:拖拽判定状态随输入处理落 screen(`_drag_active`/`_drag_press_pos`),视口件成员 6 个(≤8 达标)、公开方法 5 个(≤20 达标)。撤销方式=成员迁视口件+canvas 经方法驱动(纯结构搬移)。 -2. **open_choices 平滑判据=有无当前节点**(卡①§6 写「reanchor(false) 首锚」、T2 写「停点切换/回图接 reanchor(true)」,open_choices 同时承载两路径)——合并读法:入口停点(current_node_id<0)即达=首锚,其余停点/兑付回图平滑=跟随。R2/R7 断言均经此路径。 -3. **提交沿移至抬杆**(原提交在按下沿;布局决策 5 阈值区分语义下按下时无法预知是否成拖拽,R6 要求拖拽沿零发射)——完整点击(按下→未超阈值抬杆)提交、拖拽抬杆不提交;ui_input_probe case⑫/⑱ 补 release 沿适配(验收审计 D3 订正:原呈报误写⑰,实际落点两处)(判据语义「图上真实点击提交选路」不变,输入形态更完整)。 -4. **滚轮步进 60px、渐隐带色 BG_ROOT 不透明端 0.9、chip 底 HP_BAR_BACK/描边 STONE/文字 WARM、缓动 TRANS_CUBIC+EASE_OUT**——卡 §12 白名单 4/5/3 授权面内定值。 -5. **视口件 NOTIFICATION_RESIZED 即席重锚**——首开布局晚于 open_choices 锚定(隐藏子树容器排序首可见帧才传播,4.7 行为;实证=探针首跑 y 锚偏 88px),resize 即席 `reanchor(false)` 收敛;同时是窗口尺寸变化的正确行为。 -6. **_fit_canvas 画布尺寸同帧收敛**(`canvas.size = _content_size` 显式置)——视口锚点数学与 `_layout` 同源读画布尺寸,容器延迟收敛不等锚点。 -7. **mouse_exited 清拖距跟踪器**——按下即武装的跟踪器在丢失 release 沿(alt-tab 等)后残留会把后续 motion 误判为拖拽激活(ui_input_probe case⑰⑧ press-only 实证);非拖拽态离画布即解除。 -8. **卡②探针①注入 do.kind="spike"**(卡 T2 括注 kind=modify_ticket+mode=spike 形态)——括注形态无拒绝通道(`validate_trigger_row` 无 mode 值域检查,mode 属载荷字段非词表),按断言名「词表闭面:kind=spike 出域拒绝」与 R2 判据绑定面(effect_kinds 出域文案)的机制注入 kind 形态。 -9. **golden 两 Shot 面口径**(卡①现状事实写「本批不触渲染闸对拍」、批纪律 iter 4.4+test-conventions §8.2 要求扩项)——呈裁用户,2026-11-05 裁「只处理最初始的和最终的:关卡最开始+关卡 Boss 节点,中间过程不对拍」,按两 Shot 面扩项冻结。 -10. **卡② T3 与 T4 并笔提交**——卡 §10 白名单授权面。 - -## 遗留读数义务与发现呈报 - -1. **闸件缺陷呈报(工程批)**:`tools/gate_platform.sh` 的 `gate_run_timeout` 用 `mktemp` 造超时标志文件——mktemp 即建文件,末尾 `[ -f "$kf" ]` 在 Windows(Git Bash)恒真→**恒返回 124**。被各闸「判定锚工件而非退出码」口径掩住(菜单/棋盘 golden 段与本批 lmap 段均工件锚定,不受影响);`tools/golden_baseline_refresh.sh` 的 7 分钟等待症状(guard 子Shell `sleep 420` 未被 kill 短路)同根。修法=改 `kf="$TMP/..." ; rm -f "$kf"`(run_suite 同款,probe_gate.sh 已是正确写法)。本批不代修(闸件改动归工程批)。 -2. **mac 端关卡视口基线冻结义务**:`golden/mac/` 缺 lmap_entry/lmap_boss——渲染闸缺基线记 SKIP 不判红(windows 已锚即盯),mac 冻结归 mac 侧跑 `golden_baseline_refresh.sh --lmap`。 -3. **效果通道与事件词的零现役普查**——已在待办清单在册(卡② §5 去向),本批不扩。 -4. 卡① level-map.md 同步面:实现未发现 spec 缺口(布局决策 5 行为四条+像素级判据+AC 全部有绿读数承载),零反哺。 diff --git a/reports/iter53-验收审计-2026-11-05.md b/reports/iter53-验收审计-2026-11-05.md deleted file mode 100644 index 022f7813..00000000 --- a/reports/iter53-验收审计-2026-11-05.md +++ /dev/null @@ -1,122 +0,0 @@ -# 迭代 53 验收审计(2026-11-05) - -- 审计员:独立会话子代理——未参与本迭代任何实现、设计或写卡工作,只读证据做审计。 -- 审计对象:迭代 53 两张需求卡片——卡①卷轴视口批(`reports/需求卡片-卷轴视口批-2026-11-05.md`)+卡②改写族孤儿机制与退役名清退批(`reports/需求卡片-改写族孤儿机制与退役名清退批-2026-11-05.md`)+卡① golden 扩项(2026-11-05 用户裁两 Shot 面)。 -- 实现报告:`reports/iter53-实现报告-2026-11-05.md`(两卡「实际改动—验收对照表」为逐行核对基准)。 -- 验收档与实际执行深度:两卡均申报「中」档;本次按 test-conventions §8.7 中档执行——对照表逐行全量核对(两卡 R 行逐行)、判据绑定面抽查(超出下限)、测试削弱检查逐处、直查例外核对逐条、判据出处抽查 6 处。**最窄测试复跑=省略,该格写「合回后 CI 现查补记」**(合并尚未发生——本审计为合并前置闸,远端 CI 现查读数待合回落地后按 `tools/ci_check.sh <合并提交>` 补记;静态 grep/文件核对类检查由审计员当场重跑,不属省略面)。 -- 基线提交:`709d9a85..8b4399ad`(iter53 分支;7 笔实现笔 c1043902/4e87a012/b5c21e3a/1bd50304/ed793e8c/6394abf7/78e08234 + 1 笔并 master 8b4399ad)。工作树存在本机 Godot 导入元数据漂移(若干 `*.png.import` 未提交改动),不属提交面审计对象。 -- 审计动作面:`git diff 709d9a85..HEAD` 全量过目(37 文件);测试/探针/闸件改动逐 hunk 核对;契约 1 五词 grep、40 名退役名全扫、契约 5 残留 grep 由审计员当场重跑。 - -## 卡① 卷轴视口批(验收档:中|执行深度:中档) - -### 对照表逐行核对(全量) - -| 行 | 结论 | 依据(文件:行) | -|---|---|---| -| R1 浅图整幅居中无裁切 | 通过 | 断言在案且尾缀可 grep:`game/probe/level_map_viewport_probe.gd:71/74/76`〔卷轴批 V1〕;承载改造落地 `level_map_viewport.gd:30-36`(setup/clip_contents)+`level_map_screen.gd:134-145`(CenterContainer→视口件);真实入口=`open_choices` 真实停点(探针 :62-64,L1 固定种子直构 runner,start_level_external 注入)。运行读数=实现者「绿」在案;合回后 CI 现查补记 | -| R2 停点切换当前节点居中 x=640±2 | 通过 | 断言 `level_map_viewport_probe.gd:221`〔卷轴批 V2〕;断言钉屏空间投影(当前节点屏幕 x 对视口中心 ±2)——比卡面所写 `viewport_center_canvas_pos()` 调用更外层的真实观测,与 level-map.md:101/:154 判据①「居屏中线 x=640±2」同义,非削弱(观察 4);真实入口=断点停点重建+真实 `open_choices`(探针 :216-217)→ screen `reanchor` 接线 `level_map_screen.gd:312-315`+锚点提供方 :483-516。合回后 CI 现查补记 | -| R3 拖拽平移 | 通过 | 断言 `level_map_viewport_probe.gd:137`〔卷轴批 V3〕;真实输入沿=`ProbeUiUtil.push_drag_at`(`game/probe/probe_ui_util.gd:146-166`,press→motion×4→release 全经 `push_input`)打真实画布 `_gui_input`(`level_map_screen.gd:381-403` 拖拽态逐帧 `pan_by`)——**未绕过改动点**(探针全文零 `pan_by` 直调,grep 证);判据=视线位移=拖拽位移 40px 逐位。合回后 CI 现查补记 | -| R4 滚轮横滚 | 通过 | 断言 `level_map_viewport_probe.gd:114/116/120`〔卷轴批 V4〕;`push_wheel_at`(probe_ui_util.gd:168-176)经 `push_input`;映射 `_wheel_pan_step`(level_map_screen.gd:426-433,下/右=+60 前进向,代拍板白名单 5 授权)。合回后 CI 现查补记 | -| R5 clamp 包络与首末列可达 | 通过 | 断言 `level_map_viewport_probe.gd:88/102/158/160/161/167/168`〔卷轴批 V5〕;判据绑定 `viewport_center_canvas_pos()` 夹紧域(level_map_viewport.gd:76-77/:97-100/:111-114)+`is_clamped_at_edge()` 两极翻转(:81-86)+极值列入屏(:161-169,等价 spec 判据④);真实入口=超包络拖拽沿两极。合回后 CI 现查补记 | -| R6 拖拽不触发选路 | 通过 | 断言 `level_map_viewport_probe.gd:200/201/206`〔卷轴批 V6〕;**拖拽沿确从候选节点上方起沿**(:193 `gpos`=候选屏幕投影,:197 `push_drag_at(self, gpos, …)` 起点即候选);判据绑 `route_chosen` 发射面零计数(screen `route_chosen.emit` :465)+屏未关+阈值另一侧完整点击提交=1(:203-206,点击沿 press+release 成对经 push_input)。合回后 CI 现查补记 | -| R7 平滑滚动与减动效瞬切 | 通过 | 断言 `level_map_viewport_probe.gd:245/249/258`〔卷轴批 V7〕;tween 单段缓动 TRANS_CUBIC-EASE_OUT UiKit.motion(0.3)(level_map_viewport.gd:57-59);减动效走 `ArmedTimer.motion_still()`(armed_timer.gd:16-17=motion_scale<1)跳终态——探针置 `UiKit.motion_scale=0.5` 即设置面单点(settings_overlay.gd:96 同驱),判据同向在途+即达。合回后 CI 现查补记 | -| R8 指引件可见性与几何 | 通过 | 断言 `level_map_viewport_probe.gd:272-278`+浅图隐藏 :289〔卷轴批 V8〕;几何常量 FADE_BAND_W=70(level_map_viewport.gd:10)、CHIP_SIZE 240×30(:11)直挂 spec 判据②③;可见性=`_sync_guidance` 画布超窗判据(:181-191)。合回后 CI 现查补记 | -| R9 schema 头注指针反转(非行为) | 通过(静态重跑) | `level_gen_params.gd:3-4`+:70 反转落地;审计员重跑 grep:该文件「调参表」残留=0、「参数契约节」指向=2、`--check-only` 读数实现者在案。全仓唯一「调参表」残留=variation_table.gd:41(地形变异 v1.2 owner,不同文件不同域,不属本卡清退面) | -| golden 两 Shot 面(用户裁) | 通过 | `game/probe/level_map_shot_probe.gd`(PASS 签名 :36+落盘 fail-fast :89-91)+`game/tests/golden/windows/lmap_entry.png`/`lmap_boss.png` 已入库(6394abf7,Bin 215164/211513 字节)+`tools/render_gate.sh:168-197` 对拍段(PASS 签名+双图非零工件锚定+平台缺基线 SKIP 不判红)+`tools/golden_baseline_refresh.sh` --lmap 模式(:59-85,素材齐盘守卫)+`game/tests/golden/README.md` 台账随动;mac 缺基线义务已呈报(实现报告遗留 2+反哺点 6)。运行读数(changed=0.00% 双绿)=实现者在案;合回后 CI 现查补记 | - -卡①补充核对:26 断言计数属实(探针 26 处 `_check`+尾缀〔卷轴批 V1..V8〕27 行含 1 处缺位告警);`tools/probe_gate.sh:137-141` 注册新探针;ui_struct_probe 本批零改动(未触其结构断言面,卡①削弱申报该项落空=无事);实现报告实现决定 1-7(拖拽态落屏侧/open_choices 平滑判据/提交沿移抬杆/代拍板白名单定值/resize 即席重锚/_fit_canvas 同帧/mouse_exited 清跟踪器)均有代码承载且不越卡 §12 白名单;7 笔实现笔无一触碰 `design/`/两份根清单/`game/tests/README.md`(逐笔 name-only 核对)。 - -### 判据绑定面抽查(本卡抽 4 行,超中档下限 2 行) - -- R6(如上)——`route_chosen` 零发射+屏未关+完整点击仍提交,三面钉在「拖拽不提交/点击提交」的特有提交面上。 -- R2(如上)——当前节点屏空间投影=视口中线 ±2。 -- R5(如上)——夹紧域+两极 edge 翻转+极值列入屏。 -- R3(如上)——拖拽位移与视线位移逐位一致,且全程走引擎输入管线。 - -### 直查例外核对(逐条) - -| 直查行 | 申报状态 | 结论 | -|---|---|---| -| `level_map_viewport_probe.gd:67` `vp.get_child(0)`(取视口画布子件) | 探针内注释已给理由(「画布=视口首子件——setup 注入序」,:61),对照表/实现报告**未单列申报口径** | 缺漏(建议级,见末节 D2)——断言对象即承载结构本身,无公开可观测面可钉,风险零 | -| `level_map_viewport_probe.gd:266-268/:287-288` 按名取 FadeL/FadeR/PanHint | 同上——探针内注释在案,对照表未单列 | 缺漏(建议级,并入 D2)——R8 断言对象即指引子件结构本身 | -| screen 侧私有成员 | 新探针**未直读**任何 screen 私有成员(`_drag_active`/`_drag_press_pos` 零探针触达);既有「探针直读冻结」惯例面(level_map_screen.gd:39/:57-64)未扩 | 通过 | - -## 卡② 改写族孤儿机制与退役名清退批(验收档:中|执行深度:中档) - -### 对照表逐行核对(全量) - -| # | 结论 | 依据(文件:行) | -|---|---|---| -| R1 摘四段不可达改写分支 | 通过(静态面重跑一致;运行读数合回后 CI 现查补记) | diff 逐段核对:`damage_controller.gd` 命中侧交换/免掷覆盖/spike 置位/移档调用/增伤侧/spike 倍乘/`_discount_shift_up` 整函数全摘;`_ctx_rewrites` 返回键集={roll_read,threshold,crit,discount,clamp_hits}(:301-303)、`_hero_attack_ctx` 摘 spike_ready(:278-281)——与卡 T1 收窄键集逐字一致;armor_roll 发射点保留不接收返回值(:289-290,卡 3.6 口径);spike_ready/ar_hits/shift 残留 grep=0(审计员重跑)。六组逐字节对拍 diff=0 与三套件 exit=0=实现者读数在案;dump_battle 六组参数面(seed 42 默认+参数覆盖,dump_battle.gd:13/:21)核对成立 | -| R2 EFFECT_KINDS 摘 spike | 通过 | `effect_engine.gd:30` 词表摘名;断言 `effect_kind_retired_test.gd:89`「③词表闭面:kind=spike 出域拒绝」在案,沿既有 `_assert_rejected`/`_inject` 骨架(卡 T2 明示沿用);注入形态偏差(do.kind=spike,非卡 T2 括注 kind=modify_ticket+mode=spike)=实现决定 8 申报在案且经审计员核实——`validate_trigger_row`(effect_engine.gd:382-396)确无 mode 值域检查,括注形态无拒绝通道,实现口径与断言名/R2 判据绑定面(词表出域)一致。运行读数(负域套件 exit=1 四探针全拒)合回后 CI 现查补记 | -| R3 DO_KEYS 摘 trade_hit/trade_atk | 通过 | `effect_engine.gd:80-82` 摘两键;断言 `effect_kind_retired_test.gd:92`「④do 键闭面:trade_hit 出域拒绝」在案。运行读数合回后 CI 现查补记 | -| R4 注释面退役名清零 | 通过(40 名全扫审计员重跑) | 审计员自解析 `design/content-archive/道具退役素材库.md` 两表 40 名(41 减现役淬毒刃纹)重扫 `game/` 全域 .gd/.tres/.md/.tscn:命中仅 3 行=`treasure_items_test.gd:31/33/35` StubDB 夹具名——与卡 §5 留底申报逐行一致;契约 2 抽 4 处(grant_segment.gd:232「完美布防→封印全中倍率」、damage_controller.gd:109「猎巢人→nest_count 订阅消费面」、reward_grant.gd:130「掘进蓄能→付费积点账本」、grant_segment.gd:359「雷区图谱→标中雷追加」)——职责陈述(做什么/按什么序/取值从哪来)逐处保留,只换名;宿主套件绿=实现者读数,合回后 CI 现查补记 | -| R5 减半明细行去退役件名 | 通过 | `reward_grant.gd:226` 标签→「挖掘惩罚减半(%d→%d)」+effect_id→nest_halve;断言随动 `meta_progression_forge_test.gd:694/697/699-700`,强度三件(nc_hit 非空+等值「挖掘惩罚减半(6→3)」+零「挖雷」)与改前逐项对齐(基线 709d9a85:693-701 核对);grep nest_counter=0(审计员重跑)。合回后 CI 现查补记 | -| R6 空集拒绝 reason 去退役件名 | 通过(静态重跑) | `reward_grant.gd:189` reason 前缀→「中立移除:…」,`{"ok": false}` 形态未动(diff 核对);grep 爆破工兵包 game/=0(审计员重跑);观测面局限申报(reason 不可达、禁造行)在卡 §8/对照表一致在案 | -| R7 反弹明细标签去退役件名 | 通过(静态重跑) | `grant_segment.gd:165-166` 标签→「反弹伤害」+归因串→attune_nest_halve;**契约 3 逐字核对成立**:`channel=="reflect"` 判据、开单参数字典(channel/base_value/target_rule/ri/origin_cell)、`reward_grant.submit` 调用全未动(diff 对照基线 709d9a85:164-170);grep 惊巢反制/attune_nest_counter=0(审计员重跑)。运行读数合回后 CI 现查补记 | -| R8 sim 恒 false 匹配删除 | 通过(静态重跑) | `level_autoplay.gd:414-418` highlight=="seal_hit" 单判据保留、contains(雷区图谱) 条件与 :415 注释随删;grep 雷区图谱 game/=0(审计员重跑)。套件绿=实现者读数,合回后 CI 现查补记 | - -卡②补充核对(契约逐条):契约 1 三条 grep 审计员重跑全零——tables 五词 0、tree_rules 面 0、cell_removal 表面 0 仅 schema 在册(treasure_item_table.gd:20/:26);`feats.tres:855` clamp_bonus 现役一行对照记录与实现报告 T0 一致,表内现存 mode 值(queue/round/battle/clamp_bonus/refresh)零退役四模式。契约 5 禁留空壳——spike_ready/ar_hits/shift/_discount_shift_up 残留 grep 全零(审计员重跑)。契约 6 实现批禁写文档——7 笔实现笔 name-only 核对零触 design//待办清单/体验验证清单/game/tests/README.md。契约 7 零新增数值——diff 内零 .tres 表值改动。反哺点清单 7 条落点齐(含「明细标签是否入表」裁决点+增益状态/伤害与护甲零命中备案)。 - -### 判据绑定面抽查(本卡抽 3 行) - -- R2/R3(如上)——负域探针钉「退役词/键注入行→load_tables 拒绝+error 诊断≥1+进程退出码 1」;归属由夹具结构保证(copy_tables 全量现役表+唯一异常探针行)。观察 5:卡面写的「error 载荷含 effect_kinds 出域文案」未做逐字断言——沿用卡 T2 明示的既有骨架语义,非削弱。 -- R5(如上)——step_row display_name 等值断言+非空+零旧词,判据绑减半路径特有发射面。 -- R1 静态面(如上)——收窄键集逐字核对+摘除残留 grep,钉在「分支消亡」这一改动特有提交面。 - -### 测试削弱检查(逐处,两卡合并过目) - -`git diff 709d9a85..HEAD -- game/tests/ game/probe/` 全量 hunk 过目,共 5 文件: - -1. `effect_kind_retired_test.gd`:**纯新增**(两探针常量+两次 `_assert_rejected` 调用+PASS 文案随动);既有探针①②与 quit 语义零改动;`run_all.gd:195` 在册条目 expect=1/negative=true 未动。无削弱。 -2. `meta_progression_forge_test.gd`:恰 4 处期望串随 R5 换代(:694 匹配串/:697 描述/:699-700 等值串)+2 行注释(卡 3.3 表申报面)——断言强度逐项不降(非空+等值+不含旧词全保留),与卡 §8 削弱申报逐字吻合。无申报外削弱。 -3. `variant_placement_test.gd`:1 行注释(偏运硬币→订阅行,卡 3.3 表 :239 申报面),断言零改动。无削弱。 -4. `ui_input_probe.gd`:+16 行=case⑫断言段(图上命中提交沿)+case⑱ 雾段(雾下点击零提交)各补 release 沿——实现报告决定 3 申报在案;判据语义核对:雾段=零提交不变(且改为完整点击沿后更强)、命中段=提交沿随新语义移至抬杆(单 press 沿在新语义下不再是提交沿,不适配则必红——必要适配非放宽)。**呈报笔误**:申报写「case⑫⑰⑧」,实际落点两处、无 ⑰(case⑰ 未开格类型微光走 `_push_click` 既有成对沿,无需适配)(建议级 D3)。 -5. `ui_struct_probe.gd`:零改动——卡①「适配须保持语义」条款无事可核,非缺漏。 - -无申报外的断言删除、阈值放宽、扫描面缩小、换下层直调。 - -### 判据出处抽查(6 处,超下限 4 处) - -| 断言预期值 | 规格出处 | 独立可写出性 | -|---|---|---| -| 居中 ±2(探针 R2 :221) | level-map.md:101「屏中线 x=640±2」/:154 判据①/:269 | 能——规格句直接给出 640±2 | -| 渐隐带 70px(探针 R8 :273-274) | level-map.md:104/:154 判据②「屏缘两侧各 70px 渐隐带」 | 能 | -| chip 240×30(探针 R8 :275-276) | level-map.md:104/:154 判据③「240×30、圆角 6」 | 能 | -| 「挖掘惩罚减半(6→3)」(forge 测试 :699-700) | 卡② §8 R5 判据明文+reward_grant.gd:226 契约 3 边界;6→3 可由测试构造独立推出(heal 行 power=6×halve 50% ceil=3) | 能——预期值在卡内先行锁定,非镜像实现 | -| 拖拽阈值 8px(DRAG_THRESHOLD,level_map_screen.gd:34) | 卡① §12 白名单 2「8px 附近 provisional 区间内定值」授权;spec :103 明示阈值实现期定值 | 能——授权面在卡,值属 provisional 自主面 | -| golden 两 Shot 面 | 2026-11-05 用户裁决(实现报告决定 9 在案):只对拍关卡最开始+Boss 节点 | 能——裁决记录在实现报告与 golden/README 台账双在案 | - -六处均非「预期值只在实现里出现」的同义反复。 - -## 附加核对 - -- 能力行名实(game/tests/README.md:162-164 三行)::162 跟随行(_probe_follow_anchor/_probe_smooth_scroll_reduced_motion)与 :164 指引行(_probe_guidance_chrome)名实一致;**:163 平移行的 `_probe_clamp_bounds` 与落地名 `_probe_clamp_bounds_and_columns` 不一致**(建议级 D1——卡① §5「批末收尾核对表上名与落地一致(改名则回表)」未回表,反哺点清单亦未收录;实现批禁写 README,正确通道=回写卡段/反哺点)。 -- 负面套件在册:`game/tests/run_all.gd:195` effect_kind_retired_test expect=1/negative=true 登记在位,卡② T2 未动在册条目——一致。 -- S13 基线读数:`tools/gdstyle_baseline.txt` 恰 7 条且无本批触面键(level_map_screen/damage_controller/effect_engine/reward_grant/level_autoplay 均无键)——与实现报告 T0/T4 读数一致。 -- 闸件缺陷呈报核实(实现报告遗留 1):`tools/gate_platform.sh:37` `kf="$(mktemp …)"` 即建文件+:48 `[ -f "$kf" ]` 恒真→恒 124,呈报描述与代码相符;probe_gate.sh:97 `kf="$TMP/killed.$RANDOM"`(先赋路径不预建)为正确写法参照——呈报属实;该缺陷修法归工程批,本审计不裁定(不在验收对象内,已入反哺点 5)。 - -## 缺漏与观察清单 - -阻断级:无。 - -建议级(不阻断合并,归批后收尾/文档批): - -- D1:能力清单 `game/tests/README.md:163` 代表用例名 `_probe_clamp_bounds` ≠ 落地名 `_probe_clamp_bounds_and_columns`(卡① §5 名实核对义务未回表;反哺点清单漏收)。 -- D2:新探针对宿主内部结构的直查(`level_map_viewport_probe.gd:67` get_child(0)+:266-268/:287-288 按名取指引子件)未按 test-conventions §8.7 第 4 条在对照表逐条申报口径;探针内注释已给理由(断言对象=承载结构本身,无公开观测面),screen 侧既有「探针直读冻结」惯例未被动用、新私有成员零直读,风险零。 -- D3:实现报告/提交信息写「ui_input_probe case⑫⑰⑧ 补 release 沿」,实际落点为 case⑫断言段+case⑱雾段两处、无 ⑰——呈报笔误,判据语义已核保持。 - -观察(记录在案,不构成缺漏): - -- O1:R2 判据绑定面用屏空间投影而非卡面所写 `viewport_center_canvas_pos()` 调用——更外层真实观测,与 spec 判据①同义,非削弱;连带 `game/tests/README.md:162` 读面句与实况有轻微出入。 -- O2:卡② R2/R3 负域探针未逐字断言错误文案(沿用卡 T2 明示骨架语义;归属由夹具唯一异常行结构保证)。 -- O3:卡① T1 写「探针宿主沿组合根真实屏」、卡 §8 对照表写「场景探针实例化本屏」——卡内两处口径不一,实现取对照表口径且在对照表真实入口格如实呈现;`push_input` 真实输入管线口径照守(禁合成投喂的实质红线未破)。 -- O4:探针宿主直构 runner(start_level_external)属 test-conventions §5.4 自动化测试直构口径,探针头注已申报。 - -## 审计结论 - -**通过**(可合并;合并落地后按中档梯度以 `tools/ci_check.sh <合并提交>` 现查读数补记「最窄复跑」格——零触发或不可判不作绿证)。 - -- 卡①卷轴视口批(验收档:中):对照表 10 行全通过;绑定面抽查 4 行钉面成立;削弱零申报外;判据出处 4+ 处独立可写出;缺漏 3 项均建议级(D1 能力行名实回表、D2 直查申报口径补记、D3 呈报笔误)。 -- 卡②改写族清退批(验收档:中):对照表 8 行全通过;契约 1/2/3/5/6/7 审计员重跑/逐处核对全部成立;削弱恰为申报内 4 处期望串且强度不降;40 名扫描与卡 §5 留底逐行一致;无阻断项。 -- golden 扩项:两 Shot 面用户裁决在案、基线入库、闸件对拍段与台账齐;mac 冻结义务已呈报(反哺点 6)。 diff --git a/reports/需求卡片-卷轴视口批-2026-11-05.md b/reports/需求卡片-卷轴视口批-2026-11-05.md deleted file mode 100644 index 47c14619..00000000 --- a/reports/需求卡片-卷轴视口批-2026-11-05.md +++ /dev/null @@ -1,140 +0,0 @@ -# 需求卡片:卷轴视口批(关卡画面选路屏视口化) - -- 来源:[待办清单](../待办清单.md)「超预算图策略升级路径——等比缩放与滚动视口两案待裁」条(状态=文档设计已闭合+待写卡,2026-11-05 用户裁滚动视口案落地)。 -- **唯一事实源**:[level-map.md v2.0](../design/gdd/ux/level-map.md) §布局决策 5(行为四条表 :101–104+内嵌视口效果图 :108–153+像素级视觉判据 :154)+[关卡节点图生成.md v1.5](../design/gdd/systems/冒险循环/关卡节点图生成.md) §参数契约(图规模无呈现侧上限)。设计讨论四口子与效果图人审均 2026-11-05 用户裁决在案。 -- **验收档:中**(呈现交互面——玩家可见但不损持久状态;无存档写读、无结算公式、无 RNG 触碰;批卡 U0 时确认或改判)。 - -## 1. 目标与完成定义 - -关卡画面(选路屏)落卷轴视口范式:画布随图生长可超屏,屏为窗口——①视口锚点=当前节点居中;②停点切换与兑付回图平滑滚动跟随(减动效瞬切);③拖拽+滚轮手动平移(clamp 画布包络、拖拽不触发选路);④屏缘渐隐带+平移提示 chip 指引。 - -完成定义:验证闸对照表 R1–R9 全部有绿读数;场景探针家族扩展件当轮真实跑批通过;代码域闸全绿;用户实机目检「深度 13 图拖拽可达首末列、推进跟随方向感」登记不阻塞。 - -## 2. 现状事实(开工自行复核) - -- [level_map_screen.gd:26-32](../game/presentation/views/level_map_screen.gd) 冻结公式常量:`LAYER_BASE_X=70`/`LAYER_STEP_X=122`/`SLOT_BASE_Y=52`/`SLOT_STEP_Y=58`/`NODE_ICON_PX=20.0`/`NODE_HALF(36.5,25)`(52×36 的 1.4× 绘制)/`HIT_PAD=6.0`。 -- [level_map_screen.gd:66-69](../game/presentation/views/level_map_screen.gd) `_content_size(620,240)`、`_layout_cache`——`open_choices` 按图拟合画布尺寸。 -- [level_map_screen.gd:77-82](../game/presentation/views/level_map_screen.gd) 画布由 `CenterContainer`(`PRESET_FULL_RECT`)承载:整幅居中、无裁切无平移——超屏图(L3 层深 13,画布宽 1700.5px)两侧各 ~210px 出屏。 -- [level_gen_params.tres:41](../game/data/tables/level_gen_params.tres) L3 `layers=13`——深度 13 是现行定值,非极端情形。 -- [level_gen_params.gd:3-4、:69](../game/data/schemas/level_gen_params.gd) 头注「域校验沿关卡节点图生成.md v1.1 调参表已锁条款」「域并单点(关卡节点图生成.md v1.4 调参表)」——owner 文档已 v1.5 换代参数契约节,指针失效待反转(本卡 T4 随动)。 -- [ui_kit.gd:231-232](../game/presentation/views/ui_kit.gd) `UiKit.motion(dur)` 呈现层 tween 时长单点包装(减动效面)。 -- [ui_struct_probe.gd:204](../game/probe/ui_struct_probe.gd) `_audit("level_map", ...)` 既有结构审计锚;[golden/README.md:8](../game/tests/golden/README.md) level_map 全屏 golden=历史留根、现行闸件未对拍(本批不触渲染闸对拍)。 -- 全文件 662 行——超 code-conventions §1.1 的 ~400 行审视线,视口承载拆件有据。 - -## 3. 设计契约(违反=L3 停机呈报) - -- 🔴 **冻结值零改动**:节点图标 20px 烘焙 1:1、通道折线 2/3/4px、画布公式(宽=70+层深×122+44.5、高=52+槽位×58+25+24、下限 620×256)、节点方块 52×36×1.4 绘制、编号 10px——视口批只加行为,不动任何像素冻结件(level-map.md:69、:154)。 -- 🔴 **视口纯呈现态**:平移位置零核心写、不进存档(重进本屏按锚点规则重新定位);Core 层零触碰、RNG 零触碰(level-map.md:103 行、:107 视口为纯呈现态句)。 -- 🔴 **选路唯一通道**:图上点击提交语义零改动;拖拽超阈值不得触发选路提交(level-map.md:103)。 -- 🔴 **零自动推进**:视口跟随只随停点切换/兑付回图发生,不构成任何自动前进路径(level-map.md:141 零自动推进纪律不变)。 -- 🔴 **拆分边界纪律**(code-conventions §1.1,2026-10-28 用户裁):每个拆出单元有可陈述职责语句与单一变化原因;拆出单元有集体身份;「过阈值」只作发现信号;拆不出内聚单元=停卡走豁免通道,禁硬拆凑绿。 -- 🔴 **禁为机检文本保留无效成员**(code-conventions §1.1⑤):机检键与卡片契约互斥=停卡呈报,禁自造第三条路。 - -## 4. 范围边界 - -做:视口承载件、锚点跟随、平滑滚动、减动效瞬切、拖拽/滚轮平移、clamp、渐隐带与提示 chip、探针断言、schema 头注指针反转。 -不做:缩放与缩略图(等比缩放案已否决)、其余视口暗示形态(边缘回弹等——布局决策 5 注后置)、顶栏/底栏/放弃按钮/覆盖层改动、生成器与参数表改动、键盘/手柄输入(排 Beta)。 - -## 5. 关联文档同步面 - -| 文档 | 关联点 | 同步义务 | -|---|---|---| -| [level-map.md](../design/gdd/ux/level-map.md) v2.0 | 布局决策 5 行为实现与 AC :260–271——实现若发现 spec 缺口 | 设计权威——实现批禁写,缺口逐条列反哺点清单由文档批落 | -| [game/tests/README.md](../game/tests/README.md) 能力清单 | 本卡新增能力行三行(写卡段已同批落表,见 §8 能力行列) | 机械面——实现批禁写;批末收尾核对表上名与落地一致(改名则回表) | -| [level_gen_params.gd](../game/data/schemas/level_gen_params.gd) | 头注 :3-4/:69 指针失效(owner 已 v1.5 参数契约) | 本卡 T4 随批反转指针(非行为改动——`game/` 内实现批可写面) | -| [关卡节点图生成.md](../design/gdd/systems/冒险循环/关卡节点图生成.md) v1.5 | 无——本批实现不改变其任何陈述 | 无同步义务 | - -## 6. 文件结构图(行为改动→对照表行互指) - -| 文件 | 职责 | 改动性质 | -|---|---|---| -| `game/presentation/views/level_map_viewport.gd` | 新增——卷轴视口承载件:画布宿主与裁切、平移状态与 clamp、锚点跟随、平滑滚动、指引件(拖拽/滚轮判定留画布 `_gui_input`——事件流同源) | 行为改动(R2–R8)·新增 | -| `game/presentation/views/level_map_screen.gd` | 修改——CenterContainer 承载换视口件;停点切换/回图接线 `reanchor()`;`_content_size` 拟合后调 `reanchor(false)` 首锚 | 行为改动(R1+R2/R3 随动)·复用既有文件 | -| `game/data/schemas/level_gen_params.gd` | 修改——头注指针反转(owner 单点改为本文件域校验+参数契约指针) | 非行为改动(R9)·复用既有文件 | -| `game/probe/level_map_viewport_probe.gd` + `.tscn` | 新增——视口行为场景探针(真输入驱动) | 行为改动(R2–R8 验收载体)·新增 | -| `game/probe/probe_ui_util.gd` | 修改——新增拖拽沿与滚轮沿真输入合成工具 `push_drag_at`/`push_wheel_at`(沿 `push_click_at` :717-733 同式;探针共用面唯一落点) | 非行为改动(探针侧工具)·复用既有文件 | - -## 7. 任务卡 T0..T4 - -### T0 读数与基线(0.5 工作日) -- [ ] 核对 `tools/gdstyle_baseline.txt` 有无 `level_map_screen` 相关 S13 键;有则记录登记值(改后只降不升),无则记「无键、按工具默认」 -- [ ] 跑场景探针现状读数:`…console.exe --headless --path . res://probe/ui_struct_probe.tscn`(level_map 审计段绿)+ `res://probe/screen_flow_probe.tscn`——读数记入本步提交信息 -- [ ] 跑冒烟 `python tools/run_smoke.py`——基线读数在案 - -### T1 视口承载件与手动平移(1–1.5 工作日) -- [ ] 新增 `level_map_viewport.gd`(接口块见 §10):`setup(canvas, anchor_provider, viewport_size)`、`pan_by(delta)`、`viewport_center_canvas_pos() -> Vector2`、`is_clamped_at_edge() -> bool`;`clip_contents=true`;成员 ≤8 -- [ ] `level_map_screen.gd` 承载改造:CenterContainer 换视口件实例;`open_choices` 拟合后调 `reanchor(false)` 首锚(入口停点锚入口组、其余锚当前节点——`anchor_provider` 由 screen 提供画布坐标) -- [ ] 拖拽/滚轮判定落**画布既有 `_gui_input`**(画布已持有鼠标事件流——悬停/选路同源,禁在视口件层做父子事件路由竞争;视口件只管裁切/offset/clamp/跟随):拖动距离阈值(provisional 8px)判定,超阈值进拖拽态逐帧调 `viewport.pan_by()`;滚轮横滚映射 `pan_by`(代拍板:滚轮下=向右/前进向) -- [ ] clamp:`pan_by` 后 offset 收敛在画布包络内(`viewport_center_canvas_pos()` 画布坐标恒在 `[half_view, canvas_size-half_view]` 夹紧域;**画布小于视口=居中分支**——夹紧域退化为居中定位);探针宿主沿 ui_struct_probe :204 同款(组合根真实屏 `main.ui.modals.run.level_screen`),禁合成投喂替代真实路径 -- [ ] 探针 `level_map_viewport_probe.gd`:断言 R3(拖拽移视口)、R4(滚轮移视口)、R5(clamp 边界)、R6(拖拽不触发选路——`route_chosen` 零发射);真实入口=probe_ui_util 合成沿走 `push_input` - -### T2 锚点跟随与平滑滚动(0.5–1 工作日) -- [ ] `reanchor(smooth)`:目标 offset=锚点画布坐标−视口半宽(居中);`smooth=true` 走单段缓动 tween 时长 `UiKit.motion(0.3)`(provisional);`smooth=false` 即达;重入先杀在飞 tween 再建新(快速连续停点切换防叠加) -- [ ] 减动效:`UiKit.motion` 通道既有减动效语义下滚动跳终态——探针断言 R7(减动效开=位置即达,无 tween 中间帧) -- [ ] level_map_screen.gd 停点切换与兑付回图路径接 `reanchor(true)`——入口停点锚入口节点组(多入口取组包围盒居中) -- [ ] 探针断言 R2(停点切换后当前节点画布坐标投影=视口中线 x=640±2) - -### T3 指引件(0.5 工作日) -- [ ] 视口件内渐隐带:屏缘左右各 70px 渐变(色取屏底同族——代拍板渐变 stops);浅图画布不超屏时渐隐带隐藏(无暗示必要) -- [ ] 平移提示 chip:240×30 圆角 6、深底石灰描边、文案「◄ 拖拽画布 / 滚轮平移 ►」14px;图区底部居中(level-map.md:104) -- [ ] 探针断言 R8(渐隐带与 chip 可见性+几何判据——像素级判据②③,level-map.md:154) - -### T4 指针反转与收口(0.5 工作日) -- [ ] `level_gen_params.gd` 头注 :3-4/:69 反转:「取值域与字段契约单点=本文件域校验;概念与设计意图=关卡节点图生成.md v1.5 参数契约节」(非行为改动——grep 判据 R9) -- [ ] 全探针最窄回归:ui_struct_probe level_map 段+screen_flow_probe 复跑绿(波内修复只做出红最小单元的最窄确认) -- [ ] 产出物落位:`reports/iter-实现报告-<日期>.md`(各卡状态+实机目检总清单+实现决定记录)+ `reports/iter-反哺点-<日期>.md`(同步面所列逐条落点)——轻闸全绿后、合并前写齐 - -估时合计:3–4.5 工作日(中值 3.5)。 - -## 8. 验证闸(改动—验收对照表) - -| 需求点 | 改动(文件:行/行为) | 验收测试(名称+落点+尾缀) | 层级 | 真实入口 | 判据绑定面 | 能力行 | -|---|---|---|---|---|---|---| -| R1 浅图整幅居中无裁切+画布入视口件承载(锚 design/gdd/ux/level-map.md:260) | level_map_screen.gd(CenterContainer→viewport 件) | `level_map_viewport_probe.gd:_probe_shallow_no_crop`〔卷轴批 V1〕 | 探针 | 场景探针实例化本屏+open_choices 真实停点 | 画布尺寸≤视口时居中分支 offset 定位、无裁切 | 新增:关卡画面视口跟随 | -| R2 视口锚点:停点切换/回图后当前节点居中 x=640±2(锚 design/gdd/ux/level-map.md:101、:269) | level_map_viewport.gd `reanchor`+screen 接线 | `level_map_viewport_probe.gd:_probe_follow_anchor`〔卷轴批 V2〕 | 探针 | 合成推进停点切换经真实屏流程 | 当前节点画布坐标经 `viewport_center_canvas_pos()` 投影=640±2 | 新增:关卡画面视口跟随 | -| R3 拖拽平移移动视口(锚 design/gdd/ux/level-map.md:103) | 画布 `_gui_input`(level_map_screen.gd)拖拽态调 `pan_by` | `level_map_viewport_probe.gd:_probe_drag_pan`〔卷轴批 V3〕 | 探针 | `ProbeUiUtil.push_drag_at` 拖拽沿走 `push_input` | `_offset` 位移量=拖拽位移(clamp 前) | 新增:关卡画面视口平移 | -| R4 滚轮横滚移动视口(锚 design/gdd/ux/level-map.md:103) | 画布 `_gui_input` wheel 分支调 `pan_by` | `level_map_viewport_probe.gd:_probe_wheel_pan`〔卷轴批 V4〕 | 探针 | `ProbeUiUtil.push_wheel_at` 合成滚轮沿走 `push_input` | `_offset` 位移=滚轮步进映射 | 新增:关卡画面视口平移 | -| R5 clamp 边界与首末列可达:不出露屏底空档、拖拽两极首列与末列(含 Boss)入屏(锚 design/gdd/ux/level-map.md:103、:260) | `pan_by` 收敛逻辑+包络两极 | `level_map_viewport_probe.gd:_probe_clamp_bounds`〔卷轴批 V5〕 | 探针 | 极端拖拽沿(超包络、两极到边) | `viewport_center_canvas_pos()` 恒在夹紧域;浅图居中分支;`is_clamped_at_edge()` 翻转;两极时深度 0 与深度 13 列中心入视口 | 新增:关卡画面视口平移 | -| R6 拖拽不触发选路提交(锚 design/gdd/ux/level-map.md:103) | 画布 `_gui_input` 阈值判定(provisional 8px) | `level_map_viewport_probe.gd:_probe_drag_no_submit`〔卷轴批 V6〕 | 探针 | 拖拽沿起止于候选节点上方 | `route_chosen` 零发射+屏幕未关 | 新增:关卡画面视口平移 | -| R7 平滑滚动与减动效瞬切(锚 design/gdd/ux/level-map.md:102、:188、:227) | `UiKit.motion(0.3)` tween/减动效跳终态 | `level_map_viewport_probe.gd:_probe_smooth_scroll_reduced_motion`〔卷轴批 V7〕 | 探针 | 停点切换+设置面减动效置位 | smooth=true 有 tween 中间帧;减动效开=位置即达 | 新增:关卡画面视口跟随 | -| R8 指引件:渐隐带 70px+chip 240×30 呈现(锚 design/gdd/ux/level-map.md:104、:154) | 视口件指引子件 | `level_map_viewport_probe.gd:_probe_guidance_chrome`〔卷轴批 V8〕 | 探针 | 深图 open_choices 真实停点 | 像素级判据②③(level-map.md:154)——可见性+几何 | 新增:关卡画面视口指引 | - -非行为改动行:schema 头注指针反转(level_gen_params.gd:3-4/:69)——判据=全仓无「域并单点=调参表」残留、头注含「参数契约节」指向(锚 design/gdd/systems/冒险循环/关卡节点图生成.md:109);由 §6 文件结构图该行覆盖,T4 落步,实现报告对照表列非行为改动行。 -锚行核对义务:开工时行号以当版文件为准(本卡锚基于 v2.0/v1.5 抄录)。 - -- 测试方式两分法:R1–R8 全走探针自动化(调试注入不适用——本卡零数据面改动,状态经真实停点与真实输入驱动);用户目检项=「深度 13 图拖拽可达首末列、跟随方向感、chip 不碍选路」登记进实现报告实机目检总清单(登记不阻塞)。 -- 回归措辞:里程碑步(T 段)出口跑一次场景探针族全套;波内修复只做出红最小单元的最窄确认;新增探针先行孤立验证再并入全套。 -- 测试削弱申报:无删旧断言申报;ui_struct_probe level_map 段既有审计判据不改——承载改造若触其结构断言面,适配性调整须在实现报告申报并保持判据语义。 -- 独立验收审计:`reports/iter-验收审计-<日期>.md`,由未参与实现的会话执行;本卡验收档=中,审计深度按 test-conventions §8.7 中档执行(对照表逐行全量、判据绑定面抽查、削弱检查逐处、直查例外逐条、最窄复跑以远端 CI 现查读数代证)。 - -## 9. 异常分级 - -- L1 自救:探针断言红→改后只跑出红探针的最小单元;闸红只跑红件。 -- L2 记录继续:画布 `_gui_input` 内拖拽态与悬停/选路命中分支次序的调整、渐变/chip 视觉微调(provisional 区间内)、S13 读数波动在只降不升约束内的消化。 -- L3 停机写报告等用户:触碰 §3 任一 🔴;S13 键上升且无法只降;拆不出内聚单元;机检预算互斥=上游缺陷停卡退回写卡段;拖拽误触选路提交且路由层面消不掉。 - -## 10. 落位与可复用性预检 - -- **level_map_viewport.gd(新增)**:不复用 `ScrollContainer`——其滚动条 UI、焦点/滚动语义与本屏「纯鼠标、无滚动条、锚点居中跟随」冲突,且平滑滚动与 clamp 语义仍需全自管;承载裁切用 Control `clip_contents`(引擎内建,项目已有 clip 先例)。唯一面:视口 offset 状态只落本件(screen 的 `_layout_cache` 仍管布局、不管视口);全仓 grep 无第二处视口/平移逻辑。分层:呈现层内部子件——构造注入(canvas/anchor_provider/viewport_size 一次交齐,code-conventions §1.6 拆分交接);读核心只读面经 screen 既有出口,零新增核心触点。 -- **probe_ui_util.gd 增补(复用既有文件)**:`push_drag_at`/`push_wheel_at` 落探针共用面唯一落点——禁另起工具文件散落;`push_click_at`(ui_input_probe :717-733 同式)点击沿同式扩展。 -- **指引件(渐隐带/chip)**:随视口件承载(同职责:视口呈现行为);不立独立文件——拆出「命不出名字的打包」即凑计数袋。 -- **level_gen_params.gd 头注反转(复用既有文件)**:注释单行改动,无新增件。 - -## 11. 实现规范预算 - -- **新增 level_map_viewport.gd 三查**:①接口块公开方法 4(setup/pan_by/viewport_center_canvas_pos/is_clamped_at_edge)≤20 ✓;②成员变量 ≤8(_canvas/_anchor_provider/_viewport_size/_offset/_tween/_drag_active/_drag_accum/_guided_visible)≤15 ✓;③无迁移函数(新件零存量函数迁入——screen 侧只是接线改造,hover/命中逻辑零迁移)。 -- **存量触面**:level_map_screen.gd——T0 记 S13 键基线;本批改动为承载替换与 reanchor 接线,预期键值持平或只降;达成手段=T4 复跑 S13 对账。 -- 指标例外:无申报。 - -## 12. 代拍板白名单 - -1. 画布 `_gui_input` 内拖拽态与悬停/选路命中的事件分支次序(红线=R6 判据不破)。 -2. 拖拽距离阈值具体值(8px 附近 provisional 区间内定值)。 -3. 平滑滚动缓动曲线类型(单段缓动家族内选型)。 -4. 渐隐带渐变 stops 与 chip 深底/描边色值(art-bible §4.1 冻结色板同族取值)。 -5. 滚轮方向映射(下=向右/前进向)。 -超清单决定记入实现报告「实现决定记录」节。 - -## 13. 待裁点 - -零待裁点,开工门=U0(四口子与效果图 2026-11-05 用户已裁决;验收档「中」随批卡确认)。 diff --git a/reports/需求卡片-改写族孤儿机制与退役名清退批-2026-11-05.md b/reports/需求卡片-改写族孤儿机制与退役名清退批-2026-11-05.md deleted file mode 100644 index 131cf7fb..00000000 --- a/reports/需求卡片-改写族孤儿机制与退役名清退批-2026-11-05.md +++ /dev/null @@ -1,267 +0,0 @@ -# 需求卡片·改写族孤儿机制与退役名清退批(2026-11-05) - -来源:待办清单条目「damage_controller 按序改写族——内容孤儿机制与退役名注释层」(2026-11-04 登记,来源=会话提及)。 -唯一事实源:`design/gdd/systems/跨局循环/锻造工坊.md` v0.13 §满级特效扩展位(本期已按本批口径订正)+本卡「现状事实」所列代码读数;机制处置与注释口径的裁决记录=2026-11-05 会话,用户裁「只要有问题的都要改」,退役内容名一律清退、零现役注册的改写分支一律摘除。 -验收档:中(一处玩家可见明细行文案换代+若干不可达分支摘除;不写存档、不改乘区公式与数值表)。 -估时:2.25–2.75 个工作日(T0 0.25+T1 0.5+T2 0.5+T3 0.5–1+T4 0.25+T5 0.25 加总)。切分预案:T3 注释面若单轮改不完,按文件切成 T3a(core 八件)/T3b(schemas+sim+tests),两张各自收尾,不并进 T1。 - ---- - -## 1 目标与完成定义 - -做完这五件事算完: - -1. 主角先手攻击的四个改写分支摘除——它们零数据表行注册,游戏里从不执行。 -2. 连带收窄两处引擎词表:`EFFECT_KINDS` 摘 `spike`、`DO_KEYS` 摘 `trade_hit`/`trade_atk`,并同批补负域探针取证。 -3. `game/` 注释面退役内容名清零(42 行/13 文件),只换名不换职责陈述。 -4. 三处挂退役件名的玩家可见文案改中性机制文案(其中一处今天可达),一处 sim 死匹配删除。 -5. 产出物两份写齐(实现报告+反哺点清单),代码域闸全绿,改前改后对拍逐位一致。 - -判据总口径:本批除第 4 项文案外全部是非行为改动——零现役注册行=分支不可达=删了也不改变任何一帧输出。这条不靠感觉,T0 用三条 grep 读数坐实。 - -## 2 设计事实源 - -- 设计线闭合凭据:`design/gdd/systems/跨局循环/锻造工坊.md` v0.13(2026-11-05)§满级特效扩展位——本批订正该节四处陈述,其中重甲反震与长枪先手连击两条候选的代价档由「零新代码」改判「需新代码」,效果类型闭集词数不再抄进文档。 -- 机制处置裁决:本卡所属待办条目「实况」段所载 2026-11-05 会话裁决。 -- 代码现状取证:本卡第 3 节全部带 `文件:行号`,无一条凭记忆。 - -## 3 现状事实 - -### 3.1 四个改写分支零注册(本批要摘的) - -| 分支 | 代码位置 | 触发条件 | 现役注册行 | 退役名注释 | -|---|---|---|---|---| -| 命中交换 | `game/core/damage_controller.gd:297-302`(命中侧)、`:351-353`(增伤侧) | `kind=modify_ticket` 且载荷带 `trade_hit`/`trade_atk` | 0 行(`game/data/tables/` 全域零命中) | :285-286、:341、:350(矿工重锤) | -| 免掷恒折扣 | `:305-309` | `kind=modify_ticket` 且 `mode=armor_rewrite` | 0 行 | :287(专注) | -| 满层必中与倍乘 | `:310-313`(必中置位)、`:368-372`(倍乘) | `kind=modify_ticket` 且 `mode=spike` | 0 行 | :288(厚积薄发,行内含 spike)、:342 与 :368 | -| 轻甲折扣档改善 | `:320-323` +私有函数 `_discount_shift_up`(`:623`) | `kind=modify_ticket` 且 `mode=discount_shift` | 0 行 | :288、:622(猎弱本能) | - -穿线键 `spike_ready` 出现在 `:282`、`:310`、`:313`、`:325`、`:369` 五处,随分支一起消失。 - -克制点数面(`mode=clamp_bonus`)有现役一行注册:`game/data/tables/feats.tres:853-857` 淬毒刃纹(`kind=modify_ticket`/`mode=clamp_bonus`/`delta=2`)——**不摘**,`_ctx_clamp_delta`(`:333-338`)与 `clamp_check` 发射点(`:315`)保持原样。 - -### 3.2 两处词表在册 - -- `game/core/effect_engine.gd:30` `EFFECT_KINDS` 含 `"spike"`;该常量实数 32 词(本卡现读,摘后 31)。全仓按 `kind == "spike"` 派发效果的代码**不存在**——`spike` 只在词表与注释里在册(另两处:`:30` 词表、`:452` 「任意真族(任一命中即生效):spawn_spell、spike」注释)。 -- `game/core/effect_engine.gd:82` `DO_KEYS`(现 26 键)含 `"trade_atk"`, `"trade_hit"`;执法点在 `:417`(`if not DO_KEYS.has(String(k))` 出域即拒绝)。摘后 24 键。 -- `attack_segments` 不属本批:它已随架构审查整改甲案整链退役(`grep -r attack_segments game/` 仅命中 `game/tests/unit/data_config/effect_kind_retired_test.gd:3` 的注释),本批只把它在 GDD 里的错句一并订正(见第 6 节)。 - -### 3.3 注释面退役名全仓扫描读数 - -名单来源=`design/content-archive/道具退役素材库.md` 两张表的「原名」列,共 41 名;减去表内仍作为现役 `display_name` 出现的 1 名(淬毒刃纹)=40 名。扫 `game/` 全域 `.gd`/`.tres`/`.md` 命中 **53 行/13 文件**,无一条落在 `.tres` 数据表里。 - -| 文件 | 注释面行号(本批改) | 字面量行号 | 字面量处置 | -|---|---|---|---| -| `game/core/damage_controller.gd` | 109、138、285、287、288、328、341、350、394、424、622 | — | — | -| `game/core/reward_grant.gd` | 2、130、183、221 | 189、226 | 两处都改中性文案(T4) | -| `game/core/settlement/grant_segment.gd` | 127、128、232、240、265、279、283、351、362、373 | 166 | 玩家可见标签改中性(T4) | -| `game/core/reward_roller.gd` | 1、41、46、86 | — | — | -| `game/core/effect_engine.gd` | 64、65、157、452 | — | 452 随 T1 摘词改写 | -| `game/core/battle_orchestrator.gd` | 258、538 | — | — | -| `game/core/action_economy.gd` | 82 | — | — | -| `game/data/schemas/treasure_item_table.gd` | 20、122 | — | — | -| `game/sim/adventure_monte_carlo.gd` | 75 | — | — | -| `game/sim/level_autoplay.gd` | 415 | 421 | 死匹配删除(T4);415 随删该处注释 | -| `game/tests/unit/core/meta_progression_forge_test.gd` | 677、690 | 694、697、699、700 | 断言串随 T4 文案换代(申报见第 8 节) | -| `game/tests/unit/battle_settlement/variant_placement_test.gd` | 239 | — | — | -| `game/tests/unit/core/treasure_items_test.gd` | — | 31、33、35 | 不动——StubDB 自造夹具名,不宣称内容现役 | - -字面量合计 11 行:本批动 8 行(三文件的四处文案/死串=`reward_grant:189`/`:226`、`grant_segment:166`、`level_autoplay:421`,加锻造测试四处断言串 `694`/`697`/`699`/`700`),其余 3 行夹具名保留。注释面 42 行全改,另加 `effect_engine.gd:452` 一句随摘词改写=本批改写 43 处。 - -### 3.4 玩家可见文案三处 - -- `game/core/reward_grant.gd:226`:`mine_hit` 减半路径发射的结算明细行标签——`"惊巢反制——危险格挖掘惩罚减半(%d→%d)" % [...]`,载荷 `"effect_id": "nest_counter"`。`惊巢反制` 与 `nest_counter` 都是退役件名(素材库表一 :18),而这行文案是玩家能看见的,且这条路径今天可达(有现役锻造锋行驱动——`meta_progression_forge_test.gd:694-700` 正在钉它)。 -- `game/core/reward_grant.gd:189`:`_cell_removal_open` 空集拒绝 reason——`"爆破工兵包:3×3 区域内无可移除危险格(须未揭示且未封印)"`。该通道 `cell_removal` 在册(`game/data/schemas/treasure_item_table.gd:26`、消费点 `reward_grant.gd:160-161`)但零现役数据行(`game/data/` 全域零命中),所以 reason 今天不可达;文案仍挂退役件名。通道本体不进本批(见第 5 节),本批只清文案。 -- `game/core/settlement/grant_segment.gd:166`:`mine_hit` 订阅中 `kind=open_ticket` 且 `channel="reflect"` 的行开单,明细标签硬编码 `"惊巢反制·反弹"`,归因串 `"attune_nest_counter"`。`"reflect"` 在 `game/data/tables/` 二十一张表逐张 grep 零命中 → 今天不可达,与 `:189` 同类问题(标签挂退役件名)。`reflect` 渠道本体不进本批(见第 5 节),本批只清标签与归因串。 - -### 3.5 一处 sim 死匹配 - -`game/sim/level_autoplay.gd:421` 用 `String(row.get("display_name", "")).contains("雷区图谱")` 捕高光事件,`:415` 是配套注释。`雷区图谱` 零现役行(`game/data/` 零命中)→ 该条件恒 false。 - -### 3.6 既有测试面读数(决定本批要不要改测试) - -- 四个 mode 与两个键在 `game/tests/`、`game/probe/`、`game/sim/` **零命中**(`grep -rn "trade_hit\|trade_atk\|armor_rewrite\|discount_shift\|spike" game/tests/ game/probe/ game/sim/` 空)。摘分支不动任何既有断言。 -- `armor_roll` 有既有断言:`game/tests/unit/battle_settlement/roll_multiplier_test.gd:125 _smoke_armor_roll()`——它测的是护甲骰与折扣读数,不是订阅消费。所以掷点面 `:293 _armor_roll()` 与发射调用 `:296 _fx_hits("armor_roll", ...)` 都保留(`armor_roll` 在 `effect_engine.gd:13` 事件词表在册),只删 `:305-309` 消费环,`ar_hits` 局部变量随删。 - -## 4 设计契约 - -- 🔴 **契约 1|零现役注册坐实才许摘**:T0 三条 grep 读数必须全为零——`game/data/tables/` 内 `spike`/`armor_rewrite`/`discount_shift`/`trade_hit`/`trade_atk` 各 0 行、`tree_rules` 面 0 行、`effect_kinds` 面 `cell_removal` 0 行(后者只作记录,本批不摘通道)。任一数非零=该分支可达=停卡 L3 呈报,禁直接摘。 -- 🔴 **契约 2|注释改写只换名不换职责**:42 行注释逐处保留「这段在做什么、按什么序、为什么这样取」的陈述,把退役件名替换成机制语言。整行删除、成片缩写、或删注释换 gdstyle 行数绿=违规(先例:宿主行数压至 999 时「禁删注释凑行数红线未碰」)。 -- 🔴 **契约 3|文案换代禁碰数值与发射序**:`:226` 只改标签字符串,`[int(row.power), half]` 取值、`emit_cb.call` 参数位序、`"effect_id"` 载荷键一律不动;`:189` 只改 reason 前缀,`{"ok": false}` 形态不动。 -- 🔴 **契约 4|词表收窄与负域探针同批**:摘 `EFFECT_KINDS` 的 `spike` 与 `DO_KEYS` 的两键,必须同批落 T2 探针;只摘词不取证=本卡未完成。 -- 🔴 **契约 5|禁留空壳**:`spike_ready` ctx 键、`ar_hits`/`shift`/`trade_hit` 局部变量、`_discount_shift_up` 函数随分支即删,禁保留空返回、别名或「以后可能用」的成员凑机检文本。 -- 🔴 **契约 6|实现批禁写文档**:`design/` 整个目录、`待办清单.md`、`体验验证清单.md`、`game/tests/README.md` 一律不写;要改的文档句子全进第 6 节与反哺点清单。 -- 🔴 **契约 7|零新增数值**:本批不引入任何玩法数值,不改 `.tres` 表值。MC 与 verifier 零跑(无数值改动零跑)。 - -## 5 范围边界 - -做:3.1 四段分支+穿线键+`_discount_shift_up`;3.2 两处词表摘名;3.3 注释面 43 处;3.4 三处文案;3.5 一处 sim 死匹配;3.6 消费环 `armor_rewrite` 删而发射点留;T2 负域探针;T4 断言串随动。 - -不做,去向写明: - -| 不收件面 | 为什么不做 | 去向 | -|---|---|---| -| `EVENTS` 零订阅词普查(含 `armor_roll` 发射点去留) | 与「改写分支」不同轴,是事件词表整体普查 | 待办清单本批同登条目「效果通道与事件词的零现役普查」 | -| `effect_kinds`/渠道零现役清退(`cell_removal`、`mine_hit_halve`、`open_ticket` 的 `channel="reflect"` 行族) | 通道在册、有消费点、只缺数据行——判「删通道」要连同 schema 词、归因标识与拒绝文案整体裁 | 同上条目,与 iter52 孤儿函数清退批同族 | -| GDD 其余仍提退役内容名的句子(`systems/冒险循环/奇物.md`、`systems/战斗循环/地图战斗资源.md`、`术语表.md`、`00-游戏概念.md`、`03-内容规模.md`) | 属文档面用语,不属代码批 | 反哺点清单,文档批落文 | -| `game/tests/unit/core/treasure_items_test.gd:31/33/35` 三个退役件名夹具 | StubDB 自造行,不宣称该件现役;改名动的是测试面 | 无——保留 | -| `attack_segments` 词表补摘 | 已随甲案退役,本批只在 GDD 订正错句 | 无——已完成 | -| 结算明细标签是否入表(文案硬编码在 `:226`) | 涉及「呈现文案归属」规范裁决,不属本卡 | 反哺点清单,文档批裁 | - -## 6 关联文档同步面 - -| 文档 | 关联点 | 同步义务 | -|---|---|---| -| `design/gdd/systems/跨局循环/锻造工坊.md` §满级特效扩展位 | 闭集词数句、长枪候选代价档、重甲候选代价档、七条前提句 | **已在本批前置文档段落文**(v0.13);实现批禁再写该文件 | -| `design/gdd/systems/跨局循环/锻造工坊.md` 同节 | 重甲反震候选的实现前提:反弹需新开消费点(本批摘 `spike` 后彻底无位) | 设计权威文档,实现批不直改;写入 `reports/<迭代号>-反哺点-<日期>.md`,用户裁后归文档批 | -| `design/gdd/systems/战斗循环/增益状态.md`/`伤害与护甲.md` | 若其中叙述「改写族四拍」的句子里挂了退役件名 | 机械面核对;有则列反哺点,无则实现报告记「零命中」 | -| `game/tests/README.md` 能力表 | 本批无新增能力、无能力退役;T2 探针挂既有行「加载期违规表拒绝:跨表悬空/计数器前缀/真视窄域/效果类型出域」(:177,代表用例含 `effect_kind_retired_test.gd:_assert_rejected`) | 无改动义务;批末核对表上名字与落地一致 | -| `待办清单.md`/`roadmap.md` | 条目状态与迭代行 | 由写卡段与编排段推进,实现批禁写 | - -## 7 任务卡 - -### 文件结构图 - -| 文件 | 职责 | 改动性质 | -|---|---|---| -| `game/core/damage_controller.gd` | 主角/敌方伤害结算编排 | 非行为改动(摘不可达分支+注释改写)→ 对照表 R1、R4 | -| `game/core/effect_engine.gd` | 效果词表与行校验 | 非行为改动(摘词两枚+注释改写)→ R2、R3、R4 | -| `game/tests/unit/data_config/effect_kind_retired_test.gd` | 负域加载探针宿主 | 新增两个探针常量与两次调用(非行为改动的取证面)→ R2、R3 | -| `game/core/reward_grant.gd` | 奖励与格面兑付 | 行为改动(一处明细行标签+一处拒绝 reason 文案)→ R5、R6 | -| `game/tests/unit/core/meta_progression_forge_test.gd` | 元进度/锻造断言宿主 | 断言串随 R5 换代(申报见第 8 节)→ R5 | -| `game/sim/level_autoplay.gd` | autoplay 驱动件 | 非行为改动(删恒 false 匹配+注释)→ R4、R8 | -| `game/core/settlement/grant_segment.gd` | 授予段结算编排 | 行为改动(`:166` 明细标签文本)→ R7;注释面 10 行改写 → R4 | -| `game/core/reward_roller.gd`、`game/core/battle_orchestrator.gd`、`game/core/action_economy.gd`、`game/data/schemas/treasure_item_table.gd`、`game/sim/adventure_monte_carlo.gd`、`game/tests/unit/battle_settlement/variant_placement_test.gd` | 注释面 | 非行为改动(注释改写)→ R4 | - -零新增文件、零新增函数、零新增数据件;唯一的"新增"是既有套件内的两个探针常量。 - -### T0 基线与读数对账(0.25 工作日) - -取用:无。产出:改前基线三件——对拍转储、S13 键读数、契约 1 三条 grep 读数。 - -- [ ] 跑契约 1 三条 grep,逐条把命中数写进实现报告 T0 节(期望全 0,除 `feats.tres:854` 的 `clamp_bonus` 一行作对照记录)。 -- [ ] 读 `tools/gdstyle_baseline.txt` 内 `damage_controller.gd`/`effect_engine.gd`/`reward_grant.gd`/`level_autoplay.gd` 现登记键,抄进实现报告「存量触面」表(第 14 节要求只降不升)。 -- [ ] 采改前对拍基线:`game/sim/dump_battle.gd` 六组(L{1,2}×S{42,779401,779501},stdout 单流转储,先例=拆件批 T6 同参)。 -- [ ] 采改前明细行读数:`meta_progression_forge_test.gd:_smoke_tree_rules` 现断言串的完整文本抄进实现报告(T4 换代后的比对基准)。 - -### T1 摘四段死分支与穿线键(0.5 工作日) - -取用:T0 的契约 1 读数全零。产出:`_ctx_rewrites` 与 `_hero_attack_ctx` 的收窄返回键集(T2、T4 引用)。 - -- [ ] `damage_controller.gd`:删 `:297-302`(命中侧交换)、`:351-353`(增伤侧交换)、`:305-309`(免掷覆盖)、`:310-313` 置位块+`:368-372`(spike 倍乘)、`:320-323`(移档调用)与 `:623` 函数 `_discount_shift_up(discount: int, shift: int) -> int`。 -- [ ] 同文件:删 `clamp_hits` 收集后残留的 `shift` 局部变量、`ar_hits` 局部变量(发射调用 `:296` 保留但不接收返回值,见 3.6);`spike_ready` 键从 `:282`、`:325` 返回字典与 `:369` 消费处一并去除。 -- [ ] 收窄后的签名与键集照此,不得自创: - - `_ctx_rewrites(t: Dictionary, target: Dictionary, armor: String, matchup: String) -> Dictionary` 返回键集 = `{roll_read, threshold, crit, discount, clamp_hits}`。 - - `_hero_attack_ctx(t: Dictionary) -> Dictionary` 返回键集 = 现键集去掉 `spike_ready`(`:278-282` 其余键逐字保留)。 - - `_hero_attack_base_value(t: Dictionary, ctx: Dictionary) -> float` 签名不变,体内删两拍。 -- [ ] 头注与分节注释随删随改(`:249-254`、`:264-266`、`:285-290`、`:341-342`、`:368`):改写后的四拍叙事只剩「掷点折扣读数 → 克制点数」两拍,注释口径同步收窄(这条与 T3 同判据,禁再挂退役件名)。 -- [ ] 单元侧适配:`game/tests/unit/battle_settlement/damage_controller_test.gd`、`roll_multiplier_test.gd`、`game/tests/unit/contracts/system_contracts_test.gd` 跑一遍;3.6 已证零命中,若真出红,只改装配不改进判据,并把改动写进实现报告「实现决定记录」。 - -### T2 词表收窄与负域探针(0.5 工作日) - -取用:T1 摘除后的 `damage_controller.gd` 键集(探针只需构造表行,不引用控制器内部键)。产出:`effect_kind_retired_test.gd` 两枚新探针常量 `_assert_rejected` 新断言名(R2/R3 引用)。 - -- [ ] `effect_engine.gd:30` 摘出 `"spike"`(`EFFECT_KINDS` 实数 32→31);`:82` 摘出 `"trade_atk"`, `"trade_hit"`(`DO_KEYS` 19→17 项,实数以摘后 `grep` 行内计数为准)。 -- [ ] 同文件 `:452` 组合规则注释改为只列现役:「任意真族(任一命中即生效):`spawn_spell`。」;`:64`/`:65`/`:157` 注释改写并入 T3 判据面。 -- [ ] `game/tests/unit/data_config/effect_kind_retired_test.gd`:按既有形态新增两枚探针——`PROBE_SPIKE_MODE`(注入 `{"kind": "modify_ticket", "mode": "spike"}` 行的夹具目录)与 `PROBE_TRADE_KEY`(注入带 `trade_hit` 键的 do 字典)。各建一个 `user://` 夹具目录常量,沿用 `_inject(dir, probe)` 与 `_assert_rejected` 既有函数,不新建套件文件。 -- [ ] 断言名与尾缀:`_assert_rejected` 内新增两条检查——`"词表闭面:kind=spike 出域拒绝"` 与 `"do 键闭面:trade_hit 出域拒绝"`;该套件已在 `game/tests/run_all.gd:195` 负面清单在册(`expect=1`、`negative=true`),本步只加探针,不动在册条目与退出码判据。 -- [ ] 独立验证先行:只跑该套件(`godot --headless --path game --script res://tests/unit/data_config/effect_kind_retired_test.gd`)出绿,再并入全套。 - -### T3 注释面退役名改写(0.5–1 工作日,可切 T3a/T3b) - -取用:3.3 表逐行清单。产出:注释面 grep 零命中读数(对照表 R4)。 - -- [ ] 名单唯一来源=`design/content-archive/道具退役素材库.md` 两张表的「原名」列,现场解析;禁把 40 个名字复制成第二份清单文件(第 12 节唯一面)。 -- [ ] 逐处改写口径=「这段代码做什么、按什么序、取值从哪来」,内容名换成机制名。示例(禁照抄字句,只照抄口径): - - `:285` 「第一拍矿工重锤命中交换」→ 「命中判定减成换攻击增伤的交换位(现役零注册,随本批摘除后此句消亡)」——摘除后该注释整段随分支删除,改写只适用于 T1 未摘的 11 个文件行。 - - `reward_roller.gd:1` 「偏运硬币/board_skew 两路投影」→ 「订阅加权与 board_skew 两路投影」。 - - `grant_segment.gd:232` 「完美布防=本轮封印批全中」→ 「封印全中倍率=本轮 hit>0 且 miss==0 时」。 -- [ ] 判据 grep:改写后重跑 3.3 那条扫描,注释面命中数必须为 0;读数贴进实现报告。 -- [ ] 不碰第 5 节点名保留的三行夹具串。 - -### T4 玩家可见文案与死匹配(0.25 工作日) - -取用:T0 采到的改前明细行读数。产出:新标签文本(R5/R6 引用)。 - -- [ ] `reward_grant.gd:226` 标签 → `"挖掘惩罚减半(%d→%d)"`;同处归因串 `"effect_id": "nest_counter"` → `"nest_halve"`(依代码规范用语纪律清零退役名;该串全仓仅此一处、不进存档不读表,改动面=本行+测试匹配串随动)。 -- [ ] 同文件 `:183` 与 `:221` 注释随 T3 口径改写;`:189` reason → `"中立移除:3×3 区域内无可移除危险格(须未揭示且未封印)"`。 -- [ ] `game/core/settlement/grant_segment.gd:166` 明细标签 `"惊巢反制·反弹"` → `"反弹伤害"`,同处归因串 `"attune_nest_counter"` → `"attune_nest_halve"`;`channel == "reflect"` 判据与开单参数字典逐字不动(契约 3)。 -- [ ] `meta_progression_forge_test.gd`:`:694` 匹配串、`:697` 标签文案、`:699`/`:700` 期望串四处随动到新标签;判据仍绑 `step_row` 采集的 `display_name`,`nc_hit != ""` 与等值断言的强度不得降低。 -- [ ] `level_autoplay.gd:421` 恒 false 的 `contains("雷区图谱")` 条件与该分支一并删,`:415` 注释随删。 -- [ ] 窄测:`meta_progression_forge_test`、`round_flow_skill_pool_test`、`damage_controller_test`、`table_structure_guard_test` 四套跑绿。 - -### T5 产出物落位卡(0.25 工作日) - -- [ ] 轻闸全绿后、合并前写齐 `reports/<迭代号>-实现报告-<日期>.md`:各 T 卡状态、T0/T2/T3/T4 四条读数、契约 1 三条 grep、改前改后对拍逐位一致结论、实机目检总清单(本批目检项:结算明细行减半标签一眼可读、无退役件名突兀感——登记不阻塞)、遗留读数义务(零现役通道与零订阅事件词两件,已另登待办条目,见第 5 节)、实现决定记录。 -- [ ] `reports/<迭代号>-反哺点-<日期>.md`:第 6 节每条都要有落点,含「明细标签是否入表」这条规范裁决点。 -- [ ] 里程碑步出口跑一次全套闸(`tools/run_all_gates.sh --code`);波内出红只做出红最小单元最窄确认。 - -## 8 验证闸(改动—验收对照表) - -| # | 需求点(判据出处行锚) | 改动(文件:行) | 验收测试(名称+落点+尾缀) | 层级 | 真实入口 | 判据绑定面 | 能力行 | -|---|---|---|---|---|---|---|---| -| R1 | 摘四段不可达改写分支(锚 `design/engineering/code-conventions.md:15`) | `damage_controller.gd:297-302/305-309/310-313/351-353/368-372/320-323/623` | `damage_controller_test.gd:_run_recipe_sequence`;`roll_multiplier_test.gd:_smoke_armor_roll`;`round_flow_skill_pool_test.gd:_smoke_full_battle`+dump_battle 六组逐字节比对 | 单元+集成 | `BattleOrchestrator.begin_battle()` → 主角先手开单兑付全链 | `step_row` 明细行文本与 `outcome` 取值逐位=T0 基线;静态判据=契约 1 三条 grep 零注册+摘后键集 grep 零 `spike_ready`。**观测面局限申报**:零现役注册行使分支不可达,无法从真实入口造出命中;禁人为注入表行取证(全项目禁变异类测试) | 既有:伤害单据编排与回放;既有:伤害公式与掷点乘区;既有:轮内流与结算五段全序 | -| R2 | `EFFECT_KINDS` 摘 `spike`(锚 `design/engineering/code-conventions.md:15`) | `effect_engine.gd:30` | `effect_kind_retired_test.gd:_assert_rejected`(新断言「词表闭面:kind=spike 出域拒绝」,尾缀 `expect=1 negative=true`) | 单元(负面,独立进程) | `ConfigDB.load_tables()` → `EffectEngine.validate_trigger_row` | 出域错误载荷含 `effect_kinds 出域` 文案+进程退出码 1 | 既有:加载期违规表拒绝:跨表悬空/计数器前缀/真视窄域/效果类型出域 | -| R3 | `DO_KEYS` 摘 `trade_hit`/`trade_atk`(锚 `design/engineering/code-conventions.md:15`) | `effect_engine.gd:82` | `effect_kind_retired_test.gd:_assert_rejected`(新断言「do 键闭面:trade_hit 出域拒绝」) | 单元(负面,独立进程) | `ConfigDB.load_tables()` → `EffectEngine.validate_trigger_row` | 键出域拒绝错误载荷含 `trade_hit`+进程退出码 1 | 既有:加载期违规表拒绝:跨表悬空/计数器前缀/真视窄域/效果类型出域 | -| R4 | 注释面退役名清零 13 文件 42 行(锚 `design/engineering/code-conventions.md:26`) | 3.3 表全部注释行号 | 静态判据:3.3 那条扫描命令注释面命中 0,读数贴实现报告;`--code` 域内静态扫描与 S11 段不变红;宿主既有套件逐位不变 | 静态(闸件扫描) | `BattleOrchestrator.begin_battle()` 链上宿主套件(改写面不进运行期) | 逐文件 grep 读数(文件名+行号+命中 0)+宿主套件回归 | 既有:换图系刷新链路与效果词表接线;既有:伤害单据编排与回放 | -| R5 | 减半明细行去退役件名(锚 `design/engineering/doc-conventions.md:47`) | `reward_grant.gd:226` | `meta_progression_forge_test.gd:_smoke_tree_rules`(换代断言串,落点 694/697/699/700) | 集成(信号采集) | 锻造锋线满级特效 → `BattleOrchestrator.begin_battle()` → `mine_hit` 减半路径 → `step_row` 信号 | `step_row` 行 `display_name` == 「挖掘惩罚减半(6→3)」,且 `power` 减半数值与发射次数逐字不变;`grep -r nest_counter game/` 零命中 | 既有:天赋树购买与六键合成 | -| R6 | 空集拒绝 reason 去退役件名(锚 `design/engineering/test-conventions.md:116`) | `reward_grant.gd:189` | 静态判据:`grep -c 爆破工兵包 game/core/reward_grant.gd` == 0;`table_structure_guard_test.gd` 与 `extended_row_violation_test.gd:_init` 跑绿 | 静态+单元 | `ConfigDB.load_tables()` → `_cell_removal_open` 所在兑付链(零现役行不可达) | grep 零命中读数+通道校验面绿。**观测面局限申报**:`cell_removal` 零现役行,reason 不可达,禁造行取证 | 既有:加载期违规表拒绝:跨表悬空/计数器前缀/真视窄域/效果类型出域 | -| R7 | 反弹明细标签去退役件名(锚 `design/engineering/doc-conventions.md:47`) | `grant_segment.gd:166` | 静态判据:`grep -rc "惊巢反制·反弹" game/` == 0 且 `grep -rc "attune_nest_counter" game/` == 0;`round_flow_skill_pool_test.gd:_smoke_full_battle` 跑绿 | 静态+集成 | `BattleOrchestrator.begin_battle()` → `mine_hit` 订阅施加链(`channel="reflect"` 二十一张表零命中,今天不可达) | grep 零命中+发射面零变化回归。**观测面局限申报**:同上,禁造行取证 | 既有:轮内流与结算五段全序 | -| R8 | sim 恒 false 匹配删除(锚 `design/engineering/test-conventions.md:116`) | `level_autoplay.gd:415/421` | 静态判据:`game/sim/` 全域 grep `雷区图谱` 零命中;`--code` 域内驱动件相关套件跑绿 | 静态+单元 | `game/sim/level_autoplay.gd` 驱动链(测量面,不进游戏运行) | grep 零命中+套件绿。**观测面局限申报**:恒 false 条件不可达,禁造行取证 | 既有:轮内流与结算五段全序 | - -测试方式两分法:R1/R2/R3/R5 归调试接口与真实入口断言;R6/R7/R8 三处的改动点今天不可达(零现役注册行驱动),一律走静态判据+观测面局限申报,禁造行取证,也不设目检;R5 的文本观感归用户目检——目检项「结算明细减半标签文本可读」写进实现报告总清单,登记不阻塞,不作合回前置。 - -闸口径:本批改动含 `game/` 下非 `.md` 行为载体 → 按 `tools/run_all_gates.sh --code` 选档,所选域全绿才合并;卡内不写死闸件名单。 - -回归措辞:里程碑步(T 段)出口跑一次全套闸;波内修复只做出红最小单元的最窄确认;新增探针先行孤立验证再并入全套。 - -测试削弱申报:唯一允许改的旧断言=`meta_progression_forge_test.gd:694/697/699/700` 四处期望串,理由是 R5 文案换代要求名实相符;断言强度(非空判定+等值判定+不含旧词)一条不降,阈值与扫描面不放宽。除此之外任何断言删除、阈值放宽、扫描面缩小都属未申报改动,独立验收审计判红。 - -独立验收审计:入口=合回前由未参与实现的会话或子代理执行,报告落 `reports/<迭代号>-验收审计-<日期>.md`;本档验收档=中,按 test-conventions §8.7 中档梯度核(R1/R2/R3/R5 四条必须逐条核到判据绑定面)。 - -## 9 异常分级 - -- L1 自救:注释措辞不通、局部变量名残留、grep 命令写法——就地改,不动判据。 -- L2 记录继续:T1 单元侧适配出现既有断言装配报错(3.6 已预判零命中),按申报范围改装配并记入实现报告「实现决定记录」。 -- L3 停机呈报并写报告: - 1. 契约 1 任一条 grep 读数非零(分支可达)=上游事实与卡片互斥,停卡退回写卡段。 - 2. 摘词后加载出现非预期致命(现役行被误判出域)或现役套件出红且原因落在本批摘除面。 - 3. 机检预算与卡片契约互斥(例:收窄后某函数键数低于登记值触发基线红/留空壳才能凑绿)=停卡退回写卡段,禁自造第三条路。 - 4. 按纪律无法干净摘除、必须保留中间壳函数才能过闸=停卡呈报走豁免/还债通道,禁硬拆凑绿。 - 5. R5 断言换代后仍红且原因在数值或发射序(说明文案改动越界)。 - -## 10 代拍板白名单 - -允许实现期自行拍板:注释改写的具体中文措辞(守契约 2 即可);负面探针常量与夹具目录命名(沿用既有形态);grep/扫描命令写法;是否把 T3 与 T4 并成一次提交;测试文件内局部变量改名;实现报告小节标题措辞。 -超出白名单=记入实现报告「实现决定记录」,不得静默。 - -## 11 待裁点 - -零待裁点,开工门=U0。(机制删留与注释口径已由用户在 2026-11-05 会话裁毕;GDD 四处错陈述已在写卡段前置文档段落文 v0.13;「明细标签是否入表」与三件遗留读数不属本卡执行面,已列第 5/6 节去向。) - -## 12 落位与可复用性预检 - -- 复用面:本批零新增文件。负域探针复用 `game/tests/unit/data_config/effect_kind_retired_test.gd` 既有 `_inject`/`_assert_rejected` 骨架——它正是「退役词出域即加载致命」的现成载体,新建套件=重复落点。注释改写复用既有文件与函数,无新 helper。 -- 唯一面:退役内容名清单的唯一来源=`design/content-archive/道具退役素材库.md`,判据脚本现场解析,禁在 `game/` 或 `tools/` 落第二份名单;摘词只改 `effect_engine.gd` 两处常量,`treasure_item_table.gd:20` 的注释属说明面(随 T3 改写),不另立词表。 -- 分层与交互面:`game/core/damage_controller.gd` 与 `game/core/effect_engine.gd` 的交互仍走既有 `_fx_hits` 查询口与 `validate_trigger_row` 校验口,本批只删消费环、不改接口;`reward_grant.gd` 文案改动不动 `emit_cb` 契约;`game/sim/` 驱动件不回连产品码。Core 零 UI、数值只经 ConfigDB、随机只经 RngService 三条红线本批一律不绕(本批不新增数值与随机消费)。 - -## 13 禁为机检文本保留无效成员 - -本卡为清退类:禁止为迎合机检消息文本或计数保留/新增任何无效成员、空壳函数、无用别名或 ctx 冗余键——`spike_ready`、`ar_hits`、`shift`、`trade_hit` 局部变量与 `_discount_shift_up` 一律随分支删净。机检键与本卡契约互斥时,实现段停卡呈报,不得自造第三条路。 - -## 14 实现规范预算 - -本批无新增文件,新件三查不适用;执行的是存量触面一查: - -- `game/core/damage_controller.gd`:T1 摘除使 `_ctx_rewrites` 与 `_hero_attack_base_value` 的分支数、函数长度下降;`_discount_shift_up` 整函数消亡。预期 S13 键只降不升,T0 抄录现登记值、T5 抄录摘后读数两张对照。 -- `game/core/effect_engine.gd`:两处常量字面量变短,方法数与成员变量数不变。 -- `game/core/reward_grant.gd`、`game/sim/level_autoplay.gd`:只删文本与一条恒 false 条件,分支数下降或持平。 -- 指标例外通道:本卡不申报任何例外——若摘除后仍有键超默认,属存量在册键,沿用 `tools/gdstyle_baseline.txt` 现登记,不新增。 - -## 15 拆分边界纪律 - -本卡是清退类,不产生拆出单元;条款照写以防实现期顺手重组: - -1. 若实现中确需拆出新私有函数或新段件,每个单元必须能写出一句职责陈述与单一变化原因,并逐件写进实现报告;写不出=凑计数袋,回炉。 -2. 「过阈值」只作发现信号,禁作为本批拆分或收拢的动机——本批唯一动机是零现役注册分支的清退。 -3. 按纪律无法干净摘除时停卡呈报走豁免/还债通道,禁硬拆凑绿(进第 9 节 L3 第 4 条)。 diff --git a/roadmap.md b/roadmap.md index ad76e8a7..91cf5666 100644 --- a/roadmap.md +++ b/roadmap.md @@ -5,8 +5,8 @@ ## 当前位(只回答「现在该做什么」;三行内随批次换代,禁止在此扩写成状态快照) - **阶段**:M3——Alpha 版本的完整实现(2026-10-09 立规:未明令宣布完成前停留 M3,迭代只排 M3 需求,M4 不排期;根目录 stage.txt 为旧阶段开关仅存档)。 -- **迭代位**:迭代 1–52 全部已完成;各迭代收口与批后收尾沿革查 git 提交信息与 `reports/`。 -- **下一步**:无已编迭代在飞——待编池:改写族孤儿(待处置方向裁决)、二三关棋盘观感(待设计+待美术)、EC8 热重载实装(待用户另立条目);测试面真输入化分期与存量断言逐条精锚(待执行,归下批编排)。 +- **迭代位**:迭代 1–53 全部已完成;各迭代收口与批后收尾沿革查 git 提交信息与 `reports/`。 +- **下一步**:无已编迭代在飞——待编池:效果通道与事件词零现役普查(待写卡)、结算明细文案入表(待文档设计)、二三关棋盘观感(待设计+待美术)、测试面真输入化分期与存量断言逐条精锚(待执行)、QA 覆盖总览面板与自动试玩扩展(待执行);EC8 热重载实装待用户另立条目。 ## 里程碑时间线 @@ -86,7 +86,7 @@ | 迭代 50 | 已完成(2026-11-03) | 已退役(git 历史可考) | 2026-11-03 | ≈12.875 个工作日〔用户特批 2026-11-03 超 10 个工作日〕 | 已退役(git 历史可考) | | 迭代 51 | 已完成(2026-11-04) | 已退役(git 历史可考) | 2026-11-04 | ≈6.625 个工作日 | 已退役(git 历史可考) | | 迭代 52 | 已完成(2026-11-05) | 已退役(git 历史可考) | 2026-11-04 | ≈9.275 个工作日 | 已退役(git 历史可考) | -| 迭代 53 | 待开工 | reports/需求卡片-卷轴视口批-2026-11-05.md
reports/需求卡片-改写族孤儿机制与退役名清退批-2026-11-05.md | 2026-11-05 | ≈6.0 个工作日 | — | +| 迭代 53 | 已完成(2026-11-06) | 已退役(git 历史可考) | 2026-11-05 | ≈6.0 个工作日 | 已退役(git 历史可考) | - 历史行的「—」= 该列事实不可考:迭代 1~8 早于需求卡片制;编排时点与预计周期不再回溯,细节查 git 提交史。 - 「已退役(git 历史可考)」= 需求卡片或实现报告曾存在,已按「证据只留最新」退役;已完成迭代的实现报告列只填 reports/ 现存路径或本保留字,不填「—」。 diff --git a/tools/capability_audit.py b/tools/capability_audit.py index 64dcb891..6cb4b237 100644 --- a/tools/capability_audit.py +++ b/tools/capability_audit.py @@ -132,6 +132,16 @@ def product_funcs(): return names +def probe_funcs(): + # 真实入口锚面补探针共用面(capability E 规则用):真输入合成沿(probe_ui_util 等探针 + # 共用件)写进能力行真实入口格后,卡片退役其凭证只能锚代码面——探针件定义与 D 规则 + # 同口径认锚(仍要求 func 真实存在,不属放宽)。 + names = set() + for p in (REPO / "game" / "probe").rglob("*.gd"): + names.update(re.findall(r"^(?:static\s+)?func\s+([A-Za-z_]\w*)\s*\(", read(p), re.M)) + return names + + def cards_corpus(): """reports/需求卡片*.md 全文拼接(双通道的「卡在」锚面);无卡返回空串。""" if not CARDS_DIR.is_dir(): @@ -266,7 +276,7 @@ def check_entry(no, name, cell, funcs, cards): for _, method in tokens: if method not in funcs and not (cards and method in cards): red(README.relative_to(REPO), no, "真实入口", - "「%s」方法 %s() 无凭证——产品码与 sim 测量件无定义且需求卡片未载" % (name[:16], method)) + "「%s」方法 %s() 无凭证——产品码、sim 测量件与探针件均无定义且需求卡片未载" % (name[:16], method)) def check_coverage(cov_tables, names): @@ -333,7 +343,7 @@ def main(): suites = manifest() if not suites: selfcheck.append("run_all.gd manifest 零套件") - funcs = product_funcs() + funcs = product_funcs() | probe_funcs() if not funcs: selfcheck.append("产品码零 `func`") names, referenced = check_capability_rows(cap_tables, suites, funcs, cards_corpus()) diff --git a/体验验证清单.md b/体验验证清单.md index b36f05a3..d066d596 100644 --- a/体验验证清单.md +++ b/体验验证清单.md @@ -508,3 +508,14 @@ | 1 | 三关封印格观感 | 环+十字+环外压暗光圈呈形正确、与格底可辨;像素判据已在机检承载,本项为观感复核 | | 2 | 战末金蜡封徽记观感 | 贴图路径未动(零预期变化)——观感确认项 | | 3 | 封印格与变异纹带同格观感 | 两层共存可辨、不脏面(零代码触面——观感确认项) | +## 52 卷轴视口与结算文案换代目检(迭代 53) + +> 关卡画面视口化(卷轴视口)与结算文案换代(减半标签)后,机检已覆盖行为与像素面(探针 26 断言+golden 两 Shot 逐像素+明细行等值断言),观感面按登记不阻塞立规不拦合并。 + +| # | 目检项 | 判据 | +|---|---|---| +| 1 | 深图卷轴视口实跑观感 | 深度 13+ 图拖拽平滑可达首末列;停点推进跟随方向感自然、当前节点居中锚即时;拖拽不误触选路 | +| 2 | 指引件观感 | 深图两侧渐隐带与顶部平移提示 chip 可辨、不碍选路;浅图两件均不出现 | +| 3 | 结算明细减半标签 | 「挖掘惩罚减半(6→3)」一眼可读,无退役件名突兀感 | + +- **结论回流**:观感问题归待办清单登记新条目;数值面不在目检现场改数。 diff --git a/待办清单.md b/待办清单.md index 4e6d90fb..8a7104d7 100644 --- a/待办清单.md +++ b/待办清单.md @@ -20,14 +20,15 @@ **状态**:待文档设计 -#### 超预算图策略升级路径——等比缩放与滚动视口两案待裁(2026-10-24 登记,来源=批次移交) +#### 结算明细文案入表——玩家可见明细文案归属改数据表承载(2026-11-06 登记,来源=批次移交) -**实况**:2026-11-05 用户裁滚动视口案落地(等比缩放案否决——像素纪律):关卡画面卷轴视口,跟随+拖拽+滚轮、平滑滚动(减动效瞬切)、当前节点居中锚;「图包络 ≤ 屏预算」约束退役,画布随图生长、规模归参数档。设计闭合凭据:design/gdd/ux/level-map.md v2.0(布局决策 5+视口效果图内嵌,2026-11-05 人审通过);design/gdd/systems/冒险循环/关卡节点图生成.md v1.5(参数契约节+图规模无呈现侧上限句)。需求卡片=reports/需求卡片-卷轴视口批-2026-11-05.md(grilling 复核裁决全落,验收档中)。 -- 相关文档:关卡节点图参数取值域已归数据 schema 层;schema 头注「域并单点=调参表」指针反转随实现批顺带(卡片随动项);需求卡片 reports/需求卡片-卷轴视口批-2026-11-05.md(grilling 复核裁决全落,验收档中)。 +**实况**:迭代 53 反哺点 4 归属裁决在案=文案入数据表行(2026-11-06 用户裁);规范句已落 [战斗结算](design/gdd/systems/战斗循环/战斗结算.md) v1.8 明细流水节(显示名等玩家可见文案=数据面字段,代码读表拼行、禁代码写死文案字串);现行代码硬编码面=结算明细扩展行标签文案(如减半标签,reward_grant.gd:226 一族)。 -**改动面**:文档 +**缺口**:还差表结构设计讨论——承载表与字段形态、基础行文案是否同批入表、读表拼行接线面。 -**状态**:文档设计已闭合+已写卡+已编迭代 53 +**改动面**:文档+游戏代码 + +**状态**:待文档设计 #### UI 贴图重构批——元进度件仍是程序化占位(2026-10-13 登记,来源=审计发现) @@ -234,17 +235,9 @@ ### 文档与结构 -#### damage_controller 按序改写族——内容孤儿机制与退役名注释层(2026-11-04 登记,来源=会话提及) - -**实况**:damage_controller.gd 按序改写族通用机制(trade_hit/trade_atk 交换、armor_rewrite 免掷、spike 满层必中与倍乘、discount_shift 轻甲改善——注释叙事 :285-290、改写执行 :291-325、增伤与倍乘 :350-353 与 :368-372)现役内容面仅淬毒刃纹一行 modify_ticket(mode=clamp_bonus,feats.tres:853-857):其余子分支零表行注册(全仓 grep 证)——「框架先行、内容未接」同族债。五拍注释全以旧 27 专长名叙事(矿工重锤/专注/厚积薄发/猎弱本能,道具退役素材库.md:43-47 退役在案);charge_layers 四处已归 EffectPort 蓄力层删键批(实现提交 ace15701)。2026-11-05 会话裁决=孤儿机制与退役名一律清退(口径「只要有问题的都要改」);同轮核出 spike 的 GDD 承接句站不住(候选条写「零新代码——spike 在册」,实为词面在册、全仓零派发点;长枪条同类——attack_segments 已随架构审查甲案退役),据此订正该节四处陈述。全仓扫=40 退役名命中 53 行/13 文件(注释面 42、字面量 11),逐处清单见卡片。关联文档:设计定稿=design/gdd/systems/跨局循环/锻造工坊.md v0.13(2026-11-05);需求卡片=reports/需求卡片-改写族孤儿机制与退役名清退批-2026-11-05.md - -**改动面**:游戏代码 - -**状态**:文档设计已闭合+已写卡+已编迭代 53 - #### 效果通道与事件词的零现役普查(2026-11-05 登记,来源=审计发现) -**实况**:证据=四条 grep 读数:`cell_removal` 通道在册(`game/data/schemas/treasure_item_table.gd:26`;消费点 `game/core/reward_grant.gd:160-161`)而 `game/data/` 全域零数据行;`mine_hit_halve` 同形态(仅 schema 词表与注记在位);`open_ticket` 的 `channel="reflect"` 行族零表行(21 张 `.tres` 逐张 grep);`armor_roll` 在 `game/core/effect_engine.gd:13` 事件词表在册、发射点 `game/core/damage_controller.gd:296`,而 `game/data/tables/feats.tres` 零订阅行。形态与架构审查甲案已清的 overflow/attack_segments 死通道同族(判据出处=`design/engineering/code-conventions.md:15`、`design/engineering/test-conventions.md:116`)。本批(需求卡片-改写族孤儿机制与退役名清退批)只清其文案与归因串,通道与事件词本体去留待普查批整体裁。 +**实况**:证据=四条 grep 读数:`cell_removal` 通道在册(`game/data/schemas/treasure_item_table.gd:26`;消费点 `game/core/reward_grant.gd:160-161`)而 `game/data/` 全域零数据行;`mine_hit_halve` 同形态(仅 schema 词表与注记在位);`open_ticket` 的 `channel="reflect"` 行族零表行(21 张 `.tres` 逐张 grep);`armor_roll` 在 `game/core/effect_engine.gd:13` 事件词表在册、发射点 `game/core/damage_controller.gd:296`,而 `game/data/tables/feats.tres` 零订阅行。形态与架构审查甲案已清的 overflow/attack_segments 死通道同族(判据出处=`design/engineering/code-conventions.md:15`、`design/engineering/test-conventions.md:116`)。改写族清退批(已合回,git 历史可考)只清其文案与归因串,通道与事件词本体去留待普查批整体裁。 **改动面**:游戏代码 @@ -260,8 +253,23 @@ #### QA 覆盖总览面板与自动试玩扩展——自动发现测试验证缺漏(2026-11-05 登记,来源=会话提及) -**实况**:方案全文=`D:\code\qa-harness-discussion\QA-Harness讨论结果-中间报告.md`(三批定案,全部三关试点):①探针存量 emit 真输入化(~40 处站点,承接上条)②B 覆盖总览面板+本体枚举器(六源回执明细化+能力清单提取+HTML 双击即开+游戏内容↔测试验证对账)③C 自动试玩扩展(auto_player 扩全动线全功能,异常上报含机器自填归因)。裁决在案勿重提:A 执行覆盖矩阵不做、D 缺口闸不做、变异测试禁入、归因登记不立独立制度。 +**实况**:方案全文=`D:\code\qa-harness-discussion\QA-Harness讨论结果-中间报告.md`(三批定案,全部三关试点);证据=真实入口缺口在册:能力行「营地七物件命中区点选与分界面可达」残险行 game/tests/README.md:158(emit 直发标「接线验证」、真输入承载待建)+test-conventions §8.3 真实入口判定口径条款(2026-11-05 收窄)。①探针存量 emit 真输入化(~40 处站点,承接上条)②B 覆盖总览面板+本体枚举器(六源回执明细化+能力清单提取+HTML 双击即开+游戏内容↔测试验证对账)③C 自动试玩扩展(auto_player 扩全动线全功能,异常上报含机器自填归因)。裁决在案勿重提:A 执行覆盖矩阵不做、D 缺口闸不做、变异测试禁入、归因登记不立独立制度。 **改动面**:游戏代码+工具代码+文档 **状态**:待执行 +#### 闸机超时守卫缺陷修复——gate_run_timeout 标志文件恒真(2026-11-06 登记,来源=批次移交) + +**实况**:tools/gate_platform.sh 的 gate_run_timeout 用 mktemp 预建超时标志文件,判据 `[ -f ]` 建时即真、超时态无法与正常完成区分(Windows Git Bash 实测直接调用 4 秒返回 124;远端各闸以工件锚定未受影响)。连带 tools/golden_baseline_refresh.sh 的 guard 子Shell sleep 420 未被 kill 短路(重采集等待 7 分钟症状)。修法=kf 先赋路径+rm -f 后置守卫(probe_gate.sh:97 run_suite 同款正确写法)。证据=tools/gate_platform.sh:37/:48+迭代53实现报告遗留呈报 1(git 历史可考)。 + +**改动面**:工具代码 + +**状态**:待执行 + +#### 关卡视口两 Shot 基线 mac 侧冻结(2026-11-06 登记,来源=批次移交) + +**实况**:golden/windows/ 已锚 lmap_entry/lmap_boss(提交 6394abf7);mac 子目录无该两 Shot——渲染闸对 mac 缺基线记 SKIP 不判红,两平台同盯缺一。义务=Mac 侧跑 tools/golden_baseline_refresh.sh --lmap 冻结 mac 基线并呈报确定性读数。证据=game/tests/golden/README.md 现持清单行与时效判定纪律行+迭代53实现报告遗留 2(git 历史可考)。 + +**改动面**:游戏代码 + +**状态**:待执行 From 03f0f1aa0d25207c43c921274414db8583497969 Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Fri, 6 Nov 2026 01:17:48 +0800 Subject: [PATCH 10/10] =?UTF-8?q?=E6=94=B6=E5=B0=BE(=E8=BF=BD=E7=BA=A2?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=C2=B7=E6=99=AE=E6=9F=A5=E6=9D=A1=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E6=9C=BA=E5=90=88=E8=A7=84):=20=E3=80=8C=E6=95=88?= =?UTF-8?q?=E6=9E=9C=E9=80=9A=E9=81=93=E4=B8=8E=E4=BA=8B=E4=BB=B6=E8=AF=8D?= =?UTF-8?q?=E7=9A=84=E9=9B=B6=E7=8E=B0=E5=BD=B9=E6=99=AE=E6=9F=A5=E3=80=8D?= =?UTF-8?q?=E6=9D=A1=E7=8A=B6=E6=80=81=E5=BE=85=E6=89=A7=E8=A1=8C=E4=B8=8D?= =?UTF-8?q?=E5=BE=97=E6=AE=8B=E7=95=99=E7=BC=BA=E5=8F=A3=E5=B1=9E=E6=80=A7?= =?UTF-8?q?=E2=80=94=E2=80=94=E9=81=97=E7=95=99=E5=BE=85=E8=A3=81=E5=8F=A5?= =?UTF-8?q?=E5=B9=B6=E5=9B=9E=E5=AE=9E=E5=86=B5(=E6=B5=81=E6=B0=B4?= =?UTF-8?q?=E7=BA=BF=E9=97=B8run86=E8=B5=B7=E7=AC=AC4=E7=BA=A2,=E6=99=AE?= =?UTF-8?q?=E6=9F=A5=E6=89=B9=E5=90=88=E5=85=A5=E5=B8=A6=E5=85=A5,?= =?UTF-8?q?=E6=9C=AC=E6=89=B9=E5=90=88=E5=9B=9E=E5=89=8D=E6=B8=85=E9=9B=B6?= =?UTF-8?q?);=20=E6=9C=AC=E6=AD=A5=E5=87=AD=E6=8D=AE:=20=E6=B5=81=E6=B0=B4?= =?UTF-8?q?=E7=BA=BF=E9=97=B8PASS?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 待办清单.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/待办清单.md b/待办清单.md index 8f566af5..d12e6d62 100644 --- a/待办清单.md +++ b/待办清单.md @@ -237,9 +237,7 @@ #### 效果通道与事件词的零现役普查(2026-11-05 登记,来源=审计发现) -**实况**:普查报告 reports/普查-效果通道与事件词零现役-2026-11-06.md——结论=内容层零孤儿、四词表+秘宝表 schema 旧词层全部属预留埋点(词面全保留零清退项;架构原则=词表先行内容后接)。叙述脱节 5 处已按「预留、未设计入表」口径订正(2026-11-06 用户令直改,冒烟 15 项 0 失败三闸全过)。 - -**缺口**:唯一遗留待裁=秘宝表 schema 旧词面 9 个「迁移完成」收尾(做不做、何时做)。 +**实况**:普查报告 reports/普查-效果通道与事件词零现役-2026-11-06.md——结论=内容层零孤儿、四词表+秘宝表 schema 旧词层全部属预留埋点(词面全保留零清退项;架构原则=词表先行内容后接)。叙述脱节 5 处已按「预留、未设计入表」口径订正(2026-11-06 用户令直改,冒烟 15 项 0 失败三闸全过)。唯一遗留待裁=秘宝表 schema 旧词面 9 个「迁移完成」收尾(做不做、何时做),待用户裁。 **改动面**:游戏代码