Gaming Your Way

May contain nuts.

Game AI for dummies - or making the enemy see.

Sorry folks yet again no image ... but some code :)

The current game (let's call it CC for the sake of it) is getting close to the point where I would declare the main game engine done, most of the events are processed now and the final enemies are going to be done today (hurray!).

As the title suggests (wow it's something post related) I want to write about the dumb ass AI one, nope rather 4 of the enemies in CC use, if you were so bold to call it AI.

While reading up the docs about the original game I read this:

"goes around objects to the left"

And there are 3 more which go around things to the right.

HA!

I first simply ignored the fact of "going around" and just coded a simple "if enemie hits wall turn left".

cc_ai_00.gif
(ok, I lied, there are some images)


So after noticing my mistake I removed the old code and started to write the one that should allow my enemy to move around things. Sounds easy enough.

cc_ai_01.gif
Oh, that's easy.


"Go ahead as long as there is something to the left, if not, turn left ..."

After a while I really lost my temper and just coded something that could deal with right turns as well, by checking 3 tiles + one, as you can see in the next image.

cc_ai_02.gif
Well that is stupid, isn't it?


Jein, it's a dummy approach. (jein is a pseudo German word, combining "ja" and "nein", yes and no).

cc_ai_03.gif
Some of the common situations, the green arrow shows the next direction
and in "D" shows the use of the 4th check.


In order to simplify (though, yet unoptimised) the checking of the tiles I set up an array of points, holding the offset for each of the checks. To make my life even easier I just numbered the directions (which is used all over the game):
0 = north, 1 = east ...

So the array for 0 (north) looks like this:

this._aTest.push( [new Point(0, -1), new Point( -1, -1), new Point( -1, 0), new Point(1, 0)] );

And because this one should move to the left I added a second array that holds the next direction to go to:

this._aDirNext = [3, 0, 1, 2,  1, 2, 3, 0];

(You might wonder why it has eight entries instead of the needed four, I'll come to that later)
I now could just lookup the next direction I need to face by simply checking with the current direction:

this._iDir = this._aDirNext[this._iDir];

Now, with that in place checking the movement was easy:

private function checkMoveBug ():void {
            
    var strTest:String = "";
    var i:uint;
    var xx:int;
    var yy:int;
    
    for (i = 0; i < 4; i++) {
        
        xx = this._pPos.x + this._aTest[this._iDir][i].x;
        yy = this._pPos.y + this._aTest[this._iDir][i].y;
        
        if (this._refChipsGame.getTile(this._refChipsGame.aMapGame[xx][yy][0]).objProperties.bMonster && this._refChipsGame.aMapGame[xx][yy][1] == -1) {
            strTest += "0";
        } else {
            strTest += "1";
        }
        
    }
            
    switch (strTest.substr(0, 3)) {
        case "000":
// "C"
        case "100":
        case "110":
            this._iDir = this._aDirNext[this._iDir]; // turn to the next dir
            break;
        case "111":
// "A"
        case "101":
            if (strTest.charAt(3) == "0") {
                this._iDir = this._aDirNext[this._iDir + 4];
// this one uses the second pair for "A"
            } else {
                this._iDir = this.getOppositeDir(this._iDir); // this one is used vor "D"
            }
            break
        /*
        case "011":
        case "001": // "B"
            these are not needed because we can just move ahead
            (there is something to the left)
            break;
        */

    }
    
}

The final version has the 4th check removed from the loop and just checks it for "111" and "101".

And because we use an array to store the test offsets, we can make the enemy around things to the right by just changing the values (north):

this._aTest.push( [new Point(0, -1), new Point( 1, -1), new Point( 1, 0), new Point(-1, 0)] );

and changing the aDirNext array to face right:

this._aDirNext = [1, 2, 3, 0, 3, 0, 1, 2];

Vioal. Done.

I hope this is quite understandable (the code is, my writing might not)

nGFX




Comments are closed