Omnimaga

Calculator Community => TI Calculators => Axe => Topic started by: Aichi on November 10, 2010, 03:20:50 pm

Title: Tilemap AI algorithm?
Post by: Aichi on November 10, 2010, 03:20:50 pm
Hey Guys,
I have to provide for the NPC's AI - damn, how I hate this part of game developing. x.x
It should focus a location, then the NPC looks for a way to get there by differing free fields and blocked fields.
So I need a algorithm that is able to translate to axe (<2Kb) and that can reach the green point by starting on the red position in the attached image. Thanks in advance.
Title: Re: Tilemap AI algorithm?
Post by: AngelFish on November 10, 2010, 04:37:13 pm
There are a lot of ways to do path planning algorithms. Do you want to have the path calculated on the fly (fast, but doesn't guarantee success) or precalculated (slow and you have to figure out where to store the path data)? Also, is there a known map that the algorithm can use? How important is it that the algorithm always finds the point? If it's very important that the point be found, then you're pretty much stuck with the potential fields approach. If it's not as important and the path will generally be fairly direct, then the simplest and fastest way is to give the character random motion with attraction to the point.

Given how complex the path is for that particular route, I'd recommend using potential fields with real time path plotting. Basically, you search out two or three "squares" from the current location and you weight the directional movement of the AI towards the point and away from walls, giving closer walls more negative weight than far walls. I'm not sure any simple algorithm is going to be able to find its way around that map, though. That doorway is really small and finding the point might necessarily involve complicated look-ahead routines.

I have an old routine around here that I developed for precisely this. I'll see if it will solve that.

EDIT: Here's the paper describing the method I used. I'm not sure if you can access it though.

A directional diffusion algorithm on cellular automata
for robot path-planning (http://www.sciencedirect.com/science?_ob=MImg&_imagekey=B6V06-45Y6J8P-2-1&_cdi=5638&_user=56861&_pii=S0167739X02000778&_origin=search&_coverDate=08%2F31%2F2002&_sk=999819992&view=c&wchp=dGLzVlb-zSkzV&md5=5dd5e3f9e33d57bb12965e8f82c31b35&ie=/sdarticle.pdf)

Also, I apparently deleted the file. I'll rewrite it.
Title: Re: Tilemap AI algorithm?
Post by: Builderboy on November 10, 2010, 04:46:34 pm
http://en.wikipedia.org/wiki/Pathfinding is a great article about pathfinding.  For a tilemap of that size, Dijkstra's algorithm is probably your best bet, although implementation can be a bit tricky.

Before i write up an algorithm, i have to ask, are there going to be more than one Red dot?  Is there only going to be a singleGreen dot?  Can the Green dot move?
Title: Re: Tilemap AI algorithm?
Post by: ASHBAD_ALVIN on November 10, 2010, 04:47:40 pm
well, here's an easy way I discovered a long time ago and only costs you like 10-20 bytes of data storage:

You have a list of directions the an enemy/NCP is allowed to go, and run through them in sequential order.  Let's say the path takes 10 movements to get from point A to point B.  that's 10 list elements, each with a number specifying direction.  Let's take this code for ex.:
Code: [Select]
.PATH:
[01010303020303010101]->Str0
For(P,0,9)
.RIGHT
If {Str0+P}=1
X+1->X
End
.LEFT
If {Str0+P}=2
X-1->X
End
.UP
If {Str0+P}=3
Y-1->Y
End
.DOWN
If {Str0+P}=4
Y+1>Y
End
End
.End of subroutine, Interrupt, or just normal code section
.Continue on to rest of code or Return

You see, it'll read the path values, and if the value is equal to a certain number, the enemy will go that direction.

EDIT:
I realize now that this is not path based, it's more find the other dot based X.x
Title: Re: Tilemap AI algorithm?
Post by: Builderboy on November 10, 2010, 04:49:42 pm
well, here's an easy way I discovered a long time ago and only costs you like 10-20 bytes of data storage:

You have a list of directions the an enemy/NCP is allowed to go, and run through them in sequential order.  Let's say the path takes 10 movements to get from point A to point B.  that's 10 list elements, each with a number specifying direction.  Let's take this code for ex.:
Code: [Select]
.PATH:
[01010303020303010101]->Str0
For(P,0,9)
.RIGHT
If {Str0+P}=1
X+1->X
End
.LEFT
If {Str0+P}=2
X-1->X
End
.UP
If {Str0+P}=3
Y-1->Y
End
.DOWN
If {Str0+P}=4
Y+1>Y
End
End
.End of subroutine, Interrupt, or just normal code section
.Continue on to rest of code or Return

You see, it'll read the path values, and if the value is equal to a certain number, the enemy will go that direction.

Isn't that more like following a specific path? Not actually finding the path itself?
Title: Re: Tilemap AI algorithm?
Post by: ASHBAD_ALVIN on November 10, 2010, 04:51:07 pm
yeah I was thinking in terms of a tower defense game :P

Sorry for the interruption, proceed with discussion and ignore my suggestion.
Title: Re: Tilemap AI algorithm?
Post by: Aichi on November 10, 2010, 05:54:03 pm
There are a lot of ways to do path planning algorithms. Do you want to have the path calculated on the fly (fast, but doesn't guarantee success) or precalculated (slow and you have to figure out where to store the path data)?
I want to precalculate the path. I just hope that the speed is still nice on a 20x20 map with 15Mhz.

Also, is there a known map that the algorithm can use? How important is it that the algorithm always finds the point? If it's very important that the point be found, then you're pretty much stuck with the potential fields approach. If it's not as important and the path will generally be fairly direct, then the simplest and fastest way is to give the character random motion with attraction to the point.
The path should be exact as long as the calculating dont get too slow.
The page you link to is only for members that pay 20$ for a registration.

Before i write up an algorithm, i have to ask, are there going to be more than one Red dot?  Is there only going to be a singleGreen dot?  Can the Green dot move?
There will be many red dots in my game representing the enemies positions. A enemy is able to (just for example) walk 8 fields per round. If this enemy already doenst has a location to focus, he will search for one green point that he can reach with 8 fields. If there is no green point with this close, he will focus the next green point he can reach and keep this focus.
Now the enemy has a focus in any case, so a path from the enemy to the focused location will be precalculated and the enemy follow this path by 8 fields. In the next round the path has to be generated again, cause the green points (the players characters) are also able to move (the focus follow the character/green point automatically).
I dont know how feasable this is, since the tilemaps are going to be 20x20 and the focus searching routine & the path calculating routine must will repeat by up to 30 times per round. Also, I have to take a look on the needed memory size.
The result should be looks like this (http://www.youtube.com/watch?v=5PRABSTjLUw) (enemies are moving at 1:35).
Title: Re: Tilemap AI algorithm?
Post by: Runer112 on November 10, 2010, 06:22:56 pm
Well that certainly changes things... *throws away just about all the code I had been working on* :-\ I thought this would be like a real-time thing in which the enemy would track one moving target, like enemies tracking you in Zelda games. But now you mention that it's one of those turn-based games in which enemies have a maximum move distance and have to choose among multiple targets.

I suggest putting that in your first post so anyone else who wants to try it doesn't do the same thing I did and work for a while to find out later it isn't what you need.
Title: Re: Tilemap AI algorithm?
Post by: AngelFish on November 10, 2010, 07:35:32 pm
There are a lot of ways to do path planning algorithms. Do you want to have the path calculated on the fly (fast, but doesn't guarantee success) or precalculated (slow and you have to figure out where to store the path data)?
I want to precalculate the path. I just hope that the speed is still nice on a 20x20 map with 15Mhz.

Also, is there a known map that the algorithm can use? How important is it that the algorithm always finds the point? If it's very important that the point be found, then you're pretty much stuck with the potential fields approach. If it's not as important and the path will generally be fairly direct, then the simplest and fastest way is to give the character random motion with attraction to the point.
The path should be exact as long as the calculating dont get too slow.
The page you link to is only for members that pay 20$ for a registration.

Okay. I have a hard copy of the file on my end, so I wasn't sure.

Precalculating is possible, but I'm not sure how it should be stored. The only efficient way I can think of would be to store a series of directional instructions, telling it Left, then Forward, then Forward, then Right, and so on. But that would mean you're wasting at least 1 byte for every tile moved and in all likelihood 2 bytes for a practical minimum (X and Y).

As for algorithms, the one I linked won't work. It's a real time system, as was the code I was working on.
Title: Re: Tilemap AI algorithm?
Post by: Runer112 on November 10, 2010, 10:21:45 pm
I win :)

The AI will find the shortest route to any opposing character, and then move as far along that route as possible (in this case, a maximum of 8 tiles). The AI will pull right up alongside the enemy, avoiding all walls and allied characters. It built it to be able to handle more than one AI character and more than one player character, I just haven't tried that yet.

The flashing "THINKING..." message when the AI is right next to the target is due to me repeatedly commanding the AI to make a move, but his move takes virtually no time to plan and execute.

EDIT: Yup, works flawlessly with more characters ;D . This is all automated. Observe the slower enemy on the left.
Title: Re: Tilemap AI algorithm?
Post by: ztrumpet on November 10, 2010, 10:52:53 pm
Nice!  Can we get the source for this? ;D
Title: Re: Tilemap AI algorithm?
Post by: Runer112 on November 10, 2010, 10:55:08 pm
Sure, I just need to add some code to handle the case where there is no path to an enemy, I didn't add that yet.
Title: Re: Tilemap AI algorithm?
Post by: AngelFish on November 10, 2010, 11:00:04 pm
(http://img.removedfromgame.com/imgs/1289447925-Path.gif)

Spoiler For Spoiler:
It's *technically* preprocessing  ;)

In all seriousness, I'm still working on it.
Title: Re: Tilemap AI algorithm?
Post by: DJ Omnimaga on November 10, 2010, 11:02:39 pm
I'M not sure if I missed anything, but why not just using a pre-stored path for the NPCs? ???  Like for example a NPC will go 2 steps right, 1 step up, stop one frame, move all the way back, stop again and so on? THere wouldn't be much need for AI, then, although he would stop moving while you're on his way.
Title: Re: Tilemap AI algorithm?
Post by: ztrumpet on November 10, 2010, 11:05:29 pm
There will be many red dots in my game representing the enemies positions. A enemy is able to (just for example) walk 8 fields per round. If this enemy already doenst has a location to focus, he will search for one green point that he can reach with 8 fields. If there is no green point with this close, he will focus the next green point he can reach and keep this focus.
Now the enemy has a focus in any case, so a path from the enemy to the focused location will be precalculated and the enemy follow this path by 8 fields. In the next round the path has to be generated again, cause the green points (the players characters) are also able to move (the focus follow the character/green point automatically).
I dont know how feasable this is, since the tilemaps are going to be 20x20 and the focus searching routine & the path calculating routine must will repeat by up to 30 times per round. Also, I have to take a look on the needed memory size.
The result should be looks like this (http://www.youtube.com/watch?v=5PRABSTjLUw) (enemies are moving at 1:35).
Re-read this and click the link. ;)
Title: Re: Tilemap AI algorithm?
Post by: Runer112 on November 10, 2010, 11:34:15 pm
It's completely completed now :) It would've frozen before if there was no path directly to an enemy before, but now it will handle pathfinding in the following priority order:

This will handle any situation. Whether or not the enemy can actually reach a player character, it will get as close as possible. Below is an example screenshot of the fully completed AI.

The source code is both pasted here and attached. I commented pretty much every line, I hope that makes it at least a bit easier to understand.

Code: [Select]
.AI

.<DATA>

.Map buffer
det(768)→GDB0MB

.Map
[]→GDB0M
[000000010000000000010000]
[000000010000000000010000]
[000101010000000000010000]
[000000000000000101010101]
[000101010101010100000000]
[000100000000000000000000]
[000100000000000100000000]
[000000000000000100000000]

.Tiles
[]→GDB0T
[0000000000000000]
[FFFFFFFFFFFFFFFF]

.Target
[8142241818244281]→Pic0T
[8142241818244281]

.Character
[3C4281818181423C]→Pic0C
[3C7EFFFFFFFF7E3C]

.Ally data
.Number of characters
∆List(2ʳ)→GDB0A
.Data:
  .x position
  .y position
  .Max move distance
  .Other
  .data
  .you'll
  .probably
  .have
∆List(6,1,8,0,0,0,0,0)
∆List(1,0,8,0,0,0,0,0)

.Enemy data
.Number of enemies
∆List(3ʳ)→GDB0E
.Data:
∆List(10,6,8,0,0,0,0,0)
∆List(3,7,2,0,0,0,0,0)
∆List(11,2,8,0,0,0,0,0)


.<INITIALIZATION>

.Draw tilemap
GDB0M-1→D
0→Y
While -64
  0→X
  While -96
    Pt-Off(Y,X,{D+1→D}*8+GDB0T)→GDB0MB
    X+8→X
  End
  Y+8→Y
End

.Copy ally data to L₁
conj(GDB0A,L₁,258)

.Copy enemy data to L₁+258
conj(GDB0E,L₁+258,258)

Fix 5

.<MAIN LOOP>

Repeat getKey(15)

  .Advance AI if enter is pressed
  If getKey(9)
    .For each enemy
    For(r₁,1,{L₁+258}ʳ)
      .Let user know AI is thinking; T=test stage (0=normal, 1=ignore other enemies, 2=ignore walls)
      Text(0→T,,"THINKING...")
      .Update screen
      DispGraph
      .Pathfinding start
      Lbl PFS
      .ᴇ8000=Start of pathfinding map
      0→{ᴇ8000}ʳ
      .Fill pathfinding map with 0s
      Fill(ᴇ8001,254)
      .r₃=Iteration, r₂=pointer to enemy data; mark current location with 1
      1→r₃→{{r₁*8+L₁+258+2-8→r₂+1}*12+{r₂}+ᴇ8000}
      .Start of pathfinding loop
      Lbl PFL
      .Default to no viable path
      0→r₆
      .D=Data pointer in pathfinding map
      ᴇ8000→D
      .While data pointer is in the map
      While -ᴇ8000-96
        .If tile is not already part of a (shorter) path
        !If {D}
          .If tile can be traversed or in test stage 2
          If {D-ᴇ8000+GDB0M}=0+(T>1)
            .If tile borders the end of a path
            !If sub(PCL)
              .Check tile (skip pathfinding failed goto)
              Goto PFC
            End
            !If sub(PCR)
              Goto PFC
            End
            !If sub(PCD)
              Goto PFC
            End
            !If sub(PCU)
              Goto PFC
            End
            .Pathfinding failed
            Goto PFF
            .Pathfinding check
            Lbl PFC
            .If in test stage 0
            !If T
              .If tile is occupied by another character
              !If sub(PCC)
                .Pathfinding failed
                Goto PFF
              End
            End
            .For each allied character
            For(r₄,1,{L₁}ʳ)
              .If occupying current tile
              !If 0sub(O0)
                .Target found
                Goto PFE
              End
            End
            .Viable paths exist
            1→r₆
            .Mark as extension of path
            r₃+1→{D}
          End
        End
        .Pathfinding fail (tile cannot be traversed)
        Lbl PFF
        .Increase data pointer
        D+1→D
      End
      .Increase iteration
      r₃+1→r₃
      .If no viable path was found this iteration
      !If r₆
        .Increase test stage
        T+1→T
        .Reset pathfinding
        Goto PFS
      End
      .Continue pathfinding
      Goto PFL
      .Pathfinding end
      Lbl PFE
      .Length of path
      0→{ᴇ8060}ʳ
      .While not at start of path
      While r₃-1
        .If bordering tile is part of path
        !If sub(PCL)
          .Backtrack to tile
          Goto PFB
        End
        !If sub(PCR)
          Goto PFB
        End
        !If sub(PCU)
          Goto PFB
        End
        sub(PCD)
        .Pathfinding backtrack
        Lbl PFB
        r₄→D
        .Decrease iteration
        r₃-1→r₃
        .If distance to tile is not greater than maximum move distance
        !If >{r₂+2}
          .Record tile as part of path
          D-ᴇ8000→{{ᴇ8060}ʳ+1→{ᴇ8060}ʳ+ᴇ8062-1}
        End
        .If tile is occupied by another character
        !If sub(PCC)
          .Reset path
          Goto PFE
        End
        .If tile cannot be traversed
        If {D-ᴇ8000+GDB0M}
          .Reset path
          Goto PFE
        End
      End
      .For each element in path
      For(r₃,1,{ᴇ8060}ʳ)
        .Move character
        {{ᴇ8060}ʳ+ᴇ8062-r₃}→r₄^12→{r₂}
        r₄/12→{r₂+1}
        sub(D)
        Pause 256
      End
    End
    .Wait for user to let go of enter key
    While getKey(9)
    End
  End

  sub(D)
End


.<EXIT>

Fix 4
Return


.<SUBROUTINES>

.Draw everything
Lbl D
  .Draw map
  conj(GDB0MB,L₆,768)
  .Draw allies
  For(r₅,1,{L₁}ʳ)
    Plot1({r₅*8+L₁+2-8→r₆}*8,{r₆+1}*8,Pic0T)
  End
  .Draw enemies
  For(r₅,1,{L₁+258}ʳ)
    Plot1({r₅*8+L₁+258+2-8→r₆}*8,{r₆+1}*8,Pic0C)
  End
  .Update screen
  DispGraph
Return

.Pathfinding check tile
Lbl PCT
  {→r₄}-r₃
Return

.Pathfinding check left
Lbl PCL
  Dsub(O1) or (D-1sub(PCT))
Return

.Pathfinding check right
Lbl PCR
  D+1sub(O1) or (D+1sub(PCT))
Return

.Pathfinding check up
Lbl PCU
  D<ᴇ800C or (D-12sub(PCT))
Return

.Pathfinding check down
Lbl PCD
  ᴇ8053<D or (D+12sub(PCT))
Return

.Pathfinding check characters
Lbl PCC
  .For each enemy character
  For(r₄,1,{L₁+258}ʳ)
    .If occupying current tile
    !If 258sub(O0)
      .Tile cannot be traversed
       Goto PCF
    End
  End
  .Tile can be traversed
  1
  Return
  .Pathfinding check fail
  Lbl PCF
Return

.Optimization 0
Lbl O0
  {+(r₄*8)+1+L₁+2-8→r₅}*12+{r₅-1}+ᴇ8000-D
Return

.Optimization 1
Lbl O1
  -ᴇ8000^12=0
Return
Title: Re: Tilemap AI algorithm?
Post by: Aichi on November 11, 2010, 12:37:36 am
@ Runer
Thanks very much for this effort, Runer. I cant take a closer look on it, since I have to go to school now.
It seems to be very helpful. I just hope it handles path calculating on a 20x20 map fast enough.
Do you already implement target finding? I am looking for a target finding routine, that find the nearest green point.
But the important thing is not the distance. It are the fields that would be needed to reach the target,
so the enemy on the attached image should focus the dark green point, not the light green one.

@ Qwerty
It looks great, too. Hope you also post your source.

@ DJ Omnimaga
The map attached on the first post is not the only situation the AI has to solute.
In the real game the red point is elswhere, the green point too, and on different maps.

Title: Re: Tilemap AI algorithm?
Post by: DJ Omnimaga on November 11, 2010, 12:38:23 am
Ah I see, so depending of different situations, the NPC will move differently?
Title: Re: Tilemap AI algorithm?
Post by: AngelFish on November 11, 2010, 01:17:33 am
@ Qwerty
It looks great, too. Hope you also post your source.

It's working, but the target finding isn't quite as good as Runer's. I'd just go with his.
Title: Re: Tilemap AI algorithm?
Post by: Runer112 on November 11, 2010, 01:27:12 am
Here is a screenshot I whipped up with lots of debug output. It's a great learning experience to watch how I did it. You can follow along with the screenshot with my explanation below.










(http://www.omnimaga.org/index.php?action=dlattach;topic=5251.0;attach=4392;image)
  • AI 1 finds closest target, avoiding walls and other characters (stage 0), using flood fill method.
  • AI 1 backtracks path by repeatedly finding a square with a value of 1 lower than the current square until reaching 1.
  • Backtracking is recorded starting at 8 squares away (tile value 9, because the counting system is offset by one).
  • AI 1 moves 8 tiles.
  • AI 2 finds a path and backtracks it, but only moves 2 tiles.
  • AI 3 cannot find a path to an enemy in stage 0 so...
  • Change to stage 1, in which AI is allowed to make paths over other characters. This still fails, so...
  • Change to the desperation stage 2, in which AI is allowed to make any path without collision.
  • AI 3 knows it cannot reach a target, but gets as close to a target as possible.
  • <END OF TURN>
  • AI 1 cannot find a path, as the only route is blocked by another character.
  • Change to stage 1, in which the path is allowed to cross over other characters. A target is found and backtracked, but...
  • The path is reset where it hits the other character, so AI 1 doesn't walk right through AI 2.
  • AI 1 follows the path that was reset to end at the other character.
  • AI 2 and 3 move predictably.
  • <FAST FORWARD>
  • AI 1 cannot reach the target that is closer linearly because the path is blocked, so it keeps searching and finds a further target.
  • AI 1 moves 8 squares towards its target.
  • AI 2 moves next to a target.
  • AI 3 fails.
  • <END OF TURN>
  • AI 1 finds a path of only 1 square to a target, so stops searching. AI 1 moves 1 square along that path of a possible 8 it could move.
  • <EVERYBODY IS DONE>



@Aichi:

(http://www.omnimaga.org/index.php?action=dlattach;topic=5251.0;attach=4393;image)

Give me a 20x20 map with multiple player and AI characters that I can test it on ;)

EDIT: The algorithm scales easily to a 20x20 map. It may take upwards of 5 or 10 seconds for each AI character to make a move, but it works.
Title: Re: Tilemap AI algorithm?
Post by: DJ Omnimaga on November 11, 2010, 01:36:58 am
Woah! That's nice! I'll have to bookmark this post to read it later when I am feeling more sane to read lots of stuff. It seems like you made it as visual as possible, too, so I might be able to understand. :)

EDIT: Oh an edit. ^^
Title: Re: Tilemap AI algorithm?
Post by: Aichi on November 11, 2010, 12:34:31 pm
Wow, thanks! This is exactly that what I need. :o
Up to 10 seconds sounds kinda much (Btw: 10 Secs on 6Mhz, correct?), though. I will make sure I dont use too big maps with too many enemies. I cant test it for now, since I have to plan at first the development next days.

Edit: It seems to have trouble as an application and my game is going to be an app.
Title: Re: Tilemap AI algorithm?
Post by: jnesselr on November 11, 2010, 07:06:49 pm
Can you post the program source for that so I can study it? Thanks!
Title: Re: Tilemap AI algorithm?
Post by: Runer112 on November 11, 2010, 09:33:04 pm
Can you post the program source for that so I can study it? Thanks!

I posted the source for people to look at on the first post of this page, here (http://ourl.ca/7848/139445).


Wow, thanks! This is exactly that what I need. :o
Up to 10 seconds sounds kinda much (Btw: 10 Secs on 6Mhz, correct?), though. I will make sure I dont use too big maps with too many enemies. I cant test it for now, since I have to plan at first the development next days.

Edit: It seems to have trouble as an application and my game is going to be an app.

It uses a pretty slow flood filling algorithm currently that takes up most of the time, I'm sure I could optimize that to run a lot faster. As for incompatibility with apps, that's because I used 768 bytes of internal storage for the map buffer. This could be avoided by allocating a 768-byte appvar for the map buffer storage and storing the map there instead.
Title: Re: Tilemap AI algorithm?
Post by: jnesselr on November 11, 2010, 09:40:03 pm
Can you post the program source for that so I can study it? Thanks!

I posted the source for people to look at on the first post of this page, here (http://ourl.ca/7848/139445).
I meant one with the numbers. I think it would be better with the numbers to learn from. Plus it's cool to watch. ;-)
Title: Re: Tilemap AI algorithm?
Post by: Runer112 on November 11, 2010, 10:31:00 pm
Oh, ok. Here it is, but it's horridly unoptimized because this is only for testing purposes and I just copied and pasted large sections of code around. I think the tilemap displaying code exists in three places now.

Press enter to start the AI's next turn, hold any key to fast forward.

To alter the map (currently only supports tiles being 0s or 1s), change the data stored into GDB0M. To change the player character data (what the AI targets, called "Ally data"), set the number of player characters appropriately in the ∆List(nʳ)→GDB0A line and then add 8 bytes of data for each character. Byte 1 = x position, byte 2 = y position, byte 3 = max move distance, and bytes 4-8 = unused, but fill in data here anyways. The AI character data is formatted exactly like the player character data, but is labeled "Enemy data" instead.
Title: Re: Tilemap AI algorithm?
Post by: jnesselr on November 11, 2010, 10:33:44 pm
Thanks! I will try that out tomorrow.
Title: Re: Tilemap AI algorithm?
Post by: ztrumpet on November 11, 2010, 11:09:54 pm
Wow.  This is very impressive.  Wonderful job Runer. :)