127 lines
4.9 KiB
GDScript
127 lines
4.9 KiB
GDScript
extends SceneTree
|
|
|
|
const MainScene = preload("res://main.tscn")
|
|
|
|
var failures: Array[String] = []
|
|
|
|
|
|
func _initialize() -> void:
|
|
call_deferred("run_test")
|
|
|
|
|
|
func run_test() -> void:
|
|
var game := MainScene.instantiate()
|
|
game.auto_boot = false
|
|
root.add_child(game)
|
|
await settle(10)
|
|
game.locale = "zh_CN"
|
|
game.muted = true
|
|
|
|
prepare_first_victory(game, "Hearthguard", "Farstring")
|
|
expect(game.page == game.AppPage.VICTORY, "first battle reaches diagnosis")
|
|
expect(game.coin == 20 and game.first_reward_committed, "first victory grants 20 Coin exactly once")
|
|
expect(find_control(game, "VictoryDiagnosis") != null, "first result renders causal diagnosis")
|
|
expect(find_control(game, "FirstReward") != null, "first result renders the reward")
|
|
game.commit_first_victory_reward()
|
|
expect(game.coin == 20, "replaying reward commit cannot duplicate Coin")
|
|
|
|
game.open_adaptation()
|
|
expect(game.page == game.AppPage.ADAPTATION, "diagnosis opens adaptation")
|
|
expect(game.adaptation_choice.is_empty(), "adaptation has no preselection")
|
|
expect(find_control(game, "Adaptation_EQ_002") != null and find_control(game, "Adaptation_EQ_061") != null, "both stable choices render")
|
|
var begin := find_control(game, "BeginSecondBattle") as BaseButton
|
|
expect(begin != null and begin.disabled, "second battle is disabled until a choice")
|
|
game.choose_adaptation("EQ-061")
|
|
game.choose_adaptation("EQ-002")
|
|
expect(game.adaptation_choice == "EQ-002", "selection is reversible before commit")
|
|
game.begin_second_battle()
|
|
expect(game.page == game.AppPage.SECOND_BATTLE and game.adaptation_committed, "departure locks the chosen loan")
|
|
game.choose_adaptation("EQ-061")
|
|
expect(game.adaptation_choice == "EQ-002", "committed loan cannot change")
|
|
var safe_time := resolve_second_battle(game)
|
|
expect(game.page == game.AppPage.SECOND_RESULT, "safe route reaches second result")
|
|
expect(game.front_hp == 90 and game.enemy_hp == 0, "Frontpin Farstring route keeps 90 front HP and wins")
|
|
expect(game.coin == 20, "second battle does not duplicate first reward")
|
|
expect(game.battle_feedback_history.size() == 4, "safe route emits four exact HP feedback events")
|
|
expect(find_control(game, "SecondResultFacts") != null, "second result renders exact facts")
|
|
|
|
game.request_restart()
|
|
game.confirm_restart()
|
|
expect(game.page == game.AppPage.MAIN_MENU, "confirmed replay returns to Main Menu")
|
|
expect(game.coin == 0 and game.adaptation_choice.is_empty() and not game.adaptation_committed, "restart clears reward and adaptation")
|
|
|
|
prepare_first_victory(game, "Hearthguard", "Farstring")
|
|
game.open_adaptation()
|
|
game.choose_adaptation("EQ-061")
|
|
game.begin_second_battle()
|
|
var fast_time := resolve_second_battle(game)
|
|
expect(game.front_hp == 70 and game.enemy_hp == 0, "Early Bell Farstring route accepts full strike and wins")
|
|
expect(game.battle_feedback_history.size() == 5, "fast route emits initiative plus four HP feedback events")
|
|
expect(fast_time < safe_time, "Early Bell route is faster than Frontpin route")
|
|
|
|
game.clear_experience()
|
|
prepare_first_victory(game, "Hearthguard", "Kindhand")
|
|
game.open_adaptation()
|
|
game.choose_adaptation("EQ-002")
|
|
game.begin_second_battle()
|
|
resolve_second_battle(game)
|
|
expect(game.front_hp == 100, "Frontpin Kindhand route caps healing at 100")
|
|
|
|
game.clear_experience()
|
|
prepare_first_victory(game, "Wayrunner", "Kindhand")
|
|
game.open_adaptation()
|
|
game.choose_adaptation("EQ-061")
|
|
game.begin_second_battle()
|
|
resolve_second_battle(game)
|
|
expect(game.front_hp == 82, "Early Bell Kindhand route heals 70 to 82")
|
|
game.go_home()
|
|
expect(game.page == game.AppPage.MAIN_MENU and game.coin == 0 and game.front_choice.is_empty(), "Home clears the complete transient loop")
|
|
|
|
game.queue_free()
|
|
await settle(80)
|
|
if failures.is_empty():
|
|
print("ABG_P9_0R4_SECOND_CYCLE_OK coin=20 once=true choices=2 unselected=true revision=true lock=true safe_hp=90,100 fast_hp=70,82 safe_time=%.2f fast_time=%.2f feedback=4,5 cleanup=true" % [safe_time, fast_time])
|
|
quit(0)
|
|
else:
|
|
for failure in failures:
|
|
push_error(failure)
|
|
quit(1)
|
|
|
|
|
|
func prepare_first_victory(game: Control, front: String, rear: String) -> void:
|
|
game.front_choice = front
|
|
game.rear_choice = rear
|
|
game.depart()
|
|
for phase in range(6):
|
|
game.advance_battle_phase()
|
|
|
|
|
|
func resolve_second_battle(game: Control) -> float:
|
|
var declared_time := 0.0
|
|
for phase in range(6):
|
|
var duration: float = game.phase_duration(phase)
|
|
declared_time += duration
|
|
game.second_battle_elapsed += duration
|
|
game.advance_battle_phase()
|
|
return declared_time
|
|
|
|
|
|
func find_control(node: Node, node_name: String) -> Control:
|
|
if node.name == node_name and node is Control and not node.is_queued_for_deletion():
|
|
return node
|
|
for child in node.get_children():
|
|
var found := find_control(child, node_name)
|
|
if found != null:
|
|
return found
|
|
return null
|
|
|
|
|
|
func settle(frames: int) -> void:
|
|
for frame in range(frames):
|
|
await process_frame
|
|
|
|
|
|
func expect(condition: bool, message: String) -> void:
|
|
if not condition:
|
|
failures.append("P9.0R4 second cycle: %s" % message)
|