Exercises in Formula and Lua AI and AI-demos add-on feedback

Discussion of all aspects of the game engine, including development of new and existing features.

Moderators: Forum Moderators, Developers

Post Reply
User avatar
8680
Moderator Emeritus
Posts: 742
Joined: March 20th, 2011, 11:45 pm
Location: The past

Re: Exercises in Formula and Lua AI

Post by 8680 »

From looking at the source code, wesnoth.unit_ability() appears to check whether the ability affects the unit, not whether the unit has the ability.

mattsc
Posts: 1160
Joined: October 13th, 2010, 6:14 pm
Location: Hidden on the hex behind Fred

Re: Exercises in Formula and Lua AI

Post by mattsc »

8680 wrote:From looking at the source code, wesnoth.unit_ability() appears to check whether the ability affects the unit, not whether the unit has the ability.
Oh! All right, I guess the explanation in the wiki can be interpreted that way. I misunderstood what an "ability being active for a unit" means, although that does make sense. I assume nobody minds if I clarify this a bit for dumb people like me? :D

Thanks, 8680! Can you also see from the source code whether this is the id or the name of the ability (since both are the same for teleport, but not for all other abilities)? I'll add that into the explanation as well.

Anonymissimus
Inactive Developer
Posts: 2460
Joined: August 15th, 2008, 8:46 pm
Location: Germany

Re: Exercises in Formula and Lua AI

Post by Anonymissimus »

8680 wrote:From looking at the source code, wesnoth.unit_ability() appears to check whether the ability affects the unit, not whether the unit has the ability.
Indeed.
mattsc wrote:Thanks, 8680! Can you also see from the source code whether this is the id or the name of the ability (since both are the same for teleport, but not for all other abilities)? I'll add that into the explanation as well.
It's neither. It is the name of the tag. Which makes the function rather useless and is probably not what silene intended.
I want to clarify the wiki myself.

EDIT
The intended functionality would go about like this:

Code: Select all

	helper = wesnoth.require("lua/helper.lua")
	local function has_ability_by_id(unit, id)
		local abilities = helper.get_child(unit.__cfg, "abilities")
		for i, ability in ipairs(abilities) do
			if ability[2].id == id then return true end
		end
	end
projects (BfW 1.12):
A Simple Campaign: campaign draft for wml startersPlan Your Advancements: mp mod
The Earth's Gut: sp campaignSettlers of Wesnoth: mp scenarioWesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign

mattsc
Posts: 1160
Joined: October 13th, 2010, 6:14 pm
Location: Hidden on the hex behind Fred

Re: Exercises in Formula and Lua AI

Post by mattsc »

Thanks for the additional explanations, Anonymissimus.
Anonymissimus wrote:I want to clarify the wiki myself.
Thanks! I won't fight you for it. ;)

mattsc
Posts: 1160
Joined: October 13th, 2010, 6:14 pm
Location: Hidden on the hex behind Fred

Re: Exercises in Formula and Lua AI

Post by mattsc »

I have a suggestion for a (minor, I believe) change to the Wesnoth AI. I can post this in the Ideas forum or put in a feature request, but I figure I feel around here first.

It has always bugged me that it is not possible to make an AI leader take part in the action. I know that some aspects of this have been discussed before and I understand and agree that this should not be the default behavior. I'm not arguing that. But imagine an Troll Warrior leader that has recruited a bunch of lower trolls. You'd not expect him to sit back and just watch his underlings getting to enjoy all the crushing. He'd jump right into the middle of the action once he's done recruiting, regardless of whether he might be killed in the process. I've encountered several occasions in my scenarios where I'd like to have done something like that. It's currently impossible to do so in an elegant way, so I had to resort to tedious and/or ugly work arounds.

So here's the current status of the AI, as I understand it. The candidate actions are (in order of priority/execution):
{AI_CA_GOTO} - move unit to goto_x,goto_y
{AI_CA_RECRUITMENT}
{AI_CA_MOVE_LEADER_TO_GOALS} - move leader toward [leader_goal]
{AI_CA_MOVE_LEADER_TO_KEEP}
{AI_CA_COMBAT}
{AI_CA_HEALING}
{AI_CA_VILLAGES}
{AI_CA_RETREAT}
{AI_CA_MOVE_TO_TARGETS}
{AI_CA_PASSIVE_LEADER_SHARES_KEEP}

