Broaden chairman target scope event support
This commit is contained in:
parent
5c2156bcbf
commit
a63de904fa
15 changed files with 1257 additions and 30 deletions
13
README.md
13
README.md
|
|
@ -18,17 +18,20 @@ selected-company and controller-role context through overlay imports, and real d
|
|||
execute through the ordinary runtime path, and descriptors `1` `Player Cash` and `14`
|
||||
`Deactivate Player` now join that batch through the same service engine. Synthetic packed records
|
||||
still exercise the same runtime without a parallel packed executor. The first grounded
|
||||
chairman-profile runtime slice now exists too: overlay-backed selected-chairman context plus the
|
||||
hidden grouped target-subject lane let those same real descriptors `1` and `14` execute on
|
||||
selected-chairman scope, while wider chairman target scopes remain explicit parity. The first grounded
|
||||
chairman-profile runtime slice now exists too: save-slice or overlay-backed chairman/company
|
||||
context plus the hidden grouped target-subject lane let those same real descriptors `1` and `14`
|
||||
execute on the grounded chairman scope ordinals `0..3` (`condition_true`, `selected`, `human`,
|
||||
`ai`), while wider chairman ordinals remain explicit parity. The first grounded
|
||||
chairman and governance condition batch is broader now: selected-chairman cash / holdings / net
|
||||
worth / purchasing-power thresholds and company book-value-per-share / investor-confidence /
|
||||
management-attitude thresholds now import through the normal event-service path, while wider
|
||||
chairman target scopes remain explicit frontier. Checked-in save-slice
|
||||
chairman ordinals remain explicit frontier. Checked-in save-slice
|
||||
documents can now also carry explicit company rosters and chairman-profile tables, so the current
|
||||
company-targeted and chairman-targeted descriptor and condition batches can execute from standalone
|
||||
save-slice fixtures without overlay snapshots when that context is present; raw `.gms` inspection
|
||||
still does not reconstruct those company/chairman collections automatically. The first grounded
|
||||
still does not reconstruct those company/chairman collections automatically. A generic
|
||||
company-governance scalar effect surface now exists in runtime too, but real governance descriptor
|
||||
ids are still deferred until the checked-in effect-table evidence is stronger. The first grounded
|
||||
condition-side unlock now exists for negative-sentinel `raw_condition_id = -1` company scopes, and
|
||||
the first ordinary nonnegative condition batch now executes too: numeric-threshold company
|
||||
finance, company track, aggregate territory track, and company-territory track rows can import
|
||||
|
|
|
|||
|
|
@ -4489,11 +4489,20 @@ mod tests {
|
|||
.join("../../fixtures/runtime/packed-event-chairman-cash-overlay-fixture.json");
|
||||
let chairman_cash_save_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("../../fixtures/runtime/packed-event-chairman-cash-save-slice-fixture.json");
|
||||
let chairman_condition_true_save_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(
|
||||
"../../fixtures/runtime/packed-event-chairman-condition-true-save-slice-fixture.json",
|
||||
);
|
||||
let chairman_human_cash_save_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(
|
||||
"../../fixtures/runtime/packed-event-chairman-human-cash-save-slice-fixture.json",
|
||||
);
|
||||
let deactivate_chairman_overlay_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("../../fixtures/runtime/packed-event-deactivate-chairman-overlay-fixture.json");
|
||||
let deactivate_chairman_save_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(
|
||||
"../../fixtures/runtime/packed-event-deactivate-chairman-save-slice-fixture.json",
|
||||
);
|
||||
let deactivate_chairman_ai_save_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join(
|
||||
"../../fixtures/runtime/packed-event-deactivate-chairman-ai-save-slice-fixture.json",
|
||||
);
|
||||
let deactivate_company_save_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
.join("../../fixtures/runtime/packed-event-deactivate-company-save-slice-fixture.json");
|
||||
let track_capacity_save_fixture = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||
|
|
@ -4580,10 +4589,16 @@ mod tests {
|
|||
.expect("overlay-backed chairman-cash fixture should summarize");
|
||||
run_runtime_summarize_fixture(&chairman_cash_save_fixture)
|
||||
.expect("save-slice-backed chairman-cash fixture should summarize");
|
||||
run_runtime_summarize_fixture(&chairman_condition_true_save_fixture)
|
||||
.expect("save-slice-backed condition-true chairman fixture should summarize");
|
||||
run_runtime_summarize_fixture(&chairman_human_cash_save_fixture)
|
||||
.expect("save-slice-backed human-chairman cash fixture should summarize");
|
||||
run_runtime_summarize_fixture(&deactivate_chairman_overlay_fixture)
|
||||
.expect("overlay-backed deactivate-chairman fixture should summarize");
|
||||
run_runtime_summarize_fixture(&deactivate_chairman_save_fixture)
|
||||
.expect("save-slice-backed deactivate-chairman fixture should summarize");
|
||||
run_runtime_summarize_fixture(&deactivate_chairman_ai_save_fixture)
|
||||
.expect("save-slice-backed AI-chairman deactivate fixture should summarize");
|
||||
run_runtime_summarize_fixture(&deactivate_company_save_fixture)
|
||||
.expect("save-slice-backed deactivate-company fixture should summarize");
|
||||
run_runtime_summarize_fixture(&track_capacity_save_fixture)
|
||||
|
|
|
|||
|
|
@ -1161,6 +1161,7 @@ fn runtime_packed_event_grouped_effect_row_summary_from_smp(
|
|||
target_mask_bits: row.target_mask_bits,
|
||||
parameter_family: row.parameter_family.clone(),
|
||||
grouped_target_subject: row.grouped_target_subject.clone(),
|
||||
grouped_target_scope: row.grouped_target_scope.clone(),
|
||||
opcode: row.opcode,
|
||||
raw_scalar_value: row.raw_scalar_value,
|
||||
value_byte_0x09: row.value_byte_0x09,
|
||||
|
|
@ -1279,6 +1280,7 @@ fn lowered_record_decoded_actions(
|
|||
if let Some(blocker) = packed_record_condition_scope_import_blocker(record, company_context) {
|
||||
return Err(blocker);
|
||||
}
|
||||
ensure_condition_true_chairman_context(record)?;
|
||||
|
||||
let lowered_company_target = lowered_condition_true_company_target(record)?;
|
||||
let lowered_player_target = lowered_condition_true_player_target(record)?;
|
||||
|
|
@ -1582,6 +1584,18 @@ fn lower_condition_targets_in_effect(
|
|||
)?,
|
||||
value: *value,
|
||||
},
|
||||
RuntimeEffect::SetCompanyGovernanceScalar {
|
||||
target,
|
||||
metric,
|
||||
value,
|
||||
} => RuntimeEffect::SetCompanyGovernanceScalar {
|
||||
target: lower_condition_true_company_target_in_company_target(
|
||||
target,
|
||||
lowered_company_target,
|
||||
)?,
|
||||
metric: *metric,
|
||||
value: *value,
|
||||
},
|
||||
RuntimeEffect::SetChairmanCash { target, value } => RuntimeEffect::SetChairmanCash {
|
||||
target: target.clone(),
|
||||
value: *value,
|
||||
|
|
@ -1912,6 +1926,23 @@ fn lower_condition_true_player_target_in_player_target(
|
|||
}
|
||||
}
|
||||
|
||||
fn ensure_condition_true_chairman_context(
|
||||
record: &SmpLoadedPackedEventRecordSummary,
|
||||
) -> Result<(), ImportBlocker> {
|
||||
if !record_uses_condition_true_chairman(record) {
|
||||
return Ok(());
|
||||
}
|
||||
if record
|
||||
.decoded_conditions
|
||||
.iter()
|
||||
.any(|condition| matches!(condition, RuntimeCondition::ChairmanNumericThreshold { .. }))
|
||||
{
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ImportBlocker::MissingConditionContext)
|
||||
}
|
||||
}
|
||||
|
||||
fn lower_territory_target_in_condition(
|
||||
target: &RuntimeTerritoryTarget,
|
||||
row: &SmpLoadedPackedEventConditionRowSummary,
|
||||
|
|
@ -1991,6 +2022,15 @@ fn chairman_target_import_blocker(
|
|||
None
|
||||
}
|
||||
}
|
||||
RuntimeChairmanTarget::HumanChairmen | RuntimeChairmanTarget::AiChairmen => {
|
||||
if company_context.known_chairman_profile_ids.is_empty() {
|
||||
Some(ImportBlocker::MissingChairmanContext)
|
||||
} else if !company_context.has_complete_company_controller_context {
|
||||
Some(ImportBlocker::MissingCompanyRoleContext)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
RuntimeChairmanTarget::SelectedChairman => {
|
||||
if company_context.selected_chairman_profile_id.is_some() {
|
||||
None
|
||||
|
|
@ -1998,6 +2038,13 @@ fn chairman_target_import_blocker(
|
|||
Some(ImportBlocker::MissingChairmanContext)
|
||||
}
|
||||
}
|
||||
RuntimeChairmanTarget::ConditionTrueChairman => {
|
||||
if company_context.known_chairman_profile_ids.is_empty() {
|
||||
Some(ImportBlocker::MissingChairmanContext)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
RuntimeChairmanTarget::Ids { ids } => {
|
||||
if company_context.known_chairman_profile_ids.is_empty() {
|
||||
Some(ImportBlocker::MissingChairmanContext)
|
||||
|
|
@ -2173,6 +2220,25 @@ fn smp_runtime_effect_to_runtime_effect(
|
|||
Err(company_target_import_error_message(target, company_context))
|
||||
}
|
||||
}
|
||||
RuntimeEffect::SetCompanyGovernanceScalar {
|
||||
target,
|
||||
metric,
|
||||
value,
|
||||
} => {
|
||||
if company_target_allowed_for_import(
|
||||
target,
|
||||
company_context,
|
||||
allow_condition_true_company,
|
||||
) {
|
||||
Ok(RuntimeEffect::SetCompanyGovernanceScalar {
|
||||
target: target.clone(),
|
||||
metric: *metric,
|
||||
value: *value,
|
||||
})
|
||||
} else {
|
||||
Err(company_target_import_error_message(target, company_context))
|
||||
}
|
||||
}
|
||||
RuntimeEffect::RetireTrains {
|
||||
company_target,
|
||||
territory_target,
|
||||
|
|
@ -2838,10 +2904,9 @@ fn real_grouped_row_is_unsupported_chairman_target_scope(
|
|||
) -> bool {
|
||||
matches!(row.grouped_target_subject.as_deref(), Some("chairman"))
|
||||
&& matches!(row.descriptor_id, 1 | 14)
|
||||
&& row
|
||||
.notes
|
||||
.iter()
|
||||
.any(|note| note == "chairman row requires selected-chairman scope")
|
||||
&& row.notes.iter().any(|note| {
|
||||
note.starts_with("chairman row uses unsupported grouped target scope ordinal ")
|
||||
})
|
||||
}
|
||||
|
||||
fn real_grouped_row_is_unsupported_territory_access_scope(
|
||||
|
|
@ -2883,6 +2948,7 @@ fn real_grouped_row_is_unsupported_retire_train_scope(
|
|||
fn runtime_effect_uses_condition_true_company(effect: &RuntimeEffect) -> bool {
|
||||
match effect {
|
||||
RuntimeEffect::SetCompanyCash { target, .. }
|
||||
| RuntimeEffect::SetCompanyGovernanceScalar { target, .. }
|
||||
| RuntimeEffect::SetCompanyTerritoryAccess { target, .. }
|
||||
| RuntimeEffect::ConfiscateCompanyAssets { target }
|
||||
| RuntimeEffect::DeactivateCompany { target }
|
||||
|
|
@ -2936,12 +3002,34 @@ fn runtime_effect_uses_condition_true_player(effect: &RuntimeEffect) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
fn record_uses_condition_true_chairman(record: &SmpLoadedPackedEventRecordSummary) -> bool {
|
||||
record
|
||||
.decoded_actions
|
||||
.iter()
|
||||
.any(runtime_effect_uses_condition_true_chairman)
|
||||
}
|
||||
|
||||
fn runtime_effect_uses_condition_true_chairman(effect: &RuntimeEffect) -> bool {
|
||||
match effect {
|
||||
RuntimeEffect::SetChairmanCash { target, .. }
|
||||
| RuntimeEffect::DeactivateChairman { target } => {
|
||||
matches!(target, RuntimeChairmanTarget::ConditionTrueChairman)
|
||||
}
|
||||
RuntimeEffect::AppendEventRecord { record } => record
|
||||
.effects
|
||||
.iter()
|
||||
.any(runtime_effect_uses_condition_true_chairman),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn runtime_effect_company_target_import_blocker(
|
||||
effect: &RuntimeEffect,
|
||||
company_context: &ImportRuntimeContext,
|
||||
) -> Option<ImportBlocker> {
|
||||
match effect {
|
||||
RuntimeEffect::SetCompanyCash { target, .. }
|
||||
| RuntimeEffect::SetCompanyGovernanceScalar { target, .. }
|
||||
| RuntimeEffect::SetCompanyTerritoryAccess { target, .. }
|
||||
| RuntimeEffect::ConfiscateCompanyAssets { target }
|
||||
| RuntimeEffect::DeactivateCompany { target }
|
||||
|
|
@ -3490,6 +3578,7 @@ mod tests {
|
|||
target_mask_bits: Some(0x01),
|
||||
parameter_family: Some("company_finance_scalar".to_string()),
|
||||
grouped_target_subject: None,
|
||||
grouped_target_scope: None,
|
||||
opcode: 8,
|
||||
raw_scalar_value: 7,
|
||||
value_byte_0x09: 1,
|
||||
|
|
@ -3520,6 +3609,7 @@ mod tests {
|
|||
target_mask_bits: Some(0x01),
|
||||
parameter_family: Some("company_lifecycle_toggle".to_string()),
|
||||
grouped_target_subject: None,
|
||||
grouped_target_scope: None,
|
||||
opcode: 1,
|
||||
raw_scalar_value: if enabled { 1 } else { 0 },
|
||||
value_byte_0x09: 0,
|
||||
|
|
@ -3551,6 +3641,7 @@ mod tests {
|
|||
target_mask_bits: Some(0x01),
|
||||
parameter_family: Some("company_build_limit_scalar".to_string()),
|
||||
grouped_target_subject: None,
|
||||
grouped_target_scope: None,
|
||||
opcode: 3,
|
||||
raw_scalar_value: value,
|
||||
value_byte_0x09: 0,
|
||||
|
|
@ -3581,6 +3672,7 @@ mod tests {
|
|||
target_mask_bits: Some(0x02),
|
||||
parameter_family: Some("player_lifecycle_toggle".to_string()),
|
||||
grouped_target_subject: None,
|
||||
grouped_target_scope: None,
|
||||
opcode: 1,
|
||||
raw_scalar_value: if enabled { 1 } else { 0 },
|
||||
value_byte_0x09: 0,
|
||||
|
|
@ -3615,6 +3707,7 @@ mod tests {
|
|||
target_mask_bits: Some(0x05),
|
||||
parameter_family: Some("territory_access_toggle".to_string()),
|
||||
grouped_target_subject: None,
|
||||
grouped_target_scope: None,
|
||||
opcode: 1,
|
||||
raw_scalar_value: if enabled { 1 } else { 0 },
|
||||
value_byte_0x09: 0,
|
||||
|
|
@ -3646,6 +3739,7 @@ mod tests {
|
|||
target_mask_bits: Some(0x08),
|
||||
parameter_family: Some("whole_game_state_enum".to_string()),
|
||||
grouped_target_subject: None,
|
||||
grouped_target_scope: None,
|
||||
opcode: 3,
|
||||
raw_scalar_value: value,
|
||||
value_byte_0x09: 0,
|
||||
|
|
@ -3676,6 +3770,7 @@ mod tests {
|
|||
target_mask_bits: Some(0x08),
|
||||
parameter_family: Some("world_track_build_limit_scalar".to_string()),
|
||||
grouped_target_subject: None,
|
||||
grouped_target_scope: None,
|
||||
opcode: 3,
|
||||
raw_scalar_value: value,
|
||||
value_byte_0x09: 0,
|
||||
|
|
@ -3706,6 +3801,7 @@ mod tests {
|
|||
target_mask_bits: Some(0x08),
|
||||
parameter_family: Some("special_condition_scalar".to_string()),
|
||||
grouped_target_subject: None,
|
||||
grouped_target_scope: None,
|
||||
opcode: 3,
|
||||
raw_scalar_value: value,
|
||||
value_byte_0x09: 0,
|
||||
|
|
@ -3736,6 +3832,7 @@ mod tests {
|
|||
target_mask_bits: Some(0x08),
|
||||
parameter_family: Some("candidate_availability_scalar".to_string()),
|
||||
grouped_target_subject: None,
|
||||
grouped_target_scope: None,
|
||||
opcode: 3,
|
||||
raw_scalar_value: value,
|
||||
value_byte_0x09: 0,
|
||||
|
|
@ -3767,6 +3864,7 @@ mod tests {
|
|||
target_mask_bits: Some(0x08),
|
||||
parameter_family: Some("locomotive_availability_scalar".to_string()),
|
||||
grouped_target_subject: None,
|
||||
grouped_target_scope: None,
|
||||
opcode: 3,
|
||||
raw_scalar_value: value,
|
||||
value_byte_0x09: 0,
|
||||
|
|
@ -3810,6 +3908,7 @@ mod tests {
|
|||
target_mask_bits: Some(0x08),
|
||||
parameter_family: Some("locomotive_cost_scalar".to_string()),
|
||||
grouped_target_subject: None,
|
||||
grouped_target_scope: None,
|
||||
opcode: 3,
|
||||
raw_scalar_value: value,
|
||||
value_byte_0x09: 0,
|
||||
|
|
@ -3998,6 +4097,7 @@ mod tests {
|
|||
target_mask_bits: Some(0x08),
|
||||
parameter_family: Some("cargo_production_scalar".to_string()),
|
||||
grouped_target_subject: None,
|
||||
grouped_target_scope: None,
|
||||
opcode: 3,
|
||||
raw_scalar_value: value,
|
||||
value_byte_0x09: 0,
|
||||
|
|
@ -4028,6 +4128,7 @@ mod tests {
|
|||
target_mask_bits: Some(0x08),
|
||||
parameter_family: Some("territory_access_cost_scalar".to_string()),
|
||||
grouped_target_subject: None,
|
||||
grouped_target_scope: None,
|
||||
opcode: 3,
|
||||
raw_scalar_value: value,
|
||||
value_byte_0x09: 0,
|
||||
|
|
@ -4060,6 +4161,7 @@ mod tests {
|
|||
target_mask_bits: Some(0x08),
|
||||
parameter_family: Some("world_flag_toggle".to_string()),
|
||||
grouped_target_subject: None,
|
||||
grouped_target_scope: None,
|
||||
opcode: 0,
|
||||
raw_scalar_value: if enabled { 1 } else { 0 },
|
||||
value_byte_0x09: 0,
|
||||
|
|
@ -4093,6 +4195,7 @@ mod tests {
|
|||
target_mask_bits: Some(0x01),
|
||||
parameter_family: Some("company_confiscation_variant".to_string()),
|
||||
grouped_target_subject: None,
|
||||
grouped_target_scope: None,
|
||||
opcode: 1,
|
||||
raw_scalar_value: if enabled { 1 } else { 0 },
|
||||
value_byte_0x09: 0,
|
||||
|
|
@ -4128,6 +4231,7 @@ mod tests {
|
|||
target_mask_bits: Some(0x0d),
|
||||
parameter_family: Some("company_or_territory_asset_toggle".to_string()),
|
||||
grouped_target_subject: None,
|
||||
grouped_target_scope: None,
|
||||
opcode: 1,
|
||||
raw_scalar_value: if enabled { 1 } else { 0 },
|
||||
value_byte_0x09: 0,
|
||||
|
|
@ -4159,6 +4263,7 @@ mod tests {
|
|||
target_mask_bits: Some(0x01),
|
||||
parameter_family: Some("company_confiscation_variant".to_string()),
|
||||
grouped_target_subject: None,
|
||||
grouped_target_scope: None,
|
||||
opcode: 1,
|
||||
raw_scalar_value: 0,
|
||||
value_byte_0x09: 0,
|
||||
|
|
@ -6005,6 +6110,7 @@ mod tests {
|
|||
target_mask_bits: Some(0x08),
|
||||
parameter_family: Some("locomotive_availability_scalar".to_string()),
|
||||
grouped_target_subject: None,
|
||||
grouped_target_scope: None,
|
||||
opcode: 3,
|
||||
raw_scalar_value: 42,
|
||||
value_byte_0x09: 0,
|
||||
|
|
@ -7155,6 +7261,7 @@ mod tests {
|
|||
target_mask_bits: Some(0x01),
|
||||
parameter_family: Some("company_finance_scalar".to_string()),
|
||||
grouped_target_subject: None,
|
||||
grouped_target_scope: None,
|
||||
opcode: 8,
|
||||
raw_scalar_value: 250,
|
||||
value_byte_0x09: 1,
|
||||
|
|
@ -8785,6 +8892,7 @@ mod tests {
|
|||
target_mask_bits: Some(0x08),
|
||||
parameter_family: Some("candidate_availability_scalar".to_string()),
|
||||
grouped_target_subject: None,
|
||||
grouped_target_scope: None,
|
||||
opcode: 3,
|
||||
raw_scalar_value: 1,
|
||||
value_byte_0x09: 0,
|
||||
|
|
|
|||
|
|
@ -196,7 +196,10 @@ pub enum RuntimePlayerTarget {
|
|||
#[serde(tag = "kind", rename_all = "snake_case")]
|
||||
pub enum RuntimeChairmanTarget {
|
||||
AllActive,
|
||||
HumanChairmen,
|
||||
AiChairmen,
|
||||
SelectedChairman,
|
||||
ConditionTrueChairman,
|
||||
Ids { ids: Vec<u32> },
|
||||
}
|
||||
|
||||
|
|
@ -402,6 +405,11 @@ pub enum RuntimeEffect {
|
|||
target: RuntimeChairmanTarget,
|
||||
value: i64,
|
||||
},
|
||||
SetCompanyGovernanceScalar {
|
||||
target: RuntimeCompanyTarget,
|
||||
metric: RuntimeCompanyMetric,
|
||||
value: i64,
|
||||
},
|
||||
DeactivatePlayer {
|
||||
target: RuntimePlayerTarget,
|
||||
},
|
||||
|
|
@ -661,6 +669,8 @@ pub struct RuntimePackedEventGroupedEffectRowSummary {
|
|||
pub parameter_family: Option<String>,
|
||||
#[serde(default)]
|
||||
pub grouped_target_subject: Option<String>,
|
||||
#[serde(default)]
|
||||
pub grouped_target_scope: Option<String>,
|
||||
pub opcode: u8,
|
||||
pub raw_scalar_value: i32,
|
||||
pub value_byte_0x09: u8,
|
||||
|
|
@ -1512,6 +1522,10 @@ fn validate_runtime_effect(
|
|||
| RuntimeEffect::AdjustCompanyDebt { target, .. } => {
|
||||
validate_company_target(target, valid_company_ids)?;
|
||||
}
|
||||
RuntimeEffect::SetCompanyGovernanceScalar { target, metric, .. } => {
|
||||
validate_company_target(target, valid_company_ids)?;
|
||||
validate_company_governance_scalar_metric(*metric)?;
|
||||
}
|
||||
RuntimeEffect::SetCompanyTerritoryAccess {
|
||||
target, territory, ..
|
||||
} => {
|
||||
|
|
@ -1761,7 +1775,11 @@ fn validate_chairman_target(
|
|||
valid_chairman_profile_ids: &BTreeSet<u32>,
|
||||
) -> Result<(), String> {
|
||||
match target {
|
||||
RuntimeChairmanTarget::AllActive | RuntimeChairmanTarget::SelectedChairman => Ok(()),
|
||||
RuntimeChairmanTarget::AllActive
|
||||
| RuntimeChairmanTarget::HumanChairmen
|
||||
| RuntimeChairmanTarget::AiChairmen
|
||||
| RuntimeChairmanTarget::SelectedChairman
|
||||
| RuntimeChairmanTarget::ConditionTrueChairman => Ok(()),
|
||||
RuntimeChairmanTarget::Ids { ids } => {
|
||||
if ids.is_empty() {
|
||||
return Err("target ids must not be empty".to_string());
|
||||
|
|
@ -1778,6 +1796,19 @@ fn validate_chairman_target(
|
|||
}
|
||||
}
|
||||
|
||||
fn validate_company_governance_scalar_metric(metric: RuntimeCompanyMetric) -> Result<(), String> {
|
||||
match metric {
|
||||
RuntimeCompanyMetric::CreditRating
|
||||
| RuntimeCompanyMetric::PrimeRate
|
||||
| RuntimeCompanyMetric::BookValuePerShare
|
||||
| RuntimeCompanyMetric::InvestorConfidence
|
||||
| RuntimeCompanyMetric::ManagementAttitude => Ok(()),
|
||||
_ => Err(
|
||||
"governance scalar effect requires a writable company governance metric".to_string(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn validate_territory_target(
|
||||
target: &RuntimeTerritoryTarget,
|
||||
valid_territory_ids: &BTreeSet<u32>,
|
||||
|
|
|
|||
|
|
@ -2007,6 +2007,8 @@ pub struct SmpLoadedPackedEventGroupedEffectRowSummary {
|
|||
pub parameter_family: Option<String>,
|
||||
#[serde(default)]
|
||||
pub grouped_target_subject: Option<String>,
|
||||
#[serde(default)]
|
||||
pub grouped_target_scope: Option<String>,
|
||||
pub opcode: u8,
|
||||
pub raw_scalar_value: i32,
|
||||
pub value_byte_0x09: u8,
|
||||
|
|
@ -2736,9 +2738,20 @@ fn parse_real_event_runtime_record_summary(
|
|||
}
|
||||
if let Some(control) = compact_control.as_ref() {
|
||||
for row in &mut grouped_effect_rows {
|
||||
row.grouped_target_subject = derive_real_grouped_target_subject(row, control)
|
||||
let target_subject = derive_real_grouped_target_subject(row, control);
|
||||
let target_scope_ordinal = control
|
||||
.grouped_target_scope_ordinals_0x7fb
|
||||
.get(row.group_index)
|
||||
.copied();
|
||||
row.grouped_target_subject = target_subject
|
||||
.map(real_grouped_target_subject_name)
|
||||
.map(str::to_string);
|
||||
row.grouped_target_scope = derive_real_grouped_target_scope_name(
|
||||
row,
|
||||
control,
|
||||
target_subject,
|
||||
target_scope_ordinal,
|
||||
);
|
||||
let company_target_present = control
|
||||
.grouped_target_scope_ordinals_0x7fb
|
||||
.get(row.group_index)
|
||||
|
|
@ -2771,13 +2784,13 @@ fn parse_real_event_runtime_record_summary(
|
|||
row.notes
|
||||
.push("territory access row is missing company or territory scope".to_string());
|
||||
}
|
||||
if matches!(
|
||||
derive_real_grouped_target_subject(row, control),
|
||||
Some(RealGroupedTargetSubject::Chairman)
|
||||
) && !chairman_target_present
|
||||
if matches!(target_subject, Some(RealGroupedTargetSubject::Chairman))
|
||||
&& !chairman_target_present
|
||||
{
|
||||
row.notes
|
||||
.push("chairman row requires selected-chairman scope".to_string());
|
||||
let ordinal = target_scope_ordinal.unwrap_or(u8::MAX);
|
||||
row.notes.push(format!(
|
||||
"chairman row uses unsupported grouped target scope ordinal {ordinal}"
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3337,6 +3350,7 @@ fn parse_real_grouped_effect_row_summary(
|
|||
target_mask_bits: descriptor_metadata.map(|metadata| metadata.target_mask_bits),
|
||||
parameter_family: descriptor_metadata.map(|metadata| metadata.parameter_family.to_string()),
|
||||
grouped_target_subject: None,
|
||||
grouped_target_scope: None,
|
||||
opcode,
|
||||
raw_scalar_value,
|
||||
value_byte_0x09,
|
||||
|
|
@ -3524,9 +3538,11 @@ fn real_condition_chairman_target(
|
|||
RuntimePlayerConditionTestScope::SelectedPlayerOnly => {
|
||||
Some(RuntimeChairmanTarget::SelectedChairman)
|
||||
}
|
||||
RuntimePlayerConditionTestScope::Disabled
|
||||
| RuntimePlayerConditionTestScope::AiPlayersOnly
|
||||
| RuntimePlayerConditionTestScope::HumanPlayersOnly => None,
|
||||
RuntimePlayerConditionTestScope::AiPlayersOnly => Some(RuntimeChairmanTarget::AiChairmen),
|
||||
RuntimePlayerConditionTestScope::HumanPlayersOnly => {
|
||||
Some(RuntimeChairmanTarget::HumanChairmen)
|
||||
}
|
||||
RuntimePlayerConditionTestScope::Disabled => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3892,6 +3908,63 @@ fn real_grouped_target_subject_name(subject: RealGroupedTargetSubject) -> &'stat
|
|||
}
|
||||
}
|
||||
|
||||
fn derive_real_grouped_target_scope_name(
|
||||
row: &SmpLoadedPackedEventGroupedEffectRowSummary,
|
||||
compact_control: &SmpLoadedPackedEventCompactControlSummary,
|
||||
target_subject: Option<RealGroupedTargetSubject>,
|
||||
target_scope_ordinal: Option<u8>,
|
||||
) -> Option<String> {
|
||||
match target_subject {
|
||||
Some(RealGroupedTargetSubject::Company) => target_scope_ordinal
|
||||
.map(real_grouped_company_scope_name)
|
||||
.map(str::to_string),
|
||||
Some(RealGroupedTargetSubject::Player) => target_scope_ordinal
|
||||
.map(real_grouped_player_scope_name)
|
||||
.map(str::to_string),
|
||||
Some(RealGroupedTargetSubject::Chairman) => target_scope_ordinal
|
||||
.map(real_grouped_chairman_scope_name)
|
||||
.map(str::to_string),
|
||||
Some(RealGroupedTargetSubject::Territory) => compact_control
|
||||
.grouped_territory_selectors_0x80f
|
||||
.get(row.group_index)
|
||||
.copied()
|
||||
.filter(|selector| *selector >= 0)
|
||||
.map(|_| "specified_territories".to_string()),
|
||||
Some(RealGroupedTargetSubject::WholeGame) => Some("whole_game".to_string()),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn real_grouped_company_scope_name(ordinal: u8) -> &'static str {
|
||||
match ordinal {
|
||||
0 => "condition_true_company",
|
||||
1 => "selected_company",
|
||||
2 => "human_companies",
|
||||
3 => "ai_companies",
|
||||
_ => "unsupported_company_scope",
|
||||
}
|
||||
}
|
||||
|
||||
fn real_grouped_player_scope_name(ordinal: u8) -> &'static str {
|
||||
match ordinal {
|
||||
0 => "condition_true_player",
|
||||
1 => "selected_player",
|
||||
2 => "human_players",
|
||||
3 => "ai_players",
|
||||
_ => "unsupported_player_scope",
|
||||
}
|
||||
}
|
||||
|
||||
fn real_grouped_chairman_scope_name(ordinal: u8) -> &'static str {
|
||||
match ordinal {
|
||||
0 => "condition_true_chairman",
|
||||
1 => "selected_chairman",
|
||||
2 => "human_chairmen",
|
||||
3 => "ai_chairmen",
|
||||
_ => "unsupported_chairman_scope",
|
||||
}
|
||||
}
|
||||
|
||||
fn decode_real_grouped_effect_actions(
|
||||
grouped_effect_rows: &[SmpLoadedPackedEventGroupedEffectRowSummary],
|
||||
compact_control: &SmpLoadedPackedEventCompactControlSummary,
|
||||
|
|
@ -4127,7 +4200,10 @@ fn real_grouped_player_target(ordinal: u8) -> Option<RuntimePlayerTarget> {
|
|||
|
||||
fn real_grouped_chairman_target(ordinal: u8) -> Option<RuntimeChairmanTarget> {
|
||||
match ordinal {
|
||||
0 => Some(RuntimeChairmanTarget::ConditionTrueChairman),
|
||||
1 => Some(RuntimeChairmanTarget::SelectedChairman),
|
||||
2 => Some(RuntimeChairmanTarget::HumanChairmen),
|
||||
3 => Some(RuntimeChairmanTarget::AiChairmen),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -4287,12 +4363,16 @@ fn runtime_effect_supported_for_save_import(effect: &RuntimeEffect) -> bool {
|
|||
| RuntimeEffect::DeactivateChairman { target } => matches!(
|
||||
target,
|
||||
RuntimeChairmanTarget::AllActive
|
||||
| RuntimeChairmanTarget::HumanChairmen
|
||||
| RuntimeChairmanTarget::AiChairmen
|
||||
| RuntimeChairmanTarget::SelectedChairman
|
||||
| RuntimeChairmanTarget::ConditionTrueChairman
|
||||
| RuntimeChairmanTarget::Ids { .. }
|
||||
),
|
||||
RuntimeEffect::SetWorldFlag { .. }
|
||||
| RuntimeEffect::SetLimitedTrackBuildingAmount { .. }
|
||||
| RuntimeEffect::SetEconomicStatusCode { .. }
|
||||
| RuntimeEffect::SetCompanyGovernanceScalar { .. }
|
||||
| RuntimeEffect::SetCandidateAvailability { .. }
|
||||
| RuntimeEffect::SetNamedLocomotiveAvailability { .. }
|
||||
| RuntimeEffect::SetNamedLocomotiveAvailabilityValue { .. }
|
||||
|
|
|
|||
|
|
@ -87,7 +87,6 @@ struct AppliedEffectsSummary {
|
|||
struct ResolvedConditionContext {
|
||||
matching_company_ids: BTreeSet<u32>,
|
||||
matching_player_ids: BTreeSet<u32>,
|
||||
#[allow(dead_code)]
|
||||
matching_chairman_profile_ids: BTreeSet<u32>,
|
||||
}
|
||||
|
||||
|
|
@ -363,6 +362,48 @@ fn apply_runtime_effects(
|
|||
chairman.current_cash = *value;
|
||||
}
|
||||
}
|
||||
RuntimeEffect::SetCompanyGovernanceScalar {
|
||||
target,
|
||||
metric,
|
||||
value,
|
||||
} => {
|
||||
let company_ids = resolve_company_target_ids(state, target, condition_context)?;
|
||||
for company_id in company_ids {
|
||||
let company = state
|
||||
.companies
|
||||
.iter_mut()
|
||||
.find(|company| company.company_id == company_id)
|
||||
.ok_or_else(|| {
|
||||
format!(
|
||||
"missing company_id {company_id} while applying governance effect"
|
||||
)
|
||||
})?;
|
||||
match metric {
|
||||
RuntimeCompanyMetric::CreditRating => {
|
||||
company.credit_rating_score = Some(*value);
|
||||
}
|
||||
RuntimeCompanyMetric::PrimeRate => {
|
||||
company.prime_rate = Some(*value);
|
||||
}
|
||||
RuntimeCompanyMetric::BookValuePerShare => {
|
||||
company.book_value_per_share = *value;
|
||||
}
|
||||
RuntimeCompanyMetric::InvestorConfidence => {
|
||||
company.investor_confidence = *value;
|
||||
}
|
||||
RuntimeCompanyMetric::ManagementAttitude => {
|
||||
company.management_attitude = *value;
|
||||
}
|
||||
_ => {
|
||||
return Err(format!(
|
||||
"unsupported governance metric {:?} in company governance effect",
|
||||
metric
|
||||
));
|
||||
}
|
||||
}
|
||||
mutated_company_ids.insert(company_id);
|
||||
}
|
||||
}
|
||||
RuntimeEffect::DeactivatePlayer { target } => {
|
||||
let player_ids = resolve_player_target_ids(state, target, condition_context)?;
|
||||
for player_id in player_ids {
|
||||
|
|
@ -1152,7 +1193,7 @@ fn resolve_player_target_ids(
|
|||
fn resolve_chairman_target_ids(
|
||||
state: &RuntimeState,
|
||||
target: &RuntimeChairmanTarget,
|
||||
_condition_context: &ResolvedConditionContext,
|
||||
condition_context: &ResolvedConditionContext,
|
||||
) -> Result<Vec<u32>, String> {
|
||||
match target {
|
||||
RuntimeChairmanTarget::AllActive => Ok(state
|
||||
|
|
@ -1161,6 +1202,30 @@ fn resolve_chairman_target_ids(
|
|||
.filter(|profile| profile.active)
|
||||
.map(|profile| profile.profile_id)
|
||||
.collect()),
|
||||
RuntimeChairmanTarget::HumanChairmen => Ok(state
|
||||
.chairman_profiles
|
||||
.iter()
|
||||
.filter(|profile| {
|
||||
chairman_profile_matches_company_controller_kind(
|
||||
state,
|
||||
profile,
|
||||
RuntimeCompanyControllerKind::Human,
|
||||
)
|
||||
})
|
||||
.map(|profile| profile.profile_id)
|
||||
.collect()),
|
||||
RuntimeChairmanTarget::AiChairmen => Ok(state
|
||||
.chairman_profiles
|
||||
.iter()
|
||||
.filter(|profile| {
|
||||
chairman_profile_matches_company_controller_kind(
|
||||
state,
|
||||
profile,
|
||||
RuntimeCompanyControllerKind::Ai,
|
||||
)
|
||||
})
|
||||
.map(|profile| profile.profile_id)
|
||||
.collect()),
|
||||
RuntimeChairmanTarget::Ids { ids } => {
|
||||
let known_ids = state
|
||||
.chairman_profiles
|
||||
|
|
@ -1193,9 +1258,37 @@ fn resolve_chairman_target_ids(
|
|||
)
|
||||
}
|
||||
}
|
||||
RuntimeChairmanTarget::ConditionTrueChairman => {
|
||||
if condition_context.matching_chairman_profile_ids.is_empty() {
|
||||
Err("target requires chairman condition-evaluation context".to_string())
|
||||
} else {
|
||||
Ok(condition_context
|
||||
.matching_chairman_profile_ids
|
||||
.iter()
|
||||
.copied()
|
||||
.collect())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn chairman_profile_matches_company_controller_kind(
|
||||
state: &RuntimeState,
|
||||
profile: &crate::RuntimeChairmanProfile,
|
||||
controller_kind: RuntimeCompanyControllerKind,
|
||||
) -> bool {
|
||||
profile.active
|
||||
&& profile
|
||||
.linked_company_id
|
||||
.and_then(|company_id| {
|
||||
state
|
||||
.companies
|
||||
.iter()
|
||||
.find(|company| company.company_id == company_id)
|
||||
})
|
||||
.is_some_and(|company| company.controller_kind == controller_kind)
|
||||
}
|
||||
|
||||
fn resolve_territory_target_ids(
|
||||
state: &RuntimeState,
|
||||
target: &RuntimeTerritoryTarget,
|
||||
|
|
|
|||
|
|
@ -85,8 +85,9 @@ The highest-value next passes are now:
|
|||
through the same ordinary runtime path, backed by the minimal player runtime and overlay-import
|
||||
context
|
||||
- the first chairman-targeted real grouped rows now execute too through that same path when the
|
||||
hidden grouped target-subject lane resolves to selected-chairman scope; broader chairman target
|
||||
scopes stay parity-only under `blocked_chairman_target_scope`
|
||||
hidden grouped target-subject lane resolves to grounded chairman scope ordinals `0..3`:
|
||||
`condition_true_chairman`, `selected_chairman`, `human_chairmen`, and `ai_chairmen`; wider
|
||||
chairman ordinals stay parity-only under `blocked_chairman_target_scope`
|
||||
- chairman runtime ownership is broader now too: selected-chairman condition rows for chairman
|
||||
cash, holdings value, net worth, and purchasing power import through the same service path, and
|
||||
the first grounded company governance issue batch now executes too via book-value-per-share,
|
||||
|
|
@ -96,6 +97,9 @@ The highest-value next passes are now:
|
|||
tables too, so the current company-targeted and chairman-targeted descriptor/condition batches
|
||||
can execute from standalone save-slice fixtures without overlay snapshots when that context is
|
||||
present; raw `.gms` inspection/export still does not reconstruct those company/chairman surfaces
|
||||
- a generic company-governance scalar effect surface now exists in runtime too, but real
|
||||
governance descriptor ids remain deferred until the checked-in `EventEffects.win` evidence is
|
||||
strong enough to recover them honestly
|
||||
- widen real packed-event executable coverage descriptor by descriptor after identity, target mask,
|
||||
and normalized effect semantics are all grounded, not just after row framing is parsed
|
||||
- the first grounded condition-side unlock now exists for negative-sentinel `raw_condition_id = -1`
|
||||
|
|
|
|||
|
|
@ -51,13 +51,18 @@ Implemented today:
|
|||
lanes, and the first grounded chairman/control-transfer ordinary-condition batch now imports and
|
||||
executes through the same path for selected-chairman cash / holdings / net-worth /
|
||||
purchasing-power thresholds plus company book-value-per-share / investor-confidence /
|
||||
management-attitude thresholds; wider chairman target ordinals remain parity frontier
|
||||
management-attitude thresholds; real chairman grouped-effect scope ordinals `0..3` now execute
|
||||
too as `condition_true`, `selected`, `human`, and `ai`, while wider ordinals remain parity
|
||||
frontier
|
||||
- checked-in save-slice documents can now carry explicit company rosters and chairman profile
|
||||
tables too, and runtime projection/import will seed or replace company/chairman context from
|
||||
those save-owned surfaces; that lets the currently supported company-targeted and
|
||||
chairman-targeted descriptor/condition batches execute from standalone save-slice fixtures
|
||||
without overlay snapshots when the checked-in documents include that context, while raw `.gms`
|
||||
inspection/export still leaves those company/chairman surfaces absent
|
||||
- a generic company-governance scalar effect surface now exists in runtime, but real governance
|
||||
descriptor recovery is still deferred until the checked-in effect-table evidence can ground the
|
||||
ids honestly
|
||||
- a minimal event-owned train surface and an opaque economic-status lane now exist in runtime
|
||||
state, and real descriptors `8` = `Economic Status`, `9` = `Confiscate All`, and `15` =
|
||||
`Retire Train` now import and execute through the ordinary runtime path when overlay context
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
"format_version": 1,
|
||||
"fixture_id": "packed-event-chairman-condition-true-save-slice-fixture",
|
||||
"source": {
|
||||
"kind": "captured-runtime",
|
||||
"description": "Fixture proving grouped target-scope ordinal 0 executes as condition-true chairman scope from save-slice-backed context."
|
||||
},
|
||||
"state_save_slice_path": "packed-event-chairman-condition-true-save-slice.json",
|
||||
"commands": [
|
||||
{
|
||||
"kind": "service_trigger_kind",
|
||||
"trigger_kind": 6
|
||||
}
|
||||
],
|
||||
"expected_summary": {
|
||||
"calendar_projection_source": "default-1830-placeholder",
|
||||
"calendar_projection_is_placeholder": true,
|
||||
"company_count": 2,
|
||||
"chairman_profile_count": 2,
|
||||
"active_chairman_profile_count": 2,
|
||||
"selected_chairman_profile_id": 1,
|
||||
"packed_event_collection_present": true,
|
||||
"packed_event_record_count": 1,
|
||||
"packed_event_decoded_record_count": 1,
|
||||
"packed_event_imported_runtime_record_count": 1,
|
||||
"event_runtime_record_count": 1,
|
||||
"total_event_record_service_count": 1,
|
||||
"total_trigger_dispatch_count": 1
|
||||
},
|
||||
"expected_state_fragment": {
|
||||
"chairman_profiles": [
|
||||
{
|
||||
"profile_id": 1,
|
||||
"current_cash": 777
|
||||
},
|
||||
{
|
||||
"profile_id": 2,
|
||||
"current_cash": 250
|
||||
}
|
||||
],
|
||||
"packed_event_collection": {
|
||||
"records": [
|
||||
{
|
||||
"import_outcome": "imported"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,284 @@
|
|||
{
|
||||
"format_version": 1,
|
||||
"save_slice_id": "packed-event-chairman-condition-true-save-slice",
|
||||
"source": {
|
||||
"description": "Tracked save-slice document proving condition-true chairman scope executes through matched chairman conditions.",
|
||||
"original_save_filename": "captured-chairman-condition-true.gms",
|
||||
"original_save_sha256": "chairman-condition-true-sample-sha256",
|
||||
"notes": [
|
||||
"tracked as JSON save-slice document rather than raw .smp",
|
||||
"proves grouped target-scope ordinal 0 resolves to condition-true chairman scope"
|
||||
]
|
||||
},
|
||||
"save_slice": {
|
||||
"file_extension_hint": "gms",
|
||||
"container_profile_family": "rt3-classic-save-container-v1",
|
||||
"mechanism_family": "classic-save-rehydrate-v1",
|
||||
"mechanism_confidence": "grounded",
|
||||
"trailer_family": null,
|
||||
"bridge_family": null,
|
||||
"profile": null,
|
||||
"candidate_availability_table": null,
|
||||
"named_locomotive_availability_table": null,
|
||||
"cargo_catalog": null,
|
||||
"special_conditions_table": null,
|
||||
"event_runtime_collection": {
|
||||
"source_kind": "packed-event-runtime-collection",
|
||||
"mechanism_family": "classic-save-rehydrate-v1",
|
||||
"mechanism_confidence": "grounded",
|
||||
"container_profile_family": "rt3-classic-save-container-v1",
|
||||
"metadata_tag_offset": 28928,
|
||||
"records_tag_offset": 29184,
|
||||
"close_tag_offset": 29696,
|
||||
"packed_state_version": 1001,
|
||||
"packed_state_version_hex": "0x000003e9",
|
||||
"live_id_bound": 72,
|
||||
"live_record_count": 1,
|
||||
"live_entry_ids": [
|
||||
72
|
||||
],
|
||||
"decoded_record_count": 1,
|
||||
"imported_runtime_record_count": 1,
|
||||
"records": [
|
||||
{
|
||||
"record_index": 0,
|
||||
"live_entry_id": 72,
|
||||
"payload_offset": 29186,
|
||||
"payload_len": 136,
|
||||
"decode_status": "executable",
|
||||
"payload_family": "real_packed_v1",
|
||||
"trigger_kind": 6,
|
||||
"active": null,
|
||||
"marks_collection_dirty": null,
|
||||
"one_shot": false,
|
||||
"compact_control": {
|
||||
"mode_byte_0x7ef": 6,
|
||||
"primary_selector_0x7f0": 99,
|
||||
"grouped_mode_0x7f4": 2,
|
||||
"one_shot_header_0x7f5": 1,
|
||||
"modifier_flag_0x7f9": 1,
|
||||
"modifier_flag_0x7fa": 0,
|
||||
"grouped_target_scope_ordinals_0x7fb": [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3
|
||||
],
|
||||
"grouped_scope_checkboxes_0x7ff": [
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0
|
||||
],
|
||||
"summary_toggle_0x800": 1,
|
||||
"grouped_territory_selectors_0x80f": [
|
||||
-1,
|
||||
10,
|
||||
-1,
|
||||
22
|
||||
]
|
||||
},
|
||||
"text_bands": [],
|
||||
"standalone_condition_row_count": 1,
|
||||
"standalone_condition_rows": [
|
||||
{
|
||||
"row_index": 0,
|
||||
"raw_condition_id": 2218,
|
||||
"subtype": 4,
|
||||
"flag_bytes": [
|
||||
244,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"candidate_name": null,
|
||||
"comparator": "eq",
|
||||
"metric": "Player Cash",
|
||||
"semantic_family": "numeric_threshold",
|
||||
"semantic_preview": "Test Player Cash == 500",
|
||||
"requires_candidate_name_binding": false,
|
||||
"notes": []
|
||||
}
|
||||
],
|
||||
"negative_sentinel_scope": {
|
||||
"company_test_scope": "disabled",
|
||||
"player_test_scope": "selected_player_only",
|
||||
"territory_scope_selector_is_0x63": false,
|
||||
"source_row_indexes": [
|
||||
0
|
||||
]
|
||||
},
|
||||
"grouped_effect_row_counts": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"grouped_effect_rows": [
|
||||
{
|
||||
"group_index": 0,
|
||||
"row_index": 0,
|
||||
"descriptor_id": 1,
|
||||
"descriptor_label": "Player Cash",
|
||||
"target_mask_bits": 2,
|
||||
"parameter_family": "player_cash_scalar",
|
||||
"grouped_target_subject": "chairman",
|
||||
"grouped_target_scope": "condition_true_chairman",
|
||||
"opcode": 8,
|
||||
"raw_scalar_value": 777,
|
||||
"value_byte_0x09": 0,
|
||||
"value_dword_0x0d": 0,
|
||||
"value_byte_0x11": 0,
|
||||
"value_byte_0x12": 0,
|
||||
"value_word_0x14": 0,
|
||||
"value_word_0x16": 0,
|
||||
"row_shape": "multivalue_scalar",
|
||||
"semantic_family": "multivalue_scalar",
|
||||
"semantic_preview": "Set Player Cash to 777 with aux [0, 0, 0, 0]",
|
||||
"locomotive_name": null,
|
||||
"notes": []
|
||||
}
|
||||
],
|
||||
"decoded_conditions": [
|
||||
{
|
||||
"kind": "chairman_numeric_threshold",
|
||||
"target": {
|
||||
"kind": "selected_chairman"
|
||||
},
|
||||
"metric": "current_cash",
|
||||
"comparator": "eq",
|
||||
"value": 500
|
||||
}
|
||||
],
|
||||
"decoded_actions": [
|
||||
{
|
||||
"kind": "set_chairman_cash",
|
||||
"target": {
|
||||
"kind": "condition_true_chairman"
|
||||
},
|
||||
"value": 777
|
||||
}
|
||||
],
|
||||
"executable_import_ready": true,
|
||||
"notes": [
|
||||
"condition-true chairman scope resolves through matched chairman conditions"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"notes": [
|
||||
"real chairman condition-true grouped-effect sample"
|
||||
],
|
||||
"company_roster": {
|
||||
"source_kind": "tracked-save-slice-company-roster",
|
||||
"semantic_family": "save-slice-runtime-company-context",
|
||||
"observed_entry_count": 2,
|
||||
"selected_company_id": 1,
|
||||
"entries": [
|
||||
{
|
||||
"company_id": 1,
|
||||
"active": true,
|
||||
"controller_kind": "human",
|
||||
"current_cash": 150,
|
||||
"debt": 80,
|
||||
"credit_rating_score": 650,
|
||||
"prime_rate": 5,
|
||||
"available_track_laying_capacity": 6,
|
||||
"track_piece_counts": {
|
||||
"total": 20,
|
||||
"single": 5,
|
||||
"double": 8,
|
||||
"transition": 1,
|
||||
"electric": 3,
|
||||
"non_electric": 17
|
||||
},
|
||||
"linked_chairman_profile_id": 1,
|
||||
"book_value_per_share": 2620,
|
||||
"investor_confidence": 37,
|
||||
"management_attitude": 58,
|
||||
"takeover_cooldown_year": 1839,
|
||||
"merger_cooldown_year": 1838
|
||||
},
|
||||
{
|
||||
"company_id": 2,
|
||||
"active": true,
|
||||
"controller_kind": "ai",
|
||||
"current_cash": 90,
|
||||
"debt": 40,
|
||||
"credit_rating_score": 480,
|
||||
"prime_rate": 6,
|
||||
"available_track_laying_capacity": 2,
|
||||
"track_piece_counts": {
|
||||
"total": 8,
|
||||
"single": 2,
|
||||
"double": 2,
|
||||
"transition": 0,
|
||||
"electric": 1,
|
||||
"non_electric": 7
|
||||
},
|
||||
"linked_chairman_profile_id": 2,
|
||||
"book_value_per_share": 1400,
|
||||
"investor_confidence": 22,
|
||||
"management_attitude": 31,
|
||||
"takeover_cooldown_year": null,
|
||||
"merger_cooldown_year": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"chairman_profile_table": {
|
||||
"source_kind": "tracked-save-slice-chairman-profile-table",
|
||||
"semantic_family": "save-slice-runtime-chairman-context",
|
||||
"observed_entry_count": 2,
|
||||
"selected_chairman_profile_id": 1,
|
||||
"entries": [
|
||||
{
|
||||
"profile_id": 1,
|
||||
"name": "Chairman One",
|
||||
"active": true,
|
||||
"current_cash": 500,
|
||||
"linked_company_id": 1,
|
||||
"company_holdings": {
|
||||
"1": 1000
|
||||
},
|
||||
"holdings_value_total": 700,
|
||||
"net_worth_total": 1200,
|
||||
"purchasing_power_total": 1500
|
||||
},
|
||||
{
|
||||
"profile_id": 2,
|
||||
"name": "Chairman Two",
|
||||
"active": true,
|
||||
"current_cash": 250,
|
||||
"linked_company_id": 2,
|
||||
"company_holdings": {
|
||||
"2": 900
|
||||
},
|
||||
"holdings_value_total": 600,
|
||||
"net_worth_total": 900,
|
||||
"purchasing_power_total": 1100
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
"format_version": 1,
|
||||
"fixture_id": "packed-event-chairman-human-cash-save-slice-fixture",
|
||||
"source": {
|
||||
"kind": "captured-runtime",
|
||||
"description": "Fixture proving grouped target-scope ordinal 2 executes as human-chairmen scope from save-slice-backed context."
|
||||
},
|
||||
"state_save_slice_path": "packed-event-chairman-human-cash-save-slice.json",
|
||||
"commands": [
|
||||
{
|
||||
"kind": "service_trigger_kind",
|
||||
"trigger_kind": 6
|
||||
}
|
||||
],
|
||||
"expected_summary": {
|
||||
"calendar_projection_source": "default-1830-placeholder",
|
||||
"calendar_projection_is_placeholder": true,
|
||||
"company_count": 2,
|
||||
"chairman_profile_count": 2,
|
||||
"active_chairman_profile_count": 2,
|
||||
"selected_chairman_profile_id": 1,
|
||||
"packed_event_collection_present": true,
|
||||
"packed_event_record_count": 1,
|
||||
"packed_event_decoded_record_count": 1,
|
||||
"packed_event_imported_runtime_record_count": 1,
|
||||
"event_runtime_record_count": 1,
|
||||
"total_event_record_service_count": 1,
|
||||
"total_trigger_dispatch_count": 1
|
||||
},
|
||||
"expected_state_fragment": {
|
||||
"chairman_profiles": [
|
||||
{
|
||||
"profile_id": 1,
|
||||
"current_cash": 777
|
||||
},
|
||||
{
|
||||
"profile_id": 2,
|
||||
"current_cash": 250
|
||||
}
|
||||
],
|
||||
"packed_event_collection": {
|
||||
"records": [
|
||||
{
|
||||
"import_outcome": "imported"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,222 @@
|
|||
{
|
||||
"format_version": 1,
|
||||
"save_slice_id": "packed-event-chairman-human-cash-save-slice",
|
||||
"source": {
|
||||
"description": "Tracked save-slice document proving grouped target-scope ordinal 2 executes as human-chairmen scope.",
|
||||
"original_save_filename": "captured-chairman-human-cash.gms",
|
||||
"original_save_sha256": "chairman-human-cash-sample-sha256",
|
||||
"notes": [
|
||||
"tracked as JSON save-slice document rather than raw .smp",
|
||||
"proves human-chairmen grouped target scope through save-native company/chairman context"
|
||||
]
|
||||
},
|
||||
"save_slice": {
|
||||
"file_extension_hint": "gms",
|
||||
"container_profile_family": "rt3-classic-save-container-v1",
|
||||
"mechanism_family": "classic-save-rehydrate-v1",
|
||||
"mechanism_confidence": "grounded",
|
||||
"trailer_family": null,
|
||||
"bridge_family": null,
|
||||
"profile": null,
|
||||
"candidate_availability_table": null,
|
||||
"special_conditions_table": null,
|
||||
"event_runtime_collection": {
|
||||
"source_kind": "packed-event-runtime-collection",
|
||||
"mechanism_family": "classic-save-rehydrate-v1",
|
||||
"mechanism_confidence": "grounded",
|
||||
"container_profile_family": "rt3-classic-save-container-v1",
|
||||
"metadata_tag_offset": 28928,
|
||||
"records_tag_offset": 29184,
|
||||
"close_tag_offset": 29696,
|
||||
"packed_state_version": 1001,
|
||||
"packed_state_version_hex": "0x000003e9",
|
||||
"live_id_bound": 73,
|
||||
"live_record_count": 1,
|
||||
"live_entry_ids": [
|
||||
73
|
||||
],
|
||||
"decoded_record_count": 1,
|
||||
"imported_runtime_record_count": 1,
|
||||
"records": [
|
||||
{
|
||||
"record_index": 0,
|
||||
"live_entry_id": 73,
|
||||
"payload_offset": 29296,
|
||||
"payload_len": 140,
|
||||
"decode_status": "executable",
|
||||
"payload_family": "real_packed_v1",
|
||||
"trigger_kind": 6,
|
||||
"one_shot": false,
|
||||
"compact_control": {
|
||||
"mode_byte_0x7ef": 6,
|
||||
"primary_selector_0x7f0": 12,
|
||||
"grouped_mode_0x7f4": 2,
|
||||
"one_shot_header_0x7f5": 0,
|
||||
"modifier_flag_0x7f9": 0,
|
||||
"modifier_flag_0x7fa": 0,
|
||||
"grouped_target_scope_ordinals_0x7fb": [
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
1
|
||||
],
|
||||
"grouped_scope_checkboxes_0x7ff": [
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"summary_toggle_0x800": 1,
|
||||
"grouped_territory_selectors_0x80f": [
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1
|
||||
]
|
||||
},
|
||||
"text_bands": [],
|
||||
"standalone_condition_row_count": 0,
|
||||
"standalone_condition_rows": [],
|
||||
"grouped_effect_row_counts": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"grouped_effect_rows": [
|
||||
{
|
||||
"group_index": 0,
|
||||
"row_index": 0,
|
||||
"descriptor_id": 1,
|
||||
"descriptor_label": "Player Cash",
|
||||
"target_mask_bits": 2,
|
||||
"parameter_family": "player_cash_scalar",
|
||||
"grouped_target_subject": "chairman",
|
||||
"grouped_target_scope": "human_chairmen",
|
||||
"opcode": 8,
|
||||
"raw_scalar_value": 777,
|
||||
"value_byte_0x09": 0,
|
||||
"value_dword_0x0d": 0,
|
||||
"value_byte_0x11": 0,
|
||||
"value_byte_0x12": 0,
|
||||
"value_word_0x14": 0,
|
||||
"value_word_0x16": 0,
|
||||
"row_shape": "multivalue_scalar",
|
||||
"semantic_family": "multivalue_scalar",
|
||||
"semantic_preview": "Set Player Cash to 777 with aux [0, 0, 0, 0]",
|
||||
"locomotive_name": null,
|
||||
"notes": []
|
||||
}
|
||||
],
|
||||
"decoded_conditions": [],
|
||||
"decoded_actions": [
|
||||
{
|
||||
"kind": "set_chairman_cash",
|
||||
"target": {
|
||||
"kind": "human_chairmen"
|
||||
},
|
||||
"value": 777
|
||||
}
|
||||
],
|
||||
"executable_import_ready": true,
|
||||
"notes": [
|
||||
"hidden grouped target-subject lane resolves descriptor 1 to human-chairmen scope"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"notes": [
|
||||
"real chairman-targeted human-scope cash descriptor sample"
|
||||
],
|
||||
"company_roster": {
|
||||
"source_kind": "tracked-save-slice-company-roster",
|
||||
"semantic_family": "save-slice-runtime-company-context",
|
||||
"observed_entry_count": 2,
|
||||
"selected_company_id": 1,
|
||||
"entries": [
|
||||
{
|
||||
"company_id": 1,
|
||||
"active": true,
|
||||
"controller_kind": "human",
|
||||
"current_cash": 150,
|
||||
"debt": 80,
|
||||
"credit_rating_score": 650,
|
||||
"prime_rate": 5,
|
||||
"available_track_laying_capacity": 6,
|
||||
"track_piece_counts": {
|
||||
"total": 20,
|
||||
"single": 5,
|
||||
"double": 8,
|
||||
"transition": 1,
|
||||
"electric": 3,
|
||||
"non_electric": 17
|
||||
},
|
||||
"linked_chairman_profile_id": 1,
|
||||
"book_value_per_share": 2620,
|
||||
"investor_confidence": 37,
|
||||
"management_attitude": 58,
|
||||
"takeover_cooldown_year": 1839,
|
||||
"merger_cooldown_year": 1838
|
||||
},
|
||||
{
|
||||
"company_id": 2,
|
||||
"active": true,
|
||||
"controller_kind": "ai",
|
||||
"current_cash": 90,
|
||||
"debt": 40,
|
||||
"credit_rating_score": 480,
|
||||
"prime_rate": 6,
|
||||
"available_track_laying_capacity": 2,
|
||||
"track_piece_counts": {
|
||||
"total": 8,
|
||||
"single": 2,
|
||||
"double": 2,
|
||||
"transition": 0,
|
||||
"electric": 1,
|
||||
"non_electric": 7
|
||||
},
|
||||
"linked_chairman_profile_id": 2,
|
||||
"book_value_per_share": 1400,
|
||||
"investor_confidence": 22,
|
||||
"management_attitude": 31,
|
||||
"takeover_cooldown_year": null,
|
||||
"merger_cooldown_year": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"chairman_profile_table": {
|
||||
"source_kind": "tracked-save-slice-chairman-profile-table",
|
||||
"semantic_family": "save-slice-runtime-chairman-context",
|
||||
"observed_entry_count": 2,
|
||||
"selected_chairman_profile_id": 1,
|
||||
"entries": [
|
||||
{
|
||||
"profile_id": 1,
|
||||
"name": "Chairman One",
|
||||
"active": true,
|
||||
"current_cash": 500,
|
||||
"linked_company_id": 1,
|
||||
"company_holdings": {
|
||||
"1": 1000
|
||||
},
|
||||
"holdings_value_total": 700,
|
||||
"net_worth_total": 1200,
|
||||
"purchasing_power_total": 1500
|
||||
},
|
||||
{
|
||||
"profile_id": 2,
|
||||
"name": "Chairman Two",
|
||||
"active": true,
|
||||
"current_cash": 250,
|
||||
"linked_company_id": 2,
|
||||
"company_holdings": {
|
||||
"2": 900
|
||||
},
|
||||
"holdings_value_total": 600,
|
||||
"net_worth_total": 900,
|
||||
"purchasing_power_total": 1100
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,12 +2,12 @@
|
|||
"format_version": 1,
|
||||
"save_slice_id": "packed-event-chairman-scope-parity-save-slice",
|
||||
"source": {
|
||||
"description": "Tracked save-slice document with a chairman-targeted row on an unsupported non-selected scope.",
|
||||
"description": "Tracked save-slice document with a chairman-targeted row on an unsupported chairman scope ordinal outside the grounded 0..3 strip.",
|
||||
"original_save_filename": "captured-chairman-scope-parity.gms",
|
||||
"original_save_sha256": "chairman-scope-parity-sample-sha256",
|
||||
"notes": [
|
||||
"tracked as JSON save-slice document rather than raw .smp",
|
||||
"pins the selected-chairman-only execution boundary"
|
||||
"pins the remaining unsupported chairman-scope ordinal frontier"
|
||||
]
|
||||
},
|
||||
"save_slice": {
|
||||
|
|
@ -52,7 +52,7 @@
|
|||
"one_shot_header_0x7f5": 0,
|
||||
"modifier_flag_0x7f9": 0,
|
||||
"modifier_flag_0x7fa": 0,
|
||||
"grouped_target_scope_ordinals_0x7fb": [0, 1, 1, 1],
|
||||
"grouped_target_scope_ordinals_0x7fb": [8, 1, 1, 1],
|
||||
"grouped_scope_checkboxes_0x7ff": [2, 0, 0, 0],
|
||||
"summary_toggle_0x800": 1,
|
||||
"grouped_territory_selectors_0x80f": [-1, -1, -1, -1]
|
||||
|
|
@ -70,6 +70,7 @@
|
|||
"target_mask_bits": 2,
|
||||
"parameter_family": "player_cash_scalar",
|
||||
"grouped_target_subject": "chairman",
|
||||
"grouped_target_scope": "unsupported_chairman_scope",
|
||||
"opcode": 8,
|
||||
"raw_scalar_value": 700,
|
||||
"value_byte_0x09": 0,
|
||||
|
|
@ -83,7 +84,7 @@
|
|||
"semantic_preview": "Set Player Cash to 700 with aux [0, 0, 0, 0]",
|
||||
"locomotive_name": null,
|
||||
"notes": [
|
||||
"chairman row requires selected-chairman scope"
|
||||
"chairman row uses unsupported grouped target scope ordinal 8"
|
||||
]
|
||||
}
|
||||
],
|
||||
|
|
@ -92,7 +93,7 @@
|
|||
"executable_import_ready": false,
|
||||
"notes": [
|
||||
"decoded from grounded real 0x4e9a row framing",
|
||||
"selected-chairman scope is the only grounded chairman-target subset in this slice"
|
||||
"only chairman target-scope ordinals 0..3 are grounded in this slice"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
{
|
||||
"format_version": 1,
|
||||
"fixture_id": "packed-event-deactivate-chairman-ai-save-slice-fixture",
|
||||
"source": {
|
||||
"kind": "captured-runtime",
|
||||
"description": "Fixture proving grouped target-scope ordinal 3 executes as AI-chairmen scope from save-slice-backed context."
|
||||
},
|
||||
"state_save_slice_path": "packed-event-deactivate-chairman-ai-save-slice.json",
|
||||
"commands": [
|
||||
{
|
||||
"kind": "service_trigger_kind",
|
||||
"trigger_kind": 6
|
||||
}
|
||||
],
|
||||
"expected_summary": {
|
||||
"calendar_projection_source": "default-1830-placeholder",
|
||||
"calendar_projection_is_placeholder": true,
|
||||
"company_count": 2,
|
||||
"chairman_profile_count": 2,
|
||||
"active_chairman_profile_count": 1,
|
||||
"selected_chairman_profile_id": 1,
|
||||
"packed_event_collection_present": true,
|
||||
"packed_event_record_count": 1,
|
||||
"packed_event_decoded_record_count": 1,
|
||||
"packed_event_imported_runtime_record_count": 1,
|
||||
"event_runtime_record_count": 1,
|
||||
"total_event_record_service_count": 1,
|
||||
"total_trigger_dispatch_count": 1
|
||||
},
|
||||
"expected_state_fragment": {
|
||||
"selected_chairman_profile_id": 1,
|
||||
"companies": [
|
||||
{
|
||||
"company_id": 1,
|
||||
"linked_chairman_profile_id": 1
|
||||
},
|
||||
{
|
||||
"company_id": 2,
|
||||
"linked_chairman_profile_id": null
|
||||
}
|
||||
],
|
||||
"chairman_profiles": [
|
||||
{
|
||||
"profile_id": 1,
|
||||
"active": true,
|
||||
"linked_company_id": 1
|
||||
},
|
||||
{
|
||||
"profile_id": 2,
|
||||
"active": false,
|
||||
"linked_company_id": null
|
||||
}
|
||||
],
|
||||
"packed_event_collection": {
|
||||
"records": [
|
||||
{
|
||||
"import_outcome": "imported"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,221 @@
|
|||
{
|
||||
"format_version": 1,
|
||||
"save_slice_id": "packed-event-deactivate-chairman-ai-save-slice",
|
||||
"source": {
|
||||
"description": "Tracked save-slice document proving grouped target-scope ordinal 3 executes as AI-chairmen scope.",
|
||||
"original_save_filename": "captured-deactivate-chairman-ai.gms",
|
||||
"original_save_sha256": "deactivate-chairman-ai-sample-sha256",
|
||||
"notes": [
|
||||
"tracked as JSON save-slice document rather than raw .smp",
|
||||
"proves AI-chairmen lifecycle import through save-native company/chairman context"
|
||||
]
|
||||
},
|
||||
"save_slice": {
|
||||
"file_extension_hint": "gms",
|
||||
"container_profile_family": "rt3-classic-save-container-v1",
|
||||
"mechanism_family": "classic-save-rehydrate-v1",
|
||||
"mechanism_confidence": "grounded",
|
||||
"trailer_family": null,
|
||||
"bridge_family": null,
|
||||
"profile": null,
|
||||
"candidate_availability_table": null,
|
||||
"special_conditions_table": null,
|
||||
"event_runtime_collection": {
|
||||
"source_kind": "packed-event-runtime-collection",
|
||||
"mechanism_family": "classic-save-rehydrate-v1",
|
||||
"mechanism_confidence": "grounded",
|
||||
"container_profile_family": "rt3-classic-save-container-v1",
|
||||
"metadata_tag_offset": 28928,
|
||||
"records_tag_offset": 29184,
|
||||
"close_tag_offset": 29696,
|
||||
"packed_state_version": 1001,
|
||||
"packed_state_version_hex": "0x000003e9",
|
||||
"live_id_bound": 74,
|
||||
"live_record_count": 1,
|
||||
"live_entry_ids": [
|
||||
74
|
||||
],
|
||||
"decoded_record_count": 1,
|
||||
"imported_runtime_record_count": 1,
|
||||
"records": [
|
||||
{
|
||||
"record_index": 0,
|
||||
"live_entry_id": 74,
|
||||
"payload_offset": 29296,
|
||||
"payload_len": 140,
|
||||
"decode_status": "executable",
|
||||
"payload_family": "real_packed_v1",
|
||||
"trigger_kind": 6,
|
||||
"one_shot": false,
|
||||
"compact_control": {
|
||||
"mode_byte_0x7ef": 6,
|
||||
"primary_selector_0x7f0": 12,
|
||||
"grouped_mode_0x7f4": 2,
|
||||
"one_shot_header_0x7f5": 0,
|
||||
"modifier_flag_0x7f9": 0,
|
||||
"modifier_flag_0x7fa": 0,
|
||||
"grouped_target_scope_ordinals_0x7fb": [
|
||||
3,
|
||||
1,
|
||||
1,
|
||||
1
|
||||
],
|
||||
"grouped_scope_checkboxes_0x7ff": [
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"summary_toggle_0x800": 1,
|
||||
"grouped_territory_selectors_0x80f": [
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
-1
|
||||
]
|
||||
},
|
||||
"text_bands": [],
|
||||
"standalone_condition_row_count": 0,
|
||||
"standalone_condition_rows": [],
|
||||
"grouped_effect_row_counts": [
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
],
|
||||
"grouped_effect_rows": [
|
||||
{
|
||||
"group_index": 0,
|
||||
"row_index": 0,
|
||||
"descriptor_id": 14,
|
||||
"descriptor_label": "Deactivate Player",
|
||||
"target_mask_bits": 2,
|
||||
"parameter_family": "player_lifecycle_toggle",
|
||||
"grouped_target_subject": "chairman",
|
||||
"grouped_target_scope": "ai_chairmen",
|
||||
"opcode": 1,
|
||||
"raw_scalar_value": 1,
|
||||
"value_byte_0x09": 0,
|
||||
"value_dword_0x0d": 0,
|
||||
"value_byte_0x11": 0,
|
||||
"value_byte_0x12": 0,
|
||||
"value_word_0x14": 0,
|
||||
"value_word_0x16": 0,
|
||||
"row_shape": "bool_toggle",
|
||||
"semantic_family": "bool_toggle",
|
||||
"semantic_preview": "Set Deactivate Player to TRUE",
|
||||
"locomotive_name": null,
|
||||
"notes": []
|
||||
}
|
||||
],
|
||||
"decoded_conditions": [],
|
||||
"decoded_actions": [
|
||||
{
|
||||
"kind": "deactivate_chairman",
|
||||
"target": {
|
||||
"kind": "ai_chairmen"
|
||||
}
|
||||
}
|
||||
],
|
||||
"executable_import_ready": true,
|
||||
"notes": [
|
||||
"hidden grouped target-subject lane resolves descriptor 14 to AI-chairmen scope"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"notes": [
|
||||
"real chairman-targeted AI-scope lifecycle descriptor sample"
|
||||
],
|
||||
"company_roster": {
|
||||
"source_kind": "tracked-save-slice-company-roster",
|
||||
"semantic_family": "save-slice-runtime-company-context",
|
||||
"observed_entry_count": 2,
|
||||
"selected_company_id": 1,
|
||||
"entries": [
|
||||
{
|
||||
"company_id": 1,
|
||||
"active": true,
|
||||
"controller_kind": "human",
|
||||
"current_cash": 150,
|
||||
"debt": 80,
|
||||
"credit_rating_score": 650,
|
||||
"prime_rate": 5,
|
||||
"available_track_laying_capacity": 6,
|
||||
"track_piece_counts": {
|
||||
"total": 20,
|
||||
"single": 5,
|
||||
"double": 8,
|
||||
"transition": 1,
|
||||
"electric": 3,
|
||||
"non_electric": 17
|
||||
},
|
||||
"linked_chairman_profile_id": 1,
|
||||
"book_value_per_share": 2620,
|
||||
"investor_confidence": 37,
|
||||
"management_attitude": 58,
|
||||
"takeover_cooldown_year": 1839,
|
||||
"merger_cooldown_year": 1838
|
||||
},
|
||||
{
|
||||
"company_id": 2,
|
||||
"active": true,
|
||||
"controller_kind": "ai",
|
||||
"current_cash": 90,
|
||||
"debt": 40,
|
||||
"credit_rating_score": 480,
|
||||
"prime_rate": 6,
|
||||
"available_track_laying_capacity": 2,
|
||||
"track_piece_counts": {
|
||||
"total": 8,
|
||||
"single": 2,
|
||||
"double": 2,
|
||||
"transition": 0,
|
||||
"electric": 1,
|
||||
"non_electric": 7
|
||||
},
|
||||
"linked_chairman_profile_id": 2,
|
||||
"book_value_per_share": 1400,
|
||||
"investor_confidence": 22,
|
||||
"management_attitude": 31,
|
||||
"takeover_cooldown_year": null,
|
||||
"merger_cooldown_year": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"chairman_profile_table": {
|
||||
"source_kind": "tracked-save-slice-chairman-profile-table",
|
||||
"semantic_family": "save-slice-runtime-chairman-context",
|
||||
"observed_entry_count": 2,
|
||||
"selected_chairman_profile_id": 1,
|
||||
"entries": [
|
||||
{
|
||||
"profile_id": 1,
|
||||
"name": "Chairman One",
|
||||
"active": true,
|
||||
"current_cash": 500,
|
||||
"linked_company_id": 1,
|
||||
"company_holdings": {
|
||||
"1": 1000
|
||||
},
|
||||
"holdings_value_total": 700,
|
||||
"net_worth_total": 1200,
|
||||
"purchasing_power_total": 1500
|
||||
},
|
||||
{
|
||||
"profile_id": 2,
|
||||
"name": "Chairman Two",
|
||||
"active": true,
|
||||
"current_cash": 250,
|
||||
"linked_company_id": 2,
|
||||
"company_holdings": {
|
||||
"2": 900
|
||||
},
|
||||
"holdings_value_total": 600,
|
||||
"net_worth_total": 900,
|
||||
"purchasing_power_total": 1100
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue