Spring Lisp Game Jam Entry


Given that I've been learning Common Lisp (to see what all the fuss is about, with respect to REPL-driven development), when I saw a link on Hacker News for a Lisp game jam, I was intrigued.

This post briefly covers my game's (simple and unoriginal) concept, a challenge I set for myself, technology choices/lessons, and a day-by-day progress report. I'm mostly writing this for my own future reference!

Concept

A year or two ago, I had wanted to make a simple word-finding game with a simple goal of finding the longest possible word, so I decided to see if I could throw that together in my spare time during the ten-day jam. To ensure I completed something, I opted to create a simple command line game first, and then pursue a real-time multiplayer game (hosted in the browser, for convenience).

Challenge

Since I was participating just to learn, I set a challenge to try and write all code in Common Lisp, even if it meant writing in a non-native language. For the browser-based version, this meant using various Lisp-to-X translators. I settled on:

  • Parenscript for JavaScript
  • Spinneret for HTML
  • cl-css for CSS

Luckily, I didn't use a database, so I didn't have to find a translator to SQL.

Technology choices

  1. Use WebSockets for real-time interaction amongst browser clients
  2. Embrace "development in production", with a REPL (and Emacs SLIME) connected directly to the production server to (hopefully) speed development
  3. Use Spinneret for HTML and Parenscript for direct DOM manipulation instead of some VDOM solution, just because I ran out of time for learning new technologies (and figured, worst case, I could just reverse engineer Parenscript from the JavaScript I'd normally write)
  4. Use s-expressions as a data-interchange format (... or not)

Lessons learned

I learned a lot in a short time, but unfortunately most of what I learned revolved around what not to do:

  1. Distributing 100% portable Common Lisp binaries is nigh impossible on Linux, especially if you're developing on Alpine Linux.
    1. I had hoped to use ECL, but, even with decades of C experience, I couldn't get it to produce a fully static build.
    2. SBCL can run on musl libc, but I haven't found a reliable and maintained fully static version--also, the binaries are ridiculously huge (fine for most cases, but not for my trivial game that is probably < 1 MB, including data).
    3. AppImages require glibc, and thus don't work on Alpine Linux! I was pretty disappointed when I learned this, since I'm running on a musl libc-based distribution.
  2. Data interchange formats: I couldn't find a secure s-expression-based serialization library (Common Lisp's default functions are ripe for injection, annoyingly), so I ended up just using JSON -- this felt like a letdown, but not a huge deal.
  3. Developing in production works, but don't do it all from within SLIME! If you disconnect from the Swank server, it will subsequently hang on each attempt to write output. Solution: start the server from a normal REPL and just tweak via Swank.
  4. ngrok's free tier is impressive, but it can't support public WebSockets because it sniffs for browser user agents and then adds an interstitial HTML page to the HTTP Upgrade request. Solution is what I wanted to avoid: running and managing a public endpoint myself.
  5. Mobile browsers are extremely aggressive about suspending tabs (and thus closing WebSockets). Theoretical solution: add suspend/un-suspend hooks and reconnect the WebSocket if needed ("theoretical" because I haven't implementing anything like this yet).
  6. It's (still) basically impossible to format using CSS quickly without a 100% interactive experience. Sadly, I didn't have time to set anything productive up, and just resorted to playing with F12 dev tools and then translating back into cl-css code.

Day-by-day progress

  • May 26: Generated a word list (most frequent words from the YAWL corpus)
  • May 27: Implemented command line game loop
  • May 28: Investigated binary distribution options (static SBCL/ECL builds, AppImages), eventually giving up
  • May 29: Prepared backup submission (the command line version)
  • May 30: Investigated libraries for browser-based version (Hunchensocket, Lisp in Parallel, Parenscript, Spinneret, cl-json, cl-css)
  • May 31: Partially implemented WebSocket-based server
  • June 1: Completed server (mostly)
  • June 2: Discovered ngrok free tier couldn't support public WebSockets, settling on standing up a simple VPS instead
  • June 3: Implemented basic HTML+JavaScript front end
  • June 4: Added a countdown timer, hall of fame, and mobile formatting

Get Thirteen Letters

Leave a comment

Log in with itch.io to leave a comment.