From 6e8babdcfd7d7f5e8a2433abe678af755fd63cac Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Mon, 21 Sep 2026 19:23:03 +0800 Subject: [PATCH] =?UTF-8?q?fix(terrain-variation):=20=E5=8F=98=E5=BC=82?= =?UTF-8?q?=E5=B8=83=E7=BD=AE=E5=9F=BA=E6=95=B0=E4=BF=AE=E6=AD=A3=E2=80=94?= =?UTF-8?q?=E2=80=94=E6=95=B0=E9=87=8F=E5=85=AC=E5=BC=8F=E7=99=BE=E5=88=86?= =?UTF-8?q?=E6=AF=94=E5=9F=BA=E6=95=B0=E7=94=B1=E6=80=BB=E6=A0=BC=E6=95=B0?= =?UTF-8?q?=E6=94=B9=E5=80=99=E9=80=89=E6=B1=A0=E6=A0=BC=E6=95=B0=EF=BC=88?= =?UTF-8?q?2026-09-21=20=E7=94=A8=E6=88=B7=E6=8B=8D=E6=9D=BF=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 初始展开平均占全板 56–67%,总格数基数使变异在剩余可挖格中的有效密度膨胀 4–6 倍 (实测:L1 10×10 板配置 5% 实际 30.1%,极端板可挖格 100% 覆盖;L2 25.8%/L3 23–26%)。 修正后 percent 语义 = 占可挖安全格比例,关卡递增由 per_level_bonus 绝对格数承载; 表值 percent=5/per_level_bonus=2 不动(provisional 归难度曲线与Boss 调参批)。 - battle_orchestrator._place_variants:公式基数 candidates.size();头注同步 - smoke:布置公式上限断言同步候选池基数;非零金丝雀改条件式(L1 无加成极小池 round 至 0 = 合法零布置,与池空同口径) - 文档五处同步:GDD 地形变异正文公式行+调参表、registry variation mvp_content、 variation.tres 尾注、variation_table schema 头注 验证:冒烟 550 项 0 失败(run_smoke 三闸过);同种子 36 局(24 普通+12 完美)A/B—— 变异触发 8.08→4.83 次/局(-40%),荆棘触发 177→51,变异占主角承伤 31.9%→19.6%; 全冒险通关 3/36→17/36(同种子窗小样本,正式重基线归调参批)。 --- design/gdd/systems/排雷循环/地形变异.md | 4 ++-- design/registry/entities.yaml | 2 +- .../core/battle_orchestrator.gd | 8 +++++--- .../data/schemas/variation_table.gd | 5 +++-- .../data/tables/variation.tres | 7 ++++++- .../smoke/smoke_all.gd | 12 +++++++++--- 6 files changed, 26 insertions(+), 12 deletions(-) diff --git a/design/gdd/systems/排雷循环/地形变异.md b/design/gdd/systems/排雷循环/地形变异.md index b34d5d7a..37d7ff1a 100644 --- a/design/gdd/systems/排雷循环/地形变异.md +++ b/design/gdd/systems/排雷循环/地形变异.md @@ -81,7 +81,7 @@ 变异在战斗初始化末段布置:初始展开完成、地图战斗资源格设置之后,由战斗结算的编排段执行。候选池非空时从池内均匀选一类型,按布置参数生长连通片写入格子快照: -- 数量 = round(总格数 × percent_of_cells / 100) + (关卡序号 − 1) × per_level_bonus(当前 5% + 每关 +2——图规模百分比兼顾大小图,关卡递增承载"越深越险";provisional 归难度曲线与Boss)。 +- 数量 = round(候选池格数 × percent_of_cells / 100) + (关卡序号 − 1) × per_level_bonus(当前 5% + 每关 +2——百分比的基数是候选池格数而非总格数:初始展开通常占全板过半,按总格数取数会使变异在剩余可挖格中的实际密度远超配置值(2026-09-21 用户拍板基数修正);percent 承载"占可挖格比例",关卡递增由 per_level_bonus 绝对格数承载"越深越险";provisional 归难度曲线与Boss)。 - 形状 = 全连通生长(8 邻),单片 ≤ pack_max(当前 4:2×2 / 1×4 / 1×3+1 等形;2026-09-19 用户拍板)。 - 候选格域 = 安全格 − 初始展开区,且排除雷格。 - 布置取数走专用随机流(variant_place,一板恰一 scope),换图/轮内刷新图各取号一次,确定性可复放。 @@ -124,7 +124,7 @@ | 参数 | 现行值 | 归属 | |---|---|---| -| 布置数量基数 percent_of_cells | 5(总格数百分比) | 难度曲线与Boss(provisional) | +| 布置数量基数 percent_of_cells | 5(候选池格数百分比,2026-09-21 基数修正) | 难度曲线与Boss(provisional) | | 关卡递增 per_level_bonus | +2 格/关 | 难度曲线与Boss(provisional) | | 连通片上限 pack_max | 4 | 定稿值(2026-09-19 用户拍板形状约束) | | 直伤量 effect_value | 荆棘丛 1 / 岩浆 2 / 落石 3 | 难度曲线与Boss(provisional,加法核 [1,9]) | diff --git a/design/registry/entities.yaml b/design/registry/entities.yaml index 1e4ee037..b60b91c3 100644 --- a/design/registry/entities.yaml +++ b/design/registry/entities.yaml @@ -111,7 +111,7 @@ entities: attributes: table: VariationTable(数据配置 承载,键 = variant_id;地形变异 回填 owner,2026-09-08 定稿回填;2026-09-20 首批类型定稿批字段集枚举化重写) fields: variant_id(String 主键唯一)/ display_name / unlock_level(int [1,999],knob)/ scope(enum region|global,global 预留 难度曲线与Boss)/ effect(enum none|flat_damage|hide_number,词表可扩充)/ effect_value(int [1,9],仅 flat_damage 消费,加法核小整数 knob)/ trigger(enum on_open|on_number_shown,词表可扩充)/ placement(enum closed_only|any,词表可扩充)/ board_types(StringList,∅=通配,knob——2026-09-20 用户裁定由 biome_tag 更名对齐 board_type 词表)/ counter_item_ids(StringList,魔法道具 预留,非 knob——首批四行恒空,Alpha 反制批回填)/ 表头布置参数 percent_of_cells=5 · per_level_bonus=2 · pack_max=4(knob,难度曲线与Boss) - mvp_content: 六行两轴×三关(2026-09-20 首批类型定稿批四行 + **第三关内容批两行**)——thorn 荆棘丛(flat_damage/on_open/closed_only/dungeon/1)· vine 藤蔓缠绕(hide_number/on_number_shown/any/dungeon)· magma 岩浆(flat_damage/on_open/closed_only/underdark/2,登记名沿用)· ash 烬覆(hide_number/on_number_shown/any/underdark)· rockfall 落石(flat_damage/on_open/closed_only/deep_underdark/3——伤害型关间递进 1→2→3)· mine_dust 矿尘(hide_number/on_number_shown/any/deep_underdark/3,信息型);counter_items 恒空(反制归 Alpha 反制批);布量走既有公式(5%+per_level_bonus×2=9%);行值 provisional 归 难度曲线与Boss;冰冻占位名退役 + mvp_content: 六行两轴×三关(2026-09-20 首批类型定稿批四行 + **第三关内容批两行**)——thorn 荆棘丛(flat_damage/on_open/closed_only/dungeon/1)· vine 藤蔓缠绕(hide_number/on_number_shown/any/dungeon)· magma 岩浆(flat_damage/on_open/closed_only/underdark/2,登记名沿用)· ash 烬覆(hide_number/on_number_shown/any/underdark)· rockfall 落石(flat_damage/on_open/closed_only/deep_underdark/3——伤害型关间递进 1→2→3)· mine_dust 矿尘(hide_number/on_number_shown/any/deep_underdark/3,信息型);counter_items 恒空(反制归 Alpha 反制批);布量走既有公式(5%+per_level_bonus×2——2026-09-21 基数修正批:百分比基数=候选池格数〔安全格−初始展开区〕非总格数,percent 语义=占可挖格比例);行值 provisional 归 难度曲线与Boss;冰冻占位名退役 zero_special_casing: 连锁/数字计数/清图/旗/价目/结算零特判——既有系统行为不感知变异状态(排雷玩法 执行逻辑无变异分支;地形变异 Rule 3 的推论);读取方按 effect/trigger/placement 枚举路由(战斗结算 兑付段 / 呈现层 遮蔽回调),不按类型名分支 rule4_exemption: 定义表非进度成长表,键 = variant_id,进度语义承载于 unlock_level 列(数据配置 Rule 4 豁免,schema 注释承载) cross_field_validation: flat_damage ⇒ trigger=on_open ∧ placement=closed_only ∧ effect_value∈[1,9];hide_number ⇒ trigger=on_number_shown——VariationTable schema validate() 跨字段类别,违规加载期致命(2026-09-20 首批类型定稿批重立;旧 hide_numbers⇒safe_nonzero 闸随字段集退役) diff --git a/prototypes/dungeon-sweeper-vertical-slice/core/battle_orchestrator.gd b/prototypes/dungeon-sweeper-vertical-slice/core/battle_orchestrator.gd index 430eedb2..1e64059e 100644 --- a/prototypes/dungeon-sweeper-vertical-slice/core/battle_orchestrator.gd +++ b/prototypes/dungeon-sweeper-vertical-slice/core/battle_orchestrator.gd @@ -169,8 +169,10 @@ func _install_new_board(during_round := false) -> bool: # 池空 = 合法态,静默零布置(框架 P0 口径不变)。零特判:本段只写格子变异数据快照,不改扫雷规则本体。 # 候选格域 = 安全格 − 初始展开区(伤害型 placement=closed_only 的结构保障——布置发生在初始展开之后, # 已开格天然排除);雷格不吃变异(挖雷一层惩罚 + 变异伤害双层叠罚污染逐行归因,首版排除——provisional)。 -# 每图至多一种类型(候选池内均匀选一,混型布置归因复杂留待后续批);数量 = round(总格数×percent) + -# (关卡序号−1)×per_level_bonus;连通片生长(8 邻),单片 ≤ pack_max(2×2 / 1×4 / 1×3+1 等形)。 +# 每图至多一种类型(候选池内均匀选一,混型布置归因复杂留待后续批);数量 = round(候选池格数×percent) + +# (关卡序号−1)×per_level_bonus——基数为候选池而非总格数(2026-09-21 用户拍板基数修正批:初始展开 +# 占全板 56–67%,总格数基数使有效密度膨胀 4–6 倍、L1 小板极端全池覆盖;percent 语义 = 占可挖格比例, +# 关卡递增由 per_level_bonus 绝对格数承载);连通片生长(8 邻),单片 ≤ pack_max(2×2 / 1×4 / 1×3+1 等形)。 func _place_variants(board: BoardData) -> void: var pool: Array = db.variant_pool(int(encounter.level_index), String(board.board_type)) if pool.is_empty(): @@ -186,7 +188,7 @@ func _place_variants(board: BoardData) -> void: return var stream: RandomNumberGenerator = rng.open_stream("variant_place") # 一板恰一 scope(换图/刷新图各取号一次) var vrow: Dictionary = pool[stream.randi_range(0, pool.size() - 1)] - var total: int = int(round(float(board.width * board.height) * float(db.variation.percent_of_cells) / 100.0)) \ + var total: int = int(round(float(candidates.size()) * float(db.variation.percent_of_cells) / 100.0)) \ + (int(encounter.level_index) - 1) * int(db.variation.per_level_bonus) total = mini(total, candidates.size()) var placed := {} diff --git a/prototypes/dungeon-sweeper-vertical-slice/data/schemas/variation_table.gd b/prototypes/dungeon-sweeper-vertical-slice/data/schemas/variation_table.gd index 40cd0ef1..4a8cb5b5 100644 --- a/prototypes/dungeon-sweeper-vertical-slice/data/schemas/variation_table.gd +++ b/prototypes/dungeon-sweeper-vertical-slice/data/schemas/variation_table.gd @@ -12,8 +12,9 @@ class_name VariationTable extends Resource @export var rows: Array = [] # Array[Dictionary] -# 布置参数(表头字段;数量公式 = round(总格数 × percent_of_cells / 100) + (关卡序号 − 1) × per_level_bonus, -# 连通片生长、单片 ≤ pack_max——2026-09-19 用户拍板:图规模百分比 × 关卡递增,全连通、单片不超 4) +# 布置参数(表头字段;数量公式 = round(候选池格数 × percent_of_cells / 100) + (关卡序号 − 1) × per_level_bonus, +# 连通片生长、单片 ≤ pack_max——2026-09-19 用户拍板:图规模百分比 × 关卡递增,全连通、单片不超 4; +# 2026-09-21 用户拍板基数修正:百分比基数 = 候选池(安全格 − 初始展开区,即实际可挖格)而非总格数) @export var percent_of_cells: int = 5 @export var per_level_bonus: int = 2 @export var pack_max: int = 4 diff --git a/prototypes/dungeon-sweeper-vertical-slice/data/tables/variation.tres b/prototypes/dungeon-sweeper-vertical-slice/data/tables/variation.tres index 3be17880..eb989254 100644 --- a/prototypes/dungeon-sweeper-vertical-slice/data/tables/variation.tres +++ b/prototypes/dungeon-sweeper-vertical-slice/data/tables/variation.tres @@ -86,5 +86,10 @@ rows = [{ ; ; 第三关内容批(2026-09-20):伤害型关间递进 1(荆棘)→ 2(岩浆)→ 3(落石)+ 信息型矿尘; ; counter_items 恒空(反制归 Alpha 反制批);布量走既有公式 -; (5% + per_level_bonus × 2 = 9%——percent_of_cells 表头字段驱动,不加新配置)。 +; (5% + per_level_bonus × 2——percent_of_cells 表头字段驱动,不加新配置)。 ; 行值全 provisional 归 难度曲线与Boss。 +; +; 基数修正批(2026-09-21 用户拍板):数量公式百分比基数由总格数改为候选池格数 +; (安全格 − 初始展开区 = 实际可挖格)——总格数基数下初始展开占全板 56–67%, +; 有效密度膨胀 4–6 倍(L1 10×10 板实测 5%→30%,极端板全池覆盖);percent 语义 = +; 占可挖格比例,关卡递增由 per_level_bonus 绝对格数承载。表值不变归 调参批 重标。 diff --git a/prototypes/dungeon-sweeper-vertical-slice/smoke/smoke_all.gd b/prototypes/dungeon-sweeper-vertical-slice/smoke/smoke_all.gd index 8a331154..c4577eaf 100644 --- a/prototypes/dungeon-sweeper-vertical-slice/smoke/smoke_all.gd +++ b/prototypes/dungeon-sweeper-vertical-slice/smoke/smoke_all.gd @@ -850,10 +850,16 @@ func _smoke_variant_placement(L: int) -> void: if r0.has(c) or b.is_mine(c): domain_ok = false check(domain_ok, "L%d 变异格全在初始展开区外且不吃雷格(布置域结构保障——closed_only)" % L) - var expect_cap: int = int(round(float(b.width * b.height) * float(_db.variation.percent_of_cells) / 100.0)) \ + var cand_count := 0 + for c in b.safe_cells(): + if not r0.has(c): + cand_count += 1 + var expect_cap: int = int(round(float(cand_count) * float(_db.variation.percent_of_cells) / 100.0)) \ + (L - 1) * int(_db.variation.per_level_bonus) - check(vcells.size() <= expect_cap, "L%d 变异格数 %d ≤ 公式上限 %d(图规模百分比 + 关卡递增)" % [L, vcells.size(), expect_cap]) - check(vcells.size() > 0, "L%d 种子 42 板非零布置(候选池非空下应有遭遇面)" % L) + check(vcells.size() <= expect_cap, "L%d 变异格数 %d ≤ 公式上限 %d(可挖池百分比 + 关卡递增)" % [L, vcells.size(), expect_cap]) + # 数量公式量随候选池缩放(2026-09-21 基数修正批):L1 无关卡加成,极小池(<10 格)可 round 至 0—— + # 零布置为合法态(同池空口径);非零断言改为条件式,公式量>0 时才要求非零(L2/L3 关卡加成保底恒>0) + check(expect_cap == 0 or vcells.size() > 0, "L%d 公式量>0 时非零布置(极小池 round 至 0 = 合法零布置——2026-09-21 基数修正批)" % L) var pack_max: int = int(_db.variation.pack_max) var vset := {} for c in vcells: