# VERTICAL SLICE - NOT FOR PRODUCTION # playtest-2026-09-12 Q1 复核——"安全格减伤是否过量导致满血打完 Boss" # 口径:逐结算轮统计 ac_up 授予层数(AC10→11→12)与该轮敌方实伤, # 分割"高 AC 轮"(叠满 = AC12,期望减免 28.75%)与基线轮(AC10,期望减免 21.25%)的承伤读数。 # 运行:Godot_console.exe --headless --path . --script res://sim/defense_scan.gd -- [N] [seed0] extends SceneTree func _initialize() -> void: var args := OS.get_cmdline_user_args() var n := 8 if args.size() >= 1 and args[0].is_valid_int(): n = maxi(2, int(args[0])) var seed0 := 42 if args.size() >= 2 and args[1].is_valid_int(): seed0 = int(args[1]) var db = load("res://core/config_db.gd").new() if not db.load_tables("res://data/tables", false): print("表加载失败") quit(1) return var autoplay = load("res://sim/level_autoplay.gd") print("=== 盾牌加护叠层扫描(AC 口径):第一关 · N=%d · 种子 %d+%d ===" % [n, seed0, n]) print("%-6s %-6s %-8s %-12s %-14s %-14s" % ["seed", "轮数", "战斗轮", "满层轮(AC12)", "满层轮承伤", "非满层轮承伤"]) var full_rounds := 0 var open_rounds := 0 var full_dmg := 0 var open_dmg := 0 var stack_total := 0 var combat_rounds := 0 for i in range(n): var st = autoplay.run_level(db, seed0 + i, 1, 0, 0, true) # 逐轮聚合(按战斗分段——round_index 跨战斗重置,直接用轮号会串桶): # effect 行 effect_id=ac_up 计盾牌加护层;enemy_action damage 计承伤 var ac_by_round := {} var dmg_by_round := {} var battle_seq := 0 var last_round := 0 for row in st.rows: var r: int = int(row.get("round_index", 0)) if r < last_round: battle_seq += 1 # 轮号回卷 = 新战斗 last_round = r var key := battle_seq * 1000 + r if String(row.get("type", "")) == "effect" and String(row.get("effect_id", "")) == "ac_up" \ and String(row.get("source_class", "")) == "safe_cell": ac_by_round[key] = int(ac_by_round.get(key, 0)) + 1 elif String(row.get("type", "")) == "damage" and String(row.get("source_class", "")) == "enemy_action": dmg_by_round[key] = int(dmg_by_round.get(key, 0)) + int(row.get("value", 0)) for k in ac_by_round: combat_rounds += 1 stack_total += int(ac_by_round[k]) var d: int = int(dmg_by_round.get(k, 0)) if int(ac_by_round[k]) >= 2: full_rounds += 1 full_dmg += d else: open_rounds += 1 open_dmg += d print("%-6d %-6d %-8d %-12d %-14s %-14s" % [seed0 + i, st.rounds, ac_by_round.size(), _full_count(ac_by_round), str(dmg_in(dmg_by_round, ac_by_round, 2)), str(dmg_in(dmg_by_round, ac_by_round, 1))]) if combat_rounds > 0: print("---- 战斗轮 %d:满层轮 %d(%.0f%%,均值 %.2f 层/轮)· 满层轮承伤合计 %d(AC12——期望减免 28.75%%)· 非满层轮承伤合计 %d(均 %.1f/轮,AC10/11)" % [ combat_rounds, full_rounds, 100.0 * float(full_rounds) / float(combat_rounds), float(stack_total) / float(combat_rounds), full_dmg, open_dmg, float(open_dmg) / float(maxi(1, open_rounds))]) quit(0) func _full_count(ac_by_round: Dictionary) -> int: var c := 0 for r in ac_by_round: if int(ac_by_round[r]) >= 2: c += 1 return c func dmg_in(dmg_by_round: Dictionary, ac_by_round: Dictionary, mode: int) -> int: # mode=2 满层轮承伤 / mode=1 非满层轮承伤 var t := 0 for r in ac_by_round: var full: bool = int(ac_by_round[r]) >= 2 if (mode == 2 and full) or (mode == 1 and not full): t += int(dmg_by_round.get(r, 0)) return t