Goto MAI: add avoid_enemies= parameter

This commit is contained in:
mattsc 2013-07-06 10:47:09 -07:00
parent b103ded118
commit 8d55cc572f
2 changed files with 67 additions and 4 deletions

View file

@ -5,8 +5,19 @@ return {
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 function custom_cost(x, y, u, enemy_map, enemy_attack_map, multiplier)
local terrain = wesnoth.get_terrain(x, y)
local move_cost = wesnoth.unit_movement_cost(u, terrain)
move_cost = move_cost + (enemy_map:get(x,y) or 0)
move_cost = move_cost + (enemy_attack_map.units:get(x,y) or 0) * multiplier
return move_cost
end
function engine:mai_goto_eval(cfg)
-- If cfg.release_all_units_at_goal is set, check
@ -75,6 +86,28 @@ return {
function engine:mai_goto_exec(cfg)
local units, locs = self.data.units, self.data.locs -- simply for convenience
-- Need the enemy map and enemy attack map if avoid_enemies is set
local enemy_map, enemy_attack_map
if cfg.avoid_enemies then
if (type(cfg.avoid_enemies) ~= 'number') then
H.wml_error("Goto AI avoid_enemies= requires a number as argument")
elseif (cfg.avoid_enemies <= 0) then
H.wml_error("Goto AI avoid_enemies= argument must be >0")
end
local enemies = wesnoth.get_units { { "filter_side", { {"enemy_of", {side = wesnoth.current.side} } } } }
enemy_map = LS.create()
for i,e in ipairs(enemies) do
enemy_map:insert(e.x, e.y, (enemy_map:get(e.x, e.y) or 0) + 1000)
for x, y in H.adjacent_tiles(e.x, e.y) do
enemy_map:insert(x, y, (enemy_map:get(x, y) or 0) + 10)
end
end
enemy_attack_map = BC.get_attack_map(enemies)
end
local closest_hex, best_unit, max_rating = {}, {}, -9e99
for i,u in ipairs(units) do
for i,l in ipairs(locs) do
@ -95,7 +128,15 @@ return {
closest_hex, best_unit = hex, u
end
else -- Otherwise find the best path to take
local path, cost = wesnoth.find_path(u, l[1], l[2])
local path, cost
if cfg.avoid_enemies then
path, cost = wesnoth.find_path(u, l[1], l[2],
function(x, y, current_cost)
return custom_cost(x, y, u, enemy_map, enemy_attack_map, cfg.avoid_enemies)
end)
else
path, cost = wesnoth.find_path(u, l[1], l[2])
end
-- Make all hexes within the unit's current MP equaivalent
if (cost <= u.moves) then cost = 0 end
@ -118,8 +159,6 @@ return {
end
--print(best_unit.id, best_unit.x, best_unit.y, closest_hex[1], closest_hex[2], max_rating)
AH.movefull_outofway_stopunit(ai, best_unit, closest_hex[1], closest_hex[2])
-- If 'unique_goals' is set, mark this location as being taken
if cfg.unique_goals then
local str = 'goals_taken_' .. wesnoth.current.turn
@ -127,6 +166,30 @@ return {
self.data[str]:insert(closest_hex[1], closest_hex[2])
end
-- If avoid_enemies is set, we need to pick farthest reachable hex along that path
if cfg.avoid_enemies then
local path, cost = wesnoth.find_path(best_unit, closest_hex[1], closest_hex[2],
function(x, y, current_cost)
return custom_cost(x, y, best_unit, enemy_map, enemy_attack_map, cfg.avoid_enemies)
end)
-- Now go through the hexes along that path, use normal path finding
closest_hex = path[1]
for i = 2,#path do
local sub_path, sub_cost = wesnoth.find_path(best_unit, path[i][1], path[i][2], cfg)
if sub_cost <= best_unit.moves then
local unit_in_way = wesnoth.get_unit(path[i][1], path[i][2])
if not unit_in_way then
closest_hex = path[i]
end
else
break
end
end
end
AH.movefull_outofway_stopunit(ai, best_unit, closest_hex[1], closest_hex[2])
-- If release_unit_at_goal= or release_all_units_at_goal= key is set:
-- Check if the unit made it to one of the goal hexes
-- This needs to be done for the original goal hexes, not checking the SLF again,

View file

@ -457,7 +457,7 @@ function wesnoth.wml_actions.micro_ai(cfg)
--------- Goto Micro AI - side-wide AI ------------------------------------
elseif (cfg.ai_type == 'goto') then
required_keys = { "filter", "filter_location" }
optional_keys = { "release_all_units_at_goal", "release_unit_at_goal", "unique_goals", "use_straight_line" }
optional_keys = { "avoid_enemies", "release_all_units_at_goal", "release_unit_at_goal", "unique_goals", "use_straight_line" }
CA_parms = { { ca_id = 'mai_goto', score = cfg.ca_score or 300000 } }
--------- Hang Out Micro AI - side-wide AI ------------------------------------