# デバッグとパフォーマンス

> ティックが遅い、コマンドが効かない、ゲームが動かない。現象から原因を絞り込み、付属の実機検証スクリプトで確認します。

出典: https://war3ai.com/ja/docs/debugging/

## レシートを見る

各コマンドのレシートが一次情報です。

```python
r = g.cast(hero, "blizzard", x=tx, y=ty)
if not r:
    print(r.reason, r.verdict)     # rejected（…）と理由コード
print(r.exec_us, r.engine_us)      # このコマンドがゲームスレッドで実行された時間（µs）/ そのうちエンジンの命令関数自体にかかった時間
```

通常、1 つのコマンドがゲームスレッドで使う時間は数マイクロ秒から数百マイクロ秒です。バッチブロックの終了後、`g.last_receipts` にそのバッチの各コマンドのレシートが入っています。

## ゲーム内で見る

```python
g.say(unit, "撤退")          # ユニットの頭上にチャット吹き出しを表示（ゲームには影響しない）
g.message("クリーピング開始")    # 左下のメッセージ欄に 1 行表示（ローカルでのみ見える）
```

`print` の内容は Bot を実行しているターミナルに表示されます。ティックごとの主要な判断を出力し、頭上の吹き出しと組み合わせると、コードを読むよりずっと早く状況を把握できます。

## ティックが遅い

まず次のケースに当てはまらないか確認してください。

| 原因 | 対処 |
|---|---|
| コマンドを 1 件ずつ送り、毎回 1 フレーム待っている | `with g.batch():` で包めば、数十件でも待つのは 1 回だけ |
| `g.visible()` / `g.can_do()` を 1 件ずつ呼んでいる（毎回ファストレーン経由で 1 フレーム待つ） | 可視性はスナップショットの `u.visible_to()` を使い、実行可否は `g.can_do_many([...])` でまとめて問い合わせる |
| `on_tick` の中で `sleep` や待機をしている | ゲーム時間を記録し、次のティックで判定する |
| 重い処理（経路探索、全マップ走査）を毎ティック再計算している | 結果をキャッシュし、数ティックおきに再計算する。`g.grid()` には 2 秒のキャッシュがあり、`g.stats()` のテクノロジーレベルは 5 秒ごとにキャッシュされる |

## ゲームが動かない / Bot がゲーム開始を待ち続ける

| 現象 | 主な原因 |
|---|---|
| ずっと「ゲーム開始待ち」のまま | インスタンス番号が違う。またはゲームウィンドウが**最小化**されている。最小化中はゲームのシミュレーションが止まっている（時計が進まない） |
| ゲームは動いているのに、Bot の命令に反応がない | 他人のユニットに命令している（レシートが `not_owner`）。または Bot が observer として接続している（`forbidden`） |
| コマンドが `held` になる | このユニットがより優先度の高い層（リファレンスブレインのリフレックス層、コンソールからの手動命令）に確保されていて、送信されなかった |
| 一時停止中もコマンドを出せる | 正常です。一時停止中はエンジンの時計が止まりますが、イベントディスパッチは動き続け、コマンドも通常どおり実行されます |

## 接続して状態を見る

```bash
python -m openwar3 status --inst 5
```

接続状態を出力します。ゲームの pid、ワールドの発行周期と 1 回の収集時間、ファストレーンのカウンター、ゲーム中かどうか、ユニット数、ゲーム時計。

## 実機検証スクリプト

テストインスタンスを 1 つ起動し、SDK の各機能があなたのマシンで正常に動くか 1 項目ずつ確認します。

```bash
python tools/sdk_live_check.py --inst 20                 # すべて
python tools/sdk_live_check.py --inst 20 --only prod     # 1 セクションだけ確認
```

セクション：バッチ、時間、生産、キュー付き命令、戦闘ステータス、経路探索、フェアモード。各セクションは実際の対戦でコマンドを出して効果を読み戻し、合格数を出力します。

オフラインテストはゲームを起動しなくても実行できます。

```bash
python tools/run_tests.py
```

## 「バグに見える」よくあるケース

- **建設のレシートは受理されたのに、いつまでも建設が始まらない**：森の中の地点でもエンジンはその場で受理し、ワーカーが到着してから失敗します。`build_near` を使えば、建設を追跡し、失敗した地点をしばらくブラックリストに入れてくれます。
- **スキルのレシートは受理されたのに、発動しない**：中断されたか、マナ不足です。使用後の次のティックで `g.cooldown()` がクールダウンに入ったか確認してください。
- **攻撃命令は受理されたのに、兵が別の相手を攻撃する**：特定の目標を攻撃するには `g.attack(兵, 敵)`（右クリックのセマンティクス）を使います。生の攻撃オーダーは目標に対してオーダーを切り替えるだけで目標を記録しないため、近くの別の相手を攻撃しに行きます。
- **ワーカーの数が合わない**：金鉱に入ったワーカーはスナップショットにいません。
- **死んだヒーローを訓練できない**：ヒーローは唯一なので `g.revive(祭壇)` が必要です。蘇生には人口が必要で、死亡後約 3 ゲーム秒経たないと蘇生できません。
