Welcome to the first march devlog!
This time we're looking at getting the game to control combatants in combat - this is going to be a single player game, so of course this is an essential step.
A quick note on terminology: all throughout my life, we used to call this kind of programming Game AI. Or we'd say that the enemies in the game were AI-controlled. But these days, I think many will associate the term AI with deep learning algorithms. Just to be clear, what I'm doing here is not related to deep learning or chat bots.
So I started this period by reading a bit about different techniques. I was initially trying to implement something called Goal Oriented Action Planning, which is a way to make your decision-making agents in your game work toward a goal or a series of prioritised goals. However, in the end I decided that this technique doesn't work for our purposes - instead of trying to accomplish a single, potentially distant goal, we want our agents to get the most out of each turn.
So we made our agents look through all the possible abilities they have and see which one will give the most value. To explain how the system works, let's look at this example:
We've zoomed out a bit and labelled the teams to show that the goblin is on team 1 and that the human and the elephant is on team 2
In this example, the goblin has 2 abilities: A stab which does damage to a single adjacent enemy and a Set Fire ability, which puts fire on the ground in 2 adjacent tiles. In this example, we'll focus on the Set Fire ability since it targets 2 tiles
First we determine that since the Set Fire ability costs 2 action points, and the goblin currently has 4 action points, the maximal distance the goblin could move and also use the ability is 2.
To make it more clear how the algorithm works, we've drawn on the screenshot. We've drawn in red the tiles within distance 2 of the Goblin. These are the tiles we think the Goblin could possibly move to and still use the ability.
Next, we look at all the possible targets and estimate how much value we'd get from hitting each target. The Set Fire ability prefers to target tiles with opponents on them, so we'll see if it's possible to hit them. Let's start with the elephant tile. In order to hit this tile, we need to be adjacent.
We've drawn in blue the tiles that are adjacent to the elephant. We see that there is an overlap, so it is probably possible to move to the elephant and use the Set Fire ability.
Next up, let's see if we can also hit the tile with the human. In order to hit them, the goblin has to be adjacent.
On this screenshot, we've drawn the overlap from before in red. The tiles adjacent to the human are drawn in blue. We see that there once again is an overlap, so it is probably possible to move to a tile where the goblin could hit both targets
Now we have found a tile where we can hit both targets. We use
A* pathfinding to find a path to the tile, which is the same algorithm we use when the player clicks a tile to move there. If we successfully found a path, we save that whole action (Both the movement and the using of the Set Fire Ability) along with the estimated value of hitting the two targets.
Then we do the whole thing again with the Stab action.
Once we have found potential targets for each action and calculated the value, we pick the action with the highest value and execute it. Then, if the Goblin has more action points left, we repeat the process.
Another thing I'd like to mention is that the way we calculate values for different effects: Applying Ground effects to the tiles or applying passive effects to combatants has a set value depending on the effect. So for example, if we have an ability with a powerful effect (like a charm effect that causes an opponent to temporarily switch sides) we could give that a higher value than a less powerful effect.
For damage effects, we estimate how much damage the effect would do in some different scenarios. The goal would be that if we in the future add ways to mitigate certain types of damage (like some characters having fire resistance) then the agents should be smart enough to know to not target those characters with that type of damage.
Finally, we did manage to add a feature that we left over from last time: It's now possible for abilities to summon combatants. To celebrate I've given our example human a Summon Rat ability
The Rat is added to the turn order, but not in the same round it was summoned
I hope you liked this devlog, even though it might be a little longer and more detailed than previous ones.
Next up is our last combat focused period. When I did my planning, I added an extra period as a buffer. That's a good thing, because there is a number of features that I didn't have time to implement in the previous periods.
The second March devlog will be on March 28th. Talk to you then!
A well thought out approach. Nicely done 👏🏼.
ReplyDeleteThat rat hand is hilarious well drawn 😂🔥
Great stuff, can't wait for the next one.
ReplyDeleteDon't mind the rat hand - it's the face that'll get you!