Clojure Cup: Puppeteers Take a Prize for Their Lisp-y MUD

I had the pleasure of competing in the first Clojure Cup, a competitive hackathon that highlights the Clojure programming language. I worked with Andrew Roetker under the auspices of Puppet Labs and we won second place for our project, MUREPL, a browser-based MUD that doubles as a Clojure REPL. We are big Clojure fans at Puppet Labs. While we work predominantly in Ruby, Clojure has been finding its way into our development more and more (To learn more, skip down to Clojure At Puppet Labs). The Cup was a great way for us to get even more Clojure under our belts. Plus, writing Clojure is just fun. It’s a very practical and thoroughly modern Lisp dialect that stands on the shoulders of many heavy-weight and battle-tested Java libraries. I’m an even bigger fan of Clojure after a grueling and mostly sleepless 48 hours’ worth of working with it.

A MUD for Learning Clojure

MUREPL is a browser-based MUD, or Multi User Dungeon. Long before games like World of Warcraft, MUDs were the gold standard of multiplayer gaming. Users explored a virtual world together and could do a variety of things: build a character, collect items, fight each other, or simply socialize. Their decreased popularity in the 21st century is usually explained by their entirely text-based user interface. MUDs are a far cry from flashy, modern 3-D games, but often inspire the imagination in ways that make them more fun than their big-budget counterparts.

Why interact with the MUD in Clojure?

Given that MUDs are text based, a player interacts with one with a command prompt by typing commands such as go north or say “hello.” The fun of MUREPL is that its prompt is a fully fledged Clojure REPL. MUREPL was conceived as a learning tool, where people build and interact with the game world by writing Clojure code. Interactivity is one of the cornerstones of programming with a Lisp language. The ability to modify the game as you play is directly inspired by the kind of dynamic, interactive programming Lispers do in REPLs every day.

Technical Implementation

MUREPL’s backend consists of three simple namespaces: handler, commands, and core. The handler namespace contains a simple Compojure app and a main function that sets up the world’s initial state; a Jetty web server; and a Webbit websocket server. The commands namespace contains the entirety of the game’s UI: the various functions that players run to play the game, like go or look. The core namespace contains all of the game’s state and state manipulation. The game world consists of three data structures: a players map, a rooms map, and a set of tuples mapping players to rooms. The maps’ values are simple maps and players and rooms are keyed by UUIDs and names, respectively. These data structures are manipulated with simple functions like place-player!, add-room!, and logout-player!. MUREPL is not complicated: given only 48 hours to build the game, we had to cut a number of corners. Most glaring is what MUREPL lacks: sandboxing and persistence. The lack of sandboxing makes the name “Multi-User REPL” quite literal, as things defined by one user are accessible by others. More amusingly, a clever player can manually update the state of the world via a reference to the core namespace. No persistence means that players’ hard work of creating the virtual world all disappeared when the server went down, which it did about once a day during the judging period. Oops. While persistence will certainly be added to MUREPL, the ability to significantly alter the running program turned out to be a neat feature, and good for learning about programming. Sandboxing may end up being an optional feature that an administrator of the MUD can enable or disable. MUREPL’s frontend is written in Clojurescript and uses the jquery.console tool. The frontend simply takes the Clojure forms submitted and passes them to the backend for evaluation using clj-params. Messages about game world events — like other players entering your area, users logging out, or chats — arrive via websocket and are printed to the console. Clojurescript was a joy to use, but its Javascript interop was a little confusing. I place this blame pretty thoroughly on Javascript, though, and not Clojurescript.

Clojure at Puppet Labs

At Puppet Labs, we use Clojure primarily for developing PuppetDB, a datastore for data that Puppet generates. PuppetDB has become a large and mature open source Clojure codebase, thanks to both hardworking Clojurians within the company and to community contributors.

Puppet Labs: a creative place to work

Clojure Cup was a great experience. I’m grateful to Puppet Labs for its support before and after the competition. If you’d like to come work with us, we have plenty of positions open in software engineering and other departments. We’re a creative bunch, and we welcome other creative people.

Learn More

Puppet sites use proprietary and third-party cookies. By using our sites, you agree to our cookie policy.