203 lines
9.5 KiB
GDScript
203 lines
9.5 KiB
GDScript
extends SceneTree
|
|
|
|
const Controller = preload("res://p10_1/runtime_controller.gd")
|
|
const Main = preload("res://main.gd")
|
|
const Fixture = preload("res://tests/p10_1/runtime_fixture.gd")
|
|
const SaveService = preload("res://p10_1/save_v7_service.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_main_handoff()
|
|
await verify_victory_flow()
|
|
await verify_defeat_recovery()
|
|
if is_instance_valid(experience):
|
|
experience.queue_free()
|
|
for _index in 45:
|
|
await process_frame
|
|
if failures.is_empty():
|
|
print("ABG_P10_1_RUNTIME_TOUCH_FLOW_OK gate=true market=3,4,3 hire=2 gear=buy+equip order=drag route=risk2 plan=hold,follow battle=pull,tide,healing_denial,damage fallen=true recovery=true market2=saved touch=%d drag=%d fallback=0 direct=0" % [parsed_touches, parsed_drags])
|
|
quit(0)
|
|
else:
|
|
for failure in failures:
|
|
push_error(failure)
|
|
quit(1)
|
|
|
|
|
|
func verify_main_handoff() -> void:
|
|
var game = Main.new()
|
|
game.auto_boot = true
|
|
game.p100_experience_enabled = true
|
|
game.p100_persistence_enabled = false
|
|
root.add_child(game)
|
|
await settle_frames()
|
|
expect(is_instance_valid(game.p100_experience), "main creates one canonical runtime")
|
|
if is_instance_valid(game.p100_experience):
|
|
expect(game.p100_experience.get_script() == Controller, "main canonical runtime uses the P10.1 compatibility controller")
|
|
expect(game.p100_experience.screen == "title", "fresh main still preserves the P10.0 Title")
|
|
game.queue_free()
|
|
await settle_frames(12)
|
|
|
|
|
|
func verify_victory_flow() -> void:
|
|
await mount(Fixture.gate_snapshot())
|
|
expect(experience.screen == "guild", "closed Windglass state restores the Guild record gate")
|
|
await tap("P101EnterRegionButton")
|
|
expect(experience.region_mode and experience.screen == Controller.REGION_SCREEN_MARKET, "parsed touch enters Siltwake Market 1")
|
|
expect(experience.region_market.state.current_run.market_board.recruit_offers.size() == 3, "Market exposes three Recruit world targets")
|
|
expect(experience.region_market.state.current_run.market_board.equipment_offers.size() == 4, "Market exposes four equipment world objects")
|
|
expect(experience.region_market.state.current_run.market_board.battle_offers.size() == 3, "Market exposes three route posts")
|
|
var recruits: Array = Array(experience.region_market.state.current_run.market_board.recruit_offers).duplicate(true)
|
|
for index in range(2):
|
|
var offer_id := String(recruits[index].source_offer_id)
|
|
await tap("P101RecruitTarget_%s" % offer_id)
|
|
await tap("P101RecruitTarget_%s" % offer_id)
|
|
expect(experience.region_market.state.current_run.company.size() == 2, "inspect-then-hire forms a two-Recruit Company")
|
|
var equipment := affordable_equipment()
|
|
expect(not equipment.is_empty(), "the first Market retains one affordable regional equipment response")
|
|
if not equipment.is_empty():
|
|
await tap("P101EquipmentTarget_%s" % String(equipment.offer_id))
|
|
await tap("P101EquipmentTarget_%s" % String(equipment.offer_id))
|
|
await tap("P101CompanyTarget_%s" % String(experience.region_market.state.current_run.company[0]))
|
|
expect(String(experience.region_market.state.current_run.inventory.get(experience.region_market.state.current_run.equipped_by_recruit[experience.region_market.state.current_run.company[0]], {}).get("catalog_id", "")).begins_with("EQ-04"), "bought regional equipment equips through the Company actor")
|
|
var before_order: Array = Array(experience.region_market.state.current_run.deployed_recruit_ids).duplicate()
|
|
await drag("P101CompanyTarget_%s" % String(before_order[-1]), "P101CompanyTarget_%s" % String(before_order[0]))
|
|
expect(experience.region_market.state.current_run.deployed_recruit_ids != before_order, "parsed ScreenDrag changes front-to-rear order")
|
|
var high_route := route_offer(2)
|
|
expect(not high_route.is_empty(), "risk-two route exists")
|
|
await tap("P101RouteTarget_%s" % String(high_route.offer_id))
|
|
await tap("P101PrepareRouteButton")
|
|
expect(experience.screen == Controller.REGION_SCREEN_PLAN and experience.region_market.state.current_run.phase == "prepared", "explicit route command opens the opposed plan choice")
|
|
await tap("P101PlanTarget_follow_tide")
|
|
expect(experience.screen == Controller.REGION_SCREEN_BATTLE and not experience.region_battle_complete, "follow-tide touch starts event playback")
|
|
while not experience.region_battle_complete:
|
|
experience.advance_region_battle_ticks(8)
|
|
await process_frame
|
|
for kind in ["pull_committed", "indexed_mud_created", "healing_denial_attached", "tide_followed", "authoritative_damage", "battle_terminal"]:
|
|
expect(int(experience.region_event_counts.get(kind, 0)) > 0, "battle presents authoritative %s" % kind)
|
|
expect(String(experience.region_battle_snapshot.outcome) == "victory", "follow-tide wins the disclosed high-risk counterfactual")
|
|
await tap("P101SettleButton")
|
|
expect(experience.screen == Controller.REGION_SCREEN_MARKET_2, "victory settlement reaches saved Market 2")
|
|
expect(int(experience.region_market.state.current_run.market_index) == 2 and not experience.region_market.state.current_run.market_2_handoff.is_empty(), "Market 2 contains the exact reward handoff")
|
|
var encoded: Dictionary = SaveService.new().encode_snapshot(experience.region_market.state.snapshot(), 1)
|
|
expect(encoded.ok and SaveService.new().decode_text(String(encoded.text)).ok, "player-visible Market 2 round-trips through Save v7")
|
|
|
|
|
|
func verify_defeat_recovery() -> void:
|
|
await mount(Fixture.prepared_snapshot(2))
|
|
expect(experience.screen == Controller.REGION_SCREEN_PLAN, "prepared high route resumes at plan choice")
|
|
await tap("P101PlanTarget_hold_line")
|
|
while not experience.region_battle_complete:
|
|
experience.advance_region_battle_ticks(10)
|
|
await process_frame
|
|
expect(String(experience.region_battle_snapshot.outcome) == "defeat" and not experience.region_battle_snapshot.fallen_recruit_ids.is_empty(), "holding through the high tide causes readable permanent loss")
|
|
await tap("P101SettleButton")
|
|
expect(experience.screen == Controller.REGION_SCREEN_RECOVERY, "defeat settlement opens bounded recovery")
|
|
var survivors_before: int = experience.region_market.state.current_run.company.size()
|
|
await tap("P101RecoverButton")
|
|
expect(experience.screen == Controller.REGION_SCREEN_MARKET, "exact-cost recovery returns to the changed first Market")
|
|
expect(experience.region_market.state.current_run.company.size() == survivors_before and experience.region_market.state.current_run.company.all(func(recruit_id): return int(experience.region_market.state.current_run.recruit_records[recruit_id].current_hp) > 0), "recovery restores survivors without resurrecting Fallen")
|
|
|
|
|
|
func mount(snapshot: Dictionary) -> void:
|
|
if is_instance_valid(experience):
|
|
experience.queue_free()
|
|
await settle_frames(12)
|
|
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 affordable_equipment() -> Dictionary:
|
|
var coin := int(experience.region_market.state.current_run.coin)
|
|
for offer in experience.region_market.state.current_run.market_board.equipment_offers:
|
|
if String(offer.offer_id) in experience.region_market.state.current_run.available_equipment_offer_ids and int(offer.list_price) <= coin:
|
|
return Dictionary(offer).duplicate(true)
|
|
return {}
|
|
|
|
|
|
func route_offer(risk: int) -> Dictionary:
|
|
for offer in experience.region_market.state.current_run.market_board.battle_offers:
|
|
if int(offer.risk) == risk:
|
|
return Dictionary(offer).duplicate(true)
|
|
return {}
|
|
|
|
|
|
func tap(node_name: String) -> void:
|
|
var control := experience.find_child(node_name, true, false) as Control
|
|
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 drag(source_name: String, target_name: String) -> void:
|
|
var source := experience.find_child(source_name, true, false) as Control
|
|
var target := experience.find_child(target_name, true, false) as Control
|
|
expect(source != null and target != null, "formation drag targets exist")
|
|
if source == null or target == null:
|
|
return
|
|
var start := root.get_final_transform() * source.get_global_rect().get_center()
|
|
var finish := root.get_final_transform() * target.get_global_rect().get_center()
|
|
var down := InputEventScreenTouch.new()
|
|
down.index = 1
|
|
down.position = start
|
|
down.pressed = true
|
|
Input.parse_input_event(down)
|
|
parsed_touches += 1
|
|
await process_frame
|
|
var motion := InputEventScreenDrag.new()
|
|
motion.index = 1
|
|
motion.position = finish
|
|
motion.relative = finish - start
|
|
Input.parse_input_event(motion)
|
|
parsed_drags += 1
|
|
await process_frame
|
|
var up := InputEventScreenTouch.new()
|
|
up.index = 1
|
|
up.position = finish
|
|
up.pressed = false
|
|
Input.parse_input_event(up)
|
|
await settle_frames()
|
|
|
|
|
|
func settle_frames(count := 5) -> void:
|
|
for _index in count:
|
|
await process_frame
|
|
|
|
|
|
func expect(condition: bool, message: String) -> void:
|
|
if not condition:
|
|
failures.append("P10.1 runtime touch: %s" % message)
|