feature image

2017年11月22日 | ブログ記事

ぷよぷよの連鎖を探索する

この記事はtraP Advent Calendar 11月22日の記事です。


こんにちは、ninjaです。ハル研究所プログラミングコンテスト2017で4位になりました✌
今回はぷよぷよを計算機の力でプレイしていきます。

0. ぷよぷよとは

ぷよぷよは対戦型パズルゲームです。
降ってくる3~5種類のピース(ぷよ)を操作して最上部に来ないようにするゲームです。
ぷよは4つ以上つながると消え、消した量に応じて相手を妨害することができます。
ぷよが消えたあとにさらにぷよがつながり、消えることを連鎖といいます。

残念ながら対戦する相手がいなかったのでとことんぷよぷよという一人プレイ用のモードで連鎖数を伸ばす遊びをします。

1. 準備

全てシミュレーションしてもよかったのですが、画面映えしなさそうだったので実機で行うことにしました。

使ったもの

画面からぷよの色を取得する

windows apiでPS2のキャプチャーのウィンドウのピクセル情報をもらい、その色からぷよが何色かを取得します。
各ぷよに関して5点から色を取得し、その平均値からRGBの3次元ベクトルを作成します。
ぷよの赤緑青黄の値を計測して大体

赤 : "rgb(180,0,0)"
緑 : "rgb(50, 170, 50)"
青 : "rgb(10, 25, 140)"
黄 : "rgb(145, 116, 25)"
であることがわかりました。 色によって判定するのでRGBの値をHSV色空間に変換し、そのH(色相)の値によって色を決定します。 数秒間判定を取り、多数となった色を採用することで精度を上げました。\[1\]

ターン遷移検出

次のターンに移る際、0.2秒程度ぷよがスライドすることによって背景の色がぷよの色として得られます。
プログラム側ではこの色を見ることで、ターンの遷移を検出することができます。

ターンの遷移と色の取得ができたのでいよいよ探索部分の構築をします.

2. アルゴリズム

ここで今回のゲームのルールを決めます。

入力は2手のみなので全探査は簡単に行うことができます。
しかし、2手先程度ではどの操作がよいのか判定することは非常に難しいです。

pu

そこで、モンテカルロ木探索[2]を行います。
乱数で後続のぷよを上限まで生成し、その中での最適な第一ぷよに対する操作を求めます。
今回は5回行い、多数決を取り、操作を決定します。
複数の乱数入力で同じ初手になるということは、現在見ることができない先の入力がどのようなものであってもある程度有効に働くと考えることができるためです。

後続のぷよがすべて明らかなとき、プレイヤーが行うことができる操作は1手につき22種類です(縦2種類*6 + 横2種類*5)
なので被りを考慮しなければ、n回先の盤面状態は22^nあると考えられます。
全ての状態を見て、その中で一番連鎖数の多いものを採用できればよいのですが、nが6を超えるあたりから全探査は困難になります。
ですが、この盤面の中には明らかに大きい連鎖数を達成できないものがたくさんあります。

amarec-20171119-135319-
適当においたものです。

このような盤面を無視することができれば、大きい連鎖数を見つけやすくなります。
盤面に対して、大きい連鎖数を作ることができるか、という指標に評価関数を導入します。
さらに、探索にビームサーチ[3]を導入します。
ビームサーチは各ターンの状態を評価関数が大きい順に固定数(ビーム幅と言う)で採用していきます。

beam
幅3のビームサーチ[4]

よい探索が行えるかはほぼ評価関数の質で決まるので後は評価関数を頑張って生成します。

3. 実演

今回は以下の条件で探索を行いました。
ビーム幅: 50
モンテカルロ木探索: 5回

1

評価関数:
隣接する同色の数^2の総和

2

評価関数:
隣接する同色の数^2の総和+0, 5列の高さ*2+1, 4列の高さ

3

評価関数:
隣接する同色の数^2の総和+0, 5列の高さ*2+1, 4列の高さ
+各列に1つだけぷよを落としたときに連鎖する数の最大値*10

4

評価関数:
隣接する同色の数^2の総和+0, 5列の高さ*2+1, 4列の高さ
+4または5個で消える連鎖数の最大値*10

4. おわりに

最後まで読んでいただきありがとうございました。
思い付きの実装が多かったのですがいい感じになったので助かりました。
マラソン系で結果を残せるようになりたいなあと思うばかりです。
明日はarcusさん、crotkazさんの2人です。

参考文献

MSDN
スクリーンキャプチャ【Windowsプログラミング研究所】
プログラミングと色々 ほかのプログラムのウィンドウハンドルを取得する
ぷよぷよAIの新しい探索法


[1]:
PS2の映像出力はアナログで、画面にノイズがたくさん入ってました。
緑と黄が色的に近かったのでそこの判定が一番困った点でした。

[2]:
囲碁や将棋のAIなどで使われているようです。乱択は神。

[3]:
去年のハルコンではかなり有効な手段だったので、今年も使うぞと意気込んでいたのですが結局使いませんでした。

[4]:
ビーム幅1だと貪欲法、十分に大きい値だと全探索になります。

ninja icon
この記事を書いた人
ninja

競技プログラミングなどをします

この記事をシェア

このエントリーをはてなブックマークに追加
共有

関連する記事

2017年11月14日
IBIS2017参加報告
Keijan icon Keijan
ERC20トークンを用いた宝探しゲーム(真)の提案【アドベントカレンダー2018 10日目】 feature image
2018年11月3日
ERC20トークンを用いた宝探しゲーム(真)の提案【アドベントカレンダー2018 10日目】
Azon icon Azon
2021年5月19日
CPCTF2021を実現させたスコアサーバー
xxpoxx icon xxpoxx
2023年4月27日
Vulkanのデバイスドライバを自作してみた
kegra icon kegra
2021年12月8日
C++ with JUCEでステレオパンを作ってみた【AdC2021 26日目】
liquid1224 icon liquid1224
2019年4月22日
アセンブリを読んでみよう【新歓ブログリレー2019 45日目】
eiya icon eiya
記事一覧 タグ一覧 Google アナリティクスについて 特定商取引法に基づく表記