DEV Community

Cover image for Porting a board game to the web
Eric Tillberg
Eric Tillberg

Posted on

Porting a board game to the web

For almost a year, I've been working (with the gracious help of friends!) on a web implementation of a board game, Imperial. Of many attempted side-projects of mine, this is the one that has made the most progress. Therefore, I wanted to take the opportunity to reflect on what went well, what hasn't gone so well, and what I continue to be ambivalent about.

By way of introduction, the project is an open-source web app with a JavaScript game engine on the front end that operates on a game log. The game log is a series of actions and the entire log is consumed by a VueJS front end, which then renders a nice map and numbers among other things in the gameplay UI. Until rather recently there was no database or authentication system backing it, but I have since then added a very thin Rails app to handle those responsibilities. The project also went through a period in which there was a Go WebSockets server (now entirely replaced by Rails and ActionCable).

What went well

It works! (mostly)

My Imperial implementation more-or-less faithfully reproduces the rules of the game and is playable. In one sense, this is the end of the "invent-out-of-thin-air" portion of the software development process and I've now entered the part where I actually test it on real people. Of course, playing real games with real people has revealed many more edge cases and game rules that I hadn't anticipated and correctly coded from the start. But by and large, it works.

One lesson from this experience that I've picked up is that board game rules are far more complex, logically speaking, than the logic that backs your average web app. Testing becomes much more challenging because some of the situations you'll find yourself in are very particular. But I'll get to testing and TDD later.

I learned a ton

I had never used Go before working on this project. I had never really encountered "event-based architecture". I had never worked with WebSockets in a serious way. I had never used VueJS. Really, the only familiar thing to me was the Rails component, and that was slapped on at the very end.

The truth about how I managed to make any progress whatsoever is that I had guidance and help from friends. I don't think courses or blog posts could have conveyed to me some of the nuances that I managed to learn from friends who were more experienced than I, and who were willing to give me their time. Much of the most complex parts of this code was written while pair-programming.

Some people are playing it

For the longest time, this project was a learning-only endeavor and I never imagined other people might play it. Once it started taking shape and seeming plausible that I could actually put it into production and let others play too, my appetite grew with my ambition.

I've been very encouraged by the enthusiasm out there, in both board gaming and programming communities. Some people are very interested in seeing this game come to life online while others are intrigued by some of the technical decisions I've made along the way. I'd love to reach more casual board gamers and I think I'll need a few more rounds of thorough testing before the game is iron-clad enough for broader appeal.

What didn't go so well:

I got obsessive about it

Side-projects are dangerous for one's private life and they get even more dangerous if they are successful in any way. I found my mood fluctuating with the fortunes of the program. If I managed to get a certain action working correctly, I was elated, but if I was stuck on some webpacker nonsense, I got depressed.

I had a rough time a few months ago but things have ironed out and gotten better. Honestly, I don't have a great learned-lesson from this one because I think it would have been justifiable for me to give it up earlier, when things weren't going well. It becomes a very personal decision and I think my tolerance for the emotional whiplash was perhaps too high.

Testing and TDD

I've always been a strong TDD advocate with the nuance that it only makes sense if I kind of know what I'm doing. If I don't know what I'm doing, then I'm effectively writing spike code and it should be disposable. This works fine in a normal work setting, where I'm more comfortable with the languages and paradigms at play, but it got to be immobilizing on Imperial.

The result? Some of the code is well-tested and sensible. Other parts are spaghetti code that I don't know how to disentangle (and it's unsurprisingly not well-tested). There is a real art to working on a project and only taking on conceptually (or linguistically) novel ideas in measured doses. Too little, and you learn nothing. Too much, and you're writing frustrating code that probably won't tolerate too much change. More of the Imperial code is the latter kind than I'd like to admit.

One additional compromise that I made in terms of testing, but which I think is working out nicely, is to leave the game logic technically not all tested but have some end-to-end tests cover the gaps between the logic and the UI. I recently introduced Cypress to the project and the setup was thankfully simple. The tests take awhile to run but they give me more confidence that everything is working.

What I'm ambivalent about:

The architecture

From the start I was playing with the idea of making it some kind of peer-to-peer game without a centralizing server. After starting to code up the game (including the idea that the game logic would live in browser-housed JavaScript but not be "front-end code") but before investigating the implications of that idea very far, I determined that it made much more sense to have a centralized server for those web app niceties we've all come to love (database, authentication, etc.). What this means is that I now have the game logic inexplicably living in the browser, which is probably confusing for other developers who might want to get involved. But, in truth, it's fine and I don't believe anything is worse off for this decision.

Where to go from here?

I want help on this project. I want some other developers who are interested to get in touch with me. I am happy to help them contribute meaningfully to the codebase. I also want more people to play the game!

The GitHub repo is here and it can be played in production at https://www.playimperial.club.

Top comments (2)

Collapse
 
jayarghargh profile image
Justin R

hey Eric - this is really cool! How did you go about making the map. I'm defo going to put some time aside to read the rules and have a game!

Collapse
 
thrillberg profile image
Eric Tillberg

Hey Justin, thanks for the message! Yeah the map was one of the more arduous parts of the project. I started by grabbing SVGs of historical maps of the various European countries from Wikipedia (they're all open for use, as far as I could tell). This was great for the countries themselves but you may notice that each major power is subdivided into regions. For those I had to manipulate much more detailed SVGs that included interior boundaries. Anyway, with these SVGs in hand, I used Inkscape to manually futz with them until they looked halfway decent.

Russia was a special case since finding maps that were confined to only the European parts was important because of globe-curvature skewing that I got with SVGs of all of Russia. But those maps tended not to have the interior boundaries. So Russia is more done "by hand" than the others. If you look closely at the Russian borders, they are more jagged and clearly drawn with a trackpad.

That is all how I made the map look correct (or close to correct 😂). In terms of the VueJS code to make it all clickable, I had to make each province be its own Vue component so that I could load them up with click handlers and such. I believe I made use of dynamic components, but I'd have to look back at the code to confirm.