Skip to content

afotherg/yahtzee

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

21 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Yahtzee (Web + Tables)

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.

Inspiration and provenance

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.

Decoding the binary tables (.gstbl)

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 usneed in [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.getFloat64 in 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.

Running the web app

  • From the repo root, serve files using any static server, then open web/index.html.
    • Example: python3 -m http.server 8000 then go to http://localhost:8000/web/
  • The app prefers gstbl/OptEScore-Official.json (canonical JSON). If not present, it falls back to the binary OptEScore-Official.gstbl.
  • The UI includes an “Advice” panel and a final-roll EV breakdown. The computer plays its turn automatically and optimally.

GitHub Pages (static hosting)

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 includes gstbl/ at gstbl/ 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.

Converting .gstbl to JSON

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.

Tests

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

Notes on licensing

  • 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.

Repo structure

  • web/ — client app, loader, and tests
  • gstbl/ — precomputed optimal expected-score tables (binary) and optional JSON
  • YahtzeeTrainerLazarus/ — Pascal sources for the original Yahtzee Trainer

Acknowledgements

  • Tom Verhoeff for the original Yahtzee Trainer and published materials
  • The broader community for analyses of optimal Yahtzee strategies

About

Yahtzee

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published