みるめも

麻雀って本当にランダムなの?? - 暗号学の世界に迷い込んだ話

「ランダムってなんだ?」麻雀をやっていたら暗号学の世界に迷い込んだ話
みるみ
\ Follow Me! /
みるみ

ブロガー、エンジニア。

文章を書くのが好きです。

実は最近、またもや麻雀に寝食を蝕まれている。

コロナで在宅時間が増えたので友人たちと「麻雀やろう」みたいになったのを皮切りに、スキあらば天鳳()にログインして対局しているんです。在宅勤務中にもやっていr
ネット麻雀のプラットフォームのこと。後述します。

しかしね、まあ勝てないときってあるんですよ。

大して強くない僕が言うのもあれなんですが、麻雀っていうのは確率論と実力が織りなすあの絶妙なバランスが醍醐味のゲームだと思っているんですよね。

でもさ、明らかに納得できねぇ運の悪さが立て続けに起こりすぎると思いません?

「絶対誰かが俺のこといじめてるだろ!!!」みたいな。誰しも一度は思ったことあるはずです。

しかし世界は僕たちにこう言います。

「麻雀は配牌もツモも完全にランダムなんだよ。みんな平等です。」

そうかランダムか。そうだよな、たまたま運が悪かっただけだよな。

 

…。

ランダム?本当にランダムなの?
っていうかランダムってなに?????

 

というわけで今回は「ランダムについて初めて考えてみた話」です。

別に僕は暗号理論とかに詳しい技術者ではないので、もしかしたら間違ったこと言ってるかもです。その際はやんわりとご指摘いただければ幸いです…。

アナログの世界に完全なランダムはない(と思う)

例えば今あなたの目の前にサイコロがあります。

one-dice

これを無造作に転がしたとき、1~6の目が出る確率は完璧なランダムだと思いますか?

僕はNOだと思う。

そのサイコロが完全な六面体でできている保証はないし、もしかしたら目の穴の数でわずかな空気抵抗値に差が出て目の出やすさが変わるかもしれないし、ひょっとしたらあなたがプロのディーラーで賽の目を操れるスペシャリストかもしれない。

「完全なランダム」、つまり「全ての事象が同様に確からしい」状態を目指すとするなら、現実世界でサイコロを振るのは理想ではないと僕は思うんです。

「屁理屈だろ」と言われると「まあ、はい」って感じですが、今回はそこを突き詰めるお話です。屁理屈派の方はそっ閉じしてくだされば。

コンピュータに頼る

じゃあどうするか。
コンピュータの力を借ります。

ExcelでもGoogleスプレッドシートでもNumbersでも何でもいいので、表計算ソフトをお持ちの方は

=RAND()

と入力してEnterを押してみてください。

0以上1未満の数字が"ランダムに"返されます。

excel-random-functions

おお!これは完璧なランダムだな!!

…と、僕も思っていました。今日この日まで。

だがしかしBUT!!!!!

ここで改めて考えてみたんです。「ランダムってどういうロジックで値を決めているのかな」って。というか今まで考えたことがなかったこと自体にもちょっと驚いていました。

で、結果はというと、やっぱり何回考えても論理的に納得することができなかった。

アナログの世界でも完全なランダムを作ることができないのに、コンピュータだからといって何もないところから完全なランダムという概念を作り出すイメージが全く湧かなかったんです。

これ以上は僕の頭じゃどうにもならんということで、ここで初めてググる。

以下の記事がヒットしました(良質な記事がすぐ見つかって良かった!)。

技術者の方が書いたらしい「コンピュータのランダムは本当にランダムなのか?」というもの。

ここには衝撃的なことが書いてありました。

考える能力がなく、入力値がないと何もできないコンピューターが、どのようにランダムを作っているのでしょうか。
答えは、「擬似ランダム関数」です。
コンピューターは擬似ランダム関数を使います。

やっぱりコンピュータのランダムは「完全なランダム」ではなかった!!!

知らなかった…。
情報工学出身のエンジニアやってんのにこれを知らなかったとはめちゃ恥ずかしい…!!

また、さらに重要と思われる文章も見つかります。

