Spider Solitaire for Android: free undo, a bot that plays 800 games, and why landscape didn't help
Spider Solitaire was the third game in the portfolio and the first card game. It was also the first real test of the engine idea: take Word Search, keep the ads, purchases, analytics, daily puzzle, streaks and build scripts, and replace the rules, the board and the art.
It took about five hours from an empty folder to a build ready for review.
Why Spider
The search research looked good for solitaire in general and Spider in particular:
- a keyword tool rated "spider solitaire" as higher volume than "word search" with a fraction of the difficulty (I treat those scores as relative, not gospel),
- solitaire players are the textbook audience for this portfolio: older, US-heavy, daily players,
- and the reviews of the market leader were full of complaints about loud, unskippable ads.
That last point shaped the design more than anything else.
The rules engine
Spider is played with two decks, 104 cards, across ten columns. You build down in sequence, a full King-to-Ace run of one suit leaves the table, and you can deal ten more cards from the stock when you're stuck. Clear eight runs to win. There are one-, two- and four-suit versions.
The core is a small rules module where a card's suit and rank derive from its id, so a completed run is just a list of ids and checking it costs almost nothing. The table on top is plain DOM: cards are elements, moves are CSS transforms, and you can tap or drag.
Tap to move needed more thought than I expected. Tapping a card should do what you meant, and in Spider the natural reading is "move the longest movable part of this run to the best place". Getting that right matters more than drag-and-drop, because most people on phones tap.
A bot that plays 800 games
Card games have a nasty class of bugs: a card gets duplicated, one disappears, a run is removed that wasn't complete. You'd never find them by hand.
So the test suite includes a bot that plays 800 full games with random legal moves and checks the invariants after every single step. There are always 104 cards. No card is in two places. Every column is a legal stack. Every removed run is a real King-to-Ace sequence of one suit. If any check fails, the build fails.
On top of that is a flow test that drives the real UI in a browser: resume after closing, undo, hints, a staged win, statistics and the daily deal.
Decisions that came from players' complaints
- Undo is free and unlimited. Solitaire players hate paying for undo. Some apps charge coins or make you watch a video. It feels like a trap, and the reviews say so.
- Ads at natural breaks only. A banner during play, an interstitial after a finished game (never mid-game), and an optional rewarded video for hints. Remove Ads is a single one-time purchase, not a subscription.
- Big cards and a dark mode, because the audience includes plenty of people who don't want to squint.
- A daily deal with a streak, the same for everyone, using the engine's seeded generation.
Landscape: a lesson in measuring before assuming
Landscape support was on my list, and my assumption was that cards would get much bigger on a sideways phone. So I measured it with a 50-pixel banner ad on screen:
- phone, landscape (915×388): 38 px cards
- small phone, landscape (780×336): 32 px
- tablet, landscape (1280×752): 76 px
- phone, portrait: 37 px
On phones, landscape makes almost no difference, because height is what limits the cards. Ten columns with a long stack (the heaviest column I found was 21 cards) have to fit vertically. The real win is on tablets. Landscape shipped anyway, with the score on a left rail and tools on the right, but I stopped expecting it to help phone players.
Things that went wrong
- The undo history lived only in memory. I found this in the FreeCell fork: if Android killed the app in the background, or the browser preview reloaded, undo was gone. FreeCell now saves its history with the game, and the fix needs porting back to Spider.
- A signed APK downloaded from Play won't run if you sideload it. Play's integrity protection says "Get this app from Play". Test through the internal testing link instead.
- The game went live before its AdMob store link was set up, so ads were limited for the first hours. That's why there's now an hourly job that watches for approvals and links AdMob automatically. (It then failed silently for ten days, which is a story for the automation post.)



Next week: FreeCell, Microsoft's deal numbers, and a store rejection for writing "#1".