Wednesday, February 23, 2022

KIMdle: Sorta-Wordle for the KIM-1

UPDATE: I'm trying to solve a debouncing bug for someone who reported it, though I can't reproduce it. If you have a similar issue on real hardware, please try the version up now.

Wordle mania (trademark, probably, of the New York Times) continues. My wife and I, who bonded over word games and later got married because that's how you pick a good life partner, play daily on a private instance, except that she's 19 hours ahead so she has to be careful not to give out spoilers. Retro has gotten into the action. There are Wordle ports for Windows 3.1, Palm Pilots, Game Boys and at least three versions for the Commodore 64, such as this, this and this poop themed one called Turdle, ha ha ha.

Still, however, while these ports ditch dependence on JavaScript and HTML, they still rely on other modern conveniences such as, you know, a screen, a keyboard, and multiple kilobytes of RAM.

You see where I'm going with this.

This is KIMdle, a semi-Wordle for the KIM-1. If you are unfamiliar with the MOS (later Commodore) KIM-1, it was the original 1976 single-board computer for the 8-bit MOS Technology 6502 CPU. It ran at 1MHz, had 1KB (1,024 bytes) of RAM, provided six seven-segment LEDs as a "display" and a hex keypad as input, and was very popular because it was one of the least expensive ways at the time to build your own microcomputer.
KIMdle works on a real unexpanded KIM with just the baseline LEDs and hex keypad (if you feel like keying in a dump or converting it to paper tape). No cheating, no tricks. You can actually play it. It's 100% 6502 assembly language.

To fit this into 1K of RAM with a dictionary — and actually, since I don't like putting code where the processor stack is, it's limited to 768 bytes — required some significant compromises, which is why I call it "sorta-" and "semi-Wordle."

This space limit meant there was no way to have a custom routine to drive the LEDs because I'd blow too much memory budget just on that (letter shapes, timing, etc., and keep in mind not every letter is legibly representable on a seven-segment LED). I would have to restrict myself to ROM routines, most importantly SCANDS, the routine the KIM's built-in monitor uses to display hexadecimal data. That meant limiting the game to letters A-F, plus 0, 1, and 5, because those can substitute for O, I and S. This also reduced the dictionary substantially, allowing single letters to be stored efficiently in a single nybble, and lets the player enter any valid guess directly on the keypad. (As I was writing this up it occurred to me 2 could substitute for Z, but that wouldn't help the dictionary a great deal.) I brute-forced /usr/share/dict/words with a Perl script and hand-edited the extract to only include words that actually appeared in my real Webster's dictionary. A few are obscure, but they're all real! There are 41 of them. The dictionary thus takes up a mere 123 bytes (I had to waste the unused nybble).

The space limit also meant two changes to gameplay, one minor and one major. The minor change is that KIMdle doesn't check if you've entered a legal word; you can enter AAAAA or BBBBB or 55555 and it will accept them. Many of the other small computer ports don't do this either, so this deficiency is hardly unusual. However, the major change is that KIMdle only reports letters you got right in the right place, not any letters that are right but out of place.

The simple reason for that is that the game was already occupying almost all of $0200 through $03ff (the words and temporary data occupy most of zero page) — KIM-1's 1K RAM ends at $0400 — and the search algorithm wasn't going to fit. Plus, it would have to do more bookkeeping than it currently does, too, which also has a memory cost. I could have squeezed a bit more out of the code by not having trivial encryption for the dictionary, but an innocent glance at the hex data shouldn't be an insta-spoiler, and any space I would have recovered in the processor stack (even if it fit) wouldn't be worth the inconvenience to debugging.

On top of that, how would you help the player distinguish a letter that's valid from a letter that's valid but misplaced? There are only seven segments; there's no other way to mark the LED. Plus, those are the same set of LEDs you're trying to enter your next guess into. I toyed with an "alternator" routine that would blink misplaced letters, but this required overhead of its own to display a second set of data and properly overlay it with the new guess the player is keying in, plus the additional code needed in the game loop. So I gave up and KIMdle just tells you what you got totally right and leaves it at that.

At this point some of you will say that I am cheating, because this is a substantial enough deviation to no longer qualify as Wordle. I can't really argue with this assertion, but you've still got a word game reminiscent of Wordle playing on a 1976 single board computer with less RAM than some modern TV remotes, and you don't even need a terminal or a keyboard.

Okay, so you want to play this. If you don't have a KIM-1 or clone but you do have a Commodore 64 or a Commodore 64 emulator, you can use the Incredible KIMplement (which is what I used to get the port up). It runs just dandy in VICE. Another simple emulator which will run KIMdle on your terminal session is this one, which should build on pretty much anything.

To build KIMdle itself you'll need a cross-assembler. Install xa65, either from your distro package manager or downloading it. It has no prerequisites or dependencies other than a C compiler and make, and is very portable. Other cross-assemblers may work, but I don't guarantee it.

Now, grab the source. There are two assembler files in this Github gist. The first one is the game itself; the second is the dictionary. If you are using KIMplement, they already encode a starting address in the file. If you are using another emulator or an actual real KIM, remove the initial .word pseudo-op so this isn't emitted to the output. Then,

xa -o kimdle kimdle.s
xa -o words words.s

If you're planning to load this into a real KIM, the simplest method is to then hexdump those files and key them in by hand. This is labourious but (with the relatively small length) not insane. If you have a serial connection, though, a better solution is paper tape and there are tools to do this conversion, or you can emit commands to the KIM's TTY (which is how I did it); words starts at $0003 and kimdle starts at $0200.

However, let's proceed assuming you're just playing with it in an emulator. If you do this in KIMplement, specify they are "KIMplement format" when loading them and the emulator will automatically use the encoded starting address. Otherwise, load words to $0003 and kimdle to $0200 (remember to assemble them without that leading .word pseudo-op). Once this is done, type 0200 g on the keypad (or, on the TTY emulator I linked above, press CTRL-G). The machine will appear to do nothing, but it's actually waiting for you to press GO (g/CTRL-G) again to seed its simple little RNG. Then the game will begin.

You get six guesses, as in regular Wordle. The display starts off 888880 (the eights represent "blanks" and the 0 means you are on your first guess). Enter letters with A-F, 0, 1 and 5. If you make an error, press GO to clear the line. When you enter five letters, KIMdle will keep the letters you got right in the right place, but will erase everything else back to "blanks," and the guess counter will advance.

If you hit guess 7, KIMdle will display the word. If you got it right, KIMdle will say you aCEd it, with your score. Press RS to reset and quit (on KIMplement, press the Commodore key twice), or any other keypad key to start a new game.

Yes, that's an actual picture of KIMdle playing on my Revision F KIM-1. I look forward to Wordle played in binary on the front panel of an IMSAI 8080. Someone should get on this. I can't be the only one this crazy.

No comments:

Post a Comment

Comments are subject to moderation. Be nice.