POSTS
Friend Off!
A free game I made for you and your friendsFriend Off is a web-based multiplayer game I made over the past year. In it, you ask your friends a question, receive all of their answers without their names attached, and then try to guess who said what. It’s free and open source software, so anyone is welcome to play any time by visiting friendoff.net.
Why?
During the COVID-19 pandemic, my friends occasionally hosted trivia games over teleconferencing services. This was charming but labor-intensive. They had to curate questions, drive the gameplay, and tabulate scores as we went along. They inevitably struggled to fully participate, and even the non-facilitators couldn’t interact as much as they would have liked.
As a software developer, I naturally started wondering about how much of this work could be performed by a shoddily-programmed machine. Game lifecycle management and scorekeeping are obvious candidates for automation, but question selection? Not so much.
It got me thinking about tabletop games like Apples to Apples and Cards Against Humanity. Those are interesting because they make a mystery out of your friends’ actions: each round, everyone answers a question, and one person picks their favorite answer. The games’ biggest weakness is how tightly they constrain player input. Rather than submitting the best or funniest or darkest answer they can imagine, each player chooses from a literal handful of random responses. This occasionally inspires serendipity, but it rarely feels creative.
Who Do You Know?
Friend Off tweaks that formula a bit. Answers are in free text, so players can truly express themselves. This change alone might ruin Apples to Apples since it would advantage folks who have a certain kind of wit. By also changing the goal from giving the best answer to making the best guesses, there’s no specific skill to find victory. It’s really just about the BFFs.
Players might wonder “who do I know best?” rather than just “who’s answered the more questions correctly?” making scoring this free-for-all a multidimensional affair. Friend Off attempts to convey affinities between players using a network graph where players are clustered according to their mutual familiarity.
The game provides the same data in tabular form for folks with low/no vision and for stats nerds.
Mike | Mark | Yve | Matt | Karen | Caroline | |
---|---|---|---|---|---|---|
Mike | 16 | 2 | 16 | 16 | 2 | |
Mark | 16 | 20 | 6 | 0 | 0 | |
Yve | 2 | 20 | 4 | 2 | 16 | |
Matt | 16 | 6 | 4 | 18 | 22 | |
Karen | 16 | 0 | 2 | 18 | 4 | |
Caroline | 2 | 0 | 16 | 22 | 4 |
Player-authored questions are also a delight. I didn’t even consider how entertaining hypothetical questions could be in this context until my friend wrote, “You’re lost in a desert and come across a talking turtle. What do you do?” (Everyone knew I would hug the turtle.)
Question submission is just one aspect that makes Friend Off more participatory than other question-and-answer tabletop games. In Cards Against Humanity, you mostly only play a card, and you occasionally get to pick your favorite. In every round of Friend Off, you’re writing out your own answer and also trying to suss out everyone else’s identity.
While automation was initially just a means to reduce the workload, it ended up enabling gameplay that’d be infeasible with pen-and-paper.
A Griefer’s Paradise
This game has no appeal for groups of strangers. Even after it surpasses Wordle, Fortnight, and Parcheesi Online in popularity, “pubbing” will never catch on because there’s no incentive to play with people you don’t know. This makes it safe to assume that all players are interested in cooperating.
That’s a rare thing for an Internet-enabled game! It’s something I particularly enjoyed as a developer because it meant that I didn’t have to make any effort to enforce rules. I don’t even mind listing some exploits here in this post:
- The secrets are poorly hidden. Under the hood, the answers and their authors are sent to all players in plain text.
- There’s no authentication. Players only squat on their names, so others can assume their identity after they sign off.
- There’s no forced name differentiation. Players can use diacritics to mimic their friends’ names and generally confuse gameplay.
- There’s no content filtering. Players can be as bawdy as they want (which may be very bawdy, indeed).
There are probably more that I haven’t even considered. It’s been a privilege to not think about it too deeply.
Writing in Standards
Friend Off is written entirely with standard programming languages: HTML, CSS, and JavaScript. That’s not nearly as obvious today as it would have been ten years ago. These days, web developers commonly use non-standard languages like JSX, Svelte, and TypeScript to get their work done.
Despite the popularity of non-standard architectures, the practice isn’t all roses. Writing code in more exotic languages means limiting your options for tooling (particularly when those languages are supersets of the standards).
To be clear: JSX and TypeScript are not fringe languages, and web development is not a cottage industry. Folks who choose those particular proprietary components still have plenty of choice in tooling, but even then, they risk getting strung up between version requirements. If any of the maintainers upon whom they rely don’t keep up to date, developers may have to make tough choices about their technical debt. For instance, I’ve consulted with a company which was stuck on an old version of TypeScript and unable to use new tooling because of it.
“Transpiling” source code to languages which are then interpreted also increases the cognitive load of development. Source maps address the most glaring problems but only by adding still more complexity. Even before web developers opt in to these advanced processes, we’re already working in a magnificently byzantine environment. We should set a high bar for each additional abstraction since it further separates us from the runtime and from the people running our code.
Finally, I find it grating to express myself in terms of any language that’s controlled by a private business. That’s meaningfully different from simply using corporate-backed frameworks: programmers apply frameworks as tools to get work done, but languages change how we think and communicate1. Not only does adoption effect us individually–it tends to entrench overly-powerful companies. I work on the web platform specifically because I’m not comfortable with some firm defining my mode of expression. Standards bodies can certainly make mistakes, but they’re more transparent, receptive, and responsible than profit-seeking corporations.
That’s why I used Friend Off as an opportunity to experience what strong types and declarative markup could feel like while still using web standards. That meant using the TypeScript compiler’s JSDoc support to express types via JavaScript comments. Gil Tayar’s perspective on this practice matches my own, so if this sounds interesting to you, check out “JSDoc typings: all the benefits of TypeScript, with none of the drawbacks.” For ergonomically describing data-bound markup, I once again turned to the htm project by Jason Miller. Long story short: I genuinely appreciate seeing language boundary in JavaScript tagged templates, and I don’t find the extra characters onerous.
The Build Process
I strung all of this together with Snowpack, a tool that enables a development workflow where the browser is loading and executing source files directly–no transformations, no source maps, just your code. It felt a lot like the best parts of working with RequireJS back in the day. Almost nostalgic, if I’m being honest.
Ironically, Snowpack is no longer maintained as of a few weeks ago.
You can probably see my next point coming. Snowpack’s relatively limited responsibility in Friend Off’s tool chain reduces the impact of this development (or rather, lack of development, buh-dum-bum). None of the project’s other dependencies are aware of it, so their release cycles are completely decoupled. And should I be forced to migrate to another tool, the process ought to be straightforward. I Might Be Wrong, but this will be a practical way to learn how!
Proselytizing free software
Whenever I build an application, I try to put a spotlight on free and open source software. Although FOSS is nothing new, I think that the general public still needs convincing about its relevance.
At a minimum, this involves providing the licenses for my code and for the project’s dependencies. Even a free software geek like me can see that a stack of legal documents is unlikely to impress a casual-gaming audience.
That’s why I built source code links into the application itself. Wherever the game describes how it works, it invites players to review the specific instructions which encode the behavior in question.
I’ve been documenting the code more than I have in my other pet projects to further support those curious enough to take a look.
I hope this will demonstrate the power of algorithmic transparency, encouraging folks to think about if/why/how they might appreciate the practice in systems that actually matter. And if it inspires even one kid to try programming, then I’ll have repaid my debt to “View Source” and that fan-made Warcraft II website back in 2000.
Future Work: Peer-to-peer
Although I’ve completed a few technical projects during the pandemic, this one is the first to require a server. I get enough DevOps experience in my day job, so I really wanted to deploy to a PaaS. I considered Heroku, but their terms of service turned me off. On the other hand, Glitch has a surprisingly-accessible TOS. I’ve been pushing my work-in-progress there for about six months, and the developer experience has been great.
…except that centralization is such a drag! I originally envisioned Friend Off as a strictly peer-to-peer game using WebRTC, but this turned out to be too much of a stretch for me. Even with the more modest variations to my typical development practices, the project took twice as long as I expected. Since playing the game was my primary goal, I let this feature go.
I’m still very interested in decentralization, though! It’d be rad if I could integrate a third-party STUN/TURN server, but maintaining game state across clients is probably the larger challenge. This could be an opportunity to play with Automerge.
That said, further development really depends on public interest. My goal all along was to play this game, and I’ve played my fair share by now. If other folks have some fun with it, I’ll be pleased that my work had some larger purpose and motivated to refine it. If you do play, please let me know, and don’t hesitate to send me bug reports, feature requests, or even translations!
-
React blurs this line. Its “hooks” system imposes restrictions on JavaScript that I’m not entirely comfortable with. Friend Off uses Preact, but as an alternate implementation of React, it carries the same drawback. ↩︎