Files
aetherbound-guild/runtime/tests/p9_0r7_individual_growth_test.gd
T

152 lines
6.1 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_second_cycle_result(game, "EQ-002", "Farstring", "")
expect(game.member_slots() == ["front", "rear"], "two-person Company exposes front/rear only")
game.open_training()
expect(game.page == game.AppPage.TRAINING and game.training_choice.is_empty(), "training opens unselected")
expect(find_control(game, "Training_Added") == null, "absent added member never renders")
game.choose_training("added")
expect(game.training_choice.is_empty(), "absent added member is rejected")
game.choose_training("front")
game.choose_training("rear")
expect(game.training_choice == "rear", "selection is reversible without committing")
game.open_training_review()
game.cancel_training_review()
expect(game.page == game.AppPage.TRAINING and game.training_choice == "rear", "review cancel preserves choice")
prepare_second_cycle_result(game, "", "Farstring", "Kindhand")
expect(game.member_slots() == ["front", "rear", "added"], "three-person Company exposes actual added member")
for slot in ["front", "rear", "added"]:
expect(game.member_level(slot) == 1, "%s starts at Lv.1" % slot)
game.open_training()
game.choose_training("added")
game.open_training_review()
var coin_before: int = game.coin
game.commit_training()
expect(game.training_committed and game.trained_member == "added", "commit binds one actual member")
expect(game.member_level("added") == 2 and game.member_level("front") == 1 and game.member_level("rear") == 1, "exactly one member reaches Lv.2")
game.commit_training()
expect(game.coin == coin_before and game.trained_member == "added", "duplicate training commit is inert")
resolve_fifth_battle(game)
expect(game.page == game.AppPage.THIRD_CYCLE_RESULT and game.enemy_hp == 0, "fifth battle reaches causal result")
expect(game.rear_hp == 85 and game.rear_events == 2, "trained added Kindhand heals +25 and both rears act once")
expect(game.coin == coin_before + 8 and game.fifth_reward_committed, "fifth reward commits once")
game.commit_fifth_reward()
expect(game.coin == coin_before + 8, "duplicate fifth reward is inert")
for item in ["EQ-002", ""]:
for training_slot in ["front", "rear", "added"]:
prepare_second_cycle_result(game, item, "Farstring", "Kindhand")
commit_training_choice(game, training_slot)
var duration := resolve_fifth_battle(game)
var expected_front := 90 if item == "EQ-002" else 75
if training_slot != "front":
expected_front = 70 if item == "EQ-002" else 55
var expected_rear := 85 if training_slot == "added" else 72
var expected_time := 6.40 if training_slot == "rear" else 7.40
expect(game.front_hp == expected_front, "%s/%s front counterfactual" % [item, training_slot])
expect(game.rear_hp == expected_rear, "%s/%s rear counterfactual" % [item, training_slot])
expect(is_equal_approx(duration, expected_time), "%s/%s timing counterfactual" % [item, training_slot])
expect(game.rear_events == 2, "%s/%s rear actions remain exactly two" % [item, training_slot])
prepare_second_cycle_result(game, "", "Kindhand", "Farstring")
commit_training_choice(game, "rear")
resolve_fifth_battle(game)
expect(game.rear_hp == 85 and game.rear_events == 2, "trained original Kindhand heals +25")
prepare_second_cycle_result(game, "EQ-002", "Farstring", "")
commit_training_choice(game, "rear")
var two_person_time := resolve_fifth_battle(game)
expect(game.rear_hp == 60 and game.rear_events == 1, "two-person Farstring acts once and cannot heal")
expect(is_equal_approx(two_person_time, 6.40), "two-person trained Farstring preserves fast timing")
game.request_restart()
game.confirm_restart()
expect(game.page == game.AppPage.MAIN_MENU, "Restart returns to Main Menu")
expect(game.training_choice.is_empty() and not game.training_committed and game.trained_member.is_empty() and not game.fifth_reward_committed, "Restart clears growth transaction")
game.queue_free()
await settle(90)
if failures.is_empty():
print("ABG_P9_0R7_INDIVIDUAL_GROWTH_OK slots=2,3 revise=true review_cancel=true commit_once=true level2=1 outcomes=8 front_hp=90,75,70,55 rear_hp=85,72,60 times=7.40,6.40 reward=8 cleanup=true")
quit(0)
else:
for failure in failures:
push_error(failure)
quit(1)
func prepare_second_cycle_result(game: Control, item: String, original_rear: String, extra_rear: String) -> void:
game.clear_experience()
game.front_choice = "Hearthguard"
game.rear_choice = original_rear
game.adaptation_choice = item if not item.is_empty() else "EQ-061"
game.adaptation_committed = true
game.guild_choice = "retain_item" if extra_rear.is_empty() else "recruit_rear"
game.guild_committed = true
game.retained_item = item
game.added_rear = extra_rear
game.coin = 12
game.route_choice = "R6-01"
game.route_committed = true
game.route_reward_committed = true
game.front_hp = 90
game.rear_hp = 100
game.enemy_hp = 0
game.fourth_result_time = 7.40
game.page = game.AppPage.SECOND_CYCLE_RESULT
game.render()
func commit_training_choice(game: Control, slot: String) -> void:
game.open_training()
game.choose_training(slot)
game.open_training_review()
game.commit_training()
func resolve_fifth_battle(game: Control) -> float:
var declared_time := 0.0
for phase in range(7):
var duration: float = game.phase_duration(phase)
declared_time += duration
game.fifth_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.0R7 growth: %s" % message)