擬似ランダム関数は関数(Function)の一種なので、必ずInputが必要です。
数式を適用する引数が必要になるため、SEED値を入力しなければなりません。

そう、これ。これだ。

何もないところからランダムを生み出すのは絶対に無理だ、と感覚的に思っていた正体はこれです。コンピュータの機能なのだから、受け渡す「引数」が必ずあるはず。

さーて面白くなってきたぞ。

じゃあ麻雀の「ランダム」ってなんなのよ?

話を麻雀に戻します。

僕が冒頭に言った「天鳳」というネット麻雀プラットフォームは、プロの公式大会でも使われるような由緒正しい(?)麻雀システムです。

tenhou-marjong

ということは、その正当性には確かな保証があるってことになるよね。

天鳳のマニュアルにアクセスするとこう書いてあります。

天鳳では、公正な対戦環境を保つことを目的として牌山を生成するアルゴリズムに、 意図的な牌山の操作が不可能であることを検証できる独自の方法を採用しています。
(中略)
「天鳳の牌山はインターネットのセキュリティ技術と同じ方法で信頼性が担保されている」と言えます。

なるほどなるほど。

今日までの僕でもここに書いてあることのイメージは湧くし理解はできます(実はここの内容は何年も前から知ってました)。

しかし今回はちゃんと読み解いてみることにしましょう。以下ちょっと技術的な話になっちゃいますが適当に読み飛ばしながらどうぞ。

まずここまでの状況を整理します。
※詳しい説明はちょっと端折ってまとめちゃってます

  • コンピュータが使う単なるランダム関数は「擬似乱数生成器(PRNG)」と呼ばれ、入力が同じなら出力もいつも一定になる
  • 擬似乱数の生成アルゴリズム自体は現代で使われているバリエーションは多くなく、突き詰めると線形合同法メルセンヌ・ツイスタなどに集約される
  • これらは出力の「ランダムさ」は現実的な範囲で保証されていて、入力値さえ一定じゃないor常に新規の値を使えていれば理論上の問題はない

という感じ。

では天鳳のアプローチを見てみます。

天鳳は牌山の生成方法を公開していて、これをもとに僕らがいつでも信頼性を検証できるようになっています。

ここにあるソースコードを見る限り、まず牌山の生成には前述した「メルセンヌ・ツイスタ」を使っているらしいことが分かります。

メルセンヌ・ツイスタの基礎理論である「mt19937ar.c」という関数が確認できるから。

