Micro AIs new question
Moderator: Forum Moderators
- Spannerbag
- Posts: 735
- Joined: December 18th, 2016, 6:14 pm
- Location: Yes
Micro AIs new question
Hi, hope I'm posting this in the right place.

Basically I want a "nuisance" micro ai that gets in the way by moving its units randomly around the map, ignoring other units (be they friend or enemy).
The (hoped for) result would be combat vs enemy units if, after movement by either side, they happen end up adjacent to each other.
There are two other sides in the scenario in question (both enemy sides); the player's side and another (RCA) ai side (which is unlikely, due to unit placement and behaviour) to attack the micro ai units very often (the converse is much more likely).
As far as I can tell there is no micro ai that does this?
If the "nuisance" micro ai begins its turn with unit(s) adjacent to enemy units ideally I'd prefer that the units randomly wander off rather staying put and fighting - but I could live with the latter behaviour.
I'm wondering if it's possible to tweak the behaviour of the forest animals micro ai to approximate this?
What I'd like to do is amend tusker/tusklet behaviour so they both (or just the tusklets) ignore enemies.
From my admittedly brief skim of the lua code, would it be at all possible to do this by hacking the tusklet and/or tusker move candidate actions?
I am well out of my depth here!
Alternatively I can explore WML options such as hacking team names with
I'd just like to know if this is even feasible - or if there's another way?
Any thoughts or suggestions greatly appreciated!
Cheers!
-- Spannerbag
Edit: Oops and thanks!
Basically I want a "nuisance" micro ai that gets in the way by moving its units randomly around the map, ignoring other units (be they friend or enemy).
The (hoped for) result would be combat vs enemy units if, after movement by either side, they happen end up adjacent to each other.
There are two other sides in the scenario in question (both enemy sides); the player's side and another (RCA) ai side (which is unlikely, due to unit placement and behaviour) to attack the micro ai units very often (the converse is much more likely).
As far as I can tell there is no micro ai that does this?
If the "nuisance" micro ai begins its turn with unit(s) adjacent to enemy units ideally I'd prefer that the units randomly wander off rather staying put and fighting - but I could live with the latter behaviour.
I'm wondering if it's possible to tweak the behaviour of the forest animals micro ai to approximate this?
What I'd like to do is amend tusker/tusklet behaviour so they both (or just the tusklets) ignore enemies.
From my admittedly brief skim of the lua code, would it be at all possible to do this by hacking the tusklet and/or tusker move candidate actions?
I am well out of my depth here!
Alternatively I can explore WML options such as hacking team names with
moveto
and [filter] [filter_adjacent]
but that is an ugly solution.I'd just like to know if this is even feasible - or if there's another way?
Any thoughts or suggestions greatly appreciated!
Cheers!
-- Spannerbag
Last edited by Spannerbag on April 14th, 2025, 8:43 am, edited 3 times in total.
- Pentarctagon
- Project Manager
- Posts: 5716
- Joined: March 22nd, 2009, 10:50 pm
- Location: Earth (occasionally)
Re: Micro AIs question
Moved over to the Lua Labs.
99 little bugs in the code, 99 little bugs
take one down, patch it around
-2,147,483,648 little bugs in the code
take one down, patch it around
-2,147,483,648 little bugs in the code
- Lord-Knightmare
- Discord Moderator
- Posts: 2467
- Joined: May 24th, 2010, 5:26 pm
- Location: Somewhere in the depths of Irdya, gathering my army to eventually destroy the known world.
- Contact:
Re: Micro AIs question
Use coward MAI or the forest animals MAI with unit ids in the tusklet type attribute.
Creator of "War of Legends"
Creator of the Isle of Mists survival scenario.
Maintainer of Forward They Cried
User:Knyghtmare | My Medium
Creator of the Isle of Mists survival scenario.
Maintainer of Forward They Cried
User:Knyghtmare | My Medium
- Spannerbag
- Posts: 735
- Joined: December 18th, 2016, 6:14 pm
- Location: Yes
Re: Micro AIs question
Thanks for the advice, I tried forest animals but they avoid enemies?Lord-Knightmare wrote: ↑April 1st, 2025, 2:28 pm Use coward MAI or the forest animals MAI with unit ids in the tusklet type attribute.
I tried tuskers and tusklets so could try just tusklets but then, I understand, they'd act like deer.
What I'd (ideally) like is a micro ai that moves its units randomly, resulting in occasional skirmishes.
Unless I've missed some setting in the micro ai (quite possible!) then I don't think it'll work the way I want.
Cheers!
-- Spannerbag
- Lord-Knightmare
- Discord Moderator
- Posts: 2467
- Joined: May 24th, 2010, 5:26 pm
- Location: Somewhere in the depths of Irdya, gathering my army to eventually destroy the known world.
- Contact:
Re: Micro AIs question
Try NPC bird behaviour code from IftU then.What I'd (ideally) like is a micro ai that moves its units randomly, resulting in occasional skirmishes.
Creator of "War of Legends"
Creator of the Isle of Mists survival scenario.
Maintainer of Forward They Cried
User:Knyghtmare | My Medium
Creator of the Isle of Mists survival scenario.
Maintainer of Forward They Cried
User:Knyghtmare | My Medium
- Spannerbag
- Posts: 735
- Joined: December 18th, 2016, 6:14 pm
- Location: Yes
Re: Micro AIs question
Many thanks, have found the relevant lua chunk (not that - so far at least - I understand it much).
When I get chance will read up on Project Ethea and, if this code hasn't been formally released for general use, will contact the author(s) (Iris I guess) and ask if I can steal borrow (and maybe adapt if needed) their code.
I know this is all GNU GPL but, especially for bigger or more complex works at least, usually ask anyway.

