Files
gplan-2/game/sim/defense_scan.gd

85 lines
3.5 KiB
GDScript
Raw Permalink 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
# 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