Files
gplan-2/game/tests/unit/presentation/terrain_tile_sets_test.gd
T
DKChan 9f21236f80 工程(注释标记词换代·oracle→判据出处): 用户 2026-11-07 令——判据出处注记的标记词改用项目已有中文名,避免 Oracle 被读成数据库。注释格式句、机检正则、标识符、卡片与登记同步换代;零行为改动。
改动面 112 文件 572+/572-:game/tests/** 与 game/probe/** 共 106 件 545 行 `# oracle:`→`# 判据出处:`;tools/capability_audit.py 正则字面量换中文+ORACLE_*→CRITERION_*/check_oracle_markers→check_criterion_markers/oracle_marked(flagged)→criterion_* 共 11 行;test-conventions.md:119 格式句+:155 措辞;待办清单与需求卡片-QA覆盖余量收口批各 1 处字面量;coverage_enum.py:21 与 camp_scene_layout_test.gd:101 旁支措辞;ui_click_probe.gd 对拍局部变量 oracle→expected 7 处;auto_player.gd 三处 safe_set 真值措辞。不动:历史审计报告两份、test-oracle-anchor 分支名、git 史、生成日志;指针格式/扫描面/判红条件/验收义务全不变。

读数(区内实跑):改前 capability_audit --strict「417 注记函数·红项 0」→改后「417 判据出处注记函数·红项 0」exit=0;新标记 545 行/106 文件,现行义务面 oracle 残留 0(在册沿革除外);diff 自检 game/ 非注释新增行仅 6 行且全在 ui_click_probe.gd 的 expected 变量段;112 改动文件 CRLF=0;py_compile tools/capability_audit.py OK;--docs exit=0【验收通过】无新增红;--gates exit=0(静态扫描绿、闸壳 bash -n ×13 失败 0)。
2026-11-07 07:11:15 +08:00