Thanks for the suggestion, much appreciated.
Cheers!
-- Spannerbag
Re: Micro AIs question
Did you look at the big_animals AI? That is probably the simplest one - it is basically a single file of about 100 lines.Spannerbag wrote: ↑March 31st, 2025, 11:16 pm I'm wondering if it's possible to tweak the behaviour of the forest animals micro ai to approximate this?
What I'd like to do is amend tusker/tusklet behaviour so they both (or just the tusklets) ignore enemies.
From my admittedly brief skim of the lua code, would it be at all possible to do this by hacking the tusklet and/or tusker move candidate actions?
I am well out of my depth here!
You would need to modify it, but it might be a matter of simply deleting the attack code.
- Spannerbag
- Posts: 735
- Joined: December 18th, 2016, 6:14 pm
- Location: Yes
Re: Micro AIs question
No I didn't, thanks for the advice.gnombat wrote: ↑April 2nd, 2025, 11:04 pm
Did you look at the big_animals AI? That is probably the simplest one - it is basically a single file of about 100 lines.
You would need to modify it, but it might be a matter of simply deleting the attack code.
When time permits I'm currently exploring a tortuous implementation in WML that uses either cloned unit types or different sides and swapping unit types/sides on various turns and moveto events. Even if I can get it to work it'll be uuuugly...
The problem, I suspect, with what I want to do is to have the micro ai ignore enemies whilst moving units but attack them if they randomly blunder into them. The WML logic I'm mulling would have a default 50% chance of the micro ai unit attacking if it does blunder into an enemy.
Will have a look at the lua and see if I can make sense of it!
Cheers!
-- Spannerbag
- Spannerbag
- Posts: 735
- Joined: December 18th, 2016, 6:14 pm
- Location: Yes
Re: Micro AIs question *** Resolved ***
Hi all,
Thanks for your help and suggestions.
In the end I went with what I know and got the WML logic working well enough (Forest Animals: tuskers + side switching).
Cheers!
-- Spannerbag
Thanks for your help and suggestions.
In the end I went with what I know and got the WML logic working well enough (Forest Animals: tuskers + side switching).
Cheers!
-- Spannerbag
- Spannerbag
- Posts: 735
- Joined: December 18th, 2016, 6:14 pm
- Location: Yes
Re: Micro AIs new question
Hi,
Although I've got the logic working in WML it's got a few rough edges (mainly to do with the side swapping) so I revisited the forest animals micro_ai lua and realised that on a second viewing it made more sense.
So, I've hacked changed the code and disabled the "flee enemies" bit, hopefully.
However I'm not clear on what goes where nor whether I only need to shove code into a
There are a lot of possible combinations so I thought I'd ask here first.
FWIW here are the changes I made:
Copied
Deleted all micro ais except forest animals, and edited that (only changed 2 lines; the micro_ai name and id).
Then likewise copied
Here I just commented out the logic to store nearby enemies:
I've just done the minimum to hopefully create a working custom micro_ai, I appreciate it's ugly.
Will tidy and refine later once I am able to test it.
So, my question is what (if anything) do I need to put in
Do I need to use
Can I make the micro_ai globally visible across the entire
Code fragment examples would be really helpful; pointing me to the wiki won't as I'm too thick to understand I've read that but (unless I've missed something) am still unclear as to what goes where?
Thanks in advance for any advice/guidance!
Cheers!
-- Spannerbag
Although I've got the logic working in WML it's got a few rough edges (mainly to do with the side swapping) so I revisited the forest animals micro_ai lua and realised that on a second viewing it made more sense.

