This repository contains a browser-based Yahtzee implementation where a human plays against a computer using an optimal, table-driven strategy. It also vendors the original Pascal sources used to generate the optimal-strategy tables, and the precomputed binary tables themselves.
- Implemented using Codex
- Web app lives in
web/(pure client-side HTML/CSS/JS). - Optimal expected-score tables live in
gstbl/as binary files. - Original Pascal sources are in
YahtzeeTrainerLazarus/for reference.
This work is directly inspired by (and cross-checked against) Tom Verhoeff’s Yahtzee Trainer (Pascal) described at:
The Pascal project computes an optimal Yahtzee strategy by dynamic programming and saves results in a compact binary “game state table” (.gstbl). The web version here loads that table and mirrors the key DP steps in JavaScript to produce optimal advice and play.
The Pascal sources (GPL-licensed) included here are for reference and to make the data tables’ meaning precise. The web app does not execute Pascal; it reads and uses the precomputed tables generated by that code.
The .gstbl files are a serialized array of double-precision values, indexed by a compact encoding of the “between-turns” game state:
- 11 booleans: whether each category in Aces..Sixes and 3-kind..Large Straight is still free
- A combined flag
i12 = 2*ord(Yahtzee in free) + ord(chip) - A boolean for
Chance in free - An integer
usneedin [0..63] for upper-section bonus need
In memory, Pascal uses the rightmost index fastest. The original (Pascal) table writer is sensitive to platform endianness and bit-order of the boolean block. To make loading robust on different JS/browser/CPU combinations, the loader in web/logic.js:
- Reads every 8-byte float via
DataView.getFloat64in both little- and big-endian - Tries both boolean-block orders when computing the linear index
- Calibrates by evaluating
gstbl[InitialGameState]and picking the combination that yields a plausible expected score (≈ 250 for official Yahtzee)
This calibration step ensures the table is interpreted correctly on machines like Apple Silicon (M1/M2) in Chrome and other browsers.
- From the repo root, serve files using any static server, then open
web/index.html.- Example:
python3 -m http.server 8000then go tohttp://localhost:8000/web/
- Example:
- The app prefers
gstbl/OptEScore-Official.json(canonical JSON). If not present, it falls back to the binaryOptEScore-Official.gstbl. - The UI includes an “Advice” panel and a final-roll EV breakdown. The computer plays its turn automatically and optimally.
This repo includes a GitHub Actions workflow to publish the site from web/ plus the gstbl/ data:
- The workflow is in
.github/workflows/deploy-pages.yml. - It copies
web/to the publish artifact and also includesgstbl/atgstbl/so the web app can fetch the binary table. - On push to
main, it builds and deploys to GitHub Pages.
Enable Pages in your repo:
- Settings → Pages → Build and deployment → Source: GitHub Actions.
- The action will publish to
https://<owner>.github.io/<repo>/(or the private Pages URL if the repo is private and your plan supports private Pages).
Note: The app’s loader tries JSON first (gstbl/OptEScore-Official.json), then falls back to the binary (gstbl/OptEScore-Official.gstbl) so it works both in local dev and on the published site.
To avoid binary parsing issues and ensure a canonical index order in the browser, convert the binary table to JSON once:
node scripts/convert-gstbl-to-json.mjs gstbl/OptEScore-Official.gstbl gstbl/OptEScore-Official.json
The converter will calibrate endianness and boolean-block order, then emit a canonical JSON with the data array in the standard index order expected by the web app.
Open web/tests.html to run the browser tests:
- Structural checks (using a zeroed table) for scoring, Joker rule, and DP wiring
- Real-table checks (load the actual
.gstbl) for key scenarios:- First roll 3,3,6,5,6 → keep 6×2
- First roll 2,2,2,1,2 → keep 2×4
- Final roll 2,2,2,6,6 → Full House
- A console helper
debugKeeperEVs([…], rollsLeft)prints per-keeper EVs for diagnosis
- The Pascal sources in
YahtzeeTrainerLazarus/are GPL-licensed by their author. If you distribute modified binaries or the Pascal code, ensure GPL requirements are followed. - The JS web app code and loader are original to this repo and designed to interoperate with the published table format.
web/— client app, loader, and testsgstbl/— precomputed optimal expected-score tables (binary) and optional JSONYahtzeeTrainerLazarus/— Pascal sources for the original Yahtzee Trainer
- Tom Verhoeff for the original Yahtzee Trainer and published materials
- The broader community for analyses of optimal Yahtzee strategies