From 9e26df16be3a1ff740e75c2f53fb49e8e0df9f01 Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Fri, 6 Nov 2026 07:23:25 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B7=A5=E7=A8=8B(=E5=88=A4=E6=8D=AE=E5=87=BA?= =?UTF-8?q?=E5=A4=84=E6=B3=A8=E8=AE=B03/7=C2=B7battle+contracts+integratio?= =?UTF-8?q?n):=2020=E5=A5=97=E4=BB=B680=E5=87=BD=E6=95=B0=E9=80=90?= =?UTF-8?q?=E5=87=BD=E6=95=B0=E6=8C=82#=20oracle=E6=B3=A8=E8=AE=B0?= =?UTF-8?q?=E2=80=94=E2=80=94=E6=88=98=E6=96=97=E5=9B=9B=E6=96=87=E6=A1=A3?= =?UTF-8?q?=E9=AA=8C=E6=94=B6=E5=8F=A5(=E6=88=98=E6=96=97=E7=BB=93?= =?UTF-8?q?=E7=AE=97:360-366/=E6=95=8C=E4=BA=BA=E7=B3=BB=E7=BB=9F:295-311/?= =?UTF-8?q?=E5=A2=9E=E7=9B=8A=E7=8A=B6=E6=80=81:250-262/=E5=9C=B0=E5=9B=BE?= =?UTF-8?q?=E6=88=98=E6=96=97=E8=B5=84=E6=BA=90:235-241)+=E6=8E=92?= =?UTF-8?q?=E9=9B=B7=E7=8E=A9=E6=B3=95:231/237+=E8=A1=8C=E5=8A=A8=E7=BB=8F?= =?UTF-8?q?=E6=B5=8E+=E5=9C=B0=E5=BD=A2=E5=8F=98=E5=BC=82:156-158+?= =?UTF-8?q?=E5=A5=87=E7=89=A9+=E5=AD=98=E6=A1=A3=E5=BA=8F=E5=88=97?= =?UTF-8?q?=E5=8C=96=E6=96=AD=E7=82=B9=E5=9F=9F/=E8=BF=81=E7=A7=BB?= =?UTF-8?q?=E9=93=BE+=E5=85=B3=E5=8D=A1=E8=8A=82=E7=82=B9=E5=9B=BE?= =?UTF-8?q?=E7=94=9F=E6=88=90:132+architecture:89/90/107/144+code-conventi?= =?UTF-8?q?ons:40/41/54;=20=E6=9C=AC=E6=AD=A5=E5=87=AD=E6=8D=AE:=20?= =?UTF-8?q?=E5=85=AD=E7=9B=AE=E5=BD=95=E4=BB=A3=E8=A1=A8=E5=A5=97=E4=BB=B6?= =?UTF-8?q?=E7=9B=B4=E8=B7=91=E5=85=A8=E7=BB=BF(seal/contracts=C3=972/inte?= =?UTF-8?q?gration=C3=973),=E5=85=B6=E4=BD=99=E9=9A=8FWP4=E5=85=A8?= =?UTF-8?q?=E9=87=8F=E6=A1=A3=E5=85=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../integration/cross_system_flow_test.gd | 4 ++++ .../integration/node_map_determinism_test.gd | 1 + .../integration/save_rng_roundtrip_test.gd | 2 ++ .../unit/battle_settlement/boss_gate_test.gd | 2 ++ .../damage_controller_test.gd | 6 +++++ .../battle_settlement/damage_math_test.gd | 5 ++++ .../battle_settlement/effect_port_test.gd | 4 ++++ .../extended_row_violation_test.gd | 1 + .../battle_settlement/refresh_feats_test.gd | 13 ++++++++++ .../battle_settlement/roll_multiplier_test.gd | 4 ++++ .../round_flow_skill_pool_test.gd | 5 ++++ .../battle_settlement/seal_polarity_test.gd | 16 +++++++++++++ .../settlement_wiring_snapshot_test.gd | 1 + .../battle_settlement/skill_unlock_test.gd | 4 ++++ .../battle_settlement/trigger_cond_test.gd | 1 + .../variant_placement_test.gd | 4 ++++ .../tests/unit/contracts/source_guard_test.gd | 2 ++ .../unit/contracts/system_contracts_test.gd | 24 +++++++++++++++++++ 18 files changed, 99 insertions(+) diff --git a/game/tests/integration/cross_system_flow_test.gd b/game/tests/integration/cross_system_flow_test.gd index 165ae097..22c1b78d 100644 --- a/game/tests/integration/cross_system_flow_test.gd +++ b/game/tests/integration/cross_system_flow_test.gd @@ -46,6 +46,7 @@ func _fresh_rng(seed_val: int): # ---- ① RNG 事件日志会话落盘(源 `_initialize` :70,主会话裁决一改判集成—— # 驱动沿源 :60–70 取号序列自持:master 种子 42 → 前置取号 → new_adventure 开日志会话 → 会话内取号)---- func _rng_event_log_session() -> void: +# oracle: design/engineering/architecture/architecture.md:90(事件日志落盘会话组) var rng = load("res://core/rng_service.gd").new() rng.set_master_seed(42) rng.open_stream("board_gen") @@ -60,6 +61,7 @@ func _rng_event_log_session() -> void: # _on_level_finished(victory)+breakpoint_snapshot 取读+clear_breakpoint; # 起局与兑付两步的受理断言留单元宿主(adventure_feats_test),此处纯驱动——前置失败自然落红)---- func _feats_breakpoint_roundtrip() -> void: +# oracle: design/gdd/systems/表现与支撑/存档序列化.md:180(专长断点附随件往返组) var rt := FeatTable.new() rt.rows = [ {"feat_id": "x1", "display_name": "试一", "rarity": "common", "desc": "测试揭示", "cap": 1, @@ -105,6 +107,7 @@ func _feats_breakpoint_roundtrip() -> void: # level_autoplay 真局摘要 → apply 原语 → 域读数 → 写盘读回保持;临时档 user://smoke_save_integration.json # 段首清场+段尾清理(源 _smoke_save 隔离纪律),绝不碰 user://save.json(红线))---- func _save_summary_integration() -> void: +# oracle: design/gdd/systems/跨局循环/元进度.md:150(摘要集成与钥石只增不减组) var sm_script = load("res://core/save_manager.gd") var path9 := "user://smoke_save_integration.json" # 源 paths[8] if FileAccess.file_exists(path9): @@ -137,6 +140,7 @@ func _save_summary_integration() -> void: # ---- ④ 试玩记录仪(源 `_smoke_playtest_logger` 整套八条,主会话裁决七改判集成—— # PlaytestLogger 挂真实结算流:会话文件/逐结算快照/字段齐备/spawn_count 回归/诊断转储/JSONL 回读)---- func _smoke_playtest_logger() -> void: +# oracle: design/engineering/code-conventions.md:40(试玩日志器跨系统接线组) print("--- PlaytestLogger(结算快照 JSONL + 诊断转储)---") var rng = load("res://core/rng_service.gd").new() rng.set_master_seed(20260912) diff --git a/game/tests/integration/node_map_determinism_test.gd b/game/tests/integration/node_map_determinism_test.gd index 773fce03..0ddcd4cb 100644 --- a/game/tests/integration/node_map_determinism_test.gd +++ b/game/tests/integration/node_map_determinism_test.gd @@ -33,6 +33,7 @@ func _init() -> void: # ---- 关卡节点图生成·确定性承载断言面 ---- func _smoke_generated_map_determinism() -> void: +# oracle: design/gdd/systems/冒险循环/关卡节点图生成.md:134(起关/选路/断点重生成同图组) # ① 纯函数复现:图 = f(参数档, 种子)——同档同种子两次产图逐位同图,换种子必变图 var gen = NodeMapGenerator.new(_fresh_rng(910001)) var params2: Dictionary = _db.run.level_gen_params.row_by_level_index(2) diff --git a/game/tests/integration/save_rng_roundtrip_test.gd b/game/tests/integration/save_rng_roundtrip_test.gd index 263b7842..ade5b288 100644 --- a/game/tests/integration/save_rng_roundtrip_test.gd +++ b/game/tests/integration/save_rng_roundtrip_test.gd @@ -35,6 +35,7 @@ func _init() -> void: # ---- 用例一:盘上往返保真——写档再读回,断点逐键零漂移 ---- func _test_disk_roundtrip_preserves_breakpoint() -> void: +# oracle: design/gdd/systems/表现与支撑/存档序列化.md:180(存档⇄RNG 快照往返——断点域逐位组) var rng := RngServiceScript.new() var sm := SaveManagerScript.new(SAVE_PATH) var adr := AdventureRunnerScript.new(_db, rng) @@ -65,6 +66,7 @@ func _test_disk_roundtrip_preserves_breakpoint() -> void: # ---- 用例二:旧版本档经迁移链后仍可续玩(单测不覆盖的跨系统集成面)---- func _test_old_version_save_migrates_and_resumes() -> void: +# oracle: design/gdd/systems/表现与支撑/存档序列化.md:179(旧档迁移链读回续玩组) var rng := RngServiceScript.new() var sm := SaveManagerScript.new(SAVE_PATH) var adr := AdventureRunnerScript.new(_db, rng) diff --git a/game/tests/unit/battle_settlement/boss_gate_test.gd b/game/tests/unit/battle_settlement/boss_gate_test.gd index bf32d8c4..6691a46d 100644 --- a/game/tests/unit/battle_settlement/boss_gate_test.gd +++ b/game/tests/unit/battle_settlement/boss_gate_test.gd @@ -8,11 +8,13 @@ const Kit := preload("res://tests/unit/test_kit.gd") func _init() -> void: +# oracle: design/gdd/systems/战斗循环/敌人系统.md:293 Boss 节点开战行集宿主(装载组) _test_boss_node_spawns_boss_rowset() quit(Kit.finish("boss_gate_test")) func _test_boss_node_spawns_boss_rowset() -> void: +# oracle: design/gdd/systems/战斗循环/敌人系统.md:295 开战生成按遭遇坐标取行集(Boss 行集组) var db = load("res://core/config_db.gd").new() var load_ok: bool = db.load_tables("res://data/tables", true) and db.diagnostics_count("error") == 0 Kit.check("前置:表加载零 error", load_ok) diff --git a/game/tests/unit/battle_settlement/damage_controller_test.gd b/game/tests/unit/battle_settlement/damage_controller_test.gd index d2cebb7e..250a3cda 100644 --- a/game/tests/unit/battle_settlement/damage_controller_test.gd +++ b/game/tests/unit/battle_settlement/damage_controller_test.gd @@ -23,6 +23,7 @@ var _rows: Array = [] # 当前 run 的行协议收集(_on_row 绑定法— func _init() -> void: +# oracle: design/gdd/systems/战斗循环/战斗结算.md:360 伤害单据编排宿主(装载组) 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) @@ -70,6 +71,7 @@ func _row_by_display_prefix(prefix: String) -> Dictionary: # ---- 五配方一次全流程 + 双跑逐位复现 ---- func _run_recipe_sequence(db) -> Array: +# oracle: design/gdd/systems/战斗循环/战斗结算.md:362(五段全序——配方序列组) _rows = [] var h = _harness(db) var units = h.units @@ -176,6 +178,7 @@ func _run_recipe_sequence(db) -> Array: func _test_five_recipes_and_replay(db) -> void: +# oracle: design/gdd/systems/战斗循环/战斗结算.md:363(同种子回放逐行相同组) var run1: Array = _run_recipe_sequence(db) Kit.check("五配方序列产出 5 行伤害行", run1.size() == 5) var run2: Array = _run_recipe_sequence(db) @@ -185,6 +188,7 @@ func _test_five_recipes_and_replay(db) -> void: # ---- A 模式(开单即结——回切位) ---- func _test_policy_immediate_mode(db) -> void: +# oracle: design/gdd/systems/战斗循环/战斗结算.md:362(结算策略即时面组) _rows = [] var h = _harness(db) if not h.spawn_ok: @@ -200,6 +204,7 @@ func _test_policy_immediate_mode(db) -> void: # ---- 来源敌死亡:队列中未结单据作废(死亡即不动手) ---- func _test_source_death_void(db) -> void: +# oracle: design/gdd/systems/战斗循环/敌人系统.md:133(摇定后兑现前被杀本拍作废组) _rows = [] var h = _harness(db) if not h.spawn_ok: @@ -233,6 +238,7 @@ func _unit_fixture() -> Dictionary: func _test_identical_content_dual_enemy(db: ConfigDb) -> void: +# oracle: design/gdd/systems/战斗循环/敌人系统.md:303(双敌同内容顺位组) var a := _unit_fixture() var b := _unit_fixture() Kit.check("前置:双敌字典内容全同且非同一实例", a == b and not is_same(a, b)) diff --git a/game/tests/unit/battle_settlement/damage_math_test.gd b/game/tests/unit/battle_settlement/damage_math_test.gd index db07970d..e5d9114f 100644 --- a/game/tests/unit/battle_settlement/damage_math_test.gd +++ b/game/tests/unit/battle_settlement/damage_math_test.gd @@ -12,6 +12,7 @@ var db func _init() -> void: +# oracle: design/gdd/systems/战斗循环/战斗结算.md:360(伤害公式宿主——装载组) db = ConfigDBScript.new() var load_ok: bool = db.load_tables("res://data/tables", true) Kit.check("前置:settlement 表加载零 error", load_ok and db.diagnostics_count("error") == 0) @@ -30,6 +31,7 @@ func _floor_val() -> int: # ---- F2 乘区:池内加算 → 池间乘算 → floor(单一取整规则)---- func _test_pool_damage() -> void: +# oracle: design/gdd/systems/战斗循环/战斗结算.md:360(池伤害公式组) var d := _floor_val() + 9 # 表值推导的任意正探针量(非玩法行值) Kit.check("中性双池 (0,0) 原样透传", DamageMathScript.pool_damage(d, 0, 0) == d) Kit.check("负敌方池压低不增高", DamageMathScript.pool_damage(d, 0, int(db.combat.settlement.core.pool_clamp_lo)) <= d) @@ -42,6 +44,7 @@ func _test_pool_damage() -> void: # ---- 克制分量:空桶不吃修正恒 0;落地下限保底([1,+∞) 全来源)---- func _test_counter_component() -> void: +# oracle: design/gdd/systems/战斗循环/战斗结算.md:360(计数器分量组) var floor_v := _floor_val() Kit.check("空桶(点数≤0)恒 0 不吃修正", DamageMathScript.counter_component(0, floor_v, floor_v) == 0 and DamageMathScript.counter_component(-1, 5, floor_v) == 0) @@ -53,6 +56,7 @@ func _test_counter_component() -> void: # ---- 掷点折扣查档(纯函数):满阈值恒全额;档位边界/末档语义与表数组一致 ---- func _test_roll_discount_percent() -> void: +# oracle: design/gdd/systems/战斗循环/战斗结算.md:360(乘区折扣组) var threshold := 10 # 查档探针阈值(夹具值——档位参数本身全部来自表) var bounds: Array = db.combat.settlement.damage_roll.roll_tier_bounds var discounts: Array = db.combat.settlement.damage_roll.roll_tier_discounts @@ -77,6 +81,7 @@ func _test_roll_discount_percent() -> void: # ---- 吃掷点分量算术:折扣→(暴击)→floor→+克制修正(单一取整链)---- func _test_rolled_component() -> void: +# oracle: design/gdd/systems/战斗循环/战斗结算.md:360(掷点分量组) var base := float(_floor_val() + 7) # 表值推导探针基线 var crit_mult: int = int(db.combat.settlement.damage_roll.crit_multiplier) Kit.check("满额折扣无暴击 = floor(基线) + 修正 0", DamageMathScript.rolled_component(base, 100, false, crit_mult, 0) == int(floor(base))) diff --git a/game/tests/unit/battle_settlement/effect_port_test.gd b/game/tests/unit/battle_settlement/effect_port_test.gd index 4790e064..a8948a1e 100644 --- a/game/tests/unit/battle_settlement/effect_port_test.gd +++ b/game/tests/unit/battle_settlement/effect_port_test.gd @@ -19,6 +19,7 @@ var _db func _init() -> void: +# oracle: design/engineering/architecture/architecture.md:144(效果端口宿主——装载组) _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) @@ -53,6 +54,7 @@ func _hero_attack_value(rows: Array) -> int: # ---- V1 端口单实例与真实发射路由 ---- func _smoke_effect_port_wiring() -> void: +# oracle: design/engineering/architecture/architecture.md:144(端口单实例与六 Callable 路由组) print("--- 效果端口:装配链单实例+真实发射路由 ---") # 充能跑(蓄力周转 charge_rotation 在册——attack_commit 订阅行 attack_bonus per 蓄力周转计数器) var orch_c = _orch(TEST_SEED) @@ -86,6 +88,7 @@ func _smoke_effect_port_wiring() -> void: # ---- V2 业务类零引擎直连(源码契约锚——theme_projection_test 源码锚惯例)---- func _test_business_classes_engine_free() -> void: +# oracle: design/engineering/architecture/architecture.md:144(业务类零引擎直连组) print("--- 效果端口:业务类零引擎直连源码锚 ---") for path in ["res://core/damage_controller.gd", "res://core/action_economy.gd"]: var src := FileAccess.get_file_as_string(path) @@ -97,6 +100,7 @@ func _test_business_classes_engine_free() -> void: # ---- V3 伤害域事实面闭集(合成行两对照——damage_taken 真实单据流)---- func _test_biz_fact_face_closed() -> void: +# oracle: design/engineering/architecture/architecture.md:144(闭面四键 biz_fact 组) print("--- 效果端口:业务发射事实面闭集 ---") var orch = _orch(TEST_SEED) Kit.check("V3 begin_battle 受理", orch.begin_battle(_enc([]))) diff --git a/game/tests/unit/battle_settlement/extended_row_violation_test.gd b/game/tests/unit/battle_settlement/extended_row_violation_test.gd index 0198c410..827eed8b 100644 --- a/game/tests/unit/battle_settlement/extended_row_violation_test.gd +++ b/game/tests/unit/battle_settlement/extended_row_violation_test.gd @@ -11,6 +11,7 @@ const Kit := preload("res://tests/unit/test_kit.gd") func _init() -> void: +# oracle: design/gdd/systems/表现与支撑/数据配置.md:199(扩展行必载 effect_id——加载致命组) var db = load("res://core/config_db.gd").new() if not db.load_tables("res://data/tables", false): push_error("[extended_row_violation_test] 表加载失败") diff --git a/game/tests/unit/battle_settlement/refresh_feats_test.gd b/game/tests/unit/battle_settlement/refresh_feats_test.gd index 7b7932c9..958427cb 100644 --- a/game/tests/unit/battle_settlement/refresh_feats_test.gd +++ b/game/tests/unit/battle_settlement/refresh_feats_test.gd @@ -154,6 +154,7 @@ func _seal_direct_with_expansion(orch) -> Vector2i: # 四条真实路径(敌方攻击/危险格/错误封印/地形)逐路驱动:每条至少一张主角承伤单据在案, # 且承伤计数器 == 主角承伤单据行数(每单据恰发射一次的全量判据——重复发射即计数器>行数)。 func test_all_hero_damage_paths_emit_once() -> void: +# oracle: design/gdd/systems/冒险循环/奇物.md:465(换图生存:全局固定减伤全伤害路径恰一次组) print("--- V5 全局 damage_taken:四路径逐路恰一次 ---") # ① 敌方攻击路径(Boss 战零挖掘连停三轮——干净样本:零地形零资源单据;多轮保证伤害技在案) var orch1 = _orch(46001) @@ -223,6 +224,7 @@ func _plan_seal(orch, target: Vector2i) -> Dictionary: # 同一伤害不得出现两次消费(重复发射=计数器>行数):敌方路径与地形路径两样本逐位核对—— # 地形单据带 hero_damage_consumed 标记,战斗段末 _resolve_board_flat_hero 跳过二次发射由此钉住。 func test_no_duplicate_damage_taken_event() -> void: +# oracle: design/gdd/systems/冒险循环/奇物.md:465(受击事件零重复组) print("--- V5 全局 damage_taken:无重复消费 ---") var orch1 = _orch(46011) var rows1 := _collect_hero_rows(orch1) @@ -264,6 +266,7 @@ func _auto_dig(orch) -> void: # V2 矿脉储能:受理的付费挖格 RAP 恰 +1、AP 按表扣、板资源不变 func test_reserve_on_accepted_dig() -> void: +# oracle: design/gdd/systems/排雷循环/行动经济.md:256(换图基座:挖格产 RAP 组) print("--- V2 矿脉储能:付费挖格产 RAP ---") var orch = _orch(46021) Kit.check("V2 前置:战斗受理", orch.begin_battle(_enc(["vein_reserve"]))) @@ -301,6 +304,7 @@ func _drain_round_rap_accounting(orch) -> bool: # V3 省力周转:折价门槛与扣费(can 与执行同源;base 8→扣 4) func test_refresh_discount_gate_and_charge() -> void: +# oracle: design/gdd/systems/排雷循环/行动经济.md:256(刷新折扣门控与充能组) print("--- V3 省力周转:折价门槛与扣费 ---") var orch = _orch(46022) Kit.check("V3 前置:战斗受理", orch.begin_battle(_enc(["easy_swap"]))) @@ -322,6 +326,7 @@ func test_refresh_discount_gate_and_charge() -> void: # V3 双基座叠加:挖格产 RAP 与刷新折价同场生效 func test_double_base_stack() -> void: +# oracle: design/gdd/systems/冒险循环/奇物.md:465(双基座叠加组) print("--- V3 双基座叠加 ---") var orch = _orch(46023) Kit.check("V3 前置:战斗受理", orch.begin_battle(_enc(["vein_reserve", "easy_swap"]))) @@ -338,6 +343,7 @@ func test_double_base_stack() -> void: # V12(refresh_feats 侧):无专长基线——挖格零产 RAP、刷新按表基线扣、AP 保留、上限照旧 func test_no_feats_baseline() -> void: +# oracle: design/gdd/systems/冒险循环/奇物.md:465(零专长基线组) print("--- V12 无专长基线(refresh_feats 侧) ---") var orch = _orch(46024) Kit.check("V12 前置:战斗受理", orch.begin_battle(_enc([]))) @@ -373,6 +379,7 @@ func _br_count(orch) -> int: # V4 成功事实只在新板就位后发射:成功恰一次;非 Active/每轮上限/RAP 不足三拒面全零事实零换图 func test_board_refresh_fact_only_on_success() -> void: +# oracle: design/gdd/systems/排雷循环/行动经济.md:256(弃图刷新事实面仅成功态组) print("--- V4 成功刷新事实:拒绝零事实 ---") _install_br_probe() var orch = _orch(46031) @@ -407,6 +414,7 @@ func test_board_refresh_fact_only_on_success() -> void: # V10 矿道红利:每次成功刷新 escrow 恰 +1 且 fx_grant_gp 行在案;拒绝零变化 func test_mine_profit_gp() -> void: +# oracle: design/gdd/systems/冒险循环/奇物.md:465(换图资源:刷新固定 GP 收益组) print("--- V10 矿道红利:刷新固定 GP ---") var orch = _orch(46032) var gp_rows := {"n": 0} @@ -453,6 +461,7 @@ func _damage_rows_by_source(rows: Array, source: String) -> Array: # V6 石层缓冲:全局固定减伤(危险格 pierce 8→6 两档钉死:单刷减 2·同轮多刷不叠加·未刷新轮不减; # 地形路径减后值=max(下限, effect_value−2)——含下限保持;敌方路径照常单次发射) func test_stone_mitigation_all_damage() -> void: +# oracle: design/gdd/systems/冒险循环/奇物.md:465(全局减伤全覆盖组) print("--- V6 石层缓冲:全局固定减伤 ---") # S1 同轮双刷 → 危险格 pierce 8 减 2=6(叠加即 4——多刷不增钉死) var orch1 = _orch(46041) @@ -508,6 +517,7 @@ func test_stone_mitigation_all_damage() -> void: # V9 坑道小憩:轮末合计回复(白盒预置承载上限 3——计数器直改属数据面注入; # 自然累计 2 与满血未生效两形态分战场钉死) func test_rest_rotation_cap_and_clear() -> void: +# oracle: design/gdd/systems/冒险循环/奇物.md:465(轮末恢复 cap 与清账组) print("--- V9 坑道小憩:轮末恢复 ---") # R1 白盒预置 3 层 + 刷新闸(when<3 拒第 4 层)→ 停手回复 min(3, 缺血)——护甲降档保缺血 ≥3 var orch1 = _orch(46051) @@ -565,6 +575,7 @@ func test_rest_rotation_cap_and_clear() -> void: # V8 蓄力周转:当轮攻击消费全部层数(上限 3 闸=白盒预置;战斗新建自然清空) func test_charge_layers_consumed_same_round() -> void: +# oracle: design/gdd/systems/冒险循环/奇物.md:465(充能当轮消耗组) print("--- V8 蓄力周转:攻击消费层 ---") var orch1 = _orch(46061) var rows1 := _collect_damage_rows(orch1) @@ -591,6 +602,7 @@ func test_charge_layers_consumed_same_round() -> void: # V7 崩壁冲击:延迟群伤单(刷新时点零伤害行——战斗段末按存活目标结账) func test_blast_defers_to_combat_segment() -> void: +# oracle: design/gdd/systems/战斗循环/战斗结算.md:362(刷新群伤让位战斗段组) print("--- V7 崩壁冲击:延迟群伤 ---") var orch = _orch(46071) var rows := _collect_damage_rows(orch) @@ -609,6 +621,7 @@ func test_blast_defers_to_combat_segment() -> void: # 七件 validate/在册/稀有度 cap 对表/跨表计数器引用闭合/desc 禁词 func test_seven_feats_validate_and_pool() -> void: +# oracle: design/gdd/systems/冒险循环/奇物.md:465(换图系七件校验与池组) print("--- V11 七件数据与池 ---") var seven := {"vein_reserve": "excellent", "easy_swap": "excellent", "wall_blast": "excellent", "charge_rotation": "excellent", "stone_mitigation": "common", "tunnel_rest": "common", "mine_profit": "rare"} diff --git a/game/tests/unit/battle_settlement/roll_multiplier_test.gd b/game/tests/unit/battle_settlement/roll_multiplier_test.gd index 723f8129..3096787f 100644 --- a/game/tests/unit/battle_settlement/roll_multiplier_test.gd +++ b/game/tests/unit/battle_settlement/roll_multiplier_test.gd @@ -19,6 +19,7 @@ var _db func _init() -> void: +# oracle: design/gdd/systems/战斗循环/战斗结算.md:360(掷点与乘区宿主——装载组) _db = ConfigDBScript.new() # 表加载失败不中止(承 G2/G3 同款:表损坏的红落在具体断言上—— # 诊断在此展开,后续断言按坏表实况逐条验红;collect_only=true 下成员照常赋值可评) @@ -43,6 +44,7 @@ func _init() -> void: # 受理后不变量(encounter 受理后只读)。攻击单 base_value 贯通由 _smoke_damage_types 的 # hero_atk_val=100 全链路行值承载(同夹具既有覆盖——派生读在攻击链上工作即行值随 override 走)---- func _smoke_hero_atk_derived() -> void: +# oracle: design/gdd/systems/战斗循环/战斗结算.md:360(英雄攻击派生组) var rng_a = load("res://core/rng_service.gd").new() rng_a.set_master_seed(4242) var s_a = load("res://core/battle_orchestrator.gd").new(_db, rng_a) @@ -65,6 +67,7 @@ func _smoke_hero_atk_derived() -> void: # → heavy 伤害 == light −1、ward == light +1(要求基线伤害 ≥ 2——地板 1 会吞 −1 位移)。 # 承伤位移红线(卡片 §8 L3):全局位移只允许 ±1 量级——非此量级 = 矩阵消费面有未盘点的第二落点(停机)。 func _smoke_enemy_attack_type() -> void: +# oracle: design/gdd/systems/战斗循环/敌人系统.md:295(敌攻击类型行集组) print("--- 敌方攻击类型轴(迭代 24 N3)---") # ① 表列:20 行全填 normal(N3 全填不做差异化——Q9) var at_ok := true @@ -123,6 +126,7 @@ func _smoke_enemy_attack_type() -> void: # ---- 护甲等级掷点·行为面(折扣档分布 / nat20 暴击 / 伤害下限 / 棋盘来源必中)---- func _smoke_armor_roll() -> void: +# oracle: design/gdd/systems/战斗循环/增益状态.md:254(护甲掷点与叠层合并组) print("--- 护甲等级掷点(查档纯函数 + 暴击 + 伤害下限 + AC12 分布 + 棋盘必中)---") # ① 查档纯函数:全掷点域逐位对照(AC10 / AC12)+ EV 锚(AC10 期望减免 21.25% —— registry 参考数) var expect_ac10 := {100: 11, 75: 3, 50: 4, 25: 2} # 掷 10-20 全额 / 7-9 / 3-6 / 1-2 diff --git a/game/tests/unit/battle_settlement/round_flow_skill_pool_test.gd b/game/tests/unit/battle_settlement/round_flow_skill_pool_test.gd index 9fd663be..3f2fe528 100644 --- a/game/tests/unit/battle_settlement/round_flow_skill_pool_test.gd +++ b/game/tests/unit/battle_settlement/round_flow_skill_pool_test.gd @@ -22,6 +22,7 @@ var _db func _init() -> void: +# oracle: design/gdd/systems/战斗循环/战斗结算.md:360(轮内流与技能池宿主——装载组) _db = ConfigDBScript.new() # 表加载失败不中止(承 G2/G3/G4/G5 同款:表损坏的红落在具体断言上—— # 诊断在此展开,后续断言按坏表实况逐条验红;collect_only=true 下成员照常赋值可评) @@ -47,6 +48,7 @@ func _init() -> void: # ---- 完整战斗回放(自动玩家,确定性)——回放断言:同种子两遍步骤流逐行相同 ---- func _smoke_full_battle(L: int, D: int, label: String) -> void: +# oracle: design/gdd/systems/战斗循环/战斗结算.md:362(全战斗回放——五段全序组) print("--- 完整战斗回放:%s ---" % label) var run1 = _run_battle(L, D) var run2 = _run_battle(L, D) @@ -81,6 +83,7 @@ func _smoke_full_battle(L: int, D: int, label: String) -> void: func _run_battle(L: int, D: int, axes: Dictionary = {}) -> Dictionary: +# oracle: design/gdd/systems/战斗循环/战斗结算.md:362(战斗驱动组) # 每遍全新 RngService(同 master 种子)——回放断言的隔离前提(地图战斗资源 AC"两套全新 RngService+地图战斗资源"同款) var rng = load("res://core/rng_service.gd").new() rng.set_master_seed(42) @@ -145,6 +148,7 @@ func _auto_play_round(settlement, out: Dictionary) -> void: # ---- 行动经济·轮内刷新冒烟(方案 A:Active 相位当场换图继续挖)---- func _smoke_active_refresh() -> void: +# oracle: design/gdd/systems/排雷循环/行动经济.md:262(停手转存储备与轮内刷新组) print("--- 行动经济·轮内刷新(方案 A)---") var rng = load("res://core/rng_service.gd").new() rng.set_master_seed(20260912) @@ -251,6 +255,7 @@ func _active_refresh_replay() -> Array: # ---- 遭遇随机化冒烟(难度曲线与Boss Core Rule 8:区间骰/encounter 流/可回放/空表定值路径)---- func _smoke_encounter_roll() -> void: +# oracle: design/gdd/systems/战斗循环/敌人系统.md:296(遭遇区间骰——摇号确定性组) print("--- 遭遇随机化(unit_count 区间骰)---") var counts: Array = [] for i in range(20): diff --git a/game/tests/unit/battle_settlement/seal_polarity_test.gd b/game/tests/unit/battle_settlement/seal_polarity_test.gd index 547f394a..70178b65 100644 --- a/game/tests/unit/battle_settlement/seal_polarity_test.gd +++ b/game/tests/unit/battle_settlement/seal_polarity_test.gd @@ -22,6 +22,7 @@ var _db func _init() -> void: +# oracle: design/gdd/systems/排雷循环/排雷玩法.md:231(封印与极性宿主——装载组) _db = ConfigDBScript.new() # 表加载失败不中止(承 G2/G3/G4 同款:表损坏的红落在具体断言上—— # 诊断在此展开,后续断言按坏表实况逐条验红;collect_only=true 下成员照常赋值可评) @@ -45,6 +46,7 @@ func _init() -> void: # ---- 末点 AP 封印轮末结算(playtest 缺陷②回归:末点 AP 花在封印必须终结轮次进入下一轮)---- func _smoke_seal_ap_exhausted() -> void: +# oracle: design/gdd/systems/排雷循环/行动经济.md:260(末点 AP 耗尽即收轮组) print("--- 排雷玩法·封印动作耗尽末点 AP 回归 ---") var rng = load("res://core/rng_service.gd").new() rng.set_master_seed(20260911) @@ -322,6 +324,8 @@ func _rows_at(rows: Array, source_class: String, cell) -> Array: func _smoke_clear_reward_chain() -> void: +# oracle: design/gdd/systems/战斗循环/地图战斗资源.md:235(清图奖励链——清图槽对象身份组) +# oracle: design/gdd/systems/战斗循环/地图战斗资源.md:235(清图奖励链——清图槽对象身份组) print("--- 清图奖励·双份兑付链(完美封印 / 零兑付 / 第二份被拒 / 高光记实)---") # ① 真实流完美封印:标中一面真雷封印 + 零误标 + 清全图 → grant_clear 身份(clear_blast)双份真实兑付 var rows: Array = [] @@ -350,6 +354,8 @@ func _smoke_clear_reward_chain() -> void: # 弱形式登记:正常战斗流下"授段时刻无存活敌"不可达——敌全灭当轮判定段即判胜并终止战斗,而清图批在判定段之前, # 恒有存活敌;故本组直调编排私有面构造状态,只断言"路径存在 + 行为符合契约"(构造手法见各行注释)。 func _smoke_clear_reward_zero_paths() -> void: +# oracle: design/gdd/systems/战斗循环/地图战斗资源.md:240(无存活敌群伤记「奖励未生效」组) +# oracle: design/gdd/systems/战斗循环/地图战斗资源.md:240(无存活敌群伤记「奖励未生效」组) # ②-a 首份零兑付判定(无存活敌)→ first_ok=false + 未生效行 var rng = load("res://core/rng_service.gd").new() rng.set_master_seed(20260915) @@ -404,6 +410,8 @@ func _smoke_clear_reward_zero_paths() -> void: # 轮内刷新 provenance 守卫:刷新换来的图同轮清图不发清图奖励(_board_from_midround_refresh 守卫) func _smoke_refresh_provenance_guard() -> void: +# oracle: design/gdd/systems/排雷循环/排雷玩法.md:237(换图重置:旧封印印记先判定后消失组) +# oracle: design/gdd/systems/排雷循环/排雷玩法.md:237(换图重置:旧封印印记先判定后消失组) print("--- 轮内刷新 provenance 守卫(刷新图清图不发清图奖励)---") var rows: Array = [] var run := _run_full_clear(20260916, true, rows) @@ -430,6 +438,8 @@ func _smoke_refresh_provenance_guard() -> void: func _smoke_polarity_routing() -> void: +# oracle: design/gdd/systems/战斗循环/战斗结算.md:366(极性路由:正向只兑正向、负向只兑负向组) +# oracle: design/gdd/systems/战斗循环/战斗结算.md:366(极性路由:正向只兑正向、负向只兑负向组) print("--- 极性路由(挖安全格正向 / 挖危险格负向 / 标中正向 / 标空负向)---") # 战斗随机值面随全局序漂移——构造种子按行为面扫描(谓词见 _polarity_probe_accepts) var probe := {} @@ -567,6 +577,8 @@ func _smoke_polarity_routing() -> void: # 场景 B(②):标危险格 → 直接挖开 → 收轮。 # 场景 C(①③):标安全格 + 标危险格 → 不挖收轮 → 标空/标中判定照常。 func _smoke_seal_irreversible_quadrants() -> void: +# oracle: design/gdd/systems/排雷循环/排雷玩法.md:231(封印不可逆四情况组) +# oracle: design/gdd/systems/排雷循环/排雷玩法.md:231(封印不可逆四情况组) print("--- 封印不可逆四情况(禁撤封印 + 挖封印格兑付改判)---") # 场景 A:安全格直挖(情况④)+ seal_pull/重复封印拒绝面 var rng_a = load("res://core/rng_service.gd").new() @@ -675,6 +687,8 @@ func _smoke_seal_irreversible_quadrants() -> void: # 负向字典逐型直验(类型化兑付行协议):找真实板上各型非封锁格,直调 grant_routed 负向路由(att 归因束形态), # 断言每型的兑付形态(enrage/off_guard/sapped 效果行、heal 直伤行、blast 警觉行、action 行动点排队)。 func _smoke_negative_dictionary() -> void: +# oracle: design/gdd/systems/排雷循环/行动经济.md:256(下轮行动点修正排队与兑现组) +# oracle: design/gdd/systems/排雷循环/行动经济.md:256(下轮行动点修正排队与兑现组) print("--- 负向字典逐型直验(sapped 在位 / heal 直伤 / blast 警觉 / action 行动点)---") # 数据面:sapped 行在位(状态表七行 + effect_pool_map 映射在位) var sapped: Dictionary = _db.combat.status_effects.row_by_id("sapped") @@ -768,6 +782,8 @@ func _smoke_negative_dictionary() -> void: # 资源面断言:chain/dig 事件恒携带 resource=true(危险格同权);initial 恒 false(封锁格); # 封锁格查询 = null、危险格未开恒可查。 func _smoke_resource_surface() -> void: +# oracle: design/gdd/systems/战斗循环/地图战斗资源.md:235(资源面只读查询组) +# oracle: design/gdd/systems/战斗循环/地图战斗资源.md:235(资源面只读查询组) print("--- 格面资源资格面(危险格携带 / 封锁格无资源)---") var run1 = _run_battle(1, 0) var run2 = _run_battle(2, 0) diff --git a/game/tests/unit/battle_settlement/settlement_wiring_snapshot_test.gd b/game/tests/unit/battle_settlement/settlement_wiring_snapshot_test.gd index 3c5d16db..934c1aaf 100644 --- a/game/tests/unit/battle_settlement/settlement_wiring_snapshot_test.gd +++ b/game/tests/unit/battle_settlement/settlement_wiring_snapshot_test.gd @@ -419,6 +419,7 @@ var _db func _init() -> void: +# oracle: design/gdd/systems/战斗循环/战斗结算.md:362(结算接线同种子逐项 golden 对拍组) _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) diff --git a/game/tests/unit/battle_settlement/skill_unlock_test.gd b/game/tests/unit/battle_settlement/skill_unlock_test.gd index dabb76d4..53005034 100644 --- a/game/tests/unit/battle_settlement/skill_unlock_test.gd +++ b/game/tests/unit/battle_settlement/skill_unlock_test.gd @@ -13,6 +13,7 @@ const Kit := preload("res://tests/unit/test_kit.gd") func _init() -> void: +# oracle: design/gdd/systems/战斗循环/敌人系统.md:293 Boss 半血解锁技宿主(装载组) 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) @@ -43,6 +44,7 @@ func _has_sid(arr: Array, sid: String) -> bool: func _test_gate_predicate(db) -> void: +# oracle: design/gdd/systems/战斗循环/敌人系统.md:143(门谓词:条件不满足不进可摇集合组) var ec = _boss(db, 2, 9) var u: Dictionary = _boss_u(ec) var mhp: int = int(u.max_hp) @@ -71,6 +73,7 @@ func _test_gate_predicate(db) -> void: # 闩不可逆:解锁后治疗抬回满血 → 复查零新解锁、可摇集合不回退 func _test_latch_irreversible(db) -> void: +# oracle: design/gdd/systems/战斗循环/敌人系统.md:143(闩型条件首次为真整场保持组) var ec = _boss(db, 2, 9) var u: Dictionary = _boss_u(ec) ec.apply_damage(u, int(u.max_hp) / 2) # → 半血触发 @@ -82,6 +85,7 @@ func _test_latch_irreversible(db) -> void: # 普通行无字段逐位零扰动:地精 (1,0) 池快照零 unlock 键、过滤恒空转、可摇=全池 func _test_plain_rows_zero_drift(db) -> void: +# oracle: design/gdd/systems/战斗循环/敌人系统.md:301(普攻倍率 1 特例——零漂移组) var ec = load("res://core/unit_container.gd").new(db) Kit.check("零扰动前置:巨蜘蛛首遇带 spawn(池三行全无 trigger——快照键策略钉死载体)", ec.spawn({"level_index": 2, "node_depth": 1, "hero_hp": int(db.combat.hero.max_hp)})) var u: Dictionary = ec.all_enemies()[0] diff --git a/game/tests/unit/battle_settlement/trigger_cond_test.gd b/game/tests/unit/battle_settlement/trigger_cond_test.gd index fc6eb2c7..fd6347ae 100644 --- a/game/tests/unit/battle_settlement/trigger_cond_test.gd +++ b/game/tests/unit/battle_settlement/trigger_cond_test.gd @@ -9,6 +9,7 @@ const Kit := preload("res://tests/unit/test_kit.gd") func _init() -> void: +# oracle: design/gdd/systems/战斗循环/敌人系统.md:143(触发条件机制 V1–V10 组) var db = load("res://core/config_db.gd").new() if not db.load_tables("res://data/tables", false): print("[trigger_cond_test] FAIL — 数值表加载失败") diff --git a/game/tests/unit/battle_settlement/variant_placement_test.gd b/game/tests/unit/battle_settlement/variant_placement_test.gd index 620c3be3..b8963d6b 100644 --- a/game/tests/unit/battle_settlement/variant_placement_test.gd +++ b/game/tests/unit/battle_settlement/variant_placement_test.gd @@ -15,6 +15,7 @@ var _db func _init() -> void: +# oracle: design/gdd/systems/排雷循环/地形变异.md:151 变异布置宿主(装载组) _db = ConfigDBScript.new() # 表加载失败不中止(承 G2/G3/G4/G5 同款:表损坏的红落在具体断言上—— # 诊断在此展开,后续断言按坏表实况逐条验红;collect_only=true 下成员照常赋值可评) @@ -53,6 +54,7 @@ class _CountVariantRng extends RngServiceCore: # 本段经 begin_battle 走完整初始化序后断言:门控一致性 / 布置域 / 数量公式 / 连通片上限 / 确定性。 func _smoke_variant_placement(L: int) -> void: +# oracle: design/gdd/systems/排雷循环/地形变异.md:63(战内布置段门控组) print("--- 地形变异 布置段(L%d)---" % L) var rng = load("res://core/rng_service.gd").new() rng.set_master_seed(42) @@ -146,6 +148,7 @@ func _variant_dump(b) -> String: func _smoke_global_variant() -> void: +# oracle: design/gdd/systems/排雷循环/地形变异.md:74(全局替换制与回落组) print("--- 全局作用域变异(门控三维 + 全局池空兜底回落 + 资源面偏斜)---") # ① 跨字段互锁负样本(resource_face ⟺ scope=global 三条 + effect_value 新域 [0,50]) var vt = load("res://data/schemas/variation_table.gd").new() @@ -340,6 +343,7 @@ func _errs_has_cross_field(errs: Array) -> bool: # 全称不可断)。可达判据=①静态(布置面零字面量下界)+②同种子改值产物互异(真实入口=begin_battle 布置段)。 func _test_pack_min_from_table() -> void: +# oracle: design/gdd/systems/排雷循环/地形变异.md:63(连通片格数 [pack_min,pack_max] 读表组) # ① 静态:布置面零字面量下界(randi_range(2, 退役——下界读 pack_min 表头单点) var src := FileAccess.get_file_as_string("res://core/board_installer.gd") Kit.check("布置面零字面量下界(randi_range(2, 退役、下界读表单点在位)〔架构整改 V10·静态〕", diff --git a/game/tests/unit/contracts/source_guard_test.gd b/game/tests/unit/contracts/source_guard_test.gd index 0b8a60aa..86822e4f 100644 --- a/game/tests/unit/contracts/source_guard_test.gd +++ b/game/tests/unit/contracts/source_guard_test.gd @@ -21,6 +21,7 @@ func _init() -> void: # ---- 类型闸断言(V7——project.godot warning 配置在位〔源码断言〕+审计器脚本在位; # 审计器归零判定走 static_scan S9 闸机,此处兜配置面)---- func _smoke_type_gate() -> void: +# oracle: design/engineering/code-conventions.md:41(封装边界——类型闸源码扫描组) var pj: String = FileAccess.get_file_as_string("res://project.godot") Kit.check("V7 类型闸 warning 配置在位(untyped_declaration=1 显形)〔迭代27 T5〕", pj.contains("gdscript/warnings/untyped_declaration=1")) @@ -31,6 +32,7 @@ func _smoke_type_gate() -> void: # ---- 卫生件 grep 闸(V8——死代码/字符串 Callable/影子账残留零命中;源码扫描面)---- func _smoke_hygiene_gates() -> void: +# oracle: design/engineering/code-conventions.md:54(模态覆盖层层级与登记纪律——卫生闸组) var callables := 0 for d in ["res://core", "res://presentation", "res://data"]: var dir := DirAccess.open(d) diff --git a/game/tests/unit/contracts/system_contracts_test.gd b/game/tests/unit/contracts/system_contracts_test.gd index 350e1308..a5d3cc0b 100644 --- a/game/tests/unit/contracts/system_contracts_test.gd +++ b/game/tests/unit/contracts/system_contracts_test.gd @@ -40,6 +40,8 @@ func _init() -> void: # ---- B1 兑付配方词表:五配方/三目标规则/双结账政策——常量非空且互异(封闭枚举负空间) ---- func _test_damage_controller_vocabularies() -> void: +# oracle: design/engineering/architecture/architecture.md:89(事件/事实/效果类型/算子四词表封闭——契约词表组) +# oracle: design/engineering/architecture/architecture.md:89(事件/事实/效果类型/算子四词表封闭——契约词表组) var kinds: Array = [ DamageControllerScript.KIND_HERO_ATTACK, DamageControllerScript.KIND_ENEMY_SKILL, DamageControllerScript.KIND_BOARD_TYPED, DamageControllerScript.KIND_BOARD_BLAST, @@ -69,6 +71,8 @@ func _test_damage_controller_vocabularies() -> void: # ---- D2↔B1:掷点用途标签 ∈ RngService 封闭词表(EC12——跨系统字面量契约的成员性断言) ---- func _test_rng_tag_closure(db) -> void: +# oracle: design/engineering/architecture/architecture.md:90(流 scope 封闭词表组) +# oracle: design/engineering/architecture/architecture.md:90(流 scope 封闭词表组) var stream_label: String = String(db.combat.settlement.damage_roll.armor_roll_stream) Kit.check("settlement.armor_roll_stream ∈ RngService 封闭标签词表(EC12)", RngServiceScript.PURPOSE_TAGS.has(stream_label)) @@ -82,6 +86,8 @@ func _test_rng_tag_closure(db) -> void: # ---- B1→D1 行协议:单据九栏缺省齐备 + 协议公共键形态 ---- func _test_ticket_nine_columns() -> void: +# oracle: design/gdd/systems/战斗循环/战斗结算.md:362(单据九列协议组) +# oracle: design/gdd/systems/战斗循环/战斗结算.md:362(单据九列协议组) var ctrl = _bare_controller() var t: Dictionary = ctrl.open_ticket(DamageControllerScript.KIND_BOARD_FLAT_HERO, "mine_hit", "契约探针", {"channel": "棋盘兑付", "base_value": 1, "target_rule": DamageControllerScript.TARGET_HERO, "ri": 0}) @@ -111,6 +117,8 @@ func _bare_controller(): # ---- B4→B3:增益授予布尔受理口径(受理/拒绝二元面 + 投影一致性) ---- func _test_status_boolean_acceptance(db) -> void: +# oracle: design/gdd/systems/战斗循环/增益状态.md:250(受理布尔面组) +# oracle: design/gdd/systems/战斗循环/增益状态.md:250(受理布尔面组) var effects = StatusContainerScript.new(db) # EC1 域闭:notify_battle_start 前授予 = false(受理面封闭) var any_row: Dictionary = {} @@ -137,6 +145,8 @@ func _test_status_boolean_acceptance(db) -> void: # 个体键直传字面量("e1"/"e2"/"e3"——拼写约定单点在 StatusContainer.owner_key_for,测试面模拟授予路径逐只授) func _test_status_individual_isolation(db) -> void: +# oracle: design/gdd/systems/战斗循环/增益状态.md:251(按个体归属组) +# oracle: design/gdd/systems/战斗循环/增益状态.md:251(按个体归属组) var effects = StatusContainerScript.new(db) effects.notify_battle_start() var src := {"source_class": "seal_hit", "origin_cell": Vector2i(-1, -1), "round_index": 0} @@ -158,6 +168,8 @@ func _test_status_individual_isolation(db) -> void: func _test_status_grant_all_per_unit(db) -> void: +# oracle: design/gdd/systems/战斗循环/增益状态.md:252(授予即生效组) +# oracle: design/gdd/systems/战斗循环/增益状态.md:252(授予即生效组) var effects = StatusContainerScript.new(db) effects.notify_battle_start() var src := {"source_class": "mine_hit", "origin_cell": Vector2i(-1, -1), "round_index": 0} @@ -184,6 +196,8 @@ func _test_status_grant_all_per_unit(db) -> void: func _test_status_death_clears(db) -> void: +# oracle: design/gdd/systems/战斗循环/增益状态.md:250(战斗结束清空组) +# oracle: design/gdd/systems/战斗循环/增益状态.md:250(战斗结束清空组) var effects = StatusContainerScript.new(db) effects.notify_battle_start() var src := {"source_class": "seal_hit", "origin_cell": Vector2i(-1, -1), "round_index": 0} @@ -197,6 +211,8 @@ func _test_status_death_clears(db) -> void: func _test_status_merge_per_unit(db) -> void: +# oracle: design/gdd/systems/战斗循环/增益状态.md:253(只登记不去重组) +# oracle: design/gdd/systems/战斗循环/增益状态.md:253(只登记不去重组) var effects = StatusContainerScript.new(db) effects.notify_battle_start() var src := {"source_class": "enemy_action", "origin_cell": Vector2i(-1, -1), "round_index": 0} @@ -219,6 +235,8 @@ func _test_status_merge_per_unit(db) -> void: # ---- B4 结算链契约(断言补齐批——①增益状态结算链):衰减逐值/战斗结束全清/满层拒绝/独立并存/首授快照 ---- func _test_status_decay_and_clear(db) -> void: +# oracle: design/gdd/systems/战斗循环/增益状态.md:21(先兑付后衰减组) +# oracle: design/gdd/systems/战斗循环/增益状态.md:21(先兑付后衰减组) var effects = StatusContainerScript.new(db) effects.notify_battle_start() var src := {"source_class": "seal_hit", "origin_cell": Vector2i(-1, -1), "round_index": 0} @@ -239,6 +257,8 @@ func _test_status_decay_and_clear(db) -> void: func _test_status_stack_full_reject(db) -> void: +# oracle: design/gdd/systems/战斗循环/增益状态.md:255(满层拒绝原子且留痕组) +# oracle: design/gdd/systems/战斗循环/增益状态.md:255(满层拒绝原子且留痕组) var effects = StatusContainerScript.new(db) effects.notify_battle_start() var src := {"source_class": "seal_hit", "origin_cell": Vector2i(-1, -1), "round_index": 0} @@ -256,6 +276,8 @@ func _test_status_stack_full_reject(db) -> void: func _test_status_independent_branch(db) -> void: +# oracle: design/gdd/systems/战斗循环/增益状态.md:257(合成不设上下限组) +# oracle: design/gdd/systems/战斗循环/增益状态.md:257(合成不设上下限组) var effects = StatusContainerScript.new(db) effects.notify_battle_start() var probe := { @@ -280,6 +302,8 @@ func _test_status_independent_branch(db) -> void: func _test_status_snapshot_first_grant(db) -> void: +# oracle: design/gdd/systems/战斗循环/增益状态.md:258(快照抗重载组) +# oracle: design/gdd/systems/战斗循环/增益状态.md:258(快照抗重载组) var effects = StatusContainerScript.new(db) effects.notify_battle_start() var src_first := {"source_class": "seal_hit", "origin_cell": Vector2i(3, 4), "round_index": 1}