befb377774
- Added cosmic_unicorns.ogg - Added funky_eldritch.ogg - Added meditative_beings.ogg - Added owniverse_main_theme.ogg These tracks enhance the audio experience of the project.
97 lines
5.5 KiB
GDScript
97 lines
5.5 KiB
GDScript
extends SceneTree
|
|
|
|
const E = preload("res://world/owniverse/math/exact.gd")
|
|
const Q = preload("res://world/owniverse/quantity_math.gd")
|
|
const Clock = preload("res://world/owniverse/simulation_time.gd")
|
|
var checks: int = 0
|
|
var failures: int = 0
|
|
|
|
func _initialize():
|
|
call_deferred("run")
|
|
|
|
func check(actual, expected: String, label: String):
|
|
checks += 1
|
|
if str(actual) != expected:
|
|
failures += 1
|
|
push_error(label + ": " + str(actual) + " != " + expected)
|
|
|
|
func check_number(actual, expected: String, label: String):
|
|
var reference = E.of(expected)
|
|
checks += 1
|
|
if E.gt(E.absolute(E.subtract(actual, reference)), E.of("1e-12")):
|
|
failures += 1
|
|
push_error(label + ": " + str(actual) + " != " + expected)
|
|
|
|
func run():
|
|
# Expected strings were generated independently with Python fractions.Fraction.
|
|
var cases = JSON.parse_string(FileAccess.get_file_as_string("res://tests/fixtures/exact_oracle.json"))
|
|
for row in cases:
|
|
var a = E.of(row[0])
|
|
var b = E.of(row[1])
|
|
check_number(E.add(a, b), row[2], "sum")
|
|
check_number(E.subtract(a, b), row[3], "difference")
|
|
check_number(E.multiply(a, b), row[4], "product")
|
|
check_number(E.divide(a, b), row[5], "quotient")
|
|
check(E.floor_value(E.divide(a, b)), row[6], "floor")
|
|
for text in ["9223372036854775807", "-9223372036854775808", "9007199254740993", "1000000000000000000000000001", "-1/10000000000000"]:
|
|
var value = E.of(text)
|
|
check(E.eq(E.decode(JSON.parse_string(JSON.stringify(E.encode(value)))), value), "true", "JSON round trip")
|
|
check(E.add(E.of("9223372036854775807"), 1), "9223372036854775808", "int64 overflow promoted")
|
|
check(E.subtract(E.of("-9223372036854775808"), 1), "-9223372036854775809", "int64 underflow promoted")
|
|
check(Q.production_step([E.of("1e27")]), "1", "large integral recipe")
|
|
check(Q.production_step([E.of("1e-13")]), "10000000000000", "tiny fractional recipe")
|
|
var count = E.of("1000000000000000000000000001")
|
|
var allocation = Q.allocate_whole({"a": count, "b": count, "c": count}, count)
|
|
check(Q.sum(allocation), str(count), "allocation conserves every unit")
|
|
check(allocation.a, "333333333333333333333333334", "deterministic remainder")
|
|
var clock = Clock.advance({"datetime": E.of("1e27")}, 0.000000001, 1)
|
|
check_number(E.subtract(clock.datetime, E.of("1e27")), "1/1000000000", "single tick at huge age")
|
|
var world = load("res://world/owniverse/owniverse.gd").new()
|
|
world.catalog.load_definitions(root.get_node("Global").OwniverseEntities)
|
|
for id in world.catalog.entities:
|
|
world.state.amount[id] = 0
|
|
world.state.stats.total_amount[id] = 0
|
|
var group: String = world.catalog.entities[id].group_as
|
|
if group != "":
|
|
world.state.amount[group] = 0
|
|
world.state.stats.total_amount[group] = 0
|
|
world.production.produce_hs("H", 1)
|
|
check(world.state.energy, "999999999999999999999999999", "spend one energy")
|
|
var life = world.life.life_products(world.state, world.catalog.entities.EON5, count)
|
|
check(Q.sum(life), str(count), "life conservation at 1e27")
|
|
check(E.bounded(count), str(count), "integer counts never quantized")
|
|
check(E.mul_div(E.of("1e27"), 15, 100), "150000000000000000000000000", "exact percentage")
|
|
check(E.mul_div(count, count, count), str(count), "fused product beyond storage range")
|
|
check(E.subtract(E.add(count, 1), count), "1", "single unit at E27")
|
|
check(E.floor_value(E.divide(E.subtract(count, 1), count)), "0", "division must not round up a whole object")
|
|
check(E.fixed(E.add(count, E.of("0.125")), 3), "1000000000000000000000000001.125", "formatting without oversized intermediate")
|
|
check(E.scientific(E.of("9.999999e27"), 2), "1.00E+28", "display rounding at upper boundary")
|
|
check(E.eq(E.power(10, -100), E.of("1e-100")), "true", "negative power needs no huge intermediate")
|
|
var largest = E.of("9999999999999999999999999999")
|
|
check(E.eq(E.decode(E.encode(largest)), largest), "true", "upper range round trip")
|
|
check(E.valid_encoded(E.encode(largest)), "true", "upper range encoding valid")
|
|
for tiny in ["1e-13", "1e-20", "1e-100", "1e-310"]:
|
|
var value = E.of(tiny)
|
|
check(E.gt(value, 0), "true", "tiny fraction remains nonzero")
|
|
check(E.eq(value, E.decode(JSON.parse_string(JSON.stringify(E.encode(value))))), "true", "tiny float round trip")
|
|
for invalid in [{"$fixed": ["0", "0", "ffffffffffffffff", 1]}, {"$fixed": ["0", "-1", "0000000000000000", 1]}, {"$exact": "1/3"}, {"$exact": "10000000000000000000000000000"}, 1e100]:
|
|
check(E.valid_encoded(invalid), "false", "reject invalid saved number")
|
|
world.state.amount.S = E.of("1e24")
|
|
world.state.amount.H = E.of("1e24")
|
|
world.state.amount.RD = 1234567
|
|
world.state.amount.YD = 765432
|
|
world.state.amount.STN = 654321
|
|
world.speed = 6
|
|
var started: int = Time.get_ticks_msec()
|
|
for i in 100:
|
|
world.state.amount.RD = E.add(world.state.amount.RD, i + 1)
|
|
world.evolute(0.1)
|
|
check(str(world.state.auto_star_deficits).length() < 500, "true", "fraction storage stays bounded")
|
|
print("100 changing-composition cycles: %d ms" % (Time.get_ticks_msec() - started))
|
|
var saves = root.get_node("SaveManager")
|
|
check(saves.validate_data({"format_version": 4, "app_version": "", "ui": {"current_page": 0}, "state": world.state}), "", "long-running state saves")
|
|
for entity in world.catalog.entities.values(): entity.free()
|
|
world.free()
|
|
print("Exact math: %d checks, %d failures" % [checks, failures])
|
|
quit(0 if failures == 0 else 1)
|