# VERTICAL SLICE - NOT FOR PRODUCTION # Validation Question: 挖掘期撞上推理断头时,玩家能否从掉落池捡到秘宝、在关键时刻花掉买回情报或行动点(P0) # Date: 2026-09-29(迭代 7 T1 数据面——秘宝内容批;设计权威 design/gdd/systems/排雷循环/秘宝.md v0.4+ # + registry 秘宝条目六行 mvp_content;2026-09-29 用户拍板:①乙 探宝罗盘退役留痕 ④甲 显影尘/地穴全图卷失义件 # 六行全建零投放「已解锁·能力封存中」) # 数据配置 TreasureItemTable schema(秘宝 回填 owner)。 # 行 = Dictionary,键 item_id(Rule 4 豁免:定义表——registry 秘宝条目 Rule 4 豁免先例)。 # 七字段(registry fields 全量):item_id 主键 / display_name / dimension_tags ⊆ 五维 非空 / # effect_kinds ⊆ {mine_reveal, reward_preview, ap_grant}(活性校验见下)/ target ∈ {none, area_3x3, board_wide} / # magnitude [0,999](仅 ap_grant 行消费,加载校验 ≥1)/ use_phase ∈ {active_dig}。 # additive 两标记(迭代 7 T1——拍板①④的表内表达,非 registry fields 预登记字段的扩列随批登记): # retired = 退役留痕行(loot_compass——未开格类型微光常显覆盖预读价值,2026-09-29 用户拍板退役; # 行名保留=meta.tres workshop_items 六件词表恰全校验兼容,存档 item_unlocks 旧键无害; # 免活性校验、不入投放校验、不入 F2 覆盖面、奖励节点/掉落池排除) # deferred = 效果失义待重定行(probe_dust/catacomb_scroll——原显影半边随雾格移除失义,效果与目标 # 随秘宝整体重设计归 Alpha(2026-09-20 用户拍板);免 effect_kinds 非空校验、不入投放与 F2) # 承重护栏(秘宝 GDD §结构冻结,schema 校验强制不靠运行时拦截): # 真视窄域——effect_kinds 含 mine_reveal 的活行 target 必须 area_3x3(真视一次最多 3×3,禁全图看雷); # board_wide 仅恢复推理原料类——target=board_wide 的活行 effect_kinds 不得含 mine_reveal(现行无此类活行, # 显影载体待 Alpha 重定后落位)。 # 同调实施批扩列(迭代 11 第①批 T1,2026-10-03——任务书 v1.1;设计权威 proposal-magic-item-attunement-2026-09-22): # form ∈ {"", "passive", "active_charged"}(空 = 切片期过渡形态行——掉落/停点渠道现行承载,T7 退役; # passive = 装配整局生效;active_charged = 每冒险充能、挖掘期发起); # charges_per_adventure(active_charged ≥1 / passive 恒 0);slot_cost(同调行恒 1——底稿裁决 5,schema 强制); # unlock_requires 谓词行 [{key ∈ AttunementGrowthTable.COUNTER_KEYS, threshold ∈ [1,999]}](空 = 已解锁—— # 首批全解锁合法态,底稿 §2.2 用户裁;正式解锁渠道归 元进度 道具工坊柜台); # effective_rounds(前 N 轮限时件轮数——P4 甲表值化;仅 ap_rounds_front 行消费); # charge_n(充能进度阈值 N——仅 ap_charge_safe 行消费)。 # 🔴 零裸 flat 结构护栏(任务书 §三 1——机制轴禁无条件属性加项):行键白名单封闭(KEY_WHITELIST 外键 = # 加载致命)+ effect_kinds 封闭枚举只收条件触发/机制修正类 kind——任何「无条件属性加项」类效果不得以 # 新 kind 或新键入表(返工红线)。 class_name TreasureItemTable extends Resource @export var rows: Array = [] # Array[Dictionary] 键 item_id const DIMENSIONS := ["info", "risk", "action", "plan", "counter"] # 同调批扩 enum(迭代 11 第①批 T1)——新增九 kind 全部条件触发/机制修正类;mine_reveal/ap_grant 语义不变。 # cell_removal = 爆破工兵包中立移除格(T7 原位换装时启用——T6 影响评估前置);mine_hit_halve 系固定 # 「减半」语义不消费 magnitude(反弹 N 由 reflect_damage 行 magnitude 承载)。 const EFFECT_KINDS := ["mine_reveal", "reward_preview", "ap_grant", "venom_rider", "flag_burst", "mine_hit_halve", "reflect_damage", "ap_rounds_front", "ap_charge_safe", "cell_removal", "reward_weight_bias", "bonus_refresh"] const TARGETS := ["none", "area_3x3", "board_wide"] const USE_PHASES := ["active_dig"] const FORMS := ["", "passive", "active_charged"] # magnitude 消费面(≥1 校验):ap_grant 与同调 N 值 kind;其余 kind 活行 magnitude 恒 0 const MAGNITUDE_KINDS := ["ap_grant", "venom_rider", "flag_burst", "reflect_damage", "ap_rounds_front", "ap_charge_safe", "reward_weight_bias", "bonus_refresh"] # 🔴 零裸 flat 结构护栏:行键白名单封闭(键出域=加载致命)——机制轴禁无条件属性加项的表结构承载 const KEY_WHITELIST := ["item_id", "display_name", "dimension_tags", "effect_kinds", "target", "magnitude", "use_phase", "retired", "deferred", "form", "charges_per_adventure", "slot_cost", "unlock_requires", "effective_rounds", "charge_n"] func validate() -> Array: var errs: Array = [] if rows.is_empty(): # 空表合法态(2026-09-17 用户拍板——切片期无道具内容;F2 覆盖检查仅对非空清单执行) return errs var seen := {} for row in rows: var iid: String = row.get("item_id", "") if iid == "": errs.append({"category": "domain", "message": "item_id 空"}) continue if seen.has(iid): errs.append({"category": "dup_key", "message": "item_id 重复: %s" % iid}) continue seen[iid] = true if String(row.get("display_name", "")) == "": errs.append({"category": "domain", "message": "%s display_name 空" % iid}) var retired: bool = bool(row.get("retired", false)) var deferred: bool = bool(row.get("deferred", false)) # dimension_tags:五维词表 + 非空(退役/失义行仍须登记维度——语义面保留) var tags: Array = row.get("dimension_tags", []) if tags.is_empty(): errs.append({"category": "domain", "message": "%s dimension_tags 空" % iid}) for tag in tags: if not DIMENSIONS.has(String(tag)): errs.append({"category": "enum", "message": "%s dimension_tag 出域 %s: %s" % [iid, str(DIMENSIONS), str(tag)]}) var kinds: Array = row.get("effect_kinds", []) var target: String = String(row.get("target", "none")) if not TARGETS.has(target): errs.append({"category": "enum", "message": "%s target 出域 %s: %s" % [iid, str(TARGETS), target]}) var phase: String = String(row.get("use_phase", "active_dig")) if not USE_PHASES.has(phase): errs.append({"category": "enum", "message": "%s use_phase 出域 %s: %s" % [iid, str(USE_PHASES), phase]}) # 🔴 零裸 flat 结构护栏:键白名单封闭(同调批 T1——机制轴禁无条件属性加项) for k in row.keys(): if not KEY_WHITELIST.has(String(k)): errs.append({"category": "zero_flat", "message": "%s 行键出白名单: %s(KEY_WHITELIST 外键禁入)" % [iid, String(k)]}) var form: String = String(row.get("form", "")) if not FORMS.has(form): errs.append({"category": "enum", "message": "%s form 出域 %s: %s" % [iid, str(FORMS), form]}) if retired or deferred: # 退役/失义行:免 effect_kinds 非空与承重护栏校验(登记面保留,不入投放与 F2) continue # ---- 活行校验 ---- if kinds.is_empty(): errs.append({"category": "domain", "message": "%s effect_kinds 空(活行;失义件应标 deferred)" % iid}) var kind_seen := {} for k in kinds: var kind: String = String(k) if not EFFECT_KINDS.has(kind): errs.append({"category": "enum", "message": "%s effect_kind 出域 %s: %s" % [iid, str(EFFECT_KINDS), kind]}) if kind_seen.has(kind): errs.append({"category": "dup_key", "message": "%s effect_kind 重复: %s" % [iid, kind]}) kind_seen[kind] = true # 承重护栏①真视窄域:mine_reveal 活行 target 必须 area_3x3(一次最多 3×3,禁全图看雷) if kind_seen.has("mine_reveal") and target != "area_3x3": errs.append({"category": "load_bearing", "message": "%s 真视窄域护栏:mine_reveal 行 target 必须 area_3x3,实得 %s(秘宝 GDD 结构冻结)" % [iid, target]}) # 承重护栏②board_wide 仅恢复推理类:全图域行禁替推理效果 if target == "board_wide" and kind_seen.has("mine_reveal"): errs.append({"category": "load_bearing", "message": "%s board_wide 行 effect_kinds 不得含 mine_reveal(全图域仅恢复推理原料类——Alpha 重定后落位)" % iid}) # magnitude:MAGNITUDE_KINDS 行消费(≥1);其余活行恒 0(同调批 T1——消费面自 ap_grant 扩至 N 值 kind) var mag: int = int(row.get("magnitude", 0)) if mag < 0 or mag > 999: errs.append({"category": "domain", "message": "%s magnitude 越域 [0,999]: %d" % [iid, mag]}) var mag_consuming := false for k in kind_seen.keys(): if MAGNITUDE_KINDS.has(String(k)): mag_consuming = true if mag_consuming and mag < 1: errs.append({"category": "cross_field", "message": "%s N 值 kind 行 magnitude 应 ≥1,实得 %d" % [iid, mag]}) if not mag_consuming and mag != 0: errs.append({"category": "cross_field", "message": "%s 非 N 值 kind 活行 magnitude 应 0,实得 %d" % [iid, mag]}) # ---- 同调行约束(form 非空——装配面;过渡行 form="" 不校验)---- if form != "": if int(row.get("slot_cost", 1)) != 1: errs.append({"category": "load_bearing", "message": "%s 同调占位统一 1 槽(slot_cost 恒 1——底稿裁决 5,schema 强制)" % iid}) var charges: int = int(row.get("charges_per_adventure", 0)) if form == "passive" and charges != 0: errs.append({"category": "cross_field", "message": "%s passive 行 charges_per_adventure 应 0,实得 %d" % [iid, charges]}) if form == "active_charged" and charges < 1: errs.append({"category": "cross_field", "message": "%s active_charged 行 charges_per_adventure 应 ≥1,实得 %d" % [iid, charges]}) var eff_rounds: int = int(row.get("effective_rounds", 0)) if eff_rounds < 0 or eff_rounds > 999: errs.append({"category": "domain", "message": "%s effective_rounds 越域 [0,999]: %d" % [iid, eff_rounds]}) if kind_seen.has("ap_rounds_front") and eff_rounds < 1: errs.append({"category": "cross_field", "message": "%s ap_rounds_front 行 effective_rounds 应 ≥1(P4 甲表值化),实得 %d" % [iid, eff_rounds]}) if not kind_seen.has("ap_rounds_front") and eff_rounds != 0: errs.append({"category": "cross_field", "message": "%s 非 ap_rounds_front 行 effective_rounds 应 0,实得 %d" % [iid, eff_rounds]}) var charge_n: int = int(row.get("charge_n", 0)) if charge_n < 0 or charge_n > 999: errs.append({"category": "domain", "message": "%s charge_n 越域 [0,999]: %d" % [iid, charge_n]}) if kind_seen.has("ap_charge_safe") and charge_n < 1: errs.append({"category": "cross_field", "message": "%s ap_charge_safe 行 charge_n 应 ≥1(每次充能需 N 安全格),实得 %d" % [iid, charge_n]}) if not kind_seen.has("ap_charge_safe") and charge_n != 0: errs.append({"category": "cross_field", "message": "%s 非 ap_charge_safe 行 charge_n 应 0,实得 %d" % [iid, charge_n]}) # unlock_requires 谓词行:空 = 已解锁(首批全解锁合法态,底稿 §2.2);非空键 ∈ 计数键封闭枚举 var ureqs: Array = row.get("unlock_requires", []) var ukeys := {} for req in ureqs: var ukey: String = String(req.get("key", "")) if not AttunementGrowthTable.COUNTER_KEYS.has(ukey): errs.append({"category": "enum", "message": "%s unlock_requires 计数键出域 %s: %s" % [iid, str(AttunementGrowthTable.COUNTER_KEYS), ukey]}) if ukeys.has(ukey): errs.append({"category": "dup_key", "message": "%s unlock_requires 计数键重复: %s" % [iid, ukey]}) ukeys[ukey] = true var uth: int = int(req.get("threshold", 0)) if uth < 1 or uth > 999: errs.append({"category": "domain", "message": "%s unlock_requires 阈值越域 [1,999]: %d" % [iid, uth]}) return errs # 同调行词表(form 非空)——装配覆盖层/效果接线/同调位上限的唯一取数口径(迭代 11 第①批 T1) func attunement_rows() -> Array: var out: Array = [] for row in rows: if String(row.get("form", "")) != "" and not bool(row.get("retired", false)) and not bool(row.get("deferred", false)): out.append(row) return out # 过渡行词表(form 空 = 切片期过渡形态活行)——掉落投放/停点池/过渡覆盖面的取数口径; # 同调行永不入过渡渠道。T7 退役面切换后本口径随渠道消亡。 func transitional_rows() -> Array: var out: Array = [] for row in rows: if String(row.get("form", "")) == "" and not bool(row.get("retired", false)) and not bool(row.get("deferred", false)): out.append(row) return out # 活行词表(非 retired 非 deferred)——投放校验/奖励节点池/F2 覆盖面的唯一取数口径 func active_rows() -> Array: var out: Array = [] for row in rows: if not bool(row.get("retired", false)) and not bool(row.get("deferred", false)): out.append(row) return out func row_by_id(item_id: String) -> Dictionary: for row in rows: if String(row.get("item_id", "")) == item_id: return row return {}