概要
友人とよくDiscordで通話しながらボードゲームやワンナイト人狼を遊びます。ワンナイト人狼はWebで遊んでいたのですが、自分でカスタマイズして自由に遊びたいと思い立ち作ってみました。
ソースコード・遊び方
GitHubにソースコードや遊び方を公開しています。Dockerをインストールしておく必要があります。(ローカルにpythonの環境を作れば当然Docker無しでも動きます。)
つまずいた点
Qiitaでは、DiscordのBotを作る上でつまずいた点を書き留めておきます。
discord.pyのバージョンがよくわからなかった
discord.py 1.0.0aのリファレンスがあるので、最新版はこれだろうと思っていたのですが、pipでdiscord.pyを落としても、最新は0.16.12だと怒られました。調べてみても結局よくわからなかったので、0.16.12で開発しています(なお、pythonは3.5.3です)。
日本語の情報が少ない
DiscordでBotを作ってみたという情報はQiitaにも個人ブログにもそこそこあるのですが大体がハンズオンのみで、それ以上のことをしたいとなると途端に情報が途絶えました。「チャンネルじゃなくて個人にメッセージを送りたい!」っていう一見簡単な要求も日本語の情報は無かったです(探し方の問題でしょうか ちなみに、個人にメッセージを送りたい場合は、discord.Client.send_message(discord.Member, String)です)。拙い英語力で仕方なく公式のリファレンスとにらめっこしてました。とりあえず検索してみてお目当てのものが無さそうだったらすぐに公式リファレンスを参照した方がかえって効率良いと思います。
非同期処理に慣れていなかった
Discordへメッセージが送られてきたイベントのハンドラはasync def on_message()です。これは、ユーザがメッセージを送信したタイミングで呼ばれるので、複数のユーザが同じタイミングでメッセージを送信した場合、同じ数だけハンドラが呼ばれます。当たり前ですが。この性質を抑えておかないと、ちょっと実装で苦労するかもしれません。このワンナイト人狼Botでいうと、全員が夜行動を終えたタイミングや、投票を終えたタイミングをどう判定するか、という点で悩みました。私の場合、プレイヤーに行動完了フラグと投票完了フラグを持たせ、ハンドラが呼ばれるたびにプレイヤー全員のフラグをチェックし、全部立っていたら次へ進む、といった同期方式で実装しました。正直この実装も、他の方式が思いつかなかったので苦肉の策です。全く同じタイミングでメッセージが送信された場合、フラグチェックをパスしてしまう気がします。どういう実装が良いんだろ。。