Where parallels cross

Interesting bits of life

How to organize a CodeNames tournament with your Emacs and emacs-slack

Too long; didn't read

I partition Slack users via emacs-slack to form teams for the online game CodeNames.

The problem

I joined into an effort to make the remote-first company I work for more social. A friend initiated me to CodeNames, a nice little game in which you have to guess words following a clue of your teammate (rules here). So I proposed to my colleagues to have a tournament! People liked the idea and so I started organizing it.

So I asked myself: how can I do that with Emacs?

And there is a solution

After some thought I came up with these todos:

  1. find all my colleagues names
  2. partition them in teams of two
  3. produce a nice little tournament bracket graph to make things look professional

I could achieve the first two points within Emacs! For the last I hoped to do it via Graphviz, but an online solution was just easier.

Anyway, the first bit is easy: emacs-slack! Being a remote-first company, we use a chat tool. Luckily emacs-slack opens the Slack API to Emacs. So, given a configured emacs-slack, gathering my colleagues names is easy:

(setq my/teammates (slack-team-users slack-current-team))

That's it! With this snippet you have all the users in your team.

Now if we want to form some teams, we need some cool names:

(setq my/team-names '(
                            "Nacho Kings"
                            "Crypto fries"
                            "The Potato Sacks"
                            "Tequila on Oats"
                            "Corny Corn Dogs"
                            "The Pizza Party"
                            "Food Critics"
                            "Chunky Dunkers"
                            "Stoned Cookies"
                            "Dumb Dumplings"
                            "Smoked Salmons"
                            "Snack Attacks"
                            "Stud Potatoes"
                            "Addicted to Cookies"
                            "Cheeses and Chips"
                            "Boozed Boys"

And finally we split our colleagues and assign them a team name using the amazing dash.el!

(setq my/codenames-teams
            (--> my/teammates
                 (--keep (and (not (-contains? '("slackbot" "other-user-you-don't-want") (plist-get it :name)))
                              (eq (plist-get it :deleted) :json-false)
                              (me-get-in it '(:profile :real_name_normalized)))
                 (-shuffle it)
                 (-partition-all 2 it)
                 (--map-indexed (list :team-name (nth it-index my/team-names) :participants it) it))

I use -partition-all because I don't want to lose users (-partition would drop the last partition that hasn't reached 2 members), but if you have an odd number you will have a team of one. For CodeNames, just add that user to another team: the game works fine like that too. Note that the above removes some users (i.e., bots that Slack considers as users in the team). Also, we get only the names of users here. It's a good idea to keep the whole user plist, if for example you want to send automated messages with a little script.

I printed the names that way because I wanted to share the teams composition with my colleagues. Here the snippet for printing out that info in a nice format.

(concat "|Team Name | Participants |\n" (s-join "\n" (--map (format "| %s | %s |" (plist-get it :team-name) (s-join ", " (plist-get it :participants))) my/codenames-teams)))

If you want to use the same online tool I used to form the tournament bracket, just extract the right number of team names and copy the output in the textbox here: https://challonge.com/tournaments/bracket_generator.

(s-join "\n" (--map (plist-get it :team-name) my/codenames-teams ))


That's it! A creative and social way to use our favourite editor and its extensions to have fun together. And if you are a fan of CodeNames, get in touch and we can organize a match :D

Happy gaming!