とある落ちゲーを自動で解かせる話 その2
前稿では落ちゲーPentasを処理するためのクラスやゲームドライバーについて既述した。
(追記:最近のバージョンでは複数行消しボーナスがあることが発覚した。1行消しで+8、2行消しで+25、以降+70, +190, +450となっているようだが、これらを全て+8でコーディングしてしまっていた。つまり、この解析での得点は過小評価になっているが、得点よりも生存することがアルゴリズムとして適切なことや、結論は余り変わらないので、この間違いについてはいまのところ放置している。)
いよいよゲームを走らせる。保存されていくゲームログを盤面表示を有効にして解析していくと、おおコードが解いていく様子が見える。ぱっと見では自分が解くのと変わらないように見えるのだが…
最初はクリアボーナスを適当に5と設定して100回程度走らせた。その結果をgame_analysis.ipynbで解析してみる。
ちょ、容易に私の最高点の4656点を越えてくるんですが!10000点越えまで!スコアの分布をヒストグラムにして見ると
平均2143点で最高が10690点。チューニングもしていないのに、あっという間に負けた…。ニューラルネットとか持ち出す必要が全然ないじゃん。「しかし小僧、自分の力で勝ったのではないぞ!そのアルゴリズムの性能のおかげだということを忘れるな!」あー、もう手でやる気がせんわ。
それで分布を見ると指数分布に近い形をしている。青線は適当に指数関数を当てはめたもの。得点が0点ということはなかなかあり得ないのだから、0が最頻となる指数分布には完全には沿わないはずだが、得点分布は標準偏差と平均が近いことからもだいたい指数分布に近いのだろうと推測される。
クリアボーナスの最適化
ひとつだけチューニングしておきたいのが、コスト関数における行クリアボーナスの重み付けである。行クリアボーナスを全く考慮しないとだめなのは直観からも結果からもわかるのであるが、どれくらい重視すべきか?あまりクリアにこだわると盤面が荒れてダメになると思うのだが。
そこで、クリアボーナスを0~20で適当に変えて実行してみた結果が以下の通りである。
青が平均値と標準偏差、赤が最大値である。厳密ではないが、各点でおおむね20回程度ずつ試行している。
最大はなんとクリアボーナス3~4あたりでの13000〜14000。平均はクリアボーナス3~4でピーク値約2800を迎えた。つまり、ライン消し無視(ボーナス0)は論外だが、表面積換算で3~4あたりのボーナスにすると良い塩梅らしい。「消せるからって余りに表面積増やすようではNG」である。逆に言えば「孤立ブロック1~2個出ても1ライン消せればOK」という感じか?
ボーナスがより大きくなると緩やかに平均点が2000くらいまで落ちていった。ちなみにボーナス100でも1800点程度であった。2つのピースで行を取れるだけ取ることにし、取れないときは表面積を最小にするようにする、という方針だけで、それくらいの平均点まではいくはずなのだが…人力での平均が700点とは…不甲斐ない。
どのボーナス値でも標準偏差が平均値と近いのはやはり分布が指数分布に近いのであろう。
まとめ
まあぼちぼちの計算コストで充分満足な程度プレイしてくれるアルゴリズムが見つかったし、Pythonのトレーニングにもなったし、今回はこれでよしとする。
プレイログはたくさんあるから、自動プレイする様子をスクリーンセーバーかガジェットにでもして眺めたら楽しいかな?