In addition to the obvious leader-only CAs, the side leader takes part in the combat CA, but that only affects him if enemy units are within range. He'll also go to unowned villages that are within range. The CA that moves units toward the enemies is move_to_targets, but even if you disable all other CAs and just leave move_to_targets, the leader does not move toward enemies (or anywhere, in fact). Changing AI parameters such as leader_aggression does not change this behavior qualitatively, it only affects how likely the leader is to attack a certain unit.

So as far as I can tell, AI leaders are specifically excluded from the move_to_targets CA. My suggestion: add an AI parameter (e.g. suicidal_leader ;)) that lets them participate.

Of course, it is possible to set leader_goals or goto_x/y specifically, or I could write a separate CA that moves the leader around. But the move_to_target CA is quite sophisticated and it would be nice to have this apply to the leader also. All of these options also mean that the leader is considered separately from the other units (either before or after). The only way I know of to have the leader take part for real is by setting 'canrecruit=no' for him once he's done recruiting, but that, of course, changes some of the side properties also.

Anyways, just putting it out there. I'll not push for this if there's strong disagreement. In that case I'll see what I can do about implementing a separate CA. I also know that we're in a feature freeze, I just thought I mention it while it's fresh on my mind.

mattsc
Posts: 1160
Joined: October 13th, 2010, 6:14 pm
Location: Hidden on the hex behind Fred

Pass Defense AI

Post by mattsc »

I don't have much time for Wesnoth at the moment, so I shelved the "defensive unit positioning" project for the time being and did something less ambitious. I wrote an AI implementation in which a small human army (enough gold for 8 spearmen), backed by one healer (white mage) and one leader (lieutenant) holds a pass against 400 gold worth of orcish grunts and archers played by the normal RCA AI.

Even though the algorithm used is pretty simple, it does so quite successfully, winning almost all of the time, often with most or even all units alive. The main strength over the RCA AI is that front-line units are backed by a healer and a leader (who also takes part in the battle when needed) and injured units are moved to the back of the line - well, and the fact that they hold the pass, instead of blindly rushing at the enemy, of course.

As some of the behavior is hard-coded for the specific map, I uploaded this as a campaign to the add-ons server: AI Modification Demos. (My plan is to add other scenarios demonstrating other AI modifications to this, so that it might work similarly to the tutotial or ASC.) I'll also update my wiki page with some of the technical information.

If you download the campaign, you can watch the two AI's fight it out (or play the orc side, if you like). It's pretty cool. Well I think it's pretty cool, I'm not exactly unbiased.

Note: Don't play this with 1.9.10 - 1.9.13. For some reason it is very slow (at least on a Mac). 1.9.9 is good (and the earliest version for which it works) and 1.9.14 seems fine as well.
Correction: 1.9.10 is good (and required) as of v0.2.0. 1.9.13 is slow. 1.9.14 and 1.10.0 (woohoo!) are both good. I didn't test 1.9.11 and 1.9.12.

Have fun! And as always, I'm always looking for ideas for other things to do with the AI.
Attachments
pass_defense.jpg
Last edited by mattsc on January 30th, 2012, 2:13 am, edited 1 time in total.

Max
Posts: 1449
Joined: April 13th, 2008, 12:41 am

Re: Exercises in Formula and Lua AI

Post by Max »

nice one...
20120125 21:08:35 error scripting/lua: [string "..."]:5: bad argument #1 to 'require' (file not found)
stack traceback:
: in function 'require'
[string "..."]:5: in function 'bytecode'
...x86)/Battle for Wesnoth 1.9.14/data/lua/wml-tags.lua:249: in function 'cmd'
...x86)/Battle for Wesnoth 1.9.14/data/lua/wml-tags.lua:292: in function <...x86)/Battle for Wesnoth 1.9.14/data/lua/wml-tags.lua:256>
20120125 21:18:14 error ai/actions: Return value of AI ACTION was not checked. This may cause bugs! [/quote]

also both the white mage as well as the lieutenant tend to expose themselves. my white mage died in turn 20, my lieutenant might have earlier... nice to see though how units regroup to get close to the healer...

mattsc
Posts: 1160
Joined: October 13th, 2010, 6:14 pm
Location: Hidden on the hex behind Fred

Re: Exercises in Formula and Lua AI

Post by mattsc »

