AI を作ってみる
自作のポケモンカード AI (bot) を持ち込んで、このアリーナで対戦させられます。リファレンス実装 + 接続クライアントが公開されています。clone して connect を動かせば、今すぐ自分の bot をアリーナに投入できます。
⧉ GitHub で見る: PTCG_AI_Battle_Client
これは何?
- サーバとの通信は純粋な JSON プロトコル (src/wire/) で、ルールエンジン本体には依存しません。軽量で特別なビルド依存もありません。
- カードの事実 (ex 判定・ワザ index) は pokemon-card-data (submodule) から読みます。
- 同梱 bot のロジックが、そのまま「ポケカ bot の書き方」の実例になっています。
クイックスタート
Rust 1.80+ が必要。submodule (カードデータ) ごと clone してビルド:
git clone --recurse-submodules https://github.com/1ulce/PTCG_AI_Battle_Client.git
cd PTCG_AI_Battle_Client
cargo build --release
一番簡単な例 — アリーナ内蔵 bot に挑戦する:
cargo run --release --bin connect -- \
--server wss://arena.ptcgtools.com \
--vs dragapult-yopifutto --bot dragapult-takeuchi \
--deck decks/dragapult-ex.yaml --games 3
同梱 bot
| 名前 | 説明 |
|---|---|
random | 合法手・選択肢から一様ランダムに選ぶ。基準・フォールバック |
dragapult-takeuchi | ドラパルト ex デッキの固定戦略 — 「口悪竹内」ペルソナ |
dragapult-yopifutto | ドラパルト ex デッキの固定戦略 — 「よぴふっと博士」ペルソナ |
対戦相手の見つけ方 (intent)
| オプション | 意味 |
|---|---|
--room | --room ID: 同じ room の 2 人を確実にペア (自作 bot 同士に最適) |
--vs | --vs NAME: サーバ内蔵 bot を相手に指定 |
--participant-id | --participant-id ID --auth-token TOK: ラダー (レート対戦。「参加申請」で token 発行)。持参デッキ (--deck) で参加できます |
相手無指定の自動マッチング (open) は廃止しました。room / vs / ladder のいずれかを指定してください。各接続が --deck を持参するので、左右で別デッキの非対称対戦もできます。
時間制御 (時間内に応答すること)
アリーナは「切れ負け: 1 人 10 分 + 1 手 30 秒上限」です。1 手 = request→response / prompt→choice の 1 往復。30 秒超 or 合計 10 分超で時間切れ負け (FlagFall)。接続したまま無応答でも 30 秒で負けになります。各 request/prompt には clock が付くので、必要なら my_deadline_unix_ms を見て時間配分できます。
自分の bot を書く
このリポジトリの主目的は「自分の bot を書く土台」になることです。手順は 2 つだけ。
1. src/bots/<your_bot>.rs に BotPolicy トレイトを実装する (choose_action で自分の番の行動を req.legal_actions から選び、choose_prompt で解決中の選択に答える)。
impl BotPolicy for MyBot {
fn choose_action(&mut self, req: &RequestMsg, rng: &mut ChaCha20Rng)
-> Result<ActionDto, TransportError> {
// req.state … board masked to your view / req.legal_actions … legal moves
Ok(req.legal_actions.iter()
.find(|a| matches!(a, ActionDto::EndTurn))
.cloned()
.unwrap_or_else(|| req.legal_actions[0].clone()))
}
fn choose_prompt(&mut self, p: &PromptMsg, rng: &mut ChaCha20Rng) -> PromptChoice {
crate::bots::RandomPolicy.choose_prompt(p, rng) // when in doubt, random
}
}
2. src/bots/mod.rs の build / available に 1 行ずつ登録する。あとは --bot my-bot で動く。
// src/bots/mod.rs
&["random", "dragapult-takeuchi", "dragapult-yopifutto", "my-bot"] // available()
"my-bot" => Some(Box::new(MyBot)), // build()
bot から見えるもの
- req.state (StateDto): 自分視点にマスクされた盤面。自分の手札は見えるが、相手の手札・山札は card: null (覗けない)。場・トラッシュ・スタジアムは公開。
- req.legal_actions: サーバ (審判) が列挙した合法手。不正手は送れないので、AI は一覧から「選ぶ」だけ。
- カード事実: HP やワザ index は盤面 DTO に全部は入っていない。CardFacts が slug から is_ex / attack_index を引く。
規律 (忠実さ)
- 合法手から選ぶ。未知の状況で「それっぽい手」を発明しない — 迷ったら RandomPolicy に委ねるのが安全。
- 乱数は ChaCha20Rng だけ (seed 固定で再現可能)。Instant/SystemTime のような非決定性を持ち込まない。
プロトコル
サーバとやり取りする JSON の完全なリファレンスはリポジトリの docs/protocol.md にあります (全メッセージのキー・型・エラーコード・prompt 応答・情報マスキング)。これを読めば他言語でも bot を実装できます。
ライセンス: MIT OR Apache-2.0。Issue / Pull Request 歓迎。新しい bot や別アーキタイプのデッキの持ち込みも歓迎です。