How I learned to program
“Mom, what do you want me to write? Just tell me and I’ll write a program for you.” That was me at 9, urgently tugging at my mom’s pant leg.
I don't remember what, if anything, I ended up writing in BASIC on our Timex Sinclair computer, but I do remember wanting to be taken seriously—wanting to make something that would be useful to someone. I think my dad bought that computer on a whim out of a gadget catalog, though he’s not much of a gadget guy. I hooked it up to an old 8" black and white portable TV we had. I’d become fascinated with computers ever since mom wrote a program that printed my name across the screen in an infinite loop.
The computer was calling to me. My brother and I wrote some things in BASIC on that computer, and we were even able to load and save our programs using a cassette player attached to the audio jack of the computer. We tried playing the cassette on a regular tape player and it sounded like screeching cicadas.
It wasn't until much later, at 15, that I really got excited about programming. I became addicted to an online adventure game—a free Multi-User Dungeon (MUD) called HexOnyx. Hex was a popular virtual world with at least a hundred people playing at any given time. I made great friends there, and each night we'd battle vicious snarling wargs and Demons of Decay together in the dungeons and dark woods. One day we found a monster called Your Worst Nightmare:
“It looks like you deepest, darkest fears personified. Wait a minute! It IS your deepest, darkest fears personified!”
The game was entirely text-based, so imagination was mandatory. Nearly 20 years later, I still have pictures in my head of some of my old stomping grounds in the game.
Every night was a new adventure. Punctuated, of course, by the dinner bell. “I'll be right there!” I'd shout, only to slink into the dining room much later, midway through the meal. There's never an easy stopping point when you're facing a four-legged lamia beast who wants your head for her next meal.
For months, me and my online friends battled these computer-generated creatures obsessively. I eventually advanced my character to the point of immortality, which is the effective endpoint of the game.* Immortals can no longer battle—they're just around to be helpful to new players, resolve disputes, and so on.
As an immortal, I made friends with Hex's administrators and developers, and I started looking at the MUD's design, trying to understand how it was able to trigger such deep immersion, and wondering how we might make it even better.
There were hundreds of MUDS and each one tried to differentiate itself. To differentiate Hex, the developers had created a custom, in-game world builder. Where other MUDs had to edit a flat text file with a very confusing, proprietary format (no JSON back then), the in-game builder made writing worlds enjoyable and it allowed players to get involved easily. Yaz, Hex's caretaker, had this to say:
“The object of the game from our POV at that time was to create an environment that could be maintained from within the world. i.e.: no one would really need to run the game from the outside. We got close with the world builder.”
With the world builder, you could write a new door and a new room in the game, then step through the door into the room and see how it felt. This triggered a development boom, with many new worlds under construction, waiting to be finished and connected up with the main map of the game. These unfinished worlds were eerie places accessible only to admins and filled with bloodthirsty monsters that wandered around alone day and night.
I had no interest in building worlds; even with the world builder, it seemed like too much work. Instead I wanted to understand the mechanics of the software and make structural changes.
Unlike modern multiplayer games like WoW, most MUDs, including Hex, were based on open source software. I downloaded CircleMUD, Hex's ancestor, and ran on my home computer. I'd programmed a few things in BASIC before, but Circle was in C—a whole new world for me. THANKFULLY, IT WAS A WORLD WITH A LOT LESS UPPERCASE THAN BASIC. But I figured out how to make small changes, and it was thrilling to recompile the MUD and see a change locally.
I was learning the fundamentals of computer science by example, tweaking functions like this:
/*
* Function: find_guard
*
* Returns the pointer to a guard on duty.
* Used by Peter, the Captain of the Royal Guard
*/
struct char_data *find_guard(struct char_data *chAtChar)
{
struct char_data *ch;
for (ch = world[IN_ROOM(chAtChar)].people; ch; ch = ch->next_in_room)
if (!FIGHTING(ch) && member_of_royal_guard(ch))
return (ch);
return (NULL);
}
By today's standards, parts of Circle's code would be judged smelly and inelegant. It has no tests, as prevention-oriented software testing hadn't caught on yet. Still, Circle is quite brilliant. Itself a fork of the MUD project DikuMUD, written in 1990 by a few guys at the University of Copenhagen, Circle has the rugged appeal of a great C program: It engages intimately with the OS, it is highly optimized, and it does a lot of heavy lifting. It manages its own TCP sockets and I/O buffers from the ground up, defines its own flat file formats, and so on.
What today would be considered bare metal was, back then, the top of the stack. Circle's creators did not lament the lack of dynamic typing or other higher-level luxuries—they reveled in the conveniences of flying above assembly language and of leaning into the operating system for all kinds of important tasks.
As a result, Circle is a workhorse, and in production, Hex can run smoothly with 200+ concurrent users in under 20MB of RAM on a 486. The game runs in one big 100ms loop which never blocks; it just services all of the currently connected users, steps the world forward by one tick, then sleeps until it's time to do it again. I remember doing some long-running thing inside this loop and learning the hard way that it halts the game for everyone.
After weeks of poring over the code, and after much trial and error, I was delighted to send in a little patch that changed the style of the command prompt in the game. In an mid-90s-style pull request, I dashed off an e-mail to the Hex administrators with my patch and eagerly awaited a reply.
They accepted it. They applied it. And it was magical to see my small change incorporated into a game that so many people played every day. The developers—mostly college-age Computer Science students—gave me feedback on my patch, as did the players.
I kept working and I sent in more small patches. Eventually Yaz got tired of playing middleman and said, “Why don't you just made edits directly to our code.” and he created an account on the server for me.
Implementor status on Hex was by far the most responsibility I'd ever felt. I started releasing new changes almost every night, receiving immediate feedback from other players. Not only was I designing and building features that I, as a veteran player, wanted to see in the game—more importantly, I was iterating inside a tight feedback loop with other users.
This feedback drove me. It kept me going through bugs that seemed unfixable and problems that seemed intractable. There was no schedule—just endless small steps every day toward a better game. I was hooked on the deep satisfaction that came with enhancing something people loved to use, and I'd reached an incredible flow state.
This is, I think, a great way to learn programming: rather than saying “I want to learn to program”, start with a desire to improve something that already exists. Something people use. Expect that you will hit roadblocks and challenges, and let feedback from users and collaborators be your encouragement to persevere through those. Plenty of open source projects make this opportunity available, but I think there's something special about the gaming environment.
Over the following months, I learned about data structures and memory allocation. I learned about sane ways to structure procedural software. I learned about sockets, data serialization, timers and interrupts. I didn't know the vocabulary for these things beyond what I was able to read in code's comments and in man pages for system calls. Coding for the MUD was all I thought about at school each day and all I did at home each night.
I added a host of new features over the next year or two. I expanded the MUDs internal economy, building a system of houses (virtual storage lockers, really) and a real estate market for them. I introduced scarcity of goods into the game's economy, writing an algorithm that limited the rate at which the best equipment would be introduced into the world. I was the invisible hand, making the game more fun and challenging for people, and it was a blast.
The fun of being a developer pushed me to learn more and strive to build more things that people wanted. I'm an engineer today because of that experience. I'm grateful that CircleMUD was malleable open source code, and that Yaz took a leap of faith in handing the keys to Hex over to a 15-year-old.
Today, I'm interested in creating experiences for people that mirror how the MUD was for me: you approach as a consumer and transition into a creator. Wikipedia excels at this, and the open source movement continues to provide a ton of opportunities for young developers, but the most popular multiplayer games of today are immutable.
And that's a problem. As technology advances, it should not close up like a black box. Because games like WoW are not open source, there's no opportunity to take the leap into the role of developer. I'd love for the generation that's coming up now to have as much fun learning to program as I did. Changing the game is a lot more interesting than playing it.