merge(迭代32 卡②补漏): §9 正向验收主力 V1/V2/V6 与全 Vn 标注断言
前次卡②合回缺 §9 四桶正向断言(adventure 桶跨战持久无回归网)——本批补齐 V1(真实 request_dig 跨战累积) /V2(新冒险置空)/V6(battle 桶随宿主销毁)并给 V1-V10 打〔无状态化 Vn〕尾缀;V1/V4/V9/V10 变异验证均能转红。 冒烟 1156/0、单元 35 全绿、S12 旧件零残留、代码域闸 all_green(回执 d8622ee2)。
This commit is contained in:
commit
f103177471
6 files changed
+86
-9
No files matched your search
+54
-2
@@ -697,6 +697,7 @@ func _run_core_smoke(db, rng) -> void:
|
||||
_smoke_meta()
|
||||
_smoke_tree()
|
||||
_smoke_tree_rules()
|
||||
_smoke_counter_buckets()
|
||||
_smoke_node_map_templates()
|
||||
|
||||
|
||||
@@ -6049,6 +6050,57 @@ func _smoke_tree() -> void:
|
||||
|
||||
# ---- 天赋树六键行为冒烟(V10:开局姿态窗/危险直觉限次/财富之道聚散/守侧失误补偿;
|
||||
# 引擎直构 + 编排授予段直注(_grant_seg._judge_seal=结算授予段封印判定单口))----
|
||||
func _smoke_counter_buckets() -> void:
|
||||
print("--- 效果引擎无状态化四桶正向验收(卡② §9 V1/V6)---")
|
||||
# V1——adventure 桶跨战持久:同一 RunLedger 下两战各真实 request_dig 一次,
|
||||
# 断付费计数经 ctx 就地写入宿主字典并跨战累积(副本搬运态:读不到上一战值→第 2 战仍 1,此断言会红)。
|
||||
var led = load("res://core/run_ledger.gd").new()
|
||||
var RigS = load("res://core/battle_orchestrator.gd")
|
||||
var RngS = load("res://core/rng_service.gd")
|
||||
var enc1 = {"level_index": 1, "node_depth": 0, "hero_hp": 40, "hero_atk": 8, "hero_max_hp": 40,
|
||||
"hero_armor_class": 10, "hero_ap_bonus": 0, "attunement": [], "attune_charges": {},
|
||||
"feats": ["twin_pick"], "tree_rules": [], "battle_index": 1,
|
||||
"bonus_ref": {"atk": 0, "max_hp": 0, "armor_class": 0}, "voucher_rap": 0, "voucher_time_sand": 0,
|
||||
"node_type": "battle", "ledger": led}
|
||||
var o1 = RigS.new(_db, _fresh_rng(779301))
|
||||
o1.begin_battle(enc1)
|
||||
var dig1: bool = o1.action_economy.request_dig(0, false)
|
||||
check(dig1, "V1 第1战真实 request_dig 受理(begin_battle 后 ACTIVE 相位)〔无状态化 V1〕")
|
||||
check(int(led.adventure_counters.get("adv_twin_digs", 0)) == 1,
|
||||
"V1 第1战付费挖格经 ctx 就地写 adventure 桶=1(无 export 搬运时点)〔无状态化 V1〕")
|
||||
var enc2 = enc1.duplicate(true)
|
||||
enc2["battle_index"] = 2
|
||||
var o2 = RigS.new(_db, _fresh_rng(779302))
|
||||
o2.begin_battle(enc2)
|
||||
check(EffectEngine.counter(o2.counters_ctx, "adv_twin_digs") == 1,
|
||||
"V1 第2战 begin_battle 经 ctx 读到上一战持久值=1(读路径走宿主字典引用,非副本种子回灌)〔无状态化 V1〕")
|
||||
o2.action_economy.request_dig(0, false)
|
||||
check(int(led.adventure_counters.get("adv_twin_digs", 0)) == 2,
|
||||
"V1 第2战挖后 adventure 桶跨战累积=2(run_ledger:42 判空早退缺陷消解的回归钉面——旧副本态恒 1)〔无状态化 V1〕")
|
||||
# V6——battle 桶随宿主销毁:第1战标错落 insurance_used(battle 桶无前缀),次战新编排器读 0。
|
||||
var encA = {"level_index": 1, "node_depth": 0, "hero_hp": 40, "hero_atk": 8, "hero_max_hp": 40,
|
||||
"hero_armor_class": 10, "hero_ap_bonus": 0, "attunement": [], "attune_charges": {},
|
||||
"feats": ["perfect_insurance"], "tree_rules": [], "battle_index": 1,
|
||||
"bonus_ref": {"atk": 0, "max_hp": 0, "armor_class": 0}, "voucher_rap": 0, "voucher_time_sand": 0,
|
||||
"node_type": "battle", "ledger": load("res://core/run_ledger.gd").new()}
|
||||
var oA = RigS.new(_db, _fresh_rng(779401))
|
||||
oA.begin_battle(encA)
|
||||
var safe_a: Variant = null
|
||||
for ca in oA.minesweeper.current_board().all_cells():
|
||||
if not oA.minesweeper.current_board().is_mine(ca):
|
||||
safe_a = ca
|
||||
break
|
||||
oA._grant_seg._judge_seal({"cell": safe_a, "hit": false}, 1)
|
||||
check(EffectEngine.counter(oA.counters_ctx, "insurance_used") == 1,
|
||||
"V6 第1战标错落 battle 桶 insurance_used=1(_apply_counter_hit 静态写口经 ctx)〔无状态化 V6〕")
|
||||
var encB = encA.duplicate(true)
|
||||
encB["battle_index"] = 2
|
||||
var oB = RigS.new(_db, _fresh_rng(779402))
|
||||
oB.begin_battle(encB)
|
||||
check(EffectEngine.counter(oB.counters_ctx, "insurance_used") == 0,
|
||||
"V6 battle 桶随宿主销毁:次战新编排器 fx_counters_battle 天然空,读 insurance_used=0〔无状态化 V6〕")
|
||||
|
||||
|
||||
func _smoke_tree_rules() -> void:
|
||||
print("--- 天赋树六键行为(V10:窗/限次/聚散/守侧)---")
|
||||
# 开局姿态组:每关首轮窗(battle_index 事实——引擎直构 + 自建 ctx)
|
||||
@@ -6078,13 +6130,13 @@ func _smoke_tree_rules() -> void:
|
||||
got_add = true
|
||||
check(got_mult and got_add, "锋:踩雷减半命中+限次记账(counter 0<2 闸开——damage_mult+counter_add 双行同预评估态)")
|
||||
EffectEngine.counter_add(ctx_fz, "lvl_tree_sense_sharp_used", 2) # 直调置数(V10 注入口径——置 level 桶计数后走事件路径)
|
||||
check((fz.dispatch(ctx_fz, "mine_hit", {}, Callable()) as Array).is_empty(), "锋:限次耗尽全额(counter 2 不<2 闸关——每关限次 provisional 2)")
|
||||
check((fz.dispatch(ctx_fz, "mine_hit", {}, Callable()) as Array).is_empty(), "锋:限次耗尽全额(counter 2 不<2 闸关——每关限次 provisional 2)〔无状态化 V5〕")
|
||||
var fz2 = load("res://core/effect_engine.gd").new(null)
|
||||
fz2.rebuild([], [], ["sense_sharp"])
|
||||
var ctx_fz2 := EffectContext.new()
|
||||
ctx_fz2.level_bucket = lvl_shared # 挂同一 level 桶引用(新形态跨战持久:无 export/seed,同字典即持久)
|
||||
check((fz2.dispatch(ctx_fz2, "mine_hit", {}, Callable()) as Array).is_empty(),
|
||||
"锋:限次跨战持久(level 桶共享引用——替代旧副本搬运链)")
|
||||
"锋:限次跨战持久(level 桶共享引用——替代旧副本搬运链)〔无状态化 V4〕")
|
||||
# 守侧五场景(契约 12):编排 rig——begin_battle 携 sense_guard,授予段 _grant_seg._judge_seal 直注
|
||||
var orch = load("res://core/battle_orchestrator.gd").new(_db, _fresh_rng(777001))
|
||||
check(orch.begin_battle({"level_index": 1, "node_depth": 0, "hero_hp": 40, "hero_atk": 8, "hero_max_hp": 40,
|
||||
|
||||
@@ -228,7 +228,7 @@ else
|
||||
echo "$S12_FACE" | tr '\n' '\0' | xargs -0 grep -En "$S12_SYM" 2>/dev/null
|
||||
fail=1
|
||||
else
|
||||
echo "[static_scan] S12 ok(扫描面 $S12_FC 个 .gd/.tres,旧件零残留)"
|
||||
echo "[static_scan] S12 ok(扫描面 $S12_FC 个 .gd/.tres,旧件零残留)〔无状态化 V10〕"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -113,7 +113,7 @@ func _init() -> void:
|
||||
"V4:counter_spend 静态写口消耗(用后清零语义承载面)〔专长批 V4〕")
|
||||
fx5.dispatch(ctx5, "round_start", {"round": 2})
|
||||
Kit.check_quiet(EffectEngine.counter(ctx5, "round_mines") == 0,
|
||||
"V4:round_ 前缀计数器随 round_start 整桶清空(旧 reset_at 名单声明制换代为前缀归桶)〔专长批 V4〕")
|
||||
"V4:round_ 前缀计数器随 round_start 整桶清空(旧 reset_at 名单声明制换代为前缀归桶)〔无状态化 V8〕")
|
||||
# battle 桶对照:无前缀 helm_layers 不受 round_start 影响(跨 round_start 存活)
|
||||
var fx6 = EffectEngineScript.new(null)
|
||||
var ctx6 := EffectContext.new()
|
||||
|
||||
@@ -26,6 +26,9 @@ func _init() -> void:
|
||||
Kit.check_quiet(false, "V9 前置:冒险启动")
|
||||
quit(Kit.finish("feat_vouchers"))
|
||||
return
|
||||
# V2——adventure 桶新冒险置空:start_adventure 后宿主字典为空(寿命随 RunLedger,无残留)
|
||||
Kit.check_quiet(a.run_ledger.adventure_counters.is_empty(),
|
||||
"V2:新冒险 adventure 桶置空(start_adventure 后 run_ledger.adventure_counters 为空)〔无状态化 V2〕")
|
||||
|
||||
# V9-1 刷新券:入存量账(冒险级)——反例=写进 _attune_refresh_x(X 每停点重置会吞存量)
|
||||
a._reset_refresh_x() # X 归零基线(模拟新停点)
|
||||
@@ -136,7 +139,7 @@ func _init() -> void:
|
||||
Kit.check_quiet(b4.resume_adventure(bp_legacy2, {}),
|
||||
"V13:旧档 adventure_counters 含改名前旧键续玩受理零崩溃(无迁移——旧键留桶成死键)〔卡② V13/H1〕")
|
||||
Kit.check_quiet(int(b2.run_ledger.adventure_counters.get("pain_layers", -1)) == 3 and b2.refresh_stock() == 2,
|
||||
"V16:续玩回填逐项一致(计数恢复——跨战账不丢)〔专长批 V16〕")
|
||||
"V16:续玩回填逐项一致(adventure 桶随断点往返·计数恢复)〔无状态化 V3〕")
|
||||
# V25 完美保险专长验收组(R2 全项:装载/限次一次/计数纯净/两账相减/跨战清零/事件不吞)
|
||||
var fi: Dictionary = db.feats.row_by_id("perfect_insurance")
|
||||
Kit.check_quiet(not fi.is_empty() and String(fi.get("rarity", "")) == "rare"
|
||||
@@ -178,7 +181,7 @@ func _init() -> void:
|
||||
orch._perfect_hit_false = 1
|
||||
orch._perfect_hit_true = 1
|
||||
Kit.check_quiet(orch.perfect_sweep_earned(),
|
||||
"判定相减:误标 1 − 豁免 1 = 有效 0 且标中≥1 → 完美成立〔卡② R2 真值表〕")
|
||||
"判定相减:误标1−豁免1=有效0且标中≥1→完美成立(保险每战限次一次迁移保绿)〔无状态化 V7〕")
|
||||
orch._perfect_hit_true = 0
|
||||
Kit.check_quiet(not orch.perfect_sweep_earned(),
|
||||
"判定守卫:标中数 0 时零误标也不成立(整图 ≥1 标中条件零松动)〔卡② R2 真值表〕")
|
||||
|
||||
@@ -67,5 +67,5 @@ func _init() -> void:
|
||||
if not _assert_rejected(BAD_REF_DIR, PROBE_REF, "counter_prefix_fatal_test/②悬空读点"):
|
||||
quit(2)
|
||||
return
|
||||
print("[counter_prefix_fatal_test] 双断言均正确拒绝(前缀合法性 + 引用闭合)")
|
||||
print("[counter_prefix_fatal_test] 双断言均正确拒绝(前缀合法性 + 引用闭合)〔无状态化 V9〕")
|
||||
quit(1)
|
||||
@@ -39,8 +39,30 @@
|
||||
| T4 round 泛化+宿主清零确认 | 并入 T2/T3 | ✅(round 整桶 clear+宿主 new 天然空) |
|
||||
| T5 前缀双落点+引用闭合+负面套件+manifest | d402ea14, 4c5bdbc9 | ✅ |
|
||||
| T6 数据行/合成行改名+domain/reset_at 删 | 7f45f904 | ✅ |
|
||||
| T7 断言迁移+S12+V12+变异 | b226a292, 003581f4, a9d5ac13, b42463c9 | ✅(见下) |
|
||||
| T8 产出物 | 本批 reports | 进行中 |
|
||||
| T7 断言迁移+§9 正向断言+S12+V12+变异 | b226a292, 003581f4, a9d5ac13, b42463c9, 33e1f110 | ✅(§9 见下) |
|
||||
| T8 产出物 | 本批 reports | ✅ |
|
||||
|
||||
## §9 逐需求点正向验收主力(V1–V14·补漏记录 33e1f110)
|
||||
|
||||
> 首合(d00f24a8)时本节缺 V1/V2/V6——只靠迁移旧测+V12 兜底。V12 formed/rules 输出面不作判据,adventure 桶跨战持久若坏不会红,核心缺陷消解无回归网。补漏批建齐并打〔无状态化 Vn〕尾缀:
|
||||
|
||||
| V | 需求点 | 落点 | 断言 | 变异拦截 |
|
||||
|---|---|---|---|---|
|
||||
| V1 | adventure 桶跨战持久(真实事件面) | smoke `_smoke_counter_buckets` | 同一 RunLedger 两 begin_battle 各真实 request_dig→adv_twin_digs 经 ctx 累积=2、第2战读到持久值1 | **变异红**(桶引用改新建空字典→3 断言 FAIL) |
|
||||
| V2 | adventure 桶新冒险置空 | feat_vouchers | start_adventure 后 run_ledger.adventure_counters 空 | — |
|
||||
| V3 | adventure 桶随断点往返 | feat_vouchers V16 换代 | 写桶→快照→回读逐键一致 | — |
|
||||
| V4 | level 桶同关跨战保持 | smoke `_smoke_tree_rules` | 共享 level 字典引用第2战读到限次值 | **变异红**(level 不共享→FAIL) |
|
||||
| V5 | tree_sense 每关限 2 | smoke `_smoke_tree_rules` | 置 2 后 mine_hit 闸关零命中 | — |
|
||||
| V6 | battle 桶随宿主销毁 | smoke `_smoke_counter_buckets` | 次战新编排器读 insurance_used=0 | — |
|
||||
| V7 | 保险每战限次迁移保绿 | feat_vouchers V25 | 组内断言原样绿(双账不改面) | — |
|
||||
| V8 | round 桶轮始清空 | effect_words_t1 ⑦ | round_ 前缀随 round_start 整桶 clear | — |
|
||||
| V9 | 前缀致命+引用闭合 | counter_prefix_fatal_test | meta_/悬空读点两断言拒绝 | **变异红**(前缀分支置 false/闭合降 info→quit2) |
|
||||
| V10 | 旧件零残留 | static_scan.sh S12 | game/**/*.gd+*.tres 旧符号 0 命中 | **变异红**(注入 counters_export→命中) |
|
||||
| V11 | 旧断言同批摘除 | F2 迁移 | smoke 裸引擎段+4 单测件 ctx 化 | — |
|
||||
| V12 | 同种子复放三组 | parity_compare.py | off 逐位/formed·rules 输入面恒等 | rules≠off 0 相同=非空转 |
|
||||
| V13 | 旧档加载不崩 | feat_vouchers | 含改名前旧键 resume 受理零崩 | — |
|
||||
| V14 | tree_sense 削弱目检 | 实机目检清单 | 每关第3次无减半/无返 AP | 用户实战验(只登记) |
|
||||
|
||||
|
||||
## V12 同种子复放三组判读(完成定义 6 主力证据)
|
||||
|
||||
|
||||
Reference in new issue
Block a user