So, I've hacked changed the code and disabled the "flee enemies" bit, hopefully.
However I'm not clear on what goes where nor whether I only need to shove code into a
[preload]
event and/or whether I need to also embed the code via wesnoth.require
in _main.cfg
.There are a lot of possible combinations so I thought I'd ask here first.
FWIW here are the changes I made:
Copied
data\ai\micro_ais\mai-defs\animals.lua
to local lua directory as mai_forest_animals_ignore_enemies.lua
.Deleted all micro ais except forest animals, and edited that (only changed 2 lines; the micro_ai name and id).
Code: Select all
-- Ugly hack of forest animals ai to remove avoidance of enemy units
local AH = wesnoth.require "ai/lua/ai_helper.lua"
local MAIH = wesnoth.require("ai/micro_ais/micro_ai_helper.lua")
local rabbit_registry_counter = 0;
local save_rabbit_spawn, save_rabbit_despawn
local function register_rabbit_commands()
function wesnoth.custom_synced_commands.rabbit_despawn(cfg)
--TODO: maybe we only want to allow erasing of unit of certain types/sides/locations?
wesnoth.units.erase(cfg.x, cfg.y)
end
function wesnoth.custom_synced_commands.rabbit_spawn(cfg)
--TODO: maybe we only want to allow creation of unit of certain types/sides/locations?
wesnoth.units.to_map({ side = wesnoth.current.side, type = cfg.rabbit_type}, cfg.x, cfg.y)
end
end
function wesnoth.persistent_tags.micro_ai_rabbits.read(cfg)
rabbit_registry_counter = cfg.counter or 0
register_rabbit_commands()
end
function wesnoth.persistent_tags.micro_ai_rabbits.write(add)
if rabbit_registry_counter > 0 then
add{counter = rabbit_registry_counter}
end
end
-- Rename micro ai to "forest_animals_noavoid"
-- Rename ai_id to "mai_forest_animals_noavoid"
--
function wesnoth.micro_ais.forest_animals_noavoid(cfg)
local optional_keys = { rabbit_type = 'string', rabbit_number = 'integer',
rabbit_enemy_distance = 'integer', rabbit_hole_img = 'string', tusker_type = 'string',
tusklet_type = 'string', deer_type = 'string', filter_location = 'tag'
}
local score = cfg.ca_score or 300000
local CA_parms = {
ai_id = 'mai_forest_animals_noavoid',
{ ca_id = "new_rabbit", location = 'ca_forest_animals_new_rabbit.lua', score = score },
{ ca_id = "tusker_attack", location = 'ca_forest_animals_tusker_attack.lua', score = score - 1 },
{ ca_id = "move", location = 'ca_forest_animals_move.lua', score = score - 2 },
{ ca_id = "tusklet_move", location = 'ca_forest_animals_tusklet_move.lua', score = score - 3 }
}
-- Register custom synced commands for the rabbit AI
if cfg.action == "delete" then
rabbit_registry_counter = rabbit_registry_counter - 1
if rabbit_registry_counter == 0 then
wesnoth.custom_synced_commands.rabbit_spawn = save_rabbit_spawn
wesnoth.custom_synced_commands.rabbit_despawn = save_rabbit_despawn
end
else
if rabbit_registry_counter == 0 then
save_rabbit_spawn = wesnoth.custom_synced_commands.rabbit_spawn
save_rabbit_despawn = wesnoth.custom_synced_commands.rabbit_despawn
end
rabbit_registry_counter = rabbit_registry_counter + 1
register_rabbit_commands()
end
return {}, optional_keys, CA_parms
end
Then likewise copied
data\ai\micro_ais\cas\ca_forest_animals_move.lua
to local lua directory as ca_forest_animals_move_ignore_enemies.lua
.Here I just commented out the logic to store nearby enemies:
Code: Select all
function ca_forest_animals_move:execution(cfg)
-- These animals run from any enemy
local unit = get_forest_animals(cfg)[1]
local enemies = AH.get_attackable_enemies()
...
-- Behavior is different depending on whether a predator is close or not
local close_enemies = {}
--
-- Leave close_enemies empty --
--
-- for _,enemy in ipairs(enemies) do
-- if (M.distance_between(unit.x, unit.y, enemy.x, enemy.y) <= unit.max_moves+1) then
-- table.insert(close_enemies, enemy)
-- end
-- end
-- If no close enemies, do a random move
local wander_terrain = wml.get_child(cfg, "filter_location") or {}
...
Will tidy and refine later once I am able to test it.
So, my question is what (if anything) do I need to put in
_main.cfg
and/or the scenario [preload
event?Do I need to use
wesnoth.require
anywhere?Can I make the micro_ai globally visible across the entire
[campaign]
?Code fragment examples would be really helpful; pointing me to the wiki won't as I'm too thick to understand I've read that but (unless I've missed something) am still unclear as to what goes where?

