Gamblin (Genetic) Gladiators. Why Genes? How Genes?


The Genes behind Gamblin Gladiators is another step on my quest to figuring out how to make a game with evolution.

I've always been fascinated by genetic algorithms and evolution, and recently helping out on @lunarsignals  dicey TTRPG. So GG became an intersection of those interests. The plan was to implement a combat system and use a genetic simulation to find the optimal matchups and team comps inside that system. Teams would be taken out of that genetic pool and matched up in brackets or 3v3 face-offs and the player would sus out the winner. As the player places bets they would build superstitions or maybe even learn about what makes a good team.

I was inspired by FF XII Gambit system when I designed these fellas' brains. Their brains are full of phrases like "if anyone is below 11HP, Attack the enemy with the least health." Each gladiator simply does whatever their first if-then statement directs them to. I love how easy this approach is to explain via UI, without sacrificing a complex range of behavior. In contrast to something like a tiny neural network that is popular among other genetic brains: those can be extremely flexible, but very difficult to predict behavior just by looking at the brain. Gambits, in theory, would allow you to figure out how a Gladiator might act before it does.

I went with a genetic simulation because I was hoping I could see some sort of emergent behavior out of these teams. For example a healer, healer, mage team evolves to protect the one glass cannon spellcaster. Evolution is particularly good at finding these types of unexpected combos. And on top of that, it does it all more or less automatically: so I used it as a tool to check the balance of weapons, classes, and spells! I spent a good amount of time tweaking weapon damages, running the simulation, then checking if more or less gladiators use that weapon. If everyone ends up with a hammer, I'd nudge the hammer damage down a bit, rinse and repeat until every weapon is represented in some way. The final outcome came out more-or-less balanced but there are still some definite winners and losers

What went well

- Super happy with the combat animation sequencing. Definitely going to use a code-first async/await/DOTween approach again.

- Getting to evolution simulation early was extremely motivating to me

- Gambits were quick to set up

Whats different next time

- I could have seen a playable game loop earlier :'). An age old advice. I started iterating on the game loop itself right around the 15th, more than 2/3rds of the way through the jam. Before this point I was tweaking evolution and combat config.
- The Gambit setup worked well but can be refined. There is still a conflict between giving the gladiators more flexibility and expecting the player to understand what they're doing. In GG, Gambits are all mostly preconfigured and each gladiator picks their favorite 3 out of a big list based on their genes. I'd love to figure out a way to allow full customization of Gambits in a way that is simple for players to understand.

Milestones

I collected a few artifacts and notes from the development process below:

First team fight - 18 days remain

The first team fight was pure code. I had just got the basics of combat working: melee weapons, gambit "brains", and death. All the teams were completely random at this point but still managed to eventually kill each other. Following are some of the combat logs from this phase. Sable is using their pocket to their advantage: taking high numbers out to succeed, and placing high numbers in when they aren't able to otherwise pass the check.

[          Sable HP 00/04 PKT 3 DEF 06] Rolled 2 dice: [D6[1], D6[5]]
[          Sable HP 00/04 PKT 1 DEF 04] swapped D6[1] into their pocket, taking out D6[3]
[          Sable HP 00/04 PKT 1 DEF 04] Healed [      Spartacus HP 04/04 PKT 3 DEF 06] by 4, increasing health by 4
[         Rubble HP 02/10 PKT 4 DEF 09] Rolled 2 dice: [D6[2], D6[3]]
[         Rubble HP 02/10 PKT 4 DEF 09] Dealt 3 Mid damage to [          Sable HP 00/04 PKT 1 DEF 04], reducing health by 0
[          Sable HP 00/04 PKT 1 DEF 04] Rolled 2 dice: [D6[3], D6[3]]
// Sable cannot win the DC check here, so they use their dice to upgrade their pocket from a 1 to 3
[          Sable HP 00/04 PKT 3 DEF 06] swapped D6[3] into their pocket, taking out D6[1]
[      Spartacus HP 00/04 PKT 3 DEF 06] Rolled 2 dice: [D6[3], D6[2]]
[      Spartacus HP 00/04 PKT 3 DEF 06] Dealt 1 Min damage to [       Aurelius HP 00/11 PKT 4 DEF 09], reducing health by 1
<etc>
[          Sable HP 00/04 PKT 3 DEF 06] Rolled 2 dice: [D6[1], D6[5]]
// Sable now uses the upgraded pocket to succeed this DC check
[          Sable HP 00/04 PKT 1 DEF 04] swapped D6[1] into their pocket, taking out D6[3]
[          Sable HP 00/04 PKT 1 DEF 04] Healed [      Spartacus HP 04/04 PKT 3 DEF 06] by 4, increasing health by 4
Encounter completed with result: SideBSurvives

Gotta Go Fast - 15 days remain

In order to simulate evolution I knew I'd need something that could run rounds of combat very quickly. I spent a couple days crunching down the runtime of a combat round to around 400μs per combat or 20μs per turn. In Unity, I found this basically meant removing as many object allocations as I could. Here's a before/after screenshot of the profiler:


GRAPHS - 14-5 days remain

I set up some janky tools to help evaluate the simulation as it ran, spitting out various graphs. This is the first graph that showed me real evolution was happening! Each line shows the average of some value over the entire population. Right between generation 150 and 200 a sudden change occurs which reduces how many bows are in the population while increasing the number of swords. This shows a new mutated team which traded an archer for a knight taking over the whole gene pool!


Here's another graph. This graph was a way for me to determine if the teams were actually getting any better or just changing randomly without actually improving. More details in the skeet:

This is another interesting result. In this graph we can see around generation 13000, the "Has Wizard Blast" line jumps up. At the same time, the green "ARC" line jumps up. Wizards are much more effective when they have more ARC so this team may have resulted from a multi-point mutation: mutating into Wizards and adding ARC at the same time.


Files

GamblinGladiators_Android_v1.0.0_submission.zip 46 MB
3 days ago
GamblingGladiators_v1.0.0.zip Play in browser
3 days ago
GamblinGladiators_Win_v1.0.0.zip 45 MB
3 days ago

Get Gamblin Gladiators

Leave a comment

Log in with itch.io to leave a comment.