Rehost selected-year bucket companion bands
This commit is contained in:
parent
f9b3cf8571
commit
b5d194f678
9 changed files with 326 additions and 20 deletions
|
|
@ -129,7 +129,10 @@ living only as ad hoc world flags.
|
||||||
The selected-year seam is now doing the same thing: the checked-in `0x00433bd0` year ladder now
|
The selected-year seam is now doing the same thing: the checked-in `0x00433bd0` year ladder now
|
||||||
drives a derived selected-year bucket scalar in runtime restore state, and the economic-tuning
|
drives a derived selected-year bucket scalar in runtime restore state, and the economic-tuning
|
||||||
mirror `[world+0x0bde]` now rebuilds from tuning lane `0` instead of freezing one stale load-time
|
mirror `[world+0x0bde]` now rebuilds from tuning lane `0` instead of freezing one stale load-time
|
||||||
word.
|
word. That same checked-in owner family now also rebuilds the direct bucket trio
|
||||||
|
`[world+0x65/+0x69/+0x6d]`, the complement trio `[world+0x71/+0x75/+0x79]`, and the scaled
|
||||||
|
companion trio `[world+0x7d/+0x81/+0x85]` from the selected-year bucket scalar instead of
|
||||||
|
preserving stale save-time residue.
|
||||||
Those bankruptcy branches now follow the grounded owner semantics too: they stamp the bankruptcy
|
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.
|
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
|
The same save-native live bond-slot surface now also carries per-slot maturity years all the way
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,26 @@
|
||||||
"pair_count": 21,
|
"pair_count": 21,
|
||||||
"terminal_scalar_virtual_address": "0x005f3a24",
|
"terminal_scalar_virtual_address": "0x005f3a24",
|
||||||
"terminal_scalar_value": 123.0,
|
"terminal_scalar_value": 123.0,
|
||||||
|
"direct_lane_multipliers": [
|
||||||
|
0.9,
|
||||||
|
1.05,
|
||||||
|
0.7
|
||||||
|
],
|
||||||
|
"complement_formula": {
|
||||||
|
"divisor": 50.0,
|
||||||
|
"multiplier": 0.65,
|
||||||
|
"bias": 0.35,
|
||||||
|
"scale": 0.001190483570098877,
|
||||||
|
"floor": 0.0001,
|
||||||
|
"build_106_multiplier": 1.15,
|
||||||
|
"cap": 0.15
|
||||||
|
},
|
||||||
|
"scaled_companion_formula": {
|
||||||
|
"numerator": 50.0,
|
||||||
|
"multiplier": 0.7,
|
||||||
|
"bias": 0.3,
|
||||||
|
"scale": 75.0
|
||||||
|
},
|
||||||
"entries": [
|
"entries": [
|
||||||
{
|
{
|
||||||
"year": 1800,
|
"year": 1800,
|
||||||
|
|
|
||||||
|
|
@ -982,6 +982,12 @@ fn project_save_slice_components(
|
||||||
.cached_available_locomotive_rating_value_f32_text
|
.cached_available_locomotive_rating_value_f32_text
|
||||||
.clone()
|
.clone()
|
||||||
}),
|
}),
|
||||||
|
selected_year_bucket_direct_lane_raw_u32: Vec::new(),
|
||||||
|
selected_year_bucket_direct_lane_value_f32_text: Vec::new(),
|
||||||
|
selected_year_bucket_complement_lane_raw_u32: Vec::new(),
|
||||||
|
selected_year_bucket_complement_lane_value_f32_text: Vec::new(),
|
||||||
|
selected_year_bucket_scaled_companion_lane_raw_u32: Vec::new(),
|
||||||
|
selected_year_bucket_scaled_companion_lane_value_f32_text: Vec::new(),
|
||||||
selected_year_bucket_scalar_raw_u32: None,
|
selected_year_bucket_scalar_raw_u32: None,
|
||||||
selected_year_bucket_scalar_value_f32_text: None,
|
selected_year_bucket_scalar_value_f32_text: None,
|
||||||
selected_year_gap_scalar_raw_u32: None,
|
selected_year_gap_scalar_raw_u32: None,
|
||||||
|
|
|
||||||
|
|
@ -1423,6 +1423,18 @@ pub struct RuntimeWorldRestoreState {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub selected_year_bucket_scalar_value_f32_text: Option<String>,
|
pub selected_year_bucket_scalar_value_f32_text: Option<String>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
pub selected_year_bucket_direct_lane_raw_u32: Vec<u32>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub selected_year_bucket_direct_lane_value_f32_text: Vec<String>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub selected_year_bucket_complement_lane_raw_u32: Vec<u32>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub selected_year_bucket_complement_lane_value_f32_text: Vec<String>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub selected_year_bucket_scaled_companion_lane_raw_u32: Vec<u32>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub selected_year_bucket_scaled_companion_lane_value_f32_text: Vec<String>,
|
||||||
|
#[serde(default)]
|
||||||
pub selected_year_gap_scalar_raw_u32: Option<u32>,
|
pub selected_year_gap_scalar_raw_u32: Option<u32>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub selected_year_gap_scalar_value_f32_text: Option<String>,
|
pub selected_year_gap_scalar_value_f32_text: Option<String>,
|
||||||
|
|
@ -2423,6 +2435,37 @@ impl RuntimeState {
|
||||||
self.world_restore.selected_year_bucket_scalar_raw_u32 = Some(value.to_bits());
|
self.world_restore.selected_year_bucket_scalar_raw_u32 = Some(value.to_bits());
|
||||||
self.world_restore
|
self.world_restore
|
||||||
.selected_year_bucket_scalar_value_f32_text = Some(format!("{value:.6}"));
|
.selected_year_bucket_scalar_value_f32_text = Some(format!("{value:.6}"));
|
||||||
|
if let Some(bands) = runtime_selected_year_bucket_bands_from_scalar(value) {
|
||||||
|
self.world_restore.selected_year_bucket_direct_lane_raw_u32 =
|
||||||
|
bands.direct.iter().map(|lane| lane.to_bits()).collect();
|
||||||
|
self.world_restore
|
||||||
|
.selected_year_bucket_direct_lane_value_f32_text = bands
|
||||||
|
.direct
|
||||||
|
.iter()
|
||||||
|
.map(|lane| format!("{lane:.6}"))
|
||||||
|
.collect();
|
||||||
|
self.world_restore
|
||||||
|
.selected_year_bucket_complement_lane_raw_u32 =
|
||||||
|
bands.complement.iter().map(|lane| lane.to_bits()).collect();
|
||||||
|
self.world_restore
|
||||||
|
.selected_year_bucket_complement_lane_value_f32_text = bands
|
||||||
|
.complement
|
||||||
|
.iter()
|
||||||
|
.map(|lane| format!("{lane:.6}"))
|
||||||
|
.collect();
|
||||||
|
self.world_restore
|
||||||
|
.selected_year_bucket_scaled_companion_lane_raw_u32 = bands
|
||||||
|
.scaled_companion
|
||||||
|
.iter()
|
||||||
|
.map(|lane| lane.to_bits())
|
||||||
|
.collect();
|
||||||
|
self.world_restore
|
||||||
|
.selected_year_bucket_scaled_companion_lane_value_f32_text = bands
|
||||||
|
.scaled_companion
|
||||||
|
.iter()
|
||||||
|
.map(|lane| format!("{lane:.6}"))
|
||||||
|
.collect();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if let Some(value) = runtime_world_selected_year_gap_scalar_from_year_word(year_word) {
|
if let Some(value) = runtime_world_selected_year_gap_scalar_from_year_word(year_word) {
|
||||||
self.world_restore.selected_year_gap_scalar_raw_u32 = Some(value.to_bits());
|
self.world_restore.selected_year_gap_scalar_raw_u32 = Some(value.to_bits());
|
||||||
|
|
@ -2455,6 +2498,9 @@ impl RuntimeState {
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize)]
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
struct CheckedInSelectedYearBucketLadderArtifact {
|
struct CheckedInSelectedYearBucketLadderArtifact {
|
||||||
|
direct_lane_multipliers: Vec<f32>,
|
||||||
|
complement_formula: CheckedInSelectedYearBucketComplementFormula,
|
||||||
|
scaled_companion_formula: CheckedInSelectedYearBucketScaledCompanionFormula,
|
||||||
entries: Vec<CheckedInSelectedYearBucketLadderEntry>,
|
entries: Vec<CheckedInSelectedYearBucketLadderEntry>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2464,21 +2510,44 @@ struct CheckedInSelectedYearBucketLadderEntry {
|
||||||
value: f32,
|
value: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn checked_in_selected_year_bucket_ladder() -> &'static [CheckedInSelectedYearBucketLadderEntry] {
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
static LADDER: OnceLock<Vec<CheckedInSelectedYearBucketLadderEntry>> = OnceLock::new();
|
struct CheckedInSelectedYearBucketComplementFormula {
|
||||||
LADDER
|
divisor: f32,
|
||||||
.get_or_init(|| {
|
multiplier: f32,
|
||||||
serde_json::from_str::<CheckedInSelectedYearBucketLadderArtifact>(include_str!(
|
bias: f32,
|
||||||
"../../../artifacts/exports/rt3-1.06/selected-year-bucket-ladder.json"
|
scale: f32,
|
||||||
))
|
floor: f32,
|
||||||
.expect("checked-in selected-year bucket ladder should parse")
|
build_106_multiplier: f32,
|
||||||
.entries
|
cap: f32,
|
||||||
})
|
}
|
||||||
.as_slice()
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
struct CheckedInSelectedYearBucketScaledCompanionFormula {
|
||||||
|
numerator: f32,
|
||||||
|
multiplier: f32,
|
||||||
|
bias: f32,
|
||||||
|
scale: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct RuntimeSelectedYearBucketBands {
|
||||||
|
direct: [f32; 3],
|
||||||
|
complement: [f32; 3],
|
||||||
|
scaled_companion: [f32; 3],
|
||||||
|
}
|
||||||
|
|
||||||
|
fn checked_in_selected_year_bucket_ladder() -> &'static CheckedInSelectedYearBucketLadderArtifact {
|
||||||
|
static LADDER: OnceLock<CheckedInSelectedYearBucketLadderArtifact> = OnceLock::new();
|
||||||
|
LADDER.get_or_init(|| {
|
||||||
|
serde_json::from_str::<CheckedInSelectedYearBucketLadderArtifact>(include_str!(
|
||||||
|
"../../../artifacts/exports/rt3-1.06/selected-year-bucket-ladder.json"
|
||||||
|
))
|
||||||
|
.expect("checked-in selected-year bucket ladder should parse")
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn runtime_world_selected_year_bucket_scalar_from_year_word(year_word: u32) -> Option<f32> {
|
pub fn runtime_world_selected_year_bucket_scalar_from_year_word(year_word: u32) -> Option<f32> {
|
||||||
let ladder = checked_in_selected_year_bucket_ladder();
|
let ladder = &checked_in_selected_year_bucket_ladder().entries;
|
||||||
if ladder.is_empty() {
|
if ladder.is_empty() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
@ -2500,6 +2569,41 @@ pub fn runtime_world_selected_year_bucket_scalar_from_year_word(year_word: u32)
|
||||||
ladder.last().map(|entry| entry.value)
|
ladder.last().map(|entry| entry.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn runtime_selected_year_bucket_bands_from_scalar(
|
||||||
|
scalar: f32,
|
||||||
|
) -> Option<RuntimeSelectedYearBucketBands> {
|
||||||
|
let artifact = checked_in_selected_year_bucket_ladder();
|
||||||
|
if artifact.direct_lane_multipliers.len() != 3 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let direct = [
|
||||||
|
scalar * artifact.direct_lane_multipliers[0],
|
||||||
|
scalar * artifact.direct_lane_multipliers[1],
|
||||||
|
scalar * artifact.direct_lane_multipliers[2],
|
||||||
|
];
|
||||||
|
let mut complement = [0.0f32; 3];
|
||||||
|
let mut scaled_companion = [0.0f32; 3];
|
||||||
|
for (index, direct_value) in direct.iter().copied().enumerate() {
|
||||||
|
let mut x = (((direct_value / artifact.complement_formula.divisor)
|
||||||
|
* artifact.complement_formula.multiplier)
|
||||||
|
+ artifact.complement_formula.bias)
|
||||||
|
* artifact.complement_formula.scale;
|
||||||
|
x = x.max(artifact.complement_formula.floor);
|
||||||
|
x *= artifact.complement_formula.build_106_multiplier;
|
||||||
|
x = x.min(artifact.complement_formula.cap);
|
||||||
|
complement[index] = 1.0 - x;
|
||||||
|
scaled_companion[index] = (((artifact.scaled_companion_formula.numerator / direct_value)
|
||||||
|
* artifact.scaled_companion_formula.multiplier)
|
||||||
|
+ artifact.scaled_companion_formula.bias)
|
||||||
|
* artifact.scaled_companion_formula.scale;
|
||||||
|
}
|
||||||
|
Some(RuntimeSelectedYearBucketBands {
|
||||||
|
direct,
|
||||||
|
complement,
|
||||||
|
scaled_companion,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn runtime_world_selected_year_gap_scalar_from_year_word(year_word: u32) -> Option<f32> {
|
pub fn runtime_world_selected_year_gap_scalar_from_year_word(year_word: u32) -> Option<f32> {
|
||||||
let normalized = (year_word as f64 - 1850.0) / 150.0;
|
let normalized = (year_word as f64 - 1850.0) / 150.0;
|
||||||
if !normalized.is_finite() {
|
if !normalized.is_finite() {
|
||||||
|
|
@ -5134,6 +5238,12 @@ mod tests {
|
||||||
economic_tuning_lane_value_f32_text: Vec::new(),
|
economic_tuning_lane_value_f32_text: Vec::new(),
|
||||||
selected_year_bucket_scalar_raw_u32: None,
|
selected_year_bucket_scalar_raw_u32: None,
|
||||||
selected_year_bucket_scalar_value_f32_text: None,
|
selected_year_bucket_scalar_value_f32_text: None,
|
||||||
|
selected_year_bucket_direct_lane_raw_u32: Vec::new(),
|
||||||
|
selected_year_bucket_direct_lane_value_f32_text: Vec::new(),
|
||||||
|
selected_year_bucket_complement_lane_raw_u32: Vec::new(),
|
||||||
|
selected_year_bucket_complement_lane_value_f32_text: Vec::new(),
|
||||||
|
selected_year_bucket_scaled_companion_lane_raw_u32: Vec::new(),
|
||||||
|
selected_year_bucket_scaled_companion_lane_value_f32_text: Vec::new(),
|
||||||
selected_year_gap_scalar_raw_u32: None,
|
selected_year_gap_scalar_raw_u32: None,
|
||||||
selected_year_gap_scalar_value_f32_text: None,
|
selected_year_gap_scalar_value_f32_text: None,
|
||||||
absolute_counter_restore_kind: Some(
|
absolute_counter_restore_kind: Some(
|
||||||
|
|
@ -8136,6 +8246,13 @@ mod tests {
|
||||||
runtime_world_selected_year_bucket_scalar_from_year_word(2000),
|
runtime_world_selected_year_bucket_scalar_from_year_word(2000),
|
||||||
Some(123.0)
|
Some(123.0)
|
||||||
);
|
);
|
||||||
|
let bands = runtime_selected_year_bucket_bands_from_scalar(25.0)
|
||||||
|
.expect("selected-year bucket companion bands");
|
||||||
|
assert!((bands.direct[0] - 22.5).abs() < 1e-6);
|
||||||
|
assert!((bands.direct[1] - 26.25).abs() < 1e-5);
|
||||||
|
assert!((bands.direct[2] - 17.5).abs() < 1e-6);
|
||||||
|
assert!((bands.complement[0] - 0.999121).abs() < 1e-6);
|
||||||
|
assert!((bands.scaled_companion[0] - 139.16667).abs() < 1e-4);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
runtime_world_selected_year_gap_scalar_from_year_word(1830),
|
runtime_world_selected_year_gap_scalar_from_year_word(1830),
|
||||||
Some((1.0f32 / 3.0).clamp(1.0 / 3.0, 1.0))
|
Some((1.0f32 / 3.0).clamp(1.0 / 3.0, 1.0))
|
||||||
|
|
@ -8224,6 +8341,36 @@ mod tests {
|
||||||
.as_deref(),
|
.as_deref(),
|
||||||
Some("70.000000")
|
Some("70.000000")
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
state
|
||||||
|
.world_restore
|
||||||
|
.selected_year_bucket_direct_lane_value_f32_text,
|
||||||
|
vec![
|
||||||
|
"63.000000".to_string(),
|
||||||
|
"73.500000".to_string(),
|
||||||
|
"49.000000".to_string()
|
||||||
|
]
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
state
|
||||||
|
.world_restore
|
||||||
|
.selected_year_bucket_complement_lane_value_f32_text,
|
||||||
|
vec![
|
||||||
|
"0.998400".to_string(),
|
||||||
|
"0.998213".to_string(),
|
||||||
|
"0.998649".to_string()
|
||||||
|
]
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
state
|
||||||
|
.world_restore
|
||||||
|
.selected_year_bucket_scaled_companion_lane_value_f32_text,
|
||||||
|
vec![
|
||||||
|
"64.166672".to_string(),
|
||||||
|
"58.214291".to_string(),
|
||||||
|
"76.071426".to_string()
|
||||||
|
]
|
||||||
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
state.world_restore.selected_year_gap_scalar_raw_u32,
|
state.world_restore.selected_year_gap_scalar_raw_u32,
|
||||||
Some(((50.0f32 / 150.0).clamp(1.0 / 3.0, 1.0)).to_bits())
|
Some(((50.0f32 / 150.0).clamp(1.0 / 3.0, 1.0)).to_bits())
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,12 @@ pub struct RuntimeSummary {
|
||||||
pub world_restore_cached_available_locomotive_rating_value_f32_text: Option<String>,
|
pub world_restore_cached_available_locomotive_rating_value_f32_text: Option<String>,
|
||||||
pub world_restore_selected_year_bucket_scalar_raw_u32: Option<u32>,
|
pub world_restore_selected_year_bucket_scalar_raw_u32: Option<u32>,
|
||||||
pub world_restore_selected_year_bucket_scalar_value_f32_text: Option<String>,
|
pub world_restore_selected_year_bucket_scalar_value_f32_text: Option<String>,
|
||||||
|
pub world_restore_selected_year_bucket_direct_lane_count: usize,
|
||||||
|
pub world_restore_selected_year_bucket_direct_lane_value_f32_text: Vec<String>,
|
||||||
|
pub world_restore_selected_year_bucket_complement_lane_count: usize,
|
||||||
|
pub world_restore_selected_year_bucket_complement_lane_value_f32_text: Vec<String>,
|
||||||
|
pub world_restore_selected_year_bucket_scaled_companion_lane_count: usize,
|
||||||
|
pub world_restore_selected_year_bucket_scaled_companion_lane_value_f32_text: Vec<String>,
|
||||||
pub world_restore_selected_year_gap_scalar_raw_u32: Option<u32>,
|
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_selected_year_gap_scalar_value_f32_text: Option<String>,
|
||||||
pub world_restore_absolute_counter_restore_kind: Option<String>,
|
pub world_restore_absolute_counter_restore_kind: Option<String>,
|
||||||
|
|
@ -480,6 +486,30 @@ impl RuntimeSummary {
|
||||||
.world_restore
|
.world_restore
|
||||||
.selected_year_bucket_scalar_value_f32_text
|
.selected_year_bucket_scalar_value_f32_text
|
||||||
.clone(),
|
.clone(),
|
||||||
|
world_restore_selected_year_bucket_direct_lane_count: state
|
||||||
|
.world_restore
|
||||||
|
.selected_year_bucket_direct_lane_raw_u32
|
||||||
|
.len(),
|
||||||
|
world_restore_selected_year_bucket_direct_lane_value_f32_text: state
|
||||||
|
.world_restore
|
||||||
|
.selected_year_bucket_direct_lane_value_f32_text
|
||||||
|
.clone(),
|
||||||
|
world_restore_selected_year_bucket_complement_lane_count: state
|
||||||
|
.world_restore
|
||||||
|
.selected_year_bucket_complement_lane_raw_u32
|
||||||
|
.len(),
|
||||||
|
world_restore_selected_year_bucket_complement_lane_value_f32_text: state
|
||||||
|
.world_restore
|
||||||
|
.selected_year_bucket_complement_lane_value_f32_text
|
||||||
|
.clone(),
|
||||||
|
world_restore_selected_year_bucket_scaled_companion_lane_count: state
|
||||||
|
.world_restore
|
||||||
|
.selected_year_bucket_scaled_companion_lane_raw_u32
|
||||||
|
.len(),
|
||||||
|
world_restore_selected_year_bucket_scaled_companion_lane_value_f32_text: state
|
||||||
|
.world_restore
|
||||||
|
.selected_year_bucket_scaled_companion_lane_value_f32_text
|
||||||
|
.clone(),
|
||||||
world_restore_selected_year_gap_scalar_raw_u32: state
|
world_restore_selected_year_gap_scalar_raw_u32: state
|
||||||
.world_restore
|
.world_restore
|
||||||
.selected_year_gap_scalar_raw_u32,
|
.selected_year_gap_scalar_raw_u32,
|
||||||
|
|
@ -1818,6 +1848,36 @@ mod tests {
|
||||||
cached_available_locomotive_rating_value_f32_text: Some("20.000000".to_string()),
|
cached_available_locomotive_rating_value_f32_text: Some("20.000000".to_string()),
|
||||||
selected_year_bucket_scalar_raw_u32: Some(25.0f32.to_bits()),
|
selected_year_bucket_scalar_raw_u32: Some(25.0f32.to_bits()),
|
||||||
selected_year_bucket_scalar_value_f32_text: Some("25.000000".to_string()),
|
selected_year_bucket_scalar_value_f32_text: Some("25.000000".to_string()),
|
||||||
|
selected_year_bucket_direct_lane_raw_u32: vec![
|
||||||
|
22.5f32.to_bits(),
|
||||||
|
26.25f32.to_bits(),
|
||||||
|
17.5f32.to_bits(),
|
||||||
|
],
|
||||||
|
selected_year_bucket_direct_lane_value_f32_text: vec![
|
||||||
|
"22.500000".to_string(),
|
||||||
|
"26.250000".to_string(),
|
||||||
|
"17.500000".to_string(),
|
||||||
|
],
|
||||||
|
selected_year_bucket_complement_lane_raw_u32: vec![
|
||||||
|
0.999121f32.to_bits(),
|
||||||
|
0.998998f32.to_bits(),
|
||||||
|
0.999210f32.to_bits(),
|
||||||
|
],
|
||||||
|
selected_year_bucket_complement_lane_value_f32_text: vec![
|
||||||
|
"0.999121".to_string(),
|
||||||
|
"0.998998".to_string(),
|
||||||
|
"0.999210".to_string(),
|
||||||
|
],
|
||||||
|
selected_year_bucket_scaled_companion_lane_raw_u32: vec![
|
||||||
|
139.16667f32.to_bits(),
|
||||||
|
122.5f32.to_bits(),
|
||||||
|
171.42857f32.to_bits(),
|
||||||
|
],
|
||||||
|
selected_year_bucket_scaled_companion_lane_value_f32_text: vec![
|
||||||
|
"139.166672".to_string(),
|
||||||
|
"122.500000".to_string(),
|
||||||
|
"171.428574".to_string(),
|
||||||
|
],
|
||||||
selected_year_gap_scalar_raw_u32: Some(0x3eaaaaab),
|
selected_year_gap_scalar_raw_u32: Some(0x3eaaaaab),
|
||||||
selected_year_gap_scalar_value_f32_text: Some("0.333333".to_string()),
|
selected_year_gap_scalar_value_f32_text: Some("0.333333".to_string()),
|
||||||
..RuntimeWorldRestoreState::default()
|
..RuntimeWorldRestoreState::default()
|
||||||
|
|
@ -1982,6 +2042,30 @@ mod tests {
|
||||||
.as_deref(),
|
.as_deref(),
|
||||||
Some("25.000000")
|
Some("25.000000")
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
summary.world_restore_selected_year_bucket_direct_lane_count,
|
||||||
|
3
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
summary.world_restore_selected_year_bucket_direct_lane_value_f32_text,
|
||||||
|
vec!["22.500000", "26.250000", "17.500000"]
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
summary.world_restore_selected_year_bucket_complement_lane_count,
|
||||||
|
3
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
summary.world_restore_selected_year_bucket_complement_lane_value_f32_text,
|
||||||
|
vec!["0.999121", "0.998998", "0.999210"]
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
summary.world_restore_selected_year_bucket_scaled_companion_lane_count,
|
||||||
|
3
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
summary.world_restore_selected_year_bucket_scaled_companion_lane_value_f32_text,
|
||||||
|
vec!["139.166672", "122.500000", "171.428574"]
|
||||||
|
);
|
||||||
assert_eq!(summary.world_restore_economic_tuning_lane_count, 6);
|
assert_eq!(summary.world_restore_economic_tuning_lane_count, 6);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
summary.world_restore_economic_tuning_lane_value_f32_text,
|
summary.world_restore_economic_tuning_lane_value_f32_text,
|
||||||
|
|
|
||||||
|
|
@ -177,6 +177,10 @@ The highest-value next passes are now:
|
||||||
drives a derived selected-year bucket scalar in runtime restore state, and the economic-tuning
|
drives a derived selected-year bucket scalar in runtime restore state, and the economic-tuning
|
||||||
mirror `[world+0x0bde]` now rebuilds from tuning lane `0` instead of freezing one stale
|
mirror `[world+0x0bde]` now rebuilds from tuning lane `0` instead of freezing one stale
|
||||||
load-time word
|
load-time word
|
||||||
|
- that same selected-year owner family now also rebuilds the direct bucket trio
|
||||||
|
`[world+0x65/+0x69/+0x6d]`, the complement trio `[world+0x71/+0x75/+0x79]`, and the scaled
|
||||||
|
companion trio `[world+0x7d/+0x81/+0x85]` from the bucket scalar instead of preserving stale
|
||||||
|
save-time residue
|
||||||
- the project rule on the remaining closure work is now explicit too: when one runtime-facing field
|
- 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
|
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
|
instead of guessing another derived leaf field from neighboring raw offsets
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,9 @@ Working rule:
|
||||||
|
|
||||||
## Next
|
## Next
|
||||||
|
|
||||||
- Rehost the next selected-year periodic-boundary world seam under
|
- Rehost the next periodic-boundary world seam after the selected-year bucket family, favoring
|
||||||
`simulation_service_periodic_boundary_work`, extending the now-grounded selected-year bucket
|
owner-state rebuilds that can advance shellless simulation without freezing load-time residue.
|
||||||
scalar into the direct bucket trio `[world+0x65/+0x69/+0x6d]` and any safe follow-on companion
|
- Keep widening selected-year world-owner state only when a full owning reader/rebuild family is
|
||||||
lanes rooted in `0x00433bd0`.
|
|
||||||
- Expand the selected-year world-owner surface beyond the stepped calendar, gap scalar,
|
|
||||||
bucket-scalar, mirror, and locomotive-policy lanes when the owning reader/rebuild family is
|
|
||||||
grounded strongly enough to avoid one-off leaf guesses.
|
grounded strongly enough to avoid one-off leaf guesses.
|
||||||
|
|
||||||
## In Progress
|
## In Progress
|
||||||
|
|
@ -51,6 +48,10 @@ Working rule:
|
||||||
and runtime restore state now derives both the selected-year bucket scalar and the
|
and runtime restore state now derives both the selected-year bucket scalar and the
|
||||||
`[world+0x0bde]` economic-tuning mirror from owner-family inputs instead of preserving stale
|
`[world+0x0bde]` economic-tuning mirror from owner-family inputs instead of preserving stale
|
||||||
load-time residue.
|
load-time residue.
|
||||||
|
- That same selected-year owner family now also rebuilds the direct bucket trio
|
||||||
|
`[world+0x65/+0x69/+0x6d]`, the complement trio `[world+0x71/+0x75/+0x79]`, and the scaled
|
||||||
|
companion trio `[world+0x7d/+0x81/+0x85]` from the checked-in `0x00433bd0` artifact instead of
|
||||||
|
preserving stale save-time residue.
|
||||||
- Company cash, confiscation, and major governance effects now write through owner state instead of
|
- Company cash, confiscation, and major governance effects now write through owner state instead of
|
||||||
drifting from market/cache readers.
|
drifting from market/cache readers.
|
||||||
- Company credit rating, prime rate, book value per share, investor confidence, and management
|
- Company credit rating, prime rate, book value per share, investor confidence, and management
|
||||||
|
|
|
||||||
|
|
@ -223,7 +223,10 @@ the fixed world block, so the `All Steam/Diesel/Electric Locos Avail.` descripto
|
||||||
through owner state instead of living only as mirrored world flags. The selected-year seam now
|
through owner state instead of living only as mirrored world flags. The selected-year seam now
|
||||||
follows the same owner rule: the checked-in `0x00433bd0` year ladder now drives a derived
|
follows the same owner rule: the checked-in `0x00433bd0` year ladder now drives a derived
|
||||||
selected-year bucket scalar in runtime restore state, and the economic-tuning mirror `[world+0x0bde]`
|
selected-year bucket scalar in runtime restore state, and the economic-tuning mirror `[world+0x0bde]`
|
||||||
now rebuilds from tuning lane `0` instead of freezing one stale load-time word. The same owned company annual-finance state
|
now rebuilds from tuning lane `0` instead of freezing one stale load-time word. That same
|
||||||
|
checked-in owner family now also rebuilds the direct bucket trio `[world+0x65/+0x69/+0x6d]`, the
|
||||||
|
complement trio `[world+0x71/+0x75/+0x79]`, and the scaled companion trio `[world+0x7d/+0x81/+0x85]`
|
||||||
|
from the bucket scalar instead of preserving stale save-time residue. The same owned company annual-finance state
|
||||||
now also drives a shared company market reader seam for stock-capital, salary, bonus, and the full
|
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
|
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
|
simulation than summary-only helpers. That same owned annual-finance state now also derives elapsed
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,18 @@ IMAGE_BASE = 0x400000
|
||||||
PAIRED_YEAR_VALUE_TABLE_VA = 0x005F3980
|
PAIRED_YEAR_VALUE_TABLE_VA = 0x005F3980
|
||||||
PAIR_COUNT = 21
|
PAIR_COUNT = 21
|
||||||
TERMINAL_SCALAR_VA = 0x005F3A24
|
TERMINAL_SCALAR_VA = 0x005F3A24
|
||||||
|
DIRECT_MULTIPLIER_VAS = [0x005C8888, 0x005C9ED8, 0x005C8680]
|
||||||
|
COMPLEMENT_DIVISOR_VA = 0x005C8A20
|
||||||
|
COMPLEMENT_MULTIPLIER_VA = 0x005C8DA8
|
||||||
|
COMPLEMENT_BIAS_VA = 0x005C8618
|
||||||
|
COMPLEMENT_SCALE_VA = 0x005C9ED0
|
||||||
|
COMPLEMENT_FLOOR_VA = 0x005C88A0
|
||||||
|
COMPLEMENT_BUILD_106_MULTIPLIER_VA = 0x005C8878
|
||||||
|
COMPLEMENT_CAP_VA = 0x005C8988
|
||||||
|
SCALED_COMPANION_NUMERATOR_VA = 0x005C8A20
|
||||||
|
SCALED_COMPANION_MULTIPLIER_VA = 0x005C8680
|
||||||
|
SCALED_COMPANION_BIAS_VA = 0x005C88C8
|
||||||
|
SCALED_COMPANION_SCALE_VA = 0x005C9EC8
|
||||||
|
|
||||||
|
|
||||||
def read_u32_table(blob: bytes, va: int, count: int) -> list[int]:
|
def read_u32_table(blob: bytes, va: int, count: int) -> list[int]:
|
||||||
|
|
@ -20,6 +32,14 @@ def read_u32_table(blob: bytes, va: int, count: int) -> list[int]:
|
||||||
return [struct.unpack("<I", data[i : i + 4])[0] for i in range(0, len(data), 4)]
|
return [struct.unpack("<I", data[i : i + 4])[0] for i in range(0, len(data), 4)]
|
||||||
|
|
||||||
|
|
||||||
|
def read_f64(blob: bytes, va: int) -> float:
|
||||||
|
offset = va - IMAGE_BASE
|
||||||
|
data = blob[offset : offset + 8]
|
||||||
|
if len(data) != 8:
|
||||||
|
raise ValueError(f"f64 at {va:#x} truncated")
|
||||||
|
return struct.unpack("<d", data)[0]
|
||||||
|
|
||||||
|
|
||||||
def build_artifact(exe_bytes: bytes) -> dict[str, object]:
|
def build_artifact(exe_bytes: bytes) -> dict[str, object]:
|
||||||
raw_pairs = read_u32_table(exe_bytes, PAIRED_YEAR_VALUE_TABLE_VA, PAIR_COUNT * 2)
|
raw_pairs = read_u32_table(exe_bytes, PAIRED_YEAR_VALUE_TABLE_VA, PAIR_COUNT * 2)
|
||||||
terminal_scalar_raw = read_u32_table(exe_bytes, TERMINAL_SCALAR_VA, 1)[0]
|
terminal_scalar_raw = read_u32_table(exe_bytes, TERMINAL_SCALAR_VA, 1)[0]
|
||||||
|
|
@ -33,6 +53,24 @@ def build_artifact(exe_bytes: bytes) -> dict[str, object]:
|
||||||
"pair_count": PAIR_COUNT,
|
"pair_count": PAIR_COUNT,
|
||||||
"terminal_scalar_virtual_address": f"0x{TERMINAL_SCALAR_VA:08x}",
|
"terminal_scalar_virtual_address": f"0x{TERMINAL_SCALAR_VA:08x}",
|
||||||
"terminal_scalar_value": float(terminal_scalar_raw),
|
"terminal_scalar_value": float(terminal_scalar_raw),
|
||||||
|
"direct_lane_multipliers": [
|
||||||
|
read_f64(exe_bytes, va) for va in DIRECT_MULTIPLIER_VAS
|
||||||
|
],
|
||||||
|
"complement_formula": {
|
||||||
|
"divisor": read_f64(exe_bytes, COMPLEMENT_DIVISOR_VA),
|
||||||
|
"multiplier": read_f64(exe_bytes, COMPLEMENT_MULTIPLIER_VA),
|
||||||
|
"bias": read_f64(exe_bytes, COMPLEMENT_BIAS_VA),
|
||||||
|
"scale": read_f64(exe_bytes, COMPLEMENT_SCALE_VA),
|
||||||
|
"floor": read_f64(exe_bytes, COMPLEMENT_FLOOR_VA),
|
||||||
|
"build_106_multiplier": read_f64(exe_bytes, COMPLEMENT_BUILD_106_MULTIPLIER_VA),
|
||||||
|
"cap": read_f64(exe_bytes, COMPLEMENT_CAP_VA),
|
||||||
|
},
|
||||||
|
"scaled_companion_formula": {
|
||||||
|
"numerator": read_f64(exe_bytes, SCALED_COMPANION_NUMERATOR_VA),
|
||||||
|
"multiplier": read_f64(exe_bytes, SCALED_COMPANION_MULTIPLIER_VA),
|
||||||
|
"bias": read_f64(exe_bytes, SCALED_COMPANION_BIAS_VA),
|
||||||
|
"scale": read_f64(exe_bytes, SCALED_COMPANION_SCALE_VA),
|
||||||
|
},
|
||||||
"entries": entries,
|
"entries": entries,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue