Using formula AI to direct unit movement

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

Moderators: Forum Moderators, Developers

Post Reply
Derekkk
Posts: 64
Joined: April 25th, 2007, 5:43 pm

Using formula AI to direct unit movement

Post by Derekkk »

I have spent hours staring at this but I couldn't figure out what is wrong with this formula AI code that I wrote.

It is supposed to move a unit from location (4,3) to location (17,8) and then back repeatly. It is written in a slightly generic manner because I would like to use the same code on other units as well.

But what happens is that every time after the code is run, the variable north_dest remains as null (I know this by checking in-game). It is supposed to store the destination of the unit, i.e. if the unit is heading towards (17,8), north_dest should be equal to loc(17,8).

The code also seems to abort when it's run because the normal AI takes over the control of the unit every time.

Code: Select all

                [unit]
			x=4
			y=3
			side=3
			type=Drake_youth
			id=Top_Drake
			name=Top_Drake
			[ai]
				[vars]
					temp="if(me.vars.north_dest=null,1,me.vars.north_dest)"
					north_dest="if(me.loc=loc(4,3), loc(17,8), me.loc=loc(17,8), loc(4,3), me.vars.temp)"
					new_loc="choose(unit_moves(me.loc), -distance_between(self, me.vars.north_dest))"
				[/vars]
				formula="move(me.loc, me.vars.new_loc)"
			[/ai]
		[/unit]
The variable temp does get a value of 1 though, so the formula-AI does run to an extent, albeit a small one.

Any help would be greatly appreciated. If more info is needed on how the code is supposed to work, I am happy to explain further.

User avatar
Dragonking
Inactive Developer
Posts: 591
Joined: November 6th, 2004, 10:45 am
Location: Poland

Re: Using formula AI to direct unit movement

Post by Dragonking »

Derekkk wrote:

Code: Select all

                [unit]
			x=4
			y=3
			side=3
			type=Drake_youth
			id=Top_Drake
			name=Top_Drake
			[ai]
				[vars]
					temp="if(me.vars.north_dest=null,1,me.vars.north_dest)"
					north_dest="if(me.loc=loc(4,3), loc(17,8), me.loc=loc(17,8), loc(4,3), me.vars.temp)"
					new_loc="choose(unit_moves(me.loc), -distance_between(self, me.vars.north_dest))"
				[/vars]
				formula="move(me.loc, me.vars.new_loc)"
			[/ai]
		[/unit]
Wesnoth wiki covers what can unit variables be set to. You can't assign formula that operates on a unit to a unit variable. It will not work properly.

That's error I got after running this code:
ERROR: type error: expected object but found string ('choose(unit_moves(me.loc), -distance_between(self, me.vars.north_dest))')
It means that "choose(unit_moves(me.loc), -distance_between(self, me.vars.north_dest))" was treated like a string, not like a formula.

You can use loop_formula to set some variables before executing the move. If you write what you want to acheve (maybe in steps?), we can try to help you. :)
This is a block of text that can be added to posts you make. There is a 255 character limit

Derekkk
Posts: 64
Joined: April 25th, 2007, 5:43 pm

Re: Using formula AI to direct unit movement

Post by Derekkk »

Dragonking, you are a godsend! I will give you a quick answer first before attempting to further tested what you have suggested here.

The overall goal of the formula AI is to move the unit between loc(4,3) and loc(17,8) repeatedly.

At the moment, the way it does this is to
1. check if the unit is at loc(17,8) or loc(4,3)
2.1.if the unit is loc(17,8), it will switch the destination to loc(4,3) and vice versa. Variable north_des stores the destination.
2.2. if the unit is elsewhere, just go to step 3.
3. Move the unit towards the destination by moving it to the move-to-able location that is closest to the destination. The location closest to the destination is stored in variable new_loc. (As you have said, new_loc cannot take the formula as value so this step has to be adjusted.)

The variable temp is there just so to avoid storing a null variable into itself as it seems to be not allowed under Formula-AI. I might be wrong.

I have a feeling that step 2 is incorrect also siince north_dest never seems to get assigned a value as I said in the first post.

Hope this explanation helps....

User avatar
Dragonking
Inactive Developer
Posts: 591
Joined: November 6th, 2004, 10:45 am
Location: Poland

Re: Using formula AI to direct unit movement

Post by Dragonking »

Derekkk wrote:The overall goal of the formula AI is to move the unit between loc(4,3) and loc(17,8) repeatedly.

At the moment, the way it does this is to
1. check if the unit is at loc(17,8) or loc(4,3)
2.1.if the unit is loc(17,8), it will switch the destination to loc(4,3) and vice versa. Variable north_des stores the destination.
2.2. if the unit is elsewhere, just go to step 3.
3. Move the unit towards the destination by moving it to the move-to-able location that is closest to the destination. The location closest to the destination is stored in variable new_loc. (As you have said, new_loc cannot take the formula as value so this step has to be adjusted.)
Ok, first question: which version of wesnoth you are using? Generally formula is a bit immature in stable, and thus requires often more work to get what we want.

I implemented what you need (I think :) ) in two versions: for latest svn (NOT 1.7.2, but svn, so once 1.7.3 is out, it should work there), and for stable.
It supports not only moving between just 2, but between any number of given points that are specified inside "waypoints" map (note - there must be loop - last location point to the first so unit can "circle").

SVN version:

Code: Select all

[ai]
  loop_formula="if( me.loc != me.vars.next_step,  move_partial( me.loc, me.vars.next_step ),  set_unit_var( 'next_step', waypoints[me.loc], me.loc )  )"
  [vars] 
    waypoints=[ loc(13,3) -> loc(13,18), loc(13,18) -> loc(13,3) ]
    next_step="loc(13,18)"
  [/vars]
