As quarantine restrictions begin to ease in some parts of Australia (hang in there Victoria), a games night seemed like a good way to reconnect with colleagues that I hadn’t seen in a few months. It seemed I wasn’t alone in this thinking, as colleagues quickly jumped on the invite and I found myself trying to organise a games night for 18 people. Very few boardgames can support 18 players (“another round of One Night Werewolf?”), and I found myself struggling to handle logistics for these numbers. The easy and most common answer in this situation is just to split the party in two and get multiple games happening. However I was reluctant to do this for multiple reasons, so the problem continued to nag at me for a few days. Then it hit me: what if I built my own game?
At university, we played a game called “You’ve been assassinated” where the goal was to “assassinate” another player by covertly revealing their name to them written on a piece of paper. It’s a great party game as it gets people talking, forces people to introduce themselves to new people and most importantly, has no limit on the number of players that can participate. In a moment of clarity after an arduous gym session, I realised I could digitally recreate this game. Using QR codes I could turn my guests into ‘targets’ that could be virtually assassinated by simply scanning the code. I had less than a week before the party night to build it, but I was confident it could be done in only a night.
Coding the game
To quote Thorin – “I have never been so wrong in all my life.” The code took significantly longer to write than expected, including to implementations of the “scorched earth” protocol where I simply abandoned the code I had written and started from scratch. The old saying of “measure twice, cut once” is full of wisdom and good intentions, but in my excitement to get going my ego decided I could make up the code and logic on the fly; a practice I refer to as “cowboy coding”. I’d like to say this was a lesson well learnt, but I really can’t guarantee that I won’t do exactly the same thing on my next project.
Jokes aside, the game was eventually coded, albeit without many of the features I had planned to include. I wrote it in PHP, using Bootstrap to manage the front end and Twilio plugins to handle the SMS functionality, and added a repo for it on GitHub. I decided not to use a framework as it would have added too much overhead for no benefit. There is much that can still be improved, but given the time constraints in building it, I was satisfied with the result.
One final note about development – always ensure you leave time to QA your work. I was QA’ing this project until about 15 minutes before the party started and still finding bugs. I ended up writing the front up script 30 minutes before the party started and adding it to the code with:
include_once 'hit.php' die();
See the problem? When the game started people complained of getting an unresponsive page and I had to make changes on the fly in production. All that hard work was almost undone for want of a semi-colon.
Making the hats
The final part of building the game was not writing the software but building the hardware. I bought a bunch of party hats and started sticking QR codes on them about an hour and a half ahead of the party. To my dismay, the sticky tape was not enough to hold the QR code to the glittery hats. Blu tack worked to some extent but was not reliable. My roommate suggested staples, and after some problem solving this proved successful – until we ran out of staples. I had to go to three different stores to find the right-sized ones, which is not what I planned on, but we got there in the end.
A semi-colon and a staple. It’s the small things that make the difference.
A bunch of cybersecurity professionals are playing a digital game. What could go wrong? Surely no one will try and hack the game, right? I was very aware of the probability of someone trying to exploit a bug in the game for their advantage. My solution in this situation is almost always the same – consult Rick Astley. I added basic authentication to most of the critical scripts involved and redirected anyone who failed the authentication check to check out this awesome video. The authentication is not secure and relies a lot on security through obscurity, but for my purposes that was enough.
Sure enough, it was about halfway through the night when I heard a voice call out across the room “Dylan, you’re a jerk!” (this is the PG-13 version of what was said). When I asked what I had done, I was told that they had tried to fuzz the URL and had been rickrolled. For me, this was the highlight of the whole night, and my only regret was that I wasn’t standing next to him to hear the opening bars and see the reaction live.
The game is simple enough: everyone is an assassin trying to assassinate a target. Assassinations occur by scanning a targets QR code, which players wear attached to a hat. Instructions are sent by SMS. When a player is assassinated, the assassin receives that players target as their new target, and so the game continues until only one player is left.
Even though the game is simple in concept there are a lot of potential logic flaws that can destroy the whole game if not thought out. The worst one I only found during my QA process an hour before go-live – players could be assigned themselves as a target. Whilst this was quite amusing conceptually, it threatened to undermine the whole game and ruin the night. Fortunately, I was able to debug this quite quickly and no damage was done.
Introducing the game
I decided that rather than me simply explaining what was going on, it would be more fun and add to the mood of the night to introduce the game in the form of a briefing from a “mysterious source”. I made a video and then wrote a script to share the video via SMS before the game started. After everyone arrived I loaded the script and told my friend to push the button and watch what happened. Phones around the room started pinging as soon as he did, and people were quickly talking about this strange SMS they had all received. Rather than watch the video individually, we cast it to the TV and watched the briefing together.
Playing the game
I was curious to see what strategies people would come up with to stay alive and to kill others, and my guests did not disappoint. A common tactic was to simply shake your head; you can’t scan a moving QR code, so I would see people having conversations whilst constantly shaking their head. Other tactics involved simply standing next to a wall for the whole party so others couldn’t see your code, or hiding your hat. I did implement a rule that QR codes could not be hidden, as I didn’t want people to simply stuff their hat somewhere really obscure and then run around killing everyone else. Nonetheless, I still found a hat in my microwave the next day.
Other tactics included people working groups to take down a target. This was often in the form of several assassinated targets supporting one assassin in return for free alcohol. These groups would take pictures of every QR code they could find, regardless of whether or not that person was a target. Once they had developed a bank of codes they could simply scan the right one from someone else’s phone. Other people resorted to crawling through windows to sneak up on their target and swapping hats to confuse would-be assassins.
One event that I did anticipate was the initial bloodbath. While everyone was gathered around the TV watching the briefing certain players began to pick up on the concept faster than others. This meant they had a brief opportunity to assassinate their target while they were still distracted by the TV and before the target even knew what was going on. At least 3 people were assassinated this way.
I had also anticipated people leaving early, losing/damaging their QR code or breaking the rules. In all of these situations, I had to have a means of removing this player from the game quickly and easily. I didn’t want to be constantly ducking out of the party to go make changes in the database. Therefore I wrote a script to grant me the power of God and “smite” any deemed unworthy. This script marked the assassin as “alive = 0” in the database, cancelled their current contract and reassigned their target. I only had to use this script once for a player who left early but simply having it was useful for deterring rule breakers.
The game ended when there was only one assassin was left alive. We declared our victor champion and then rebooted the game for round two.
I’ve added the code I used to GitHub. It’s pretty poor code, but it’s functional and that’s what matters. If I want to play this game again I will go through and add some more functionality, including better authentication on the management scripts, better communication with database, and less tightly coupled functions.