Phaser AE

Five-dice scorecard games

Pro packv3.0.0-4Grid

The rules of the five-dice category game: roll, hold, reroll and choose where to score, across thirteen categories and their bonuses. One scorecard per player or three, solo or for up to four players, with computer opponents and honest advice.

This is a Pro pack. Upgrade to Phaser Pro to use it in your games.See Phaser Pro →

Released October 14, 2026 · updated October 20, 2026

Five-dice scorecard games: a screenshot of its demo
A note about these graphics

Expansion packs don't come with graphics. This screenshot is one way of drawing what the pack does, made for its demo: none of the sprites, tiles or backgrounds in it are in the pack.

That's by design. A pack is a game's logic, mechanics and effects, and it works with whatever art you give it. Some packs draw effects, backdrops or 3D scenes of their own, but none carries a game's sprites.

So the look is yours. Make the art on phaser.io, bring your own, or let your agent draw it in code: the same pack can look like anything.

The pack

yahtzee

function yahtzee(): Pack<{ yahtzee: typeof rules }>

Install classic and triple Yahtzee scoring, matches and visible-information advice above dice-core.

Helpers

createYahtzee

function createYahtzee(options: YahtzeeOptions = {}): YahtzeeGame

Create a seeded solo, local or computer-opponent match.

YAHTZEE_CATEGORIES

const YAHTZEE_CATEGORIES: readonly ["ones", "twos", "threes", "fours", "fives", "sixes", "three-kind", "four-kind", "full-house", "small-straight", "large-straight", "yahtzee", "chance"]

The classic thirteen categories, in scorecard order.

yahtzeeHint

function yahtzeeHint(view: YahtzeeObservation, difficulty = view.difficulty): YahtzeeAdvice

Evaluate all 31 nontrivial hold masks with a bounded one-turn Monte Carlo heuristic on visible state only.

yahtzeeScore

function yahtzeeScore(category: YahtzeeCategory, dice: readonly number[]): number

Exact ordinary category scoring; a five-of-kind is not an ordinary full house.

yahtzeeScoringOptions

function yahtzeeScoringOptions(dice: readonly number[], card: YahtzeeScorecard): YahtzeeScoringOption[]

Exact legal scoring with classic Joker rules, including when Yahtzee was previously scored zero.

yahtzeeTotals

function yahtzeeTotals(card: YahtzeeScorecard): { upper: number; upperBonus: number; lower: number; yahtzeeBonus: number; total: number }

Exact scorecard totals, including the 63-point upper threshold and all 100-point bonuses.

Classes

YahtzeeGame

class YahtzeeGame

Yahtzee owns scoring and three-roll turns above one ordinary flexible dice pool. The match is a kernel history: its state is a function of the seed and the accepted commands, so a save is those commands and a restore replays them.

  • constructor(options: YahtzeeOptions = {})
  • observation(): YahtzeeObservation — Public state for players and bots. No future random state is included.
  • preview(action: YahtzeeAction): { ok: true } | { ok: false; reason: string } — Explain roll/hold/score legality without changing dice or state.
  • apply(action: YahtzeeAction): YahtzeeResult — Apply a valid command, returning exact rendering events.
  • hint(difficulty = this.options.difficulty): YahtzeeAdvice — Pure advice; inspection never consumes the match's randomness.
  • autoStep(difficulty = this.options.difficulty): YahtzeeResult — Apply one advice step; rerolls set holds then roll through ordinary legal commands.
  • snapshot(): YahtzeeSnapshot — Save a bounded deterministic command trace.
  • restore(snapshot: YahtzeeSnapshot): void — Recompute every score, bonus, hold and roll from commands. Invalid traces leave the match intact.

Types

YahtzeeAction

type YahtzeeAction = { kind: 'roll' } | { kind: 'hold'; index: number; held: boolean } | { kind: 'score'; category: YahtzeeCategory; card?: number }

Public roll/hold/score commands.

YahtzeeAdvice

interface YahtzeeAdvice

