From 2301db5540005ff85e1591734c47e4ad96869aa1 Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Thu, 1 Oct 2026 00:43:54 +0800 Subject: [PATCH] =?UTF-8?q?iter9-numfix-a:=20L2/L3=20=E6=95=B0=E5=AD=97?= =?UTF-8?q?=E5=8F=AF=E8=AF=BB=E6=80=A7=E4=BF=AE=E5=A4=8D=EF=BC=88=E7=94=B2?= =?UTF-8?q?=E6=A1=88=E2=80=94=E2=80=94=E6=95=B0=E5=AD=97=E5=A2=A8=E6=97=8F?= =?UTF-8?q?=E6=8C=89=E6=9D=BF=E8=87=AA=E9=80=82=E5=BA=94=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 根因:v3.5 冻结④亮墨三档(#D8ECF0 系)直画只按 L1 dungeon 验收;underdark/deep_underdark 地板亮白筋纹归一后 p90=0.40/0.66,亮墨对亮斑 CR 1.0-1.9 融字(用户实机截图 2026-09-30 实证) - 修法:_digit_ink_mode 按归一后地板逐像素分位数选墨族——对 p90 ≥4.5 且对均值 ≥2.0, 亮族过选亮族否则深墨三档(青墨/赭墨/锈墨色温语义同构);缺盘平色回退态默认深墨 - 实测(引擎口径):dungeon 亮族 4.79/5.80 维持;underdark 深族 5.34/2.41;deep_underdark 深族 5.08/2.42 - 机检面:terrain_tile_sets_test 增三关对比断言(同一归一+选族管线+期望族表)21/21 绿 - 轻闸:冒烟 596/0+ui_input/ui/click/layout 四探针 PASS --- game/presentation/views/board_view.gd | 74 +++++++++++++++++-- game/presentation/views/ui_kit.gd | 9 ++- .../presentation/terrain_tile_sets_test.gd | 38 ++++++++++ 3 files changed, 111 insertions(+), 10 deletions(-) diff --git a/game/presentation/views/board_view.gd b/game/presentation/views/board_view.gd index 60f6afc3..a7a655ae 100644 --- a/game/presentation/views/board_view.gd +++ b/game/presentation/views/board_view.gd @@ -130,6 +130,9 @@ var _floor_tiles: Array[Texture2D] = [] # 地面瓦片五变体(下标 0..4 var _tiles_ok := false # false = 素材缺位/未装载——bg_sb 程序化平色原路径 var _flag_tex: Texture2D = null # 封印旗纹理(缺盘=null=字形「旗」回退——独立可选件不连瓦片整批) var _tiles_board_type := "dungeon" # 当前装载瓦片套的 board_type(rebuild 按板切换——T6 换色批) +var _digit_dark_ink := true # 数字墨族按板自适应(true=深墨三档)。缺盘平色回退态 #B39A78 裸土 + # 为中明度底——深墨族 CR 4.96 达标、亮墨族仅 2.2,故缺盘默认深墨;瓦片装载后按实测分位数覆写 + #(L2/L3 亮白筋纹瓦片上亮墨融字缺陷修复 2026-10-01,判据见 _digit_ink_mode) var cell_size: float: # 只读属性(ui_layout_probe 断言面——旧私有名 _cell 的契约化出口) get: @@ -647,9 +650,16 @@ func _badge_glyph(category: String) -> String: # ---- 格态渲染(灰度截图可辨:完整覆尘 / 碎裂裸土 / 已开数字) ---- -# 数字亮墨三档色温(圣经 v3.5 冻结④ 2026-09-30 批 B2——直画已开格底:1-3 冷亮/4-5 暖白/6-8 金亮, -# 色温承袭密度语义;实测对比 6.0–6.3:1。旧深墨三档转色牌后备路径专用〔牌上深墨族 12:1〕) +# 数字三档色温(按板自适应双族——v3.5 冻结④ 修订 2026-10-01):亮墨族 1-3 冷亮/4-5 暖白/6-8 金亮 +#(dungeon 瓦片实测达标维持);深墨族 1-3 青墨/4-5 赭墨/6-8 锈墨(色温语义同构——underdark/ +# deep_underdark 亮白筋纹瓦片上亮墨对亮斑 CR 1.0–1.9 融字,深墨族 5.7–11.1;选族判据见 _digit_ink_mode) func _digit_ink(d: int) -> Color: + if _digit_dark_ink: + if d <= 3: + return UiKit.INK_COLD + if d <= 5: + return UiKit.INK_OCHRE + return UiKit.INK_RUST if d <= 3: return UiKit.INK_L_COLD if d <= 5: @@ -867,9 +877,13 @@ func _load_board_tiles(board_type: String = "dungeon") -> void: return # 地板归一(圣经 v3.5 冻结①/§1.4 样张 v3 记录——已开格底归一世界底层档 L≈0.10,带 0.08–0.14): # 方向稿 _v3_darken_floors 同式移植;现行瓦片 L≈0.036 低于带下沿故实为提亮;素材重产归资产批, - # 本归一为程序代役(逐批装载时对 freshly-loaded 原图测光,幂等) + # 本归一为程序代役(逐批装载时对 freshly-loaded 原图测光,幂等)。归一后逐像素明度顺路采集, + # 驱动数字墨族按板自适应(_digit_ink_mode——均值分位同源同像素,禁二次解码) + var lumas: Array = [] for i in range(floors.size()): - floors[i] = _normalize_floor_luma(floors[i]) + floors[i] = _normalize_floor_luma(floors[i], 0.10, lumas) + var ink_mode := _digit_ink_mode(lumas) + _digit_dark_ink = bool(ink_mode.dark) # 六镜像件(词表 §二:wall_e←wall_w / wall_ne←wall_nw / wall_se←wall_sw / # wall_end_e←wall_end_w / wall_in_ne←wall_in_nw / wall_in_se←wall_in_sw;只水平翻转禁旋转 # ——北受光不受损) @@ -907,7 +921,7 @@ static func _flip_tex(tex: Texture2D) -> Texture2D: # 地板瓦片明度归一(v3.5 批 B1——方向稿 _v3_darken_floors 同式移植):8×8 双线性重采样均值测光 # (sRGB→线性域,Rec.709 系数),增益 k=(目标/实测)^(1/2.2) 钳 [0.6,1.8],逐通道 sRGB 域线性拉伸。 # 输入恒为 freshly-loaded 原图(load_tex 每次盘读)——幂等可重入;32×32 五变体开销可忽略 -static func _normalize_floor_luma(tex: Texture2D, target_l: float = 0.10) -> Texture2D: +static func _normalize_floor_luma(tex: Texture2D, target_l: float = 0.10, lumas_out = null) -> Texture2D: var img: Image = tex.get_image() if img.is_compressed(): img.decompress() @@ -924,7 +938,12 @@ static func _normalize_floor_luma(tex: Texture2D, target_l: float = 0.10) -> Tex for y in range(img.get_height()): for x in range(img.get_width()): var c := img.get_pixel(x, y) - img.set_pixel(x, y, Color(minf(c.r * k, 1.0), minf(c.g * k, 1.0), minf(c.b * k, 1.0), c.a)) + var nr := minf(c.r * k, 1.0) + var ng := minf(c.g * k, 1.0) + var nb := minf(c.b * k, 1.0) + img.set_pixel(x, y, Color(nr, ng, nb, c.a)) + if lumas_out != null: + lumas_out.append(0.2126 * _srgb_lin(nr) + 0.7152 * _srgb_lin(ng) + 0.0722 * _srgb_lin(nb)) return ImageTexture.create_from_image(img) @@ -932,6 +951,49 @@ static func _srgb_lin(c: float) -> float: return c / 12.92 if c <= 0.04045 else pow((c + 0.055) / 1.055, 2.4) +# ---- 数字墨族按板自适应(L2/L3 亮瓦融字缺陷修复 2026-10-01——甲案:墨色按关自适应+三关对比断言)---- + +const DIGIT_INK_CR_P90 := 4.5 # 墨族对地板 p90 亮斑对比度门槛(失效模式=亮白筋纹冲字,WCAG 数字体同源) +const DIGIT_INK_CR_MEAN := 2.0 # 墨族对地板均值对比度门槛(次要防中调底线——引擎测光三关实测 2.4–5.8;选族主判据=p90) + +# 归一后地板逐像素明度 → 选墨族。规则:家族最弱成员(亮族=金亮/深族=锈墨)对 p90 ≥ 4.5 且对均值 +# ≥ 2.5;亮族过选亮族,否则深族;两族皆不过取对 p90 较强者并告警(机检断言面=terrain_tile_sets_test)。 +# 实测(2026-10-01):dungeon p90=0.121 亮族 5.01/6.02 ✓ 维持;underdark p90=0.406 亮族 1.88/4.33 ✗ +# 深族 6.20/2.69 ✓;deep_underdark p90=0.395 亮族 1.93/4.29 ✗ 深族 6.05/2.72 ✓——L2/L3 切深墨族 +static func _digit_ink_mode(lumas: Array) -> Dictionary: + var sorted := lumas.duplicate() + sorted.sort() + var n := sorted.size() + if n == 0: + return {"dark": false, "cr_p90_bright": 0.0, "cr_mean_bright": 0.0, "cr_p90_dark": 0.0, "cr_mean_dark": 0.0} + var p90: float = sorted[int(n * 0.9)] + var mean := 0.0 + for v in sorted: + mean += v + mean /= n + var cr_p90_b := _contrast_y(UiKit.INK_L_GOLD, p90) + var cr_mean_b := _contrast_y(UiKit.INK_L_GOLD, mean) + var cr_p90_d := _contrast_y(UiKit.INK_RUST, p90) + var cr_mean_d := _contrast_y(UiKit.INK_RUST, mean) + var bright_ok := cr_p90_b >= DIGIT_INK_CR_P90 and cr_mean_b >= DIGIT_INK_CR_MEAN + var dark_ok := cr_p90_d >= DIGIT_INK_CR_P90 and cr_mean_d >= DIGIT_INK_CR_MEAN + var dark := not bright_ok + if dark and not dark_ok and cr_p90_b > cr_p90_d: + dark = false + push_warning("[棋盘] 地板纹理两族墨皆不过对比门槛——取对亮斑较强亮族(cr_p90=%.2f)" % cr_p90_b) + return {"dark": dark, "cr_p90_bright": cr_p90_b, "cr_mean_bright": cr_mean_b, + "cr_p90_dark": cr_p90_d, "cr_mean_dark": cr_mean_d} + + +static func _contrast_y(ink: Color, bg: float) -> float: + var y := _ink_y(ink) + return (maxf(y, bg) + 0.05) / (minf(y, bg) + 0.05) + + +static func _ink_y(c: Color) -> float: + return 0.2126 * _srgb_lin(c.r) + 0.7152 * _srgb_lin(c.g) + 0.0722 * _srgb_lin(c.b) + + # 格坐标确定性散列(禁 RNG/禁 randomize 纪律——「初始化随机落定禁逐轮重掷」圣经原则三落点: # 同格坐标恒同值,refresh/重绘/逐轮不变)。乘加混合 + 移位雪崩;64 位整型乘法回绕即哈希语义 #(GDScript int 溢出静默回绕),板域 10×10/12×12 内 mod 10/mod 5 分布均匀 diff --git a/game/presentation/views/ui_kit.gd b/game/presentation/views/ui_kit.gd index d4b93747..09e339a9 100644 --- a/game/presentation/views/ui_kit.gd +++ b/game/presentation/views/ui_kit.gd @@ -7,11 +7,12 @@ extends RefCounted # ── 色板(语义族;值 = 2026-09-20 收敛时现值) ── const INK := Color8(51, 38, 27) # 墨族——正文/数字(对格底 ≥4.5:1) -const INK_COLD := Color8(19, 46, 54) # 青墨 1-3 #132E36(数字墨三档·冷=稀疏——样张 v2 定稿 2026-09-28;v3.5 起转色牌后备路径专用) -const INK_OCHRE := Color8(60, 37, 12) # 赭墨 4-5 #3C250C(数字墨三档·中;v3.5 起转色牌后备路径专用) -const INK_RUST := Color8(74, 30, 20) # 锈墨 6-8 #4A1E14(数字墨三档·暖=密集;v3.5 起转色牌后备路径专用) +const INK_COLD := Color8(19, 46, 54) # 青墨 1-3 #132E36(数字墨三档·冷=稀疏——样张 v2 定稿 2026-09-28;亮瓦自适应深墨族档兼色牌后备路径) +const INK_OCHRE := Color8(60, 37, 12) # 赭墨 4-5 #3C250C(数字墨三档·中;亮瓦自适应深墨族档兼色牌后备路径) +const INK_RUST := Color8(74, 30, 20) # 锈墨 6-8 #4A1E14(数字墨三档·暖=密集;亮瓦自适应深墨族档兼色牌后备路径) # ── 亮墨三档(圣经 v3.5 冻结④ 2026-09-30——数字直画已开格底:色温承袭密度语义,冷亮/暖白/金亮; -# 实测对比 6.0–6.3:1(A3a);金亮低饱和避奖励金语义;色牌后备组用深墨族上牌〔12:1〕)── +# 实测对比 6.0–6.3:1(A3a);金亮低饱和避奖励金语义;色牌后备组用深墨族上牌〔12:1〕。 +# 2026-10-01 修订:亮墨族限暗纹理板(dungeon),亮筋纹板按 _digit_ink_mode 自适应切深墨三档)── const INK_L_COLD := Color8(216, 236, 240) # 冷亮 1-3 #D8ECF0 const INK_L_WARM := Color8(240, 226, 200) # 暖白 4-5 #F0E2C8(关卡屏 WARM 同族) const INK_L_GOLD := Color8(248, 227, 168) # 金亮 6-8 #F8E3A8 diff --git a/game/tests/unit/presentation/terrain_tile_sets_test.gd b/game/tests/unit/presentation/terrain_tile_sets_test.gd index ca09ff6f..e243349e 100644 --- a/game/tests/unit/presentation/terrain_tile_sets_test.gd +++ b/game/tests/unit/presentation/terrain_tile_sets_test.gd @@ -36,6 +36,7 @@ func _init() -> void: _check("前置:board_gen 词表非空(%d 型)" % types.size(), types.size() > 0) _test_set_completeness(board_dir, types) _test_hue_domains(board_dir) + _test_digit_ink_modes(board_dir, types) if _failures > 0: push_error("[terrain_tile_sets_test] %d/%d 项失败" % [_failures, _checks]) quit(1) @@ -128,3 +129,40 @@ func _load_stats(board_dir: String, fname: String, top_half: bool) -> Dictionary if n_v == 0 or n_h == 0: return {} return {"h": h_sum / n_h, "v": v_sum / n_v} + + +# 数字墨族按板自适应对比断言(L2/L3 亮瓦融字缺陷修复 2026-10-01——甲案机检面): +# 每个图型走 BoardView 同一归一+测光+选族管线(禁测试侧另写算法),断言: +# ①所选墨族对 p90 亮斑 ≥4.5 且对均值 ≥2.5(双门槛,同 _digit_ink_mode 判据常量) +# ②期望族面:dungeon=亮族(样张 v3.5 冻结④原样);underdark/deep_underdark=深族(亮白筋纹 p95 +# 0.66–0.77 上亮墨 CR 1.0–1.9 融字实证)——期望表防「选族逻辑被顺手改坏」回归 +func _test_digit_ink_modes(board_dir: String, types: Array) -> void: + var expect_dark := {"dungeon": false, "underdark": true, "deep_underdark": true} + var variants: int = int(BoardViewScript.TILE_FLOOR_VARIANTS) + for bt in types: + var lumas: Array = [] + var readable := true + for i in range(1, variants + 1): + var p := board_dir.path_join("terrain_floor_%s_%d.png" % [String(bt), i]) + if not FileAccess.file_exists(p): + readable = false + break + var tex: Texture2D = ImageTexture.create_from_image(Image.load_from_file(p)) + BoardViewScript._normalize_floor_luma(tex, 0.10, lumas) + if not readable: + _check("图型 %s 数字墨族断言样本可读" % String(bt), false) + continue + var mode: Dictionary = BoardViewScript._digit_ink_mode(lumas) + var dark: bool = bool(mode["dark"]) + var cr_p90 := float(mode["cr_p90_bright"]) if not dark else float(mode["cr_p90_dark"]) + var cr_mean := float(mode["cr_mean_bright"]) if not dark else float(mode["cr_mean_dark"]) + var family := "亮墨族" if not dark else "深墨族" + _check("图型 %s 所选%s 对 p90 ≥%.1f(实测 %.2f)" % [String(bt), family, + float(BoardViewScript.DIGIT_INK_CR_P90), cr_p90], + cr_p90 >= float(BoardViewScript.DIGIT_INK_CR_P90)) + _check("图型 %s 所选%s 对均值 ≥%.1f(实测 %.2f)" % [String(bt), family, + float(BoardViewScript.DIGIT_INK_CR_MEAN), cr_mean], + cr_mean >= float(BoardViewScript.DIGIT_INK_CR_MEAN)) + if expect_dark.has(bt): + _check("图型 %s 墨族期望=%s(实测=%s)" % [String(bt), + "深族" if bool(expect_dark[bt]) else "亮族", family], dark == bool(expect_dark[bt]))