強化学習で自作ゲームを攻略する

概要

強化学習を用いて自作ゲームを攻略してみた。

・強化学習初心者でも単純なゲームならいける

・導出された最適プレイからゲームデザインの失敗が浮き彫りに

・UE4 Festはヤバい奴の集まり

背景

拙作の第10回UE4ぷちコン応募作品「ベリーぷちぷち」について、

UE4 Festで展示して頂いた際に開発者の最高スコアをあっさりぶち抜かれて

嬉し涙&悔し涙が左右の眼(まなこ)からそれぞれ垂れてアメリカンクラッカーみたいになったので

強化学習で攻略して実際どういう風に遊ばれたのか解析する事にした。

ゲームについて

一人用パズルゲーム。

ぷちコン応募時の動画はこちら

プレイアブル版はこちら

ゲームルールは以下の通り。

[基本ルール]

・中央に9つの枠、左右にそれぞれ5つの枠がある。

・中央に3種類のコマを3つずつ配置した状態からゲームを開始する。

・プレイヤーは手数(初期値30)を消費して、場からコマを取る。

・手数がなくなったらゲーム終了。とったコマの個数が点数になる。

[コマ補充]

・中央からコマを取った場合、空いた枠にコマが補充される。

・次に何が補充されるか、プレイヤーは4つ先まで見える。

・4つ先以降は3種類からランダム抽選される(見えるようになった時点で確定する)。

[チェイン]

・同じ種類のコマが隣接している場合、1手でまとめて取れる。

・ただし、中央と左右の場をまたいでまとめる事はできない。

[コンボ]

・同じ種類のコマを3個続けて取ると、左右の場の空いている枠にランダムで2つコマが配置される。

・「続けて取る」判定は手番をまたいで継続する。ある種類を1個とって、次の手番で同じ種類のものを2個取るとコンボ成立。

つまり、なるべく多くの同種コマが隣接しあうように調整しながらコマを取っていくゲームとなる。

強化学習

環境

行列計算ライブラリEigenを用いて、C++環境で自作した。

制作においてはEigenでDNNを構築しているMiniDNNをベースに、

機能面についてtiny-dnnを参考に拡張した。

また、ゲーム環境については

上記のゲームルールをもとに改めてルールのみのクラスを作り直した。

つまり、UE4を使わずにゲームをプレイして学習できる状態にした。

※応募用にUE4でゲームを作った時は機械学習に使うなどと考えてもいなかったので

ルールが複数クラスに分散していて…そりゃあもうひどい有様だった(帰還兵の表情)

手法

Advantage Actor-Critic(A2C)を利用した。

実装は書籍「つくりながら学ぶ!深層強化学習 PyTorchによる実践プログラミング」を参考にした。

ただし、ActorとCriticのNetworkは別になっている。

これは単に自作のDNNクラスにLayerをCatするような機能がない為である。

各Networkへの入力は以下の通り。

・盤面(one-hot vector)

・Next(one-hot vector)

・残り手数

・コンボ数

・コンボ種類(one-hot vector)

隠れ層は64unitの全結合層を2層、そこから

Actor-NetworkはSoftmax層へ、Critic-Networkは活性化ナシの1unitに全結合している。

最適化手法はAdam。

学習率はActor-Networkで0.001、Critic-Networkで0.01とした。

このあたりが学習の進行速度と安定が丁度よいようだ。

報酬割引率は1.0。

毎回確実な手数で終わるので割り引かなくてもよかろうと思い1.0にした。

Advantage step数は10。

30で毎回ゲーム終了まで進めながらやると、かえって学習が遅くなったのでこの値にしている。

並列環境数は64。

これはいくつが適正なのかあまりよくわからない。32でも十分に学習は進む。

報酬設計

プレイヤーと同じように獲得したコマがそのまま報酬値になるようにした。(clippingなし)

ただし、コマがない枠からコマを取った場合は、

それまで獲得した点数分の罰則(-1.0倍の報酬)を与えゲーム終了するようにした。

プレイヤーが実行できない「無を取得」する行為はこの罰則で行わないようになった。

目標

おかずさんのツイートから、89点が展示時の最高成績だと判断し、

これを超える90点の獲得を目標に学習させた。

UE4側の対応

学習済みActor-Networkのデータをファイルに出力して保存し、

UE4のゲーム側にDNNのForward部分だけ組み込んで再生すれば

ゲーム中に学習AIのおススメ手を見ることができるようになる。

Eigenと自作DNNクラスを丸ごと入れて終わりなので移植自体は楽だった。

結果

Ryzen 7 2700Xで15分程度学習させると

直近100ゲームの平均スコアが90を超えるようになった。

学習済みNetworkの指示のもとにゲームを進行すると、実際に高スコアを得る事が出来た。

ちなみに自力では最高で72点しか取れなかった。

読者も気が付いていると思うが、作者はルールのガバガバさに気が付かない程度の頭脳なのだ…

考察

ゲームデザインの検証

最適化されたゲームプレイをなぞる事で分かったことがある。

・コンボボーナスの意味がない

・上記の点数は、中央の枠しか使わなかった。

・生える場所がランダム+生えるものもランダムという事で、不確実性が高すぎて戦略に組み込めない為だろう。

・9個チェインは狙わない方が良い

・上記の点数は、3~4チェインをコンスタントに出す戦略で獲得できた。

・これを狙っていると無駄に手番を消費するので狙ってはいけないのだろう。

・一番気持ちいい部分であるはずなのに…

・運ゲーすぎる

・強化学習中の得点ログを見ると、90を中心に80~100点でバラついている。

・ランダムでコマを出しているのでどうしてもこうなるが、ランキングのあるゲームでこの幅はまずい気がする

うん、あれだね、

ゲームデザインがまずいのか自分のプレイが下手なのかわかんなかったんだけど

やっぱりデザインがまずかったね…(白目)

プレイヤーにどのような体験をさせたいか、そのためにどのようなルールにするか、というところで

機械学習による最適解がそれに沿っているか確認する、というのは

ゲームデザインで役に立ちそうだ。

NEXT表示数の妥当性検証

・Next表示は大事

・ためしにNext情報を渡さずに学習をさせると、65点前後で学習が進まなくなった。そりゃそうだ。

・いくつNextを見せるのがいいかの検証にも使えるかもしれない。

・NEXT表示数が4個でも10個でも、スコア期待値は95程度が上限だった

・頭だけで考えると、NEXTがいっぱい見えるほどに有利そうだが…?

・プレイヤーがコマの補充される位置を制御できないので、先まで見えていてもあまり意味がないという事か

・あるいは、制御対象となる場の数が少なすぎて、有効に消化できないというのもあるだろう

・テトリスで□ブロック置き場をキープできてない感じだ

・つまり、ゲーム展開の幅が少ないという事だ…

→補充位置をもっと制御下に置けるようにする必要がある。

ほか

・学習成功まで、ざっくり2,240,000ゲームほどかかった。1プレイ3分として106,624‬時間(12年)

・フェス展示の数時間、講演聴講を含めればより少ない時間で、この領域に到達する猛者がUE4 Festには集う

・コワイ!

以上