カードゲーム対戦サーバ構築への道
UML, シーケンス図

Flying Object lab

飛行物体の実験室 > 記事 > カードゲーム対戦サーバ構築への道 > カードゲーム対戦サーバ構築への道 3 -ゲームの仕様を練る-

カードゲーム対戦サーバ構築への道 3 -ゲームの仕様を練る-

2024年12月30日

前回は準備ないし確認のような回でしたが、今回はP2Pサーバ構築に向けて本格的に作業を行います。

前回、前前回はNode.jsベースでWebRTCを利用するという方針を打ち立てていました。

今回は、通信の分野に突っ込む前に想定しなければならないことを回収していくための回となります。

WebRTCへの浅い理解

私はたまたまNode.jsを触ったことがあったので、それを起点として物事を進めかけていました。

WebRTCの事を書いているサイトを渡り歩いているとやはり私のWeb通信への理解が浅いことが分かりました。

大前提として、リアルタイム通信即ちUDPを利用するにはWebRTCを用いる以外の選択肢はないようです。[1]

そして、このような記事を見かけました。

WebRTC を今から学ぶ人に向けて

まず私は「手を動かすこと」に固執しすぎています。これは私の悪癖です。一旦「手を動かす事=この記事を更新すること」として強制的に自身を勉強モードに切り替えます。

ゲームの仕様を考える

私のゴールは決まっているようで決まっていません。明確なビジョンと仕様が定まっていないのでまずはそこから考えましょう。

今作っているゲームは1人もしくは2人でプレイするものです。1人の方はそもそもゲームのルール自体が議論できていないので2人の方だけ実現することを考えます。

ということで、まずはこのゲームの「説明書」を書いていきます。

説明書

本ゲームは、2人用の対戦型カードゲームです。ゲームには内包されている30枚のカードを用います。

1人は「勇者(hero)」、もう一方は「魔王(demon)」のロールです。

30枚のカードの表面は勇者用、裏面は魔王用です。

勇者サイドは「経験値」と「防御力」、魔王サイドは「コスト」と「攻撃力」というステータスをそれぞれ持っています。

戦略フェーズ

まず、勇者サイドはNo.1~8(基本カード/白)から4枚、他から11枚ランダムにカードを引きます。(計15枚)

残った15枚から魔王サイドは好きなカード9枚を引き、勇者サイドに開示します。

勇者サイドは15枚から7枚のカードを選出し、魔王サイドへ開示します。

勇者のカードを見て、魔王サイドは9枚のカードを6ターンの間どう動かすのか決定します。

魔王サイドの「コスト」は1ターン目には1、2ターン目は2...と利用できる基本コストが増加していきます。

魔王サイドは各ターン、この「コスト」の許す限り、カードを何枚でも使えます。(1枚のカードは1ターン1回のみ使用可能)

これらの準備が整ったら、戦闘フェーズを勇者ターンから開始です。

戦闘フェーズ(勇者ターン)

勇者サイドは魔王サイドの手持ちから動きを予想しつつ、カードを1ターン最大3枚まで使用します。

勇者サイドのカードには0~12の「必要経験値」が書かれており、所持している「経験値」を消費してカードを使用します。

勇者サイドは、魔王サイドのライフを3削り切った場合に勝利となります。

勇者サイドが最大3枚のカードを使用し終えたら、戦闘フェーズを魔王ターンへ移行します。

戦闘フェーズ(魔王ターン)

魔王サイドは戦略フェーズで決めたカードを使用し、勇者サイドの撃破を目指します。

指定しておいたカードの発動条件を満たしていないか、手札にない場合はそのカードをスキップします。

魔王サイドが攻撃を行う際は「魔王の攻撃力」ー「勇者の防御力」(最小0)が勇者のダメージとなります。

魔王サイドは、勇者サイドのライフを15削り切った場合に勝利となります。

両サイドが行動し終わった後、6ターンが経過していた場合は精算フェーズへ移行します。

そうでない場合は、次の勇者ターンへ移ります。

精算フェーズ

6ターンの戦闘フェーズを終えて勝敗が決まらなかった場合、手札の枚数が少ないほうが勝利となります。

手札の枚数が同じ場合、勇者の残りライフを5で割った数と魔王の残りライフを比較して数値の多いほうの勝利となります。

ライフも同値だった場合は引き分けです。

ゲームルールに関する話

言い訳がましくなりますが、このゲームのルールは筆者が考えたものではありません。

実際にこのゲームを魔王サイドで初見プレイすると、動きを考えるのにかなり時間がかかります。

この時間的非対称性はこのゲームの弱点となっており、開発陣は全員この問題を把握しているはずです。

何が言いたいのかというと、今後もゲームの仕様変更の可能性があります。

つまり、ゴールが私の一存で明確に定まらない...ということです。

この問題を抱えつつ、仕様変更が起こっても問題を吸収するような柔軟な設計が求められるということです。

というより、ルールの是正のためにこのサーバを構築しようとしているまであるのです。

ちなみに、このゲームの開発における私の主たる役割は「イラストレーター」です。エンジニアではありません。

このサーバの構築は私がイラストの業務をしていない時間に独断で行っている状態です。

さて、4か月後私はどうなっているのでしょうか?不安は残りますが、続けましょう。

サーバ対クライアントのシーケンス図を考える

おおよそのゲームの仕様は分かったので、それを踏まえてシーケンス図を考えます。

PlantUMLというツールを利用して、サーバとクライアントの立ち位置を図示するとこうなります。[2]

これはあくまで「マッチング」メインの図です。

ということで、次はゲームの中身について議論します。

ゲームプレイのシーケンス図を考える

先述の構造の弱点に、サーバが不正を監視できないという点があります。

この不正を防止するために、サーバは1ターン毎に結果を監視することにします。

片方のターンが終了する際に、結果をゲームサーバに送信し、何かの不正があった場合はゲームの中断等を行うという処理です。

それを踏まえた結果、こうなりました。

利用する技術を再考する...前に

ということで、大まかではありますが仕様が具体的になりました。

特にこのシリーズにて重要になるのは「通信」の領域になりますが、通信は最後に行うことにします。

Node.jsやWebRTCを使用する以前のものができない限り、送る情報の詳細やタイミングも分かってきません。

ということでまずは、ローカルである程度動作する環境を整備してから通信が必要な領域を書き直します。

というわけで、1人でプレイできる環境を作り上げます。

そのためにまずは「レイアウト」とその「動き」を想定します。

まとめ・次回予告

今回はゲームの説明からおおまかなシーケンス図を作成しました。

次回はレイアウトとローカル(1人)で動かすための環境を検討していきます。

参考

[1]:Qiita@yusukem99: ブラウザのリアルタイム通信の変遷

[2]:Qiita@couzie: Visual Studio Code で UML を描こう!