merge: 贫矿脉屏蔽+DS_DEBUG写死批全量入库(五提交, worktree g-plan2-shielddebug-20261016)

用户令两项(2026-10-16):①「地形变异特异关卡后续重新做设计,先屏蔽」——variation.tres
删 skewed_veins 行,Boss/精英图全局池空→region 兜底回落,玩家面零横幅零角标零偏斜;
②「debug 变量直接写死,不读环境变量」——main.gd _debug_entry 恒 true,全库 DS_DEBUG
引用清零。机械面文档四件同步(07 ⑪ 转记/架构行数/数据配置/06 条目);设计语义面立
反哺点待裁(地形变异.md §全局作用域型/HUD 框架三层预告/教学引导手册行/难度曲线两行/
art-bible §4.6.3 括注)。闸面三修(冒烟作用域/shot_probe 浮窗归一/click_probe 断言
归位)+ 基线 09 指纹刷新(并行会话头注漂移,非本批引入——主区与分支审计逐行一致)。
全量闸验收通过(存量红零新增);读数义务归 M4(Boss 图资源面/region 布置分布)。
This commit is contained in:
DKChan committed 2026-10-16 03:53:30 +08:00
commit d3356985a8
17 files changed
+84 -75

No files matched your search

+1 -1
View File
@@ -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 | 无 |
+1 -1
View File
@@ -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 不含」节。
+2
View File
@@ -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 批调整以当批登记为准。
@@ -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) |
+1 -1
View File
@@ -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 历史可查)`):
+6 -17
View File
@@ -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 互锁/负样本
; 断言)全部保留,重建设计直接加行即可。
+7 -7
View File
@@ -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
+1 -1
View File
@@ -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" # 常驻屏态(关卡地图屏——自身开态不计入本屏角标判据)
+3 -3
View File
@@ -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()
+2 -2
View File
@@ -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)
+2 -2
View File
@@ -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())
+2 -2
View File
@@ -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)
+5
View File
@@ -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(内容层树遍历——屏壳是容器不当候选:
+34 -24
View File
@@ -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()
+10 -6
View File
@@ -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:
+5 -6
View File
@@ -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 排除式判据失守)")
+1 -1
View File
@@ -39,7 +39,7 @@
},
"09 静态扫描": {
"exit": "1",
"fp": "3220614b09c4"
"fp": "4354b2aa72a7"
},
"10 熵增闸": {
"exit": "0",