diff --git a/prototypes/dungeon-sweeper-vertical-slice/core/battle_orchestrator.gd b/prototypes/dungeon-sweeper-vertical-slice/core/battle_orchestrator.gd index 1d862054..466fef49 100644 --- a/prototypes/dungeon-sweeper-vertical-slice/core/battle_orchestrator.gd +++ b/prototypes/dungeon-sweeper-vertical-slice/core/battle_orchestrator.gd @@ -193,28 +193,42 @@ func _place_variants(board: BoardData) -> void: var pack_size: int = mini(total - placed.size(), stream.randi_range(2, int(db.variation.pack_max))) var free: Array = [] for c in candidates: - if not placed.has(c): - free.append(c) + # 新片种子/生长格禁与其他已布片 8 邻贴接——否则两片粘连成一个超 pack_max 的连通分量 + # (R3 随机流下实测暴露:独立生长的相邻片合流击穿单片上限断言) + if placed.has(c) or _adjacent_to_packs(board, placed, c): + continue + free.append(c) if free.is_empty(): break var seed_c: Vector2i = free[stream.randi_range(0, free.size() - 1)] placed[seed_c] = true var pack: Array = [seed_c] + var pack_set := {seed_c: true} while pack.size() < pack_size: var fringe: Array = [] for c in pack: for n in board.neighbors8(c): - if candidates.has(n) and not placed.has(n) and not fringe.has(n): + if candidates.has(n) and not placed.has(n) and not fringe.has(n) \ + and not _adjacent_to_packs(board, placed, n, pack_set): fringe.append(n) if fringe.is_empty(): break # 生长域耗尽——该片就地收束(数量不足总目标为合法态,候选域碎片化时触发) var nxt: Vector2i = fringe[stream.randi_range(0, fringe.size() - 1)] placed[nxt] = true + pack_set[nxt] = true pack.append(nxt) for c in placed.keys(): board.variants[c] = [String(vrow.variant_id)] +# 候选格是否与其他已布片(own_pack 之外的 placed 格)8 邻贴接——片间隔离保证连通分量 = 单片 ≤ pack_max +func _adjacent_to_packs(board: BoardData, placed: Dictionary, c: Vector2i, own_pack: Dictionary = {}) -> bool: + for m in board.neighbors8(c): + if placed.has(m) and not own_pack.has(m): + return true + return false + + # ---- 事件缓冲(轮 facts 收集;结算触发 = Waiting 相位编排点,不依赖到达序)---- func _on_cell_revealed(evt: Dictionary) -> void: