Goto MAI: add avoid_enemies= parameter
This commit is contained in:
parent
b103ded118
commit
8d55cc572f
2 changed files with 67 additions and 4 deletions
|
@ -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,
|
||||
|
|
|
@ -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 ------------------------------------
|
||||
|
|
Loading…
Add table
Reference in a new issue