From 093d52a7abef92964a96bb5b8b698aae450058d5 Mon Sep 17 00:00:00 2001 From: autocommit Date: Thu, 16 Apr 2026 13:23:52 -0700 Subject: [PATCH] =?UTF-8?q?feat(ai):=20=E2=9C=A8=20Add=20capital=20wall=20?= =?UTF-8?q?prioritization=20logic=20to=20prioritize=20early-game=20defense?= =?UTF-8?q?=20in=20SimpleHeuristicAI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Lilith Autocommit --- .../src/modules/ai/simple_heuristic_ai.gd | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) 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):