Rules stay exact
TypeScript deals cards, checks rank and group size, creates legal moves, applies plays, tracks passes, ends rounds, exchanges cards, and scores the match. The model cannot invent an illegal action.
Model field guide
The game uses Jev as a teacher, compresses its move choices into 849 numbers, and runs the student directly in your browser. Card rules stay in normal code. Only the strategic ranking is learned.
This is not a general language model in the browser. It is a focused policy model. The game gives it a small list of legal moves, and it scores each one.
TypeScript deals cards, checks rank and group size, creates legal moves, applies plays, tracks passes, ends rounds, exchanges cards, and scores the match. The model cannot invent an illegal action.
The student learns which legal move Jev tends to prefer: finish now, react to a near-out opponent, preserve useful groups, shed cards, and avoid wasting control.
Candidate rank and size, cards left, group breaks, control cards, the full hand shape, current target, public opponent counts, pass state, and threat indicators.
Eight nonlinear units combine signals such as “lowest card during a threat” or “shed an intact group when the hand is short.”
One score for each candidate. Softmax turns all scores into probabilities. The game uses the highest-probability move.
A second browser model estimates each player's chance to win the round. Its four probabilities always sum to 100%.
The app calls the model only at an open-lead boundary, before the next player starts a trick. The probabilities stay fixed during that trick.
The 86 inputs contain all four rank-count hands, cards already played as derived from the hands, hand-shape summaries, round progress, and the next player through relative seating.
Sixteen hidden units produce four player probabilities. The network has 1,460
learned weights. The browser API is evaluateWinProbability().
Complete games use the existing local policy and sample its move choices.
The test games are not used to fit or select the model.
A second independent four-player distribution estimates who will finish fourth. This result is the real-loss probability. Its four probabilities always sum to 100%.
The model refreshes only at an open-lead boundary. It stays fixed during a trick. Open leads after the President has finished are also valid boundaries.
The inputs include all four hands, played cards, round progress, and the player who plays next.
The model uses the same complete-information architecture as the win model. It has 1,460 learned values and produces four real-loss probabilities.
The real-loss model uses a separate data split for training and evaluation.
The test games are not used to fit or select the model.
Distillation means that a smaller student learns from the outputs of a larger or remote teacher. Here, the teacher gives both its selected move and its full Choice probability distribution.
Seeded four-player games produce reproducible hands, targets, opponents, and candidate moves. Twelve fixed scenarios cover important edge cases.
Each state is sent to the existing TypeSafe Choice question. Jev returns one selected move and a probability for every candidate. Collection is sequential and resumable.
Every candidate becomes 104 normalized values. The model can compare a changing number of legal moves because the same scorer is reused for each one.
The target is 80% of Jev’s full probability distribution and 20% extra weight on Jev’s selected move. Adam updates the 849 values. Weight decay limits overfitting.
Training checks game 5 every five epochs and keeps the best checkpoint. Game 6 stays separate until final testing, so it measures a new game trajectory.
240 total labeled states, grouped by game seed.
The final test uses a game seed not used for fitting.
Probabilities let the student express close calls. They do not explain why a move is correct, and they do not make the teacher perfectly consistent.
The model only sees legal candidates. Passing is removed when a card can be played. If only one move exists, code returns it directly. This keeps uncertain strategy separate from exact game behavior.
On a free lead with 11 cards, Jev slightly preferred a standalone 6. The local model slightly preferred an intact triple of 7s. This is one of its two test misses.
The local student is useful because it is focused. The same limits that make it tiny also keep it from matching Jev in every unusual state.
Playing needs no API key. Teacher collection is the only step that contacts Vercel AI Gateway and creates billed usage.
Run from the repository root:
cd experiments/president-card-game-sol
pnpm dev
# Open the game
http://localhost:3000/
# Open this guide
http://localhost:3000/model-guide.html
# Requires AI_GATEWAY_API_KEY and creates billed usage
pnpm distill:collect -- 240
# Rebuild the generated weight file
pnpm distill:train
# Check the stored weights without any API call
pnpm distill:evaluate
# Train and evaluate the win-probability model
pnpm win-model:train
pnpm win-model:evaluate
# Train and evaluate the real-loss probability model
pnpm loss-model:train
pnpm loss-model:evaluate
# Local behavior and build checks
pnpm test
pnpm test:types
pnpm build
src/local-policy.ts
Feature encoding, neural scorer, softmax, and browser inference.
src/local-policy-weights.ts
The generated 849-value model. This ships to the browser.
src/win-probability.ts
Win-model input encoding and browser inference.
src/win-probability-weights.ts
The generated 1,460-weight win model.
src/loss-probability.ts
Real-loss inference over the shared complete-information encoding.
src/loss-probability-weights.ts
The generated 1,460-value real-loss model.
src/train-win-probability.ts
Seeded self-play training and held-out evaluation for both forecasts.
src/distill.ts
State generation, Jev collection, training, early stopping, and
evaluation.
data/distillation.jsonl
The 240 teacher examples. Development only; not in the browser bundle.
app/app.vue
The game loop calls evaluateLocalPolicy() directly.
src/local-policy.test.ts
All 12 expected moves plus a complete legal four-player game.