# test_inventory_expansion_parity.gd —— 40250 背包扩展凭证与阶梯解锁系统回归测试 extends SceneTree const SystemClass = preload("res://inventory_expansion_system.gd") var _passed: int = 0 var _failed: int = 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_inventory_expansion_parity (Batch 26 Direction 4) ===") _test_default_unlocked_baseline() _test_key_cost_curve() _test_stage_by_stage_unlocking() _test_locked_slot_item_placement_rejection() _test_multislot_item_boundary_and_lock_check() _test_full_180_slots_unlock_completion() print("\n=== Result: %d Passed, %d Failed ===" % [_passed, _failed]) if _failed == 0: print("ALL TESTS PASSED!\n") else: printerr("SOME TESTS FAILED!\n") quit(0 if _failed == 0 else 1) func _test_default_unlocked_baseline() -> void: print("\n--- Test 1: Default Baseline (Pages 1 & 2 = 90 Slots Unlocked) ---") var inv = SystemClass.new() _assert(inv.get_unlocked_slot_count() == 90, "Baseline has 90 unlocked slots (2 pages)") _assert(inv.is_slot_unlocked(0) == true, "Slot 0 (Page 1) is unlocked") _assert(inv.is_slot_unlocked(44) == true, "Slot 44 (Page 1 end) is unlocked") _assert(inv.is_slot_unlocked(45) == true, "Slot 45 (Page 2 start) is unlocked") _assert(inv.is_slot_unlocked(89) == true, "Slot 89 (Page 2 end) is unlocked") # Locked slots on Pages 3 & 4 _assert(inv.is_slot_unlocked(90) == false, "Slot 90 (Page 3 start) is locked") _assert(inv.is_slot_unlocked(134) == false, "Slot 134 (Page 3 end) is locked") _assert(inv.is_slot_unlocked(135) == false, "Slot 135 (Page 4 start) is locked") _assert(inv.is_slot_unlocked(179) == false, "Slot 179 (Page 4 end) is locked") func _test_key_cost_curve() -> void: print("\n--- Test 2: 18-Stage Key Cost Curve (Official 40250) ---") var inv = SystemClass.new() _assert(inv.get_next_stage_key_cost() == 1, "Stage 1 costs 1 key") inv.unlocked_stages = 5 _assert(inv.get_next_stage_key_cost() == 1, "Stage 6 costs 1 key") inv.unlocked_stages = 6 _assert(inv.get_next_stage_key_cost() == 2, "Stage 7 costs 2 keys") inv.unlocked_stages = 11 _assert(inv.get_next_stage_key_cost() == 2, "Stage 12 costs 2 keys") inv.unlocked_stages = 12 _assert(inv.get_next_stage_key_cost() == 3, "Stage 13 costs 3 keys") inv.unlocked_stages = 17 _assert(inv.get_next_stage_key_cost() == 4, "Stage 18 costs 4 keys") # Sum of all stages var total_keys := 0 for cost in SystemClass.STAGE_KEY_COSTS: total_keys += cost _assert(total_keys == 37, "Total keys for all 18 stages is exactly 37 keys") func _test_stage_by_stage_unlocking() -> void: print("\n--- Test 3: Stage-by-Stage Unlocking and Key Deduction ---") var inv = SystemClass.new() # Insufficient keys var r_fail = inv.unlock_next_stage(0) _assert(r_fail["error_code"] == "INSUFFICIENT_KEYS", "Reject unlock if keys < required") # Unlock stage 1 (costs 1 key) var r_stage1 = inv.unlock_next_stage(10) _assert(r_stage1["success"] == true, "Stage 1 unlocked") _assert(r_stage1["keys_deducted"] == 1, "1 key deducted") _assert(r_stage1["remaining_keys"] == 9, "9 keys remain") _assert(r_stage1["unlocked_slots"] == 95, "Unlocked slots increased to 95") _assert(inv.is_slot_unlocked(90) == true, "Slot 90 now unlocked") _assert(inv.is_slot_unlocked(94) == true, "Slot 94 now unlocked") _assert(inv.is_slot_unlocked(95) == false, "Slot 95 still locked") func _test_locked_slot_item_placement_rejection() -> void: print("\n--- Test 4: Locked Slot Item Placement Rejection ---") var inv = SystemClass.new() var sword = { "vnum": 10, "name": "Sword+0" } # Put into unlocked slot 0 var r_ok = inv.put_item(0, sword, 1) _assert(r_ok["success"] == true, "Placed item into unlocked slot 0") # Put into locked slot 90 var r_lock = inv.put_item(90, sword, 1) _assert(r_lock["error_code"] == "SLOT_LOCKED", "Reject putting item into locked slot 90") func _test_multislot_item_boundary_and_lock_check() -> void: print("\n--- Test 5: Multi-Slot Item Boundary & Partial Lock Detection ---") var inv = SystemClass.new() var greatsword = { "vnum": 3000, "name": "Glaive+0" } # Height = 3 # Slot 80 is Page 2, row 7 (cells 80, 85, 90). # But row 7 + 3 = 10 > 9 -> PAGE_OVERFLOW! var r_overflow = inv.can_place_item_at(80, 3) _assert(r_overflow["error_code"] == "PAGE_OVERFLOW", "Reject multi-slot item crossing page bottom") # Slot 70 is Page 2, row 5 (cells 70, 75, 80). row 5 + 3 = 8 <= 9 -> OK! var r_valid = inv.can_place_item_at(70, 3) _assert(r_valid["can_place"] == true, "Can place 3-slot item safely inside page 2") # Now unlock Stage 1 (slots 90..94 unlocked) inv.unlock_next_stage(1) # Try to place 2-slot item at slot 91 (needs 91 and 96; 91 is unlocked, but 96 is locked!) var r_part_locked = inv.can_place_item_at(91, 2) _assert(r_part_locked["error_code"] == "SLOT_LOCKED", "Reject multi-slot item when lower cell (96) is locked") # But 1-slot item at 91 is fine var r_single_ok = inv.can_place_item_at(91, 1) _assert(r_single_ok["can_place"] == true, "Single slot item at 91 can be placed") func _test_full_180_slots_unlock_completion() -> void: print("\n--- Test 6: Full 180 Slots Unlocking (All 18 Stages) ---") var inv = SystemClass.new() var total_keys_available := 50 # Unlock all 18 stages for s in range(18): var res = inv.unlock_next_stage(total_keys_available) _assert(res["success"] == true, "Stage %d unlocked successfully" % (s + 1)) total_keys_available = res["remaining_keys"] _assert(inv.unlocked_stages == 18, "All 18 stages unlocked") _assert(inv.get_unlocked_slot_count() == 180, "All 180 slots unlocked") _assert(inv.is_slot_unlocked(179) == true, "Final slot 179 is unlocked") _assert(total_keys_available == 50 - 37, "Remaining keys is 13 (50 - 37)") # Attempting 19th stage var r_max = inv.unlock_next_stage(total_keys_available) _assert(r_max["error_code"] == "ALREADY_MAX_EXPANDED", "Reject unlocking beyond 18 stages")