修复: 卡④T3——测试三形态落位(契约 9):①probe=ui_input_probe case⑮ 内载体级段不开新 case——装配 fog_lantern→开局参数面(build_adventure_params=卡⓪①修复面回归)+settlement.attunement 注入→呈现桥 _sync_fog_lantern→lantern=2 且 dist==R+1 格转可见+卸装显式重算复原 0;case⑮ 既有断言零删减(实查 17 断言面原样)②smoke=现有套件 _smoke_adventure_table 加断言不新开套件——行字段逐键裁值+同调目录投影 display_name(九件→十件)+装配→战斗贯通 enc 注入→attune_has=true+空装配基线 false③存档回归=breakpoint_resume_test 新增 Part 6——装配(params.attunement)→停点→续玩受理→回局首战 attune_has 仍 true④呈现桥判定 stub 单测+行加载单测=新件 fog_lantern_wiring_test.gd(run_all manifest 17→18 套)。闸:冒烟 840→844/0+ui_input_probe PASS+breakpoint PASS+新套件 PASS
This commit is contained in:
1 parent
fd6c208b2e
commit
510cdab506
6 files changed
+131
-1
No files matched your search
@@ -230,6 +230,34 @@ func _smoke_adventure_table() -> void:
|
||||
check(_db.attunement_growth != null and int(_db.attunement_slot_cap()) == 3
|
||||
and Attunement.slots(_db, null) == 0,
|
||||
"同调位读数源=attunement_growth 谓词表(slot_cap 3;未注入档求值 0——transitional_sync_slots 过渡键已退役,迭代 11 第①批 T7)")
|
||||
# 迭代 19 卡④——提灯载体行(fog_lantern):新行加载/schema/同调目录投影+装配→战斗贯通(核心层半边;
|
||||
# 呈现半边归 ui_input_probe case⑮ 载体级段——测试三形态契约 9)
|
||||
var lantern_row: Dictionary = _db.treasure_items.row_by_id("fog_lantern")
|
||||
check(not lantern_row.is_empty() and String(lantern_row.get("display_name", "")) == "魔法提灯"
|
||||
and String(lantern_row.get("desc", "")) == "灯光区半径+2"
|
||||
and String(lantern_row.get("form", "")) == "passive" and int(lantern_row.get("slot_cost", -1)) == 1
|
||||
and (lantern_row.get("dimension_tags", []) as Array) == ["info"]
|
||||
and (lantern_row.get("effect_kinds", []) as Array).is_empty()
|
||||
and lantern_row.has("triggers") and (lantern_row.get("triggers", []) as Array).is_empty()
|
||||
and String(lantern_row.get("target", "")) == "none" and int(lantern_row.get("magnitude", -1)) == 0
|
||||
and String(lantern_row.get("use_phase", "")) == "active_dig"
|
||||
and not lantern_row.has("unlock_requires")
|
||||
and not bool(lantern_row.get("retired", false)) and not bool(lantern_row.get("deferred", false)),
|
||||
"提灯载体行 fog_lantern:行字段逐键=裁值(魔法提灯/灯光区半径+2/passive/slot_cost 1/[info]/空效果/显式 triggers 空数组/none/0/active_dig/unlock 键省略=已解锁/活行非封存)")
|
||||
var att_lantern := {}
|
||||
for r in _db.treasure_attunement_rows():
|
||||
if String(r.get("item_id", "")) == "fog_lantern":
|
||||
att_lantern = r
|
||||
check(not att_lantern.is_empty() and String(att_lantern.get("display_name", "")) == "魔法提灯",
|
||||
"同调目录投影:fog_lantern 在装配词表且 display_name=魔法提灯(营地工坊目录九件→十件)")
|
||||
var orch_l = load("res://core/battle_orchestrator.gd").new(_db, _fresh_rng(191))
|
||||
check(orch_l.begin_battle({"level_index": 1, "node_depth": 0, "hero_hp": int(_db.hero.max_hp), "attunement": ["fog_lantern"]})
|
||||
and orch_l.attune_has("fog_lantern"),
|
||||
"装配→战斗贯通:enc.attunement=[fog_lantern] 起战 attune_has=true(注入面+只读出口)")
|
||||
var orch_e = load("res://core/battle_orchestrator.gd").new(_db, _fresh_rng(192))
|
||||
check(orch_e.begin_battle({"level_index": 1, "node_depth": 0, "hero_hp": int(_db.hero.max_hp)})
|
||||
and not orch_e.attune_has("fog_lantern"),
|
||||
"空装配基线:不带 attunement 起战 attune_has=false(off 态零扰动)")
|
||||
|
||||
|
||||
# ② 冒险结构 API 闸(状态机受理面——重复开始拒绝 / 入口停点 / 放弃两态)
|
||||
|
||||
@@ -416,6 +416,27 @@ func _ready() -> void:
|
||||
_problems.append("case⑮ 提灯关闭后雾参数未复原(lantern 应=0)")
|
||||
if int(bv.cells_probe()[ring_cell].fog_state) == 0:
|
||||
_problems.append("case⑮ 提灯关闭后 dist==R+1 格未复原遮蔽")
|
||||
# 载体级断言(迭代 19 卡④——fog_lantern 装配链贯通:①装配→开局参数面〔build_adventure_params
|
||||
# 统一构造=卡⓪①缺陷修复面回归〕②装配集→呈现桥〔_sync_fog_lantern 消费 attune_has 只读出口
|
||||
# →set_fog_lantern〕→视野 +2 生效与卸装复原。settlement.attunement 手动注入=模拟 begin_battle
|
||||
# enc 注入后的运行态〔注入面本体归冒烟+单测覆盖〕;不重启冒险——case⑯ 起既有板面继续用)
|
||||
main.save_manager.set_attunement_equipped(["fog_lantern"])
|
||||
var p_lantern: Dictionary = main.build_adventure_params(main.save_manager, main.meta)
|
||||
if not (p_lantern.get("attunement", []) as Array).has("fog_lantern"):
|
||||
_problems.append("case⑮ 载体装配未进开局参数面(attunement=%s 应含 fog_lantern)" % str(p_lantern.get("attunement", [])))
|
||||
main.settlement.attunement = ["fog_lantern"]
|
||||
main._sync_fog_lantern()
|
||||
if int(bv.fog_params_probe()["lantern"]) != 2:
|
||||
_problems.append("case⑮ 载体装配后视野未扩(lantern 应=2——呈现桥未生效)")
|
||||
if int(bv.cells_probe()[ring_cell].fog_state) != 0:
|
||||
_problems.append("case⑮ 载体装配后 dist==R+1 格仍被遮(应转可见)")
|
||||
main.settlement.attunement = []
|
||||
main._sync_fog_lantern()
|
||||
if int(bv.fog_params_probe()["lantern"]) != 0:
|
||||
_problems.append("case⑮ 载体卸装后视野未复原(lantern 应=0——契约 7 显式重算含否)")
|
||||
if int(bv.cells_probe()[ring_cell].fog_state) == 0:
|
||||
_problems.append("case⑮ 载体卸装后 dist==R+1 格未复原遮蔽")
|
||||
main.save_manager.set_attunement_equipped([])
|
||||
# ---- case⑯ 暂停层输入锁语义(迭代 17 卡③ R3——开层锁棋盘、关层恢复无残留;真实 push_input
|
||||
# 路径:入口角标本体 press+release 真点击 → 暂停层开;锁期挖掘点击零穿透;「继续」关层后
|
||||
# 同格挖掘重新到达——锁语义与既有模态同款,无状态残留。置于全 case 之尾:取格若需前沿移位
|
||||
|
||||
@@ -43,6 +43,7 @@ func _suites() -> Array:
|
||||
{"path": "res://tests/unit/contracts/system_contracts_test.gd", "expect": 0},
|
||||
{"path": "res://tests/unit/presentation/ui_font_asset_test.gd", "expect": 0},
|
||||
{"path": "res://tests/unit/presentation/terrain_tile_sets_test.gd", "expect": 0},
|
||||
{"path": "res://tests/unit/core/fog_lantern_wiring_test.gd", "expect": 0}, # 迭代 19 卡④——提灯载体装配链(行加载/schema/只读出口双态/enc 注入面)
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -128,8 +128,27 @@ func _init() -> void:
|
||||
Kit.check_quiet(String(got_result["r"].get("picked", "")) == picked_e, "P5 已兑付不重付(resolved 重发同件)")
|
||||
Kit.check_quiet(adr_g.continue_to_next_level(), "P5 已兑付续玩后推进受理(下一关开始)")
|
||||
|
||||
# ---- Part 6:装配存档回归(迭代 19 卡④——装配→停点→回局载体态一致:params.attunement 随续玩
|
||||
# 受理面重建再注入战斗〔begin_battle enc 携带〕;呈现态每战重算归呈现桥(main._sync_fog_lantern),
|
||||
# 本断言钉核心层装载往返——回局后 attune_has 只读出口读数一致)----
|
||||
var rng_h = load("res://core/rng_service.gd").new()
|
||||
var sm_h = SaveManagerScript.new(_bp_path)
|
||||
var adr_h = AdventureRunnerScript.new(db, rng_h)
|
||||
adr_h.set_save_manager(sm_h)
|
||||
var params_h := {"hero_override": {}, "treasure_unlocked": {}, "attunement": ["fog_lantern"]}
|
||||
Kit.check_quiet(adr_h.start_adventure(5678, params_h), "P6 装配冒险启动(seed 5678——params 带 fog_lantern)")
|
||||
Kit.check_quiet(adr_h.runner().pick_next_node(int(adr_h.runner().next_candidate_ids()[0])), "P6 选路进首战")
|
||||
Kit.check_quiet(adr_h.runner().current_battle().attune_has("fog_lantern"), "P6 首战装配集含 fog_lantern(attune_has 只读出口)")
|
||||
var sm_i = SaveManagerScript.new(_bp_path)
|
||||
Kit.check_quiet(sm_i.load_from_disk() and sm_i.has_breakpoint(), "P6 断点在档(停点可中断)")
|
||||
var adr_i = AdventureRunnerScript.new(db, load("res://core/rng_service.gd").new())
|
||||
adr_i.set_save_manager(sm_i)
|
||||
Kit.check_quiet(adr_i.resume_adventure(sm_i.breakpoint_snapshot(), params_h), "P6 续玩受理(装配集随 params 再注入)")
|
||||
Kit.check_quiet(adr_i.runner().pick_next_node(int(adr_i.runner().next_candidate_ids()[0])), "P6 续玩选路进首战")
|
||||
Kit.check_quiet(adr_i.runner().current_battle().attune_has("fog_lantern"), "P6 回局首战装配集仍含 fog_lantern(停点往返载体态一致)")
|
||||
|
||||
_clear_disk()
|
||||
quit(Kit.finish("breakpoint_resume_test", "PASS — 断点往返/续玩确定性/幂等/退出清断点 全绿"))
|
||||
quit(Kit.finish("breakpoint_resume_test", "PASS — 断点往返/续玩确定性/幂等/退出清断点/装配存档回归 全绿"))
|
||||
|
||||
|
||||
func _board_fingerprint(b) -> String:
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
# VERTICAL SLICE - NOT FOR PRODUCTION
|
||||
# 提灯载体 fog_lantern 装配链单测(迭代 19 卡④ T3——测试三形态之「呈现桥判定=注入装配集 stub 的
|
||||
# 单测 + 行加载单测」(任务书契约 9);probe=case⑮ 载体级段 / smoke=现有套件加断言,另两形态不在本件)。
|
||||
# 覆盖:真实表行加载+schema 校验零违例 / 行字段裁值逐键 / 同调目录词表收录 / attune_has 只读出口
|
||||
# 双态(组合根 _sync_fog_lantern 消费面)/ begin_battle enc 注入面。
|
||||
# 运行:godot --headless --path game --script res://tests/unit/core/fog_lantern_wiring_test.gd(expect 0)
|
||||
extends SceneTree
|
||||
|
||||
const Kit := preload("res://tests/unit/test_kit.gd") # check/汇总退出样板单点(静默收集通道)
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
# ① 行加载+schema 校验(真实 treasure_items.tres——活行空 effect_kinds 豁免以 row.has("triggers")
|
||||
# 为条件(treasure_item_table.gd:111),triggers 键漏写=加载红——本断言钉住该易错点)
|
||||
var tbl = load("res://data/tables/treasure_items.tres")
|
||||
Kit.check_quiet(tbl != null and tbl.validate().is_empty(),
|
||||
"fog_lantern 入表后 TreasureItemTable.validate 零违例(KEY_WHITELIST/活行校验全过)")
|
||||
var row: Dictionary = tbl.row_by_id("fog_lantern") if tbl != null else {}
|
||||
Kit.check_quiet(not row.is_empty() and String(row.get("display_name", "")) == "魔法提灯"
|
||||
and String(row.get("desc", "")) == "灯光区半径+2"
|
||||
and String(row.get("form", "")) == "passive" and int(row.get("slot_cost", -1)) == 1
|
||||
and row.has("triggers") and (row.get("triggers", []) as Array).is_empty()
|
||||
and (row.get("effect_kinds", []) as Array).is_empty()
|
||||
and String(row.get("target", "")) == "none" and int(row.get("magnitude", -1)) == 0
|
||||
and String(row.get("use_phase", "")) == "active_dig"
|
||||
and (row.get("dimension_tags", []) as Array) == ["info"]
|
||||
and not row.has("unlock_requires")
|
||||
and not bool(row.get("retired", false)) and not bool(row.get("deferred", false)),
|
||||
"行字段逐键=用户「按推荐」裁值(魔法提灯/灯光区半径+2/passive/slot_cost 1/显式 triggers 空/none/0/active_dig/[info]/unlock 键省略=已解锁/活行)")
|
||||
var in_att := false
|
||||
for r in (tbl.attunement_rows() as Array):
|
||||
if String(r.get("item_id", "")) == "fog_lantern":
|
||||
in_att = true
|
||||
Kit.check_quiet(in_att, "同调目录词表收录 fog_lantern(attunement_rows=form 非空活行口径)")
|
||||
|
||||
# ② 数据表宿主(②③需 db)
|
||||
var db = load("res://core/config_db.gd").new()
|
||||
if not db.load_tables("res://data/tables", false):
|
||||
print("[fog_lantern_wiring_test] FAIL — 数值表加载失败")
|
||||
quit(1)
|
||||
return
|
||||
|
||||
# ③ 呈现桥判定 stub:装配集直注→只读出口双态(组合根 _sync_fog_lantern 消费面——不经完整战斗)
|
||||
var rng_a = load("res://core/rng_service.gd").new()
|
||||
rng_a.set_master_seed(191) # 播种(EC7 未播种取数致命——begin_battle 板生成取号前提)
|
||||
var orch = load("res://core/battle_orchestrator.gd").new(db, rng_a)
|
||||
orch.attunement = ["fog_lantern"]
|
||||
Kit.check_quiet(orch.attune_has("fog_lantern"), "attune_has(fog_lantern)=true(装配集在册)")
|
||||
Kit.check_quiet(not orch.attune_has("luck_coin"), "attune_has(luck_coin)=false(他件不误判)")
|
||||
orch.attunement = []
|
||||
Kit.check_quiet(not orch.attune_has("fog_lantern"), "attune_has(fog_lantern)=false(空集=复原语义读数源)")
|
||||
|
||||
# ④ begin_battle enc 注入面(runner→enc.attunement→orchestrator 运行态)
|
||||
var rng_b = load("res://core/rng_service.gd").new()
|
||||
rng_b.set_master_seed(192)
|
||||
var orch2 = load("res://core/battle_orchestrator.gd").new(db, rng_b)
|
||||
Kit.check_quiet(orch2.begin_battle({"level_index": 1, "node_depth": 0, "hero_hp": int(db.hero.max_hp), "attunement": ["fog_lantern"]})
|
||||
and orch2.attune_has("fog_lantern"), "begin_battle enc.attunement 注入→attune_has=true(每战装配链装载)")
|
||||
|
||||
quit(Kit.finish("fog_lantern_wiring_test", "PASS — 行加载/schema 校验/同调词表收录/只读出口双态/enc 注入面 全绿"))
|
||||
@@ -0,0 +1 @@
|
||||
uid://jlkj801c81qd
|
||||
Reference in new issue
Block a user