test(@projects/@magic-civilization): ✅ p3-25 — end-to-end headless trade pipeline proof
process_trade_phase_forms_and_persists_strategic_swap: a crafted 2-player state with complementary owned-tile strategics (p0 rainforest→hardwood, p1 mountains→iron_ore, biomes guarantee neither has the other's) → process_trade_phase forms a StrategicSwap, persists it to state.trade_ledger, and fans it onto both players' traded_strategics. Proves the full chain end-to-end: owned-tile territory (step 2) → resource-category classification (step 3) → real sourcing + evaluate_trades + persistence (step 4) → which DiplomacyView.trade_deals then projects (step 5, separately tested). mc-turn green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
507a87104f
commit
7e93dcef42
1 changed files with 69 additions and 0 deletions
|
|
@ -5727,6 +5727,75 @@ mod tests {
|
|||
assert!(el.is_empty() && es.is_empty(), "no categories → no tradeables");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn process_trade_phase_forms_and_persists_strategic_swap() {
|
||||
// p3-25 end-to-end: complementary owned-tile strategics → evaluate_trades
|
||||
// forms a StrategicSwap → persisted to state.trade_ledger → fanned onto
|
||||
// both players' traded_strategics. Biomes guarantee complementarity:
|
||||
// rainforest yields only hardwood (categorized strategic) for p0; mountains
|
||||
// yield only iron_ore (categorized) for p1 — neither has the other's.
|
||||
use mc_core::grid::GridState;
|
||||
let mut state = GameState::default();
|
||||
state.turn = 5;
|
||||
state.map_seed = 0x1234_5678;
|
||||
let mut grid = GridState::new(40, 40);
|
||||
for c in 0..10 {
|
||||
if let Some(t) = grid.tile_mut(c, 0) {
|
||||
t.biome_label_id = "tropical_rainforest".into();
|
||||
t.quality = 6;
|
||||
}
|
||||
}
|
||||
for c in 0..12 {
|
||||
if let Some(t) = grid.tile_mut(c, 10) {
|
||||
t.biome_label_id = "mountains".into();
|
||||
t.quality = 6;
|
||||
}
|
||||
}
|
||||
state.grid = Some(grid);
|
||||
state
|
||||
.resource_categories
|
||||
.insert("hardwood".into(), "strategic".into());
|
||||
state
|
||||
.resource_categories
|
||||
.insert("iron_ore".into(), "strategic".into());
|
||||
|
||||
let mut p0 = crate::game_state::PlayerState::default();
|
||||
p0.player_index = 0;
|
||||
p0.cities = vec![CityState::starter()];
|
||||
p0.cities[0].owned_tiles = (0..10).map(|c| (c, 0)).collect();
|
||||
p0.city_positions = vec![(0, 0)];
|
||||
p0.strategic_axes.insert("trade_willingness".into(), 9);
|
||||
let mut p1 = crate::game_state::PlayerState::default();
|
||||
p1.player_index = 1;
|
||||
p1.cities = vec![CityState::starter()];
|
||||
p1.cities[0].owned_tiles = (0..12).map(|c| (c, 10)).collect();
|
||||
p1.city_positions = vec![(0, 10)];
|
||||
p1.strategic_axes.insert("trade_willingness".into(), 9);
|
||||
state.players = vec![p0, p1];
|
||||
|
||||
let processor = TurnProcessor::new(100);
|
||||
processor.process_trade_phase(&mut state);
|
||||
|
||||
let has_swap = state.trade_ledger.agreements.iter().any(|ag| {
|
||||
matches!(ag, mc_trade::DiplomaticAgreement::StrategicSwap(ta) if ta.partners == (0, 1))
|
||||
});
|
||||
assert!(
|
||||
has_swap,
|
||||
"strategic swap should form + persist: {:?}",
|
||||
state.trade_ledger.agreements
|
||||
);
|
||||
assert!(
|
||||
state.players[0].traded_strategics.contains("iron_ore"),
|
||||
"p0 gains iron_ore via the swap: {:?}",
|
||||
state.players[0].traded_strategics
|
||||
);
|
||||
assert!(
|
||||
state.players[1].traded_strategics.contains("hardwood"),
|
||||
"p1 gains hardwood via the swap: {:?}",
|
||||
state.players[1].traded_strategics
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn processor_is_deterministic() {
|
||||
use mc_core::grid::GridState;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue