22 KiB
棋盘生成
一句话:棋盘怎么生成、怎么保证可推理可清图 状态:已定稿;现行为 v1.3
设计目的
棋盘生成是全项目扫雷图的唯一生产者:战斗结算每要一张新图,它就按关卡序号与节点深度对应的参数行,确定性造出一张可推理、可清图的雷图。它在生成时刻就作出质量承诺——玩家只会输给自己选的赌(比如终局只能猜的一格),不会拿到大面积无解的局;这是核心循环里"推理的确定性"卖点的生成端保障。同种子同参数必产同图,回放、测试、复盘都能精确复现——确定性既是卖点,也是调试工具。
系统范围
边界这样划:本系统管"图从哪来、生成时承诺什么质量"。图上的动作怎么执行归排雷玩法,什么时候换图归战斗结算编排,数值定多少归难度曲线与Boss(本系统只提供参数表给数值落点),变异内容是什么归地形变异(本系统不为变异做任何工作——变异格赋予在战斗初始化第 4 步执行,生成器产物恒零变异格)。本系统是个无状态的生产者:进参数与种子,出棋盘与指标,自己不留任何记忆。
负责:
| 负责 | 说明 |
|---|---|
| 四阶段确定性生成管线 | 读参数 → 布雷 → 生成-验证 → 产出上报;顺序冻结,不调换、不跳步(变异布置段已移出管线) |
| 棋盘生成参数表 | 全项目第一张按进度键(关卡序号 × 节点深度)回填的配置表;表结构归本系统定 |
| 可推理率度量与达标判定 | 生成时刻的质量承诺,含计算口径与定义版本号 |
| 出生区与反退化保证 | 出生 3×3 无雷、最小安全格数、开局白给板拒绝、清图可达性(变异不落出生区与展开域由布置段顺序保障) |
| 加载期参数校验 | 参数域、布雷数下限、可行性与成本闸校验;违例加载期致命 |
| 生成期指标集产出 | 实测可推理率、实际雷数等,供调参与下游对账 |
不负责:
| 不负责 | 归谁 |
|---|---|
| 挖掘、封印、连锁展开的执行 | 排雷玩法 |
| 换图时机与轮次编排 | 战斗结算(本系统纯被调用) |
| 难度数值定多少 | 难度曲线与Boss(调参所有权在对方) |
| 变异内容与解锁节奏 | 地形变异(布置执行位在其自身——战斗初始化第 4 步,不在本管线) |
| 奖励内容与图类型差异化插槽 | 地图战斗资源 |
| 界面呈现 | HUD 框架 |
| 配置表承载与读取机制 | 数据配置(本系统是该表的回填责任方) |
在核心循环中的位置
棋盘生成 ──(雷图 + 生成指标)──▶ 扫雷(排雷玩法 × 行动经济)──▶ 轮末结算(战斗结算)──▶ 换图请求 ──▶ 回到棋盘生成
本系统站在每场战斗"扫雷"一段的最上游:战斗结算发起换图请求,它交出图与指标,扫雷段在图上展开,清完或主动换掉再回来要下一张。它是纯被调用方,不主动发起任何事。
核心规则
四阶段管线:一次调用跑完四步,同种子必产同图
每次生成都是一次纯粹的函数调用——输入关卡序号、节点深度和随机种子,输出一张完整棋盘加一组生成期指标。调用按固定四步跑完,顺序冻结:
生成(关卡序号, 节点深度, 种子) → 棋盘 + 生成期指标集
① 参数解析 ─── 读对应参数行,生成开始时单次读取并快照
▼
② 布雷 ─────── 雷数 N = round(雷密度 × (宽×高 − 出生格数))(先定数;出生格数 = 出生区边长²,读表,出生区恒排除)
│ 在"全格 − 出生 3×3"范围均匀布雷
│ 开局免费展开域外扩一圈,圈内的雷移除(只减不增、不重投、无迭代)
▼
③ 生成-验证 ── 实测可推理率;不达标在同一张图的随机数配额内重试,至上限按出口分发
▼
④ 产出上报 ─── 交出棋盘 + 生成期指标集
生成期间的每一次随机取数——布雷、重试——都从本图专属的一条"棋盘生成随机流"按固定顺序取:一张图只开一条流、用到底,重试不开新流;流之外零随机,全局随机函数一律禁用。参数行开始时一次快照,配置表中途热重载不影响进行中的生成。管线本身无状态——这些合起来就是"同种子同参数必产同图"的根基。(变异布置不消费本流——其取数走专用 variant_place 流,归战斗结算 布置段。)
各阶段的失败都有明确语义,全部失败路径都不让玩家卡死(本节为纯流程规则,无计算;数值与校验式见后续各节):
| 阶段 | 失败情形 | 语义 |
|---|---|---|
| 参数解析 | 行缺失或域违例 | 加载期校验已拦,运行期不会失败 |
| 布雷 | 雷数为 0 | 不会发生(零雷板加载期已拒) |
| 生成-验证 | 重试耗尽 | 按三分支出图(见"生成重试与成本闸") |
| 产出 | —— | 无失败路径,交出棋盘与指标 |
出生区安全与反退化布雷:脚下无雷、废板不出厂
玩家开局站在棋盘上的 3×3 出生区,开局不花行动点就能看到一片区域——出生 3×3 加上从它出发经连锁展开(翻到八邻无雷的格时整片免费翻开的机制,玩家可见名"坍塌显形")免费带出的格,下文称开局免费展开域。本规则保证两件事:其一,脚下永远安全——出生区与开局免费展开域内恒无雷(变异亦然——变异格赋予在初始展开之后执行,天然不落已开区,见地形变异布置段);其二,流出的每张图都可正常游玩——零雷板、安全格寥寥的板、开局白给的板、带孤岛安全格的板,都在生成期被拦下或整张弃用。
结论:雷数先定数、再落位;零雷板与安全格不足的参数组合在加载期就被拒绝。
布雷数 N = round(mine_density × (board_width × board_height − 出生格数)) (出生格数 = 出生区边长²,读表;出生区恒排除)
下限校验:N ≥ 1(零雷板加载期拒绝)
计数可行:board_width × board_height − N ≥ min_safe_count(加载期校验)
产物断言:实际安全格数 ≥ min_safe_count;实际雷数 ≤ N(先布后删只减不增)
| 符号 | 含义 |
|---|---|
| mine_density | 雷密度参数,与图尺寸解耦 |
| board_width / board_height | 图尺寸参数 |
| min_safe_count | 最小安全格数下限参数——对冲"图上没几格安全、随便挖挖就清图领奖励"的刷奖励打法 |
| N | 该参数行每张图的目标雷数 |
| 反退化规则 | 内容 |
|---|---|
| 先布后删 | 先把 N 颗雷在"全格 − 出生 3×3"上布完,再把剃雷域内的雷移除——只减不增、不重投、无迭代,必然终止且可复现;实际雷数与 N 的差额随指标观测。剃雷域:「出生 3×3 ∪ 外扩 r 环」(切比雪夫距离 ≤1+r,r=shave_ring_radius 现行 1 → 5×5=25 格)——全域剃雷=开局免费展开巨大(10×10 板 R₀ 均值 68.6=板面 68.6%)的根因;现口径下开局免费展开=出生邻域剃雷诱发的自然连锁,均值降至板面约四成(10×10 实测 39.7) |
| 出生区安全 | 出生 3×3 与开局免费展开域内恒无雷;变异不落两域由布置段顺序保障(非本管线义务) |
| 开局白给板拒绝 | 开局免费展开域禁止覆盖全部安全格——等于即退化板,尝试弃用重试;运行期另有同义兜底不变式,归排雷玩法 |
| 清图可达性 | 每个安全格都必须能从出生区沿安全格八向连通走到;带孤岛安全格的板判非法,不进降级候选 |
| R₀≤cap 重掷闸 | 每次尝试出板后实测自然 R₀(开局免费展开格数),超过该行 r0_max_cap 即整板作废同流重试——合法性先于质量评分(同白给板先例);全部尝试超阈 → 既有三分出口接受最不坏+非法产物标记诚实降级,玩家永不卡死;闸触发次数随指标集 r0_cap_rejected 观测(占比过高=剃雷半径与闸配比失衡信号) |
清图可达性与可推理率是两道独立的闸:合法性先查、质量分后算——一张"分高但通不了"的图没有意义。另一条推理前提也由本系统保证:数字恒真,每个非危险格的数字恒等于它的八邻雷数,整局推理都建立在这句话上。
可推理率承诺:生成时就担保玩家算得对
可推理率(inferability)回答一个问题:这张图上有多少安全格,玩家不靠赌、纯凭逻辑就能挖开?它是整张图的"不靠赌占比":把开局免费展开、连锁展开、数字推导三种通道能确定挖开的安全格数,除以安全格总数。生成端承诺每张图实测占比不低于该行及格线——玩家可以输给自己选的赌,但不会拿到一张大面积无解的图。
结论:每张图生成时实测可推理率,实测值 ≥ 该行及格线;及格线取值域 [0.85, 1],域下限 0.85 是"不许纯猜局"的绝对锚(结构冻结——调整走文档修订,不是调参)。
可推理率(图) = 不靠赌能确定挖开的安全格数 ÷ 安全格总数
不靠赌揭示闭包:从开局免费展开域出发,交替应用两条规则直到不再新增——
① 连锁:翻到 0 格(八邻无雷的数字格)→ 其八邻安全格全部计入
② 推导:与已揭示区八向相邻的安全格,求解器凭可见数字能唯一断定其非雷 → 计入
| 口径 | 内容 |
|---|---|
| 与玩家信息同步 | 评分模拟只看玩家能看见的盘面:没开的格看不见,危险格位置不许偷看 |
| 三通道计入 | 免费展开、连锁、推导挖开的格都算"不靠赌";免费展开格同时计入分子与分母 |
| 次序无关 | 先连锁还是先推导,闭包结果相同——分数与玩家的操作顺序无关 |
| 版本防漂移 | 指标输出带定义版本号(当前 1);改推理定义 = 文档修订 + 黄金图向量重制,版本号随之跳变 |
推理规则域 solver_rules 冻结为 single_subset(单点规则加子集消减——经典扫雷式确定性推理:凭单个数字、以及两组数字的差能唯一断定的格)。它是可推理率定义的一部分,不是调参项;放宽或收紧它都等于改"算得对"的定义,须走文档修订。
生成重试与成本闸:重试有上限、降级必上报
一张图生成后先实测可推理率,不达标就在同一张图的随机数配额内重试——不开新图、不换种子。重试不是无限的:总取数规模受成本闸约束,且禁止拿真实耗时当逃生阀——否则同一颗种子在快慢机器上会产出不同的图,"同种子同图"就不成立了。
结论:重试次数与图尺寸联合受成本闸约束。
成本闸:max_gen_attempts × board_width × board_height ≤ 成本闸护栏常数 (结构护栏常数,见棋盘参数表字段定义;provisional 量级,正式值待实现期定)
| 出口 | 何时走 | 发生什么 |
|---|---|---|
| 达标即出 | 重试中出现合法且达标的图 | 出最早达标的那张,不追求全场最高分 |
| 接受最优 | 重试耗尽,有合法图但无一达标 | 出合法图中可推理率最高的一张(并列取最早)+ 强告警 + 降级标记 |
| 接受最不坏 | 重试耗尽且一张合法图都没有 | 按确定性劣度排序出最不坏的一张 + 最高级告警 + 非法产物标记 |
最后一条出口是诚实降级:玩家永不卡死——哪怕找不到合法板也照常出图;但绝不静默——非法产物标记随指标集上抛,由战斗结算编排、经 HUD 框架诚实告知玩家(提示、补偿还是回退,呈现细节归下游)。运行期安全网兜住体验,质量红线靠调参期批量断言守住:非法产物严格零容忍、低于及格线的板数严格为零——两层不许互相折算。
每次尝试先过合法性关——清图可达、安全格数达标、结构不变式全过——再谈质量分;非法尝试弃用重试。合法性闸在质量评分之前,质量分禁止掩盖功能残废。
图类型标签与第三轴预留:主题恒定、Boss 板有座位
每张图带一个图类型标签(board_type 字段;图类型即图的主题、题材,玩家侧显示名「地图类型」)。同关卡的所有图,主题静态恒定——不存在逐图重掷主题的接口,"不会上钓鱼的当"是结构保证而非文案。词表现行 v1.1:dungeon(地牢基线)/ underdark(幽暗地域)/ deep_underdark(灰矮人矿道方向),现行值见 board_gen.tres(L1 = dungeon,L2 = underdark,L3 = deep_underdark);域校验 = 词表成员检查(词表归棋盘参数表,扩词随内容批走修订)。这组标签是表现侧换色板与地图战斗资源图类型差异化插槽的数据源。本节为数据约定,无计算。
参数表的键是关卡序号 × 节点深度,难度沿这两条轴雕刻;精英与 Boss 修饰是预留的第三条轴。本系统不定任何修饰数值,只锁定落点约定——这也是关卡节点地图与难度曲线与Boss两份文档的输入:
| 约定 | 内容 |
|---|---|
| Boss 板 | 各关最深深度行即 Boss 行——关底 Boss 恒为该关最后节点 |
| 字段命名空间 | 参数表预留 elite_ / boss_ 前缀字段,语义归上述两文档定稿 |
| 改键退路 | 若未来节点形态使精英性无法由现有键唯一确定,走数据配置的改键通道修订 |
依赖与输出
本系统对外只有一个生成入口和一份指标集,自己不发起任何调用。下面的依赖清单同时是影响面清单:删改本系统的某个概念时,按行逐个通知。
| 方向 | 系统 | 接口要点 |
|---|---|---|
| 上游 | 数据配置 | 参数表承载、类型化读取与加载期校验通道;棋盘生成随机流的种子派生(每图开一次流) |
| 相邻 | 地形变异 | 相邻事实依赖:布置执行位在战斗初始化第 4 步(战斗结算 编排段),生成器产物恒零变异格;出生区/展开域"无变异"承诺由该顺序结构保障 |
| 下游 | 排雷玩法 | 棋盘产物消费方;开局免费展开由对方执行,展开域口径按双方登记的回验条款对齐 |
| 下游 | 战斗结算 | 换图调用方与指标对账方;零合法板的玩家侧诚实告知由其编排 |
| 下游 | 行动经济 | 单向事实依赖:P(安全)(挖掘目标格为安全格的概率)是对方挖掘风险不等式的概率锚,锚值由本系统供给——实测可推理率分布的低分位值,不是及格线参数 |
| 下游 | 难度曲线与Boss | 参数数值所有权方;只按表调参,禁反向调用生成 |
| 下游 | 关卡节点地图 | 第三轴 Boss 板落点约定的共同输入 |
| 下游 | 地图战斗资源 | board_type 作图类型上下文(行参数静态恒定) |
| 对外接口 | 形态 |
|---|---|
| 生成入口 | 生成(关卡序号, 节点深度, 种子) → 棋盘 + 生成期指标集;无状态纯函数 |
| 生成期指标集 | 实测可推理率(带定义版本号)、实际雷数与安全格数、重试次数、降级/非法产物标记 |
措辞登记(防口径混写):可推理率是整图级的"不靠赌占比",生成侧口径;P(安全) 是单格认知概率,决策侧口径——免赌集内 P(安全) 恒为 1,风险全部收缩到剩余盲猜集。本系统供给前者,不定义后者。
P0 最小闭环
- 战斗结算以(关卡序号,节点深度)调用生成,本系统开一条棋盘生成随机流。
- 读取并快照参数行(加载期校验已通过)。
- 先定数布雷、先布后删;出生区安全与反退化不变式全过。
- 实测可推理率,不达标在流内重试至上限,按三分支出图(变异布置不在本管线——装板后由战斗结算 布置段执行)。
- 交出棋盘 + 指标集:排雷玩法消费棋盘,战斗结算消费指标对账——循环闭合于下一次换图请求。
P1 / P2 后置
| 优先级 | 内容 | 后置原因 |
|---|---|---|
| P1 | 调参期批量断言工具全量交付(逐行数百样本;可推理率零违例、及格线下限、非法产物零容忍、难度方向 advisory 与分位报告) | 调参期离线工具域;冒烟只载缩样 |
| P1 | 与战斗结算的接线断言(图内重试不当作新流事件、对账消费实测分布) | 断言登记在对方验收清单 |
| P1 | 与排雷玩法的展开域回验集成 | 回验两臂登记在对方文档,集成随对方排期 |
| P2 | 推理域扩展(solver_rules 启用其他规则集或新增信息源) | 改可推理率定义 = 文档修订,MVP 冻结 |
| P2 | 生成异步化与成本闸正式值定稿 | 实现期决策,随性能预算批 |
| P2 | — |
调参表
参数行以(关卡序号 × 节点深度)为键;已锁数值以 data/tables/board_gen.tres 为准。第一关、第二关的深度 0 参考行只是表结构自洽性证明,全部 provisional——曲线数值归难度曲线与Boss的调参所有权。
| 参数 | 域 | 现行值 | 说明 |
|---|---|---|---|
| board_width / board_height | int [8, 64] | 两档结构,现行面值见 board_gen.tres(provisional 参考行) | 图尺寸 |
| mine_density | float (0, 0.5] | 现行值见 board_gen.tres | 雷密度,与尺寸解耦 |
| inferability_target | float [0.85, 1] | 现行值见 board_gen.tres | 可推理率及格线;域下限 0.85 绝对锚 |
| solver_rules | enum {single, single_subset} | single_subset(冻结,非调参) | 推理规则域 |
| min_safe_count | int [1, 999] | 现行值见 board_gen.tres | 最小安全格数下限 |
| max_gen_attempts | int [1, 32] | 域 [1, 32],现行按行取值见 board_gen.tres | 生成-验证重试上限;受成本闸联合约束 |
| board_type | String,词表 {dungeon, underdark, deep_underdark} | 现行值见 board_gen.tres(词表 v1.1) | 图类型标签(玩家侧「地图类型」);域校验 = 词表成员检查 |
| shave_ring_radius | int [0, 2] | 现行 1(board_gen.tres 全行) | 先布后删剃雷半径:剃雷域=距出生中心切比雪夫距离 ≤1+r 的格(r=1 → 5×5=25 格;r=0 即只剃出生 3×3 本身=无环剃雷)。调参项非结构冻结 |
| r0_max_cap | int [出生格数, 板格数一半](护栏,违例加载期致命;出生格数=出生区边长自乘,读出生区行) | 现行按板形:10×10=45 / 12×12=43 / 13×13=51 / 14×14=59(board_gen.tres) | 自然 R₀(开局免费展开格数)上限闸=合法性门;超阈整板重掷、耗尽走三分出口。板面锚现行值 = 45/43/51/59(10×10 行经用户裁上调——r=1 自然均值 39>30 结构性倒挂;其余行维持 30% 锚) |
| 出生区边长 | int [3, 5],奇数(中心对称,side = 2r+1);现行值读 board_gen.tres 表头 | 表头全局单值(非逐行) | 玩家出生区为以出生中心对称的 side×side 方区,区内恒无雷;布雷域基与 r0_max_cap 护栏下限均由它导出(格数 = side²)。入表后格数零字面量 |
结构冻结(非调参项):键结构与每关深度 0 锚行、四阶段顺序(变异布置段已移出管线)、solver_rules、可推理率的合法信息源枚举、及格线域下限 0.85、成本闸常数(结构护栏,登记在案,调整走文档修订)、先布后删语义。
验收标准
- 确定性复现:同参数行同种子生成两遍,格状态与指标集逐位相同;换种子产物不全同。
- 出生区安全:出生 3×3 与开局免费展开域内零雷(零变异由布置段顺序保障——生成器产物恒零变异格)。
- 数字恒真:每个非危险格的数字恒等于其八邻雷数。
- 布雷纪律:N ≥ 1、实际雷数 ≤ N、实际安全格数 ≥ min_safe_count。
- 无开局白给板:开局免费展开域 ≠ 全部安全格,违例尝试弃用重试。
- 可清图:每个安全格都能从出生区沿安全格八向连通到达;合法性闸先于质量评分。
- 及格线:每张图实测可推理率 ≥ 该行及格线;任何行及格线 ≥ 0.85。
- 重试有界:实际重试次数落在 [1, max_gen_attempts];同一次生成内的重试不开新随机流。
- 成本闸:max_gen_attempts × 宽 × 高超过成本闸护栏常数(结构护栏常数,见棋盘参数表字段定义)的行加载期被拒;同种子同参数在任意机器上出图逐位一致。
- 降级诚实:零合法板照常出图,必带非法产物标记与最高级告警;进程不死锁,玩家界面得到诚实告知。
- 加载期校验:布雷数下限、计数可行性、标签非空等违例组合加载期致命。
- 黄金图回归:手工核验小板集的可推理率输出与登记整数对逐位相等(整数对比对,禁浮点容差);换生成参数(推理定义、信息源、定义版本号)必须重制向量并入版本库。
- R₀≤cap 闸:每张出图自然 R₀ ≤ 该行 r0_max_cap(合法板),或带非法产物标记(接受最不坏·诚实降级);闸触发次数入指标集 r0_cap_rejected。
- 剃雷域参数化:剃雷域=出生中心切比雪夫 ≤1+shave_ring_radius 的方域,出图 ring_removed ≤ 域内候选危险格数 (3+2r)²−9。
- 表实一致:配置表字段与棋盘参数表字段定义一致。