コンテンツにスキップ

2026-06-17 セッション 1: 参戦方針の決定とドキュメント基盤構築

今日やったこと

  • リポジトリ初期状態を確認 (pyproject.toml, 当時の空の main.py, サンプル reinforcement-learning-and-mcts-sample-code.ipynb)。uv セットアップ済みだが依存はまだ空。
  • Kaggle コンペ「Pokemon TCG AI Battle Challenge」と CABT エンジン (松尾研) のドキュメントを通読 (WebFetch で取得できた範囲)。
  • サンプル ipynb (MCTS + Transformer + 自己対戦) を完全に読解。
  • サンプル仕様: MyModel = d_model=128, heads=2, layers_enc=1, layers_dec=1SEARCH_COUNT=10。5 イテレーション × 100 self-play で random 相手 76% 勝率まで到達 (notebook 出力済)。
  • サンプルの 2 つの弱点を発見 (後で Codex レビューで再確認):
    1. 隠し情報サンプリングが「雑な determinization 1 本」。相手 deck/hand/prize は Snorlax (id=1072) / Basic Energy (id=1) 固定。
    2. policy target が visit 分布ではなく、child.total/visit - root.total/visit で作っており、直前の NN policy 出力に強く依存 する自己回帰的ループになっている (AlphaZero の標準実装ではない)。
  • 関連研究を WebSearch で広く調査: IS-MCTS, Determinized UCT, AlphaZero/MuZero, DeepStack/Pluribus (CFR), Suphx (Mahjong, oracle guiding), DouZero+, Hearthstone/MTG AI, Pokemon Showdown (poke-env, MIT thesis 等), CCG taxonomy。
  • Codex (gpt-5.4-codex) で計画レビューを依頼し、以下 3 つの指摘を取り込んだ:
  • belief 改善 (IS-MCTS 化) を Phase 2 へ前倒しSEARCH_COUNT 拡大より優先。
  • 学習 target を visit 分布へ修正。policy head の loss を HuberLoss → CE/KL へ。
  • ヒューリスティクス / デッキ研究を前倒し、モデル巨大化は後ろへ。
  • 計画書を/Users/ryo/.claude/plans/...からdocs/PLAN.mdへコピーし、以後はこのファイルを参照する。
  • 参考文献を docs/references.md として独立化。
  • docs/{journal,exploration,decisions}/ の構造とセッション連続性ルール (開始時に PLAN+journal 読む / 終了時に journal 書く / 重要判断は decisions/NNNN-*.md) をプラン内で確定。
  • CABT の使い方とローカルシミュレーション手順を docs/exploration/cabt-local-simulation.md に整理。
  • sample/ を新設し、最小サンプル一式を追加。
  • sample/README.md
  • sample/deck.csv
  • sample/run_local_battle.py
  • sample/render_kaggle_html.py
  • uv run python -m py_compile ... でサンプル 2 本の構文確認を実施。
  • uv run python sample/run_local_battle.py を実行し、cg-lib 未指定時に案内メッセージで止まることを確認。
  • uv run python sample/render_kaggle_html.py を実行し、kaggle_environments 未導入時に案内メッセージで止まることを確認。
  • 添付の beginner notebook をもとに、最初の valid submission 導線を docs / sample に追加。
  • docs/exploration/first-valid-submission-guide.md
  • sample/submission_main.py
  • sample/build_submission_bundle.py
  • uv run python sample/build_submission_bundle.py を実行し、sample/submission.tar.gzmain.pydeck.csv を含むことを確認。
  • CABT 用の Linux 実行環境を Docker で追加。
  • Dockerfile.cabt
  • scripts/run_cabt_docker.sh
  • docs/exploration/cabt-docker-runtime.md
  • bash scripts/run_cabt_docker.sh --max-steps 10 を実行し、Docker 上の Linux amd64 環境で sample/run_local_battle.py が起動して Battle started. まで進むことを確認。
  • sample/render_kaggle_html.py の初期デッキ返却バグを修正し、sample/result.htmlstderr から TypeError が消えることを確認。
  • kaggle_environments の CABT package を調べ、html_renderer() が参照する visualizer/default/dist/index.html / cabt.js が pip 配布物に含まれていないため、result.html が共通プレイヤー UI のみになることを確認。
  • Docker 内で動くリアルタイム viewer を追加。
  • sample/realtime_server.py
  • scripts/run_cabt_viewer_docker.sh
  • bash scripts/run_cabt_viewer_docker.sh で viewer サーバーを起動し、http://127.0.0.1:8000/api/state から JSON が返ることを確認。
  • tcg-replay-viewer.ipynb の画像抽出ロジックをベースに、Card_ID List_JP.pdf から必要カードだけ切り出して使うローカル viewer 生成スクリプト sample/render_local_viewer.py を追加。
  • Docker から同じ viewer を生成できるショートカット scripts/render_local_viewer_docker.sh を追加し、Dockerfile.cabtpymupdf / Pillow / flask を追加。
  • 公式 viewer 系のファイル (sample/official_replay/index.html / gameVisualizer.js) を流用して local battle を replay できる sample/export_official_replay.pyscripts/render_official_replay_docker.sh を追加。
  • sample/realtime_server.py を拡張し、ブラウザ上で option index を選択して battle_select() できる手動プレイ導線を追加。

