The game is playable on itch: https://fowl-machinations.itch.io/monolithic
Monolithic is a real time strategy game where the player commands a pantheon on gods and followers. Use abilities to kill your foes and conquer settlements. Be careful, however, because your enemy will be trying to do the same to you. Test your skills in single player against AI. Once you’re ready, you can take on a real player.
There are three (3) main parts to each game of Monolithic: monoliths, followers, and settlements.
Monoliths are controllable units that have abilities. Currently, there are five (5) different monoliths in the game, each with three (3) unique abilities. Monoliths use abilities to control the battlefield and take down your enemy.
Followers are spawnable units that attack settlements or enemy followers.
Settlements act as a safe haven for your monoliths. They are points of interest for monoliths to attack. Friendly settlements can be used to spawn followers, and can grow in population to make it harder to attack.
What Did I Work On?
I joined the team for the second semester to work on AI. I decided to use my favorite type of AI called Utility.
To make it easier to work with, I created a comma separated value (csv) reader. This acted as a tool for designers to create scorers for the bots, and by those different scorers the bots would act in unique ways.
A UtilityAction is a set of data that holds scores, probabilities, and arguments for test functions. These default values get changed when their set function gets called.
UtilityTestManager is a manager class that holds all the tests that each Utility can use. This is one example of a test that gets input from a bool parameter. The monoliths are known ahead of time, so there is no need for putting each one into a .csv. However, I do not know how each test will get executed without a bool saying if I want to test if a.Durability is below or above b.Durability. This can be as much as 3 different values that get passed in from the .csv.
The Utility class holds the main Update for each AI. It is a MonoBehavior so it can get attached as a component to the AI prefab. It starts with resetting the score on all the tests. After this, it goes through and performs each test in tests. Then, it creates a list of actions based on the score of those tests. Later, it chooses an action based on an algorithm called WeightedRandom. Assuming an action gets chosen, it performs the given activity based on the chosen action.
This is the bread and butter of Utility. This is ultimately what decides the actions the AI takes each update. It starts with eliminating all actions with a score of 0 or less. Then, it sets the probability of each remaining action based on its score. To make it human-like, and so it doesn’t always do the same thing every game, this algorithm chooses a random number between 0 and 1. If that random number is less than the probability of the current action, the current action gets added to a list of potential actions. After all that, the potential actions get randomized, and a single action gets returned.
The UtilityBrain class is a manager class for all AIs in the scene. Obviously, the previous function, Weighted Random, can be expensive if it has a high iteration set. This Update in UtilityBrain iterates on a timer for each AI to update. This drastically reduces the cost of the Weight Random function because it only ever updates every second instead of every frame.