PURPLE MARTIANS

by Michael David Weiss

History

I had been trying to write a game for a long time.

In 1978, when I was 10, I learned BASIC on a Commodore PET and wrote a few simple programs to manipulate and draw text.

From 1980-1987, I had access to an Apple II+ and spent a lot of time learning how to program on that. (280 x 192 hires graphics mode!)

I made some games in BASIC, and assembly.

The BASIC games could not not get fast enough, no matter what.
Probably due to an interpreted language and my lack of skills.


Assembly was better, but my skills were not enough to write that complex of a program in assembly.

For many years I had no access to a computer, or the time or inclination to do anything about it.


I still wanted to create the game I had in my head, with a little man running around a level, jumping from platform to platform.


Then in 1997, I was in a seasonal layoff from my job over the winter, waiting on unemployment benefits, and I had a laptop and internet access.


I decided I was going to work on the game I had in my head.



I searched for some proper tools to create games. I was thinking even if I had to pirate something, I was going to figure out how to make my game a reality. All of the microsoft crap did not appeal to me, but I resigned myself to go there if I had to.



What I found instead was Allegro. It looked awesome. The more I read, the more I knew it was what I was looking for. And the best part was that it was free! Nothing to pirate!


The only catch... I would have to learn how to program in C.


I downloaded DJGPP, used RHIDE as my IDE, and added Allegro 2.2.


As I learned C, I was amazed at how logical, simple, precise and elegant it is. No gotos or line numbers. And it's really fast!


In my game I built everything from scratch. (Well, except for Allegro!)

I started by learning how to draw on the screen. Then I made some shapes to blit here and there. Early on I decided to make my game sprites 20x20 pixels.I made an bitmap editor to draw and edit these sprites.

I built my own routine for saving and loading bitmaps to disk, (one get_pixel and put_pixel at a time!)

I decided on a level size of 100x100 blocks made of these shapes.

I used an array of 10,000 ints, int l[100][100].



When I was figuring out how to run my game loop flicker free with a screen buffer, I created a bitmap the size of the whole level: 2000 x 2000 pixels. 4 million pixels!


From 1997 to 2003 I call the first phase of the development.

I always knew I wanted to do some kind of multiplayer. The game would just be so much better with more players.
It had to be simultaneous multiplayer, like Bubble Bobble. Just two players taking turns was never even considered.
Initially, I came up with a split screen method. I created a second player and re-wrote a lot of code that assumed there was only ever going to be one player.

That worked, but the split screens were kind of small.

Still it was really cool to play simultaneously with another player.

I started to think about how amazing networked multiplayer would be.


I found libnet and made a simple packet exchange of moves.
Exchanging game move packets was easy, but synchronizing the game was not.

I spent a lot of time trying different concepts and abandoning them when I realized they wouldn't work or I thought of a better way to do it.


In 2003 I released version 5. The netplay stuff didn't work yet, so I disabled all traces of it with #ifdef's in the source.

I let it go for a few years until I came back with a vengeance in 2009-2010 to solve the netplay stuff.


I made a lot of changes and improvements, but still had sync issues.
It would almost run perfectly until they slightly went out of sync.


I had made a lot of changes, but because netplay was broken I didn't want to release without it. Eventually I gave up and let it go for many years.



I had been thinking about the various methods of syncing, but was still convinced my method should work.

The method I used is called deterministic lockstep, and I wrote in depth about it in netplay.txt.


The concept is that for the exact same set of inputs, the output will be exactly the same. So if I could just sync the inputs (what controls are pressed on what frame), the output should be identical.


I was almost going to try something like Unity that had built in network multiplayer.
I even spent a few hours building a test project in Unity and seeing what it would be like to re-do the game in that.

I decided not to for a few reasons.

I wanted do it my way.

I wanted to figure it out myself.



In 2017-2018 I came back again and tested a new idea I had.

Basically I removed all floats and replaced them with fixed point numbers.

Floats, while very precise, were not as perfectly deterministic across different systems as I needed.

