Playing Against a Human
As a person who had played many (many, many) strategy games before developing Warcraft, I was well aware of the limitations of computer AIs of that era. While I had battled against many computer AIs -- sometimes losing, many times winning -- I was never scared by AI intelligence, even when battling the terrible Russian offensive in the game Eastern Front by Chris Crawford, which I played on a friend's Atari 800 until eventually the audio cassette tape (!) that contained the game was so old it could no longer be read.
These games were fun, exciting, and most certainly challenging, but not scary. But something changed when I played the first multiplayer game of Warcraft.
The knowledge that I was competing against an able human player -- not just in terms of skill and strategy, but also in terms of speed of command -- but was prevented from seeing his actions by the fog of war was both electrifying and terrifying. In my entire career I have never felt as excited about a single game as I was during that first experience playing Warcraft, where it was impossible to know whether I was winning or losing.
As a massive adrenaline rush spiked in my bloodstream, I did my best to efficiently harvest gold and lumber, build farms and barracks, develop an offensive capability, explore the map, and -- most importantly -- crush Bob's armies before he could do the same to mine.
This was no test-game to verify the functionality of the engine; I know he felt the same desire to claim bragging rights over who won the first-ever multiplayer game of Warcraft. Moreover, when we had played Doom together at Blizzard, I had won some renown because, after a particularly fierce game, Bob had become so angry at me for killing him so frequently with a rocket launcher that he had vowed never to play me again. I knew he'd be looking for payback.
As our armies met in battle, we redoubled our efforts to build more units and threw them into the fray. Once I discovered his encampment and attacked, I felt more hopeful. Bob's strategy seemed disorganized and it appeared I would be able to crush his forces, but I wanted to leave nothing to chance so I continued at a frenzied pace, attacking his units and buildings wherever I could find them.
And then... crash.
As any programmer knows, the likelihood of new code working properly the first time is close to zero, and so it should be no surprise that the game crashed. The game's graphics scrolled off the top of the monitor and were replaced with the blocky text of the DOS4GW "crash screen" so familiar to gamers in the era before Windows gaming. Now we have the far more sophisticated Windows Error Reporting dialog, which enables the player to submit the crash report, though occasionally players see the dreaded Blue Screen of Death, which is remarkably similar to those of old.
After the crash, I leaped up from my chair and ran into Bob's office, yelling "That was awesooooommmme!" immediately followed by "...and I was kicking your ass!" So I was surprised to hear Bob's immediate rebuttal: to the contrary, he had been destroying me.
It took a few minutes for our jangled nerves to return to normal, but in short order we determined that not only did we have a crash bug but also a game-state synchronization problem, which I termed a "sync bug": the two computers were showing entirely different battles that, while they started identically, diverged into two entirely different universes.
Someone who hasn't worked on programming network code might assume that the two Warcraft game clients would send the entire game state back and forth each turn as the game is played. That is, each turn the computers would send the positions and actions for every game unit. In a slow-paced game with only a few board positions, like Chess or Checkers, this would certainly be possible, but in a game like Warcraft, with up to 600 units in action at once, it was impossible to send that volume of information over the network.
We anticipated that many gamers would play Warcraft with 2400 baud modems, which could only transmit a few hundred characters per second. Younger gamers who never used a modem should take the time to read up on the technology, which was little removed from smoke signals, and only slightly more advanced than banging rocks together. Remember, this was before Amazon, Google, and Netflix -- we're talking the dark ages, man.
Having previously "ported" Battle Chess from DOS to Windows, I was familiar with how multiplayer games could communicate using modems. I knew that because of the limited bandwidth available via a modem it would have been impossible to send the entire game state over the network, so my solution was to send only each player's commands and have both players execute those commands simultaneously.
I knew that this solution would work because computers are great at doing exactly what they're told. Unfortunately, it turned out that many times we humans who program them are not so good at telling computers exactly the right thing to do, and that is a major source of bugs. When two computers are supposed to be doing the same thing, but disagree because of a bug, well, that's a problem.
A sync bug arises when the two computers simulating the game each choose different answers to the same question, and from there diverge further and further over time. As in time-travel movies like Back to the Future, small changes made by the time traveler while in the past lead to entirely different futures; so it was that games of Warcraft would similarly diverge. On my computer my Elvish archer would see your Orcish peon and attack, whereas on your computer the peon would fail to notice the attack and wander off to harvest lumber. With no mechanism to discover or rectify these types of disagreements, our two games would soon be entirely different.
So it was that the first game of Warcraft was a draw, but at the same time it was a giant win for the game team -- it was hella fun! Other team members in the office played multiplayer soon afterwards and discovered it was like Blue Sky, the pure crystal meth manufactured by Walter White in Breaking Bad. Once people got a taste for multiplayer Warcraft, nothing else was as good. Even with regular game crashes, we knew we were on to something big.
All we needed to do was get the game done.
Tragically, we soon made an even worse discovery: not only did we have numerous sync bugs, but there were also many different causes for those sync bugs. If all the sync bugs were for similar reasons, we could have endeavored to fix the singular root cause. Instead, it turned out there were numerous different types of problems, each of which caused a different type of sync bug, and each which therefore necessitated its own fix.
Why Do Sync Bugs Happen?
When developing Warcraft, I had designed a solution to minimize the amount of data that needed to be transmitted over the network by only sending the commands that each player initiated, like "select unit 5", "move to 650, 1224", and "attack unit 53". Many programmers have independently designed this same system; it's an obvious solution to the problem of trying to synchronize two computers without sending the entire game state between them every single game turn.
These days, there are probably several patents retroactively trying to claim credit for this approach. Over time, I've come to believe that software should not be patentable; most any idea in software is something that a moderately experienced programmer could invent, and the definition of patents requires that patents be non-obvious. 'Nuff said.
I hadn't yet implemented a mechanism to verify synchronization between the two computers, so any bug in the game code that caused those computers to make different choices would cause the game to "bifurcate" -- that is, split it into two loosely-coupled universes that would continue to communicate but diverge with increasing rapidity over time.
Creating systems designed to detect de-synchronization issues was clearly the next task on my long list of things to do to ship the game!
In For the Long Haul
You know the ending to this story: Warcraft "eventually" shipped only five months later. It seemed an eternity, because we worked so many hours each day, encountered so many obstacles, overcame so many challenges, and created something we cared for so passionately. I'll continue to explore those remaining months in future blog articles, but so much was packed into that time that it's impossible to squeeze those recollections into this already too-long post!