囚人のジレンマをオンライン対戦ゲーにしたら30分で攻略されてゲームが終わった
この記事で
学べそうなこと
- 囚人のジレンマ
- マッチングシステムの難しさとゲーム設計の難しさ
起きたこと
- Unityで囚人のジレンマの対戦ゲーを作った
- イケダが釈放されて、ヤマシタが懲役600年になり、ゲームが終了した
きっかけ
ある日こんな動画を見た。
「囚人のジレンマは何回も続くのであれば突然協力したほうがプラスになる」 ホンマか?
囚人のジレンマとは
(以下wikiより引用)
共同で犯罪を行ったと思われる2人の囚人A・Bを自白させるため、検事は囚人A・Bに次のような司法取引をもちかけた
本来ならお前たちは懲役5年なんだが、もし2人とも黙秘したら、証拠不十分として減刑し、2人とも懲役2年だ。
もし片方だけが自白したら、そいつはその場で釈放してやろう(つまり懲役0年)。この場合黙秘してた方は懲役10年だ。
ただし、2人とも自白したら、判決どおり2人とも懲役5年だ。
このとき、「2人の囚人A・Bはそれぞれ黙秘すべきかそれとも自白すべきか」というのが問題である。なお2人の囚人A・Bは別室に隔離されており、相談することはできない状況に置かれているものとする。
| 囚人B 黙秘 | 囚人B 自白 | |
|---|---|---|
| 囚人A 黙秘 | (2年, 2年) | (10年, 0年) |
| 囚人A 自白 | (0年, 10年) | (5年, 5年) |
人の囚人A・Bにとって、「互いに自白」して互いに5年の刑を受けるよりは「互いに黙秘」して互いに2年、合計で4年の刑を受ける方が得である。しかし、2人の囚人が「互いに黙秘」が全体の利益で得であると認識した上で2人の囚人A・Bがそれぞれ自分の利益のみを追求している限り、「互いに黙秘」という結果ではなく「互いに自白」という結果となってしまう。というジレンマ
そして、これを繰り返した場合に、「有限回」「無期限」で行動が変わる
有限繰り返しゲーム
2人の囚人がゲームの繰り返し回数を知っている場合は有限繰り返しゲームと呼ばれ、この場合には2人の囚人が全てのゲームで「裏切り」を選択することが知られている
無期限繰り返しゲーム
2人の囚人がゲームの繰り返し回数を知らない場合は無期限繰り返しゲームと呼ばれる。有限繰り返しゲームにおいては、最終回のゲームから順に後退帰納法を適用することで全てのゲームで裏切りを選択するのが均衡となることを導ける。しかし,無期限繰り返しゲームではゲームが終了する確定的な期限がないので後退帰納法を適用できず、協調の可能性が生まれる。
unity1weekとの出会い
そんなことを考えていたら、ちょうど 1週間ゲームジャム の開催期間だった。
こちらは 1週間でお題に沿ったゲームを作ってunityroomに投稿する というイベントで、今回のお題が 「うら」。
「裏切り」という単語が頭に浮かんだ
「気になるなら実際に作って確かめればいいじゃないか!!」
ゲーム概要
作ったのは「囚人のジレンマ」をベースにした対戦ゲーム。
- 全員 懲役300年 からスタート
- ランダムマッチングで対戦相手が決まる
- お互い「協力」か「裏切り」を選ぶ
- 選択の組み合わせで刑期が増減する
- 誰か1人でも刑期0年に到達したら、その人が釈放されてゲーム終了
| あなた | 相手 | あなたの刑期 | 相手の刑期 |
|---|---|---|---|
| 協力 | 協力 | -3年 | -3年 |
| 裏切り | 裏切り | +2年 | +2年 |
| 裏切り | 協力 | -10年 | +10年 |
| 協力 | 裏切り | +10年 | -10年 |
お互い協力し続ければみんな少しずつ幸せになる。でも裏切れば自分だけ大幅に得をする。まさに囚人のジレンマ。
「うはwww天才wwww」と思いながら、初めてのマッチングシステムをなんとか完成
システム構成
初オンラインマッチング対戦実装ということで、バックエンドには使いやすそうなFirebaseを採用した
| 層 | 技術 | 役割 |
|---|---|---|
| ホスティング | unityroom.com | WebGLビルドの配信 |
| クライアント | Unity C# + jslib Bridge | ゲームUI、Firebase JS SDKとの橋渡し |
| 認証 | Firebase Anonymous Auth | ユーザーIDの自動生成(アカウント登録不要) |
| API | Cloud Functions (HTTP) |
joinQueue(マッチング参加)、getRanking(ランキング取得) |
| ロジック | Cloud Functions (Trigger) |
onMatchQueueCreate(ペアリング)、onActionWrite(対戦結果計算・勝利判定) |
| DB | Cloud Firestore | ユーザー情報、マッチ情報、対戦履歴、ゲーム状態 |
| 定期処理 | Cloud Scheduler | 60秒毎にタイムアウトしたマッチを処理 |
ゲームロジックはすべてCloud Functions側で処理した。クライアントが直接Firestoreに刑期を書き込むことはできない。「協力」か「裏切り」のアクションを書き込むと、onActionWriteトリガーがサーバー側で刑期計算して結果を反映する仕組み。
公開、そして就寝
深夜23時過ぎ、unityroomに公開。
ワクワクが止まらない。みんなどんな選択をするんだろう。協力の輪が広がるのか、それとも裏切りの連鎖が始まるのか。
「明日の朝、データ見るの楽しみだな〜」
そう思いながら布団に入った。
起床
朝、unityroomのコメントを確認する。
「遊ぶ前に終わってた…笑」
え?
急いでゲーム画面を確認
イケダ釈放されとる!!!!
データを見てみる
データをエクスポートして並べてみる。
まず目に飛び込んできたのがこの2人。
| ユーザー | 刑期 |
|---|---|
| イケダM00002 | 0年(釈放済み) |
| ヤマシタK00002 | 595年 |
ヤマシタがとんでもない罪を犯したことになっている
この2人の対戦ログを見てみる
23:40:29 イケダ:協力 vs ヤマシタ:協力 ← 様子見?
23:40:53 イケダ:協力 vs ヤマシタ:協力 ← まだ様子見
23:41:13 イケダ:協力 vs ヤマシタ:協力 ← ここまで友好的
23:41:20 イケダ:裏切り vs ヤマシタ:協力 ← 本性出す
23:41:33 イケダ:裏切り vs ヤマシタ:裏切り ← ヤマシタも裏切ってみる
23:41:42 イケダ:裏切り vs ヤマシタ:裏切り ← うーん効率悪い
23:41:52 イケダ:裏切り vs ヤマシタ:協力 ← 役割確定、ここから作業
23:42:06 イケダ:裏切り vs ヤマシタ:協力
23:42:12 イケダ:裏切り vs ヤマシタ:協力
... (ひたすら同じパターンが続く)
23:44:36 イケダ:裏切り vs ヤマシタ:協力 ← 35戦目、フィニッシュ
23:44:39 ゲーム終了 🎉
35戦を約4分で消化。1マッチ平均7秒。
公開から30分で仕組みを見抜いて、最適な攻略法を編み出して、実行まで完了してる
何が起きたのか
たぶんこういうことっぽい?
- 2つの端末 を用意(PCとスマホとか)
- 端末Aで「ヤマシタ」、端末Bで「イケダ」のアカウントを作成
- 同時にマッチングキューに入って同一ペアでマッチ
- イケダ = 常に裏切り(毎回 -10年)、ヤマシタ = 常に協力(犠牲役)
- これを 35回 高速で繰り返す
ヤマシタは自由のための尊い犠牲となった。
2026/03/24追記) コンピュータ同士に反復囚人のジレンマを戦わせる戦略コンテストで使われた、
「主人と奴隷」という戦略と同じらしい、20年以上前にすでにこのゲームあったのか...😌
自分の実装を振り返る
同一IPは弾いてたんだけどなぁ
一応、自演対策として 同一IPアドレスからのマッチングは弾く 処理は入れていた。
// matching.js より(一部簡略化)
const ipHash = crypto.createHash("sha256").update(clientIp).digest("hex");
const filteredCandidates = candidates.filter(
(c) => c.ipHash !== myIpHash // 同一IP除外
);
でも冷静に考えると、スマホのモバイル回線とPCのWi-Fi を使えばIPは違う。
🌞
どうすればよかったのか
同一ペアの対戦回数に上限をつけてみる?
例: 同じ相手との対戦は5回まで
→ 5回を超えたらそのペアはマッチング不可
ただしこれでも問題がある、アカウントはシークレットウィンドウで開けばいくらでも作れてしまうので、マッチ上限に達したら新しいアカウントを作ればいいだけ
そもそも「同一人物」って判断できるのか?
根本原因は「1人の人間が複数のアカウントを操作していることを検知できなかった」こと。バックエンドの世界からは、イケダとヤマシタは完全に 別人 に見えていた。
オンラインで「同一人物」を判定する方法と限界
では、サーバー側から「この2つのアカウントは同一人物だ」と判定するにはどうすればいいのか。一般的な手法を強度順に整理する。
レベル1:IPアドレス
| 方法 | 同一IPからのアクセスを弾く |
|---|---|
| 実装コスト | ★☆☆☆☆ |
| 突破難易度 | ★☆☆☆☆ |
| 限界 | VPN、モバイル回線、テザリングで簡単に別IPになる。逆にNATやキャリアグレードNATで別人が同一IPになることもある |
| 実ゲーム事例 | Robloxなど多くのゲームが採用。ただしVPN・モバイル回線で即突破される[1][2] |
今回の自分の実装がまさにこれ。 スマホのモバイル回線を使うだけで突破された。
レベル2:デバイスフィンガープリント
| 方法 | ブラウザのUser-Agent、画面解像度、Canvas描画結果、WebGL情報、タイムゾーン、インストール済みフォントなどを組み合わせてデバイスを一意に識別 |
|---|---|
| 実装コスト | ★★★☆☆ |
| 突破難易度 | ★★☆☆☆ |
| 限界 | PCとスマホなど異なるデバイスを使えば当然指紋は別。ブラウザ変更や環境によって同一デバイスでも異なる指紋が生成されることがある[3][4] |
| 実ゲーム事例 | FingerprintJSなどのライブラリが有名。オープンソース版の精度は40〜60%程度だが、商用版(Fingerprint Pro)はサーバーサイド処理との組み合わせで99.5%の精度を謳っている[5] |
端末が2つある時点で無力 なので、今回のケースでは効果なし。
レベル3:電話番号 / SMS認証
| 方法 | アカウント作成時にSMS認証を要求。1電話番号 = 1アカウント |
|---|---|
| 実装コスト | ★★☆☆☆ |
| 突破難易度 | ★★★☆☆ |
| 限界 | 格安SIM、プリペイドSIM、SMS受信サービスで複数番号取得可能。家族の番号を借りることもできる |
| 実ゲーム事例 | Riot Games(VALORANT / LoL)がトーナメントモード参加に必須化。2025年からは高ランク帯にスマホアプリによる多要素認証(MFA)も導入[6][7][8] |
多くのオンラインゲームが採用する手法。効果的だが 1weekのカジュアルゲーに電話番号認証は重すぎる。 ユーザーが逃げる。
レベル4:行動分析(Behavioral Biometrics)
| 方法 | 操作パターン(タップ速度、マウスの軌跡、意思決定のタイミング)を機械学習で分析し、同一人物の操作する複数アカウントを検出 |
|---|---|
| 実装コスト | ★★★★★ |
| 突破難易度 | ★★★★☆ |
| 限界 | 十分なデータ量が必要。意識的に操作パターンを変えれば回避可能。プライバシーの懸念もある |
| 実ゲーム事例 | VALORANTが2022年に自動スマーフ検知を導入。ヘッドショット率・移動パターン等の行動データをMLで分析し、スマーフアカウントを検出後にMMRを2〜3倍速で適正レートへ引き上げる[9]。スタートアップのAnybrainは70以上の行動バイオメトリクスをAIで追跡し、ボット検出100%を主張[10] |
学術的には最も面白いアプローチ。実際にイケダとヤマシタの対戦ログを見ると、両方のアクション入力のタイミングが異常に近い(数秒以内に両者がアクション送信)ことから、機械的に検出できた可能性はある。ただし1weekの個人開発で実装するのは現実的ではない。
レベル5:ソーシャルグラフ / 信頼ネットワーク
| 方法 | 既存ユーザーからの招待や保証(vouching)を要求。信頼の連鎖でシビル耐性を確保 |
|---|---|
| 実装コスト | ★★★★☆ |
| 突破難易度 | ★★★★☆ |
| 限界 | コミュニティが成熟していないと成り立たない。シビル攻撃者同士で相互保証される可能性もある |
| 実ゲーム事例 | CS:GOの「Trust Factor」が近い思想。プレイ時間・購入履歴・通報歴などの複数シグナルを組み合わせた信頼スコアでマッチング相手を制御する |
Proof of Humanity や BrightID などのWeb3プロジェクトも同様のアプローチに取り組んでいる。[11][12]
レベル6:公的身分証明 / KYC
| 方法 | 政府発行のIDで本人確認。1人間 = 1アカウントを担保 |
|---|---|
| 実装コスト | ★★★☆☆(外部サービス利用) |
| 突破難易度 | ★★★★★ |
| 限界 | プライバシーの侵害、法的要件、UXの大幅な悪化。ゲームで身分証を求めるのは論外 |
| 実ゲーム事例 | Robloxが顔認証による年齢確認の展開を2025年に開始。ゲーム業界での先行事例として注目されている[13] |
金融サービスでは当たり前だが、ゲームでここまでやるケースはほぼない。
結局のところ
デジタルの世界において 「この2つのリクエストは同一人物から来ている」 と100%確実に判定することは、技術的に原理的に不可能そう
ゲーム設計としてのアプローチ
なので、アプローチを変えてみる
「不正を完璧に検知する」のではなく、「不正しても得をしない」設計にする。
| 対策 | 効果 | 実ゲームでの採用例 |
|---|---|---|
| ペア対戦回数の上限 | 自演の利益に上限を設ける | 多くのランクマッチシステム |
| マッチング間のクールタイム | 高速周回を防ぐ | FACEITなどの競技プラットフォーム[14] |
| 報酬の逓減 | 同じ相手との繰り返しで得られる報酬を減らす | VALORANT、Dota 2[15][16] |
| 異常速度の検知 | 7秒/マッチのような非人間的速度をブロック | Anybrain等のAI行動分析[10:1] |
| ELO的なレーティング | 極端な勝率の偏りを検知・適正化 | VALORANT自動スマーフ検知[9:1] |
参加者が自分の利益を追求して行動しても、設計者が望む社会的目標が自然に達成されるような仕組みを設計する[17]
つまり 「イケダがイケダとして合理的に行動しても、ゲームが壊れない」 ようなルールを最初から設計すべきだった。
イケダは不正をしたのではない。ルールの穴を突いた のだ。禁止されていないことを効率的にやっただけ。だからこれは設計の問題であり、イケダの問題ではない。
他に考えられるルール改善案
- マッチを4人にしてみる
- 4端末の用意はさすがにめんどくさいと思う
- オフライン限定にしてみる
- 大学の講義とかでやったら盛り上がりそう
- 1日5マッチまでとかにしてみる
こんくらいしか思いつかなかった...難しい...
「囚人のジレンマを繰り返すと協力が生まれる」のか?
当初の疑問に戻る。データを見る
公開からゲーム終了までイケダとヤマシタしかマッチしていないことが分かった
今回のゲームではそれだけが分かった
激動の30分間、そして遊んでくれてありがとう、イケダとヤマシタ
まとめ
「この2つのリクエストは同一人物から来ている」の判断の難しさという、マッチングシステムの奥深さを体感できるいい経験になった
そして、unityroomの1週間ゲームジャムでは面白いゲームが大量に無料で遊べますので、是非覗いてみてください!
また、ゲーム制作に興味ある方は、最初の一歩にとても最適です!
こういう変なゲームでも暖かく見守ってくれるので、ゲームを作ってみてください!ただ対戦ゲー作る時には釈放されたイケダに注意
-
Roblox IP Bans: And How to Protect Yourself - Using cheats to gain an unfair advantage, such as exploiting game bugs, using unauthorized tools, or... ↩︎
-
Roblox IP Ban 2025 Explained: Why It Happens and How ... - Bypass Roblox IP ban safely using VPNs and clean IPs to restore access and enjoy smooth, secure game... ↩︎
-
The fingerprint in incognito mode is always different · Issue #1088 · fingerprintjs/fingerprintjs - The fingerprint in incognito mode is always different and differs from the fingerprint that is displ... ↩︎
-
Why fingerprint is same in private mode as well ? · Issue #861 · fingerprintjs/fingerprintjs - Team can you please give me a knowledge that why this is same in incognito mode as well, as last mon... ↩︎
-
@automattic/fingerprintjs - npm - Browser fingerprinting library with the highest accuracy and stability.. Latest version: 3.4.2, last... ↩︎
-
Riot Tournament Modes - SMS Verification - In the Clash tab of the client, click Team and the Confirm SMS button next to your name. · Enter you... ↩︎
-
Riot Mobile Verification Beta - This step links your mobile device to your Riot account to help ensure it's being used securely and ... ↩︎
-
Riot rolls out Mobile Verification to combat smurfing in ... - With the Riot Mobile Verification Beta, flagged accounts must enable MFA through Riot Mobile. This p... ↩︎
-
VALORANT Systems Health Series - Smurf Detection - With Automated Smurf Detection, the primary goal was to use data to place smurf accounts within thei... ↩︎ ↩︎
-
This company is using AI to track players' inputs and detect ... - It tracks more than 70 behavioural biometrics, including keyboard and mouse dynamics as well as touc... ↩︎ ↩︎
-
Proof-of-Personhood: How It's Solving Sybil Attacks In 2025 ... - BrightID takes a decentralized approach. It verifies humanity by analyzing social connections. Real ... ↩︎
-
Proof of Humanity - Registry of Verified Humans - PoH ensures that only verified humans can participate in online voting and governance, preventing Sy... ↩︎
-
Roblox is rolling out face ID age checks to stop older ... - Age simply hasn't been the problem the actual problem is their inability to do any meaningful modera... ↩︎
-
Anti Cheat Smurf Detection FAQ - When accounts are detected by the Anti-Cheat system, they are required to complete a verification pr... ↩︎
-
VALORANT New Smurf Detection System - Riot Games developed sophisticated detection systems that target smurfing through behavioral analysi... ↩︎
-
Is Valorant's automated smurf detection system working? - With automated smurf detection, Riot uses data to place smurf accounts within the correct MMR as qui... ↩︎
-
Theory of Mechanism Design - D Mishra 著 · 2026 · 被引用数: 5 — The theory of mechanism design is probably the most successful story o... ↩︎
Discussion