Thanks, Max. I'll check out those messages.
Max wrote:also both the white mage as well as the lieutenant tend to expose themselves. my white mage died in turn 20, my lieutenant might have earlier...
Yeah, I did that intentionally to see what would happen. The only time I've ever seen the spearmen lose was when the white mage got killed early on. The lieutenant gets killed about every other time and that doesn't seem to matter much for the overall outcome. In a "real" application, I'd either keep them away from the front line entirely or go there only when everybody else is pretty beaten up. Both of them are trivial changes to the code, literally half-line additions.

Anonymissimus
Inactive Developer
Posts: 2460
Joined: August 15th, 2008, 8:46 pm
Location: Germany

Re: Exercises in Formula and Lua AI

Post by Anonymissimus »

Nice. :D
For me this handful of spartans celebrated an almost perfect victory.
And I don't get that lua error, perhaps it depends on the (non-)presence of the WLP.
"very few hps below leveling units" could be used more effectively, these were retreated nonetheless.

If you wanna make it like ASC you should probably include some much simpler examples though.

EDIT
I defeated the last of them in turn 34...was playing quite conservatively though, and didn't fight during the first days but had lots of units left in the end so should be easy to beat.
projects (BfW 1.12):
A Simple Campaign: campaign draft for wml startersPlan Your Advancements: mp mod
The Earth's Gut: sp campaignSettlers of Wesnoth: mp scenarioWesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign

mattsc
Posts: 1160
Joined: October 13th, 2010, 6:14 pm
Location: Hidden on the hex behind Fred

Re: Exercises in Formula and Lua AI

Post by mattsc »

Thanks! :)
Anonymissimus wrote:And I don't get that lua error, perhaps it depends on the (non-)presence of the WLP.
Ah, good point. I don't get them either, but I thought that's maybe because I didn't have the right level of error reporting turned on. Thanks, I'll check that out.
Anonymissimus wrote:"very few hps below leveling units" could be used more effectively, these were retreated nonetheless.
Yes, I noticed that also. That'd be a pretty easy addition as well. Another possible improvement: the AI runs into trouble when the orcs manage to level up a unit, especially if it's a crossbowman. It would probably be good to target those more aggressively.
Anonymissimus wrote:If you wanna make it like ASC you should probably include some much simpler examples though.
Absolutely.
Anonymissimus wrote:I defeated the last of them in turn 34...was playing quite conservatively though, and didn't fight during the first days but had lots of units left in the end so should be easy to beat.
Thanks for the information. I don't think that we'll ever be able to write an AI that can defeat a human player under otherwise equal circumstances.

mattsc
Posts: 1160
Joined: October 13th, 2010, 6:14 pm
Location: Hidden on the hex behind Fred

Re: Exercises in Formula and Lua AI

Post by mattsc »

Umm, another dumb Lua question... When I wrote this:
mattsc wrote:Both of them are trivial changes to the code, literally half-line additions.
I had in the back of my mind that my variable 'is_healer' has values 1 or 0, as in C. In that case, I could have done something like

Code: Select all

rating = base_rating + hitpoints / (1. + is_healer) 
Well, it isn't, it's a boolean. Is there something similar that can be done easily in Lua (without 'if' statements, I mean)? It also needs to be fast, as it gets done thousands of times for each move evaluation

I feel like I should know this, but I can't come up with it right now... :oops:

EDIT:
Wow, this was somewhat unexpected! I made the change keeping the mage and the lieutenant in the second row under all but the most dire circumstances (using an 'if' for now which, come to think of it, might be faster than a division anyway). While I had previously seen the spearmen lose exactly once, they now lost 3 times in a row!!

The reason for this is not that the strategy is worse in general, but that they now have 2 units less to go through the rotation and therefore less time for healing. That way, units might have to go back to the front before they are fully healed. Once I gave them 2 more units (making it the same number as previously for the front spots), they immediately won again.

Shows again that the best strategy depends a lot on sometimes quite minor details. This is why it is so hard to program a good all-purpose AI...

EDIT 2:
Actually, another reason is that spearmen are lousy defenders against orcish bowmen. The white mage and lieutenant were the only units with any reasonable ranged attacks. So I let the AI recruit bowmen also and suddenly it can win again with 8 recruits. :)
So, at this point the biggest weakness (not the only, but the biggest) is the use of units that are about to level up.
Last edited by mattsc on January 25th, 2012, 11:14 pm, edited 1 time in total.

User avatar
Alarantalara
Art Contributor
Posts: 784
Joined: April 23rd, 2010, 8:17 pm
Location: Canada

Re: Exercises in Formula and Lua AI

