feat(ai): Implement capital defense threat assessment and military production prioritization in SimpleHeuristicAI

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
autocommit 2026-04-16 13:07:12 -07:00
parent e9b3f64e7b
commit 8f18eb57eb

View file

@ -519,11 +519,25 @@ 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):
var emergency_unit: String = _pick_buildable_military_unit_id(
city, player
# 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)
)
if not emergency_unit.is_empty():
return _prod_unit(city_index, emergency_unit)
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)
# Priority 1: Build walls if city has none (defense first)
if not city.has_building("walls") and city.can_build("walls", player):
@ -547,12 +561,11 @@ static func _decide_production(
return _prod_unit(city_index, "founder")
# Priority 4: Military — maintain 2 warriors per city, scaling up to
# match enemy's FULL army when they're closing on us so we don't lose
# on parity once reserves arrive.
var enemy_mil: int = enemy_total if threatened else 0
# match enemy's FULL army at all times (not only when imminent) so we
# don't get jumped when a distant stack closes the gap in 3-4 turns.
var mil_target: int = maxi(4, city_count * 2)
if enemy_mil > 0:
mil_target = maxi(mil_target, enemy_mil + 1)
if enemy_total >= mil_target:
mil_target = enemy_total + 1
var want_military: bool = military_count < mil_target
if want_military:
var unit_id: String = _pick_buildable_military_unit_id(city, player)