A grid of dots with arrows wound through it. Tap one and it threads itself off the board the way it points — or it runs into another arrow's body, stops where it ran out of room, turns red, and costs one of three lives. That is the entire game. There is nothing to unlock, nothing to buy, and no advertisement anywhere in it.
Going to the App Store shortly. Android runs from the same source tree and always has — until either listing exists, the source builds and runs on both.
iOS & Android · Flutter · Dart · Free & open source · No ads, no accounts, no network
Why it exists
This one is not trying to be a big idea. It started as a want for a mindless puzzle to play in a queue, and an unwillingness to put up with what that costs on a phone: a full-screen advertisement between levels, a countdown before the close button appears, a banner in the way of the board, an offer of coins. The game underneath all of that is usually fine. It is the fifteen seconds either side of it that are not.
So Maze Hippo is that game with none of it. No advertising, no advertisement identifier, no analytics, no accounts, no leaderboard, no energy meter, no shop, no daily-return nudge, no notification, and no network connection at all — it works with the SIM out, because there is nothing in it that could use one. It is not free-to-play with the nasty parts taken out; there was never anything there to take out.
The rest of it was the interesting part to build, which is the honest reason it exists. What is written up below is there because it was worth writing down, not because it is a reason to install anything.
How it works
The head takes one step in the direction it points, and every other dot of the arrow moves up onto the one in front of it. The body threads along the line the head has already travelled — it does not slide sideways and it does not drag its bends through the board.
Everything else follows from that one sentence. Whether an arrow can leave depends on the straight line of dots in front of its point, out to the edge, and on nothing else. Its own bends cost it nothing, because every dot the body will pass through is a dot the head has already been through and found empty. So a four-bend arrow tucked into a corner is under no more threat than a straight one with the same reach — and the thing you have to check before tapping is one line, which is a thing you can actually see.
You can never be stuck, and that is provable rather than hoped for. Removing an arrow can only ever free others, so an arrow that is free stays free. Whatever order you play in, the last-placed arrow still standing was free when it was put down onto a board that had more on it than yours does — so it is free now. There is always a legal move, a life is only ever lost to a wrong tap, and the game needs no undo button to be fair to you.
From a 14 × 14 grid with twenty-two arrows to a 30 × 30 with thirty-eight. The board grows for the first fifty and then holds — 30 dots across is the most a phone can show at a size a finger can aim at.
A wrong tap costs a life and leaves the board exactly as it was. The clock does not start when the level appears — it starts when you first touch an arrow, because a board is read before it is played and that reading is not the puzzle.
Between 50% and 400%, dragging to move around, and the tangle cannot be pushed off the screen. The late boards are dense enough that reading one line often means going in for a closer look.
Two synthesised loops play under the game, one of 97 seconds and one of 71. They share no factors, so the pair line up again only every hour and fifty-five minutes. Two faders on the front page, one for the music and one for the effects.
The picker shows all hundred in their difficulty bands, and the ones you have finished keep their best time and the lives you had left. A first finish is not a record — beat your own time and the panel says so.
Your progress and your two volumes are stored on the device and
nowhere else. The Android package ships without the
INTERNET permission, so the operating system itself would
refuse a connection the game tried to open.
A look at it
Not screenshots. These come out of the game's own painter, its own camera and its own level generator, run at a size the web wants — so what is below is the real level 1, the real level 100, and a real blocked tap rather than a picture of one. Push them sideways.
The part that was interesting
A hundred hand-built levels would be a hundred files to ship and a solver to prove each one finishable. Maze Hippo has neither. Every level is computed from its number, on the phone, in a few milliseconds — and the trick is the direction it is built in.
Arrows are placed one at a time, each with a clear run to the edge past everything already down. The reverse of the placement order is then a solution: when an arrow was put down, its run was clear of exactly the arrows that are still there when its turn comes to be lifted. No search and no verification pass — the level is generated along its own solution, so a level that cannot be finished is not something the generator is capable of producing.
The difficulty comes out of the same construction. What makes one of these hard is not its size but how many arrows can leave at any moment: at four there is nearly always an obvious move, at one there is never a choice. Adding an arrow can never free another one, so requiring each placement to block exactly one currently-free arrow holds that count wherever it was set. Ten levels at four, fifteen at three, twenty at two, and the last fifty-five at one.
Level 63 is the same tangle on every phone. Because a
level is computed rather than stored, the random number generator behind
it had to be written out by hand rather than taken from the standard
library — Random(seed) is deterministic, but which sequence a
given seed produces is not part of Dart's contract and could change under
an SDK update. Every one of the hundred is generated and solved in the
test suite on every run, which takes about a second and is the whole
safety net under the thing that decides what a level is.
Feedback
There is no crash reporting in Maze Hippo and no telemetry of any kind, which is the point of it and also the catch: a level that reads badly, a board that will not fit on your phone, or a tap that did something unexpected leaves no trace anywhere except the phone it happened on. Until somebody writes it down, it did not happen.
All of it goes to the issue tracker on GitHub, beside the source. The phone, its OS version and the level number are usually the whole of what is needed — the level number especially, because that number is the level, so anyone can regenerate exactly the board you were looking at.
Get it
One Flutter codebase for both phones. There is nothing to buy in it, there never will be, and the source is public — so the claim that it collects nothing is one you can check rather than one you have to take.