Bounded advice for one turn, not an optimal full-match solver.

  • action: { kind: 'roll' } | { kind: 'reroll'; keep: number[] } | { kind: 'score'; category: YahtzeeCategory; card: number } | null — Suggested roll, reroll holding indices, or category choice.
  • reason: string — Human-readable explanation.
  • method: 'bounded-heuristic' — Honest analysis label.
  • samples: number — Simulated terminal rolls evaluated.

YahtzeeCategory

type YahtzeeCategory = typeof YAHTZEE_CATEGORIES[number]

One scorecard row.

YahtzeeEvent

type YahtzeeEvent = { kind: 'roll'; dice: number[]; held: boolean[]; rolls: number } | { kind: 'hold'; index: number; held: boolean } | { kind: 'score'; player: number; card: number; category: YahtzeeCategory; points: number; bonus: number } | { kind: 'turn'; player: number; turn: number } | { kind: 'complete'; winners: number[] }

Ordered events for rendering and replay.

YahtzeeMatchScoringOption

interface YahtzeeMatchScoringOption extends YahtzeeScoringOption

A category preview for one of the current player's cards.

  • card: number — Zero-based scorecard within the current seat.

YahtzeeObservation

interface YahtzeeObservation

Visible match state; includes no seed, RNG state or future dice.

  • phase: 'playing' | 'complete' — Playing or finished.
  • players: string[] — Seat names.
  • bots: number[] — Computer seat indices.
  • active: number — Current seat.
  • turn: number — Current turn, starting at one.
  • rolls: number — Rolls consumed this turn, zero to three.
  • dice: (number | null)[] — Current faces; null before the first roll of each turn.
  • held: boolean[] — Held dice.
  • variant: 'classic' | 'triple' — Match variant.
  • cardsPerPlayer: 1 | 3 — Number of cards belonging to each seat.
  • scorecards: YahtzeeScorecard[] — Public cards in player-major order: player * cardsPerPlayer + card.
  • totals: number[] — Grand totals per seat, adding each card's total without multipliers.
  • previews: YahtzeeMatchScoringOption[] — Exact category previews for every card of the current seat.
  • winners: number[] — Winning seat indices; multiple indices represent a tie.
  • difficulty: 'easy' | 'medium' | 'hard' — Bot/hint strength.

YahtzeeOptions

interface YahtzeeOptions

A classic or triple match, with one to four seats and optional computer seats.

  • seed?: number — Unsigned 32-bit seed.
  • variant?: 'classic' | 'triple' — Classic has one card per seat; triple has three, with unweighted combined totals.
  • players?: string[] — Unique, nonempty seat names; default solo.
  • bots?: number[] — Seat indices controlled by computer play; default none.
  • difficulty?: 'easy' | 'medium' | 'hard' — Changes advice/bot sampling only, never the dice.

YahtzeeResult

type YahtzeeResult = { ok: true; events: YahtzeeEvent[] } | { ok: false; reason: string }

An atomic action response.

YahtzeeScorecard

interface YahtzeeScorecard

Filled scores and extra-Yahtzee count. Missing rows remain playable; zero is a filled row.

  • scores: Partial<Record<YahtzeeCategory, number>> — At most one score per category.
  • yahtzeeBonuses: number — Number of additional Yahtzees after a scored 50.

YahtzeeScoringOption

interface YahtzeeScoringOption

An exact preview, including forced Joker placement and bonus effects.

  • category: YahtzeeCategory — Scorecard row.
  • legal: boolean — Legal to select this row.
  • reason: string — Rejection reason, empty for legal rows.
  • points: number — Points in this row, not including bonuses.
  • bonus: number — Additional Yahtzee bonus, 0 or 100.
  • joker: boolean — This roll is governed by the Joker placement rules.

YahtzeeSnapshot

interface YahtzeeSnapshot

Save/replay format; seed is privileged data and is never an input to a hint.

  • version: 1 — Format version.
  • options: Required<Omit<YahtzeeOptions, 'variant'>> & Pick<YahtzeeOptions, 'variant'> — Original match settings.
  • actions: YahtzeeAction[] — Accepted player/bot commands.