Fixed points, while not as accurate, gave the exact same results every time.

After a lot of rewriting, I finally was getting good sync. I could play 3 and 4 players games with no problems.
I still had rare occasions that the sync would break. Often enough that I couldn't call it fixed.
I wrote a huge amount of logging code, trying to get to the bottom of the problem.

Eventually I started passing some state information from server to clients to tell when the game was going out of sync.


That grew to be more and more information until I thought, why don't I try to send the entire state?

I never designed the game with that in mind, and the structures and arrays holding all of that data were huge.

100 enemies, each with 16 ints and 32 fixed_point
500 items,  each with 16 ints and 4 fixed_point
40 lifts structures, each with up to 40 steps
the level block array (100x100) ints
8 player data structures



All of that came in at over 100k. Way too much to sync with 1K packets.
I did some research and decided to try to use zlib to compress it.
That got my 100K down to around 6-12K.

I wrote code to split it into 1K packets and reassemble them on the clients.
It worked, but it was still too much data and was too slow.
At this point I was only using it to check and see if the game had gone out of sync.

Then I came up with a dif method. Instead of sending the whole 100K, I would only send what had changed.
I basically just subtracted one entire state from another, called that my dif, and compressed that.
That gave me around 600 to 1800 bytes. I would only need 1 or 2 packets!

When I got that working, I decided instead of just checking if I am out of sync, why don't I just use that to correct the state on the clients?

That is the way that it works now. It checks for differences, but then just overwrites with the new state anyway.
I still check for differences because I want to know what is drifting and see if I can find out why.
Its not really necessary because getting a new state fixes everything.


So there are two methods for the game sync:

The old original one just sync's the clients inputs.
Every frame, if the clients controls change, a packet with that control change is sent to the server.
The server then consolidates all client inputs, and syncs that back to each client independently.

The second method periodically sends a new complete state to each client in the form of a dif from the last acknowledged one.

Between these two methods, I can now play very long games, with up to 8 players, across all windows and linux versions, and it works perfectly!

Then I cleaned up a lot of things in the code that I had broken, refactored just about every line in the game, added new features, removed some old ones, went through all the levels, updated the help screens, made a fancy new rotating logo with splines for the splash screen...

Finally here we are on March 11, 2018 with Version 6.

Netplayer with up to 8 players.

Works on Windows XP, Windows 7, Windows 10, Ubuntu 16.04.



This will be the final release on Allegro 4.

For the next version, I'll convert to Allegro 5.



Well here we are again on April 22, 2018 with Version 7.

Now with Allegro 5.2.4!

Just about every line (25K) of code has been re-factored.

The display routines have been completely redone.

Now with dynamic resizing while the game is playing!

The linux version now is a precompiled executable.

Numerous small bug fixes and improvements.



Updated to Version 7.24 on October 18, 2022

Added some new items, enemies, redid levels...

My Programming Journey

Purple Martians was started in the winter of 1997 in a cold, dark, one bedroom basement apartment in Victoria, BC.

I was on a seasonal layoff from a construction job, waiting on unemployment benefits, and I had some time on my hands.

This was 1997 so the high end PC's were Pentium 120 with 16M of RAM. I had an old 486/33 Compaq laptop with 8M of RAM.

1997 was also the year I first connected the internet. I had a dial-up account with Pacific Coast Net.

It's amazing when I think of the time before the internet. What did we do without it?


I was unusual in that I had access to computers at a much earlier age than almost anyone I knew.

In 1978, when I was 10, my dad brought home a Commodore PET from the college where he taught electronics.

I spent a lot of time figuring out how it worked. That was my first exposure to programming.

BASIC. It seems so simplistic and crude now.

But the joy of typing in commands and seeing the results instantly...it was something I fell in love with.

A few years later the Commodore PET was replaced with an Apple II.

Kind of similar, but the one huge difference was the graphics.

Color. 280x192 hi res graphics. Commands in BASIC to draw pixels and lines.

I created programs that drew string art-moire patterns.

