← PortfolioCHOMP

CHOMP — Technical Documentation

Version 3.0.0 · Last updated 2026-10-13 Written in ASD-STE100 Simplified Technical English. Organised with the Diátaxis model.


0. About this document

0.1 Purpose

This document tells you how to run, test and maintain CHOMP v1, the team-preview solver in ABRA. For results and figures, read the white paper: docs/CHOMP-whitepaper.md. This document does not repeat them.

0.2 Where the code is

The code of CHOMP v1 is in the ABRA repository, https://github.com/willhoop/abra, in the folder solver/chomp/. This repository (willhoop/chomp) holds the CHOMP documents and the retired browser tool (Part 5).

0.3 Structure

0.4 Terms

Use these terms with these meanings only.

Term Meaning
a sheet The open team sheet of one player: six Pokémon with species, item, ability and moves.
an option One choice at team preview: four Pokémon to bring, and two of the four to lead. Each sheet has 90 options.
a cell One pair of options: my option and the opponent option. The table has 90 × 90 = 8,100 cells.
the scorer The model that gives each cell a win probability. File solver/chomp/v1/scorer.js.
the mix A probability for each of my 90 options. CHOMP samples its choice from the mix.
a release A frozen copy of the ABRA simulator MEDICHAM. CHOMP v1 was tested on release eaa5becc54eb.
ROTOM The ABRA client that plays on Pokémon Showdown.
an arm A ROTOM configuration file in solver/rotom/arms/.

PART 1 — TUTORIAL

Get one CHOMP answer. Do these steps one time.

1.1 Get the code

  1. Clone ABRA: git clone https://github.com/willhoop/abra.git.
  2. Clone the Reg M-C Showdown checkout next to it, as pokemon-showdown-mc. ABRA reads the format from it.
  3. Make sure that the folder data/releases/eaa5becc54eb is in the ABRA checkout. Git does not track this folder. If it is not there, copy it from a checkout that has it.

1.2 Solve one preview

Open a terminal in the ABRA folder. Run this command:

ABRA_REGULATION=regmc node -e "
const CH = require('./solver/chomp/v1/chomp1.js').create({ release: 'eaa5becc54eb' });
const { parseShowteam } = require('./solver/human/parse_game.js');
const P = require('./solver/rotom/teams/regmc-pool.json');
const r = CH.solve({ mine: parseShowteam(P.teams['0'].packed), theirs: parseShowteam(P.teams['1'].packed) });
console.log(r.support.map(s => s.p.toFixed(3) + '  ' + s.label).join('\n'));
console.log('value', r.value.toFixed(3));
"

The command uses two teams from the ABRA team pool. It prints the options that have weight in the mix, and the value of the game for you.

Caution: Set ABRA_REGULATION=regmc. If you do not set it, ABRA reads the retired Reg M-B data and the solve stops with the error does not build.


PART 2 — HOW-TO GUIDES

Do one task.

2.1 How to run the CHOMP tests

In the ABRA folder, run:

node solver/tests/test-chomp1.js
node solver/tests/test-chomp.js

Each test prints its failed clauses. Each test has deliberate breaks. A deliberate break must make the test fail. On Windows, start heavy runs through tools\lownode.cmd.

2.2 How to use CHOMP in a ladder arm

  1. Open an arms file in solver/rotom/arms/.
  2. In the arm, set "preview": "chomp".
  3. Set "preview_max_ms" to the time budget for the preview, in milliseconds.
  4. Save the file.

ROTOM then asks CHOMP for every preview. The arm solver/rotom/arms/gen5-chomp-top.json is an example.

Caution: A ladder run uses a real rating. Only the owner (Will) starts a ladder run.

2.3 How to read what CHOMP did in a ladder run

  1. Run node solver/rotom/report.js ladder <run folder>.
  2. Read preview_by in the summary. It shows which policy answered each preview.
  3. Read the counters chomp:threw and chomp:illegal. If one of them is more than 0, CHOMP failed on that preview and ROTOM used the team's own recorded bring.

2.4 How to train a new scorer

Do not replace v1 without a gate. A new scorer must pass gate (a) against v1 first. CHOMP v2 did not pass, so v1 stayed.

  1. Write a pre-registration before you play the first game. Use solver/chomp/v1/prereg.js as the model.
  2. Make the targeted games with solver/chomp/v1/gen.js.
  3. Make the rows with solver/chomp/v1/build_rows.js.
  4. Train with python solver/chomp/v1/train.py. It reads gate (a) one time, on the test set.
  5. Run the label-shuffle break (CHOMP1_BREAK=shuffle). The break must fail.

