Wolves Micro AI: take default AI [avoid] tag into account

This commit is contained in:
mattsc 2018-11-01 18:07:21 -07:00
parent abaa2dcc84
commit d7418ab8e2
2 changed files with 39 additions and 20 deletions

View file

@ -22,7 +22,18 @@ local ca_wolves_move = {}
function ca_wolves_move:evaluation(cfg)
if (not get_wolves(cfg)[1]) then return 0 end
if (not get_prey(cfg)[1]) then return 0 end
local avoid_map = AH.get_avoid_map(ai, nil, true)
local prey = get_prey(cfg)
local prey_found = false
for _,prey_unit in ipairs(prey) do
if (not avoid_map:get(prey_unit.x, prey_unit.y)) then
prey_found = true
break
end
end
if (not prey_found) then return 0 end
return cfg.ca_score
end
@ -30,18 +41,23 @@ function ca_wolves_move:execution(cfg)
local wolves = get_wolves(cfg)
local prey = get_prey(cfg)
-- Only default AI [avoid] tag makes sense for the wolves since attacks are done by RCA AI
local avoid_map = AH.get_avoid_map(ai, nil, true)
local avoid_units = AH.get_attackable_enemies({ type = cfg.avoid_type })
local avoid_map = BC.get_attack_map(avoid_units).units
local avoid_enemies_map = BC.get_attack_map(avoid_units).units
-- Find prey that is closest to the wolves
local min_dist, target = math.huge
for _,prey_unit in ipairs(prey) do
local dist = 0
for _,wolf in ipairs(wolves) do
dist = dist + M.distance_between(wolf.x, wolf.y, prey_unit.x, prey_unit.y)
end
if (dist < min_dist) then
min_dist, target = dist, prey_unit
if (not avoid_map:get(prey_unit.x, prey_unit.y)) then
local dist = 0
for _,wolf in ipairs(wolves) do
dist = dist + M.distance_between(wolf.x, wolf.y, prey_unit.x, prey_unit.y)
end
if (dist < min_dist) then
min_dist, target = dist, prey_unit
end
end
end
@ -61,12 +77,12 @@ function ca_wolves_move:execution(cfg)
if (height - y <= 5) then rating = rating - (6 - (height - y)) / 1.4 end
-- Hexes that avoid_type units can reach get a massive penalty
if avoid_map:get(x, y) then rating = rating - 1000 end
if avoid_enemies_map:get(x, y) then rating = rating - 1000 end
return rating
end)
end, { avoid_map = avoid_map })
local move_result = AH.movefull_stopunit(ai, wolves[1], wolf1)
local move_result = AH.movefull_stopunit(ai, wolves[1], wolf1 or { wolf1.x, wolf1.y })
-- If the wolf was ambushed, return and reconsider; also if an event removed a wolf
if (AH.is_incomplete_move(move_result)) then return end
for _,check_wolf in ipairs(wolves) do
@ -90,12 +106,12 @@ function ca_wolves_move:execution(cfg)
rating = rating - (dist_t - dist_1t)^2
-- Hexes that avoid_type units can reach get a massive penalty
if avoid_map:get(x, y) then rating = rating - 1000 end
if avoid_enemies_map:get(x, y) then rating = rating - 1000 end
return rating
end)
end, { avoid_map = avoid_map })
local move_result = AH.movefull_stopunit(ai, wolves[i], move)
local move_result = AH.movefull_stopunit(ai, wolves[i], move or { wolves[i].x, wolves[i].y })
-- If the wolf was ambushed, return and reconsider; also if an event removed a wolf
if (AH.is_incomplete_move(move_result)) then return end
for _,check_wolf in ipairs(wolves) do

View file

@ -21,20 +21,23 @@ end
function ca_wolves_wander:execution(cfg)
local wolves = get_wolves(cfg)
-- Only default AI [avoid] tag makes sense for the wolves
local avoid_map = AH.get_avoid_map(ai, nil, true)
-- Number of wolves that can reach each hex
local reach_map = LS.create()
for _,wolf in ipairs(wolves) do
local r = AH.get_reachable_unocc(wolf)
local r = AH.get_reachable_unocc(wolf, { avoid_map = avoid_map })
reach_map:union_merge(r, function(x, y, v1, v2) return (v1 or 0) + (v2 or 0) end)
end
local avoid_units = AH.get_attackable_enemies({ type = cfg.avoid_type })
local avoid_map = BC.get_attack_map(avoid_units).units
local avoid_enemies_map = BC.get_attack_map(avoid_units).units
local max_rating, goal_hex = - math.huge
reach_map:iter( function (x, y, v)
local rating = v + math.random(99)/100.
if avoid_map:get(x, y) then rating = rating - 1000 end
if avoid_enemies_map:get(x, y) then rating = rating - 1000 end
if (rating > max_rating) then
max_rating, goal_hex = rating, { x, y }
@ -47,11 +50,11 @@ function ca_wolves_wander:execution(cfg)
-- For each wolf, we need to check that goal hex is reachable, and out of harm's way
local best_hex = AH.find_best_move(wolf, function(x, y)
local rating = -wesnoth.map.distance_between(x, y, goal_hex[1], goal_hex[2])
if avoid_map:get(x, y) then rating = rating - 1000 end
if avoid_enemies_map:get(x, y) then rating = rating - 1000 end
return rating
end)
end, { avoid_map = avoid_map })
local move_result = AH.movefull_stopunit(ai, wolf, best_hex)
local move_result = AH.movefull_stopunit(ai, wolf, best_hex or { wolf.x, wolf.y })
-- If the wolf was ambushed, return and reconsider; also if an event removed a wolf
if (AH.is_incomplete_move(move_result)) then return end
for _,check_wolf in ipairs(wolves) do