8
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

gRPCAdvent Calendar 2019

Day 2

gRPCでオンラインポーカーを作った話

Last updated at Posted at 2019-12-12

ここ何ヶ月か合間の時間を見繕って勉強がてらgRPCとgoでオンラインポーカーを作っていたのでご紹介してみる(ソースがあれですみません。。

Dockernizeしていないのでそのままですが多分諸々入れればローカルで動作するようになっています。

仕様

  • ポーカーのルール的には古いクローズドなファイブカードドローで(ただし現状ベッティング要素なし)、4人プレイ専用で、単純に1人ずつカード交換をします。
  • 他のクライアントからの接続がない場合Wait後残りのプレイヤーをNPCとしてゲームが開始されます。
  • 基本的にクライアントが何もしないとサーバ側で自動的にタイムアウトしたとみなして処理を進めていきます。
  • リクエスト的には以下があります(詳細は proto を御覧ください)
rpc 概要 サーバ クライアント
SignUp 登録 新規登録時に名前を設定しないと自動的に名前が決められてレスポンスに返します レスポンスの名前をデータベースに保存します。
ChangeName 名前変更 二回目以降で違う名前で実行した時にサーバへ変更のリクエストがされます。
SignIn ログイン
Join 部屋に参加 部屋のIDと名前を返します。
Start ゲームスタート game_id(一ゲームを一意に表すID)、クライアントのIDおよび他プレイヤーのIDと名前を返します。また最初の手番となるプレイヤーのIDとクライアント用の5枚のカードを返します。
Change カード交換(自分用)
Draw カード交換(他人用) 他のプレイヤーのカード交換をリクエストします。順番が違う場合エラーを返します。また、他のプレイヤーの入力待ちの場合一定時間Wait後に結果を返します。
Open カードオープン すべてのプレイヤーの交換後のカードをレスポンスとして返します。またポーカーの役と結果としてのランクを返します。 すべてのプレイヤーの交換が終わった段階でリクエストします。各プレイヤーのカードの役とランクを表示し、誰が勝者かを表示します。
End ゲーム終了 プレイヤーの入力に応じてゲームを続けるか終えるかをリクエストします。サーバはリクエストに応じて次のゲームのためのリフレッシュ処理、または終了処理を行います。すべてのプレイヤーがOpenResponseを受け取るまでWaitします。

構成/アーキテクチャ

スクリーンショット 2019-12-12 20.31.05.png
  • クライアントはsqliteにユーザデータ(現状名前とID)を保存します。
  • サーバはSignUpしたユーザ情報(現状名前とID)をMySQLに保存します。
  • サーバはredisにゲームに利用する情報を保存して使います。
    https://github.com/admogh/online-porker-server/wiki/Redis-Keys

デモ

porker.gif

上がサーバで下がクライアントになります(たまたま最後にストレートがでた。

gRPCについて

gRPCを使った実装ははじめてではなかったですが、今回改めて一から設計・実装をやってみて、gRPCが担保してくれるところはあるにしても、サーバとクライアントとのインタフェースを考えるのはやはりいつも大変だなと感じました(よりリアルタイムなオンラインゲームを作ろうとした時には、protoで表現できる領域が少なくなって、もっと実感することが多いかもしれないです)。
実際今も完成形ではありませんが、最後までprotoをフィックスさせることができませんでした。

今回は結局使いませんでしたが、streamingを使ったprotoも検討していました(途中まで実装していた)。今回は1ターンで終わりなので必要性がないという判断に至ったのですが、本質的にストリーム処理として必要なものなのかということを考えるのが判断のポイントになるように思いました。

サーバとクライアントとのインタフェースを考えていると悩む場面も少なからずありましたが、protoについて、リクエストがサーバに必要なものであり、レスポンスがクライアントにとって必要なものであると意識すること、protocで生成される利点を活かして共通に使われるような機能を組み込むこと(今回であればポーカーの役など)がよいように思いました。

その他

  • NPCの機能は必須項目として実装しましたが、やはり考えることは増えます。設計次第なところはあると思いますが、NPCを完全にPCと同じものとして扱うのは他にかかるコストが増えていく気がしてバランスが求められるように思いました。
  • 正直現状色々足りてないし、バグもあります。gRPC的にちゃんとエラーコードを適切なものとして返すことも必要です。
    https://github.com/admogh/online-porker-server/issues

最後に

ここまで読んでいただいてありがとうございました。
最近ボードゲームをやっていてアプリ化して遊べないかなとかぼんやりと考えることがあるのですが、このようなことに興味ありましたらお気軽にご連絡ください。一緒に何かを考えましょう。
https://twitter.com/admonow

8
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?