A bug that’s been in the game for awhile, and which some of you may have encountered (albeit very rarely) is the following peculiar circumstance: You start the game, you load up a new map… and suddenly, everything slowly starts to drift into the corner of the map. Finally, you end up with a giant frothing mass of dodos, and colonists, and monsters and who knows what else stuck in one corner of the map, apparently unable to move.
For those of you who haven’t seen it, you end up with the following scenario (screenshot thanks to a forum user):
So… what in the world causes this mess?
Part of shipping a game is dealing with all of your long standing issues that you have always decided to put off until later. Well, later is now. A week or so ago, I was able to finally find a replay of the game where this consistently happened, and decided…. okay, today’s the day I fix it. So… start the game up, see everything float into the corner of the map as it is sucked into the black hole of THE VOID… all without animating. Hmm. Okay.
A cheerful examination of the console revealed that the STUCK messages were going off. Recall, from Many Blogs Ago, that characters take great pains to not get stuck in trees and things. Specifically, if a character is trapped in a space (defined as “a connected component that is isolated from the main map and smaller than a certain size”) the game pops them into the next component over by a random displacement of their position. This size is large enough that you can get unstuck if, say, we drop a tree on you; but small enough that you can still brick somebody in a house. (DESIGN GOALS.) So… clearly, the game thought everybody was stuck.
We have SVG code to dump the “spatial dictionary” (the data structure that holds all the collision information; it’s been engineered and reengineered to death so many times now that the original use of the word “dictionary” is misleading but the data structure kept its names); it writes out a SVG file of vectors that you can put into, say, Adobe Illustrator. I learned the trick of writing to SVG files directly when working on an academic paper a few years ago, and it’s saved my bacon. Anyhow, what the SVG files revealed was… no, there’s absolutely nothing to get stuck on here. At all. So… why does it think things are stuck?
Cue more headscratching.
Finally, I get cranky and break open the debugger, figuring “Alright, I’ll check the stuck test to walk through it and see what component it thinks it’s in.” Some poking around and it thinks it’s in component 0. In fact, it… thinks the entire map is component 0. Well, that makes sense if there’s absolutely no stuck regions that everything is the same component. Do we just assume that component 0, the first thing you would place on the map, is always an obstructed component? Well, that seems likely… except that, after more digging, component 0 is always used as a scratch variable. The first component ID should be component 1024. So for some reason, if a map contains no obstructions in it, it… just doesn’t initialize the components.
And that’s when I realized: when obstructions are added to the map, we set a flag that requires you to rebuild the connected components for the navigation layer and stuck code. If you don’t have any obstructions placed during the map generation, then there’s nothing to trigger that flag… and we don’t rebuild the connected components for the first time. Hence, the component IDs everywhere are set to whatever we initialized the array with (0, a good number for initializing an array with) it thinks everything’s in a “stuck” component, and so…
Once connected components were forced to rebuild themselves after every game start and load, the VOID was sent back into the void from whence it came… after something like four hours of painstaking archaeology.
Clockwork Empires is a huge, huge game. There’s big chunks of stuff that was written years ago that has lain dormant, happily… except when it causes problems like this. The disappearing modules, which I fixed yesterday, are another example of this; ancient code from before the dawn of time was found, discovered to be triggering when you modified terrain too close to a building, and then resetting the heights of any module nearby – incorrectly. Archaeology!