Add sentry pacing to opening battle
This commit is contained in:
@@ -698,6 +698,14 @@ func _check_opening_battle_tactical_spacing(failures: Array[String]) -> void:
|
||||
var origin: Vector2i = scene._best_auto_attack_origin(player, enemy)
|
||||
if origin != Vector2i(-1, -1):
|
||||
failures.append("opening battle should not allow immediate move-attack from %s to %s via %s" % [player_id, str(enemy.get("id", "")), str(origin)])
|
||||
var front_guard: Dictionary = scene.state.get_unit("yellow_turban_4")
|
||||
if str(front_guard.get("ai_behavior", "")) != "guard" or int(front_guard.get("ai_guard_radius", 0)) < 3:
|
||||
failures.append("opening front guard should react to the lure line without charging from turn one")
|
||||
var central_sentry: Dictionary = scene.state.get_unit("yellow_turban_5")
|
||||
if str(central_sentry.get("ai_behavior", "")) != "sentry" or int(central_sentry.get("ai_sentry_radius", 0)) < 5:
|
||||
failures.append("opening central enemy should use sentry AI for lure-line pacing")
|
||||
if bool(central_sentry.get("ai_awake", false)):
|
||||
failures.append("opening central sentry should start asleep")
|
||||
scene.free()
|
||||
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ func _init() -> void:
|
||||
_check_priority_changes_enemy_targeting(state, failures)
|
||||
_check_reinforcement_priority_events(failures)
|
||||
_check_guard_ai_behavior(failures)
|
||||
_check_sentry_ai_behavior(failures)
|
||||
|
||||
if failures.is_empty():
|
||||
print("event ai priority smoke ok")
|
||||
@@ -130,6 +131,49 @@ func _check_guard_ai_behavior(failures: Array[String]) -> void:
|
||||
failures.append("guard target search should prefer targets inside the guard zone: %s" % str(target.get("id", "")))
|
||||
|
||||
|
||||
func _check_sentry_ai_behavior(failures: Array[String]) -> void:
|
||||
var state = BattleStateScript.new()
|
||||
if not state.load_battle("res://data/scenarios/001_yellow_turbans.json"):
|
||||
failures.append("Could not load stage 1 sentry AI scenario")
|
||||
return
|
||||
|
||||
var sentry: Dictionary = state.get_unit("yellow_turban_5")
|
||||
if str(sentry.get("ai_behavior", "")) != "sentry":
|
||||
failures.append("central raider should load sentry AI behavior")
|
||||
if sentry.get("ai_sentry_anchor", Vector2i(-1, -1)) != Vector2i(10, 6):
|
||||
failures.append("central raider should keep its sentry anchor: %s" % str(sentry.get("ai_sentry_anchor", null)))
|
||||
if int(sentry.get("ai_sentry_radius", 0)) != 5:
|
||||
failures.append("central raider should keep its sentry radius")
|
||||
if int(sentry.get("ai_sentry_activation_turn", 0)) != 4:
|
||||
failures.append("central raider should keep delayed activation turn")
|
||||
|
||||
state._enemy_take_action(sentry)
|
||||
if bool(sentry.get("ai_awake", false)):
|
||||
failures.append("sentry should not wake while opening player positions are distant")
|
||||
if sentry.get("pos", Vector2i.ZERO) != Vector2i(10, 6):
|
||||
failures.append("sleeping sentry should hold its watch post: %s" % str(sentry.get("pos", null)))
|
||||
|
||||
state.get_unit("cao_cao")["pos"] = Vector2i(5, 6)
|
||||
state._enemy_take_action(sentry)
|
||||
if not bool(sentry.get("ai_awake", false)):
|
||||
failures.append("sentry should wake when a player enters the lure line")
|
||||
if sentry.get("pos", Vector2i.ZERO) == Vector2i(10, 6):
|
||||
failures.append("woken sentry should start pressing the lure-line target")
|
||||
|
||||
var delayed_state = BattleStateScript.new()
|
||||
if not delayed_state.load_battle("res://data/scenarios/001_yellow_turbans.json"):
|
||||
failures.append("Could not load delayed sentry AI scenario")
|
||||
return
|
||||
var delayed_sentry: Dictionary = delayed_state.get_unit("yellow_turban_2")
|
||||
delayed_state._enemy_take_action(delayed_sentry)
|
||||
if bool(delayed_sentry.get("ai_awake", false)):
|
||||
failures.append("delayed sentry should not wake before its activation turn")
|
||||
delayed_state.turn_number = 5
|
||||
delayed_state._enemy_take_action(delayed_sentry)
|
||||
if not bool(delayed_sentry.get("ai_awake", false)):
|
||||
failures.append("delayed sentry should wake on its activation turn")
|
||||
|
||||
|
||||
func _feedback_has(feedback: Array[Dictionary], expected_unit_id: String, expected_text: String, expected_kind: String) -> bool:
|
||||
for entry in feedback:
|
||||
if (
|
||||
|
||||
@@ -536,11 +536,11 @@ function Check-Deployment($Deployment, [string]$ScenarioId, [int]$Width, [int]$H
|
||||
}
|
||||
$aiBehavior = [string](Get-Prop $Deployment "ai_behavior" "")
|
||||
if (-not [string]::IsNullOrWhiteSpace($aiBehavior)) {
|
||||
if ($aiBehavior -ne "guard") {
|
||||
if ($aiBehavior -notin @("guard", "sentry")) {
|
||||
Fail "Scenario $ScenarioId deployment $unitId has unknown ai_behavior: $aiBehavior"
|
||||
}
|
||||
if ($team -ne "enemy") {
|
||||
Fail "Scenario $ScenarioId deployment $unitId ai_behavior guard is only valid for enemy deployments."
|
||||
Fail "Scenario $ScenarioId deployment $unitId ai_behavior $aiBehavior is only valid for enemy deployments."
|
||||
}
|
||||
}
|
||||
if ((Has-Prop $Deployment "ai_guard_anchor") -and $aiBehavior -ne "guard") {
|
||||
@@ -549,6 +549,15 @@ function Check-Deployment($Deployment, [string]$ScenarioId, [int]$Width, [int]$H
|
||||
if ((Has-Prop $Deployment "ai_guard_radius") -and $aiBehavior -ne "guard") {
|
||||
Fail "Scenario $ScenarioId deployment $unitId ai_guard_radius needs ai_behavior guard."
|
||||
}
|
||||
if ((Has-Prop $Deployment "ai_sentry_anchor") -and $aiBehavior -ne "sentry") {
|
||||
Fail "Scenario $ScenarioId deployment $unitId ai_sentry_anchor needs ai_behavior sentry."
|
||||
}
|
||||
if ((Has-Prop $Deployment "ai_sentry_radius") -and $aiBehavior -ne "sentry") {
|
||||
Fail "Scenario $ScenarioId deployment $unitId ai_sentry_radius needs ai_behavior sentry."
|
||||
}
|
||||
if ((Has-Prop $Deployment "ai_sentry_activation_turn") -and $aiBehavior -ne "sentry") {
|
||||
Fail "Scenario $ScenarioId deployment $unitId ai_sentry_activation_turn needs ai_behavior sentry."
|
||||
}
|
||||
if (Has-Prop $Deployment "ai_guard_radius") {
|
||||
$guardRadiusValue = Get-Prop $Deployment "ai_guard_radius" 0
|
||||
if (-not ($guardRadiusValue -is [int] -or $guardRadiusValue -is [long])) {
|
||||
@@ -559,6 +568,26 @@ function Check-Deployment($Deployment, [string]$ScenarioId, [int]$Width, [int]$H
|
||||
Fail "Scenario $ScenarioId deployment $unitId ai_guard_radius must be between 0 and 12."
|
||||
}
|
||||
}
|
||||
if (Has-Prop $Deployment "ai_sentry_radius") {
|
||||
$sentryRadiusValue = Get-Prop $Deployment "ai_sentry_radius" 0
|
||||
if (-not ($sentryRadiusValue -is [int] -or $sentryRadiusValue -is [long])) {
|
||||
Fail "Scenario $ScenarioId deployment $unitId ai_sentry_radius must be an integer."
|
||||
}
|
||||
$sentryRadius = [int]$sentryRadiusValue
|
||||
if ($sentryRadius -lt 0 -or $sentryRadius -gt 12) {
|
||||
Fail "Scenario $ScenarioId deployment $unitId ai_sentry_radius must be between 0 and 12."
|
||||
}
|
||||
}
|
||||
if (Has-Prop $Deployment "ai_sentry_activation_turn") {
|
||||
$sentryActivationTurnValue = Get-Prop $Deployment "ai_sentry_activation_turn" 0
|
||||
if (-not ($sentryActivationTurnValue -is [int] -or $sentryActivationTurnValue -is [long])) {
|
||||
Fail "Scenario $ScenarioId deployment $unitId ai_sentry_activation_turn must be an integer."
|
||||
}
|
||||
$sentryActivationTurn = [int]$sentryActivationTurnValue
|
||||
if ($sentryActivationTurn -lt 0 -or $sentryActivationTurn -gt 99) {
|
||||
Fail "Scenario $ScenarioId deployment $unitId ai_sentry_activation_turn must be between 0 and 99."
|
||||
}
|
||||
}
|
||||
|
||||
$classId = Resolve-Class-Id $Deployment $ScenarioId
|
||||
if (-not $classIds.Contains($classId)) {
|
||||
@@ -606,6 +635,25 @@ function Check-Deployment($Deployment, [string]$ScenarioId, [int]$Width, [int]$H
|
||||
Fail "Scenario $ScenarioId deployment $unitId ai_guard_anchor is on impassable terrain."
|
||||
}
|
||||
}
|
||||
if (Has-Prop $Deployment "ai_sentry_anchor") {
|
||||
$sentryAnchor = Get-Prop $Deployment "ai_sentry_anchor" @()
|
||||
if ($sentryAnchor.Count -lt 2) {
|
||||
Fail "Scenario $ScenarioId deployment $unitId has malformed ai_sentry_anchor."
|
||||
}
|
||||
$sentryAnchorX = [int]$sentryAnchor[0]
|
||||
$sentryAnchorY = [int]$sentryAnchor[1]
|
||||
if ($sentryAnchorX -lt 0 -or $sentryAnchorY -lt 0 -or $sentryAnchorX -ge $Width -or $sentryAnchorY -ge $Height) {
|
||||
Fail "Scenario $ScenarioId deployment $unitId ai_sentry_anchor is outside map at [$sentryAnchorX,$sentryAnchorY]."
|
||||
}
|
||||
$sentryAnchorTerrainKey = Terrain-At $Rows $sentryAnchorX $sentryAnchorY
|
||||
$sentryAnchorMoveCost = $terrain.$sentryAnchorTerrainKey.move_cost.$moveType
|
||||
if ($null -eq $sentryAnchorMoveCost) {
|
||||
$sentryAnchorMoveCost = $terrain.$sentryAnchorTerrainKey.move_cost.foot
|
||||
}
|
||||
if ([int]$sentryAnchorMoveCost -ge 99) {
|
||||
Fail "Scenario $ScenarioId deployment $unitId ai_sentry_anchor is on impassable terrain."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Add-Deployment-Unit-Id($Deployment, $Result) {
|
||||
|
||||
Reference in New Issue
Block a user