Who wants an insight into the debugging process? Nobody? Well you’re getting one anyway.
‘Meatpiling’ was a survival strategy, caused by a bug which was fixed in hotfix 3, where hundreds of giant carnivorous blobs would converge in a small location and survive by eating each other. The name comes from the gigantic corpses that served as the food source for the entire mass. It was a horrific conglomeration of living and dead biomass: the pinnacle of evolution!
Logically, this shouldn’t be possible. Carnivores can’t get energy without eating herbivores, who in turn can’t get energy without eating plants, but The Mass was almost entirely carnivorous, and stationary. There was no way should have been able to feed itself, yet it was such a viable survival strategy that almost every simulation seemed to converge on this end result. The logical conclusion was that there was a bug in there somewhere.
And thus began the bug finding endeavour, a heroic tale heroism and courage, uniting the world and saving the- no okay it was long and boring.
I started by studying the creatures. In addition to being giant fat carnivores with an energy capacity that would rival a medium sized star, they were social and amorous, and had a very high attack damage.
“Aha!” I thought, excited and slightly aroused by the prospect of solving the bug simply by looking at it, “Clearly The Cause Of This Problem Is Attack Damage! Onward, To Victory And Pie!”
My assumption was that when a creature attacked and killed another creature, the corpse was accidentally gaining energy. The logic behind this is simple: when a creature attacks another creature, any health lost is converted to biomass (meat).
Attack Damage = 100
Health Before Attack = 10 Biomass Before Attack = 0
Health After Attack = -90 Biomass After Attack = 100
Since hP is no longer used when a creature is dead, the resultant corpse has 90 more energy than the original creature.
I checked the code for attack damage, and sure enough it was subtracting the full amount of attack damage, without regard to how much was left. So I fixed this by subtracting/adding whichever was smaller of Attack Damage and Total Health, dislocated my shoulder trying to pat myself on the back, and loaded up the simulation just to make sure it was fixed.
Guess what happened next?
After a bit more research, I determined that not only was Attack Damage not the problem, it was never a problem in the first place. You see, when a creature dies, any remaining health and energy is dumped into biomass. So the negative 90 health in the above example was being added to the positive 100 biomass, resulting in a correct value of 10 biomass. My actions hadn’t actually made any difference.
This still left me with a problem: if it wasn’t attack damage, what was it? Where was all the extra delicious meat energy coming from?
I adopted a new approach, one I’ve used in the past. I have a function called “RecalculateGlobalEnergy”, that generates the Mega joule statistic next to the ‘environment’ by adding together all the creatures health, energy, biomass and all the tree, corpse and ground energy. By peppering the game code with this function, turning off photosynthesis, and watching for when the energy content increases, I can spot exactly when positive energy leaks like this one occur (negative energy leaks are harder to find, but are also less dangerous: you can’t make a survival strategy out of losing energy).
This should have worked. It really should have. Unfortunately, things are never that simple.
See, floating point digits can store 7 unique digits. This can be expanded to store numbers with more digits, but you lose precision at the lowest level to rounding errors.
The environment The Mass lived in had an energy content with 8 digits.
This meant that, due to rounding errors, the lower end of the energy content number would jump up and down by a few units, resulting in loads and loads of false-positive increases. Separating the genuine increases from the false ones was more difficult than it should have been.
I experimented briefly with reducing the number by only looking at meat energy, and turning off eating plants entirely. Unfortunately, the number was still more than 7 digits.
So I adopted yet another new approach: reduce the energy content the nasty way. I already had a genocide button (“K”, for anyone wondering), and I went and added some new functionality to clear the corpses (“L”).
For anyone keeping count: by this stage the game runs at less than 1 fps due to recalculating the Global Energy dozens of times each frame, hits a breakpoint a couple of times per frame in debug mode, the creatures can no longer eat or interact with plants, and I was holding down K and L to make them die and erase their corpses from existence.
I managed to get the energy content down to 7 digits and save the map, then I reactivated debug mode. The game barely-ran for quite some time, before hitting the breakpoint with a positive increase of more than 400 energy. Got you.
(And yes, I’m aware I could have filtered out the false positives by only looking for larger increases, but I didn’t know at the time how large an individual increase would be. For all I knew, the false positives were the increases)
The end result: it had nothing to do with carnivory, energy content or attack damage. The energy increase happened during reproduction. When a mated/non-virgin creature reproduced, I’d forgotten to subtract energy from the parent when giving it to the child. Effectively, mated creatures could give birth for free.
The meatpile was an orgy.
The worst thing about this particular comedy of errors? If I’d paid closer attention at the start, I could have worked it out myself. Amorousness, the behavioural tendency that makes creatures decide to mate, was extremely high in every creature in the pile. I mistakenly assumed it was a side effect of being in such close proximity to each other, not the reason they were converging.
So quite often, that’s what Species is for me. A comedy of frustrating, painful errors that, at the end, results in a nothing more than a slightly more accurate, slightly more interesting, simulation of evolution.
And you know something? It’s totally worth it.
“There are things in this world: dark, terrible things, that should never be googled.”