確率の悪魔と物理世界を理解するAIの構築に挑む

Blackjack Omega & Melon AI 開発日誌

Python Machine Learning Box2D GCP

第1章:ブラックジャックで「運」をねじ伏せる攻略法

このサイトで稼働しているブラックジャックは、実際のブラックジャックのルールと同じではなく、かなり簡素化されています。しかし単なる運ゲーではありません。「Omega」と名付けられた対戦AIは、デッキに残っているカードを全て記憶(カウンティング)し、次の1枚が自分にとって有利か不利かを常に計算しています。 しかし、人間が勝つための攻略の糸口は確実に存在します。

1. 「見えているカード」から逆算せよ

ブラックジャックの基本にして奥義です。AIのアップカード(見えている1枚)が「6」以下の場合、AIはバースト(21オーバー)する確率が統計的に高くなります。 この時、あなたは無理に「Hit」してリスクを冒す必要はありません。たとえ自分の手札が「12」や「13」という弱い数字でも、状況によっては「Stand」してAIの自滅を待つのが定石です。

2. 共通デッキの特性を利用する

攻略のヒント:
本ゲームの最大の特徴は、プレイヤーとAIが「同じ山札」を使っている点です。もし、低い数字(2〜6)がたくさん場に出ているなら、山札には高い数字(10, 11)が眠っているでしょう。

高い数字が手元に多い状況は、手札が強い反面、バーストもしやすい「高リスク・高リターン」な状態です。ここでSPカード「ポイント-3」を使い、相手を精神的に追い詰めるのが勝利への鍵です。

第2章:技術的挑戦 —— なぜブラウザゲームに「世界モデル」を搭載したのか

ここからは開発者向けの技術的な話をします。このサイトは一見すると普通のブラウザゲームですが、裏側ではGCP (Google Cloud Platform) 上で、かなり無茶なアーキテクチャが動いていました。

サーバーサイド物理演算の地獄

「メロンゲーム」のような物理パズルをオンライン化する際、最大の敵は「同期ズレ」です。通常、物理演算はJavaScriptを使ってブラウザ(クライアント)側で行います。しかし、それではクライアント改ざんによるチートし放題になってしまいます。

初期の私は、Pythonの物理エンジン「Box2D」をサーバー(Cloud Run)上で走らせ、その計算結果をリアルタイムでブラウザに送信する実装を選びました。 開発当初は地獄でした。通信ラグで果物がワープしたり、床を突き抜けたり…。解決策として採用したのが、「物理ステップの先行計算」「スナップショット補間」です。サーバー側で数フレーム先まで計算を済ませておき、ブラウザ側ではその隙間をアニメーションで埋める。これにより、サーバー負荷を抑えつつ、ヌルヌル動く物理挙動を実現しました。しかし今ではそれらギリギリの最適化を放棄し、GCEに移行しています。

世界モデル (World Models) というロマン

メロンゲームの対戦相手であるAIには、最新の研究トレンドである「世界モデル」を組み込んでいます。通常のAIは「今の画面」を見て「次の操作」を決めます。しかし、このAIは違います。

ブラウザゲームのAIにここまでのスペックを求めた結果、メモリ使用量が跳ね上がり、Cloud Runのメモリ制限(4GiB)との戦いが始まりました。「Tensor Train Layer」という技術を使ってニューラルネットワークの結合パラメータを圧縮し、なんとか実用速度で動くようにチューニングしています。

「重い」初期ロードとの戦い

リリース直前、致命的な問題が発覚しました。TensorFlowと巨大な学習済みモデルを読み込むため、サーバーの起動(コールドスタート)に10秒以上かかってしまうのです。これではユーザーが逃げてしまいます。

そこで、AIモデルのロードを「アプリ起動時」ではなく、「ユーザーがメロンゲームを開始した瞬間」まで遅延させる(Lazy Loading)仕組みを導入しました。さらに、モデルをメモリ上に常駐させる「シングルトンパターン」を徹底することで、2回目以降の推論速度を極限まで高めています。

ゲームに戻る