# AI スキーム

> 1 つのスキームは 1 つの完全な AI です。Farsight でワンクリックで切り替えられ、対戦中のゲームでもすぐに別の AI が引き継げます。zip でエクスポートして共有し、他の人のスキームをインポートしてテストでき、スキームごとの戦績は自動で集計されます。

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

1 つの**スキーム** = 1 つの完全な AI：フォルダ 1 つ + マニフェスト `scheme.json` + コード。ゲームインスタンスごとにスキームを 1 つ選びます。Farsight でワンクリックで切り替えられ、**対戦中のゲームでもすぐに別の AI が引き継げます**。

他の人が共有したスキームをインポートすると**別枠**に入り、あなた自身のスキームとは互いに影響しません。変更したいときは「マイにコピー」します。

```text
schemes/
  mine/<id>/          マイスキーム：自分で書いたもの、または他のスキームからコピーして改造したもの（自由に変更でき、次のゲームから反映）
  installed/<id>/     インストール済み：他の人が共有した zip をここに展開（初回実行前に信頼の確認が必要）
brains/xwar3/         組み込み：リファレンスブレイン（完全な AI）
brains/examples/      組み込み：4 つの学習用サンプル hello / rush / macro / micro、コンパニオンのサンプル buddy、2 つのゲームプレイ MOD（ヒーローローグライク、エンドレスディフェンス）
```

