Source lives here. Play it here.

In a joint effort, Aliasing and myself have created a novel top-down action rogue-lite for the 2023 Spring Lisp Game Jam. Aliasing is an experienced game dev so in a way, I was along for the ride. Still, I managed to contribute some game mechanics, features, unit testing, CI/CD that deploys to on every commit. This was a fun devops exercise for me - Aliasing mentioned to me that I helped keep him on track with the addition of automated testing and per-commit deploys to a website (it makes it easy to play-test pull requests).

§Technologies used

The game runs in Love - a game engine that is programmable using Lua.

The game is written in Fennel - a lisp embedded in Lua. Why Lisp? Structural editing. Everything-is-a-value semantics. Less-varied syntax which is easier to read and type. Macros unlock the capability to parameterize code at compile-time - leading to expressive, concise code.

The CI/CD and local builds used Nix. There is one exception - to save on development time we opted to use an existing GitHub action for the Linux and Windows release builds. macOS builds forthcoming.1 Nix proved to be a helpful choice: we had issues with failures that would occur only in GitHub Actions early on, so we opted to use a flake to specify exact dependencies to use for each build.

§Playing to our strengths

Aliasing is an experienced, very clever game dev and I learned a lot about making a game in Love (in fennel, no less!) as a team. Aliasing built the game engine on top of love while we deliberated on game design ideas. Personally, I have no game dev experience, but I do have a lot of devops and project management experience.

While Aliasing worked on core game mechanics, I used my devops skills to create a runway for success. Here is a brief list of the devops and PM strategies we used:

  1. We used a PR workflow but reserved the right to merge if the other is AFK for too long.
  2. We set up the unit test support. Took a lot of research as there’s a lot of testing frameworks, our first couple choices didn’t meet our technical requirements.2 We ended up using luaunit.
  3. We set up the web, windows, and linux deploys. Each commit would result in a new test game webpage. This allowed us to playtest every change in our pull requests. Because of the sheer convienence it was easier to playtest than to review the code.
  4. We met to re-prioritize tasks once or twice. Mainly to just make sure we’re aligned on our goals and ideas of done-ness.

§Call to action

Whenever I end up working on something I have this wish-list of things I hope existed. Does anybody else wish these things existed?

  1. docset for Fennel
  2. docset for Love
  3. A contract system for Fennel. Think like Racket contracts or Pycontracts.
  4. A nix derivation that has a headless flag as to reduce runtime dependencies of Love. This would to speed up GitHub Actions running the Love binary - such as unit tests.

If you’re building any of these things I’d love to help… :)

§That’s it

I had a blast and I’m looking forward to another opportunity to tackle some engineering problems like this again. I’m sold on Fennel. Whenever I need tot rouch a system programmable in Lua, I’m using Fennel from now on. A lot of software uses Lua for its scripting engine.3 Feel free to hack on the source code or open a PR. Or maybe just play the game :).

  1. The lack of macOS build isn’t due to a lack of trying; I had tried to re-install macOS on a 2014 Mac Mini, however it seems Apple’s “Internet Recovery” feature errors out during installation. Additionally I tried to obtain a macOS installer USB. Turns out it is not trivial to write a macOS installer USB as Apple does not publish download URLs. I found some mediafire links to the .DMG files, however had no luck using dmg2img then writing it to a USB - dang thing wouldn’t boot. I am not an Apple fan, except for AAPL stock performance. ↩︎

  2. The tests must run within love2d. This eliminated a few that use an external program to run tests. The other requirement was it had to work with fennel. Some use globals injection at test-time, which breaks fennel’s compiler as it can’t resolve variable references. Also easy to use would be ideal. ↩︎

  3. Some programs that I use that are scriptable in Lua:

    • Awesome window manager
    • Love2d the game engine as seen in this post
    • MPV the multimedia player
    • Pandoc document processor/converter
    • Nmap uses it for scripting. If you ever want to see super basic protocol implementations - check out its service discover scripts.
    • Many games including: Factorio, World of Warcraft, BZFlag, Project Zomboid, NetHack, The Battle of Wesnoth, and so on.