工程(bp对拍载体退役): 删 game/tests/bp_baseline_dump.gd+.uid 边车——迭代39批bp1断点对拍的一次性dump载体,断点片段化后七时点对拍已收口进审计报告(292dumps×28键零漂移),件核全仓零引用;实现报告§五退役清单件,随批后收尾扫尾批执行(用户令2026-10-28'一并全部处理掉');属文档面收尾的代码面尾巴,按车道铁律走worktree小批
This commit is contained in:
1 parent
fa7747e501
commit
d26b5e68ee
2 files changed
-178
No files matched your search
@@ -1,177 +0,0 @@
|
|||||||
# VERTICAL SLICE - NOT FOR PRODUCTION
|
|
||||||
# 断点基线对拍采集脚本(迭代 39 拆件批 T0 载体,批末随中间产物退役——非长期测试件)。
|
|
||||||
# 固定种子集驱动完整冒险至各停点(节点入口/选路/三选一在途/兑付后待推进),逐停点
|
|
||||||
# dump 断点 Dictionary 全键值(直调 _bp_parts 写侧取值面)→ JSON 落盘,供改前/改后
|
|
||||||
# 逐键逐位比对(bp1:同种子改前改后 27 键逐位一致)。
|
|
||||||
# 运行:BP_DUMP_OUT=<json 路径> godot --headless --path . --script res://tests/bp_baseline_dump.gd
|
|
||||||
# 缺省输出 user://bp_baseline_dump.json。
|
|
||||||
# 驱动与 sim/level_autoplay 同构(完美档战斗驱动 + 确定性选件/选路)——零随机流自开,
|
|
||||||
# 同种子逐位可复放;dump 时点由驱动循环状态判定,确定性时点。
|
|
||||||
extends SceneTree
|
|
||||||
|
|
||||||
const AdventureRunnerScript := preload("res://core/adventure_runner.gd")
|
|
||||||
const Autoplay := preload("res://sim/level_autoplay.gd")
|
|
||||||
|
|
||||||
const SEEDS: Array[int] = [1234, 4321, 910042, 20260101, 20260102, 20260103]
|
|
||||||
const PARAMS := {
|
|
||||||
"hero_override": {},
|
|
||||||
"treasure_unlocked": {"wide_scout_band": true},
|
|
||||||
"attunement": ["sky_eye", "incense_stick", "refresh_practice"], # 充能账非零形态+刷新存量加仓(attunement_charges/refresh_stock 键覆盖)
|
|
||||||
"attune_refresh_y": 2, # Y 池非零形态(attune_refresh_y 键覆盖)
|
|
||||||
"shop_mode": "pool", # 共享池货架面(shop_shelf/shop_visit_buys/shop_purchased 覆盖)
|
|
||||||
"relics_seed": ["twin_pick"], # 特性持有集+adventure_counters 非空形态(adv_twin_digs 计数器用户)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func _init() -> void:
|
|
||||||
var db = load("res://core/config_db.gd").new()
|
|
||||||
if not db.load_tables("res://data/tables", false):
|
|
||||||
print("[bp_baseline_dump] FAIL — 数值表加载失败")
|
|
||||||
quit(1)
|
|
||||||
return
|
|
||||||
var runs: Array = []
|
|
||||||
for seed_val in SEEDS:
|
|
||||||
var run := _drive_dump_run(db, int(seed_val))
|
|
||||||
runs.append({"seed": int(seed_val), "result": String(run["result"]), "dumps": run["dumps"]})
|
|
||||||
print("[bp_baseline_dump] seed=%d result=%s dumps=%d" % [int(seed_val), String(run["result"]), (run["dumps"] as Array).size()])
|
|
||||||
var out_path := OS.get_environment("BP_DUMP_OUT")
|
|
||||||
if out_path.is_empty():
|
|
||||||
out_path = "user://bp_baseline_dump.json"
|
|
||||||
var f := FileAccess.open(out_path, FileAccess.WRITE)
|
|
||||||
if f == null:
|
|
||||||
print("[bp_baseline_dump] FAIL — 输出文件打不开: %s" % out_path)
|
|
||||||
quit(1)
|
|
||||||
return
|
|
||||||
f.store_string(JSON.stringify({"generated_by": "bp_baseline_dump", "seeds": SEEDS, "runs": runs}, " "))
|
|
||||||
f.close()
|
|
||||||
print("[bp_baseline_dump] DONE — %s" % out_path)
|
|
||||||
quit(0)
|
|
||||||
|
|
||||||
|
|
||||||
# 单局驱动+停点 dump(返回 {result, dumps};dumps 元素 = {seq, tag, level_index, node_id, bp})
|
|
||||||
func _drive_dump_run(db, seed_val: int) -> Dictionary:
|
|
||||||
var rng = load("res://core/rng_service.gd").new()
|
|
||||||
rng.set_master_seed(seed_val)
|
|
||||||
var adr = AdventureRunnerScript.new(db, rng)
|
|
||||||
var ctx := {"result": "", "dumps": [] as Array, "seq": 0, "adr": adr, "db": db}
|
|
||||||
# 信号直连(拆件批 T3——转发族退役):runner 信号在 level_started 重取点重连(同关守卫恰一次);
|
|
||||||
# 停点件信号面订 stop()(每冒险一次)
|
|
||||||
adr.level_started.connect(_on_dump_level_started.bind(ctx))
|
|
||||||
adr.stop().curio_resolved.connect(_on_curio_resolved.bind(ctx))
|
|
||||||
if not adr.start_adventure(seed_val, PARAMS):
|
|
||||||
ctx["result"] = "start_failed"
|
|
||||||
return ctx
|
|
||||||
var guard := 2000
|
|
||||||
while String(ctx["result"]) == "" and guard > 0:
|
|
||||||
guard -= 1
|
|
||||||
if not (adr.stop()._node_pending as Dictionary).is_empty():
|
|
||||||
_dump(ctx, "node_curio_pending")
|
|
||||||
var ncands: Array = (adr.stop()._node_pending.get("candidates", []) as Array)
|
|
||||||
var npick: Dictionary = Autoplay._pick_token(ncands, "off")
|
|
||||||
if not adr.stop().apply_node_curio(String(npick.get("kind", "")), String(npick.get("tier", "")), String(npick.get("feat_id", ""))):
|
|
||||||
ctx["result"] = "node_advance_failed"
|
|
||||||
continue
|
|
||||||
if not (adr.stop()._pending as Dictionary).is_empty():
|
|
||||||
_dump(ctx, "curio_pending")
|
|
||||||
var cands: Array = (adr.stop()._pending.get("candidates", []) as Array)
|
|
||||||
var pick: Dictionary = Autoplay._pick_token(cands, "off")
|
|
||||||
if not adr.stop().pick_curio(String(pick.get("kind", "")), String(pick.get("tier", "")), String(pick.get("feat_id", ""))):
|
|
||||||
ctx["result"] = "advance_failed"
|
|
||||||
continue
|
|
||||||
if bool(adr._pending_next_level):
|
|
||||||
_dump(ctx, "resolved_wait_continue")
|
|
||||||
if not adr.continue_to_next_level():
|
|
||||||
ctx["result"] = "advance_failed"
|
|
||||||
continue
|
|
||||||
var runner = adr.runner()
|
|
||||||
if runner == null:
|
|
||||||
break # 冒险已收束或停点态未覆盖(防御)
|
|
||||||
if runner.awaiting_choice():
|
|
||||||
_dump(ctx, "route_choice")
|
|
||||||
var ids: Array = runner.next_candidate_ids()
|
|
||||||
if ids.is_empty():
|
|
||||||
ctx["result"] = "no_candidates"
|
|
||||||
break
|
|
||||||
if not runner.pick_next_node(int(ids[0])):
|
|
||||||
ctx["result"] = "route_failed"
|
|
||||||
continue
|
|
||||||
var settlement = runner.current_battle()
|
|
||||||
if settlement != null and String(settlement.battle_result) == "":
|
|
||||||
_drive_battle(ctx, runner, settlement)
|
|
||||||
continue
|
|
||||||
# 收束态分派:结算受理后(state=idle/settling)按 summary 定局;其余态无战无停点无选路 = 死循环防护
|
|
||||||
if String(ctx["result"]) == "":
|
|
||||||
var sum: Dictionary = adr.summary if adr.summary != null else {}
|
|
||||||
if not sum.is_empty():
|
|
||||||
ctx["result"] = String(sum.get("result", "settled"))
|
|
||||||
break
|
|
||||||
if String(adr.state) in ["idle", "settling"]:
|
|
||||||
ctx["result"] = "settled_no_summary"
|
|
||||||
break
|
|
||||||
if guard == 1:
|
|
||||||
ctx["result"] = "timeout"
|
|
||||||
return ctx
|
|
||||||
|
|
||||||
|
|
||||||
# 完美档战斗驱动(复用 sim 同款决策——上界策略;st 键集满足 _autoplay_battle 消费面)
|
|
||||||
func _drive_battle(ctx: Dictionary, runner, settlement) -> void:
|
|
||||||
var st := {"result": "", "rounds": 0, "refreshes": 0, "seal_placed": 0,
|
|
||||||
"policy": "perfect", "adv": false}
|
|
||||||
Autoplay._autoplay_battle(runner, settlement, st, null)
|
|
||||||
|
|
||||||
|
|
||||||
# 停点 dump(写侧取值面直调;_runner 为 null 的停点态节点域字段按缺省落档——与真机同构)
|
|
||||||
static func _dump(ctx: Dictionary, tag: String) -> void:
|
|
||||||
var adr = ctx["adr"]
|
|
||||||
var bp: Dictionary = adr._bp_parts()
|
|
||||||
var runner = adr.runner()
|
|
||||||
var dumps: Array = ctx["dumps"]
|
|
||||||
ctx["seq"] = int(ctx["seq"]) + 1
|
|
||||||
dumps.append({
|
|
||||||
"seq": int(ctx["seq"]),
|
|
||||||
"tag": String(tag),
|
|
||||||
"level_index": int(adr.level_index),
|
|
||||||
"node_id": int(runner.current_node_id()) if runner != null else -1,
|
|
||||||
"bp": bp,
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
# 每关开始(dump 直连面):重取 runner 重连 node_entered(同关守卫——level_started 每关恰一次发射)
|
|
||||||
static func _on_dump_level_started(_li: int, _dn: String, ctx: Dictionary) -> void:
|
|
||||||
var adr = ctx["adr"]
|
|
||||||
if String(ctx.get("wired_level", "")) == "%s|%d" % [str(adr.master_seed), int(adr.level_index)]:
|
|
||||||
return
|
|
||||||
ctx["wired_level"] = "%s|%d" % [str(adr.master_seed), int(adr.level_index)]
|
|
||||||
var r = adr.runner()
|
|
||||||
if r == null:
|
|
||||||
return
|
|
||||||
r.node_entered.connect(_on_node_entered.bind(ctx))
|
|
||||||
|
|
||||||
|
|
||||||
# 节点入口驱动(信号时点):入口 dump 覆盖节点域字段形态;rest/shop 直通继续,reward 呈现三选一
|
|
||||||
static func _on_node_entered(node: Dictionary, _info: Dictionary, ctx: Dictionary) -> void:
|
|
||||||
var adr = ctx["adr"]
|
|
||||||
var runner = adr.runner()
|
|
||||||
if runner == null:
|
|
||||||
return
|
|
||||||
var t := String(node.get("type", ""))
|
|
||||||
_dump(ctx, "node_" + t)
|
|
||||||
if t == "rest" or t == "shop":
|
|
||||||
runner.continue_after_node()
|
|
||||||
elif t == "reward":
|
|
||||||
var ndraw: Dictionary = adr.stop().node_curio_candidates()
|
|
||||||
var ncands: Array = ndraw.get("candidates", []) as Array
|
|
||||||
if ncands.is_empty():
|
|
||||||
runner.continue_after_node() # 牌库空合法态直通(池耗即枯竭)
|
|
||||||
else:
|
|
||||||
adr.stop().present_node_curio(ncands)
|
|
||||||
|
|
||||||
|
|
||||||
# 节点三选一兑付完成回图(context=reward_node → continue_after_node 回选路)
|
|
||||||
static func _on_curio_resolved(result: Dictionary, ctx: Dictionary) -> void:
|
|
||||||
if String(result.get("context", "")) != "reward_node":
|
|
||||||
return
|
|
||||||
var adr = ctx["adr"]
|
|
||||||
var runner = adr.runner()
|
|
||||||
if runner != null and not runner.continue_after_node():
|
|
||||||
ctx["result"] = "node_advance_failed"
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
uid://byleq6f7m8qm6
|
|
||||||
Reference in new issue
Block a user