AI and Games Jam 2021


“Ants” is a whole multitude of firsts for me - my first game, period. My first game jam submission. My first endeavor to earn even the smallest amount of money! In this devlog I’m going to dive into the process of creating this work of passion, as well as some of the things I’ve learned along the way.

The Story

Impetus

When the AI and Games Jam 2021 was first announced I immediately signed up. I’d wanted for years to design and build a game and had even started a couple projects here and there. But I had a feeling that a game jam with a tight-but-longer-than-usual schedule would be the perfect way to really get myself to do it. 7 days? I could manage that.

I’d messed around with XNA a lot back in high school and could still remember quite a bit of how it worked. While XNA itself has long since been defunct, the MonoGame framework lives on and implements a very very compatible environment. A few times I’d picked up some lower-level frameworks (OpenTK.NET, for example) and even higher-level frameworks (Unity), but nothing hit the spot like XNA/MonoGame did.

Design

Ok, so I have a framework. Now what am I going to build? Being that the jam is hosted by AI and Games, one of my favorite YouTube channels, the focus is of course on making an interesting video game AI. I toyed around with a lot of ideas, but in the end a good old “ant sandbox” seemed like something I could accomplish in the time allotted. All kinds of ideas flew around in my head leading up to the jam start date:

  • A general sandbox-style game where there are no rules, just remarkably simple ant behaviors leading to beautifully complex emergent colony behaviors.
  • Dozens, no, hundreds, even thousands of ants!
  • Intuitive and simple controls to allow players to control their colonies.
  • Enemy AIs with different “personalities” based on a simple mix of traits.
  • Generative level goals along multiple archetypes and increasing in difficulty as levels progress.
  • Ant traits that can be upgraded as you level up.
  • Generative level design with multiple terrain types, assets, and (dis)advantageous features.
  • Buildable structures such as more anthills, food stores, or walls.
  • And so, so much more.

Wrench in the Plans

“Breaking the Rules”. Wow, what an abstract theme! As soon as the jam started my hopes were immediately dashed. I had put so much thought into a sandbox game with no rules. And now I had to somehow make my game “break the rules”. Honestly, at this point I considered giving up entirely, and spent several hours brainstorming just how this would even work. Eventually I decided to wade in and just start programming. I hand-drew some really ugly sprites and gave it a go.

Original Ant Sprite (with added background and resized 5x) Anthill Sprite (with added background and resized 5x)

Within a couple of hours, I had working “entities”! They didn’t do much - ants just wandered around the screen and anthills did nothing at all. But hey, they were there. And by day 2 I had a lot more working, improved my sprites (less is more), and had finally figured out what to do about that pesky jam theme…

Overcoming Adversity

How do you break the rules in a game without rules? This was a real head scratcher, but eventually I decided that the player or even the game itself doesn’t have to break any rules, at least no rules that are encoded into the gameplay. Ants are an existing, real-life thing, and in real life they have easily anticipated behavior. Ants build anthills, gather food, and sometimes go out on the warpath against other ants. Beyond that there’s not that much to it.

So what if the enemy ant colonies “break the ant rules” once players get to higher levels? Imagine an ant teleporting, or building a missile silo, or… So many possibilities! Making the game more difficult as levels progress merely through scaling of goals gets boring after a while - so why not add some diversity to the challenge?

Ant Thoughts?

In the End

In the end I wasn’t able to implement many of the features that I had intended to. Most notable I ran out of time to implement non-player colonies controlled by game AI, which is very disappointing since that was the whole point of the game jam! Additionally, I was unable to implement “breaking the ant rules”, as there are no enemy AI.

I stop-gapped the playability of the game by adding a special “sandbox” mode where the player is free to place any of the in-game items, including a partially implemented “fire ant” species that will attack the player’s anthills (though there is no “defend” AI, sadly). I even added an easter egg specific to the aiandgames jam!

Overall, I do think the game as a whole is a success - the simple AI used by the players’ ants produces remarkably interesting emergent behavior for the colony overall, and I’m satisfied that at the very least the game is interesting and maybe - just maybe - even a little fun.

I do have plans to finish the game after the jam is over, so stay tuned!

The Tech

Design Decisions and Optimization

This is probably my favorite part of Ants, because by putting in some thought ahead of time on how to write a performant game that can display and process 100k entities at once I was able to save myself a lot of time later by not having to refactor and optimize code over and over to get over different performance barriers.

The first design choice I made was not implementing different classes for different entities. In fact, there are only two types in the game: Antity and Thing (and the only difference between the two is that Things don’t have logic to update every game tick - “Food” is currently the only Thing in the game). All of the logic used to make entities behave differently is stored in the main game code, saving precious function calls and lookup table overhead. Each Antity is a struct storing basic information about itself - such as what type of Antity it is, and its position on screen.

The second design choice I made was avoiding allocation where possible. All of the entities in the game are stored in a single array: Antity[MAX_ANTITIES], where MAX_ANTITIES is currently 100,000. Things are stored similarly, and going forward when I talk about the Antity array the same mostly applies to Things as well. Because Antity and Thing are both structs (stored by value and not reference) it is easy for the CPU to efficiently cache both as the update and render code iterates over the arrays. A bonus to this design is that it’s really easy to efficiently iterate over, and even easier to optimize this iteration. Both arrays have an accompanying BitArray(MAX_ANTITIES) that descibes whether a given array index is actually being used - this means that in my looping code I can easily if (!_antitySet[i]) continue; to efficiently ignore entities that aren’t allocated. Additionally a “trim” function runs once per second that iterates over the array in reverse and identifies the index of the rightmost allocated entity in the array - this is then used to preemtively shorten any drawing/updating loops: for (var i = 0; i < _rightmostAntity; i++). This value is similarly updated when new entities are inserted (if it is done at the end of the array).

Finally, I made use of the [MethodImpl(MethodImplOptions.AggressiveInlining)] attribute so that I could logically split out my drawing and updating code into multiple functions without the overhead of a method call. I also used this attribute on many helper functions for finding entities or items by locality, or when the player clicks on the screen - the inlining makes the compiled code larger, but faster.

“AI”

The ants’ AI is very, very simple: ants are either:

  • Idle, in which case they wander the map aimlessly waiting for jobs
  • Working a Job, which is one of:
    • Gather, in which case they collect food from Food items (either the nearest or specified by the job) and deliver it to the nearest anthill.
    • Distribute, in which case they collect food from the anthill with the most and deliver it to the anhill with the least.
    • Attack (only used by fire ants currently), in which case they attack the nearest non-player anthill, decreasing its food score to 0 at which point it disappears.

Get Ants

Download NowName your own price

Leave a comment

Log in with itch.io to leave a comment.