Files
owniverse/world/owniverse/item_description.gd
T
Kirill fb8a3f5658 Add exact arithmetic implementation and tests
- Introduced exact arithmetic with support for large integers and fractions in `exact.gd`, `big_integer.gd`, and `exact_value.gd`.
- Implemented a comprehensive test suite in `test_exact_math.gd` to validate arithmetic operations against expected results.
- Added a README in `math` directory to document the exact arithmetic system and its usage.
- Ensured that all arithmetic operations maintain precision without floating-point errors, using a custom representation for large numbers.
- Included methods for encoding and decoding exact values for serialization.
2026-09-30 08:08:27 +03:00

91 lines
5.6 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
extends RefCounted
const E = preload("res://world/owniverse/math/exact.gd")
const GREEN = "#40cc40"
const RED = "#ff6060"
const GREY = "#888888"
const Parameters = preload("res://world/owniverse/world_parameters.gd")
static func number(value, digits: int = 0) -> String:
if not E.finite(value): return "—"
return E.scientific(value, 4) if E.ge(E.absolute(value), 100000) else E.fixed(value, digits)
static func colored(text: String, color: String) -> String:
return E.add(E.add(E.add(E.add("[color=", color), "]"), text), "[/color]")
static func matches(world, id: String) -> Array:
var result: Array = []
for key in world.catalog.entities:
var entity = world.catalog.entities[key]
if ((E.eq(key, id) or E.eq(entity.count_as, id)) or E.eq(entity.group_as, id)):
if (not world.catalog.is_group(key)):
result.append(key)
return result
static func quantities(world, id: String) -> Dictionary:
var free: Variant = 0
var total: Variant = 0
var physical: Dictionary = world.ledger.physical_amounts(world.state)
for key in matches(world, id):
free = E.add(free, world.state.amount.get(key, 0))
total = E.add(total, physical.get(key, 0))
if E.eq(id, "SMBH"):
free = world.state.amount.get(id, 0)
total = free
return {"free": free, "total": total}
static func costs(world, global: Node, id: String) -> String:
if (not world.catalog.entities.has(id)):
return ""
var lines: PackedStringArray = []
for requirements in [world.catalog.entities[id].cost, world.catalog.entities[id].bind]:
for resource in requirements:
var required: Variant = requirements[resource]
if E.lt(required, 0):
continue
var available: Variant = E.floor_value(world.ledger.available(world.state, resource))
var name: String = str(global.get_template(resource, "Entity", "Name").get("text", resource))
lines.append(colored(E.add(E.add(E.add(E.add(E.add(name, ": "), number(required)), " ("), number(available)), ")"), (GREEN if E.ge(available, required) else RED)))
return "\n".join(lines)
static func variables(world, global: Node, id: String, rate: Variant = 0.0) -> Dictionary:
var counts: Dictionary = quantities(world, id)
var show_total: bool = false
for key in matches(world, id):
show_total = (show_total or E.eq(world.catalog.entities[key].group_as, "Planet"))
var amount: String = (number((counts.total if show_total else counts.free)) if world.catalog.entities.has(id) else "—")
if ((not show_total) and E.gt(counts.total, counts.free)):
amount = E.add(amount, E.add(" ", colored(E.add(E.add("(", number(counts.total)), ")"), GREY)))
if E.ne(rate, 0):
amount = E.add(amount, E.add(" | ", colored(E.add((("−" if E.lt(rate, 0) else "+")), number(E.absolute(rate), 1)), (RED if E.lt(rate, 0) else GREEN))))
var physical: Dictionary = world.ledger.physical_amounts(world.state)
var voids: Variant = 0
for key in physical:
voids = E.add(voids, E.multiply(physical[key], world.catalog.entities[key].voids))
var he: Variant = world.state.amount.get("He", 0)
var h: Variant = world.state.amount.get("H", 0)
var mixture: String = "—"
if E.gt(E.add(he, h), 0):
mixture = E.add(E.add(E.add(E.add("He: ", number(E.divide(E.multiply(100, he), (E.add(he, h))), 2)), "% / H: "), number(E.divide(E.multiply(100, h), (E.add(he, h))), 2)), "%")
var environment: Dictionary = world.environment.stellar_environment(world.state)
return {"amount": amount, "colored costs": costs(world, global, id), "lifespan": (number(world.catalog.entities[id].lifespan) if world.catalog.entities.has(id) else "—"), "voids": number(voids), "he / h": E.add("\n", mixture), "metallicity": E.add(number(E.multiply(environment.metallicity, 100), 2), "%"), "энергия": number(world.state.energy), "плотность": number(environment.density, 6), "лет в секунду": number(world.state.speed_in_year), "amount1": "—", "amount2": "—", "amount3": "—", "amount4": "—"}
static func render(world, global: Node, id: String, category: String = "Entity", rate: Variant = 0.0) -> String:
var values: Dictionary = variables(world, global, id, rate)
if E.eq(category, "Indicator"):
if E.eq(id, "Density"):
id = Parameters.density_display(world.environment.stellar_environment(world.state).density).mode
var scales: Dictionary = {"Burnability": "Bur", "Explosiveness": "Exp", "Aggression": "Agg"}
if scales.has(id):
var level: Variant = Parameters.value(world.state, scales[id])
values.amount = number(level, (1 if E.ne(level, E.floor_value(level)) else 0))
values.scale = global.render_template(global.get_template(E.add("Scale", str(clampi(E.integer(E.round_value(level)), 1, 19))), "Indicator", "Scale"), {})
if E.eq(id, "Trends"):
for trend in Parameters.TRENDS:
values[trend.to_lower()] = E.add(number(E.multiply(world.state.get("trends", {}).get(trend, 0), 100), 2), "%")
if E.eq(id, "Energy"):
values["энергия"] = E.add(E.add(E.add(number(world.state.energy), " ("), number(E.multiply(E.clamp_value(E.divide(world.state.energy, Parameters.INITIAL_ENERGY), 0, 1), 100), 2)), "%)")
var title: String = global.render_template(global.get_template(id, category, "Name"), values)
var body: String = global.render_template(global.get_template(id, category, "Description"), values)
return E.add(E.add(E.add("[b]", ((title if E.ne(title, "") else id))), "[/b]\n"), body)