Animals Micro AIs: code cleanup
This commit is contained in:
parent
8ea8cd5bd4
commit
dc3f503be0
5 changed files with 92 additions and 123 deletions
|
@ -19,38 +19,34 @@ function ca_big_animals:evaluation(ai, cfg)
|
|||
end
|
||||
|
||||
function ca_big_animals:execution(ai, cfg)
|
||||
-- Big animals just move toward goal that gets set occasionally
|
||||
-- Avoid the other big animals (bears, yetis, spiders) and the dogs, otherwise attack whatever is in their range
|
||||
-- The only difference in behavior is the area in which the units move
|
||||
-- Big animals just move toward a goal that gets (re)set occasionally
|
||||
-- and attack whatever is in their range (except for some units that they avoid)
|
||||
|
||||
local big_animals = get_big_animals(cfg)
|
||||
local avoid = LS.of_pairs(wesnoth.get_locations { radius = 1,
|
||||
local avoid_map = LS.of_pairs(wesnoth.get_locations { radius = 1,
|
||||
{ "filter", { { "and", cfg.avoid_unit },
|
||||
{ "filter_side", {{"enemy_of", {side = wesnoth.current.side} }} }
|
||||
{ "filter_side", { { "enemy_of", { side = wesnoth.current.side } } } }
|
||||
} }
|
||||
})
|
||||
--AH.put_labels(avoid)
|
||||
|
||||
for i,unit in ipairs(big_animals) do
|
||||
for _,unit in ipairs(big_animals) do
|
||||
local goal = MAIUV.get_mai_unit_variables(unit, cfg.ai_id)
|
||||
|
||||
-- Unit gets a new goal if none exist or on any move with 10% random chance
|
||||
-- Unit gets a new goal if none is set or on any move with a 10% random chance
|
||||
local r = math.random(10)
|
||||
if (not goal.goal_x) or (r == 1) then
|
||||
local locs = AH.get_passable_locations(cfg.filter_location or {})
|
||||
local rand = math.random(#locs)
|
||||
--print(type, ': #locs', #locs, rand)
|
||||
|
||||
goal.goal_x, goal.goal_y = locs[rand][1], locs[rand][2]
|
||||
MAIUV.set_mai_unit_variables(unit, cfg.ai_id, goal)
|
||||
end
|
||||
--print('Big animal goto: ', unit.id, goal.goal_x, goal.goal_y, r)
|
||||
|
||||
-- hexes the unit can reach
|
||||
local reach_map = AH.get_reachable_unocc(unit)
|
||||
local wander_terrain = cfg.filter_location_wander or {}
|
||||
reach_map:iter( function(x, y, v)
|
||||
-- Remove tiles that do not comform to the wander terrain filter
|
||||
if (not wesnoth.match_location(x, y, wander_terrain) ) then
|
||||
if (not wesnoth.match_location(x, y, wander_terrain)) then
|
||||
reach_map:remove(x, y)
|
||||
end
|
||||
end)
|
||||
|
@ -58,56 +54,52 @@ function ca_big_animals:execution(ai, cfg)
|
|||
-- Now find the one of these hexes that is closest to the goal
|
||||
local max_rating, best_hex = -9e99, {}
|
||||
reach_map:iter( function(x, y, v)
|
||||
-- Distance from goal is first rating
|
||||
local rating = - H.distance_between(x, y, goal.goal_x, goal.goal_y)
|
||||
|
||||
-- Proximity to an enemy unit is a plus
|
||||
local enemy_hp = 500
|
||||
for xa, ya in H.adjacent_tiles(x, y) do
|
||||
for xa,ya in H.adjacent_tiles(x, y) do
|
||||
local enemy = wesnoth.get_unit(xa, ya)
|
||||
if enemy and wesnoth.is_enemy(enemy.side, wesnoth.current.side) then
|
||||
if (enemy.hitpoints < enemy_hp) then enemy_hp = enemy.hitpoints end
|
||||
end
|
||||
end
|
||||
rating = rating + 500 - enemy_hp -- prefer attack on weakest enemy
|
||||
rating = rating + 500 - enemy_hp -- Prefer attack on weakest enemy
|
||||
|
||||
-- However, hexes that enemy bears, yetis and spiders can reach get a massive negative hit
|
||||
-- meaning that they will only ever be chosen if there's no way around them
|
||||
if avoid:get(x, y) then rating = rating - 1000 end
|
||||
-- Hexes reachable by units to be be avoided get a massive negative hit
|
||||
if avoid_map:get(x, y) then rating = rating - 1000 end
|
||||
|
||||
reach_map:insert(x, y, rating)
|
||||
if (rating > max_rating) then
|
||||
max_rating, best_hex = rating, { x, y }
|
||||
end
|
||||
end)
|
||||
--print(' best_hex: ', best_hex[1], best_hex[2])
|
||||
--AH.put_labels(reach_map)
|
||||
|
||||
if (best_hex[1] ~= unit.x) or (best_hex[2] ~= unit.y) then
|
||||
AH.checked_move(ai, unit, best_hex[1], best_hex[2]) -- partial move only
|
||||
AH.checked_move(ai, unit, best_hex[1], best_hex[2]) -- Partial move only
|
||||
if (not unit) or (not unit.valid) then return end
|
||||
else -- If animal did not move, we need to stop it (also delete the goal)
|
||||
else -- If unit did not move, we need to stop it (also delete the goal)
|
||||
AH.checked_stopunit_moves(ai, unit)
|
||||
if (not unit) or (not unit.valid) then return end
|
||||
MAIUV.delete_mai_unit_variables(unit, cfg.ai_id)
|
||||
end
|
||||
|
||||
-- Or if this gets the unit to the goal, we also delete the goal
|
||||
-- If this gets the unit to the goal, we also delete the goal
|
||||
if (unit.x == goal.goal_x) and (unit.y == goal.goal_y) then
|
||||
MAIUV.delete_mai_unit_variables(unit, cfg.ai_id)
|
||||
end
|
||||
|
||||
-- Finally, if the unit ended up next to enemies, attack the weakest of those
|
||||
local min_hp, target = 9e99, {}
|
||||
for x, y in H.adjacent_tiles(unit.x, unit.y) do
|
||||
local enemy = wesnoth.get_unit(x, y)
|
||||
local min_hp, target = 9e99
|
||||
for xa,ya in H.adjacent_tiles(unit.x, unit.y) do
|
||||
local enemy = wesnoth.get_unit(xa, ya)
|
||||
if enemy and wesnoth.is_enemy(enemy.side, wesnoth.current.side) then
|
||||
if (enemy.hitpoints < min_hp) then
|
||||
min_hp, target = enemy.hitpoints, enemy
|
||||
end
|
||||
end
|
||||
end
|
||||
if target.id then
|
||||
|
||||
if target then
|
||||
AH.checked_attack(ai, unit, target)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,7 +4,7 @@ local AH = wesnoth.require "ai/lua/ai_helper.lua"
|
|||
local LS = wesnoth.require "lua/location_set.lua"
|
||||
|
||||
local function get_forest_animals(cfg)
|
||||
-- We want the deer/rabbits to move first, tuskers later
|
||||
-- We want the deer/rabbits to move first, tuskers afterward
|
||||
local deer_type = cfg.deer_type or "no_unit_of_this_type"
|
||||
local rabbit_type = cfg.rabbit_type or "no_unit_of_this_type"
|
||||
local forest_animals = AH.get_units_with_moves {
|
||||
|
@ -14,16 +14,16 @@ local function get_forest_animals(cfg)
|
|||
|
||||
local tusker_type = cfg.tusker_type or "no_unit_of_this_type"
|
||||
local all_tuskers = wesnoth.get_units { side = wesnoth.current.side, type = tusker_type }
|
||||
for i,t in ipairs(all_tuskers) do
|
||||
if (t.moves > 0) then table.insert(forest_animals, t) end
|
||||
for _,tusker in ipairs(all_tuskers) do
|
||||
if (tusker.moves > 0) then table.insert(forest_animals, tusker) end
|
||||
end
|
||||
|
||||
-- Tusklets get moved by this CA if there are no tuskers left
|
||||
if not all_tuskers[1] then
|
||||
local tusklet_type = cfg.tusklet_type or "no_unit_of_this_type"
|
||||
local tusklets = wesnoth.get_units { side = wesnoth.current.side, type = tusklet_type }
|
||||
for i,t in ipairs(tusklets) do
|
||||
if (t.moves > 0) then table.insert(forest_animals, t) end
|
||||
for _,tusklet in ipairs(tusklets) do
|
||||
if (tusklet.moves > 0) then table.insert(forest_animals, tusklet) end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -38,10 +38,9 @@ function ca_forest_animals_move:evaluation(ai, cfg)
|
|||
end
|
||||
|
||||
function ca_forest_animals_move:execution(ai, cfg)
|
||||
local forest_animals = get_forest_animals(cfg)
|
||||
|
||||
-- These animals run from any enemy
|
||||
local enemies = wesnoth.get_units { { "filter_side", {{"enemy_of", {side = wesnoth.current.side} }} } }
|
||||
local forest_animals = get_forest_animals(cfg)
|
||||
local enemies = wesnoth.get_units { { "filter_side", { { "enemy_of", {side = wesnoth.current.side } } } } }
|
||||
|
||||
-- Get the locations of all the rabbit holes
|
||||
W.store_items { variable = 'holes_wml' }
|
||||
|
@ -49,73 +48,64 @@ function ca_forest_animals_move:execution(ai, cfg)
|
|||
W.clear_variable { name = 'holes_wml' }
|
||||
|
||||
-- If cfg.rabbit_hole_img is set, only items with that image or halo count as holes
|
||||
local holes = {}
|
||||
for _, item in ipairs(all_items) do
|
||||
if cfg.rabbit_hole_img then
|
||||
local holes
|
||||
if cfg.rabbit_hole_img then
|
||||
for _,item in ipairs(all_items) do
|
||||
if (item.image == cfg.rabbit_hole_img) or (item.halo == cfg.rabbit_hole_img) then
|
||||
table.insert(holes, item)
|
||||
end
|
||||
else
|
||||
table.insert(holes, item)
|
||||
end
|
||||
else
|
||||
holes = all_items
|
||||
end
|
||||
|
||||
local hole_map = LS.create()
|
||||
for i,h in ipairs(holes) do hole_map:insert(h.x, h.y, 1) end
|
||||
--AH.put_labels(hole_map)
|
||||
for _,hole in ipairs(holes) do hole_map:insert(hole.x, hole.y, 1) end
|
||||
|
||||
-- Each unit moves independently
|
||||
for i,unit in ipairs(forest_animals) do
|
||||
--print('Unit', i, unit.x, unit.y)
|
||||
for _,unit in ipairs(forest_animals) do
|
||||
-- Behavior is different depending on whether a predator is close or not
|
||||
local close_enemies = {}
|
||||
for j,e in ipairs(enemies) do
|
||||
if (H.distance_between(unit.x, unit.y, e.x, e.y) <= unit.max_moves+1) then
|
||||
table.insert(close_enemies, e)
|
||||
for _,enemy in ipairs(enemies) do
|
||||
if (H.distance_between(unit.x, unit.y, enemy.x, enemy.y) <= unit.max_moves+1) then
|
||||
table.insert(close_enemies, enemy)
|
||||
end
|
||||
end
|
||||
--print(' #close_enemies', #close_enemies)
|
||||
|
||||
-- If no close enemies, do a random move
|
||||
local wander_terrain = cfg.filter_location or {}
|
||||
if (not close_enemies[1]) then
|
||||
-- All hexes the unit can reach that are unoccupied
|
||||
local reach = AH.get_reachable_unocc(unit)
|
||||
local locs = wesnoth.get_locations(wander_terrain)
|
||||
local locs_map = LS.of_pairs(locs)
|
||||
--print(' #all reachable', reach:size())
|
||||
local wander_locs = wesnoth.get_locations(wander_terrain)
|
||||
local locs_map = LS.of_pairs(wander_locs)
|
||||
|
||||
-- Select only those that satisfy wander_terrain
|
||||
local reachable_terrain = {}
|
||||
local reachable_wander_terrain = {}
|
||||
reach:iter( function(x, y, v)
|
||||
local terrain = wesnoth.get_terrain(x,y)
|
||||
--print(x, y, terrain)
|
||||
if locs_map:get(x,y) then -- doesn't work with '^', so start search at char 2
|
||||
table.insert(reachable_terrain, {x, y})
|
||||
if locs_map:get(x,y) then
|
||||
table.insert(reachable_wander_terrain, {x, y})
|
||||
end
|
||||
end)
|
||||
--print(' #reachable_terrain', #reachable_terrain)
|
||||
|
||||
-- Choose one of the possible locations at random
|
||||
if reachable_terrain[1] then
|
||||
local rand = math.random(#reachable_terrain)
|
||||
if reachable_wander_terrain[1] then
|
||||
local rand = math.random(#reachable_wander_terrain)
|
||||
-- This is not a full move, as running away might happen next
|
||||
if (unit.x ~= reachable_terrain[rand][1]) or (unit.y ~= reachable_terrain[rand][2]) then
|
||||
AH.checked_move(ai, unit, reachable_terrain[rand][1], reachable_terrain[rand][2])
|
||||
if (unit.x ~= reachable_wander_terrain[rand][1]) or (unit.y ~= reachable_wander_terrain[rand][2]) then
|
||||
AH.checked_move(ai, unit, reachable_wander_terrain[rand][1], reachable_wander_terrain[rand][2])
|
||||
end
|
||||
else -- or if no close reachable terrain was found, move toward the closest
|
||||
local locs = wesnoth.get_locations(wander_terrain)
|
||||
else -- Or if no close reachable terrain was found, move toward the closest
|
||||
local best_hex, min_dist = {}, 9e99
|
||||
for j,l in ipairs(locs) do
|
||||
local d = H.distance_between(l[1], l[2], unit.x, unit.y)
|
||||
if d < min_dist then
|
||||
best_hex, min_dist = l,d
|
||||
for _,loc in ipairs(wander_locs) do
|
||||
local dist = H.distance_between(loc[1], loc[2], unit.x, unit.y)
|
||||
if dist < min_dist then
|
||||
best_hex, min_dist = loc, dist
|
||||
end
|
||||
end
|
||||
|
||||
if (best_hex[1]) then
|
||||
local x,y = wesnoth.find_vacant_tile(best_hex[1], best_hex[2], unit)
|
||||
local next_hop = AH.next_hop(unit, x, y)
|
||||
--print(next_hop[1], next_hop[2])
|
||||
|
||||
if (unit.x ~= next_hop[1]) or (unit.y ~= next_hop[2]) then
|
||||
AH.checked_move(ai, unit, next_hop[1], next_hop[2])
|
||||
end
|
||||
|
@ -125,17 +115,13 @@ function ca_forest_animals_move:execution(ai, cfg)
|
|||
|
||||
-- Now we check for close enemies again, as we might just have moved within reach of some
|
||||
local close_enemies = {}
|
||||
|
||||
-- We use a trick here to exclude the case when the unit might have been
|
||||
-- removed in an event above
|
||||
if unit and unit.valid then
|
||||
for j,e in ipairs(enemies) do
|
||||
if (H.distance_between(unit.x, unit.y, e.x, e.y) <= unit.max_moves+1) then
|
||||
table.insert(close_enemies, e)
|
||||
for _,enemy in ipairs(enemies) do
|
||||
if (H.distance_between(unit.x, unit.y, enemy.x, enemy.y) <= unit.max_moves+1) then
|
||||
table.insert(close_enemies, enemy)
|
||||
end
|
||||
end
|
||||
end
|
||||
--print(' #close_enemies after move', #close_enemies, #enemies, unit.id)
|
||||
|
||||
-- If there are close enemies, run away (and rabbits disappear into holes)
|
||||
local rabbit_type = cfg.rabbit_type or "no_unit_of_this_type"
|
||||
|
@ -144,33 +130,34 @@ function ca_forest_animals_move:execution(ai, cfg)
|
|||
-- Returns nil if the only hex that can be reached is the one the unit is on
|
||||
local farthest_hex = AH.find_best_move(unit, function(x, y)
|
||||
local rating = 0
|
||||
for i,e in ipairs(close_enemies) do
|
||||
local d = H.distance_between(e.x, e.y, x, y)
|
||||
rating = rating - 1 / d^2
|
||||
for _,enemy in ipairs(close_enemies) do
|
||||
local dist = H.distance_between(enemy.x, enemy.y, x, y)
|
||||
rating = rating - 1 / dist^2
|
||||
end
|
||||
|
||||
-- If this is a rabbit, try to go for holes
|
||||
if (unit.type == rabbit_type) and hole_map:get(x, y) then
|
||||
rating = rating + 1000
|
||||
-- but if possible, go to another hole
|
||||
-- But if possible, go to another hole if unit is on one
|
||||
if (x == unit.x) and (y == unit.y) then rating = rating - 10 end
|
||||
end
|
||||
|
||||
return rating
|
||||
end)
|
||||
--print(' farthest_hex: ', farthest_hex[1], farthest_hex[2])
|
||||
|
||||
-- This will always find at least the hex the unit is on
|
||||
-- so no check is necessary
|
||||
AH.movefull_stopunit(ai, unit, farthest_hex)
|
||||
|
||||
-- If this is a rabbit ending on a hole -> disappears
|
||||
if (unit.type == rabbit_type) and hole_map:get(farthest_hex[1], farthest_hex[2]) then
|
||||
if unit and unit.valid
|
||||
and (unit.type == rabbit_type) and hole_map:get(farthest_hex[1], farthest_hex[2])
|
||||
then
|
||||
local command = "wesnoth.put_unit(x1, y1)"
|
||||
ai.synced_command(command, farthest_hex[1], farthest_hex[2])
|
||||
end
|
||||
end
|
||||
|
||||
-- Finally, take moves away, as only partial move might have been done
|
||||
-- Also attacks, as these units never attack
|
||||
-- Also take attacks away, as these units never attack
|
||||
if unit and unit.valid then AH.checked_stopunit_all(ai, unit) end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,9 +5,8 @@ local AH = wesnoth.require "ai/lua/ai_helper.lua"
|
|||
local ca_forest_animals_new_rabbit = {}
|
||||
|
||||
function ca_forest_animals_new_rabbit:evaluation(ai, cfg)
|
||||
-- Put new rabbits out the if there are fewer than cfg.rabbit_number
|
||||
-- but only if cfg.rabbit_type is set, otherwise do nothing
|
||||
-- If this gets executed, we'll let the CA black-list itself
|
||||
-- Put new rabbits on map if there are fewer than cfg.rabbit_number
|
||||
-- To end this, we'll let the CA black-list itself
|
||||
|
||||
if (not cfg.rabbit_type) then return 0 end
|
||||
return cfg.ca_score
|
||||
|
@ -25,11 +24,12 @@ function ca_forest_animals_new_rabbit:execution(ai, cfg)
|
|||
-- Eliminate all holes that have an enemy within 'rabbit_enemy_distance' hexes
|
||||
-- We also add a random number to the ones we keep, for selection of the holes later
|
||||
local holes = {}
|
||||
for _, item in ipairs(all_items) do
|
||||
for _,item in ipairs(all_items) do
|
||||
local enemies = wesnoth.get_units {
|
||||
{ "filter_side", {{"enemy_of", {side = wesnoth.current.side} }} },
|
||||
{ "filter_side", { { "enemy_of", { side = wesnoth.current.side } } } },
|
||||
{ "filter_location", { x = item.x, y = item.y, radius = rabbit_enemy_distance } }
|
||||
}
|
||||
|
||||
if (not enemies[1]) then
|
||||
-- If cfg.rabbit_hole_img is set, only items with that image or halo count as holes
|
||||
if cfg.rabbit_hole_img then
|
||||
|
@ -46,13 +46,10 @@ function ca_forest_animals_new_rabbit:execution(ai, cfg)
|
|||
table.sort(holes, function(a, b) return a.random > b.random end)
|
||||
|
||||
local rabbits = wesnoth.get_units { side = wesnoth.current.side, type = cfg.rabbit_type }
|
||||
--print('total number:', number)
|
||||
number = number - #rabbits
|
||||
--print('to add number:', number)
|
||||
number = math.min(number, #holes)
|
||||
--print('to add number possible:', number)
|
||||
|
||||
-- Now we just can take the first 'number' (randomized) holes
|
||||
-- Now we simply take the first 'number' (randomized) holes
|
||||
local tmp_unit = wesnoth.get_units { side = wesnoth.current.side }[1]
|
||||
for i = 1,number do
|
||||
local x, y = -1, -1
|
||||
|
@ -66,7 +63,7 @@ function ca_forest_animals_new_rabbit:execution(ai, cfg)
|
|||
.. wesnoth.current.side
|
||||
.. ", type = '"
|
||||
.. cfg.rabbit_type
|
||||
.. "' } )"
|
||||
.. "' })"
|
||||
ai.synced_command(command, x, y)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -22,9 +22,7 @@ local ca_forest_animals_tusker_attack = {}
|
|||
function ca_forest_animals_tusker_attack:evaluation(ai, cfg)
|
||||
-- Check whether there is an enemy next to a tusklet and attack it ("protective parents" AI)
|
||||
|
||||
-- Both cfg.tusker_type and cfg.tusklet_type need to be set for this to kick in
|
||||
if (not cfg.tusker_type) or (not cfg.tusklet_type) then return 0 end
|
||||
|
||||
if (not get_tuskers(cfg)[1]) then return 0 end
|
||||
if (not get_adjacent_enemies(cfg)[1]) then return 0 end
|
||||
return cfg.ca_score
|
||||
|
@ -35,37 +33,37 @@ function ca_forest_animals_tusker_attack:execution(ai, cfg)
|
|||
local adjacent_enemies = get_adjacent_enemies(cfg)
|
||||
|
||||
-- Find the closest enemy to any tusker
|
||||
local min_dist, attacker, target = 9e99, {}, {}
|
||||
for i,t in ipairs(tuskers) do
|
||||
for j,e in ipairs(adjacent_enemies) do
|
||||
local dist = H.distance_between(t.x, t.y, e.x, e.y)
|
||||
local min_dist, attacker, target = 9e99
|
||||
for _,tusker in ipairs(tuskers) do
|
||||
for _,enemy in ipairs(adjacent_enemies) do
|
||||
local dist = H.distance_between(tusker.x, tusker.y, enemy.x, enemy.y)
|
||||
if (dist < min_dist) then
|
||||
min_dist, attacker, target = dist, t, e
|
||||
min_dist, attacker, target = dist, tusker, enemy
|
||||
end
|
||||
end
|
||||
end
|
||||
--print(attacker.id, target.id)
|
||||
|
||||
-- The tusker moves as close to enemy as possible
|
||||
-- Closeness to tusklets is secondary criterion
|
||||
local adj_tusklets = wesnoth.get_units { side = wesnoth.current.side, type = cfg.tusklet_type,
|
||||
local adj_tusklets = wesnoth.get_units {
|
||||
side = wesnoth.current.side,
|
||||
type = cfg.tusklet_type,
|
||||
{ "filter_adjacent", { id = target.id } }
|
||||
}
|
||||
|
||||
local best_hex = AH.find_best_move(attacker, function(x, y)
|
||||
local rating = - H.distance_between(x, y, target.x, target.y)
|
||||
for i,t in ipairs(adj_tusklets) do
|
||||
if (H.distance_between(x, y, t.x, t.y) == 1) then rating = rating + 0.1 end
|
||||
for _,tusklet in ipairs(adj_tusklets) do
|
||||
if (H.distance_between(x, y, tusklet.x, tusklet.y) == 1) then rating = rating + 0.1 end
|
||||
end
|
||||
|
||||
return rating
|
||||
end)
|
||||
--print('attacker', attacker.x, attacker.y, ' -> ', best_hex[1], best_hex[2])
|
||||
|
||||
AH.movefull_stopunit(ai, attacker, best_hex)
|
||||
if (not attacker) or (not attacker.valid) then return end
|
||||
if (not target) or (not target.valid) then return end
|
||||
|
||||
-- If adjacent, attack
|
||||
local dist = H.distance_between(attacker.x, attacker.y, target.x, target.y)
|
||||
if (dist == 1) then
|
||||
AH.checked_attack(ai, attacker, target)
|
||||
|
|
|
@ -21,11 +21,9 @@ local ca_forest_animals_tusklet_move = {}
|
|||
|
||||
function ca_forest_animals_tusklet_move:evaluation(ai, cfg)
|
||||
-- Tusklets will simply move toward the closest tusker, without regard for anything else
|
||||
-- Except if no tuskers are left, in which case the previous CA takes over and does a random move
|
||||
-- Except if no tuskers are left, in which case ca_forest_animals_move takes over and does a random move
|
||||
|
||||
-- Both cfg.tusker_type and cfg.tusklet_type need to be set for this to kick in
|
||||
if (not cfg.tusker_type) or (not cfg.tusklet_type) then return 0 end
|
||||
|
||||
if (not get_tusklets(cfg)[1]) then return 0 end
|
||||
if (not get_tuskers(cfg)[1]) then return 0 end
|
||||
return cfg.ca_score
|
||||
|
@ -35,22 +33,19 @@ function ca_forest_animals_tusklet_move:execution(ai, cfg)
|
|||
local tusklets = get_tusklets(cfg)
|
||||
local tuskers = get_tuskers(cfg)
|
||||
|
||||
for i,tusklet in ipairs(tusklets) do
|
||||
-- find closest tusker
|
||||
local goto_tusker, min_dist = {}, 9999
|
||||
for i,t in ipairs(tuskers) do
|
||||
local dist = H.distance_between(t.x, t.y, tusklet.x, tusklet.y)
|
||||
for _,tusklet in ipairs(tusklets) do
|
||||
local goto_tusker, min_dist = {}, 9e99
|
||||
for _,tusker in ipairs(tuskers) do
|
||||
local dist = H.distance_between(tusker.x, tusker.y, tusklet.x, tusklet.y)
|
||||
if (dist < min_dist) then
|
||||
min_dist, goto_tusker = dist, t
|
||||
min_dist, goto_tusker = dist, tusker
|
||||
end
|
||||
end
|
||||
--print('closets tusker:', goto_tusker.x, goto_tusker.y, goto_tusker.id)
|
||||
|
||||
-- Move tusklet toward that tusker
|
||||
local best_hex = AH.find_best_move(tusklet, function(x, y)
|
||||
return -H.distance_between(x, y, goto_tusker.x, goto_tusker.y)
|
||||
return - H.distance_between(x, y, goto_tusker.x, goto_tusker.y)
|
||||
end)
|
||||
--print('tusklet', tusklet.x, tusklet.y, ' -> ', best_hex[1], best_hex[2])
|
||||
|
||||
AH.movefull_stopunit(ai, tusklet, best_hex)
|
||||
|
||||
-- Also make sure tusklets never attack
|
||||
|
|
Loading…
Add table
Reference in a new issue