int nGame=0;
for(;nGame<10;++nGame){ // 10回目の対戦まで
mtRoot.genrand_int32(); // 席順決定などで3つ消費
mtRoot.genrand_int32();
mtRoot.genrand_int32(); // サンマは未使用
mtRoot.genrand_int32(); // 未使用
_MTRAND mtLocal;

この辺。

楽しいね。
次の話へ行きましょう!

ちなみにさっき表計算ソフトでやった

=RAND()

も、このメルセンヌ・ツイスタがもとに出来上がっている関数っぽいです。今や世界の基盤になっていると言っても良いこの基礎技術ですが、発明はどうやら日本人2人組とのこと。誇らしいですね。

「完全なランダム」の実現とその保証のために、暗号学が活躍する

ここで登場するのは「SHA-512」というもの。

また、公開しているハッシュ値(SHA512)の一方向性から対戦者が牌山を逆算することが事実上不可能であることや、 衝突困難性から天鳳の運営者が乱数種を差し替えることが不可能であることが分かります。

天鳳のマニュアルにも言及があります。

SHA-512の説明のためには「暗号学的ハッシュ関数」の説明が必要で、その説明のためには「ハッシュ関数」の説明が必要なんですが、今回はほぼ全部すっ飛ばします。笑

みるみ
みるみ

ここは情報工学としてもかなり一般的な内容なので大きく知られたものです。身の回りのあらゆるところに応用されている技術ですよ~

ただしハッシュの概念だけは説明する必要があるのでちょびっとだけ。

about-hash-function

「あるメッセージ(入力)を全く別の暗号文のようなものに変えてしまうフィルターのような役割」を持つのがハッシュ関数です。この「フィルター」の形は適宜使い分けることもできます。

注意したいのは、復元はできないので暗号化とは違うものです。
この「復元はできない」、つまり「一方向性」がハッシュ関数の最も大きな特徴です。

つまり「ある入力は必ずある出力になるけれども、その出力の結果だけで入力値を推定することは不可能」ということです。

なぜ計算によってハッシュ値が求められるのに逆算はできないのかというと、一方向性関数の存在があるからです。この根本原理は人類史でしばらく崩れることはないでしょう(証明はされていないらしいけど)。

そして天鳳が採用している「SHA-512」とはそのハッシュ関数の現状最強版、みたいに思ってください。最強というのはセキュリティ強度的にもそうだし、どんな入力が来ても入力が違えば必ず出力も変わる、結果にダブりがないという意味も含んでいます。

ややこしくなってきたのでまとめましょう。

天鳳の信頼性確保&検証可能な仕組み
  • 天鳳では牌山の生成自体のランダム関数は「擬似乱数生成アルゴリズム」であるメルセンヌ・ツイスタを採用している
  • しかしその入力値は公開されてはいないので、対局者が事前に牌山の乱数列を知ることはできない
  • 「SHA-512」で出力されるハッシュ値は天鳳での対局が始まる遥か前から常に公開されており、対局終了後に実際の牌譜を使って公開されていたハッシュ値と一致を確認することで検証が可能である=牌山の操作が何者によっても行われていないことをいつでも証明できる

というシステムになる、ってことですね!!

「入力値(乱数シード)のランダムは完全ランダムじゃないよね?」とお気付きの鋭い方はこの記事などを見るといいかも。

簡単に言うと「時刻」のように毎度必ず違う値が使われているのなら問題はないということですね。

しかもそもそもここの値は対局者が知っていなければいいだけなので完全ランダムである必要もないです。「既にある牌山情報の並びから初期値を推測する」ことについても、公開されている牌山の生成情報はSHA-512で逆算できないようになっているのでこれも不可能です。完璧!

いやー、よくできてます…。

だいぶ説明がド下手くそだったと思いますが、みなさん分かりました?笑

 

ちなみに、牌山のランダム生成(メルセンヌ・ツイスタ)の段階から検証できるような情報も公開されていて、この場合の初期入力となる乱数シードの例もここに置いてあります。

暇な人は計算してみてどうぞ。

ランダムじゃないネット麻雀は腐るほどある

さてさて、どうやら天鳳は本当にランダムっぽいし、事前に誰かがチートすることもできないし、運営側が「ひひひ、こいつのロン牌はどっかに隠しちゃお」とかもできないらしいということが分かりました。

では他のネット麻雀は?

細工されまくりです。

もちろん明確なソースなんかないですが、僕の経験だけで命を賭けて言える。
絶対に意図的な牌操作はされまくりだあああああああぁぁぁぁ!!!!!!!!!!

一番簡単な例を見たい人は、課金要素のあるソシャゲ系麻雀を遊んでみましょう。課金しないとアガれないし、課金した直後はアガれます。これはこれでよくアルゴリズム考えてあるな…。

「気のせいだろ?」

って思います?いや、ちょっとでも遊んでみれば分かりますよ。

もっと面白い特性は色々あって、例えばその日最初に遊んでいるときはかなり勝たせてくれます。異常なレベルで良い配牌が来て、アホみたいにツモれる。でもしばらく遊んでいると怒涛のいじめターンが回ってくる。まるで「それ以上遊んでも勝たせてあげないよ」と言わんばかりに。

麻雀は盤ゲームの中では珍しく「僕らの目には見えない部分が多い」ゲームなので、コンピュータを介して遊ぶのには注意が必要だともともと思ってました。からのクソ麻雀アプリの横行を知り、「すげぇ金儲けを考えたな…」ともう呆れちゃうレベルでしたとさ。

健全な麻雀環境が増えるといいな。

おわりに

ふぅ。
で、何の話をしていたんだっけ?

そうだ、麻雀楽しいねって話だ!(してない)

 

あの、良い機会なので最後に言っておきたいんですが、麻雀の神は絶対にいます。普段から遊んでいる人はみんな知っていることですけど。ね?

そう、理論では語れぬ世界がここにはあるのだ…(今までの内容全否定)

関連しそうな記事