We live within constant connection with our phones to both gather information and inform others of our intentions. Why not leverage our digital extensions to be the primary tool of the game?
This actually sequentially solved each of my main problems. First, I started by building a way for the werewolves to surreptitiously vote on their phones without interrupting the game. However, if only the werewolves were playing with their phones through the game, the game would be obvious. So next, I introduced another symmetric usage for the non-werewolves.
As it turned out, the perfect task that I could give non-werewolves was to obtain verified information about the werewolves. Again, I don't want to go into too much detail, but in general, the non-werewolves were able to query a central database that had unambiguous information about who was a werewolf. By limiting how much information they could gather at a time, the game could be tuned to both enforce cooperation and balance the rate of information gain with the rate of werewolf kills.
To easily incorporate the usage of the phone, I needed to leverage something everyone would have access to. It would have been impossible for me to build a real phone app that would be compatible on everybody's devices. Instead, I leveraged something I knew everyone could use: email.
I built an automated email response bot that could shuffle information back and forth between players, myself, and a central database full of information that they could use to complete the game. The subject lines of the player's emails had a certain syntax that indicated whether they were trying to gather information or cast a vote to kill. The script I wrote just read the emails and followed some simple logic to direct the information around and keep the game moving along.
To set up the Gmail API, the Gmail API Quickstart Tutorial contains instructions and the link to the spot on Google Cloud where you can activate the API. This will allow 100 sent emails per day, which should be enough if you have 20 or so people playing for an hour.
I used this gist to figure out how to send emails, and this code to figure out how to read subject lines.
My code is here, but I'll explain the few bits that are important below.
This connects to your web browser to allow authentication of the Google account that has Gmail API access.
creds = flow.run_local_server()
service = build('gmail', 'v1', credentials=creds)
Next, I grab the unread messages and iterate through them.
unread_msgs = service.users().messages().list(userId='me',labelIds=['INBOX', 'UNREAD']).execute()
mssg_list = unread_msgs['messages']
for mssg in mssg_list:
message = service.users().messages().get(userId='me', id=m_id).execute() # fetch the message using API
I step through the header items to get the subject and the sender.
payld = message['payload']
headr = payld['headers']
for item in headr: # getting the Subject,Time Sent, and Sender
if item['name'] == 'Subject':
msg_subject = str_clean(item['value'])
elif item['name'] == 'Date':
msg_date = item['value']
date_parse = (parser.parse(msg_date))
elif item['name'] == 'From':
msg_from = str_clean(item['value'].split('>')[0].split('<')[1])
At this point I go through several rounds of custom logic to compare this to the central database. I won't go into the details of the logic, but I want to mention how I access this "central database" in a very cheap and easily editable way.
To handle both the emailing permissions and the werewolf feature database, I just pulled the details from a Google Sheet. I already described how to connect to gsheets in a previous blog post. I reused the same credentials to download a sheet and convert into a python dictionary with all the info needed.
sheets_service = build('sheets', 'v4', credentials=creds)
result = sheets_service.spreadsheets().values().get(
spreadsheetId='game_db_spreadsheet_id', range='db!A:I').execute()
Finally, I sent emails with the requested information back to the players.
message = MIMEText(message_body)
message['to'] = to
message['from'] = 'robot-db@gmail.com'
message['subject'] = subject
encoded_message = urlsafe_b64encode(message.as_bytes())
service.users().messages().send(userId='me', body={'raw': encoded_message.decode()}).execute()
All of this worked by repeatedly calling the API to get the new unread messages and then running through this over and over again. I used the sent email time to prevent people from repeatedly querying the database in less than the alotted time.
Each time I ran this game, I did it with more and more people. The first time I ran it, I only had about 8 people playing and I just manually responded to the emails they were sending. The last time I ran it, there were more than 25 people playing, and the automation came in really handy. It also allowed me to manage other aspects of the game at the same time.
Over time, I hope to perfect this game even further. If you are reading this in the SF Bay Area and would like to bring this game to your organization, please leave me a comment and I will get in touch to try to run it for you.