按 code-conventions §1.4.1 第三轮定稿执行:core 22+schemas 18+presentation 根 14+views 28,全部头注 #→##、删日期/变更叙事/GDD 与架构反向链接/字段与域清单/机制描述,保留职责摘要+真实使用约束(防事故禁令/单一入口/信号契约每信号一行)。main.gd 31→5 行、save_manager 45→5 行、adventure_runner 37→5 行为最大单件。子代理分模块执行(波一 core+schemas、波二 presentation+views,并发≤2)。验收=tools/verify_comment_only_change.py 逐字节校验(82 文件头注区外逐行一致=零行为变更)+audit_file_headers 全绿;纯注释批免冒烟(先例 5843270)
63 lines
2.9 KiB
GDScript
63 lines
2.9 KiB
GDScript
## VERTICAL SLICE - NOT FOR PRODUCTION
|
|
## 调整板批量模拟控制器:逐次驱动关卡自动策略(与 headless 扫描同口径),进度/报告经面板 setter 注入。
|
|
## 零核心写——表基线复位由组合根在移交前完成,加成施加只走自动策略内部 runner.set_hero_override 单路径。
|
|
## presentation 不 preload smoke:驱动实例由调用方注入(须供与 level_autoplay 同款 run_level 签名),缺省 null=运行时 load 兜底。
|
|
extends RefCounted
|
|
|
|
const SEED_BASE := 4200 # 模拟种子基(与历史实现同源——同种子可回放)
|
|
const PlaytestLogger := preload("res://presentation/playtest_logger.gd") # 试玩日志(同层依赖——运行时 load 收敛为 preload 常量)
|
|
|
|
var db
|
|
var panel # 调试浮窗 setter 面:atk_pct/hp_pct/set_sim_running/set_sim_progress/set_sim_report
|
|
var _base_hp := 0 # 报告中的"基础 HP"口径注记值
|
|
var _driver = null # 关卡自动策略驱动(调用方注入;null = 旧行为运行时 load 兜底)
|
|
|
|
|
|
func _init(db_ref, panel_ref, base_hp: int, driver = null) -> void:
|
|
db = db_ref
|
|
panel = panel_ref
|
|
_base_hp = base_hp
|
|
_driver = driver
|
|
|
|
|
|
# 驱动解析:注入优先;缺省回退运行时 load(旧行为——编译期反向依赖已解除,运行时口径与拆分前逐位一致)
|
|
func _autoplay():
|
|
if _driver != null:
|
|
return _driver
|
|
return load("res://smoke/level_autoplay.gd") # 与 headless 扫描同口径的自动策略(P3 兜底路径)
|
|
|
|
|
|
func run(n: int) -> void:
|
|
# 共享日志会话(2026-09-12 用户要求:模拟运行与真人试玩同日志合规——操作/轮次/战斗/通关全量 JSONL;
|
|
# 一文件多局,run 行携带种子切分局次)
|
|
var logger = PlaytestLogger.new()
|
|
logger.ap_per_round = int(db.action_economy.ap_per_round)
|
|
var log_path: String = logger.start_session(SEED_BASE)
|
|
print("[tune_sim] 模拟日志: %s" % log_path)
|
|
panel.set_sim_running(true)
|
|
panel.set_sim_progress("模拟中:0/%d …" % n)
|
|
var wins := 0
|
|
var dmg_all: Array[float] = []
|
|
var hp_left_win: Array[float] = []
|
|
var hp_boss: Array[float] = []
|
|
var rounds_all: Array[int] = []
|
|
var death_nodes := {}
|
|
var autoplay = _autoplay()
|
|
for i in range(n):
|
|
var st = autoplay.run_level(db, SEED_BASE + i, 1, panel.atk_pct(), panel.hp_pct(), false, logger)
|
|
dmg_all.append(st.hero_dmg)
|
|
rounds_all.append(st.rounds)
|
|
if st.result == "victory":
|
|
wins += 1
|
|
hp_left_win.append(st.hp_left)
|
|
hp_boss.append(st.hp_at_boss)
|
|
elif st.result == "defeat":
|
|
var key := "%d.%s" % [st.defeat_node_index, st.defeat_node_type]
|
|
death_nodes[key] = int(death_nodes.get(key, 0)) + 1
|
|
panel.set_sim_progress("模拟中:%d/%d …" % [i + 1, n])
|
|
await panel.get_tree().process_frame
|
|
logger.close_session()
|
|
panel.set_sim_report(HudPresenter.tune_sim_report(n, panel.atk_pct(), panel.hp_pct(),
|
|
wins, dmg_all, hp_left_win, hp_boss, rounds_all, death_nodes, _base_hp))
|
|
panel.set_sim_running(false)
|