It was in last November that I texted the following to my good friend Sam, a fellow computer nerd:
Imagine a videogame where you are an operating system. You have to manage CPU cores, processes, memory pages and swap space. You have to make sure that no process starves, and to swap memory pages when necessary. Your goal is to avoid angering the user by being too slow.
So, what to you think?
"I think you're a big nerd!" was his answer.
So I proceeded to start developing my nerdy game. First I had to pick a tech. I didn't feel like learning how to use a full-fledged game engine for my quite simple project, so I figured a simple 2D library would do. I also had been wanting to get back into Python. Naturally, Pygame was the obvious choice. Pygame also had the added benefit of making it possible to compile a game to WebAssembly (using pygbag), making it playable in a web browser. With Pygame I started my journey, and completed it in what was probably a single week spread across eight months.
At the core of the game, there are processes and CPU's. You can click on an idle process to assign it to an available CPU, and click on an active process to remove it from its CPU. Over time, idle processes go through six starvation levels represented by colours and emojis. If a process spends too much time in the last starvation level, the user becomes impatient and kills it. After having killed 10 processes, the user becomes so angry that they reboot you — the operating system —, ending the game. The goal is to survive as long as possible without getting rebooted. That means making sure that every process spends enough time on a CPU to not go through all the starvation levels.
An active process can also become blocked because it is waiting for an I/O event. Blocked processes waste CPU time and it is therefore a good idea to remove them from their CPU. I/O events must be processed by clicking on a button that changes appearance when events are available.
As the game progresses, more processes appear, making the game increasingly difficult. At some point, all these processes start taking more memory than is available in the RAM, so you need to start swapping memory pages between the RAM and the disk. An active process starts blinking when it is trying to access pages that are on disk, and the corresponding pages also blink. This is when you know you need to swap pages.
A process that is trying to access pages that are on disk will stay blocked until the pages are placed back in RAM. If it stays blocked for too long, it will keep going through the starvation levels and eventually get killed.
Finally, the game has multiple difficulty levels available, which influence things such as the number of CPU's, the amount of RAM, the number of processes existing when starting the game, the probability of I/O events, etc. It also has a custom mode where all these settings can be tweaked independently.
One has to keep in mind that this game is primarily, well, a game, and as such, has been designed to prioritize playability over realism. The first way in which it is not entirely realistic is the obvious fact that the player is not expected to have the speed of an actual computer! Many other details are technically wrong, such as processes using WAY LESS memory pages than typical actual processes would do, and the fact that a computer user does not usually keep launching new processes indefinitely — that is solely a game mechanic to make the game increasingly difficult.
In other words, this game has not been created with education in mind. All that being said, I do believe it can have some value in introducing computer science students to operating system principles like process scheduling and memory swapping, as long as it is made clear that it is not an exact depiction. As a computer science teacher myself, I might use it this fall while teaching a class about computer components, to better illustrate what it actually means for a processor to have more cores, or what happens when we run out of RAM.
Compiling the game to WebAssembly was easier than expected, thanks to the documentation available here. The main steps are to install pygbag and implement the modifications to the code that are detailed in the documentation. The biggest problem I encountered was with the library I was using to render emojis, which I could not make work with pygbag. I ended up downloading SVG files from OpenMoji and using GIMP to resize them as needed and export them to PNG.
By default, the game adapts its size to the browser's viewport, while maintaining the same ratio as the desktop version. It ends up being stretched if the desktop version uses a smaller window size. This does not result in unbearable pixelization for my game, which has a somewhat retro style, but your mileage may vary.