学んだこと / 観察したこと

コンペの構造 (二次情報、Phase 0 で公式確認すべき)

  • 2 部門制: Simulation Category (AI agent 提出) と Strategy Category (レポート提出、賞金あり)。後者があるため、設計判断の都度ドキュメント化することが直接スコアに効く。
  • 賞金: 第 1 ラウンド上位 8 チーム各 $30,000、グランプリ $50,000、総額 $300,000+ と報道。
  • タイムライン: 第 1 ラウンド 2026年6月〜8月、最終締切 2026年9月14日と報道。
  • カードプール: スタンダードの約 2,000 枚。
  • 主催の公式コメント (Overview): 「相手手札不明が最大の課題」「ルールベース単独不可」「novel methods を推奨」。

技術的に重要な知見

  • Determinized UCT は strategy fusion に弱く、IS-MCTS の方が品質高い (Cowling 2012, Dou Di Zhu での比較)。ただし IS-MCTS は実装コストが高い → 段階的に Determinized → SO-ISMCTS が現実的。
  • Suphx の oracle guiding: 学習時のみ完全情報で auxiliary head を学習する手法。提出 inference には影響しないが学習品質を底上げ。
  • MIT thesis (2024): Pokemon Showdown ランダムバトルで PPO 単体 1677 → PPO+MCTS lookahead 1756 (Glicko-1)。MCTS 併用が効くことの数値証拠
  • CABT の公式 docs には kaggle_environments.make("cabt")env.render(mode="html") を使った HTML 出力例があり、Kaggle 風の見た目確認は「動画」より「HTML リプレイ」と捉えるのが自然。
  • ローカル直接対戦の最小 API は battle_start()battle_select() のループ → battle_finish() で十分組める。
  • いまの repo には cg-lib が含まれていないため、ローカル実行の成否は Kaggle 配布物の取得可否に依存する。
  • beginner notebook の観点では、最初の目的は「強さ」ではなく submission.tar.gz の構造理解。main.pydeck.csv だけでも提出 bundle の形は再現できる。
  • cg/libcg.so は Linux x86_64 ELF なので、Apple Silicon / macOS では直接読めないが、Docker の linux/amd64 ならそのまま動かせる。
  • CABT の env.render(mode="html") は試合データ生成まではできるが、pip 版 kaggle_environments に CABT 専用 renderer asset が欠けているため、ローカルでは完全な盤面描画にならない。
  • その代替として、obs.current / obs.select / obs.logs / visualize_data() をブラウザへ配信する自前 viewer は十分実用になる。

