Files
gplan-2/game/core/board_data.gd
T

118 lines
4.3 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# VERTICAL SLICE - NOT FOR PRODUCTION
# Validation Question: 玩家能否无指导在一场完整战斗中经历「开战→挖掘规划→轮末结算逐行兑现→胜/负」并逐行归因(P2)
# Date: 2026-09-10
# 棋盘产物数据契约(排雷玩法消费;生成后不可变——排雷玩法持快照即持活引用,生成器不再触碰)。
# 实现 GDD:design/archive/gdd-2026-09-14/a1-board-generation.md(系统 ID A1·棋盘生成——registry 追溯锚,命名规范见 CLAUDE.md)
class_name BoardData
extends RefCounted
# 出生 3×3 区格数(2026-10-02 修复批 T2 魔法数结构化——W×H−9 布雷域基的双落点收口单点:
# 棋盘生成 _attempt/_finalize 与 BoardGenTable 布雷数下限校验共用;与 spawn_cells() 的 3×3 几何同源)
const SPAWN_AREA_CELLS := 9
var width: int = 0
var height: int = 0
var spawn_center := Vector2i.ZERO
var mines := {} # Vector2i → true
var digits := {} # Vector2i → int(安全格恒有值;数字恒真 = 8 邻雷数)
var variants := {} # Vector2i → Array[String](生成期快照,抗表重载)
var board_variants: Array[String] = [] # 板级变异 id 集(scope=global 整图作用域——全局作用域变异批 2026-10-04:
# 战斗编排装板决议写入,随图生灭同 variants;普通图恒空)
var board_type := "" # 图类型标签(词表 v1.0:dungeon/underdark;玩家侧显示名「地图类型」)
var level_index: int = 1
var node_depth: int = 0
var metrics := {} # 生成期指标集(键清单单点定义在 board_generator._finalize)
var illegal_product := false # 非法产物标记(接受最不坏出口——零合法板诚实降级)
var degraded_product := false # 降级产物标记(接受最优出口——有合法板但无一达标;与 illegal_product 对称)
func in_bounds(c: Vector2i) -> bool:
return c.x >= 0 and c.y >= 0 and c.x < width and c.y < height
# 行主序排序键(2026-10-02 修复批——排雷玩法 旗判定批与 地图战斗资源 资格规范化两处手抄收口单点):
# y×1000+x 字典序 = 行主序;板宽域 [8,64] 远小于 1000,x 不跨行、键值不碰撞。
static func row_major_key(c: Vector2i) -> int:
return c.y * 1000 + c.x
func is_mine(c: Vector2i) -> bool:
return mines.has(c)
func is_safe(c: Vector2i) -> bool:
return in_bounds(c) and not mines.has(c)
func digit_of(c: Vector2i) -> int:
return digits.get(c, -1)
func variant_ids(c: Vector2i) -> Array:
return variants.get(c, [])
# 板级变异只读出口(scope=global 行集——呈现快照/断言消费;空 = 无全局型合法态)
func board_variant_ids() -> Array[String]:
return board_variants
# 中和格变异(迭代 12 T6 净化工兵——伤害型地形格变普通格;🔴 R4 甲仅限伤害型的过滤在调用方)
func clear_variants(c: Vector2i) -> void:
variants.erase(c)
func neighbors8(c: Vector2i) -> Array:
var out: Array[Vector2i] = []
for dy in range(-1, 2):
for dx in range(-1, 2):
if dx == 0 and dy == 0:
continue
var n := Vector2i(c.x + dx, c.y + dy)
if in_bounds(n):
out.append(n)
return out # 行主序(规范序的邻接枚举基序)
func spawn_cells() -> Array:
var out: Array[Vector2i] = []
for dy in range(-1, 2):
for dx in range(-1, 2):
var c := Vector2i(spawn_center.x + dx, spawn_center.y + dy)
if in_bounds(c):
out.append(c)
return out
func all_cells() -> Array:
var out: Array[Vector2i] = []
for y in height:
for x in width:
out.append(Vector2i(x, y))
return out
func safe_cells() -> Array:
var out: Array[Vector2i] = []
for c in all_cells():
if is_safe(c):
out.append(c)
return out
# R₀ = 出生 3×3 ∪ (出生 3×3 经 0 格的 flood 闭包)——与 排雷玩法 F3 逐字同构(棋盘生成 F1 求解器初始态)。
func compute_r0() -> Array:
var b3 := spawn_cells()
var r0 := {}
for c in b3:
r0[c] = true
var queue: Array = b3.duplicate()
while not queue.is_empty():
var c: Vector2i = queue.pop_front()
if is_safe(c) and digit_of(c) == 0: # 变异死分支退役(2026-09-18 用户拍板删——与 排雷玩法 展开实现口径归一;变异定稿批按正式语义重接)
for n in neighbors8(c):
if is_safe(n) and not r0.has(n):
r0[n] = true
queue.append(n)
return r0.keys()