test(敌人表深度带): 冒烟与单测断言按 S 清单改写
冒烟全部寻址点改为三参 resolve_enemy_rowset(关卡, 深度, 行类),结算/单元/探针直呼的 spawn 与 begin_battle 显式带行类(battle/boss)——终点战仍按 Boss 行集取数,行为不变。 首遇位断言改为扫表取该 (关卡, battle, 敌种) 的最低深度带,不再写死坐标〔fv21〕;新增 _enemy_bands 结构段验 20 行键序、hobgoblin 留任 (1,battle,3)、三 Boss 行类与带键〔fv11–fv13〕; L2 混编 (2,battle,5) 行序与骰和、巨蜘蛛/bugbear/duergar 首遇带固定数、Boss 行类显式传入 等断言逐条加〔fv18/fv19/fv22–fv24〕尾缀。职业节奏探针与伤害探针同步三参寻址。 变异验证七项全部命中(记录表进实现报告):band_of 反向 floor → fv1/fv3 红;row_kind 枚举 判据注释 → fv7 红;Boss 同带判据删除 → fv15 红;顶带消解判据短路 → fv16 红;巨蜘蛛首遇行 加 unit_count_max → fv22 红;混编两行文件内对调 → fv18/fv11 红;hobgoblin 迁错带键 → fv11/fv12 红(直接迁到带 2 先被加载期同带规则拦下,改用与带 2 行互换带键,表可加载后键位断言红)。
This commit is contained in:
1 parent
07f3eb55e3
commit
61537da889
7 files changed
+410
-165
No files matched your search
@@ -11,7 +11,7 @@ const Kit := preload("res://tests/unit/test_kit.gd") # T6 收口:_check/汇
|
||||
func _init() -> void:
|
||||
var db = ConfigDBScript.new()
|
||||
var load_ok: bool = db.load_tables("res://data/tables", true)
|
||||
Kit.check("全部表加载 + 校验通过(含跨表护栏零 error 诊断)", load_ok and db.diagnostics_count("error") == 0)
|
||||
Kit.check("全部表加载 + 校验通过(含跨表护栏零 error 诊断)〔fv6〕", load_ok and db.diagnostics_count("error") == 0)
|
||||
Kit.check("is_ready 通道随加载置位", db.is_ready)
|
||||
if not load_ok:
|
||||
for d in db.diagnostics():
|
||||
@@ -59,8 +59,8 @@ func _test_progress_resolution(db) -> void:
|
||||
|
||||
# enemy 行集同通道:同 (L,D) 行集数组非空(关卡节点地图 前置——battle 节点双表精确行集契约;
|
||||
# 行集面契约:返回形态是行集数组,精确性断言随行集面)
|
||||
var en_got: Array = db.resolve_enemy_rowset(int(probe_row.level_index), int(probe_row.node_depth))
|
||||
Kit.check("enemy 行集同坐标解析非空(双表精确行契约)", not en_got.is_empty())
|
||||
var en_got: Array = db.resolve_enemy_rowset(int(probe_row.level_index), int(probe_row.node_depth), "battle")
|
||||
Kit.check("enemy 行集同坐标解析非空(双表精确行契约——battle 行类)", not en_got.is_empty())
|
||||
|
||||
# 深度 clamp:请求深度超最大行 → 取该关最大深度行 + 警告诊断一次(去重)
|
||||
db.reset_diagnostics()
|
||||
@@ -197,44 +197,46 @@ func _test_rowset_discipline() -> void:
|
||||
# 数组字面量会触发「Invalid assignment」脚本错误——该错误不改退出码,却会**中断本函数剩余断言**
|
||||
#(本函数五条纪律断言曾因此全部静默不跑,套件仍报 all green,是零覆盖假象)。
|
||||
const EnemyTableScript := preload("res://data/schemas/enemy_table.gd")
|
||||
var mk_row := func(l: int, d: int, eid: String) -> Dictionary:
|
||||
return {"level_index": l, "node_depth": d, "enemy_id": eid, "display_name": eid + "名",
|
||||
var mk_row := func(l: int, kind: String, band: int, eid: String) -> Dictionary:
|
||||
return {"level_index": l, "row_kind": kind, "depth_band": band, "enemy_id": eid, "display_name": eid + "名",
|
||||
"unit_count": 1, "hp": 10, "atk": 2, "pool": [{"skill_id": "attack", "weight": 9}]}
|
||||
# 正向:同坐标两行不同敌种(相邻)= 混编合法,validate 零错
|
||||
# 正向:同带键两行不同敌种(相邻)= 混编合法,validate 零错
|
||||
var t_mix = EnemyTableScript.new()
|
||||
t_mix.rows.assign([mk_row.call(1, 5, "goblin"), mk_row.call(1, 5, "bugbear"),
|
||||
mk_row.call(1, 0, "goblin")]) # 末行=depth-0 锚行(validate 的 anchor 规则:每 level 必须有)
|
||||
t_mix.rows.assign([mk_row.call(1, "battle", 5, "goblin"), mk_row.call(1, "battle", 5, "bugbear"),
|
||||
mk_row.call(1, "battle", 0, "goblin"), mk_row.call(1, "boss", 9, "ogre_chief")])
|
||||
var errs: Array = t_mix.validate()
|
||||
Kit.check("混编行集加载通过(同坐标两行不同敌种相邻——行集恰一敌种校验退役的正向面)", errs.is_empty())
|
||||
# 正向:Boss 坐标两行同构合法(P4 乙——Boss 行集校验同样放开,加载层无 Boss 单行硬闸)
|
||||
Kit.check("混编行集加载通过(同带键两行不同敌种相邻——行集恰一敌种校验退役的正向面)", errs.is_empty())
|
||||
# 正向:Boss 行集两行同构合法(P4 乙——Boss 行集校验同样放开,加载层无 Boss 单行硬闸)
|
||||
var t_boss = EnemyTableScript.new()
|
||||
t_boss.rows.assign([mk_row.call(2, 9, "drider"), mk_row.call(2, 9, "bugbear"),
|
||||
mk_row.call(2, 0, "drider")]) # 末行=depth-0 锚行
|
||||
t_boss.rows.assign([mk_row.call(2, "battle", 0, "drider"), mk_row.call(2, "boss", 9, "drider"),
|
||||
mk_row.call(2, "boss", 9, "bugbear")])
|
||||
errs = t_boss.validate()
|
||||
Kit.check("Boss 坐标混编行集加载通过(P4 乙——Boss 多行合法,无硬闸)", errs.is_empty())
|
||||
# 负向:同坐标行不相邻 = rowset_rule 且报错定位到坐标(R6 行序纪律 + R3 错误类别可定位)
|
||||
Kit.check("Boss 带混编行集加载通过(P4 乙——Boss 多行合法,无硬闸)", errs.is_empty())
|
||||
# 负向:同行集行不相邻 = rowset_rule 且报错定位到带键(R6 行序纪律 + R3 错误类别可定位)
|
||||
var t_gap = EnemyTableScript.new()
|
||||
t_gap.rows.assign([mk_row.call(1, 5, "goblin"), mk_row.call(1, 9, "hobgoblin"), mk_row.call(1, 5, "bugbear"),
|
||||
mk_row.call(1, 0, "goblin")]) # 末行=depth-0 锚行(隔断关系不受影响)
|
||||
t_gap.rows.assign([mk_row.call(1, "battle", 5, "goblin"), mk_row.call(1, "battle", 9, "hobgoblin"),
|
||||
mk_row.call(1, "battle", 5, "bugbear"), mk_row.call(1, "battle", 0, "goblin"),
|
||||
mk_row.call(1, "boss", 9, "ogre_chief")])
|
||||
errs = t_gap.validate()
|
||||
var gap_hit := false
|
||||
for e in errs:
|
||||
if String(e.get("category", "")) == "rowset_rule" and String(e.get("message", "")).contains("(1,5)"):
|
||||
if String(e.get("category", "")) == "rowset_rule" and String(e.get("message", "")).contains("(1,battle,5)"):
|
||||
gap_hit = true
|
||||
Kit.check("行序相邻校验:同坐标行被隔断报 rowset_rule 且定位坐标(R6——行序即契约加载期兜底)", gap_hit)
|
||||
Kit.check("行序相邻校验:同带键行被隔断报 rowset_rule 且定位带键〔fv9〕〔fv20〕", gap_hit)
|
||||
# 负向:同敌种第二行仍被 dup_key 拦(键含 enemy_id——纪律①既有通道不回归)
|
||||
var t_dup = EnemyTableScript.new()
|
||||
t_dup.rows.assign([mk_row.call(1, 5, "goblin"), mk_row.call(1, 5, "goblin"),
|
||||
mk_row.call(1, 0, "goblin")]) # 末行=depth-0 锚行
|
||||
t_dup.rows.assign([mk_row.call(1, "battle", 5, "goblin"), mk_row.call(1, "battle", 5, "goblin"),
|
||||
mk_row.call(1, "battle", 0, "goblin"), mk_row.call(1, "boss", 9, "ogre_chief")])
|
||||
errs = t_dup.validate()
|
||||
var dup_hit := false
|
||||
for e in errs:
|
||||
if String(e.get("category", "")) == "dup_key":
|
||||
dup_hit = true
|
||||
Kit.check("行集内同敌种第二行仍被 dup_key 拦(纪律①——enemy_id 唯一)", dup_hit)
|
||||
Kit.check("同带键同敌种二行被 dup_key 新键拦(纪律①——enemy_id 唯一)〔fv8〕", dup_hit)
|
||||
# 负向:域校验不回归(单行 unit_count 越域仍拦——UNIT_COUNT_MAX 单种数语义下的同款域闸)
|
||||
var t_dom = EnemyTableScript.new()
|
||||
t_dom.rows.assign([mk_row.call(1, 5, "goblin"), mk_row.call(1, 0, "goblin")]) # 末行=depth-0 锚行
|
||||
t_dom.rows.assign([mk_row.call(1, "battle", 5, "goblin"), mk_row.call(1, "battle", 0, "goblin"),
|
||||
mk_row.call(1, "boss", 9, "ogre_chief")])
|
||||
t_dom.rows[0]["unit_count"] = 4
|
||||
errs = t_dom.validate()
|
||||
var dom_hit := false
|
||||
@@ -242,3 +244,30 @@ func _test_rowset_discipline() -> void:
|
||||
if String(e.get("category", "")) == "domain" and String(e.get("message", "")).contains("unit_count"):
|
||||
dom_hit = true
|
||||
Kit.check("单行数量域 [1,3] 域闸不回归(UNIT_COUNT_MAX 语义 = 单种数)", dom_hit)
|
||||
# 负向:row_kind 封闭枚举(非法值拒——键面换代后新增判据)
|
||||
var t_kind = EnemyTableScript.new()
|
||||
t_kind.rows.assign([mk_row.call(1, "elite", 5, "goblin"), mk_row.call(1, "battle", 0, "goblin"),
|
||||
mk_row.call(1, "boss", 9, "ogre_chief")])
|
||||
errs = t_kind.validate()
|
||||
var kind_hit := false
|
||||
for e in errs:
|
||||
if String(e.get("category", "")) == "domain" and String(e.get("message", "")).contains("row_kind"):
|
||||
kind_hit = true
|
||||
Kit.check("非法 row_kind 被拒(封闭枚举 {battle, boss})〔fv7〕", kind_hit)
|
||||
# 负向:anchor 两半——缺 battle band 0 锚行、缺 Boss 行集,各自报 anchor
|
||||
var t_no_anchor = EnemyTableScript.new()
|
||||
t_no_anchor.rows.assign([mk_row.call(1, "battle", 5, "goblin"), mk_row.call(1, "boss", 9, "ogre_chief")])
|
||||
errs = t_no_anchor.validate()
|
||||
var no_anchor_hit := false
|
||||
for e in errs:
|
||||
if String(e.get("category", "")) == "anchor" and String(e.get("message", "")).contains("band 0"):
|
||||
no_anchor_hit = true
|
||||
Kit.check("缺 (battle, band 0) 锚行报 anchor〔fv10〕", no_anchor_hit)
|
||||
var t_no_boss = EnemyTableScript.new()
|
||||
t_no_boss.rows.assign([mk_row.call(1, "battle", 0, "goblin"), mk_row.call(1, "battle", 5, "bugbear")])
|
||||
errs = t_no_boss.validate()
|
||||
var no_boss_hit := false
|
||||
for e in errs:
|
||||
if String(e.get("category", "")) == "anchor" and String(e.get("message", "")).contains("Boss"):
|
||||
no_boss_hit = true
|
||||
Kit.check("缺 Boss 行集报 anchor(每关 Boss 行集 ≥1)〔fv10〕", no_boss_hit)
|
||||
Reference in new issue
Block a user