Skip to content

About

Classic minesweeper, but the board can be almost any surface and tiling — from a flat aperiodic Penrose mosaic to a Möbius strip.

Topics

Resources

Stars

6 stars

Watchers

0 watching

Forks

Latest commit

 

History

446 Commits

Folders and files

Repository files navigation

Hypersweeper

Classic minesweeper, but the board can be almost any surface and tiling — from a flat aperiodic Penrose mosaic to a Goldberg sphere or a Möbius strip.

Play in the browser: https://hypersweeper.pages.dev/ (the TypeScript/WebGL app in web/, deployed from master by GitHub Actions; installable, and it works offline once loaded)


Goldberg GP(3,0) on a sphere · Bright, domed, light

Hexagons on a Möbius strip · Bright, domed, dark

Penrose rhombi · Bright, domed, light

Snub square on a donut, boom · Bright, domed, dark

Hexagons in a Gosper island · Bright, flat, dark

A hexagon of hexagons · Classic, beveled, light

The menu · Bright, dark

Three themes — the page and what the board is coloured in — over three board shapes and three colour schemes

Pick a surface, then a tiling:

  • Flat surface — classic squares (8 neighbors), a triangle grid (12) and the same triangles cut to a triangular or a hexagonal board, hexagons (6) and a big hexagon composed of small hexagons (6); the eight non-regular uniform tilings: snub hexagonal 3.3.3.3.6, elongated triangular 3.3.3.4.4, snub square 3.3.4.3.4, rhombitrihexagonal 3.4.6.4, trihexagonal 3.6.3.6, truncated hexagonal 3.12.12, truncated trihexagonal 4.6.12 and truncated square 4.8.8 — and their eight Laves (dual) tilings, from Cairo pentagonal and rhombille to the kisrhombille. Then, tiled by one congruent rectangle rather than by regular polygons, the five brick bonds — stacked bond, running bond, basket weave, the same weave three bricks at a time, and herringbone — where all the interest is in how the courses are staggered. Several tilings have no translation at all: two Penrose mosaics (P3 rhombi, and P2 kites and darts), the eight-fold Ammann–Beenker tiling of squares and 45° rhombi, "the spectre" (Tile(1,1)), the chiral monotile whose tiling uses rotations only and never mirrors a tile, a phyllotactic spiral of one equilateral hexagon in five arms, and Klaassen's spirals of one convex pentagon, in five, six and seven arms. Five more are self-similar — one tile inflated into a patch shaped like itself: the sphinx, the chair, the Sierpiński carpet, the pentaflake, and hexagons filling a Gosper island. And thirty-seven are not Euclidean at all — the game's namesake: eleven regular {p,q} tilings, from nonagons and octagons three to a corner ({9,3}, {8,3}) and heptagons three and four to a corner ({7,3}, {7,4}) to squares six to a corner ({4,6}) and triangles seven and eight to a corner ({3,7}, {3,8} — a {3,7} triangle has 15 neighbours), which only fit in the hyperbolic plane, drawn in the Poincaré disc with tiles shrinking toward a rim they never reach; and twenty-two uniform tilings made from {7,3}, {8,3}, {9,3}, {5,4}, {6,4} and {5,5}: among them the hyperbolic soccer ball (6.6.7 — hexagons ringing every heptagon, HyperRogue's tiling) and its nonagon cousin 6.6.9, triangles and heptagons (3.7.3.7), squares and pentagons (4.5.4.5), squares, octagons and decagons (4.8.10), and squares, hexagons and 16-gons (4.6.16). One is drawn in the upper half-plane instead, as a rectangle: Böröczky's binary tiling, every row twice as many tiles as the one above. And six have no rim at all: the plane glued up into closed surfaces — the Bolza surface, Klein's quartic, Dyck's and Bring's surfaces, Macbeath's surface and a genus-14 Hurwitz surface — each drawn as a patch of the disc that covers it, every cell drawn at least once and keeping its full count of neighbours; each grows by its tiling — plain heptagons, 6.6.7 or 4.4.4.5, then subdivided — under a view sized to hold three quarters of the surface, and the pan never runs out. The menu groups these as Regular, Uniform, Laves, 2-uniform (regular polygons edge to edge with two kinds of corner — all twenty of them, named for how each is made from a uniform tiling, from Studded triangular [3⁶; 3⁴.6]₁ to Studded rhombitrihexagonal [3.4.6.4; 4.6.12]), Isogonal (six tilings by regular polygons that are not edge to edge — a tile's corner in the middle of its neighbour's edge), Congruent rectangles, Other (the sphinx and the L-tromino laid down in half-turned pairs rather than inflated, and regular pentagons with the rhombs that fill the gaps they leave, as Dürer drew it in 1525), Aperiodic, Spirals, Fractals and Hyperbolic; every periodic family bar 2-uniform and the last five also wraps the cylinder and the torus below, and — unless the tiling is chiral — the Möbius strip and the Klein bottle too
  • Sphere (3D) — boards rounded onto the sphere, growing with the difficulty: two Goldberg polyhedra, GP(n,0) (12 pentagons among 80, 240 and 480 hexagons) and the chiral GP(h,k) (60, 270 and 480 hexagons, twisted off the icosahedron's edges), and a geodesic icosahedron (80, 320 and 500 triangles — the Platonic icosahedron's cells, drawn round). (A sphere cannot be tiled with hexagons alone — Euler's formula forces 12 pentagons in.)
  • Platonic solids (3D) — the five regular solids, each tiled with triangles or squares, flat and creased at the edges rather than rounded onto a sphere: a tetrahedron (4 faces), a cube (6, squares), an octahedron (8), a dodecahedron (12 pentagons, each fanned into 5 triangles from its own centre) and an icosahedron (20)
  • Archimedean solids (3D) — solids of regular polygons, every corner alike, flat-faced and each face cut into a grid: a cuboctahedron (8 triangles + 6 squares), a truncated octahedron (6 squares + 8 hexagons, each cut into three rhombi), a snub cube (32 triangles + 6 squares), and the three icosahedral solids — the rhombicosidodecahedron, truncated icosidodecahedron and snub dodecahedron — one cell a face on Easy, then with their pentagons, hexagons and decagons fanned into triangles
  • Catalan solids (3D) — all thirteen duals of the Archimedean solids, flat-faced, each face cut into smaller copies of itself to make a board: the triakis tetrahedron, rhombic dodecahedron, triakis octahedron, tetrakis hexahedron, deltoidal icositetrahedron, pentagonal icositetrahedron, disdyakis dodecahedron, rhombic triacontahedron, triakis icosahedron, pentakis dodecahedron, deltoidal hexecontahedron, pentagonal hexecontahedron (60 pentagons, 7 neighbors) and disdyakis triacontahedron. Unlike the Archimedean solids these are face-transitive — one congruent face throughout, and no face regular: golden rhombi, kites, scalene triangles, irregular pentagons
  • Polyhedra (3D) — a tetrahedron frame (a level-1 Sierpiński tetrahedron: the middle triangle removed from each face, leaving four corner tetrahedra that meet at the edge midpoints), a cube frame (a cube with a square tunnel bored through each pair of opposite faces — a level-1 Menger sponge, genus 5), a stepped pyramid (square terraces narrowing to a single-cell apex, its foundation itself a playable face since nothing mirrors it below), and a stepped bipyramid (two of those pyramids stitched base-to-base into a terraced diamond). Cells stitch across the edges where faces meet, inner walls and step shoulders included. Three more are the same cube laid in brick bonds — stacked bond, basket weave and its three-brick version, the three congruent-rectangle bonds whose block is a square and so fills a square face. A brick cannot run round a corner, so the courses break at some of the twelve edges; the bricks either side still meet as neighbours. A fourth is laid in the brick rings, every face the flat board's concentric rings about its own centre
  • Volumetric (3D) — a cube filled with cubes rather than a surface of them: an n×n×n block where a cell's neighbours are the 26 cubes that share a corner with it, against 21 for the densest surface here. A solid shows only its shell, so the cube is played taken apart — each slice is its own sheet of tiles, laid out side by side and stepped back in depth, so every cell is readable at once (a number spans three slices, and you need all three). The header's controls turn the solid itself, which is the one move dragging cannot make: dragging turns the drawing, and the drawing is the cube pulled apart rather than the cube
  • Torus (3D) — the grid wraps in both directions, so there are no border cells; pure hexagons are possible here, because the torus has Euler characteristic 0
  • Trefoil knot (3D) — the donut's grid on a tube tied in a trefoil: the same board as the torus neighbour for neighbour, drawn round a knot that passes over and under itself three times. The tube is as fat as it can be without its strands touching. Squares, triangles or hexagons
  • Double torus (3D) — two donuts merged into a figure of eight, set so that a point of each one's outer rim lies on the other's inner rim: they overlap in a lens of real volume rather than touching. Each gives up everything it puts on the other's side and the two are sewn together along the plane between them, so away from the waist every cell is the donut's own. Squares, triangles or hexagons
  • Möbius strip (3D) — a one-sided surface: the strip glues to itself with a flip, so a chiral tiling cannot wrap it at all
  • Klein bottle (3D) — the donut glued with that same flip, one-sided and closed; the immersion hides cells behind its own neck, so the board scrolls to bring them round
  • Projective plane (3D) — a sphere with every point glued to the point diametrically opposite: closed, one-sided, and the only such surface besides the Klein bottle. It cannot be built in 3D without passing through itself, so it is drawn as the whole sphere with every cell shown twice — reveal or flag a cell and its antipodal twin round the back changes with it. A cell's neighbours are its own and its twin's, so a number counts mines on both sides of the ball. Squares (a cube's faces rounded onto the sphere), triangles (a geodesic sphere) or hexagons (a Goldberg sphere, with the six pentagons the surface forces)
  • Boy's surface (3D) — the same projective plane, drawn as itself: a surface that passes through itself along three loops meeting at one point, every cell drawn once. The squares keep their right angles but not their size, and the board's moves bring the cells hidden under its lobes into view. Squares
  • Cylinder (3D) — an open tube, wrapping in one direction only

Playing

  • Left-click / tap — reveal a cell (the first reveal always opens an empty area); click a revealed number to chord
  • Right-click, long-press, or the flag button in the header — toggle a flag
  • Face button — new game; the < button goes back to the menu
  • Drag a 3D board to turn it (arrow keys too); pinch or ctrl+wheel to zoom any board, 0 to frame it again
  • On a Klein bottle, the chevrons (or [ / ]) scroll the board round its neck

Every board is a link — ?mode=…&difficulty=…, plus a seed to share the exact layout. Winning files the time: the fastest three per board and difficulty live under Settings › Best times. It also files an achievement where there is one to file — fifty-two of them, and none written by hand: they are the catalogue's own structure, one per kind of tile a board can be made of (triangles through 13-gons), one for playing a tiling family and one for finishing it, the same pair for each surface and each group of solids, and one for the lot. The card that goes up on a win says what it just unlocked and links to the rest, under Settings › Achievements. Settings also holds the three themes (the page behind the board and how its cells are cut) over three colour schemes (auto, following the device, plus light and dark), three sound presets (synthesised from the move that caused them — a tile's side count is its voice) with a volume slider, an animations toggle, and — on a phone that can buzz — a haptics switch.

The hosted game counts, anonymously, which boards get opened and how they go — the board and difficulty, whether it was won and how long it took, how far the board got and how the flags fell, how the game was started, and whether this is a phone, tablet or desktop. No account, no cookie, no identifier, and nothing about the request itself (no IP, no country, no user agent), so there is no way to link two games. The switch is Settings › Privacy › Analytics. The macOS and iPhone apps send nothing at all: they are built without the collector, not merely with it switched off. The full policy is at hypersweeper.pages.dev/privacy.

Development

The game is a TypeScript/Three.js app in web/:

cd web
npm install
npm run dev          # http://localhost:5173
npm run typecheck    # tsc
npm run test         # vitest unit tests
npm run e2e          # Playwright e2e + visual regression
npm run build        # production bundle into web/dist
npm run screenshots  # regenerate the gallery above

A Mac app that plays offline

make mac-app       # build/desktop/mac*/Hypersweeper.app  (run this on a Mac)
make mac-app-dmg   # …and a drag-to-Applications .dmg

The same game, packaged with everything it draws — bundle, fonts, icons, board data — inside the app, so it needs no internet connection at all. The build proves that rather than promising it: it refuses to package a bundle that references a remote URL, and then launches the app it built with the network cut. See desktop/README.md.

An iPhone app that buzzes

make ios-app       # build the game and open the project in Xcode  (on a Mac)
make ios-run       # …or build straight onto a connected iPhone

The same game again, wrapped in a Capacitor WKWebView so it installs on a phone and plays offline — and, being native, can reach the Taptic Engine: a light tick when a flag lands, the system's sharp error buzz when you step on a mine, its success buzz when the board falls. No web API on iOS can ask for that. Building it needs a Mac with Xcode; a free Apple ID signs it for 7 days at a time. See ios/README.md.

web/AGENTS.md is the guide to the code — the renderer, the board builders, themes, sound, and how to drive the app headless; web/README.md is its milestone history. data/*.json is shared configuration (the board catalog, presets, UI screens) that both implementations read, plus a conformance oracle exported from the Python game and replayed by the TypeScript tests, so the two can never disagree about the rules.

The pygame implementation

The original game is a Python/pygame app and stays in the repo as the reference implementation — the behaviour the TypeScript port is checked against, and the place data/*.json is exported from. It is no longer deployed to the web; the site root serves the TypeScript app (/next/, where that app lived during the rewrite, redirects there).

pip install -r requirements.txt
python3 -m minesweeper                 # menu
python3 -m minesweeper --mode hex      # skip the menu
python3 -m minesweeper --theme paper   # one of the six pygame themes

Controls match the web app; n starts a new game, 1 / 2 / 3 switch difficulty and Escape goes back to the menu.

make venv     # create .venv with every dependency group
make test     # pytest
make lint     # ruff
make run      # desktop game
make web-run  # the pygbag browser build at http://localhost:8000
make help     # everything else

Code layout: minesweeper/game.py holds the rules over an arbitrary cell graph; minesweeper/boards/ generates the tilings (cell vertices get exact hashable ids — lattice points in 2D, symbolic keys in 3D — and two cells are neighbors when they share a vertex); the sphere is built with the Conway gyro operation on an icosahedron; minesweeper/gui.py is the pygame interface, including the rotatable orthographic 3D view. Tests run headless via SDL's dummy video driver.

License

MIT — copy it, fork it, build something else on top of it, commercially or not; the one condition is that the copyright notice comes along. The game itself is free.

Most of it was written with AI assistance.

The two bundled fonts are not covered by that license. Rubik (© 2015 The Rubik Project Authors) and DSEG7 Classic (© 2017 keshikan) are both under the SIL Open Font License 1.1, and their license texts ship next to the font files in minesweeper/assets/fonts/ — mirrored into web/public/fonts/ so the browser app is self-contained offline.

About

Classic minesweeper, but the board can be almost any surface and tiling — from a flat aperiodic Penrose mosaic to a Möbius strip.

Topics

Resources

Stars

6 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages