From fd6cf968dc6bf9b02cb2cbb53fb3a7a689a521a4 Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Wed, 28 Oct 2026 23:51:01 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B7=A5=E7=A8=8B(=E5=AD=98=E9=87=8F=E6=96=AD?= =?UTF-8?q?=E8=A8=80=E7=B2=BE=E7=AE=80=C2=B7C=E6=A1=A3=E6=89=B9):=20?= =?UTF-8?q?=E5=85=AD=E7=BB=84=E6=89=8B=E5=86=99=E6=96=AD=E8=A8=80=E6=97=8F?= =?UTF-8?q?=E6=94=B9=E8=A1=A8=E9=A9=B1=E5=8A=A8=E5=BE=AA=E7=8E=AF=E2=80=94?= =?UTF-8?q?=E2=80=9433=20=E9=9D=99=E6=80=81=E7=AB=99=E7=82=B9=E5=B9=B6?= =?UTF-8?q?=E4=B8=BA=207=EF=BC=8C=E6=B8=85=E5=8D=95=201587=E2=86=921561?= =?UTF-8?q?=EF=BC=8C=E8=BF=90=E8=A1=8C=E6=9C=9F=E6=9D=A1=E6=95=B0=E4=B8=8D?= =?UTF-8?q?=E5=8F=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - C1 level_gen_params 逐类负向 11→1(消息带期望/实际与违例明细);C2 rng_stream_boot 黄金向量 8→1;C3 player_copy 禁词族 3→1、2→1;C4 standee_fx 蓄力判据 4→1;C5 ui_font 字形集 3→1(缺字明细进消息);C6 forge_workbench 持有行 2→1(两行取谓词并集,轻甲行补两子句,只增不减) - 个案标签字面量全部保留在表内,失败定位不降级;冻结清单不动(对账基准 1587),extract_checks --diff=消失 33/新增 7,逐条对应删并申报表 - 用户裁决 2026-10-28:六组全批 --- .../unit/data_config/level_gen_params_test.gd | 37 ++++++++++--------- .../unit/data_config/rng_stream_boot_test.gd | 13 +++---- .../unit/presentation/forge_workbench_test.gd | 14 +++---- .../presentation/player_copy_sweep_test.gd | 10 ++--- .../presentation/standee_fx_sweep_test.gd | 18 +++++---- .../unit/presentation/ui_font_asset_test.gd | 17 +++++++-- 6 files changed, 59 insertions(+), 50 deletions(-) diff --git a/game/tests/unit/data_config/level_gen_params_test.gd b/game/tests/unit/data_config/level_gen_params_test.gd index d99beb67..dee8e2fa 100644 --- a/game/tests/unit/data_config/level_gen_params_test.gd +++ b/game/tests/unit/data_config/level_gen_params_test.gd @@ -69,37 +69,40 @@ func _test_negative() -> void: 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)] - Kit.check("合法三行域校验零错误(夹具自证)〔fv2〕", _table(base).validate().is_empty()) # ① 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]] - Kit.check("L1 出口=2 被拒(出口 L1 恒 1 已锁)〔fv2〕", not _table(bad_l1_exit).validate().is_empty()) # ② 配比合计 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]] - Kit.check("配比合计 0.5 被拒(四类合计 1 已锁)〔fv2〕", not _table(bad_ratio).validate().is_empty()) # ③ 层深低于下限 var bad_layers := [_row(1, 5, 0.3, [0.5, 0.2, 0.2, 0.1], 1, 1, 4), base[1], base[2]] - Kit.check("层深 5<6 被拒(层深下限已锁)〔fv2〕", not _table(bad_layers).validate().is_empty()) # ④ 增幅未变大(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)] - Kit.check("层深增幅倒挂被拒(递增且增幅变大)〔fv2〕", not _table(bad_growth).validate().is_empty()) # ⑤ 出口越上界(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)] - Kit.check("出口 4 越域 [1,3] 被拒〔fv2〕", not _table(bad_exit).validate().is_empty()) # ⑥ 岔口去路数改 (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 - Kit.check("岔口去路数 (2,4) 被拒(恒 2/3 已锁)〔fv2〕", - not _table([bad_fork_row, base[1], base[2]]).validate().is_empty()) # ⑦ 键集非闭集(多塞未知键) 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 - Kit.check("字段键集非 ROW_KEYS 闭集被拒〔fv2〕", - not _table([bad_keys_row, base[1], base[2]]).validate().is_empty()) - # ⑧ level_index 重复 - Kit.check("键重复行被拒〔fv2〕", not _table([base[0], base[0]]).validate().is_empty()) - # ⑨ 战斗保底负值 - Kit.check("战斗保底 -1 被拒(≥0)〔fv2〕", - not _table([_row(1, 6, 0.3, [0.5, 0.2, 0.2, 0.1], 1, 1, -1), base[1], base[2]]).validate().is_empty()) - # ⑩ 空表=合法态(沿 difficulty_table 先例) - Kit.check("空表域校验零错误(合法态)〔fv2〕", _table([]).validate().is_empty()) + # 逐类负向表:[个案标签, 行集, 期望零错误]——每行仍逐案断言,消息带期望/实际与违例明细 + 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]) diff --git a/game/tests/unit/data_config/rng_stream_boot_test.gd b/game/tests/unit/data_config/rng_stream_boot_test.gd index f3747bde..1943c7e9 100644 --- a/game/tests/unit/data_config/rng_stream_boot_test.gd +++ b/game/tests/unit/data_config/rng_stream_boot_test.gd @@ -34,14 +34,11 @@ func _smoke_initialize() -> void: rng.set_master_seed(42) # 统一流黄金向量(数据配置 AC-3:单盐沿用 board_gen 盐, # scope 0-3 与 board_gen 向量逐位连续;Python 参考实现逐位交叉验证一致) - Kit.check("统一流向量 m=42 scope=0(=旧 board_gen scope0 连续性锚)", rng.derive_at(0) == 8672514112661456564) - Kit.check("统一流向量 m=42 scope=1", rng.derive_at(1) == 8834291164406037215) - Kit.check("统一流向量 m=42 scope=2", rng.derive_at(2) == 7714373262647006282) - Kit.check("统一流向量 m=42 scope=3", rng.derive_at(3) == 1280102845971471347) - Kit.check("统一流向量 m=42 scope=4", rng.derive_at(4) == 82585501446482399) - Kit.check("统一流向量 m=42 scope=5", rng.derive_at(5) == 8078924421474470922) - Kit.check("统一流向量 m=42 scope=6", rng.derive_at(6) == 6638052740430622424) - Kit.check("统一流向量 m=42 scope=7", rng.derive_at(7) == 8264196488417721294) + var golden := [8672514112661456564, 8834291164406037215, 7714373262647006282, 1280102845971471347, + 82585501446482399, 8078924421474470922, 6638052740430622424, 8264196488417721294] + for i in golden.size(): + Kit.check("统一流向量 m=42 scope=%d(黄金向量;scope0=旧 board_gen 连续性锚)" % i, + rng.derive_at(i) == golden[i]) Kit.check("derive_at 纯函数恒等", rng.derive_at(0) == rng.derive_at(0)) # scope 取号语义:首个 open_stream = 全局 scope 0;计数器单调;用途标签不参与派生(只进事件日志) var s0 = rng.open_stream("board_gen") diff --git a/game/tests/unit/presentation/forge_workbench_test.gd b/game/tests/unit/presentation/forge_workbench_test.gd index e0c09afe..a41256dd 100644 --- a/game/tests/unit/presentation/forge_workbench_test.gd +++ b/game/tests/unit/presentation/forge_workbench_test.gd @@ -58,14 +58,12 @@ func _run() -> void: and rows.has("light") and rows.has("heavy") and rows.has("ward")) # ③ 初始持有行(长剑/轻甲):购买钮现形带几何价、选中钮=当前禁用 - var rsw = rows.get("sword", {}) - var rli = rows.get("light", {}) - Kit.check("长剑行:购买钮「锻造 20」(0 级位几何价)+选中钮「当前」禁用〔锻造工坊批 V13〕", - rsw.get("buy_btn") != null and String(rsw.buy_btn.text) == "锻造 20" and not rsw.buy_btn.disabled - and rsw.get("select_btn") != null and String(rsw.select_btn.text) == "当前" and rsw.select_btn.disabled) - Kit.check("轻甲行:购买钮「锻造 20」+选中钮「当前」禁用〔锻造工坊批 V13〕", - rli.get("buy_btn") != null and String(rli.buy_btn.text) == "锻造 20" - and String(rli.select_btn.text) == "当前" and rli.select_btn.disabled) + # 两行同取谓词并集(轻甲行补 select_btn 非空 + buy_btn 可用两子句——原件少写,只增不减) + for pair in [["sword", "长剑"], ["light", "轻甲"]]: + var r: Dictionary = rows.get(pair[0], {}) + Kit.check("%s行:购买钮「锻造 20」(0 级位几何价)+选中钮「当前」禁用〔锻造工坊批 V13〕" % pair[1], + r.get("buy_btn") != null and String(r.buy_btn.text) == "锻造 20" and not r.buy_btn.disabled + and r.get("select_btn") != null and String(r.select_btn.text) == "当前" and r.select_btn.disabled) # ④ 待解锁行(长枪/法杖/重甲/魔法护甲):解锁钮 200、无购买钮、无选中钮、状态含双通道文案 var rsp = rows.get("spear", {}) diff --git a/game/tests/unit/presentation/player_copy_sweep_test.gd b/game/tests/unit/presentation/player_copy_sweep_test.gd index 613c764f..9013be8b 100644 --- a/game/tests/unit/presentation/player_copy_sweep_test.gd +++ b/game/tests/unit/presentation/player_copy_sweep_test.gd @@ -56,9 +56,8 @@ func _sweep_narrator() -> void: var head := String(narrator.node_curio_header()) Kit.check("奖励点头部含「冒险牌库」(u3 机制事实①同库)〔wa4〕", head.contains("冒险牌库")) Kit.check("奖励点头部含「属性值提升与补给」(u3 机制事实②渠道分流)〔wa4〕", head.contains("属性值提升与补给")) - Kit.check("奖励点头部零「同权重」旧话(u3 清零)〔wa4〕", not head.contains("同权重")) - Kit.check("奖励点头部零「同上限」旧话(u3 清零)〔wa4〕", not head.contains("同上限")) - Kit.check("奖励点头部零「提升池」旧话(u3 清零)〔wa4〕", not head.contains("提升池")) + for w in ["同权重", "同上限", "提升池"]: + Kit.check("奖励点头部零「%s」旧话(u3 清零)〔wa4〕" % w, not head.contains(w)) Kit.check("专长卡兜底==「专长\n???」(u11 换代——数据缺行真实兜底路径)〔wa3〕", String(narrator.feat_card_text({})) == "专长\n???") @@ -73,8 +72,9 @@ func _sweep_legend() -> void: break Kit.check("图例封印行含「标空」(u4——与「标中」成对)〔wa5〕", String(seal_row[2] if seal_row.size() > 2 else "").contains("标空")) Kit.check("图例封印行含「受挖掘惩罚」(u4 雷字清零换代)〔wa5〕", String(seal_row[2] if seal_row.size() > 2 else "").contains("受挖掘惩罚")) - Kit.check("图例封印行零「插错」(u4 旗族遗留词干清零)〔wa5〕", not String(seal_row[2] if seal_row.size() > 2 else "").contains("插错")) - Kit.check("图例封印行零「挖雷」(u4 雷字清零)〔wa5〕", not String(seal_row[2] if seal_row.size() > 2 else "").contains("挖雷")) + for w in ["插错", "挖雷"]: + Kit.check("图例封印行零「%s」〔wa5〕" % w, + not String(seal_row[2] if seal_row.size() > 2 else "").contains(w)) # ⑤⑥ 来源名双源(u5/u6——状态槽消费半+表值 ConfigDB 真装载+battle_log 行消费半) diff --git a/game/tests/unit/presentation/standee_fx_sweep_test.gd b/game/tests/unit/presentation/standee_fx_sweep_test.gd index b886e92b..b26b13e0 100644 --- a/game/tests/unit/presentation/standee_fx_sweep_test.gd +++ b/game/tests/unit/presentation/standee_fx_sweep_test.gd @@ -91,14 +91,16 @@ func _init() -> void: Kit.check("无 target_id 时按名兜底同旧行为(首命中)〔wd12〕", c_fallback != null and c_fallback == c_fallback_expect) # ---- ① 意图蓄力档可达(d2)---- - s1.set_pending("damage", "heavy") - Kit.check("蓄力技能(heavy)置 _intent_charge=true〔wd2〕", s1._intent_charge) - s1.set_pending("damage", "goblin_slash") - Kit.check("非蓄力攻击技(goblin_slash)零置位〔wd2〕", not s1._intent_charge) - s1.set_pending("buff", "goblin_rage") - Kit.check("增益系零置位〔wd2〕", not s1._intent_charge) - s1.set_pending("damage", "basic") - Kit.check("普攻零表示路径复位 _intent_charge〔wd2〕", not s1._intent_charge) + # 蓄力判据表:[kind, skill_id, 期望 _intent_charge, 个案标签] + var charge_cases := [ + ["damage", "heavy", true, "蓄力技能(heavy)置 _intent_charge=true"], + ["damage", "goblin_slash", false, "非蓄力攻击技(goblin_slash)零置位"], + ["buff", "goblin_rage", false, "增益系零置位"], + ["damage", "basic", false, "普攻零表示路径复位 _intent_charge"], + ] + for c in charge_cases: + s1.set_pending(c[0], c[1]) + Kit.check("%s〔wd2〕" % c[3], s1._intent_charge == c[2]) # ---- ② 庆祝 tween 句柄纪律(d4)---- var ov = BattleEndScript.new() diff --git a/game/tests/unit/presentation/ui_font_asset_test.gd b/game/tests/unit/presentation/ui_font_asset_test.gd index b4b6f1bb..c22c1a74 100644 --- a/game/tests/unit/presentation/ui_font_asset_test.gd +++ b/game/tests/unit/presentation/ui_font_asset_test.gd @@ -15,10 +15,19 @@ func _init() -> void: var f: Font = UiKitScript.load_font(path) Kit.check("随包字体守卫装载非空(res://assets/fonts/ui_font_fusion_pixel_zh_hans.ttf)", f != null) if f != null: - Kit.check("中文字形在集(攻/雷/旗/封)", f.has_char("攻".unicode_at(0)) and f.has_char("雷".unicode_at(0)) \ - and f.has_char("旗".unicode_at(0)) and f.has_char("封".unicode_at(0))) - Kit.check("中文字形在集(危——已开危险格字形换代前置,迭代36 u12/wa9)", f.has_char("危".unicode_at(0))) - Kit.check("ASCII/数字字形在集(A/0/%)", f.has_char("A".unicode_at(0)) and f.has_char("0".unicode_at(0)) and f.has_char("%".unicode_at(0))) + # 字形集表:[个案标签, 须在集字符]——缺字明细进消息 + var glyph_groups := [ + ["中文字形在集(攻/雷/旗/封)", "攻雷旗封"], + ["中文字形在集(危——已开危险格字形换代前置,迭代36 u12/wa9)", "危"], + ["ASCII/数字字形在集(A/0/%)", "A0%"], + ] + for g in glyph_groups: + var missing := "" + for i in String(g[1]).length(): + var ch := String(g[1])[i] + if not f.has_char(ch.unicode_at(0)): + missing += ch + Kit.check("%s(缺=%s)" % [g[0], missing if missing != "" else "无"], missing == "") var sz := 18 var w_cn: float = f.get_string_size("战斗胜利", HORIZONTAL_ALIGNMENT_LEFT, -1, sz).x var w_label: float = f.get_string_size("攻击 2", HORIZONTAL_ALIGNMENT_LEFT, -1, sz).x