Hi,
Found time to do a bit more on this recently and am making progress, albeit slooowly...![Mad :x]()
I'm not sure of some syntax and am just checking to see if I've got it right?
I'm stealing the "protective parents" ca logic from forest animals (
Specifically it's this snippet I'm unsure of how to rewrite:
Instead of I also want to honour
So I have this code for the protect action (it's not finished, I just want to minimise syntax errors here
).
Questions:
I've kept my questions to a minimun (I have loads more but those I'll work on) but these would be quick wins if anyone could point out the more glaring errors!![Smile :)]()
Thanks in advance for your time and trouble, much appreciated as always.
Cheers!
-- Spannerbag
Found time to do a bit more on this recently and am making progress, albeit slooowly...

I'm not sure of some syntax and am just checking to see if I've got it right?
I'm stealing the "protective parents" ca logic from forest animals (
ca_forest_animals_tusker_attack.lua
).Specifically it's this snippet I'm unsure of how to rewrite:
Code:
-- The tusker moves as close to enemy as possible -- Closeness to tusklets is secondary criterion local adj_tusklets = wesnoth.units.find_on_map { side = wesnoth.current.side, type = cfg.tusklet_type, { "filter_adjacent", { id = target.id } } }
cfg.tusklet_type
, the method used to identify the tusklet equivalent ("follower") in my version is a unit filter:Code:
[filter_follower] type=Icemonax [filter_wml] [variables] wmai=1 [/variables] [/filter_wml] [/filter_follower]
[avoid]
whilst moving the protecting unit ("wanderer").So I have this code for the protect action (it's not finished, I just want to minimise syntax errors here

Code:
-- ca_wanderers_protect.lualocal AH = wesnoth.require "ai/lua/ai_helper.lua"local M = wesnoth.maplocal function get_wanderers(cfg) local wanderers = AH.get_units_with_moves { side = wesnoth.current.side, { "and", filter_wanderer } } return wanderersend-- Returns enemies adjacent to follower units-- function ai_helper.get_attackable_enemies(filter, side, cfg)-- ****************************************************-- *** REFERENCED BY QUESTION 1 BELOW ***-- **************************************************** local function get_adjacent_enemies(cfg) local adjacent_enemies = AH.get_attackable_enemies( { "filter_adjacent", { side = wesnoth.current.side, { "and", filter_follower } } } side = wesnoth.current.side avoid_map = avoid_locs ) return adjacent_enemiesendlocal ca_wanderers_protect = {}-- Check whether there is an enemy next to a follower and attack it (if disable_protect=false)function ca_wanderers_protect:evaluation(cfg) if cfg.disable_protectthen return 0 end -- Protect followers disabled (not default) if (not filter_wanderer)then return 0 end -- No filter_wanderer tag if (not filter_follower)then return 0 end -- No filter_follower tag if (not get_wanderers(cfg)[1])then return 0 end -- No wanderers with moves, so nothing to move if (not get_adjacent_enemies(cfg)[1])then return 0 end -- No adjacent enemies return cfg.ca_scoreendfunction ca_wanderers_protect:execution(cfg) local wanderers = get_wanderers(cfg) local adjacent_enemies = get_adjacent_enemies(cfg) local avoid_locs = AH.get_avoid_map(ai, nil, true) -- [avoid]ed locations, if any -- Find the closest enemy to any wanderer ---@type number, unit?, unit? local min_dist, attacker, target = math.huge, nil, nil for _,wanderer in ipairs(wanderers) do for _,enemy in ipairs(adjacent_enemies) do local dist = M.distance_between(wanderer.x, wanderer.y, enemy.x, enemy.y) if (dist < min_dist) then min_dist, attacker, target = dist, wanderer, enemy end end end-- ****************************************************-- *** REFERENCED BY QUESTION 2 BELOW ***-- **************************************************** -- The wanderer moves as close to enemy as possible -- Closeness to followers is secondary criterion -- wesnoth.units.find_on_map(filter) → array of units local adj_followers = wesnoth.units.find_on_map { side = wesnoth.current.side, { "and", filter_follower } { "and", "filter_adjacent", { id = target.id } } } local best_hex = AH.find_best_move(attacker, function(x, y), { avoid_map = avoid_locs } local rating = -M.distance_between(x, y, target.x, target.y) for _,follower in ipairs(adj_followers) do if (M.distance_between(x, y, follower.x, follower.y) == 1) then rating = rating + 0.1 end end return rating end) AH.robust_move_and_attack(ai, attacker, best_hex, target)endreturn ca_wanderers_protect
Questions:
- Follower filter is stored thus:
local filter_follower = wml.get_child(cfg,"filter_follower")
I'd like this to honourCode:
local adjacent_enemies = AH.get_attackable_enemies( { "filter_adjacent", { side = wesnoth.current.side, { "and", filter_follower } } } side = wesnoth.current.side avoid_map = avoid_locs )
[avoid]
when moving attacking wanderers (more for consistency than anything else, if it's complicated I can omit it).
Is the best place to add that here (presumably removing some otherwise attackable enemies due to[avoid]
) or process avoided locations later?
Presently I specifyside=
so the function knows thatavoid_map
is indeed that and not a garbledside
- is there a more elegant way to do this?
Is enclosing parameters with "(...)" correct or should I use "{...}"?
Finally: any other syntax errors? - When using the existing logic I need to identify enemies adjacent to followers.
Original reference code usestype = cfg.tusklet_type
whereas I havefilter_follower
.Can I simply appendCode:
local adj_followers = wesnoth.units.find_on_map { side = wesnoth.current.side, { "and", filter_follower } { "and", "filter_adjacent", { id = target.id } } }
filter_adjacent
and if so have I done it correctly?
Alternatively, is there a better way given what I have to work with?
E.g. maybe working with the enemy units adjacent to followers rather than vice-versa?
I've kept my questions to a minimun (I have loads more but those I'll work on) but these would be quick wins if anyone could point out the more glaring errors!

Thanks in advance for your time and trouble, much appreciated as always.
Cheers!
-- Spannerbag
Statistics: Posted by Spannerbag — Yesterday, 12:00 pm