Execute recovered world scalar event descriptors
This commit is contained in:
parent
09039d24e4
commit
13c7268b0d
23 changed files with 675 additions and 98 deletions
|
|
@ -4468,6 +4468,9 @@ mod tests {
|
|||
let scalar_band_parity_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(
|
||||
"../../fixtures/runtime/packed-event-world-scalar-band-parity-save-slice-fixture.json",
|
||||
);
|
||||
let world_scalar_executable_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(
|
||||
"../../fixtures/runtime/packed-event-world-scalar-executable-save-slice-fixture.json",
|
||||
);
|
||||
|
||||
run_runtime_summarize_fixture(&parity_fixture)
|
||||
.expect("save-slice-backed parity fixture should summarize");
|
||||
|
|
@ -4496,6 +4499,8 @@ mod tests {
|
|||
.expect("overlay-backed locomotive cost fixture should summarize");
|
||||
run_runtime_summarize_fixture(&scalar_band_parity_fixture)
|
||||
.expect("save-slice-backed recovered scalar-band parity fixture should summarize");
|
||||
run_runtime_summarize_fixture(&world_scalar_executable_fixture)
|
||||
.expect("save-slice-backed executable world-scalar fixture should summarize");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -186,6 +186,7 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState::default(),
|
||||
},
|
||||
|
|
@ -359,6 +360,7 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState::default(),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -58,6 +58,8 @@ pub struct ExpectedRuntimeSummary {
|
|||
#[serde(default)]
|
||||
pub world_restore_economic_status_code: Option<i32>,
|
||||
#[serde(default)]
|
||||
pub world_restore_territory_access_cost: Option<u32>,
|
||||
#[serde(default)]
|
||||
pub world_restore_absolute_counter_restore_kind: Option<String>,
|
||||
#[serde(default)]
|
||||
pub world_restore_absolute_counter_adjustment_context: Option<String>,
|
||||
|
|
@ -160,6 +162,8 @@ pub struct ExpectedRuntimeSummary {
|
|||
#[serde(default)]
|
||||
pub named_locomotive_cost_count: Option<usize>,
|
||||
#[serde(default)]
|
||||
pub cargo_production_override_count: Option<usize>,
|
||||
#[serde(default)]
|
||||
pub special_condition_count: Option<usize>,
|
||||
#[serde(default)]
|
||||
pub enabled_special_condition_count: Option<usize>,
|
||||
|
|
@ -373,6 +377,14 @@ impl ExpectedRuntimeSummary {
|
|||
));
|
||||
}
|
||||
}
|
||||
if let Some(value) = self.world_restore_territory_access_cost {
|
||||
if actual.world_restore_territory_access_cost != Some(value) {
|
||||
mismatches.push(format!(
|
||||
"world_restore_territory_access_cost mismatch: expected {value}, got {:?}",
|
||||
actual.world_restore_territory_access_cost
|
||||
));
|
||||
}
|
||||
}
|
||||
if let Some(kind) = &self.world_restore_absolute_counter_restore_kind {
|
||||
if actual.world_restore_absolute_counter_restore_kind.as_ref() != Some(kind) {
|
||||
mismatches.push(format!(
|
||||
|
|
@ -785,6 +797,14 @@ impl ExpectedRuntimeSummary {
|
|||
));
|
||||
}
|
||||
}
|
||||
if let Some(count) = self.cargo_production_override_count {
|
||||
if actual.cargo_production_override_count != count {
|
||||
mismatches.push(format!(
|
||||
"cargo_production_override_count mismatch: expected {count}, got {}",
|
||||
actual.cargo_production_override_count
|
||||
));
|
||||
}
|
||||
}
|
||||
if let Some(count) = self.special_condition_count {
|
||||
if actual.special_condition_count != count {
|
||||
mismatches.push(format!(
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@ struct SaveSliceProjection {
|
|||
candidate_availability: BTreeMap<String, u32>,
|
||||
named_locomotive_availability: BTreeMap<String, u32>,
|
||||
named_locomotive_cost: BTreeMap<String, u32>,
|
||||
cargo_production_overrides: BTreeMap<u32, u32>,
|
||||
special_conditions: BTreeMap<String, u32>,
|
||||
}
|
||||
|
||||
|
|
@ -251,6 +252,7 @@ pub fn project_save_slice_to_runtime_state_import(
|
|||
candidate_availability: projection.candidate_availability,
|
||||
named_locomotive_availability: projection.named_locomotive_availability,
|
||||
named_locomotive_cost: projection.named_locomotive_cost,
|
||||
cargo_production_overrides: projection.cargo_production_overrides,
|
||||
special_conditions: projection.special_conditions,
|
||||
service_state: RuntimeServiceState::default(),
|
||||
};
|
||||
|
|
@ -293,7 +295,10 @@ pub fn project_save_slice_overlay_to_runtime_state_import(
|
|||
calendar: base_state.calendar,
|
||||
world_flags,
|
||||
save_profile: projection.save_profile,
|
||||
world_restore: projection.world_restore,
|
||||
world_restore: RuntimeWorldRestoreState {
|
||||
territory_access_cost: base_state.world_restore.territory_access_cost,
|
||||
..projection.world_restore
|
||||
},
|
||||
metadata,
|
||||
companies: base_state.companies.clone(),
|
||||
selected_company_id: base_state.selected_company_id,
|
||||
|
|
@ -311,6 +316,7 @@ pub fn project_save_slice_overlay_to_runtime_state_import(
|
|||
candidate_availability: projection.candidate_availability,
|
||||
named_locomotive_availability: projection.named_locomotive_availability,
|
||||
named_locomotive_cost: base_state.named_locomotive_cost.clone(),
|
||||
cargo_production_overrides: base_state.cargo_production_overrides.clone(),
|
||||
special_conditions: projection.special_conditions,
|
||||
service_state: base_state.service_state.clone(),
|
||||
};
|
||||
|
|
@ -554,6 +560,7 @@ fn project_save_slice_components(
|
|||
ai_ignore_territories_at_startup_enabled: special_condition_enabled(34),
|
||||
limited_track_building_amount: None,
|
||||
economic_status_code: None,
|
||||
territory_access_cost: None,
|
||||
absolute_counter_restore_kind: Some(
|
||||
"mode-adjusted-selected-year-lane".to_string(),
|
||||
),
|
||||
|
|
@ -640,6 +647,7 @@ fn project_save_slice_components(
|
|||
}
|
||||
|
||||
let named_locomotive_cost = BTreeMap::new();
|
||||
let cargo_production_overrides = BTreeMap::new();
|
||||
|
||||
for (index, note) in save_slice.notes.iter().enumerate() {
|
||||
metadata.insert(format!("save_slice.note.{index}"), note.clone());
|
||||
|
|
@ -655,6 +663,7 @@ fn project_save_slice_components(
|
|||
candidate_availability,
|
||||
named_locomotive_availability,
|
||||
named_locomotive_cost,
|
||||
cargo_production_overrides,
|
||||
special_conditions,
|
||||
})
|
||||
}
|
||||
|
|
@ -978,6 +987,14 @@ fn lower_contextual_real_grouped_effects(
|
|||
|
||||
let mut effects = Vec::with_capacity(record.grouped_effect_rows.len());
|
||||
for row in &record.grouped_effect_rows {
|
||||
if let Some(effect) = lower_contextual_cargo_production_effect(row)? {
|
||||
effects.push(effect);
|
||||
continue;
|
||||
}
|
||||
if let Some(effect) = lower_contextual_territory_access_cost_effect(row)? {
|
||||
effects.push(effect);
|
||||
continue;
|
||||
}
|
||||
if let Some(effect) = lower_contextual_locomotive_cost_effect(row, company_context)? {
|
||||
effects.push(effect);
|
||||
continue;
|
||||
|
|
@ -1011,10 +1028,8 @@ fn lower_contextual_locomotive_availability_effect(
|
|||
if row.row_shape != "scalar_assignment" {
|
||||
return Ok(None);
|
||||
}
|
||||
let value = match row.raw_scalar_value {
|
||||
0 => false,
|
||||
1 => true,
|
||||
_ => return Ok(None),
|
||||
let Some(value) = u32::try_from(row.raw_scalar_value).ok() else {
|
||||
return Ok(None);
|
||||
};
|
||||
let Some(locomotive_id) = row.recovered_locomotive_id else {
|
||||
return Ok(None);
|
||||
|
|
@ -1026,12 +1041,48 @@ fn lower_contextual_locomotive_availability_effect(
|
|||
else {
|
||||
return Err(ImportBlocker::MissingLocomotiveCatalogContext);
|
||||
};
|
||||
Ok(Some(RuntimeEffect::SetNamedLocomotiveAvailability {
|
||||
Ok(Some(RuntimeEffect::SetNamedLocomotiveAvailabilityValue {
|
||||
name,
|
||||
value,
|
||||
}))
|
||||
}
|
||||
|
||||
fn lower_contextual_cargo_production_effect(
|
||||
row: &SmpLoadedPackedEventGroupedEffectRowSummary,
|
||||
) -> Result<Option<RuntimeEffect>, ImportBlocker> {
|
||||
if row.parameter_family.as_deref() != Some("cargo_production_scalar") {
|
||||
return Ok(None);
|
||||
}
|
||||
if row.row_shape != "scalar_assignment" {
|
||||
return Ok(None);
|
||||
}
|
||||
let Some(value) = u32::try_from(row.raw_scalar_value).ok() else {
|
||||
return Ok(None);
|
||||
};
|
||||
let Some(slot) = row.descriptor_id.checked_sub(229) else {
|
||||
return Ok(None);
|
||||
};
|
||||
if !(1..=11).contains(&slot) {
|
||||
return Ok(None);
|
||||
}
|
||||
Ok(Some(RuntimeEffect::SetCargoProductionSlot { slot, value }))
|
||||
}
|
||||
|
||||
fn lower_contextual_territory_access_cost_effect(
|
||||
row: &SmpLoadedPackedEventGroupedEffectRowSummary,
|
||||
) -> Result<Option<RuntimeEffect>, ImportBlocker> {
|
||||
if row.parameter_family.as_deref() != Some("territory_access_cost_scalar") {
|
||||
return Ok(None);
|
||||
}
|
||||
if row.row_shape != "scalar_assignment" {
|
||||
return Ok(None);
|
||||
}
|
||||
let Some(value) = u32::try_from(row.raw_scalar_value).ok() else {
|
||||
return Ok(None);
|
||||
};
|
||||
Ok(Some(RuntimeEffect::SetTerritoryAccessCost { value }))
|
||||
}
|
||||
|
||||
fn lower_contextual_locomotive_cost_effect(
|
||||
row: &SmpLoadedPackedEventGroupedEffectRowSummary,
|
||||
company_context: &ImportRuntimeContext,
|
||||
|
|
@ -1288,12 +1339,27 @@ fn lower_condition_targets_in_effect(
|
|||
value: *value,
|
||||
}
|
||||
}
|
||||
RuntimeEffect::SetNamedLocomotiveAvailabilityValue { name, value } => {
|
||||
RuntimeEffect::SetNamedLocomotiveAvailabilityValue {
|
||||
name: name.clone(),
|
||||
value: *value,
|
||||
}
|
||||
}
|
||||
RuntimeEffect::SetNamedLocomotiveCost { name, value } => {
|
||||
RuntimeEffect::SetNamedLocomotiveCost {
|
||||
name: name.clone(),
|
||||
value: *value,
|
||||
}
|
||||
}
|
||||
RuntimeEffect::SetCargoProductionSlot { slot, value } => {
|
||||
RuntimeEffect::SetCargoProductionSlot {
|
||||
slot: *slot,
|
||||
value: *value,
|
||||
}
|
||||
}
|
||||
RuntimeEffect::SetTerritoryAccessCost { value } => {
|
||||
RuntimeEffect::SetTerritoryAccessCost { value: *value }
|
||||
}
|
||||
RuntimeEffect::SetSpecialCondition { label, value } => RuntimeEffect::SetSpecialCondition {
|
||||
label: label.clone(),
|
||||
value: *value,
|
||||
|
|
@ -1729,12 +1795,27 @@ fn smp_runtime_effect_to_runtime_effect(
|
|||
value: *value,
|
||||
})
|
||||
}
|
||||
RuntimeEffect::SetNamedLocomotiveAvailabilityValue { name, value } => {
|
||||
Ok(RuntimeEffect::SetNamedLocomotiveAvailabilityValue {
|
||||
name: name.clone(),
|
||||
value: *value,
|
||||
})
|
||||
}
|
||||
RuntimeEffect::SetNamedLocomotiveCost { name, value } => {
|
||||
Ok(RuntimeEffect::SetNamedLocomotiveCost {
|
||||
name: name.clone(),
|
||||
value: *value,
|
||||
})
|
||||
}
|
||||
RuntimeEffect::SetCargoProductionSlot { slot, value } => {
|
||||
Ok(RuntimeEffect::SetCargoProductionSlot {
|
||||
slot: *slot,
|
||||
value: *value,
|
||||
})
|
||||
}
|
||||
RuntimeEffect::SetTerritoryAccessCost { value } => {
|
||||
Ok(RuntimeEffect::SetTerritoryAccessCost { value: *value })
|
||||
}
|
||||
RuntimeEffect::SetSpecialCondition { label, value } => {
|
||||
Ok(RuntimeEffect::SetSpecialCondition {
|
||||
label: label.clone(),
|
||||
|
|
@ -2296,7 +2377,10 @@ fn runtime_effect_uses_condition_true_company(effect: &RuntimeEffect) -> bool {
|
|||
| RuntimeEffect::DeactivatePlayer { .. }
|
||||
| RuntimeEffect::SetCandidateAvailability { .. }
|
||||
| RuntimeEffect::SetNamedLocomotiveAvailability { .. }
|
||||
| RuntimeEffect::SetNamedLocomotiveAvailabilityValue { .. }
|
||||
| RuntimeEffect::SetNamedLocomotiveCost { .. }
|
||||
| RuntimeEffect::SetCargoProductionSlot { .. }
|
||||
| RuntimeEffect::SetTerritoryAccessCost { .. }
|
||||
| RuntimeEffect::SetSpecialCondition { .. }
|
||||
| RuntimeEffect::ActivateEventRecord { .. }
|
||||
| RuntimeEffect::DeactivateEventRecord { .. }
|
||||
|
|
@ -2375,7 +2459,10 @@ fn runtime_effect_company_target_import_blocker(
|
|||
| RuntimeEffect::SetEconomicStatusCode { .. }
|
||||
| RuntimeEffect::SetCandidateAvailability { .. }
|
||||
| RuntimeEffect::SetNamedLocomotiveAvailability { .. }
|
||||
| RuntimeEffect::SetNamedLocomotiveAvailabilityValue { .. }
|
||||
| RuntimeEffect::SetNamedLocomotiveCost { .. }
|
||||
| RuntimeEffect::SetCargoProductionSlot { .. }
|
||||
| RuntimeEffect::SetTerritoryAccessCost { .. }
|
||||
| RuntimeEffect::SetSpecialCondition { .. }
|
||||
| RuntimeEffect::ActivateEventRecord { .. }
|
||||
| RuntimeEffect::DeactivateEventRecord { .. }
|
||||
|
|
@ -2717,6 +2804,7 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState::default(),
|
||||
}
|
||||
|
|
@ -4882,7 +4970,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn leaves_recovered_locomotive_availability_rows_blocked_unmapped_world_descriptor() {
|
||||
fn blocks_scalar_locomotive_availability_rows_without_catalog_context() {
|
||||
let save_slice = SmpLoadedSaveSlice {
|
||||
file_extension_hint: Some("gms".to_string()),
|
||||
container_profile_family: Some("rt3-classic-save-container-v1".to_string()),
|
||||
|
|
@ -4953,7 +5041,7 @@ mod tests {
|
|||
executable_import_ready: false,
|
||||
notes: vec![
|
||||
"decoded from grounded real 0x4e9a row framing".to_string(),
|
||||
"recovered locomotive availability descriptor family remains parity-only"
|
||||
"scalar locomotive availability rows still need catalog context"
|
||||
.to_string(),
|
||||
],
|
||||
}],
|
||||
|
|
@ -4975,7 +5063,7 @@ mod tests {
|
|||
.packed_event_collection
|
||||
.as_ref()
|
||||
.and_then(|summary| summary.records[0].import_outcome.as_deref()),
|
||||
Some("blocked_unmapped_world_descriptor")
|
||||
Some("blocked_missing_locomotive_catalog_context")
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -5056,7 +5144,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn overlays_boolean_locomotive_availability_rows_into_named_availability_effects() {
|
||||
fn overlays_scalar_locomotive_availability_rows_into_named_availability_effects() {
|
||||
let base_state = RuntimeState {
|
||||
calendar: CalendarPoint {
|
||||
year: 1845,
|
||||
|
|
@ -5094,6 +5182,7 @@ mod tests {
|
|||
("Locomotive 112".to_string(), 1),
|
||||
]),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState::default(),
|
||||
};
|
||||
|
|
@ -5141,14 +5230,14 @@ mod tests {
|
|||
negative_sentinel_scope: None,
|
||||
grouped_effect_row_counts: vec![2, 0, 0, 0],
|
||||
grouped_effect_rows: vec![
|
||||
real_locomotive_availability_row(250, 1),
|
||||
real_locomotive_availability_row(457, 0),
|
||||
real_locomotive_availability_row(250, 42),
|
||||
real_locomotive_availability_row(457, 7),
|
||||
],
|
||||
decoded_conditions: Vec::new(),
|
||||
decoded_actions: vec![],
|
||||
executable_import_ready: false,
|
||||
notes: vec![
|
||||
"boolean locomotive availability rows use overlay catalog context"
|
||||
"scalar locomotive availability rows use overlay catalog context"
|
||||
.to_string(),
|
||||
],
|
||||
}],
|
||||
|
|
@ -5185,14 +5274,14 @@ mod tests {
|
|||
.state
|
||||
.named_locomotive_availability
|
||||
.get("Locomotive 10"),
|
||||
Some(&1)
|
||||
Some(&42)
|
||||
);
|
||||
assert_eq!(
|
||||
import
|
||||
.state
|
||||
.named_locomotive_availability
|
||||
.get("Locomotive 112"),
|
||||
Some(&0)
|
||||
Some(&7)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -5385,6 +5474,7 @@ mod tests {
|
|||
("Locomotive 1".to_string(), 100000),
|
||||
("Locomotive 101".to_string(), 200000),
|
||||
]),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState::default(),
|
||||
};
|
||||
|
|
@ -5554,7 +5644,7 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn keeps_recovered_cargo_production_rows_parity_only() {
|
||||
fn imports_recovered_cargo_production_rows_into_runtime_records() {
|
||||
let save_slice = SmpLoadedSaveSlice {
|
||||
file_extension_hint: Some("gms".to_string()),
|
||||
container_profile_family: Some("rt3-classic-save-container-v1".to_string()),
|
||||
|
|
@ -5602,32 +5692,42 @@ mod tests {
|
|||
decoded_conditions: Vec::new(),
|
||||
decoded_actions: vec![],
|
||||
executable_import_ready: false,
|
||||
notes: vec!["cargo production rows remain metadata-only".to_string()],
|
||||
notes: vec![
|
||||
"cargo production rows now import through world overrides".to_string(),
|
||||
],
|
||||
}],
|
||||
}),
|
||||
notes: vec![],
|
||||
};
|
||||
|
||||
let import = project_save_slice_to_runtime_state_import(
|
||||
let mut import = project_save_slice_to_runtime_state_import(
|
||||
&save_slice,
|
||||
"packed-events-cargo-production-frontier",
|
||||
None,
|
||||
)
|
||||
.expect("save slice should project");
|
||||
|
||||
assert!(import.state.event_runtime_records.is_empty());
|
||||
assert_eq!(import.state.event_runtime_records.len(), 1);
|
||||
assert_eq!(
|
||||
import
|
||||
.state
|
||||
.packed_event_collection
|
||||
.as_ref()
|
||||
.and_then(|summary| summary.records[0].import_outcome.as_deref()),
|
||||
Some("blocked_unmapped_world_descriptor")
|
||||
Some("imported")
|
||||
);
|
||||
|
||||
execute_step_command(
|
||||
&mut import.state,
|
||||
&StepCommand::ServiceTriggerKind { trigger_kind: 7 },
|
||||
)
|
||||
.expect("cargo production runtime record should run");
|
||||
|
||||
assert_eq!(import.state.cargo_production_overrides.get(&1), Some(&125));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keeps_recovered_territory_access_cost_rows_parity_only() {
|
||||
fn imports_recovered_territory_access_cost_rows_into_runtime_records() {
|
||||
let save_slice = SmpLoadedSaveSlice {
|
||||
file_extension_hint: Some("gms".to_string()),
|
||||
container_profile_family: Some("rt3-classic-save-container-v1".to_string()),
|
||||
|
|
@ -5675,27 +5775,40 @@ mod tests {
|
|||
decoded_conditions: Vec::new(),
|
||||
decoded_actions: vec![],
|
||||
executable_import_ready: false,
|
||||
notes: vec!["territory access cost rows remain metadata-only".to_string()],
|
||||
notes: vec![
|
||||
"territory access cost rows now import through world restore".to_string(),
|
||||
],
|
||||
}],
|
||||
}),
|
||||
notes: vec![],
|
||||
};
|
||||
|
||||
let import = project_save_slice_to_runtime_state_import(
|
||||
let mut import = project_save_slice_to_runtime_state_import(
|
||||
&save_slice,
|
||||
"packed-events-territory-access-cost-frontier",
|
||||
None,
|
||||
)
|
||||
.expect("save slice should project");
|
||||
|
||||
assert!(import.state.event_runtime_records.is_empty());
|
||||
assert_eq!(import.state.event_runtime_records.len(), 1);
|
||||
assert_eq!(
|
||||
import
|
||||
.state
|
||||
.packed_event_collection
|
||||
.as_ref()
|
||||
.and_then(|summary| summary.records[0].import_outcome.as_deref()),
|
||||
Some("blocked_unmapped_world_descriptor")
|
||||
Some("imported")
|
||||
);
|
||||
|
||||
execute_step_command(
|
||||
&mut import.state,
|
||||
&StepCommand::ServiceTriggerKind { trigger_kind: 7 },
|
||||
)
|
||||
.expect("territory access cost runtime record should run");
|
||||
|
||||
assert_eq!(
|
||||
import.state.world_restore.territory_access_cost,
|
||||
Some(750000)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -5736,6 +5849,7 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState::default(),
|
||||
};
|
||||
|
|
@ -8596,6 +8710,7 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState {
|
||||
periodic_boundary_calls: 9,
|
||||
|
|
@ -8766,6 +8881,7 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState::default(),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState::default(),
|
||||
},
|
||||
|
|
|
|||
|
|
@ -317,10 +317,21 @@ pub enum RuntimeEffect {
|
|||
name: String,
|
||||
value: bool,
|
||||
},
|
||||
SetNamedLocomotiveAvailabilityValue {
|
||||
name: String,
|
||||
value: u32,
|
||||
},
|
||||
SetNamedLocomotiveCost {
|
||||
name: String,
|
||||
value: u32,
|
||||
},
|
||||
SetCargoProductionSlot {
|
||||
slot: u32,
|
||||
value: u32,
|
||||
},
|
||||
SetTerritoryAccessCost {
|
||||
value: u32,
|
||||
},
|
||||
SetSpecialCondition {
|
||||
label: String,
|
||||
value: u32,
|
||||
|
|
@ -614,6 +625,8 @@ pub struct RuntimeWorldRestoreState {
|
|||
#[serde(default)]
|
||||
pub economic_status_code: Option<i32>,
|
||||
#[serde(default)]
|
||||
pub territory_access_cost: Option<u32>,
|
||||
#[serde(default)]
|
||||
pub absolute_counter_restore_kind: Option<String>,
|
||||
#[serde(default)]
|
||||
pub absolute_counter_adjustment_context: Option<String>,
|
||||
|
|
@ -659,6 +672,8 @@ pub struct RuntimeState {
|
|||
#[serde(default)]
|
||||
pub named_locomotive_cost: BTreeMap<String, u32>,
|
||||
#[serde(default)]
|
||||
pub cargo_production_overrides: BTreeMap<u32, u32>,
|
||||
#[serde(default)]
|
||||
pub special_conditions: BTreeMap<String, u32>,
|
||||
#[serde(default)]
|
||||
pub service_state: RuntimeServiceState,
|
||||
|
|
@ -1173,6 +1188,14 @@ impl RuntimeState {
|
|||
return Err("named_locomotive_cost contains an empty key".to_string());
|
||||
}
|
||||
}
|
||||
for slot in self.cargo_production_overrides.keys() {
|
||||
if !(1..=11).contains(slot) {
|
||||
return Err(format!(
|
||||
"cargo_production_overrides contains out-of-range slot {}",
|
||||
slot
|
||||
));
|
||||
}
|
||||
}
|
||||
for key in self.special_conditions.keys() {
|
||||
if key.trim().is_empty() {
|
||||
return Err("special_conditions contains an empty key".to_string());
|
||||
|
|
@ -1249,11 +1272,22 @@ fn validate_runtime_effect(
|
|||
return Err("name must not be empty".to_string());
|
||||
}
|
||||
}
|
||||
RuntimeEffect::SetNamedLocomotiveAvailabilityValue { name, .. } => {
|
||||
if name.trim().is_empty() {
|
||||
return Err("name must not be empty".to_string());
|
||||
}
|
||||
}
|
||||
RuntimeEffect::SetNamedLocomotiveCost { name, .. } => {
|
||||
if name.trim().is_empty() {
|
||||
return Err("name must not be empty".to_string());
|
||||
}
|
||||
}
|
||||
RuntimeEffect::SetCargoProductionSlot { slot, .. } => {
|
||||
if !(1..=11).contains(slot) {
|
||||
return Err("slot must be in 1..=11".to_string());
|
||||
}
|
||||
}
|
||||
RuntimeEffect::SetTerritoryAccessCost { .. } => {}
|
||||
RuntimeEffect::SetSpecialCondition { label, .. } => {
|
||||
if label.trim().is_empty() {
|
||||
return Err("label must not be empty".to_string());
|
||||
|
|
@ -1476,6 +1510,7 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState::default(),
|
||||
};
|
||||
|
|
@ -1512,6 +1547,7 @@ mod tests {
|
|||
ai_ignore_territories_at_startup_enabled: Some(false),
|
||||
limited_track_building_amount: None,
|
||||
economic_status_code: None,
|
||||
territory_access_cost: None,
|
||||
absolute_counter_restore_kind: Some(
|
||||
"mode-adjusted-selected-year-lane".to_string(),
|
||||
),
|
||||
|
|
@ -1534,6 +1570,7 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState::default(),
|
||||
};
|
||||
|
|
@ -1591,6 +1628,7 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState::default(),
|
||||
};
|
||||
|
|
@ -1658,6 +1696,7 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState::default(),
|
||||
};
|
||||
|
|
@ -1756,6 +1795,7 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState::default(),
|
||||
};
|
||||
|
|
@ -1800,6 +1840,7 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState::default(),
|
||||
};
|
||||
|
|
@ -1844,6 +1885,7 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState::default(),
|
||||
};
|
||||
|
|
@ -1905,6 +1947,7 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState::default(),
|
||||
};
|
||||
|
|
@ -1956,6 +1999,7 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState::default(),
|
||||
};
|
||||
|
|
@ -2011,6 +2055,7 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState::default(),
|
||||
};
|
||||
|
|
@ -2062,6 +2107,7 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState::default(),
|
||||
};
|
||||
|
|
@ -2119,6 +2165,7 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState::default(),
|
||||
};
|
||||
|
|
@ -2170,6 +2217,7 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState::default(),
|
||||
};
|
||||
|
|
@ -2221,6 +2269,7 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState::default(),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2838,7 +2838,7 @@ fn recovered_cargo_production_descriptor_metadata(
|
|||
target_mask_bits: 0x08,
|
||||
parameter_family: "cargo_production_scalar",
|
||||
runtime_key: None,
|
||||
executable_in_runtime: false,
|
||||
executable_in_runtime: true,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -2951,7 +2951,7 @@ fn recovered_territory_access_cost_descriptor_metadata(
|
|||
target_mask_bits: 0x08,
|
||||
parameter_family: "territory_access_cost_scalar",
|
||||
runtime_key: None,
|
||||
executable_in_runtime: false,
|
||||
executable_in_runtime: true,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -3241,6 +3241,28 @@ fn decode_real_grouped_effect_action(
|
|||
});
|
||||
}
|
||||
|
||||
if descriptor_metadata.executable_in_runtime
|
||||
&& descriptor_metadata.parameter_family == "cargo_production_scalar"
|
||||
&& row.row_shape == "scalar_assignment"
|
||||
&& row.raw_scalar_value >= 0
|
||||
{
|
||||
let slot = descriptor_metadata.descriptor_id.checked_sub(229)?;
|
||||
return Some(RuntimeEffect::SetCargoProductionSlot {
|
||||
slot,
|
||||
value: row.raw_scalar_value as u32,
|
||||
});
|
||||
}
|
||||
|
||||
if descriptor_metadata.executable_in_runtime
|
||||
&& descriptor_metadata.parameter_family == "territory_access_cost_scalar"
|
||||
&& row.row_shape == "scalar_assignment"
|
||||
&& row.raw_scalar_value >= 0
|
||||
{
|
||||
return Some(RuntimeEffect::SetTerritoryAccessCost {
|
||||
value: row.raw_scalar_value as u32,
|
||||
});
|
||||
}
|
||||
|
||||
if descriptor_metadata.executable_in_runtime
|
||||
&& descriptor_metadata.parameter_family == "world_flag_toggle"
|
||||
&& row.row_shape == "bool_toggle"
|
||||
|
|
@ -3489,7 +3511,10 @@ fn runtime_effect_supported_for_save_import(effect: &RuntimeEffect) -> bool {
|
|||
| RuntimeEffect::SetEconomicStatusCode { .. }
|
||||
| RuntimeEffect::SetCandidateAvailability { .. }
|
||||
| RuntimeEffect::SetNamedLocomotiveAvailability { .. }
|
||||
| RuntimeEffect::SetNamedLocomotiveAvailabilityValue { .. }
|
||||
| RuntimeEffect::SetNamedLocomotiveCost { .. }
|
||||
| RuntimeEffect::SetCargoProductionSlot { .. }
|
||||
| RuntimeEffect::SetTerritoryAccessCost { .. }
|
||||
| RuntimeEffect::SetSpecialCondition { .. }
|
||||
| RuntimeEffect::ConfiscateCompanyAssets { .. }
|
||||
| RuntimeEffect::DeactivateCompany { .. }
|
||||
|
|
@ -9345,7 +9370,7 @@ mod tests {
|
|||
assert_eq!(metadata.target_mask_bits, 0x08);
|
||||
assert_eq!(metadata.parameter_family, "cargo_production_scalar");
|
||||
assert_eq!(metadata.runtime_key, None);
|
||||
assert!(!metadata.executable_in_runtime);
|
||||
assert!(metadata.executable_in_runtime);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -9381,7 +9406,7 @@ mod tests {
|
|||
assert_eq!(metadata.target_mask_bits, 0x08);
|
||||
assert_eq!(metadata.parameter_family, "territory_access_cost_scalar");
|
||||
assert_eq!(metadata.runtime_key, None);
|
||||
assert!(!metadata.executable_in_runtime);
|
||||
assert!(metadata.executable_in_runtime);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -495,9 +495,20 @@ fn apply_runtime_effects(
|
|||
.named_locomotive_availability
|
||||
.insert(name.clone(), u32::from(*value));
|
||||
}
|
||||
RuntimeEffect::SetNamedLocomotiveAvailabilityValue { name, value } => {
|
||||
state
|
||||
.named_locomotive_availability
|
||||
.insert(name.clone(), *value);
|
||||
}
|
||||
RuntimeEffect::SetNamedLocomotiveCost { name, value } => {
|
||||
state.named_locomotive_cost.insert(name.clone(), *value);
|
||||
}
|
||||
RuntimeEffect::SetCargoProductionSlot { slot, value } => {
|
||||
state.cargo_production_overrides.insert(*slot, *value);
|
||||
}
|
||||
RuntimeEffect::SetTerritoryAccessCost { value } => {
|
||||
state.world_restore.territory_access_cost = Some(*value);
|
||||
}
|
||||
RuntimeEffect::SetSpecialCondition { label, value } => {
|
||||
state.special_conditions.insert(label.clone(), *value);
|
||||
}
|
||||
|
|
@ -1169,6 +1180,7 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState::default(),
|
||||
}
|
||||
|
|
@ -1457,6 +1469,80 @@ mod tests {
|
|||
assert_eq!(result.service_events[0].applied_effect_count, 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn applies_scalar_named_locomotive_availability_effects() {
|
||||
let mut state = RuntimeState {
|
||||
event_runtime_records: vec![RuntimeEventRecord {
|
||||
record_id: 12,
|
||||
trigger_kind: 7,
|
||||
active: true,
|
||||
service_count: 0,
|
||||
marks_collection_dirty: false,
|
||||
one_shot: false,
|
||||
has_fired: false,
|
||||
conditions: Vec::new(),
|
||||
effects: vec![
|
||||
RuntimeEffect::SetNamedLocomotiveAvailabilityValue {
|
||||
name: "Big Boy".to_string(),
|
||||
value: 42,
|
||||
},
|
||||
RuntimeEffect::SetNamedLocomotiveAvailabilityValue {
|
||||
name: "GP7".to_string(),
|
||||
value: 7,
|
||||
},
|
||||
],
|
||||
}],
|
||||
..state()
|
||||
};
|
||||
|
||||
let result = execute_step_command(
|
||||
&mut state,
|
||||
&StepCommand::ServiceTriggerKind { trigger_kind: 7 },
|
||||
)
|
||||
.expect("scalar named locomotive availability effects should succeed");
|
||||
|
||||
assert_eq!(
|
||||
state.named_locomotive_availability.get("Big Boy"),
|
||||
Some(&42)
|
||||
);
|
||||
assert_eq!(state.named_locomotive_availability.get("GP7"), Some(&7));
|
||||
assert_eq!(result.service_events[0].applied_effect_count, 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn applies_world_scalar_override_effects() {
|
||||
let mut state = RuntimeState {
|
||||
event_runtime_records: vec![RuntimeEventRecord {
|
||||
record_id: 13,
|
||||
trigger_kind: 7,
|
||||
active: true,
|
||||
service_count: 0,
|
||||
marks_collection_dirty: false,
|
||||
one_shot: false,
|
||||
has_fired: false,
|
||||
conditions: Vec::new(),
|
||||
effects: vec![
|
||||
RuntimeEffect::SetCargoProductionSlot {
|
||||
slot: 1,
|
||||
value: 125,
|
||||
},
|
||||
RuntimeEffect::SetTerritoryAccessCost { value: 750000 },
|
||||
],
|
||||
}],
|
||||
..state()
|
||||
};
|
||||
|
||||
let result = execute_step_command(
|
||||
&mut state,
|
||||
&StepCommand::ServiceTriggerKind { trigger_kind: 7 },
|
||||
)
|
||||
.expect("world scalar override effects should succeed");
|
||||
|
||||
assert_eq!(state.cargo_production_overrides.get(&1), Some(&125));
|
||||
assert_eq!(state.world_restore.territory_access_cost, Some(750000));
|
||||
assert_eq!(result.service_events[0].applied_effect_count, 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resolves_symbolic_company_targets() {
|
||||
let mut state = RuntimeState {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ pub struct RuntimeSummary {
|
|||
pub world_restore_ai_ignore_territories_at_startup_enabled: Option<bool>,
|
||||
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_absolute_counter_restore_kind: Option<String>,
|
||||
pub world_restore_absolute_counter_adjustment_context: Option<String>,
|
||||
pub metadata_count: usize,
|
||||
|
|
@ -77,6 +78,7 @@ pub struct RuntimeSummary {
|
|||
pub named_locomotive_availability_count: usize,
|
||||
pub zero_named_locomotive_availability_count: usize,
|
||||
pub named_locomotive_cost_count: usize,
|
||||
pub cargo_production_override_count: usize,
|
||||
pub special_condition_count: usize,
|
||||
pub enabled_special_condition_count: usize,
|
||||
pub save_profile_kind: Option<String>,
|
||||
|
|
@ -149,6 +151,7 @@ impl RuntimeSummary {
|
|||
.world_restore
|
||||
.limited_track_building_amount,
|
||||
world_restore_economic_status_code: state.world_restore.economic_status_code,
|
||||
world_restore_territory_access_cost: state.world_restore.territory_access_cost,
|
||||
world_restore_absolute_counter_restore_kind: state
|
||||
.world_restore
|
||||
.absolute_counter_restore_kind
|
||||
|
|
@ -597,6 +600,7 @@ impl RuntimeSummary {
|
|||
.filter(|value| **value == 0)
|
||||
.count(),
|
||||
named_locomotive_cost_count: state.named_locomotive_cost.len(),
|
||||
cargo_production_override_count: state.cargo_production_overrides.len(),
|
||||
special_condition_count: state.special_conditions.len(),
|
||||
enabled_special_condition_count: state
|
||||
.special_conditions
|
||||
|
|
@ -820,6 +824,7 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState::default(),
|
||||
};
|
||||
|
|
@ -920,6 +925,7 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState::default(),
|
||||
};
|
||||
|
|
@ -969,6 +975,7 @@ mod tests {
|
|||
("Mikado".to_string(), 0),
|
||||
]),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState::default(),
|
||||
};
|
||||
|
|
@ -1010,6 +1017,7 @@ mod tests {
|
|||
("Big Boy".to_string(), 250000),
|
||||
("GP7".to_string(), 175000),
|
||||
]),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState::default(),
|
||||
};
|
||||
|
|
@ -1019,6 +1027,47 @@ mod tests {
|
|||
assert_eq!(summary.named_locomotive_cost_count, 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn counts_world_scalar_override_surfaces() {
|
||||
let state = RuntimeState {
|
||||
calendar: CalendarPoint {
|
||||
year: 1830,
|
||||
month_slot: 0,
|
||||
phase_slot: 0,
|
||||
tick_slot: 0,
|
||||
},
|
||||
world_flags: BTreeMap::new(),
|
||||
save_profile: RuntimeSaveProfileState::default(),
|
||||
world_restore: RuntimeWorldRestoreState {
|
||||
territory_access_cost: Some(750000),
|
||||
..RuntimeWorldRestoreState::default()
|
||||
},
|
||||
metadata: BTreeMap::new(),
|
||||
companies: Vec::new(),
|
||||
selected_company_id: None,
|
||||
players: Vec::new(),
|
||||
selected_player_id: None,
|
||||
trains: Vec::new(),
|
||||
locomotive_catalog: Vec::new(),
|
||||
territories: Vec::new(),
|
||||
company_territory_track_piece_counts: Vec::new(),
|
||||
company_territory_access: Vec::new(),
|
||||
packed_event_collection: None,
|
||||
event_runtime_records: Vec::new(),
|
||||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::from([(1, 125), (2, 250)]),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState::default(),
|
||||
};
|
||||
|
||||
let summary = RuntimeSummary::from_state(&state);
|
||||
|
||||
assert_eq!(summary.cargo_production_override_count, 2);
|
||||
assert_eq!(summary.world_restore_territory_access_cost, Some(750000));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn counts_world_frontier_buckets_separately() {
|
||||
let state = RuntimeState {
|
||||
|
|
@ -1110,6 +1159,7 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState::default(),
|
||||
};
|
||||
|
|
@ -1189,6 +1239,7 @@ mod tests {
|
|||
candidate_availability: BTreeMap::new(),
|
||||
named_locomotive_availability: BTreeMap::new(),
|
||||
named_locomotive_cost: BTreeMap::new(),
|
||||
cargo_production_overrides: BTreeMap::new(),
|
||||
special_conditions: BTreeMap::new(),
|
||||
service_state: RuntimeServiceState::default(),
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue