mirror of
https://github.com/wesnoth/wesnoth
synced 2025-05-10 03:14:14 +00:00

Previously, the Micro AI behavior was inconsistent at best when it came to dealing with these units and could even result in AI errors when an AI unit was ambushed or a petrified unit was in the way of a move. Now, both types of units are properly "ignored" and the AI moves have been made robust against unexpected events such as ambushes. Incidentally, the latter also makes the AI more robust against WML events doing things the AI cannot know about (such as removing units).
64 lines
1.9 KiB
Lua
64 lines
1.9 KiB
Lua
local H = wesnoth.require "lua/helper.lua"
|
|
local AH = wesnoth.require "ai/lua/ai_helper.lua"
|
|
local BC = wesnoth.require "ai/lua/battle_calcs.lua"
|
|
local LS = wesnoth.require "lua/location_set.lua"
|
|
|
|
local ca_simple_attack, best_attack = {}
|
|
|
|
function ca_simple_attack:evaluation(cfg)
|
|
local units = AH.get_units_with_attacks {
|
|
side = wesnoth.current.side,
|
|
{ "and", H.get_child(cfg, "filter") }
|
|
}
|
|
if (not units[1]) then return 0 end
|
|
|
|
-- If cfg.filter_second is set, set up a map (location set)
|
|
-- of enemies that it is okay to attack
|
|
local enemy_filter = H.get_child(cfg, "filter_second")
|
|
local enemy_map
|
|
if enemy_filter then
|
|
local enemies = AH.get_attackable_enemies(enemy_filter)
|
|
if (not enemies[1]) then return 0 end
|
|
|
|
enemy_map = LS.create()
|
|
for _,enemy in ipairs(enemies) do enemy_map:insert(enemy.x, enemy.y) end
|
|
end
|
|
|
|
-- Now find the best of the possible attacks
|
|
local attacks = AH.get_attacks(units, { include_occupied = true })
|
|
if (not attacks[1]) then return 0 end
|
|
|
|
local max_rating = -9e99
|
|
for _, att in ipairs(attacks) do
|
|
local valid_target = true
|
|
if enemy_filter and (not enemy_map:get(att.target.x, att.target.y)) then
|
|
valid_target = false
|
|
end
|
|
|
|
if valid_target then
|
|
local attacker = wesnoth.get_unit(att.src.x, att.src.y)
|
|
local enemy = wesnoth.get_unit(att.target.x, att.target.y)
|
|
local dst = { att.dst.x, att.dst.y }
|
|
|
|
local rating = BC.attack_rating(attacker, enemy, dst)
|
|
|
|
if (rating > max_rating) then
|
|
max_rating, best_attack = rating, att
|
|
end
|
|
end
|
|
end
|
|
|
|
if best_attack then
|
|
return cfg.ca_score
|
|
end
|
|
|
|
return 0
|
|
end
|
|
|
|
function ca_simple_attack:execution(cfg)
|
|
AH.robust_move_and_attack(ai, best_attack.src, best_attack.dst, best_attack.target, cfg)
|
|
best_attack = nil
|
|
end
|
|
|
|
return ca_simple_attack
|