test(@projects/@magic-civilization): p3-18 P6 — capstone: army fords water then attacks enemy on the far landmass

teched_army_fords_water_then_attacks_enemy_on_far_landmass: end-to-end proof of
the conquest payoff that motivated p3-18. Over an ocean-wall map, a player-0 army
with ocean_navigation embark fords the ocean column to landmass B (process_move_requests),
then strikes a player-1 unit waiting there (queued AttackRequest → process_pvp_combat):
a cross-water battle resolves and the enemy takes damage. Embark turns an
otherwise-unreachable rival on another landmass into an attackable one.

Deterministic, cargo-verifiable; complements P6-core (the ford proof). The full
headless 1v1-to-game_over demo is the only remaining (confirmatory) P6 item.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Natalie 2026-06-25 07:26:11 -04:00
parent 1f3f535e10
commit 22d0379a2c

View file

@ -5285,6 +5285,81 @@ mod move_request_tests {
);
}
#[test]
fn teched_army_fords_water_then_attacks_enemy_on_far_landmass() {
// The conquest payoff end-to-end: landmass A (col 0) | ocean wall (col 1)
// | landmass B (cols 2-3). A teched army on A fords the ocean to B and
// strikes an enemy waiting there — embark turns an unreachable rival into
// an attackable one.
let mut grid = GridState::new(4, 3);
for r in 0..3 {
for c in 0..4 {
let idx = grid.idx(c, r);
grid.tiles[idx].biome_label_id =
if c == 1 { "ocean" } else { "plains" }.to_string();
}
}
let mut state = GameState::default();
state.grid = Some(grid);
state
.units_catalog
.load_json_str(
r#"[{"id":"warrior","movement":10,"domain":"land","hp":60,"attack":20,"defense":2}]"#,
)
.expect("catalog loads");
state.players.push(PlayerState {
player_index: 0,
embark_level: mc_core::EmbarkLevel::Ocean,
units: vec![MapUnit {
id: 1, col: 0, row: 0, unit_id: "warrior".into(),
hp: 60, max_hp: 60, attack: 20, defense: 2, ..MapUnit::default()
}
.with_moves(10)],
..PlayerState::default()
});
state.players.push(PlayerState {
player_index: 1,
units: vec![MapUnit {
id: 2, col: 3, row: 0, unit_id: "warrior".into(),
hp: 60, max_hp: 60, attack: 20, defense: 2, ..MapUnit::default()
}
.with_moves(0)],
..PlayerState::default()
});
// 1) FORD: army (0,0) -> (2,0), crossing the ocean column to landmass B,
// landing adjacent to the enemy at (3,0).
state.pending_move_requests.push(move_req(0, (2, 0)));
process_move_requests(&mut state);
assert_eq!(
(state.players[0].units[0].col, state.players[0].units[0].row),
(2, 0),
"teched army forded the ocean to the far landmass"
);
// 2) ATTACK: strike the enemy now within reach across the water.
let enemy_hp_before = state.players[1].units[0].hp;
state.pending_pvp_attacks.push(crate::game_state::AttackRequest {
attacker_player: 0,
attacker_unit: 0,
defender_player: 1,
defender_unit: 0,
});
let processor = TurnProcessor::new(500);
let mut result = TurnResult::default();
processor.process_pvp_combat(&mut state, &mut result);
assert!(result.pvp_battles >= 1, "a cross-water battle resolved");
let enemy_dead = !state.players[1].units.iter().any(|u| u.id == 2);
let enemy_hurt = enemy_dead
|| state.players[1].units.iter().find(|u| u.id == 2).map(|u| u.hp).unwrap_or(0)
< enemy_hp_before;
assert!(
enemy_hurt,
"the army that forded the ocean damaged the enemy on the far landmass"
);
}
#[test]
fn zero_budget_rejects() {
let mut state = build_state_with_unit(7, (0, 0), 0, |_, _| "plains");