519 lines
25 KiB
GDScript
519 lines
25 KiB
GDScript
extends SceneTree
|
|
|
|
const Adapter = preload("res://campaign/fg4_adapter.gd")
|
|
const RG03Suite = preload("res://tests/fg4/five_profile_simulation_test.gd")
|
|
const Fixture = preload("res://tests/fg4/contract1_fixture.gd")
|
|
const RG04Contract1Battle = preload("res://fg4/rg04_contract1_battle_service.gd")
|
|
const RG04Contract2Battle = preload("res://fg4/rg04_contract2_battle_service.gd")
|
|
const SaveV11 = preload("res://fg4/save_v11_service.gd")
|
|
|
|
const PROFILE_EXTENSIONS := [
|
|
{
|
|
"id": "normal",
|
|
"contract1_risks": [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
|
|
"contract2_risks": [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0],
|
|
"boss1_plan": "steer_action_count",
|
|
"boss2_plan": "safe_rule_seed",
|
|
},
|
|
{
|
|
"id": "active",
|
|
"contract1_risks": [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0],
|
|
"contract2_risks": [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
|
|
"boss1_plan": "interrupt_pointer",
|
|
"boss2_plan": "reorder_and_interrupt",
|
|
},
|
|
{
|
|
"id": "efficient",
|
|
"contract1_risks": [0, 0, 1, 0, 2, 0, 0, 0, 1, 0, 2, 0],
|
|
"contract2_risks": [0, 1, 0, 2, 0, 0, 0, 1, 0, 2, 0, 0],
|
|
"boss1_plan": "steer_action_count",
|
|
"boss2_plan": "reorder_and_interrupt",
|
|
},
|
|
{
|
|
"id": "adversarial",
|
|
"contract1_risks": [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],
|
|
"contract2_risks": [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2],
|
|
"boss1_plan": "interrupt_pointer",
|
|
"boss2_plan": "safe_rule_seed",
|
|
},
|
|
{
|
|
"id": "returning",
|
|
"contract1_risks": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
"contract2_risks": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
|
"boss1_plan": "steer_action_count",
|
|
"boss2_plan": "safe_rule_seed",
|
|
},
|
|
]
|
|
|
|
var failures: Array[String] = []
|
|
|
|
|
|
func _initialize() -> void:
|
|
call_deferred("run_test")
|
|
|
|
|
|
func run_test() -> void:
|
|
var rg03_suite = RG03Suite.new()
|
|
var results: Array[Dictionary] = []
|
|
for index in range(PROFILE_EXTENSIONS.size()):
|
|
var rg03_profile: Dictionary = RG03Suite.PROFILES[index]
|
|
var extension: Dictionary = PROFILE_EXTENSIONS[index]
|
|
expect(String(rg03_profile.id) == String(extension.id), "profile order stays source-bound")
|
|
var rg03_result: Dictionary = rg03_suite.simulate_profile(rg03_profile)
|
|
if bool(rg03_result.get("failed", true)):
|
|
results.append(rg03_result)
|
|
continue
|
|
results.append(simulate_rg04(rg03_result, rg03_profile, extension))
|
|
rg03_suite.free()
|
|
verify_artifact_counterfactuals()
|
|
verify_results(results)
|
|
if failures.is_empty():
|
|
var total_decisions := 0
|
|
var longest_gap := 0.0
|
|
var recoveries := 0
|
|
var reloads := 0
|
|
for result in results:
|
|
total_decisions += int(result.decision_count)
|
|
longest_gap = maxf(longest_gap, float(result.max_gap))
|
|
recoveries += int(result.recoveries)
|
|
reloads += int(result.reloads)
|
|
print("ABG_FG4_MIDPOINT_FIVE_PROFILE_OK profiles=normal,active,efficient,adversarial,returning core_decisions=%d per_profile=107 longest_gap=%.1f ordinary_rounds=48 bosses=4 records=6 rg03_records=2 rg04_records=2 recoveries=%d reloads=%d policy_signatures=5 inherited_artifacts=3 rg04_artifact_reversals=24 boss_artifact_reversals=4 offline_rewards=0 resurrection=0 terminal=RG-05" % [total_decisions, longest_gap, recoveries, reloads])
|
|
quit(0)
|
|
else:
|
|
for failure in failures:
|
|
push_error(failure)
|
|
quit(1)
|
|
|
|
|
|
func simulate_rg04(rg03_result: Dictionary, rg03_profile: Dictionary, extension: Dictionary) -> Dictionary:
|
|
var adapter := Adapter.new()
|
|
var configured := adapter.configure(Dictionary(rg03_result.terminal_snapshot).duplicate(true))
|
|
if not bool(configured.get("ok", false)):
|
|
return failed_result(String(extension.id), "rg03_terminal_configure")
|
|
var state := {
|
|
"adapter": adapter,
|
|
"labels": Array(rg03_result.labels).duplicate(),
|
|
"timestamps": Array(rg03_result.timestamps).duplicate(),
|
|
"recovery_labels": Array(rg03_result.recovery_labels).duplicate(),
|
|
"recovery_timestamps": Array(rg03_result.recovery_timestamps).duplicate(),
|
|
"reload_timestamps": Array(rg03_result.reload_timestamps).duplicate(),
|
|
"route_risks": Array(rg03_result.route_risks).duplicate(),
|
|
"route_ids": Array(rg03_result.route_ids).duplicate(),
|
|
"plan_ids": Array(rg03_result.plan_ids).duplicate(),
|
|
"boss_plans": Array(rg03_result.boss_plans).duplicate(),
|
|
"clock": float(rg03_result.total_seconds),
|
|
"automatic_seconds": float(rg03_result.automatic_seconds),
|
|
"recoveries": int(rg03_result.recoveries),
|
|
"rg04_recoveries": 0,
|
|
"reloads": int(rg03_result.reloads),
|
|
"offline_zero": bool(rg03_result.offline_zero),
|
|
"fallen_ids": Array(rg03_result.fallen_ids).duplicate(),
|
|
"secondary_counts": [
|
|
int(rg03_result.contract1_secondary_choices),
|
|
int(rg03_result.contract2_secondary_choices),
|
|
0,
|
|
0,
|
|
],
|
|
"pressure_families": {},
|
|
"clause_kinds": {},
|
|
"redaction_seen": false,
|
|
}
|
|
var decision_seconds := float(rg03_profile.decision_seconds)
|
|
record_decision(state, "rg04_region_activation", decision_seconds)
|
|
var activated: Dictionary = state.adapter.continue_result()
|
|
if not bool(activated.get("ok", false)) or String(activated.view.phase) != "rg04_market":
|
|
return failed_result(String(extension.id), "rg04_activation")
|
|
if String(extension.id) == "returning" and not reload_state(state):
|
|
return failed_result(String(extension.id), "rg04_activation_reload")
|
|
|
|
var first_contract := run_routes(
|
|
state,
|
|
String(extension.id),
|
|
"r4c1",
|
|
Array(extension.contract1_risks),
|
|
RG04Contract1Battle,
|
|
decision_seconds
|
|
)
|
|
if not bool(first_contract.get("ok", false)):
|
|
return failed_result(String(extension.id), String(first_contract.get("code", "rg04_contract1")))
|
|
|
|
record_decision(state, "r4_boss1_plan_%s" % String(extension.boss1_plan), decision_seconds)
|
|
state.boss_plans.append(String(extension.boss1_plan))
|
|
var boss1 := run_victory(state.adapter, String(extension.boss1_plan))
|
|
if not bool(boss1.get("ok", false)):
|
|
return failed_result(String(extension.id), "rg04_boss1")
|
|
capture_archive_events(boss1, state)
|
|
state.automatic_seconds = float(state.automatic_seconds) + battle_seconds(boss1)
|
|
state.clock = float(state.clock) + battle_seconds(boss1) + 1.0
|
|
var boss1_settled: Dictionary = state.adapter.settle_terminal()
|
|
if not bool(boss1_settled.get("ok", false)) or String(boss1_settled.view.mode) != "contract_record":
|
|
return failed_result(String(extension.id), "rg04_boss1_settle")
|
|
record_decision(state, "rg04_record1_commit", decision_seconds)
|
|
var record1: Dictionary = state.adapter.continue_result()
|
|
if not bool(record1.get("ok", false)) or String(record1.view.phase) != "rg04_contract2_handoff":
|
|
return failed_result(String(extension.id), "rg04_record1")
|
|
record_decision(state, "rg04_contract2_handoff", decision_seconds)
|
|
var handoff: Dictionary = state.adapter.continue_result()
|
|
if not bool(handoff.get("ok", false)) or String(handoff.view.contract_id) != "CTR-R4-02":
|
|
return failed_result(String(extension.id), "rg04_contract2_handoff")
|
|
if String(extension.id) == "returning" and not reload_state(state):
|
|
return failed_result(String(extension.id), "rg04_handoff_reload")
|
|
|
|
var second_contract := run_routes(
|
|
state,
|
|
String(extension.id),
|
|
"r4c2",
|
|
Array(extension.contract2_risks),
|
|
RG04Contract2Battle,
|
|
decision_seconds
|
|
)
|
|
if not bool(second_contract.get("ok", false)):
|
|
return failed_result(String(extension.id), String(second_contract.get("code", "rg04_contract2")))
|
|
|
|
record_decision(state, "r4_boss2_plan_%s" % String(extension.boss2_plan), decision_seconds)
|
|
state.boss_plans.append(String(extension.boss2_plan))
|
|
var boss2 := run_victory(state.adapter, String(extension.boss2_plan))
|
|
if not bool(boss2.get("ok", false)):
|
|
return failed_result(String(extension.id), "rg04_boss2")
|
|
capture_archive_events(boss2, state)
|
|
state.automatic_seconds = float(state.automatic_seconds) + battle_seconds(boss2)
|
|
state.clock = float(state.clock) + battle_seconds(boss2) + 1.0
|
|
var boss2_settled: Dictionary = state.adapter.settle_terminal()
|
|
if not bool(boss2_settled.get("ok", false)) or String(boss2_settled.view.mode) != "region_record":
|
|
return failed_result(String(extension.id), "rg04_boss2_settle")
|
|
record_decision(state, "rg04_record2_commit", decision_seconds)
|
|
var closed: Dictionary = state.adapter.continue_result()
|
|
if not bool(closed.get("ok", false)) or String(closed.view.phase) != "rg04_region_closed":
|
|
return failed_result(String(extension.id), "rg04_region_close")
|
|
if String(extension.id) == "returning" and not reload_state(state):
|
|
return failed_result(String(extension.id), "rg04_terminal_reload")
|
|
|
|
var view: Dictionary = state.adapter.view_state()
|
|
var final_snapshot: Dictionary = state.adapter.snapshot()
|
|
var result := {
|
|
"id": String(extension.id),
|
|
"failed": false,
|
|
"artifact": String(rg03_result.artifact),
|
|
"boss_plans": state.boss_plans,
|
|
"route_risks": state.route_risks,
|
|
"route_ids": state.route_ids,
|
|
"plan_ids": state.plan_ids,
|
|
"secondary_counts": state.secondary_counts,
|
|
"labels": state.labels,
|
|
"timestamps": state.timestamps,
|
|
"decision_count": state.timestamps.size(),
|
|
"first_decision": float(state.timestamps[0]),
|
|
"max_gap": maximum_gap(state.timestamps),
|
|
"total_seconds": float(state.clock),
|
|
"automatic_seconds": float(state.automatic_seconds),
|
|
"recoveries": int(state.recoveries),
|
|
"rg04_recoveries": int(state.rg04_recoveries),
|
|
"recovery_labels": state.recovery_labels,
|
|
"recovery_timestamps": state.recovery_timestamps,
|
|
"fallen_ids": state.fallen_ids,
|
|
"reloads": int(state.reloads),
|
|
"reload_timestamps": state.reload_timestamps,
|
|
"offline_zero": bool(state.offline_zero),
|
|
"rg04_pressure_families": sorted_keys(state.pressure_families),
|
|
"clause_kinds": sorted_keys(state.clause_kinds),
|
|
"redaction_seen": bool(state.redaction_seen),
|
|
"records": int(view.records_count),
|
|
"region_records": int(view.region_records_count),
|
|
"unlocked_rg05": view.unlocked_region_ids.count("RG-05"),
|
|
"phase": String(view.phase),
|
|
"cleared_rounds": int(view.cleared_rounds),
|
|
"route_history_count": final_snapshot.current_run.route_history.size(),
|
|
"company_size": view.company.size(),
|
|
"coin": int(view.coin),
|
|
}
|
|
print("FG4_MIDPOINT_PROFILE_RESULT profile=%s artifact=%s risks=%s bosses=%s decisions=%s recovery=%s reloads=%s first=%.1f max_gap=%.1f total=%.1f company=%d coin=%d records=%d rg04_records=%d rg05=%d" % [result.id, result.artifact, result.route_risks, result.boss_plans, format_timestamps(result.labels, result.timestamps), format_timestamps(result.recovery_labels, result.recovery_timestamps), result.reload_timestamps, result.first_decision, result.max_gap, result.total_seconds, result.company_size, result.coin, result.records, result.region_records, result.unlocked_rg05])
|
|
return result
|
|
|
|
|
|
func run_routes(
|
|
state: Dictionary,
|
|
profile_id: String,
|
|
contract_key: String,
|
|
risks: Array,
|
|
battle_script,
|
|
decision_seconds: float
|
|
) -> Dictionary:
|
|
for offset in range(12):
|
|
var market_index := offset + 1
|
|
var risk := int(risks[offset])
|
|
var route := route_for_risk(state.adapter.view_state().routes, risk)
|
|
if route.is_empty():
|
|
return {"ok": false, "code": "%s_route_%d" % [contract_key, market_index]}
|
|
record_decision(state, "%s_m%d_route_r%d" % [contract_key, market_index, risk], decision_seconds)
|
|
state.route_risks.append(risk)
|
|
state.route_ids.append(String(route.route_id))
|
|
var prepared: Dictionary = state.adapter.prepare_route(String(route.offer_id))
|
|
if not bool(prepared.get("ok", false)):
|
|
return {"ok": false, "code": "%s_prepare_%d" % [contract_key, market_index]}
|
|
|
|
if profile_id == "normal" and contract_key == "r4c1" and market_index == 1:
|
|
record_recovery(state, "r4c1_wrong_archive_response", decision_seconds)
|
|
var wrong_plan := first_wrong_plan(battle_script, market_index)
|
|
var wrong_started: Dictionary = state.adapter.start_plan(wrong_plan)
|
|
var wrong_terminal: Dictionary = state.adapter.run_battle_to_terminal()
|
|
if not bool(wrong_started.get("ok", false)) or not bool(wrong_terminal.get("ok", false)) or String(wrong_terminal.view.battle.outcome) != "defeat":
|
|
return {"ok": false, "code": "rg04_recovery_defeat"}
|
|
state.automatic_seconds = float(state.automatic_seconds) + battle_seconds(wrong_terminal)
|
|
state.clock = float(state.clock) + battle_seconds(wrong_terminal) + 1.0
|
|
state.fallen_ids.append_array(Array(wrong_terminal.view.battle.fallen_recruit_ids))
|
|
var failed_settlement: Dictionary = state.adapter.settle_terminal()
|
|
if not bool(failed_settlement.get("ok", false)) or String(failed_settlement.view.mode) != "recovery":
|
|
return {"ok": false, "code": "rg04_recovery_settle"}
|
|
record_recovery(state, "r4c1_accept_permanent_loss", decision_seconds)
|
|
var recovered: Dictionary = state.adapter.recover()
|
|
if not bool(recovered.get("ok", false)) or String(recovered.view.mode) != "market":
|
|
return {"ok": false, "code": "rg04_recovery_commit"}
|
|
state.recoveries = int(state.recoveries) + 1
|
|
state.rg04_recoveries = int(state.rg04_recoveries) + 1
|
|
record_recovery(state, "r4c1_retry_same_route", decision_seconds)
|
|
route = route_for_risk(state.adapter.view_state().routes, risk)
|
|
prepared = state.adapter.prepare_route(String(route.offer_id))
|
|
if not bool(prepared.get("ok", false)):
|
|
return {"ok": false, "code": "rg04_recovery_retry"}
|
|
|
|
var prefer_secondary := should_prefer_secondary(profile_id, contract_key, market_index)
|
|
var plan_id := choose_route_plan(battle_script, state.adapter.snapshot(), market_index, prefer_secondary)
|
|
if plan_id == String(battle_script.SECONDARY_PLAN[market_index]):
|
|
var counter_index := 2 if contract_key == "r4c1" else 3
|
|
state.secondary_counts[counter_index] = int(state.secondary_counts[counter_index]) + 1
|
|
record_decision(state, "%s_m%d_plan_%s" % [contract_key, market_index, plan_id], decision_seconds)
|
|
state.plan_ids.append(plan_id)
|
|
var terminal := run_victory(state.adapter, plan_id)
|
|
if not bool(terminal.get("ok", false)):
|
|
return {"ok": false, "code": "%s_battle_%d" % [contract_key, market_index]}
|
|
capture_archive_events(terminal, state)
|
|
state.automatic_seconds = float(state.automatic_seconds) + battle_seconds(terminal)
|
|
state.clock = float(state.clock) + battle_seconds(terminal) + 1.0
|
|
if not bool(state.adapter.settle_terminal().get("ok", false)):
|
|
return {"ok": false, "code": "%s_settle_%d" % [contract_key, market_index]}
|
|
if profile_id == "returning" and market_index in [3, 6, 9, 12] and not reload_state(state):
|
|
return {"ok": false, "code": "%s_reload_%d" % [contract_key, market_index]}
|
|
return {"ok": true}
|
|
|
|
|
|
func run_victory(adapter, plan_id: String) -> Dictionary:
|
|
var started: Dictionary = adapter.start_plan(plan_id)
|
|
if not bool(started.get("ok", false)):
|
|
return {"ok": false, "code": String(started.get("code", "start_failed"))}
|
|
var terminal: Dictionary = adapter.run_battle_to_terminal()
|
|
if not bool(terminal.get("ok", false)) or String(terminal.view.battle.outcome) != "victory":
|
|
return {"ok": false, "code": "victory_required", "terminal": terminal}
|
|
return terminal
|
|
|
|
|
|
func choose_route_plan(battle_script, snapshot: Dictionary, market_index: int, prefer_secondary: bool) -> String:
|
|
var primary := String(battle_script.PRIMARY_PLAN[market_index])
|
|
if not prefer_secondary:
|
|
return primary
|
|
var secondary := String(battle_script.SECONDARY_PLAN[market_index])
|
|
var probe: Dictionary = battle_script.new(snapshot).run_to_terminal(secondary)
|
|
return secondary if bool(probe.get("ok", false)) and String(probe.snapshot.outcome) == "victory" else primary
|
|
|
|
|
|
func should_prefer_secondary(profile_id: String, contract_key: String, market_index: int) -> bool:
|
|
if profile_id == "active":
|
|
return market_index % 2 == (0 if contract_key == "r4c1" else 1)
|
|
if profile_id == "efficient":
|
|
return market_index % 2 == (1 if contract_key == "r4c1" else 0)
|
|
if profile_id == "returning":
|
|
return market_index % 4 == 0
|
|
return false
|
|
|
|
|
|
func reload_state(state: Dictionary) -> bool:
|
|
var sequence := 1000 + int(state.reloads)
|
|
var encoded := SaveV11.new().encode_snapshot(state.adapter.snapshot(), sequence)
|
|
if not bool(encoded.get("ok", false)):
|
|
return false
|
|
var decoded := SaveV11.new().decode_text(String(encoded.text), sequence)
|
|
if not bool(decoded.get("ok", false)) or decoded.snapshot != state.adapter.snapshot():
|
|
return false
|
|
var replacement := Adapter.new()
|
|
var configured := replacement.configure(decoded.snapshot)
|
|
if not bool(configured.get("ok", false)):
|
|
return false
|
|
state.adapter = replacement
|
|
state.offline_zero = bool(state.offline_zero) and decoded.offline_delta == SaveV11.OFFLINE_ZERO
|
|
state.reloads = int(state.reloads) + 1
|
|
state.clock = float(state.clock) + 1.5
|
|
state.reload_timestamps.append(float(state.clock))
|
|
return true
|
|
|
|
|
|
func capture_archive_events(terminal: Dictionary, state: Dictionary) -> void:
|
|
for event_value in terminal.get("events", []):
|
|
var event: Dictionary = event_value
|
|
var kind := String(event.get("kind", ""))
|
|
var detail: Dictionary = event.get("detail", {})
|
|
if kind == "archive_clause_disclosed":
|
|
state.clause_kinds[String(detail.get("kind", ""))] = true
|
|
elif kind in ["action_copy_resolved", "target_redirect_resolved", "cleanse_trap_resolved", "clause_evaluation_resolved"]:
|
|
state.pressure_families[String(detail.get("pressure_family", ""))] = true
|
|
elif kind in ["redaction_source_disclosed", "target_clause_omitted", "replay_order_disclosed"]:
|
|
state.redaction_seen = true
|
|
|
|
|
|
func verify_artifact_counterfactuals() -> void:
|
|
var reversals := 0
|
|
for battle_script in [RG04Contract1Battle, RG04Contract2Battle]:
|
|
for market_index in range(1, 13):
|
|
var primary := String(battle_script.PRIMARY_PLAN[market_index])
|
|
var secondary := String(battle_script.SECONDARY_PLAN[market_index])
|
|
var odd_primary: int = int(battle_script.route_plan_score(market_index, 1, primary, "AR-023", 0, 1.0))
|
|
var odd_secondary: int = int(battle_script.route_plan_score(market_index, 1, secondary, "AR-023", 0, 1.0))
|
|
var even_primary: int = int(battle_script.route_plan_score(market_index, 1, primary, "AR-024", 0, 1.0))
|
|
var even_secondary: int = int(battle_script.route_plan_score(market_index, 1, secondary, "AR-024", 0, 1.0))
|
|
expect(odd_primary > odd_secondary and even_secondary > even_primary, "RG-04 Market %d flips Artifact response" % market_index)
|
|
if odd_primary > odd_secondary and even_secondary > even_primary:
|
|
reversals += 1
|
|
expect(reversals == 24, "all 24 RG-04 Markets have Artifact counterfactuals")
|
|
|
|
var c1_base := Fixture.new().rg04_boss_muster_snapshot()
|
|
expect(boss_outcome(c1_base, "steer_action_count", "AR-024") == "victory", "Walking Index steering survives AR-024")
|
|
expect(boss_outcome(c1_base, "interrupt_pointer", "AR-024") == "defeat", "AR-024 reverses Walking Index interrupt")
|
|
expect(boss_outcome(c1_base, "interrupt_pointer", "AR-023") == "victory", "Walking Index interrupt wins outside AR-024")
|
|
var c2_base := Fixture.new().rg04_contract2_boss_muster_snapshot()
|
|
expect(boss_outcome(c2_base, "safe_rule_seed", "AR-024") == "defeat", "AR-024 reverses Redaction Hart seed")
|
|
expect(boss_outcome(c2_base, "reorder_and_interrupt", "AR-024") == "victory", "AR-024 favors Redaction Hart reorder")
|
|
expect(boss_outcome(c2_base, "safe_rule_seed", "AR-023") == "victory", "AR-023 favors Redaction Hart seed")
|
|
expect(boss_outcome(c2_base, "reorder_and_interrupt", "AR-023") == "defeat", "AR-023 reverses Redaction Hart reorder")
|
|
|
|
|
|
func boss_outcome(source: Dictionary, plan_id: String, artifact_id: String) -> String:
|
|
var snapshot_value: Dictionary = source.duplicate(true)
|
|
snapshot_value.current_run.active_artifact_ids = [artifact_id]
|
|
var adapter := Adapter.new()
|
|
if not bool(adapter.configure(snapshot_value).get("ok", false)):
|
|
return "invalid"
|
|
if not bool(adapter.start_plan(plan_id).get("ok", false)):
|
|
return "invalid"
|
|
var terminal: Dictionary = adapter.run_battle_to_terminal()
|
|
return String(terminal.get("view", {}).get("battle", {}).get("outcome", "invalid"))
|
|
|
|
|
|
func verify_results(results: Array[Dictionary]) -> void:
|
|
expect(results.size() == 5, "all five combined profiles return results")
|
|
var signatures := {}
|
|
var artifacts := {}
|
|
var bosses_by_slot: Array[Dictionary] = [{}, {}, {}, {}]
|
|
var risks_by_slot: Array[Dictionary] = []
|
|
var secondary_by_contract := [0, 0, 0, 0]
|
|
var total_rg04_recoveries := 0
|
|
for _index in range(48):
|
|
risks_by_slot.append({})
|
|
for result in results:
|
|
expect(not bool(result.get("failed", true)), "%s completes both Regions" % String(result.get("id", "unknown")))
|
|
if bool(result.get("failed", true)):
|
|
continue
|
|
expect(int(result.decision_count) == 107, "%s records exact combined decisions" % result.id)
|
|
expect(float(result.first_decision) <= 20.0 and float(result.max_gap) <= 45.0, "%s meets decision timing bounds" % result.id)
|
|
expect(strictly_increasing(result.timestamps), "%s timestamps strictly increase" % result.id)
|
|
expect(result.route_ids.size() == 48 and result.route_risks.size() == 48, "%s executes all 48 ordinary rounds" % result.id)
|
|
expect(result.plan_ids.size() == 48 and result.boss_plans.size() == 4, "%s records all route and Boss plans" % result.id)
|
|
expect(result.rg04_pressure_families == ["clause", "cleanse_trap", "copy", "redirect"], "%s sees every archive pressure" % result.id)
|
|
expect(result.clause_kinds == ["alternate", "preserve", "repeat"] and bool(result.redaction_seen), "%s sees every clause and redaction disclosure" % result.id)
|
|
expect(int(result.records) == 6 and int(result.region_records) == 2, "%s writes all six carried Records" % result.id)
|
|
expect(int(result.unlocked_rg05) == 1 and String(result.phase) == "rg04_region_closed", "%s reaches exact RG-05 handoff" % result.id)
|
|
expect(int(result.cleared_rounds) == 72 and int(result.route_history_count) == 72, "%s preserves the complete route lineage" % result.id)
|
|
expect(int(result.company_size) >= 1 and int(result.coin) >= 0, "%s remains solvent with a viable Company" % result.id)
|
|
expect(bool(result.offline_zero), "%s reloads with zero offline value" % result.id)
|
|
var signature := "%s:%s:%s" % [result.artifact, result.route_risks, result.boss_plans]
|
|
signatures[signature] = true
|
|
artifacts[String(result.artifact)] = true
|
|
for slot in range(4):
|
|
bosses_by_slot[slot][String(result.boss_plans[slot])] = true
|
|
secondary_by_contract[slot] += int(result.secondary_counts[slot])
|
|
for index in range(48):
|
|
risks_by_slot[index][int(result.route_risks[index])] = true
|
|
total_rg04_recoveries += int(result.rg04_recoveries)
|
|
if String(result.id) == "normal":
|
|
expect(int(result.rg04_recoveries) == 1, "normal profile proves RG-04 permanent-loss recovery")
|
|
if String(result.id) == "returning":
|
|
expect(int(result.reloads) >= 12 and strictly_increasing(result.reload_timestamps), "returning profile reloads both Regions")
|
|
expect(signatures.size() == 5, "five combined policy signatures are distinct")
|
|
expect(artifacts.size() == 3, "combined profiles preserve three inherited Artifact contexts")
|
|
for slot in range(4):
|
|
expect(bosses_by_slot[slot].size() == 2, "Boss slot %d exercises both legal answers" % (slot + 1))
|
|
expect(secondary_by_contract[slot] > 0, "Contract slot %d exercises a winning secondary" % (slot + 1))
|
|
for index in range(48):
|
|
expect(risks_by_slot[index].size() >= 2, "route decision %d changes risk across profiles" % (index + 1))
|
|
expect(total_rg04_recoveries >= 1, "combined profiles include RG-04 recovery")
|
|
|
|
|
|
func route_for_risk(routes: Array, risk: int) -> Dictionary:
|
|
for route_value in routes:
|
|
var route: Dictionary = route_value
|
|
if int(route.get("risk", -1)) == risk:
|
|
return route
|
|
return {}
|
|
|
|
|
|
func first_wrong_plan(battle_script, market_index: int) -> String:
|
|
for plan_id in battle_script.PLAN_IDS:
|
|
if plan_id not in [battle_script.PRIMARY_PLAN[market_index], battle_script.SECONDARY_PLAN[market_index]]:
|
|
return String(plan_id)
|
|
return ""
|
|
|
|
|
|
func battle_seconds(terminal: Dictionary) -> float:
|
|
return float(terminal.get("view", {}).get("battle", {}).get("event_count", 0)) * 0.1
|
|
|
|
|
|
func record_decision(state: Dictionary, label: String, dwell: float) -> void:
|
|
state.clock = float(state.clock) + dwell
|
|
state.labels.append(label)
|
|
state.timestamps.append(float(state.clock))
|
|
|
|
|
|
func record_recovery(state: Dictionary, label: String, dwell: float) -> void:
|
|
state.clock = float(state.clock) + dwell
|
|
state.recovery_labels.append(label)
|
|
state.recovery_timestamps.append(float(state.clock))
|
|
|
|
|
|
func maximum_gap(timestamps: Array) -> float:
|
|
var prior := 0.0
|
|
var result := 0.0
|
|
for timestamp in timestamps:
|
|
result = maxf(result, float(timestamp) - prior)
|
|
prior = float(timestamp)
|
|
return result
|
|
|
|
|
|
func strictly_increasing(values: Array) -> bool:
|
|
for index in range(1, values.size()):
|
|
if float(values[index]) <= float(values[index - 1]):
|
|
return false
|
|
return true
|
|
|
|
|
|
func sorted_keys(values: Dictionary) -> Array[String]:
|
|
var result: Array[String] = []
|
|
for key in values:
|
|
if not String(key).is_empty():
|
|
result.append(String(key))
|
|
result.sort()
|
|
return result
|
|
|
|
|
|
func format_timestamps(labels: Array, timestamps: Array) -> String:
|
|
var rows: Array[String] = []
|
|
for index in range(labels.size()):
|
|
rows.append("%s@%.1f" % [labels[index], timestamps[index]])
|
|
return "[" + ",".join(rows) + "]"
|
|
|
|
|
|
func failed_result(profile_id: String, code: String) -> Dictionary:
|
|
print("FG4_MIDPOINT_PROFILE_FAILURE profile=%s code=%s" % [profile_id, code])
|
|
return {"id": profile_id, "failed": true, "code": code}
|
|
|
|
|
|
func expect(condition: bool, message: String) -> void:
|
|
if not condition:
|
|
failures.append("FG-4 midpoint five-profile simulation: %s" % message)
|