Rehost world locomotive policy owner state

This commit is contained in:
Jan Petykiewicz 2026-04-18 06:51:22 -07:00
commit 95215d836e
11 changed files with 536 additions and 6 deletions

View file

@ -122,6 +122,10 @@ invoke the periodic-boundary service automatically on year rollover, so shellles
can drive the annual finance stack instead of requiring a separate manual service command.
That stepped world-time path now also refreshes the rehosted selected-year gap scalar owner lane
instead of leaving `[world+0x4ca2]` as a frozen load-time residue.
The same save-native world restore surface now also carries the grounded locomotive-policy bytes
and cached available-locomotive rating from the fixed world block, so the `All
Steam/Diesel/Electric Locos Avail.` descriptor strip now writes through owner state instead of
living only as ad hoc world flags.
Those bankruptcy branches now follow the grounded owner semantics too: they stamp the bankruptcy
year and halve live bond principals in place instead of treating bankruptcy as a liquidation path.
The same save-native live bond-slot surface now also carries per-slot maturity years all the way

View file

@ -4934,6 +4934,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,

View file

@ -283,6 +283,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -427,6 +428,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,

View file

@ -836,6 +836,42 @@ fn project_save_slice_components(
limited_track_building_amount: None,
economic_status_code: None,
territory_access_cost: None,
linked_site_removal_follow_on_gate_raw_u8: save_slice
.world_locomotive_policy_state
.as_ref()
.and_then(|state| state.linked_site_removal_follow_on_gate_raw_u8),
linked_site_removal_follow_on_gate_enabled: save_slice
.world_locomotive_policy_state
.as_ref()
.and_then(|state| state.linked_site_removal_follow_on_gate_raw_u8)
.map(|raw| raw != 0),
all_steam_locomotives_available_raw_u8: save_slice
.world_locomotive_policy_state
.as_ref()
.and_then(|state| state.all_steam_locomotives_available_raw_u8),
all_steam_locomotives_available_enabled: save_slice
.world_locomotive_policy_state
.as_ref()
.and_then(|state| state.all_steam_locomotives_available_raw_u8)
.map(|raw| raw != 0),
all_diesel_locomotives_available_raw_u8: save_slice
.world_locomotive_policy_state
.as_ref()
.and_then(|state| state.all_diesel_locomotives_available_raw_u8),
all_diesel_locomotives_available_enabled: save_slice
.world_locomotive_policy_state
.as_ref()
.and_then(|state| state.all_diesel_locomotives_available_raw_u8)
.map(|raw| raw != 0),
all_electric_locomotives_available_raw_u8: save_slice
.world_locomotive_policy_state
.as_ref()
.and_then(|state| state.all_electric_locomotives_available_raw_u8),
all_electric_locomotives_available_enabled: save_slice
.world_locomotive_policy_state
.as_ref()
.and_then(|state| state.all_electric_locomotives_available_raw_u8)
.map(|raw| raw != 0),
issue_37_value: save_slice
.world_issue_37_state
.as_ref()
@ -934,6 +970,18 @@ fn project_save_slice_components(
.as_ref()
.map(|state| state.lane_value_f32_text.clone())
.unwrap_or_default(),
cached_available_locomotive_rating_raw_u32: save_slice
.world_locomotive_policy_state
.as_ref()
.and_then(|state| state.cached_available_locomotive_rating_raw_u32),
cached_available_locomotive_rating_value_f32_text: save_slice
.world_locomotive_policy_state
.as_ref()
.and_then(|state| {
state
.cached_available_locomotive_rating_value_f32_text
.clone()
}),
selected_year_gap_scalar_raw_u32: None,
selected_year_gap_scalar_value_f32_text: None,
absolute_counter_restore_kind: Some(
@ -5839,6 +5887,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -5885,6 +5934,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -6085,6 +6135,24 @@ mod tests {
"0.000000".to_string(),
],
}),
world_locomotive_policy_state: Some(crate::smp::SmpLoadedWorldLocomotivePolicyState {
source_kind: "save-fixed-world-block".to_string(),
semantic_family: "world-locomotive-policy".to_string(),
selected_year_gap_scalar_raw_u32: Some(0x3eaaaaab),
selected_year_gap_scalar_raw_hex: Some("0x3eaaaaab".to_string()),
selected_year_gap_scalar_value_f32_text: Some("0.333333".to_string()),
linked_site_removal_follow_on_gate_raw_u8: Some(1),
linked_site_removal_follow_on_gate_raw_hex: Some("0x01".to_string()),
all_steam_locomotives_available_raw_u8: Some(1),
all_steam_locomotives_available_raw_hex: Some("0x01".to_string()),
all_diesel_locomotives_available_raw_u8: Some(0),
all_diesel_locomotives_available_raw_hex: Some("0x00".to_string()),
all_electric_locomotives_available_raw_u8: Some(1),
all_electric_locomotives_available_raw_hex: Some("0x01".to_string()),
cached_available_locomotive_rating_raw_u32: Some(0x41a00000),
cached_available_locomotive_rating_raw_hex: Some("0x41a00000".to_string()),
cached_available_locomotive_rating_value_f32_text: Some("20.000000".to_string()),
}),
company_roster: None,
chairman_profile_table: None,
special_conditions_table: Some(crate::SmpLoadedSpecialConditionsTable {
@ -6401,6 +6469,41 @@ mod tests {
.economic_tuning_lane_value_f32_text,
vec!["0.750000".to_string(), "0.007000".to_string()]
);
assert_eq!(
import
.state
.world_restore
.linked_site_removal_follow_on_gate_raw_u8,
Some(1)
);
assert_eq!(
import
.state
.world_restore
.all_steam_locomotives_available_enabled,
Some(true)
);
assert_eq!(
import
.state
.world_restore
.all_diesel_locomotives_available_enabled,
Some(false)
);
assert_eq!(
import
.state
.world_restore
.all_electric_locomotives_available_enabled,
Some(true)
);
assert_eq!(
import
.state
.world_restore
.cached_available_locomotive_rating_raw_u32,
Some(0x41a00000)
);
assert_eq!(
import
.state
@ -6547,6 +6650,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: Some(save_company_roster()),
chairman_profile_table: Some(save_chairman_profile_table()),
special_conditions_table: None,
@ -6634,6 +6738,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: Some(save_company_roster()),
chairman_profile_table: Some(save_chairman_profile_table()),
special_conditions_table: None,
@ -6790,6 +6895,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: Some(crate::SmpLoadedCompanyRoster {
source_kind: "save-direct-world-block-company-selection-only".to_string(),
semantic_family: "scenario-selected-company-context".to_string(),
@ -6850,6 +6956,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -6975,6 +7082,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -7078,6 +7186,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -7207,6 +7316,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -7297,6 +7407,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -7455,6 +7566,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -7703,6 +7815,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -7786,6 +7899,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -7893,6 +8007,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -7973,6 +8088,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: Some(save_company_roster()),
chairman_profile_table: Some(save_chairman_profile_table()),
special_conditions_table: None,
@ -8056,6 +8172,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: Some(save_company_roster()),
chairman_profile_table: Some(save_chairman_profile_table()),
special_conditions_table: None,
@ -8152,6 +8269,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -8264,6 +8382,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -8347,6 +8466,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -8507,6 +8627,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -8612,6 +8733,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -8694,6 +8816,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -8776,6 +8899,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -8932,6 +9056,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -9033,6 +9158,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -9113,6 +9239,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -9203,6 +9330,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -9302,6 +9430,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -9409,6 +9538,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -9505,6 +9635,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -9587,6 +9718,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -9739,6 +9871,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -9901,6 +10034,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -10011,6 +10145,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -10102,6 +10237,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -10220,6 +10356,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -10332,6 +10469,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -10434,6 +10572,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -10532,6 +10671,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -10644,6 +10784,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -10741,6 +10882,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -10820,6 +10962,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -10904,6 +11047,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -10993,6 +11137,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -11082,6 +11227,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -11187,6 +11333,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -11283,6 +11430,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -11382,6 +11530,27 @@ mod tests {
.get("world.all_electric_locos_available"),
Some(&true)
);
assert_eq!(
import
.state
.world_restore
.all_steam_locomotives_available_raw_u8,
Some(1)
);
assert_eq!(
import
.state
.world_restore
.all_diesel_locomotives_available_raw_u8,
Some(0)
);
assert_eq!(
import
.state
.world_restore
.all_electric_locomotives_available_raw_u8,
Some(1)
);
}
#[test]
@ -11405,6 +11574,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -11547,6 +11717,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -12080,6 +12251,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -12267,6 +12439,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -12399,6 +12572,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: Some(save_company_roster()),
chairman_profile_table: Some(save_chairman_profile_table()),
special_conditions_table: None,
@ -12530,6 +12704,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: Some(save_company_roster()),
chairman_profile_table: Some(save_chairman_profile_table()),
special_conditions_table: None,
@ -12662,6 +12837,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -12778,6 +12954,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -12969,6 +13146,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -13068,6 +13246,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -13169,6 +13348,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -13341,6 +13521,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -13496,6 +13677,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -13592,6 +13774,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -13721,6 +13904,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -13838,6 +14022,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -14024,6 +14209,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,
@ -14225,6 +14411,7 @@ mod tests {
world_issue_37_state: None,
world_economic_tuning_state: None,
world_finance_neighborhood_state: None,
world_locomotive_policy_state: None,
company_roster: None,
chairman_profile_table: None,
special_conditions_table: None,

View file

@ -1358,6 +1358,22 @@ pub struct RuntimeWorldRestoreState {
#[serde(default)]
pub territory_access_cost: Option<u32>,
#[serde(default)]
pub linked_site_removal_follow_on_gate_raw_u8: Option<u8>,
#[serde(default)]
pub linked_site_removal_follow_on_gate_enabled: Option<bool>,
#[serde(default)]
pub all_steam_locomotives_available_raw_u8: Option<u8>,
#[serde(default)]
pub all_steam_locomotives_available_enabled: Option<bool>,
#[serde(default)]
pub all_diesel_locomotives_available_raw_u8: Option<u8>,
#[serde(default)]
pub all_diesel_locomotives_available_enabled: Option<bool>,
#[serde(default)]
pub all_electric_locomotives_available_raw_u8: Option<u8>,
#[serde(default)]
pub all_electric_locomotives_available_enabled: Option<bool>,
#[serde(default)]
pub issue_37_value: Option<u32>,
#[serde(default)]
pub issue_38_value: Option<u32>,
@ -1398,6 +1414,10 @@ pub struct RuntimeWorldRestoreState {
#[serde(default)]
pub economic_tuning_lane_value_f32_text: Vec<String>,
#[serde(default)]
pub cached_available_locomotive_rating_raw_u32: Option<u32>,
#[serde(default)]
pub cached_available_locomotive_rating_value_f32_text: Option<String>,
#[serde(default)]
pub selected_year_gap_scalar_raw_u32: Option<u32>,
#[serde(default)]
pub selected_year_gap_scalar_value_f32_text: Option<String>,
@ -2358,6 +2378,24 @@ impl RuntimeState {
}
pub fn refresh_derived_world_state(&mut self) {
self.world_restore
.linked_site_removal_follow_on_gate_enabled = self
.world_restore
.linked_site_removal_follow_on_gate_raw_u8
.map(|raw| raw != 0);
self.world_restore.all_steam_locomotives_available_enabled = self
.world_restore
.all_steam_locomotives_available_raw_u8
.map(|raw| raw != 0);
self.world_restore.all_diesel_locomotives_available_enabled = self
.world_restore
.all_diesel_locomotives_available_raw_u8
.map(|raw| raw != 0);
self.world_restore
.all_electric_locomotives_available_enabled = self
.world_restore
.all_electric_locomotives_available_raw_u8
.map(|raw| raw != 0);
let year_word = self
.world_restore
.packed_year_word_raw_u16
@ -2376,6 +2414,27 @@ impl RuntimeState {
self.world_restore.selected_year_gap_scalar_value_f32_text =
Some(format!("{value:.6}"));
}
for (key, value) in [
(
"world.all_steam_locos_available",
self.world_restore.all_steam_locomotives_available_enabled,
),
(
"world.all_diesel_locos_available",
self.world_restore.all_diesel_locomotives_available_enabled,
),
(
"world.all_electric_locos_available",
self.world_restore
.all_electric_locomotives_available_enabled,
),
] {
if let Some(enabled) = value {
self.world_flags.insert(key.to_string(), enabled);
} else {
self.world_flags.remove(key);
}
}
}
}
@ -4981,6 +5040,16 @@ mod tests {
limited_track_building_amount: None,
economic_status_code: None,
territory_access_cost: None,
linked_site_removal_follow_on_gate_raw_u8: None,
linked_site_removal_follow_on_gate_enabled: None,
all_steam_locomotives_available_raw_u8: None,
all_steam_locomotives_available_enabled: None,
all_diesel_locomotives_available_raw_u8: None,
all_diesel_locomotives_available_enabled: None,
all_electric_locomotives_available_raw_u8: None,
all_electric_locomotives_available_enabled: None,
cached_available_locomotive_rating_raw_u32: None,
cached_available_locomotive_rating_value_f32_text: None,
issue_37_value: None,
issue_38_value: None,
issue_39_value: None,

View file

@ -2289,6 +2289,40 @@ pub struct SmpLoadedWorldFinanceNeighborhoodState {
pub value_f32_text: Vec<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SmpLoadedWorldLocomotivePolicyState {
pub source_kind: String,
pub semantic_family: String,
#[serde(default)]
pub selected_year_gap_scalar_raw_u32: Option<u32>,
#[serde(default)]
pub selected_year_gap_scalar_raw_hex: Option<String>,
#[serde(default)]
pub selected_year_gap_scalar_value_f32_text: Option<String>,
#[serde(default)]
pub linked_site_removal_follow_on_gate_raw_u8: Option<u8>,
#[serde(default)]
pub linked_site_removal_follow_on_gate_raw_hex: Option<String>,
#[serde(default)]
pub all_steam_locomotives_available_raw_u8: Option<u8>,
#[serde(default)]
pub all_steam_locomotives_available_raw_hex: Option<String>,
#[serde(default)]
pub all_diesel_locomotives_available_raw_u8: Option<u8>,
#[serde(default)]
pub all_diesel_locomotives_available_raw_hex: Option<String>,
#[serde(default)]
pub all_electric_locomotives_available_raw_u8: Option<u8>,
#[serde(default)]
pub all_electric_locomotives_available_raw_hex: Option<String>,
#[serde(default)]
pub cached_available_locomotive_rating_raw_u32: Option<u32>,
#[serde(default)]
pub cached_available_locomotive_rating_raw_hex: Option<String>,
#[serde(default)]
pub cached_available_locomotive_rating_value_f32_text: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SmpLoadedCompanyRosterEntry {
pub company_id: u32,
@ -2699,6 +2733,8 @@ pub struct SmpLoadedSaveSlice {
#[serde(default)]
pub world_finance_neighborhood_state: Option<SmpLoadedWorldFinanceNeighborhoodState>,
#[serde(default)]
pub world_locomotive_policy_state: Option<SmpLoadedWorldLocomotivePolicyState>,
#[serde(default)]
pub company_roster: Option<SmpLoadedCompanyRoster>,
#[serde(default)]
pub chairman_profile_table: Option<SmpLoadedChairmanProfileTable>,
@ -2892,6 +2928,10 @@ pub fn load_save_slice_from_report(
.save_world_finance_neighborhood_probe
.as_ref()
.map(derive_loaded_world_finance_neighborhood_state_from_probe);
let world_locomotive_policy_state = report
.locomotive_policy_neighborhood_probe
.as_ref()
.map(derive_loaded_world_locomotive_policy_state_from_probe);
let company_roster = report.save_company_roster_probe.clone().or_else(|| {
report
.save_world_selection_context_probe
@ -3028,6 +3068,7 @@ pub fn load_save_slice_from_report(
world_issue_37_state,
world_economic_tuning_state,
world_finance_neighborhood_state,
world_locomotive_policy_state,
company_roster,
chairman_profile_table,
special_conditions_table,
@ -3585,6 +3626,52 @@ fn derive_loaded_world_finance_neighborhood_state_from_probe(
}
}
fn derive_loaded_world_locomotive_policy_state_from_probe(
probe: &SmpLocomotivePolicyNeighborhoodProbe,
) -> SmpLoadedWorldLocomotivePolicyState {
let field_by_name = |name: &str| {
probe
.grounded_field_observations
.iter()
.find(|field| field.field_name == name)
};
let selected_year_gap_scalar = field_by_name("selected-year bucket companion scalar");
let linked_site_gate = field_by_name("linked-site removal follow-on gate");
let all_steam = field_by_name("All Steam Locos Avail.");
let all_diesel = field_by_name("All Diesel Locos Avail.");
let all_electric = field_by_name("All Electric Locos Avail.");
let cached_available_rating = field_by_name("cached available-locomotive rating");
SmpLoadedWorldLocomotivePolicyState {
source_kind: probe.source_kind.clone(),
semantic_family: "world-locomotive-policy".to_string(),
selected_year_gap_scalar_raw_u32: selected_year_gap_scalar
.and_then(|field| field.value_u32),
selected_year_gap_scalar_raw_hex: selected_year_gap_scalar
.and_then(|field| field.value_u32_hex.clone()),
selected_year_gap_scalar_value_f32_text: selected_year_gap_scalar
.and_then(|field| field.probable_f32_le.clone()),
linked_site_removal_follow_on_gate_raw_u8: linked_site_gate
.and_then(|field| field.value_u8),
linked_site_removal_follow_on_gate_raw_hex: linked_site_gate
.and_then(|field| field.value_u8_hex.clone()),
all_steam_locomotives_available_raw_u8: all_steam.and_then(|field| field.value_u8),
all_steam_locomotives_available_raw_hex: all_steam
.and_then(|field| field.value_u8_hex.clone()),
all_diesel_locomotives_available_raw_u8: all_diesel.and_then(|field| field.value_u8),
all_diesel_locomotives_available_raw_hex: all_diesel
.and_then(|field| field.value_u8_hex.clone()),
all_electric_locomotives_available_raw_u8: all_electric.and_then(|field| field.value_u8),
all_electric_locomotives_available_raw_hex: all_electric
.and_then(|field| field.value_u8_hex.clone()),
cached_available_locomotive_rating_raw_u32: cached_available_rating
.and_then(|field| field.value_u32),
cached_available_locomotive_rating_raw_hex: cached_available_rating
.and_then(|field| field.value_u32_hex.clone()),
cached_available_locomotive_rating_value_f32_text: cached_available_rating
.and_then(|field| field.probable_f32_le.clone()),
}
}
fn derive_selection_only_company_roster_from_save_world_probe(
probe: &SmpSaveWorldSelectionContextProbe,
header_probe: Option<&SmpSaveTaggedCollectionHeaderProbe>,

View file

@ -1389,6 +1389,26 @@ fn apply_runtime_effects(
match effect {
RuntimeEffect::SetWorldFlag { key, value } => {
state.world_flags.insert(key.clone(), *value);
let raw = u8::from(*value);
match key.as_str() {
"world.all_steam_locos_available" => {
state.world_restore.all_steam_locomotives_available_raw_u8 = Some(raw);
state.world_restore.all_steam_locomotives_available_enabled = Some(*value);
}
"world.all_diesel_locos_available" => {
state.world_restore.all_diesel_locomotives_available_raw_u8 = Some(raw);
state.world_restore.all_diesel_locomotives_available_enabled = Some(*value);
}
"world.all_electric_locos_available" => {
state
.world_restore
.all_electric_locomotives_available_raw_u8 = Some(raw);
state
.world_restore
.all_electric_locomotives_available_enabled = Some(*value);
}
_ => {}
}
}
RuntimeEffect::SetWorldScalarOverride { key, value } => {
state.world_scalar_overrides.insert(key.clone(), *value);
@ -5341,6 +5361,63 @@ mod tests {
assert_eq!(result.service_events[0].applied_effect_count, 7);
}
#[test]
fn applies_locomotive_policy_world_flags_through_owner_state() {
let mut state = RuntimeState {
event_runtime_records: vec![RuntimeEventRecord {
record_id: 213,
trigger_kind: 7,
active: true,
service_count: 0,
marks_collection_dirty: false,
one_shot: false,
has_fired: false,
conditions: Vec::new(),
effects: vec![
RuntimeEffect::SetWorldFlag {
key: "world.all_steam_locos_available".to_string(),
value: true,
},
RuntimeEffect::SetWorldFlag {
key: "world.all_diesel_locos_available".to_string(),
value: false,
},
RuntimeEffect::SetWorldFlag {
key: "world.all_electric_locos_available".to_string(),
value: true,
},
],
}],
..state()
};
let result = execute_step_command(
&mut state,
&StepCommand::ServiceTriggerKind { trigger_kind: 7 },
)
.expect("locomotive policy world flags should succeed");
assert_eq!(
state.world_flags.get("world.all_steam_locos_available"),
Some(&true)
);
assert_eq!(
state.world_restore.all_steam_locomotives_available_raw_u8,
Some(1)
);
assert_eq!(
state.world_restore.all_diesel_locomotives_available_raw_u8,
Some(0)
);
assert_eq!(
state
.world_restore
.all_electric_locomotives_available_raw_u8,
Some(1)
);
assert_eq!(result.service_events[0].applied_effect_count, 3);
}
#[test]
fn applies_runtime_variable_effects() {
let mut state = RuntimeState {

View file

@ -49,6 +49,14 @@ pub struct RuntimeSummary {
pub world_restore_limited_track_building_amount: Option<i32>,
pub world_restore_economic_status_code: Option<i32>,
pub world_restore_territory_access_cost: Option<u32>,
pub world_restore_linked_site_removal_follow_on_gate_raw_u8: Option<u8>,
pub world_restore_linked_site_removal_follow_on_gate_enabled: Option<bool>,
pub world_restore_all_steam_locomotives_available_raw_u8: Option<u8>,
pub world_restore_all_steam_locomotives_available_enabled: Option<bool>,
pub world_restore_all_diesel_locomotives_available_raw_u8: Option<u8>,
pub world_restore_all_diesel_locomotives_available_enabled: Option<bool>,
pub world_restore_all_electric_locomotives_available_raw_u8: Option<u8>,
pub world_restore_all_electric_locomotives_available_enabled: Option<bool>,
pub world_restore_issue_37_value: Option<u32>,
pub world_restore_issue_38_value: Option<u32>,
pub world_restore_issue_39_value: Option<u32>,
@ -70,6 +78,8 @@ pub struct RuntimeSummary {
pub world_restore_economic_tuning_mirror_value_f32_text: Option<String>,
pub world_restore_economic_tuning_lane_count: usize,
pub world_restore_economic_tuning_lane_value_f32_text: Vec<String>,
pub world_restore_cached_available_locomotive_rating_raw_u32: Option<u32>,
pub world_restore_cached_available_locomotive_rating_value_f32_text: Option<String>,
pub world_restore_selected_year_gap_scalar_raw_u32: Option<u32>,
pub world_restore_selected_year_gap_scalar_value_f32_text: Option<String>,
pub world_restore_absolute_counter_restore_kind: Option<String>,
@ -430,6 +440,37 @@ impl RuntimeSummary {
.world_restore
.economic_tuning_lane_value_f32_text
.clone(),
world_restore_linked_site_removal_follow_on_gate_raw_u8: state
.world_restore
.linked_site_removal_follow_on_gate_raw_u8,
world_restore_linked_site_removal_follow_on_gate_enabled: state
.world_restore
.linked_site_removal_follow_on_gate_enabled,
world_restore_all_steam_locomotives_available_raw_u8: state
.world_restore
.all_steam_locomotives_available_raw_u8,
world_restore_all_steam_locomotives_available_enabled: state
.world_restore
.all_steam_locomotives_available_enabled,
world_restore_all_diesel_locomotives_available_raw_u8: state
.world_restore
.all_diesel_locomotives_available_raw_u8,
world_restore_all_diesel_locomotives_available_enabled: state
.world_restore
.all_diesel_locomotives_available_enabled,
world_restore_all_electric_locomotives_available_raw_u8: state
.world_restore
.all_electric_locomotives_available_raw_u8,
world_restore_all_electric_locomotives_available_enabled: state
.world_restore
.all_electric_locomotives_available_enabled,
world_restore_cached_available_locomotive_rating_raw_u32: state
.world_restore
.cached_available_locomotive_rating_raw_u32,
world_restore_cached_available_locomotive_rating_value_f32_text: state
.world_restore
.cached_available_locomotive_rating_value_f32_text
.clone(),
world_restore_selected_year_gap_scalar_raw_u32: state
.world_restore
.selected_year_gap_scalar_raw_u32,
@ -1756,6 +1797,16 @@ mod tests {
"0.01".to_string(),
"0.01".to_string(),
],
linked_site_removal_follow_on_gate_raw_u8: Some(1),
linked_site_removal_follow_on_gate_enabled: Some(true),
all_steam_locomotives_available_raw_u8: Some(1),
all_steam_locomotives_available_enabled: Some(true),
all_diesel_locomotives_available_raw_u8: Some(0),
all_diesel_locomotives_available_enabled: Some(false),
all_electric_locomotives_available_raw_u8: Some(1),
all_electric_locomotives_available_enabled: Some(true),
cached_available_locomotive_rating_raw_u32: Some(0x41a00000),
cached_available_locomotive_rating_value_f32_text: Some("20.000000".to_string()),
selected_year_gap_scalar_raw_u32: Some(0x3eaaaaab),
selected_year_gap_scalar_value_f32_text: Some("0.333333".to_string()),
..RuntimeWorldRestoreState::default()
@ -1868,6 +1919,48 @@ mod tests {
.as_deref(),
Some("0.7766201")
);
assert_eq!(
summary.world_restore_linked_site_removal_follow_on_gate_raw_u8,
Some(1)
);
assert_eq!(
summary.world_restore_linked_site_removal_follow_on_gate_enabled,
Some(true)
);
assert_eq!(
summary.world_restore_all_steam_locomotives_available_raw_u8,
Some(1)
);
assert_eq!(
summary.world_restore_all_steam_locomotives_available_enabled,
Some(true)
);
assert_eq!(
summary.world_restore_all_diesel_locomotives_available_raw_u8,
Some(0)
);
assert_eq!(
summary.world_restore_all_diesel_locomotives_available_enabled,
Some(false)
);
assert_eq!(
summary.world_restore_all_electric_locomotives_available_raw_u8,
Some(1)
);
assert_eq!(
summary.world_restore_all_electric_locomotives_available_enabled,
Some(true)
);
assert_eq!(
summary.world_restore_cached_available_locomotive_rating_raw_u32,
Some(0x41a00000)
);
assert_eq!(
summary
.world_restore_cached_available_locomotive_rating_value_f32_text
.as_deref(),
Some("20.000000")
);
assert_eq!(summary.world_restore_economic_tuning_lane_count, 6);
assert_eq!(
summary.world_restore_economic_tuning_lane_value_f32_text,

View file

@ -169,6 +169,10 @@ The highest-value next passes are now:
- that stepped world-time path now also refreshes the derived selected-year gap scalar owner lane
`[world+0x4ca2]`, so later selected-year and periodic-boundary world work can build on runtime
state instead of a frozen load-time scalar
- that same save-native world restore surface now also carries the grounded locomotive-policy bytes
and cached available-locomotive rating from the fixed world block, so the `All
Steam/Diesel/Electric Locos Avail.` descriptor strip now writes through owner state instead of
living only as mirrored world flags
- the project rule on the remaining closure work is now explicit too: when one runtime-facing field
is still ambiguous, prefer rehosting the owning source state or real reader/setter family first
instead of guessing another derived leaf field from neighboring raw offsets

View file

@ -11,11 +11,11 @@ Working rule:
- Rehost the next selected-year periodic-boundary world seam under
`simulation_service_periodic_boundary_work`, starting with the save-world economic tuning mirror
`[world+0x0bde]` and any directly adjacent selected-year companion bands that can be refreshed
from stepped world time without shell ownership.
- Expand the selected-year world-owner surface beyond the new stepped calendar and gap-scalar
lanes when the owning reader/rebuild family is grounded strongly enough to avoid one-off leaf
guesses.
`[world+0x0bde]` and the directly adjacent selected-year bucket ladder rooted in the grounded
`0x00433bd0` reader family instead of another isolated scalar guess.
- Expand the selected-year world-owner surface beyond the stepped calendar, gap scalar, and
locomotive-policy lanes when the owning reader/rebuild family is grounded strongly enough to
avoid one-off leaf guesses.
## In Progress
@ -44,6 +44,9 @@ Working rule:
- Stepped calendar progression now also refreshes save-world owner time fields, including packed
year, packed tuple words, absolute counter, and the derived selected-year gap scalar.
- Automatic year-rollover calendar stepping now invokes periodic-boundary service.
- Save-native world locomotive policy owner state now flows through runtime restore state,
summaries, and keyed world-flag execution for the grounded `All Steam/Diesel/Electric Locos
Avail.` descriptor strip plus the cached available-locomotive rating.
- Company cash, confiscation, and major governance effects now write through owner state instead of
drifting from market/cache readers.
- Company credit rating, prime rate, book value per share, investor confidence, and management

View file

@ -217,7 +217,10 @@ the saved world absolute counter as first-class runtime restore state instead of
metadata, plus the packed year word and partial-year progress lane that feed the annual-finance
recent-history weighting path. Stepped world time now also refreshes the derived selected-year gap
scalar owner lane `[world+0x4ca2]`, so later selected-year periodic-boundary world work can build
on runtime state instead of a frozen load-time scalar. The same owned company annual-finance state
on runtime state instead of a frozen load-time scalar. That same save-native world restore surface
now also carries the grounded locomotive-policy bytes and cached available-locomotive rating from
the fixed world block, so the `All Steam/Diesel/Electric Locos Avail.` descriptor strip now writes
through owner state instead of living only as mirrored world flags. The same owned company annual-finance state
now also drives a shared company market reader seam for stock-capital, salary, bonus, and the full
two-word current/prior issue-calendar tuples, which is a better base for shellless finance
simulation than summary-only helpers. That same owned annual-finance state now also derives elapsed