But what I really wanted to do was make a video game.

To have a little player jumping around from level to level, shooting and avoiding enemies,
climbing ladders.

Some early influences were Ms. Pac Man and Donkey Kong Junior, the only 2 games at the local convenience store.
The only time I could see them was during school lunch breaks, because I lived out in the country.
For a few years, I mostly watched other kids play, mesmerized, wanting so bad to have a quarter and a turn.
Lunch time was so short there was only time for a few games, so it was rare that I got a turn.

There were a few games that could be played on the Apple. A pac man clone called snoogle. Lode Runner.

Lode Runner had a big influence on the game I wanted to create. Simple block based, puzzle solving.

Other games that had a huge influence are the Mario series, Doom and of course one of my all time favorites,
Bubble Bobble. That game is so amazing with all of the secrets and special items. I consider it a masterpiece.

I had tried many times to make a game. At the bare minimum I wanted a player that could move and jump on platforms.

I first tried to do that in BASIC on the Apple II. The character was a simple collection of drawn lines and pixels.
Very simple and crude. But even that was agonizingly slow as I attempted to draw and move it across the screen.

I experimented with the vector based shape tables built into the apple, and taught myself the the basics of assembly language.
I made some progress, but it was such a huge task, and I did not have the skills to build a complex project like that in assembly.
Eventually I grew up, moved out, got a job, and left programming behind. I never did own a computer, they were all borrowed.
The apple that my dad brought home to learn on, and then in high school I hung out lots in the computer lab that had a bunch
of apples also.


It's hard to realize what computers were like back in those days, before the internet.
They were pretty much all stand alone units used for a single purpose.
I used some in the course of my electronics career, but mostly just to perform one specific task.

What got me back into computers was digital audio. I had been writing and recording music with analog tape
machines for years, and was excited to try digital recording. It looked so promising.
Unlimited tracks, non-linear editing, digital effects.

I started that with a Pentium 100 with 8M of RAM and a huge 1.2G HD.
I bought Cakewalk Pro Audio at the local Long and McQuade and a Soundblaster from Radio Shack.

At that time, consumer computer technology was just barely fast enough to record audio.
There was a lot of pain setting things up, and even at the best, it just barely worked.

This was also the time that I really developed a strong dislike for any garbage that Creative Labs makes.
The sound blaster I bought was advertised as full duplex, windows compatible.
Cakewalk said that all it required was a full duplex windows sound card.
It just would not work. It would record and it would play back, but it would not do both at once.
After spending many hours on the phone with tech support, I finally figured out that by design, this card could only
do full duplex by severely degrading the recording quality. So I returned it and bought a much more expensive
sound card that just simply did what it was supposed to.

In the process of getting tech support over the phone, the guys I were talking to told me about these
on-line tech support forums, that would probably help me way more than telephone tech support.

And that was the catalyst. That was the reason I got a dial up internet connection. I think it was $25 a month.
The forums were great, many people running the same software, running into the same issues, and discussing solutions.

I was able to get my DAW (Digital Audio Workstation) fully functional and did quite a lot of recording for
a few months before my computer and a lots of other valuable things were stolen in a break-in.

I lost all of my digital copies of my music, all I had were the cassette tapes master I had recorded from the DAW.

Months passed and I moved into a bedroom in a basement in Oak Bay. Cold, dark, dingy...sketchy people that lived in the
other rooms. Landlady that lived upstairs and complained about the tiniest noise. She literally complained one time about
the music being too loud when I was wearing headphones.

I had this old broke down 486 laptop, and I still had my internet account. I had been laid off for the winter (it happened every year)
so I had some time on my hands. And with the internet I had the entirety of the worlds information just waiting to be explored.

How hard could it be to make some shapes and draw them on the screen? It had been so many years since the Apple II days. The last time
I had tried to program. That was probably around 1987 or so, 10 years earlier.

