fix(simulation): prosperity in basis points + shared log10_floor helper (#954)
Address PR #145 review. Convert prosperity from f32 to integer basis points (matching the existing prosperity_bps, D-010 integer-only), removing both float-determinism bugs by construction: - New server/src/bps.rs: log10_floor (integer order-of-magnitude) + bps_to_f32 edge helper, with boundary tests. - city_context_reader: prosperity_baseline_bps (u32, 0-10000). role base + pop bonus (400*log10_floor, cap 1200) + symmetric noise via integer modulo (fixes the always-negative bug) + clamp [1000,9500]. No floats. - CityGenerationContext.prosperity_baseline -> prosperity_baseline_bps; updated the two test context builders. Not serialized — no wire break. - district_mix population_tier now uses log10_floor (same determinism bug class as the comment claimed to avoid). - Tests in bps + assert positive noise is achievable (the case the old test hid). cargo check/clippy --all-targets -D warnings clean; 1291 lib tests pass; fmt clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -485,7 +485,7 @@ pub enum BuildingEntryClass {
|
||||
|
||||
/// Construction era of a building block (D-229).
|
||||
///
|
||||
/// Derived from `founding_age_years + prosperity_baseline + seed`.
|
||||
/// Derived from `founding_age_years + prosperity_baseline_bps + seed`.
|
||||
/// Reads primarily as **age/wear** via the condition layer (D-217/D-198);
|
||||
/// not a material-technology ladder (era = maintenance signal, not style signal).
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
|
||||
@@ -710,7 +710,7 @@ pub struct BuildingPropertyTag {
|
||||
pub era: ConstructionEra,
|
||||
/// Cause of this block's era classification.
|
||||
pub era_cause: EraCause,
|
||||
/// Frozen-amber condition snapshot from `prosperity_baseline` (D-197/D-217).
|
||||
/// Frozen-amber condition snapshot from `prosperity_baseline_bps` (D-197/D-217).
|
||||
/// The rolling condition overlay (D-198) paints over this; never mutates the tag.
|
||||
pub initial_condition: crate::atlas::tile_condition::TileCondition,
|
||||
/// Doors into / out of this building (D-231). At least one `Main` door.
|
||||
@@ -933,8 +933,9 @@ pub struct CityGenerationContext {
|
||||
/// Foreign key into atlas_city_names.id
|
||||
pub city_id: u64,
|
||||
pub political_archetype: PoliticalArchetype,
|
||||
/// Starting economic health seed (0.0–1.0). Derived per D-197.
|
||||
pub prosperity_baseline: f32,
|
||||
/// Starting economic health seed in basis points (0–10_000; 10_000 = 1.0).
|
||||
/// Derived per D-197. Integer to avoid f32 non-determinism (D-010).
|
||||
pub prosperity_baseline_bps: u32,
|
||||
pub surrounding_biome: SettingType,
|
||||
/// Compass octants (0=N, 1=NE … 7=NW) where roads enter the city footprint.
|
||||
pub road_entry_directions: Vec<u8>,
|
||||
|
||||
Reference in New Issue
Block a user