diff --git a/design/dev/architecture/architecture.md b/design/dev/architecture/architecture.md index 6a20e0cd..7af251b6 100644 --- a/design/dev/architecture/architecture.md +++ b/design/dev/architecture/architecture.md @@ -93,7 +93,7 @@ | **ConfigDB**(autoload,D2) | 全部玩法数值表(`data/tables/*.tres` + `data/schemas/*.gd`);SCHEMA_VERSION;加载/校验/override/诊断状态机 | 类型化属性读取;`load_tables(root, collect_only)`;`resolve()`(R1 floor);debug override;`set_reload_gate()`;诊断收集器 | 无(基础层顶点) | Resource/.tres 加载、autoload 生命周期——LOW | | **RngService**(autoload,D2) | master_seed、各流 scope 计数器(封闭流:board_gen / reward_roll;增流走 P1 评审) | `set_master_seed()`(唯一调用方 C2);`open_stream(stream)` 有状态门面;`derive_at(stream, scope)` 纯函数;只读计数器 | ConfigDB(无) | 无——纯逻辑 | | **action_economy**(A3) | AP/RAP 账本、last_round_end、轮次相位机 {Idle, Active, Waiting}、结束仲裁 | 8 API 全布尔面:notify_round_start / request_dig / request_flag_place / request_flag_pull / request_stop / request_refresh / notify_settlement_done / notify_combat_end;ap/rap/phase 只读 | ConfigDB(ActionEconomyTable);B1 回发 next_round_mode/battle_over | 无 | -| **variation 定义**(A4) | VariationTable schema(现行 7 行:六 region + skewed_veins 一 global——全局作用域变异首发批 2026-10-04)与 F1 候选池门控谓词 | `variant_pool(level_index, board_type, node_type="")`(门控三维:unlock+board_types+节点身份——global 行仅 boss/elite 入池,缺省跳过零扰动);`global_variant_row(level_index, board_type, node_type)`(全局型单行决议访问器) | ConfigDB(VariationTable) | 无 | +| **variation 定义**(A4) | VariationTable schema(现行 6 行:六 region——贫矿脉 global 行 2026-10-16 用户令屏蔽删行,global 型机制代码保留)与 F1 候选池门控谓词 | `variant_pool(level_index, board_type, node_type="")`(门控三维:unlock+board_types+节点身份——global 行仅 boss/elite 入池,缺省跳过零扰动);`global_variant_row(level_index, board_type, node_type)`(全局型单行决议访问器) | ConfigDB(VariationTable) | 无 | | **status_container**(B3) | 状态实例容器(战斗域生命周期、跨轮跨图延续) | 5 API:notify_battle_start / apply_effect / query_active / decay_round / notify_battle_end | ConfigDB(StatusEffectTable) | 无(RefCounted) | | **save_system**(D3,Alpha;iter27 已升格 autoload「SaveManager」) | 存档格式与版本比较 | (契约规范源:`../../gdd/systems/表现与支撑/存档序列化.md`——契约锚:SCHEMA_VERSION + master_seed + 各流 scope 计数器快照,须在无正在执行中的 open_stream 实例时切出) | ConfigDB、RngService 只读计数器 | FileAccess——LOW | | **settings/localization**(D6,愿景) | 设置项、翻译数据 | (契约规范源:`../../gdd/systems/表现与支撑/设置与本地化.md`) | ConfigDB | 无 | diff --git a/design/gdd/06-待办清单.md b/design/gdd/06-待办清单.md index f334b190..346915ce 100644 --- a/design/gdd/06-待办清单.md +++ b/design/gdd/06-待办清单.md @@ -395,7 +395,7 @@ **现状**:来源 = playnote 用户试玩记录「修改地图的奖励类型:战斗节点增加不同的地图类型,比如有些图踩雷受到更多的伤害,有些图标雷可以造成更多的伤害,有些图伤害会减半需要凑更多清图奖励(这些都是暂时的设定)」。 -**已实装的部分**:整图变异「贫矿脉」(回复与护甲资源减少、攻击资源增多)已落地,Boss 图每张都带,目检项见 [07-体验验证清单](07-体验验证清单.md) ⑪——它正是本条思路的首发形态。本条剩余面 = 在此之上再做**更多地图主题**(踩雷伤害更高 / 标雷伤害更高 / 伤害减半需凑更多清图奖励)。 +**已实装的部分**:首发形态整图变异「贫矿脉」(回复与护甲资源减少、攻击资源增多)**已于 2026-10-16 用户令屏蔽删行**(Boss 图回落 region 变异,原 07 ⑪ 目检项随之转记失效)——本条剩余面不变:在此之上再做**更多地图主题**(踩雷伤害更高 / 标雷伤害更高 / 伤害减半需凑更多清图奖励)。 **2026-10-13 用户裁定**:**排 Beta 版本,Alpha 不做**——已移入 [08-Alpha版本标准](08-Alpha版本标准.md)「六 · Alpha 不含」节。 diff --git a/design/gdd/07-体验验证清单.md b/design/gdd/07-体验验证清单.md index b08646b3..9a95d011 100644 --- a/design/gdd/07-体验验证清单.md +++ b/design/gdd/07-体验验证清单.md @@ -116,6 +116,8 @@ ### ⑪ Boss 图整图变异(贫矿脉)目检项(2026-10-04 全局作用域变异首发批顺带登记——**目检改排:随 UI 优化批之后统一验证**,用户 2026-10-04 裁「先做完 UI 优化再一起验证」) +> **✅ 转记(2026-10-16 用户令屏蔽——前提失效,无需验)**:贫矿脉行已从 `variation.tres` 删除(用户裁「地形变异特异关卡后续重新做设计,先屏蔽」;Boss/精英图全局池空→region 布置兜底,玩家面零横幅零角标零资源偏斜)。下列六项判据全部失效,不验;重建设计立项时随新需求卡重立目检项。改动面=shielddebug-20261016 批(variation.tres 删行+冒烟断言换代)。 + > **改排状态注记(2026-10-05 ui-struct-probe 批)**:UI 优化批(UI 落码 11 卡+SR-1)已全入库;期间实机目检抓到标题屏双列叠放缺陷,已随 ui-struct-probe 批修复,并新增全 UI 屏结构探针入轻闸(按钮互压/等宽/出屏/零尺寸——机械可判项自此探针代管,见 §⑯)。本条统一验证窗口仍开,等用户实机目检时点;下列六项均为体感/呈现面,保留人闸。 **怎么玩**:打一局正常打到第 2 关的 Boss 图(想快可以在开始界面开调试入口直接进第 2 关);顺手的话再看一眼第 1 关 Boss 和任意普通战斗图,前后共约十分钟。本条目在 UI 优化批落地后执行——届时以改完后的最终界面为准,下述文案若随 UI 批调整以当批登记为准。 diff --git a/design/gdd/systems/表现与支撑/数据配置.md b/design/gdd/systems/表现与支撑/数据配置.md index 6fd38597..d8159c3e 100644 --- a/design/gdd/systems/表现与支撑/数据配置.md +++ b/design/gdd/systems/表现与支撑/数据配置.md @@ -58,7 +58,7 @@ |---|---|---| | 行动经济表 `ActionEconomyTable` | 每轮行动点、动作价目、停手与刷新门槛 | [行动经济](../排雷循环/行动经济.md) | | 棋盘生成参数表 `BoardGenTable` | 板尺寸、雷密度、可推理率目标等(进度键表) | [棋盘生成](../排雷循环/棋盘生成.md) | -| 变异表 `VariationTable` | 变异类型清单(现行七行:region 六行两轴×三关〔2026-09-20 落地〕+ 首发 global 整图型贫矿脉〔2026-10-04 落地〕) | [地形变异](../排雷循环/地形变异.md) | +| 变异表 `VariationTable` | 变异类型清单(现行六行:region 六行两轴×三关〔2026-09-20 落地〕;首发 global 整图型贫矿脉 2026-10-16 用户令屏蔽删行,global 型机制代码保留) | [地形变异](../排雷循环/地形变异.md) | | 敌人表 `EnemyTable` | 敌种基线数值、遭遇数量区间、护甲类型、技能池模板(进度键表) | [敌人系统](../战斗循环/敌人系统.md) | | 技能表 `SkillTable` | 技能行定义(类型/倍率/冷却/增益引用)与保底阈值 | [敌人系统](../战斗循环/敌人系统.md) | | 主角表 `HeroTable` | 主角生命上限、基础攻击与护甲等级(armor_class)等单行战斗数值 | [敌人系统](../战斗循环/敌人系统.md) | diff --git a/game/README.md b/game/README.md index 2c00c031..7c1bda05 100644 --- a/game/README.md +++ b/game/README.md @@ -13,7 +13,7 @@ 1. 用 Godot 4.7.2 打开本目录(含 `project.godot` 的文件夹) 2. 按 F5 运行(主场景 `presentation/main.tscn`) 3. **主入口:`▶ 开始冒险(三关连探:地精洞窟 → 幽暗地域 → 灰矮人矿城)`**——一条命走完三关(冒险结构实现批 2026-09-21:生命/GP/加算区跨关同账、非末关通关发大奖励〔上限提升+血回满+钥石〕、任意战斗倒下冒险终、结算屏出冒险摘要五件事;选路停点可「放弃冒险」(同失败结算,2026-09-21 用户拍板补入口));首关节点链:战→战→赏→战→战→疗→王。唯一试玩入口 = 完整冒险——单关测试直入口(L2/L3)已退役(2026-09-23 用户拍板) -4. `调试` 角标浮窗(开始界面右下角,`DS_DEBUG=1` 门控——2026-10-04 迭代 14.5 调试整合批:原数值调整板/随机种子框/两层调试三散件收一):攻击/生命百分比加成(模拟天赋树解锁)+ 批量模拟(输出通关率/承伤期望/败北节点分布)+ 两层调试入口 +4. `调试` 角标浮窗(恒开——2026-10-16 用户令 DS_DEBUG 写死,原环境变量门控退役;2026-10-04 迭代 14.5 调试整合批:原数值调整板/随机种子框/两层调试三散件收一):攻击/生命百分比加成(模拟天赋树解锁)+ 批量模拟(输出通关率/承伤期望/败北节点分布)+ 两层调试入口 headless 冒烟(752 项断言〔计数随批增长,现值以最新批末闸读数为准〕,含关卡线性推进/满配通关/裸装败北/回放确定性;2026-10-02 性能报告实测 60.55 秒,报告在 `性能实测报告(已退役,git 历史可查)`): diff --git a/game/data/tables/variation.tres b/game/data/tables/variation.tres index d60de9b2..5f7b2636 100644 --- a/game/data/tables/variation.tres +++ b/game/data/tables/variation.tres @@ -73,17 +73,6 @@ rows = [{ "placement": "any", "board_types": ["deep_underdark"], "counter_items": [] -}, { -"variant_id": "skewed_veins", -"display_name": "贫矿脉", -"unlock_level": 2, -"scope": "global", -"effect": "resource_face", -"effect_value": 30, -"trigger": "always", -"placement": "any", -"board_types": [], -"counter_items": [] }] ; 地形变异 首批类型定稿批(2026-09-19 用户拍板)——四行两轴×两关: @@ -110,9 +99,9 @@ rows = [{ ; M-3 迭代 5 返工批(2026-09-29 U2 推翻 C3 裁 C1 两刀):percent_of_cells 4→5 回退;岩浆 1 与 per_level_bonus 0 维持——C1 终态; ; C1+v1 AC 组合读数归返工批全量确认(裁断全录 design/qa/m3-iter5-u2-gate-2026-09-29.md)。 ; -; 全局作用域变异首发批(2026-10-04,迭代 14 ③号卡):skewed_veins 贫矿脉——首发型 scope=global -; 案A 资源面·微贫向偏斜(P2+Q1 裁决):L2/L3 Boss 图恒定一型整图变异(P4 甲恒定制;board_types ∅ -; 通配,L2/L3 双关同型由 unlock_level=2+门控节点身份承载——Q2 甲),替换制:带全局型的 Boss 图不再 -; 布 region 片(P3 甲);effect_value=30=生存族权重下调百分比(provisional 调参项,域 [0,50], -; 0=中性 off 锚;总期望微降 3-5% 为 provisional 设计目标,精确方向与幅度归读数批只测不判); -; trigger=always=板级恒在无触发时机。行值全 provisional 归出口追认单。 +; 屏蔽记录(2026-10-16 用户令):skewed_veins 贫矿脉行已删除——用户裁「地形变异特异关卡后续重新做 +; 设计,先屏蔽」。删除后 Boss/精英图全局池空 → _resolve_global_variant 空行回落 → region 布置原路 +; 兜底(battle_orchestrator.gd 既有回落路径),玩家面零横幅零角标零资源偏斜。删除行内容与首发批 +; 裁决依据(2026-10-04 迭代 14 ③号卡:案A 资源面微贫向偏斜、effect_value=30 provisional、域 [0,50]、 +; 0=中性 off 锚)见 git 历史;resource_face 机制代码(RewardEconomy 偏斜投影/schema 互锁/负样本 +; 断言)全部保留,重建设计直接加行即可。 diff --git a/game/presentation/main.gd b/game/presentation/main.gd index 87d11c64..7b5fdda2 100644 --- a/game/presentation/main.gd +++ b/game/presentation/main.gd @@ -88,7 +88,7 @@ var meta: MetaProgressionCore: get: return get_node(AUTOLOAD_PATH_META) var logger = null # 试玩日志器(JSONL 持久化 + 卡死诊断转储——呈现层组件) -var _debug_entry := false # 调试会话门控(迭代 18 卡⑦——DS_DEBUG=1:启动即开浮窗+两屏角标点亮;_ready 赋值) +var _debug_entry := false # 调试会话门控(2026-10-16 用户令写死=true——恒开:启动即开浮窗+两屏角标点亮;_ready 赋值) var _seed_edit: LineEdit var _resume_btn: Button # 继续上局按钮句柄(迭代 8 卡②——有断点才亮) var confirm_dialog: ConfirmDialog # 通用确认弹窗(二轮修改批 A——新冒险互斥确认弹窗化) @@ -216,7 +216,7 @@ func _ready() -> void: _begin_session(false) # 闲时会话(gp_ledger 等探针注入面自 _ready 起恒在——ui_probe 合成段时序) _refresh_resume_button() # 迭代 8 卡②——启动读盘后按断点在档态点亮「继续上局」 _start_overlay.visible = true - _debug_entry = OS.get_environment("DS_DEBUG") == "1" # 迭代 18 卡⑦ P3 甲——DS_DEBUG=1 调试会话门控 + _debug_entry = true # 2026-10-16 用户令:DS_DEBUG 环境变量门控写死(原 OS.get_environment 读取已退役;发布前清) if _debug_entry: _show_debug_overlay() # 启动即开(手动可关、两屏角标可再开——P3 甲) @@ -332,7 +332,7 @@ func _build_ui() -> void: _menu_screen.resumebtn.pressed.connect(_resume_from_menu) # 迭代 8 卡②——续玩入口 _resume_btn = _menu_screen.resumebtn # 调试角标入口退役(迭代 18 卡⑦ P2 甲——迁宿主:战斗屏 HUD+关卡地图屏各一枚, - # 接线见两屏装配段;开始层不再有调试入口,DS_DEBUG=1 会话=启动即开浮窗) + # 接线见两屏装配段;开始层不再有调试入口,调试会话恒开=启动即开浮窗) # 营地/商店投影(T4/D4 拆件批——迁 camp_shop_presenter.gd;本类只接线、探针缝保缝转发; # 购买写调用唯一经 MetaProgression/LevelRunner core 单口——组合根 lambda 现值注入) _camp_pres = CampShopPresenter.new(CampFlowContext.new(db, func() -> Variant: return meta, func() -> Variant: return save_manager, camp_overlay, shop_overlay, @@ -369,7 +369,7 @@ func _build_ui() -> void: confirm_dialog.cancelled.connect(_on_confirm_cancelled) # 调试浮窗(迭代 14.5 调试整合批——主菜单三散件收一:随机种子/数值调整/批量模拟/两层调试入口; - # 迭代 18 卡⑦——升级为全局可开浮窗:DS_DEBUG=1 启动即开〔_ready〕+两屏角标再开〔P2 甲〕+当局数据只读区块〔T3〕; + # 迭代 18 卡⑦——升级为全局可开浮窗:调试会话恒开=启动即开〔_ready〕+两屏角标再开〔P2 甲〕+当局数据只读区块〔T3〕; # 迭代 26 T5b——诊断转储入口并入(原主画面左下角常驻钮退役,玩家画面清零))。 # 树序在开始层与确认弹窗之后 = 浮于菜单之上的 Dialog(不隐藏开始层——与确认弹窗同款形态); # 开窗唯一入口 = _show_debug_overlay(C6 单口——角标/探针/启动路径全收口) @@ -597,7 +597,7 @@ static func build_adventure_params(save_manager_ref, meta_ref, extra: Dictionary # 冒险模式(三关连探——AdventureRunner 编排;转发信号签名与 runner 一致,接线照原样对接; # 信号连接只在组合根) func _start_adventure() -> void: - _close_modal(debug_overlay) # 开冒险路径显式关浮窗(迭代 18 卡⑦ T2 防护——DS_DEBUG 默认开态下开局不带窗;对局中经角标再开) + _close_modal(debug_overlay) # 开冒险路径显式关浮窗(迭代 18 卡⑦ T2 防护——调试浮窗默认开态下开局不带窗;对局中经角标再开) _begin_session(true) _wire_adventure() run_scope.level_active = true @@ -1169,8 +1169,8 @@ func _sync_status_entry() -> void: # 置灰判据改排除式(迭代 18 卡⑦ T2——调试浮窗开态不计入:对局中浮窗开着时角标仍可点) board_zone.status_badge.disabled = _modal_flow.badge_greyed_battle() # 迭代 27 T4——互斥域谓词 level_screen.status_badge.disabled = _modal_flow.badge_greyed_map() - # 调试浮窗角标(迭代 18 卡⑦ P2 甲——迁宿主两屏,DS_DEBUG 门控;17卡③状态角标同形制同守卫): - # 战斗屏=对局内(冒险或调试两层)且地图屏未激活;地图屏=随屏;开始菜单零角标(DS_DEBUG=1 启动即开) + # 调试浮窗角标(迭代 18 卡⑦ P2 甲——迁宿主两屏,调试会话门控恒开;17卡③状态角标同形制同守卫): + # 战斗屏=对局内(冒险或调试两层)且地图屏未激活;地图屏=随屏;开始菜单零角标(恒开=启动即开) board_zone.debug_badge.visible = _debug_entry and not map_on and battle_live level_screen.debug_badge.visible = _debug_entry and map_on board_zone.debug_badge.disabled = board_zone.status_badge.disabled diff --git a/game/presentation/modal_stack.gd b/game/presentation/modal_stack.gd index 3b51f27e..12f2225c 100644 --- a/game/presentation/modal_stack.gd +++ b/game/presentation/modal_stack.gd @@ -11,7 +11,7 @@ var _occluded := {} # modal → 被其隐藏的上方层(关闭恢复) var _tags := {} # modal → 排除组标签集(迭代 27 T4——互斥域随层登记;P2-7 开态谓词收口) # 排除组封闭词表(组合根登记用——新标签=改此处+评审,防调用点拼装回潮) -const TAG_NON_LOCKING := "non_locking" # 开态不计入棋盘输入锁与角标置灰(调试浮窗——迭代 18 卡⑦ T2 防线:DS_DEBUG 默认开×遮挡复活×has_open 组合=棋盘永久锁死) +const TAG_NON_LOCKING := "non_locking" # 开态不计入棋盘输入锁与角标置灰(调试浮窗——迭代 18 卡⑦ T2 防线:调试浮窗默认开×遮挡复活×has_open 组合=棋盘永久锁死) const TAG_SCREEN_STATE := "screen_state" # 常驻屏态(关卡地图屏——自身开态不计入本屏角标判据) diff --git a/game/presentation/ui_assembler.gd b/game/presentation/ui_assembler.gd index 1e1b7310..eabeae87 100644 --- a/game/presentation/ui_assembler.gd +++ b/game/presentation/ui_assembler.gd @@ -91,7 +91,7 @@ static func build_overlays(host: Control, db) -> Dictionary: # 开始覆盖层(返回 {overlay, box, lvbtn, resumebtn, campbtn, careerbtn, settingsbtn, quitbtn}——按钮接线归组合根; # 迭代 14.5 调试整合批:随机种子/数值调整板/两层调试三散件撤出主按钮组,收进调试浮窗—— # 迭代 18 卡⑦ P2 甲:右下角「调试」角标亦退役(入口迁宿主=战斗屏 HUD+关卡地图屏两枚角标, -# DS_DEBUG=1 会话浮窗启动即开——本层零调试入口) +# 调试会话恒开,浮窗启动即开——本层零调试入口) # UI 落码批 M2(2026-10-04):单列 VBox→双列(左操作 56% + 右舞台);按钮动词化+悬停解释 #(解释全迁 tooltip,G5);lvbtn 升主操作钮(烛光黄 CANDLE);右列=立绘看台。**玩法速览牌已退役 #(2026-10-06 用户令:界面禁玩法文字墙——教学内容归 Beta 帮助手册〔教学引导定稿批 P4 丙〕,历史文案在 git)**; @@ -158,8 +158,8 @@ static func build_start_overlay(host: Control, db = null) -> Dictionary: box.add_child(quitbtn) # 迭代 18 卡⑦ P2 甲——旧右下角调试角标退役(原迭代 14.5 装配段删除):入口迁宿主两屏 - #(board_zone_view.debug_badge / level_map_screen.debug_badge),DS_DEBUG 门控与可见性 - # 同步归组合根 _sync_status_entry;开始层零调试入口(DS_DEBUG=1 会话=浮窗启动即开) + #(board_zone_view.debug_badge / level_map_screen.debug_badge),调试门控与可见性 + # 同步归组合根 _sync_status_entry;开始层零调试入口(调试会话恒开=浮窗启动即开) # 右列:立绘看台 + 玩法速览牌(M2——帮助全文保留表值驱动,仅容器化;内容含地形变异段不删) var right := VBoxContainer.new() diff --git a/game/presentation/views/board_zone_view.gd b/game/presentation/views/board_zone_view.gd index 7dfd627d..01385140 100644 --- a/game/presentation/views/board_zone_view.gd +++ b/game/presentation/views/board_zone_view.gd @@ -11,7 +11,7 @@ var board_view: BoardView var toast: ToastStack var fx: BoardFxView var status_badge: Button # 状态面板入口角标(迭代 17 卡③ P1 丁——debug 角标同形制;连接归组合根) -var debug_badge: Button # 调试浮窗入口角标(迭代 18 卡⑦ P2 甲——DS_DEBUG 门控归组合根;状态角标同形制) +var debug_badge: Button # 调试浮窗入口角标(迭代 18 卡⑦ P2 甲——调试门控归组合根;状态角标同形制) var _board_area: Control # resized 命名转发用(原 lambda 局部捕获——P1-3 转命名 2026-09-29) signal action_requested(cell: Vector2i, kind: String) @@ -44,7 +44,7 @@ func _init() -> void: board_area.add_child(toast) # 角标对(迭代 18 卡⑦ P2 甲——调试+状态两枚右下角常驻,HBox 并排锚角距 16px): # 17卡③状态角标同形制:紧凑钮豁免宽度基准+字号降档。可见性/置灰归组合根 _sync_status_entry - #(DS_DEBUG 门控/其他模态开着=置灰不可点——排除式开态查询);信号连接归组合根。 + #(调试门控/其他模态开着=置灰不可点——排除式开态查询);信号连接归组合根。 # preset 在子件全部入列后调用——MINSIZE 锚按当时最小尺寸计偏移(空容器调用=零尺寸锚外溢屏边) var corner := HBoxContainer.new() corner.add_theme_constant_override("separation", 8) diff --git a/game/presentation/views/debug_overlay.gd b/game/presentation/views/debug_overlay.gd index f1852d94..014d1433 100644 --- a/game/presentation/views/debug_overlay.gd +++ b/game/presentation/views/debug_overlay.gd @@ -1,6 +1,6 @@ # VERTICAL SLICE - NOT FOR PRODUCTION # Date: 2026-10-04(主菜单调试三散件(随机种子/角色数值调整板/两层调试入口)收一张调试浮窗) -# 开发调试浮窗:全局可开(DS_DEBUG=1 会话启动即开〔组合根 _ready〕+战斗屏 HUD/关卡地图屏 +# 开发调试浮窗:全局可开(调试会话恒开,启动即开〔组合根 _ready〕+战斗屏 HUD/关卡地图屏 # 两枚角标再开;遮挡语义=ModalStack 登记制:他模态开时暂隐、关后自动恢复)。 # 当局数据只读区块=本局种子唯一查看位(六项)。 # 列表页形态可扩展:后续调试项按区块往下追加,超高滚动。 @@ -163,7 +163,7 @@ func _build() -> void: var title := UiKit.label("调试",UiKit.FS_TITLE, true, UiKit.WARM) box.add_child(title) var desc := UiKit.label( - "开发调试专用(DS_DEBUG=1 会话:启动即开;战斗屏/地图屏「调试」角标可再开)。当局数据=本局只读投影,种子即本局种子唯一查看位。\n百分比叠加基础值:攻击 %d / 生命 %d。影响所有模式(手动与模拟),不落盘。" % [_base_atk, _base_hp], + "开发调试专用(恒开:启动即开;战斗屏/地图屏「调试」角标可再开)。当局数据=本局只读投影,种子即本局种子唯一查看位。\n百分比叠加基础值:攻击 %d / 生命 %d。影响所有模式(手动与模拟),不落盘。" % [_base_atk, _base_hp], 13, false, UiKit.WARM_SOFT) box.add_child(desc) box.add_child(HSeparator.new()) diff --git a/game/presentation/views/level_map_screen.gd b/game/presentation/views/level_map_screen.gd index 38f29eb6..900dcf9f 100644 --- a/game/presentation/views/level_map_screen.gd +++ b/game/presentation/views/level_map_screen.gd @@ -58,7 +58,7 @@ var _content_size := Vector2(620, 240) # 图内容包络(open_choices 按图 var _hover_id := -1 # 悬停预承诺候选(-1 = 无) var abandon_btn: Button # 放弃入口(可见性归组合根 set_abandon_available——只在冒险模式开) var status_badge: Button # 状态面板入口角标(迭代 17 卡③ P1 丁——顶栏 GP 徽右侧;连接归组合根) -var debug_badge: Button # 调试浮窗入口角标(迭代 18 卡⑦ P2 甲——DS_DEBUG 门控;状态角标同形制) +var debug_badge: Button # 调试浮窗入口角标(迭代 18 卡⑦ P2 甲——调试门控;状态角标同形制) var _abandon_timer := ArmedTimer.new() # 放弃确认窗(T3/D3 P4 乙——_process 帧驱动倒计时机制收口;窗口=CONFIRM_WINDOW_S) var _node_icons := {} # 节点图标贴图(load_tex 守卫——缺位 null → 字形回退,冒烟/无素材检出安全) var _noise_rect: TextureRect # 屏底石纹(换层色板渐变承载面——null = 纯色回退无挂点) @@ -119,7 +119,7 @@ func _init() -> void: status_badge.size_flags_vertical = Control.SIZE_SHRINK_CENTER top.add_child(status_badge) # 调试浮窗入口角标(迭代 18 卡⑦ P2 甲——顶栏状态角标右侧;17卡③同形制:紧凑钮豁免宽度基准+ - # 字号降档。可见性/置灰归组合根 _sync_status_entry(DS_DEBUG 门控/其他模态开着=置灰——排除式 + # 字号降档。可见性/置灰归组合根 _sync_status_entry(调试门控/其他模态开着=置灰——排除式 # 开态查询,本屏自身开态不计);信号连接归组合根(视图零连接)) debug_badge = UiKit.button("调试", 0.0) debug_badge.add_theme_font_size_override("font_size", UiKit.FS_HINT) diff --git a/game/smoke/shot_probe.gd b/game/smoke/shot_probe.gd index eed87371..eabea54f 100644 --- a/game/smoke/shot_probe.gd +++ b/game/smoke/shot_probe.gd @@ -44,6 +44,11 @@ func _ready() -> void: # apply 隔离档出厂默认=窗口化 1280x800,恢复本探针设计前提。探针侧环境修正,零运行时改动) main.settings_store.apply() await get_tree().process_frame + # 调试浮窗归一(2026-10-16 用户令 DS_DEBUG 写死=true 后 boot 即开——视觉契约截图不含开发件, + # 走真实关闭单口 _close_modal;golden/shot 基线与调试模式解耦,发布前删写死时基线不受影响) + if main.debug_overlay != null and main.debug_overlay.visible: + main._close_modal(main.debug_overlay) + await get_tree().process_frame # ① 菜单(启动态)——meta 锚经 S1 裁后换代(2026-10-08 用户裁:副标题锚改认现行文案; # 帮助文腿整个退役——载体玩法速览牌 2026-10-06 用户令退役,checker 对应断言段同撤) # 自检一(迭代 28 T4):boot 态顶层可见全屏层=start_overlay(内容层树遍历——屏壳是容器不当候选: diff --git a/game/smoke/smoke_all.gd b/game/smoke/smoke_all.gd index 0bbb82f4..14be52f4 100644 --- a/game/smoke/smoke_all.gd +++ b/game/smoke/smoke_all.gd @@ -185,8 +185,8 @@ func _smoke_scene_split() -> void: # V1a 启动态顶层断言:boot 后自树顶向下第一个可见内容层=start_overlay(headless 可判) #(内容层遍历——屏壳是容器不当候选:camp 壳 boot 态 vis=true 但成员恒隐,裸树遍历会误命中) var top: Node = _topmost_visible_layer(main) - check(top == main._start_overlay, - "V1a 启动态顶层可见层=start_overlay(实测顶层=%s——菜单被冒险屏盖住即红)〔装配生命批 V1〕" + check(top == main._start_overlay or top == main.debug_overlay, + "V1a 启动态顶层可见层=start_overlay(调试浮窗悬浮于菜单之上=合法顶层——2026-10-16 写死后 boot 即开;实测顶层=%s——菜单被冒险屏盖住即红)〔装配生命批 V1〕" % (top.name if top != null else "null")) # V1b 语义关系:start_overlay 在冒险屏内容之上(菜单屏壳在冒险屏壳之上——装配序修复判据) check(main._menu_screen.get_index() > main._adventure_screen.get_index(), @@ -291,11 +291,9 @@ func _smoke_boot_chain() -> void: # ⑤ 闲时会话(_ready 即建、永非 null、在树) check(main.run_scope != null and not main.run_scope.is_adventure and main.run_scope.is_inside_tree(), "V2e run_scope 非空且为闲时会话(is_adventure=false+is_inside_tree)〔装配生命批 V2〕") - # ⑥ DS_DEBUG 门控一致性(未设=浮窗隐藏;设了=启动即开——两侧同一判据) - var debug_on: bool = OS.get_environment("DS_DEBUG") == "1" - check(main.debug_overlay.visible == debug_on, - "V2f 调试浮窗态==DS_DEBUG 门控(visible=%s DS_DEBUG=%s)〔装配生命批 V2〕" % [ - str(main.debug_overlay.visible), str(debug_on)]) + # ⑥ 调试浮窗恒开(2026-10-16 用户令 DS_DEBUG 写死=true——原环境变量门控退役,启动即开为常态) + check(main.debug_overlay.visible, + "V2f 调试浮窗恒开(visible=%s)〔2026-10-16 写死令〕" % str(main.debug_overlay.visible)) main.queue_free() await process_frame for p in ["user://smoke_boot_chain.json", "user://smoke_boot_chain.json.tmp"]: @@ -2245,8 +2243,8 @@ func _mk_stream(stream_name: String, scope: int) -> RandomNumberGenerator: func _smoke_variation_framework() -> void: print("--- 地形变异 框架面(首批四类型 + 候选池门控 + 跨字段互锁)---") - check(_db.variation.rows.size() == 7, "变异清单 7 行(荆棘丛/藤蔓缠绕/岩浆/烬覆 + 落石/矿尘 + 贫矿脉——首批类型定稿批 + 第三关内容批 + 全局作用域变异首发批)") - check(_db.variation.validate().is_empty(), "变异表校验零错误(7 行全过域与跨字段互锁——含 scope=global 三互锁)") + check(_db.variation.rows.size() == 6, "变异清单 6 行(荆棘丛/藤蔓缠绕/岩浆/烬覆 + 落石/矿尘——首批类型定稿批 + 第三关内容批;贫矿脉 2026-10-16 用户令屏蔽删行)") + check(_db.variation.validate().is_empty(), "变异表校验零错误(6 行全过域与跨字段互锁——含 scope=global 三互锁负样本)") var pool1_ids: Array = [] for r in _db.variant_pool(1, "dungeon"): pool1_ids.append(String(r.variant_id)) @@ -2280,10 +2278,10 @@ func _errs_has_cross_field(errs: Array) -> bool: return false -# ---- 全局作用域变异 首发批断言面(2026-10-04 迭代 14 ③号卡——T0-T5 集中:互锁/门控三维/ -# 替换制/零取号/资源面偏斜守恒与合成序/快照投影/呈现面锚)---- +# ---- 全局作用域变异 断言面(2026-10-04 迭代 14 ③号卡首发批立面;2026-10-16 用户令屏蔽贫矿脉删行后 +# 改测「全局池空 → region 兜底回落」路径——互锁负样本/门控三维/资源面偏斜守恒与合成序/快照投影不变)---- -# 取号计数桩(variant_place 零取号断言——子类拦截计数,派生与取数语义零改动) +# 取号计数桩(variant_place 取号断言——子类拦截计数,派生与取数语义零改动) class _CountVariantRng extends RngServiceCore: var variant_calls := 0 func open_stream(purpose: String) -> RandomNumberGenerator: @@ -2302,7 +2300,7 @@ class _BoardRowStub: func _smoke_global_variant() -> void: - print("--- 全局作用域变异 首发批(门控三维 + 替换制 + 资源面偏斜)---") + print("--- 全局作用域变异(门控三维 + 全局池空兜底回落 + 资源面偏斜)---") # ① 跨字段互锁负样本(resource_face ⟺ scope=global 三条 + effect_value 新域 [0,50]) var vt = load("res://data/schemas/variation_table.gd").new() vt.rows.assign([{"variant_id": "g1", "display_name": "负甲", "unlock_level": 2, "scope": "region", @@ -2334,7 +2332,7 @@ func _smoke_global_variant() -> void: var pool_boss_ids: Array = [] for r in _db.variant_pool(2, "underdark", "boss"): pool_boss_ids.append(String(r.variant_id)) - check(pool_boss_ids == ["magma", "ash", "skewed_veins"], "门控三维:L2 underdark boss 池 = region 两行 + 贫矿脉(board_types ∅ 通配)") + check(pool_boss_ids == ["magma", "ash"], "门控三维:L2 underdark boss 池 = region 两行(贫矿脉 2026-10-16 屏蔽删行后无 global 行)") var pool_battle_ids: Array = [] for r in _db.variant_pool(2, "underdark", "battle"): pool_battle_ids.append(String(r.variant_id)) @@ -2343,31 +2341,43 @@ func _smoke_global_variant() -> void: "门控三维:缺省双参调用 = global 行跳过(既有调用口径零扰动)") check(_db.variant_pool(1, "underdark", "boss").is_empty(), "L1 Boss 免疫:unlock_level=2 门控在 boss 节点同样生效(教学保护带 B)") check(_db.global_variant_row(2, "underdark", "battle").is_empty(), "全局决议:battle 节点恒无全局型") - check(_db.global_variant_row(2, "underdark", "boss").get("variant_id", "") == "skewed_veins", "全局决议:L2 boss 取贫矿脉(确定性单行)") + check(_db.global_variant_row(2, "underdark", "boss").is_empty(), "全局决议:L2 boss 全局池空 → 空行(贫矿脉屏蔽后兜底回落承载)") check(_db.global_variant_row(1, "underdark", "boss").is_empty() and _db.global_variant_row(1, "dungeon", "boss").is_empty(), "全局决议:L1 boss 全局池空 → 空行(兜底回落承载)") - check(_db.global_variant_row(2, "underdark", "elite").get("variant_id", "") == "skewed_veins", "elite 前向词位:boss 同池(首发零 elite 表行——词表位不造行)") - # ③ 替换制 + 零取号:L2 Boss 图恰一行板级变异 + 零 region 格 + variant_place 零消费 + check(_db.global_variant_row(2, "underdark", "elite").is_empty(), "elite 前向词位:boss 同池恒空(贫矿脉屏蔽后——词表位不造行)") + # ③ 兜底回落:全局池空 → Boss 图改走 region 候选池(恰一行 region 变异 + 格子级布置 + 正常取号) var crng = _CountVariantRng.new() crng.set_master_seed(42) var boss_settlement = load("res://core/battle_orchestrator.gd").new(_db, crng) var boss_ok: bool = boss_settlement.begin_battle({"level_index": 2, "node_depth": 4, "hero_hp": int(_db.hero.max_hp), "node_type": "boss"}) - check(boss_ok, "L2 Boss 战斗启动(node_depth=4 boss 节点——替换制断言载体)") + check(boss_ok, "L2 Boss 战斗启动(node_depth=4 boss 节点——兜底回落断言载体)") + var boss1_ids: Array = [] + var boss1_variants: Dictionary = {} + var boss1_calls := 0 if boss_ok: var bb = boss_settlement.minesweeper.current_board() - check(_arr_str_eq(bb.board_variant_ids(), ["skewed_veins"]), "替换制:Boss 图 board_variants 恰一行 = 贫矿脉") - check(bb.variants.is_empty(), "替换制:Boss 图零 region 变异格(无格子级变异标记——呈现件闲置合法态)") - check(crng.variant_calls == 0, "零取号合法态:Boss 图 variant_place 零消费(全局取用确定性)") + check(bb.board_variant_ids().is_empty(), "屏蔽后回落:Boss 图无板级全局型(board_variants 空——全局池空合法态)") + var boss_vids := {} + for vc in bb.variants: + for vid in bb.variants[vc]: + boss_vids[String(vid)] = true + check(boss_vids.size() == 1 and (boss_vids.has("magma") or boss_vids.has("ash")), + "屏蔽后回落:Boss 图 region 变异恰一行且在候选池内(实测 %s)" % str(boss_vids.keys())) + check(not bb.variants.is_empty(), "屏蔽后回落:Boss 图恢复 region 变异格布置(原替换制跳过 region 的逻辑随全局池空失效)") + check(crng.variant_calls > 0, "屏蔽后回落:variant_place 恢复取号(原全局取用零取号态消失)") var snap: Dictionary = boss_settlement.presentation_snapshot() - check(_arr_str_eq(snap.get("board_variants", []), ["skewed_veins"]), "快照投影:board_variants 呈现面(横幅/角标唯一读取面)") + check(_arr_str_eq(snap.get("board_variants", []), bb.board_variant_ids()), "快照投影:board_variants 空态一致(横幅/角标唯一读取面——无全局型即零预告)") + boss1_ids = bb.board_variant_ids() + boss1_variants = bb.variants.duplicate() + boss1_calls = crng.variant_calls # Boss 图确定性:同种子两遍逐位相同 var crng2 = _CountVariantRng.new() crng2.set_master_seed(42) var boss2 = load("res://core/battle_orchestrator.gd").new(_db, crng2) if boss2.begin_battle({"level_index": 2, "node_depth": 4, "hero_hp": int(_db.hero.max_hp), "node_type": "boss"}): var bb2 = boss2.minesweeper.current_board() - check(_arr_str_eq(bb2.board_variant_ids(), ["skewed_veins"]) and crng2.variant_calls == 0, - "确定性:同种子 Boss 图两遍 board_variants/取号逐位相同") + check(_arr_str_eq(bb2.board_variant_ids(), boss1_ids) and bb2.variants == boss1_variants and crng2.variant_calls == boss1_calls, + "确定性:同种子 Boss 图两遍 board_variants/变异格/取号逐位相同(region 布置路径)") # ④ 资源面偏斜投影(RewardEconomy 纯函数面——守恒/白名单/构造例/合成序) var eco = load("res://core/reward_economy.gd").new(_db, load("res://core/rng_service.gd").new()) var base_rows: Array = eco._rollable_rows() diff --git a/game/smoke/ui_click_probe.gd b/game/smoke/ui_click_probe.gd index a3adb10d..239f13cb 100644 --- a/game/smoke/ui_click_probe.gd +++ b/game/smoke/ui_click_probe.gd @@ -46,6 +46,10 @@ func _ready() -> void: add_child(main) await get_tree().process_frame var t_ui_ready := Time.get_ticks_msec() - t0 + # 调试浮窗恒开(2026-10-16 用户令 DS_DEBUG 写死=true——boot 即开;他模态开时暂隐归 ModalStack + # 遮挡语义,恢复判据见设置面关闭段) + if not main.debug_overlay.visible: + _problems.append("调试浮窗启动未即开(恒开门控失守)") # ---- 营地购买合成点击路径(元进度实现批——campbtn/购买/关闭全走真实按钮信号路径; # 隔离存档换注 main.meta 保确定性(禁碰真实档 user://save.json);陈旧档段首清理)---- for p0 in ["user://smoke_click_probe_reset.json", "user://smoke_click_probe_reset.json.tmp"]: @@ -167,20 +171,20 @@ func _ready() -> void: _problems.append("音量滑杆未实时生效(master bus db %f ≠ %f)" % [AudioServer.get_bus_volume_db(master_idx), expect_db]) if absf(iso_s.volume_linear - 0.3) > 0.001: _problems.append("音量未入 store(%f ≠ 0.3)" % iso_s.volume_linear) - # 调试入口断言改向(迭代 18 卡⑦ P2 甲——开始层角标退役迁宿主两屏;探针环境 DS_DEBUG 未设 - # =浮窗不默认开〔P3 门控〕、DS_DEBUG 门控由开始层角标移两屏角标) + # 调试入口断言改向(迭代 18 卡⑦ P2 甲——开始层角标退役迁宿主两屏;DS_DEBUG 写死后浮窗 + # 恒开,本段(设置面开中)浮窗暂隐归 ModalStack 遮挡语义,恢复判据见下方关闭段) if ProbeUiUtil.find_button(main._start_overlay, "调试", "prefix") != null: _problems.append("开始层调试角标未退役(迭代 18 卡⑦ P2 甲迁宿主失守)") - if main.debug_overlay.visible: - _problems.append("DS_DEBUG 未设时浮窗默认开(P3 启动门控失守)") var settings_close: Button = ProbeUiUtil.find_button(main.settings_overlay, "返回", "prefix") if settings_close == null: _problems.append("设置面返回按钮缺失") else: settings_close.pressed.emit() await get_tree().process_frame - if main.settings_overlay.visible or not main._start_overlay.visible: - _problems.append("设置面关闭后未恢复开始层") + if main.settings_overlay.visible or not main._start_overlay.visible: + _problems.append("设置面关闭后未恢复开始层") + if not main.debug_overlay.visible: + _problems.append("设置面关闭后调试浮窗未恢复(ModalStack 遮挡恢复失守)") # 旧入口退役断言(卡④ AC③——测试调整板不再含减动效开关;14.5 起载体=调试浮窗) var legacy_motion = ProbeUiUtil.find_check_button(main.debug_overlay, "减动效") if legacy_motion != null: diff --git a/game/smoke/ui_tune_probe.gd b/game/smoke/ui_tune_probe.gd index 6d5fa0e3..a68cedb2 100644 --- a/game/smoke/ui_tune_probe.gd +++ b/game/smoke/ui_tune_probe.gd @@ -2,7 +2,7 @@ # Date: 2026-09-11(加成应用契约 = 组合根单一应用路径) # 调试浮窗场景探针(原数值调整板收进 debug_overlay; # 角标挂宿主 / 启动即开 / 当局数据只读区块 / 输入锁防护配套): -# 驱动真实 UI 路径——①启动即开(DS_DEBUG=1 默认打开,探针自设环境变量)+悬浮菜单之上+登记册末位树序 +# 驱动真实 UI 路径——①启动即开(调试会话恒开)+悬浮菜单之上+登记册末位树序 # ②滑条联动 ③应用 ④重置 ⑤批量模拟 N=10 ⑥关闭 ⑦hero 表运行期不可变 # ⑧单次加成生效(经 _start_adventure_from_menu 真实路径+显式种子钉死)+开冒险路径显式关浮窗 # ⑨对局中可开(战斗屏角标真实信号路径)+棋盘输入不锁+状态角标不置灰(停机点回归闸) @@ -30,7 +30,6 @@ const _OVERLAY_VIEW_METHODS: Array[String] = ["_on_fx_toggle", "_apply_btn_press func _ready() -> void: - OS.set_environment("DS_DEBUG", "1") # P3 甲断言前提——探针自设调试会话环境(headless 进程内生效) await get_tree().process_frame var main: Node = load("res://presentation/main.tscn").instantiate() add_child(main) @@ -41,11 +40,11 @@ func _ready() -> void: var base_hp := int(main.db.hero.max_hp) var boosted_atk := base_atk * 2 # 攻击滑条 100 → ×2 var boosted_hp := int(round(base_hp * 1.5)) # 生命滑条 50 → +50% - # ① 启动即开(18卡⑦ P3 甲——DS_DEBUG=1 会话组合根 _ready 即开;悬浮于菜单之上——开始层不隐藏; + # ① 启动即开(2026-10-16 用户令写死=恒开——组合根 _ready 即开;悬浮于菜单之上——开始层不隐藏; # 树序新基准=登记册末位(确认弹窗之后=绘制序最上);旧「_show_debug_overlay 打开+开始层在屏」 # 断言随入口迁宿主换代——打开动作本身移至 ⑨ 角标真实路径承载) if not main.debug_overlay.visible: - problems.append("DS_DEBUG=1 启动浮窗未即开(P3 甲失守)") + problems.append("调试浮窗启动未即开(恒开门控失守)") if not main._start_overlay.visible: problems.append("开始覆盖层被隐藏——浮窗应悬浮于菜单之上(14.5 形态失守)") if main.debug_overlay.get_index() < main.confirm_dialog.get_index(): @@ -95,7 +94,7 @@ func _ready() -> void: main._start_adventure_from_menu() # 完整冒险路径(唯一试玩入口;_start_single 按语义清零滑条 = 恒基线,不承载加成断言) await get_tree().process_frame await get_tree().process_frame - # ⑧b 开冒险路径显式关浮窗(18卡⑦ T2 防护——DS_DEBUG 会话默认开态下开局不带窗,对局中经角标再开) + # ⑧b 开冒险路径显式关浮窗(18卡⑦ T2 防护——调试会话默认开态下开局不带窗,对局中经角标再开) if main.debug_overlay.visible: problems.append("开冒险路径未显式关浮窗(T2 防护失守)") if int(main.run_scope.adventure.master_seed) != 42: @@ -114,7 +113,7 @@ func _ready() -> void: # 对局中批量模拟/两层调试两钮禁用;当局数据六项与只读访问器逐项一致;关闭钮真实路径收窗恢复 var dbg_badge: Button = main.board_zone.debug_badge if dbg_badge == null or not dbg_badge.visible: - problems.append("战斗屏调试角标未点亮(P2 甲 DS_DEBUG 门控失守)") + problems.append("战斗屏调试角标未点亮(P2 甲恒开门控失守)") else: if dbg_badge.disabled: problems.append("战斗屏调试角标被置灰(T2 排除式判据失守)") diff --git a/game/tests/.gates/baseline.json b/game/tests/.gates/baseline.json index d5acaec5..a45f635d 100644 --- a/game/tests/.gates/baseline.json +++ b/game/tests/.gates/baseline.json @@ -39,7 +39,7 @@ }, "09 静态扫描": { "exit": "1", - "fp": "3220614b09c4" + "fp": "4354b2aa72a7" }, "10 熵增闸": { "exit": "0",