194 lines
7.8 KiB
GDScript
194 lines
7.8 KiB
GDScript
extends SceneTree
|
|
|
|
const Controller = preload("res://p9_8/runtime_controller.gd")
|
|
const ContractState = preload("res://p9_8/contract_state.gd")
|
|
const Fixture = preload("res://tests/p9_8/runtime_fixture.gd")
|
|
|
|
const VIEWPORT := Vector2i(844, 390)
|
|
|
|
var failures: Array[String] = []
|
|
var experience
|
|
var parsed_touches := 0
|
|
var parsed_drags := 0
|
|
|
|
|
|
func _initialize() -> void:
|
|
call_deferred("run_test")
|
|
|
|
|
|
func run_test() -> void:
|
|
root.content_scale_mode = Window.CONTENT_SCALE_MODE_CANVAS_ITEMS
|
|
root.content_scale_aspect = Window.CONTENT_SCALE_ASPECT_EXPAND
|
|
root.content_scale_size = VIEWPORT
|
|
root.size = VIEWPORT
|
|
await verify_complete_contract()
|
|
await verify_boss_defeat_recovery()
|
|
if is_instance_valid(experience):
|
|
experience.queue_free()
|
|
await settle_frames()
|
|
if failures.is_empty():
|
|
print("ABG_P9_8_FULL_CONTRACT_RUNTIME_TOUCH_OK touch=%d drag=%d fallback=0 direct=0 markets=8,9,10,11,12 artifact=AR-001 promotion=committed rounds=5 boss=BO-R1-01 plan=brace defeat_recovery=14 clear=CLEAR-RG01-C01 renown=3 record=1 controls=48 cards=0" % [parsed_touches, parsed_drags])
|
|
quit(0)
|
|
else:
|
|
for failure in failures:
|
|
push_error(failure)
|
|
quit(1)
|
|
|
|
|
|
func verify_complete_contract() -> void:
|
|
await mount(Fixture.market8())
|
|
expect(find_control("P98ArtifactButton_AR-001") != null, "Market 8 opens the Artifact shrine")
|
|
await tap("P98ArtifactButton_AR-001")
|
|
expect(experience.market.state.selected_artifact_id == "AR-001", "Artifact touch commits Open Ledger")
|
|
await commit_visible_promotion()
|
|
await neutral_drag()
|
|
for market_index in [8, 9, 10, 11, 12]:
|
|
expect(int(experience.market.state.current_market) == market_index, "Market %d is reached in order" % market_index)
|
|
if experience.market.state.company.size() < 10:
|
|
var recruit_id := String(experience.market.state.available_recruit_offer_ids[0])
|
|
await tap("P97RecruitTarget_%s" % recruit_id)
|
|
await tap("P97RecruitTarget_%s" % recruit_id)
|
|
expect(recruit_id in experience.market.state.company, "Market %d Recruit hires through touch" % market_index)
|
|
if experience.pending_line_ids.size() < experience.market.state.line_capacity:
|
|
await tap("P97CompanyTarget_%s" % recruit_id)
|
|
await tap("P97CompanyTarget_%s" % recruit_id)
|
|
await tap("P97CommitLineButton")
|
|
var route_id := "P98-R%d-Q0" % market_index
|
|
await tap("P97RouteTarget_%s" % route_id)
|
|
await tap("P97RouteTarget_%s" % route_id)
|
|
expect(experience.battle_active, "Round %d begins through the route gate" % market_index)
|
|
var guard := 0
|
|
while not experience.battle.state.terminal and guard < 2000:
|
|
experience.advance_battle_ticks(1)
|
|
if guard % 20 == 0:
|
|
await process_frame
|
|
guard += 1
|
|
expect(guard < 2000 and experience.battle.state.outcome == "victory", "Round %d reaches deterministic victory" % market_index)
|
|
await settle_frames()
|
|
await tap("P97SettleButton")
|
|
if experience.market.state.recovery_required:
|
|
await tap("P97RecoveryButton")
|
|
await commit_visible_promotion()
|
|
expect(int(experience.market.state.contract_phase) == ContractState.ContractPhase.BOSS_MUSTER, "Round 12 opens Boss Muster")
|
|
await tap("P98BossRallyButton")
|
|
expect(experience.market.state.deployed_recruit_ids.size() == 10, "final Rally fills the ten-member boss line")
|
|
await tap("P98BossPlanButton_brace")
|
|
expect(experience.boss_mode and experience.battle_active, "Brace touch starts the Stag battle")
|
|
var boss_guard := 0
|
|
while not experience.boss_battle.state.terminal and boss_guard < 1800:
|
|
experience.advance_battle_ticks(1)
|
|
if boss_guard % 12 == 0:
|
|
await process_frame
|
|
boss_guard += 1
|
|
expect(boss_guard < 1800 and experience.boss_battle.state.outcome == "victory", "Brace defeats the Stag")
|
|
expect(int(experience.presented_event_counts.get("boss_rule", 0)) > 0 and int(experience.presented_event_counts.get("boss_action", 0)) > 0, "pane and boss actions reach presentation")
|
|
await settle_frames()
|
|
await tap("P98BossSettleButton")
|
|
expect(int(experience.market.state.contract_phase) == ContractState.ContractPhase.CONTRACT_RESULT, "boss result opens the atomic close state")
|
|
await tap("P98CloseContractButton")
|
|
expect(experience.market.state.run_closed and experience.market.state.persistent_renown == 3, "close touch grants three Renown and closes the run")
|
|
expect(experience.market.state.company_records.size() == 1 and find_control("P98CloseContractButton") == null, "persistent result has one Company Record and no duplicate close target")
|
|
|
|
|
|
func verify_boss_defeat_recovery() -> void:
|
|
await mount(Fixture.boss_muster())
|
|
var fragile_id := "Farstring" if "Farstring" in experience.market.state.company else String(experience.market.state.company[-1])
|
|
var fragile_line: Array[String] = [fragile_id]
|
|
var committed: Dictionary = experience.market.commit_deployment("runtime-fragile-line", fragile_line)
|
|
expect(committed.ok, "defeat fixture commits one fragile Recruit")
|
|
experience.pending_line_ids.assign([fragile_id])
|
|
experience._queue_render()
|
|
await settle_frames()
|
|
await tap("P98BossPlanButton_rotate")
|
|
var guard := 0
|
|
while not experience.boss_battle.state.terminal and guard < 1800:
|
|
experience.advance_battle_ticks(1)
|
|
if guard % 12 == 0:
|
|
await process_frame
|
|
guard += 1
|
|
expect(guard < 1800 and experience.boss_battle.state.outcome == "defeat", "fragile line reaches a truthful Boss defeat")
|
|
await settle_frames()
|
|
await tap("P98BossSettleButton")
|
|
expect(experience.market.state.recovery_required and find_control("P98BossRecoveryButton") != null, "defeat returns to the same Muster with recovery")
|
|
var boss_hash := String(experience.market.state.boss_muster.boss_hash)
|
|
await tap("P98BossRecoveryButton")
|
|
expect(not experience.market.state.recovery_required and String(experience.market.state.boss_muster.boss_hash) == boss_hash, "recovery touch preserves the fixed Boss Muster")
|
|
|
|
|
|
func mount(snapshot: Dictionary) -> void:
|
|
if is_instance_valid(experience):
|
|
experience.queue_free()
|
|
await settle_frames()
|
|
experience = Controller.new()
|
|
experience.persistence_enabled = false
|
|
experience.battle_auto_advance = false
|
|
experience.size = Vector2(VIEWPORT)
|
|
experience.configure_entry(snapshot)
|
|
root.add_child(experience)
|
|
await settle_frames()
|
|
|
|
|
|
func commit_visible_promotion() -> void:
|
|
if experience.market.state.promotion_draft.is_empty():
|
|
return
|
|
var promotion_id := String(experience.market.state.promotion_draft.offer_ids[0])
|
|
await tap("P98PromotionButton_%s" % promotion_id)
|
|
expect(not experience.market.state.promotion_receipts.is_empty(), "promotion commits through the anvil")
|
|
|
|
|
|
func tap(node_name: String) -> void:
|
|
var control := find_control(node_name)
|
|
expect(control != null, "%s exists before parsed touch" % node_name)
|
|
if control == null:
|
|
return
|
|
var point := root.get_final_transform() * control.get_global_rect().get_center()
|
|
var down := InputEventScreenTouch.new()
|
|
down.index = 0
|
|
down.position = point
|
|
down.pressed = true
|
|
Input.parse_input_event(down)
|
|
parsed_touches += 1
|
|
await process_frame
|
|
var up := InputEventScreenTouch.new()
|
|
up.index = 0
|
|
up.position = point
|
|
up.pressed = false
|
|
Input.parse_input_event(up)
|
|
await settle_frames()
|
|
|
|
|
|
func neutral_drag() -> void:
|
|
var down := InputEventScreenTouch.new()
|
|
down.index = 1
|
|
down.position = Vector2(20, 210)
|
|
down.pressed = true
|
|
Input.parse_input_event(down)
|
|
await process_frame
|
|
var drag := InputEventScreenDrag.new()
|
|
drag.index = 1
|
|
drag.position = Vector2(74, 210)
|
|
drag.relative = Vector2(54, 0)
|
|
Input.parse_input_event(drag)
|
|
parsed_drags += 1
|
|
await process_frame
|
|
var up := InputEventScreenTouch.new()
|
|
up.index = 1
|
|
up.position = drag.position
|
|
up.pressed = false
|
|
Input.parse_input_event(up)
|
|
await settle_frames()
|
|
|
|
|
|
func find_control(node_name: String) -> Control:
|
|
return experience.find_child(node_name, true, false) as Control
|
|
|
|
|
|
func settle_frames() -> void:
|
|
await process_frame
|
|
await process_frame
|
|
|
|
|
|
func expect(condition: bool, message: String) -> void:
|
|
if not condition:
|
|
failures.append("P9.8 runtime: %s" % message)
|