Save The Tree implementation and acceptance work in progress
Preserve production code, regression fixtures, audio assets and provenance, test infrastructure, and the original-completion plan and progress ledger. Final game and Windows acceptance remain pending; excluded local artifacts and native experiments are not part of this snapshot.
This commit is contained in:
@@ -17,7 +17,7 @@ signal terminal_state_changed(old_state: StringName, new_state: StringName, reas
|
||||
|
||||
const CommandResultType = preload("res://scripts/core/command_result.gd")
|
||||
|
||||
const SNAPSHOT_VERSION := 4
|
||||
const SNAPSHOT_VERSION := 5
|
||||
const MIN_SUPPORTED_SNAPSHOT_VERSION := 1
|
||||
const MINUTES_PER_DAY := 1_440
|
||||
const DEMAND_INTERVAL_MINUTES := 60
|
||||
@@ -78,6 +78,8 @@ const DAILY_CATEGORIES: Array[StringName] = [
|
||||
&"construction_cash_flow",
|
||||
]
|
||||
|
||||
const FINANCING_CATEGORIES: Array[StringName] = [&"financing_principal_inflows", &"financing_principal_outflows"]
|
||||
|
||||
const DEFAULT_CONFIG := {
|
||||
&"world_seed": 1,
|
||||
&"population_cap": 100,
|
||||
@@ -102,6 +104,8 @@ var _origin_minute := 0
|
||||
# Historical insolvency evidence is retained without mixing it into new loss streaks.
|
||||
var _legacy_calendar_last_day := 0
|
||||
var _legacy_history_last_day := 0
|
||||
# Closed records from versions 1-4 retain their original principal-excluded basis.
|
||||
var _legacy_principal_profit_last_day := 0
|
||||
|
||||
var _config: Dictionary = DEFAULT_CONFIG.duplicate(true)
|
||||
var _demand_profiles: Dictionary = {}
|
||||
@@ -670,6 +674,7 @@ func create_snapshot() -> Dictionary:
|
||||
&"schema_version": SNAPSHOT_VERSION,
|
||||
&"legacy_calendar_last_day": _legacy_calendar_last_day,
|
||||
&"legacy_history_last_day": _legacy_history_last_day,
|
||||
&"legacy_principal_profit_last_day": _legacy_principal_profit_last_day,
|
||||
&"origin_minute": _origin_minute,
|
||||
&"current_minute": current_minute,
|
||||
&"config": _string_key_dictionary(_config),
|
||||
@@ -718,6 +723,7 @@ func restore_snapshot(snapshot: Dictionary) -> bool:
|
||||
# Atomic swap begins only after the entire candidate passed validation.
|
||||
_legacy_calendar_last_day = int(state[&"legacy_calendar_last_day"])
|
||||
_legacy_history_last_day = int(state[&"legacy_history_last_day"])
|
||||
_legacy_principal_profit_last_day = int(state[&"legacy_principal_profit_last_day"])
|
||||
_origin_minute = int(state[&"origin_minute"])
|
||||
current_minute = int(state[&"current_minute"])
|
||||
_config = (state[&"config"] as Dictionary).duplicate(true)
|
||||
@@ -766,6 +772,8 @@ func validate_invariants() -> Dictionary:
|
||||
errors.append({&"code": &"INVALID_CONFIG"})
|
||||
if _population_count < 0 or _population_count > int(_config[&"population_cap"]):
|
||||
errors.append({&"code": &"INVALID_POPULATION"})
|
||||
if _legacy_principal_profit_last_day < 0 or _legacy_principal_profit_last_day > _day_summaries.size():
|
||||
errors.append({&"code": &"INVALID_LEGACY_PRINCIPAL_PROFIT_MARKER"})
|
||||
if _arrears_total < 0 or _consecutive_insolvency_count < 0:
|
||||
errors.append({&"code": &"INVALID_INSOLVENCY_STATE"})
|
||||
if _terminal_state not in [TERMINAL_RUNNING, TERMINAL_BANKRUPT]:
|
||||
@@ -1531,7 +1539,7 @@ func _normalize_categories(source: Dictionary) -> Dictionary:
|
||||
return {&"ok": false, &"error": "Daily categories contain duplicate canonical keys."}
|
||||
for raw_key: Variant in source:
|
||||
if typeof(raw_key) not in [TYPE_STRING, TYPE_STRING_NAME] \
|
||||
or StringName(str(raw_key)) not in DAILY_CATEGORIES:
|
||||
or (StringName(str(raw_key)) not in DAILY_CATEGORIES and StringName(str(raw_key)) not in FINANCING_CATEGORIES):
|
||||
return {
|
||||
&"ok": false,
|
||||
&"error": "Unknown financial category requires explicit classification: %s" % raw_key,
|
||||
@@ -1546,6 +1554,13 @@ func _normalize_categories(source: Dictionary) -> Dictionary:
|
||||
&"error": "Daily category '%s' must be a non-negative integer." % category,
|
||||
}
|
||||
result[category] = int(value)
|
||||
for category: StringName in FINANCING_CATEGORIES:
|
||||
if not source.has(category) and not source.has(String(category)):
|
||||
continue
|
||||
var value: Variant = _value(source, category, null)
|
||||
if not _is_integral_value(value) or int(value) < 0 or int(value) > MAX_FINANCIAL_AMOUNT:
|
||||
return {&"ok": false, &"error": "Principal financing totals must be non-negative checked integers."}
|
||||
result[category] = int(value)
|
||||
return {&"ok": true, &"categories": result}
|
||||
|
||||
|
||||
@@ -1597,6 +1612,11 @@ func _default_daily_apply_result() -> Dictionary:
|
||||
|
||||
|
||||
func _net_profit(categories: Dictionary) -> int:
|
||||
# Original daily expenses include debt repayment; borrowed principal is not sales.
|
||||
return _principal_excluded_profit(categories) - int(categories.get(&"financing_principal_outflows", 0))
|
||||
|
||||
|
||||
func _principal_excluded_profit(categories: Dictionary) -> int:
|
||||
return int(categories.get(&"revenue", 0)) \
|
||||
- int(categories.get(&"refunds", 0)) \
|
||||
- int(categories.get(&"cost_of_goods", 0)) \
|
||||
@@ -1815,6 +1835,8 @@ func _current_snapshot_exact_shape_error(snapshot: Dictionary) -> String:
|
||||
]
|
||||
if int(_value(snapshot, &"schema_version", 0)) >= 4:
|
||||
top_keys.append_array([&"legacy_calendar_last_day", &"legacy_history_last_day"])
|
||||
if int(_value(snapshot, &"schema_version", 0)) >= 5:
|
||||
top_keys.append(&"legacy_principal_profit_last_day")
|
||||
if not _dictionary_has_exact_string_keys(snapshot, top_keys):
|
||||
return "Operations snapshot has missing or unknown root fields."
|
||||
|
||||
@@ -2170,7 +2192,19 @@ func _parse_snapshot(snapshot: Dictionary) -> Dictionary:
|
||||
for day in range(1, legacy_history + 1):
|
||||
if not (histories[&"day_summaries"] as Dictionary).has(day):
|
||||
return {&"ok": false, &"error": "Missing legacy financial history."}
|
||||
var last_closed_day := 0
|
||||
for day: int in histories[&"day_summaries"]:
|
||||
last_closed_day = maxi(last_closed_day, day)
|
||||
var legacy_principal := last_closed_day
|
||||
if version >= 5:
|
||||
var principal_value: Variant = _value(snapshot, &"legacy_principal_profit_last_day", null)
|
||||
if not _is_integral_value(principal_value):
|
||||
return {&"ok": false, &"error": "Legacy principal profit marker must be an integer."}
|
||||
legacy_principal = int(principal_value)
|
||||
if legacy_principal < 0 or legacy_principal > last_closed_day:
|
||||
return {&"ok": false, &"error": "Legacy principal profit marker exceeds closed history."}
|
||||
var state := {
|
||||
&"legacy_principal_profit_last_day": legacy_principal,
|
||||
&"legacy_calendar_last_day": legacy_calendar,
|
||||
&"legacy_history_last_day": legacy_history,
|
||||
&"origin_minute": restored_origin,
|
||||
@@ -2206,6 +2240,7 @@ func _parse_snapshot(snapshot: Dictionary) -> Dictionary:
|
||||
var candidate := OperationsCoordinator.new(state[&"config"])
|
||||
candidate._legacy_calendar_last_day = legacy_calendar
|
||||
candidate._legacy_history_last_day = legacy_history
|
||||
candidate._legacy_principal_profit_last_day = legacy_principal
|
||||
candidate._origin_minute = restored_origin
|
||||
candidate.current_minute = restored_minute
|
||||
candidate._config = (state[&"config"] as Dictionary).duplicate(true)
|
||||
@@ -2541,7 +2576,8 @@ func _validate_financial_history(errors: Array[Dictionary]) -> void:
|
||||
if not bool(categories[&"ok"]):
|
||||
errors.append({&"code": &"INVALID_DAY_CATEGORIES", &"day": day})
|
||||
continue
|
||||
var net := _net_profit(categories[&"categories"])
|
||||
var net := _principal_excluded_profit(categories[&"categories"]) \
|
||||
if day <= _legacy_principal_profit_last_day else _net_profit(categories[&"categories"])
|
||||
if net != int(_value(summary, &"net_profit", 0)):
|
||||
errors.append({&"code": &"NET_PROFIT_MISMATCH", &"day": day})
|
||||
var difference_value: Variant = _value(summary, &"reconciliation_difference", null)
|
||||
@@ -3156,3 +3192,7 @@ func _boundary_failure(code: StringName, report: Dictionary) -> CommandResult:
|
||||
"An operations boundary failed without committing coordinator state.",
|
||||
{&"boundary": report.duplicate(true)}
|
||||
)
|
||||
|
||||
|
||||
func is_legacy_principal_profit_history(day: int) -> bool:
|
||||
return day > 0 and day <= _legacy_principal_profit_last_day
|
||||
|
||||
Reference in New Issue
Block a user