/shibboleth_bot

Discord bot for the Shibboleth hidden-team word game

Primary LanguagePython

Shibboleth bot

This is a Discord bot to play the hidden-team word game Shibboleth remotely via real-time text on the Shibboleth Discord server or any Discord server. Please message xnor#7491 on Discord if you have any questions or if the bot is down.

Table of Contents

  1. Joining a game
  2. How to play Shibboleth
  3. Playing on Discord
  4. Development
  5. Credits

Joining a game

Use !help (or !h) to show the bot's list of commands.

To join a game, write !join (or !j) in the channel with the game. If a round is ongoing, it will queue you to join when it ends. Use !start (or !s) to begin a round.

How to play Shibboleth

Rules

Shibboleth (aka Castlefall) is a fast-paced hidden-team word game for 3 to 12 players. It's kind-of like Codenames, Spyfall, and Castle of the Devil. A round takes about 2 to 15 minutes.

You are given a secret word that only you know. Half the players get one secret word and half have another. For example, in a five-player game, three players might have "banana" and two might have "skateboard".

The players sharing your word are your team, and those with the other word are your opponents. You want to work with your team and figure out who they are. At any point in the round, you can submit a guess of either:

  • The full set of people on your team
  • The opposing team's word

After any guess, the round ends and the teams and words are revealed. If you're right, your team wins, and you're wrong, your team loses.

You try to find your team by giving clues about your word. The idea is to convince teammates that you share the same word, while being vague or tricky enough that the opposing team won't figure out your word. Cluing is freeform, and there aren't any turns. You can say whatever you want in your clues at any time. The only rule is your clues have to be public to everyone. You can assume anything said during a round is a clue, unless it's marked as "not a clue" ("nac").

A list of 14 or so random words including both secret words is publicly displayed. Scanning through it can help you look for words that the other team might be cluing. If you find one that seems to match, you might then give clues pretending this is your secret word to test this theory and try to infiltrate their team.

Veto phase

Games are typically player with a veto phase. When a player guesses their team, the round doesn't end yet and nothing is revealed. Instead, there's a 45-second veto period where anyone may guess the opposing team's word. If someone does, this word guess takes precedence and immediately determines who wins the round, and the earlier team guess is ignored. If, however, the veto period finishes without anyone guessing a word, the original team guess goes through and determines the winner.

A veto phase is not triggered when someone guesses the opposing team's word -- the round still ends immediately.

The idea of the veto phase is that if the other team gives obvious clues for their word and then quickly guesses their team, you have a bit of time to review their clues and the word list to figure out their word and take the win. Usually it's players not among the guessed team are deciding whether or not to guess a word, but anyone may submit a word guess, including a player who was guessed or even the guesser themselves.

Partial team guesses

In games with 7+ players, guessing your exact team is hard, so a standard option is to guess only part of your team. For example, in a 9-player game, you need to guess exactly 3 people on your team counting yourself. If all those people are your on team, the guess counts as right and your whole team wins, even though some teammates aren't included in the guess.

Skew

Small games with 2, 3, or 4 players can use the "skew" option to give a chance of more unbalanced team sizes 0v2, 0v3, or 1v3, which makes guessing your team harder. For example, in a 3-player game with skew chance 0.3, there's a 30% chance that the teams are secretly 0v3 instead of the usual 1v2, where every has the same word and will all win or all lose. Here, you could guess a team size 1 (just yourself), size 2, or size 3 (everyone).

Fair play

This games runs on the honor system.

  • Don't look up information such as by Googling things
  • Don't tell things to other players except through the chat
  • Don't edit your messages or remove reactions to intentionally hide information
  • Don't use weird crypto-ish clues like "The sum of the letter values mod 7...". Wordplay is fine and encouraged.

Playing on Discord

You can play on the Shibboleth Discord server. Just follow the link, click to accept the invite, and type in a name to show for you. If Discord asks for your e-mail to link your account, you can ignore this by clicking outside the prompt.

The bot automatically sends players their secret words and resolves guesses. Write !help to see the list of bot commands. You can play with your friends online at any time. If the Shibboleth user doesn't appear as online under "Bot", it's offline -- please let xnor#7491 know.

Round logistics

The game usually happens in the channel shibboleth-game. Go to that channel and write !join to play in the next round. You can see who is playing in the panel on the right. Players' names are highlighted in chat. There can be multiple games going at once in different game channels.

When a round starts, you'll get a DM (direct message) from the Shibboleth bot with your secret word. This will appear as a notication in "Home" (the Discord controller symbol) at the top of the list of channels on the left side. Click Home, then under direct messages click Shibboleth to see the message with your secret word. Then return to the game by clicking the link in the message.

