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:
2026-05-31 14:31:27 +02:00
co-authored by Claude Opus 4.8
parent a854b89aa0
commit d6e37c0c0e
7 changed files with 304 additions and 114 deletions
+1 -1
View File
@@ -468,7 +468,7 @@ mod tests {
context: Box::new(CityGenerationContext {
city_id,
political_archetype: PoliticalArchetype::Commission,
prosperity_baseline: 0.6,
prosperity_baseline_bps: 6_000,
surrounding_biome: SettingType::Urban,
road_entry_directions: vec![],
footprint_radius_km: 5.0,