Lukas Rosenstock's Blog

Lukas Rosenstock's Blog

Before the pandemic started, I used to run board game meetups frequently. One of the highlights of those gaming nights was a party game called “Werewolves”, which some of you may also know as “Mafia”. I often led sessions as a narrator. When Anna Gát of The Interintellect wanted to run a virtual gaming night on Zoom, I quickly volunteered for that. I mostly based my approach towards implementing a virtual game on Anjuan Simmons’ “How to Play Werewolf Over Zoom” guide, but a day before it, I decided I had to add some code, API, and no-code stuff to it. Here’s a quick high-level overview of how I did it.

First, I created a new base in Airtable and a table for the game. Inside the table, every player gets a row. I added several columns for the characters, elimination status, and free-text fields for notes that I could take during the game to assist with the narration (for example, whether the Witch has used her potions). With Airtable’s grouping feature, I arranged the view to list villagers and werewolves separately and hide eliminated players to remove clutter. Another benefit of Airtable is that after the game, I could share a private link to the table so players can see what happened.

Then, I wrote some custom PHP code as a phpMAE class for two purposes. One is to assign characters randomly. The function takes a list of role cards, fills up the deck’s remainder with regular villagers, shuffles it, and updates every row in Airtable with the card’s character. While I did this with PHP due to personal preference (and to “selfdogfood” phpMAE), I think this is also a great use case to build with the new Airtable Apps they announced lately.

The second purpose is player registration and role reveal. Using phpMAE and Twig templates, I created a minimalist HTML website for players to enter their names. The PHP code calls Airtable’s API and adds a row for the player, returning the ID for the created record and a secure hash to the frontend. After I announce that I have dealt the cards, players can click a button on the website. If the hash is valid, it fetches their player record from Airtable and displays their role without revealing additional information. You can see the source code for both here, but it partly relies on undocumented or invite-only phpMAE and CloudObjects features. Contact me if you’re interested in those.

Most interactions throughout the game occur on Zoom voice chat, and communication with particular roles during the night uses private messages. For the werewolves, I created a separate group chat to interact in ways that Zoom doesn’t allow. For this game, we used Interintellect’s Mattermost instance, but any group chat tool works. When it comes to voting at the end of the day phase, I asked everyone to paste their decision in the public chat and hit send at once. However, counting the votes was the most tedious task of the narration, so if I add any additional gameplay features to my custom app, it would probably be voting.

It was not just the first time I narrated a werewolves game over Zoom but also the first time I did so in English (instead of my native language, German). Therefore, I also spent some preparation time writing a script with how and when I wanted to explain everything. Its primary purpose was not to forget to call anyone. I even flexed my creative muscles and added some color to the narration. All in all, running this game was a great experience that let me combine many things I enjoy, and I’ll probably do it again.