diff --git a/src/physcom/engine/pipeline.py b/src/physcom/engine/pipeline.py index bd3ff9f..bf64168 100644 --- a/src/physcom/engine/pipeline.py +++ b/src/physcom/engine/pipeline.py @@ -932,12 +932,12 @@ class Pipeline: platform's representative mass (ctx.p_rep) -- pass an explicit value to explore a specific weight class instead (see evaluate_allocation). Cargo capacity is derived from THIS build's - actual assembled mass (floor_total below), not a separate - declared-floor constant -- a deadweight/lightship-style ratio of - "how much this vehicle could additionally carry, proportional to - its own (empty of cargo) mass" only makes sense against the mass - it's actually built to, so it responds to the same optimizer/ - explore-slider choices every other metric here does.""" + actual platform+actuator mass (not a separate declared-floor + constant), with storage_mass subtracted out of that allowance -- + see the deadweight/lightship comment at its computation below for + why fuel/battery competes with cargo instead of padding it. It + responds to the same optimizer/explore-slider choices every other + metric here does.""" p_mass = ctx.p_rep if platform_mass is None else platform_mass out: dict[str, float] = {} floor_total = p_mass + actuator_mass + storage_mass @@ -946,14 +946,27 @@ class Pipeline: if "power_density" in bounds_by_name: out["power_density"] = power_density_value - # Deadweight/lightship-style cargo capacity, proportional to this - # build's own actual mass -- two conventions coexist because heavy - # freight/maritime vehicles genuinely carry a much larger multiple - # of their own mass in cargo than light personal/delivery vehicles - # do (see CARGO_KG_PER_STRUCTURAL_KG's module comment); which one - # a domain scores is just which metric_name it declares. - cargo_capacity_2_5x = floor_total * CARGO_KG_PER_STRUCTURAL_KG - cargo_capacity_0_3x = floor_total * 0.3 + # Deadweight/lightship cargo capacity. Real deadweight tonnage is a + # FIXED allowance sized off the vessel's own empty (lightship) mass + # -- hull + machinery, NOT fuel or cargo -- and fuel and cargo then + # SHARE that one allowance: a ship that bunkers more fuel has that + # much less room left for cargo, and vice versa. platform+actuator + # is the lightship analog here (the vehicle's own hardware); + # storage_mass is the fuel/battery competing with cargo for the + # same pool, not part of the base the pool is sized from -- get + # that backwards (basing the pool on platform+actuator+storage, + # as an earlier version of this did) and more battery looks like it + # BUYS more cargo room instead of using it up. Two ratio + # conventions coexist because heavy freight/maritime vehicles + # genuinely carry a much larger multiple of their own mass in + # cargo than light personal/delivery vehicles do (see + # CARGO_KG_PER_STRUCTURAL_KG's module comment); which one a domain + # scores is just which metric_name it declares. Floored at 0: a + # storage mass bigger than the whole allowance leaves no cargo + # room, not negative room. + lightship_mass = p_mass + actuator_mass + cargo_capacity_2_5x = max(0.0, lightship_mass * CARGO_KG_PER_STRUCTURAL_KG - storage_mass) + cargo_capacity_0_3x = max(0.0, lightship_mass * 0.3 - storage_mass) if "cargo_capacity" in bounds_by_name: out["cargo_capacity"] = cargo_capacity_2_5x if "cargo_capacity_kg" in bounds_by_name: