Refactor capacity enforcement and production logic
- Updated `enforce_capacity` function to accept an optional `physical` parameter, allowing for more flexible handling of physical amounts. - Modified `initialize_life_batches` to return physical amounts after enforcing capacity, improving data flow. - Enhanced `try_production` to utilize shared physical amounts, reducing redundant calculations. - Adjusted `stellar_environment` to accept an optional `quantities` parameter, streamlining its usage. - Added new test results for physical totals to validate performance improvements across various scenarios.
This commit is contained in:
@@ -116,7 +116,8 @@ func produce_for_period(previous: Dictionary, target: Dictionary, quantities: Di
|
||||
var order: Array = candidates.keys()
|
||||
order.sort_custom(func ( a : String , b : String ) -> bool : return (E.lt(candidates[a], candidates[b]) if E.ne(candidates[a], candidates[b]) else E.lt(a, b)))
|
||||
var created: Dictionary = {}
|
||||
var metallicity: Variant = world.environment.stellar_environment(target).metallicity
|
||||
var current_quantities: Dictionary = world.ledger.physical_amounts(target)
|
||||
var metallicity: Variant = world.environment.stellar_environment(target, current_quantities).metallicity
|
||||
var total_created: Variant = 0
|
||||
for id in order:
|
||||
var entity: OwniverseEntity = world.catalog.entities[id]
|
||||
@@ -128,7 +129,7 @@ func produce_for_period(previous: Dictionary, target: Dictionary, quantities: Di
|
||||
var actual: Variant = E.minimum(desired, auto_capacity(target, entity, budget))
|
||||
if E.le(actual, 0):
|
||||
continue
|
||||
if (not world.production.try_production(target, entity, actual, true)):
|
||||
if (not world.production.try_production(target, entity, actual, true, current_quantities)):
|
||||
continue
|
||||
budget = ordinary_star_budget(target)
|
||||
created[id] = actual
|
||||
|
||||
@@ -6,9 +6,9 @@ const ETHICS = State.ETHICS
|
||||
const OPPOSITE = {"m": "l", "l": "m", "w": "d", "d": "w", "c": "b", "b": "c"}
|
||||
|
||||
# Cache the weighted float worship rate multiplied by the exact population.
|
||||
static func worship(world, target: Dictionary, rules: Dictionary) -> Variant:
|
||||
static func worship(world, target: Dictionary, rules: Dictionary, physical: Dictionary = {}) -> Variant:
|
||||
var result: Variant = 0
|
||||
var physical: Dictionary = world.ledger.physical_amounts(target)
|
||||
if physical.is_empty(): physical = world.ledger.physical_amounts(target)
|
||||
for id in rules:
|
||||
if not rules[id].worships: continue
|
||||
var pop: Dictionary = State.normalize_profile(target.ethics.get(id, {}))
|
||||
|
||||
@@ -10,7 +10,7 @@ var _generator_key: String = ""
|
||||
var _generator: Dictionary = {}
|
||||
var _solutions: Dictionary = {}
|
||||
|
||||
func _edges(target: Dictionary, rules: Dictionary) -> Dictionary:
|
||||
func _edges(target: Dictionary, rules: Dictionary, physical: Dictionary = {}) -> Dictionary:
|
||||
var modifiers: Dictionary = Parameters.life_modifiers(target)
|
||||
var order: float = maxf(1e-12, E.approx(Parameters.value(target, "Order")))
|
||||
var stages: Array = rules.keys()
|
||||
@@ -18,13 +18,13 @@ func _edges(target: Dictionary, rules: Dictionary) -> Dictionary:
|
||||
var rates: Dictionary = {}
|
||||
var spans: Dictionary = {}
|
||||
var progression: Dictionary = {}
|
||||
var budget: Dictionary = State.stellar_budget(world, target, rules)
|
||||
var budget: Dictionary = State.stellar_budget(world, target, rules, physical)
|
||||
var signature: String = str(modifiers) + ":" + str(order)
|
||||
for id in stages.duplicate():
|
||||
if rules[id].ethics.is_empty(): continue
|
||||
rates[id] = Civ.coefficients(world, rules, id, modifiers)
|
||||
progression[id] = _can_progress(id, rules[id].next, budget, rules)
|
||||
spans[id] = maxf(1e-12, E.approx(State.effective_span(world, target, id, rules)))
|
||||
spans[id] = maxf(1e-12, E.approx(State.effective_span(world, target, id, rules, physical)))
|
||||
signature += id + str(spans[id]) + str(rates[id]) + str(rules[id]) + str(progression[id])
|
||||
for row: Dictionary in rules[id].ethics.values():
|
||||
for destination in Q.rule_weights(str(row.fall)):
|
||||
@@ -171,11 +171,11 @@ func _solve_basis(generator: Dictionary, source: String, years: float) -> Dictio
|
||||
for node in range(e, size, 6): occupation[node] *= factor
|
||||
return {"mass": mass, "occupation": occupation}
|
||||
|
||||
func _drift(target: Dictionary, rules: Dictionary, generator: Dictionary, years: float) -> void:
|
||||
func _drift(target: Dictionary, rules: Dictionary, generator: Dictionary, years: float, physical: Dictionary = {}) -> void:
|
||||
for id in rules:
|
||||
if rules[id].ethics.is_empty() or not target.ethics.has(id): continue
|
||||
var profile: Dictionary = State.normalize_profile(target.ethics[id])
|
||||
var span: float = maxf(1e-12, E.approx(State.effective_span(world, target, id, rules)))
|
||||
var span: float = maxf(1e-12, E.approx(State.effective_span(world, target, id, rules, physical)))
|
||||
var duration: float = years / span
|
||||
var pair_decay: float = exp(-0.03 * duration)
|
||||
var opposite_decay: float = exp(-0.02 * duration)
|
||||
@@ -307,11 +307,16 @@ func _limit(plans: Dictionary, budget: Dictionary, rules: Dictionary) -> void:
|
||||
_merge(plans[source], source, rejected, plans[source].profiles[destination])
|
||||
|
||||
## Apply one conserved source-by-owner table, then credit each destination once.
|
||||
func _commit(target: Dictionary, physical: Dictionary, plans: Dictionary, rules: Dictionary, year: Variant) -> void:
|
||||
func _commit(target: Dictionary, physical: Dictionary, plans: Dictionary, rules: Dictionary, year: Variant) -> Dictionary:
|
||||
var credits: Dictionary = {}
|
||||
var contributions: Dictionary = {}
|
||||
var births: Dictionary = {}
|
||||
var ownership: Dictionary = {}
|
||||
# Each source quota replaces its old physical population. Transfers between
|
||||
# owners do not change these exact totals, and credits are applied below.
|
||||
var final: Dictionary = physical.duplicate()
|
||||
for source in plans:
|
||||
if final.has(source): final[source] = plans[source].counts.get(source, 0)
|
||||
var space_stages: Dictionary = {"Ct": true}
|
||||
for id in rules: space_stages[id] = id == "Ct" or str(rules[id].home) != ""
|
||||
for source in plans:
|
||||
@@ -368,7 +373,9 @@ func _commit(target: Dictionary, physical: Dictionary, plans: Dictionary, rules:
|
||||
if world.catalog.entities[id].event_group == "DwStar" and E.gt(physical[id], 0): hosts[id] = physical[id]
|
||||
var host_shares: Array = _host_shares(hosts) if not hosts.is_empty() else []
|
||||
for destination in credits:
|
||||
var created: Variant = world.ledger.credit(target, destination, Q.sum(credits[destination]))
|
||||
var requested: Variant = Q.sum(credits[destination])
|
||||
var created: Variant = world.ledger.credit(target, destination, requested)
|
||||
if final.has(destination): final[destination] = E.add(final[destination], created)
|
||||
var bound: Variant = 0
|
||||
for owner in credits[destination]:
|
||||
var count: Variant = credits[destination][owner]
|
||||
@@ -385,7 +392,6 @@ func _commit(target: Dictionary, physical: Dictionary, plans: Dictionary, rules:
|
||||
bound = E.add(bound, count)
|
||||
target.amount[destination] = E.subtract(target.amount[destination], bound)
|
||||
if not rules.has(destination): births[destination] = created
|
||||
var final: Dictionary = world.ledger.physical_amounts(target)
|
||||
for destination in contributions:
|
||||
if not rules.has(destination) or E.le(final.get(destination, 0), 0): continue
|
||||
var profile: Dictionary = {}
|
||||
@@ -400,6 +406,7 @@ func _commit(target: Dictionary, physical: Dictionary, plans: Dictionary, rules:
|
||||
for ethic in ETHICS: profile[ethic] += entry.profile[ethic] * ratio
|
||||
target.ethics[destination] = State.normalize_profile(profile)
|
||||
for destination in births: world.batches.append_batch(target, destination, births[destination], year, year)
|
||||
return final
|
||||
|
||||
func _host_shares(hosts: Dictionary) -> Array:
|
||||
var total: Variant = Q.sum(hosts)
|
||||
@@ -407,16 +414,16 @@ func _host_shares(hosts: Dictionary) -> Array:
|
||||
for value in hosts.values(): result.append(E.ratio_approx(value, total))
|
||||
return result
|
||||
|
||||
func _colonize(target: Dictionary, colonies: Dictionary, year: Variant, rules: Dictionary) -> void:
|
||||
if colonies.is_empty(): return
|
||||
var physical: Dictionary = world.ledger.physical_amounts(target)
|
||||
func _colonize(target: Dictionary, colonies: Dictionary, year: Variant, rules: Dictionary, physical: Dictionary = {}) -> Dictionary:
|
||||
if physical.is_empty(): physical = world.ledger.physical_amounts(target)
|
||||
if colonies.is_empty(): return physical
|
||||
var stocks: Dictionary = {}
|
||||
for id in ["GG", "AB", "RP", "HP"]: stocks[id] = physical.get(id, 0)
|
||||
var requests: Dictionary = {}
|
||||
for id in colonies: requests[id] = colonies[id].counts.get(id, 0)
|
||||
var granted: Dictionary = Q.allocate_profiled(requests, Q.sum(stocks))
|
||||
var total: Variant = Q.sum(granted)
|
||||
if E.le(total, 0): return
|
||||
if E.le(total, 0): return physical
|
||||
var taken_resources: Dictionary = Q.allocate_profiled(stocks, total)
|
||||
var removed_by_owner: Dictionary = {}
|
||||
for resource in taken_resources:
|
||||
@@ -435,6 +442,7 @@ func _colonize(target: Dictionary, colonies: Dictionary, year: Variant, rules: D
|
||||
removed_by_owner[owner] = E.add(removed_by_owner.get(owner, 0), amount)
|
||||
var remaining: Dictionary = granted.duplicate()
|
||||
var placements: Dictionary = {}
|
||||
var final: Dictionary = physical.duplicate()
|
||||
var owners: Array = removed_by_owner.keys()
|
||||
for i in owners.size():
|
||||
var owner: String = owners[i]
|
||||
@@ -449,7 +457,8 @@ func _colonize(target: Dictionary, colonies: Dictionary, year: Variant, rules: D
|
||||
for destination in granted:
|
||||
var count: Variant = granted[destination]
|
||||
if E.le(count, 0): continue
|
||||
world.ledger.credit(target, destination, count)
|
||||
var created: Variant = world.ledger.credit(target, destination, count)
|
||||
if final.has(destination): final[destination] = E.add(final[destination], created)
|
||||
var bound: Variant = 0
|
||||
for owner in placements.get(destination, {}):
|
||||
var held: Variant = placements[destination][owner]
|
||||
@@ -466,6 +475,9 @@ func _colonize(target: Dictionary, colonies: Dictionary, year: Variant, rules: D
|
||||
drifted[ethic] += profile[source] * (0.96 if source == ethic else (0.004 if Civ.OPPOSITE[source] == ethic else 0.009))
|
||||
target.ethics[id] = State.merge_profiles(target.ethics.get(id, {}), physical.get(id, 0), drifted, granted[id])
|
||||
target.civilization_stats.colonies = E.add(target.civilization_stats.get("colonies", 0), total)
|
||||
for resource in taken_resources:
|
||||
final[resource] = E.subtract(final.get(resource, 0), taken_resources[resource])
|
||||
return final
|
||||
|
||||
func evolve(target: Dictionary, from_year: Variant, to_year: Variant, timer: RefCounted = null) -> void:
|
||||
var keep_alive: RefCounted = self
|
||||
@@ -476,12 +488,12 @@ func evolve(target: Dictionary, from_year: Variant, to_year: Variant, timer: Ref
|
||||
# Bound the Poisson mean, processing the entire requested interval.
|
||||
var maximum_years: float = years
|
||||
var cursor: Variant = from_year
|
||||
var physical: Dictionary = world.ledger.physical_amounts(target)
|
||||
while E.lt(cursor, to_year):
|
||||
if timer != null and not await timer.pause(): return
|
||||
generator = _edges(target, rules)
|
||||
generator = _edges(target, rules, physical)
|
||||
maximum_years = 32.0 / generator.lambda if generator.lambda > 0.0 else years
|
||||
var end: Variant = E.minimum(to_year, E.add(cursor, E.of(maximum_years)))
|
||||
var physical: Dictionary = world.ledger.physical_amounts(target)
|
||||
var started: int = world.profile_start()
|
||||
var transaction: Dictionary = _plans(target, physical, rules, generator, E.approx(E.subtract(end, cursor)))
|
||||
world.profile_end("civilization_flow_plan", started)
|
||||
@@ -509,18 +521,18 @@ func evolve(target: Dictionary, from_year: Variant, to_year: Variant, timer: Ref
|
||||
_limit(plans, State.stellar_budget(world, target, rules, physical), rules)
|
||||
world.profile_end("civilization_flow_capacity", started)
|
||||
started = world.profile_start()
|
||||
_commit(target, physical, plans, rules, end)
|
||||
physical = _commit(target, physical, plans, rules, end)
|
||||
world.profile_end("civilization_flow_ledger", started)
|
||||
if timer != null and not await timer.pause(): return
|
||||
started = world.profile_start()
|
||||
_colonize(target, transaction.colonies, end, rules)
|
||||
physical = _colonize(target, transaction.colonies, end, rules, physical)
|
||||
world.profile_end("civilization_flow_colonies", started)
|
||||
started = world.profile_start()
|
||||
_drift(target, rules, generator, E.approx(E.subtract(end, cursor)))
|
||||
_drift(target, rules, generator, E.approx(E.subtract(end, cursor)), physical)
|
||||
target.civilization_stats.wars = E.add(target.civilization_stats.get("wars", 0), transaction.wars)
|
||||
target.civilization_stats.collateral = E.add(target.civilization_stats.get("collateral", 0), damage_total)
|
||||
State.enforce_capacity(world, target, rules, end)
|
||||
State.reconcile(world, target, rules)
|
||||
target.civilization_stats.worship = Civ.worship(world, target, rules)
|
||||
physical = State.enforce_capacity(world, target, rules, end, physical)
|
||||
State.reconcile(world, target, rules, physical)
|
||||
target.civilization_stats.worship = Civ.worship(world, target, rules, physical)
|
||||
world.profile_end("civilization_flow_finish", started)
|
||||
cursor = end
|
||||
|
||||
@@ -133,10 +133,11 @@ static func admit_transition(budget: Dictionary, rules: Dictionary, source: Stri
|
||||
|
||||
# Resolve shortages from the most advanced stages downwards. This gives existing
|
||||
# advanced populations priority and lets a demotion cascade in the same cycle.
|
||||
static func enforce_capacity(world, target: Dictionary, rules: Dictionary, year: Variant) -> void:
|
||||
static func enforce_capacity(world, target: Dictionary, rules: Dictionary, year: Variant, physical: Dictionary = {}) -> Dictionary:
|
||||
var profile_started: int = world.profile_start()
|
||||
detach_space_civilizations(target, rules)
|
||||
var physical: Dictionary = world.ledger.physical_amounts(target)
|
||||
if physical.is_empty(): physical = world.ledger.physical_amounts(target)
|
||||
else: physical = physical.duplicate()
|
||||
reconcile(world, target, rules, physical)
|
||||
var ethical_totals: Dictionary = physical.duplicate()
|
||||
var budget: Dictionary = stellar_budget(world, target, rules, physical)
|
||||
@@ -163,7 +164,9 @@ static func enforce_capacity(world, target: Dictionary, rules: Dictionary, year:
|
||||
var previous: String = (stages[E.subtract(index, 1)] if E.gt(index, 0) else "C1.9")
|
||||
world.batches.scale_batches(target, id, E.divide(supported, count))
|
||||
target.amount[id] = supported
|
||||
world.ledger.credit(target, previous, excess)
|
||||
var credited: Variant = world.ledger.credit(target, previous, excess)
|
||||
physical[id] = E.maximum(0, supported)
|
||||
physical[previous] = E.add(physical.get(previous, 0), credited)
|
||||
world.batches.append_batch(target, previous, excess, year, year)
|
||||
var previous_count: Variant = ethical_totals.get(previous, physical.get(previous, target.amount.get(previous, 0)))
|
||||
var previous_profile: Dictionary = target.ethics.get(previous, empty_profile())
|
||||
@@ -174,7 +177,7 @@ static func enforce_capacity(world, target: Dictionary, rules: Dictionary, year:
|
||||
# Capacity losses are proportional, so the surviving source keeps its profile.
|
||||
if E.eq(previous, "C1.9"):
|
||||
var stars: Dictionary = {}
|
||||
var current_physical: Dictionary = world.ledger.physical_amounts(target)
|
||||
var current_physical: Dictionary = physical
|
||||
for star in current_physical:
|
||||
if (E.eq(world.catalog.entities[star].event_group, "DwStar") and E.gt(current_physical[star], 0)):
|
||||
stars[star] = current_physical[star]
|
||||
@@ -192,10 +195,10 @@ static func enforce_capacity(world, target: Dictionary, rules: Dictionary, year:
|
||||
target.binds[owner][previous] = E.add(target.binds[owner].get(previous, 0), amount)
|
||||
target.amount[previous] = E.subtract(target.amount[previous], amount)
|
||||
if changed:
|
||||
physical = world.ledger.physical_amounts(target)
|
||||
reconcile(world, target, rules, physical)
|
||||
assign_homes(world, target, rules, physical)
|
||||
world.profile_end("enforce_capacity", profile_started)
|
||||
return physical
|
||||
|
||||
# Unity's structure chain: direct Claim resets the required structure count;
|
||||
# intervening stages require ten times more units of the preceding structure.
|
||||
@@ -247,13 +250,13 @@ static func assign_homes(world, target: Dictionary, rules: Dictionary, physical:
|
||||
world.profile_end("assign_homes", profile_started)
|
||||
|
||||
|
||||
static func effective_span(world, target: Dictionary, id: String, rules: Dictionary) -> Variant:
|
||||
static func effective_span(world, target: Dictionary, id: String, rules: Dictionary, physical: Dictionary = {}) -> Variant:
|
||||
if (not rules.has(id)): return world.catalog.entities[id].lifespan
|
||||
var base: Variant = rules[id].span
|
||||
if (not is_space_civilization(id, rules)): return base
|
||||
var population: Variant = target.amount.get(id, 0)
|
||||
if E.le(population, 0): return base
|
||||
var homes: Dictionary = stage_homes(world, target, id, world.catalog.civilization_layout(rules))
|
||||
var homes: Dictionary = stage_homes(world, target, id, world.catalog.civilization_layout(rules), physical)
|
||||
target.civilization_homes[id] = homes
|
||||
var multiplier: float = 1.0
|
||||
for home in homes:
|
||||
|
||||
@@ -5,13 +5,12 @@ const SimulationTime = preload("res://world/owniverse/simulation_time.gd")
|
||||
const WorldParameters = preload("res://world/owniverse/world_parameters.gd")
|
||||
const QuantityMath = preload("res://world/owniverse/quantity_math.gd")
|
||||
|
||||
func initialize_life_batches() -> void:
|
||||
func initialize_life_batches() -> Dictionary:
|
||||
for id in Global.CivilizationRules:
|
||||
world.state.batches.erase(id)
|
||||
world.state.batch_origins.erase(id)
|
||||
CivilizationState.detach_space_civilizations(world.state, Global.CivilizationRules)
|
||||
CivilizationState.enforce_capacity(world, world.state, Global.CivilizationRules, world.state.time.datetime)
|
||||
var physical: Dictionary = world.ledger.physical_amounts(world.state)
|
||||
var physical: Dictionary = CivilizationState.enforce_capacity(world, world.state, Global.CivilizationRules, world.state.time.datetime)
|
||||
for id in world.catalog.entities:
|
||||
if world.catalog.entities[id].life_rule.is_empty():
|
||||
continue
|
||||
@@ -19,6 +18,7 @@ func initialize_life_batches() -> void:
|
||||
for batch : Dictionary in world.state.batches.get(id, []):
|
||||
tracked = E.add(tracked, batch.amount)
|
||||
world.batches.append_batch(world.state, id, E.maximum(0, E.subtract(physical.get(id, 0), tracked)), world.state.time.datetime, world.state.time.datetime)
|
||||
return physical
|
||||
|
||||
|
||||
func run_frame(clock: Dictionary, budget: RefCounted) -> void:
|
||||
@@ -31,10 +31,11 @@ func evolute_to_datetime(datetime: Variant, clock: Dictionary = {}, budget: RefC
|
||||
# Reconcile only when simulation advances.
|
||||
# Fractional frame updates cannot change capacity or populations.
|
||||
var processed_year: Variant = SimulationTime.processed_year(datetime)
|
||||
var quantities: Dictionary = {}
|
||||
if E.gt(processed_year, world.state.time.year):
|
||||
if budget != null: budget.call("set_phase", "initialize_life_batches")
|
||||
var profile_initialize: int = world.profile_start()
|
||||
initialize_life_batches()
|
||||
quantities = initialize_life_batches()
|
||||
world.profile_end("initialize", profile_initialize)
|
||||
var previous: Dictionary = world.state
|
||||
if budget != null: budget.call("set_phase", "deep_copy_and_coarsen")
|
||||
@@ -46,7 +47,6 @@ func evolute_to_datetime(datetime: Variant, clock: Dictionary = {}, budget: RefC
|
||||
var from_year: Variant = previous.time.year
|
||||
var to_year: Variant = processed_year
|
||||
if E.gt(to_year, from_year):
|
||||
var quantities: Dictionary = world.ledger.physical_amounts(previous)
|
||||
var distribution: Dictionary = QuantityMath.normalize_distribution(quantities)
|
||||
next.distribution = distribution
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ const E = preload("res://world/owniverse/math/exact.gd")
|
||||
const CivilizationState = preload("res://world/owniverse/civilization_state.gd")
|
||||
const QuantityMath = preload("res://world/owniverse/quantity_math.gd")
|
||||
|
||||
func try_production(target: Dictionary, entity: OwniverseEntity, amount: Variant, automatic: bool = false) -> bool:
|
||||
func try_production(target: Dictionary, entity: OwniverseEntity, amount: Variant, automatic: bool = false, physical: Dictionary = {}) -> bool:
|
||||
if (E.le(amount, 0) or E.ne(amount, E.floor_value(amount))):
|
||||
return false
|
||||
var trial: Dictionary = target.duplicate()
|
||||
@@ -13,7 +13,9 @@ func try_production(target: Dictionary, entity: OwniverseEntity, amount: Variant
|
||||
trial.batches = target.batches.duplicate()
|
||||
# Physical object totals do not change while resources are withdrawn from
|
||||
# this transaction. Keep one snapshot instead of scanning every resource.
|
||||
var physical: Dictionary = world.ledger.physical_amounts(trial)
|
||||
var shared_physical: bool = not physical.is_empty()
|
||||
if not shared_physical: physical = world.ledger.physical_amounts(trial)
|
||||
var next_physical: Dictionary = physical.duplicate() if shared_physical else {}
|
||||
var copied_batches: Dictionary = {}
|
||||
for resource in entity.cost:
|
||||
var cost: Variant = E.round_value(E.multiply(E.maximum(0, entity.cost[resource]), amount))
|
||||
@@ -28,6 +30,7 @@ func try_production(target: Dictionary, entity: OwniverseEntity, amount: Variant
|
||||
if automatic:
|
||||
trial.auto_resources[resource] = E.maximum(0, E.subtract(trial.auto_resources.get(resource, 0), cost))
|
||||
for id in taken:
|
||||
if shared_physical and next_physical.has(id): next_physical[id] = E.subtract(next_physical[id], taken[id])
|
||||
# Isolate only batches actually touched by this transaction.
|
||||
if (trial.batches.has(id) and (not copied_batches.has(id))):
|
||||
trial.batches[id] = trial.batches[id].duplicate(true)
|
||||
@@ -41,6 +44,7 @@ func try_production(target: Dictionary, entity: OwniverseEntity, amount: Variant
|
||||
for field in ["amount", "binds", "batches", "auto_resources"]:
|
||||
if trial.has(field):
|
||||
target[field] = trial[field]
|
||||
if shared_physical: physical.merge(next_physical, true)
|
||||
return true
|
||||
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ extends "res://world/owniverse/simulation_module.gd"
|
||||
const E = preload("res://world/owniverse/math/exact.gd")
|
||||
const WorldParameters = preload("res://world/owniverse/world_parameters.gd")
|
||||
|
||||
func stellar_environment(source: Dictionary) -> Dictionary:
|
||||
var quantities: Dictionary = world.ledger.physical_amounts(source)
|
||||
func stellar_environment(source: Dictionary, quantities: Dictionary = {}) -> Dictionary:
|
||||
if quantities.is_empty(): quantities = world.ledger.physical_amounts(source)
|
||||
# SMBH is a self-group in GI; its quantity stores mass, not object count.
|
||||
var mass: Variant = source.amount.get("SMBH", 0)
|
||||
# Geometric volume includes a 1e22 scale per void and can exceed E27.
|
||||
|
||||
Reference in New Issue
Block a user