(Shamelessly reposted from Shamus’s Good Robot Devblog)
When you’ve got more than one person working on a complex bit of software, you generally need a specification (spec) for new features. The bigger the team, the more you need a spec. The more complex a feature, the more you need a spec.
According to stereotypes, big firms usually lean too hard on specs, to the point where they might spend more time writing the specs than coding the feature:
“The button will be ten pixels from the left margin and will conform to the usability guidelines sheet 201-a. It will be labeled “Join Game” and will – after a confirmation popup as outlined in the interface framework – begin polling the designated server in request for an open slot. If no slot is found, then the fallback behavior […]”
Meanwhile, little indie houses have a slightly less formal approach:
Bruce: Can you add a button that will let players join the game?
Stuff gets done either way, but sometimes indies are a little slapdash and sometimes big firms are a little too bureaucratic. On Good Robot, our spec is usually a sentence or two in the shared Google doc that we use as a universal to-do list.
But this week I ran into something that I realized was too complicated for that. It was one of those features that sounded obvious and simple in the meeting, but then became mysterious when I sat down to write the damn thing. (This is the point of a spec: To reveal the unknowns BEFORE coding begins. This is important in big firms, since once you’ve begun coding you’ve ALREADY been allotted a fixed time budget, which means this is a bad time to begin figuring out what you need to do.)
So I proposed a spec. And then I thought I’d post it here, just to show what the non-exciting bits of game development look like. This is pretty informal as these things go, but it should give you an idea of what needs to be hammered out before you start coding.
Also note that I’ve replaced the names of the stuff in our game with DOOM references to make it easier to follow.
Drop Tables Discussion
“Add a drop table” has been lurking on my to-do list for several weeks now. This is actually a complex enough topic that we need to define a spec. It turns out this is a bigger feature than we might have anticipated in meetings. Every time I’ve tried to start on it, I ended up with more questions on what we needed and what I was supposed to be doing.
We will be adding a new file called drops.ini or drops.xml, which will allow artists to design things to be dropped in the game. (Things that the player can pick up.) We want the system to be robust enough that it feels unpredictable and varied on repeated playthroughs, yet controllable enough that the game doesn’t feel like random chaos. Specifically, we want to be able to ensure things like, “Player will be offered at least 1 half-decent weapon before reaching point N.”
- Right now there are two main things that need to result in drops. We should go ahead and assume that more “causes” might be added later.
- When you destroy a robot.
- When you destroy a machine. (Boxes are “machines”, in the parlance of the game’s internal workings.)
- A drop can deliver a number of things. Given our discussions so far, It seems like it should be possible for a single drop to create multiple things:
- Weapon pickup. (Of a specific type. Ex: “AlienBlaster”) This might be too naive a design. I’ll talk more about this at the end.
- Money. (Of a certain range of values. Ex: Between $10 and $20.)
- Robots. (Of a given type and number. Ex: 5 instances of “Imp”)
- MAYBE projectiles? This would let a boss release a swarm of missiles as it dies. I don’t know how these would be aimed, but it’s here for discussion.
- A drop must have some sort of probability associated with it.
- This probability ought to work on a per-item basis. So, maybe the “Cyberdemon” boss has 100% chance of dropping some imps, a 50% chance of dropping some PinkyDemons, and a 1% chance of dropping the BFG 9000.
- For simplicity of parsing, I THINK this probability should be expressed as a percentage (50%) and not a ratio (1:2). The first is simply much easier to write, but the latter is better if we plan to have very very small chances (say 1 in 10,000’s), since percentages like “0.01%” aren’t as intuitive. (And I worry about floating-point shenanigans.)
- Drops will be named.
- So in our file, the artist will name a drop something descriptive. “Level1Trash”, “Level2MiniBoss”, “BellaAndJacobOTP”, or “foo”. Whatever.
- The name will be referred to by the robots and machines in their respective files: “drop=Level2MiniBoss”
- If we go crazy, I suppose we could add something insane like recursive drops. So “Level2MiniBoss” has a 50% chance to create “Level1Trash”, which itself might contain references to other drops. This is powerful, but it’s also an exercise in juggling dynamite. It’s only slightly more effort to code, but you can create a lot of needless complexity and bugs with this. Protip: I’m not going to build in a system to detect infinite recursion, so if you screw up you might crash the game. Choose wisely.
My proposal, which needs to be discussed before I begin work on it:
I’m 99% sure that this needs to be in XML. The problem is hierarchical, which means using .ini files would be clumsy. Let’s just start with this assumption.
The definition starts with the name of the drop. It is then followed by one or more entries of things that might be dropped. Example:
1 2 3 4 5
<PhatLewt> <AlienBlaster chance="50"/> <Imp Min="0" Max="6" Chance="50"/> <Cash Min="0" Max="100" Chance="100"/> </PhatLewt>
For each entry:
There is the name of the drop: Either the name of a robot, the name of a weapon, or the word “cash”.
There is a minimum and maximum number to drop. If you omit these, it will default to a min and max of 1. (This is good for weapons, since it doesn’t make any sense to drop more than one of the same weapon.)
Then there is the value “chance”, which will probably be a percent. Note that it will roll this chance and THEN roll again for min and max. So in the example above, it might roll the dice for Imps. The roll comes up positive, so it rolls again to see HOW MANY. Then it might roll zero, meaning no imps actually appear. Keep this in mind.
You can use this system to create bell curves. For example, if you don’t want cash drops to be completely random, then you could do this:
1 2 3 4
<ThrowMoney> <Cash Min="1" Max="6" Chance="100"/> <Cash Min="1" Max="6" Chance="100"/> </ThrowMoney>
Both cash drops will always happen, and will always drop between 1 and 6 coins. This is the exact thing you get when rolling 2d6 in a tabletop setting: Most values will be in the mid range, and values of 2 or 12 will be rare.
Robots already have a value for how much money they will drop. I don’t see any reason to REMOVE that system, but we might simply transition to using this new system for that. Or maybe we’ll just limit this new system for specials and bosses.
One final note is that this doesn’t allow us to drop weapons from lists of possibilities, which is what vending machines use. Maybe we also need to add a systems of “weapon pools” of similar-powered weapons. So each entity can be a weapon, a weapon pool, money, or a robot. (And maybe projectiles.)
This needs a lot of discussion. It’s probably the most complex item on my list right now, so the sooner we hammer this out, the better.
So this is what I sent to the rest of the team (minus the animated Gifs) this morning. This afternoon we’ll have our meeting and we’ll see if what I’ve proposed fits with the needs of the project.