BeginnerMediate

Not a beginner — Not a comfortable intermediate — and certainly never done

View my projects on GitHub

Morse Code Game

28 May 2019

Trevor Clack


The following is the explanation of a game I wrote uploaded here to my GitHub.

Non-standard libraries needed:

readchar      -   pip3 install readchar
termcolor     -   pip3 install termcolor
sox           -   sudo apt install sox

Background

I don’t really know what it was that first drew me to Morse code. I guess I built it up in my head from watching too many movies as this arcane secret language. I tried learning it at two different points in my life, so for whatever arbitrary reason, it has kept returning to my thoughts.

It started with a beep…

I remember I wanted to make my computer beep for some reason that now escapes me. I was probably running some long script and wanted an audio signal to let me know it had finished. So I turned to google. At first I found purely pythonic ways of doing it where you define a sine wave and specify its wavelength and frequency, but that ended up being overly complicated and too many lines long. I just wanted a simple beep. I eventually found a Linux library (Doesn’t come by default)

sudo apt install sox

“SoX reads and writes audio files in most popular formats and can optionally apply effects to them. It can combine multiple input sources, synthesise audio, and, on many systems, act as a general purpose audio player or a multi-track audio recorder.”

…and so on according to the man pages. It’s the quite British ‘synthesise audio’ feature that we are interested in.

Try out the following command in your terminal

play -nqt alsa synth 1 sin 850

-q “quiet”, silences progress which is usually displayed during the build
-n “null” as in we aren’t giving an input file
The rest means we choose alsa (a built in audio driver) synthesize for 1 second a sine wave at 850 hz.

The core definition in the code is MorsePlay() which will “morsify” any text, however it comes about (There are lots of games, so many ways to have characters generated). This is done with nested if loops. We have a dictionary that relates the ascii character to the corresponding Morse string then from there call dot() or dah() for any . or - symbols. So that’s it, we are done!

Except we aren’t! Because there are some more subtleties to be discussed.

Some of the games include playing sets of 5 random letters or grabbing a quote or Wikipedia article and playing it while the listener types what they hear. During my first attempt, the audio would play, but the user couldn’t type anything in until the full audio had finished, and that can take a while, especially for extra long Wikipedia paragraphs, so I implemented multiprocessing. I also have a learning mode where you hit keys on your keyboard at a whim and it will play them in Morse. I implemented threading for that to smoothen it out, otherwise the characters you hit during the time the Morse audio is playing wouldn’t get picked up.

On the note of keeping things smooth, I wanted for some game modes, especially the speed runs and the single character translations to just play automatically as the key is pressed; it’s annoying to have to hit <enter> each time. I could have used the pygame library, but that would have added too many lines of code. Instead I found a wonderful and simple python library called readchar (not a standard one, you must install). Consider using it over pygame for simplicity.

Here is a preview of the game, feel free to try it :D Morse Code Game Menu

Extras

For absolutely no reason, I wanted to color some of my texts. So I imported termcolor (again not a standard library, sorry). It was my first game, so I was proud of it. I also want ed to change the screen size when you start (you know, so it’s obvious that you’re playing a game… also to perfectly fit the menu). So if you ever want to change the screen size from terminal and are too lazy to drag it to (or you’re a Linux nerd who must know these things) try this:

printf '\e[8;38;80t'

It can also be done with a much simpler function resize -s 38 80 which is much simpler syntax but that requires installing a nonstandard library (xterm) and I’ve already done too much of that to you. Besides, this is more esoteric making it that much more awesome!

Threading vs Multiprocessing

Some subtleties here: We have threading and multiprocessing, both are used to increase computing power, but what’s the difference? In short, multiprocessing adds a CPU while threading adds a thread to the same process. So threading uses less system resources and thus is more ‘economical’. It’s a very difficult subject (for me) to wrap one’s head around. I just remember opting for threading and it didn’t go as smoothly when I was trying it for my long paragraphs, so I switched to multiprocessing and it all went well. I’ll continue to use this thumb rule in the future: try threading, if performance sucks, switch to multiprocessing. There’s something called GIL (Global Interpreter Lock) which limits python’s ability to thread, particularly with cpython. You can read more about it as well as see some nice graphical comparisons here.

Easter Egg

There is an Easter egg in the game. You might be able to spot it by examining the code and seeing something that well… just doesn’t belong contextually. But it’s more fun to try and spot it by just playing the game, taking care to read everything.