From 1bd1a29d9a16ddaf63f46217e38deafa522d1700 Mon Sep 17 00:00:00 2001 From: Natalie Date: Wed, 24 Jun 2026 20:24:02 -0400 Subject: [PATCH] =?UTF-8?q?test(@projects/@magic-civilization):=20?= =?UTF-8?q?=F0=9F=90=9B=20update=20siege=20capture=20tests=20for=20HP-gate?= =?UTF-8?q?d=20process=5Fsiege?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit process_siege was changed from "≥3 attackers within 2 hexes = instant capture" to HP-gated siege: 15 dmg/attacker/turn against the city's persistent hp, capture at hp<=0. A starter city has 510 hp, so 3 attackers (45/turn) capture neither in one step (last_survivor) nor in 10 turns (event_collector). Drop each defender city's hp below the single-turn 3-attacker total (45) so the capture fires as the tests intend, and refresh the stale "nearby_attackers >= 3" doc comments. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../mc-turn/tests/event_collector_wiring.rs | 7 +++++-- .../mc-turn/tests/last_survivor_via_capture.rs | 18 +++++++++++------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/simulator/crates/mc-turn/tests/event_collector_wiring.rs b/src/simulator/crates/mc-turn/tests/event_collector_wiring.rs index 472b7c4f..3b4754ff 100644 --- a/src/simulator/crates/mc-turn/tests/event_collector_wiring.rs +++ b/src/simulator/crates/mc-turn/tests/event_collector_wiring.rs @@ -94,8 +94,11 @@ fn fixture_state() -> GameState { p0_city0.queue_tier = Some(1); p0_city0.production_stored = 5_000; - // Stand 3 player-0 units on player-1's only city tile so the siege - // capture trigger (`nearby_attackers >= 3`) fires immediately. + // Stand 3 player-0 units on player-1's only city tile so the per-unit + // HP-gated siege in `process_siege` captures it. A starter city has 510 hp + // and siege deals 15/attacker/turn; drop the defender city below the + // single-turn 3-attacker total (45) so CityCaptured fires on turn 1. + state.players[1].cities[0].hp = 30; let p1_city_pos = state.players[1].city_positions[0]; for i in 0..3 { state.players[0].units.push(MapUnit { diff --git a/src/simulator/crates/mc-turn/tests/last_survivor_via_capture.rs b/src/simulator/crates/mc-turn/tests/last_survivor_via_capture.rs index 84bbb7a8..20501fc6 100644 --- a/src/simulator/crates/mc-turn/tests/last_survivor_via_capture.rs +++ b/src/simulator/crates/mc-turn/tests/last_survivor_via_capture.rs @@ -8,9 +8,9 @@ //! && `cities.is_empty()`) stayed false forever and domination / //! last-survivor never fired even after total annihilation. //! -//! This test exercises the actual capture pipeline (3 attacker units -//! within 2 hexes of the defender's only city → `nearby_attackers >= 3` -//! → `process_siege` swap-removes the city), then asserts both: +//! This test exercises the actual capture pipeline (3 attacker units on the +//! defender's only city tile → the per-unit HP-gated siege in `process_siege` +//! drives the city's hp to 0 → the city is swap-removed), then asserts both: //! • `defender.capital_position == None` after capture //! • `TurnEvent::GameOver { reason_kind: "last_survivor", winner: 0 }` //! emitted. @@ -78,11 +78,15 @@ fn capturing_last_city_clears_capital_and_emits_last_survivor() { let p1_pos = (8, 0); let mut p0 = player_with_city_at(0, p0_pos); - let p1 = player_with_city_at(1, p1_pos); + let mut p1 = player_with_city_at(1, p1_pos); + // HP-gated siege deals 15 dmg per attacker per turn (`process_siege`); a + // starter city has 510 hp. Drop the defender's lone city below the + // single-turn 3-attacker siege total (3 × 15 = 45) so the capture completes + // on the first step, as this Bug-5 regression requires. + p1.cities[0].hp = 30; - // Stack 3 p0 units on p1's only city → siege capture trigger fires - // (matches the `nearby_attackers >= 3` predicate in - // `processor::process_siege`). + // Stack 3 p0 units on p1's only city tile → the per-unit siege loop in + // `processor::process_siege` drives the city's hp to 0 and captures it. for i in 0..3 { p0.units.push(MapUnit { id: 100 + i,