merge(master)+禁令残留清扫:并回 master 新进提交(gdstyle 闸件批/S9 卡/iter36 收尾),冲突 test-conventions §8.4 保重编号版+吸收 master 新条款「判据绑可观测提交面」(措辞去变异化);随批清扫——待办清单 gdstyle/S9 两条目「变异验证义务」改撤销证明口径;S9 活卡全量改写(契约 3/T2/D2/D4/来源行/对照表列头/审计面/两轮 grilling 记录——旧「闸件豁免」定界标注经用户全项目禁令推翻,验证义务统一撤销证明,禁令条款原文保留)

This commit is contained in:
DKChan committed 2026-10-25 01:31:21 +08:00
commit e89f486aa9
94 files changed
+4608 -3451

No files matched your search

@@ -72,14 +72,6 @@ static func _errs_has_cross_field(errs: Array) -> bool:
return false
# 该关 Boss 节点深度(单终点图的终点编号——数据驱动,禁写死坐标)
func _boss_depth(level_index: int) -> int:
for n in _level_active_nodes(level_index):
if String(n.get("type", "")) == "boss":
return int(n.get("node_depth", -1))
return -1
# 首遇带数据驱动定位(契约 8):该 (L, battle, enemy_id) 的最低 depth_band,禁写死坐标数字
func _first_encounter_band(level_index: int, enemy_id: String) -> int:
var best := -1
@@ -94,17 +86,6 @@ func _first_encounter_band(level_index: int, enemy_id: String) -> int:
return best
# 模板感知取节点表(row.templates 非空取模板 0=现行固定图,保持既有断言语义)
func _level_active_nodes(level_index: int) -> Array:
for row in _db.level.rows:
if int(row.level_index) == level_index:
var tpls: Array = row.get("templates", [])
if not tpls.is_empty():
return tpls[0].get("nodes", [])
return row.get("nodes", [])
return []
# ① 冒险表(单行全局 Rule 4 豁免——建表与接线闸;TP0 令牌池:配额结构/件值对/池总量域检)
func _smoke_adventure_table() -> void:
print("--- 冒险表(AdventureTable——令牌池行值单点:回血/配额/件值对/同调位)---")
@@ -222,26 +203,31 @@ func _smoke_adventure_table() -> void:
v18_ok and locked_n == 12)
# ---- 敌人表深度带键结构(迭代 34:20 行键迁移 · 键序=迁移表序 · hobgoblin 留任 · 三 Boss 行 kind/band)----
# ---- 敌人表深度带键结构(迭代 34 建·迭代 35 覆盖批换代:28 行键序=覆盖表序·hobgoblin 留任·Boss 行集带键清单)----
func _smoke_enemy_bands() -> void:
print("--- 敌人表深度带键结构(20 行键序 · hobgoblin 留任 · 三 Boss 行)---")
# ① 20 行计数 + 键序 = 迁移表序(文件行序不变——行序即契约)
print("--- 敌人表深度带键结构(28 行键序 · hobgoblin 留任 · Boss 带键覆盖表)---")
# ① 28 行计数 + 键序 = 覆盖表序(文件行序不变——行序即契约)
# 迭代 35 生成图深度扩面覆盖批随动:战斗带顶扩到各关最大生成深度(L1→6/L2→9/L3→13)、
# Boss 行按终点深度分带(L1 6/L2 8·9/L3 11·12·13),模板时代带键 4/9/9 全部在册不动
var expect_keys: Array[String] = [
"1|battle|0|goblin", "1|battle|1|goblin", "1|battle|2|bugbear", "1|battle|3|hobgoblin",
"1|boss|4|ogre_chief",
"1|battle|6|bugbear",
"1|boss|4|ogre_chief", "1|boss|6|ogre_chief",
"2|battle|0|bugbear", "2|battle|1|bugbear", "2|battle|4|giant_spider",
"2|battle|5|bugbear", "2|battle|5|giant_spider", "2|battle|6|giant_spider", "2|battle|7|giant_spider",
"2|boss|9|drider",
"2|battle|9|giant_spider",
"2|boss|8|drider", "2|boss|9|drider",
"3|battle|0|duergar", "3|battle|1|hook_horror", "3|battle|4|hook_horror", "3|battle|5|duergar",
"3|battle|6|hook_horror", "3|battle|7|duergar", "3|boss|9|duergar_king",
"3|battle|6|hook_horror", "3|battle|7|duergar", "3|battle|13|duergar",
"3|boss|9|duergar_king", "3|boss|11|duergar_king", "3|boss|12|duergar_king", "3|boss|13|duergar_king",
]
var got_keys: Array[String] = []
for row in _db.enemy.rows:
got_keys.append("%d|%s|%d|%s" % [int(row.get("level_index", -1)), String(row.get("row_kind", "")),
int(row.get("depth_band", -1)), String(row.get("enemy_id", ""))])
Kit.check("敌人表 20 行且键序 = 迁移表序((L,row_kind,depth_band,enemy_id) 逐行比对——文件行序不变)〔fv11〕",
_db.enemy.rows.size() == 20 and got_keys == expect_keys)
Kit.check("敌人表 28 行且键序 = 覆盖表序((L,row_kind,depth_band,enemy_id) 逐行比对——文件行序不变)〔fv11〕",
_db.enemy.rows.size() == 28 and got_keys == expect_keys)
# ② hobgoblin 缺口行留任随迁(契约 9:不删行不补立绘——缺口登记随行)
var hob := {}
for row in _db.enemy.rows:
@@ -252,23 +238,27 @@ func _smoke_enemy_bands() -> void:
and int(hob.get("depth_band", -1)) == 3)
Kit.check("hobgoblin 缺口登记随行(表文件注释在位——缺口不静默)〔fv25〕",
FileAccess.get_file_as_string("res://data/tables/enemy.tres").contains("hobgoblin 行为缺口行"))
# ③ 三 Boss 行 kind/band 就位(band = 该关图 Boss 节点深度——单终点图数据驱动)
# ③ Boss 行集带键 = 覆盖表(旧判据「各恰一行=图 Boss 节点深度」属单终点模板时代;
# 生成图多终点要求每终点深度解析到互异带键 ⇒ 每关 Boss 行必然多于一行——
# 迭代 35 覆盖批随动改写为带键清单,「带键互异」的运行时把关在 level_shop_economy_test〔v11〕)
var boss_bands := {}
for row in _db.enemy.rows:
if String(row.get("row_kind", "")) == "boss":
var lk: int = int(row.get("level_index", -1))
if not boss_bands.has(lk):
boss_bands[lk] = []
boss_bands[lk].append(int(row.get("depth_band", -1)))
var expect_bands := {1: [4, 6], 2: [8, 9], 3: [9, 11, 12, 13]}
var boss_ok := true
var boss_detail := ""
for L in [1, 2, 3]:
var bdepth := _boss_depth(L)
var hits := 0
for row in _db.enemy.rows:
if int(row.get("level_index", -1)) == L and String(row.get("row_kind", "")) == "boss":
hits += 1
if int(row.get("depth_band", -1)) != bdepth:
boss_ok = false
boss_detail += " L%d:%d≠%d" % [L, int(row.get("depth_band", -1)), bdepth]
if hits != 1:
var got: Array = boss_bands.get(L, [])
got.sort()
if got != expect_bands[L]:
boss_ok = false
boss_detail += " L%d:boss 行×%d" % [L, hits]
Kit.check("三关 Boss 行各恰一行且 row_kind=boss、band=图 Boss 节点深度(%d/%d/%d%s)〔fv13〕" % [
_boss_depth(1), _boss_depth(2), _boss_depth(3), boss_detail], boss_ok)
boss_detail += " L%d:%s≠%s" % [L, str(got), str(expect_bands[L])]
Kit.check("三关 Boss 行集带键 = 覆盖表(模板终点 4/9/9 在册+生成图终点 6/8/9/11/12/13 扩带)%s〔fv13〕" % boss_detail,
boss_ok)
# ② 免伤墙归零护栏泛化保留(BUG-0003 事故类永久免疫):hero_defense 池任何 percent 行