Artificial intelligence - part 3

Top  Previous  Next

This month we will make a few more improvements to our AI code, trying to make our bot behave more like a human. The first thing that needs our attention is the sight area, the visibility sector, whatever you want to call it. Ackbot needs to become more human by ignoring what it can't "see" directly. This means that we should be able to sneak behind it without getting caught; fortunately, there's an easy way to do that using c_scan.

 

For those of you that have forgotten how c_scan works, there's a workshop that deals with it in Aum54. You, my only Padawan, can of course read on without going through that workshop again.

 

This is the original snippet that was used in the previous AI version.

 

w32_01

 

Note the green line of code; it tells the enemy to attack the player as soon as it has come closer than 1000 quants to it. Now let's see what has changed in this area.

 

w32_02

 

We have added a single line of code that checks if c_scan returns a value above zero or not. According to the manual, c_scan returns a value that's greater than zero only when it has detected an entity. If that entity is the player (you == player) Ackbot will start attacking it.

 

What values give our vision sector? Play with vector (120, 60, 1000) until you are happy with the result; you have seen a similar picture elsewhere but I'll throw another one in here to help you get started more quickly.

 

w32_03

 

It wasn't too complicated, right? Now let's try to delve into something that's even more interesting: obstacle avoidance. You know that I have added a few small blocks to the level because I wanted to show Ackbot's inability to avoid them. If we don't write the code that deals with that, we shouldn't expect our bot to receive some magical obstacle avoidance abilities. The only "magic" that I know of and is associated with programming is the magic of bugs, which tend to appear out of nowhere, but that's another story...

 

We won't get into complex path finding algorithms now, but the code that we will get at the end of this workshop should allow Ackbot to avoid several obstacles; here's a top view of the test level that I am going to use for this demo.

 

w32_04

 

First of all, our enemy needs to detect the environment; it must have some sort of sensors that allow it to "see" in front of it. I have defined two local variables named "content_right" and "content_left" that do just that.

 

w32_05

 

Let's take another look at the old "attacking" code that was used in last month's workshop:

 

w32_06

 

The code is pretty simple: if the status is "attacking", it rotates the bot towards the player at all times. This means that if a level block gets between the player and the enemy, the bot won't be able to avoid it if it can't glide along it. Now let's examine the new code that makes Ackbot look more intelligent.

 

w32_07

 

See? Our bot has become much more intelligent with only a few (maybe 10) extra lines of code.

 

       if (my.status == attacking) // shooting at the player?

       {

               // the road is clear? then rotate the enemy towards the player

               if (c_content (content_right.x, 0) + c_content (content_left.x, 0) == 2)

               {

                       vec_set(temp, player.x);

                       vec_sub(temp,my.x);

                       vec_to_angle(my.pan, temp); // turn the enemy towards the player

               }

 

First of all we need to discuss about c_content, an instruction that can check the content (empty, passable or solid) of a certain position (place) in the level. Its definition is really simple:

 

c_content (position, mode);

 

- "position" is the vector, variable, entity, etc that needs to be checked;

- "mode" is the mode in which the c_content instruction is supposed to run; use zero for it.

 

C_content will return a value of 1 when "position" is placed in an empty area, 2 when "position" is placed in a passable area and 3 when "position" is placed inside a solid area.

 

Ackbot has the "content_right" and "content_left" sensors placed in front of it, just like in the picture below.

 

w32_08

 

Each sensor is placed 50 quants in front of the bot, 20 quants sideways (left and right) and 15 quants below Ackbot's origin. We have discussed about vec_rotate in Aum 54 but here's a brief explanation of it.

 

       vec_set(content_right, vector(50, -20, -15));

       vec_rotate(content_right, my.pan);

       vec_add(content_right.x, my.x);

 

The first line of code sets content_right to the desired offset; the following lines rotate content_right according to Ackbot's pan angle and add it to Ackbot's origin, setting it at the proper position in relation to the bot. With all these things in our minds, let's examine the enemy code once again.

 

w32_07

 

If the bot is attacking and the content of its sensors is 1 + 1 = 2 (empty space for both of them) Ackbot will rotate towards the player, just like it did in the previous versions of our AI code. If at least one of the sensors is placed inside a solid area (a level block or a wmb entity), the bot will rotate with the speed given by 5 * time, avoiding the obstacle. Take a look at the picture below to see what I mean.

 

w32_09

 

Believe it or not, the AI series is over. We have now got a decent,  expandable piece of artificial intelligence in our hands, but most of all, we have learned how FSMs work and we will be able to use the information in all our future projects. I'll see you all next month!