Amazon Bedrock AgentCore を使って 3マッチパズルの自動プレイ検証に挑戦し、ハマった話
はじめに
こちらは「Applibot Advent Calendar 2025」6日目(?)の記事になります。
今回の話は、クラウドでの自動テストに向き合おうと思い、AWS Device Farm の利用を見据えつつ、
Amazon Bedrock AgentCore と Appium を使って「3マッチパズル」の自動プレイ検証に挑戦したものです。
結果から言うと、自動プレイとしては失敗しました。
ただし、その過程で
- AI が「盤面をどう理解しているか」を可視化すると、何が起きているかが見えてきたこと
- 同じ盤面を ChatGPT Pro, Gemini 3 Pro に与えると、認識・推論が成立するケースを確認できたこと
などの示唆が得られたため、その試行錯誤をまとめます。
なおこの記事は、次の 2 つのフェーズに分けて書きます。
-
Phase 1:自動プレイ検証
スクリーンショット → 推論 → 操作(Appium)を実際に回し、どこで崩れるかを確認します。 -
Phase 2:単体評価(盤面認識の検証)
失敗原因を切り分けるため、同一スクリーンショットを入力に「成立する 1 手を判断できるか」をモデル比較します。
Phase 1:自動プレイ検証
自動プレイ検証の概要
まずは Phase 1 として、AgentCore + Appium で自動プレイのループを回し、どこまで動くかを確認しました。
最初に、以下が今回の検証結果の GIF です(倍速になっています)。
最初のステージ選択などの画面遷移は問題なく進むのですが、
インゲームの 3マッチが安定せず、ステージクリアまでは到達しませんでした。
一見すると「それっぽくタップやスワイプはしている」のですが、推論で出た swap の座標を画像に重ねて可視化してみると、たまたまうまくいっているように見えるだけの状態でした。
そのため、実際には ゲームとして成立していない 状態です。
自動プレイの全体像
今回やったこと自体は、かなりシンプルです。
- スクリーンショットを取得する
- LLM に渡して「次の 1 手」を JSON で返してもらう
- Appium で tap / swap を実行する
- before / after や推論結果を保存する
利用した構成要素は以下になります。
- AWS Bedrock AgentCore
- Appium
- Android Studio のエミュレータ
- Unity 製の 3マッチパズル Gem Hunter Match
「盤面が毎回ランダムで、決め打ちの UI テストが書きづらい」
という点から、3マッチパズルを題材に選びました。
※これが達成できれば、他のテストもやりやすくなるのでは?と思ったためです。
実際に使用したプロンプト
下記のプロンプトを system プロンプトとして入力しました。
出力を固定させながら、rules_textを変更することで他のゲームにも対応できるようにした想定です。
system_prompt = f"""You are an automated game testing agent.
Follow the game-specific rules provided below to decide the single best next action.
=== GAME RULES START ===
{rules_text}
=== GAME RULES END ===
Output requirements (must override any conflicting rule text):
- Respond with JSON only (no prose, no code fences).
- Use normalized screen coordinates where top-left is (0,0) and bottom-right is (1,1).
- All coordinate ratios must be between 0 and 1 (inclusive).
- Parameter requirements by action:
- tap: params.x and params.y are required
- drag/swipe/swap: params.x, params.y, params.x2, params.y2 are required (start -> end)
- wait: params.duration_ms is required (milliseconds)
- back/end/noop/error: no extra params required
If a screenshot is provided, identify highlighted/arrow/framed UI first. Optionally put structured data in params.note (JSON object/array/string; e.g. an array of {{name, x, y}}). Then pick ONE action that best follows the guide.
You must respond ONLY with a JSON object of the following schema:
{{
"action": "tap" | "drag" | "swipe" | "swap" | "wait" | "back" | "end" | "noop" | "error",
"reason": string,
"params": {{
"x": number | null,
"y": number | null,
"x2": number | null,
"y2": number | null,
"duration_ms": integer | null,
"note": any | null
}}
}}"""
今回の3マッチパズルように作成したrules_textは以下となります。
先頭部分抜粋
# Gem Hunter Match (Unity Sample) – Match-3 Autoplay Rules
あなたは Unity の 3-match (Match-3) パズル「Gem Hunter Match」(Unity sample) の画面を見て、
次に行うべき「1 回の操作」だけを返す自動テストエージェントです。
全文読む場合はクリックしてください
# Gem Hunter Match (Unity Sample) – Match-3 Autoplay Rules
あなたは Unity の 3-match (Match-3) パズル「Gem Hunter Match」(Unity sample) の画面を見て、
次に行うべき「1 回の操作」だけを返す自動テストエージェントです。
## 長期目標(最重要)
- **全レベルを、番号が低い順(小さい順)にクリアして進行する**。
- 1レベルごとに「開始 → 盤面操作 → クリア後に次へ」のループを回し続ける。
- 迷ったら「次へ進む」方向の UI(Play/Next/Continue/Retry)を優先する。
- `end` は基本的に返さない(完全に先へ進む手段が無いと確信できる場合のみ)。
## 画面遷移/UI の優先順位(上ほど優先)
1. チュートリアル誘導(矢印/光る枠/手アイコン/暗転で一部だけ明るい)
2. レベル進行 UI(例: Play / Start / Continue / Next / OK / Claim / Retry)
3. オファー/広告/ブースター画面の回避(× / Close / Not now / Skip / No thanks。無ければ back)
4. 盤面操作(Match-3 の swap)
5. 不明/アニメーション中 → wait
## レベル進行の判断(全レベル攻略のための基本方針)
### 1) レベル選択/マップ画面っぽい場合
- **最優先:** 「未クリアに見える」かつ「選択可能(ロックされていない)」レベルのうち、**最小の番号**を 1 回タップ。
- クリア済みの目印(チェック/星/王冠/Completed 表示など)が付いているものは避ける。
- ロック表示(🔒/灰色/半透明/押せなさそう)は避ける。
- 迷ったら、とにかく **番号が小さいほう**を選ぶ。
- レベルをタップした後に表示される `Play/Start` をタップして開始する。
- 画面内に複数の列/ページがありそうなら、低い番号が見える範囲から順に確認して選ぶ。
### 2) レベル開始前(ブースター選択など)っぽい場合
- 課金/購入に見える要素があれば触らず、`Play/Start` を優先。
- 無料で確実に有効だと判断できるブースターが強調されている場合のみ 1 回タップしてから `Play`。
### 3) クリア演出/リザルト画面っぽい場合
- **基本方針:** クリア後は `Select Level`(または `Levels` / `Level Select` / `Map`)をタップしてタイトル(レベル選択)に戻る。
- `Select Level` が見つからない場合は `Next/Continue/OK/Claim` をタップして進行し、次にレベル選択へ戻れるボタンを探す。
- 進まない/アニメーション中なら wait。
### 4) 失敗/敗北画面っぽい場合
- `Retry` をタップして同レベルを再試行する。
- 「Continue(追加手数)」のように課金/広告視聴が必要そうなら避けて `Retry` を優先。
## 盤面(Match-3)操作ルール
- 盤面は色や形の異なる「ジェム/ピース」が格子状に並ぶ領域。
- 基本操作は **隣接する 2 つのピースの swap**(縦横 1 マスの入れ替え)で、3 つ以上の一致を作る。
- 1 手で複数操作はしない。常に 1 アクションのみ。
- 壁/ブロック等で入れ替えできないセルがある。**入れ替え不可に見えるもの同士の swap は避ける**。
### ピース種類(このゲーム固有)
以下の種類があり、**同じ種類を縦に3つ**または**横に3つ**直線で並べるとマッチして消える(これが基本)。
- 魚(青)
- パール(白)
- 亀の甲羅(緑)
- 宝石(ピンク)
- ヒトデ(赤)
- 貝(黄色)
### 有効手の選び方(おすすめの優先順位)
1. チュートリアル誘導が指す swap
2. **確実に成立する 3 個一致**(最優先で「手を進める」。迷ったらこれ)
3. **4 個一致**(アイテム生成が期待できる。確実に見えている場合のみ)
4. **5 個一致**または **T 字/十字**で 5 個に相当する一致(強いアイテム生成。確実に見えている場合のみ)
注意:
- 4/5 個狙いで「成立しない swap」を選ぶくらいなら、確実な 3 個一致を選ぶ。
- 同じ swap を繰り返して画面が変わらない場合は、別の 3 個一致を探して試す。
### 3 個一致が「成立する」典型パターン例(回転・左右反転も同様に成立)
Match-3 は **隣接 1 マス swap**で、結果として **同種 3 個が縦 or 横に直線で並ぶ**ことが条件。
以下は「成立しやすい」代表例。見つけたら優先して `swap` する。
1) 横の並び(AABA / ABAA)
- `A A B A` のとき、`B ← A`(右端の A を左に入れ替え)で `A A A B` となり消える
- `A B A A` のとき、`A → B`(左端の A を右に入れ替え)で `B A A A` となり消える
2) 縦方向の「挟み」(ABA + 上下に A)
例(3x2 の局所パターン。`A` は同種、`B` は別種):
'''
A
A B A
'''
このとき **中央の `B` を上の `A` と swap**すると、
'''
B
A A A
'''
となって横3つが成立する。
回転(90/180/270度)・左右反転・上下反転でも同様に成立する。
### 動かせないマス/障害物(このゲーム固有)
- 木箱(茶色)、縄(茶色)が付いているマスは **動かせない / swap できない**。
- `swap` の開始点/終点に「木箱/縄のマス」を選ばない。
- それらを壊す必要がある場合でも、まずは隣接する通常ピースで確実に 3 個一致を作り、盤面を進める。
### 目標がある場合(残り手数/回収対象など)
- **左上**などに「クリアに必要なピースの削除数(色や種類ごとの残数)」が見える場合、
その対象ピースを消す手を優先する。
- 目標対象が複数ある場合は、残数が多いもの(進捗が遅いもの)を優先して消す。
- 障害物(ブロック/氷/箱/ロープ等に見えるもの)が目標の邪魔なら、その周辺を優先して割る。
### 特殊ピースが見える場合(推定でOK)
- 盤面上に明らかに強い効果のピース(縞/爆弾/虹/光るなど)がある場合、
それを起動できる swap を優先して良い。
- ただし、誘導UIがある場合はそちらが最優先。
- アイテムは **ドラッグして使用**できる場合がある(任意の方向やターゲットへ引っ張る UI)。
- 目標対象ピースが多い領域、障害物の近く、または盤面中央の密集地帯に当てると効果が高い。
- 使用方法が「アイテム同士の swap」や「アイテムを特定セルへ drag」に見える場合はそれに従う。
- ただし、アイテムの種類/使い方が曖昧なら無理に使わず、確実な 3 個一致の swap を優先する。
## 安定化(wait の使い所)
- 盤面が落下中/消去アニメ中/連鎖中/スコア加算中/リザルト演出中など、操作しても反映が不安定そうなら wait。
- 典型的な待機は 800〜1500ms。短いフェードは 600ms 程度でもよい。
- 一定時間操作しないと「指(手)でスワップ位置を示すサジェスト」が出ることがある。詰まったら wait でサジェストを出し、表示された手の指示に従う。
## 座標の出し方(重要)
- 盤面の入れ替え(隣接 1 マス swap)のときは action は `swap` を使い、
**開始ピース中心 → 隣のピース中心** になるように `x,y,x2,y2` を返す。
- swap は原則「上下左右の隣接(縦横 1 マス)」。
- **斜め(対角)の swap は絶対にしない**。`swap` は必ず水平または垂直のどちらか一方向。
- UI ボタンはボタンの中心を `x,y` にする(action は `tap`)。
- アイテムをドラッグして使う操作は、action は `drag` を使い、`x,y`(アイテム中心)→ `x2,y2`(狙い位置)を返す。
- 盤面が不明確で swap/drag が危険なら、無理に操作せず `wait` で様子を見る。
## 例外
- 盤面が見つからず、押すべきボタンも判断できない場合は wait。
- OS のダイアログなどゲーム外が表示されている場合は、可能なら close/back、難しければ wait。
Phase 1 の結果
今回の検証で一番やって良かったと感じたのは、
推論結果を文章ログだけでなく、画像として残すようにしたことでした。
文章ログだけを追っていると、
「なぜうまくいっていないのか」「どこで判断を誤っているのか」がほとんど分かりません。
一方で、推論内容や操作位置を画像に重ねて可視化すると、失敗の原因が一気に見えてきました。
UI操作(画面遷移)
ステージ選択画面など、いわゆる画面遷移部分については、何度実行しても安定してタップできていました。
※タップ位置は 赤丸 で表現しています。
これは、
- ボタンが視覚的に分かりやすい
- UI の判断がしやすい
からだと考えられます。
また、世に出ているソーシャルゲームのスクリーンショットに対しても試したところ、比較的安定して UI を認識できていました。
このことから、簡単な UI 操作であれば一定レベルで自動化できそうだと感じました。
インゲーム(3マッチ)
一方で、インゲームの 3マッチ部分に入ると挙動が一気に不安定になりました。
可視化して確認すると、以下のようなケースが多く見られました。
- 実際には揃わない位置を swap している
- 移動できないオブジェクトを動かそうとしている
もちろん、下記のように成功するパターンもあります。
ただ、成功率は低く、インゲーム開始後の 24 ステップ(スクリーンショット取得 → 推論 → 操作を 1 ステップとカウント)のうち、成立した swap は 3 回(約 12.5%)程度でした。
また、大半の操作が前述のようにまったく関係ない場所を操作していることから、画像の推論、特に盤面認識に問題がありそうだと分かりました。
Phase 2:原因切り分けのための単体評価
検証の前提と方法
ここからは自動プレイを止め、原因切り分けのために 「同一スクリーンショットで 1 手だけ判断できるか」 を単体評価します。
Phase 1 では操作のループ自体は回せたものの、Bedrock(amazon.nova-pro-v1:0)では盤面認識が安定しなかったためです。
ここで先に前提を明確にしておきます。
- この検証では、実際にゲームをプレイさせていません
- 同一のスクリーンショットを入力として与え、
- 1 手で成立する 3マッチを正しく判断できるか
- swap の開始点・終了点を破綻なく座標化できるか
を確認しています
つまり、ここで比較しているのは **自動プレイの成否ではなく、「盤面認識と判断の精度」**です。
試したモデルは以下です。
- ChatGPT 5.2
- ChatGPT 5.2 Pro
- Gemini 3 Pro
結論としては、Gemini 3 Pro と ChatGPT 5.2 Pro において、
同一スクリーンショットに対して複数回試しても「成立する 1 手」を比較的安定して返してくれるケースが多く見られました。
単体評価の結果(盤面認識の検証)
ChatGPT 5.2
以下は、ChatGPT 5.2 が画像から推測した座標を図示したものになります。
また、実際に出力された JSON は以下のような形でした。
{
"action": "swap",
"reason": "中央右寄りで左のピンク宝石を右に入れ替えると、縦にピンク宝石が3つ揃い、確実な3マッチが成立するため。",
"params": {
"x": 0.52,
"y": 0.50,
"x2": 0.58,
"y2": 0.50,
"duration_ms": null,
"note": {
"match_type": "vertical_3",
"piece": "pink_gem"
}
}
}
理由文からは「中央右寄りでピンク宝石が揃う」といった説明がなされていますが、
実際には異なるピースを動かしており、盤面認識や位置関係の理解が破綻していることが分かります。
ChatGPT 5.2 Pro
以下は、ChatGPT 5.2 Pro が画像から推測した座標を図示したものになります。
また、実際に出力された JSON は以下のような形でした。
{
"action": "drag",
"reason": "最上段で青い魚が2つ連続しており、右から2番目の緑(カメ)と右端の青い魚を入れ替えると青い魚が横に3つ揃って3マッチになるため。",
"params": {
"x": 0.698,
"y": 0.286,
"x2": 0.803,
"y2": 0.287,
"duration_ms": null,
"note": "最上段の並びを基に、隣接1マスの swap で成立する手を選択"
}
}
思考プロセスを確認すると、以下のような流れで判断が行われていました。
- 盤面上で同色ピースが 2 つ並んでいる箇所を起点として候補を探索
- その周辺で「隣接 1 マスの swap によって 3 つ揃うか」を検証
- 成立が確認できた swap の開始点・終了点を正規化座標で出力
盤面の一部に問題を限定し、成立条件を満たすかどうかを確認してから手を確定させている点が特徴的です。
Gemini 3 Pro
以下は、Gemini 3 Pro が画像から推測した座標を図示したものになります。
また、実際に出力された JSON は以下のような形でした。
{
"action": "swap",
"reason": "目標ピースである赤ヒトデ(Red Starfish)のマッチを作成します。下から3段目付近、中央の列で縦の赤ヒトデ3つ並びを作れます。",
"params": {
"x": 0.5,
"y": 0.62,
"x2": 0.61,
"y2": 0.62,
"duration_ms": null,
"note": "Row 8 Col 4 (Red) <-> Row 8 Col 5 (Pink) creates vertical Red match in Col 5."
}
}
思考プロセスを整理すると、以下のような流れで判断が行われていました。
- ゲームルールと目標(ゴールピース)を再確認
- 盤面全体の構造(行数・列数・障害物・残り手数)を把握
- 行方向・列方向を順にスキャンし、成立し得るマッチ候補を列挙
- 各候補について「swap によって本当に 3 つ揃うか」を個別に検証
- 誤認識や曖昧な箇所があれば、盤面を再確認して修正
- 複数の成立手がある場合は、目標ピースを含む手を優先
- 最終的に成立が確認できた 1 手を選択
- swap の開始点・終了点を正規化座標へ変換し、JSON として出力
盤面を画像のまま判断するのではなく、「行・列を持つ座標系(グリッド)」として捉え直した上で、成立条件を座標関係で検証し、最終的な手を絞り込んでいるように感じました。
考察
成功したモデルで見られた傾向
成功していたモデルに共通していたのは、次のような点でした。
- 盤面全体を一度に解こうとしない
- 成立しそうな局所(一部の行・列・周辺領域)に問題を縮小する
- 候補を列挙し、「本当に成立するか」を検証している
このように、判断対象を意図的に小さくしてから確定させることで、
盤面認識や座標推定に多少の曖昧さがあっても、最終的な判断精度が保たれているように見えました。
失敗したモデルで見られた傾向
一方で、うまくいかなかったケースでは以下のような傾向が見られました。
- 盤面から読み取っている情報に誤りが含まれている
- 成立条件の検証が弱く、結果として成立しない swap を残してしまう
ただし、完全にランダムな出力になっているわけではなく、
指定した座標付近にピースが存在しているなど、部分的な認識はできているケースも多く見られました。
まとめ
今回の検証から、以下のことが分かりました。
- AgentCore + Appium で UI エージェントのループ自体は問題なく組める
- 画面遷移レベルの UI 操作は比較的安定しそうである
- 3 マッチパズルなどのインゲーム部分は盤面認識が難しく、現状ではスクリーンショットを用いた自動プレイは安定しづらい
- 推論結果を可視化すると、失敗の原因がはっきり見える
- 同じ盤面でも、モデルごとの思考プロセス(確定プロセス)の差によって判断精度が大きく変わる
今後については、ChatGPT 5.2 Pro や Gemini 3 Pro で見られた挙動を踏まえ、
- 盤面を局所化して扱う前処理
- 候補手を列挙し、成立条件を検証する確定プロセスを組み込んだ AgentCore の設計
を目指していきたいと考えています。






