Editor's note: This paper was originally published in the
2000 Game Developer's Conference proceedings.
To the Moon and Back…
A few years ago, after Quake shipped, I decided it was time to move on from games. Although working on Quake was a great experience, it felt like doing another game would be much the same, but far less interesting the second time around. What I needed, I thought, was a software field with deep structure and long-term challenges-something more significant, difficult, and ultimately rewarding. So I figured it was the right time to switch over to work on natural language, which fit that description perfectly.
I figured wrong. By way of explanation, two stories and a conclusion:
Story the first: After a couple of years of natural language work, I thought about moving to the Games group at Microsoft, and went to talk with the folks over there. While I was talking to Andy Glaister, my future manager in Games, he asked me, "How old is your daughter now?" When I told him she was 13, he said, "Really? I always think of her as being three or four." This was interesting, considering he had never met her, and had only met me a few days before-but he had read about her in the articles I had written in Dr. Dobb's and elsewhere over the preceding decade or so. It was a useful reminder of how long I had been working on and writing about performance and graphics, and how that had always stayed challenging and interesting even as computers and software changed drastically through the years.
Story the second: While I was working on natural language, I read Mihaly Csikszentmihalyi's book Flow, about what sort of work people are happiest doing. It turns out there's a sweet spot, where the work is challenging and stimulating but plausibly doable, and where success happens often enough to form a positive feedback loop. As I read this, I realized that it was basically a description of successful game development. True, games have short development cycles, and progress is made incrementally-but at least progress is made, while the short cycles mean that success in the form of shipping occurs often, and positive feedback in the form of seeing cool stuff on the screen happens pretty much nonstop. And for all the incremental nature of game advancement, in many ways games are pushing the envelope harder than almost any other kind of software-what else does a consumer need a 700 MHz machine with a high-end 3D accelerator for? Plus games cover a huge range of technologies-graphics, physics, modeling, scripting, AI, networking, databases-more than any other kind of software I can think of. What I finally realized was that, for me at least, game programming is the sweetest spot in all of software development.
In Robert A. Heinlein's story "It's Great To Be Back," a couple leaves the Moon, after working there for years and hating it: hating the lack of fresh air, the lack of weather, the lack of cozy old houses, the lack of normal people-basically, hating everything. They make no bones about their feelings, and when they get to Earth, they just keep saying, "It's great to be back!"-although sometimes it seems a little forced.
Gradually, the truth seeps in. Weather is often unpleasant. Germs are everywhere. Fresh air results in allergies. The old house they buy is falling apart. Worst of all, the people are rude and stupid, where the Loonies had been hand-picked for skills and compatiblity. Before the year is over, they realize they had been living in paradise and ask for their old jobs back, and before they know it, they're heading back to the Moon, saying "It'll be great to be back!"-and this time, it fits.
There's lots of interesting stuff to think about and work on in natural language, or in any of dozens of other types of software, for that matter, and there are lots of other worthwhile pursuits that have nothing to do with software-but in terms of rewarding challenge, stimulation, and flat-out excitement, having made the round trip and returned, all I can say is:
It's great to be back!
Optimizing the Game of Life
Like most of you, I suspect, I just plain like writing software-I did it for fun before I did it for a living-and one of the best things about game programming is the opportunity to do challenging programming in a broad range of areas, from graphics to physics to AI to you-name-it. Another is that the game industry changes so fast and is so close to the leading edge of consumer technology that it's a terrific opportunity to ride the wave of the future. The rest of this paper presents a number of principles and approaches to writing software and riding that wave that I've found to be helpful and/or enlightening over the years. At the risk of sounding like "Everybody's Free (To Wear Sunscreen)" (the alleged Kurt Vonnegut graduation speech that became a novelty hit when recited over a musical background), I'm going to present just the core points here, as succinctly as possible. This is basically just an outline, so you'll have some idea in advance of what to expect from the talk, and to jog your memory when you pick up the proceedings later. The talk itself will expand upon and illustrate the points, complete with anecdotes and examples ranging from working on Quake to working on Windows NT to writing "the last great software rasterizer" to speeding up the Game of Life.
Herewith, some thoughts on fast code, game programming, software development, and more:
The three secrets to success are:
1) Hard work,
2) Hard work, and
3) Hard work.
Learn by doing. Thinking is great, but the only way you ever really learn something thoroughly is by doing it-and particularly by finishing it, which is harder than it sounds because shipping software is an unnatural act (thanks to David Stafford for the phrase). Accept reality: no software is ever going to be perfect, and perfection is a moving target anyway. Make the necessary tradeoffs and get it out the door.
Success is more than just a big paycheck-or, as John Carmack put it, "The Ferraris are only gravy, honest!" You're going to be financially solvent-or better-anyway, so why not do what you love? If you do what you love and work hard and passionately, you're building the foundation of a rewarding life, and in the long term you'll succeed in every way that's important to you.
If you like it, game programming is about the best software job there is. It touches on practically every area of programming, and it's one of the few places where code can still be written clean instead of patched over or pieced together from canned parts. It's also one of the few places where optimization still really matters.
Aim high, think big. Right now is a particularly good time for ambitious game programming, because so much more is possible now than ever before, thanks to CPU performance and 3D accelerators.
Great software is more than just great code. First, a great design is needed, before the code can be written. Don't write code until you have a clear model in your head of what you're trying to accomplish. Take the time to get this right, and don't jump on the first workable idea you come up with.
Design and optimize from the highest levels of your model on down, focusing on the big architectural issues first. Premature optimization-including premature low-level design--is the root of all evil.
Keep looking for new, better approaches, and be ready and willing to change the model constantly as you learn more-or even throw it away entirely. Until you start running out of time, think of whatever design you have as just a jumping-off point for a better one.
Get past the abstractions and know what your code does. Profile in many ways: profilers, NULL drivers, bracketing key code with timing calls, breaking into the debugger at random and seeing where you are. If you don't do this, you're guessing.
Knowing what to optimize matters as much as knowing how to optimize. Otherwise, you'll optimize the wrong thing, and end up with really fast slow code.
When it seems you've made your code as good as it can be, and you still need more from it, try to change the way you're seeing the problem. You may be solving your abstraction of the problem rather than the problem itself. Terje Mathisen says, "Almost all programming can be viewed as an exercise in caching." David Stafford views almost all programming as a form of compression. There are infinitely many programming perspectives available to you-use them.
Check your assumptions.
Assume nothing. Always ask yourself questions and challenge your assumptions, and just laugh and be glad for what you've learned when you find you could have done something better.
Stand on the shoulders of giants. There are few brand-new ideas in the world; read what others have done rather than trying to invent everything yourself. Most of programming success lies in engineering and integrating and finishing and being flexible, rather than in raw invention. Sure, it's fun to reinvent things, but there's a huge amount you have to know now, so it's hard to do it all on your own. Besides, there's plenty of cool stuff to figure out after you learn what's already been solved.
Learn as much math as you can stand. Then learn some more. The industry is moving from broad, seat-of-the-pants programming to software more dominated by content and deep knowledge of areas like physics. Programming itself is easy; it's expertise in knowledge-intensive areas that will increasingly set programmers apart in the future.
Be patient. It takes one year to become competent at something new, three years to become an expert.
Stretch until it hurts. Be flexible. Don't get attached to your designs or code. Be willing to listen to new viewpoints, admit it when you're wrong, and change your mind as appropriate.
Embrace change… or watch it run you over and leave you behind. Accept that the goals, techniques, and rules will constantly change.
The only thing standing between you and great software ideas is you. Think past the limits you've unconsciously set.
TANSTATFC: There ain't no such thing as the fastest code (with apologies to Robert A. Heinlein and thanks to Terje Mathisen, who came up with the phrase).
Turn your right brain loose. Try lots of stuff, even wild stuff. Listen to that little voice. Relax. Let yourself be creative. Accept that many ideas will fail. This is the only way to learn and make real progress.
If your code is getting more complex, you're probably fine-tuning. Step back and look at the bigger picture for more global solutions. Try to change the rules so you can succeed, rather than straining to be mediocre under the current constraints.
Don't get too comfortable. Aspire to excellence. Fight that satisfied feeling about your code, and constantly ask how to improve. Fight code entropy.
Simplify. Try to do better with less, in a different way.
Programming is not a zero-sum game. Unless you have legal or employer restrictions, share what you've learned, and learn from others. Having to explain something forces you to know it cold. It also makes you known, and leads to interesting opportunities.
Remember to have fun! It's about the best job around, but like anything else, game programming can turn into a job if you let it. Don't let it. You're one of the luckiest people in the history of the planet, getting incredibly well rewarded for doing something challenging, fun, and just plain cool. Remember that and count your blessings every day. Then get out there and write some great software!