FreeCell: recreating Microsoft's deal numbers, a hint solver, and a store rejection for writing #1
FreeCell came out of the same search research that picked Spider Solitaire, and it looked even better on paper. The top ten results for "freecell" had a median in the millions of installs, and two tiny apps sat in that top ten, one with about 2,500 installs and one with 150. Google was clearly willing to rank newcomers for it. It took one working session to build on top of the Spider card table.
Deal numbers players already know
FreeCell has a quirk no other solitaire has. Players know deals by number. "Game #617" is a specific layout, the same one people played on Windows decades ago, and FreeCell fans discuss particular deals by number.
Those numbers come from a tiny, well-documented algorithm: a linear congruential generator, seed × 214013 + 2531011 mod 2³¹, taking the high bits, picking cards from a deck ordered A♣ A♦ A♥ A♠ 2♣ and so on. Implement it faithfully and deal #1 and deal #617 match the published layouts card for card. I check both in the test suite.
So the game lets you pick any deal from 1 to 32,000, and random deals skip number 11982, the one deal among them that can't be won.
A solver for hints
Hints in FreeCell are only useful if they're right. "Move this card" means nothing unless the move leads somewhere. So the hint button runs a best-first solver in the background:
- it solves 149 of 150 test deals, averaging about 24 ms each,
- if you follow its hints, you win (15 of 15 test games),
- it understands supermoves (moving a run using free cells and empty columns) and safe automatic moves to the foundations.
The undo bug I found on my own phone
I was eight moves into deal #7259 when the hint said the game was lost and Undo was greyed out. Two separate things were going on.
- "Lost" was correct. An independent brute-force search from that position reached only 115 positions, none of them winning. Eight moves in, the deal was already dead.
- Undo being gone was a bug. The undo history lived only in memory, and the phone browser had reloaded the page in the background. The game resumed from its save, but the history didn't come with it.
The fix: undo history is saved with the game (up to 300 positions, round-trip tested after every move), the flow test checks undo after leaving and after a reload, and it replays my exact position. And because a dead position is miserable, a lost game now offers "Undo back to the last winnable position", for free. The solver already knows where that is.
Rejected: "#1" and "Windows"
FreeCell's first submission came back rejected under Google Play's Metadata policy: "Full description: violating store listing promotion policies".
Nothing in the email said what was wrong, so I compared the text with Spider's, which had passed. FreeCell's description said:
- "EVERY DEAL NUMBERED, #1 TO #32000"
- "Just like the Windows game"
- "the famous #11982"
To a reviewer, "#1" reads as a ranking claim ("the #1 FreeCell game"), even when it's a deal number. "Windows" is someone else's product. "Famous" is promotional. None of it was meant that way, and all of it reads that way to a policy check.
The fix was boring: "32,000 numbered deals", "the classic FreeCell numbering", "number 11982". It went into all fifteen translated listings, the screenshot captions, the feature graphics and the in-game text, and was resubmitted the same day.
The lasting fix is a pre-publish check that refuses, in any language:
#followed by a number,- other companies' product names (Windows, Microsoft, Apple, iPhone),
- ranking or hype words: "best game", "famous", "award-winning", "millions of players".
After a rejection, the API behaves differently
One more thing I learned: after a rejection, Google Play refuses an API commit that would also send the change for review. You get a 400 telling you to set changesNotSentForReview to true. My publishing scripts now retry with that flag, and the actual "send for review" happens in the console.
The second review took about four and a half days, much longer than the same-day approvals of the first games. I can't say for sure whether that was extra scrutiny after a rejection or just a busy week at Google. Plan for a week either way.