You clue by typing in the chat. If players agree, you can instead clue over voice chat. To join the voice channel, click the Voice Chat channel corresponding to the game room.

During a round, the list of words is pinned to the channel, and you can view it with the shortcut Ctrl+P or pressing the pin icon. There is unfortunately not a way to keep it open while typing a clue, short of opening a separate broswer window with it. You can write !words to post it in the channel.

Discord tricks

When making a team guess, it's recommend to use Discord's user autocomplete by typing @, starting to type their names, then pressing tab or clicking on it. This helps avoid typos. Both nicknames and usernames work. If there are similarly-named users, you can usually find the one who is playing because they have a green circle for online.

Use @username to direct your message to someone, such as to indicate that your message is aimed at them. You can reply to a message of theirs by clicking the ... menu on their message on it and choosing reply, which will put their message above yours for context.

You might want to choose "Compact" for the Discord appearance when playing to shrink space between clues so you can see more on screen. Set this by clicking to the settings gear next to your user name at the bottom left, click Appearance under App settings, and check Compact.

Reactions

You can post reactions (emoji) on a message by clicking the smiley-face while hovering over it. You can also include them in your own message by clicking the smiley on the far right of the message box, or pressing Ctrl+E. You can also type the name like :tree:, which will autocomplete. Beware that the specific emoji images might differ on different people's devices.

Reactions on a clue can be used as a shorthand to express what you think about it. Some emoji with a conventional meaning are listed in the Shibboleth server category for convenience. For example, the :vouch: star symbol ⭐ expresses that you fully trust the cluer as being on your team, and the :fishing: rod 🎣 accuses the cluer of cluing a word that isn't theirs as bait. These have no rules function and are just a means of communication.

Development

Adding the bot to your server

You can add this bot to any Discord server that you manage. This is easy to do through Discord's interface; it doesn't require running any code.

Add the bot to a server

You can optionally do these:

  • To restrict the bot to a channel or channels, for each channel you don't want it in, go to its channel permissions, add the Shibboleth role as a new permissions category, and remove its "Read Messages" permission. (Unfortunately, Discord doesn't have a less tedious way to do this.)
  • If you want a visible role to mark who is playing, create a role named Playing Shibboleth. Put it lower than the bot's Shibboleth role in the role list.
  • If you want a role people can use to ping others about games, create a role named Notify of Shibboleth Games. Put it lower than the bot's Shibboleth role in the role list. Users can do !notify and !unnotify to get or remove this role. The bot won't be ping the role automatically.

The bot asks for the following permissions. The first two are needed for it to function, and the other two are optional. You can uncheck them, or later change them via the permissions of the "Shibboleth" role or permissions for specific channels.

  • Send Messages
  • View Channels (aka Read Messages)
  • Manage Roles (optional: to handle Playing Shibboleth and Notify of Shibboleth Games roles if they exist)
  • Manage Messages (optional: to pin the word list each round for easy access)

Forking this code

You can also fork this code to run it locally for your Discord servers, creating a copy of this bot. To set up the project for local development:

  1. Install dependencies (optionally in a virtualenv, if desired):

    $ python3 -m pip install -r requirements.txt

To make a new instance of the bot and add it to your server:

  1. Obtain a Discord bot token and save it in config/token.txt.
  2. Invite the bot to an appropriate server using the instructions in the previous section, except using your bot application's invite link.
  3. (Optional) Create an appropriately named role on the server for each channel (to hold users who are currently playing). You can also create a role for players who wish to be notified of a game. Role names are configured in ./config. (See ./config/shib.yaml for an example.) Make sure these role are listed below the role for your bot so that the bot has permissions for them.

Run unit tests:

$ python3 -m unittest

Start the bot:

$ python3 bot.py

Or pass --config to use a custom configuration matching your server/channels. To use ./config/foo.yaml, run:

$ python3 bot.py --config=foo

Credits

Shibboleth bot and server by xnor-gate. If you have comments or questions, please ask in the Shibboleth server or message xnor#7491 on Discord

Shibboleth (as Castlefall) was invented by people at MIT in 2017. Thanks to garywang and betaveros for making their sites to play the game in person at mp.garywang.net and bpchen.com/castlefall, from which this project took inspiration.

Thanks to dfkoh for producing part of the word list, to tckmn for making the server icon, and to lchen025 for code contributions. Thanks to everyone who suggested names and improvements.

Thanks to Discord for their platform and API, to Rapptz and contributors for discord.py in which the bot was written, and to the discord.py Discord community for their frequent help.