Micro AIs new question

Discussion of Lua and LuaWML support, development, and ideas.

Moderator: Forum Moderators

User avatar
Spannerbag
Posts: 735
Joined: December 18th, 2016, 6:14 pm
Location: Yes

Micro AIs new question

Post by Spannerbag »

Hi, hope I'm posting this in the right place.
Pentarctagon wrote: April 1st, 2025, 5:09 am Moved over to the Lua Labs.
Edit: Oops and thanks! :thumbsup:

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.
SP Campaigns: After EI (v1.14) Leafsea Burning (v1.18, v1.16)
I suspect the universe is simpler than we think and stranger than we can know.
Also, I fear that beyond a certain point more intelligence does not necessarily benefit a species...
User avatar
Pentarctagon
Project Manager
Posts: 5716
Joined: March 22nd, 2009, 10:50 pm
Location: Earth (occasionally)

Re: Micro AIs question

Post by Pentarctagon »

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
User avatar
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

Post by Lord-Knightmare »

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
User avatar
Spannerbag
Posts: 735
Joined: December 18th, 2016, 6:14 pm
Location: Yes

Re: Micro AIs question

Post by Spannerbag »

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.
Thanks for the advice, I tried forest animals but they avoid enemies?
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
SP Campaigns: After EI (v1.14) Leafsea Burning (v1.18, v1.16)
I suspect the universe is simpler than we think and stranger than we can know.
Also, I fear that beyond a certain point more intelligence does not necessarily benefit a species...
User avatar
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

Post by Lord-Knightmare »

What I'd (ideally) like is a micro ai that moves its units randomly, resulting in occasional skirmishes.
Try NPC bird behaviour code from IftU then.
Creator of "War of Legends"
Creator of the Isle of Mists survival scenario.
Maintainer of Forward They Cried
User:Knyghtmare | My Medium
User avatar
Spannerbag
Posts: 735
Joined: December 18th, 2016, 6:14 pm
Location: Yes

Re: Micro AIs question

Post by Spannerbag »

Lord-Knightmare wrote: April 1st, 2025, 5:03 pm Try NPC bird behaviour code from IftU then.
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
SP Campaigns: After EI (v1.14) Leafsea Burning (v1.18, v1.16)
I suspect the universe is simpler than we think and stranger than we can know.
Also, I fear that beyond a certain point more intelligence does not necessarily benefit a species...
gnombat
Posts: 867
Joined: June 10th, 2010, 8:49 pm

Re: Micro AIs question

Post by gnombat »

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!
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.
User avatar
Spannerbag
Posts: 735
Joined: December 18th, 2016, 6:14 pm
Location: Yes

Re: Micro AIs question

Post by Spannerbag »

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.
No I didn't, thanks for the advice.
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
SP Campaigns: After EI (v1.14) Leafsea Burning (v1.18, v1.16)
I suspect the universe is simpler than we think and stranger than we can know.
Also, I fear that beyond a certain point more intelligence does not necessarily benefit a species...
User avatar
Spannerbag
Posts: 735
Joined: December 18th, 2016, 6:14 pm
Location: Yes

Re: Micro AIs question *** Resolved ***

Post by Spannerbag »

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
SP Campaigns: After EI (v1.14) Leafsea Burning (v1.18, v1.16)
I suspect the universe is simpler than we think and stranger than we can know.
Also, I fear that beyond a certain point more intelligence does not necessarily benefit a species...
User avatar
Spannerbag
Posts: 735
Joined: December 18th, 2016, 6:14 pm
Location: Yes

Re: Micro AIs new question

Post by Spannerbag »

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. :D
So, I've hacked changed the code and disabled the "flee enemies" bit, hopefully. :crossed_fingers:

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 {}
...
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 _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
SP Campaigns: After EI (v1.14) Leafsea Burning (v1.18, v1.16)
I suspect the universe is simpler than we think and stranger than we can know.
Also, I fear that beyond a certain point more intelligence does not necessarily benefit a species...
User avatar
Celtic_Minstrel
Developer
Posts: 2361
Joined: August 3rd, 2012, 11:26 pm
Location: Canada
Contact:

Re: Micro AIs new question

Post by Celtic_Minstrel »

You use it with the [micro_ai] tag and set ai_type to the value you defined – in this case, forest_animals_noavoid.
Author of The Black Cross of Aleron campaign and Default++ era.
Former maintainer of Steelhive.
User avatar
Spannerbag
Posts: 735
Joined: December 18th, 2016, 6:14 pm
Location: Yes

Re: Micro AIs new question

Post by Spannerbag »

Hi,

Thanks for taking the trouble to reply, it's appreciated.

Sorry, wasn't clear.
Celtic_Minstrel wrote: April 14th, 2025, 1:14 pm You use it with the [micro_ai] tag and set ai_type to the value you defined – in this case, forest_animals_noavoid.
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?
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]
In _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. :augh:

Hope this all makes sense and clarifies my query.

Thanks again,
cheers!
-- Spannerbag
SP Campaigns: After EI (v1.14) Leafsea Burning (v1.18, v1.16)
I suspect the universe is simpler than we think and stranger than we can know.
Also, I fear that beyond a certain point more intelligence does not necessarily benefit a species...
User avatar
Celtic_Minstrel
Developer
Posts: 2361
Joined: August 3rd, 2012, 11:26 pm
Location: Canada
Contact:

Re: Micro AIs new question

Post by Celtic_Minstrel »

Spannerbag wrote: April 15th, 2025, 9:42 am 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]
In _main.cfg?
Yes, but you only need the second one. The first one won't do anything useful.
Author of The Black Cross of Aleron campaign and Default++ era.
Former maintainer of Steelhive.
User avatar
Spannerbag
Posts: 735
Joined: December 18th, 2016, 6:14 pm
Location: Yes

Re: Micro AIs new question

Post by Spannerbag »

Hi Celtic_Minstrel,

Brilliant, thanks for that will try it out when I get chance. :thumbsup:
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
SP Campaigns: After EI (v1.14) Leafsea Burning (v1.18, v1.16)
I suspect the universe is simpler than we think and stranger than we can know.
Also, I fear that beyond a certain point more intelligence does not necessarily benefit a species...
User avatar
Celtic_Minstrel
Developer
Posts: 2361
Joined: August 3rd, 2012, 11:26 pm
Location: Canada
Contact:

Re: Micro AIs new question

Post by Celtic_Minstrel »

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.
Author of The Black Cross of Aleron campaign and Default++ era.
Former maintainer of Steelhive.
Post Reply