It all started with our most recent OpenDNS hackathon. Or rather, just after it on Friday — after 24 hours of frenetic work, demos, and of course, lunch. There was a lull in the air; people were too tired to get real work done, but didn’t quite feel like heading home for the day. It was at that point that our director of engineering said, “Hey, who wants to see if we can figure out how to play Zork in HipChat?”

In case you didn’t grow up during the earliest days of PC gaming, there was a time when Zork was all the rage — or, more accurately, the whole family of Infocom text adventure games. The game describes each location, and you move around and interact with the world using text input…in other words, the perfect kind of game to play in a chat room:

Screen Shot 2015-10-19 at 3.50.14 PM

Rather than reinvent the wheel, we decided to leverage Hubot to do the actual interfacing with the chat room. For one thing, we already use Hubot in our chat rooms, so that was a time saver right off the bat. Hubot is basically a collection of plugin scripts that listen for expressions in chat rooms and responds, so all we had to do was write a plugin that would listen for game inputs, send it off to a copy of the game, and then return the output as a chat response.

As it turned out, the ‘copy of the game’ part was relatively simple. The first decision was to build a web service separate from Hubot we could ship game input off to. That way we’d have the most flexibility with the games, and avoid adding lots of overhead to Hubot itself. With that decision made, a couple of people started assembling a skeleton application with Express.

That left us with the question of how to actually run the games. We knew we didn’t want to implement an interpreter for the games from scratch. They’ve been around since the ‘80s, and there’s no shortage of open-source implementations out there. After a few false starts with pure-JavaScript implementations we found, we settled on frotz. It’s a C implementation, but it offers a ‘dumb’ interface that was perfect for us. You pipe in input, it pipes out output. Using Node’s built-in ChildProcess support we had our Express application spawn an instance of this ‘dumb’ version of frotz.

The first iteration of our API was the grossest possible piece of prototype code. It started one instance of the game, accepted commands via a POST request, and echoed back whatever the game returned in the response to that POST. That was enough, though, to point our Hubot script at and play a few turns. Of course, it was rough. There was one game, and if people played it in one room, the state would change unexpectedly for people playing in other rooms.

In the days that followed, we made a few improvements:

  • Cleaned up the code quite a bit
  • Added the ability to start multiple game instances at once
  • Added support for choosing which game to load when starting a new game
  • Added support for per-room and private message game sessions to the Hubot connector
  • Added support for rooms where no prefix is required for Hubot to treat text as game input
  • Put the lot into CI and brought up the web service on Quadra, our in-house Docker platform.

And that’s where the project stands today. We’ve spent the last few days cleaning up the code’s more egregious embarrassments, and are happy to say that the zmachine api and the Hubot connector are both up on our GitHub account. We’d love for more people to rediscover the fun of old games, and all of us who worked on it are really looking forward to seeing what comes of the projects on GitHub.

By the way, while the Infocom games are a little hard to find nowadays, there’s still a surprisingly large community making games in the genre now known as interactive fiction. Why not check out a few of the sites available out there to grab some games to play?

Special thanks to the team of OpenDNS Hackers who made this possible:

Justin Swift
Josh Eveleth
Doug Tabacco
Ian Hook
Geoff Townsend
Eric Reynolds

This post is categorized in: