Skip to content
rvenningPublic

About

Web version of the Monza racing dice board game for 2-6 players

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

9 Commits

Folders and files

Repository files navigation

Monza — the racing dice game (web version)

An unofficial fan-made browser version of the board game Monza for 2–6 players, played hot-seat on one screen.

Play it here: https://rvenning.github.io/monza/

Credits

  • Game design: Jürgen P. K. Grunau — all game rules and mechanics implemented here are his design.
  • Original board game: Monza (Jubilee edition), published by HABA (HABA Sales GmbH & Co. KG, Bad Rodach, Germany), illustrated by Maša Zeidan.
  • This project is a non-commercial fan tribute and is not affiliated with, endorsed by, or sponsored by HABA. All code, artwork, and text in this repository are original; no material from the published game is included (the official rulebook is not part of this repository, as it is HABA's copyrighted work).
  • If you enjoy this game, please support the designer and publisher by buying the real thing — the physical game is wonderful with kids.

How to run

Just open index.html in any modern browser — no install, no server needed (double-click it).

Optionally you can serve it locally with any static server:

npx http-server . -p 8321 -c-1
# then open http://localhost:8321/

Install it (PWA)

Monza is a progressive web app, so it can live on a phone or tablet home screen with its own icon and run fullscreen, offline included:

  • Android / Chrome / Edge: tap the 📲 Install button in the header (or the browser's own "Install app" menu item).
  • iPhone / iPad: in Safari, tap Share → Add to Home Screen. The 📲 button in the header shows these steps.

The service worker caches the game the first time it loads, so a race started in the car keeps working with no signal. It is network-first, so a new deploy still arrives as soon as there is a connection.

The icons are generated, not hand-drawn — rerun node tools/make-icons.js after editing the art in that file.

What's implemented

Basic game

  • 2–6 players, each with a colored racing car (the six game colors: red, yellow, green, blue, purple, white)
  • Short / medium / long oval tracks, randomly generated each race, with gray tire obstacle spaces
  • Roll all six colored dice, then chain moves forward one space at a time — each space entered must match an unused die's color (tap a white-outlined space on the board, or a move button under the dice; Undo supported)
  • Forward-only movement with lane changes; driving across occupied spaces is allowed
  • Overtaking: end your turn on an occupied space and that car is moved back to the next free space in its lane (or to the start)
  • A white die is required to cross the finish line
  • When the first car finishes, the round is played out so everyone gets the same number of turns; among the finishers, whoever used the fewest dice in the final round wins — ties share the trophy

Monza Challenge (pro variation)

  • One re-roll tile per player: once per game, re-roll any of your dice before placing
  • Six acceleration tiles per player (one per color): each works once as a die of its color (spaces marked with a ⚡ bolt)
  • Turbo roll: place all six dice in one turn and you move up, then roll two more dice and keep going; occupied-space overtaking is checked only after the turbo roll

Bonus step variation (toggle at setup, works with either mode)

  • When a turn ends, the car matching the color of the last die/tile used may move one space forward to any free adjacent space

Family-night conveniences

  • The setup is remembered: names, player count, car colors, turn order, track, mode and bonus toggle all come back next time
  • Tap a car's color chip to change it; ▲▼ reorder the players (turn order)
  • "First to roll" picks who starts (or 🎲 random), and moves on to the next player after every race
  • Rematch on the trophy screen starts a new track straight away with the same players; Change setup goes back to the pre-filled setup
  • Leaderboard: all-time wins, races, win % and overtakes by player name (placeholder "Player N" names aren't recorded), shared across the family's devices through the same Firestore sync the other family games use; reset button on the setup screen (resets it everywhere)
  • Tonight's tally: trophies won in the current run of races with the same line-up (starts over when the line-up changes or after 12 hours)
  • An unfinished race is saved at the start of every turn and offered back ("Resume race") after a refresh or closed tab
  • 🏳️ Quit race in the header; tap the start lights to skip them
  • When nothing on the board matches the roll, the turn passes by itself (unless an unused re-roll tile could still help)
  • On a phone held upright the oval stands on its end to fill the screen, and the dice and buttons stick to the bottom; on a phone on its side the controls move to a column beside the board
  • A tap anywhere near a legal space counts (the nearest one wins), so small boards stay easy to play
  • Keyboard: Space/Enter = roll or end turn, 1 / 2 = drive to the first / second space offered (also picks a bonus-step space), Backspace/Z = undo, Esc = cancel re-roll, R = rematch; Tab reaches every button, and a focused button does what it says

The setup, tonight's tally and an unfinished race are per device, in localStorage (monzaSetup, monzaTonight, monzaSave).

How the leaderboard syncs. Monza vendors gamekit's gk-storage.js and gk-util.js (in lib/, via node ../gamekit/tools/sync-to-game.js .), with prefix and collection monza in the wordvoyage-e5a5c Firebase project. Each driver name is a gamekit profile with a deterministic id (d + hex of the lower-cased name), so every device writes "Rosalie" to the same record. That record's progress is {since, races:{<raceId>:{at,w,f,o}}}: merging is a union of race ids, so two devices recording at once lose nothing, and a reset stamps since so a stale device can't bring old results back. Offline, races are kept locally and sent up on the next online load.

The look (design pass, 2026-09)

Everything is drawn in code — procedural canvas art and CSS, no image files. The circuit sits in a royal park: tiled colour spaces with a quiet shape on each (▲ red, ● yellow, ■ green, ◆ blue, ★ purple, ✚ white — the same shapes are on the dice, for anyone who finds red and green hard to tell apart), grey tyre-stack obstacles, cream-and-slate kerbs, a chequered finish and a start grid, trees, gravel traps and a pit building. The cars are 1950s-style Grand Prix cars with the driver's initial in a roundel on the nose.

Legibility rules the art follows (see the header of js/art.js): cars share the six space colours, so a car is told from its space by its ink outline, roundel and shadow, never by hue; nothing that marks a move uses a space colour — a legal space is a white outline with an arrow, a ⚡ bolt means it spends an acceleration tile, a dashed outline with a ★ is a bonus step; spent dice are numbered in the order they were used, on the board and on the dice; a ↺ badge warns which car you will overtake if you end the turn where you are; and when nothing matches, the spaces in reach are crossed out so a pass reads as the rule working, not a stall. Announcements are drawn inside the infield, where nothing can be.

Effects and sound

  • F1-style start light gantry with beeps before every race
  • Dice tumble and settle; cars drive along the curve of the track with exhaust puffs; an overtaken car spins back and leaves skid marks
  • Banners in the infield (GO! / TURBO! / OVERTAKE! / FINISH! / FINAL ROUND / NO MATCH / BONUS STEP), board shake on turbo, confetti and a fanfare for the winner, whose car is drawn on the podium
  • Reduced motion: the system "reduce motion" setting turns off everything that pulses, drifts, spins or sparkles (Art.setMotion() is the one switch for the canvas and the CSS)
  • All sounds are synthesized live with the Web Audio API (no audio files); use the 🔊 button in the header to mute (remembered between sessions)

Files

File Purpose
index.html Markup only: the setup screen, the race screen, the overlays
css/style.css Every style, built from one token block (colour, space, radius, depth, motion, type)
js/rules.js The colours, track lengths and random track generator (DOM-free)
js/game.js The turn engine: every rule, reaching the screen only through Game.hooks (DOM-free)
js/audio.js The synthesized sounds
js/art.js What things look like: park, track, cars, move marks, banners (procedural canvas)
js/board.js The board: fitting it to the screen, the frame loop, taps, car moves, effects
js/storage.js The synced leaderboard, the saved setup, tonight's tally, the unfinished race
js/main.js The app shell: setup, the turn dock, standings, results, keyboard
js/pwa.js Service-worker registration and the Install button
manifest.json PWA manifest — name, colors and home-screen icons
lib/ Vendored gamekit (gk-util.js and gk-storage.js are loaded; tools/stamp-version.js stamps releases)
sw.js Service worker — caches the game so it plays offline; node lib/tools/stamp-version.js . --bump bumps CACHE and stamps index.html + version.json
tests/ npm test (node --test): 60 whole races replayed against a trace captured from the original single-file game, plus focused rule tests; tests/browser-drive.js is a console helper for checking the board in a browser
icons/ Generated home-screen icons (192, 512, maskable)
tools/make-icons.js Draws those icons; run node tools/make-icons.js
tools/png.js Dependency-free PNG writer used by the icon script (vendored from gamekit)

About

Web version of the Monza racing dice board game for 2-6 players

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages