Since nobody has commented on various matters: yes, we are still working towards a beta, yes it will be soon, but right now I’m sticking with the “When It’s Done” line. When we have a beta, we have a beta. Also, for the record: the Dwarven Panini Press did make it into Dungeons of Dredmor. Right now, it’s a throwing weapon. I’m not sure *where* I’m going with that. Anyhow, the coffee is on, Miles Davis is playing on the speakers, and it’s a long night of work ahead to get my TODO list whittled back to the state where it needs to be.
I keep saying that I’m going to make a post on this blog about some of the more interesting code that we’ve written for Dredmor, but – again – a lot of the Dredmor code isn’t that interesting. Instead, I think you get rambly thoughts on software engineering for the next little while. I was inspired by reading a post over at the IMVU engineering blog on how they expanded their business model. (Well, actually, it was a set of presentation slides.) I know many of the IMVU folks – a few of them were involved in the original seed work that turned into Dungeons of Dredmor, and they do a lot of very interesting work with continual deployment and Agile that is interesting if you’re interested in continuous deployment and Agile. Their CEO person, Eric Reis, also writes a lot about Agile Startups and how to bootstrap yourself via continually listening to what your customer has to say and then integrating that, continually, into your software deployment process. This is very similar to a Valve-style design-by-playtesting model, and I think that the game development community can either a) learn a lot from this, or b) has been doing it all along, and the rest of the world is just now playing catch-up. Eric’s blog is fascinating, and you should all go read it.
Many moons ago I was invited to interview for IMVU. I flew into Palo Alto, via a red-eye flight, and was treated to a fascinating hiring process. In fact, it was the most fascinating hiring process that I’ve ever been involved with. The sleep deprivation was cool, too, although I’m pretty sure it was accidental. Anyhow, I highly recommend applying for a job there simply so that you can check out how they hire people. Seriously. Go do it.
At the end of the day, I was offered a job. I declined to take that job, for a number of reasons, some of which are between me and IMVU and some of which are between me and myself. One of the more interesting reasons was that the company was struggling under the volume of significant technical debt in the area that I was interested in working on (the character rendering system and various other parts of the rendering pipeline), as well as all over. To actually read what they’ve been doing to try and deal with the technical debt, go hit up their weblog. I don’t know how well their approach to dealing with technical debt has panned out; that’s for them to talk about. But I can talk about technical debt with respect to how it affects myself, and I think that this will make interesting reading material this week.Technical debt, for those of you in the know, is the situation where you write code for a project, but you do it using duct tape and glue. Instead of writing your code with proper engineering and architecture behind it, and then refactoring it to make everything work correctly and be elegant and maintainable, you put just enough work into your codebase so that the feature that you’re working on passes the test/delivers the features/hits the milestone deadline, and you then have to deal with it “later.” As with all debt, there is interest to be paid; technical debt is hard stuff to resolve. If you have a bad system and you stack other code on top of it, when you replace the bad system with properly engineered code the stuff on the top has a nasty tendency to fall off and stop working.
The dirty secret of game development is that technical debt rarely, if ever, gets paid. We continue to pay off the interest on it, but we never actually pay the debtload itself because, at some point, the game ships and that’s it. We’re done. New game, new codebase. We may learn that, yes, these things we did last time suck; accordingly, we know better. However, the original debt just sort of carries on through the life cycle of the product. If you want to see an interesting example of technical debt, you should check out the codebase for Lugaru, Wolfire’s recently open-sourced rabbit beating simulator. The main processing component for Lugaru consists of this file here, which contains an absolutely brutal nine thousand line function called Game::Tick() with thirty-two levels of indentation. I don’t know how that function grew to that point, but I’m amazed that it never got split into subroutines. I’m also amazed that whoever was responsible for that manged to ship a game that required bug fixes to be made to that function without giving up, or going insane, or both. Nonetheless, that game shipped, made money, and is now open source for the rest of us to look at. Technical debt does not always need to be paid off in game development!
One of my jobs as Technical Director is to decide where to take on technical debt, and when and where to deal with it. The ultimate goal is to ship a project. With Spectre, our in house technology platform, I am much more careful about accruing technical debt. For one thing, we intend to license the technology to other people; for another thing, if we take on technical debt here we may end up suffering for it throughout the course of other projects. Spectre itself has a lot of technical debt in its renderer; certain elements (fonts, 2D objects) are not handled in a way that fits nicely into a modern hardware-accelerated rendering pipeline, and I need to deal with it. (To be fair, this is the earliest code in the Spectre codebase, originating circa… 2001 or 2002.) Ruby is another example of a technical debt that we will have to pay off; in this case, it simply means that I have to remove Ruby from the engine, and add support for another scripting language. This was unpredicted, but at the end of the day it turns out that Ruby is unsuitable for real time game development due to the current state of its garbage collector. (I wrote about this already.)
In the case of Dredmor, our main technical debt has to do with the UI system – surprise, surprise. Our UI takes the form of a number of one-off pieces of code that throw SDL surfaces around, and do hideous, hacky immediate-mode GUI style programming to make everything work. There is a lot of duplicate code, a lot of manual labour, and a lot of copy and paste. I don’t intend to fix it until after we ship, if ever. Bluntly, I don’t have time. The next game, whatever form it may take, will have a visual system for UI design that will let David and his artistic brethren change things as they see fit. It will also mean that I don’t have to keep hand-rolling scrollbar code. 🙂
The buff situation has also evolved to the point where it needs a refactoring quite badly, but I think that will wait for post-release as part of our “let’s make everything modder friendly” work and, if we decide it’s fiscally viable to do it, the expansion pack/DLC song and dance. There are features in there that are not being used in the current set of 135 skills, but that were used back when we had 180 spells and no skills. Similarily, there are features that we still need to implement that are not handled nicely by the new system. Bleeding – having characters run around with giant wounds spurting out of their head – is a recently added feature that didn’t *quite* fit into the existing framework of the buff system, and ended up being hard-coded. Saving and loading the game also sucks, because it requires a great deal of care and attention to get working and it breaks easily. (Unit testing would help this, I fully admit. That might be how we survive beta; I may write just enough tests to survive.)
In general, though, I’m pretty pleased with the state of Dredmor’s code base. Most of it is written using a very immediate programming paradigm that lets us do simple things easily. It does not have a whole lot of object-oriented architecture. There is one base class, GameObj, from which everything descends (except, I think, for levels). GameObj has two main descendants, in the forms of the Item and Hittable classes; these do the valuable work of being items and, well, being things that you can hit (including the player.) The rendering system sits somewhat adjacent to that, and uses a Bob/sprite paradigm where sprites are sequences of animation, and a Bob represents an instance of a thing that might use multiple sprites. (Bobs, incidentally, get their name from the glorious world of Amiga programming; this shows how long I’ve been in the business.) Had I planned on reusing any of this code, I would probably have done more engineering; however, this will enable us to ship, and at the end of the day this is the first step in separating the winners from the losers.
Joel Spolsky posits the existence of a class of “duct tape programmers” – people who build projects By Any Means Necessary, in a MacGyver style fashion. That’s a little bit of a crude definition of the class, but it will do. You know what? If I had to describe my particular approach to technology building, I would say that a lot of duct tape is involved. That’s okay. At the end of the day, software gets out the door.
Next week: how to ship games.