スキームは、あなたの代わりに戦う AI とは限りません。`kind: mod` のスキームは**ゲームのルール一式**で、あなた自身がプレイし、スキームがお題を出します。[ゲームプレイ MOD](https://war3ai.com/ja/docs/mods/) を参照してください。

## Farsight で使う

「AI スキーム」ページ（左サイドバーの「システム → AI スキーム」）：

| 操作 | 内容 |
|---|---|
| スキームをインポート（zip） | `installed/` にインストールします。同じ id がすでにインストール済みなら、置き換えるかどうかを確認します（置き換えたら信頼の確認をやり直す必要があります） |
| インスタンスに適用… | インスタンスを選び、「すぐに反映」（現在の AI を停止し、新しいスキームがこのゲームを引き継ぐ）または「次のテスト開始から反映」を選びます |
| マイにコピー | `mine/` にコピーします。作者は「自分」、バージョンは 0.1.0 として記録し、どのスキームのどのバージョンからコピーしたかも記録します |
| zip をエクスポート | `<id>-<バージョン>.zip` にまとめます。これを人に送れば共有になります |
| フォルダを開く | エクスプローラーでスキームのディレクトリを開き、コードを直接編集します |
| 信頼 | 他の人のスキームは、初回実行前に必ずクリックする必要があります（後述の「信頼とセキュリティ」を参照） |
| 最近の戦績 | このスキームの各ゲームの勝敗、時間、終了理由 |
| 削除 | 削除できるのは「マイ」と「インストール済み」だけです。インスタンスが使用中のものは削除できません |

インスタンスカードにも「AI スキーム」の行が加わりました：ドロップダウンでスキームを選ぶ →「切り替え（すぐに反映）」。インスタンスが実行されていないときはボタンが「選択」になり、次に「テスト開始」したときにそのスキームで AI を起動します。

## マニフェスト scheme.json

```json
{
  "format": 1,
  "id": "fast-rush",
  "name": "3 分ラッシュ",
  "version": "1.2.0",
  "author": "山田",
  "description": "この AI がどんな戦い方をするかを一言で",
  "entry": "rush_bot.py",
  "class": "RushBot",
  "fair": true,
  "hz": 5,
  "races": ["human", "orc"],
  "license": "MIT"
}
```

| フィールド | 必須 | 説明 |
|---|---|---|
| `id` | ✔ | 小文字の英字、数字、`-`、`_`、2 〜 41 文字 |
| `entry` | ✔ | スキームディレクトリ内の `.py` ファイル 1 つ（絶対パスと `..` は不可） |
| `kind` | | デフォルトは `bot`（`openwar3.Bot` のサブクラスで、あなたの代わりに戦う）。`mod` = [ゲームプレイ MOD](https://war3ai.com/ja/docs/mods/)（`openwar3.Mod` のサブクラス。常にフェアモードを使わず、対戦ルールでの勝敗判定もしない） |
| `class` | | エントリファイル内の Bot（または Mod）サブクラス名。省略すると、エントリファイル内の最後の `openwar3.Bot` サブクラスを使います |
| `fair` | | デフォルトは `true`：視界内のものしか見えず、アリーナと同じルールです。`false` = マップ全体が見え、[JASS チャネル](https://war3ai.com/ja/docs/jass/) も使えるようになります（コンパニオンに必要） |
| `judge` | | デフォルトは `true`：対戦ルールで勝敗を判定します。RPG / コンパニオンのスキームでは `false` にします |
| `hz` | | `on_tick` を 1 秒に何回呼ぶか。デフォルトは 5 |
| `format` | | マニフェストの形式バージョン。現在は 1。ローカルの OpenWar3 より新しいものは拒否され、更新を促されます |
| その他 | | `name`、`version`、`author`、`description`、`races`、`license`、`homepage`、`forked_from` は表示専用 |

スキームのディレクトリは Python のモジュール検索パスに追加されるので、エントリファイルから同じディレクトリにある他のファイルを `import` できます。サードパーティのパッケージ（numpy、torch……）は自動ではインストールされません —— 必要なものは `description` に明記してください。

**最小のスキームは、ファイル 2 つで十分です**：

```python
# my_bot.py
from openwar3 import Bot

class MyBot(Bot):
    def on_tick(self, g):
        for w in g.idle_workers():
            mine = g.nearest(g.gold_mines(), w)
            if mine:
                g.gather(w, mine)
```

```json
{"id": "my-first", "name": "はじめての AI", "entry": "my_bot.py"}
```

`schemes/mine/my-first/` に置き、Farsight を再読み込みすれば表示されます。もっと手軽な出発点：「組み込み」からサンプルを 1 つ選び、「マイにコピー」をクリックします。

## 実行方法と戦績

スキームは**スキームランナー**が実行します（Farsight の「テスト開始 / 切り替え」で起動されるのがこれです）。

```bash
python tools/run_scheme.py --inst 20 --scheme builtin/micro --hours 6
```

- インスタンスごとに常駐の監視プロセスが 1 つあり、**ゲームごとに子プロセスを 1 つ起動して**スキームを実行します。スキームのコードがクラッシュしても、監視プロセスは巻き込まれません。「マイスキーム」のコードを変更すると、次のゲームから自動で新しいコードが使われます。
- ゲームが終わるたびに戦績を 1 行記録します：スキーム、バージョン、作者、勝敗、理由、ゲーム時間、エラー回数。Farsight の勝率はここから集計されます。

勝敗の判定方法：

| 状況 | 記録 |
|---|---|
| 相手の建物が全滅 | 勝ち |
| 自軍の建物が全滅（兵が生き残っていても同じ —— 対戦ではこれで負けと判定されます） | 負け |
| 自軍のユニットが全滅 | 負け |
| Farsight で手動で終了 / 停止 | 未定 |
| 切り替えた時点で、そのゲームがすでに 60 ゲーム秒以上経過していた（途中からの引き継ぎ） | 別途カウントし、**勝率には含めない** |
| ゲーム時計が長時間進まない | 未定 |

勝敗がつくと、ランナーはリザルト画面を閉じ、「次のゲームの設定」に従って次のゲームを開始し、スキームが引き続き引き継ぎます —— 一晩中放置して戦績を貯めることができます。一時停止は終了とはみなしません。一時停止中も Bot は通常どおり動き、止まるのはゲーム時計だけです。

## 信頼とセキュリティ

**スキームはコードであり、実行時にはあなた本人と同じ権限を持ちます**（ファイルの読み書きもネットワーク接続もできます）。そのため：

- `installed/` のスキームはデフォルトで**信頼されておらず**、あなたが「信頼」をクリックするまで、Farsight もランナーも実行を拒否します。
- 同じ id のスキームを置き換えてインストールすると、**信頼がリセットされます**（新しいバージョン = 新しいコード）。
- インポート時のチェック：zip は 50 MB 以下、ファイル数は 2000 以下。絶対パスと `..` は不可（スキームのディレクトリの外に書き込まれるのを防ぐため）。マニフェストが不正、またはエントリファイルが存在しない場合はその場で拒否します。

> **注意**
>
> 信頼する前に、「フォルダを開く」でコードに一通り目を通してください。スキームは信頼できる人からだけ受け取ってください。

## API（スクリプト向け）

| API | 説明 |
|---|---|
| `GET /api/schemes` | スキーム一覧 + 戦績 + 各インスタンスで選択中・実行中のスキーム |
| `GET /api/schemes/results?ref=` | 1 つのスキームの直近 30 ゲーム |
| `POST /api/schemes/import` | zip をインポート |
| `GET /api/schemes/export?ref=` | zip をダウンロード |
| `POST /api/schemes/fork` | マイにコピー |
| `POST /api/schemes/trust` | 信頼 |
| `DELETE /api/schemes?ref=` | 削除（インスタンスが使用中なら拒否） |
| `POST /api/instances/{n}/scheme` | インスタンスのスキームを変更：このゲームをすぐに引き継ぐか、次のテスト開始から反映 |

Python ではライブラリを直接使えます：`from openwar3 import schemes`（`list_schemes`、`install_zip`、`export_zip`、`fork`、`trust`、`stats`……）。

## 今後：スキームサイト

エクスポートした zip がそのまま共有の単位なので、サイトは外側に 1 層加えるだけで済みます。Farsight からワンクリックでアップロードし、サイトからダウンロードしたものは「スキームをインポート」とまったく同じチェックを通り、同じく信頼の確認が必要です。戦績の報告を選ぶこともでき、サイトはバージョンごとに勝率を集計します。Farsight には「スキームサイトで共有」ボタンの場所がすでに用意されています。進捗は [ロードマップ](https://war3ai.com/ja/roadmap/) を参照してください。