164 lines
8.2 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# tests/unit/presentation/terrain_tile_sets_test.gd — 瓦片换色机检(T6 卡交付:色相域抽检+套完整性)
# 运行:godot --headless --path game --script res://tests/unit/presentation/terrain_tile_sets_test.gd
# 事实源:board_gen.tres board_type 词表 v1.1(dungeon/underdark/deep_underdark——从表读值,禁写死);
# 色相域方向 = art-bible §4.3 三关方向(underdark 灰白蓝紫 / deep_underdark 蓝黑紫黑);
# 图底分离 = 圣经 §8.5(已开地面明度低于未开墙体)。
# 前置守卫:素材不入 git——fresh checkout 无瓦片文件时本套件跳过(打印注记,不红);
# 源 dungeon 套在盘而换色套缺位 = 回归(换色脚本在库可复现)。
extends SceneTree
const ConfigDBScript := preload("res://core/config_db.gd")
const TilePaletteScript := preload("res://presentation/views/tile_palette.gd")
const Kit := preload("res://tests/unit/test_kit.gd") # T6 收口:_check/汇总退出样板单点
func _init() -> void:
# 判据出处: design/gdd/systems/表现与支撑/HUD框架.md:260 (地形瓦片套宿主——装载组)
var board_dir := ProjectSettings.globalize_path("res://assets/art/board/")
var probe_path := board_dir.path_join("terrain_wall_center_dungeon.png")
if not FileAccess.file_exists(probe_path):
print("[terrain_tile_sets_test] SKIP——素材工作区缺位(瓦片不入 git 纪律,fresh checkout 预期态)")
quit(0)
return
var db = ConfigDBScript.new()
var load_ok: bool = db.load_tables("res://data/tables", true)
Kit.check("前置:表加载零 error", load_ok and db.diagnostics_count("error") == 0)
if not load_ok:
quit(1)
return
# board_type 词表自 board_gen 行集推导(禁测试侧写死词表)
var types: Array = []
for row in db.combat.board_gen.rows:
var bt := String(row.get("board_type", ""))
if bt != "" and not types.has(bt):
types.append(bt)
Kit.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)
quit(Kit.finish("terrain_tile_sets_test"))
# 套完整性:词表每个 board_type 的 16 墙 + 5 地面变体全部在盘(缺位 → BoardView 整批回落 dungeon 的
# 缺位回退断言由 ui_input_probe 覆盖;本断言管「入包完整」面)
func _test_set_completeness(board_dir: String, types: Array) -> void:
# 判据出处: design/gdd/systems/表现与支撑/HUD框架.md:260 (瓦片套完整性组)
var wall_names: Array = TilePaletteScript.TILE_WALL_NAMES
var variants: int = int(TilePaletteScript.TILE_FLOOR_VARIANTS)
for bt in types:
var missing: Array = []
for w in wall_names:
var p := board_dir.path_join("terrain_%s_%s.png" % [String(w), String(bt)])
if not FileAccess.file_exists(p):
missing.append(String(w))
for i in range(1, variants + 1):
var pf := board_dir.path_join("terrain_floor_%s_%d.png" % [String(bt), i])
if not FileAccess.file_exists(pf):
missing.append("floor_%d" % i)
Kit.check("图型 %s 瓦片套完整(16 墙 + %d 地面,缺=%s)" % [String(bt), variants, str(missing)], missing.is_empty())
# 色相域抽检:wall_center 上半幅(墙顶面)与 floor_1 全幅的均值色相/明度
func _test_hue_domains(board_dir: String) -> void:
# 判据出处: design/gdd/systems/表现与支撑/HUD框架.md:260 地形瓦片色相域(色相域组)
var bands := {
"dungeon": [0.02, 0.16], # 暖石棕 ≈15°–58°
"underdark": [0.50, 0.72], # 灰白蓝紫 ≈180°–260°
"deep_underdark": [0.55, 0.78], # 蓝黑紫黑 ≈200°–280°
}
var wall_v := {}
var floor_v := {}
for bt in bands.keys():
var wall := _load_stats(board_dir, "terrain_wall_center_%s.png" % String(bt), true)
var floor_img := _load_stats(board_dir, "terrain_floor_%s_1.png" % String(bt), false)
if wall.is_empty() or floor_img.is_empty():
Kit.check("图型 %s 抽检样本可读" % String(bt), false)
continue
wall_v[bt] = float(wall["v"])
floor_v[bt] = float(floor_img["v"])
var band: Array = bands[bt]
Kit.check("图型 %s 墙顶均值色相在带 %s(实测 %.3f)" % [String(bt), str(band), float(wall["h"])],
float(wall["h"]) >= float(band[0]) and float(wall["h"]) <= float(band[1]))
Kit.check("图型 %s 图底分离(墙顶明度 %.3f > 地面 %.3f)" % [String(bt), wall_v[bt], floor_v[bt]],
wall_v[bt] > floor_v[bt])
if wall_v.has("underdark") and wall_v.has("deep_underdark"):
Kit.check("deep_underdark 墙顶更暗于 underdark(更深蓝黑方向)", float(wall_v["deep_underdark"]) < float(wall_v["underdark"]))
# 均值读数:hue 取饱和度 > 0.05 的像素(墨线/灰黑不影响色相均值);v 取全幅均值
func _load_stats(board_dir: String, fname: String, top_half: bool) -> Dictionary:
var p := board_dir.path_join(fname)
if not FileAccess.file_exists(p):
return {}
var img := Image.load_from_file(p)
if img == null:
return {}
if img.is_compressed():
img.decompress()
var w := img.get_width()
var h := img.get_height()
var y0 := 0
var y1 := h
if top_half:
y1 = h / 2 # 墙顶面 = 上半幅(立面暗带不参与色相均值)
var h_sum := 0.0
var v_sum := 0.0
var n_h := 0
var n_v := 0
for y in range(y0, y1):
for x in range(w):
var c := img.get_pixel(x, y)
v_sum += c.v
n_v += 1
if c.s > 0.05:
h_sum += c.h
n_h += 1
if n_v == 0 or n_h == 0:
return {}
return {"h": h_sum / n_h, "v": v_sum / n_v}
# 数字呈现模式对比断言(L2/L3 亮瓦融字缺陷的甲案机检面,v3.4 扩三态):
# 每个图型走 BoardView 同一归一+测光+选模式管线(禁测试侧另写算法),断言:
# ①dungeon=亮墨族直画(对 p90 ≥4.5 且对均值 ≥2.5);②underdark/deep_underdark=色牌垫底
# (双峰纹理直画不可救——渲染帧取证深墨隐形实证,牌上深墨 12:1);③直画模式的双门槛值照抄
# TilePalette 判据常量(防判据漂移)
func _test_digit_ink_modes(board_dir: String, types: Array) -> void:
# 判据出处: design/gdd/systems/表现与支撑/HUD框架.md:260 (数字墨色模式组)
var expect_plate := {"dungeon": false, "underdark": true, "deep_underdark": true}
var variants: int = int(TilePaletteScript.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))
TilePaletteScript.normalize_floor_luma(tex, 0.10, lumas)
if not readable:
Kit.check("图型 %s 数字墨族断言样本可读" % String(bt), false)
continue
var mode: Dictionary = TilePaletteScript.digit_ink_mode(lumas)
var plate: bool = bool(mode["plate"])
var dark: bool = bool(mode["dark"])
var mode_name := "色牌垫底" if plate else ("深墨族直画" if dark else "亮墨族直画")
if plate:
Kit.check("图型 %s 双峰纹理落牌(亮族 p90 %.2f/均值 %.2f,深族 p90 %.2f/均值 %.2f 均未过门)" % [
String(bt), float(mode["cr_p90_bright"]), float(mode["cr_mean_bright"]),
float(mode["cr_p90_dark"]), float(mode["cr_mean_dark"])],
float(mode["cr_mean_dark"]) < float(TilePaletteScript.DIGIT_INK_CR_MEAN_DARK))
else:
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"])
Kit.check("图型 %s 所选%s 对 p90 ≥%.1f(实测 %.2f)" % [String(bt), mode_name,
float(TilePaletteScript.DIGIT_INK_CR_P90), cr_p90],
cr_p90 >= float(TilePaletteScript.DIGIT_INK_CR_P90))
var mean_gate := float(TilePaletteScript.DIGIT_INK_CR_MEAN_BRIGHT) if not dark else float(TilePaletteScript.DIGIT_INK_CR_MEAN_DARK)
Kit.check("图型 %s 所选%s 对均值 ≥%.1f(实测 %.2f)" % [String(bt), mode_name, mean_gate, cr_mean],
cr_mean >= mean_gate)
if expect_plate.has(bt):
Kit.check("图型 %s 呈现模式期望=%s(实测=%s)" % [String(bt),
"色牌" if bool(expect_plate[bt]) else "直画", mode_name], plate == bool(expect_plate[bt]))