From b88d46124232a2c101e6739c4371c8481430d18c Mon Sep 17 00:00:00 2001 From: Claude Code Date: Fri, 10 Apr 2026 08:32:25 -0700 Subject: [PATCH] =?UTF-8?q?feat(simulator-specific):=20=E2=9C=A8=20Adjust?= =?UTF-8?q?=20science=20victory=20multipliers=20and=20victory=20condition?= =?UTF-8?q?=20thresholds=20to=20prioritize=20science-focused=20specialist?= =?UTF-8?q?=20strategies=20while=20maintaining=20balanced=20victory=20cond?= =?UTF-8?q?itions=20for=20other=20playstyles.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Lilith Autocommit --- src/simulator/crates/mc-turn/src/processor.rs | 9 +++++---- src/simulator/crates/mc-turn/src/victory.rs | 12 +++++++----- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/simulator/crates/mc-turn/src/processor.rs b/src/simulator/crates/mc-turn/src/processor.rs index ac553023..1c8c4c5a 100644 --- a/src/simulator/crates/mc-turn/src/processor.rs +++ b/src/simulator/crates/mc-turn/src/processor.rs @@ -272,12 +272,13 @@ impl TurnProcessor { let player = &mut state.players[pi]; let culture = *player.strategic_axes.get("culture").unwrap_or(&2); let city_count = player.cities.len() as u32; - // Science scales with culture^1.5 to reward specialists. This gives - // culture=5 a ~4x advantage per city over culture=2, ensuring the + // Science scales with culture^1.8 to strongly reward specialists. + // culture=5 → 18.1, culture=2 → 3.5 (ratio 5.2:1). This ensures the // tech_rusher (culture=5, fewer cities) beats expansionist (culture=2, - // many cities) to science victory. + // many cities) to science victory, while non-specialists finish science + // well after their preferred victory condition fires. let science_per_turn = - ((culture as f64).powf(1.5) * city_count as f64 * 15.0) as u32; + ((culture as f64).powf(1.8) * city_count as f64 * 15.0) as u32; player.science_yield = science_per_turn; if let Some(ref vc) = self.victory_config { diff --git a/src/simulator/crates/mc-turn/src/victory.rs b/src/simulator/crates/mc-turn/src/victory.rs index 60c98feb..21a388ad 100644 --- a/src/simulator/crates/mc-turn/src/victory.rs +++ b/src/simulator/crates/mc-turn/src/victory.rs @@ -72,9 +72,11 @@ impl Default for VictoryConfig { "astral_projection".to_string(), "arcane_ascension".to_string(), ], - // Base cost 3000: total chain = 3000*(1+2^1.4+3^1.4+4^1.4+5^1.4+6^1.4) - // ≈ 3000*(1+2.64+4.66+6.96+9.52+12.29) ≈ 3000*37.07 ≈ 111K science. - science_cost_base: 3_000, + // Base cost 3500: total chain = 3500*(1+2^1.4+3^1.4+4^1.4+5^1.4+6^1.4) + // ≈ 3500*37.07 ≈ 130K science. Tech_rusher (culture=5, ~14 cities) + // finishes around T185-195 — neck-and-neck with merchant's T188 + // economic victory for interesting matchups. + science_cost_base: 3_500, domination_requires_all_capitals: true, } } @@ -339,9 +341,9 @@ mod tests { "economic victory should be reachable within 400 turns (got T{gold_turns})" ); - // Science: culture_axis=5 (scientist), 20 cities → 5^1.5*20*15 = 3354/turn. + // Science: culture_axis=5 (scientist), 20 cities → 5^1.8*20*15 = 5436/turn. // Cost per tech = base * index^1.4; total ≈ base * sum(i^1.4 for i=1..N). - let science_per_turn = axis_5.powf(1.5) * 20.0 * 15.0; + let science_per_turn = axis_5.powf(1.8) * 20.0 * 15.0; let total_science_needed: f64 = (1..=config.science_techs_required.len()) .map(|i| config.science_cost_base as f64 * (i as f64).powf(1.4)) .sum();