Terry Pratchett is one of my favorite authors, and I’ve read just about all of his Discworld books. Sometimes I like to combine my various interests, so a few years ago I decided I wanted to build my own dedicated, portable “Cripple Mr Onion” player – a device so thoroughly, impractically useless that it’s practically just begging to exist (a lot of my projects start out that way). My first attempt eventually petered out, but I recently re-attacked the problem with renewed vigor, and I’m pretty satisfied with the results.
Attempt the First
My initial stab at this, way back in 2010 or so, was built using a Picaxe-28X microcontroller in a custom laser-cut wooden case, a giant serial LCD display, and a rechargeable battery stolen from a surplus Cyber Surfer (another nearly useless device, a pallet of which showed up at NYCResistor sometime in 2009 courtesy of my friend Alicia).
This attempt failed for a few reasons, but primarily:
- I wasn’t a very good programmer at the time. Card games actually require some tricky programming, particularly if you’re in a very resource-constrained environment. That’s actually a big part of the fun of making something like this, but I got bogged down too much on my first attempt and eventually got distracted by shinier things (namely my Cray work).
- The technology at the time was way worse. My weapon-of-choice back then was the Picaxe series of microcontrollers (PIC uCs loaded with a BASIC interpreter), which were both very slow and very limited in terms of resources, as well as being limited to using Picaxe BASIC for programming them.
Attempt the Second
I was doing some shelf-cleaning at NYCResistor a year or so ago, and I stumbled upon my old prototype (which led to me lamenting my previous failures on this front). With Terry Pratchett’s recent passing, I decided I really needed to finally make this happen. My free-time is somewhat more precious these days, but I had two things going for me – I’m now a much better programmer, and a few years of Moore’s law has been kind to embedded electronics.
For Christmas, my delightful wife gave me an Arduboy – “It’s like a Gameboy, but you have to write all of the software yourself!” This let me focus on just the software bit, which was super fun to write. Having never written a card game before, it was also a generally fun learning experience.
Crippling Mr. Onion
Enough yammering – let’s get to the crippling! Cripple Mr. Onion is a fictional card game played throughout the Discworld universe. Discworld enthusiasts fleshed out the rules in the early 1990’s with Terry Pratchett’s blessing, and thus a hilariously complicated card game was born. The game is a sort of mix between blackjack and poker, and requires an 8-suited deck of cards and a lengthy list of rules. My goal was to cram a suitably fun version of this onto my poor, unsuspecting Arduboy, thus providing me with tens of minutes of wholesome, on-the-go entertainment.
A Dream Fulfilled
The Arduboy is powered by an Atmega32u4 giving me roughly the following to work with:
- 32KB of flash space for code (28KB of which is available)
- 2.5KB of RAM
- 16 MHz, 8-bit CPU
- 128×64 monochrome display
- 6 buttons (a D-pad and A/B buttons)
- Rechargeable battery and nice, compact case
From a technical standpoint, this falls firmly into the one-arm-tied-behind-my-back engineering category that I consider my comfort zone. The main constraint is the flash space, which has to contain both code and any graphics the game uses, but 32KB is plenty for a simple card game. My initial plan was to flesh out the basic game logic, and then add graphical embellishments until I ran out of flash space. This strategy worked pretty well. Final result?
Sketch uses 26668 bytes (93%) of program storage space. Maximum is 28672 bytes. Global variables use 1801 bytes (70%) of dynamic memory, leaving 759 bytes for local variables. Maximum is 2560 bytes.
From a creative standpoint, it was more important to me that my implementation was true to the game in spirit, if not necessarily in exact detail. I’d like to think my implementation is at least truer to the original than, say, E.T. on the Atari was. Also, for anyone that’s never done it before, it turns out that drawing monochrome sprites is extremely fun, particularly with such a whimsical theme in mind.
Welcome to the Ankh-Morpork Casino! You play as a character trying to bet their way up the Discworld social ladder by accumulating as much money as you can. You can choose your name and player type (from a wide cast of Discworld characters), and save your character state to EEPROM between sessions. I actually put a reasonable amount of effort into making it both fun and playable, and I think it turned out reasonably well.
For the card game itself, you play one-on-one versus the dealer, like a blackjack game. Adding additional players seemed needlessly complicated, particularly given the cramped screen real-estate. Players are each dealt 5 cards face-down, of which they can trade in up to four. Each game starts out with a $25 bet, and after you trade in your initial cards, the player can raise the bet up to $500. After raising, each player is dealt an additional 5 cards, and the hands are then evaluated.
Anyone who glanced at the rules might have suspected that evaluating the hands (i.e. determining who actually won) might be pretty tricky, particularly on such a constrained device. They would be absolutely right, and compromises abound in my implementation. The only ‘modifier’ I support (at least at the moment) is the ability to “Cripple Mr. Onion”, which I felt was basically a requirement. I had initially thought about making the player choose which hand to play somehow (thus requiring them to memorize the rules), but I ultimately simplified things by just searching both players’ cards for the highest value hand they can play. I know some of my evaluation logic is a bit incomplete (handling whether Aces are worth 1 or 11 doesn’t always happen correctly, for instance, so a few card combos will probably get evaluated incorrectly), but it works well enough to be pretty fun in practice.
As you gain money, your character increases their ‘rank,’ with the ultimate goal of becoming the Patrician. If you lose all of your money, however, you have the opportunity to join CMOT Dibbler selling sausages to scrape together enough cash to make your way back to the tables. Go bankrupt enough times, though, and Death steps in to put you out of your misery (with a vengeance! He not only resets your character settings, he destroys your saved character state stored in EEPROM as well!).
A Temporary Setback
About 2/3 of the way through developing this, I somehow managed to corrupt the bootloader of my Arduboy. Despite all of my efforts, I was unable to revive it, and I nearly gave up on this project for a 2nd time.
I contacted the wonderful support people at Arduboy.com, however, and they mailed me a replacement right away. From an embedded electronics standpoint, the quality isn’t super amazing, but their support more than made up for it in this case. Thanks, Arduboy! With a replacement in hand, I was able to finish without any further issues.
Seeing it in Action
For those that wanted to see Cripple Mr. Onion in all of its monochrome glory, enjoy!
Room for Improvement
The only real obvious ‘problem’ is that the hand-evaluation code isn’t perfect. It’s pretty good, but it’s not perfect, and it could probably be perfect without a ton more effort. That being said, there is plenty of room for improvement. In no particular order:
- The sprites could be compressed. I used the Arduboy2 library for everything, and I used the most straightforward method of drawing graphics – just raw, monochrome bitmaps, using this handy tool. The Arduboy2 library supports compressed bitmaps, though, so just converting all of the graphics would probably save a few kilobytes of flash space with pretty minimal effort. Each character is currently using 128B of space, with each full-screen image using a full Kilobyte. This is definitely the lowest-hanging fruit.
- Sound! The Arduboy has a built-in, ultra-crappy speaker. I would love to add some theme music and simple sound effects (and the ability to disable them, of course). It would probably make the game generally feel more polished.
- Modifiers! The card game supports several ‘modifiers’ that can be played mid-game, vastly complicating hand evaluation. I just ignored these, for the most part, but it would be cool to add them if possible.
- Discworld Mini-games! There’s almost certainly no room left for it, but it would be fun to add Discworld-themed mini-games, as well as additional graphics / cut scenes (particularly when you jump ranks). Actually forcing the user to sell sausages, or adding a City Watch game or something would be fun, and give the game a lot more ‘depth.’
Package the game up properly in *.arduboy format for distribution. I might actually get around to doing this.Done!
- Generally clean up the code. It’s currently in ‘rough-first-pass’ mode. The general formatting could be cleaned up, some of the states could be compacted (I added the whole ‘substate’ concept when I was about 70% done, and didn’t bother to go back and apply it to earlier code). The code could probably be reduced by at least 20% with a reasonable amount of effort – particularly by abstracting the combination-enumeration code in the hand-evaluation function so that it isn’t just repeated in slightly modified form everywhere.
Grab a copy!
For any fellow Arduboy owners and Discworld enthusiasts out there (a Venn diagram that probably includes at least a handful of other people), grab a copy of the game and give it a shot! All of my code is public domain as usual, so do what you will with it. Feel free to contact me with suggestions/questions/criticism/angry rants/bug fixes/etc.
Download Cripple Mr Onion – (Rename to .arduboy to use with Arduboy manager, otherwise extract and compile the *.ino file. The *.arduboy file is untested, since there isn’t a manager for Linux yet, but it *should* work)
Rest in Peace Mr. Pratchett – SQUEAK!