Okay, I’ve procrastinated enough. I’ve been trying to handle all of these other things (which are important), but at the end of the day, it’s all lead up to this. The first implementation of artificial intelligence in this game.
And god damn, what a start to it all.
I knew I wanted to start out with the most basic A.I., and move on from there. When I mean basic, I’m talking about just having the enemy units move towards the ally units, kamikaze style. There’s no regard for what will happen to them, they just find the nearest opposing faction unit, and move towards them. Nice and easy. Or, so I think everything is when I sit down to start implementing it 🙂
Forgetting about the actual code structure, which I’ll come back to at another point, I just wanted a quick and dirty implementation of having the enemy make their way towards the player. Well, I did create an AIManager class, but it’s just a spider web of a bunch of functions at the moment.
First thing I had to create was a function that would find the nearest enemy unit. That was easy enough, and I was able to code that function within minutes. Next came my first sort of stumbling block. The idea was, once the target was found, an appropriate tile next to them had to be found. My first solution was to build a collection of all the tiles that the unit could move to. From there, I would calculate the distance between each tile in that collection and the tile that the nearest enemy was standing on. Once I found the lowest, that would be my target tile to move to.
From there, I would make use of existing code to actually find a path to the target, then move them there.
See results below:
I immediately realized there were issues. If you look closely:
The 1st enemy is making their way to the nearest target (the teal character), but then pulls up. Why?!
The 2nd enemy starts moving south, but then starts cutting south-west, instead of proceeding over the desert bridge.
The 3rd enemy is confused as shit and does nothing.
The 4th enemy seems to know what is going on.
After a bit of debugging, it was pretty clear that the issue was that while I have built in the logic to not highlight un-walkable tiles, or have the pathfinding ignore said un-walkable tiles, this same logic was not used when finding the right target tile before a move. For instance, with the 2nd enemy, they’re clearly not thinking about the water, so they think that the fastest way to the target is by heading south-west, instead of realizing that it’s not worth the time, and that a better path needs to be found.
Then I had an epiphany!
Why in the hell was I trying to write logic to find a target tile, when I sort of already had that done in my Pathfinder class?! Sure, there were some minor differences, the biggest one being that the Pathfinder class requires the source/final target tiles, and if the target tile cannot be reached, it returns nothing. In this case, the enemy won’t be able to reach the target in one move, which is why I’m going through this work to determine the best tile to move them to, a tile that’s closest to the target.
Then I realized that I could just pass in the final target’s tile to the Pathfinder class, then once the path was generated, I could remove all tiles from it that the enemy actually couldn’t reach. That would give the shorter path I needed, while maintaining the core logic of the path generation.
See results below:
Tomorrow, I’ll need to take this spaghetti code, and refactor the shit out of it. From there, I’ll start working on some other basic AI templates. Maybe a unit that won’t move towards you until you’re within range. Or maybe a defender unit that follows around a leader. The options are limitless!