refactor(p2-65): 🏗️ Phase 4 C1 — retarget consumers off mc_turn::GameState onto mc_state

Sweep all 44 real code references + 14 doc-comment references from
mc_turn::game_state::/mc_turn::GameState to mc_state::game_state:: across
the external consumer surface (mc-player-api src+tests, mc-sim, api-gdext,
mc-save tests, mc-vision, mc-turn integration tests). Add `mc-state` path
dep to the 5 consumer crates (api-gdext, mc-player-api, mc-sim, mc-save,
mc-vision). The mc-turn/lib.rs:63 re-export + game_state.rs shim stay in
place for this green boundary; the pub(crate) alias + shim deletion land
in C2.

mc-core doc-comment refs (derived_stats/lair/tactical_types) retargeted
too — they are real gate violations for the bullet-6 grep, not legit use;
no code dep on mc_turn (all prose), so no dev-dep needed.

Gate (apricot, shared target): cargo test --workspace --no-run exit 0;
serde_roundtrip 6/6; full_turn_golden 3/3; mc-turn lib 234/234 (1 ignored,
pre-existing five_players_overflow); mc-ai 268/268; mc-player-api 126/126;
mc-state 12/12.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
autocommit 2026-06-04 19:36:07 -07:00
parent 180c521977
commit 1917c3db53
36 changed files with 68 additions and 58 deletions

View file