サンプルコード詳細 (Phase 3-A 移植時に参照)

  • 状態エンコード: SparseVectorEmbeddingBag 入力。ベンチ 8 枠 + アクティブ + プレイヤー状態 + 手札 + デッキ + スタジアム を順に並べる。
  • アクションエンコード: OptionType ごとに decoder_main_feature (PLAY/ATTACH/EVOLVE/ABILITY/DISCARD/RETREAT) と decoder_card_offset (CARD/TOOL/ENERGY/SKILL) で領域分け。
  • MCTS: UCB に似た v + c * prior / (1 + visit)c = 0.4 * sqrt(parent.visit)
  • λ=0.9 で value をブートストラップ (value = value * λ + sample.value * (1 - λ))。

次にやること (Phase 0 残り)

直近 (次のセッション最初)

  • [ ] docs/decisions/0001-staged-extension-approach.md を書く (本セッション内で着手予定)
  • [ ] docs/decisions/0002-determinized-then-ismcts-roadmap.md を書く (本セッション内で着手予定)
  • [ ] Kaggle Notebook で cg-lib の実在パスと配布形態を確認し、sample/run_local_battle.py の想定とずれていないか検証
  • [ ] sample/render_kaggle_html.py を Kaggle 上で実行して result.html の見え方を確認
  • [ ] sample/submission.tar.gz を Kaggle Notebook 側に持ち込み、最小提出 bundle として通るか確認
  • [ ] Docker 環境上で sample/render_kaggle_html.py 相当の HTML 出力まで再現できるか確認
  • [ ] sample/realtime_server.py にカード画像や option のカード名解決を足して viewer を見やすくする
  • [ ] Phase 0-A: Kaggle Overview / Data / Rules ページから 公式情報 (提出形式、制限時間、カードプール、賞金、評価方式) を確定し docs/exploration/competition-rules.md に記載
  • [ ] Phase 0-A: Kaggle Discussion を 1 周ざっと眺めて主催アナウンス・既知バグ・参加者 tips を docs/exploration/discussion-notes.md に記録

Phase 0 残作業

  • [ ] Phase 0-B: cg-lib 入手と配布形態確認 (Kaggle Notebook 上で確認)
  • [ ] Phase 0-C: notebooks/00_api_exploration.ipynb を作って all_card_data / all_attack / Observation の中身を実観察
  • [ ] Phase 0-D: notebooks/01_card_dictionary.ipynb で全カード一覧と環境上位デッキ候補メモ
  • [ ] Phase 0-E: notebooks/02_one_game_trace.ipynb で 1 試合手動トレース (option を print して手で index 選ぶ)
  • [ ] Phase 0-F: search_step レイテンシを time.perf_counter で計測 → docs/exploration/search-api-latency.md
  • [ ] Phase 0-G: ポケカ要素 ⇔ API マッピング表を埋める
  • [ ] Phase 0 完了基準のチェック (PLAN.md 参照)

行き詰まり / 未解決

  • cg-lib のローカル入手手段が未確定: Kaggle Notebook 内でしかインストールパスが取れない可能性がある。Phase 0-B で要確認。
  • Kaggle コンペページの本文を WebFetch で取得できない (JS レンダリングの可能性)。Kaggle Notebook 経由か、ブラウザで手動コピーして docs/exploration/competition-rules.md に貼り付ける運用に。
  • MPS で EmbeddingBag が動くかは未確認。Phase 1 冒頭で確認、ダメなら CPU フォールバック確定。
  • デッキレシピが事前公開かどうかが未確認。これが分かると相手 deck の belief 初期化方法が変わる。Phase 0-A で要確認。
  • Strategy Category の評価基準・締切が未確認。Simulation と同じ 9/14 締切かは不明。Phase 0-A で確認必要。

参考リンク

  • docs/PLAN.md — 本計画 (この session の決定がベース)
  • docs/references.md — 参考文献
  • 計画原本: /Users/ryo/.claude/plans/https-www-kaggle-com-competitions-pokemo-staged-fiddle.md (Claude Code が plan mode で生成。以後の改訂は docs/PLAN.md 側で行う)