Procedural Artificial Intelligence

Platform: Itch.Io

An infinitely procedural and adaptive medieval world

Back to Projects

Play on Itch.Io

Immerse yourself in this 2D simulated environment as each agent utilises a dynamic behavioural hierarchy blended with individual state machines to evolve, expand, and help prosper their own small Kingdom.

To play the completed version of this project check out The Throne.

Project Overview

During the capstone semester of my MSc I had the opportunity to create an abstract project that showed off the abilities learned throughout the academic year, later being used as an introduction to my thesis in helping visualise and explain my intentions for a larger scale project. For my thesis I'm excited to add some gameplay focused elements, the goal being to figure out what makes AI enjoyable to interact with, but before I get too ahead of myself I want to break down this project and cover some notable points from its development.

Throughout the initial planning phase for this project my first steps were focused on establishing a strong core loop for the kingdom's progression, splitting the world in two parts - agents and hive-minds. Each agent receives actions from observing the environment, utilising their individual state machine to dictate their decisions. The hivemind then decides what these decisions will be, prioritising various choices depending on that kingdoms many needs and acting as the core decision maker for this world's expansion.

The application then joins these agents and hiveminds and forces them to interact through three core actions - building, gathering, and fighting. This project focuses on allowing the AI to take from the environment and give it back in a very literal way as each agent slowly but surely colonises and expands their influence over the observable world.

The Setup

Before discussing the AI, I'll briefly break down the two core components that allow the game to function as it does - the pathfinding and procedural generation. By creating a simple 2D grid array I could attribute variables by setting walls, removing walls, and lastly checking walls. This was easily adapted as I looped through each x and y position, before instantiating a grass, tree, bush, or water object on each position.

private bool[,] Wall;
private bool[,] Road;
public Grid2D (Vector2Int size)
	// Automatically initialised to false:
	// Loops through each point and sets it to true based on position.
	Wall = new bool[size.x, size.y];
	Road = new bool[size.x, size.y];

Next I focused on implementing the procedurally generated environment, looping through each point in the grid and placing the resources based on a random number generator. There were also some external restrictions such as preventing resources from spawning in the centre and creating realistic water placements, but to view them yourself simply run the application through the link above.

for (int y = 0; y < gridHeight; y++)
	for (int x = 0; x < gridWidth; x++)
		// Bushes = 8%, Ores = 3%, Trees = 4%, Water = 1%
		Transform Plane = Instantiate(plainPrefab) as Transform;
		Plane.position = new Vector2(x, y);
		Plane.parent = this.transform;
		Plane.name = x + "," + y;

Both of these techniques, as well as some more technical breakdowns, can be found on my blog in much greater detail.

The Economy

The next step to creating this AI was through the world's progression, implementing a sort of hive-mind to keep an eye on the core values, before deciding on which focus should currently be the priority and passing it on to the agents, allowing the world and economy to expand.

The four main resources that run this kingdom are Religion, Public, Military, and Gold, each of these attributes controlling how and when the kingdoms priorities get updated based on numerous in game factors. For example, if the kingdom notices too many of its units are dying, it will prioritise making a blacksmith to strengthen their stats, if it notices the kingdom requires gold, it will make more farms, the perfect kingdom managing to keep each of these attributes balanced to prevent any one avenue of play dominating the other.

These checks, rather than override and dominate the AI’s individual needs, simply add to their schedules and allows each agent to decide which task requires their immediate attention based on their independent variables and determining which condition to carry out and prioritise inside each unit's individual scripts.

The AI

We can now finally focus on creating the individual AI, using each of the pre-existing mechanics to replicate individual personalities and decision-making abilities. As a disclaimer, this project was created in Unity rather than Python or Unreal simply due to my level of comfort and if approached on a much larger scale, much like my upcoming thesis, might be worth reconsidering the Engine.

When designing and later implementing AI, it's important that each action remains distinct and clear for the player observing, certain avenues and shortcuts being required to maintain each player's magic circle and create an enjoyable player experience. All code for this project can be viewed on the GitHub link below at the directory - ...Behavior-Trees/tree/main/CW2AI/Assets/Scripts/AI - and shows the implementation in greater detail.

View Github Files

The goal for this project and its use of fuzzy logic was to ultimately replicate how a human would react in a similar way, though in much simpler terms. For example, the King understands that the kingdom requires more gold. The King has numerous decisions they can make, but in a binary sense that can simply translate to:

if (Gold <= 75)
	Unit.Schedule.Add("Create Farm");

However, this betrays the point of studying and breaking down intelligent AI - rather than create such binary rules, we can instead implement numerous values that calculate elements such as the economical weight, distance from goal, and lastly what the AI did prior, then start branching and replicating human-like behavior. It's incredibly interesting to observe how humans interact with simple decisions in the real world, the basic question of "should I go eat?" varying wildly due to time, schedules, and laziness. It's these branching choices that make this topic of study interesting, and is what I tried capturing with this project and later my thesis.

Below is an example of what a similar behavior tree might look like with the external fuzzy factors in very basic code:

if (!Unit.onSchedule)
	if (Gold >= unitCost && Random.value > 0.5f && Public <= 75)
		Unit.Schedule.Add("Create Unit Worker"); 
		Gold -= unitCost; Public += 25;
	// Else if Public is above Military, create Military Unit.
	else if (Gold >= 40 && Random.value > 0.5f && Public > Military)
		if (Random.value > 0.85f) Unit.Schedule.Add("Create Unit Scout");
		else Unit.Schedule.Add("Create Unit Knight");
		Gold -= 25; Public -= 35; Military += 25;

It's this level of intelligence and both strategic and reactive behaviour that makes for an intelligent AI agent, and allows the world to both expand whilst allowing each individual unit that level of distinct, realistic control over their environment and world.

All of these elements then function together to create this procedural artificial intelligence and, once sped up, shows the evolution and natural expansion of the world in intriguing and vastly distinct ways. There is currently no win or lose condition but upon losing your King the game slows down and requires a reset to witness a new iteration of the world.

I hope you enjoyed watching and reading about how this world builds up as much as I enjoyed creating it. Make sure to give The Throne a try if you wish to see this project at its full potential!

Back to Projects