PokaiTrainer: Scaling Equilibrium Search to Competitive Pokémon VGC
Organizations: Independent Researcher
Abstract
Decision-time equilibrium search carried poker to superhuman play, but it has so far relied on tractable subgames: a handful of actions per decision, chance confined to card deals, one player moving at a time. Competitive Pokémon in its official doubles format (VGC) breaks all three assumptions at once. Both players act simultaneously from joint menus in the hundreds, each joint action resolves to hundreds of stochastic outcomes, and the opponent's reserves and stat allocations are hidden. No prior Pokémon agent performs equilibrium search, and whether it scales to this regime was open; we show that it does, and report what it took. PokaiEngine, our Rust battle engine, enumerates a joint action's full weighted outcome distribution in one pass, at parity with Pokémon Showdown and a fraction of the cost of sampling it. PokaiTrainer adapts Student of Games to this scale and trains it by self-play over hundreds of human teams. Each decision is solved by counterfactual regret minimization as a Bayesian matrix game over public belief states, subgames grow under an explicit compute budget, and value targets are harvested from the interior of every solve and grounded by realized outcomes. The strength is in the search. The network's policy alone loses even to a shallow heuristic search. PokaiTrainer is, to our knowledge, the first VGC agent rated on the live Showdown ladder. Under open team sheets it wins 59% of 150 best-of-three sets against a human field averaging Elo, holds a 1350-1400 Elo band, and at its peak reached 1492 Elo, entering the format's top 500.
Figures & tables
| Chess / Go | HUNL poker | Scotland Yard | No-press Diplomacy | VGC doubles | |
|---|---|---|---|---|---|
| Simultaneous actors | — | — | — | 7 powers | 2 players 2 slots |
| Hidden information | — | hands | 199 stations | — | 15 brings spreads per Pokémon |
| Chance | — | card deals only | — | — | – outcomes per joint action |
| Actions per decision | 35 / 250 | a few bet sizes | 10 | up to per power; a few dozen searched | per player, joint |
| Horizon | 80 / 150 plies | 4 bet rounds | 24 rounds | open-ended | 5–20 turns |
| Method | Mean time (ms) | Mass covered | Mass misallocated |
|---|---|---|---|
| Search , exhaustive | 9.9 | 100% | 0% (reference) |
| Search , 32-branch cap | 1.0 | 99.5% | 0.7% |
| Compute / Showdown sampling, | 1.3 / 36.0 | 94.3% / 93.0% | 10.0% / 10.2% |
| Compute / Showdown sampling, | 4.9 / 132.0 | 98.4% / 98.2% | 4.8% / 4.8% |
| Compute / Showdown sampling, | 19.4 / 509.0 | 99.7% / 99.4% | 2.8% / 2.6% |
Appendix figures & tables8 assets
Supplementary material from the paper’s appendix.
Appendix
| Component | Follows | Departure for VGC |
|---|---|---|
| Belief states, CFR solve, CV net at leaves | ReBeL, SoG | simultaneous-move matrix nodes; exactly enumerated chance nodes ( Section 4.2 ) |
| Incremental subgame growth | SoG (GT-CFR) | walk over a matrix game; admissions priced by compute cost, budget in cost units ( Section 4.3 ) |
| Value targets | SoG (solver values TD(1) rows) | per-row -mix, grounded on the realized world’s slot only ( Section 4.6 ) |
| Extra supervision | SoG (re-solved leaf queries) | interior nodes of the same solve, reach-sampled and bootstrap-weighted |
| Off-line coverage | SoG (recursive queries) | hypothetical augmentation, grounded by play |
| Decision | Chooses | / | Hidden | Solve size |
|---|---|---|---|---|
| Team preview | both | bring-4 lead pair | none ( ) | |
| Turn | both | move-or-switch per slot | root; interior | |
| Forced switch (after faints) | both | replacement | ||
| Mid-turn switch (pivot) | one seat | replacement (one slot) | , opponent’s uncommitted actions |
| Team | Elo | Pokémon |
|---|---|---|
| mb486 | 1676 | Charizard , Garchomp, Venusaur, Incineroar, Toxapex, Annihilape |
| mb355 | 1579 | Charizard , Floette-Eternal , Kingambit, Whimsicott, Basculegion, Garchomp |
| mb520 | 1531 | Tyranitar , Staraptor , Excadrill, Gholdengo, Sinistcha, Milotic |
| mb300 | 1523 | Raichu , Basculegion, Garchomp, Kingambit, Whimsicott, Ninetales-Alola |
| mb443 | 1520 | Charizard , Aerodactyl , Garchomp, Sylveon, Farigiraf, Kingambit |
| mb210 | 1516 | Froslass , Scovillain , Lycanroc-Dusk, Kingambit, Basculegion, Sneasler |
| # | Team | Win% | cRk | Pokémon |
|---|---|---|---|---|
| 1 | mb1 | 76.3 | 11 | Tyranitar , Staraptor , Excadrill, Basculegion, Sinistcha, Raichu |
| 2 | mb194 | 69.9 | 6 | Froslass , Incineroar, Gholdengo, Basculegion, Kingambit, Arcanine-Hisui |
| 3 | mb537 | 68.8 | 19 | Charizard , Mawile , Whimsicott, Basculegion, Farigiraf, Garchomp |
| 4 | mb345 | 65.6 | 13 | Charizard , Garchomp , Venusaur, Farigiraf, Incineroar, Sylveon |
| 5 | mb198 | 64.5 | 20 | Swampert , Floette-Eternal , Whimsicott, Pelipper, Archaludon, Basculegion |
| 6 | mb423 | 63.4 | 7 | Raichu , Tyranitar , Meowscarada, Basculegion, Kleavor, Talonflame |
| Arm | Change | Result | Verdict |
|---|---|---|---|
| no grounding | , | 50.0% (256/512) h2h, same deploy | wash at 2 rounds; calibration drifts |
| decoupled + zero-sum | re-priced targets, moment loss, | 42.6% (109/256) vs sibling r3 | loses; dropped |
| hypothetical forks, 3/game | augmentation only | 48.8% (125/256) compute-matched | wash per unit compute |
| hypothetical forks, 1/game + PUCT | 52.0% (133/256) on half the rows | kept | |
| full- on hypo rows | on augmented rows | 40.6% (104/256) vs control | loses |
| entry continuations | replacement + preview roots | 52.0% r5, 57.0% r7 | kept |
| Agent’s solver | Agent’s play | Best-response win% [95% CI] | Gain / decision | |
|---|---|---|---|---|
| CFR | argmax (eval cells) | 77.7 | [72.2, 82.4] | 0.097 |
| CFR | (ladder) | 52.3 | [46.2, 58.4] | 0.027 |
| CFR | (solved mix) | 49.6 | [43.5, 55.7] | 0.0003 |
| decoupled UCT | argmax | 74.6 | [68.9, 79.6] | 0.193 |
| decoupled UCT | 72.7 | [66.9, 77.8] | 0.110 | |
| decoupled UCT | 83.6 | [78.6, 87.6] | 0.058 | |