1. 最初に決める――ゲームを作るのか、「勝つ研究所」を作るのか
カードゲームのシミュレーターを作ろう、と聞くと、最初に巨大なゲーム画面を想像しがちだ。
カード画像。アニメーション。ボイス。ドラッグ操作。キラキラした進化演出。
でも「どのデッキが強いか」「この手とあの手、どちらが勝ちやすいか」を調べたいだけなら、その大半はいらない。
研究用シミュレーターの中心はこれだけだ。
現在の状態
↓
合法な行動を出す
↓
どれかを選ぶ
↓
ルール通り状態を更新する
↓
次の状態
これを勝敗が決まるまで繰り返す。
つまり作りたいのはゲームの見た目ではなく、カードゲームの世界を数字だけで動かせる実験室だ。
もし信頼できる既存エンジンがあるなら、それを借りて研究層だけ作るのが最速。なければ、最小ルールから自分で作る。
「ゼロから作る」とは、全部を手作業で再発明することではない。
目的に必要な部品をゼロから組み合わせて、再現可能な研究システムを作ることだ。
2. 完成形を先に決める――入力と出力を書けば設計が見える
コードを書く前に、「何を入れたら、何が返ってくる装置か」を決める。
入力の例はこう。
- カードDB
- 40枚デッキ
- 対戦相手のデッキ
- 先攻・後攻
- 乱数seed
- プレイ方策
- 環境情報
- 試合数
出力の例はこう。
- 勝敗
- ターン数
- 先攻・後攻別勝率
- 対面勝率
- 平均勝率
- 最悪対面
- 手札事故率
- キーカードを引けなかった時の低下
- よく起きるミス
- どのカードを入れ替えると改善したか
ここを先に決めないと、「カードを動かせるようになったけど、何を調べるソフトなの?」という巨大なおもちゃが完成する。
シミュレーターは、先に質問を決める。
コードはその質問に答えるために書く。
3. カードDBを作る――カード一覧とルール実装は別物
最初の大仕事はカードデータだ。
最低限、カードごとに次のような情報を持たせる。
id
name
class
cost
type
attack
defense
rarity
set
text
evolved_stats
related_cards
tags
ここはJSONやSQLiteなどで構造化する。
重要なのは、カードの文章を集めたことと、そのカードが正しく動くことは別という点。
「ファンファーレ:4ダメージ」とDBに書いてあっても、誰を対象にできるか、対象がいない時どうなるか、ダメージ軽減がある時どうなるか、破壊時効果が動くか、同時発動の順番はどうなるかまで処理できなければ、まだカードカタログでしかない。
カードDB部門は「説明書を集める部署」。
ルールエンジン部門は「説明書どおり世界を動かす部署」。
名簿ができても社員はまだ働かない。
4. ゲーム状態を数字にする――画面ではなく「状態」を保存する
次に、対戦中のすべてをデータとして表現する。
turn
active_player
leader_hp
max_pp
current_pp
hand
deck
board
graveyard
evolution_points
super_evolution_points
crests
amulets
counters
temporary_effects
ここで大切なのは、画面の見た目ではなく「ルール判断に必要な情報」を持つこと。
カードが右から2番目に見えているかは研究にはどうでもいい。しかし、そのフォロワーは今ターン攻撃できるか、守護を持っているか、進化済みか、一時バフはいつ切れるかは絶対に必要だ。
良い状態モデルは、ゲーム画面をスクリーンショットで保存するのではなく、世界の意味を保存する。
5. ルールエンジンを作る――ゲームは「状態A→行動→状態B」
ルールエンジンの仕事は、ある行動を受け取って、次の状態を正しく作ることだ。
状態A:
自分PP 3
手札に3コストフォロワー
盤面空き1
行動:
そのフォロワーをプレイ
結果:
PP 0
手札 -1
盤面 +1
ファンファーレ処理
カードを出す、攻撃する、進化する、超進化する、アクトする、対象を選ぶ、ターン終了、ドロー、PP回復、勝敗判定を全部この考え方で処理する。
エンジンは「賢くプレイする」必要はない。
まず必要なのは、バカでも合法な行動をすれば、世界が正しく動くこと。
AIの頭脳とゲームの物理法則を混ぜると、バグの原因が分からなくなる。
6. カード効果は「共通ルール+例外」で実装する
数百枚を全部1枚ずつカード名ifで書くと地獄になる。
だから共通効果は一般化する。
deal_damage
heal
draw
buff
summon
destroy
banish
gain_ward
gain_storm
カードの文章をこうした共通部品へ落とす。
ただしカードゲームには必ず変なカードがいる。そういうものは個別overrideで処理する。
そして必ず「未対応カード数」「partial対応」「runtime gap」を数える。
分からないカードを適当に動かすより、未対応として止める方が研究では正しい。
7. 合法手生成を作る――AIは「選択肢にない正解」を選べない
次は、今の状態で可能な行動を全部出す。これをcandidate generation、候補手生成という。
どのカードを出せるか、どこへ出せるか、どの相手を攻撃できるか、何を対象にできるか、進化できるか、ターン終了できるかを列挙する。
ここが意外と超重要。
評価AIがどれだけ賢くても、「カードを使わず温存する」、「自分の弱いフォロワーを消して盤面を空ける」、**「先にドローする」**という正解が候補に存在しなければ、絶対に選べない。
「AIがアホ」だと思ったら、まず正解候補そのものが生成されているかを見る。
8. seed・replay・hash――同じ実験をもう一度できるようにする
カードゲームにはランダムがある。ドロー順、ランダム対象、生成カードなど。
そこでseedを固定する。
さらに、
engine commit
card DB hash
deck hash
policy hash
environment hash
schedule hash
seed hash
を記録する。
同じエンジン、DB、デッキ、方策、seed、先攻後攻なら、同じ試合を再現できるようにする。
これがないと「前より勝率上がった!」と言っても、DBやAIやデッキや運が変わっただけかもしれない。
研究で一番怖いのはバグより、何を比較したのか後から分からなくなることだ。
9. 最初のAIは賢くなくていい――まず基準方策を作る
いきなりAlphaGo級を目指す必要はない。
リーサルがある → 勝つ
死にそう → 守る
低コストを出せる → 出す
盤面有利 → 顔を詰める
盤面不利 → トレードする
これをreference policy、基準方策にする。
重要なのは「強いAI」より、比較の基準になる固定AIを持つこと。
あとで人間知識を入れたAIや探索AIを作った時、「本当に改善したのか?」を測れる。
10. 人間ノウハウは「絶対命令」ではなくpriorにする
攻略記事や上位プレイヤーの知識には価値がある。マリガン、温存、EP/SEP予約、コンボ準備、相手の強い返し、盤面枠、手札上限、2〜3ターン後のリーサルなど。
しかし、そのまま絶対ルールにすると「このカードは温存」→今使わないと死ぬ→それでも温存して死亡になる。
だから人間知識は、
hold_value +20
future_combo +30
survival +50
premature_spend -40
のような「考えるクセ」にする。
人間の攻略本は答えではない。探索AIへ渡す地図だ。
11. 木探索・ビーム探索・ノード予算――数ターン先を読む
AIを一段賢くするなら、未来を見る。
毎回10候補なら、
1手先 10
2手先 100
3手先 1,000
4手先 10,000
と爆発する。
そこでdepth、beam width、node budget、pruningを使う。
ただし「今は弱いが2ターン後に超強い」コンボ線を切ると弱くなる。
だから評価関数には、immediate_value、future_value、survival_value、setup_value、lethal_value、resource_valueを分けて持たせる。
探索AIの難しさは、未来をたくさん読むことではない。
どの未来を捨てないかだ。
12. 相手の手札は見せない――belief・POMDP・モンテカルロ
相手の隠し手札をAIへ直接渡したらチートになる。
そこで公開情報だけから、
AoEを持っているかも 30%
守護を持っているかも 20%
何もないかも 50%
のような「あり得る世界」を作る。これがbelief、信念状態の考え方。
相手手札など一部が見えないので、数学的にはPOMDP、部分観測マルコフ決定過程に近い。
実装では厳密なPOMDP solverを作らなくてもいい。複数の仮想手札をsampleして、その未来を何度も試す。これはモンテカルロ法の考え方。
これで「全体除去を持っているかもしれない。でも全部をケアしていたら攻められない」という人間らしい不確実性を作る。
13. 大量対戦はA/B実験として設計する――試合数だけ増やすな
AIを変えたら、同じ問題で比較する。
同じデッキ、同じ相手、同じ先後、同じseedで、
旧AI 1戦
新AI 1戦
を走らせる。これがpaired A/B、対応あり比較。
先に小さいquick testを行い、明らかな退行がないかを見る。通った候補だけ、本番のholdoutへ進める。そしてholdoutのseedは開発中に使わない。
学校でいうなら、練習問題→quick、模試→development、初見の期末試験→holdout。
大量対戦の目的は「数字を大きくする」ことではない。比較条件を揃えて、偶然を減らすことだ。
14. 勝率以外も測る――統計とロバスト評価
平均勝率だけ見ると危ない。
デッキAが平均60%でも1対面だけ20%、デッキBが平均57%で最悪でも52%なら、環境が少し変わった時にBの方が生き残るかもしれない。
だから平均勝率、メタ加重勝率、最悪対面、下位2対面平均、対面分散、先攻後攻差、brick率、キーカード未取得時の低下、平均ターン、信頼区間を見る。
CVaR的に「悪い方の成績」を見るのも有効。
A/BならMcNemar検定やbootstrapで差が偶然っぽいか調べる。
平均点だけ高い生徒ではなく、苦手科目で赤点を取らない生徒を探す。
15. デッキ最適化――40枚総当たりは無理なので、賢く候補を減らす
カードが数百枚あるゲームで40枚の全組み合わせを総当たりするのは無理。
まず大会デッキや人気デッキをseedにして、1枚入れ替え、2枚入れ替え、3枚入れ替え、同じ役割カードへの置換、苦手対面用techを試す。
Double Oracleは現在の戦略集に強い新しい対抗策を追加する。
PSROは「デッキ40枚」だけでなく「デッキ+プレイ方策」を1つの戦略として扱う。
No-Regret Learningは長期で「別の戦略を選べばよかった」という後悔を小さくする。
Robust Optimizationで平均だけでなく最悪対面も守る。
最強デッキ探索は、全部探す仕事ではなく、良い候補だけ残す工場だ。
16. AIが負けた理由を取る――action trace・ablation・反実仮想
「新AI、勝率下がりました」だけでは次に進めない。
毎ターン、候補、各候補の点数、選択、objective、EP/SEP予約、コンボ札の早切り、missed lethal、hand burn、board lockをaction traceとして残す。
原因候補を1個ずつ切るのがablation。
同じ盤面から実際に選んだAと、選ばなかったBを両方シミュレーションするのがcounterfactual、反実仮想。
「Aを選んだ試合は負けやすかった」だけでは相関。同じ状態からBへ変えたら本当に勝率が上がるなら、因果に近づく。
17. 新弾対応――環境をsnapshot化し、変わった部分だけ再計算する
新弾、能力変更、禁止・制限、人気デッキの変化に対して、
environment_id
date
format
legal_sets
engine_hash
card_db_hash
policy_hash
deck_corpus_hash
meta_hash
を固定する。
新しいカードDBが来たらdiffを取り、新カード、修正カード、関連カード、影響するデッキ、影響する対面を出す。
カードが1枚変わっただけなら、全試合をゼロから回さず、その周辺だけ再計算する。メタ比率だけ変わったなら、試合を再利用して重みだけ再集計できる。
新弾のたびに研究所を建て直すのではなく、差分だけ夜勤させる。
18. ソフトウェア構成――CLI中心の小さい研究所にする
src/
upstream/
deck/
policy/
simulation/
diagnosis/
statistics/
config/
data/
reports/
docs/
tests/
CLIはstatus、doctor、db check、env validate、simulate、experiment run、experiment analyze、optimize、diagnose、context buildのように分ける。
巨大な生traceやエンジン本体はGitへ入れず、cacheへ置く。
Gitに残すのはlock、config、manifest、hash、集計結果、再現コマンド、小さいfixture。
GitHubはコード置き場だけでなく、研究所の外部記憶になる。
19. ゼロイチ実装順――いきなり最強AIを作らない
1 カードDBを読める
2 最小ルールで1試合完走
3 合法手生成と対象選択
4 seed固定・replay・hash
5 単純AIで100戦
6 coverage監査と全カード対応
7 大会デッキで対面表
8 人間prior
9 木探索・belief
10 paired A/B・holdout
11 デッキ最適化
12 行動診断・新弾差分更新
最初から1万戦、MCTS、強化学習、最強40枚を全部やると、何が壊れたのか分からない。
まず1試合を正しく。次に100試合。その後に1万試合。
1万回高速で間違える機械を作るな。
20. 結論――カードゲームシミュレーターは「ゲーム」より「研究工程」を作るもの
本当に難しいのはカードを表示することではない。
世界を正しく数字にする、ルールを正しく動かす、正解候補を落とさない、見えない情報をチートせず扱う、AI同士を公平に比較する、勝率以外の弱点も見る、失敗理由を観測する、新弾が来ても再利用できる――ここが本体だ。
カードDBは記憶。ルールエンジンは物理法則。方策は頭脳。探索は先読み。統計は成績表。行動traceは監視カメラ。Gitは研究ノート。AIエージェントは研究員。
そして人間は、「その数字、本当に信用していい?」を聞く所長である。
最初は「疾走ドーンしたい」だけだった。
気づけばカードゲームAI研究所、開設。
まあ最後にやることは同じだ。
守護どける。進化する。
疾走ドーン。