I can't remember all the things I looked at then, but I do remember that even back then, I did not like Microsoft.
What they did in the browser wars, plus many other low down shady tactics, plus just using windows and getting annoyed at all the
stupid design decisions, locked in data, predatory business practices. But the worst for me was the crap software.
Barely functional, riddled with bugs, and only successful because they were the largest installed base.

But if I had to use something microsoft to make my game, I resigned myself to give it a shot.

What I found instead was Allegro, a small project by Shawn Hargreaves. It was exactly what I was looking for.
I did not want a game engine, what I wanted was a game programming library.
Some simple functions to draw shapes on the screen. Fast.

Allegro is completely free. Thus began my lifelong love of open source, freely distributable software.
The complete opposite of windows.

I would have to learn to program in C. I did not know anything about it, but I learned fast.

The compiler used is gcc. I am so happy I have never once had to use MSVC.

I followed the install directions to setup gcc for windows (DJGPP), installed Allegro 2.0, and set up RHIDE as my integrated development editor.

The best way to learn is by doing. I had a few books on C, and worked through a couple of examples, but then I just focused on getting things done.

Like for example:

Create a display and change its color. Then draw some different colored lines on it. Then some other graphics primitives like rectangle and circle.
This is pretty cool! Now back to the first days with the Apple II, I recreated some string art moire patterns. They looked great!
OK, enough with primitives, I want to create some sprites and draw them to the screen. That worked great also.

Then in the spirit of doing everything from scratch, I built tools to create, save and edit my own sprites.
I saved and loaded them one get_pixel and set_pixel at a time.
I learned how to save things to disk, file handles, iostreams, data formats. All new and all so very cool.

And also I was leaning C at the same time.

C is so simple and elegant, I like compare it to the game of chess.

Chess has a very simple set of rules about how each piece can move. Those rules can be learned very quickly.
However the strategies of playing the game can take a lifetime to master.

C is similar in that the core functionality of the language is very simple.
How you use those very simple building blocks to create more complex things is an art that can take a lifetime to master.

I had some bad habits from BASIC, but I soon overcame them. Now 25 years later I am still improving all the time.

I love to program. To me all of programming is 'managing complexity'

To simplify, abstract, to make very complex things easier to understand, implement, and maintain.


Now my project uses C++ objects and has over 40k lines of code.

I can't count the number of times I have refactored, I am continually learning and improving.

Older Versions

Click on the date to download older versions.

Note: You will need DOSBOX to run version 4 and earlier.

Version Date Platform Allegro Version Compiler IDE Screen Modes Level Editor Multiplayer Linux Notes
- 19980922 DOS/WIN98 2.2 DJGPP RHIDE 320x200 integrated no no Earliest surviving version (no sources)
- 19981112 DOS/WIN98 2.2 DJGPP RHIDE 320x200 integrated no no Earliest surviving version with sources
1 19981120 DOS/WIN98 2.2 DJGPP RHIDE 320x200 integrated no no Not released. Mentions shareware and full versions but not implemented
2 19991202 DOS/WIN98 2.2 DJGPP RHIDE 640x480 800x600 1024x768 standalone no no First version actually released. Has shareware and full version for $10
3 20000404 DOS/WIN98 3.12 DJGPP RHIDE Allegro Screen Mode GUI standalone no no Changed to free from now on
4 20010301 DOS/WIN98 3.12 DJGPP RHIDE Allegro Screen Mode GUI standalone no no More levels, added sliders in level editor
5 20030622 WIN98/WINXP/linux 4.0 MinGW Dev-Cpp Allegro Screen Mode GUI with windowed mode standalone 2 player split screen source First linux version, 2 player split screen
6 20180311 WINXP/WIN7/WIN10/linux 4.4.2 MinGW Dev-Cpp Allegro Screen Mode GUI with windowed mode integrated 8 player netgame source Finally got netplay to work! Many other changes.
7 20180422 WINXP/WIN7/WIN10/linux 5.2.4 MinGW-w64 Code::Blocks Dynamically resizeable window and fullscreen integrated 8 player netgame binary Ported to Allegro 5.