Contrary to an infamous opinion from a bygone era, 640KB is not really sufficient for anyone anymore. A typical website exceeds that easily, and executable programs are usually measured inmegabytes.
But what if you only had 1234 bytes to workwith?…
A friend of mine, Gynvael Coldwind , organized a game programming compothat had precisely this limitation. Unlike most demoscene ones, however, the size limit here applies to either the final binary or its source code. This can be chosen at the participant’sdiscretion.
Since my currently favorite compiled language produces the exact opposite of small binaries , I was quite intrigued by the source code option. But as the rules say, the final game must run on a clean installation (only standard packages) of either windows or Ubuntu linux. The choice of viable languages and technologies was therefore ratherlimited.
It was time to get a little creative.
GametheoryWhat must an environment provide to be a suitable platform for game development? Not much, really. We only need to be ableto:
put stuff on thescreen react to userinput execute time-dependentlogicYou could arguably get away without the last one, but the kind of games you would end up with had gone out of fashion about half a century ago . For the “real” arcade games, we really ought to run our code at least a dozen times persecond.
There’s only a handful of standard technologies that allow all of this out of thebox.
I’m a wee bit out of touch with Windows these days but on Linux, there’s one thing that I really wanted to take for a serious spin. And luckily for me, it also has one extremely terse language to go hand in handwith.
I’m talking, of course, about the ANSI terminal that can be scripted in Bash. If there ever was anything that worked anywhere by default, then this got to be it.
…put intopracticeNote that I’ve stressed the “terminal” part. The shell itself is a neat instrument, but (perhaps surprisingly) it doesn’t actually concern itself with displaying anything on thescreen.
This has traditionally been the job of a terminal emulator . To this end, it has a couple of special codes that are undoubtedly useful for an aspiring indie shell game developer. They are what allows us to display things in a specific position on the screen, complete with chosen color, background color, and (text)style.
So this nails down our first requisitefeature.
As for the second one, the vanilla read command supports everything we may need for handling user input. The only real “trick” is passing the -n flag which makes it wait for a specific number of characters (e.g. one) rather than a whole line ending with Enter . Add a few more flags ― like the one that prevents text from being echoed back to the console ― and you can make a rudimentary inputloop:
KEY='\0' while :; do read -rsn 1 KEY doneI can imagine, however, that you’d want to do other things besides just waiting for input. Stuff like “updating the game state” and “drawing the next frame” is generally considered pretty important ingames.
Normally, we would deal with those things in between checking for input events, leading to a particular structure of the so-called real-time loop .
But the shell doesn’t really handle input via “events”. Instead, you just ask for some text and wait until you get it. There is no “peek mode” that’d allow to squeeze in some rendering logic before the next keypress.
What do we do, then, with a tight loop that leaves us no wiggleroom?…
Why, we take a crowbar and pry itopen!
(Don’t) bealarmedLet’s start by noticing that to run some code whenever there is nothing else to do has a rough equivalent of running it periodically . This isn’t an exactly new observation: the setTimeout function in javascript has been the basis of “real-time” animation since the 90s era of falling snowflakes, and up to the contemporary browser games.
Neither does the shell nor the hosting terminal support anything like setTimeout , though. But fortunately, they don’t need to: Linux itself does. And it accomplishes it quite effortlessly, due to the sole fact of being an operating system . All we have to do is access some of its capabilities directly from the shellscript:
KEY='\0' DT=0.05 # timeout value in seconds tick() { # .. do stuff ... ( sleep $DT; kill ALRM $$ )& } trap tick ALRM tick while :; do read -rsn 1 KEY doneWhat we’re doing here is set up the tick function to be a signal handler . A callback, if youwill.
Inside of this callback, we can do all the state updates and drawing we need, as long as we follow it with “scheduling” of the next tick call. As a direct equivalent of a setTimeout invocation, this can be doneby:
starting a subshell to run in the background (with & ) letting it sleep for however long we want to delay the nextupdate sending a signal to the main script ( kill $$ )The signal we chose is of course SIGALRM . Technically, however, it can be anything, as long as we can set up a trap to actually handleit.
In any case, success! Bash is officially a game programmingplatform!
Integration inpartsAnd so having figured out the technicalities, I was faced with the crucial dilemma: what game could I actuallywrite?
Nothing too complicated, that’s for sure. After the initial scaffolding has used up about 1/4 of the harsh size limit, I knew that radical simplicity was the order of theday.
And so I went for possibly the most trivial game ever .

Sorry, Pong!
Then, after hours of ( ahem ) meticulous research , I managed to reverse-engineer the coremechanic:
let the bird fall down with a constantacceleration to jump, give it some upwards-facingvelocity Actually