@ -1609,6 +1609,7 @@ dependencies = [
"mc-replay",
"mc-save",
"mc-score",
"mc-state",
"mc-tech",
"mc-trade",
"mc-turn",
@ -1910,6 +1911,7 @@ dependencies = [
"mc-items",
"mc-replay",
"mc-score",
"mc-state",
"mc-tech",
"mc-trade",
"mc-turn",
@ -1937,6 +1939,7 @@ name = "mc-save"
version = "0.1.0"
dependencies = [
"mc-core",
"mc-state",
"mc-turn",
"mc-vision",
"serde",
@ -1971,6 +1974,7 @@ dependencies = [
"mc-flora",
"mc-mapgen",
"mc-observation",
"mc-state",
"mc-turn",
"rayon",
"serde",
@ -2062,6 +2066,7 @@ dependencies = [
"mc-city",
"mc-core",
"mc-replay",
"mc-state",
"mc-turn",
"serde",
"serde_json",

View file

@ -22,6 +22,7 @@ mc-combat = { path = "../crates/mc-combat" }
mc-items = { path = "../crates/mc-items" }
mc-trade = { path = "../crates/mc-trade" }
mc-tech = { path = "../crates/mc-tech" }
mc-state = { path = "../crates/mc-state" }
mc-turn = { path = "../crates/mc-turn" }
mc-units = { path = "../crates/mc-units" }
mc-player-api = { path = "../crates/mc-player-api" }

View file

@ -31,7 +31,7 @@ use mc_ai::tactical::{
TacticalTile,
};
use mc_player_api::project_tactical_with_vision;
use mc_turn::GameState;
use mc_state::game_state::GameState;
// ── GdMcTreeController ───────────────────────────────────────────────────────

View file

@ -12,7 +12,7 @@ use mc_core::building_action::{
BuildingActionAvailability, BuildingActionKind, BuildingCapability,
legal_actions_for_building,
};
use mc_turn::game_state::BuildingActionRequest;
use mc_state::game_state::BuildingActionRequest;
#[derive(GodotClass)]
#[class(base=RefCounted)]

View file

@ -2854,7 +2854,7 @@ impl GdItemSystem {
// ── GdGameState ─────────────────────────────────────────────────────────
//
// Wraps mc_turn::GameState — the full headless game state (players, grid,
// Wraps mc_state::game_state::GameState — the full headless game state (players, grid,
// turn counter) — for consumption by Godot. This is the bridge that lets
// the Godot engine use the Rust turn processor as the authoritative
// simulation runtime, rather than running a parallel GDScript turn loop.
@ -2870,13 +2870,13 @@ impl GdItemSystem {
/// Headless game state bridge.
///
/// Owns an `mc_turn::GameState`. Godot scripts create one of these, populate
/// Owns an `mc_state::game_state::GameState`. Godot scripts create one of these, populate
/// it, hand it to a `GdTurnProcessor`, and read the updated state back after
/// each `step()` call.
#[derive(GodotClass)]
#[class(base=RefCounted)]
pub struct GdGameState {
inner: mc_turn::GameState,
inner: mc_state::game_state::GameState,
/// p2-72a Stage 3 — Wall-2 side-table of presentation-only player
/// metadata (display name, race id, gender preset, banner colour,
/// is_human). Aligned with `inner.players` by `slot`. Populated by
@ -2889,7 +2889,7 @@ pub struct GdGameState {
/// p2-72a Stage 3 — canonical on-disk save envelope. Rust now owns
/// serialisation (the GDScript `SaveManager` becomes a thin wrapper around
/// `GdGameState::serialize_full` / `load_from_json`). Holds both the
/// simulation state (`mc_turn::GameState`) and the Wall-2 presentation
/// simulation state (`mc_state::game_state::GameState`) and the Wall-2 presentation
/// side-table.
///
/// `version` starts at 1; bump on any future breaking shape change.
@ -2898,7 +2898,7 @@ pub struct SaveEnvelope {
/// Save-format version. Starts at 1. Bumped on breaking shape changes.
pub save_format_version: u32,
/// Authoritative simulation state.
pub sim: mc_turn::GameState,
pub sim: mc_state::game_state::GameState,
/// Presentation-only per-player metadata. Aligned with `sim.players` by slot.
pub presentation: Vec<mc_core::PresentationPlayer>,
}
@ -2977,7 +2977,7 @@ impl IRefCounted for GdGameState {
// `#[serde(default = "default_threshold_mult")]` attribute only
// applies on deserialise; `Default` derives go through the field
// type's own Default.
let mut inner = mc_turn::GameState::default();
let mut inner = mc_state::game_state::GameState::default();
inner.ai_difficulty_threshold_mult = 1.0;
Self {
inner,
@ -2989,7 +2989,7 @@ impl IRefCounted for GdGameState {
#[godot_api]
impl GdGameState {
/// Serialise the inner `mc_turn::game_state::GameState` to JSON.
/// Serialise the inner `mc_state::game_state::GameState` to JSON.
/// Pair with `GdPlayerApi::load_state_json` to hand the bootstrapped
/// world over to the Claude Player API. Returns `"{}"` only on a
/// serde failure (logged via `godot_error!`).
@ -3008,7 +3008,7 @@ impl GdGameState {
/// Used by tests that need to round-trip a hand-built state through
/// disk or the wire. Returns `false` on parse failure.
///
/// **Boot-only**. The serialised payload covers only `mc_turn::GameState`
/// **Boot-only**. The serialised payload covers only `mc_state::game_state::GameState`
/// — `#[serde(skip)]` fields (`units_catalog`, `improvement_registry`,
/// `ai_unit_catalog`, `ai_building_catalog`) are wiped on load and the
/// harness must rehydrate them before the next turn. For mid-game
@ -3016,7 +3016,7 @@ impl GdGameState {
/// boot-loaded catalogs across the round-trip.
#[func]
fn from_json(&mut self, json: GString) -> bool {
match serde_json::from_str::<mc_turn::game_state::GameState>(json.to_string().as_str()) {
match serde_json::from_str::<mc_state::game_state::GameState>(json.to_string().as_str()) {
Ok(state) => {
self.inner = state;
true
@ -3046,7 +3046,7 @@ impl GdGameState {
///
/// Output shape:
/// ```json
/// { "save_format_version": 1, "sim": { ... mc_turn::GameState ... },
/// { "save_format_version": 1, "sim": { ... mc_state::game_state::GameState ... },
/// "presentation": [ { "slot": 0, "player_name": "Thorin", ... }, ... ] }
/// ```
///
@ -8208,7 +8208,7 @@ impl GdVision {
#[func]
pub fn refresh(&mut self, state_json: GString) -> bool {
let raw = state_json.to_string();
let Ok(state) = serde_json::from_str::<mc_turn::game_state::GameState>(&raw) else {
let Ok(state) = serde_json::from_str::<mc_state::game_state::GameState>(&raw) else {
godot_error!("GdVision::refresh: state JSON failed to parse");
return false;
};
@ -8227,7 +8227,7 @@ impl GdVision {
catalog_json: GString,
) -> bool {
let raw = state_json.to_string();
let Ok(state) = serde_json::from_str::<mc_turn::game_state::GameState>(&raw) else {
let Ok(state) = serde_json::from_str::<mc_state::game_state::GameState>(&raw) else {
godot_error!("GdVision::refresh_with_catalog: state JSON failed");
return false;
};

View file

@ -28,7 +28,7 @@ use mc_player_api::{
apply_action, project_view, suggest_actions, ActionError, PlayerAction, PlayerView,
PlayerId,
};
use mc_turn::game_state::GameState;
use mc_state::game_state::GameState;
/// Godot-visible facade over the player API surface. Holds one
/// `GameState` internally so calls don't have to round-trip it on

View file

@ -13,7 +13,7 @@ use magic_civ_physics_gdext::capture::{
};
use mc_combat::resolver::{CombatOutcome, PostureResolution};
use mc_turn::capture::CapturePosture;
use mc_turn::game_state::MapUnit;
use mc_state::game_state::MapUnit;
use mc_turn::ransom::RansomQueue;
/// (1) `CombatOutcome::Captured` and friends round-trip through the bridge's

View file

@ -8,7 +8,7 @@
use magic_civ_physics_gdext::{validate_presentation_controllers, SaveEnvelope};
use mc_core::PresentationPlayer;
use mc_turn::game_state::GameState;
use mc_state::game_state::GameState;
#[test]
fn empty_envelope_round_trips() {

View file

@ -1,7 +1,7 @@
//! Cross-turn tactical memory (p1-29h).
//!
//! [`TacticalState`](super::state::TacticalState) is a per-turn snapshot
//! projected fresh from `mc_turn::GameState` each turn — it has no field that
//! projected fresh from `mc_state::game_state::GameState` each turn — it has no field that
//! survives the turn boundary, so the army-level *commitment hysteresis* and
//! *target-lock* that turn a city capture into an elimination cannot live on
//! it. This module owns the persistent channel.

View file

@ -46,7 +46,7 @@ impl Default for InequalityStat {
/// Derived realm-level statistics recomputed at the end of every turn.
///
/// Stored on `mc_turn::game_state::PlayerState` behind `#[serde(default)]`
/// Stored on `mc_state::game_state::PlayerState` behind `#[serde(default)]`
/// for save-migration safety — pre-existing saves load with all fields at
/// their zero defaults, which is correct (a just-loaded game has not yet run
/// the recompute pass for turn N).

View file

@ -144,7 +144,7 @@ impl SiegePressure {
/// Persistent state for a single besieged lair tile.
///
/// Lives on `mc_turn::GameState::siege_pressure` keyed by `(col, row)`
/// Lives on `mc_state::game_state::GameState::siege_pressure` keyed by `(col, row)`
/// so the entry round-trips through the save format.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SiegeState {
@ -242,7 +242,7 @@ pub enum RaidOutcome {
/// fauna pursue for a short window, increasing aggression / encounter
/// rate for stacks crossing the territory zone.
///
/// Lives on `mc_turn::GameState::raid_aftermath` keyed by `(col, row)`
/// Lives on `mc_state::game_state::GameState::raid_aftermath` keyed by `(col, row)`
/// of the lair tile, mirroring `siege_pressure`. The bridge ticks
/// `pursuing_until_turn` against the current turn counter and drops
/// expired entries.

View file

@ -1,7 +1,7 @@
//! Tactical AI data shapes carried on the simulation state (p2-65 Phase 0c).
//!
//! These four types were authored in `mc-ai::tactical` but are pure data
//! (no AI logic): `mc_turn::GameState`/`PlayerState` carry them as fields, so
//! (no AI logic): `mc_state::game_state::GameState`/`PlayerState` carry them as fields, so
//! they must live in a crate that the future `mc-state` crate can depend on
//! WITHOUT pulling in `mc-ai`. `mc-core` is that crate (same precedent as
//! `ScoringWeights` and `CombatBalance`, both relocated here earlier).

View file

@ -260,7 +260,7 @@ pub type PersonalityPriorsMirror = mc_ai::policy::PersonalityPriors;
/// the GPU MCTS service plumbing.
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct SearchActionViaAbstractJob {
/// Root rollout state — projected from `mc_turn::GameState` via
/// Root rollout state — projected from `mc_state::game_state::GameState` via
/// `mc_turn::abstract_projection::to_abstract_rollout_state`.
pub abstract_state: AbstractJobState,
/// Per-player priors aligned with `abstract_state.players`. Slot order

View file

@ -8,6 +8,7 @@ mc-core = { path = "../mc-core" }
mc-city = { path = "../mc-city" }
mc-tech = { path = "../mc-tech" }
mc-trade = { path = "../mc-trade" }
mc-state = { path = "../mc-state" }
mc-turn = { path = "../mc-turn" }
mc-combat = { path = "../mc-combat" }
mc-items = { path = "../mc-items" }

View file

@ -35,7 +35,7 @@ use mc_replay::{ClanId, TileCoord, TurnEvent};
use mc_trade::relation::{pair_key, Relation};
use mc_trade::{CourierMapView, CourierRoute};
use mc_turn::courier_resolver::{dispatch_courier, GameStateMapView};
use mc_turn::game_state::GameState;
use mc_state::game_state::GameState;
use crate::PlayerId;
@ -536,7 +536,7 @@ pub fn sender_has_war_mode(state: &GameState, sender: PlayerId, target: PlayerId
mod tests {
use super::*;
use mc_core::grid::GridState;
use mc_turn::game_state::PlayerState;
use mc_state::game_state::PlayerState;
fn make_state(caps: &[(i32, i32)]) -> GameState {
let mut state = GameState::default();

View file

@ -33,7 +33,7 @@
use mc_core::action::ActionKind;
use mc_core::civic::{AxisChoice, CivicAxis as CoreCivicAxis};
use mc_turn::action_handlers;
use mc_turn::game_state::{AttackRequest, GameState};
use mc_state::game_state::{AttackRequest, GameState};
use crate::action::{CivicAxis as WireCivicAxis, PlayerAction, RansomResponse};
use crate::error::ActionError;
@ -2077,7 +2077,7 @@ fn apply_offer_shared_map(
mod tests {
use super::*;
use crate::action::PlayerAction;
use mc_turn::game_state::{MapUnit, PlayerState};
use mc_state::game_state::{MapUnit, PlayerState};
fn make_state_with_units(units: Vec<(u8, u32, i32, i32)>) -> GameState {
// Vec<(owner_player_idx, unit_id, col, row)>. Creates as many

View file

@ -1,4 +1,4 @@
//! Fog-aware view projection — reads a [`mc_turn::game_state::GameState`]
//! Fog-aware view projection — reads a [`mc_state::game_state::GameState`]
//! and assembles a [`crate::view::PlayerView`] from the perspective of one
//! player slot.
//!
@ -42,7 +42,7 @@
//! Claude-API path runs against the default. The matching spec-widening
//! note lives in the `mc-vision` crate-level docs.
use mc_turn::game_state::GameState;
use mc_state::game_state::GameState;
use mc_vision::{compute_vision, PlayerVision, VisionCatalog};
use crate::view::{
@ -145,7 +145,7 @@ pub fn project_view_with_vision(
}
}
fn project_resources(player: &mc_turn::game_state::PlayerState) -> ResourceView {
fn project_resources(player: &mc_state::game_state::PlayerState) -> ResourceView {
let mut stockpile = std::collections::BTreeMap::new();
for (k, v) in &player.strategic_ledger {
stockpile.insert(k.clone(), *v as i32);
@ -164,7 +164,7 @@ fn project_resources(player: &mc_turn::game_state::PlayerState) -> ResourceView
}
}
fn project_research(player: &mc_turn::game_state::PlayerState) -> ResearchView {
fn project_research(player: &mc_state::game_state::PlayerState) -> ResearchView {
let (current_tech, tech_progress, researched) = if let Some(pt) = &player.player_tech {
let researched: Vec<String> = pt.researched_techs().iter().cloned().collect();
let current = pt.current_research().map(std::string::ToString::to_string);
@ -187,7 +187,7 @@ fn project_research(player: &mc_turn::game_state::PlayerState) -> ResearchView {
}
}
fn project_culture(player: &mc_turn::game_state::PlayerState) -> CultureView {
fn project_culture(player: &mc_state::game_state::PlayerState) -> CultureView {
let current = if player.researching_tradition.is_empty() {
None
} else {
@ -395,7 +395,7 @@ fn project_units(
fn project_unit_legal_actions(
state: &GameState,
player_idx: usize,
unit: &mc_turn::game_state::MapUnit,
unit: &mc_state::game_state::MapUnit,
) -> Vec<LegalActionEntry> {
let uid = unit.id.to_string();
let mut entries: Vec<LegalActionEntry> = Vec::new();
@ -779,7 +779,7 @@ fn score_weights() -> &'static mc_score::ScoreWeights {
})
}
fn project_score(state: &GameState, player: &mc_turn::game_state::PlayerState) -> ScoreView {
fn project_score(state: &GameState, player: &mc_state::game_state::PlayerState) -> ScoreView {
let _ = state;
// Per-player composite-score inputs. Field sourcing mirrors the canonical
@ -1116,7 +1116,7 @@ fn project_tactical_map(state: &GameState, vision: Option<&PlayerVision>) -> Tac
fn project_tactical_player(
state: &GameState,
player: &mc_turn::game_state::PlayerState,
player: &mc_state::game_state::PlayerState,
n_players: usize,
bound_player: PlayerId,
vision: Option<&PlayerVision>,
@ -1327,7 +1327,7 @@ fn project_tactical_relations(state: &GameState, player_idx: u8, n_players: usiz
#[cfg(test)]
mod tests {
use super::*;
use mc_turn::game_state::{MapUnit, PlayerState};
use mc_state::game_state::{MapUnit, PlayerState};
fn make_state(num_players: u8, own_gold: i32, own_units: Vec<(u32, i32, i32)>) -> GameState {
let mut state = GameState::default();

View file

@ -7,7 +7,7 @@
//! (no vision) is preserved as the omniscient debug/test path.
use mc_player_api::{project_tactical, project_tactical_with_vision};
use mc_turn::game_state::{GameState, MapUnit, PlayerState};
use mc_state::game_state::{GameState, MapUnit, PlayerState};
use mc_vision::{compute_vision, VisionCatalog};
fn flat_grid(width: i32, height: i32, biome: &str) -> mc_core::grid::GridState {

View file

@ -23,7 +23,7 @@
use mc_ai::evaluator::ScoringWeights;
use mc_ai::tactical::state::{TacticalBuildingSpec, TacticalUnitSpec};
use mc_turn::game_state::{GameState, MapUnit, PlayerState};
use mc_state::game_state::{GameState, MapUnit, PlayerState};
use mc_units::{CombatStats, UnitStats, UnitsCatalog};
/// Mirror of `GdGameState::add_player_militarist` (api-gdext/src/lib.rs).

View file

@ -1841,7 +1841,7 @@ const MCTS_ROLLOUT_HORIZON: u32 = 5;
/// until the picked action set converges (no new picks) or
/// MAX_ACTIONS_PER_TURN is hit. Then return.
fn run_claude_mcts_turn(
state: &mut mc_turn::game_state::GameState,
state: &mut mc_state::game_state::GameState,
out_signatures: &mut Vec<(String, Vec<Event>)>,
weights: &mc_ai::evaluator::ScoringWeights,
seed: u64,

View file

@ -14,7 +14,7 @@
use mc_player_api::action::PlayerAction;
use mc_player_api::projection::project_view;
use mc_player_api::{apply_action, PlayerView};
use mc_turn::game_state::{GameState, MapUnit, PlayerState};
use mc_state::game_state::{GameState, MapUnit, PlayerState};
mod common;
use common::build_3_player_state_like_harness;

View file

@ -40,7 +40,7 @@ use mc_ai::evaluator::ScoringWeights;
use mc_player_api::action::PlayerAction;
use mc_player_api::apply_action;
use mc_trade::relation::{Relation, RelationState};
use mc_turn::game_state::{GameState, MapUnit, PlayerState};
use mc_state::game_state::{GameState, MapUnit, PlayerState};
mod common;
use common::{build_runtime_units_catalog, build_building_catalog, build_unit_catalog};

View file

@ -11,7 +11,7 @@ use mc_player_api::action::PlayerAction;
use mc_player_api::dispatch::apply_action;
use mc_player_api::error::ActionError;
use mc_replay::TurnEvent;
use mc_turn::game_state::{GameState, PlayerState};
use mc_state::game_state::{GameState, PlayerState};
fn fresh_state(players: usize) -> GameState {
let mut state = GameState::default();
@ -181,7 +181,7 @@ fn beacon_tap_pass_runs_end_of_turn() {
};
state.tile_improvements.insert((7_u16, 5_u16), beacon);
// Add a hostile unit on the beacon tile (player 1).
let mut u = mc_turn::game_state::MapUnit::default();
let mut u = mc_state::game_state::MapUnit::default();
u.col = 7;
u.row = 5;
state.players[1].units.push(u);

View file

@ -8,7 +8,7 @@
//! unexplored tiles, and resources on unseen tiles do not leak.
use mc_player_api::projection::{project_view, project_view_with_vision};
use mc_turn::game_state::{GameState, MapUnit, PlayerState};
use mc_state::game_state::{GameState, MapUnit, PlayerState};
use mc_vision::{compute_vision, VisionCatalog};
fn flat_grid(width: i32, height: i32, biome: &str) -> mc_core::grid::GridState {

View file

@ -32,7 +32,7 @@ use mc_player_api::action::PlayerAction;
use mc_player_api::apply_action;
use mc_player_api::projection::project_tactical;
use mc_player_api::wire::Event;
use mc_turn::game_state::GameState;
use mc_state::game_state::GameState;
mod common;
use common::build_3_player_state_like_harness;

View file

@ -14,6 +14,7 @@ thiserror = "1"
# only a dev-dependency.
[dev-dependencies]
mc-vision = { path = "../mc-vision" }
mc-state = { path = "../mc-state" }
mc-turn = { path = "../mc-turn" }
[lints]

View file

@ -65,7 +65,7 @@ fn save_load_round_trip() {
#[test]
fn vision_state_round_trips_byte_equal() {
use mc_turn::game_state::{GameState, MapUnit, PlayerState};
use mc_state::game_state::{GameState, MapUnit, PlayerState};
use mc_vision::{compute_vision, VisionCatalog};
// Build a small state with one scout — vision will contain a non-empty

View file

@ -17,6 +17,7 @@ mc-flora = { path = "../mc-flora" }
mc-compute = { path = "../mc-compute", optional = true, features = ["gpu"] }
mc-mapgen = { path = "../mc-mapgen" }
mc-observation = { path = "../mc-observation" }
mc-state = { path = "../mc-state" }
mc-turn = { path = "../mc-turn" }
mc-city = { path = "../mc-city" }
mc-culture = { path = "../mc-culture" }

View file

@ -57,7 +57,7 @@ use mc_ecology::tile::{apply_damage, TileEcoState};
use mc_mapgen::events::{derive_events as derive_geological_events, GeologicalThresholds};
use mc_observation::apply_fog;
use mc_turn::chronicle::{Chronicle, ChronicleEntry};
use mc_turn::GameState;
use mc_state::game_state::GameState;
/// Run all three world-event derivation passes for this turn and apply their
/// side-effects to `state` and `eco_map`.
@ -268,7 +268,7 @@ mod tests {
}
fn make_state_with_grid() -> GameState {
let mut state = mc_turn::GameState::default();
let mut state = mc_state::game_state::GameState::default();
state.grid = Some(seeded_grid());
state.turn = 1;
state
@ -431,7 +431,7 @@ mod tests {
#[test]
fn p3_13_event_dispatch_noop_without_grid() {
let mut state = mc_turn::GameState::default();
let mut state = mc_state::game_state::GameState::default();
// state.grid is None by default — headless unit-test path.
let mut eco_map: HashMap<(u16, u16), TileEcoState> = HashMap::new();
let mut chronicle = Chronicle::new();

View file

@ -29,7 +29,7 @@ use mc_ai::policy::{ActionKind, PersonalityPriors};
use mc_ai::rollout::GameRolloutState;
use mc_city::CityState;
use mc_turn::abstract_projection::to_abstract_rollout_state;
use mc_turn::game_state::{GameState, MapUnit, PlayerState};
use mc_state::game_state::{GameState, MapUnit, PlayerState};
/// Build a synthetic 4-player `GameState` with enough material that the
/// projection produces a non-trivial POD: every player has a city, units

View file

@ -16,7 +16,7 @@ use mc_city::CityState;
use mc_core::formation::{Formation, FormationCommand, FormationShape};
use mc_trade::relation::{Relation, RelationState};
use mc_turn::abstract_projection::to_abstract_rollout_state;
use mc_turn::game_state::{GameState, MapUnit, PlayerState, TechState};
use mc_state::game_state::{GameState, MapUnit, PlayerState, TechState};
// ── Test fixture helpers ────────────────────────────────────────────────────

View file

@ -6,7 +6,7 @@
use mc_combat::resolver::PostureResolution;
use mc_turn::capture::{resolve_posture, CapturePosture, PromptUnresolved};
use mc_turn::game_state::{MapUnit, PlayerState};
use mc_state::game_state::{MapUnit, PlayerState};
fn unit_with_override(o: Option<CapturePosture>) -> MapUnit {
MapUnit { posture_override: o, ..MapUnit::default() }

View file

@ -107,7 +107,7 @@ use mc_turn::combat_event::{
UnitRansomAcceptedEvent, UnitRansomExpiredEvent,
};
use mc_turn::capture_drain::DrainCaptureEvents;
use mc_turn::game_state::PendingCaptureEvents;
use mc_state::game_state::PendingCaptureEvents;
use mc_turn::combat_event::TurnResult;
#[test]
@ -211,7 +211,7 @@ fn combat_balance_json_load_threads_nondefault_duration_into_game_state() {
// `GdGameState::set_combat_balance_json` does at game-boot time: read the
// file, parse via `load_combat_balance`, write to `state.combat_balance`.
use mc_turn::combat_balance::load_combat_balance;
use mc_turn::game_state::GameState;
use mc_state::game_state::GameState;
let json = r#"{
"default_ransom_multiplier": 2.0,
"ransom_offer_duration_turns": 5,

View file

@ -5,6 +5,7 @@ edition = "2021"
[dependencies]
mc-core = { path = "../mc-core" }
mc-state = { path = "../mc-state" }
mc-turn = { path = "../mc-turn" }
mc-replay = { path = "../mc-replay" }
serde.workspace = true

View file

@ -25,7 +25,7 @@
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use mc_core::grid::GridState;
use mc_turn::game_state::{GameState, MapUnit, PlayerState};
use mc_state::game_state::{GameState, MapUnit, PlayerState};
use mc_vision::{compute_vision, VisionCatalog};
/// Build a flat `width × height` grassland grid — replicates the

View file

@ -1,6 +1,6 @@
//! `mc-vision` — per-player tile visibility producer.
//!
//! Builds [`VisionState`] from a [`mc_turn::game_state::GameState`] snapshot.
//! Builds [`VisionState`] from a [`mc_state::game_state::GameState`] snapshot.
//! Drives fog-of-war for the Claude Player API projector and (eventually)
//! the headless AI. Deterministic — no RNG, BTree-ordered, byte-stable
//! across runs.
@ -90,7 +90,7 @@ use mc_core::grid::biome_registry::BiomeTag;
use mc_core::grid::{GridState, TileState};
use mc_replay::event::TurnEvent;
use mc_replay::ids::{CityName, ClanId, TileCoord, UnitKind};
use mc_turn::game_state::{GameState, PlayerState};
use mc_state::game_state::{GameState, PlayerState};
use serde::{Deserialize, Serialize};
/// Default decay-short threshold (turns from snapshot to `Fresh → Faded`).
@ -1144,7 +1144,7 @@ pub fn diff_for_events(
mod tests {
use super::*;
use mc_core::grid::GridState;
use mc_turn::game_state::{MapUnit, PlayerState};
use mc_state::game_state::{MapUnit, PlayerState};
/// Build a flat `width × height` grid where every tile has the
/// given biome id. `GridState::default` lacks public constructors