概要
自分は某カタンクラブにて大会運営システムを運用しています。
これまではドメインのおまけで借りてるホスティングサーバに、ルーティングすら自作のオレオレシステムで運用してました。
まぁそれはそれで目的は達成できているので問題はないんですが、自分自身の勉強を兼ね、今何かと流行りなのに業務で全然使えていないFirebaseとVue.jsを使ってリプレースしてみることにしました。
その第一歩として、カタンの大会をシステム化するために必要な機能のまとめと、それをFirebase+Vue.jsで実現するための仕組みを検討します。
今回はその第一歩として、大会システムを作る動機や必要な機能をまとめます。
長くなってしまうので技術的な話は次回以降になるため、カタンの大会自体に興味がない人は次回以降からご覧ください。
【余談1】カタンってなに
とても面白いボードゲームです。
それをここに記すには余白が狭すぎるので、日本カタン協会の公式ページを見てくれ!
なお、以下の話は所々カタンのルールを把握している前提で記載している部分があることをご留意ください。
【余談2】カタン大会の現状
カタンはアナログのボードゲームなので何でもかんでもデジタル化するのは興ざめな面はあるのですが、とはいえ大規模な大会となると話が変わってくると思っています。
参加者が10名前後の大会ならともかく、100人近い大会では特にそうです。(日本選手権の東日本予選は300人近い人間が集まります)
対戦結果を出場者自身が紙に記載し、それを運営が手作業で集計し次の対戦カードを決めるというのは、運営する人のマンパワー・集計ミスなどいろいろな意味でつらいです。
なので自分が関わっている大会は当初からシステム化しており、それを少しずつブラッシュアップしています。
どこに出しても恥ずかしくないシステムの構築ができたら日本全国の大会で使ってもらえたらという野望はあるものの、現時点ではまだトラブル対応で直接DBを触ることがあり、システムとしては未熟さを痛感しています。
ちなみに、大会運営をシステム化しても参加者全員がスマホを持っているわけでもないので、スコアシートや座席の案内などは紙や口頭でも伝える必要があることは考慮の上、実践しております。
カタン大会システムに求められる機能
既存システムで実装済みの機能を基に必要と思われる列挙する
- 【公開側】大会ルール確認
- 【公開側】順位表閲覧
- 【公開側】座席表閲覧
- 【公開側】個人成績閲覧
- 【管理側】参加者登録
- 【管理側】参加者事前登録
- 【管理側】対戦カード自動マッチング
- 【管理側】対戦カード手動調整
- 【管理側】ゲーム結果登録
【公開側】大会ルール確認
現行システムには未実装の機能
とはいえ、単純にルールを記載したページを1枚表示するだけなので機能と呼ぶほどでもない
【公開側】順位表閲覧
参加者の現在順位をリアルタイムで確認するための機能
※自身が大会に参加したときに気になったので、システム化した動機の一つ
【公開側】座席表閲覧
次の対戦カードに基づき、どのテーブルに座ればいいか案内する機能
※手動運営だとここが超大変なので、システム化した動機の一つ
【公開側】個人成績閲覧
現行システムには未実装の機能
順位表から自分の名前や受付番号を探せばわかるものの、各参加者個人のページがあるともっと見やすいなと思っている
同じく座席表から探せばわかるものの、対戦履歴も表示すれば後でゲーム内容を振り返るときに便利では
【管理側】参加者登録
当日の受付で大会に訪れた参加者の名前を登録し、受付番号を発行する(受付番号は名札に記載してもらう)
その場で名前を入力する当日受付パターンと、事前登録から選択するパターンとある
【管理側】参加者事前登録
前日までに申し込みフォームから受付した参加者を登録しておく機能
とはいえ事前申込者全員が当日来るわけではないので、ここでの登録=参加者ではない
当初は全て当日受付で「参加者登録」から入力してたけど、参加者が増えるにつれて受付が回らなくなったので追加された機能
バタバタ追加したので現状はDBに直接データを突っ込んでいるが、リニューアルを機に画面から行いたい
【管理側】対戦カード自動マッチング
一般的なアナログ運営大会では
- 1回戦:受付時にランダムに座席番号を配布
- 2回戦:1回戦のテーブル番号+1回戦の手番で次のテーブル番号を決める
(手間が少なく同卓もない、よく考えられた仕組み) - 3回戦:スイスドロー
(成績上位者から順番に対戦する、強い人同士を当てて最強を素早く決めるルール) - 4回戦:スイスドロー
という流れが多い
ただし、これには以下の問題点がある
- 1回戦目のランダムが手動なので、たまに疑問が残る
(近いタイミングで受付をすると近いテーブル、もしくは同卓することもしばしば) - 3回戦、4回戦のスイスドローのため全参加者を成績順に並べる必要があるが、そこの労力が大変、かつ集計ミスが発生する
- スイスドローは本来2人対戦のゲームにおいて有効なマッチングで、4人対戦であるカタンに適用すると若干の不公平が発生する
(長文になるので後述)
それらを回避するため、本システムでは
- 1回戦:純粋なランダムマッチ
- 2回戦:純粋なランダムマッチだが、同卓は再抽選とする
- 3回戦:変則スイスドロー
上位16名だけ以下のような卓分けを行い、それ以外はランダムマッチ([1位,8位,9位,16位], [2位,7位,10位,15位], [3位,6位,11位,14位], [4位,5位,12位,13位]) - 4回戦:上位4名だけの決勝卓だけを行う
としている
最後の決勝卓ルールはそれまでの3戦を予選と位置づけている当大会独自ルールになっている
公式日本大会予選とは違うので、優勝者が決まる戦いを希望者はみんな観戦できるようにとこの形式をとっているものの、観客はそんなに多くない
(空いたテーブルで各自が希望者集めてフリーのゲームを行うことを許容しているため、遊んでいる人も多い)
汎用的なツールとして展開するならば、ここの仕組みは複数の手法を選択できるようにするのが望ましいと思う
【管理側】対戦カード手動調整
参加者の様々な都合に合わせて、オートマッチング以降に再調整するケースはレアケースながらも稀にある
これは今は未実装機能で、必要になった場合は自分が現場で必死にDBのレコードを書き換えている…
優先度は低いが、汎用的なツールとして展開するならばこの仕組みはあったほうがいい
【管理側】ゲーム結果登録
対戦カードを基にテーブルごとのゲーム結果を入力する
カタンの大会では占有点という独自のポイント計算ルールがあるのだけど、手作業だとよく間違うのでシステム側で計算する
なので、ここで入力するのは参加者全員の勝利点のみを入力している
現状はないが、明示的に勝者フラグを選択する機能が必要なケースもあり得る(レアケースだけど、プレイミスにより複数名10点獲得というのはあり得るため)
システム上必要ではないのだが、勝利点の内訳を入力できるようになると表彰の際にいろいろと面白いかもしれない
例:大会最長交易路賞、大会最大騎士力賞などなど
【余談3】2人対戦ゲーム以外でスイスドローを適用するときの違和感
※完全に個人的な意見なので読み飛ばし推奨
2人対戦の場合、スイスドローというのは少ない回数で最も強いプレイヤーを決める良い手法だと思います。
スイスドローは端的に言うと、「全勝が1人になるまでゲームを繰り返す」から、おのずと最強が決まるからです。
対戦としても大会後半は実力が近い人同士があたるため、ゲームとしても楽しみやすい。
ただし参加人数に対してゲーム回数が十分でない場合は同率が複数出てしまい、順位付けで混乱しないように勝ち方による優劣をつける必要がでてくるという課題はありますが。
とはいえ、これを4人対戦に適用するとある問題が起きる。
それは「毎回全力で勝たないほうが生存戦略として有利な場合がある」ことです。
具体的に、通常のスイスドローで上位から卓分けをした場合、1番テーブルは[1位,2位,3位,4位]、2番テーブルは[5位,6位,7位,8位]となります。
この時、4位と5位でゲーム後より上位に位置しやすいのはどちらかといえば、おそらく5位のプレイヤーでしょう。
対戦相手を見ると(それまでの対戦で実力が正しく適用されていると仮定した場合)4位は全員格上、5位は全員格下だからです。
もし、レーティング制度のような、強者に勝った人ほど評価があがるシステムが採用されているのなら4位にもメリットはありますが、誰もが納得するレーティング制度もなかなか難しいです。(興味はありますが)
現実問題としてそこまで繊細な調整は難しいと思うかもしれませんが、実際の大会でも「3勝で高占有点が優勝条件ならば、2勝したあとの3回戦は高得点を維持しつつあえて負けよう」というのは十分期待値の高い戦略として耳にしたことはあります。
ルールを把握したうえででそのような戦略で挑むこと自体はむしろ素晴らしいと思うのですが、一方で毎試合全力で勝ちに行くことがカタンらしいなという自分個人のわがままがあるが故の違和感です。
自分が検討した変則スイスドローは予選最終戦という前提で、
- それまでの上位プレイヤーがより格下と当たりやすい
- 4回戦は決勝卓のみとしているので、3回戦での意図的な負けに意味がない
という意図が含まれています。
優勝者は1番テーブルから出てほしいんですよ。それまでの1位が負けた結果、2番テーブルで圧勝した5位が逆転優勝ってなんか嫌だ。
次回予告
今回まとめた機能別に、Firebase側とVue.js側とでどのような責務に切り分けるのかを考察していきます。