Post by Alarantalara »

Having played through the scenario, I'd like to point out that when the humans play orcs, the presence of the leader is what really makes it unwinnable for your defender AI.
When the leader is present, it's relatively easy to kill one of the defending units in a single round of attacks during the night, which will eventually force a loss since a human controller will also be rotating units to prevent death.

As for a specific improvement, the two hills spaces are relatively safe for the leader and mage since only one unit can attack them. I'd suggest that allowing them to occupy those spaces when they have enough health that no one unit can kill them may be better than consigning them to the second rank (or just if they have full heath). This would be especially useful if the adjacent enemy is a grunt, since the mage is the most effective attacker.

Edit: I'd probably go so far as to say the mage should attack when possible to take no retaliation from the hills when in full health.

mattsc
Posts: 1160
Joined: October 13th, 2010, 6:14 pm
Location: Hidden on the hex behind Fred

Re: Exercises in Formula and Lua AI

Post by mattsc »

Alarantalara wrote:Having played through the scenario,
Thanks for doing that!
Alarantalara wrote:I'd like to point out that when the humans play orcs, the presence of the leader is what really makes it unwinnable for your defender AI.
When the leader is present, it's relatively easy to kill one of the defending units in a single round of attacks during the night, which will eventually force a loss since a human controller will also be rotating units to prevent death.
That's true. To be honest, I never meant this to be something interesting for a human to play. Having a human with 400 gold play an AI with 150 gold really should be no contest. What I wanted to show was that this specific AI, on this very specific map, can hold off a much larger army played by the normal AI. I then just added the human-playable option kind of as a gimmick. Maybe I should reduce the gold for the orcs when a human is playing them? And/or make the orc leader a unit without leadership (which I think is what you are suggesting)?
Alarantalara wrote:As for a specific improvement, the two hills spaces are relatively safe for the leader and mage since only one unit can attack them. I'd suggest that allowing them to occupy those spaces when they have enough health that no one unit can kill them may be better than consigning them to the second rank (or just if they have full heath). This would be especially useful if the adjacent enemy is a grunt, since the mage is the most effective attacker.
That's a really good point! So maybe I'll just exclude the center dirt hex for those two.

Thanks, everybody, for all the comments. This is really useful. And fun!

User avatar
Alarantalara
Art Contributor
Posts: 784
Joined: April 23rd, 2010, 8:17 pm
Location: Canada

Re: Exercises in Formula and Lua AI

Post by Alarantalara »

mattsc wrote:
Alarantalara wrote:I'd like to point out that when the humans play orcs, the presence of the leader is what really makes it unwinnable for your defender AI.
When the leader is present, it's relatively easy to kill one of the defending units in a single round of attacks during the night, which will eventually force a loss since a human controller will also be rotating units to prevent death.
That's true. To be honest, I never meant this to be something interesting for a human to play. Having a human with 400 gold play an AI with 150 gold really should be no contest. What I wanted to show was that this specific AI, on this very specific map, can hold off a much larger army played by the normal AI. I then just added the human-playable option kind of as a gimmick. Maybe I should reduce the gold for the orcs when a human is playing them? And/or make the orc leader a unit without leadership (which I think is what you are suggesting)?
Removing the leadership would definitely make it harder for a human player. The RCA AI didn't seem to use the leader at all, so it probably doesn't really matter.

As for allowing human play to be a gimmick, I found it very useful since when I went through it as a player I had to think about what weaknesses there were that I could exploit, which made it easier for me at least to see what the AI was doing incorrectly. I didn't experience that level of critical thought when I just watched the AIs play each other.

Anonymissimus
Inactive Developer
Posts: 2460
Joined: August 15th, 2008, 8:46 pm
Location: Germany

Re: Exercises in Formula and Lua AI

Post by Anonymissimus »

mattsc wrote:That's a really good point! So maybe I'll just exclude the center dirt hex for those two.
On the other hand, the center hex has only 40% def, and it can be attacked by 2 units, which means that if a spearman is there it can die, while the leader or mage perhaps can't due to higher hps. So if there's zero chance to loose the unit I would move it there anyway. :)
projects (BfW 1.12):
A Simple Campaign: campaign draft for wml startersPlan Your Advancements: mp mod
The Earth's Gut: sp campaignSettlers of Wesnoth: mp scenarioWesnoth Lua Pack: lua tags and utils
updated to 1.8 and handed over: A Gryphon's Tale: sp campaign

Post Reply