extends SceneTree const StateScript = preload("res://autoload/game_state.gd") const EconomyScript = preload("res://scripts/economy/economy_service.gd") const AdapterScript = preload("res://scripts/economy/ledger_backed_resource_state.gd") var _checks := 0 var _failures := 0 func _initialize() -> void: call_deferred("_run") func _run() -> void: print("S2: ledger-backed resource adapter") var state = StateScript.new() state.reset() var economy = EconomyScript.new({ &"PLAYER_CASH": false, &"CONSTRUCTION_EXPENSE": false, }) economy.initialize_account(&"PLAYER_CASH", state.get_resource(&"gold"), 360, &"initial-player") var minute := 400 var adapter = AdapterScript.new( state, economy, &"CONSTRUCTION_EXPENSE", &"CONSTRUCTION", &"CONSTRUCTION_REFUND", &"construction_service", func() -> int: return minute ) _expect(adapter.can_afford({&"gold": 500, &"materials": 8}), "combined ledger and material balances validate together") _expect(adapter.spend({&"gold": 500, &"materials": 8}), "construction cost commits through one resource contract") _expect(economy.get_balance(&"PLAYER_CASH") == 4500, "Gold spending changes the authoritative ledger balance") _expect(state.get_resource(&"gold") == 4500, "GameState Gold remains a read-compatible UI mirror") _expect(state.get_resource(&"materials") == 42, "non-Gold resources commit with the same spend") _expect(economy.get_balance(&"CONSTRUCTION_EXPENSE") == 500, "construction uses an explicit counter-account") var expense_entries: Array = economy.get_entries() _expect(expense_entries[-1].absolute_minute == 400 and expense_entries[-1].category == &"CONSTRUCTION", "ledger entry captures minute and construction category") minute = 410 _expect(adapter.apply_resource_deltas({&"gold": 125, &"materials": 2}), "demolition refund restores Gold and material atomically") _expect(economy.get_balance(&"PLAYER_CASH") == 4625 and state.get_resource(&"gold") == 4625, "refund keeps ledger and UI mirror equal") _expect(economy.get_balance(&"CONSTRUCTION_EXPENSE") == 375, "refund reduces its original expense counter-account") _expect(state.get_resource(&"materials") == 44, "material refund is applied once") var before: Dictionary = adapter.create_snapshot() _expect(not adapter.spend({&"gold": 10_000, &"materials": 1}), "insufficient Gold rejects a mixed spend") _expect(adapter.create_snapshot() == before, "rejected mixed spend changes neither ledger nor resources") _expect(not adapter.apply_resource_deltas({&"gold": 1000}), "refund cannot exceed the recorded expense balance") _expect(adapter.create_snapshot() == before, "failed refund rolls back every resource and ledger field") adapter.spend({&"gold": 100, &"materials": 1}) _expect(adapter.restore_snapshot(before), "adapter restores resource and economy snapshots together") _expect(adapter.create_snapshot() == before, "adapter snapshot round trip is exact") _expect(economy.validate_ledger()[&"ok"], "restored authoritative ledger still reconciles") state.free() if _failures == 0: print("PASS: %d checks" % _checks) else: push_error("FAIL: %d of %d checks failed" % [_failures, _checks]) quit(_failures) func _expect(condition: bool, label: String) -> void: _checks += 1 if condition: print(" ✓ %s" % label) return _failures += 1 push_error(" ✗ %s" % label)