e48d4bbe88
- Introduced a new benchmark save script to create a stress test scenario with extreme values for simulation performance. - Added a full UI benchmark script to measure frame rates and performance metrics during UI interactions. - Implemented tests for coarse generations to ensure population transitions are handled correctly. - Created tests for extra parameters to validate the loading and application of configuration settings. - Developed simulation optimization tests to verify the efficiency of population drift and rounding mechanisms. - Added split optimization tests to ensure accurate allocation and rounding behavior in population management. - Included startup parameter tests to confirm the correct initialization of global parameters before scene readiness. - Enhanced the audit rounding ledger to compare selective and full rounding results for consistency.
158 lines
6.2 KiB
GDScript
158 lines
6.2 KiB
GDScript
extends Node
|
|
class_name OwniverseEntity
|
|
const E = preload("res://world/owniverse/math/exact.gd")
|
|
const QuantityMath = preload("res://world/owniverse/quantity_math.gd")
|
|
|
|
var id: String
|
|
var is_visible: bool = false
|
|
var unlock: Dictionary = {}
|
|
var cost: Dictionary = {}
|
|
var bind: Dictionary = {}
|
|
var mass: Variant
|
|
var space: int
|
|
var life_rule: Dictionary = {}
|
|
var life_fall_weights: Dictionary = {}
|
|
var generation_plan: Dictionary = {}
|
|
var lifespan: Variant
|
|
var lifespan_delta: Variant
|
|
var auto: Variant
|
|
var gamma: Variant
|
|
var blast: int
|
|
var blastability: bool = false
|
|
var life_product: Dictionary = {}
|
|
var product_per_year_type: String = ""
|
|
var product_per_year_amount: Variant = 0
|
|
var voids: int
|
|
var output_or: Dictionary = {}
|
|
var output_and: Dictionary = {}
|
|
var destroy_level: int
|
|
var degradation: Dictionary = {}
|
|
var planets: Dictionary = {}
|
|
var count_as: String
|
|
var group_as: String
|
|
var event_group: String
|
|
var space_bonus: Variant
|
|
var civ_bonus: Variant
|
|
var claim: String
|
|
|
|
var amount: Variant = 0
|
|
|
|
|
|
func _init(values: Dictionary) -> void:
|
|
id = values.id
|
|
is_visible = E.eq(values.is_visible, "1")
|
|
unlock = _parse_and_string(values.unlock)
|
|
cost = _parse_and_string(values.cost)
|
|
bind = _parse_and_string(values.bind)
|
|
#print(id, " | ", cost, " | ", bind)
|
|
mass = E.of(values.mass)
|
|
space = E.integer(values.space)
|
|
life_rule = Global.LifeRules.get(id, {}).duplicate(true)
|
|
if Global.CivilizationRules.has(id):
|
|
life_rule = {"ethical": true, "span": Global.CivilizationRules[id].span}
|
|
elif not life_rule.is_empty():
|
|
life_fall_weights = QuantityMath.rule_weights(str(life_rule.get("fall", "")))
|
|
lifespan = (E.of(life_rule.span) if (not life_rule.is_empty()) else E.of(values.lifespan))
|
|
lifespan_delta = (E.divide(lifespan, Global.batch_count) if E.gt(lifespan, 10) else lifespan)
|
|
auto = E.of(values.auto)
|
|
gamma = E.of(values.gamma if str(values.gamma).is_valid_float() else "0")
|
|
blast = E.integer(values.blast)
|
|
blastability = E.eq(str(values.get("blastability", "")), "1")
|
|
|
|
life_product = _parse_and_string(values.life_product)
|
|
for key in life_product.keys():
|
|
product_per_year_type = key
|
|
product_per_year_amount = (E.divide(life_product[key], lifespan) if E.ne(lifespan, 0) else 0)
|
|
#print(id, " | ", lifespan_delta, " | ", lifespan)
|
|
|
|
voids = E.integer(values.voids)
|
|
output_or = _parse_or_string(values.output)
|
|
output_and = _parse_and_string(values.output)
|
|
destroy_level = E.integer(values.destroy_level)
|
|
degradation = _parse_and_string(values.degradation)
|
|
planets = _parse_planet_string(values.planets)
|
|
count_as = values.count_as
|
|
group_as = values.group_as
|
|
event_group = values.event_group
|
|
space_bonus = E.of(values.space_bonus)
|
|
civ_bonus = E.of(values.civ_bonus)
|
|
claim = values.claim
|
|
refresh_generation_plan()
|
|
|
|
|
|
func refresh_generation_plan() -> void:
|
|
var fall_text: String = str(life_rule.get("fall", ""))
|
|
if not generation_plan.is_empty() \
|
|
and E.eq(generation_plan.outputs, output_and) \
|
|
and E.eq(generation_plan.chance, output_or.get("chance", 0)) \
|
|
and E.eq(generation_plan.positive, output_or.get("positive", "")) \
|
|
and E.eq(generation_plan.negative, output_or.get("negative", "")) \
|
|
and E.eq(generation_plan.blast, blast) \
|
|
and E.eq(generation_plan.life_progress, life_rule.get("progress", 0)) \
|
|
and E.eq(generation_plan.life_degradation, life_rule.get("degradation", 0)) \
|
|
and E.eq(generation_plan.life_next, str(life_rule.get("next", id))) \
|
|
and E.eq(generation_plan.life_fall_text, fall_text):
|
|
return
|
|
life_fall_weights = QuantityMath.rule_weights(fall_text) if not fall_text.is_empty() else {}
|
|
generation_plan = {
|
|
"life": not life_rule.is_empty(),
|
|
"life_progress": E.of(life_rule.get("progress", 0)),
|
|
"life_degradation": E.of(life_rule.get("degradation", 0)),
|
|
"life_next": str(life_rule.get("next", id)),
|
|
"life_fall": life_fall_weights,
|
|
"outputs": output_and,
|
|
"chance": output_or.get("chance", 0),
|
|
"positive": output_or.get("positive", ""),
|
|
"negative": output_or.get("negative", ""),
|
|
"life_fall_text": fall_text,
|
|
"positive_terms": QuantityMath.output_terms(str(output_or.get("positive", ""))),
|
|
"negative_terms": QuantityMath.output_terms(str(output_or.get("negative", ""))),
|
|
"blast": blast,
|
|
"destroy_level": destroy_level
|
|
}
|
|
generation_plan.make_read_only()
|
|
|
|
|
|
func _parse_or_string(source_line: String) -> Dictionary:
|
|
var result = {}
|
|
if source_line.contains("^"):
|
|
var first_split = source_line.split("^")
|
|
var second_split = first_split[1].split("%")
|
|
var probability = E.of(second_split[1])
|
|
result["chance"] = probability
|
|
result["positive"] = second_split[0]
|
|
result["negative"] = first_split[0]
|
|
|
|
return result
|
|
|
|
|
|
func _parse_and_string(source_line: String) -> Dictionary:
|
|
var result = {}
|
|
var first_split = source_line.split("&")
|
|
|
|
for elem in first_split:
|
|
var second_split = elem.split(":")
|
|
if E.eq(len(second_split), 2):
|
|
result[second_split[0]] = E.of(second_split[1])
|
|
|
|
return result
|
|
|
|
func _parse_planet_string(source_line: String) -> Dictionary:
|
|
var result = {}
|
|
for elem in source_line.split("&", false):
|
|
var parts: PackedStringArray = elem.strip_edges().split(":")
|
|
if (E.ne(parts.size(), 3) or parts[0].strip_edges().is_empty()):
|
|
push_warning(("Invalid planet definition for %s: %s" % [id, elem]))
|
|
continue
|
|
if ((not parts[1].is_valid_float()) or (not parts[2].is_valid_float())):
|
|
push_warning(("Invalid planet numbers for %s: %s" % [id, elem]))
|
|
continue
|
|
var count: Variant = E.of(parts[1])
|
|
var chance: Variant = E.of(parts[2])
|
|
if ((((((not E.finite(count)) or (not E.finite(chance))) or E.lt(count, 0)) or E.ne(count, E.floor_value(count))) or E.lt(chance, 0)) or E.gt(chance, 1)):
|
|
push_warning(("Planet values out of range for %s: %s" % [id, elem]))
|
|
continue
|
|
# Planet chances are fractions (0.01 = 1%), unlike output_or percentages.
|
|
result[parts[0].strip_edges()] = {"amount": count, "chance": chance}
|
|
return result
|