test(迁移): 批 B 波 1 G5 套1 末点 AP 封印回归五条迁入新建宿主 seal_polarity_test.gd——新宿主落位+manifest 登记+剪切挂载绿(宿主 5 检查)+按条变异 5/5 验红(受理守卫恒拒/dig 扣费+1/revealed_cells 置空/seal 计费 99/try_spend 耗尽仲裁恒假各验红);smoke_all.gd 同批删函数节头块与调用行;闸01 剩余面 976 绿

This commit is contained in:
DKChan committed 2026-10-23 03:38:50 +08:00
1 parent 9b91731055
commit 5ed1ec99af
4 files changed
+82 -37

No files matched your search

@@ -0,0 +1,74 @@
# tests/unit/battle_settlement/seal_polarity_test.gd — 封印与极性单元测试宿主
# 断言面 = 八套(批 B 断言迁移自 smoke_all.gd,G5 施工组;八套按源编排序分八笔原子提交迁入):
# 末点 AP 封印轮末结算(playtest 缺陷②回归——action_economy 末点花费与轮终结)
# 封印不可逆四情况(禁撤封印 + 挖封印格兑付改判——minesweeper_rules 拒绝面)
# 清图奖励双份兑付链(真实流完美封印——orchestrator grant_clear 身份兑付)
# 清图奖励弱形式分支(零兑付 / 高光守卫 / 第二份拒——直调编排私有面构造)
# 轮内刷新 provenance 守卫(刷新图清图不发清图奖励)
# 极性路由 + 封印溢价 125%(挖安全格正向 / 挖危险格负向 / 标中标空兑付极性)
# 负向字典逐型直验(效果行 / heal 直伤 / blast 警觉 / action 行动点排队)
# 格面资源资格面(揭示事件 resource 标记 + 封锁格身份查询)
# 协议照单元侧惯例:extends SceneTree+Kit.check 主通道;--script 模式无 autoload,
# ConfigDB 显式实例化构造注入(各套自建 RngService——源套掷点隔离形态,宿主不持统一流);
# 表加载失败不中止(沿被迁断言面的源语义——诊断在此展开,表值变异的红由具体断言落,承 G2/G3/G4 同款)。
# 运行:godot --headless --path game --script res://tests/unit/battle_settlement/seal_polarity_test.gd
extends SceneTree
const Kit := preload("res://tests/unit/test_kit.gd")
const ConfigDBScript := preload("res://core/config_db.gd")
const AutoPlayer := preload("res://smoke/auto_player.gd") # 自动玩家策略单一实现(迁移期按现路径 preload——账本 §五夹具前提)
var _db
func _init() -> void:
_db = ConfigDBScript.new()
# 表加载失败不中止(承 G2/G3/G4 同款:表损坏的红落在具体断言上——
# 诊断在此展开,后续断言按坏表实况逐条验红;collect_only=true 下成员照常赋值可评)
var load_ok: bool = _db.load_tables("res://data/tables", true)
if not load_ok:
push_error("[seal_polarity_test] 表加载返回失败——诊断如下(红由具体断言落)")
for d in _db.diagnostics():
if d.severity == "error" or d.severity == "fatal":
push_error(" [%s] %s: %s" % [d.severity, d.category, d.message])
# 套执行序沿源编排序
_smoke_seal_ap_exhausted()
quit(Kit.finish("seal_polarity_test"))
# ---- 末点 AP 封印轮末结算(playtest 缺陷②回归:末点 AP 花在封印必须终结轮次进入下一轮)----
func _smoke_seal_ap_exhausted() -> void:
print("--- 排雷玩法·封印动作耗尽末点 AP 回归 ---")
var rng = load("res://core/rng_service.gd").new()
rng.set_master_seed(20260911)
var settlement = load("res://core/battle_orchestrator.gd").new(_db, rng)
var rounds: Array = []
settlement.round_started.connect(func(ri): rounds.append(ri))
Kit.check("回归战斗启动(Boss 行——D0 20HP 级会被盲挖粉尘秒杀,无法承载封印回归场景)",
settlement.begin_battle({"level_index": 1, "node_depth": 4, "hero_hp": int(_db.hero.max_hp), "node_type": "boss"}))
var minesweeper = settlement.minesweeper
# 恰花 (AP-1) 点挖掘,留末点给封印(表驱动——AP 从表读不写死)
var ap_total: int = int(_db.action_economy.ap_per_round)
for i in range(ap_total - 1):
if settlement.action_economy.phase != "Active" or settlement.action_economy.ap == 0:
break
var plan = AutoPlayer.choose_dig(minesweeper)
if plan.is_empty():
break
if plan.hero_cell != minesweeper.hero_pos():
minesweeper.settle_batch([{"action": "move", "cell": plan.hero_cell}])
minesweeper.settle_batch([{"action": "dig", "cell": plan.dig_cell}])
Kit.check("%d 次挖掘后恰剩 1 AP(phase=%s ap=%d)" % [ap_total - 1, str(settlement.action_economy.phase), settlement.action_economy.ap],
settlement.action_economy.phase == "Active" and settlement.action_economy.ap == 1)
# 末点 AP 花在封印——轮次必须终结并结算进入第 2 轮
# 封印目标 = 挖掘策略的下一目标格(构造保证:未开、与小人邻接——先把小人移到其邻接已开格)
var plan2 = AutoPlayer.choose_dig(minesweeper)
Kit.check("仍存在可挖目标(封印目标来源)", not plan2.is_empty())
var out: Array = []
if not plan2.is_empty():
if plan2.hero_cell != minesweeper.hero_pos():
minesweeper.settle_batch([{"action": "move", "cell": plan2.hero_cell}])
out = minesweeper.settle_batch([{"action": "seal_place", "cell": plan2.dig_cell}])
Kit.check("末点 AP 封印被受理", not out.is_empty() and bool(out[0].accepted))
Kit.check("封印动作耗尽 AP 触发轮末结算并进入第 2 轮(rounds=%s)" % str(rounds), rounds.size() >= 2)