# レシートと理由コード

> 各コマンドのレシートにはステータスコードと理由コードが含まれます。これは Bot と Agent が自己修正するための根拠で、「なぜうまくいかなかったか」を機械可読な数値に変えます。

出典: https://war3ai.com/ja/docs/reason-codes/

```python
r = g.train(barracks, "hfoo")
bool(r)        # False
r.status       # 1              -> rejected
r.verdict      # 3              -> 人口不足
r.reason       # 'rejected（人口不够）'
r.exec_us      # このコマンドがゲームスレッドで実行された時間（マイクロ秒）
```

`if r:` は `r.status == 0`（エンジンが受理した）と同じ意味です。

## ステータスコード `status`

| コード | 名前 | 意味 | よくある原因 |
|---|---|---|---|
| 0 | `accepted` | エンジンが受理した | —（ただし受理 ≠ 成功。後述） |
| 1 | `rejected` | エンジンに拒否された | `verdict` を確認 |
| 2 | `bad_unit` | ユニットが存在しない、またはハンドルが一致しない | ユニットがすでに死んでいる。古いユニットオブジェクトを使った |
| 3 | `not_owner` | 自分のユニットではない | `player` として他人のユニットに命令した |
| 4 | `fault` | 実行時の例外（ランタイムが捕捉済みで、ゲームは落ちない） | 再現手順を添えて報告してください |
| 5 | `bad_args` | 引数エラー | 座標、グリッド番号、4 文字コードの誤り |
| 6 | `unsupported` | 未対応 | このバージョンのランタイムにはこの機能がない |
| 7 | `bad_target` | 無効な目標 | 目標がすでに消えている。目標の種類が違う |
| 8 | `forbidden` | レーンのロールで許可されていない | `observer` として命令した |
| 97 | `cancelled` | バッチブロック内で例外が発生し、バッチ全体が送信されなかった | `with g.batch():` ブロック内のコードでエラー |
| 98 | `held` | ユニットがより優先度の高い層に確保されていて、送信されなかった | リファレンスブレインのリフレックス層や、コンソールからの手動命令がこのユニットを確保している |
| 99 | `timeout` | タイムアウト | ゲームの一時停止やカクつきで期限を過ぎた（期限切れのコマンドは実行されない） |

## 理由コード `verdict`

拒否されたとき、ランタイムはエンジン自身の実行可否チェックを使って理由を示します。命令を出さずに先に問い合わせることもできます。`g.can_do(ユニット, 4文字コード)` は同じコードを返します。

| コード | 意味 | 対処 |
|---|---|---|
| 0 / 220 | 可能 | — |
| 3 | 人口不足 | 人口建物を建てる。`g.production(b).blocked` で早めに検出 |
| 8 | ゴールド不足 | 資金を待つ。命令前に `g.can_afford(code)` |
| 9 | 木材不足 | 伐採の人数を増やす |
| 32 | 訓練キューが満杯（7 枠） | キューは 1 体だけ：`g.queue(b)` が空になってから追加 |
| 183 | 前提テクノロジー / 建物が不足 | 先に前提の建物を建てる、ティアアップする |
| 185 | 建物が使用中 | 祭壇がヒーローを蘇生中。タウンホールのキューが空でないとアップグレードできない |
| 221 | 該当項目なし / 建設中 / アップグレード中 / すでに存在 | ヒーローがすでにいる（死んだら `revive`）。このショップでは売っていない |
| 89 | ショップに未入荷 | 開始時はアイテム表の入荷時間になるまで在庫がない。新しく建てたショップは完成した時点からカウントが始まる |
| 1001 | 目標が見えない | 目標が戦場の霧かブラックマスクの中にいる。その位置に `attack_move` |

## 受理 ≠ 成功

レシートが示すのは「エンジンがこのコマンドを受け取った」ことだけで、同じフレーム内で読み戻したものです。その後に起こることは関知しません。

| コマンド | レシートで受理されても失敗しうるケース | 確認方法 |
|---|---|---|
| 建設 | 森の中の地点でもその場では受理され、ワーカーが到着してから失敗する | `build_near` を使う（建設が始まったかを追跡する）か、`production.done` を待つ |
| スペル使用 | 中断された、マナ不足 | 次のティックで `g.cooldown(u, スキル)` がクールダウンに入ったか確認 |
| 訓練 | キューには入ったが、人口不足でいつまでも始まらない | `g.production(b).blocked` |
| 移動 / 攻撃 | 別のロジック（またはより優先度の高い層）に上書きされた | `g.current_target(u)`、`g.order_of(u)` |

## クエリ API

以下の API は命令を出さず、エンジンに問い合わせるだけです。結果もレシートの `value` に入ります（SDK は値を直接返します）。

| API | 戻り値 |
|---|---|
| `g.can_do(u, code)` / `g.can_do_many([(u, code), ...])` | 上表の理由コード |
| `g.tech(code, player=None)` / `g.tech_many([...])` | 研究レベル / 完成した建物数（アップグレード系列を含む） |
| `g.visible(x, y)` | この地点が自軍から見えているか |
| `g.gold_left(mine)` | 金鉱の残りゴールド |
| `g.enemy_ai_plan(敵ユニット)` | コンピューター対戦相手の隊長が兵をどこへ向かわせるか（コンピューター AI にのみ有効） |
