76 lines
3.3 KiB
GDScript
76 lines
3.3 KiB
GDScript
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)
|