[/ai]
stable version:

Code: Select all

[ai]
  loop_formula="if( me.movement_left > 0, 
     if( me.loc != me.vars.next_step, 
          if( unit_at( me.vars.next_step ),
                if( unit_at(shortest_path(me.loc, me.vars.next_step )[0]),
                  end,
                  move_partial( me.loc, me.vars.next_step )
                ),
                move_partial( me.loc, me.vars.next_step )
             ),
             set_unit_var( 'next_step', me.vars.waypoints[me.loc], me.loc )
           ),
           end
     )"
    [vars]
        waypoints=[ loc(13,3) -> loc(13,18), loc(13,18) -> loc(13,3) ]
        next_step="loc(13,18)"
    [/vars]
[/ai]
I think it should work, if you encounter any problems, just tell me.

One thing: unti to move to the next loc, must stand exactly on one of the waypoints - otherwise it's not like he "reached it".

You may also want to run wesnoth and look at formula AI test scenario:

Code: Select all

wesnoth -t formula -d
Scenario is under data/scenario-formula.cfg and contains wolf rider that has 2 waypoints and a guard_radius - it partols map and if there is enemy within guard_radius he attacks it.
This is a block of text that can be added to posts you make. There is a 255 character limit

Jacques_Fol
Posts: 153
Joined: August 16th, 2008, 2:41 am

Re: Using formula AI to direct unit movement

Post by Jacques_Fol »

Dragonking wrote:I think it should work, if you encounter any problems, just tell me.
Although I am not OP, I did find this mightily interesting and tried to use it. Alas, it didn't work, although it may have to do with the conditions in which it was being used.

I copied the stable version verbatim to a scenario in the 1.6 branch (I'm using 1.6.1 to code). I hoped to get a unit that would patrol between two points. The first time I used it, I moved an enemy unit within range right away, and it attacked it. (Which is fine, playwise.) The second time, I wanted to see it in action - but rather than walk its beat, the unit jumped on the nearest empty village, and then refused to return to the beat. I tried giving the control of villages to that side and it almost looked like it worked because the unit sauntered off in the right direction, but then it (unprovoked) carried on, ignoring the idea that it should return back towards the original point of departure.

Is there something I'm missing, or would you need further information to be able to tell? In any event, thanks for the help!

User avatar
Dragonking
Inactive Developer
Posts: 591
Joined: November 6th, 2004, 10:45 am
Location: Poland

Re: Using formula AI to direct unit movement

Post by Dragonking »

Can you provide a scenario cfg file?

Note that this is part of formula AI, and thus you need to specifiy appriopate AI algorithm for a side controlling this unit:

Code: Select all

        ai_algorithm=formula_ai
        [ai]
            move="fallback('')"
        [/ai]
Thanks to move="fallback('')" as soon as units with their formulas move, default ai takes over control of a side.
This is a block of text that can be added to posts you make. There is a 255 character limit

Jacques_Fol
Posts: 153
Joined: August 16th, 2008, 2:41 am

Re: Using formula AI to direct unit movement

Post by Jacques_Fol »

I can PM it to you if you'd like to check it out
Spoiler:
but I'm happy to report that merely adding that one line specifying the ai_algorithm seemed to do the trick, as it now works like a charm!

It may be interesting to note that I added only this one inside the [side] tag and it already seemed to work just fine without using the move="fallback('')" one. I suppose it may be because I also specify certain general [ai] parameters for the side, so the engine first moves this one unit according to its unit-specific formula AI and then reverts to using the side AI for the other units.

Of course, now the unit is so keen on walking the beat that it promptly ignores my enemy units attacking it, so I'll have to play with it a bit longer to decide when and how it should divert from its formula to regular fighting fun. I will study that wolf rider example seems it seems quite close and report on my progress (which will be attempted early next week).

(And the final challenge will be to decide on a suitable walking path on the map in question, but that will be fun.)

Much obliged, Dragonking, thank you for the help!

Derekkk
Posts: 64
Joined: April 25th, 2007, 5:43 pm

Re: Using formula AI to direct unit movement

Post by Derekkk »

Dragonking wrote: I think it should work, if you encounter any problems, just tell me.
Just to reiterate what Jacques_Fol has said, the stable version's code works like a charm. Thanks so much!
Scenario is under data/scenario-formula.cfg and contains wolf rider that has 2 waypoints and a guard_radius - it partols map and if there is enemy within guard_radius he attacks it.
Funnily enough, this is exactly the AI behaviour I was trying to produce.

Just an observation: The wiki on formula AI could be a bit more blunt and precise when going through the syntax of the language because I think on writing the code, an unreasonable proportion of my time was spent on trying to work out the correct location of all the quotation marks and the "where"s.

Jacques_Fol
Posts: 153
Joined: August 16th, 2008, 2:41 am

Re: Using formula AI to direct unit movement

Post by Jacques_Fol »

I am also happy to report that I finally decided to simply use that Wolf Rider example as well - especially since I saw that, if the unit spots an enemy and diverts from the patrol path to deal with the enemy, it returns to its predetermined beat afterwards. (Provided no further enemies lure it away.)

That really ended up being just what the scenario required. I ended up using that formula AI to set five patrolling points for the unit, and it now has a patrol path that seems to work just well with the other units and sides in terms of gameplay. (As said, it will be possible to see it in practice in the first scenario of ARL when the somewhat bigger update is finally uploaded.)

Much obliged to both, Derekkk for bringing it up and Dragonking for being so helpful.

Post Reply