Inspiration
The problem. The business model that won on mobile is the one that interrupts. An ad between levels. A timer that empties while you are not playing. A shop that sells back the difficulty it just added. In that model the puzzle is not the product. It is the thing that holds you still long enough to show you something else.
What that costs. Money, attention, and in places worse than either.
- Mobile advertising took $419 billion in 2025, up 7.4% on the year before, and it is more than double what mobile subscriptions and in-app purchases earn put together. (Business of Apps, Mobile Ad Spend Data, updated 8 September 2026: https://www.businessofapps.com/data/ad-spend/)
- Loot boxes sit in 59.0% of the top grossing iPhone games and 58.0% of the top grossing Google Play games. Of the games that carry them, 94.9% on iPhone and 93.1% on Android are rated as suitable for children of 12 and over. (Zendle, Meyer, Cairns, Waters and Ballou, "The prevalence of loot boxes in mobile and desktop games", Addiction, 2020: https://doi.org/10.1111/add.14973)
- The ads for those games do not mention it. Across 2,358 ads for 394 games, 8.4% of UK ads and 7.6% of South Korean ads disclosed a loot box, and once disclosures too small to read were discounted, the real figures were 2.4% and 4.2%. (Journal of Behavioral Addictions, 2025: https://doi.org/10.1556/2006.2025.00057)
- A Norwegian Media Authority survey found 28% of 9 to 18 year olds had paid money for a loot box, and 55% of boys aged 15 and 16. (Norwegian Consumer Council, "Insert Coin", May 2022: https://storage02.forbrukerradet.no/media/2022/05/2022-05-31-insert-coin-publish.pdf)
- Regulators now treat the interface itself as the harm. The FTC's staff report "Bringing Dark Patterns to Light" cites EU mystery shopping that found dark patterns on 73 of the 75 sites and apps examined, and a study where a dark pattern doubled sign ups to a dubious identity theft service. The UK's Competition and Markets Authority published its own work on online choice architecture the same year. (FTC, September 2022: https://www.ftc.gov/system/files/ftc_gov/pdf/P214800%20Dark%20Patterns%20Report%209.14.2022%20-%20FINAL.pdf. CMA, 5 April 2022: https://www.gov.uk/government/publications/online-choice-architecture-how-digital-design-can-harm-competition-and-consumers)
- Sometimes the ad is the harm on its own. The UK's Advertising Standards Authority has upheld complaints about sexualised ads served inside mobile games, including two for "Naughty Puzzle: Tricky Test" that appeared inside Scrabble GO (upheld 6 July 2022) and one for a mobile romance game ruled harmful and offensive (upheld 24 January 2024). (https://www.asa.org.uk/rulings/onesoft-studio-g22-1153489-onesoft-studio.html and https://www.asa.org.uk/rulings/gamehaus-network-technology-co-ltd-a23-1218813-gamehaus-network-technology-co-ltd.html)
So I went and asked players. I pulled a year of r/AndroidGaming out of the Arctic Shift archive and counted. 198 posts about mobile games, sorted by what they were asking for:
- 92 posts asking for premium games, or games with no pay to win, or games with no ads. The largest single ask in the set. The top one, Looking for premium games with LOTS of grind and progression, pulled 304 upvotes and 265 comments.
- 38 posts asking for offline, portrait, one hand, short sessions. Portrait games suggestions that are not pay to win. Help me find a simple game to play at work.
- 11 posts working out what ads players will actually sit through. What's an acceptable amount of ads in a free mobile game? ran to 68 comments. Another one just asks the question outright: If a game is no pay to win, are you willing to press an ads to support the developer?
- 10 posts about ads that were predatory or not safe to have on screen. One is titled I don't mind watching ads but.. Ads are p**n this days.
Read those two groups together and the position is not "no advertising". It is "not without asking me", and "not that". The last group is the one that changed the build.
The answer. Rivulet is the game those 198 posts describe. Portrait, one thumb, offline, a board in a minute or two, nothing you can buy that makes a puzzle easier, and an ad only when you press a button that says what it gives you.
What it does
One rule, and the whole game comes out of it. Water leaves the spring and moves to any neighbouring tile at the same height or lower. That is it. Tap a stone to raise it one level; tap it past the top and it drops back to the ground.
Every board is a hillside: a spring at the top, thirsty plants at the bottom, a slope of stone in between, and a tap budget. You are not matching colours or beating a clock. You are working out a shape. Undo and reset cost nothing, so the only thing at risk is the next thirty seconds.
Three ways to play.
- Daily Pour. One board a day, generated from the date, so everyone who opens the game that morning gets the same hillside.
- Journey. 24 hand made boards across Meadow, Quarry, Orchard and Marsh. Each region introduces one idea, and Marsh hands you a second spring to reconcile.
- Quick Pour. Three minutes, and as many generated boards as you can get through. The only mode that watches the clock, and it is the one mode you choose to enter.
The terrace. Every plant you water for the first time blooms in your own terraced garden. It is the progress system, and it cannot be bought past.
Comfort. Portrait only. A left hand mirror flips the board for the other thumb. Haptics and sound each have a switch. No account, no sign in, and every puzzle mode plays with the radio off.
How it is monetised
This is the genre where energy timers and lives counters are normal furniture. So the constraint I set was simple: nothing a player spends, in money or in attention, may change how hard a puzzle is.
Ads, only when asked for.
- There are exactly two buttons that can play one. A hint, on the board, which reveals the next correct tap. A seed packet in the shop, worth 30 seeds. Both say what they give before anything loads.
- No interstitials. No banners. Nothing on launch, nothing between boards, nothing when a board beats you.
- Five a day is the ceiling, the count is on screen, and Settings keeps a ledger of every ad you watched.
- Ad content is capped at a rating suitable for everyone before the first request is made, in
RivuletApplication.onCreate. That line exists because of those ten Reddit posts.
Keeper, one payment. Removes the ad buttons for good, gives 3 free hints a day, and unlocks every cosmetic plus 500 seeds. It is a non-consumable, so there is no subscription behind it and no second bill.
Seeds, 500 for a small one off. Cosmetics only. They buy plants for your terrace and touch nothing else.
Daily Pour, all 24 Journey boards and Quick Pour are free and complete without paying anything.
How Rivulet uses RevenueCat
- Configured by build type. Debug builds use a Test Store key through
PurchasesConfiguration. Release builds useGalaxyConfigurationwithGalaxyBillingMode.PRODUCTIONfor the Samsung Galaxy Store. A build with no key deliberately leaves the SDK unconfigured, and the UI says purchases are not set up rather than unlocking anything by accident. - Offering
default. A$rc_lifetimepackage forrivulet_keeper, which grants entitlementkeeper, and aseeds_500package for the consumablerivulet_seeds_500. The purchase screen is RevenueCat's ownPaywallDialog, with Restore purchases. No price is hard coded; the button shows whatever the store formats. - Unlocking without a restart. A
CustomerInfolistener means Keeper takes effect the moment it lands, and the ad buttons disappear under your thumb. - Ad events in the same place as revenue. Every ad displayed, reward earned and failed to load goes through
Purchases.sharedInstance.adTracker, so ad activity and purchase revenue sit in one dashboard. Details in the Catvertising section.
How I built it
Two modules, and the interesting one has no Android in it. :engine is pure Kotlin: the board model, the flow fill, the star rules, a solver, the seeded daily generator, and the 24 Journey boards as JSON resources. :app is Jetpack Compose, with the hillside painted in Canvas and ViewModels holding StateFlow. Splitting it that way is why the puzzle logic is testable at all.
Every Journey board is solver verified. The solver runs over each board before it ships, so none of the 24 is impossible and none of them claims a par it cannot actually hit. A level designer who tells you the truth is worth more than a level editor.
97 JVM tests. 33 over the engine, 64 over the app, covering the flow fill, the star rules, the generator, the ViewModels, the daily ad cap and Keeper's separate hint allowance. Roborazzi captures host screenshots at 1179 by 2556, which is how the art got reviewed without a device in hand.
The art is drawn, not assembled. No sprite sheet. Every stone, the water and the terrace are drawn into a Compose Canvas, which is what let the stone tones carry the height information instead of a number printed on the tile.
Challenges I ran into
"Or lower" had to become "the same height or lower". The first rule was strictly downhill, which is tidier to explain and dead on arrival to play: flat ground stopped the water cold and every board turned into a staircase. Allowing water across equal heights made the hillsides feel like water and made the puzzles readable. It also meant re-running the solver over every board, because a rule change invalidates every par you have written down.
The first build looked like an app, not a game. Flat lilac squares and glossy buttons. It worked and it was lifeless. The second pass drew stone as stacked blocks with a lit top face, gave the water a crest and a glow, and painted the terrace by hand. Same code underneath.
Being honest about ad rewards. RevenueCat can verify a rewarded ad server side before granting anything, which is the right way to do it. That needs an ad network account link this project does not have yet, so Rivulet grants the reward client side and reports it to RevenueCat as unverified, using the SDK's own trackAdRewardEarnedUnverified call. Saying so is cheaper than being found out.
Accomplishments that I am proud of
- A monetisation model where every line answers a specific complaint from the research, and none of them costs the player a puzzle.
- 24 boards that are proven solvable before anyone downloads them.
- A game that can be finished standing on a train, one handed, with the radio off.
- It shipped on 17 September 2026 and has 111 downloads.
What I learned
- Players do not hate ads. They hate being ambushed. Put the ad behind a button that says what it gives, and most of the objection goes away.
- A solver cannot tell you whether a board is fun. It will tell you within a second when a board is a lie, which turns out to be most of what I needed while building 24 of them.
- If the rule needs an "except" to be written down, the rule is wrong. That is the whole reason water crosses equal heights.
What is next
- The Cliffs and Moonpond regions, with one way sluices and dry wells.
- Server verified ad rewards through RevenueCat once the ad network account is linked, so the reward is granted from the server rather than the device.
- Quick Pour on the Flex mode layout. Daily Pour and Journey already have it.
- A side by side board and terrace layout for windows 600dp and wider.
Built With
- android
- jetpack-compose
- jetpack-windowmanager
- kotlin
- samsung-galaxy-store
Log in or sign up for Devpost to join the conversation.