A Gift in Good Faith - Minotaur AI Breakdown

A Gift in Good Faith was our first game to really implement AI, so it was my first experience making it. In this post, I’ll walk you through how the AI for the Minotaur in the game works.

GameMaker Studio 2 has built-in pathfinding, so that aspect was sorted already. However, the way it works is a little strange: GameMaker has assets called “paths”, which are lines from point A to point B with various turns on the way. The built-in pathfinding outputted a single path to use. Unfortunately, this wouldn’t work if I wanted to have the Minotaur constantly follow the player, as since each path started and stopped individually, it would quickly fall out-of-date once the player moved.
The solution to this problem seemed simple; I could just recalculate the Minotaur’s path every frame so it always tracked the player’s current position. However, this created a strange effect in the movement - see if you can spot it:

It’s very distracting and looks off. The solution wasn’t too difficult, though. To explain it, I’ll first have to explain how the map is parsed by the Minotaur.
GameMaker doesn’t automatically let you pathfind around tiles; it makes you input “cells” first, which are points on a grid. I decided that my cells would be 2x2 tiles wide, as it feels much less cramped when playing.
These cells could be automatically created, but only for objects. This posed a problem, as I was using tiles for this game. My solution was to automatically generate instances based on the tiles:

The opaque tiles are cells the Minotaur has decided are walls (so ones with any amount of tiles), and the transparent ones are marked as “safe”. The latter was necessary to implement for the solution to the strange movement.
By the way, cells not filled with wall tiles being seen as walls by the Minotaur can lead to fun moments like this:

Anyway, the solution to the strange movement was to only recalculate the Minotaur’s path when the player steps on a new “safe” cell. The Minotaur would then pathfind to the center of that cell, ensuring it doesn’t try to move off its grid. This eliminated the movement bugs.
Next up was to add the flares, which work fairly simply. If a flare is on the ground, the Minotaur will pathfind to it instead of the player, and wait there for 10 seconds. The game also has support for multiple flares, as originally, you were going to have multiple. This came in handy for the player’s other main ability.

Pushing the minotaur away (or the "shockwave", as it was called internally) actually uses the flare code. When used, it places an invisible flare a few tiles behind the Minotaur, causing it to pathfind to it. This “flare” only lasts 3 seconds, and is not collectable upon being dropped. Reusing this code rapidly sped up development, and was responsible for this mechanic being in the game at all.

That’s my breakdown of A Gift in Good Faith’s AI! The Minotaur, being the first complex enemy AI I’ve had to code, was a new experience for me, and it's been very interesting to learn how this side of game development works.
I hope you enjoyed the post, and if you haven’t already, you can play the game here: https://ldjam.com/events/ludum-dare/49/a-gift-in-good-faith

Thanks for reading! :)