test(迭代35卡②T3 尾缀对齐): 本批新落地断言补可 grep 尾缀(〔v2〕入口候选数=参数档 entry_count 与第二入口进入/〔v5〕商店三性质与扫描面非空/〔v7〕同档同种子两次产图同图·起关图=生成器直取·种子 42 两开局同图·断点重生成同图·同种子重开局同图/〔v8〕快照代差标记·句柄往返·旧断点拒绝/〔v9〕快照无已抽模板键·表无 templates 键/〔v4〕三关图各含奖励节点)+商店宿主重复段头清理——独立审计第 1 件(对照表逐行核尾缀可 grep)的执行面;四宿主复跑 21/176/138 全绿零错误行
This commit is contained in:
1 parent
4cec838f0e
commit
3461e83bec
5 files changed
+30
-24
No files matched your search
@@ -40,7 +40,7 @@ func _smoke_generated_map_determinism() -> void:
|
||||
var g_b: Dictionary = gen.generate(params2, 910002)
|
||||
var g_c: Dictionary = gen.generate(params2, 910003)
|
||||
var nodes_a: Array = g_a.get("nodes", [])
|
||||
Kit.check("同参数档同种子两次产图逐位同图(D2 执行边界)",
|
||||
Kit.check("同参数档同种子两次产图逐位同图(D2 执行边界)〔v7〕",
|
||||
nodes_a == (g_b.get("nodes", []) as Array))
|
||||
Kit.check("同参数档换种子即变图(图确为种子函数,非恒定输出)",
|
||||
nodes_a != (g_c.get("nodes", []) as Array))
|
||||
@@ -50,7 +50,7 @@ func _smoke_generated_map_determinism() -> void:
|
||||
var runner1 = load("res://core/level_runner.gd").new(_db, _fresh_rng(910004))
|
||||
Kit.check("单关起关受理(种子 910004——生成图直供,无兜底图)",
|
||||
runner1.start_level(2, 910004))
|
||||
Kit.check("起关生效图 = 生成器同档同种子直取逐位一致(消费侧无第二图源)",
|
||||
Kit.check("起关生效图 = 生成器同档同种子直取逐位一致(消费侧无第二图源)〔v7〕",
|
||||
runner1.level_row.get("nodes", []) == (gen.generate(params2, 910004) as Dictionary).get("nodes", []))
|
||||
# ③ 产图零统一流消费(纯派生流不占计数器号位——断点在任意号位重生成同图的机制承载)
|
||||
var rng_c = _fresh_rng(910005)
|
||||
@@ -61,11 +61,11 @@ func _smoke_generated_map_determinism() -> void:
|
||||
Kit.check("起关产图零计数器消费(同图不依赖取数号位)", rng_c.counter() == counter_before)
|
||||
var params3: Dictionary = _db.level_gen_params_row(3)
|
||||
var entry_count: int = int(params3.get("entry_count", -1))
|
||||
Kit.check("入口停点候选数=参数档入口个数(L3 档 %d——多入口首跳即选路,禁写死单入口)" % entry_count,
|
||||
Kit.check("入口停点候选数=参数档入口个数(L3 档 %d——多入口首跳即选路,禁写死单入口)〔v2〕" % entry_count,
|
||||
entry_count >= 1 and (runner2.next_candidates() as Array).size() == entry_count)
|
||||
if entry_count >= 2:
|
||||
var eids: Array = runner2.next_candidate_ids()
|
||||
Kit.check("第二入口经句柄显式进入(句柄 %d)" % int(eids[1]),
|
||||
Kit.check("第二入口经句柄显式进入(句柄 %d)〔v2〕" % int(eids[1]),
|
||||
runner2.pick_next_node(int(eids[1])) and int(runner2.current_node_id()) == int(eids[1]))
|
||||
# ④ 开局种子承载:新档(首局)种子 42 两次开局逐位同图,且与生成器直取一致
|
||||
DirAccess.remove_absolute(_bp_path) # 测试隔离——上轮落盘残留先删,断点面从零档起
|
||||
@@ -77,7 +77,7 @@ func _smoke_generated_map_determinism() -> void:
|
||||
var adr_y = AdventureRunnerScript.new(_db, _fresh_rng(42))
|
||||
Kit.check("同种子第二次开局受理", adr_y.start_adventure(42,
|
||||
{"hero_override": {}, "treasure_unlocked": {}}))
|
||||
Kit.check("种子 42 两次开局图逐位同图(教学局恒同图——首局固定种子的确定性承载)",
|
||||
Kit.check("种子 42 两次开局图逐位同图(教学局恒同图——首局固定种子的确定性承载)〔v7〕",
|
||||
adr_x.runner().nodes() == adr_y.runner().nodes())
|
||||
Kit.check("开局图 = L1 参数档在种子 42 下的生成图(开局无隐式取数分叉)",
|
||||
adr_x.runner().nodes() == (gen.generate(_db.level_gen_params_row(1), 42) as Dictionary).get("nodes", []))
|
||||
@@ -85,20 +85,20 @@ func _smoke_generated_map_determinism() -> void:
|
||||
Kit.check("停点断点落盘在档", sv_w.has_breakpoint())
|
||||
var bp: Dictionary = sv_w.breakpoint_snapshot()
|
||||
var adr_z = AdventureRunnerScript.new(_db, load("res://core/rng_service.gd").new())
|
||||
Kit.check("断点续玩受理(代差标记键在档)", adr_z.resume_adventure(bp,
|
||||
Kit.check("断点续玩受理(代差标记键在档)〔v8〕", adr_z.resume_adventure(bp,
|
||||
{"hero_override": {}, "treasure_unlocked": {}}))
|
||||
Kit.check("续玩重生成图与中断前逐位同图", adr_z.runner().nodes() == adr_x.runner().nodes())
|
||||
Kit.check("续玩重生成图与中断前逐位同图〔v7〕", adr_z.runner().nodes() == adr_x.runner().nodes())
|
||||
var adr_old = AdventureRunnerScript.new(_db, load("res://core/rng_service.gd").new())
|
||||
var bp_old: Dictionary = bp.duplicate(true)
|
||||
bp_old.erase("graph_gen_v2") # 换代前旧断点形态(模板池时代无代差标记键)
|
||||
Kit.check("缺生成图代差标记键的旧断点被显式拒绝(禁按新语义静默回放)",
|
||||
Kit.check("缺生成图代差标记键的旧断点被显式拒绝(禁按新语义静默回放)〔v8〕",
|
||||
adr_old.resume_adventure(bp_old, {}) == false)
|
||||
# ⑥ 关卡表不再携带图数据(图源换代后 level 行只剩行级字段)
|
||||
var tpl_free := true
|
||||
for li in range(1, _db.level_count() + 1):
|
||||
if (_db.level_row(li) as Dictionary).has("templates"):
|
||||
tpl_free = false
|
||||
Kit.check("level 表三行均无 templates 键(模板数据已清出)",
|
||||
Kit.check("level 表三行均无 templates 键(模板数据已清出)〔v9〕",
|
||||
tpl_free and _db.level_count() == 3)
|
||||
# ⑦ 收束置位:新档 false → settle 置 true 恰一次(幂等)
|
||||
var sv = SaveManagerScript.new(_bp_path + ".flag.json")
|
||||
|
||||
@@ -162,7 +162,7 @@ func _smoke_adventure() -> void:
|
||||
rc += 1
|
||||
if rc >= 1:
|
||||
reward_levels += 1
|
||||
Kit.check("三关生成图各含 ≥1 奖励节点(节点三选一候选位在图)", reward_levels == 3)
|
||||
Kit.check("三关生成图各含 ≥1 奖励节点(节点三选一候选位在图)〔v4〕", reward_levels == 3)
|
||||
# 行进侧两断言走真实选路入口(满配赢下途中战→岔口按偏好显式点选):奖励支路经停即呈三选一、
|
||||
# 进战载荷带节点深度——确定性评分策略恒选推进支路,奖励位不在扫描路由上,故显式点选验证接线
|
||||
var rw: Dictionary = _drive_to_pref(autoplay, "reward")
|
||||
|
||||
@@ -157,9 +157,9 @@ func _init() -> void:
|
||||
var graph_j: Array = runner_j.nodes()
|
||||
var bp_j: Dictionary = sm_j.breakpoint_snapshot()
|
||||
Kit.check_quiet(not bp_j.has("template_pick"),
|
||||
"P7 断点快照无已抽模板键(模板链路退役——件核面在档)")
|
||||
"P7 断点快照无已抽模板键(模板链路退役——件核面在档)〔v9〕")
|
||||
Kit.check_quiet(int(bp_j.get("graph_gen_v2", 0)) == 1,
|
||||
"P7 断点含生成图代差标记键(换代承载)")
|
||||
"P7 断点含生成图代差标记键(换代承载)〔v8〕")
|
||||
var entry_id: int = int(runner_j.next_candidate_ids()[0])
|
||||
var mid_id: int = _first_out_id(graph_j, entry_id)
|
||||
var bp_mid: Dictionary = bp_j.duplicate(true)
|
||||
@@ -169,17 +169,17 @@ func _init() -> void:
|
||||
Kit.check_quiet(adr_m.resume_adventure(bp_mid, params), "P7 中途停点断点续玩受理(句柄落档形态)")
|
||||
var runner_m = adr_m.runner()
|
||||
Kit.check_quiet(int(runner_m.current_node_id()) == mid_id,
|
||||
"P7 停点句柄回读一致(图内 id 单空间寻址)")
|
||||
"P7 停点句柄回读一致(图内 id 单空间寻址)〔v8〕")
|
||||
Kit.check_quiet(runner_m.visited_ids() == [entry_id], "P7 已到节点序按句柄往返一致")
|
||||
Kit.check_quiet(runner_m.nodes() == graph_j, "P7 续玩重生成图与中断前逐位同图(断点不存图快照)")
|
||||
Kit.check_quiet(runner_m.nodes() == graph_j, "P7 续玩重生成图与中断前逐位同图(断点不存图快照)〔v7〕")
|
||||
var adr_l = AdventureRunnerScript.new(db, load("res://core/rng_service.gd").new())
|
||||
var bp_legacy: Dictionary = bp_mid.duplicate(true)
|
||||
bp_legacy.erase("graph_gen_v2")
|
||||
Kit.check_quiet(adr_l.resume_adventure(bp_legacy, params) == false,
|
||||
"P7 缺生成图代差标记键的旧断点显式拒绝(禁按新句柄空间静默回放)")
|
||||
"P7 缺生成图代差标记键的旧断点显式拒绝(禁按新句柄空间静默回放)〔v8〕")
|
||||
var adr_n = AdventureRunnerScript.new(db, load("res://core/rng_service.gd").new())
|
||||
Kit.check_quiet(adr_n.start_adventure(910042, params) and adr_n.runner().nodes() == graph_j,
|
||||
"P7 同种子重开局同图(开局入口复现承载)")
|
||||
"P7 同种子重开局同图(开局入口复现承载)〔v7〕")
|
||||
|
||||
_clear_disk()
|
||||
quit(Kit.finish("breakpoint_resume_test", "PASS — 断点往返/续玩确定性/幂等/退出清断点/装配存档回归/生成图换代 全绿"))
|
||||
|
||||
@@ -1080,9 +1080,6 @@ func _shop_products_by_id(prods: Array) -> Dictionary:
|
||||
return out
|
||||
|
||||
|
||||
# ---- ④ 商店编排性质(每终点前一位恰一店 · 店数=终点数 · 全路径恰穿一店)----
|
||||
|
||||
|
||||
# ---- ④ 商店编排性质(生成图扫描面——三条性质 + 终点跨表解析)----
|
||||
|
||||
func _smoke_shop_graph() -> void:
|
||||
@@ -1126,11 +1123,11 @@ func _smoke_shop_graph() -> void:
|
||||
if _path_shop_count(nodes, p) != 1:
|
||||
path_bad += 1
|
||||
print("商店编排扫描读数:图 %d 张·终点 %d 个·入口→终点路径 %d 条" % [graph_total, term_total, path_total])
|
||||
Kit.check("编排断言扫描面非空(三关参数档 × 种子 %d–%d=图 %d 张·终点 %d·路径 %d)" % [SWEEP_SEED_FROM, SWEEP_SEED_TO - 1, graph_total, term_total, path_total],
|
||||
Kit.check("编排断言扫描面非空(三关参数档 × 种子 %d–%d=图 %d 张·终点 %d·路径 %d)〔v5〕" % [SWEEP_SEED_FROM, SWEEP_SEED_TO - 1, graph_total, term_total, path_total],
|
||||
graph_total == 3 * (SWEEP_SEED_TO - SWEEP_SEED_FROM) and term_total >= 3 and path_total >= 3)
|
||||
Kit.check("性质① 每个终点的直接前驱恰一家商店(入边一条且源型别=shop·违例 %d/%d 终点)" % [pred_bad, term_total], pred_bad == 0)
|
||||
Kit.check("性质② 每图商店节点数 = 终点数(违例 %d/%d 图)" % [count_bad, graph_total], count_bad == 0)
|
||||
Kit.check("性质③ 每条入口→终点路径恰穿一家商店(违例 %d/%d 条路径)" % [path_bad, path_total], path_bad == 0)
|
||||
Kit.check("性质① 每个终点的直接前驱恰一家商店(入边一条且源型别=shop·违例 %d/%d 终点)〔v5〕" % [pred_bad, term_total], pred_bad == 0)
|
||||
Kit.check("性质② 每图商店节点数 = 终点数(违例 %d/%d 图)〔v5〕" % [count_bad, graph_total], count_bad == 0)
|
||||
Kit.check("性质③ 每条入口→终点路径恰穿一家商店(违例 %d/%d 条路径)〔v5〕" % [path_bad, path_total], path_bad == 0)
|
||||
# 现行起关图(种子 %d)逐关读数——L1 单终点、L2/L3 多终点(每终点前一位恰一店的当关投影)
|
||||
for L in [1, 2, 3]:
|
||||
var cur_nodes: Array = _level_active_nodes(L)
|
||||
|
||||
@@ -140,7 +140,16 @@
|
||||
|
||||
卡片 §8 变异清单九条的落位:V1 两条(T1 已录)、V11 两条(覆盖批已录)、V2/V5×2/V6/V7/V8/V9 共六条(本表 M1–M7,V5 拆两条)。
|
||||
|
||||
## 三、遗留读数义务
|
||||
## 三·一 实机目检总清单(真人判断项,登记即完成义务,不作为合回前置)
|
||||
|
||||
| # | 观测项 | 真实入口 | 期望看到什么 | 本批机检已覆盖的部分 |
|
||||
|---|---|---|---|---|
|
||||
| 目检① | 三关选路观感不回归:多入口首跳、大岔口取舍、多终点走向可见 | 主菜单开局 → 关卡地图(`res://probe/ui_click_probe.tscn` 亦可走同路径) | 开局即出现两个可选入口(L2/L3);岔口处候选互异且分属不同支路;走 A 支只遇 A 支终点 Boss | 候选数=参数档 `entry_count`、第二入口句柄可进入、终点数=`exit_count`、岔口 ≥1、每终点前恰一店(`node_map_templates`/`level_shop_economy` 扫描面) |
|
||||
| 目检② | 首局教学图体验(种子 42 固定图) | 新档开局(`is_first_adventure_done==false` → 恒种子 42) | 同一张图、节奏可教学:入口战→岔口→商店→Boss 的可读顺序,含至少一个奖励位与一个恢复位 | 种子 42 两开局逐位同图、开局图=参数档直取、三关图各含奖励/恢复节点、恢复公式两分支读数 |
|
||||
|
||||
登记口径:以上两项由用户自行安排试玩;本批不以任何目检为停工或合回理由(硬性红线「真人检测只登记不阻塞」)。
|
||||
|
||||
## 三·二 其余遗留读数义务
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user