The full commands are in the ABRA report docs/_reports/2026-09-27-chomp-v1.md §6.


PART 3 — REFERENCE

3.1 Files (ABRA repository)

File Function
solver/chomp/options.js The 90 options of one sheet, in a fixed order.
solver/chomp/v1/chomp1.js The solver: create, solve, sample.
solver/chomp/v1/features.js The engine facts for each pair of Pokémon, and the 22 cell features.
solver/chomp/v1/scorer.js The cell scorer, in JavaScript.
solver/chomp/v1/model/chomp1.json The trained v1 model.
solver/chomp/v1/preregistration.json The gates, written before the first game.
solver/chomp/v1/train.py The training script and the gate (a) read.
solver/slowking/matrix.js solveLP: the exact matrix-game solve.
solver/chomp/arms.js The arena arms that use CHOMP.
solver/rotom/policy.js ROTOM's preview hook (previewChomp).
solver/tests/test-chomp1.js The v1 tests.
solver/chomp/chomp.js, solver/chomp/v2/ v0 and v2. They are not used live.

3.2 Interface

const CH = require('./solver/chomp/v1/chomp1.js').create({ release })   // or { API }
const r  = CH.solve({ mine, theirs }, { deadline, series: { oppLast } })
const op = CH.sample(r, u)                                               // u in [0, 1)
Input Meaning
mine, theirs The two sheets, as arrays of six sets.
deadline Optional. A time limit for the scoring.
series.oppLast Optional. Games 2 and 3 only: { brought, leads, won } for the opponent's previous game.
Output field Meaning
options The 90 options.
mix, oppMix My equilibrium mix and the opponent equilibrium mix.
value The value of the game for me.
win[i] For option i: the win chance against their mix, against a uniform opponent, and in the worst case.
support The options with weight, with labels.
bo3 The best-of-three adjustment. It is null in game 1.
counters, ms, engine, model The receipt.

3.3 Settings

Setting Value Where
Best-of-three weight λ 0.5 LAMBDA in solver/chomp/v1/chomp1.js (pre-registered)
Repeat rates of human players read at run time solver/out/meta/bo3.json
Model version v1 CHOMP_VERSION environment variable (v0 selects v0)
Preview in an arm "preview": "chomp" the arms file

3.4 Data


PART 4 — EXPLANATION

4.1 Why CHOMP gives a mix and not one answer

Both players choose at the same time. If CHOMP always gives the same answer, an opponent can learn it and beat it. The equilibrium mix has a value that the opponent cannot make lower.

4.2 Why the scorer is antisymmetric

The two players are in the same game. If I win a cell with probability p, the opponent wins the mirror cell with probability 1 − p. The model has this property by construction, so a mirror match scores exactly 1/2.

4.3 Why the solve is exact

The table has only 90 × 90 cells. A linear program solves a table of this size exactly in milliseconds, so CHOMP does not use an approximate method.

4.4 Why the gates use a frozen release

The simulator changes over time. If the simulator changes during a test, the two halves of the test measure different things. A frozen release keeps the simulator the same for the full test.

4.5 Limits

Read the white paper, §6.


PART 5 — RETIRED: THE BROWSER USERSCRIPT (REG M-B)

Status: retired in 3.0.0. Do not use it for Reg M-C. It targets Reg M-B, and its species data is old. The code stays in this repository as history.

5.1 What it was

A Tampermonkey userscript for Pokémon Showdown. At team preview it showed one recommended bring and lead, from a single-ply damage calculation. It also had a replay analyzer and a damage calculator.

5.2 Files

File Function
app/plugin/chomp-bring4.user.js The userscript. It contains a copy of the engine.
engine/champ-model.js The old damage and matchup engine. The FORMAT block is at the top.
app/chomp-replay-app.html The replay analyzer.
build/build_v2_userscript.py, build/build_replay_app.py The builders. They copy the engine into the userscript and the analyzer.
tests/ The old engine tests. CI runs them.

5.3 How to rebuild it

  1. Change engine/champ-model.js.
  2. Run python3 build/build_v2_userscript.py.
  3. Run python3 build/build_replay_app.py.

Caution: If you do not rebuild, the userscript keeps the old engine.

5.4 Its validation

Read the white paper, §9, and docs/VALIDATION-REPORT.md. All of its figures are Reg M-B.


References