2026-09-16 07:58:19 +03:00
|
|
|
extends SceneTree
|
2026-09-30 08:08:27 +03:00
|
|
|
const E = preload("res://world/owniverse/math/exact.gd")
|
2026-09-16 07:58:19 +03:00
|
|
|
const Clock = preload("res://world/owniverse/simulation_time.gd")
|
|
|
|
|
var checks: int = 0
|
|
|
|
|
var failures: int = 0
|
|
|
|
|
|
|
|
|
|
func _initialize() -> void:
|
|
|
|
|
call_deferred("run")
|
|
|
|
|
|
|
|
|
|
func check(condition: bool, message: String) -> void:
|
2026-09-30 08:08:27 +03:00
|
|
|
checks = E.add(checks, 1)
|
|
|
|
|
if (not condition):
|
|
|
|
|
failures = E.add(failures, 1)
|
2026-09-16 07:58:19 +03:00
|
|
|
push_error(message)
|
|
|
|
|
|
|
|
|
|
func fixture():
|
|
|
|
|
var world = load("res://world/owniverse/owniverse.gd").new()
|
|
|
|
|
var global: Node = root.get_node("Global")
|
|
|
|
|
for id in global.OwniverseEntities:
|
|
|
|
|
var entity = load("res://world/owniverse/owniverse_entity.gd").new(global.OwniverseEntities[id])
|
2026-09-29 20:23:20 +03:00
|
|
|
world.catalog.entities[id] = entity
|
2026-09-30 08:08:27 +03:00
|
|
|
world.state.amount[id] = 0
|
|
|
|
|
world.state.stats.total_amount[id] = 0
|
|
|
|
|
if E.ne(entity.group_as, ""):
|
|
|
|
|
world.state.amount[entity.group_as] = 0
|
|
|
|
|
world.state.stats.total_amount[entity.group_as] = 0
|
2026-09-29 20:23:20 +03:00
|
|
|
world.catalog.entities["N"].life_product = {}
|
|
|
|
|
world.catalog.entities["N"].product_per_year_type = "H"
|
2026-09-30 08:08:27 +03:00
|
|
|
world.catalog.entities["N"].product_per_year_amount = 10
|
|
|
|
|
world.catalog.entities["N"].auto = 0
|
|
|
|
|
world.state.amount.N = 1
|
2026-09-16 07:58:19 +03:00
|
|
|
return world
|
|
|
|
|
|
|
|
|
|
func dispose(world) -> void:
|
2026-09-29 20:23:20 +03:00
|
|
|
for entity in world.catalog.entities.values():
|
2026-09-16 07:58:19 +03:00
|
|
|
entity.free()
|
|
|
|
|
world.free()
|
|
|
|
|
|
|
|
|
|
func run() -> void:
|
|
|
|
|
var world = fixture()
|
2026-10-05 22:16:59 +03:00
|
|
|
world.catalog.entities.N.lifespan = 100
|
|
|
|
|
world.batches.append_batch(world.state, "N", 2, 10, 10)
|
|
|
|
|
world.batches.append_batch(world.state, "N", 3, 10, 10)
|
|
|
|
|
check(world.state.batches.N.size() == 1 and E.eq(world.state.batches.N[0].amount, 5), "Repeated insertion merges using the cohort index")
|
|
|
|
|
world.batches.append_batch(world.state, "N", 1, 0, 0)
|
|
|
|
|
check(E.eq(world.state.batches.N[0].created_from, 0), "Earlier insertion preserves chronological order")
|
|
|
|
|
var replaced: Array = world.state.batches.N.duplicate(true)
|
|
|
|
|
world.state.batches.N = replaced
|
|
|
|
|
world.batches.append_batch(world.state, "N", 7, 10, 10)
|
|
|
|
|
check(E.eq(replaced[1].amount, 12), "Replacing cohort array invalidates cached references")
|
|
|
|
|
var separate: Dictionary = world.state.duplicate(true)
|
|
|
|
|
world.batches.append_batch(separate, "N", 9, 10, 10)
|
|
|
|
|
check(E.eq(separate.batches.N[1].amount, 21) and E.eq(world.state.batches.N[1].amount, 12), "Index is isolated between transaction states")
|
|
|
|
|
dispose(world)
|
|
|
|
|
world = fixture()
|
|
|
|
|
for speed in range(1, 7):
|
|
|
|
|
world.state.speed = speed
|
|
|
|
|
check(E.eq(world.batches.window_duration(world.state, 100), 2.5 if speed < 4 else pow(10, speed - 2)), "Windows follow selected speed")
|
|
|
|
|
check(E.eq(world.batches.window_duration(world.state, 5), 5), "Short explosions retain their timing")
|
|
|
|
|
var huge: Variant = E.of("10000000000000000000000000000000000000000")
|
|
|
|
|
world.catalog.entities.N.lifespan = 100
|
|
|
|
|
world.state.batches.N = [
|
|
|
|
|
{"amount": huge, "start_year": 100, "end_year": 110, "created_from": 0, "created_to": 10, "withdraw_remainder": 0.25},
|
|
|
|
|
{"amount": 7, "start_year": 120, "end_year": 130, "created_from": 20, "created_to": 30, "withdraw_remainder": 0.5}
|
|
|
|
|
]
|
|
|
|
|
world.batches.coarsen(world.state)
|
|
|
|
|
check(world.state.batches.N.size() == 1, "High speed combines nearby cohorts")
|
|
|
|
|
check(E.eq(world.state.batches.N[0].amount, E.add(huge, 7)), "Coarsening preserves exact large whole counts")
|
|
|
|
|
check(E.eq(world.state.batches.N[0].withdraw_remainder, 0.75), "Coarsening preserves withdrawal carry")
|
|
|
|
|
var combined: Dictionary = world.state.batches.N[0].duplicate(true)
|
|
|
|
|
world.batches.coarsen(world.state)
|
|
|
|
|
check(world.state.batches.N[0] == combined, "Coarsening is idempotent")
|
|
|
|
|
world.state.speed = 1
|
|
|
|
|
world.batches.coarsen(world.state)
|
|
|
|
|
check(world.state.batches.N[0] == combined, "Slowing down does not invent finer history")
|
|
|
|
|
dispose(world)
|
|
|
|
|
world = fixture()
|
2026-09-30 08:08:27 +03:00
|
|
|
world.state.batch_origins.LGRB = E.of("10357034.80000000074505806")
|
|
|
|
|
var boundary: Variant = E.of("41215289.79999999701976776")
|
|
|
|
|
for interval in [[E.subtract(boundary, E.of("2.5")), E.add(boundary, E.of("2.25"))], [boundary, E.add(boundary, 2)]]:
|
2026-09-16 07:58:19 +03:00
|
|
|
world.state.batches.LGRB = []
|
2026-09-30 08:08:27 +03:00
|
|
|
world.batches.append_batch(world.state, "LGRB", 100, interval[0], interval[1])
|
|
|
|
|
var total: Variant = 0
|
|
|
|
|
var last: Variant = E.neg(INF)
|
|
|
|
|
for batch : Dictionary in world.state.batches.LGRB:
|
|
|
|
|
total = E.add(total, batch.amount)
|
|
|
|
|
check(E.gt(batch.created_from, last), "Batch windows advance monotonically")
|
|
|
|
|
check(E.gt(batch.created_to, batch.created_from), "Positive window duration")
|
|
|
|
|
check(E.ge(batch.amount, 0), "No negative batch amounts")
|
2026-09-16 07:58:19 +03:00
|
|
|
last = batch.created_from
|
2026-09-30 08:08:27 +03:00
|
|
|
check(E.eq(total, 100), "Boundary correction preserves all objects")
|
|
|
|
|
check(E.le(world.state.batches.LGRB.size(), 7), "Finite number of windows")
|
2026-09-16 07:58:19 +03:00
|
|
|
dispose(world)
|
2026-10-05 22:16:59 +03:00
|
|
|
world = fixture()
|
|
|
|
|
world.batches.append_batch(world.state, "N", 100, 100, 100)
|
|
|
|
|
var first: Dictionary = world.state.batches.N[0].duplicate(true)
|
|
|
|
|
world.batches.append_batch(world.state, "N", 7, 100, 100)
|
|
|
|
|
check(world.state.batches.N.size() == 1 and E.eq(world.state.batches.N[0].amount, 107), "Repeated births merge directly into one window")
|
|
|
|
|
check(E.eq(world.state.batches.N[0].start_year, first.start_year), "Direct merge preserves transition time")
|
|
|
|
|
check(world.batches.withdraw_batches(world.state, "N", 0).is_empty(), "Future cohorts are not withdrawn")
|
|
|
|
|
var untouched: Array = world.state.batches.N
|
|
|
|
|
check(world.batches.withdraw_batches(world.state, "N", 1).is_empty() and is_same(untouched, world.state.batches.N), "Readiness index skips future cohorts")
|
|
|
|
|
world.state.batches.N = [{"amount": 7, "start_year": 0, "end_year": 0, "created_from": 0, "created_to": 0}]
|
|
|
|
|
check(world.batches.withdraw_batches(world.state, "N", 1).size() == 1, "Replacing cohorts invalidates readiness index")
|
|
|
|
|
world.batches.append_batch(world.state, "N", 3, 100, 100)
|
|
|
|
|
check(E.eq(world.state.batches.N[0].amount, 3), "Replacing cohorts invalidates instant merge cache")
|
|
|
|
|
world.batches.withdraw_batches(world.state, "N", 0)
|
|
|
|
|
world.batches.scale_batches(world.state, "N", 0)
|
|
|
|
|
world.batches.withdraw_batches(world.state, "N", 1)
|
|
|
|
|
check(world.state.batches.N.is_empty(), "Scaling invalidates readiness and removes zero cohorts")
|
|
|
|
|
dispose(world)
|
2026-09-30 08:08:27 +03:00
|
|
|
print(("Batch boundaries: %d checks, %d failures" % [checks, failures]))
|
|
|
|
|
quit((0 if E.eq(failures, 0) else 1))
|