feat(@projects/@magic-civilization): ✨ expose drive_ai_slot for benchmarking
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
9e7566a628
commit
db30279c60
3 changed files with 29 additions and 2 deletions
|
|
@ -976,7 +976,12 @@ fn translate_processor_events(events: &[mc_replay::TurnEvent]) -> Vec<Event> {
|
|||
/// counted but DO NOT abort the rest of the turn — a single
|
||||
/// unknown unit or illegal move must not collapse the entire AI
|
||||
/// side (matches the GDScript dispatch behaviour).
|
||||
fn drive_ai_slot(state: &mut GameState, ai_slot: u8) -> u32 {
|
||||
/// Drive one AI slot for a turn: project vision, run the slot's controller
|
||||
/// (`run_ai_turn` by default), and apply the chosen actions. Public so headless
|
||||
/// multi-clan benches (`dominion_bench`) can drive the *real* AI through the
|
||||
/// same path the interactive game uses (`apply_end_turn`), instead of relying
|
||||
/// on `mc-turn`'s inline fallback movement. Returns the action count.
|
||||
pub fn drive_ai_slot(state: &mut GameState, ai_slot: u8) -> u32 {
|
||||
let pi: usize = ai_slot as usize;
|
||||
if pi >= state.players.len() {
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ mc-city = { path = "../mc-city" }
|
|||
mc-culture = { path = "../mc-culture" }
|
||||
mc-economy = { path = "../mc-economy" }
|
||||
mc-ai = { path = "../mc-ai" }
|
||||
mc-player-api = { path = "../mc-player-api" }
|
||||
serde.workspace = true
|
||||
serde_json.workspace = true
|
||||
rayon = "1"
|
||||
|
|
|
|||
|
|
@ -355,7 +355,20 @@ fn run_scenario_with_profiles(num_players: usize, all_profiles: &[ProfileJson])
|
|||
..Default::default() }],
|
||||
unit_upkeep: vec![],
|
||||
strategic_axes: make_axes(profile),
|
||||
scoring_weights: ScoringWeights::default(),
|
||||
// Real per-personality scoring weights (military/expansion/etc.),
|
||||
// the same source the live game uses (`ScoringWeights::from_personality`).
|
||||
// Without these the AI scores every action ~0 and `drive_ai_slot`
|
||||
// produces no moves — the inert `default()` was why the bench showed
|
||||
// zero PvP. Falls back to default if the personality file is absent.
|
||||
scoring_weights: ScoringWeights::from_personality(
|
||||
&profile.id,
|
||||
&Path::new(env!("CARGO_MANIFEST_DIR"))
|
||||
.ancestors()
|
||||
.nth(2)
|
||||
.expect("workspace root")
|
||||
.join("public/resources/ai/personalities"),
|
||||
)
|
||||
.unwrap_or_default(),
|
||||
expansion_points: 0,
|
||||
city_buildings: vec![vec![]],
|
||||
city_improvements: Default::default(),
|
||||
|
|
@ -413,6 +426,14 @@ fn run_scenario_with_profiles(num_players: usize, all_profiles: &[ProfileJson])
|
|||
let mut victory_turn: Option<u32> = None;
|
||||
|
||||
for turn_num in 1..=TOTAL_TURNS {
|
||||
// Drive every slot's REAL AI (`run_ai_turn` via the controller registry)
|
||||
// before the turn resolves — the same `drive_ai_slot` the interactive
|
||||
// game runs inside `apply_end_turn`. Without this the bench relied on
|
||||
// `mc-turn`'s inline `nearest_lair` fallback (PvE only → zero PvP). All
|
||||
// slots are AI here (no human), so we drive all of them.
|
||||
for slot in 0..state.players.len() as u8 {
|
||||
mc_player_api::dispatch::drive_ai_slot(&mut state, slot);
|
||||
}
|
||||
let result = processor.step(&mut state);
|
||||
|
||||
// Track unit production per player.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue