local H = wesnoth.require "lua/helper.lua" local AH = wesnoth.require "ai/lua/ai_helper.lua" local herding_area = wesnoth.require "ai/micro_ais/cas/ca_herding_f_herding_area.lua" local function get_dogs(cfg) local dogs = AH.get_units_with_moves { side = wesnoth.current.side, { "and", cfg.filter } } return dogs end local function get_sheep_to_herd(cfg) local all_sheep = wesnoth.get_units { side = wesnoth.current.side, { "and", cfg.filter_second }, { "not", { { "filter_adjacent", { side = wesnoth.current.side, { "and", cfg.filter } } } } } } local sheep_to_herd = {} local herding_area = herding_area(cfg) for _,single_sheep in ipairs(all_sheep) do if (not herding_area:get(single_sheep.x, single_sheep.y)) then table.insert(sheep_to_herd, single_sheep) end end return sheep_to_herd end local ca_herding_herd_sheep = {} function ca_herding_herd_sheep:evaluation(ai, cfg) -- If dogs have moves left, and there is a sheep with moves left outside the -- herding area, chase it back if (not get_dogs(cfg)[1]) then return 0 end if (not get_sheep_to_herd(cfg)[1]) then return 0 end return cfg.ca_score end function ca_herding_herd_sheep:execution(ai, cfg) local dogs = get_dogs(cfg) local sheep_to_herd = get_sheep_to_herd(cfg) local max_rating, best_dog, best_hex = -9e99 local c_x, c_y = cfg.herd_x, cfg.herd_y for _,single_sheep in ipairs(sheep_to_herd) do -- Farthest sheep goes first local sheep_rating = H.distance_between(c_x, c_y, single_sheep.x, single_sheep.y) / 10. -- Sheep with no movement left gets big hit if (single_sheep.moves == 0) then sheep_rating = sheep_rating - 100. end for _,dog in ipairs(dogs) do local reach_map = AH.get_reachable_unocc(dog) reach_map:iter( function(x, y, v) local dist = H.distance_between(x, y, single_sheep.x, single_sheep.y) local rating = sheep_rating - dist -- Needs to be on "far side" of sheep, wrt center for adjacent hexes if (H.distance_between(x, y, c_x, c_y) <= H.distance_between(single_sheep.x, single_sheep.y, c_x, c_y)) and (dist == 1) then rating = rating - 1000 end -- And the closer dog goes first (so that it might be able to chase another sheep afterward) rating = rating - H.distance_between(x, y, dog.x, dog.y) / 100. -- Finally, prefer to stay on path, if possible if (wesnoth.match_location(x, y, cfg.filter_location) ) then rating = rating + 0.001 end reach_map:insert(x, y, rating) if (rating > max_rating) then max_rating, best_dog, best_hex = rating, dog, { x, y } end end) end end if (best_hex[1] == best_dog.x) and (best_hex[2] == best_dog.y) then AH.checked_stopunit_moves(ai, best_dog) else AH.checked_move(ai, best_dog, best_hex[1], best_hex[2]) -- partial move only! end end return ca_herding_herd_sheep