Thanks in advance for any advice/guidance!
Cheers!
-- Spannerbag
- Celtic_Minstrel
- Developer
- Posts: 2361
- Joined: August 3rd, 2012, 11:26 pm
- Location: Canada
- Contact:
Re: Micro AIs new question
You use it with the
[micro_ai]
tag and set ai_type
to the value you defined – in this case, forest_animals_noavoid
.- Spannerbag
- Posts: 735
- Joined: December 18th, 2016, 6:14 pm
- Location: Yes
Re: Micro AIs new question
Hi,
Thanks for taking the trouble to reply, it's appreciated.
Sorry, wasn't clear.
That is, how to allow the engine to access and execute my hacked custom ai.
The other ais all live in the wesnoth
The amended components are currrently in my campaign's
I think the lua code itself has all the necessary path information to stitch together the various components but it's how to tell the engine that this campaign has a custom ai and where to find what it needs.
So, how and where do I add the code?
For example do I put something like:
In
If so is the order important (as the second block references the first)?
And/or do I need to put anything in
Again, if so then what?
I can imagine many ways to do this and with no idea which is correct could waste an awful lot of time before getting it right.
Hope this all makes sense and clarifies my query.
Thanks again,
cheers!
-- Spannerbag
Thanks for taking the trouble to reply, it's appreciated.
Sorry, wasn't clear.
Yep, I understand the WML needed to actually fire up the ai in a scenario, but what I don't know is how to "register" the custom ai with the engine?Celtic_Minstrel wrote: ↑April 14th, 2025, 1:14 pm You use it with the[micro_ai]
tag and setai_type
to the value you defined – in this case,forest_animals_noavoid
.
That is, how to allow the engine to access and execute my hacked custom ai.
The other ais all live in the wesnoth
data/ai/micro_ais
directory subtree but mine is dispersed.The amended components are currrently in my campaign's
lua
directory whereas the remaining (unchanged) components are still in data/ai/micro_ais
.I think the lua code itself has all the necessary path information to stitch together the various components but it's how to tell the engine that this campaign has a custom ai and where to find what it needs.
So, how and where do I add the code?
For example do I put something like:
Code: Select all
[lua]
code="wesnoth.require '~add-ons/LSB/lua/ca_forest_animals_move_ignore_enemies.lua'"
[/lua]
[lua]
code="wesnoth.require '~add-ons/LSB/lua/mai_forest_animals_ignore_enemies.lua'"
[/lua]
_main.cfg
?If so is the order important (as the second block references the first)?
And/or do I need to put anything in
[preload]
as mentioned in the wiki?Again, if so then what?
I can imagine many ways to do this and with no idea which is correct could waste an awful lot of time before getting it right.

