TinyGames · how it works
Minesweeping, with one promise: you will never have to guess.
Open index.html. No build step, no dependencies, no images.
quarry/
index.html markup
style.css the frame around the canvas
js/engine.js copied unchanged from Overdrive - the thirteenth game on it
js/mines.js the field, the cascade and a fairness solver
- no pixels, no engine, no DOM
js/quarry.js the playable layer
test-mines.js node test-mines.js
Scatter mines at random and you regularly produce a board that, at some point, cannot be finished by reasoning — only by picking one of two squares and hoping. The player cannot tell that from having missed something, which is the worst thing a puzzle can do to somebody.
It is not a rare edge case. On the middle setting:
unfiltered boards that happen to be fair: 115 / 200
Two boards in five would have made you guess.
So the generator does not merely scatter mines. It scatters them, plays the whole board through a logical solver, and throws it away if the solver ever has to guess. What ships is a field that can be cleared by deduction from the first click to the last — and the HUD tells you how many boards were discarded to find it.
$ node test-mines.js
generating fair boards:
Shallow 9x9 10 mines mean 1.3 tries worst 3 8ms all fair
Seam 12x12 22 mines mean 1.6 tries worst 4 16ms all fair
Deep 16x14 40 mines mean 3.3 tries worst 10 21ms all fair
43 passed, 0 failed
"Every board is fair" is a vacuous claim if the fairness check always returns true. So the suite also proves it can detect an unfair board — with a coin toss worked out by hand:
M 1 0 three wide, two tall, one mine, first click bottom-right.
? 1 @ The click cascades and opens everything but the left column.
Both remaining squares are touched by both revealed 1s and nothing else. The test then moves the mine to the other candidate and asserts the numbers come out identical — so the board genuinely cannot be resolved, and the checker correctly refuses it.
The solver itself uses two rules to fixpoint:
A board this cannot finish might still be solvable by deeper reasoning, so "solvable" here means solvable by these two rules — a stronger promise than the player needs, which is the right way round.
Laying mines before the player clicks means the first click can be one, which is not a game. Laying them after means the click is guaranteed safe and the whole board can be checked for fairness before anybody sees it.
The clicked square's entire neighbourhood is cleared too, not just the square. Guaranteeing only the square means a first click can open a single number, which tells you nothing — and the game starts with a guess anyway.
Click an already-open number whose flags match it and everything else around it opens at once. Wrong flags make that fatal, which is exactly the bargain that makes it worth having — and the tests hold both halves: it is safe when the flag is right and it blows up when it is not.
| Tap | dig, or chord an open number |
| Hold, or right-click | flag |
| Digging / Flagging button | swap what a tap does |
| F or Space | swap mode |
| 1 2 3 | Shallow, Seam, Deep |
| R | new dig |
When you lose, the mines you had not found are shown faintly and any flag in the wrong place gets a cross — so it is always clear what the board was actually saying.
Advertisement