diff --git a/src/game/engine/src/modules/ai/simple_heuristic_ai.gd b/src/game/engine/src/modules/ai/simple_heuristic_ai.gd index d29915dd..0256dea1 100644 --- a/src/game/engine/src/modules/ai/simple_heuristic_ai.gd +++ b/src/game/engine/src/modules/ai/simple_heuristic_ai.gd @@ -503,6 +503,20 @@ static func _decide_production( var threatened: bool = bool(threat.get("threatens_city", false)) var enemy_total: int = int(threat.get("total_count", 0)) + # Capital walls interject: a 1-city capital that's >20 turns old with at + # least one defender gets walls slotted in BEFORE any other priority + # (including threat preemption). Walls were starved indefinitely during + # early harassment phases where threat-preempt locked us to warriors. + var capital_age: int = GameState.turn_number - int(city.turn_founded) + var capital_needs_walls: bool = ( + city_count == 1 and city_index == 0 + and military_count >= 1 and capital_age > 20 + and not city.has_building("walls") + and city.can_build("walls", player) + ) + if capital_needs_walls: + return _prod_building(city_index, "walls") + # Threat preemption: when an enemy stack is closing on a city, force # military production over walls/happiness/founders until we can field # at least enemy_total + 1 defenders (matches opponent's full army, not @@ -519,25 +533,11 @@ static func _decide_production( # T100. After T80 the standard Priority 4 target takes over. var early_mil_floor: int = 4 if GameState.turn_number <= 80 else 0 if military_count < maxi(1, early_mil_floor): - # Capital walls interject: once the capital has at least 1 defender - # and is >20 turns old, pause military top-up to slot walls in. Walls - # were being starved indefinitely by the mil-floor above; a T40-50 - # wall hardens the capital before the opponent's full army arrives. - var capital_age: int = ( - GameState.turn_number - int(city.turn_founded) + var emergency_unit: String = _pick_buildable_military_unit_id( + city, player ) - var capital_needs_walls: bool = ( - city_count == 1 and city_index == 0 - and military_count >= 1 and capital_age > 20 - and not city.has_building("walls") - and city.can_build("walls", player) - ) - if not capital_needs_walls: - var emergency_unit: String = _pick_buildable_military_unit_id( - city, player - ) - if not emergency_unit.is_empty(): - return _prod_unit(city_index, emergency_unit) + if not emergency_unit.is_empty(): + return _prod_unit(city_index, emergency_unit) # Priority 1: Build walls if city has none (defense first) if not city.has_building("walls") and city.can_build("walls", player):