Hope this all makes sense and clarifies my query.
Thanks again,
cheers!
-- Spannerbag
- Celtic_Minstrel
- Developer
- Posts: 2361
- Joined: August 3rd, 2012, 11:26 pm
- Location: Canada
- Contact:
Re: Micro AIs new question
Yes, but you only need the second one. The first one won't do anything useful.Spannerbag wrote: ↑April 15th, 2025, 9:42 am For example do I put something like:InCode: Select all
[lua] code="wesnoth.require '~add-ons/LSB/lua/ca_forest_animals_move_ignore_enemies.lua'" [/lua] [lua] code="wesnoth.require '~add-ons/LSB/lua/mai_forest_animals_ignore_enemies.lua'" [/lua]
_main.cfg
?
- Spannerbag
- Posts: 735
- Joined: December 18th, 2016, 6:14 pm
- Location: Yes
Re: Micro AIs new question
Hi Celtic_Minstrel,
Brilliant, thanks for that will try it out when I get chance.
Hopefully final question, in
My version is:
As
Alternatively, could I just shovel the code from
Sorry to keep asking such basic questions.
Thanks again for your time and trouble,
cheers!
-- Spannerbag
Brilliant, thanks for that will try it out when I get chance.
Hopefully final question, in
function wesnoth.micro_ais.forest_animals(cfg)
there's a pointer to the file ca_forest_animals_tusklet_move.lua
:{ ca_id = "move", location = 'ca_forest_animals_move.lua', score = score - 2 }
My version is:
{ ca_id = "move", location = 'ca_forest_animals_move_ignore_enemies.lua', score = score - 2 }
As
ca_forest_animals_move_ignore_enemies.lua
is in the same directory as the calling function's file ( mai_forest_animals_ignore_enemies.lua
) will the file be found with the location
as it is or do I need to prepend a path of some sort?Alternatively, could I just shovel the code from
ca_forest_animals_move_ignore_enemies.lua
into mai_forest_animals_ignore_enemies.lua
and discard the former file?Sorry to keep asking such basic questions.
Thanks again for your time and trouble,
cheers!
-- Spannerbag
- Celtic_Minstrel
- Developer
- Posts: 2361
- Joined: August 3rd, 2012, 11:26 pm
- Location: Canada
- Contact:
Re: Micro AIs new question
I don't think the engine knows that the reference to ca_forest_animals_ignore_enemies.lua was in mai_forest_animals_ignore_enemies.lua – by the time the engine actually uses that reference to load the file, the source information of where that reference came from is probably lost. So yes, I'd use the full path to the file, relative to ~add-ons.