Stratego online
Building a realtime multiplayer version of the board game Stratego
Fri December 15, 2023
tech
TLDR
I've been working on a realtime online version of the board game Stratego, and it's at a stage where it's finally (mostly) playable. You can find the game here and the codebase here.
Premise
A couple years ago, my brother and I got into playing the board game Stratego online. It's an awesome open-source implementation of the classic game, and it plays very smoothly.
Inspired by this, I set out to create my own implementation using Phoenix LiveView. I've done several Phoenix projects over the past couple years— this site one of them— and LiveView felt like a natural choice for a realtime browser game. I set out to make this mostly for the fun of building something, although I also figured I'd be able to throw in new features since stratego.io is no longer being updated.
At this point, I've got a mostly-playable (at least for two players) game, with plans to wrap up 3/4 player in the coming weeks and then maybe move on to other fun features (a "blitz" mode with smaller/quicker games, an AI implementation, etc). The codebase is public on Github; it definitely needs to be cleaned up, but feel free to open an issue if you find a bug or want to request an enhancement.
Implementation
I truly loved writing the game logic in Elixir. For me, there's no programming language as interesting and productive right now; the more I work with it, the more impressed I am.
I feel similarly about Phoenix LiveView. For realtime functionality, it's shockingly simple to set up and run. It's a tradeoff: having used React/Next.js for the majority of projects in my professional career, I sometimes find myself missing the expansive JavaScript community and can't always accomplish simple features as quickly in Phoenix. That said, writing Elixir instead of JavaScript is a beautiful thing, and PubSub and GenServers are soooo fun to work with. To put it succinctly, the menial work sometimes has more friction with Phoenix, but the complex and interesting problems are way more fun to solve.
Anyway, the project's been a lot of fun to work on, and each new Phoenix/LiveView release brings awesome new features that have further improved developer experience. While working on this, I've learned/reinforced a few lessons I'd like to share.
Takeaways
1. Plan ahead, but don't overcomplicate. Some things that felt a bit "hacky" to me at the start ended up being perfectly reasonable design decisions. For whatever reason, my instinct on a few points was to opt for the theoretically-perfect-but-practically-infeasible solution. For example, I wanted to have a model for the game's board, and maybe a model for a piece... or for a cell on the board... or both... After a brief exploration, I realized this would be both unnecessary and difficult to work with. Representing the game board as a 2-D array of strings met all of my constraints, and it was easy to build the game logic around this state. No need to go overboard.
2. Use the Phoenix boilerplate as a guide. This one's framework-specific. The Phoenix community isn't huge, and it's common for me to google a question and not come up with many useful results. This is especially true since the framework has changed significantly in recent releases. It took me a while, but eventually I realized I could learn a lot by reading through the core_components
file that comes with a new LiveView project. My LiveView abilities in things like modal transitions and effective component design greatly improved thanks to using those starter components as an example. (Now I just have to go back and refactor the earlier code...)
3. (Some) duplication is okay. This is a lesson I've learned and relearned in my professional life. As a new developer, my instinct was to try to reuse code as little as possible. I think that's a goal that's drilled into programmers' brains a lot early on— the acronym DRY comes to mind— but it cuts both ways. There's certainly plenty of bad duplication that results in a messy, hard-to-maintain codebase; in my experience, duplication in business logic can and should often be condensed. But I've also witnessed (okay, been responsible for) plenty of over-engineering to make e.g. a given UI component handle more responsibilities than it needs to. Lately, I've felt much more comfortable using multiple views or components that accomplish slightly different purposes, rather than trying to cram a broad range of functionality into a single ultra-flexible super-component.
Thoughts?
As linked above, you can find the Stratego game here. The codebase can be found here, on Github. Find a bug or have an idea for an enhancement? Open an issue on the Github repo!
© Mike Considine 2024
Drop me a line