82 lines
4.1 KiB
GDScript
82 lines
4.1 KiB
GDScript
# VERTICAL SLICE - NOT FOR PRODUCTION
|
||
# Date: 2026-09-21
|
||
# 冒险全流程期望扫描(三关连探零加成基线批量试玩——run_adventure 的蒙特卡洛批量工具,
|
||
# 补 level_monte_carlo 只测单关的空白面):固定 atk+0%/hp+0%(零天赋格加成,关间大奖励
|
||
# 按冒险结构现行设计自动兑付),逐局独立种子,输出:
|
||
# ① 每局一行 RUNSUM JSON(stdout,局级摘要:策略/种子/result/summary/战斗轮数/承伤/踩雷/
|
||
# 刷新/行进序列/逐战上限序列——后续统计分析的取数面);
|
||
# ② 全量操作日志 = playtest_logger 共享会话 JSONL(与真人试玩同合规口径,每策略一批一文件,
|
||
# run 行携带种子/策略切分局次,落 user://logs/)。
|
||
# 本工具只采集与落盘数据,不做统计判读(通关率/败因分布归分析会话)。
|
||
# 运行:Godot_console.exe --headless --path . --script res://smoke/adventure_monte_carlo.gd -- [N] [seed0] [normal|perfect|both] [route min|max]
|
||
extends SceneTree
|
||
|
||
|
||
var _run_cursor := 0 # 全局局序号(seed = seed0 + cursor,逐局独立消费一次)
|
||
|
||
|
||
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(5, int(args[0]))
|
||
var seed0 := 71000
|
||
if args.size() >= 2 and args[1].is_valid_int():
|
||
seed0 = int(args[1])
|
||
var policy_arg := "both"
|
||
if args.size() >= 3 and args[2] in ["normal", "perfect", "both"]:
|
||
policy_arg = args[2]
|
||
var policies: Array = ["normal"]
|
||
if policy_arg == "perfect":
|
||
policies = ["perfect"]
|
||
elif policy_arg == "both":
|
||
policies = ["normal", "perfect"]
|
||
var route := "min"
|
||
if args.size() >= 4 and args[3] in ["min", "max"]:
|
||
route = args[3]
|
||
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://smoke/level_autoplay.gd")
|
||
var t0 := Time.get_ticks_msec()
|
||
print("=== 冒险全流程扫描:三关连探 · N=%d/策略 · 种子 %d 起逐局独立 · 策略=%s · atk+0%%/hp+0%% 零加成 · route=%s ===" % [n, seed0, policy_arg, route])
|
||
for policy in policies:
|
||
# 每策略一个共享日志会话(全量 JSONL 体量随局数增长,分文件便于定位)
|
||
var logger = load("res://presentation/playtest_logger.gd").new()
|
||
logger.ap_per_round = int(db.action_economy.ap_per_round)
|
||
var log_path: String = logger.start_session(seed0)
|
||
var tally := {}
|
||
for i in range(n):
|
||
var seed_val := seed0 + _run_cursor
|
||
_run_cursor += 1
|
||
var st = autoplay.run_adventure(db, seed_val, 0, 0, false, logger, policy, route)
|
||
var sum: Dictionary = st["summary"]
|
||
var rec := {
|
||
"policy": policy, "seed": seed_val, "atk_pct": 0, "hp_pct": 0, "route": route,
|
||
"result": st["result"],
|
||
"cleared": bool(sum.get("cleared", false)),
|
||
"levels_cleared": int(sum.get("levels_cleared", -1)),
|
||
"stopped_at": int(sum.get("stopped_at", -1)),
|
||
"keystone_total": int(sum.get("keystone_total", -1)),
|
||
"battles": int(st["battles"]), "rounds": int(st["rounds"]),
|
||
"hero_dmg": int(st["hero_dmg"]), "mine_hits": int(st["mine_hits"]),
|
||
"refreshes": int(st["refreshes"]), "choices": int(st["choices"]),
|
||
"visited_count": (st["visited_ids"] as Array).size(),
|
||
"encounter_max_hp_seq": st["encounter_max_hp_seq"],
|
||
"reward_events": st["reward_events"],
|
||
"shop_gp_seq": st["shop_gp_seq"],
|
||
"level_templates": st.get("level_templates", []),
|
||
"wallet_count": (st["wallet_events"] as Array).size(),
|
||
}
|
||
var rs := String(sum.get("result", ""))
|
||
tally[rs] = int(tally.get(rs, 0)) + 1
|
||
print("RUNSUM " + JSON.stringify(rec))
|
||
if (i + 1) % 20 == 0:
|
||
print("... %s 进度 %d/%d(耗时 %.1f 秒)" % [policy, i + 1, n, float(Time.get_ticks_msec() - t0) / 1000.0])
|
||
logger.close_session()
|
||
print("BATCH %s N=%d 终局计数=%s 日志=%s" % [policy, n, JSON.stringify(tally), log_path])
|
||
print("(口径注:零加成 = atk/hp 天赋格百分比均 0;关间大奖励(HP 上限提升+回满)按冒险结构设计自动兑付,未额外剥离 · 全程日志见 user://logs/ · 总耗时 %.1f 秒)" % [float(Time.get_ticks_msec() - t0) / 1000.0])
|
||
quit(0)
|