Upload
mayahjp
View
8.163
Download
3
Embed Size (px)
Citation preview
@mayah_puyo最近の普段の仕事
chrome のビルドを速くする仕事
3年ぐらい前はShadowDOMの実装とか
ぷよぷよ AI
ACぷよぷよ通 第一回 人類 vs AI 総監督
現状のフレームワーク大体全部書いた
ぷよ歴は断続的に20年ぐらい
古くは ばよえ~んツアー '97 CSA愛媛大会マスター
Red Bull 5g 2014 ぷよぷよ東日本代表決定戦 3位
← この娘は誰?mayah (擬)
イラスト もりやあこ様
人類 vs AI のときに、最近の流行りにのって擬人化しとくかと思った
ぷよら~エンジニア飲み会でたまたま横に座ったので発注させていただきました
mayah (AI) の評価方法基本は単純な2手読み
NEXT1 と NEXT2 を見て、NEXT1を置く場所を考える
それぞれの置き方に対して評価点を付与し、最も高得点な場所へ置く
1連鎖1000点で線形に増えていくような評価点
5連鎖 = 5000点、10連鎖 = 10000点
評価点の計算なんらかのフィールド上の「特徴」に対して、その特徴が現れた回数だけその特徴に対する得点を付与
序盤、中盤、終盤で評価点が異なる
序盤・中盤・終盤は、フィールド上のぷよの個数で決める程度のラフな決め方
序盤はスキが多少あっても良い(スキが増えるものに対する減点を小さくする)、終盤はいつでも打てるようにする、など
フレーム数ぷよを置くのに必要なフレーム数が大きいほど減点する
ただし、最終的にはフィールドを埋め尽くすほどぷよを置いてしまうので、今遅い置き方でも後で取り返せる
従って、1フレーム 0.1 点程度の微小な減点のみにとどめてある
基本的にはタイブレークとしてのみ使われる6列目の方が若干遅いが、どうせあとで6列目に置かなければならない
U字型AIは端を使うのが苦手なので、積極的に置くようにする
U字型から外れることに対して減点
理想の高さを平均高さから求め、そこからの二乗誤差で減点
高さが低いときはU字型を意識しなくても良いので、高さに応じて減点を調整 この辺が使いづらい
山・谷
山: 左右の列より高い列
谷: 左右の列より低い列
山や谷を作るとそこに置けるぷよが制限されがち
高さ4以上の山、もしくは深さ4以上の谷に対して2000点以上の大きな減点
谷(深さ5) 山(高さ4)
連鎖に関する評価自分のフィールドから可能な連鎖を列挙
列挙した連鎖に対して評価を行なう
「本線」と「副砲」の両方を別の基準でカウントし、それぞれ良いものを1つずつ選ぶ
評価基準
連鎖数
発火までに必要な個数
定積パターンマッチ
パターンマッチによる補完mayah (AI) は、人がよく使いそうな連鎖をパターンとして保持
A→青、B→赤、C→黄
マッチしたら、空白パターンをマッチしたもので埋める
この状態で、3連鎖が見つかる
mayah (AI) は100パターンぐらいの3連鎖のパターンを持っている
A.....ABC...AABCCCBBC...
GTR pattern埋める前 埋めた後
パターンマッチによる補完 (contd.)
連鎖が見つかったら、連鎖を1つ進めて、さらにパターンマッチを行なう
......
..B.C.
.AABBBAABCCC
連鎖前 1つ進めて C→緑を補完別のパターン
パターンマッチによる補完 (contd.)
補完したぷよを、最初にフィールドに全部補完して、連鎖が壊れてないことを確認
この場合、「青2個、赤1個、緑1個を補完して4連鎖」という連鎖が列挙できたことになる
パターンを使わない場合の補完消せるぷよは、消すためのぷよを補完して消してみる
右の場合、黄色を2列目に2個、もしくは4列目に1個、6列目に1個おくと消える
どういう連鎖になるのかはわからないが、とにかく消せるものは補完して消してみる
よい連鎖かどうかは後の評価で分かるので、とにかく候補を列挙する
連鎖の形連鎖としても、山や谷、U字型になっているかどうかを評価する
形の悪い連鎖を目指しても良くないので、形の良い連鎖を最終的に目指すようにおいていく
2列目に高さ1の山、6列目に深さ1の谷6列目が低いので、U字型としての評価は低い
連鎖までに必要なぷよの数連鎖を発火するのに補完したぷよから、何個ぷよを引けば連鎖が発火できるかを計算
補完が赤1個なら、
確率50%で赤を1個引く場合、ランダムに3回引くことが必要
確率80%で赤を1個引くには、ランダムに6回引くことが必要
何回ぷよを引く必要があるかを計算し、二次関数的に減点
この場合の確率はひとまず50%での値を使う
この確率は、プログラム開始時に事前に計算している
凝視と発火に関する評価いくつかのハードコーディング(ただし、消したい)
N個以上おじゃまが自陣に降るなら対応する、など
if文並ぶだけであまりおもしろくないので省略します
RensaHandTreeと呼ばれる木の作成と評価
自分の想定される連鎖と、相手の想定される連鎖の打ち合いを行なった後、どちらにおじゃまぷよがどれぐらい降るかを予測する
こちらにおじゃまが降りそうならば減点する。こちらから発火時するときは、相手に返されないことを確認できる
RensaHandTreeどういう連鎖が打てるのか、その連鎖を打った後にさらにどういう連鎖が打てるのかを木で表現したもの
全部の連鎖を列挙するには連鎖の数が多すぎる、木として抽象化し、不要そうな連鎖を間引いて所持
何フレームで何連鎖が打てて、何フレームで終わるかを列挙
自分と相手の両方作る
フレーム数は50%の確率での値を利用している
現在
2ダブ 5連鎖 11連鎖0F,120F 32F,183F 0F, 612F
3連鎖 5連鎖
0F, 180F 0F, 250F
5連鎖
120F, 250F
xF, yFx: その連鎖を打つために引く最後のぷよを引くのにかかるフレーム数y: 発火した時に、操作を開始してから発火終了までに何フレームかかるか
RensaHandTreeの作り方まずフィールドから考えられる連鎖を列挙できるだけ列挙
列挙した連鎖を終了フレームでソート
先頭から見て行って、今までで一番連鎖の得点が大きかったら選ぶ
選ばれた連鎖を発火後にもう一度同じことをやって、木の次段を作成する
5連鎖 250フレーム
4000点
2連鎖 150フレーム
1000点
3連鎖 300フレーム
1200点
採用
今までの最大点
1000
採用 4000
不採用 4000
RensaHandTreeの評価 (ケース1)今、自分はすぐに打てて120フレームで終了する2ダブがある
相手には240フレーム後に打てる14連鎖しかない(他の連鎖がない)
つまり、2ダブが刺さると判断できる
現在
2ダブ 11連鎖
0F, 120F 120F, 550F
3連鎖 5連鎖
0F, 150F 0F, 250F
現在
14連鎖
240F, 840F
相手自分
RensaHandTreeの評価 (ケース2)0Fで打てる2ダブを打つと、相手は4連鎖で対応できる
対応されてもて260Fまでに自分は4連鎖を打てる相手はその後、2連鎖しか打てず、12連鎖には間に合わない
最終的に相手に10個ぐらいのおじゃまが降りそう
現在
2ダブ 11連鎖
0F, 120F 120F, 550F
4連鎖 5連鎖
0F, 150F 0F, 250F
現在
14連鎖
240F, 840F
相手自分
4連鎖
60F, 260F
2連鎖 12連鎖
130F, 200F 250F, 600F
発火判断
RensaHandTreeの結果を使う
打った後に、RensaHandTreeを評価し、おじゃまが相手のフィールドに何個か降ると判断されるならば、おそらく打って良いとして加点、こちらのフィールドに降ってくるなら、返されるとして減点
実際には掘りや伸ばしなども考慮して打って良いかどうかを判断しているが非常に複雑になるのでここでは省略
ちなみに、どれぐらい連鎖組めるの?
2手読み、とこぷよ
中央値が80,000点ぐらい
RensaHandTreeナシ(重いので)、3手読み、パターンによる補完を3回とすると、中央値が95,000点ぐらいになる