Solitaire Finally Gets a Guarantee I Said I'd Revisit
Generating deals backward from a known solution, keeping them from feeling suspiciously easy, and a hint system that actually knows the way out.
Back in August I wrote that nothing guaranteed a dealt Solitaire game was actually winnable, matching how the physical card game has always worked, but flagged I expected to revisit it once I'd watched enough people hit a genuinely dead deal with no way to know whether they'd misplayed or were just never going to win. Today that guarantee arrived, along with a hint system for anyone who gets stuck along the way.
Guaranteeing solvability meant generating backward, not forward
You can't easily verify an already-shuffled Klondike deal is solvable by just trying to solve it forward — Klondike's hidden information and branching choices make brute-force solvability checking on an arbitrary shuffle a genuinely expensive search. The practical approach is generating a deal by working backward from a known-solved state, effectively reverse-engineering a valid shuffle from a winning sequence of moves rather than shuffling randomly and hoping. That's a fundamentally different generation process than August's version, which just shuffled a deck honestly and let whatever resulted stand, winnable or not.
A solvable deal still had to feel like a fair, random one
The real risk with backward generation is producing deals that are technically solvable but suspiciously easy, or that carry some subtle, detectable pattern from how they were constructed rather than feeling like a genuinely random shuffle. I had to make sure the backward generation process still produces deals with real, varied difficulty — some deals that take real thought to solve, not just deals that happen to have at least one guaranteed solution path sitting conveniently near the surface. Solvability was the hard constraint; keeping that constraint from flattening every deal into an easy one was the actual design work layered on top of it.
A hint system needs to know the actual solution, not just legal moves
Suggesting a next move that's merely legal is trivial — plenty of legal moves lead nowhere useful. A hint that's actually helpful has to know a real path to victory from the current board state and suggest a move that's genuinely part of that path, not just any move that happens to be allowed right now. Because today's deals are generated with a known winning sequence already baked in from the backward-generation process, the hint system can reference that real solution path directly rather than trying to search for one live from an arbitrary, possibly-unsolved position — which wouldn't have been reliably possible under August's honestly-shuffled, not-guaranteed-solvable deals at all.
Existing saved games from before today needed a real answer, not a shrug
Anyone with an in-progress game dealt before today is playing a deal generated under the old, not-guaranteed-solvable system, and I had to decide whether to leave those games exactly as they were or somehow reconcile them with the new guarantee. I left existing in-progress deals untouched rather than retroactively regenerating them, since silently swapping out a board someone's already partway through reasoning about would be a strange, disorienting kind of correctness to impose after the fact. The guarantee applies cleanly to every new deal from today forward, which felt like the more honest boundary than reaching backward into games already in progress.
Deciding how much a hint should actually reveal
A hint that plays the entire remaining game for you removes Solitaire entirely, and a hint that's too vague to actually help someone stuck isn't worth having at all. I settled on suggesting one specific next move rather than a longer sequence, which keeps a player making every subsequent decision themselves while removing the specific frustration of being stuck with no visibility into whether a winning path even still exists from where they are. That's a meaningfully different design goal than an auto-solver, and keeping the hint scoped to "here's one good move" rather than "here's the rest of the game" was important for keeping the actual game intact underneath the assistance.
The shuffle-fairness concern from August needed its own answer here too
Back in August I wrote about the importance of using a genuinely unbiased shuffle rather than a naive sort-by-random-key approach that's a well-known source of subtle bias in card-shuffling code. Backward generation raises a related but distinct concern: does building a deal from a known solution introduce its own kind of bias, favoring certain card arrangements the backward process happens to produce more easily over others it doesn't. I had to verify the distribution of generated deals still spreads believably across the space of possible arrangements, not just that each individual deal is solvable — solving one fairness problem in a new generation process while accidentally reintroducing a different one would have been a genuine regression dressed up as an improvement.
Was this worth reversing my own August decision?
In August I explicitly said matching the real game's own imperfection — unwinnable deals included — felt more honest than quietly changing the rules without saying so. I still believe that reasoning was sound at the time. What changed is having watched enough real play to know hitting a genuinely dead deal reads as a bug to almost everyone, not as an authentic piece of solitaire heritage worth preserving. Being honest about a limitation in a devlog post is one thing; letting it actively frustrate people who have no way of knowing it's an intentional, faithful-to-the-original design choice is a different thing entirely, and today's change is me updating that judgment based on what actually happened once real people played it.
I don't think revising a past decision like this is a failure of the original reasoning. It's what the devlog is actually for — writing down a real decision with its real justification, then coming back once reality disagreed with the assumption behind it, rather than quietly changing course and pretending the original reasoning never happened or never made sense in the first place. It only made sense with the information I had back in August, and today's information is genuinely different.
More from the Devlog