I said I’d talk about the most difficult bug I’ve ever encountered, but I want to talk about my favorite bug instead. The most difficult issues I’ve faced in programming have been working with bad legacy code, but those stories are just me bashing my head against the keyboard because someone used !important on every other line of a stylesheet.
Instead I want to talk about my favorite bug ever, which took about 30 seconds to fix, but which I’m still thinking about five years later. Here’s the story of the self destructing wolves.
So it’s 2014. I’m developing my first game. It’s a massive project with a scope that has gradually increased to the point of insanity. What started as a simple roguelike has turned into a massive graphical game with two crafting systems and ostensibly a multiplayer element.
I’m in college and skipping most of my coursework to develop the game—I’m pulling all-nighters to meet an arbitrary deadline I’ve set. On this particular night I haven’t slept in probably two days.
One of the things that has suffered from scope-creep is the enemies. Originally there were going to be one enemy, but this has snow-balled into close to 30, grouped into factions. Each faction has around five enemies which have their own AI and behavior (mostly running around and shooting, mind you). The game is procedurally generated, so any zone can be populated by any faction—sometimes multiple.
Some of the factions are allied, and some are enemies. The humans and the elvs (I was so clever and original to call them elvs and not elfs) are allies—if they spawn in the same zone they won’t attack each other. The dwarvs (see elvs) and the goblins are enemies, if they spawn in the same zone, they will start fighting each other. It’s not a very advanced system, but it’s cool to see fights play out in front of you when you enter a new zone. You can see the fights happen visually, and there is a console that writes out what is happening in game. It reads like:
THE GOBLIN HITS THE DWARF FOR 7DMG
THE DWARF HITS THE GOBLIN WITH FIREBALL FOR 12DMG
THE GOBLIN IS ON FIRE. 1DMG
THE GOBLIN HITS THE DWARF FOR 4DMG
THE DWARF HITS THE GOBLIN FOR 6DMG
THE GOBLIN IS ON FIRE. 1DMG.
THE GOBLIN PERISHES!
One faction is enemies with everyone: the wolves (thankfully I kept the E in wolves, though I did spell it wrong in the promo video). Wolves will fight any faction they spawn with. The logic behind the faction combat is very simple. It checks if the factions are allies, if they are, don’t fight each other, if they aren’t, fight each other. Wolves have no allies though—they even fight each other. I will miss one piece of logic.
I write the code for the faction system, I test the game. First screen: no enemies—check. Second screen: humans and elvs, they fight me but not each other—check. Third screen: wolves.
I enter the screen and the wolves don’t move. I move towards them and this appears in the console:
THE WOLF HITS THE WOLF FOR 6DMG
THE WOLF HITS THE WOLF FOR 4DMG
THE WOLF HITS THE WOLF FOR 12DMG (CRITICAL HIT!)
THE WOLF PERISHES!
I had based enemies attack criteria on factions and not individual enemies. This meant that if a faction had no allies (including itself), it would fight itself. In essence, when I entered the wolf zone, the wolves committed mass suicide.
I immediately know what’s happened as I watch all my wolf children disappear. It’s a very simple, easy to correct mistake, but, one which, at this sleep deprived junction, puts me into a small existential crisis. “What have I done? What kind of horrible world have I created where the wolves have no will to live?”
I momentarily consider abandoning the project, remorseful for creating this universe. But I instead add an OR to my if statement and voila, the wolves go after me and not themselves. That’s when I decide to call it a night. I go back to my dorm, and go to sleep.
The game, which was called LikeARogue, did indeed get finished on time. PHP updates have since broken it and I don’t really have the will to muck through my terrible code to fix it, but I remain very proud of it. A crazy amount of features got crammed into it, mostly because I didn’t know what I couldn’t do. So let your scope creep, kids! To heck with what they tell ya! Just don’t start skipping your coursework and pulling all-nighters.
The moral of this story is that you should mind your if statements. Or maybe mind your wolves. Mind your health. Mind something && !attackSelf;
This post is brought to you by (but not sponsored or endorsed by) SummerTech Computer Camps! I went to camp there as a kid and they currently employ me! If you are a youth aged 7-17 or know anyone of that age who is interested in computers, check out our website! It’s an amazing experience.