# VERTICAL SLICE - NOT FOR PRODUCTION # 棋盘口径校准(分析会话取数工具——冒险零加成完成度分母实证): # 逐 board_gen 行真实生成 N 板,统计 实际雷数/安全格数/R₀ 初始展开占比—— # 生成期「先布后删+可推理率重试」使实际雷数远低于表口径 round(d×(W×H−9)), # 日志侧只有清图板可反推 safe_total(未清图深度无样本),本工具给全网格精确分母。 # 运行:Godot_console.exe --headless --path . --script res://sim/calibrate_boards.gd -- [N] # 输出:stdout CSV 行 level,depth,w,h,n,mines_mean,mines_med,safe_mean,safe_med,r0_mean,inf_mean extends SceneTree class FakeDB: var row: Dictionary func resolve_board_gen(_L: int, _D: int) -> Dictionary: return row func status_effect_row(_id: String) -> Dictionary: return {} func _initialize() -> void: var args := OS.get_cmdline_user_args() var n := 200 if args.size() >= 1 and args[0].is_valid_int(): n = maxi(10, int(args[0])) var db = load("res://core/config_db.gd").new() if not db.load_tables("res://data/tables", false): print("表加载失败") quit(1) return var gen = load("res://core/board_generator.gd").new() print("level,depth,w,h,n,mines_mean,mines_med,safe_mean,safe_med,r0_mean,r0_sd,r0_p90,r0_max,inf_mean,cap_rej_mean") for row in db.board_gen.rows: var rd := { "level_index": int(row.level_index), "node_depth": int(row.node_depth), "board_width": int(row.board_width), "board_height": int(row.board_height), "mine_density": float(row.mine_density), "inferability_target": float(row.inferability_target), "solver_rules": String(row.solver_rules), "min_safe_count": int(row.min_safe_count), "max_gen_attempts": int(row.max_gen_attempts), "board_type": String(row.board_type), # 初始展开收窄两参数透传(.get 缺省与生成器防御口径一致) "shave_ring_radius": int(row.get("shave_ring_radius", 1)), "r0_max_cap": int(row.get("r0_max_cap", 0)), } var fdb := FakeDB.new() fdb.row = rd var mines: Array = [] var safes: Array = [] var r0s: Array = [] var infs: Array = [] var cap_rejs: Array = [] for i in range(n): var rg := RandomNumberGenerator.new() rg.seed = 900000 + i var b = gen.generate(int(row.level_index), int(row.node_depth), rg, fdb) if b == null: continue mines.append(b.mines.size()) safes.append(b.safe_cells().size()) r0s.append(int(b.metrics.r0_count)) infs.append(float(b.metrics.inferability)) cap_rejs.append(int(b.metrics.get("r0_cap_rejected", 0))) if mines.is_empty(): printerr("L%d d%d 生成全部失败" % [int(row.level_index), int(row.node_depth)]) continue print("%d,%d,%d,%d,%d,%.1f,%d,%.1f,%d,%.1f,%.2f,%d,%d,%.3f,%.2f" % [ int(row.level_index), int(row.node_depth), int(row.board_width), int(row.board_height), mines.size(), _mean(mines), _med(mines), _mean(safes), _med(safes), _mean(r0s), _sd(r0s), _p90(r0s), _max(r0s), _mean(infs), _mean(cap_rejs)]) quit(0) func _mean(a: Array) -> float: var t := 0.0 for v in a: t += float(v) return t / float(a.size()) func _sd(a: Array) -> float: var m := _mean(a) var t := 0.0 for v in a: t += (float(v) - m) * (float(v) - m) return sqrt(t / float(a.size())) func _p90(a: Array) -> int: var b := a.duplicate() b.sort() return int(b[mini(a.size() - 1, int(ceil(a.size() * 0.9)) - 1)]) func _max(a: Array) -> int: var b := a.duplicate() b.sort() return int(b[b.size() - 1]) func _med(a: Array) -> int: var b := a.duplicate() b.sort() return int(b[b.size() / 2])