動的難易度調整の研究
研究室のメンバー4人で作ったブラウザの3Dゲームで、遊んだ人のプレイ記録189件を集め、その人に合う難易度をAIに決めさせる仕組みを作りました。 機械学習でいちばん難しかったのは、モデルではなく、「ちょうどいい難易度」をどう定義するかでした。
Problem 189回のうち、勝てたのは60回だけだった
DOG SQUADは、犬を操作して自分の家をリスの群れから守る、ブラウザで遊べる3Dタワーディフェンスゲームです。 Three.jsで描き、効果音やBGMはWeb Audio APIでその場でリアルタイム生成しています。
公開後に集まった189回分のプレイデータを集計してみると、勝てたのはわずか60回(勝率32%)でした。 作り手としては歯ごたえのある難易度にしたつもりでしたが、遊ぶ人にとっては難しすぎたのです。
最初から難易度を手で選ばせる作りにしていたのですが、自分の腕前に合う設定を選べる人はほとんどいませんでした。
Idea ゲーム側がプレイヤーの腕前に合わせる
そこで、プレイ結果から自動的に次の難易度を調整する動的難易度調整(DDA)を取り入れることにしました。
単に「負けたら簡単にする」だけでは、上手なプレイヤーにとって退屈になってしまいます。 「ギリギリ勝てる、一番楽しい手応え」をどう数値化するかが大きな鍵でした。
Label 「ちょうどいい」のルールを設計する
クリア時の残り体力や勝敗をもとに、次回の敵の強さの倍率を決める教師データを独自に設計しました。
- 20%〜70%残しで勝利白熱した良い勝負なので、現在の倍率を維持
- 70%以上残して完勝余裕がありすぎるため、難易度を1.3倍に引き上げ
- 20%未満のギリギリ勝利運が良かった可能性を考慮し、0.8倍に微調整
- 敗北挫折を防ぐため、0.6倍にして再挑戦しやすくする
Model & Result 予測精度と軽量化の両立
直近5回分の戦績とスコアを特徴量にして、軽量なニューラルネットワークで学習させました。 過学習を抑えつつ、負けた人には優しく、上手な人には歯ごたえを残す。そのバランスを取る予測モデルができました。
左が学習中の誤差です。最初の20回ほどで0.06から0.03あたりまで一気に下がり、 そこからは細かく上下しながら、80回目で0.013付近に落ち着いています。 後半のギザギザは学習率を下げずに回しているせいですが、下がりきったあとに跳ね上がってはいないので、 過学習の手前で止められていると判断しました。
右が本題です。横軸が教師データの倍率、縦軸がAIの予測値で、赤い点線の上に乗るほど正解に近い。 点が縦の帯に分かれているのは、倍率が1.3倍や0.6倍のかけ算で積み上がるので、 取りうる値がとびとびになるためです。
1.0前後の帯はよく当たっています。 外れているのは両端でした。 とくに右端の1.7付近では、予測がほぼ全部点線より下にあります。 強くしていいと教えているのに、AIは控えめな数字しか出していません。
理由はデータの数だと考えています。189件のうち大半は普通に勝ったか負けたかで、 3回連続で完勝して倍率が1.7まで積み上がるような記録はごく少数です。 数の少ない値は平均に引っぱられるので、上手い人ほど本来より易しい難易度を出されてしまう。 いちばん歯ごたえを求めている層に、いちばん効きが弱いという結果になりました。
Limit 正解そのものを疑う
ここまでの精度は「教師データにどれだけ近づけたか」でしかありません。 その教師データは、残り体力で場合分けした自分たちの手作りのルールです。 つまりこのモデルが上手くなるほど、私たちが決めた線引きを忠実になぞるだけになります。
体力を20%残して勝った人が本当に楽しかったのかは、体力の数字からは分かりません。 それを確かめるには、遊んだ人に面白かったかを聞いて、その回答を正解として学習させる必要があります。 機械学習でいちばん難しいのはモデルではなく「ちょうどいい」の定義だった、というのは、 最後までそこに戻ってきたからです。