## VERTICAL SLICE - NOT FOR PRODUCTION ## R1 难度行解析协作类:进度坐标 ceil 取行、越域 Fatal、告警去重,由 ConfigDb 门面持有(垂直切片验证:数值缺行不静默)。 ## 非直调面——全部消费方经 ConfigDb 同名方法取数;数据面与诊断通道均经构造注入 Callable(类型环断根)。 class_name ConfigDbResolver extends RefCounted var _diag: Callable # 诊断/致命通道(门面类型反持解耦,validator 先例:签名 (level, category, message)) var _board_gen_rows_get: Callable # () -> Array——board_gen 行集活读(数据面经 Callable 注入,ConfigDb 类型环断根) var _enemy_rows_get: Callable # () -> Array——enemy 行集活读 var _difficulty_get: Callable # () -> DifficultyTable(可空——表缺省合法态) var _warn_dedup: Dictionary[String, bool] = {} # R1 四元组去重注册表 func _init(diag_cb: Callable, board_gen_rows_cb: Callable, enemy_rows_cb: Callable, difficulty_cb: Callable) -> void: _diag = diag_cb _board_gen_rows_get = board_gen_rows_cb _enemy_rows_get = enemy_rows_cb _difficulty_get = difficulty_cb # 去重注册表清空(门面 load_tables / reset_diagnostics 调用) func reset_warn_dedup() -> void: _warn_dedup.clear() # ---- R1 难度行解析(ceil 向上取整保证偏难;域越界与内容缺口 Fatal 退出)---- func resolve_board_gen(L: int, D: int) -> Dictionary: return _resolve_progress(_board_gen_rows_get.call(), L, D, "board_gen") func resolve_enemy_rowset(L: int, D: int, row_kind: String) -> Array[Dictionary]: # 带寻址:L 维沿进度行解析现状(ceil 向上取整保证偏难、越最大行 clamp), # D 维经 EnemyTable.band_of 落带——命中该 (L, row_kind) 的某一个 depth_band, # 返回该带全部行、按表文件行序(行序即契约——同带键多行文件内相邻由 EnemyTable.validate 兜底)。 # 空集表达 = 空数组(band_keys 空时可达,交消费侧既有空行集 fatal 路径——validate 已拦无 Boss 行集)。 if L < 1 or D < 0: _diag.call("fatal", "request_oob", "enemy 请求越域 (%d,%d)——进度坐标低于合法域(关卡序号≥1、节点深度≥0)" % [L, D]) return [] if not EnemyTable.ENCOUNTER_ROW_KINDS.has(row_kind): # 开战寻址行类门——elite 行静置合法、任何寻址拿不到它(敌人系统.md:151) _diag.call("fatal", "request_oob", "enemy 请求行类非法 (%d,%d,\"%s\")——row_kind 域 {battle, boss}" % [L, D, row_kind]) return [] var rows: Array[Dictionary] = [] rows.assign(_enemy_rows_get.call()) var level_keys: Array[int] = _level_keys_of(rows) if level_keys.is_empty(): _diag.call("fatal", "structural", "enemy 行集为空——锚行校验应已拦截") return [] level_keys.sort() var l_star := _ceil_key(level_keys, L) if l_star < 0: l_star = int(level_keys[-1]) # 超出最大行 → 取最大行封顶 _warn_resolve("enemy", "resolve_level_clamp", "enemy 请求 (%d,%d) clamp 解析(超出最大关卡取最大值)→ 关卡 %d" % [L, D, l_star], l_star, D) elif l_star != L: _warn_resolve("enemy", "resolve_level_ceil", "enemy 请求 (%d,%d) ceil 解析(向上取整保证偏难)→ 关卡 %d" % [L, D, l_star], l_star, D) var band_keys: Array[int] = _band_keys_of(rows, l_star, row_kind) if band_keys.is_empty(): return [] band_keys.sort() var d_star := EnemyTable.band_of(band_keys, D) if d_star < 0: d_star = int(band_keys[-1]) # 越顶 clamp 顶带(调参事故面,跨表校验另报) _warn_resolve("enemy", "resolve_depth_clamp", "enemy 请求 (%d,%d) clamp 解析(超出顶带取顶带)→ (%d,band %d)" % [L, D, l_star, d_star], l_star, d_star) elif d_star != D: _warn_resolve("enemy", "resolve_depth_ceil", "enemy 请求 (%d,%d) ceil 解析(向上取整保证偏难)→ (%d,band %d)" % [L, D, l_star, d_star], l_star, d_star) return _band_rows(rows, l_star, row_kind, d_star) ## 行集关卡键收集(纯行扫描——告警发射序不变) func _level_keys_of(rows: Array) -> Array[int]: var level_keys: Array[int] = [] for row in rows: var lv := int(row.get("level_index", 0)) if not level_keys.has(lv): level_keys.append(lv) return level_keys ## 带键收集(纯行扫描——l_star × row_kind 的 depth_band 去重集) func _band_keys_of(rows: Array, l_star: int, row_kind: String) -> Array[int]: var band_keys: Array[int] = [] for row in rows: if int(row.get("level_index", 0)) == l_star and String(row.get("row_kind", "")) == row_kind: var bv := int(row.get("depth_band", -1)) if not band_keys.has(bv): band_keys.append(bv) return band_keys ## 带行收集(纯行扫描——命中带全部行、按表文件行序) func _band_rows(rows: Array, l_star: int, row_kind: String, d_star: int) -> Array[Dictionary]: var all_out: Array[Dictionary] = [] for row in rows: if int(row.get("level_index", 0)) == l_star and String(row.get("row_kind", "")) == row_kind \ and int(row.get("depth_band", -1)) == d_star: all_out.append(row) return all_out # 解析告警单点(类别 + 命中键四元组去重——R1 既有去重注册表) func _warn_resolve(table_id: String, category: String, message: String, l_key: int, d_key: int) -> void: var dedup_key := "%s|%s|%d|%d" % [table_id, category, l_key, d_key] if _warn_dedup.has(dedup_key): return _warn_dedup[dedup_key] = true _diag.call("warning", category, message) # 难度曲线与Boss DifficultyTable 消费面(敌人系统.spawn 调用):(L,D) 精确匹配修饰乘数, # 越域值 clamp(域常量读 DifficultyTable.MULT_MIN/MULT_MAX 单点——使用时 clamp 口径,warning 预登记同族) func resolve_difficulty_modifiers(L: int, D: int) -> Dictionary: var dt = _difficulty_get.call() if dt == null: return {} for row in dt.rows: if int(row.get("level_index", 0)) == L and int(row.get("node_depth", -1)) == D: return { "hp_mult": clampf(float(row.get("hp_mult", 1.0)), DifficultyTable.MULT_MIN, DifficultyTable.MULT_MAX), "atk_mult": clampf(float(row.get("atk_mult", 1.0)), DifficultyTable.MULT_MIN, DifficultyTable.MULT_MAX), } return {} func _resolve_progress(rows: Array, L: int, D: int, table_id: String) -> Variant: if L < 1 or D < 0: _diag.call("fatal", "request_oob", "%s 请求越域 (%d,%d)——进度坐标低于合法域(关卡序号≥1、节点深度≥0)" % [table_id, L, D]) return {} var level_keys: Array[int] = _level_keys_of(rows) if level_keys.is_empty(): _diag.call("fatal", "structural", "%s 行集为空——锚行校验应已拦截" % table_id) return {} level_keys.sort() var l_star := _ceil_key(level_keys, L) var l_clamped := l_star < 0 if l_clamped: l_star = int(level_keys[-1]) # 超出最大行 → 取最大行封顶(可取范围内向上取整,超出用最大值) var depth_keys: Array[int] = _depth_keys_of(rows, l_star) depth_keys.sort() var d_star := _ceil_key(depth_keys, D) var d_clamped := d_star < 0 if d_clamped: d_star = int(depth_keys[-1]) var missing := _missing_label(l_clamped, d_clamped, l_star != L, d_star != D) if missing != "": _emit_missing_warning(table_id, missing, [l_star, d_star], [L, D]) for row in rows: if int(row.get("level_index", 0)) == l_star and int(row.get("node_depth", 0)) == d_star: return row return {} ## 层键收集(纯行扫描——l_star 行的 node_depth 去重集) func _depth_keys_of(rows: Array, l_star: int) -> Array[int]: var depth_keys: Array[int] = [] for row in rows: if int(row.get("level_index", 0)) == l_star: var dv := int(row.get("node_depth", 0)) if not depth_keys.has(dv): depth_keys.append(dv) return depth_keys ## 解析偏移形态标签(clamp/ceil × level/depth/both 六形态——空串 = 精确命中; ## l_ceil/d_ceil = 解析值 ≠ 请求值) func _missing_label(l_clamped: bool, d_clamped: bool, l_ceil: bool, d_ceil: bool) -> String: var label := "" if l_clamped and d_clamped: label = "both_clamp" elif l_clamped: label = "level_clamp" elif d_clamped: label = "depth_clamp" elif l_ceil and d_ceil: label = "both_ceil" elif l_ceil: label = "level_ceil" elif d_ceil: label = "depth_ceil" return label ## 偏移告警发射(四元组去重注册表语义逐字——R1 既有去重; ## req/resolved = [L, D]/[l_star, d_star] 进度坐标对) func _emit_missing_warning(table_id: String, missing: String, resolved: Array, req: Array) -> void: var dedup_key := "%s|%s|%d|%d" % [table_id, missing, resolved[0], resolved[1]] if not _warn_dedup.has(dedup_key): _warn_dedup[dedup_key] = true var verb := "clamp 解析(超出最大行取最大值)" if missing.contains("clamp") else "ceil 解析(向上取整保证偏难)" _diag.call("warning", "resolve_" + missing, "%s 请求 (%d,%d) %s → (%d,%d) [%s]——2026-09-18 拍板" % [table_id, req[0], req[1], verb, resolved[0], resolved[1], missing]) # 取 sorted_keys 中第一个 >= request 的键;无(请求高于最大行)返回 -1 → 调用方 Fatal func _ceil_key(sorted_keys: Array, request: int) -> int: for k in sorted_keys: if int(k) >= request: return int(k) return -1