Game Verification and Fix Skill
ゲームを実際にプレイしてクリアできるか検証し、問題があれば修正するスキルです。
目的
play-gameスキルを使うエージェントが詰まらずにクリアできることを保証する。
play-game との違い
| 観点 | play-game | verify-game |
|---|
| ソースコード | 読み取り禁止(READMEのみ) | 読み取り・修正可能 |
| 目的 | エンタメとしてプレイ | 詰まらないことを保証 |
| 詰まった時 | 諦める or 適当に操作 | 原因特定 → 修正 → 再プレイ |
| 出力 | 実況付きプレイ | 検証レポート + 修正 |
検証フロー
Phase 1: 事前準備
bash
1# 1. ソースコードを読んでゲーム構造を把握
2cat games/<game-name>/script.js
3cat games/<game-name>/README.md
4
5# 2. HTTPサーバー起動(既存プロセスがなければ)
6lsof -i:8888 || (cd /Users/user/WorkSpace/ai-agent-game-streamer/games && python3 -m http.server 8888 &)
7
8# 3. ゲームを開く(--headed必須)
9agent-browser --headed open http://127.0.0.1:8888/<game-name>/index.html
10
11# 4. 初期状態をスクリーンショット
12mkdir -p logs
13agent-browser screenshot "logs/$(date +%Y%m%d-%H%M%S)_initial.png"
Phase 1.5: 初期状態の整合性チェック(重要)
プレイを開始する前に、ゲームデータの整合性を確認する。
倉庫番(sokoban)の場合
bash
1# 箱とゴールの数が一致しているか確認
2agent-browser eval "
3const boxes = game.getBoxPositions();
4const goals = game.goals;
5JSON.stringify({boxCount: boxes.length, goalCount: goals.length, match: boxes.length === goals.length})
6"
チェック項目:
boxCount === goalCount であること(不一致ならクリア不可能)
- 各ステージで確認すること
ボードゲーム(othello, gomoku)の場合
bash
1# 初期状態で有効な手があるか確認
2agent-browser eval "JSON.stringify(game.getValidMoves(game.currentPlayer))"
チェック項目:
- 初期状態で有効な手が存在すること
- ゲームオーバーでないこと
整合性エラーが見つかった場合は、Phase 4 でデータバグ(タイプD)として修正する。
Phase 2: 実際にプレイしてクリアを目指す(1手ずつ検証)
play-gameスキルと同じ方法でゲームをプレイする。
ただし、ソースコードを読めるので、APIの正確な挙動を把握した上でプレイできる。
重要: 1手ずつ期待値と実測値を比較する
検証では「意図通りに動いているか」を確認することが目的。
単にクリアを目指すのではなく、各操作の結果が期待通りかを検証する。
bash
1# 悪い例: ただ移動するだけ
2agent-browser eval "game.move('up')"
3agent-browser eval "game.move('up')"
4
5# 良い例: 期待値と実測値を比較しながら移動
6agent-browser eval "
7const before = {...game.playerPos};
8const result = game.move('up');
9const after = {...game.playerPos};
10JSON.stringify({
11 before,
12 expected: {row: before.row - 1, col: before.col},
13 after,
14 result,
15 match: after.row === before.row - 1 && after.col === before.col
16})
17"
検証すべき項目:
| 操作 | 期待値 | 実測値 | 一致するか |
|---|
| 移動前の位置 | - | before | - |
| 移動後の位置 | expected | after | match |
| 戻り値 | true or false | result | 期待通りか |
ボードゲーム(othello, gomoku)
bash
1# 有効な手を確認
2agent-browser eval "JSON.stringify(game.getValidMoves(game.currentPlayer))"
3
4# 手を打つ(期待値と実測値を比較)
5agent-browser eval "
6const beforePlayer = game.currentPlayer;
7const result = game.handleCellClick(row, col);
8const afterPlayer = game.currentPlayer;
9JSON.stringify({beforePlayer, afterPlayer, result, turnChanged: beforePlayer !== afterPlayer})
10"
11sleep 0.5
12
13# ゲーム終了まで繰り返す
14agent-browser eval "game.gameOver"
パズルゲーム(sokoban)
bash
1# 現在位置と箱の位置を確認
2agent-browser eval "JSON.stringify({playerPos: game.playerPos, boxes: game.getBoxPositions()})"
3
4# 移動(期待値と実測値を比較)
5agent-browser eval "
6const beforePlayer = {...game.playerPos};
7const beforeBoxes = game.getBoxPositions();
8const result = game.move('right');
9const afterPlayer = {...game.playerPos};
10const afterBoxes = game.getBoxPositions();
11JSON.stringify({
12 player: {before: beforePlayer, after: afterPlayer, moved: result},
13 boxMoved: JSON.stringify(beforeBoxes) !== JSON.stringify(afterBoxes)
14})
15"
16sleep 0.5
17
18# クリアまで繰り返す
19agent-browser eval "game.checkClear()"
カードゲーム(card-battle)
bash
1# ゲーム状態を確認
2agent-browser eval "JSON.stringify(game.getGameState())"
3
4# カードをプレイ(期待値と実測値を比較)
5agent-browser eval "
6const before = game.getGameState();
7game.playCard(0);
8const after = game.getGameState();
9JSON.stringify({before, after})
10"
Phase 3: 詰まったら原因を特定
「詰まった」の定義:
- 有効な手がないのにゲーム終了していない
- 操作しても状態が変わらない
- APIが期待と異なる値を返す
- エラーが発生する
原因特定の手順:
-
症状を確認
bash
1# 現在の状態をダンプ
2agent-browser eval "JSON.stringify(game)"
3agent-browser screenshot "logs/$(date +%Y%m%d-%H%M%S)_stuck.png"
-
ソースコードで原因を調査
bash
1# 該当メソッドの実装を確認
2grep -A 30 "getValidMoves" games/<game-name>/script.js
-
問題を分類
| タイプ | 症状 | 修正対象 |
|---|
| A: READMEの曖昧さ | コードは正しいがドキュメントが不明確で誤操作した | README.md |
| B: コードのバグ | APIが期待通りに動作しない | script.js |
| C: API不足 | 必要な情報を取得するAPIがない | script.js + README.md |
| D: データバグ | ステージデータ自体が間違っている(箱とゴールの数不一致等) | script.js(STAGESデータ) |
Phase 4: 修正を適用
タイプA: READMEの曖昧さ
例: getValidMoves(player) の player が 1=黒, 2=白 だと分からなかった
markdown
1# 修正前
2| `game.getValidMoves(player)` | 有効な手の一覧を取得 |
3
4# 修正後
5| `game.getValidMoves(player)` | 有効な手の一覧を取得(player: 1=黒, 2=白)。戻り値: `[{ row: number, col: number }, ...]` |
タイプB: コードのバグ
例: handleCellClick がプレイヤーのターンでも動作しない
javascript
1// 修正前
2handleCellClick(row, col) {
3 if (this.gameOver || this.currentPlayer !== BLACK) return;
4 // BLACK=1 だが、初期化で currentPlayer が設定されていない
5}
6
7// 修正後
8handleCellClick(row, col) {
9 if (this.gameOver || this.currentPlayer !== BLACK) return;
10 // init() で this.currentPlayer = BLACK を確実に設定
11}
タイプC: API不足
例: 現在のステージ番号を取得するAPIがない
javascript
1// script.js に追加
2get currentStageNumber() {
3 return this.currentStage;
4}
markdown
1// README.md に追加
2| `game.currentStageNumber` | 現在のステージ番号(0-9) |
タイプD: データバグ
例: 倉庫番のステージ2で箱6個、ゴール5個だった(クリア不可能)
javascript
1// 修正前(箱が1つ多い)
2// ステージ 2
3[
4 "########",
5 "# #",
6 "# .**$ #",
7 "# . $ #",
8 "# . $$ #", // ← $$ で箱が2つ
9 "# @ #",
10 "########"
11],
12
13// 修正後(箱を1つ削除)
14// ステージ 2
15[
16 "########",
17 "# #",
18 "# .**$ #",
19 "# . $ #",
20 "# . $ #", // ← $ 1つに修正
21 "# @ #",
22 "########"
23],
データバグの発見方法:
- Phase 1.5 の整合性チェックで検出
- または、プレイ中に「全部正しく動かしてもクリアできない」場合に疑う
Phase 5: 再プレイで検証
bash
1# ページリロードして修正を反映
2agent-browser reload
3
4# 再度プレイしてクリアを目指す
5# Phase 2 に戻る
クリアできたら Phase 6 へ進む。
Phase 6: 検証後チェック(必須)
クリア成功後、以下のチェックを必ず実施する。
6-1. READMEの完全性チェック
play-gameスキルはREADMEのみを参照するため、以下がすべて記載されているか確認:
| チェック項目 | 確認内容 |
|---|
| 操作API | move(), handleCellClick() 等の操作メソッドが記載されているか |
| 状態取得API | ゲーム状態を取得するプロパティ(playerPos, board, currentPlayer 等)が記載されているか |
| 戻り値の説明 | メソッドの戻り値の型と意味が明記されているか(true/false の意味など) |
| 定数の説明 | セルタイプやプレイヤー番号などの定数値が説明されているか |
| クリア条件 | クリア判定APIとその使い方が記載されているか |
不足があれば README.md を修正する。
6-2. ゲームロジックのレビュー
検証中に使用したAPIやゲームデータに問題がないか確認:
| チェック項目 | 確認内容 |
|---|
| クリア可能性 | すべてのステージ/初期状態がクリア可能か(詰み状態がないか) |
| API一貫性 | READMEに記載されたAPIが実際のコードと一致しているか |
| エッジケース | 境界条件(盤面端、最終ステージ等)で正常動作するか |
問題があれば script.js を修正し、Phase 5 に戻って再検証する。
6-3. チェックリスト
markdown
1## 検証後チェックリスト
2
3- [ ] データ: 箱とゴールの数が一致している(倉庫番)
4- [ ] データ: 初期状態で有効な手がある(ボードゲーム)
5- [ ] README: 操作APIが記載されている
6- [ ] README: 状態取得プロパティが記載されている
7- [ ] README: 戻り値の型と意味が明記されている
8- [ ] README: 定数値(セルタイプ等)が説明されている
9- [ ] ゲーム: すべてのステージがクリア可能
10- [ ] ゲーム: APIがREADMEの説明通りに動作する
11- [ ] ゲーム: 1手ずつの操作が期待通りに動作する
すべてチェックが完了したら検証完了。
ゲーム別の「クリア」条件
| ゲーム | クリア条件 | 確認方法 |
|---|
| othello | ゲーム終了(両者パス or 盤面埋まる) | game.gameOver === true |
| gomoku | 5つ並ぶ or 盤面埋まる | game.winner !== null |
| sokoban | 全箱がゴール上 | game.checkClear() === true |
| card-battle | 3勝する or 相手が3勝 | game.getGameState().gameOver === true |
出力フォーマット
検証完了後、以下の形式でレポートを出力:
markdown
1# ゲーム検証レポート: <game-name>
2
3## 検証日時
4YYYY-MM-DD HH:MM
5
6## 結果
7クリア成功 / クリア失敗(修正後成功)
8
9## プレイログ
101. [操作] → [結果]
112. [操作] → [結果]
12...
13
14## 発見した問題(あれば)
15
16### 問題1: [タイプA/B/C] 問題の概要
17- **症状**: 何が起きたか
18- **原因**: なぜ起きたか
19- **修正内容**: 何を修正したか
20- **修正ファイル**: どのファイルを変更したか
21
22## 修正したファイル一覧
23- games/<game-name>/README.md
24- games/<game-name>/script.js
25
26## play-gameスキルへの影響
27影響なし / [影響内容を記載]
28
29## 検証後チェックリスト
30- [x] データ: 箱とゴールの数が一致している(倉庫番)
31- [x] データ: 初期状態で有効な手がある(ボードゲーム)
32- [x] README: 操作APIが記載されている
33- [x] README: 状態取得プロパティが記載されている
34- [x] README: 戻り値の型と意味が明記されている
35- [x] README: 定数値(セルタイプ等)が説明されている
36- [x] ゲーム: すべてのステージがクリア可能
37- [x] ゲーム: APIがREADMEの説明通りに動作する
38- [x] ゲーム: 1手ずつの操作が期待通りに動作する
注意事項
- --headed 必須: ブラウザは必ず
--headed オプションで起動
- 0.5秒以上の間隔: 操作は間隔を空けて実行(状態反映のため)
- 破壊的変更に注意: APIシグネチャを変更する場合、play-gameスキルへの影響を考慮
- 大きな修正前は git commit: 変更を追跡できるように
- スクリーンショットを残す:
logs/ にスクリーンショットを保存
使用例
bash
1# オセロを検証(クリアできるまでプレイ、問題あれば修正)
2/verify-game othello
3
4# 倉庫番ステージ1を検証
5/verify-game sokoban
6
7# 五目並べを検証
8/verify-game gomoku
検証後、/play-game <game> で修正が有効か確認することを推奨。