# test_biologist_chaegirab_research_parity.gd —— 40250 生物学者车齿木研究链 1:1 回归测试套件 extends SceneTree const BiologistChaegirabResearchSystem = preload("res://biologist_chaegirab_research_system.gd") var _passed := 0 var _failed := 0 func _assert(cond: bool, msg: String) -> void: if cond: _passed += 1 print(" [PASS] %s" % msg) else: _failed += 1 printerr(" [FAIL] %s" % msg) func _init() -> void: print("\n=== Running test_biologist_chaegirab_research_parity (Direction 1: Biologist Research 1:1) ===") _test_stage_progression_and_sample_validation() _test_sample_completion_and_soul_stone_capstone() _test_subsequent_stages_and_stat_stacking() _test_serialization() _finish() func _test_stage_progression_and_sample_validation() -> void: print("\n--- Test 1: Stage Requirements & Sample Item Validations ---") var sys := BiologistChaegirabResearchSystem.new() var inv: Array = [ {"vnum": 10, "name": "木剑", "count": 1}, {"vnum": 30006, "name": "兽人牙齿", "count": 5} ] # 1. Level too low (< 30) var res_low = sys.submit_sample(inv, 1, 25) _assert(res_low["ok"] == false, "Rejected: level 25 < 30") _assert(res_low["reason"] == "PLAYER_LEVEL_TOO_LOW", "Reason is PLAYER_LEVEL_TOO_LOW") # 2. Wrong sample item var res_wrong = sys.submit_sample(inv, 0, 35) _assert(res_wrong["ok"] == false, "Rejected: wrong item (Wood Sword)") _assert(res_wrong["reason"] == "WRONG_SAMPLE_ITEM", "Reason is WRONG_SAMPLE_ITEM") # 3. Valid sample submission (force success) var sub_sig := {"fired": false, "cur": 0} sys.sample_submitted.connect(func(_n: String, _s: bool, c: int, _t: int): sub_sig["fired"] = true sub_sig["cur"] = c ) var res_succ = sys.submit_sample(inv, 1, 35, true) _assert(res_succ["ok"] == true, "Orc Tooth submitted successfully") _assert(res_succ["current"] == 1, "Progress is 1/10") _assert(inv[1]["count"] == 4, "Orc tooth count decremented 5 -> 4") _assert(sub_sig["fired"] == true, "sample_submitted signal emitted") func _test_sample_completion_and_soul_stone_capstone() -> void: print("\n--- Test 2: Sample Completion & Capstone Soul Stone Delivery ---") var sys := BiologistChaegirabResearchSystem.new() var player_stats := {"move_speed": 100} var inv: Array = [ {"vnum": 30006, "name": "兽人牙齿", "count": 10}, {"vnum": 30220, "name": "兽人灵魂石", "count": 1} ] # Submit remaining 9 teeth to hit 10/10 for i in range(10): sys.submit_sample(inv, 0, 35, true) _assert(sys.current_samples == 10, "Collected all 10 Orc Teeth") _assert(sys.waiting_for_soul_stone == true, "Now waiting for soul stone") # Cannot submit more teeth inv[0] = {"vnum": 30006, "name": "兽人牙齿", "count": 1} var res_excess = sys.submit_sample(inv, 0, 35, true) _assert(res_excess["ok"] == false, "Excess sample submission blocked") _assert(res_excess["reason"] == "WAITING_FOR_SOUL_STONE", "Reason is WAITING_FOR_SOUL_STONE") var cap_sig := {"fired": false, "stone": ""} sys.capstone_submitted.connect(func(sn: String, _st: String): cap_sig["fired"] = true cap_sig["stone"] = sn ) # Submit wrong soul stone inv[0] = {"vnum": 30221, "name": "诅咒灵魂石", "count": 1} var res_wrong_stone = sys.submit_soul_stone(inv, 0, player_stats) _assert(res_wrong_stone["ok"] == false, "Wrong soul stone rejected") _assert(res_wrong_stone["reason"] == "WRONG_SOUL_STONE", "Reason is WRONG_SOUL_STONE") # Submit valid Orc Soul Stone (slot 1) var res_stone_succ = sys.submit_soul_stone(inv, 1, player_stats) _assert(res_stone_succ["ok"] == true, "Orc Soul Stone submitted") _assert(player_stats["move_speed"] == 110, "Permanent move speed +10 applied (100 -> 110)") _assert(sys.permanent_bonuses["move_speed"] == 10, "Permanent bonus recorded") _assert(sys.current_stage_index == 1, "Advanced to Stage 2 (Curse Book)") _assert(sys.current_samples == 0, "Current samples reset to 0") _assert(sys.waiting_for_soul_stone == false, "No longer waiting for soul stone") _assert(cap_sig["fired"] == true, "capstone_submitted signal emitted") func _test_subsequent_stages_and_stat_stacking() -> void: print("\n--- Test 3: Subsequent Stages (Curse Book & Demon Keepsake) Stacking ---") var sys := BiologistChaegirabResearchSystem.new() var player_stats := {"move_speed": 100, "cast_speed_pct": 0, "defense": 200} # Stage 1: Complete Orc Tooth (+10 move speed) var inv1: Array = [ {"vnum": 30006, "name": "兽人牙齿", "count": 10}, {"vnum": 30220, "name": "兽人灵魂石", "count": 1} ] for i in range(10): sys.submit_sample(inv1, 0, 30, true) sys.submit_soul_stone(inv1, 1, player_stats) # Stage 2: Complete Curse Book (+5% cast speed) var inv2: Array = [ {"vnum": 30047, "name": "诅咒之书", "count": 15}, {"vnum": 30221, "name": "诅咒灵魂石", "count": 1} ] for i in range(15): sys.submit_sample(inv2, 0, 40, true) sys.submit_soul_stone(inv2, 1, player_stats) # Stage 3: Complete Demon Keepsake (+60 def) var inv3: Array = [ {"vnum": 30015, "name": "恶魔纪念物", "count": 15}, {"vnum": 30222, "name": "恶魔灵魂石", "count": 1} ] for i in range(15): sys.submit_sample(inv3, 0, 50, true) sys.submit_soul_stone(inv3, 1, player_stats) _assert(player_stats["move_speed"] == 110, "Stage 1 bonus active (+10)") _assert(player_stats["cast_speed_pct"] == 5, "Stage 2 bonus active (+5%)") _assert(player_stats["defense"] == 260, "Stage 3 bonus active (+60)") _assert(sys.completed_stages.size() == 3, "3 stages completed in total") func _test_serialization() -> void: print("\n--- Test 4: Serialization & Restoration ---") var sys1 := BiologistChaegirabResearchSystem.new() sys1.current_stage_index = 4 # Stage 5: Zelkova Branch sys1.current_samples = 18 sys1.waiting_for_soul_stone = false sys1.completed_stages = [1, 2, 3, 4] sys1.permanent_bonuses = {"move_speed": 10, "cast_speed_pct": 5, "defense": 60, "attack_power": 50} var data = sys1.serialize() var sys2 := BiologistChaegirabResearchSystem.new() sys2.deserialize(data) _assert(sys2.current_stage_index == 4, "Restored stage index 4") _assert(sys2.current_samples == 18, "Restored samples 18") _assert(sys2.completed_stages.size() == 4, "Restored 4 completed stages") _assert(sys2.permanent_bonuses["attack_power"] == 50, "Restored attack bonus 50") func _finish() -> void: print("\n=======================================================") print("Biologist Research Parity Tests: %d Passed, %d Failed" % [_passed, _failed]) print("=======================================================\n") if _failed > 0: quit(1) else: quit(0)