Files
gplan-2/game/tests/unit/data_config/level_gen_params_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

114 lines
6.1 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/data_config/level_gen_params_test.gd — 关卡节点图参数档单测(节点图生成器核心批 卡① T1/V2)
# 覆盖:生产表三行加载+validate 零违例、域校验逐类负向(出口 L1 恒 1/配比合计 1/层深下限/增幅变大/
# 岔口去路数锁定/键集闭集/键重复)、ConfigDB 访问器按 level_index 读回与缺行空字典。
# 运行:godot --headless --path game --script res://tests/unit/data_config/level_gen_params_test.gd(expect 0)
# 协议(tests/README):extends SceneTree + quit(code);负向用例资源直构不碰生产表。
extends SceneTree
const ConfigDBScript := preload("res://core/config_db.gd")
const LgpScript := preload("res://data/schemas/level_gen_params.gd")
const Kit := preload("res://tests/unit/test_kit.gd")
func _init() -> void:
# 判据出处: design/gdd/systems/表现与支撑/数据配置.md:198 参数档表装载与就绪态(装载组)
var db = ConfigDBScript.new()
var load_ok: bool = db.load_tables("res://data/tables", true)
Kit.check("生产 level_gen_params.tres 随全表加载 + validate 零违例〔fv2〕",
load_ok and db.diagnostics_count("error") == 0)
if load_ok:
_test_production(db)
_test_accessor()
_test_negative()
quit(Kit.finish("level_gen_params_test"))
func _row(L: int, layers: int, bd: float, ratios: Array, entry: int, exit_c: int, floor_n: int) -> Dictionary:
return {"level_index": L, "layers": layers, "branch_density": bd,
"battle_ratio": ratios[0], "reward_ratio": ratios[1], "rest_ratio": ratios[2], "shop_ratio": ratios[3],
"entry_count": entry, "exit_count": exit_c, "battle_floor": floor_n,
"fork_ways_min": 2, "fork_ways_max": 3,
"fork_third_way_pct": 35, "fill_rest_first_pct": 50, "width_max": 4}
func _table(rows: Array) -> Variant:
var t = LgpScript.new()
var typed: Array[Dictionary] = []
for r in rows:
typed.append(r)
t.rows = typed
return t
# ---- 生产三行正向(V2)----
func _test_production(db) -> void:
# 判据出处: design/gdd/systems/冒险循环/关卡节点图生成.md:127 产出合格:任意参数档产出的图必过产出约束(生产档组)
var r1: Dictionary = db.run.level_gen_params.row_by_level_index(1)
var r2: Dictionary = db.run.level_gen_params.row_by_level_index(2)
var r3: Dictionary = db.run.level_gen_params.row_by_level_index(3)
Kit.check("访问器读回 L1 行五旋钮齐备〔fv2〕",
int(r1.get("layers", 0)) == 6 and is_equal_approx(float(r1.get("branch_density", 0.0)), 0.3)
and int(r1.get("exit_count", 0)) == 1 and int(r1.get("entry_count", 0)) == 1)
Kit.check("访问器读回 L2/L3 行层深 9/13 递增〔fv2〕",
int(r2.get("layers", 0)) == 9 and int(r3.get("layers", 0)) == 13)
Kit.check("三行出口 = 1/2/3、战斗保底 = 4/6/8 与 §8.1 表对上〔fv2〕",
int(r1.get("battle_floor", 0)) == 4 and int(r2.get("exit_count", 0)) == 2
and int(r3.get("exit_count", 0)) == 3 and int(r3.get("battle_floor", 0)) == 8)
Kit.check("生产表 validate 零错误〔fv2〕", db.run.level_gen_params.validate().is_empty())
# ---- 访问器缺行防御 ----
func _test_accessor() -> void:
# 判据出处: design/gdd/systems/冒险循环/关卡节点图生成.md:127 参数档访问器读回与产出约束(访问器组)
var t = _table([_row(1, 6, 0.3, [0.5, 0.2, 0.2, 0.1], 1, 1, 4)])
Kit.check("row_by_level_index 缺行返回空字典〔fv2〕", t.row_by_level_index(9).is_empty())
# ---- 域校验逐类负向(V2)----
func _test_negative() -> void:
# 判据出处: design/gdd/systems/表现与支撑/数据配置.md:199 校验类别全覆盖:参数档 schema 拒绝(负向组)
# 合法基线三行
var base := [_row(1, 6, 0.3, [0.5, 0.2, 0.2, 0.1], 1, 1, 4),
_row(2, 9, 0.5, [0.5, 0.2, 0.15, 0.15], 2, 2, 6),
_row(3, 13, 0.7, [0.55, 0.15, 0.15, 0.15], 2, 3, 8)]
# ① L1 出口改 2 → 出口恒 1 断言红(负样本夹具)
var bad_l1_exit := [_row(1, 6, 0.3, [0.5, 0.2, 0.2, 0.1], 1, 2, 4), base[1], base[2]]
# ② 配比合计 0.5 → 合计 1 断言红(负样本夹具)
var bad_ratio := [_row(1, 6, 0.3, [0.2, 0.1, 0.1, 0.1], 1, 1, 4), base[1], base[2]]
# ③ 层深低于下限
var bad_layers := [_row(1, 5, 0.3, [0.5, 0.2, 0.2, 0.1], 1, 1, 4), base[1], base[2]]
# ④ 增幅未变大(6/9/11:Δ12=3、Δ23=2)
var bad_growth := [base[0], _row(2, 9, 0.5, [0.5, 0.2, 0.15, 0.15], 2, 2, 6),
_row(3, 11, 0.7, [0.55, 0.15, 0.15, 0.15], 2, 3, 8)]
# ⑤ 出口越上界(L3 出口 4)
var bad_exit := [base[0], base[1], _row(3, 13, 0.7, [0.55, 0.15, 0.15, 0.15], 2, 4, 8)]
# ⑥ 岔口去路数改 (2,4)
var bad_fork_row := _row(1, 6, 0.3, [0.5, 0.2, 0.2, 0.1], 1, 1, 4)
bad_fork_row["fork_ways_max"] = 4
# ⑦ 键集非闭集(多塞未知键)
var bad_keys_row: Dictionary = _row(1, 6, 0.3, [0.5, 0.2, 0.2, 0.1], 1, 1, 4)
bad_keys_row["mystery"] = 1
# 逐类负向表:[个案标签, 行集, 期望零错误]——每行仍逐案断言,消息带期望/实际与违例明细
var cases: Array = [
["合法三行域校验零错误(夹具自证)", base, true],
["L1 出口=2 被拒(出口 L1 恒 1 已锁)", bad_l1_exit, false],
["配比合计 0.5 被拒(四类合计 1 已锁)", bad_ratio, false],
["层深 5<6 被拒(层深下限已锁)", bad_layers, false],
["层深增幅倒挂被拒(递增且增幅变大)", bad_growth, false],
["出口 4 越域 [1,3] 被拒", bad_exit, false],
["岔口去路数 (2,4) 被拒(恒 2/3 已锁)", [bad_fork_row, base[1], base[2]], false],
["字段键集非 ROW_KEYS 闭集被拒", [bad_keys_row, base[1], base[2]], false],
["键重复行被拒", [base[0], base[0]], false],
["战斗保底 -1 被拒(≥0)", [_row(1, 6, 0.3, [0.5, 0.2, 0.2, 0.1], 1, 1, -1), base[1], base[2]], false],
["空表域校验零错误(合法态)", [], true],
]
for c in cases:
var errs: Array = _table(c[1]).validate()
var expect_label := "零错误" if c[2] else "有违例"
var actual_label := "零错误" if errs.is_empty() else "违例 %d 条 %s" % [errs.size(), str(errs)]
Kit.check("域校验:%s(期望%s,实际%s)〔fv2〕" % [c[0], expect_label, actual_label],
errs.is_empty() == c[2])